From ed7889105dc31d842293d775f64b0f43d6dcfaab Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Mon, 10 Oct 2022 10:40:00 -0700 Subject: [PATCH] [generated] Run dprint and update baselines [git-generate] set -x npm ci npx dprint fmt npx hereby clean npx hereby dts npx hereby runtests -t 'Public APIs|goToTypeDefinition_' &> /dev/null || npx hereby baseline-accept --- Herebyfile.mjs | 88 +- scripts/build/localization.mjs | 16 +- scripts/build/options.mjs | 18 +- scripts/build/projects.mjs | 13 +- scripts/build/tests.mjs | 26 +- scripts/build/utils.mjs | 8 +- scripts/checkPackageSize.mjs | 4 +- scripts/configurePrerelease.mjs | 23 +- scripts/dtsBundler.mjs | 21 +- scripts/eslint/rules/debug-assert.cjs | 6 +- scripts/eslint/rules/jsdoc-format.cjs | 21 +- scripts/eslint/rules/no-double-space.cjs | 15 +- scripts/eslint/rules/no-keywords.cjs | 24 +- scripts/eslint/rules/only-arrow-functions.cjs | 4 +- scripts/failed-tests.cjs | 26 +- .../generateLocalizedDiagnosticMessages.mjs | 9 +- scripts/open-cherry-pick-pr.mjs | 22 +- scripts/open-user-pr.mjs | 24 +- scripts/perf-result-post.mjs | 14 +- scripts/post-vsts-artifact-comment.mjs | 11 +- scripts/processDiagnosticMessages.mjs | 29 +- .../regenerate-unicode-identifier-parts.mjs | 4 +- scripts/run-sequence.mjs | 8 +- scripts/update-experimental-branches.mjs | 3 +- src/cancellationToken/cancellationToken.ts | 4 +- src/compiler/binder.ts | 952 +- src/compiler/builder.ts | 679 +- src/compiler/builderPublic.ts | 138 +- src/compiler/builderState.ts | 175 +- src/compiler/checker.ts | 25125 ++++++++++++---- src/compiler/commandLineParser.ts | 1101 +- src/compiler/core.ts | 550 +- src/compiler/debug.ts | 419 +- src/compiler/emitter.ts | 1398 +- src/compiler/factory/baseNodeFactory.ts | 31 +- src/compiler/factory/emitHelpers.ts | 203 +- src/compiler/factory/emitNode.ts | 67 +- src/compiler/factory/nodeConverters.ts | 17 +- src/compiler/factory/nodeFactory.ts | 2605 +- src/compiler/factory/parenthesizerRules.ts | 80 +- src/compiler/factory/utilities.ts | 492 +- src/compiler/moduleNameResolver.ts | 1937 +- src/compiler/moduleSpecifiers.ts | 607 +- src/compiler/parser.ts | 3906 ++- src/compiler/path.ts | 147 +- src/compiler/performanceCore.ts | 37 +- src/compiler/program.ts | 2510 +- src/compiler/resolutionCache.ts | 396 +- src/compiler/scanner.ts | 411 +- src/compiler/semver.ts | 71 +- src/compiler/sourcemap.ts | 144 +- src/compiler/sys.ts | 402 +- src/compiler/tracing.ts | 28 +- src/compiler/transformer.ts | 208 +- src/compiler/transformers/classFields.ts | 818 +- src/compiler/transformers/classThis.ts | 38 +- src/compiler/transformers/declarations.ts | 712 +- .../transformers/declarations/diagnostics.ts | 433 +- src/compiler/transformers/destructuring.ts | 204 +- src/compiler/transformers/es2015.ts | 1052 +- src/compiler/transformers/es2016.ts | 5 +- src/compiler/transformers/es2017.ts | 162 +- src/compiler/transformers/es2018.ts | 206 +- src/compiler/transformers/es2020.ts | 97 +- src/compiler/transformers/es2021.ts | 21 +- src/compiler/transformers/esDecorators.ts | 622 +- src/compiler/transformers/esnext.ts | 155 +- src/compiler/transformers/generators.ts | 164 +- src/compiler/transformers/jsx.ts | 204 +- src/compiler/transformers/legacyDecorators.ts | 92 +- .../transformers/module/esnextAnd2015.ts | 106 +- src/compiler/transformers/module/module.ts | 455 +- src/compiler/transformers/module/system.ts | 191 +- src/compiler/transformers/namedEvaluation.ts | 204 +- src/compiler/transformers/taggedTemplate.ts | 13 +- src/compiler/transformers/ts.ts | 443 +- src/compiler/transformers/typeSerializer.ts | 152 +- src/compiler/transformers/utilities.ts | 180 +- src/compiler/tsbuild.ts | 5 +- src/compiler/tsbuildPublic.ts | 935 +- src/compiler/types.ts | 2501 +- src/compiler/utilities.ts | 2294 +- src/compiler/utilitiesPublic.ts | 221 +- src/compiler/visitorPublic.ts | 2226 +- src/compiler/watch.ts | 301 +- src/compiler/watchPublic.ts | 396 +- src/compiler/watchUtilities.ts | 281 +- src/deprecatedCompat/deprecate.ts | 34 +- src/deprecatedCompat/deprecations.ts | 15 +- src/executeCommandLine/executeCommandLine.ts | 362 +- src/harness/client.ts | 304 +- src/harness/collectionsImpl.ts | 3 +- src/harness/compilerImpl.ts | 94 +- src/harness/documentsUtil.ts | 18 +- src/harness/evaluatorImpl.ts | 67 +- src/harness/fakesHosts.ts | 107 +- src/harness/findUpDir.ts | 3 +- src/harness/fourslashImpl.ts | 2002 +- src/harness/fourslashInterfaceImpl.ts | 168 +- src/harness/harnessIO.ts | 436 +- src/harness/harnessLanguageService.ts | 230 +- src/harness/harnessUtils.ts | 54 +- src/harness/incrementalUtils.ts | 36 +- src/harness/runnerbase.ts | 5 +- src/harness/sourceMapRecorder.ts | 78 +- src/harness/typeWriter.ts | 59 +- src/harness/util.ts | 24 +- src/harness/vfsUtil.ts | 220 +- src/harness/vpathUtil.ts | 12 +- src/jsTyping/jsTyping.ts | 65 +- src/jsTyping/shared.ts | 4 +- src/jsTyping/types.ts | 19 +- src/lib/decorators.d.ts | 3 +- src/lib/decorators.legacy.d.ts | 12 +- src/lib/es2015.core.d.ts | 5 +- src/lib/es2015.promise.d.ts | 4 +- src/lib/es2015.reflect.d.ts | 6 +- src/lib/es2015.symbol.wellknown.d.ts | 12 +- src/lib/es2017.date.d.ts | 10 +- src/lib/es2017.object.d.ts | 4 +- src/lib/es2017.sharedmemory.d.ts | 54 +- src/lib/es2018.intl.d.ts | 25 +- src/lib/es2019.array.d.ts | 3 +- src/lib/es2020.bigint.d.ts | 166 +- src/lib/es2020.intl.d.ts | 11 +- src/lib/es2020.promise.d.ts | 4 +- src/lib/es2020.sharedmemory.d.ts | 7 +- src/lib/es2021.intl.d.ts | 10 +- src/lib/es2022.intl.d.ts | 9 +- src/lib/es2022.sharedmemory.d.ts | 14 +- src/lib/es5.d.ts | 424 +- src/server/editorServices.ts | 1089 +- src/server/moduleSpecifierCache.ts | 36 +- src/server/packageJsonCache.ts | 6 +- src/server/project.ts | 649 +- src/server/scriptInfo.ts | 83 +- src/server/scriptVersionCache.ts | 90 +- src/server/session.ts | 1064 +- src/server/types.ts | 19 +- src/server/typingsCache.ts | 41 +- src/server/utilities.ts | 5 +- src/server/utilitiesPublic.ts | 20 +- src/services/breakpoints.ts | 141 +- src/services/callHierarchy.ts | 161 +- src/services/classifier.ts | 161 +- src/services/classifier2020.ts | 64 +- src/services/codeFixProvider.ts | 75 +- ...dConvertToUnknownForNonOverlappingTypes.ts | 27 +- .../codefixes/addEmptyExportDeclaration.ts | 20 +- src/services/codefixes/addMissingAsync.ts | 62 +- src/services/codefixes/addMissingAwait.ts | 197 +- src/services/codefixes/addMissingConst.ts | 66 +- .../codefixes/addMissingDeclareProperty.ts | 36 +- .../addMissingInvocationForDecorator.ts | 29 +- .../codefixes/addNameToNamelessParameter.ts | 18 +- .../codefixes/addOptionalPropertyUndefined.ts | 40 +- .../codefixes/annotateWithTypeFromJSDoc.ts | 83 +- src/services/codefixes/convertConstToLet.ts | 16 +- .../codefixes/convertFunctionToEs6Class.ts | 186 +- .../convertLiteralTypeToMappedType.ts | 26 +- .../codefixes/convertToAsyncFunction.ts | 433 +- src/services/codefixes/convertToEsModule.ts | 364 +- .../codefixes/convertToMappedObjectType.ts | 35 +- .../codefixes/convertToTypeOnlyExport.ts | 35 +- .../codefixes/convertToTypeOnlyImport.ts | 71 +- .../codefixes/convertTypedefToType.ts | 5 +- ...correctQualifiedNameToIndexedAccessType.ts | 22 +- .../codefixes/disableJsDiagnostics.ts | 20 +- .../codefixes/fixAddMissingConstraint.ts | 72 +- src/services/codefixes/fixAddMissingMember.ts | 561 +- .../codefixes/fixAddMissingNewOperator.ts | 13 +- .../fixAddModuleReferTypeMissingTypeof.ts | 24 +- src/services/codefixes/fixAddVoidToPromise.ts | 56 +- .../codefixes/fixAwaitInSyncFunction.ts | 30 +- src/services/codefixes/fixCannotFindModule.ts | 15 +- ...sDoesntImplementInheritedAbstractMember.ts | 36 +- .../fixClassIncorrectlyImplementsInterface.ts | 74 +- .../fixClassSuperMustPrecedeThisAccess.ts | 26 +- .../fixConstructorForDerivedNeedSuperCall.ts | 21 +- src/services/codefixes/fixEnableJsxFlag.ts | 6 +- src/services/codefixes/fixExpectedComma.ts | 8 +- .../fixExtendsInterfaceBecomesImplements.ts | 34 +- .../fixForgottenThisPropertyAccess.ts | 28 +- src/services/codefixes/fixImplicitThis.ts | 15 +- .../codefixes/fixImportNonExportedMember.ts | 95 +- .../codefixes/fixIncorrectNamedTupleSyntax.ts | 19 +- .../codefixes/fixInvalidImportSyntax.ts | 39 +- .../codefixes/fixInvalidJsxCharacters.ts | 47 +- src/services/codefixes/fixJSDocTypes.ts | 62 +- .../codefixes/fixMissingCallParentheses.ts | 20 +- .../codefixes/fixModuleAndTargetOptions.ts | 26 +- src/services/codefixes/fixNaNEquality.ts | 27 +- .../fixNoPropertyAccessFromIndexSignature.ts | 36 +- src/services/codefixes/fixOverrideModifier.ts | 117 +- .../codefixes/fixPropertyAssignment.ts | 25 +- .../codefixes/fixPropertyOverrideAccessor.ts | 37 +- .../codefixes/fixReturnTypeInAsyncFunction.ts | 28 +- src/services/codefixes/fixSpelling.ts | 75 +- .../codefixes/fixStrictClassInitialization.ts | 68 +- .../codefixes/fixUnmatchedParameter.ts | 31 +- src/services/codefixes/fixUnreachableCode.ts | 40 +- .../fixUnreferenceableDecoratorMetadata.ts | 61 +- src/services/codefixes/fixUnusedIdentifier.ts | 272 +- src/services/codefixes/fixUnusedLabel.ts | 24 +- src/services/codefixes/generateAccessors.ts | 146 +- src/services/codefixes/helpers.ts | 334 +- src/services/codefixes/importFixes.ts | 930 +- src/services/codefixes/inferFromUsage.ts | 451 +- .../removeAccidentalCallParentheses.ts | 5 +- .../codefixes/removeUnnecessaryAwait.ts | 15 +- src/services/codefixes/requireInTs.ts | 35 +- src/services/codefixes/returnValueCorrect.ts | 159 +- src/services/codefixes/splitTypeOnlyImport.ts | 30 +- src/services/codefixes/useBigintLiteral.ts | 14 +- src/services/codefixes/useDefaultImport.ts | 33 +- src/services/codefixes/wrapJsxInFragment.ts | 23 +- src/services/completions.ts | 1669 +- src/services/documentHighlights.ts | 129 +- src/services/documentRegistry.ts | 201 +- src/services/exportInfoMap.ts | 303 +- src/services/findAllReferences.ts | 1278 +- src/services/formatting/formatting.ts | 412 +- src/services/formatting/formattingContext.ts | 14 +- src/services/formatting/formattingScanner.ts | 26 +- src/services/formatting/rules.ts | 928 +- src/services/formatting/rulesMap.ts | 28 +- src/services/formatting/smartIndenter.ts | 311 +- src/services/getEditsForFileRename.ts | 147 +- src/services/goToDefinition.ts | 349 +- src/services/importTracker.ts | 187 +- src/services/inlayHints.ts | 56 +- src/services/jsDoc.ts | 96 +- src/services/navigateTo.ts | 51 +- src/services/navigationBar.ts | 116 +- src/services/organizeImports.ts | 265 +- src/services/outliningElementsCollector.ts | 165 +- src/services/patternMatcher.ts | 87 +- src/services/preProcess.ts | 61 +- src/services/refactorProvider.ts | 25 +- .../addOrRemoveBracesToArrowFunction.ts | 51 +- ...onvertArrowFunctionOrFunctionExpression.ts | 112 +- src/services/refactors/convertExport.ts | 212 +- src/services/refactors/convertImport.ts | 140 +- .../convertOverloadListToSingleSignature.ts | 64 +- .../convertParamsToDestructuredObject.ts | 157 +- .../convertStringOrTemplateLiteral.ts | 87 +- .../convertToOptionalChainExpression.ts | 126 +- src/services/refactors/extractSymbol.ts | 492 +- src/services/refactors/extractType.ts | 150 +- .../generateGetAccessorAndSetAccessor.ts | 32 +- .../refactors/inferFunctionReturnType.ts | 22 +- src/services/refactors/inlineVariable.ts | 84 +- src/services/refactors/moveToFile.ts | 684 +- src/services/refactors/moveToNewFile.ts | 89 +- src/services/rename.ts | 63 +- src/services/services.ts | 961 +- src/services/shims.ts | 366 +- src/services/signatureHelp.ts | 479 +- src/services/smartSelection.ts | 50 +- src/services/sourcemaps.ts | 26 +- src/services/stringCompletions.ts | 656 +- src/services/suggestionDiagnostics.ts | 135 +- src/services/symbolDisplay.ts | 307 +- src/services/textChanges.ts | 802 +- src/services/transform.ts | 16 +- src/services/transpile.ts | 36 +- src/services/types.ts | 266 +- src/services/utilities.ts | 976 +- src/testRunner/compilerRunner.ts | 49 +- src/testRunner/parallel/host.ts | 76 +- src/testRunner/parallel/shared.ts | 6 +- src/testRunner/parallel/worker.ts | 35 +- src/testRunner/projectsRunner.ts | 187 +- src/testRunner/unittests/asserts.ts | 19 +- src/testRunner/unittests/builder.ts | 10 +- src/testRunner/unittests/canWatch.ts | 58 +- .../unittests/config/commandLineParsing.ts | 73 +- .../config/configurationExtension.ts | 46 +- .../config/convertCompilerOptionsFromJson.ts | 10 +- .../config/convertTypeAcquisitionFromJson.ts | 3 +- src/testRunner/unittests/config/helpers.ts | 21 +- .../unittests/config/initializeTSConfig.ts | 31 +- src/testRunner/unittests/config/matchFiles.ts | 22 +- src/testRunner/unittests/config/showConfig.ts | 49 +- .../unittests/config/tsconfigParsing.ts | 40 +- src/testRunner/unittests/convertToBase64.ts | 4 +- src/testRunner/unittests/customTransforms.ts | 37 +- src/testRunner/unittests/factory.ts | 94 +- src/testRunner/unittests/helpers.ts | 65 +- src/testRunner/unittests/helpers/baseline.ts | 193 +- .../unittests/helpers/libraryResolution.ts | 26 +- .../unittests/helpers/node10Result.ts | 36 +- .../unittests/helpers/solutionBuilder.ts | 25 +- src/testRunner/unittests/helpers/tsc.ts | 122 +- src/testRunner/unittests/helpers/tscWatch.ts | 77 +- src/testRunner/unittests/helpers/tsserver.ts | 277 +- src/testRunner/unittests/helpers/vfs.ts | 11 +- .../helpers/virtualFileSystemWithWatch.ts | 294 +- src/testRunner/unittests/incrementalParser.ts | 190 +- src/testRunner/unittests/jsDocParsing.ts | 35 +- src/testRunner/unittests/moduleResolution.ts | 358 +- src/testRunner/unittests/parsePseudoBigInt.ts | 4 +- src/testRunner/unittests/paths.ts | 20 +- src/testRunner/unittests/printer.ts | 47 +- src/testRunner/unittests/programApi.ts | 88 +- src/testRunner/unittests/publicApi.ts | 35 +- .../unittests/reuseProgramStructure.ts | 153 +- src/testRunner/unittests/semver.ts | 96 +- .../cancellableLanguageServiceOperations.ts | 31 +- .../unittests/services/colorization.ts | 381 +- .../services/convertToAsyncFunction.ts | 77 +- .../unittests/services/documentRegistry.ts | 66 +- .../unittests/services/extract/helpers.ts | 48 +- .../unittests/services/extract/ranges.ts | 35 +- .../services/extract/symbolWalker.ts | 6 +- .../unittests/services/hostNewLineSupport.ts | 41 +- .../unittests/services/languageService.ts | 44 +- .../unittests/services/organizeImports.ts | 120 +- .../unittests/services/patternMatcher.ts | 117 +- .../unittests/services/preProcessFile.ts | 436 +- .../unittests/services/textChanges.ts | 1486 +- .../unittests/services/transpile.ts | 245 +- .../unittests/services/utilities.ts | 5 +- src/testRunner/unittests/transform.ts | 153 +- .../unittests/tsbuild/amdModulesWithOut.ts | 7 +- .../unittests/tsbuild/commandLine.ts | 48 +- .../unittests/tsbuild/emitDeclarationOnly.ts | 10 +- .../unittests/tsbuild/fileDelete.ts | 7 +- .../unittests/tsbuild/graphOrdering.ts | 20 +- .../unittests/tsbuild/moduleResolution.ts | 23 +- src/testRunner/unittests/tsbuild/noEmit.ts | 7 +- src/testRunner/unittests/tsbuild/outFile.ts | 47 +- .../unittests/tsbuild/outputPaths.ts | 18 +- src/testRunner/unittests/tsbuild/publicApi.ts | 14 +- .../unittests/tsbuild/resolveJsonModule.ts | 8 +- src/testRunner/unittests/tsbuild/sample.ts | 74 +- src/testRunner/unittests/tsbuildWatch/demo.ts | 5 +- .../tsbuildWatch/libraryResolution.ts | 12 +- .../tsbuildWatch/moduleResolution.ts | 74 +- .../unittests/tsbuildWatch/noEmit.ts | 11 +- .../unittests/tsbuildWatch/noEmitOnError.ts | 6 +- .../unittests/tsbuildWatch/programUpdates.ts | 72 +- .../tsbuildWatch/projectsBuilding.ts | 45 +- .../unittests/tsbuildWatch/publicApi.ts | 13 +- .../unittests/tsbuildWatch/reexport.ts | 3 +- .../tsbuildWatch/watchEnvironment.ts | 5 +- .../unittests/tsc/cancellationToken.ts | 13 +- src/testRunner/unittests/tsc/composite.ts | 3 +- .../unittests/tsc/declarationEmit.ts | 78 +- src/testRunner/unittests/tsc/incremental.ts | 85 +- .../unittests/tsc/moduleResolution.ts | 48 +- .../unittests/tsc/runWithoutArgs.ts | 3 +- .../unittests/tscWatch/consoleClearing.ts | 3 +- src/testRunner/unittests/tscWatch/emit.ts | 58 +- .../unittests/tscWatch/emitAndErrorUpdates.ts | 32 +- .../forceConsistentCasingInFileNames.ts | 105 +- .../unittests/tscWatch/incremental.ts | 101 +- .../unittests/tscWatch/libraryResolution.ts | 43 +- .../unittests/tscWatch/moduleResolution.ts | 98 +- .../unittests/tscWatch/nodeNextWatch.ts | 5 +- .../unittests/tscWatch/programUpdates.ts | 271 +- .../tscWatch/projectsWithReferences.ts | 107 +- .../unittests/tscWatch/resolutionCache.ts | 92 +- .../resolveJsonModuleWithIncremental.ts | 6 +- .../sourceOfProjectReferenceRedirect.ts | 11 +- src/testRunner/unittests/tscWatch/watchApi.ts | 216 +- .../unittests/tscWatch/watchEnvironment.ts | 153 +- .../unittests/tsserver/autoImportProvider.ts | 157 +- .../tsserver/cachingFileSystemInformation.ts | 91 +- .../unittests/tsserver/cancellationToken.ts | 15 +- .../unittests/tsserver/compileOnSave.ts | 115 +- .../unittests/tsserver/completions.ts | 18 +- .../tsserver/completionsIncomplete.ts | 187 +- .../unittests/tsserver/configFileSearch.ts | 23 +- .../unittests/tsserver/configuredProjects.ts | 247 +- .../unittests/tsserver/declarationFileMaps.ts | 64 +- .../unittests/tsserver/documentRegistry.ts | 27 +- .../unittests/tsserver/dynamicFiles.ts | 99 +- .../tsserver/events/largeFileReferenced.ts | 17 +- .../events/projectLanguageServiceState.ts | 21 +- .../tsserver/events/projectLoading.ts | 52 +- .../events/projectUpdatedInBackground.ts | 140 +- .../unittests/tsserver/exportMapCache.ts | 39 +- .../unittests/tsserver/externalProjects.ts | 151 +- .../unittests/tsserver/findAllReferences.ts | 12 +- .../forceConsistentCasingInFileNames.ts | 28 +- .../unittests/tsserver/formatSettings.ts | 51 +- .../tsserver/getEditsForFileRename.ts | 19 +- .../unittests/tsserver/getExportReferences.ts | 6 +- .../getMoveToRefactoringFileSuggestions.ts | 54 +- .../unittests/tsserver/importHelpers.ts | 6 +- .../tsserver/inconsistentErrorInEditor.ts | 18 +- .../unittests/tsserver/inferredProjects.ts | 74 +- .../unittests/tsserver/inlayHints.ts | 10 +- src/testRunner/unittests/tsserver/jsdocTag.ts | 36 +- .../unittests/tsserver/languageService.ts | 23 +- .../unittests/tsserver/libraryResolution.ts | 25 +- .../tsserver/maxNodeModuleJsDepth.ts | 41 +- .../unittests/tsserver/metadataInResponse.ts | 12 +- .../unittests/tsserver/moduleResolution.ts | 51 +- .../tsserver/moduleSpecifierCache.ts | 69 +- src/testRunner/unittests/tsserver/openFile.ts | 26 +- .../unittests/tsserver/packageJsonInfo.ts | 22 +- .../tsserver/partialSemanticServer.ts | 36 +- src/testRunner/unittests/tsserver/plugins.ts | 16 +- .../unittests/tsserver/pluginsAsync.ts | 24 +- .../unittests/tsserver/projectErrors.ts | 137 +- .../tsserver/projectReferenceCompileOnSave.ts | 244 +- .../tsserver/projectReferenceErrors.ts | 8 +- .../unittests/tsserver/projectReferences.ts | 309 +- .../tsserver/projectReferencesSourcemap.ts | 819 +- src/testRunner/unittests/tsserver/projects.ts | 303 +- .../tsserver/projectsWithReferences.ts | 60 +- .../unittests/tsserver/refactors.ts | 6 +- .../unittests/tsserver/reloadProjects.ts | 5 +- src/testRunner/unittests/tsserver/rename.ts | 6 +- .../unittests/tsserver/resolutionCache.ts | 123 +- src/testRunner/unittests/tsserver/session.ts | 13 +- .../unittests/tsserver/skipLibCheck.ts | 6 +- src/testRunner/unittests/tsserver/symLinks.ts | 157 +- .../unittests/tsserver/symlinkCache.ts | 6 +- .../unittests/tsserver/syntacticServer.ts | 17 +- .../unittests/tsserver/syntaxOperations.ts | 5 +- .../unittests/tsserver/telemetry.ts | 10 +- .../unittests/tsserver/textStorage.ts | 30 +- .../unittests/tsserver/typeAquisition.ts | 6 +- .../tsserver/typeOnlyImportChains.ts | 6 +- .../tsserver/typeReferenceDirectives.ts | 12 +- .../unittests/tsserver/typingsInstaller.ts | 353 +- .../unittests/tsserver/versionCache.ts | 20 +- .../unittests/tsserver/watchEnvironment.ts | 39 +- src/tsserver/nodeServer.ts | 118 +- src/tsserver/server.ts | 9 +- src/typingsInstaller/nodeTypingsInstaller.ts | 111 +- src/typingsInstallerCore/typingsInstaller.ts | 107 +- .../reference/api/tsserverlibrary.d.ts | 3317 +- tests/baselines/reference/api/typescript.d.ts | 3147 +- ...oToTypeDefinition_arrayType.baseline.jsonc | 30 +- ...oTypeDefinition_promiseType.baseline.jsonc | 18 +- 439 files changed, 87581 insertions(+), 23222 deletions(-) diff --git a/Herebyfile.mjs b/Herebyfile.mjs index 700e974a7a101..3c81c2fa4dbd0 100644 --- a/Herebyfile.mjs +++ b/Herebyfile.mjs @@ -131,7 +131,12 @@ const localize = task({ dependencies: [generateDiagnostics], run: async () => { if (needsUpdate(diagnosticMessagesGeneratedJson, generatedLCGFile)) { - await exec(process.execPath, ["scripts/generateLocalizedDiagnosticMessages.mjs", "src/loc/lcl", "built/local", diagnosticMessagesGeneratedJson], { ignoreExitCode: true }); + await exec(process.execPath, [ + "scripts/generateLocalizedDiagnosticMessages.mjs", + "src/loc/lcl", + "built/local", + diagnosticMessagesGeneratedJson, + ], { ignoreExitCode: true }); } }, }); @@ -312,7 +317,10 @@ function entrypointBuildTask(options) { const outDir = path.dirname(options.output); await fs.promises.mkdir(outDir, { recursive: true }); const moduleSpecifier = path.relative(outDir, options.builtEntrypoint); - await fs.promises.writeFile(options.output, `module.exports = require("./${moduleSpecifier.replace(/[\\/]/g, "/")}")`); + await fs.promises.writeFile( + options.output, + `module.exports = require("./${moduleSpecifier.replace(/[\\/]/g, "/")}")`, + ); }, }); @@ -336,13 +344,19 @@ function entrypointBuildTask(options) { const watch = task({ name: `watch-${options.name}`, hiddenFromTaskList: true, // This is best effort. - dependencies: (options.buildDeps ?? []).concat(options.mainDeps ?? []).concat(cmdLineOptions.bundle ? [] : [shim]), + dependencies: (options.buildDeps ?? []).concat(options.mainDeps ?? []).concat( + cmdLineOptions.bundle ? [] : [shim], + ), run: () => { // These watch functions return promises that resolve once watch mode has started, // allowing them to operate as regular tasks, while creating unresolved promises // in the background that keep the process running after all tasks have exited. if (!printedWatchWarning) { - console.error(chalk.yellowBright("Warning: watch mode is incomplete and may not work as expected. Use at your own risk.")); + console.error( + chalk.yellowBright( + "Warning: watch mode is incomplete and may not work as expected. Use at your own risk.", + ), + ); printedWatchWarning = true; } @@ -386,7 +400,12 @@ export const dtsServices = task({ description: "Bundles typescript.d.ts", dependencies: [buildServices], run: async () => { - if (needsUpdate("./built/local/typescript/tsconfig.tsbuildinfo", ["./built/local/typescript.d.ts", "./built/local/typescript.internal.d.ts"])) { + if ( + needsUpdate("./built/local/typescript/tsconfig.tsbuildinfo", [ + "./built/local/typescript.d.ts", + "./built/local/typescript.internal.d.ts", + ]) + ) { await runDtsBundler("./built/local/typescript/typescript.d.ts", "./built/local/typescript.d.ts"); } }, @@ -435,8 +454,16 @@ export const dtsLssl = task({ description: "Bundles tsserverlibrary.d.ts", dependencies: [buildLssl], run: async () => { - if (needsUpdate("./built/local/tsserverlibrary/tsconfig.tsbuildinfo", ["./built/local/tsserverlibrary.d.ts", "./built/local/tsserverlibrary.internal.d.ts"])) { - await runDtsBundler("./built/local/tsserverlibrary/tsserverlibrary.d.ts", "./built/local/tsserverlibrary.d.ts"); + if ( + needsUpdate("./built/local/tsserverlibrary/tsconfig.tsbuildinfo", [ + "./built/local/tsserverlibrary.d.ts", + "./built/local/tsserverlibrary.internal.d.ts", + ]) + ) { + await runDtsBundler( + "./built/local/tsserverlibrary/tsserverlibrary.d.ts", + "./built/local/tsserverlibrary.d.ts", + ); } }, }); @@ -572,7 +599,13 @@ export const watchOtherOutputs = task({ name: "watch-other-outputs", description: "Builds miscelaneous scripts and documents distributed with the LKG", hiddenFromTaskList: true, - dependencies: [watchCancellationToken, watchTypingsInstaller, watchWatchGuard, generateTypesMap, copyBuiltLocalDiagnosticMessages], + dependencies: [ + watchCancellationToken, + watchTypingsInstaller, + watchWatchGuard, + generateTypesMap, + copyBuiltLocalDiagnosticMessages, + ], }); export const local = task({ @@ -650,7 +683,10 @@ export const runTestsAndWatch = task({ if (!token.signaled) { running = true; try { - await runConsoleTests(testRunner, "mocha-fivemat-progress-reporter", /*runInParallel*/ false, { token, watching: true }); + await runConsoleTests(testRunner, "mocha-fivemat-progress-reporter", /*runInParallel*/ false, { + token, + watching: true, + }); } catch { // ignore @@ -805,7 +841,10 @@ export const updateSublime = task({ dependencies: [tsserver], run: async () => { for (const file of ["built/local/tsserver.js", "built/local/tsserver.js.map"]) { - await fs.promises.copyFile(file, path.resolve("../TypeScript-Sublime-Plugin/tsserver/", path.basename(file))); + await fs.promises.copyFile( + file, + path.resolve("../TypeScript-Sublime-Plugin/tsserver/", path.basename(file)), + ); } }, }); @@ -834,7 +873,10 @@ export const produceLKG = task({ .concat(localizationTargets) .filter(f => !fs.existsSync(f)); if (missingFiles.length > 0) { - throw new Error("Cannot replace the LKG unless all built targets are present in directory 'built/local/'. The following files are missing:\n" + missingFiles.join("\n")); + throw new Error( + "Cannot replace the LKG unless all built targets are present in directory 'built/local/'. The following files are missing:\n" + + missingFiles.join("\n"), + ); } await exec(process.execPath, ["scripts/produceLKG.mjs"]); @@ -862,19 +904,37 @@ export const clean = task({ export const configureNightly = task({ name: "configure-nightly", description: "Runs scripts/configurePrerelease.mjs to prepare a build for nightly publishing", - run: () => exec(process.execPath, ["scripts/configurePrerelease.mjs", "dev", "package.json", "src/compiler/corePublic.ts"]), + run: () => + exec(process.execPath, [ + "scripts/configurePrerelease.mjs", + "dev", + "package.json", + "src/compiler/corePublic.ts", + ]), }); export const configureInsiders = task({ name: "configure-insiders", description: "Runs scripts/configurePrerelease.mjs to prepare a build for insiders publishing", - run: () => exec(process.execPath, ["scripts/configurePrerelease.mjs", "insiders", "package.json", "src/compiler/corePublic.ts"]), + run: () => + exec(process.execPath, [ + "scripts/configurePrerelease.mjs", + "insiders", + "package.json", + "src/compiler/corePublic.ts", + ]), }); export const configureExperimental = task({ name: "configure-experimental", description: "Runs scripts/configurePrerelease.mjs to prepare a build for experimental publishing", - run: () => exec(process.execPath, ["scripts/configurePrerelease.mjs", "experimental", "package.json", "src/compiler/corePublic.ts"]), + run: () => + exec(process.execPath, [ + "scripts/configurePrerelease.mjs", + "experimental", + "package.json", + "src/compiler/corePublic.ts", + ]), }); export const help = task({ diff --git a/scripts/build/localization.mjs b/scripts/build/localization.mjs index 142bd14c1a073..e429db6ea3b32 100644 --- a/scripts/build/localization.mjs +++ b/scripts/build/localization.mjs @@ -1 +1,15 @@ -export const localizationDirectories = ["cs", "de", "es", "fr", "it", "ja", "ko", "pl", "pt-br", "ru", "tr", "zh-cn", "zh-tw"].map(f => f.toLowerCase()); +export const localizationDirectories = [ + "cs", + "de", + "es", + "fr", + "it", + "ja", + "ko", + "pl", + "pt-br", + "ru", + "tr", + "zh-cn", + "zh-tw", +].map(f => f.toLowerCase()); diff --git a/scripts/build/options.mjs b/scripts/build/options.mjs index 9cd8f64c3ba92..a8ab056c76096 100644 --- a/scripts/build/options.mjs +++ b/scripts/build/options.mjs @@ -4,7 +4,23 @@ import os from "os"; const ci = ["1", "true"].includes(process.env.CI ?? ""); const parsed = minimist(process.argv.slice(2), { - boolean: ["dirty", "light", "colors", "lkg", "soft", "fix", "failed", "keepFailed", "force", "built", "ci", "bundle", "typecheck", "lint", "coverage"], + boolean: [ + "dirty", + "light", + "colors", + "lkg", + "soft", + "fix", + "failed", + "keepFailed", + "force", + "built", + "ci", + "bundle", + "typecheck", + "lint", + "coverage", + ], string: ["browser", "tests", "break", "host", "reporter", "stackTraceLimit", "timeout", "shards", "shardId"], alias: { /* eslint-disable quote-props */ diff --git a/scripts/build/projects.mjs b/scripts/build/projects.mjs index 70e25766672c0..5657c71abd9dc 100644 --- a/scripts/build/projects.mjs +++ b/scripts/build/projects.mjs @@ -39,14 +39,17 @@ class ProjectQueue { const tscPath = resolve( findUpRoot(), - cmdLineOptions.lkg ? "./lib/tsc.js" : - cmdLineOptions.built ? "./built/local/tsc.js" : - "./node_modules/typescript/lib/tsc.js", + cmdLineOptions.lkg ? "./lib/tsc.js" + : cmdLineOptions.built ? "./built/local/tsc.js" + : "./node_modules/typescript/lib/tsc.js", ); -const execTsc = (/** @type {string[]} */ ...args) => exec(process.execPath, [tscPath, "-b", ...args], { hidePrompt: true }); +const execTsc = (/** @type {string[]} */ ...args) => + exec(process.execPath, [tscPath, "-b", ...args], { hidePrompt: true }); -const projectBuilder = new ProjectQueue(projects => execTsc(...(cmdLineOptions.bundle ? [] : ["--emitDeclarationOnly", "false"]), ...projects)); +const projectBuilder = new ProjectQueue(projects => + execTsc(...(cmdLineOptions.bundle ? [] : ["--emitDeclarationOnly", "false"]), ...projects) +); /** * @param {string} project diff --git a/scripts/build/tests.mjs b/scripts/build/tests.mjs index eda3422e365d1..6bd776a17b029 100644 --- a/scripts/build/tests.mjs +++ b/scripts/build/tests.mjs @@ -79,7 +79,18 @@ export async function runConsoleTests(runJs, defaultReporter, runInParallel, opt } if (tests || runners || light || testTimeout || taskConfigsFolder || keepFailed || shards || shardId) { - writeTestConfigFile(tests, runners, light, taskConfigsFolder, workerCount, stackTraceLimit, testTimeout, keepFailed, shards, shardId); + writeTestConfigFile( + tests, + runners, + light, + taskConfigsFolder, + workerCount, + stackTraceLimit, + testTimeout, + keepFailed, + shards, + shardId, + ); } const colors = cmdLineOptions.colors; @@ -198,7 +209,18 @@ async function cleanCoverageDir() { * @param {number | undefined} [shards] * @param {number | undefined} [shardId] */ -export function writeTestConfigFile(tests, runners, light, taskConfigsFolder, workerCount, stackTraceLimit, timeout, keepFailed, shards, shardId) { +export function writeTestConfigFile( + tests, + runners, + light, + taskConfigsFolder, + workerCount, + stackTraceLimit, + timeout, + keepFailed, + shards, + shardId, +) { const testConfigContents = JSON.stringify({ test: tests ? [tests] : undefined, runners: runners ? runners.split(",") : undefined, diff --git a/scripts/build/utils.mjs b/scripts/build/utils.mjs index 6a60fec2d995d..dfd862bced779 100644 --- a/scripts/build/utils.mjs +++ b/scripts/build/utils.mjs @@ -28,7 +28,9 @@ export async function exec(cmd, args, options = {}) { const { ignoreExitCode, waitForExit = true, ignoreStdout } = options; if (!options.hidePrompt) console.log(`> ${chalk.green(cmd)} ${args.join(" ")}`); - const proc = spawn(which.sync(cmd), args, { stdio: waitForExit ? ignoreStdout ? ["inherit", "ignore", "inherit"] : "inherit" : "ignore" }); + const proc = spawn(which.sync(cmd), args, { + stdio: waitForExit ? ignoreStdout ? ["inherit", "ignore", "inherit"] : "inherit" : "ignore", + }); if (waitForExit) { const onCanceled = () => { proc.kill(); @@ -39,8 +41,8 @@ export async function exec(cmd, args, options = {}) { resolve({ exitCode: exitCode ?? undefined }); } else { - const reason = options.token?.signaled ? options.token.reason ?? new CancelError() : - new ExecError(exitCode); + const reason = options.token?.signaled ? options.token.reason ?? new CancelError() + : new ExecError(exitCode); reject(reason); } subscription?.unsubscribe(); diff --git a/scripts/checkPackageSize.mjs b/scripts/checkPackageSize.mjs index 4d65c7328102e..4ba086b9bfa84 100644 --- a/scripts/checkPackageSize.mjs +++ b/scripts/checkPackageSize.mjs @@ -5,7 +5,9 @@ const baseRepo = process.argv[2]; const headRepo = process.argv[3]; /** @type {Array<{ size: number, unpackedSize: number; files: Array<{ path: string; size: number; }>; }>} */ -const [before, after] = JSON.parse(cp.execFileSync("npm", ["pack", "--dry-run", "--json", baseRepo, headRepo], { encoding: "utf8" })); +const [before, after] = JSON.parse( + cp.execFileSync("npm", ["pack", "--dry-run", "--json", baseRepo, headRepo], { encoding: "utf8" }), +); /** @param {{ path: string; size: number; }[]} files */ function filesToMap(files) { diff --git a/scripts/configurePrerelease.mjs b/scripts/configurePrerelease.mjs index de0d48f0f657e..41e157e9d63bc 100644 --- a/scripts/configurePrerelease.mjs +++ b/scripts/configurePrerelease.mjs @@ -54,7 +54,8 @@ function main() { // Ensure we are actually changing something - the user probably wants to know that the update failed. if (tsFileContents === modifiedTsFileContents) { let err = `\n '${tsFilePath}' was not updated while configuring for a prerelease publish for '${tag}'.\n `; - err += `Ensure that you have not already run this script; otherwise, erase your changes using 'git checkout -- "${tsFilePath}"'.`; + err += + `Ensure that you have not already run this script; otherwise, erase your changes using 'git checkout -- "${tsFilePath}"'.`; throw new Error(err + "\n"); } @@ -78,19 +79,31 @@ function main() { function updateTsFile(tsFilePath, tsFileContents, majorMinor, patch, nightlyPatch) { const majorMinorRgx = /export const versionMajorMinor = "(\d+\.\d+)"/; const majorMinorMatch = majorMinorRgx.exec(tsFileContents); - assert(majorMinorMatch !== null, `The file '${tsFilePath}' seems to no longer have a string matching '${majorMinorRgx}'.`); + assert( + majorMinorMatch !== null, + `The file '${tsFilePath}' seems to no longer have a string matching '${majorMinorRgx}'.`, + ); const parsedMajorMinor = majorMinorMatch[1]; - assert(parsedMajorMinor === majorMinor, `versionMajorMinor does not match. ${tsFilePath}: '${parsedMajorMinor}'; package.json: '${majorMinor}'`); + assert( + parsedMajorMinor === majorMinor, + `versionMajorMinor does not match. ${tsFilePath}: '${parsedMajorMinor}'; package.json: '${majorMinor}'`, + ); const versionRgx = /export const version(?:: string)? = `\$\{versionMajorMinor\}\.(\d)(-\w+)?`;/; const patchMatch = versionRgx.exec(tsFileContents); - assert(patchMatch !== null, `The file '${tsFilePath}' seems to no longer have a string matching '${versionRgx.toString()}'.`); + assert( + patchMatch !== null, + `The file '${tsFilePath}' seems to no longer have a string matching '${versionRgx.toString()}'.`, + ); const parsedPatch = patchMatch[1]; if (parsedPatch !== patch) { throw new Error(`patch does not match. ${tsFilePath}: '${parsedPatch}; package.json: '${patch}'`); } - return tsFileContents.replace(versionRgx, `export const version: string = \`\${versionMajorMinor}.${nightlyPatch}\`;`); + return tsFileContents.replace( + versionRgx, + `export const version: string = \`\${versionMajorMinor}.${nightlyPatch}\`;`, + ); } /** diff --git a/scripts/dtsBundler.mjs b/scripts/dtsBundler.mjs index ddf3b36cefd79..cf95f1575ef46 100644 --- a/scripts/dtsBundler.mjs +++ b/scripts/dtsBundler.mjs @@ -56,8 +56,14 @@ function isInternalDeclaration(node) { */ function getParentVariableStatement(node) { const declarationList = node.parent; - assert(ts.isVariableDeclarationList(declarationList), `expected VariableDeclarationList at ${nodeToLocation(node)}`); - assert(declarationList.declarations.length === 1, `expected VariableDeclarationList of length 1 at ${nodeToLocation(node)}`); + assert( + ts.isVariableDeclarationList(declarationList), + `expected VariableDeclarationList at ${nodeToLocation(node)}`, + ); + assert( + declarationList.declarations.length === 1, + `expected VariableDeclarationList of length 1 at ${nodeToLocation(node)}`, + ); const variableStatement = declarationList.parent; assert(ts.isVariableStatement(variableStatement), `expected VariableStatement at ${nodeToLocation(node)}`); return variableStatement; @@ -235,7 +241,8 @@ function findInScope(name) { /** @type {(symbol: ts.Symbol | undefined, excludes?: ts.SymbolFlags) => boolean} */ function isNonLocalAlias(symbol, excludes = ts.SymbolFlags.Value | ts.SymbolFlags.Type | ts.SymbolFlags.Namespace) { if (!symbol) return false; - return (symbol.flags & (ts.SymbolFlags.Alias | excludes)) === ts.SymbolFlags.Alias || !!(symbol.flags & ts.SymbolFlags.Alias && symbol.flags & ts.SymbolFlags.Assignment); + return (symbol.flags & (ts.SymbolFlags.Alias | excludes)) === ts.SymbolFlags.Alias + || !!(symbol.flags & ts.SymbolFlags.Alias && symbol.flags & ts.SymbolFlags.Assignment); } /** @@ -319,7 +326,13 @@ function verifyMatchingSymbols(decl) { } if (symbolsConflict(symbolOfNode, symbolInScope)) { - fail(`Declaration at ${nodeToLocation(decl)}\n references ${symbolOfNode.name} at ${symbolOfNode.declarations && nodeToLocation(symbolOfNode.declarations[0])},\n but containing scope contains a symbol with the same name declared at ${symbolInScope.declarations && nodeToLocation(symbolInScope.declarations[0])}`); + fail( + `Declaration at ${nodeToLocation(decl)}\n references ${symbolOfNode.name} at ${ + symbolOfNode.declarations && nodeToLocation(symbolOfNode.declarations[0]) + },\n but containing scope contains a symbol with the same name declared at ${ + symbolInScope.declarations && nodeToLocation(symbolInScope.declarations[0]) + }`, + ); } } diff --git a/scripts/eslint/rules/debug-assert.cjs b/scripts/eslint/rules/debug-assert.cjs index 31a735c246889..58f289e0de2ff 100644 --- a/scripts/eslint/rules/debug-assert.cjs +++ b/scripts/eslint/rules/debug-assert.cjs @@ -9,7 +9,8 @@ module.exports = createRule({ }, messages: { secondArgumentDebugAssertError: `Second argument to 'Debug.assert' should be a string literal`, - thirdArgumentDebugAssertError: `Third argument to 'Debug.assert' should be a string literal or arrow function`, + thirdArgumentDebugAssertError: + `Third argument to 'Debug.assert' should be a string literal or arrow function`, }, schema: [], type: "problem", @@ -21,7 +22,8 @@ module.exports = createRule({ const isArrowFunction = node => node.type === AST_NODE_TYPES.ArrowFunctionExpression; /** @type {(node: TSESTree.Node) => boolean} */ const isStringLiteral = node => ( - (node.type === AST_NODE_TYPES.Literal && typeof node.value === "string") || node.type === AST_NODE_TYPES.TemplateLiteral + (node.type === AST_NODE_TYPES.Literal && typeof node.value === "string") + || node.type === AST_NODE_TYPES.TemplateLiteral ); /** @type {(node: TSESTree.MemberExpression) => boolean} */ diff --git a/scripts/eslint/rules/jsdoc-format.cjs b/scripts/eslint/rules/jsdoc-format.cjs index b16de44b4aaa5..be7f8586465c0 100644 --- a/scripts/eslint/rules/jsdoc-format.cjs +++ b/scripts/eslint/rules/jsdoc-format.cjs @@ -11,7 +11,8 @@ module.exports = createRule({ internalCommentInNonJSDocError: `@internal should not appear in non-JSDoc comment for declaration.`, internalCommentNotLastError: `@internal should only appear in final JSDoc comment for declaration.`, multipleJSDocError: `Declaration has multiple JSDoc comments.`, - internalCommentOnParameterProperty: `@internal cannot appear on a JSDoc comment; use a declared property and an assignment in the constructor instead.`, + internalCommentOnParameterProperty: + `@internal cannot appear on a JSDoc comment; use a declared property and an assignment in the constructor instead.`, }, schema: [], type: "problem", @@ -80,13 +81,25 @@ module.exports = createRule({ } if (!isJSDoc) { - context.report({ messageId: "internalCommentInNonJSDocError", node: c, loc: getAtInternalLoc(c, indexInComment) }); + context.report({ + messageId: "internalCommentInNonJSDocError", + node: c, + loc: getAtInternalLoc(c, indexInComment), + }); } else if (i !== last) { - context.report({ messageId: "internalCommentNotLastError", node: c, loc: getAtInternalLoc(c, indexInComment) }); + context.report({ + messageId: "internalCommentNotLastError", + node: c, + loc: getAtInternalLoc(c, indexInComment), + }); } else if (node.type === "TSParameterProperty") { - context.report({ messageId: "internalCommentOnParameterProperty", node: c, loc: getAtInternalLoc(c, indexInComment) }); + context.report({ + messageId: "internalCommentOnParameterProperty", + node: c, + loc: getAtInternalLoc(c, indexInComment), + }); } } }; diff --git a/scripts/eslint/rules/no-double-space.cjs b/scripts/eslint/rules/no-double-space.cjs index 35ad24474660f..63eb580f0a504 100644 --- a/scripts/eslint/rules/no-double-space.cjs +++ b/scripts/eslint/rules/no-double-space.cjs @@ -22,15 +22,16 @@ module.exports = createRule({ /** @type {(node: TSESTree.Node | null) => boolean} */ const isStringLiteral = node => { return !!(node && ( - (node.type === AST_NODE_TYPES.TemplateElement) || - (node.type === AST_NODE_TYPES.TemplateLiteral && node.quasis) || - (node.type === AST_NODE_TYPES.Literal && typeof node.value === "string") + (node.type === AST_NODE_TYPES.TemplateElement) + || (node.type === AST_NODE_TYPES.TemplateLiteral && node.quasis) + || (node.type === AST_NODE_TYPES.Literal && typeof node.value === "string") )); }; /** @type {(node: TSESTree.Node | null) => boolean} */ const isRegexLiteral = node => { - return !!(node && node.type === AST_NODE_TYPES.Literal && Object.prototype.hasOwnProperty.call(node, "regex")); + return !!(node && node.type === AST_NODE_TYPES.Literal + && Object.prototype.hasOwnProperty.call(node, "regex")); }; /** @type {(node: TSESTree.Node) => void} */ @@ -61,7 +62,11 @@ module.exports = createRule({ return; } - context.report({ messageId: "noDoubleSpaceError", node, loc: { line: index + 1, column: doubleSpace.index + 1 } }); + context.report({ + messageId: "noDoubleSpaceError", + node, + loc: { line: index + 1, column: doubleSpace.index + 1 }, + }); }); }; diff --git a/scripts/eslint/rules/no-keywords.cjs b/scripts/eslint/rules/no-keywords.cjs index a0032bf5ff102..d7c9f6f3fd8aa 100644 --- a/scripts/eslint/rules/no-keywords.cjs +++ b/scripts/eslint/rules/no-keywords.cjs @@ -46,10 +46,10 @@ module.exports = createRule({ const checkProperties = node => { node.properties.forEach(property => { if ( - property && - property.type === AST_NODE_TYPES.Property && - property.key.type === AST_NODE_TYPES.Identifier && - isKeyword(property.key.name) + property + && property.type === AST_NODE_TYPES.Property + && property.key.type === AST_NODE_TYPES.Identifier + && isKeyword(property.key.name) ) { report(property.key); } @@ -60,9 +60,9 @@ module.exports = createRule({ const checkElements = node => { node.elements.forEach(element => { if ( - element && - element.type === AST_NODE_TYPES.Identifier && - isKeyword(element.name) + element + && element.type === AST_NODE_TYPES.Identifier + && isKeyword(element.name) ) { report(element); } @@ -77,9 +77,9 @@ module.exports = createRule({ node.params.forEach(param => { if ( - param && - param.type === AST_NODE_TYPES.Identifier && - isKeyword(param.name) + param + && param.type === AST_NODE_TYPES.Identifier + && isKeyword(param.name) ) { report(param); } @@ -97,8 +97,8 @@ module.exports = createRule({ } if ( - node.id.type === AST_NODE_TYPES.Identifier && - isKeyword(node.id.name) + node.id.type === AST_NODE_TYPES.Identifier + && isKeyword(node.id.name) ) { report(node.id); } diff --git a/scripts/eslint/rules/only-arrow-functions.cjs b/scripts/eslint/rules/only-arrow-functions.cjs index 9abde8775c08d..898d96dce0efb 100644 --- a/scripts/eslint/rules/only-arrow-functions.cjs +++ b/scripts/eslint/rules/only-arrow-functions.cjs @@ -28,7 +28,9 @@ module.exports = createRule({ create(context, [{ allowNamedFunctions, allowDeclarations }]) { /** @type {(node: TSESTree.FunctionDeclaration | TSESTree.FunctionExpression) => boolean} */ - const isThisParameter = node => !!node.params.length && !!node.params.find(param => param.type === AST_NODE_TYPES.Identifier && param.name === "this"); + const isThisParameter = node => + !!node.params.length + && !!node.params.find(param => param.type === AST_NODE_TYPES.Identifier && param.name === "this"); /** @type {(node: TSESTree.Node) => boolean} */ const isMethodType = node => { diff --git a/scripts/failed-tests.cjs b/scripts/failed-tests.cjs index c214f6eea90b1..8160b73de506e 100644 --- a/scripts/failed-tests.cjs +++ b/scripts/failed-tests.cjs @@ -138,17 +138,23 @@ class FailedTestsReporter extends Mocha.reporters.Base { done(failures, fn) { assert(this.reporterOptions); assert(this.reporterOptions.file); - FailedTestsReporter.writeFailures(this.reporterOptions.file, this.passes, this.failures, this.reporterOptions.keepFailed || this.stats.tests === 0, err => { - const reporter = this.reporter; - if (reporter && reporter.done) { - reporter.done(failures, fn); - } - else if (fn) { - fn(failures); - } + FailedTestsReporter.writeFailures( + this.reporterOptions.file, + this.passes, + this.failures, + this.reporterOptions.keepFailed || this.stats.tests === 0, + err => { + const reporter = this.reporter; + if (reporter && reporter.done) { + reporter.done(failures, fn); + } + else if (fn) { + fn(failures); + } - if (err) console.error(err); - }); + if (err) console.error(err); + }, + ); } } diff --git a/scripts/generateLocalizedDiagnosticMessages.mjs b/scripts/generateLocalizedDiagnosticMessages.mjs index 72b3e7febcf6f..dfb89c207d492 100644 --- a/scripts/generateLocalizedDiagnosticMessages.mjs +++ b/scripts/generateLocalizedDiagnosticMessages.mjs @@ -28,7 +28,9 @@ async function main() { const args = process.argv.slice(2); if (args.length !== 3) { console.log("Usage:"); - console.log("\tnode generateLocalizedDiagnosticMessages.js "); + console.log( + "\tnode generateLocalizedDiagnosticMessages.js ", + ); return; } @@ -62,7 +64,10 @@ async function main() { console.error(`Invalid output locale name for '${result.LCX.$_TgtCul}'.`); process.exit(1); } - await writeFile(path.join(outputPath, outputDirectoryName, "diagnosticMessages.generated.json"), xmlObjectToString(result)); + await writeFile( + path.join(outputPath, outputDirectoryName, "diagnosticMessages.generated.json"), + xmlObjectToString(result), + ); } /** diff --git a/scripts/open-cherry-pick-pr.mjs b/scripts/open-cherry-pick-pr.mjs index 46c166c9c5f03..13002bb7b0e36 100644 --- a/scripts/open-cherry-pick-pr.mjs +++ b/scripts/open-cherry-pick-pr.mjs @@ -36,9 +36,13 @@ async function main() { auth: process.argv[2], }); - const inputPR = (await gh.pulls.get({ pull_number: +process.env.SOURCE_ISSUE, owner: "microsoft", repo: "TypeScript" })).data; + const inputPR = + (await gh.pulls.get({ pull_number: +process.env.SOURCE_ISSUE, owner: "microsoft", repo: "TypeScript" })).data; let remoteName = "origin"; - if (inputPR.base.repo.git_url !== `git:github.com/microsoft/TypeScript` && inputPR.base.repo.git_url !== `git://github.com/microsoft/TypeScript`) { + if ( + inputPR.base.repo.git_url !== `git:github.com/microsoft/TypeScript` + && inputPR.base.repo.git_url !== `git://github.com/microsoft/TypeScript` + ) { runSequence([ ["git", ["remote", "add", "nonlocal", inputPR.base.repo.git_url.replace(/^git:(?:\/\/)?/, "https://")]], ]); @@ -90,11 +94,16 @@ ${logText.trim()}`; owner: "Microsoft", repo: "TypeScript", maintainer_can_modify: true, - title: `🤖 Pick PR #${process.env.SOURCE_ISSUE} (${inputPR.title.substring(0, 35)}${inputPR.title.length > 35 ? "..." : ""}) into ${process.env.TARGET_BRANCH}`, + title: `🤖 Pick PR #${process.env.SOURCE_ISSUE} (${inputPR.title.substring(0, 35)}${ + inputPR.title.length > 35 ? "..." : "" + }) into ${process.env.TARGET_BRANCH}`, head: `${userName}:${branchName}`, base: process.env.TARGET_BRANCH, - body: `This cherry-pick was triggered by a request on https://github.com/Microsoft/TypeScript/pull/${process.env.SOURCE_ISSUE} -Please review the diff and merge if no changes are unexpected.${produceLKG ? ` An LKG update commit is included separately from the base change.` : ""} + body: + `This cherry-pick was triggered by a request on https://github.com/Microsoft/TypeScript/pull/${process.env.SOURCE_ISSUE} +Please review the diff and merge if no changes are unexpected.${ + produceLKG ? ` An LKG update commit is included separately from the base change.` : "" + } You can view the cherry-pick log [here](https://typescript.visualstudio.com/TypeScript/_build/index?buildId=${process.env.BUILD_BUILDID}&_a=summary). cc ${reviewers.map(r => "@" + r).join(" ")}`, @@ -121,7 +130,8 @@ main().catch(async e => { issue_number: +process.env.SOURCE_ISSUE, owner: "Microsoft", repo: "TypeScript", - body: `Hey @${process.env.REQUESTING_USER}, I couldn't open a PR with the cherry-pick. ([You can check the log here](https://typescript.visualstudio.com/TypeScript/_build/index?buildId=${process.env.BUILD_BUILDID}&_a=summary)). You may need to squash and pick this PR into ${process.env.TARGET_BRANCH} manually.`, + body: + `Hey @${process.env.REQUESTING_USER}, I couldn't open a PR with the cherry-pick. ([You can check the log here](https://typescript.visualstudio.com/TypeScript/_build/index?buildId=${process.env.BUILD_BUILDID}&_a=summary)). You may need to squash and pick this PR into ${process.env.TARGET_BRANCH} manually.`, }); } }); diff --git a/scripts/open-user-pr.mjs b/scripts/open-user-pr.mjs index ef2509a075c44..ac706c3a1da5a 100644 --- a/scripts/open-user-pr.mjs +++ b/scripts/open-user-pr.mjs @@ -7,10 +7,12 @@ import { } from "./run-sequence.mjs"; const userName = process.env.GH_USERNAME || "typescript-bot"; -const reviewers = process.env.REQUESTING_USER ? [process.env.REQUESTING_USER] : ["weswigham", "sandersn", "RyanCavanaugh"]; +const reviewers = process.env.REQUESTING_USER ? [process.env.REQUESTING_USER] + : ["weswigham", "sandersn", "RyanCavanaugh"]; const masterBranchname = `user-baseline-updates`; const targetBranch = process.env.TARGET_BRANCH || "main"; -const branchName = process.env.TARGET_FORK?.toLowerCase() === "microsoft" && (targetBranch === "main" || targetBranch === "refs/heads/main") +const branchName = process.env.TARGET_FORK?.toLowerCase() === "microsoft" + && (targetBranch === "main" || targetBranch === "refs/heads/main") ? masterBranchname : `user-update-${process.env.TARGET_FORK}-${process.env.TARGET_BRANCH ? "-" + process.env.TARGET_BRANCH : ""}`; const remoteUrl = `https://${process.argv[2]}@github.com/${userName}/TypeScript.git`; @@ -23,7 +25,11 @@ runSequence([ ["node", ["./node_modules/hereby/dist/cli.js", "baseline-accept"]], // accept baselines ["git", ["checkout", "-b", branchName]], // create a branch ["git", ["add", "."]], // Add all changes - ["git", ["commit", "-m", `"Update user baselines${+(process.env.SOURCE_ISSUE ?? 0) === 33716 ? " +cc @sandersn" : ""}"`]], // Commit all changes (ping nathan if we would post to CI thread) + ["git", [ + "commit", + "-m", + `"Update user baselines${+(process.env.SOURCE_ISSUE ?? 0) === 33716 ? " +cc @sandersn" : ""}"`, + ]], // Commit all changes (ping nathan if we would post to CI thread) ["git", ["push", "--set-upstream", "fork", branchName, "-f"]], // push the branch ]); @@ -35,10 +41,15 @@ gh.pulls.create({ owner: prOwner, repo: "TypeScript", maintainer_can_modify: true, - title: `🤖 User test baselines have changed` + (process.env.TARGET_BRANCH ? ` for ${process.env.TARGET_BRANCH}` : ""), + title: `🤖 User test baselines have changed` + + (process.env.TARGET_BRANCH ? ` for ${process.env.TARGET_BRANCH}` : ""), head: `${userName}:${branchName}`, base: branchName === masterBranchname ? "main" : masterBranchname, - body: `${process.env.SOURCE_ISSUE ? `This test run was triggerd by a request on https://github.com/Microsoft/TypeScript/pull/${process.env.SOURCE_ISSUE} ` + "\n" : ""}Please review the diff and merge if no changes are unexpected. + body: `${ + process.env.SOURCE_ISSUE + ? `This test run was triggerd by a request on https://github.com/Microsoft/TypeScript/pull/${process.env.SOURCE_ISSUE} ` + + "\n" : "" + }Please review the diff and merge if no changes are unexpected. You can view the build log [here](https://typescript.visualstudio.com/TypeScript/_build/index?buildId=${process.env.BUILD_BUILDID}&_a=summary). cc ${reviewers.map(r => "@" + r).join(" ")}`, @@ -58,7 +69,8 @@ cc ${reviewers.map(r => "@" + r).join(" ")}`, issue_number: +process.env.SOURCE_ISSUE, owner: "microsoft", repo: "TypeScript", - body: `The user suite test run you requested has finished and _failed_. I've opened a [PR with the baseline diff from master](${r.data.html_url}).`, + body: + `The user suite test run you requested has finished and _failed_. I've opened a [PR with the baseline diff from master](${r.data.html_url}).`, }); } }).then(() => { diff --git a/scripts/perf-result-post.mjs b/scripts/perf-result-post.mjs index 1be50f172ab1b..c64ae5eb6ca01 100644 --- a/scripts/perf-result-post.mjs +++ b/scripts/perf-result-post.mjs @@ -32,7 +32,10 @@ async function main() { let benchmarkText = ""; if (includeArtifact === "--include-artifact") { // post a link to the benchmark file - const cli = new ado.WebApi("https://typescript.visualstudio.com/defaultcollection", ado.getHandlerFromToken("")); // Empty token, anon auth + const cli = new ado.WebApi( + "https://typescript.visualstudio.com/defaultcollection", + ado.getHandlerFromToken(""), + ); // Empty token, anon auth const build = await cli.getBuildApi(); const artifact = await build.getArtifact("typescript", +buildId, "benchmark"); assert(artifact.resource?.url); @@ -43,7 +46,8 @@ async function main() { if (/[\\/]linux\.benchmark$/.test(file.path)) { const benchmarkUrl = new URL(artifact.resource.url); benchmarkUrl.search = `artifactName=benchmark&fileId=${file.blob.id}&fileName=linux.benchmark`; - benchmarkText = `\n
Developer Information:

Download Benchmark

\n`; + benchmarkText = + `\n
Developer Information:

Download Benchmark

\n`; break; } } @@ -53,7 +57,8 @@ async function main() { issue_number: +source, owner: "Microsoft", repo: "TypeScript", - body: `@${requester}\nThe results of the perf run you requested are in!\n
Here they are:

\n${outputTableText}\n

${benchmarkText}
`, + body: + `@${requester}\nThe results of the perf run you requested are in!\n
Here they are:

\n${outputTableText}\n

${benchmarkText}
`, }); console.log(`Results posted!`); @@ -77,7 +82,8 @@ async function main() { issue_number: +source, owner: "Microsoft", repo: "TypeScript", - body: `Hey @${requester}, something went wrong when publishing results. ([You can check the log here](https://typescript.visualstudio.com/TypeScript/_build/index?buildId=${buildId}&_a=summary)).`, + body: + `Hey @${requester}, something went wrong when publishing results. ([You can check the log here](https://typescript.visualstudio.com/TypeScript/_build/index?buildId=${buildId}&_a=summary)).`, }); } } diff --git a/scripts/post-vsts-artifact-comment.mjs b/scripts/post-vsts-artifact-comment.mjs index c5015ac9bcb0f..8b16a90a4ae1b 100644 --- a/scripts/post-vsts-artifact-comment.mjs +++ b/scripts/post-vsts-artifact-comment.mjs @@ -35,7 +35,8 @@ async function main() { issue_number: +process.env.SOURCE_ISSUE, owner: "Microsoft", repo: "TypeScript", - body: `Hey @${process.env.REQUESTING_USER}, I've packed this into [an installable tgz](${link}). You can install it for testing by referencing it in your \`package.json\` like so: + body: + `Hey @${process.env.REQUESTING_USER}, I've packed this into [an installable tgz](${link}). You can install it for testing by referencing it in your \`package.json\` like so: \`\`\` { "devDependencies": { @@ -49,7 +50,10 @@ and then running \`npm install\`. // Temporarily disable until we get access controls set up right // Send a ping to https://github.com/microsoft/typescript-make-monaco-builds#pull-request-builds - await gh.request("POST /repos/microsoft/typescript-make-monaco-builds/dispatches", { event_type: process.env.SOURCE_ISSUE, headers: { Accept: "application/vnd.github.everest-preview+json" } }); + await gh.request("POST /repos/microsoft/typescript-make-monaco-builds/dispatches", { + event_type: process.env.SOURCE_ISSUE, + headers: { Accept: "application/vnd.github.everest-preview+json" }, + }); } main().catch(async e => { @@ -63,7 +67,8 @@ main().catch(async e => { issue_number: +process.env.SOURCE_ISSUE, owner: "Microsoft", repo: "TypeScript", - body: `Hey @${process.env.REQUESTING_USER}, something went wrong when looking for the build artifact. ([You can check the log here](https://typescript.visualstudio.com/TypeScript/_build/index?buildId=${process.env.BUILD_BUILDID}&_a=summary)).`, + body: + `Hey @${process.env.REQUESTING_USER}, something went wrong when looking for the build artifact. ([You can check the log here](https://typescript.visualstudio.com/TypeScript/_build/index?buildId=${process.env.BUILD_BUILDID}&_a=summary)).`, }); } }); diff --git a/scripts/processDiagnosticMessages.mjs b/scripts/processDiagnosticMessages.mjs index 069bd95aa4308..986be171e248f 100644 --- a/scripts/processDiagnosticMessages.mjs +++ b/scripts/processDiagnosticMessages.mjs @@ -95,14 +95,27 @@ function buildInfoFileOutput(messageTable, inputFilePathRel) { "/** @internal */", "export const Diagnostics = {", ]; - messageTable.forEach(({ code, category, reportsUnnecessary, elidedInCompatabilityPyramid, reportsDeprecated }, name) => { - const propName = convertPropertyName(name); - const argReportsUnnecessary = reportsUnnecessary ? `, /*reportsUnnecessary*/ ${reportsUnnecessary}` : ""; - const argElidedInCompatabilityPyramid = elidedInCompatabilityPyramid ? `${!reportsUnnecessary ? ", /*reportsUnnecessary*/ undefined" : ""}, /*elidedInCompatabilityPyramid*/ ${elidedInCompatabilityPyramid}` : ""; - const argReportsDeprecated = reportsDeprecated ? `${!argElidedInCompatabilityPyramid ? ", /*reportsUnnecessary*/ undefined, /*elidedInCompatabilityPyramid*/ undefined" : ""}, /*reportsDeprecated*/ ${reportsDeprecated}` : ""; - - result.push(` ${propName}: diag(${code}, DiagnosticCategory.${category}, "${createKey(propName, code)}", ${JSON.stringify(name)}${argReportsUnnecessary}${argElidedInCompatabilityPyramid}${argReportsDeprecated}),`); - }); + messageTable.forEach( + ({ code, category, reportsUnnecessary, elidedInCompatabilityPyramid, reportsDeprecated }, name) => { + const propName = convertPropertyName(name); + const argReportsUnnecessary = reportsUnnecessary ? `, /*reportsUnnecessary*/ ${reportsUnnecessary}` : ""; + const argElidedInCompatabilityPyramid = elidedInCompatabilityPyramid + ? `${ + !reportsUnnecessary ? ", /*reportsUnnecessary*/ undefined" : "" + }, /*elidedInCompatabilityPyramid*/ ${elidedInCompatabilityPyramid}` : ""; + const argReportsDeprecated = reportsDeprecated + ? `${ + !argElidedInCompatabilityPyramid + ? ", /*reportsUnnecessary*/ undefined, /*elidedInCompatabilityPyramid*/ undefined" : "" + }, /*reportsDeprecated*/ ${reportsDeprecated}` : ""; + + result.push( + ` ${propName}: diag(${code}, DiagnosticCategory.${category}, "${createKey(propName, code)}", ${ + JSON.stringify(name) + }${argReportsUnnecessary}${argElidedInCompatabilityPyramid}${argReportsDeprecated}),`, + ); + }, + ); result.push("};"); diff --git a/scripts/regenerate-unicode-identifier-parts.mjs b/scripts/regenerate-unicode-identifier-parts.mjs index e993a40e7a8d9..a21b0bf848eea 100644 --- a/scripts/regenerate-unicode-identifier-parts.mjs +++ b/scripts/regenerate-unicode-identifier-parts.mjs @@ -2,7 +2,9 @@ const MAX_UNICODE_CODEPOINT = 0x10FFFF; /** @type {(c: string) => boolean} */ const isStart = c => /[\p{ID_Start}\u{2118}\u{212E}\u{309B}\u{309C}]/u.test(c); // Other_ID_Start explicitly included for back compat - see http://www.unicode.org/reports/tr31/#Introduction /** @type {(c: string) => boolean} */ -const isPart = c => /[\p{ID_Continue}\u{00B7}\u{0387}\u{19DA}\u{1369}\u{136A}\u{136B}\u{136C}\u{136D}\u{136E}\u{136F}\u{1370}\u{1371}]/u.test(c) || isStart(c); // Likewise for Other_ID_Continue +const isPart = c => + /[\p{ID_Continue}\u{00B7}\u{0387}\u{19DA}\u{1369}\u{136A}\u{136B}\u{136C}\u{136D}\u{136E}\u{136F}\u{1370}\u{1371}]/u + .test(c) || isStart(c); // Likewise for Other_ID_Continue const parts = []; let partsActive = false; let startsActive = false; diff --git a/scripts/run-sequence.mjs b/scripts/run-sequence.mjs index 910c9e5e5182d..96ccb1e220cb1 100644 --- a/scripts/run-sequence.mjs +++ b/scripts/run-sequence.mjs @@ -11,7 +11,13 @@ export function runSequence(tasks, opts = { timeout: 100000, shell: true }) { for (const task of tasks) { console.log(`${task[0]} ${task[1].join(" ")}`); const result = cp.spawnSync(task[0], task[1], opts); - if (result.status !== 0) throw new Error(`${task[0]} ${task[1].join(" ")} failed: ${result.stderr && "stderr: " + result.stderr.toString()}${result.stdout && "\nstdout: " + result.stdout.toString()}`); + if (result.status !== 0) { + throw new Error( + `${task[0]} ${task[1].join(" ")} failed: ${result.stderr && "stderr: " + result.stderr.toString()}${ + result.stdout && "\nstdout: " + result.stdout.toString() + }`, + ); + } console.log(result.stdout && result.stdout.toString()); lastResult = result; } diff --git a/scripts/update-experimental-branches.mjs b/scripts/update-experimental-branches.mjs index 0b1fa533966fc..5f2205f7a3c77 100644 --- a/scripts/update-experimental-branches.mjs +++ b/scripts/update-experimental-branches.mjs @@ -54,7 +54,8 @@ async function main() { owner: "Microsoft", repo: "TypeScript", issue_number: num, - body: `This PR is configured as an experiment, and currently has rebase conflicts with main - please rebase onto main and fix the conflicts.`, + body: + `This PR is configured as an experiment, and currently has rebase conflicts with main - please rebase onto main and fix the conflicts.`, }); } throw new Error(`Rebase conflict detected in PR ${num} with main`); // A PR is currently in conflict, give up diff --git a/src/cancellationToken/cancellationToken.ts b/src/cancellationToken/cancellationToken.ts index 8ea543e01d473..ff087607e1ef2 100644 --- a/src/cancellationToken/cancellationToken.ts +++ b/src/cancellationToken/cancellationToken.ts @@ -40,7 +40,9 @@ function createCancellationToken(args: string[]): ServerCancellationToken { if (cancellationPipeName.charAt(cancellationPipeName.length - 1) === "*") { const namePrefix = cancellationPipeName.slice(0, -1); if (namePrefix.length === 0 || namePrefix.indexOf("*") >= 0) { - throw new Error("Invalid name for template cancellation pipe: it should have length greater than 2 characters and contain only one '*'."); + throw new Error( + "Invalid name for template cancellation pipe: it should have length greater than 2 characters and contain only one '*'.", + ); } let perRequestPipeName: string | undefined; let currentRequestId: number; diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 19566c05b4f2b..b1fa3c68b7e51 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -333,7 +333,10 @@ interface ActiveLabel { } /** @internal */ -export function getModuleInstanceState(node: ModuleDeclaration, visited?: Map): ModuleInstanceState { +export function getModuleInstanceState( + node: ModuleDeclaration, + visited?: Map, +): ModuleInstanceState { if (node.body && !node.body.parent) { // getModuleInstanceStateForAliasTarget needs to walk up the parent chain, so parent pointers must be set on this tree already setParent(node.body, node); @@ -353,7 +356,10 @@ function getModuleInstanceStateCached(node: Node, visited = new Map): ModuleInstanceState { +function getModuleInstanceStateWorker( + node: Node, + visited: Map, +): ModuleInstanceState { // A module is uninstantiated if it contains only switch (node.kind) { // 1. interface declarations, type alias declarations @@ -376,7 +382,10 @@ function getModuleInstanceStateWorker(node: Node, visited: Map) { +function getModuleInstanceStateForAliasTarget( + specifier: ExportSpecifier, + visited: Map, +) { const name = specifier.propertyName || specifier.name; let p: Node | undefined = specifier.parent; while (p) { @@ -566,7 +578,11 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { * If so, the node _must_ be in the current file (as that's the only way anything could have traversed to it to yield it as the error node) * This version of `createDiagnosticForNode` uses the binder's context to account for this, and always yields correct diagnostics even in these situations. */ - function createDiagnosticForNode(node: Node, message: DiagnosticMessage, ...args: DiagnosticArguments): DiagnosticWithLocation { + function createDiagnosticForNode( + node: Node, + message: DiagnosticMessage, + ...args: DiagnosticArguments + ): DiagnosticWithLocation { return createDiagnosticForNodeInSourceFile(getSourceFileOfNode(node) || file, node, message, ...args); } @@ -637,16 +653,26 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { node.symbol = symbol; symbol.declarations = appendIfUnique(symbol.declarations, node); - if (symbolFlags & (SymbolFlags.Class | SymbolFlags.Enum | SymbolFlags.Module | SymbolFlags.Variable) && !symbol.exports) { + if ( + symbolFlags & (SymbolFlags.Class | SymbolFlags.Enum | SymbolFlags.Module | SymbolFlags.Variable) + && !symbol.exports + ) { symbol.exports = createSymbolTable(); } - if (symbolFlags & (SymbolFlags.Class | SymbolFlags.Interface | SymbolFlags.TypeLiteral | SymbolFlags.ObjectLiteral) && !symbol.members) { + if ( + symbolFlags + & (SymbolFlags.Class | SymbolFlags.Interface | SymbolFlags.TypeLiteral | SymbolFlags.ObjectLiteral) + && !symbol.members + ) { symbol.members = createSymbolTable(); } // On merge of const enum module with class or function, reset const enum only flag (namespaces will already recalculate) - if (symbol.constEnumOnlyModule && (symbol.flags & (SymbolFlags.Function | SymbolFlags.Class | SymbolFlags.RegularEnum))) { + if ( + symbol.constEnumOnlyModule + && (symbol.flags & (SymbolFlags.Function | SymbolFlags.Class | SymbolFlags.RegularEnum)) + ) { symbol.constEnumOnlyModule = false; } @@ -659,14 +685,16 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { // unless it is a well known Symbol. function getDeclarationName(node: Declaration): __String | undefined { if (node.kind === SyntaxKind.ExportAssignment) { - return (node as ExportAssignment).isExportEquals ? InternalSymbolName.ExportEquals : InternalSymbolName.Default; + return (node as ExportAssignment).isExportEquals ? InternalSymbolName.ExportEquals + : InternalSymbolName.Default; } const name = getNameOfDeclaration(node); if (name) { if (isAmbientModule(node)) { const moduleName = getTextOfIdentifierOrLiteral(name as Identifier | StringLiteral); - return (isGlobalScopeAugmentation(node as ModuleDeclaration) ? "__global" : `"${moduleName}"`) as __String; + return (isGlobalScopeAugmentation(node as ModuleDeclaration) ? "__global" + : `"${moduleName}"`) as __String; } if (name.kind === SyntaxKind.ComputedPropertyName) { const nameExpression = name.expression; @@ -715,7 +743,9 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { // module.exports = ... return InternalSymbolName.ExportEquals; case SyntaxKind.BinaryExpression: - if (getAssignmentDeclarationKind(node as BinaryExpression) === AssignmentDeclarationKind.ModuleExports) { + if ( + getAssignmentDeclarationKind(node as BinaryExpression) === AssignmentDeclarationKind.ModuleExports + ) { // module.exports = ... return InternalSymbolName.ExportEquals; } @@ -726,7 +756,11 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { case SyntaxKind.Parameter: // Parameters with names are handled at the top of this function. Parameters // without names can only come from JSDocFunctionTypes. - Debug.assert(node.parent.kind === SyntaxKind.JSDocFunctionType, "Impossible parameter parent kind", () => `parent is: ${Debug.formatSyntaxKind(node.parent.kind)}, expected JSDocFunctionType`); + Debug.assert( + node.parent.kind === SyntaxKind.JSDocFunctionType, + "Impossible parameter parent kind", + () => `parent is: ${Debug.formatSyntaxKind(node.parent.kind)}, expected JSDocFunctionType`, + ); const functionType = node.parent as JSDocFunctionType; const index = functionType.parameters.indexOf(node as ParameterDeclaration); return "arg" + index as __String; @@ -734,7 +768,8 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { } function getDisplayName(node: Declaration): string { - return isNamedDeclaration(node) ? declarationNameToString(node.name) : unescapeLeadingUnderscores(Debug.checkDefined(getDeclarationName(node))); + return isNamedDeclaration(node) ? declarationNameToString(node.name) + : unescapeLeadingUnderscores(Debug.checkDefined(getDeclarationName(node))); } /** @@ -745,10 +780,19 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { * @param includes - The SymbolFlags that node has in addition to its declaration type (eg: export, ambient, etc.) * @param excludes - The flags which node cannot be declared alongside in a symbol table. Used to report forbidden declarations. */ - function declareSymbol(symbolTable: SymbolTable, parent: Symbol | undefined, node: Declaration, includes: SymbolFlags, excludes: SymbolFlags, isReplaceableByMethod?: boolean, isComputedName?: boolean): Symbol { + function declareSymbol( + symbolTable: SymbolTable, + parent: Symbol | undefined, + node: Declaration, + includes: SymbolFlags, + excludes: SymbolFlags, + isReplaceableByMethod?: boolean, + isComputedName?: boolean, + ): Symbol { Debug.assert(isComputedName || !hasDynamicName(node)); - const isDefaultExport = hasSyntacticModifier(node, ModifierFlags.Default) || isExportSpecifier(node) && node.name.escapedText === "default"; + const isDefaultExport = hasSyntacticModifier(node, ModifierFlags.Default) + || isExportSpecifier(node) && node.name.escapedText === "default"; // The exported symbol for an export default function/class node is always named "default" const name = isComputedName ? InternalSymbolName.Computed @@ -816,7 +860,8 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { let messageNeedsName = true; if (symbol.flags & SymbolFlags.Enum || includes & SymbolFlags.Enum) { - message = Diagnostics.Enum_declarations_can_only_merge_with_namespace_or_other_enum_declarations; + message = + Diagnostics.Enum_declarations_can_only_merge_with_namespace_or_other_enum_declarations; messageNeedsName = false; } @@ -836,8 +881,9 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { // 1. multiple export default of class declaration or function declaration by checking NodeFlags.Default // 2. multiple export default of export assignment. This one doesn't have NodeFlags.Default on (as export default doesn't considered as modifiers) if ( - symbol.declarations && symbol.declarations.length && - (node.kind === SyntaxKind.ExportAssignment && !(node as ExportAssignment).isExportEquals) + symbol.declarations && symbol.declarations.length + && (node.kind === SyntaxKind.ExportAssignment + && !(node as ExportAssignment).isExportEquals) ) { message = Diagnostics.A_module_cannot_have_multiple_default_exports; messageNeedsName = false; @@ -847,24 +893,47 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { } const relatedInformation: DiagnosticRelatedInformation[] = []; - if (isTypeAliasDeclaration(node) && nodeIsMissing(node.type) && hasSyntacticModifier(node, ModifierFlags.Export) && symbol.flags & (SymbolFlags.Alias | SymbolFlags.Type | SymbolFlags.Namespace)) { + if ( + isTypeAliasDeclaration(node) && nodeIsMissing(node.type) + && hasSyntacticModifier(node, ModifierFlags.Export) + && symbol.flags & (SymbolFlags.Alias | SymbolFlags.Type | SymbolFlags.Namespace) + ) { // export type T; - may have meant export type { T }? - relatedInformation.push(createDiagnosticForNode(node, Diagnostics.Did_you_mean_0, `export type { ${unescapeLeadingUnderscores(node.name.escapedText)} }`)); + relatedInformation.push( + createDiagnosticForNode( + node, + Diagnostics.Did_you_mean_0, + `export type { ${unescapeLeadingUnderscores(node.name.escapedText)} }`, + ), + ); } const declarationName = getNameOfDeclaration(node) || node; forEach(symbol.declarations, (declaration, index) => { const decl = getNameOfDeclaration(declaration) || declaration; - const diag = messageNeedsName ? createDiagnosticForNode(decl, message, getDisplayName(declaration)) : createDiagnosticForNode(decl, message); + const diag = messageNeedsName + ? createDiagnosticForNode(decl, message, getDisplayName(declaration)) + : createDiagnosticForNode(decl, message); file.bindDiagnostics.push( - multipleDefaultExports ? addRelatedInfo(diag, createDiagnosticForNode(declarationName, index === 0 ? Diagnostics.Another_export_default_is_here : Diagnostics.and_here)) : diag, + multipleDefaultExports + ? addRelatedInfo( + diag, + createDiagnosticForNode( + declarationName, + index === 0 ? Diagnostics.Another_export_default_is_here : Diagnostics.and_here, + ), + ) : diag, ); if (multipleDefaultExports) { - relatedInformation.push(createDiagnosticForNode(decl, Diagnostics.The_first_export_default_is_here)); + relatedInformation.push( + createDiagnosticForNode(decl, Diagnostics.The_first_export_default_is_here), + ); } }); - const diag = messageNeedsName ? createDiagnosticForNode(declarationName, message, getDisplayName(node)) : createDiagnosticForNode(declarationName, message); + const diag = messageNeedsName + ? createDiagnosticForNode(declarationName, message, getDisplayName(node)) + : createDiagnosticForNode(declarationName, message); file.bindDiagnostics.push(addRelatedInfo(diag, ...relatedInformation)); symbol = createSymbol(SymbolFlags.None, name); @@ -884,9 +953,13 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { } function declareModuleMember(node: Declaration, symbolFlags: SymbolFlags, symbolExcludes: SymbolFlags): Symbol { - const hasExportModifier = !!(getCombinedModifierFlags(node) & ModifierFlags.Export) || jsdocTreatAsExported(node); + const hasExportModifier = !!(getCombinedModifierFlags(node) & ModifierFlags.Export) + || jsdocTreatAsExported(node); if (symbolFlags & SymbolFlags.Alias) { - if (node.kind === SyntaxKind.ExportSpecifier || (node.kind === SyntaxKind.ImportEqualsDeclaration && hasExportModifier)) { + if ( + node.kind === SyntaxKind.ExportSpecifier + || (node.kind === SyntaxKind.ImportEqualsDeclaration && hasExportModifier) + ) { return declareSymbol(container.symbol.exports!, container.symbol, node, symbolFlags, symbolExcludes); } else { @@ -912,12 +985,27 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { // and should never be merged directly with other augmentation, and the latter case would be possible if automatic merge is allowed. if (isJSDocTypeAlias(node)) Debug.assert(isInJSFile(node)); // We shouldn't add symbols for JSDoc nodes if not in a JS file. if (!isAmbientModule(node) && (hasExportModifier || container.flags & NodeFlags.ExportContext)) { - if (!canHaveLocals(container) || !container.locals || (hasSyntacticModifier(node, ModifierFlags.Default) && !getDeclarationName(node))) { - return declareSymbol(container.symbol.exports!, container.symbol, node, symbolFlags, symbolExcludes); // No local symbol for an unnamed default! + if ( + !canHaveLocals(container) || !container.locals + || (hasSyntacticModifier(node, ModifierFlags.Default) && !getDeclarationName(node)) + ) { + return declareSymbol( + container.symbol.exports!, + container.symbol, + node, + symbolFlags, + symbolExcludes, + ); // No local symbol for an unnamed default! } const exportKind = symbolFlags & SymbolFlags.Value ? SymbolFlags.ExportValue : 0; const local = declareSymbol(container.locals, /*parent*/ undefined, node, exportKind, symbolExcludes); - local.exportSymbol = declareSymbol(container.symbol.exports!, container.symbol, node, symbolFlags, symbolExcludes); + local.exportSymbol = declareSymbol( + container.symbol.exports!, + container.symbol, + node, + symbolFlags, + symbolExcludes, + ); node.localSymbol = local; return local; } @@ -939,8 +1027,12 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { // 2. The thing a nameless typedef pulls its name from is implicitly a direct export (either by assignment or actual export flag). const declName = getNameOfDeclaration(node); if (!declName) return false; - if (isPropertyAccessEntityNameExpression(declName.parent) && isTopLevelNamespaceAssignment(declName.parent)) return true; - if (isDeclaration(declName.parent) && getCombinedModifierFlags(declName.parent) & ModifierFlags.Export) return true; + if (isPropertyAccessEntityNameExpression(declName.parent) && isTopLevelNamespaceAssignment(declName.parent)) { + return true; + } + if (isDeclaration(declName.parent) && getCombinedModifierFlags(declName.parent) & ModifierFlags.Export) { + return true; + } // This could potentially be simplified by having `delayedBindJSDocTypedefTag` pass in an override for `hasExportModifier`, since it should // already have calculated and branched on most of this. return false; @@ -998,22 +1090,34 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { const saveExceptionTarget = currentExceptionTarget; const saveActiveLabelList = activeLabelList; const saveHasExplicitReturn = hasExplicitReturn; - const isImmediatelyInvoked = (containerFlags & ContainerFlags.IsFunctionExpression && - !hasSyntacticModifier(node, ModifierFlags.Async) && - !(node as FunctionLikeDeclaration).asteriskToken && - !!getImmediatelyInvokedFunctionExpression(node)) || - node.kind === SyntaxKind.ClassStaticBlockDeclaration; + const isImmediatelyInvoked = (containerFlags & ContainerFlags.IsFunctionExpression + && !hasSyntacticModifier(node, ModifierFlags.Async) + && !(node as FunctionLikeDeclaration).asteriskToken + && !!getImmediatelyInvokedFunctionExpression(node)) + || node.kind === SyntaxKind.ClassStaticBlockDeclaration; // A non-async, non-generator IIFE is considered part of the containing control flow. Return statements behave // similarly to break statements that exit to a label just past the statement body. if (!isImmediatelyInvoked) { currentFlow = initFlowNode({ flags: FlowFlags.Start }); - if (containerFlags & (ContainerFlags.IsFunctionExpression | ContainerFlags.IsObjectLiteralOrClassExpressionMethodOrAccessor)) { - currentFlow.node = node as FunctionExpression | ArrowFunction | MethodDeclaration | GetAccessorDeclaration | SetAccessorDeclaration; + if ( + containerFlags + & (ContainerFlags.IsFunctionExpression + | ContainerFlags.IsObjectLiteralOrClassExpressionMethodOrAccessor) + ) { + currentFlow.node = node as + | FunctionExpression + | ArrowFunction + | MethodDeclaration + | GetAccessorDeclaration + | SetAccessorDeclaration; } } // We create a return control flow graph for IIFEs and constructors. For constructors // we use the return control flow graph in strict property initialization checks. - currentReturnTarget = isImmediatelyInvoked || node.kind === SyntaxKind.Constructor || (isInJSFile(node) && (node.kind === SyntaxKind.FunctionDeclaration || node.kind === SyntaxKind.FunctionExpression)) ? createBranchLabel() : undefined; + currentReturnTarget = isImmediatelyInvoked || node.kind === SyntaxKind.Constructor + || (isInJSFile(node) + && (node.kind === SyntaxKind.FunctionDeclaration + || node.kind === SyntaxKind.FunctionExpression)) ? createBranchLabel() : undefined; currentExceptionTarget = undefined; currentBreakTarget = undefined; currentContinueTarget = undefined; @@ -1022,7 +1126,10 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { bindChildren(node); // Reset all reachability check related flags on node (for incremental scenarios) node.flags &= ~NodeFlags.ReachabilityAndEmitFlags; - if (!(currentFlow.flags & FlowFlags.Unreachable) && containerFlags & ContainerFlags.IsFunctionLike && nodeIsPresent((node as FunctionLikeDeclaration | ClassStaticBlockDeclaration).body)) { + if ( + !(currentFlow.flags & FlowFlags.Unreachable) && containerFlags & ContainerFlags.IsFunctionLike + && nodeIsPresent((node as FunctionLikeDeclaration | ClassStaticBlockDeclaration).body) + ) { node.flags |= NodeFlags.HasImplicitReturn; if (hasExplicitReturn) node.flags |= NodeFlags.HasExplicitReturn; (node as FunctionLikeDeclaration | ClassStaticBlockDeclaration).endFlowNode = currentFlow; @@ -1035,7 +1142,12 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { if (currentReturnTarget) { addAntecedent(currentReturnTarget, currentFlow); currentFlow = finishFlowLabel(currentReturnTarget); - if (node.kind === SyntaxKind.Constructor || node.kind === SyntaxKind.ClassStaticBlockDeclaration || (isInJSFile(node) && (node.kind === SyntaxKind.FunctionDeclaration || node.kind === SyntaxKind.FunctionExpression))) { + if ( + node.kind === SyntaxKind.Constructor || node.kind === SyntaxKind.ClassStaticBlockDeclaration + || (isInJSFile(node) + && (node.kind === SyntaxKind.FunctionDeclaration + || node.kind === SyntaxKind.FunctionExpression)) + ) { (node as FunctionLikeDeclaration | ClassStaticBlockDeclaration).returnFlowNode = currentFlow; } } @@ -1092,7 +1204,10 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { inAssignmentPattern = saveInAssignmentPattern; return; } - if (node.kind >= SyntaxKind.FirstStatement && node.kind <= SyntaxKind.LastStatement && !options.allowUnreachableCode) { + if ( + node.kind >= SyntaxKind.FirstStatement && node.kind <= SyntaxKind.LastStatement + && !options.allowUnreachableCode + ) { (node as HasFlowNode).flowNode = currentFlow; } switch (node.kind) { @@ -1226,7 +1341,8 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { case SyntaxKind.BinaryExpression: return isNarrowingBinaryExpression(expr as BinaryExpression); case SyntaxKind.PrefixUnaryExpression: - return (expr as PrefixUnaryExpression).operator === SyntaxKind.ExclamationToken && isNarrowingExpression((expr as PrefixUnaryExpression).operand); + return (expr as PrefixUnaryExpression).operator === SyntaxKind.ExclamationToken + && isNarrowingExpression((expr as PrefixUnaryExpression).operand); case SyntaxKind.TypeOfExpression: return isNarrowingExpression((expr as TypeOfExpression).expression); } @@ -1235,9 +1351,14 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { function isNarrowableReference(expr: Expression): boolean { return isDottedName(expr) - || (isPropertyAccessExpression(expr) || isNonNullExpression(expr) || isParenthesizedExpression(expr)) && isNarrowableReference(expr.expression) - || isBinaryExpression(expr) && expr.operatorToken.kind === SyntaxKind.CommaToken && isNarrowableReference(expr.right) - || isElementAccessExpression(expr) && (isStringOrNumericLiteralLike(expr.argumentExpression) || isEntityNameExpression(expr.argumentExpression)) && isNarrowableReference(expr.expression) + || (isPropertyAccessExpression(expr) || isNonNullExpression(expr) || isParenthesizedExpression(expr)) + && isNarrowableReference(expr.expression) + || isBinaryExpression(expr) && expr.operatorToken.kind === SyntaxKind.CommaToken + && isNarrowableReference(expr.right) + || isElementAccessExpression(expr) + && (isStringOrNumericLiteralLike(expr.argumentExpression) + || isEntityNameExpression(expr.argumentExpression)) + && isNarrowableReference(expr.expression) || isAssignmentExpression(expr) && isNarrowableReference(expr.left); } @@ -1254,8 +1375,8 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { } } if ( - expr.expression.kind === SyntaxKind.PropertyAccessExpression && - containsNarrowableReference((expr.expression as PropertyAccessExpression).expression) + expr.expression.kind === SyntaxKind.PropertyAccessExpression + && containsNarrowableReference((expr.expression as PropertyAccessExpression).expression) ) { return true; } @@ -1277,8 +1398,9 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { case SyntaxKind.ExclamationEqualsToken: case SyntaxKind.EqualsEqualsEqualsToken: case SyntaxKind.ExclamationEqualsEqualsToken: - return isNarrowableOperand(expr.left) || isNarrowableOperand(expr.right) || - isNarrowingTypeofOperands(expr.right, expr.left) || isNarrowingTypeofOperands(expr.left, expr.right); + return isNarrowableOperand(expr.left) || isNarrowableOperand(expr.right) + || isNarrowingTypeofOperands(expr.right, expr.left) + || isNarrowingTypeofOperands(expr.left, expr.right); case SyntaxKind.InstanceOfKeyword: return isNarrowableOperand(expr.left); case SyntaxKind.InKeyword: @@ -1336,9 +1458,9 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { return flags & FlowFlags.TrueCondition ? antecedent : unreachableFlow; } if ( - (expression.kind === SyntaxKind.TrueKeyword && flags & FlowFlags.FalseCondition || - expression.kind === SyntaxKind.FalseKeyword && flags & FlowFlags.TrueCondition) && - !isExpressionOfOptionalChainRoot(expression) && !isNullishCoalesce(expression.parent) + (expression.kind === SyntaxKind.TrueKeyword && flags & FlowFlags.FalseCondition + || expression.kind === SyntaxKind.FalseKeyword && flags & FlowFlags.TrueCondition) + && !isExpressionOfOptionalChainRoot(expression) && !isNullishCoalesce(expression.parent) ) { return unreachableFlow; } @@ -1349,12 +1471,21 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { return initFlowNode({ flags, antecedent, node: expression }); } - function createFlowSwitchClause(antecedent: FlowNode, switchStatement: SwitchStatement, clauseStart: number, clauseEnd: number): FlowNode { + function createFlowSwitchClause( + antecedent: FlowNode, + switchStatement: SwitchStatement, + clauseStart: number, + clauseEnd: number, + ): FlowNode { setFlowNodeReferenced(antecedent); return initFlowNode({ flags: FlowFlags.SwitchClause, antecedent, switchStatement, clauseStart, clauseEnd }); } - function createFlowMutation(flags: FlowFlags, antecedent: FlowNode, node: Expression | VariableDeclaration | ArrayBindingElement): FlowNode { + function createFlowMutation( + flags: FlowFlags, + antecedent: FlowNode, + node: Expression | VariableDeclaration | ArrayBindingElement, + ): FlowNode { setFlowNodeReferenced(antecedent); const result = initFlowNode({ flags, antecedent, node }); if (currentExceptionTarget) { @@ -1398,7 +1529,10 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { if (node.kind === SyntaxKind.ParenthesizedExpression) { node = (node as ParenthesizedExpression).expression; } - else if (node.kind === SyntaxKind.PrefixUnaryExpression && (node as PrefixUnaryExpression).operator === SyntaxKind.ExclamationToken) { + else if ( + node.kind === SyntaxKind.PrefixUnaryExpression + && (node as PrefixUnaryExpression).operator === SyntaxKind.ExclamationToken + ) { node = (node as PrefixUnaryExpression).operand; } else { @@ -1413,17 +1547,22 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { function isTopLevelLogicalExpression(node: Node): boolean { while ( - isParenthesizedExpression(node.parent) || - isPrefixUnaryExpression(node.parent) && node.parent.operator === SyntaxKind.ExclamationToken + isParenthesizedExpression(node.parent) + || isPrefixUnaryExpression(node.parent) && node.parent.operator === SyntaxKind.ExclamationToken ) { node = node.parent; } - return !isStatementCondition(node) && - !isLogicalExpression(node.parent) && - !(isOptionalChain(node.parent) && node.parent.expression === node); + return !isStatementCondition(node) + && !isLogicalExpression(node.parent) + && !(isOptionalChain(node.parent) && node.parent.expression === node); } - function doWithConditionalBranches(action: (value: T) => void, value: T, trueTarget: FlowLabel, falseTarget: FlowLabel) { + function doWithConditionalBranches( + action: (value: T) => void, + value: T, + trueTarget: FlowLabel, + falseTarget: FlowLabel, + ) { const savedTrueTarget = currentTrueTarget; const savedFalseTarget = currentFalseTarget; currentTrueTarget = trueTarget; @@ -1435,7 +1574,11 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { function bindCondition(node: Expression | undefined, trueTarget: FlowLabel, falseTarget: FlowLabel) { doWithConditionalBranches(bind, node, trueTarget, falseTarget); - if (!node || !isLogicalAssignmentExpression(node) && !isLogicalExpression(node) && !(isOptionalChain(node) && isOutermostOptionalChain(node))) { + if ( + !node + || !isLogicalAssignmentExpression(node) && !isLogicalExpression(node) + && !(isOptionalChain(node) && isOutermostOptionalChain(node)) + ) { addAntecedent(trueTarget, createFlowCondition(FlowFlags.TrueCondition, currentFlow, node)); addAntecedent(falseTarget, createFlowCondition(FlowFlags.FalseCondition, currentFlow, node)); } @@ -1555,7 +1698,11 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { return undefined; } - function bindBreakOrContinueFlow(node: BreakOrContinueStatement, breakTarget: FlowLabel | undefined, continueTarget: FlowLabel | undefined) { + function bindBreakOrContinueFlow( + node: BreakOrContinueStatement, + breakTarget: FlowLabel | undefined, + continueTarget: FlowLabel | undefined, + ) { const flowLabel = node.kind === SyntaxKind.BreakStatement ? breakTarget : continueTarget; if (flowLabel) { addAntecedent(flowLabel, currentFlow); @@ -1626,7 +1773,10 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { // set of antecedents for the pre-finally label. As control flow analysis passes by a ReduceLabel // node, the pre-finally label is temporarily switched to the reduced antecedent set. const finallyLabel = createBranchLabel(); - finallyLabel.antecedents = concatenate(concatenate(normalExitLabel.antecedents, exceptionLabel.antecedents), returnLabel.antecedents); + finallyLabel.antecedents = concatenate( + concatenate(normalExitLabel.antecedents, exceptionLabel.antecedents), + returnLabel.antecedents, + ); currentFlow = finallyLabel; bind(node.finallyBlock); if (currentFlow.flags & FlowFlags.Unreachable) { @@ -1637,17 +1787,24 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { // If we have an IIFE return target and return statements in the try or catch blocks, add a control // flow that goes back through the finally block and back through only the return statements. if (currentReturnTarget && returnLabel.antecedents) { - addAntecedent(currentReturnTarget, createReduceLabel(finallyLabel, returnLabel.antecedents, currentFlow)); + addAntecedent( + currentReturnTarget, + createReduceLabel(finallyLabel, returnLabel.antecedents, currentFlow), + ); } // If we have an outer exception target (i.e. a containing try-finally or try-catch-finally), add a // control flow that goes back through the finally blok and back through each possible exception source. if (currentExceptionTarget && exceptionLabel.antecedents) { - addAntecedent(currentExceptionTarget, createReduceLabel(finallyLabel, exceptionLabel.antecedents, currentFlow)); + addAntecedent( + currentExceptionTarget, + createReduceLabel(finallyLabel, exceptionLabel.antecedents, currentFlow), + ); } // If the end of the finally block is reachable, but the end of the try and catch blocks are not, // convert the current flow to unreachable. For example, 'try { return 1; } finally { ... }' should // result in an unreachable current control flow. - currentFlow = normalExitLabel.antecedents ? createReduceLabel(finallyLabel, normalExitLabel.antecedents, currentFlow) : unreachableFlow; + currentFlow = normalExitLabel.antecedents + ? createReduceLabel(finallyLabel, normalExitLabel.antecedents, currentFlow) : unreachableFlow; } } else { @@ -1688,13 +1845,20 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { i++; } const preCaseLabel = createBranchLabel(); - addAntecedent(preCaseLabel, isNarrowingSwitch ? createFlowSwitchClause(preSwitchCaseFlow!, node.parent, clauseStart, i + 1) : preSwitchCaseFlow!); + addAntecedent( + preCaseLabel, + isNarrowingSwitch ? createFlowSwitchClause(preSwitchCaseFlow!, node.parent, clauseStart, i + 1) + : preSwitchCaseFlow!, + ); addAntecedent(preCaseLabel, fallthroughFlow); currentFlow = finishFlowLabel(preCaseLabel); const clause = clauses[i]; bind(clause); fallthroughFlow = currentFlow; - if (!(currentFlow.flags & FlowFlags.Unreachable) && i !== clauses.length - 1 && options.noFallthroughCasesInSwitch) { + if ( + !(currentFlow.flags & FlowFlags.Unreachable) && i !== clauses.length - 1 + && options.noFallthroughCasesInSwitch + ) { clause.fallthroughFlowNode = currentFlow; } } @@ -1744,7 +1908,10 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { } function bindDestructuringTargetFlow(node: Expression) { - if (node.kind === SyntaxKind.BinaryExpression && (node as BinaryExpression).operatorToken.kind === SyntaxKind.EqualsToken) { + if ( + node.kind === SyntaxKind.BinaryExpression + && (node as BinaryExpression).operatorToken.kind === SyntaxKind.EqualsToken + ) { bindAssignmentTargetFlow((node as BinaryExpression).left); } else { @@ -1783,7 +1950,10 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { function bindLogicalLikeExpression(node: BinaryExpression, trueTarget: FlowLabel, falseTarget: FlowLabel) { const preRightLabel = createBranchLabel(); - if (node.operatorToken.kind === SyntaxKind.AmpersandAmpersandToken || node.operatorToken.kind === SyntaxKind.AmpersandAmpersandEqualsToken) { + if ( + node.operatorToken.kind === SyntaxKind.AmpersandAmpersandToken + || node.operatorToken.kind === SyntaxKind.AmpersandAmpersandEqualsToken + ) { bindCondition(node.left, preRightLabel, falseTarget); } else { @@ -2156,7 +2326,10 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { } if (node.expression.kind === SyntaxKind.PropertyAccessExpression) { const propertyAccess = node.expression as PropertyAccessExpression; - if (isIdentifier(propertyAccess.name) && isNarrowableOperand(propertyAccess.expression) && isPushOrUnshiftIdentifier(propertyAccess.name)) { + if ( + isIdentifier(propertyAccess.name) && isNarrowableOperand(propertyAccess.expression) + && isPushOrUnshiftIdentifier(propertyAccess.name) + ) { currentFlow = createFlowMutation(FlowFlags.ArrayMutation, currentFlow, node); } } @@ -2170,7 +2343,11 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { lastContainer = next; } - function declareSymbolAndAddToSymbolTable(node: Declaration, symbolFlags: SymbolFlags, symbolExcludes: SymbolFlags): Symbol | undefined { + function declareSymbolAndAddToSymbolTable( + node: Declaration, + symbolFlags: SymbolFlags, + symbolExcludes: SymbolFlags, + ): Symbol | undefined { switch (container.kind) { // Modules, source files, and classes need specialized handling for how their // members are declared (for example, a member of a class will go into a specific @@ -2262,7 +2439,11 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { setExportContextFlag(node); if (isAmbientModule(node)) { if (hasSyntacticModifier(node, ModifierFlags.Export)) { - errorOnFirstToken(node, Diagnostics.export_modifier_cannot_be_applied_to_ambient_modules_and_module_augmentations_since_they_are_always_visible); + errorOnFirstToken( + node, + Diagnostics + .export_modifier_cannot_be_applied_to_ambient_modules_and_module_augmentations_since_they_are_always_visible, + ); } if (isModuleAugmentationExternal(node)) { declareModuleSymbol(node); @@ -2273,12 +2454,23 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { const { text } = node.name; pattern = tryParsePattern(text); if (pattern === undefined) { - errorOnFirstToken(node.name, Diagnostics.Pattern_0_can_have_at_most_one_Asterisk_character, text); + errorOnFirstToken( + node.name, + Diagnostics.Pattern_0_can_have_at_most_one_Asterisk_character, + text, + ); } } - const symbol = declareSymbolAndAddToSymbolTable(node, SymbolFlags.ValueModule, SymbolFlags.ValueModuleExcludes)!; - file.patternAmbientModules = append(file.patternAmbientModules, pattern && !isString(pattern) ? { pattern, symbol } : undefined); + const symbol = declareSymbolAndAddToSymbolTable( + node, + SymbolFlags.ValueModule, + SymbolFlags.ValueModuleExcludes, + )!; + file.patternAmbientModules = append( + file.patternAmbientModules, + pattern && !isString(pattern) ? { pattern, symbol } : undefined, + ); } } else { @@ -2286,7 +2478,8 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { if (state !== ModuleInstanceState.NonInstantiated) { const { symbol } = node; // if module was already merged with some function, class or non-const enum, treat it as non-const-enum-only - symbol.constEnumOnlyModule = (!(symbol.flags & (SymbolFlags.Function | SymbolFlags.Class | SymbolFlags.RegularEnum))) + symbol.constEnumOnlyModule = + (!(symbol.flags & (SymbolFlags.Function | SymbolFlags.Class | SymbolFlags.RegularEnum))) // Current must be `const enum` only && state === ModuleInstanceState.ConstEnumOnly // Can't have been set to 'false' in a previous merged symbol. ('undefined' OK) @@ -2298,7 +2491,11 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { function declareModuleSymbol(node: ModuleDeclaration): ModuleInstanceState { const state = getModuleInstanceState(node); const instantiated = state !== ModuleInstanceState.NonInstantiated; - declareSymbolAndAddToSymbolTable(node, instantiated ? SymbolFlags.ValueModule : SymbolFlags.NamespaceModule, instantiated ? SymbolFlags.ValueModuleExcludes : SymbolFlags.NamespaceModuleExcludes); + declareSymbolAndAddToSymbolTable( + node, + instantiated ? SymbolFlags.ValueModule : SymbolFlags.NamespaceModule, + instantiated ? SymbolFlags.ValueModuleExcludes : SymbolFlags.NamespaceModuleExcludes, + ); return state; } @@ -2377,11 +2574,23 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { parent = typeAlias; bind(typeAlias.typeExpression); const declName = getNameOfDeclaration(typeAlias); - if ((isJSDocEnumTag(typeAlias) || !typeAlias.fullName) && declName && isPropertyAccessEntityNameExpression(declName.parent)) { + if ( + (isJSDocEnumTag(typeAlias) || !typeAlias.fullName) && declName + && isPropertyAccessEntityNameExpression(declName.parent) + ) { // typedef anchored to an A.B.C assignment - we need to bind into B's namespace under name C const isTopLevel = isTopLevelNamespaceAssignment(declName.parent); if (isTopLevel) { - bindPotentiallyMissingNamespaces(file.symbol, declName.parent, isTopLevel, !!findAncestor(declName, d => isPropertyAccessExpression(d) && d.name.escapedText === "prototype"), /*containerIsClass*/ false); + bindPotentiallyMissingNamespaces( + file.symbol, + declName.parent, + isTopLevel, + !!findAncestor( + declName, + d => isPropertyAccessExpression(d) && d.name.escapedText === "prototype", + ), + /*containerIsClass*/ false, + ); const oldContainer = container; switch (getAssignmentDeclarationPropertyAccessKind(declName.parent)) { case AssignmentDeclarationKind.ExportsProperty: @@ -2401,7 +2610,8 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { break; case AssignmentDeclarationKind.Property: container = isExportsOrModuleExportsOrAlias(file, declName.parent.expression) ? file - : isPropertyAccessExpression(declName.parent.expression) ? declName.parent.expression.name + : isPropertyAccessExpression(declName.parent.expression) + ? declName.parent.expression.name : declName.parent.expression; break; case AssignmentDeclarationKind.None: @@ -2413,7 +2623,9 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { container = oldContainer; } } - else if (isJSDocEnumTag(typeAlias) || !typeAlias.fullName || typeAlias.fullName.kind === SyntaxKind.Identifier) { + else if ( + isJSDocEnumTag(typeAlias) || !typeAlias.fullName || typeAlias.fullName.kind === SyntaxKind.Identifier + ) { parent = typeAlias.parent; bindBlockScopedDeclaration(typeAlias, SymbolFlags.TypeAlias, SymbolFlags.TypeAliasExcludes); } @@ -2434,10 +2646,10 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { function checkContextualIdentifier(node: Identifier) { // Report error only if there are no parse errors in file if ( - !file.parseDiagnostics.length && - !(node.flags & NodeFlags.Ambient) && - !(node.flags & NodeFlags.JSDoc) && - !isIdentifierName(node) + !file.parseDiagnostics.length + && !(node.flags & NodeFlags.Ambient) + && !(node.flags & NodeFlags.JSDoc) + && !isIdentifierName(node) ) { // strict mode identifiers const originalKeywordKind = identifierToKeywordKind(node); @@ -2446,22 +2658,42 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { } if ( - inStrictMode && - originalKeywordKind >= SyntaxKind.FirstFutureReservedWord && - originalKeywordKind <= SyntaxKind.LastFutureReservedWord + inStrictMode + && originalKeywordKind >= SyntaxKind.FirstFutureReservedWord + && originalKeywordKind <= SyntaxKind.LastFutureReservedWord ) { - file.bindDiagnostics.push(createDiagnosticForNode(node, getStrictModeIdentifierMessage(node), declarationNameToString(node))); + file.bindDiagnostics.push( + createDiagnosticForNode(node, getStrictModeIdentifierMessage(node), declarationNameToString(node)), + ); } else if (originalKeywordKind === SyntaxKind.AwaitKeyword) { if (isExternalModule(file) && isInTopLevelContext(node)) { - file.bindDiagnostics.push(createDiagnosticForNode(node, Diagnostics.Identifier_expected_0_is_a_reserved_word_at_the_top_level_of_a_module, declarationNameToString(node))); + file.bindDiagnostics.push( + createDiagnosticForNode( + node, + Diagnostics.Identifier_expected_0_is_a_reserved_word_at_the_top_level_of_a_module, + declarationNameToString(node), + ), + ); } else if (node.flags & NodeFlags.AwaitContext) { - file.bindDiagnostics.push(createDiagnosticForNode(node, Diagnostics.Identifier_expected_0_is_a_reserved_word_that_cannot_be_used_here, declarationNameToString(node))); + file.bindDiagnostics.push( + createDiagnosticForNode( + node, + Diagnostics.Identifier_expected_0_is_a_reserved_word_that_cannot_be_used_here, + declarationNameToString(node), + ), + ); } } else if (originalKeywordKind === SyntaxKind.YieldKeyword && node.flags & NodeFlags.YieldContext) { - file.bindDiagnostics.push(createDiagnosticForNode(node, Diagnostics.Identifier_expected_0_is_a_reserved_word_that_cannot_be_used_here, declarationNameToString(node))); + file.bindDiagnostics.push( + createDiagnosticForNode( + node, + Diagnostics.Identifier_expected_0_is_a_reserved_word_that_cannot_be_used_here, + declarationNameToString(node), + ), + ); } } } @@ -2470,11 +2702,13 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { // Provide specialized messages to help the user understand why we think they're in // strict mode. if (getContainingClass(node)) { - return Diagnostics.Identifier_expected_0_is_a_reserved_word_in_strict_mode_Class_definitions_are_automatically_in_strict_mode; + return Diagnostics + .Identifier_expected_0_is_a_reserved_word_in_strict_mode_Class_definitions_are_automatically_in_strict_mode; } if (file.externalModuleIndicator) { - return Diagnostics.Identifier_expected_0_is_a_reserved_word_in_strict_mode_Modules_are_automatically_in_strict_mode; + return Diagnostics + .Identifier_expected_0_is_a_reserved_word_in_strict_mode_Modules_are_automatically_in_strict_mode; } return Diagnostics.Identifier_expected_0_is_a_reserved_word_in_strict_mode; @@ -2486,7 +2720,13 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { if (node.escapedText === "#constructor") { // Report error only if there are no parse errors in file if (!file.parseDiagnostics.length) { - file.bindDiagnostics.push(createDiagnosticForNode(node, Diagnostics.constructor_is_a_reserved_word, declarationNameToString(node))); + file.bindDiagnostics.push( + createDiagnosticForNode( + node, + Diagnostics.constructor_is_a_reserved_word, + declarationNameToString(node), + ), + ); } } } @@ -2513,7 +2753,14 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { // When a delete operator occurs within strict mode code, a SyntaxError is thrown if its // UnaryExpression is a direct reference to a variable, function argument, or function name const span = getErrorSpanForNode(file, node.expression); - file.bindDiagnostics.push(createFileDiagnostic(file, span.start, span.length, Diagnostics.delete_cannot_be_called_on_an_identifier_in_strict_mode)); + file.bindDiagnostics.push( + createFileDiagnostic( + file, + span.start, + span.length, + Diagnostics.delete_cannot_be_called_on_an_identifier_in_strict_mode, + ), + ); } } @@ -2528,7 +2775,15 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { // We check first if the name is inside class declaration or class expression; if so give explicit message // otherwise report generic error message. const span = getErrorSpanForNode(file, name); - file.bindDiagnostics.push(createFileDiagnostic(file, span.start, span.length, getStrictModeEvalOrArgumentsMessage(contextNode), idText(identifier))); + file.bindDiagnostics.push( + createFileDiagnostic( + file, + span.start, + span.length, + getStrictModeEvalOrArgumentsMessage(contextNode), + idText(identifier), + ), + ); } } } @@ -2537,7 +2792,8 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { // Provide specialized messages to help the user understand why we think they're in // strict mode. if (getContainingClass(node)) { - return Diagnostics.Code_contained_in_a_class_is_evaluated_in_JavaScript_s_strict_mode_which_does_not_allow_this_use_of_0_For_more_information_see_https_Colon_Slash_Slashdeveloper_mozilla_org_Slashen_US_Slashdocs_SlashWeb_SlashJavaScript_SlashReference_SlashStrict_mode; + return Diagnostics + .Code_contained_in_a_class_is_evaluated_in_JavaScript_s_strict_mode_which_does_not_allow_this_use_of_0_For_more_information_see_https_Colon_Slash_Slashdeveloper_mozilla_org_Slashen_US_Slashdocs_SlashWeb_SlashJavaScript_SlashReference_SlashStrict_mode; } if (file.externalModuleIndicator) { @@ -2558,11 +2814,13 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { // Provide specialized messages to help the user understand why we think they're in // strict mode. if (getContainingClass(node)) { - return Diagnostics.Function_declarations_are_not_allowed_inside_blocks_in_strict_mode_when_targeting_ES3_or_ES5_Class_definitions_are_automatically_in_strict_mode; + return Diagnostics + .Function_declarations_are_not_allowed_inside_blocks_in_strict_mode_when_targeting_ES3_or_ES5_Class_definitions_are_automatically_in_strict_mode; } if (file.externalModuleIndicator) { - return Diagnostics.Function_declarations_are_not_allowed_inside_blocks_in_strict_mode_when_targeting_ES3_or_ES5_Modules_are_automatically_in_strict_mode; + return Diagnostics + .Function_declarations_are_not_allowed_inside_blocks_in_strict_mode_when_targeting_ES3_or_ES5_Modules_are_automatically_in_strict_mode; } return Diagnostics.Function_declarations_are_not_allowed_inside_blocks_in_strict_mode_when_targeting_ES3_or_ES5; @@ -2572,14 +2830,21 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { if (languageVersion < ScriptTarget.ES2015) { // Report error if function is not top level function declaration if ( - blockScopeContainer.kind !== SyntaxKind.SourceFile && - blockScopeContainer.kind !== SyntaxKind.ModuleDeclaration && - !isFunctionLikeOrClassStaticBlockDeclaration(blockScopeContainer) + blockScopeContainer.kind !== SyntaxKind.SourceFile + && blockScopeContainer.kind !== SyntaxKind.ModuleDeclaration + && !isFunctionLikeOrClassStaticBlockDeclaration(blockScopeContainer) ) { // We check first if the name is inside class declaration or class expression; if so give explicit message // otherwise report generic error message. const errorSpan = getErrorSpanForNode(file, node); - file.bindDiagnostics.push(createFileDiagnostic(file, errorSpan.start, errorSpan.length, getStrictModeBlockScopeFunctionDeclarationMessage(node))); + file.bindDiagnostics.push( + createFileDiagnostic( + file, + errorSpan.start, + errorSpan.length, + getStrictModeBlockScopeFunctionDeclarationMessage(node), + ), + ); } } } @@ -2628,7 +2893,12 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { errorOrSuggestionOnRange(isError, node, node, message); } - function errorOrSuggestionOnRange(isError: boolean, startNode: Node, endNode: Node, message: DiagnosticMessage): void { + function errorOrSuggestionOnRange( + isError: boolean, + startNode: Node, + endNode: Node, + message: DiagnosticMessage, + ): void { addErrorOrSuggestionDiagnostic(isError, { pos: getTokenPosOfNode(startNode, file), end: endNode.end }, message); } @@ -2638,7 +2908,10 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { file.bindDiagnostics.push(diag); } else { - file.bindSuggestionDiagnostics = append(file.bindSuggestionDiagnostics, { ...diag, category: DiagnosticCategory.Suggestion }); + file.bindSuggestionDiagnostics = append(file.bindSuggestionDiagnostics, { + ...diag, + category: DiagnosticCategory.Suggestion, + }); } } @@ -2749,7 +3022,11 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { while (parentNode && !isJSDocTypeAlias(parentNode)) { parentNode = parentNode.parent; } - bindBlockScopedDeclaration(parentNode as Declaration, SymbolFlags.TypeAlias, SymbolFlags.TypeAliasExcludes); + bindBlockScopedDeclaration( + parentNode as Declaration, + SymbolFlags.TypeAlias, + SymbolFlags.TypeAliasExcludes, + ); break; } // falls through @@ -2781,12 +3058,18 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { bindSpecialPropertyDeclaration(expr); } if ( - isInJSFile(expr) && - file.commonJsModuleIndicator && - isModuleExportsAccessExpression(expr) && - !lookupSymbolForName(blockScopeContainer, "module" as __String) + isInJSFile(expr) + && file.commonJsModuleIndicator + && isModuleExportsAccessExpression(expr) + && !lookupSymbolForName(blockScopeContainer, "module" as __String) ) { - declareSymbol(file.locals!, /*parent*/ undefined, expr.expression, SymbolFlags.FunctionScopedVariable | SymbolFlags.ModuleExports, SymbolFlags.FunctionScopedVariableExcludes); + declareSymbol( + file.locals!, + /*parent*/ undefined, + expr.expression, + SymbolFlags.FunctionScopedVariable | SymbolFlags.ModuleExports, + SymbolFlags.FunctionScopedVariableExcludes, + ); } break; case SyntaxKind.BinaryExpression: @@ -2799,7 +3082,10 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { bindModuleExportsAssignment(node as BindablePropertyAssignmentExpression); break; case AssignmentDeclarationKind.PrototypeProperty: - bindPrototypePropertyAssignment((node as BindableStaticPropertyAssignmentExpression).left, node); + bindPrototypePropertyAssignment( + (node as BindableStaticPropertyAssignmentExpression).left, + node, + ); break; case AssignmentDeclarationKind.Prototype: bindPrototypeAssignment(node as BindableStaticPropertyAssignmentExpression); @@ -2856,9 +3142,17 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { return bindPropertyWorker(node as PropertyDeclaration | PropertySignature); case SyntaxKind.PropertyAssignment: case SyntaxKind.ShorthandPropertyAssignment: - return bindPropertyOrMethodOrAccessor(node as Declaration, SymbolFlags.Property, SymbolFlags.PropertyExcludes); + return bindPropertyOrMethodOrAccessor( + node as Declaration, + SymbolFlags.Property, + SymbolFlags.PropertyExcludes, + ); case SyntaxKind.EnumMember: - return bindPropertyOrMethodOrAccessor(node as Declaration, SymbolFlags.EnumMember, SymbolFlags.EnumMemberExcludes); + return bindPropertyOrMethodOrAccessor( + node as Declaration, + SymbolFlags.EnumMember, + SymbolFlags.EnumMemberExcludes, + ); case SyntaxKind.CallSignature: case SyntaxKind.ConstructSignature: @@ -2870,15 +3164,32 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { // as other properties in the object literal. So we use SymbolFlags.PropertyExcludes // so that it will conflict with any other object literal members with the same // name. - return bindPropertyOrMethodOrAccessor(node as Declaration, SymbolFlags.Method | ((node as MethodDeclaration).questionToken ? SymbolFlags.Optional : SymbolFlags.None), isObjectLiteralMethod(node) ? SymbolFlags.PropertyExcludes : SymbolFlags.MethodExcludes); + return bindPropertyOrMethodOrAccessor( + node as Declaration, + SymbolFlags.Method + | ((node as MethodDeclaration).questionToken ? SymbolFlags.Optional : SymbolFlags.None), + isObjectLiteralMethod(node) ? SymbolFlags.PropertyExcludes : SymbolFlags.MethodExcludes, + ); case SyntaxKind.FunctionDeclaration: return bindFunctionDeclaration(node as FunctionDeclaration); case SyntaxKind.Constructor: - return declareSymbolAndAddToSymbolTable(node as Declaration, SymbolFlags.Constructor, /*symbolExcludes:*/ SymbolFlags.None); + return declareSymbolAndAddToSymbolTable( + node as Declaration, + SymbolFlags.Constructor, + /*symbolExcludes:*/ SymbolFlags.None, + ); case SyntaxKind.GetAccessor: - return bindPropertyOrMethodOrAccessor(node as Declaration, SymbolFlags.GetAccessor, SymbolFlags.GetAccessorExcludes); + return bindPropertyOrMethodOrAccessor( + node as Declaration, + SymbolFlags.GetAccessor, + SymbolFlags.GetAccessorExcludes, + ); case SyntaxKind.SetAccessor: - return bindPropertyOrMethodOrAccessor(node as Declaration, SymbolFlags.SetAccessor, SymbolFlags.SetAccessorExcludes); + return bindPropertyOrMethodOrAccessor( + node as Declaration, + SymbolFlags.SetAccessor, + SymbolFlags.SetAccessorExcludes, + ); case SyntaxKind.FunctionType: case SyntaxKind.JSDocFunctionType: case SyntaxKind.JSDocSignature: @@ -2922,9 +3233,17 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { inStrictMode = true; return bindClassLikeDeclaration(node as ClassLikeDeclaration); case SyntaxKind.InterfaceDeclaration: - return bindBlockScopedDeclaration(node as Declaration, SymbolFlags.Interface, SymbolFlags.InterfaceExcludes); + return bindBlockScopedDeclaration( + node as Declaration, + SymbolFlags.Interface, + SymbolFlags.InterfaceExcludes, + ); case SyntaxKind.TypeAliasDeclaration: - return bindBlockScopedDeclaration(node as Declaration, SymbolFlags.TypeAlias, SymbolFlags.TypeAliasExcludes); + return bindBlockScopedDeclaration( + node as Declaration, + SymbolFlags.TypeAlias, + SymbolFlags.TypeAliasExcludes, + ); case SyntaxKind.EnumDeclaration: return bindEnumDeclaration(node as EnumDeclaration); case SyntaxKind.ModuleDeclaration: @@ -2940,7 +3259,11 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { case SyntaxKind.NamespaceImport: case SyntaxKind.ImportSpecifier: case SyntaxKind.ExportSpecifier: - return declareSymbolAndAddToSymbolTable(node as Declaration, SymbolFlags.Alias, SymbolFlags.AliasExcludes); + return declareSymbolAndAddToSymbolTable( + node as Declaration, + SymbolFlags.Alias, + SymbolFlags.AliasExcludes, + ); case SyntaxKind.NamespaceExportDeclaration: return bindNamespaceExportDeclaration(node as NamespaceExportDeclaration); case SyntaxKind.ImportClause: @@ -2970,14 +3293,17 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { // falls through case SyntaxKind.JSDocPropertyTag: const propTag = node as JSDocPropertyLikeTag; - const flags = propTag.isBracketed || propTag.typeExpression && propTag.typeExpression.type.kind === SyntaxKind.JSDocOptionalType ? - SymbolFlags.Property | SymbolFlags.Optional : - SymbolFlags.Property; + const flags = propTag.isBracketed + || propTag.typeExpression && propTag.typeExpression.type.kind === SyntaxKind.JSDocOptionalType + ? SymbolFlags.Property | SymbolFlags.Optional + : SymbolFlags.Property; return declareSymbolAndAddToSymbolTable(propTag, flags, SymbolFlags.PropertyExcludes); case SyntaxKind.JSDocTypedefTag: case SyntaxKind.JSDocCallbackTag: case SyntaxKind.JSDocEnumTag: - return (delayedTypeAliases || (delayedTypeAliases = [])).push(node as JSDocTypedefTag | JSDocCallbackTag | JSDocEnumTag); + return (delayedTypeAliases || (delayedTypeAliases = [])).push( + node as JSDocTypedefTag | JSDocCallbackTag | JSDocEnumTag, + ); case SyntaxKind.JSDocOverloadTag: return bind((node as JSDocOverloadTag).typeExpression); } @@ -2987,7 +3313,11 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { const isAutoAccessor = isAutoAccessorPropertyDeclaration(node); const includes = isAutoAccessor ? SymbolFlags.Accessor : SymbolFlags.Property; const excludes = isAutoAccessor ? SymbolFlags.AccessorExcludes : SymbolFlags.PropertyExcludes; - return bindPropertyOrMethodOrAccessor(node, includes | (node.questionToken ? SymbolFlags.Optional : SymbolFlags.None), excludes); + return bindPropertyOrMethodOrAccessor( + node, + includes | (node.questionToken ? SymbolFlags.Optional : SymbolFlags.None), + excludes, + ); } function bindAnonymousTypeWorker(node: TypeLiteralNode | MappedTypeNode | JSDocTypeLiteral) { @@ -3064,7 +3394,13 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { // declareSymbol walks up parents to find name text, parent _must_ be set // but won't be set by the normal binder walk until `bindChildren` later on. setParent(node.exportClause, node); - declareSymbol(container.symbol.exports, container.symbol, node.exportClause, SymbolFlags.Alias, SymbolFlags.AliasExcludes); + declareSymbol( + container.symbol.exports, + container.symbol, + node.exportClause, + SymbolFlags.Alias, + SymbolFlags.AliasExcludes, + ); } } @@ -3116,7 +3452,8 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { return symbol; }); if (symbol) { - const isAlias = isAliasableExpression(node.right) && (isExportsIdentifier(node.left.expression) || isModuleExportsAccessExpression(node.left.expression)); + const isAlias = isAliasableExpression(node.right) + && (isExportsIdentifier(node.left.expression) || isModuleExportsAccessExpression(node.left.expression)); const flags = isAlias ? SymbolFlags.Alias : SymbolFlags.Property | SymbolFlags.ExportValue; setParent(node.left, node); declareSymbol(symbol.exports!, symbol, node.left, flags, SymbolFlags.None); @@ -3132,11 +3469,17 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { return; } const assignedExpression = getRightMostAssignedExpression(node.right); - if (isEmptyObjectLiteral(assignedExpression) || container === file && isExportsOrModuleExportsOrAlias(file, assignedExpression)) { + if ( + isEmptyObjectLiteral(assignedExpression) + || container === file && isExportsOrModuleExportsOrAlias(file, assignedExpression) + ) { return; } - if (isObjectLiteralExpression(assignedExpression) && every(assignedExpression.properties, isShorthandPropertyAssignment)) { + if ( + isObjectLiteralExpression(assignedExpression) + && every(assignedExpression.properties, isShorthandPropertyAssignment) + ) { forEach(assignedExpression.properties, bindExportAssignedObjectMemberAlias); return; } @@ -3145,29 +3488,51 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { const flags = exportAssignmentIsAlias(node) ? SymbolFlags.Alias // An export= with an EntityNameExpression or a ClassExpression exports all meanings of that identifier or class : SymbolFlags.Property | SymbolFlags.ExportValue | SymbolFlags.ValueModule; - const symbol = declareSymbol(file.symbol.exports!, file.symbol, node, flags | SymbolFlags.Assignment, SymbolFlags.None); + const symbol = declareSymbol( + file.symbol.exports!, + file.symbol, + node, + flags | SymbolFlags.Assignment, + SymbolFlags.None, + ); setValueDeclaration(symbol, node); } function bindExportAssignedObjectMemberAlias(node: ShorthandPropertyAssignment) { - declareSymbol(file.symbol.exports!, file.symbol, node, SymbolFlags.Alias | SymbolFlags.Assignment, SymbolFlags.None); - } - - function bindThisPropertyAssignment(node: BindablePropertyAssignmentExpression | PropertyAccessExpression | LiteralLikeElementAccessExpression) { + declareSymbol( + file.symbol.exports!, + file.symbol, + node, + SymbolFlags.Alias | SymbolFlags.Assignment, + SymbolFlags.None, + ); + } + + function bindThisPropertyAssignment( + node: BindablePropertyAssignmentExpression | PropertyAccessExpression | LiteralLikeElementAccessExpression, + ) { Debug.assert(isInJSFile(node)); // private identifiers *must* be declared (even in JS files) - const hasPrivateIdentifier = (isBinaryExpression(node) && isPropertyAccessExpression(node.left) && isPrivateIdentifier(node.left.name)) + const hasPrivateIdentifier = + (isBinaryExpression(node) && isPropertyAccessExpression(node.left) && isPrivateIdentifier(node.left.name)) || (isPropertyAccessExpression(node) && isPrivateIdentifier(node.name)); if (hasPrivateIdentifier) { return; } - const thisContainer = getThisContainer(node, /*includeArrowFunctions*/ false, /*includeClassComputedPropertyName*/ false); + const thisContainer = getThisContainer( + node, + /*includeArrowFunctions*/ false, + /*includeClassComputedPropertyName*/ false, + ); switch (thisContainer.kind) { case SyntaxKind.FunctionDeclaration: case SyntaxKind.FunctionExpression: let constructorSymbol: Symbol | undefined = thisContainer.symbol; // For `f.prototype.m = function() { this.x = 0; }`, `this.x = 0` should modify `f`'s members, not the function expression. - if (isBinaryExpression(thisContainer.parent) && thisContainer.parent.operatorToken.kind === SyntaxKind.EqualsToken) { + if ( + isBinaryExpression(thisContainer.parent) + && thisContainer.parent.operatorToken.kind === SyntaxKind.EqualsToken + ) { const l = thisContainer.parent.left; if (isBindableStaticAccessExpression(l) && isPrototypeAccess(l.expression)) { constructorSymbol = lookupSymbolForPropertyAccess(l.expression.expression, thisParentContainer); @@ -3182,7 +3547,13 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { bindDynamicallyNamedThisPropertyAssignment(node, constructorSymbol, constructorSymbol.members); } else { - declareSymbol(constructorSymbol.members, constructorSymbol, node, SymbolFlags.Property | SymbolFlags.Assignment, SymbolFlags.PropertyExcludes & ~SymbolFlags.Property); + declareSymbol( + constructorSymbol.members, + constructorSymbol, + node, + SymbolFlags.Property | SymbolFlags.Assignment, + SymbolFlags.PropertyExcludes & ~SymbolFlags.Property, + ); } addDeclarationToSymbol(constructorSymbol, constructorSymbol.valueDeclaration, SymbolFlags.Class); } @@ -3197,12 +3568,20 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { // this.foo assignment in a JavaScript class // Bind this property to the containing class const containingClass = thisContainer.parent; - const symbolTable = isStatic(thisContainer) ? containingClass.symbol.exports! : containingClass.symbol.members!; + const symbolTable = isStatic(thisContainer) ? containingClass.symbol.exports! + : containingClass.symbol.members!; if (hasDynamicName(node)) { bindDynamicallyNamedThisPropertyAssignment(node, containingClass.symbol, symbolTable); } else { - declareSymbol(symbolTable, containingClass.symbol, node, SymbolFlags.Property | SymbolFlags.Assignment, SymbolFlags.None, /*isReplaceableByMethod*/ true); + declareSymbol( + symbolTable, + containingClass.symbol, + node, + SymbolFlags.Property | SymbolFlags.Assignment, + SymbolFlags.None, + /*isReplaceableByMethod*/ true, + ); } break; case SyntaxKind.SourceFile: @@ -3211,10 +3590,20 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { break; } else if (thisContainer.commonJsModuleIndicator) { - declareSymbol(thisContainer.symbol.exports!, thisContainer.symbol, node, SymbolFlags.Property | SymbolFlags.ExportValue, SymbolFlags.None); + declareSymbol( + thisContainer.symbol.exports!, + thisContainer.symbol, + node, + SymbolFlags.Property | SymbolFlags.ExportValue, + SymbolFlags.None, + ); } else { - declareSymbolAndAddToSymbolTable(node, SymbolFlags.FunctionScopedVariable, SymbolFlags.FunctionScopedVariableExcludes); + declareSymbolAndAddToSymbolTable( + node, + SymbolFlags.FunctionScopedVariable, + SymbolFlags.FunctionScopedVariableExcludes, + ); } break; // Namespaces are not allowed in javascript files, so do nothing here @@ -3225,14 +3614,32 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { } } - function bindDynamicallyNamedThisPropertyAssignment(node: BinaryExpression | DynamicNamedDeclaration, symbol: Symbol, symbolTable: SymbolTable) { - declareSymbol(symbolTable, symbol, node, SymbolFlags.Property, SymbolFlags.None, /*isReplaceableByMethod*/ true, /*isComputedName*/ true); + function bindDynamicallyNamedThisPropertyAssignment( + node: BinaryExpression | DynamicNamedDeclaration, + symbol: Symbol, + symbolTable: SymbolTable, + ) { + declareSymbol( + symbolTable, + symbol, + node, + SymbolFlags.Property, + SymbolFlags.None, + /*isReplaceableByMethod*/ true, + /*isComputedName*/ true, + ); addLateBoundAssignmentDeclarationToSymbol(node, symbol); } - function addLateBoundAssignmentDeclarationToSymbol(node: BinaryExpression | DynamicNamedDeclaration, symbol: Symbol | undefined) { + function addLateBoundAssignmentDeclarationToSymbol( + node: BinaryExpression | DynamicNamedDeclaration, + symbol: Symbol | undefined, + ) { if (symbol) { - (symbol.assignmentDeclarationMembers || (symbol.assignmentDeclarationMembers = new Map())).set(getNodeId(node), node); + (symbol.assignmentDeclarationMembers || (symbol.assignmentDeclarationMembers = new Map())).set( + getNodeId(node), + node, + ); } } @@ -3254,11 +3661,18 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { function bindPrototypeAssignment(node: BindableStaticPropertyAssignmentExpression) { setParent(node.left, node); setParent(node.right, node); - bindPropertyAssignment(node.left.expression, node.left, /*isPrototypeProperty*/ false, /*containerIsClass*/ true); + bindPropertyAssignment( + node.left.expression, + node.left, + /*isPrototypeProperty*/ false, + /*containerIsClass*/ true, + ); } function bindObjectDefinePrototypeProperty(node: BindableObjectDefinePropertyCall) { - const namespaceSymbol = lookupSymbolForPropertyAccess((node.arguments[0] as PropertyAccessExpression).expression as EntityNameExpression); + const namespaceSymbol = lookupSymbolForPropertyAccess( + (node.arguments[0] as PropertyAccessExpression).expression as EntityNameExpression, + ); if (namespaceSymbol && namespaceSymbol.valueDeclaration) { // Ensure the namespace symbol becomes class-like addDeclarationToSymbol(namespaceSymbol, namespaceSymbol.valueDeclaration, SymbolFlags.Class); @@ -3287,24 +3701,36 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { function bindObjectDefinePropertyAssignment(node: BindableObjectDefinePropertyCall) { let namespaceSymbol = lookupSymbolForPropertyAccess(node.arguments[0]); const isToplevel = node.parent.parent.kind === SyntaxKind.SourceFile; - namespaceSymbol = bindPotentiallyMissingNamespaces(namespaceSymbol, node.arguments[0], isToplevel, /*isPrototypeProperty*/ false, /*containerIsClass*/ false); + namespaceSymbol = bindPotentiallyMissingNamespaces( + namespaceSymbol, + node.arguments[0], + isToplevel, + /*isPrototypeProperty*/ false, + /*containerIsClass*/ false, + ); bindPotentiallyNewExpandoMemberToNamespace(node, namespaceSymbol, /*isPrototypeProperty*/ false); } function bindSpecialPropertyAssignment(node: BindablePropertyAssignmentExpression) { // Class declarations in Typescript do not allow property declarations - const parentSymbol = lookupSymbolForPropertyAccess(node.left.expression, container) || lookupSymbolForPropertyAccess(node.left.expression, blockScopeContainer); + const parentSymbol = lookupSymbolForPropertyAccess(node.left.expression, container) + || lookupSymbolForPropertyAccess(node.left.expression, blockScopeContainer); if (!isInJSFile(node) && !isFunctionSymbol(parentSymbol)) { return; } const rootExpr = getLeftmostAccessExpression(node.left); - if (isIdentifier(rootExpr) && lookupSymbolForName(container, rootExpr.escapedText)?.flags! & SymbolFlags.Alias) { + if ( + isIdentifier(rootExpr) && lookupSymbolForName(container, rootExpr.escapedText)?.flags! & SymbolFlags.Alias + ) { return; } // Fix up parent pointers since we're going to use these nodes before we bind into them setParent(node.left, node); setParent(node.right, node); - if (isIdentifier(node.left.expression) && container === file && isExportsOrModuleExportsOrAlias(file, node.left.expression)) { + if ( + isIdentifier(node.left.expression) && container === file + && isExportsOrModuleExportsOrAlias(file, node.left.expression) + ) { // This can be an alias for the 'exports' or 'module.exports' names, e.g. // var util = module.exports; // util.property = function ... @@ -3312,7 +3738,13 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { } else if (hasDynamicName(node)) { bindAnonymousDeclaration(node, SymbolFlags.Property | SymbolFlags.Assignment, InternalSymbolName.Computed); - const sym = bindPotentiallyMissingNamespaces(parentSymbol, node.left.expression, isTopLevelNamespaceAssignment(node.left), /*isPrototypeProperty*/ false, /*containerIsClass*/ false); + const sym = bindPotentiallyMissingNamespaces( + parentSymbol, + node.left.expression, + isTopLevelNamespaceAssignment(node.left), + /*isPrototypeProperty*/ false, + /*containerIsClass*/ false, + ); addLateBoundAssignmentDeclarationToSymbol(node, sym); } else { @@ -3330,7 +3762,13 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { bindPropertyAssignment(node.expression, node, /*isPrototypeProperty*/ false, /*containerIsClass*/ false); } - function bindPotentiallyMissingNamespaces(namespaceSymbol: Symbol | undefined, entityName: BindableStaticNameExpression, isToplevel: boolean, isPrototypeProperty: boolean, containerIsClass: boolean) { + function bindPotentiallyMissingNamespaces( + namespaceSymbol: Symbol | undefined, + entityName: BindableStaticNameExpression, + isToplevel: boolean, + isPrototypeProperty: boolean, + containerIsClass: boolean, + ) { if (namespaceSymbol?.flags! & SymbolFlags.Alias) { return namespaceSymbol; } @@ -3344,8 +3782,8 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { return symbol; } else { - const table = parent ? parent.exports! : - file.jsGlobalAugmentations || (file.jsGlobalAugmentations = createSymbolTable()); + const table = parent ? parent.exports! + : file.jsGlobalAugmentations || (file.jsGlobalAugmentations = createSymbolTable()); return declareSymbol(table, parent, id, flags, excludeFlags); } }); @@ -3356,15 +3794,19 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { return namespaceSymbol; } - function bindPotentiallyNewExpandoMemberToNamespace(declaration: BindableStaticAccessExpression | CallExpression, namespaceSymbol: Symbol | undefined, isPrototypeProperty: boolean) { + function bindPotentiallyNewExpandoMemberToNamespace( + declaration: BindableStaticAccessExpression | CallExpression, + namespaceSymbol: Symbol | undefined, + isPrototypeProperty: boolean, + ) { if (!namespaceSymbol || !isExpandoSymbol(namespaceSymbol)) { return; } // Set up the members collection if it doesn't exist already - const symbolTable = isPrototypeProperty ? - (namespaceSymbol.members || (namespaceSymbol.members = createSymbolTable())) : - (namespaceSymbol.exports || (namespaceSymbol.exports = createSymbolTable())); + const symbolTable = isPrototypeProperty + ? (namespaceSymbol.members || (namespaceSymbol.members = createSymbolTable())) + : (namespaceSymbol.exports || (namespaceSymbol.exports = createSymbolTable())); let includes = SymbolFlags.None; let excludes = SymbolFlags.None; @@ -3402,7 +3844,13 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { excludes = SymbolFlags.PropertyExcludes; } - declareSymbol(symbolTable, namespaceSymbol, declaration, includes | SymbolFlags.Assignment, excludes & ~SymbolFlags.Assignment); + declareSymbol( + symbolTable, + namespaceSymbol, + declaration, + includes | SymbolFlags.Assignment, + excludes & ~SymbolFlags.Assignment, + ); } function isTopLevelNamespaceAssignment(propertyAccess: BindableAccessExpression) { @@ -3411,10 +3859,22 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { : propertyAccess.parent.parent.kind === SyntaxKind.SourceFile; } - function bindPropertyAssignment(name: BindableStaticNameExpression, propertyAccess: BindableStaticAccessExpression, isPrototypeProperty: boolean, containerIsClass: boolean) { - let namespaceSymbol = lookupSymbolForPropertyAccess(name, container) || lookupSymbolForPropertyAccess(name, blockScopeContainer); + function bindPropertyAssignment( + name: BindableStaticNameExpression, + propertyAccess: BindableStaticAccessExpression, + isPrototypeProperty: boolean, + containerIsClass: boolean, + ) { + let namespaceSymbol = lookupSymbolForPropertyAccess(name, container) + || lookupSymbolForPropertyAccess(name, blockScopeContainer); const isToplevel = isTopLevelNamespaceAssignment(propertyAccess); - namespaceSymbol = bindPotentiallyMissingNamespaces(namespaceSymbol, propertyAccess.expression, isToplevel, isPrototypeProperty, containerIsClass); + namespaceSymbol = bindPotentiallyMissingNamespaces( + namespaceSymbol, + propertyAccess.expression, + isToplevel, + isPrototypeProperty, + containerIsClass, + ); bindPotentiallyNewExpandoMemberToNamespace(propertyAccess, namespaceSymbol, isPrototypeProperty); } @@ -3436,15 +3896,22 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { if (node && isCallExpression(node)) { return !!getAssignedExpandoInitializer(node); } - let init = !node ? undefined : - isVariableDeclaration(node) ? node.initializer : - isBinaryExpression(node) ? node.right : - isPropertyAccessExpression(node) && isBinaryExpression(node.parent) ? node.parent.right : - undefined; + let init = !node ? undefined + : isVariableDeclaration(node) ? node.initializer + : isBinaryExpression(node) ? node.right + : isPropertyAccessExpression(node) && isBinaryExpression(node.parent) ? node.parent.right + : undefined; init = init && getRightMostAssignedExpression(init); if (init) { - const isPrototypeAssignment = isPrototypeAccess(isVariableDeclaration(node!) ? node.name : isBinaryExpression(node!) ? node.left : node!); - return !!getExpandoInitializer(isBinaryExpression(init) && (init.operatorToken.kind === SyntaxKind.BarBarToken || init.operatorToken.kind === SyntaxKind.QuestionQuestionToken) ? init.right : init, isPrototypeAssignment); + const isPrototypeAssignment = isPrototypeAccess( + isVariableDeclaration(node!) ? node.name : isBinaryExpression(node!) ? node.left : node!, + ); + return !!getExpandoInitializer( + isBinaryExpression(init) + && (init.operatorToken.kind === SyntaxKind.BarBarToken + || init.operatorToken.kind === SyntaxKind.QuestionQuestionToken) ? init.right : init, + isPrototypeAssignment, + ); } return false; } @@ -3456,7 +3923,10 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { return expr.parent; } - function lookupSymbolForPropertyAccess(node: BindableStaticNameExpression, lookupContainer: IsContainer | IsBlockScopedContainer | EntityNameExpression = container): Symbol | undefined { + function lookupSymbolForPropertyAccess( + node: BindableStaticNameExpression, + lookupContainer: IsContainer | IsBlockScopedContainer | EntityNameExpression = container, + ): Symbol | undefined { if (isIdentifier(node)) { return lookupSymbolForName(lookupContainer, node.escapedText); } @@ -3466,7 +3936,11 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { } } - function forEachIdentifierInEntityName(e: BindableStaticNameExpression, parent: Symbol | undefined, action: (e: Declaration, symbol: Symbol | undefined, parent: Symbol | undefined) => Symbol | undefined): Symbol | undefined { + function forEachIdentifierInEntityName( + e: BindableStaticNameExpression, + parent: Symbol | undefined, + action: (e: Declaration, symbol: Symbol | undefined, parent: Symbol | undefined) => Symbol | undefined, + ): Symbol | undefined { if (isExportsOrModuleExportsOrAlias(file, e)) { return file.symbol; } @@ -3522,7 +3996,13 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { if (node.name) { setParent(node.name, node); } - file.bindDiagnostics.push(createDiagnosticForNode(symbolExport.declarations![0], Diagnostics.Duplicate_identifier_0, symbolName(prototypeSymbol))); + file.bindDiagnostics.push( + createDiagnosticForNode( + symbolExport.declarations![0], + Diagnostics.Duplicate_identifier_0, + symbolName(prototypeSymbol), + ), + ); } symbol.exports!.set(prototypeSymbol.escapedName, prototypeSymbol); prototypeSymbol.parent = symbol; @@ -3542,16 +4022,20 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { if (!isBindingPattern(node.name)) { const possibleVariableDecl = node.kind === SyntaxKind.VariableDeclaration ? node : node.parent.parent; if ( - isInJSFile(node) && - shouldResolveJsRequire(options) && - isVariableDeclarationInitializedToBareOrAccessedRequire(possibleVariableDecl) && - !getJSDocTypeTag(node) && - !(getCombinedModifierFlags(node) & ModifierFlags.Export) + isInJSFile(node) + && shouldResolveJsRequire(options) + && isVariableDeclarationInitializedToBareOrAccessedRequire(possibleVariableDecl) + && !getJSDocTypeTag(node) + && !(getCombinedModifierFlags(node) & ModifierFlags.Export) ) { declareSymbolAndAddToSymbolTable(node as Declaration, SymbolFlags.Alias, SymbolFlags.AliasExcludes); } else if (isBlockOrCatchScoped(node)) { - bindBlockScopedDeclaration(node, SymbolFlags.BlockScopedVariable, SymbolFlags.BlockScopedVariableExcludes); + bindBlockScopedDeclaration( + node, + SymbolFlags.BlockScopedVariable, + SymbolFlags.BlockScopedVariableExcludes, + ); } else if (isParameterDeclaration(node)) { // It is safe to walk up parent chain to find whether the node is a destructuring parameter declaration @@ -3563,10 +4047,18 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { // function foo([a,a]) {} // Duplicate Identifier error // function bar(a,a) {} // Duplicate Identifier error, parameter declaration in this case is handled in bindParameter // // which correctly set excluded symbols - declareSymbolAndAddToSymbolTable(node, SymbolFlags.FunctionScopedVariable, SymbolFlags.ParameterExcludes); + declareSymbolAndAddToSymbolTable( + node, + SymbolFlags.FunctionScopedVariable, + SymbolFlags.ParameterExcludes, + ); } else { - declareSymbolAndAddToSymbolTable(node, SymbolFlags.FunctionScopedVariable, SymbolFlags.FunctionScopedVariableExcludes); + declareSymbolAndAddToSymbolTable( + node, + SymbolFlags.FunctionScopedVariable, + SymbolFlags.FunctionScopedVariableExcludes, + ); } } } @@ -3582,7 +4074,12 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { } if (isBindingPattern(node.name)) { - bindAnonymousDeclaration(node, SymbolFlags.FunctionScopedVariable, "__" + (node as ParameterDeclaration).parent.parameters.indexOf(node as ParameterDeclaration) as __String); + bindAnonymousDeclaration( + node, + SymbolFlags.FunctionScopedVariable, + "__" + + (node as ParameterDeclaration).parent.parameters.indexOf(node as ParameterDeclaration) as __String, + ); } else { declareSymbolAndAddToSymbolTable(node, SymbolFlags.FunctionScopedVariable, SymbolFlags.ParameterExcludes); @@ -3592,7 +4089,13 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { // containing class. if (isParameterPropertyDeclaration(node, node.parent)) { const classDeclaration = node.parent.parent; - declareSymbol(classDeclaration.symbol.members!, classDeclaration.symbol, node, SymbolFlags.Property | (node.questionToken ? SymbolFlags.Optional : SymbolFlags.None), SymbolFlags.PropertyExcludes); + declareSymbol( + classDeclaration.symbol.members!, + classDeclaration.symbol, + node, + SymbolFlags.Property | (node.questionToken ? SymbolFlags.Optional : SymbolFlags.None), + SymbolFlags.PropertyExcludes, + ); } } @@ -3642,7 +4145,10 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { } function getInferTypeContainer(node: Node): ConditionalTypeNode | undefined { - const extendsType = findAncestor(node, n => n.parent && isConditionalTypeNode(n.parent) && n.parent.extendsType === n); + const extendsType = findAncestor( + node, + n => n.parent && isConditionalTypeNode(n.parent) && n.parent.extendsType === n, + ); return extendsType && extendsType.parent as ConditionalTypeNode; } @@ -3652,7 +4158,13 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { if (container) { Debug.assertNode(container, canHaveLocals); container.locals ??= createSymbolTable(); - declareSymbol(container.locals, /*parent*/ undefined, node, SymbolFlags.TypeParameter, SymbolFlags.TypeParameterExcludes); + declareSymbol( + container.locals, + /*parent*/ undefined, + node, + SymbolFlags.TypeParameter, + SymbolFlags.TypeParameterExcludes, + ); } else { declareSymbolAndAddToSymbolTable(node, SymbolFlags.TypeParameter, SymbolFlags.TypeParameterExcludes); @@ -3663,7 +4175,13 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { if (container) { Debug.assertNode(container, canHaveLocals); container.locals ??= createSymbolTable(); - declareSymbol(container.locals, /*parent*/ undefined, node, SymbolFlags.TypeParameter, SymbolFlags.TypeParameterExcludes); + declareSymbol( + container.locals, + /*parent*/ undefined, + node, + SymbolFlags.TypeParameter, + SymbolFlags.TypeParameterExcludes, + ); } else { bindAnonymousDeclaration(node, SymbolFlags.TypeParameter, getDeclarationName(node)!); // TODO: GH#18217 @@ -3678,7 +4196,8 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { function shouldReportErrorOnModuleDeclaration(node: ModuleDeclaration): boolean { const instanceState = getModuleInstanceState(node); - return instanceState === ModuleInstanceState.Instantiated || (instanceState === ModuleInstanceState.ConstEnumOnly && shouldPreserveConstEnums(options)); + return instanceState === ModuleInstanceState.Instantiated + || (instanceState === ModuleInstanceState.ConstEnumOnly && shouldPreserveConstEnums(options)); } function checkUnreachable(node: Node): boolean { @@ -3688,11 +4207,12 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { if (currentFlow === unreachableFlow) { const reportError = // report error on all statements except empty ones - (isStatementButNotDeclaration(node) && node.kind !== SyntaxKind.EmptyStatement) || + (isStatementButNotDeclaration(node) && node.kind !== SyntaxKind.EmptyStatement) // report error on class declarations - node.kind === SyntaxKind.ClassDeclaration || + || node.kind === SyntaxKind.ClassDeclaration // report error on instantiated modules or const-enums only modules if preserveConstEnums is set - (node.kind === SyntaxKind.ModuleDeclaration && shouldReportErrorOnModuleDeclaration(node as ModuleDeclaration)); + || (node.kind === SyntaxKind.ModuleDeclaration + && shouldReportErrorOnModuleDeclaration(node as ModuleDeclaration)); if (reportError) { currentFlow = reportedUnreachableFlow; @@ -3707,15 +4227,19 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { // - node is not block scoped variable statement and at least one variable declaration has initializer // Rationale: we don't want to report errors on non-initialized var's since they are hoisted // On the other side we do want to report errors on non-initialized 'lets' because of TDZ - const isError = unreachableCodeIsError(options) && - !(node.flags & NodeFlags.Ambient) && - ( - !isVariableStatement(node) || - !!(getCombinedNodeFlags(node.declarationList) & NodeFlags.BlockScoped) || - node.declarationList.declarations.some(d => !!d.initializer) + const isError = unreachableCodeIsError(options) + && !(node.flags & NodeFlags.Ambient) + && ( + !isVariableStatement(node) + || !!(getCombinedNodeFlags(node.declarationList) & NodeFlags.BlockScoped) + || node.declarationList.declarations.some(d => !!d.initializer) ); - eachUnreachableRange(node, (start, end) => errorOrSuggestionOnRange(isError, start, end, Diagnostics.Unreachable_code_detected)); + eachUnreachableRange( + node, + (start, end) => + errorOrSuggestionOnRange(isError, start, end, Diagnostics.Unreachable_code_detected), + ); } } } @@ -3736,9 +4260,10 @@ function eachUnreachableRange(node: Node, cb: (start: Node, last: Node) => void) // As opposed to a pure declaration like an `interface` function isExecutableStatement(s: Statement): boolean { // Don't remove statements that can validly be used before they appear. - return !isFunctionDeclaration(s) && !isPurelyTypeDeclaration(s) && !isEnumDeclaration(s) && + return !isFunctionDeclaration(s) && !isPurelyTypeDeclaration(s) && !isEnumDeclaration(s) // `var x;` may declare a variable used above - !(isVariableStatement(s) && !(getCombinedNodeFlags(s) & (NodeFlags.BlockScoped)) && s.declarationList.declarations.some(d => !d.initializer)); + && !(isVariableStatement(s) && !(getCombinedNodeFlags(s) & (NodeFlags.BlockScoped)) + && s.declarationList.declarations.some(d => !d.initializer)); } function isPurelyTypeDeclaration(s: Statement): boolean { @@ -3768,7 +4293,10 @@ export function isExportsOrModuleExportsOrAlias(sourceFile: SourceFile, node: Ex } else if (isIdentifier(node)) { const symbol = lookupSymbolForName(sourceFile, node.escapedText); - if (!!symbol && !!symbol.valueDeclaration && isVariableDeclaration(symbol.valueDeclaration) && !!symbol.valueDeclaration.initializer) { + if ( + !!symbol && !!symbol.valueDeclaration && isVariableDeclaration(symbol.valueDeclaration) + && !!symbol.valueDeclaration.initializer + ) { const init = symbol.valueDeclaration.initializer; q.enqueue(init); if (isAssignmentExpression(init, /*excludeCompoundAssignment*/ true)) { @@ -3809,7 +4337,8 @@ export function getContainerFlags(node: Node): ContainerFlags { case SyntaxKind.SetAccessor: case SyntaxKind.MethodDeclaration: if (isObjectLiteralOrClassExpressionMethodOrAccessor(node)) { - return ContainerFlags.IsContainer | ContainerFlags.IsControlFlowContainer | ContainerFlags.HasLocals | ContainerFlags.IsFunctionLike | ContainerFlags.IsObjectLiteralOrClassExpressionMethodOrAccessor; + return ContainerFlags.IsContainer | ContainerFlags.IsControlFlowContainer | ContainerFlags.HasLocals + | ContainerFlags.IsFunctionLike | ContainerFlags.IsObjectLiteralOrClassExpressionMethodOrAccessor; } // falls through case SyntaxKind.Constructor: @@ -3822,11 +4351,13 @@ export function getContainerFlags(node: Node): ContainerFlags { case SyntaxKind.ConstructSignature: case SyntaxKind.ConstructorType: case SyntaxKind.ClassStaticBlockDeclaration: - return ContainerFlags.IsContainer | ContainerFlags.IsControlFlowContainer | ContainerFlags.HasLocals | ContainerFlags.IsFunctionLike; + return ContainerFlags.IsContainer | ContainerFlags.IsControlFlowContainer | ContainerFlags.HasLocals + | ContainerFlags.IsFunctionLike; case SyntaxKind.FunctionExpression: case SyntaxKind.ArrowFunction: - return ContainerFlags.IsContainer | ContainerFlags.IsControlFlowContainer | ContainerFlags.HasLocals | ContainerFlags.IsFunctionLike | ContainerFlags.IsFunctionExpression; + return ContainerFlags.IsContainer | ContainerFlags.IsControlFlowContainer | ContainerFlags.HasLocals + | ContainerFlags.IsFunctionLike | ContainerFlags.IsFunctionExpression; case SyntaxKind.ModuleBlock: return ContainerFlags.IsControlFlowContainer; @@ -3857,7 +4388,8 @@ export function getContainerFlags(node: Node): ContainerFlags { // By not creating a new block-scoped-container here, we ensure that both 'var x' // and 'let x' go into the Function-container's locals, and we do get a collision // conflict. - return isFunctionLike(node.parent) || isClassStaticBlockDeclaration(node.parent) ? ContainerFlags.None : ContainerFlags.IsBlockScopedContainer | ContainerFlags.HasLocals; + return isFunctionLike(node.parent) || isClassStaticBlockDeclaration(node.parent) ? ContainerFlags.None + : ContainerFlags.IsBlockScopedContainer | ContainerFlags.HasLocals; } return ContainerFlags.None; diff --git a/src/compiler/builder.ts b/src/compiler/builder.ts index aa355678286dd..54d4bc3ee596e 100644 --- a/src/compiler/builder.ts +++ b/src/compiler/builder.ts @@ -283,8 +283,12 @@ export function getBuilderFileEmit(options: CompilerOptions) { * * @internal */ -export function getPendingEmitKind(optionsOrEmitKind: CompilerOptions | BuilderFileEmit, oldOptionsOrEmitKind: CompilerOptions | BuilderFileEmit | undefined): BuilderFileEmit { - const oldEmitKind = oldOptionsOrEmitKind && (isNumber(oldOptionsOrEmitKind) ? oldOptionsOrEmitKind : getBuilderFileEmit(oldOptionsOrEmitKind)); +export function getPendingEmitKind( + optionsOrEmitKind: CompilerOptions | BuilderFileEmit, + oldOptionsOrEmitKind: CompilerOptions | BuilderFileEmit | undefined, +): BuilderFileEmit { + const oldEmitKind = oldOptionsOrEmitKind + && (isNumber(oldOptionsOrEmitKind) ? oldOptionsOrEmitKind : getBuilderFileEmit(oldOptionsOrEmitKind)); const emitKind = isNumber(optionsOrEmitKind) ? optionsOrEmitKind : getBuilderFileEmit(optionsOrEmitKind); if (oldEmitKind === emitKind) return BuilderFileEmit.None; if (!oldEmitKind || !emitKind) return emitKind; @@ -297,16 +301,28 @@ export function getPendingEmitKind(optionsOrEmitKind: CompilerOptions | BuilderF return result; } -function hasSameKeys(map1: ReadonlyCollection | undefined, map2: ReadonlyCollection | undefined): boolean { +function hasSameKeys( + map1: ReadonlyCollection | undefined, + map2: ReadonlyCollection | undefined, +): boolean { // Has same size and every key is present in both maps - return map1 === map2 || map1 !== undefined && map2 !== undefined && map1.size === map2.size && !forEachKey(map1, key => !map2.has(key)); + return map1 === map2 + || map1 !== undefined && map2 !== undefined && map1.size === map2.size + && !forEachKey(map1, key => !map2.has(key)); } /** * Create the state so that we can iterate on changedFiles/affected files */ -function createBuilderProgramState(newProgram: Program, oldState: Readonly | undefined): BuilderProgramState { - const state = BuilderState.create(newProgram, oldState, /*disableUseFileVersionAsSignature*/ false) as BuilderProgramState; +function createBuilderProgramState( + newProgram: Program, + oldState: Readonly | undefined, +): BuilderProgramState { + const state = BuilderState.create( + newProgram, + oldState, + /*disableUseFileVersionAsSignature*/ false, + ) as BuilderProgramState; state.program = newProgram; const compilerOptions = newProgram.getCompilerOptions(); state.compilerOptions = compilerOptions; @@ -315,26 +331,30 @@ function createBuilderProgramState(newProgram: Program, oldState: Readonly state.changedFilesSet.add(value)); @@ -352,25 +372,31 @@ function createBuilderProgramState(newProgram: Program, oldState: Readonly { let oldInfo: Readonly | undefined; let newReferences: ReadonlySet | undefined; // if not using old state, every file is changed if ( - !useOldState || + !useOldState // File wasn't present in old state - !(oldInfo = oldState!.fileInfos.get(sourceFilePath)) || + || !(oldInfo = oldState!.fileInfos.get(sourceFilePath)) // versions dont match - oldInfo.version !== info.version || + || oldInfo.version !== info.version // Implied formats dont match - oldInfo.impliedFormat !== info.impliedFormat || + || oldInfo.impliedFormat !== info.impliedFormat // Referenced files changed - !hasSameKeys(newReferences = referencedMap && referencedMap.getValues(sourceFilePath), oldReferencedMap && oldReferencedMap.getValues(sourceFilePath)) || + || !hasSameKeys( + newReferences = referencedMap && referencedMap.getValues(sourceFilePath), + oldReferencedMap && oldReferencedMap.getValues(sourceFilePath), + ) // Referenced file was deleted in the new program - newReferences && forEachKey(newReferences, path => !state.fileInfos.has(path) && oldState!.fileInfos.has(path)) + || newReferences + && forEachKey(newReferences, path => !state.fileInfos.has(path) && oldState!.fileInfos.has(path)) ) { // Register file as changed file and do not copy semantic diagnostics, since all changed files need to be re-evaluated addFileToChangeSet(state, sourceFilePath); @@ -386,9 +412,9 @@ function createBuilderProgramState(newProgram: Program, oldState: Readonly !!ref.prepend)) state.programEmitPending = getBuilderFileEmit(compilerOptions); + if (some(newProgram.getProjectReferences(), ref => !!ref.prepend)) { + state.programEmitPending = getBuilderFileEmit(compilerOptions); + } } return state; } @@ -467,22 +498,31 @@ function addFileToChangeSet(state: BuilderProgramState, path: Path) { * Covert to Emit signature based on oldOptions and EmitSignature format * If d.ts map options differ then swap the format, otherwise use as is */ -function getEmitSignatureFromOldSignature(options: CompilerOptions, oldOptions: CompilerOptions, oldEmitSignature: EmitSignature): EmitSignature { - return !!options.declarationMap === !!oldOptions.declarationMap ? +function getEmitSignatureFromOldSignature( + options: CompilerOptions, + oldOptions: CompilerOptions, + oldEmitSignature: EmitSignature, +): EmitSignature { + return !!options.declarationMap === !!oldOptions.declarationMap // Use same format of signature - oldEmitSignature : + ? oldEmitSignature // Convert to different format - isString(oldEmitSignature) ? [oldEmitSignature] : oldEmitSignature[0]; + : isString(oldEmitSignature) ? [oldEmitSignature] : oldEmitSignature[0]; } function repopulateDiagnostics(diagnostics: readonly Diagnostic[], newProgram: Program): readonly Diagnostic[] { if (!diagnostics.length) return diagnostics; return sameMap(diagnostics, diag => { if (isString(diag.messageText)) return diag; - const repopulatedChain = convertOrRepopulateDiagnosticMessageChain(diag.messageText, diag.file, newProgram, chain => chain.repopulateInfo?.()); - return repopulatedChain === diag.messageText ? - diag : - { ...diag, messageText: repopulatedChain }; + const repopulatedChain = convertOrRepopulateDiagnosticMessageChain( + diag.messageText, + diag.file, + newProgram, + chain => chain.repopulateInfo?.(), + ); + return repopulatedChain === diag.messageText + ? diag + : { ...diag, messageText: repopulatedChain }; }); } @@ -495,56 +535,97 @@ function convertOrRepopulateDiagnosticMessageChain( +function convertOrRepopulateDiagnosticMessageChainArray< + T extends DiagnosticMessageChain | ReusableDiagnosticMessageChain, +>( array: T[] | undefined, sourceFile: SourceFile | undefined, newProgram: Program, repopulateInfo: (chain: T) => RepopulateDiagnosticChainInfo | undefined, ): DiagnosticMessageChain[] | undefined { - return sameMap(array, chain => convertOrRepopulateDiagnosticMessageChain(chain, sourceFile, newProgram, repopulateInfo)); + return sameMap( + array, + chain => convertOrRepopulateDiagnosticMessageChain(chain, sourceFile, newProgram, repopulateInfo), + ); } function convertToDiagnostics(diagnostics: readonly ReusableDiagnostic[], newProgram: Program): readonly Diagnostic[] { if (!diagnostics.length) return emptyArray; let buildInfoDirectory: string | undefined; return diagnostics.map(diagnostic => { - const result: Diagnostic = convertToDiagnosticRelatedInformation(diagnostic, newProgram, toPathInBuildInfoDirectory); + const result: Diagnostic = convertToDiagnosticRelatedInformation( + diagnostic, + newProgram, + toPathInBuildInfoDirectory, + ); result.reportsUnnecessary = diagnostic.reportsUnnecessary; result.reportsDeprecated = diagnostic.reportDeprecated; result.source = diagnostic.source; result.skippedOn = diagnostic.skippedOn; const { relatedInformation } = diagnostic; - result.relatedInformation = relatedInformation ? - relatedInformation.length ? - relatedInformation.map(r => convertToDiagnosticRelatedInformation(r, newProgram, toPathInBuildInfoDirectory)) : - [] : - undefined; + result.relatedInformation = relatedInformation + ? relatedInformation.length + ? relatedInformation.map(r => + convertToDiagnosticRelatedInformation(r, newProgram, toPathInBuildInfoDirectory) + ) + : [] + : undefined; return result; }); function toPathInBuildInfoDirectory(path: string) { - buildInfoDirectory ??= getDirectoryPath(getNormalizedAbsolutePath(getTsBuildInfoEmitOutputFilePath(newProgram.getCompilerOptions())!, newProgram.getCurrentDirectory())); + buildInfoDirectory ??= getDirectoryPath( + getNormalizedAbsolutePath( + getTsBuildInfoEmitOutputFilePath(newProgram.getCompilerOptions())!, + newProgram.getCurrentDirectory(), + ), + ); return toPath(path, buildInfoDirectory, newProgram.getCanonicalFileName); } } -function convertToDiagnosticRelatedInformation(diagnostic: ReusableDiagnosticRelatedInformation, newProgram: Program, toPath: (path: string) => Path): DiagnosticRelatedInformation { +function convertToDiagnosticRelatedInformation( + diagnostic: ReusableDiagnosticRelatedInformation, + newProgram: Program, + toPath: (path: string) => Path, +): DiagnosticRelatedInformation { const { file } = diagnostic; const sourceFile = file ? newProgram.getSourceFileByPath(toPath(file)) : undefined; return { ...diagnostic, file: sourceFile, - messageText: isString(diagnostic.messageText) ? - diagnostic.messageText : - convertOrRepopulateDiagnosticMessageChain(diagnostic.messageText, sourceFile, newProgram, chain => (chain as ReusableRepopulateModuleNotFoundChain).info), + messageText: isString(diagnostic.messageText) + ? diagnostic.messageText + : convertOrRepopulateDiagnosticMessageChain( + diagnostic.messageText, + sourceFile, + newProgram, + chain => (chain as ReusableRepopulateModuleNotFoundChain).info, + ), }; } @@ -587,7 +668,10 @@ function restoreBuilderProgramEmitState(state: BuilderProgramState, savedEmitSta * Verifies that source file is ok to be used in calls that arent handled by next */ function assertSourceFileOkWithoutNextAffectedCall(state: BuilderProgramState, sourceFile: SourceFile | undefined) { - Debug.assert(!sourceFile || !state.affectedFiles || state.affectedFiles[state.affectedFilesIndex! - 1] !== sourceFile || !state.semanticDiagnosticsPerFile!.has(sourceFile.resolvedPath)); + Debug.assert( + !sourceFile || !state.affectedFiles || state.affectedFiles[state.affectedFilesIndex! - 1] !== sourceFile + || !state.semanticDiagnosticsPerFile!.has(sourceFile.resolvedPath), + ); } /** @@ -611,7 +695,11 @@ function getNextAffectedFile( if (!seenAffectedFiles.has(affectedFile.resolvedPath)) { // Set the next affected file as seen and remove the cached semantic diagnostics state.affectedFilesIndex = affectedFilesIndex; - addToAffectedFilesPendingEmit(state, affectedFile.resolvedPath, getBuilderFileEmit(state.compilerOptions)); + addToAffectedFilesPendingEmit( + state, + affectedFile.resolvedPath, + getBuilderFileEmit(state.compilerOptions), + ); handleDtsMayChangeOfAffectedFile( state, affectedFile, @@ -697,9 +785,9 @@ function removeDiagnosticsOfLibraryFiles(state: BuilderProgramState) { const program = Debug.checkDefined(state.program); const options = program.getCompilerOptions(); forEach(program.getSourceFiles(), f => - program.isSourceFileDefaultLibrary(f) && - !skipTypeChecking(f, options, program) && - removeSemanticDiagnosticsOf(state, f.resolvedPath)); + program.isSourceFileDefaultLibrary(f) + && !skipTypeChecking(f, options, program) + && removeSemanticDiagnosticsOf(state, f.resolvedPath)); } } @@ -770,7 +858,11 @@ function handleDtsMayChangeOf( ); // If not dts emit, nothing more to do if (getEmitDeclarations(state.compilerOptions)) { - addToAffectedFilesPendingEmit(state, path, state.compilerOptions.declarationMap ? BuilderFileEmit.AllDts : BuilderFileEmit.Dts); + addToAffectedFilesPendingEmit( + state, + path, + state.compilerOptions.declarationMap ? BuilderFileEmit.AllDts : BuilderFileEmit.Dts, + ); } } } @@ -896,8 +988,8 @@ function handleDtsMayChangeOfFileAndExportsOfFile( // Remove diagnostics of files that import this file (without going to exports of referencing files) state.referencedMap!.getKeys(filePath)?.forEach(referencingFilePath => - !seenFileAndExportsOfFile.has(referencingFilePath) && // Not already removed diagnostic file - handleDtsMayChangeOf( // Dont add to seen since this is not yet done with the export removal + !seenFileAndExportsOfFile.has(referencingFilePath) // Not already removed diagnostic file + && handleDtsMayChangeOf( // Dont add to seen since this is not yet done with the export removal state, referencingFilePath, cancellationToken, @@ -911,7 +1003,11 @@ function handleDtsMayChangeOfFileAndExportsOfFile( * Gets semantic diagnostics for the file which are * bindAndCheckDiagnostics (from cache) and program diagnostics */ -function getSemanticDiagnosticsOfFile(state: BuilderProgramState, sourceFile: SourceFile, cancellationToken?: CancellationToken): readonly Diagnostic[] { +function getSemanticDiagnosticsOfFile( + state: BuilderProgramState, + sourceFile: SourceFile, + cancellationToken?: CancellationToken, +): readonly Diagnostic[] { return concatenate( getBinderAndCheckerDiagnosticsOfFile(state, sourceFile, cancellationToken), Debug.checkDefined(state.program).getProgramDiagnostics(sourceFile), @@ -922,7 +1018,11 @@ function getSemanticDiagnosticsOfFile(state: BuilderProgramState, sourceFile: So * Gets the binder and checker diagnostics either from cache if present, or otherwise from program and caches it * Note that it is assumed that when asked about binder and checker diagnostics, the file has been taken out of affected files/changed file set */ -function getBinderAndCheckerDiagnosticsOfFile(state: BuilderProgramState, sourceFile: SourceFile, cancellationToken?: CancellationToken): readonly Diagnostic[] { +function getBinderAndCheckerDiagnosticsOfFile( + state: BuilderProgramState, + sourceFile: SourceFile, + cancellationToken?: CancellationToken, +): readonly Diagnostic[] { const path = sourceFile.resolvedPath; if (state.semanticDiagnosticsPerFile) { const cachedDiagnostics = state.semanticDiagnosticsPerFile.get(path); @@ -945,7 +1045,10 @@ export type ProgramBuildInfoFileId = number & { __programBuildInfoFileIdBrand: a /** @internal */ export type ProgramBuildInfoFileIdListId = number & { __programBuildInfoFileIdListIdBrand: any; }; /** @internal */ -export type ProgramBuildInfoDiagnostic = ProgramBuildInfoFileId | [fileId: ProgramBuildInfoFileId, diagnostics: readonly ReusableDiagnostic[]]; +export type ProgramBuildInfoDiagnostic = ProgramBuildInfoFileId | [ + fileId: ProgramBuildInfoFileId, + diagnostics: readonly ReusableDiagnostic[], +]; /** * fileId if pending emit is same as what compilerOptions suggest * [fileId] if pending emit is only dts file emit @@ -953,9 +1056,15 @@ export type ProgramBuildInfoDiagnostic = ProgramBuildInfoFileId | [fileId: Progr * * @internal */ -export type ProgramBuilderInfoFilePendingEmit = ProgramBuildInfoFileId | [fileId: ProgramBuildInfoFileId] | [fileId: ProgramBuildInfoFileId, emitKind: BuilderFileEmit]; +export type ProgramBuilderInfoFilePendingEmit = ProgramBuildInfoFileId | [fileId: ProgramBuildInfoFileId] | [ + fileId: ProgramBuildInfoFileId, + emitKind: BuilderFileEmit, +]; /** @internal */ -export type ProgramBuildInfoReferencedMap = [fileId: ProgramBuildInfoFileId, fileIdListId: ProgramBuildInfoFileIdListId][]; +export type ProgramBuildInfoReferencedMap = [ + fileId: ProgramBuildInfoFileId, + fileIdListId: ProgramBuildInfoFileIdListId, +][]; /** @internal */ export type ProgramMultiFileEmitBuildInfoBuilderStateFileInfo = Omit & { /** @@ -972,7 +1081,10 @@ export type ProgramMultiFileEmitBuildInfoBuilderStateFileInfo = Omit(); const root: ProgramBuildInfoRoot[] = []; @@ -1052,9 +1167,14 @@ function getBuildInfo(state: BuilderProgramState, bundle: BundleBuildInfo | unde // Ensure fileId const fileId = toFileId(key); tryAddRoot(key, fileId); - return value.impliedFormat ? - { version: value.version, impliedFormat: value.impliedFormat, signature: undefined, affectsGlobalScope: undefined } : - value.version; + return value.impliedFormat + ? { + version: value.version, + impliedFormat: value.impliedFormat, + signature: undefined, + affectsGlobalScope: undefined, + } + : value.version; }); const program: ProgramBundleEmitBuildInfo = { fileNames, @@ -1063,11 +1183,11 @@ function getBuildInfo(state: BuilderProgramState, bundle: BundleBuildInfo | unde options: convertToProgramBuildInfoCompilerOptions(state.compilerOptions), outSignature: state.outSignature, latestChangedDtsFile, - pendingEmit: !state.programEmitPending ? - undefined : // Pending is undefined or None is encoded as undefined - state.programEmitPending === getBuilderFileEmit(state.compilerOptions) ? - false : // Pending emit is same as deteremined by compilerOptions - state.programEmitPending, // Actual value + pendingEmit: !state.programEmitPending + ? undefined // Pending is undefined or None is encoded as undefined + : state.programEmitPending === getBuilderFileEmit(state.compilerOptions) + ? false // Pending emit is same as deteremined by compilerOptions + : state.programEmitPending, // Actual value }; // Complete the bundle information if we are doing partial emit (only js or only dts) const { js, dts, commonSourceDirectory, sourceFiles } = bundle!; @@ -1096,28 +1216,47 @@ function getBuildInfo(state: BuilderProgramState, bundle: BundleBuildInfo | unde const emitSignature = state.emitSignatures?.get(key); if (emitSignature !== actualSignature) { (emitSignatures ||= []).push( - emitSignature === undefined ? - fileId : // There is no emit, encode as false + emitSignature === undefined + ? fileId // There is no emit, encode as false // fileId, signature: emptyArray if signature only differs in dtsMap option than our own compilerOptions otherwise EmitSignature - [fileId, !isString(emitSignature) && emitSignature[0] === actualSignature ? emptyArray as [] : emitSignature], + : [ + fileId, + !isString(emitSignature) && emitSignature[0] === actualSignature ? emptyArray as [] + : emitSignature, + ], ); } } } - return value.version === actualSignature ? - value.affectsGlobalScope || value.impliedFormat ? + return value.version === actualSignature + ? value.affectsGlobalScope || value.impliedFormat // If file version is same as signature, dont serialize signature - { version: value.version, signature: undefined, affectsGlobalScope: value.affectsGlobalScope, impliedFormat: value.impliedFormat } : + ? { + version: value.version, + signature: undefined, + affectsGlobalScope: value.affectsGlobalScope, + impliedFormat: value.impliedFormat, + } // If file info only contains version and signature and both are same we can just write string - value.version : - actualSignature !== undefined ? // If signature is not same as version, encode signature in the fileInfo - oldSignature === undefined ? + : value.version + : actualSignature !== undefined // If signature is not same as version, encode signature in the fileInfo + ? oldSignature === undefined // If we havent computed signature, use fileInfo as is - value : + ? value // Serialize fileInfo with new updated signature - { version: value.version, signature: actualSignature, affectsGlobalScope: value.affectsGlobalScope, impliedFormat: value.impliedFormat } : + : { + version: value.version, + signature: actualSignature, + affectsGlobalScope: value.affectsGlobalScope, + impliedFormat: value.impliedFormat, + } // Signature of the FileInfo is undefined, serialize it as false - { version: value.version, signature: false, affectsGlobalScope: value.affectsGlobalScope, impliedFormat: value.impliedFormat }; + : { + version: value.version, + signature: false, + affectsGlobalScope: value.affectsGlobalScope, + impliedFormat: value.impliedFormat, + }; }); let referencedMap: ProgramBuildInfoReferencedMap | undefined; @@ -1130,13 +1269,20 @@ function getBuildInfo(state: BuilderProgramState, bundle: BundleBuildInfo | unde let exportedModulesMap: ProgramBuildInfoReferencedMap | undefined; if (state.exportedModulesMap) { - exportedModulesMap = mapDefined(arrayFrom(state.exportedModulesMap.keys()).sort(compareStringsCaseSensitive), key => { - const oldValue = state.oldExportedModulesMap?.get(key); - // Not in temporary cache, use existing value - if (oldValue === undefined) return [toFileId(key), toFileIdListId(state.exportedModulesMap!.getValues(key)!)]; - if (oldValue) return [toFileId(key), toFileIdListId(oldValue)]; - return undefined; - }); + exportedModulesMap = mapDefined( + arrayFrom(state.exportedModulesMap.keys()).sort(compareStringsCaseSensitive), + key => { + const oldValue = state.oldExportedModulesMap?.get(key); + // Not in temporary cache, use existing value + if (oldValue === undefined) { + return [toFileId(key), toFileIdListId(state.exportedModulesMap!.getValues(key)!)]; + } + if (oldValue) { + return [toFileId(key), toFileIdListId(oldValue)]; + } + return undefined; + }, + ); } let semanticDiagnosticsPerFile: ProgramBuildInfoDiagnostic[] | undefined; @@ -1144,12 +1290,12 @@ function getBuildInfo(state: BuilderProgramState, bundle: BundleBuildInfo | unde for (const key of arrayFrom(state.semanticDiagnosticsPerFile.keys()).sort(compareStringsCaseSensitive)) { const value = state.semanticDiagnosticsPerFile.get(key)!; (semanticDiagnosticsPerFile ||= []).push( - value.length ? - [ + value.length + ? [ toFileId(key), convertToReusableDiagnostics(value, relativeToBuildInfo), - ] : - toFileId(key), + ] + : toFileId(key), ); } } @@ -1164,11 +1310,11 @@ function getBuildInfo(state: BuilderProgramState, bundle: BundleBuildInfo | unde if (!file || !sourceFileMayBeEmitted(file, state.program!)) continue; const fileId = toFileId(path), pendingEmit = state.affectedFilesPendingEmit.get(path)!; (affectedFilesPendingEmit ||= []).push( - pendingEmit === fullEmitForOptions ? - fileId : // Pending full emit per options - pendingEmit === BuilderFileEmit.Dts ? - [fileId] : // Pending on Dts only - [fileId, pendingEmit], // Anything else + pendingEmit === fullEmitForOptions + ? fileId // Pending full emit per options + : pendingEmit === BuilderFileEmit.Dts + ? [fileId] // Pending on Dts only + : [fileId, pendingEmit], // Anything else ); } } @@ -1202,7 +1348,9 @@ function getBuildInfo(state: BuilderProgramState, bundle: BundleBuildInfo | unde } function relativeToBuildInfo(path: string) { - return ensurePathIsNonModuleName(getRelativePathFromDirectory(buildInfoDirectory, path, state.program!.getCanonicalFileName)); + return ensurePathIsNonModuleName( + getRelativePathFromDirectory(buildInfoDirectory, path, state.program!.getCanonicalFileName), + ); } function toFileId(path: Path): ProgramBuildInfoFileId { @@ -1220,14 +1368,19 @@ function getBuildInfo(state: BuilderProgramState, bundle: BundleBuildInfo | unde let fileIdListId = fileNamesToFileIdListId?.get(key); if (fileIdListId === undefined) { (fileIdsList ||= []).push(fileIds); - (fileNamesToFileIdListId ||= new Map()).set(key, fileIdListId = fileIdsList.length as ProgramBuildInfoFileIdListId); + (fileNamesToFileIdListId ||= new Map()).set( + key, + fileIdListId = fileIdsList.length as ProgramBuildInfoFileIdListId, + ); } return fileIdListId; } function tryAddRoot(path: Path, fileId: ProgramBuildInfoFileId) { const file = state.program!.getSourceFile(path)!; - if (!state.program!.getFileIncludeReasons().get(file.path)!.some(r => r.kind === FileIncludeKind.RootFile)) return; + if (!state.program!.getFileIncludeReasons().get(file.path)!.some(r => r.kind === FileIncludeKind.RootFile)) { + return; + } // First fileId as is if (!root.length) return root.push(fileId); const last = root[root.length - 1]; @@ -1264,7 +1417,11 @@ function getBuildInfo(state: BuilderProgramState, bundle: BundleBuildInfo | unde } } -function convertToReusableCompilerOptionValue(option: CommandLineOption | undefined, value: CompilerOptionsValue, relativeToBuildInfo: (path: string) => string) { +function convertToReusableCompilerOptionValue( + option: CommandLineOption | undefined, + value: CompilerOptionsValue, + relativeToBuildInfo: (path: string) => string, +) { if (option) { Debug.assert(option.type !== "listOrElement"); if (option.type === "list") { @@ -1280,30 +1437,40 @@ function convertToReusableCompilerOptionValue(option: CommandLineOption | undefi return value; } -function convertToReusableDiagnostics(diagnostics: readonly Diagnostic[], relativeToBuildInfo: (path: string) => string): readonly ReusableDiagnostic[] { +function convertToReusableDiagnostics( + diagnostics: readonly Diagnostic[], + relativeToBuildInfo: (path: string) => string, +): readonly ReusableDiagnostic[] { Debug.assert(!!diagnostics.length); return diagnostics.map(diagnostic => { - const result: ReusableDiagnostic = convertToReusableDiagnosticRelatedInformation(diagnostic, relativeToBuildInfo); + const result: ReusableDiagnostic = convertToReusableDiagnosticRelatedInformation( + diagnostic, + relativeToBuildInfo, + ); result.reportsUnnecessary = diagnostic.reportsUnnecessary; result.reportDeprecated = diagnostic.reportsDeprecated; result.source = diagnostic.source; result.skippedOn = diagnostic.skippedOn; const { relatedInformation } = diagnostic; - result.relatedInformation = relatedInformation ? - relatedInformation.length ? - relatedInformation.map(r => convertToReusableDiagnosticRelatedInformation(r, relativeToBuildInfo)) : - [] : - undefined; + result.relatedInformation = relatedInformation + ? relatedInformation.length + ? relatedInformation.map(r => convertToReusableDiagnosticRelatedInformation(r, relativeToBuildInfo)) + : [] + : undefined; return result; }); } -function convertToReusableDiagnosticRelatedInformation(diagnostic: DiagnosticRelatedInformation, relativeToBuildInfo: (path: string) => string): ReusableDiagnosticRelatedInformation { +function convertToReusableDiagnosticRelatedInformation( + diagnostic: DiagnosticRelatedInformation, + relativeToBuildInfo: (path: string) => string, +): ReusableDiagnosticRelatedInformation { const { file } = diagnostic; return { ...diagnostic, file: file ? relativeToBuildInfo(file.resolvedPath) : undefined, - messageText: isString(diagnostic.messageText) ? diagnostic.messageText : convertToReusableDiagnosticMessageChain(diagnostic.messageText), + messageText: isString(diagnostic.messageText) ? diagnostic.messageText + : convertToReusableDiagnosticMessageChain(diagnostic.messageText), }; } @@ -1318,7 +1485,9 @@ function convertToReusableDiagnosticMessageChain(chain: DiagnosticMessageChain): return next === chain.next ? chain : { ...chain, next }; } -function convertToReusableDiagnosticMessageChainArray(array: DiagnosticMessageChain[] | undefined): ReusableDiagnosticMessageChain[] | undefined { +function convertToReusableDiagnosticMessageChainArray( + array: DiagnosticMessageChain[] | undefined, +): ReusableDiagnosticMessageChain[] | undefined { if (!array) return array; return forEach(array, (chain, index) => { const reusable = convertToReusableDiagnosticMessageChain(chain); @@ -1347,7 +1516,14 @@ export interface BuilderCreationParameters { } /** @internal */ -export function getBuilderCreationParameters(newProgramOrRootNames: Program | readonly string[] | undefined, hostOrOptions: BuilderProgramHost | CompilerOptions | undefined, oldProgramOrHost?: BuilderProgram | CompilerHost, configFileParsingDiagnosticsOrOldProgram?: readonly Diagnostic[] | BuilderProgram, configFileParsingDiagnostics?: readonly Diagnostic[], projectReferences?: readonly ProjectReference[]): BuilderCreationParameters { +export function getBuilderCreationParameters( + newProgramOrRootNames: Program | readonly string[] | undefined, + hostOrOptions: BuilderProgramHost | CompilerOptions | undefined, + oldProgramOrHost?: BuilderProgram | CompilerHost, + configFileParsingDiagnosticsOrOldProgram?: readonly Diagnostic[] | BuilderProgram, + configFileParsingDiagnostics?: readonly Diagnostic[], + projectReferences?: readonly ProjectReference[], +): BuilderCreationParameters { let host: BuilderProgramHost; let newProgram: Program; let oldProgram: BuilderProgram; @@ -1394,22 +1570,28 @@ export function computeSignatureWithDiagnostics( text = getTextHandlingSourceMapForSignature(text, data); let sourceFileDirectory: string | undefined; if (data?.diagnostics?.length) { - text += data.diagnostics.map(diagnostic => `${locationInfo(diagnostic)}${DiagnosticCategory[diagnostic.category]}${diagnostic.code}: ${flattenDiagnosticMessageText(diagnostic.messageText)}`).join("\n"); + text += data.diagnostics.map(diagnostic => + `${locationInfo(diagnostic)}${DiagnosticCategory[diagnostic.category]}${diagnostic.code}: ${ + flattenDiagnosticMessageText(diagnostic.messageText) + }` + ).join("\n"); } return (host.createHash ?? generateDjb2Hash)(text); function flattenDiagnosticMessageText(diagnostic: string | DiagnosticMessageChain | undefined): string { - return isString(diagnostic) ? - diagnostic : - diagnostic === undefined ? - "" : - !diagnostic.next ? - diagnostic.messageText : - diagnostic.messageText + diagnostic.next.map(flattenDiagnosticMessageText).join("\n"); + return isString(diagnostic) + ? diagnostic + : diagnostic === undefined + ? "" + : !diagnostic.next + ? diagnostic.messageText + : diagnostic.messageText + diagnostic.next.map(flattenDiagnosticMessageText).join("\n"); } function locationInfo(diagnostic: DiagnosticWithLocation) { - if (diagnostic.file.resolvedPath === sourceFile.resolvedPath) return `(${diagnostic.start},${diagnostic.length})`; + if (diagnostic.file.resolvedPath === sourceFile.resolvedPath) { + return `(${diagnostic.start},${diagnostic.length})`; + } if (sourceFileDirectory === undefined) sourceFileDirectory = getDirectoryPath(sourceFile.resolvedPath); return `${ ensurePathIsNonModuleName(getRelativePathFromDirectory( @@ -1427,14 +1609,26 @@ export function computeSignature(text: string, host: HostForComputeHash, data?: } /** @internal */ -export function createBuilderProgram(kind: BuilderProgramKind.SemanticDiagnosticsBuilderProgram, builderCreationParameters: BuilderCreationParameters): SemanticDiagnosticsBuilderProgram; +export function createBuilderProgram( + kind: BuilderProgramKind.SemanticDiagnosticsBuilderProgram, + builderCreationParameters: BuilderCreationParameters, +): SemanticDiagnosticsBuilderProgram; /** @internal */ -export function createBuilderProgram(kind: BuilderProgramKind.EmitAndSemanticDiagnosticsBuilderProgram, builderCreationParameters: BuilderCreationParameters): EmitAndSemanticDiagnosticsBuilderProgram; +export function createBuilderProgram( + kind: BuilderProgramKind.EmitAndSemanticDiagnosticsBuilderProgram, + builderCreationParameters: BuilderCreationParameters, +): EmitAndSemanticDiagnosticsBuilderProgram; /** @internal */ -export function createBuilderProgram(kind: BuilderProgramKind, { newProgram, host, oldProgram, configFileParsingDiagnostics }: BuilderCreationParameters) { +export function createBuilderProgram( + kind: BuilderProgramKind, + { newProgram, host, oldProgram, configFileParsingDiagnostics }: BuilderCreationParameters, +) { // Return same program if underlying program doesnt change let oldState = oldProgram && oldProgram.getState(); - if (oldState && newProgram === oldState.program && configFileParsingDiagnostics === newProgram.getConfigFileParsingDiagnostics()) { + if ( + oldState && newProgram === oldState.program + && configFileParsingDiagnostics === newProgram.getConfigFileParsingDiagnostics() + ) { newProgram = undefined!; // TODO: GH#18217 oldState = undefined; return oldProgram; @@ -1454,16 +1648,19 @@ export function createBuilderProgram(kind: BuilderProgramKind, { newProgram, hos builderProgram.saveEmitState = () => backupBuilderProgramEmitState(state); builderProgram.restoreEmitState = saved => restoreBuilderProgramEmitState(state, saved); builderProgram.hasChangedEmitSignature = () => !!state.hasChangedEmitSignature; - builderProgram.getAllDependencies = sourceFile => BuilderState.getAllDependencies(state, Debug.checkDefined(state.program), sourceFile); + builderProgram.getAllDependencies = sourceFile => + BuilderState.getAllDependencies(state, Debug.checkDefined(state.program), sourceFile); builderProgram.getSemanticDiagnostics = getSemanticDiagnostics; builderProgram.emit = emit; builderProgram.releaseProgram = () => releaseCache(state); if (kind === BuilderProgramKind.SemanticDiagnosticsBuilderProgram) { - (builderProgram as SemanticDiagnosticsBuilderProgram).getSemanticDiagnosticsOfNextAffectedFile = getSemanticDiagnosticsOfNextAffectedFile; + (builderProgram as SemanticDiagnosticsBuilderProgram).getSemanticDiagnosticsOfNextAffectedFile = + getSemanticDiagnosticsOfNextAffectedFile; } else if (kind === BuilderProgramKind.EmitAndSemanticDiagnosticsBuilderProgram) { - (builderProgram as EmitAndSemanticDiagnosticsBuilderProgram).getSemanticDiagnosticsOfNextAffectedFile = getSemanticDiagnosticsOfNextAffectedFile; + (builderProgram as EmitAndSemanticDiagnosticsBuilderProgram).getSemanticDiagnosticsOfNextAffectedFile = + getSemanticDiagnosticsOfNextAffectedFile; (builderProgram as EmitAndSemanticDiagnosticsBuilderProgram).emitNextAffectedFile = emitNextAffectedFile; builderProgram.emitBuildInfo = emitBuildInfo; } @@ -1475,7 +1672,10 @@ export function createBuilderProgram(kind: BuilderProgramKind, { newProgram, hos function emitBuildInfo(writeFile?: WriteFileCallback, cancellationToken?: CancellationToken): EmitResult { if (state.buildInfoEmitPending) { - const result = Debug.checkDefined(state.program).emitBuildInfo(writeFile || maybeBind(host, host.writeFile), cancellationToken); + const result = Debug.checkDefined(state.program).emitBuildInfo( + writeFile || maybeBind(host, host.writeFile), + cancellationToken, + ); state.buildInfoEmitPending = false; return result; } @@ -1487,11 +1687,16 @@ export function createBuilderProgram(kind: BuilderProgramKind, { newProgram, hos * The first of writeFile if provided, writeFile of BuilderProgramHost if provided, writeFile of compiler host * in that order would be used to write the files */ - function emitNextAffectedFile(writeFile?: WriteFileCallback, cancellationToken?: CancellationToken, emitOnlyDtsFiles?: boolean, customTransformers?: CustomTransformers): AffectedFileResult { + function emitNextAffectedFile( + writeFile?: WriteFileCallback, + cancellationToken?: CancellationToken, + emitOnlyDtsFiles?: boolean, + customTransformers?: CustomTransformers, + ): AffectedFileResult { let affected = getNextAffectedFile(state, cancellationToken, host); const programEmitKind = getBuilderFileEmit(state.compilerOptions); - let emitKind: BuilderFileEmit = emitOnlyDtsFiles ? - programEmitKind & BuilderFileEmit.AllDts : programEmitKind; + let emitKind: BuilderFileEmit = emitOnlyDtsFiles + ? programEmitKind & BuilderFileEmit.AllDts : programEmitKind; if (!affected) { if (!outFile(state.compilerOptions)) { const pendingAffectedFile = getNextAffectedFilePendingEmit(state, emitOnlyDtsFiles); @@ -1499,7 +1704,10 @@ export function createBuilderProgram(kind: BuilderProgramKind, { newProgram, hos // Emit buildinfo if pending if (!state.buildInfoEmitPending) return undefined; const affected = state.program!; - const result = affected.emitBuildInfo(writeFile || maybeBind(host, host.writeFile), cancellationToken); + const result = affected.emitBuildInfo( + writeFile || maybeBind(host, host.writeFile), + cancellationToken, + ); state.buildInfoEmitPending = false; return { result, affected }; } @@ -1521,11 +1729,11 @@ export function createBuilderProgram(kind: BuilderProgramKind, { newProgram, hos if (emitKind & BuilderFileEmit.AllDts) emitOnly = emitOnly === undefined ? EmitOnly.Dts : undefined; if (affected === state.program) { // Set up programEmit before calling emit so that its set in buildInfo - state.programEmitPending = state.changedFilesSet.size ? - getPendingEmitKind(programEmitKind, emitKind) : - state.programEmitPending ? - getPendingEmitKind(state.programEmitPending, emitKind) : - undefined; + state.programEmitPending = state.changedFilesSet.size + ? getPendingEmitKind(programEmitKind, emitKind) + : state.programEmitPending + ? getPendingEmitKind(state.programEmitPending, emitKind) + : undefined; } // Actual emit const result = state.program!.emit( @@ -1545,9 +1753,12 @@ export function createBuilderProgram(kind: BuilderProgramKind, { newProgram, hos // Update the pendingEmit for the file const existing = state.seenEmittedFiles?.get(affectedSourceFile.resolvedPath) || BuilderFileEmit.None; (state.seenEmittedFiles ??= new Map()).set(affectedSourceFile.resolvedPath, emitKind | existing); - const existingPending = state.affectedFilesPendingEmit?.get(affectedSourceFile.resolvedPath) || programEmitKind; + const existingPending = state.affectedFilesPendingEmit?.get(affectedSourceFile.resolvedPath) + || programEmitKind; const pendingKind = getPendingEmitKind(existingPending, emitKind | existing); - if (pendingKind) (state.affectedFilesPendingEmit ??= new Map()).set(affectedSourceFile.resolvedPath, pendingKind); + if (pendingKind) { + (state.affectedFilesPendingEmit ??= new Map()).set(affectedSourceFile.resolvedPath, pendingKind); + } else state.affectedFilesPendingEmit?.delete(affectedSourceFile.resolvedPath); } else { @@ -1557,7 +1768,10 @@ export function createBuilderProgram(kind: BuilderProgramKind, { newProgram, hos return { result, affected }; } - function getWriteFileCallback(writeFile: WriteFileCallback | undefined, customTransformers: CustomTransformers | undefined): WriteFileCallback | undefined { + function getWriteFileCallback( + writeFile: WriteFileCallback | undefined, + customTransformers: CustomTransformers | undefined, + ): WriteFileCallback | undefined { if (!getEmitDeclarations(state.compilerOptions)) return writeFile || maybeBind(host, host.writeFile); return (fileName, text, writeByteOrderMark, onError, sourceFiles, data) => { if (isDeclarationFileName(fileName)) { @@ -1578,12 +1792,25 @@ export function createBuilderProgram(kind: BuilderProgramKind, { newProgram, hos // With d.ts diagnostics they are also part of the signature so emitSignature will be different from it since its just hash of d.ts if (!data?.diagnostics?.length) emitSignature = signature; if (signature !== file.version) { // Update it - if (host.storeFilesChangingSignatureDuringEmit) (state.filesChangingSignature ??= new Set()).add(file.resolvedPath); - if (state.exportedModulesMap) BuilderState.updateExportedModules(state, file, file.exportedModulesFromDeclarationEmit); + if (host.storeFilesChangingSignatureDuringEmit) { + (state.filesChangingSignature ??= new Set()).add(file.resolvedPath); + } + if (state.exportedModulesMap) { + BuilderState.updateExportedModules( + state, + file, + file.exportedModulesFromDeclarationEmit, + ); + } if (state.affectedFiles) { // Keep old signature so we know what to undo if cancellation happens const existing = state.oldSignatures?.get(file.resolvedPath); - if (existing === undefined) (state.oldSignatures ??= new Map()).set(file.resolvedPath, info.signature || false); + if (existing === undefined) { + (state.oldSignatures ??= new Map()).set( + file.resolvedPath, + info.signature || false, + ); + } info.signature = signature; } else { @@ -1619,8 +1846,12 @@ export function createBuilderProgram(kind: BuilderProgramKind, { newProgram, hos * Compare to existing computed signature and store it or handle the changes in d.ts map option from before * returning undefined means that, we dont need to emit this d.ts file since its contents didnt change */ - function handleNewSignature(oldSignatureFormat: EmitSignature | undefined, newSignature: string | undefined) { - const oldSignature = !oldSignatureFormat || isString(oldSignatureFormat) ? oldSignatureFormat : oldSignatureFormat[0]; + function handleNewSignature( + oldSignatureFormat: EmitSignature | undefined, + newSignature: string | undefined, + ) { + const oldSignature = !oldSignatureFormat || isString(oldSignatureFormat) ? oldSignatureFormat + : oldSignatureFormat[0]; newSignature ??= computeSignature(text, host, data); // Dont write dts files if they didn't change if (newSignature === oldSignature) { @@ -1651,7 +1882,13 @@ export function createBuilderProgram(kind: BuilderProgramKind, { newProgram, hos * The first of writeFile if provided, writeFile of BuilderProgramHost if provided, writeFile of compiler host * in that order would be used to write the files */ - function emit(targetSourceFile?: SourceFile, writeFile?: WriteFileCallback, cancellationToken?: CancellationToken, emitOnlyDtsFiles?: boolean, customTransformers?: CustomTransformers): EmitResult { + function emit( + targetSourceFile?: SourceFile, + writeFile?: WriteFileCallback, + cancellationToken?: CancellationToken, + emitOnlyDtsFiles?: boolean, + customTransformers?: CustomTransformers, + ): EmitResult { if (kind === BuilderProgramKind.EmitAndSemanticDiagnosticsBuilderProgram) { assertSourceFileOkWithoutNextAffectedCall(state, targetSourceFile); } @@ -1668,7 +1905,14 @@ export function createBuilderProgram(kind: BuilderProgramKind, { newProgram, hos let emittedFiles: string[] = []; let affectedEmitResult: AffectedFileResult; - while (affectedEmitResult = emitNextAffectedFile(writeFile, cancellationToken, emitOnlyDtsFiles, customTransformers)) { + while ( + affectedEmitResult = emitNextAffectedFile( + writeFile, + cancellationToken, + emitOnlyDtsFiles, + customTransformers, + ) + ) { emitSkipped = emitSkipped || affectedEmitResult.result.emitSkipped; diagnostics = addRange(diagnostics, affectedEmitResult.result.diagnostics); emittedFiles = addRange(emittedFiles, affectedEmitResult.result.emittedFiles); @@ -1699,7 +1943,10 @@ export function createBuilderProgram(kind: BuilderProgramKind, { newProgram, hos * Return the semantic diagnostics for the next affected file or undefined if iteration is complete * If provided ignoreSourceFile would be called before getting the diagnostics and would ignore the sourceFile if the returned value was true */ - function getSemanticDiagnosticsOfNextAffectedFile(cancellationToken?: CancellationToken, ignoreSourceFile?: (sourceFile: SourceFile) => boolean): AffectedFileResult { + function getSemanticDiagnosticsOfNextAffectedFile( + cancellationToken?: CancellationToken, + ignoreSourceFile?: (sourceFile: SourceFile) => boolean, + ): AffectedFileResult { while (true) { const affected = getNextAffectedFile(state, cancellationToken, host); let result; @@ -1734,7 +1981,10 @@ export function createBuilderProgram(kind: BuilderProgramKind, { newProgram, hos * In case of SemanticDiagnosticsBuilderProgram if the source file is not provided, * it will iterate through all the affected files, to ensure that cache stays valid and yet provide a way to get all semantic diagnostics */ - function getSemanticDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): readonly Diagnostic[] { + function getSemanticDiagnostics( + sourceFile?: SourceFile, + cancellationToken?: CancellationToken, + ): readonly Diagnostic[] { assertSourceFileOkWithoutNextAffectedCall(state, sourceFile); const compilerOptions = Debug.checkDefined(state.program).getCompilerOptions(); if (outFile(compilerOptions)) { @@ -1761,32 +2011,53 @@ export function createBuilderProgram(kind: BuilderProgramKind, { newProgram, hos } } -function addToAffectedFilesPendingEmit(state: BuilderProgramState, affectedFilePendingEmit: Path, kind: BuilderFileEmit) { +function addToAffectedFilesPendingEmit( + state: BuilderProgramState, + affectedFilePendingEmit: Path, + kind: BuilderFileEmit, +) { const existingKind = state.affectedFilesPendingEmit?.get(affectedFilePendingEmit) || BuilderFileEmit.None; (state.affectedFilesPendingEmit ??= new Map()).set(affectedFilePendingEmit, existingKind | kind); } /** @internal */ -export function toBuilderStateFileInfoForMultiEmit(fileInfo: ProgramMultiFileEmitBuildInfoFileInfo): BuilderState.FileInfo { - return isString(fileInfo) ? - { version: fileInfo, signature: fileInfo, affectsGlobalScope: undefined, impliedFormat: undefined } : - isString(fileInfo.signature) ? - fileInfo as BuilderState.FileInfo : - { version: fileInfo.version, signature: fileInfo.signature === false ? undefined : fileInfo.version, affectsGlobalScope: fileInfo.affectsGlobalScope, impliedFormat: fileInfo.impliedFormat }; +export function toBuilderStateFileInfoForMultiEmit( + fileInfo: ProgramMultiFileEmitBuildInfoFileInfo, +): BuilderState.FileInfo { + return isString(fileInfo) + ? { version: fileInfo, signature: fileInfo, affectsGlobalScope: undefined, impliedFormat: undefined } + : isString(fileInfo.signature) + ? fileInfo as BuilderState.FileInfo + : { + version: fileInfo.version, + signature: fileInfo.signature === false ? undefined : fileInfo.version, + affectsGlobalScope: fileInfo.affectsGlobalScope, + impliedFormat: fileInfo.impliedFormat, + }; } /** @internal */ -export function toBuilderFileEmit(value: ProgramBuilderInfoFilePendingEmit, fullEmitForOptions: BuilderFileEmit): BuilderFileEmit { +export function toBuilderFileEmit( + value: ProgramBuilderInfoFilePendingEmit, + fullEmitForOptions: BuilderFileEmit, +): BuilderFileEmit { return isNumber(value) ? fullEmitForOptions : value[1] || BuilderFileEmit.Dts; } /** @internal */ -export function toProgramEmitPending(value: ProgramBuildInfoBundlePendingEmit, options: CompilerOptions | undefined): BuilderFileEmit | undefined { +export function toProgramEmitPending( + value: ProgramBuildInfoBundlePendingEmit, + options: CompilerOptions | undefined, +): BuilderFileEmit | undefined { return !value ? getBuilderFileEmit(options || {}) : value; } /** @internal */ -export function createBuilderProgramUsingProgramBuildInfo(buildInfo: BuildInfo, buildInfoPath: string, host: ReadBuildProgramHost): EmitAndSemanticDiagnosticsBuilderProgram { +export function createBuilderProgramUsingProgramBuildInfo( + buildInfo: BuildInfo, + buildInfoPath: string, + host: ReadBuildProgramHost, +): EmitAndSemanticDiagnosticsBuilderProgram { const program = buildInfo.program!; const buildInfoDirectory = getDirectoryPath(getNormalizedAbsolutePath(buildInfoPath, host.getCurrentDirectory())); const getCanonicalFileName = createGetCanonicalFileName(host.useCaseSensitiveFileNames()); @@ -1794,26 +2065,38 @@ export function createBuilderProgramUsingProgramBuildInfo(buildInfo: BuildInfo, let state: ReusableBuilderProgramState; const filePaths = program.fileNames?.map(toPathInBuildInfoDirectory); let filePathsSetList: Set[] | undefined; - const latestChangedDtsFile = program.latestChangedDtsFile ? toAbsolutePath(program.latestChangedDtsFile) : undefined; + const latestChangedDtsFile = program.latestChangedDtsFile ? toAbsolutePath(program.latestChangedDtsFile) + : undefined; if (isProgramBundleEmitBuildInfo(program)) { const fileInfos = new Map(); program.fileInfos.forEach((fileInfo, index) => { const path = toFilePath(index + 1 as ProgramBuildInfoFileId); - fileInfos.set(path, isString(fileInfo) ? { version: fileInfo, signature: undefined, affectsGlobalScope: undefined, impliedFormat: undefined } : fileInfo); + fileInfos.set( + path, + isString(fileInfo) + ? { + version: fileInfo, + signature: undefined, + affectsGlobalScope: undefined, + impliedFormat: undefined, + } : fileInfo, + ); }); state = { fileInfos, compilerOptions: program.options ? convertToOptionsWithAbsolutePaths(program.options, toAbsolutePath) : {}, latestChangedDtsFile, outSignature: program.outSignature, - programEmitPending: program.pendingEmit === undefined ? undefined : toProgramEmitPending(program.pendingEmit, program.options), + programEmitPending: program.pendingEmit === undefined ? undefined + : toProgramEmitPending(program.pendingEmit, program.options), bundle: buildInfo.bundle, }; } else { filePathsSetList = program.fileIdsList?.map(fileIds => new Set(fileIds.map(toFilePath))); const fileInfos = new Map(); - const emitSignatures = program.options?.composite && !outFile(program.options) ? new Map() : undefined; + const emitSignatures = program.options?.composite && !outFile(program.options) ? new Map() + : undefined; program.fileInfos.forEach((fileInfo, index) => { const path = toFilePath(index + 1 as ProgramBuildInfoFileId); const stateFileInfo = toBuilderStateFileInfoForMultiEmit(fileInfo); @@ -1826,22 +2109,33 @@ export function createBuilderProgramUsingProgramBuildInfo(buildInfo: BuildInfo, const key = toFilePath(value[0]); emitSignatures!.set( key, - !isString(value[1]) && !value[1].length ? + !isString(value[1]) && !value[1].length // File signature is emit signature but differs in map - [emitSignatures!.get(key)! as string] : - value[1], + ? [emitSignatures!.get(key)! as string] + : value[1], ); } }); - const fullEmitForOptions = program.affectedFilesPendingEmit ? getBuilderFileEmit(program.options || {}) : undefined; + const fullEmitForOptions = program.affectedFilesPendingEmit ? getBuilderFileEmit(program.options || {}) + : undefined; state = { fileInfos, compilerOptions: program.options ? convertToOptionsWithAbsolutePaths(program.options, toAbsolutePath) : {}, referencedMap: toManyToManyPathMap(program.referencedMap), exportedModulesMap: toManyToManyPathMap(program.exportedModulesMap), - semanticDiagnosticsPerFile: program.semanticDiagnosticsPerFile && arrayToMap(program.semanticDiagnosticsPerFile, value => toFilePath(isNumber(value) ? value : value[0]), value => isNumber(value) ? emptyArray : value[1]), + semanticDiagnosticsPerFile: program.semanticDiagnosticsPerFile + && arrayToMap( + program.semanticDiagnosticsPerFile, + value => toFilePath(isNumber(value) ? value : value[0]), + value => isNumber(value) ? emptyArray : value[1], + ), hasReusableDiagnostic: true, - affectedFilesPendingEmit: program.affectedFilesPendingEmit && arrayToMap(program.affectedFilesPendingEmit, value => toFilePath(isNumber(value) ? value : value[0]), value => toBuilderFileEmit(value, fullEmitForOptions!)), + affectedFilesPendingEmit: program.affectedFilesPendingEmit + && arrayToMap( + program.affectedFilesPendingEmit, + value => toFilePath(isNumber(value) ? value : value[0]), + value => toBuilderFileEmit(value, fullEmitForOptions!), + ), changedFilesSet: new Set(map(program.changeFileSet, toFilePath)), latestChangedDtsFile, emitSignatures: emitSignatures?.size ? emitSignatures : undefined, @@ -1890,7 +2184,9 @@ export function createBuilderProgramUsingProgramBuildInfo(buildInfo: BuildInfo, return filePathsSetList![fileIdsListId - 1]; } - function toManyToManyPathMap(referenceMap: ProgramBuildInfoReferencedMap | undefined): BuilderState.ManyToManyPathMap | undefined { + function toManyToManyPathMap( + referenceMap: ProgramBuildInfoReferencedMap | undefined, + ): BuilderState.ManyToManyPathMap | undefined { if (!referenceMap) { return undefined; } @@ -1935,7 +2231,10 @@ export function getBuildInfoFileVersionMap( } /** @internal */ -export function createRedirectedBuilderProgram(getState: () => { program?: Program | undefined; compilerOptions: CompilerOptions; }, configFileParsingDiagnostics: readonly Diagnostic[]): BuilderProgram { +export function createRedirectedBuilderProgram( + getState: () => { program?: Program | undefined; compilerOptions: CompilerOptions; }, + configFileParsingDiagnostics: readonly Diagnostic[], +): BuilderProgram { return { getState: notImplemented, saveEmitState: noop as BuilderProgram["saveEmitState"], @@ -1949,10 +2248,14 @@ export function createRedirectedBuilderProgram(getState: () => { program?: Progr getOptionsDiagnostics: cancellationToken => getProgram().getOptionsDiagnostics(cancellationToken), getGlobalDiagnostics: cancellationToken => getProgram().getGlobalDiagnostics(cancellationToken), getConfigFileParsingDiagnostics: () => configFileParsingDiagnostics, - getSyntacticDiagnostics: (sourceFile, cancellationToken) => getProgram().getSyntacticDiagnostics(sourceFile, cancellationToken), - getDeclarationDiagnostics: (sourceFile, cancellationToken) => getProgram().getDeclarationDiagnostics(sourceFile, cancellationToken), - getSemanticDiagnostics: (sourceFile, cancellationToken) => getProgram().getSemanticDiagnostics(sourceFile, cancellationToken), - emit: (sourceFile, writeFile, cancellationToken, emitOnlyDts, customTransformers) => getProgram().emit(sourceFile, writeFile, cancellationToken, emitOnlyDts, customTransformers), + getSyntacticDiagnostics: (sourceFile, cancellationToken) => + getProgram().getSyntacticDiagnostics(sourceFile, cancellationToken), + getDeclarationDiagnostics: (sourceFile, cancellationToken) => + getProgram().getDeclarationDiagnostics(sourceFile, cancellationToken), + getSemanticDiagnostics: (sourceFile, cancellationToken) => + getProgram().getSemanticDiagnostics(sourceFile, cancellationToken), + emit: (sourceFile, writeFile, cancellationToken, emitOnlyDts, customTransformers) => + getProgram().emit(sourceFile, writeFile, cancellationToken, emitOnlyDts, customTransformers), emitBuildInfo: (writeFile, cancellationToken) => getProgram().emitBuildInfo(writeFile, cancellationToken), getAllDependencies: notImplemented, getCurrentDirectory: () => getProgram().getCurrentDirectory(), diff --git a/src/compiler/builderPublic.ts b/src/compiler/builderPublic.ts index 4cfcb731fb61c..a6ef2a942531f 100644 --- a/src/compiler/builderPublic.ts +++ b/src/compiler/builderPublic.ts @@ -100,7 +100,10 @@ export interface BuilderProgram { /** * Get the declaration diagnostics, for all source files if source file is not supplied */ - getDeclarationDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): readonly DiagnosticWithLocation[]; + getDeclarationDiagnostics( + sourceFile?: SourceFile, + cancellationToken?: CancellationToken, + ): readonly DiagnosticWithLocation[]; /** * Get all the dependencies of the file */ @@ -126,7 +129,13 @@ export interface BuilderProgram { * The first of writeFile if provided, writeFile of BuilderProgramHost if provided, writeFile of compiler host * in that order would be used to write the files */ - emit(targetSourceFile?: SourceFile, writeFile?: WriteFileCallback, cancellationToken?: CancellationToken, emitOnlyDtsFiles?: boolean, customTransformers?: CustomTransformers): EmitResult; + emit( + targetSourceFile?: SourceFile, + writeFile?: WriteFileCallback, + cancellationToken?: CancellationToken, + emitOnlyDtsFiles?: boolean, + customTransformers?: CustomTransformers, + ): EmitResult; /** @internal */ emitBuildInfo(writeFile?: WriteFileCallback, cancellationToken?: CancellationToken): EmitResult; /** @@ -145,7 +154,10 @@ export interface SemanticDiagnosticsBuilderProgram extends BuilderProgram { * Gets the semantic diagnostics from the program for the next affected file and caches it * Returns undefined if the iteration is complete */ - getSemanticDiagnosticsOfNextAffectedFile(cancellationToken?: CancellationToken, ignoreSourceFile?: (sourceFile: SourceFile) => boolean): AffectedFileResult; + getSemanticDiagnosticsOfNextAffectedFile( + cancellationToken?: CancellationToken, + ignoreSourceFile?: (sourceFile: SourceFile) => boolean, + ): AffectedFileResult; } /** @@ -158,34 +170,126 @@ export interface EmitAndSemanticDiagnosticsBuilderProgram extends SemanticDiagno * The first of writeFile if provided, writeFile of BuilderProgramHost if provided, writeFile of compiler host * in that order would be used to write the files */ - emitNextAffectedFile(writeFile?: WriteFileCallback, cancellationToken?: CancellationToken, emitOnlyDtsFiles?: boolean, customTransformers?: CustomTransformers): AffectedFileResult; + emitNextAffectedFile( + writeFile?: WriteFileCallback, + cancellationToken?: CancellationToken, + emitOnlyDtsFiles?: boolean, + customTransformers?: CustomTransformers, + ): AffectedFileResult; } /** * Create the builder to manage semantic diagnostics and cache them */ -export function createSemanticDiagnosticsBuilderProgram(newProgram: Program, host: BuilderProgramHost, oldProgram?: SemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: readonly Diagnostic[]): SemanticDiagnosticsBuilderProgram; -export function createSemanticDiagnosticsBuilderProgram(rootNames: readonly string[] | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: SemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: readonly Diagnostic[], projectReferences?: readonly ProjectReference[]): SemanticDiagnosticsBuilderProgram; -export function createSemanticDiagnosticsBuilderProgram(newProgramOrRootNames: Program | readonly string[] | undefined, hostOrOptions: BuilderProgramHost | CompilerOptions | undefined, oldProgramOrHost?: CompilerHost | SemanticDiagnosticsBuilderProgram, configFileParsingDiagnosticsOrOldProgram?: readonly Diagnostic[] | SemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: readonly Diagnostic[], projectReferences?: readonly ProjectReference[]) { - return createBuilderProgram(BuilderProgramKind.SemanticDiagnosticsBuilderProgram, getBuilderCreationParameters(newProgramOrRootNames, hostOrOptions, oldProgramOrHost, configFileParsingDiagnosticsOrOldProgram, configFileParsingDiagnostics, projectReferences)); +export function createSemanticDiagnosticsBuilderProgram( + newProgram: Program, + host: BuilderProgramHost, + oldProgram?: SemanticDiagnosticsBuilderProgram, + configFileParsingDiagnostics?: readonly Diagnostic[], +): SemanticDiagnosticsBuilderProgram; +export function createSemanticDiagnosticsBuilderProgram( + rootNames: readonly string[] | undefined, + options: CompilerOptions | undefined, + host?: CompilerHost, + oldProgram?: SemanticDiagnosticsBuilderProgram, + configFileParsingDiagnostics?: readonly Diagnostic[], + projectReferences?: readonly ProjectReference[], +): SemanticDiagnosticsBuilderProgram; +export function createSemanticDiagnosticsBuilderProgram( + newProgramOrRootNames: Program | readonly string[] | undefined, + hostOrOptions: BuilderProgramHost | CompilerOptions | undefined, + oldProgramOrHost?: CompilerHost | SemanticDiagnosticsBuilderProgram, + configFileParsingDiagnosticsOrOldProgram?: readonly Diagnostic[] | SemanticDiagnosticsBuilderProgram, + configFileParsingDiagnostics?: readonly Diagnostic[], + projectReferences?: readonly ProjectReference[], +) { + return createBuilderProgram( + BuilderProgramKind.SemanticDiagnosticsBuilderProgram, + getBuilderCreationParameters( + newProgramOrRootNames, + hostOrOptions, + oldProgramOrHost, + configFileParsingDiagnosticsOrOldProgram, + configFileParsingDiagnostics, + projectReferences, + ), + ); } /** * Create the builder that can handle the changes in program and iterate through changed files * to emit the those files and manage semantic diagnostics cache as well */ -export function createEmitAndSemanticDiagnosticsBuilderProgram(newProgram: Program, host: BuilderProgramHost, oldProgram?: EmitAndSemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: readonly Diagnostic[]): EmitAndSemanticDiagnosticsBuilderProgram; -export function createEmitAndSemanticDiagnosticsBuilderProgram(rootNames: readonly string[] | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: EmitAndSemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: readonly Diagnostic[], projectReferences?: readonly ProjectReference[]): EmitAndSemanticDiagnosticsBuilderProgram; -export function createEmitAndSemanticDiagnosticsBuilderProgram(newProgramOrRootNames: Program | readonly string[] | undefined, hostOrOptions: BuilderProgramHost | CompilerOptions | undefined, oldProgramOrHost?: CompilerHost | EmitAndSemanticDiagnosticsBuilderProgram, configFileParsingDiagnosticsOrOldProgram?: readonly Diagnostic[] | EmitAndSemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: readonly Diagnostic[], projectReferences?: readonly ProjectReference[]) { - return createBuilderProgram(BuilderProgramKind.EmitAndSemanticDiagnosticsBuilderProgram, getBuilderCreationParameters(newProgramOrRootNames, hostOrOptions, oldProgramOrHost, configFileParsingDiagnosticsOrOldProgram, configFileParsingDiagnostics, projectReferences)); +export function createEmitAndSemanticDiagnosticsBuilderProgram( + newProgram: Program, + host: BuilderProgramHost, + oldProgram?: EmitAndSemanticDiagnosticsBuilderProgram, + configFileParsingDiagnostics?: readonly Diagnostic[], +): EmitAndSemanticDiagnosticsBuilderProgram; +export function createEmitAndSemanticDiagnosticsBuilderProgram( + rootNames: readonly string[] | undefined, + options: CompilerOptions | undefined, + host?: CompilerHost, + oldProgram?: EmitAndSemanticDiagnosticsBuilderProgram, + configFileParsingDiagnostics?: readonly Diagnostic[], + projectReferences?: readonly ProjectReference[], +): EmitAndSemanticDiagnosticsBuilderProgram; +export function createEmitAndSemanticDiagnosticsBuilderProgram( + newProgramOrRootNames: Program | readonly string[] | undefined, + hostOrOptions: BuilderProgramHost | CompilerOptions | undefined, + oldProgramOrHost?: CompilerHost | EmitAndSemanticDiagnosticsBuilderProgram, + configFileParsingDiagnosticsOrOldProgram?: readonly Diagnostic[] | EmitAndSemanticDiagnosticsBuilderProgram, + configFileParsingDiagnostics?: readonly Diagnostic[], + projectReferences?: readonly ProjectReference[], +) { + return createBuilderProgram( + BuilderProgramKind.EmitAndSemanticDiagnosticsBuilderProgram, + getBuilderCreationParameters( + newProgramOrRootNames, + hostOrOptions, + oldProgramOrHost, + configFileParsingDiagnosticsOrOldProgram, + configFileParsingDiagnostics, + projectReferences, + ), + ); } /** * Creates a builder thats just abstraction over program and can be used with watch */ -export function createAbstractBuilder(newProgram: Program, host: BuilderProgramHost, oldProgram?: BuilderProgram, configFileParsingDiagnostics?: readonly Diagnostic[]): BuilderProgram; -export function createAbstractBuilder(rootNames: readonly string[] | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: BuilderProgram, configFileParsingDiagnostics?: readonly Diagnostic[], projectReferences?: readonly ProjectReference[]): BuilderProgram; -export function createAbstractBuilder(newProgramOrRootNames: Program | readonly string[] | undefined, hostOrOptions: BuilderProgramHost | CompilerOptions | undefined, oldProgramOrHost?: CompilerHost | BuilderProgram, configFileParsingDiagnosticsOrOldProgram?: readonly Diagnostic[] | BuilderProgram, configFileParsingDiagnostics?: readonly Diagnostic[], projectReferences?: readonly ProjectReference[]): BuilderProgram { - const { newProgram, configFileParsingDiagnostics: newConfigFileParsingDiagnostics } = getBuilderCreationParameters(newProgramOrRootNames, hostOrOptions, oldProgramOrHost, configFileParsingDiagnosticsOrOldProgram, configFileParsingDiagnostics, projectReferences); - return createRedirectedBuilderProgram(() => ({ program: newProgram, compilerOptions: newProgram.getCompilerOptions() }), newConfigFileParsingDiagnostics); +export function createAbstractBuilder( + newProgram: Program, + host: BuilderProgramHost, + oldProgram?: BuilderProgram, + configFileParsingDiagnostics?: readonly Diagnostic[], +): BuilderProgram; +export function createAbstractBuilder( + rootNames: readonly string[] | undefined, + options: CompilerOptions | undefined, + host?: CompilerHost, + oldProgram?: BuilderProgram, + configFileParsingDiagnostics?: readonly Diagnostic[], + projectReferences?: readonly ProjectReference[], +): BuilderProgram; +export function createAbstractBuilder( + newProgramOrRootNames: Program | readonly string[] | undefined, + hostOrOptions: BuilderProgramHost | CompilerOptions | undefined, + oldProgramOrHost?: CompilerHost | BuilderProgram, + configFileParsingDiagnosticsOrOldProgram?: readonly Diagnostic[] | BuilderProgram, + configFileParsingDiagnostics?: readonly Diagnostic[], + projectReferences?: readonly ProjectReference[], +): BuilderProgram { + const { newProgram, configFileParsingDiagnostics: newConfigFileParsingDiagnostics } = getBuilderCreationParameters( + newProgramOrRootNames, + hostOrOptions, + oldProgramOrHost, + configFileParsingDiagnosticsOrOldProgram, + configFileParsingDiagnostics, + projectReferences, + ); + return createRedirectedBuilderProgram( + () => ({ program: newProgram, compilerOptions: newProgram.getCompilerOptions() }), + newConfigFileParsingDiagnostics, + ); } diff --git a/src/compiler/builderState.ts b/src/compiler/builderState.ts index 159652e2ad285..fd98799a1e4b1 100644 --- a/src/compiler/builderState.ts +++ b/src/compiler/builderState.ts @@ -36,9 +36,23 @@ import { } from "./_namespaces/ts"; /** @internal */ -export function getFileEmitOutput(program: Program, sourceFile: SourceFile, emitOnlyDtsFiles: boolean, cancellationToken?: CancellationToken, customTransformers?: CustomTransformers, forceDtsEmit?: boolean): EmitOutput { +export function getFileEmitOutput( + program: Program, + sourceFile: SourceFile, + emitOnlyDtsFiles: boolean, + cancellationToken?: CancellationToken, + customTransformers?: CustomTransformers, + forceDtsEmit?: boolean, +): EmitOutput { const outputFiles: OutputFile[] = []; - const { emitSkipped, diagnostics } = program.emit(sourceFile, writeFile, cancellationToken, emitOnlyDtsFiles, customTransformers, forceDtsEmit); + const { emitSkipped, diagnostics } = program.emit( + sourceFile, + writeFile, + cancellationToken, + emitOnlyDtsFiles, + customTransformers, + forceDtsEmit, + ); return { outputFiles, emitSkipped, diagnostics }; function writeFile(fileName: string, text: string, writeByteOrderMark: boolean) { @@ -117,7 +131,11 @@ export namespace BuilderState { } export function createManyToManyPathMap(): ManyToManyPathMap { - function create(forward: Map>, reverse: Map>, deleted: Set | undefined): ManyToManyPathMap { + function create( + forward: Map>, + reverse: Map>, + deleted: Set | undefined, + ): ManyToManyPathMap { const map: ManyToManyPathMap = { getKeys: v => reverse.get(v), getValues: k => forward.get(k), @@ -192,7 +210,10 @@ export namespace BuilderState { /** * Get the module source file and all augmenting files from the import name node from file */ - function getReferencedFilesFromImportLiteral(checker: TypeChecker, importName: StringLiteralLike): Path[] | undefined { + function getReferencedFilesFromImportLiteral( + checker: TypeChecker, + importName: StringLiteralLike, + ): Path[] | undefined { const symbol = checker.getSymbolAtLocation(importName); return symbol && getReferencedFilesFromImportedModuleSymbol(symbol); } @@ -200,14 +221,27 @@ export namespace BuilderState { /** * Gets the path to reference file from file name, it could be resolvedPath if present otherwise path */ - function getReferencedFileFromFileName(program: Program, fileName: string, sourceFileDirectory: Path, getCanonicalFileName: GetCanonicalFileName): Path { - return toPath(program.getProjectReferenceRedirect(fileName) || fileName, sourceFileDirectory, getCanonicalFileName); + function getReferencedFileFromFileName( + program: Program, + fileName: string, + sourceFileDirectory: Path, + getCanonicalFileName: GetCanonicalFileName, + ): Path { + return toPath( + program.getProjectReferenceRedirect(fileName) || fileName, + sourceFileDirectory, + getCanonicalFileName, + ); } /** * Gets the referenced files for a file from the program with values for the keys as referenced file's path to be true */ - function getReferencedFiles(program: Program, sourceFile: SourceFile, getCanonicalFileName: GetCanonicalFileName): Set | undefined { + function getReferencedFiles( + program: Program, + sourceFile: SourceFile, + getCanonicalFileName: GetCanonicalFileName, + ): Set | undefined { let referencedFiles: Set | undefined; // We need to use a set here since the code can contain the same import twice, @@ -225,7 +259,12 @@ export namespace BuilderState { // Handle triple slash references if (sourceFile.referencedFiles && sourceFile.referencedFiles.length > 0) { for (const referencedFile of sourceFile.referencedFiles) { - const referencedPath = getReferencedFileFromFileName(program, referencedFile.fileName, sourceFileDirectory, getCanonicalFileName); + const referencedPath = getReferencedFileFromFileName( + program, + referencedFile.fileName, + sourceFileDirectory, + getCanonicalFileName, + ); addReferencedFile(referencedPath); } } @@ -238,7 +277,12 @@ export namespace BuilderState { } const fileName = resolvedTypeReferenceDirective.resolvedFileName!; // TODO: GH#18217 - const typeFilePath = getReferencedFileFromFileName(program, fileName, sourceFileDirectory, getCanonicalFileName); + const typeFilePath = getReferencedFileFromFileName( + program, + fileName, + sourceFileDirectory, + getCanonicalFileName, + ); addReferencedFile(typeFilePath); }); } @@ -273,8 +317,8 @@ export namespace BuilderState { for (const declaration of symbol.declarations) { const declarationSourceFile = getSourceFileOfNode(declaration); if ( - declarationSourceFile && - declarationSourceFile !== sourceFile + declarationSourceFile + && declarationSourceFile !== sourceFile ) { addReferencedFile(declarationSourceFile.resolvedPath); } @@ -289,19 +333,26 @@ export namespace BuilderState { /** * Returns true if oldState is reusable, that is the emitKind = module/non module has not changed */ - export function canReuseOldState(newReferencedMap: ReadonlyManyToManyPathMap | undefined, oldState: BuilderState | undefined) { + export function canReuseOldState( + newReferencedMap: ReadonlyManyToManyPathMap | undefined, + oldState: BuilderState | undefined, + ) { return oldState && !oldState.referencedMap === !newReferencedMap; } /** * Creates the state of file references and signature for the new program from oldState if it is safe */ - export function create(newProgram: Program, oldState: Readonly | undefined, disableUseFileVersionAsSignature: boolean): BuilderState { + export function create( + newProgram: Program, + oldState: Readonly | undefined, + disableUseFileVersionAsSignature: boolean, + ): BuilderState { const fileInfos = new Map(); const options = newProgram.getCompilerOptions(); const isOutFile = outFile(options); - const referencedMap = options.module !== ModuleKind.None && !isOutFile ? - createManyToManyPathMap() : undefined; + const referencedMap = options.module !== ModuleKind.None && !isOutFile + ? createManyToManyPathMap() : undefined; const exportedModulesMap = referencedMap ? createManyToManyPathMap() : undefined; const useOldState = canReuseOldState(referencedMap, oldState); @@ -310,11 +361,15 @@ export namespace BuilderState { // Create the reference map, and set the file infos for (const sourceFile of newProgram.getSourceFiles()) { - const version = Debug.checkDefined(sourceFile.version, "Program intended to be used with Builder should have source files with versions set"); - const oldUncommittedSignature = useOldState ? oldState!.oldSignatures?.get(sourceFile.resolvedPath) : undefined; - const signature = oldUncommittedSignature === undefined ? - useOldState ? oldState!.fileInfos.get(sourceFile.resolvedPath)?.signature : undefined : - oldUncommittedSignature || undefined; + const version = Debug.checkDefined( + sourceFile.version, + "Program intended to be used with Builder should have source files with versions set", + ); + const oldUncommittedSignature = useOldState ? oldState!.oldSignatures?.get(sourceFile.resolvedPath) + : undefined; + const signature = oldUncommittedSignature === undefined + ? useOldState ? oldState!.fileInfos.get(sourceFile.resolvedPath)?.signature : undefined + : oldUncommittedSignature || undefined; if (referencedMap) { const newReferences = getReferencedFiles(newProgram, sourceFile, newProgram.getCanonicalFileName); if (newReferences) { @@ -323,9 +378,9 @@ export namespace BuilderState { // Copy old visible to outside files map if (useOldState) { const oldUncommittedExportedModules = oldState!.oldExportedModulesMap?.get(sourceFile.resolvedPath); - const exportedModules = oldUncommittedExportedModules === undefined ? - oldState!.exportedModulesMap!.getValues(sourceFile.resolvedPath) : - oldUncommittedExportedModules || undefined; + const exportedModules = oldUncommittedExportedModules === undefined + ? oldState!.exportedModulesMap!.getValues(sourceFile.resolvedPath) + : oldUncommittedExportedModules || undefined; if (exportedModules) { exportedModulesMap!.set(sourceFile.resolvedPath, exportedModules); } @@ -394,7 +449,14 @@ export namespace BuilderState { return [sourceFile]; } - return (state.referencedMap ? getFilesAffectedByUpdatedShapeWhenModuleEmit : getFilesAffectedByUpdatedShapeWhenNonModuleEmit)(state, programOfThisState, sourceFile, cancellationToken, host); + return (state.referencedMap ? getFilesAffectedByUpdatedShapeWhenModuleEmit + : getFilesAffectedByUpdatedShapeWhenNonModuleEmit)( + state, + programOfThisState, + sourceFile, + cancellationToken, + host, + ); } export function updateSignatureOfFile(state: BuilderState, signature: string | undefined, path: Path) { @@ -412,7 +474,10 @@ export namespace BuilderState { programOfThisState.emit( sourceFile, (fileName, text, _writeByteOrderMark, _onError, sourceFiles, data) => { - Debug.assert(isDeclarationFileName(fileName), `File extension for signature expected to be dts: Got:: ${fileName}`); + Debug.assert( + isDeclarationFileName(fileName), + `File extension for signature expected to be dts: Got:: ${fileName}`, + ); onNewSignature( computeSignatureWithDiagnostics( programOfThisState, @@ -460,9 +525,13 @@ export namespace BuilderState { if (latestSignature === undefined) { latestSignature = sourceFile.version; if (state.exportedModulesMap && latestSignature !== prevSignature) { - (state.oldExportedModulesMap ||= new Map()).set(sourceFile.resolvedPath, state.exportedModulesMap.getValues(sourceFile.resolvedPath) || false); + (state.oldExportedModulesMap ||= new Map()).set( + sourceFile.resolvedPath, + state.exportedModulesMap.getValues(sourceFile.resolvedPath) || false, + ); // All the references in this file are exported - const references = state.referencedMap ? state.referencedMap.getValues(sourceFile.resolvedPath) : undefined; + const references = state.referencedMap ? state.referencedMap.getValues(sourceFile.resolvedPath) + : undefined; if (references) { state.exportedModulesMap.set(sourceFile.resolvedPath, references); } @@ -480,9 +549,16 @@ export namespace BuilderState { /** * Coverts the declaration emit result into exported modules map */ - export function updateExportedModules(state: BuilderState, sourceFile: SourceFile, exportedModulesFromDeclarationEmit: ExportedModulesFromDeclarationEmit | undefined) { + export function updateExportedModules( + state: BuilderState, + sourceFile: SourceFile, + exportedModulesFromDeclarationEmit: ExportedModulesFromDeclarationEmit | undefined, + ) { if (!state.exportedModulesMap) return; - (state.oldExportedModulesMap ||= new Map()).set(sourceFile.resolvedPath, state.exportedModulesMap.getValues(sourceFile.resolvedPath) || false); + (state.oldExportedModulesMap ||= new Map()).set( + sourceFile.resolvedPath, + state.exportedModulesMap.getValues(sourceFile.resolvedPath) || false, + ); const exportedModules = getExportedModules(exportedModulesFromDeclarationEmit); if (exportedModules) { state.exportedModulesMap.set(sourceFile.resolvedPath, exportedModules); @@ -492,7 +568,9 @@ export namespace BuilderState { } } - export function getExportedModules(exportedModulesFromDeclarationEmit: ExportedModulesFromDeclarationEmit | undefined) { + export function getExportedModules( + exportedModulesFromDeclarationEmit: ExportedModulesFromDeclarationEmit | undefined, + ) { let exportedModules: Set | undefined; exportedModulesFromDeclarationEmit?.forEach( symbol => @@ -506,7 +584,11 @@ export namespace BuilderState { /** * Get all the dependencies of the sourceFile */ - export function getAllDependencies(state: BuilderState, programOfThisState: Program, sourceFile: SourceFile): readonly string[] { + export function getAllDependencies( + state: BuilderState, + programOfThisState: Program, + sourceFile: SourceFile, + ): readonly string[] { const compilerOptions = programOfThisState.getCompilerOptions(); // With --out or --outFile all outputs go into single file, all files depend on each other if (outFile(compilerOptions)) { @@ -534,7 +616,9 @@ export namespace BuilderState { } } - return arrayFrom(mapDefinedIterator(seenMap.keys(), path => programOfThisState.getSourceFileByPath(path)?.fileName ?? path)); + return arrayFrom( + mapDefinedIterator(seenMap.keys(), path => programOfThisState.getSourceFileByPath(path)?.fileName ?? path), + ); } /** @@ -576,21 +660,29 @@ export namespace BuilderState { * they are global files as well as module */ function containsGlobalScopeAugmentation(sourceFile: SourceFile) { - return some(sourceFile.moduleAugmentations, augmentation => isGlobalScopeAugmentation(augmentation.parent as ModuleDeclaration)); + return some( + sourceFile.moduleAugmentations, + augmentation => isGlobalScopeAugmentation(augmentation.parent as ModuleDeclaration), + ); } /** * Return true if the file will invalidate all files because it affectes global scope */ function isFileAffectingGlobalScope(sourceFile: SourceFile) { - return containsGlobalScopeAugmentation(sourceFile) || - !isExternalOrCommonJsModule(sourceFile) && !isJsonSourceFile(sourceFile) && !containsOnlyAmbientModules(sourceFile); + return containsGlobalScopeAugmentation(sourceFile) + || !isExternalOrCommonJsModule(sourceFile) && !isJsonSourceFile(sourceFile) + && !containsOnlyAmbientModules(sourceFile); } /** * Gets all files of the program excluding the default library file */ - export function getAllFilesExcludingDefaultLibraryFile(state: BuilderState, programOfThisState: Program, firstSourceFile: SourceFile | undefined): readonly SourceFile[] { + export function getAllFilesExcludingDefaultLibraryFile( + state: BuilderState, + programOfThisState: Program, + firstSourceFile: SourceFile | undefined, + ): readonly SourceFile[] { // Use cached result if (state.allFilesExcludingDefaultLibraryFile) { return state.allFilesExcludingDefaultLibraryFile; @@ -616,7 +708,11 @@ export namespace BuilderState { /** * When program emits non modular code, gets the files affected by the sourceFile whose shape has changed */ - function getFilesAffectedByUpdatedShapeWhenNonModuleEmit(state: BuilderState, programOfThisState: Program, sourceFileWithUpdatedShape: SourceFile) { + function getFilesAffectedByUpdatedShapeWhenNonModuleEmit( + state: BuilderState, + programOfThisState: Program, + sourceFileWithUpdatedShape: SourceFile, + ) { const compilerOptions = programOfThisState.getCompilerOptions(); // If `--out` or `--outFile` is specified, any new emit will result in re-emitting the entire project, // so returning the file itself is good enough. @@ -658,7 +754,10 @@ export namespace BuilderState { if (!seenFileNamesMap.has(currentPath)) { const currentSourceFile = programOfThisState.getSourceFileByPath(currentPath)!; seenFileNamesMap.set(currentPath, currentSourceFile); - if (currentSourceFile && updateShapeSignature(state, programOfThisState, currentSourceFile, cancellationToken, host)) { + if ( + currentSourceFile + && updateShapeSignature(state, programOfThisState, currentSourceFile, cancellationToken, host) + ) { queue.push(...getReferencedByPaths(state, currentSourceFile.resolvedPath)); } } diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 56b1059f5ef18..bb9a4cd62d01f 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -1173,7 +1173,8 @@ export const enum TypeFacts { // The following members encode facts about particular kinds of types for use in the getTypeFacts function. // The presence of a particular fact means that the given test is true for some (and possibly all) values // of that kind of type. - BaseStringStrictFacts = TypeofEQString | TypeofNENumber | TypeofNEBigInt | TypeofNEBoolean | TypeofNESymbol | TypeofNEObject | TypeofNEFunction | TypeofNEHostObject | NEUndefined | NENull | NEUndefinedOrNull, + BaseStringStrictFacts = TypeofEQString | TypeofNENumber | TypeofNEBigInt | TypeofNEBoolean | TypeofNESymbol + | TypeofNEObject | TypeofNEFunction | TypeofNEHostObject | NEUndefined | NENull | NEUndefinedOrNull, BaseStringFacts = BaseStringStrictFacts | EQUndefined | EQNull | EQUndefinedOrNull | Falsy, StringStrictFacts = BaseStringStrictFacts | Truthy | Falsy, StringFacts = BaseStringFacts | Truthy, @@ -1181,7 +1182,8 @@ export const enum TypeFacts { EmptyStringFacts = BaseStringFacts, NonEmptyStringStrictFacts = BaseStringStrictFacts | Truthy, NonEmptyStringFacts = BaseStringFacts | Truthy, - BaseNumberStrictFacts = TypeofEQNumber | TypeofNEString | TypeofNEBigInt | TypeofNEBoolean | TypeofNESymbol | TypeofNEObject | TypeofNEFunction | TypeofNEHostObject | NEUndefined | NENull | NEUndefinedOrNull, + BaseNumberStrictFacts = TypeofEQNumber | TypeofNEString | TypeofNEBigInt | TypeofNEBoolean | TypeofNESymbol + | TypeofNEObject | TypeofNEFunction | TypeofNEHostObject | NEUndefined | NENull | NEUndefinedOrNull, BaseNumberFacts = BaseNumberStrictFacts | EQUndefined | EQNull | EQUndefinedOrNull | Falsy, NumberStrictFacts = BaseNumberStrictFacts | Truthy | Falsy, NumberFacts = BaseNumberFacts | Truthy, @@ -1189,7 +1191,8 @@ export const enum TypeFacts { ZeroNumberFacts = BaseNumberFacts, NonZeroNumberStrictFacts = BaseNumberStrictFacts | Truthy, NonZeroNumberFacts = BaseNumberFacts | Truthy, - BaseBigIntStrictFacts = TypeofEQBigInt | TypeofNEString | TypeofNENumber | TypeofNEBoolean | TypeofNESymbol | TypeofNEObject | TypeofNEFunction | TypeofNEHostObject | NEUndefined | NENull | NEUndefinedOrNull, + BaseBigIntStrictFacts = TypeofEQBigInt | TypeofNEString | TypeofNENumber | TypeofNEBoolean | TypeofNESymbol + | TypeofNEObject | TypeofNEFunction | TypeofNEHostObject | NEUndefined | NENull | NEUndefinedOrNull, BaseBigIntFacts = BaseBigIntStrictFacts | EQUndefined | EQNull | EQUndefinedOrNull | Falsy, BigIntStrictFacts = BaseBigIntStrictFacts | Truthy | Falsy, BigIntFacts = BaseBigIntFacts | Truthy, @@ -1197,7 +1200,8 @@ export const enum TypeFacts { ZeroBigIntFacts = BaseBigIntFacts, NonZeroBigIntStrictFacts = BaseBigIntStrictFacts | Truthy, NonZeroBigIntFacts = BaseBigIntFacts | Truthy, - BaseBooleanStrictFacts = TypeofEQBoolean | TypeofNEString | TypeofNENumber | TypeofNEBigInt | TypeofNESymbol | TypeofNEObject | TypeofNEFunction | TypeofNEHostObject | NEUndefined | NENull | NEUndefinedOrNull, + BaseBooleanStrictFacts = TypeofEQBoolean | TypeofNEString | TypeofNENumber | TypeofNEBigInt | TypeofNESymbol + | TypeofNEObject | TypeofNEFunction | TypeofNEHostObject | NEUndefined | NENull | NEUndefinedOrNull, BaseBooleanFacts = BaseBooleanStrictFacts | EQUndefined | EQNull | EQUndefinedOrNull | Falsy, BooleanStrictFacts = BaseBooleanStrictFacts | Truthy | Falsy, BooleanFacts = BaseBooleanFacts | Truthy, @@ -1205,19 +1209,27 @@ export const enum TypeFacts { FalseFacts = BaseBooleanFacts, TrueStrictFacts = BaseBooleanStrictFacts | Truthy, TrueFacts = BaseBooleanFacts | Truthy, - SymbolStrictFacts = TypeofEQSymbol | TypeofNEString | TypeofNENumber | TypeofNEBigInt | TypeofNEBoolean | TypeofNEObject | TypeofNEFunction | TypeofNEHostObject | NEUndefined | NENull | NEUndefinedOrNull | Truthy, + SymbolStrictFacts = TypeofEQSymbol | TypeofNEString | TypeofNENumber | TypeofNEBigInt | TypeofNEBoolean + | TypeofNEObject | TypeofNEFunction | TypeofNEHostObject | NEUndefined | NENull | NEUndefinedOrNull | Truthy, SymbolFacts = SymbolStrictFacts | EQUndefined | EQNull | EQUndefinedOrNull | Falsy, - ObjectStrictFacts = TypeofEQObject | TypeofEQHostObject | TypeofNEString | TypeofNENumber | TypeofNEBigInt | TypeofNEBoolean | TypeofNESymbol | TypeofNEFunction | NEUndefined | NENull | NEUndefinedOrNull | Truthy, + ObjectStrictFacts = TypeofEQObject | TypeofEQHostObject | TypeofNEString | TypeofNENumber | TypeofNEBigInt + | TypeofNEBoolean | TypeofNESymbol | TypeofNEFunction | NEUndefined | NENull | NEUndefinedOrNull | Truthy, ObjectFacts = ObjectStrictFacts | EQUndefined | EQNull | EQUndefinedOrNull | Falsy, - FunctionStrictFacts = TypeofEQFunction | TypeofEQHostObject | TypeofNEString | TypeofNENumber | TypeofNEBigInt | TypeofNEBoolean | TypeofNESymbol | TypeofNEObject | NEUndefined | NENull | NEUndefinedOrNull | Truthy, + FunctionStrictFacts = TypeofEQFunction | TypeofEQHostObject | TypeofNEString | TypeofNENumber | TypeofNEBigInt + | TypeofNEBoolean | TypeofNESymbol | TypeofNEObject | NEUndefined | NENull | NEUndefinedOrNull | Truthy, FunctionFacts = FunctionStrictFacts | EQUndefined | EQNull | EQUndefinedOrNull | Falsy, - VoidFacts = TypeofNEString | TypeofNENumber | TypeofNEBigInt | TypeofNEBoolean | TypeofNESymbol | TypeofNEObject | TypeofNEFunction | TypeofNEHostObject | EQUndefined | EQUndefinedOrNull | NENull | Falsy, - UndefinedFacts = TypeofNEString | TypeofNENumber | TypeofNEBigInt | TypeofNEBoolean | TypeofNESymbol | TypeofNEObject | TypeofNEFunction | TypeofNEHostObject | EQUndefined | EQUndefinedOrNull | NENull | Falsy | IsUndefined, - NullFacts = TypeofEQObject | TypeofNEString | TypeofNENumber | TypeofNEBigInt | TypeofNEBoolean | TypeofNESymbol | TypeofNEFunction | TypeofNEHostObject | EQNull | EQUndefinedOrNull | NEUndefined | Falsy | IsNull, + VoidFacts = TypeofNEString | TypeofNENumber | TypeofNEBigInt | TypeofNEBoolean | TypeofNESymbol | TypeofNEObject + | TypeofNEFunction | TypeofNEHostObject | EQUndefined | EQUndefinedOrNull | NENull | Falsy, + UndefinedFacts = TypeofNEString | TypeofNENumber | TypeofNEBigInt | TypeofNEBoolean | TypeofNESymbol + | TypeofNEObject | TypeofNEFunction | TypeofNEHostObject | EQUndefined | EQUndefinedOrNull | NENull | Falsy + | IsUndefined, + NullFacts = TypeofEQObject | TypeofNEString | TypeofNENumber | TypeofNEBigInt | TypeofNEBoolean | TypeofNESymbol + | TypeofNEFunction | TypeofNEHostObject | EQNull | EQUndefinedOrNull | NEUndefined | Falsy | IsNull, EmptyObjectStrictFacts = All & ~(EQUndefined | EQNull | EQUndefinedOrNull | IsUndefinedOrNull), EmptyObjectFacts = All & ~IsUndefinedOrNull, UnknownFacts = All & ~IsUndefinedOrNull, - AllTypeofNE = TypeofNEString | TypeofNENumber | TypeofNEBigInt | TypeofNEBoolean | TypeofNESymbol | TypeofNEObject | TypeofNEFunction | NEUndefined, + AllTypeofNE = TypeofNEString | TypeofNENumber | TypeofNEBigInt | TypeofNEBoolean | TypeofNESymbol | TypeofNEObject + | TypeofNEFunction | NEUndefined, // Masks OrFactsMask = TypeofEQFunction | TypeofNEObject, AndFactsMask = All & ~OrFactsMask, @@ -1384,8 +1396,8 @@ export function getSymbolId(symbol: Symbol): SymbolId { /** @internal */ export function isInstantiatedModule(node: ModuleDeclaration, preserveConstEnums: boolean) { const moduleState = getModuleInstanceState(node); - return moduleState === ModuleInstanceState.Instantiated || - (preserveConstEnums && moduleState === ModuleInstanceState.ConstEnumOnly); + return moduleState === ModuleInstanceState.Instantiated + || (preserveConstEnums && moduleState === ModuleInstanceState.ConstEnumOnly); } /** @internal */ @@ -1468,7 +1480,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { var isolatedModulesLikeFlagName = compilerOptions.verbatimModuleSyntax ? "verbatimModuleSyntax" : "isolatedModules"; // It is an error to use `importsNotUsedAsValues` alongside `verbatimModuleSyntax`, but we still need to not crash. // Given that, in such a scenario, `verbatimModuleSyntax` is basically disabled, as least as far as alias visibility tracking goes. - var canCollectSymbolAliasAccessabilityData = !compilerOptions.verbatimModuleSyntax || !!compilerOptions.importsNotUsedAsValues; + var canCollectSymbolAliasAccessabilityData = !compilerOptions.verbatimModuleSyntax + || !!compilerOptions.importsNotUsedAsValues; /** This will be set during calls to `getResolvedSignature` where services determines an apparent number of arguments greater than what is actually provided. */ var apparentArgumentCount: number | undefined; @@ -1510,7 +1523,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { getTypeOfSymbol, getSymbolsOfParameterPropertyDeclaration: (parameterIn, parameterName) => { const parameter = getParseTreeNode(parameterIn, isParameter); - if (parameter === undefined) return Debug.fail("Cannot get symbols of a synthetic parameter that cannot be resolved to a parse-tree node."); + if (parameter === undefined) { + return Debug.fail( + "Cannot get symbols of a synthetic parameter that cannot be resolved to a parse-tree node.", + ); + } Debug.assert(isParameterPropertyDeclaration(parameter, parameter.parent)); return getSymbolsOfParameterPropertyDeclaration(parameter, escapeLeadingUnderscores(parameterName)); }, @@ -1524,14 +1541,17 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } const propName = escapeLeadingUnderscores(name); const lexicallyScopedIdentifier = lookupSymbolForPrivateIdentifierDeclaration(propName, node); - return lexicallyScopedIdentifier ? getPrivateIdentifierPropertyOfType(leftType, lexicallyScopedIdentifier) : undefined; + return lexicallyScopedIdentifier ? getPrivateIdentifierPropertyOfType(leftType, lexicallyScopedIdentifier) + : undefined; }, getTypeOfPropertyOfType: (type, name) => getTypeOfPropertyOfType(type, escapeLeadingUnderscores(name)), - getIndexInfoOfType: (type, kind) => getIndexInfoOfType(type, kind === IndexKind.String ? stringType : numberType), + getIndexInfoOfType: (type, kind) => + getIndexInfoOfType(type, kind === IndexKind.String ? stringType : numberType), getIndexInfosOfType, getIndexInfosOfIndexSymbol, getSignaturesOfType, - getIndexTypeOfType: (type, kind) => getIndexTypeOfType(type, kind === IndexKind.String ? stringType : numberType), + getIndexTypeOfType: (type, kind) => + getIndexTypeOfType(type, kind === IndexKind.String ? stringType : numberType), getIndexType: type => getIndexType(type), getBaseTypes, getBaseTypeOfLiteralType, @@ -1647,14 +1667,42 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { isContextSensitive, getTypeOfPropertyOfContextualType, getFullyQualifiedName, - getResolvedSignature: (node, candidatesOutArray, argumentCount) => getResolvedSignatureWorker(node, candidatesOutArray, argumentCount, CheckMode.Normal), - getResolvedSignatureForStringLiteralCompletions: (call, editingArgument, candidatesOutArray, checkMode = CheckMode.IsForStringLiteralArgumentCompletions) => { + getResolvedSignature: (node, candidatesOutArray, argumentCount) => + getResolvedSignatureWorker(node, candidatesOutArray, argumentCount, CheckMode.Normal), + getResolvedSignatureForStringLiteralCompletions: ( + call, + editingArgument, + candidatesOutArray, + checkMode = CheckMode.IsForStringLiteralArgumentCompletions, + ) => { if (checkMode & CheckMode.IsForStringLiteralArgumentCompletions) { - return runWithInferenceBlockedFromSourceNode(editingArgument, () => getResolvedSignatureWorker(call, candidatesOutArray, /*argumentCount*/ undefined, checkMode & ~CheckMode.IsForStringLiteralArgumentCompletions)); + return runWithInferenceBlockedFromSourceNode( + editingArgument, + () => + getResolvedSignatureWorker( + call, + candidatesOutArray, + /*argumentCount*/ undefined, + checkMode & ~CheckMode.IsForStringLiteralArgumentCompletions, + ), + ); } - return runWithoutResolvedSignatureCaching(editingArgument, () => getResolvedSignatureWorker(call, candidatesOutArray, /*argumentCount*/ undefined, checkMode & ~CheckMode.IsForStringLiteralArgumentCompletions)); + return runWithoutResolvedSignatureCaching( + editingArgument, + () => + getResolvedSignatureWorker( + call, + candidatesOutArray, + /*argumentCount*/ undefined, + checkMode & ~CheckMode.IsForStringLiteralArgumentCompletions, + ), + ); }, - getResolvedSignatureForSignatureHelp: (node, candidatesOutArray, argumentCount) => runWithoutResolvedSignatureCaching(node, () => getResolvedSignatureWorker(node, candidatesOutArray, argumentCount, CheckMode.IsForSignatureHelp)), + getResolvedSignatureForSignatureHelp: (node, candidatesOutArray, argumentCount) => + runWithoutResolvedSignatureCaching( + node, + () => getResolvedSignatureWorker(node, candidatesOutArray, argumentCount, CheckMode.IsForSignatureHelp), + ), getExpandedParameters, hasEffectiveRestParameter, containsArgumentsReference, @@ -1702,8 +1750,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const node = getParseTreeNode(nodeIn, isParameter); return node ? isOptionalParameter(node) : false; }, - tryGetMemberInModuleExports: (name, symbol) => tryGetMemberInModuleExports(escapeLeadingUnderscores(name), symbol), - tryGetMemberInModuleExportsAndProperties: (name, symbol) => tryGetMemberInModuleExportsAndProperties(escapeLeadingUnderscores(name), symbol), + tryGetMemberInModuleExports: (name, symbol) => + tryGetMemberInModuleExports(escapeLeadingUnderscores(name), symbol), + tryGetMemberInModuleExportsAndProperties: (name, symbol) => + tryGetMemberInModuleExportsAndProperties(escapeLeadingUnderscores(name), symbol), tryFindAmbientModule: moduleName => tryFindAmbientModule(moduleName, /*withAugmentations*/ true), tryFindAmbientModuleWithoutAugmentations: moduleName => { // we deliberately exclude augmentations @@ -1753,15 +1803,27 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { getSuggestedSymbolForNonexistentProperty, getSuggestionForNonexistentProperty, getSuggestedSymbolForNonexistentJSXAttribute, - getSuggestedSymbolForNonexistentSymbol: (location, name, meaning) => getSuggestedSymbolForNonexistentSymbol(location, escapeLeadingUnderscores(name), meaning), - getSuggestionForNonexistentSymbol: (location, name, meaning) => getSuggestionForNonexistentSymbol(location, escapeLeadingUnderscores(name), meaning), + getSuggestedSymbolForNonexistentSymbol: (location, name, meaning) => + getSuggestedSymbolForNonexistentSymbol(location, escapeLeadingUnderscores(name), meaning), + getSuggestionForNonexistentSymbol: (location, name, meaning) => + getSuggestionForNonexistentSymbol(location, escapeLeadingUnderscores(name), meaning), getSuggestedSymbolForNonexistentModule, getSuggestionForNonexistentExport, getSuggestedSymbolForNonexistentClassMember, getBaseConstraintOfType, - getDefaultFromTypeParameter: type => type && type.flags & TypeFlags.TypeParameter ? getDefaultFromTypeParameter(type as TypeParameter) : undefined, + getDefaultFromTypeParameter: type => + type && type.flags & TypeFlags.TypeParameter ? getDefaultFromTypeParameter(type as TypeParameter) + : undefined, resolveName(name, location, meaning, excludeGlobals) { - return resolveName(location, escapeLeadingUnderscores(name), meaning, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ false, excludeGlobals); + return resolveName( + location, + escapeLeadingUnderscores(name), + meaning, + /*nameNotFoundMessage*/ undefined, + /*nameArg*/ undefined, + /*isUse*/ false, + excludeGlobals, + ); }, getJsxNamespace: n => unescapeLeadingUnderscores(getJsxNamespace(n)), getJsxFragmentFactory: n => { @@ -1772,7 +1834,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { getTypePredicateOfSignature, resolveExternalModuleName: moduleSpecifierIn => { const moduleSpecifier = getParseTreeNode(moduleSpecifierIn, isExpression); - return moduleSpecifier && resolveExternalModuleName(moduleSpecifier, moduleSpecifier, /*ignoreErrors*/ true); + return moduleSpecifier + && resolveExternalModuleName(moduleSpecifier, moduleSpecifier, /*ignoreErrors*/ true); }, resolveExternalModuleSymbol, tryGetThisTypeAt: (nodeIn, includeGlobalThis, container) => { @@ -1784,7 +1847,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return node && getTypeArgumentConstraint(node); }, getSuggestionDiagnostics: (fileIn, ct) => { - const file = getParseTreeNode(fileIn, isSourceFile) || Debug.fail("Could not determine parsed source file."); + const file = getParseTreeNode(fileIn, isSourceFile) + || Debug.fail("Could not determine parsed source file."); if (skipTypeChecking(file, compilerOptions, host)) { return emptyArray; } @@ -1802,7 +1866,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { diagnostics = addRange(diagnostics, suggestionDiagnostics.getDiagnostics(file.fileName)); checkUnusedIdentifiers(getPotentiallyUnusedIdentifiers(file), (containingNode, kind, diag) => { - if (!containsParseError(containingNode) && !unusedIsError(kind, !!(containingNode.flags & NodeFlags.Ambient))) { + if ( + !containsParseError(containingNode) + && !unusedIsError(kind, !!(containingNode.flags & NodeFlags.Ambient)) + ) { (diagnostics || (diagnostics = [])).push({ ...diag, category: DiagnosticCategory.Suggestion }); } }); @@ -1877,7 +1944,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return result; } - function getResolvedSignatureWorker(nodeIn: CallLikeExpression, candidatesOutArray: Signature[] | undefined, argumentCount: number | undefined, checkMode: CheckMode): Signature | undefined { + function getResolvedSignatureWorker( + nodeIn: CallLikeExpression, + candidatesOutArray: Signature[] | undefined, + argumentCount: number | undefined, + checkMode: CheckMode, + ): Signature | undefined { const node = getParseTreeNode(nodeIn, isCallLikeExpression); apparentArgumentCount = argumentCount; const res = !node ? undefined : getResolvedSignature(node, candidatesOutArray, checkMode); @@ -1923,12 +1995,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { var unknownType = createIntrinsicType(TypeFlags.Unknown, "unknown"); var nonNullUnknownType = createIntrinsicType(TypeFlags.Unknown, "unknown"); var undefinedType = createIntrinsicType(TypeFlags.Undefined, "undefined"); - var undefinedWideningType = strictNullChecks ? undefinedType : createIntrinsicType(TypeFlags.Undefined, "undefined", ObjectFlags.ContainsWideningType); + var undefinedWideningType = strictNullChecks ? undefinedType + : createIntrinsicType(TypeFlags.Undefined, "undefined", ObjectFlags.ContainsWideningType); var missingType = createIntrinsicType(TypeFlags.Undefined, "undefined"); var undefinedOrMissingType = exactOptionalPropertyTypes ? missingType : undefinedType; var optionalType = createIntrinsicType(TypeFlags.Undefined, "undefined"); var nullType = createIntrinsicType(TypeFlags.Null, "null"); - var nullWideningType = strictNullChecks ? nullType : createIntrinsicType(TypeFlags.Null, "null", ObjectFlags.ContainsWideningType); + var nullWideningType = strictNullChecks ? nullType + : createIntrinsicType(TypeFlags.Null, "null", ObjectFlags.ContainsWideningType); var stringType = createIntrinsicType(TypeFlags.String, "string"); var numberType = createIntrinsicType(TypeFlags.Number, "number"); var bigintType = createIntrinsicType(TypeFlags.BigInt, "bigint"); @@ -1956,13 +2030,29 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { var stringNumberSymbolType = getUnionType([stringType, numberType, esSymbolType]); var keyofConstraintType = keyofStringsOnly ? stringType : stringNumberSymbolType; var numberOrBigIntType = getUnionType([numberType, bigintType]); - var templateConstraintType = getUnionType([stringType, numberType, booleanType, bigintType, nullType, undefinedType]) as UnionType; + var templateConstraintType = getUnionType([ + stringType, + numberType, + booleanType, + bigintType, + nullType, + undefinedType, + ]) as UnionType; var numericStringType = getTemplateLiteralType(["", ""], [numberType]); // The `${number}` type - var restrictiveMapper: TypeMapper = makeFunctionTypeMapper(t => t.flags & TypeFlags.TypeParameter ? getRestrictiveTypeParameter(t as TypeParameter) : t, () => "(restrictive mapper)"); - var permissiveMapper: TypeMapper = makeFunctionTypeMapper(t => t.flags & TypeFlags.TypeParameter ? wildcardType : t, () => "(permissive mapper)"); + var restrictiveMapper: TypeMapper = makeFunctionTypeMapper( + t => t.flags & TypeFlags.TypeParameter ? getRestrictiveTypeParameter(t as TypeParameter) : t, + () => "(restrictive mapper)", + ); + var permissiveMapper: TypeMapper = makeFunctionTypeMapper( + t => t.flags & TypeFlags.TypeParameter ? wildcardType : t, + () => "(permissive mapper)", + ); var uniqueLiteralType = createIntrinsicType(TypeFlags.Never, "never"); // `uniqueLiteralType` is a special `never` flagged by union reduction to behave as a literal - var uniqueLiteralMapper: TypeMapper = makeFunctionTypeMapper(t => t.flags & TypeFlags.TypeParameter ? uniqueLiteralType : t, () => "(unique literal mapper)"); // replace all type parameters with the unique literal type (disregarding constraints) + var uniqueLiteralMapper: TypeMapper = makeFunctionTypeMapper( + t => t.flags & TypeFlags.TypeParameter ? uniqueLiteralType : t, + () => "(unique literal mapper)", + ); // replace all type parameters with the unique literal type (disregarding constraints) var outofbandVarianceMarkerHandler: ((onlyUnreliable: boolean) => void) | undefined; var reportUnreliableMapper = makeFunctionTypeMapper(t => { if (outofbandVarianceMarkerHandler && (t === markerSuperType || t === markerSubType || t === markerOtherType)) { @@ -1978,17 +2068,42 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { }, () => "(unreliable reporter)"); var emptyObjectType = createAnonymousType(/*symbol*/ undefined, emptySymbols, emptyArray, emptyArray, emptyArray); - var emptyJsxObjectType = createAnonymousType(/*symbol*/ undefined, emptySymbols, emptyArray, emptyArray, emptyArray); + var emptyJsxObjectType = createAnonymousType( + /*symbol*/ undefined, + emptySymbols, + emptyArray, + emptyArray, + emptyArray, + ); emptyJsxObjectType.objectFlags |= ObjectFlags.JsxAttributes; var emptyTypeLiteralSymbol = createSymbol(SymbolFlags.TypeLiteral, InternalSymbolName.Type); emptyTypeLiteralSymbol.members = createSymbolTable(); - var emptyTypeLiteralType = createAnonymousType(emptyTypeLiteralSymbol, emptySymbols, emptyArray, emptyArray, emptyArray); - - var unknownEmptyObjectType = createAnonymousType(/*symbol*/ undefined, emptySymbols, emptyArray, emptyArray, emptyArray); - var unknownUnionType = strictNullChecks ? getUnionType([undefinedType, nullType, unknownEmptyObjectType]) : unknownType; - - var emptyGenericType = createAnonymousType(/*symbol*/ undefined, emptySymbols, emptyArray, emptyArray, emptyArray) as ObjectType as GenericType; + var emptyTypeLiteralType = createAnonymousType( + emptyTypeLiteralSymbol, + emptySymbols, + emptyArray, + emptyArray, + emptyArray, + ); + + var unknownEmptyObjectType = createAnonymousType( + /*symbol*/ undefined, + emptySymbols, + emptyArray, + emptyArray, + emptyArray, + ); + var unknownUnionType = strictNullChecks ? getUnionType([undefinedType, nullType, unknownEmptyObjectType]) + : unknownType; + + var emptyGenericType = createAnonymousType( + /*symbol*/ undefined, + emptySymbols, + emptyArray, + emptyArray, + emptyArray, + ) as ObjectType as GenericType; emptyGenericType.instantiations = new Map(); var anyFunctionType = createAnonymousType(/*symbol*/ undefined, emptySymbols, emptyArray, emptyArray, emptyArray); @@ -1997,8 +2112,20 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { anyFunctionType.objectFlags |= ObjectFlags.NonInferrableType; var noConstraintType = createAnonymousType(/*symbol*/ undefined, emptySymbols, emptyArray, emptyArray, emptyArray); - var circularConstraintType = createAnonymousType(/*symbol*/ undefined, emptySymbols, emptyArray, emptyArray, emptyArray); - var resolvingDefaultType = createAnonymousType(/*symbol*/ undefined, emptySymbols, emptyArray, emptyArray, emptyArray); + var circularConstraintType = createAnonymousType( + /*symbol*/ undefined, + emptySymbols, + emptyArray, + emptyArray, + emptyArray, + ); + var resolvingDefaultType = createAnonymousType( + /*symbol*/ undefined, + emptySymbols, + emptyArray, + emptyArray, + emptyArray, + ); var markerSuperType = createTypeParameter(); var markerSubType = createTypeParameter(); @@ -2011,10 +2138,46 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { var noTypePredicate = createTypePredicate(TypePredicateKind.Identifier, "<>", 0, anyType); - var anySignature = createSignature(/*declaration*/ undefined, /*typeParameters*/ undefined, /*thisParameter*/ undefined, emptyArray, anyType, /*resolvedTypePredicate*/ undefined, 0, SignatureFlags.None); - var unknownSignature = createSignature(/*declaration*/ undefined, /*typeParameters*/ undefined, /*thisParameter*/ undefined, emptyArray, errorType, /*resolvedTypePredicate*/ undefined, 0, SignatureFlags.None); - var resolvingSignature = createSignature(/*declaration*/ undefined, /*typeParameters*/ undefined, /*thisParameter*/ undefined, emptyArray, anyType, /*resolvedTypePredicate*/ undefined, 0, SignatureFlags.None); - var silentNeverSignature = createSignature(/*declaration*/ undefined, /*typeParameters*/ undefined, /*thisParameter*/ undefined, emptyArray, silentNeverType, /*resolvedTypePredicate*/ undefined, 0, SignatureFlags.None); + var anySignature = createSignature( + /*declaration*/ undefined, + /*typeParameters*/ undefined, + /*thisParameter*/ undefined, + emptyArray, + anyType, + /*resolvedTypePredicate*/ undefined, + 0, + SignatureFlags.None, + ); + var unknownSignature = createSignature( + /*declaration*/ undefined, + /*typeParameters*/ undefined, + /*thisParameter*/ undefined, + emptyArray, + errorType, + /*resolvedTypePredicate*/ undefined, + 0, + SignatureFlags.None, + ); + var resolvingSignature = createSignature( + /*declaration*/ undefined, + /*typeParameters*/ undefined, + /*thisParameter*/ undefined, + emptyArray, + anyType, + /*resolvedTypePredicate*/ undefined, + 0, + SignatureFlags.None, + ); + var silentNeverSignature = createSignature( + /*declaration*/ undefined, + /*typeParameters*/ undefined, + /*thisParameter*/ undefined, + emptyArray, + silentNeverType, + /*resolvedTypePredicate*/ undefined, + 0, + SignatureFlags.None, + ); var enumNumberIndexInfo = createIndexInfo(numberType, stringType, /*isReadonly*/ true); @@ -2043,10 +2206,17 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { getGlobalIterableType: getGlobalAsyncIterableType, getGlobalIterableIteratorType: getGlobalAsyncIterableIteratorType, getGlobalGeneratorType: getGlobalAsyncGeneratorType, - resolveIterationType: (type, errorNode) => getAwaitedType(type, errorNode, Diagnostics.Type_of_await_operand_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member), + resolveIterationType: (type, errorNode) => + getAwaitedType( + type, + errorNode, + Diagnostics + .Type_of_await_operand_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member, + ), mustHaveANextMethodDiagnostic: Diagnostics.An_async_iterator_must_have_a_next_method, mustBeAMethodDiagnostic: Diagnostics.The_0_property_of_an_async_iterator_must_be_a_method, - mustHaveAValueDiagnostic: Diagnostics.The_type_returned_by_the_0_method_of_an_async_iterator_must_be_a_promise_for_a_type_with_a_value_property, + mustHaveAValueDiagnostic: Diagnostics + .The_type_returned_by_the_0_method_of_an_async_iterator_must_be_a_promise_for_a_type_with_a_value_property, }; var syncIterationTypesResolver: IterationTypesResolver = { @@ -2060,7 +2230,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { resolveIterationType: (type, _errorNode) => type, mustHaveANextMethodDiagnostic: Diagnostics.An_iterator_must_have_a_next_method, mustBeAMethodDiagnostic: Diagnostics.The_0_property_of_an_iterator_must_be_a_method, - mustHaveAValueDiagnostic: Diagnostics.The_type_returned_by_the_0_method_of_an_iterator_must_have_a_value_property, + mustHaveAValueDiagnostic: + Diagnostics.The_type_returned_by_the_0_method_of_an_iterator_must_have_a_value_property, }; interface DuplicateInfoForSymbol { @@ -2254,10 +2425,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const jsxFragmentPragma = file.pragmas.get("jsxfrag"); if (jsxFragmentPragma) { const chosenPragma = isArray(jsxFragmentPragma) ? jsxFragmentPragma[0] : jsxFragmentPragma; - file.localJsxFragmentFactory = parseIsolatedEntityName(chosenPragma.arguments.factory, languageVersion); + file.localJsxFragmentFactory = parseIsolatedEntityName( + chosenPragma.arguments.factory, + languageVersion, + ); visitNode(file.localJsxFragmentFactory, markAsSynthetic, isEntityName); if (file.localJsxFragmentFactory) { - return file.localJsxFragmentNamespace = getFirstIdentifier(file.localJsxFragmentFactory).escapedText; + return file.localJsxFragmentNamespace = + getFirstIdentifier(file.localJsxFragmentFactory).escapedText; } } const entity = getJsxFragmentFactoryEntity(location); @@ -2288,7 +2463,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } if (!_jsxFactoryEntity) { - _jsxFactoryEntity = factory.createQualifiedName(factory.createIdentifier(unescapeLeadingUnderscores(_jsxNamespace)), "createElement"); + _jsxFactoryEntity = factory.createQualifiedName( + factory.createIdentifier(unescapeLeadingUnderscores(_jsxNamespace)), + "createElement", + ); } return _jsxNamespace; } @@ -2320,7 +2498,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return emitResolver; } - function lookupOrIssueError(location: Node | undefined, message: DiagnosticMessage, ...args: DiagnosticArguments): Diagnostic { + function lookupOrIssueError( + location: Node | undefined, + message: DiagnosticMessage, + ...args: DiagnosticArguments + ): Diagnostic { const diagnostic = location ? createDiagnosticForNode(location, message, ...args) : createCompilerDiagnostic(message, ...args); @@ -2334,13 +2516,22 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } - function errorSkippedOn(key: keyof CompilerOptions, location: Node | undefined, message: DiagnosticMessage, ...args: DiagnosticArguments): Diagnostic { + function errorSkippedOn( + key: keyof CompilerOptions, + location: Node | undefined, + message: DiagnosticMessage, + ...args: DiagnosticArguments + ): Diagnostic { const diagnostic = error(location, message, ...args); diagnostic.skippedOn = key; return diagnostic; } - function createError(location: Node | undefined, message: DiagnosticMessage, ...args: DiagnosticArguments): Diagnostic { + function createError( + location: Node | undefined, + message: DiagnosticMessage, + ...args: DiagnosticArguments + ): Diagnostic { return location ? createDiagnosticForNode(location, message, ...args) : createCompilerDiagnostic(message, ...args); @@ -2360,7 +2551,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { suggestionDiagnostics.add({ ...diagnostic, category: DiagnosticCategory.Suggestion }); } } - function errorOrSuggestion(isError: boolean, location: Node, message: DiagnosticMessage | DiagnosticMessageChain, ...args: DiagnosticArguments): void { + function errorOrSuggestion( + isError: boolean, + location: Node, + message: DiagnosticMessage | DiagnosticMessageChain, + ...args: DiagnosticArguments + ): void { // Pseudo-synthesized input node if (location.pos < 0 || location.end < 0) { if (!isError) { @@ -2368,10 +2564,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } // Issue errors globally const file = getSourceFileOfNode(location); - addErrorOrSuggestion(isError, "message" in message ? createFileDiagnostic(file, 0, 0, message, ...args) : createDiagnosticForFileFromMessageChain(file, message)); // eslint-disable-line local/no-in-operator + addErrorOrSuggestion( + isError, + "message" in message ? createFileDiagnostic(file, 0, 0, message, ...args) + : createDiagnosticForFileFromMessageChain(file, message), + ); // eslint-disable-line local/no-in-operator return; } - addErrorOrSuggestion(isError, "message" in message ? createDiagnosticForNode(location, message, ...args) : createDiagnosticForNodeFromMessageChain(getSourceFileOfNode(location), location, message)); // eslint-disable-line local/no-in-operator + addErrorOrSuggestion( + isError, + "message" in message ? createDiagnosticForNode(location, message, ...args) + : createDiagnosticForNodeFromMessageChain(getSourceFileOfNode(location), location, message), + ); // eslint-disable-line local/no-in-operator } function errorAndMaybeSuggestAwait( @@ -2389,7 +2593,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function addDeprecatedSuggestionWorker(declarations: Node | Node[], diagnostic: DiagnosticWithLocation) { - const deprecatedTag = Array.isArray(declarations) ? forEach(declarations, getJSDocDeprecatedTag) : getJSDocDeprecatedTag(declarations); + const deprecatedTag = Array.isArray(declarations) ? forEach(declarations, getJSDocDeprecatedTag) + : getJSDocDeprecatedTag(declarations); if (deprecatedTag) { addRelatedInfo( diagnostic, @@ -2404,7 +2609,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function isDeprecatedSymbol(symbol: Symbol) { const parentSymbol = getParentOfSymbol(symbol); if (parentSymbol && length(symbol.declarations) > 1) { - return parentSymbol.flags & SymbolFlags.Interface ? some(symbol.declarations, isDeprecatedDeclaration) : every(symbol.declarations, isDeprecatedDeclaration); + return parentSymbol.flags & SymbolFlags.Interface ? some(symbol.declarations, isDeprecatedDeclaration) + : every(symbol.declarations, isDeprecatedDeclaration); } return !!symbol.valueDeclaration && isDeprecatedDeclaration(symbol.valueDeclaration) || length(symbol.declarations) && every(symbol.declarations, isDeprecatedDeclaration); @@ -2419,9 +2625,19 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return addDeprecatedSuggestionWorker(declarations, diagnostic); } - function addDeprecatedSuggestionWithSignature(location: Node, declaration: Node, deprecatedEntity: string | undefined, signatureString: string) { + function addDeprecatedSuggestionWithSignature( + location: Node, + declaration: Node, + deprecatedEntity: string | undefined, + signatureString: string, + ) { const diagnostic = deprecatedEntity - ? createDiagnosticForNode(location, Diagnostics.The_signature_0_of_1_is_deprecated, signatureString, deprecatedEntity) + ? createDiagnosticForNode( + location, + Diagnostics.The_signature_0_of_1_is_deprecated, + signatureString, + deprecatedEntity, + ) : createDiagnosticForNode(location, Diagnostics._0_is_deprecated, signatureString); return addDeprecatedSuggestionWorker(declaration, diagnostic); } @@ -2493,8 +2709,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { */ function mergeSymbol(target: Symbol, source: Symbol, unidirectional = false): Symbol { if ( - !(target.flags & getExcludedSymbolFlags(source.flags)) || - (source.flags | target.flags) & SymbolFlags.Assignment + !(target.flags & getExcludedSymbolFlags(source.flags)) + || (source.flags | target.flags) & SymbolFlags.Assignment ) { if (source === target) { // This can happen when an export assigned namespace exports something also erroneously exported at the top level @@ -2509,7 +2725,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { target = cloneSymbol(resolvedTarget); } // Javascript static-property-assignment declarations always merge, even though they are also values - if (source.flags & SymbolFlags.ValueModule && target.flags & SymbolFlags.ValueModule && target.constEnumOnlyModule && !source.constEnumOnlyModule) { + if ( + source.flags & SymbolFlags.ValueModule && target.flags & SymbolFlags.ValueModule + && target.constEnumOnlyModule && !source.constEnumOnlyModule + ) { // reset flag when merging instantiated module into value module that has only const enums target.constEnumOnlyModule = false; } @@ -2544,8 +2763,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } else { // error const isEitherEnum = !!(target.flags & SymbolFlags.Enum || source.flags & SymbolFlags.Enum); - const isEitherBlockScoped = !!(target.flags & SymbolFlags.BlockScopedVariable || source.flags & SymbolFlags.BlockScopedVariable); - const message = isEitherEnum ? Diagnostics.Enum_declarations_can_only_merge_with_namespace_or_other_enum_declarations + const isEitherBlockScoped = + !!(target.flags & SymbolFlags.BlockScopedVariable || source.flags & SymbolFlags.BlockScopedVariable); + const message = isEitherEnum + ? Diagnostics.Enum_declarations_can_only_merge_with_namespace_or_other_enum_declarations : isEitherBlockScoped ? Diagnostics.Cannot_redeclare_block_scoped_variable_0 : Diagnostics.Duplicate_identifier_0; const sourceSymbolFile = source.declarations && getSourceFileOfNode(source.declarations[0]); @@ -2556,11 +2777,27 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const symbolName = symbolToString(source); // Collect top-level duplicate identifier errors into one mapping, so we can then merge their diagnostics if there are a bunch - if (sourceSymbolFile && targetSymbolFile && amalgamatedDuplicates && !isEitherEnum && sourceSymbolFile !== targetSymbolFile) { - const firstFile = comparePaths(sourceSymbolFile.path, targetSymbolFile.path) === Comparison.LessThan ? sourceSymbolFile : targetSymbolFile; + if ( + sourceSymbolFile && targetSymbolFile && amalgamatedDuplicates && !isEitherEnum + && sourceSymbolFile !== targetSymbolFile + ) { + const firstFile = comparePaths(sourceSymbolFile.path, targetSymbolFile.path) === Comparison.LessThan + ? sourceSymbolFile : targetSymbolFile; const secondFile = firstFile === sourceSymbolFile ? targetSymbolFile : sourceSymbolFile; - const filesDuplicates = getOrUpdate(amalgamatedDuplicates, `${firstFile.path}|${secondFile.path}`, (): DuplicateInfoForFiles => ({ firstFile, secondFile, conflictingSymbols: new Map() })); - const conflictingSymbolInfo = getOrUpdate(filesDuplicates.conflictingSymbols, symbolName, (): DuplicateInfoForSymbol => ({ isBlockScoped: isEitherBlockScoped, firstFileLocations: [], secondFileLocations: [] })); + const filesDuplicates = getOrUpdate( + amalgamatedDuplicates, + `${firstFile.path}|${secondFile.path}`, + (): DuplicateInfoForFiles => ({ firstFile, secondFile, conflictingSymbols: new Map() }), + ); + const conflictingSymbolInfo = getOrUpdate( + filesDuplicates.conflictingSymbols, + symbolName, + (): DuplicateInfoForSymbol => ({ + isBlockScoped: isEitherBlockScoped, + firstFileLocations: [], + secondFileLocations: [], + }), + ); if (!isSourcePlainJs) addDuplicateLocations(conflictingSymbolInfo.firstFileLocations, source); if (!isTargetPlainJs) addDuplicateLocations(conflictingSymbolInfo.secondFileLocations, target); } @@ -2580,27 +2817,52 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } - function addDuplicateDeclarationErrorsForSymbols(target: Symbol, message: DiagnosticMessage, symbolName: string, source: Symbol) { + function addDuplicateDeclarationErrorsForSymbols( + target: Symbol, + message: DiagnosticMessage, + symbolName: string, + source: Symbol, + ) { forEach(target.declarations, node => { addDuplicateDeclarationError(node, message, symbolName, source.declarations); }); } - function addDuplicateDeclarationError(node: Declaration, message: DiagnosticMessage, symbolName: string, relatedNodes: readonly Declaration[] | undefined) { - const errorNode = (getExpandoInitializer(node, /*isPrototypeAssignment*/ false) ? getNameOfExpando(node) : getNameOfDeclaration(node)) || node; + function addDuplicateDeclarationError( + node: Declaration, + message: DiagnosticMessage, + symbolName: string, + relatedNodes: readonly Declaration[] | undefined, + ) { + const errorNode = (getExpandoInitializer(node, /*isPrototypeAssignment*/ false) ? getNameOfExpando(node) + : getNameOfDeclaration(node)) || node; const err = lookupOrIssueError(errorNode, message, symbolName); for (const relatedNode of relatedNodes || emptyArray) { - const adjustedNode = (getExpandoInitializer(relatedNode, /*isPrototypeAssignment*/ false) ? getNameOfExpando(relatedNode) : getNameOfDeclaration(relatedNode)) || relatedNode; + const adjustedNode = + (getExpandoInitializer(relatedNode, /*isPrototypeAssignment*/ false) ? getNameOfExpando(relatedNode) + : getNameOfDeclaration(relatedNode)) || relatedNode; if (adjustedNode === errorNode) continue; err.relatedInformation = err.relatedInformation || []; - const leadingMessage = createDiagnosticForNode(adjustedNode, Diagnostics._0_was_also_declared_here, symbolName); + const leadingMessage = createDiagnosticForNode( + adjustedNode, + Diagnostics._0_was_also_declared_here, + symbolName, + ); const followOnMessage = createDiagnosticForNode(adjustedNode, Diagnostics.and_here); - if (length(err.relatedInformation) >= 5 || some(err.relatedInformation, r => compareDiagnostics(r, followOnMessage) === Comparison.EqualTo || compareDiagnostics(r, leadingMessage) === Comparison.EqualTo)) continue; + if ( + length(err.relatedInformation) >= 5 + || some(err.relatedInformation, r => + compareDiagnostics(r, followOnMessage) === Comparison.EqualTo + || compareDiagnostics(r, leadingMessage) === Comparison.EqualTo) + ) continue; addRelatedInfo(err, !length(err.relatedInformation) ? leadingMessage : followOnMessage); } } - function combineSymbolTables(first: SymbolTable | undefined, second: SymbolTable | undefined): SymbolTable | undefined { + function combineSymbolTables( + first: SymbolTable | undefined, + second: SymbolTable | undefined, + ): SymbolTable | undefined { if (!first?.size) return second; if (!second?.size) return first; const combined = createSymbolTable(); @@ -2612,7 +2874,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function mergeSymbolTable(target: SymbolTable, source: SymbolTable, unidirectional = false) { source.forEach((sourceSymbol, id) => { const targetSymbol = target.get(id); - target.set(id, targetSymbol ? mergeSymbol(targetSymbol, sourceSymbol, unidirectional) : getMergedSymbol(sourceSymbol)); + target.set( + id, + targetSymbol ? mergeSymbol(targetSymbol, sourceSymbol, unidirectional) : getMergedSymbol(sourceSymbol), + ); }); } @@ -2635,7 +2900,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const moduleNotFoundError = !(moduleName.parent.parent.flags & NodeFlags.Ambient) ? Diagnostics.Invalid_module_name_in_augmentation_module_0_cannot_be_found : undefined; - let mainModule = resolveExternalModuleNameWorker(moduleName, moduleName, moduleNotFoundError, /*isForAugmentation*/ true); + let mainModule = resolveExternalModuleNameWorker( + moduleName, + moduleName, + moduleNotFoundError, + /*isForAugmentation*/ true, + ); if (!mainModule) { return; } @@ -2656,9 +2926,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { patternAmbientModuleAugmentations.set((moduleName as StringLiteral).text, merged); } else { - if (mainModule.exports?.get(InternalSymbolName.ExportStar) && moduleAugmentation.symbol.exports?.size) { + if ( + mainModule.exports?.get(InternalSymbolName.ExportStar) + && moduleAugmentation.symbol.exports?.size + ) { // We may need to merge the module augmentation's exports into the target symbols of the resolved exports - const resolvedExports = getResolvedMembersOrExportsOfSymbol(mainModule, MembersOrExportsResolutionKind.resolvedExports); + const resolvedExports = getResolvedMembersOrExportsOfSymbol( + mainModule, + MembersOrExportsResolutionKind.resolvedExports, + ); for (const [key, value] of arrayFrom(moduleAugmentation.symbol.exports.entries())) { if (resolvedExports.has(key) && !mainModule.exports.has(key)) { mergeSymbol(resolvedExports.get(key)!, value); @@ -2670,7 +2946,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } else { // moduleName will be a StringLiteral since this is not `declare global`. - error(moduleName, Diagnostics.Cannot_augment_module_0_because_it_resolves_to_a_non_module_entity, (moduleName as StringLiteral).text); + error( + moduleName, + Diagnostics.Cannot_augment_module_0_because_it_resolves_to_a_non_module_entity, + (moduleName as StringLiteral).text, + ); } } } @@ -2711,7 +2991,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (meaning) { const symbol = getMergedSymbol(symbols.get(name)); if (symbol) { - Debug.assert((getCheckFlags(symbol) & CheckFlags.Instantiated) === 0, "Should never get an instantiated symbol here."); + Debug.assert( + (getCheckFlags(symbol) & CheckFlags.Instantiated) === 0, + "Should never get an instantiated symbol here.", + ); if (symbol.flags & meaning) { return symbol; } @@ -2733,7 +3016,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { * @param parameterName a name of the parameter to get the symbols for. * @return a tuple of two symbols */ - function getSymbolsOfParameterPropertyDeclaration(parameter: ParameterPropertyDeclaration, parameterName: __String): [Symbol, Symbol] { + function getSymbolsOfParameterPropertyDeclaration( + parameter: ParameterPropertyDeclaration, + parameterName: __String, + ): [Symbol, Symbol] { const constructorDeclaration = parameter.parent; const classDeclaration = parameter.parent.parent; @@ -2744,7 +3030,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return [parameterSymbol, propertySymbol]; } - return Debug.fail("There should exist two symbols, one as property declaration and one as parameter declaration"); + return Debug.fail( + "There should exist two symbols, one as property declaration and one as parameter declaration", + ); } function isBlockScopedNameDeclaredBeforeUse(declaration: Declaration, usage: Node): boolean { @@ -2753,10 +3041,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const declContainer = getEnclosingBlockScopeContainer(declaration); if (declarationFile !== useFile) { if ( - (moduleKind && (declarationFile.externalModuleIndicator || useFile.externalModuleIndicator)) || - (!outFile(compilerOptions)) || - isInTypeQuery(usage) || - declaration.flags & NodeFlags.Ambient + (moduleKind && (declarationFile.externalModuleIndicator || useFile.externalModuleIndicator)) + || (!outFile(compilerOptions)) + || isInTypeQuery(usage) + || declaration.flags & NodeFlags.Ambient ) { // nodes are in different files and order cannot be determined return true; @@ -2770,17 +3058,25 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return sourceFiles.indexOf(declarationFile) <= sourceFiles.indexOf(useFile); } - if (declaration.pos <= usage.pos && !(isPropertyDeclaration(declaration) && isThisProperty(usage.parent) && !declaration.initializer && !declaration.exclamationToken)) { + if ( + declaration.pos <= usage.pos + && !(isPropertyDeclaration(declaration) && isThisProperty(usage.parent) && !declaration.initializer + && !declaration.exclamationToken) + ) { // declaration is before usage if (declaration.kind === SyntaxKind.BindingElement) { // still might be illegal if declaration and usage are both binding elements (eg var [a = b, b = b] = [1, 2]) const errorBindingElement = getAncestor(usage, SyntaxKind.BindingElement) as BindingElement; if (errorBindingElement) { - return findAncestor(errorBindingElement, isBindingElement) !== findAncestor(declaration, isBindingElement) || - declaration.pos < errorBindingElement.pos; + return findAncestor(errorBindingElement, isBindingElement) + !== findAncestor(declaration, isBindingElement) + || declaration.pos < errorBindingElement.pos; } // or it might be illegal if usage happens before parent variable is declared (eg var [a] = a) - return isBlockScopedNameDeclaredBeforeUse(getAncestor(declaration, SyntaxKind.VariableDeclaration) as Declaration, usage); + return isBlockScopedNameDeclaredBeforeUse( + getAncestor(declaration, SyntaxKind.VariableDeclaration) as Declaration, + usage, + ); } else if (declaration.kind === SyntaxKind.VariableDeclaration) { // still might be illegal if usage is in the initializer of the variable declaration (eg var a = a) @@ -2792,7 +3088,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } else if (isPropertyDeclaration(declaration)) { // still might be illegal if a self-referencing property initializer (eg private x = this.x) - return !isPropertyImmediatelyReferencedWithinDeclaration(declaration, usage, /*stopAtAnyPropertyDeclaration*/ false); + return !isPropertyImmediatelyReferencedWithinDeclaration( + declaration, + usage, + /*stopAtAnyPropertyDeclaration*/ false, + ); } else if (isParameterPropertyDeclaration(declaration, declaration.parent)) { // foo = this.bar is illegal in emitStandardClassFields when bar is a parameter property @@ -2813,7 +3113,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // or if usage is in a type context: // 1. inside a type query (typeof in type position) // 2. inside a jsdoc comment - if (usage.parent.kind === SyntaxKind.ExportSpecifier || (usage.parent.kind === SyntaxKind.ExportAssignment && (usage.parent as ExportAssignment).isExportEquals)) { + if ( + usage.parent.kind === SyntaxKind.ExportSpecifier + || (usage.parent.kind === SyntaxKind.ExportAssignment && (usage.parent as ExportAssignment).isExportEquals) + ) { // export specifiers do not use the variable, they only make it available for use return true; } @@ -2829,9 +3132,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if ( emitStandardClassFields && getContainingClass(declaration) - && (isPropertyDeclaration(declaration) || isParameterPropertyDeclaration(declaration, declaration.parent)) + && (isPropertyDeclaration(declaration) + || isParameterPropertyDeclaration(declaration, declaration.parent)) ) { - return !isPropertyImmediatelyReferencedWithinDeclaration(declaration, usage, /*stopAtAnyPropertyDeclaration*/ true); + return !isPropertyImmediatelyReferencedWithinDeclaration( + declaration, + usage, + /*stopAtAnyPropertyDeclaration*/ true, + ); } else { return true; @@ -2839,7 +3147,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } return false; - function isImmediatelyUsedInInitializerOfBlockScopedVariable(declaration: VariableDeclaration, usage: Node): boolean { + function isImmediatelyUsedInInitializerOfBlockScopedVariable( + declaration: VariableDeclaration, + usage: Node, + ): boolean { switch (declaration.parent.parent.kind) { case SyntaxKind.VariableStatement: case SyntaxKind.ForStatement: @@ -2854,7 +3165,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // ForIn/ForOf case - use site should not be used in expression part const grandparent = declaration.parent.parent; - return isForInOrOfStatement(grandparent) && isSameScopeDescendentOf(usage, grandparent.expression, declContainer); + return isForInOrOfStatement(grandparent) + && isSameScopeDescendentOf(usage, grandparent.expression, declContainer); } function isUsedInFunctionOrInstanceProperty(usage: Node, declaration: Node): boolean { @@ -2877,20 +3189,38 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (declaration.kind === SyntaxKind.MethodDeclaration) { return true; } - if (isPropertyDeclaration(declaration) && getContainingClass(usage) === getContainingClass(declaration)) { + if ( + isPropertyDeclaration(declaration) + && getContainingClass(usage) === getContainingClass(declaration) + ) { const propName = declaration.name; if (isIdentifier(propName) || isPrivateIdentifier(propName)) { const type = getTypeOfSymbol(getSymbolOfDeclaration(declaration)); - const staticBlocks = filter(declaration.parent.members, isClassStaticBlockDeclaration); - if (isPropertyInitializedInStaticBlocks(propName, type, staticBlocks, declaration.parent.pos, current.pos)) { + const staticBlocks = filter( + declaration.parent.members, + isClassStaticBlockDeclaration, + ); + if ( + isPropertyInitializedInStaticBlocks( + propName, + type, + staticBlocks, + declaration.parent.pos, + current.pos, + ) + ) { return true; } } } } else { - const isDeclarationInstanceProperty = declaration.kind === SyntaxKind.PropertyDeclaration && !isStatic(declaration); - if (!isDeclarationInstanceProperty || getContainingClass(usage) !== getContainingClass(declaration)) { + const isDeclarationInstanceProperty = declaration.kind === SyntaxKind.PropertyDeclaration + && !isStatic(declaration); + if ( + !isDeclarationInstanceProperty + || getContainingClass(usage) !== getContainingClass(declaration) + ) { return true; } } @@ -2901,7 +3231,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } /** stopAtAnyPropertyDeclaration is used for detecting ES-standard class field use-before-def errors */ - function isPropertyImmediatelyReferencedWithinDeclaration(declaration: PropertyDeclaration | ParameterPropertyDeclaration, usage: Node, stopAtAnyPropertyDeclaration: boolean) { + function isPropertyImmediatelyReferencedWithinDeclaration( + declaration: PropertyDeclaration | ParameterPropertyDeclaration, + usage: Node, + stopAtAnyPropertyDeclaration: boolean, + ) { // always legal if usage is after declaration if (usage.end > declaration.end) { return false; @@ -2919,9 +3253,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return true; case SyntaxKind.PropertyDeclaration: // even when stopping at any property declaration, they need to come from the same class - return stopAtAnyPropertyDeclaration && - (isPropertyDeclaration(declaration) && node.parent === declaration.parent - || isParameterPropertyDeclaration(declaration, declaration.parent) && node.parent === declaration.parent.parent) + return stopAtAnyPropertyDeclaration + && (isPropertyDeclaration(declaration) && node.parent === declaration.parent + || isParameterPropertyDeclaration(declaration, declaration.parent) + && node.parent === declaration.parent.parent) ? "quit" : true; case SyntaxKind.Block: switch (node.parent.kind) { @@ -2959,7 +3294,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (target >= ScriptTarget.ES2015) { const links = getNodeLinks(functionLocation); if (links.declarationRequiresScopeChange === undefined) { - links.declarationRequiresScopeChange = forEach(functionLocation.parameters, requiresScopeChange) || false; + links.declarationRequiresScopeChange = forEach(functionLocation.parameters, requiresScopeChange) + || false; } return !links.declarationRequiresScopeChange; } @@ -2983,7 +3319,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { case SyntaxKind.GetAccessor: case SyntaxKind.SetAccessor: case SyntaxKind.PropertyAssignment: - return requiresScopeChangeWorker((node as MethodDeclaration | AccessorDeclaration | PropertyAssignment).name); + return requiresScopeChangeWorker( + (node as MethodDeclaration | AccessorDeclaration | PropertyAssignment).name, + ); case SyntaxKind.PropertyDeclaration: // static properties in classes introduce temporary variables if (hasStaticModifier(node)) { @@ -3027,7 +3365,17 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { excludeGlobals = false, getSpellingSuggestions = true, ): Symbol | undefined { - return resolveNameHelper(location, name, meaning, nameNotFoundMessage, nameArg, isUse, excludeGlobals, getSpellingSuggestions, getSymbol); + return resolveNameHelper( + location, + name, + meaning, + nameNotFoundMessage, + nameArg, + isUse, + excludeGlobals, + getSpellingSuggestions, + getSymbol, + ); } function resolveNameHelper( @@ -3046,7 +3394,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { let lastLocation: Node | undefined; let lastSelfReferenceLocation: Declaration | undefined; let propertyWithInvalidInitializer: PropertyDeclaration | undefined; - let associatedDeclarationForContainingInitializerOrBindingName: ParameterDeclaration | BindingElement | undefined; + let associatedDeclarationForContainingInitializerOrBindingName: + | ParameterDeclaration + | BindingElement + | undefined; let withinDeferredContext = false; const errorLocation = location; let grandparent: Node; @@ -3069,7 +3420,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (canHaveLocals(location) && location.locals && !isGlobalSourceFile(location)) { if (result = lookup(location.locals, name, meaning)) { let useResult = true; - if (isFunctionLike(location) && lastLocation && lastLocation !== (location as FunctionLikeDeclaration).body) { + if ( + isFunctionLike(location) && lastLocation + && lastLocation !== (location as FunctionLikeDeclaration).body + ) { // symbol lookup restrictions for function-like declarations // - Type parameters of a function are in scope in the entire function declaration, including the parameter // list and return type. However, local types are only in scope in the function body. @@ -3079,11 +3433,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (meaning & result.flags & SymbolFlags.Type && lastLocation.kind !== SyntaxKind.JSDoc) { useResult = result.flags & SymbolFlags.TypeParameter // type parameters are visible in parameter list, return type and type parameter list - ? lastLocation === (location as FunctionLikeDeclaration).type || - lastLocation.kind === SyntaxKind.Parameter || - lastLocation.kind === SyntaxKind.JSDocParameterTag || - lastLocation.kind === SyntaxKind.JSDocReturnTag || - lastLocation.kind === SyntaxKind.TypeParameter + ? lastLocation === (location as FunctionLikeDeclaration).type + || lastLocation.kind === SyntaxKind.Parameter + || lastLocation.kind === SyntaxKind.JSDocParameterTag + || lastLocation.kind === SyntaxKind.JSDocReturnTag + || lastLocation.kind === SyntaxKind.TypeParameter // local types not visible outside the function body : false; } @@ -3097,10 +3451,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // technically for parameter list case here we might mix parameters and variables declared in function, // however it is detected separately when checking initializers of parameters // to make sure that they reference no variables declared after them. - useResult = lastLocation.kind === SyntaxKind.Parameter || - ( - lastLocation === (location as FunctionLikeDeclaration).type && - !!findAncestor(result.valueDeclaration, isParameter) + useResult = lastLocation.kind === SyntaxKind.Parameter + || ( + lastLocation === (location as FunctionLikeDeclaration).type + && !!findAncestor(result.valueDeclaration, isParameter) ); } } @@ -3126,8 +3480,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { isInExternalModule = true; // falls through case SyntaxKind.ModuleDeclaration: - const moduleExports = getSymbolOfDeclaration(location as SourceFile | ModuleDeclaration)?.exports || emptySymbols; - if (location.kind === SyntaxKind.SourceFile || (isModuleDeclaration(location) && location.flags & NodeFlags.Ambient && !isGlobalScopeAugmentation(location))) { + const moduleExports = getSymbolOfDeclaration(location as SourceFile | ModuleDeclaration)?.exports + || emptySymbols; + if ( + location.kind === SyntaxKind.SourceFile + || (isModuleDeclaration(location) && location.flags & NodeFlags.Ambient + && !isGlobalScopeAugmentation(location)) + ) { // It's an external module. First see if the module has an export default and if the local // name of that export default matches. if (result = moduleExports.get(InternalSymbolName.Default)) { @@ -3151,17 +3510,24 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // which is not the desired behavior. const moduleExport = moduleExports.get(name); if ( - moduleExport && - moduleExport.flags === SymbolFlags.Alias && - (getDeclarationOfKind(moduleExport, SyntaxKind.ExportSpecifier) || getDeclarationOfKind(moduleExport, SyntaxKind.NamespaceExport)) + moduleExport + && moduleExport.flags === SymbolFlags.Alias + && (getDeclarationOfKind(moduleExport, SyntaxKind.ExportSpecifier) + || getDeclarationOfKind(moduleExport, SyntaxKind.NamespaceExport)) ) { break; } } // ES6 exports are also visible locally (except for 'default'), but commonjs exports are not (except typedefs) - if (name !== InternalSymbolName.Default && (result = lookup(moduleExports, name, meaning & SymbolFlags.ModuleMember))) { - if (isSourceFile(location) && location.commonJsModuleIndicator && !result.declarations?.some(isJSDocTypeAlias)) { + if ( + name !== InternalSymbolName.Default + && (result = lookup(moduleExports, name, meaning & SymbolFlags.ModuleMember)) + ) { + if ( + isSourceFile(location) && location.commonJsModuleIndicator + && !result.declarations?.some(isJSDocTypeAlias) + ) { result = undefined; } else { @@ -3170,14 +3536,27 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } break; case SyntaxKind.EnumDeclaration: - if (result = lookup(getSymbolOfDeclaration(location as EnumDeclaration)?.exports || emptySymbols, name, meaning & SymbolFlags.EnumMember)) { - if (nameNotFoundMessage && getIsolatedModules(compilerOptions) && !(location.flags & NodeFlags.Ambient) && getSourceFileOfNode(location) !== getSourceFileOfNode(result.valueDeclaration)) { + if ( + result = lookup( + getSymbolOfDeclaration(location as EnumDeclaration)?.exports || emptySymbols, + name, + meaning & SymbolFlags.EnumMember, + ) + ) { + if ( + nameNotFoundMessage && getIsolatedModules(compilerOptions) + && !(location.flags & NodeFlags.Ambient) + && getSourceFileOfNode(location) !== getSourceFileOfNode(result.valueDeclaration) + ) { error( errorLocation, - Diagnostics.Cannot_access_0_from_another_file_without_qualification_when_1_is_enabled_Use_2_instead, + Diagnostics + .Cannot_access_0_from_another_file_without_qualification_when_1_is_enabled_Use_2_instead, unescapeLeadingUnderscores(name), isolatedModulesLikeFlagName, - `${unescapeLeadingUnderscores(getSymbolOfNode(location)!.escapedName)}.${unescapeLeadingUnderscores(name)}`, + `${unescapeLeadingUnderscores(getSymbolOfNode(location)!.escapedName)}.${ + unescapeLeadingUnderscores(name) + }`, ); } break loop; @@ -3207,7 +3586,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // The below is used to lookup type parameters within a class or interface, as they are added to the class/interface locals // These can never be latebound, so the symbol's raw members are sufficient. `getMembersOfNode` cannot be used, as it would // trigger resolving late-bound names, which we may already be in the process of doing while we're here! - if (result = lookup(getSymbolOfDeclaration(location as ClassLikeDeclaration | InterfaceDeclaration).members || emptySymbols, name, meaning & SymbolFlags.Type)) { + if ( + result = lookup( + getSymbolOfDeclaration(location as ClassLikeDeclaration | InterfaceDeclaration).members + || emptySymbols, + name, + meaning & SymbolFlags.Type, + ) + ) { if (!isTypeParameterSymbolDeclaredInContainer(result, location)) { // ignore type parameters not declared in this container result = undefined; @@ -3234,11 +3620,24 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { break; case SyntaxKind.ExpressionWithTypeArguments: // The type parameters of a class are not in scope in the base class expression. - if (lastLocation === (location as ExpressionWithTypeArguments).expression && (location.parent as HeritageClause).token === SyntaxKind.ExtendsKeyword) { + if ( + lastLocation === (location as ExpressionWithTypeArguments).expression + && (location.parent as HeritageClause).token === SyntaxKind.ExtendsKeyword + ) { const container = location.parent.parent; - if (isClassLike(container) && (result = lookup(getSymbolOfDeclaration(container).members!, name, meaning & SymbolFlags.Type))) { + if ( + isClassLike(container) + && (result = lookup( + getSymbolOfDeclaration(container).members!, + name, + meaning & SymbolFlags.Type, + )) + ) { if (nameNotFoundMessage) { - error(errorLocation, Diagnostics.Base_class_expressions_cannot_reference_class_type_parameters); + error( + errorLocation, + Diagnostics.Base_class_expressions_cannot_reference_class_type_parameters, + ); } return undefined; } @@ -3256,9 +3655,20 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { grandparent = location.parent.parent; if (isClassLike(grandparent) || grandparent.kind === SyntaxKind.InterfaceDeclaration) { // A reference to this grandparent's type parameters would be an error - if (result = lookup(getSymbolOfDeclaration(grandparent as ClassLikeDeclaration | InterfaceDeclaration).members!, name, meaning & SymbolFlags.Type)) { + if ( + result = lookup( + getSymbolOfDeclaration(grandparent as ClassLikeDeclaration | InterfaceDeclaration) + .members!, + name, + meaning & SymbolFlags.Type, + ) + ) { if (nameNotFoundMessage) { - error(errorLocation, Diagnostics.A_computed_property_name_cannot_reference_a_type_parameter_from_its_containing_type); + error( + errorLocation, + Diagnostics + .A_computed_property_name_cannot_reference_a_type_parameter_from_its_containing_type, + ); } return undefined; } @@ -3320,7 +3730,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // declare function y(x: T): any; // @param(1 as T) // <-- T should resolve to the type alias outside of class C // class C {} - if (location.parent && (isClassElement(location.parent) || location.parent.kind === SyntaxKind.ClassDeclaration)) { + if ( + location.parent + && (isClassElement(location.parent) || location.parent.kind === SyntaxKind.ClassDeclaration) + ) { location = location.parent; } break; @@ -3336,23 +3749,28 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { case SyntaxKind.Parameter: if ( lastLocation && ( - lastLocation === (location as ParameterDeclaration).initializer || - lastLocation === (location as ParameterDeclaration).name && isBindingPattern(lastLocation) + lastLocation === (location as ParameterDeclaration).initializer + || lastLocation === (location as ParameterDeclaration).name + && isBindingPattern(lastLocation) ) ) { if (!associatedDeclarationForContainingInitializerOrBindingName) { - associatedDeclarationForContainingInitializerOrBindingName = location as ParameterDeclaration; + associatedDeclarationForContainingInitializerOrBindingName = + location as ParameterDeclaration; } } break; case SyntaxKind.BindingElement: if ( lastLocation && ( - lastLocation === (location as BindingElement).initializer || - lastLocation === (location as BindingElement).name && isBindingPattern(lastLocation) + lastLocation === (location as BindingElement).initializer + || lastLocation === (location as BindingElement).name && isBindingPattern(lastLocation) ) ) { - if (isParameterDeclaration(location as BindingElement) && !associatedDeclarationForContainingInitializerOrBindingName) { + if ( + isParameterDeclaration(location as BindingElement) + && !associatedDeclarationForContainingInitializerOrBindingName + ) { associatedDeclarationForContainingInitializerOrBindingName = location as BindingElement; } } @@ -3369,9 +3787,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { case SyntaxKind.ExportSpecifier: // External module export bindings shouldn't be resolved to local symbols. if ( - lastLocation && - lastLocation === (location as ExportSpecifier).propertyName && - (location as ExportSpecifier).parent.parent.moduleSpecifier + lastLocation + && lastLocation === (location as ExportSpecifier).propertyName + && (location as ExportSpecifier).parent.parent.moduleSpecifier ) { location = location.parent.parent.parent; } @@ -3381,9 +3799,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { lastSelfReferenceLocation = location; } lastLocation = location; - location = isJSDocTemplateTag(location) ? getEffectiveContainerForJSDocTemplateTag(location) || location.parent : - isJSDocParameterTag(location) || isJSDocReturnTag(location) ? getHostSignatureFromJSDoc(location) || location.parent : - location.parent; + location = isJSDocTemplateTag(location) + ? getEffectiveContainerForJSDocTemplateTag(location) || location.parent + : isJSDocParameterTag(location) || isJSDocReturnTag(location) + ? getHostSignatureFromJSDoc(location) || location.parent + : location.parent; } // We just climbed up parents looking for the name, meaning that we started in a descendant node of `lastLocation`. @@ -3423,9 +3843,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // with emitStandardClassFields because the scope semantics are different. error( errorLocation, - errorLocation && propertyWithInvalidInitializer.type && textRangeContainsPositionInclusive(propertyWithInvalidInitializer.type, errorLocation.pos) - ? Diagnostics.Type_of_instance_member_variable_0_cannot_reference_identifier_1_declared_in_the_constructor - : Diagnostics.Initializer_of_instance_member_variable_0_cannot_reference_identifier_1_declared_in_the_constructor, + errorLocation && propertyWithInvalidInitializer.type + && textRangeContainsPositionInclusive(propertyWithInvalidInitializer.type, errorLocation.pos) + ? Diagnostics + .Type_of_instance_member_variable_0_cannot_reference_identifier_1_declared_in_the_constructor + : Diagnostics + .Initializer_of_instance_member_variable_0_cannot_reference_identifier_1_declared_in_the_constructor, declarationNameToString(propertyWithInvalidInitializer.name), diagnosticName(nameArg!), ); @@ -3438,16 +3861,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (nameNotFoundMessage) { addLazyDiagnostic(() => { if ( - !errorLocation || - errorLocation.parent.kind !== SyntaxKind.JSDocLink && - !checkAndReportErrorForMissingPrefix(errorLocation, name, nameArg!) && // TODO: GH#18217 - !checkAndReportErrorForInvalidInitializer() && - !checkAndReportErrorForExtendingInterface(errorLocation) && - !checkAndReportErrorForUsingTypeAsNamespace(errorLocation, name, meaning) && - !checkAndReportErrorForExportingPrimitiveType(errorLocation, name) && - !checkAndReportErrorForUsingNamespaceAsTypeOrValue(errorLocation, name, meaning) && - !checkAndReportErrorForUsingTypeAsValue(errorLocation, name, meaning) && - !checkAndReportErrorForUsingValueAsType(errorLocation, name, meaning) + !errorLocation + || errorLocation.parent.kind !== SyntaxKind.JSDocLink + && !checkAndReportErrorForMissingPrefix(errorLocation, name, nameArg!) // TODO: GH#18217 + && !checkAndReportErrorForInvalidInitializer() + && !checkAndReportErrorForExtendingInterface(errorLocation) + && !checkAndReportErrorForUsingTypeAsNamespace(errorLocation, name, meaning) + && !checkAndReportErrorForExportingPrimitiveType(errorLocation, name) + && !checkAndReportErrorForUsingNamespaceAsTypeOrValue(errorLocation, name, meaning) + && !checkAndReportErrorForUsingTypeAsValue(errorLocation, name, meaning) + && !checkAndReportErrorForUsingValueAsType(errorLocation, name, meaning) ) { let suggestion: Symbol | undefined; let suggestedLib: string | undefined; @@ -3461,22 +3884,39 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // then spelling suggestions if (!suggestedLib && getSpellingSuggestions && suggestionCount < maximumSuggestionCount) { suggestion = getSuggestedSymbolForNonexistentSymbol(originalLocation, name, meaning); - const isGlobalScopeAugmentationDeclaration = suggestion?.valueDeclaration && isAmbientModule(suggestion.valueDeclaration) && isGlobalScopeAugmentation(suggestion.valueDeclaration); + const isGlobalScopeAugmentationDeclaration = suggestion?.valueDeclaration + && isAmbientModule(suggestion.valueDeclaration) + && isGlobalScopeAugmentation(suggestion.valueDeclaration); if (isGlobalScopeAugmentationDeclaration) { suggestion = undefined; } if (suggestion) { const suggestionName = symbolToString(suggestion); - const isUncheckedJS = isUncheckedJSSuggestion(originalLocation, suggestion, /*excludeClasses*/ false); - const message = meaning === SymbolFlags.Namespace || nameArg && typeof nameArg !== "string" && nodeIsSynthesized(nameArg) ? Diagnostics.Cannot_find_namespace_0_Did_you_mean_1 + const isUncheckedJS = isUncheckedJSSuggestion( + originalLocation, + suggestion, + /*excludeClasses*/ false, + ); + const message = meaning === SymbolFlags.Namespace + || nameArg && typeof nameArg !== "string" && nodeIsSynthesized(nameArg) + ? Diagnostics.Cannot_find_namespace_0_Did_you_mean_1 : isUncheckedJS ? Diagnostics.Could_not_find_name_0_Did_you_mean_1 : Diagnostics.Cannot_find_name_0_Did_you_mean_1; - const diagnostic = createError(errorLocation, message, diagnosticName(nameArg!), suggestionName); + const diagnostic = createError( + errorLocation, + message, + diagnosticName(nameArg!), + suggestionName, + ); addErrorOrSuggestion(!isUncheckedJS, diagnostic); if (suggestion.valueDeclaration) { addRelatedInfo( diagnostic, - createDiagnosticForNode(suggestion.valueDeclaration, Diagnostics._0_is_declared_here, suggestionName), + createDiagnosticForNode( + suggestion.valueDeclaration, + Diagnostics._0_is_declared_here, + suggestionName, + ), ); } } @@ -3510,41 +3950,87 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // try to resolve name in /*1*/ which is used in variable position, // we want to check for block-scoped if ( - errorLocation && - (meaning & SymbolFlags.BlockScopedVariable || - ((meaning & SymbolFlags.Class || meaning & SymbolFlags.Enum) && (meaning & SymbolFlags.Value) === SymbolFlags.Value)) + errorLocation + && (meaning & SymbolFlags.BlockScopedVariable + || ((meaning & SymbolFlags.Class || meaning & SymbolFlags.Enum) + && (meaning & SymbolFlags.Value) === SymbolFlags.Value)) ) { const exportOrLocalSymbol = getExportSymbolOfValueSymbolIfExported(result!); - if (exportOrLocalSymbol.flags & SymbolFlags.BlockScopedVariable || exportOrLocalSymbol.flags & SymbolFlags.Class || exportOrLocalSymbol.flags & SymbolFlags.Enum) { + if ( + exportOrLocalSymbol.flags & SymbolFlags.BlockScopedVariable + || exportOrLocalSymbol.flags & SymbolFlags.Class || exportOrLocalSymbol.flags & SymbolFlags.Enum + ) { checkResolvedBlockScopedVariable(exportOrLocalSymbol, errorLocation); } } // If we're in an external module, we can't reference value symbols created from UMD export declarations - if (result && isInExternalModule && (meaning & SymbolFlags.Value) === SymbolFlags.Value && !(originalLocation!.flags & NodeFlags.JSDoc)) { + if ( + result && isInExternalModule && (meaning & SymbolFlags.Value) === SymbolFlags.Value + && !(originalLocation!.flags & NodeFlags.JSDoc) + ) { const merged = getMergedSymbol(result); - if (length(merged.declarations) && every(merged.declarations, d => isNamespaceExportDeclaration(d) || isSourceFile(d) && !!d.symbol.globalExports)) { - errorOrSuggestion(!compilerOptions.allowUmdGlobalAccess, errorLocation!, Diagnostics._0_refers_to_a_UMD_global_but_the_current_file_is_a_module_Consider_adding_an_import_instead, unescapeLeadingUnderscores(name)); + if ( + length(merged.declarations) + && every( + merged.declarations, + d => isNamespaceExportDeclaration(d) || isSourceFile(d) && !!d.symbol.globalExports, + ) + ) { + errorOrSuggestion( + !compilerOptions.allowUmdGlobalAccess, + errorLocation!, + Diagnostics + ._0_refers_to_a_UMD_global_but_the_current_file_is_a_module_Consider_adding_an_import_instead, + unescapeLeadingUnderscores(name), + ); } } // If we're in a parameter initializer or binding name, we can't reference the values of the parameter whose initializer we're within or parameters to the right - if (result && associatedDeclarationForContainingInitializerOrBindingName && !withinDeferredContext && (meaning & SymbolFlags.Value) === SymbolFlags.Value) { + if ( + result && associatedDeclarationForContainingInitializerOrBindingName && !withinDeferredContext + && (meaning & SymbolFlags.Value) === SymbolFlags.Value + ) { const candidate = getMergedSymbol(getLateBoundSymbol(result)); - const root = getRootDeclaration(associatedDeclarationForContainingInitializerOrBindingName) as ParameterDeclaration; + const root = getRootDeclaration( + associatedDeclarationForContainingInitializerOrBindingName, + ) as ParameterDeclaration; // A parameter initializer or binding pattern initializer within a parameter cannot refer to itself - if (candidate === getSymbolOfDeclaration(associatedDeclarationForContainingInitializerOrBindingName)) { - error(errorLocation, Diagnostics.Parameter_0_cannot_reference_itself, declarationNameToString(associatedDeclarationForContainingInitializerOrBindingName.name)); + if ( + candidate === getSymbolOfDeclaration(associatedDeclarationForContainingInitializerOrBindingName) + ) { + error( + errorLocation, + Diagnostics.Parameter_0_cannot_reference_itself, + declarationNameToString(associatedDeclarationForContainingInitializerOrBindingName.name), + ); } // And it cannot refer to any declarations which come after it - else if (candidate.valueDeclaration && candidate.valueDeclaration.pos > associatedDeclarationForContainingInitializerOrBindingName.pos && root.parent.locals && lookup(root.parent.locals, candidate.escapedName, meaning) === candidate) { - error(errorLocation, Diagnostics.Parameter_0_cannot_reference_identifier_1_declared_after_it, declarationNameToString(associatedDeclarationForContainingInitializerOrBindingName.name), declarationNameToString(errorLocation as Identifier)); + else if ( + candidate.valueDeclaration + && candidate.valueDeclaration.pos + > associatedDeclarationForContainingInitializerOrBindingName.pos + && root.parent.locals + && lookup(root.parent.locals, candidate.escapedName, meaning) === candidate + ) { + error( + errorLocation, + Diagnostics.Parameter_0_cannot_reference_identifier_1_declared_after_it, + declarationNameToString(associatedDeclarationForContainingInitializerOrBindingName.name), + declarationNameToString(errorLocation as Identifier), + ); } } - if (result && errorLocation && meaning & SymbolFlags.Value && result.flags & SymbolFlags.Alias && !(result.flags & SymbolFlags.Value) && !isValidTypeOnlyAliasUseSite(errorLocation)) { + if ( + result && errorLocation && meaning & SymbolFlags.Value && result.flags & SymbolFlags.Alias + && !(result.flags & SymbolFlags.Value) && !isValidTypeOnlyAliasUseSite(errorLocation) + ) { const typeOnlyDeclaration = getTypeOnlyAliasDeclaration(result, SymbolFlags.Value); if (typeOnlyDeclaration) { - const message = typeOnlyDeclaration.kind === SyntaxKind.ExportSpecifier || typeOnlyDeclaration.kind === SyntaxKind.ExportDeclaration || typeOnlyDeclaration.kind === SyntaxKind.NamespaceExport + const message = typeOnlyDeclaration.kind === SyntaxKind.ExportSpecifier + || typeOnlyDeclaration.kind === SyntaxKind.ExportDeclaration + || typeOnlyDeclaration.kind === SyntaxKind.NamespaceExport ? Diagnostics._0_cannot_be_used_as_a_value_because_it_was_exported_using_export_type : Diagnostics._0_cannot_be_used_as_a_value_because_it_was_imported_using_import_type; const unescapedName = unescapeLeadingUnderscores(name); @@ -3560,13 +4046,19 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return result; } - function addTypeOnlyDeclarationRelatedInfo(diagnostic: Diagnostic, typeOnlyDeclaration: TypeOnlyCompatibleAliasDeclaration | undefined, unescapedName: string) { + function addTypeOnlyDeclarationRelatedInfo( + diagnostic: Diagnostic, + typeOnlyDeclaration: TypeOnlyCompatibleAliasDeclaration | undefined, + unescapedName: string, + ) { if (!typeOnlyDeclaration) return diagnostic; return addRelatedInfo( diagnostic, createDiagnosticForNode( typeOnlyDeclaration, - typeOnlyDeclaration.kind === SyntaxKind.ExportSpecifier || typeOnlyDeclaration.kind === SyntaxKind.ExportDeclaration || typeOnlyDeclaration.kind === SyntaxKind.NamespaceExport + typeOnlyDeclaration.kind === SyntaxKind.ExportSpecifier + || typeOnlyDeclaration.kind === SyntaxKind.ExportDeclaration + || typeOnlyDeclaration.kind === SyntaxKind.NamespaceExport ? Diagnostics._0_was_exported_here : Diagnostics._0_was_imported_here, unescapedName, @@ -3578,15 +4070,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (location.kind !== SyntaxKind.ArrowFunction && location.kind !== SyntaxKind.FunctionExpression) { // initializers in instance property declaration of class like entities are executed in constructor and thus deferred return isTypeQueryNode(location) || (( - isFunctionLikeDeclaration(location) || - (location.kind === SyntaxKind.PropertyDeclaration && !isStatic(location)) + isFunctionLikeDeclaration(location) + || (location.kind === SyntaxKind.PropertyDeclaration && !isStatic(location)) ) && (!lastLocation || lastLocation !== (location as SignatureDeclaration | PropertyDeclaration).name)); // A name is evaluated within the enclosing scope - so it shouldn't count as deferred } if (lastLocation && lastLocation === (location as FunctionExpression | ArrowFunction).name) { return false; } // generator functions and async functions are not inlined in control flow when immediately invoked - if ((location as FunctionExpression | ArrowFunction).asteriskToken || hasSyntacticModifier(location, ModifierFlags.Async)) { + if ( + (location as FunctionExpression | ArrowFunction).asteriskToken + || hasSyntacticModifier(location, ModifierFlags.Async) + ) { return true; } return !getImmediatelyInvokedFunctionExpression(location); @@ -3615,7 +4110,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function diagnosticName(nameArg: __String | Identifier | PrivateIdentifier) { - return isString(nameArg) ? unescapeLeadingUnderscores(nameArg as __String) : declarationNameToString(nameArg as Identifier); + return isString(nameArg) ? unescapeLeadingUnderscores(nameArg as __String) + : declarationNameToString(nameArg as Identifier); } function isTypeParameterSymbolDeclaredInContainer(symbol: Symbol, container: Node) { @@ -3624,7 +4120,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (decl.kind === SyntaxKind.TypeParameter) { const parent = isJSDocTemplateTag(decl.parent) ? getJSDocHost(decl.parent) : decl.parent; if (parent === container) { - return !(isJSDocTemplateTag(decl.parent) && find((decl.parent.parent as JSDoc).tags, isJSDocTypeAlias)); + return !(isJSDocTemplateTag(decl.parent) + && find((decl.parent.parent as JSDoc).tags, isJSDocTypeAlias)); } } } @@ -3633,12 +4130,23 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return false; } - function checkAndReportErrorForMissingPrefix(errorLocation: Node, name: __String, nameArg: __String | Identifier): boolean { - if (!isIdentifier(errorLocation) || errorLocation.escapedText !== name || isTypeReferenceIdentifier(errorLocation) || isInTypeQuery(errorLocation)) { + function checkAndReportErrorForMissingPrefix( + errorLocation: Node, + name: __String, + nameArg: __String | Identifier, + ): boolean { + if ( + !isIdentifier(errorLocation) || errorLocation.escapedText !== name + || isTypeReferenceIdentifier(errorLocation) || isInTypeQuery(errorLocation) + ) { return false; } - const container = getThisContainer(errorLocation, /*includeArrowFunctions*/ false, /*includeClassComputedPropertyName*/ false); + const container = getThisContainer( + errorLocation, + /*includeArrowFunctions*/ false, + /*includeClassComputedPropertyName*/ false, + ); let location: Node = container; while (location) { if (isClassLike(location.parent)) { @@ -3650,7 +4158,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // Check to see if a static member exists. const constructorType = getTypeOfSymbol(classSymbol); if (getPropertyOfType(constructorType, name)) { - error(errorLocation, Diagnostics.Cannot_find_name_0_Did_you_mean_the_static_member_1_0, diagnosticName(nameArg), symbolToString(classSymbol)); + error( + errorLocation, + Diagnostics.Cannot_find_name_0_Did_you_mean_the_static_member_1_0, + diagnosticName(nameArg), + symbolToString(classSymbol), + ); return true; } @@ -3659,7 +4172,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (location === container && !isStatic(location)) { const instanceType = (getDeclaredTypeOfSymbol(classSymbol) as InterfaceType).thisType!; // TODO: GH#18217 if (getPropertyOfType(instanceType, name)) { - error(errorLocation, Diagnostics.Cannot_find_name_0_Did_you_mean_the_instance_member_this_0, diagnosticName(nameArg)); + error( + errorLocation, + Diagnostics.Cannot_find_name_0_Did_you_mean_the_instance_member_this_0, + diagnosticName(nameArg), + ); return true; } } @@ -3673,7 +4190,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function checkAndReportErrorForExtendingInterface(errorLocation: Node): boolean { const expression = getEntityNameForExtendingInterface(errorLocation); if (expression && resolveEntityName(expression, SymbolFlags.Interface, /*ignoreErrors*/ true)) { - error(errorLocation, Diagnostics.Cannot_extend_an_interface_0_Did_you_mean_implements, getTextOfNode(expression)); + error( + errorLocation, + Diagnostics.Cannot_extend_an_interface_0_Did_you_mean_implements, + getTextOfNode(expression), + ); return true; } return false; @@ -3697,27 +4218,48 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } - function checkAndReportErrorForUsingTypeAsNamespace(errorLocation: Node, name: __String, meaning: SymbolFlags): boolean { + function checkAndReportErrorForUsingTypeAsNamespace( + errorLocation: Node, + name: __String, + meaning: SymbolFlags, + ): boolean { const namespaceMeaning = SymbolFlags.Namespace | (isInJSFile(errorLocation) ? SymbolFlags.Value : 0); if (meaning === namespaceMeaning) { - const symbol = resolveSymbol(resolveName(errorLocation, name, SymbolFlags.Type & ~namespaceMeaning, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ false)); + const symbol = resolveSymbol( + resolveName( + errorLocation, + name, + SymbolFlags.Type & ~namespaceMeaning, + /*nameNotFoundMessage*/ undefined, + /*nameArg*/ undefined, + /*isUse*/ false, + ), + ); const parent = errorLocation.parent; if (symbol) { if (isQualifiedName(parent)) { - Debug.assert(parent.left === errorLocation, "Should only be resolving left side of qualified name as a namespace"); + Debug.assert( + parent.left === errorLocation, + "Should only be resolving left side of qualified name as a namespace", + ); const propName = parent.right.escapedText; const propType = getPropertyOfType(getDeclaredTypeOfSymbol(symbol), propName); if (propType) { error( parent, - Diagnostics.Cannot_access_0_1_because_0_is_a_type_but_not_a_namespace_Did_you_mean_to_retrieve_the_type_of_the_property_1_in_0_with_0_1, + Diagnostics + .Cannot_access_0_1_because_0_is_a_type_but_not_a_namespace_Did_you_mean_to_retrieve_the_type_of_the_property_1_in_0_with_0_1, unescapeLeadingUnderscores(name), unescapeLeadingUnderscores(propName), ); return true; } } - error(errorLocation, Diagnostics._0_only_refers_to_a_type_but_is_being_used_as_a_namespace_here, unescapeLeadingUnderscores(name)); + error( + errorLocation, + Diagnostics._0_only_refers_to_a_type_but_is_being_used_as_a_namespace_here, + unescapeLeadingUnderscores(name), + ); return true; } } @@ -3725,11 +4267,28 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return false; } - function checkAndReportErrorForUsingValueAsType(errorLocation: Node, name: __String, meaning: SymbolFlags): boolean { + function checkAndReportErrorForUsingValueAsType( + errorLocation: Node, + name: __String, + meaning: SymbolFlags, + ): boolean { if (meaning & (SymbolFlags.Type & ~SymbolFlags.Namespace)) { - const symbol = resolveSymbol(resolveName(errorLocation, name, ~SymbolFlags.Type & SymbolFlags.Value, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ false)); + const symbol = resolveSymbol( + resolveName( + errorLocation, + name, + ~SymbolFlags.Type & SymbolFlags.Value, + /*nameNotFoundMessage*/ undefined, + /*nameArg*/ undefined, + /*isUse*/ false, + ), + ); if (symbol && !(symbol.flags & SymbolFlags.Namespace)) { - error(errorLocation, Diagnostics._0_refers_to_a_value_but_is_being_used_as_a_type_here_Did_you_mean_typeof_0, unescapeLeadingUnderscores(name)); + error( + errorLocation, + Diagnostics._0_refers_to_a_value_but_is_being_used_as_a_type_here_Did_you_mean_typeof_0, + unescapeLeadingUnderscores(name), + ); return true; } } @@ -3737,40 +4296,82 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function isPrimitiveTypeName(name: __String) { - return name === "any" || name === "string" || name === "number" || name === "boolean" || name === "never" || name === "unknown"; + return name === "any" || name === "string" || name === "number" || name === "boolean" || name === "never" + || name === "unknown"; } function checkAndReportErrorForExportingPrimitiveType(errorLocation: Node, name: __String): boolean { if (isPrimitiveTypeName(name) && errorLocation.parent.kind === SyntaxKind.ExportSpecifier) { - error(errorLocation, Diagnostics.Cannot_export_0_Only_local_declarations_can_be_exported_from_a_module, name as string); + error( + errorLocation, + Diagnostics.Cannot_export_0_Only_local_declarations_can_be_exported_from_a_module, + name as string, + ); return true; } return false; } - function checkAndReportErrorForUsingTypeAsValue(errorLocation: Node, name: __String, meaning: SymbolFlags): boolean { + function checkAndReportErrorForUsingTypeAsValue( + errorLocation: Node, + name: __String, + meaning: SymbolFlags, + ): boolean { if (meaning & SymbolFlags.Value) { if (isPrimitiveTypeName(name)) { if (isExtendedByInterface(errorLocation)) { - error(errorLocation, Diagnostics.An_interface_cannot_extend_a_primitive_type_like_0_an_interface_can_only_extend_named_types_and_classes, unescapeLeadingUnderscores(name)); + error( + errorLocation, + Diagnostics + .An_interface_cannot_extend_a_primitive_type_like_0_an_interface_can_only_extend_named_types_and_classes, + unescapeLeadingUnderscores(name), + ); } else { - error(errorLocation, Diagnostics._0_only_refers_to_a_type_but_is_being_used_as_a_value_here, unescapeLeadingUnderscores(name)); + error( + errorLocation, + Diagnostics._0_only_refers_to_a_type_but_is_being_used_as_a_value_here, + unescapeLeadingUnderscores(name), + ); } return true; } - const symbol = resolveSymbol(resolveName(errorLocation, name, SymbolFlags.Type & ~SymbolFlags.Value, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ false)); + const symbol = resolveSymbol( + resolveName( + errorLocation, + name, + SymbolFlags.Type & ~SymbolFlags.Value, + /*nameNotFoundMessage*/ undefined, + /*nameArg*/ undefined, + /*isUse*/ false, + ), + ); const allFlags = symbol && getSymbolFlags(symbol); if (symbol && allFlags !== undefined && !(allFlags & SymbolFlags.Value)) { const rawName = unescapeLeadingUnderscores(name); if (isES2015OrLaterConstructorName(name)) { - error(errorLocation, Diagnostics._0_only_refers_to_a_type_but_is_being_used_as_a_value_here_Do_you_need_to_change_your_target_library_Try_changing_the_lib_compiler_option_to_es2015_or_later, rawName); + error( + errorLocation, + Diagnostics + ._0_only_refers_to_a_type_but_is_being_used_as_a_value_here_Do_you_need_to_change_your_target_library_Try_changing_the_lib_compiler_option_to_es2015_or_later, + rawName, + ); } else if (maybeMappedType(errorLocation, symbol)) { - error(errorLocation, Diagnostics._0_only_refers_to_a_type_but_is_being_used_as_a_value_here_Did_you_mean_to_use_1_in_0, rawName, rawName === "K" ? "P" : "K"); + error( + errorLocation, + Diagnostics + ._0_only_refers_to_a_type_but_is_being_used_as_a_value_here_Did_you_mean_to_use_1_in_0, + rawName, + rawName === "K" ? "P" : "K", + ); } else { - error(errorLocation, Diagnostics._0_only_refers_to_a_type_but_is_being_used_as_a_value_here, rawName); + error( + errorLocation, + Diagnostics._0_only_refers_to_a_type_but_is_being_used_as_a_value_here, + rawName, + ); } return true; } @@ -3790,10 +4391,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function maybeMappedType(node: Node, symbol: Symbol) { - const container = findAncestor(node.parent, n => isComputedPropertyName(n) || isPropertySignature(n) ? false : isTypeLiteralNode(n) || "quit") as TypeLiteralNode | undefined; + const container = findAncestor( + node.parent, + n => isComputedPropertyName(n) || isPropertySignature(n) ? false : isTypeLiteralNode(n) || "quit", + ) as TypeLiteralNode | undefined; if (container && container.members.length === 1) { const type = getDeclaredTypeOfSymbol(symbol); - return !!(type.flags & TypeFlags.Union) && allTypesAssignableToKind(type, TypeFlags.StringOrNumberLiteral, /*strict*/ true); + return !!(type.flags & TypeFlags.Union) + && allTypesAssignableToKind(type, TypeFlags.StringOrNumberLiteral, /*strict*/ true); } return false; } @@ -3811,9 +4416,22 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return false; } - function checkAndReportErrorForUsingNamespaceAsTypeOrValue(errorLocation: Node, name: __String, meaning: SymbolFlags): boolean { + function checkAndReportErrorForUsingNamespaceAsTypeOrValue( + errorLocation: Node, + name: __String, + meaning: SymbolFlags, + ): boolean { if (meaning & (SymbolFlags.Value & ~SymbolFlags.Type)) { - const symbol = resolveSymbol(resolveName(errorLocation, name, SymbolFlags.NamespaceModule, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ false)); + const symbol = resolveSymbol( + resolveName( + errorLocation, + name, + SymbolFlags.NamespaceModule, + /*nameNotFoundMessage*/ undefined, + /*nameArg*/ undefined, + /*isUse*/ false, + ), + ); if (symbol) { error( errorLocation, @@ -3824,7 +4442,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } else if (meaning & (SymbolFlags.Type & ~SymbolFlags.Value)) { - const symbol = resolveSymbol(resolveName(errorLocation, name, SymbolFlags.Module, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ false)); + const symbol = resolveSymbol( + resolveName( + errorLocation, + name, + SymbolFlags.Module, + /*nameNotFoundMessage*/ undefined, + /*nameArg*/ undefined, + /*isUse*/ false, + ), + ); if (symbol) { error(errorLocation, Diagnostics.Cannot_use_namespace_0_as_a_type, unescapeLeadingUnderscores(name)); return true; @@ -3834,8 +4461,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function checkResolvedBlockScopedVariable(result: Symbol, errorLocation: Node): void { - Debug.assert(!!(result.flags & SymbolFlags.BlockScopedVariable || result.flags & SymbolFlags.Class || result.flags & SymbolFlags.Enum)); - if (result.flags & (SymbolFlags.Function | SymbolFlags.FunctionScopedVariable | SymbolFlags.Assignment) && result.flags & SymbolFlags.Class) { + Debug.assert( + !!(result.flags & SymbolFlags.BlockScopedVariable || result.flags & SymbolFlags.Class + || result.flags & SymbolFlags.Enum), + ); + if ( + result.flags & (SymbolFlags.Function | SymbolFlags.FunctionScopedVariable | SymbolFlags.Assignment) + && result.flags & SymbolFlags.Class + ) { // constructor functions aren't block scoped return; } @@ -3844,23 +4477,42 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { d => isBlockOrCatchScoped(d) || isClassLike(d) || (d.kind === SyntaxKind.EnumDeclaration), ); - if (declaration === undefined) return Debug.fail("checkResolvedBlockScopedVariable could not find block-scoped declaration"); + if (declaration === undefined) { + return Debug.fail("checkResolvedBlockScopedVariable could not find block-scoped declaration"); + } - if (!(declaration.flags & NodeFlags.Ambient) && !isBlockScopedNameDeclaredBeforeUse(declaration, errorLocation)) { + if ( + !(declaration.flags & NodeFlags.Ambient) && !isBlockScopedNameDeclaredBeforeUse(declaration, errorLocation) + ) { let diagnosticMessage; const declarationName = declarationNameToString(getNameOfDeclaration(declaration)); if (result.flags & SymbolFlags.BlockScopedVariable) { - diagnosticMessage = error(errorLocation, Diagnostics.Block_scoped_variable_0_used_before_its_declaration, declarationName); + diagnosticMessage = error( + errorLocation, + Diagnostics.Block_scoped_variable_0_used_before_its_declaration, + declarationName, + ); } else if (result.flags & SymbolFlags.Class) { - diagnosticMessage = error(errorLocation, Diagnostics.Class_0_used_before_its_declaration, declarationName); + diagnosticMessage = error( + errorLocation, + Diagnostics.Class_0_used_before_its_declaration, + declarationName, + ); } else if (result.flags & SymbolFlags.RegularEnum) { - diagnosticMessage = error(errorLocation, Diagnostics.Enum_0_used_before_its_declaration, declarationName); + diagnosticMessage = error( + errorLocation, + Diagnostics.Enum_0_used_before_its_declaration, + declarationName, + ); } if (diagnosticMessage) { - addRelatedInfo(diagnosticMessage, createDiagnosticForNode(declaration, Diagnostics._0_is_declared_here, declarationName)); + addRelatedInfo( + diagnosticMessage, + createDiagnosticForNode(declaration, Diagnostics._0_is_declared_here, declarationName), + ); } } } @@ -3873,7 +4525,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function isSameScopeDescendentOf(initial: Node, parent: Node | undefined, stopAt: Node): boolean { return !!parent && !!findAncestor(initial, n => n === parent - || (n === stopAt || isFunctionLike(n) && (!getImmediatelyInvokedFunctionExpression(n) || isAsyncFunction(n)) ? "quit" : false)); + || (n === stopAt || isFunctionLike(n) && (!getImmediatelyInvokedFunctionExpression(n) || isAsyncFunction(n)) + ? "quit" : false)); } function getAnyImportSyntax(node: Node): AnyImportSyntax | undefined { @@ -3919,28 +4572,42 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { || node.kind === SyntaxKind.ImportSpecifier || node.kind === SyntaxKind.ExportSpecifier || node.kind === SyntaxKind.ExportAssignment && exportAssignmentIsAlias(node as ExportAssignment) - || isBinaryExpression(node) && getAssignmentDeclarationKind(node) === AssignmentDeclarationKind.ModuleExports && exportAssignmentIsAlias(node) + || isBinaryExpression(node) + && getAssignmentDeclarationKind(node) === AssignmentDeclarationKind.ModuleExports + && exportAssignmentIsAlias(node) || isAccessExpression(node) && isBinaryExpression(node.parent) && node.parent.left === node && node.parent.operatorToken.kind === SyntaxKind.EqualsToken && isAliasableOrJsExpression(node.parent.right) || node.kind === SyntaxKind.ShorthandPropertyAssignment - || node.kind === SyntaxKind.PropertyAssignment && isAliasableOrJsExpression((node as PropertyAssignment).initializer) - || node.kind === SyntaxKind.VariableDeclaration && isVariableDeclarationInitializedToBareOrAccessedRequire(node) - || node.kind === SyntaxKind.BindingElement && isVariableDeclarationInitializedToBareOrAccessedRequire(node.parent.parent); + || node.kind === SyntaxKind.PropertyAssignment + && isAliasableOrJsExpression((node as PropertyAssignment).initializer) + || node.kind === SyntaxKind.VariableDeclaration + && isVariableDeclarationInitializedToBareOrAccessedRequire(node) + || node.kind === SyntaxKind.BindingElement + && isVariableDeclarationInitializedToBareOrAccessedRequire(node.parent.parent); } function isAliasableOrJsExpression(e: Expression) { return isAliasableExpression(e) || isFunctionExpression(e) && isJSConstructor(e); } - function getTargetOfImportEqualsDeclaration(node: ImportEqualsDeclaration | VariableDeclaration, dontResolveAlias: boolean): Symbol | undefined { + function getTargetOfImportEqualsDeclaration( + node: ImportEqualsDeclaration | VariableDeclaration, + dontResolveAlias: boolean, + ): Symbol | undefined { const commonJSPropertyAccess = getCommonJSPropertyAccess(node); if (commonJSPropertyAccess) { - const name = (getLeftmostAccessExpression(commonJSPropertyAccess.expression) as CallExpression).arguments[0] as StringLiteral; + const name = (getLeftmostAccessExpression(commonJSPropertyAccess.expression) as CallExpression) + .arguments[0] as StringLiteral; return isIdentifier(commonJSPropertyAccess.name) - ? resolveSymbol(getPropertyOfType(resolveExternalModuleTypeByLiteral(name), commonJSPropertyAccess.name.escapedText)) + ? resolveSymbol( + getPropertyOfType( + resolveExternalModuleTypeByLiteral(name), + commonJSPropertyAccess.name.escapedText, + ), + ) : undefined; } if (isVariableDeclaration(node) || node.moduleReference.kind === SyntaxKind.ExternalModuleReference) { @@ -3957,10 +4624,21 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return resolved; } - function checkAndReportErrorForResolvingImportAliasToTypeOnlySymbol(node: ImportEqualsDeclaration, resolved: Symbol | undefined) { - if (markSymbolOfAliasDeclarationIfTypeOnly(node, /*immediateTarget*/ undefined, resolved, /*overwriteEmpty*/ false) && !node.isTypeOnly) { + function checkAndReportErrorForResolvingImportAliasToTypeOnlySymbol( + node: ImportEqualsDeclaration, + resolved: Symbol | undefined, + ) { + if ( + markSymbolOfAliasDeclarationIfTypeOnly( + node, + /*immediateTarget*/ undefined, + resolved, + /*overwriteEmpty*/ false, + ) && !node.isTypeOnly + ) { const typeOnlyDeclaration = getTypeOnlyAliasDeclaration(getSymbolOfDeclaration(node))!; - const isExport = typeOnlyDeclaration.kind === SyntaxKind.ExportSpecifier || typeOnlyDeclaration.kind === SyntaxKind.ExportDeclaration; + const isExport = typeOnlyDeclaration.kind === SyntaxKind.ExportSpecifier + || typeOnlyDeclaration.kind === SyntaxKind.ExportDeclaration; const message = isExport ? Diagnostics.An_import_alias_cannot_reference_a_declaration_that_was_exported_using_export_type : Diagnostics.An_import_alias_cannot_reference_a_declaration_that_was_imported_using_import_type; @@ -3969,12 +4647,21 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { : Diagnostics._0_was_imported_here; // TODO: how to get name for export *? - const name = typeOnlyDeclaration.kind === SyntaxKind.ExportDeclaration ? "*" : unescapeLeadingUnderscores(typeOnlyDeclaration.name.escapedText); - addRelatedInfo(error(node.moduleReference, message), createDiagnosticForNode(typeOnlyDeclaration, relatedMessage, name)); + const name = typeOnlyDeclaration.kind === SyntaxKind.ExportDeclaration ? "*" + : unescapeLeadingUnderscores(typeOnlyDeclaration.name.escapedText); + addRelatedInfo( + error(node.moduleReference, message), + createDiagnosticForNode(typeOnlyDeclaration, relatedMessage, name), + ); } } - function resolveExportByName(moduleSymbol: Symbol, name: __String, sourceNode: TypeOnlyCompatibleAliasDeclaration | undefined, dontResolveAlias: boolean) { + function resolveExportByName( + moduleSymbol: Symbol, + name: __String, + sourceNode: TypeOnlyCompatibleAliasDeclaration | undefined, + dontResolveAlias: boolean, + ) { const exportValue = moduleSymbol.exports!.get(InternalSymbolName.ExportEquals); const exportSymbol = exportValue ? getPropertyOfType(getTypeOfSymbol(exportValue), name, /*skipObjectFunctionPropertyAugment*/ true) @@ -3985,7 +4672,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function isSyntacticDefault(node: Node) { - return ((isExportAssignment(node) && !node.isExportEquals) || hasSyntacticModifier(node, ModifierFlags.Default) || isExportSpecifier(node)); + return ((isExportAssignment(node) && !node.isExportEquals) || hasSyntacticModifier(node, ModifierFlags.Default) + || isExportSpecifier(node)); } function getUsageModeForExpression(usage: Expression) { @@ -4001,7 +4689,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return usageMode === ModuleKind.ESNext && endsWith((usage as StringLiteralLike).text, Extension.Json); } - function canHaveSyntheticDefault(file: SourceFile | undefined, moduleSymbol: Symbol, dontResolveAlias: boolean, usage: Expression) { + function canHaveSyntheticDefault( + file: SourceFile | undefined, + moduleSymbol: Symbol, + dontResolveAlias: boolean, + usage: Expression, + ) { const usageMode = file && getUsageModeForExpression(usage); if (file && usageMode !== undefined) { const result = isESMFormatImportImportingCommonjsFormatFile(usageMode, file.impliedNodeFormat); @@ -4016,13 +4709,25 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // Declaration files (and ambient modules) if (!file || file.isDeclarationFile) { // Definitely cannot have a synthetic default if they have a syntactic default member specified - const defaultExportSymbol = resolveExportByName(moduleSymbol, InternalSymbolName.Default, /*sourceNode*/ undefined, /*dontResolveAlias*/ true); // Dont resolve alias because we want the immediately exported symbol's declaration + const defaultExportSymbol = resolveExportByName( + moduleSymbol, + InternalSymbolName.Default, + /*sourceNode*/ undefined, + /*dontResolveAlias*/ true, + ); // Dont resolve alias because we want the immediately exported symbol's declaration if (defaultExportSymbol && some(defaultExportSymbol.declarations, isSyntacticDefault)) { return false; } // It _might_ still be incorrect to assume there is no __esModule marker on the import at runtime, even if there is no `default` member // So we check a bit more, - if (resolveExportByName(moduleSymbol, escapeLeadingUnderscores("__esModule"), /*sourceNode*/ undefined, dontResolveAlias)) { + if ( + resolveExportByName( + moduleSymbol, + escapeLeadingUnderscores("__esModule"), + /*sourceNode*/ undefined, + dontResolveAlias, + ) + ) { // If there is an `__esModule` specified in the declaration (meaning someone explicitly added it or wrote it in their code), // it definitely is a module and does not have a synthetic default return false; @@ -4037,7 +4742,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return hasExportAssignmentSymbol(moduleSymbol); } // JS files have a synthetic default if they do not contain ES2015+ module syntax (export = is not valid in js) _and_ do not have an __esModule marker - return typeof file.externalModuleIndicator !== "object" && !resolveExportByName(moduleSymbol, escapeLeadingUnderscores("__esModule"), /*sourceNode*/ undefined, dontResolveAlias); + return typeof file.externalModuleIndicator !== "object" + && !resolveExportByName( + moduleSymbol, + escapeLeadingUnderscores("__esModule"), + /*sourceNode*/ undefined, + dontResolveAlias, + ); } function getTargetOfImportClause(node: ImportClause, dontResolveAlias: boolean): Symbol | undefined { @@ -4047,7 +4758,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } - function getTargetofModuleDefault(moduleSymbol: Symbol, node: ImportClause | ImportOrExportSpecifier, dontResolveAlias: boolean) { + function getTargetofModuleDefault( + moduleSymbol: Symbol, + node: ImportClause | ImportOrExportSpecifier, + dontResolveAlias: boolean, + ) { let exportDefaultSymbol: Symbol | undefined; if (isShorthandAmbientModuleSymbol(moduleSymbol)) { exportDefaultSymbol = moduleSymbol; @@ -4065,17 +4780,24 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const hasSyntheticDefault = canHaveSyntheticDefault(file, moduleSymbol, dontResolveAlias, specifier); if (!exportDefaultSymbol && !hasSyntheticDefault && !hasDefaultOnly) { if (hasExportAssignmentSymbol(moduleSymbol) && !allowSyntheticDefaultImports) { - const compilerOptionName = moduleKind >= ModuleKind.ES2015 ? "allowSyntheticDefaultImports" : "esModuleInterop"; + const compilerOptionName = moduleKind >= ModuleKind.ES2015 ? "allowSyntheticDefaultImports" + : "esModuleInterop"; const exportEqualsSymbol = moduleSymbol.exports!.get(InternalSymbolName.ExportEquals); const exportAssignment = exportEqualsSymbol!.valueDeclaration; - const err = error(node.name, Diagnostics.Module_0_can_only_be_default_imported_using_the_1_flag, symbolToString(moduleSymbol), compilerOptionName); + const err = error( + node.name, + Diagnostics.Module_0_can_only_be_default_imported_using_the_1_flag, + symbolToString(moduleSymbol), + compilerOptionName, + ); if (exportAssignment) { addRelatedInfo( err, createDiagnosticForNode( exportAssignment, - Diagnostics.This_module_is_declared_with_export_and_can_only_be_used_with_a_default_import_when_using_the_0_flag, + Diagnostics + .This_module_is_declared_with_export_and_can_only_be_used_with_a_default_import_when_using_the_0_flag, compilerOptionName, ), ); @@ -4085,20 +4807,33 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { reportNonDefaultExport(moduleSymbol, node); } else { - errorNoModuleMemberSymbol(moduleSymbol, moduleSymbol, node, isImportOrExportSpecifier(node) && node.propertyName || node.name); + errorNoModuleMemberSymbol( + moduleSymbol, + moduleSymbol, + node, + isImportOrExportSpecifier(node) && node.propertyName || node.name, + ); } } else if (hasSyntheticDefault || hasDefaultOnly) { // per emit behavior, a synthetic default overrides a "real" .default member if `__esModule` is not present - const resolved = resolveExternalModuleSymbol(moduleSymbol, dontResolveAlias) || resolveSymbol(moduleSymbol, dontResolveAlias); + const resolved = resolveExternalModuleSymbol(moduleSymbol, dontResolveAlias) + || resolveSymbol(moduleSymbol, dontResolveAlias); markSymbolOfAliasDeclarationIfTypeOnly(node, moduleSymbol, resolved, /*overwriteEmpty*/ false); return resolved; } - markSymbolOfAliasDeclarationIfTypeOnly(node, exportDefaultSymbol, /*finalTarget*/ undefined, /*overwriteEmpty*/ false); + markSymbolOfAliasDeclarationIfTypeOnly( + node, + exportDefaultSymbol, + /*finalTarget*/ undefined, + /*overwriteEmpty*/ false, + ); return exportDefaultSymbol; } - function getModuleSpecifierForImportOrExport(node: ImportEqualsDeclaration | ImportClause | NamespaceImport | ImportOrExportSpecifier): Expression | undefined { + function getModuleSpecifierForImportOrExport( + node: ImportEqualsDeclaration | ImportClause | NamespaceImport | ImportOrExportSpecifier, + ): Expression | undefined { switch (node.kind) { case SyntaxKind.ImportClause: return node.parent.moduleSpecifier; @@ -4125,17 +4860,29 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { ); } else { - const diagnostic = error(node.name, Diagnostics.Module_0_has_no_default_export, symbolToString(moduleSymbol)); + const diagnostic = error( + node.name, + Diagnostics.Module_0_has_no_default_export, + symbolToString(moduleSymbol), + ); const exportStar = moduleSymbol.exports?.get(InternalSymbolName.ExportStar); if (exportStar) { const defaultExport = exportStar.declarations?.find(decl => !!( - isExportDeclaration(decl) && decl.moduleSpecifier && - resolveExternalModuleName(decl, decl.moduleSpecifier)?.exports?.has(InternalSymbolName.Default) + isExportDeclaration(decl) && decl.moduleSpecifier + && resolveExternalModuleName(decl, decl.moduleSpecifier)?.exports?.has( + InternalSymbolName.Default, + ) ) ); if (defaultExport) { - addRelatedInfo(diagnostic, createDiagnosticForNode(defaultExport, Diagnostics.export_Asterisk_does_not_re_export_a_default)); + addRelatedInfo( + diagnostic, + createDiagnosticForNode( + defaultExport, + Diagnostics.export_Asterisk_does_not_re_export_a_default, + ), + ); } } } @@ -4144,7 +4891,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function getTargetOfNamespaceImport(node: NamespaceImport, dontResolveAlias: boolean): Symbol | undefined { const moduleSpecifier = node.parent.parent.moduleSpecifier; const immediate = resolveExternalModuleName(node, moduleSpecifier); - const resolved = resolveESModuleSymbol(immediate, moduleSpecifier, dontResolveAlias, /*suppressInteropError*/ false); + const resolved = resolveESModuleSymbol( + immediate, + moduleSpecifier, + dontResolveAlias, + /*suppressInteropError*/ false, + ); markSymbolOfAliasDeclarationIfTypeOnly(node, immediate, resolved, /*overwriteEmpty*/ false); return resolved; } @@ -4152,7 +4904,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function getTargetOfNamespaceExport(node: NamespaceExport, dontResolveAlias: boolean): Symbol | undefined { const moduleSpecifier = node.parent.moduleSpecifier; const immediate = moduleSpecifier && resolveExternalModuleName(node, moduleSpecifier); - const resolved = moduleSpecifier && resolveESModuleSymbol(immediate, moduleSpecifier, dontResolveAlias, /*suppressInteropError*/ false); + const resolved = moduleSpecifier + && resolveESModuleSymbol(immediate, moduleSpecifier, dontResolveAlias, /*suppressInteropError*/ false); markSymbolOfAliasDeclarationIfTypeOnly(node, immediate, resolved, /*overwriteEmpty*/ false); return resolved; } @@ -4184,7 +4937,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } const result = createSymbol(valueSymbol.flags | typeSymbol.flags, valueSymbol.escapedName); Debug.assert(valueSymbol.declarations || typeSymbol.declarations); - result.declarations = deduplicate(concatenate(valueSymbol.declarations!, typeSymbol.declarations), equateValues); + result.declarations = deduplicate( + concatenate(valueSymbol.declarations!, typeSymbol.declarations), + equateValues, + ); result.parent = valueSymbol.parent || typeSymbol.parent; if (valueSymbol.valueDeclaration) result.valueDeclaration = valueSymbol.valueDeclaration; if (typeSymbol.members) result.members = new Map(typeSymbol.members); @@ -4192,12 +4948,24 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return result; } - function getExportOfModule(symbol: Symbol, name: Identifier, specifier: Declaration, dontResolveAlias: boolean): Symbol | undefined { + function getExportOfModule( + symbol: Symbol, + name: Identifier, + specifier: Declaration, + dontResolveAlias: boolean, + ): Symbol | undefined { if (symbol.flags & SymbolFlags.Module) { const exportSymbol = getExportsOfSymbol(symbol).get(name.escapedText); const resolved = resolveSymbol(exportSymbol, dontResolveAlias); const exportStarDeclaration = getSymbolLinks(symbol).typeOnlyExportStarMap?.get(name.escapedText); - markSymbolOfAliasDeclarationIfTypeOnly(specifier, exportSymbol, resolved, /*overwriteEmpty*/ false, exportStarDeclaration, name.escapedText); + markSymbolOfAliasDeclarationIfTypeOnly( + specifier, + exportSymbol, + resolved, + /*overwriteEmpty*/ false, + exportStarDeclaration, + name.escapedText, + ); return resolved; } } @@ -4211,15 +4979,25 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } - function getExternalModuleMember(node: ImportDeclaration | ExportDeclaration | VariableDeclaration, specifier: ImportOrExportSpecifier | BindingElement | PropertyAccessExpression, dontResolveAlias = false): Symbol | undefined { - const moduleSpecifier = getExternalModuleRequireArgument(node) || (node as ImportDeclaration | ExportDeclaration).moduleSpecifier!; + function getExternalModuleMember( + node: ImportDeclaration | ExportDeclaration | VariableDeclaration, + specifier: ImportOrExportSpecifier | BindingElement | PropertyAccessExpression, + dontResolveAlias = false, + ): Symbol | undefined { + const moduleSpecifier = getExternalModuleRequireArgument(node) + || (node as ImportDeclaration | ExportDeclaration).moduleSpecifier!; const moduleSymbol = resolveExternalModuleName(node, moduleSpecifier)!; // TODO: GH#18217 const name = !isPropertyAccessExpression(specifier) && specifier.propertyName || specifier.name; if (!isIdentifier(name)) { return undefined; } const suppressInteropError = name.escapedText === InternalSymbolName.Default && allowSyntheticDefaultImports; - const targetSymbol = resolveESModuleSymbol(moduleSymbol, moduleSpecifier, /*dontResolveAlias*/ false, suppressInteropError); + const targetSymbol = resolveESModuleSymbol( + moduleSymbol, + moduleSpecifier, + /*dontResolveAlias*/ false, + suppressInteropError, + ); if (targetSymbol) { if (name.escapedText) { if (isShorthandAmbientModuleSymbol(moduleSymbol)) { @@ -4229,7 +5007,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { let symbolFromVariable: Symbol | undefined; // First check if module was specified with "export=". If so, get the member from the resolved type if (moduleSymbol && moduleSymbol.exports && moduleSymbol.exports.get(InternalSymbolName.ExportEquals)) { - symbolFromVariable = getPropertyOfType(getTypeOfSymbol(targetSymbol), name.escapedText, /*skipObjectFunctionPropertyAugment*/ true); + symbolFromVariable = getPropertyOfType( + getTypeOfSymbol(targetSymbol), + name.escapedText, + /*skipObjectFunctionPropertyAugment*/ true, + ); } else { symbolFromVariable = getPropertyOfVariable(targetSymbol, name.escapedText); @@ -4240,14 +5022,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { let symbolFromModule = getExportOfModule(targetSymbol, name, specifier, dontResolveAlias); if (symbolFromModule === undefined && name.escapedText === InternalSymbolName.Default) { const file = moduleSymbol.declarations?.find(isSourceFile); - if (isOnlyImportedAsDefault(moduleSpecifier) || canHaveSyntheticDefault(file, moduleSymbol, dontResolveAlias, moduleSpecifier)) { - symbolFromModule = resolveExternalModuleSymbol(moduleSymbol, dontResolveAlias) || resolveSymbol(moduleSymbol, dontResolveAlias); + if ( + isOnlyImportedAsDefault(moduleSpecifier) + || canHaveSyntheticDefault(file, moduleSymbol, dontResolveAlias, moduleSpecifier) + ) { + symbolFromModule = resolveExternalModuleSymbol(moduleSymbol, dontResolveAlias) + || resolveSymbol(moduleSymbol, dontResolveAlias); } } - const symbol = symbolFromModule && symbolFromVariable && symbolFromModule !== symbolFromVariable ? - combineValueAndTypeSymbols(symbolFromVariable, symbolFromModule) : - symbolFromModule || symbolFromVariable; + const symbol = symbolFromModule && symbolFromVariable && symbolFromModule !== symbolFromVariable + ? combineValueAndTypeSymbols(symbolFromVariable, symbolFromModule) + : symbolFromModule || symbolFromVariable; if (!symbol) { errorNoModuleMemberSymbol(moduleSymbol, targetSymbol, node, name); } @@ -4262,9 +5048,22 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const suggestion = getSuggestedSymbolForNonexistentModule(name, targetSymbol); if (suggestion !== undefined) { const suggestionName = symbolToString(suggestion); - const diagnostic = error(name, Diagnostics._0_has_no_exported_member_named_1_Did_you_mean_2, moduleName, declarationName, suggestionName); + const diagnostic = error( + name, + Diagnostics._0_has_no_exported_member_named_1_Did_you_mean_2, + moduleName, + declarationName, + suggestionName, + ); if (suggestion.valueDeclaration) { - addRelatedInfo(diagnostic, createDiagnosticForNode(suggestion.valueDeclaration, Diagnostics._0_is_declared_here, suggestionName)); + addRelatedInfo( + diagnostic, + createDiagnosticForNode( + suggestion.valueDeclaration, + Diagnostics._0_is_declared_here, + suggestionName, + ), + ); } } else { @@ -4282,21 +5081,49 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } - function reportNonExportedMember(node: Node, name: Identifier, declarationName: string, moduleSymbol: Symbol, moduleName: string): void { + function reportNonExportedMember( + node: Node, + name: Identifier, + declarationName: string, + moduleSymbol: Symbol, + moduleName: string, + ): void { const localSymbol = tryCast(moduleSymbol.valueDeclaration, canHaveLocals)?.locals?.get(name.escapedText); const exports = moduleSymbol.exports; if (localSymbol) { const exportedEqualsSymbol = exports?.get(InternalSymbolName.ExportEquals); if (exportedEqualsSymbol) { - getSymbolIfSameReference(exportedEqualsSymbol, localSymbol) ? reportInvalidImportEqualsExportMember(node, name, declarationName, moduleName) : - error(name, Diagnostics.Module_0_has_no_exported_member_1, moduleName, declarationName); + getSymbolIfSameReference(exportedEqualsSymbol, localSymbol) + ? reportInvalidImportEqualsExportMember(node, name, declarationName, moduleName) + : error(name, Diagnostics.Module_0_has_no_exported_member_1, moduleName, declarationName); } else { - const exportedSymbol = exports ? find(symbolsToArray(exports), symbol => !!getSymbolIfSameReference(symbol, localSymbol)) : undefined; - const diagnostic = exportedSymbol ? error(name, Diagnostics.Module_0_declares_1_locally_but_it_is_exported_as_2, moduleName, declarationName, symbolToString(exportedSymbol)) : - error(name, Diagnostics.Module_0_declares_1_locally_but_it_is_not_exported, moduleName, declarationName); + const exportedSymbol = exports ? find(symbolsToArray(exports), symbol => + !!getSymbolIfSameReference(symbol, localSymbol)) : undefined; + const diagnostic = exportedSymbol + ? error( + name, + Diagnostics.Module_0_declares_1_locally_but_it_is_exported_as_2, + moduleName, + declarationName, + symbolToString(exportedSymbol), + ) + : error( + name, + Diagnostics.Module_0_declares_1_locally_but_it_is_not_exported, + moduleName, + declarationName, + ); if (localSymbol.declarations) { - addRelatedInfo(diagnostic, ...map(localSymbol.declarations, (decl, index) => createDiagnosticForNode(decl, index === 0 ? Diagnostics._0_is_declared_here : Diagnostics.and_here, declarationName))); + addRelatedInfo( + diagnostic, + ...map(localSymbol.declarations, (decl, index) => + createDiagnosticForNode( + decl, + index === 0 ? Diagnostics._0_is_declared_here : Diagnostics.and_here, + declarationName, + )), + ); } } } @@ -4305,27 +5132,40 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } - function reportInvalidImportEqualsExportMember(node: Node, name: Identifier, declarationName: string, moduleName: string) { + function reportInvalidImportEqualsExportMember( + node: Node, + name: Identifier, + declarationName: string, + moduleName: string, + ) { if (moduleKind >= ModuleKind.ES2015) { - const message = getESModuleInterop(compilerOptions) ? Diagnostics._0_can_only_be_imported_by_using_a_default_import : - Diagnostics._0_can_only_be_imported_by_turning_on_the_esModuleInterop_flag_and_using_a_default_import; + const message = getESModuleInterop(compilerOptions) + ? Diagnostics._0_can_only_be_imported_by_using_a_default_import + : Diagnostics._0_can_only_be_imported_by_turning_on_the_esModuleInterop_flag_and_using_a_default_import; error(name, message, declarationName); } else { if (isInJSFile(node)) { - const message = getESModuleInterop(compilerOptions) ? Diagnostics._0_can_only_be_imported_by_using_a_require_call_or_by_using_a_default_import : - Diagnostics._0_can_only_be_imported_by_using_a_require_call_or_by_turning_on_the_esModuleInterop_flag_and_using_a_default_import; + const message = getESModuleInterop(compilerOptions) + ? Diagnostics._0_can_only_be_imported_by_using_a_require_call_or_by_using_a_default_import + : Diagnostics + ._0_can_only_be_imported_by_using_a_require_call_or_by_turning_on_the_esModuleInterop_flag_and_using_a_default_import; error(name, message, declarationName); } else { - const message = getESModuleInterop(compilerOptions) ? Diagnostics._0_can_only_be_imported_by_using_import_1_require_2_or_a_default_import : - Diagnostics._0_can_only_be_imported_by_using_import_1_require_2_or_by_turning_on_the_esModuleInterop_flag_and_using_a_default_import; + const message = getESModuleInterop(compilerOptions) + ? Diagnostics._0_can_only_be_imported_by_using_import_1_require_2_or_a_default_import + : Diagnostics + ._0_can_only_be_imported_by_using_import_1_require_2_or_by_turning_on_the_esModuleInterop_flag_and_using_a_default_import; error(name, message, declarationName, declarationName, moduleName); } } } - function getTargetOfImportSpecifier(node: ImportSpecifier | BindingElement, dontResolveAlias: boolean): Symbol | undefined { + function getTargetOfImportSpecifier( + node: ImportSpecifier | BindingElement, + dontResolveAlias: boolean, + ): Symbol | undefined { if (isImportSpecifier(node) && idText(node.propertyName || node.name) === InternalSymbolName.Default) { const specifier = getModuleSpecifierForImportOrExport(node); const moduleSymbol = specifier && resolveExternalModuleName(node, specifier); @@ -4333,7 +5173,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return getTargetofModuleDefault(moduleSymbol, node, dontResolveAlias); } } - const root = isBindingElement(node) ? getRootDeclaration(node) as VariableDeclaration : node.parent.parent.parent; + const root = isBindingElement(node) ? getRootDeclaration(node) as VariableDeclaration + : node.parent.parent.parent; const commonJSPropertyAccess = getCommonJSPropertyAccess(root); const resolved = getExternalModuleMember(root, commonJSPropertyAccess || node, dontResolveAlias); const name = node.propertyName || node.name; @@ -4350,10 +5191,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } - function getTargetOfNamespaceExportDeclaration(node: NamespaceExportDeclaration, dontResolveAlias: boolean): Symbol | undefined { + function getTargetOfNamespaceExportDeclaration( + node: NamespaceExportDeclaration, + dontResolveAlias: boolean, + ): Symbol | undefined { if (canHaveSymbol(node.parent)) { const resolved = resolveExternalModuleSymbol(node.parent.symbol, dontResolveAlias); - markSymbolOfAliasDeclarationIfTypeOnly(node, /*immediateTarget*/ undefined, resolved, /*overwriteEmpty*/ false); + markSymbolOfAliasDeclarationIfTypeOnly( + node, + /*immediateTarget*/ undefined, + resolved, + /*overwriteEmpty*/ false, + ); return resolved; } } @@ -4366,14 +5215,17 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return getTargetofModuleDefault(moduleSymbol, node, !!dontResolveAlias); } } - const resolved = node.parent.parent.moduleSpecifier ? - getExternalModuleMember(node.parent.parent, node, dontResolveAlias) : - resolveEntityName(node.propertyName || node.name, meaning, /*ignoreErrors*/ false, dontResolveAlias); + const resolved = node.parent.parent.moduleSpecifier + ? getExternalModuleMember(node.parent.parent, node, dontResolveAlias) + : resolveEntityName(node.propertyName || node.name, meaning, /*ignoreErrors*/ false, dontResolveAlias); markSymbolOfAliasDeclarationIfTypeOnly(node, /*immediateTarget*/ undefined, resolved, /*overwriteEmpty*/ false); return resolved; } - function getTargetOfExportAssignment(node: ExportAssignment | BinaryExpression, dontResolveAlias: boolean): Symbol | undefined { + function getTargetOfExportAssignment( + node: ExportAssignment | BinaryExpression, + dontResolveAlias: boolean, + ): Symbol | undefined { const expression = isExportAssignment(node) ? node.expression : node.right; const resolved = getTargetOfAliasLikeExpression(expression, dontResolveAlias); markSymbolOfAliasDeclarationIfTypeOnly(node, /*immediateTarget*/ undefined, resolved, /*overwriteEmpty*/ false); @@ -4387,7 +5239,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (!isEntityName(expression) && !isEntityNameExpression(expression)) { return undefined; } - const aliasLike = resolveEntityName(expression, SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace, /*ignoreErrors*/ true, dontResolveAlias); + const aliasLike = resolveEntityName( + expression, + SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace, + /*ignoreErrors*/ true, + dontResolveAlias, + ); if (aliasLike) { return aliasLike; } @@ -4396,7 +5253,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function getTargetOfAccessExpression(node: AccessExpression, dontRecursivelyResolve: boolean): Symbol | undefined { - if (!(isBinaryExpression(node.parent) && node.parent.left === node && node.parent.operatorToken.kind === SyntaxKind.EqualsToken)) { + if ( + !(isBinaryExpression(node.parent) && node.parent.left === node + && node.parent.operatorToken.kind === SyntaxKind.EqualsToken) + ) { return undefined; } @@ -4407,7 +5267,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { switch (node.kind) { case SyntaxKind.ImportEqualsDeclaration: case SyntaxKind.VariableDeclaration: - return getTargetOfImportEqualsDeclaration(node as ImportEqualsDeclaration | VariableDeclaration, dontRecursivelyResolve); + return getTargetOfImportEqualsDeclaration( + node as ImportEqualsDeclaration | VariableDeclaration, + dontRecursivelyResolve, + ); case SyntaxKind.ImportClause: return getTargetOfImportClause(node as ImportClause, dontRecursivelyResolve); case SyntaxKind.NamespaceImport: @@ -4418,14 +5281,26 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { case SyntaxKind.BindingElement: return getTargetOfImportSpecifier(node as ImportSpecifier | BindingElement, dontRecursivelyResolve); case SyntaxKind.ExportSpecifier: - return getTargetOfExportSpecifier(node as ExportSpecifier, SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace, dontRecursivelyResolve); + return getTargetOfExportSpecifier( + node as ExportSpecifier, + SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace, + dontRecursivelyResolve, + ); case SyntaxKind.ExportAssignment: case SyntaxKind.BinaryExpression: return getTargetOfExportAssignment(node as ExportAssignment | BinaryExpression, dontRecursivelyResolve); case SyntaxKind.NamespaceExportDeclaration: - return getTargetOfNamespaceExportDeclaration(node as NamespaceExportDeclaration, dontRecursivelyResolve); + return getTargetOfNamespaceExportDeclaration( + node as NamespaceExportDeclaration, + dontRecursivelyResolve, + ); case SyntaxKind.ShorthandPropertyAssignment: - return resolveEntityName((node as ShorthandPropertyAssignment).name, SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace, /*ignoreErrors*/ true, dontRecursivelyResolve); + return resolveEntityName( + (node as ShorthandPropertyAssignment).name, + SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace, + /*ignoreErrors*/ true, + dontRecursivelyResolve, + ); case SyntaxKind.PropertyAssignment: return getTargetOfAliasLikeExpression((node as PropertyAssignment).initializer, dontRecursivelyResolve); case SyntaxKind.ElementAccessExpression: @@ -4440,9 +5315,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { * Indicates that a symbol is an alias that does not merge with a local declaration. * OR Is a JSContainer which may merge an alias with a local declaration */ - function isNonLocalAlias(symbol: Symbol | undefined, excludes = SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace): symbol is Symbol { + function isNonLocalAlias( + symbol: Symbol | undefined, + excludes = SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace, + ): symbol is Symbol { if (!symbol) return false; - return (symbol.flags & (SymbolFlags.Alias | excludes)) === SymbolFlags.Alias || !!(symbol.flags & SymbolFlags.Alias && symbol.flags & SymbolFlags.Assignment); + return (symbol.flags & (SymbolFlags.Alias | excludes)) === SymbolFlags.Alias + || !!(symbol.flags & SymbolFlags.Alias && symbol.flags & SymbolFlags.Assignment); } function resolveSymbol(symbol: Symbol, dontResolveAlias?: boolean): Symbol; @@ -4501,22 +5380,31 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { * @returns SymbolFlags.All if `symbol` is an alias that ultimately resolves to `unknown`; * combined flags of all alias targets otherwise. */ - function getSymbolFlags(symbol: Symbol, excludeTypeOnlyMeanings?: boolean, excludeLocalMeanings?: boolean): SymbolFlags { + function getSymbolFlags( + symbol: Symbol, + excludeTypeOnlyMeanings?: boolean, + excludeLocalMeanings?: boolean, + ): SymbolFlags { const typeOnlyDeclaration = excludeTypeOnlyMeanings && getTypeOnlyAliasDeclaration(symbol); const typeOnlyDeclarationIsExportStar = typeOnlyDeclaration && isExportDeclaration(typeOnlyDeclaration); const typeOnlyResolution = typeOnlyDeclaration && ( typeOnlyDeclarationIsExportStar - ? resolveExternalModuleName(typeOnlyDeclaration.moduleSpecifier, typeOnlyDeclaration.moduleSpecifier, /*ignoreErrors*/ true) + ? resolveExternalModuleName( + typeOnlyDeclaration.moduleSpecifier, + typeOnlyDeclaration.moduleSpecifier, + /*ignoreErrors*/ true, + ) : resolveAlias(typeOnlyDeclaration.symbol) ); - const typeOnlyExportStarTargets = typeOnlyDeclarationIsExportStar && typeOnlyResolution ? getExportsOfModule(typeOnlyResolution) : undefined; + const typeOnlyExportStarTargets = typeOnlyDeclarationIsExportStar && typeOnlyResolution + ? getExportsOfModule(typeOnlyResolution) : undefined; let flags = excludeLocalMeanings ? SymbolFlags.None : symbol.flags; let seenSymbols; while (symbol.flags & SymbolFlags.Alias) { const target = getExportSymbolOfValueSymbolIfExported(resolveAlias(symbol)); if ( - !typeOnlyDeclarationIsExportStar && target === typeOnlyResolution || - typeOnlyExportStarTargets?.get(target.escapedName) === target + !typeOnlyDeclarationIsExportStar && target === typeOnlyResolution + || typeOnlyExportStarTargets?.get(target.escapedName) === target ) { break; } @@ -4568,7 +5456,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { immediateTarget: Symbol | undefined, finalTarget: Symbol | undefined, overwriteEmpty: boolean, - exportStarDeclaration?: ExportDeclaration & { readonly isTypeOnly: true; readonly moduleSpecifier: Expression; }, + exportStarDeclaration?: ExportDeclaration & { + readonly isTypeOnly: true; + readonly moduleSpecifier: Expression; + }, exportStarName?: __String, ): boolean { if (!aliasDeclaration || isPropertyAccessExpression(aliasDeclaration)) return false; @@ -4595,11 +5486,21 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { || markSymbolOfAliasDeclarationIfTypeOnlyWorker(links, finalTarget, overwriteEmpty); } - function markSymbolOfAliasDeclarationIfTypeOnlyWorker(aliasDeclarationLinks: SymbolLinks, target: Symbol | undefined, overwriteEmpty: boolean): boolean { - if (target && (aliasDeclarationLinks.typeOnlyDeclaration === undefined || overwriteEmpty && aliasDeclarationLinks.typeOnlyDeclaration === false)) { + function markSymbolOfAliasDeclarationIfTypeOnlyWorker( + aliasDeclarationLinks: SymbolLinks, + target: Symbol | undefined, + overwriteEmpty: boolean, + ): boolean { + if ( + target + && (aliasDeclarationLinks.typeOnlyDeclaration === undefined + || overwriteEmpty && aliasDeclarationLinks.typeOnlyDeclaration === false) + ) { const exportSymbol = target.exports?.get(InternalSymbolName.ExportEquals) ?? target; - const typeOnly = exportSymbol.declarations && find(exportSymbol.declarations, isTypeOnlyImportOrExportDeclaration); - aliasDeclarationLinks.typeOnlyDeclaration = typeOnly ?? getSymbolLinks(exportSymbol).typeOnlyDeclaration ?? false; + const typeOnly = exportSymbol.declarations + && find(exportSymbol.declarations, isTypeOnlyImportOrExportDeclaration); + aliasDeclarationLinks.typeOnlyDeclaration = typeOnly ?? getSymbolLinks(exportSymbol).typeOnlyDeclaration + ?? false; } return !!aliasDeclarationLinks.typeOnlyDeclaration; } @@ -4615,7 +5516,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } if (links.typeOnlyDeclaration) { const resolved = links.typeOnlyDeclaration.kind === SyntaxKind.ExportDeclaration - ? resolveSymbol(getExportsOfModule(links.typeOnlyDeclaration.symbol.parent!).get(links.typeOnlyExportStarName || symbol.escapedName))! + ? resolveSymbol( + getExportsOfModule(links.typeOnlyDeclaration.symbol.parent!).get( + links.typeOnlyExportStarName || symbol.escapedName, + ), + )! : resolveAlias(links.typeOnlyDeclaration.symbol); return getSymbolFlags(resolved) & include ? links.typeOnlyDeclaration : undefined; } @@ -4629,8 +5534,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const symbol = getSymbolOfDeclaration(node); const target = resolveAlias(symbol); if (target) { - const markAlias = target === unknownSymbol || - ((getSymbolFlags(symbol, /*excludeTypeOnlyMeanings*/ true) & SymbolFlags.Value) && !isConstEnumOrConstEnumOnlyModule(target)); + const markAlias = target === unknownSymbol + || ((getSymbolFlags(symbol, /*excludeTypeOnlyMeanings*/ true) & SymbolFlags.Value) + && !isConstEnumOrConstEnumOnlyModule(target)); if (markAlias) { markAliasSymbolAsReferenced(symbol); @@ -4670,7 +5576,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } // This function is only for imports with entity names - function getSymbolOfPartOfRightHandSideOfImportEquals(entityName: EntityName, dontResolveAlias?: boolean): Symbol | undefined { + function getSymbolOfPartOfRightHandSideOfImportEquals( + entityName: EntityName, + dontResolveAlias?: boolean, + ): Symbol | undefined { // There are three things we might try to look for. In the following examples, // the search term is enclosed in |...|: // @@ -4688,12 +5597,23 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // Case 2 in above example // entityName.kind could be a QualifiedName or a Missing identifier Debug.assert(entityName.parent.kind === SyntaxKind.ImportEqualsDeclaration); - return resolveEntityName(entityName, SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace, /*ignoreErrors*/ false, dontResolveAlias); + return resolveEntityName( + entityName, + SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace, + /*ignoreErrors*/ false, + dontResolveAlias, + ); } } function getFullyQualifiedName(symbol: Symbol, containingLocation?: Node): string { - return symbol.parent ? getFullyQualifiedName(symbol.parent, containingLocation) + "." + symbolToString(symbol) : symbolToString(symbol, containingLocation, /*meaning*/ undefined, SymbolFormatFlags.DoNotIncludeSymbolChain | SymbolFormatFlags.AllowAnyNodeKind); + return symbol.parent ? getFullyQualifiedName(symbol.parent, containingLocation) + "." + symbolToString(symbol) + : symbolToString( + symbol, + containingLocation, + /*meaning*/ undefined, + SymbolFormatFlags.DoNotIncludeSymbolChain | SymbolFormatFlags.AllowAnyNodeKind, + ); } function getContainingQualifiedNameNode(node: QualifiedName) { @@ -4705,7 +5625,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function tryGetQualifiedNameAsValue(node: QualifiedName) { let left: Identifier | QualifiedName = getFirstIdentifier(node); - let symbol = resolveName(left, left.escapedText, SymbolFlags.Value, /*nameNotFoundMessage*/ undefined, left, /*isUse*/ true); + let symbol = resolveName( + left, + left.escapedText, + SymbolFlags.Value, + /*nameNotFoundMessage*/ undefined, + left, + /*isUse*/ true, + ); if (!symbol) { return undefined; } @@ -4723,7 +5650,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { /** * Resolves a qualified name and any involved aliases. */ - function resolveEntityName(name: EntityNameOrEntityNameExpression, meaning: SymbolFlags, ignoreErrors?: boolean, dontResolveAlias?: boolean, location?: Node): Symbol | undefined { + function resolveEntityName( + name: EntityNameOrEntityNameExpression, + meaning: SymbolFlags, + ignoreErrors?: boolean, + dontResolveAlias?: boolean, + location?: Node, + ): Symbol | undefined { if (nodeIsMissing(name)) { return undefined; } @@ -4731,9 +5664,21 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const namespaceMeaning = SymbolFlags.Namespace | (isInJSFile(name) ? meaning & SymbolFlags.Value : 0); let symbol: Symbol | undefined; if (name.kind === SyntaxKind.Identifier) { - const message = meaning === namespaceMeaning || nodeIsSynthesized(name) ? Diagnostics.Cannot_find_namespace_0 : getCannotFindNameDiagnosticForName(getFirstIdentifier(name)); - const symbolFromJSPrototype = isInJSFile(name) && !nodeIsSynthesized(name) ? resolveEntityNameFromAssignmentDeclaration(name, meaning) : undefined; - symbol = getMergedSymbol(resolveName(location || name, name.escapedText, meaning, ignoreErrors || symbolFromJSPrototype ? undefined : message, name, /*isUse*/ true, /*excludeGlobals*/ false)); + const message = meaning === namespaceMeaning || nodeIsSynthesized(name) + ? Diagnostics.Cannot_find_namespace_0 : getCannotFindNameDiagnosticForName(getFirstIdentifier(name)); + const symbolFromJSPrototype = isInJSFile(name) && !nodeIsSynthesized(name) + ? resolveEntityNameFromAssignmentDeclaration(name, meaning) : undefined; + symbol = getMergedSymbol( + resolveName( + location || name, + name.escapedText, + meaning, + ignoreErrors || symbolFromJSPrototype ? undefined : message, + name, + /*isUse*/ true, + /*excludeGlobals*/ false, + ), + ); if (!symbol) { return getMergedSymbol(symbolFromJSPrototype); } @@ -4741,7 +5686,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { else if (name.kind === SyntaxKind.QualifiedName || name.kind === SyntaxKind.PropertyAccessExpression) { const left = name.kind === SyntaxKind.QualifiedName ? name.left : name.expression; const right = name.kind === SyntaxKind.QualifiedName ? name.right : name.name; - let namespace = resolveEntityName(left, namespaceMeaning, ignoreErrors, /*dontResolveAlias*/ false, location); + let namespace = resolveEntityName( + left, + namespaceMeaning, + ignoreErrors, + /*dontResolveAlias*/ false, + location, + ); if (!namespace || nodeIsMissing(right)) { return undefined; } @@ -4749,14 +5700,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return namespace; } if ( - namespace.valueDeclaration && - isInJSFile(namespace.valueDeclaration) && - getEmitModuleResolutionKind(compilerOptions) !== ModuleResolutionKind.Bundler && - isVariableDeclaration(namespace.valueDeclaration) && - namespace.valueDeclaration.initializer && - isCommonJsRequire(namespace.valueDeclaration.initializer) + namespace.valueDeclaration + && isInJSFile(namespace.valueDeclaration) + && getEmitModuleResolutionKind(compilerOptions) !== ModuleResolutionKind.Bundler + && isVariableDeclaration(namespace.valueDeclaration) + && namespace.valueDeclaration.initializer + && isCommonJsRequire(namespace.valueDeclaration.initializer) ) { - const moduleName = (namespace.valueDeclaration.initializer as CallExpression).arguments[0] as StringLiteral; + const moduleName = (namespace.valueDeclaration.initializer as CallExpression) + .arguments[0] as StringLiteral; const moduleSym = resolveExternalModuleName(moduleName, moduleName); if (moduleSym) { const resolvedModuleSymbol = resolveExternalModuleSymbol(moduleSym); @@ -4768,7 +5720,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { symbol = getMergedSymbol(getSymbol(getExportsOfSymbol(namespace), right.escapedText, meaning)); if (!symbol && (namespace.flags & SymbolFlags.Alias)) { // `namespace` can be resolved further if there was a symbol merge with a re-export - symbol = getMergedSymbol(getSymbol(getExportsOfSymbol(resolveAlias(namespace)), right.escapedText, meaning)); + symbol = getMergedSymbol( + getSymbol(getExportsOfSymbol(resolveAlias(namespace)), right.escapedText, meaning), + ); } if (!symbol) { if (!ignoreErrors) { @@ -4776,7 +5730,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const declarationName = declarationNameToString(right); const suggestionForNonexistentModule = getSuggestedSymbolForNonexistentModule(right, namespace); if (suggestionForNonexistentModule) { - error(right, Diagnostics._0_has_no_exported_member_named_1_Did_you_mean_2, namespaceName, declarationName, symbolToString(suggestionForNonexistentModule)); + error( + right, + Diagnostics._0_has_no_exported_member_named_1_Did_you_mean_2, + namespaceName, + declarationName, + symbolToString(suggestionForNonexistentModule), + ); return undefined; } @@ -4796,11 +5756,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } if (meaning & SymbolFlags.Namespace && isQualifiedName(name.parent)) { - const exportedTypeSymbol = getMergedSymbol(getSymbol(getExportsOfSymbol(namespace), right.escapedText, SymbolFlags.Type)); + const exportedTypeSymbol = getMergedSymbol( + getSymbol(getExportsOfSymbol(namespace), right.escapedText, SymbolFlags.Type), + ); if (exportedTypeSymbol) { error( name.parent.right, - Diagnostics.Cannot_access_0_1_because_0_is_a_type_but_not_a_namespace_Did_you_mean_to_retrieve_the_type_of_the_property_1_in_0_with_0_1, + Diagnostics + .Cannot_access_0_1_because_0_is_a_type_but_not_a_namespace_Did_you_mean_to_retrieve_the_type_of_the_property_1_in_0_with_0_1, symbolToString(exportedTypeSymbol), unescapeLeadingUnderscores(name.parent.right.escapedText), ); @@ -4816,9 +5779,20 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { else { Debug.assertNever(name, "Unknown entity name kind."); } - Debug.assert((getCheckFlags(symbol) & CheckFlags.Instantiated) === 0, "Should never get an instantiated symbol here."); - if (!nodeIsSynthesized(name) && isEntityName(name) && (symbol.flags & SymbolFlags.Alias || name.parent.kind === SyntaxKind.ExportAssignment)) { - markSymbolOfAliasDeclarationIfTypeOnly(getAliasDeclarationFromName(name), symbol, /*finalTarget*/ undefined, /*overwriteEmpty*/ true); + Debug.assert( + (getCheckFlags(symbol) & CheckFlags.Instantiated) === 0, + "Should never get an instantiated symbol here.", + ); + if ( + !nodeIsSynthesized(name) && isEntityName(name) + && (symbol.flags & SymbolFlags.Alias || name.parent.kind === SyntaxKind.ExportAssignment) + ) { + markSymbolOfAliasDeclarationIfTypeOnly( + getAliasDeclarationFromName(name), + symbol, + /*finalTarget*/ undefined, + /*overwriteEmpty*/ true, + ); } return (symbol.flags & meaning) || dontResolveAlias ? symbol : resolveAlias(symbol); } @@ -4833,13 +5807,23 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (isJSDocTypeReference(name.parent)) { const secondaryLocation = getAssignmentDeclarationLocation(name.parent); if (secondaryLocation) { - return resolveName(secondaryLocation, name.escapedText, meaning, /*nameNotFoundMessage*/ undefined, name, /*isUse*/ true); + return resolveName( + secondaryLocation, + name.escapedText, + meaning, + /*nameNotFoundMessage*/ undefined, + name, + /*isUse*/ true, + ); } } } function getAssignmentDeclarationLocation(node: TypeReferenceNode): Node | undefined { - const typeAlias = findAncestor(node, node => !(isJSDocNode(node) || node.flags & NodeFlags.JSDoc) ? "quit" : isJSDocTypeAlias(node)); + const typeAlias = findAncestor( + node, + node => !(isJSDocNode(node) || node.flags & NodeFlags.JSDoc) ? "quit" : isJSDocTypeAlias(node), + ); if (typeAlias) { return; } @@ -4851,7 +5835,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return getDeclarationOfJSPrototypeContainer(symbol); } } - if (host && isFunctionExpression(host) && isPrototypePropertyAssignment(host.parent) && isExpressionStatement(host.parent.parent)) { + if ( + host && isFunctionExpression(host) && isPrototypePropertyAssignment(host.parent) + && isExpressionStatement(host.parent.parent) + ) { // X.prototype.m = /** @param {K} p */ function () { } <-- look for K on X's declaration const symbol = getSymbolOfDeclaration(host.parent.left); if (symbol) { @@ -4859,9 +5846,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } if ( - host && (isObjectLiteralMethod(host) || isPropertyAssignment(host)) && - isBinaryExpression(host.parent.parent) && - getAssignmentDeclarationKind(host.parent.parent) === AssignmentDeclarationKind.Prototype + host && (isObjectLiteralMethod(host) || isPropertyAssignment(host)) + && isBinaryExpression(host.parent.parent) + && getAssignmentDeclarationKind(host.parent.parent) === AssignmentDeclarationKind.Prototype ) { // X.prototype = { /** @param {K} p */m() { } } <-- look for K on X's declaration const symbol = getSymbolOfDeclaration(host.parent.parent.left as BindableStaticNameExpression); @@ -4881,9 +5868,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (!decl) { return undefined; } - const initializer = isAssignmentDeclaration(decl) ? getAssignedExpandoInitializer(decl) : - hasOnlyExpressionInitializer(decl) ? getDeclaredExpandoInitializer(decl) : - undefined; + const initializer = isAssignmentDeclaration(decl) ? getAssignedExpandoInitializer(decl) + : hasOnlyExpressionInitializer(decl) ? getDeclaredExpandoInitializer(decl) + : undefined; return initializer || decl; } @@ -4895,10 +5882,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { */ function getExpandoSymbol(symbol: Symbol): Symbol | undefined { const decl = symbol.valueDeclaration; - if (!decl || !isInJSFile(decl) || symbol.flags & SymbolFlags.TypeAlias || getExpandoInitializer(decl, /*isPrototypeAssignment*/ false)) { + if ( + !decl || !isInJSFile(decl) || symbol.flags & SymbolFlags.TypeAlias + || getExpandoInitializer(decl, /*isPrototypeAssignment*/ false) + ) { return undefined; } - const init = isVariableDeclaration(decl) ? getDeclaredExpandoInitializer(decl) : getAssignedExpandoInitializer(decl); + const init = isVariableDeclaration(decl) ? getDeclaredExpandoInitializer(decl) + : getAssignedExpandoInitializer(decl); if (init) { const initSymbol = getSymbolOfNode(init); if (initSymbol) { @@ -4907,21 +5898,47 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } - function resolveExternalModuleName(location: Node, moduleReferenceExpression: Expression, ignoreErrors?: boolean): Symbol | undefined { + function resolveExternalModuleName( + location: Node, + moduleReferenceExpression: Expression, + ignoreErrors?: boolean, + ): Symbol | undefined { const isClassic = getEmitModuleResolutionKind(compilerOptions) === ModuleResolutionKind.Classic; - const errorMessage = isClassic ? - Diagnostics.Cannot_find_module_0_Did_you_mean_to_set_the_moduleResolution_option_to_nodenext_or_to_add_aliases_to_the_paths_option + const errorMessage = isClassic + ? Diagnostics + .Cannot_find_module_0_Did_you_mean_to_set_the_moduleResolution_option_to_nodenext_or_to_add_aliases_to_the_paths_option : Diagnostics.Cannot_find_module_0_or_its_corresponding_type_declarations; - return resolveExternalModuleNameWorker(location, moduleReferenceExpression, ignoreErrors ? undefined : errorMessage); + return resolveExternalModuleNameWorker( + location, + moduleReferenceExpression, + ignoreErrors ? undefined : errorMessage, + ); } - function resolveExternalModuleNameWorker(location: Node, moduleReferenceExpression: Expression, moduleNotFoundError: DiagnosticMessage | undefined, isForAugmentation = false): Symbol | undefined { + function resolveExternalModuleNameWorker( + location: Node, + moduleReferenceExpression: Expression, + moduleNotFoundError: DiagnosticMessage | undefined, + isForAugmentation = false, + ): Symbol | undefined { return isStringLiteralLike(moduleReferenceExpression) - ? resolveExternalModule(location, moduleReferenceExpression.text, moduleNotFoundError, moduleReferenceExpression, isForAugmentation) + ? resolveExternalModule( + location, + moduleReferenceExpression.text, + moduleNotFoundError, + moduleReferenceExpression, + isForAugmentation, + ) : undefined; } - function resolveExternalModule(location: Node, moduleReference: string, moduleNotFoundError: DiagnosticMessage | undefined, errorNode: Node, isForAugmentation = false): Symbol | undefined { + function resolveExternalModule( + location: Node, + moduleReference: string, + moduleNotFoundError: DiagnosticMessage | undefined, + errorNode: Node, + isForAugmentation = false, + ): Symbol | undefined { if (startsWith(moduleReference, "@types/")) { const diag = Diagnostics.Cannot_import_type_declaration_files_Consider_importing_0_instead_of_1; const withoutAtTypePrefix = removePrefix(moduleReference, "@types/"); @@ -4935,18 +5952,23 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const currentSourceFile = getSourceFileOfNode(location); const contextSpecifier = isStringLiteralLike(location) ? location - : findAncestor(location, isImportCall)?.arguments[0] || - findAncestor(location, isImportDeclaration)?.moduleSpecifier || - findAncestor(location, isExternalModuleImportEqualsDeclaration)?.moduleReference.expression || - findAncestor(location, isExportDeclaration)?.moduleSpecifier || - (isModuleDeclaration(location) ? location : location.parent && isModuleDeclaration(location.parent) && location.parent.name === location ? location.parent : undefined)?.name || - (isLiteralImportTypeNode(location) ? location : undefined)?.argument.literal; - const mode = contextSpecifier && isStringLiteralLike(contextSpecifier) ? getModeForUsageLocation(currentSourceFile, contextSpecifier) : currentSourceFile.impliedNodeFormat; + : findAncestor(location, isImportCall)?.arguments[0] + || findAncestor(location, isImportDeclaration)?.moduleSpecifier + || findAncestor(location, isExternalModuleImportEqualsDeclaration)?.moduleReference.expression + || findAncestor(location, isExportDeclaration)?.moduleSpecifier + || (isModuleDeclaration(location) ? location + : location.parent && isModuleDeclaration(location.parent) && location.parent.name === location + ? location.parent : undefined)?.name + || (isLiteralImportTypeNode(location) ? location : undefined)?.argument.literal; + const mode = contextSpecifier && isStringLiteralLike(contextSpecifier) + ? getModeForUsageLocation(currentSourceFile, contextSpecifier) : currentSourceFile.impliedNodeFormat; const moduleResolutionKind = getEmitModuleResolutionKind(compilerOptions); const resolvedModule = getResolvedModule(currentSourceFile, moduleReference, mode); - const resolutionDiagnostic = resolvedModule && getResolutionDiagnostic(compilerOptions, resolvedModule, currentSourceFile); + const resolutionDiagnostic = resolvedModule + && getResolutionDiagnostic(compilerOptions, resolvedModule, currentSourceFile); const sourceFile = resolvedModule - && (!resolutionDiagnostic || resolutionDiagnostic === Diagnostics.Module_0_was_resolved_to_1_but_jsx_is_not_set) + && (!resolutionDiagnostic + || resolutionDiagnostic === Diagnostics.Module_0_was_resolved_to_1_but_jsx_is_not_set) && host.getSourceFile(resolvedModule.resolvedFileName); if (sourceFile) { // If there's a resolutionDiagnostic we need to report it even if a sourceFile is found. @@ -4955,52 +5977,92 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } if (resolvedModule.resolvedUsingTsExtension && isDeclarationFileName(moduleReference)) { - const importOrExport = findAncestor(location, isImportDeclaration)?.importClause || - findAncestor(location, or(isImportEqualsDeclaration, isExportDeclaration)); + const importOrExport = findAncestor(location, isImportDeclaration)?.importClause + || findAncestor(location, or(isImportEqualsDeclaration, isExportDeclaration)); if (importOrExport && !importOrExport.isTypeOnly || findAncestor(location, isImportCall)) { error( errorNode, - Diagnostics.A_declaration_file_cannot_be_imported_without_import_type_Did_you_mean_to_import_an_implementation_file_0_instead, + Diagnostics + .A_declaration_file_cannot_be_imported_without_import_type_Did_you_mean_to_import_an_implementation_file_0_instead, getSuggestedImportSource(Debug.checkDefined(tryExtractTSExtension(moduleReference))), ); } } - else if (resolvedModule.resolvedUsingTsExtension && !shouldAllowImportingTsExtension(compilerOptions, currentSourceFile.fileName)) { - const importOrExport = findAncestor(location, isImportDeclaration)?.importClause || - findAncestor(location, or(isImportEqualsDeclaration, isExportDeclaration)); + else if ( + resolvedModule.resolvedUsingTsExtension + && !shouldAllowImportingTsExtension(compilerOptions, currentSourceFile.fileName) + ) { + const importOrExport = findAncestor(location, isImportDeclaration)?.importClause + || findAncestor(location, or(isImportEqualsDeclaration, isExportDeclaration)); if (!(importOrExport?.isTypeOnly || findAncestor(location, isImportTypeNode))) { const tsExtension = Debug.checkDefined(tryExtractTSExtension(moduleReference)); - error(errorNode, Diagnostics.An_import_path_can_only_end_with_a_0_extension_when_allowImportingTsExtensions_is_enabled, tsExtension); + error( + errorNode, + Diagnostics + .An_import_path_can_only_end_with_a_0_extension_when_allowImportingTsExtensions_is_enabled, + tsExtension, + ); } } if (sourceFile.symbol) { - if (resolvedModule.isExternalLibraryImport && !resolutionExtensionIsTSOrJson(resolvedModule.extension)) { - errorOnImplicitAnyModule(/*isError*/ false, errorNode, currentSourceFile, mode, resolvedModule, moduleReference); + if ( + resolvedModule.isExternalLibraryImport && !resolutionExtensionIsTSOrJson(resolvedModule.extension) + ) { + errorOnImplicitAnyModule( + /*isError*/ false, + errorNode, + currentSourceFile, + mode, + resolvedModule, + moduleReference, + ); } - if (moduleResolutionKind === ModuleResolutionKind.Node16 || moduleResolutionKind === ModuleResolutionKind.NodeNext) { - const isSyncImport = (currentSourceFile.impliedNodeFormat === ModuleKind.CommonJS && !findAncestor(location, isImportCall)) || !!findAncestor(location, isImportEqualsDeclaration); - const overrideClauseHost = findAncestor(location, l => isImportTypeNode(l) || isExportDeclaration(l) || isImportDeclaration(l)) as ImportTypeNode | ImportDeclaration | ExportDeclaration | undefined; - const overrideClause = overrideClauseHost && isImportTypeNode(overrideClauseHost) ? overrideClauseHost.assertions?.assertClause : overrideClauseHost?.assertClause; + if ( + moduleResolutionKind === ModuleResolutionKind.Node16 + || moduleResolutionKind === ModuleResolutionKind.NodeNext + ) { + const isSyncImport = (currentSourceFile.impliedNodeFormat === ModuleKind.CommonJS + && !findAncestor(location, isImportCall)) + || !!findAncestor(location, isImportEqualsDeclaration); + const overrideClauseHost = findAncestor( + location, + l => isImportTypeNode(l) || isExportDeclaration(l) || isImportDeclaration(l), + ) as ImportTypeNode | ImportDeclaration | ExportDeclaration | undefined; + const overrideClause = overrideClauseHost && isImportTypeNode(overrideClauseHost) + ? overrideClauseHost.assertions?.assertClause : overrideClauseHost?.assertClause; // An override clause will take effect for type-only imports and import types, and allows importing the types across formats, regardless of // normal mode restrictions - if (isSyncImport && sourceFile.impliedNodeFormat === ModuleKind.ESNext && !getResolutionModeOverrideForClause(overrideClause)) { + if ( + isSyncImport && sourceFile.impliedNodeFormat === ModuleKind.ESNext + && !getResolutionModeOverrideForClause(overrideClause) + ) { if (findAncestor(location, isImportEqualsDeclaration)) { // ImportEquals in a ESM file resolving to another ESM file - error(errorNode, Diagnostics.Module_0_cannot_be_imported_using_this_construct_The_specifier_only_resolves_to_an_ES_module_which_cannot_be_imported_with_require_Use_an_ECMAScript_import_instead, moduleReference); + error( + errorNode, + Diagnostics + .Module_0_cannot_be_imported_using_this_construct_The_specifier_only_resolves_to_an_ES_module_which_cannot_be_imported_with_require_Use_an_ECMAScript_import_instead, + moduleReference, + ); } else { // CJS file resolving to an ESM file let diagnosticDetails; const ext = tryGetExtensionFromPath(currentSourceFile.fileName); - if (ext === Extension.Ts || ext === Extension.Js || ext === Extension.Tsx || ext === Extension.Jsx) { + if ( + ext === Extension.Ts || ext === Extension.Js || ext === Extension.Tsx + || ext === Extension.Jsx + ) { const scope = currentSourceFile.packageJsonScope; - const targetExt = ext === Extension.Ts ? Extension.Mts : ext === Extension.Js ? Extension.Mjs : undefined; + const targetExt = ext === Extension.Ts ? Extension.Mts + : ext === Extension.Js ? Extension.Mjs : undefined; if (scope && !scope.contents.packageJsonContent.type) { if (targetExt) { diagnosticDetails = chainDiagnosticMessages( /*details*/ undefined, - Diagnostics.To_convert_this_file_to_an_ECMAScript_module_change_its_file_extension_to_0_or_add_the_field_type_Colon_module_to_1, + Diagnostics + .To_convert_this_file_to_an_ECMAScript_module_change_its_file_extension_to_0_or_add_the_field_type_Colon_module_to_1, targetExt, combinePaths(scope.packageDirectory, "package.json"), ); @@ -5008,7 +6070,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { else { diagnosticDetails = chainDiagnosticMessages( /*details*/ undefined, - Diagnostics.To_convert_this_file_to_an_ECMAScript_module_add_the_field_type_Colon_module_to_0, + Diagnostics + .To_convert_this_file_to_an_ECMAScript_module_add_the_field_type_Colon_module_to_0, combinePaths(scope.packageDirectory, "package.json"), ); } @@ -5017,14 +6080,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (targetExt) { diagnosticDetails = chainDiagnosticMessages( /*details*/ undefined, - Diagnostics.To_convert_this_file_to_an_ECMAScript_module_change_its_file_extension_to_0_or_create_a_local_package_json_file_with_type_Colon_module, + Diagnostics + .To_convert_this_file_to_an_ECMAScript_module_change_its_file_extension_to_0_or_create_a_local_package_json_file_with_type_Colon_module, targetExt, ); } else { diagnosticDetails = chainDiagnosticMessages( /*details*/ undefined, - Diagnostics.To_convert_this_file_to_an_ECMAScript_module_create_a_local_package_json_file_with_type_Colon_module, + Diagnostics + .To_convert_this_file_to_an_ECMAScript_module_create_a_local_package_json_file_with_type_Colon_module, ); } } @@ -5034,7 +6099,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { errorNode, chainDiagnosticMessages( diagnosticDetails, - Diagnostics.The_current_file_is_a_CommonJS_module_whose_imports_will_produce_require_calls_however_the_referenced_file_is_an_ECMAScript_module_and_cannot_be_imported_with_require_Consider_writing_a_dynamic_import_0_call_instead, + Diagnostics + .The_current_file_is_a_CommonJS_module_whose_imports_will_produce_require_calls_however_the_referenced_file_is_an_ECMAScript_module_and_cannot_be_imported_with_require_Consider_writing_a_dynamic_import_0_call_instead, moduleReference, ), )); @@ -5058,7 +6124,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // module augmentation by the specific name requested ('a.foo'), we store the merged symbol // by the augmentation name ('a.foo'), because asking for *.foo should not give you exports // from a.foo. - const augmentation = patternAmbientModuleAugmentations && patternAmbientModuleAugmentations.get(moduleReference); + const augmentation = patternAmbientModuleAugmentations + && patternAmbientModuleAugmentations.get(moduleReference); if (augmentation) { return getMergedSymbol(augmentation); } @@ -5067,13 +6134,26 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } // May be an untyped module. If so, ignore resolutionDiagnostic. - if (resolvedModule && !resolutionExtensionIsTSOrJson(resolvedModule.extension) && resolutionDiagnostic === undefined || resolutionDiagnostic === Diagnostics.Could_not_find_a_declaration_file_for_module_0_1_implicitly_has_an_any_type) { + if ( + resolvedModule && !resolutionExtensionIsTSOrJson(resolvedModule.extension) + && resolutionDiagnostic === undefined + || resolutionDiagnostic + === Diagnostics.Could_not_find_a_declaration_file_for_module_0_1_implicitly_has_an_any_type + ) { if (isForAugmentation) { - const diag = Diagnostics.Invalid_module_name_in_augmentation_Module_0_resolves_to_an_untyped_module_at_1_which_cannot_be_augmented; + const diag = Diagnostics + .Invalid_module_name_in_augmentation_Module_0_resolves_to_an_untyped_module_at_1_which_cannot_be_augmented; error(errorNode, diag, moduleReference, resolvedModule!.resolvedFileName); } else { - errorOnImplicitAnyModule(/*isError*/ noImplicitAny && !!moduleNotFoundError, errorNode, currentSourceFile, mode, resolvedModule!, moduleReference); + errorOnImplicitAnyModule( + /*isError*/ noImplicitAny && !!moduleNotFoundError, + errorNode, + currentSourceFile, + mode, + resolvedModule!, + moduleReference, + ); } // Failed imports and untyped modules are both treated in an untyped manner; only difference is whether we give a diagnostic first. return undefined; @@ -5084,7 +6164,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (resolvedModule) { const redirect = host.getProjectReferenceRedirect(resolvedModule.resolvedFileName); if (redirect) { - error(errorNode, Diagnostics.Output_file_0_has_not_been_built_from_source_file_1, redirect, resolvedModule.resolvedFileName); + error( + errorNode, + Diagnostics.Output_file_0_has_not_been_built_from_source_file_1, + redirect, + resolvedModule.resolvedFileName, + ); return undefined; } } @@ -5093,25 +6178,45 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { error(errorNode, resolutionDiagnostic, moduleReference, resolvedModule.resolvedFileName); } else { - const isExtensionlessRelativePathImport = pathIsRelative(moduleReference) && !hasExtension(moduleReference); - const resolutionIsNode16OrNext = moduleResolutionKind === ModuleResolutionKind.Node16 || - moduleResolutionKind === ModuleResolutionKind.NodeNext; + const isExtensionlessRelativePathImport = pathIsRelative(moduleReference) + && !hasExtension(moduleReference); + const resolutionIsNode16OrNext = moduleResolutionKind === ModuleResolutionKind.Node16 + || moduleResolutionKind === ModuleResolutionKind.NodeNext; if ( - !getResolveJsonModule(compilerOptions) && - fileExtensionIs(moduleReference, Extension.Json) && - moduleResolutionKind !== ModuleResolutionKind.Classic && - hasJsonModuleEmitEnabled(compilerOptions) + !getResolveJsonModule(compilerOptions) + && fileExtensionIs(moduleReference, Extension.Json) + && moduleResolutionKind !== ModuleResolutionKind.Classic + && hasJsonModuleEmitEnabled(compilerOptions) ) { - error(errorNode, Diagnostics.Cannot_find_module_0_Consider_using_resolveJsonModule_to_import_module_with_json_extension, moduleReference); + error( + errorNode, + Diagnostics + .Cannot_find_module_0_Consider_using_resolveJsonModule_to_import_module_with_json_extension, + moduleReference, + ); } else if (mode === ModuleKind.ESNext && resolutionIsNode16OrNext && isExtensionlessRelativePathImport) { - const absoluteRef = getNormalizedAbsolutePath(moduleReference, getDirectoryPath(currentSourceFile.path)); - const suggestedExt = suggestedExtensions.find(([actualExt, _importExt]) => host.fileExists(absoluteRef + actualExt))?.[1]; + const absoluteRef = getNormalizedAbsolutePath( + moduleReference, + getDirectoryPath(currentSourceFile.path), + ); + const suggestedExt = suggestedExtensions.find(([actualExt, _importExt]) => + host.fileExists(absoluteRef + actualExt) + )?.[1]; if (suggestedExt) { - error(errorNode, Diagnostics.Relative_import_paths_need_explicit_file_extensions_in_EcmaScript_imports_when_moduleResolution_is_node16_or_nodenext_Did_you_mean_0, moduleReference + suggestedExt); + error( + errorNode, + Diagnostics + .Relative_import_paths_need_explicit_file_extensions_in_EcmaScript_imports_when_moduleResolution_is_node16_or_nodenext_Did_you_mean_0, + moduleReference + suggestedExt, + ); } else { - error(errorNode, Diagnostics.Relative_import_paths_need_explicit_file_extensions_in_EcmaScript_imports_when_moduleResolution_is_node16_or_nodenext_Consider_adding_an_extension_to_the_import_path); + error( + errorNode, + Diagnostics + .Relative_import_paths_need_explicit_file_extensions_in_EcmaScript_imports_when_moduleResolution_is_node16_or_nodenext_Consider_adding_an_extension_to_the_import_path, + ); } } else { @@ -5128,17 +6233,25 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { * @see https://github.com/microsoft/TypeScript/issues/42151 */ if (emitModuleKindIsNonNodeESM(moduleKind) || mode === ModuleKind.ESNext) { - const preferTs = isDeclarationFileName(moduleReference) && shouldAllowImportingTsExtension(compilerOptions); - const ext = tsExtension === Extension.Mts || tsExtension === Extension.Dmts ? preferTs ? ".mts" : ".mjs" : - tsExtension === Extension.Cts || tsExtension === Extension.Dmts ? preferTs ? ".cts" : ".cjs" : - preferTs ? ".ts" : ".js"; + const preferTs = isDeclarationFileName(moduleReference) + && shouldAllowImportingTsExtension(compilerOptions); + const ext = tsExtension === Extension.Mts || tsExtension === Extension.Dmts ? preferTs ? ".mts" : ".mjs" + : tsExtension === Extension.Cts || tsExtension === Extension.Dmts ? preferTs ? ".cts" : ".cjs" + : preferTs ? ".ts" : ".js"; return importSourceWithoutExtension + ext; } return importSourceWithoutExtension; } } - function errorOnImplicitAnyModule(isError: boolean, errorNode: Node, sourceFile: SourceFile, mode: ResolutionMode, { packageId, resolvedFileName }: ResolvedModuleFull, moduleReference: string): void { + function errorOnImplicitAnyModule( + isError: boolean, + errorNode: Node, + sourceFile: SourceFile, + mode: ResolutionMode, + { packageId, resolvedFileName }: ResolvedModuleFull, + moduleReference: string, + ): void { let errorInfo: DiagnosticMessageChain | undefined; if (!isExternalModuleNameRelative(moduleReference) && packageId) { errorInfo = createModuleNotFoundChain(sourceFile, host, moduleReference, mode, packageId.name); @@ -5156,10 +6269,19 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function resolveExternalModuleSymbol(moduleSymbol: Symbol, dontResolveAlias?: boolean): Symbol; - function resolveExternalModuleSymbol(moduleSymbol: Symbol | undefined, dontResolveAlias?: boolean): Symbol | undefined; - function resolveExternalModuleSymbol(moduleSymbol: Symbol | undefined, dontResolveAlias?: boolean): Symbol | undefined { + function resolveExternalModuleSymbol( + moduleSymbol: Symbol | undefined, + dontResolveAlias?: boolean, + ): Symbol | undefined; + function resolveExternalModuleSymbol( + moduleSymbol: Symbol | undefined, + dontResolveAlias?: boolean, + ): Symbol | undefined { if (moduleSymbol?.exports) { - const exportEquals = resolveSymbol(moduleSymbol.exports.get(InternalSymbolName.ExportEquals), dontResolveAlias); + const exportEquals = resolveSymbol( + moduleSymbol.exports.get(InternalSymbolName.ExportEquals), + dontResolveAlias, + ); const exported = getCommonJsExportEquals(getMergedSymbol(exportEquals), getMergedSymbol(moduleSymbol)); return getMergedSymbol(exported) || moduleSymbol; } @@ -5167,7 +6289,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function getCommonJsExportEquals(exported: Symbol | undefined, moduleSymbol: Symbol): Symbol | undefined { - if (!exported || exported === unknownSymbol || exported === moduleSymbol || moduleSymbol.exports!.size === 1 || exported.flags & SymbolFlags.Alias) { + if ( + !exported || exported === unknownSymbol || exported === moduleSymbol || moduleSymbol.exports!.size === 1 + || exported.flags & SymbolFlags.Alias + ) { return exported; } const links = getSymbolLinks(exported); @@ -5196,26 +6321,40 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // An external module with an 'export =' declaration may be referenced as an ES6 module provided the 'export =' // references a symbol that is at least declared as a module or a variable. The target of the 'export =' may // combine other declarations with the module or variable (e.g. a class/module, function/module, interface/variable). - function resolveESModuleSymbol(moduleSymbol: Symbol | undefined, referencingLocation: Node, dontResolveAlias: boolean, suppressInteropError: boolean): Symbol | undefined { + function resolveESModuleSymbol( + moduleSymbol: Symbol | undefined, + referencingLocation: Node, + dontResolveAlias: boolean, + suppressInteropError: boolean, + ): Symbol | undefined { const symbol = resolveExternalModuleSymbol(moduleSymbol, dontResolveAlias); if (!dontResolveAlias && symbol) { - if (!suppressInteropError && !(symbol.flags & (SymbolFlags.Module | SymbolFlags.Variable)) && !getDeclarationOfKind(symbol, SyntaxKind.SourceFile)) { + if ( + !suppressInteropError && !(symbol.flags & (SymbolFlags.Module | SymbolFlags.Variable)) + && !getDeclarationOfKind(symbol, SyntaxKind.SourceFile) + ) { const compilerOptionName = moduleKind >= ModuleKind.ES2015 ? "allowSyntheticDefaultImports" : "esModuleInterop"; - error(referencingLocation, Diagnostics.This_module_can_only_be_referenced_with_ECMAScript_imports_Slashexports_by_turning_on_the_0_flag_and_referencing_its_default_export, compilerOptionName); + error( + referencingLocation, + Diagnostics + .This_module_can_only_be_referenced_with_ECMAScript_imports_Slashexports_by_turning_on_the_0_flag_and_referencing_its_default_export, + compilerOptionName, + ); return symbol; } const referenceParent = referencingLocation.parent; if ( - (isImportDeclaration(referenceParent) && getNamespaceDeclarationNode(referenceParent)) || - isImportCall(referenceParent) + (isImportDeclaration(referenceParent) && getNamespaceDeclarationNode(referenceParent)) + || isImportCall(referenceParent) ) { - const reference = isImportCall(referenceParent) ? referenceParent.arguments[0] : referenceParent.moduleSpecifier; + const reference = isImportCall(referenceParent) ? referenceParent.arguments[0] + : referenceParent.moduleSpecifier; const type = getTypeOfSymbol(symbol); const defaultOnlyType = getTypeWithSyntheticDefaultOnly(type, symbol, moduleSymbol!, reference); if (defaultOnlyType) { @@ -5223,16 +6362,24 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } const targetFile = moduleSymbol?.declarations?.find(isSourceFile); - const isEsmCjsRef = targetFile && isESMFormatImportImportingCommonjsFormatFile(getUsageModeForExpression(reference), targetFile.impliedNodeFormat); + const isEsmCjsRef = targetFile + && isESMFormatImportImportingCommonjsFormatFile( + getUsageModeForExpression(reference), + targetFile.impliedNodeFormat, + ); if (getESModuleInterop(compilerOptions) || isEsmCjsRef) { let sigs = getSignaturesOfStructuredType(type, SignatureKind.Call); if (!sigs || !sigs.length) { sigs = getSignaturesOfStructuredType(type, SignatureKind.Construct); } if ( - (sigs && sigs.length) || - getPropertyOfType(type, InternalSymbolName.Default, /*skipObjectFunctionPropertyAugment*/ true) || - isEsmCjsRef + (sigs && sigs.length) + || getPropertyOfType( + type, + InternalSymbolName.Default, + /*skipObjectFunctionPropertyAugment*/ true, + ) + || isEsmCjsRef ) { const moduleType = type.flags & TypeFlags.StructuredType ? getTypeWithSyntheticDefaultImportType(type, symbol, moduleSymbol!, reference) @@ -5259,7 +6406,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (symbol.members) result.members = new Map(symbol.members); if (symbol.exports) result.exports = new Map(symbol.exports); const resolvedModuleType = resolveStructuredTypeMembers(moduleType as StructuredType); // Should already be resolved from the signature checks above - result.links.type = createAnonymousType(result, resolvedModuleType.members, emptyArray, emptyArray, resolvedModuleType.indexInfos); + result.links.type = createAnonymousType( + result, + resolvedModuleType.members, + emptyArray, + emptyArray, + resolvedModuleType.indexInfos, + ); return result; } @@ -5324,17 +6477,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function shouldTreatPropertiesOfExternalModuleAsExports(resolvedExternalModuleType: Type) { - return !(resolvedExternalModuleType.flags & TypeFlags.Primitive || - getObjectFlags(resolvedExternalModuleType) & ObjectFlags.Class || + return !(resolvedExternalModuleType.flags & TypeFlags.Primitive + || getObjectFlags(resolvedExternalModuleType) & ObjectFlags.Class // `isArrayOrTupleLikeType` is too expensive to use in this auto-imports hot path - isArrayType(resolvedExternalModuleType) || - isTupleType(resolvedExternalModuleType)); + || isArrayType(resolvedExternalModuleType) + || isTupleType(resolvedExternalModuleType)); } function getExportsOfSymbol(symbol: Symbol): SymbolTable { - return symbol.flags & SymbolFlags.LateBindingContainer ? getResolvedMembersOrExportsOfSymbol(symbol, MembersOrExportsResolutionKind.resolvedExports) : - symbol.flags & SymbolFlags.Module ? getExportsOfModule(symbol) : - symbol.exports || emptySymbols; + return symbol.flags & SymbolFlags.LateBindingContainer + ? getResolvedMembersOrExportsOfSymbol(symbol, MembersOrExportsResolutionKind.resolvedExports) + : symbol.flags & SymbolFlags.Module ? getExportsOfModule(symbol) + : symbol.exports || emptySymbols; } function getExportsOfModule(moduleSymbol: Symbol): SymbolTable { @@ -5358,7 +6512,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { * Extends one symbol table with another while collecting information on name collisions for error message generation into the `lookupTable` argument * Not passing `lookupTable` and `exportNode` disables this collection, and just extends the tables */ - function extendExportSymbols(target: SymbolTable, source: SymbolTable | undefined, lookupTable?: ExportCollisionTrackerTable, exportNode?: ExportDeclaration) { + function extendExportSymbols( + target: SymbolTable, + source: SymbolTable | undefined, + lookupTable?: ExportCollisionTrackerTable, + exportNode?: ExportDeclaration, + ) { if (!source) return; source.forEach((sourceSymbol, id) => { if (id === InternalSymbolName.Default) return; @@ -5372,7 +6531,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { }); } } - else if (lookupTable && exportNode && targetSymbol && resolveSymbol(targetSymbol) !== resolveSymbol(sourceSymbol)) { + else if ( + lookupTable && exportNode && targetSymbol && resolveSymbol(targetSymbol) !== resolveSymbol(sourceSymbol) + ) { const collisionTracker = lookupTable.get(id)!; if (!collisionTracker.exportsWithDuplicate) { collisionTracker.exportsWithDuplicate = [exportNode]; @@ -5386,7 +6547,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function getExportsOfModuleWorker(moduleSymbol: Symbol) { const visitedSymbols: Symbol[] = []; - let typeOnlyExportStarMap: Map<__String, ExportDeclaration & { readonly isTypeOnly: true; readonly moduleSpecifier: Expression; }> | undefined; + let typeOnlyExportStarMap: + | Map<__String, ExportDeclaration & { readonly isTypeOnly: true; readonly moduleSpecifier: Expression; }> + | undefined; const nonTypeOnlyNames = new Set<__String>(); // A module defined by an 'export=' consists of one export that needs to be resolved @@ -5404,7 +6567,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // The ES6 spec permits export * declarations in a module to circularly reference the module itself. For example, // module 'a' can 'export * from "b"' and 'b' can 'export * from "a"' without error. - function visit(symbol: Symbol | undefined, exportStar?: ExportDeclaration, isTypeOnly?: boolean): SymbolTable | undefined { + function visit( + symbol: Symbol | undefined, + exportStar?: ExportDeclaration, + isTypeOnly?: boolean, + ): SymbolTable | undefined { if (!isTypeOnly && symbol?.exports) { // Add non-type-only names before checking if we've visited this module, // because we might have visited it via an 'export type *', and visiting @@ -5423,8 +6590,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const lookupTable: ExportCollisionTrackerTable = new Map(); if (exportStars.declarations) { for (const node of exportStars.declarations) { - const resolvedModule = resolveExternalModuleName(node, (node as ExportDeclaration).moduleSpecifier!); - const exportedSymbols = visit(resolvedModule, node as ExportDeclaration, isTypeOnly || (node as ExportDeclaration).isTypeOnly); + const resolvedModule = resolveExternalModuleName( + node, + (node as ExportDeclaration).moduleSpecifier!, + ); + const exportedSymbols = visit( + resolvedModule, + node as ExportDeclaration, + isTypeOnly || (node as ExportDeclaration).isTypeOnly, + ); extendExportSymbols( nestedSymbols, exportedSymbols, @@ -5441,7 +6615,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { for (const node of exportsWithDuplicate) { diagnostics.add(createDiagnosticForNode( node, - Diagnostics.Module_0_has_already_exported_a_member_named_1_Consider_explicitly_re_exporting_to_resolve_the_ambiguity, + Diagnostics + .Module_0_has_already_exported_a_member_named_1_Consider_explicitly_re_exporting_to_resolve_the_ambiguity, lookupTable.get(id)!.specifierText, unescapeLeadingUnderscores(id), )); @@ -5454,7 +6629,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { symbols.forEach((_, escapedName) => typeOnlyExportStarMap!.set( escapedName, - exportStar as ExportDeclaration & { readonly isTypeOnly: true; readonly moduleSpecifier: Expression; }, + exportStar as ExportDeclaration & { + readonly isTypeOnly: true; + readonly moduleSpecifier: Expression; + }, ) ); } @@ -5497,7 +6675,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // Try to make an import using an import already in the enclosing file, if possible for (const importRef of containingFile.imports) { if (nodeIsSynthesized(importRef)) continue; // Synthetic names can't be resolved by `resolveExternalModuleName` - they'll cause a debug assert if they error - const resolvedModule = resolveExternalModuleName(enclosingDeclaration, importRef, /*ignoreErrors*/ true); + const resolvedModule = resolveExternalModuleName( + enclosingDeclaration, + importRef, + /*ignoreErrors*/ true, + ); if (!resolvedModule) continue; const ref = getAliasForSymbolInContainer(resolvedModule, symbol); if (!ref) continue; @@ -5527,19 +6709,35 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { * Attempts to find the symbol corresponding to the container a symbol is in - usually this * is just its' `.parent`, but for locals, this value is `undefined` */ - function getContainersOfSymbol(symbol: Symbol, enclosingDeclaration: Node | undefined, meaning: SymbolFlags): Symbol[] | undefined { + function getContainersOfSymbol( + symbol: Symbol, + enclosingDeclaration: Node | undefined, + meaning: SymbolFlags, + ): Symbol[] | undefined { const container = getParentOfSymbol(symbol); // Type parameters end up in the `members` lists but are not externally visible if (container && !(symbol.flags & SymbolFlags.TypeParameter)) { - const additionalContainers = mapDefined(container.declarations, fileSymbolIfFileSymbolExportEqualsContainer); - const reexportContainers = enclosingDeclaration && getAlternativeContainingModules(symbol, enclosingDeclaration); + const additionalContainers = mapDefined( + container.declarations, + fileSymbolIfFileSymbolExportEqualsContainer, + ); + const reexportContainers = enclosingDeclaration + && getAlternativeContainingModules(symbol, enclosingDeclaration); const objectLiteralContainer = getVariableDeclarationOfObjectLiteral(container, meaning); if ( - enclosingDeclaration && - container.flags & getQualifiedLeftMeaning(meaning) && - getAccessibleSymbolChain(container, enclosingDeclaration, SymbolFlags.Namespace, /*useOnlyExternalAliasing*/ false) + enclosingDeclaration + && container.flags & getQualifiedLeftMeaning(meaning) + && getAccessibleSymbolChain( + container, + enclosingDeclaration, + SymbolFlags.Namespace, + /*useOnlyExternalAliasing*/ false, + ) ) { - return append(concatenate(concatenate([container], additionalContainers), reexportContainers), objectLiteralContainer); // This order expresses a preference for the real container if it is in scope + return append( + concatenate(concatenate([container], additionalContainers), reexportContainers), + objectLiteralContainer, + ); // This order expresses a preference for the real container if it is in scope } // we potentially have a symbol which is a member of the instance side of something - look for a variable in scope with the container's type // which may be acting like a namespace (eg, `Symbol` acts like a namespace when looking up `Symbol.toStringTag`) @@ -5549,12 +6747,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { && meaning === SymbolFlags.Value ? forEachSymbolTableInScope(enclosingDeclaration, t => { return forEachEntry(t, s => { - if (s.flags & getQualifiedLeftMeaning(meaning) && getTypeOfSymbol(s) === getDeclaredTypeOfSymbol(container)) { + if ( + s.flags & getQualifiedLeftMeaning(meaning) + && getTypeOfSymbol(s) === getDeclaredTypeOfSymbol(container) + ) { return s; } }); }) : undefined; - let res = firstVariableMatch ? [firstVariableMatch, ...additionalContainers, container] : [...additionalContainers, container]; + let res = firstVariableMatch ? [firstVariableMatch, ...additionalContainers, container] + : [...additionalContainers, container]; res = append(res, objectLiteralContainer); res = addRange(res, reexportContainers); return res; @@ -5566,11 +6768,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return getSymbolOfDeclaration(d.parent as Declaration); } // export ='d member of an ambient module - if (isModuleBlock(d.parent) && d.parent.parent && resolveExternalModuleSymbol(getSymbolOfDeclaration(d.parent.parent)) === symbol) { + if ( + isModuleBlock(d.parent) && d.parent.parent + && resolveExternalModuleSymbol(getSymbolOfDeclaration(d.parent.parent)) === symbol + ) { return getSymbolOfDeclaration(d.parent.parent); } } - if (isClassExpression(d) && isBinaryExpression(d.parent) && d.parent.operatorToken.kind === SyntaxKind.EqualsToken && isAccessExpression(d.parent.left) && isEntityNameExpression(d.parent.left.expression)) { + if ( + isClassExpression(d) && isBinaryExpression(d.parent) + && d.parent.operatorToken.kind === SyntaxKind.EqualsToken && isAccessExpression(d.parent.left) + && isEntityNameExpression(d.parent.left.expression) + ) { if (isModuleExportsAccessExpression(d.parent.left) || isExportsIdentifier(d.parent.left.expression)) { return getSymbolOfDeclaration(getSourceFileOfNode(d)); } @@ -5581,7 +6790,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (!length(candidates)) { return undefined; } - return mapDefined(candidates, candidate => getAliasForSymbolInContainer(candidate, symbol) ? candidate : undefined); + return mapDefined( + candidates, + candidate => getAliasForSymbolInContainer(candidate, symbol) ? candidate : undefined, + ); function fileSymbolIfFileSymbolExportEqualsContainer(d: Declaration) { return container && getFileSymbolIfFileSymbolExportEqualsContainer(d, container); @@ -5594,7 +6806,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // we'd like to make that connection here - potentially causing us to paint the declaration's visibility, and therefore the literal. const firstDecl: Node | false = !!length(symbol.declarations) && first(symbol.declarations!); if (meaning & SymbolFlags.Value && firstDecl && firstDecl.parent && isVariableDeclaration(firstDecl.parent)) { - if (isObjectLiteralExpression(firstDecl) && firstDecl === firstDecl.parent.initializer || isTypeLiteralNode(firstDecl) && firstDecl === firstDecl.parent.type) { + if ( + isObjectLiteralExpression(firstDecl) && firstDecl === firstDecl.parent.initializer + || isTypeLiteralNode(firstDecl) && firstDecl === firstDecl.parent.type + ) { return getSymbolOfDeclaration(firstDecl.parent); } } @@ -5633,7 +6848,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { * Checks if two symbols, through aliasing and/or merging, refer to the same thing */ function getSymbolIfSameReference(s1: Symbol, s2: Symbol) { - if (getMergedSymbol(resolveSymbol(getMergedSymbol(s1))) === getMergedSymbol(resolveSymbol(getMergedSymbol(s2)))) { + if ( + getMergedSymbol(resolveSymbol(getMergedSymbol(s1))) === getMergedSymbol(resolveSymbol(getMergedSymbol(s2))) + ) { return s1; } } @@ -5641,13 +6858,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function getExportSymbolOfValueSymbolIfExported(symbol: Symbol): Symbol; function getExportSymbolOfValueSymbolIfExported(symbol: Symbol | undefined): Symbol | undefined; function getExportSymbolOfValueSymbolIfExported(symbol: Symbol | undefined): Symbol | undefined { - return getMergedSymbol(symbol && (symbol.flags & SymbolFlags.ExportValue) !== 0 && symbol.exportSymbol || symbol); + return getMergedSymbol( + symbol && (symbol.flags & SymbolFlags.ExportValue) !== 0 && symbol.exportSymbol || symbol, + ); } function symbolIsValue(symbol: Symbol, includeTypeOnlyMembers?: boolean): boolean { return !!( - symbol.flags & SymbolFlags.Value || - symbol.flags & SymbolFlags.Alias && getSymbolFlags(symbol, !includeTypeOnlyMembers) & SymbolFlags.Value + symbol.flags & SymbolFlags.Value + || symbol.flags & SymbolFlags.Alias && getSymbolFlags(symbol, !includeTypeOnlyMembers) & SymbolFlags.Value ); } @@ -5678,10 +6897,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return new Type(checker, flags); } - function createIntrinsicType(kind: TypeFlags, intrinsicName: string, objectFlags = ObjectFlags.None): IntrinsicType { + function createIntrinsicType( + kind: TypeFlags, + intrinsicName: string, + objectFlags = ObjectFlags.None, + ): IntrinsicType { const type = createType(kind) as IntrinsicType; type.intrinsicName = intrinsicName; - type.objectFlags = objectFlags | ObjectFlags.CouldContainTypeVariablesComputed | ObjectFlags.IsGenericTypeComputed | ObjectFlags.IsUnknownLikeUnionComputed | ObjectFlags.IsNeverIntersectionComputed; + type.objectFlags = objectFlags | ObjectFlags.CouldContainTypeVariablesComputed + | ObjectFlags.IsGenericTypeComputed | ObjectFlags.IsUnknownLikeUnionComputed + | ObjectFlags.IsNeverIntersectionComputed; return type; } @@ -5709,11 +6934,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // with at least two underscores. The @ character indicates that the name is denoted by a well known ES // Symbol instance and the # character indicates that the name is a PrivateIdentifier. function isReservedMemberName(name: __String) { - return (name as string).charCodeAt(0) === CharacterCodes._ && - (name as string).charCodeAt(1) === CharacterCodes._ && - (name as string).charCodeAt(2) !== CharacterCodes._ && - (name as string).charCodeAt(2) !== CharacterCodes.at && - (name as string).charCodeAt(2) !== CharacterCodes.hash; + return (name as string).charCodeAt(0) === CharacterCodes._ + && (name as string).charCodeAt(1) === CharacterCodes._ + && (name as string).charCodeAt(2) !== CharacterCodes._ + && (name as string).charCodeAt(2) !== CharacterCodes.at + && (name as string).charCodeAt(2) !== CharacterCodes.hash; } function getNamedMembers(members: SymbolTable): Symbol[] { @@ -5736,7 +6961,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return index ? concatenate(result, [index]) : result; } - function setStructuredTypeMembers(type: StructuredType, members: SymbolTable, callSignatures: readonly Signature[], constructSignatures: readonly Signature[], indexInfos: readonly IndexInfo[]): ResolvedType { + function setStructuredTypeMembers( + type: StructuredType, + members: SymbolTable, + callSignatures: readonly Signature[], + constructSignatures: readonly Signature[], + indexInfos: readonly IndexInfo[], + ): ResolvedType { const resolved = type as ResolvedType; resolved.members = members; resolved.properties = emptyArray; @@ -5748,14 +6979,29 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return resolved; } - function createAnonymousType(symbol: Symbol | undefined, members: SymbolTable, callSignatures: readonly Signature[], constructSignatures: readonly Signature[], indexInfos: readonly IndexInfo[]): ResolvedType { - return setStructuredTypeMembers(createObjectType(ObjectFlags.Anonymous, symbol), members, callSignatures, constructSignatures, indexInfos); + function createAnonymousType( + symbol: Symbol | undefined, + members: SymbolTable, + callSignatures: readonly Signature[], + constructSignatures: readonly Signature[], + indexInfos: readonly IndexInfo[], + ): ResolvedType { + return setStructuredTypeMembers( + createObjectType(ObjectFlags.Anonymous, symbol), + members, + callSignatures, + constructSignatures, + indexInfos, + ); } function getResolvedTypeWithoutAbstractConstructSignatures(type: ResolvedType) { if (type.constructSignatures.length === 0) return type; if (type.objectTypeWithoutAbstractConstructSignatures) return type.objectTypeWithoutAbstractConstructSignatures; - const constructSignatures = filter(type.constructSignatures, signature => !(signature.flags & SignatureFlags.Abstract)); + const constructSignatures = filter( + type.constructSignatures, + signature => !(signature.flags & SignatureFlags.Abstract), + ); if (type.constructSignatures === constructSignatures) return type; const typeCopy = createAnonymousType( type.symbol, @@ -5769,12 +7015,27 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return typeCopy; } - function forEachSymbolTableInScope(enclosingDeclaration: Node | undefined, callback: (symbolTable: SymbolTable, ignoreQualification?: boolean, isLocalNameLookup?: boolean, scopeNode?: Node) => T): T { + function forEachSymbolTableInScope( + enclosingDeclaration: Node | undefined, + callback: ( + symbolTable: SymbolTable, + ignoreQualification?: boolean, + isLocalNameLookup?: boolean, + scopeNode?: Node, + ) => T, + ): T { let result: T; for (let location = enclosingDeclaration; location; location = location.parent) { // Locals of a source file are not in scope (because they get merged into the global symbol table) if (canHaveLocals(location) && location.locals && !isGlobalSourceFile(location)) { - if (result = callback(location.locals, /*ignoreQualification*/ undefined, /*isLocalNameLookup*/ true, location)) { + if ( + result = callback( + location.locals, + /*ignoreQualification*/ undefined, + /*isLocalNameLookup*/ true, + location, + ) + ) { return result; } } @@ -5789,7 +7050,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // `sym` may not have exports if this module declaration is backed by the symbol for a `const` that's being rewritten // into a namespace - in such cases, it's best to just let the namespace appear empty (the const members couldn't have referred // to one another anyway) - if (result = callback(sym?.exports || emptySymbols, /*ignoreQualification*/ undefined, /*isLocalNameLookup*/ true, location)) { + if ( + result = callback( + sym?.exports || emptySymbols, + /*ignoreQualification*/ undefined, + /*isLocalNameLookup*/ true, + location, + ) + ) { return result; } break; @@ -5805,12 +7073,21 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // trigger resolving late-bound names, which we may already be in the process of doing while we're here! let table: Map<__String, Symbol> | undefined; // TODO: Should this filtered table be cached in some way? - (getSymbolOfDeclaration(location as ClassLikeDeclaration | InterfaceDeclaration).members || emptySymbols).forEach((memberSymbol, key) => { - if (memberSymbol.flags & (SymbolFlags.Type & ~SymbolFlags.Assignment)) { - (table || (table = createSymbolTable())).set(key, memberSymbol); - } - }); - if (table && (result = callback(table, /*ignoreQualification*/ undefined, /*isLocalNameLookup*/ false, location))) { + (getSymbolOfDeclaration(location as ClassLikeDeclaration | InterfaceDeclaration).members + || emptySymbols).forEach((memberSymbol, key) => { + if (memberSymbol.flags & (SymbolFlags.Type & ~SymbolFlags.Assignment)) { + (table || (table = createSymbolTable())).set(key, memberSymbol); + } + }); + if ( + table + && (result = callback( + table, + /*ignoreQualification*/ undefined, + /*isLocalNameLookup*/ false, + location, + )) + ) { return result; } break; @@ -5825,7 +7102,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return rightMeaning === SymbolFlags.Value ? SymbolFlags.Value : SymbolFlags.Namespace; } - function getAccessibleSymbolChain(symbol: Symbol | undefined, enclosingDeclaration: Node | undefined, meaning: SymbolFlags, useOnlyExternalAliasing: boolean, visitedSymbolTablesMap = new Map()): Symbol[] | undefined { + function getAccessibleSymbolChain( + symbol: Symbol | undefined, + enclosingDeclaration: Node | undefined, + meaning: SymbolFlags, + useOnlyExternalAliasing: boolean, + visitedSymbolTablesMap = new Map(), + ): Symbol[] | undefined { if (!(symbol && !isPropertyOrMethodDeclarationSymbol(symbol))) { return undefined; } @@ -5833,7 +7116,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const cache = (links.accessibleChainCache ||= new Map()); // Go from enclosingDeclaration to the first scope we check, so the cache is keyed off the scope and thus shared more const firstRelevantLocation = forEachSymbolTableInScope(enclosingDeclaration, (_, __, ___, node) => node); - const key = `${useOnlyExternalAliasing ? 0 : 1}|${firstRelevantLocation && getNodeId(firstRelevantLocation)}|${meaning}`; + const key = `${useOnlyExternalAliasing ? 0 : 1}|${ + firstRelevantLocation && getNodeId(firstRelevantLocation) + }|${meaning}`; if (cache.has(key)) { return cache.get(key); } @@ -5850,7 +7135,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { /** * @param {ignoreQualification} boolean Set when a symbol is being looked for through the exports of another symbol (meaning we have a route to qualify it already) */ - function getAccessibleSymbolChainFromSymbolTable(symbols: SymbolTable, ignoreQualification?: boolean, isLocalNameLookup?: boolean): Symbol[] | undefined { + function getAccessibleSymbolChainFromSymbolTable( + symbols: SymbolTable, + ignoreQualification?: boolean, + isLocalNameLookup?: boolean, + ): Symbol[] | undefined { if (!pushIfUnique(visitedSymbolTables!, symbols)) { return undefined; } @@ -5862,23 +7151,40 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function canQualifySymbol(symbolFromSymbolTable: Symbol, meaning: SymbolFlags) { // If the symbol is equivalent and doesn't need further qualification, this symbol is accessible - return !needsQualification(symbolFromSymbolTable, enclosingDeclaration, meaning) || + return !needsQualification(symbolFromSymbolTable, enclosingDeclaration, meaning) // If symbol needs qualification, make sure that parent is accessible, if it is then this symbol is accessible too - !!getAccessibleSymbolChain(symbolFromSymbolTable.parent, enclosingDeclaration, getQualifiedLeftMeaning(meaning), useOnlyExternalAliasing, visitedSymbolTablesMap); + || !!getAccessibleSymbolChain( + symbolFromSymbolTable.parent, + enclosingDeclaration, + getQualifiedLeftMeaning(meaning), + useOnlyExternalAliasing, + visitedSymbolTablesMap, + ); } - function isAccessible(symbolFromSymbolTable: Symbol, resolvedAliasSymbol?: Symbol, ignoreQualification?: boolean) { - return (symbol === (resolvedAliasSymbol || symbolFromSymbolTable) || getMergedSymbol(symbol) === getMergedSymbol(resolvedAliasSymbol || symbolFromSymbolTable)) && + function isAccessible( + symbolFromSymbolTable: Symbol, + resolvedAliasSymbol?: Symbol, + ignoreQualification?: boolean, + ) { + return (symbol === (resolvedAliasSymbol || symbolFromSymbolTable) + || getMergedSymbol(symbol) === getMergedSymbol(resolvedAliasSymbol || symbolFromSymbolTable)) // if the symbolFromSymbolTable is not external module (it could be if it was determined as ambient external module and would be in globals table) // and if symbolFromSymbolTable or alias resolution matches the symbol, // check the symbol can be qualified, it is only then this symbol is accessible - !some(symbolFromSymbolTable.declarations, hasNonGlobalAugmentationExternalModuleSymbol) && - (ignoreQualification || canQualifySymbol(getMergedSymbol(symbolFromSymbolTable), meaning)); + && !some(symbolFromSymbolTable.declarations, hasNonGlobalAugmentationExternalModuleSymbol) + && (ignoreQualification || canQualifySymbol(getMergedSymbol(symbolFromSymbolTable), meaning)); } - function trySymbolTable(symbols: SymbolTable, ignoreQualification: boolean | undefined, isLocalNameLookup: boolean | undefined): Symbol[] | undefined { + function trySymbolTable( + symbols: SymbolTable, + ignoreQualification: boolean | undefined, + isLocalNameLookup: boolean | undefined, + ): Symbol[] | undefined { // If symbol is directly available by its name in the symbol table - if (isAccessible(symbols.get(symbol!.escapedName)!, /*resolvedAliasSymbol*/ undefined, ignoreQualification)) { + if ( + isAccessible(symbols.get(symbol!.escapedName)!, /*resolvedAliasSymbol*/ undefined, ignoreQualification) + ) { return [symbol!]; } @@ -5888,33 +7194,52 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { symbolFromSymbolTable.flags & SymbolFlags.Alias && symbolFromSymbolTable.escapedName !== InternalSymbolName.ExportEquals && symbolFromSymbolTable.escapedName !== InternalSymbolName.Default - && !(isUMDExportSymbol(symbolFromSymbolTable) && enclosingDeclaration && isExternalModule(getSourceFileOfNode(enclosingDeclaration))) + && !(isUMDExportSymbol(symbolFromSymbolTable) && enclosingDeclaration + && isExternalModule(getSourceFileOfNode(enclosingDeclaration))) // If `!useOnlyExternalAliasing`, we can use any type of alias to get the name - && (!useOnlyExternalAliasing || some(symbolFromSymbolTable.declarations, isExternalModuleImportEqualsDeclaration)) + && (!useOnlyExternalAliasing + || some(symbolFromSymbolTable.declarations, isExternalModuleImportEqualsDeclaration)) // If we're looking up a local name to reference directly, omit namespace reexports, otherwise when we're trawling through an export list to make a dotted name, we can keep it - && (isLocalNameLookup ? !some(symbolFromSymbolTable.declarations, isNamespaceReexportDeclaration) : true) + && (isLocalNameLookup ? !some(symbolFromSymbolTable.declarations, isNamespaceReexportDeclaration) + : true) // While exports are generally considered to be in scope, export-specifier declared symbols are _not_ // See similar comment in `resolveName` for details && (ignoreQualification || !getDeclarationOfKind(symbolFromSymbolTable, SyntaxKind.ExportSpecifier)) ) { const resolvedImportedSymbol = resolveAlias(symbolFromSymbolTable); - const candidate = getCandidateListForSymbol(symbolFromSymbolTable, resolvedImportedSymbol, ignoreQualification); + const candidate = getCandidateListForSymbol( + symbolFromSymbolTable, + resolvedImportedSymbol, + ignoreQualification, + ); if (candidate) { return candidate; } } if (symbolFromSymbolTable.escapedName === symbol!.escapedName && symbolFromSymbolTable.exportSymbol) { - if (isAccessible(getMergedSymbol(symbolFromSymbolTable.exportSymbol), /*resolvedAliasSymbol*/ undefined, ignoreQualification)) { + if ( + isAccessible( + getMergedSymbol(symbolFromSymbolTable.exportSymbol), + /*resolvedAliasSymbol*/ undefined, + ignoreQualification, + ) + ) { return [symbol!]; } } }); // If there's no result and we're looking at the global symbol table, treat `globalThis` like an alias and try to lookup thru that - return result || (symbols === globals ? getCandidateListForSymbol(globalThisSymbol, globalThisSymbol, ignoreQualification) : undefined); + return result + || (symbols === globals + ? getCandidateListForSymbol(globalThisSymbol, globalThisSymbol, ignoreQualification) : undefined); } - function getCandidateListForSymbol(symbolFromSymbolTable: Symbol, resolvedImportedSymbol: Symbol, ignoreQualification: boolean | undefined) { + function getCandidateListForSymbol( + symbolFromSymbolTable: Symbol, + resolvedImportedSymbol: Symbol, + ignoreQualification: boolean | undefined, + ) { if (isAccessible(symbolFromSymbolTable, resolvedImportedSymbol, ignoreQualification)) { return [symbolFromSymbolTable]; } @@ -5922,8 +7247,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // Look in the exported members, if we can find accessibleSymbolChain, symbol is accessible using this chain // but only if the symbolFromSymbolTable can be qualified const candidateTable = getExportsOfSymbol(resolvedImportedSymbol); - const accessibleSymbolsFromExports = candidateTable && getAccessibleSymbolChainFromSymbolTable(candidateTable, /*ignoreQualification*/ true); - if (accessibleSymbolsFromExports && canQualifySymbol(symbolFromSymbolTable, getQualifiedLeftMeaning(meaning))) { + const accessibleSymbolsFromExports = candidateTable + && getAccessibleSymbolChainFromSymbolTable(candidateTable, /*ignoreQualification*/ true); + if ( + accessibleSymbolsFromExports + && canQualifySymbol(symbolFromSymbolTable, getQualifiedLeftMeaning(meaning)) + ) { return [symbolFromSymbolTable].concat(accessibleSymbolsFromExports); } } @@ -5945,7 +7274,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } // Qualify if the symbol from symbol table has same meaning as expected - const shouldResolveAlias = symbolFromSymbolTable.flags & SymbolFlags.Alias && !getDeclarationOfKind(symbolFromSymbolTable, SyntaxKind.ExportSpecifier); + const shouldResolveAlias = symbolFromSymbolTable.flags & SymbolFlags.Alias + && !getDeclarationOfKind(symbolFromSymbolTable, SyntaxKind.ExportSpecifier); symbolFromSymbolTable = shouldResolveAlias ? resolveAlias(symbolFromSymbolTable) : symbolFromSymbolTable; const flags = shouldResolveAlias ? getSymbolFlags(symbolFromSymbolTable) : symbolFromSymbolTable.flags; if (flags & meaning) { @@ -5979,31 +7309,68 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function isTypeSymbolAccessible(typeSymbol: Symbol, enclosingDeclaration: Node | undefined): boolean { - const access = isSymbolAccessibleWorker(typeSymbol, enclosingDeclaration, SymbolFlags.Type, /*shouldComputeAliasesToMakeVisible*/ false, /*allowModules*/ true); + const access = isSymbolAccessibleWorker( + typeSymbol, + enclosingDeclaration, + SymbolFlags.Type, + /*shouldComputeAliasesToMakeVisible*/ false, + /*allowModules*/ true, + ); return access.accessibility === SymbolAccessibility.Accessible; } function isValueSymbolAccessible(typeSymbol: Symbol, enclosingDeclaration: Node | undefined): boolean { - const access = isSymbolAccessibleWorker(typeSymbol, enclosingDeclaration, SymbolFlags.Value, /*shouldComputeAliasesToMakeVisible*/ false, /*allowModules*/ true); + const access = isSymbolAccessibleWorker( + typeSymbol, + enclosingDeclaration, + SymbolFlags.Value, + /*shouldComputeAliasesToMakeVisible*/ false, + /*allowModules*/ true, + ); return access.accessibility === SymbolAccessibility.Accessible; } - function isSymbolAccessibleByFlags(typeSymbol: Symbol, enclosingDeclaration: Node | undefined, flags: SymbolFlags): boolean { - const access = isSymbolAccessibleWorker(typeSymbol, enclosingDeclaration, flags, /*shouldComputeAliasesToMakeVisible*/ false, /*allowModules*/ false); + function isSymbolAccessibleByFlags( + typeSymbol: Symbol, + enclosingDeclaration: Node | undefined, + flags: SymbolFlags, + ): boolean { + const access = isSymbolAccessibleWorker( + typeSymbol, + enclosingDeclaration, + flags, + /*shouldComputeAliasesToMakeVisible*/ false, + /*allowModules*/ false, + ); return access.accessibility === SymbolAccessibility.Accessible; } - function isAnySymbolAccessible(symbols: Symbol[] | undefined, enclosingDeclaration: Node | undefined, initialSymbol: Symbol, meaning: SymbolFlags, shouldComputeAliasesToMakeVisible: boolean, allowModules: boolean): SymbolAccessibilityResult | undefined { + function isAnySymbolAccessible( + symbols: Symbol[] | undefined, + enclosingDeclaration: Node | undefined, + initialSymbol: Symbol, + meaning: SymbolFlags, + shouldComputeAliasesToMakeVisible: boolean, + allowModules: boolean, + ): SymbolAccessibilityResult | undefined { if (!length(symbols)) return; let hadAccessibleChain: Symbol | undefined; let earlyModuleBail = false; for (const symbol of symbols!) { // Symbol is accessible if it by itself is accessible - const accessibleSymbolChain = getAccessibleSymbolChain(symbol, enclosingDeclaration, meaning, /*useOnlyExternalAliasing*/ false); + const accessibleSymbolChain = getAccessibleSymbolChain( + symbol, + enclosingDeclaration, + meaning, + /*useOnlyExternalAliasing*/ false, + ); if (accessibleSymbolChain) { hadAccessibleChain = symbol; - const hasAccessibleDeclarations = hasVisibleDeclarations(accessibleSymbolChain[0], shouldComputeAliasesToMakeVisible); + const hasAccessibleDeclarations = hasVisibleDeclarations( + accessibleSymbolChain[0], + shouldComputeAliasesToMakeVisible, + ); if (hasAccessibleDeclarations) { return hasAccessibleDeclarations; } @@ -6039,7 +7406,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // It is accessible if the parent m is accessible because then m.c can be accessed through qualification const containers = getContainersOfSymbol(symbol, enclosingDeclaration, meaning); - const parentResult = isAnySymbolAccessible(containers, enclosingDeclaration, initialSymbol, initialSymbol === symbol ? getQualifiedLeftMeaning(meaning) : meaning, shouldComputeAliasesToMakeVisible, allowModules); + const parentResult = isAnySymbolAccessible( + containers, + enclosingDeclaration, + initialSymbol, + initialSymbol === symbol ? getQualifiedLeftMeaning(meaning) : meaning, + shouldComputeAliasesToMakeVisible, + allowModules, + ); if (parentResult) { return parentResult; } @@ -6055,7 +7429,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return { accessibility: SymbolAccessibility.NotAccessible, errorSymbolName: symbolToString(initialSymbol, enclosingDeclaration, meaning), - errorModuleName: hadAccessibleChain !== initialSymbol ? symbolToString(hadAccessibleChain, enclosingDeclaration, SymbolFlags.Namespace) : undefined, + errorModuleName: hadAccessibleChain !== initialSymbol + ? symbolToString(hadAccessibleChain, enclosingDeclaration, SymbolFlags.Namespace) : undefined, }; } } @@ -6068,13 +7443,37 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { * @param meaning a SymbolFlags to check if such meaning of the symbol is accessible * @param shouldComputeAliasToMakeVisible a boolean value to indicate whether to return aliases to be mark visible in case the symbol is accessible */ - function isSymbolAccessible(symbol: Symbol | undefined, enclosingDeclaration: Node | undefined, meaning: SymbolFlags, shouldComputeAliasesToMakeVisible: boolean): SymbolAccessibilityResult { - return isSymbolAccessibleWorker(symbol, enclosingDeclaration, meaning, shouldComputeAliasesToMakeVisible, /*allowModules*/ true); + function isSymbolAccessible( + symbol: Symbol | undefined, + enclosingDeclaration: Node | undefined, + meaning: SymbolFlags, + shouldComputeAliasesToMakeVisible: boolean, + ): SymbolAccessibilityResult { + return isSymbolAccessibleWorker( + symbol, + enclosingDeclaration, + meaning, + shouldComputeAliasesToMakeVisible, + /*allowModules*/ true, + ); } - function isSymbolAccessibleWorker(symbol: Symbol | undefined, enclosingDeclaration: Node | undefined, meaning: SymbolFlags, shouldComputeAliasesToMakeVisible: boolean, allowModules: boolean): SymbolAccessibilityResult { + function isSymbolAccessibleWorker( + symbol: Symbol | undefined, + enclosingDeclaration: Node | undefined, + meaning: SymbolFlags, + shouldComputeAliasesToMakeVisible: boolean, + allowModules: boolean, + ): SymbolAccessibilityResult { if (symbol && enclosingDeclaration) { - const result = isAnySymbolAccessible([symbol], enclosingDeclaration, symbol, meaning, shouldComputeAliasesToMakeVisible, allowModules); + const result = isAnySymbolAccessible( + [symbol], + enclosingDeclaration, + symbol, + meaning, + shouldComputeAliasesToMakeVisible, + allowModules, + ); if (result) { return result; } @@ -6111,14 +7510,19 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function hasExternalModuleSymbol(declaration: Node) { - return isAmbientModule(declaration) || (declaration.kind === SyntaxKind.SourceFile && isExternalOrCommonJsModule(declaration as SourceFile)); + return isAmbientModule(declaration) + || (declaration.kind === SyntaxKind.SourceFile && isExternalOrCommonJsModule(declaration as SourceFile)); } function hasNonGlobalAugmentationExternalModuleSymbol(declaration: Node) { - return isModuleWithStringLiteralName(declaration) || (declaration.kind === SyntaxKind.SourceFile && isExternalOrCommonJsModule(declaration as SourceFile)); + return isModuleWithStringLiteralName(declaration) + || (declaration.kind === SyntaxKind.SourceFile && isExternalOrCommonJsModule(declaration as SourceFile)); } - function hasVisibleDeclarations(symbol: Symbol, shouldComputeAliasToMakeVisible: boolean): SymbolVisibilityResult | undefined { + function hasVisibleDeclarations( + symbol: Symbol, + shouldComputeAliasToMakeVisible: boolean, + ): SymbolVisibilityResult | undefined { let aliasesToMakeVisible: LateVisibilityPaintedStatement[] | undefined; if (!every(filter(symbol.declarations, d => d.kind !== SyntaxKind.Identifier), getIsDeclarationVisible)) { return undefined; @@ -6132,16 +7536,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const anyImportSyntax = getAnyImportSyntax(declaration); if ( - anyImportSyntax && - !hasSyntacticModifier(anyImportSyntax, ModifierFlags.Export) && // import clause without export - isDeclarationVisible(anyImportSyntax.parent) + anyImportSyntax + && !hasSyntacticModifier(anyImportSyntax, ModifierFlags.Export) // import clause without export + && isDeclarationVisible(anyImportSyntax.parent) ) { return addVisibleAlias(declaration, anyImportSyntax); } else if ( - isVariableDeclaration(declaration) && isVariableStatement(declaration.parent.parent) && - !hasSyntacticModifier(declaration.parent.parent, ModifierFlags.Export) && // unexported variable statement - isDeclarationVisible(declaration.parent.parent.parent) + isVariableDeclaration(declaration) && isVariableStatement(declaration.parent.parent) + && !hasSyntacticModifier(declaration.parent.parent, ModifierFlags.Export) // unexported variable statement + && isDeclarationVisible(declaration.parent.parent.parent) ) { return addVisibleAlias(declaration, declaration.parent.parent); } @@ -6156,7 +7560,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if ( symbol.flags & SymbolFlags.Alias && isInJSFile(declaration) && declaration.parent?.parent // exported import-like top-level JS require statement && isVariableDeclaration(declaration.parent.parent) - && declaration.parent.parent.parent?.parent && isVariableStatement(declaration.parent.parent.parent.parent) + && declaration.parent.parent.parent?.parent + && isVariableStatement(declaration.parent.parent.parent.parent) && !hasSyntacticModifier(declaration.parent.parent.parent.parent, ModifierFlags.Export) && declaration.parent.parent.parent.parent.parent // check if the thing containing the variable statement is visible (ie, the file) && isDeclarationVisible(declaration.parent.parent.parent.parent.parent) @@ -6194,20 +7599,23 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } - function isEntityNameVisible(entityName: EntityNameOrEntityNameExpression, enclosingDeclaration: Node): SymbolVisibilityResult { + function isEntityNameVisible( + entityName: EntityNameOrEntityNameExpression, + enclosingDeclaration: Node, + ): SymbolVisibilityResult { // get symbol of the first identifier of the entityName let meaning: SymbolFlags; if ( - entityName.parent.kind === SyntaxKind.TypeQuery || - entityName.parent.kind === SyntaxKind.ExpressionWithTypeArguments && !isPartOfTypeNode(entityName.parent) || - entityName.parent.kind === SyntaxKind.ComputedPropertyName + entityName.parent.kind === SyntaxKind.TypeQuery + || entityName.parent.kind === SyntaxKind.ExpressionWithTypeArguments && !isPartOfTypeNode(entityName.parent) + || entityName.parent.kind === SyntaxKind.ComputedPropertyName ) { // Typeof value meaning = SymbolFlags.Value | SymbolFlags.ExportValue; } else if ( - entityName.kind === SyntaxKind.QualifiedName || entityName.kind === SyntaxKind.PropertyAccessExpression || - entityName.parent.kind === SyntaxKind.ImportEqualsDeclaration + entityName.kind === SyntaxKind.QualifiedName || entityName.kind === SyntaxKind.PropertyAccessExpression + || entityName.parent.kind === SyntaxKind.ImportEqualsDeclaration ) { // Left identifier from type reference or TypeAlias // Entity name of the import declaration @@ -6219,11 +7627,32 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } const firstIdentifier = getFirstIdentifier(entityName); - const symbol = resolveName(enclosingDeclaration, firstIdentifier.escapedText, meaning, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ false); + const symbol = resolveName( + enclosingDeclaration, + firstIdentifier.escapedText, + meaning, + /*nameNotFoundMessage*/ undefined, + /*nameArg*/ undefined, + /*isUse*/ false, + ); if (symbol && symbol.flags & SymbolFlags.TypeParameter && meaning & SymbolFlags.Type) { return { accessibility: SymbolAccessibility.Accessible }; } - if (!symbol && isThisIdentifier(firstIdentifier) && isSymbolAccessible(getSymbolOfDeclaration(getThisContainer(firstIdentifier, /*includeArrowFunctions*/ false, /*includeClassComputedPropertyName*/ false)), firstIdentifier, meaning, /*shouldComputeAliasesToMakeVisible*/ false).accessibility === SymbolAccessibility.Accessible) { + if ( + !symbol && isThisIdentifier(firstIdentifier) + && isSymbolAccessible( + getSymbolOfDeclaration( + getThisContainer( + firstIdentifier, + /*includeArrowFunctions*/ false, + /*includeClassComputedPropertyName*/ false, + ), + ), + firstIdentifier, + meaning, + /*shouldComputeAliasesToMakeVisible*/ false, + ).accessibility === SymbolAccessibility.Accessible + ) { return { accessibility: SymbolAccessibility.Accessible }; } @@ -6235,7 +7664,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { }; } - function symbolToString(symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags, flags: SymbolFormatFlags = SymbolFormatFlags.AllowAnyNodeKind, writer?: EmitTextWriter): string { + function symbolToString( + symbol: Symbol, + enclosingDeclaration?: Node, + meaning?: SymbolFlags, + flags: SymbolFormatFlags = SymbolFormatFlags.AllowAnyNodeKind, + writer?: EmitTextWriter, + ): string { let nodeFlags = NodeBuilderFlags.IgnoreErrors; if (flags & SymbolFormatFlags.UseOnlyExternalAliasing) { nodeFlags |= NodeBuilderFlags.UseOnlyExternalAliasing; @@ -6252,7 +7687,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (flags & SymbolFormatFlags.WriteComputedProps) { nodeFlags |= NodeBuilderFlags.WriteComputedProps; } - const builder = flags & SymbolFormatFlags.AllowAnyNodeKind ? nodeBuilder.symbolToNode : nodeBuilder.symbolToEntityName; + const builder = flags & SymbolFormatFlags.AllowAnyNodeKind ? nodeBuilder.symbolToNode + : nodeBuilder.symbolToEntityName; return writer ? symbolToStringWorker(writer).getText() : usingSingleLineStringWriter(symbolToStringWorker); function symbolToStringWorker(writer: EmitTextWriter) { @@ -6267,8 +7703,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } - function signatureToString(signature: Signature, enclosingDeclaration?: Node, flags = TypeFormatFlags.None, kind?: SignatureKind, writer?: EmitTextWriter): string { - return writer ? signatureToStringWorker(writer).getText() : usingSingleLineStringWriter(signatureToStringWorker); + function signatureToString( + signature: Signature, + enclosingDeclaration?: Node, + flags = TypeFormatFlags.None, + kind?: SignatureKind, + writer?: EmitTextWriter, + ): string { + return writer ? signatureToStringWorker(writer).getText() + : usingSingleLineStringWriter(signatureToStringWorker); function signatureToStringWorker(writer: EmitTextWriter) { let sigOutput: SyntaxKind; @@ -6278,17 +7721,39 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { else { sigOutput = kind === SignatureKind.Construct ? SyntaxKind.ConstructSignature : SyntaxKind.CallSignature; } - const sig = nodeBuilder.signatureToSignatureDeclaration(signature, sigOutput, enclosingDeclaration, toNodeBuilderFlags(flags) | NodeBuilderFlags.IgnoreErrors | NodeBuilderFlags.WriteTypeParametersInQualifiedName); + const sig = nodeBuilder.signatureToSignatureDeclaration( + signature, + sigOutput, + enclosingDeclaration, + toNodeBuilderFlags(flags) | NodeBuilderFlags.IgnoreErrors + | NodeBuilderFlags.WriteTypeParametersInQualifiedName, + ); const printer = createPrinterWithRemoveCommentsOmitTrailingSemicolon(); const sourceFile = enclosingDeclaration && getSourceFileOfNode(enclosingDeclaration); - printer.writeNode(EmitHint.Unspecified, sig!, /*sourceFile*/ sourceFile, getTrailingSemicolonDeferringWriter(writer)); // TODO: GH#18217 + printer.writeNode( + EmitHint.Unspecified, + sig!, + /*sourceFile*/ sourceFile, + getTrailingSemicolonDeferringWriter(writer), + ); // TODO: GH#18217 return writer; } } - function typeToString(type: Type, enclosingDeclaration?: Node, flags: TypeFormatFlags = TypeFormatFlags.AllowUniqueESSymbolType | TypeFormatFlags.UseAliasDefinedOutsideCurrentScope, writer: EmitTextWriter = createTextWriter("")): string { + function typeToString( + type: Type, + enclosingDeclaration?: Node, + flags: TypeFormatFlags = TypeFormatFlags.AllowUniqueESSymbolType + | TypeFormatFlags.UseAliasDefinedOutsideCurrentScope, + writer: EmitTextWriter = createTextWriter(""), + ): string { const noTruncation = compilerOptions.noErrorTruncation || flags & TypeFormatFlags.NoTruncation; - const typeNode = nodeBuilder.typeToTypeNode(type, enclosingDeclaration, toNodeBuilderFlags(flags) | NodeBuilderFlags.IgnoreErrors | (noTruncation ? NodeBuilderFlags.NoTruncation : 0)); + const typeNode = nodeBuilder.typeToTypeNode( + type, + enclosingDeclaration, + toNodeBuilderFlags(flags) | NodeBuilderFlags.IgnoreErrors + | (noTruncation ? NodeBuilderFlags.NoTruncation : 0), + ); if (typeNode === undefined) return Debug.fail("should always get typenode"); // The unresolved type gets a synthesized comment on `any` to hint to users that it's not a plain `any`. // Otherwise, we always strip comments out. @@ -6305,8 +7770,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function getTypeNamesForErrorDisplay(left: Type, right: Type): [string, string] { - let leftStr = symbolValueDeclarationIsContextSensitive(left.symbol) ? typeToString(left, left.symbol.valueDeclaration) : typeToString(left); - let rightStr = symbolValueDeclarationIsContextSensitive(right.symbol) ? typeToString(right, right.symbol.valueDeclaration) : typeToString(right); + let leftStr = symbolValueDeclarationIsContextSensitive(left.symbol) + ? typeToString(left, left.symbol.valueDeclaration) : typeToString(left); + let rightStr = symbolValueDeclarationIsContextSensitive(right.symbol) + ? typeToString(right, right.symbol.valueDeclaration) : typeToString(right); if (leftStr === rightStr) { leftStr = getTypeNameForErrorDisplay(left); rightStr = getTypeNameForErrorDisplay(right); @@ -6319,7 +7786,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function symbolValueDeclarationIsContextSensitive(symbol: Symbol): boolean { - return symbol && !!symbol.valueDeclaration && isExpression(symbol.valueDeclaration) && !isContextSensitive(symbol.valueDeclaration); + return symbol && !!symbol.valueDeclaration && isExpression(symbol.valueDeclaration) + && !isContextSensitive(symbol.valueDeclaration); } function toNodeBuilderFlags(flags = TypeFormatFlags.None): NodeBuilderFlags { @@ -6327,21 +7795,118 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function isClassInstanceSide(type: Type) { - return !!type.symbol && !!(type.symbol.flags & SymbolFlags.Class) && (type === getDeclaredTypeOfClassOrInterface(type.symbol) || (!!(type.flags & TypeFlags.Object) && !!(getObjectFlags(type) & ObjectFlags.IsClassInstanceClone))); + return !!type.symbol && !!(type.symbol.flags & SymbolFlags.Class) + && (type === getDeclaredTypeOfClassOrInterface(type.symbol) + || (!!(type.flags & TypeFlags.Object) && !!(getObjectFlags(type) & ObjectFlags.IsClassInstanceClone))); } function createNodeBuilder() { return { - typeToTypeNode: (type: Type, enclosingDeclaration?: Node, flags?: NodeBuilderFlags, tracker?: SymbolTracker) => withContext(enclosingDeclaration, flags, tracker, context => typeToTypeNodeHelper(type, context)), - indexInfoToIndexSignatureDeclaration: (indexInfo: IndexInfo, enclosingDeclaration?: Node, flags?: NodeBuilderFlags, tracker?: SymbolTracker) => withContext(enclosingDeclaration, flags, tracker, context => indexInfoToIndexSignatureDeclarationHelper(indexInfo, context, /*typeNode*/ undefined)), - signatureToSignatureDeclaration: (signature: Signature, kind: SignatureDeclaration["kind"], enclosingDeclaration?: Node, flags?: NodeBuilderFlags, tracker?: SymbolTracker) => withContext(enclosingDeclaration, flags, tracker, context => signatureToSignatureDeclarationHelper(signature, kind, context)), - symbolToEntityName: (symbol: Symbol, meaning: SymbolFlags, enclosingDeclaration?: Node, flags?: NodeBuilderFlags, tracker?: SymbolTracker) => withContext(enclosingDeclaration, flags, tracker, context => symbolToName(symbol, context, meaning, /*expectsIdentifier*/ false)), - symbolToExpression: (symbol: Symbol, meaning: SymbolFlags, enclosingDeclaration?: Node, flags?: NodeBuilderFlags, tracker?: SymbolTracker) => withContext(enclosingDeclaration, flags, tracker, context => symbolToExpression(symbol, context, meaning)), - symbolToTypeParameterDeclarations: (symbol: Symbol, enclosingDeclaration?: Node, flags?: NodeBuilderFlags, tracker?: SymbolTracker) => withContext(enclosingDeclaration, flags, tracker, context => typeParametersToTypeParameterDeclarations(symbol, context)), - symbolToParameterDeclaration: (symbol: Symbol, enclosingDeclaration?: Node, flags?: NodeBuilderFlags, tracker?: SymbolTracker) => withContext(enclosingDeclaration, flags, tracker, context => symbolToParameterDeclaration(symbol, context)), - typeParameterToDeclaration: (parameter: TypeParameter, enclosingDeclaration?: Node, flags?: NodeBuilderFlags, tracker?: SymbolTracker) => withContext(enclosingDeclaration, flags, tracker, context => typeParameterToDeclaration(parameter, context)), - symbolTableToDeclarationStatements: (symbolTable: SymbolTable, enclosingDeclaration?: Node, flags?: NodeBuilderFlags, tracker?: SymbolTracker, bundled?: boolean) => withContext(enclosingDeclaration, flags, tracker, context => symbolTableToDeclarationStatements(symbolTable, context, bundled)), - symbolToNode: (symbol: Symbol, meaning: SymbolFlags, enclosingDeclaration?: Node, flags?: NodeBuilderFlags, tracker?: SymbolTracker) => withContext(enclosingDeclaration, flags, tracker, context => symbolToNode(symbol, context, meaning)), + typeToTypeNode: ( + type: Type, + enclosingDeclaration?: Node, + flags?: NodeBuilderFlags, + tracker?: SymbolTracker, + ) => withContext(enclosingDeclaration, flags, tracker, context => typeToTypeNodeHelper(type, context)), + indexInfoToIndexSignatureDeclaration: ( + indexInfo: IndexInfo, + enclosingDeclaration?: Node, + flags?: NodeBuilderFlags, + tracker?: SymbolTracker, + ) => withContext( + enclosingDeclaration, + flags, + tracker, + context => indexInfoToIndexSignatureDeclarationHelper(indexInfo, context, /*typeNode*/ undefined), + ), + signatureToSignatureDeclaration: ( + signature: Signature, + kind: SignatureDeclaration["kind"], + enclosingDeclaration?: Node, + flags?: NodeBuilderFlags, + tracker?: SymbolTracker, + ) => withContext( + enclosingDeclaration, + flags, + tracker, + context => signatureToSignatureDeclarationHelper(signature, kind, context), + ), + symbolToEntityName: ( + symbol: Symbol, + meaning: SymbolFlags, + enclosingDeclaration?: Node, + flags?: NodeBuilderFlags, + tracker?: SymbolTracker, + ) => withContext( + enclosingDeclaration, + flags, + tracker, + context => symbolToName(symbol, context, meaning, /*expectsIdentifier*/ false), + ), + symbolToExpression: ( + symbol: Symbol, + meaning: SymbolFlags, + enclosingDeclaration?: Node, + flags?: NodeBuilderFlags, + tracker?: SymbolTracker, + ) => withContext( + enclosingDeclaration, + flags, + tracker, + context => symbolToExpression(symbol, context, meaning), + ), + symbolToTypeParameterDeclarations: ( + symbol: Symbol, + enclosingDeclaration?: Node, + flags?: NodeBuilderFlags, + tracker?: SymbolTracker, + ) => withContext( + enclosingDeclaration, + flags, + tracker, + context => typeParametersToTypeParameterDeclarations(symbol, context), + ), + symbolToParameterDeclaration: ( + symbol: Symbol, + enclosingDeclaration?: Node, + flags?: NodeBuilderFlags, + tracker?: SymbolTracker, + ) => withContext( + enclosingDeclaration, + flags, + tracker, + context => symbolToParameterDeclaration(symbol, context), + ), + typeParameterToDeclaration: ( + parameter: TypeParameter, + enclosingDeclaration?: Node, + flags?: NodeBuilderFlags, + tracker?: SymbolTracker, + ) => withContext( + enclosingDeclaration, + flags, + tracker, + context => typeParameterToDeclaration(parameter, context), + ), + symbolTableToDeclarationStatements: ( + symbolTable: SymbolTable, + enclosingDeclaration?: Node, + flags?: NodeBuilderFlags, + tracker?: SymbolTracker, + bundled?: boolean, + ) => withContext( + enclosingDeclaration, + flags, + tracker, + context => symbolTableToDeclarationStatements(symbolTable, context, bundled), + ), + symbolToNode: ( + symbol: Symbol, + meaning: SymbolFlags, + enclosingDeclaration?: Node, + flags?: NodeBuilderFlags, + tracker?: SymbolTracker, + ) => withContext(enclosingDeclaration, flags, tracker, context => symbolToNode(symbol, context, meaning)), }; function symbolToNode(symbol: Symbol, context: NodeBuilderContext, meaning: SymbolFlags) { @@ -6359,11 +7924,19 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return symbolToExpression(symbol, context, meaning); } - function withContext(enclosingDeclaration: Node | undefined, flags: NodeBuilderFlags | undefined, tracker: SymbolTracker | undefined, cb: (context: NodeBuilderContext) => T): T | undefined { - Debug.assert(enclosingDeclaration === undefined || (enclosingDeclaration.flags & NodeFlags.Synthesized) === 0); - const moduleResolverHost = tracker?.trackSymbol ? tracker.moduleResolverHost : - flags! & NodeBuilderFlags.DoNotIncludeSymbolChain ? createBasicNodeBuilderModuleSpecifierResolutionHost(host) : - undefined; + function withContext( + enclosingDeclaration: Node | undefined, + flags: NodeBuilderFlags | undefined, + tracker: SymbolTracker | undefined, + cb: (context: NodeBuilderContext) => T, + ): T | undefined { + Debug.assert( + enclosingDeclaration === undefined || (enclosingDeclaration.flags & NodeFlags.Synthesized) === 0, + ); + const moduleResolverHost = tracker?.trackSymbol ? tracker.moduleResolverHost + : flags! & NodeBuilderFlags.DoNotIncludeSymbolChain + ? createBasicNodeBuilderModuleSpecifierResolutionHost(host) + : undefined; const context: NodeBuilderContext = { enclosingDeclaration, flags: flags || NodeBuilderFlags.None, @@ -6385,7 +7958,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function checkTruncationLength(context: NodeBuilderContext): boolean { if (context.truncating) return context.truncating; - return context.truncating = context.approximateLength > ((context.flags & NodeBuilderFlags.NoTruncation) ? noTruncationMaximumTruncationLength : defaultMaximumTruncationLength); + return context.truncating = context.approximateLength + > ((context.flags & NodeBuilderFlags.NoTruncation) ? noTruncationMaximumTruncationLength + : defaultMaximumTruncationLength); } function typeToTypeNodeHelper(type: Type, context: NodeBuilderContext): TypeNode { @@ -6417,13 +7992,22 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (type.flags & TypeFlags.Any) { if (type.aliasSymbol) { - return factory.createTypeReferenceNode(symbolToEntityNameNode(type.aliasSymbol), mapToTypeNodes(type.aliasTypeArguments, context)); + return factory.createTypeReferenceNode( + symbolToEntityNameNode(type.aliasSymbol), + mapToTypeNodes(type.aliasTypeArguments, context), + ); } if (type === unresolvedType) { - return addSyntheticLeadingComment(factory.createKeywordTypeNode(SyntaxKind.AnyKeyword), SyntaxKind.MultiLineCommentTrivia, "unresolved"); + return addSyntheticLeadingComment( + factory.createKeywordTypeNode(SyntaxKind.AnyKeyword), + SyntaxKind.MultiLineCommentTrivia, + "unresolved", + ); } context.approximateLength += 3; - return factory.createKeywordTypeNode(type === intrinsicMarkerType ? SyntaxKind.IntrinsicKeyword : SyntaxKind.AnyKeyword); + return factory.createKeywordTypeNode( + type === intrinsicMarkerType ? SyntaxKind.IntrinsicKeyword : SyntaxKind.AnyKeyword, + ); } if (type.flags & TypeFlags.Unknown) { return factory.createKeywordTypeNode(SyntaxKind.UnknownKeyword); @@ -6460,10 +8044,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } if (isImportTypeNode(parentName)) { (parentName as any).isTypeOf = true; // mutably update, node is freshly manufactured anyhow - return factory.createIndexedAccessTypeNode(parentName, factory.createLiteralTypeNode(factory.createStringLiteral(memberName))); + return factory.createIndexedAccessTypeNode( + parentName, + factory.createLiteralTypeNode(factory.createStringLiteral(memberName)), + ); } else if (isTypeReferenceNode(parentName)) { - return factory.createIndexedAccessTypeNode(factory.createTypeQueryNode(parentName.typeName), factory.createLiteralTypeNode(factory.createStringLiteral(memberName))); + return factory.createIndexedAccessTypeNode( + factory.createTypeQueryNode(parentName.typeName), + factory.createLiteralTypeNode(factory.createStringLiteral(memberName)), + ); } else { return Debug.fail("Unhandled type node kind returned from `symbolToTypeNode`."); @@ -6473,12 +8063,26 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } if (type.flags & TypeFlags.StringLiteral) { context.approximateLength += (type as StringLiteralType).value.length + 2; - return factory.createLiteralTypeNode(setEmitFlags(factory.createStringLiteral((type as StringLiteralType).value, !!(context.flags & NodeBuilderFlags.UseSingleQuotesForStringLiteralType)), EmitFlags.NoAsciiEscaping)); + return factory.createLiteralTypeNode( + setEmitFlags( + factory.createStringLiteral( + (type as StringLiteralType).value, + !!(context.flags & NodeBuilderFlags.UseSingleQuotesForStringLiteralType), + ), + EmitFlags.NoAsciiEscaping, + ), + ); } if (type.flags & TypeFlags.NumberLiteral) { const value = (type as NumberLiteralType).value; context.approximateLength += ("" + value).length; - return factory.createLiteralTypeNode(value < 0 ? factory.createPrefixUnaryExpression(SyntaxKind.MinusToken, factory.createNumericLiteral(-value)) : factory.createNumericLiteral(value)); + return factory.createLiteralTypeNode( + value < 0 + ? factory.createPrefixUnaryExpression( + SyntaxKind.MinusToken, + factory.createNumericLiteral(-value), + ) : factory.createNumericLiteral(value), + ); } if (type.flags & TypeFlags.BigIntLiteral) { context.approximateLength += (pseudoBigIntToString((type as BigIntLiteralType).value).length) + 1; @@ -6486,7 +8090,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } if (type.flags & TypeFlags.BooleanLiteral) { context.approximateLength += (type as IntrinsicType).intrinsicName.length; - return factory.createLiteralTypeNode((type as IntrinsicType).intrinsicName === "true" ? factory.createTrue() : factory.createFalse()); + return factory.createLiteralTypeNode( + (type as IntrinsicType).intrinsicName === "true" ? factory.createTrue() : factory.createFalse(), + ); } if (type.flags & TypeFlags.UniqueESSymbol) { if (!(context.flags & NodeBuilderFlags.AllowUniqueESSymbolType)) { @@ -6499,7 +8105,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } context.approximateLength += 13; - return factory.createTypeOperatorNode(SyntaxKind.UniqueKeyword, factory.createKeywordTypeNode(SyntaxKind.SymbolKeyword)); + return factory.createTypeOperatorNode( + SyntaxKind.UniqueKeyword, + factory.createKeywordTypeNode(SyntaxKind.SymbolKeyword), + ); } if (type.flags & TypeFlags.Void) { context.approximateLength += 4; @@ -6536,9 +8145,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return factory.createThisTypeNode(); } - if (!inTypeAlias && type.aliasSymbol && (context.flags & NodeBuilderFlags.UseAliasDefinedOutsideCurrentScope || isTypeSymbolAccessible(type.aliasSymbol, context.enclosingDeclaration))) { + if ( + !inTypeAlias && type.aliasSymbol + && (context.flags & NodeBuilderFlags.UseAliasDefinedOutsideCurrentScope + || isTypeSymbolAccessible(type.aliasSymbol, context.enclosingDeclaration)) + ) { const typeArgumentNodes = mapToTypeNodes(type.aliasTypeArguments, context); - if (isReservedMemberName(type.aliasSymbol.escapedName) && !(type.aliasSymbol.flags & SymbolFlags.Class)) return factory.createTypeReferenceNode(factory.createIdentifier(""), typeArgumentNodes); + if ( + isReservedMemberName(type.aliasSymbol.escapedName) && !(type.aliasSymbol.flags & SymbolFlags.Class) + ) return factory.createTypeReferenceNode(factory.createIdentifier(""), typeArgumentNodes); if (length(typeArgumentNodes) === 1 && type.aliasSymbol === globalArrayType.symbol) { return factory.createArrayTypeNode(typeArgumentNodes![0]); } @@ -6549,7 +8164,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (objectFlags & ObjectFlags.Reference) { Debug.assert(!!(type.flags & TypeFlags.Object)); - return (type as TypeReference).node ? visitAndTransformType(type as TypeReference, typeReferenceToTypeNode) : typeReferenceToTypeNode(type as TypeReference); + return (type as TypeReference).node + ? visitAndTransformType(type as TypeReference, typeReferenceToTypeNode) + : typeReferenceToTypeNode(type as TypeReference); } if (type.flags & TypeFlags.TypeParameter || objectFlags & ObjectFlags.ClassOrInterface) { if (type.flags & TypeFlags.TypeParameter && contains(context.inferTypeParameters, type)) { @@ -6561,45 +8178,60 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // we would have normally inferred based on context, we emit the constraint // using `infer T extends ?`. We omit inferred constraints from type references // as they may be elided. - const inferredConstraint = getInferredTypeParameterConstraint(type as TypeParameter, /*omitTypeReferences*/ true); + const inferredConstraint = getInferredTypeParameterConstraint( + type as TypeParameter, + /*omitTypeReferences*/ true, + ); if (!(inferredConstraint && isTypeIdenticalTo(constraint, inferredConstraint))) { context.approximateLength += 9; constraintNode = constraint && typeToTypeNodeHelper(constraint, context); } } - return factory.createInferTypeNode(typeParameterToDeclarationWithConstraint(type as TypeParameter, context, constraintNode)); + return factory.createInferTypeNode( + typeParameterToDeclarationWithConstraint(type as TypeParameter, context, constraintNode), + ); } if ( - context.flags & NodeBuilderFlags.GenerateNamesForShadowedTypeParams && - type.flags & TypeFlags.TypeParameter && - !isTypeSymbolAccessible(type.symbol, context.enclosingDeclaration) + context.flags & NodeBuilderFlags.GenerateNamesForShadowedTypeParams + && type.flags & TypeFlags.TypeParameter + && !isTypeSymbolAccessible(type.symbol, context.enclosingDeclaration) ) { const name = typeParameterToName(type, context); context.approximateLength += idText(name).length; - return factory.createTypeReferenceNode(factory.createIdentifier(idText(name)), /*typeArguments*/ undefined); + return factory.createTypeReferenceNode( + factory.createIdentifier(idText(name)), + /*typeArguments*/ undefined, + ); } // Ignore constraint/default when creating a usage (as opposed to declaration) of a type parameter. if (type.symbol) { return symbolToTypeNode(type.symbol, context, SymbolFlags.Type); } - const name = (type === markerSuperTypeForCheck || type === markerSubTypeForCheck) && varianceTypeParameter && varianceTypeParameter.symbol ? - (type === markerSubTypeForCheck ? "sub-" : "super-") + symbolName(varianceTypeParameter.symbol) : "?"; + const name = + (type === markerSuperTypeForCheck || type === markerSubTypeForCheck) && varianceTypeParameter + && varianceTypeParameter.symbol + ? (type === markerSubTypeForCheck ? "sub-" : "super-") + + symbolName(varianceTypeParameter.symbol) : "?"; return factory.createTypeReferenceNode(factory.createIdentifier(name), /*typeArguments*/ undefined); } if (type.flags & TypeFlags.Union && (type as UnionType).origin) { type = (type as UnionType).origin!; } if (type.flags & (TypeFlags.Union | TypeFlags.Intersection)) { - const types = type.flags & TypeFlags.Union ? formatUnionTypes((type as UnionType).types) : (type as IntersectionType).types; + const types = type.flags & TypeFlags.Union ? formatUnionTypes((type as UnionType).types) + : (type as IntersectionType).types; if (length(types) === 1) { return typeToTypeNodeHelper(types[0], context); } const typeNodes = mapToTypeNodes(types, context, /*isBareList*/ true); if (typeNodes && typeNodes.length > 0) { - return type.flags & TypeFlags.Union ? factory.createUnionTypeNode(typeNodes) : factory.createIntersectionTypeNode(typeNodes); + return type.flags & TypeFlags.Union ? factory.createUnionTypeNode(typeNodes) + : factory.createIntersectionTypeNode(typeNodes); } else { - if (!context.encounteredError && !(context.flags & NodeBuilderFlags.AllowEmptyUnionOrIntersection)) { + if ( + !context.encounteredError && !(context.flags & NodeBuilderFlags.AllowEmptyUnionOrIntersection) + ) { context.encounteredError = true; } return undefined!; // TODO: GH#18217 @@ -6624,7 +8256,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { map(types, (t, i) => factory.createTemplateLiteralTypeSpan( typeToTypeNodeHelper(t, context), - (i < types.length - 1 ? factory.createTemplateMiddle : factory.createTemplateTail)(texts[i + 1]), + (i < types.length - 1 ? factory.createTemplateMiddle : factory.createTemplateTail)( + texts[i + 1], + ), )), ); context.approximateLength += 2; @@ -6652,7 +8286,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function conditionalTypeToTypeNode(type: ConditionalType) { const checkTypeNode = typeToTypeNodeHelper(type.checkType, context); context.approximateLength += 15; - if (context.flags & NodeBuilderFlags.GenerateNamesForShadowedTypeParams && type.root.isDistributive && !(type.checkType.flags & TypeFlags.TypeParameter)) { + if ( + context.flags & NodeBuilderFlags.GenerateNamesForShadowedTypeParams && type.root.isDistributive + && !(type.checkType.flags & TypeFlags.TypeParameter) + ) { const newParam = createTypeParameter(createSymbol(SymbolFlags.TypeParameter, "T" as __String)); const name = typeParameterToName(newParam, context); const newTypeVariable = factory.createTypeReferenceNode(name); @@ -6660,10 +8297,17 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const newMapper = prependTypeMapping(type.root.checkType, newParam, type.mapper); const saveInferTypeParameters = context.inferTypeParameters; context.inferTypeParameters = type.root.inferTypeParameters; - const extendsTypeNode = typeToTypeNodeHelper(instantiateType(type.root.extendsType, newMapper), context); + const extendsTypeNode = typeToTypeNodeHelper( + instantiateType(type.root.extendsType, newMapper), + context, + ); context.inferTypeParameters = saveInferTypeParameters; - const trueTypeNode = typeToTypeNodeOrCircularityElision(instantiateType(getTypeFromTypeNode(type.root.node.trueType), newMapper)); - const falseTypeNode = typeToTypeNodeOrCircularityElision(instantiateType(getTypeFromTypeNode(type.root.node.falseType), newMapper)); + const trueTypeNode = typeToTypeNodeOrCircularityElision( + instantiateType(getTypeFromTypeNode(type.root.node.trueType), newMapper), + ); + const falseTypeNode = typeToTypeNodeOrCircularityElision( + instantiateType(getTypeFromTypeNode(type.root.node.falseType), newMapper), + ); // outermost conditional makes `T` a type parameter, allowing the inner conditionals to be distributive // second conditional makes `T` have `T & checkType` substitution, so it is correctly usable as the checkType @@ -6677,11 +8321,21 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // may also work with `infer ... extends ...` in, but would produce declarations only compatible with the latest TS. return factory.createConditionalTypeNode( checkTypeNode, - factory.createInferTypeNode(factory.createTypeParameterDeclaration(/*modifiers*/ undefined, factory.cloneNode(newTypeVariable.typeName) as Identifier)), + factory.createInferTypeNode( + factory.createTypeParameterDeclaration( + /*modifiers*/ undefined, + factory.cloneNode(newTypeVariable.typeName) as Identifier, + ), + ), factory.createConditionalTypeNode( factory.createTypeReferenceNode(factory.cloneNode(name)), typeToTypeNodeHelper(type.checkType, context), - factory.createConditionalTypeNode(newTypeVariable, extendsTypeNode, trueTypeNode, falseTypeNode), + factory.createConditionalTypeNode( + newTypeVariable, + extendsTypeNode, + trueTypeNode, + falseTypeNode, + ), factory.createKeywordTypeNode(SyntaxKind.NeverKeyword), ), factory.createKeywordTypeNode(SyntaxKind.NeverKeyword), @@ -6715,29 +8369,44 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function isHomomorphicMappedTypeWithNonHomomorphicInstantiation(type: MappedType) { - return !!type.target && isMappedTypeHomomorphic(type.target as MappedType) && !isMappedTypeHomomorphic(type); + return !!type.target && isMappedTypeHomomorphic(type.target as MappedType) + && !isMappedTypeHomomorphic(type); } function createMappedTypeNodeFromType(type: MappedType) { Debug.assert(!!(type.flags & TypeFlags.Object)); - const readonlyToken = type.declaration.readonlyToken ? factory.createToken(type.declaration.readonlyToken.kind) as ReadonlyKeyword | PlusToken | MinusToken : undefined; - const questionToken = type.declaration.questionToken ? factory.createToken(type.declaration.questionToken.kind) as QuestionToken | PlusToken | MinusToken : undefined; + const readonlyToken = type.declaration.readonlyToken + ? factory.createToken(type.declaration.readonlyToken.kind) as + | ReadonlyKeyword + | PlusToken + | MinusToken : undefined; + const questionToken = type.declaration.questionToken + ? factory.createToken(type.declaration.questionToken.kind) as QuestionToken | PlusToken | MinusToken + : undefined; let appropriateConstraintTypeNode: TypeNode; let newTypeVariable: TypeReferenceNode | undefined; // If the mapped type isn't `keyof` constraint-declared, _but_ still has modifiers preserved, and its naive instantiation won't preserve modifiers because its constraint isn't `keyof` constrained, we have work to do const needsModifierPreservingWrapper = !isMappedTypeWithKeyofConstraintDeclaration(type) && !(getModifiersTypeFromMappedType(type).flags & TypeFlags.Unknown) && context.flags & NodeBuilderFlags.GenerateNamesForShadowedTypeParams - && !(getConstraintTypeFromMappedType(type).flags & TypeFlags.TypeParameter && getConstraintOfTypeParameter(getConstraintTypeFromMappedType(type))?.flags! & TypeFlags.Index); + && !(getConstraintTypeFromMappedType(type).flags & TypeFlags.TypeParameter + && getConstraintOfTypeParameter(getConstraintTypeFromMappedType(type))?.flags! + & TypeFlags.Index); if (isMappedTypeWithKeyofConstraintDeclaration(type)) { // We have a { [P in keyof T]: X } // We do this to ensure we retain the toplevel keyof-ness of the type which may be lost due to keyof distribution during `getConstraintTypeFromMappedType` - if (isHomomorphicMappedTypeWithNonHomomorphicInstantiation(type) && context.flags & NodeBuilderFlags.GenerateNamesForShadowedTypeParams) { + if ( + isHomomorphicMappedTypeWithNonHomomorphicInstantiation(type) + && context.flags & NodeBuilderFlags.GenerateNamesForShadowedTypeParams + ) { const newParam = createTypeParameter(createSymbol(SymbolFlags.TypeParameter, "T" as __String)); const name = typeParameterToName(newParam, context); newTypeVariable = factory.createTypeReferenceNode(name); } - appropriateConstraintTypeNode = factory.createTypeOperatorNode(SyntaxKind.KeyOfKeyword, newTypeVariable || typeToTypeNodeHelper(getModifiersTypeFromMappedType(type), context)); + appropriateConstraintTypeNode = factory.createTypeOperatorNode( + SyntaxKind.KeyOfKeyword, + newTypeVariable || typeToTypeNodeHelper(getModifiersTypeFromMappedType(type), context), + ); } else if (needsModifierPreservingWrapper) { // So, step 1: new type variable @@ -6748,22 +8417,60 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { appropriateConstraintTypeNode = newTypeVariable; } else { - appropriateConstraintTypeNode = typeToTypeNodeHelper(getConstraintTypeFromMappedType(type), context); + appropriateConstraintTypeNode = typeToTypeNodeHelper( + getConstraintTypeFromMappedType(type), + context, + ); } - const typeParameterNode = typeParameterToDeclarationWithConstraint(getTypeParameterFromMappedType(type), context, appropriateConstraintTypeNode); - const nameTypeNode = type.declaration.nameType ? typeToTypeNodeHelper(getNameTypeFromMappedType(type)!, context) : undefined; - const templateTypeNode = typeToTypeNodeHelper(removeMissingType(getTemplateTypeFromMappedType(type), !!(getMappedTypeModifiers(type) & MappedTypeModifiers.IncludeOptional)), context); - const mappedTypeNode = factory.createMappedTypeNode(readonlyToken, typeParameterNode, nameTypeNode, questionToken, templateTypeNode, /*members*/ undefined); + const typeParameterNode = typeParameterToDeclarationWithConstraint( + getTypeParameterFromMappedType(type), + context, + appropriateConstraintTypeNode, + ); + const nameTypeNode = type.declaration.nameType + ? typeToTypeNodeHelper(getNameTypeFromMappedType(type)!, context) : undefined; + const templateTypeNode = typeToTypeNodeHelper( + removeMissingType( + getTemplateTypeFromMappedType(type), + !!(getMappedTypeModifiers(type) & MappedTypeModifiers.IncludeOptional), + ), + context, + ); + const mappedTypeNode = factory.createMappedTypeNode( + readonlyToken, + typeParameterNode, + nameTypeNode, + questionToken, + templateTypeNode, + /*members*/ undefined, + ); context.approximateLength += 10; const result = setEmitFlags(mappedTypeNode, EmitFlags.SingleLine); - if (isHomomorphicMappedTypeWithNonHomomorphicInstantiation(type) && context.flags & NodeBuilderFlags.GenerateNamesForShadowedTypeParams) { + if ( + isHomomorphicMappedTypeWithNonHomomorphicInstantiation(type) + && context.flags & NodeBuilderFlags.GenerateNamesForShadowedTypeParams + ) { // homomorphic mapped type with a non-homomorphic naive inlining // wrap it with a conditional like `SomeModifiersType extends infer U ? {..the mapped type...} : never` to ensure the resulting // type stays homomorphic - const originalConstraint = instantiateType(getConstraintOfTypeParameter(getTypeFromTypeNode((type.declaration.typeParameter.constraint! as TypeOperatorNode).type) as TypeParameter) || unknownType, type.mapper); + const originalConstraint = instantiateType( + getConstraintOfTypeParameter( + getTypeFromTypeNode( + (type.declaration.typeParameter.constraint! as TypeOperatorNode).type, + ) as TypeParameter, + ) || unknownType, + type.mapper, + ); return factory.createConditionalTypeNode( typeToTypeNodeHelper(getModifiersTypeFromMappedType(type), context), - factory.createInferTypeNode(factory.createTypeParameterDeclaration(/*modifiers*/ undefined, factory.cloneNode(newTypeVariable!.typeName) as Identifier, originalConstraint.flags & TypeFlags.Unknown ? undefined : typeToTypeNodeHelper(originalConstraint, context))), + factory.createInferTypeNode( + factory.createTypeParameterDeclaration( + /*modifiers*/ undefined, + factory.cloneNode(newTypeVariable!.typeName) as Identifier, + originalConstraint.flags & TypeFlags.Unknown ? undefined + : typeToTypeNodeHelper(originalConstraint, context), + ), + ), result, factory.createKeywordTypeNode(SyntaxKind.NeverKeyword), ); @@ -6775,7 +8482,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // just homomorphic ones. return factory.createConditionalTypeNode( typeToTypeNodeHelper(getConstraintTypeFromMappedType(type), context), - factory.createInferTypeNode(factory.createTypeParameterDeclaration(/*modifiers*/ undefined, factory.cloneNode(newTypeVariable!.typeName) as Identifier, factory.createTypeOperatorNode(SyntaxKind.KeyOfKeyword, typeToTypeNodeHelper(getModifiersTypeFromMappedType(type), context)))), + factory.createInferTypeNode( + factory.createTypeParameterDeclaration( + /*modifiers*/ undefined, + factory.cloneNode(newTypeVariable!.typeName) as Identifier, + factory.createTypeOperatorNode( + SyntaxKind.KeyOfKeyword, + typeToTypeNodeHelper(getModifiersTypeFromMappedType(type), context), + ), + ), + ), result, factory.createKeywordTypeNode(SyntaxKind.NeverKeyword), ); @@ -6796,9 +8512,17 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { else if ( symbol.flags & SymbolFlags.Class && !getBaseTypeVariableOfClass(symbol) - && !(symbol.valueDeclaration && isClassLike(symbol.valueDeclaration) && context.flags & NodeBuilderFlags.WriteClassExpressionAsTypeLiteral && (!isClassDeclaration(symbol.valueDeclaration) || isSymbolAccessible(symbol, context.enclosingDeclaration, isInstanceType, /*shouldComputeAliasesToMakeVisible*/ false).accessibility !== SymbolAccessibility.Accessible)) || - symbol.flags & (SymbolFlags.Enum | SymbolFlags.ValueModule) || - shouldWriteTypeOfFunctionSymbol() + && !(symbol.valueDeclaration && isClassLike(symbol.valueDeclaration) + && context.flags & NodeBuilderFlags.WriteClassExpressionAsTypeLiteral + && (!isClassDeclaration(symbol.valueDeclaration) + || isSymbolAccessible( + symbol, + context.enclosingDeclaration, + isInstanceType, + /*shouldComputeAliasesToMakeVisible*/ false, + ).accessibility !== SymbolAccessibility.Accessible)) + || symbol.flags & (SymbolFlags.Enum | SymbolFlags.ValueModule) + || shouldWriteTypeOfFunctionSymbol() ) { return symbolToTypeNode(symbol, context, isInstanceType); } @@ -6818,7 +8542,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } else { - const isInstantiationExpressionType = !!(getObjectFlags(type) & ObjectFlags.InstantiationExpressionType); + const isInstantiationExpressionType = + !!(getObjectFlags(type) & ObjectFlags.InstantiationExpressionType); if (isInstantiationExpressionType) { const instantiationExpressionType = type as InstantiationExpressionType; if (isTypeQueryNode(instantiationExpressionType.node)) { @@ -6836,26 +8561,35 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return createTypeNodeFromObjectType(type); } function shouldWriteTypeOfFunctionSymbol() { - const isStaticMethodSymbol = !!(symbol.flags & SymbolFlags.Method) && // typeof static method - some(symbol.declarations, declaration => isStatic(declaration)); - const isNonLocalFunctionSymbol = !!(symbol.flags & SymbolFlags.Function) && - (symbol.parent || // is exported function symbol - forEach(symbol.declarations, declaration => declaration.parent.kind === SyntaxKind.SourceFile || declaration.parent.kind === SyntaxKind.ModuleBlock)); + const isStaticMethodSymbol = !!(symbol.flags & SymbolFlags.Method) // typeof static method + && some(symbol.declarations, declaration => isStatic(declaration)); + const isNonLocalFunctionSymbol = !!(symbol.flags & SymbolFlags.Function) + && (symbol.parent // is exported function symbol + || forEach( + symbol.declarations, + declaration => + declaration.parent.kind === SyntaxKind.SourceFile + || declaration.parent.kind === SyntaxKind.ModuleBlock, + )); if (isStaticMethodSymbol || isNonLocalFunctionSymbol) { // typeof is allowed only for static/non local functions - return (!!(context.flags & NodeBuilderFlags.UseTypeOfFunction) || (context.visitedTypes?.has(typeId))) && // it is type of the symbol uses itself recursively - (!(context.flags & NodeBuilderFlags.UseStructuralFallback) || isValueSymbolAccessible(symbol, context.enclosingDeclaration)); // And the build is going to succeed without visibility error or there is no structural fallback allowed + return (!!(context.flags & NodeBuilderFlags.UseTypeOfFunction) + || (context.visitedTypes?.has(typeId))) // it is type of the symbol uses itself recursively + && (!(context.flags & NodeBuilderFlags.UseStructuralFallback) + || isValueSymbolAccessible(symbol, context.enclosingDeclaration)); // And the build is going to succeed without visibility error or there is no structural fallback allowed } } } function visitAndTransformType(type: T, transform: (type: T) => TypeNode) { const typeId = type.id; - const isConstructorObject = getObjectFlags(type) & ObjectFlags.Anonymous && type.symbol && type.symbol.flags & SymbolFlags.Class; - const id = getObjectFlags(type) & ObjectFlags.Reference && (type as TypeReference & T).node ? "N" + getNodeId((type as TypeReference & T).node!) : - type.flags & TypeFlags.Conditional ? "N" + getNodeId((type as ConditionalType & T).root.node) : - type.symbol ? (isConstructorObject ? "+" : "") + getSymbolId(type.symbol) : - undefined; + const isConstructorObject = getObjectFlags(type) & ObjectFlags.Anonymous && type.symbol + && type.symbol.flags & SymbolFlags.Class; + const id = getObjectFlags(type) & ObjectFlags.Reference && (type as TypeReference & T).node + ? "N" + getNodeId((type as TypeReference & T).node!) + : type.flags & TypeFlags.Conditional ? "N" + getNodeId((type as ConditionalType & T).root.node) + : type.symbol ? (isConstructorObject ? "+" : "") + getSymbolId(type.symbol) + : undefined; // Since instantiations of the same anonymous type have the same symbol, tracking symbols instead // of types allows us to catch circular references to instantiations of the same anonymous type if (!context.visitedTypes) { @@ -6904,7 +8638,17 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (!nodeIsSynthesized(node) && getParseTreeNode(node) === node) { return node; } - return setTextRange(factory.cloneNode(visitEachChild(node, deepCloneOrReuseNode, nullTransformationContext, deepCloneOrReuseNodes)), node); + return setTextRange( + factory.cloneNode( + visitEachChild( + node, + deepCloneOrReuseNode, + nullTransformationContext, + deepCloneOrReuseNodes, + ), + ), + node, + ); } function deepCloneOrReuseNodes( @@ -6917,7 +8661,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (nodes && nodes.length === 0) { // Ensure we explicitly make a copy of an empty array; visitNodes will not do this unless the array has elements, // which can lead to us reusing the same empty NodeArray more than once within the same AST during type noding. - return setTextRange(factory.createNodeArray(/*elements*/ undefined, nodes.hasTrailingComma), nodes); + return setTextRange( + factory.createNodeArray(/*elements*/ undefined, nodes.hasTrailingComma), + nodes, + ); } return visitNodes(nodes, visitor, test, start, count); } @@ -6937,29 +8684,40 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (resolved.callSignatures.length === 1 && !resolved.constructSignatures.length) { const signature = resolved.callSignatures[0]; - const signatureNode = signatureToSignatureDeclarationHelper(signature, SyntaxKind.FunctionType, context) as FunctionTypeNode; + const signatureNode = signatureToSignatureDeclarationHelper( + signature, + SyntaxKind.FunctionType, + context, + ) as FunctionTypeNode; return signatureNode; } if (resolved.constructSignatures.length === 1 && !resolved.callSignatures.length) { const signature = resolved.constructSignatures[0]; - const signatureNode = signatureToSignatureDeclarationHelper(signature, SyntaxKind.ConstructorType, context) as ConstructorTypeNode; + const signatureNode = signatureToSignatureDeclarationHelper( + signature, + SyntaxKind.ConstructorType, + context, + ) as ConstructorTypeNode; return signatureNode; } } - const abstractSignatures = filter(resolved.constructSignatures, signature => !!(signature.flags & SignatureFlags.Abstract)); + const abstractSignatures = filter( + resolved.constructSignatures, + signature => !!(signature.flags & SignatureFlags.Abstract), + ); if (some(abstractSignatures)) { const types = map(abstractSignatures, getOrCreateTypeFromSignature); // count the number of type elements excluding abstract constructors - const typeElementCount = resolved.callSignatures.length + - (resolved.constructSignatures.length - abstractSignatures.length) + - resolved.indexInfos.length + + const typeElementCount = resolved.callSignatures.length + + (resolved.constructSignatures.length - abstractSignatures.length) + + resolved.indexInfos.length // exclude `prototype` when writing a class expression as a type literal, as per // the logic in `createTypeNodesFromResolvedType`. - (context.flags & NodeBuilderFlags.WriteClassExpressionAsTypeLiteral ? - countWhere(resolved.properties, p => !(p.flags & SymbolFlags.Prototype)) : - length(resolved.properties)); + + (context.flags & NodeBuilderFlags.WriteClassExpressionAsTypeLiteral + ? countWhere(resolved.properties, p => !(p.flags & SymbolFlags.Prototype)) + : length(resolved.properties)); // don't include an empty object literal if there were no other static-side // properties to write, i.e. `abstract class C { }` becomes `abstract new () => {}` // and not `(abstract new () => {}) & {}` @@ -6976,7 +8734,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { context.flags = savedFlags; const typeLiteralNode = factory.createTypeLiteralNode(members); context.approximateLength += 2; - setEmitFlags(typeLiteralNode, (context.flags & NodeBuilderFlags.MultilineObjectLiterals) ? 0 : EmitFlags.SingleLine); + setEmitFlags( + typeLiteralNode, + (context.flags & NodeBuilderFlags.MultilineObjectLiterals) ? 0 : EmitFlags.SingleLine, + ); return typeLiteralNode; } @@ -6985,14 +8746,25 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (type.target === globalArrayType || type.target === globalReadonlyArrayType) { if (context.flags & NodeBuilderFlags.WriteArrayAsGenericType) { const typeArgumentNode = typeToTypeNodeHelper(typeArguments[0], context); - return factory.createTypeReferenceNode(type.target === globalArrayType ? "Array" : "ReadonlyArray", [typeArgumentNode]); + return factory.createTypeReferenceNode( + type.target === globalArrayType ? "Array" : "ReadonlyArray", + [typeArgumentNode], + ); } const elementType = typeToTypeNodeHelper(typeArguments[0], context); const arrayType = factory.createArrayTypeNode(elementType); - return type.target === globalArrayType ? arrayType : factory.createTypeOperatorNode(SyntaxKind.ReadonlyKeyword, arrayType); + return type.target === globalArrayType ? arrayType + : factory.createTypeOperatorNode(SyntaxKind.ReadonlyKeyword, arrayType); } else if (type.target.objectFlags & ObjectFlags.Tuple) { - typeArguments = sameMap(typeArguments, (t, i) => removeMissingType(t, !!((type.target as TupleType).elementFlags[i] & ElementFlags.Optional))); + typeArguments = sameMap( + typeArguments, + (t, i) => + removeMissingType( + t, + !!((type.target as TupleType).elementFlags[i] & ElementFlags.Optional), + ), + ); if (typeArguments.length > 0) { const arity = getTypeReferenceArity(type); const tupleConstituentNodes = mapToTypeNodes(typeArguments.slice(0, arity), context); @@ -7004,35 +8776,52 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (labeledElementDeclaration) { tupleConstituentNodes[i] = factory.createNamedTupleMember( - flags & ElementFlags.Variable ? factory.createToken(SyntaxKind.DotDotDotToken) : undefined, - factory.createIdentifier(unescapeLeadingUnderscores(getTupleElementLabel(labeledElementDeclaration))), - flags & ElementFlags.Optional ? factory.createToken(SyntaxKind.QuestionToken) : undefined, - flags & ElementFlags.Rest ? factory.createArrayTypeNode(tupleConstituentNodes[i]) : - tupleConstituentNodes[i], + flags & ElementFlags.Variable ? factory.createToken(SyntaxKind.DotDotDotToken) + : undefined, + factory.createIdentifier( + unescapeLeadingUnderscores(getTupleElementLabel(labeledElementDeclaration)), + ), + flags & ElementFlags.Optional ? factory.createToken(SyntaxKind.QuestionToken) + : undefined, + flags & ElementFlags.Rest + ? factory.createArrayTypeNode(tupleConstituentNodes[i]) + : tupleConstituentNodes[i], ); } else { - tupleConstituentNodes[i] = flags & ElementFlags.Variable ? factory.createRestTypeNode(flags & ElementFlags.Rest ? factory.createArrayTypeNode(tupleConstituentNodes[i]) : tupleConstituentNodes[i]) : - flags & ElementFlags.Optional ? factory.createOptionalTypeNode(tupleConstituentNodes[i]) : - tupleConstituentNodes[i]; + tupleConstituentNodes[i] = flags & ElementFlags.Variable + ? factory.createRestTypeNode( + flags & ElementFlags.Rest + ? factory.createArrayTypeNode(tupleConstituentNodes[i]) + : tupleConstituentNodes[i], + ) + : flags & ElementFlags.Optional + ? factory.createOptionalTypeNode(tupleConstituentNodes[i]) + : tupleConstituentNodes[i]; } } - const tupleTypeNode = setEmitFlags(factory.createTupleTypeNode(tupleConstituentNodes), EmitFlags.SingleLine); - return (type.target as TupleType).readonly ? factory.createTypeOperatorNode(SyntaxKind.ReadonlyKeyword, tupleTypeNode) : tupleTypeNode; + const tupleTypeNode = setEmitFlags( + factory.createTupleTypeNode(tupleConstituentNodes), + EmitFlags.SingleLine, + ); + return (type.target as TupleType).readonly + ? factory.createTypeOperatorNode(SyntaxKind.ReadonlyKeyword, tupleTypeNode) + : tupleTypeNode; } } if (context.encounteredError || (context.flags & NodeBuilderFlags.AllowEmptyTuple)) { const tupleTypeNode = setEmitFlags(factory.createTupleTypeNode([]), EmitFlags.SingleLine); - return (type.target as TupleType).readonly ? factory.createTypeOperatorNode(SyntaxKind.ReadonlyKeyword, tupleTypeNode) : tupleTypeNode; + return (type.target as TupleType).readonly + ? factory.createTypeOperatorNode(SyntaxKind.ReadonlyKeyword, tupleTypeNode) : tupleTypeNode; } context.encounteredError = true; return undefined!; // TODO: GH#18217 } else if ( - context.flags & NodeBuilderFlags.WriteClassExpressionAsTypeLiteral && - type.symbol.valueDeclaration && - isClassLike(type.symbol.valueDeclaration) && - !isValueSymbolAccessible(type.symbol, context.enclosingDeclaration) + context.flags & NodeBuilderFlags.WriteClassExpressionAsTypeLiteral + && type.symbol.valueDeclaration + && isClassLike(type.symbol.valueDeclaration) + && !isValueSymbolAccessible(type.symbol, context.enclosingDeclaration) ) { return createAnonymousTypeNode(type); } @@ -7056,9 +8845,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const typeArgumentSlice = mapToTypeNodes(typeArguments.slice(start, i), context); const flags = context.flags; context.flags |= NodeBuilderFlags.ForbidIndexedAccessSymbolReferences; - const ref = symbolToTypeNode(parent, context, SymbolFlags.Type, typeArgumentSlice) as TypeReferenceNode | ImportTypeNode; + const ref = symbolToTypeNode(parent, context, SymbolFlags.Type, typeArgumentSlice) as + | TypeReferenceNode + | ImportTypeNode; context.flags = flags; - resultType = !resultType ? ref : appendReferenceToType(resultType, ref as TypeReferenceNode); + resultType = !resultType ? ref + : appendReferenceToType(resultType, ref as TypeReferenceNode); } } } @@ -7075,7 +8867,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } - function appendReferenceToType(root: TypeReferenceNode | ImportTypeNode, ref: TypeReferenceNode): TypeReferenceNode | ImportTypeNode { + function appendReferenceToType( + root: TypeReferenceNode | ImportTypeNode, + ref: TypeReferenceNode, + ): TypeReferenceNode | ImportTypeNode { if (isImportTypeNode(root)) { // first shift type arguments let typeArguments = root.typeArguments; @@ -7088,7 +8883,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } else { if (typeArguments !== getIdentifierTypeArguments(qualifier.right)) { - qualifier = factory.updateQualifiedName(qualifier, qualifier.left, setIdentifierTypeArguments(factory.cloneNode(qualifier.right), typeArguments)); + qualifier = factory.updateQualifiedName( + qualifier, + qualifier.left, + setIdentifierTypeArguments(factory.cloneNode(qualifier.right), typeArguments), + ); } } } @@ -7118,7 +8917,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } else { if (typeArguments !== getIdentifierTypeArguments(typeName.right)) { - typeName = factory.updateQualifiedName(typeName, typeName.left, setIdentifierTypeArguments(factory.cloneNode(typeName.right), typeArguments)); + typeName = factory.updateQualifiedName( + typeName, + typeName.left, + setIdentifierTypeArguments(factory.cloneNode(typeName.right), typeArguments), + ); } } typeArguments = ref.typeArguments; @@ -7148,18 +8951,44 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function createTypeNodesFromResolvedType(resolvedType: ResolvedType): TypeElement[] | undefined { if (checkTruncationLength(context)) { - return [factory.createPropertySignature(/*modifiers*/ undefined, "...", /*questionToken*/ undefined, /*type*/ undefined)]; + return [ + factory.createPropertySignature( + /*modifiers*/ undefined, + "...", + /*questionToken*/ undefined, + /*type*/ undefined, + ), + ]; } const typeElements: TypeElement[] = []; for (const signature of resolvedType.callSignatures) { - typeElements.push(signatureToSignatureDeclarationHelper(signature, SyntaxKind.CallSignature, context) as CallSignatureDeclaration); + typeElements.push( + signatureToSignatureDeclarationHelper( + signature, + SyntaxKind.CallSignature, + context, + ) as CallSignatureDeclaration, + ); } for (const signature of resolvedType.constructSignatures) { if (signature.flags & SignatureFlags.Abstract) continue; - typeElements.push(signatureToSignatureDeclarationHelper(signature, SyntaxKind.ConstructSignature, context) as ConstructSignatureDeclaration); + typeElements.push( + signatureToSignatureDeclarationHelper( + signature, + SyntaxKind.ConstructSignature, + context, + ) as ConstructSignatureDeclaration, + ); } for (const info of resolvedType.indexInfos) { - typeElements.push(indexInfoToIndexSignatureDeclarationHelper(info, context, resolvedType.objectFlags & ObjectFlags.ReverseMapped ? createElidedInformationPlaceholder(context) : undefined)); + typeElements.push( + indexInfoToIndexSignatureDeclarationHelper( + info, + context, + resolvedType.objectFlags & ObjectFlags.ReverseMapped + ? createElidedInformationPlaceholder(context) : undefined, + ), + ); } const properties = resolvedType.properties; @@ -7174,12 +9003,25 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (propertySymbol.flags & SymbolFlags.Prototype) { continue; } - if (getDeclarationModifierFlagsFromSymbol(propertySymbol) & (ModifierFlags.Private | ModifierFlags.Protected) && context.tracker.reportPrivateInBaseOfClassExpression) { - context.tracker.reportPrivateInBaseOfClassExpression(unescapeLeadingUnderscores(propertySymbol.escapedName)); + if ( + getDeclarationModifierFlagsFromSymbol(propertySymbol) + & (ModifierFlags.Private | ModifierFlags.Protected) + && context.tracker.reportPrivateInBaseOfClassExpression + ) { + context.tracker.reportPrivateInBaseOfClassExpression( + unescapeLeadingUnderscores(propertySymbol.escapedName), + ); } } if (checkTruncationLength(context) && (i + 2 < properties.length - 1)) { - typeElements.push(factory.createPropertySignature(/*modifiers*/ undefined, `... ${properties.length - i} more ...`, /*questionToken*/ undefined, /*type*/ undefined)); + typeElements.push( + factory.createPropertySignature( + /*modifiers*/ undefined, + `... ${properties.length - i} more ...`, + /*questionToken*/ undefined, + /*type*/ undefined, + ), + ); addPropertyToElementList(properties[properties.length - 1], context, typeElements); break; } @@ -7209,15 +9051,20 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { contains(context.reverseMappedStack, propertySymbol as ReverseMappedSymbol) || ( context.reverseMappedStack?.[0] - && !(getObjectFlags(last(context.reverseMappedStack).links.propertyType) & ObjectFlags.Anonymous) + && !(getObjectFlags(last(context.reverseMappedStack).links.propertyType) + & ObjectFlags.Anonymous) ) ); } - function addPropertyToElementList(propertySymbol: Symbol, context: NodeBuilderContext, typeElements: TypeElement[]) { + function addPropertyToElementList( + propertySymbol: Symbol, + context: NodeBuilderContext, + typeElements: TypeElement[], + ) { const propertyIsReverseMapped = !!(getCheckFlags(propertySymbol) & CheckFlags.ReverseMapped); - const propertyType = shouldUsePlaceholderForProperty(propertySymbol, context) ? - anyType : getNonMissingTypeOfSymbol(propertySymbol); + const propertyType = shouldUsePlaceholderForProperty(propertySymbol, context) + ? anyType : getNonMissingTypeOfSymbol(propertySymbol); const saveEnclosingDeclaration = context.enclosingDeclaration; context.enclosingDeclaration = undefined; if (context.tracker.canTrackSymbol && isLateBoundName(propertySymbol.escapedName)) { @@ -7226,7 +9073,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (hasLateBindableName(decl)) { if (isBinaryExpression(decl)) { const name = getNameOfDeclaration(decl); - if (name && isElementAccessExpression(name) && isPropertyAccessEntityNameExpression(name.argumentExpression)) { + if ( + name && isElementAccessExpression(name) + && isPropertyAccessEntityNameExpression(name.argumentExpression) + ) { trackComputedName(name.argumentExpression, saveEnclosingDeclaration, context); } } @@ -7239,15 +9089,28 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { context.tracker.reportNonSerializableProperty(symbolToString(propertySymbol)); } } - context.enclosingDeclaration = propertySymbol.valueDeclaration || propertySymbol.declarations?.[0] || saveEnclosingDeclaration; + context.enclosingDeclaration = propertySymbol.valueDeclaration || propertySymbol.declarations?.[0] + || saveEnclosingDeclaration; const propertyName = getPropertyNameNodeForSymbol(propertySymbol, context); context.enclosingDeclaration = saveEnclosingDeclaration; context.approximateLength += symbolName(propertySymbol).length + 1; - const optionalToken = propertySymbol.flags & SymbolFlags.Optional ? factory.createToken(SyntaxKind.QuestionToken) : undefined; - if (propertySymbol.flags & (SymbolFlags.Function | SymbolFlags.Method) && !getPropertiesOfObjectType(propertyType).length && !isReadonlySymbol(propertySymbol)) { - const signatures = getSignaturesOfType(filterType(propertyType, t => !(t.flags & TypeFlags.Undefined)), SignatureKind.Call); + const optionalToken = propertySymbol.flags & SymbolFlags.Optional + ? factory.createToken(SyntaxKind.QuestionToken) : undefined; + if ( + propertySymbol.flags & (SymbolFlags.Function | SymbolFlags.Method) + && !getPropertiesOfObjectType(propertyType).length && !isReadonlySymbol(propertySymbol) + ) { + const signatures = getSignaturesOfType( + filterType(propertyType, t => !(t.flags & TypeFlags.Undefined)), + SignatureKind.Call, + ); for (const signature of signatures) { - const methodDeclaration = signatureToSignatureDeclarationHelper(signature, SyntaxKind.MethodSignature, context, { name: propertyName, questionToken: optionalToken }) as MethodSignature; + const methodDeclaration = signatureToSignatureDeclarationHelper( + signature, + SyntaxKind.MethodSignature, + context, + { name: propertyName, questionToken: optionalToken }, + ) as MethodSignature; typeElements.push(preserveCommentsOn(methodDeclaration)); } if (signatures.length || !optionalToken) { @@ -7263,13 +9126,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { context.reverseMappedStack ||= []; context.reverseMappedStack.push(propertySymbol as ReverseMappedSymbol); } - propertyTypeNode = propertyType ? serializeTypeForDeclaration(context, propertyType, propertySymbol, saveEnclosingDeclaration) : factory.createKeywordTypeNode(SyntaxKind.AnyKeyword); + propertyTypeNode = propertyType + ? serializeTypeForDeclaration(context, propertyType, propertySymbol, saveEnclosingDeclaration) + : factory.createKeywordTypeNode(SyntaxKind.AnyKeyword); if (propertyIsReverseMapped) { context.reverseMappedStack!.pop(); } } - const modifiers = isReadonlySymbol(propertySymbol) ? [factory.createToken(SyntaxKind.ReadonlyKeyword)] : undefined; + const modifiers = isReadonlySymbol(propertySymbol) ? [factory.createToken(SyntaxKind.ReadonlyKeyword)] + : undefined; if (modifiers) { context.approximateLength += 9; } @@ -7284,10 +9150,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function preserveCommentsOn(node: T) { if (some(propertySymbol.declarations, d => d.kind === SyntaxKind.JSDocPropertyTag)) { - const d = propertySymbol.declarations?.find(d => d.kind === SyntaxKind.JSDocPropertyTag)! as JSDocPropertyTag; + const d = propertySymbol.declarations?.find(d => + d.kind === SyntaxKind.JSDocPropertyTag + )! as JSDocPropertyTag; const commentText = getTextOfJSDocComment(d.comment); if (commentText) { - setSyntheticLeadingComments(node, [{ kind: SyntaxKind.MultiLineCommentTrivia, text: "*\n * " + commentText.replace(/\n/g, "\n * ") + "\n ", pos: -1, end: -1, hasTrailingNewLine: true }]); + setSyntheticLeadingComments(node, [{ + kind: SyntaxKind.MultiLineCommentTrivia, + text: "*\n * " + commentText.replace(/\n/g, "\n * ") + "\n ", + pos: -1, + end: -1, + hasTrailingNewLine: true, + }]); } } else if (propertySymbol.valueDeclaration) { @@ -7298,7 +9172,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } - function mapToTypeNodes(types: readonly Type[] | undefined, context: NodeBuilderContext, isBareList?: boolean): TypeNode[] | undefined { + function mapToTypeNodes( + types: readonly Type[] | undefined, + context: NodeBuilderContext, + isBareList?: boolean, + ): TypeNode[] | undefined { if (some(types)) { if (checkTruncationLength(context)) { if (!isBareList) { @@ -7307,7 +9185,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { else if (types.length > 2) { return [ typeToTypeNodeHelper(types[0], context), - factory.createTypeReferenceNode(`... ${types.length - 2} more ...`, /*typeArguments*/ undefined), + factory.createTypeReferenceNode( + `... ${types.length - 2} more ...`, + /*typeArguments*/ undefined, + ), typeToTypeNodeHelper(types[types.length - 1], context), ]; } @@ -7320,7 +9201,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { for (const type of types) { i++; if (checkTruncationLength(context) && (i + 2 < types.length - 1)) { - result.push(factory.createTypeReferenceNode(`... ${types.length - i} more ...`, /*typeArguments*/ undefined)); + result.push( + factory.createTypeReferenceNode( + `... ${types.length - i} more ...`, + /*typeArguments*/ undefined, + ), + ); const typeNode = typeToTypeNodeHelper(types[types.length - 1], context); if (typeNode) { result.push(typeNode); @@ -7367,7 +9253,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { || !!a.aliasSymbol && a.aliasSymbol === b.aliasSymbol; } - function indexInfoToIndexSignatureDeclarationHelper(indexInfo: IndexInfo, context: NodeBuilderContext, typeNode: TypeNode | undefined): IndexSignatureDeclaration { + function indexInfoToIndexSignatureDeclarationHelper( + indexInfo: IndexInfo, + context: NodeBuilderContext, + typeNode: TypeNode | undefined, + ): IndexSignatureDeclaration { const name = getNameFromIndexInfo(indexInfo) || "x"; const indexerTypeNode = typeToTypeNodeHelper(indexInfo.keyType, context); @@ -7401,17 +9291,28 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { bundledImports?: boolean; } - function signatureToSignatureDeclarationHelper(signature: Signature, kind: SignatureDeclaration["kind"], context: NodeBuilderContext, options?: SignatureToSignatureDeclarationOptions): SignatureDeclaration { + function signatureToSignatureDeclarationHelper( + signature: Signature, + kind: SignatureDeclaration["kind"], + context: NodeBuilderContext, + options?: SignatureToSignatureDeclarationOptions, + ): SignatureDeclaration { const suppressAny = context.flags & NodeBuilderFlags.SuppressAnyReturnType; if (suppressAny) context.flags &= ~NodeBuilderFlags.SuppressAnyReturnType; // suppress only toplevel `any`s context.approximateLength += 3; // Usually a signature contributes a few more characters than this, but 3 is the minimum let typeParameters: TypeParameterDeclaration[] | undefined; let typeArguments: TypeNode[] | undefined; - if (context.flags & NodeBuilderFlags.WriteTypeArgumentsOfSignature && signature.target && signature.mapper && signature.target.typeParameters) { - typeArguments = signature.target.typeParameters.map(parameter => typeToTypeNodeHelper(instantiateType(parameter, signature.mapper), context)); + if ( + context.flags & NodeBuilderFlags.WriteTypeArgumentsOfSignature && signature.target && signature.mapper + && signature.target.typeParameters + ) { + typeArguments = signature.target.typeParameters.map(parameter => + typeToTypeNodeHelper(instantiateType(parameter, signature.mapper), context) + ); } else { - typeParameters = signature.typeParameters && signature.typeParameters.map(parameter => typeParameterToDeclaration(parameter, context)); + typeParameters = signature.typeParameters + && signature.typeParameters.map(parameter => typeParameterToDeclaration(parameter, context)); } const expandedParams = getExpandedParameters(signature, /*skipUnionExpanding*/ true)[0]; @@ -7455,7 +9356,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // Note that we only check the most immediate enclosingDeclaration; the only place we // could potentially add another fake scope into the chain is right here, so we don't // traverse all ancestors. - const existingFakeScope = getNodeLinks(context.enclosingDeclaration).fakeScopeForSignatureDeclaration ? context.enclosingDeclaration : undefined; + const existingFakeScope = getNodeLinks(context.enclosingDeclaration).fakeScopeForSignatureDeclaration + ? context.enclosingDeclaration : undefined; Debug.assertOptionalNode(existingFakeScope, isBlock); const locals = existingFakeScope?.locals ?? createSymbolTable(); @@ -7496,8 +9398,21 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } // If the expanded parameter list had a variadic in a non-trailing position, don't expand it - const parameters = (some(expandedParams, p => p !== expandedParams[expandedParams.length - 1] && !!(getCheckFlags(p) & CheckFlags.RestParameter)) ? signature.parameters : expandedParams).map(parameter => symbolToParameterDeclaration(parameter, context, kind === SyntaxKind.Constructor, options?.privateSymbolVisitor, options?.bundledImports)); - const thisParameter = context.flags & NodeBuilderFlags.OmitThisParameter ? undefined : tryGetThisParameterDeclaration(signature, context); + const parameters = (some( + expandedParams, + p => p !== expandedParams[expandedParams.length - 1] + && !!(getCheckFlags(p) & CheckFlags.RestParameter), + ) ? signature.parameters : expandedParams).map(parameter => + symbolToParameterDeclaration( + parameter, + context, + kind === SyntaxKind.Constructor, + options?.privateSymbolVisitor, + options?.bundledImports, + ) + ); + const thisParameter = context.flags & NodeBuilderFlags.OmitThisParameter ? undefined + : tryGetThisParameterDeclaration(signature, context); if (thisParameter) { parameters.unshift(thisParameter); } @@ -7505,19 +9420,27 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { let returnTypeNode: TypeNode | undefined; const typePredicate = getTypePredicateOfSignature(signature); if (typePredicate) { - const assertsModifier = typePredicate.kind === TypePredicateKind.AssertsThis || typePredicate.kind === TypePredicateKind.AssertsIdentifier ? - factory.createToken(SyntaxKind.AssertsKeyword) : - undefined; - const parameterName = typePredicate.kind === TypePredicateKind.Identifier || typePredicate.kind === TypePredicateKind.AssertsIdentifier ? - setEmitFlags(factory.createIdentifier(typePredicate.parameterName), EmitFlags.NoAsciiEscaping) : - factory.createThisTypeNode(); + const assertsModifier = typePredicate.kind === TypePredicateKind.AssertsThis + || typePredicate.kind === TypePredicateKind.AssertsIdentifier + ? factory.createToken(SyntaxKind.AssertsKeyword) + : undefined; + const parameterName = typePredicate.kind === TypePredicateKind.Identifier + || typePredicate.kind === TypePredicateKind.AssertsIdentifier + ? setEmitFlags(factory.createIdentifier(typePredicate.parameterName), EmitFlags.NoAsciiEscaping) + : factory.createThisTypeNode(); const typeNode = typePredicate.type && typeToTypeNodeHelper(typePredicate.type, context); returnTypeNode = factory.createTypePredicateNode(assertsModifier, parameterName, typeNode); } else { const returnType = getReturnTypeOfSignature(signature); if (returnType && !(suppressAny && isTypeAny(returnType))) { - returnTypeNode = serializeReturnTypeForSignature(context, returnType, signature, options?.privateSymbolVisitor, options?.bundledImports); + returnTypeNode = serializeReturnTypeForSignature( + context, + returnType, + signature, + options?.privateSymbolVisitor, + options?.bundledImports, + ); } else if (!suppressAny) { returnTypeNode = factory.createKeywordTypeNode(SyntaxKind.AnyKeyword); @@ -7529,28 +9452,109 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { modifiers = factory.createModifiersFromModifierFlags(flags | ModifierFlags.Abstract); } - const node = kind === SyntaxKind.CallSignature ? factory.createCallSignature(typeParameters, parameters, returnTypeNode) : - kind === SyntaxKind.ConstructSignature ? factory.createConstructSignature(typeParameters, parameters, returnTypeNode) : - kind === SyntaxKind.MethodSignature ? factory.createMethodSignature(modifiers, options?.name ?? factory.createIdentifier(""), options?.questionToken, typeParameters, parameters, returnTypeNode) : - kind === SyntaxKind.MethodDeclaration ? factory.createMethodDeclaration(modifiers, /*asteriskToken*/ undefined, options?.name ?? factory.createIdentifier(""), /*questionToken*/ undefined, typeParameters, parameters, returnTypeNode, /*body*/ undefined) : - kind === SyntaxKind.Constructor ? factory.createConstructorDeclaration(modifiers, parameters, /*body*/ undefined) : - kind === SyntaxKind.GetAccessor ? factory.createGetAccessorDeclaration(modifiers, options?.name ?? factory.createIdentifier(""), parameters, returnTypeNode, /*body*/ undefined) : - kind === SyntaxKind.SetAccessor ? factory.createSetAccessorDeclaration(modifiers, options?.name ?? factory.createIdentifier(""), parameters, /*body*/ undefined) : - kind === SyntaxKind.IndexSignature ? factory.createIndexSignature(modifiers, parameters, returnTypeNode) : - kind === SyntaxKind.JSDocFunctionType ? factory.createJSDocFunctionType(parameters, returnTypeNode) : - kind === SyntaxKind.FunctionType ? factory.createFunctionTypeNode(typeParameters, parameters, returnTypeNode ?? factory.createTypeReferenceNode(factory.createIdentifier(""))) : - kind === SyntaxKind.ConstructorType ? factory.createConstructorTypeNode(modifiers, typeParameters, parameters, returnTypeNode ?? factory.createTypeReferenceNode(factory.createIdentifier(""))) : - kind === SyntaxKind.FunctionDeclaration ? factory.createFunctionDeclaration(modifiers, /*asteriskToken*/ undefined, options?.name ? cast(options.name, isIdentifier) : factory.createIdentifier(""), typeParameters, parameters, returnTypeNode, /*body*/ undefined) : - kind === SyntaxKind.FunctionExpression ? factory.createFunctionExpression(modifiers, /*asteriskToken*/ undefined, options?.name ? cast(options.name, isIdentifier) : factory.createIdentifier(""), typeParameters, parameters, returnTypeNode, factory.createBlock([])) : - kind === SyntaxKind.ArrowFunction ? factory.createArrowFunction(modifiers, typeParameters, parameters, returnTypeNode, /*equalsGreaterThanToken*/ undefined, factory.createBlock([])) : - Debug.assertNever(kind); + const node = kind === SyntaxKind.CallSignature + ? factory.createCallSignature(typeParameters, parameters, returnTypeNode) + : kind === SyntaxKind.ConstructSignature + ? factory.createConstructSignature(typeParameters, parameters, returnTypeNode) + : kind === SyntaxKind.MethodSignature + ? factory.createMethodSignature( + modifiers, + options?.name ?? factory.createIdentifier(""), + options?.questionToken, + typeParameters, + parameters, + returnTypeNode, + ) + : kind === SyntaxKind.MethodDeclaration + ? factory.createMethodDeclaration( + modifiers, + /*asteriskToken*/ undefined, + options?.name ?? factory.createIdentifier(""), + /*questionToken*/ undefined, + typeParameters, + parameters, + returnTypeNode, + /*body*/ undefined, + ) + : kind === SyntaxKind.Constructor + ? factory.createConstructorDeclaration(modifiers, parameters, /*body*/ undefined) + : kind === SyntaxKind.GetAccessor + ? factory.createGetAccessorDeclaration( + modifiers, + options?.name ?? factory.createIdentifier(""), + parameters, + returnTypeNode, + /*body*/ undefined, + ) + : kind === SyntaxKind.SetAccessor + ? factory.createSetAccessorDeclaration( + modifiers, + options?.name ?? factory.createIdentifier(""), + parameters, + /*body*/ undefined, + ) + : kind === SyntaxKind.IndexSignature + ? factory.createIndexSignature(modifiers, parameters, returnTypeNode) + : kind === SyntaxKind.JSDocFunctionType ? factory.createJSDocFunctionType(parameters, returnTypeNode) + : kind === SyntaxKind.FunctionType + ? factory.createFunctionTypeNode( + typeParameters, + parameters, + returnTypeNode ?? factory.createTypeReferenceNode(factory.createIdentifier("")), + ) + : kind === SyntaxKind.ConstructorType + ? factory.createConstructorTypeNode( + modifiers, + typeParameters, + parameters, + returnTypeNode ?? factory.createTypeReferenceNode(factory.createIdentifier("")), + ) + : kind === SyntaxKind.FunctionDeclaration + ? factory.createFunctionDeclaration( + modifiers, + /*asteriskToken*/ undefined, + options?.name ? cast(options.name, isIdentifier) : factory.createIdentifier(""), + typeParameters, + parameters, + returnTypeNode, + /*body*/ undefined, + ) + : kind === SyntaxKind.FunctionExpression + ? factory.createFunctionExpression( + modifiers, + /*asteriskToken*/ undefined, + options?.name ? cast(options.name, isIdentifier) : factory.createIdentifier(""), + typeParameters, + parameters, + returnTypeNode, + factory.createBlock([]), + ) + : kind === SyntaxKind.ArrowFunction + ? factory.createArrowFunction( + modifiers, + typeParameters, + parameters, + returnTypeNode, + /*equalsGreaterThanToken*/ undefined, + factory.createBlock([]), + ) + : Debug.assertNever(kind); if (typeArguments) { node.typeArguments = factory.createNodeArray(typeArguments); } - if (signature.declaration?.kind === SyntaxKind.JSDocSignature && signature.declaration.parent.kind === SyntaxKind.JSDocOverloadTag) { - const comment = getTextOfNode(signature.declaration.parent.parent, /*includeTrivia*/ true).slice(2, -2).split(/\r\n|\n|\r/).map(line => line.replace(/^\s+/, " ")).join("\n"); - addSyntheticLeadingComment(node, SyntaxKind.MultiLineCommentTrivia, comment, /*hasTrailingNewLine*/ true); + if ( + signature.declaration?.kind === SyntaxKind.JSDocSignature + && signature.declaration.parent.kind === SyntaxKind.JSDocOverloadTag + ) { + const comment = getTextOfNode(signature.declaration.parent.parent, /*includeTrivia*/ true).slice(2, -2) + .split(/\r\n|\n|\r/).map(line => line.replace(/^\s+/, " ")).join("\n"); + addSyntheticLeadingComment( + node, + SyntaxKind.MultiLineCommentTrivia, + comment, + /*hasTrailingNewLine*/ true, + ); } cleanup?.(); @@ -7575,7 +9579,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } - function typeParameterToDeclarationWithConstraint(type: TypeParameter, context: NodeBuilderContext, constraintNode: TypeNode | undefined): TypeParameterDeclaration { + function typeParameterToDeclarationWithConstraint( + type: TypeParameter, + context: NodeBuilderContext, + constraintNode: TypeNode | undefined, + ): TypeParameterDeclaration { const savedContextFlags = context.flags; context.flags &= ~NodeBuilderFlags.WriteTypeParametersInQualifiedName; // Avoids potential infinite loop when building for a claimspace with a generic const modifiers = factory.createModifiersFromModifierFlags(getTypeParameterModifiers(type)); @@ -7586,33 +9594,61 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return factory.createTypeParameterDeclaration(modifiers, name, constraintNode, defaultParameterNode); } - function typeParameterToDeclaration(type: TypeParameter, context: NodeBuilderContext, constraint = getConstraintOfTypeParameter(type)): TypeParameterDeclaration { + function typeParameterToDeclaration( + type: TypeParameter, + context: NodeBuilderContext, + constraint = getConstraintOfTypeParameter(type), + ): TypeParameterDeclaration { const constraintNode = constraint && typeToTypeNodeHelper(constraint, context); return typeParameterToDeclarationWithConstraint(type, context, constraintNode); } - function symbolToParameterDeclaration(parameterSymbol: Symbol, context: NodeBuilderContext, preserveModifierFlags?: boolean, privateSymbolVisitor?: (s: Symbol) => void, bundledImports?: boolean): ParameterDeclaration { - let parameterDeclaration: ParameterDeclaration | JSDocParameterTag | undefined = getDeclarationOfKind(parameterSymbol, SyntaxKind.Parameter); + function symbolToParameterDeclaration( + parameterSymbol: Symbol, + context: NodeBuilderContext, + preserveModifierFlags?: boolean, + privateSymbolVisitor?: (s: Symbol) => void, + bundledImports?: boolean, + ): ParameterDeclaration { + let parameterDeclaration: ParameterDeclaration | JSDocParameterTag | undefined = getDeclarationOfKind< + ParameterDeclaration + >(parameterSymbol, SyntaxKind.Parameter); if (!parameterDeclaration && !isTransientSymbol(parameterSymbol)) { - parameterDeclaration = getDeclarationOfKind(parameterSymbol, SyntaxKind.JSDocParameterTag); + parameterDeclaration = getDeclarationOfKind( + parameterSymbol, + SyntaxKind.JSDocParameterTag, + ); } let parameterType = getTypeOfSymbol(parameterSymbol); if (parameterDeclaration && isRequiredInitializedParameter(parameterDeclaration)) { parameterType = getOptionalType(parameterType); } - const parameterTypeNode = serializeTypeForDeclaration(context, parameterType, parameterSymbol, context.enclosingDeclaration, privateSymbolVisitor, bundledImports); + const parameterTypeNode = serializeTypeForDeclaration( + context, + parameterType, + parameterSymbol, + context.enclosingDeclaration, + privateSymbolVisitor, + bundledImports, + ); - const modifiers = !(context.flags & NodeBuilderFlags.OmitParameterModifiers) && preserveModifierFlags && parameterDeclaration && canHaveModifiers(parameterDeclaration) ? map(getModifiers(parameterDeclaration), factory.cloneNode) : undefined; - const isRest = parameterDeclaration && isRestParameter(parameterDeclaration) || getCheckFlags(parameterSymbol) & CheckFlags.RestParameter; + const modifiers = !(context.flags & NodeBuilderFlags.OmitParameterModifiers) && preserveModifierFlags + && parameterDeclaration && canHaveModifiers(parameterDeclaration) + ? map(getModifiers(parameterDeclaration), factory.cloneNode) : undefined; + const isRest = parameterDeclaration && isRestParameter(parameterDeclaration) + || getCheckFlags(parameterSymbol) & CheckFlags.RestParameter; const dotDotDotToken = isRest ? factory.createToken(SyntaxKind.DotDotDotToken) : undefined; - const name = parameterDeclaration ? parameterDeclaration.name ? - parameterDeclaration.name.kind === SyntaxKind.Identifier ? setEmitFlags(factory.cloneNode(parameterDeclaration.name), EmitFlags.NoAsciiEscaping) : - parameterDeclaration.name.kind === SyntaxKind.QualifiedName ? setEmitFlags(factory.cloneNode(parameterDeclaration.name.right), EmitFlags.NoAsciiEscaping) : - cloneBindingName(parameterDeclaration.name) : - symbolName(parameterSymbol) : - symbolName(parameterSymbol); - const isOptional = parameterDeclaration && isOptionalParameter(parameterDeclaration) || getCheckFlags(parameterSymbol) & CheckFlags.OptionalParameter; + const name = parameterDeclaration ? parameterDeclaration.name + ? parameterDeclaration.name.kind === SyntaxKind.Identifier + ? setEmitFlags(factory.cloneNode(parameterDeclaration.name), EmitFlags.NoAsciiEscaping) + : parameterDeclaration.name.kind === SyntaxKind.QualifiedName + ? setEmitFlags(factory.cloneNode(parameterDeclaration.name.right), EmitFlags.NoAsciiEscaping) + : cloneBindingName(parameterDeclaration.name) + : symbolName(parameterSymbol) + : symbolName(parameterSymbol); + const isOptional = parameterDeclaration && isOptionalParameter(parameterDeclaration) + || getCheckFlags(parameterSymbol) & CheckFlags.OptionalParameter; const questionToken = isOptional ? factory.createToken(SyntaxKind.QuestionToken) : undefined; const parameterNode = factory.createParameterDeclaration( modifiers, @@ -7631,7 +9667,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (context.tracker.canTrackSymbol && isComputedPropertyName(node) && isLateBindableName(node)) { trackComputedName(node.expression, context.enclosingDeclaration, context); } - let visited = visitEachChild(node, elideInitializerAndSetEmitFlags, nullTransformationContext, /*nodesVisitor*/ undefined, elideInitializerAndSetEmitFlags)!; + let visited = visitEachChild( + node, + elideInitializerAndSetEmitFlags, + nullTransformationContext, + /*nodesVisitor*/ undefined, + elideInitializerAndSetEmitFlags, + )!; if (isBindingElement(visited)) { visited = factory.updateBindingElement( visited, @@ -7649,26 +9691,51 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } - function trackComputedName(accessExpression: EntityNameOrEntityNameExpression, enclosingDeclaration: Node | undefined, context: NodeBuilderContext) { + function trackComputedName( + accessExpression: EntityNameOrEntityNameExpression, + enclosingDeclaration: Node | undefined, + context: NodeBuilderContext, + ) { if (!context.tracker.canTrackSymbol) return; // get symbol of the first identifier of the entityName const firstIdentifier = getFirstIdentifier(accessExpression); - const name = resolveName(firstIdentifier, firstIdentifier.escapedText, SymbolFlags.Value | SymbolFlags.ExportValue, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ true); + const name = resolveName( + firstIdentifier, + firstIdentifier.escapedText, + SymbolFlags.Value | SymbolFlags.ExportValue, + /*nameNotFoundMessage*/ undefined, + /*nameArg*/ undefined, + /*isUse*/ true, + ); if (name) { context.tracker.trackSymbol(name, enclosingDeclaration, SymbolFlags.Value); } } - function lookupSymbolChain(symbol: Symbol, context: NodeBuilderContext, meaning: SymbolFlags, yieldModuleSymbol?: boolean) { + function lookupSymbolChain( + symbol: Symbol, + context: NodeBuilderContext, + meaning: SymbolFlags, + yieldModuleSymbol?: boolean, + ) { context.tracker.trackSymbol(symbol, context.enclosingDeclaration, meaning); return lookupSymbolChainWorker(symbol, context, meaning, yieldModuleSymbol); } - function lookupSymbolChainWorker(symbol: Symbol, context: NodeBuilderContext, meaning: SymbolFlags, yieldModuleSymbol?: boolean) { + function lookupSymbolChainWorker( + symbol: Symbol, + context: NodeBuilderContext, + meaning: SymbolFlags, + yieldModuleSymbol?: boolean, + ) { // Try to get qualified name if the symbol is not a type parameter and there is an enclosing declaration. let chain: Symbol[]; const isTypeParameter = symbol.flags & SymbolFlags.TypeParameter; - if (!isTypeParameter && (context.enclosingDeclaration || context.flags & NodeBuilderFlags.UseFullyQualifiedType) && !(context.flags & NodeBuilderFlags.DoNotIncludeSymbolChain)) { + if ( + !isTypeParameter + && (context.enclosingDeclaration || context.flags & NodeBuilderFlags.UseFullyQualifiedType) + && !(context.flags & NodeBuilderFlags.DoNotIncludeSymbolChain) + ) { chain = Debug.checkDefined(getSymbolChain(symbol, meaning, /*endOfChain*/ true)); Debug.assert(chain && chain.length > 0); } @@ -7679,14 +9746,27 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { /** @param endOfChain Set to false for recursive calls; non-recursive calls should always output something. */ function getSymbolChain(symbol: Symbol, meaning: SymbolFlags, endOfChain: boolean): Symbol[] | undefined { - let accessibleSymbolChain = getAccessibleSymbolChain(symbol, context.enclosingDeclaration, meaning, !!(context.flags & NodeBuilderFlags.UseOnlyExternalAliasing)); + let accessibleSymbolChain = getAccessibleSymbolChain( + symbol, + context.enclosingDeclaration, + meaning, + !!(context.flags & NodeBuilderFlags.UseOnlyExternalAliasing), + ); let parentSpecifiers: (string | undefined)[]; if ( - !accessibleSymbolChain || - needsQualification(accessibleSymbolChain[0], context.enclosingDeclaration, accessibleSymbolChain.length === 1 ? meaning : getQualifiedLeftMeaning(meaning)) + !accessibleSymbolChain + || needsQualification( + accessibleSymbolChain[0], + context.enclosingDeclaration, + accessibleSymbolChain.length === 1 ? meaning : getQualifiedLeftMeaning(meaning), + ) ) { // Go up and add our parent. - const parents = getContainersOfSymbol(accessibleSymbolChain ? accessibleSymbolChain[0] : symbol, context.enclosingDeclaration, meaning); + const parents = getContainersOfSymbol( + accessibleSymbolChain ? accessibleSymbolChain[0] : symbol, + context.enclosingDeclaration, + meaning, + ); if (length(parents)) { parentSpecifiers = parents!.map(symbol => some(symbol.declarations, hasNonGlobalAugmentationExternalModuleSymbol) @@ -7697,18 +9777,27 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { indices.sort(sortByBestName); const sortedParents = indices.map(i => parents![i]); for (const parent of sortedParents) { - const parentChain = getSymbolChain(parent, getQualifiedLeftMeaning(meaning), /*endOfChain*/ false); + const parentChain = getSymbolChain( + parent, + getQualifiedLeftMeaning(meaning), + /*endOfChain*/ false, + ); if (parentChain) { if ( - parent.exports && parent.exports.get(InternalSymbolName.ExportEquals) && - getSymbolIfSameReference(parent.exports.get(InternalSymbolName.ExportEquals)!, symbol) + parent.exports && parent.exports.get(InternalSymbolName.ExportEquals) + && getSymbolIfSameReference( + parent.exports.get(InternalSymbolName.ExportEquals)!, + symbol, + ) ) { // parentChain root _is_ symbol - symbol is a module export=, so it kinda looks like it's own parent // No need to lookup an alias for the symbol in itself accessibleSymbolChain = parentChain; break; } - accessibleSymbolChain = parentChain.concat(accessibleSymbolChain || [getAliasForSymbolInContainer(parent, symbol) || symbol]); + accessibleSymbolChain = parentChain.concat( + accessibleSymbolChain || [getAliasForSymbolInContainer(parent, symbol) || symbol], + ); break; } } @@ -7720,12 +9809,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } if ( // If this is the last part of outputting the symbol, always output. The cases apply only to parent symbols. - endOfChain || + endOfChain // If a parent symbol is an anonymous type, don't write it. - !(symbol.flags & (SymbolFlags.TypeLiteral | SymbolFlags.ObjectLiteral)) + || !(symbol.flags & (SymbolFlags.TypeLiteral | SymbolFlags.ObjectLiteral)) ) { // If a parent symbol is an external module, don't write it. (We prefer just `x` vs `"foo/bar".x`.) - if (!endOfChain && !yieldModuleSymbol && !!forEach(symbol.declarations, hasNonGlobalAugmentationExternalModuleSymbol)) { + if ( + !endOfChain && !yieldModuleSymbol + && !!forEach(symbol.declarations, hasNonGlobalAugmentationExternalModuleSymbol) + ) { return; } return [symbol]; @@ -7738,7 +9830,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const isBRelative = pathIsRelative(specifierB); if (pathIsRelative(specifierA) === isBRelative) { // Both relative or both non-relative, sort by number of parts - return moduleSpecifiers.countPathComponents(specifierA) - moduleSpecifiers.countPathComponents(specifierB); + return moduleSpecifiers.countPathComponents(specifierA) + - moduleSpecifiers.countPathComponents(specifierB); } if (isBRelative) { // A is non-relative, B is relative: prefer A @@ -7756,7 +9849,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { let typeParameterNodes: NodeArray | undefined; const targetSymbol = getTargetSymbol(symbol); if (targetSymbol.flags & (SymbolFlags.Class | SymbolFlags.Interface | SymbolFlags.TypeAlias)) { - typeParameterNodes = factory.createNodeArray(map(getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(symbol), tp => typeParameterToDeclaration(tp, context))); + typeParameterNodes = factory.createNodeArray( + map( + getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(symbol), + tp => typeParameterToDeclaration(tp, context), + ), + ); } return typeParameterNodes; } @@ -7778,7 +9876,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { parentSymbol.flags & SymbolFlags.Alias ? resolveAlias(parentSymbol) : parentSymbol, ); // NOTE: cast to TransientSymbol should be safe because only TransientSymbol can have CheckFlags.Instantiated - typeParameterNodes = mapToTypeNodes(map(params, t => getMappedType(t, (nextSymbol as TransientSymbol).links.mapper!)), context); + typeParameterNodes = mapToTypeNodes( + map(params, t => getMappedType(t, (nextSymbol as TransientSymbol).links.mapper!)), + context, + ); } else { typeParameterNodes = typeParametersToTypeParameterDeclarations(symbol, context); @@ -7797,10 +9898,17 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return top; } - function getSpecifierForModuleSymbol(symbol: Symbol, context: NodeBuilderContext, overrideImportMode?: ResolutionMode) { + function getSpecifierForModuleSymbol( + symbol: Symbol, + context: NodeBuilderContext, + overrideImportMode?: ResolutionMode, + ) { let file = getDeclarationOfKind(symbol, SyntaxKind.SourceFile); if (!file) { - const equivalentFileSymbol = firstDefined(symbol.declarations, d => getFileSymbolIfFileSymbolExportEqualsContainer(d, symbol)); + const equivalentFileSymbol = firstDefined( + symbol.declarations, + d => getFileSymbolIfFileSymbolExportEqualsContainer(d, symbol), + ); if (equivalentFileSymbol) { file = getDeclarationOfKind(equivalentFileSymbol, SyntaxKind.SourceFile); } @@ -7841,7 +9949,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // using the `baseUrl` compiler option (which we would otherwise never use in declaration emit) and a non-relative // specifier preference const { moduleResolverHost } = context.tracker; - const specifierCompilerOptions = isBundle ? { ...compilerOptions, baseUrl: moduleResolverHost.getCommonSourceDirectory() } : compilerOptions; + const specifierCompilerOptions = isBundle + ? { ...compilerOptions, baseUrl: moduleResolverHost.getCommonSourceDirectory() } : compilerOptions; specifier = first(moduleSpecifiers.getModuleSpecifiers( symbol, checker, @@ -7864,42 +9973,70 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function symbolToEntityNameNode(symbol: Symbol): EntityName { const identifier = factory.createIdentifier(unescapeLeadingUnderscores(symbol.escapedName)); - return symbol.parent ? factory.createQualifiedName(symbolToEntityNameNode(symbol.parent), identifier) : identifier; - } - - function symbolToTypeNode(symbol: Symbol, context: NodeBuilderContext, meaning: SymbolFlags, overrideTypeArguments?: readonly TypeNode[]): TypeNode { - const chain = lookupSymbolChain(symbol, context, meaning, !(context.flags & NodeBuilderFlags.UseAliasDefinedOutsideCurrentScope)); // If we're using aliases outside the current scope, dont bother with the module + return symbol.parent ? factory.createQualifiedName(symbolToEntityNameNode(symbol.parent), identifier) + : identifier; + } + + function symbolToTypeNode( + symbol: Symbol, + context: NodeBuilderContext, + meaning: SymbolFlags, + overrideTypeArguments?: readonly TypeNode[], + ): TypeNode { + const chain = lookupSymbolChain( + symbol, + context, + meaning, + !(context.flags & NodeBuilderFlags.UseAliasDefinedOutsideCurrentScope), + ); // If we're using aliases outside the current scope, dont bother with the module const isTypeOf = meaning === SymbolFlags.Value; if (some(chain[0].declarations, hasNonGlobalAugmentationExternalModuleSymbol)) { // module is root, must use `ImportTypeNode` - const nonRootParts = chain.length > 1 ? createAccessFromSymbolChain(chain, chain.length - 1, 1) : undefined; + const nonRootParts = chain.length > 1 ? createAccessFromSymbolChain(chain, chain.length - 1, 1) + : undefined; const typeParameterNodes = overrideTypeArguments || lookupTypeParameterNodes(chain, 0, context); const contextFile = getSourceFileOfNode(getOriginalNode(context.enclosingDeclaration)); const targetFile = getSourceFileOfModule(chain[0]); let specifier: string | undefined; let assertion: ImportTypeAssertionContainer | undefined; - if (getEmitModuleResolutionKind(compilerOptions) === ModuleResolutionKind.Node16 || getEmitModuleResolutionKind(compilerOptions) === ModuleResolutionKind.NodeNext) { + if ( + getEmitModuleResolutionKind(compilerOptions) === ModuleResolutionKind.Node16 + || getEmitModuleResolutionKind(compilerOptions) === ModuleResolutionKind.NodeNext + ) { // An `import` type directed at an esm format file is only going to resolve in esm mode - set the esm mode assertion - if (targetFile?.impliedNodeFormat === ModuleKind.ESNext && targetFile.impliedNodeFormat !== contextFile?.impliedNodeFormat) { + if ( + targetFile?.impliedNodeFormat === ModuleKind.ESNext + && targetFile.impliedNodeFormat !== contextFile?.impliedNodeFormat + ) { specifier = getSpecifierForModuleSymbol(chain[0], context, ModuleKind.ESNext); - assertion = factory.createImportTypeAssertionContainer(factory.createAssertClause(factory.createNodeArray([ - factory.createAssertEntry( - factory.createStringLiteral("resolution-mode"), - factory.createStringLiteral("import"), - ), - ]))); + assertion = factory.createImportTypeAssertionContainer( + factory.createAssertClause(factory.createNodeArray([ + factory.createAssertEntry( + factory.createStringLiteral("resolution-mode"), + factory.createStringLiteral("import"), + ), + ])), + ); context.tracker.reportImportTypeNodeResolutionModeOverride?.(); } } if (!specifier) { specifier = getSpecifierForModuleSymbol(chain[0], context); } - if (!(context.flags & NodeBuilderFlags.AllowNodeModulesRelativePaths) && getEmitModuleResolutionKind(compilerOptions) !== ModuleResolutionKind.Classic && specifier.indexOf("/node_modules/") >= 0) { + if ( + !(context.flags & NodeBuilderFlags.AllowNodeModulesRelativePaths) + && getEmitModuleResolutionKind(compilerOptions) !== ModuleResolutionKind.Classic + && specifier.indexOf("/node_modules/") >= 0 + ) { const oldSpecifier = specifier; - if (getEmitModuleResolutionKind(compilerOptions) === ModuleResolutionKind.Node16 || getEmitModuleResolutionKind(compilerOptions) === ModuleResolutionKind.NodeNext) { + if ( + getEmitModuleResolutionKind(compilerOptions) === ModuleResolutionKind.Node16 + || getEmitModuleResolutionKind(compilerOptions) === ModuleResolutionKind.NodeNext + ) { // We might be able to write a portable import type using a mode override; try specifier generation again, but with a different mode set - const swappedMode = contextFile?.impliedNodeFormat === ModuleKind.ESNext ? ModuleKind.CommonJS : ModuleKind.ESNext; + const swappedMode = contextFile?.impliedNodeFormat === ModuleKind.ESNext ? ModuleKind.CommonJS + : ModuleKind.ESNext; specifier = getSpecifierForModuleSymbol(chain[0], context, swappedMode); if (specifier.indexOf("/node_modules/") >= 0) { @@ -7907,12 +10044,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { specifier = oldSpecifier; } else { - assertion = factory.createImportTypeAssertionContainer(factory.createAssertClause(factory.createNodeArray([ - factory.createAssertEntry( - factory.createStringLiteral("resolution-mode"), - factory.createStringLiteral(swappedMode === ModuleKind.ESNext ? "import" : "require"), - ), - ]))); + assertion = factory.createImportTypeAssertionContainer( + factory.createAssertClause(factory.createNodeArray([ + factory.createAssertEntry( + factory.createStringLiteral("resolution-mode"), + factory.createStringLiteral( + swappedMode === ModuleKind.ESNext ? "import" : "require", + ), + ), + ])), + ); context.tracker.reportImportTypeNodeResolutionModeOverride?.(); } } @@ -7927,19 +10068,36 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } const lit = factory.createLiteralTypeNode(factory.createStringLiteral(specifier)); - if (context.tracker.trackExternalModuleSymbolOfImportTypeNode) context.tracker.trackExternalModuleSymbolOfImportTypeNode(chain[0]); + if (context.tracker.trackExternalModuleSymbolOfImportTypeNode) { + context.tracker.trackExternalModuleSymbolOfImportTypeNode(chain[0]); + } context.approximateLength += specifier.length + 10; // specifier + import("") if (!nonRootParts || isEntityName(nonRootParts)) { if (nonRootParts) { const lastId = isIdentifier(nonRootParts) ? nonRootParts : nonRootParts.right; setIdentifierTypeArguments(lastId, /*typeArguments*/ undefined); } - return factory.createImportTypeNode(lit, assertion, nonRootParts as EntityName, typeParameterNodes as readonly TypeNode[], isTypeOf); + return factory.createImportTypeNode( + lit, + assertion, + nonRootParts as EntityName, + typeParameterNodes as readonly TypeNode[], + isTypeOf, + ); } else { const splitNode = getTopmostIndexedAccessType(nonRootParts); const qualifier = (splitNode.objectType as TypeReferenceNode).typeName; - return factory.createIndexedAccessTypeNode(factory.createImportTypeNode(lit, assertion, qualifier, typeParameterNodes as readonly TypeNode[], isTypeOf), splitNode.indexType); + return factory.createIndexedAccessTypeNode( + factory.createImportTypeNode( + lit, + assertion, + qualifier, + typeParameterNodes as readonly TypeNode[], + isTypeOf, + ), + splitNode.indexType, + ); } } @@ -7957,8 +10115,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return factory.createTypeReferenceNode(entityName, lastTypeArgs as NodeArray); } - function createAccessFromSymbolChain(chain: Symbol[], index: number, stopper: number): EntityName | IndexedAccessTypeNode { - const typeParameterNodes = index === (chain.length - 1) ? overrideTypeArguments : lookupTypeParameterNodes(chain, index, context); + function createAccessFromSymbolChain( + chain: Symbol[], + index: number, + stopper: number, + ): EntityName | IndexedAccessTypeNode { + const typeParameterNodes = index === (chain.length - 1) ? overrideTypeArguments + : lookupTypeParameterNodes(chain, index, context); const symbol = chain[index]; const parent = chain[index - 1]; @@ -7973,7 +10136,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (parent && getExportsOfSymbol(parent)) { const exports = getExportsOfSymbol(parent); forEachEntry(exports, (ex, name) => { - if (getSymbolIfSameReference(ex, symbol) && !isLateBoundName(name) && name !== InternalSymbolName.ExportEquals) { + if ( + getSymbolIfSameReference(ex, symbol) && !isLateBoundName(name) + && name !== InternalSymbolName.ExportEquals + ) { symbolName = unescapeLeadingUnderscores(name); return true; } @@ -7986,7 +10152,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (name && isComputedPropertyName(name) && isEntityName(name.expression)) { const LHS = createAccessFromSymbolChain(chain, index - 1, stopper); if (isEntityName(LHS)) { - return factory.createIndexedAccessTypeNode(factory.createParenthesizedType(factory.createTypeQueryNode(LHS)), factory.createTypeQueryNode(name.expression)); + return factory.createIndexedAccessTypeNode( + factory.createParenthesizedType(factory.createTypeQueryNode(LHS)), + factory.createTypeQueryNode(name.expression), + ); } return LHS; } @@ -7995,22 +10164,33 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { context.approximateLength += symbolName.length + 1; if ( - !(context.flags & NodeBuilderFlags.ForbidIndexedAccessSymbolReferences) && parent && - getMembersOfSymbol(parent) && getMembersOfSymbol(parent).get(symbol.escapedName) && - getSymbolIfSameReference(getMembersOfSymbol(parent).get(symbol.escapedName)!, symbol) + !(context.flags & NodeBuilderFlags.ForbidIndexedAccessSymbolReferences) && parent + && getMembersOfSymbol(parent) && getMembersOfSymbol(parent).get(symbol.escapedName) + && getSymbolIfSameReference(getMembersOfSymbol(parent).get(symbol.escapedName)!, symbol) ) { // Should use an indexed access const LHS = createAccessFromSymbolChain(chain, index - 1, stopper); if (isIndexedAccessTypeNode(LHS)) { - return factory.createIndexedAccessTypeNode(LHS, factory.createLiteralTypeNode(factory.createStringLiteral(symbolName))); + return factory.createIndexedAccessTypeNode( + LHS, + factory.createLiteralTypeNode(factory.createStringLiteral(symbolName)), + ); } else { - return factory.createIndexedAccessTypeNode(factory.createTypeReferenceNode(LHS, typeParameterNodes as readonly TypeNode[]), factory.createLiteralTypeNode(factory.createStringLiteral(symbolName))); + return factory.createIndexedAccessTypeNode( + factory.createTypeReferenceNode(LHS, typeParameterNodes as readonly TypeNode[]), + factory.createLiteralTypeNode(factory.createStringLiteral(symbolName)), + ); } } const identifier = setEmitFlags(factory.createIdentifier(symbolName), EmitFlags.NoAsciiEscaping); - if (typeParameterNodes) setIdentifierTypeArguments(identifier, factory.createNodeArray(typeParameterNodes)); + if (typeParameterNodes) { + setIdentifierTypeArguments( + identifier, + factory.createNodeArray(typeParameterNodes), + ); + } identifier.symbol = symbol; if (index > stopper) { @@ -8024,8 +10204,19 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } - function typeParameterShadowsNameInScope(escapedName: __String, context: NodeBuilderContext, type: TypeParameter) { - const result = resolveName(context.enclosingDeclaration, escapedName, SymbolFlags.Type, /*nameNotFoundMessage*/ undefined, escapedName, /*isUse*/ false); + function typeParameterShadowsNameInScope( + escapedName: __String, + context: NodeBuilderContext, + type: TypeParameter, + ) { + const result = resolveName( + context.enclosingDeclaration, + escapedName, + SymbolFlags.Type, + /*nameNotFoundMessage*/ undefined, + escapedName, + /*isUse*/ false, + ); if (result) { if (result.flags & SymbolFlags.TypeParameter && result === type.symbol) { return false; @@ -8050,7 +10241,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const rawtext = result.escapedText as string; let i = context.typeParameterNamesByTextNextNameCount?.get(rawtext) || 0; let text = rawtext; - while (context.typeParameterNamesByText?.has(text) || typeParameterShadowsNameInScope(text as __String, context, type)) { + while ( + context.typeParameterNamesByText?.has(text) + || typeParameterShadowsNameInScope(text as __String, context, type) + ) { i++; text = `${rawtext}_${i}`; } @@ -8068,9 +10262,24 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return result; } - function symbolToName(symbol: Symbol, context: NodeBuilderContext, meaning: SymbolFlags, expectsIdentifier: true): Identifier; - function symbolToName(symbol: Symbol, context: NodeBuilderContext, meaning: SymbolFlags, expectsIdentifier: false): EntityName; - function symbolToName(symbol: Symbol, context: NodeBuilderContext, meaning: SymbolFlags, expectsIdentifier: boolean): EntityName { + function symbolToName( + symbol: Symbol, + context: NodeBuilderContext, + meaning: SymbolFlags, + expectsIdentifier: true, + ): Identifier; + function symbolToName( + symbol: Symbol, + context: NodeBuilderContext, + meaning: SymbolFlags, + expectsIdentifier: false, + ): EntityName; + function symbolToName( + symbol: Symbol, + context: NodeBuilderContext, + meaning: SymbolFlags, + expectsIdentifier: boolean, + ): EntityName { const chain = lookupSymbolChain(symbol, context, meaning); if ( @@ -8095,10 +10304,17 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } const identifier = setEmitFlags(factory.createIdentifier(symbolName), EmitFlags.NoAsciiEscaping); - if (typeParameterNodes) setIdentifierTypeArguments(identifier, factory.createNodeArray(typeParameterNodes)); + if (typeParameterNodes) { + setIdentifierTypeArguments( + identifier, + factory.createNodeArray(typeParameterNodes), + ); + } identifier.symbol = symbol; - return index > 0 ? factory.createQualifiedName(createEntityNameFromSymbolChain(chain, index - 1), identifier) : identifier; + return index > 0 + ? factory.createQualifiedName(createEntityNameFromSymbolChain(chain, index - 1), identifier) + : identifier; } } @@ -8120,15 +10336,27 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } let firstChar = symbolName.charCodeAt(0); - if (isSingleOrDoubleQuote(firstChar) && some(symbol.declarations, hasNonGlobalAugmentationExternalModuleSymbol)) { + if ( + isSingleOrDoubleQuote(firstChar) + && some(symbol.declarations, hasNonGlobalAugmentationExternalModuleSymbol) + ) { return factory.createStringLiteral(getSpecifierForModuleSymbol(symbol, context)); } if (index === 0 || canUsePropertyAccess(symbolName, languageVersion)) { const identifier = setEmitFlags(factory.createIdentifier(symbolName), EmitFlags.NoAsciiEscaping); - if (typeParameterNodes) setIdentifierTypeArguments(identifier, factory.createNodeArray(typeParameterNodes)); + if (typeParameterNodes) { + setIdentifierTypeArguments( + identifier, + factory.createNodeArray(typeParameterNodes), + ); + } identifier.symbol = symbol; - return index > 0 ? factory.createPropertyAccessExpression(createExpressionFromSymbolChain(chain, index - 1), identifier) : identifier; + return index > 0 + ? factory.createPropertyAccessExpression( + createExpressionFromSymbolChain(chain, index - 1), + identifier, + ) : identifier; } else { if (firstChar === CharacterCodes.openBracket) { @@ -8137,18 +10365,32 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } let expression: Expression | undefined; if (isSingleOrDoubleQuote(firstChar) && !(symbol.flags & SymbolFlags.EnumMember)) { - expression = factory.createStringLiteral(stripQuotes(symbolName).replace(/\\./g, s => s.substring(1)), firstChar === CharacterCodes.singleQuote); + expression = factory.createStringLiteral( + stripQuotes(symbolName).replace(/\\./g, s => s.substring(1)), + firstChar === CharacterCodes.singleQuote, + ); } else if (("" + +symbolName) === symbolName) { expression = factory.createNumericLiteral(+symbolName); } if (!expression) { - const identifier = setEmitFlags(factory.createIdentifier(symbolName), EmitFlags.NoAsciiEscaping); - if (typeParameterNodes) setIdentifierTypeArguments(identifier, factory.createNodeArray(typeParameterNodes)); + const identifier = setEmitFlags( + factory.createIdentifier(symbolName), + EmitFlags.NoAsciiEscaping, + ); + if (typeParameterNodes) { + setIdentifierTypeArguments( + identifier, + factory.createNodeArray(typeParameterNodes), + ); + } identifier.symbol = symbol; expression = identifier; } - return factory.createElementAccessExpression(createExpressionFromSymbolChain(chain, index - 1), expression); + return factory.createElementAccessExpression( + createExpressionFromSymbolChain(chain, index - 1), + expression, + ); } } } @@ -8160,7 +10402,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function isSingleQuotedStringNamed(d: Declaration) { const name = getNameOfDeclaration(d); - return !!(name && isStringLiteral(name) && (name.singleQuote || !nodeIsSynthesized(name) && startsWith(getTextOfNode(name, /*includeTrivia*/ false), "'"))); + return !!(name && isStringLiteral(name) + && (name.singleQuote + || !nodeIsSynthesized(name) && startsWith(getTextOfNode(name, /*includeTrivia*/ false), "'"))); } function getPropertyNameNodeForSymbol(symbol: Symbol, context: NodeBuilderContext) { @@ -8171,25 +10415,45 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return fromNameType; } const rawName = unescapeLeadingUnderscores(symbol.escapedName); - return createPropertyNameNodeForIdentifierOrLiteral(rawName, getEmitScriptTarget(compilerOptions), singleQuote, stringNamed); + return createPropertyNameNodeForIdentifierOrLiteral( + rawName, + getEmitScriptTarget(compilerOptions), + singleQuote, + stringNamed, + ); } // See getNameForSymbolFromNameType for a stringy equivalent - function getPropertyNameNodeForSymbolFromNameType(symbol: Symbol, context: NodeBuilderContext, singleQuote?: boolean, stringNamed?: boolean) { + function getPropertyNameNodeForSymbolFromNameType( + symbol: Symbol, + context: NodeBuilderContext, + singleQuote?: boolean, + stringNamed?: boolean, + ) { const nameType = getSymbolLinks(symbol).nameType; if (nameType) { if (nameType.flags & TypeFlags.StringOrNumberLiteral) { const name = "" + (nameType as StringLiteralType | NumberLiteralType).value; - if (!isIdentifierText(name, getEmitScriptTarget(compilerOptions)) && (stringNamed || !isNumericLiteralName(name))) { + if ( + !isIdentifierText(name, getEmitScriptTarget(compilerOptions)) + && (stringNamed || !isNumericLiteralName(name)) + ) { return factory.createStringLiteral(name, !!singleQuote); } if (isNumericLiteralName(name) && startsWith(name, "-")) { - return factory.createComputedPropertyName(factory.createPrefixUnaryExpression(SyntaxKind.MinusToken, factory.createNumericLiteral(Math.abs(+name)))); + return factory.createComputedPropertyName( + factory.createPrefixUnaryExpression( + SyntaxKind.MinusToken, + factory.createNumericLiteral(Math.abs(+name)), + ), + ); } return createPropertyNameNodeForIdentifierOrLiteral(name, getEmitScriptTarget(compilerOptions)); } if (nameType.flags & TypeFlags.UniqueESSymbol) { - return factory.createComputedPropertyName(symbolToExpression((nameType as UniqueESSymbolType).symbol, context, SymbolFlags.Value)); + return factory.createComputedPropertyName( + symbolToExpression((nameType as UniqueESSymbolType).symbol, context, SymbolFlags.Value), + ); } } } @@ -8222,28 +10486,55 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function getDeclarationWithTypeAnnotation(symbol: Symbol, enclosingDeclaration: Node | undefined) { - return symbol.declarations && find(symbol.declarations, s => !!getEffectiveTypeAnnotationNode(s) && (!enclosingDeclaration || !!findAncestor(s, n => n === enclosingDeclaration))); + return symbol.declarations + && find( + symbol.declarations, + s => !!getEffectiveTypeAnnotationNode(s) + && (!enclosingDeclaration || !!findAncestor(s, n => n === enclosingDeclaration)), + ); } - function existingTypeNodeIsNotReferenceOrIsReferenceWithCompatibleTypeArgumentCount(existing: TypeNode, type: Type) { - return !(getObjectFlags(type) & ObjectFlags.Reference) || !isTypeReferenceNode(existing) || length(existing.typeArguments) >= getMinTypeArgumentCount((type as TypeReference).target.typeParameters); + function existingTypeNodeIsNotReferenceOrIsReferenceWithCompatibleTypeArgumentCount( + existing: TypeNode, + type: Type, + ) { + return !(getObjectFlags(type) & ObjectFlags.Reference) || !isTypeReferenceNode(existing) + || length(existing.typeArguments) + >= getMinTypeArgumentCount((type as TypeReference).target.typeParameters); } function getEnclosingDeclarationIgnoringFakeScope(enclosingDeclaration: Node) { - return getNodeLinks(enclosingDeclaration).fakeScopeForSignatureDeclaration ? enclosingDeclaration.parent : enclosingDeclaration; + return getNodeLinks(enclosingDeclaration).fakeScopeForSignatureDeclaration ? enclosingDeclaration.parent + : enclosingDeclaration; } /** * Unlike `typeToTypeNodeHelper`, this handles setting up the `AllowUniqueESSymbolType` flag * so a `unique symbol` is returned when appropriate for the input symbol, rather than `typeof sym` */ - function serializeTypeForDeclaration(context: NodeBuilderContext, type: Type, symbol: Symbol, enclosingDeclaration: Node | undefined, includePrivateSymbol?: (s: Symbol) => void, bundled?: boolean) { + function serializeTypeForDeclaration( + context: NodeBuilderContext, + type: Type, + symbol: Symbol, + enclosingDeclaration: Node | undefined, + includePrivateSymbol?: (s: Symbol) => void, + bundled?: boolean, + ) { if (!isErrorType(type) && enclosingDeclaration) { - const declWithExistingAnnotation = getDeclarationWithTypeAnnotation(symbol, getEnclosingDeclarationIgnoringFakeScope(enclosingDeclaration)); - if (declWithExistingAnnotation && !isFunctionLikeDeclaration(declWithExistingAnnotation) && !isGetAccessorDeclaration(declWithExistingAnnotation)) { + const declWithExistingAnnotation = getDeclarationWithTypeAnnotation( + symbol, + getEnclosingDeclarationIgnoringFakeScope(enclosingDeclaration), + ); + if ( + declWithExistingAnnotation && !isFunctionLikeDeclaration(declWithExistingAnnotation) + && !isGetAccessorDeclaration(declWithExistingAnnotation) + ) { // try to reuse the existing annotation const existing = getEffectiveTypeAnnotationNode(declWithExistingAnnotation)!; - if (typeNodeIsEquivalentToType(existing, declWithExistingAnnotation, type) && existingTypeNodeIsNotReferenceOrIsReferenceWithCompatibleTypeArgumentCount(existing, type)) { + if ( + typeNodeIsEquivalentToType(existing, declWithExistingAnnotation, type) + && existingTypeNodeIsNotReferenceOrIsReferenceWithCompatibleTypeArgumentCount(existing, type) + ) { const result = serializeExistingTypeNode(context, existing, includePrivateSymbol, bundled); if (result) { return result; @@ -8253,8 +10544,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } const oldFlags = context.flags; if ( - type.flags & TypeFlags.UniqueESSymbol && - type.symbol === symbol && (!context.enclosingDeclaration || some(symbol.declarations, d => getSourceFileOfNode(d) === getSourceFileOfNode(context.enclosingDeclaration!))) + type.flags & TypeFlags.UniqueESSymbol + && type.symbol === symbol + && (!context.enclosingDeclaration + || some( + symbol.declarations, + d => getSourceFileOfNode(d) === getSourceFileOfNode(context.enclosingDeclaration!), + )) ) { context.flags |= NodeBuilderFlags.AllowUniqueESSymbolType; } @@ -8274,14 +10570,27 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return false; } - function serializeReturnTypeForSignature(context: NodeBuilderContext, type: Type, signature: Signature, includePrivateSymbol?: (s: Symbol) => void, bundled?: boolean) { + function serializeReturnTypeForSignature( + context: NodeBuilderContext, + type: Type, + signature: Signature, + includePrivateSymbol?: (s: Symbol) => void, + bundled?: boolean, + ) { if (!isErrorType(type) && context.enclosingDeclaration) { const annotation = signature.declaration && getEffectiveReturnTypeNode(signature.declaration); - const enclosingDeclarationIgnoringFakeScope = getEnclosingDeclarationIgnoringFakeScope(context.enclosingDeclaration); + const enclosingDeclarationIgnoringFakeScope = getEnclosingDeclarationIgnoringFakeScope( + context.enclosingDeclaration, + ); if (!!findAncestor(annotation, n => n === enclosingDeclarationIgnoringFakeScope) && annotation) { const annotated = getTypeFromTypeNode(annotation); - const thisInstantiated = annotated.flags & TypeFlags.TypeParameter && (annotated as TypeParameter).isThisType ? instantiateType(annotated, signature.mapper) : annotated; - if (thisInstantiated === type && existingTypeNodeIsNotReferenceOrIsReferenceWithCompatibleTypeArgumentCount(annotation, type)) { + const thisInstantiated = + annotated.flags & TypeFlags.TypeParameter && (annotated as TypeParameter).isThisType + ? instantiateType(annotated, signature.mapper) : annotated; + if ( + thisInstantiated === type + && existingTypeNodeIsNotReferenceOrIsReferenceWithCompatibleTypeArgumentCount(annotation, type) + ) { const result = serializeExistingTypeNode(context, annotation, includePrivateSymbol, bundled); if (result) { return result; @@ -8292,16 +10601,32 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return typeToTypeNodeHelper(type, context); } - function trackExistingEntityName(node: T, context: NodeBuilderContext, includePrivateSymbol?: (s: Symbol) => void) { + function trackExistingEntityName( + node: T, + context: NodeBuilderContext, + includePrivateSymbol?: (s: Symbol) => void, + ) { let introducesError = false; const leftmost = getFirstIdentifier(node); - if (isInJSFile(node) && (isExportsIdentifier(leftmost) || isModuleExportsAccessExpression(leftmost.parent) || (isQualifiedName(leftmost.parent) && isModuleIdentifier(leftmost.parent.left) && isExportsIdentifier(leftmost.parent.right)))) { + if ( + isInJSFile(node) + && (isExportsIdentifier(leftmost) || isModuleExportsAccessExpression(leftmost.parent) + || (isQualifiedName(leftmost.parent) && isModuleIdentifier(leftmost.parent.left) + && isExportsIdentifier(leftmost.parent.right))) + ) { introducesError = true; return { introducesError, node }; } const sym = resolveEntityName(leftmost, SymbolFlags.All, /*ignoreErrors*/ true, /*dontResolveAlias*/ true); if (sym) { - if (isSymbolAccessible(sym, context.enclosingDeclaration, SymbolFlags.All, /*shouldComputeAliasesToMakeVisible*/ false).accessibility !== SymbolAccessibility.Accessible) { + if ( + isSymbolAccessible( + sym, + context.enclosingDeclaration, + SymbolFlags.All, + /*shouldComputeAliasesToMakeVisible*/ false, + ).accessibility !== SymbolAccessibility.Accessible + ) { introducesError = true; } else { @@ -8310,16 +10635,26 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } if (isIdentifier(node)) { const type = getDeclaredTypeOfSymbol(sym); - const name = sym.flags & SymbolFlags.TypeParameter && !isTypeSymbolAccessible(type.symbol, context.enclosingDeclaration) ? typeParameterToName(type, context) : factory.cloneNode(node); + const name = sym.flags & SymbolFlags.TypeParameter + && !isTypeSymbolAccessible(type.symbol, context.enclosingDeclaration) + ? typeParameterToName(type, context) : factory.cloneNode(node); name.symbol = sym; // for quickinfo, which uses identifier symbol information - return { introducesError, node: setEmitFlags(setOriginalNode(name, node), EmitFlags.NoAsciiEscaping) }; + return { + introducesError, + node: setEmitFlags(setOriginalNode(name, node), EmitFlags.NoAsciiEscaping), + }; } } return { introducesError, node }; } - function serializeExistingTypeNode(context: NodeBuilderContext, existing: TypeNode, includePrivateSymbol?: (s: Symbol) => void, bundled?: boolean) { + function serializeExistingTypeNode( + context: NodeBuilderContext, + existing: TypeNode, + includePrivateSymbol?: (s: Symbol) => void, + bundled?: boolean, + ) { if (cancellationToken && cancellationToken.throwIfCancellationRequested) { cancellationToken.throwIfCancellationRequested(); } @@ -8340,10 +10675,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return factory.createKeywordTypeNode(SyntaxKind.UnknownKeyword); } if (isJSDocNullableType(node)) { - return factory.createUnionTypeNode([visitNode(node.type, visitExistingNodeTreeSymbols, isTypeNode), factory.createLiteralTypeNode(factory.createNull())]); + return factory.createUnionTypeNode([ + visitNode(node.type, visitExistingNodeTreeSymbols, isTypeNode), + factory.createLiteralTypeNode(factory.createNull()), + ]); } if (isJSDocOptionalType(node)) { - return factory.createUnionTypeNode([visitNode(node.type, visitExistingNodeTreeSymbols, isTypeNode), factory.createKeywordTypeNode(SyntaxKind.UndefinedKeyword)]); + return factory.createUnionTypeNode([ + visitNode(node.type, visitExistingNodeTreeSymbols, isTypeNode), + factory.createKeywordTypeNode(SyntaxKind.UndefinedKeyword), + ]); } if (isJSDocNonNullableType(node)) { return visitNode(node.type, visitExistingNodeTreeSymbols); @@ -8355,13 +10696,19 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return factory.createTypeLiteralNode(map(node.jsDocPropertyTags, t => { const name = isIdentifier(t.name) ? t.name : t.name.right; const typeViaParent = getTypeOfPropertyOfType(getTypeFromTypeNode(node), name.escapedText); - const overrideTypeNode = typeViaParent && t.typeExpression && getTypeFromTypeNode(t.typeExpression.type) !== typeViaParent ? typeToTypeNodeHelper(typeViaParent, context) : undefined; + const overrideTypeNode = typeViaParent && t.typeExpression + && getTypeFromTypeNode(t.typeExpression.type) !== typeViaParent + ? typeToTypeNodeHelper(typeViaParent, context) : undefined; return factory.createPropertySignature( /*modifiers*/ undefined, name, - t.isBracketed || t.typeExpression && isJSDocOptionalType(t.typeExpression.type) ? factory.createToken(SyntaxKind.QuestionToken) : undefined, - overrideTypeNode || (t.typeExpression && visitNode(t.typeExpression.type, visitExistingNodeTreeSymbols, isTypeNode)) || factory.createKeywordTypeNode(SyntaxKind.AnyKeyword), + t.isBracketed || t.typeExpression && isJSDocOptionalType(t.typeExpression.type) + ? factory.createToken(SyntaxKind.QuestionToken) : undefined, + overrideTypeNode + || (t.typeExpression + && visitNode(t.typeExpression.type, visitExistingNodeTreeSymbols, isTypeNode)) + || factory.createKeywordTypeNode(SyntaxKind.AnyKeyword), ); })); } @@ -8387,16 +10734,21 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return factory.createConstructorTypeNode( /*modifiers*/ undefined, visitNodes(node.typeParameters, visitExistingNodeTreeSymbols, isTypeParameterDeclaration), - mapDefined(node.parameters, (p, i) => - p.name && isIdentifier(p.name) && p.name.escapedText === "new" ? (newTypeNode = p.type, undefined) : factory.createParameterDeclaration( - /*modifiers*/ undefined, - getEffectiveDotDotDotForParameter(p), - getNameForJSDocFunctionParameter(p, i), - p.questionToken, - visitNode(p.type, visitExistingNodeTreeSymbols, isTypeNode), - /*initializer*/ undefined, - )), - visitNode(newTypeNode || node.type, visitExistingNodeTreeSymbols, isTypeNode) || factory.createKeywordTypeNode(SyntaxKind.AnyKeyword), + mapDefined( + node.parameters, + (p, i) => + p.name && isIdentifier(p.name) && p.name.escapedText === "new" + ? (newTypeNode = p.type, undefined) : factory.createParameterDeclaration( + /*modifiers*/ undefined, + getEffectiveDotDotDotForParameter(p), + getNameForJSDocFunctionParameter(p, i), + p.questionToken, + visitNode(p.type, visitExistingNodeTreeSymbols, isTypeNode), + /*initializer*/ undefined, + ), + ), + visitNode(newTypeNode || node.type, visitExistingNodeTreeSymbols, isTypeNode) + || factory.createKeywordTypeNode(SyntaxKind.AnyKeyword), ); } else { @@ -8411,30 +10763,44 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { visitNode(p.type, visitExistingNodeTreeSymbols, isTypeNode), /*initializer*/ undefined, )), - visitNode(node.type, visitExistingNodeTreeSymbols, isTypeNode) || factory.createKeywordTypeNode(SyntaxKind.AnyKeyword), + visitNode(node.type, visitExistingNodeTreeSymbols, isTypeNode) + || factory.createKeywordTypeNode(SyntaxKind.AnyKeyword), ); } } - if (isTypeReferenceNode(node) && isInJSDoc(node) && (!existingTypeNodeIsNotReferenceOrIsReferenceWithCompatibleTypeArgumentCount(node, getTypeFromTypeNode(node)) || getIntendedTypeFromJSDocTypeReference(node) || unknownSymbol === resolveTypeReferenceName(node, SymbolFlags.Type, /*ignoreErrors*/ true))) { + if ( + isTypeReferenceNode(node) && isInJSDoc(node) + && (!existingTypeNodeIsNotReferenceOrIsReferenceWithCompatibleTypeArgumentCount( + node, + getTypeFromTypeNode(node), + ) || getIntendedTypeFromJSDocTypeReference(node) + || unknownSymbol === resolveTypeReferenceName(node, SymbolFlags.Type, /*ignoreErrors*/ true)) + ) { return setOriginalNode(typeToTypeNodeHelper(getTypeFromTypeNode(node), context), node); } if (isLiteralImportTypeNode(node)) { const nodeSymbol = getNodeLinks(node).resolvedSymbol; if ( - isInJSDoc(node) && - nodeSymbol && - ( + isInJSDoc(node) + && nodeSymbol + && ( // The import type resolved using jsdoc fallback logic - (!node.isTypeOf && !(nodeSymbol.flags & SymbolFlags.Type)) || + (!node.isTypeOf && !(nodeSymbol.flags & SymbolFlags.Type)) // The import type had type arguments autofilled by js fallback logic - !(length(node.typeArguments) >= getMinTypeArgumentCount(getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(nodeSymbol))) + || !(length(node.typeArguments) + >= getMinTypeArgumentCount( + getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(nodeSymbol), + )) ) ) { return setOriginalNode(typeToTypeNodeHelper(getTypeFromTypeNode(node), context), node); } return factory.updateImportTypeNode( node, - factory.updateLiteralTypeNode(node.argument, rewriteModuleSpecifier(node, node.argument.literal)), + factory.updateLiteralTypeNode( + node.argument, + rewriteModuleSpecifier(node, node.argument.literal), + ), node.assertions, node.qualifier, visitNodes(node.typeArguments, visitExistingNodeTreeSymbols, isTypeNode), @@ -8443,21 +10809,31 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } if (isEntityName(node) || isEntityNameExpression(node)) { - const { introducesError, node: result } = trackExistingEntityName(node, context, includePrivateSymbol); + const { introducesError, node: result } = trackExistingEntityName( + node, + context, + includePrivateSymbol, + ); hadError = hadError || introducesError; if (result !== node) { return result; } } - if (file && isTupleTypeNode(node) && (getLineAndCharacterOfPosition(file, node.pos).line === getLineAndCharacterOfPosition(file, node.end).line)) { + if ( + file && isTupleTypeNode(node) + && (getLineAndCharacterOfPosition(file, node.pos).line + === getLineAndCharacterOfPosition(file, node.end).line) + ) { setEmitFlags(node, EmitFlags.SingleLine); } return visitEachChild(node, visitExistingNodeTreeSymbols, nullTransformationContext); function getEffectiveDotDotDotForParameter(p: ParameterDeclaration) { - return p.dotDotDotToken || (p.type && isJSDocVariadicType(p.type) ? factory.createToken(SyntaxKind.DotDotDotToken) : undefined); + return p.dotDotDotToken + || (p.type && isJSDocVariadicType(p.type) ? factory.createToken(SyntaxKind.DotDotDotToken) + : undefined); } /** Note that `new:T` parameters are not handled, but should be before calling this function. */ @@ -8472,11 +10848,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (context.tracker && context.tracker.moduleResolverHost) { const targetFile = getExternalModuleFileFromDeclaration(parent); if (targetFile) { - const getCanonicalFileName = createGetCanonicalFileName(!!host.useCaseSensitiveFileNames); + const getCanonicalFileName = createGetCanonicalFileName( + !!host.useCaseSensitiveFileNames, + ); const resolverHost = { getCanonicalFileName, - getCurrentDirectory: () => context.tracker.moduleResolverHost!.getCurrentDirectory(), - getCommonSourceDirectory: () => context.tracker.moduleResolverHost!.getCommonSourceDirectory(), + getCurrentDirectory: () => + context.tracker.moduleResolverHost!.getCurrentDirectory(), + getCommonSourceDirectory: () => + context.tracker.moduleResolverHost!.getCommonSourceDirectory(), }; const newName = getResolvedExternalModuleName(resolverHost, targetFile); return factory.createStringLiteral(newName); @@ -8485,7 +10865,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } else { if (context.tracker && context.tracker.trackExternalModuleSymbolOfImportTypeNode) { - const moduleSym = resolveExternalModuleNameWorker(lit, lit, /*moduleNotFoundError*/ undefined); + const moduleSym = resolveExternalModuleNameWorker( + lit, + lit, + /*moduleNotFoundError*/ undefined, + ); if (moduleSym) { context.tracker.trackExternalModuleSymbolOfImportTypeNode(moduleSym); } @@ -8496,9 +10880,21 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } - function symbolTableToDeclarationStatements(symbolTable: SymbolTable, context: NodeBuilderContext, bundled?: boolean): Statement[] { - const serializePropertySymbolForClass = makeSerializePropertySymbol(factory.createPropertyDeclaration, SyntaxKind.MethodDeclaration, /*useAccessors*/ true); - const serializePropertySymbolForInterfaceWorker = makeSerializePropertySymbol((mods, name, question, type) => factory.createPropertySignature(mods, name, question, type), SyntaxKind.MethodSignature, /*useAccessors*/ false); + function symbolTableToDeclarationStatements( + symbolTable: SymbolTable, + context: NodeBuilderContext, + bundled?: boolean, + ): Statement[] { + const serializePropertySymbolForClass = makeSerializePropertySymbol( + factory.createPropertyDeclaration, + SyntaxKind.MethodDeclaration, + /*useAccessors*/ true, + ); + const serializePropertySymbolForInterfaceWorker = makeSerializePropertySymbol( + (mods, name, question, type) => factory.createPropertySignature(mods, name, question, type), + SyntaxKind.MethodSignature, + /*useAccessors*/ false, + ); // TODO: Use `setOriginalNode` on original declaration names where possible so these declarations see some kind of // declaration mapping @@ -8520,7 +10916,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const tracker: SymbolTracker = { ...oldcontext.tracker.inner, trackSymbol: (sym, decl, meaning) => { - const accessibleResult = isSymbolAccessible(sym, decl, meaning, /*shouldComputeAliasesToMakeVisible*/ false); + const accessibleResult = isSymbolAccessible( + sym, + decl, + meaning, + /*shouldComputeAliasesToMakeVisible*/ false, + ); if (accessibleResult.accessibility === SymbolAccessibility.Accessible) { // Lookup the root symbol of the chain of refs we'll use to access it and serialize it const chain = lookupSymbolChainWorker(sym, context, meaning); @@ -8556,7 +10957,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function getNamesOfDeclaration(statement: Statement): Identifier[] { if (isVariableStatement(statement)) { - return filter(map(statement.declarationList.declarations, getNameOfDeclaration), isIdentifierAndNotUndefined); + return filter( + map(statement.declarationList.declarations, getNameOfDeclaration), + isIdentifierAndNotUndefined, + ); } return filter([getNameOfDeclaration(statement as DeclarationStatement)], isIdentifierAndNotUndefined); } @@ -8566,13 +10970,17 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const nsIndex = findIndex(statements, isModuleDeclaration); let ns = nsIndex !== -1 ? statements[nsIndex] as ModuleDeclaration : undefined; if ( - ns && exportAssignment && exportAssignment.isExportEquals && - isIdentifier(exportAssignment.expression) && isIdentifier(ns.name) && idText(ns.name) === idText(exportAssignment.expression) && - ns.body && isModuleBlock(ns.body) + ns && exportAssignment && exportAssignment.isExportEquals + && isIdentifier(exportAssignment.expression) && isIdentifier(ns.name) + && idText(ns.name) === idText(exportAssignment.expression) + && ns.body && isModuleBlock(ns.body) ) { // Pass 0: Correct situations where a module has both an `export = ns` and multiple top-level exports by stripping the export modifiers from // the top-level exports and exporting them in the targeted ns, as can occur when a js file has both typedefs and `module.export` assignments - const excessExports = filter(statements, s => !!(getEffectiveModifierFlags(s) & ModifierFlags.Export)); + const excessExports = filter( + statements, + s => !!(getEffectiveModifierFlags(s) & ModifierFlags.Export), + ); const name = ns.name; let body = ns.body; if (length(excessExports)) { @@ -8587,7 +10995,17 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { factory.createExportDeclaration( /*modifiers*/ undefined, /*isTypeOnly*/ false, - factory.createNamedExports(map(flatMap(excessExports, e => getNamesOfDeclaration(e)), id => factory.createExportSpecifier(/*isTypeOnly*/ false, /*propertyName*/ undefined, id))), + factory.createNamedExports( + map( + flatMap(excessExports, e => getNamesOfDeclaration(e)), + id => + factory.createExportSpecifier( + /*isTypeOnly*/ false, + /*propertyName*/ undefined, + id, + ), + ), + ), /*moduleSpecifier*/ undefined, ), ]), @@ -8601,7 +11019,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { results = []; // If the namespace contains no export assignments or declarations, and no declarations flagged with `export`, then _everything_ is exported - // to respect this as the top level, we need to add an `export` modifier to everything - const mixinExportFlag = !some(body.statements, s => hasSyntacticModifier(s, ModifierFlags.Export) || isExportAssignment(s) || isExportDeclaration(s)); + const mixinExportFlag = !some( + body.statements, + s => hasSyntacticModifier(s, ModifierFlags.Export) || isExportAssignment(s) + || isExportDeclaration(s), + ); forEach(body.statements, s => { addResult(s, mixinExportFlag ? ModifierFlags.Export : ModifierFlags.None); // Recalculates the ambient (and export, if applicable from above) flag }); @@ -8613,23 +11035,39 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function mergeExportDeclarations(statements: Statement[]) { // Pass 2: Combine all `export {}` declarations - const exports = filter(statements, d => isExportDeclaration(d) && !d.moduleSpecifier && !!d.exportClause && isNamedExports(d.exportClause)) as ExportDeclaration[]; + const exports = filter( + statements, + d => isExportDeclaration(d) && !d.moduleSpecifier && !!d.exportClause + && isNamedExports(d.exportClause), + ) as ExportDeclaration[]; if (length(exports) > 1) { - const nonExports = filter(statements, d => !isExportDeclaration(d) || !!d.moduleSpecifier || !d.exportClause); + const nonExports = filter( + statements, + d => !isExportDeclaration(d) || !!d.moduleSpecifier || !d.exportClause, + ); statements = [ ...nonExports, factory.createExportDeclaration( /*modifiers*/ undefined, /*isTypeOnly*/ false, - factory.createNamedExports(flatMap(exports, e => cast(e.exportClause, isNamedExports).elements)), + factory.createNamedExports( + flatMap(exports, e => cast(e.exportClause, isNamedExports).elements), + ), /*moduleSpecifier*/ undefined, ), ]; } // Pass 2b: Also combine all `export {} from "..."` declarations as needed - const reexports = filter(statements, d => isExportDeclaration(d) && !!d.moduleSpecifier && !!d.exportClause && isNamedExports(d.exportClause)) as ExportDeclaration[]; + const reexports = filter( + statements, + d => isExportDeclaration(d) && !!d.moduleSpecifier && !!d.exportClause + && isNamedExports(d.exportClause), + ) as ExportDeclaration[]; if (length(reexports) > 1) { - const groups = group(reexports, decl => isStringLiteral(decl.moduleSpecifier!) ? ">" + decl.moduleSpecifier.text : ">"); + const groups = group( + reexports, + decl => isStringLiteral(decl.moduleSpecifier!) ? ">" + decl.moduleSpecifier.text : ">", + ); if (groups.length !== reexports.length) { for (const group of groups) { if (group.length > 1) { @@ -8639,7 +11077,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { factory.createExportDeclaration( /*modifiers*/ undefined, /*isTypeOnly*/ false, - factory.createNamedExports(flatMap(group, e => cast(e.exportClause, isNamedExports).elements)), + factory.createNamedExports( + flatMap(group, e => cast(e.exportClause, isNamedExports).elements), + ), group[0].moduleSpecifier, ), ]; @@ -8652,17 +11092,28 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function inlineExportModifiers(statements: Statement[]) { // Pass 3: Move all `export {}`'s to `export` modifiers where possible - const index = findIndex(statements, d => isExportDeclaration(d) && !d.moduleSpecifier && !d.assertClause && !!d.exportClause && isNamedExports(d.exportClause)); + const index = findIndex( + statements, + d => isExportDeclaration(d) && !d.moduleSpecifier && !d.assertClause && !!d.exportClause + && isNamedExports(d.exportClause), + ); if (index >= 0) { - const exportDecl = statements[index] as ExportDeclaration & { readonly exportClause: NamedExports; }; + const exportDecl = statements[index] as ExportDeclaration & { + readonly exportClause: NamedExports; + }; const replacements = mapDefined(exportDecl.exportClause.elements, e => { if (!e.propertyName) { // export {name} - look thru `statements` for `name`, and if all results can take an `export` modifier, do so and filter it const indices = indicesOf(statements); const associatedIndices = filter(indices, i => nodeHasName(statements[i], e.name)); - if (length(associatedIndices) && every(associatedIndices, i => canHaveExportModifier(statements[i]))) { + if ( + length(associatedIndices) + && every(associatedIndices, i => canHaveExportModifier(statements[i])) + ) { for (const index of associatedIndices) { - statements[index] = addExportModifier(statements[index] as Extract); + statements[index] = addExportModifier( + statements[index] as Extract, + ); } return undefined; } @@ -8699,9 +11150,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // Not a cleanup, but as a final step: If there is a mix of `export` and non-`export` declarations, but no `export =` or `export {}` add a `export {};` so // declaration privacy is respected. if ( - enclosingDeclaration && - ((isSourceFile(enclosingDeclaration) && isExternalOrCommonJsModule(enclosingDeclaration)) || isModuleDeclaration(enclosingDeclaration)) && - (!some(statements, isExternalModuleIndicator) || (!hasScopeMarker(statements) && some(statements, needsScopeMarker))) + enclosingDeclaration + && ((isSourceFile(enclosingDeclaration) && isExternalOrCommonJsModule(enclosingDeclaration)) + || isModuleDeclaration(enclosingDeclaration)) + && (!some(statements, isExternalModuleIndicator) + || (!hasScopeMarker(statements) && some(statements, needsScopeMarker))) ) { statements.push(createEmptyExports(factory)); } @@ -8718,7 +11171,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return factory.updateModifiers(node, flags); } - function visitSymbolTable(symbolTable: SymbolTable, suppressNewPrivateContext?: boolean, propertyAsAlias?: boolean) { + function visitSymbolTable( + symbolTable: SymbolTable, + suppressNewPrivateContext?: boolean, + propertyAsAlias?: boolean, + ) { if (!suppressNewPrivateContext) { deferredPrivatesStack.push(new Map()); } @@ -8746,7 +11203,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { visitedSymbols.add(getSymbolId(visitedSym)); // Only actually serialize symbols within the correct enclosing declaration, otherwise do nothing with the out-of-context symbol const skipMembershipCheck = !isPrivate; // We only call this on exported symbols when we know they're in the correct scope - if (skipMembershipCheck || (!!length(symbol.declarations) && some(symbol.declarations, d => !!findAncestor(d, n => n === enclosingDeclaration)))) { + if ( + skipMembershipCheck + || (!!length(symbol.declarations) + && some(symbol.declarations, d => !!findAncestor(d, n => n === enclosingDeclaration))) + ) { const oldContext = context; context = cloneNodeBuilderContext(context); serializeSymbolWorker(symbol, isPrivate, propertyAsAlias); @@ -8769,7 +11230,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function serializeSymbolWorker(symbol: Symbol, isPrivate: boolean, propertyAsAlias: boolean): void { const symbolName = unescapeLeadingUnderscores(symbol.escapedName); const isDefault = symbol.escapedName === InternalSymbolName.Default; - if (isPrivate && !(context.flags & NodeBuilderFlags.AllowAnonymousIdentifier) && isStringANonContextualKeyword(symbolName) && !isDefault) { + if ( + isPrivate && !(context.flags & NodeBuilderFlags.AllowAnonymousIdentifier) + && isStringANonContextualKeyword(symbolName) && !isDefault + ) { // Oh no. We cannot use this symbol's name as it's name... It's likely some jsdoc had an invalid name like `export` or `default` :( context.encounteredError = true; // TODO: Issue error via symbol tracker? @@ -8779,18 +11243,30 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { symbol.flags & SymbolFlags.ExportDoesNotSupportDefaultModifier || (symbol.flags & SymbolFlags.Function && length(getPropertiesOfType(getTypeOfSymbol(symbol)))) ) && !(symbol.flags & SymbolFlags.Alias); // An alias symbol should preclude needing to make an alias ourselves - let needsExportDeclaration = !needsPostExportDefault && !isPrivate && isStringANonContextualKeyword(symbolName) && !isDefault; + let needsExportDeclaration = !needsPostExportDefault && !isPrivate + && isStringANonContextualKeyword(symbolName) && !isDefault; // `serializeVariableOrProperty` will handle adding the export declaration if it is run (since `getInternalSymbolName` will create the name mapping), so we need to ensuer we unset `needsExportDeclaration` if it is if (needsPostExportDefault || needsExportDeclaration) { isPrivate = true; } - const modifierFlags = (!isPrivate ? ModifierFlags.Export : 0) | (isDefault && !needsPostExportDefault ? ModifierFlags.Default : 0); - const isConstMergedWithNS = symbol.flags & SymbolFlags.Module && - symbol.flags & (SymbolFlags.BlockScopedVariable | SymbolFlags.FunctionScopedVariable | SymbolFlags.Property) && - symbol.escapedName !== InternalSymbolName.ExportEquals; - const isConstMergedWithNSPrintableAsSignatureMerge = isConstMergedWithNS && isTypeRepresentableAsFunctionNamespaceMerge(getTypeOfSymbol(symbol), symbol); - if (symbol.flags & (SymbolFlags.Function | SymbolFlags.Method) || isConstMergedWithNSPrintableAsSignatureMerge) { - serializeAsFunctionNamespaceMerge(getTypeOfSymbol(symbol), symbol, getInternalSymbolName(symbol, symbolName), modifierFlags); + const modifierFlags = (!isPrivate ? ModifierFlags.Export : 0) + | (isDefault && !needsPostExportDefault ? ModifierFlags.Default : 0); + const isConstMergedWithNS = symbol.flags & SymbolFlags.Module + && symbol.flags + & (SymbolFlags.BlockScopedVariable | SymbolFlags.FunctionScopedVariable | SymbolFlags.Property) + && symbol.escapedName !== InternalSymbolName.ExportEquals; + const isConstMergedWithNSPrintableAsSignatureMerge = isConstMergedWithNS + && isTypeRepresentableAsFunctionNamespaceMerge(getTypeOfSymbol(symbol), symbol); + if ( + symbol.flags & (SymbolFlags.Function | SymbolFlags.Method) + || isConstMergedWithNSPrintableAsSignatureMerge + ) { + serializeAsFunctionNamespaceMerge( + getTypeOfSymbol(symbol), + symbol, + getInternalSymbolName(symbol, symbolName), + modifierFlags, + ); } if (symbol.flags & SymbolFlags.TypeAlias) { serializeTypeAlias(symbol, symbolName, modifierFlags); @@ -8798,7 +11274,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // Need to skip over export= symbols below - json source files get a single `Property` flagged // symbol of name `export=` which needs to be handled like an alias. It's not great, but it is what it is. if ( - symbol.flags & (SymbolFlags.BlockScopedVariable | SymbolFlags.FunctionScopedVariable | SymbolFlags.Property | SymbolFlags.Accessor) + symbol.flags + & (SymbolFlags.BlockScopedVariable | SymbolFlags.FunctionScopedVariable | SymbolFlags.Property + | SymbolFlags.Accessor) && symbol.escapedName !== InternalSymbolName.ExportEquals && !(symbol.flags & SymbolFlags.Prototype) && !(symbol.flags & SymbolFlags.Class) @@ -8815,7 +11293,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { else { const type = getTypeOfSymbol(symbol); const localName = getInternalSymbolName(symbol, symbolName); - if (!(symbol.flags & SymbolFlags.Function) && isTypeRepresentableAsFunctionNamespaceMerge(type, symbol)) { + if ( + !(symbol.flags & SymbolFlags.Function) + && isTypeRepresentableAsFunctionNamespaceMerge(type, symbol) + ) { // If the type looks like a function declaration + ns could represent it, and it's type is sourced locally, rewrite it into a function declaration + ns serializeAsFunctionNamespaceMerge(type, symbol, localName, modifierFlags); } @@ -8829,38 +11310,65 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { : isConstantVariable(symbol) ? NodeFlags.Const : NodeFlags.Let; - const name = (needsPostExportDefault || !(symbol.flags & SymbolFlags.Property)) ? localName : getUnusedName(localName, symbol); - let textRange: Node | undefined = symbol.declarations && find(symbol.declarations, d => isVariableDeclaration(d)); - if (textRange && isVariableDeclarationList(textRange.parent) && textRange.parent.declarations.length === 1) { + const name = (needsPostExportDefault || !(symbol.flags & SymbolFlags.Property)) ? localName + : getUnusedName(localName, symbol); + let textRange: Node | undefined = symbol.declarations + && find(symbol.declarations, d => isVariableDeclaration(d)); + if ( + textRange && isVariableDeclarationList(textRange.parent) + && textRange.parent.declarations.length === 1 + ) { textRange = textRange.parent.parent; } const propertyAccessRequire = symbol.declarations?.find(isPropertyAccessExpression); if ( - propertyAccessRequire && isBinaryExpression(propertyAccessRequire.parent) && isIdentifier(propertyAccessRequire.parent.right) + propertyAccessRequire && isBinaryExpression(propertyAccessRequire.parent) + && isIdentifier(propertyAccessRequire.parent.right) && type.symbol?.valueDeclaration && isSourceFile(type.symbol.valueDeclaration) ) { - const alias = localName === propertyAccessRequire.parent.right.escapedText ? undefined : propertyAccessRequire.parent.right; + const alias = localName === propertyAccessRequire.parent.right.escapedText ? undefined + : propertyAccessRequire.parent.right; addResult( factory.createExportDeclaration( /*modifiers*/ undefined, /*isTypeOnly*/ false, - factory.createNamedExports([factory.createExportSpecifier(/*isTypeOnly*/ false, alias, localName)]), + factory.createNamedExports([ + factory.createExportSpecifier(/*isTypeOnly*/ false, alias, localName), + ]), ), ModifierFlags.None, ); - context.tracker.trackSymbol(type.symbol, context.enclosingDeclaration, SymbolFlags.Value); + context.tracker.trackSymbol( + type.symbol, + context.enclosingDeclaration, + SymbolFlags.Value, + ); } else { const statement = setTextRange( factory.createVariableStatement( /*modifiers*/ undefined, factory.createVariableDeclarationList([ - factory.createVariableDeclaration(name, /*exclamationToken*/ undefined, serializeTypeForDeclaration(context, type, symbol, enclosingDeclaration, includePrivateSymbol, bundled)), + factory.createVariableDeclaration( + name, + /*exclamationToken*/ undefined, + serializeTypeForDeclaration( + context, + type, + symbol, + enclosingDeclaration, + includePrivateSymbol, + bundled, + ), + ), ], flags), ), textRange, ); - addResult(statement, name !== localName ? modifierFlags & ~ModifierFlags.Export : modifierFlags); + addResult( + statement, + name !== localName ? modifierFlags & ~ModifierFlags.Export : modifierFlags, + ); if (name !== localName && !isPrivate) { // We rename the variable declaration we generate for Property symbols since they may have a name which // conflicts with a local declaration. For example, given input: @@ -8887,7 +11395,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { factory.createExportDeclaration( /*modifiers*/ undefined, /*isTypeOnly*/ false, - factory.createNamedExports([factory.createExportSpecifier(/*isTypeOnly*/ false, name, localName)]), + factory.createNamedExports([ + factory.createExportSpecifier(/*isTypeOnly*/ false, name, localName), + ]), ), ModifierFlags.None, ); @@ -8917,7 +11427,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { serializeAsClass(symbol, getInternalSymbolName(symbol, symbolName), modifierFlags); } } - if ((symbol.flags & (SymbolFlags.ValueModule | SymbolFlags.NamespaceModule) && (!isConstMergedWithNS || isTypeOnlyNamespace(symbol))) || isConstMergedWithNSPrintableAsSignatureMerge) { + if ( + (symbol.flags & (SymbolFlags.ValueModule | SymbolFlags.NamespaceModule) + && (!isConstMergedWithNS || isTypeOnlyNamespace(symbol))) + || isConstMergedWithNSPrintableAsSignatureMerge + ) { serializeModule(symbol, symbolName, modifierFlags); } // The class meaning serialization should handle serializing all interface members @@ -8935,21 +11449,45 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // Straightforward - only one thing to do - make an export declaration if (symbol.declarations) { for (const node of symbol.declarations) { - const resolvedModule = resolveExternalModuleName(node, (node as ExportDeclaration).moduleSpecifier!); + const resolvedModule = resolveExternalModuleName( + node, + (node as ExportDeclaration).moduleSpecifier!, + ); if (!resolvedModule) continue; - addResult(factory.createExportDeclaration(/*modifiers*/ undefined, /*isTypeOnly*/ (node as ExportDeclaration).isTypeOnly, /*exportClause*/ undefined, factory.createStringLiteral(getSpecifierForModuleSymbol(resolvedModule, context))), ModifierFlags.None); + addResult( + factory.createExportDeclaration( + /*modifiers*/ undefined, + /*isTypeOnly*/ (node as ExportDeclaration).isTypeOnly, + /*exportClause*/ undefined, + factory.createStringLiteral(getSpecifierForModuleSymbol(resolvedModule, context)), + ), + ModifierFlags.None, + ); } } } if (needsPostExportDefault) { - addResult(factory.createExportAssignment(/*modifiers*/ undefined, /*isExportEquals*/ false, factory.createIdentifier(getInternalSymbolName(symbol, symbolName))), ModifierFlags.None); + addResult( + factory.createExportAssignment( + /*modifiers*/ undefined, + /*isExportEquals*/ false, + factory.createIdentifier(getInternalSymbolName(symbol, symbolName)), + ), + ModifierFlags.None, + ); } else if (needsExportDeclaration) { addResult( factory.createExportDeclaration( /*modifiers*/ undefined, /*isTypeOnly*/ false, - factory.createNamedExports([factory.createExportSpecifier(/*isTypeOnly*/ false, getInternalSymbolName(symbol, symbolName), symbolName)]), + factory.createNamedExports([ + factory.createExportSpecifier( + /*isTypeOnly*/ false, + getInternalSymbolName(symbol, symbolName), + symbolName, + ), + ]), ), ModifierFlags.None, ); @@ -8965,41 +11503,52 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // will throw a wrench in this, since those may have been nested, but we'll need to synthesize them in the outer scope // anyway, as that's the only place the import they translate to is valid. In such a case, we might need to use a unique name // for the moved import; which hopefully the above `getUnusedName` call should produce. - const isExternalImportAlias = !!(symbol.flags & SymbolFlags.Alias) && !some(symbol.declarations, d => - !!findAncestor(d, isExportDeclaration) || - isNamespaceExport(d) || - (isImportEqualsDeclaration(d) && !isExternalModuleReference(d.moduleReference))); - deferredPrivatesStack[isExternalImportAlias ? 0 : (deferredPrivatesStack.length - 1)].set(getSymbolId(symbol), symbol); + const isExternalImportAlias = !!(symbol.flags & SymbolFlags.Alias) + && !some(symbol.declarations, d => + !!findAncestor(d, isExportDeclaration) + || isNamespaceExport(d) + || (isImportEqualsDeclaration(d) && !isExternalModuleReference(d.moduleReference))); + deferredPrivatesStack[isExternalImportAlias ? 0 : (deferredPrivatesStack.length - 1)].set( + getSymbolId(symbol), + symbol, + ); } function isExportingScope(enclosingDeclaration: Node) { - return ((isSourceFile(enclosingDeclaration) && (isExternalOrCommonJsModule(enclosingDeclaration) || isJsonSourceFile(enclosingDeclaration))) || - (isAmbientModule(enclosingDeclaration) && !isGlobalScopeAugmentation(enclosingDeclaration))); + return ((isSourceFile(enclosingDeclaration) + && (isExternalOrCommonJsModule(enclosingDeclaration) || isJsonSourceFile(enclosingDeclaration))) + || (isAmbientModule(enclosingDeclaration) && !isGlobalScopeAugmentation(enclosingDeclaration))); } // Prepends a `declare` and/or `export` modifier if the context requires it, and then adds `node` to `result` and returns `node` function addResult(node: Statement, additionalModifierFlags: ModifierFlags) { if (canHaveModifiers(node)) { let newModifierFlags: ModifierFlags = ModifierFlags.None; - const enclosingDeclaration = context.enclosingDeclaration && - (isJSDocTypeAlias(context.enclosingDeclaration) ? getSourceFileOfNode(context.enclosingDeclaration) : context.enclosingDeclaration); + const enclosingDeclaration = context.enclosingDeclaration + && (isJSDocTypeAlias(context.enclosingDeclaration) + ? getSourceFileOfNode(context.enclosingDeclaration) : context.enclosingDeclaration); if ( - additionalModifierFlags & ModifierFlags.Export && - enclosingDeclaration && (isExportingScope(enclosingDeclaration) || isModuleDeclaration(enclosingDeclaration)) && - canHaveExportModifier(node) + additionalModifierFlags & ModifierFlags.Export + && enclosingDeclaration + && (isExportingScope(enclosingDeclaration) || isModuleDeclaration(enclosingDeclaration)) + && canHaveExportModifier(node) ) { // Classes, namespaces, variables, functions, interfaces, and types should all be `export`ed in a module context if not private newModifierFlags |= ModifierFlags.Export; } if ( - addingDeclare && !(newModifierFlags & ModifierFlags.Export) && - (!enclosingDeclaration || !(enclosingDeclaration.flags & NodeFlags.Ambient)) && - (isEnumDeclaration(node) || isVariableStatement(node) || isFunctionDeclaration(node) || isClassDeclaration(node) || isModuleDeclaration(node)) + addingDeclare && !(newModifierFlags & ModifierFlags.Export) + && (!enclosingDeclaration || !(enclosingDeclaration.flags & NodeFlags.Ambient)) + && (isEnumDeclaration(node) || isVariableStatement(node) || isFunctionDeclaration(node) + || isClassDeclaration(node) || isModuleDeclaration(node)) ) { // Classes, namespaces, variables, enums, and functions all need `declare` modifiers to be valid in a declaration file top-level scope newModifierFlags |= ModifierFlags.Ambient; } - if ((additionalModifierFlags & ModifierFlags.Default) && (isClassDeclaration(node) || isInterfaceDeclaration(node) || isFunctionDeclaration(node))) { + if ( + (additionalModifierFlags & ModifierFlags.Default) + && (isClassDeclaration(node) || isInterfaceDeclaration(node) || isFunctionDeclaration(node)) + ) { newModifierFlags |= ModifierFlags.Default; } if (newModifierFlags) { @@ -9014,19 +11563,38 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const typeParams = getSymbolLinks(symbol).typeParameters; const typeParamDecls = map(typeParams, p => typeParameterToDeclaration(p, context)); const jsdocAliasDecl = symbol.declarations?.find(isJSDocTypeAlias); - const commentText = getTextOfJSDocComment(jsdocAliasDecl ? jsdocAliasDecl.comment || jsdocAliasDecl.parent.comment : undefined); + const commentText = getTextOfJSDocComment( + jsdocAliasDecl ? jsdocAliasDecl.comment || jsdocAliasDecl.parent.comment : undefined, + ); const oldFlags = context.flags; context.flags |= NodeBuilderFlags.InTypeAlias; const oldEnclosingDecl = context.enclosingDeclaration; context.enclosingDeclaration = jsdocAliasDecl; const typeNode = jsdocAliasDecl && jsdocAliasDecl.typeExpression && isJSDocTypeExpression(jsdocAliasDecl.typeExpression) - && serializeExistingTypeNode(context, jsdocAliasDecl.typeExpression.type, includePrivateSymbol, bundled) + && serializeExistingTypeNode( + context, + jsdocAliasDecl.typeExpression.type, + includePrivateSymbol, + bundled, + ) || typeToTypeNodeHelper(aliasType, context); addResult( setSyntheticLeadingComments( - factory.createTypeAliasDeclaration(/*modifiers*/ undefined, getInternalSymbolName(symbol, symbolName), typeParamDecls, typeNode), - !commentText ? [] : [{ kind: SyntaxKind.MultiLineCommentTrivia, text: "*\n * " + commentText.replace(/\n/g, "\n * ") + "\n ", pos: -1, end: -1, hasTrailingNewLine: true }], + factory.createTypeAliasDeclaration( + /*modifiers*/ undefined, + getInternalSymbolName(symbol, symbolName), + typeParamDecls, + typeNode, + ), + !commentText ? [] + : [{ + kind: SyntaxKind.MultiLineCommentTrivia, + text: "*\n * " + commentText.replace(/\n/g, "\n * ") + "\n ", + pos: -1, + end: -1, + hasTrailingNewLine: true, + }], ), modifierFlags, ); @@ -9040,12 +11608,29 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const typeParamDecls = map(localParams, p => typeParameterToDeclaration(p, context)); const baseTypes = getBaseTypes(interfaceType); const baseType = length(baseTypes) ? getIntersectionType(baseTypes) : undefined; - const members = flatMap(getPropertiesOfType(interfaceType), p => serializePropertySymbolForInterface(p, baseType)); - const callSignatures = serializeSignatures(SignatureKind.Call, interfaceType, baseType, SyntaxKind.CallSignature) as CallSignatureDeclaration[]; - const constructSignatures = serializeSignatures(SignatureKind.Construct, interfaceType, baseType, SyntaxKind.ConstructSignature) as ConstructSignatureDeclaration[]; + const members = flatMap( + getPropertiesOfType(interfaceType), + p => serializePropertySymbolForInterface(p, baseType), + ); + const callSignatures = serializeSignatures( + SignatureKind.Call, + interfaceType, + baseType, + SyntaxKind.CallSignature, + ) as CallSignatureDeclaration[]; + const constructSignatures = serializeSignatures( + SignatureKind.Construct, + interfaceType, + baseType, + SyntaxKind.ConstructSignature, + ) as ConstructSignatureDeclaration[]; const indexSignatures = serializeIndexSignatures(interfaceType, baseType); - const heritageClauses = !length(baseTypes) ? undefined : [factory.createHeritageClause(SyntaxKind.ExtendsKeyword, mapDefined(baseTypes, b => trySerializeAsTypeReference(b, SymbolFlags.Value)))]; + const heritageClauses = !length(baseTypes) ? undefined + : [factory.createHeritageClause( + SyntaxKind.ExtendsKeyword, + mapDefined(baseTypes, b => trySerializeAsTypeReference(b, SymbolFlags.Value)), + )]; addResult( factory.createInterfaceDeclaration( /*modifiers*/ undefined, @@ -9060,11 +11645,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function getNamespaceMembersForSerialization(symbol: Symbol) { const exports = getExportsOfSymbol(symbol); - return !exports ? [] : filter(arrayFrom(exports.values()), m => isNamespaceMember(m) && isIdentifierText(m.escapedName as string, ScriptTarget.ESNext)); + return !exports ? [] + : filter( + arrayFrom(exports.values()), + m => isNamespaceMember(m) && isIdentifierText(m.escapedName as string, ScriptTarget.ESNext), + ); } function isTypeOnlyNamespace(symbol: Symbol) { - return every(getNamespaceMembersForSerialization(symbol), m => !(getSymbolFlags(resolveSymbol(m)) & SymbolFlags.Value)); + return every( + getNamespaceMembersForSerialization(symbol), + m => !(getSymbolFlags(resolveSymbol(m)) & SymbolFlags.Value), + ); } function serializeModule(symbol: Symbol, symbolName: string, modifierFlags: ModifierFlags) { @@ -9078,7 +11670,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // so we don't even have placeholders to fill in. if (length(realMembers)) { const localName = getInternalSymbolName(symbol, symbolName); - serializeAsNamespaceDeclaration(realMembers, localName, modifierFlags, !!(symbol.flags & (SymbolFlags.Function | SymbolFlags.Assignment))); + serializeAsNamespaceDeclaration( + realMembers, + localName, + modifierFlags, + !!(symbol.flags & (SymbolFlags.Function | SymbolFlags.Assignment)), + ); } if (length(mergedMembers)) { const containingFile = getSourceFileOfNode(context.enclosingDeclaration); @@ -9086,19 +11683,35 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const nsBody = factory.createModuleBlock([factory.createExportDeclaration( /*modifiers*/ undefined, /*isTypeOnly*/ false, - factory.createNamedExports(mapDefined(filter(mergedMembers, n => n.escapedName !== InternalSymbolName.ExportEquals), s => { - const name = unescapeLeadingUnderscores(s.escapedName); - const localName = getInternalSymbolName(s, name); - const aliasDecl = s.declarations && getDeclarationOfAliasSymbol(s); - if (containingFile && (aliasDecl ? containingFile !== getSourceFileOfNode(aliasDecl) : !some(s.declarations, d => getSourceFileOfNode(d) === containingFile))) { - context.tracker?.reportNonlocalAugmentation?.(containingFile, symbol, s); - return undefined; - } - const target = aliasDecl && getTargetOfAliasDeclaration(aliasDecl, /*dontRecursivelyResolve*/ true); - includePrivateSymbol(target || s); - const targetName = target ? getInternalSymbolName(target, unescapeLeadingUnderscores(target.escapedName)) : localName; - return factory.createExportSpecifier(/*isTypeOnly*/ false, name === targetName ? undefined : targetName, name); - })), + factory.createNamedExports( + mapDefined( + filter(mergedMembers, n => n.escapedName !== InternalSymbolName.ExportEquals), + s => { + const name = unescapeLeadingUnderscores(s.escapedName); + const localName = getInternalSymbolName(s, name); + const aliasDecl = s.declarations && getDeclarationOfAliasSymbol(s); + if ( + containingFile + && (aliasDecl ? containingFile !== getSourceFileOfNode(aliasDecl) + : !some(s.declarations, d => getSourceFileOfNode(d) === containingFile)) + ) { + context.tracker?.reportNonlocalAugmentation?.(containingFile, symbol, s); + return undefined; + } + const target = aliasDecl + && getTargetOfAliasDeclaration(aliasDecl, /*dontRecursivelyResolve*/ true); + includePrivateSymbol(target || s); + const targetName = target + ? getInternalSymbolName(target, unescapeLeadingUnderscores(target.escapedName)) + : localName; + return factory.createExportSpecifier( + /*isTypeOnly*/ false, + name === targetName ? undefined : targetName, + name, + ); + }, + ), + ), )]); addResult( factory.createModuleDeclaration( @@ -9117,41 +11730,71 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { factory.createEnumDeclaration( factory.createModifiersFromModifierFlags(isConstEnumSymbol(symbol) ? ModifierFlags.Const : 0), getInternalSymbolName(symbol, symbolName), - map(filter(getPropertiesOfType(getTypeOfSymbol(symbol)), p => !!(p.flags & SymbolFlags.EnumMember)), p => { - // TODO: Handle computed names - // I hate that to get the initialized value we need to walk back to the declarations here; but there's no - // other way to get the possible const value of an enum member that I'm aware of, as the value is cached - // _on the declaration_, not on the declaration's symbol... - const initializedValue = p.declarations && p.declarations[0] && isEnumMember(p.declarations[0]) ? getConstantValue(p.declarations[0]) : undefined; - return factory.createEnumMember( - unescapeLeadingUnderscores(p.escapedName), - initializedValue === undefined ? undefined : - typeof initializedValue === "string" ? factory.createStringLiteral(initializedValue) : - factory.createNumericLiteral(initializedValue), - ); - }), + map( + filter( + getPropertiesOfType(getTypeOfSymbol(symbol)), + p => !!(p.flags & SymbolFlags.EnumMember), + ), + p => { + // TODO: Handle computed names + // I hate that to get the initialized value we need to walk back to the declarations here; but there's no + // other way to get the possible const value of an enum member that I'm aware of, as the value is cached + // _on the declaration_, not on the declaration's symbol... + const initializedValue = + p.declarations && p.declarations[0] && isEnumMember(p.declarations[0]) + ? getConstantValue(p.declarations[0]) : undefined; + return factory.createEnumMember( + unescapeLeadingUnderscores(p.escapedName), + initializedValue === undefined ? undefined + : typeof initializedValue === "string" + ? factory.createStringLiteral(initializedValue) + : factory.createNumericLiteral(initializedValue), + ); + }, + ), ), modifierFlags, ); } - function serializeAsFunctionNamespaceMerge(type: Type, symbol: Symbol, localName: string, modifierFlags: ModifierFlags) { + function serializeAsFunctionNamespaceMerge( + type: Type, + symbol: Symbol, + localName: string, + modifierFlags: ModifierFlags, + ) { const signatures = getSignaturesOfType(type, SignatureKind.Call); for (const sig of signatures) { // Each overload becomes a separate function declaration, in order - const decl = signatureToSignatureDeclarationHelper(sig, SyntaxKind.FunctionDeclaration, context, { name: factory.createIdentifier(localName), privateSymbolVisitor: includePrivateSymbol, bundledImports: bundled }) as FunctionDeclaration; + const decl = signatureToSignatureDeclarationHelper(sig, SyntaxKind.FunctionDeclaration, context, { + name: factory.createIdentifier(localName), + privateSymbolVisitor: includePrivateSymbol, + bundledImports: bundled, + }) as FunctionDeclaration; addResult(setTextRange(decl, getSignatureTextRangeLocation(sig)), modifierFlags); } // Module symbol emit will take care of module-y members, provided it has exports - if (!(symbol.flags & (SymbolFlags.ValueModule | SymbolFlags.NamespaceModule) && !!symbol.exports && !!symbol.exports.size)) { + if ( + !(symbol.flags & (SymbolFlags.ValueModule | SymbolFlags.NamespaceModule) && !!symbol.exports + && !!symbol.exports.size) + ) { const props = filter(getPropertiesOfType(type), isNamespaceMember); - serializeAsNamespaceDeclaration(props, localName, modifierFlags, /*suppressNewPrivateContext*/ true); + serializeAsNamespaceDeclaration( + props, + localName, + modifierFlags, + /*suppressNewPrivateContext*/ true, + ); } } function getSignatureTextRangeLocation(signature: Signature) { if (signature.declaration && signature.declaration.parent) { - if (isBinaryExpression(signature.declaration.parent) && getAssignmentDeclarationKind(signature.declaration.parent) === AssignmentDeclarationKind.Property) { + if ( + isBinaryExpression(signature.declaration.parent) + && getAssignmentDeclarationKind(signature.declaration.parent) + === AssignmentDeclarationKind.Property + ) { return signature.declaration.parent; } // for expressions assigned to `var`s, use the `var` as the text range @@ -9162,9 +11805,22 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return signature.declaration; } - function serializeAsNamespaceDeclaration(props: readonly Symbol[], localName: string, modifierFlags: ModifierFlags, suppressNewPrivateContext: boolean) { + function serializeAsNamespaceDeclaration( + props: readonly Symbol[], + localName: string, + modifierFlags: ModifierFlags, + suppressNewPrivateContext: boolean, + ) { if (length(props)) { - const localVsRemoteMap = arrayToMultiMap(props, p => !length(p.declarations) || some(p.declarations, d => getSourceFileOfNode(d) === getSourceFileOfNode(context.enclosingDeclaration!)) ? "local" : "remote"); + const localVsRemoteMap = arrayToMultiMap( + props, + p => !length(p.declarations) + || some( + p.declarations, + d => getSourceFileOfNode(d) === getSourceFileOfNode(context.enclosingDeclaration!), + ) ? "local" + : "remote", + ); const localProps = localVsRemoteMap.get("local") || emptyArray; // handle remote props first - we need to make an `import` declaration that points at the module containing each remote // prop in the outermost scope (TODO: a namespace within a namespace would need to be appropriately handled by this) @@ -9183,7 +11839,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // Add a namespace // Create namespace as non-synthetic so it is usable as an enclosing declaration - let fakespace = parseNodeFactory.createModuleDeclaration(/*modifiers*/ undefined, factory.createIdentifier(localName), factory.createModuleBlock([]), NodeFlags.Namespace); + let fakespace = parseNodeFactory.createModuleDeclaration( + /*modifiers*/ undefined, + factory.createIdentifier(localName), + factory.createModuleBlock([]), + NodeFlags.Namespace, + ); setParent(fakespace, enclosingDeclaration as SourceFile | NamespaceDeclaration); fakespace.locals = createSymbolTable(props); fakespace.symbol = props[0].parent!; @@ -9196,19 +11857,35 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const oldContext = context; context = subcontext; // TODO: implement handling for the localVsRemoteMap.get("remote") - should be difficult to trigger (see comment above), as only interesting cross-file js merges should make this possible - visitSymbolTable(createSymbolTable(localProps), suppressNewPrivateContext, /*propertyAsAlias*/ true); + visitSymbolTable( + createSymbolTable(localProps), + suppressNewPrivateContext, + /*propertyAsAlias*/ true, + ); context = oldContext; addingDeclare = oldAddingDeclare; const declarations = results; results = oldResults; // replace namespace with synthetic version - const defaultReplaced = map(declarations, d => - isExportAssignment(d) && !d.isExportEquals && isIdentifier(d.expression) ? factory.createExportDeclaration( - /*modifiers*/ undefined, - /*isTypeOnly*/ false, - factory.createNamedExports([factory.createExportSpecifier(/*isTypeOnly*/ false, d.expression, factory.createIdentifier(InternalSymbolName.Default))]), - ) : d); - const exportModifierStripped = every(defaultReplaced, d => hasSyntacticModifier(d, ModifierFlags.Export)) ? map(defaultReplaced as Extract[], removeExportModifier) : defaultReplaced; + const defaultReplaced = map( + declarations, + d => isExportAssignment(d) && !d.isExportEquals && isIdentifier(d.expression) + ? factory.createExportDeclaration( + /*modifiers*/ undefined, + /*isTypeOnly*/ false, + factory.createNamedExports([ + factory.createExportSpecifier( + /*isTypeOnly*/ false, + d.expression, + factory.createIdentifier(InternalSymbolName.Default), + ), + ]), + ) : d, + ); + const exportModifierStripped = every(defaultReplaced, d => + hasSyntacticModifier(d, ModifierFlags.Export)) + ? map(defaultReplaced as Extract[], removeExportModifier) + : defaultReplaced; fakespace = factory.updateModuleDeclaration( fakespace, fakespace.modifiers, @@ -9220,11 +11897,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function isNamespaceMember(p: Symbol) { - return !!(p.flags & (SymbolFlags.Type | SymbolFlags.Namespace | SymbolFlags.Alias)) || - !(p.flags & SymbolFlags.Prototype || p.escapedName === "prototype" || p.valueDeclaration && isStatic(p.valueDeclaration) && isClassLike(p.valueDeclaration.parent)); + return !!(p.flags & (SymbolFlags.Type | SymbolFlags.Namespace | SymbolFlags.Alias)) + || !(p.flags & SymbolFlags.Prototype || p.escapedName === "prototype" + || p.valueDeclaration && isStatic(p.valueDeclaration) + && isClassLike(p.valueDeclaration.parent)); } - function sanitizeJSDocImplements(clauses: readonly ExpressionWithTypeArguments[]): ExpressionWithTypeArguments[] | undefined { + function sanitizeJSDocImplements( + clauses: readonly ExpressionWithTypeArguments[], + ): ExpressionWithTypeArguments[] | undefined { const result = mapDefined(clauses, e => { const oldEnclosing = context.enclosingDeclaration; context.enclosingDeclaration = e; @@ -9234,7 +11915,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return cleanup(/*result*/ undefined); // Empty heritage clause, should be an error, but prefer emitting no heritage clauses to reemitting the empty one } let introducesError: boolean; - ({ introducesError, node: expr } = trackExistingEntityName(expr, context, includePrivateSymbol)); + ({ introducesError, node: expr } = trackExistingEntityName( + expr, + context, + includePrivateSymbol, + )); if (introducesError) { return cleanup(/*result*/ undefined); } @@ -9269,13 +11954,19 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const implementsExpressions = originalImplements && sanitizeJSDocImplements(originalImplements) || mapDefined(getImplementsTypes(classType), serializeImplementedType); const staticType = getTypeOfSymbol(symbol); - const isClass = !!staticType.symbol?.valueDeclaration && isClassLike(staticType.symbol.valueDeclaration); + const isClass = !!staticType.symbol?.valueDeclaration + && isClassLike(staticType.symbol.valueDeclaration); const staticBaseType = isClass ? getBaseConstructorTypeOfClass(staticType as InterfaceType) : anyType; const heritageClauses = [ - ...!length(baseTypes) ? [] : [factory.createHeritageClause(SyntaxKind.ExtendsKeyword, map(baseTypes, b => serializeBaseType(b, staticBaseType, localName)))], - ...!length(implementsExpressions) ? [] : [factory.createHeritageClause(SyntaxKind.ImplementsKeyword, implementsExpressions)], + ...!length(baseTypes) ? [] + : [factory.createHeritageClause( + SyntaxKind.ExtendsKeyword, + map(baseTypes, b => serializeBaseType(b, staticBaseType, localName)), + )], + ...!length(implementsExpressions) ? [] + : [factory.createHeritageClause(SyntaxKind.ImplementsKeyword, implementsExpressions)], ]; const symbolProps = getNonInheritedProperties(classType, baseTypes, getPropertiesOfType(classType)); const publicSymbolProps = filter(symbolProps, s => { @@ -9293,31 +11984,47 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return !!valueDecl && isNamedDeclaration(valueDecl) && isPrivateIdentifier(valueDecl.name); }); // Boil down all private properties into a single one. - const privateProperties = hasPrivateIdentifier ? - [factory.createPropertyDeclaration( + const privateProperties = hasPrivateIdentifier + ? [factory.createPropertyDeclaration( /*modifiers*/ undefined, factory.createPrivateIdentifier("#private"), /*questionOrExclamationToken*/ undefined, /*type*/ undefined, /*initializer*/ undefined, - )] : - emptyArray; - const publicProperties = flatMap(publicSymbolProps, p => serializePropertySymbolForClass(p, /*isStatic*/ false, baseTypes[0])); + )] + : emptyArray; + const publicProperties = flatMap( + publicSymbolProps, + p => serializePropertySymbolForClass(p, /*isStatic*/ false, baseTypes[0]), + ); // Consider static members empty if symbol also has function or module meaning - function namespacey emit will handle statics const staticMembers = flatMap( - filter(getPropertiesOfType(staticType), p => !(p.flags & SymbolFlags.Prototype) && p.escapedName !== "prototype" && !isNamespaceMember(p)), + filter( + getPropertiesOfType(staticType), + p => !(p.flags & SymbolFlags.Prototype) && p.escapedName !== "prototype" + && !isNamespaceMember(p), + ), p => serializePropertySymbolForClass(p, /*isStatic*/ true, staticBaseType), ); // When we encounter an `X.prototype.y` assignment in a JS file, we bind `X` as a class regardless as to whether // the value is ever initialized with a class or function-like value. For cases where `X` could never be // created via `new`, we will inject a `private constructor()` declaration to indicate it is not createable. - const isNonConstructableClassLikeInJsFile = !isClass && - !!symbol.valueDeclaration && - isInJSFile(symbol.valueDeclaration) && - !some(getSignaturesOfType(staticType, SignatureKind.Construct)); - const constructors = isNonConstructableClassLikeInJsFile ? - [factory.createConstructorDeclaration(factory.createModifiersFromModifierFlags(ModifierFlags.Private), [], /*body*/ undefined)] : - serializeSignatures(SignatureKind.Construct, staticType, staticBaseType, SyntaxKind.Constructor) as ConstructorDeclaration[]; + const isNonConstructableClassLikeInJsFile = !isClass + && !!symbol.valueDeclaration + && isInJSFile(symbol.valueDeclaration) + && !some(getSignaturesOfType(staticType, SignatureKind.Construct)); + const constructors = isNonConstructableClassLikeInJsFile + ? [factory.createConstructorDeclaration( + factory.createModifiersFromModifierFlags(ModifierFlags.Private), + [], + /*body*/ undefined, + )] + : serializeSignatures( + SignatureKind.Construct, + staticType, + staticBaseType, + SyntaxKind.Constructor, + ) as ConstructorDeclaration[]; const indexSignatures = serializeIndexSignatures(classType, baseTypes[0]); context.enclosingDeclaration = oldEnclosing; addResult( @@ -9327,9 +12034,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { localName, typeParamDecls, heritageClauses, - [...indexSignatures, ...staticMembers, ...constructors, ...publicProperties, ...privateProperties], + [ + ...indexSignatures, + ...staticMembers, + ...constructors, + ...publicProperties, + ...privateProperties, + ], ), - symbol.declarations && filter(symbol.declarations, d => isClassDeclaration(d) || isClassExpression(d))[0], + symbol.declarations + && filter(symbol.declarations, d => isClassDeclaration(d) || isClassExpression(d))[0], ), modifierFlags, ); @@ -9369,7 +12083,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } // If `target` refers to a shorthand module symbol, the name we're trying to pull out isn;t recoverable from the target symbol // In such a scenario, we must fall back to looking for an alias declaration on `symbol` and pulling the target name from that - let verbatimTargetName = isShorthandAmbientModuleSymbol(target) && getSomeTargetNameFromDeclarations(symbol.declarations) || unescapeLeadingUnderscores(target.escapedName); + let verbatimTargetName = + isShorthandAmbientModuleSymbol(target) && getSomeTargetNameFromDeclarations(symbol.declarations) + || unescapeLeadingUnderscores(target.escapedName); if (verbatimTargetName === InternalSymbolName.ExportEquals && allowSyntheticDefaultImports) { // target refers to an `export=` symbol that was hoisted into a synthetic default - rename here to match verbatimTargetName = InternalSymbolName.Default; @@ -9390,7 +12106,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { /*name*/ undefined, factory.createNamedImports([factory.createImportSpecifier( /*isTypeOnly*/ false, - propertyName && isIdentifier(propertyName) ? factory.createIdentifier(idText(propertyName)) : undefined, + propertyName && isIdentifier(propertyName) + ? factory.createIdentifier(idText(propertyName)) : undefined, factory.createIdentifier(localName), )]), ), @@ -9402,7 +12119,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { break; } // We don't know how to serialize this (nested?) binding element - Debug.failBadSyntaxKind(node.parent?.parent || node, "Unhandled binding element grandparent kind in declaration serialization"); + Debug.failBadSyntaxKind( + node.parent?.parent || node, + "Unhandled binding element grandparent kind in declaration serialization", + ); break; case SyntaxKind.ShorthandPropertyAssignment: if (node.parent?.parent?.kind === SyntaxKind.BinaryExpression) { @@ -9446,7 +12166,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { case SyntaxKind.ImportEqualsDeclaration: // This _specifically_ only exists to handle json declarations - where we make aliases, but since // we emit no declarations for the json document, must not refer to it in the declarations - if (target.escapedName === InternalSymbolName.ExportEquals && some(target.declarations, d => isSourceFile(d) && isJsonSourceFile(d))) { + if ( + target.escapedName === InternalSymbolName.ExportEquals + && some(target.declarations, d => isSourceFile(d) && isJsonSourceFile(d)) + ) { serializeMaybeAliasAssignment(symbol); break; } @@ -9460,7 +12183,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { factory.createIdentifier(localName), isLocalImport ? symbolToName(target, context, SymbolFlags.All, /*expectsIdentifier*/ false) - : factory.createExternalModuleReference(factory.createStringLiteral(getSpecifierForModuleSymbol(target, context))), + : factory.createExternalModuleReference( + factory.createStringLiteral(getSpecifierForModuleSymbol(target, context)), + ), ), isLocalImport ? modifierFlags : ModifierFlags.None, ); @@ -9469,15 +12194,23 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // export as namespace foo // TODO: Not part of a file's local or export symbol tables // Is bound into file.symbol.globalExports instead, which we don't currently traverse - addResult(factory.createNamespaceExportDeclaration(idText((node as NamespaceExportDeclaration).name)), ModifierFlags.None); + addResult( + factory.createNamespaceExportDeclaration(idText((node as NamespaceExportDeclaration).name)), + ModifierFlags.None, + ); break; case SyntaxKind.ImportClause: { const generatedSpecifier = getSpecifierForModuleSymbol(target.parent || target, context); // generate specifier (even though we're reusing and existing one) for ambient module reference include side effects - const specifier = bundled ? factory.createStringLiteral(generatedSpecifier) : (node as ImportClause).parent.moduleSpecifier; + const specifier = bundled ? factory.createStringLiteral(generatedSpecifier) + : (node as ImportClause).parent.moduleSpecifier; addResult( factory.createImportDeclaration( /*modifiers*/ undefined, - factory.createImportClause(/*isTypeOnly*/ false, factory.createIdentifier(localName), /*namedBindings*/ undefined), + factory.createImportClause( + /*isTypeOnly*/ false, + factory.createIdentifier(localName), + /*namedBindings*/ undefined, + ), specifier, (node as ImportClause).parent.assertClause, ), @@ -9487,11 +12220,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } case SyntaxKind.NamespaceImport: { const generatedSpecifier = getSpecifierForModuleSymbol(target.parent || target, context); // generate specifier (even though we're reusing and existing one) for ambient module reference include side effects - const specifier = bundled ? factory.createStringLiteral(generatedSpecifier) : (node as NamespaceImport).parent.parent.moduleSpecifier; + const specifier = bundled ? factory.createStringLiteral(generatedSpecifier) + : (node as NamespaceImport).parent.parent.moduleSpecifier; addResult( factory.createImportDeclaration( /*modifiers*/ undefined, - factory.createImportClause(/*isTypeOnly*/ false, /*name*/ undefined, factory.createNamespaceImport(factory.createIdentifier(localName))), + factory.createImportClause( + /*isTypeOnly*/ false, + /*name*/ undefined, + factory.createNamespaceImport(factory.createIdentifier(localName)), + ), specifier, (node as NamespaceImport).parent.parent.assertClause, ), @@ -9512,7 +12250,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { break; case SyntaxKind.ImportSpecifier: { const generatedSpecifier = getSpecifierForModuleSymbol(target.parent || target, context); // generate specifier (even though we're reusing and existing one) for ambient module reference include side effects - const specifier = bundled ? factory.createStringLiteral(generatedSpecifier) : (node as ImportSpecifier).parent.parent.parent.moduleSpecifier; + const specifier = bundled ? factory.createStringLiteral(generatedSpecifier) + : (node as ImportSpecifier).parent.parent.parent.moduleSpecifier; addResult( factory.createImportDeclaration( /*modifiers*/ undefined, @@ -9522,7 +12261,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { factory.createNamedImports([ factory.createImportSpecifier( /*isTypeOnly*/ false, - localName !== verbatimTargetName ? factory.createIdentifier(verbatimTargetName) : undefined, + localName !== verbatimTargetName + ? factory.createIdentifier(verbatimTargetName) : undefined, factory.createIdentifier(localName), ), ]), @@ -9543,7 +12283,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { serializeExportSpecifier( unescapeLeadingUnderscores(symbol.escapedName), specifier ? verbatimTargetName : targetName, - specifier && isStringLiteralLike(specifier) ? factory.createStringLiteral(specifier.text) : undefined, + specifier && isStringLiteralLike(specifier) ? factory.createStringLiteral(specifier.text) + : undefined, ); break; case SyntaxKind.ExportAssignment: @@ -9555,7 +12296,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // Could be best encoded as though an export specifier or as though an export assignment // If name is default or export=, do an export assignment // Otherwise do an export specifier - if (symbol.escapedName === InternalSymbolName.Default || symbol.escapedName === InternalSymbolName.ExportEquals) { + if ( + symbol.escapedName === InternalSymbolName.Default + || symbol.escapedName === InternalSymbolName.ExportEquals + ) { serializeMaybeAliasAssignment(symbol); } else { @@ -9572,7 +12316,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { factory.createExportDeclaration( /*modifiers*/ undefined, /*isTypeOnly*/ false, - factory.createNamedExports([factory.createExportSpecifier(/*isTypeOnly*/ false, localName !== targetName ? targetName : undefined, localName)]), + factory.createNamedExports([ + factory.createExportSpecifier( + /*isTypeOnly*/ false, + localName !== targetName ? targetName : undefined, + localName, + ), + ]), specifier, ), ModifierFlags.None, @@ -9597,13 +12347,35 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // serialize what the alias points to, preserve the declaration's initializer const target = aliasDecl && getTargetOfAliasDeclaration(aliasDecl, /*dontRecursivelyResolve*/ true); // If the target resolves and resolves to a thing defined in this file, emit as an alias, otherwise emit as a const - if (target && length(target.declarations) && some(target.declarations, d => getSourceFileOfNode(d) === getSourceFileOfNode(enclosingDeclaration))) { + if ( + target && length(target.declarations) + && some( + target.declarations, + d => getSourceFileOfNode(d) === getSourceFileOfNode(enclosingDeclaration), + ) + ) { // In case `target` refers to a namespace member, look at the declaration and serialize the leftmost symbol in it // eg, `namespace A { export class B {} }; exports = A.B;` // Technically, this is all that's required in the case where the assignment is an entity name expression - const expr = aliasDecl && ((isExportAssignment(aliasDecl) || isBinaryExpression(aliasDecl)) ? getExportAssignmentExpression(aliasDecl) : getPropertyAssignmentAliasLikeExpression(aliasDecl as ShorthandPropertyAssignment | PropertyAssignment | PropertyAccessExpression)); - const first = expr && isEntityNameExpression(expr) ? getFirstNonModuleExportsIdentifier(expr) : undefined; - const referenced = first && resolveEntityName(first, SymbolFlags.All, /*ignoreErrors*/ true, /*dontResolveAlias*/ true, enclosingDeclaration); + const expr = aliasDecl + && ((isExportAssignment(aliasDecl) || isBinaryExpression(aliasDecl)) + ? getExportAssignmentExpression(aliasDecl) + : getPropertyAssignmentAliasLikeExpression( + aliasDecl as + | ShorthandPropertyAssignment + | PropertyAssignment + | PropertyAccessExpression, + )); + const first = expr && isEntityNameExpression(expr) ? getFirstNonModuleExportsIdentifier(expr) + : undefined; + const referenced = first + && resolveEntityName( + first, + SymbolFlags.All, + /*ignoreErrors*/ true, + /*dontResolveAlias*/ true, + enclosingDeclaration, + ); if (referenced || target) { includePrivateSymbol(referenced || target); } @@ -9656,20 +12428,41 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const typeToSerialize = getWidenedType(getTypeOfSymbol(getMergedSymbol(symbol))); if (isTypeRepresentableAsFunctionNamespaceMerge(typeToSerialize, symbol)) { // If there are no index signatures and `typeToSerialize` is an object type, emit as a namespace instead of a const - serializeAsFunctionNamespaceMerge(typeToSerialize, symbol, varName, isExportAssignmentCompatibleSymbolName ? ModifierFlags.None : ModifierFlags.Export); + serializeAsFunctionNamespaceMerge( + typeToSerialize, + symbol, + varName, + isExportAssignmentCompatibleSymbolName ? ModifierFlags.None : ModifierFlags.Export, + ); } else { const statement = factory.createVariableStatement( /*modifiers*/ undefined, - factory.createVariableDeclarationList([ - factory.createVariableDeclaration(varName, /*exclamationToken*/ undefined, serializeTypeForDeclaration(context, typeToSerialize, symbol, enclosingDeclaration, includePrivateSymbol, bundled)), - ], context.enclosingDeclaration?.kind === SyntaxKind.ModuleDeclaration ? NodeFlags.Let : NodeFlags.Const), + factory.createVariableDeclarationList( + [ + factory.createVariableDeclaration( + varName, + /*exclamationToken*/ undefined, + serializeTypeForDeclaration( + context, + typeToSerialize, + symbol, + enclosingDeclaration, + includePrivateSymbol, + bundled, + ), + ), + ], + context.enclosingDeclaration?.kind === SyntaxKind.ModuleDeclaration ? NodeFlags.Let + : NodeFlags.Const, + ), ); // Inlined JSON types exported with [module.]exports= will already emit an export=, so should use `declare`. // Otherwise, the type itself should be exported. addResult( statement, - target && target.flags & SymbolFlags.Property && target.escapedName === InternalSymbolName.ExportEquals ? ModifierFlags.Ambient + target && target.flags & SymbolFlags.Property + && target.escapedName === InternalSymbolName.ExportEquals ? ModifierFlags.Ambient : name === varName ? ModifierFlags.Export : ModifierFlags.None, ); @@ -9695,16 +12488,24 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // context source file, and whose property names are all valid identifiers and not late-bound, _and_ // whose input is not type annotated (if the input symbol has an annotation we can reuse, we should prefer it) const ctxSrc = getSourceFileOfNode(context.enclosingDeclaration); - return getObjectFlags(typeToSerialize) & (ObjectFlags.Anonymous | ObjectFlags.Mapped) && - !length(getIndexInfosOfType(typeToSerialize)) && - !isClassInstanceSide(typeToSerialize) && // While a class instance is potentially representable as a NS, prefer printing a reference to the instance type and serializing the class - !!(length(filter(getPropertiesOfType(typeToSerialize), isNamespaceMember)) || length(getSignaturesOfType(typeToSerialize, SignatureKind.Call))) && - !length(getSignaturesOfType(typeToSerialize, SignatureKind.Construct)) && // TODO: could probably serialize as function + ns + class, now that that's OK - !getDeclarationWithTypeAnnotation(hostSymbol, enclosingDeclaration) && - !(typeToSerialize.symbol && some(typeToSerialize.symbol.declarations, d => getSourceFileOfNode(d) !== ctxSrc)) && - !some(getPropertiesOfType(typeToSerialize), p => isLateBoundName(p.escapedName)) && - !some(getPropertiesOfType(typeToSerialize), p => some(p.declarations, d => getSourceFileOfNode(d) !== ctxSrc)) && - every(getPropertiesOfType(typeToSerialize), p => isIdentifierText(symbolName(p), languageVersion)); + return getObjectFlags(typeToSerialize) & (ObjectFlags.Anonymous | ObjectFlags.Mapped) + && !length(getIndexInfosOfType(typeToSerialize)) + && !isClassInstanceSide(typeToSerialize) // While a class instance is potentially representable as a NS, prefer printing a reference to the instance type and serializing the class + && !!(length(filter(getPropertiesOfType(typeToSerialize), isNamespaceMember)) + || length(getSignaturesOfType(typeToSerialize, SignatureKind.Call))) + && !length(getSignaturesOfType(typeToSerialize, SignatureKind.Construct)) // TODO: could probably serialize as function + ns + class, now that that's OK + && !getDeclarationWithTypeAnnotation(hostSymbol, enclosingDeclaration) + && !(typeToSerialize.symbol + && some(typeToSerialize.symbol.declarations, d => getSourceFileOfNode(d) !== ctxSrc)) + && !some(getPropertiesOfType(typeToSerialize), p => isLateBoundName(p.escapedName)) + && !some( + getPropertiesOfType(typeToSerialize), + p => some(p.declarations, d => getSourceFileOfNode(d) !== ctxSrc), + ) + && every( + getPropertiesOfType(typeToSerialize), + p => isIdentifierText(symbolName(p), languageVersion), + ); } function makeSerializePropertySymbol( @@ -9717,7 +12518,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { ) => T, methodKind: SignatureDeclaration["kind"], useAccessors: true, - ): (p: Symbol, isStatic: boolean, baseType: Type | undefined) => T | AccessorDeclaration | (T | AccessorDeclaration)[]; + ): ( + p: Symbol, + isStatic: boolean, + baseType: Type | undefined, + ) => T | AccessorDeclaration | (T | AccessorDeclaration)[]; function makeSerializePropertySymbol( createProperty: ( modifiers: readonly Modifier[] | undefined, @@ -9739,8 +12544,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { ) => T, methodKind: SignatureDeclaration["kind"], useAccessors: boolean, - ): (p: Symbol, isStatic: boolean, baseType: Type | undefined) => T | AccessorDeclaration | (T | AccessorDeclaration)[] { - return function serializePropertySymbol(p: Symbol, isStatic: boolean, baseType: Type | undefined): T | AccessorDeclaration | (T | AccessorDeclaration)[] { + ): ( + p: Symbol, + isStatic: boolean, + baseType: Type | undefined, + ) => T | AccessorDeclaration | (T | AccessorDeclaration)[] { + return function serializePropertySymbol( + p: Symbol, + isStatic: boolean, + baseType: Type | undefined, + ): T | AccessorDeclaration | (T | AccessorDeclaration)[] { const modifierFlags = getDeclarationModifierFlagsFromSymbol(p); const isPrivate = !!(modifierFlags & ModifierFlags.Private); if (isStatic && (p.flags & (SymbolFlags.Type | SymbolFlags.Namespace | SymbolFlags.Alias))) { @@ -9749,17 +12562,27 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return []; } if ( - p.flags & SymbolFlags.Prototype || p.escapedName === "constructor" || - (baseType && getPropertyOfType(baseType, p.escapedName) + p.flags & SymbolFlags.Prototype || p.escapedName === "constructor" + || (baseType && getPropertyOfType(baseType, p.escapedName) && isReadonlySymbol(getPropertyOfType(baseType, p.escapedName)!) === isReadonlySymbol(p) - && (p.flags & SymbolFlags.Optional) === (getPropertyOfType(baseType, p.escapedName)!.flags & SymbolFlags.Optional) + && (p.flags & SymbolFlags.Optional) + === (getPropertyOfType(baseType, p.escapedName)!.flags & SymbolFlags.Optional) && isTypeIdenticalTo(getTypeOfSymbol(p), getTypeOfPropertyOfType(baseType, p.escapedName)!)) ) { return []; } const flag = (modifierFlags & ~ModifierFlags.Async) | (isStatic ? ModifierFlags.Static : 0); const name = getPropertyNameNodeForSymbol(p, context); - const firstPropertyLikeDecl = p.declarations?.find(or(isPropertyDeclaration, isAccessor, isVariableDeclaration, isPropertySignature, isBinaryExpression, isPropertyAccessExpression)); + const firstPropertyLikeDecl = p.declarations?.find( + or( + isPropertyDeclaration, + isAccessor, + isVariableDeclaration, + isPropertySignature, + isBinaryExpression, + isPropertyAccessExpression, + ), + ); if (p.flags & SymbolFlags.Accessor && useAccessors) { const result: AccessorDeclaration[] = []; if (p.flags & SymbolFlags.SetAccessor) { @@ -9772,7 +12595,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { /*dotDotDotToken*/ undefined, "arg", /*questionToken*/ undefined, - isPrivate ? undefined : serializeTypeForDeclaration(context, getTypeOfSymbol(p), p, enclosingDeclaration, includePrivateSymbol, bundled), + isPrivate ? undefined + : serializeTypeForDeclaration( + context, + getTypeOfSymbol(p), + p, + enclosingDeclaration, + includePrivateSymbol, + bundled, + ), )], /*body*/ undefined, ), @@ -9786,7 +12617,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { factory.createModifiersFromModifierFlags(flag), name, [], - isPrivate ? undefined : serializeTypeForDeclaration(context, getTypeOfSymbol(p), p, enclosingDeclaration, includePrivateSymbol, bundled), + isPrivate ? undefined + : serializeTypeForDeclaration( + context, + getTypeOfSymbol(p), + p, + enclosingDeclaration, + includePrivateSymbol, + bundled, + ), /*body*/ undefined, ), p.declarations?.find(isGetAccessor) || firstPropertyLikeDecl, @@ -9799,15 +12638,27 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { else if (p.flags & (SymbolFlags.Property | SymbolFlags.Variable | SymbolFlags.Accessor)) { return setTextRange( createProperty( - factory.createModifiersFromModifierFlags((isReadonlySymbol(p) ? ModifierFlags.Readonly : 0) | flag), + factory.createModifiersFromModifierFlags( + (isReadonlySymbol(p) ? ModifierFlags.Readonly : 0) | flag, + ), name, - p.flags & SymbolFlags.Optional ? factory.createToken(SyntaxKind.QuestionToken) : undefined, - isPrivate ? undefined : serializeTypeForDeclaration(context, getWriteTypeOfSymbol(p), p, enclosingDeclaration, includePrivateSymbol, bundled), + p.flags & SymbolFlags.Optional ? factory.createToken(SyntaxKind.QuestionToken) + : undefined, + isPrivate ? undefined + : serializeTypeForDeclaration( + context, + getWriteTypeOfSymbol(p), + p, + enclosingDeclaration, + includePrivateSymbol, + bundled, + ), // TODO: https://github.com/microsoft/TypeScript/pull/32372#discussion_r328386357 // interface members can't have initializers, however class members _can_ /*initializer*/ undefined, ), - p.declarations?.find(or(isPropertyDeclaration, isVariableDeclaration)) || firstPropertyLikeDecl, + p.declarations?.find(or(isPropertyDeclaration, isVariableDeclaration)) + || firstPropertyLikeDecl, ); } if (p.flags & (SymbolFlags.Method | SymbolFlags.Function)) { @@ -9816,13 +12667,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (flag & ModifierFlags.Private) { return setTextRange( createProperty( - factory.createModifiersFromModifierFlags((isReadonlySymbol(p) ? ModifierFlags.Readonly : 0) | flag), + factory.createModifiersFromModifierFlags( + (isReadonlySymbol(p) ? ModifierFlags.Readonly : 0) | flag, + ), name, - p.flags & SymbolFlags.Optional ? factory.createToken(SyntaxKind.QuestionToken) : undefined, + p.flags & SymbolFlags.Optional ? factory.createToken(SyntaxKind.QuestionToken) + : undefined, /*type*/ undefined, /*initializer*/ undefined, ), - p.declarations?.find(isFunctionLikeDeclaration) || signatures[0] && signatures[0].declaration || p.declarations && p.declarations[0], + p.declarations?.find(isFunctionLikeDeclaration) + || signatures[0] && signatures[0].declaration + || p.declarations && p.declarations[0], ); } @@ -9835,11 +12691,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { context, { name, - questionToken: p.flags & SymbolFlags.Optional ? factory.createToken(SyntaxKind.QuestionToken) : undefined, + questionToken: p.flags & SymbolFlags.Optional + ? factory.createToken(SyntaxKind.QuestionToken) : undefined, modifiers: flag ? factory.createModifiersFromModifierFlags(flag) : undefined, }, ); - const location = sig.declaration && isPrototypePropertyAssignment(sig.declaration.parent) ? sig.declaration.parent : sig.declaration; + const location = sig.declaration && isPrototypePropertyAssignment(sig.declaration.parent) + ? sig.declaration.parent : sig.declaration; results.push(setTextRange(decl, location)); } return results as unknown as T[]; @@ -9853,7 +12711,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return serializePropertySymbolForInterfaceWorker(p, /*isStatic*/ false, baseType); } - function serializeSignatures(kind: SignatureKind, input: Type, baseType: Type | undefined, outputKind: SignatureDeclaration["kind"]) { + function serializeSignatures( + kind: SignatureKind, + input: Type, + baseType: Type | undefined, + outputKind: SignatureDeclaration["kind"], + ) { const signatures = getSignaturesOfType(input, kind); if (kind === SignatureKind.Construct) { if (!baseType && every(signatures, s => length(s.parameters) === 0)) { @@ -9868,7 +12731,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (baseSigs.length === signatures.length) { let failed = false; for (let i = 0; i < baseSigs.length; i++) { - if (!compareSignaturesIdentical(signatures[i], baseSigs[i], /*partialMatch*/ false, /*ignoreThisTypes*/ false, /*ignoreReturnTypes*/ true, compareTypesIdentical)) { + if ( + !compareSignaturesIdentical( + signatures[i], + baseSigs[i], + /*partialMatch*/ false, + /*ignoreThisTypes*/ false, + /*ignoreReturnTypes*/ true, + compareTypesIdentical, + ) + ) { failed = true; break; } @@ -9881,7 +12753,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { let privateProtected: ModifierFlags = 0; for (const s of signatures) { if (s.declaration) { - privateProtected |= getSelectedEffectiveModifierFlags(s.declaration, ModifierFlags.Private | ModifierFlags.Protected); + privateProtected |= getSelectedEffectiveModifierFlags( + s.declaration, + ModifierFlags.Private | ModifierFlags.Protected, + ); } } if (privateProtected) { @@ -9930,11 +12805,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const statement = factory.createVariableStatement( /*modifiers*/ undefined, factory.createVariableDeclarationList([ - factory.createVariableDeclaration(tempName, /*exclamationToken*/ undefined, typeToTypeNodeHelper(staticType, context)), + factory.createVariableDeclaration( + tempName, + /*exclamationToken*/ undefined, + typeToTypeNodeHelper(staticType, context), + ), ], NodeFlags.Const), ); addResult(statement, ModifierFlags.None); - return factory.createExpressionWithTypeArguments(factory.createIdentifier(tempName), /*typeArguments*/ undefined); + return factory.createExpressionWithTypeArguments( + factory.createIdentifier(tempName), + /*typeArguments*/ undefined, + ); } function trySerializeAsTypeReference(t: Type, flags: SymbolFlags) { @@ -9943,7 +12825,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // We don't use `isValueSymbolAccessible` below. since that considers alternative containers (like modules) // which we can't write out in a syntactically valid way as an expression - if ((t as TypeReference).target && isSymbolAccessibleByFlags((t as TypeReference).target.symbol, enclosingDeclaration, flags)) { + if ( + (t as TypeReference).target + && isSymbolAccessibleByFlags((t as TypeReference).target.symbol, enclosingDeclaration, flags) + ) { typeArgs = map(getTypeArguments(t as TypeReference), t => typeToTypeNodeHelper(t, context)); reference = symbolToExpression((t as TypeReference).target.symbol, context, SymbolFlags.Type); } @@ -9961,7 +12846,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return ref; } if (t.symbol) { - return factory.createExpressionWithTypeArguments(symbolToExpression(t.symbol, context, SymbolFlags.Type), /*typeArguments*/ undefined); + return factory.createExpressionWithTypeArguments( + symbolToExpression(t.symbol, context, SymbolFlags.Type), + /*typeArguments*/ undefined, + ); } } @@ -9989,12 +12877,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function getNameCandidateWorker(symbol: Symbol, localName: string) { - if (localName === InternalSymbolName.Default || localName === InternalSymbolName.Class || localName === InternalSymbolName.Function) { + if ( + localName === InternalSymbolName.Default || localName === InternalSymbolName.Class + || localName === InternalSymbolName.Function + ) { const flags = context.flags; context.flags |= NodeBuilderFlags.InInitialEntityName; const nameCandidate = getNameOfSymbolAsWritten(symbol, context); context.flags = flags; - localName = nameCandidate.length > 0 && isSingleOrDoubleQuote(nameCandidate.charCodeAt(0)) ? stripQuotes(nameCandidate) : nameCandidate; + localName = nameCandidate.length > 0 && isSingleOrDoubleQuote(nameCandidate.charCodeAt(0)) + ? stripQuotes(nameCandidate) : nameCandidate; } if (localName === InternalSymbolName.Default) { localName = "_default"; @@ -10002,7 +12894,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { else if (localName === InternalSymbolName.ExportEquals) { localName = "_exports"; } - localName = isIdentifierText(localName, languageVersion) && !isStringANonContextualKeyword(localName) ? localName : "_" + localName.replace(/[^a-zA-Z0-9]/g, "_"); + localName = isIdentifierText(localName, languageVersion) && !isStringANonContextualKeyword(localName) + ? localName : "_" + localName.replace(/[^a-zA-Z0-9]/g, "_"); return localName; } @@ -10019,14 +12912,30 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } - function typePredicateToString(typePredicate: TypePredicate, enclosingDeclaration?: Node, flags: TypeFormatFlags = TypeFormatFlags.UseAliasDefinedOutsideCurrentScope, writer?: EmitTextWriter): string { - return writer ? typePredicateToStringWorker(writer).getText() : usingSingleLineStringWriter(typePredicateToStringWorker); + function typePredicateToString( + typePredicate: TypePredicate, + enclosingDeclaration?: Node, + flags: TypeFormatFlags = TypeFormatFlags.UseAliasDefinedOutsideCurrentScope, + writer?: EmitTextWriter, + ): string { + return writer ? typePredicateToStringWorker(writer).getText() + : usingSingleLineStringWriter(typePredicateToStringWorker); function typePredicateToStringWorker(writer: EmitTextWriter) { const predicate = factory.createTypePredicateNode( - typePredicate.kind === TypePredicateKind.AssertsThis || typePredicate.kind === TypePredicateKind.AssertsIdentifier ? factory.createToken(SyntaxKind.AssertsKeyword) : undefined, - typePredicate.kind === TypePredicateKind.Identifier || typePredicate.kind === TypePredicateKind.AssertsIdentifier ? factory.createIdentifier(typePredicate.parameterName) : factory.createThisTypeNode(), - typePredicate.type && nodeBuilder.typeToTypeNode(typePredicate.type, enclosingDeclaration, toNodeBuilderFlags(flags) | NodeBuilderFlags.IgnoreErrors | NodeBuilderFlags.WriteTypeParametersInQualifiedName)!, // TODO: GH#18217 + typePredicate.kind === TypePredicateKind.AssertsThis + || typePredicate.kind === TypePredicateKind.AssertsIdentifier + ? factory.createToken(SyntaxKind.AssertsKeyword) : undefined, + typePredicate.kind === TypePredicateKind.Identifier + || typePredicate.kind === TypePredicateKind.AssertsIdentifier + ? factory.createIdentifier(typePredicate.parameterName) : factory.createThisTypeNode(), + typePredicate.type + && nodeBuilder.typeToTypeNode( + typePredicate.type, + enclosingDeclaration, + toNodeBuilderFlags(flags) | NodeBuilderFlags.IgnoreErrors + | NodeBuilderFlags.WriteTypeParametersInQualifiedName, + )!, // TODO: GH#18217 ); const printer = createPrinterWithRemoveComments(); const sourceFile = enclosingDeclaration && getSourceFileOfNode(enclosingDeclaration); @@ -10043,10 +12952,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { flags |= t.flags; if (!(t.flags & TypeFlags.Nullable)) { if (t.flags & (TypeFlags.BooleanLiteral | TypeFlags.EnumLike)) { - const baseType = t.flags & TypeFlags.BooleanLiteral ? booleanType : getBaseTypeOfEnumLikeType(t as LiteralType); + const baseType = t.flags & TypeFlags.BooleanLiteral ? booleanType + : getBaseTypeOfEnumLikeType(t as LiteralType); if (baseType.flags & TypeFlags.Union) { const count = (baseType as UnionType).types.length; - if (i + count <= types.length && getRegularTypeOfLiteralType(types[i + count - 1]) === getRegularTypeOfLiteralType((baseType as UnionType).types[count - 1])) { + if ( + i + count <= types.length + && getRegularTypeOfLiteralType(types[i + count - 1]) + === getRegularTypeOfLiteralType((baseType as UnionType).types[count - 1]) + ) { result.push(baseType); i += count - 1; continue; @@ -10082,9 +12996,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function isTopLevelInExternalModuleAugmentation(node: Node): boolean { - return node && node.parent && - node.parent.kind === SyntaxKind.ModuleBlock && - isExternalModuleAugmentation(node.parent.parent); + return node && node.parent + && node.parent.kind === SyntaxKind.ModuleBlock + && isExternalModuleAugmentation(node.parent.parent); } function isDefaultBindingContext(location: Node) { @@ -10119,13 +13033,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { */ function getNameOfSymbolAsWritten(symbol: Symbol, context?: NodeBuilderContext): string { if ( - context && symbol.escapedName === InternalSymbolName.Default && !(context.flags & NodeBuilderFlags.UseAliasDefinedOutsideCurrentScope) && + context && symbol.escapedName === InternalSymbolName.Default + && !(context.flags & NodeBuilderFlags.UseAliasDefinedOutsideCurrentScope) // If it's not the first part of an entity name, it must print as `default` - (!(context.flags & NodeBuilderFlags.InInitialEntityName) || + && (!(context.flags & NodeBuilderFlags.InInitialEntityName) // if the symbol is synthesized, it will only be referenced externally it must print as `default` - !symbol.declarations || + || !symbol.declarations // if not in the same binding context (source file, module declaration), it must print as `default` - (context.enclosingDeclaration && findAncestor(symbol.declarations[0], isDefaultBindingContext) !== findAncestor(context.enclosingDeclaration, isDefaultBindingContext))) + || (context.enclosingDeclaration + && findAncestor(symbol.declarations[0], isDefaultBindingContext) + !== findAncestor(context.enclosingDeclaration, isDefaultBindingContext))) ) { return "default"; } @@ -10158,10 +13075,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { case SyntaxKind.ClassExpression: case SyntaxKind.FunctionExpression: case SyntaxKind.ArrowFunction: - if (context && !context.encounteredError && !(context.flags & NodeBuilderFlags.AllowAnonymousIdentifier)) { + if ( + context && !context.encounteredError + && !(context.flags & NodeBuilderFlags.AllowAnonymousIdentifier) + ) { context.encounteredError = true; } - return declaration.kind === SyntaxKind.ClassExpression ? "(Anonymous class)" : "(Anonymous function)"; + return declaration.kind === SyntaxKind.ClassExpression ? "(Anonymous class)" + : "(Anonymous function)"; } } const name = getNameOfSymbolFromNameType(symbol, context); @@ -10186,13 +13107,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { case SyntaxKind.JSDocEnumTag: // Top-level jsdoc type aliases are considered exported // First parent is comment node, second is hosting declaration or token; we only care about those tokens or declarations whose parent is a source file - return !!(node.parent && node.parent.parent && node.parent.parent.parent && isSourceFile(node.parent.parent.parent)); + return !!(node.parent && node.parent.parent && node.parent.parent.parent + && isSourceFile(node.parent.parent.parent)); case SyntaxKind.BindingElement: return isDeclarationVisible(node.parent.parent); case SyntaxKind.VariableDeclaration: if ( - isBindingPattern((node as VariableDeclaration).name) && - !((node as VariableDeclaration).name as BindingPattern).elements.length + isBindingPattern((node as VariableDeclaration).name) + && !((node as VariableDeclaration).name as BindingPattern).elements.length ) { // If the binding pattern is empty, this variable declaration is not visible return false; @@ -10212,8 +13134,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const parent = getDeclarationContainer(node); // If the node is not exported or it is not ambient module element (except import declaration) if ( - !(getCombinedModifierFlagsCached(node as Declaration) & ModifierFlags.Export) && - !(node.kind !== SyntaxKind.ImportEqualsDeclaration && parent.kind !== SyntaxKind.SourceFile && parent.flags & NodeFlags.Ambient) + !(getCombinedModifierFlagsCached(node as Declaration) & ModifierFlags.Export) + && !(node.kind !== SyntaxKind.ImportEqualsDeclaration && parent.kind !== SyntaxKind.SourceFile + && parent.flags & NodeFlags.Ambient) ) { return isGlobalSourceFile(parent); } @@ -10280,10 +13203,20 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function collectLinkedAliases(node: Identifier, setVisibility?: boolean): Node[] | undefined { let exportSymbol: Symbol | undefined; if (node.parent && node.parent.kind === SyntaxKind.ExportAssignment) { - exportSymbol = resolveName(node, node.escapedText, SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace | SymbolFlags.Alias, /*nameNotFoundMessage*/ undefined, node, /*isUse*/ false); + exportSymbol = resolveName( + node, + node.escapedText, + SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace | SymbolFlags.Alias, + /*nameNotFoundMessage*/ undefined, + node, + /*isUse*/ false, + ); } else if (node.parent.kind === SyntaxKind.ExportSpecifier) { - exportSymbol = getTargetOfExportSpecifier(node.parent as ExportSpecifier, SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace | SymbolFlags.Alias); + exportSymbol = getTargetOfExportSpecifier( + node.parent as ExportSpecifier, + SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace | SymbolFlags.Alias, + ); } let result: Node[] | undefined; let visited: Set | undefined; @@ -10309,7 +13242,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // Add the referenced top container visible const internalModuleReference = declaration.moduleReference as Identifier | QualifiedName; const firstIdentifier = getFirstIdentifier(internalModuleReference); - const importSymbol = resolveName(declaration, firstIdentifier.escapedText, SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ false); + const importSymbol = resolveName( + declaration, + firstIdentifier.escapedText, + SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace, + /*nameNotFoundMessage*/ undefined, + /*nameArg*/ undefined, + /*isUse*/ false, + ); if (importSymbol && visited) { if (tryAddToSet(visited, getSymbolId(importSymbol))) { buildVisibleNodeList(importSymbol.declarations); @@ -10417,7 +13357,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // the type of which is an instantiation of the class type with type Any supplied as a type argument for each type parameter. // It is an error to explicitly declare a static property member with the name 'prototype'. const classType = getDeclaredTypeOfSymbol(getParentOfSymbol(prototype)!) as InterfaceType; - return classType.typeParameters ? createTypeReference(classType as GenericType, map(classType.typeParameters, _ => anyType)) : classType; + return classType.typeParameters + ? createTypeReference(classType as GenericType, map(classType.typeParameters, _ => anyType)) : classType; } // Return the type of the given property in the given type, or undefined if no such property exists @@ -10437,9 +13378,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { */ function getTypeOfPropertyOrIndexSignatureOfType(type: Type, name: __String): Type | undefined { let propType; - return getTypeOfPropertyOfType(type, name) || - (propType = getApplicableIndexInfoForName(type, name)?.type) && - addOptionality(propType, /*isProperty*/ true, /*isOptional*/ true); + return getTypeOfPropertyOfType(type, name) + || (propType = getApplicableIndexInfoForName(type, name)?.type) + && addOptionality(propType, /*isProperty*/ true, /*isOptional*/ true); } function isTypeAny(type: Type | undefined) { @@ -10459,7 +13400,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return getTypeForVariableLikeDeclaration(node, /*includeOptionality*/ false, checkMode); } const symbol = getSymbolOfDeclaration(node); - return symbol && getSymbolLinks(symbol).type || getTypeForVariableLikeDeclaration(node, /*includeOptionality*/ false, checkMode); + return symbol && getSymbolLinks(symbol).type + || getTypeForVariableLikeDeclaration(node, /*includeOptionality*/ false, checkMode); } function getRestType(source: Type, properties: PropertyName[], symbol: Symbol | undefined): Type { @@ -10518,11 +13460,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function isGenericTypeWithUndefinedConstraint(type: Type) { - return !!(type.flags & TypeFlags.Instantiable) && maybeTypeOfKind(getBaseConstraintOfType(type) || unknownType, TypeFlags.Undefined); + return !!(type.flags & TypeFlags.Instantiable) + && maybeTypeOfKind(getBaseConstraintOfType(type) || unknownType, TypeFlags.Undefined); } function getNonUndefinedType(type: Type) { - const typeOrConstraint = someType(type, isGenericTypeWithUndefinedConstraint) ? mapType(type, t => t.flags & TypeFlags.Instantiable ? getBaseConstraintOrType(t) : t) : type; + const typeOrConstraint = someType(type, isGenericTypeWithUndefinedConstraint) + ? mapType(type, t => t.flags & TypeFlags.Instantiable ? getBaseConstraintOrType(t) : t) : type; return getTypeWithFacts(typeOrConstraint, TypeFacts.NEUndefined); } @@ -10535,18 +13479,24 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // [ x ] = obj; // Expression // We construct a synthetic element access expression corresponding to 'obj.x' such that the control // flow analyzer doesn't have to handle all the different syntactic forms. - function getFlowTypeOfDestructuring(node: BindingElement | PropertyAssignment | ShorthandPropertyAssignment | Expression, declaredType: Type) { + function getFlowTypeOfDestructuring( + node: BindingElement | PropertyAssignment | ShorthandPropertyAssignment | Expression, + declaredType: Type, + ) { const reference = getSyntheticElementAccess(node); return reference ? getFlowTypeOfReference(reference, declaredType) : declaredType; } - function getSyntheticElementAccess(node: BindingElement | PropertyAssignment | ShorthandPropertyAssignment | Expression): ElementAccessExpression | undefined { + function getSyntheticElementAccess( + node: BindingElement | PropertyAssignment | ShorthandPropertyAssignment | Expression, + ): ElementAccessExpression | undefined { const parentAccess = getParentElementAccess(node); if (parentAccess && canHaveFlowNode(parentAccess) && parentAccess.flowNode) { const propName = getDestructuringPropertyName(node); if (propName) { const literal = setTextRange(parseNodeFactory.createStringLiteral(propName), node); - const lhsExpr = isLeftHandSideExpression(parentAccess) ? parentAccess : parseNodeFactory.createParenthesizedExpression(parentAccess); + const lhsExpr = isLeftHandSideExpression(parentAccess) ? parentAccess + : parseNodeFactory.createParenthesizedExpression(parentAccess); const result = setTextRange(parseNodeFactory.createElementAccessExpression(lhsExpr, literal), node); setParent(literal, result); setParent(result, node); @@ -10559,7 +13509,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } - function getParentElementAccess(node: BindingElement | PropertyAssignment | ShorthandPropertyAssignment | Expression) { + function getParentElementAccess( + node: BindingElement | PropertyAssignment | ShorthandPropertyAssignment | Expression, + ) { const ancestor = node.parent.parent; switch (ancestor.kind) { case SyntaxKind.BindingElement: @@ -10574,10 +13526,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } - function getDestructuringPropertyName(node: BindingElement | PropertyAssignment | ShorthandPropertyAssignment | Expression) { + function getDestructuringPropertyName( + node: BindingElement | PropertyAssignment | ShorthandPropertyAssignment | Expression, + ) { const parent = node.parent; if (node.kind === SyntaxKind.BindingElement && parent.kind === SyntaxKind.ObjectBindingPattern) { - return getLiteralPropertyNameText((node as BindingElement).propertyName || (node as BindingElement).name as Identifier); + return getLiteralPropertyNameText( + (node as BindingElement).propertyName || (node as BindingElement).name as Identifier, + ); } if (node.kind === SyntaxKind.PropertyAssignment || node.kind === SyntaxKind.ShorthandPropertyAssignment) { return getLiteralPropertyNameText((node as PropertyAssignment | ShorthandPropertyAssignment).name); @@ -10587,7 +13543,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function getLiteralPropertyNameText(name: PropertyName) { const type = getLiteralTypeFromPropertyName(name); - return type.flags & (TypeFlags.StringLiteral | TypeFlags.NumberLiteral) ? "" + (type as StringLiteralType | NumberLiteralType).value : undefined; + return type.flags & (TypeFlags.StringLiteral | TypeFlags.NumberLiteral) + ? "" + (type as StringLiteralType | NumberLiteralType).value : undefined; } /** Return the inferred type for a binding element */ @@ -10608,7 +13565,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { parentType = getNonNullableType(parentType); } // Filter `undefined` from the type we check against if the parent has an initializer and that initializer is not possibly `undefined` - else if (strictNullChecks && pattern.parent.initializer && !(getTypeFacts(getTypeOfInitializer(pattern.parent.initializer)) & TypeFacts.EQUndefined)) { + else if ( + strictNullChecks && pattern.parent.initializer + && !(getTypeFacts(getTypeOfInitializer(pattern.parent.initializer)) & TypeFacts.EQUndefined) + ) { parentType = getTypeWithFacts(parentType, TypeFacts.NEUndefined); } @@ -10640,21 +13600,31 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // This elementType will be used if the specific property corresponding to this index is not // present (aka the tuple element property). This call also checks that the parentType is in // fact an iterable or array (depending on target language). - const elementType = checkIteratedTypeOrElementType(IterationUse.Destructuring | (declaration.dotDotDotToken ? 0 : IterationUse.PossiblyOutOfBounds), parentType, undefinedType, pattern); + const elementType = checkIteratedTypeOrElementType( + IterationUse.Destructuring | (declaration.dotDotDotToken ? 0 : IterationUse.PossiblyOutOfBounds), + parentType, + undefinedType, + pattern, + ); const index = pattern.elements.indexOf(declaration); if (declaration.dotDotDotToken) { // If the parent is a tuple type, the rest element has a tuple type of the // remaining tuple element types. Otherwise, the rest element has an array type with same // element type as the parent type. - const baseConstraint = mapType(parentType, t => t.flags & TypeFlags.InstantiableNonPrimitive ? getBaseConstraintOrType(t) : t); - type = everyType(baseConstraint, isTupleType) ? - mapType(baseConstraint, t => sliceTupleType(t as TupleTypeReference, index)) : - createArrayType(elementType); + const baseConstraint = mapType( + parentType, + t => t.flags & TypeFlags.InstantiableNonPrimitive ? getBaseConstraintOrType(t) : t, + ); + type = everyType(baseConstraint, isTupleType) + ? mapType(baseConstraint, t => sliceTupleType(t as TupleTypeReference, index)) + : createArrayType(elementType); } else if (isArrayLikeType(parentType)) { const indexType = getNumberLiteralType(index); - const accessFlags = AccessFlags.ExpressionPosition | (hasDefaultValue(declaration) ? AccessFlags.NoTupleBoundsCheck : 0); - const declaredType = getIndexedAccessTypeOrUndefined(parentType, indexType, accessFlags, declaration.name) || errorType; + const accessFlags = AccessFlags.ExpressionPosition + | (hasDefaultValue(declaration) ? AccessFlags.NoTupleBoundsCheck : 0); + const declaredType = + getIndexedAccessTypeOrUndefined(parentType, indexType, accessFlags, declaration.name) || errorType; type = getFlowTypeOfDestructuring(declaration, declaredType); } else { @@ -10667,9 +13637,17 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (getEffectiveTypeAnnotationNode(walkUpBindingElementsAndPatterns(declaration))) { // In strict null checking mode, if a default value of a non-undefined type is specified, remove // undefined from the final type. - return strictNullChecks && !(getTypeFacts(checkDeclarationInitializer(declaration, CheckMode.Normal)) & TypeFacts.IsUndefined) ? getNonUndefinedType(type) : type; + return strictNullChecks + && !(getTypeFacts(checkDeclarationInitializer(declaration, CheckMode.Normal)) + & TypeFacts.IsUndefined) ? getNonUndefinedType(type) : type; } - return widenTypeInferredFromInitializer(declaration, getUnionType([getNonUndefinedType(type), checkDeclarationInitializer(declaration, CheckMode.Normal)], UnionReduction.Subtype)); + return widenTypeInferredFromInitializer( + declaration, + getUnionType( + [getNonUndefinedType(type), checkDeclarationInitializer(declaration, CheckMode.Normal)], + UnionReduction.Subtype, + ), + ); } function getTypeForDeclarationFromJSDocComment(declaration: Node) { @@ -10682,12 +13660,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function isNullOrUndefined(node: Expression) { const expr = skipParentheses(node, /*excludeJSDocTypeAssertions*/ true); - return expr.kind === SyntaxKind.NullKeyword || expr.kind === SyntaxKind.Identifier && getResolvedSymbol(expr as Identifier) === undefinedSymbol; + return expr.kind === SyntaxKind.NullKeyword + || expr.kind === SyntaxKind.Identifier && getResolvedSymbol(expr as Identifier) === undefinedSymbol; } function isEmptyArrayLiteral(node: Expression) { const expr = skipParentheses(node, /*excludeJSDocTypeAssertions*/ true); - return expr.kind === SyntaxKind.ArrayLiteralExpression && (expr as ArrayLiteralExpression).elements.length === 0; + return expr.kind === SyntaxKind.ArrayLiteralExpression + && (expr as ArrayLiteralExpression).elements.length === 0; } function addOptionality(type: Type, isProperty = false, isOptional = true): Type { @@ -10696,15 +13676,26 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // Return the inferred type for a variable, parameter, or property declaration function getTypeForVariableLikeDeclaration( - declaration: ParameterDeclaration | PropertyDeclaration | PropertySignature | VariableDeclaration | BindingElement | JSDocPropertyLikeTag, + declaration: + | ParameterDeclaration + | PropertyDeclaration + | PropertySignature + | VariableDeclaration + | BindingElement + | JSDocPropertyLikeTag, includeOptionality: boolean, checkMode: CheckMode, ): Type | undefined { // A variable declared in a for..in statement is of type string, or of type keyof T when the // right hand expression is of a type parameter type. if (isVariableDeclaration(declaration) && declaration.parent.parent.kind === SyntaxKind.ForInStatement) { - const indexType = getIndexType(getNonNullableTypeIfNeeded(checkExpression(declaration.parent.parent.expression, /*checkMode*/ checkMode))); - return indexType.flags & (TypeFlags.TypeParameter | TypeFlags.Index) ? getExtractStringType(indexType) : stringType; + const indexType = getIndexType( + getNonNullableTypeIfNeeded( + checkExpression(declaration.parent.parent.expression, /*checkMode*/ checkMode), + ), + ); + return indexType.flags & (TypeFlags.TypeParameter | TypeFlags.Index) ? getExtractStringType(indexType) + : stringType; } if (isVariableDeclaration(declaration) && declaration.parent.parent.kind === SyntaxKind.ForOfStatement) { @@ -10720,7 +13711,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return getTypeForBindingElement(declaration as BindingElement); } - const isProperty = (isPropertyDeclaration(declaration) && !hasAccessorModifier(declaration)) || isPropertySignature(declaration) || isJSDocPropertyTag(declaration); + const isProperty = (isPropertyDeclaration(declaration) && !hasAccessorModifier(declaration)) + || isPropertySignature(declaration) || isJSDocPropertyTag(declaration); const isOptional = includeOptionality && isOptionalDeclaration(declaration); // Use type from type annotation if one is present @@ -10739,14 +13731,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } if ( - (noImplicitAny || isInJSFile(declaration)) && - isVariableDeclaration(declaration) && !isBindingPattern(declaration.name) && - !(getCombinedModifierFlagsCached(declaration) & ModifierFlags.Export) && !(declaration.flags & NodeFlags.Ambient) + (noImplicitAny || isInJSFile(declaration)) + && isVariableDeclaration(declaration) && !isBindingPattern(declaration.name) + && !(getCombinedModifierFlagsCached(declaration) & ModifierFlags.Export) + && !(declaration.flags & NodeFlags.Ambient) ) { // If --noImplicitAny is on or the declaration is in a Javascript file, // use control flow tracked 'any' type for non-ambient, non-exported var or let variables with no // initializer or a 'null' or 'undefined' initializer. - if (!(getCombinedNodeFlagsCached(declaration) & NodeFlags.Constant) && (!declaration.initializer || isNullOrUndefined(declaration.initializer))) { + if ( + !(getCombinedNodeFlagsCached(declaration) & NodeFlags.Constant) + && (!declaration.initializer || isNullOrUndefined(declaration.initializer)) + ) { return autoType; } // Use control flow tracked 'any[]' type for non-ambient, non-exported variables with an empty array @@ -10760,7 +13756,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const func = declaration.parent as FunctionLikeDeclaration; // For a parameter of a set accessor, use the type of the get accessor if one is present if (func.kind === SyntaxKind.SetAccessor && hasBindableName(func)) { - const getter = getDeclarationOfKind(getSymbolOfDeclaration(declaration.parent), SyntaxKind.GetAccessor); + const getter = getDeclarationOfKind( + getSymbolOfDeclaration(declaration.parent), + SyntaxKind.GetAccessor, + ); if (getter) { const getterSignature = getSignatureFromDeclaration(getter); const thisParameter = getAccessorThisParameter(func as AccessorDeclaration); @@ -10775,7 +13774,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const parameterTypeOfTypeTag = getParameterTypeOfTypeTag(func, declaration); if (parameterTypeOfTypeTag) return parameterTypeOfTypeTag; // Use contextual parameter type if one is available - const type = declaration.symbol.escapedName === InternalSymbolName.This ? getContextualThisParameterType(func) : getContextuallyTypedParameterType(declaration); + const type = declaration.symbol.escapedName === InternalSymbolName.This + ? getContextualThisParameterType(func) : getContextuallyTypedParameterType(declaration); if (type) { return addOptionality(type, /*isProperty*/ false, isOptional); } @@ -10785,12 +13785,19 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // not a parameter of a contextually typed function if (hasOnlyExpressionInitializer(declaration) && !!declaration.initializer) { if (isInJSFile(declaration) && !isParameter(declaration)) { - const containerObjectType = getJSContainerObjectType(declaration, getSymbolOfDeclaration(declaration), getDeclaredExpandoInitializer(declaration)); + const containerObjectType = getJSContainerObjectType( + declaration, + getSymbolOfDeclaration(declaration), + getDeclaredExpandoInitializer(declaration), + ); if (containerObjectType) { return containerObjectType; } } - const type = widenTypeInferredFromInitializer(declaration, checkDeclarationInitializer(declaration, checkMode)); + const type = widenTypeInferredFromInitializer( + declaration, + checkDeclarationInitializer(declaration, checkMode), + ); return addOptionality(type, isProperty, isOptional); } @@ -10799,16 +13806,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // Use control flow analysis of this.xxx assignments in the constructor or static block to determine the type of the property. if (!hasStaticModifier(declaration)) { const constructor = findConstructorDeclaration(declaration.parent); - const type = constructor ? getFlowTypeInConstructor(declaration.symbol, constructor) : - getEffectiveModifierFlags(declaration) & ModifierFlags.Ambient ? getTypeOfPropertyInBaseClass(declaration.symbol) : - undefined; + const type = constructor ? getFlowTypeInConstructor(declaration.symbol, constructor) + : getEffectiveModifierFlags(declaration) & ModifierFlags.Ambient + ? getTypeOfPropertyInBaseClass(declaration.symbol) + : undefined; return type && addOptionality(type, /*isProperty*/ true, isOptional); } else { const staticBlocks = filter(declaration.parent.members, isClassStaticBlockDeclaration); - const type = staticBlocks.length ? getFlowTypeInStaticBlocks(declaration.symbol, staticBlocks) : - getEffectiveModifierFlags(declaration) & ModifierFlags.Ambient ? getTypeOfPropertyInBaseClass(declaration.symbol) : - undefined; + const type = staticBlocks.length ? getFlowTypeInStaticBlocks(declaration.symbol, staticBlocks) + : getEffectiveModifierFlags(declaration) & ModifierFlags.Ambient + ? getTypeOfPropertyInBaseClass(declaration.symbol) + : undefined; return type && addOptionality(type, /*isProperty*/ true, isOptional); } } @@ -10837,11 +13846,20 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const links = getSymbolLinks(symbol); if (links.isConstructorDeclaredProperty === undefined) { links.isConstructorDeclaredProperty = false; - links.isConstructorDeclaredProperty = !!getDeclaringConstructor(symbol) && every(symbol.declarations, declaration => - isBinaryExpression(declaration) && - isPossiblyAliasedThisProperty(declaration) && - (declaration.left.kind !== SyntaxKind.ElementAccessExpression || isStringOrNumericLiteralLike((declaration.left as ElementAccessExpression).argumentExpression)) && - !getAnnotatedTypeForAssignmentDeclaration(/*declaredType*/ undefined, declaration, symbol, declaration)); + links.isConstructorDeclaredProperty = !!getDeclaringConstructor(symbol) + && every(symbol.declarations, declaration => + isBinaryExpression(declaration) + && isPossiblyAliasedThisProperty(declaration) + && (declaration.left.kind !== SyntaxKind.ElementAccessExpression + || isStringOrNumericLiteralLike( + (declaration.left as ElementAccessExpression).argumentExpression, + )) + && !getAnnotatedTypeForAssignmentDeclaration( + /*declaredType*/ undefined, + declaration, + symbol, + declaration, + )); } return links.isConstructorDeclaredProperty; } @@ -10852,8 +13870,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // A property is auto-typed when its declaration has no type annotation or initializer and we're in // noImplicitAny mode or a .js file. const declaration = symbol.valueDeclaration; - return declaration && isPropertyDeclaration(declaration) && !getEffectiveTypeAnnotationNode(declaration) && - !declaration.initializer && (noImplicitAny || isInJSFile(declaration)); + return declaration && isPropertyDeclaration(declaration) && !getEffectiveTypeAnnotationNode(declaration) + && !declaration.initializer && (noImplicitAny || isInJSFile(declaration)); } function getDeclaringConstructor(symbol: Symbol) { @@ -10861,7 +13879,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return; } for (const declaration of symbol.declarations) { - const container = getThisContainer(declaration, /*includeArrowFunctions*/ false, /*includeClassComputedPropertyName*/ false); + const container = getThisContainer( + declaration, + /*includeArrowFunctions*/ false, + /*includeClassComputedPropertyName*/ false, + ); if (container && (container.kind === SyntaxKind.Constructor || isJSConstructor(container))) { return container as ConstructorDeclaration; } @@ -10872,9 +13894,17 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function getFlowTypeFromCommonJSExport(symbol: Symbol) { const file = getSourceFileOfNode(symbol.declarations![0]); const accessName = unescapeLeadingUnderscores(symbol.escapedName); - const areAllModuleExports = symbol.declarations!.every(d => isInJSFile(d) && isAccessExpression(d) && isModuleExportsAccessExpression(d.expression)); + const areAllModuleExports = symbol.declarations!.every(d => + isInJSFile(d) && isAccessExpression(d) && isModuleExportsAccessExpression(d.expression) + ); const reference = areAllModuleExports - ? factory.createPropertyAccessExpression(factory.createPropertyAccessExpression(factory.createIdentifier("module"), factory.createIdentifier("exports")), accessName) + ? factory.createPropertyAccessExpression( + factory.createPropertyAccessExpression( + factory.createIdentifier("module"), + factory.createIdentifier("exports"), + ), + accessName, + ) : factory.createPropertyAccessExpression(factory.createIdentifier("exports"), accessName); if (areAllModuleExports) { setParent((reference.expression as PropertyAccessExpression).expression, reference.expression); @@ -10896,7 +13926,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { reference.flowNode = staticBlock.returnFlowNode; const flowType = getFlowTypeOfProperty(reference, symbol); if (noImplicitAny && (flowType === autoType || flowType === autoArrayType)) { - error(symbol.valueDeclaration, Diagnostics.Member_0_implicitly_has_an_1_type, symbolToString(symbol), typeToString(flowType)); + error( + symbol.valueDeclaration, + Diagnostics.Member_0_implicitly_has_an_1_type, + symbolToString(symbol), + typeToString(flowType), + ); } // We don't infer a type if assignments are only null or undefined. if (everyType(flowType, isNullableType)) { @@ -10916,7 +13951,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { reference.flowNode = constructor.returnFlowNode; const flowType = getFlowTypeOfProperty(reference, symbol); if (noImplicitAny && (flowType === autoType || flowType === autoArrayType)) { - error(symbol.valueDeclaration, Diagnostics.Member_0_implicitly_has_an_1_type, symbolToString(symbol), typeToString(flowType)); + error( + symbol.valueDeclaration, + Diagnostics.Member_0_implicitly_has_an_1_type, + symbolToString(symbol), + typeToString(flowType), + ); } // We don't infer a type if assignments are only null or undefined. return everyType(flowType, isNullableType) ? undefined : convertAutoToAny(flowType); @@ -10924,7 +13964,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function getFlowTypeOfProperty(reference: Node, prop: Symbol | undefined) { const initialType = prop?.valueDeclaration - && (!isAutoTypedProperty(prop) || getEffectiveModifierFlags(prop.valueDeclaration) & ModifierFlags.Ambient) + && (!isAutoTypedProperty(prop) + || getEffectiveModifierFlags(prop.valueDeclaration) & ModifierFlags.Ambient) && getTypeOfPropertyInBaseClass(prop) || undefinedType; return getFlowTypeOfReference(reference, autoType, initialType); @@ -10938,7 +13979,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (tag && tag.typeExpression) { return getTypeFromTypeNode(tag.typeExpression); } - const containerObjectType = symbol.valueDeclaration && getJSContainerObjectType(symbol.valueDeclaration, symbol, container); + const containerObjectType = symbol.valueDeclaration + && getJSContainerObjectType(symbol.valueDeclaration, symbol, container); return containerObjectType || getWidenedLiteralType(checkExpressionCached(container)); } let type; @@ -10954,9 +13996,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (symbol.declarations) { let jsdocType: Type | undefined; for (const declaration of symbol.declarations) { - const expression = (isBinaryExpression(declaration) || isCallExpression(declaration)) ? declaration : - isAccessExpression(declaration) ? isBinaryExpression(declaration.parent) ? declaration.parent : declaration : - undefined; + const expression = (isBinaryExpression(declaration) || isCallExpression(declaration)) ? declaration + : isAccessExpression(declaration) + ? isBinaryExpression(declaration.parent) ? declaration.parent : declaration + : undefined; if (!expression) { continue; // Non-assignment declaration merged in (eg, an Identifier to mark the thing as a namespace) - skip over it and pull type info from elsewhere } @@ -10964,7 +14007,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const kind = isAccessExpression(expression) ? getAssignmentDeclarationPropertyAccessKind(expression) : getAssignmentDeclarationKind(expression); - if (kind === AssignmentDeclarationKind.ThisProperty || isBinaryExpression(expression) && isPossiblyAliasedThisProperty(expression, kind)) { + if ( + kind === AssignmentDeclarationKind.ThisProperty + || isBinaryExpression(expression) && isPossiblyAliasedThisProperty(expression, kind) + ) { if (isDeclarationInConstructor(expression)) { definedInConstructor = true; } @@ -10973,10 +14019,19 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } if (!isCallExpression(expression)) { - jsdocType = getAnnotatedTypeForAssignmentDeclaration(jsdocType, expression, symbol, declaration); + jsdocType = getAnnotatedTypeForAssignmentDeclaration( + jsdocType, + expression, + symbol, + declaration, + ); } if (!jsdocType) { - (types || (types = [])).push((isBinaryExpression(expression) || isCallExpression(expression)) ? getInitializerTypeFromAssignmentDeclaration(symbol, resolvedSymbol, expression, kind) : neverType); + (types || (types = [])).push( + (isBinaryExpression(expression) || isCallExpression(expression)) + ? getInitializerTypeFromAssignmentDeclaration(symbol, resolvedSymbol, expression, kind) + : neverType, + ); } } type = jsdocType; @@ -10985,7 +14040,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (!length(types)) { return errorType; // No types from any declarations :( } - let constructorTypes = definedInConstructor && symbol.declarations ? getConstructorDefinedThisAssignmentTypes(types!, symbol.declarations) : undefined; + let constructorTypes = definedInConstructor && symbol.declarations + ? getConstructorDefinedThisAssignmentTypes(types!, symbol.declarations) : undefined; // use only the constructor types unless they were only assigned null | undefined (including widening variants) if (definedInMethod) { const propType = getTypeOfPropertyInBaseClass(symbol); @@ -10994,12 +14050,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { definedInConstructor = true; } } - const sourceTypes = some(constructorTypes, t => !!(t.flags & ~TypeFlags.Nullable)) ? constructorTypes : types; // TODO: GH#18217 + const sourceTypes = some(constructorTypes, t => !!(t.flags & ~TypeFlags.Nullable)) ? constructorTypes + : types; // TODO: GH#18217 type = getUnionType(sourceTypes!); } } - const widened = getWidenedType(addOptionality(type, /*isProperty*/ false, definedInMethod && !definedInConstructor)); - if (symbol.valueDeclaration && isInJSFile(symbol.valueDeclaration) && filterType(widened, t => !!(t.flags & ~TypeFlags.Nullable)) === neverType) { + const widened = getWidenedType( + addOptionality(type, /*isProperty*/ false, definedInMethod && !definedInConstructor), + ); + if ( + symbol.valueDeclaration && isInJSFile(symbol.valueDeclaration) + && filterType(widened, t => !!(t.flags & ~TypeFlags.Nullable)) === neverType + ) { reportImplicitAny(symbol.valueDeclaration, anyType); return anyType; } @@ -11027,7 +14089,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return type; } - function getAnnotatedTypeForAssignmentDeclaration(declaredType: Type | undefined, expression: Expression, symbol: Symbol, declaration: Declaration) { + function getAnnotatedTypeForAssignmentDeclaration( + declaredType: Type | undefined, + expression: Expression, + symbol: Symbol, + declaration: Declaration, + ) { const typeNode = getEffectiveTypeAnnotationNode(expression.parent); if (typeNode) { const type = getWidenedType(getTypeFromTypeNode(typeNode)); @@ -11035,7 +14102,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return type; } else if (!isErrorType(declaredType) && !isErrorType(type) && !isTypeIdenticalTo(declaredType, type)) { - errorNextVariableOrPropertyDeclarationMustHaveSameType(/*firstDeclaration*/ undefined, declaredType, declaration, type); + errorNextVariableOrPropertyDeclarationMustHaveSameType( + /*firstDeclaration*/ undefined, + declaredType, + declaration, + type, + ); } } if (symbol.parent?.valueDeclaration) { @@ -11052,7 +14124,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } /** If we don't have an explicit JSDoc type, get the type from the initializer. */ - function getInitializerTypeFromAssignmentDeclaration(symbol: Symbol, resolvedSymbol: Symbol | undefined, expression: BinaryExpression | CallExpression, kind: AssignmentDeclarationKind) { + function getInitializerTypeFromAssignmentDeclaration( + symbol: Symbol, + resolvedSymbol: Symbol | undefined, + expression: BinaryExpression | CallExpression, + kind: AssignmentDeclarationKind, + ) { if (isCallExpression(expression)) { if (resolvedSymbol) { return getTypeOfSymbol(resolvedSymbol); // This shouldn't happen except under some hopefully forbidden merges of export assignments and object define assignments @@ -11081,14 +14158,17 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (containsSameNamedThisProperty(expression.left, expression.right)) { return anyType; } - const isDirectExport = kind === AssignmentDeclarationKind.ExportsProperty && (isPropertyAccessExpression(expression.left) || isElementAccessExpression(expression.left)) && (isModuleExportsAccessExpression(expression.left.expression) || (isIdentifier(expression.left.expression) && isExportsIdentifier(expression.left.expression))); + const isDirectExport = kind === AssignmentDeclarationKind.ExportsProperty + && (isPropertyAccessExpression(expression.left) || isElementAccessExpression(expression.left)) + && (isModuleExportsAccessExpression(expression.left.expression) + || (isIdentifier(expression.left.expression) && isExportsIdentifier(expression.left.expression))); const type = resolvedSymbol ? getTypeOfSymbol(resolvedSymbol) : isDirectExport ? getRegularTypeOfLiteralType(checkExpressionCached(expression.right)) : getWidenedLiteralType(checkExpressionCached(expression.right)); if ( - type.flags & TypeFlags.Object && - kind === AssignmentDeclarationKind.ModuleExports && - symbol.escapedName === InternalSymbolName.ExportEquals + type.flags & TypeFlags.Object + && kind === AssignmentDeclarationKind.ModuleExports + && symbol.escapedName === InternalSymbolName.ExportEquals ) { const exportedType = resolveStructuredTypeMembers(type as ObjectType); const members = createSymbolTable(); @@ -11111,16 +14191,30 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // but we may have a JS file with `module.exports = { a: true }` along with a TypeScript module augmentation // declaring an `export const a: number`. In that case, we issue a duplicate identifier error, because // it's unclear what that's supposed to mean, so it's probably a mistake. - if (s.valueDeclaration && exportedMember.valueDeclaration && getSourceFileOfNode(s.valueDeclaration) !== getSourceFileOfNode(exportedMember.valueDeclaration)) { + if ( + s.valueDeclaration && exportedMember.valueDeclaration + && getSourceFileOfNode(s.valueDeclaration) + !== getSourceFileOfNode(exportedMember.valueDeclaration) + ) { const unescapedName = unescapeLeadingUnderscores(s.escapedName); - const exportedMemberName = tryCast(exportedMember.valueDeclaration, isNamedDeclaration)?.name || exportedMember.valueDeclaration; + const exportedMemberName = + tryCast(exportedMember.valueDeclaration, isNamedDeclaration)?.name + || exportedMember.valueDeclaration; addRelatedInfo( error(s.valueDeclaration, Diagnostics.Duplicate_identifier_0, unescapedName), - createDiagnosticForNode(exportedMemberName, Diagnostics._0_was_also_declared_here, unescapedName), + createDiagnosticForNode( + exportedMemberName, + Diagnostics._0_was_also_declared_here, + unescapedName, + ), ); addRelatedInfo( error(exportedMemberName, Diagnostics.Duplicate_identifier_0, unescapedName), - createDiagnosticForNode(s.valueDeclaration, Diagnostics._0_was_also_declared_here, unescapedName), + createDiagnosticForNode( + s.valueDeclaration, + Diagnostics._0_was_also_declared_here, + unescapedName, + ), ); } const union = createSymbol(s.flags | exportedMember.flags, name); @@ -11156,7 +14250,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } result.objectFlags |= getObjectFlags(type) & ObjectFlags.JSLiteral; // Propagate JSLiteral flag - if (result.symbol && result.symbol.flags & SymbolFlags.Class && type === getDeclaredTypeOfClassOrInterface(result.symbol)) { + if ( + result.symbol && result.symbol.flags & SymbolFlags.Class + && type === getDeclaredTypeOfClassOrInterface(result.symbol) + ) { result.objectFlags |= ObjectFlags.IsClassInstanceClone; // Propagate the knowledge that this type is equivalent to the symbol's class instance type } return result; @@ -11175,20 +14272,25 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function isDeclarationInConstructor(expression: Expression) { - const thisContainer = getThisContainer(expression, /*includeArrowFunctions*/ false, /*includeClassComputedPropertyName*/ false); + const thisContainer = getThisContainer( + expression, + /*includeArrowFunctions*/ false, + /*includeClassComputedPropertyName*/ false, + ); // Properties defined in a constructor (or base constructor, or javascript constructor function) don't get undefined added. // Function expressions that are assigned to the prototype count as methods. - return thisContainer.kind === SyntaxKind.Constructor || - thisContainer.kind === SyntaxKind.FunctionDeclaration || - (thisContainer.kind === SyntaxKind.FunctionExpression && !isPrototypePropertyAssignment(thisContainer.parent)); + return thisContainer.kind === SyntaxKind.Constructor + || thisContainer.kind === SyntaxKind.FunctionDeclaration + || (thisContainer.kind === SyntaxKind.FunctionExpression + && !isPrototypePropertyAssignment(thisContainer.parent)); } function getConstructorDefinedThisAssignmentTypes(types: Type[], declarations: Declaration[]): Type[] | undefined { Debug.assert(types.length === declarations.length); return types.filter((_, i) => { const declaration = declarations[i]; - const expression = isBinaryExpression(declaration) ? declaration : - isBinaryExpression(declaration.parent) ? declaration.parent : undefined; + const expression = isBinaryExpression(declaration) ? declaration + : isBinaryExpression(declaration.parent) ? declaration.parent : undefined; return expression && isDeclarationInConstructor(expression); }); } @@ -11196,13 +14298,24 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // Return the type implied by a binding pattern element. This is the type of the initializer of the element if // one is present. Otherwise, if the element is itself a binding pattern, it is the type implied by the binding // pattern. Otherwise, it is the type any. - function getTypeFromBindingElement(element: BindingElement, includePatternInType?: boolean, reportErrors?: boolean): Type { + function getTypeFromBindingElement( + element: BindingElement, + includePatternInType?: boolean, + reportErrors?: boolean, + ): Type { if (element.initializer) { // The type implied by a binding pattern is independent of context, so we check the initializer with no // contextual type or, if the element itself is a binding pattern, with the type implied by that binding // pattern. - const contextualType = isBindingPattern(element.name) ? getTypeFromBindingPattern(element.name, /*includePatternInType*/ true, /*reportErrors*/ false) : unknownType; - return addOptionality(widenTypeInferredFromInitializer(element, checkDeclarationInitializer(element, CheckMode.Normal, contextualType))); + const contextualType = isBindingPattern(element.name) + ? getTypeFromBindingPattern(element.name, /*includePatternInType*/ true, /*reportErrors*/ false) + : unknownType; + return addOptionality( + widenTypeInferredFromInitializer( + element, + checkDeclarationInitializer(element, CheckMode.Normal, contextualType), + ), + ); } if (isBindingPattern(element.name)) { return getTypeFromBindingPattern(element.name, includePatternInType, reportErrors); @@ -11218,7 +14331,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } // Return the type implied by an object binding pattern - function getTypeFromObjectBindingPattern(pattern: ObjectBindingPattern, includePatternInType: boolean, reportErrors: boolean): Type { + function getTypeFromObjectBindingPattern( + pattern: ObjectBindingPattern, + includePatternInType: boolean, + reportErrors: boolean, + ): Type { const members = createSymbolTable(); let stringIndexInfo: IndexInfo | undefined; let objectFlags = ObjectFlags.ObjectLiteral | ObjectFlags.ContainsObjectOrArrayLiteral; @@ -11242,7 +14359,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { symbol.links.bindingElement = e; members.set(symbol.escapedName, symbol); }); - const result = createAnonymousType(/*symbol*/ undefined, members, emptyArray, emptyArray, stringIndexInfo ? [stringIndexInfo] : emptyArray); + const result = createAnonymousType( + /*symbol*/ undefined, + members, + emptyArray, + emptyArray, + stringIndexInfo ? [stringIndexInfo] : emptyArray, + ); result.objectFlags |= objectFlags; if (includePatternInType) { result.pattern = pattern; @@ -11252,16 +14375,32 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } // Return the type implied by an array binding pattern - function getTypeFromArrayBindingPattern(pattern: BindingPattern, includePatternInType: boolean, reportErrors: boolean): Type { + function getTypeFromArrayBindingPattern( + pattern: BindingPattern, + includePatternInType: boolean, + reportErrors: boolean, + ): Type { const elements = pattern.elements; const lastElement = lastOrUndefined(elements); - const restElement = lastElement && lastElement.kind === SyntaxKind.BindingElement && lastElement.dotDotDotToken ? lastElement : undefined; + const restElement = lastElement && lastElement.kind === SyntaxKind.BindingElement && lastElement.dotDotDotToken + ? lastElement : undefined; if (elements.length === 0 || elements.length === 1 && restElement) { return languageVersion >= ScriptTarget.ES2015 ? createIterableType(anyType) : anyArrayType; } - const elementTypes = map(elements, e => isOmittedExpression(e) ? anyType : getTypeFromBindingElement(e, includePatternInType, reportErrors)); - const minLength = findLastIndex(elements, e => !(e === restElement || isOmittedExpression(e) || hasDefaultValue(e)), elements.length - 1) + 1; - const elementFlags = map(elements, (e, i) => e === restElement ? ElementFlags.Rest : i >= minLength ? ElementFlags.Optional : ElementFlags.Required); + const elementTypes = map( + elements, + e => isOmittedExpression(e) ? anyType : getTypeFromBindingElement(e, includePatternInType, reportErrors), + ); + const minLength = findLastIndex( + elements, + e => !(e === restElement || isOmittedExpression(e) || hasDefaultValue(e)), + elements.length - 1, + ) + 1; + const elementFlags = map( + elements, + (e, i) => + e === restElement ? ElementFlags.Rest : i >= minLength ? ElementFlags.Optional : ElementFlags.Required, + ); let result = createTupleType(elementTypes, elementFlags) as TypeReference; if (includePatternInType) { result = cloneTypeReference(result); @@ -11278,7 +14417,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // used as the contextual type of an initializer associated with the binding pattern. Also, for a destructuring // parameter with no type annotation or initializer, the type implied by the binding pattern becomes the type of // the parameter. - function getTypeFromBindingPattern(pattern: BindingPattern, includePatternInType = false, reportErrors = false): Type { + function getTypeFromBindingPattern( + pattern: BindingPattern, + includePatternInType = false, + reportErrors = false, + ): Type { return pattern.kind === SyntaxKind.ObjectBindingPattern ? getTypeFromObjectBindingPattern(pattern, includePatternInType, reportErrors) : getTypeFromArrayBindingPattern(pattern, includePatternInType, reportErrors); @@ -11293,8 +14436,21 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // Here, the array literal [1, "one"] is contextually typed by the type [any, string], which is the implied type of the // binding pattern [x, s = ""]. Because the contextual type is a tuple type, the resulting type of [1, "one"] is the // tuple type [number, string]. Thus, the type inferred for 'x' is number and the type inferred for 's' is string. - function getWidenedTypeForVariableLikeDeclaration(declaration: ParameterDeclaration | PropertyDeclaration | PropertySignature | VariableDeclaration | BindingElement | JSDocPropertyLikeTag, reportErrors?: boolean): Type { - return widenTypeForVariableLikeDeclaration(getTypeForVariableLikeDeclaration(declaration, /*includeOptionality*/ true, CheckMode.Normal), declaration, reportErrors); + function getWidenedTypeForVariableLikeDeclaration( + declaration: + | ParameterDeclaration + | PropertyDeclaration + | PropertySignature + | VariableDeclaration + | BindingElement + | JSDocPropertyLikeTag, + reportErrors?: boolean, + ): Type { + return widenTypeForVariableLikeDeclaration( + getTypeForVariableLikeDeclaration(declaration, /*includeOptionality*/ true, CheckMode.Normal), + declaration, + reportErrors, + ); } function isGlobalSymbolConstructor(node: Node) { @@ -11314,7 +14470,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } // always widen a 'unique symbol' type if the type was created for a different declaration. - if (type.flags & TypeFlags.UniqueESSymbol && (isBindingElement(declaration) || !declaration.type) && type.symbol !== getSymbolOfDeclaration(declaration)) { + if ( + type.flags & TypeFlags.UniqueESSymbol && (isBindingElement(declaration) || !declaration.type) + && type.symbol !== getSymbolOfDeclaration(declaration) + ) { type = esSymbolType; } @@ -11424,12 +14583,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } let type: Type; if (declaration.kind === SyntaxKind.ExportAssignment) { - type = widenTypeForVariableLikeDeclaration(tryGetTypeFromEffectiveTypeNode(declaration) || checkExpressionCached((declaration as ExportAssignment).expression), declaration); + type = widenTypeForVariableLikeDeclaration( + tryGetTypeFromEffectiveTypeNode(declaration) + || checkExpressionCached((declaration as ExportAssignment).expression), + declaration, + ); } else if ( - isBinaryExpression(declaration) || - (isInJSFile(declaration) && - (isCallExpression(declaration) || (isPropertyAccessExpression(declaration) || isBindableStaticElementAccessExpression(declaration)) && isBinaryExpression(declaration.parent))) + isBinaryExpression(declaration) + || (isInJSFile(declaration) + && (isCallExpression(declaration) + || (isPropertyAccessExpression(declaration) || isBindableStaticElementAccessExpression(declaration)) + && isBinaryExpression(declaration.parent))) ) { type = getWidenedTypeForAssignmentDeclaration(symbol); } @@ -11446,12 +14611,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { || isSourceFile(declaration) ) { // Symbol is property of some kind that is merged with something - should use `getTypeOfFuncClassEnumModule` and not `getTypeOfVariableOrParameterOrProperty` - if (symbol.flags & (SymbolFlags.Function | SymbolFlags.Method | SymbolFlags.Class | SymbolFlags.Enum | SymbolFlags.ValueModule)) { + if ( + symbol.flags + & (SymbolFlags.Function | SymbolFlags.Method | SymbolFlags.Class | SymbolFlags.Enum + | SymbolFlags.ValueModule) + ) { return getTypeOfFuncClassEnumModule(symbol); } - type = isBinaryExpression(declaration.parent) ? - getWidenedTypeForAssignmentDeclaration(symbol) : - tryGetTypeFromEffectiveTypeNode(declaration) || anyType; + type = isBinaryExpression(declaration.parent) + ? getWidenedTypeForAssignmentDeclaration(symbol) + : tryGetTypeFromEffectiveTypeNode(declaration) || anyType; } else if (isPropertyAssignment(declaration)) { type = tryGetTypeFromEffectiveTypeNode(declaration) || checkPropertyAssignment(declaration); @@ -11460,10 +14629,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { type = tryGetTypeFromEffectiveTypeNode(declaration) || checkJsxAttribute(declaration); } else if (isShorthandPropertyAssignment(declaration)) { - type = tryGetTypeFromEffectiveTypeNode(declaration) || checkExpressionForMutableLocation(declaration.name, CheckMode.Normal); + type = tryGetTypeFromEffectiveTypeNode(declaration) + || checkExpressionForMutableLocation(declaration.name, CheckMode.Normal); } else if (isObjectLiteralMethod(declaration)) { - type = tryGetTypeFromEffectiveTypeNode(declaration) || checkObjectLiteralMethod(declaration, CheckMode.Normal); + type = tryGetTypeFromEffectiveTypeNode(declaration) + || checkObjectLiteralMethod(declaration, CheckMode.Normal); } else if ( isParameter(declaration) @@ -11484,7 +14655,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { type = getTypeOfEnumMember(symbol); } else { - return Debug.fail("Unhandled declaration kind! " + Debug.formatSyntaxKind(declaration.kind) + " for " + Debug.formatSymbol(symbol)); + return Debug.fail( + "Unhandled declaration kind! " + Debug.formatSyntaxKind(declaration.kind) + " for " + + Debug.formatSymbol(symbol), + ); } if (!popTypeResolution()) { @@ -11497,7 +14671,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return type; } - function getAnnotatedAccessorTypeNode(accessor: AccessorDeclaration | PropertyDeclaration | undefined): TypeNode | undefined { + function getAnnotatedAccessorTypeNode( + accessor: AccessorDeclaration | PropertyDeclaration | undefined, + ): TypeNode | undefined { if (accessor) { switch (accessor.kind) { case SyntaxKind.GetAccessor: @@ -11515,7 +14691,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return undefined; } - function getAnnotatedAccessorType(accessor: AccessorDeclaration | PropertyDeclaration | undefined): Type | undefined { + function getAnnotatedAccessorType( + accessor: AccessorDeclaration | PropertyDeclaration | undefined, + ): Type | undefined { const node = getAnnotatedAccessorTypeNode(accessor); return node && getTypeFromTypeNode(node); } @@ -11537,40 +14715,79 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } const getter = getDeclarationOfKind(symbol, SyntaxKind.GetAccessor); const setter = getDeclarationOfKind(symbol, SyntaxKind.SetAccessor); - const accessor = tryCast(getDeclarationOfKind(symbol, SyntaxKind.PropertyDeclaration), isAutoAccessorPropertyDeclaration); + const accessor = tryCast( + getDeclarationOfKind(symbol, SyntaxKind.PropertyDeclaration), + isAutoAccessorPropertyDeclaration, + ); // We try to resolve a getter type annotation, a setter type annotation, or a getter function // body return type inference, in that order. - let type = getter && isInJSFile(getter) && getTypeForDeclarationFromJSDocComment(getter) || - getAnnotatedAccessorType(getter) || - getAnnotatedAccessorType(setter) || - getAnnotatedAccessorType(accessor) || - getter && getter.body && getReturnTypeFromBody(getter) || - accessor && accessor.initializer && getWidenedTypeForVariableLikeDeclaration(accessor, /*reportErrors*/ true); + let type = getter && isInJSFile(getter) && getTypeForDeclarationFromJSDocComment(getter) + || getAnnotatedAccessorType(getter) + || getAnnotatedAccessorType(setter) + || getAnnotatedAccessorType(accessor) + || getter && getter.body && getReturnTypeFromBody(getter) + || accessor && accessor.initializer + && getWidenedTypeForVariableLikeDeclaration(accessor, /*reportErrors*/ true); if (!type) { if (setter && !isPrivateWithinAmbient(setter)) { - errorOrSuggestion(noImplicitAny, setter, Diagnostics.Property_0_implicitly_has_type_any_because_its_set_accessor_lacks_a_parameter_type_annotation, symbolToString(symbol)); + errorOrSuggestion( + noImplicitAny, + setter, + Diagnostics + .Property_0_implicitly_has_type_any_because_its_set_accessor_lacks_a_parameter_type_annotation, + symbolToString(symbol), + ); } else if (getter && !isPrivateWithinAmbient(getter)) { - errorOrSuggestion(noImplicitAny, getter, Diagnostics.Property_0_implicitly_has_type_any_because_its_get_accessor_lacks_a_return_type_annotation, symbolToString(symbol)); + errorOrSuggestion( + noImplicitAny, + getter, + Diagnostics + .Property_0_implicitly_has_type_any_because_its_get_accessor_lacks_a_return_type_annotation, + symbolToString(symbol), + ); } else if (accessor && !isPrivateWithinAmbient(accessor)) { - errorOrSuggestion(noImplicitAny, accessor, Diagnostics.Member_0_implicitly_has_an_1_type, symbolToString(symbol), "any"); + errorOrSuggestion( + noImplicitAny, + accessor, + Diagnostics.Member_0_implicitly_has_an_1_type, + symbolToString(symbol), + "any", + ); } type = anyType; } if (!popTypeResolution()) { if (getAnnotatedAccessorTypeNode(getter)) { - error(getter, Diagnostics._0_is_referenced_directly_or_indirectly_in_its_own_type_annotation, symbolToString(symbol)); + error( + getter, + Diagnostics._0_is_referenced_directly_or_indirectly_in_its_own_type_annotation, + symbolToString(symbol), + ); } else if (getAnnotatedAccessorTypeNode(setter)) { - error(setter, Diagnostics._0_is_referenced_directly_or_indirectly_in_its_own_type_annotation, symbolToString(symbol)); + error( + setter, + Diagnostics._0_is_referenced_directly_or_indirectly_in_its_own_type_annotation, + symbolToString(symbol), + ); } else if (getAnnotatedAccessorTypeNode(accessor)) { - error(setter, Diagnostics._0_is_referenced_directly_or_indirectly_in_its_own_type_annotation, symbolToString(symbol)); + error( + setter, + Diagnostics._0_is_referenced_directly_or_indirectly_in_its_own_type_annotation, + symbolToString(symbol), + ); } else if (getter && noImplicitAny) { - error(getter, Diagnostics._0_implicitly_has_return_type_any_because_it_does_not_have_a_return_type_annotation_and_is_referenced_directly_or_indirectly_in_one_of_its_return_expressions, symbolToString(symbol)); + error( + getter, + Diagnostics + ._0_implicitly_has_return_type_any_because_it_does_not_have_a_return_type_annotation_and_is_referenced_directly_or_indirectly_in_one_of_its_return_expressions, + symbolToString(symbol), + ); } type = anyType; } @@ -11587,11 +14804,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } const setter = getDeclarationOfKind(symbol, SyntaxKind.SetAccessor) - ?? tryCast(getDeclarationOfKind(symbol, SyntaxKind.PropertyDeclaration), isAutoAccessorPropertyDeclaration); + ?? tryCast( + getDeclarationOfKind(symbol, SyntaxKind.PropertyDeclaration), + isAutoAccessorPropertyDeclaration, + ); let writeType = getAnnotatedAccessorType(setter); if (!popTypeResolution()) { if (getAnnotatedAccessorTypeNode(setter)) { - error(setter, Diagnostics._0_is_referenced_directly_or_indirectly_in_its_own_type_annotation, symbolToString(symbol)); + error( + setter, + Diagnostics._0_is_referenced_directly_or_indirectly_in_its_own_type_annotation, + symbolToString(symbol), + ); } writeType = anyType; } @@ -11603,16 +14827,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function getBaseTypeVariableOfClass(symbol: Symbol) { const baseConstructorType = getBaseConstructorTypeOfClass(getDeclaredTypeOfClassOrInterface(symbol)); - return baseConstructorType.flags & TypeFlags.TypeVariable ? baseConstructorType : - baseConstructorType.flags & TypeFlags.Intersection ? find((baseConstructorType as IntersectionType).types, t => !!(t.flags & TypeFlags.TypeVariable)) : - undefined; + return baseConstructorType.flags & TypeFlags.TypeVariable ? baseConstructorType + : baseConstructorType.flags & TypeFlags.Intersection + ? find((baseConstructorType as IntersectionType).types, t => !!(t.flags & TypeFlags.TypeVariable)) + : undefined; } function getTypeOfFuncClassEnumModule(symbol: Symbol): Type { let links = getSymbolLinks(symbol); const originalLinks = links; if (!links.type) { - const expando = symbol.valueDeclaration && getSymbolOfExpando(symbol.valueDeclaration, /*allowDeclaration*/ false); + const expando = symbol.valueDeclaration + && getSymbolOfExpando(symbol.valueDeclaration, /*allowDeclaration*/ false); if (expando) { const merged = mergeJSSymbols(symbol, expando); if (merged) { @@ -11632,20 +14858,26 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return anyType; } else if ( - declaration && (declaration.kind === SyntaxKind.BinaryExpression || - isAccessExpression(declaration) && - declaration.parent.kind === SyntaxKind.BinaryExpression) + declaration && (declaration.kind === SyntaxKind.BinaryExpression + || isAccessExpression(declaration) + && declaration.parent.kind === SyntaxKind.BinaryExpression) ) { return getWidenedTypeForAssignmentDeclaration(symbol); } - else if (symbol.flags & SymbolFlags.ValueModule && declaration && isSourceFile(declaration) && declaration.commonJsModuleIndicator) { + else if ( + symbol.flags & SymbolFlags.ValueModule && declaration && isSourceFile(declaration) + && declaration.commonJsModuleIndicator + ) { const resolvedModule = resolveExternalModuleSymbol(symbol); if (resolvedModule !== symbol) { if (!pushTypeResolution(symbol, TypeSystemPropertyName.Type)) { return errorType; } const exportEquals = getMergedSymbol(symbol.exports!.get(InternalSymbolName.ExportEquals)!); - const type = getWidenedTypeForAssignmentDeclaration(exportEquals, exportEquals === resolvedModule ? undefined : resolvedModule); + const type = getWidenedTypeForAssignmentDeclaration( + exportEquals, + exportEquals === resolvedModule ? undefined : resolvedModule, + ); if (!popTypeResolution()) { return reportCircularityError(symbol); } @@ -11658,7 +14890,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return baseTypeVariable ? getIntersectionType([type, baseTypeVariable]) : type; } else { - return strictNullChecks && symbol.flags & SymbolFlags.Optional ? getOptionalType(type, /*isProperty*/ true) : type; + return strictNullChecks && symbol.flags & SymbolFlags.Optional ? getOptionalType(type, /*isProperty*/ true) + : type; } } @@ -11671,14 +14904,19 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const links = getSymbolLinks(symbol); if (!links.type) { const targetSymbol = resolveAlias(symbol); - const exportSymbol = symbol.declarations && getTargetOfAliasDeclaration(getDeclarationOfAliasSymbol(symbol)!, /*dontRecursivelyResolve*/ true); - const declaredType = firstDefined(exportSymbol?.declarations, d => isExportAssignment(d) ? tryGetTypeFromEffectiveTypeNode(d) : undefined); + const exportSymbol = symbol.declarations + && getTargetOfAliasDeclaration(getDeclarationOfAliasSymbol(symbol)!, /*dontRecursivelyResolve*/ true); + const declaredType = firstDefined( + exportSymbol?.declarations, + d => isExportAssignment(d) ? tryGetTypeFromEffectiveTypeNode(d) : undefined, + ); // It only makes sense to get the type of a value symbol. If the result of resolving // the alias is not a value, then it has no type. To get the type associated with a // type symbol, call getDeclaredTypeOfSymbol. // This check is important because without it, a call to getTypeOfSymbol could end // up recursively calling getTypeOfAlias, causing a stack overflow. - links.type = exportSymbol?.declarations && isDuplicatedCommonJSExport(exportSymbol.declarations) && symbol.declarations!.length ? getFlowTypeFromCommonJSExport(exportSymbol) + links.type = exportSymbol?.declarations && isDuplicatedCommonJSExport(exportSymbol.declarations) + && symbol.declarations!.length ? getFlowTypeFromCommonJSExport(exportSymbol) : isDuplicatedCommonJSExport(symbol.declarations) ? autoType : declaredType ? declaredType : getSymbolFlags(targetSymbol) & SymbolFlags.Value ? getTypeOfSymbol(targetSymbol) @@ -11694,19 +14932,31 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function getWriteTypeOfInstantiatedSymbol(symbol: Symbol): Type { const links = getSymbolLinks(symbol); - return links.writeType || (links.writeType = instantiateType(getWriteTypeOfSymbol(links.target!), links.mapper)); + return links.writeType + || (links.writeType = instantiateType(getWriteTypeOfSymbol(links.target!), links.mapper)); } function reportCircularityError(symbol: Symbol) { const declaration = symbol.valueDeclaration as VariableLikeDeclaration; // Check if variable has type annotation that circularly references the variable itself if (getEffectiveTypeAnnotationNode(declaration)) { - error(symbol.valueDeclaration, Diagnostics._0_is_referenced_directly_or_indirectly_in_its_own_type_annotation, symbolToString(symbol)); + error( + symbol.valueDeclaration, + Diagnostics._0_is_referenced_directly_or_indirectly_in_its_own_type_annotation, + symbolToString(symbol), + ); return errorType; } // Check if variable has initializer that circularly references the variable itself - if (noImplicitAny && (declaration.kind !== SyntaxKind.Parameter || (declaration as HasInitializer).initializer)) { - error(symbol.valueDeclaration, Diagnostics._0_implicitly_has_type_any_because_it_does_not_have_a_type_annotation_and_is_referenced_directly_or_indirectly_in_its_own_initializer, symbolToString(symbol)); + if ( + noImplicitAny && (declaration.kind !== SyntaxKind.Parameter || (declaration as HasInitializer).initializer) + ) { + error( + symbol.valueDeclaration, + Diagnostics + ._0_implicitly_has_type_any_because_it_does_not_have_a_type_annotation_and_is_referenced_directly_or_indirectly_in_its_own_initializer, + symbolToString(symbol), + ); } // Circularities could also result from parameters in function expressions that end up // having themselves as contextual types following type argument inference. In those cases @@ -11719,7 +14969,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (!links.type) { Debug.assertIsDefined(links.deferralParent); Debug.assertIsDefined(links.deferralConstituents); - links.type = links.deferralParent.flags & TypeFlags.Union ? getUnionType(links.deferralConstituents) : getIntersectionType(links.deferralConstituents); + links.type = links.deferralParent.flags & TypeFlags.Union ? getUnionType(links.deferralConstituents) + : getIntersectionType(links.deferralConstituents); } return links.type; } @@ -11729,7 +14980,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (!links.writeType && links.deferralWriteConstituents) { Debug.assertIsDefined(links.deferralParent); Debug.assertIsDefined(links.deferralConstituents); - links.writeType = links.deferralParent.flags & TypeFlags.Union ? getUnionType(links.deferralWriteConstituents) : getIntersectionType(links.deferralWriteConstituents); + links.writeType = links.deferralParent.flags & TypeFlags.Union + ? getUnionType(links.deferralWriteConstituents) : getIntersectionType(links.deferralWriteConstituents); } return links.writeType; } @@ -11742,17 +14994,17 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function getWriteTypeOfSymbol(symbol: Symbol): Type { const checkFlags = getCheckFlags(symbol); if (symbol.flags & SymbolFlags.Property) { - return checkFlags & CheckFlags.SyntheticProperty ? - checkFlags & CheckFlags.DeferredType ? - getWriteTypeOfSymbolWithDeferredType(symbol) || getTypeOfSymbolWithDeferredType(symbol) : + return checkFlags & CheckFlags.SyntheticProperty + ? checkFlags & CheckFlags.DeferredType + ? getWriteTypeOfSymbolWithDeferredType(symbol) || getTypeOfSymbolWithDeferredType(symbol) // NOTE: cast to TransientSymbol should be safe because only TransientSymbols can have CheckFlags.SyntheticProperty - (symbol as TransientSymbol).links.writeType || (symbol as TransientSymbol).links.type! : - getTypeOfSymbol(symbol); + : (symbol as TransientSymbol).links.writeType || (symbol as TransientSymbol).links.type! + : getTypeOfSymbol(symbol); } if (symbol.flags & SymbolFlags.Accessor) { - return checkFlags & CheckFlags.Instantiated ? - getWriteTypeOfInstantiatedSymbol(symbol) : - getWriteTypeOfAccessors(symbol); + return checkFlags & CheckFlags.Instantiated + ? getWriteTypeOfInstantiatedSymbol(symbol) + : getWriteTypeOfAccessors(symbol); } return getTypeOfSymbol(symbol); } @@ -11774,7 +15026,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (symbol.flags & (SymbolFlags.Variable | SymbolFlags.Property)) { return getTypeOfVariableOrParameterOrProperty(symbol); } - if (symbol.flags & (SymbolFlags.Function | SymbolFlags.Method | SymbolFlags.Class | SymbolFlags.Enum | SymbolFlags.ValueModule)) { + if ( + symbol.flags + & (SymbolFlags.Function | SymbolFlags.Method | SymbolFlags.Class | SymbolFlags.Enum + | SymbolFlags.ValueModule) + ) { return getTypeOfFuncClassEnumModule(symbol); } if (symbol.flags & SymbolFlags.EnumMember) { @@ -11822,9 +15078,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // Appends the type parameters given by a list of declarations to a set of type parameters and returns the resulting set. // The function allocates a new array if the input type parameter set is undefined, but otherwise it modifies the set // in-place and returns the same array. - function appendTypeParameters(typeParameters: TypeParameter[] | undefined, declarations: readonly TypeParameterDeclaration[]): TypeParameter[] | undefined { + function appendTypeParameters( + typeParameters: TypeParameter[] | undefined, + declarations: readonly TypeParameterDeclaration[], + ): TypeParameter[] | undefined { for (const declaration of declarations) { - typeParameters = appendIfUnique(typeParameters, getDeclaredTypeOfTypeParameter(getSymbolOfDeclaration(declaration))); + typeParameters = appendIfUnique( + typeParameters, + getDeclaredTypeOfTypeParameter(getSymbolOfDeclaration(declaration)), + ); } return typeParameters; } @@ -11836,8 +15098,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (node && isBinaryExpression(node)) { // prototype assignments get the outer type parameters of their constructor function const assignmentKind = getAssignmentDeclarationKind(node); - if (assignmentKind === AssignmentDeclarationKind.Prototype || assignmentKind === AssignmentDeclarationKind.PrototypeProperty) { - const symbol = getSymbolOfDeclaration(node.left as BindableStaticNameExpression | PropertyAssignment); + if ( + assignmentKind === AssignmentDeclarationKind.Prototype + || assignmentKind === AssignmentDeclarationKind.PrototypeProperty + ) { + const symbol = getSymbolOfDeclaration( + node.left as BindableStaticNameExpression | PropertyAssignment, + ); if (symbol && symbol.parent && !findAncestor(symbol.parent.valueDeclaration, d => node === d)) { node = symbol.parent.valueDeclaration!; } @@ -11869,15 +15136,26 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { case SyntaxKind.ConditionalType: { const outerTypeParameters = getOuterTypeParameters(node, includeThisTypes); if (node.kind === SyntaxKind.MappedType) { - return append(outerTypeParameters, getDeclaredTypeOfTypeParameter(getSymbolOfDeclaration((node as MappedTypeNode).typeParameter))); + return append( + outerTypeParameters, + getDeclaredTypeOfTypeParameter( + getSymbolOfDeclaration((node as MappedTypeNode).typeParameter), + ), + ); } else if (node.kind === SyntaxKind.ConditionalType) { return concatenate(outerTypeParameters, getInferTypeParameters(node as ConditionalTypeNode)); } - const outerAndOwnTypeParameters = appendTypeParameters(outerTypeParameters, getEffectiveTypeParameterDeclarations(node as DeclarationWithTypeParameters)); - const thisType = includeThisTypes && - (node.kind === SyntaxKind.ClassDeclaration || node.kind === SyntaxKind.ClassExpression || node.kind === SyntaxKind.InterfaceDeclaration || isJSConstructor(node)) && - getDeclaredTypeOfClassOrInterface(getSymbolOfDeclaration(node as ClassLikeDeclaration | InterfaceDeclaration)).thisType; + const outerAndOwnTypeParameters = appendTypeParameters( + outerTypeParameters, + getEffectiveTypeParameterDeclarations(node as DeclarationWithTypeParameters), + ); + const thisType = includeThisTypes + && (node.kind === SyntaxKind.ClassDeclaration || node.kind === SyntaxKind.ClassExpression + || node.kind === SyntaxKind.InterfaceDeclaration || isJSConstructor(node)) + && getDeclaredTypeOfClassOrInterface( + getSymbolOfDeclaration(node as ClassLikeDeclaration | InterfaceDeclaration), + ).thisType; return thisType ? append(outerAndOwnTypeParameters, thisType) : outerAndOwnTypeParameters; } case SyntaxKind.JSDocParameterTag: @@ -11889,7 +15167,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { case SyntaxKind.JSDoc: { const outerTypeParameters = getOuterTypeParameters(node, includeThisTypes); return (node as JSDoc).tags - ? appendTypeParameters(outerTypeParameters, flatMap((node as JSDoc).tags, t => isJSDocTemplateTag(t) ? t.typeParameters : undefined)) + ? appendTypeParameters( + outerTypeParameters, + flatMap((node as JSDoc).tags, t => isJSDocTemplateTag(t) ? t.typeParameters : undefined), + ) : outerTypeParameters; } } @@ -11908,7 +15189,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return false; } const initializer = (decl as VariableDeclaration).initializer; - return !!initializer && (initializer.kind === SyntaxKind.FunctionExpression || initializer.kind === SyntaxKind.ArrowFunction); + return !!initializer + && (initializer.kind === SyntaxKind.FunctionExpression + || initializer.kind === SyntaxKind.ArrowFunction); })!; Debug.assert(!!declaration, "Class was missing valueDeclaration -OR- non-class had no interface declarations"); return getOuterTypeParameters(declaration); @@ -11923,13 +15206,17 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { let result: TypeParameter[] | undefined; for (const node of symbol.declarations) { if ( - node.kind === SyntaxKind.InterfaceDeclaration || - node.kind === SyntaxKind.ClassDeclaration || - node.kind === SyntaxKind.ClassExpression || - isJSConstructor(node) || - isTypeAlias(node) + node.kind === SyntaxKind.InterfaceDeclaration + || node.kind === SyntaxKind.ClassDeclaration + || node.kind === SyntaxKind.ClassExpression + || isJSConstructor(node) + || isTypeAlias(node) ) { - const declaration = node as InterfaceDeclaration | TypeAliasDeclaration | JSDocTypedefTag | JSDocCallbackTag; + const declaration = node as + | InterfaceDeclaration + | TypeAliasDeclaration + | JSDocTypedefTag + | JSDocCallbackTag; result = appendTypeParameters(result, getEffectiveTypeParameterDeclarations(declaration)); } } @@ -11939,7 +15226,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // The full set of type parameters for a generic class or interface type consists of its outer type parameters plus // its locally declared type parameters. function getTypeParametersOfClassOrInterface(symbol: Symbol): TypeParameter[] | undefined { - return concatenate(getOuterTypeParametersOfClassOrInterface(symbol), getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(symbol)); + return concatenate( + getOuterTypeParametersOfClassOrInterface(symbol), + getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(symbol), + ); } // A type is a mixin constructor if it has a single construct signature taking no type parameters and a single @@ -11972,16 +15262,32 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return decl && getEffectiveBaseTypeNode(decl); } - function getConstructorsForTypeArguments(type: Type, typeArgumentNodes: readonly TypeNode[] | undefined, location: Node): readonly Signature[] { + function getConstructorsForTypeArguments( + type: Type, + typeArgumentNodes: readonly TypeNode[] | undefined, + location: Node, + ): readonly Signature[] { const typeArgCount = length(typeArgumentNodes); const isJavascript = isInJSFile(location); - return filter(getSignaturesOfType(type, SignatureKind.Construct), sig => (isJavascript || typeArgCount >= getMinTypeArgumentCount(sig.typeParameters)) && typeArgCount <= length(sig.typeParameters)); + return filter( + getSignaturesOfType(type, SignatureKind.Construct), + sig => + (isJavascript || typeArgCount >= getMinTypeArgumentCount(sig.typeParameters)) + && typeArgCount <= length(sig.typeParameters), + ); } - function getInstantiatedConstructorsForTypeArguments(type: Type, typeArgumentNodes: readonly TypeNode[] | undefined, location: Node): readonly Signature[] { + function getInstantiatedConstructorsForTypeArguments( + type: Type, + typeArgumentNodes: readonly TypeNode[] | undefined, + location: Node, + ): readonly Signature[] { const signatures = getConstructorsForTypeArguments(type, typeArgumentNodes, location); const typeArguments = map(typeArgumentNodes, getTypeFromTypeNode); - return sameMap(signatures, sig => some(sig.typeParameters) ? getSignatureInstantiation(sig, typeArguments, isInJSFile(location)) : sig); + return sameMap( + signatures, + sig => some(sig.typeParameters) ? getSignatureInstantiation(sig, typeArguments, isInJSFile(location)) : sig, + ); } /** @@ -12014,11 +15320,22 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { resolveStructuredTypeMembers(baseConstructorType as ObjectType); } if (!popTypeResolution()) { - error(type.symbol.valueDeclaration, Diagnostics._0_is_referenced_directly_or_indirectly_in_its_own_base_expression, symbolToString(type.symbol)); + error( + type.symbol.valueDeclaration, + Diagnostics._0_is_referenced_directly_or_indirectly_in_its_own_base_expression, + symbolToString(type.symbol), + ); return type.resolvedBaseConstructorType = errorType; } - if (!(baseConstructorType.flags & TypeFlags.Any) && baseConstructorType !== nullWideningType && !isConstructorType(baseConstructorType)) { - const err = error(baseTypeNode.expression, Diagnostics.Type_0_is_not_a_constructor_function_type, typeToString(baseConstructorType)); + if ( + !(baseConstructorType.flags & TypeFlags.Any) && baseConstructorType !== nullWideningType + && !isConstructorType(baseConstructorType) + ) { + const err = error( + baseTypeNode.expression, + Diagnostics.Type_0_is_not_a_constructor_function_type, + typeToString(baseConstructorType), + ); if (baseConstructorType.flags & TypeFlags.TypeParameter) { const constraint = getConstraintFromTypeParameter(baseConstructorType); let ctorReturn: Type = unknownType; @@ -12029,7 +15346,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } if (baseConstructorType.symbol.declarations) { - addRelatedInfo(err, createDiagnosticForNode(baseConstructorType.symbol.declarations[0], Diagnostics.Did_you_mean_for_0_to_be_constrained_to_type_new_args_Colon_any_1, symbolToString(baseConstructorType.symbol), typeToString(ctorReturn))); + addRelatedInfo( + err, + createDiagnosticForNode( + baseConstructorType.symbol.declarations[0], + Diagnostics.Did_you_mean_for_0_to_be_constrained_to_type_new_args_Colon_any_1, + symbolToString(baseConstructorType.symbol), + typeToString(ctorReturn), + ), + ); } } return type.resolvedBaseConstructorType = errorType; @@ -12062,7 +15387,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function reportCircularBaseType(node: Node, type: Type) { - error(node, Diagnostics.Type_0_recursively_references_itself_as_a_base_type, typeToString(type, /*enclosingDeclaration*/ undefined, TypeFormatFlags.WriteArrayAsGenericType)); + error( + node, + Diagnostics.Type_0_recursively_references_itself_as_a_base_type, + typeToString(type, /*enclosingDeclaration*/ undefined, TypeFormatFlags.WriteArrayAsGenericType), + ); } function getBaseTypes(type: InterfaceType): BaseType[] { @@ -12084,7 +15413,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } if (!popTypeResolution() && type.symbol.declarations) { for (const declaration of type.symbol.declarations) { - if (declaration.kind === SyntaxKind.ClassDeclaration || declaration.kind === SyntaxKind.InterfaceDeclaration) { + if ( + declaration.kind === SyntaxKind.ClassDeclaration + || declaration.kind === SyntaxKind.InterfaceDeclaration + ) { reportCircularBaseType(declaration, type); } } @@ -12096,7 +15428,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function getTupleBaseType(type: TupleType) { - const elementTypes = sameMap(type.typeParameters, (t, i) => type.elementFlags[i] & ElementFlags.Variadic ? getIndexedAccessType(t, numberType) : t); + const elementTypes = sameMap( + type.typeParameters, + (t, i) => type.elementFlags[i] & ElementFlags.Variadic ? getIndexedAccessType(t, numberType) : t, + ); return createArrayType(getUnionType(elementTypes || emptyArray), type.readonly); } @@ -12108,10 +15443,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } const baseTypeNode = getBaseTypeNodeOfClass(type)!; let baseType: Type; - const originalBaseType = baseConstructorType.symbol ? getDeclaredTypeOfSymbol(baseConstructorType.symbol) : undefined; + const originalBaseType = baseConstructorType.symbol ? getDeclaredTypeOfSymbol(baseConstructorType.symbol) + : undefined; if ( - baseConstructorType.symbol && baseConstructorType.symbol.flags & SymbolFlags.Class && - areAllOuterTypeParametersApplied(originalBaseType!) + baseConstructorType.symbol && baseConstructorType.symbol.flags & SymbolFlags.Class + && areAllOuterTypeParametersApplied(originalBaseType!) ) { // When base constructor type is a class with no captured type arguments we know that the constructors all have the same type parameters as the // class and all return the instance type of the class. There is no need for further checks and we can apply the @@ -12125,9 +15461,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // The class derives from a "class-like" constructor function, check that we have at least one construct signature // with a matching number of type parameters and use the return type of the first instantiated signature. Elsewhere // we check that all instantiated signatures return the same type. - const constructors = getInstantiatedConstructorsForTypeArguments(baseConstructorType, baseTypeNode.typeArguments, baseTypeNode); + const constructors = getInstantiatedConstructorsForTypeArguments( + baseConstructorType, + baseTypeNode.typeArguments, + baseTypeNode, + ); if (!constructors.length) { - error(baseTypeNode.expression, Diagnostics.No_base_constructor_has_the_specified_number_of_type_arguments); + error( + baseTypeNode.expression, + Diagnostics.No_base_constructor_has_the_specified_number_of_type_arguments, + ); return type.resolvedBaseTypes = emptyArray; } baseType = getReturnTypeOfSignature(constructors[0]); @@ -12139,12 +15482,27 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const reducedBaseType = getReducedType(baseType); if (!isValidBaseType(reducedBaseType)) { const elaboration = elaborateNeverIntersection(/*errorInfo*/ undefined, baseType); - const diagnostic = chainDiagnosticMessages(elaboration, Diagnostics.Base_constructor_return_type_0_is_not_an_object_type_or_intersection_of_object_types_with_statically_known_members, typeToString(reducedBaseType)); - diagnostics.add(createDiagnosticForNodeFromMessageChain(getSourceFileOfNode(baseTypeNode.expression), baseTypeNode.expression, diagnostic)); + const diagnostic = chainDiagnosticMessages( + elaboration, + Diagnostics + .Base_constructor_return_type_0_is_not_an_object_type_or_intersection_of_object_types_with_statically_known_members, + typeToString(reducedBaseType), + ); + diagnostics.add( + createDiagnosticForNodeFromMessageChain( + getSourceFileOfNode(baseTypeNode.expression), + baseTypeNode.expression, + diagnostic, + ), + ); return type.resolvedBaseTypes = emptyArray; } if (type === reducedBaseType || hasBaseType(reducedBaseType, type)) { - error(type.symbol.valueDeclaration, Diagnostics.Type_0_recursively_references_itself_as_a_base_type, typeToString(type, /*enclosingDeclaration*/ undefined, TypeFormatFlags.WriteArrayAsGenericType)); + error( + type.symbol.valueDeclaration, + Diagnostics.Type_0_recursively_references_itself_as_a_base_type, + typeToString(type, /*enclosingDeclaration*/ undefined, TypeFormatFlags.WriteArrayAsGenericType), + ); return type.resolvedBaseTypes = emptyArray; } if (type.resolvedBaseTypes === resolvingEmptyArray) { @@ -12179,15 +15537,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } // TODO: Given that we allow type parmeters here now, is this `!isGenericMappedType(type)` check really needed? // There's no reason a `T` should be allowed while a `Readonly` should not. - return !!(type.flags & (TypeFlags.Object | TypeFlags.NonPrimitive | TypeFlags.Any) && !isGenericMappedType(type) || - type.flags & TypeFlags.Intersection && every((type as IntersectionType).types, isValidBaseType)); + return !!(type.flags & (TypeFlags.Object | TypeFlags.NonPrimitive | TypeFlags.Any) && !isGenericMappedType(type) + || type.flags & TypeFlags.Intersection && every((type as IntersectionType).types, isValidBaseType)); } function resolveBaseTypesOfInterface(type: InterfaceType): void { type.resolvedBaseTypes = type.resolvedBaseTypes || emptyArray; if (type.symbol.declarations) { for (const declaration of type.symbol.declarations) { - if (declaration.kind === SyntaxKind.InterfaceDeclaration && getInterfaceBaseTypeNodes(declaration as InterfaceDeclaration)) { + if ( + declaration.kind === SyntaxKind.InterfaceDeclaration + && getInterfaceBaseTypeNodes(declaration as InterfaceDeclaration) + ) { for (const node of getInterfaceBaseTypeNodes(declaration as InterfaceDeclaration)!) { const baseType = getReducedType(getTypeFromTypeNode(node)); if (!isErrorType(baseType)) { @@ -12205,7 +15566,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } else { - error(node, Diagnostics.An_interface_can_only_extend_an_object_type_or_intersection_of_object_types_with_statically_known_members); + error( + node, + Diagnostics + .An_interface_can_only_extend_an_object_type_or_intersection_of_object_types_with_statically_known_members, + ); } } } @@ -12234,8 +15599,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (baseTypeNodes) { for (const node of baseTypeNodes) { if (isEntityNameExpression(node.expression)) { - const baseSymbol = resolveEntityName(node.expression, SymbolFlags.Type, /*ignoreErrors*/ true); - if (!baseSymbol || !(baseSymbol.flags & SymbolFlags.Interface) || getDeclaredTypeOfClassOrInterface(baseSymbol).thisType) { + const baseSymbol = resolveEntityName( + node.expression, + SymbolFlags.Type, + /*ignoreErrors*/ true, + ); + if ( + !baseSymbol || !(baseSymbol.flags & SymbolFlags.Interface) + || getDeclaredTypeOfClassOrInterface(baseSymbol).thisType + ) { return false; } } @@ -12251,14 +15623,20 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const originalLinks = links; if (!links.declaredType) { const kind = symbol.flags & SymbolFlags.Class ? ObjectFlags.Class : ObjectFlags.Interface; - const merged = mergeJSSymbols(symbol, symbol.valueDeclaration && getAssignedClassSymbol(symbol.valueDeclaration)); + const merged = mergeJSSymbols( + symbol, + symbol.valueDeclaration && getAssignedClassSymbol(symbol.valueDeclaration), + ); if (merged) { // note:we overwrite links because we just cloned the symbol symbol = merged; links = merged.links; } - const type = originalLinks.declaredType = links.declaredType = createObjectType(kind, symbol) as InterfaceType; + const type = originalLinks.declaredType = links.declaredType = createObjectType( + kind, + symbol, + ) as InterfaceType; const outerTypeParameters = getOuterTypeParametersOfClassOrInterface(symbol); const localTypeParameters = getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(symbol); // A class or interface is generic if it has type parameters or a "this" type. We always give classes a "this" type @@ -12266,7 +15644,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // property types inferred from initializers and method return types inferred from return statements are very hard // to exhaustively analyze). We give interfaces a "this" type if we can't definitely determine that they are free of // "this" references. - if (outerTypeParameters || localTypeParameters || kind === ObjectFlags.Class || !isThislessInterface(symbol)) { + if ( + outerTypeParameters || localTypeParameters || kind === ObjectFlags.Class || !isThislessInterface(symbol) + ) { type.objectFlags |= ObjectFlags.Reference; type.typeParameters = concatenate(outerTypeParameters, localTypeParameters); type.outerTypeParameters = outerTypeParameters; @@ -12292,7 +15672,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return errorType; } - const declaration = Debug.checkDefined(symbol.declarations?.find(isTypeAlias), "Type alias symbol with no valid declaration found"); + const declaration = Debug.checkDefined( + symbol.declarations?.find(isTypeAlias), + "Type alias symbol with no valid declaration found", + ); const typeNode = isJSDocTypeAlias(declaration) ? declaration.typeExpression : declaration.type; // If typeNode is missing, we will error in checkJSDocTypedefTag. let type = typeNode ? getTypeFromTypeNode(typeNode) : errorType; @@ -12310,10 +15693,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { else { type = errorType; if (declaration.kind === SyntaxKind.JSDocEnumTag) { - error(declaration.typeExpression.type, Diagnostics.Type_alias_0_circularly_references_itself, symbolToString(symbol)); + error( + declaration.typeExpression.type, + Diagnostics.Type_alias_0_circularly_references_itself, + symbolToString(symbol), + ); } else { - error(isNamedDeclaration(declaration) ? declaration.name || declaration : declaration, Diagnostics.Type_alias_0_circularly_references_itself, symbolToString(symbol)); + error( + isNamedDeclaration(declaration) ? declaration.name || declaration : declaration, + Diagnostics.Type_alias_0_circularly_references_itself, + symbolToString(symbol), + ); } } links.declaredType = type; @@ -12322,7 +15713,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function getBaseTypeOfEnumLikeType(type: Type) { - return type.flags & TypeFlags.EnumLike && type.symbol.flags & SymbolFlags.EnumMember ? getDeclaredTypeOfSymbol(getParentOfSymbol(type.symbol)!) : type; + return type.flags & TypeFlags.EnumLike && type.symbol.flags & SymbolFlags.EnumMember + ? getDeclaredTypeOfSymbol(getParentOfSymbol(type.symbol)!) : type; } function getDeclaredTypeOfEnum(symbol: Symbol): Type { @@ -12337,9 +15729,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const memberSymbol = getSymbolOfDeclaration(member); const value = getEnumMemberValue(member); const memberType = getFreshTypeOfLiteralType( - value !== undefined ? - getEnumLiteralType(value, getSymbolId(symbol), memberSymbol) : - createComputedEnumType(memberSymbol), + value !== undefined + ? getEnumLiteralType(value, getSymbolId(symbol), memberSymbol) + : createComputedEnumType(memberSymbol), ); getSymbolLinks(memberSymbol).declaredType = memberType; memberTypeList.push(getRegularTypeOfLiteralType(memberType)); @@ -12348,9 +15740,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } } - const enumType = memberTypeList.length ? - getUnionType(memberTypeList, UnionReduction.Literal, symbol, /*aliasTypeArguments*/ undefined) : - createComputedEnumType(symbol); + const enumType = memberTypeList.length + ? getUnionType(memberTypeList, UnionReduction.Literal, symbol, /*aliasTypeArguments*/ undefined) + : createComputedEnumType(symbol); if (enumType.flags & TypeFlags.Union) { enumType.flags |= TypeFlags.EnumLiteral; enumType.symbol = symbol; @@ -12440,7 +15832,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { case SyntaxKind.ArrayType: return isThislessType((node as ArrayTypeNode).elementType); case SyntaxKind.TypeReference: - return !(node as TypeReferenceNode).typeArguments || (node as TypeReferenceNode).typeArguments!.every(isThislessType); + return !(node as TypeReferenceNode).typeArguments + || (node as TypeReferenceNode).typeArguments!.every(isThislessType); } return false; } @@ -12468,9 +15861,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function isThislessFunctionLikeDeclaration(node: FunctionLikeDeclaration): boolean { const returnType = getEffectiveReturnTypeNode(node); const typeParameters = getEffectiveTypeParameterDeclarations(node); - return (node.kind === SyntaxKind.Constructor || (!!returnType && isThislessType(returnType))) && - node.parameters.every(isThislessVariableLikeDeclaration) && - typeParameters.every(isThislessTypeParameter); + return (node.kind === SyntaxKind.Constructor || (!!returnType && isThislessType(returnType))) + && node.parameters.every(isThislessVariableLikeDeclaration) + && typeParameters.every(isThislessTypeParameter); } /** @@ -12493,7 +15886,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { case SyntaxKind.Constructor: case SyntaxKind.GetAccessor: case SyntaxKind.SetAccessor: - return isThislessFunctionLikeDeclaration(declaration as FunctionLikeDeclaration | AccessorDeclaration); + return isThislessFunctionLikeDeclaration( + declaration as FunctionLikeDeclaration | AccessorDeclaration, + ); } } } @@ -12502,10 +15897,17 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // The mappingThisOnly flag indicates that the only type parameter being mapped is "this". When the flag is true, // we check symbols to see if we can quickly conclude they are free of "this" references, thus needing no instantiation. - function createInstantiatedSymbolTable(symbols: Symbol[], mapper: TypeMapper, mappingThisOnly: boolean): SymbolTable { + function createInstantiatedSymbolTable( + symbols: Symbol[], + mapper: TypeMapper, + mappingThisOnly: boolean, + ): SymbolTable { const result = createSymbolTable(); for (const symbol of symbols) { - result.set(symbol.escapedName, mappingThisOnly && isThisless(symbol) ? symbol : instantiateSymbol(symbol, mapper)); + result.set( + symbol.escapedName, + mappingThisOnly && isThisless(symbol) ? symbol : instantiateSymbol(symbol, mapper), + ); } return result; } @@ -12531,7 +15933,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function isStaticPrivateIdentifierProperty(s: Symbol): boolean { - return !!s.valueDeclaration && isPrivateIdentifierClassElementDeclaration(s.valueDeclaration) && isStatic(s.valueDeclaration); + return !!s.valueDeclaration && isPrivateIdentifierClassElementDeclaration(s.valueDeclaration) + && isStatic(s.valueDeclaration); } function resolveDeclaredMembers(type: InterfaceType): InterfaceTypeWithDeclaredMembers { @@ -12544,8 +15947,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { (type as InterfaceTypeWithDeclaredMembers).declaredConstructSignatures = emptyArray; (type as InterfaceTypeWithDeclaredMembers).declaredIndexInfos = emptyArray; - (type as InterfaceTypeWithDeclaredMembers).declaredCallSignatures = getSignaturesOfSymbol(members.get(InternalSymbolName.Call)); - (type as InterfaceTypeWithDeclaredMembers).declaredConstructSignatures = getSignaturesOfSymbol(members.get(InternalSymbolName.New)); + (type as InterfaceTypeWithDeclaredMembers).declaredCallSignatures = getSignaturesOfSymbol( + members.get(InternalSymbolName.Call), + ); + (type as InterfaceTypeWithDeclaredMembers).declaredConstructSignatures = getSignaturesOfSymbol( + members.get(InternalSymbolName.New), + ); (type as InterfaceTypeWithDeclaredMembers).declaredIndexInfos = getIndexInfosOfSymbol(symbol); } return type as InterfaceTypeWithDeclaredMembers; @@ -12565,19 +15972,23 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } const expr = isComputedPropertyName(node) ? node.expression : node.argumentExpression; return isEntityNameExpression(expr) - && isTypeUsableAsPropertyName(isComputedPropertyName(node) ? checkComputedPropertyName(node) : checkExpressionCached(expr)); + && isTypeUsableAsPropertyName( + isComputedPropertyName(node) ? checkComputedPropertyName(node) : checkExpressionCached(expr), + ); } function isLateBoundName(name: __String): boolean { - return (name as string).charCodeAt(0) === CharacterCodes._ && - (name as string).charCodeAt(1) === CharacterCodes._ && - (name as string).charCodeAt(2) === CharacterCodes.at; + return (name as string).charCodeAt(0) === CharacterCodes._ + && (name as string).charCodeAt(1) === CharacterCodes._ + && (name as string).charCodeAt(2) === CharacterCodes.at; } /** * Indicates whether a declaration has a late-bindable dynamic name. */ - function hasLateBindableName(node: Declaration): node is LateBoundDeclaration | LateBoundBinaryExpressionDeclaration { + function hasLateBindableName( + node: Declaration, + ): node is LateBoundDeclaration | LateBoundBinaryExpressionDeclaration { const name = getNameOfDeclaration(node); return !!name && isLateBindableName(name); } @@ -12601,7 +16012,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { * late-bound members that `addDeclarationToSymbol` in binder.ts performs for early-bound * members. */ - function addDeclarationToLateBoundSymbol(symbol: Symbol, member: LateBoundDeclaration | BinaryExpression, symbolFlags: SymbolFlags) { + function addDeclarationToLateBoundSymbol( + symbol: Symbol, + member: LateBoundDeclaration | BinaryExpression, + symbolFlags: SymbolFlags, + ) { Debug.assert(!!(getCheckFlags(symbol) & CheckFlags.Late), "Expected a late-bound symbol."); symbol.flags |= symbolFlags; getSymbolLinks(member.symbol).lateSymbol = symbol; @@ -12646,7 +16061,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { * @param lateSymbols The late-bound symbols of the parent. * @param decl The member to bind. */ - function lateBindMember(parent: Symbol, earlySymbols: SymbolTable | undefined, lateSymbols: Map<__String, TransientSymbol>, decl: LateBoundDeclaration | LateBoundBinaryExpressionDeclaration) { + function lateBindMember( + parent: Symbol, + earlySymbols: SymbolTable | undefined, + lateSymbols: Map<__String, TransientSymbol>, + decl: LateBoundDeclaration | LateBoundBinaryExpressionDeclaration, + ) { Debug.assert(!!decl.symbol, "The member is expected to have a symbol."); const links = getNodeLinks(decl); if (!links.resolvedSymbol) { @@ -12654,14 +16074,20 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // fall back to the early-bound name of this member. links.resolvedSymbol = decl.symbol; const declName = isBinaryExpression(decl) ? decl.left : decl.name; - const type = isElementAccessExpression(declName) ? checkExpressionCached(declName.argumentExpression) : checkComputedPropertyName(declName); + const type = isElementAccessExpression(declName) ? checkExpressionCached(declName.argumentExpression) + : checkComputedPropertyName(declName); if (isTypeUsableAsPropertyName(type)) { const memberName = getPropertyNameFromType(type); const symbolFlags = decl.symbol.flags; // Get or add a late-bound symbol for the member. This allows us to merge late-bound accessor declarations. let lateSymbol = lateSymbols.get(memberName); - if (!lateSymbol) lateSymbols.set(memberName, lateSymbol = createSymbol(SymbolFlags.None, memberName, CheckFlags.Late)); + if (!lateSymbol) { + lateSymbols.set( + memberName, + lateSymbol = createSymbol(SymbolFlags.None, memberName, CheckFlags.Late), + ); + } // Report an error if a late-bound member has the same name as an early-bound member, // or if we have another early-bound symbol declaration with the same name and @@ -12670,9 +16096,19 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (lateSymbol.flags & getExcludedSymbolFlags(symbolFlags) || earlySymbol) { // If we have an existing early-bound member, combine its declarations so that we can // report an error at each declaration. - const declarations = earlySymbol ? concatenate(earlySymbol.declarations, lateSymbol.declarations) : lateSymbol.declarations; - const name = !(type.flags & TypeFlags.UniqueESSymbol) && unescapeLeadingUnderscores(memberName) || declarationNameToString(declName); - forEach(declarations, declaration => error(getNameOfDeclaration(declaration) || declaration, Diagnostics.Property_0_was_also_declared_here, name)); + const declarations = earlySymbol ? concatenate(earlySymbol.declarations, lateSymbol.declarations) + : lateSymbol.declarations; + const name = !(type.flags & TypeFlags.UniqueESSymbol) && unescapeLeadingUnderscores(memberName) + || declarationNameToString(declName); + forEach( + declarations, + declaration => + error( + getNameOfDeclaration(declaration) || declaration, + Diagnostics.Property_0_was_also_declared_here, + name, + ), + ); error(declName || decl, Diagnostics.Duplicate_property_0, name); lateSymbol = createSymbol(SymbolFlags.None, memberName, CheckFlags.Late); } @@ -12690,13 +16126,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return links.resolvedSymbol; } - function getResolvedMembersOrExportsOfSymbol(symbol: Symbol, resolutionKind: MembersOrExportsResolutionKind): Map<__String, Symbol> { + function getResolvedMembersOrExportsOfSymbol( + symbol: Symbol, + resolutionKind: MembersOrExportsResolutionKind, + ): Map<__String, Symbol> { const links = getSymbolLinks(symbol); if (!links[resolutionKind]) { const isStatic = resolutionKind === MembersOrExportsResolutionKind.resolvedExports; - const earlySymbols = !isStatic ? symbol.members : - symbol.flags & SymbolFlags.Module ? getExportsOfModuleWorker(symbol).exports : - symbol.exports; + const earlySymbols = !isStatic ? symbol.members + : symbol.flags & SymbolFlags.Module ? getExportsOfModuleWorker(symbol).exports + : symbol.exports; // In the event we recursively resolve the members/exports of the symbol, we // set the initial value of resolvedMembers/resolvedExports to the early-bound @@ -12717,9 +16156,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } } - const assignments = (symbol.valueDeclaration?.kind === SyntaxKind.ArrowFunction || symbol.valueDeclaration?.kind === SyntaxKind.FunctionExpression) && - getSymbolOfNode(symbol.valueDeclaration.parent)?.assignmentDeclarationMembers || - symbol.assignmentDeclarationMembers; + const assignments = (symbol.valueDeclaration?.kind === SyntaxKind.ArrowFunction + || symbol.valueDeclaration?.kind === SyntaxKind.FunctionExpression) + && getSymbolOfNode(symbol.valueDeclaration.parent)?.assignmentDeclarationMembers + || symbol.assignmentDeclarationMembers; if (assignments) { const decls = arrayFrom(assignments.values()); @@ -12782,16 +16222,25 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (getObjectFlags(type) & ObjectFlags.Reference) { const target = (type as TypeReference).target; const typeArguments = getTypeArguments(type as TypeReference); - return length(target.typeParameters) === length(typeArguments) ? createTypeReference(target, concatenate(typeArguments, [thisArgument || target.thisType!])) : type; + return length(target.typeParameters) === length(typeArguments) + ? createTypeReference(target, concatenate(typeArguments, [thisArgument || target.thisType!])) : type; } else if (type.flags & TypeFlags.Intersection) { - const types = sameMap((type as IntersectionType).types, t => getTypeWithThisArgument(t, thisArgument, needApparentType)); + const types = sameMap( + (type as IntersectionType).types, + t => getTypeWithThisArgument(t, thisArgument, needApparentType), + ); return types !== (type as IntersectionType).types ? getIntersectionType(types) : type; } return needApparentType ? getApparentType(type) : type; } - function resolveObjectTypeMembers(type: ObjectType, source: InterfaceTypeWithDeclaredMembers, typeParameters: readonly TypeParameter[], typeArguments: readonly Type[]) { + function resolveObjectTypeMembers( + type: ObjectType, + source: InterfaceTypeWithDeclaredMembers, + typeParameters: readonly TypeParameter[], + typeArguments: readonly Type[], + ) { let mapper: TypeMapper | undefined; let members: SymbolTable; let callSignatures: readonly Signature[]; @@ -12805,7 +16254,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } else { mapper = createTypeMapper(typeParameters, typeArguments); - members = createInstantiatedSymbolTable(source.declaredProperties, mapper, /*mappingThisOnly*/ typeParameters.length === 1); + members = createInstantiatedSymbolTable( + source.declaredProperties, + mapper, + /*mappingThisOnly*/ typeParameters.length === 1, + ); callSignatures = instantiateSignatures(source.declaredCallSignatures, mapper); constructSignatures = instantiateSignatures(source.declaredConstructSignatures, mapper); indexInfos = instantiateIndexInfos(source.declaredIndexInfos, mapper); @@ -12818,12 +16271,23 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { setStructuredTypeMembers(type, members, callSignatures, constructSignatures, indexInfos); const thisArgument = lastOrUndefined(typeArguments); for (const baseType of baseTypes) { - const instantiatedBaseType = thisArgument ? getTypeWithThisArgument(instantiateType(baseType, mapper), thisArgument) : baseType; + const instantiatedBaseType = thisArgument + ? getTypeWithThisArgument(instantiateType(baseType, mapper), thisArgument) : baseType; addInheritedMembers(members, getPropertiesOfType(instantiatedBaseType)); - callSignatures = concatenate(callSignatures, getSignaturesOfType(instantiatedBaseType, SignatureKind.Call)); - constructSignatures = concatenate(constructSignatures, getSignaturesOfType(instantiatedBaseType, SignatureKind.Construct)); - const inheritedIndexInfos = instantiatedBaseType !== anyType ? getIndexInfosOfType(instantiatedBaseType) : [createIndexInfo(stringType, anyType, /*isReadonly*/ false)]; - indexInfos = concatenate(indexInfos, filter(inheritedIndexInfos, info => !findIndexInfo(indexInfos, info.keyType))); + callSignatures = concatenate( + callSignatures, + getSignaturesOfType(instantiatedBaseType, SignatureKind.Call), + ); + constructSignatures = concatenate( + constructSignatures, + getSignaturesOfType(instantiatedBaseType, SignatureKind.Construct), + ); + const inheritedIndexInfos = instantiatedBaseType !== anyType ? getIndexInfosOfType(instantiatedBaseType) + : [createIndexInfo(stringType, anyType, /*isReadonly*/ false)]; + indexInfos = concatenate( + indexInfos, + filter(inheritedIndexInfos, info => !findIndexInfo(indexInfos, info.keyType)), + ); } } setStructuredTypeMembers(type, members, callSignatures, constructSignatures, indexInfos); @@ -12837,7 +16301,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const source = resolveDeclaredMembers(type.target); const typeParameters = concatenate(source.typeParameters!, [source.thisType!]); const typeArguments = getTypeArguments(type); - const paddedTypeArguments = typeArguments.length === typeParameters.length ? typeArguments : concatenate(typeArguments, [type]); + const paddedTypeArguments = typeArguments.length === typeParameters.length ? typeArguments + : concatenate(typeArguments, [type]); resolveObjectTypeMembers(type, source, typeParameters, paddedTypeArguments); } @@ -12868,7 +16333,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function cloneSignature(sig: Signature): Signature { - const result = createSignature(sig.declaration, sig.typeParameters, sig.thisParameter, sig.parameters, /*resolvedReturnType*/ undefined, /*resolvedTypePredicate*/ undefined, sig.minArgumentCount, sig.flags & SignatureFlags.PropagatingFlags); + const result = createSignature( + sig.declaration, + sig.typeParameters, + sig.thisParameter, + sig.parameters, + /*resolvedReturnType*/ undefined, + /*resolvedTypePredicate*/ undefined, + sig.minArgumentCount, + sig.flags & SignatureFlags.PropagatingFlags, + ); result.target = sig.target; result.mapper = sig.mapper; result.compositeSignatures = sig.compositeSignatures; @@ -12898,7 +16372,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function createOptionalCallSignature(signature: Signature, callChainFlags: SignatureFlags) { - Debug.assert(callChainFlags === SignatureFlags.IsInnerCallChain || callChainFlags === SignatureFlags.IsOuterCallChain, "An optional call signature can either be for an inner call chain or an outer call chain, but not both."); + Debug.assert( + callChainFlags === SignatureFlags.IsInnerCallChain || callChainFlags === SignatureFlags.IsOuterCallChain, + "An optional call signature can either be for an inner call chain or an outer call chain, but not both.", + ); const result = cloneSignature(signature); result.flags |= callChainFlags; return result; @@ -12912,22 +16389,32 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (isTupleType(restType)) { return [expandSignatureParametersWithTupleMembers(restType, restIndex, restName)]; } - else if (!skipUnionExpanding && restType.flags & TypeFlags.Union && every((restType as UnionType).types, isTupleType)) { - return map((restType as UnionType).types, t => expandSignatureParametersWithTupleMembers(t as TupleTypeReference, restIndex, restName)); + else if ( + !skipUnionExpanding && restType.flags & TypeFlags.Union + && every((restType as UnionType).types, isTupleType) + ) { + return map( + (restType as UnionType).types, + t => expandSignatureParametersWithTupleMembers(t as TupleTypeReference, restIndex, restName), + ); } } return [sig.parameters]; - function expandSignatureParametersWithTupleMembers(restType: TupleTypeReference, restIndex: number, restName: __String) { + function expandSignatureParametersWithTupleMembers( + restType: TupleTypeReference, + restIndex: number, + restName: __String, + ) { const elementTypes = getTypeArguments(restType); const associatedNames = getUniqAssociatedNamesFromTupleType(restType, restName); const restParams = map(elementTypes, (t, i) => { // Lookup the label from the individual tuple passed in before falling back to the signature `rest` parameter name - const name = associatedNames && associatedNames[i] ? associatedNames[i] : - getParameterNameAtPosition(sig, restIndex + i, restType); + const name = associatedNames && associatedNames[i] ? associatedNames[i] + : getParameterNameAtPosition(sig, restIndex + i, restType); const flags = restType.target.elementFlags[i]; - const checkFlags = flags & ElementFlags.Variable ? CheckFlags.RestParameter : - flags & ElementFlags.Optional ? CheckFlags.OptionalParameter : 0; + const checkFlags = flags & ElementFlags.Variable ? CheckFlags.RestParameter + : flags & ElementFlags.Optional ? CheckFlags.OptionalParameter : 0; const symbol = createSymbol(SymbolFlags.FunctionScopedVariable, name, checkFlags); symbol.links.type = flags & ElementFlags.Rest ? createArrayType(t) : t; return symbol; @@ -12958,7 +16445,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const declaration = getClassLikeDeclarationOfSymbol(classType.symbol); const isAbstract = !!declaration && hasSyntacticModifier(declaration, ModifierFlags.Abstract); if (baseSignatures.length === 0) { - return [createSignature(/*declaration*/ undefined, classType.localTypeParameters, /*thisParameter*/ undefined, emptyArray, classType, /*resolvedTypePredicate*/ undefined, 0, isAbstract ? SignatureFlags.Abstract : SignatureFlags.None)]; + return [ + createSignature( + /*declaration*/ undefined, + classType.localTypeParameters, + /*thisParameter*/ undefined, + emptyArray, + classType, + /*resolvedTypePredicate*/ undefined, + 0, + isAbstract ? SignatureFlags.Abstract : SignatureFlags.None, + ), + ]; } const baseTypeNode = getBaseTypeNodeOfClass(classType)!; const isJavaScript = isInJSFile(baseTypeNode); @@ -12969,7 +16467,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const minTypeArgumentCount = getMinTypeArgumentCount(baseSig.typeParameters); const typeParamCount = length(baseSig.typeParameters); if (isJavaScript || typeArgCount >= minTypeArgumentCount && typeArgCount <= typeParamCount) { - const sig = typeParamCount ? createSignatureInstantiation(baseSig, fillMissingTypeArguments(typeArguments, baseSig.typeParameters, minTypeArgumentCount, isJavaScript)) : cloneSignature(baseSig); + const sig = typeParamCount + ? createSignatureInstantiation( + baseSig, + fillMissingTypeArguments( + typeArguments, + baseSig.typeParameters, + minTypeArgumentCount, + isJavaScript, + ), + ) : cloneSignature(baseSig); sig.typeParameters = classType.localTypeParameters; sig.resolvedReturnType = classType; sig.flags = isAbstract ? sig.flags | SignatureFlags.Abstract : sig.flags & ~SignatureFlags.Abstract; @@ -12979,15 +16486,34 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return result; } - function findMatchingSignature(signatureList: readonly Signature[], signature: Signature, partialMatch: boolean, ignoreThisTypes: boolean, ignoreReturnTypes: boolean): Signature | undefined { + function findMatchingSignature( + signatureList: readonly Signature[], + signature: Signature, + partialMatch: boolean, + ignoreThisTypes: boolean, + ignoreReturnTypes: boolean, + ): Signature | undefined { for (const s of signatureList) { - if (compareSignaturesIdentical(s, signature, partialMatch, ignoreThisTypes, ignoreReturnTypes, partialMatch ? compareTypesSubtypeOf : compareTypesIdentical)) { + if ( + compareSignaturesIdentical( + s, + signature, + partialMatch, + ignoreThisTypes, + ignoreReturnTypes, + partialMatch ? compareTypesSubtypeOf : compareTypesIdentical, + ) + ) { return s; } } } - function findMatchingSignatures(signatureLists: readonly (readonly Signature[])[], signature: Signature, listIndex: number): Signature[] | undefined { + function findMatchingSignatures( + signatureLists: readonly (readonly Signature[])[], + signature: Signature, + listIndex: number, + ): Signature[] | undefined { if (signature.typeParameters) { // We require an exact match for generic signatures, so we only return signatures from the first // signature list and only if they have exact matches in the other signature lists. @@ -12995,7 +16521,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return undefined; } for (let i = 1; i < signatureLists.length; i++) { - if (!findMatchingSignature(signatureLists[i], signature, /*partialMatch*/ false, /*ignoreThisTypes*/ false, /*ignoreReturnTypes*/ false)) { + if ( + !findMatchingSignature( + signatureLists[i], + signature, + /*partialMatch*/ false, + /*ignoreThisTypes*/ false, + /*ignoreReturnTypes*/ false, + ) + ) { return undefined; } } @@ -13005,7 +16539,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { for (let i = 0; i < signatureLists.length; i++) { // Allow matching non-generic signatures to have excess parameters and different return types. // Prefer matching this types if possible. - const match = i === listIndex ? signature : findMatchingSignature(signatureLists[i], signature, /*partialMatch*/ true, /*ignoreThisTypes*/ false, /*ignoreReturnTypes*/ true); + const match = i === listIndex ? signature + : findMatchingSignature( + signatureLists[i], + signature, + /*partialMatch*/ true, + /*ignoreThisTypes*/ false, + /*ignoreReturnTypes*/ true, + ); if (!match) { return undefined; } @@ -13028,16 +16569,33 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } for (const signature of signatureLists[i]) { // Only process signatures with parameter lists that aren't already in the result list - if (!result || !findMatchingSignature(result, signature, /*partialMatch*/ false, /*ignoreThisTypes*/ false, /*ignoreReturnTypes*/ true)) { + if ( + !result + || !findMatchingSignature( + result, + signature, + /*partialMatch*/ false, + /*ignoreThisTypes*/ false, + /*ignoreReturnTypes*/ true, + ) + ) { const unionSignatures = findMatchingSignatures(signatureLists, signature, i); if (unionSignatures) { let s = signature; // Union the result types when more than one signature matches if (unionSignatures.length > 1) { let thisParameter = signature.thisParameter; - const firstThisParameterOfUnionSignatures = forEach(unionSignatures, sig => sig.thisParameter); + const firstThisParameterOfUnionSignatures = forEach( + unionSignatures, + sig => sig.thisParameter, + ); if (firstThisParameterOfUnionSignatures) { - const thisType = getIntersectionType(mapDefined(unionSignatures, sig => sig.thisParameter && getTypeOfSymbol(sig.thisParameter))); + const thisType = getIntersectionType( + mapDefined( + unionSignatures, + sig => sig.thisParameter && getTypeOfSymbol(sig.thisParameter), + ), + ); thisParameter = createSymbolWithType(firstThisParameterOfUnionSignatures, thisType); } s = createUnionSignature(signature, unionSignatures); @@ -13058,8 +16616,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { for (const signatures of signatureLists) { if (signatures !== masterList) { const signature = signatures[0]; - Debug.assert(!!signature, "getUnionSignatures bails early on empty signature lists and should not have empty lists on second pass"); - results = !!signature.typeParameters && some(results, s => !!s.typeParameters && !compareTypeParametersIdentical(signature.typeParameters, s.typeParameters)) ? undefined : map(results, sig => combineSignaturesOfUnionMembers(sig, signature)); + Debug.assert( + !!signature, + "getUnionSignatures bails early on empty signature lists and should not have empty lists on second pass", + ); + results = !!signature.typeParameters && some(results, s => + !!s.typeParameters + && !compareTypeParametersIdentical(signature.typeParameters, s.typeParameters)) ? undefined + : map(results, sig => combineSignaturesOfUnionMembers(sig, signature)); if (!results) { break; } @@ -13070,7 +16634,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return result || emptyArray; } - function compareTypeParametersIdentical(sourceParams: readonly TypeParameter[] | undefined, targetParams: readonly TypeParameter[] | undefined): boolean { + function compareTypeParametersIdentical( + sourceParams: readonly TypeParameter[] | undefined, + targetParams: readonly TypeParameter[] | undefined, + ): boolean { if (length(sourceParams) !== length(targetParams)) { return false; } @@ -13084,7 +16651,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const target = targetParams[i]; if (source === target) continue; // We instantiate the target type parameter constraints into the source types so we can recognize `` as the same as `` - if (!isTypeIdenticalTo(getConstraintFromTypeParameter(source) || unknownType, instantiateType(getConstraintFromTypeParameter(target) || unknownType, mapper))) return false; + if ( + !isTypeIdenticalTo( + getConstraintFromTypeParameter(source) || unknownType, + instantiateType(getConstraintFromTypeParameter(target) || unknownType, mapper), + ) + ) return false; // We don't compare defaults - we just use the type parameter defaults from the first signature that seems to match. // It might make sense to combine these defaults in the future, but doing so intelligently requires knowing // if the parameter is used covariantly or contravariantly (so we intersect if it's used like a parameter or union if used like a return type) @@ -13094,7 +16666,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return true; } - function combineUnionThisParam(left: Symbol | undefined, right: Symbol | undefined, mapper: TypeMapper | undefined): Symbol | undefined { + function combineUnionThisParam( + left: Symbol | undefined, + right: Symbol | undefined, + mapper: TypeMapper | undefined, + ): Symbol | undefined { if (!left || !right) { return left || right; } @@ -13129,10 +16705,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const leftName = i >= leftCount ? undefined : getParameterNameAtPosition(left, i); const rightName = i >= rightCount ? undefined : getParameterNameAtPosition(right, i); - const paramName = leftName === rightName ? leftName : - !leftName ? rightName : - !rightName ? leftName : - undefined; + const paramName = leftName === rightName ? leftName + : !leftName ? rightName + : !rightName ? leftName + : undefined; const paramSymbol = createSymbol( SymbolFlags.FunctionScopedVariable | (isOptional && !isRestParam ? SymbolFlags.Optional : 0), paramName || `arg${i}` as __String, @@ -13173,9 +16749,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { (left.flags | right.flags) & SignatureFlags.PropagatingFlags, ); result.compositeKind = TypeFlags.Union; - result.compositeSignatures = concatenate(left.compositeKind !== TypeFlags.Intersection && left.compositeSignatures || [left], [right]); + result.compositeSignatures = concatenate( + left.compositeKind !== TypeFlags.Intersection && left.compositeSignatures || [left], + [right], + ); if (paramMapper) { - result.mapper = left.compositeKind !== TypeFlags.Intersection && left.mapper && left.compositeSignatures ? combineTypeMappers(left.mapper, paramMapper) : paramMapper; + result.mapper = left.compositeKind !== TypeFlags.Intersection && left.mapper && left.compositeSignatures + ? combineTypeMappers(left.mapper, paramMapper) : paramMapper; } return result; } @@ -13187,7 +16767,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { for (const info of sourceInfos) { const indexType = info.keyType; if (every(types, t => !!getIndexInfoOfType(t, indexType))) { - result.push(createIndexInfo(indexType, getUnionType(map(types, t => getIndexTypeOfType(t, indexType)!)), some(types, t => getIndexInfoOfType(t, indexType)!.isReadonly))); + result.push( + createIndexInfo( + indexType, + getUnionType(map(types, t => getIndexTypeOfType(t, indexType)!)), + some(types, t => getIndexInfoOfType(t, indexType)!.isReadonly), + ), + ); } } return result; @@ -13198,8 +16784,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function resolveUnionTypeMembers(type: UnionType) { // The members and properties collections are empty for union types. To get all properties of a union // type use getPropertiesOfType (only the language service uses this). - const callSignatures = getUnionSignatures(map(type.types, t => t === globalFunctionType ? [unknownSignature] : getSignaturesOfType(t, SignatureKind.Call))); - const constructSignatures = getUnionSignatures(map(type.types, t => getSignaturesOfType(t, SignatureKind.Construct))); + const callSignatures = getUnionSignatures( + map( + type.types, + t => t === globalFunctionType ? [unknownSignature] : getSignaturesOfType(t, SignatureKind.Call), + ), + ); + const constructSignatures = getUnionSignatures( + map(type.types, t => getSignaturesOfType(t, SignatureKind.Construct)), + ); const indexInfos = getUnionIndexInfos(type.types); setStructuredTypeMembers(type, emptySymbols, callSignatures, constructSignatures, indexInfos); } @@ -13261,14 +16854,34 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { constructSignatures = appendSignatures(constructSignatures, signatures); } callSignatures = appendSignatures(callSignatures, getSignaturesOfType(t, SignatureKind.Call)); - indexInfos = reduceLeft(getIndexInfosOfType(t), (infos, newInfo) => appendIndexInfo(infos, newInfo, /*union*/ false), indexInfos); + indexInfos = reduceLeft( + getIndexInfosOfType(t), + (infos, newInfo) => appendIndexInfo(infos, newInfo, /*union*/ false), + indexInfos, + ); } - setStructuredTypeMembers(type, emptySymbols, callSignatures || emptyArray, constructSignatures || emptyArray, indexInfos || emptyArray); + setStructuredTypeMembers( + type, + emptySymbols, + callSignatures || emptyArray, + constructSignatures || emptyArray, + indexInfos || emptyArray, + ); } function appendSignatures(signatures: Signature[] | undefined, newSignatures: readonly Signature[]) { for (const sig of newSignatures) { - if (!signatures || every(signatures, s => !compareSignaturesIdentical(s, sig, /*partialMatch*/ false, /*ignoreThisTypes*/ false, /*ignoreReturnTypes*/ false, compareTypesIdentical))) { + if ( + !signatures || every(signatures, s => + !compareSignaturesIdentical( + s, + sig, + /*partialMatch*/ false, + /*ignoreThisTypes*/ false, + /*ignoreReturnTypes*/ false, + compareTypesIdentical, + )) + ) { signatures = append(signatures, sig); } } @@ -13280,7 +16893,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { for (let i = 0; i < indexInfos.length; i++) { const info = indexInfos[i]; if (info.keyType === newInfo.keyType) { - indexInfos[i] = createIndexInfo(info.keyType, union ? getUnionType([info.type, newInfo.type]) : getIntersectionType([info.type, newInfo.type]), union ? info.isReadonly || newInfo.isReadonly : info.isReadonly && newInfo.isReadonly); + indexInfos[i] = createIndexInfo( + info.keyType, + union ? getUnionType([info.type, newInfo.type]) + : getIntersectionType([info.type, newInfo.type]), + union ? info.isReadonly || newInfo.isReadonly : info.isReadonly && newInfo.isReadonly, + ); return indexInfos; } } @@ -13294,9 +16912,19 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function resolveAnonymousTypeMembers(type: AnonymousType) { if (type.target) { setStructuredTypeMembers(type, emptySymbols, emptyArray, emptyArray, emptyArray); - const members = createInstantiatedSymbolTable(getPropertiesOfObjectType(type.target), type.mapper!, /*mappingThisOnly*/ false); - const callSignatures = instantiateSignatures(getSignaturesOfType(type.target, SignatureKind.Call), type.mapper!); - const constructSignatures = instantiateSignatures(getSignaturesOfType(type.target, SignatureKind.Construct), type.mapper!); + const members = createInstantiatedSymbolTable( + getPropertiesOfObjectType(type.target), + type.mapper!, + /*mappingThisOnly*/ false, + ); + const callSignatures = instantiateSignatures( + getSignaturesOfType(type.target, SignatureKind.Call), + type.mapper!, + ); + const constructSignatures = instantiateSignatures( + getSignaturesOfType(type.target, SignatureKind.Construct), + type.mapper!, + ); const indexInfos = instantiateIndexInfos(getIndexInfosOfType(type.target), type.mapper!); setStructuredTypeMembers(type, members, callSignatures, constructSignatures, indexInfos); return; @@ -13317,7 +16945,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (symbol === globalThisSymbol) { const varsOnly = new Map<__String, Symbol>(); members.forEach(p => { - if (!(p.flags & SymbolFlags.BlockScoped) && !(p.flags & SymbolFlags.ValueModule && p.declarations?.length && every(p.declarations, isAmbientModule))) { + if ( + !(p.flags & SymbolFlags.BlockScoped) + && !(p.flags & SymbolFlags.ValueModule && p.declarations?.length + && every(p.declarations, isAmbientModule)) + ) { varsOnly.set(p.escapedName, p); } }); @@ -13346,8 +16978,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { indexInfos = append(indexInfos, baseConstructorIndexInfo); } if ( - symbol.flags & SymbolFlags.Enum && (getDeclaredTypeOfSymbol(symbol).flags & TypeFlags.Enum || - some(type.properties, prop => !!(getTypeOfSymbol(prop).flags & TypeFlags.NumberLike))) + symbol.flags & SymbolFlags.Enum && (getDeclaredTypeOfSymbol(symbol).flags & TypeFlags.Enum + || some(type.properties, prop => !!(getTypeOfSymbol(prop).flags & TypeFlags.NumberLike))) ) { indexInfos = append(indexInfos, enumNumberIndexInfo); } @@ -13363,16 +16995,26 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // And likewise for construct signatures for classes if (symbol.flags & SymbolFlags.Class) { const classType = getDeclaredTypeOfClassOrInterface(symbol); - let constructSignatures = symbol.members ? getSignaturesOfSymbol(symbol.members.get(InternalSymbolName.Constructor)) : emptyArray; + let constructSignatures = symbol.members + ? getSignaturesOfSymbol(symbol.members.get(InternalSymbolName.Constructor)) : emptyArray; if (symbol.flags & SymbolFlags.Function) { constructSignatures = addRange( constructSignatures.slice(), mapDefined( type.callSignatures, sig => - isJSConstructor(sig.declaration) ? - createSignature(sig.declaration, sig.typeParameters, sig.thisParameter, sig.parameters, classType, /*resolvedTypePredicate*/ undefined, sig.minArgumentCount, sig.flags & SignatureFlags.PropagatingFlags) : - undefined, + isJSConstructor(sig.declaration) + ? createSignature( + sig.declaration, + sig.typeParameters, + sig.thisParameter, + sig.parameters, + classType, + /*resolvedTypePredicate*/ undefined, + sig.minArgumentCount, + sig.flags & SignatureFlags.PropagatingFlags, + ) + : undefined, ), ); } @@ -13388,7 +17030,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // map type.indexType to 0 // map type.objectType to `[TReplacement]` // thus making the indexed access `[TReplacement][0]` or `TReplacement` - return instantiateType(instantiable, createTypeMapper([type.indexType, type.objectType], [getNumberLiteralType(0), createTupleType([replacement])])); + return instantiateType( + instantiable, + createTypeMapper([type.indexType, type.objectType], [ + getNumberLiteralType(0), + createTupleType([replacement]), + ]), + ); } function resolveReverseMappedTypeMembers(type: ReverseMappedType) { @@ -13396,11 +17044,21 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const modifiers = getMappedTypeModifiers(type.mappedType); const readonlyMask = modifiers & MappedTypeModifiers.IncludeReadonly ? false : true; const optionalMask = modifiers & MappedTypeModifiers.IncludeOptional ? 0 : SymbolFlags.Optional; - const indexInfos = indexInfo ? [createIndexInfo(stringType, inferReverseMappedType(indexInfo.type, type.mappedType, type.constraintType), readonlyMask && indexInfo.isReadonly)] : emptyArray; + const indexInfos = indexInfo + ? [createIndexInfo( + stringType, + inferReverseMappedType(indexInfo.type, type.mappedType, type.constraintType), + readonlyMask && indexInfo.isReadonly, + )] : emptyArray; const members = createSymbolTable(); for (const prop of getPropertiesOfType(type.source)) { - const checkFlags = CheckFlags.ReverseMapped | (readonlyMask && isReadonlySymbol(prop) ? CheckFlags.Readonly : 0); - const inferredProp = createSymbol(SymbolFlags.Property | prop.flags & optionalMask, prop.escapedName, checkFlags) as ReverseMappedSymbol; + const checkFlags = CheckFlags.ReverseMapped + | (readonlyMask && isReadonlySymbol(prop) ? CheckFlags.Readonly : 0); + const inferredProp = createSymbol( + SymbolFlags.Property | prop.flags & optionalMask, + prop.escapedName, + checkFlags, + ) as ReverseMappedSymbol; inferredProp.declarations = prop.declarations; inferredProp.links.nameType = getSymbolLinks(prop).nameType; inferredProp.links.propertyType = getTypeOfSymbol(prop); @@ -13413,7 +17071,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // inferring to the "type parameter" (or indexed access) shared by the constraint and template. So, to reduce the number of // type identities produced, we simplify such indexed access occurences const newTypeParam = (type.constraintType.type as IndexedAccessType).objectType; - const newMappedType = replaceIndexedAccess(type.mappedType, type.constraintType.type as ReplaceableIndexedAccessType, newTypeParam); + const newMappedType = replaceIndexedAccess( + type.mappedType, + type.constraintType.type as ReplaceableIndexedAccessType, + newTypeParam, + ); inferredProp.links.mappedType = newMappedType as MappedType; inferredProp.links.constraintType = getIndexType(newTypeParam) as IndexType; } @@ -13439,7 +17101,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const checkType = (type as ConditionalType).checkType; const constraint = getLowerBoundOfKeyType(checkType); if (constraint !== checkType) { - return getConditionalTypeInstantiation(type as ConditionalType, prependTypeMapping((type as ConditionalType).root.checkType, constraint, (type as ConditionalType).mapper)); + return getConditionalTypeInstantiation( + type as ConditionalType, + prependTypeMapping( + (type as ConditionalType).root.checkType, + constraint, + (type as ConditionalType).mapper, + ), + ); } } return type; @@ -13451,7 +17120,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // Similarly to getTypeFromIntersectionTypeNode, we preserve the special string & {}, number & {}, // and bigint & {} intersections that are used to prevent subtype reduction in union types. const types = (type as IntersectionType).types; - if (types.length === 2 && !!(types[0].flags & (TypeFlags.String | TypeFlags.Number | TypeFlags.BigInt)) && types[1] === emptyTypeLiteralType) { + if ( + types.length === 2 && !!(types[0].flags & (TypeFlags.String | TypeFlags.Number | TypeFlags.BigInt)) + && types[1] === emptyTypeLiteralType + ) { return type; } return getIntersectionType(sameMap((type as UnionType).types, getLowerBoundOfKeyType)); @@ -13463,7 +17135,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return getCheckFlags(s) & CheckFlags.Late; } - function forEachMappedTypePropertyKeyTypeAndIndexSignatureKeyType(type: Type, include: TypeFlags, stringsOnly: boolean, cb: (keyType: Type) => void) { + function forEachMappedTypePropertyKeyTypeAndIndexSignatureKeyType( + type: Type, + include: TypeFlags, + stringsOnly: boolean, + cb: (keyType: Type) => void, + ) { for (const prop of getPropertiesOfType(type)) { cb(getLiteralTypeFromProperty(prop, include)); } @@ -13498,7 +17175,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const include = keyofStringsOnly ? TypeFlags.StringLiteral : TypeFlags.StringOrNumberLiteralOrUnique; if (isMappedTypeWithKeyofConstraintDeclaration(type)) { // We have a { [P in keyof T]: X } - forEachMappedTypePropertyKeyTypeAndIndexSignatureKeyType(modifiersType, include, keyofStringsOnly, addMemberForKeyType); + forEachMappedTypePropertyKeyTypeAndIndexSignatureKeyType( + modifiersType, + include, + keyofStringsOnly, + addMemberForKeyType, + ); } else { forEachType(getLowerBoundOfKeyType(constraintType), addMemberForKeyType); @@ -13506,7 +17188,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { setStructuredTypeMembers(type, members, emptyArray, emptyArray, indexInfos || emptyArray); function addMemberForKeyType(keyType: Type) { - const propNameType = nameType ? instantiateType(nameType, appendTypeMapping(type.mapper, typeParameter, keyType)) : keyType; + const propNameType = nameType + ? instantiateType(nameType, appendTypeMapping(type.mapper, typeParameter, keyType)) : keyType; forEachType(propNameType, t => addMemberForKeyTypeWorker(keyType, t)); } @@ -13524,14 +17207,23 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { existingProp.links.keyType = getUnionType([existingProp.links.keyType, keyType]); } else { - const modifiersProp = isTypeUsableAsPropertyName(keyType) ? getPropertyOfType(modifiersType, getPropertyNameFromType(keyType)) : undefined; - const isOptional = !!(templateModifiers & MappedTypeModifiers.IncludeOptional || - !(templateModifiers & MappedTypeModifiers.ExcludeOptional) && modifiersProp && modifiersProp.flags & SymbolFlags.Optional); - const isReadonly = !!(templateModifiers & MappedTypeModifiers.IncludeReadonly || - !(templateModifiers & MappedTypeModifiers.ExcludeReadonly) && modifiersProp && isReadonlySymbol(modifiersProp)); - const stripOptional = strictNullChecks && !isOptional && modifiersProp && modifiersProp.flags & SymbolFlags.Optional; + const modifiersProp = isTypeUsableAsPropertyName(keyType) + ? getPropertyOfType(modifiersType, getPropertyNameFromType(keyType)) : undefined; + const isOptional = !!(templateModifiers & MappedTypeModifiers.IncludeOptional + || !(templateModifiers & MappedTypeModifiers.ExcludeOptional) && modifiersProp + && modifiersProp.flags & SymbolFlags.Optional); + const isReadonly = !!(templateModifiers & MappedTypeModifiers.IncludeReadonly + || !(templateModifiers & MappedTypeModifiers.ExcludeReadonly) && modifiersProp + && isReadonlySymbol(modifiersProp)); + const stripOptional = strictNullChecks && !isOptional && modifiersProp + && modifiersProp.flags & SymbolFlags.Optional; const lateFlag: CheckFlags = modifiersProp ? getIsLateCheckFlag(modifiersProp) : 0; - const prop = createSymbol(SymbolFlags.Property | (isOptional ? SymbolFlags.Optional : 0), propName, lateFlag | CheckFlags.Mapped | (isReadonly ? CheckFlags.Readonly : 0) | (stripOptional ? CheckFlags.StripOptional : 0)) as MappedSymbol; + const prop = createSymbol( + SymbolFlags.Property | (isOptional ? SymbolFlags.Optional : 0), + propName, + lateFlag | CheckFlags.Mapped | (isReadonly ? CheckFlags.Readonly : 0) + | (stripOptional ? CheckFlags.StripOptional : 0), + ) as MappedSymbol; prop.links.mappedType = type; prop.links.nameType = propNameType; prop.links.keyType = keyType; @@ -13543,11 +17235,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } else if (isValidIndexKeyType(propNameType) || propNameType.flags & (TypeFlags.Any | TypeFlags.Enum)) { - const indexKeyType = propNameType.flags & (TypeFlags.Any | TypeFlags.String) ? stringType : - propNameType.flags & (TypeFlags.Number | TypeFlags.Enum) ? numberType : - propNameType; + const indexKeyType = propNameType.flags & (TypeFlags.Any | TypeFlags.String) ? stringType + : propNameType.flags & (TypeFlags.Number | TypeFlags.Enum) ? numberType + : propNameType; const propType = instantiateType(templateType, appendTypeMapping(type.mapper, typeParameter, keyType)); - const indexInfo = createIndexInfo(indexKeyType, propType, !!(templateModifiers & MappedTypeModifiers.IncludeReadonly)); + const indexInfo = createIndexInfo( + indexKeyType, + propType, + !!(templateModifiers & MappedTypeModifiers.IncludeReadonly), + ); indexInfos = appendIndexInfo(indexInfos, indexInfo, /*union*/ true); } } @@ -13561,16 +17257,27 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return errorType; } const templateType = getTemplateTypeFromMappedType(mappedType.target as MappedType || mappedType); - const mapper = appendTypeMapping(mappedType.mapper, getTypeParameterFromMappedType(mappedType), symbol.links.keyType); + const mapper = appendTypeMapping( + mappedType.mapper, + getTypeParameterFromMappedType(mappedType), + symbol.links.keyType, + ); const propType = instantiateType(templateType, mapper); // When creating an optional property in strictNullChecks mode, if 'undefined' isn't assignable to the // type, we include 'undefined' in the type. Similarly, when creating a non-optional property in strictNullChecks // mode, if the underlying property is optional we remove 'undefined' from the type. - let type = strictNullChecks && symbol.flags & SymbolFlags.Optional && !maybeTypeOfKind(propType, TypeFlags.Undefined | TypeFlags.Void) ? getOptionalType(propType, /*isProperty*/ true) : - symbol.links.checkFlags & CheckFlags.StripOptional ? removeMissingOrUndefinedType(propType) : - propType; + let type = strictNullChecks && symbol.flags & SymbolFlags.Optional + && !maybeTypeOfKind(propType, TypeFlags.Undefined | TypeFlags.Void) + ? getOptionalType(propType, /*isProperty*/ true) + : symbol.links.checkFlags & CheckFlags.StripOptional ? removeMissingOrUndefinedType(propType) + : propType; if (!popTypeResolution()) { - error(currentNode, Diagnostics.Type_of_property_0_circularly_references_itself_in_mapped_type_1, symbolToString(symbol), typeToString(mappedType)); + error( + currentNode, + Diagnostics.Type_of_property_0_circularly_references_itself_in_mapped_type_1, + symbolToString(symbol), + typeToString(mappedType), + ); type = errorType; } symbol.links.type = type; @@ -13579,26 +17286,36 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function getTypeParameterFromMappedType(type: MappedType) { - return type.typeParameter || - (type.typeParameter = getDeclaredTypeOfTypeParameter(getSymbolOfDeclaration(type.declaration.typeParameter))); + return type.typeParameter + || (type.typeParameter = getDeclaredTypeOfTypeParameter( + getSymbolOfDeclaration(type.declaration.typeParameter), + )); } function getConstraintTypeFromMappedType(type: MappedType) { - return type.constraintType || - (type.constraintType = getConstraintOfTypeParameter(getTypeParameterFromMappedType(type)) || errorType); + return type.constraintType + || (type.constraintType = getConstraintOfTypeParameter(getTypeParameterFromMappedType(type)) || errorType); } function getNameTypeFromMappedType(type: MappedType) { - return type.declaration.nameType ? - type.nameType || (type.nameType = instantiateType(getTypeFromTypeNode(type.declaration.nameType), type.mapper)) : - undefined; + return type.declaration.nameType + ? type.nameType + || (type.nameType = instantiateType(getTypeFromTypeNode(type.declaration.nameType), type.mapper)) + : undefined; } function getTemplateTypeFromMappedType(type: MappedType) { - return type.templateType || - (type.templateType = type.declaration.type ? - instantiateType(addOptionality(getTypeFromTypeNode(type.declaration.type), /*isProperty*/ true, !!(getMappedTypeModifiers(type) & MappedTypeModifiers.IncludeOptional)), type.mapper) : - errorType); + return type.templateType + || (type.templateType = type.declaration.type + ? instantiateType( + addOptionality( + getTypeFromTypeNode(type.declaration.type), + /*isProperty*/ true, + !!(getMappedTypeModifiers(type) & MappedTypeModifiers.IncludeOptional), + ), + type.mapper, + ) + : errorType); } function getConstraintDeclarationForMappedType(type: MappedType) { @@ -13607,8 +17324,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function isMappedTypeWithKeyofConstraintDeclaration(type: MappedType) { const constraintDeclaration = getConstraintDeclarationForMappedType(type)!; // TODO: GH#18217 - return constraintDeclaration.kind === SyntaxKind.TypeOperator && - (constraintDeclaration as TypeOperatorNode).operator === SyntaxKind.KeyOfKeyword; + return constraintDeclaration.kind === SyntaxKind.TypeOperator + && (constraintDeclaration as TypeOperatorNode).operator === SyntaxKind.KeyOfKeyword; } function getModifiersTypeFromMappedType(type: MappedType) { @@ -13617,7 +17334,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // If the constraint declaration is a 'keyof T' node, the modifiers type is T. We check // AST nodes here because, when T is a non-generic type, the logic below eagerly resolves // 'keyof T' to a literal union type and we can't recover T from that type. - type.modifiersType = instantiateType(getTypeFromTypeNode((getConstraintDeclarationForMappedType(type) as TypeOperatorNode).type), type.mapper); + type.modifiersType = instantiateType( + getTypeFromTypeNode((getConstraintDeclarationForMappedType(type) as TypeOperatorNode).type), + type.mapper, + ); } else { // Otherwise, get the declared constraint type, and if the constraint type is a type parameter, @@ -13625,8 +17345,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // the modifiers type is T. Otherwise, the modifiers type is unknown. const declaredType = getTypeFromMappedTypeNode(type.declaration) as MappedType; const constraint = getConstraintTypeFromMappedType(declaredType); - const extendedConstraint = constraint && constraint.flags & TypeFlags.TypeParameter ? getConstraintOfTypeParameter(constraint as TypeParameter) : constraint; - type.modifiersType = extendedConstraint && extendedConstraint.flags & TypeFlags.Index ? instantiateType((extendedConstraint as IndexType).type, type.mapper) : unknownType; + const extendedConstraint = constraint && constraint.flags & TypeFlags.TypeParameter + ? getConstraintOfTypeParameter(constraint as TypeParameter) : constraint; + type.modifiersType = extendedConstraint && extendedConstraint.flags & TypeFlags.Index + ? instantiateType((extendedConstraint as IndexType).type, type.mapper) : unknownType; } } return type.modifiersType; @@ -13634,13 +17356,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function getMappedTypeModifiers(type: MappedType): MappedTypeModifiers { const declaration = type.declaration; - return (declaration.readonlyToken ? declaration.readonlyToken.kind === SyntaxKind.MinusToken ? MappedTypeModifiers.ExcludeReadonly : MappedTypeModifiers.IncludeReadonly : 0) | - (declaration.questionToken ? declaration.questionToken.kind === SyntaxKind.MinusToken ? MappedTypeModifiers.ExcludeOptional : MappedTypeModifiers.IncludeOptional : 0); + return (declaration.readonlyToken + ? declaration.readonlyToken.kind === SyntaxKind.MinusToken ? MappedTypeModifiers.ExcludeReadonly + : MappedTypeModifiers.IncludeReadonly : 0) + | (declaration.questionToken + ? declaration.questionToken.kind === SyntaxKind.MinusToken ? MappedTypeModifiers.ExcludeOptional + : MappedTypeModifiers.IncludeOptional : 0); } function getMappedTypeOptionality(type: MappedType): number { const modifiers = getMappedTypeModifiers(type); - return modifiers & MappedTypeModifiers.ExcludeOptional ? -1 : modifiers & MappedTypeModifiers.IncludeOptional ? 1 : 0; + return modifiers & MappedTypeModifiers.ExcludeOptional ? -1 + : modifiers & MappedTypeModifiers.IncludeOptional ? 1 : 0; } function getCombinedMappedTypeOptionality(type: MappedType): number { @@ -13650,7 +17377,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function isPartialMappedType(type: Type) { - return !!(getObjectFlags(type) & ObjectFlags.Mapped && getMappedTypeModifiers(type as MappedType) & MappedTypeModifiers.IncludeOptional); + return !!(getObjectFlags(type) & ObjectFlags.Mapped + && getMappedTypeModifiers(type as MappedType) & MappedTypeModifiers.IncludeOptional); } function isGenericMappedType(type: Type): type is MappedType { @@ -13663,7 +17391,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // To determine this, we substitute the constraint type (that we now know isn't generic) for the iteration // type and check whether the resulting type is generic. const nameType = getNameTypeFromMappedType(type as MappedType); - if (nameType && isGenericIndexType(instantiateType(nameType, makeUnaryTypeMapper(getTypeParameterFromMappedType(type as MappedType), constraint)))) { + if ( + nameType + && isGenericIndexType( + instantiateType( + nameType, + makeUnaryTypeMapper(getTypeParameterFromMappedType(type as MappedType), constraint), + ), + ) + ) { return true; } } @@ -13756,9 +17492,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function getPropertiesOfType(type: Type): Symbol[] { type = getReducedApparentType(type); - return type.flags & TypeFlags.UnionOrIntersection ? - getPropertiesOfUnionOrIntersectionType(type as UnionType) : - getPropertiesOfObjectType(type); + return type.flags & TypeFlags.UnionOrIntersection + ? getPropertiesOfUnionOrIntersectionType(type as UnionType) + : getPropertiesOfObjectType(type); } function forEachPropertyOfType(type: Type, action: (symbol: Symbol, escapedName: __String) => void): void { @@ -13772,11 +17508,17 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } - function isTypeInvalidDueToUnionDiscriminant(contextualType: Type, obj: ObjectLiteralExpression | JsxAttributes): boolean { + function isTypeInvalidDueToUnionDiscriminant( + contextualType: Type, + obj: ObjectLiteralExpression | JsxAttributes, + ): boolean { const list = obj.properties as NodeArray; return list.some(property => { - const nameType = property.name && (isJsxNamespacedName(property.name) ? getStringLiteralType(getTextOfJsxAttributeName(property.name)) : getLiteralTypeFromPropertyName(property.name)); - const name = nameType && isTypeUsableAsPropertyName(nameType) ? getPropertyNameFromType(nameType) : undefined; + const nameType = property.name + && (isJsxNamespacedName(property.name) ? getStringLiteralType(getTextOfJsxAttributeName(property.name)) + : getLiteralTypeFromPropertyName(property.name)); + const name = nameType && isTypeUsableAsPropertyName(nameType) ? getPropertyNameFromType(nameType) + : undefined; const expected = name === undefined ? undefined : getTypeOfPropertyOfType(contextualType, name); return !!expected && isLiteralType(expected) && !isTypeAssignableTo(getTypeOfNode(property), expected); }); @@ -13802,10 +17544,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function getConstraintOfType(type: InstantiableType | UnionOrIntersectionType): Type | undefined { - return type.flags & TypeFlags.TypeParameter ? getConstraintOfTypeParameter(type as TypeParameter) : - type.flags & TypeFlags.IndexedAccess ? getConstraintOfIndexedAccess(type as IndexedAccessType) : - type.flags & TypeFlags.Conditional ? getConstraintOfConditionalType(type as ConditionalType) : - getBaseConstraintOfType(type); + return type.flags & TypeFlags.TypeParameter ? getConstraintOfTypeParameter(type as TypeParameter) + : type.flags & TypeFlags.IndexedAccess ? getConstraintOfIndexedAccess(type as IndexedAccessType) + : type.flags & TypeFlags.Conditional ? getConstraintOfConditionalType(type as ConditionalType) + : getBaseConstraintOfType(type); } function getConstraintOfTypeParameter(typeParameter: TypeParameter): Type | undefined { @@ -13814,12 +17556,20 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function isConstTypeVariable(type: Type | undefined, depth = 0): boolean { return depth < 5 && !!(type && ( - type.flags & TypeFlags.TypeParameter && some((type as TypeParameter).symbol?.declarations, d => hasSyntacticModifier(d, ModifierFlags.Const)) || - type.flags & TypeFlags.Union && some((type as UnionType).types, t => isConstTypeVariable(t, depth)) || - type.flags & TypeFlags.IndexedAccess && isConstTypeVariable((type as IndexedAccessType).objectType, depth + 1) || - type.flags & TypeFlags.Conditional && isConstTypeVariable(getConstraintOfConditionalType(type as ConditionalType), depth + 1) || - type.flags & TypeFlags.Substitution && isConstTypeVariable((type as SubstitutionType).baseType, depth) || - isGenericTupleType(type) && findIndex(getElementTypes(type), (t, i) => !!(type.target.elementFlags[i] & ElementFlags.Variadic) && isConstTypeVariable(t, depth)) >= 0 + type.flags & TypeFlags.TypeParameter + && some((type as TypeParameter).symbol?.declarations, d => hasSyntacticModifier(d, ModifierFlags.Const)) + || type.flags & TypeFlags.Union && some((type as UnionType).types, t => isConstTypeVariable(t, depth)) + || type.flags & TypeFlags.IndexedAccess + && isConstTypeVariable((type as IndexedAccessType).objectType, depth + 1) + || type.flags & TypeFlags.Conditional + && isConstTypeVariable(getConstraintOfConditionalType(type as ConditionalType), depth + 1) + || type.flags & TypeFlags.Substitution && isConstTypeVariable((type as SubstitutionType).baseType, depth) + || isGenericTupleType(type) + && findIndex( + getElementTypes(type), + (t, i) => + !!(type.target.elementFlags[i] & ElementFlags.Variadic) && isConstTypeVariable(t, depth), + ) >= 0 )); } @@ -13860,7 +17610,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // in effect treating `any` like `never` rather than `unknown` in this location. const trueConstraint = getInferredTrueTypeFromConditionalType(type); const falseConstraint = getFalseTypeFromConditionalType(type); - type.resolvedDefaultConstraint = isTypeAny(trueConstraint) ? falseConstraint : isTypeAny(falseConstraint) ? trueConstraint : getUnionType([trueConstraint, falseConstraint]); + type.resolvedDefaultConstraint = isTypeAny(trueConstraint) ? falseConstraint + : isTypeAny(falseConstraint) ? trueConstraint : getUnionType([trueConstraint, falseConstraint]); } return type.resolvedDefaultConstraint; } @@ -13885,7 +17636,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const simplified = getSimplifiedType(type.checkType, /*writing*/ false); const constraint = simplified === type.checkType ? getConstraintOfType(simplified) : simplified; if (constraint && constraint !== type.checkType) { - const instantiated = getConditionalTypeInstantiation(type, prependTypeMapping(type.root.checkType, constraint, type.mapper)); + const instantiated = getConditionalTypeInstantiation( + type, + prependTypeMapping(type.root.checkType, constraint, type.mapper), + ); if (!(instantiated.flags & TypeFlags.Never)) { type.resolvedConstraintOfDistributive = instantiated; return instantiated; @@ -13912,7 +17666,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // We keep following constraints as long as we have an instantiable type that is known // not to be circular or infinite (hence we stop on index access types). let constraint = getConstraintOfType(t); - while (constraint && constraint.flags & (TypeFlags.TypeParameter | TypeFlags.Index | TypeFlags.Conditional)) { + while ( + constraint && constraint.flags & (TypeFlags.TypeParameter | TypeFlags.Index | TypeFlags.Conditional) + ) { constraint = getConstraintOfType(constraint); } if (constraint) { @@ -13945,7 +17701,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function getBaseConstraintOfType(type: Type): Type | undefined { - if (type.flags & (TypeFlags.InstantiableNonPrimitive | TypeFlags.UnionOrIntersection | TypeFlags.TemplateLiteral | TypeFlags.StringMapping) || isGenericTupleType(type)) { + if ( + type.flags + & (TypeFlags.InstantiableNonPrimitive | TypeFlags.UnionOrIntersection | TypeFlags.TemplateLiteral + | TypeFlags.StringMapping) || isGenericTupleType(type) + ) { const constraint = getResolvedBaseConstraint(type as InstantiableType | UnionOrIntersectionType); return constraint !== noConstraintType && constraint !== circularConstraintType ? constraint : undefined; } @@ -13998,9 +17758,22 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (t.flags & TypeFlags.TypeParameter) { const errorNode = getConstraintDeclaration(t as TypeParameter); if (errorNode) { - const diagnostic = error(errorNode, Diagnostics.Type_parameter_0_has_a_circular_constraint, typeToString(t)); - if (currentNode && !isNodeDescendantOf(errorNode, currentNode) && !isNodeDescendantOf(currentNode, errorNode)) { - addRelatedInfo(diagnostic, createDiagnosticForNode(currentNode, Diagnostics.Circularity_originates_in_type_at_this_location)); + const diagnostic = error( + errorNode, + Diagnostics.Type_parameter_0_has_a_circular_constraint, + typeToString(t), + ); + if ( + currentNode && !isNodeDescendantOf(errorNode, currentNode) + && !isNodeDescendantOf(currentNode, errorNode) + ) { + addRelatedInfo( + diagnostic, + createDiagnosticForNode( + currentNode, + Diagnostics.Circularity_originates_in_type_at_this_location, + ), + ); } } } @@ -14019,9 +17792,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function computeBaseConstraint(t: Type): Type | undefined { if (t.flags & TypeFlags.TypeParameter) { const constraint = getConstraintFromTypeParameter(t as TypeParameter); - return (t as TypeParameter).isThisType || !constraint ? - constraint : - getBaseConstraint(constraint); + return (t as TypeParameter).isThisType || !constraint + ? constraint + : getBaseConstraint(constraint); } if (t.flags & TypeFlags.UnionOrIntersection) { const types = (t as UnionOrIntersectionType).types; @@ -14042,9 +17815,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (!different) { return t; } - return t.flags & TypeFlags.Union && baseTypes.length === types.length ? getUnionType(baseTypes) : - t.flags & TypeFlags.Intersection && baseTypes.length ? getIntersectionType(baseTypes) : - undefined; + return t.flags & TypeFlags.Union && baseTypes.length === types.length ? getUnionType(baseTypes) + : t.flags & TypeFlags.Intersection && baseTypes.length ? getIntersectionType(baseTypes) + : undefined; } if (t.flags & TypeFlags.Index) { return keyofConstraintType; @@ -14052,21 +17825,33 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (t.flags & TypeFlags.TemplateLiteral) { const types = (t as TemplateLiteralType).types; const constraints = mapDefined(types, getBaseConstraint); - return constraints.length === types.length ? getTemplateLiteralType((t as TemplateLiteralType).texts, constraints) : stringType; + return constraints.length === types.length + ? getTemplateLiteralType((t as TemplateLiteralType).texts, constraints) : stringType; } if (t.flags & TypeFlags.StringMapping) { const constraint = getBaseConstraint((t as StringMappingType).type); - return constraint && constraint !== (t as StringMappingType).type ? getStringMappingType((t as StringMappingType).symbol, constraint) : stringType; + return constraint && constraint !== (t as StringMappingType).type + ? getStringMappingType((t as StringMappingType).symbol, constraint) : stringType; } if (t.flags & TypeFlags.IndexedAccess) { if (isMappedTypeGenericIndexedAccess(t)) { // For indexed access types of the form { [P in K]: E }[X], where K is non-generic and X is generic, // we substitute an instantiation of E where P is replaced with X. - return getBaseConstraint(substituteIndexedMappedType((t as IndexedAccessType).objectType as MappedType, (t as IndexedAccessType).indexType)); + return getBaseConstraint( + substituteIndexedMappedType( + (t as IndexedAccessType).objectType as MappedType, + (t as IndexedAccessType).indexType, + ), + ); } const baseObjectType = getBaseConstraint((t as IndexedAccessType).objectType); const baseIndexType = getBaseConstraint((t as IndexedAccessType).indexType); - const baseIndexedAccess = baseObjectType && baseIndexType && getIndexedAccessTypeOrUndefined(baseObjectType, baseIndexType, (t as IndexedAccessType).accessFlags); + const baseIndexedAccess = baseObjectType && baseIndexType + && getIndexedAccessTypeOrUndefined( + baseObjectType, + baseIndexType, + (t as IndexedAccessType).accessFlags, + ); return baseIndexedAccess && getBaseConstraint(baseIndexedAccess); } if (t.flags & TypeFlags.Conditional) { @@ -14080,29 +17865,44 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // We substitute constraints for variadic elements only when the constraints are array types or // non-variadic tuple types as we want to avoid further (possibly unbounded) recursion. const newElements = map(getElementTypes(t), (v, i) => { - const constraint = v.flags & TypeFlags.TypeParameter && t.target.elementFlags[i] & ElementFlags.Variadic && getBaseConstraint(v) || v; - return constraint !== v && everyType(constraint, c => isArrayOrTupleType(c) && !isGenericTupleType(c)) ? constraint : v; + const constraint = + v.flags & TypeFlags.TypeParameter && t.target.elementFlags[i] & ElementFlags.Variadic + && getBaseConstraint(v) || v; + return constraint !== v + && everyType(constraint, c => isArrayOrTupleType(c) && !isGenericTupleType(c)) ? constraint + : v; }); - return createTupleType(newElements, t.target.elementFlags, t.target.readonly, t.target.labeledElementDeclarations); + return createTupleType( + newElements, + t.target.elementFlags, + t.target.readonly, + t.target.labeledElementDeclarations, + ); } return t; } } function getApparentTypeOfIntersectionType(type: IntersectionType, thisArgument: Type) { - return type.resolvedApparentType || (type.resolvedApparentType = getTypeWithThisArgument(type, thisArgument, /*needApparentType*/ true)); + return type.resolvedApparentType + || (type.resolvedApparentType = getTypeWithThisArgument(type, thisArgument, /*needApparentType*/ true)); } function getResolvedTypeParameterDefault(typeParameter: TypeParameter): Type | undefined { if (!typeParameter.default) { if (typeParameter.target) { const targetDefault = getResolvedTypeParameterDefault(typeParameter.target); - typeParameter.default = targetDefault ? instantiateType(targetDefault, typeParameter.mapper) : noConstraintType; + typeParameter.default = targetDefault ? instantiateType(targetDefault, typeParameter.mapper) + : noConstraintType; } else { // To block recursion, set the initial value to the resolvingDefaultType. typeParameter.default = resolvingDefaultType; - const defaultDeclaration = typeParameter.symbol && forEach(typeParameter.symbol.declarations, decl => isTypeParameterDeclaration(decl) && decl.default); + const defaultDeclaration = typeParameter.symbol + && forEach( + typeParameter.symbol.declarations, + decl => isTypeParameterDeclaration(decl) && decl.default, + ); const defaultType = defaultDeclaration ? getTypeFromTypeNode(defaultDeclaration) : noConstraintType; if (typeParameter.default === resolvingDefaultType) { // If we have not been called recursively, set the correct default type. @@ -14137,7 +17937,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { * Indicates whether the declaration of a typeParameter has a default type. */ function hasTypeParameterDefault(typeParameter: TypeParameter): boolean { - return !!(typeParameter.symbol && forEach(typeParameter.symbol.declarations, decl => isTypeParameterDeclaration(decl) && decl.default)); + return !!(typeParameter.symbol + && forEach(typeParameter.symbol.declarations, decl => isTypeParameterDeclaration(decl) && decl.default)); } function getApparentTypeOfMappedType(type: MappedType) { @@ -14157,9 +17958,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function isMappedTypeGenericIndexedAccess(type: Type) { let objectType; - return !!(type.flags & TypeFlags.IndexedAccess && getObjectFlags(objectType = (type as IndexedAccessType).objectType) & ObjectFlags.Mapped && - !isGenericMappedType(objectType) && isGenericIndexType((type as IndexedAccessType).indexType) && - !(getMappedTypeModifiers(objectType as MappedType) & MappedTypeModifiers.ExcludeOptional) && !(objectType as MappedType).declaration.nameType); + return !!(type.flags & TypeFlags.IndexedAccess + && getObjectFlags(objectType = (type as IndexedAccessType).objectType) & ObjectFlags.Mapped + && !isGenericMappedType(objectType) && isGenericIndexType((type as IndexedAccessType).indexType) + && !(getMappedTypeModifiers(objectType as MappedType) & MappedTypeModifiers.ExcludeOptional) + && !(objectType as MappedType).declaration.nameType); } /** @@ -14170,18 +17973,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function getApparentType(type: Type): Type { const t = type.flags & TypeFlags.Instantiable ? getBaseConstraintOfType(type) || unknownType : type; const objectFlags = getObjectFlags(t); - return objectFlags & ObjectFlags.Mapped ? getApparentTypeOfMappedType(t as MappedType) : - objectFlags & ObjectFlags.Reference && t !== type ? getTypeWithThisArgument(t, type) : - t.flags & TypeFlags.Intersection ? getApparentTypeOfIntersectionType(t as IntersectionType, type) : - t.flags & TypeFlags.StringLike ? globalStringType : - t.flags & TypeFlags.NumberLike ? globalNumberType : - t.flags & TypeFlags.BigIntLike ? getGlobalBigIntType() : - t.flags & TypeFlags.BooleanLike ? globalBooleanType : - t.flags & TypeFlags.ESSymbolLike ? getGlobalESSymbolType() : - t.flags & TypeFlags.NonPrimitive ? emptyObjectType : - t.flags & TypeFlags.Index ? keyofConstraintType : - t.flags & TypeFlags.Unknown && !strictNullChecks ? emptyObjectType : - t; + return objectFlags & ObjectFlags.Mapped ? getApparentTypeOfMappedType(t as MappedType) + : objectFlags & ObjectFlags.Reference && t !== type ? getTypeWithThisArgument(t, type) + : t.flags & TypeFlags.Intersection ? getApparentTypeOfIntersectionType(t as IntersectionType, type) + : t.flags & TypeFlags.StringLike ? globalStringType + : t.flags & TypeFlags.NumberLike ? globalNumberType + : t.flags & TypeFlags.BigIntLike ? getGlobalBigIntType() + : t.flags & TypeFlags.BooleanLike ? globalBooleanType + : t.flags & TypeFlags.ESSymbolLike ? getGlobalESSymbolType() + : t.flags & TypeFlags.NonPrimitive ? emptyObjectType + : t.flags & TypeFlags.Index ? keyofConstraintType + : t.flags & TypeFlags.Unknown && !strictNullChecks ? emptyObjectType + : t; } function getReducedApparentType(type: Type): Type { @@ -14192,7 +17995,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return getReducedType(getApparentType(getReducedType(type))); } - function createUnionOrIntersectionProperty(containingType: UnionOrIntersectionType, name: __String, skipObjectFunctionPropertyAugment?: boolean): Symbol | undefined { + function createUnionOrIntersectionProperty( + containingType: UnionOrIntersectionType, + name: __String, + skipObjectFunctionPropertyAugment?: boolean, + ): Symbol | undefined { let singleProp: Symbol | undefined; let propSet: Map | undefined; let indexTypes: Type[] | undefined; @@ -14221,15 +18028,21 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { singleProp = prop; } else if (prop !== singleProp) { - const isInstantiation = (getTargetSymbol(prop) || prop) === (getTargetSymbol(singleProp) || singleProp); + const isInstantiation = + (getTargetSymbol(prop) || prop) === (getTargetSymbol(singleProp) || singleProp); // If the symbols are instances of one another with identical types - consider the symbols // equivalent and just use the first one, which thus allows us to avoid eliding private // members when intersecting a (this-)instantiations of a class with its raw base or another instance - if (isInstantiation && compareProperties(singleProp, prop, (a, b) => a === b ? Ternary.True : Ternary.False) === Ternary.True) { + if ( + isInstantiation + && compareProperties(singleProp, prop, (a, b) => a === b ? Ternary.True : Ternary.False) + === Ternary.True + ) { // If we merged instantiations of a generic type, we replicate the symbol parent resetting behavior we used // to do when we recorded multiple distinct symbols so that we still get, eg, `Array.length` printed // back and not `Array.length` when we're looking at a `.length` access on a `string[] | number[]` - mergedInstantiations = !!singleProp.parent && !!length(getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(singleProp.parent)); + mergedInstantiations = !!singleProp.parent + && !!length(getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(singleProp.parent)); } else { if (!propSet) { @@ -14248,10 +18061,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { else if (!isUnion && !isReadonlySymbol(prop)) { checkFlags &= ~CheckFlags.Readonly; } - checkFlags |= (!(modifiers & ModifierFlags.NonPublicAccessibilityModifier) ? CheckFlags.ContainsPublic : 0) | - (modifiers & ModifierFlags.Protected ? CheckFlags.ContainsProtected : 0) | - (modifiers & ModifierFlags.Private ? CheckFlags.ContainsPrivate : 0) | - (modifiers & ModifierFlags.Static ? CheckFlags.ContainsStatic : 0); + checkFlags |= + (!(modifiers & ModifierFlags.NonPublicAccessibilityModifier) ? CheckFlags.ContainsPublic : 0) + | (modifiers & ModifierFlags.Protected ? CheckFlags.ContainsProtected : 0) + | (modifiers & ModifierFlags.Private ? CheckFlags.ContainsPrivate : 0) + | (modifiers & ModifierFlags.Static ? CheckFlags.ContainsStatic : 0); if (!isPrototypeProperty(prop)) { syntheticFlag = CheckFlags.SyntheticProperty; } @@ -14260,7 +18074,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const indexInfo = !isLateBoundName(name) && getApplicableIndexInfoForName(type, name); if (indexInfo) { checkFlags |= CheckFlags.WritePartial | (indexInfo.isReadonly ? CheckFlags.Readonly : 0); - indexTypes = append(indexTypes, isTupleType(type) ? getRestTypeOfTupleType(type) || undefinedType : indexInfo.type); + indexTypes = append( + indexTypes, + isTupleType(type) ? getRestTypeOfTupleType(type) || undefinedType : indexInfo.type, + ); } else if (isObjectLiteralType(type) && !(getObjectFlags(type) & ObjectFlags.ContainsSpread)) { checkFlags |= CheckFlags.WritePartial; @@ -14273,11 +18090,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } if ( - !singleProp || - isUnion && - (propSet || checkFlags & CheckFlags.Partial) && - checkFlags & (CheckFlags.ContainsPrivate | CheckFlags.ContainsProtected) && - !(propSet && getCommonDeclarationsOfSymbols(propSet.values())) + !singleProp + || isUnion + && (propSet || checkFlags & CheckFlags.Partial) + && checkFlags & (CheckFlags.ContainsPrivate | CheckFlags.ContainsProtected) + && !(propSet && getCommonDeclarationsOfSymbols(propSet.values())) ) { // No property was found, or, in a union, a property has a private or protected declaration in one // constituent, but is missing or has a different declaration in another constituent. @@ -14370,15 +18187,19 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // constituents, in which case the isPartial flag is set when the containing type is union type. We need // these partial properties when identifying discriminant properties, but otherwise they are filtered out // and do not appear to be present in the union type. - function getUnionOrIntersectionProperty(type: UnionOrIntersectionType, name: __String, skipObjectFunctionPropertyAugment?: boolean): Symbol | undefined { - let property = type.propertyCacheWithoutObjectFunctionPropertyAugment?.get(name) || - !skipObjectFunctionPropertyAugment ? type.propertyCache?.get(name) : undefined; + function getUnionOrIntersectionProperty( + type: UnionOrIntersectionType, + name: __String, + skipObjectFunctionPropertyAugment?: boolean, + ): Symbol | undefined { + let property = type.propertyCacheWithoutObjectFunctionPropertyAugment?.get(name) + || !skipObjectFunctionPropertyAugment ? type.propertyCache?.get(name) : undefined; if (!property) { property = createUnionOrIntersectionProperty(type, name, skipObjectFunctionPropertyAugment); if (property) { - const properties = skipObjectFunctionPropertyAugment ? - type.propertyCacheWithoutObjectFunctionPropertyAugment ||= createSymbolTable() : - type.propertyCache ||= createSymbolTable(); + const properties = skipObjectFunctionPropertyAugment + ? type.propertyCacheWithoutObjectFunctionPropertyAugment ||= createSymbolTable() + : type.propertyCache ||= createSymbolTable(); properties.set(name, property); } } @@ -14407,7 +18228,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return commonDeclarations; } - function getPropertyOfUnionOrIntersectionType(type: UnionOrIntersectionType, name: __String, skipObjectFunctionPropertyAugment?: boolean): Symbol | undefined { + function getPropertyOfUnionOrIntersectionType( + type: UnionOrIntersectionType, + name: __String, + skipObjectFunctionPropertyAugment?: boolean, + ): Symbol | undefined { const property = getUnionOrIntersectionProperty(type, name, skipObjectFunctionPropertyAugment); // We need to filter out partial properties in union types return property && !(getCheckFlags(property) & CheckFlags.ReadPartial) ? property : undefined; @@ -14421,12 +18246,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { */ function getReducedType(type: Type): Type { if (type.flags & TypeFlags.Union && (type as UnionType).objectFlags & ObjectFlags.ContainsIntersections) { - return (type as UnionType).resolvedReducedType || ((type as UnionType).resolvedReducedType = getReducedUnionType(type as UnionType)); + return (type as UnionType).resolvedReducedType + || ((type as UnionType).resolvedReducedType = getReducedUnionType(type as UnionType)); } else if (type.flags & TypeFlags.Intersection) { if (!((type as IntersectionType).objectFlags & ObjectFlags.IsNeverIntersectionComputed)) { - (type as IntersectionType).objectFlags |= ObjectFlags.IsNeverIntersectionComputed | - (some(getPropertiesOfUnionOrIntersectionType(type as IntersectionType), isNeverReducedProperty) ? ObjectFlags.IsNeverIntersection : 0); + (type as IntersectionType).objectFlags |= ObjectFlags.IsNeverIntersectionComputed + | (some(getPropertiesOfUnionOrIntersectionType(type as IntersectionType), isNeverReducedProperty) + ? ObjectFlags.IsNeverIntersection : 0); } return (type as IntersectionType).objectFlags & ObjectFlags.IsNeverIntersection ? neverType : type; } @@ -14452,9 +18279,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function isDiscriminantWithNeverType(prop: Symbol) { // Return true for a synthetic non-optional property with non-uniform types, where at least one is // a literal type and none is never, that reduces to never. - return !(prop.flags & SymbolFlags.Optional) && - (getCheckFlags(prop) & (CheckFlags.Discriminant | CheckFlags.HasNeverType)) === CheckFlags.Discriminant && - !!(getTypeOfSymbol(prop).flags & TypeFlags.Never); + return !(prop.flags & SymbolFlags.Optional) + && (getCheckFlags(prop) & (CheckFlags.Discriminant | CheckFlags.HasNeverType)) === CheckFlags.Discriminant + && !!(getTypeOfSymbol(prop).flags & TypeFlags.Never); } function isConflictingPrivateProperty(prop: Symbol) { @@ -14470,24 +18297,44 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { * literal-typed properties are reducible). */ function isGenericReducibleType(type: Type): boolean { - return !!(type.flags & TypeFlags.Union && (type as UnionType).objectFlags & ObjectFlags.ContainsIntersections && some((type as UnionType).types, isGenericReducibleType) || - type.flags & TypeFlags.Intersection && isReducibleIntersection(type as IntersectionType)); + return !!(type.flags & TypeFlags.Union && (type as UnionType).objectFlags & ObjectFlags.ContainsIntersections + && some((type as UnionType).types, isGenericReducibleType) + || type.flags & TypeFlags.Intersection && isReducibleIntersection(type as IntersectionType)); } function isReducibleIntersection(type: IntersectionType) { - const uniqueFilled = type.uniqueLiteralFilledInstantiation || (type.uniqueLiteralFilledInstantiation = instantiateType(type, uniqueLiteralMapper)); + const uniqueFilled = type.uniqueLiteralFilledInstantiation + || (type.uniqueLiteralFilledInstantiation = instantiateType(type, uniqueLiteralMapper)); return getReducedType(uniqueFilled) !== uniqueFilled; } function elaborateNeverIntersection(errorInfo: DiagnosticMessageChain | undefined, type: Type) { if (type.flags & TypeFlags.Intersection && getObjectFlags(type) & ObjectFlags.IsNeverIntersection) { - const neverProp = find(getPropertiesOfUnionOrIntersectionType(type as IntersectionType), isDiscriminantWithNeverType); + const neverProp = find( + getPropertiesOfUnionOrIntersectionType(type as IntersectionType), + isDiscriminantWithNeverType, + ); if (neverProp) { - return chainDiagnosticMessages(errorInfo, Diagnostics.The_intersection_0_was_reduced_to_never_because_property_1_has_conflicting_types_in_some_constituents, typeToString(type, /*enclosingDeclaration*/ undefined, TypeFormatFlags.NoTypeReduction), symbolToString(neverProp)); + return chainDiagnosticMessages( + errorInfo, + Diagnostics + .The_intersection_0_was_reduced_to_never_because_property_1_has_conflicting_types_in_some_constituents, + typeToString(type, /*enclosingDeclaration*/ undefined, TypeFormatFlags.NoTypeReduction), + symbolToString(neverProp), + ); } - const privateProp = find(getPropertiesOfUnionOrIntersectionType(type as IntersectionType), isConflictingPrivateProperty); + const privateProp = find( + getPropertiesOfUnionOrIntersectionType(type as IntersectionType), + isConflictingPrivateProperty, + ); if (privateProp) { - return chainDiagnosticMessages(errorInfo, Diagnostics.The_intersection_0_was_reduced_to_never_because_property_1_exists_in_multiple_constituents_and_is_private_in_some, typeToString(type, /*enclosingDeclaration*/ undefined, TypeFormatFlags.NoTypeReduction), symbolToString(privateProp)); + return chainDiagnosticMessages( + errorInfo, + Diagnostics + .The_intersection_0_was_reduced_to_never_because_property_1_exists_in_multiple_constituents_and_is_private_in_some, + typeToString(type, /*enclosingDeclaration*/ undefined, TypeFormatFlags.NoTypeReduction), + symbolToString(privateProp), + ); } } return errorInfo; @@ -14501,7 +18348,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { * @param type a type to look up property from * @param name a name of property to look up in a given type */ - function getPropertyOfType(type: Type, name: __String, skipObjectFunctionPropertyAugment?: boolean, includeTypeOnlyMembers?: boolean): Symbol | undefined { + function getPropertyOfType( + type: Type, + name: __String, + skipObjectFunctionPropertyAugment?: boolean, + includeTypeOnlyMembers?: boolean, + ): Symbol | undefined { type = getReducedApparentType(type); if (type.flags & TypeFlags.Object) { const resolved = resolveStructuredTypeMembers(type as ObjectType); @@ -14510,10 +18362,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return symbol; } if (skipObjectFunctionPropertyAugment) return undefined; - const functionType = resolved === anyFunctionType ? globalFunctionType : - resolved.callSignatures.length ? globalCallableFunctionType : - resolved.constructSignatures.length ? globalNewableFunctionType : - undefined; + const functionType = resolved === anyFunctionType ? globalFunctionType + : resolved.callSignatures.length ? globalCallableFunctionType + : resolved.constructSignatures.length ? globalNewableFunctionType + : undefined; if (functionType) { const symbol = getPropertyOfObjectType(functionType, name); if (symbol) { @@ -14523,7 +18375,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return getPropertyOfObjectType(globalObjectType, name); } if (type.flags & TypeFlags.UnionOrIntersection) { - return getPropertyOfUnionOrIntersectionType(type as UnionOrIntersectionType, name, skipObjectFunctionPropertyAugment); + return getPropertyOfUnionOrIntersectionType( + type as UnionOrIntersectionType, + name, + skipObjectFunctionPropertyAugment, + ); } return undefined; } @@ -14548,11 +18404,28 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } // If the union is all different instantiations of a member of the global array type... let memberName: __String; - if (everyType(type, t => !!t.symbol?.parent && isArrayOrTupleSymbol(t.symbol.parent) && (!memberName ? (memberName = t.symbol.escapedName, true) : memberName === t.symbol.escapedName))) { + if ( + everyType(type, t => + !!t.symbol?.parent && isArrayOrTupleSymbol(t.symbol.parent) + && (!memberName ? (memberName = t.symbol.escapedName, true) : memberName === t.symbol.escapedName)) + ) { // Transform the type from `(A[] | B[])["member"]` to `(A | B)[]["member"]` (since we pretend array is covariant anyway) - const arrayArg = mapType(type, t => getMappedType((isReadonlyArraySymbol(t.symbol.parent) ? globalReadonlyArrayType : globalArrayType).typeParameters![0], (t as AnonymousType).mapper!)); - const arrayType = createArrayType(arrayArg, someType(type, t => isReadonlyArraySymbol(t.symbol.parent))); - return (type as UnionType).arrayFallbackSignatures = getSignaturesOfType(getTypeOfPropertyOfType(arrayType, memberName!)!, kind); + const arrayArg = mapType( + type, + t => getMappedType( + (isReadonlyArraySymbol(t.symbol.parent) ? globalReadonlyArrayType : globalArrayType) + .typeParameters![0], + (t as AnonymousType).mapper!, + ), + ); + const arrayType = createArrayType( + arrayArg, + someType(type, t => isReadonlyArraySymbol(t.symbol.parent)), + ); + return (type as UnionType).arrayFallbackSignatures = getSignaturesOfType( + getTypeOfPropertyOfType(arrayType, memberName!)!, + kind, + ); } (type as UnionType).arrayFallbackSignatures = result; } @@ -14563,7 +18436,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (!symbol || !globalArrayType.symbol || !globalReadonlyArrayType.symbol) { return false; } - return !!getSymbolIfSameReference(symbol, globalArrayType.symbol) || !!getSymbolIfSameReference(symbol, globalReadonlyArrayType.symbol); + return !!getSymbolIfSameReference(symbol, globalArrayType.symbol) + || !!getSymbolIfSameReference(symbol, globalReadonlyArrayType.symbol); } function isReadonlyArraySymbol(symbol: Symbol | undefined) { @@ -14598,18 +18472,26 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // When more than one index signature is applicable we create a synthetic IndexInfo. Instead of computing // the intersected key type, we just use unknownType for the key type as nothing actually depends on the // keyType property of the returned IndexInfo. - return applicableInfos ? createIndexInfo(unknownType, getIntersectionType(map(applicableInfos, info => info.type)), reduceLeft(applicableInfos, (isReadonly, info) => isReadonly && info.isReadonly, /*initial*/ true)) : - applicableInfo ? applicableInfo : - stringIndexInfo && isApplicableIndexType(keyType, stringType) ? stringIndexInfo : - undefined; + return applicableInfos + ? createIndexInfo( + unknownType, + getIntersectionType(map(applicableInfos, info => info.type)), + reduceLeft(applicableInfos, (isReadonly, info) => isReadonly && info.isReadonly, /*initial*/ true), + ) + : applicableInfo ? applicableInfo + : stringIndexInfo && isApplicableIndexType(keyType, stringType) ? stringIndexInfo + : undefined; } function isApplicableIndexType(source: Type, target: Type): boolean { // A 'string' index signature applies to types assignable to 'string' or 'number', and a 'number' index // signature applies to types assignable to 'number', `${number}` and numeric string literal types. - return isTypeAssignableTo(source, target) || - target === stringType && isTypeAssignableTo(source, numberType) || - target === numberType && (source === numericStringType || !!(source.flags & TypeFlags.StringLiteral) && isNumericLiteralName((source as StringLiteralType).value)); + return isTypeAssignableTo(source, target) + || target === stringType && isTypeAssignableTo(source, numberType) + || target === numberType + && (source === numericStringType + || !!(source.flags & TypeFlags.StringLiteral) + && isNumericLiteralName((source as StringLiteralType).value)); } function getIndexInfosOfStructuredType(type: Type): readonly IndexInfo[] { @@ -14645,12 +18527,17 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function getApplicableIndexInfoForName(type: Type, name: __String): IndexInfo | undefined { - return getApplicableIndexInfo(type, isLateBoundName(name) ? esSymbolType : getStringLiteralType(unescapeLeadingUnderscores(name))); + return getApplicableIndexInfo( + type, + isLateBoundName(name) ? esSymbolType : getStringLiteralType(unescapeLeadingUnderscores(name)), + ); } // Return list of type parameters with duplicates removed (duplicate identifier errors are generated in the actual // type checking functions). - function getTypeParametersFromDeclaration(declaration: DeclarationWithTypeParameters): readonly TypeParameter[] | undefined { + function getTypeParametersFromDeclaration( + declaration: DeclarationWithTypeParameters, + ): readonly TypeParameter[] | undefined { let result: TypeParameter[] | undefined; for (const node of getEffectiveTypeParameterDeclarations(declaration)) { result = appendIfUnique(result, getDeclaredTypeOfTypeParameter(node.symbol)); @@ -14691,13 +18578,17 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // Only consider syntactic or instantiated parameters as optional, not `void` parameters as this function is used // in grammar checks and checking for `void` too early results in parameter types widening too early // and causes some noImplicitAny errors to be lost. - return parameterIndex >= getMinArgumentCount(signature, MinArgumentCountFlags.StrongArityForUntypedJS | MinArgumentCountFlags.VoidIsNonOptional); + return parameterIndex + >= getMinArgumentCount( + signature, + MinArgumentCountFlags.StrongArityForUntypedJS | MinArgumentCountFlags.VoidIsNonOptional, + ); } const iife = getImmediatelyInvokedFunctionExpression(node.parent); if (iife) { - return !node.type && - !node.dotDotDotToken && - node.parent.parameters.indexOf(node) >= iife.arguments.length; + return !node.type + && !node.dotDotDotToken + && node.parent.parameters.indexOf(node) >= iife.arguments.length; } return false; @@ -14707,7 +18598,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return isPropertyDeclaration(node) && !hasAccessorModifier(node) && node.questionToken; } - function createTypePredicate(kind: TypePredicateKind, parameterName: string | undefined, parameterIndex: number | undefined, type: Type | undefined): TypePredicate { + function createTypePredicate( + kind: TypePredicateKind, + parameterName: string | undefined, + parameterIndex: number | undefined, + type: Type | undefined, + ): TypePredicate { return { kind, parameterName, parameterIndex, type } as TypePredicate; } @@ -14735,15 +18631,33 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { * @param typeParameters The requested type parameters. * @param minTypeArgumentCount The minimum number of required type arguments. */ - function fillMissingTypeArguments(typeArguments: readonly Type[], typeParameters: readonly TypeParameter[] | undefined, minTypeArgumentCount: number, isJavaScriptImplicitAny: boolean): Type[]; - function fillMissingTypeArguments(typeArguments: readonly Type[] | undefined, typeParameters: readonly TypeParameter[] | undefined, minTypeArgumentCount: number, isJavaScriptImplicitAny: boolean): Type[] | undefined; - function fillMissingTypeArguments(typeArguments: readonly Type[] | undefined, typeParameters: readonly TypeParameter[] | undefined, minTypeArgumentCount: number, isJavaScriptImplicitAny: boolean) { + function fillMissingTypeArguments( + typeArguments: readonly Type[], + typeParameters: readonly TypeParameter[] | undefined, + minTypeArgumentCount: number, + isJavaScriptImplicitAny: boolean, + ): Type[]; + function fillMissingTypeArguments( + typeArguments: readonly Type[] | undefined, + typeParameters: readonly TypeParameter[] | undefined, + minTypeArgumentCount: number, + isJavaScriptImplicitAny: boolean, + ): Type[] | undefined; + function fillMissingTypeArguments( + typeArguments: readonly Type[] | undefined, + typeParameters: readonly TypeParameter[] | undefined, + minTypeArgumentCount: number, + isJavaScriptImplicitAny: boolean, + ) { const numTypeParameters = length(typeParameters); if (!numTypeParameters) { return []; } const numTypeArguments = length(typeArguments); - if (isJavaScriptImplicitAny || (numTypeArguments >= minTypeArgumentCount && numTypeArguments <= numTypeParameters)) { + if ( + isJavaScriptImplicitAny + || (numTypeArguments >= minTypeArgumentCount && numTypeArguments <= numTypeParameters) + ) { const result = typeArguments ? typeArguments.slice() : []; // Map invalid forward references in default types to the error type for (let i = numTypeArguments; i < numTypeParameters; i++) { @@ -14752,10 +18666,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const baseDefaultType = getDefaultTypeArgumentType(isJavaScriptImplicitAny); for (let i = numTypeArguments; i < numTypeParameters; i++) { let defaultType = getDefaultFromTypeParameter(typeParameters![i]); - if (isJavaScriptImplicitAny && defaultType && (isTypeIdenticalTo(defaultType, unknownType) || isTypeIdenticalTo(defaultType, emptyObjectType))) { + if ( + isJavaScriptImplicitAny && defaultType + && (isTypeIdenticalTo(defaultType, unknownType) || isTypeIdenticalTo(defaultType, emptyObjectType)) + ) { defaultType = anyType; } - result[i] = defaultType ? instantiateType(defaultType, createTypeMapper(typeParameters!, result)) : baseDefaultType; + result[i] = defaultType ? instantiateType(defaultType, createTypeMapper(typeParameters!, result)) + : baseDefaultType; } result.length = typeParameters!.length; return result; @@ -14773,11 +18691,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { let hasThisParameter = false; const iife = getImmediatelyInvokedFunctionExpression(declaration); const isJSConstructSignature = isJSDocConstructSignature(declaration); - const isUntypedSignatureInJSFile = !iife && - isInJSFile(declaration) && - isValueSignatureDeclaration(declaration) && - !hasJSDocParameterTags(declaration) && - !getJSDocType(declaration); + const isUntypedSignatureInJSFile = !iife + && isInJSFile(declaration) + && isValueSignatureDeclaration(declaration) + && !hasJSDocParameterTags(declaration) + && !getJSDocType(declaration); if (isUntypedSignatureInJSFile) { flags |= SignatureFlags.IsUntypedSignatureInJSFile; } @@ -14789,10 +18707,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const param = declaration.parameters[i]; let paramSymbol = param.symbol; - const type = isJSDocParameterTag(param) ? (param.typeExpression && param.typeExpression.type) : param.type; + const type = isJSDocParameterTag(param) ? (param.typeExpression && param.typeExpression.type) + : param.type; // Include parameter symbol instead of property symbol in the signature if (paramSymbol && !!(paramSymbol.flags & SymbolFlags.Property) && !isBindingPattern(param.name)) { - const resolvedSymbol = resolveName(param, paramSymbol.escapedName, SymbolFlags.Value, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ false); + const resolvedSymbol = resolveName( + param, + paramSymbol.escapedName, + SymbolFlags.Value, + /*nameNotFoundMessage*/ undefined, + /*nameArg*/ undefined, + /*isUse*/ false, + ); paramSymbol = resolvedSymbol!; } if (i === 0 && paramSymbol.escapedName === InternalSymbolName.This) { @@ -14808,10 +18734,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } // Record a new minimum argument count if this is not an optional parameter - const isOptionalParameter = isOptionalJSDocPropertyLikeTag(param) || - param.initializer || param.questionToken || isRestParameter(param) || - iife && parameters.length > iife.arguments.length && !type || - isJSDocOptionalParameter(param); + const isOptionalParameter = isOptionalJSDocPropertyLikeTag(param) + || param.initializer || param.questionToken || isRestParameter(param) + || iife && parameters.length > iife.arguments.length && !type + || isJSDocOptionalParameter(param); if (!isOptionalParameter) { minArgumentCount = parameters.length; } @@ -14819,11 +18745,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // If only one accessor includes a this-type annotation, the other behaves as if it had the same type annotation if ( - (declaration.kind === SyntaxKind.GetAccessor || declaration.kind === SyntaxKind.SetAccessor) && - hasBindableName(declaration) && - (!hasThisParameter || !thisParameter) + (declaration.kind === SyntaxKind.GetAccessor || declaration.kind === SyntaxKind.SetAccessor) + && hasBindableName(declaration) + && (!hasThisParameter || !thisParameter) ) { - const otherKind = declaration.kind === SyntaxKind.GetAccessor ? SyntaxKind.SetAccessor : SyntaxKind.GetAccessor; + const otherKind = declaration.kind === SyntaxKind.GetAccessor ? SyntaxKind.SetAccessor + : SyntaxKind.GetAccessor; const other = getDeclarationOfKind(getSymbolOfDeclaration(declaration), otherKind); if (other) { thisParameter = getAnnotatedAccessorThisParameter(other); @@ -14833,25 +18760,44 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (isInJSFile(declaration)) { const thisTag = getJSDocThisTag(declaration); if (thisTag && thisTag.typeExpression) { - thisParameter = createSymbolWithType(createSymbol(SymbolFlags.FunctionScopedVariable, InternalSymbolName.This), getTypeFromTypeNode(thisTag.typeExpression)); + thisParameter = createSymbolWithType( + createSymbol(SymbolFlags.FunctionScopedVariable, InternalSymbolName.This), + getTypeFromTypeNode(thisTag.typeExpression), + ); } } const hostDeclaration = isJSDocSignature(declaration) ? getEffectiveJSDocHost(declaration) : declaration; - const classType = hostDeclaration && isConstructorDeclaration(hostDeclaration) ? - getDeclaredTypeOfClassOrInterface(getMergedSymbol((hostDeclaration.parent as ClassDeclaration).symbol)) + const classType = hostDeclaration && isConstructorDeclaration(hostDeclaration) + ? getDeclaredTypeOfClassOrInterface( + getMergedSymbol((hostDeclaration.parent as ClassDeclaration).symbol), + ) : undefined; - const typeParameters = classType ? classType.localTypeParameters : getTypeParametersFromDeclaration(declaration); - if (hasRestParameter(declaration) || isInJSFile(declaration) && maybeAddJsSyntheticRestParameter(declaration, parameters)) { + const typeParameters = classType ? classType.localTypeParameters + : getTypeParametersFromDeclaration(declaration); + if ( + hasRestParameter(declaration) + || isInJSFile(declaration) && maybeAddJsSyntheticRestParameter(declaration, parameters) + ) { flags |= SignatureFlags.HasRestParameter; } if ( - isConstructorTypeNode(declaration) && hasSyntacticModifier(declaration, ModifierFlags.Abstract) || - isConstructorDeclaration(declaration) && hasSyntacticModifier(declaration.parent, ModifierFlags.Abstract) + isConstructorTypeNode(declaration) && hasSyntacticModifier(declaration, ModifierFlags.Abstract) + || isConstructorDeclaration(declaration) + && hasSyntacticModifier(declaration.parent, ModifierFlags.Abstract) ) { flags |= SignatureFlags.Abstract; } - links.resolvedSignature = createSignature(declaration, typeParameters, thisParameter, parameters, /*resolvedReturnType*/ undefined, /*resolvedTypePredicate*/ undefined, minArgumentCount, flags); + links.resolvedSignature = createSignature( + declaration, + typeParameters, + thisParameter, + parameters, + /*resolvedReturnType*/ undefined, + /*resolvedTypePredicate*/ undefined, + minArgumentCount, + flags, + ); } return links.resolvedSignature; } @@ -14862,13 +18808,20 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { * OR * 2. It has at least one parameter, and the last parameter has a matching `@param` with a type that starts with `...` */ - function maybeAddJsSyntheticRestParameter(declaration: SignatureDeclaration | JSDocSignature, parameters: Symbol[]): boolean { + function maybeAddJsSyntheticRestParameter( + declaration: SignatureDeclaration | JSDocSignature, + parameters: Symbol[], + ): boolean { if (isJSDocSignature(declaration) || !containsArgumentsReference(declaration)) { return false; } const lastParam = lastOrUndefined(declaration.parameters); - const lastParamTags = lastParam ? getJSDocParameterTags(lastParam) : getJSDocTags(declaration).filter(isJSDocParameterTag); - const lastParamVariadicType = firstDefined(lastParamTags, p => p.typeExpression && isJSDocVariadicType(p.typeExpression.type) ? p.typeExpression.type : undefined); + const lastParamTags = lastParam ? getJSDocParameterTags(lastParam) + : getJSDocTags(declaration).filter(isJSDocParameterTag); + const lastParamVariadicType = firstDefined( + lastParamTags, + p => p.typeExpression && isJSDocVariadicType(p.typeExpression.type) ? p.typeExpression.type : undefined, + ); const syntheticArgsSymbol = createSymbol(SymbolFlags.Variable, "args" as __String, CheckFlags.RestParameter); if (lastParamVariadicType) { @@ -14927,7 +18880,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (!node) return false; switch (node.kind) { case SyntaxKind.Identifier: - return (node as Identifier).escapedText === argumentsSymbol.escapedName && getReferencedValueSymbol(node as Identifier) === argumentsSymbol; + return (node as Identifier).escapedText === argumentsSymbol.escapedName + && getReferencedValueSymbol(node as Identifier) === argumentsSymbol; case SyntaxKind.PropertyDeclaration: case SyntaxKind.MethodDeclaration: @@ -14944,7 +18898,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return traverse((node as PropertyAssignment).initializer); default: - return !nodeStartsNewLexicalEnvironment(node) && !isPartOfTypeNode(node) && !!forEachChild(node, traverse); + return !nodeStartsNewLexicalEnvironment(node) && !isPartOfTypeNode(node) + && !!forEachChild(node, traverse); } } } @@ -14987,10 +18942,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // If this is a function or method declaration, get the signature from the @type tag for the sake of optional parameters. // Exclude contextually-typed kinds because we already apply the @type tag to the context, plus applying it here to the initializer would supress checks that the two are compatible. result.push( - (!isFunctionExpressionOrArrowFunction(decl) && - !isObjectLiteralMethod(decl) && - getSignatureOfTypeTag(decl)) || - getSignatureFromDeclaration(decl), + (!isFunctionExpressionOrArrowFunction(decl) + && !isObjectLiteralMethod(decl) + && getSignatureOfTypeTag(decl)) + || getSignatureFromDeclaration(decl), ); } return result; @@ -15018,10 +18973,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (!signature.resolvedTypePredicate) { if (signature.target) { const targetTypePredicate = getTypePredicateOfSignature(signature.target); - signature.resolvedTypePredicate = targetTypePredicate ? instantiateTypePredicate(targetTypePredicate, signature.mapper!) : noTypePredicate; + signature.resolvedTypePredicate = targetTypePredicate + ? instantiateTypePredicate(targetTypePredicate, signature.mapper!) : noTypePredicate; } else if (signature.compositeSignatures) { - signature.resolvedTypePredicate = getUnionOrIntersectionTypePredicate(signature.compositeSignatures, signature.compositeKind) || noTypePredicate; + signature.resolvedTypePredicate = + getUnionOrIntersectionTypePredicate(signature.compositeSignatures, signature.compositeKind) + || noTypePredicate; } else { const type = signature.declaration && getEffectiveReturnTypeNode(signature.declaration); @@ -15032,9 +18990,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { jsdocPredicate = getTypePredicateOfSignature(jsdocSignature); } } - signature.resolvedTypePredicate = type && isTypePredicateNode(type) ? - createTypePredicateFromTypePredicateNode(type, signature) : - jsdocPredicate || noTypePredicate; + signature.resolvedTypePredicate = type && isTypePredicateNode(type) + ? createTypePredicateFromTypePredicateNode(type, signature) + : jsdocPredicate || noTypePredicate; } Debug.assert(!!signature.resolvedTypePredicate); } @@ -15044,9 +19002,19 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function createTypePredicateFromTypePredicateNode(node: TypePredicateNode, signature: Signature): TypePredicate { const parameterName = node.parameterName; const type = node.type && getTypeFromTypeNode(node.type); - return parameterName.kind === SyntaxKind.ThisType ? - createTypePredicate(node.assertsModifier ? TypePredicateKind.AssertsThis : TypePredicateKind.This, /*parameterName*/ undefined, /*parameterIndex*/ undefined, type) : - createTypePredicate(node.assertsModifier ? TypePredicateKind.AssertsIdentifier : TypePredicateKind.Identifier, parameterName.escapedText as string, findIndex(signature.parameters, p => p.escapedName === parameterName.escapedText), type); + return parameterName.kind === SyntaxKind.ThisType + ? createTypePredicate( + node.assertsModifier ? TypePredicateKind.AssertsThis : TypePredicateKind.This, + /*parameterName*/ undefined, + /*parameterIndex*/ undefined, + type, + ) + : createTypePredicate( + node.assertsModifier ? TypePredicateKind.AssertsIdentifier : TypePredicateKind.Identifier, + parameterName.escapedText as string, + findIndex(signature.parameters, p => p.escapedName === parameterName.escapedText), + type, + ); } function getUnionOrIntersectionType(types: Type[], kind: TypeFlags | undefined, unionReduction?: UnionReduction) { @@ -15058,10 +19026,19 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (!pushTypeResolution(signature, TypeSystemPropertyName.ResolvedReturnType)) { return errorType; } - let type = signature.target ? instantiateType(getReturnTypeOfSignature(signature.target), signature.mapper) : - signature.compositeSignatures ? instantiateType(getUnionOrIntersectionType(map(signature.compositeSignatures, getReturnTypeOfSignature), signature.compositeKind, UnionReduction.Subtype), signature.mapper) : - getReturnTypeFromAnnotation(signature.declaration!) || - (nodeIsMissing((signature.declaration as FunctionLikeDeclaration).body) ? anyType : getReturnTypeFromBody(signature.declaration as FunctionLikeDeclaration)); + let type = signature.target ? instantiateType(getReturnTypeOfSignature(signature.target), signature.mapper) + : signature.compositeSignatures + ? instantiateType( + getUnionOrIntersectionType( + map(signature.compositeSignatures, getReturnTypeOfSignature), + signature.compositeKind, + UnionReduction.Subtype, + ), + signature.mapper, + ) + : getReturnTypeFromAnnotation(signature.declaration!) + || (nodeIsMissing((signature.declaration as FunctionLikeDeclaration).body) ? anyType + : getReturnTypeFromBody(signature.declaration as FunctionLikeDeclaration)); if (signature.flags & SignatureFlags.IsInnerCallChain) { type = addOptionalTypeMarker(type); } @@ -15078,10 +19055,19 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const declaration = signature.declaration as Declaration; const name = getNameOfDeclaration(declaration); if (name) { - error(name, Diagnostics._0_implicitly_has_return_type_any_because_it_does_not_have_a_return_type_annotation_and_is_referenced_directly_or_indirectly_in_one_of_its_return_expressions, declarationNameToString(name)); + error( + name, + Diagnostics + ._0_implicitly_has_return_type_any_because_it_does_not_have_a_return_type_annotation_and_is_referenced_directly_or_indirectly_in_one_of_its_return_expressions, + declarationNameToString(name), + ); } else { - error(declaration, Diagnostics.Function_implicitly_has_return_type_any_because_it_does_not_have_a_return_type_annotation_and_is_referenced_directly_or_indirectly_in_one_of_its_return_expressions); + error( + declaration, + Diagnostics + .Function_implicitly_has_return_type_any_because_it_does_not_have_a_return_type_annotation_and_is_referenced_directly_or_indirectly_in_one_of_its_return_expressions, + ); } } } @@ -15100,7 +19086,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (isJSDocSignature(declaration)) { const root = getJSDocRoot(declaration); if (root && isConstructorDeclaration(root.parent) && !typeNode) { - return getDeclaredTypeOfClassOrInterface(getMergedSymbol((root.parent.parent as ClassDeclaration).symbol)); + return getDeclaredTypeOfClassOrInterface( + getMergedSymbol((root.parent.parent as ClassDeclaration).symbol), + ); } } if (isJSDocConstructSignature(declaration)) { @@ -15114,7 +19102,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (jsDocType) { return jsDocType; } - const setter = getDeclarationOfKind(getSymbolOfDeclaration(declaration), SyntaxKind.SetAccessor); + const setter = getDeclarationOfKind( + getSymbolOfDeclaration(declaration), + SyntaxKind.SetAccessor, + ); const setterType = getAnnotatedAccessorType(setter); if (setterType) { return setterType; @@ -15124,8 +19115,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function isResolvingReturnTypeOfSignature(signature: Signature): boolean { - return signature.compositeSignatures && some(signature.compositeSignatures, isResolvingReturnTypeOfSignature) || - !signature.resolvedReturnType && findResolutionCycleStartIndex(signature, TypeSystemPropertyName.ResolvedReturnType) >= 0; + return signature.compositeSignatures && some(signature.compositeSignatures, isResolvingReturnTypeOfSignature) + || !signature.resolvedReturnType + && findResolutionCycleStartIndex(signature, TypeSystemPropertyName.ResolvedReturnType) >= 0; } function getRestTypeOfSignature(signature: Signature): Type { @@ -15141,8 +19133,21 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return undefined; } - function getSignatureInstantiation(signature: Signature, typeArguments: Type[] | undefined, isJavascript: boolean, inferredTypeParameters?: readonly TypeParameter[]): Signature { - const instantiatedSignature = getSignatureInstantiationWithoutFillingInTypeArguments(signature, fillMissingTypeArguments(typeArguments, signature.typeParameters, getMinTypeArgumentCount(signature.typeParameters), isJavascript)); + function getSignatureInstantiation( + signature: Signature, + typeArguments: Type[] | undefined, + isJavascript: boolean, + inferredTypeParameters?: readonly TypeParameter[], + ): Signature { + const instantiatedSignature = getSignatureInstantiationWithoutFillingInTypeArguments( + signature, + fillMissingTypeArguments( + typeArguments, + signature.typeParameters, + getMinTypeArgumentCount(signature.typeParameters), + isJavascript, + ), + ); if (inferredTypeParameters) { const returnSignature = getSingleCallOrConstructSignature(getReturnTypeOfSignature(instantiatedSignature)); if (returnSignature) { @@ -15156,7 +19161,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return instantiatedSignature; } - function getSignatureInstantiationWithoutFillingInTypeArguments(signature: Signature, typeArguments: readonly Type[] | undefined): Signature { + function getSignatureInstantiationWithoutFillingInTypeArguments( + signature: Signature, + typeArguments: readonly Type[] | undefined, + ): Signature { const instantiations = signature.instantiations || (signature.instantiations = new Map()); const id = getTypeListId(typeArguments); let instantiation = instantiations.get(id); @@ -15167,7 +19175,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function createSignatureInstantiation(signature: Signature, typeArguments: readonly Type[] | undefined): Signature { - return instantiateSignature(signature, createSignatureTypeMapper(signature, typeArguments), /*eraseTypeParameters*/ true); + return instantiateSignature( + signature, + createSignatureTypeMapper(signature, typeArguments), + /*eraseTypeParameters*/ true, + ); } function createSignatureTypeMapper(signature: Signature, typeArguments: readonly Type[] | undefined): TypeMapper { @@ -15175,20 +19187,25 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function getErasedSignature(signature: Signature): Signature { - return signature.typeParameters ? - signature.erasedSignatureCache || (signature.erasedSignatureCache = createErasedSignature(signature)) : - signature; + return signature.typeParameters + ? signature.erasedSignatureCache || (signature.erasedSignatureCache = createErasedSignature(signature)) + : signature; } function createErasedSignature(signature: Signature) { // Create an instantiation of the signature where all type arguments are the any type. - return instantiateSignature(signature, createTypeEraser(signature.typeParameters!), /*eraseTypeParameters*/ true); + return instantiateSignature( + signature, + createTypeEraser(signature.typeParameters!), + /*eraseTypeParameters*/ true, + ); } function getCanonicalSignature(signature: Signature): Signature { - return signature.typeParameters ? - signature.canonicalSignatureCache || (signature.canonicalSignatureCache = createCanonicalSignature(signature)) : - signature; + return signature.typeParameters + ? signature.canonicalSignatureCache + || (signature.canonicalSignatureCache = createCanonicalSignature(signature)) + : signature; } function createCanonicalSignature(signature: Signature) { @@ -15212,8 +19229,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return signature.baseSignatureCache; } const typeEraser = createTypeEraser(typeParameters); - const baseConstraintMapper = createTypeMapper(typeParameters, map(typeParameters, tp => getConstraintOfTypeParameter(tp) || unknownType)); - let baseConstraints: readonly Type[] = map(typeParameters, tp => instantiateType(tp, baseConstraintMapper) || unknownType); + const baseConstraintMapper = createTypeMapper( + typeParameters, + map(typeParameters, tp => getConstraintOfTypeParameter(tp) || unknownType), + ); + let baseConstraints: readonly Type[] = map( + typeParameters, + tp => instantiateType(tp, baseConstraintMapper) || unknownType, + ); // Run N type params thru the immediate constraint mapper up to N times // This way any noncircular interdependent type parameters are definitely resolved to their external dependencies for (let i = 0; i < typeParameters.length - 1; i++) { @@ -15221,7 +19244,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } // and then apply a type eraser to remove any remaining circularly dependent type parameters baseConstraints = instantiateTypes(baseConstraints, typeEraser); - return signature.baseSignatureCache = instantiateSignature(signature, createTypeMapper(typeParameters, baseConstraints), /*eraseTypeParameters*/ true); + return signature.baseSignatureCache = instantiateSignature( + signature, + createTypeMapper(typeParameters, baseConstraints), + /*eraseTypeParameters*/ true, + ); } return signature; } @@ -15235,7 +19262,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const kind = signature.declaration?.kind; // If declaration is undefined, it is likely to be the signature of the default constructor. - const isConstructor = kind === undefined || kind === SyntaxKind.Constructor || kind === SyntaxKind.ConstructSignature || kind === SyntaxKind.ConstructorType; + const isConstructor = kind === undefined || kind === SyntaxKind.Constructor + || kind === SyntaxKind.ConstructSignature || kind === SyntaxKind.ConstructorType; const type = createObjectType(ObjectFlags.Anonymous); type.members = emptySymbols; @@ -15257,7 +19285,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return symbolTable.get(InternalSymbolName.Index); } - function createIndexInfo(keyType: Type, type: Type, isReadonly: boolean, declaration?: IndexSignatureDeclaration): IndexInfo { + function createIndexInfo( + keyType: Type, + type: Type, + isReadonly: boolean, + declaration?: IndexSignatureDeclaration, + ): IndexInfo { return { keyType, type, isReadonly, declaration }; } @@ -15275,7 +19308,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (parameter.type) { forEachType(getTypeFromTypeNode(parameter.type), keyType => { if (isValidIndexKeyType(keyType) && !findIndexInfo(indexInfos, keyType)) { - indexInfos.push(createIndexInfo(keyType, declaration.type ? getTypeFromTypeNode(declaration.type) : anyType, hasEffectiveModifier(declaration, ModifierFlags.Readonly), declaration)); + indexInfos.push( + createIndexInfo( + keyType, + declaration.type ? getTypeFromTypeNode(declaration.type) : anyType, + hasEffectiveModifier(declaration, ModifierFlags.Readonly), + declaration, + ), + ); } }); } @@ -15287,12 +19327,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function isValidIndexKeyType(type: Type): boolean { - return !!(type.flags & (TypeFlags.String | TypeFlags.Number | TypeFlags.ESSymbol)) || isPatternLiteralType(type) || - !!(type.flags & TypeFlags.Intersection) && !isGenericType(type) && some((type as IntersectionType).types, isValidIndexKeyType); + return !!(type.flags & (TypeFlags.String | TypeFlags.Number | TypeFlags.ESSymbol)) || isPatternLiteralType(type) + || !!(type.flags & TypeFlags.Intersection) && !isGenericType(type) + && some((type as IntersectionType).types, isValidIndexKeyType); } function getConstraintDeclaration(type: TypeParameter): TypeNode | undefined { - return mapDefined(filter(type.symbol && type.symbol.declarations, isTypeParameterDeclaration), getEffectiveConstraintOfTypeParameter)[0]; + return mapDefined( + filter(type.symbol && type.symbol.declarations, isTypeParameterDeclaration), + getEffectiveConstraintOfTypeParameter, + )[0]; } function getInferredTypeParameterConstraint(typeParameter: TypeParameter, omitTypeReferences?: boolean) { @@ -15304,7 +19348,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // (such as 'Foo'), T's constraint is inferred from the constraint of the // corresponding type parameter in 'Foo'. When multiple 'infer T' declarations are // present, we form an intersection of the inferred constraint types. - const [childTypeParameter = declaration.parent, grandParent] = walkUpParenthesizedTypesAndGetParentAndChild(declaration.parent.parent); + const [childTypeParameter = declaration.parent, grandParent] = + walkUpParenthesizedTypesAndGetParentAndChild(declaration.parent.parent); if (grandParent.kind === SyntaxKind.TypeReference && !omitTypeReferences) { const typeReference = grandParent as TypeReferenceNode; const typeParameters = getTypeParametersForTypeReferenceOrImport(typeReference); @@ -15322,7 +19367,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const mapper = makeDeferredTypeMapper( typeParameters, typeParameters.map((_, index) => () => { - return getEffectiveTypeArgumentAtIndex(typeReference, typeParameters, index); + return getEffectiveTypeArgumentAtIndex( + typeReference, + typeParameters, + index, + ); }), ); const constraint = instantiateType(declaredConstraint, mapper); @@ -15336,9 +19385,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // When an 'infer T' declaration is immediately contained in a rest parameter declaration, a rest type // or a named rest tuple element, we infer an 'unknown[]' constraint. else if ( - grandParent.kind === SyntaxKind.Parameter && (grandParent as ParameterDeclaration).dotDotDotToken || - grandParent.kind === SyntaxKind.RestType || - grandParent.kind === SyntaxKind.NamedTupleMember && (grandParent as NamedTupleMember).dotDotDotToken + grandParent.kind === SyntaxKind.Parameter + && (grandParent as ParameterDeclaration).dotDotDotToken + || grandParent.kind === SyntaxKind.RestType + || grandParent.kind === SyntaxKind.NamedTupleMember + && (grandParent as NamedTupleMember).dotDotDotToken ) { inferences = append(inferences, createArrayType(unknownType)); } @@ -15349,21 +19400,39 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } // When an 'infer T' declaration is in the constraint position of a mapped type, we infer a 'keyof any' // constraint. - else if (grandParent.kind === SyntaxKind.TypeParameter && grandParent.parent.kind === SyntaxKind.MappedType) { + else if ( + grandParent.kind === SyntaxKind.TypeParameter + && grandParent.parent.kind === SyntaxKind.MappedType + ) { inferences = append(inferences, keyofConstraintType); } // When an 'infer T' declaration is the template of a mapped type, and that mapped type is the extends // clause of a conditional whose check type is also a mapped type, give it a constraint equal to the template // of the check type's mapped type else if ( - grandParent.kind === SyntaxKind.MappedType && (grandParent as MappedTypeNode).type && - skipParentheses((grandParent as MappedTypeNode).type!) === declaration.parent && grandParent.parent.kind === SyntaxKind.ConditionalType && - (grandParent.parent as ConditionalTypeNode).extendsType === grandParent && (grandParent.parent as ConditionalTypeNode).checkType.kind === SyntaxKind.MappedType && - ((grandParent.parent as ConditionalTypeNode).checkType as MappedTypeNode).type + grandParent.kind === SyntaxKind.MappedType && (grandParent as MappedTypeNode).type + && skipParentheses((grandParent as MappedTypeNode).type!) === declaration.parent + && grandParent.parent.kind === SyntaxKind.ConditionalType + && (grandParent.parent as ConditionalTypeNode).extendsType === grandParent + && (grandParent.parent as ConditionalTypeNode).checkType.kind === SyntaxKind.MappedType + && ((grandParent.parent as ConditionalTypeNode).checkType as MappedTypeNode).type ) { const checkMappedType = (grandParent.parent as ConditionalTypeNode).checkType as MappedTypeNode; const nodeType = getTypeFromTypeNode(checkMappedType.type!); - inferences = append(inferences, instantiateType(nodeType, makeUnaryTypeMapper(getDeclaredTypeOfTypeParameter(getSymbolOfDeclaration(checkMappedType.typeParameter)), checkMappedType.typeParameter.constraint ? getTypeFromTypeNode(checkMappedType.typeParameter.constraint) : keyofConstraintType))); + inferences = append( + inferences, + instantiateType( + nodeType, + makeUnaryTypeMapper( + getDeclaredTypeOfTypeParameter( + getSymbolOfDeclaration(checkMappedType.typeParameter), + ), + checkMappedType.typeParameter.constraint + ? getTypeFromTypeNode(checkMappedType.typeParameter.constraint) + : keyofConstraintType, + ), + ), + ); } } } @@ -15376,7 +19445,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (!typeParameter.constraint) { if (typeParameter.target) { const targetConstraint = getConstraintOfTypeParameter(typeParameter.target); - typeParameter.constraint = targetConstraint ? instantiateType(targetConstraint, typeParameter.mapper) : noConstraintType; + typeParameter.constraint = targetConstraint ? instantiateType(targetConstraint, typeParameter.mapper) + : noConstraintType; } else { const constraintDeclaration = getConstraintDeclaration(typeParameter); @@ -15388,7 +19458,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (type.flags & TypeFlags.Any && !isErrorType(type)) { // Allow errorType to propegate to keep downstream errors suppressed // use keyofConstraintType as the base constraint for mapped type key constraints (unknown isn;t assignable to that, but `any` was), // use unknown otherwise - type = constraintDeclaration.parent.parent.kind === SyntaxKind.MappedType ? keyofConstraintType : unknownType; + type = constraintDeclaration.parent.parent.kind === SyntaxKind.MappedType ? keyofConstraintType + : unknownType; } typeParameter.constraint = type; } @@ -15428,7 +19499,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function getAliasId(aliasSymbol: Symbol | undefined, aliasTypeArguments: readonly Type[] | undefined) { - return aliasSymbol ? `@${getSymbolId(aliasSymbol)}` + (aliasTypeArguments ? `:${getTypeListId(aliasTypeArguments)}` : "") : ""; + return aliasSymbol + ? `@${getSymbolId(aliasSymbol)}` + (aliasTypeArguments ? `:${getTypeListId(aliasTypeArguments)}` : "") : ""; } // This function is used to propagate certain flags when creating new object type references and union types. @@ -15474,7 +19546,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return type; } - function createDeferredTypeReference(target: GenericType, node: TypeReferenceNode | ArrayTypeNode | TupleTypeNode, mapper?: TypeMapper, aliasSymbol?: Symbol, aliasTypeArguments?: readonly Type[]): DeferredTypeReference { + function createDeferredTypeReference( + target: GenericType, + node: TypeReferenceNode | ArrayTypeNode | TupleTypeNode, + mapper?: TypeMapper, + aliasSymbol?: Symbol, + aliasTypeArguments?: readonly Type[], + ): DeferredTypeReference { if (!aliasSymbol) { aliasSymbol = getAliasSymbolForTypeNode(node); const localAliasTypeArguments = getTypeArgumentsForAliasSymbol(aliasSymbol); @@ -15495,10 +19573,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return type.target.localTypeParameters?.map(() => errorType) || emptyArray; } const node = type.node; - const typeArguments = !node ? emptyArray : - node.kind === SyntaxKind.TypeReference ? concatenate(type.target.outerTypeParameters, getEffectiveTypeArguments(node, type.target.localTypeParameters!)) : - node.kind === SyntaxKind.ArrayType ? [getTypeFromTypeNode(node.elementType)] : - map(node.elements, getTypeFromTypeNode); + const typeArguments = !node ? emptyArray + : node.kind === SyntaxKind.TypeReference + ? concatenate( + type.target.outerTypeParameters, + getEffectiveTypeArguments(node, type.target.localTypeParameters!), + ) + : node.kind === SyntaxKind.ArrayType ? [getTypeFromTypeNode(node.elementType)] + : map(node.elements, getTypeFromTypeNode); if (popTypeResolution()) { type.resolvedTypeArguments = type.mapper ? instantiateTypes(typeArguments, type.mapper) : typeArguments; } @@ -15506,7 +19588,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { type.resolvedTypeArguments = type.target.localTypeParameters?.map(() => errorType) || emptyArray; error( type.node || currentNode, - type.target.symbol ? Diagnostics.Type_arguments_for_0_circularly_reference_themselves : Diagnostics.Tuple_type_arguments_circularly_reference_themselves, + type.target.symbol ? Diagnostics.Type_arguments_for_0_circularly_reference_themselves + : Diagnostics.Tuple_type_arguments_circularly_reference_themselves, type.target.symbol && symbolToString(type.target.symbol), ); } @@ -15529,38 +19612,72 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const minTypeArgumentCount = getMinTypeArgumentCount(typeParameters); const isJs = isInJSFile(node); const isJsImplicitAny = !noImplicitAny && isJs; - if (!isJsImplicitAny && (numTypeArguments < minTypeArgumentCount || numTypeArguments > typeParameters.length)) { - const missingAugmentsTag = isJs && isExpressionWithTypeArguments(node) && !isJSDocAugmentsTag(node.parent); - const diag = minTypeArgumentCount === typeParameters.length ? - missingAugmentsTag ? - Diagnostics.Expected_0_type_arguments_provide_these_with_an_extends_tag : - Diagnostics.Generic_type_0_requires_1_type_argument_s : - missingAugmentsTag ? - Diagnostics.Expected_0_1_type_arguments_provide_these_with_an_extends_tag : - Diagnostics.Generic_type_0_requires_between_1_and_2_type_arguments; - - const typeStr = typeToString(type, /*enclosingDeclaration*/ undefined, TypeFormatFlags.WriteArrayAsGenericType); + if ( + !isJsImplicitAny + && (numTypeArguments < minTypeArgumentCount || numTypeArguments > typeParameters.length) + ) { + const missingAugmentsTag = isJs && isExpressionWithTypeArguments(node) + && !isJSDocAugmentsTag(node.parent); + const diag = minTypeArgumentCount === typeParameters.length + ? missingAugmentsTag + ? Diagnostics.Expected_0_type_arguments_provide_these_with_an_extends_tag + : Diagnostics.Generic_type_0_requires_1_type_argument_s + : missingAugmentsTag + ? Diagnostics.Expected_0_1_type_arguments_provide_these_with_an_extends_tag + : Diagnostics.Generic_type_0_requires_between_1_and_2_type_arguments; + + const typeStr = typeToString( + type, + /*enclosingDeclaration*/ undefined, + TypeFormatFlags.WriteArrayAsGenericType, + ); error(node, diag, typeStr, minTypeArgumentCount, typeParameters.length); if (!isJs) { // TODO: Adopt same permissive behavior in TS as in JS to reduce follow-on editing experience failures (requires editing fillMissingTypeArguments) return errorType; } } - if (node.kind === SyntaxKind.TypeReference && isDeferredTypeReferenceNode(node as TypeReferenceNode, length(node.typeArguments) !== typeParameters.length)) { - return createDeferredTypeReference(type as GenericType, node as TypeReferenceNode, /*mapper*/ undefined); + if ( + node.kind === SyntaxKind.TypeReference + && isDeferredTypeReferenceNode( + node as TypeReferenceNode, + length(node.typeArguments) !== typeParameters.length, + ) + ) { + return createDeferredTypeReference( + type as GenericType, + node as TypeReferenceNode, + /*mapper*/ undefined, + ); } // In a type reference, the outer type parameters of the referenced class or interface are automatically // supplied as type arguments and the type reference only specifies arguments for the local type parameters // of the class or interface. - const typeArguments = concatenate(type.outerTypeParameters, fillMissingTypeArguments(typeArgumentsFromTypeReferenceNode(node), typeParameters, minTypeArgumentCount, isJs)); + const typeArguments = concatenate( + type.outerTypeParameters, + fillMissingTypeArguments( + typeArgumentsFromTypeReferenceNode(node), + typeParameters, + minTypeArgumentCount, + isJs, + ), + ); return createTypeReference(type as GenericType, typeArguments); } return checkNoTypeArguments(node, symbol) ? type : errorType; } - function getTypeAliasInstantiation(symbol: Symbol, typeArguments: readonly Type[] | undefined, aliasSymbol?: Symbol, aliasTypeArguments?: readonly Type[]): Type { + function getTypeAliasInstantiation( + symbol: Symbol, + typeArguments: readonly Type[] | undefined, + aliasSymbol?: Symbol, + aliasTypeArguments?: readonly Type[], + ): Type { const type = getDeclaredTypeOfSymbol(symbol); - if (type === intrinsicMarkerType && intrinsicTypeKinds.has(symbol.escapedName as string) && typeArguments && typeArguments.length === 1) { + if ( + type === intrinsicMarkerType && intrinsicTypeKinds.has(symbol.escapedName as string) && typeArguments + && typeArguments.length === 1 + ) { return getStringMappingType(symbol, typeArguments[0]); } const links = getSymbolLinks(symbol); @@ -15568,7 +19685,23 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const id = getTypeListId(typeArguments) + getAliasId(aliasSymbol, aliasTypeArguments); let instantiation = links.instantiations!.get(id); if (!instantiation) { - links.instantiations!.set(id, instantiation = instantiateTypeWithAlias(type, createTypeMapper(typeParameters, fillMissingTypeArguments(typeArguments, typeParameters, getMinTypeArgumentCount(typeParameters), isInJSFile(symbol.valueDeclaration))), aliasSymbol, aliasTypeArguments)); + links.instantiations!.set( + id, + instantiation = instantiateTypeWithAlias( + type, + createTypeMapper( + typeParameters, + fillMissingTypeArguments( + typeArguments, + typeParameters, + getMinTypeArgumentCount(typeParameters), + isInJSFile(symbol.valueDeclaration), + ), + ), + aliasSymbol, + aliasTypeArguments, + ), + ); } return instantiation; } @@ -15599,9 +19732,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (numTypeArguments < minTypeArgumentCount || numTypeArguments > typeParameters.length) { error( node, - minTypeArgumentCount === typeParameters.length ? - Diagnostics.Generic_type_0_requires_1_type_argument_s : - Diagnostics.Generic_type_0_requires_between_1_and_2_type_arguments, + minTypeArgumentCount === typeParameters.length + ? Diagnostics.Generic_type_0_requires_1_type_argument_s + : Diagnostics.Generic_type_0_requires_between_1_and_2_type_arguments, symbolToString(symbol), minTypeArgumentCount, typeParameters.length, @@ -15613,7 +19746,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // accessible--which in turn may lead to a large structural expansion of the type when generating // a .d.ts file. See #43622 for an example. const aliasSymbol = getAliasSymbolForTypeNode(node); - let newAliasSymbol = aliasSymbol && (isLocalTypeAlias(symbol) || !isLocalTypeAlias(aliasSymbol)) ? aliasSymbol : undefined; + let newAliasSymbol = aliasSymbol && (isLocalTypeAlias(symbol) || !isLocalTypeAlias(aliasSymbol)) + ? aliasSymbol : undefined; let aliasTypeArguments: Type[] | undefined; if (newAliasSymbol) { aliasTypeArguments = getTypeArgumentsForAliasSymbol(newAliasSymbol); @@ -15626,11 +19760,17 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const resolved = resolveAlias(aliasSymbol); if (resolved && resolved.flags & SymbolFlags.TypeAlias) { newAliasSymbol = resolved; - aliasTypeArguments = typeArgumentsFromTypeReferenceNode(node) || (typeParameters ? [] : undefined); + aliasTypeArguments = typeArgumentsFromTypeReferenceNode(node) + || (typeParameters ? [] : undefined); } } } - return getTypeAliasInstantiation(symbol, typeArgumentsFromTypeReferenceNode(node), newAliasSymbol, aliasTypeArguments); + return getTypeAliasInstantiation( + symbol, + typeArgumentsFromTypeReferenceNode(node), + newAliasSymbol, + aliasTypeArguments, + ); } return checkNoTypeArguments(node, symbol) ? type : errorType; } @@ -15662,14 +19802,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function getUnresolvedSymbolForEntityName(name: EntityNameOrEntityNameExpression) { - const identifier = name.kind === SyntaxKind.QualifiedName ? name.right : - name.kind === SyntaxKind.PropertyAccessExpression ? name.name : - name; + const identifier = name.kind === SyntaxKind.QualifiedName ? name.right + : name.kind === SyntaxKind.PropertyAccessExpression ? name.name + : name; const text = identifier.escapedText; if (text) { - const parentSymbol = name.kind === SyntaxKind.QualifiedName ? getUnresolvedSymbolForEntityName(name.left) : - name.kind === SyntaxKind.PropertyAccessExpression ? getUnresolvedSymbolForEntityName(name.expression) : - undefined; + const parentSymbol = name.kind === SyntaxKind.QualifiedName ? getUnresolvedSymbolForEntityName(name.left) + : name.kind === SyntaxKind.PropertyAccessExpression ? getUnresolvedSymbolForEntityName(name.expression) + : undefined; const path = parentSymbol ? `${getSymbolPath(parentSymbol)}.${text}` : text as string; let result = unresolvedSymbols.get(path); if (!result) { @@ -15688,8 +19828,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return unknownSymbol; } const symbol = resolveEntityName(name, meaning, ignoreErrors); - return symbol && symbol !== unknownSymbol ? symbol : - ignoreErrors ? unknownSymbol : getUnresolvedSymbolForEntityName(name); + return symbol && symbol !== unknownSymbol ? symbol + : ignoreErrors ? unknownSymbol : getUnresolvedSymbolForEntityName(name); } function getTypeReferenceType(node: NodeWithTypeArguments, symbol: Symbol): Type { @@ -15732,7 +19872,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const valueType = getTypeOfSymbol(symbol); let typeType = valueType; if (symbol.valueDeclaration) { - const isImportTypeWithQualifier = node.kind === SyntaxKind.ImportType && (node as ImportTypeNode).qualifier; + const isImportTypeWithQualifier = node.kind === SyntaxKind.ImportType + && (node as ImportTypeNode).qualifier; // valueType might not have a symbol, eg, {import('./b').STRING_LITERAL} if (valueType.symbol && valueType.symbol !== symbol && isImportTypeWithQualifier) { typeType = getTypeReferenceType(node, valueType.symbol); @@ -15768,9 +19909,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function getImpliedConstraint(type: Type, checkNode: TypeNode, extendsNode: TypeNode): Type | undefined { - return isUnaryTupleTypeNode(checkNode) && isUnaryTupleTypeNode(extendsNode) ? getImpliedConstraint(type, (checkNode as TupleTypeNode).elements[0], (extendsNode as TupleTypeNode).elements[0]) : - getActualTypeVariable(getTypeFromTypeNode(checkNode)) === getActualTypeVariable(type) ? getTypeFromTypeNode(extendsNode) : - undefined; + return isUnaryTupleTypeNode(checkNode) && isUnaryTupleTypeNode(extendsNode) + ? getImpliedConstraint( + type, + (checkNode as TupleTypeNode).elements[0], + (extendsNode as TupleTypeNode).elements[0], + ) + : getActualTypeVariable(getTypeFromTypeNode(checkNode)) === getActualTypeVariable(type) + ? getTypeFromTypeNode(extendsNode) + : undefined; } function getConditionalFlowTypeOfType(type: Type, node: Node) { @@ -15785,15 +19932,25 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } // Always substitute on type parameters, regardless of variance, since even // in contravariant positions, they may rely on substituted constraints to be valid - if ((covariant || type.flags & TypeFlags.TypeVariable) && parent.kind === SyntaxKind.ConditionalType && node === (parent as ConditionalTypeNode).trueType) { - const constraint = getImpliedConstraint(type, (parent as ConditionalTypeNode).checkType, (parent as ConditionalTypeNode).extendsType); + if ( + (covariant || type.flags & TypeFlags.TypeVariable) && parent.kind === SyntaxKind.ConditionalType + && node === (parent as ConditionalTypeNode).trueType + ) { + const constraint = getImpliedConstraint( + type, + (parent as ConditionalTypeNode).checkType, + (parent as ConditionalTypeNode).extendsType, + ); if (constraint) { constraints = append(constraints, constraint); } } // Given a homomorphic mapped type { [K in keyof T]: XXX }, where T is constrained to an array or tuple type, in the // template type XXX, K has an added constraint of number | `${number}`. - else if (type.flags & TypeFlags.TypeParameter && parent.kind === SyntaxKind.MappedType && node === (parent as MappedTypeNode).type) { + else if ( + type.flags & TypeFlags.TypeParameter && parent.kind === SyntaxKind.MappedType + && node === (parent as MappedTypeNode).type + ) { const mappedType = getTypeFromTypeNode(parent as TypeNode) as MappedType; if (getTypeParameterFromMappedType(mappedType) === getActualTypeVariable(type)) { const typeParameter = getHomomorphicTypeVariable(mappedType); @@ -15811,12 +19968,19 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function isJSDocTypeReference(node: Node): node is TypeReferenceNode { - return !!(node.flags & NodeFlags.JSDoc) && (node.kind === SyntaxKind.TypeReference || node.kind === SyntaxKind.ImportType); + return !!(node.flags & NodeFlags.JSDoc) + && (node.kind === SyntaxKind.TypeReference || node.kind === SyntaxKind.ImportType); } function checkNoTypeArguments(node: NodeWithTypeArguments, symbol?: Symbol) { if (node.typeArguments) { - error(node, Diagnostics.Type_0_is_not_generic, symbol ? symbolToString(symbol) : (node as TypeReferenceNode).typeName ? declarationNameToString((node as TypeReferenceNode).typeName) : anon); + error( + node, + Diagnostics.Type_0_is_not_generic, + symbol ? symbolToString(symbol) + : (node as TypeReferenceNode).typeName + ? declarationNameToString((node as TypeReferenceNode).typeName) : anon, + ); return false; } return true; @@ -15857,8 +20021,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (isJSDocIndexSignature(node)) { const indexed = getTypeFromTypeNode(typeArgs[0]); const target = getTypeFromTypeNode(typeArgs[1]); - const indexInfo = indexed === stringType || indexed === numberType ? [createIndexInfo(indexed, target, /*isReadonly*/ false)] : emptyArray; - return createAnonymousType(/*symbol*/ undefined, emptySymbols, emptyArray, emptyArray, indexInfo); + const indexInfo = indexed === stringType || indexed === numberType + ? [createIndexInfo(indexed, target, /*isReadonly*/ false)] : emptyArray; + return createAnonymousType( + /*symbol*/ undefined, + emptySymbols, + emptyArray, + emptyArray, + indexInfo, + ); } return anyType; } @@ -15946,26 +20117,47 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } const type = getDeclaredTypeOfSymbol(symbol); if (!(type.flags & TypeFlags.Object)) { - error(getTypeDeclaration(symbol), Diagnostics.Global_type_0_must_be_a_class_or_interface_type, symbolName(symbol)); + error( + getTypeDeclaration(symbol), + Diagnostics.Global_type_0_must_be_a_class_or_interface_type, + symbolName(symbol), + ); return arity ? emptyGenericType : emptyObjectType; } if (length((type as InterfaceType).typeParameters) !== arity) { - error(getTypeDeclaration(symbol), Diagnostics.Global_type_0_must_have_1_type_parameter_s, symbolName(symbol), arity); + error( + getTypeDeclaration(symbol), + Diagnostics.Global_type_0_must_have_1_type_parameter_s, + symbolName(symbol), + arity, + ); return arity ? emptyGenericType : emptyObjectType; } return type as ObjectType; } function getGlobalValueSymbol(name: __String, reportErrors: boolean): Symbol | undefined { - return getGlobalSymbol(name, SymbolFlags.Value, reportErrors ? Diagnostics.Cannot_find_global_value_0 : undefined); + return getGlobalSymbol( + name, + SymbolFlags.Value, + reportErrors ? Diagnostics.Cannot_find_global_value_0 : undefined, + ); } function getGlobalTypeSymbol(name: __String, reportErrors: boolean): Symbol | undefined { - return getGlobalSymbol(name, SymbolFlags.Type, reportErrors ? Diagnostics.Cannot_find_global_type_0 : undefined); + return getGlobalSymbol( + name, + SymbolFlags.Type, + reportErrors ? Diagnostics.Cannot_find_global_type_0 : undefined, + ); } function getGlobalTypeAliasSymbol(name: __String, arity: number, reportErrors: boolean): Symbol | undefined { - const symbol = getGlobalSymbol(name, SymbolFlags.Type, reportErrors ? Diagnostics.Cannot_find_global_type_0 : undefined); + const symbol = getGlobalSymbol( + name, + SymbolFlags.Type, + reportErrors ? Diagnostics.Cannot_find_global_type_0 : undefined, + ); if (symbol) { // Resolve the declared type of the symbol. This resolves type parameters for the type // alias so that we can check arity. @@ -15979,9 +20171,22 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return symbol; } - function getGlobalSymbol(name: __String, meaning: SymbolFlags, diagnostic: DiagnosticMessage | undefined): Symbol | undefined { + function getGlobalSymbol( + name: __String, + meaning: SymbolFlags, + diagnostic: DiagnosticMessage | undefined, + ): Symbol | undefined { // Don't track references for global symbols anyway, so value if `isReference` is arbitrary - return resolveName(/*location*/ undefined, name, meaning, diagnostic, name, /*isUse*/ false, /*excludeGlobals*/ false, /*getSpellingSuggestions*/ false); + return resolveName( + /*location*/ undefined, + name, + meaning, + diagnostic, + name, + /*isUse*/ false, + /*excludeGlobals*/ false, + /*getSpellingSuggestions*/ false, + ); } function getGlobalType(name: __String, arity: 0, reportErrors: true): ObjectType; @@ -15995,17 +20200,21 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function getGlobalTypedPropertyDescriptorType() { // We always report an error, so store a result in the event we could not resolve the symbol to prevent reporting it multiple times - return deferredGlobalTypedPropertyDescriptorType ||= getGlobalType("TypedPropertyDescriptor" as __String, /*arity*/ 1, /*reportErrors*/ true) || emptyGenericType; + return deferredGlobalTypedPropertyDescriptorType ||= + getGlobalType("TypedPropertyDescriptor" as __String, /*arity*/ 1, /*reportErrors*/ true) + || emptyGenericType; } function getGlobalTemplateStringsArrayType() { // We always report an error, so store a result in the event we could not resolve the symbol to prevent reporting it multiple times - return deferredGlobalTemplateStringsArrayType ||= getGlobalType("TemplateStringsArray" as __String, /*arity*/ 0, /*reportErrors*/ true) || emptyObjectType; + return deferredGlobalTemplateStringsArrayType ||= + getGlobalType("TemplateStringsArray" as __String, /*arity*/ 0, /*reportErrors*/ true) || emptyObjectType; } function getGlobalImportMetaType() { // We always report an error, so store a result in the event we could not resolve the symbol to prevent reporting it multiple times - return deferredGlobalImportMetaType ||= getGlobalType("ImportMeta" as __String, /*arity*/ 0, /*reportErrors*/ true) || emptyObjectType; + return deferredGlobalImportMetaType ||= + getGlobalType("ImportMeta" as __String, /*arity*/ 0, /*reportErrors*/ true) || emptyObjectType; } function getGlobalImportMetaExpressionType() { @@ -16021,13 +20230,23 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const members = createSymbolTable([metaPropertySymbol]); symbol.members = members; - deferredGlobalImportMetaExpressionType = createAnonymousType(symbol, members, emptyArray, emptyArray, emptyArray); + deferredGlobalImportMetaExpressionType = createAnonymousType( + symbol, + members, + emptyArray, + emptyArray, + emptyArray, + ); } return deferredGlobalImportMetaExpressionType; } function getGlobalImportCallOptionsType(reportErrors: boolean) { - return (deferredGlobalImportCallOptionsType ||= getGlobalType("ImportCallOptions" as __String, /*arity*/ 0, reportErrors)) || emptyObjectType; + return (deferredGlobalImportCallOptionsType ||= getGlobalType( + "ImportCallOptions" as __String, + /*arity*/ 0, + reportErrors, + )) || emptyObjectType; } function getGlobalESSymbolConstructorSymbol(reportErrors: boolean): Symbol | undefined { @@ -16035,19 +20254,25 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function getGlobalESSymbolConstructorTypeSymbol(reportErrors: boolean): Symbol | undefined { - return deferredGlobalESSymbolConstructorTypeSymbol ||= getGlobalTypeSymbol("SymbolConstructor" as __String, reportErrors); + return deferredGlobalESSymbolConstructorTypeSymbol ||= getGlobalTypeSymbol( + "SymbolConstructor" as __String, + reportErrors, + ); } function getGlobalESSymbolType() { - return (deferredGlobalESSymbolType ||= getGlobalType("Symbol" as __String, /*arity*/ 0, /*reportErrors*/ false)) || emptyObjectType; + return (deferredGlobalESSymbolType ||= getGlobalType("Symbol" as __String, /*arity*/ 0, /*reportErrors*/ false)) + || emptyObjectType; } function getGlobalPromiseType(reportErrors: boolean) { - return (deferredGlobalPromiseType ||= getGlobalType("Promise" as __String, /*arity*/ 1, reportErrors)) || emptyGenericType; + return (deferredGlobalPromiseType ||= getGlobalType("Promise" as __String, /*arity*/ 1, reportErrors)) + || emptyGenericType; } function getGlobalPromiseLikeType(reportErrors: boolean) { - return (deferredGlobalPromiseLikeType ||= getGlobalType("PromiseLike" as __String, /*arity*/ 1, reportErrors)) || emptyGenericType; + return (deferredGlobalPromiseLikeType ||= getGlobalType("PromiseLike" as __String, /*arity*/ 1, reportErrors)) + || emptyGenericType; } function getGlobalPromiseConstructorSymbol(reportErrors: boolean): Symbol | undefined { @@ -16055,55 +20280,95 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function getGlobalPromiseConstructorLikeType(reportErrors: boolean) { - return (deferredGlobalPromiseConstructorLikeType ||= getGlobalType("PromiseConstructorLike" as __String, /*arity*/ 0, reportErrors)) || emptyObjectType; + return (deferredGlobalPromiseConstructorLikeType ||= getGlobalType( + "PromiseConstructorLike" as __String, + /*arity*/ 0, + reportErrors, + )) || emptyObjectType; } function getGlobalAsyncIterableType(reportErrors: boolean) { - return (deferredGlobalAsyncIterableType ||= getGlobalType("AsyncIterable" as __String, /*arity*/ 1, reportErrors)) || emptyGenericType; + return (deferredGlobalAsyncIterableType ||= getGlobalType( + "AsyncIterable" as __String, + /*arity*/ 1, + reportErrors, + )) || emptyGenericType; } function getGlobalAsyncIteratorType(reportErrors: boolean) { - return (deferredGlobalAsyncIteratorType ||= getGlobalType("AsyncIterator" as __String, /*arity*/ 3, reportErrors)) || emptyGenericType; + return (deferredGlobalAsyncIteratorType ||= getGlobalType( + "AsyncIterator" as __String, + /*arity*/ 3, + reportErrors, + )) || emptyGenericType; } function getGlobalAsyncIterableIteratorType(reportErrors: boolean) { - return (deferredGlobalAsyncIterableIteratorType ||= getGlobalType("AsyncIterableIterator" as __String, /*arity*/ 1, reportErrors)) || emptyGenericType; + return (deferredGlobalAsyncIterableIteratorType ||= getGlobalType( + "AsyncIterableIterator" as __String, + /*arity*/ 1, + reportErrors, + )) || emptyGenericType; } function getGlobalAsyncGeneratorType(reportErrors: boolean) { - return (deferredGlobalAsyncGeneratorType ||= getGlobalType("AsyncGenerator" as __String, /*arity*/ 3, reportErrors)) || emptyGenericType; + return (deferredGlobalAsyncGeneratorType ||= getGlobalType( + "AsyncGenerator" as __String, + /*arity*/ 3, + reportErrors, + )) || emptyGenericType; } function getGlobalIterableType(reportErrors: boolean) { - return (deferredGlobalIterableType ||= getGlobalType("Iterable" as __String, /*arity*/ 1, reportErrors)) || emptyGenericType; + return (deferredGlobalIterableType ||= getGlobalType("Iterable" as __String, /*arity*/ 1, reportErrors)) + || emptyGenericType; } function getGlobalIteratorType(reportErrors: boolean) { - return (deferredGlobalIteratorType ||= getGlobalType("Iterator" as __String, /*arity*/ 3, reportErrors)) || emptyGenericType; + return (deferredGlobalIteratorType ||= getGlobalType("Iterator" as __String, /*arity*/ 3, reportErrors)) + || emptyGenericType; } function getGlobalIterableIteratorType(reportErrors: boolean) { - return (deferredGlobalIterableIteratorType ||= getGlobalType("IterableIterator" as __String, /*arity*/ 1, reportErrors)) || emptyGenericType; + return (deferredGlobalIterableIteratorType ||= getGlobalType( + "IterableIterator" as __String, + /*arity*/ 1, + reportErrors, + )) || emptyGenericType; } function getGlobalGeneratorType(reportErrors: boolean) { - return (deferredGlobalGeneratorType ||= getGlobalType("Generator" as __String, /*arity*/ 3, reportErrors)) || emptyGenericType; + return (deferredGlobalGeneratorType ||= getGlobalType("Generator" as __String, /*arity*/ 3, reportErrors)) + || emptyGenericType; } function getGlobalIteratorYieldResultType(reportErrors: boolean) { - return (deferredGlobalIteratorYieldResultType ||= getGlobalType("IteratorYieldResult" as __String, /*arity*/ 1, reportErrors)) || emptyGenericType; + return (deferredGlobalIteratorYieldResultType ||= getGlobalType( + "IteratorYieldResult" as __String, + /*arity*/ 1, + reportErrors, + )) || emptyGenericType; } function getGlobalIteratorReturnResultType(reportErrors: boolean) { - return (deferredGlobalIteratorReturnResultType ||= getGlobalType("IteratorReturnResult" as __String, /*arity*/ 1, reportErrors)) || emptyGenericType; + return (deferredGlobalIteratorReturnResultType ||= getGlobalType( + "IteratorReturnResult" as __String, + /*arity*/ 1, + reportErrors, + )) || emptyGenericType; } function getGlobalDisposableType(reportErrors: boolean) { - return (deferredGlobalDisposableType ||= getGlobalType("Disposable" as __String, /*arity*/ 0, reportErrors)) || emptyObjectType; + return (deferredGlobalDisposableType ||= getGlobalType("Disposable" as __String, /*arity*/ 0, reportErrors)) + || emptyObjectType; } function getGlobalAsyncDisposableType(reportErrors: boolean) { - return (deferredGlobalAsyncDisposableType ||= getGlobalType("AsyncDisposable" as __String, /*arity*/ 0, reportErrors)) || emptyObjectType; + return (deferredGlobalAsyncDisposableType ||= getGlobalType( + "AsyncDisposable" as __String, + /*arity*/ 0, + reportErrors, + )) || emptyObjectType; } function getGlobalTypeOrUndefined(name: __String, arity = 0): ObjectType | undefined { @@ -16113,56 +20378,92 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function getGlobalExtractSymbol(): Symbol | undefined { // We always report an error, so cache a result in the event we could not resolve the symbol to prevent reporting it multiple times - deferredGlobalExtractSymbol ||= getGlobalTypeAliasSymbol("Extract" as __String, /*arity*/ 2, /*reportErrors*/ true) || unknownSymbol; + deferredGlobalExtractSymbol ||= + getGlobalTypeAliasSymbol("Extract" as __String, /*arity*/ 2, /*reportErrors*/ true) || unknownSymbol; return deferredGlobalExtractSymbol === unknownSymbol ? undefined : deferredGlobalExtractSymbol; } function getGlobalOmitSymbol(): Symbol | undefined { // We always report an error, so cache a result in the event we could not resolve the symbol to prevent reporting it multiple times - deferredGlobalOmitSymbol ||= getGlobalTypeAliasSymbol("Omit" as __String, /*arity*/ 2, /*reportErrors*/ true) || unknownSymbol; + deferredGlobalOmitSymbol ||= getGlobalTypeAliasSymbol("Omit" as __String, /*arity*/ 2, /*reportErrors*/ true) + || unknownSymbol; return deferredGlobalOmitSymbol === unknownSymbol ? undefined : deferredGlobalOmitSymbol; } function getGlobalAwaitedSymbol(reportErrors: boolean): Symbol | undefined { // Only cache `unknownSymbol` if we are reporting errors so that we don't report the error more than once. - deferredGlobalAwaitedSymbol ||= getGlobalTypeAliasSymbol("Awaited" as __String, /*arity*/ 1, reportErrors) || (reportErrors ? unknownSymbol : undefined); + deferredGlobalAwaitedSymbol ||= getGlobalTypeAliasSymbol("Awaited" as __String, /*arity*/ 1, reportErrors) + || (reportErrors ? unknownSymbol : undefined); return deferredGlobalAwaitedSymbol === unknownSymbol ? undefined : deferredGlobalAwaitedSymbol; } function getGlobalBigIntType() { - return (deferredGlobalBigIntType ||= getGlobalType("BigInt" as __String, /*arity*/ 0, /*reportErrors*/ false)) || emptyObjectType; + return (deferredGlobalBigIntType ||= getGlobalType("BigInt" as __String, /*arity*/ 0, /*reportErrors*/ false)) + || emptyObjectType; } function getGlobalClassDecoratorContextType(reportErrors: boolean) { - return (deferredGlobalClassDecoratorContextType ??= getGlobalType("ClassDecoratorContext" as __String, /*arity*/ 1, reportErrors)) ?? emptyGenericType; + return (deferredGlobalClassDecoratorContextType ??= getGlobalType( + "ClassDecoratorContext" as __String, + /*arity*/ 1, + reportErrors, + )) ?? emptyGenericType; } function getGlobalClassMethodDecoratorContextType(reportErrors: boolean) { - return (deferredGlobalClassMethodDecoratorContextType ??= getGlobalType("ClassMethodDecoratorContext" as __String, /*arity*/ 2, reportErrors)) ?? emptyGenericType; + return (deferredGlobalClassMethodDecoratorContextType ??= getGlobalType( + "ClassMethodDecoratorContext" as __String, + /*arity*/ 2, + reportErrors, + )) ?? emptyGenericType; } function getGlobalClassGetterDecoratorContextType(reportErrors: boolean) { - return (deferredGlobalClassGetterDecoratorContextType ??= getGlobalType("ClassGetterDecoratorContext" as __String, /*arity*/ 2, reportErrors)) ?? emptyGenericType; + return (deferredGlobalClassGetterDecoratorContextType ??= getGlobalType( + "ClassGetterDecoratorContext" as __String, + /*arity*/ 2, + reportErrors, + )) ?? emptyGenericType; } function getGlobalClassSetterDecoratorContextType(reportErrors: boolean) { - return (deferredGlobalClassSetterDecoratorContextType ??= getGlobalType("ClassSetterDecoratorContext" as __String, /*arity*/ 2, reportErrors)) ?? emptyGenericType; + return (deferredGlobalClassSetterDecoratorContextType ??= getGlobalType( + "ClassSetterDecoratorContext" as __String, + /*arity*/ 2, + reportErrors, + )) ?? emptyGenericType; } function getGlobalClassAccessorDecoratorContextType(reportErrors: boolean) { - return (deferredGlobalClassAccessorDecoratorContextType ??= getGlobalType("ClassAccessorDecoratorContext" as __String, /*arity*/ 2, reportErrors)) ?? emptyGenericType; + return (deferredGlobalClassAccessorDecoratorContextType ??= getGlobalType( + "ClassAccessorDecoratorContext" as __String, + /*arity*/ 2, + reportErrors, + )) ?? emptyGenericType; } function getGlobalClassAccessorDecoratorTargetType(reportErrors: boolean) { - return (deferredGlobalClassAccessorDecoratorTargetType ??= getGlobalType("ClassAccessorDecoratorTarget" as __String, /*arity*/ 2, reportErrors)) ?? emptyGenericType; + return (deferredGlobalClassAccessorDecoratorTargetType ??= getGlobalType( + "ClassAccessorDecoratorTarget" as __String, + /*arity*/ 2, + reportErrors, + )) ?? emptyGenericType; } function getGlobalClassAccessorDecoratorResultType(reportErrors: boolean) { - return (deferredGlobalClassAccessorDecoratorResultType ??= getGlobalType("ClassAccessorDecoratorResult" as __String, /*arity*/ 2, reportErrors)) ?? emptyGenericType; + return (deferredGlobalClassAccessorDecoratorResultType ??= getGlobalType( + "ClassAccessorDecoratorResult" as __String, + /*arity*/ 2, + reportErrors, + )) ?? emptyGenericType; } function getGlobalClassFieldDecoratorContextType(reportErrors: boolean) { - return (deferredGlobalClassFieldDecoratorContextType ??= getGlobalType("ClassFieldDecoratorContext" as __String, /*arity*/ 2, reportErrors)) ?? emptyGenericType; + return (deferredGlobalClassFieldDecoratorContextType ??= getGlobalType( + "ClassFieldDecoratorContext" as __String, + /*arity*/ 2, + reportErrors, + )) ?? emptyGenericType; } function getGlobalNaNSymbol(): Symbol | undefined { @@ -16170,15 +20471,20 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function getGlobalRecordSymbol(): Symbol | undefined { - deferredGlobalRecordSymbol ||= getGlobalTypeAliasSymbol("Record" as __String, /*arity*/ 2, /*reportErrors*/ true) || unknownSymbol; + deferredGlobalRecordSymbol ||= + getGlobalTypeAliasSymbol("Record" as __String, /*arity*/ 2, /*reportErrors*/ true) || unknownSymbol; return deferredGlobalRecordSymbol === unknownSymbol ? undefined : deferredGlobalRecordSymbol; } /** * Instantiates a global type that is generic with some element type, and returns that instantiation. */ - function createTypeFromGenericGlobalType(genericGlobalType: GenericType, typeArguments: readonly Type[]): ObjectType { - return genericGlobalType !== emptyGenericType ? createTypeReference(genericGlobalType, typeArguments) : emptyObjectType; + function createTypeFromGenericGlobalType( + genericGlobalType: GenericType, + typeArguments: readonly Type[], + ): ObjectType { + return genericGlobalType !== emptyGenericType ? createTypeReference(genericGlobalType, typeArguments) + : emptyObjectType; } function createTypedPropertyDescriptorType(propertyType: Type): Type { @@ -16200,9 +20506,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { case SyntaxKind.RestType: return getRestTypeElementFlags(node as RestTypeNode); case SyntaxKind.NamedTupleMember: - return (node as NamedTupleMember).questionToken ? ElementFlags.Optional : - (node as NamedTupleMember).dotDotDotToken ? getRestTypeElementFlags(node as NamedTupleMember) : - ElementFlags.Required; + return (node as NamedTupleMember).questionToken ? ElementFlags.Optional + : (node as NamedTupleMember).dotDotDotToken ? getRestTypeElementFlags(node as NamedTupleMember) + : ElementFlags.Required; default: return ElementFlags.Required; } @@ -16219,7 +20525,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return readonly ? globalReadonlyArrayType : globalArrayType; } const elementFlags = map((node as TupleTypeNode).elements, getTupleElementFlags); - return getTupleTargetType(elementFlags, readonly, map((node as TupleTypeNode).elements, memberIfLabeledElementDeclaration)); + return getTupleTargetType( + elementFlags, + readonly, + map((node as TupleTypeNode).elements, memberIfLabeledElementDeclaration), + ); } function memberIfLabeledElementDeclaration(member: Node): NamedTupleMember | ParameterDeclaration | undefined { @@ -16228,11 +20538,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // Return true if the given type reference node is directly aliased or if it needs to be deferred // because it is possibly contained in a circular chain of eagerly resolved types. - function isDeferredTypeReferenceNode(node: TypeReferenceNode | ArrayTypeNode | TupleTypeNode, hasDefaultTypeArguments?: boolean) { + function isDeferredTypeReferenceNode( + node: TypeReferenceNode | ArrayTypeNode | TupleTypeNode, + hasDefaultTypeArguments?: boolean, + ) { return !!getAliasSymbolForTypeNode(node) || isResolvedByTypeAlias(node) && ( - node.kind === SyntaxKind.ArrayType ? mayResolveTypeAlias(node.elementType) : - node.kind === SyntaxKind.TupleType ? some(node.elements, mayResolveTypeAlias) : - hasDefaultTypeArguments || some(node.typeArguments, mayResolveTypeAlias) + node.kind === SyntaxKind.ArrayType ? mayResolveTypeAlias(node.elementType) + : node.kind === SyntaxKind.TupleType ? some(node.elements, mayResolveTypeAlias) + : hasDefaultTypeArguments || some(node.typeArguments, mayResolveTypeAlias) ); } @@ -16264,11 +20577,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function mayResolveTypeAlias(node: Node): boolean { switch (node.kind) { case SyntaxKind.TypeReference: - return isJSDocTypeReference(node) || !!(resolveTypeReferenceName(node as TypeReferenceNode, SymbolFlags.Type).flags & SymbolFlags.TypeAlias); + return isJSDocTypeReference(node) + || !!(resolveTypeReferenceName(node as TypeReferenceNode, SymbolFlags.Type).flags + & SymbolFlags.TypeAlias); case SyntaxKind.TypeQuery: return true; case SyntaxKind.TypeOperator: - return (node as TypeOperatorNode).operator !== SyntaxKind.UniqueKeyword && mayResolveTypeAlias((node as TypeOperatorNode).type); + return (node as TypeOperatorNode).operator !== SyntaxKind.UniqueKeyword + && mayResolveTypeAlias((node as TypeOperatorNode).type); case SyntaxKind.ParenthesizedType: case SyntaxKind.OptionalType: case SyntaxKind.NamedTupleMember: @@ -16276,17 +20592,24 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { case SyntaxKind.JSDocNullableType: case SyntaxKind.JSDocNonNullableType: case SyntaxKind.JSDocTypeExpression: - return mayResolveTypeAlias((node as ParenthesizedTypeNode | OptionalTypeNode | JSDocTypeReferencingNode | NamedTupleMember).type); + return mayResolveTypeAlias( + (node as ParenthesizedTypeNode | OptionalTypeNode | JSDocTypeReferencingNode | NamedTupleMember) + .type, + ); case SyntaxKind.RestType: - return (node as RestTypeNode).type.kind !== SyntaxKind.ArrayType || mayResolveTypeAlias(((node as RestTypeNode).type as ArrayTypeNode).elementType); + return (node as RestTypeNode).type.kind !== SyntaxKind.ArrayType + || mayResolveTypeAlias(((node as RestTypeNode).type as ArrayTypeNode).elementType); case SyntaxKind.UnionType: case SyntaxKind.IntersectionType: return some((node as UnionOrIntersectionTypeNode).types, mayResolveTypeAlias); case SyntaxKind.IndexedAccessType: - return mayResolveTypeAlias((node as IndexedAccessTypeNode).objectType) || mayResolveTypeAlias((node as IndexedAccessTypeNode).indexType); + return mayResolveTypeAlias((node as IndexedAccessTypeNode).objectType) + || mayResolveTypeAlias((node as IndexedAccessTypeNode).indexType); case SyntaxKind.ConditionalType: - return mayResolveTypeAlias((node as ConditionalTypeNode).checkType) || mayResolveTypeAlias((node as ConditionalTypeNode).extendsType) || - mayResolveTypeAlias((node as ConditionalTypeNode).trueType) || mayResolveTypeAlias((node as ConditionalTypeNode).falseType); + return mayResolveTypeAlias((node as ConditionalTypeNode).checkType) + || mayResolveTypeAlias((node as ConditionalTypeNode).extendsType) + || mayResolveTypeAlias((node as ConditionalTypeNode).trueType) + || mayResolveTypeAlias((node as ConditionalTypeNode).falseType); } return false; } @@ -16298,12 +20621,17 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (target === emptyGenericType) { links.resolvedType = emptyObjectType; } - else if (!(node.kind === SyntaxKind.TupleType && some(node.elements, e => !!(getTupleElementFlags(e) & ElementFlags.Variadic))) && isDeferredTypeReferenceNode(node)) { - links.resolvedType = node.kind === SyntaxKind.TupleType && node.elements.length === 0 ? target : - createDeferredTypeReference(target, node, /*mapper*/ undefined); + else if ( + !(node.kind === SyntaxKind.TupleType + && some(node.elements, e => !!(getTupleElementFlags(e) & ElementFlags.Variadic))) + && isDeferredTypeReferenceNode(node) + ) { + links.resolvedType = node.kind === SyntaxKind.TupleType && node.elements.length === 0 ? target + : createDeferredTypeReference(target, node, /*mapper*/ undefined); } else { - const elementTypes = node.kind === SyntaxKind.ArrayType ? [getTypeFromTypeNode(node.elementType)] : map(node.elements, getTypeFromTypeNode); + const elementTypes = node.kind === SyntaxKind.ArrayType ? [getTypeFromTypeNode(node.elementType)] + : map(node.elements, getTypeFromTypeNode); links.resolvedType = createNormalizedTypeReference(target, elementTypes); } } @@ -16314,22 +20642,39 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return isTypeOperatorNode(node) && node.operator === SyntaxKind.ReadonlyKeyword; } - function createTupleType(elementTypes: readonly Type[], elementFlags?: readonly ElementFlags[], readonly = false, namedMemberDeclarations: readonly (NamedTupleMember | ParameterDeclaration | undefined)[] = []) { - const tupleTarget = getTupleTargetType(elementFlags || map(elementTypes, _ => ElementFlags.Required), readonly, namedMemberDeclarations); - return tupleTarget === emptyGenericType ? emptyObjectType : - elementTypes.length ? createNormalizedTypeReference(tupleTarget, elementTypes) : - tupleTarget; + function createTupleType( + elementTypes: readonly Type[], + elementFlags?: readonly ElementFlags[], + readonly = false, + namedMemberDeclarations: readonly (NamedTupleMember | ParameterDeclaration | undefined)[] = [], + ) { + const tupleTarget = getTupleTargetType( + elementFlags || map(elementTypes, _ => ElementFlags.Required), + readonly, + namedMemberDeclarations, + ); + return tupleTarget === emptyGenericType ? emptyObjectType + : elementTypes.length ? createNormalizedTypeReference(tupleTarget, elementTypes) + : tupleTarget; } - function getTupleTargetType(elementFlags: readonly ElementFlags[], readonly: boolean, namedMemberDeclarations: readonly (NamedTupleMember | ParameterDeclaration | undefined)[]): GenericType { + function getTupleTargetType( + elementFlags: readonly ElementFlags[], + readonly: boolean, + namedMemberDeclarations: readonly (NamedTupleMember | ParameterDeclaration | undefined)[], + ): GenericType { if (elementFlags.length === 1 && elementFlags[0] & ElementFlags.Rest) { // [...X[]] is equivalent to just X[] return readonly ? globalReadonlyArrayType : globalArrayType; } const memberIds = mapDefined(namedMemberDeclarations, node => node ? getNodeId(node) : undefined); - const key = map(elementFlags, f => f & ElementFlags.Required ? "#" : f & ElementFlags.Optional ? "?" : f & ElementFlags.Rest ? "." : "*").join() + - (readonly ? "R" : "") + - (memberIds.length ? "," + memberIds.join(",") : ""); + const key = map( + elementFlags, + f => f & ElementFlags.Required ? "#" + : f & ElementFlags.Optional ? "?" : f & ElementFlags.Rest ? "." : "*", + ).join() + + (readonly ? "R" : "") + + (memberIds.length ? "," + memberIds.join(",") : ""); let type = tupleTypes.get(key); if (!type) { tupleTypes.set(key, type = createTupleTargetType(elementFlags, readonly, namedMemberDeclarations)); @@ -16344,7 +20689,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // // Note that the generic type created by this function has no symbol associated with it. The same // is true for each of the synthesized type parameters. - function createTupleTargetType(elementFlags: readonly ElementFlags[], readonly: boolean, namedMemberDeclarations: readonly (NamedTupleMember | ParameterDeclaration | undefined)[]): TupleType { + function createTupleTargetType( + elementFlags: readonly ElementFlags[], + readonly: boolean, + namedMemberDeclarations: readonly (NamedTupleMember | ParameterDeclaration | undefined)[], + ): TupleType { const arity = elementFlags.length; const minLength = countWhere(elementFlags, f => !!(f & (ElementFlags.Required | ElementFlags.Variadic))); let typeParameters: TypeParameter[] | undefined; @@ -16357,7 +20706,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const flags = elementFlags[i]; combinedFlags |= flags; if (!(combinedFlags & ElementFlags.Variable)) { - const property = createSymbol(SymbolFlags.Property | (flags & ElementFlags.Optional ? SymbolFlags.Optional : 0), "" + i as __String, readonly ? CheckFlags.Readonly : 0); + const property = createSymbol( + SymbolFlags.Property | (flags & ElementFlags.Optional ? SymbolFlags.Optional : 0), + "" + i as __String, + readonly ? CheckFlags.Readonly : 0, + ); property.links.tupleLabelDeclaration = namedMemberDeclarations?.[i]; property.links.type = typeParameter; properties.push(property); @@ -16365,7 +20718,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } const fixedLength = properties.length; - const lengthSymbol = createSymbol(SymbolFlags.Property, "length" as __String, readonly ? CheckFlags.Readonly : 0); + const lengthSymbol = createSymbol( + SymbolFlags.Property, + "length" as __String, + readonly ? CheckFlags.Readonly : 0, + ); if (combinedFlags & ElementFlags.Variable) { lengthSymbol.links.type = numberType; } @@ -16375,7 +20732,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { lengthSymbol.links.type = getUnionType(literalTypes); } properties.push(lengthSymbol); - const type = createObjectType(ObjectFlags.Tuple | ObjectFlags.Reference) as TupleType & InterfaceTypeWithDeclaredMembers; + const type = createObjectType(ObjectFlags.Tuple | ObjectFlags.Reference) as + & TupleType + & InterfaceTypeWithDeclaredMembers; type.typeParameters = typeParameters; type.outerTypeParameters = undefined; type.localTypeParameters = typeParameters; @@ -16401,7 +20760,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function createNormalizedTypeReference(target: GenericType, typeArguments: readonly Type[] | undefined) { - return target.objectFlags & ObjectFlags.Tuple ? createNormalizedTupleType(target as TupleType, typeArguments!) : createTypeReference(target, typeArguments); + return target.objectFlags & ObjectFlags.Tuple ? createNormalizedTupleType(target as TupleType, typeArguments!) + : createTypeReference(target, typeArguments); } function createNormalizedTupleType(target: TupleType, elementTypes: readonly Type[]): Type { @@ -16411,11 +20771,20 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } if (target.combinedFlags & ElementFlags.Variadic) { // Transform [A, ...(X | Y | Z)] into [A, ...X] | [A, ...Y] | [A, ...Z] - const unionIndex = findIndex(elementTypes, (t, i) => !!(target.elementFlags[i] & ElementFlags.Variadic && t.flags & (TypeFlags.Never | TypeFlags.Union))); + const unionIndex = findIndex( + elementTypes, + (t, i) => + !!(target.elementFlags[i] & ElementFlags.Variadic && t.flags & (TypeFlags.Never | TypeFlags.Union)), + ); if (unionIndex >= 0) { - return checkCrossProductUnion(map(elementTypes, (t, i) => target.elementFlags[i] & ElementFlags.Variadic ? t : unknownType)) ? - mapType(elementTypes[unionIndex], t => createNormalizedTupleType(target, replaceElement(elementTypes, unionIndex, t))) : - errorType; + return checkCrossProductUnion( + map(elementTypes, (t, i) => target.elementFlags[i] & ElementFlags.Variadic ? t : unknownType), + ) + ? mapType( + elementTypes[unionIndex], + t => createNormalizedTupleType(target, replaceElement(elementTypes, unionIndex, t)), + ) + : errorType; } } // We have optional, rest, or variadic elements that may need normalizing. Normalization ensures that all variadic @@ -16449,11 +20818,19 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return errorType; } // Spread variadic elements with tuple types into the resulting tuple. - forEach(elements, (t, n) => addElement(t, type.target.elementFlags[n], type.target.labeledElementDeclarations?.[n])); + forEach( + elements, + (t, n) => + addElement(t, type.target.elementFlags[n], type.target.labeledElementDeclarations?.[n]), + ); } else { // Treat everything else as an array type and create a rest element. - addElement(isArrayLikeType(type) && getIndexTypeOfType(type, numberType) || errorType, ElementFlags.Rest, target.labeledElementDeclarations?.[i]); + addElement( + isArrayLikeType(type) && getIndexTypeOfType(type, numberType) || errorType, + ElementFlags.Rest, + target.labeledElementDeclarations?.[i], + ); } } else { @@ -16467,17 +20844,28 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } if (firstRestIndex >= 0 && firstRestIndex < lastOptionalOrRestIndex) { // Turn elements between first rest and last optional/rest into a single rest element - expandedTypes[firstRestIndex] = getUnionType(sameMap(expandedTypes.slice(firstRestIndex, lastOptionalOrRestIndex + 1), (t, i) => expandedFlags[firstRestIndex + i] & ElementFlags.Variadic ? getIndexedAccessType(t, numberType) : t)); + expandedTypes[firstRestIndex] = getUnionType( + sameMap( + expandedTypes.slice(firstRestIndex, lastOptionalOrRestIndex + 1), + (t, i) => + expandedFlags[firstRestIndex + i] & ElementFlags.Variadic ? getIndexedAccessType(t, numberType) + : t, + ), + ); expandedTypes.splice(firstRestIndex + 1, lastOptionalOrRestIndex - firstRestIndex); expandedFlags.splice(firstRestIndex + 1, lastOptionalOrRestIndex - firstRestIndex); expandedDeclarations.splice(firstRestIndex + 1, lastOptionalOrRestIndex - firstRestIndex); } const tupleTarget = getTupleTargetType(expandedFlags, target.readonly, expandedDeclarations); - return tupleTarget === emptyGenericType ? emptyObjectType : - expandedFlags.length ? createTypeReference(tupleTarget, expandedTypes) : - tupleTarget; - - function addElement(type: Type, flags: ElementFlags, declaration: NamedTupleMember | ParameterDeclaration | undefined) { + return tupleTarget === emptyGenericType ? emptyObjectType + : expandedFlags.length ? createTypeReference(tupleTarget, expandedTypes) + : tupleTarget; + + function addElement( + type: Type, + flags: ElementFlags, + declaration: NamedTupleMember | ParameterDeclaration | undefined, + ) { if (flags & ElementFlags.Required) { lastRequiredIndex = expandedFlags.length; } @@ -16496,12 +20884,22 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function sliceTupleType(type: TupleTypeReference, index: number, endSkipCount = 0) { const target = type.target; const endIndex = getTypeReferenceArity(type) - endSkipCount; - return index > target.fixedLength ? getRestArrayTypeOfTupleType(type) || createTupleType(emptyArray) : - createTupleType(getTypeArguments(type).slice(index, endIndex), target.elementFlags.slice(index, endIndex), /*readonly*/ false, target.labeledElementDeclarations && target.labeledElementDeclarations.slice(index, endIndex)); + return index > target.fixedLength ? getRestArrayTypeOfTupleType(type) || createTupleType(emptyArray) + : createTupleType( + getTypeArguments(type).slice(index, endIndex), + target.elementFlags.slice(index, endIndex), + /*readonly*/ false, + target.labeledElementDeclarations && target.labeledElementDeclarations.slice(index, endIndex), + ); } function getKnownKeysOfTupleType(type: TupleTypeReference) { - return getUnionType(append(arrayOf(type.target.fixedLength, i => getStringLiteralType("" + i)), getIndexType(type.target.readonly ? globalReadonlyArrayType : globalArrayType))); + return getUnionType( + append( + arrayOf(type.target.fixedLength, i => getStringLiteralType("" + i)), + getIndexType(type.target.readonly ? globalReadonlyArrayType : globalArrayType), + ), + ); } // Return count of starting consecutive tuple elements of the given kind(s) @@ -16554,11 +20952,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (flags & TypeFlags.Instantiable) includes |= TypeFlags.IncludesInstantiable; if (type === wildcardType) includes |= TypeFlags.IncludesWildcard; if (!strictNullChecks && flags & TypeFlags.Nullable) { - if (!(getObjectFlags(type) & ObjectFlags.ContainsWideningType)) includes |= TypeFlags.IncludesNonWideningType; + if (!(getObjectFlags(type) & ObjectFlags.ContainsWideningType)) { + includes |= TypeFlags.IncludesNonWideningType; + } } else { const len = typeSet.length; - const index = len && type.id > typeSet[len - 1].id ? ~len : binarySearch(typeSet, type, getTypeId, compareValues); + const index = len && type.id > typeSet[len - 1].id ? ~len + : binarySearch(typeSet, type, getTypeId, compareValues); if (index < 0) { typeSet.splice(~index, 0, type); } @@ -16576,9 +20977,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // saves a lot of work for large lists of the same union type, such as when resolving `Record[A]`, // where A and B are large union types. if (type !== lastType) { - includes = type.flags & TypeFlags.Union ? - addTypesToUnion(typeSet, includes | (isNamedUnionType(type) ? TypeFlags.Union : 0), (type as UnionType).types) : - addTypeToUnion(typeSet, includes, type); + includes = type.flags & TypeFlags.Union + ? addTypesToUnion( + typeSet, + includes | (isNamedUnionType(type) ? TypeFlags.Union : 0), + (type as UnionType).types, + ) + : addTypeToUnion(typeSet, includes, type); lastType = type; } } @@ -16600,7 +21005,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // We assume that redundant primitive types have already been removed from the types array and that there // are no any and unknown types in the array. Thus, the only possible supertypes for primitive types are empty // object types, and if none of those are present we can exclude primitive types from the subtype check. - const hasEmptyObject = hasObjectTypes && some(types, t => !!(t.flags & TypeFlags.Object) && !isGenericMappedType(t) && isEmptyResolvedType(resolveStructuredTypeMembers(t as ObjectType))); + const hasEmptyObject = hasObjectTypes + && some( + types, + t => !!(t.flags & TypeFlags.Object) && !isGenericMappedType(t) + && isEmptyResolvedType(resolveStructuredTypeMembers(t as ObjectType)), + ); const len = types.length; let i = len; let count = 0; @@ -16613,7 +21023,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // a subtype of just `A` or just `B`. When we encounter such a type parameter, we therefore check if the // type parameter is a subtype of a union of all the other types. if (source.flags & TypeFlags.TypeParameter && getBaseConstraintOrType(source).flags & TypeFlags.Union) { - if (isTypeRelatedTo(source, getUnionType(map(types, t => t === source ? neverType : t)), strictSubtypeRelation)) { + if ( + isTypeRelatedTo( + source, + getUnionType(map(types, t => t === source ? neverType : t)), + strictSubtypeRelation, + ) + ) { orderedRemoveItemAt(types, i); } continue; @@ -16621,9 +21037,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // Find the first property with a unit type, if any. When constituents have a property by the same name // but of a different unit type, we can quickly disqualify them from subtype checks. This helps subtype // reduction of large discriminated union types. - const keyProperty = source.flags & (TypeFlags.Object | TypeFlags.Intersection | TypeFlags.InstantiableNonPrimitive) ? - find(getPropertiesOfType(source), p => isUnitType(getTypeOfSymbol(p))) : - undefined; + const keyProperty = + source.flags & (TypeFlags.Object | TypeFlags.Intersection | TypeFlags.InstantiableNonPrimitive) + ? find(getPropertiesOfType(source), p => isUnitType(getTypeOfSymbol(p))) + : undefined; const keyPropertyType = keyProperty && getRegularTypeOfLiteralType(getTypeOfSymbol(keyProperty)); for (const target of types) { if (source !== target) { @@ -16634,13 +21051,22 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // caps union types at 1000 unique object types. const estimatedCount = (count / (len - i)) * len; if (estimatedCount > 1000000) { - tracing?.instant(tracing.Phase.CheckTypes, "removeSubtypes_DepthLimit", { typeIds: types.map(t => t.id) }); - error(currentNode, Diagnostics.Expression_produces_a_union_type_that_is_too_complex_to_represent); + tracing?.instant(tracing.Phase.CheckTypes, "removeSubtypes_DepthLimit", { + typeIds: types.map(t => t.id), + }); + error( + currentNode, + Diagnostics.Expression_produces_a_union_type_that_is_too_complex_to_represent, + ); return undefined; } } count++; - if (keyProperty && target.flags & (TypeFlags.Object | TypeFlags.Intersection | TypeFlags.InstantiableNonPrimitive)) { + if ( + keyProperty + && target.flags + & (TypeFlags.Object | TypeFlags.Intersection | TypeFlags.InstantiableNonPrimitive) + ) { const t = getTypeOfPropertyOfType(target, keyProperty.escapedName); if (t && isUnitType(t) && getRegularTypeOfLiteralType(t) !== keyPropertyType) { continue; @@ -16648,9 +21074,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } if ( isTypeRelatedTo(source, target, strictSubtypeRelation) && ( - !(getObjectFlags(getTargetType(source)) & ObjectFlags.Class) || - !(getObjectFlags(getTargetType(target)) & ObjectFlags.Class) || - isTypeDerivedFrom(source, target) + !(getObjectFlags(getTargetType(source)) & ObjectFlags.Class) + || !(getObjectFlags(getTargetType(target)) & ObjectFlags.Class) + || isTypeDerivedFrom(source, target) ) ) { orderedRemoveItemAt(types, i); @@ -16670,12 +21096,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { i--; const t = types[i]; const flags = t.flags; - const remove = flags & (TypeFlags.StringLiteral | TypeFlags.TemplateLiteral | TypeFlags.StringMapping) && includes & TypeFlags.String || - flags & TypeFlags.NumberLiteral && includes & TypeFlags.Number || - flags & TypeFlags.BigIntLiteral && includes & TypeFlags.BigInt || - flags & TypeFlags.UniqueESSymbol && includes & TypeFlags.ESSymbol || - reduceVoidUndefined && flags & TypeFlags.Undefined && includes & TypeFlags.Void || - isFreshLiteralType(t) && containsType(types, (t as LiteralType).regularType); + const remove = flags & (TypeFlags.StringLiteral | TypeFlags.TemplateLiteral | TypeFlags.StringMapping) + && includes & TypeFlags.String + || flags & TypeFlags.NumberLiteral && includes & TypeFlags.Number + || flags & TypeFlags.BigIntLiteral && includes & TypeFlags.BigInt + || flags & TypeFlags.UniqueESSymbol && includes & TypeFlags.ESSymbol + || reduceVoidUndefined && flags & TypeFlags.Undefined && includes & TypeFlags.Void + || isFreshLiteralType(t) && containsType(types, (t as LiteralType).regularType); if (remove) { orderedRemoveItemAt(types, i); } @@ -16684,15 +21111,21 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function removeStringLiteralsMatchedByTemplateLiterals(types: Type[]) { const templates = filter(types, t => - !!(t.flags & TypeFlags.TemplateLiteral) && - isPatternLiteralType(t) && - (t as TemplateLiteralType).types.every(t => !(t.flags & TypeFlags.Intersection) || !areIntersectedTypesAvoidingPrimitiveReduction((t as IntersectionType).types))) as TemplateLiteralType[]; + !!(t.flags & TypeFlags.TemplateLiteral) + && isPatternLiteralType(t) + && (t as TemplateLiteralType).types.every(t => + !(t.flags & TypeFlags.Intersection) + || !areIntersectedTypesAvoidingPrimitiveReduction((t as IntersectionType).types) + )) as TemplateLiteralType[]; if (templates.length) { let i = types.length; while (i > 0) { i--; const t = types[i]; - if (t.flags & TypeFlags.StringLiteral && some(templates, template => isTypeMatchedByTemplateLiteralType(t, template))) { + if ( + t.flags & TypeFlags.StringLiteral + && some(templates, template => isTypeMatchedByTemplateLiteralType(t, template)) + ) { orderedRemoveItemAt(types, i); } } @@ -16730,7 +21163,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // expression constructs such as array literals and the || and ?: operators). Named types can // circularly reference themselves and therefore cannot be subtype reduced during their declaration. // For example, "type Item = string | (() => Item" is a named type that circularly references itself. - function getUnionType(types: readonly Type[], unionReduction: UnionReduction = UnionReduction.Literal, aliasSymbol?: Symbol, aliasTypeArguments?: readonly Type[], origin?: Type): Type { + function getUnionType( + types: readonly Type[], + unionReduction: UnionReduction = UnionReduction.Literal, + aliasSymbol?: Symbol, + aliasTypeArguments?: readonly Type[], + origin?: Type, + ): Type { if (types.length === 0) { return neverType; } @@ -16739,7 +21178,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } // We optimize for the common case of unioning a union type with some other type (such as `undefined`). if (types.length === 2 && !origin && (types[0].flags & TypeFlags.Union || types[1].flags & TypeFlags.Union)) { - const infix = unionReduction === UnionReduction.None ? "N" : unionReduction === UnionReduction.Subtype ? "S" : "L"; + const infix = unionReduction === UnionReduction.None ? "N" + : unionReduction === UnionReduction.Subtype ? "S" : "L"; const index = types[0].id < types[1].id ? 0 : 1; const id = types[index].id + infix + types[1 - index].id + getAliasId(aliasSymbol, aliasTypeArguments); let type = unionOfUnionTypes.get(id); @@ -16752,14 +21192,21 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return getUnionTypeWorker(types, unionReduction, aliasSymbol, aliasTypeArguments, origin); } - function getUnionTypeWorker(types: readonly Type[], unionReduction: UnionReduction, aliasSymbol: Symbol | undefined, aliasTypeArguments: readonly Type[] | undefined, origin: Type | undefined): Type { + function getUnionTypeWorker( + types: readonly Type[], + unionReduction: UnionReduction, + aliasSymbol: Symbol | undefined, + aliasTypeArguments: readonly Type[] | undefined, + origin: Type | undefined, + ): Type { let typeSet: Type[] | undefined = []; const includes = addTypesToUnion(typeSet, 0 as TypeFlags, types); if (unionReduction !== UnionReduction.None) { if (includes & TypeFlags.AnyOrUnknown) { - return includes & TypeFlags.Any ? - includes & TypeFlags.IncludesWildcard ? wildcardType : anyType : - includes & TypeFlags.Null || containsType(typeSet, unknownType) ? unknownType : nonNullUnknownType; + return includes & TypeFlags.Any + ? includes & TypeFlags.IncludesWildcard ? wildcardType : anyType + : includes & TypeFlags.Null || containsType(typeSet, unknownType) ? unknownType + : nonNullUnknownType; } if (includes & TypeFlags.Undefined) { // If type set contains both undefinedType and missingType, remove missingType @@ -16767,7 +21214,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { orderedRemoveItemAt(typeSet, 1); } } - if (includes & (TypeFlags.Enum | TypeFlags.Literal | TypeFlags.UniqueESSymbol | TypeFlags.TemplateLiteral | TypeFlags.StringMapping) || includes & TypeFlags.Void && includes & TypeFlags.Undefined) { + if ( + includes + & (TypeFlags.Enum | TypeFlags.Literal | TypeFlags.UniqueESSymbol | TypeFlags.TemplateLiteral + | TypeFlags.StringMapping) || includes & TypeFlags.Void && includes & TypeFlags.Undefined + ) { removeRedundantLiteralTypes(typeSet, includes, !!(unionReduction & UnionReduction.Subtype)); } if (includes & TypeFlags.StringLiteral && includes & TypeFlags.TemplateLiteral) { @@ -16780,9 +21231,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } if (typeSet.length === 0) { - return includes & TypeFlags.Null ? includes & TypeFlags.IncludesNonWideningType ? nullType : nullWideningType : - includes & TypeFlags.Undefined ? includes & TypeFlags.IncludesNonWideningType ? undefinedType : undefinedWideningType : - neverType; + return includes & TypeFlags.Null + ? includes & TypeFlags.IncludesNonWideningType ? nullType : nullWideningType + : includes & TypeFlags.Undefined + ? includes & TypeFlags.IncludesNonWideningType ? undefinedType : undefinedWideningType + : neverType; } } if (!origin && includes & TypeFlags.Union) { @@ -16807,19 +21260,25 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { origin = createOriginUnionOrIntersectionType(TypeFlags.Union, reducedTypes); } } - const objectFlags = (includes & TypeFlags.NotPrimitiveUnion ? 0 : ObjectFlags.PrimitiveUnion) | - (includes & TypeFlags.Intersection ? ObjectFlags.ContainsIntersections : 0); + const objectFlags = (includes & TypeFlags.NotPrimitiveUnion ? 0 : ObjectFlags.PrimitiveUnion) + | (includes & TypeFlags.Intersection ? ObjectFlags.ContainsIntersections : 0); return getUnionTypeFromSortedList(typeSet, objectFlags, aliasSymbol, aliasTypeArguments, origin); } - function getUnionOrIntersectionTypePredicate(signatures: readonly Signature[], kind: TypeFlags | undefined): TypePredicate | undefined { + function getUnionOrIntersectionTypePredicate( + signatures: readonly Signature[], + kind: TypeFlags | undefined, + ): TypePredicate | undefined { let last: TypePredicate | undefined; const types: Type[] = []; for (const sig of signatures) { const pred = getTypePredicateOfSignature(sig); if (pred) { // Constituent type predicates must all have matching kinds. We don't create composite type predicates for assertions. - if (pred.kind !== TypePredicateKind.This && pred.kind !== TypePredicateKind.Identifier || last && !typePredicateKindsMatch(last, pred)) { + if ( + pred.kind !== TypePredicateKind.This && pred.kind !== TypePredicateKind.Identifier + || last && !typePredicateKindsMatch(last, pred) + ) { return undefined; } last = pred; @@ -16845,27 +21304,37 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } // This function assumes the constituent type list is sorted and deduplicated. - function getUnionTypeFromSortedList(types: Type[], precomputedObjectFlags: ObjectFlags, aliasSymbol?: Symbol, aliasTypeArguments?: readonly Type[], origin?: Type): Type { + function getUnionTypeFromSortedList( + types: Type[], + precomputedObjectFlags: ObjectFlags, + aliasSymbol?: Symbol, + aliasTypeArguments?: readonly Type[], + origin?: Type, + ): Type { if (types.length === 0) { return neverType; } if (types.length === 1) { return types[0]; } - const typeKey = !origin ? getTypeListId(types) : - origin.flags & TypeFlags.Union ? `|${getTypeListId((origin as UnionType).types)}` : - origin.flags & TypeFlags.Intersection ? `&${getTypeListId((origin as IntersectionType).types)}` : - `#${(origin as IndexType).type.id}|${getTypeListId(types)}`; // origin type id alone is insufficient, as `keyof x` may resolve to multiple WIP values while `x` is still resolving + const typeKey = !origin ? getTypeListId(types) + : origin.flags & TypeFlags.Union ? `|${getTypeListId((origin as UnionType).types)}` + : origin.flags & TypeFlags.Intersection ? `&${getTypeListId((origin as IntersectionType).types)}` + : `#${(origin as IndexType).type.id}|${getTypeListId(types)}`; // origin type id alone is insufficient, as `keyof x` may resolve to multiple WIP values while `x` is still resolving const id = typeKey + getAliasId(aliasSymbol, aliasTypeArguments); let type = unionTypes.get(id); if (!type) { type = createType(TypeFlags.Union) as UnionType; - type.objectFlags = precomputedObjectFlags | getPropagatingFlagsOfTypes(types, /*excludeKinds*/ TypeFlags.Nullable); + type.objectFlags = precomputedObjectFlags + | getPropagatingFlagsOfTypes(types, /*excludeKinds*/ TypeFlags.Nullable); type.types = types; type.origin = origin; type.aliasSymbol = aliasSymbol; type.aliasTypeArguments = aliasTypeArguments; - if (types.length === 2 && types[0].flags & TypeFlags.BooleanLiteral && types[1].flags & TypeFlags.BooleanLiteral) { + if ( + types.length === 2 && types[0].flags & TypeFlags.BooleanLiteral + && types[1].flags & TypeFlags.BooleanLiteral + ) { type.flags |= TypeFlags.Boolean; (type as UnionType & IntrinsicType).intrinsicName = "boolean"; } @@ -16878,7 +21347,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const links = getNodeLinks(node); if (!links.resolvedType) { const aliasSymbol = getAliasSymbolForTypeNode(node); - links.resolvedType = getUnionType(map(node.types, getTypeFromTypeNode), UnionReduction.Literal, aliasSymbol, getTypeArgumentsForAliasSymbol(aliasSymbol)); + links.resolvedType = getUnionType( + map(node.types, getTypeFromTypeNode), + UnionReduction.Literal, + aliasSymbol, + getTypeArgumentsForAliasSymbol(aliasSymbol), + ); } return links.resolvedType; } @@ -16931,12 +21405,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { while (i > 0) { i--; const t = types[i]; - const remove = t.flags & TypeFlags.String && includes & (TypeFlags.StringLiteral | TypeFlags.TemplateLiteral | TypeFlags.StringMapping) || - t.flags & TypeFlags.Number && includes & TypeFlags.NumberLiteral || - t.flags & TypeFlags.BigInt && includes & TypeFlags.BigIntLiteral || - t.flags & TypeFlags.ESSymbol && includes & TypeFlags.UniqueESSymbol || - t.flags & TypeFlags.Void && includes & TypeFlags.Undefined || - isEmptyAnonymousObjectType(t) && includes & TypeFlags.DefinitelyNonNullable; + const remove = t.flags & TypeFlags.String + && includes & (TypeFlags.StringLiteral | TypeFlags.TemplateLiteral | TypeFlags.StringMapping) + || t.flags & TypeFlags.Number && includes & TypeFlags.NumberLiteral + || t.flags & TypeFlags.BigInt && includes & TypeFlags.BigIntLiteral + || t.flags & TypeFlags.ESSymbol && includes & TypeFlags.UniqueESSymbol + || t.flags & TypeFlags.Void && includes & TypeFlags.Undefined + || isEmptyAnonymousObjectType(t) && includes & TypeFlags.DefinitelyNonNullable; if (remove) { orderedRemoveItemAt(types, i); } @@ -16949,11 +21424,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function eachUnionContains(unionTypes: UnionType[], type: Type) { for (const u of unionTypes) { if (!containsType(u.types, type)) { - const primitive = type.flags & TypeFlags.StringLiteral ? stringType : - type.flags & (TypeFlags.Enum | TypeFlags.NumberLiteral) ? numberType : - type.flags & TypeFlags.BigIntLiteral ? bigintType : - type.flags & TypeFlags.UniqueESSymbol ? esSymbolType : - undefined; + const primitive = type.flags & TypeFlags.StringLiteral ? stringType + : type.flags & (TypeFlags.Enum | TypeFlags.NumberLiteral) ? numberType + : type.flags & TypeFlags.BigIntLiteral ? bigintType + : type.flags & TypeFlags.UniqueESSymbol ? esSymbolType + : undefined; if (!primitive || !containsType(u.types, primitive)) { return false; } @@ -17056,7 +21531,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // a type alias of the form "type List = T & { next: List }" cannot be reduced during its declaration. // Also, unlike union types, the order of the constituent types is preserved in order that overload resolution // for intersections of types with signatures can be deterministic. - function getIntersectionType(types: readonly Type[], aliasSymbol?: Symbol, aliasTypeArguments?: readonly Type[], noSupertypeReduction?: boolean): Type { + function getIntersectionType( + types: readonly Type[], + aliasSymbol?: Symbol, + aliasTypeArguments?: readonly Type[], + noSupertypeReduction?: boolean, + ): Type { const typeMembershipMap = new Map(); const includes = addTypesToIntersection(typeMembershipMap, 0 as TypeFlags, types); const typeSet: Type[] = arrayFrom(typeMembershipMap.values()); @@ -17073,32 +21553,38 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return contains(typeSet, silentNeverType) ? silentNeverType : neverType; } if ( - strictNullChecks && includes & TypeFlags.Nullable && includes & (TypeFlags.Object | TypeFlags.NonPrimitive | TypeFlags.IncludesEmptyObject) || - includes & TypeFlags.NonPrimitive && includes & (TypeFlags.DisjointDomains & ~TypeFlags.NonPrimitive) || - includes & TypeFlags.StringLike && includes & (TypeFlags.DisjointDomains & ~TypeFlags.StringLike) || - includes & TypeFlags.NumberLike && includes & (TypeFlags.DisjointDomains & ~TypeFlags.NumberLike) || - includes & TypeFlags.BigIntLike && includes & (TypeFlags.DisjointDomains & ~TypeFlags.BigIntLike) || - includes & TypeFlags.ESSymbolLike && includes & (TypeFlags.DisjointDomains & ~TypeFlags.ESSymbolLike) || - includes & TypeFlags.VoidLike && includes & (TypeFlags.DisjointDomains & ~TypeFlags.VoidLike) + strictNullChecks && includes & TypeFlags.Nullable + && includes & (TypeFlags.Object | TypeFlags.NonPrimitive | TypeFlags.IncludesEmptyObject) + || includes & TypeFlags.NonPrimitive && includes & (TypeFlags.DisjointDomains & ~TypeFlags.NonPrimitive) + || includes & TypeFlags.StringLike && includes & (TypeFlags.DisjointDomains & ~TypeFlags.StringLike) + || includes & TypeFlags.NumberLike && includes & (TypeFlags.DisjointDomains & ~TypeFlags.NumberLike) + || includes & TypeFlags.BigIntLike && includes & (TypeFlags.DisjointDomains & ~TypeFlags.BigIntLike) + || includes & TypeFlags.ESSymbolLike && includes & (TypeFlags.DisjointDomains & ~TypeFlags.ESSymbolLike) + || includes & TypeFlags.VoidLike && includes & (TypeFlags.DisjointDomains & ~TypeFlags.VoidLike) ) { return neverType; } - if (includes & TypeFlags.TemplateLiteral && includes & TypeFlags.StringLiteral && extractRedundantTemplateLiterals(typeSet)) { + if ( + includes & TypeFlags.TemplateLiteral && includes & TypeFlags.StringLiteral + && extractRedundantTemplateLiterals(typeSet) + ) { return neverType; } if (includes & TypeFlags.Any) { return includes & TypeFlags.IncludesWildcard ? wildcardType : anyType; } if (!strictNullChecks && includes & TypeFlags.Nullable) { - return includes & TypeFlags.IncludesEmptyObject ? neverType : includes & TypeFlags.Undefined ? undefinedType : nullType; + return includes & TypeFlags.IncludesEmptyObject ? neverType + : includes & TypeFlags.Undefined ? undefinedType : nullType; } if ( - includes & TypeFlags.String && includes & (TypeFlags.StringLiteral | TypeFlags.TemplateLiteral | TypeFlags.StringMapping) || - includes & TypeFlags.Number && includes & TypeFlags.NumberLiteral || - includes & TypeFlags.BigInt && includes & TypeFlags.BigIntLiteral || - includes & TypeFlags.ESSymbol && includes & TypeFlags.UniqueESSymbol || - includes & TypeFlags.Void && includes & TypeFlags.Undefined || - includes & TypeFlags.IncludesEmptyObject && includes & TypeFlags.DefinitelyNonNullable + includes & TypeFlags.String + && includes & (TypeFlags.StringLiteral | TypeFlags.TemplateLiteral | TypeFlags.StringMapping) + || includes & TypeFlags.Number && includes & TypeFlags.NumberLiteral + || includes & TypeFlags.BigInt && includes & TypeFlags.BigIntLiteral + || includes & TypeFlags.ESSymbol && includes & TypeFlags.UniqueESSymbol + || includes & TypeFlags.Void && includes & TypeFlags.Undefined + || includes & TypeFlags.IncludesEmptyObject && includes & TypeFlags.DefinitelyNonNullable ) { if (!noSupertypeReduction) removeRedundantSupertypes(typeSet, includes); } @@ -17121,14 +21607,34 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // reduced we'll never reduce again, so this occurs at most once. result = getIntersectionType(typeSet, aliasSymbol, aliasTypeArguments); } - else if (every(typeSet, t => !!(t.flags & TypeFlags.Union && (t as UnionType).types[0].flags & TypeFlags.Undefined))) { + else if ( + every( + typeSet, + t => !!(t.flags & TypeFlags.Union && (t as UnionType).types[0].flags & TypeFlags.Undefined), + ) + ) { const containedUndefinedType = some(typeSet, containsMissingType) ? missingType : undefinedType; removeFromEach(typeSet, TypeFlags.Undefined); - result = getUnionType([getIntersectionType(typeSet), containedUndefinedType], UnionReduction.Literal, aliasSymbol, aliasTypeArguments); + result = getUnionType( + [getIntersectionType(typeSet), containedUndefinedType], + UnionReduction.Literal, + aliasSymbol, + aliasTypeArguments, + ); } - else if (every(typeSet, t => !!(t.flags & TypeFlags.Union && ((t as UnionType).types[0].flags & TypeFlags.Null || (t as UnionType).types[1].flags & TypeFlags.Null)))) { + else if ( + every(typeSet, t => + !!(t.flags & TypeFlags.Union + && ((t as UnionType).types[0].flags & TypeFlags.Null + || (t as UnionType).types[1].flags & TypeFlags.Null))) + ) { removeFromEach(typeSet, TypeFlags.Null); - result = getUnionType([getIntersectionType(typeSet), nullType], UnionReduction.Literal, aliasSymbol, aliasTypeArguments); + result = getUnionType( + [getIntersectionType(typeSet), nullType], + UnionReduction.Literal, + aliasSymbol, + aliasTypeArguments, + ); } else { // We are attempting to construct a type of the form X & (A | B) & (C | D). Transform this into a type of @@ -17141,8 +21647,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // We attach a denormalized origin type when at least one constituent of the cross-product union is an // intersection (i.e. when the intersection didn't just reduce one or more unions to smaller unions) and // the denormalized origin has fewer constituents than the union itself. - const origin = some(constituents, t => !!(t.flags & TypeFlags.Intersection)) && getConstituentCountOfTypes(constituents) > getConstituentCountOfTypes(typeSet) ? createOriginUnionOrIntersectionType(TypeFlags.Intersection, typeSet) : undefined; - result = getUnionType(constituents, UnionReduction.Literal, aliasSymbol, aliasTypeArguments, origin); + const origin = some(constituents, t => !!(t.flags & TypeFlags.Intersection)) + && getConstituentCountOfTypes(constituents) > getConstituentCountOfTypes(typeSet) + ? createOriginUnionOrIntersectionType(TypeFlags.Intersection, typeSet) : undefined; + result = getUnionType( + constituents, + UnionReduction.Literal, + aliasSymbol, + aliasTypeArguments, + origin, + ); } } else { @@ -17154,13 +21668,20 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function getCrossProductUnionSize(types: readonly Type[]) { - return reduceLeft(types, (n, t) => t.flags & TypeFlags.Union ? n * (t as UnionType).types.length : t.flags & TypeFlags.Never ? 0 : n, 1); + return reduceLeft( + types, + (n, t) => t.flags & TypeFlags.Union ? n * (t as UnionType).types.length : t.flags & TypeFlags.Never ? 0 : n, + 1, + ); } function checkCrossProductUnion(types: readonly Type[]) { const size = getCrossProductUnionSize(types); if (size >= 100000) { - tracing?.instant(tracing.Phase.CheckTypes, "checkCrossProductUnion_DepthLimit", { typeIds: types.map(t => t.id), size }); + tracing?.instant(tracing.Phase.CheckTypes, "checkCrossProductUnion_DepthLimit", { + typeIds: types.map(t => t.id), + size, + }); error(currentNode, Diagnostics.Expression_produces_a_union_type_that_is_too_complex_to_represent); return false; } @@ -17188,21 +21709,26 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function getConstituentCount(type: Type): number { - return !(type.flags & TypeFlags.UnionOrIntersection) || type.aliasSymbol ? 1 : - type.flags & TypeFlags.Union && (type as UnionType).origin ? getConstituentCount((type as UnionType).origin!) : - getConstituentCountOfTypes((type as UnionOrIntersectionType).types); + return !(type.flags & TypeFlags.UnionOrIntersection) || type.aliasSymbol ? 1 + : type.flags & TypeFlags.Union && (type as UnionType).origin + ? getConstituentCount((type as UnionType).origin!) + : getConstituentCountOfTypes((type as UnionOrIntersectionType).types); } function getConstituentCountOfTypes(types: Type[]): number { return reduceLeft(types, (n, t) => n + getConstituentCount(t), 0); } - function areIntersectedTypesAvoidingPrimitiveReduction(types: Type[], primitiveFlags = TypeFlags.String | TypeFlags.Number | TypeFlags.BigInt): boolean { + function areIntersectedTypesAvoidingPrimitiveReduction( + types: Type[], + primitiveFlags = TypeFlags.String | TypeFlags.Number | TypeFlags.BigInt, + ): boolean { if (types.length !== 2) { return false; } const [t1, t2] = types; - return !!(t1.flags & primitiveFlags) && t2 === emptyTypeLiteralType || !!(t2.flags & primitiveFlags) && t1 === emptyTypeLiteralType; + return !!(t1.flags & primitiveFlags) && t2 === emptyTypeLiteralType + || !!(t2.flags & primitiveFlags) && t1 === emptyTypeLiteralType; } function getTypeFromIntersectionTypeNode(node: IntersectionTypeNode): Type { @@ -17211,7 +21737,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const aliasSymbol = getAliasSymbolForTypeNode(node); const types = map(node.types, getTypeFromTypeNode); const noSupertypeReduction = areIntersectedTypesAvoidingPrimitiveReduction(types); - links.resolvedType = getIntersectionType(types, aliasSymbol, getTypeArgumentsForAliasSymbol(aliasSymbol), noSupertypeReduction); + links.resolvedType = getIntersectionType( + types, + aliasSymbol, + getTypeArgumentsForAliasSymbol(aliasSymbol), + noSupertypeReduction, + ); } return links.resolvedType; } @@ -17230,9 +21761,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function getIndexTypeForGenericType(type: InstantiableType | UnionOrIntersectionType, indexFlags: IndexFlags) { - return indexFlags & IndexFlags.StringsOnly ? - type.resolvedStringIndexType || (type.resolvedStringIndexType = createIndexType(type, IndexFlags.StringsOnly)) : - type.resolvedIndexType || (type.resolvedIndexType = createIndexType(type, IndexFlags.None)); + return indexFlags & IndexFlags.StringsOnly + ? type.resolvedStringIndexType + || (type.resolvedStringIndexType = createIndexType(type, IndexFlags.StringsOnly)) + : type.resolvedIndexType || (type.resolvedIndexType = createIndexType(type, IndexFlags.None)); } /** @@ -17259,7 +21791,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // so we only eagerly manifest the keys if the constraint is nongeneric if (!isGenericIndexType(constraintType)) { const modifiersType = getApparentType(getModifiersTypeFromMappedType(type)); // The 'T' in 'keyof T' - forEachMappedTypePropertyKeyTypeAndIndexSignatureKeyType(modifiersType, TypeFlags.StringOrNumberLiteralOrUnique, !!(indexFlags & IndexFlags.StringsOnly), addMemberForKeyType); + forEachMappedTypePropertyKeyTypeAndIndexSignatureKeyType( + modifiersType, + TypeFlags.StringOrNumberLiteralOrUnique, + !!(indexFlags & IndexFlags.StringsOnly), + addMemberForKeyType, + ); } else { // we have a generic index and a homomorphic mapping (but a distributive key remapping) - we need to defer the whole `keyof whatever` for later @@ -17275,14 +21812,20 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } // we had to pick apart the constraintType to potentially map/filter it - compare the final resulting list with the original constraintType, // so we can return the union that preserves aliases/origin data if possible - const result = indexFlags & IndexFlags.NoIndexSignatures ? filterType(getUnionType(keyTypes), t => !(t.flags & (TypeFlags.Any | TypeFlags.String))) : getUnionType(keyTypes); - if (result.flags & TypeFlags.Union && constraintType.flags & TypeFlags.Union && getTypeListId((result as UnionType).types) === getTypeListId((constraintType as UnionType).types)) { + const result = indexFlags & IndexFlags.NoIndexSignatures + ? filterType(getUnionType(keyTypes), t => !(t.flags & (TypeFlags.Any | TypeFlags.String))) + : getUnionType(keyTypes); + if ( + result.flags & TypeFlags.Union && constraintType.flags & TypeFlags.Union + && getTypeListId((result as UnionType).types) === getTypeListId((constraintType as UnionType).types) + ) { return constraintType; } return result; function addMemberForKeyType(keyType: Type) { - const propNameType = nameType ? instantiateType(nameType, appendTypeMapping(type.mapper, typeParameter, keyType)) : keyType; + const propNameType = nameType + ? instantiateType(nameType, appendTypeMapping(type.mapper, typeParameter, keyType)) : keyType; // `keyof` currently always returns `string | number` for concrete `string` index signatures - the below ternary keeps that behavior for mapped types // See `getLiteralTypeFromProperties` where there's a similar ternary to cause the same behavior. keyTypes.push(propNameType === stringType ? stringOrNumberType : propNameType); @@ -17298,13 +21841,21 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const typeVariable = getTypeParameterFromMappedType(mappedType); return isDistributive(getNameTypeFromMappedType(mappedType) || typeVariable); function isDistributive(type: Type): boolean { - return type.flags & (TypeFlags.AnyOrUnknown | TypeFlags.Primitive | TypeFlags.Never | TypeFlags.TypeParameter | TypeFlags.Object | TypeFlags.NonPrimitive) ? true : - type.flags & TypeFlags.Conditional ? (type as ConditionalType).root.isDistributive && (type as ConditionalType).checkType === typeVariable : - type.flags & (TypeFlags.UnionOrIntersection | TypeFlags.TemplateLiteral) ? every((type as UnionOrIntersectionType | TemplateLiteralType).types, isDistributive) : - type.flags & TypeFlags.IndexedAccess ? isDistributive((type as IndexedAccessType).objectType) && isDistributive((type as IndexedAccessType).indexType) : - type.flags & TypeFlags.Substitution ? isDistributive((type as SubstitutionType).baseType) && isDistributive((type as SubstitutionType).constraint) : - type.flags & TypeFlags.StringMapping ? isDistributive((type as StringMappingType).type) : - false; + return type.flags + & (TypeFlags.AnyOrUnknown | TypeFlags.Primitive | TypeFlags.Never | TypeFlags.TypeParameter + | TypeFlags.Object | TypeFlags.NonPrimitive) ? true + : type.flags & TypeFlags.Conditional + ? (type as ConditionalType).root.isDistributive && (type as ConditionalType).checkType === typeVariable + : type.flags & (TypeFlags.UnionOrIntersection | TypeFlags.TemplateLiteral) + ? every((type as UnionOrIntersectionType | TemplateLiteralType).types, isDistributive) + : type.flags & TypeFlags.IndexedAccess + ? isDistributive((type as IndexedAccessType).objectType) + && isDistributive((type as IndexedAccessType).indexType) + : type.flags & TypeFlags.Substitution + ? isDistributive((type as SubstitutionType).baseType) + && isDistributive((type as SubstitutionType).constraint) + : type.flags & TypeFlags.StringMapping ? isDistributive((type as StringMappingType).type) + : false; } } @@ -17329,12 +21880,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function getLiteralTypeFromProperty(prop: Symbol, include: TypeFlags, includeNonPublic?: boolean) { - if (includeNonPublic || !(getDeclarationModifierFlagsFromSymbol(prop) & ModifierFlags.NonPublicAccessibilityModifier)) { + if ( + includeNonPublic + || !(getDeclarationModifierFlagsFromSymbol(prop) & ModifierFlags.NonPublicAccessibilityModifier) + ) { let type = getSymbolLinks(getLateBoundSymbol(prop)).nameType; if (!type) { const name = getNameOfDeclaration(prop.valueDeclaration) as PropertyName | JsxAttributeName; - type = prop.escapedName === InternalSymbolName.Default ? getStringLiteralType("default") : - name && getLiteralTypeFromPropertyName(name) || (!isKnownSymbol(prop) ? getStringLiteralType(symbolName(prop)) : undefined); + type = prop.escapedName === InternalSymbolName.Default ? getStringLiteralType("default") + : name && getLiteralTypeFromPropertyName(name) + || (!isKnownSymbol(prop) ? getStringLiteralType(symbolName(prop)) : undefined); } if (type && type.flags & include) { return type; @@ -17344,36 +21899,60 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function isKeyTypeIncluded(keyType: Type, include: TypeFlags): boolean { - return !!(keyType.flags & include || keyType.flags & TypeFlags.Intersection && some((keyType as IntersectionType).types, t => isKeyTypeIncluded(t, include))); + return !!(keyType.flags & include + || keyType.flags & TypeFlags.Intersection + && some((keyType as IntersectionType).types, t => isKeyTypeIncluded(t, include))); } function getLiteralTypeFromProperties(type: Type, include: TypeFlags, includeOrigin: boolean) { - const origin = includeOrigin && (getObjectFlags(type) & (ObjectFlags.ClassOrInterface | ObjectFlags.Reference) || type.aliasSymbol) ? createOriginIndexType(type) : undefined; + const origin = includeOrigin + && (getObjectFlags(type) & (ObjectFlags.ClassOrInterface | ObjectFlags.Reference) || type.aliasSymbol) + ? createOriginIndexType(type) : undefined; const propertyTypes = map(getPropertiesOfType(type), prop => getLiteralTypeFromProperty(prop, include)); - const indexKeyTypes = map(getIndexInfosOfType(type), info => - info !== enumNumberIndexInfo && isKeyTypeIncluded(info.keyType, include) ? - info.keyType === stringType && include & TypeFlags.Number ? stringOrNumberType : info.keyType : neverType); - return getUnionType(concatenate(propertyTypes, indexKeyTypes), UnionReduction.Literal, /*aliasSymbol*/ undefined, /*aliasTypeArguments*/ undefined, origin); + const indexKeyTypes = map( + getIndexInfosOfType(type), + info => + info !== enumNumberIndexInfo && isKeyTypeIncluded(info.keyType, include) + ? info.keyType === stringType && include & TypeFlags.Number ? stringOrNumberType : info.keyType + : neverType, + ); + return getUnionType( + concatenate(propertyTypes, indexKeyTypes), + UnionReduction.Literal, + /*aliasSymbol*/ undefined, + /*aliasTypeArguments*/ undefined, + origin, + ); } function shouldDeferIndexType(type: Type, indexFlags = IndexFlags.None) { - return !!(type.flags & TypeFlags.InstantiableNonPrimitive || - isGenericTupleType(type) || - isGenericMappedType(type) && !hasDistributiveNameType(type) || - type.flags & TypeFlags.Union && !(indexFlags & IndexFlags.NoReducibleCheck) && isGenericReducibleType(type) || - type.flags & TypeFlags.Intersection && maybeTypeOfKind(type, TypeFlags.Instantiable) && some((type as IntersectionType).types, isEmptyAnonymousObjectType)); + return !!(type.flags & TypeFlags.InstantiableNonPrimitive + || isGenericTupleType(type) + || isGenericMappedType(type) && !hasDistributiveNameType(type) + || type.flags & TypeFlags.Union && !(indexFlags & IndexFlags.NoReducibleCheck) + && isGenericReducibleType(type) + || type.flags & TypeFlags.Intersection && maybeTypeOfKind(type, TypeFlags.Instantiable) + && some((type as IntersectionType).types, isEmptyAnonymousObjectType)); } function getIndexType(type: Type, indexFlags = defaultIndexFlags): Type { type = getReducedType(type); - return shouldDeferIndexType(type, indexFlags) ? getIndexTypeForGenericType(type as InstantiableType | UnionOrIntersectionType, indexFlags) : - type.flags & TypeFlags.Union ? getIntersectionType(map((type as UnionType).types, t => getIndexType(t, indexFlags))) : - type.flags & TypeFlags.Intersection ? getUnionType(map((type as IntersectionType).types, t => getIndexType(t, indexFlags))) : - getObjectFlags(type) & ObjectFlags.Mapped ? getIndexTypeForMappedType(type as MappedType, indexFlags) : - type === wildcardType ? wildcardType : - type.flags & TypeFlags.Unknown ? neverType : - type.flags & (TypeFlags.Any | TypeFlags.Never) ? keyofConstraintType : - getLiteralTypeFromProperties(type, (indexFlags & IndexFlags.NoIndexSignatures ? TypeFlags.StringLiteral : TypeFlags.StringLike) | (indexFlags & IndexFlags.StringsOnly ? 0 : TypeFlags.NumberLike | TypeFlags.ESSymbolLike), indexFlags === defaultIndexFlags); + return shouldDeferIndexType(type, indexFlags) + ? getIndexTypeForGenericType(type as InstantiableType | UnionOrIntersectionType, indexFlags) + : type.flags & TypeFlags.Union + ? getIntersectionType(map((type as UnionType).types, t => getIndexType(t, indexFlags))) + : type.flags & TypeFlags.Intersection + ? getUnionType(map((type as IntersectionType).types, t => getIndexType(t, indexFlags))) + : getObjectFlags(type) & ObjectFlags.Mapped ? getIndexTypeForMappedType(type as MappedType, indexFlags) + : type === wildcardType ? wildcardType + : type.flags & TypeFlags.Unknown ? neverType + : type.flags & (TypeFlags.Any | TypeFlags.Never) ? keyofConstraintType + : getLiteralTypeFromProperties( + type, + (indexFlags & IndexFlags.NoIndexSignatures ? TypeFlags.StringLiteral : TypeFlags.StringLike) + | (indexFlags & IndexFlags.StringsOnly ? 0 : TypeFlags.NumberLike | TypeFlags.ESSymbolLike), + indexFlags === defaultIndexFlags, + ); } function getExtractStringType(type: Type) { @@ -17425,9 +22004,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function getTemplateLiteralType(texts: readonly string[], types: readonly Type[]): Type { const unionIndex = findIndex(types, t => !!(t.flags & (TypeFlags.Never | TypeFlags.Union))); if (unionIndex >= 0) { - return checkCrossProductUnion(types) ? - mapType(types[unionIndex], t => getTemplateLiteralType(texts, replaceElement(types, unionIndex, t))) : - errorType; + return checkCrossProductUnion(types) + ? mapType(types[unionIndex], t => getTemplateLiteralType(texts, replaceElement(types, unionIndex, t))) + : errorType; } if (contains(types, wildcardType)) { return wildcardType; @@ -17484,11 +22063,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function getTemplateStringForType(type: Type) { - return type.flags & TypeFlags.StringLiteral ? (type as StringLiteralType).value : - type.flags & TypeFlags.NumberLiteral ? "" + (type as NumberLiteralType).value : - type.flags & TypeFlags.BigIntLiteral ? pseudoBigIntToString((type as BigIntLiteralType).value) : - type.flags & (TypeFlags.BooleanLiteral | TypeFlags.Nullable) ? (type as IntrinsicType).intrinsicName : - undefined; + return type.flags & TypeFlags.StringLiteral ? (type as StringLiteralType).value + : type.flags & TypeFlags.NumberLiteral ? "" + (type as NumberLiteralType).value + : type.flags & TypeFlags.BigIntLiteral ? pseudoBigIntToString((type as BigIntLiteralType).value) + : type.flags & (TypeFlags.BooleanLiteral | TypeFlags.Nullable) ? (type as IntrinsicType).intrinsicName + : undefined; } function createTemplateLiteralType(texts: readonly string[], types: readonly Type[]) { @@ -17500,15 +22079,25 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function getStringMappingType(symbol: Symbol, type: Type): Type { - return type.flags & (TypeFlags.Union | TypeFlags.Never) ? mapType(type, t => getStringMappingType(symbol, t)) : - type.flags & TypeFlags.StringLiteral ? getStringLiteralType(applyStringMapping(symbol, (type as StringLiteralType).value)) : - type.flags & TypeFlags.TemplateLiteral ? getTemplateLiteralType(...applyTemplateStringMapping(symbol, (type as TemplateLiteralType).texts, (type as TemplateLiteralType).types)) : + return type.flags & (TypeFlags.Union | TypeFlags.Never) ? mapType(type, t => getStringMappingType(symbol, t)) + : type.flags & TypeFlags.StringLiteral + ? getStringLiteralType(applyStringMapping(symbol, (type as StringLiteralType).value)) + : type.flags & TypeFlags.TemplateLiteral + ? getTemplateLiteralType( + ...applyTemplateStringMapping( + symbol, + (type as TemplateLiteralType).texts, + (type as TemplateLiteralType).types, + ), + ) // Mapping> === Mapping - type.flags & TypeFlags.StringMapping && symbol === type.symbol ? type : - type.flags & (TypeFlags.Any | TypeFlags.String | TypeFlags.StringMapping) || isGenericIndexType(type) ? getStringMappingTypeForGenericType(symbol, type) : + : type.flags & TypeFlags.StringMapping && symbol === type.symbol ? type + : type.flags & (TypeFlags.Any | TypeFlags.String | TypeFlags.StringMapping) || isGenericIndexType(type) + ? getStringMappingTypeForGenericType(symbol, type) // This handles Mapping<`${number}`> and Mapping<`${bigint}`> - isPatternLiteralPlaceholderType(type) ? getStringMappingTypeForGenericType(symbol, getTemplateLiteralType(["", ""], [type])) : - type; + : isPatternLiteralPlaceholderType(type) + ? getStringMappingTypeForGenericType(symbol, getTemplateLiteralType(["", ""], [type])) + : type; } function applyStringMapping(symbol: Symbol, str: string) { @@ -17525,16 +22114,26 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return str; } - function applyTemplateStringMapping(symbol: Symbol, texts: readonly string[], types: readonly Type[]): [texts: readonly string[], types: readonly Type[]] { + function applyTemplateStringMapping( + symbol: Symbol, + texts: readonly string[], + types: readonly Type[], + ): [texts: readonly string[], types: readonly Type[]] { switch (intrinsicTypeKinds.get(symbol.escapedName as string)) { case IntrinsicTypeKind.Uppercase: return [texts.map(t => t.toUpperCase()), types.map(t => getStringMappingType(symbol, t))]; case IntrinsicTypeKind.Lowercase: return [texts.map(t => t.toLowerCase()), types.map(t => getStringMappingType(symbol, t))]; case IntrinsicTypeKind.Capitalize: - return [texts[0] === "" ? texts : [texts[0].charAt(0).toUpperCase() + texts[0].slice(1), ...texts.slice(1)], texts[0] === "" ? [getStringMappingType(symbol, types[0]), ...types.slice(1)] : types]; + return [ + texts[0] === "" ? texts : [texts[0].charAt(0).toUpperCase() + texts[0].slice(1), ...texts.slice(1)], + texts[0] === "" ? [getStringMappingType(symbol, types[0]), ...types.slice(1)] : types, + ]; case IntrinsicTypeKind.Uncapitalize: - return [texts[0] === "" ? texts : [texts[0].charAt(0).toLowerCase() + texts[0].slice(1), ...texts.slice(1)], texts[0] === "" ? [getStringMappingType(symbol, types[0]), ...types.slice(1)] : types]; + return [ + texts[0] === "" ? texts : [texts[0].charAt(0).toLowerCase() + texts[0].slice(1), ...texts.slice(1)], + texts[0] === "" ? [getStringMappingType(symbol, types[0]), ...types.slice(1)] : types, + ]; } return [texts, types]; } @@ -17554,7 +22153,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return result; } - function createIndexedAccessType(objectType: Type, indexType: Type, accessFlags: AccessFlags, aliasSymbol: Symbol | undefined, aliasTypeArguments: readonly Type[] | undefined) { + function createIndexedAccessType( + objectType: Type, + indexType: Type, + accessFlags: AccessFlags, + aliasSymbol: Symbol | undefined, + aliasTypeArguments: readonly Type[] | undefined, + ) { const type = createType(TypeFlags.IndexedAccess) as IndexedAccessType; type.objectType = objectType; type.indexType = indexType; @@ -17593,13 +22198,27 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return false; } - function getPropertyNameFromIndex(indexType: Type, accessNode: StringLiteral | Identifier | PrivateIdentifier | ObjectBindingPattern | ArrayBindingPattern | ComputedPropertyName | NumericLiteral | IndexedAccessTypeNode | ElementAccessExpression | SyntheticExpression | undefined) { - return isTypeUsableAsPropertyName(indexType) ? - getPropertyNameFromType(indexType) : - accessNode && isPropertyName(accessNode) ? + function getPropertyNameFromIndex( + indexType: Type, + accessNode: + | StringLiteral + | Identifier + | PrivateIdentifier + | ObjectBindingPattern + | ArrayBindingPattern + | ComputedPropertyName + | NumericLiteral + | IndexedAccessTypeNode + | ElementAccessExpression + | SyntheticExpression + | undefined, + ) { + return isTypeUsableAsPropertyName(indexType) + ? getPropertyNameFromType(indexType) + : accessNode && isPropertyName(accessNode) // late bound names are handled in the first branch, so here we only need to handle normal names - getPropertyNameForPropertyNameNode(accessNode) : - undefined; + ? getPropertyNameForPropertyNameNode(accessNode) + : undefined; } function isUncalledFunctionReference(node: Node, symbol: Symbol) { @@ -17613,9 +22232,24 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return true; } - function getPropertyTypeForIndexType(originalObjectType: Type, objectType: Type, indexType: Type, fullIndexType: Type, accessNode: ElementAccessExpression | IndexedAccessTypeNode | PropertyName | BindingName | SyntheticExpression | undefined, accessFlags: AccessFlags) { - const accessExpression = accessNode && accessNode.kind === SyntaxKind.ElementAccessExpression ? accessNode : undefined; - const propName = accessNode && isPrivateIdentifier(accessNode) ? undefined : getPropertyNameFromIndex(indexType, accessNode); + function getPropertyTypeForIndexType( + originalObjectType: Type, + objectType: Type, + indexType: Type, + fullIndexType: Type, + accessNode: + | ElementAccessExpression + | IndexedAccessTypeNode + | PropertyName + | BindingName + | SyntheticExpression + | undefined, + accessFlags: AccessFlags, + ) { + const accessExpression = accessNode && accessNode.kind === SyntaxKind.ElementAccessExpression ? accessNode + : undefined; + const propName = accessNode && isPrivateIdentifier(accessNode) ? undefined + : getPropertyNameFromIndex(indexType, accessNode); if (propName !== undefined) { if (accessFlags & AccessFlags.Contextual) { @@ -17623,14 +22257,28 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } const prop = getPropertyOfType(objectType, propName); if (prop) { - if (accessFlags & AccessFlags.ReportDeprecated && accessNode && prop.declarations && isDeprecatedSymbol(prop) && isUncalledFunctionReference(accessNode, prop)) { - const deprecatedNode = accessExpression?.argumentExpression ?? (isIndexedAccessTypeNode(accessNode) ? accessNode.indexType : accessNode); + if ( + accessFlags & AccessFlags.ReportDeprecated && accessNode && prop.declarations + && isDeprecatedSymbol(prop) && isUncalledFunctionReference(accessNode, prop) + ) { + const deprecatedNode = accessExpression?.argumentExpression + ?? (isIndexedAccessTypeNode(accessNode) ? accessNode.indexType : accessNode); addDeprecatedSuggestion(deprecatedNode, prop.declarations, propName as string); } if (accessExpression) { - markPropertyAsReferenced(prop, accessExpression, isSelfTypeAccess(accessExpression.expression, objectType.symbol)); - if (isAssignmentToReadonlyEntity(accessExpression, prop, getAssignmentTargetKind(accessExpression))) { - error(accessExpression.argumentExpression, Diagnostics.Cannot_assign_to_0_because_it_is_a_read_only_property, symbolToString(prop)); + markPropertyAsReferenced( + prop, + accessExpression, + isSelfTypeAccess(accessExpression.expression, objectType.symbol), + ); + if ( + isAssignmentToReadonlyEntity(accessExpression, prop, getAssignmentTargetKind(accessExpression)) + ) { + error( + accessExpression.argumentExpression, + Diagnostics.Cannot_assign_to_0_because_it_is_a_read_only_property, + symbolToString(prop), + ); return undefined; } if (accessFlags & AccessFlags.CacheSymbol) { @@ -17641,61 +22289,94 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } const propType = getTypeOfSymbol(prop); - return accessExpression && getAssignmentTargetKind(accessExpression) !== AssignmentKind.Definite ? getFlowTypeOfReference(accessExpression, propType) : - accessNode && isIndexedAccessTypeNode(accessNode) && containsMissingType(propType) ? getUnionType([propType, undefinedType]) : - propType; + return accessExpression && getAssignmentTargetKind(accessExpression) !== AssignmentKind.Definite + ? getFlowTypeOfReference(accessExpression, propType) + : accessNode && isIndexedAccessTypeNode(accessNode) && containsMissingType(propType) + ? getUnionType([propType, undefinedType]) + : propType; } if (everyType(objectType, isTupleType) && isNumericLiteralName(propName)) { const index = +propName; - if (accessNode && everyType(objectType, t => !(t as TupleTypeReference).target.hasRestElement) && !(accessFlags & AccessFlags.NoTupleBoundsCheck)) { + if ( + accessNode && everyType(objectType, t => !(t as TupleTypeReference).target.hasRestElement) + && !(accessFlags & AccessFlags.NoTupleBoundsCheck) + ) { const indexNode = getIndexNodeForAccessExpression(accessNode); if (isTupleType(objectType)) { if (index < 0) { error(indexNode, Diagnostics.A_tuple_type_cannot_be_indexed_with_a_negative_value); return undefinedType; } - error(indexNode, Diagnostics.Tuple_type_0_of_length_1_has_no_element_at_index_2, typeToString(objectType), getTypeReferenceArity(objectType), unescapeLeadingUnderscores(propName)); + error( + indexNode, + Diagnostics.Tuple_type_0_of_length_1_has_no_element_at_index_2, + typeToString(objectType), + getTypeReferenceArity(objectType), + unescapeLeadingUnderscores(propName), + ); } else { - error(indexNode, Diagnostics.Property_0_does_not_exist_on_type_1, unescapeLeadingUnderscores(propName), typeToString(objectType)); + error( + indexNode, + Diagnostics.Property_0_does_not_exist_on_type_1, + unescapeLeadingUnderscores(propName), + typeToString(objectType), + ); } } if (index >= 0) { errorIfWritingToReadonlyIndex(getIndexInfoOfType(objectType, numberType)); - return getTupleElementTypeOutOfStartCount(objectType, index, accessFlags & AccessFlags.IncludeUndefined ? missingType : undefined); + return getTupleElementTypeOutOfStartCount( + objectType, + index, + accessFlags & AccessFlags.IncludeUndefined ? missingType : undefined, + ); } } } - if (!(indexType.flags & TypeFlags.Nullable) && isTypeAssignableToKind(indexType, TypeFlags.StringLike | TypeFlags.NumberLike | TypeFlags.ESSymbolLike)) { + if ( + !(indexType.flags & TypeFlags.Nullable) + && isTypeAssignableToKind(indexType, TypeFlags.StringLike | TypeFlags.NumberLike | TypeFlags.ESSymbolLike) + ) { if (objectType.flags & (TypeFlags.Any | TypeFlags.Never)) { return objectType; } // If no index signature is applicable, we default to the string index signature. In effect, this means the string // index signature applies even when accessing with a symbol-like type. - const indexInfo = getApplicableIndexInfo(objectType, indexType) || getIndexInfoOfType(objectType, stringType); + const indexInfo = getApplicableIndexInfo(objectType, indexType) + || getIndexInfoOfType(objectType, stringType); if (indexInfo) { if (accessFlags & AccessFlags.NoIndexSignatures && indexInfo.keyType !== numberType) { if (accessExpression) { - error(accessExpression, Diagnostics.Type_0_cannot_be_used_to_index_type_1, typeToString(indexType), typeToString(originalObjectType)); + error( + accessExpression, + Diagnostics.Type_0_cannot_be_used_to_index_type_1, + typeToString(indexType), + typeToString(originalObjectType), + ); } return undefined; } - if (accessNode && indexInfo.keyType === stringType && !isTypeAssignableToKind(indexType, TypeFlags.String | TypeFlags.Number)) { + if ( + accessNode && indexInfo.keyType === stringType + && !isTypeAssignableToKind(indexType, TypeFlags.String | TypeFlags.Number) + ) { const indexNode = getIndexNodeForAccessExpression(accessNode); error(indexNode, Diagnostics.Type_0_cannot_be_used_as_an_index_type, typeToString(indexType)); - return accessFlags & AccessFlags.IncludeUndefined ? getUnionType([indexInfo.type, missingType]) : indexInfo.type; + return accessFlags & AccessFlags.IncludeUndefined ? getUnionType([indexInfo.type, missingType]) + : indexInfo.type; } errorIfWritingToReadonlyIndex(indexInfo); // When accessing an enum object with its own type, // e.g. E[E.A] for enum E { A }, undefined shouldn't // be included in the result type if ( - (accessFlags & AccessFlags.IncludeUndefined) && - !(objectType.symbol && - objectType.symbol.flags & (SymbolFlags.RegularEnum | SymbolFlags.ConstEnum) && - (indexType.symbol && - indexType.flags & TypeFlags.EnumLiteral && - getParentOfSymbol(indexType.symbol) === objectType.symbol)) + (accessFlags & AccessFlags.IncludeUndefined) + && !(objectType.symbol + && objectType.symbol.flags & (SymbolFlags.RegularEnum | SymbolFlags.ConstEnum) + && (indexType.symbol + && indexType.flags & TypeFlags.EnumLiteral + && getParentOfSymbol(indexType.symbol) === objectType.symbol)) ) { return getUnionType([indexInfo.type, missingType]); } @@ -17710,7 +22391,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (accessExpression && !isConstEnumObjectType(objectType)) { if (isObjectLiteralType(objectType)) { if (noImplicitAny && indexType.flags & (TypeFlags.StringLiteral | TypeFlags.NumberLiteral)) { - diagnostics.add(createDiagnosticForNode(accessExpression, Diagnostics.Property_0_does_not_exist_on_type_1, (indexType as StringLiteralType).value, typeToString(objectType))); + diagnostics.add( + createDiagnosticForNode( + accessExpression, + Diagnostics.Property_0_does_not_exist_on_type_1, + (indexType as StringLiteralType).value, + typeToString(objectType), + ), + ); return undefinedType; } else if (indexType.flags & (TypeFlags.Number | TypeFlags.String)) { @@ -17721,55 +22409,132 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } - if (objectType.symbol === globalThisSymbol && propName !== undefined && globalThisSymbol.exports!.has(propName) && (globalThisSymbol.exports!.get(propName)!.flags & SymbolFlags.BlockScoped)) { - error(accessExpression, Diagnostics.Property_0_does_not_exist_on_type_1, unescapeLeadingUnderscores(propName), typeToString(objectType)); + if ( + objectType.symbol === globalThisSymbol && propName !== undefined + && globalThisSymbol.exports!.has(propName) + && (globalThisSymbol.exports!.get(propName)!.flags & SymbolFlags.BlockScoped) + ) { + error( + accessExpression, + Diagnostics.Property_0_does_not_exist_on_type_1, + unescapeLeadingUnderscores(propName), + typeToString(objectType), + ); } - else if (noImplicitAny && !compilerOptions.suppressImplicitAnyIndexErrors && !(accessFlags & AccessFlags.SuppressNoImplicitAnyError)) { + else if ( + noImplicitAny && !compilerOptions.suppressImplicitAnyIndexErrors + && !(accessFlags & AccessFlags.SuppressNoImplicitAnyError) + ) { if (propName !== undefined && typeHasStaticProperty(propName, objectType)) { const typeName = typeToString(objectType); - error(accessExpression, Diagnostics.Property_0_does_not_exist_on_type_1_Did_you_mean_to_access_the_static_member_2_instead, propName as string, typeName, typeName + "[" + getTextOfNode(accessExpression.argumentExpression) + "]"); + error( + accessExpression, + Diagnostics + .Property_0_does_not_exist_on_type_1_Did_you_mean_to_access_the_static_member_2_instead, + propName as string, + typeName, + typeName + "[" + getTextOfNode(accessExpression.argumentExpression) + "]", + ); } else if (getIndexTypeOfType(objectType, numberType)) { - error(accessExpression.argumentExpression, Diagnostics.Element_implicitly_has_an_any_type_because_index_expression_is_not_of_type_number); + error( + accessExpression.argumentExpression, + Diagnostics + .Element_implicitly_has_an_any_type_because_index_expression_is_not_of_type_number, + ); } else { let suggestion: string | undefined; - if (propName !== undefined && (suggestion = getSuggestionForNonexistentProperty(propName as string, objectType))) { + if ( + propName !== undefined + && (suggestion = getSuggestionForNonexistentProperty(propName as string, objectType)) + ) { if (suggestion !== undefined) { - error(accessExpression.argumentExpression, Diagnostics.Property_0_does_not_exist_on_type_1_Did_you_mean_2, propName as string, typeToString(objectType), suggestion); + error( + accessExpression.argumentExpression, + Diagnostics.Property_0_does_not_exist_on_type_1_Did_you_mean_2, + propName as string, + typeToString(objectType), + suggestion, + ); } } else { - const suggestion = getSuggestionForNonexistentIndexSignature(objectType, accessExpression, indexType); + const suggestion = getSuggestionForNonexistentIndexSignature( + objectType, + accessExpression, + indexType, + ); if (suggestion !== undefined) { - error(accessExpression, Diagnostics.Element_implicitly_has_an_any_type_because_type_0_has_no_index_signature_Did_you_mean_to_call_1, typeToString(objectType), suggestion); + error( + accessExpression, + Diagnostics + .Element_implicitly_has_an_any_type_because_type_0_has_no_index_signature_Did_you_mean_to_call_1, + typeToString(objectType), + suggestion, + ); } else { let errorInfo: DiagnosticMessageChain | undefined; if (indexType.flags & TypeFlags.EnumLiteral) { - errorInfo = chainDiagnosticMessages(/*details*/ undefined, Diagnostics.Property_0_does_not_exist_on_type_1, "[" + typeToString(indexType) + "]", typeToString(objectType)); + errorInfo = chainDiagnosticMessages( + /*details*/ undefined, + Diagnostics.Property_0_does_not_exist_on_type_1, + "[" + typeToString(indexType) + "]", + typeToString(objectType), + ); } else if (indexType.flags & TypeFlags.UniqueESSymbol) { - const symbolName = getFullyQualifiedName((indexType as UniqueESSymbolType).symbol, accessExpression); - errorInfo = chainDiagnosticMessages(/*details*/ undefined, Diagnostics.Property_0_does_not_exist_on_type_1, "[" + symbolName + "]", typeToString(objectType)); + const symbolName = getFullyQualifiedName( + (indexType as UniqueESSymbolType).symbol, + accessExpression, + ); + errorInfo = chainDiagnosticMessages( + /*details*/ undefined, + Diagnostics.Property_0_does_not_exist_on_type_1, + "[" + symbolName + "]", + typeToString(objectType), + ); } else if (indexType.flags & TypeFlags.StringLiteral) { - errorInfo = chainDiagnosticMessages(/*details*/ undefined, Diagnostics.Property_0_does_not_exist_on_type_1, (indexType as StringLiteralType).value, typeToString(objectType)); + errorInfo = chainDiagnosticMessages( + /*details*/ undefined, + Diagnostics.Property_0_does_not_exist_on_type_1, + (indexType as StringLiteralType).value, + typeToString(objectType), + ); } else if (indexType.flags & TypeFlags.NumberLiteral) { - errorInfo = chainDiagnosticMessages(/*details*/ undefined, Diagnostics.Property_0_does_not_exist_on_type_1, (indexType as NumberLiteralType).value, typeToString(objectType)); + errorInfo = chainDiagnosticMessages( + /*details*/ undefined, + Diagnostics.Property_0_does_not_exist_on_type_1, + (indexType as NumberLiteralType).value, + typeToString(objectType), + ); } else if (indexType.flags & (TypeFlags.Number | TypeFlags.String)) { - errorInfo = chainDiagnosticMessages(/*details*/ undefined, Diagnostics.No_index_signature_with_a_parameter_of_type_0_was_found_on_type_1, typeToString(indexType), typeToString(objectType)); + errorInfo = chainDiagnosticMessages( + /*details*/ undefined, + Diagnostics.No_index_signature_with_a_parameter_of_type_0_was_found_on_type_1, + typeToString(indexType), + typeToString(objectType), + ); } errorInfo = chainDiagnosticMessages( errorInfo, - Diagnostics.Element_implicitly_has_an_any_type_because_expression_of_type_0_can_t_be_used_to_index_type_1, + Diagnostics + .Element_implicitly_has_an_any_type_because_expression_of_type_0_can_t_be_used_to_index_type_1, typeToString(fullIndexType), typeToString(objectType), ); - diagnostics.add(createDiagnosticForNodeFromMessageChain(getSourceFileOfNode(accessExpression), accessExpression, errorInfo)); + diagnostics.add( + createDiagnosticForNodeFromMessageChain( + getSourceFileOfNode(accessExpression), + accessExpression, + errorInfo, + ), + ); } } } @@ -17783,10 +22548,20 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (accessNode) { const indexNode = getIndexNodeForAccessExpression(accessNode); if (indexType.flags & (TypeFlags.StringLiteral | TypeFlags.NumberLiteral)) { - error(indexNode, Diagnostics.Property_0_does_not_exist_on_type_1, "" + (indexType as StringLiteralType | NumberLiteralType).value, typeToString(objectType)); + error( + indexNode, + Diagnostics.Property_0_does_not_exist_on_type_1, + "" + (indexType as StringLiteralType | NumberLiteralType).value, + typeToString(objectType), + ); } else if (indexType.flags & (TypeFlags.String | TypeFlags.Number)) { - error(indexNode, Diagnostics.Type_0_has_no_matching_index_signature_for_type_1, typeToString(objectType), typeToString(indexType)); + error( + indexNode, + Diagnostics.Type_0_has_no_matching_index_signature_for_type_1, + typeToString(objectType), + typeToString(indexType), + ); } else { error(indexNode, Diagnostics.Type_0_cannot_be_used_as_an_index_type, typeToString(indexType)); @@ -17798,29 +22573,45 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return undefined; function errorIfWritingToReadonlyIndex(indexInfo: IndexInfo | undefined): void { - if (indexInfo && indexInfo.isReadonly && accessExpression && (isAssignmentTarget(accessExpression) || isDeleteTarget(accessExpression))) { - error(accessExpression, Diagnostics.Index_signature_in_type_0_only_permits_reading, typeToString(objectType)); + if ( + indexInfo && indexInfo.isReadonly && accessExpression + && (isAssignmentTarget(accessExpression) || isDeleteTarget(accessExpression)) + ) { + error( + accessExpression, + Diagnostics.Index_signature_in_type_0_only_permits_reading, + typeToString(objectType), + ); } } } - function getIndexNodeForAccessExpression(accessNode: ElementAccessExpression | IndexedAccessTypeNode | PropertyName | BindingName | SyntheticExpression) { - return accessNode.kind === SyntaxKind.ElementAccessExpression ? accessNode.argumentExpression : - accessNode.kind === SyntaxKind.IndexedAccessType ? accessNode.indexType : - accessNode.kind === SyntaxKind.ComputedPropertyName ? accessNode.expression : - accessNode; + function getIndexNodeForAccessExpression( + accessNode: ElementAccessExpression | IndexedAccessTypeNode | PropertyName | BindingName | SyntheticExpression, + ) { + return accessNode.kind === SyntaxKind.ElementAccessExpression ? accessNode.argumentExpression + : accessNode.kind === SyntaxKind.IndexedAccessType ? accessNode.indexType + : accessNode.kind === SyntaxKind.ComputedPropertyName ? accessNode.expression + : accessNode; } function isPatternLiteralPlaceholderType(type: Type): boolean { if (type.flags & TypeFlags.Intersection) { - return some((type as IntersectionType).types, t => !!(t.flags & (TypeFlags.Literal | TypeFlags.Null | TypeFlags.Undefined)) || isPatternLiteralPlaceholderType(t)); + return some( + (type as IntersectionType).types, + t => !!(t.flags & (TypeFlags.Literal | TypeFlags.Null | TypeFlags.Undefined)) + || isPatternLiteralPlaceholderType(t), + ); } - return !!(type.flags & (TypeFlags.Any | TypeFlags.String | TypeFlags.Number | TypeFlags.BigInt)) || isPatternLiteralType(type); + return !!(type.flags & (TypeFlags.Any | TypeFlags.String | TypeFlags.Number | TypeFlags.BigInt)) + || isPatternLiteralType(type); } function isPatternLiteralType(type: Type) { - return !!(type.flags & TypeFlags.TemplateLiteral) && every((type as TemplateLiteralType).types, isPatternLiteralPlaceholderType) || - !!(type.flags & TypeFlags.StringMapping) && isPatternLiteralPlaceholderType((type as StringMappingType).type); + return !!(type.flags & TypeFlags.TemplateLiteral) + && every((type as TemplateLiteralType).types, isPatternLiteralPlaceholderType) + || !!(type.flags & TypeFlags.StringMapping) + && isPatternLiteralPlaceholderType((type as StringMappingType).type); } function isGenericType(type: Type): boolean { @@ -17837,36 +22628,53 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function getGenericObjectFlags(type: Type): ObjectFlags { if (type.flags & (TypeFlags.UnionOrIntersection | TypeFlags.TemplateLiteral)) { - if (!((type as UnionOrIntersectionType | TemplateLiteralType).objectFlags & ObjectFlags.IsGenericTypeComputed)) { - (type as UnionOrIntersectionType | TemplateLiteralType).objectFlags |= ObjectFlags.IsGenericTypeComputed | - reduceLeft((type as UnionOrIntersectionType | TemplateLiteralType).types, (flags, t) => flags | getGenericObjectFlags(t), 0); + if ( + !((type as UnionOrIntersectionType | TemplateLiteralType).objectFlags + & ObjectFlags.IsGenericTypeComputed) + ) { + (type as UnionOrIntersectionType | TemplateLiteralType).objectFlags |= ObjectFlags.IsGenericTypeComputed + | reduceLeft( + (type as UnionOrIntersectionType | TemplateLiteralType).types, + (flags, t) => flags | getGenericObjectFlags(t), + 0, + ); } return (type as UnionOrIntersectionType | TemplateLiteralType).objectFlags & ObjectFlags.IsGenericType; } if (type.flags & TypeFlags.Substitution) { if (!((type as SubstitutionType).objectFlags & ObjectFlags.IsGenericTypeComputed)) { - (type as SubstitutionType).objectFlags |= ObjectFlags.IsGenericTypeComputed | - getGenericObjectFlags((type as SubstitutionType).baseType) | getGenericObjectFlags((type as SubstitutionType).constraint); + (type as SubstitutionType).objectFlags |= ObjectFlags.IsGenericTypeComputed + | getGenericObjectFlags((type as SubstitutionType).baseType) + | getGenericObjectFlags((type as SubstitutionType).constraint); } return (type as SubstitutionType).objectFlags & ObjectFlags.IsGenericType; } - return (type.flags & TypeFlags.InstantiableNonPrimitive || isGenericMappedType(type) || isGenericTupleType(type) ? ObjectFlags.IsGenericObjectType : 0) | - (type.flags & (TypeFlags.InstantiableNonPrimitive | TypeFlags.Index | TypeFlags.StringMapping) && !isPatternLiteralType(type) ? ObjectFlags.IsGenericIndexType : 0); + return (type.flags & TypeFlags.InstantiableNonPrimitive || isGenericMappedType(type) || isGenericTupleType(type) + ? ObjectFlags.IsGenericObjectType : 0) + | (type.flags & (TypeFlags.InstantiableNonPrimitive | TypeFlags.Index | TypeFlags.StringMapping) + && !isPatternLiteralType(type) ? ObjectFlags.IsGenericIndexType : 0); } function getSimplifiedType(type: Type, writing: boolean): Type { - return type.flags & TypeFlags.IndexedAccess ? getSimplifiedIndexedAccessType(type as IndexedAccessType, writing) : - type.flags & TypeFlags.Conditional ? getSimplifiedConditionalType(type as ConditionalType, writing) : - type; + return type.flags & TypeFlags.IndexedAccess ? getSimplifiedIndexedAccessType(type as IndexedAccessType, writing) + : type.flags & TypeFlags.Conditional ? getSimplifiedConditionalType(type as ConditionalType, writing) + : type; } function distributeIndexOverObjectType(objectType: Type, indexType: Type, writing: boolean) { // (T | U)[K] -> T[K] | U[K] (reading) // (T | U)[K] -> T[K] & U[K] (writing) // (T & U)[K] -> T[K] & U[K] - if (objectType.flags & TypeFlags.Union || objectType.flags & TypeFlags.Intersection && !shouldDeferIndexType(objectType)) { - const types = map((objectType as UnionOrIntersectionType).types, t => getSimplifiedType(getIndexedAccessType(t, indexType), writing)); - return objectType.flags & TypeFlags.Intersection || writing ? getIntersectionType(types) : getUnionType(types); + if ( + objectType.flags & TypeFlags.Union + || objectType.flags & TypeFlags.Intersection && !shouldDeferIndexType(objectType) + ) { + const types = map( + (objectType as UnionOrIntersectionType).types, + t => getSimplifiedType(getIndexedAccessType(t, indexType), writing), + ); + return objectType.flags & TypeFlags.Intersection || writing ? getIntersectionType(types) + : getUnionType(types); } } @@ -17874,7 +22682,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // T[A | B] -> T[A] | T[B] (reading) // T[A | B] -> T[A] & T[B] (writing) if (indexType.flags & TypeFlags.Union) { - const types = map((indexType as UnionType).types, t => getSimplifiedType(getIndexedAccessType(objectType, t), writing)); + const types = map( + (indexType as UnionType).types, + t => getSimplifiedType(getIndexedAccessType(objectType, t), writing), + ); return writing ? getIntersectionType(types) : getUnionType(types); } } @@ -17915,7 +22726,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // fixed element. We simplify to either the combined type of all elements (when the index type // the actual number type) or to the combined type of all non-fixed elements. if (isGenericTupleType(objectType) && indexType.flags & TypeFlags.NumberLike) { - const elementType = getElementTypeOfSliceOfTupleType(objectType, indexType.flags & TypeFlags.Number ? 0 : objectType.target.fixedLength, /*endSkipCount*/ 0, writing); + const elementType = getElementTypeOfSliceOfTupleType( + objectType, + indexType.flags & TypeFlags.Number ? 0 : objectType.target.fixedLength, + /*endSkipCount*/ 0, + writing, + ); if (elementType) { return type[cache] = elementType; } @@ -17925,7 +22741,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // For example, for an index access { [P in K]: Box }[X], we construct the type Box. if (isGenericMappedType(objectType)) { if (!getNameTypeFromMappedType(objectType) || isFilteringMappedType(objectType)) { - return type[cache] = mapType(substituteIndexedMappedType(objectType, type.indexType), t => getSimplifiedType(t, writing)); + return type[cache] = mapType( + substituteIndexedMappedType(objectType, type.indexType), + t => getSimplifiedType(t, writing), + ); } } return type[cache] = type; @@ -17938,15 +22757,23 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const falseType = getFalseTypeFromConditionalType(type); // Simplifications for types of the form `T extends U ? T : never` and `T extends U ? never : T`. if (falseType.flags & TypeFlags.Never && getActualTypeVariable(trueType) === getActualTypeVariable(checkType)) { - if (checkType.flags & TypeFlags.Any || isTypeAssignableTo(getRestrictiveInstantiation(checkType), getRestrictiveInstantiation(extendsType))) { // Always true + if ( + checkType.flags & TypeFlags.Any + || isTypeAssignableTo(getRestrictiveInstantiation(checkType), getRestrictiveInstantiation(extendsType)) + ) { // Always true return getSimplifiedType(trueType, writing); } else if (isIntersectionEmpty(checkType, extendsType)) { // Always false return neverType; } } - else if (trueType.flags & TypeFlags.Never && getActualTypeVariable(falseType) === getActualTypeVariable(checkType)) { - if (!(checkType.flags & TypeFlags.Any) && isTypeAssignableTo(getRestrictiveInstantiation(checkType), getRestrictiveInstantiation(extendsType))) { // Always true + else if ( + trueType.flags & TypeFlags.Never && getActualTypeVariable(falseType) === getActualTypeVariable(checkType) + ) { + if ( + !(checkType.flags & TypeFlags.Any) + && isTypeAssignableTo(getRestrictiveInstantiation(checkType), getRestrictiveInstantiation(extendsType)) + ) { // Always true return neverType; } else if (checkType.flags & TypeFlags.Any || isIntersectionEmpty(checkType, extendsType)) { // Always false @@ -17966,11 +22793,28 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function substituteIndexedMappedType(objectType: MappedType, index: Type) { const mapper = createTypeMapper([getTypeParameterFromMappedType(objectType)], [index]); const templateMapper = combineTypeMappers(objectType.mapper, mapper); - return instantiateType(getTemplateTypeFromMappedType(objectType.target as MappedType || objectType), templateMapper); + return instantiateType( + getTemplateTypeFromMappedType(objectType.target as MappedType || objectType), + templateMapper, + ); } - function getIndexedAccessType(objectType: Type, indexType: Type, accessFlags = AccessFlags.None, accessNode?: ElementAccessExpression | IndexedAccessTypeNode | PropertyName | BindingName | SyntheticExpression, aliasSymbol?: Symbol, aliasTypeArguments?: readonly Type[]): Type { - return getIndexedAccessTypeOrUndefined(objectType, indexType, accessFlags, accessNode, aliasSymbol, aliasTypeArguments) || (accessNode ? errorType : unknownType); + function getIndexedAccessType( + objectType: Type, + indexType: Type, + accessFlags = AccessFlags.None, + accessNode?: ElementAccessExpression | IndexedAccessTypeNode | PropertyName | BindingName | SyntheticExpression, + aliasSymbol?: Symbol, + aliasTypeArguments?: readonly Type[], + ): Type { + return getIndexedAccessTypeOrUndefined( + objectType, + indexType, + accessFlags, + accessNode, + aliasSymbol, + aliasTypeArguments, + ) || (accessNode ? errorType : unknownType); } function indexTypeLessThan(indexType: Type, limit: number) { @@ -17986,19 +22830,31 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { }); } - function getIndexedAccessTypeOrUndefined(objectType: Type, indexType: Type, accessFlags = AccessFlags.None, accessNode?: ElementAccessExpression | IndexedAccessTypeNode | PropertyName | BindingName | SyntheticExpression, aliasSymbol?: Symbol, aliasTypeArguments?: readonly Type[]): Type | undefined { + function getIndexedAccessTypeOrUndefined( + objectType: Type, + indexType: Type, + accessFlags = AccessFlags.None, + accessNode?: ElementAccessExpression | IndexedAccessTypeNode | PropertyName | BindingName | SyntheticExpression, + aliasSymbol?: Symbol, + aliasTypeArguments?: readonly Type[], + ): Type | undefined { if (objectType === wildcardType || indexType === wildcardType) { return wildcardType; } objectType = getReducedType(objectType); // If the object type has a string index signature and no other members we know that the result will // always be the type of that index signature and we can simplify accordingly. - if (isStringIndexSignatureOnlyType(objectType) && !(indexType.flags & TypeFlags.Nullable) && isTypeAssignableToKind(indexType, TypeFlags.String | TypeFlags.Number)) { + if ( + isStringIndexSignatureOnlyType(objectType) && !(indexType.flags & TypeFlags.Nullable) + && isTypeAssignableToKind(indexType, TypeFlags.String | TypeFlags.Number) + ) { indexType = stringType; } // In noUncheckedIndexedAccess mode, indexed access operations that occur in an expression in a read position and resolve to // an index signature have 'undefined' included in their type. - if (compilerOptions.noUncheckedIndexedAccess && accessFlags & AccessFlags.ExpressionPosition) accessFlags |= AccessFlags.IncludeUndefined; + if (compilerOptions.noUncheckedIndexedAccess && accessFlags & AccessFlags.ExpressionPosition) { + accessFlags |= AccessFlags.IncludeUndefined; + } // If the index type is generic, or if the object type is generic and doesn't originate in an expression and // the operation isn't exclusively indexing the fixed (non-variadic) portion of a tuple type, we are performing // a higher-order index access where we cannot meaningfully access the properties of the object type. Note that @@ -18006,19 +22862,33 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // preserve backwards compatibility. For example, an element access 'this["foo"]' has always been resolved // eagerly using the constraint type of 'this' at the given location. if ( - isGenericIndexType(indexType) || (accessNode && accessNode.kind !== SyntaxKind.IndexedAccessType ? - isGenericTupleType(objectType) && !indexTypeLessThan(indexType, getTotalFixedElementCount(objectType.target)) : - isGenericObjectType(objectType) && !(isTupleType(objectType) && indexTypeLessThan(indexType, getTotalFixedElementCount(objectType.target))) || isGenericReducibleType(objectType)) + isGenericIndexType(indexType) || (accessNode && accessNode.kind !== SyntaxKind.IndexedAccessType + ? isGenericTupleType(objectType) + && !indexTypeLessThan(indexType, getTotalFixedElementCount(objectType.target)) + : isGenericObjectType(objectType) + && !(isTupleType(objectType) + && indexTypeLessThan(indexType, getTotalFixedElementCount(objectType.target))) + || isGenericReducibleType(objectType)) ) { if (objectType.flags & TypeFlags.AnyOrUnknown) { return objectType; } // Defer the operation by creating an indexed access type. const persistentAccessFlags = accessFlags & AccessFlags.Persistent; - const id = objectType.id + "," + indexType.id + "," + persistentAccessFlags + getAliasId(aliasSymbol, aliasTypeArguments); + const id = objectType.id + "," + indexType.id + "," + persistentAccessFlags + + getAliasId(aliasSymbol, aliasTypeArguments); let type = indexedAccessTypes.get(id); if (!type) { - indexedAccessTypes.set(id, type = createIndexedAccessType(objectType, indexType, persistentAccessFlags, aliasSymbol, aliasTypeArguments)); + indexedAccessTypes.set( + id, + type = createIndexedAccessType( + objectType, + indexType, + persistentAccessFlags, + aliasSymbol, + aliasTypeArguments, + ), + ); } return type; @@ -18031,7 +22901,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const propTypes: Type[] = []; let wasMissingProp = false; for (const t of (indexType as UnionType).types) { - const propType = getPropertyTypeForIndexType(objectType, apparentObjectType, t, indexType, accessNode, accessFlags | (wasMissingProp ? AccessFlags.SuppressNoImplicitAnyError : 0)); + const propType = getPropertyTypeForIndexType( + objectType, + apparentObjectType, + t, + indexType, + accessNode, + accessFlags | (wasMissingProp ? AccessFlags.SuppressNoImplicitAnyError : 0), + ); if (propType) { propTypes.push(propType); } @@ -18051,7 +22928,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { ? getIntersectionType(propTypes, aliasSymbol, aliasTypeArguments) : getUnionType(propTypes, UnionReduction.Literal, aliasSymbol, aliasTypeArguments); } - return getPropertyTypeForIndexType(objectType, apparentObjectType, indexType, indexType, accessNode, accessFlags | AccessFlags.CacheSymbol | AccessFlags.ReportDeprecated); + return getPropertyTypeForIndexType( + objectType, + apparentObjectType, + indexType, + indexType, + accessNode, + accessFlags | AccessFlags.CacheSymbol | AccessFlags.ReportDeprecated, + ); } function getTypeFromIndexedAccessTypeNode(node: IndexedAccessTypeNode) { @@ -18060,7 +22944,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const objectType = getTypeFromTypeNode(node.objectType); const indexType = getTypeFromTypeNode(node.indexType); const potentialAlias = getAliasSymbolForTypeNode(node); - links.resolvedType = getIndexedAccessType(objectType, indexType, AccessFlags.None, node, potentialAlias, getTypeArgumentsForAliasSymbol(potentialAlias)); + links.resolvedType = getIndexedAccessType( + objectType, + indexType, + AccessFlags.None, + node, + potentialAlias, + getTypeArgumentsForAliasSymbol(potentialAlias), + ); } return links.resolvedType; } @@ -18086,30 +22977,43 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } if ( type.flags & TypeFlags.IndexedAccess && ( - (type as IndexedAccessType).objectType.flags & TypeFlags.Substitution || - (type as IndexedAccessType).indexType.flags & TypeFlags.Substitution + (type as IndexedAccessType).objectType.flags & TypeFlags.Substitution + || (type as IndexedAccessType).indexType.flags & TypeFlags.Substitution ) ) { - return getIndexedAccessType(getActualTypeVariable((type as IndexedAccessType).objectType), getActualTypeVariable((type as IndexedAccessType).indexType)); + return getIndexedAccessType( + getActualTypeVariable((type as IndexedAccessType).objectType), + getActualTypeVariable((type as IndexedAccessType).indexType), + ); } return type; } function maybeCloneTypeParameter(p: TypeParameter) { const constraint = getConstraintOfTypeParameter(p); - return constraint && (isGenericObjectType(constraint) || isGenericIndexType(constraint)) ? cloneTypeParameter(p) : p; + return constraint && (isGenericObjectType(constraint) || isGenericIndexType(constraint)) ? cloneTypeParameter(p) + : p; } function isSimpleTupleType(node: TypeNode) { - return isTupleTypeNode(node) && length(node.elements) > 0 && - !some(node.elements, e => isOptionalTypeNode(e) || isRestTypeNode(e) || isNamedTupleMember(e) && !!(e.questionToken || e.dotDotDotToken)); + return isTupleTypeNode(node) && length(node.elements) > 0 + && !some( + node.elements, + e => isOptionalTypeNode(e) || isRestTypeNode(e) + || isNamedTupleMember(e) && !!(e.questionToken || e.dotDotDotToken), + ); } function isDeferredType(type: Type, checkTuples: boolean) { return isGenericType(type) || checkTuples && isTupleType(type) && some(getElementTypes(type), isGenericType); } - function getConditionalType(root: ConditionalRoot, mapper: TypeMapper | undefined, aliasSymbol?: Symbol, aliasTypeArguments?: readonly Type[]): Type { + function getConditionalType( + root: ConditionalRoot, + mapper: TypeMapper | undefined, + aliasSymbol?: Symbol, + aliasTypeArguments?: readonly Type[], + ): Type { let result; let extraTypes: Type[] | undefined; let tailCount = 0; @@ -18134,8 +23038,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // When the check and extends types are simple tuple types of the same arity, we defer resolution of the // conditional type when any tuple elements are generic. This is such that non-distributable conditional // types can be written `[X] extends [Y] ? ...` and be deferred similarly to `X extends Y ? ...`. - const checkTuples = isSimpleTupleType(root.node.checkType) && isSimpleTupleType(root.node.extendsType) && - length((root.node.checkType as TupleTypeNode).elements) === length((root.node.extendsType as TupleTypeNode).elements); + const checkTuples = isSimpleTupleType(root.node.checkType) && isSimpleTupleType(root.node.extendsType) + && length((root.node.checkType as TupleTypeNode).elements) + === length((root.node.extendsType as TupleTypeNode).elements); const checkTypeDeferred = isDeferredType(checkType, checkTuples); let combinedMapper: TypeMapper | undefined; if (root.inferTypeParameters) { @@ -18157,7 +23062,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // * The mapper that maps the old root type parameter to the clone (`freshMapper`) // * The mapper that maps the clone to its inference result (`context.mapper`) const freshParams = sameMap(root.inferTypeParameters, maybeCloneTypeParameter); - const freshMapper = freshParams !== root.inferTypeParameters ? createTypeMapper(root.inferTypeParameters, freshParams) : undefined; + const freshMapper = freshParams !== root.inferTypeParameters + ? createTypeMapper(root.inferTypeParameters, freshParams) : undefined; const context = createInferenceContext(freshParams, /*signature*/ undefined, InferenceFlags.None); if (freshMapper) { const freshCombinedMapper = combineTypeMappers(mapper, freshMapper); @@ -18171,7 +23077,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // We don't want inferences from constraints as they may cause us to eagerly resolve the // conditional type instead of deferring resolution. Also, we always want strict function // types rules (i.e. proper contravariance) for inferences. - inferTypes(context.inferences, checkType, instantiateType(extendsType, freshMapper), InferencePriority.NoConstraints | InferencePriority.AlwaysStrict); + inferTypes( + context.inferences, + checkType, + instantiateType(extendsType, freshMapper), + InferencePriority.NoConstraints | InferencePriority.AlwaysStrict, + ); } const innerMapper = combineTypeMappers(freshMapper, context.mapper); // It's possible for 'infer T' type paramteters to be given uninstantiated constraints when the @@ -18180,24 +23091,37 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { combinedMapper = mapper ? combineTypeMappers(innerMapper, mapper) : innerMapper; } // Instantiate the extends type including inferences for 'infer T' type parameters - const inferredExtendsType = combinedMapper ? instantiateType(root.extendsType, combinedMapper) : extendsType; + const inferredExtendsType = combinedMapper ? instantiateType(root.extendsType, combinedMapper) + : extendsType; // We attempt to resolve the conditional type only when the check and extends types are non-generic if (!checkTypeDeferred && !isDeferredType(inferredExtendsType, checkTuples)) { // Return falseType for a definitely false extends check. We check an instantiations of the two // types with type parameters mapped to the wildcard type, the most permissive instantiations // possible (the wildcard type is assignable to and from all types). If those are not related, // then no instantiations will be and we can just return the false branch type. - if (!(inferredExtendsType.flags & TypeFlags.AnyOrUnknown) && (checkType.flags & TypeFlags.Any || !isTypeAssignableTo(getPermissiveInstantiation(checkType), getPermissiveInstantiation(inferredExtendsType)))) { + if ( + !(inferredExtendsType.flags & TypeFlags.AnyOrUnknown) + && (checkType.flags & TypeFlags.Any + || !isTypeAssignableTo( + getPermissiveInstantiation(checkType), + getPermissiveInstantiation(inferredExtendsType), + )) + ) { // Return union of trueType and falseType for 'any' since it matches anything if (checkType.flags & TypeFlags.Any) { - (extraTypes || (extraTypes = [])).push(instantiateType(getTypeFromTypeNode(root.node.trueType), combinedMapper || mapper)); + (extraTypes || (extraTypes = [])).push( + instantiateType(getTypeFromTypeNode(root.node.trueType), combinedMapper || mapper), + ); } // If falseType is an immediately nested conditional type that isn't distributive or has an // identical checkType, switch to that type and loop. const falseType = getTypeFromTypeNode(root.node.falseType); if (falseType.flags & TypeFlags.Conditional) { const newRoot = (falseType as ConditionalType).root; - if (newRoot.node.parent === root.node && (!newRoot.isDistributive || newRoot.checkType === root.checkType)) { + if ( + newRoot.node.parent === root.node + && (!newRoot.isDistributive || newRoot.checkType === root.checkType) + ) { root = newRoot; continue; } @@ -18213,7 +23137,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // that has no constraint. This ensures that, for example, the type // type Foo = T extends { x: string } ? string : number // doesn't immediately resolve to 'string' instead of being deferred. - if (inferredExtendsType.flags & TypeFlags.AnyOrUnknown || isTypeAssignableTo(getRestrictiveInstantiation(checkType), getRestrictiveInstantiation(inferredExtendsType))) { + if ( + inferredExtendsType.flags & TypeFlags.AnyOrUnknown + || isTypeAssignableTo( + getRestrictiveInstantiation(checkType), + getRestrictiveInstantiation(inferredExtendsType), + ) + ) { const trueType = getTypeFromTypeNode(root.node.trueType); const trueMapper = combinedMapper || mapper; if (canTailRecurse(trueType, trueMapper)) { @@ -18231,7 +23161,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { result.mapper = mapper; result.combinedMapper = combinedMapper; result.aliasSymbol = aliasSymbol || root.aliasSymbol; - result.aliasTypeArguments = aliasSymbol ? aliasTypeArguments : instantiateTypes(root.aliasTypeArguments, mapper!); // TODO: GH#18217 + result.aliasTypeArguments = aliasSymbol ? aliasTypeArguments + : instantiateTypes(root.aliasTypeArguments, mapper!); // TODO: GH#18217 break; } return extraTypes ? getUnionType(append(extraTypes, result)) : result; @@ -18246,8 +23177,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const typeParamMapper = combineTypeMappers((newType as ConditionalType).mapper, newMapper); const typeArguments = map(newRoot.outerTypeParameters, t => getMappedType(t, typeParamMapper)); const newRootMapper = createTypeMapper(newRoot.outerTypeParameters, typeArguments); - const newCheckType = newRoot.isDistributive ? getMappedType(newRoot.checkType, newRootMapper) : undefined; - if (!newCheckType || newCheckType === newRoot.checkType || !(newCheckType.flags & (TypeFlags.Union | TypeFlags.Never))) { + const newCheckType = newRoot.isDistributive ? getMappedType(newRoot.checkType, newRootMapper) + : undefined; + if ( + !newCheckType || newCheckType === newRoot.checkType + || !(newCheckType.flags & (TypeFlags.Union | TypeFlags.Never)) + ) { root = newRoot; mapper = newRootMapper; aliasSymbol = undefined; @@ -18264,15 +23199,20 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function getTrueTypeFromConditionalType(type: ConditionalType) { - return type.resolvedTrueType || (type.resolvedTrueType = instantiateType(getTypeFromTypeNode(type.root.node.trueType), type.mapper)); + return type.resolvedTrueType + || (type.resolvedTrueType = instantiateType(getTypeFromTypeNode(type.root.node.trueType), type.mapper)); } function getFalseTypeFromConditionalType(type: ConditionalType) { - return type.resolvedFalseType || (type.resolvedFalseType = instantiateType(getTypeFromTypeNode(type.root.node.falseType), type.mapper)); + return type.resolvedFalseType + || (type.resolvedFalseType = instantiateType(getTypeFromTypeNode(type.root.node.falseType), type.mapper)); } function getInferredTrueTypeFromConditionalType(type: ConditionalType) { - return type.resolvedInferredTrueType || (type.resolvedInferredTrueType = type.combinedMapper ? instantiateType(getTypeFromTypeNode(type.root.node.trueType), type.combinedMapper) : getTrueTypeFromConditionalType(type)); + return type.resolvedInferredTrueType + || (type.resolvedInferredTrueType = type.combinedMapper + ? instantiateType(getTypeFromTypeNode(type.root.node.trueType), type.combinedMapper) + : getTrueTypeFromConditionalType(type)); } function getInferTypeParameters(node: ConditionalTypeNode): TypeParameter[] | undefined { @@ -18289,8 +23229,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function isDistributionDependent(root: ConditionalRoot) { return root.isDistributive && ( - isTypeParameterPossiblyReferenced(root.checkType as TypeParameter, root.node.trueType) || - isTypeParameterPossiblyReferenced(root.checkType as TypeParameter, root.node.falseType) + isTypeParameterPossiblyReferenced(root.checkType as TypeParameter, root.node.trueType) + || isTypeParameterPossiblyReferenced(root.checkType as TypeParameter, root.node.falseType) ); } @@ -18301,7 +23241,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const aliasSymbol = getAliasSymbolForTypeNode(node); const aliasTypeArguments = getTypeArgumentsForAliasSymbol(aliasSymbol); const allOuterTypeParameters = getOuterTypeParameters(node, /*includeThisTypes*/ true); - const outerTypeParameters = aliasTypeArguments ? allOuterTypeParameters : filter(allOuterTypeParameters, tp => isTypeParameterPossiblyReferenced(tp, node)); + const outerTypeParameters = aliasTypeArguments ? allOuterTypeParameters + : filter(allOuterTypeParameters, tp => isTypeParameterPossiblyReferenced(tp, node)); const root: ConditionalRoot = { node, checkType, @@ -18347,7 +23288,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { links.resolvedSymbol = unknownSymbol; return links.resolvedType = errorType; } - const targetMeaning = node.isTypeOf ? SymbolFlags.Value : node.flags & NodeFlags.JSDoc ? SymbolFlags.Value | SymbolFlags.Type : SymbolFlags.Type; + const targetMeaning = node.isTypeOf ? SymbolFlags.Value + : node.flags & NodeFlags.JSDoc ? SymbolFlags.Value | SymbolFlags.Type : SymbolFlags.Type; // TODO: Future work: support unions/generics/whatever via a deferred import-type const innerModuleSymbol = resolveExternalModuleName(node, node.argument.literal); if (!innerModuleSymbol) { @@ -18367,12 +23309,23 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // the `exports` lookup process that only looks up namespace members which is used for most type references const mergedResolvedSymbol = getMergedSymbol(resolveSymbol(currentNamespace)); const symbolFromVariable = node.isTypeOf || isInJSFile(node) && isExportEquals - ? getPropertyOfType(getTypeOfSymbol(mergedResolvedSymbol), current.escapedText, /*skipObjectFunctionPropertyAugment*/ false, /*includeTypeOnlyMembers*/ true) + ? getPropertyOfType( + getTypeOfSymbol(mergedResolvedSymbol), + current.escapedText, + /*skipObjectFunctionPropertyAugment*/ false, + /*includeTypeOnlyMembers*/ true, + ) : undefined; - const symbolFromModule = node.isTypeOf ? undefined : getSymbol(getExportsOfSymbol(mergedResolvedSymbol), current.escapedText, meaning); + const symbolFromModule = node.isTypeOf ? undefined + : getSymbol(getExportsOfSymbol(mergedResolvedSymbol), current.escapedText, meaning); const next = symbolFromModule ?? symbolFromVariable; if (!next) { - error(current, Diagnostics.Namespace_0_has_no_exported_member_1, getFullyQualifiedName(currentNamespace), declarationNameToString(current)); + error( + current, + Diagnostics.Namespace_0_has_no_exported_member_1, + getFullyQualifiedName(currentNamespace), + declarationNameToString(current), + ); return links.resolvedType = errorType; } getNodeLinks(current).resolvedSymbol = next; @@ -18388,7 +23341,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { else { const errorMessage = targetMeaning === SymbolFlags.Value ? Diagnostics.Module_0_does_not_refer_to_a_value_but_is_used_as_a_value_here - : Diagnostics.Module_0_does_not_refer_to_a_type_but_is_used_as_a_type_here_Did_you_mean_typeof_import_0; + : Diagnostics + .Module_0_does_not_refer_to_a_type_but_is_used_as_a_type_here_Did_you_mean_typeof_import_0; error(node, errorMessage, node.argument.literal.text); @@ -18411,7 +23365,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } - function getTypeFromTypeLiteralOrFunctionOrConstructorTypeNode(node: TypeLiteralNode | FunctionOrConstructorTypeNode | JSDocTypeLiteral | JSDocFunctionType | JSDocSignature): Type { + function getTypeFromTypeLiteralOrFunctionOrConstructorTypeNode( + node: TypeLiteralNode | FunctionOrConstructorTypeNode | JSDocTypeLiteral | JSDocFunctionType | JSDocSignature, + ): Type { const links = getNodeLinks(node); if (!links.resolvedType) { // Deferred resolution of members is handled by resolveObjectTypeMembers @@ -18434,7 +23390,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function getAliasSymbolForTypeNode(node: Node) { let host = node.parent; - while (isParenthesizedTypeNode(host) || isJSDocTypeExpression(host) || isTypeOperatorNode(host) && host.operator === SyntaxKind.ReadonlyKeyword) { + while ( + isParenthesizedTypeNode(host) || isJSDocTypeExpression(host) + || isTypeOperatorNode(host) && host.operator === SyntaxKind.ReadonlyKeyword + ) { host = host.parent; } return isTypeAlias(host) ? getSymbolOfDeclaration(host) : undefined; @@ -18449,7 +23408,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function isEmptyObjectTypeOrSpreadsIntoEmptyObject(type: Type) { - return isEmptyObjectType(type) || !!(type.flags & (TypeFlags.Null | TypeFlags.Undefined | TypeFlags.BooleanLike | TypeFlags.NumberLike | TypeFlags.BigIntLike | TypeFlags.StringLike | TypeFlags.EnumLike | TypeFlags.NonPrimitive | TypeFlags.Index)); + return isEmptyObjectType(type) + || !!(type.flags + & (TypeFlags.Null | TypeFlags.Undefined | TypeFlags.BooleanLike | TypeFlags.NumberLike + | TypeFlags.BigIntLike | TypeFlags.StringLike | TypeFlags.EnumLike | TypeFlags.NonPrimitive + | TypeFlags.Index)); } function tryMergeUnionOfObjectTypeAndEmptyObject(type: Type, readonly: boolean): Type { @@ -18463,7 +23426,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (!firstType) { return type; } - const secondType = find((type as UnionType).types, t => t !== firstType && !isEmptyObjectTypeOrSpreadsIntoEmptyObject(t)); + const secondType = find( + (type as UnionType).types, + t => t !== firstType && !isEmptyObjectTypeOrSpreadsIntoEmptyObject(t), + ); if (secondType) { return type; } @@ -18477,10 +23443,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // do nothing, skip privates } else if (isSpreadableProperty(prop)) { - const isSetonlyAccessor = prop.flags & SymbolFlags.SetAccessor && !(prop.flags & SymbolFlags.GetAccessor); + const isSetonlyAccessor = prop.flags & SymbolFlags.SetAccessor + && !(prop.flags & SymbolFlags.GetAccessor); const flags = SymbolFlags.Property | SymbolFlags.Optional; - const result = createSymbol(flags, prop.escapedName, getIsLateCheckFlag(prop) | (readonly ? CheckFlags.Readonly : 0)); - result.links.type = isSetonlyAccessor ? undefinedType : addOptionality(getTypeOfSymbol(prop), /*isProperty*/ true); + const result = createSymbol( + flags, + prop.escapedName, + getIsLateCheckFlag(prop) | (readonly ? CheckFlags.Readonly : 0), + ); + result.links.type = isSetonlyAccessor ? undefinedType + : addOptionality(getTypeOfSymbol(prop), /*isProperty*/ true); result.declarations = prop.declarations; result.links.nameType = getSymbolLinks(prop).nameType; result.links.syntheticOrigin = prop; @@ -18498,7 +23470,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { * this function should be called in a left folding style, with left = previous result of getSpreadType * and right = the new element to be spread. */ - function getSpreadType(left: Type, right: Type, symbol: Symbol | undefined, objectFlags: ObjectFlags, readonly: boolean): Type { + function getSpreadType( + left: Type, + right: Type, + symbol: Symbol | undefined, + objectFlags: ObjectFlags, + readonly: boolean, + ): Type { if (left.flags & TypeFlags.Any || right.flags & TypeFlags.Any) { return anyType; } @@ -18523,7 +23501,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { ? mapType(right, t => getSpreadType(left, t, symbol, objectFlags, readonly)) : errorType; } - if (right.flags & (TypeFlags.BooleanLike | TypeFlags.NumberLike | TypeFlags.BigIntLike | TypeFlags.StringLike | TypeFlags.EnumLike | TypeFlags.NonPrimitive | TypeFlags.Index)) { + if ( + right.flags + & (TypeFlags.BooleanLike | TypeFlags.NumberLike | TypeFlags.BigIntLike | TypeFlags.StringLike + | TypeFlags.EnumLike | TypeFlags.NonPrimitive | TypeFlags.Index) + ) { return left; } @@ -18538,7 +23520,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const types = (left as IntersectionType).types; const lastLeft = types[types.length - 1]; if (isNonGenericObjectType(lastLeft) && isNonGenericObjectType(right)) { - return getIntersectionType(concatenate(types.slice(0, types.length - 1), [getSpreadType(lastLeft, right, symbol, objectFlags, readonly)])); + return getIntersectionType( + concatenate(types.slice(0, types.length - 1), [ + getSpreadType(lastLeft, right, symbol, objectFlags, readonly), + ]), + ); } } return getIntersectionType([left, right]); @@ -18575,7 +23561,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const leftType = getTypeOfSymbol(leftProp); const leftTypeWithoutUndefined = removeMissingOrUndefinedType(leftType); const rightTypeWithoutUndefined = removeMissingOrUndefinedType(rightType); - result.links.type = leftTypeWithoutUndefined === rightTypeWithoutUndefined ? leftType : getUnionType([leftType, rightTypeWithoutUndefined], UnionReduction.Subtype); + result.links.type = leftTypeWithoutUndefined === rightTypeWithoutUndefined ? leftType + : getUnionType([leftType, rightTypeWithoutUndefined], UnionReduction.Subtype); result.links.leftSpread = leftProp; result.links.rightSpread = rightProp; result.declarations = declarations; @@ -18588,16 +23575,23 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } - const spread = createAnonymousType(symbol, members, emptyArray, emptyArray, sameMap(indexInfos, info => getIndexInfoWithReadonly(info, readonly))); - spread.objectFlags |= ObjectFlags.ObjectLiteral | ObjectFlags.ContainsObjectOrArrayLiteral | ObjectFlags.ContainsSpread | objectFlags; + const spread = createAnonymousType( + symbol, + members, + emptyArray, + emptyArray, + sameMap(indexInfos, info => getIndexInfoWithReadonly(info, readonly)), + ); + spread.objectFlags |= ObjectFlags.ObjectLiteral | ObjectFlags.ContainsObjectOrArrayLiteral + | ObjectFlags.ContainsSpread | objectFlags; return spread; } /** We approximate own properties as non-methods plus methods that are inside the object literal */ function isSpreadableProperty(prop: Symbol): boolean { - return !some(prop.declarations, isPrivateIdentifierClassElementDeclaration) && - (!(prop.flags & (SymbolFlags.Method | SymbolFlags.GetAccessor | SymbolFlags.SetAccessor)) || - !prop.declarations?.some(decl => isClassLike(decl.parent))); + return !some(prop.declarations, isPrivateIdentifierClassElementDeclaration) + && (!(prop.flags & (SymbolFlags.Method | SymbolFlags.GetAccessor | SymbolFlags.SetAccessor)) + || !prop.declarations?.some(decl => isClassLike(decl.parent))); } function getSpreadSymbol(prop: Symbol, readonly: boolean) { @@ -18606,7 +23600,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return prop; } const flags = SymbolFlags.Property | (prop.flags & SymbolFlags.Optional); - const result = createSymbol(flags, prop.escapedName, getIsLateCheckFlag(prop) | (readonly ? CheckFlags.Readonly : 0)); + const result = createSymbol( + flags, + prop.escapedName, + getIsLateCheckFlag(prop) | (readonly ? CheckFlags.Readonly : 0), + ); result.links.type = isSetonlyAccessor ? undefinedType : getTypeOfSymbol(prop); result.declarations = prop.declarations; result.links.nameType = getSymbolLinks(prop).nameType; @@ -18615,10 +23613,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function getIndexInfoWithReadonly(info: IndexInfo, readonly: boolean) { - return info.isReadonly !== readonly ? createIndexInfo(info.keyType, info.type, readonly, info.declaration) : info; + return info.isReadonly !== readonly ? createIndexInfo(info.keyType, info.type, readonly, info.declaration) + : info; } - function createLiteralType(flags: TypeFlags, value: string | number | PseudoBigInt, symbol?: Symbol, regularType?: LiteralType) { + function createLiteralType( + flags: TypeFlags, + value: string | number | PseudoBigInt, + symbol?: Symbol, + regularType?: LiteralType, + ) { const type = createTypeWithSymbol(flags, symbol!) as LiteralType; type.value = value; type.regularType = regularType || type; @@ -18628,7 +23632,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function getFreshTypeOfLiteralType(type: Type): Type { if (type.flags & TypeFlags.Freshable) { if (!(type as FreshableType).freshType) { - const freshType = createLiteralType(type.flags, (type as LiteralType).value, (type as LiteralType).symbol, type as LiteralType); + const freshType = createLiteralType( + type.flags, + (type as LiteralType).value, + (type as LiteralType).symbol, + type as LiteralType, + ); freshType.freshType = freshType; (type as FreshableType).freshType = freshType; } @@ -18638,9 +23647,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function getRegularTypeOfLiteralType(type: Type): Type { - return type.flags & TypeFlags.Freshable ? (type as FreshableType).regularType : - type.flags & TypeFlags.Union ? ((type as UnionType).regularType || ((type as UnionType).regularType = mapType(type, getRegularTypeOfLiteralType) as UnionType)) : - type; + return type.flags & TypeFlags.Freshable ? (type as FreshableType).regularType + : type.flags & TypeFlags.Union + ? ((type as UnionType).regularType + || ((type as UnionType).regularType = mapType(type, getRegularTypeOfLiteralType) as UnionType)) + : type; } function isFreshLiteralType(type: Type) { @@ -18649,29 +23660,42 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function getStringLiteralType(value: string): StringLiteralType { let type; - return stringLiteralTypes.get(value) || - (stringLiteralTypes.set(value, type = createLiteralType(TypeFlags.StringLiteral, value) as StringLiteralType), type); + return stringLiteralTypes.get(value) + || (stringLiteralTypes.set( + value, + type = createLiteralType(TypeFlags.StringLiteral, value) as StringLiteralType, + ), + type); } function getNumberLiteralType(value: number): NumberLiteralType { let type; - return numberLiteralTypes.get(value) || - (numberLiteralTypes.set(value, type = createLiteralType(TypeFlags.NumberLiteral, value) as NumberLiteralType), type); + return numberLiteralTypes.get(value) + || (numberLiteralTypes.set( + value, + type = createLiteralType(TypeFlags.NumberLiteral, value) as NumberLiteralType, + ), + type); } function getBigIntLiteralType(value: PseudoBigInt): BigIntLiteralType { let type; const key = pseudoBigIntToString(value); - return bigIntLiteralTypes.get(key) || - (bigIntLiteralTypes.set(key, type = createLiteralType(TypeFlags.BigIntLiteral, value) as BigIntLiteralType), type); + return bigIntLiteralTypes.get(key) + || (bigIntLiteralTypes.set( + key, + type = createLiteralType(TypeFlags.BigIntLiteral, value) as BigIntLiteralType, + ), + type); } function getEnumLiteralType(value: string | number, enumId: number, symbol: Symbol): LiteralType { let type; const key = `${enumId}${typeof value === "string" ? "@" : "#"}${value}`; - const flags = TypeFlags.EnumLiteral | (typeof value === "string" ? TypeFlags.StringLiteral : TypeFlags.NumberLiteral); - return enumLiteralTypes.get(key) || - (enumLiteralTypes.set(key, type = createLiteralType(flags, value, symbol)), type); + const flags = TypeFlags.EnumLiteral + | (typeof value === "string" ? TypeFlags.StringLiteral : TypeFlags.NumberLiteral); + return enumLiteralTypes.get(key) + || (enumLiteralTypes.set(key, type = createLiteralType(flags, value, symbol)), type); } function getTypeFromLiteralTypeNode(node: LiteralTypeNode): Type { @@ -18693,7 +23717,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function getESSymbolLikeTypeForNode(node: Node) { if (isValidESSymbolDeclaration(node)) { - const symbol = isCommonJsExportPropertyAssignment(node) ? getSymbolOfNode((node as BinaryExpression).left) : getSymbolOfNode(node); + const symbol = isCommonJsExportPropertyAssignment(node) ? getSymbolOfNode((node as BinaryExpression).left) + : getSymbolOfNode(node); if (symbol) { const links = getSymbolLinks(symbol); return links.uniqueESSymbolType || (links.uniqueESSymbolType = createUniqueESSymbolType(symbol)); @@ -18703,25 +23728,37 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function getThisType(node: Node): Type { - const container = getThisContainer(node, /*includeArrowFunctions*/ false, /*includeClassComputedPropertyName*/ false); + const container = getThisContainer( + node, + /*includeArrowFunctions*/ false, + /*includeClassComputedPropertyName*/ false, + ); const parent = container && container.parent; if (parent && (isClassLike(parent) || parent.kind === SyntaxKind.InterfaceDeclaration)) { if ( - !isStatic(container) && - (!isConstructorDeclaration(container) || isNodeDescendantOf(node, container.body)) + !isStatic(container) + && (!isConstructorDeclaration(container) || isNodeDescendantOf(node, container.body)) ) { - return getDeclaredTypeOfClassOrInterface(getSymbolOfDeclaration(parent as ClassLikeDeclaration | InterfaceDeclaration)).thisType!; + return getDeclaredTypeOfClassOrInterface( + getSymbolOfDeclaration(parent as ClassLikeDeclaration | InterfaceDeclaration), + ).thisType!; } } // inside x.prototype = { ... } - if (parent && isObjectLiteralExpression(parent) && isBinaryExpression(parent.parent) && getAssignmentDeclarationKind(parent.parent) === AssignmentDeclarationKind.Prototype) { + if ( + parent && isObjectLiteralExpression(parent) && isBinaryExpression(parent.parent) + && getAssignmentDeclarationKind(parent.parent) === AssignmentDeclarationKind.Prototype + ) { return getDeclaredTypeOfClassOrInterface(getSymbolOfNode(parent.parent.left)!.parent!).thisType!; } // /** @return {this} */ // x.prototype.m = function() { ... } const host = node.flags & NodeFlags.JSDoc ? getHostSignatureFromJSDoc(node) : undefined; - if (host && isFunctionExpression(host) && isBinaryExpression(host.parent) && getAssignmentDeclarationKind(host.parent) === AssignmentDeclarationKind.PrototypeProperty) { + if ( + host && isFunctionExpression(host) && isBinaryExpression(host.parent) + && getAssignmentDeclarationKind(host.parent) === AssignmentDeclarationKind.PrototypeProperty + ) { return getDeclaredTypeOfClassOrInterface(getSymbolOfNode(host.parent.left)!.parent!).thisType!; } // inside constructor function C() { ... } @@ -18751,7 +23788,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { case SyntaxKind.TupleType: if ((node as TupleTypeNode).elements.length === 1) { node = (node as TupleTypeNode).elements[0]; - if (node.kind === SyntaxKind.RestType || node.kind === SyntaxKind.NamedTupleMember && (node as NamedTupleMember).dotDotDotToken) { + if ( + node.kind === SyntaxKind.RestType + || node.kind === SyntaxKind.NamedTupleMember && (node as NamedTupleMember).dotDotDotToken + ) { return getArrayElementTypeNode((node as RestTypeNode | NamedTupleMember).type); } } @@ -18764,8 +23804,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function getTypeFromNamedTupleTypeNode(node: NamedTupleMember): Type { const links = getNodeLinks(node); - return links.resolvedType || (links.resolvedType = node.dotDotDotToken ? getTypeFromRestTypeNode(node) : - addOptionality(getTypeFromTypeNode(node.type), /*isProperty*/ true, !!node.questionToken)); + return links.resolvedType || (links.resolvedType = node.dotDotDotToken ? getTypeFromRestTypeNode(node) + : addOptionality(getTypeFromTypeNode(node.type), /*isProperty*/ true, !!node.questionToken)); } function getTypeFromTypeNode(node: TypeNode): Type { @@ -18835,7 +23875,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { case SyntaxKind.ParenthesizedType: case SyntaxKind.JSDocNonNullableType: case SyntaxKind.JSDocTypeExpression: - return getTypeFromTypeNode((node as ParenthesizedTypeNode | JSDocTypeReferencingNode | JSDocTypeExpression | NamedTupleMember).type); + return getTypeFromTypeNode( + (node as ParenthesizedTypeNode | JSDocTypeReferencingNode | JSDocTypeExpression | NamedTupleMember) + .type, + ); case SyntaxKind.RestType: return getTypeFromRestTypeNode(node as RestTypeNode); case SyntaxKind.JSDocVariadicType: @@ -18846,7 +23889,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { case SyntaxKind.JSDocTypeLiteral: case SyntaxKind.JSDocFunctionType: case SyntaxKind.JSDocSignature: - return getTypeFromTypeLiteralOrFunctionOrConstructorTypeNode(node as TypeLiteralNode | FunctionOrConstructorTypeNode | JSDocTypeLiteral | JSDocFunctionType | JSDocSignature); + return getTypeFromTypeLiteralOrFunctionOrConstructorTypeNode( + node as + | TypeLiteralNode + | FunctionOrConstructorTypeNode + | JSDocTypeLiteral + | JSDocFunctionType + | JSDocSignature, + ); case SyntaxKind.TypeOperator: return getTypeFromTypeOperatorNode(node as TypeOperatorNode); case SyntaxKind.IndexedAccessType: @@ -18874,9 +23924,21 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } - function instantiateList(items: readonly T[], mapper: TypeMapper, instantiator: (item: T, mapper: TypeMapper) => T): readonly T[]; - function instantiateList(items: readonly T[] | undefined, mapper: TypeMapper, instantiator: (item: T, mapper: TypeMapper) => T): readonly T[] | undefined; - function instantiateList(items: readonly T[] | undefined, mapper: TypeMapper, instantiator: (item: T, mapper: TypeMapper) => T): readonly T[] | undefined { + function instantiateList( + items: readonly T[], + mapper: TypeMapper, + instantiator: (item: T, mapper: TypeMapper) => T, + ): readonly T[]; + function instantiateList( + items: readonly T[] | undefined, + mapper: TypeMapper, + instantiator: (item: T, mapper: TypeMapper) => T, + ): readonly T[] | undefined; + function instantiateList( + items: readonly T[] | undefined, + mapper: TypeMapper, + instantiator: (item: T, mapper: TypeMapper) => T, + ): readonly T[] | undefined { if (items && items.length) { for (let i = 0; i < items.length; i++) { const item = items[i]; @@ -18909,7 +23971,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function createTypeMapper(sources: readonly TypeParameter[], targets: readonly Type[] | undefined): TypeMapper { - return sources.length === 1 ? makeUnaryTypeMapper(sources[0], targets ? targets[0] : anyType) : makeArrayTypeMapper(sources, targets); + return sources.length === 1 ? makeUnaryTypeMapper(sources[0], targets ? targets[0] : anyType) + : makeArrayTypeMapper(sources, targets); } function getMappedType(type: Type, mapper: TypeMapper): Type { @@ -18941,7 +24004,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { case TypeMapKind.Composite: case TypeMapKind.Merged: const t1 = getMappedType(type, mapper.mapper1); - return t1 !== type && mapper.kind === TypeMapKind.Composite ? instantiateType(t1, mapper.mapper2) : getMappedType(t1, mapper.mapper2); + return t1 !== type && mapper.kind === TypeMapKind.Composite ? instantiateType(t1, mapper.mapper2) + : getMappedType(t1, mapper.mapper2); } } @@ -18954,14 +24018,22 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function makeFunctionTypeMapper(func: (t: Type) => Type, debugInfo: () => string): TypeMapper { - return Debug.attachDebugPrototypeIfDebug({ kind: TypeMapKind.Function, func, debugInfo: Debug.isDebugging ? debugInfo : undefined }); + return Debug.attachDebugPrototypeIfDebug({ + kind: TypeMapKind.Function, + func, + debugInfo: Debug.isDebugging ? debugInfo : undefined, + }); } function makeDeferredTypeMapper(sources: readonly TypeParameter[], targets: (() => Type)[]) { return Debug.attachDebugPrototypeIfDebug({ kind: TypeMapKind.Deferred, sources, targets }); } - function makeCompositeTypeMapper(kind: TypeMapKind.Composite | TypeMapKind.Merged, mapper1: TypeMapper, mapper2: TypeMapper): TypeMapper { + function makeCompositeTypeMapper( + kind: TypeMapKind.Composite | TypeMapKind.Merged, + mapper1: TypeMapper, + mapper2: TypeMapper, + ): TypeMapper { return Debug.attachDebugPrototypeIfDebug({ kind, mapper1, mapper2 }); } @@ -18975,7 +24047,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { */ function createBackreferenceMapper(context: InferenceContext, index: number): TypeMapper { const forwardInferences = context.inferences.slice(index); - return createTypeMapper(map(forwardInferences, i => i.typeParameter), map(forwardInferences, () => unknownType)); + return createTypeMapper( + map(forwardInferences, i => i.typeParameter), + map(forwardInferences, () => unknownType), + ); } function combineTypeMappers(mapper1: TypeMapper | undefined, mapper2: TypeMapper): TypeMapper { @@ -18987,17 +24062,22 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function prependTypeMapping(source: Type, target: Type, mapper: TypeMapper | undefined) { - return !mapper ? makeUnaryTypeMapper(source, target) : makeCompositeTypeMapper(TypeMapKind.Merged, makeUnaryTypeMapper(source, target), mapper); + return !mapper ? makeUnaryTypeMapper(source, target) + : makeCompositeTypeMapper(TypeMapKind.Merged, makeUnaryTypeMapper(source, target), mapper); } function appendTypeMapping(mapper: TypeMapper | undefined, source: Type, target: Type) { - return !mapper ? makeUnaryTypeMapper(source, target) : makeCompositeTypeMapper(TypeMapKind.Merged, mapper, makeUnaryTypeMapper(source, target)); + return !mapper ? makeUnaryTypeMapper(source, target) + : makeCompositeTypeMapper(TypeMapKind.Merged, mapper, makeUnaryTypeMapper(source, target)); } function getRestrictiveTypeParameter(tp: TypeParameter) { - return !tp.constraint && !getConstraintDeclaration(tp) || tp.constraint === noConstraintType ? tp : tp.restrictiveInstantiation || ( - tp.restrictiveInstantiation = createTypeParameter(tp.symbol), (tp.restrictiveInstantiation as TypeParameter).constraint = noConstraintType, tp.restrictiveInstantiation - ); + return !tp.constraint && !getConstraintDeclaration(tp) || tp.constraint === noConstraintType ? tp + : tp.restrictiveInstantiation || ( + tp.restrictiveInstantiation = createTypeParameter(tp.symbol), + (tp.restrictiveInstantiation as TypeParameter).constraint = noConstraintType, + tp.restrictiveInstantiation + ); } function cloneTypeParameter(typeParameter: TypeParameter): TypeParameter { @@ -19007,7 +24087,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function instantiateTypePredicate(predicate: TypePredicate, mapper: TypeMapper): TypePredicate { - return createTypePredicate(predicate.kind, predicate.parameterName, predicate.parameterIndex, instantiateType(predicate.type, mapper)); + return createTypePredicate( + predicate.kind, + predicate.parameterName, + predicate.parameterIndex, + instantiateType(predicate.type, mapper), + ); } function instantiateSignature(signature: Signature, mapper: TypeMapper, eraseTypeParameters?: boolean): Signature { @@ -19025,7 +24110,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // Don't compute resolvedReturnType and resolvedTypePredicate now, // because using `mapper` now could trigger inferences to become fixed. (See `createInferenceContext`.) // See GH#17600. - const result = createSignature(signature.declaration, freshTypeParameters, signature.thisParameter && instantiateSymbol(signature.thisParameter, mapper), instantiateList(signature.parameters, mapper, instantiateSymbol), /*resolvedReturnType*/ undefined, /*resolvedTypePredicate*/ undefined, signature.minArgumentCount, signature.flags & SignatureFlags.PropagatingFlags); + const result = createSignature( + signature.declaration, + freshTypeParameters, + signature.thisParameter && instantiateSymbol(signature.thisParameter, mapper), + instantiateList(signature.parameters, mapper, instantiateSymbol), + /*resolvedReturnType*/ undefined, + /*resolvedTypePredicate*/ undefined, + signature.minArgumentCount, + signature.flags & SignatureFlags.PropagatingFlags, + ); result.target = signature; result.mapper = mapper; return result; @@ -19047,7 +24141,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } // Keep the flags from the symbol we're instantiating. Mark that is instantiated, and // also transient so that we can just store data on it directly. - const result = createSymbol(symbol.flags, symbol.escapedName, CheckFlags.Instantiated | getCheckFlags(symbol) & (CheckFlags.Readonly | CheckFlags.Late | CheckFlags.OptionalParameter | CheckFlags.RestParameter)); + const result = createSymbol( + symbol.flags, + symbol.escapedName, + CheckFlags.Instantiated + | getCheckFlags(symbol) + & (CheckFlags.Readonly | CheckFlags.Late | CheckFlags.OptionalParameter | CheckFlags.RestParameter), + ); result.declarations = symbol.declarations; result.parent = symbol.parent; result.links.target = symbol; @@ -19061,13 +24161,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return result; } - function getObjectTypeInstantiation(type: AnonymousType | DeferredTypeReference, mapper: TypeMapper, aliasSymbol?: Symbol, aliasTypeArguments?: readonly Type[]) { - const declaration = type.objectFlags & ObjectFlags.Reference ? (type as TypeReference).node! : - type.objectFlags & ObjectFlags.InstantiationExpressionType ? (type as InstantiationExpressionType).node : - type.symbol.declarations![0]; + function getObjectTypeInstantiation( + type: AnonymousType | DeferredTypeReference, + mapper: TypeMapper, + aliasSymbol?: Symbol, + aliasTypeArguments?: readonly Type[], + ) { + const declaration = type.objectFlags & ObjectFlags.Reference ? (type as TypeReference).node! + : type.objectFlags & ObjectFlags.InstantiationExpressionType ? (type as InstantiationExpressionType).node + : type.symbol.declarations![0]; const links = getNodeLinks(declaration); - const target = type.objectFlags & ObjectFlags.Reference ? links.resolvedType! as DeferredTypeReference : - type.objectFlags & ObjectFlags.Instantiated ? type.target! : type; + const target = type.objectFlags & ObjectFlags.Reference ? links.resolvedType! as DeferredTypeReference + : type.objectFlags & ObjectFlags.Instantiated ? type.target! : type; let typeParameters = links.outerTypeParameters; if (!typeParameters) { // The first time an anonymous type is instantiated we compute and store a list of the type @@ -19076,14 +24181,19 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // set of type parameters to those that are possibly referenced in the literal. let outerTypeParameters = getOuterTypeParameters(declaration, /*includeThisTypes*/ true); if (isJSConstructor(declaration)) { - const templateTagParameters = getTypeParametersFromDeclaration(declaration as DeclarationWithTypeParameters); + const templateTagParameters = getTypeParametersFromDeclaration( + declaration as DeclarationWithTypeParameters, + ); outerTypeParameters = addRange(outerTypeParameters, templateTagParameters); } typeParameters = outerTypeParameters || emptyArray; - const allDeclarations = type.objectFlags & (ObjectFlags.Reference | ObjectFlags.InstantiationExpressionType) ? [declaration] : type.symbol.declarations!; - typeParameters = (target.objectFlags & (ObjectFlags.Reference | ObjectFlags.InstantiationExpressionType) || target.symbol.flags & SymbolFlags.Method || target.symbol.flags & SymbolFlags.TypeLiteral) && !target.aliasTypeArguments ? - filter(typeParameters, tp => some(allDeclarations, d => isTypeParameterPossiblyReferenced(tp, d))) : - typeParameters; + const allDeclarations = type.objectFlags & (ObjectFlags.Reference | ObjectFlags.InstantiationExpressionType) + ? [declaration] : type.symbol.declarations!; + typeParameters = (target.objectFlags & (ObjectFlags.Reference | ObjectFlags.InstantiationExpressionType) + || target.symbol.flags & SymbolFlags.Method || target.symbol.flags & SymbolFlags.TypeLiteral) + && !target.aliasTypeArguments + ? filter(typeParameters, tp => some(allDeclarations, d => isTypeParameterPossiblyReferenced(tp, d))) + : typeParameters; links.outerTypeParameters = typeParameters; } if (typeParameters.length) { @@ -19093,32 +24203,49 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const combinedMapper = combineTypeMappers(type.mapper, mapper); const typeArguments = map(typeParameters, t => getMappedType(t, combinedMapper)); const newAliasSymbol = aliasSymbol || type.aliasSymbol; - const newAliasTypeArguments = aliasSymbol ? aliasTypeArguments : instantiateTypes(type.aliasTypeArguments, mapper); + const newAliasTypeArguments = aliasSymbol ? aliasTypeArguments + : instantiateTypes(type.aliasTypeArguments, mapper); const id = getTypeListId(typeArguments) + getAliasId(newAliasSymbol, newAliasTypeArguments); if (!target.instantiations) { target.instantiations = new Map(); - target.instantiations.set(getTypeListId(typeParameters) + getAliasId(target.aliasSymbol, target.aliasTypeArguments), target); + target.instantiations.set( + getTypeListId(typeParameters) + getAliasId(target.aliasSymbol, target.aliasTypeArguments), + target, + ); } let result = target.instantiations.get(id); if (!result) { const newMapper = createTypeMapper(typeParameters, typeArguments); - result = target.objectFlags & ObjectFlags.Reference ? createDeferredTypeReference((type as DeferredTypeReference).target, (type as DeferredTypeReference).node, newMapper, newAliasSymbol, newAliasTypeArguments) : - target.objectFlags & ObjectFlags.Mapped ? instantiateMappedType(target as MappedType, newMapper, newAliasSymbol, newAliasTypeArguments) : - instantiateAnonymousType(target, newMapper, newAliasSymbol, newAliasTypeArguments); + result = target.objectFlags & ObjectFlags.Reference + ? createDeferredTypeReference( + (type as DeferredTypeReference).target, + (type as DeferredTypeReference).node, + newMapper, + newAliasSymbol, + newAliasTypeArguments, + ) + : target.objectFlags & ObjectFlags.Mapped + ? instantiateMappedType(target as MappedType, newMapper, newAliasSymbol, newAliasTypeArguments) + : instantiateAnonymousType(target, newMapper, newAliasSymbol, newAliasTypeArguments); target.instantiations.set(id, result); // Set cached result early in case we recursively invoke instantiation while eagerly computing type variable visibility below const resultObjectFlags = getObjectFlags(result); - if (result.flags & TypeFlags.ObjectFlagsType && !(resultObjectFlags & ObjectFlags.CouldContainTypeVariablesComputed)) { + if ( + result.flags & TypeFlags.ObjectFlagsType + && !(resultObjectFlags & ObjectFlags.CouldContainTypeVariablesComputed) + ) { const resultCouldContainTypeVariables = some(typeArguments, couldContainTypeVariables); // one of the input type arguments might be or contain the result if (!(getObjectFlags(result) & ObjectFlags.CouldContainTypeVariablesComputed)) { // if `result` is one of the object types we tried to make (it may not be, due to how `instantiateMappedType` works), we can carry forward the type variable containment check from the input type arguments if (resultObjectFlags & (ObjectFlags.Mapped | ObjectFlags.Anonymous | ObjectFlags.Reference)) { - (result as ObjectFlagsType).objectFlags |= ObjectFlags.CouldContainTypeVariablesComputed | (resultCouldContainTypeVariables ? ObjectFlags.CouldContainTypeVariables : 0); + (result as ObjectFlagsType).objectFlags |= ObjectFlags.CouldContainTypeVariablesComputed + | (resultCouldContainTypeVariables ? ObjectFlags.CouldContainTypeVariables : 0); } // If none of the type arguments for the outer type parameters contain type variables, it follows // that the instantiated type doesn't reference type variables. // Intrinsics have `CouldContainTypeVariablesComputed` pre-set, so this should only cover unions and intersections resulting from `instantiateMappedType` else { - (result as ObjectFlagsType).objectFlags |= !resultCouldContainTypeVariables ? ObjectFlags.CouldContainTypeVariablesComputed : 0; + (result as ObjectFlagsType).objectFlags |= !resultCouldContainTypeVariables + ? ObjectFlags.CouldContainTypeVariablesComputed : 0; } } } @@ -19129,8 +24256,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function maybeTypeParameterReference(node: Node) { - return !(node.parent.kind === SyntaxKind.TypeReference && (node.parent as TypeReferenceNode).typeArguments && node === (node.parent as TypeReferenceNode).typeName || - node.parent.kind === SyntaxKind.ImportType && (node.parent as ImportTypeNode).typeArguments && node === (node.parent as ImportTypeNode).qualifier); + return !(node.parent.kind === SyntaxKind.TypeReference && (node.parent as TypeReferenceNode).typeArguments + && node === (node.parent as TypeReferenceNode).typeName + || node.parent.kind === SyntaxKind.ImportType && (node.parent as ImportTypeNode).typeArguments + && node === (node.parent as ImportTypeNode).qualifier); } function isTypeParameterPossiblyReferenced(tp: TypeParameter, node: Node) { @@ -19141,7 +24270,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (tp.symbol && tp.symbol.declarations && tp.symbol.declarations.length === 1) { const container = tp.symbol.declarations[0].parent; for (let n = node; n !== container; n = n.parent) { - if (!n || n.kind === SyntaxKind.Block || n.kind === SyntaxKind.ConditionalType && forEachChild((n as ConditionalTypeNode).extendsType, containsReference)) { + if ( + !n || n.kind === SyntaxKind.Block + || n.kind === SyntaxKind.ConditionalType + && forEachChild((n as ConditionalTypeNode).extendsType, containsReference) + ) { return true; } } @@ -19153,29 +24286,33 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { case SyntaxKind.ThisType: return !!tp.isThisType; case SyntaxKind.Identifier: - return !tp.isThisType && isPartOfTypeNode(node) && maybeTypeParameterReference(node) && - getTypeFromTypeNodeWorker(node as TypeNode) === tp; // use worker because we're looking for === equality + return !tp.isThisType && isPartOfTypeNode(node) && maybeTypeParameterReference(node) + && getTypeFromTypeNodeWorker(node as TypeNode) === tp; // use worker because we're looking for === equality case SyntaxKind.TypeQuery: const entityName = (node as TypeQueryNode).exprName; const firstIdentifier = getFirstIdentifier(entityName); if (!isThisIdentifier(firstIdentifier)) { // Don't attempt to analyze typeof this.xxx const firstIdentifierSymbol = getResolvedSymbol(firstIdentifier); const tpDeclaration = tp.symbol.declarations![0]; // There is exactly one declaration, otherwise `containsReference` is not called - const tpScope = tpDeclaration.kind === SyntaxKind.TypeParameter ? tpDeclaration.parent : // Type parameter is a regular type parameter, e.g. foo - tp.isThisType ? tpDeclaration : // Type parameter is the this type, and its declaration is the class declaration. - undefined; // Type parameter's declaration was unrecognized, e.g. comes from JSDoc annotation. + const tpScope = tpDeclaration.kind === SyntaxKind.TypeParameter ? tpDeclaration.parent // Type parameter is a regular type parameter, e.g. foo + : tp.isThisType ? tpDeclaration // Type parameter is the this type, and its declaration is the class declaration. + : undefined; // Type parameter's declaration was unrecognized, e.g. comes from JSDoc annotation. if (firstIdentifierSymbol.declarations && tpScope) { - return some(firstIdentifierSymbol.declarations, idDecl => isNodeDescendantOf(idDecl, tpScope)) || - some((node as TypeQueryNode).typeArguments, containsReference); + return some( + firstIdentifierSymbol.declarations, + idDecl => isNodeDescendantOf(idDecl, tpScope), + ) + || some((node as TypeQueryNode).typeArguments, containsReference); } } return true; case SyntaxKind.MethodDeclaration: case SyntaxKind.MethodSignature: - return !(node as FunctionLikeDeclaration).type && !!(node as FunctionLikeDeclaration).body || - some((node as FunctionLikeDeclaration).typeParameters, containsReference) || - some((node as FunctionLikeDeclaration).parameters, containsReference) || - !!(node as FunctionLikeDeclaration).type && containsReference((node as FunctionLikeDeclaration).type!); + return !(node as FunctionLikeDeclaration).type && !!(node as FunctionLikeDeclaration).body + || some((node as FunctionLikeDeclaration).typeParameters, containsReference) + || some((node as FunctionLikeDeclaration).parameters, containsReference) + || !!(node as FunctionLikeDeclaration).type + && containsReference((node as FunctionLikeDeclaration).type!); } return !!forEachChild(node, containsReference); } @@ -19192,7 +24329,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return undefined; } - function instantiateMappedType(type: MappedType, mapper: TypeMapper, aliasSymbol?: Symbol, aliasTypeArguments?: readonly Type[]): Type { + function instantiateMappedType( + type: MappedType, + mapper: TypeMapper, + aliasSymbol?: Symbol, + aliasTypeArguments?: readonly Type[], + ): Type { // For a homomorphic mapped type { [P in keyof T]: X }, where T is some type variable, the mapping // operation depends on T as follows: // * If T is a primitive type no mapping is performed and the result is simply T. @@ -19210,20 +24352,38 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return mapTypeWithAlias( getReducedType(mappedTypeVariable), t => { - if (t.flags & (TypeFlags.AnyOrUnknown | TypeFlags.InstantiableNonPrimitive | TypeFlags.Object | TypeFlags.Intersection) && t !== wildcardType && !isErrorType(t)) { + if ( + t.flags + & (TypeFlags.AnyOrUnknown | TypeFlags.InstantiableNonPrimitive | TypeFlags.Object + | TypeFlags.Intersection) && t !== wildcardType && !isErrorType(t) + ) { if (!type.declaration.nameType) { let constraint; if ( - isArrayType(t) || t.flags & TypeFlags.Any && findResolutionCycleStartIndex(typeVariable, TypeSystemPropertyName.ImmediateBaseConstraint) < 0 && - (constraint = getConstraintOfTypeParameter(typeVariable)) && everyType(constraint, isArrayOrTupleType) + isArrayType(t) + || t.flags & TypeFlags.Any + && findResolutionCycleStartIndex( + typeVariable, + TypeSystemPropertyName.ImmediateBaseConstraint, + ) < 0 + && (constraint = getConstraintOfTypeParameter(typeVariable)) + && everyType(constraint, isArrayOrTupleType) ) { - return instantiateMappedArrayType(t, type, prependTypeMapping(typeVariable, t, mapper)); + return instantiateMappedArrayType( + t, + type, + prependTypeMapping(typeVariable, t, mapper), + ); } if (isGenericTupleType(t)) { return instantiateMappedGenericTupleType(t, type, typeVariable, mapper); } if (isTupleType(t)) { - return instantiateMappedTupleType(t, type, prependTypeMapping(typeVariable, t, mapper)); + return instantiateMappedTupleType( + t, + type, + prependTypeMapping(typeVariable, t, mapper), + ); } } return instantiateAnonymousType(type, prependTypeMapping(typeVariable, t, mapper)); @@ -19236,23 +24396,30 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } // If the constraint type of the instantiation is the wildcard type, return the wildcard type. - return instantiateType(getConstraintTypeFromMappedType(type), mapper) === wildcardType ? wildcardType : instantiateAnonymousType(type, mapper, aliasSymbol, aliasTypeArguments); + return instantiateType(getConstraintTypeFromMappedType(type), mapper) === wildcardType ? wildcardType + : instantiateAnonymousType(type, mapper, aliasSymbol, aliasTypeArguments); } function getModifiedReadonlyState(state: boolean, modifiers: MappedTypeModifiers) { - return modifiers & MappedTypeModifiers.IncludeReadonly ? true : modifiers & MappedTypeModifiers.ExcludeReadonly ? false : state; + return modifiers & MappedTypeModifiers.IncludeReadonly ? true + : modifiers & MappedTypeModifiers.ExcludeReadonly ? false : state; } - function instantiateMappedGenericTupleType(tupleType: TupleTypeReference, mappedType: MappedType, typeVariable: TypeVariable, mapper: TypeMapper) { + function instantiateMappedGenericTupleType( + tupleType: TupleTypeReference, + mappedType: MappedType, + typeVariable: TypeVariable, + mapper: TypeMapper, + ) { // When a tuple type is generic (i.e. when it contains variadic elements), we want to eagerly map the // non-generic elements and defer mapping the generic elements. In order to facilitate this, we transform // M<[A, B?, ...T, ...C[]] into [...M<[A]>, ...M<[B?]>, ...M, ...M] and then rely on tuple type // normalization to resolve the non-generic parts of the resulting tuple. const elementFlags = tupleType.target.elementFlags; const elementTypes = map(getElementTypes(tupleType), (t, i) => { - const singleton = elementFlags[i] & ElementFlags.Variadic ? t : - elementFlags[i] & ElementFlags.Rest ? createArrayType(t) : - createTupleType([t], [elementFlags[i]]); + const singleton = elementFlags[i] & ElementFlags.Variadic ? t + : elementFlags[i] & ElementFlags.Rest ? createArrayType(t) + : createTupleType([t], [elementFlags[i]]); // avoid infinite recursion, if the singleton is the type variable itself // then we'd just get back here with the same arguments from within instantiateMappedType if (singleton === typeVariable) { @@ -19267,33 +24434,67 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function instantiateMappedArrayType(arrayType: Type, mappedType: MappedType, mapper: TypeMapper) { const elementType = instantiateMappedTypeTemplate(mappedType, numberType, /*isOptional*/ true, mapper); - return isErrorType(elementType) ? errorType : - createArrayType(elementType, getModifiedReadonlyState(isReadonlyArrayType(arrayType), getMappedTypeModifiers(mappedType))); + return isErrorType(elementType) ? errorType + : createArrayType( + elementType, + getModifiedReadonlyState(isReadonlyArrayType(arrayType), getMappedTypeModifiers(mappedType)), + ); } function instantiateMappedTupleType(tupleType: TupleTypeReference, mappedType: MappedType, mapper: TypeMapper) { const elementFlags = tupleType.target.elementFlags; - const elementTypes = map(getElementTypes(tupleType), (_, i) => instantiateMappedTypeTemplate(mappedType, getStringLiteralType("" + i), !!(elementFlags[i] & ElementFlags.Optional), mapper)); + const elementTypes = map( + getElementTypes(tupleType), + (_, i) => + instantiateMappedTypeTemplate( + mappedType, + getStringLiteralType("" + i), + !!(elementFlags[i] & ElementFlags.Optional), + mapper, + ), + ); const modifiers = getMappedTypeModifiers(mappedType); - const newTupleModifiers = modifiers & MappedTypeModifiers.IncludeOptional ? map(elementFlags, f => f & ElementFlags.Required ? ElementFlags.Optional : f) : - modifiers & MappedTypeModifiers.ExcludeOptional ? map(elementFlags, f => f & ElementFlags.Optional ? ElementFlags.Required : f) : - elementFlags; + const newTupleModifiers = modifiers & MappedTypeModifiers.IncludeOptional + ? map(elementFlags, f => f & ElementFlags.Required ? ElementFlags.Optional : f) + : modifiers & MappedTypeModifiers.ExcludeOptional + ? map(elementFlags, f => f & ElementFlags.Optional ? ElementFlags.Required : f) + : elementFlags; const newReadonly = getModifiedReadonlyState(tupleType.target.readonly, modifiers); - return contains(elementTypes, errorType) ? errorType : - createTupleType(elementTypes, newTupleModifiers, newReadonly, tupleType.target.labeledElementDeclarations); + return contains(elementTypes, errorType) ? errorType + : createTupleType( + elementTypes, + newTupleModifiers, + newReadonly, + tupleType.target.labeledElementDeclarations, + ); } function instantiateMappedTypeTemplate(type: MappedType, key: Type, isOptional: boolean, mapper: TypeMapper) { const templateMapper = appendTypeMapping(mapper, getTypeParameterFromMappedType(type), key); - const propType = instantiateType(getTemplateTypeFromMappedType(type.target as MappedType || type), templateMapper); + const propType = instantiateType( + getTemplateTypeFromMappedType(type.target as MappedType || type), + templateMapper, + ); const modifiers = getMappedTypeModifiers(type); - return strictNullChecks && modifiers & MappedTypeModifiers.IncludeOptional && !maybeTypeOfKind(propType, TypeFlags.Undefined | TypeFlags.Void) ? getOptionalType(propType, /*isProperty*/ true) : - strictNullChecks && modifiers & MappedTypeModifiers.ExcludeOptional && isOptional ? getTypeWithFacts(propType, TypeFacts.NEUndefined) : - propType; - } - - function instantiateAnonymousType(type: AnonymousType, mapper: TypeMapper, aliasSymbol?: Symbol, aliasTypeArguments?: readonly Type[]): AnonymousType { - const result = createObjectType(type.objectFlags & ~(ObjectFlags.CouldContainTypeVariablesComputed | ObjectFlags.CouldContainTypeVariables) | ObjectFlags.Instantiated, type.symbol) as AnonymousType; + return strictNullChecks && modifiers & MappedTypeModifiers.IncludeOptional + && !maybeTypeOfKind(propType, TypeFlags.Undefined | TypeFlags.Void) + ? getOptionalType(propType, /*isProperty*/ true) + : strictNullChecks && modifiers & MappedTypeModifiers.ExcludeOptional && isOptional + ? getTypeWithFacts(propType, TypeFacts.NEUndefined) + : propType; + } + + function instantiateAnonymousType( + type: AnonymousType, + mapper: TypeMapper, + aliasSymbol?: Symbol, + aliasTypeArguments?: readonly Type[], + ): AnonymousType { + const result = createObjectType( + type.objectFlags & ~(ObjectFlags.CouldContainTypeVariablesComputed | ObjectFlags.CouldContainTypeVariables) + | ObjectFlags.Instantiated, + type.symbol, + ) as AnonymousType; if (type.objectFlags & ObjectFlags.Mapped) { (result as MappedType).declaration = (type as MappedType).declaration; // C.f. instantiateSignature @@ -19309,12 +24510,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { result.target = type; result.mapper = mapper; result.aliasSymbol = aliasSymbol || type.aliasSymbol; - result.aliasTypeArguments = aliasSymbol ? aliasTypeArguments : instantiateTypes(type.aliasTypeArguments, mapper); + result.aliasTypeArguments = aliasSymbol ? aliasTypeArguments + : instantiateTypes(type.aliasTypeArguments, mapper); result.objectFlags |= result.aliasTypeArguments ? getPropagatingFlagsOfTypes(result.aliasTypeArguments) : 0; return result; } - function getConditionalTypeInstantiation(type: ConditionalType, mapper: TypeMapper, aliasSymbol?: Symbol, aliasTypeArguments?: readonly Type[]): Type { + function getConditionalTypeInstantiation( + type: ConditionalType, + mapper: TypeMapper, + aliasSymbol?: Symbol, + aliasTypeArguments?: readonly Type[], + ): Type { const root = type.root; if (root.outerTypeParameters) { // We are instantiating a conditional type that has one or more type parameters in scope. Apply the @@ -19330,9 +24537,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // Distributive conditional types are distributed over union types. For example, when the // distributive conditional type T extends U ? X : Y is instantiated with A | B for T, the // result is (A extends U ? X : Y) | (B extends U ? X : Y). - result = distributionType && checkType !== distributionType && distributionType.flags & (TypeFlags.Union | TypeFlags.Never) ? - mapTypeWithAlias(getReducedType(distributionType), t => getConditionalType(root, prependTypeMapping(checkType, t, newMapper)), aliasSymbol, aliasTypeArguments) : - getConditionalType(root, newMapper, aliasSymbol, aliasTypeArguments); + result = distributionType && checkType !== distributionType + && distributionType.flags & (TypeFlags.Union | TypeFlags.Never) + ? mapTypeWithAlias( + getReducedType(distributionType), + t => getConditionalType(root, prependTypeMapping(checkType, t, newMapper)), + aliasSymbol, + aliasTypeArguments, + ) + : getConditionalType(root, newMapper, aliasSymbol, aliasTypeArguments); root.instantiations!.set(id, result); } return result; @@ -19343,10 +24556,17 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function instantiateType(type: Type, mapper: TypeMapper | undefined): Type; function instantiateType(type: Type | undefined, mapper: TypeMapper | undefined): Type | undefined; function instantiateType(type: Type | undefined, mapper: TypeMapper | undefined): Type | undefined { - return type && mapper ? instantiateTypeWithAlias(type, mapper, /*aliasSymbol*/ undefined, /*aliasTypeArguments*/ undefined) : type; + return type && mapper + ? instantiateTypeWithAlias(type, mapper, /*aliasSymbol*/ undefined, /*aliasTypeArguments*/ undefined) + : type; } - function instantiateTypeWithAlias(type: Type, mapper: TypeMapper, aliasSymbol: Symbol | undefined, aliasTypeArguments: readonly Type[] | undefined): Type { + function instantiateTypeWithAlias( + type: Type, + mapper: TypeMapper, + aliasSymbol: Symbol | undefined, + aliasTypeArguments: readonly Type[] | undefined, + ): Type { if (!couldContainTypeVariables(type)) { return type; } @@ -19354,7 +24574,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // We have reached 100 recursive type instantiations, or 5M type instantiations caused by the same statement // or expression. There is a very high likelyhood we're dealing with a combination of infinite generic types // that perpetually generate new type identities, so we stop the recursion here by yielding the error type. - tracing?.instant(tracing.Phase.CheckTypes, "instantiateType_DepthLimit", { typeId: type.id, instantiationDepth, instantiationCount }); + tracing?.instant(tracing.Phase.CheckTypes, "instantiateType_DepthLimit", { + typeId: type.id, + instantiationDepth, + instantiationCount, + }); error(currentNode, Diagnostics.Type_instantiation_is_excessively_deep_and_possibly_infinite); return errorType; } @@ -19366,7 +24590,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return result; } - function instantiateTypeWorker(type: Type, mapper: TypeMapper, aliasSymbol: Symbol | undefined, aliasTypeArguments: readonly Type[] | undefined): Type { + function instantiateTypeWorker( + type: Type, + mapper: TypeMapper, + aliasSymbol: Symbol | undefined, + aliasTypeArguments: readonly Type[] | undefined, + ): Type { const flags = type.flags; if (flags & TypeFlags.TypeParameter) { return getMappedType(type, mapper); @@ -19377,44 +24606,71 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (objectFlags & ObjectFlags.Reference && !(type as TypeReference).node) { const resolvedTypeArguments = (type as TypeReference).resolvedTypeArguments; const newTypeArguments = instantiateTypes(resolvedTypeArguments, mapper); - return newTypeArguments !== resolvedTypeArguments ? createNormalizedTypeReference((type as TypeReference).target, newTypeArguments) : type; + return newTypeArguments !== resolvedTypeArguments + ? createNormalizedTypeReference((type as TypeReference).target, newTypeArguments) : type; } if (objectFlags & ObjectFlags.ReverseMapped) { return instantiateReverseMappedType(type as ReverseMappedType, mapper); } - return getObjectTypeInstantiation(type as TypeReference | AnonymousType | MappedType, mapper, aliasSymbol, aliasTypeArguments); + return getObjectTypeInstantiation( + type as TypeReference | AnonymousType | MappedType, + mapper, + aliasSymbol, + aliasTypeArguments, + ); } return type; } if (flags & TypeFlags.UnionOrIntersection) { const origin = type.flags & TypeFlags.Union ? (type as UnionType).origin : undefined; - const types = origin && origin.flags & TypeFlags.UnionOrIntersection ? (origin as UnionOrIntersectionType).types : (type as UnionOrIntersectionType).types; + const types = origin && origin.flags & TypeFlags.UnionOrIntersection + ? (origin as UnionOrIntersectionType).types : (type as UnionOrIntersectionType).types; const newTypes = instantiateTypes(types, mapper); if (newTypes === types && aliasSymbol === type.aliasSymbol) { return type; } const newAliasSymbol = aliasSymbol || type.aliasSymbol; - const newAliasTypeArguments = aliasSymbol ? aliasTypeArguments : instantiateTypes(type.aliasTypeArguments, mapper); - return flags & TypeFlags.Intersection || origin && origin.flags & TypeFlags.Intersection ? - getIntersectionType(newTypes, newAliasSymbol, newAliasTypeArguments) : - getUnionType(newTypes, UnionReduction.Literal, newAliasSymbol, newAliasTypeArguments); + const newAliasTypeArguments = aliasSymbol ? aliasTypeArguments + : instantiateTypes(type.aliasTypeArguments, mapper); + return flags & TypeFlags.Intersection || origin && origin.flags & TypeFlags.Intersection + ? getIntersectionType(newTypes, newAliasSymbol, newAliasTypeArguments) + : getUnionType(newTypes, UnionReduction.Literal, newAliasSymbol, newAliasTypeArguments); } if (flags & TypeFlags.Index) { return getIndexType(instantiateType((type as IndexType).type, mapper)); } if (flags & TypeFlags.TemplateLiteral) { - return getTemplateLiteralType((type as TemplateLiteralType).texts, instantiateTypes((type as TemplateLiteralType).types, mapper)); + return getTemplateLiteralType( + (type as TemplateLiteralType).texts, + instantiateTypes((type as TemplateLiteralType).types, mapper), + ); } if (flags & TypeFlags.StringMapping) { - return getStringMappingType((type as StringMappingType).symbol, instantiateType((type as StringMappingType).type, mapper)); + return getStringMappingType( + (type as StringMappingType).symbol, + instantiateType((type as StringMappingType).type, mapper), + ); } if (flags & TypeFlags.IndexedAccess) { const newAliasSymbol = aliasSymbol || type.aliasSymbol; - const newAliasTypeArguments = aliasSymbol ? aliasTypeArguments : instantiateTypes(type.aliasTypeArguments, mapper); - return getIndexedAccessType(instantiateType((type as IndexedAccessType).objectType, mapper), instantiateType((type as IndexedAccessType).indexType, mapper), (type as IndexedAccessType).accessFlags, /*accessNode*/ undefined, newAliasSymbol, newAliasTypeArguments); + const newAliasTypeArguments = aliasSymbol ? aliasTypeArguments + : instantiateTypes(type.aliasTypeArguments, mapper); + return getIndexedAccessType( + instantiateType((type as IndexedAccessType).objectType, mapper), + instantiateType((type as IndexedAccessType).indexType, mapper), + (type as IndexedAccessType).accessFlags, + /*accessNode*/ undefined, + newAliasSymbol, + newAliasTypeArguments, + ); } if (flags & TypeFlags.Conditional) { - return getConditionalTypeInstantiation(type as ConditionalType, combineTypeMappers((type as ConditionalType).mapper, mapper), aliasSymbol, aliasTypeArguments); + return getConditionalTypeInstantiation( + type as ConditionalType, + combineTypeMappers((type as ConditionalType).mapper, mapper), + aliasSymbol, + aliasTypeArguments, + ); } if (flags & TypeFlags.Substitution) { const newBaseType = instantiateType((type as SubstitutionType).baseType, mapper); @@ -19425,10 +24681,17 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (newBaseType.flags & TypeFlags.TypeVariable && isGenericType(newConstraint)) { return getSubstitutionType(newBaseType, newConstraint); } - if (newConstraint.flags & TypeFlags.AnyOrUnknown || isTypeAssignableTo(getRestrictiveInstantiation(newBaseType), getRestrictiveInstantiation(newConstraint))) { + if ( + newConstraint.flags & TypeFlags.AnyOrUnknown + || isTypeAssignableTo( + getRestrictiveInstantiation(newBaseType), + getRestrictiveInstantiation(newConstraint), + ) + ) { return newBaseType; } - return newBaseType.flags & TypeFlags.TypeVariable ? getSubstitutionType(newBaseType, newConstraint) : getIntersectionType([newConstraint, newBaseType]); + return newBaseType.flags & TypeFlags.TypeVariable ? getSubstitutionType(newBaseType, newConstraint) + : getIntersectionType([newConstraint, newBaseType]); } return type; } @@ -19454,8 +24717,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function getPermissiveInstantiation(type: Type) { - return type.flags & (TypeFlags.Primitive | TypeFlags.AnyOrUnknown | TypeFlags.Never) ? type : - type.permissiveInstantiation || (type.permissiveInstantiation = instantiateType(type, permissiveMapper)); + return type.flags & (TypeFlags.Primitive | TypeFlags.AnyOrUnknown | TypeFlags.Never) ? type + : type.permissiveInstantiation || (type.permissiveInstantiation = instantiateType(type, permissiveMapper)); } function getRestrictiveInstantiation(type: Type) { @@ -19481,30 +24744,37 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // Returns true if the given expression contains (at any level of nesting) a function or arrow expression // that is subject to contextual typing. - function isContextSensitive(node: Expression | MethodDeclaration | ObjectLiteralElementLike | JsxAttributeLike | JsxChild): boolean { + function isContextSensitive( + node: Expression | MethodDeclaration | ObjectLiteralElementLike | JsxAttributeLike | JsxChild, + ): boolean { Debug.assert(node.kind !== SyntaxKind.MethodDeclaration || isObjectLiteralMethod(node)); switch (node.kind) { case SyntaxKind.FunctionExpression: case SyntaxKind.ArrowFunction: case SyntaxKind.MethodDeclaration: case SyntaxKind.FunctionDeclaration: // Function declarations can have context when annotated with a jsdoc @type - return isContextSensitiveFunctionLikeDeclaration(node as FunctionExpression | ArrowFunction | MethodDeclaration); + return isContextSensitiveFunctionLikeDeclaration( + node as FunctionExpression | ArrowFunction | MethodDeclaration, + ); case SyntaxKind.ObjectLiteralExpression: return some((node as ObjectLiteralExpression).properties, isContextSensitive); case SyntaxKind.ArrayLiteralExpression: return some((node as ArrayLiteralExpression).elements, isContextSensitive); case SyntaxKind.ConditionalExpression: - return isContextSensitive((node as ConditionalExpression).whenTrue) || - isContextSensitive((node as ConditionalExpression).whenFalse); + return isContextSensitive((node as ConditionalExpression).whenTrue) + || isContextSensitive((node as ConditionalExpression).whenFalse); case SyntaxKind.BinaryExpression: - return ((node as BinaryExpression).operatorToken.kind === SyntaxKind.BarBarToken || (node as BinaryExpression).operatorToken.kind === SyntaxKind.QuestionQuestionToken) && - (isContextSensitive((node as BinaryExpression).left) || isContextSensitive((node as BinaryExpression).right)); + return ((node as BinaryExpression).operatorToken.kind === SyntaxKind.BarBarToken + || (node as BinaryExpression).operatorToken.kind === SyntaxKind.QuestionQuestionToken) + && (isContextSensitive((node as BinaryExpression).left) + || isContextSensitive((node as BinaryExpression).right)); case SyntaxKind.PropertyAssignment: return isContextSensitive((node as PropertyAssignment).initializer); case SyntaxKind.ParenthesizedExpression: return isContextSensitive((node as ParenthesizedExpression).expression); case SyntaxKind.JsxAttributes: - return some((node as JsxAttributes).properties, isContextSensitive) || isJsxOpeningElement(node.parent) && some(node.parent.parent.children, isContextSensitive); + return some((node as JsxAttributes).properties, isContextSensitive) + || isJsxOpeningElement(node.parent) && some(node.parent.parent.children, isContextSensitive); case SyntaxKind.JsxAttribute: { // If there is no initializer, JSX attribute has a boolean value of true which is not context sensitive. const { initializer } = node as JsxAttribute; @@ -19531,12 +24801,17 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (node.body.kind !== SyntaxKind.Block) { return isContextSensitive(node.body); } - return !!forEachReturnStatement(node.body as Block, statement => !!statement.expression && isContextSensitive(statement.expression)); + return !!forEachReturnStatement( + node.body as Block, + statement => !!statement.expression && isContextSensitive(statement.expression), + ); } - function isContextSensitiveFunctionOrObjectLiteralMethod(func: Node): func is FunctionExpression | ArrowFunction | MethodDeclaration { - return (isFunctionExpressionOrArrowFunction(func) || isObjectLiteralMethod(func)) && - isContextSensitiveFunctionLikeDeclaration(func); + function isContextSensitiveFunctionOrObjectLiteralMethod( + func: Node, + ): func is FunctionExpression | ArrowFunction | MethodDeclaration { + return (isFunctionExpressionOrArrowFunction(func) || isObjectLiteralMethod(func)) + && isContextSensitiveFunctionLikeDeclaration(func); } function getTypeWithoutSignatures(type: Type): Type { @@ -19599,14 +24874,20 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // Note that this check ignores type parameters and only considers the // inheritance hierarchy. function isTypeDerivedFrom(source: Type, target: Type): boolean { - return source.flags & TypeFlags.Union ? every((source as UnionType).types, t => isTypeDerivedFrom(t, target)) : - target.flags & TypeFlags.Union ? some((target as UnionType).types, t => isTypeDerivedFrom(source, t)) : - source.flags & TypeFlags.Intersection ? some((source as IntersectionType).types, t => isTypeDerivedFrom(t, target)) : - source.flags & TypeFlags.InstantiableNonPrimitive ? isTypeDerivedFrom(getBaseConstraintOfType(source) || unknownType, target) : - isEmptyAnonymousObjectType(target) ? !!(source.flags & (TypeFlags.Object | TypeFlags.NonPrimitive)) : - target === globalObjectType ? !!(source.flags & (TypeFlags.Object | TypeFlags.NonPrimitive)) && !isEmptyAnonymousObjectType(source) : - target === globalFunctionType ? !!(source.flags & TypeFlags.Object) && isFunctionObjectType(source as ObjectType) : - hasBaseType(source, getTargetType(target)) || (isArrayType(target) && !isReadonlyArrayType(target) && isTypeDerivedFrom(source, globalReadonlyArrayType)); + return source.flags & TypeFlags.Union ? every((source as UnionType).types, t => isTypeDerivedFrom(t, target)) + : target.flags & TypeFlags.Union ? some((target as UnionType).types, t => isTypeDerivedFrom(source, t)) + : source.flags & TypeFlags.Intersection + ? some((source as IntersectionType).types, t => isTypeDerivedFrom(t, target)) + : source.flags & TypeFlags.InstantiableNonPrimitive + ? isTypeDerivedFrom(getBaseConstraintOfType(source) || unknownType, target) + : isEmptyAnonymousObjectType(target) ? !!(source.flags & (TypeFlags.Object | TypeFlags.NonPrimitive)) + : target === globalObjectType + ? !!(source.flags & (TypeFlags.Object | TypeFlags.NonPrimitive)) && !isEmptyAnonymousObjectType(source) + : target === globalFunctionType + ? !!(source.flags & TypeFlags.Object) && isFunctionObjectType(source as ObjectType) + : hasBaseType(source, getTargetType(target)) + || (isArrayType(target) && !isReadonlyArrayType(target) + && isTypeDerivedFrom(source, globalReadonlyArrayType)); } /** @@ -19627,16 +24908,47 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return isTypeComparableTo(type1, type2) || isTypeComparableTo(type2, type1); } - function checkTypeAssignableTo(source: Type, target: Type, errorNode: Node | undefined, headMessage?: DiagnosticMessage, containingMessageChain?: () => DiagnosticMessageChain | undefined, errorOutputObject?: { errors?: Diagnostic[]; }): boolean { - return checkTypeRelatedTo(source, target, assignableRelation, errorNode, headMessage, containingMessageChain, errorOutputObject); + function checkTypeAssignableTo( + source: Type, + target: Type, + errorNode: Node | undefined, + headMessage?: DiagnosticMessage, + containingMessageChain?: () => DiagnosticMessageChain | undefined, + errorOutputObject?: { errors?: Diagnostic[]; }, + ): boolean { + return checkTypeRelatedTo( + source, + target, + assignableRelation, + errorNode, + headMessage, + containingMessageChain, + errorOutputObject, + ); } /** * Like `checkTypeAssignableTo`, but if it would issue an error, instead performs structural comparisons of the types using the given expression node to * attempt to issue more specific errors on, for example, specific object literal properties or tuple members. */ - function checkTypeAssignableToAndOptionallyElaborate(source: Type, target: Type, errorNode: Node | undefined, expr: Expression | undefined, headMessage?: DiagnosticMessage, containingMessageChain?: () => DiagnosticMessageChain | undefined): boolean { - return checkTypeRelatedToAndOptionallyElaborate(source, target, assignableRelation, errorNode, expr, headMessage, containingMessageChain, /*errorOutputContainer*/ undefined); + function checkTypeAssignableToAndOptionallyElaborate( + source: Type, + target: Type, + errorNode: Node | undefined, + expr: Expression | undefined, + headMessage?: DiagnosticMessage, + containingMessageChain?: () => DiagnosticMessageChain | undefined, + ): boolean { + return checkTypeRelatedToAndOptionallyElaborate( + source, + target, + assignableRelation, + errorNode, + expr, + headMessage, + containingMessageChain, + /*errorOutputContainer*/ undefined, + ); } function checkTypeRelatedToAndOptionallyElaborate( @@ -19650,14 +24962,35 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { errorOutputContainer: { errors?: Diagnostic[]; skipLogging?: boolean; } | undefined, ): boolean { if (isTypeRelatedTo(source, target, relation)) return true; - if (!errorNode || !elaborateError(expr, source, target, relation, headMessage, containingMessageChain, errorOutputContainer)) { - return checkTypeRelatedTo(source, target, relation, errorNode, headMessage, containingMessageChain, errorOutputContainer); + if ( + !errorNode + || !elaborateError( + expr, + source, + target, + relation, + headMessage, + containingMessageChain, + errorOutputContainer, + ) + ) { + return checkTypeRelatedTo( + source, + target, + relation, + errorNode, + headMessage, + containingMessageChain, + errorOutputContainer, + ); } return false; } function isOrHasGenericConditional(type: Type): boolean { - return !!(type.flags & TypeFlags.Conditional || (type.flags & TypeFlags.Intersection && some((type as IntersectionType).types, isOrHasGenericConditional))); + return !!(type.flags & TypeFlags.Conditional + || (type.flags & TypeFlags.Intersection + && some((type as IntersectionType).types, isOrHasGenericConditional))); } function elaborateError( @@ -19672,7 +25005,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (!node || isOrHasGenericConditional(target)) return false; if ( !checkTypeRelatedTo(source, target, relation, /*errorNode*/ undefined) - && elaborateDidYouMeanToCallOrConstruct(node, source, target, relation, headMessage, containingMessageChain, errorOutputContainer) + && elaborateDidYouMeanToCallOrConstruct( + node, + source, + target, + relation, + headMessage, + containingMessageChain, + errorOutputContainer, + ) ) { return true; } @@ -19684,22 +25025,66 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // fallthrough case SyntaxKind.JsxExpression: case SyntaxKind.ParenthesizedExpression: - return elaborateError((node as AsExpression | ParenthesizedExpression | JsxExpression).expression, source, target, relation, headMessage, containingMessageChain, errorOutputContainer); + return elaborateError( + (node as AsExpression | ParenthesizedExpression | JsxExpression).expression, + source, + target, + relation, + headMessage, + containingMessageChain, + errorOutputContainer, + ); case SyntaxKind.BinaryExpression: switch ((node as BinaryExpression).operatorToken.kind) { case SyntaxKind.EqualsToken: case SyntaxKind.CommaToken: - return elaborateError((node as BinaryExpression).right, source, target, relation, headMessage, containingMessageChain, errorOutputContainer); + return elaborateError( + (node as BinaryExpression).right, + source, + target, + relation, + headMessage, + containingMessageChain, + errorOutputContainer, + ); } break; case SyntaxKind.ObjectLiteralExpression: - return elaborateObjectLiteral(node as ObjectLiteralExpression, source, target, relation, containingMessageChain, errorOutputContainer); + return elaborateObjectLiteral( + node as ObjectLiteralExpression, + source, + target, + relation, + containingMessageChain, + errorOutputContainer, + ); case SyntaxKind.ArrayLiteralExpression: - return elaborateArrayLiteral(node as ArrayLiteralExpression, source, target, relation, containingMessageChain, errorOutputContainer); + return elaborateArrayLiteral( + node as ArrayLiteralExpression, + source, + target, + relation, + containingMessageChain, + errorOutputContainer, + ); case SyntaxKind.JsxAttributes: - return elaborateJsxComponents(node as JsxAttributes, source, target, relation, containingMessageChain, errorOutputContainer); + return elaborateJsxComponents( + node as JsxAttributes, + source, + target, + relation, + containingMessageChain, + errorOutputContainer, + ); case SyntaxKind.ArrowFunction: - return elaborateArrowFunction(node as ArrowFunction, source, target, relation, containingMessageChain, errorOutputContainer); + return elaborateArrowFunction( + node as ArrowFunction, + source, + target, + relation, + containingMessageChain, + errorOutputContainer, + ); } return false; } @@ -19719,7 +25104,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if ( some(signatures, s => { const returnType = getReturnTypeOfSignature(s); - return !(returnType.flags & (TypeFlags.Any | TypeFlags.Never)) && checkTypeRelatedTo(returnType, target, relation, /*errorNode*/ undefined); + return !(returnType.flags & (TypeFlags.Any | TypeFlags.Never)) + && checkTypeRelatedTo(returnType, target, relation, /*errorNode*/ undefined); }) ) { const resultObj: { errors?: Diagnostic[]; } = errorOutputContainer || {}; @@ -19729,7 +25115,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { diagnostic, createDiagnosticForNode( node, - signatures === constructSignatures ? Diagnostics.Did_you_mean_to_use_new_with_this_expression : Diagnostics.Did_you_mean_to_call_this_expression, + signatures === constructSignatures ? Diagnostics.Did_you_mean_to_use_new_with_this_expression + : Diagnostics.Did_you_mean_to_call_this_expression, ), ); return true; @@ -19766,12 +25153,29 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const sourceReturn = getReturnTypeOfSignature(sourceSig); const targetReturn = getUnionType(map(targetSignatures, getReturnTypeOfSignature)); if (!checkTypeRelatedTo(sourceReturn, targetReturn, relation, /*errorNode*/ undefined)) { - const elaborated = returnExpression && elaborateError(returnExpression, sourceReturn, targetReturn, relation, /*headMessage*/ undefined, containingMessageChain, errorOutputContainer); + const elaborated = returnExpression + && elaborateError( + returnExpression, + sourceReturn, + targetReturn, + relation, + /*headMessage*/ undefined, + containingMessageChain, + errorOutputContainer, + ); if (elaborated) { return elaborated; } const resultObj: { errors?: Diagnostic[]; } = errorOutputContainer || {}; - checkTypeRelatedTo(sourceReturn, targetReturn, relation, returnExpression, /*headMessage*/ undefined, containingMessageChain, resultObj); + checkTypeRelatedTo( + sourceReturn, + targetReturn, + relation, + returnExpression, + /*headMessage*/ undefined, + containingMessageChain, + resultObj, + ); if (resultObj.errors) { if (target.symbol && length(target.symbol.declarations)) { addRelatedInfo( @@ -19787,7 +25191,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // exclude cases where source itself is promisy - this way we don't make a suggestion when relating // an IPromise and a Promise that are slightly different && !getTypeOfPropertyOfType(sourceReturn, "then" as __String) - && checkTypeRelatedTo(createPromiseType(sourceReturn), targetReturn, relation, /*errorNode*/ undefined) + && checkTypeRelatedTo( + createPromiseType(sourceReturn), + targetReturn, + relation, + /*errorNode*/ undefined, + ) ) { addRelatedInfo( resultObj.errors[resultObj.errors.length - 1], @@ -19823,7 +25232,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return result; } - type ElaborationIterator = IterableIterator<{ errorNode: Node; innerExpression: Expression | undefined; nameType: Type; errorMessage?: DiagnosticMessage | undefined; }>; + type ElaborationIterator = IterableIterator< + { + errorNode: Node; + innerExpression: Expression | undefined; + nameType: Type; + errorMessage?: DiagnosticMessage | undefined; + } + >; /** * For every element returned from the iterator, checks that element to issue an error on a property of that element's type * If that element would issue an error, we first attempt to dive into that element's inner expression and issue a more specific error by recuring into `elaborateError` @@ -19847,52 +25263,104 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (!sourcePropType) continue; const propName = getPropertyNameFromIndex(nameType, /*accessNode*/ undefined); if (!checkTypeRelatedTo(sourcePropType, targetPropType, relation, /*errorNode*/ undefined)) { - const elaborated = next && elaborateError(next, sourcePropType, targetPropType, relation, /*headMessage*/ undefined, containingMessageChain, errorOutputContainer); + const elaborated = next + && elaborateError( + next, + sourcePropType, + targetPropType, + relation, + /*headMessage*/ undefined, + containingMessageChain, + errorOutputContainer, + ); reportedError = true; if (!elaborated) { // Issue error on the prop itself, since the prop couldn't elaborate the error const resultObj: { errors?: Diagnostic[]; } = errorOutputContainer || {}; // Use the expression type, if available - const specificSource = next ? checkExpressionForMutableLocationWithContextualType(next, sourcePropType) : sourcePropType; + const specificSource = next + ? checkExpressionForMutableLocationWithContextualType(next, sourcePropType) : sourcePropType; if (exactOptionalPropertyTypes && isExactOptionalPropertyMismatch(specificSource, targetPropType)) { - const diag = createDiagnosticForNode(prop, Diagnostics.Type_0_is_not_assignable_to_type_1_with_exactOptionalPropertyTypes_Colon_true_Consider_adding_undefined_to_the_type_of_the_target, typeToString(specificSource), typeToString(targetPropType)); + const diag = createDiagnosticForNode( + prop, + Diagnostics + .Type_0_is_not_assignable_to_type_1_with_exactOptionalPropertyTypes_Colon_true_Consider_adding_undefined_to_the_type_of_the_target, + typeToString(specificSource), + typeToString(targetPropType), + ); diagnostics.add(diag); resultObj.errors = [diag]; } else { - const targetIsOptional = !!(propName && (getPropertyOfType(target, propName) || unknownSymbol).flags & SymbolFlags.Optional); - const sourceIsOptional = !!(propName && (getPropertyOfType(source, propName) || unknownSymbol).flags & SymbolFlags.Optional); + const targetIsOptional = !!(propName + && (getPropertyOfType(target, propName) || unknownSymbol).flags & SymbolFlags.Optional); + const sourceIsOptional = !!(propName + && (getPropertyOfType(source, propName) || unknownSymbol).flags & SymbolFlags.Optional); targetPropType = removeMissingType(targetPropType, targetIsOptional); sourcePropType = removeMissingType(sourcePropType, targetIsOptional && sourceIsOptional); - const result = checkTypeRelatedTo(specificSource, targetPropType, relation, prop, errorMessage, containingMessageChain, resultObj); + const result = checkTypeRelatedTo( + specificSource, + targetPropType, + relation, + prop, + errorMessage, + containingMessageChain, + resultObj, + ); if (result && specificSource !== sourcePropType) { // If for whatever reason the expression type doesn't yield an error, make sure we still issue an error on the sourcePropType - checkTypeRelatedTo(sourcePropType, targetPropType, relation, prop, errorMessage, containingMessageChain, resultObj); + checkTypeRelatedTo( + sourcePropType, + targetPropType, + relation, + prop, + errorMessage, + containingMessageChain, + resultObj, + ); } } if (resultObj.errors) { const reportedDiag = resultObj.errors[resultObj.errors.length - 1]; - const propertyName = isTypeUsableAsPropertyName(nameType) ? getPropertyNameFromType(nameType) : undefined; - const targetProp = propertyName !== undefined ? getPropertyOfType(target, propertyName) : undefined; + const propertyName = isTypeUsableAsPropertyName(nameType) ? getPropertyNameFromType(nameType) + : undefined; + const targetProp = propertyName !== undefined ? getPropertyOfType(target, propertyName) + : undefined; let issuedElaboration = false; if (!targetProp) { const indexInfo = getApplicableIndexInfo(target, nameType); - if (indexInfo && indexInfo.declaration && !getSourceFileOfNode(indexInfo.declaration).hasNoDefaultLib) { + if ( + indexInfo && indexInfo.declaration + && !getSourceFileOfNode(indexInfo.declaration).hasNoDefaultLib + ) { issuedElaboration = true; - addRelatedInfo(reportedDiag, createDiagnosticForNode(indexInfo.declaration, Diagnostics.The_expected_type_comes_from_this_index_signature)); + addRelatedInfo( + reportedDiag, + createDiagnosticForNode( + indexInfo.declaration, + Diagnostics.The_expected_type_comes_from_this_index_signature, + ), + ); } } - if (!issuedElaboration && (targetProp && length(targetProp.declarations) || target.symbol && length(target.symbol.declarations))) { - const targetNode = targetProp && length(targetProp.declarations) ? targetProp.declarations![0] : target.symbol.declarations![0]; + if ( + !issuedElaboration + && (targetProp && length(targetProp.declarations) + || target.symbol && length(target.symbol.declarations)) + ) { + const targetNode = targetProp && length(targetProp.declarations) + ? targetProp.declarations![0] : target.symbol.declarations![0]; if (!getSourceFileOfNode(targetNode).hasNoDefaultLib) { addRelatedInfo( reportedDiag, createDiagnosticForNode( targetNode, - Diagnostics.The_expected_type_comes_from_property_0_which_is_declared_here_on_type_1, - propertyName && !(nameType.flags & TypeFlags.UniqueESSymbol) ? unescapeLeadingUnderscores(propertyName) : typeToString(nameType), + Diagnostics + .The_expected_type_comes_from_property_0_which_is_declared_here_on_type_1, + propertyName && !(nameType.flags & TypeFlags.UniqueESSymbol) + ? unescapeLeadingUnderscores(propertyName) : typeToString(nameType), typeToString(target), ), ); @@ -19921,43 +25389,85 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const nonTupleOrArrayLikeTargetParts = filterType(target, t => !isArrayOrTupleLikeType(t)); // If `nonTupleOrArrayLikeTargetParts` is not `never`, then that should mean `Iterable` is defined. const iterationType = nonTupleOrArrayLikeTargetParts !== neverType - ? getIterationTypeOfIterable(IterationUse.ForOf, IterationTypeKind.Yield, nonTupleOrArrayLikeTargetParts, /*errorNode*/ undefined) + ? getIterationTypeOfIterable( + IterationUse.ForOf, + IterationTypeKind.Yield, + nonTupleOrArrayLikeTargetParts, + /*errorNode*/ undefined, + ) : undefined; let reportedError = false; for (let status = iterator.next(); !status.done; status = iterator.next()) { const { errorNode: prop, innerExpression: next, nameType, errorMessage } = status.value; let targetPropType = iterationType; - const targetIndexedPropType = tupleOrArrayLikeTargetParts !== neverType ? getBestMatchIndexedAccessTypeOrUndefined(source, tupleOrArrayLikeTargetParts, nameType) : undefined; + const targetIndexedPropType = tupleOrArrayLikeTargetParts !== neverType + ? getBestMatchIndexedAccessTypeOrUndefined(source, tupleOrArrayLikeTargetParts, nameType) : undefined; if (targetIndexedPropType && !(targetIndexedPropType.flags & TypeFlags.IndexedAccess)) { // Don't elaborate on indexes on generic variables - targetPropType = iterationType ? getUnionType([iterationType, targetIndexedPropType]) : targetIndexedPropType; + targetPropType = iterationType ? getUnionType([iterationType, targetIndexedPropType]) + : targetIndexedPropType; } if (!targetPropType) continue; let sourcePropType = getIndexedAccessTypeOrUndefined(source, nameType); if (!sourcePropType) continue; const propName = getPropertyNameFromIndex(nameType, /*accessNode*/ undefined); if (!checkTypeRelatedTo(sourcePropType, targetPropType, relation, /*errorNode*/ undefined)) { - const elaborated = next && elaborateError(next, sourcePropType, targetPropType, relation, /*headMessage*/ undefined, containingMessageChain, errorOutputContainer); + const elaborated = next + && elaborateError( + next, + sourcePropType, + targetPropType, + relation, + /*headMessage*/ undefined, + containingMessageChain, + errorOutputContainer, + ); reportedError = true; if (!elaborated) { // Issue error on the prop itself, since the prop couldn't elaborate the error const resultObj: { errors?: Diagnostic[]; } = errorOutputContainer || {}; // Use the expression type, if available - const specificSource = next ? checkExpressionForMutableLocationWithContextualType(next, sourcePropType) : sourcePropType; + const specificSource = next + ? checkExpressionForMutableLocationWithContextualType(next, sourcePropType) : sourcePropType; if (exactOptionalPropertyTypes && isExactOptionalPropertyMismatch(specificSource, targetPropType)) { - const diag = createDiagnosticForNode(prop, Diagnostics.Type_0_is_not_assignable_to_type_1_with_exactOptionalPropertyTypes_Colon_true_Consider_adding_undefined_to_the_type_of_the_target, typeToString(specificSource), typeToString(targetPropType)); + const diag = createDiagnosticForNode( + prop, + Diagnostics + .Type_0_is_not_assignable_to_type_1_with_exactOptionalPropertyTypes_Colon_true_Consider_adding_undefined_to_the_type_of_the_target, + typeToString(specificSource), + typeToString(targetPropType), + ); diagnostics.add(diag); resultObj.errors = [diag]; } else { - const targetIsOptional = !!(propName && (getPropertyOfType(tupleOrArrayLikeTargetParts, propName) || unknownSymbol).flags & SymbolFlags.Optional); - const sourceIsOptional = !!(propName && (getPropertyOfType(source, propName) || unknownSymbol).flags & SymbolFlags.Optional); + const targetIsOptional = !!(propName + && (getPropertyOfType(tupleOrArrayLikeTargetParts, propName) || unknownSymbol).flags + & SymbolFlags.Optional); + const sourceIsOptional = !!(propName + && (getPropertyOfType(source, propName) || unknownSymbol).flags & SymbolFlags.Optional); targetPropType = removeMissingType(targetPropType, targetIsOptional); sourcePropType = removeMissingType(sourcePropType, targetIsOptional && sourceIsOptional); - const result = checkTypeRelatedTo(specificSource, targetPropType, relation, prop, errorMessage, containingMessageChain, resultObj); + const result = checkTypeRelatedTo( + specificSource, + targetPropType, + relation, + prop, + errorMessage, + containingMessageChain, + resultObj, + ); if (result && specificSource !== sourcePropType) { // If for whatever reason the expression type doesn't yield an error, make sure we still issue an error on the sourcePropType - checkTypeRelatedTo(sourcePropType, targetPropType, relation, prop, errorMessage, containingMessageChain, resultObj); + checkTypeRelatedTo( + sourcePropType, + targetPropType, + relation, + prop, + errorMessage, + containingMessageChain, + resultObj, + ); } } } @@ -19970,11 +25480,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (!length(node.properties)) return; for (const prop of node.properties) { if (isJsxSpreadAttribute(prop) || isHyphenatedJsxName(getTextOfJsxAttributeName(prop.name))) continue; - yield { errorNode: prop.name, innerExpression: prop.initializer, nameType: getStringLiteralType(getTextOfJsxAttributeName(prop.name)) }; + yield { + errorNode: prop.name, + innerExpression: prop.initializer, + nameType: getStringLiteralType(getTextOfJsxAttributeName(prop.name)), + }; } } - function* generateJsxChildren(node: JsxElement, getInvalidTextDiagnostic: () => DiagnosticMessage): ElaborationIterator { + function* generateJsxChildren( + node: JsxElement, + getInvalidTextDiagnostic: () => DiagnosticMessage, + ): ElaborationIterator { if (!length(node.children)) return; let memberOffset = 0; for (let i = 0; i < node.children.length; i++) { @@ -19990,7 +25507,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } - function getElaborationElementForJsxChild(child: JsxChild, nameType: LiteralType, getInvalidTextDiagnostic: () => DiagnosticMessage) { + function getElaborationElementForJsxChild( + child: JsxChild, + nameType: LiteralType, + getInvalidTextDiagnostic: () => DiagnosticMessage, + ) { switch (child.kind) { case SyntaxKind.JsxExpression: // child is of the type of the expression @@ -20000,7 +25521,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { break; // Whitespace only jsx text isn't real jsx text } // child is a string - return { errorNode: child, innerExpression: undefined, nameType, errorMessage: getInvalidTextDiagnostic() }; + return { + errorNode: child, + innerExpression: undefined, + nameType, + errorMessage: getInvalidTextDiagnostic(), + }; case SyntaxKind.JsxElement: case SyntaxKind.JsxSelfClosingElement: case SyntaxKind.JsxFragment: @@ -20019,12 +25545,20 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { containingMessageChain: (() => DiagnosticMessageChain | undefined) | undefined, errorOutputContainer: { errors?: Diagnostic[]; skipLogging?: boolean; } | undefined, ) { - let result = elaborateElementwise(generateJsxAttributes(node), source, target, relation, containingMessageChain, errorOutputContainer); + let result = elaborateElementwise( + generateJsxAttributes(node), + source, + target, + relation, + containingMessageChain, + errorOutputContainer, + ); let invalidTextDiagnostic: DiagnosticMessage | undefined; if (isJsxOpeningElement(node.parent) && isJsxElement(node.parent.parent)) { const containingElement = node.parent.parent; const childPropName = getJsxElementChildrenPropertyName(getJsxNamespaceAt(node)); - const childrenPropName = childPropName === undefined ? "children" : unescapeLeadingUnderscores(childPropName); + const childrenPropName = childPropName === undefined ? "children" + : unescapeLeadingUnderscores(childPropName); const childrenNameType = getStringLiteralType(childrenPropName); const childrenTargetType = getIndexedAccessType(target, childrenNameType); const validChildren = getSemanticJsxChildren(containingElement.children); @@ -20048,14 +25582,24 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (arrayLikeTargetParts !== neverType) { const realSource = createTupleType(checkJsxChildren(containingElement, CheckMode.Normal)); const children = generateJsxChildren(containingElement, getInvalidTextualChildDiagnostic); - result = elaborateIterableOrArrayLikeTargetElementwise(children, realSource, arrayLikeTargetParts, relation, containingMessageChain, errorOutputContainer) || result; + result = elaborateIterableOrArrayLikeTargetElementwise( + children, + realSource, + arrayLikeTargetParts, + relation, + containingMessageChain, + errorOutputContainer, + ) || result; } - else if (!isTypeRelatedTo(getIndexedAccessType(source, childrenNameType), childrenTargetType, relation)) { + else if ( + !isTypeRelatedTo(getIndexedAccessType(source, childrenNameType), childrenTargetType, relation) + ) { // arity mismatch result = true; const diag = error( containingElement.openingElement.tagName, - Diagnostics.This_JSX_tag_s_0_prop_expects_a_single_child_of_type_1_but_multiple_children_were_provided, + Diagnostics + .This_JSX_tag_s_0_prop_expects_a_single_child_of_type_1_but_multiple_children_were_provided, childrenPropName, typeToString(childrenTargetType), ); @@ -20067,7 +25611,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { else { if (nonArrayLikeTargetParts !== neverType) { const child = validChildren[0]; - const elem = getElaborationElementForJsxChild(child, childrenNameType, getInvalidTextualChildDiagnostic); + const elem = getElaborationElementForJsxChild( + child, + childrenNameType, + getInvalidTextualChildDiagnostic, + ); if (elem) { result = elaborateElementwise( (function* () { @@ -20081,12 +25629,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { ) || result; } } - else if (!isTypeRelatedTo(getIndexedAccessType(source, childrenNameType), childrenTargetType, relation)) { + else if ( + !isTypeRelatedTo(getIndexedAccessType(source, childrenNameType), childrenTargetType, relation) + ) { // arity mismatch result = true; const diag = error( containingElement.openingElement.tagName, - Diagnostics.This_JSX_tag_s_0_prop_expects_type_1_which_requires_multiple_children_but_only_a_single_child_was_provided, + Diagnostics + .This_JSX_tag_s_0_prop_expects_type_1_which_requires_multiple_children_but_only_a_single_child_was_provided, childrenPropName, typeToString(childrenTargetType), ); @@ -20102,10 +25653,22 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (!invalidTextDiagnostic) { const tagNameText = getTextOfNode(node.parent.tagName); const childPropName = getJsxElementChildrenPropertyName(getJsxNamespaceAt(node)); - const childrenPropName = childPropName === undefined ? "children" : unescapeLeadingUnderscores(childPropName); + const childrenPropName = childPropName === undefined ? "children" + : unescapeLeadingUnderscores(childPropName); const childrenTargetType = getIndexedAccessType(target, getStringLiteralType(childrenPropName)); - const diagnostic = Diagnostics._0_components_don_t_accept_text_as_child_elements_Text_in_JSX_has_the_type_string_but_the_expected_type_of_1_is_2; - invalidTextDiagnostic = { ...diagnostic, key: "!!ALREADY FORMATTED!!", message: formatMessage(/*dummy*/ undefined, diagnostic, tagNameText, childrenPropName, typeToString(childrenTargetType)) }; + const diagnostic = Diagnostics + ._0_components_don_t_accept_text_as_child_elements_Text_in_JSX_has_the_type_string_but_the_expected_type_of_1_is_2; + invalidTextDiagnostic = { + ...diagnostic, + key: "!!ALREADY FORMATTED!!", + message: formatMessage( + /*dummy*/ undefined, + diagnostic, + tagNameText, + childrenPropName, + typeToString(childrenTargetType), + ), + }; } return invalidTextDiagnostic; } @@ -20134,7 +25697,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { ) { if (target.flags & (TypeFlags.Primitive | TypeFlags.Never)) return false; if (isTupleLikeType(source)) { - return elaborateElementwise(generateLimitedTupleElements(node, target), source, target, relation, containingMessageChain, errorOutputContainer); + return elaborateElementwise( + generateLimitedTupleElements(node, target), + source, + target, + relation, + containingMessageChain, + errorOutputContainer, + ); } // recreate a tuple from the elements, if possible // Since we're re-doing the expression type, we need to reapply the contextual type @@ -20142,7 +25712,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const tupleizedType = checkArrayLiteral(node, CheckMode.Contextual, /*forceTuple*/ true); popContextualType(); if (isTupleLikeType(tupleizedType)) { - return elaborateElementwise(generateLimitedTupleElements(node, target), tupleizedType, target, relation, containingMessageChain, errorOutputContainer); + return elaborateElementwise( + generateLimitedTupleElements(node, target), + tupleizedType, + target, + relation, + containingMessageChain, + errorOutputContainer, + ); } return false; } @@ -20151,7 +25728,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (!length(node.properties)) return; for (const prop of node.properties) { if (isSpreadAssignment(prop)) continue; - const type = getLiteralTypeFromProperty(getSymbolOfDeclaration(prop), TypeFlags.StringOrNumberLiteralOrUnique); + const type = getLiteralTypeFromProperty( + getSymbolOfDeclaration(prop), + TypeFlags.StringOrNumberLiteralOrUnique, + ); if (!type || (type.flags & TypeFlags.Never)) { continue; } @@ -20163,7 +25743,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { yield { errorNode: prop.name, innerExpression: undefined, nameType: type }; break; case SyntaxKind.PropertyAssignment: - yield { errorNode: prop.name, innerExpression: prop.initializer, nameType: type, errorMessage: isComputedNonLiteralName(prop.name) ? Diagnostics.Type_of_computed_property_s_value_is_0_which_is_not_assignable_to_type_1 : undefined }; + yield { + errorNode: prop.name, + innerExpression: prop.initializer, + nameType: type, + errorMessage: isComputedNonLiteralName(prop.name) + ? Diagnostics.Type_of_computed_property_s_value_is_0_which_is_not_assignable_to_type_1 + : undefined, + }; break; default: Debug.assertNever(prop); @@ -20180,19 +25767,41 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { errorOutputContainer: { errors?: Diagnostic[]; skipLogging?: boolean; } | undefined, ) { if (target.flags & (TypeFlags.Primitive | TypeFlags.Never)) return false; - return elaborateElementwise(generateObjectLiteralElements(node), source, target, relation, containingMessageChain, errorOutputContainer); + return elaborateElementwise( + generateObjectLiteralElements(node), + source, + target, + relation, + containingMessageChain, + errorOutputContainer, + ); } /** * This is *not* a bi-directional relationship. * If one needs to check both directions for comparability, use a second call to this function or 'isTypeComparableTo'. */ - function checkTypeComparableTo(source: Type, target: Type, errorNode: Node, headMessage?: DiagnosticMessage, containingMessageChain?: () => DiagnosticMessageChain | undefined): boolean { + function checkTypeComparableTo( + source: Type, + target: Type, + errorNode: Node, + headMessage?: DiagnosticMessage, + containingMessageChain?: () => DiagnosticMessageChain | undefined, + ): boolean { return checkTypeRelatedTo(source, target, comparableRelation, errorNode, headMessage, containingMessageChain); } function isSignatureAssignableTo(source: Signature, target: Signature, ignoreReturnTypes: boolean): boolean { - return compareSignaturesRelated(source, target, ignoreReturnTypes ? SignatureCheckMode.IgnoreReturnTypes : SignatureCheckMode.None, /*reportErrors*/ false, /*errorReporter*/ undefined, /*incompatibleErrorReporter*/ undefined, compareTypesAssignable, /*reportUnreliableMarkers*/ undefined) !== Ternary.False; + return compareSignaturesRelated( + source, + target, + ignoreReturnTypes ? SignatureCheckMode.IgnoreReturnTypes : SignatureCheckMode.None, + /*reportErrors*/ false, + /*errorReporter*/ undefined, + /*incompatibleErrorReporter*/ undefined, + compareTypesAssignable, + /*reportUnreliableMarkers*/ undefined, + ) !== Ternary.False; } type ErrorReporter = (message: DiagnosticMessage, ...args: DiagnosticArguments) => void; @@ -20201,10 +25810,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { * Returns true if `s` is `(...args: A) => R` where `A` is `any`, `any[]`, `never`, or `never[]`, and `R` is `any` or `unknown`. */ function isTopSignature(s: Signature) { - if (!s.typeParameters && (!s.thisParameter || isTypeAny(getTypeOfParameter(s.thisParameter))) && s.parameters.length === 1 && signatureHasRestParameter(s)) { + if ( + !s.typeParameters && (!s.thisParameter || isTypeAny(getTypeOfParameter(s.thisParameter))) + && s.parameters.length === 1 && signatureHasRestParameter(s) + ) { const paramType = getTypeOfParameter(s.parameters[0]); const restType = isArrayType(paramType) ? getTypeArguments(paramType)[0] : paramType; - return !!(restType.flags & (TypeFlags.Any | TypeFlags.Never) && getReturnTypeOfSignature(s).flags & TypeFlags.AnyOrUnknown); + return !!(restType.flags & (TypeFlags.Any | TypeFlags.Never) + && getReturnTypeOfSignature(s).flags & TypeFlags.AnyOrUnknown); } return false; } @@ -20212,7 +25825,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { /** * See signatureRelatedTo, compareSignaturesIdentical */ - function compareSignaturesRelated(source: Signature, target: Signature, checkMode: SignatureCheckMode, reportErrors: boolean, errorReporter: ErrorReporter | undefined, incompatibleErrorReporter: ((source: Type, target: Type) => void) | undefined, compareTypes: TypeComparer, reportUnreliableMarkers: TypeMapper | undefined): Ternary { + function compareSignaturesRelated( + source: Signature, + target: Signature, + checkMode: SignatureCheckMode, + reportErrors: boolean, + errorReporter: ErrorReporter | undefined, + incompatibleErrorReporter: ((source: Type, target: Type) => void) | undefined, + compareTypes: TypeComparer, + reportUnreliableMarkers: TypeMapper | undefined, + ): Ternary { // TODO (drosen): De-duplicate code between related functions. if (source === target) { return Ternary.True; @@ -20226,13 +25848,19 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } const targetCount = getParameterCount(target); - const sourceHasMoreParameters = !hasEffectiveRestParameter(target) && - (checkMode & SignatureCheckMode.StrictArity ? hasEffectiveRestParameter(source) || getParameterCount(source) > targetCount : getMinArgumentCount(source) > targetCount); + const sourceHasMoreParameters = !hasEffectiveRestParameter(target) + && (checkMode & SignatureCheckMode.StrictArity + ? hasEffectiveRestParameter(source) || getParameterCount(source) > targetCount + : getMinArgumentCount(source) > targetCount); if (sourceHasMoreParameters) { if (reportErrors && !(checkMode & SignatureCheckMode.StrictArity)) { // the second condition should be redundant, because there is no error reporting when comparing signatures by strict arity // since it is only done for subtype reduction - errorReporter!(Diagnostics.Target_signature_provides_too_few_arguments_Expected_0_or_more_but_got_1, getMinArgumentCount(source), targetCount); + errorReporter!( + Diagnostics.Target_signature_provides_too_few_arguments_Expected_0_or_more_but_got_1, + getMinArgumentCount(source), + targetCount, + ); } return Ternary.False; } @@ -20250,8 +25878,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } const kind = target.declaration ? target.declaration.kind : SyntaxKind.Unknown; - const strictVariance = !(checkMode & SignatureCheckMode.Callback) && strictFunctionTypes && kind !== SyntaxKind.MethodDeclaration && - kind !== SyntaxKind.MethodSignature && kind !== SyntaxKind.Constructor; + const strictVariance = !(checkMode & SignatureCheckMode.Callback) && strictFunctionTypes + && kind !== SyntaxKind.MethodDeclaration + && kind !== SyntaxKind.MethodSignature && kind !== SyntaxKind.Constructor; let result = Ternary.True; const sourceThisType = getThisTypeOfSignature(source); @@ -20271,7 +25900,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } - const paramCount = sourceRestType || targetRestType ? Math.min(sourceCount, targetCount) : Math.max(sourceCount, targetCount); + const paramCount = sourceRestType || targetRestType ? Math.min(sourceCount, targetCount) + : Math.max(sourceCount, targetCount); const restIndex = sourceRestType || targetRestType ? paramCount - 1 : -1; for (let i = 0; i < paramCount; i++) { @@ -20286,20 +25916,44 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // similar to return values, callback parameters are output positions. This means that a Promise, // where T is used only in callback parameter positions, will be co-variant (as opposed to bi-variant) // with respect to T. - const sourceSig = checkMode & SignatureCheckMode.Callback ? undefined : getSingleCallSignature(getNonNullableType(sourceType)); - const targetSig = checkMode & SignatureCheckMode.Callback ? undefined : getSingleCallSignature(getNonNullableType(targetType)); - const callbacks = sourceSig && targetSig && !getTypePredicateOfSignature(sourceSig) && !getTypePredicateOfSignature(targetSig) && - (getTypeFacts(sourceType) & TypeFacts.IsUndefinedOrNull) === (getTypeFacts(targetType) & TypeFacts.IsUndefinedOrNull); - let related = callbacks ? - compareSignaturesRelated(targetSig, sourceSig, (checkMode & SignatureCheckMode.StrictArity) | (strictVariance ? SignatureCheckMode.StrictCallback : SignatureCheckMode.BivariantCallback), reportErrors, errorReporter, incompatibleErrorReporter, compareTypes, reportUnreliableMarkers) : - !(checkMode & SignatureCheckMode.Callback) && !strictVariance && compareTypes(sourceType, targetType, /*reportErrors*/ false) || compareTypes(targetType, sourceType, reportErrors); + const sourceSig = checkMode & SignatureCheckMode.Callback ? undefined + : getSingleCallSignature(getNonNullableType(sourceType)); + const targetSig = checkMode & SignatureCheckMode.Callback ? undefined + : getSingleCallSignature(getNonNullableType(targetType)); + const callbacks = sourceSig && targetSig && !getTypePredicateOfSignature(sourceSig) + && !getTypePredicateOfSignature(targetSig) + && (getTypeFacts(sourceType) & TypeFacts.IsUndefinedOrNull) + === (getTypeFacts(targetType) & TypeFacts.IsUndefinedOrNull); + let related = callbacks + ? compareSignaturesRelated( + targetSig, + sourceSig, + (checkMode & SignatureCheckMode.StrictArity) + | (strictVariance ? SignatureCheckMode.StrictCallback + : SignatureCheckMode.BivariantCallback), + reportErrors, + errorReporter, + incompatibleErrorReporter, + compareTypes, + reportUnreliableMarkers, + ) + : !(checkMode & SignatureCheckMode.Callback) && !strictVariance + && compareTypes(sourceType, targetType, /*reportErrors*/ false) + || compareTypes(targetType, sourceType, reportErrors); // With strict arity, (x: number | undefined) => void is a subtype of (x?: number | undefined) => void - if (related && checkMode & SignatureCheckMode.StrictArity && i >= getMinArgumentCount(source) && i < getMinArgumentCount(target) && compareTypes(sourceType, targetType, /*reportErrors*/ false)) { + if ( + related && checkMode & SignatureCheckMode.StrictArity && i >= getMinArgumentCount(source) + && i < getMinArgumentCount(target) && compareTypes(sourceType, targetType, /*reportErrors*/ false) + ) { related = Ternary.False; } if (!related) { if (reportErrors) { - errorReporter!(Diagnostics.Types_of_parameters_0_and_1_are_incompatible, unescapeLeadingUnderscores(getParameterNameAtPosition(source, i)), unescapeLeadingUnderscores(getParameterNameAtPosition(target, i))); + errorReporter!( + Diagnostics.Types_of_parameters_0_and_1_are_incompatible, + unescapeLeadingUnderscores(getParameterNameAtPosition(source, i)), + unescapeLeadingUnderscores(getParameterNameAtPosition(target, i)), + ); } return Ternary.False; } @@ -20311,13 +25965,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // If a signature resolution is already in-flight, skip issuing a circularity error // here and just use the `any` type directly const targetReturnType = isResolvingReturnTypeOfSignature(target) ? anyType - : target.declaration && isJSConstructor(target.declaration) ? getDeclaredTypeOfClassOrInterface(getMergedSymbol(target.declaration.symbol)) + : target.declaration && isJSConstructor(target.declaration) + ? getDeclaredTypeOfClassOrInterface(getMergedSymbol(target.declaration.symbol)) : getReturnTypeOfSignature(target); if (targetReturnType === voidType || targetReturnType === anyType) { return result; } const sourceReturnType = isResolvingReturnTypeOfSignature(source) ? anyType - : source.declaration && isJSConstructor(source.declaration) ? getDeclaredTypeOfClassOrInterface(getMergedSymbol(source.declaration.symbol)) + : source.declaration && isJSConstructor(source.declaration) + ? getDeclaredTypeOfClassOrInterface(getMergedSymbol(source.declaration.symbol)) : getReturnTypeOfSignature(source); // The following block preserves behavior forbidding boolean returning functions from being assignable to type guard returning functions @@ -20325,7 +25981,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (targetTypePredicate) { const sourceTypePredicate = getTypePredicateOfSignature(source); if (sourceTypePredicate) { - result &= compareTypePredicateRelatedTo(sourceTypePredicate, targetTypePredicate, reportErrors, errorReporter, compareTypes); + result &= compareTypePredicateRelatedTo( + sourceTypePredicate, + targetTypePredicate, + reportErrors, + errorReporter, + compareTypes, + ); } else if (isIdentifierTypePredicate(targetTypePredicate)) { if (reportErrors) { @@ -20338,8 +26000,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // When relating callback signatures, we still need to relate return types bi-variantly as otherwise // the containing type wouldn't be co-variant. For example, interface Foo { add(cb: () => T): void } // wouldn't be co-variant for T without this rule. - result &= checkMode & SignatureCheckMode.BivariantCallback && compareTypes(targetReturnType, sourceReturnType, /*reportErrors*/ false) || - compareTypes(sourceReturnType, targetReturnType, reportErrors); + result &= checkMode & SignatureCheckMode.BivariantCallback + && compareTypes(targetReturnType, sourceReturnType, /*reportErrors*/ false) + || compareTypes(sourceReturnType, targetReturnType, reportErrors); if (!result && reportErrors && incompatibleErrorReporter) { incompatibleErrorReporter(sourceReturnType, targetReturnType); } @@ -20359,7 +26022,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (source.kind !== target.kind) { if (reportErrors) { errorReporter!(Diagnostics.A_this_based_type_guard_is_not_compatible_with_a_parameter_based_type_guard); - errorReporter!(Diagnostics.Type_predicate_0_is_not_assignable_to_1, typePredicateToString(source), typePredicateToString(target)); + errorReporter!( + Diagnostics.Type_predicate_0_is_not_assignable_to_1, + typePredicateToString(source), + typePredicateToString(target), + ); } return Ternary.False; } @@ -20367,18 +26034,30 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (source.kind === TypePredicateKind.Identifier || source.kind === TypePredicateKind.AssertsIdentifier) { if (source.parameterIndex !== (target as IdentifierTypePredicate).parameterIndex) { if (reportErrors) { - errorReporter!(Diagnostics.Parameter_0_is_not_in_the_same_position_as_parameter_1, source.parameterName, (target as IdentifierTypePredicate).parameterName); - errorReporter!(Diagnostics.Type_predicate_0_is_not_assignable_to_1, typePredicateToString(source), typePredicateToString(target)); + errorReporter!( + Diagnostics.Parameter_0_is_not_in_the_same_position_as_parameter_1, + source.parameterName, + (target as IdentifierTypePredicate).parameterName, + ); + errorReporter!( + Diagnostics.Type_predicate_0_is_not_assignable_to_1, + typePredicateToString(source), + typePredicateToString(target), + ); } return Ternary.False; } } - const related = source.type === target.type ? Ternary.True : - source.type && target.type ? compareTypes(source.type, target.type, reportErrors) : - Ternary.False; + const related = source.type === target.type ? Ternary.True + : source.type && target.type ? compareTypes(source.type, target.type, reportErrors) + : Ternary.False; if (related === Ternary.False && reportErrors) { - errorReporter!(Diagnostics.Type_predicate_0_is_not_assignable_to_1, typePredicateToString(source), typePredicateToString(target)); + errorReporter!( + Diagnostics.Type_predicate_0_is_not_assignable_to_1, + typePredicateToString(source), + typePredicateToString(target), + ); } return related; } @@ -20402,25 +26081,26 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function isEmptyResolvedType(t: ResolvedType) { - return t !== anyFunctionType && - t.properties.length === 0 && - t.callSignatures.length === 0 && - t.constructSignatures.length === 0 && - t.indexInfos.length === 0; + return t !== anyFunctionType + && t.properties.length === 0 + && t.callSignatures.length === 0 + && t.constructSignatures.length === 0 + && t.indexInfos.length === 0; } function isEmptyObjectType(type: Type): boolean { - return type.flags & TypeFlags.Object ? !isGenericMappedType(type) && isEmptyResolvedType(resolveStructuredTypeMembers(type as ObjectType)) : - type.flags & TypeFlags.NonPrimitive ? true : - type.flags & TypeFlags.Union ? some((type as UnionType).types, isEmptyObjectType) : - type.flags & TypeFlags.Intersection ? every((type as UnionType).types, isEmptyObjectType) : - false; + return type.flags & TypeFlags.Object + ? !isGenericMappedType(type) && isEmptyResolvedType(resolveStructuredTypeMembers(type as ObjectType)) + : type.flags & TypeFlags.NonPrimitive ? true + : type.flags & TypeFlags.Union ? some((type as UnionType).types, isEmptyObjectType) + : type.flags & TypeFlags.Intersection ? every((type as UnionType).types, isEmptyObjectType) + : false; } function isEmptyAnonymousObjectType(type: Type) { return !!(getObjectFlags(type) & ObjectFlags.Anonymous && ( - (type as ResolvedType).members && isEmptyResolvedType(type as ResolvedType) || - type.symbol && type.symbol.flags & SymbolFlags.TypeLiteral && getMembersOfSymbol(type.symbol).size === 0 + (type as ResolvedType).members && isEmptyResolvedType(type as ResolvedType) + || type.symbol && type.symbol.flags & SymbolFlags.TypeLiteral && getMembersOfSymbol(type.symbol).size === 0 )); } @@ -20428,8 +26108,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (strictNullChecks && type.flags & TypeFlags.Union) { if (!((type as UnionType).objectFlags & ObjectFlags.IsUnknownLikeUnionComputed)) { const types = (type as UnionType).types; - (type as UnionType).objectFlags |= ObjectFlags.IsUnknownLikeUnionComputed | (types.length >= 3 && types[0].flags & TypeFlags.Undefined && - types[1].flags & TypeFlags.Null && some(types, isEmptyAnonymousObjectType) ? ObjectFlags.IsUnknownLikeUnion : 0); + (type as UnionType).objectFlags |= ObjectFlags.IsUnknownLikeUnionComputed + | (types.length >= 3 && types[0].flags & TypeFlags.Undefined + && types[1].flags & TypeFlags.Null && some(types, isEmptyAnonymousObjectType) + ? ObjectFlags.IsUnknownLikeUnion : 0); } return !!((type as UnionType).objectFlags & ObjectFlags.IsUnknownLikeUnion); } @@ -20441,9 +26123,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function isStringIndexSignatureOnlyType(type: Type): boolean { - return type.flags & TypeFlags.Object && !isGenericMappedType(type) && getPropertiesOfType(type).length === 0 && getIndexInfosOfType(type).length === 1 && !!getIndexInfoOfType(type, stringType) || - type.flags & TypeFlags.UnionOrIntersection && every((type as UnionOrIntersectionType).types, isStringIndexSignatureOnlyType) || - false; + return type.flags & TypeFlags.Object && !isGenericMappedType(type) && getPropertiesOfType(type).length === 0 + && getIndexInfosOfType(type).length === 1 && !!getIndexInfoOfType(type, stringType) + || type.flags & TypeFlags.UnionOrIntersection + && every((type as UnionOrIntersectionType).types, isStringIndexSignatureOnlyType) + || false; } function isEnumTypeRelatedTo(source: Symbol, target: Symbol, errorReporter?: ErrorReporter) { @@ -20452,12 +26136,19 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (sourceSymbol === targetSymbol) { return true; } - if (sourceSymbol.escapedName !== targetSymbol.escapedName || !(sourceSymbol.flags & SymbolFlags.RegularEnum) || !(targetSymbol.flags & SymbolFlags.RegularEnum)) { + if ( + sourceSymbol.escapedName !== targetSymbol.escapedName || !(sourceSymbol.flags & SymbolFlags.RegularEnum) + || !(targetSymbol.flags & SymbolFlags.RegularEnum) + ) { return false; } const id = getSymbolId(sourceSymbol) + "," + getSymbolId(targetSymbol); const entry = enumRelation.get(id); - if (entry !== undefined && !(!(entry & RelationComparisonResult.Reported) && entry & RelationComparisonResult.Failed && errorReporter)) { + if ( + entry !== undefined + && !(!(entry & RelationComparisonResult.Reported) && entry & RelationComparisonResult.Failed + && errorReporter) + ) { return !!(entry & RelationComparisonResult.Succeeded); } const targetEnumType = getTypeOfSymbol(targetSymbol); @@ -20466,7 +26157,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const targetProperty = getPropertyOfType(targetEnumType, property.escapedName); if (!targetProperty || !(targetProperty.flags & SymbolFlags.EnumMember)) { if (errorReporter) { - errorReporter(Diagnostics.Property_0_is_missing_in_type_1, symbolName(property), typeToString(getDeclaredTypeOfSymbol(targetSymbol), /*enclosingDeclaration*/ undefined, TypeFormatFlags.UseFullyQualifiedType)); + errorReporter( + Diagnostics.Property_0_is_missing_in_type_1, + symbolName(property), + typeToString( + getDeclaredTypeOfSymbol(targetSymbol), + /*enclosingDeclaration*/ undefined, + TypeFormatFlags.UseFullyQualifiedType, + ), + ); enumRelation.set(id, RelationComparisonResult.Failed | RelationComparisonResult.Reported); } else { @@ -20480,7 +26179,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return true; } - function isSimpleTypeRelatedTo(source: Type, target: Type, relation: Map, errorReporter?: ErrorReporter) { + function isSimpleTypeRelatedTo( + source: Type, + target: Type, + relation: Map, + errorReporter?: ErrorReporter, + ) { const s = source.flags; const t = target.flags; if (t & TypeFlags.Any || s & TypeFlags.Never || source === wildcardType) return true; @@ -20488,45 +26192,60 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (t & TypeFlags.Never) return false; if (s & TypeFlags.StringLike && t & TypeFlags.String) return true; if ( - s & TypeFlags.StringLiteral && s & TypeFlags.EnumLiteral && - t & TypeFlags.StringLiteral && !(t & TypeFlags.EnumLiteral) && - (source as StringLiteralType).value === (target as StringLiteralType).value + s & TypeFlags.StringLiteral && s & TypeFlags.EnumLiteral + && t & TypeFlags.StringLiteral && !(t & TypeFlags.EnumLiteral) + && (source as StringLiteralType).value === (target as StringLiteralType).value ) return true; if (s & TypeFlags.NumberLike && t & TypeFlags.Number) return true; if ( - s & TypeFlags.NumberLiteral && s & TypeFlags.EnumLiteral && - t & TypeFlags.NumberLiteral && !(t & TypeFlags.EnumLiteral) && - (source as NumberLiteralType).value === (target as NumberLiteralType).value + s & TypeFlags.NumberLiteral && s & TypeFlags.EnumLiteral + && t & TypeFlags.NumberLiteral && !(t & TypeFlags.EnumLiteral) + && (source as NumberLiteralType).value === (target as NumberLiteralType).value ) return true; if (s & TypeFlags.BigIntLike && t & TypeFlags.BigInt) return true; if (s & TypeFlags.BooleanLike && t & TypeFlags.Boolean) return true; if (s & TypeFlags.ESSymbolLike && t & TypeFlags.ESSymbol) return true; if ( - s & TypeFlags.Enum && t & TypeFlags.Enum && source.symbol.escapedName === target.symbol.escapedName && - isEnumTypeRelatedTo(source.symbol, target.symbol, errorReporter) + s & TypeFlags.Enum && t & TypeFlags.Enum && source.symbol.escapedName === target.symbol.escapedName + && isEnumTypeRelatedTo(source.symbol, target.symbol, errorReporter) ) return true; if (s & TypeFlags.EnumLiteral && t & TypeFlags.EnumLiteral) { - if (s & TypeFlags.Union && t & TypeFlags.Union && isEnumTypeRelatedTo(source.symbol, target.symbol, errorReporter)) return true; if ( - s & TypeFlags.Literal && t & TypeFlags.Literal && (source as LiteralType).value === (target as LiteralType).value && - isEnumTypeRelatedTo(source.symbol, target.symbol, errorReporter) + s & TypeFlags.Union && t & TypeFlags.Union + && isEnumTypeRelatedTo(source.symbol, target.symbol, errorReporter) + ) return true; + if ( + s & TypeFlags.Literal && t & TypeFlags.Literal + && (source as LiteralType).value === (target as LiteralType).value + && isEnumTypeRelatedTo(source.symbol, target.symbol, errorReporter) ) return true; } // In non-strictNullChecks mode, `undefined` and `null` are assignable to anything except `never`. // Since unions and intersections may reduce to `never`, we exclude them here. - if (s & TypeFlags.Undefined && (!strictNullChecks && !(t & TypeFlags.UnionOrIntersection) || t & (TypeFlags.Undefined | TypeFlags.Void))) return true; - if (s & TypeFlags.Null && (!strictNullChecks && !(t & TypeFlags.UnionOrIntersection) || t & TypeFlags.Null)) return true; - if (s & TypeFlags.Object && t & TypeFlags.NonPrimitive && !(relation === strictSubtypeRelation && isEmptyAnonymousObjectType(source) && !(getObjectFlags(source) & ObjectFlags.FreshLiteral))) return true; + if ( + s & TypeFlags.Undefined + && (!strictNullChecks && !(t & TypeFlags.UnionOrIntersection) || t & (TypeFlags.Undefined | TypeFlags.Void)) + ) return true; + if (s & TypeFlags.Null && (!strictNullChecks && !(t & TypeFlags.UnionOrIntersection) || t & TypeFlags.Null)) { + return true; + } + if ( + s & TypeFlags.Object && t & TypeFlags.NonPrimitive + && !(relation === strictSubtypeRelation && isEmptyAnonymousObjectType(source) + && !(getObjectFlags(source) & ObjectFlags.FreshLiteral)) + ) return true; if (relation === assignableRelation || relation === comparableRelation) { if (s & TypeFlags.Any) return true; // Type number is assignable to any computed numeric enum type or any numeric enum literal type, and // a numeric literal type is assignable any computed numeric enum type or any numeric enum literal type // with a matching value. These rules exist such that enums can be used for bit-flag purposes. - if (s & TypeFlags.Number && (t & TypeFlags.Enum || t & TypeFlags.NumberLiteral && t & TypeFlags.EnumLiteral)) return true; if ( - s & TypeFlags.NumberLiteral && !(s & TypeFlags.EnumLiteral) && (t & TypeFlags.Enum || - t & TypeFlags.NumberLiteral && t & TypeFlags.EnumLiteral && - (source as NumberLiteralType).value === (target as NumberLiteralType).value) + s & TypeFlags.Number && (t & TypeFlags.Enum || t & TypeFlags.NumberLiteral && t & TypeFlags.EnumLiteral) + ) return true; + if ( + s & TypeFlags.NumberLiteral && !(s & TypeFlags.EnumLiteral) && (t & TypeFlags.Enum + || t & TypeFlags.NumberLiteral && t & TypeFlags.EnumLiteral + && (source as NumberLiteralType).value === (target as NumberLiteralType).value) ) return true; // Anything is assignable to a union containing undefined, null, and {} if (isUnknownLikeUnionType(target)) return true; @@ -20545,17 +26264,27 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return true; } if (relation !== identityRelation) { - if (relation === comparableRelation && !(target.flags & TypeFlags.Never) && isSimpleTypeRelatedTo(target, source, relation) || isSimpleTypeRelatedTo(source, target, relation)) { + if ( + relation === comparableRelation && !(target.flags & TypeFlags.Never) + && isSimpleTypeRelatedTo(target, source, relation) + || isSimpleTypeRelatedTo(source, target, relation) + ) { return true; } } - else if (!((source.flags | target.flags) & (TypeFlags.UnionOrIntersection | TypeFlags.IndexedAccess | TypeFlags.Conditional | TypeFlags.Substitution))) { + else if ( + !((source.flags | target.flags) + & (TypeFlags.UnionOrIntersection | TypeFlags.IndexedAccess | TypeFlags.Conditional + | TypeFlags.Substitution)) + ) { // We have excluded types that may simplify to other forms, so types must have identical flags if (source.flags !== target.flags) return false; if (source.flags & TypeFlags.Singleton) return true; } if (source.flags & TypeFlags.Object && target.flags & TypeFlags.Object) { - const related = relation.get(getRelationKey(source, target, IntersectionState.None, relation, /*ignoreConstraints*/ false)); + const related = relation.get( + getRelationKey(source, target, IntersectionState.None, relation, /*ignoreConstraints*/ false), + ); if (related !== undefined) { return !!(related & RelationComparisonResult.Succeeded); } @@ -20572,13 +26301,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function getNormalizedType(type: Type, writing: boolean): Type { while (true) { - const t = isFreshLiteralType(type) ? (type as FreshableType).regularType : - isGenericTupleType(type) ? getNormalizedTupleType(type, writing) : - getObjectFlags(type) & ObjectFlags.Reference ? (type as TypeReference).node ? createTypeReference((type as TypeReference).target, getTypeArguments(type as TypeReference)) : getSingleBaseForNonAugmentingSubtype(type) || type : - type.flags & TypeFlags.UnionOrIntersection ? getNormalizedUnionOrIntersectionType(type as UnionOrIntersectionType, writing) : - type.flags & TypeFlags.Substitution ? writing ? (type as SubstitutionType).baseType : getSubstitutionIntersection(type as SubstitutionType) : - type.flags & TypeFlags.Simplifiable ? getSimplifiedType(type, writing) : - type; + const t = isFreshLiteralType(type) ? (type as FreshableType).regularType + : isGenericTupleType(type) ? getNormalizedTupleType(type, writing) + : getObjectFlags(type) & ObjectFlags.Reference + ? (type as TypeReference).node + ? createTypeReference((type as TypeReference).target, getTypeArguments(type as TypeReference)) + : getSingleBaseForNonAugmentingSubtype(type) || type + : type.flags & TypeFlags.UnionOrIntersection + ? getNormalizedUnionOrIntersectionType(type as UnionOrIntersectionType, writing) + : type.flags & TypeFlags.Substitution + ? writing ? (type as SubstitutionType).baseType : getSubstitutionIntersection(type as SubstitutionType) + : type.flags & TypeFlags.Simplifiable ? getSimplifiedType(type, writing) + : type; if (t === type) return t; type = t; } @@ -20600,7 +26334,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function getNormalizedTupleType(type: TupleTypeReference, writing: boolean): Type { const elements = getElementTypes(type); - const normalizedElements = sameMap(elements, t => t.flags & TypeFlags.Simplifiable ? getSimplifiedType(t, writing) : t); + const normalizedElements = sameMap( + elements, + t => t.flags & TypeFlags.Simplifiable ? getSimplifiedType(t, writing) : t, + ); return elements !== normalizedElements ? createNormalizedTupleType(type.target, normalizedElements) : type; } @@ -20647,8 +26384,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { reportIncompatibleStack(); } if (overflow) { - tracing?.instant(tracing.Phase.CheckTypes, "checkTypeRelatedTo_DepthLimit", { sourceId: source.id, targetId: target.id, depth: sourceDepth, targetDepth }); - const diag = error(errorNode || currentNode, Diagnostics.Excessive_stack_depth_comparing_types_0_and_1, typeToString(source), typeToString(target)); + tracing?.instant(tracing.Phase.CheckTypes, "checkTypeRelatedTo_DepthLimit", { + sourceId: source.id, + targetId: target.id, + depth: sourceDepth, + targetDepth, + }); + const diag = error( + errorNode || currentNode, + Diagnostics.Excessive_stack_depth_comparing_types_0_and_1, + typeToString(source), + typeToString(target), + ); if (errorOutputContainer) { (errorOutputContainer.errors || (errorOutputContainer.errors = [])).push(diag); } @@ -20667,15 +26414,29 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (headMessage && errorNode && !result && source.symbol) { const links = getSymbolLinks(source.symbol); if (links.originatingImport && !isImportCall(links.originatingImport)) { - const helpfulRetry = checkTypeRelatedTo(getTypeOfSymbol(links.target!), target, relation, /*errorNode*/ undefined); + const helpfulRetry = checkTypeRelatedTo( + getTypeOfSymbol(links.target!), + target, + relation, + /*errorNode*/ undefined, + ); if (helpfulRetry) { // Likely an incorrect import. Issue a helpful diagnostic to produce a quickfix to change the import - const diag = createDiagnosticForNode(links.originatingImport, Diagnostics.Type_originates_at_this_import_A_namespace_style_import_cannot_be_called_or_constructed_and_will_cause_a_failure_at_runtime_Consider_using_a_default_import_or_import_require_here_instead); + const diag = createDiagnosticForNode( + links.originatingImport, + Diagnostics + .Type_originates_at_this_import_A_namespace_style_import_cannot_be_called_or_constructed_and_will_cause_a_failure_at_runtime_Consider_using_a_default_import_or_import_require_here_instead, + ); relatedInformation = append(relatedInformation, diag); // Cause the error to appear with the error that triggered it } } } - const diag = createDiagnosticForNodeFromMessageChain(getSourceFileOfNode(errorNode!), errorNode!, errorInfo, relatedInformation); + const diag = createDiagnosticForNodeFromMessageChain( + getSourceFileOfNode(errorNode!), + errorNode!, + errorInfo, + relatedInformation, + ); if (relatedInfo) { addRelatedInfo(diag, ...relatedInfo); } @@ -20708,7 +26469,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { incompatibleStack: incompatibleStack?.slice(), overrideNextErrorInfo, skipParentCounter, - relatedInfo: relatedInfo?.slice() as [DiagnosticRelatedInformation, ...DiagnosticRelatedInformation[]] | undefined, + relatedInfo: relatedInfo?.slice() as + | [DiagnosticRelatedInformation, ...DiagnosticRelatedInformation[]] + | undefined, }; } @@ -20765,38 +26528,72 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { case Diagnostics.Call_signature_return_types_0_and_1_are_incompatible.code: case Diagnostics.Construct_signature_return_types_0_and_1_are_incompatible.code: case Diagnostics.Call_signatures_with_no_arguments_have_incompatible_return_types_0_and_1.code: - case Diagnostics.Construct_signatures_with_no_arguments_have_incompatible_return_types_0_and_1.code: { + case Diagnostics.Construct_signatures_with_no_arguments_have_incompatible_return_types_0_and_1 + .code: { if (path.length === 0) { // Don't flatten signature compatability errors at the start of a chain - instead prefer // to unify (the with no arguments bit is excessive for printback) and print them back let mappedMsg = msg; - if (msg.code === Diagnostics.Call_signatures_with_no_arguments_have_incompatible_return_types_0_and_1.code) { + if ( + msg.code + === Diagnostics + .Call_signatures_with_no_arguments_have_incompatible_return_types_0_and_1.code + ) { mappedMsg = Diagnostics.Call_signature_return_types_0_and_1_are_incompatible; } - else if (msg.code === Diagnostics.Construct_signatures_with_no_arguments_have_incompatible_return_types_0_and_1.code) { + else if ( + msg.code + === Diagnostics + .Construct_signatures_with_no_arguments_have_incompatible_return_types_0_and_1 + .code + ) { mappedMsg = Diagnostics.Construct_signature_return_types_0_and_1_are_incompatible; } secondaryRootErrors.unshift([mappedMsg, args[0], args[1]]); } else { - const prefix = (msg.code === Diagnostics.Construct_signature_return_types_0_and_1_are_incompatible.code || - msg.code === Diagnostics.Construct_signatures_with_no_arguments_have_incompatible_return_types_0_and_1.code) - ? "new " - : ""; - const params = (msg.code === Diagnostics.Call_signatures_with_no_arguments_have_incompatible_return_types_0_and_1.code || - msg.code === Diagnostics.Construct_signatures_with_no_arguments_have_incompatible_return_types_0_and_1.code) + const prefix = + (msg.code === Diagnostics.Construct_signature_return_types_0_and_1_are_incompatible.code + || msg.code + === Diagnostics + .Construct_signatures_with_no_arguments_have_incompatible_return_types_0_and_1 + .code) + ? "new " + : ""; + const params = (msg.code + === Diagnostics + .Call_signatures_with_no_arguments_have_incompatible_return_types_0_and_1 + .code + || msg.code + === Diagnostics + .Construct_signatures_with_no_arguments_have_incompatible_return_types_0_and_1 + .code) ? "" : "..."; path = `${prefix}${path}(${params})`; } break; } - case Diagnostics.Type_at_position_0_in_source_is_not_compatible_with_type_at_position_1_in_target.code: { - secondaryRootErrors.unshift([Diagnostics.Type_at_position_0_in_source_is_not_compatible_with_type_at_position_1_in_target, args[0], args[1]]); + case Diagnostics.Type_at_position_0_in_source_is_not_compatible_with_type_at_position_1_in_target + .code: { + secondaryRootErrors.unshift([ + Diagnostics + .Type_at_position_0_in_source_is_not_compatible_with_type_at_position_1_in_target, + args[0], + args[1], + ]); break; } - case Diagnostics.Type_at_positions_0_through_1_in_source_is_not_compatible_with_type_at_position_2_in_target.code: { - secondaryRootErrors.unshift([Diagnostics.Type_at_positions_0_through_1_in_source_is_not_compatible_with_type_at_position_2_in_target, args[0], args[1], args[2]]); + case Diagnostics + .Type_at_positions_0_through_1_in_source_is_not_compatible_with_type_at_position_2_in_target + .code: { + secondaryRootErrors.unshift([ + Diagnostics + .Type_at_positions_0_through_1_in_source_is_not_compatible_with_type_at_position_2_in_target, + args[0], + args[1], + args[2], + ]); break; } default: @@ -20862,21 +26659,32 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (isLiteralType(source) && !typeCouldHaveTopLevelSingletonTypes(target)) { generalizedSource = getBaseTypeOfLiteralType(source); - Debug.assert(!isTypeAssignableTo(generalizedSource, target), "generalized source shouldn't be assignable"); + Debug.assert( + !isTypeAssignableTo(generalizedSource, target), + "generalized source shouldn't be assignable", + ); generalizedSourceType = getTypeNameForErrorDisplay(generalizedSource); } // If `target` is of indexed access type (And `source` it is not), we use the object type of `target` for better error reporting - const targetFlags = target.flags & TypeFlags.IndexedAccess && !(source.flags & TypeFlags.IndexedAccess) ? - (target as IndexedAccessType).objectType.flags : - target.flags; + const targetFlags = target.flags & TypeFlags.IndexedAccess && !(source.flags & TypeFlags.IndexedAccess) + ? (target as IndexedAccessType).objectType.flags + : target.flags; - if (targetFlags & TypeFlags.TypeParameter && target !== markerSuperTypeForCheck && target !== markerSubTypeForCheck) { + if ( + targetFlags & TypeFlags.TypeParameter && target !== markerSuperTypeForCheck + && target !== markerSubTypeForCheck + ) { const constraint = getBaseConstraintOfType(target); let needsOriginalSource; - if (constraint && (isTypeAssignableTo(generalizedSource, constraint) || (needsOriginalSource = isTypeAssignableTo(source, constraint)))) { + if ( + constraint + && (isTypeAssignableTo(generalizedSource, constraint) + || (needsOriginalSource = isTypeAssignableTo(source, constraint))) + ) { reportError( - Diagnostics._0_is_assignable_to_the_constraint_of_type_1_but_1_could_be_instantiated_with_a_different_subtype_of_constraint_2, + Diagnostics + ._0_is_assignable_to_the_constraint_of_type_1_but_1_could_be_instantiated_with_a_different_subtype_of_constraint_2, needsOriginalSource ? sourceType : generalizedSourceType, targetType, typeToString(constraint), @@ -20897,16 +26705,26 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { message = Diagnostics.Type_0_is_not_comparable_to_type_1; } else if (sourceType === targetType) { - message = Diagnostics.Type_0_is_not_assignable_to_type_1_Two_different_types_with_this_name_exist_but_they_are_unrelated; + message = Diagnostics + .Type_0_is_not_assignable_to_type_1_Two_different_types_with_this_name_exist_but_they_are_unrelated; } else if (exactOptionalPropertyTypes && getExactOptionalUnassignableProperties(source, target).length) { - message = Diagnostics.Type_0_is_not_assignable_to_type_1_with_exactOptionalPropertyTypes_Colon_true_Consider_adding_undefined_to_the_types_of_the_target_s_properties; + message = Diagnostics + .Type_0_is_not_assignable_to_type_1_with_exactOptionalPropertyTypes_Colon_true_Consider_adding_undefined_to_the_types_of_the_target_s_properties; } else { if (source.flags & TypeFlags.StringLiteral && target.flags & TypeFlags.Union) { - const suggestedType = getSuggestedTypeForNonexistentStringLiteralType(source as StringLiteralType, target as UnionType); + const suggestedType = getSuggestedTypeForNonexistentStringLiteralType( + source as StringLiteralType, + target as UnionType, + ); if (suggestedType) { - reportError(Diagnostics.Type_0_is_not_assignable_to_type_1_Did_you_mean_2, generalizedSourceType, targetType, typeToString(suggestedType)); + reportError( + Diagnostics.Type_0_is_not_assignable_to_type_1_Did_you_mean_2, + generalizedSourceType, + targetType, + typeToString(suggestedType), + ); return; } } @@ -20918,23 +26736,30 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { && exactOptionalPropertyTypes && getExactOptionalUnassignableProperties(source, target).length ) { - message = Diagnostics.Argument_of_type_0_is_not_assignable_to_parameter_of_type_1_with_exactOptionalPropertyTypes_Colon_true_Consider_adding_undefined_to_the_types_of_the_target_s_properties; + message = Diagnostics + .Argument_of_type_0_is_not_assignable_to_parameter_of_type_1_with_exactOptionalPropertyTypes_Colon_true_Consider_adding_undefined_to_the_types_of_the_target_s_properties; } reportError(message, generalizedSourceType, targetType); } function tryElaborateErrorsForPrimitivesAndObjects(source: Type, target: Type) { - const sourceType = symbolValueDeclarationIsContextSensitive(source.symbol) ? typeToString(source, source.symbol.valueDeclaration) : typeToString(source); - const targetType = symbolValueDeclarationIsContextSensitive(target.symbol) ? typeToString(target, target.symbol.valueDeclaration) : typeToString(target); + const sourceType = symbolValueDeclarationIsContextSensitive(source.symbol) + ? typeToString(source, source.symbol.valueDeclaration) : typeToString(source); + const targetType = symbolValueDeclarationIsContextSensitive(target.symbol) + ? typeToString(target, target.symbol.valueDeclaration) : typeToString(target); if ( - (globalStringType === source && stringType === target) || - (globalNumberType === source && numberType === target) || - (globalBooleanType === source && booleanType === target) || - (getGlobalESSymbolType() === source && esSymbolType === target) + (globalStringType === source && stringType === target) + || (globalNumberType === source && numberType === target) + || (globalBooleanType === source && booleanType === target) + || (getGlobalESSymbolType() === source && esSymbolType === target) ) { - reportError(Diagnostics._0_is_a_primitive_but_1_is_a_wrapper_object_Prefer_using_0_when_possible, targetType, sourceType); + reportError( + Diagnostics._0_is_a_primitive_but_1_is_a_wrapper_object_Prefer_using_0_when_possible, + targetType, + sourceType, + ); } } @@ -20955,7 +26780,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (isTupleType(source)) { if (source.target.readonly && isMutableArrayOrTuple(target)) { if (reportErrors) { - reportError(Diagnostics.The_type_0_is_readonly_and_cannot_be_assigned_to_the_mutable_type_1, typeToString(source), typeToString(target)); + reportError( + Diagnostics.The_type_0_is_readonly_and_cannot_be_assigned_to_the_mutable_type_1, + typeToString(source), + typeToString(target), + ); } return false; } @@ -20963,7 +26792,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } if (isReadonlyArrayType(source) && isMutableArrayOrTuple(target)) { if (reportErrors) { - reportError(Diagnostics.The_type_0_is_readonly_and_cannot_be_assigned_to_the_mutable_type_1, typeToString(source), typeToString(target)); + reportError( + Diagnostics.The_type_0_is_readonly_and_cannot_be_assigned_to_the_mutable_type_1, + typeToString(source), + typeToString(target), + ); } return false; } @@ -20983,15 +26816,28 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { * * Ternary.Maybe if they are related with assumptions of other relationships, or * * Ternary.False if they are not related. */ - function isRelatedTo(originalSource: Type, originalTarget: Type, recursionFlags: RecursionFlags = RecursionFlags.Both, reportErrors = false, headMessage?: DiagnosticMessage, intersectionState = IntersectionState.None): Ternary { + function isRelatedTo( + originalSource: Type, + originalTarget: Type, + recursionFlags: RecursionFlags = RecursionFlags.Both, + reportErrors = false, + headMessage?: DiagnosticMessage, + intersectionState = IntersectionState.None, + ): Ternary { if (originalSource === originalTarget) return Ternary.True; // Before normalization: if `source` is type an object type, and `target` is primitive, // skip all the checks we don't need and just return `isSimpleTypeRelatedTo` result if (originalSource.flags & TypeFlags.Object && originalTarget.flags & TypeFlags.Primitive) { if ( - relation === comparableRelation && !(originalTarget.flags & TypeFlags.Never) && isSimpleTypeRelatedTo(originalTarget, originalSource, relation) || - isSimpleTypeRelatedTo(originalSource, originalTarget, relation, reportErrors ? reportError : undefined) + relation === comparableRelation && !(originalTarget.flags & TypeFlags.Never) + && isSimpleTypeRelatedTo(originalTarget, originalSource, relation) + || isSimpleTypeRelatedTo( + originalSource, + originalTarget, + relation, + reportErrors ? reportError : undefined, + ) ) { return Ternary.True; } @@ -21014,7 +26860,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (source.flags !== target.flags) return Ternary.False; if (source.flags & TypeFlags.Singleton) return Ternary.True; traceUnionsOrIntersectionsTooLarge(source, target); - return recursiveTypeRelatedTo(source, target, /*reportErrors*/ false, IntersectionState.None, recursionFlags); + return recursiveTypeRelatedTo( + source, + target, + /*reportErrors*/ false, + IntersectionState.None, + recursionFlags, + ); } // We fastpath comparing a type parameter to exactly its constraint, as this is _super_ common, @@ -21030,9 +26882,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // plus a single non-nullable type. If so, remove null and/or undefined from the target type. if (source.flags & TypeFlags.DefinitelyNonNullable && target.flags & TypeFlags.Union) { const types = (target as UnionType).types; - const candidate = types.length === 2 && types[0].flags & TypeFlags.Nullable ? types[1] : - types.length === 3 && types[0].flags & TypeFlags.Nullable && types[1].flags & TypeFlags.Nullable ? types[2] : - undefined; + const candidate = types.length === 2 && types[0].flags & TypeFlags.Nullable ? types[1] + : types.length === 3 && types[0].flags & TypeFlags.Nullable && types[1].flags & TypeFlags.Nullable + ? types[2] + : undefined; if (candidate && !(candidate.flags & TypeFlags.Nullable)) { target = getNormalizedType(candidate, /*writing*/ true); if (source === target) return Ternary.True; @@ -21040,41 +26893,73 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } if ( - relation === comparableRelation && !(target.flags & TypeFlags.Never) && isSimpleTypeRelatedTo(target, source, relation) || - isSimpleTypeRelatedTo(source, target, relation, reportErrors ? reportError : undefined) + relation === comparableRelation && !(target.flags & TypeFlags.Never) + && isSimpleTypeRelatedTo(target, source, relation) + || isSimpleTypeRelatedTo(source, target, relation, reportErrors ? reportError : undefined) ) return Ternary.True; - if (source.flags & TypeFlags.StructuredOrInstantiable || target.flags & TypeFlags.StructuredOrInstantiable) { - const isPerformingExcessPropertyChecks = !(intersectionState & IntersectionState.Target) && (isObjectLiteralType(source) && getObjectFlags(source) & ObjectFlags.FreshLiteral); + if ( + source.flags & TypeFlags.StructuredOrInstantiable || target.flags & TypeFlags.StructuredOrInstantiable + ) { + const isPerformingExcessPropertyChecks = !(intersectionState & IntersectionState.Target) + && (isObjectLiteralType(source) && getObjectFlags(source) & ObjectFlags.FreshLiteral); if (isPerformingExcessPropertyChecks) { if (hasExcessProperties(source as FreshObjectLiteralType, target, reportErrors)) { if (reportErrors) { - reportRelationError(headMessage, source, originalTarget.aliasSymbol ? originalTarget : target); + reportRelationError( + headMessage, + source, + originalTarget.aliasSymbol ? originalTarget : target, + ); } return Ternary.False; } } - const isPerformingCommonPropertyChecks = (relation !== comparableRelation || isUnitType(source)) && - !(intersectionState & IntersectionState.Target) && - source.flags & (TypeFlags.Primitive | TypeFlags.Object | TypeFlags.Intersection) && source !== globalObjectType && - target.flags & (TypeFlags.Object | TypeFlags.Intersection) && isWeakType(target) && - (getPropertiesOfType(source).length > 0 || typeHasCallOrConstructSignatures(source)); + const isPerformingCommonPropertyChecks = (relation !== comparableRelation || isUnitType(source)) + && !(intersectionState & IntersectionState.Target) + && source.flags & (TypeFlags.Primitive | TypeFlags.Object | TypeFlags.Intersection) + && source !== globalObjectType + && target.flags & (TypeFlags.Object | TypeFlags.Intersection) && isWeakType(target) + && (getPropertiesOfType(source).length > 0 || typeHasCallOrConstructSignatures(source)); const isComparingJsxAttributes = !!(getObjectFlags(source) & ObjectFlags.JsxAttributes); - if (isPerformingCommonPropertyChecks && !hasCommonProperties(source, target, isComparingJsxAttributes)) { + if ( + isPerformingCommonPropertyChecks && !hasCommonProperties(source, target, isComparingJsxAttributes) + ) { if (reportErrors) { const sourceString = typeToString(originalSource.aliasSymbol ? originalSource : source); const targetString = typeToString(originalTarget.aliasSymbol ? originalTarget : target); const calls = getSignaturesOfType(source, SignatureKind.Call); const constructs = getSignaturesOfType(source, SignatureKind.Construct); if ( - calls.length > 0 && isRelatedTo(getReturnTypeOfSignature(calls[0]), target, RecursionFlags.Source, /*reportErrors*/ false) || - constructs.length > 0 && isRelatedTo(getReturnTypeOfSignature(constructs[0]), target, RecursionFlags.Source, /*reportErrors*/ false) + calls.length > 0 + && isRelatedTo( + getReturnTypeOfSignature(calls[0]), + target, + RecursionFlags.Source, + /*reportErrors*/ false, + ) + || constructs.length > 0 + && isRelatedTo( + getReturnTypeOfSignature(constructs[0]), + target, + RecursionFlags.Source, + /*reportErrors*/ false, + ) ) { - reportError(Diagnostics.Value_of_type_0_has_no_properties_in_common_with_type_1_Did_you_mean_to_call_it, sourceString, targetString); + reportError( + Diagnostics + .Value_of_type_0_has_no_properties_in_common_with_type_1_Did_you_mean_to_call_it, + sourceString, + targetString, + ); } else { - reportError(Diagnostics.Type_0_has_no_properties_in_common_with_type_1, sourceString, targetString); + reportError( + Diagnostics.Type_0_has_no_properties_in_common_with_type_1, + sourceString, + targetString, + ); } } return Ternary.False; @@ -21082,11 +26967,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { traceUnionsOrIntersectionsTooLarge(source, target); - const skipCaching = source.flags & TypeFlags.Union && (source as UnionType).types.length < 4 && !(target.flags & TypeFlags.Union) || - target.flags & TypeFlags.Union && (target as UnionType).types.length < 4 && !(source.flags & TypeFlags.StructuredOrInstantiable); - const result = skipCaching ? - unionOrIntersectionRelatedTo(source, target, reportErrors, intersectionState) : - recursiveTypeRelatedTo(source, target, reportErrors, intersectionState, recursionFlags); + const skipCaching = source.flags & TypeFlags.Union && (source as UnionType).types.length < 4 + && !(target.flags & TypeFlags.Union) + || target.flags & TypeFlags.Union && (target as UnionType).types.length < 4 + && !(source.flags & TypeFlags.StructuredOrInstantiable); + const result = skipCaching + ? unionOrIntersectionRelatedTo(source, target, reportErrors, intersectionState) + : recursiveTypeRelatedTo(source, target, reportErrors, intersectionState, recursionFlags); if (result) { return result; } @@ -21098,7 +26985,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return Ternary.False; } - function reportErrorResults(originalSource: Type, originalTarget: Type, source: Type, target: Type, headMessage: DiagnosticMessage | undefined) { + function reportErrorResults( + originalSource: Type, + originalTarget: Type, + source: Type, + target: Type, + headMessage: DiagnosticMessage | undefined, + ) { const sourceHasBase = !!getSingleBaseForNonAugmentingSubtype(originalSource); const targetHasBase = !!getSingleBaseForNonAugmentingSubtype(originalTarget); source = (originalSource.aliasSymbol || sourceHasBase) ? originalSource : source; @@ -21118,15 +27011,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { tryElaborateErrorsForPrimitivesAndObjects(source, target); } else if (source.symbol && source.flags & TypeFlags.Object && globalObjectType === source) { - reportError(Diagnostics.The_Object_type_is_assignable_to_very_few_other_types_Did_you_mean_to_use_the_any_type_instead); + reportError( + Diagnostics + .The_Object_type_is_assignable_to_very_few_other_types_Did_you_mean_to_use_the_any_type_instead, + ); } else if (getObjectFlags(source) & ObjectFlags.JsxAttributes && target.flags & TypeFlags.Intersection) { const targetTypes = (target as IntersectionType).types; const intrinsicAttributes = getJsxType(JsxNames.IntrinsicAttributes, errorNode); const intrinsicClassAttributes = getJsxType(JsxNames.IntrinsicClassAttributes, errorNode); if ( - !isErrorType(intrinsicAttributes) && !isErrorType(intrinsicClassAttributes) && - (contains(targetTypes, intrinsicAttributes) || contains(targetTypes, intrinsicClassAttributes)) + !isErrorType(intrinsicAttributes) && !isErrorType(intrinsicClassAttributes) + && (contains(targetTypes, intrinsicAttributes) || contains(targetTypes, intrinsicClassAttributes)) ) { // do not report top error return; @@ -21141,12 +27037,21 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return; } reportRelationError(headMessage, source, target); - if (source.flags & TypeFlags.TypeParameter && source.symbol?.declarations?.[0] && !getConstraintOfType(source as TypeVariable)) { + if ( + source.flags & TypeFlags.TypeParameter && source.symbol?.declarations?.[0] + && !getConstraintOfType(source as TypeVariable) + ) { const syntheticParam = cloneTypeParameter(source as TypeParameter); syntheticParam.constraint = instantiateType(target, makeUnaryTypeMapper(source, syntheticParam)); if (hasNonCircularBaseConstraint(syntheticParam)) { const targetConstraintString = typeToString(target, source.symbol.declarations[0]); - associateRelatedInfo(createDiagnosticForNode(source.symbol.declarations[0], Diagnostics.This_type_parameter_might_need_an_extends_0_constraint, targetConstraintString)); + associateRelatedInfo( + createDiagnosticForNode( + source.symbol.declarations[0], + Diagnostics.This_type_parameter_might_need_an_extends_0_constraint, + targetConstraintString, + ), + ); } } } @@ -21160,7 +27065,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const sourceUnionOrIntersection = source as UnionOrIntersectionType; const targetUnionOrIntersection = target as UnionOrIntersectionType; - if (sourceUnionOrIntersection.objectFlags & targetUnionOrIntersection.objectFlags & ObjectFlags.PrimitiveUnion) { + if ( + sourceUnionOrIntersection.objectFlags & targetUnionOrIntersection.objectFlags + & ObjectFlags.PrimitiveUnion + ) { // There's a fast path for comparing primitive unions return; } @@ -21183,29 +27091,37 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function getTypeOfPropertyInTypes(types: Type[], name: __String) { const appendPropType = (propTypes: Type[] | undefined, type: Type) => { type = getApparentType(type); - const prop = type.flags & TypeFlags.UnionOrIntersection ? getPropertyOfUnionOrIntersectionType(type as UnionOrIntersectionType, name) : getPropertyOfObjectType(type, name); - const propType = prop && getTypeOfSymbol(prop) || getApplicableIndexInfoForName(type, name)?.type || undefinedType; + const prop = type.flags & TypeFlags.UnionOrIntersection + ? getPropertyOfUnionOrIntersectionType(type as UnionOrIntersectionType, name) + : getPropertyOfObjectType(type, name); + const propType = prop && getTypeOfSymbol(prop) || getApplicableIndexInfoForName(type, name)?.type + || undefinedType; return append(propTypes, propType); }; return getUnionType(reduceLeft(types, appendPropType, /*initial*/ undefined) || emptyArray); } function hasExcessProperties(source: FreshObjectLiteralType, target: Type, reportErrors: boolean): boolean { - if (!isExcessPropertyCheckTarget(target) || !noImplicitAny && getObjectFlags(target) & ObjectFlags.JSLiteral) { + if ( + !isExcessPropertyCheckTarget(target) || !noImplicitAny && getObjectFlags(target) & ObjectFlags.JSLiteral + ) { return false; // Disable excess property checks on JS literals to simulate having an implicit "index signature" - but only outside of noImplicitAny } const isComparingJsxAttributes = !!(getObjectFlags(source) & ObjectFlags.JsxAttributes); if ( - (relation === assignableRelation || relation === comparableRelation) && - (isTypeSubsetOf(globalObjectType, target) || (!isComparingJsxAttributes && isEmptyObjectType(target))) + (relation === assignableRelation || relation === comparableRelation) + && (isTypeSubsetOf(globalObjectType, target) + || (!isComparingJsxAttributes && isEmptyObjectType(target))) ) { return false; } let reducedTarget = target; let checkTypes: Type[] | undefined; if (target.flags & TypeFlags.Union) { - reducedTarget = findMatchingDiscriminantType(source, target as UnionType, isRelatedTo) || filterPrimitivesIfContainsNonPrimitive(target as UnionType); - checkTypes = reducedTarget.flags & TypeFlags.Union ? (reducedTarget as UnionType).types : [reducedTarget]; + reducedTarget = findMatchingDiscriminantType(source, target as UnionType, isRelatedTo) + || filterPrimitivesIfContainsNonPrimitive(target as UnionType); + checkTypes = reducedTarget.flags & TypeFlags.Union ? (reducedTarget as UnionType).types + : [reducedTarget]; } for (const prop of getPropertiesOfType(source)) { if (shouldCheckAsExcessProperty(prop, source.symbol) && !isIgnoredJsxProperty(source, prop)) { @@ -21218,29 +27134,53 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // Use this property as the error node as this will be more helpful in // reasoning about what went wrong. if (!errorNode) return Debug.fail(); - if (isJsxAttributes(errorNode) || isJsxOpeningLikeElement(errorNode) || isJsxOpeningLikeElement(errorNode.parent)) { + if ( + isJsxAttributes(errorNode) || isJsxOpeningLikeElement(errorNode) + || isJsxOpeningLikeElement(errorNode.parent) + ) { // JsxAttributes has an object-literal flag and undergo same type-assignablity check as normal object-literal. // However, using an object-literal error message will be very confusing to the users so we give different a message. - if (prop.valueDeclaration && isJsxAttribute(prop.valueDeclaration) && getSourceFileOfNode(errorNode) === getSourceFileOfNode(prop.valueDeclaration.name)) { + if ( + prop.valueDeclaration && isJsxAttribute(prop.valueDeclaration) + && getSourceFileOfNode(errorNode) + === getSourceFileOfNode(prop.valueDeclaration.name) + ) { // Note that extraneous children (as in `extra`) don't pass this check, // since `children` is a SyntaxKind.PropertySignature instead of a SyntaxKind.JsxAttribute. errorNode = prop.valueDeclaration.name; } const propName = symbolToString(prop); - const suggestionSymbol = getSuggestedSymbolForNonexistentJSXAttribute(propName, errorTarget); + const suggestionSymbol = getSuggestedSymbolForNonexistentJSXAttribute( + propName, + errorTarget, + ); const suggestion = suggestionSymbol ? symbolToString(suggestionSymbol) : undefined; if (suggestion) { - reportError(Diagnostics.Property_0_does_not_exist_on_type_1_Did_you_mean_2, propName, typeToString(errorTarget), suggestion); + reportError( + Diagnostics.Property_0_does_not_exist_on_type_1_Did_you_mean_2, + propName, + typeToString(errorTarget), + suggestion, + ); } else { - reportError(Diagnostics.Property_0_does_not_exist_on_type_1, propName, typeToString(errorTarget)); + reportError( + Diagnostics.Property_0_does_not_exist_on_type_1, + propName, + typeToString(errorTarget), + ); } } else { // use the property's value declaration if the property is assigned inside the literal itself - const objectLiteralDeclaration = source.symbol?.declarations && firstOrUndefined(source.symbol.declarations); + const objectLiteralDeclaration = source.symbol?.declarations + && firstOrUndefined(source.symbol.declarations); let suggestion: string | undefined; - if (prop.valueDeclaration && findAncestor(prop.valueDeclaration, d => d === objectLiteralDeclaration) && getSourceFileOfNode(objectLiteralDeclaration) === getSourceFileOfNode(errorNode)) { + if ( + prop.valueDeclaration && findAncestor(prop.valueDeclaration, d => + d === objectLiteralDeclaration) + && getSourceFileOfNode(objectLiteralDeclaration) === getSourceFileOfNode(errorNode) + ) { const propDeclaration = prop.valueDeclaration as ObjectLiteralElementLike; Debug.assertNode(propDeclaration, isObjectLiteralElementLike); @@ -21252,18 +27192,40 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } if (suggestion !== undefined) { - reportParentSkippedError(Diagnostics.Object_literal_may_only_specify_known_properties_but_0_does_not_exist_in_type_1_Did_you_mean_to_write_2, symbolToString(prop), typeToString(errorTarget), suggestion); + reportParentSkippedError( + Diagnostics + .Object_literal_may_only_specify_known_properties_but_0_does_not_exist_in_type_1_Did_you_mean_to_write_2, + symbolToString(prop), + typeToString(errorTarget), + suggestion, + ); } else { - reportParentSkippedError(Diagnostics.Object_literal_may_only_specify_known_properties_and_0_does_not_exist_in_type_1, symbolToString(prop), typeToString(errorTarget)); + reportParentSkippedError( + Diagnostics + .Object_literal_may_only_specify_known_properties_and_0_does_not_exist_in_type_1, + symbolToString(prop), + typeToString(errorTarget), + ); } } } return true; } - if (checkTypes && !isRelatedTo(getTypeOfSymbol(prop), getTypeOfPropertyInTypes(checkTypes, prop.escapedName), RecursionFlags.Both, reportErrors)) { + if ( + checkTypes + && !isRelatedTo( + getTypeOfSymbol(prop), + getTypeOfPropertyInTypes(checkTypes, prop.escapedName), + RecursionFlags.Both, + reportErrors, + ) + ) { if (reportErrors) { - reportIncompatibleError(Diagnostics.Types_of_property_0_are_incompatible, symbolToString(prop)); + reportIncompatibleError( + Diagnostics.Types_of_property_0_are_incompatible, + symbolToString(prop), + ); } return true; } @@ -21273,23 +27235,48 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function shouldCheckAsExcessProperty(prop: Symbol, container: Symbol) { - return prop.valueDeclaration && container.valueDeclaration && prop.valueDeclaration.parent === container.valueDeclaration; + return prop.valueDeclaration && container.valueDeclaration + && prop.valueDeclaration.parent === container.valueDeclaration; } - function unionOrIntersectionRelatedTo(source: Type, target: Type, reportErrors: boolean, intersectionState: IntersectionState): Ternary { + function unionOrIntersectionRelatedTo( + source: Type, + target: Type, + reportErrors: boolean, + intersectionState: IntersectionState, + ): Ternary { // Note that these checks are specifically ordered to produce correct results. In particular, // we need to deconstruct unions before intersections (because unions are always at the top), // and we need to handle "each" relations before "some" relations for the same kind of type. if (source.flags & TypeFlags.Union) { - return relation === comparableRelation ? - someTypeRelatedToType(source as UnionType, target, reportErrors && !(source.flags & TypeFlags.Primitive), intersectionState) : - eachTypeRelatedToType(source as UnionType, target, reportErrors && !(source.flags & TypeFlags.Primitive), intersectionState); + return relation === comparableRelation + ? someTypeRelatedToType( + source as UnionType, + target, + reportErrors && !(source.flags & TypeFlags.Primitive), + intersectionState, + ) + : eachTypeRelatedToType( + source as UnionType, + target, + reportErrors && !(source.flags & TypeFlags.Primitive), + intersectionState, + ); } if (target.flags & TypeFlags.Union) { - return typeRelatedToSomeType(getRegularTypeOfObjectLiteral(source), target as UnionType, reportErrors && !(source.flags & TypeFlags.Primitive) && !(target.flags & TypeFlags.Primitive)); + return typeRelatedToSomeType( + getRegularTypeOfObjectLiteral(source), + target as UnionType, + reportErrors && !(source.flags & TypeFlags.Primitive) && !(target.flags & TypeFlags.Primitive), + ); } if (target.flags & TypeFlags.Intersection) { - return typeRelatedToEachType(source, target as IntersectionType, reportErrors, IntersectionState.Target); + return typeRelatedToEachType( + source, + target as IntersectionType, + reportErrors, + IntersectionState.Target, + ); } // Source is an intersection. For the comparable relation, if the target is a primitive type we hoist the // constraints of all non-primitive types in the source into a new intersection. We do this because the @@ -21297,15 +27284,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // parameter 'T extends 1 | 2', the intersection 'T & 1' should be reduced to '1' such that it doesn't // appear to be comparable to '2'. if (relation === comparableRelation && target.flags & TypeFlags.Primitive) { - const constraints = sameMap((source as IntersectionType).types, t => t.flags & TypeFlags.Instantiable ? getBaseConstraintOfType(t) || unknownType : t); + const constraints = sameMap( + (source as IntersectionType).types, + t => t.flags & TypeFlags.Instantiable ? getBaseConstraintOfType(t) || unknownType : t, + ); if (constraints !== (source as IntersectionType).types) { source = getIntersectionType(constraints); if (source.flags & TypeFlags.Never) { return Ternary.False; } if (!(source.flags & TypeFlags.Intersection)) { - return isRelatedTo(source, target, RecursionFlags.Source, /*reportErrors*/ false) || - isRelatedTo(target, source, RecursionFlags.Source, /*reportErrors*/ false); + return isRelatedTo(source, target, RecursionFlags.Source, /*reportErrors*/ false) + || isRelatedTo(target, source, RecursionFlags.Source, /*reportErrors*/ false); } } } @@ -21313,7 +27303,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // Don't report errors though. Elaborating on whether a source constituent is related to the target is // not actually useful and leads to some confusing error messages. Instead, we rely on the caller // checking whether the full intersection viewed as an object is related to the target. - return someTypeRelatedToType(source as IntersectionType, target, /*reportErrors*/ false, IntersectionState.Source); + return someTypeRelatedToType( + source as IntersectionType, + target, + /*reportErrors*/ false, + IntersectionState.Source, + ); } function eachTypeRelatedToSomeType(source: UnionOrIntersectionType, target: UnionOrIntersectionType): Ternary { @@ -21336,9 +27331,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return Ternary.True; } if ( - relation !== comparableRelation && getObjectFlags(target) & ObjectFlags.PrimitiveUnion && !(source.flags & TypeFlags.EnumLiteral) && ( - source.flags & (TypeFlags.StringLiteral | TypeFlags.BooleanLiteral | TypeFlags.BigIntLiteral) || - (relation === subtypeRelation || relation === strictSubtypeRelation) && source.flags & TypeFlags.NumberLiteral + relation !== comparableRelation && getObjectFlags(target) & ObjectFlags.PrimitiveUnion + && !(source.flags & TypeFlags.EnumLiteral) && ( + source.flags & (TypeFlags.StringLiteral | TypeFlags.BooleanLiteral | TypeFlags.BigIntLiteral) + || (relation === subtypeRelation || relation === strictSubtypeRelation) + && source.flags & TypeFlags.NumberLiteral ) ) { // When relating a literal type to a union of primitive types, we know the relation is false unless @@ -21347,12 +27344,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // numeric enum literals with the same value. Similarly, we exclude enum literal types because // identically named enum types are related (see isEnumTypeRelatedTo). We exclude the comparable // relation in entirety because it needs to be checked in both directions. - const alternateForm = source === (source as StringLiteralType).regularType ? (source as StringLiteralType).freshType : (source as StringLiteralType).regularType; - const primitive = source.flags & TypeFlags.StringLiteral ? stringType : - source.flags & TypeFlags.NumberLiteral ? numberType : - source.flags & TypeFlags.BigIntLiteral ? bigintType : - undefined; - return primitive && containsType(targetTypes, primitive) || alternateForm && containsType(targetTypes, alternateForm) ? Ternary.True : Ternary.False; + const alternateForm = source === (source as StringLiteralType).regularType + ? (source as StringLiteralType).freshType : (source as StringLiteralType).regularType; + const primitive = source.flags & TypeFlags.StringLiteral ? stringType + : source.flags & TypeFlags.NumberLiteral ? numberType + : source.flags & TypeFlags.BigIntLiteral ? bigintType + : undefined; + return primitive && containsType(targetTypes, primitive) + || alternateForm && containsType(targetTypes, alternateForm) ? Ternary.True : Ternary.False; } const match = getMatchingUnionConstituentForType(target as UnionType, source); if (match) { @@ -21378,11 +27377,23 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return Ternary.False; } - function typeRelatedToEachType(source: Type, target: IntersectionType, reportErrors: boolean, intersectionState: IntersectionState): Ternary { + function typeRelatedToEachType( + source: Type, + target: IntersectionType, + reportErrors: boolean, + intersectionState: IntersectionState, + ): Ternary { let result = Ternary.True; const targetTypes = target.types; for (const targetType of targetTypes) { - const related = isRelatedTo(source, targetType, RecursionFlags.Target, reportErrors, /*headMessage*/ undefined, intersectionState); + const related = isRelatedTo( + source, + targetType, + RecursionFlags.Target, + reportErrors, + /*headMessage*/ undefined, + intersectionState, + ); if (!related) { return Ternary.False; } @@ -21391,14 +27402,26 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return result; } - function someTypeRelatedToType(source: UnionOrIntersectionType, target: Type, reportErrors: boolean, intersectionState: IntersectionState): Ternary { + function someTypeRelatedToType( + source: UnionOrIntersectionType, + target: Type, + reportErrors: boolean, + intersectionState: IntersectionState, + ): Ternary { const sourceTypes = source.types; if (source.flags & TypeFlags.Union && containsType(sourceTypes, target)) { return Ternary.True; } const len = sourceTypes.length; for (let i = 0; i < len; i++) { - const related = isRelatedTo(sourceTypes[i], target, RecursionFlags.Source, reportErrors && i === len - 1, /*headMessage*/ undefined, intersectionState); + const related = isRelatedTo( + sourceTypes[i], + target, + RecursionFlags.Source, + reportErrors && i === len - 1, + /*headMessage*/ undefined, + intersectionState, + ); if (related) { return related; } @@ -21408,15 +27431,21 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function getUndefinedStrippedTargetIfNeeded(source: Type, target: Type) { if ( - source.flags & TypeFlags.Union && target.flags & TypeFlags.Union && - !((source as UnionType).types[0].flags & TypeFlags.Undefined) && (target as UnionType).types[0].flags & TypeFlags.Undefined + source.flags & TypeFlags.Union && target.flags & TypeFlags.Union + && !((source as UnionType).types[0].flags & TypeFlags.Undefined) + && (target as UnionType).types[0].flags & TypeFlags.Undefined ) { return extractTypesOfKind(target, ~TypeFlags.Undefined); } return target; } - function eachTypeRelatedToType(source: UnionOrIntersectionType, target: Type, reportErrors: boolean, intersectionState: IntersectionState): Ternary { + function eachTypeRelatedToType( + source: UnionOrIntersectionType, + target: Type, + reportErrors: boolean, + intersectionState: IntersectionState, + ): Ternary { let result = Ternary.True; const sourceTypes = source.types; // We strip `undefined` from the target if the `source` trivially doesn't contain it for our correspondence-checking fastpath @@ -21424,19 +27453,38 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const undefinedStrippedTarget = getUndefinedStrippedTargetIfNeeded(source, target as UnionType); for (let i = 0; i < sourceTypes.length; i++) { const sourceType = sourceTypes[i]; - if (undefinedStrippedTarget.flags & TypeFlags.Union && sourceTypes.length >= (undefinedStrippedTarget as UnionType).types.length && sourceTypes.length % (undefinedStrippedTarget as UnionType).types.length === 0) { + if ( + undefinedStrippedTarget.flags & TypeFlags.Union + && sourceTypes.length >= (undefinedStrippedTarget as UnionType).types.length + && sourceTypes.length % (undefinedStrippedTarget as UnionType).types.length === 0 + ) { // many unions are mappings of one another; in such cases, simply comparing members at the same index can shortcut the comparison // such unions will have identical lengths, and their corresponding elements will match up. Another common scenario is where a large // union has a union of objects intersected with it. In such cases, if the input was, eg `("a" | "b" | "c") & (string | boolean | {} | {whatever})`, // the result will have the structure `"a" | "b" | "c" | "a" & {} | "b" & {} | "c" & {} | "a" & {whatever} | "b" & {whatever} | "c" & {whatever}` // - the resulting union has a length which is a multiple of the original union, and the elements correspond modulo the length of the original union - const related = isRelatedTo(sourceType, (undefinedStrippedTarget as UnionType).types[i % (undefinedStrippedTarget as UnionType).types.length], RecursionFlags.Both, /*reportErrors*/ false, /*headMessage*/ undefined, intersectionState); + const related = isRelatedTo( + sourceType, + (undefinedStrippedTarget as UnionType) + .types[i % (undefinedStrippedTarget as UnionType).types.length], + RecursionFlags.Both, + /*reportErrors*/ false, + /*headMessage*/ undefined, + intersectionState, + ); if (related) { result &= related; continue; } } - const related = isRelatedTo(sourceType, target, RecursionFlags.Source, reportErrors, /*headMessage*/ undefined, intersectionState); + const related = isRelatedTo( + sourceType, + target, + RecursionFlags.Source, + reportErrors, + /*headMessage*/ undefined, + intersectionState, + ); if (!related) { return Ternary.False; } @@ -21445,7 +27493,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return result; } - function typeArgumentsRelatedTo(sources: readonly Type[] = emptyArray, targets: readonly Type[] = emptyArray, variances: readonly VarianceFlags[] = emptyArray, reportErrors: boolean, intersectionState: IntersectionState): Ternary { + function typeArgumentsRelatedTo( + sources: readonly Type[] = emptyArray, + targets: readonly Type[] = emptyArray, + variances: readonly VarianceFlags[] = emptyArray, + reportErrors: boolean, + intersectionState: IntersectionState, + ): Ternary { if (sources.length !== targets.length && relation === identityRelation) { return Ternary.False; } @@ -21466,13 +27520,29 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // Even an `Unmeasurable` variance works out without a structural check if the source and target are _identical_. // We can't simply assume invariance, because `Unmeasurable` marks nonlinear relations, for example, a relation tained by // the `-?` modifier in a mapped type (where, no matter how the inputs are related, the outputs still might not be) - related = relation === identityRelation ? isRelatedTo(s, t, RecursionFlags.Both, /*reportErrors*/ false) : compareTypesIdentical(s, t); + related = relation === identityRelation + ? isRelatedTo(s, t, RecursionFlags.Both, /*reportErrors*/ false) + : compareTypesIdentical(s, t); } else if (variance === VarianceFlags.Covariant) { - related = isRelatedTo(s, t, RecursionFlags.Both, reportErrors, /*headMessage*/ undefined, intersectionState); + related = isRelatedTo( + s, + t, + RecursionFlags.Both, + reportErrors, + /*headMessage*/ undefined, + intersectionState, + ); } else if (variance === VarianceFlags.Contravariant) { - related = isRelatedTo(t, s, RecursionFlags.Both, reportErrors, /*headMessage*/ undefined, intersectionState); + related = isRelatedTo( + t, + s, + RecursionFlags.Both, + reportErrors, + /*headMessage*/ undefined, + intersectionState, + ); } else if (variance === VarianceFlags.Bivariant) { // In the bivariant case we first compare contravariantly without reporting @@ -21481,16 +27551,37 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // which is generally easier to reason about. related = isRelatedTo(t, s, RecursionFlags.Both, /*reportErrors*/ false); if (!related) { - related = isRelatedTo(s, t, RecursionFlags.Both, reportErrors, /*headMessage*/ undefined, intersectionState); + related = isRelatedTo( + s, + t, + RecursionFlags.Both, + reportErrors, + /*headMessage*/ undefined, + intersectionState, + ); } } else { // In the invariant case we first compare covariantly, and only when that // succeeds do we proceed to compare contravariantly. Thus, error elaboration // will typically be based on the covariant check. - related = isRelatedTo(s, t, RecursionFlags.Both, reportErrors, /*headMessage*/ undefined, intersectionState); + related = isRelatedTo( + s, + t, + RecursionFlags.Both, + reportErrors, + /*headMessage*/ undefined, + intersectionState, + ); if (related) { - related &= isRelatedTo(t, s, RecursionFlags.Both, reportErrors, /*headMessage*/ undefined, intersectionState); + related &= isRelatedTo( + t, + s, + RecursionFlags.Both, + reportErrors, + /*headMessage*/ undefined, + intersectionState, + ); } } if (!related) { @@ -21507,14 +27598,23 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // Third, check if both types are part of deeply nested chains of generic type instantiations and if so assume the types are // equal and infinitely expanding. Fourth, if we have reached a depth of 100 nested comparisons, assume we have runaway recursion // and issue an error. Otherwise, actually compare the structure of the two types. - function recursiveTypeRelatedTo(source: Type, target: Type, reportErrors: boolean, intersectionState: IntersectionState, recursionFlags: RecursionFlags): Ternary { + function recursiveTypeRelatedTo( + source: Type, + target: Type, + reportErrors: boolean, + intersectionState: IntersectionState, + recursionFlags: RecursionFlags, + ): Ternary { if (overflow) { return Ternary.False; } const id = getRelationKey(source, target, intersectionState, relation, /*ignoreConstraints*/ false); const entry = relation.get(id); if (entry !== undefined) { - if (reportErrors && entry & RelationComparisonResult.Failed && !(entry & RelationComparisonResult.Reported)) { + if ( + reportErrors && entry & RelationComparisonResult.Failed + && !(entry & RelationComparisonResult.Reported) + ) { // We are elaborating errors and the cached result is an unreported failure. The result will be reported // as a failure, and should be updated as a reported failure by the bottom of this function. } @@ -21547,7 +27647,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // A key that starts with "*" is an indication that we have type references that reference constrained // type parameters. For such keys we also check against the key we would have gotten if all type parameters // were unconstrained. - const broadestEquivalentId = id.startsWith("*") ? getRelationKey(source, target, intersectionState, relation, /*ignoreConstraints*/ true) : undefined; + const broadestEquivalentId = id.startsWith("*") + ? getRelationKey(source, target, intersectionState, relation, /*ignoreConstraints*/ true) + : undefined; if (broadestEquivalentId && maybeKeysSet.has(broadestEquivalentId)) { return Ternary.Maybe; } @@ -21565,19 +27667,24 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (recursionFlags & RecursionFlags.Source) { sourceStack[sourceDepth] = source; sourceDepth++; - if (!(expandingFlags & ExpandingFlags.Source) && isDeeplyNestedType(source, sourceStack, sourceDepth)) expandingFlags |= ExpandingFlags.Source; + if (!(expandingFlags & ExpandingFlags.Source) && isDeeplyNestedType(source, sourceStack, sourceDepth)) { + expandingFlags |= ExpandingFlags.Source; + } } if (recursionFlags & RecursionFlags.Target) { targetStack[targetDepth] = target; targetDepth++; - if (!(expandingFlags & ExpandingFlags.Target) && isDeeplyNestedType(target, targetStack, targetDepth)) expandingFlags |= ExpandingFlags.Target; + if (!(expandingFlags & ExpandingFlags.Target) && isDeeplyNestedType(target, targetStack, targetDepth)) { + expandingFlags |= ExpandingFlags.Target; + } } let originalHandler: typeof outofbandVarianceMarkerHandler; let propagatingVarianceFlags = 0 as RelationComparisonResult; if (outofbandVarianceMarkerHandler) { originalHandler = outofbandVarianceMarkerHandler; outofbandVarianceMarkerHandler = onlyUnreliable => { - propagatingVarianceFlags |= onlyUnreliable ? RelationComparisonResult.ReportsUnreliable : RelationComparisonResult.ReportsUnmeasurable; + propagatingVarianceFlags |= onlyUnreliable ? RelationComparisonResult.ReportsUnreliable + : RelationComparisonResult.ReportsUnmeasurable; return originalHandler!(onlyUnreliable); }; } @@ -21595,7 +27702,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { result = Ternary.Maybe; } else { - tracing?.push(tracing.Phase.CheckTypes, "structuredTypeRelatedTo", { sourceId: source.id, targetId: target.id }); + tracing?.push(tracing.Phase.CheckTypes, "structuredTypeRelatedTo", { + sourceId: source.id, + targetId: target.id, + }); result = structuredTypeRelatedTo(source, target, reportErrors, intersectionState); tracing?.pop(); } @@ -21628,7 +27738,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { else { // A false result goes straight into global cache (when something is false under // assumptions it will also be false without assumptions) - relation.set(id, (reportErrors ? RelationComparisonResult.Reported : 0) | RelationComparisonResult.Failed | propagatingVarianceFlags); + relation.set( + id, + (reportErrors ? RelationComparisonResult.Reported : 0) | RelationComparisonResult.Failed + | propagatingVarianceFlags, + ); resetMaybeStack(/*markAllAsSucceeded*/ false); } return result; @@ -21644,7 +27758,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } - function structuredTypeRelatedTo(source: Type, target: Type, reportErrors: boolean, intersectionState: IntersectionState): Ternary { + function structuredTypeRelatedTo( + source: Type, + target: Type, + reportErrors: boolean, + intersectionState: IntersectionState, + ): Ternary { const saveErrorInfo = captureErrorCalculationState(); let result = structuredTypeRelatedToWorker(source, target, reportErrors, intersectionState, saveErrorInfo); if (relation !== identityRelation) { @@ -21661,11 +27780,25 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // needs to have its constraint hoisted into an intersection with said type parameter, this way // the type param can be compared with itself in the target (with the influence of its constraint to match other parts) // For example, if `T extends 1 | 2` and `U extends 2 | 3` and we compare `T & U` to `T & U & (1 | 2 | 3)` - if (!result && (source.flags & TypeFlags.Intersection || source.flags & TypeFlags.TypeParameter && target.flags & TypeFlags.Union)) { - const constraint = getEffectiveConstraintOfIntersection(source.flags & TypeFlags.Intersection ? (source as IntersectionType).types : [source], !!(target.flags & TypeFlags.Union)); + if ( + !result + && (source.flags & TypeFlags.Intersection + || source.flags & TypeFlags.TypeParameter && target.flags & TypeFlags.Union) + ) { + const constraint = getEffectiveConstraintOfIntersection( + source.flags & TypeFlags.Intersection ? (source as IntersectionType).types : [source], + !!(target.flags & TypeFlags.Union), + ); if (constraint && everyType(constraint, c => c !== source)) { // Skip comparison if expansion contains the source itself // TODO: Stack errors so we get a pyramid for the "normal" comparison above, _and_ a second for this - result = isRelatedTo(constraint, target, RecursionFlags.Source, /*reportErrors*/ false, /*headMessage*/ undefined, intersectionState); + result = isRelatedTo( + constraint, + target, + RecursionFlags.Source, + /*reportErrors*/ false, + /*headMessage*/ undefined, + intersectionState, + ); } } // When the target is an intersection we need an extra property check in order to detect nested excess @@ -21678,12 +27811,25 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // let weak: { a?: { x?: number } } & { c?: string } = wrong; // Nested weak object type // if ( - result && !(intersectionState & IntersectionState.Target) && target.flags & TypeFlags.Intersection && - !isGenericObjectType(target) && source.flags & (TypeFlags.Object | TypeFlags.Intersection) + result && !(intersectionState & IntersectionState.Target) && target.flags & TypeFlags.Intersection + && !isGenericObjectType(target) && source.flags & (TypeFlags.Object | TypeFlags.Intersection) ) { - result &= propertiesRelatedTo(source, target, reportErrors, /*excludedProperties*/ undefined, /*optionalsOnly*/ false, IntersectionState.None); + result &= propertiesRelatedTo( + source, + target, + reportErrors, + /*excludedProperties*/ undefined, + /*optionalsOnly*/ false, + IntersectionState.None, + ); if (result && isObjectLiteralType(source) && getObjectFlags(source) & ObjectFlags.FreshLiteral) { - result &= indexSignaturesRelatedTo(source, target, /*sourceIsPrimitive*/ false, reportErrors, IntersectionState.None); + result &= indexSignaturesRelatedTo( + source, + target, + /*sourceIsPrimitive*/ false, + reportErrors, + IntersectionState.None, + ); } } // When the source is an intersection we need an extra check of any optional properties in the target to @@ -21694,11 +27840,21 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // } // else if ( - result && isNonGenericObjectType(target) && !isArrayOrTupleType(target) && - source.flags & TypeFlags.Intersection && getApparentType(source).flags & TypeFlags.StructuredType && - !some((source as IntersectionType).types, t => t === target || !!(getObjectFlags(t) & ObjectFlags.NonInferrableType)) + result && isNonGenericObjectType(target) && !isArrayOrTupleType(target) + && source.flags & TypeFlags.Intersection && getApparentType(source).flags & TypeFlags.StructuredType + && !some( + (source as IntersectionType).types, + t => t === target || !!(getObjectFlags(t) & ObjectFlags.NonInferrableType), + ) ) { - result &= propertiesRelatedTo(source, target, reportErrors, /*excludedProperties*/ undefined, /*optionalsOnly*/ true, intersectionState); + result &= propertiesRelatedTo( + source, + target, + reportErrors, + /*excludedProperties*/ undefined, + /*optionalsOnly*/ true, + intersectionState, + ); } } if (result) { @@ -21707,7 +27863,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return result; } - function structuredTypeRelatedToWorker(source: Type, target: Type, reportErrors: boolean, intersectionState: IntersectionState, saveErrorInfo: ReturnType): Ternary { + function structuredTypeRelatedToWorker( + source: Type, + target: Type, + reportErrors: boolean, + intersectionState: IntersectionState, + saveErrorInfo: ReturnType, + ): Ternary { let result: Ternary; let originalErrorInfo: DiagnosticMessageChain | undefined; let varianceCheckFailed = false; @@ -21716,28 +27878,84 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (relation === identityRelation) { // We've already checked that source.flags and target.flags are identical if (sourceFlags & TypeFlags.UnionOrIntersection) { - let result = eachTypeRelatedToSomeType(source as UnionOrIntersectionType, target as UnionOrIntersectionType); + let result = eachTypeRelatedToSomeType( + source as UnionOrIntersectionType, + target as UnionOrIntersectionType, + ); if (result) { - result &= eachTypeRelatedToSomeType(target as UnionOrIntersectionType, source as UnionOrIntersectionType); + result &= eachTypeRelatedToSomeType( + target as UnionOrIntersectionType, + source as UnionOrIntersectionType, + ); } return result; } if (sourceFlags & TypeFlags.Index) { - return isRelatedTo((source as IndexType).type, (target as IndexType).type, RecursionFlags.Both, /*reportErrors*/ false); + return isRelatedTo( + (source as IndexType).type, + (target as IndexType).type, + RecursionFlags.Both, + /*reportErrors*/ false, + ); } if (sourceFlags & TypeFlags.IndexedAccess) { - if (result = isRelatedTo((source as IndexedAccessType).objectType, (target as IndexedAccessType).objectType, RecursionFlags.Both, /*reportErrors*/ false)) { - if (result &= isRelatedTo((source as IndexedAccessType).indexType, (target as IndexedAccessType).indexType, RecursionFlags.Both, /*reportErrors*/ false)) { + if ( + result = isRelatedTo( + (source as IndexedAccessType).objectType, + (target as IndexedAccessType).objectType, + RecursionFlags.Both, + /*reportErrors*/ false, + ) + ) { + if ( + result &= isRelatedTo( + (source as IndexedAccessType).indexType, + (target as IndexedAccessType).indexType, + RecursionFlags.Both, + /*reportErrors*/ false, + ) + ) { return result; } } } if (sourceFlags & TypeFlags.Conditional) { - if ((source as ConditionalType).root.isDistributive === (target as ConditionalType).root.isDistributive) { - if (result = isRelatedTo((source as ConditionalType).checkType, (target as ConditionalType).checkType, RecursionFlags.Both, /*reportErrors*/ false)) { - if (result &= isRelatedTo((source as ConditionalType).extendsType, (target as ConditionalType).extendsType, RecursionFlags.Both, /*reportErrors*/ false)) { - if (result &= isRelatedTo(getTrueTypeFromConditionalType(source as ConditionalType), getTrueTypeFromConditionalType(target as ConditionalType), RecursionFlags.Both, /*reportErrors*/ false)) { - if (result &= isRelatedTo(getFalseTypeFromConditionalType(source as ConditionalType), getFalseTypeFromConditionalType(target as ConditionalType), RecursionFlags.Both, /*reportErrors*/ false)) { + if ( + (source as ConditionalType).root.isDistributive + === (target as ConditionalType).root.isDistributive + ) { + if ( + result = isRelatedTo( + (source as ConditionalType).checkType, + (target as ConditionalType).checkType, + RecursionFlags.Both, + /*reportErrors*/ false, + ) + ) { + if ( + result &= isRelatedTo( + (source as ConditionalType).extendsType, + (target as ConditionalType).extendsType, + RecursionFlags.Both, + /*reportErrors*/ false, + ) + ) { + if ( + result &= isRelatedTo( + getTrueTypeFromConditionalType(source as ConditionalType), + getTrueTypeFromConditionalType(target as ConditionalType), + RecursionFlags.Both, + /*reportErrors*/ false, + ) + ) { + if ( + result &= isRelatedTo( + getFalseTypeFromConditionalType(source as ConditionalType), + getFalseTypeFromConditionalType(target as ConditionalType), + RecursionFlags.Both, + /*reportErrors*/ false, + ) + ) { return result; } } @@ -21746,8 +27964,22 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } if (sourceFlags & TypeFlags.Substitution) { - if (result = isRelatedTo((source as SubstitutionType).baseType, (target as SubstitutionType).baseType, RecursionFlags.Both, /*reportErrors*/ false)) { - if (result &= isRelatedTo((source as SubstitutionType).constraint, (target as SubstitutionType).constraint, RecursionFlags.Both, /*reportErrors*/ false)) { + if ( + result = isRelatedTo( + (source as SubstitutionType).baseType, + (target as SubstitutionType).baseType, + RecursionFlags.Both, + /*reportErrors*/ false, + ) + ) { + if ( + result &= isRelatedTo( + (source as SubstitutionType).constraint, + (target as SubstitutionType).constraint, + RecursionFlags.Both, + /*reportErrors*/ false, + ) + ) { return result; } } @@ -21767,9 +27999,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // Source is an intersection, target is a union (e.g. { a } & { b: boolean } <=> { a, b: true } | { a, b: false }). // Source is an intersection, target instantiable (e.g. string & { tag } <=> T["a"] constrained to string & { tag }). if ( - !(sourceFlags & TypeFlags.Instantiable || - sourceFlags & TypeFlags.Object && targetFlags & TypeFlags.Union || - sourceFlags & TypeFlags.Intersection && targetFlags & (TypeFlags.Object | TypeFlags.Union | TypeFlags.Instantiable)) + !(sourceFlags & TypeFlags.Instantiable + || sourceFlags & TypeFlags.Object && targetFlags & TypeFlags.Union + || sourceFlags & TypeFlags.Intersection + && targetFlags & (TypeFlags.Object | TypeFlags.Union | TypeFlags.Instantiable)) ) { return Ternary.False; } @@ -21779,8 +28012,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // is more predictable than other, interned types, which may or may not have an alias depending on // the order in which things were checked. if ( - sourceFlags & (TypeFlags.Object | TypeFlags.Conditional) && source.aliasSymbol && source.aliasTypeArguments && - source.aliasSymbol === target.aliasSymbol && !(isMarkerType(source) || isMarkerType(target)) + sourceFlags & (TypeFlags.Object | TypeFlags.Conditional) && source.aliasSymbol + && source.aliasTypeArguments + && source.aliasSymbol === target.aliasSymbol && !(isMarkerType(source) || isMarkerType(target)) ) { const variances = getAliasVariances(source.aliasSymbol); if (variances === emptyArray) { @@ -21788,8 +28022,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } const params = getSymbolLinks(source.aliasSymbol).typeParameters!; const minParams = getMinTypeArgumentCount(params); - const sourceTypes = fillMissingTypeArguments(source.aliasTypeArguments, params, minParams, isInJSFile(source.aliasSymbol.valueDeclaration)); - const targetTypes = fillMissingTypeArguments(target.aliasTypeArguments, params, minParams, isInJSFile(source.aliasSymbol.valueDeclaration)); + const sourceTypes = fillMissingTypeArguments( + source.aliasTypeArguments, + params, + minParams, + isInJSFile(source.aliasSymbol.valueDeclaration), + ); + const targetTypes = fillMissingTypeArguments( + target.aliasTypeArguments, + params, + minParams, + isInJSFile(source.aliasSymbol.valueDeclaration), + ); const varianceResult = relateVariances(sourceTypes, targetTypes, variances, intersectionState); if (varianceResult !== undefined) { return varianceResult; @@ -21799,18 +28043,31 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // For a generic type T and a type U that is assignable to T, [...U] is assignable to T, U is assignable to readonly [...T], // and U is assignable to [...T] when U is constrained to a mutable array or tuple type. if ( - isSingleElementGenericTupleType(source) && !source.target.readonly && (result = isRelatedTo(getTypeArguments(source)[0], target, RecursionFlags.Source)) || - isSingleElementGenericTupleType(target) && (target.target.readonly || isMutableArrayOrTuple(getBaseConstraintOfType(source) || source)) && (result = isRelatedTo(source, getTypeArguments(target)[0], RecursionFlags.Target)) + isSingleElementGenericTupleType(source) && !source.target.readonly + && (result = isRelatedTo(getTypeArguments(source)[0], target, RecursionFlags.Source)) + || isSingleElementGenericTupleType(target) + && (target.target.readonly || isMutableArrayOrTuple(getBaseConstraintOfType(source) || source)) + && (result = isRelatedTo(source, getTypeArguments(target)[0], RecursionFlags.Target)) ) { return result; } if (targetFlags & TypeFlags.TypeParameter) { // A source type { [P in Q]: X } is related to a target type T if keyof T is related to Q and X is related to T[Q]. - if (getObjectFlags(source) & ObjectFlags.Mapped && !(source as MappedType).declaration.nameType && isRelatedTo(getIndexType(target), getConstraintTypeFromMappedType(source as MappedType), RecursionFlags.Both)) { + if ( + getObjectFlags(source) & ObjectFlags.Mapped && !(source as MappedType).declaration.nameType + && isRelatedTo( + getIndexType(target), + getConstraintTypeFromMappedType(source as MappedType), + RecursionFlags.Both, + ) + ) { if (!(getMappedTypeModifiers(source as MappedType) & MappedTypeModifiers.IncludeOptional)) { const templateType = getTemplateTypeFromMappedType(source as MappedType); - const indexedAccessType = getIndexedAccessType(target, getTypeParameterFromMappedType(source as MappedType)); + const indexedAccessType = getIndexedAccessType( + target, + getTypeParameterFromMappedType(source as MappedType), + ); if (result = isRelatedTo(templateType, indexedAccessType, RecursionFlags.Both, reportErrors)) { return result; } @@ -21822,7 +28079,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { let constraint = getConstraintOfTypeParameter(source); if (constraint && hasNonCircularBaseConstraint(source)) { while (constraint && someType(constraint, c => !!(c.flags & TypeFlags.TypeParameter))) { - if (result = isRelatedTo(constraint, target, RecursionFlags.Source, /*reportErrors*/ false)) { + if ( + result = isRelatedTo(constraint, target, RecursionFlags.Source, /*reportErrors*/ false) + ) { return result; } constraint = getConstraintOfTypeParameter(constraint); @@ -21835,14 +28094,28 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const targetType = (target as IndexType).type; // A keyof S is related to a keyof T if T is related to S. if (sourceFlags & TypeFlags.Index) { - if (result = isRelatedTo(targetType, (source as IndexType).type, RecursionFlags.Both, /*reportErrors*/ false)) { + if ( + result = isRelatedTo( + targetType, + (source as IndexType).type, + RecursionFlags.Both, + /*reportErrors*/ false, + ) + ) { return result; } } if (isTupleType(targetType)) { // An index type can have a tuple type target when the tuple type contains variadic elements. // Check if the source is related to the known keys of the tuple type. - if (result = isRelatedTo(source, getKnownKeysOfTupleType(targetType), RecursionFlags.Target, reportErrors)) { + if ( + result = isRelatedTo( + source, + getKnownKeysOfTupleType(targetType), + RecursionFlags.Target, + reportErrors, + ) + ) { return result; } } @@ -21855,7 +28128,17 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // false positives. For example, given 'T extends { [K in keyof T]: string }', // 'keyof T' has itself as its constraint and produces a Ternary.Maybe when // related to other types. - if (isRelatedTo(source, getIndexType(constraint, (target as IndexType).indexFlags | IndexFlags.NoReducibleCheck), RecursionFlags.Target, reportErrors) === Ternary.True) { + if ( + isRelatedTo( + source, + getIndexType( + constraint, + (target as IndexType).indexFlags | IndexFlags.NoReducibleCheck, + ), + RecursionFlags.Target, + reportErrors, + ) === Ternary.True + ) { return Ternary.True; } } @@ -21876,7 +28159,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { modifiersType, TypeFlags.StringOrNumberLiteralOrUnique, /*stringsOnly*/ false, - t => void mappedKeys.push(instantiateType(nameType, appendTypeMapping(targetType.mapper, getTypeParameterFromMappedType(targetType), t))), + t => void mappedKeys.push( + instantiateType( + nameType, + appendTypeMapping( + targetType.mapper, + getTypeParameterFromMappedType(targetType), + t, + ), + ), + ), ); // We still need to include the non-apparent (and thus still generic) keys in the target side of the comparison (in case they're in the source side) targetKeys = getUnionType([...mappedKeys, nameType]); @@ -21894,8 +28186,20 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (sourceFlags & TypeFlags.IndexedAccess) { // Relate components directly before falling back to constraint relationships // A type S[K] is related to a type T[J] if S is related to T and K is related to J. - if (result = isRelatedTo((source as IndexedAccessType).objectType, (target as IndexedAccessType).objectType, RecursionFlags.Both, reportErrors)) { - result &= isRelatedTo((source as IndexedAccessType).indexType, (target as IndexedAccessType).indexType, RecursionFlags.Both, reportErrors); + if ( + result = isRelatedTo( + (source as IndexedAccessType).objectType, + (target as IndexedAccessType).objectType, + RecursionFlags.Both, + reportErrors, + ) + ) { + result &= isRelatedTo( + (source as IndexedAccessType).indexType, + (target as IndexedAccessType).indexType, + RecursionFlags.Both, + reportErrors, + ); } if (result) { return result; @@ -21912,19 +28216,30 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const baseObjectType = getBaseConstraintOfType(objectType) || objectType; const baseIndexType = getBaseConstraintOfType(indexType) || indexType; if (!isGenericObjectType(baseObjectType) && !isGenericIndexType(baseIndexType)) { - const accessFlags = AccessFlags.Writing | (baseObjectType !== objectType ? AccessFlags.NoIndexSignatures : 0); + const accessFlags = AccessFlags.Writing + | (baseObjectType !== objectType ? AccessFlags.NoIndexSignatures : 0); const constraint = getIndexedAccessTypeOrUndefined(baseObjectType, baseIndexType, accessFlags); if (constraint) { if (reportErrors && originalErrorInfo) { // create a new chain for the constraint error resetErrorInfo(saveErrorInfo); } - if (result = isRelatedTo(source, constraint, RecursionFlags.Target, reportErrors, /*headMessage*/ undefined, intersectionState)) { + if ( + result = isRelatedTo( + source, + constraint, + RecursionFlags.Target, + reportErrors, + /*headMessage*/ undefined, + intersectionState, + ) + ) { return result; } // prefer the shorter chain of the constraint comparison chain, and the direct comparison chain if (reportErrors && originalErrorInfo && errorInfo) { - errorInfo = countMessageChainBreadth([originalErrorInfo]) <= countMessageChainBreadth([errorInfo]) ? originalErrorInfo : errorInfo; + errorInfo = countMessageChainBreadth([originalErrorInfo]) + <= countMessageChainBreadth([errorInfo]) ? originalErrorInfo : errorInfo; } } } @@ -21942,19 +28257,22 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // If the mapped type has shape `{ [P in Q]: T[P] }`, // source `S` is related to target if `T` = `S`, i.e. `S` is related to `{ [P in Q]: S[P] }`. if ( - !keysRemapped && templateType.flags & TypeFlags.IndexedAccess && (templateType as IndexedAccessType).objectType === source && - (templateType as IndexedAccessType).indexType === getTypeParameterFromMappedType(target) + !keysRemapped && templateType.flags & TypeFlags.IndexedAccess + && (templateType as IndexedAccessType).objectType === source + && (templateType as IndexedAccessType).indexType === getTypeParameterFromMappedType(target) ) { return Ternary.True; } if (!isGenericMappedType(source)) { // If target has shape `{ [P in Q as R]: T}`, then its keys have type `R`. // If target has shape `{ [P in Q]: T }`, then its keys have type `Q`. - const targetKeys = keysRemapped ? getNameTypeFromMappedType(target)! : getConstraintTypeFromMappedType(target); + const targetKeys = keysRemapped ? getNameTypeFromMappedType(target)! + : getConstraintTypeFromMappedType(target); // Type of the keys of source type `S`, i.e. `keyof S`. const sourceKeys = getIndexType(source, IndexFlags.NoIndexSignatures); const includeOptional = modifiers & MappedTypeModifiers.IncludeOptional; - const filteredByApplicability = includeOptional ? intersectTypes(targetKeys, sourceKeys) : undefined; + const filteredByApplicability = includeOptional ? intersectTypes(targetKeys, sourceKeys) + : undefined; // A source type `S` is related to a target type `{ [P in Q]: T }` if `Q` is related to `keyof S` and `S[Q]` is related to `T`. // A source type `S` is related to a target type `{ [P in Q as R]: T }` if `R` is related to `keyof S` and `S[R]` is related to `T. // A source type `S` is related to a target type `{ [P in Q]?: T }` if some constituent `Q'` of `Q` is related to `keyof S` and `S[Q']` is related to `T`. @@ -21970,8 +28288,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // Fastpath: When the template type has the form `Obj[P]` where `P` is the mapped type parameter, directly compare source `S` with `Obj` // to avoid creating the (potentially very large) number of new intermediate types made by manufacturing `S[P]`. const nonNullComponent = extractTypesOfKind(templateType, ~TypeFlags.Nullable); - if (!keysRemapped && nonNullComponent.flags & TypeFlags.IndexedAccess && (nonNullComponent as IndexedAccessType).indexType === typeParameter) { - if (result = isRelatedTo(source, (nonNullComponent as IndexedAccessType).objectType, RecursionFlags.Target, reportErrors)) { + if ( + !keysRemapped && nonNullComponent.flags & TypeFlags.IndexedAccess + && (nonNullComponent as IndexedAccessType).indexType === typeParameter + ) { + if ( + result = isRelatedTo( + source, + (nonNullComponent as IndexedAccessType).objectType, + RecursionFlags.Target, + reportErrors, + ) + ) { return result; } } @@ -21992,7 +28320,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { : typeParameter; const indexedAccessType = getIndexedAccessType(source, indexingType); // Compare `S[indexingType]` to `T`, where `T` is the type of a property of the target type. - if (result = isRelatedTo(indexedAccessType, templateType, RecursionFlags.Both, reportErrors)) { + if ( + result = isRelatedTo( + indexedAccessType, + templateType, + RecursionFlags.Both, + reportErrors, + ) + ) { return result; } } @@ -22013,13 +28348,41 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // 'infer' positions, is not distributive or is distributive but doesn't reference the check type // parameter in either of the result types, and the source isn't an instantiation of the same // conditional type (as happens when computing variance). - if (!c.root.inferTypeParameters && !isDistributionDependent(c.root) && !(source.flags & TypeFlags.Conditional && (source as ConditionalType).root === c.root)) { + if ( + !c.root.inferTypeParameters && !isDistributionDependent(c.root) + && !(source.flags & TypeFlags.Conditional && (source as ConditionalType).root === c.root) + ) { // Check if the conditional is always true or always false but still deferred for distribution purposes. - const skipTrue = !isTypeAssignableTo(getPermissiveInstantiation(c.checkType), getPermissiveInstantiation(c.extendsType)); - const skipFalse = !skipTrue && isTypeAssignableTo(getRestrictiveInstantiation(c.checkType), getRestrictiveInstantiation(c.extendsType)); + const skipTrue = !isTypeAssignableTo( + getPermissiveInstantiation(c.checkType), + getPermissiveInstantiation(c.extendsType), + ); + const skipFalse = !skipTrue + && isTypeAssignableTo( + getRestrictiveInstantiation(c.checkType), + getRestrictiveInstantiation(c.extendsType), + ); // TODO: Find a nice way to include potential conditional type breakdowns in error output, if they seem good (they usually don't) - if (result = skipTrue ? Ternary.True : isRelatedTo(source, getTrueTypeFromConditionalType(c), RecursionFlags.Target, /*reportErrors*/ false, /*headMessage*/ undefined, intersectionState)) { - result &= skipFalse ? Ternary.True : isRelatedTo(source, getFalseTypeFromConditionalType(c), RecursionFlags.Target, /*reportErrors*/ false, /*headMessage*/ undefined, intersectionState); + if ( + result = skipTrue ? Ternary.True + : isRelatedTo( + source, + getTrueTypeFromConditionalType(c), + RecursionFlags.Target, + /*reportErrors*/ false, + /*headMessage*/ undefined, + intersectionState, + ) + ) { + result &= skipFalse ? Ternary.True + : isRelatedTo( + source, + getFalseTypeFromConditionalType(c), + RecursionFlags.Target, + /*reportErrors*/ false, + /*headMessage*/ undefined, + intersectionState, + ); if (result) { return result; } @@ -22029,7 +28392,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { else if (targetFlags & TypeFlags.TemplateLiteral) { if (sourceFlags & TypeFlags.TemplateLiteral) { if (relation === comparableRelation) { - return templateLiteralTypesDefinitelyUnrelated(source as TemplateLiteralType, target as TemplateLiteralType) ? Ternary.False : Ternary.True; + return templateLiteralTypesDefinitelyUnrelated( + source as TemplateLiteralType, + target as TemplateLiteralType, + ) ? Ternary.False : Ternary.True; } // Report unreliable variance for type variables referenced in template literal type placeholders. // For example, `foo-${number}` is related to `foo-${string}` even though number isn't related to string. @@ -22052,11 +28418,30 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (!(sourceFlags & TypeFlags.IndexedAccess && targetFlags & TypeFlags.IndexedAccess)) { const constraint = getConstraintOfType(source as TypeVariable) || unknownType; // hi-speed no-this-instantiation check (less accurate, but avoids costly `this`-instantiation when the constraint will suffice), see #28231 for report on why this is needed - if (result = isRelatedTo(constraint, target, RecursionFlags.Source, /*reportErrors*/ false, /*headMessage*/ undefined, intersectionState)) { + if ( + result = isRelatedTo( + constraint, + target, + RecursionFlags.Source, + /*reportErrors*/ false, + /*headMessage*/ undefined, + intersectionState, + ) + ) { return result; } // slower, fuller, this-instantiated check (necessary when comparing raw `this` types from base classes), see `subclassWithPolymorphicThisIsAssignable.ts` test for example - else if (result = isRelatedTo(getTypeWithThisArgument(constraint, source), target, RecursionFlags.Source, reportErrors && constraint !== unknownType && !(targetFlags & sourceFlags & TypeFlags.TypeParameter), /*headMessage*/ undefined, intersectionState)) { + else if ( + result = isRelatedTo( + getTypeWithThisArgument(constraint, source), + target, + RecursionFlags.Source, + reportErrors && constraint !== unknownType + && !(targetFlags & sourceFlags & TypeFlags.TypeParameter), + /*headMessage*/ undefined, + intersectionState, + ) + ) { return result; } if (isMappedTypeGenericIndexedAccess(source)) { @@ -22064,7 +28449,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // substituted for P. We also want to explore type { [P in K]: E }[C], where C is the constraint of X. const indexConstraint = getConstraintOfType((source as IndexedAccessType).indexType); if (indexConstraint) { - if (result = isRelatedTo(getIndexedAccessType((source as IndexedAccessType).objectType, indexConstraint), target, RecursionFlags.Source, reportErrors)) { + if ( + result = isRelatedTo( + getIndexedAccessType((source as IndexedAccessType).objectType, indexConstraint), + target, + RecursionFlags.Source, + reportErrors, + ) + ) { return result; } } @@ -22079,7 +28471,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { else if (sourceFlags & TypeFlags.TemplateLiteral && !(targetFlags & TypeFlags.Object)) { if (!(targetFlags & TypeFlags.TemplateLiteral)) { const constraint = getBaseConstraintOfType(source); - if (constraint && constraint !== source && (result = isRelatedTo(constraint, target, RecursionFlags.Source, reportErrors))) { + if ( + constraint && constraint !== source + && (result = isRelatedTo(constraint, target, RecursionFlags.Source, reportErrors)) + ) { return result; } } @@ -22089,7 +28484,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if ((source as StringMappingType).symbol !== (target as StringMappingType).symbol) { return Ternary.False; } - if (result = isRelatedTo((source as StringMappingType).type, (target as StringMappingType).type, RecursionFlags.Both, reportErrors)) { + if ( + result = isRelatedTo( + (source as StringMappingType).type, + (target as StringMappingType).type, + RecursionFlags.Both, + reportErrors, + ) + ) { return result; } } @@ -22115,17 +28517,48 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { let mapper: TypeMapper | undefined; if (sourceParams) { // If the source has infer type parameters, we instantiate them in the context of the target - const ctx = createInferenceContext(sourceParams, /*signature*/ undefined, InferenceFlags.None, isRelatedToWorker); - inferTypes(ctx.inferences, (target as ConditionalType).extendsType, sourceExtends, InferencePriority.NoConstraints | InferencePriority.AlwaysStrict); + const ctx = createInferenceContext( + sourceParams, + /*signature*/ undefined, + InferenceFlags.None, + isRelatedToWorker, + ); + inferTypes( + ctx.inferences, + (target as ConditionalType).extendsType, + sourceExtends, + InferencePriority.NoConstraints | InferencePriority.AlwaysStrict, + ); sourceExtends = instantiateType(sourceExtends, ctx.mapper); mapper = ctx.mapper; } if ( - isTypeIdenticalTo(sourceExtends, (target as ConditionalType).extendsType) && - (isRelatedTo((source as ConditionalType).checkType, (target as ConditionalType).checkType, RecursionFlags.Both) || isRelatedTo((target as ConditionalType).checkType, (source as ConditionalType).checkType, RecursionFlags.Both)) + isTypeIdenticalTo(sourceExtends, (target as ConditionalType).extendsType) + && (isRelatedTo( + (source as ConditionalType).checkType, + (target as ConditionalType).checkType, + RecursionFlags.Both, + ) + || isRelatedTo( + (target as ConditionalType).checkType, + (source as ConditionalType).checkType, + RecursionFlags.Both, + )) ) { - if (result = isRelatedTo(instantiateType(getTrueTypeFromConditionalType(source as ConditionalType), mapper), getTrueTypeFromConditionalType(target as ConditionalType), RecursionFlags.Both, reportErrors)) { - result &= isRelatedTo(getFalseTypeFromConditionalType(source as ConditionalType), getFalseTypeFromConditionalType(target as ConditionalType), RecursionFlags.Both, reportErrors); + if ( + result = isRelatedTo( + instantiateType(getTrueTypeFromConditionalType(source as ConditionalType), mapper), + getTrueTypeFromConditionalType(target as ConditionalType), + RecursionFlags.Both, + reportErrors, + ) + ) { + result &= isRelatedTo( + getFalseTypeFromConditionalType(source as ConditionalType), + getFalseTypeFromConditionalType(target as ConditionalType), + RecursionFlags.Both, + reportErrors, + ); } if (result) { return result; @@ -22135,7 +28568,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { else { // conditionals aren't related to one another via distributive constraint as it is much too inaccurate and allows way // more assignments than are desirable (since it maps the source check type to its constraint, it loses information) - const distributiveConstraint = hasNonCircularBaseConstraint(source) ? getConstraintOfDistributiveConditionalType(source as ConditionalType) : undefined; + const distributiveConstraint = hasNonCircularBaseConstraint(source) + ? getConstraintOfDistributiveConditionalType(source as ConditionalType) : undefined; if (distributiveConstraint) { if (result = isRelatedTo(distributiveConstraint, target, RecursionFlags.Source, reportErrors)) { return result; @@ -22154,7 +28588,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } else { // An empty object type is related to any mapped type that includes a '?' modifier. - if (relation !== subtypeRelation && relation !== strictSubtypeRelation && isPartialMappedType(target) && isEmptyObjectType(source)) { + if ( + relation !== subtypeRelation && relation !== strictSubtypeRelation && isPartialMappedType(target) + && isEmptyObjectType(source) + ) { return Ternary.True; } if (isGenericMappedType(target)) { @@ -22174,8 +28611,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return Ternary.False; } if ( - getObjectFlags(source) & ObjectFlags.Reference && getObjectFlags(target) & ObjectFlags.Reference && (source as TypeReference).target === (target as TypeReference).target && - !isTupleType(source) && !(isMarkerType(source) || isMarkerType(target)) + getObjectFlags(source) & ObjectFlags.Reference && getObjectFlags(target) & ObjectFlags.Reference + && (source as TypeReference).target === (target as TypeReference).target + && !isTupleType(source) && !(isMarkerType(source) || isMarkerType(target)) ) { // When strictNullChecks is disabled, the element type of the empty array literal is undefinedWideningType, // and an empty array literal wouldn't be assignable to a `never[]` without this check. @@ -22192,14 +28630,27 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (variances === emptyArray) { return Ternary.Unknown; } - const varianceResult = relateVariances(getTypeArguments(source as TypeReference), getTypeArguments(target as TypeReference), variances, intersectionState); + const varianceResult = relateVariances( + getTypeArguments(source as TypeReference), + getTypeArguments(target as TypeReference), + variances, + intersectionState, + ); if (varianceResult !== undefined) { return varianceResult; } } - else if (isReadonlyArrayType(target) ? everyType(source, isArrayOrTupleType) : isArrayType(target) && everyType(source, t => isTupleType(t) && !t.target.readonly)) { + else if ( + isReadonlyArrayType(target) ? everyType(source, isArrayOrTupleType) + : isArrayType(target) && everyType(source, t => isTupleType(t) && !t.target.readonly) + ) { if (relation !== identityRelation) { - return isRelatedTo(getIndexTypeOfType(source, numberType) || anyType, getIndexTypeOfType(target, numberType) || anyType, RecursionFlags.Both, reportErrors); + return isRelatedTo( + getIndexTypeOfType(source, numberType) || anyType, + getIndexTypeOfType(target, numberType) || anyType, + RecursionFlags.Both, + reportErrors, + ); } else { // By flags alone, we know that the `target` is a readonly array while the source is a normal array or tuple @@ -22215,7 +28666,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } // A fresh empty object type is never a subtype of a non-empty object type. This ensures fresh({}) <: { [x: string]: xxx } // but not vice-versa. Without this rule, those types would be mutual subtypes. - else if ((relation === subtypeRelation || relation === strictSubtypeRelation) && isEmptyObjectType(target) && getObjectFlags(target) & ObjectFlags.FreshLiteral && !isEmptyObjectType(source)) { + else if ( + (relation === subtypeRelation || relation === strictSubtypeRelation) && isEmptyObjectType(target) + && getObjectFlags(target) & ObjectFlags.FreshLiteral && !isEmptyObjectType(source) + ) { return Ternary.False; } // Even if relationship doesn't hold for unions, intersections, or generic type references, @@ -22225,14 +28679,40 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // relates to X. Thus, we include intersection types on the source side here. if (sourceFlags & (TypeFlags.Object | TypeFlags.Intersection) && targetFlags & TypeFlags.Object) { // Report structural errors only if we haven't reported any errors yet - const reportStructuralErrors = reportErrors && errorInfo === saveErrorInfo.errorInfo && !sourceIsPrimitive; - result = propertiesRelatedTo(source, target, reportStructuralErrors, /*excludedProperties*/ undefined, /*optionalsOnly*/ false, intersectionState); + const reportStructuralErrors = reportErrors && errorInfo === saveErrorInfo.errorInfo + && !sourceIsPrimitive; + result = propertiesRelatedTo( + source, + target, + reportStructuralErrors, + /*excludedProperties*/ undefined, + /*optionalsOnly*/ false, + intersectionState, + ); if (result) { - result &= signaturesRelatedTo(source, target, SignatureKind.Call, reportStructuralErrors, intersectionState); + result &= signaturesRelatedTo( + source, + target, + SignatureKind.Call, + reportStructuralErrors, + intersectionState, + ); if (result) { - result &= signaturesRelatedTo(source, target, SignatureKind.Construct, reportStructuralErrors, intersectionState); + result &= signaturesRelatedTo( + source, + target, + SignatureKind.Construct, + reportStructuralErrors, + intersectionState, + ); if (result) { - result &= indexSignaturesRelatedTo(source, target, sourceIsPrimitive, reportStructuralErrors, intersectionState); + result &= indexSignaturesRelatedTo( + source, + target, + sourceIsPrimitive, + reportStructuralErrors, + intersectionState, + ); } } } @@ -22248,7 +28728,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // with respect to T. We do not report errors here, as we will use the existing // error result from checking each constituent of the union. if (sourceFlags & (TypeFlags.Object | TypeFlags.Intersection) && targetFlags & TypeFlags.Union) { - const objectOnlyTarget = extractTypesOfKind(target, TypeFlags.Object | TypeFlags.Intersection | TypeFlags.Substitution); + const objectOnlyTarget = extractTypesOfKind( + target, + TypeFlags.Object | TypeFlags.Intersection | TypeFlags.Substitution, + ); if (objectOnlyTarget.flags & TypeFlags.Union) { const result = typeRelatedToDiscriminatedType(source, objectOnlyTarget as UnionType); if (result) { @@ -22264,8 +28747,21 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return reduceLeft(info, (value, chain) => value + 1 + countMessageChainBreadth(chain.next), 0); } - function relateVariances(sourceTypeArguments: readonly Type[] | undefined, targetTypeArguments: readonly Type[] | undefined, variances: VarianceFlags[], intersectionState: IntersectionState) { - if (result = typeArgumentsRelatedTo(sourceTypeArguments, targetTypeArguments, variances, reportErrors, intersectionState)) { + function relateVariances( + sourceTypeArguments: readonly Type[] | undefined, + targetTypeArguments: readonly Type[] | undefined, + variances: VarianceFlags[], + intersectionState: IntersectionState, + ) { + if ( + result = typeArgumentsRelatedTo( + sourceTypeArguments, + targetTypeArguments, + variances, + reportErrors, + intersectionState, + ) + ) { return result; } if (some(variances, v => !!(v & VarianceFlags.AllowsStructuralFallback))) { @@ -22277,7 +28773,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { resetErrorInfo(saveErrorInfo); return undefined; } - const allowStructuralFallback = targetTypeArguments && hasCovariantVoidArgument(targetTypeArguments, variances); + const allowStructuralFallback = targetTypeArguments + && hasCovariantVoidArgument(targetTypeArguments, variances); varianceCheckFailed = !allowStructuralFallback; // The type arguments did not relate appropriately, but it may be because we have no variance // information (in which case typeArgumentsRelatedTo defaulted to covariance for all type @@ -22295,7 +28792,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // reveal the reason). // We can switch on `reportErrors` here, since varianceCheckFailed guarantees we return `False`, // we can return `False` early here to skip calculating the structural error message we don't need. - if (varianceCheckFailed && !(reportErrors && some(variances, v => (v & VarianceFlags.VarianceMask) === VarianceFlags.Invariant))) { + if ( + varianceCheckFailed + && !(reportErrors + && some(variances, v => (v & VarianceFlags.VarianceMask) === VarianceFlags.Invariant)) + ) { return Ternary.False; } // We remember the original error information so we can restore it in case the structural @@ -22311,16 +28812,31 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // related to Y, where X' is an instantiation of X in which P is replaced with Q. Notice // that S and T are contra-variant whereas X and Y are co-variant. function mappedTypeRelatedTo(source: MappedType, target: MappedType, reportErrors: boolean): Ternary { - const modifiersRelated = relation === comparableRelation || (relation === identityRelation ? getMappedTypeModifiers(source) === getMappedTypeModifiers(target) : - getCombinedMappedTypeOptionality(source) <= getCombinedMappedTypeOptionality(target)); + const modifiersRelated = relation === comparableRelation + || (relation === identityRelation ? getMappedTypeModifiers(source) === getMappedTypeModifiers(target) + : getCombinedMappedTypeOptionality(source) <= getCombinedMappedTypeOptionality(target)); if (modifiersRelated) { let result: Ternary; const targetConstraint = getConstraintTypeFromMappedType(target); - const sourceConstraint = instantiateType(getConstraintTypeFromMappedType(source), getCombinedMappedTypeOptionality(source) < 0 ? reportUnmeasurableMapper : reportUnreliableMapper); + const sourceConstraint = instantiateType( + getConstraintTypeFromMappedType(source), + getCombinedMappedTypeOptionality(source) < 0 ? reportUnmeasurableMapper : reportUnreliableMapper, + ); if (result = isRelatedTo(targetConstraint, sourceConstraint, RecursionFlags.Both, reportErrors)) { - const mapper = createTypeMapper([getTypeParameterFromMappedType(source)], [getTypeParameterFromMappedType(target)]); - if (instantiateType(getNameTypeFromMappedType(source), mapper) === instantiateType(getNameTypeFromMappedType(target), mapper)) { - return result & isRelatedTo(instantiateType(getTemplateTypeFromMappedType(source), mapper), getTemplateTypeFromMappedType(target), RecursionFlags.Both, reportErrors); + const mapper = createTypeMapper([getTypeParameterFromMappedType(source)], [ + getTypeParameterFromMappedType(target), + ]); + if ( + instantiateType(getNameTypeFromMappedType(source), mapper) + === instantiateType(getNameTypeFromMappedType(target), mapper) + ) { + return result + & isRelatedTo( + instantiateType(getTemplateTypeFromMappedType(source), mapper), + getTemplateTypeFromMappedType(target), + RecursionFlags.Both, + reportErrors, + ); } } } @@ -22352,7 +28868,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { numCombinations *= countTypes(getNonMissingTypeOfSymbol(sourceProperty)); if (numCombinations > 25) { // We've reached the complexity limit. - tracing?.instant(tracing.Phase.CheckTypes, "typeRelatedToDiscriminatedType_DepthLimit", { sourceId: source.id, targetId: target.id, numCombinations }); + tracing?.instant(tracing.Phase.CheckTypes, "typeRelatedToDiscriminatedType_DepthLimit", { + sourceId: source.id, + targetId: target.id, + numCombinations, + }); return Ternary.False; } } @@ -22383,7 +28903,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (!targetProperty) continue outer; if (sourceProperty === targetProperty) continue; // We compare the source property to the target in the context of a single discriminant type. - const related = propertyRelatedTo(source, target, sourceProperty, targetProperty, _ => combination[i], /*reportErrors*/ false, IntersectionState.None, /*skipOptional*/ strictNullChecks || relation === comparableRelation); + const related = propertyRelatedTo( + source, + target, + sourceProperty, + targetProperty, + _ => combination[i], + /*reportErrors*/ false, + IntersectionState.None, + /*skipOptional*/ strictNullChecks || relation === comparableRelation, + ); // If the target property could not be found, or if the properties were not related, // then this constituent is not a match. if (!related) { @@ -22402,17 +28931,42 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // Compare the remaining non-discriminant properties of each match. let result = Ternary.True; for (const type of matchingTypes) { - result &= propertiesRelatedTo(source, type, /*reportErrors*/ false, excludedProperties, /*optionalsOnly*/ false, IntersectionState.None); + result &= propertiesRelatedTo( + source, + type, + /*reportErrors*/ false, + excludedProperties, + /*optionalsOnly*/ false, + IntersectionState.None, + ); if (result) { - result &= signaturesRelatedTo(source, type, SignatureKind.Call, /*reportErrors*/ false, IntersectionState.None); + result &= signaturesRelatedTo( + source, + type, + SignatureKind.Call, + /*reportErrors*/ false, + IntersectionState.None, + ); if (result) { - result &= signaturesRelatedTo(source, type, SignatureKind.Construct, /*reportErrors*/ false, IntersectionState.None); + result &= signaturesRelatedTo( + source, + type, + SignatureKind.Construct, + /*reportErrors*/ false, + IntersectionState.None, + ); if (result && !(isTupleType(source) && isTupleType(type))) { // Comparing numeric index types when both `source` and `type` are tuples is unnecessary as the // element types should be sufficiently covered by `propertiesRelatedTo`. It also causes problems // with index type assignability as the types for the excluded discriminants are still included // in the index type. - result &= indexSignaturesRelatedTo(source, type, /*sourceIsPrimitive*/ false, /*reportErrors*/ false, IntersectionState.None); + result &= indexSignaturesRelatedTo( + source, + type, + /*sourceIsPrimitive*/ false, + /*reportErrors*/ false, + IntersectionState.None, + ); } } } @@ -22439,24 +28993,58 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return result || properties; } - function isPropertySymbolTypeRelated(sourceProp: Symbol, targetProp: Symbol, getTypeOfSourceProperty: (sym: Symbol) => Type, reportErrors: boolean, intersectionState: IntersectionState): Ternary { + function isPropertySymbolTypeRelated( + sourceProp: Symbol, + targetProp: Symbol, + getTypeOfSourceProperty: (sym: Symbol) => Type, + reportErrors: boolean, + intersectionState: IntersectionState, + ): Ternary { const targetIsOptional = strictNullChecks && !!(getCheckFlags(targetProp) & CheckFlags.Partial); - const effectiveTarget = addOptionality(getNonMissingTypeOfSymbol(targetProp), /*isProperty*/ false, targetIsOptional); + const effectiveTarget = addOptionality( + getNonMissingTypeOfSymbol(targetProp), + /*isProperty*/ false, + targetIsOptional, + ); const effectiveSource = getTypeOfSourceProperty(sourceProp); - return isRelatedTo(effectiveSource, effectiveTarget, RecursionFlags.Both, reportErrors, /*headMessage*/ undefined, intersectionState); + return isRelatedTo( + effectiveSource, + effectiveTarget, + RecursionFlags.Both, + reportErrors, + /*headMessage*/ undefined, + intersectionState, + ); } - function propertyRelatedTo(source: Type, target: Type, sourceProp: Symbol, targetProp: Symbol, getTypeOfSourceProperty: (sym: Symbol) => Type, reportErrors: boolean, intersectionState: IntersectionState, skipOptional: boolean): Ternary { + function propertyRelatedTo( + source: Type, + target: Type, + sourceProp: Symbol, + targetProp: Symbol, + getTypeOfSourceProperty: (sym: Symbol) => Type, + reportErrors: boolean, + intersectionState: IntersectionState, + skipOptional: boolean, + ): Ternary { const sourcePropFlags = getDeclarationModifierFlagsFromSymbol(sourceProp); const targetPropFlags = getDeclarationModifierFlagsFromSymbol(targetProp); if (sourcePropFlags & ModifierFlags.Private || targetPropFlags & ModifierFlags.Private) { if (sourceProp.valueDeclaration !== targetProp.valueDeclaration) { if (reportErrors) { if (sourcePropFlags & ModifierFlags.Private && targetPropFlags & ModifierFlags.Private) { - reportError(Diagnostics.Types_have_separate_declarations_of_a_private_property_0, symbolToString(targetProp)); + reportError( + Diagnostics.Types_have_separate_declarations_of_a_private_property_0, + symbolToString(targetProp), + ); } else { - reportError(Diagnostics.Property_0_is_private_in_type_1_but_not_in_type_2, symbolToString(targetProp), typeToString(sourcePropFlags & ModifierFlags.Private ? source : target), typeToString(sourcePropFlags & ModifierFlags.Private ? target : source)); + reportError( + Diagnostics.Property_0_is_private_in_type_1_but_not_in_type_2, + symbolToString(targetProp), + typeToString(sourcePropFlags & ModifierFlags.Private ? source : target), + typeToString(sourcePropFlags & ModifierFlags.Private ? target : source), + ); } } return Ternary.False; @@ -22465,14 +29053,24 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { else if (targetPropFlags & ModifierFlags.Protected) { if (!isValidOverrideOf(sourceProp, targetProp)) { if (reportErrors) { - reportError(Diagnostics.Property_0_is_protected_but_type_1_is_not_a_class_derived_from_2, symbolToString(targetProp), typeToString(getDeclaringClass(sourceProp) || source), typeToString(getDeclaringClass(targetProp) || target)); + reportError( + Diagnostics.Property_0_is_protected_but_type_1_is_not_a_class_derived_from_2, + symbolToString(targetProp), + typeToString(getDeclaringClass(sourceProp) || source), + typeToString(getDeclaringClass(targetProp) || target), + ); } return Ternary.False; } } else if (sourcePropFlags & ModifierFlags.Protected) { if (reportErrors) { - reportError(Diagnostics.Property_0_is_protected_in_type_1_but_public_in_type_2, symbolToString(targetProp), typeToString(source), typeToString(target)); + reportError( + Diagnostics.Property_0_is_protected_in_type_1_but_public_in_type_2, + symbolToString(targetProp), + typeToString(source), + typeToString(target), + ); } return Ternary.False; } @@ -22484,21 +29082,33 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // They're still assignable to one another, since `readonly` doesn't affect assignability. // This is only applied during the strictSubtypeRelation -- currently used in subtype reduction if ( - relation === strictSubtypeRelation && - isReadonlySymbol(sourceProp) && !isReadonlySymbol(targetProp) + relation === strictSubtypeRelation + && isReadonlySymbol(sourceProp) && !isReadonlySymbol(targetProp) ) { return Ternary.False; } // If the target comes from a partial union prop, allow `undefined` in the target type - const related = isPropertySymbolTypeRelated(sourceProp, targetProp, getTypeOfSourceProperty, reportErrors, intersectionState); + const related = isPropertySymbolTypeRelated( + sourceProp, + targetProp, + getTypeOfSourceProperty, + reportErrors, + intersectionState, + ); if (!related) { if (reportErrors) { - reportIncompatibleError(Diagnostics.Types_of_property_0_are_incompatible, symbolToString(targetProp)); + reportIncompatibleError( + Diagnostics.Types_of_property_0_are_incompatible, + symbolToString(targetProp), + ); } return Ternary.False; } // When checking for comparability, be more lenient with optional properties. - if (!skipOptional && sourceProp.flags & SymbolFlags.Optional && targetProp.flags & SymbolFlags.ClassMember && !(targetProp.flags & SymbolFlags.Optional)) { + if ( + !skipOptional && sourceProp.flags & SymbolFlags.Optional && targetProp.flags & SymbolFlags.ClassMember + && !(targetProp.flags & SymbolFlags.Optional) + ) { // TypeScript 1.0 spec (April 2014): 3.8.3 // S is a subtype of a type T, and T is a supertype of S if ... // S' and T are object types and, for each member M in T.. @@ -22507,14 +29117,24 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // (M - property in T) // (N - property in S) if (reportErrors) { - reportError(Diagnostics.Property_0_is_optional_in_type_1_but_required_in_type_2, symbolToString(targetProp), typeToString(source), typeToString(target)); + reportError( + Diagnostics.Property_0_is_optional_in_type_1_but_required_in_type_2, + symbolToString(targetProp), + typeToString(source), + typeToString(target), + ); } return Ternary.False; } return related; } - function reportUnmatchedProperty(source: Type, target: Type, unmatchedProperty: Symbol, requireOptionalProperties: boolean) { + function reportUnmatchedProperty( + source: Type, + target: Type, + unmatchedProperty: Symbol, + requireOptionalProperties: boolean, + ) { let shouldSkipElaboration = false; // give specific error in case where private names have the same description if ( @@ -22530,7 +29150,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const sourceName = factory.getDeclarationName(source.symbol.valueDeclaration); const targetName = factory.getDeclarationName(target.symbol.valueDeclaration); reportError( - Diagnostics.Property_0_in_type_1_refers_to_a_different_member_that_cannot_be_accessed_from_within_type_2, + Diagnostics + .Property_0_in_type_1_refers_to_a_different_member_that_cannot_be_accessed_from_within_type_2, diagnosticName(privateIdentifierDescription), diagnosticName(sourceName.escapedText === "" ? anon : sourceName), diagnosticName(targetName.escapedText === "" ? anon : targetName), @@ -22538,18 +29159,43 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return; } } - const props = arrayFrom(getUnmatchedProperties(source, target, requireOptionalProperties, /*matchDiscriminantProperties*/ false)); + const props = arrayFrom( + getUnmatchedProperties( + source, + target, + requireOptionalProperties, + /*matchDiscriminantProperties*/ false, + ), + ); if ( - !headMessage || (headMessage.code !== Diagnostics.Class_0_incorrectly_implements_interface_1.code && - headMessage.code !== Diagnostics.Class_0_incorrectly_implements_class_1_Did_you_mean_to_extend_1_and_inherit_its_members_as_a_subclass.code) + !headMessage || (headMessage.code !== Diagnostics.Class_0_incorrectly_implements_interface_1.code + && headMessage.code + !== Diagnostics + .Class_0_incorrectly_implements_class_1_Did_you_mean_to_extend_1_and_inherit_its_members_as_a_subclass + .code) ) { shouldSkipElaboration = true; // Retain top-level error for interface implementing issues, otherwise omit it } if (props.length === 1) { - const propName = symbolToString(unmatchedProperty, /*enclosingDeclaration*/ undefined, SymbolFlags.None, SymbolFormatFlags.AllowAnyNodeKind | SymbolFormatFlags.WriteComputedProps); - reportError(Diagnostics.Property_0_is_missing_in_type_1_but_required_in_type_2, propName, ...getTypeNamesForErrorDisplay(source, target)); + const propName = symbolToString( + unmatchedProperty, + /*enclosingDeclaration*/ undefined, + SymbolFlags.None, + SymbolFormatFlags.AllowAnyNodeKind | SymbolFormatFlags.WriteComputedProps, + ); + reportError( + Diagnostics.Property_0_is_missing_in_type_1_but_required_in_type_2, + propName, + ...getTypeNamesForErrorDisplay(source, target), + ); if (length(unmatchedProperty.declarations)) { - associateRelatedInfo(createDiagnosticForNode(unmatchedProperty.declarations![0], Diagnostics._0_is_declared_here, propName)); + associateRelatedInfo( + createDiagnosticForNode( + unmatchedProperty.declarations![0], + Diagnostics._0_is_declared_here, + propName, + ), + ); } if (shouldSkipElaboration && errorInfo) { overrideNextErrorInfo++; @@ -22557,10 +29203,21 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } else if (tryElaborateArrayLikeErrors(source, target, /*reportErrors*/ false)) { if (props.length > 5) { // arbitrary cutoff for too-long list form - reportError(Diagnostics.Type_0_is_missing_the_following_properties_from_type_1_Colon_2_and_3_more, typeToString(source), typeToString(target), map(props.slice(0, 4), p => symbolToString(p)).join(", "), props.length - 4); + reportError( + Diagnostics.Type_0_is_missing_the_following_properties_from_type_1_Colon_2_and_3_more, + typeToString(source), + typeToString(target), + map(props.slice(0, 4), p => symbolToString(p)).join(", "), + props.length - 4, + ); } else { - reportError(Diagnostics.Type_0_is_missing_the_following_properties_from_type_1_Colon_2, typeToString(source), typeToString(target), map(props, p => symbolToString(p)).join(", ")); + reportError( + Diagnostics.Type_0_is_missing_the_following_properties_from_type_1_Colon_2, + typeToString(source), + typeToString(target), + map(props, p => symbolToString(p)).join(", "), + ); } if (shouldSkipElaboration && errorInfo) { overrideNextErrorInfo++; @@ -22569,41 +29226,66 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // No array like or unmatched property error - just issue top level error (errorInfo = undefined) } - function propertiesRelatedTo(source: Type, target: Type, reportErrors: boolean, excludedProperties: Set<__String> | undefined, optionalsOnly: boolean, intersectionState: IntersectionState): Ternary { + function propertiesRelatedTo( + source: Type, + target: Type, + reportErrors: boolean, + excludedProperties: Set<__String> | undefined, + optionalsOnly: boolean, + intersectionState: IntersectionState, + ): Ternary { if (relation === identityRelation) { return propertiesIdenticalTo(source, target, excludedProperties); } let result = Ternary.True; if (isTupleType(target)) { if (isArrayOrTupleType(source)) { - if (!target.target.readonly && (isReadonlyArrayType(source) || isTupleType(source) && source.target.readonly)) { + if ( + !target.target.readonly + && (isReadonlyArrayType(source) || isTupleType(source) && source.target.readonly) + ) { return Ternary.False; } const sourceArity = getTypeReferenceArity(source); const targetArity = getTypeReferenceArity(target); - const sourceRestFlag = isTupleType(source) ? source.target.combinedFlags & ElementFlags.Rest : ElementFlags.Rest; + const sourceRestFlag = isTupleType(source) ? source.target.combinedFlags & ElementFlags.Rest + : ElementFlags.Rest; const targetRestFlag = target.target.combinedFlags & ElementFlags.Rest; const sourceMinLength = isTupleType(source) ? source.target.minLength : 0; const targetMinLength = target.target.minLength; if (!sourceRestFlag && sourceArity < targetMinLength) { if (reportErrors) { - reportError(Diagnostics.Source_has_0_element_s_but_target_requires_1, sourceArity, targetMinLength); + reportError( + Diagnostics.Source_has_0_element_s_but_target_requires_1, + sourceArity, + targetMinLength, + ); } return Ternary.False; } if (!targetRestFlag && targetArity < sourceMinLength) { if (reportErrors) { - reportError(Diagnostics.Source_has_0_element_s_but_target_allows_only_1, sourceMinLength, targetArity); + reportError( + Diagnostics.Source_has_0_element_s_but_target_allows_only_1, + sourceMinLength, + targetArity, + ); } return Ternary.False; } if (!targetRestFlag && (sourceRestFlag || targetArity < sourceArity)) { if (reportErrors) { if (sourceMinLength < targetMinLength) { - reportError(Diagnostics.Target_requires_0_element_s_but_source_may_have_fewer, targetMinLength); + reportError( + Diagnostics.Target_requires_0_element_s_but_source_may_have_fewer, + targetMinLength, + ); } else { - reportError(Diagnostics.Target_allows_only_0_element_s_but_source_may_have_more, targetArity); + reportError( + Diagnostics.Target_allows_only_0_element_s_but_source_may_have_more, + targetArity, + ); } } return Ternary.False; @@ -22615,7 +29297,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const targetHasRestElement = target.target.hasRestElement; let canExcludeDiscriminants = !!excludedProperties; for (let sourcePosition = 0; sourcePosition < sourceArity; sourcePosition++) { - const sourceFlags = isTupleType(source) ? source.target.elementFlags[sourcePosition] : ElementFlags.Rest; + const sourceFlags = isTupleType(source) ? source.target.elementFlags[sourcePosition] + : ElementFlags.Rest; const sourcePositionFromEnd = sourceArity - 1 - sourcePosition; const targetPosition = targetHasRestElement && sourcePosition >= targetStartCount @@ -22626,19 +29309,30 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (targetFlags & ElementFlags.Variadic && !(sourceFlags & ElementFlags.Variadic)) { if (reportErrors) { - reportError(Diagnostics.Source_provides_no_match_for_variadic_element_at_position_0_in_target, targetPosition); + reportError( + Diagnostics.Source_provides_no_match_for_variadic_element_at_position_0_in_target, + targetPosition, + ); } return Ternary.False; } if (sourceFlags & ElementFlags.Variadic && !(targetFlags & ElementFlags.Variable)) { if (reportErrors) { - reportError(Diagnostics.Variadic_element_at_position_0_in_source_does_not_match_element_at_position_1_in_target, sourcePosition, targetPosition); + reportError( + Diagnostics + .Variadic_element_at_position_0_in_source_does_not_match_element_at_position_1_in_target, + sourcePosition, + targetPosition, + ); } return Ternary.False; } if (targetFlags & ElementFlags.Required && !(sourceFlags & ElementFlags.Required)) { if (reportErrors) { - reportError(Diagnostics.Source_provides_no_match_for_required_element_at_position_0_in_target, targetPosition); + reportError( + Diagnostics.Source_provides_no_match_for_required_element_at_position_0_in_target, + targetPosition, + ); } return Ternary.False; } @@ -22652,19 +29346,45 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } - const sourceType = removeMissingType(sourceTypeArguments[sourcePosition], !!(sourceFlags & targetFlags & ElementFlags.Optional)); + const sourceType = removeMissingType( + sourceTypeArguments[sourcePosition], + !!(sourceFlags & targetFlags & ElementFlags.Optional), + ); const targetType = targetTypeArguments[targetPosition]; - const targetCheckType = sourceFlags & ElementFlags.Variadic && targetFlags & ElementFlags.Rest ? createArrayType(targetType) : - removeMissingType(targetType, !!(targetFlags & ElementFlags.Optional)); - const related = isRelatedTo(sourceType, targetCheckType, RecursionFlags.Both, reportErrors, /*headMessage*/ undefined, intersectionState); + const targetCheckType = sourceFlags & ElementFlags.Variadic && targetFlags & ElementFlags.Rest + ? createArrayType(targetType) + : removeMissingType(targetType, !!(targetFlags & ElementFlags.Optional)); + const related = isRelatedTo( + sourceType, + targetCheckType, + RecursionFlags.Both, + reportErrors, + /*headMessage*/ undefined, + intersectionState, + ); if (!related) { if (reportErrors && (targetArity > 1 || sourceArity > 1)) { - if (targetHasRestElement && sourcePosition >= targetStartCount && sourcePositionFromEnd >= targetEndCount && targetStartCount !== sourceArity - targetEndCount - 1) { - reportIncompatibleError(Diagnostics.Type_at_positions_0_through_1_in_source_is_not_compatible_with_type_at_position_2_in_target, targetStartCount, sourceArity - targetEndCount - 1, targetPosition); + if ( + targetHasRestElement && sourcePosition >= targetStartCount + && sourcePositionFromEnd >= targetEndCount + && targetStartCount !== sourceArity - targetEndCount - 1 + ) { + reportIncompatibleError( + Diagnostics + .Type_at_positions_0_through_1_in_source_is_not_compatible_with_type_at_position_2_in_target, + targetStartCount, + sourceArity - targetEndCount - 1, + targetPosition, + ); } else { - reportIncompatibleError(Diagnostics.Type_at_position_0_in_source_is_not_compatible_with_type_at_position_1_in_target, sourcePosition, targetPosition); + reportIncompatibleError( + Diagnostics + .Type_at_position_0_in_source_is_not_compatible_with_type_at_position_1_in_target, + sourcePosition, + targetPosition, + ); } } return Ternary.False; @@ -22677,8 +29397,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return Ternary.False; } } - const requireOptionalProperties = (relation === subtypeRelation || relation === strictSubtypeRelation) && !isObjectLiteralType(source) && !isEmptyArrayLiteralType(source) && !isTupleType(source); - const unmatchedProperty = getUnmatchedProperty(source, target, requireOptionalProperties, /*matchDiscriminantProperties*/ false); + const requireOptionalProperties = (relation === subtypeRelation || relation === strictSubtypeRelation) + && !isObjectLiteralType(source) && !isEmptyArrayLiteralType(source) && !isTupleType(source); + const unmatchedProperty = getUnmatchedProperty( + source, + target, + requireOptionalProperties, + /*matchDiscriminantProperties*/ false, + ); if (unmatchedProperty) { if (reportErrors && shouldReportUnmatchedPropertyError(source, target)) { reportUnmatchedProperty(source, target, unmatchedProperty, requireOptionalProperties); @@ -22691,7 +29417,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const sourceType = getTypeOfSymbol(sourceProp); if (!(sourceType.flags & TypeFlags.Undefined)) { if (reportErrors) { - reportError(Diagnostics.Property_0_does_not_exist_on_type_1, symbolToString(sourceProp), typeToString(target)); + reportError( + Diagnostics.Property_0_does_not_exist_on_type_1, + symbolToString(sourceProp), + typeToString(target), + ); } return Ternary.False; } @@ -22704,10 +29434,23 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const numericNamesOnly = isTupleType(source) && isTupleType(target); for (const targetProp of excludeProperties(properties, excludedProperties)) { const name = targetProp.escapedName; - if (!(targetProp.flags & SymbolFlags.Prototype) && (!numericNamesOnly || isNumericLiteralName(name) || name === "length") && (!optionalsOnly || targetProp.flags & SymbolFlags.Optional)) { + if ( + !(targetProp.flags & SymbolFlags.Prototype) + && (!numericNamesOnly || isNumericLiteralName(name) || name === "length") + && (!optionalsOnly || targetProp.flags & SymbolFlags.Optional) + ) { const sourceProp = getPropertyOfType(source, name); if (sourceProp && sourceProp !== targetProp) { - const related = propertyRelatedTo(source, target, sourceProp, targetProp, getNonMissingTypeOfSymbol, reportErrors, intersectionState, relation === comparableRelation); + const related = propertyRelatedTo( + source, + target, + sourceProp, + targetProp, + getNonMissingTypeOfSymbol, + reportErrors, + intersectionState, + relation === comparableRelation, + ); if (!related) { return Ternary.False; } @@ -22718,7 +29461,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return result; } - function propertiesIdenticalTo(source: Type, target: Type, excludedProperties: Set<__String> | undefined): Ternary { + function propertiesIdenticalTo( + source: Type, + target: Type, + excludedProperties: Set<__String> | undefined, + ): Ternary { if (!(source.flags & TypeFlags.Object && target.flags & TypeFlags.Object)) { return Ternary.False; } @@ -22742,7 +29489,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return result; } - function signaturesRelatedTo(source: Type, target: Type, kind: SignatureKind, reportErrors: boolean, intersectionState: IntersectionState): Ternary { + function signaturesRelatedTo( + source: Type, + target: Type, + kind: SignatureKind, + reportErrors: boolean, + intersectionState: IntersectionState, + ): Ternary { if (relation === identityRelation) { return signaturesIdenticalTo(source, target, kind); } @@ -22755,13 +29508,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const sourceSignatures = getSignaturesOfType( source, - (sourceIsJSConstructor && kind === SignatureKind.Construct) ? - SignatureKind.Call : kind, + (sourceIsJSConstructor && kind === SignatureKind.Construct) + ? SignatureKind.Call : kind, ); const targetSignatures = getSignaturesOfType( target, - (targetIsJSConstructor && kind === SignatureKind.Construct) ? - SignatureKind.Call : kind, + (targetIsJSConstructor && kind === SignatureKind.Construct) + ? SignatureKind.Call : kind, ); if (kind === SignatureKind.Construct && sourceSignatures.length && targetSignatures.length) { @@ -22773,7 +29526,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // check we perform for an extends clause excludes construct signatures from the target, // so this check never proceeds. if (reportErrors) { - reportError(Diagnostics.Cannot_assign_an_abstract_constructor_type_to_a_non_abstract_constructor_type); + reportError( + Diagnostics.Cannot_assign_an_abstract_constructor_type_to_a_non_abstract_constructor_type, + ); } return Ternary.False; } @@ -22783,19 +29538,29 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } let result = Ternary.True; - const incompatibleReporter = kind === SignatureKind.Construct ? reportIncompatibleConstructSignatureReturn : reportIncompatibleCallSignatureReturn; + const incompatibleReporter = kind === SignatureKind.Construct ? reportIncompatibleConstructSignatureReturn + : reportIncompatibleCallSignatureReturn; const sourceObjectFlags = getObjectFlags(source); const targetObjectFlags = getObjectFlags(target); if ( - sourceObjectFlags & ObjectFlags.Instantiated && targetObjectFlags & ObjectFlags.Instantiated && source.symbol === target.symbol || - sourceObjectFlags & ObjectFlags.Reference && targetObjectFlags & ObjectFlags.Reference && (source as TypeReference).target === (target as TypeReference).target + sourceObjectFlags & ObjectFlags.Instantiated && targetObjectFlags & ObjectFlags.Instantiated + && source.symbol === target.symbol + || sourceObjectFlags & ObjectFlags.Reference && targetObjectFlags & ObjectFlags.Reference + && (source as TypeReference).target === (target as TypeReference).target ) { // We have instantiations of the same anonymous type (which typically will be the type of a // method). Simply do a pairwise comparison of the signatures in the two signature lists instead // of the much more expensive N * M comparison matrix we explore below. We erase type parameters // as they are known to always be the same. for (let i = 0; i < targetSignatures.length; i++) { - const related = signatureRelatedTo(sourceSignatures[i], targetSignatures[i], /*erase*/ true, reportErrors, intersectionState, incompatibleReporter(sourceSignatures[i], targetSignatures[i])); + const related = signatureRelatedTo( + sourceSignatures[i], + targetSignatures[i], + /*erase*/ true, + reportErrors, + intersectionState, + incompatibleReporter(sourceSignatures[i], targetSignatures[i]), + ); if (!related) { return Ternary.False; } @@ -22811,13 +29576,32 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const eraseGenerics = relation === comparableRelation || !!compilerOptions.noStrictGenericChecks; const sourceSignature = first(sourceSignatures); const targetSignature = first(targetSignatures); - result = signatureRelatedTo(sourceSignature, targetSignature, eraseGenerics, reportErrors, intersectionState, incompatibleReporter(sourceSignature, targetSignature)); + result = signatureRelatedTo( + sourceSignature, + targetSignature, + eraseGenerics, + reportErrors, + intersectionState, + incompatibleReporter(sourceSignature, targetSignature), + ); if ( - !result && reportErrors && kind === SignatureKind.Construct && (sourceObjectFlags & targetObjectFlags) && - (targetSignature.declaration?.kind === SyntaxKind.Constructor || sourceSignature.declaration?.kind === SyntaxKind.Constructor) + !result && reportErrors && kind === SignatureKind.Construct + && (sourceObjectFlags & targetObjectFlags) + && (targetSignature.declaration?.kind === SyntaxKind.Constructor + || sourceSignature.declaration?.kind === SyntaxKind.Constructor) ) { - const constructSignatureToString = (signature: Signature) => signatureToString(signature, /*enclosingDeclaration*/ undefined, TypeFormatFlags.WriteArrowStyleSignature, kind); - reportError(Diagnostics.Type_0_is_not_assignable_to_type_1, constructSignatureToString(sourceSignature), constructSignatureToString(targetSignature)); + const constructSignatureToString = (signature: Signature) => + signatureToString( + signature, + /*enclosingDeclaration*/ undefined, + TypeFormatFlags.WriteArrowStyleSignature, + kind, + ); + reportError( + Diagnostics.Type_0_is_not_assignable_to_type_1, + constructSignatureToString(sourceSignature), + constructSignatureToString(targetSignature), + ); reportError(Diagnostics.Types_of_construct_signatures_are_incompatible); return result; } @@ -22829,7 +29613,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // Only elaborate errors from the first failure let shouldElaborateErrors = reportErrors; for (const s of sourceSignatures) { - const related = signatureRelatedTo(s, t, /*erase*/ true, shouldElaborateErrors, intersectionState, incompatibleReporter(s, t)); + const related = signatureRelatedTo( + s, + t, + /*erase*/ true, + shouldElaborateErrors, + intersectionState, + incompatibleReporter(s, t), + ); if (related) { result &= related; resetErrorInfo(saveErrorInfo); @@ -22838,7 +29629,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { shouldElaborateErrors = false; } if (shouldElaborateErrors) { - reportError(Diagnostics.Type_0_provides_no_match_for_the_signature_1, typeToString(source), signatureToString(t, /*enclosingDeclaration*/ undefined, /*flags*/ undefined, kind)); + reportError( + Diagnostics.Type_0_provides_no_match_for_the_signature_1, + typeToString(source), + signatureToString(t, /*enclosingDeclaration*/ undefined, /*flags*/ undefined, kind), + ); } return Ternary.False; } @@ -22852,8 +29647,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const typeProperties = getPropertiesOfObjectType(source); if ((typeCallSignatures.length || typeConstructSignatures.length) && !typeProperties.length) { if ( - (getSignaturesOfType(target, SignatureKind.Call).length && typeCallSignatures.length) || - (getSignaturesOfType(target, SignatureKind.Construct).length && typeConstructSignatures.length) + (getSignaturesOfType(target, SignatureKind.Call).length && typeCallSignatures.length) + || (getSignaturesOfType(target, SignatureKind.Construct).length && typeConstructSignatures.length) ) { return true; // target has similar signature kinds to source, still focus on the unmatched property } @@ -22864,28 +29659,72 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function reportIncompatibleCallSignatureReturn(siga: Signature, sigb: Signature) { if (siga.parameters.length === 0 && sigb.parameters.length === 0) { - return (source: Type, target: Type) => reportIncompatibleError(Diagnostics.Call_signatures_with_no_arguments_have_incompatible_return_types_0_and_1, typeToString(source), typeToString(target)); + return (source: Type, target: Type) => + reportIncompatibleError( + Diagnostics.Call_signatures_with_no_arguments_have_incompatible_return_types_0_and_1, + typeToString(source), + typeToString(target), + ); } - return (source: Type, target: Type) => reportIncompatibleError(Diagnostics.Call_signature_return_types_0_and_1_are_incompatible, typeToString(source), typeToString(target)); + return (source: Type, target: Type) => + reportIncompatibleError( + Diagnostics.Call_signature_return_types_0_and_1_are_incompatible, + typeToString(source), + typeToString(target), + ); } function reportIncompatibleConstructSignatureReturn(siga: Signature, sigb: Signature) { if (siga.parameters.length === 0 && sigb.parameters.length === 0) { - return (source: Type, target: Type) => reportIncompatibleError(Diagnostics.Construct_signatures_with_no_arguments_have_incompatible_return_types_0_and_1, typeToString(source), typeToString(target)); + return (source: Type, target: Type) => + reportIncompatibleError( + Diagnostics.Construct_signatures_with_no_arguments_have_incompatible_return_types_0_and_1, + typeToString(source), + typeToString(target), + ); } - return (source: Type, target: Type) => reportIncompatibleError(Diagnostics.Construct_signature_return_types_0_and_1_are_incompatible, typeToString(source), typeToString(target)); + return (source: Type, target: Type) => + reportIncompatibleError( + Diagnostics.Construct_signature_return_types_0_and_1_are_incompatible, + typeToString(source), + typeToString(target), + ); } /** * See signatureAssignableTo, compareSignaturesIdentical */ - function signatureRelatedTo(source: Signature, target: Signature, erase: boolean, reportErrors: boolean, intersectionState: IntersectionState, incompatibleReporter: (source: Type, target: Type) => void): Ternary { - const checkMode = relation === subtypeRelation ? SignatureCheckMode.StrictTopSignature : - relation === strictSubtypeRelation ? SignatureCheckMode.StrictTopSignature | SignatureCheckMode.StrictArity : - SignatureCheckMode.None; - return compareSignaturesRelated(erase ? getErasedSignature(source) : source, erase ? getErasedSignature(target) : target, checkMode, reportErrors, reportError, incompatibleReporter, isRelatedToWorker, reportUnreliableMapper); + function signatureRelatedTo( + source: Signature, + target: Signature, + erase: boolean, + reportErrors: boolean, + intersectionState: IntersectionState, + incompatibleReporter: (source: Type, target: Type) => void, + ): Ternary { + const checkMode = relation === subtypeRelation ? SignatureCheckMode.StrictTopSignature + : relation === strictSubtypeRelation + ? SignatureCheckMode.StrictTopSignature | SignatureCheckMode.StrictArity + : SignatureCheckMode.None; + return compareSignaturesRelated( + erase ? getErasedSignature(source) : source, + erase ? getErasedSignature(target) : target, + checkMode, + reportErrors, + reportError, + incompatibleReporter, + isRelatedToWorker, + reportUnreliableMapper, + ); function isRelatedToWorker(source: Type, target: Type, reportErrors?: boolean) { - return isRelatedTo(source, target, RecursionFlags.Both, reportErrors, /*headMessage*/ undefined, intersectionState); + return isRelatedTo( + source, + target, + RecursionFlags.Both, + reportErrors, + /*headMessage*/ undefined, + intersectionState, + ); } } @@ -22897,7 +29736,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } let result = Ternary.True; for (let i = 0; i < sourceSignatures.length; i++) { - const related = compareSignaturesIdentical(sourceSignatures[i], targetSignatures[i], /*partialMatch*/ false, /*ignoreThisTypes*/ false, /*ignoreReturnTypes*/ false, isRelatedTo); + const related = compareSignaturesIdentical( + sourceSignatures[i], + targetSignatures[i], + /*partialMatch*/ false, + /*ignoreThisTypes*/ false, + /*ignoreReturnTypes*/ false, + isRelatedTo, + ); if (!related) { return Ternary.False; } @@ -22906,24 +29752,48 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return result; } - function membersRelatedToIndexInfo(source: Type, targetInfo: IndexInfo, reportErrors: boolean, intersectionState: IntersectionState): Ternary { + function membersRelatedToIndexInfo( + source: Type, + targetInfo: IndexInfo, + reportErrors: boolean, + intersectionState: IntersectionState, + ): Ternary { let result = Ternary.True; const keyType = targetInfo.keyType; - const props = source.flags & TypeFlags.Intersection ? getPropertiesOfUnionOrIntersectionType(source as IntersectionType) : getPropertiesOfObjectType(source); + const props = source.flags & TypeFlags.Intersection + ? getPropertiesOfUnionOrIntersectionType(source as IntersectionType) + : getPropertiesOfObjectType(source); for (const prop of props) { // Skip over ignored JSX and symbol-named members if (isIgnoredJsxProperty(source, prop)) { continue; } - if (isApplicableIndexType(getLiteralTypeFromProperty(prop, TypeFlags.StringOrNumberLiteralOrUnique), keyType)) { + if ( + isApplicableIndexType( + getLiteralTypeFromProperty(prop, TypeFlags.StringOrNumberLiteralOrUnique), + keyType, + ) + ) { const propType = getNonMissingTypeOfSymbol(prop); - const type = exactOptionalPropertyTypes || propType.flags & TypeFlags.Undefined || keyType === numberType || !(prop.flags & SymbolFlags.Optional) - ? propType - : getTypeWithFacts(propType, TypeFacts.NEUndefined); - const related = isRelatedTo(type, targetInfo.type, RecursionFlags.Both, reportErrors, /*headMessage*/ undefined, intersectionState); + const type = + exactOptionalPropertyTypes || propType.flags & TypeFlags.Undefined || keyType === numberType + || !(prop.flags & SymbolFlags.Optional) + ? propType + : getTypeWithFacts(propType, TypeFacts.NEUndefined); + const related = isRelatedTo( + type, + targetInfo.type, + RecursionFlags.Both, + reportErrors, + /*headMessage*/ undefined, + intersectionState, + ); if (!related) { if (reportErrors) { - reportError(Diagnostics.Property_0_is_incompatible_with_index_signature, symbolToString(prop)); + reportError( + Diagnostics.Property_0_is_incompatible_with_index_signature, + symbolToString(prop), + ); } return Ternary.False; } @@ -22942,20 +29812,42 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return result; } - function indexInfoRelatedTo(sourceInfo: IndexInfo, targetInfo: IndexInfo, reportErrors: boolean, intersectionState: IntersectionState) { - const related = isRelatedTo(sourceInfo.type, targetInfo.type, RecursionFlags.Both, reportErrors, /*headMessage*/ undefined, intersectionState); + function indexInfoRelatedTo( + sourceInfo: IndexInfo, + targetInfo: IndexInfo, + reportErrors: boolean, + intersectionState: IntersectionState, + ) { + const related = isRelatedTo( + sourceInfo.type, + targetInfo.type, + RecursionFlags.Both, + reportErrors, + /*headMessage*/ undefined, + intersectionState, + ); if (!related && reportErrors) { if (sourceInfo.keyType === targetInfo.keyType) { reportError(Diagnostics._0_index_signatures_are_incompatible, typeToString(sourceInfo.keyType)); } else { - reportError(Diagnostics._0_and_1_index_signatures_are_incompatible, typeToString(sourceInfo.keyType), typeToString(targetInfo.keyType)); + reportError( + Diagnostics._0_and_1_index_signatures_are_incompatible, + typeToString(sourceInfo.keyType), + typeToString(targetInfo.keyType), + ); } } return related; } - function indexSignaturesRelatedTo(source: Type, target: Type, sourceIsPrimitive: boolean, reportErrors: boolean, intersectionState: IntersectionState): Ternary { + function indexSignaturesRelatedTo( + source: Type, + target: Type, + sourceIsPrimitive: boolean, + reportErrors: boolean, + intersectionState: IntersectionState, + ): Ternary { if (relation === identityRelation) { return indexSignaturesIdenticalTo(source, target); } @@ -22963,9 +29855,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const targetHasStringIndex = some(indexInfos, info => info.keyType === stringType); let result = Ternary.True; for (const targetInfo of indexInfos) { - const related = relation !== strictSubtypeRelation && !sourceIsPrimitive && targetHasStringIndex && targetInfo.type.flags & TypeFlags.Any ? Ternary.True : - isGenericMappedType(source) && targetHasStringIndex ? isRelatedTo(getTemplateTypeFromMappedType(source), targetInfo.type, RecursionFlags.Both, reportErrors) : - typeRelatedToIndexInfo(source, targetInfo, reportErrors, intersectionState); + const related = relation !== strictSubtypeRelation && !sourceIsPrimitive && targetHasStringIndex + && targetInfo.type.flags & TypeFlags.Any ? Ternary.True + : isGenericMappedType(source) && targetHasStringIndex + ? isRelatedTo( + getTemplateTypeFromMappedType(source), + targetInfo.type, + RecursionFlags.Both, + reportErrors, + ) + : typeRelatedToIndexInfo(source, targetInfo, reportErrors, intersectionState); if (!related) { return Ternary.False; } @@ -22974,7 +29873,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return result; } - function typeRelatedToIndexInfo(source: Type, targetInfo: IndexInfo, reportErrors: boolean, intersectionState: IntersectionState): Ternary { + function typeRelatedToIndexInfo( + source: Type, + targetInfo: IndexInfo, + reportErrors: boolean, + intersectionState: IntersectionState, + ): Ternary { const sourceInfo = getApplicableIndexInfo(source, targetInfo.keyType); if (sourceInfo) { return indexInfoRelatedTo(sourceInfo, targetInfo, reportErrors, intersectionState); @@ -22982,11 +29886,19 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // Intersection constituents are never considered to have an inferred index signature. Also, in the strict subtype relation, // only fresh object literals are considered to have inferred index signatures. This ensures { [x: string]: xxx } <: {} but // not vice-versa. Without this rule, those types would be mutual strict subtypes. - if (!(intersectionState & IntersectionState.Source) && (relation !== strictSubtypeRelation || getObjectFlags(source) & ObjectFlags.FreshLiteral) && isObjectTypeWithInferableIndex(source)) { + if ( + !(intersectionState & IntersectionState.Source) + && (relation !== strictSubtypeRelation || getObjectFlags(source) & ObjectFlags.FreshLiteral) + && isObjectTypeWithInferableIndex(source) + ) { return membersRelatedToIndexInfo(source, targetInfo, reportErrors, intersectionState); } if (reportErrors) { - reportError(Diagnostics.Index_signature_for_type_0_is_missing_in_type_1, typeToString(targetInfo.keyType), typeToString(source)); + reportError( + Diagnostics.Index_signature_for_type_0_is_missing_in_type_1, + typeToString(targetInfo.keyType), + typeToString(source), + ); } return Ternary.False; } @@ -22999,20 +29911,33 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } for (const targetInfo of targetInfos) { const sourceInfo = getIndexInfoOfType(source, targetInfo.keyType); - if (!(sourceInfo && isRelatedTo(sourceInfo.type, targetInfo.type, RecursionFlags.Both) && sourceInfo.isReadonly === targetInfo.isReadonly)) { + if ( + !(sourceInfo && isRelatedTo(sourceInfo.type, targetInfo.type, RecursionFlags.Both) + && sourceInfo.isReadonly === targetInfo.isReadonly) + ) { return Ternary.False; } } return Ternary.True; } - function constructorVisibilitiesAreCompatible(sourceSignature: Signature, targetSignature: Signature, reportErrors: boolean) { + function constructorVisibilitiesAreCompatible( + sourceSignature: Signature, + targetSignature: Signature, + reportErrors: boolean, + ) { if (!sourceSignature.declaration || !targetSignature.declaration) { return true; } - const sourceAccessibility = getSelectedEffectiveModifierFlags(sourceSignature.declaration, ModifierFlags.NonPublicAccessibilityModifier); - const targetAccessibility = getSelectedEffectiveModifierFlags(targetSignature.declaration, ModifierFlags.NonPublicAccessibilityModifier); + const sourceAccessibility = getSelectedEffectiveModifierFlags( + sourceSignature.declaration, + ModifierFlags.NonPublicAccessibilityModifier, + ); + const targetAccessibility = getSelectedEffectiveModifierFlags( + targetSignature.declaration, + ModifierFlags.NonPublicAccessibilityModifier, + ); // A public, protected and private signature is assignable to a private signature. if (targetAccessibility === ModifierFlags.Private) { @@ -23030,7 +29955,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } if (reportErrors) { - reportError(Diagnostics.Cannot_assign_a_0_constructor_type_to_a_1_constructor_type, visibilityToString(sourceAccessibility), visibilityToString(targetAccessibility)); + reportError( + Diagnostics.Cannot_assign_a_0_constructor_type_to_a_1_constructor_type, + visibilityToString(sourceAccessibility), + visibilityToString(targetAccessibility), + ); } return false; @@ -23056,13 +29985,19 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } - return isUnitType(type) || !!(type.flags & TypeFlags.TemplateLiteral) || !!(type.flags & TypeFlags.StringMapping); + return isUnitType(type) || !!(type.flags & TypeFlags.TemplateLiteral) + || !!(type.flags & TypeFlags.StringMapping); } function getExactOptionalUnassignableProperties(source: Type, target: Type) { if (isTupleType(source) && isTupleType(target)) return emptyArray; return getPropertiesOfType(target) - .filter(targetProp => isExactOptionalPropertyMismatch(getTypeOfPropertyOfType(source, targetProp.escapedName), getTypeOfSymbol(targetProp))); + .filter(targetProp => + isExactOptionalPropertyMismatch( + getTypeOfPropertyOfType(source, targetProp.escapedName), + getTypeOfSymbol(targetProp), + ) + ); } function isExactOptionalPropertyMismatch(source: Type | undefined, target: Type | undefined) { @@ -23074,14 +30009,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function getBestMatchingType(source: Type, target: UnionOrIntersectionType, isRelatedTo = compareTypesAssignable) { - return findMatchingDiscriminantType(source, target, isRelatedTo) || - findMatchingTypeReferenceOrTypeAliasReference(source, target) || - findBestTypeForObjectLiteral(source, target) || - findBestTypeForInvokable(source, target) || - findMostOverlappyType(source, target); + return findMatchingDiscriminantType(source, target, isRelatedTo) + || findMatchingTypeReferenceOrTypeAliasReference(source, target) + || findBestTypeForObjectLiteral(source, target) + || findBestTypeForInvokable(source, target) + || findMostOverlappyType(source, target); } - function discriminateTypeByDiscriminableItems(target: UnionType, discriminators: [() => Type, __String][], related: (source: Type, target: Type) => boolean | Ternary) { + function discriminateTypeByDiscriminableItems( + target: UnionType, + discriminators: [() => Type, __String][], + related: (source: Type, target: Type) => boolean | Ternary, + ) { const types = target.types; const include: Ternary[] = types.map(t => t.flags & TypeFlags.Primitive ? Ternary.False : Ternary.True); for (const [getDiscriminatingType, propertyName] of discriminators) { @@ -23107,7 +30046,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } } - const filtered = contains(include, Ternary.False) ? getUnionType(types.filter((_, i) => include[i]), UnionReduction.None) : target; + const filtered = contains(include, Ternary.False) + ? getUnionType(types.filter((_, i) => include[i]), UnionReduction.None) : target; return filtered.flags & TypeFlags.Never ? target : filtered; } @@ -23118,8 +30058,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function isWeakType(type: Type): boolean { if (type.flags & TypeFlags.Object) { const resolved = resolveStructuredTypeMembers(type as ObjectType); - return resolved.callSignatures.length === 0 && resolved.constructSignatures.length === 0 && resolved.indexInfos.length === 0 && - resolved.properties.length > 0 && every(resolved.properties, p => !!(p.flags & SymbolFlags.Optional)); + return resolved.callSignatures.length === 0 && resolved.constructSignatures.length === 0 + && resolved.indexInfos.length === 0 + && resolved.properties.length > 0 && every(resolved.properties, p => + !!(p.flags & SymbolFlags.Optional)); } if (type.flags & TypeFlags.Intersection) { return every((type as IntersectionType).types, isWeakType); @@ -23138,9 +30080,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function getVariances(type: GenericType): VarianceFlags[] { // Arrays and tuples are known to be covariant, no need to spend time computing this. - return type === globalArrayType || type === globalReadonlyArrayType || type.objectFlags & ObjectFlags.Tuple ? - arrayVariances : - getVariancesWorker(type.symbol, type.typeParameters); + return type === globalArrayType || type === globalReadonlyArrayType || type.objectFlags & ObjectFlags.Tuple + ? arrayVariances + : getVariancesWorker(type.symbol, type.typeParameters); } function getAliasVariances(symbol: Symbol) { @@ -23152,10 +30094,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // generic type are structurally compared. We infer the variance information by comparing // instantiations of the generic type for type arguments with known relations. The function // returns the emptyArray singleton when invoked recursively for the given generic type. - function getVariancesWorker(symbol: Symbol, typeParameters: readonly TypeParameter[] = emptyArray): VarianceFlags[] { + function getVariancesWorker( + symbol: Symbol, + typeParameters: readonly TypeParameter[] = emptyArray, + ): VarianceFlags[] { const links = getSymbolLinks(symbol); if (!links.variances) { - tracing?.push(tracing.Phase.CheckTypes, "getVariancesWorker", { arity: typeParameters.length, id: getTypeId(getDeclaredTypeOfSymbol(symbol)) }); + tracing?.push(tracing.Phase.CheckTypes, "getVariancesWorker", { + arity: typeParameters.length, + id: getTypeId(getDeclaredTypeOfSymbol(symbol)), + }); const oldVarianceComputation = inVarianceComputation; if (!inVarianceComputation) { inVarianceComputation = true; @@ -23165,26 +30113,30 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const variances = []; for (const tp of typeParameters) { const modifiers = getTypeParameterModifiers(tp); - let variance = modifiers & ModifierFlags.Out ? - modifiers & ModifierFlags.In ? VarianceFlags.Invariant : VarianceFlags.Covariant : - modifiers & ModifierFlags.In ? VarianceFlags.Contravariant : undefined; + let variance = modifiers & ModifierFlags.Out + ? modifiers & ModifierFlags.In ? VarianceFlags.Invariant : VarianceFlags.Covariant + : modifiers & ModifierFlags.In ? VarianceFlags.Contravariant : undefined; if (variance === undefined) { let unmeasurable = false; let unreliable = false; const oldHandler = outofbandVarianceMarkerHandler; - outofbandVarianceMarkerHandler = onlyUnreliable => onlyUnreliable ? unreliable = true : unmeasurable = true; + outofbandVarianceMarkerHandler = onlyUnreliable => + onlyUnreliable ? unreliable = true : unmeasurable = true; // We first compare instantiations where the type parameter is replaced with // marker types that have a known subtype relationship. From this we can infer // invariance, covariance, contravariance or bivariance. const typeWithSuper = createMarkerType(symbol, tp, markerSuperType); const typeWithSub = createMarkerType(symbol, tp, markerSubType); - variance = (isTypeAssignableTo(typeWithSub, typeWithSuper) ? VarianceFlags.Covariant : 0) | - (isTypeAssignableTo(typeWithSuper, typeWithSub) ? VarianceFlags.Contravariant : 0); + variance = (isTypeAssignableTo(typeWithSub, typeWithSuper) ? VarianceFlags.Covariant : 0) + | (isTypeAssignableTo(typeWithSuper, typeWithSub) ? VarianceFlags.Contravariant : 0); // If the instantiations appear to be related bivariantly it may be because the // type parameter is independent (i.e. it isn't witnessed anywhere in the generic // type). To determine this we compare instantiations where the type parameter is // replaced with marker types that are known to be unrelated. - if (variance === VarianceFlags.Bivariant && isTypeAssignableTo(createMarkerType(symbol, tp, markerOtherType), typeWithSuper)) { + if ( + variance === VarianceFlags.Bivariant + && isTypeAssignableTo(createMarkerType(symbol, tp, markerOtherType), typeWithSuper) + ) { variance = VarianceFlags.Independent; } outofbandVarianceMarkerHandler = oldHandler; @@ -23215,9 +30167,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (isErrorType(type)) { return type; } - const result = symbol.flags & SymbolFlags.TypeAlias ? - getTypeAliasInstantiation(symbol, instantiateTypes(getSymbolLinks(symbol).typeParameters!, mapper)) : - createTypeReference(type as GenericType, instantiateTypes((type as GenericType).typeParameters, mapper)); + const result = symbol.flags & SymbolFlags.TypeAlias + ? getTypeAliasInstantiation(symbol, instantiateTypes(getSymbolLinks(symbol).typeParameters!, mapper)) + : createTypeReference(type as GenericType, instantiateTypes((type as GenericType).typeParameters, mapper)); markerTypes.add(getTypeId(result)); return result; } @@ -23227,14 +30179,21 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function getTypeParameterModifiers(tp: TypeParameter): ModifierFlags { - return reduceLeft(tp.symbol?.declarations, (modifiers, d) => modifiers | getEffectiveModifierFlags(d), ModifierFlags.None) & (ModifierFlags.In | ModifierFlags.Out | ModifierFlags.Const); + return reduceLeft( + tp.symbol?.declarations, + (modifiers, d) => modifiers | getEffectiveModifierFlags(d), + ModifierFlags.None, + ) & (ModifierFlags.In | ModifierFlags.Out | ModifierFlags.Const); } // Return true if the given type reference has a 'void' type argument for a covariant type parameter. // See comment at call in recursiveTypeRelatedTo for when this case matters. function hasCovariantVoidArgument(typeArguments: readonly Type[], variances: VarianceFlags[]): boolean { for (let i = 0; i < variances.length; i++) { - if ((variances[i] & VarianceFlags.VarianceMask) === VarianceFlags.Covariant && typeArguments[i].flags & TypeFlags.Void) { + if ( + (variances[i] & VarianceFlags.VarianceMask) === VarianceFlags.Covariant + && typeArguments[i].flags & TypeFlags.Void + ) { return true; } } @@ -23250,10 +30209,19 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function isTypeReferenceWithGenericArguments(type: Type): boolean { - return isNonDeferredTypeReference(type) && some(getTypeArguments(type), t => !!(t.flags & TypeFlags.TypeParameter) || isTypeReferenceWithGenericArguments(t)); + return isNonDeferredTypeReference(type) + && some( + getTypeArguments(type), + t => !!(t.flags & TypeFlags.TypeParameter) || isTypeReferenceWithGenericArguments(t), + ); } - function getGenericTypeReferenceRelationKey(source: TypeReference, target: TypeReference, postFix: string, ignoreConstraints: boolean) { + function getGenericTypeReferenceRelationKey( + source: TypeReference, + target: TypeReference, + postFix: string, + ignoreConstraints: boolean, + ) { const typeParameters: Type[] = []; let constraintMarker = ""; const sourceId = getTypeReferenceId(source, 0); @@ -23292,16 +30260,27 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { * To improve caching, the relation key for two generic types uses the target's id plus ids of the type parameters. * For other cases, the types ids are used. */ - function getRelationKey(source: Type, target: Type, intersectionState: IntersectionState, relation: Map, ignoreConstraints: boolean) { + function getRelationKey( + source: Type, + target: Type, + intersectionState: IntersectionState, + relation: Map, + ignoreConstraints: boolean, + ) { if (relation === identityRelation && source.id > target.id) { const temp = source; source = target; target = temp; } const postFix = intersectionState ? ":" + intersectionState : ""; - return isTypeReferenceWithGenericArguments(source) && isTypeReferenceWithGenericArguments(target) ? - getGenericTypeReferenceRelationKey(source as TypeReference, target as TypeReference, postFix, ignoreConstraints) : - `${source.id},${target.id}${postFix}`; + return isTypeReferenceWithGenericArguments(source) && isTypeReferenceWithGenericArguments(target) + ? getGenericTypeReferenceRelationKey( + source as TypeReference, + target as TypeReference, + postFix, + ignoreConstraints, + ) + : `${source.id},${target.id}${postFix}`; } // Invoke the callback for each underlying property symbol of the given symbol and return the first @@ -23323,7 +30302,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // Return the declaring class type of a property or undefined if property not declared in class function getDeclaringClass(prop: Symbol) { - return prop.parent && prop.parent.flags & SymbolFlags.Class ? getDeclaredTypeOfSymbol(getParentOfSymbol(prop)!) as InterfaceType : undefined; + return prop.parent && prop.parent.flags & SymbolFlags.Class + ? getDeclaredTypeOfSymbol(getParentOfSymbol(prop)!) as InterfaceType : undefined; } // Return the inherited type of the given property or undefined if property doesn't exist in a base class. @@ -23345,16 +30325,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // Return true if source property is a valid override of protected parts of target property. function isValidOverrideOf(sourceProp: Symbol, targetProp: Symbol) { return !forEachProperty(targetProp, tp => - getDeclarationModifierFlagsFromSymbol(tp) & ModifierFlags.Protected ? - !isPropertyInClassDerivedFrom(sourceProp, getDeclaringClass(tp)) : false); + getDeclarationModifierFlagsFromSymbol(tp) & ModifierFlags.Protected + ? !isPropertyInClassDerivedFrom(sourceProp, getDeclaringClass(tp)) : false); } // Return true if the given class derives from each of the declaring classes of the protected // constituents of the given property. function isClassDerivedFromDeclaringClasses(checkClass: T, prop: Symbol, writing: boolean) { return forEachProperty(prop, p => - getDeclarationModifierFlagsFromSymbol(p, writing) & ModifierFlags.Protected ? - !hasBaseType(checkClass, getDeclaringClass(p)) : false) ? undefined : checkClass; + getDeclarationModifierFlagsFromSymbol(p, writing) & ModifierFlags.Protected + ? !hasBaseType(checkClass, getDeclaringClass(p)) : false) ? undefined : checkClass; } // Return true if the given type is deeply nested. We consider this to be the case when structural type comparisons @@ -23381,7 +30361,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { let lastTypeId = 0; for (let i = 0; i < depth; i++) { const t = stack[i]; - if (t.flags & TypeFlags.Intersection ? some((t as IntersectionType).types, u => getRecursionIdentity(u) === identity) : getRecursionIdentity(t) === identity) { + if ( + t.flags & TypeFlags.Intersection ? some((t as IntersectionType).types, u => + getRecursionIdentity(u) === identity) : getRecursionIdentity(t) === identity + ) { // We only count occurrences with a higher type id than the previous occurrence, since higher // type ids are an indicator of newer instantiations caused by recursion. if (t.id >= lastTypeId) { @@ -23412,7 +30395,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // unique AST node. return (type as TypeReference).node!; } - if (type.symbol && !(getObjectFlags(type) & ObjectFlags.Anonymous && type.symbol.flags & SymbolFlags.Class)) { + if ( + type.symbol && !(getObjectFlags(type) & ObjectFlags.Anonymous && type.symbol.flags & SymbolFlags.Class) + ) { // We track all object types that have an associated symbol (representing the origin of the type), but // exclude the static side of classes from this check since it shares its symbol with the instance side. return type.symbol; @@ -23443,15 +30428,21 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return compareProperties(sourceProp, targetProp, compareTypesIdentical) !== Ternary.False; } - function compareProperties(sourceProp: Symbol, targetProp: Symbol, compareTypes: (source: Type, target: Type) => Ternary): Ternary { + function compareProperties( + sourceProp: Symbol, + targetProp: Symbol, + compareTypes: (source: Type, target: Type) => Ternary, + ): Ternary { // Two members are considered identical when // - they are public properties with identical names, optionality, and types, // - they are private or protected properties originating in the same declaration and having identical types if (sourceProp === targetProp) { return Ternary.True; } - const sourcePropAccessibility = getDeclarationModifierFlagsFromSymbol(sourceProp) & ModifierFlags.NonPublicAccessibilityModifier; - const targetPropAccessibility = getDeclarationModifierFlagsFromSymbol(targetProp) & ModifierFlags.NonPublicAccessibilityModifier; + const sourcePropAccessibility = getDeclarationModifierFlagsFromSymbol(sourceProp) + & ModifierFlags.NonPublicAccessibilityModifier; + const targetPropAccessibility = getDeclarationModifierFlagsFromSymbol(targetProp) + & ModifierFlags.NonPublicAccessibilityModifier; if (sourcePropAccessibility !== targetPropAccessibility) { return Ternary.False; } @@ -23481,9 +30472,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // A source signature matches a target signature if the two signatures have the same number of required, // optional, and rest parameters. if ( - sourceParameterCount === targetParameterCount && - sourceMinArgumentCount === targetMinArgumentCount && - sourceHasRestParameter === targetHasRestParameter + sourceParameterCount === targetParameterCount + && sourceMinArgumentCount === targetMinArgumentCount + && sourceHasRestParameter === targetHasRestParameter ) { return true; } @@ -23498,7 +30489,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { /** * See signatureRelatedTo, compareSignaturesIdentical */ - function compareSignaturesIdentical(source: Signature, target: Signature, partialMatch: boolean, ignoreThisTypes: boolean, ignoreReturnTypes: boolean, compareTypes: (s: Type, t: Type) => Ternary): Ternary { + function compareSignaturesIdentical( + source: Signature, + target: Signature, + partialMatch: boolean, + ignoreThisTypes: boolean, + ignoreReturnTypes: boolean, + compareTypes: (s: Type, t: Type) => Ternary, + ): Ternary { // TODO (drosen): De-duplicate code between related functions. if (source === target) { return Ternary.True; @@ -23518,8 +30516,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const s = source.typeParameters![i]; const t = target.typeParameters[i]; if ( - !(s === t || compareTypes(instantiateType(getConstraintFromTypeParameter(s), mapper) || unknownType, getConstraintFromTypeParameter(t) || unknownType) && - compareTypes(instantiateType(getDefaultFromTypeParameter(s), mapper) || unknownType, getDefaultFromTypeParameter(t) || unknownType)) + !(s === t + || compareTypes( + instantiateType(getConstraintFromTypeParameter(s), mapper) || unknownType, + getConstraintFromTypeParameter(t) || unknownType, + ) + && compareTypes( + instantiateType(getDefaultFromTypeParameter(s), mapper) || unknownType, + getDefaultFromTypeParameter(t) || unknownType, + )) ) { return Ternary.False; } @@ -23553,18 +30558,22 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (!ignoreReturnTypes) { const sourceTypePredicate = getTypePredicateOfSignature(source); const targetTypePredicate = getTypePredicateOfSignature(target); - result &= sourceTypePredicate || targetTypePredicate ? - compareTypePredicatesIdentical(sourceTypePredicate, targetTypePredicate, compareTypes) : - compareTypes(getReturnTypeOfSignature(source), getReturnTypeOfSignature(target)); + result &= sourceTypePredicate || targetTypePredicate + ? compareTypePredicatesIdentical(sourceTypePredicate, targetTypePredicate, compareTypes) + : compareTypes(getReturnTypeOfSignature(source), getReturnTypeOfSignature(target)); } return result; } - function compareTypePredicatesIdentical(source: TypePredicate | undefined, target: TypePredicate | undefined, compareTypes: (s: Type, t: Type) => Ternary): Ternary { - return !(source && target && typePredicateKindsMatch(source, target)) ? Ternary.False : - source.type === target.type ? Ternary.True : - source.type && target.type ? compareTypes(source.type, target.type) : - Ternary.False; + function compareTypePredicatesIdentical( + source: TypePredicate | undefined, + target: TypePredicate | undefined, + compareTypes: (s: Type, t: Type) => Ternary, + ): Ternary { + return !(source && target && typePredicateKindsMatch(source, target)) ? Ternary.False + : source.type === target.type ? Ternary.True + : source.type && target.type ? compareTypes(source.type, target.type) + : Ternary.False; } function literalTypesWithSameBaseType(types: Type[]): boolean { @@ -23582,7 +30591,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function getCombinedTypeFlags(types: Type[]): TypeFlags { - return reduceLeft(types, (flags, t) => flags | (t.flags & TypeFlags.Union ? getCombinedTypeFlags((t as UnionType).types) : t.flags), 0 as TypeFlags); + return reduceLeft( + types, + (flags, t) => flags | (t.flags & TypeFlags.Union ? getCombinedTypeFlags((t as UnionType).types) : t.flags), + 0 as TypeFlags, + ); } function getCommonSupertype(types: Type[]): Type { @@ -23590,15 +30603,17 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return types[0]; } // Remove nullable types from each of the candidates. - const primaryTypes = strictNullChecks ? sameMap(types, t => filterType(t, u => !(u.flags & TypeFlags.Nullable))) : types; + const primaryTypes = strictNullChecks ? sameMap(types, t => filterType(t, u => !(u.flags & TypeFlags.Nullable))) + : types; // When the candidate types are all literal types with the same base type, return a union // of those literal types. Otherwise, return the leftmost type for which no type to the // right is a supertype. - const superTypeOrUnion = literalTypesWithSameBaseType(primaryTypes) ? - getUnionType(primaryTypes) : - reduceLeft(primaryTypes, (s, t) => isTypeSubtypeOf(s, t) ? t : s)!; + const superTypeOrUnion = literalTypesWithSameBaseType(primaryTypes) + ? getUnionType(primaryTypes) + : reduceLeft(primaryTypes, (s, t) => isTypeSubtypeOf(s, t) ? t : s)!; // Add any nullable types that occurred in the candidates back to the result. - return primaryTypes === types ? superTypeOrUnion : getNullableType(superTypeOrUnion, getCombinedTypeFlags(types) & TypeFlags.Nullable); + return primaryTypes === types ? superTypeOrUnion + : getNullableType(superTypeOrUnion, getCombinedTypeFlags(types) & TypeFlags.Nullable); } // Return the leftmost type for which no type to the right is a subtype. @@ -23607,11 +30622,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function isArrayType(type: Type): type is TypeReference { - return !!(getObjectFlags(type) & ObjectFlags.Reference) && ((type as TypeReference).target === globalArrayType || (type as TypeReference).target === globalReadonlyArrayType); + return !!(getObjectFlags(type) & ObjectFlags.Reference) + && ((type as TypeReference).target === globalArrayType + || (type as TypeReference).target === globalReadonlyArrayType); } function isReadonlyArrayType(type: Type): boolean { - return !!(getObjectFlags(type) & ObjectFlags.Reference) && (type as TypeReference).target === globalReadonlyArrayType; + return !!(getObjectFlags(type) & ObjectFlags.Reference) + && (type as TypeReference).target === globalReadonlyArrayType; } function isArrayOrTupleType(type: Type): type is TypeReference { @@ -23629,15 +30647,20 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function isArrayLikeType(type: Type): boolean { // A type is array-like if it is a reference to the global Array or global ReadonlyArray type, // or if it is not the undefined or null type and if it is assignable to ReadonlyArray - return isArrayType(type) || !(type.flags & TypeFlags.Nullable) && isTypeAssignableTo(type, anyReadonlyArrayType); + return isArrayType(type) + || !(type.flags & TypeFlags.Nullable) && isTypeAssignableTo(type, anyReadonlyArrayType); } function getSingleBaseForNonAugmentingSubtype(type: Type) { - if (!(getObjectFlags(type) & ObjectFlags.Reference) || !(getObjectFlags((type as TypeReference).target) & ObjectFlags.ClassOrInterface)) { + if ( + !(getObjectFlags(type) & ObjectFlags.Reference) + || !(getObjectFlags((type as TypeReference).target) & ObjectFlags.ClassOrInterface) + ) { return undefined; } if (getObjectFlags(type) & ObjectFlags.IdenticalBaseTypeCalculated) { - return getObjectFlags(type) & ObjectFlags.IdenticalBaseTypeExists ? (type as TypeReference).cachedEquivalentBaseType : undefined; + return getObjectFlags(type) & ObjectFlags.IdenticalBaseTypeExists + ? (type as TypeReference).cachedEquivalentBaseType : undefined; } (type as TypeReference).objectFlags |= ObjectFlags.IdenticalBaseTypeCalculated; const target = (type as TypeReference).target as InterfaceType; @@ -23645,7 +30668,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const baseTypeNode = getBaseTypeNodeOfClass(target); // A base type expression may circularly reference the class itself (e.g. as an argument to function call), so we only // check for base types specified as simple qualified names. - if (baseTypeNode && baseTypeNode.expression.kind !== SyntaxKind.Identifier && baseTypeNode.expression.kind !== SyntaxKind.PropertyAccessExpression) { + if ( + baseTypeNode && baseTypeNode.expression.kind !== SyntaxKind.Identifier + && baseTypeNode.expression.kind !== SyntaxKind.PropertyAccessExpression + ) { return undefined; } } @@ -23656,7 +30682,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (getMembersOfSymbol(type.symbol).size) { return undefined; // If the interface has any members, they may subtype members in the base, so we should do a full structural comparison } - let instantiatedBase = !length(target.typeParameters) ? bases[0] : instantiateType(bases[0], createTypeMapper(target.typeParameters!, getTypeArguments(type as TypeReference).slice(0, target.typeParameters!.length))); + let instantiatedBase = !length(target.typeParameters) ? bases[0] + : instantiateType( + bases[0], + createTypeMapper( + target.typeParameters!, + getTypeArguments(type as TypeReference).slice(0, target.typeParameters!.length), + ), + ); if (length(getTypeArguments(type as TypeReference)) > length(target.typeParameters)) { instantiatedBase = getTypeWithThisArgument(instantiatedBase, last(getTypeArguments(type as TypeReference))); } @@ -23675,9 +30708,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function isTupleLikeType(type: Type): boolean { let lengthType; - return isTupleType(type) || - !!getPropertyOfType(type, "0" as __String) || - isArrayLikeType(type) && !!(lengthType = getTypeOfPropertyOfType(type, "length" as __String)) && everyType(lengthType, t => !!(t.flags & TypeFlags.NumberLiteral)); + return isTupleType(type) + || !!getPropertyOfType(type, "0" as __String) + || isArrayLikeType(type) && !!(lengthType = getTypeOfPropertyOfType(type, "length" as __String)) + && everyType(lengthType, t => !!(t.flags & TypeFlags.NumberLiteral)); } function isArrayOrTupleLikeType(type: Type): boolean { @@ -23690,7 +30724,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return propType; } if (everyType(type, isTupleType)) { - return getTupleElementTypeOutOfStartCount(type, index, compilerOptions.noUncheckedIndexedAccess ? undefinedType : undefined); + return getTupleElementTypeOutOfStartCount( + type, + index, + compilerOptions.noUncheckedIndexedAccess ? undefinedType : undefined, + ); } return undefined; } @@ -23715,19 +30753,20 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function isLiteralType(type: Type): boolean { - return type.flags & TypeFlags.Boolean ? true : - type.flags & TypeFlags.Union ? type.flags & TypeFlags.EnumLiteral ? true : every((type as UnionType).types, isUnitType) : - isUnitType(type); + return type.flags & TypeFlags.Boolean ? true + : type.flags & TypeFlags.Union + ? type.flags & TypeFlags.EnumLiteral ? true : every((type as UnionType).types, isUnitType) + : isUnitType(type); } function getBaseTypeOfLiteralType(type: Type): Type { - return type.flags & TypeFlags.EnumLike ? getBaseTypeOfEnumLikeType(type as LiteralType) : - type.flags & (TypeFlags.StringLiteral | TypeFlags.TemplateLiteral | TypeFlags.StringMapping) ? stringType : - type.flags & TypeFlags.NumberLiteral ? numberType : - type.flags & TypeFlags.BigIntLiteral ? bigintType : - type.flags & TypeFlags.BooleanLiteral ? booleanType : - type.flags & TypeFlags.Union ? getBaseTypeOfLiteralTypeUnion(type as UnionType) : - type; + return type.flags & TypeFlags.EnumLike ? getBaseTypeOfEnumLikeType(type as LiteralType) + : type.flags & (TypeFlags.StringLiteral | TypeFlags.TemplateLiteral | TypeFlags.StringMapping) ? stringType + : type.flags & TypeFlags.NumberLiteral ? numberType + : type.flags & TypeFlags.BigIntLiteral ? bigintType + : type.flags & TypeFlags.BooleanLiteral ? booleanType + : type.flags & TypeFlags.Union ? getBaseTypeOfLiteralTypeUnion(type as UnionType) + : type; } function getBaseTypeOfLiteralTypeUnion(type: UnionType) { @@ -23738,28 +30777,29 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // This like getBaseTypeOfLiteralType, but instead treats enum literals as strings/numbers instead // of returning their enum base type (which depends on the types of other literals in the enum). function getBaseTypeOfLiteralTypeForComparison(type: Type): Type { - return type.flags & (TypeFlags.StringLiteral | TypeFlags.TemplateLiteral | TypeFlags.StringMapping) ? stringType : - type.flags & (TypeFlags.NumberLiteral | TypeFlags.Enum) ? numberType : - type.flags & TypeFlags.BigIntLiteral ? bigintType : - type.flags & TypeFlags.BooleanLiteral ? booleanType : - type.flags & TypeFlags.Union ? mapType(type, getBaseTypeOfLiteralTypeForComparison) : - type; + return type.flags & (TypeFlags.StringLiteral | TypeFlags.TemplateLiteral | TypeFlags.StringMapping) ? stringType + : type.flags & (TypeFlags.NumberLiteral | TypeFlags.Enum) ? numberType + : type.flags & TypeFlags.BigIntLiteral ? bigintType + : type.flags & TypeFlags.BooleanLiteral ? booleanType + : type.flags & TypeFlags.Union ? mapType(type, getBaseTypeOfLiteralTypeForComparison) + : type; } function getWidenedLiteralType(type: Type): Type { - return type.flags & TypeFlags.EnumLike && isFreshLiteralType(type) ? getBaseTypeOfEnumLikeType(type as LiteralType) : - type.flags & TypeFlags.StringLiteral && isFreshLiteralType(type) ? stringType : - type.flags & TypeFlags.NumberLiteral && isFreshLiteralType(type) ? numberType : - type.flags & TypeFlags.BigIntLiteral && isFreshLiteralType(type) ? bigintType : - type.flags & TypeFlags.BooleanLiteral && isFreshLiteralType(type) ? booleanType : - type.flags & TypeFlags.Union ? mapType(type as UnionType, getWidenedLiteralType) : - type; + return type.flags & TypeFlags.EnumLike && isFreshLiteralType(type) + ? getBaseTypeOfEnumLikeType(type as LiteralType) + : type.flags & TypeFlags.StringLiteral && isFreshLiteralType(type) ? stringType + : type.flags & TypeFlags.NumberLiteral && isFreshLiteralType(type) ? numberType + : type.flags & TypeFlags.BigIntLiteral && isFreshLiteralType(type) ? bigintType + : type.flags & TypeFlags.BooleanLiteral && isFreshLiteralType(type) ? booleanType + : type.flags & TypeFlags.Union ? mapType(type as UnionType, getWidenedLiteralType) + : type; } function getWidenedUniqueESSymbolType(type: Type): Type { - return type.flags & TypeFlags.UniqueESSymbol ? esSymbolType : - type.flags & TypeFlags.Union ? mapType(type as UnionType, getWidenedUniqueESSymbolType) : - type; + return type.flags & TypeFlags.UniqueESSymbol ? esSymbolType + : type.flags & TypeFlags.Union ? mapType(type as UnionType, getWidenedUniqueESSymbolType) + : type; } function getWidenedLiteralLikeTypeForContextualType(type: Type, contextualType: Type | undefined) { @@ -23769,20 +30809,29 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return getRegularTypeOfLiteralType(type); } - function getWidenedLiteralLikeTypeForContextualReturnTypeIfNeeded(type: Type | undefined, contextualSignatureReturnType: Type | undefined, isAsync: boolean) { + function getWidenedLiteralLikeTypeForContextualReturnTypeIfNeeded( + type: Type | undefined, + contextualSignatureReturnType: Type | undefined, + isAsync: boolean, + ) { if (type && isUnitType(type)) { - const contextualType = !contextualSignatureReturnType ? undefined : - isAsync ? getPromisedTypeOfPromise(contextualSignatureReturnType) : - contextualSignatureReturnType; + const contextualType = !contextualSignatureReturnType ? undefined + : isAsync ? getPromisedTypeOfPromise(contextualSignatureReturnType) + : contextualSignatureReturnType; type = getWidenedLiteralLikeTypeForContextualType(type, contextualType); } return type; } - function getWidenedLiteralLikeTypeForContextualIterationTypeIfNeeded(type: Type | undefined, contextualSignatureReturnType: Type | undefined, kind: IterationTypeKind, isAsyncGenerator: boolean) { + function getWidenedLiteralLikeTypeForContextualIterationTypeIfNeeded( + type: Type | undefined, + contextualSignatureReturnType: Type | undefined, + kind: IterationTypeKind, + isAsyncGenerator: boolean, + ) { if (type && isUnitType(type)) { - const contextualType = !contextualSignatureReturnType ? undefined : - getIterationTypeOfGeneratorFunctionReturnType(kind, contextualSignatureReturnType, isAsyncGenerator); + const contextualType = !contextualSignatureReturnType ? undefined + : getIterationTypeOfGeneratorFunctionReturnType(kind, contextualSignatureReturnType, isAsyncGenerator); type = getWidenedLiteralLikeTypeForContextualType(type, contextualType); } return type; @@ -23793,7 +30842,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { * Prefer using isTupleLikeType() unless the use of `elementTypes`/`getTypeArguments` is required. */ function isTupleType(type: Type): type is TupleTypeReference { - return !!(getObjectFlags(type) & ObjectFlags.Reference && (type as TypeReference).target.objectFlags & ObjectFlags.Tuple); + return !!(getObjectFlags(type) & ObjectFlags.Reference + && (type as TypeReference).target.objectFlags & ObjectFlags.Tuple); } function isGenericTupleType(type: Type): type is TupleTypeReference { @@ -23827,23 +30877,35 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return restType && createArrayType(restType); } - function getElementTypeOfSliceOfTupleType(type: TupleTypeReference, index: number, endSkipCount = 0, writing = false, noReductions = false) { + function getElementTypeOfSliceOfTupleType( + type: TupleTypeReference, + index: number, + endSkipCount = 0, + writing = false, + noReductions = false, + ) { const length = getTypeReferenceArity(type) - endSkipCount; if (index < length) { const typeArguments = getTypeArguments(type); const elementTypes: Type[] = []; for (let i = index; i < length; i++) { const t = typeArguments[i]; - elementTypes.push(type.target.elementFlags[i] & ElementFlags.Variadic ? getIndexedAccessType(t, numberType) : t); + elementTypes.push( + type.target.elementFlags[i] & ElementFlags.Variadic ? getIndexedAccessType(t, numberType) : t, + ); } - return writing ? getIntersectionType(elementTypes) : getUnionType(elementTypes, noReductions ? UnionReduction.None : UnionReduction.Literal); + return writing ? getIntersectionType(elementTypes) + : getUnionType(elementTypes, noReductions ? UnionReduction.None : UnionReduction.Literal); } return undefined; } function isTupleTypeStructureMatching(t1: TupleTypeReference, t2: TupleTypeReference) { - return getTypeReferenceArity(t1) === getTypeReferenceArity(t2) && - every(t1.target.elementFlags, (f, i) => (f & ElementFlags.Variable) === (t2.target.elementFlags[i] & ElementFlags.Variable)); + return getTypeReferenceArity(t1) === getTypeReferenceArity(t2) + && every( + t1.target.elementFlags, + (f, i) => (f & ElementFlags.Variable) === (t2.target.elementFlags[i] & ElementFlags.Variable), + ); } function isZeroBigInt({ value }: BigIntLiteralType) { @@ -23859,16 +30921,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function getDefinitelyFalsyPartOfType(type: Type): Type { - return type.flags & TypeFlags.String ? emptyStringType : - type.flags & TypeFlags.Number ? zeroType : - type.flags & TypeFlags.BigInt ? zeroBigIntType : - type === regularFalseType || - type === falseType || - type.flags & (TypeFlags.Void | TypeFlags.Undefined | TypeFlags.Null | TypeFlags.AnyOrUnknown) || - type.flags & TypeFlags.StringLiteral && (type as StringLiteralType).value === "" || - type.flags & TypeFlags.NumberLiteral && (type as NumberLiteralType).value === 0 || - type.flags & TypeFlags.BigIntLiteral && isZeroBigInt(type as BigIntLiteralType) ? type : - neverType; + return type.flags & TypeFlags.String ? emptyStringType + : type.flags & TypeFlags.Number ? zeroType + : type.flags & TypeFlags.BigInt ? zeroBigIntType + : type === regularFalseType + || type === falseType + || type.flags & (TypeFlags.Void | TypeFlags.Undefined | TypeFlags.Null | TypeFlags.AnyOrUnknown) + || type.flags & TypeFlags.StringLiteral && (type as StringLiteralType).value === "" + || type.flags & TypeFlags.NumberLiteral && (type as NumberLiteralType).value === 0 + || type.flags & TypeFlags.BigIntLiteral && isZeroBigInt(type as BigIntLiteralType) ? type + : neverType; } /** @@ -23878,25 +30940,29 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { */ function getNullableType(type: Type, flags: TypeFlags): Type { const missing = (flags & ~type.flags) & (TypeFlags.Undefined | TypeFlags.Null); - return missing === 0 ? type : - missing === TypeFlags.Undefined ? getUnionType([type, undefinedType]) : - missing === TypeFlags.Null ? getUnionType([type, nullType]) : - getUnionType([type, undefinedType, nullType]); + return missing === 0 ? type + : missing === TypeFlags.Undefined ? getUnionType([type, undefinedType]) + : missing === TypeFlags.Null ? getUnionType([type, nullType]) + : getUnionType([type, undefinedType, nullType]); } function getOptionalType(type: Type, isProperty = false): Type { Debug.assert(strictNullChecks); const missingOrUndefined = isProperty ? undefinedOrMissingType : undefinedType; - return type === missingOrUndefined || type.flags & TypeFlags.Union && (type as UnionType).types[0] === missingOrUndefined ? type : getUnionType([type, missingOrUndefined]); + return type === missingOrUndefined + || type.flags & TypeFlags.Union && (type as UnionType).types[0] === missingOrUndefined ? type + : getUnionType([type, missingOrUndefined]); } function getGlobalNonNullableTypeInstantiation(type: Type) { if (!deferredGlobalNonNullableTypeAlias) { - deferredGlobalNonNullableTypeAlias = getGlobalSymbol("NonNullable" as __String, SymbolFlags.TypeAlias, /*diagnostic*/ undefined) || unknownSymbol; + deferredGlobalNonNullableTypeAlias = + getGlobalSymbol("NonNullable" as __String, SymbolFlags.TypeAlias, /*diagnostic*/ undefined) + || unknownSymbol; } - return deferredGlobalNonNullableTypeAlias !== unknownSymbol ? - getTypeAliasInstantiation(deferredGlobalNonNullableTypeAlias, [type]) : - getIntersectionType([type, emptyObjectType]); + return deferredGlobalNonNullableTypeAlias !== unknownSymbol + ? getTypeAliasInstantiation(deferredGlobalNonNullableTypeAlias, [type]) + : getIntersectionType([type, emptyObjectType]); } function getNonNullableType(type: Type): Type { @@ -23912,13 +30978,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function propagateOptionalTypeMarker(type: Type, node: OptionalChain, wasOptional: boolean) { - return wasOptional ? isOutermostOptionalChain(node) ? getOptionalType(type) : addOptionalTypeMarker(type) : type; + return wasOptional ? isOutermostOptionalChain(node) ? getOptionalType(type) : addOptionalTypeMarker(type) + : type; } function getOptionalExpressionType(exprType: Type, expression: Expression) { - return isExpressionOfOptionalChainRoot(expression) ? getNonNullableType(exprType) : - isOptionalChain(expression) ? removeOptionalTypeMarker(exprType) : - exprType; + return isExpressionOfOptionalChainRoot(expression) ? getNonNullableType(exprType) + : isOptionalChain(expression) ? removeOptionalTypeMarker(exprType) + : exprType; } function removeMissingType(type: Type, isOptional: boolean) { @@ -23930,7 +30997,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function removeMissingOrUndefinedType(type: Type): Type { - return exactOptionalPropertyTypes ? removeType(type, missingType) : getTypeWithFacts(type, TypeFacts.NEUndefined); + return exactOptionalPropertyTypes ? removeType(type, missingType) + : getTypeWithFacts(type, TypeFacts.NEUndefined); } /** @@ -23968,12 +31036,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { ? every((type as IntersectionType).types, isObjectTypeWithInferableIndex) : !!( type.symbol - && (type.symbol.flags & (SymbolFlags.ObjectLiteral | SymbolFlags.TypeLiteral | SymbolFlags.Enum | SymbolFlags.ValueModule)) !== 0 + && (type.symbol.flags + & (SymbolFlags.ObjectLiteral | SymbolFlags.TypeLiteral | SymbolFlags.Enum + | SymbolFlags.ValueModule)) !== 0 && !(type.symbol.flags & SymbolFlags.Class) && !typeHasCallOrConstructSignatures(type) ) || !!( objectFlags & ObjectFlags.ObjectRestType - ) || !!(objectFlags & ObjectFlags.ReverseMapped && isObjectTypeWithInferableIndex((type as ReverseMappedType).source)); + ) + || !!(objectFlags & ObjectFlags.ReverseMapped + && isObjectTypeWithInferableIndex((type as ReverseMappedType).source)); } function createSymbolWithType(source: Symbol, type: Type | undefined) { @@ -23997,7 +31069,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { for (const property of getPropertiesOfObjectType(type)) { const original = getTypeOfSymbol(property); const updated = f(original); - members.set(property.escapedName, updated === original ? property : createSymbolWithType(property, updated)); + members.set( + property.escapedName, + updated === original ? property : createSymbolWithType(property, updated), + ); } return members; } @@ -24018,14 +31093,24 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const resolved = type as ResolvedType; const members = transformTypeOfMembers(type, getRegularTypeOfObjectLiteral); - const regularNew = createAnonymousType(resolved.symbol, members, resolved.callSignatures, resolved.constructSignatures, resolved.indexInfos); + const regularNew = createAnonymousType( + resolved.symbol, + members, + resolved.callSignatures, + resolved.constructSignatures, + resolved.indexInfos, + ); regularNew.flags = resolved.flags; regularNew.objectFlags |= resolved.objectFlags & ~ObjectFlags.FreshLiteral; (type as FreshObjectLiteralType).regularType = regularNew; return regularNew; } - function createWideningContext(parent: WideningContext | undefined, propertyName: __String | undefined, siblings: Type[] | undefined): WideningContext { + function createWideningContext( + parent: WideningContext | undefined, + propertyName: __String | undefined, + siblings: Type[] | undefined, + ): WideningContext { return { parent, propertyName, siblings, resolvedProperties: undefined }; } @@ -24097,7 +31182,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } } - const result = createAnonymousType(type.symbol, members, emptyArray, emptyArray, sameMap(getIndexInfosOfType(type), info => createIndexInfo(info.keyType, getWidenedType(info.type), info.isReadonly))); + const result = createAnonymousType( + type.symbol, + members, + emptyArray, + emptyArray, + sameMap( + getIndexInfosOfType(type), + info => createIndexInfo(info.keyType, getWidenedType(info.type), info.isReadonly), + ), + ); result.objectFlags |= getObjectFlags(type) & (ObjectFlags.JSLiteral | ObjectFlags.NonInferrableType); // Retain js literal flag through widening return result; } @@ -24119,12 +31213,23 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { result = getWidenedTypeOfObjectLiteral(type, context); } else if (type.flags & TypeFlags.Union) { - const unionContext = context || createWideningContext(/*parent*/ undefined, /*propertyName*/ undefined, (type as UnionType).types); - const widenedTypes = sameMap((type as UnionType).types, t => t.flags & TypeFlags.Nullable ? t : getWidenedTypeWithContext(t, unionContext)); + const unionContext = context + || createWideningContext( + /*parent*/ undefined, + /*propertyName*/ undefined, + (type as UnionType).types, + ); + const widenedTypes = sameMap( + (type as UnionType).types, + t => t.flags & TypeFlags.Nullable ? t : getWidenedTypeWithContext(t, unionContext), + ); // Widening an empty object literal transitions from a highly restrictive type to // a highly inclusive one. For that reason we perform subtype reduction here if the // union includes empty object types (e.g. reducing {} | string to just {}). - result = getUnionType(widenedTypes, some(widenedTypes, isEmptyObjectType) ? UnionReduction.Subtype : UnionReduction.Literal); + result = getUnionType( + widenedTypes, + some(widenedTypes, isEmptyObjectType) ? UnionReduction.Subtype : UnionReduction.Literal, + ); } else if (type.flags & TypeFlags.Intersection) { result = getIntersectionType(sameMap((type as IntersectionType).types, getWidenedType)); @@ -24178,7 +31283,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const t = getTypeOfSymbol(p); if (getObjectFlags(t) & ObjectFlags.ContainsWideningType) { if (!reportWideningErrorsInType(t)) { - error(p.valueDeclaration, Diagnostics.Object_literal_s_property_0_implicitly_has_an_1_type, symbolToString(p), typeToString(getWidenedType(t))); + error( + p.valueDeclaration, + Diagnostics.Object_literal_s_property_0_implicitly_has_an_1_type, + symbolToString(p), + typeToString(getWidenedType(t)), + ); } errorReported = true; } @@ -24199,27 +31309,45 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { case SyntaxKind.BinaryExpression: case SyntaxKind.PropertyDeclaration: case SyntaxKind.PropertySignature: - diagnostic = noImplicitAny ? Diagnostics.Member_0_implicitly_has_an_1_type : Diagnostics.Member_0_implicitly_has_an_1_type_but_a_better_type_may_be_inferred_from_usage; + diagnostic = noImplicitAny ? Diagnostics.Member_0_implicitly_has_an_1_type + : Diagnostics.Member_0_implicitly_has_an_1_type_but_a_better_type_may_be_inferred_from_usage; break; case SyntaxKind.Parameter: const param = declaration as ParameterDeclaration; if (isIdentifier(param.name)) { const originalKeywordKind = identifierToKeywordKind(param.name); if ( - (isCallSignatureDeclaration(param.parent) || isMethodSignature(param.parent) || isFunctionTypeNode(param.parent)) && - param.parent.parameters.indexOf(param) > -1 && - (resolveName(param, param.name.escapedText, SymbolFlags.Type, /*nameNotFoundMessage*/ undefined, param.name.escapedText, /*isUse*/ true) || - originalKeywordKind && isTypeNodeKind(originalKeywordKind)) + (isCallSignatureDeclaration(param.parent) || isMethodSignature(param.parent) + || isFunctionTypeNode(param.parent)) + && param.parent.parameters.indexOf(param) > -1 + && (resolveName( + param, + param.name.escapedText, + SymbolFlags.Type, + /*nameNotFoundMessage*/ undefined, + param.name.escapedText, + /*isUse*/ true, + ) + || originalKeywordKind && isTypeNodeKind(originalKeywordKind)) ) { const newName = "arg" + param.parent.parameters.indexOf(param); const typeName = declarationNameToString(param.name) + (param.dotDotDotToken ? "[]" : ""); - errorOrSuggestion(noImplicitAny, declaration, Diagnostics.Parameter_has_a_name_but_no_type_Did_you_mean_0_Colon_1, newName, typeName); + errorOrSuggestion( + noImplicitAny, + declaration, + Diagnostics.Parameter_has_a_name_but_no_type_Did_you_mean_0_Colon_1, + newName, + typeName, + ); return; } } - diagnostic = (declaration as ParameterDeclaration).dotDotDotToken ? - noImplicitAny ? Diagnostics.Rest_parameter_0_implicitly_has_an_any_type : Diagnostics.Rest_parameter_0_implicitly_has_an_any_type_but_a_better_type_may_be_inferred_from_usage : - noImplicitAny ? Diagnostics.Parameter_0_implicitly_has_an_1_type : Diagnostics.Parameter_0_implicitly_has_an_1_type_but_a_better_type_may_be_inferred_from_usage; + diagnostic = (declaration as ParameterDeclaration).dotDotDotToken + ? noImplicitAny ? Diagnostics.Rest_parameter_0_implicitly_has_an_any_type + : Diagnostics + .Rest_parameter_0_implicitly_has_an_any_type_but_a_better_type_may_be_inferred_from_usage + : noImplicitAny ? Diagnostics.Parameter_0_implicitly_has_an_1_type + : Diagnostics.Parameter_0_implicitly_has_an_1_type_but_a_better_type_may_be_inferred_from_usage; break; case SyntaxKind.BindingElement: diagnostic = Diagnostics.Binding_element_0_implicitly_has_an_1_type; @@ -24229,11 +31357,20 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } break; case SyntaxKind.JSDocFunctionType: - error(declaration, Diagnostics.Function_type_which_lacks_return_type_annotation_implicitly_has_an_0_return_type, typeAsString); + error( + declaration, + Diagnostics.Function_type_which_lacks_return_type_annotation_implicitly_has_an_0_return_type, + typeAsString, + ); return; case SyntaxKind.JSDocSignature: if (noImplicitAny && isJSDocOverloadTag(declaration.parent)) { - error(declaration.parent.tagName, Diagnostics.This_overload_implicitly_returns_the_type_0_because_it_lacks_a_return_type_annotation, typeAsString); + error( + declaration.parent.tagName, + Diagnostics + .This_overload_implicitly_returns_the_type_0_because_it_lacks_a_return_type_annotation, + typeAsString, + ); } return; case SyntaxKind.FunctionDeclaration: @@ -24245,16 +31382,28 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { case SyntaxKind.ArrowFunction: if (noImplicitAny && !(declaration as NamedDeclaration).name) { if (wideningKind === WideningKind.GeneratorYield) { - error(declaration, Diagnostics.Generator_implicitly_has_yield_type_0_because_it_does_not_yield_any_values_Consider_supplying_a_return_type_annotation, typeAsString); + error( + declaration, + Diagnostics + .Generator_implicitly_has_yield_type_0_because_it_does_not_yield_any_values_Consider_supplying_a_return_type_annotation, + typeAsString, + ); } else { - error(declaration, Diagnostics.Function_expression_which_lacks_return_type_annotation_implicitly_has_an_0_return_type, typeAsString); + error( + declaration, + Diagnostics + .Function_expression_which_lacks_return_type_annotation_implicitly_has_an_0_return_type, + typeAsString, + ); } return; } - diagnostic = !noImplicitAny ? Diagnostics._0_implicitly_has_an_1_return_type_but_a_better_type_may_be_inferred_from_usage : - wideningKind === WideningKind.GeneratorYield ? Diagnostics._0_which_lacks_return_type_annotation_implicitly_has_an_1_yield_type : - Diagnostics._0_which_lacks_return_type_annotation_implicitly_has_an_1_return_type; + diagnostic = !noImplicitAny + ? Diagnostics._0_implicitly_has_an_1_return_type_but_a_better_type_may_be_inferred_from_usage + : wideningKind === WideningKind.GeneratorYield + ? Diagnostics._0_which_lacks_return_type_annotation_implicitly_has_an_1_yield_type + : Diagnostics._0_which_lacks_return_type_annotation_implicitly_has_an_1_return_type; break; case SyntaxKind.MappedType: if (noImplicitAny) { @@ -24262,14 +31411,25 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } return; default: - diagnostic = noImplicitAny ? Diagnostics.Variable_0_implicitly_has_an_1_type : Diagnostics.Variable_0_implicitly_has_an_1_type_but_a_better_type_may_be_inferred_from_usage; + diagnostic = noImplicitAny ? Diagnostics.Variable_0_implicitly_has_an_1_type + : Diagnostics.Variable_0_implicitly_has_an_1_type_but_a_better_type_may_be_inferred_from_usage; } - errorOrSuggestion(noImplicitAny, declaration, diagnostic, declarationNameToString(getNameOfDeclaration(declaration)), typeAsString); + errorOrSuggestion( + noImplicitAny, + declaration, + diagnostic, + declarationNameToString(getNameOfDeclaration(declaration)), + typeAsString, + ); } function reportErrorsFromWidening(declaration: Declaration, type: Type, wideningKind?: WideningKind) { addLazyDiagnostic(() => { - if (noImplicitAny && getObjectFlags(type) & ObjectFlags.ContainsWideningType && (!wideningKind || !getContextualSignatureForFunctionLikeDeclaration(declaration as FunctionLikeDeclaration))) { + if ( + noImplicitAny && getObjectFlags(type) & ObjectFlags.ContainsWideningType + && (!wideningKind + || !getContextualSignatureForFunctionLikeDeclaration(declaration as FunctionLikeDeclaration)) + ) { // Report implicit any error within type if possible, otherwise report error on declaration if (!reportWideningErrorsInType(type)) { reportImplicitAny(declaration, type, wideningKind); @@ -24303,7 +31463,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function applyToReturnTypes(source: Signature, target: Signature, callback: (s: Type, t: Type) => void) { const sourceTypePredicate = getTypePredicateOfSignature(source); const targetTypePredicate = getTypePredicateOfSignature(target); - if (sourceTypePredicate && targetTypePredicate && typePredicateKindsMatch(sourceTypePredicate, targetTypePredicate) && sourceTypePredicate.type && targetTypePredicate.type) { + if ( + sourceTypePredicate && targetTypePredicate + && typePredicateKindsMatch(sourceTypePredicate, targetTypePredicate) && sourceTypePredicate.type + && targetTypePredicate.type + ) { callback(sourceTypePredicate.type, targetTypePredicate.type); } else { @@ -24311,15 +31475,39 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } - function createInferenceContext(typeParameters: readonly TypeParameter[], signature: Signature | undefined, flags: InferenceFlags, compareTypes?: TypeComparer): InferenceContext { - return createInferenceContextWorker(typeParameters.map(createInferenceInfo), signature, flags, compareTypes || compareTypesAssignable); + function createInferenceContext( + typeParameters: readonly TypeParameter[], + signature: Signature | undefined, + flags: InferenceFlags, + compareTypes?: TypeComparer, + ): InferenceContext { + return createInferenceContextWorker( + typeParameters.map(createInferenceInfo), + signature, + flags, + compareTypes || compareTypesAssignable, + ); } - function cloneInferenceContext(context: T, extraFlags: InferenceFlags = 0): InferenceContext | T & undefined { - return context && createInferenceContextWorker(map(context.inferences, cloneInferenceInfo), context.signature, context.flags | extraFlags, context.compareTypes); + function cloneInferenceContext( + context: T, + extraFlags: InferenceFlags = 0, + ): InferenceContext | T & undefined { + return context + && createInferenceContextWorker( + map(context.inferences, cloneInferenceInfo), + context.signature, + context.flags | extraFlags, + context.compareTypes, + ); } - function createInferenceContextWorker(inferences: InferenceInfo[], signature: Signature | undefined, flags: InferenceFlags, compareTypes: TypeComparer): InferenceContext { + function createInferenceContextWorker( + inferences: InferenceInfo[], + signature: Signature | undefined, + flags: InferenceFlags, + compareTypes: TypeComparer, + ): InferenceContext { const context: InferenceContext = { inferences, signature, @@ -24366,7 +31554,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } - function addIntraExpressionInferenceSite(context: InferenceContext, node: Expression | MethodDeclaration, type: Type) { + function addIntraExpressionInferenceSite( + context: InferenceContext, + node: Expression | MethodDeclaration, + type: Type, + ) { (context.intraExpressionInferenceSites ??= []).push({ node, type }); } @@ -24386,9 +31578,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function inferFromIntraExpressionSites(context: InferenceContext) { if (context.intraExpressionInferenceSites) { for (const { node, type } of context.intraExpressionInferenceSites) { - const contextualType = node.kind === SyntaxKind.MethodDeclaration ? - getContextualTypeForObjectLiteralMethod(node as MethodDeclaration, ContextFlags.NoConstraints) : - getContextualType(node, ContextFlags.NoConstraints); + const contextualType = node.kind === SyntaxKind.MethodDeclaration + ? getContextualTypeForObjectLiteralMethod(node as MethodDeclaration, ContextFlags.NoConstraints) + : getContextualType(node, ContextFlags.NoConstraints); if (contextualType) { inferTypes(context.inferences, type, contextualType); } @@ -24425,9 +31617,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function cloneInferredPartOfContext(context: InferenceContext): InferenceContext | undefined { const inferences = filter(context.inferences, hasInferenceCandidates); - return inferences.length ? - createInferenceContextWorker(map(inferences, cloneInferenceInfo), context.signature, context.flags, context.compareTypes) : - undefined; + return inferences.length + ? createInferenceContextWorker( + map(inferences, cloneInferenceInfo), + context.signature, + context.flags, + context.compareTypes, + ) + : undefined; } function getMapperFromContext(context: T): TypeMapper | T & undefined { @@ -24442,15 +31639,26 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (objectFlags & ObjectFlags.CouldContainTypeVariablesComputed) { return !!(objectFlags & ObjectFlags.CouldContainTypeVariables); } - const result = !!(type.flags & TypeFlags.Instantiable || - type.flags & TypeFlags.Object && !isNonGenericTopLevelType(type) && ( - objectFlags & ObjectFlags.Reference && ((type as TypeReference).node || some(getTypeArguments(type as TypeReference), couldContainTypeVariables)) || - objectFlags & ObjectFlags.Anonymous && type.symbol && type.symbol.flags & (SymbolFlags.Function | SymbolFlags.Method | SymbolFlags.Class | SymbolFlags.TypeLiteral | SymbolFlags.ObjectLiteral) && type.symbol.declarations || - objectFlags & (ObjectFlags.Mapped | ObjectFlags.ReverseMapped | ObjectFlags.ObjectRestType | ObjectFlags.InstantiationExpressionType) - ) || - type.flags & (TypeFlags.UnionOrIntersection | TypeFlags.TemplateLiteral) && !(type.flags & TypeFlags.EnumLiteral) && !isNonGenericTopLevelType(type) && some((type as UnionOrIntersectionType | TemplateLiteralType).types, couldContainTypeVariables)); + const result = !!(type.flags & TypeFlags.Instantiable + || type.flags & TypeFlags.Object && !isNonGenericTopLevelType(type) && ( + objectFlags & ObjectFlags.Reference + && ((type as TypeReference).node + || some(getTypeArguments(type as TypeReference), couldContainTypeVariables)) + || objectFlags & ObjectFlags.Anonymous && type.symbol + && type.symbol.flags + & (SymbolFlags.Function | SymbolFlags.Method | SymbolFlags.Class | SymbolFlags.TypeLiteral + | SymbolFlags.ObjectLiteral) + && type.symbol.declarations + || objectFlags + & (ObjectFlags.Mapped | ObjectFlags.ReverseMapped | ObjectFlags.ObjectRestType + | ObjectFlags.InstantiationExpressionType) + ) + || type.flags & (TypeFlags.UnionOrIntersection | TypeFlags.TemplateLiteral) + && !(type.flags & TypeFlags.EnumLiteral) && !isNonGenericTopLevelType(type) + && some((type as UnionOrIntersectionType | TemplateLiteralType).types, couldContainTypeVariables)); if (type.flags & TypeFlags.ObjectFlagsType) { - (type as ObjectFlagsType).objectFlags |= ObjectFlags.CouldContainTypeVariablesComputed | (result ? ObjectFlags.CouldContainTypeVariables : 0); + (type as ObjectFlagsType).objectFlags |= ObjectFlags.CouldContainTypeVariablesComputed + | (result ? ObjectFlags.CouldContainTypeVariables : 0); } return result; } @@ -24458,24 +31666,34 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function isNonGenericTopLevelType(type: Type) { if (type.aliasSymbol && !type.aliasTypeArguments) { const declaration = getDeclarationOfKind(type.aliasSymbol, SyntaxKind.TypeAliasDeclaration); - return !!(declaration && findAncestor(declaration.parent, n => n.kind === SyntaxKind.SourceFile ? true : n.kind === SyntaxKind.ModuleDeclaration ? false : "quit")); + return !!(declaration + && findAncestor( + declaration.parent, + n => n.kind === SyntaxKind.SourceFile ? true + : n.kind === SyntaxKind.ModuleDeclaration ? false : "quit", + )); } return false; } function isTypeParameterAtTopLevel(type: Type, tp: TypeParameter, depth = 0): boolean { - return !!(type === tp || - type.flags & TypeFlags.UnionOrIntersection && some((type as UnionOrIntersectionType).types, t => isTypeParameterAtTopLevel(t, tp, depth)) || - depth < 3 && type.flags & TypeFlags.Conditional && ( - isTypeParameterAtTopLevel(getTrueTypeFromConditionalType(type as ConditionalType), tp, depth + 1) || - isTypeParameterAtTopLevel(getFalseTypeFromConditionalType(type as ConditionalType), tp, depth + 1) + return !!(type === tp + || type.flags & TypeFlags.UnionOrIntersection + && some((type as UnionOrIntersectionType).types, t => isTypeParameterAtTopLevel(t, tp, depth)) + || depth < 3 && type.flags & TypeFlags.Conditional && ( + isTypeParameterAtTopLevel(getTrueTypeFromConditionalType(type as ConditionalType), tp, depth + 1) + || isTypeParameterAtTopLevel( + getFalseTypeFromConditionalType(type as ConditionalType), + tp, + depth + 1, + ) )); } function isTypeParameterAtTopLevelInReturnType(signature: Signature, typeParameter: TypeParameter) { const typePredicate = getTypePredicateOfSignature(signature); - return typePredicate ? !!typePredicate.type && isTypeParameterAtTopLevel(typePredicate.type, typeParameter) : - isTypeParameterAtTopLevel(getReturnTypeOfSignature(signature), typeParameter); + return typePredicate ? !!typePredicate.type && isTypeParameterAtTopLevel(typePredicate.type, typeParameter) + : isTypeParameterAtTopLevel(getReturnTypeOfSignature(signature), typeParameter); } /** Create an object with properties named in the string literal type. Every property has type `any` */ @@ -24494,7 +31712,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } members.set(name, literalProp); }); - const indexInfos = type.flags & TypeFlags.String ? [createIndexInfo(stringType, emptyObjectType, /*isReadonly*/ false)] : emptyArray; + const indexInfos = type.flags & TypeFlags.String + ? [createIndexInfo(stringType, emptyObjectType, /*isReadonly*/ false)] : emptyArray; return createAnonymousType(/*symbol*/ undefined, members, emptyArray, emptyArray, indexInfos); } @@ -24504,7 +31723,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { * property is computed by inferring from the source property type to X for the type * variable T[P] (i.e. we treat the type T[P] as the type variable we're inferring for). */ - function inferTypeForHomomorphicMappedType(source: Type, target: MappedType, constraint: IndexType): Type | undefined { + function inferTypeForHomomorphicMappedType( + source: Type, + target: MappedType, + constraint: IndexType, + ): Type | undefined { const cacheKey = source.id + "," + target.id + "," + constraint.id; if (reverseMappedCache.has(cacheKey)) { return reverseMappedCache.get(cacheKey); @@ -24525,32 +31748,47 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // literal { a: 123, b: x => true } is marked non-inferable because it contains a context sensitive // arrow function, but is considered partially inferable because property 'a' has an inferable type. function isPartiallyInferableType(type: Type): boolean { - return !(getObjectFlags(type) & ObjectFlags.NonInferrableType) || - isObjectLiteralType(type) && some(getPropertiesOfType(type), prop => isPartiallyInferableType(getTypeOfSymbol(prop))) || - isTupleType(type) && some(getElementTypes(type), isPartiallyInferableType); + return !(getObjectFlags(type) & ObjectFlags.NonInferrableType) + || isObjectLiteralType(type) + && some(getPropertiesOfType(type), prop => isPartiallyInferableType(getTypeOfSymbol(prop))) + || isTupleType(type) && some(getElementTypes(type), isPartiallyInferableType); } function createReverseMappedType(source: Type, target: MappedType, constraint: IndexType) { // We consider a source type reverse mappable if it has a string index signature or if // it has one or more properties and is of a partially inferable type. - if (!(getIndexInfoOfType(source, stringType) || getPropertiesOfType(source).length !== 0 && isPartiallyInferableType(source))) { + if ( + !(getIndexInfoOfType(source, stringType) + || getPropertiesOfType(source).length !== 0 && isPartiallyInferableType(source)) + ) { return undefined; } // For arrays and tuples we infer new arrays and tuples where the reverse mapping has been // applied to the element type(s). if (isArrayType(source)) { - return createArrayType(inferReverseMappedType(getTypeArguments(source)[0], target, constraint), isReadonlyArrayType(source)); + return createArrayType( + inferReverseMappedType(getTypeArguments(source)[0], target, constraint), + isReadonlyArrayType(source), + ); } if (isTupleType(source)) { const elementTypes = map(getElementTypes(source), t => inferReverseMappedType(t, target, constraint)); - const elementFlags = getMappedTypeModifiers(target) & MappedTypeModifiers.IncludeOptional ? - sameMap(source.target.elementFlags, f => f & ElementFlags.Optional ? ElementFlags.Required : f) : - source.target.elementFlags; - return createTupleType(elementTypes, elementFlags, source.target.readonly, source.target.labeledElementDeclarations); + const elementFlags = getMappedTypeModifiers(target) & MappedTypeModifiers.IncludeOptional + ? sameMap(source.target.elementFlags, f => f & ElementFlags.Optional ? ElementFlags.Required : f) + : source.target.elementFlags; + return createTupleType( + elementTypes, + elementFlags, + source.target.readonly, + source.target.labeledElementDeclarations, + ); } // For all other object types we infer a new object type where the reverse mapping has been // applied to the type of each property. - const reversed = createObjectType(ObjectFlags.ReverseMapped | ObjectFlags.Anonymous, /*symbol*/ undefined) as ReverseMappedType; + const reversed = createObjectType( + ObjectFlags.ReverseMapped | ObjectFlags.Anonymous, + /*symbol*/ undefined, + ) as ReverseMappedType; reversed.source = source; reversed.mappedType = target; reversed.constraintType = constraint; @@ -24560,27 +31798,42 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function getTypeOfReverseMappedSymbol(symbol: ReverseMappedSymbol) { const links = getSymbolLinks(symbol); if (!links.type) { - links.type = inferReverseMappedType(symbol.links.propertyType, symbol.links.mappedType, symbol.links.constraintType); + links.type = inferReverseMappedType( + symbol.links.propertyType, + symbol.links.mappedType, + symbol.links.constraintType, + ); } return links.type; } function inferReverseMappedType(sourceType: Type, target: MappedType, constraint: IndexType): Type { - const typeParameter = getIndexedAccessType(constraint.type, getTypeParameterFromMappedType(target)) as TypeParameter; + const typeParameter = getIndexedAccessType( + constraint.type, + getTypeParameterFromMappedType(target), + ) as TypeParameter; const templateType = getTemplateTypeFromMappedType(target); const inference = createInferenceInfo(typeParameter); inferTypes([inference], sourceType, templateType); return getTypeFromInference(inference) || unknownType; } - function* getUnmatchedProperties(source: Type, target: Type, requireOptionalProperties: boolean, matchDiscriminantProperties: boolean): IterableIterator { + function* getUnmatchedProperties( + source: Type, + target: Type, + requireOptionalProperties: boolean, + matchDiscriminantProperties: boolean, + ): IterableIterator { const properties = getPropertiesOfType(target); for (const targetProp of properties) { // TODO: remove this when we support static private identifier fields and find other solutions to get privateNamesAndStaticFields test to pass if (isStaticPrivateIdentifierProperty(targetProp)) { continue; } - if (requireOptionalProperties || !(targetProp.flags & SymbolFlags.Optional || getCheckFlags(targetProp) & CheckFlags.Partial)) { + if ( + requireOptionalProperties + || !(targetProp.flags & SymbolFlags.Optional || getCheckFlags(targetProp) & CheckFlags.Partial) + ) { const sourceProp = getPropertyOfType(source, targetProp.escapedName); if (!sourceProp) { yield targetProp; @@ -24589,7 +31842,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const targetType = getTypeOfSymbol(targetProp); if (targetType.flags & TypeFlags.Unit) { const sourceType = getTypeOfSymbol(sourceProp); - if (!(sourceType.flags & TypeFlags.Any || getRegularTypeOfLiteralType(sourceType) === getRegularTypeOfLiteralType(targetType))) { + if ( + !(sourceType.flags & TypeFlags.Any + || getRegularTypeOfLiteralType(sourceType) === getRegularTypeOfLiteralType(targetType)) + ) { yield targetProp; } } @@ -24598,27 +31854,46 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } - function getUnmatchedProperty(source: Type, target: Type, requireOptionalProperties: boolean, matchDiscriminantProperties: boolean): Symbol | undefined { - return firstOrUndefinedIterator(getUnmatchedProperties(source, target, requireOptionalProperties, matchDiscriminantProperties)); + function getUnmatchedProperty( + source: Type, + target: Type, + requireOptionalProperties: boolean, + matchDiscriminantProperties: boolean, + ): Symbol | undefined { + return firstOrUndefinedIterator( + getUnmatchedProperties(source, target, requireOptionalProperties, matchDiscriminantProperties), + ); } function tupleTypesDefinitelyUnrelated(source: TupleTypeReference, target: TupleTypeReference) { - return !(target.target.combinedFlags & ElementFlags.Variadic) && target.target.minLength > source.target.minLength || - !target.target.hasRestElement && (source.target.hasRestElement || target.target.fixedLength < source.target.fixedLength); + return !(target.target.combinedFlags & ElementFlags.Variadic) + && target.target.minLength > source.target.minLength + || !target.target.hasRestElement + && (source.target.hasRestElement || target.target.fixedLength < source.target.fixedLength); } function typesDefinitelyUnrelated(source: Type, target: Type) { // Two tuple types with incompatible arities are definitely unrelated. // Two object types that each have a property that is unmatched in the other are definitely unrelated. - return isTupleType(source) && isTupleType(target) ? tupleTypesDefinitelyUnrelated(source, target) : - !!getUnmatchedProperty(source, target, /*requireOptionalProperties*/ false, /*matchDiscriminantProperties*/ true) && - !!getUnmatchedProperty(target, source, /*requireOptionalProperties*/ false, /*matchDiscriminantProperties*/ false); + return isTupleType(source) && isTupleType(target) ? tupleTypesDefinitelyUnrelated(source, target) + : !!getUnmatchedProperty( + source, + target, + /*requireOptionalProperties*/ false, + /*matchDiscriminantProperties*/ true, + ) + && !!getUnmatchedProperty( + target, + source, + /*requireOptionalProperties*/ false, + /*matchDiscriminantProperties*/ false, + ); } function getTypeFromInference(inference: InferenceInfo) { - return inference.candidates ? getUnionType(inference.candidates, UnionReduction.Subtype) : - inference.contraCandidates ? getIntersectionType(inference.contraCandidates) : - undefined; + return inference.candidates ? getUnionType(inference.candidates, UnionReduction.Subtype) + : inference.contraCandidates ? getIntersectionType(inference.contraCandidates) + : undefined; } function hasSkipDirectInferenceFlag(node: Node) { @@ -24637,8 +31912,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const targetEnd = target.texts[target.texts.length - 1]; const startLen = Math.min(sourceStart.length, targetStart.length); const endLen = Math.min(sourceEnd.length, targetEnd.length); - return sourceStart.slice(0, startLen) !== targetStart.slice(0, startLen) || - sourceEnd.slice(sourceEnd.length - endLen) !== targetEnd.slice(targetEnd.length - endLen); + return sourceStart.slice(0, startLen) !== targetStart.slice(0, startLen) + || sourceEnd.slice(sourceEnd.length - endLen) !== targetEnd.slice(targetEnd.length - endLen); } /** @@ -24690,34 +31965,48 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return true; } if (target.flags & TypeFlags.Intersection) { - return every((target as IntersectionType).types, t => t === emptyTypeLiteralType || isValidTypeForTemplateLiteralPlaceholder(source, t)); + return every( + (target as IntersectionType).types, + t => t === emptyTypeLiteralType || isValidTypeForTemplateLiteralPlaceholder(source, t), + ); } if (source.flags & TypeFlags.StringLiteral) { const value = (source as StringLiteralType).value; - return !!(target.flags & TypeFlags.Number && isValidNumberString(value, /*roundTripOnly*/ false) || - target.flags & TypeFlags.BigInt && isValidBigIntString(value, /*roundTripOnly*/ false) || - target.flags & (TypeFlags.BooleanLiteral | TypeFlags.Nullable) && value === (target as IntrinsicType).intrinsicName || - target.flags & TypeFlags.StringMapping && isMemberOfStringMapping(getStringLiteralType(value), target) || - target.flags & TypeFlags.TemplateLiteral && isTypeMatchedByTemplateLiteralType(source, target as TemplateLiteralType)); + return !!(target.flags & TypeFlags.Number && isValidNumberString(value, /*roundTripOnly*/ false) + || target.flags & TypeFlags.BigInt && isValidBigIntString(value, /*roundTripOnly*/ false) + || target.flags & (TypeFlags.BooleanLiteral | TypeFlags.Nullable) + && value === (target as IntrinsicType).intrinsicName + || target.flags & TypeFlags.StringMapping + && isMemberOfStringMapping(getStringLiteralType(value), target) + || target.flags & TypeFlags.TemplateLiteral + && isTypeMatchedByTemplateLiteralType(source, target as TemplateLiteralType)); } if (source.flags & TypeFlags.TemplateLiteral) { const texts = (source as TemplateLiteralType).texts; - return texts.length === 2 && texts[0] === "" && texts[1] === "" && isTypeAssignableTo((source as TemplateLiteralType).types[0], target); + return texts.length === 2 && texts[0] === "" && texts[1] === "" + && isTypeAssignableTo((source as TemplateLiteralType).types[0], target); } return isTypeAssignableTo(source, target); } function inferTypesFromTemplateLiteralType(source: Type, target: TemplateLiteralType): Type[] | undefined { - return source.flags & TypeFlags.StringLiteral ? inferFromLiteralPartsToTemplateLiteral([(source as StringLiteralType).value], emptyArray, target) : - source.flags & TypeFlags.TemplateLiteral ? - arraysEqual((source as TemplateLiteralType).texts, target.texts) ? map((source as TemplateLiteralType).types, getStringLikeTypeForType) : - inferFromLiteralPartsToTemplateLiteral((source as TemplateLiteralType).texts, (source as TemplateLiteralType).types, target) : - undefined; + return source.flags & TypeFlags.StringLiteral + ? inferFromLiteralPartsToTemplateLiteral([(source as StringLiteralType).value], emptyArray, target) + : source.flags & TypeFlags.TemplateLiteral + ? arraysEqual((source as TemplateLiteralType).texts, target.texts) + ? map((source as TemplateLiteralType).types, getStringLikeTypeForType) + : inferFromLiteralPartsToTemplateLiteral( + (source as TemplateLiteralType).texts, + (source as TemplateLiteralType).types, + target, + ) + : undefined; } function isTypeMatchedByTemplateLiteralType(source: Type, target: TemplateLiteralType): boolean { const inferences = inferTypesFromTemplateLiteralType(source, target); - return !!inferences && every(inferences, (r, i) => isValidTypeForTemplateLiteralPlaceholder(r, target.types[i])); + return !!inferences + && every(inferences, (r, i) => isValidTypeForTemplateLiteralPlaceholder(r, target.types[i])); } function getStringLikeTypeForType(type: Type) { @@ -24743,7 +32032,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // the source. The first match for the '.' in target occurs at character 1 in the source text part at index 1, and thus // the first inference is the template literal type `<${string}>`. The remainder of the source makes up the second // inference, the template literal type `<${number}-${number}>`. - function inferFromLiteralPartsToTemplateLiteral(sourceTexts: readonly string[], sourceTypes: readonly Type[], target: TemplateLiteralType): Type[] | undefined { + function inferFromLiteralPartsToTemplateLiteral( + sourceTexts: readonly string[], + sourceTypes: readonly Type[], + target: TemplateLiteralType, + ): Type[] | undefined { const lastSourceIndex = sourceTexts.length - 1; const sourceStartText = sourceTexts[0]; const sourceEndText = sourceTexts[lastSourceIndex]; @@ -24752,8 +32045,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const targetStartText = targetTexts[0]; const targetEndText = targetTexts[lastTargetIndex]; if ( - lastSourceIndex === 0 && sourceStartText.length < targetStartText.length + targetEndText.length || - !sourceStartText.startsWith(targetStartText) || !sourceEndText.endsWith(targetEndText) + lastSourceIndex === 0 && sourceStartText.length < targetStartText.length + targetEndText.length + || !sourceStartText.startsWith(targetStartText) || !sourceEndText.endsWith(targetEndText) ) return undefined; const remainingEndText = sourceEndText.slice(0, sourceEndText.length - targetEndText.length); const matches: Type[] = []; @@ -24790,9 +32083,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return index < lastSourceIndex ? sourceTexts[index] : remainingEndText; } function addMatch(s: number, p: number) { - const matchType = s === seg ? - getStringLiteralType(getSourceText(s).slice(pos, p)) : - getTemplateLiteralType( + const matchType = s === seg + ? getStringLiteralType(getSourceText(s).slice(pos, p)) + : getTemplateLiteralType( [sourceTexts[seg].slice(pos), ...sourceTexts.slice(seg + 1, s), getSourceText(s).slice(0, p)], sourceTypes.slice(seg, s), ); @@ -24802,7 +32095,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } - function inferTypes(inferences: InferenceInfo[], originalSource: Type, originalTarget: Type, priority = InferencePriority.None, contravariant = false) { + function inferTypes( + inferences: InferenceInfo[], + originalSource: Type, + originalTarget: Type, + priority = InferencePriority.None, + contravariant = false, + ) { let bivariant = false; let propagationType: Type; let inferencePriority: number = InferencePriority.MaxValue; @@ -24833,8 +32132,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // Simply infer from source type arguments to target type arguments, with defaults applied. const params = getSymbolLinks(source.aliasSymbol).typeParameters!; const minParams = getMinTypeArgumentCount(params); - const sourceTypes = fillMissingTypeArguments(source.aliasTypeArguments, params, minParams, isInJSFile(source.aliasSymbol.valueDeclaration)); - const targetTypes = fillMissingTypeArguments(target.aliasTypeArguments, params, minParams, isInJSFile(source.aliasSymbol.valueDeclaration)); + const sourceTypes = fillMissingTypeArguments( + source.aliasTypeArguments, + params, + minParams, + isInJSFile(source.aliasSymbol.valueDeclaration), + ); + const targetTypes = fillMissingTypeArguments( + target.aliasTypeArguments, + params, + minParams, + isInJSFile(source.aliasSymbol.valueDeclaration), + ); inferFromTypeArguments(sourceTypes, targetTypes!, getAliasVariances(source.aliasSymbol)); } // And if there weren't any type arguments, there's no reason to run inference as the types must be the same. @@ -24851,7 +32160,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (target.flags & TypeFlags.Union) { // First, infer between identically matching source and target constituents and remove the // matching types. - const [tempSources, tempTargets] = inferFromMatchingTypes(source.flags & TypeFlags.Union ? (source as UnionType).types : [source], (target as UnionType).types, isTypeOrBaseIdenticalTo); + const [tempSources, tempTargets] = inferFromMatchingTypes( + source.flags & TypeFlags.Union ? (source as UnionType).types : [source], + (target as UnionType).types, + isTypeOrBaseIdenticalTo, + ); // Next, infer between closely matching source and target constituents and remove // the matching types. Types closely match when they are instantiations of the same // object type or instantiations of the same type alias. @@ -24871,14 +32184,21 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } source = getUnionType(sources); } - else if (target.flags & TypeFlags.Intersection && !every((target as IntersectionType).types, isNonGenericObjectType)) { + else if ( + target.flags & TypeFlags.Intersection + && !every((target as IntersectionType).types, isNonGenericObjectType) + ) { // We reduce intersection types unless they're simple combinations of object types. For example, // when inferring from 'string[] & { extra: any }' to 'string[] & T' we want to remove string[] and // infer { extra: any } for T. But when inferring to 'string[] & Iterable' we want to keep the // string[] on the source side and infer string for T. if (!(source.flags & TypeFlags.Union)) { // Infer between identically matching source and target constituents and remove the matching types. - const [sources, targets] = inferFromMatchingTypes(source.flags & TypeFlags.Intersection ? (source as IntersectionType).types : [source], (target as IntersectionType).types, isTypeIdenticalTo); + const [sources, targets] = inferFromMatchingTypes( + source.flags & TypeFlags.Intersection ? (source as IntersectionType).types : [source], + (target as IntersectionType).types, + isTypeIdenticalTo, + ); if (sources.length === 0 || targets.length === 0) { return; } @@ -24938,7 +32258,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { clearCachedInferences(inferences); } } - if (!(priority & InferencePriority.ReturnType) && target.flags & TypeFlags.TypeParameter && inference.topLevel && !isTypeParameterAtTopLevel(originalTarget, target as TypeParameter)) { + if ( + !(priority & InferencePriority.ReturnType) && target.flags & TypeFlags.TypeParameter + && inference.topLevel && !isTypeParameterAtTopLevel(originalTarget, target as TypeParameter) + ) { inference.topLevel = false; clearCachedInferences(inferences); } @@ -24956,7 +32279,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // Generally simplifications of instantiable indexes are avoided to keep relationship checking correct, however if our target is an access, we can consider // that key of that access to be "instantiated", since we're looking to find the infernce goal in any way we can. if (indexType.flags & TypeFlags.Instantiable) { - const simplified = distributeIndexOverObjectType(getSimplifiedType((target as IndexedAccessType).objectType, /*writing*/ false), indexType, /*writing*/ false); + const simplified = distributeIndexOverObjectType( + getSimplifiedType((target as IndexedAccessType).objectType, /*writing*/ false), + indexType, + /*writing*/ false, + ); if (simplified && simplified !== target) { inferFromTypes(source, simplified); } @@ -24965,19 +32292,28 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } if ( getObjectFlags(source) & ObjectFlags.Reference && getObjectFlags(target) & ObjectFlags.Reference && ( - (source as TypeReference).target === (target as TypeReference).target || isArrayType(source) && isArrayType(target) - ) && - !((source as TypeReference).node && (target as TypeReference).node) + (source as TypeReference).target === (target as TypeReference).target + || isArrayType(source) && isArrayType(target) + ) + && !((source as TypeReference).node && (target as TypeReference).node) ) { // If source and target are references to the same generic type, infer from type arguments - inferFromTypeArguments(getTypeArguments(source as TypeReference), getTypeArguments(target as TypeReference), getVariances((source as TypeReference).target)); + inferFromTypeArguments( + getTypeArguments(source as TypeReference), + getTypeArguments(target as TypeReference), + getVariances((source as TypeReference).target), + ); } else if (source.flags & TypeFlags.Index && target.flags & TypeFlags.Index) { inferFromContravariantTypes((source as IndexType).type, (target as IndexType).type); } else if ((isLiteralType(source) || source.flags & TypeFlags.String) && target.flags & TypeFlags.Index) { const empty = createEmptyObjectTypeFromStringLiteral(source); - inferFromContravariantTypesWithPriority(empty, (target as IndexType).type, InferencePriority.LiteralKeyof); + inferFromContravariantTypesWithPriority( + empty, + (target as IndexType).type, + InferencePriority.LiteralKeyof, + ); } else if (source.flags & TypeFlags.IndexedAccess && target.flags & TypeFlags.IndexedAccess) { inferFromTypes((source as IndexedAccessType).objectType, (target as IndexedAccessType).objectType); @@ -24990,7 +32326,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } else if (source.flags & TypeFlags.Substitution) { inferFromTypes((source as SubstitutionType).baseType, target); - inferWithPriority(getSubstitutionIntersection(source as SubstitutionType), target, InferencePriority.SubstituteSource); // Make substitute inference at a lower priority + inferWithPriority( + getSubstitutionIntersection(source as SubstitutionType), + target, + InferencePriority.SubstituteSource, + ); // Make substitute inference at a lower priority } else if (target.flags & TypeFlags.Conditional) { invokeOnce(source, target as ConditionalType, inferToConditionalType); @@ -25010,12 +32350,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } else { source = getReducedType(source); - if (!(priority & InferencePriority.NoConstraints && source.flags & (TypeFlags.Intersection | TypeFlags.Instantiable))) { + if ( + !(priority & InferencePriority.NoConstraints + && source.flags & (TypeFlags.Intersection | TypeFlags.Instantiable)) + ) { const apparentSource = getApparentType(source); // getApparentType can return _any_ type, since an indexed access or conditional may simplify to any other type. // If that occurs and it doesn't simplify to an object or intersection, we'll need to restart `inferFromTypes` // with the simplified source. - if (apparentSource !== source && allowComplexConstraintInference && !(apparentSource.flags & (TypeFlags.Object | TypeFlags.Intersection))) { + if ( + apparentSource !== source && allowComplexConstraintInference + && !(apparentSource.flags & (TypeFlags.Object | TypeFlags.Intersection)) + ) { // TODO: The `allowComplexConstraintInference` flag is a hack! This forbids inference from complex constraints within constraints! // This isn't required algorithmically, but rather is used to lower the memory burden caused by performing inference // that is _too good_ in projects with complicated constraints (eg, fp-ts). In such cases, if we did not limit ourselves @@ -25048,14 +32394,23 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { priority = savePriority; } - function inferToMultipleTypesWithPriority(source: Type, targets: Type[], targetFlags: TypeFlags, newPriority: InferencePriority) { + function inferToMultipleTypesWithPriority( + source: Type, + targets: Type[], + targetFlags: TypeFlags, + newPriority: InferencePriority, + ) { const savePriority = priority; priority |= newPriority; inferToMultipleTypes(source, targets, targetFlags); priority = savePriority; } - function invokeOnce(source: Source, target: Target, action: (source: Source, target: Target) => void) { + function invokeOnce( + source: Source, + target: Target, + action: (source: Source, target: Target) => void, + ) { const key = source.id + "," + target.id; const status = visited && visited.get(key); if (status !== undefined) { @@ -25085,7 +32440,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { inferencePriority = Math.min(inferencePriority, saveInferencePriority); } - function inferFromMatchingTypes(sources: Type[], targets: Type[], matches: (s: Type, t: Type) => boolean): [Type[], Type[]] { + function inferFromMatchingTypes( + sources: Type[], + targets: Type[], + matches: (s: Type, t: Type) => boolean, + ): [Type[], Type[]] { let matchedSources: Type[] | undefined; let matchedTargets: Type[] | undefined; for (const t of targets) { @@ -25103,10 +32462,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { ]; } - function inferFromTypeArguments(sourceTypes: readonly Type[], targetTypes: readonly Type[], variances: readonly VarianceFlags[]) { + function inferFromTypeArguments( + sourceTypes: readonly Type[], + targetTypes: readonly Type[], + variances: readonly VarianceFlags[], + ) { const count = sourceTypes.length < targetTypes.length ? sourceTypes.length : targetTypes.length; for (let i = 0; i < count; i++) { - if (i < variances.length && (variances[i] & VarianceFlags.VarianceMask) === VarianceFlags.Contravariant) { + if ( + i < variances.length && (variances[i] & VarianceFlags.VarianceMask) === VarianceFlags.Contravariant + ) { inferFromContravariantTypes(sourceTypes[i], targetTypes[i]); } else { @@ -25144,7 +32509,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function getSingleTypeVariableFromIntersectionTypes(types: Type[]) { let typeVariable: Type | undefined; for (const type of types) { - const t = type.flags & TypeFlags.Intersection && find((type as IntersectionType).types, t => !!getInferenceInfoForType(t)); + const t = type.flags & TypeFlags.Intersection + && find((type as IntersectionType).types, t => !!getInferenceInfoForType(t)); if (!t || typeVariable && t !== typeVariable) { return undefined; } @@ -25175,7 +32541,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { inferencePriority = InferencePriority.MaxValue; inferFromTypes(sources[i], t); if (inferencePriority === priority) matched[i] = true; - inferenceCircularity = inferenceCircularity || inferencePriority === InferencePriority.Circularity; + inferenceCircularity = inferenceCircularity + || inferencePriority === InferencePriority.Circularity; inferencePriority = Math.min(inferencePriority, saveInferencePriority); } } @@ -25251,9 +32618,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { inferWithPriority( inferredType, inference.typeParameter, - getObjectFlags(source) & ObjectFlags.NonInferrableType ? - InferencePriority.PartialHomomorphicMappedType : - InferencePriority.HomomorphicMappedType, + getObjectFlags(source) & ObjectFlags.NonInferrableType + ? InferencePriority.PartialHomomorphicMappedType + : InferencePriority.HomomorphicMappedType, ); } } @@ -25262,7 +32629,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (constraintType.flags & TypeFlags.TypeParameter) { // We're inferring from some source type S to a mapped type { [P in K]: X }, where K is a type // parameter. First infer from 'keyof S' to K. - inferWithPriority(getIndexType(source, /*indexFlags*/ !!source.pattern ? IndexFlags.NoIndexSignatures : IndexFlags.None), constraintType, InferencePriority.MappedTypeConstraint); + inferWithPriority( + getIndexType( + source, + /*indexFlags*/ !!source.pattern ? IndexFlags.NoIndexSignatures : IndexFlags.None, + ), + constraintType, + InferencePriority.MappedTypeConstraint, + ); // If K is constrained to a type C, also infer to C. Thus, for a mapped type { [P in K]: X }, // where K extends keyof T, we make the same inferences as for a homomorphic mapped type // { [P in keyof T]: X }. This enables us to make meaningful inferences when the target is a @@ -25274,7 +32648,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // If no inferences can be made to K's constraint, infer from a union of the property types // in the source to the template type X. const propTypes = map(getPropertiesOfType(source), getTypeOfSymbol); - const indexTypes = map(getIndexInfosOfType(source), info => info !== enumNumberIndexInfo ? info.type : neverType); + const indexTypes = map( + getIndexInfosOfType(source), + info => info !== enumNumberIndexInfo ? info.type : neverType, + ); inferFromTypes(getUnionType(concatenate(propTypes, indexTypes)), getTemplateTypeFromMappedType(target)); return true; } @@ -25285,12 +32662,23 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (source.flags & TypeFlags.Conditional) { inferFromTypes((source as ConditionalType).checkType, target.checkType); inferFromTypes((source as ConditionalType).extendsType, target.extendsType); - inferFromTypes(getTrueTypeFromConditionalType(source as ConditionalType), getTrueTypeFromConditionalType(target)); - inferFromTypes(getFalseTypeFromConditionalType(source as ConditionalType), getFalseTypeFromConditionalType(target)); + inferFromTypes( + getTrueTypeFromConditionalType(source as ConditionalType), + getTrueTypeFromConditionalType(target), + ); + inferFromTypes( + getFalseTypeFromConditionalType(source as ConditionalType), + getFalseTypeFromConditionalType(target), + ); } else { const targetTypes = [getTrueTypeFromConditionalType(target), getFalseTypeFromConditionalType(target)]; - inferToMultipleTypesWithPriority(source, targetTypes, target.flags, contravariant ? InferencePriority.ContravariantConditional : 0); + inferToMultipleTypesWithPriority( + source, + targetTypes, + target.flags, + contravariant ? InferencePriority.ContravariantConditional : 0, + ); } } @@ -25312,42 +32700,84 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // allowed template literal placeholder types, infer from a literal type corresponding to the constraint. if (source.flags & TypeFlags.StringLiteral && target.flags & TypeFlags.TypeVariable) { const inferenceContext = getInferenceInfoForType(target); - const constraint = inferenceContext ? getBaseConstraintOfType(inferenceContext.typeParameter) : undefined; + const constraint = inferenceContext ? getBaseConstraintOfType(inferenceContext.typeParameter) + : undefined; if (constraint && !isTypeAny(constraint)) { - const constraintTypes = constraint.flags & TypeFlags.Union ? (constraint as UnionType).types : [constraint]; - let allTypeFlags: TypeFlags = reduceLeft(constraintTypes, (flags, t) => flags | t.flags, 0 as TypeFlags); + const constraintTypes = constraint.flags & TypeFlags.Union ? (constraint as UnionType).types + : [constraint]; + let allTypeFlags: TypeFlags = reduceLeft( + constraintTypes, + (flags, t) => flags | t.flags, + 0 as TypeFlags, + ); // If the constraint contains `string`, we don't need to look for a more preferred type if (!(allTypeFlags & TypeFlags.String)) { const str = (source as StringLiteralType).value; // If the type contains `number` or a number literal and the string isn't a valid number, exclude numbers - if (allTypeFlags & TypeFlags.NumberLike && !isValidNumberString(str, /*roundTripOnly*/ true)) { + if ( + allTypeFlags & TypeFlags.NumberLike + && !isValidNumberString(str, /*roundTripOnly*/ true) + ) { allTypeFlags &= ~TypeFlags.NumberLike; } // If the type contains `bigint` or a bigint literal and the string isn't a valid bigint, exclude bigints - if (allTypeFlags & TypeFlags.BigIntLike && !isValidBigIntString(str, /*roundTripOnly*/ true)) { + if ( + allTypeFlags & TypeFlags.BigIntLike + && !isValidBigIntString(str, /*roundTripOnly*/ true) + ) { allTypeFlags &= ~TypeFlags.BigIntLike; } // for each type in the constraint, find the highest priority matching type - const matchingType = reduceLeft(constraintTypes, (left, right) => - !(right.flags & allTypeFlags) ? left : - left.flags & TypeFlags.String ? left : right.flags & TypeFlags.String ? source : - left.flags & TypeFlags.TemplateLiteral ? left : right.flags & TypeFlags.TemplateLiteral && isTypeMatchedByTemplateLiteralType(source, right as TemplateLiteralType) ? source : - left.flags & TypeFlags.StringMapping ? left : right.flags & TypeFlags.StringMapping && str === applyStringMapping(right.symbol, str) ? source : - left.flags & TypeFlags.StringLiteral ? left : right.flags & TypeFlags.StringLiteral && (right as StringLiteralType).value === str ? right : - left.flags & TypeFlags.Number ? left : right.flags & TypeFlags.Number ? getNumberLiteralType(+str) : - left.flags & TypeFlags.Enum ? left : right.flags & TypeFlags.Enum ? getNumberLiteralType(+str) : - left.flags & TypeFlags.NumberLiteral ? left : right.flags & TypeFlags.NumberLiteral && (right as NumberLiteralType).value === +str ? right : - left.flags & TypeFlags.BigInt ? left : right.flags & TypeFlags.BigInt ? parseBigIntLiteralType(str) : - left.flags & TypeFlags.BigIntLiteral ? left : right.flags & TypeFlags.BigIntLiteral && pseudoBigIntToString((right as BigIntLiteralType).value) === str ? right : - left.flags & TypeFlags.Boolean ? left : right.flags & TypeFlags.Boolean ? str === "true" ? trueType : str === "false" ? falseType : booleanType : - left.flags & TypeFlags.BooleanLiteral ? left : right.flags & TypeFlags.BooleanLiteral && (right as IntrinsicType).intrinsicName === str ? right : - left.flags & TypeFlags.Undefined ? left : right.flags & TypeFlags.Undefined && (right as IntrinsicType).intrinsicName === str ? right : - left.flags & TypeFlags.Null ? left : right.flags & TypeFlags.Null && (right as IntrinsicType).intrinsicName === str ? right : - left, neverType as Type); + const matchingType = reduceLeft( + constraintTypes, + (left, right) => + !(right.flags & allTypeFlags) ? left + : left.flags & TypeFlags.String ? left + : right.flags & TypeFlags.String ? source + : left.flags & TypeFlags.TemplateLiteral ? left + : right.flags & TypeFlags.TemplateLiteral + && isTypeMatchedByTemplateLiteralType( + source, + right as TemplateLiteralType, + ) ? source + : left.flags & TypeFlags.StringMapping ? left + : right.flags & TypeFlags.StringMapping + && str === applyStringMapping(right.symbol, str) ? source + : left.flags & TypeFlags.StringLiteral ? left + : right.flags & TypeFlags.StringLiteral + && (right as StringLiteralType).value === str ? right + : left.flags & TypeFlags.Number ? left + : right.flags & TypeFlags.Number ? getNumberLiteralType(+str) + : left.flags & TypeFlags.Enum ? left + : right.flags & TypeFlags.Enum ? getNumberLiteralType(+str) + : left.flags & TypeFlags.NumberLiteral ? left + : right.flags & TypeFlags.NumberLiteral + && (right as NumberLiteralType).value === +str ? right + : left.flags & TypeFlags.BigInt ? left + : right.flags & TypeFlags.BigInt ? parseBigIntLiteralType(str) + : left.flags & TypeFlags.BigIntLiteral ? left + : right.flags & TypeFlags.BigIntLiteral + && pseudoBigIntToString((right as BigIntLiteralType).value) === str + ? right + : left.flags & TypeFlags.Boolean ? left + : right.flags & TypeFlags.Boolean + ? str === "true" ? trueType : str === "false" ? falseType : booleanType + : left.flags & TypeFlags.BooleanLiteral ? left + : right.flags & TypeFlags.BooleanLiteral + && (right as IntrinsicType).intrinsicName === str ? right + : left.flags & TypeFlags.Undefined ? left + : right.flags & TypeFlags.Undefined + && (right as IntrinsicType).intrinsicName === str ? right + : left.flags & TypeFlags.Null ? left + : right.flags & TypeFlags.Null + && (right as IntrinsicType).intrinsicName === str ? right + : left, + neverType as Type, + ); if (!(matchingType.flags & TypeFlags.Never)) { inferFromTypes(matchingType, target); @@ -25365,11 +32795,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function inferFromObjectTypes(source: Type, target: Type) { if ( getObjectFlags(source) & ObjectFlags.Reference && getObjectFlags(target) & ObjectFlags.Reference && ( - (source as TypeReference).target === (target as TypeReference).target || isArrayType(source) && isArrayType(target) + (source as TypeReference).target === (target as TypeReference).target + || isArrayType(source) && isArrayType(target) ) ) { // If source and target are references to the same generic type, infer from type arguments - inferFromTypeArguments(getTypeArguments(source as TypeReference), getTypeArguments(target as TypeReference), getVariances((source as TypeReference).target)); + inferFromTypeArguments( + getTypeArguments(source as TypeReference), + getTypeArguments(target as TypeReference), + getVariances((source as TypeReference).target), + ); return; } if (isGenericMappedType(source) && isGenericMappedType(target)) { @@ -25403,17 +32838,28 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } return; } - const startLength = isTupleType(source) ? Math.min(source.target.fixedLength, target.target.fixedLength) : 0; - const endLength = Math.min(isTupleType(source) ? getEndElementCount(source.target, ElementFlags.Fixed) : 0, target.target.hasRestElement ? getEndElementCount(target.target, ElementFlags.Fixed) : 0); + const startLength = isTupleType(source) + ? Math.min(source.target.fixedLength, target.target.fixedLength) : 0; + const endLength = Math.min( + isTupleType(source) ? getEndElementCount(source.target, ElementFlags.Fixed) : 0, + target.target.hasRestElement ? getEndElementCount(target.target, ElementFlags.Fixed) : 0, + ); // Infer between starting fixed elements. for (let i = 0; i < startLength; i++) { inferFromTypes(getTypeArguments(source)[i], elementTypes[i]); } - if (!isTupleType(source) || sourceArity - startLength - endLength === 1 && source.target.elementFlags[startLength] & ElementFlags.Rest) { + if ( + !isTupleType(source) + || sourceArity - startLength - endLength === 1 + && source.target.elementFlags[startLength] & ElementFlags.Rest + ) { // Single rest element remains in source, infer from that to every element in target const restType = getTypeArguments(source)[startLength]; for (let i = startLength; i < targetArity - endLength; i++) { - inferFromTypes(elementFlags[i] & ElementFlags.Variadic ? createArrayType(restType) : restType, elementTypes[i]); + inferFromTypes( + elementFlags[i] & ElementFlags.Variadic ? createArrayType(restType) : restType, + elementTypes[i], + ); } } else { @@ -25424,33 +32870,77 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const targetInfo = getInferenceInfoForType(elementTypes[startLength]); if (targetInfo && targetInfo.impliedArity !== undefined) { // Infer slices from source based on implied arity of T. - inferFromTypes(sliceTupleType(source, startLength, endLength + sourceArity - targetInfo.impliedArity), elementTypes[startLength]); - inferFromTypes(sliceTupleType(source, startLength + targetInfo.impliedArity, endLength), elementTypes[startLength + 1]); + inferFromTypes( + sliceTupleType( + source, + startLength, + endLength + sourceArity - targetInfo.impliedArity, + ), + elementTypes[startLength], + ); + inferFromTypes( + sliceTupleType(source, startLength + targetInfo.impliedArity, endLength), + elementTypes[startLength + 1], + ); } } - else if (elementFlags[startLength] & ElementFlags.Variadic && elementFlags[startLength + 1] & ElementFlags.Rest) { + else if ( + elementFlags[startLength] & ElementFlags.Variadic + && elementFlags[startLength + 1] & ElementFlags.Rest + ) { // Middle of target is [...T, ...rest] and source is tuple type // if T is constrained by a fixed-size tuple we might be able to use its arity to infer T const param = getInferenceInfoForType(elementTypes[startLength])?.typeParameter; const constraint = param && getBaseConstraintOfType(param); if (constraint && isTupleType(constraint) && !constraint.target.hasRestElement) { const impliedArity = constraint.target.fixedLength; - inferFromTypes(sliceTupleType(source, startLength, sourceArity - (startLength + impliedArity)), elementTypes[startLength]); - inferFromTypes(getElementTypeOfSliceOfTupleType(source, startLength + impliedArity, endLength)!, elementTypes[startLength + 1]); + inferFromTypes( + sliceTupleType( + source, + startLength, + sourceArity - (startLength + impliedArity), + ), + elementTypes[startLength], + ); + inferFromTypes( + getElementTypeOfSliceOfTupleType( + source, + startLength + impliedArity, + endLength, + )!, + elementTypes[startLength + 1], + ); } } - else if (elementFlags[startLength] & ElementFlags.Rest && elementFlags[startLength + 1] & ElementFlags.Variadic) { + else if ( + elementFlags[startLength] & ElementFlags.Rest + && elementFlags[startLength + 1] & ElementFlags.Variadic + ) { // Middle of target is [...rest, ...T] and source is tuple type // if T is constrained by a fixed-size tuple we might be able to use its arity to infer T const param = getInferenceInfoForType(elementTypes[startLength + 1])?.typeParameter; const constraint = param && getBaseConstraintOfType(param); if (constraint && isTupleType(constraint) && !constraint.target.hasRestElement) { const impliedArity = constraint.target.fixedLength; - const endIndex = sourceArity - getEndElementCount(target.target, ElementFlags.Fixed); + const endIndex = sourceArity + - getEndElementCount(target.target, ElementFlags.Fixed); const startIndex = endIndex - impliedArity; - const trailingSlice = createTupleType(getTypeArguments(source).slice(startIndex, endIndex), source.target.elementFlags.slice(startIndex, endIndex), /*readonly*/ false, source.target.labeledElementDeclarations && source.target.labeledElementDeclarations.slice(startIndex, endIndex)); + const trailingSlice = createTupleType( + getTypeArguments(source).slice(startIndex, endIndex), + source.target.elementFlags.slice(startIndex, endIndex), + /*readonly*/ false, + source.target.labeledElementDeclarations + && source.target.labeledElementDeclarations.slice(startIndex, endIndex), + ); - inferFromTypes(getElementTypeOfSliceOfTupleType(source, startLength, endLength + impliedArity)!, elementTypes[startLength]); + inferFromTypes( + getElementTypeOfSliceOfTupleType( + source, + startLength, + endLength + impliedArity, + )!, + elementTypes[startLength], + ); inferFromTypes(trailingSlice, elementTypes[startLength + 1]); } } @@ -25458,9 +32948,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { else if (middleLength === 1 && elementFlags[startLength] & ElementFlags.Variadic) { // Middle of target is exactly one variadic element. Infer the slice between the fixed parts in the source. // If target ends in optional element(s), make a lower priority a speculative inference. - const endsInOptional = target.target.elementFlags[targetArity - 1] & ElementFlags.Optional; + const endsInOptional = target.target.elementFlags[targetArity - 1] + & ElementFlags.Optional; const sourceSlice = sliceTupleType(source, startLength, endLength); - inferWithPriority(sourceSlice, elementTypes[startLength], endsInOptional ? InferencePriority.SpeculativeTuple : 0); + inferWithPriority( + sourceSlice, + elementTypes[startLength], + endsInOptional ? InferencePriority.SpeculativeTuple : 0, + ); } else if (middleLength === 1 && elementFlags[startLength] & ElementFlags.Rest) { // Middle of target is exactly one rest element. If middle of source is not empty, infer union of middle element types. @@ -25472,7 +32967,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } // Infer between ending fixed elements for (let i = 0; i < endLength; i++) { - inferFromTypes(getTypeArguments(source)[sourceArity - i - 1], elementTypes[targetArity - i - 1]); + inferFromTypes( + getTypeArguments(source)[sourceArity - i - 1], + elementTypes[targetArity - i - 1], + ); } return; } @@ -25505,7 +33003,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const targetLen = targetSignatures.length; const len = sourceLen < targetLen ? sourceLen : targetLen; for (let i = 0; i < len; i++) { - inferFromSignature(getBaseSignature(sourceSignatures[sourceLen - len + i]), getErasedSignature(targetSignatures[targetLen - len + i])); + inferFromSignature( + getBaseSignature(sourceSignatures[sourceLen - len + i]), + getErasedSignature(targetSignatures[targetLen - len + i]), + ); } } @@ -25514,7 +33015,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const saveBivariant = bivariant; const kind = target.declaration ? target.declaration.kind : SyntaxKind.Unknown; // Once we descend into a bivariant signature we remain bivariant for all nested inferences - bivariant = bivariant || kind === SyntaxKind.MethodDeclaration || kind === SyntaxKind.MethodSignature || kind === SyntaxKind.Constructor; + bivariant = bivariant || kind === SyntaxKind.MethodDeclaration || kind === SyntaxKind.MethodSignature + || kind === SyntaxKind.Constructor; applyToParameterTypes(source, target, inferFromContravariantTypesIfStrictFunctionTypes); bivariant = saveBivariant; } @@ -25523,15 +33025,23 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function inferFromIndexTypes(source: Type, target: Type) { // Inferences across mapped type index signatures are pretty much the same a inferences to homomorphic variables - const priority = (getObjectFlags(source) & getObjectFlags(target) & ObjectFlags.Mapped) ? InferencePriority.HomomorphicMappedType : 0; + const priority = (getObjectFlags(source) & getObjectFlags(target) & ObjectFlags.Mapped) + ? InferencePriority.HomomorphicMappedType : 0; const indexInfos = getIndexInfosOfType(target); if (isObjectTypeWithInferableIndex(source)) { for (const targetInfo of indexInfos) { const propTypes: Type[] = []; for (const prop of getPropertiesOfType(source)) { - if (isApplicableIndexType(getLiteralTypeFromProperty(prop, TypeFlags.StringOrNumberLiteralOrUnique), targetInfo.keyType)) { + if ( + isApplicableIndexType( + getLiteralTypeFromProperty(prop, TypeFlags.StringOrNumberLiteralOrUnique), + targetInfo.keyType, + ) + ) { const propType = getTypeOfSymbol(prop); - propTypes.push(prop.flags & SymbolFlags.Optional ? removeMissingOrUndefinedType(propType) : propType); + propTypes.push( + prop.flags & SymbolFlags.Optional ? removeMissingOrUndefinedType(propType) : propType, + ); } } for (const info of getIndexInfosOfType(source)) { @@ -25554,18 +33064,25 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function isTypeOrBaseIdenticalTo(s: Type, t: Type) { - return t === missingType ? s === t : - (isTypeIdenticalTo(s, t) || !!(t.flags & TypeFlags.String && s.flags & TypeFlags.StringLiteral || t.flags & TypeFlags.Number && s.flags & TypeFlags.NumberLiteral)); + return t === missingType ? s === t + : (isTypeIdenticalTo(s, t) + || !!(t.flags & TypeFlags.String && s.flags & TypeFlags.StringLiteral + || t.flags & TypeFlags.Number && s.flags & TypeFlags.NumberLiteral)); } function isTypeCloselyMatchedBy(s: Type, t: Type) { - return !!(s.flags & TypeFlags.Object && t.flags & TypeFlags.Object && s.symbol && s.symbol === t.symbol || - s.aliasSymbol && s.aliasTypeArguments && s.aliasSymbol === t.aliasSymbol); + return !!(s.flags & TypeFlags.Object && t.flags & TypeFlags.Object && s.symbol && s.symbol === t.symbol + || s.aliasSymbol && s.aliasTypeArguments && s.aliasSymbol === t.aliasSymbol); } function hasPrimitiveConstraint(type: TypeParameter): boolean { const constraint = getConstraintOfTypeParameter(type); - return !!constraint && maybeTypeOfKind(constraint.flags & TypeFlags.Conditional ? getDefaultConstraintOfConditionalType(constraint as ConditionalType) : constraint, TypeFlags.Primitive | TypeFlags.Index | TypeFlags.TemplateLiteral | TypeFlags.StringMapping); + return !!constraint + && maybeTypeOfKind( + constraint.flags & TypeFlags.Conditional + ? getDefaultConstraintOfConditionalType(constraint as ConditionalType) : constraint, + TypeFlags.Primitive | TypeFlags.Index | TypeFlags.TemplateLiteral | TypeFlags.StringMapping, + ); } function isObjectLiteralType(type: Type) { @@ -25588,7 +33105,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function getContravariantInference(inference: InferenceInfo) { - return inference.priority! & InferencePriority.PriorityImpliesCombination ? getIntersectionType(inference.contraCandidates!) : getCommonSubtype(inference.contraCandidates!); + return inference.priority! & InferencePriority.PriorityImpliesCombination + ? getIntersectionType(inference.contraCandidates!) : getCommonSubtype(inference.contraCandidates!); } function getCovariantInference(inference: InferenceInfo, signature: Signature) { @@ -25598,17 +33116,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // all inferences were made to top-level occurrences of the type parameter, and // the type parameter has no constraint or its constraint includes no primitive or literal types, and // the type parameter was fixed during inference or does not occur at top-level in the return type. - const primitiveConstraint = hasPrimitiveConstraint(inference.typeParameter) || isConstTypeVariable(inference.typeParameter); - const widenLiteralTypes = !primitiveConstraint && inference.topLevel && - (inference.isFixed || !isTypeParameterAtTopLevelInReturnType(signature, inference.typeParameter)); - const baseCandidates = primitiveConstraint ? sameMap(candidates, getRegularTypeOfLiteralType) : - widenLiteralTypes ? sameMap(candidates, getWidenedLiteralType) : - candidates; + const primitiveConstraint = hasPrimitiveConstraint(inference.typeParameter) + || isConstTypeVariable(inference.typeParameter); + const widenLiteralTypes = !primitiveConstraint && inference.topLevel + && (inference.isFixed || !isTypeParameterAtTopLevelInReturnType(signature, inference.typeParameter)); + const baseCandidates = primitiveConstraint ? sameMap(candidates, getRegularTypeOfLiteralType) + : widenLiteralTypes ? sameMap(candidates, getWidenedLiteralType) + : candidates; // If all inferences were made from a position that implies a combined result, infer a union type. // Otherwise, infer a common supertype. - const unwidenedType = inference.priority! & InferencePriority.PriorityImpliesCombination ? - getUnionType(baseCandidates, UnionReduction.Subtype) : - getCommonSupertype(baseCandidates); + const unwidenedType = inference.priority! & InferencePriority.PriorityImpliesCombination + ? getUnionType(baseCandidates, UnionReduction.Subtype) + : getCommonSupertype(baseCandidates); return getWidenedType(unwidenedType); } @@ -25618,19 +33137,25 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { let inferredType: Type | undefined; let fallbackType: Type | undefined; if (context.signature) { - const inferredCovariantType = inference.candidates ? getCovariantInference(inference, context.signature) : undefined; - const inferredContravariantType = inference.contraCandidates ? getContravariantInference(inference) : undefined; + const inferredCovariantType = inference.candidates ? getCovariantInference(inference, context.signature) + : undefined; + const inferredContravariantType = inference.contraCandidates ? getContravariantInference(inference) + : undefined; if (inferredCovariantType || inferredContravariantType) { // If we have both co- and contra-variant inferences, we prefer the co-variant inference if it is not 'never', // all co-variant inferences are subtypes of it (i.e. it isn't one of a conflicting set of candidates), it is // a subtype of some contra-variant inference, and no other type parameter is constrained to this type parameter // and has inferences that would conflict. Otherwise, we prefer the contra-variant inference. - const preferCovariantType = inferredCovariantType && (!inferredContravariantType || - !(inferredCovariantType.flags & TypeFlags.Never) && - some(inference.contraCandidates, t => isTypeSubtypeOf(inferredCovariantType, t)) && - every(context.inferences, other => - other !== inference && getConstraintOfTypeParameter(other.typeParameter) !== inference.typeParameter || - every(other.candidates, t => isTypeSubtypeOf(t, inferredCovariantType)))); + const preferCovariantType = inferredCovariantType && (!inferredContravariantType + || !(inferredCovariantType.flags & TypeFlags.Never) + && some(inference.contraCandidates, t => isTypeSubtypeOf(inferredCovariantType, t)) + && every( + context.inferences, + other => + other !== inference + && getConstraintOfTypeParameter(other.typeParameter) !== inference.typeParameter + || every(other.candidates, t => isTypeSubtypeOf(t, inferredCovariantType)), + )); inferredType = preferCovariantType ? inferredCovariantType : inferredContravariantType; fallbackType = preferCovariantType ? inferredContravariantType : inferredCovariantType; } @@ -25648,7 +33173,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (defaultType) { // Instantiate the default type. Any forward reference to a type // parameter should be instantiated to the empty object type. - inferredType = instantiateType(defaultType, mergeTypeMappers(createBackreferenceMapper(context, index), context.nonFixingMapper)); + inferredType = instantiateType( + defaultType, + mergeTypeMappers(createBackreferenceMapper(context, index), context.nonFixingMapper), + ); } } } @@ -25656,14 +33184,25 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { inferredType = getTypeFromInference(inference); } - inference.inferredType = inferredType || getDefaultTypeArgumentType(!!(context.flags & InferenceFlags.AnyDefault)); + inference.inferredType = inferredType + || getDefaultTypeArgumentType(!!(context.flags & InferenceFlags.AnyDefault)); const constraint = getConstraintOfTypeParameter(inference.typeParameter); if (constraint) { const instantiatedConstraint = instantiateType(constraint, context.nonFixingMapper); - if (!inferredType || inferredType === wildcardType || !context.compareTypes(inferredType, getTypeWithThisArgument(instantiatedConstraint, inferredType))) { + if ( + !inferredType || inferredType === wildcardType + || !context.compareTypes( + inferredType, + getTypeWithThisArgument(instantiatedConstraint, inferredType), + ) + ) { // If the fallback type satisfies the constraint, we pick it. Otherwise, we pick the constraint. - inference.inferredType = fallbackType && context.compareTypes(fallbackType, getTypeWithThisArgument(instantiatedConstraint, fallbackType)) ? fallbackType : instantiatedConstraint; + inference.inferredType = fallbackType + && context.compareTypes( + fallbackType, + getTypeWithThisArgument(instantiatedConstraint, fallbackType), + ) ? fallbackType : instantiatedConstraint; } } } @@ -25689,25 +33228,32 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { switch (node.escapedText) { case "document": case "console": - return Diagnostics.Cannot_find_name_0_Do_you_need_to_change_your_target_library_Try_changing_the_lib_compiler_option_to_include_dom; + return Diagnostics + .Cannot_find_name_0_Do_you_need_to_change_your_target_library_Try_changing_the_lib_compiler_option_to_include_dom; case "$": return compilerOptions.types - ? Diagnostics.Cannot_find_name_0_Do_you_need_to_install_type_definitions_for_jQuery_Try_npm_i_save_dev_types_Slashjquery_and_then_add_jquery_to_the_types_field_in_your_tsconfig - : Diagnostics.Cannot_find_name_0_Do_you_need_to_install_type_definitions_for_jQuery_Try_npm_i_save_dev_types_Slashjquery; + ? Diagnostics + .Cannot_find_name_0_Do_you_need_to_install_type_definitions_for_jQuery_Try_npm_i_save_dev_types_Slashjquery_and_then_add_jquery_to_the_types_field_in_your_tsconfig + : Diagnostics + .Cannot_find_name_0_Do_you_need_to_install_type_definitions_for_jQuery_Try_npm_i_save_dev_types_Slashjquery; case "describe": case "suite": case "it": case "test": return compilerOptions.types - ? Diagnostics.Cannot_find_name_0_Do_you_need_to_install_type_definitions_for_a_test_runner_Try_npm_i_save_dev_types_Slashjest_or_npm_i_save_dev_types_Slashmocha_and_then_add_jest_or_mocha_to_the_types_field_in_your_tsconfig - : Diagnostics.Cannot_find_name_0_Do_you_need_to_install_type_definitions_for_a_test_runner_Try_npm_i_save_dev_types_Slashjest_or_npm_i_save_dev_types_Slashmocha; + ? Diagnostics + .Cannot_find_name_0_Do_you_need_to_install_type_definitions_for_a_test_runner_Try_npm_i_save_dev_types_Slashjest_or_npm_i_save_dev_types_Slashmocha_and_then_add_jest_or_mocha_to_the_types_field_in_your_tsconfig + : Diagnostics + .Cannot_find_name_0_Do_you_need_to_install_type_definitions_for_a_test_runner_Try_npm_i_save_dev_types_Slashjest_or_npm_i_save_dev_types_Slashmocha; case "process": case "require": case "Buffer": case "module": return compilerOptions.types - ? Diagnostics.Cannot_find_name_0_Do_you_need_to_install_type_definitions_for_node_Try_npm_i_save_dev_types_Slashnode_and_then_add_node_to_the_types_field_in_your_tsconfig - : Diagnostics.Cannot_find_name_0_Do_you_need_to_install_type_definitions_for_node_Try_npm_i_save_dev_types_Slashnode; + ? Diagnostics + .Cannot_find_name_0_Do_you_need_to_install_type_definitions_for_node_Try_npm_i_save_dev_types_Slashnode_and_then_add_node_to_the_types_field_in_your_tsconfig + : Diagnostics + .Cannot_find_name_0_Do_you_need_to_install_type_definitions_for_node_Try_npm_i_save_dev_types_Slashnode; case "Map": case "Set": case "Promise": @@ -25726,7 +33272,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { case "Reflect": case "BigInt64Array": case "BigUint64Array": - return Diagnostics.Cannot_find_name_0_Do_you_need_to_change_your_target_library_Try_changing_the_lib_compiler_option_to_1_or_later; + return Diagnostics + .Cannot_find_name_0_Do_you_need_to_change_your_target_library_Try_changing_the_lib_compiler_option_to_1_or_later; case "await": if (isCallExpression(node.parent)) { return Diagnostics.Cannot_find_name_0_Did_you_mean_to_write_this_in_an_async_function; @@ -25734,7 +33281,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // falls through default: if (node.parent.kind === SyntaxKind.ShorthandPropertyAssignment) { - return Diagnostics.No_value_exists_in_scope_for_the_shorthand_property_0_Either_declare_one_or_provide_an_initializer; + return Diagnostics + .No_value_exists_in_scope_for_the_shorthand_property_0_Either_declare_one_or_provide_an_initializer; } else { return Diagnostics.Cannot_find_name_0; @@ -25745,8 +33293,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function getResolvedSymbol(node: Identifier): Symbol { const links = getNodeLinks(node); if (!links.resolvedSymbol) { - links.resolvedSymbol = !nodeIsMissing(node) && - resolveName( + links.resolvedSymbol = !nodeIsMissing(node) + && resolveName( node, node.escapedText, SymbolFlags.Value | SymbolFlags.ExportValue, @@ -25760,26 +33308,42 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function isInAmbientOrTypeNode(node: Node): boolean { - return !!(node.flags & NodeFlags.Ambient || findAncestor(node, n => isInterfaceDeclaration(n) || isTypeAliasDeclaration(n) || isTypeLiteralNode(n))); + return !!(node.flags & NodeFlags.Ambient + || findAncestor(node, n => isInterfaceDeclaration(n) || isTypeAliasDeclaration(n) || isTypeLiteralNode(n))); } // Return the flow cache key for a "dotted name" (i.e. a sequence of identifiers // separated by dots). The key consists of the id of the symbol referenced by the // leftmost identifier followed by zero or more property names separated by dots. // The result is undefined if the reference isn't a dotted name. - function getFlowCacheKey(node: Node, declaredType: Type, initialType: Type, flowContainer: Node | undefined): string | undefined { + function getFlowCacheKey( + node: Node, + declaredType: Type, + initialType: Type, + flowContainer: Node | undefined, + ): string | undefined { switch (node.kind) { case SyntaxKind.Identifier: if (!isThisInTypeQuery(node)) { const symbol = getResolvedSymbol(node as Identifier); - return symbol !== unknownSymbol ? `${flowContainer ? getNodeId(flowContainer) : "-1"}|${getTypeId(declaredType)}|${getTypeId(initialType)}|${getSymbolId(symbol)}` : undefined; + return symbol !== unknownSymbol + ? `${flowContainer ? getNodeId(flowContainer) : "-1"}|${getTypeId(declaredType)}|${ + getTypeId(initialType) + }|${getSymbolId(symbol)}` : undefined; } // falls through case SyntaxKind.ThisKeyword: - return `0|${flowContainer ? getNodeId(flowContainer) : "-1"}|${getTypeId(declaredType)}|${getTypeId(initialType)}`; + return `0|${flowContainer ? getNodeId(flowContainer) : "-1"}|${getTypeId(declaredType)}|${ + getTypeId(initialType) + }`; case SyntaxKind.NonNullExpression: case SyntaxKind.ParenthesizedExpression: - return getFlowCacheKey((node as NonNullExpression | ParenthesizedExpression).expression, declaredType, initialType, flowContainer); + return getFlowCacheKey( + (node as NonNullExpression | ParenthesizedExpression).expression, + declaredType, + initialType, + flowContainer, + ); case SyntaxKind.QualifiedName: const left = getFlowCacheKey((node as QualifiedName).left, declaredType, initialType, flowContainer); return left && left + "." + (node as QualifiedName).right.escapedText; @@ -25787,7 +33351,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { case SyntaxKind.ElementAccessExpression: const propName = getAccessedPropertyName(node as AccessExpression); if (propName !== undefined) { - const key = getFlowCacheKey((node as AccessExpression).expression, declaredType, initialType, flowContainer); + const key = getFlowCacheKey( + (node as AccessExpression).expression, + declaredType, + initialType, + flowContainer, + ); return key && key + "." + propName; } break; @@ -25809,8 +33378,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { case SyntaxKind.NonNullExpression: return isMatchingReference(source, (target as NonNullExpression | ParenthesizedExpression).expression); case SyntaxKind.BinaryExpression: - return (isAssignmentExpression(target) && isMatchingReference(source, target.left)) || - (isBinaryExpression(target) && target.operatorToken.kind === SyntaxKind.CommaToken && isMatchingReference(source, target.right)); + return (isAssignmentExpression(target) && isMatchingReference(source, target.left)) + || (isBinaryExpression(target) && target.operatorToken.kind === SyntaxKind.CommaToken + && isMatchingReference(source, target.right)); } switch (source.kind) { case SyntaxKind.MetaProperty: @@ -25819,11 +33389,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { && (source as MetaProperty).name.escapedText === (target as MetaProperty).name.escapedText; case SyntaxKind.Identifier: case SyntaxKind.PrivateIdentifier: - return isThisInTypeQuery(source) ? - target.kind === SyntaxKind.ThisKeyword : - target.kind === SyntaxKind.Identifier && getResolvedSymbol(source as Identifier) === getResolvedSymbol(target as Identifier) || - (isVariableDeclaration(target) || isBindingElement(target)) && - getExportSymbolOfValueSymbolIfExported(getResolvedSymbol(source as Identifier)) === getSymbolOfDeclaration(target); + return isThisInTypeQuery(source) + ? target.kind === SyntaxKind.ThisKeyword + : target.kind === SyntaxKind.Identifier + && getResolvedSymbol(source as Identifier) === getResolvedSymbol(target as Identifier) + || (isVariableDeclaration(target) || isBindingElement(target)) + && getExportSymbolOfValueSymbolIfExported(getResolvedSymbol(source as Identifier)) + === getSymbolOfDeclaration(target); case SyntaxKind.ThisKeyword: return target.kind === SyntaxKind.ThisKeyword; case SyntaxKind.SuperKeyword: @@ -25835,19 +33407,26 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { case SyntaxKind.ElementAccessExpression: const sourcePropertyName = getAccessedPropertyName(source as AccessExpression); const targetPropertyName = isAccessExpression(target) ? getAccessedPropertyName(target) : undefined; - return sourcePropertyName !== undefined && targetPropertyName !== undefined && targetPropertyName === sourcePropertyName && - isMatchingReference((source as AccessExpression).expression, (target as AccessExpression).expression); + return sourcePropertyName !== undefined && targetPropertyName !== undefined + && targetPropertyName === sourcePropertyName + && isMatchingReference( + (source as AccessExpression).expression, + (target as AccessExpression).expression, + ); case SyntaxKind.QualifiedName: - return isAccessExpression(target) && - (source as QualifiedName).right.escapedText === getAccessedPropertyName(target) && - isMatchingReference((source as QualifiedName).left, target.expression); + return isAccessExpression(target) + && (source as QualifiedName).right.escapedText === getAccessedPropertyName(target) + && isMatchingReference((source as QualifiedName).left, target.expression); case SyntaxKind.BinaryExpression: - return (isBinaryExpression(source) && source.operatorToken.kind === SyntaxKind.CommaToken && isMatchingReference(source.right, target)); + return (isBinaryExpression(source) && source.operatorToken.kind === SyntaxKind.CommaToken + && isMatchingReference(source.right, target)); } return false; } - function getAccessedPropertyName(access: AccessExpression | BindingElement | ParameterDeclaration): __String | undefined { + function getAccessedPropertyName( + access: AccessExpression | BindingElement | ParameterDeclaration, + ): __String | undefined { if (isPropertyAccessExpression(access)) { return access.name.escapedText; } @@ -25865,13 +33444,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function tryGetNameFromType(type: Type) { - return type.flags & TypeFlags.UniqueESSymbol ? (type as UniqueESSymbolType).escapedName : - type.flags & TypeFlags.StringOrNumberLiteral ? escapeLeadingUnderscores("" + (type as StringLiteralType | NumberLiteralType).value) : undefined; + return type.flags & TypeFlags.UniqueESSymbol ? (type as UniqueESSymbolType).escapedName + : type.flags & TypeFlags.StringOrNumberLiteral + ? escapeLeadingUnderscores("" + (type as StringLiteralType | NumberLiteralType).value) : undefined; } function tryGetElementAccessExpressionName(node: ElementAccessExpression) { - return isStringOrNumericLiteralLike(node.argumentExpression) ? escapeLeadingUnderscores(node.argumentExpression.text) : - isEntityNameExpression(node.argumentExpression) ? tryGetNameFromEntityNameExpression(node.argumentExpression) : undefined; + return isStringOrNumericLiteralLike(node.argumentExpression) + ? escapeLeadingUnderscores(node.argumentExpression.text) + : isEntityNameExpression(node.argumentExpression) + ? tryGetNameFromEntityNameExpression(node.argumentExpression) : undefined; } function tryGetNameFromEntityNameExpression(node: EntityNameOrEntityNameExpression) { @@ -25926,8 +33508,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (prop && getCheckFlags(prop) & CheckFlags.SyntheticProperty) { // NOTE: cast to TransientSymbol should be safe because only TransientSymbols can have CheckFlags.SyntheticProperty if ((prop as TransientSymbol).links.isDiscriminantProperty === undefined) { - (prop as TransientSymbol).links.isDiscriminantProperty = ((prop as TransientSymbol).links.checkFlags & CheckFlags.Discriminant) === CheckFlags.Discriminant && - !isGenericType(getTypeOfSymbol(prop)); + (prop as TransientSymbol).links.isDiscriminantProperty = + ((prop as TransientSymbol).links.checkFlags & CheckFlags.Discriminant) + === CheckFlags.Discriminant + && !isGenericType(getTypeOfSymbol(prop)); } return !!(prop as TransientSymbol).links.isDiscriminantProperty; } @@ -25988,18 +33572,20 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const types = unionType.types; // We only construct maps for unions with many non-primitive constituents. if ( - types.length < 10 || getObjectFlags(unionType) & ObjectFlags.PrimitiveUnion || - countWhere(types, t => !!(t.flags & (TypeFlags.Object | TypeFlags.InstantiableNonPrimitive))) < 10 + types.length < 10 || getObjectFlags(unionType) & ObjectFlags.PrimitiveUnion + || countWhere(types, t => !!(t.flags & (TypeFlags.Object | TypeFlags.InstantiableNonPrimitive))) < 10 ) { return undefined; } if (unionType.keyPropertyName === undefined) { // The candidate key property name is the name of the first property with a unit type in one of the // constituent types. - const keyPropertyName = forEach(types, t => - t.flags & (TypeFlags.Object | TypeFlags.InstantiableNonPrimitive) ? - forEach(getPropertiesOfType(t), p => isUnitType(getTypeOfSymbol(p)) ? p.escapedName : undefined) : - undefined); + const keyPropertyName = forEach( + types, + t => t.flags & (TypeFlags.Object | TypeFlags.InstantiableNonPrimitive) + ? forEach(getPropertiesOfType(t), p => isUnitType(getTypeOfSymbol(p)) ? p.escapedName : undefined) + : undefined, + ); const mapByKeyProperty = keyPropertyName && mapTypesByKeyProperty(types, keyPropertyName); unionType.keyPropertyName = mapByKeyProperty ? keyPropertyName : "" as __String; unionType.constituentMap = mapByKeyProperty; @@ -26022,9 +33608,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function getMatchingUnionConstituentForObjectLiteral(unionType: UnionType, node: ObjectLiteralExpression) { const keyPropertyName = getKeyPropertyName(unionType); - const propNode = keyPropertyName && find(node.properties, p => - p.symbol && p.kind === SyntaxKind.PropertyAssignment && - p.symbol.escapedName === keyPropertyName && isPossiblyDiscriminantValue(p.initializer)); + const propNode = keyPropertyName + && find(node.properties, p => + p.symbol && p.kind === SyntaxKind.PropertyAssignment + && p.symbol.escapedName === keyPropertyName && isPossiblyDiscriminantValue(p.initializer)); const propType = propNode && getContextFreeTypeOfExpression((propNode as PropertyAssignment).initializer); return propType && getConstituentTypeForKeyType(unionType, propType); } @@ -26042,8 +33629,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } if ( - expression.expression.kind === SyntaxKind.PropertyAccessExpression && - isOrContainsMatchingReference(reference, (expression.expression as PropertyAccessExpression).expression) + expression.expression.kind === SyntaxKind.PropertyAccessExpression + && isOrContainsMatchingReference(reference, (expression.expression as PropertyAccessExpression).expression) ) { return true; } @@ -26087,7 +33674,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function getAssignmentReducedTypeWorker(declaredType: UnionType, assignedType: Type) { const filteredType = filterType(declaredType, t => typeMaybeAssignableTo(assignedType, t)); // Ensure that we narrow to fresh types if the assignment is a fresh boolean literal type. - const reducedType = assignedType.flags & TypeFlags.BooleanLiteral && isFreshLiteralType(assignedType) ? mapType(filteredType, getFreshTypeOfLiteralType) : filteredType; + const reducedType = assignedType.flags & TypeFlags.BooleanLiteral && isFreshLiteralType(assignedType) + ? mapType(filteredType, getFreshTypeOfLiteralType) : filteredType; // Our crude heuristic produces an invalid result in some cases: see GH#26130. // For now, when that happens, we give up and don't narrow at all. (This also // means we'll never narrow for erroneous assignments where the assigned type @@ -26099,8 +33687,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // We do a quick check for a "bind" property before performing the more expensive subtype // check. This gives us a quicker out in the common case where an object type is not a function. const resolved = resolveStructuredTypeMembers(type); - return !!(resolved.callSignatures.length || resolved.constructSignatures.length || - resolved.members.get("bind" as __String) && isTypeSubtypeOf(type, globalFunctionType)); + return !!(resolved.callSignatures.length || resolved.constructSignatures.length + || resolved.members.get("bind" as __String) && isTypeSubtypeOf(type, globalFunctionType)); } function getTypeFacts(type: Type): TypeFacts { @@ -26113,42 +33701,43 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } if (flags & (TypeFlags.StringLiteral | TypeFlags.TemplateLiteral)) { const isEmpty = flags & TypeFlags.StringLiteral && (type as StringLiteralType).value === ""; - return strictNullChecks ? - isEmpty ? TypeFacts.EmptyStringStrictFacts : TypeFacts.NonEmptyStringStrictFacts : - isEmpty ? TypeFacts.EmptyStringFacts : TypeFacts.NonEmptyStringFacts; + return strictNullChecks + ? isEmpty ? TypeFacts.EmptyStringStrictFacts : TypeFacts.NonEmptyStringStrictFacts + : isEmpty ? TypeFacts.EmptyStringFacts : TypeFacts.NonEmptyStringFacts; } if (flags & (TypeFlags.Number | TypeFlags.Enum)) { return strictNullChecks ? TypeFacts.NumberStrictFacts : TypeFacts.NumberFacts; } if (flags & TypeFlags.NumberLiteral) { const isZero = (type as NumberLiteralType).value === 0; - return strictNullChecks ? - isZero ? TypeFacts.ZeroNumberStrictFacts : TypeFacts.NonZeroNumberStrictFacts : - isZero ? TypeFacts.ZeroNumberFacts : TypeFacts.NonZeroNumberFacts; + return strictNullChecks + ? isZero ? TypeFacts.ZeroNumberStrictFacts : TypeFacts.NonZeroNumberStrictFacts + : isZero ? TypeFacts.ZeroNumberFacts : TypeFacts.NonZeroNumberFacts; } if (flags & TypeFlags.BigInt) { return strictNullChecks ? TypeFacts.BigIntStrictFacts : TypeFacts.BigIntFacts; } if (flags & TypeFlags.BigIntLiteral) { const isZero = isZeroBigInt(type as BigIntLiteralType); - return strictNullChecks ? - isZero ? TypeFacts.ZeroBigIntStrictFacts : TypeFacts.NonZeroBigIntStrictFacts : - isZero ? TypeFacts.ZeroBigIntFacts : TypeFacts.NonZeroBigIntFacts; + return strictNullChecks + ? isZero ? TypeFacts.ZeroBigIntStrictFacts : TypeFacts.NonZeroBigIntStrictFacts + : isZero ? TypeFacts.ZeroBigIntFacts : TypeFacts.NonZeroBigIntFacts; } if (flags & TypeFlags.Boolean) { return strictNullChecks ? TypeFacts.BooleanStrictFacts : TypeFacts.BooleanFacts; } if (flags & TypeFlags.BooleanLike) { - return strictNullChecks ? - (type === falseType || type === regularFalseType) ? TypeFacts.FalseStrictFacts : TypeFacts.TrueStrictFacts : - (type === falseType || type === regularFalseType) ? TypeFacts.FalseFacts : TypeFacts.TrueFacts; + return strictNullChecks + ? (type === falseType || type === regularFalseType) ? TypeFacts.FalseStrictFacts + : TypeFacts.TrueStrictFacts + : (type === falseType || type === regularFalseType) ? TypeFacts.FalseFacts : TypeFacts.TrueFacts; } if (flags & TypeFlags.Object) { - return getObjectFlags(type) & ObjectFlags.Anonymous && isEmptyObjectType(type as ObjectType) ? - strictNullChecks ? TypeFacts.EmptyObjectStrictFacts : TypeFacts.EmptyObjectFacts : - isFunctionObjectType(type as ObjectType) ? - strictNullChecks ? TypeFacts.FunctionStrictFacts : TypeFacts.FunctionFacts : - strictNullChecks ? TypeFacts.ObjectStrictFacts : TypeFacts.ObjectFacts; + return getObjectFlags(type) & ObjectFlags.Anonymous && isEmptyObjectType(type as ObjectType) + ? strictNullChecks ? TypeFacts.EmptyObjectStrictFacts : TypeFacts.EmptyObjectFacts + : isFunctionObjectType(type as ObjectType) + ? strictNullChecks ? TypeFacts.FunctionStrictFacts : TypeFacts.FunctionFacts + : strictNullChecks ? TypeFacts.ObjectStrictFacts : TypeFacts.ObjectFacts; } if (flags & TypeFlags.Void) { return TypeFacts.VoidFacts; @@ -26203,16 +33792,39 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // unknown with the union {} | null | undefined (and reduces that accordingly), and it intersects remaining // instantiable types with {}, {} | null, or {} | undefined in order to remove null and/or undefined. function getAdjustedTypeWithFacts(type: Type, facts: TypeFacts) { - const reduced = recombineUnknownType(getTypeWithFacts(strictNullChecks && type.flags & TypeFlags.Unknown ? unknownUnionType : type, facts)); + const reduced = recombineUnknownType( + getTypeWithFacts(strictNullChecks && type.flags & TypeFlags.Unknown ? unknownUnionType : type, facts), + ); if (strictNullChecks) { switch (facts) { case TypeFacts.NEUndefined: - return mapType(reduced, t => getTypeFacts(t) & TypeFacts.EQUndefined ? getIntersectionType([t, getTypeFacts(t) & TypeFacts.EQNull && !maybeTypeOfKind(reduced, TypeFlags.Null) ? getUnionType([emptyObjectType, nullType]) : emptyObjectType]) : t); + return mapType( + reduced, + t => getTypeFacts(t) & TypeFacts.EQUndefined + ? getIntersectionType([ + t, + getTypeFacts(t) & TypeFacts.EQNull && !maybeTypeOfKind(reduced, TypeFlags.Null) + ? getUnionType([emptyObjectType, nullType]) : emptyObjectType, + ]) : t, + ); case TypeFacts.NENull: - return mapType(reduced, t => getTypeFacts(t) & TypeFacts.EQNull ? getIntersectionType([t, getTypeFacts(t) & TypeFacts.EQUndefined && !maybeTypeOfKind(reduced, TypeFlags.Undefined) ? getUnionType([emptyObjectType, undefinedType]) : emptyObjectType]) : t); + return mapType( + reduced, + t => getTypeFacts(t) & TypeFacts.EQNull + ? getIntersectionType([ + t, + getTypeFacts(t) & TypeFacts.EQUndefined + && !maybeTypeOfKind(reduced, TypeFlags.Undefined) + ? getUnionType([emptyObjectType, undefinedType]) : emptyObjectType, + ]) : t, + ); case TypeFacts.NEUndefinedOrNull: case TypeFacts.Truthy: - return mapType(reduced, t => getTypeFacts(t) & TypeFacts.EQUndefinedOrNull ? getGlobalNonNullableTypeInstantiation(t) : t); + return mapType( + reduced, + t => getTypeFacts(t) & TypeFacts.EQUndefinedOrNull ? getGlobalNonNullableTypeInstantiation(t) + : t, + ); } } return reduced; @@ -26223,46 +33835,60 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function getTypeWithDefault(type: Type, defaultExpression: Expression) { - return defaultExpression ? - getUnionType([getNonUndefinedType(type), getTypeOfExpression(defaultExpression)]) : - type; + return defaultExpression + ? getUnionType([getNonUndefinedType(type), getTypeOfExpression(defaultExpression)]) + : type; } function getTypeOfDestructuredProperty(type: Type, name: PropertyName) { const nameType = getLiteralTypeFromPropertyName(name); if (!isTypeUsableAsPropertyName(nameType)) return errorType; const text = getPropertyNameFromType(nameType); - return getTypeOfPropertyOfType(type, text) || includeUndefinedInIndexSignature(getApplicableIndexInfoForName(type, text)?.type) || errorType; + return getTypeOfPropertyOfType(type, text) + || includeUndefinedInIndexSignature(getApplicableIndexInfoForName(type, text)?.type) || errorType; } function getTypeOfDestructuredArrayElement(type: Type, index: number) { - return everyType(type, isTupleLikeType) && getTupleElementType(type, index) || - includeUndefinedInIndexSignature(checkIteratedTypeOrElementType(IterationUse.Destructuring, type, undefinedType, /*errorNode*/ undefined)) || - errorType; + return everyType(type, isTupleLikeType) && getTupleElementType(type, index) + || includeUndefinedInIndexSignature( + checkIteratedTypeOrElementType( + IterationUse.Destructuring, + type, + undefinedType, + /*errorNode*/ undefined, + ), + ) + || errorType; } function includeUndefinedInIndexSignature(type: Type | undefined): Type | undefined { if (!type) return type; - return compilerOptions.noUncheckedIndexedAccess ? - getUnionType([type, missingType]) : - type; + return compilerOptions.noUncheckedIndexedAccess + ? getUnionType([type, missingType]) + : type; } function getTypeOfDestructuredSpreadExpression(type: Type) { - return createArrayType(checkIteratedTypeOrElementType(IterationUse.Destructuring, type, undefinedType, /*errorNode*/ undefined) || errorType); + return createArrayType( + checkIteratedTypeOrElementType(IterationUse.Destructuring, type, undefinedType, /*errorNode*/ undefined) + || errorType, + ); } function getAssignedTypeOfBinaryExpression(node: BinaryExpression): Type { - const isDestructuringDefaultAssignment = node.parent.kind === SyntaxKind.ArrayLiteralExpression && isDestructuringAssignmentTarget(node.parent) || - node.parent.kind === SyntaxKind.PropertyAssignment && isDestructuringAssignmentTarget(node.parent.parent); - return isDestructuringDefaultAssignment ? - getTypeWithDefault(getAssignedType(node), node.right) : - getTypeOfExpression(node.right); + const isDestructuringDefaultAssignment = + node.parent.kind === SyntaxKind.ArrayLiteralExpression && isDestructuringAssignmentTarget(node.parent) + || node.parent.kind === SyntaxKind.PropertyAssignment + && isDestructuringAssignmentTarget(node.parent.parent); + return isDestructuringDefaultAssignment + ? getTypeWithDefault(getAssignedType(node), node.right) + : getTypeOfExpression(node.right); } function isDestructuringAssignmentTarget(parent: Node) { - return parent.parent.kind === SyntaxKind.BinaryExpression && (parent.parent as BinaryExpression).left === parent || - parent.parent.kind === SyntaxKind.ForOfStatement && (parent.parent as ForOfStatement).initializer === parent; + return parent.parent.kind === SyntaxKind.BinaryExpression && (parent.parent as BinaryExpression).left === parent + || parent.parent.kind === SyntaxKind.ForOfStatement + && (parent.parent as ForOfStatement).initializer === parent; } function getAssignedTypeOfArrayLiteralElement(node: ArrayLiteralExpression, element: Expression): Type { @@ -26307,11 +33933,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function getInitialTypeOfBindingElement(node: BindingElement): Type { const pattern = node.parent; const parentType = getInitialType(pattern.parent as VariableDeclaration | BindingElement); - const type = pattern.kind === SyntaxKind.ObjectBindingPattern ? - getTypeOfDestructuredProperty(parentType, node.propertyName || node.name as Identifier) : - !node.dotDotDotToken ? - getTypeOfDestructuredArrayElement(parentType, pattern.elements.indexOf(node)) : - getTypeOfDestructuredSpreadExpression(parentType); + const type = pattern.kind === SyntaxKind.ObjectBindingPattern + ? getTypeOfDestructuredProperty(parentType, node.propertyName || node.name as Identifier) + : !node.dotDotDotToken + ? getTypeOfDestructuredArrayElement(parentType, pattern.elements.indexOf(node)) + : getTypeOfDestructuredSpreadExpression(parentType); return getTypeWithDefault(type, node.initializer!); } @@ -26337,16 +33963,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function getInitialType(node: VariableDeclaration | BindingElement) { - return node.kind === SyntaxKind.VariableDeclaration ? - getInitialTypeOfVariableDeclaration(node) : - getInitialTypeOfBindingElement(node); + return node.kind === SyntaxKind.VariableDeclaration + ? getInitialTypeOfVariableDeclaration(node) + : getInitialTypeOfBindingElement(node); } function isEmptyArrayAssignment(node: VariableDeclaration | BindingElement | Expression) { - return node.kind === SyntaxKind.VariableDeclaration && (node as VariableDeclaration).initializer && - isEmptyArrayLiteral((node as VariableDeclaration).initializer!) || - node.kind !== SyntaxKind.BindingElement && node.parent.kind === SyntaxKind.BinaryExpression && - isEmptyArrayLiteral((node.parent as BinaryExpression).right); + return node.kind === SyntaxKind.VariableDeclaration && (node as VariableDeclaration).initializer + && isEmptyArrayLiteral((node as VariableDeclaration).initializer!) + || node.kind !== SyntaxKind.BindingElement && node.parent.kind === SyntaxKind.BinaryExpression + && isEmptyArrayLiteral((node.parent as BinaryExpression).right); } function getReferenceCandidate(node: Expression): Expression { @@ -26369,10 +33995,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function getReferenceRoot(node: Node): Node { const { parent } = node; - return parent.kind === SyntaxKind.ParenthesizedExpression || - parent.kind === SyntaxKind.BinaryExpression && (parent as BinaryExpression).operatorToken.kind === SyntaxKind.EqualsToken && (parent as BinaryExpression).left === node || - parent.kind === SyntaxKind.BinaryExpression && (parent as BinaryExpression).operatorToken.kind === SyntaxKind.CommaToken && (parent as BinaryExpression).right === node ? - getReferenceRoot(parent) : node; + return parent.kind === SyntaxKind.ParenthesizedExpression + || parent.kind === SyntaxKind.BinaryExpression + && (parent as BinaryExpression).operatorToken.kind === SyntaxKind.EqualsToken + && (parent as BinaryExpression).left === node + || parent.kind === SyntaxKind.BinaryExpression + && (parent as BinaryExpression).operatorToken.kind === SyntaxKind.CommaToken + && (parent as BinaryExpression).right === node + ? getReferenceRoot(parent) : node; } function getTypeOfSwitchClause(clause: CaseClause | DefaultClause) { @@ -26396,23 +34026,31 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // Get the type names from all cases in a switch on `typeof`. The default clause and/or duplicate type names are // represented as undefined. Return undefined if one or more case clause expressions are not string literals. function getSwitchClauseTypeOfWitnesses(switchStatement: SwitchStatement): (string | undefined)[] | undefined { - if (some(switchStatement.caseBlock.clauses, clause => clause.kind === SyntaxKind.CaseClause && !isStringLiteralLike(clause.expression))) { + if ( + some( + switchStatement.caseBlock.clauses, + clause => clause.kind === SyntaxKind.CaseClause && !isStringLiteralLike(clause.expression), + ) + ) { return undefined; } const witnesses: (string | undefined)[] = []; for (const clause of switchStatement.caseBlock.clauses) { - const text = clause.kind === SyntaxKind.CaseClause ? (clause.expression as StringLiteralLike).text : undefined; + const text = clause.kind === SyntaxKind.CaseClause ? (clause.expression as StringLiteralLike).text + : undefined; witnesses.push(text && !contains(witnesses, text) ? text : undefined); } return witnesses; } function eachTypeContainedIn(source: Type, types: Type[]) { - return source.flags & TypeFlags.Union ? !forEach((source as UnionType).types, t => !contains(types, t)) : contains(types, source); + return source.flags & TypeFlags.Union ? !forEach((source as UnionType).types, t => !contains(types, t)) + : contains(types, source); } function isTypeSubsetOf(source: Type, target: Type) { - return !!(source === target || source.flags & TypeFlags.Never || target.flags & TypeFlags.Union && isTypeSubsetOfUnion(source, target as UnionType)); + return !!(source === target || source.flags & TypeFlags.Never + || target.flags & TypeFlags.Union && isTypeSubsetOfUnion(source, target as UnionType)); } function isTypeSubsetOfUnion(source: Type, target: UnionType) { @@ -26472,7 +34110,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } // filtering could remove intersections so `ContainsIntersections` might be forwarded "incorrectly" // it is purely an optimization hint so there is no harm in accidentally forwarding it - return getUnionTypeFromSortedList(filtered, (type as UnionType).objectFlags & (ObjectFlags.PrimitiveUnion | ObjectFlags.ContainsIntersections), /*aliasSymbol*/ undefined, /*aliasTypeArguments*/ undefined, newOrigin); + return getUnionTypeFromSortedList( + filtered, + (type as UnionType).objectFlags & (ObjectFlags.PrimitiveUnion | ObjectFlags.ContainsIntersections), + /*aliasSymbol*/ undefined, + /*aliasTypeArguments*/ undefined, + newOrigin, + ); } return type.flags & TypeFlags.Never || f(type) ? type : neverType; } @@ -26498,7 +34142,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return mapper(type); } const origin = (type as UnionType).origin; - const types = origin && origin.flags & TypeFlags.Union ? (origin as UnionType).types : (type as UnionType).types; + const types = origin && origin.flags & TypeFlags.Union ? (origin as UnionType).types + : (type as UnionType).types; let mappedTypes: Type[] | undefined; let changed = false; for (const t of types) { @@ -26513,13 +34158,25 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } } - return changed ? mappedTypes && getUnionType(mappedTypes, noReductions ? UnionReduction.None : UnionReduction.Literal) : type; + return changed + ? mappedTypes && getUnionType(mappedTypes, noReductions ? UnionReduction.None : UnionReduction.Literal) + : type; } - function mapTypeWithAlias(type: Type, mapper: (t: Type) => Type, aliasSymbol: Symbol | undefined, aliasTypeArguments: readonly Type[] | undefined) { - return type.flags & TypeFlags.Union && aliasSymbol ? - getUnionType(map((type as UnionType).types, mapper), UnionReduction.Literal, aliasSymbol, aliasTypeArguments) : - mapType(type, mapper); + function mapTypeWithAlias( + type: Type, + mapper: (t: Type) => Type, + aliasSymbol: Symbol | undefined, + aliasTypeArguments: readonly Type[] | undefined, + ) { + return type.flags & TypeFlags.Union && aliasSymbol + ? getUnionType( + map((type as UnionType).types, mapper), + UnionReduction.Literal, + aliasSymbol, + aliasTypeArguments, + ) + : mapType(type, mapper); } function extractTypesOfKind(type: Type, kind: TypeFlags) { @@ -26533,14 +34190,34 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // types we don't actually care about. function replacePrimitivesWithLiterals(typeWithPrimitives: Type, typeWithLiterals: Type) { if ( - maybeTypeOfKind(typeWithPrimitives, TypeFlags.String | TypeFlags.TemplateLiteral | TypeFlags.Number | TypeFlags.BigInt) && - maybeTypeOfKind(typeWithLiterals, TypeFlags.StringLiteral | TypeFlags.TemplateLiteral | TypeFlags.StringMapping | TypeFlags.NumberLiteral | TypeFlags.BigIntLiteral) + maybeTypeOfKind( + typeWithPrimitives, + TypeFlags.String | TypeFlags.TemplateLiteral | TypeFlags.Number | TypeFlags.BigInt, + ) + && maybeTypeOfKind( + typeWithLiterals, + TypeFlags.StringLiteral | TypeFlags.TemplateLiteral | TypeFlags.StringMapping | TypeFlags.NumberLiteral + | TypeFlags.BigIntLiteral, + ) ) { - return mapType(typeWithPrimitives, t => - t.flags & TypeFlags.String ? extractTypesOfKind(typeWithLiterals, TypeFlags.String | TypeFlags.StringLiteral | TypeFlags.TemplateLiteral | TypeFlags.StringMapping) : - isPatternLiteralType(t) && !maybeTypeOfKind(typeWithLiterals, TypeFlags.String | TypeFlags.TemplateLiteral | TypeFlags.StringMapping) ? extractTypesOfKind(typeWithLiterals, TypeFlags.StringLiteral) : - t.flags & TypeFlags.Number ? extractTypesOfKind(typeWithLiterals, TypeFlags.Number | TypeFlags.NumberLiteral) : - t.flags & TypeFlags.BigInt ? extractTypesOfKind(typeWithLiterals, TypeFlags.BigInt | TypeFlags.BigIntLiteral) : t); + return mapType( + typeWithPrimitives, + t => t.flags & TypeFlags.String + ? extractTypesOfKind( + typeWithLiterals, + TypeFlags.String | TypeFlags.StringLiteral | TypeFlags.TemplateLiteral + | TypeFlags.StringMapping, + ) + : isPatternLiteralType(t) + && !maybeTypeOfKind( + typeWithLiterals, + TypeFlags.String | TypeFlags.TemplateLiteral | TypeFlags.StringMapping, + ) ? extractTypesOfKind(typeWithLiterals, TypeFlags.StringLiteral) + : t.flags & TypeFlags.Number + ? extractTypesOfKind(typeWithLiterals, TypeFlags.Number | TypeFlags.NumberLiteral) + : t.flags & TypeFlags.BigInt + ? extractTypesOfKind(typeWithLiterals, TypeFlags.BigInt | TypeFlags.BigIntLiteral) : t, + ); } return typeWithPrimitives; } @@ -26568,30 +34245,35 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function getEvolvingArrayType(elementType: Type): EvolvingArrayType { - return evolvingArrayTypes[elementType.id] || (evolvingArrayTypes[elementType.id] = createEvolvingArrayType(elementType)); + return evolvingArrayTypes[elementType.id] + || (evolvingArrayTypes[elementType.id] = createEvolvingArrayType(elementType)); } // When adding evolving array element types we do not perform subtype reduction. Instead, // we defer subtype reduction until the evolving array type is finalized into a manifest // array type. function addEvolvingArrayElementType(evolvingArrayType: EvolvingArrayType, node: Expression): EvolvingArrayType { - const elementType = getRegularTypeOfObjectLiteral(getBaseTypeOfLiteralType(getContextFreeTypeOfExpression(node))); - return isTypeSubsetOf(elementType, evolvingArrayType.elementType) ? evolvingArrayType : getEvolvingArrayType(getUnionType([evolvingArrayType.elementType, elementType])); + const elementType = getRegularTypeOfObjectLiteral( + getBaseTypeOfLiteralType(getContextFreeTypeOfExpression(node)), + ); + return isTypeSubsetOf(elementType, evolvingArrayType.elementType) ? evolvingArrayType + : getEvolvingArrayType(getUnionType([evolvingArrayType.elementType, elementType])); } function createFinalArrayType(elementType: Type) { - return elementType.flags & TypeFlags.Never ? - autoArrayType : - createArrayType( - elementType.flags & TypeFlags.Union ? - getUnionType((elementType as UnionType).types, UnionReduction.Subtype) : - elementType, + return elementType.flags & TypeFlags.Never + ? autoArrayType + : createArrayType( + elementType.flags & TypeFlags.Union + ? getUnionType((elementType as UnionType).types, UnionReduction.Subtype) + : elementType, ); } // We perform subtype reduction upon obtaining the final array type from an evolving array type. function getFinalArrayType(evolvingArrayType: EvolvingArrayType): Type { - return evolvingArrayType.finalArrayType || (evolvingArrayType.finalArrayType = createFinalArrayType(evolvingArrayType.elementType)); + return evolvingArrayType.finalArrayType + || (evolvingArrayType.finalArrayType = createFinalArrayType(evolvingArrayType.elementType)); } function finalizeEvolvingArrayType(type: Type): Type { @@ -26621,25 +34303,31 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const root = getReferenceRoot(node); const parent = root.parent; const isLengthPushOrUnshift = isPropertyAccessExpression(parent) && ( - parent.name.escapedText === "length" || - parent.parent.kind === SyntaxKind.CallExpression + parent.name.escapedText === "length" + || parent.parent.kind === SyntaxKind.CallExpression && isIdentifier(parent.name) && isPushOrUnshiftIdentifier(parent.name) ); - const isElementAssignment = parent.kind === SyntaxKind.ElementAccessExpression && - (parent as ElementAccessExpression).expression === root && - parent.parent.kind === SyntaxKind.BinaryExpression && - (parent.parent as BinaryExpression).operatorToken.kind === SyntaxKind.EqualsToken && - (parent.parent as BinaryExpression).left === parent && - !isAssignmentTarget(parent.parent) && - isTypeAssignableToKind(getTypeOfExpression((parent as ElementAccessExpression).argumentExpression), TypeFlags.NumberLike); + const isElementAssignment = parent.kind === SyntaxKind.ElementAccessExpression + && (parent as ElementAccessExpression).expression === root + && parent.parent.kind === SyntaxKind.BinaryExpression + && (parent.parent as BinaryExpression).operatorToken.kind === SyntaxKind.EqualsToken + && (parent.parent as BinaryExpression).left === parent + && !isAssignmentTarget(parent.parent) + && isTypeAssignableToKind( + getTypeOfExpression((parent as ElementAccessExpression).argumentExpression), + TypeFlags.NumberLike, + ); return isLengthPushOrUnshift || isElementAssignment; } function isDeclarationWithExplicitTypeAnnotation(node: Declaration) { - return (isVariableDeclaration(node) || isPropertyDeclaration(node) || isPropertySignature(node) || isParameter(node)) && - !!(getEffectiveTypeAnnotationNode(node) || - isInJSFile(node) && hasInitializer(node) && node.initializer && isFunctionExpressionOrArrowFunction(node.initializer) && getEffectiveReturnTypeNode(node.initializer)); + return (isVariableDeclaration(node) || isPropertyDeclaration(node) || isPropertySignature(node) + || isParameter(node)) + && !!(getEffectiveTypeAnnotationNode(node) + || isInJSFile(node) && hasInitializer(node) && node.initializer + && isFunctionExpressionOrArrowFunction(node.initializer) + && getEffectiveReturnTypeNode(node.initializer)); } function getExplicitTypeOfSymbol(symbol: Symbol, diagnostic?: Diagnostic) { @@ -26659,16 +34347,30 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (isDeclarationWithExplicitTypeAnnotation(declaration)) { return getTypeOfSymbol(symbol); } - if (isVariableDeclaration(declaration) && declaration.parent.parent.kind === SyntaxKind.ForOfStatement) { + if ( + isVariableDeclaration(declaration) && declaration.parent.parent.kind === SyntaxKind.ForOfStatement + ) { const statement = declaration.parent.parent; const expressionType = getTypeOfDottedName(statement.expression, /*diagnostic*/ undefined); if (expressionType) { const use = statement.awaitModifier ? IterationUse.ForAwaitOf : IterationUse.ForOf; - return checkIteratedTypeOrElementType(use, expressionType, undefinedType, /*errorNode*/ undefined); + return checkIteratedTypeOrElementType( + use, + expressionType, + undefinedType, + /*errorNode*/ undefined, + ); } } if (diagnostic) { - addRelatedInfo(diagnostic, createDiagnosticForNode(declaration, Diagnostics._0_needs_an_explicit_type_annotation, symbolToString(symbol))); + addRelatedInfo( + diagnostic, + createDiagnosticForNode( + declaration, + Diagnostics._0_needs_an_explicit_type_annotation, + symbolToString(symbol), + ), + ); } } } @@ -26697,7 +34399,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (!type.symbol) { return undefined; } - prop = getPropertyOfType(type, getSymbolNameForPrivateIdentifier(type.symbol, name.escapedText)); + prop = getPropertyOfType( + type, + getSymbolNameForPrivateIdentifier(type.symbol, name.escapedText), + ); } else { prop = getPropertyOfType(type, name.escapedText); @@ -26735,18 +34440,23 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { funcType = checkNonNullExpression(node.expression); } } - const signatures = getSignaturesOfType(funcType && getApparentType(funcType) || unknownType, SignatureKind.Call); - const candidate = signatures.length === 1 && !signatures[0].typeParameters ? signatures[0] : - some(signatures, hasTypePredicateOrNeverReturnType) ? getResolvedSignature(node) : - undefined; - signature = links.effectsSignature = candidate && hasTypePredicateOrNeverReturnType(candidate) ? candidate : unknownSignature; + const signatures = getSignaturesOfType( + funcType && getApparentType(funcType) || unknownType, + SignatureKind.Call, + ); + const candidate = signatures.length === 1 && !signatures[0].typeParameters ? signatures[0] + : some(signatures, hasTypePredicateOrNeverReturnType) ? getResolvedSignature(node) + : undefined; + signature = links.effectsSignature = candidate && hasTypePredicateOrNeverReturnType(candidate) ? candidate + : unknownSignature; } return signature === unknownSignature ? undefined : signature; } function hasTypePredicateOrNeverReturnType(signature: Signature) { - return !!(getTypePredicateOfSignature(signature) || - signature.declaration && (getReturnTypeFromAnnotation(signature.declaration) || unknownType).flags & TypeFlags.Never); + return !!(getTypePredicateOfSignature(signature) + || signature.declaration + && (getReturnTypeFromAnnotation(signature.declaration) || unknownType).flags & TypeFlags.Never); } function getTypePredicateArgument(predicate: TypePredicate, callExpression: CallExpression) { @@ -26761,7 +34471,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const block = findAncestor(node, isFunctionOrModuleBlock) as Block | ModuleBlock | SourceFile; const sourceFile = getSourceFileOfNode(node); const span = getSpanOfTokenAtPosition(sourceFile, block.statements.pos); - diagnostics.add(createFileDiagnostic(sourceFile, span.start, span.length, Diagnostics.The_containing_function_or_module_body_is_too_large_for_control_flow_analysis)); + diagnostics.add( + createFileDiagnostic( + sourceFile, + span.start, + span.length, + Diagnostics.The_containing_function_or_module_body_is_too_large_for_control_flow_analysis, + ), + ); } function isReachableFlowNode(flow: FlowNode) { @@ -26774,8 +34491,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function isFalseExpression(expr: Expression): boolean { const node = skipParentheses(expr, /*excludeJSDocTypeAssertions*/ true); return node.kind === SyntaxKind.FalseKeyword || node.kind === SyntaxKind.BinaryExpression && ( - (node as BinaryExpression).operatorToken.kind === SyntaxKind.AmpersandAmpersandToken && (isFalseExpression((node as BinaryExpression).left) || isFalseExpression((node as BinaryExpression).right)) || - (node as BinaryExpression).operatorToken.kind === SyntaxKind.BarBarToken && isFalseExpression((node as BinaryExpression).left) && isFalseExpression((node as BinaryExpression).right) + (node as BinaryExpression).operatorToken.kind === SyntaxKind.AmpersandAmpersandToken + && (isFalseExpression((node as BinaryExpression).left) + || isFalseExpression((node as BinaryExpression).right)) + || (node as BinaryExpression).operatorToken.kind === SyntaxKind.BarBarToken + && isFalseExpression((node as BinaryExpression).left) + && isFalseExpression((node as BinaryExpression).right) ); } @@ -26789,7 +34510,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (!noCacheCheck) { const id = getFlowNodeId(flow); const reachable = flowNodeReachable[id]; - return reachable !== undefined ? reachable : (flowNodeReachable[id] = isReachableFlowNodeWorker(flow, /*noCacheCheck*/ true)); + return reachable !== undefined ? reachable + : (flowNodeReachable[id] = isReachableFlowNodeWorker(flow, /*noCacheCheck*/ true)); } noCacheCheck = false; } @@ -26827,7 +34549,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { else if (flags & FlowFlags.SwitchClause) { // The control flow path representing an unmatched value in a switch statement with // no default clause is unreachable if the switch statement is exhaustive. - if ((flow as FlowSwitchClause).clauseStart === (flow as FlowSwitchClause).clauseEnd && isExhaustiveSwitchStatement((flow as FlowSwitchClause).switchStatement)) { + if ( + (flow as FlowSwitchClause).clauseStart === (flow as FlowSwitchClause).clauseEnd + && isExhaustiveSwitchStatement((flow as FlowSwitchClause).switchStatement) + ) { return false; } flow = (flow as FlowSwitchClause).antecedent; @@ -26857,11 +34582,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (!noCacheCheck) { const id = getFlowNodeId(flow); const postSuper = flowNodePostSuper[id]; - return postSuper !== undefined ? postSuper : (flowNodePostSuper[id] = isPostSuperFlowNode(flow, /*noCacheCheck*/ true)); + return postSuper !== undefined ? postSuper + : (flowNodePostSuper[id] = isPostSuperFlowNode(flow, /*noCacheCheck*/ true)); } noCacheCheck = false; } - if (flags & (FlowFlags.Assignment | FlowFlags.Condition | FlowFlags.ArrayMutation | FlowFlags.SwitchClause)) { + if ( + flags & (FlowFlags.Assignment | FlowFlags.Condition | FlowFlags.ArrayMutation | FlowFlags.SwitchClause) + ) { flow = (flow as FlowAssignment | FlowCondition | FlowArrayMutation | FlowSwitchClause).antecedent; } else if (flags & FlowFlags.Call) { @@ -26900,18 +34628,26 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { case SyntaxKind.Identifier: if (!isThisInTypeQuery(node)) { const symbol = getResolvedSymbol(node as Identifier); - return isConstantVariable(symbol) || isParameterOrCatchClauseVariable(symbol) && !isSymbolAssigned(symbol); + return isConstantVariable(symbol) + || isParameterOrCatchClauseVariable(symbol) && !isSymbolAssigned(symbol); } break; case SyntaxKind.PropertyAccessExpression: case SyntaxKind.ElementAccessExpression: // The resolvedSymbol property is initialized by checkPropertyAccess or checkElementAccess before we get here. - return isConstantReference((node as AccessExpression).expression) && isReadonlySymbol(getNodeLinks(node).resolvedSymbol || unknownSymbol); + return isConstantReference((node as AccessExpression).expression) + && isReadonlySymbol(getNodeLinks(node).resolvedSymbol || unknownSymbol); } return false; } - function getFlowTypeOfReference(reference: Node, declaredType: Type, initialType = declaredType, flowContainer?: Node, flowNode = tryCast(reference, canHaveFlowNode)?.flowNode) { + function getFlowTypeOfReference( + reference: Node, + declaredType: Type, + initialType = declaredType, + flowContainer?: Node, + flowNode = tryCast(reference, canHaveFlowNode)?.flowNode, + ) { let key: string | undefined; let isKeySet = false; let flowDepth = 0; @@ -26929,8 +34665,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // we give type 'any[]' to 'x' instead of using the type determined by control flow analysis such that operations // on empty arrays are possible without implicit any errors and new element types can be inferred without // type mismatch errors. - const resultType = getObjectFlags(evolvedType) & ObjectFlags.EvolvingArray && isEvolvingArrayOperationTarget(reference) ? autoArrayType : finalizeEvolvingArrayType(evolvedType); - if (resultType === unreachableNeverType || reference.parent && reference.parent.kind === SyntaxKind.NonNullExpression && !(resultType.flags & TypeFlags.Never) && getTypeWithFacts(resultType, TypeFacts.NEUndefinedOrNull).flags & TypeFlags.Never) { + const resultType = + getObjectFlags(evolvedType) & ObjectFlags.EvolvingArray && isEvolvingArrayOperationTarget(reference) + ? autoArrayType : finalizeEvolvingArrayType(evolvedType); + if ( + resultType === unreachableNeverType + || reference.parent && reference.parent.kind === SyntaxKind.NonNullExpression + && !(resultType.flags & TypeFlags.Never) + && getTypeWithFacts(resultType, TypeFacts.NEUndefinedOrNull).flags & TypeFlags.Never + ) { return declaredType; } // The non-null unknown type should never escape control flow analysis. @@ -26995,9 +34738,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { flow = (flow as FlowLabel).antecedents![0]; continue; } - type = flags & FlowFlags.BranchLabel ? - getTypeAtFlowBranchLabel(flow as FlowLabel) : - getTypeAtFlowLoopLabel(flow as FlowLabel); + type = flags & FlowFlags.BranchLabel + ? getTypeAtFlowBranchLabel(flow as FlowLabel) + : getTypeAtFlowLoopLabel(flow as FlowLabel); } else if (flags & FlowFlags.ArrayMutation) { type = getTypeAtFlowArrayMutation(flow as FlowArrayMutation); @@ -27017,10 +34760,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // Check if we should continue with the control flow of the containing function. const container = (flow as FlowStart).node; if ( - container && container !== flowContainer && - reference.kind !== SyntaxKind.PropertyAccessExpression && - reference.kind !== SyntaxKind.ElementAccessExpression && - !(reference.kind === SyntaxKind.ThisKeyword && container.kind !== SyntaxKind.ArrowFunction) + container && container !== flowContainer + && reference.kind !== SyntaxKind.PropertyAccessExpression + && reference.kind !== SyntaxKind.ElementAccessExpression + && !(reference.kind === SyntaxKind.ThisKeyword && container.kind !== SyntaxKind.ArrowFunction) ) { flow = container.flowNode!; continue; @@ -27047,9 +34790,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function getInitialOrAssignedType(flow: FlowAssignment) { const node = flow.node; return getNarrowableTypeForReference( - node.kind === SyntaxKind.VariableDeclaration || node.kind === SyntaxKind.BindingElement ? - getInitialType(node as VariableDeclaration | BindingElement) : - getAssignedType(node), + node.kind === SyntaxKind.VariableDeclaration || node.kind === SyntaxKind.BindingElement + ? getInitialType(node as VariableDeclaration | BindingElement) + : getAssignedType(node), reference, ); } @@ -27064,7 +34807,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } if (getAssignmentTargetKind(node) === AssignmentKind.Compound) { const flowType = getTypeAtFlowNode(flow.antecedent); - return createFlowType(getBaseTypeOfLiteralType(getTypeFromFlowType(flowType)), isIncomplete(flowType)); + return createFlowType( + getBaseTypeOfLiteralType(getTypeFromFlowType(flowType)), + isIncomplete(flowType), + ); } if (declaredType === autoType || declaredType === autoArrayType) { if (isEmptyArrayAssignment(node)) { @@ -27090,7 +34836,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // in which case we continue control flow analysis back to the function's declaration if (isVariableDeclaration(node) && (isInJSFile(node) || isVarConstLike(node))) { const init = getDeclaredExpandoInitializer(node); - if (init && (init.kind === SyntaxKind.FunctionExpression || init.kind === SyntaxKind.ArrowFunction)) { + if ( + init && (init.kind === SyntaxKind.FunctionExpression || init.kind === SyntaxKind.ArrowFunction) + ) { return getTypeAtFlowNode(flow.antecedent); } } @@ -27098,11 +34846,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } // for (const _ in ref) acts as a nonnull on ref if ( - isVariableDeclaration(node) && - node.parent.parent.kind === SyntaxKind.ForInStatement && - (isMatchingReference(reference, node.parent.parent.expression) || optionalChainContainsReference(node.parent.parent.expression, reference)) + isVariableDeclaration(node) + && node.parent.parent.kind === SyntaxKind.ForInStatement + && (isMatchingReference(reference, node.parent.parent.expression) + || optionalChainContainsReference(node.parent.parent.expression, reference)) ) { - return getNonNullableTypeIfNeeded(finalizeEvolvingArrayType(getTypeFromFlowType(getTypeAtFlowNode(flow.antecedent)))); + return getNonNullableTypeIfNeeded( + finalizeEvolvingArrayType(getTypeFromFlowType(getTypeAtFlowNode(flow.antecedent))), + ); } // Assignment doesn't affect reference return undefined; @@ -27115,10 +34866,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } if (node.kind === SyntaxKind.BinaryExpression) { if ((node as BinaryExpression).operatorToken.kind === SyntaxKind.AmpersandAmpersandToken) { - return narrowTypeByAssertion(narrowTypeByAssertion(type, (node as BinaryExpression).left), (node as BinaryExpression).right); + return narrowTypeByAssertion( + narrowTypeByAssertion(type, (node as BinaryExpression).left), + (node as BinaryExpression).right, + ); } if ((node as BinaryExpression).operatorToken.kind === SyntaxKind.BarBarToken) { - return getUnionType([narrowTypeByAssertion(type, (node as BinaryExpression).left), narrowTypeByAssertion(type, (node as BinaryExpression).right)]); + return getUnionType([ + narrowTypeByAssertion(type, (node as BinaryExpression).left), + narrowTypeByAssertion(type, (node as BinaryExpression).right), + ]); } } return narrowType(type, node, /*assumeTrue*/ true); @@ -27128,12 +34885,19 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const signature = getEffectsSignature(flow.node); if (signature) { const predicate = getTypePredicateOfSignature(signature); - if (predicate && (predicate.kind === TypePredicateKind.AssertsThis || predicate.kind === TypePredicateKind.AssertsIdentifier)) { + if ( + predicate + && (predicate.kind === TypePredicateKind.AssertsThis + || predicate.kind === TypePredicateKind.AssertsIdentifier) + ) { const flowType = getTypeAtFlowNode(flow.antecedent); const type = finalizeEvolvingArrayType(getTypeFromFlowType(flowType)); - const narrowedType = predicate.type ? narrowTypeByTypePredicate(type, predicate, flow.node, /*assumeTrue*/ true) : - predicate.kind === TypePredicateKind.AssertsIdentifier && predicate.parameterIndex >= 0 && predicate.parameterIndex < flow.node.arguments.length ? narrowTypeByAssertion(type, flow.node.arguments[predicate.parameterIndex]) : - type; + const narrowedType = predicate.type + ? narrowTypeByTypePredicate(type, predicate, flow.node, /*assumeTrue*/ true) + : predicate.kind === TypePredicateKind.AssertsIdentifier && predicate.parameterIndex >= 0 + && predicate.parameterIndex < flow.node.arguments.length + ? narrowTypeByAssertion(type, flow.node.arguments[predicate.parameterIndex]) + : type; return narrowedType === type ? flowType : createFlowType(narrowedType, isIncomplete(flowType)); } if (getReturnTypeOfSignature(signature).flags & TypeFlags.Never) { @@ -27146,9 +34910,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function getTypeAtFlowArrayMutation(flow: FlowArrayMutation): FlowType | undefined { if (declaredType === autoType || declaredType === autoArrayType) { const node = flow.node; - const expr = node.kind === SyntaxKind.CallExpression ? - (node.expression as PropertyAccessExpression).expression : - (node.left as ElementAccessExpression).expression; + const expr = node.kind === SyntaxKind.CallExpression + ? (node.expression as PropertyAccessExpression).expression + : (node.left as ElementAccessExpression).expression; if (isMatchingReference(reference, getReferenceCandidate(expr))) { const flowType = getTypeAtFlowNode(flow.antecedent); const type = getTypeFromFlowType(flowType); @@ -27161,7 +34925,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } else { // We must get the context free expression type so as to not recur in an uncached fashion on the LHS (which causes exponential blowup in compile time) - const indexType = getContextFreeTypeOfExpression((node.left as ElementAccessExpression).argumentExpression); + const indexType = getContextFreeTypeOfExpression( + (node.left as ElementAccessExpression).argumentExpression, + ); if (isTypeAssignableToKind(indexType, TypeFlags.NumberLike)) { evolvedType = addEvolvingArrayElementType(evolvedType, node.right); } @@ -27203,21 +34969,46 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (isMatchingReference(reference, expr)) { type = narrowTypeBySwitchOnDiscriminant(type, flow.switchStatement, flow.clauseStart, flow.clauseEnd); } - else if (expr.kind === SyntaxKind.TypeOfExpression && isMatchingReference(reference, (expr as TypeOfExpression).expression)) { + else if ( + expr.kind === SyntaxKind.TypeOfExpression + && isMatchingReference(reference, (expr as TypeOfExpression).expression) + ) { type = narrowTypeBySwitchOnTypeOf(type, flow.switchStatement, flow.clauseStart, flow.clauseEnd); } else { if (strictNullChecks) { if (optionalChainContainsReference(expr, reference)) { - type = narrowTypeBySwitchOptionalChainContainment(type, flow.switchStatement, flow.clauseStart, flow.clauseEnd, t => !(t.flags & (TypeFlags.Undefined | TypeFlags.Never))); + type = narrowTypeBySwitchOptionalChainContainment( + type, + flow.switchStatement, + flow.clauseStart, + flow.clauseEnd, + t => !(t.flags & (TypeFlags.Undefined | TypeFlags.Never)), + ); } - else if (expr.kind === SyntaxKind.TypeOfExpression && optionalChainContainsReference((expr as TypeOfExpression).expression, reference)) { - type = narrowTypeBySwitchOptionalChainContainment(type, flow.switchStatement, flow.clauseStart, flow.clauseEnd, t => !(t.flags & TypeFlags.Never || t.flags & TypeFlags.StringLiteral && (t as StringLiteralType).value === "undefined")); + else if ( + expr.kind === SyntaxKind.TypeOfExpression + && optionalChainContainsReference((expr as TypeOfExpression).expression, reference) + ) { + type = narrowTypeBySwitchOptionalChainContainment( + type, + flow.switchStatement, + flow.clauseStart, + flow.clauseEnd, + t => !(t.flags & TypeFlags.Never + || t.flags & TypeFlags.StringLiteral && (t as StringLiteralType).value === "undefined"), + ); } } const access = getDiscriminantPropertyAccess(expr, type); if (access) { - type = narrowTypeBySwitchOnDiscriminantProperty(type, access, flow.switchStatement, flow.clauseStart, flow.clauseEnd); + type = narrowTypeBySwitchOnDiscriminantProperty( + type, + access, + flow.switchStatement, + flow.clauseStart, + flow.clauseEnd, + ); } } return createFlowType(type, isIncomplete(flowType)); @@ -27229,7 +35020,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { let seenIncomplete = false; let bypassFlow: FlowSwitchClause | undefined; for (const antecedent of flow.antecedents!) { - if (!bypassFlow && antecedent.flags & FlowFlags.SwitchClause && (antecedent as FlowSwitchClause).clauseStart === (antecedent as FlowSwitchClause).clauseEnd) { + if ( + !bypassFlow && antecedent.flags & FlowFlags.SwitchClause + && (antecedent as FlowSwitchClause).clauseStart === (antecedent as FlowSwitchClause).clauseEnd + ) { // The antecedent is the bypass branch of a potentially exhaustive switch statement. bypassFlow = antecedent as FlowSwitchClause; continue; @@ -27260,7 +35054,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // If the bypass flow contributes a type we haven't seen yet and the switch statement // isn't exhaustive, process the bypass flow type. Since exhaustiveness checks increase // the risk of circularities, we only want to perform them when they make a difference. - if (!(type.flags & TypeFlags.Never) && !contains(antecedentTypes, type) && !isExhaustiveSwitchStatement(bypassFlow.switchStatement)) { + if ( + !(type.flags & TypeFlags.Never) && !contains(antecedentTypes, type) + && !isExhaustiveSwitchStatement(bypassFlow.switchStatement) + ) { if (type === declaredType && declaredType === initialType) { return type; } @@ -27273,7 +35070,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } } - return createFlowType(getUnionOrEvolvingArrayType(antecedentTypes, subtypeReduction ? UnionReduction.Subtype : UnionReduction.Literal), seenIncomplete); + return createFlowType( + getUnionOrEvolvingArrayType( + antecedentTypes, + subtypeReduction ? UnionReduction.Subtype : UnionReduction.Literal, + ), + seenIncomplete, + ); } function getTypeAtFlowLoopLabel(flow: FlowLabel): FlowType { @@ -27300,7 +35103,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // path that leads to the top. for (let i = flowLoopStart; i < flowLoopCount; i++) { if (flowLoopNodes[i] === flow && flowLoopKeys[i] === key && flowLoopTypes[i].length) { - return createFlowType(getUnionOrEvolvingArrayType(flowLoopTypes[i], UnionReduction.Literal), /*incomplete*/ true); + return createFlowType( + getUnionOrEvolvingArrayType(flowLoopTypes[i], UnionReduction.Literal), + /*incomplete*/ true, + ); } } // Add the flow loop junction and reference to the in-process stack and analyze @@ -27352,7 +35158,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } // The result is incomplete if the first antecedent (the non-looping control flow path) // is incomplete. - const result = getUnionOrEvolvingArrayType(antecedentTypes, subtypeReduction ? UnionReduction.Subtype : UnionReduction.Literal); + const result = getUnionOrEvolvingArrayType( + antecedentTypes, + subtypeReduction ? UnionReduction.Subtype : UnionReduction.Literal, + ); if (isIncomplete(firstAntecedentType!)) { return createFlowType(result, /*incomplete*/ true); } @@ -27367,22 +35176,33 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (isEvolvingArrayTypeList(types)) { return getEvolvingArrayType(getUnionType(map(types, getElementTypeOfEvolvingArrayType))); } - const result = recombineUnknownType(getUnionType(sameMap(types, finalizeEvolvingArrayType), subtypeReduction)); - if (result !== declaredType && result.flags & declaredType.flags & TypeFlags.Union && arraysEqual((result as UnionType).types, (declaredType as UnionType).types)) { + const result = recombineUnknownType( + getUnionType(sameMap(types, finalizeEvolvingArrayType), subtypeReduction), + ); + if ( + result !== declaredType && result.flags & declaredType.flags & TypeFlags.Union + && arraysEqual((result as UnionType).types, (declaredType as UnionType).types) + ) { return declaredType; } return result; } function getCandidateDiscriminantPropertyAccess(expr: Expression) { - if (isBindingPattern(reference) || isFunctionExpressionOrArrowFunction(reference) || isObjectLiteralMethod(reference)) { + if ( + isBindingPattern(reference) || isFunctionExpressionOrArrowFunction(reference) + || isObjectLiteralMethod(reference) + ) { // When the reference is a binding pattern or function or arrow expression, we are narrowing a pesudo-reference in // getNarrowedTypeOfSymbol. An identifier for a destructuring variable declared in the same binding pattern or // parameter declared in the same parameter list is a candidate. if (isIdentifier(expr)) { const symbol = getResolvedSymbol(expr); const declaration = symbol.valueDeclaration; - if (declaration && (isBindingElement(declaration) || isParameter(declaration)) && reference === declaration.parent && !declaration.initializer && !declaration.dotDotDotToken) { + if ( + declaration && (isBindingElement(declaration) || isParameter(declaration)) + && reference === declaration.parent && !declaration.initializer && !declaration.dotDotDotToken + ) { return declaration; } } @@ -27399,8 +35219,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const declaration = symbol.valueDeclaration!; // Given 'const x = obj.kind', allow 'x' as an alias for 'obj.kind' if ( - isVariableDeclaration(declaration) && !declaration.type && declaration.initializer && isAccessExpression(declaration.initializer) && - isMatchingReference(reference, declaration.initializer.expression) + isVariableDeclaration(declaration) && !declaration.type && declaration.initializer + && isAccessExpression(declaration.initializer) + && isMatchingReference(reference, declaration.initializer.expression) ) { return declaration.initializer; } @@ -27408,8 +35229,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (isBindingElement(declaration) && !declaration.initializer) { const parent = declaration.parent.parent; if ( - isVariableDeclaration(parent) && !parent.type && parent.initializer && (isIdentifier(parent.initializer) || isAccessExpression(parent.initializer)) && - isMatchingReference(reference, parent.initializer) + isVariableDeclaration(parent) && !parent.type && parent.initializer + && (isIdentifier(parent.initializer) || isAccessExpression(parent.initializer)) + && isMatchingReference(reference, parent.initializer) ) { return declaration; } @@ -27433,14 +35255,22 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return undefined; } - function narrowTypeByDiscriminant(type: Type, access: AccessExpression | BindingElement | ParameterDeclaration, narrowType: (t: Type) => Type): Type { + function narrowTypeByDiscriminant( + type: Type, + access: AccessExpression | BindingElement | ParameterDeclaration, + narrowType: (t: Type) => Type, + ): Type { const propName = getAccessedPropertyName(access); if (propName === undefined) { return type; } const optionalChain = isOptionalChain(access); - const removeNullable = strictNullChecks && (optionalChain || isNonNullAccess(access)) && maybeTypeOfKind(type, TypeFlags.Nullable); - let propType = getTypeOfPropertyOfType(removeNullable ? getTypeWithFacts(type, TypeFacts.NEUndefinedOrNull) : type, propName); + const removeNullable = strictNullChecks && (optionalChain || isNonNullAccess(access)) + && maybeTypeOfKind(type, TypeFlags.Nullable); + let propType = getTypeOfPropertyOfType( + removeNullable ? getTypeWithFacts(type, TypeFacts.NEUndefinedOrNull) : type, + propName, + ); if (!propType) { return type; } @@ -27448,34 +35278,62 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const narrowedPropType = narrowType(propType); return filterType(type, t => { const discriminantType = getTypeOfPropertyOrIndexSignature(t, propName); - return !(discriminantType.flags & TypeFlags.Never) && !(narrowedPropType.flags & TypeFlags.Never) && areTypesComparable(narrowedPropType, discriminantType); + return !(discriminantType.flags & TypeFlags.Never) && !(narrowedPropType.flags & TypeFlags.Never) + && areTypesComparable(narrowedPropType, discriminantType); }); } - function narrowTypeByDiscriminantProperty(type: Type, access: AccessExpression | BindingElement | ParameterDeclaration, operator: SyntaxKind, value: Expression, assumeTrue: boolean) { - if ((operator === SyntaxKind.EqualsEqualsEqualsToken || operator === SyntaxKind.ExclamationEqualsEqualsToken) && type.flags & TypeFlags.Union) { + function narrowTypeByDiscriminantProperty( + type: Type, + access: AccessExpression | BindingElement | ParameterDeclaration, + operator: SyntaxKind, + value: Expression, + assumeTrue: boolean, + ) { + if ( + (operator === SyntaxKind.EqualsEqualsEqualsToken + || operator === SyntaxKind.ExclamationEqualsEqualsToken) && type.flags & TypeFlags.Union + ) { const keyPropertyName = getKeyPropertyName(type as UnionType); if (keyPropertyName && keyPropertyName === getAccessedPropertyName(access)) { const candidate = getConstituentTypeForKeyType(type as UnionType, getTypeOfExpression(value)); if (candidate) { - return operator === (assumeTrue ? SyntaxKind.EqualsEqualsEqualsToken : SyntaxKind.ExclamationEqualsEqualsToken) ? candidate : - isUnitType(getTypeOfPropertyOfType(candidate, keyPropertyName) || unknownType) ? removeType(type, candidate) : - type; + return operator + === (assumeTrue ? SyntaxKind.EqualsEqualsEqualsToken + : SyntaxKind.ExclamationEqualsEqualsToken) ? candidate + : isUnitType(getTypeOfPropertyOfType(candidate, keyPropertyName) || unknownType) + ? removeType(type, candidate) + : type; } } } return narrowTypeByDiscriminant(type, access, t => narrowTypeByEquality(t, operator, value, assumeTrue)); } - function narrowTypeBySwitchOnDiscriminantProperty(type: Type, access: AccessExpression | BindingElement | ParameterDeclaration, switchStatement: SwitchStatement, clauseStart: number, clauseEnd: number) { - if (clauseStart < clauseEnd && type.flags & TypeFlags.Union && getKeyPropertyName(type as UnionType) === getAccessedPropertyName(access)) { + function narrowTypeBySwitchOnDiscriminantProperty( + type: Type, + access: AccessExpression | BindingElement | ParameterDeclaration, + switchStatement: SwitchStatement, + clauseStart: number, + clauseEnd: number, + ) { + if ( + clauseStart < clauseEnd && type.flags & TypeFlags.Union + && getKeyPropertyName(type as UnionType) === getAccessedPropertyName(access) + ) { const clauseTypes = getSwitchClauseTypes(switchStatement).slice(clauseStart, clauseEnd); - const candidate = getUnionType(map(clauseTypes, t => getConstituentTypeForKeyType(type as UnionType, t) || unknownType)); + const candidate = getUnionType( + map(clauseTypes, t => getConstituentTypeForKeyType(type as UnionType, t) || unknownType), + ); if (candidate !== unknownType) { return candidate; } } - return narrowTypeByDiscriminant(type, access, t => narrowTypeBySwitchOnDiscriminant(t, switchStatement, clauseStart, clauseEnd)); + return narrowTypeByDiscriminant( + type, + access, + t => narrowTypeBySwitchOnDiscriminant(t, switchStatement, clauseStart, clauseEnd), + ); } function narrowTypeByTruthiness(type: Type, expr: Expression, assumeTrue: boolean): Type { @@ -27487,19 +35345,27 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } const access = getDiscriminantPropertyAccess(expr, type); if (access) { - return narrowTypeByDiscriminant(type, access, t => getTypeWithFacts(t, assumeTrue ? TypeFacts.Truthy : TypeFacts.Falsy)); + return narrowTypeByDiscriminant( + type, + access, + t => getTypeWithFacts(t, assumeTrue ? TypeFacts.Truthy : TypeFacts.Falsy), + ); } return type; } function isTypePresencePossible(type: Type, propName: __String, assumeTrue: boolean) { const prop = getPropertyOfType(type, propName); - return prop ? - !!(prop.flags & SymbolFlags.Optional || getCheckFlags(prop) & CheckFlags.Partial) || assumeTrue : - !!getApplicableIndexInfoForName(type, propName) || !assumeTrue; + return prop + ? !!(prop.flags & SymbolFlags.Optional || getCheckFlags(prop) & CheckFlags.Partial) || assumeTrue + : !!getApplicableIndexInfoForName(type, propName) || !assumeTrue; } - function narrowTypeByInKeyword(type: Type, nameType: StringLiteralType | NumberLiteralType | UniqueESSymbolType, assumeTrue: boolean) { + function narrowTypeByInKeyword( + type: Type, + nameType: StringLiteralType | NumberLiteralType | UniqueESSymbolType, + assumeTrue: boolean, + ) { const name = getPropertyNameFromType(nameType); const isKnownProperty = someType(type, t => isTypePresencePossible(t, name, /*assumeTrue*/ true)); if (isKnownProperty) { @@ -27512,7 +35378,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // where X is the name of the property. const recordSymbol = getGlobalRecordSymbol(); if (recordSymbol) { - return getIntersectionType([type, getTypeAliasInstantiation(recordSymbol, [nameType, unknownType])]); + return getIntersectionType([ + type, + getTypeAliasInstantiation(recordSymbol, [nameType, unknownType]), + ]); } } return type; @@ -27574,9 +35443,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return narrowTypeByPrivateIdentifierInInExpression(type, expr, assumeTrue); } const target = getReferenceCandidate(expr.right); - if (containsMissingType(type) && isAccessExpression(reference) && isMatchingReference(reference.expression, target)) { + if ( + containsMissingType(type) && isAccessExpression(reference) + && isMatchingReference(reference.expression, target) + ) { const leftType = getTypeOfExpression(expr.left); - if (isTypeUsableAsPropertyName(leftType) && getAccessedPropertyName(reference) === getPropertyNameFromType(leftType)) { + if ( + isTypeUsableAsPropertyName(leftType) + && getAccessedPropertyName(reference) === getPropertyNameFromType(leftType) + ) { return getTypeWithFacts(type, assumeTrue ? TypeFacts.NEUndefined : TypeFacts.EQUndefined); } } @@ -27593,18 +35468,32 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // expressions down to individual conditional control flows. However, we may encounter them when analyzing // aliased conditional expressions. case SyntaxKind.AmpersandAmpersandToken: - return assumeTrue ? - narrowType(narrowType(type, expr.left, /*assumeTrue*/ true), expr.right, /*assumeTrue*/ true) : - getUnionType([narrowType(type, expr.left, /*assumeTrue*/ false), narrowType(type, expr.right, /*assumeTrue*/ false)]); + return assumeTrue + ? narrowType(narrowType(type, expr.left, /*assumeTrue*/ true), expr.right, /*assumeTrue*/ true) + : getUnionType([ + narrowType(type, expr.left, /*assumeTrue*/ false), + narrowType(type, expr.right, /*assumeTrue*/ false), + ]); case SyntaxKind.BarBarToken: - return assumeTrue ? - getUnionType([narrowType(type, expr.left, /*assumeTrue*/ true), narrowType(type, expr.right, /*assumeTrue*/ true)]) : - narrowType(narrowType(type, expr.left, /*assumeTrue*/ false), expr.right, /*assumeTrue*/ false); + return assumeTrue + ? getUnionType([ + narrowType(type, expr.left, /*assumeTrue*/ true), + narrowType(type, expr.right, /*assumeTrue*/ true), + ]) + : narrowType( + narrowType(type, expr.left, /*assumeTrue*/ false), + expr.right, + /*assumeTrue*/ false, + ); } return type; } - function narrowTypeByPrivateIdentifierInInExpression(type: Type, expr: BinaryExpression, assumeTrue: boolean): Type { + function narrowTypeByPrivateIdentifierInInExpression( + type: Type, + expr: BinaryExpression, + assumeTrue: boolean, + ): Type { const target = getReferenceCandidate(expr.right); if (!isMatchingReference(reference, target)) { return type; @@ -27616,13 +35505,19 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return type; } const classSymbol = symbol.parent!; - const targetType = hasStaticModifier(Debug.checkDefined(symbol.valueDeclaration, "should always have a declaration")) - ? getTypeOfSymbol(classSymbol) as InterfaceType - : getDeclaredTypeOfSymbol(classSymbol); + const targetType = + hasStaticModifier(Debug.checkDefined(symbol.valueDeclaration, "should always have a declaration")) + ? getTypeOfSymbol(classSymbol) as InterfaceType + : getDeclaredTypeOfSymbol(classSymbol); return getNarrowedType(type, targetType, assumeTrue, /*checkDerived*/ true); } - function narrowTypeByOptionalChainContainment(type: Type, operator: SyntaxKind, value: Expression, assumeTrue: boolean): Type { + function narrowTypeByOptionalChainContainment( + type: Type, + operator: SyntaxKind, + value: Expression, + assumeTrue: boolean, + ): Type { // We are in a branch of obj?.foo === value (or any one of the other equality operators). We narrow obj as follows: // When operator is === and type of value excludes undefined, null and undefined is removed from type of obj in true branch. // When operator is !== and type of value excludes undefined, null and undefined is removed from type of obj in false branch. @@ -27632,12 +35527,17 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // When operator is !== and type of value is undefined, null and undefined is removed from type of obj in true branch. // When operator is == and type of value is null or undefined, null and undefined is removed from type of obj in false branch. // When operator is != and type of value is null or undefined, null and undefined is removed from type of obj in true branch. - const equalsOperator = operator === SyntaxKind.EqualsEqualsToken || operator === SyntaxKind.EqualsEqualsEqualsToken; - const nullableFlags = operator === SyntaxKind.EqualsEqualsToken || operator === SyntaxKind.ExclamationEqualsToken ? TypeFlags.Nullable : TypeFlags.Undefined; + const equalsOperator = operator === SyntaxKind.EqualsEqualsToken + || operator === SyntaxKind.EqualsEqualsEqualsToken; + const nullableFlags = + operator === SyntaxKind.EqualsEqualsToken || operator === SyntaxKind.ExclamationEqualsToken + ? TypeFlags.Nullable : TypeFlags.Undefined; const valueType = getTypeOfExpression(value); // Note that we include any and unknown in the exclusion test because their domain includes null and undefined. - const removeNullable = equalsOperator !== assumeTrue && everyType(valueType, t => !!(t.flags & nullableFlags)) || - equalsOperator === assumeTrue && everyType(valueType, t => !(t.flags & (TypeFlags.AnyOrUnknown | nullableFlags))); + const removeNullable = + equalsOperator !== assumeTrue && everyType(valueType, t => !!(t.flags & nullableFlags)) + || equalsOperator === assumeTrue + && everyType(valueType, t => !(t.flags & (TypeFlags.AnyOrUnknown | nullableFlags))); return removeNullable ? getAdjustedTypeWithFacts(type, TypeFacts.NEUndefinedOrNull) : type; } @@ -27645,32 +35545,41 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (type.flags & TypeFlags.Any) { return type; } - if (operator === SyntaxKind.ExclamationEqualsToken || operator === SyntaxKind.ExclamationEqualsEqualsToken) { + if ( + operator === SyntaxKind.ExclamationEqualsToken || operator === SyntaxKind.ExclamationEqualsEqualsToken + ) { assumeTrue = !assumeTrue; } const valueType = getTypeOfExpression(value); - const doubleEquals = operator === SyntaxKind.EqualsEqualsToken || operator === SyntaxKind.ExclamationEqualsToken; + const doubleEquals = operator === SyntaxKind.EqualsEqualsToken + || operator === SyntaxKind.ExclamationEqualsToken; if (valueType.flags & TypeFlags.Nullable) { if (!strictNullChecks) { return type; } - const facts = doubleEquals ? - assumeTrue ? TypeFacts.EQUndefinedOrNull : TypeFacts.NEUndefinedOrNull : - valueType.flags & TypeFlags.Null ? - assumeTrue ? TypeFacts.EQNull : TypeFacts.NENull : - assumeTrue ? TypeFacts.EQUndefined : TypeFacts.NEUndefined; + const facts = doubleEquals + ? assumeTrue ? TypeFacts.EQUndefinedOrNull : TypeFacts.NEUndefinedOrNull + : valueType.flags & TypeFlags.Null + ? assumeTrue ? TypeFacts.EQNull : TypeFacts.NENull + : assumeTrue ? TypeFacts.EQUndefined : TypeFacts.NEUndefined; return getAdjustedTypeWithFacts(type, facts); } if (assumeTrue) { if (!doubleEquals && (type.flags & TypeFlags.Unknown || someType(type, isEmptyAnonymousObjectType))) { - if (valueType.flags & (TypeFlags.Primitive | TypeFlags.NonPrimitive) || isEmptyAnonymousObjectType(valueType)) { + if ( + valueType.flags & (TypeFlags.Primitive | TypeFlags.NonPrimitive) + || isEmptyAnonymousObjectType(valueType) + ) { return valueType; } if (valueType.flags & TypeFlags.Object) { return nonPrimitiveType; } } - const filteredType = filterType(type, t => areTypesComparable(t, valueType) || doubleEquals && isCoercibleUnderDoubleEquals(t, valueType)); + const filteredType = filterType( + type, + t => areTypesComparable(t, valueType) || doubleEquals && isCoercibleUnderDoubleEquals(t, valueType), + ); return replacePrimitivesWithLiterals(filteredType, valueType); } if (isUnitType(valueType)) { @@ -27679,19 +35588,34 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return type; } - function narrowTypeByTypeof(type: Type, typeOfExpr: TypeOfExpression, operator: SyntaxKind, literal: LiteralExpression, assumeTrue: boolean): Type { + function narrowTypeByTypeof( + type: Type, + typeOfExpr: TypeOfExpression, + operator: SyntaxKind, + literal: LiteralExpression, + assumeTrue: boolean, + ): Type { // We have '==', '!=', '===', or !==' operator with 'typeof xxx' and string literal operands - if (operator === SyntaxKind.ExclamationEqualsToken || operator === SyntaxKind.ExclamationEqualsEqualsToken) { + if ( + operator === SyntaxKind.ExclamationEqualsToken || operator === SyntaxKind.ExclamationEqualsEqualsToken + ) { assumeTrue = !assumeTrue; } const target = getReferenceCandidate(typeOfExpr.expression); if (!isMatchingReference(reference, target)) { - if (strictNullChecks && optionalChainContainsReference(target, reference) && assumeTrue === (literal.text !== "undefined")) { + if ( + strictNullChecks && optionalChainContainsReference(target, reference) + && assumeTrue === (literal.text !== "undefined") + ) { type = getAdjustedTypeWithFacts(type, TypeFacts.NEUndefinedOrNull); } const propertyAccess = getDiscriminantPropertyAccess(target, type); if (propertyAccess) { - return narrowTypeByDiscriminant(type, propertyAccess, t => narrowTypeByLiteralExpression(t, literal, assumeTrue)); + return narrowTypeByDiscriminant( + type, + propertyAccess, + t => narrowTypeByLiteralExpression(t, literal, assumeTrue), + ); } return type; } @@ -27699,17 +35623,29 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function narrowTypeByLiteralExpression(type: Type, literal: LiteralExpression, assumeTrue: boolean) { - return assumeTrue ? - narrowTypeByTypeName(type, literal.text) : - getAdjustedTypeWithFacts(type, typeofNEFacts.get(literal.text) || TypeFacts.TypeofNEHostObject); + return assumeTrue + ? narrowTypeByTypeName(type, literal.text) + : getAdjustedTypeWithFacts(type, typeofNEFacts.get(literal.text) || TypeFacts.TypeofNEHostObject); } - function narrowTypeBySwitchOptionalChainContainment(type: Type, switchStatement: SwitchStatement, clauseStart: number, clauseEnd: number, clauseCheck: (type: Type) => boolean) { - const everyClauseChecks = clauseStart !== clauseEnd && every(getSwitchClauseTypes(switchStatement).slice(clauseStart, clauseEnd), clauseCheck); + function narrowTypeBySwitchOptionalChainContainment( + type: Type, + switchStatement: SwitchStatement, + clauseStart: number, + clauseEnd: number, + clauseCheck: (type: Type) => boolean, + ) { + const everyClauseChecks = clauseStart !== clauseEnd + && every(getSwitchClauseTypes(switchStatement).slice(clauseStart, clauseEnd), clauseCheck); return everyClauseChecks ? getTypeWithFacts(type, TypeFacts.NEUndefinedOrNull) : type; } - function narrowTypeBySwitchOnDiscriminant(type: Type, switchStatement: SwitchStatement, clauseStart: number, clauseEnd: number) { + function narrowTypeBySwitchOnDiscriminant( + type: Type, + switchStatement: SwitchStatement, + clauseStart: number, + clauseEnd: number, + ) { // We only narrow if all case expressions specify // values with unit types, except for the case where // `type` is unknown. In this instance we map object @@ -27742,12 +35678,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return getUnionType(groundClauseTypes === undefined ? clauseTypes : groundClauseTypes); } const discriminantType = getUnionType(clauseTypes); - const caseType = discriminantType.flags & TypeFlags.Never ? neverType : - replacePrimitivesWithLiterals(filterType(type, t => areTypesComparable(discriminantType, t)), discriminantType); + const caseType = discriminantType.flags & TypeFlags.Never ? neverType + : replacePrimitivesWithLiterals( + filterType(type, t => areTypesComparable(discriminantType, t)), + discriminantType, + ); if (!hasDefaultClause) { return caseType; } - const defaultType = filterType(type, t => !(isUnitLikeType(t) && contains(switchTypes, getRegularTypeOfLiteralType(extractUnitType(t))))); + const defaultType = filterType( + type, + t => !(isUnitLikeType(t) && contains(switchTypes, getRegularTypeOfLiteralType(extractUnitType(t)))), + ); return caseType.flags & TypeFlags.Never ? defaultType : getUnionType([caseType, defaultType]); } @@ -27764,9 +35706,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { case "symbol": return narrowTypeByTypeFacts(type, esSymbolType, TypeFacts.TypeofEQSymbol); case "object": - return type.flags & TypeFlags.Any ? type : getUnionType([narrowTypeByTypeFacts(type, nonPrimitiveType, TypeFacts.TypeofEQObject), narrowTypeByTypeFacts(type, nullType, TypeFacts.EQNull)]); + return type.flags & TypeFlags.Any ? type + : getUnionType([ + narrowTypeByTypeFacts(type, nonPrimitiveType, TypeFacts.TypeofEQObject), + narrowTypeByTypeFacts(type, nullType, TypeFacts.EQNull), + ]); case "function": - return type.flags & TypeFlags.Any ? type : narrowTypeByTypeFacts(type, globalFunctionType, TypeFacts.TypeofEQFunction); + return type.flags & TypeFlags.Any ? type + : narrowTypeByTypeFacts(type, globalFunctionType, TypeFacts.TypeofEQFunction); case "undefined": return narrowTypeByTypeFacts(type, undefinedType, TypeFacts.EQUndefined); } @@ -27779,25 +35726,34 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // the constituent based on its type facts. We use the strict subtype relation because it treats `object` // as a subtype of `{}`, and we need the type facts check because function types are subtypes of `object`, // but are classified as "function" according to `typeof`. - isTypeRelatedTo(t, impliedType, strictSubtypeRelation) ? getTypeFacts(t) & facts ? t : neverType : + isTypeRelatedTo(t, impliedType, strictSubtypeRelation) ? getTypeFacts(t) & facts ? t : neverType // We next check if the consituent is a supertype of the implied type. If so, we substitute the implied // type. This handles top types like `unknown` and `{}`, and supertypes like `{ toString(): string }`. - isTypeSubtypeOf(impliedType, t) ? impliedType : + : isTypeSubtypeOf(impliedType, t) ? impliedType // Neither the constituent nor the implied type is a subtype of the other, however their domains may still // overlap. For example, an unconstrained type parameter and type `string`. If the type facts indicate // possible overlap, we form an intersection. Otherwise, we eliminate the constituent. - getTypeFacts(t) & facts ? getIntersectionType([t, impliedType]) : - neverType); + : getTypeFacts(t) & facts ? getIntersectionType([t, impliedType]) + : neverType); } - function narrowTypeBySwitchOnTypeOf(type: Type, switchStatement: SwitchStatement, clauseStart: number, clauseEnd: number): Type { + function narrowTypeBySwitchOnTypeOf( + type: Type, + switchStatement: SwitchStatement, + clauseStart: number, + clauseEnd: number, + ): Type { const witnesses = getSwitchClauseTypeOfWitnesses(switchStatement); if (!witnesses) { return type; } // Equal start and end denotes implicit fallthrough; undefined marks explicit default clause. - const defaultIndex = findIndex(switchStatement.caseBlock.clauses, clause => clause.kind === SyntaxKind.DefaultClause); - const hasDefaultClause = clauseStart === clauseEnd || (defaultIndex >= clauseStart && defaultIndex < clauseEnd); + const defaultIndex = findIndex( + switchStatement.caseBlock.clauses, + clause => clause.kind === SyntaxKind.DefaultClause, + ); + const hasDefaultClause = clauseStart === clauseEnd + || (defaultIndex >= clauseStart && defaultIndex < clauseEnd); if (hasDefaultClause) { // In the default clause we filter constituents down to those that are not-equal to all handled cases. const notEqualFacts = getNotEqualFactsFromTypeofSwitch(clauseStart, clauseEnd, witnesses); @@ -27809,14 +35765,25 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function isMatchingConstructorReference(expr: Expression) { - return (isPropertyAccessExpression(expr) && idText(expr.name) === "constructor" || - isElementAccessExpression(expr) && isStringLiteralLike(expr.argumentExpression) && expr.argumentExpression.text === "constructor") && - isMatchingReference(reference, expr.expression); - } - - function narrowTypeByConstructor(type: Type, operator: SyntaxKind, identifier: Expression, assumeTrue: boolean): Type { + return (isPropertyAccessExpression(expr) && idText(expr.name) === "constructor" + || isElementAccessExpression(expr) && isStringLiteralLike(expr.argumentExpression) + && expr.argumentExpression.text === "constructor") + && isMatchingReference(reference, expr.expression); + } + + function narrowTypeByConstructor( + type: Type, + operator: SyntaxKind, + identifier: Expression, + assumeTrue: boolean, + ): Type { // Do not narrow when checking inequality. - if (assumeTrue ? (operator !== SyntaxKind.EqualsEqualsToken && operator !== SyntaxKind.EqualsEqualsEqualsToken) : (operator !== SyntaxKind.ExclamationEqualsToken && operator !== SyntaxKind.ExclamationEqualsEqualsToken)) { + if ( + assumeTrue + ? (operator !== SyntaxKind.EqualsEqualsToken && operator !== SyntaxKind.EqualsEqualsEqualsToken) + : (operator !== SyntaxKind.ExclamationEqualsToken + && operator !== SyntaxKind.ExclamationEqualsEqualsToken) + ) { return type; } @@ -27853,8 +35820,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // that defines the same set of properties as class `A`, in that case they are structurally the same // type, but when you do something like `instanceOfA.constructor === B` it will return false. if ( - source.flags & TypeFlags.Object && getObjectFlags(source) & ObjectFlags.Class || - target.flags & TypeFlags.Object && getObjectFlags(target) & ObjectFlags.Class + source.flags & TypeFlags.Object && getObjectFlags(source) & ObjectFlags.Class + || target.flags & TypeFlags.Object && getObjectFlags(target) & ObjectFlags.Class ) { return source.symbol === target.symbol; } @@ -27880,8 +35847,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // Don't narrow from `any` if the target type is exactly `Object` or `Function`, and narrow // in the false branch only if the target is a non-empty object type. if ( - isTypeAny(type) && (instanceType === globalObjectType || instanceType === globalFunctionType) || - !assumeTrue && !(instanceType.flags & TypeFlags.Object && !isEmptyAnonymousObjectType(instanceType)) + isTypeAny(type) && (instanceType === globalObjectType || instanceType === globalFunctionType) + || !assumeTrue && !(instanceType.flags & TypeFlags.Object && !isEmptyAnonymousObjectType(instanceType)) ) { return type; } @@ -27895,7 +35862,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } const constructSignatures = getSignaturesOfType(constructorType, SignatureKind.Construct); if (constructSignatures.length) { - return getUnionType(map(constructSignatures, signature => getReturnTypeOfSignature(getErasedSignature(signature)))); + return getUnionType( + map(constructSignatures, signature => getReturnTypeOfSignature(getErasedSignature(signature))), + ); } // We use the empty object type to indicate we don't know the type of objects created by // this constructor function. @@ -27903,8 +35872,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function getNarrowedType(type: Type, candidate: Type, assumeTrue: boolean, checkDerived: boolean): Type { - const key = type.flags & TypeFlags.Union ? `N${getTypeId(type)},${getTypeId(candidate)},${(assumeTrue ? 1 : 0) | (checkDerived ? 2 : 0)}` : undefined; - return getCachedType(key) ?? setCachedType(key, getNarrowedTypeWorker(type, candidate, assumeTrue, checkDerived)); + const key = type.flags & TypeFlags.Union + ? `N${getTypeId(type)},${getTypeId(candidate)},${(assumeTrue ? 1 : 0) | (checkDerived ? 2 : 0)}` + : undefined; + return getCachedType(key) + ?? setCachedType(key, getNarrowedTypeWorker(type, candidate, assumeTrue, checkDerived)); } function getNarrowedTypeWorker(type: Type, candidate: Type, assumeTrue: boolean, checkDerived: boolean) { @@ -27932,41 +35904,60 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // prototype object types. const directlyRelated = mapType( matching || type, - checkDerived ? - t => isTypeDerivedFrom(t, c) ? t : isTypeDerivedFrom(c, t) ? c : neverType : - t => isTypeStrictSubtypeOf(t, c) ? t : isTypeStrictSubtypeOf(c, t) ? c : isTypeSubtypeOf(t, c) ? t : isTypeSubtypeOf(c, t) ? c : neverType, + checkDerived + ? t => isTypeDerivedFrom(t, c) ? t : isTypeDerivedFrom(c, t) ? c : neverType + : t => + isTypeStrictSubtypeOf(t, c) ? t + : isTypeStrictSubtypeOf(c, t) ? c + : isTypeSubtypeOf(t, c) ? t : isTypeSubtypeOf(c, t) ? c : neverType, ); // If no constituents are directly related, create intersections for any generic constituents that // are related by constraint. - return directlyRelated.flags & TypeFlags.Never ? - mapType(type, t => maybeTypeOfKind(t, TypeFlags.Instantiable) && isRelated(c, getBaseConstraintOfType(t) || unknownType) ? getIntersectionType([t, c]) : neverType) : - directlyRelated; + return directlyRelated.flags & TypeFlags.Never + ? mapType( + type, + t => maybeTypeOfKind(t, TypeFlags.Instantiable) + && isRelated(c, getBaseConstraintOfType(t) || unknownType) ? getIntersectionType([t, c]) + : neverType, + ) + : directlyRelated; }); // If filtering produced a non-empty type, return that. Otherwise, pick the most specific of the two // based on assignability, or as a last resort produce an intersection. - return !(narrowedType.flags & TypeFlags.Never) ? narrowedType : - isTypeSubtypeOf(candidate, type) ? candidate : - isTypeAssignableTo(type, candidate) ? type : - isTypeAssignableTo(candidate, type) ? candidate : - getIntersectionType([type, candidate]); + return !(narrowedType.flags & TypeFlags.Never) ? narrowedType + : isTypeSubtypeOf(candidate, type) ? candidate + : isTypeAssignableTo(type, candidate) ? type + : isTypeAssignableTo(candidate, type) ? candidate + : getIntersectionType([type, candidate]); } function narrowTypeByCallExpression(type: Type, callExpression: CallExpression, assumeTrue: boolean): Type { if (hasMatchingArgument(callExpression, reference)) { - const signature = assumeTrue || !isCallChain(callExpression) ? getEffectsSignature(callExpression) : undefined; + const signature = assumeTrue || !isCallChain(callExpression) ? getEffectsSignature(callExpression) + : undefined; const predicate = signature && getTypePredicateOfSignature(signature); - if (predicate && (predicate.kind === TypePredicateKind.This || predicate.kind === TypePredicateKind.Identifier)) { + if ( + predicate + && (predicate.kind === TypePredicateKind.This || predicate.kind === TypePredicateKind.Identifier) + ) { return narrowTypeByTypePredicate(type, predicate, callExpression, assumeTrue); } } - if (containsMissingType(type) && isAccessExpression(reference) && isPropertyAccessExpression(callExpression.expression)) { + if ( + containsMissingType(type) && isAccessExpression(reference) + && isPropertyAccessExpression(callExpression.expression) + ) { const callAccess = callExpression.expression; if ( - isMatchingReference(reference.expression, getReferenceCandidate(callAccess.expression)) && - isIdentifier(callAccess.name) && callAccess.name.escapedText === "hasOwnProperty" && callExpression.arguments.length === 1 + isMatchingReference(reference.expression, getReferenceCandidate(callAccess.expression)) + && isIdentifier(callAccess.name) && callAccess.name.escapedText === "hasOwnProperty" + && callExpression.arguments.length === 1 ) { const argument = callExpression.arguments[0]; - if (isStringLiteralLike(argument) && getAccessedPropertyName(reference) === escapeLeadingUnderscores(argument.text)) { + if ( + isStringLiteralLike(argument) + && getAccessedPropertyName(reference) === escapeLeadingUnderscores(argument.text) + ) { return getTypeWithFacts(type, assumeTrue ? TypeFacts.NEUndefined : TypeFacts.EQUndefined); } } @@ -27974,23 +35965,35 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return type; } - function narrowTypeByTypePredicate(type: Type, predicate: TypePredicate, callExpression: CallExpression, assumeTrue: boolean): Type { + function narrowTypeByTypePredicate( + type: Type, + predicate: TypePredicate, + callExpression: CallExpression, + assumeTrue: boolean, + ): Type { // Don't narrow from 'any' if the predicate type is exactly 'Object' or 'Function' - if (predicate.type && !(isTypeAny(type) && (predicate.type === globalObjectType || predicate.type === globalFunctionType))) { + if ( + predicate.type + && !(isTypeAny(type) && (predicate.type === globalObjectType || predicate.type === globalFunctionType)) + ) { const predicateArgument = getTypePredicateArgument(predicate, callExpression); if (predicateArgument) { if (isMatchingReference(reference, predicateArgument)) { return getNarrowedType(type, predicate.type, assumeTrue, /*checkDerived*/ false); } if ( - strictNullChecks && assumeTrue && optionalChainContainsReference(predicateArgument, reference) && - !(getTypeFacts(predicate.type) & TypeFacts.EQUndefined) + strictNullChecks && assumeTrue && optionalChainContainsReference(predicateArgument, reference) + && !(getTypeFacts(predicate.type) & TypeFacts.EQUndefined) ) { type = getAdjustedTypeWithFacts(type, TypeFacts.NEUndefinedOrNull); } const access = getDiscriminantPropertyAccess(predicateArgument, type); if (access) { - return narrowTypeByDiscriminant(type, access, t => getNarrowedType(t, predicate.type!, assumeTrue, /*checkDerived*/ false)); + return narrowTypeByDiscriminant( + type, + access, + t => getNarrowedType(t, predicate.type!, assumeTrue, /*checkDerived*/ false), + ); } } } @@ -28002,8 +36005,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function narrowType(type: Type, expr: Expression, assumeTrue: boolean): Type { // for `a?.b`, we emulate a synthetic `a !== null && a !== undefined` condition for `a` if ( - isExpressionOfOptionalChainRoot(expr) || - isBinaryExpression(expr.parent) && (expr.parent.operatorToken.kind === SyntaxKind.QuestionQuestionToken || expr.parent.operatorToken.kind === SyntaxKind.QuestionQuestionEqualsToken) && expr.parent.left === expr + isExpressionOfOptionalChainRoot(expr) + || isBinaryExpression(expr.parent) + && (expr.parent.operatorToken.kind === SyntaxKind.QuestionQuestionToken + || expr.parent.operatorToken.kind === SyntaxKind.QuestionQuestionEqualsToken) + && expr.parent.left === expr ) { return narrowTypeByOptionality(type, expr, assumeTrue); } @@ -28015,7 +36021,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const symbol = getResolvedSymbol(expr as Identifier); if (isConstantVariable(symbol)) { const declaration = symbol.valueDeclaration; - if (declaration && isVariableDeclaration(declaration) && !declaration.type && declaration.initializer && isConstantReference(reference)) { + if ( + declaration && isVariableDeclaration(declaration) && !declaration.type + && declaration.initializer && isConstantReference(reference) + ) { inlineLevel++; const result = narrowType(type, declaration.initializer, assumeTrue); inlineLevel--; @@ -28033,7 +36042,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return narrowTypeByCallExpression(type, expr as CallExpression, assumeTrue); case SyntaxKind.ParenthesizedExpression: case SyntaxKind.NonNullExpression: - return narrowType(type, (expr as ParenthesizedExpression | NonNullExpression).expression, assumeTrue); + return narrowType( + type, + (expr as ParenthesizedExpression | NonNullExpression).expression, + assumeTrue, + ); case SyntaxKind.BinaryExpression: return narrowTypeByBinaryExpression(type, expr as BinaryExpression, assumeTrue); case SyntaxKind.PrefixUnaryExpression: @@ -28047,11 +36060,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function narrowTypeByOptionality(type: Type, expr: Expression, assumePresent: boolean): Type { if (isMatchingReference(reference, expr)) { - return getAdjustedTypeWithFacts(type, assumePresent ? TypeFacts.NEUndefinedOrNull : TypeFacts.EQUndefinedOrNull); + return getAdjustedTypeWithFacts( + type, + assumePresent ? TypeFacts.NEUndefinedOrNull : TypeFacts.EQUndefinedOrNull, + ); } const access = getDiscriminantPropertyAccess(expr, type); if (access) { - return narrowTypeByDiscriminant(type, access, t => getTypeWithFacts(t, assumePresent ? TypeFacts.NEUndefinedOrNull : TypeFacts.EQUndefinedOrNull)); + return narrowTypeByDiscriminant( + type, + access, + t => getTypeWithFacts(t, assumePresent ? TypeFacts.NEUndefinedOrNull : TypeFacts.EQUndefinedOrNull), + ); } return type; } @@ -28075,7 +36095,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } } - if (isDeclarationName(location) && isSetAccessor(location.parent) && getAnnotatedAccessorTypeNode(location.parent)) { + if ( + isDeclarationName(location) && isSetAccessor(location.parent) + && getAnnotatedAccessorTypeNode(location.parent) + ) { return getWriteTypeOfAccessors(location.parent.symbol); } // The location isn't a reference to the given symbol, meaning we're being asked @@ -28088,10 +36111,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function getControlFlowContainer(node: Node): Node { return findAncestor(node.parent, node => - isFunctionLike(node) && !getImmediatelyInvokedFunctionExpression(node) || - node.kind === SyntaxKind.ModuleBlock || - node.kind === SyntaxKind.SourceFile || - node.kind === SyntaxKind.PropertyDeclaration)!; + isFunctionLike(node) && !getImmediatelyInvokedFunctionExpression(node) + || node.kind === SyntaxKind.ModuleBlock + || node.kind === SyntaxKind.SourceFile + || node.kind === SyntaxKind.PropertyDeclaration)!; } // Check if a parameter or catch variable is assigned anywhere @@ -28111,7 +36134,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function hasParentWithAssignmentsMarked(node: Node) { - return !!findAncestor(node.parent, node => (isFunctionLike(node) || isCatchClause(node)) && !!(getNodeLinks(node).flags & NodeCheckFlags.AssignmentsMarked)); + return !!findAncestor( + node.parent, + node => + (isFunctionLike(node) || isCatchClause(node)) + && !!(getNodeLinks(node).flags & NodeCheckFlags.AssignmentsMarked), + ); } function markNodeAssignments(node: Node) { @@ -28129,7 +36157,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function isConstantVariable(symbol: Symbol) { - return symbol.flags & SymbolFlags.Variable && (getDeclarationNodeFlagsFromSymbol(symbol) & NodeFlags.Constant) !== 0; + return symbol.flags & SymbolFlags.Variable + && (getDeclarationNodeFlagsFromSymbol(symbol) & NodeFlags.Constant) !== 0; } function parameterInitializerContainsUndefined(declaration: ParameterDeclaration): boolean { @@ -28141,7 +36170,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return true; } - const containsUndefined = !!(getTypeFacts(checkDeclarationInitializer(declaration, CheckMode.Normal)) & TypeFacts.IsUndefined); + const containsUndefined = + !!(getTypeFacts(checkDeclarationInitializer(declaration, CheckMode.Normal)) & TypeFacts.IsUndefined); if (!popTypeResolution()) { reportCircularityError(declaration.symbol); @@ -28156,11 +36186,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { /** remove undefined from the annotated type of a parameter when there is an initializer (that doesn't include undefined) */ function removeOptionalityFromDeclaredType(declaredType: Type, declaration: VariableLikeDeclaration): Type { - const removeUndefined = strictNullChecks && - declaration.kind === SyntaxKind.Parameter && - declaration.initializer && - getTypeFacts(declaredType) & TypeFacts.IsUndefined && - !parameterInitializerContainsUndefined(declaration); + const removeUndefined = strictNullChecks + && declaration.kind === SyntaxKind.Parameter + && declaration.initializer + && getTypeFacts(declaredType) & TypeFacts.IsUndefined + && !parameterInitializerContainsUndefined(declaration); return removeUndefined ? getTypeWithFacts(declaredType, TypeFacts.NEUndefined) : declaredType; } @@ -28170,23 +36200,27 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // In an element access obj[x], we consider obj to be in a constraint position, except when obj is of // a generic type without a nullable constraint and x is a generic type. This is because when both obj // and x are of generic types T and K, we want the resulting type to be T[K]. - return parent.kind === SyntaxKind.PropertyAccessExpression || - parent.kind === SyntaxKind.QualifiedName || - parent.kind === SyntaxKind.CallExpression && (parent as CallExpression).expression === node || - parent.kind === SyntaxKind.ElementAccessExpression && (parent as ElementAccessExpression).expression === node && - !(someType(type, isGenericTypeWithoutNullableConstraint) && isGenericIndexType(getTypeOfExpression((parent as ElementAccessExpression).argumentExpression))); + return parent.kind === SyntaxKind.PropertyAccessExpression + || parent.kind === SyntaxKind.QualifiedName + || parent.kind === SyntaxKind.CallExpression && (parent as CallExpression).expression === node + || parent.kind === SyntaxKind.ElementAccessExpression + && (parent as ElementAccessExpression).expression === node + && !(someType(type, isGenericTypeWithoutNullableConstraint) + && isGenericIndexType(getTypeOfExpression((parent as ElementAccessExpression).argumentExpression))); } function isGenericTypeWithUnionConstraint(type: Type): boolean { - return type.flags & TypeFlags.Intersection ? - some((type as IntersectionType).types, isGenericTypeWithUnionConstraint) : - !!(type.flags & TypeFlags.Instantiable && getBaseConstraintOrType(type).flags & (TypeFlags.Nullable | TypeFlags.Union)); + return type.flags & TypeFlags.Intersection + ? some((type as IntersectionType).types, isGenericTypeWithUnionConstraint) + : !!(type.flags & TypeFlags.Instantiable + && getBaseConstraintOrType(type).flags & (TypeFlags.Nullable | TypeFlags.Union)); } function isGenericTypeWithoutNullableConstraint(type: Type): boolean { - return type.flags & TypeFlags.Intersection ? - some((type as IntersectionType).types, isGenericTypeWithoutNullableConstraint) : - !!(type.flags & TypeFlags.Instantiable && !maybeTypeOfKind(getBaseConstraintOrType(type), TypeFlags.Nullable)); + return type.flags & TypeFlags.Intersection + ? some((type as IntersectionType).types, isGenericTypeWithoutNullableConstraint) + : !!(type.flags & TypeFlags.Instantiable + && !maybeTypeOfKind(getBaseConstraintOrType(type), TypeFlags.Nullable)); } function hasContextualTypeWithNoGenericTypes(node: Node, checkMode: CheckMode | undefined) { @@ -28194,10 +36228,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // element's tag name, so we exclude that here to avoid circularities. // If check mode has `CheckMode.RestBindingElement`, we skip binding pattern contextual types, // as we want the type of a rest element to be generic when possible. - const contextualType = (isIdentifier(node) || isPropertyAccessExpression(node) || isElementAccessExpression(node)) && - !((isJsxOpeningElement(node.parent) || isJsxSelfClosingElement(node.parent)) && node.parent.tagName === node) && - (checkMode && checkMode & CheckMode.RestBindingElement ? - getContextualType(node, ContextFlags.SkipBindingPatterns) + const contextualType = + (isIdentifier(node) || isPropertyAccessExpression(node) || isElementAccessExpression(node)) + && !((isJsxOpeningElement(node.parent) || isJsxSelfClosingElement(node.parent)) + && node.parent.tagName === node) + && (checkMode && checkMode & CheckMode.RestBindingElement + ? getContextualType(node, ContextFlags.SkipBindingPatterns) : getContextualType(node, /*contextFlags*/ undefined)); return contextualType && !isGenericType(contextualType); } @@ -28210,9 +36246,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // control flow analysis an opportunity to narrow it further. For example, for a reference of a type // parameter type 'T extends string | undefined' with a contextual type 'string', we substitute // 'string | undefined' to give control flow analysis the opportunity to narrow to type 'string'. - const substituteConstraints = !(checkMode && checkMode & CheckMode.Inferential) && - someType(type, isGenericTypeWithUnionConstraint) && - (isConstraintPosition(type, reference) || hasContextualTypeWithNoGenericTypes(reference, checkMode)); + const substituteConstraints = !(checkMode && checkMode & CheckMode.Inferential) + && someType(type, isGenericTypeWithUnionConstraint) + && (isConstraintPosition(type, reference) || hasContextualTypeWithNoGenericTypes(reference, checkMode)); return substituteConstraints ? mapType(type, getBaseConstraintOrType) : type; } @@ -28238,14 +36274,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } if (isNonLocalAlias(symbol, /*excludes*/ SymbolFlags.Value) && !isInTypeQuery(location)) { const target = resolveAlias(symbol); - if (getSymbolFlags(symbol, /*excludeTypeOnlyMeanings*/ true) & (SymbolFlags.Value | SymbolFlags.ExportValue)) { + if ( + getSymbolFlags(symbol, /*excludeTypeOnlyMeanings*/ true) & (SymbolFlags.Value | SymbolFlags.ExportValue) + ) { // An alias resolving to a const enum cannot be elided if (1) 'isolatedModules' is enabled // (because the const enum value will not be inlined), or if (2) the alias is an export // of a const enum declaration that will be preserved. if ( - getIsolatedModules(compilerOptions) || - shouldPreserveConstEnums(compilerOptions) && isExportOrExportExpression(location) || - !isConstEnumOrConstEnumOnlyModule(getExportSymbolOfValueSymbolIfExported(target)) + getIsolatedModules(compilerOptions) + || shouldPreserveConstEnums(compilerOptions) && isExportOrExportExpression(location) + || !isConstEnumOrConstEnumOnlyModule(getExportSymbolOfValueSymbolIfExported(target)) ) { markAliasSymbolAsReferenced(symbol); } @@ -28283,18 +36321,34 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // the binding pattern AST instance for '{ kind, payload }' as a pseudo-reference and narrow this reference // as if it occurred in the specified location. We then recompute the narrowed binding element type by // destructuring from the narrowed parent type. - if (isBindingElement(declaration) && !declaration.initializer && !declaration.dotDotDotToken && declaration.parent.elements.length >= 2) { + if ( + isBindingElement(declaration) && !declaration.initializer && !declaration.dotDotDotToken + && declaration.parent.elements.length >= 2 + ) { const parent = declaration.parent.parent; - if (parent.kind === SyntaxKind.VariableDeclaration && getCombinedNodeFlagsCached(declaration) & NodeFlags.Constant || parent.kind === SyntaxKind.Parameter) { + if ( + parent.kind === SyntaxKind.VariableDeclaration + && getCombinedNodeFlagsCached(declaration) & NodeFlags.Constant + || parent.kind === SyntaxKind.Parameter + ) { const links = getNodeLinks(parent); if (!(links.flags & NodeCheckFlags.InCheckIdentifier)) { links.flags |= NodeCheckFlags.InCheckIdentifier; const parentType = getTypeForBindingElementParent(parent, CheckMode.Normal); const parentTypeConstraint = parentType && mapType(parentType, getBaseConstraintOrType); links.flags &= ~NodeCheckFlags.InCheckIdentifier; - if (parentTypeConstraint && parentTypeConstraint.flags & TypeFlags.Union && !(parent.kind === SyntaxKind.Parameter && isSymbolAssigned(symbol))) { + if ( + parentTypeConstraint && parentTypeConstraint.flags & TypeFlags.Union + && !(parent.kind === SyntaxKind.Parameter && isSymbolAssigned(symbol)) + ) { const pattern = declaration.parent; - const narrowedType = getFlowTypeOfReference(pattern, parentTypeConstraint, parentTypeConstraint, /*flowContainer*/ undefined, location.flowNode); + const narrowedType = getFlowTypeOfReference( + pattern, + parentTypeConstraint, + parentTypeConstraint, + /*flowContainer*/ undefined, + location.flowNode, + ); if (narrowedType.flags & TypeFlags.Never) { return neverType; } @@ -28323,14 +36377,33 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // the arrow function AST node for '(kind, payload) => ...' as a pseudo-reference and narrow this reference as // if it occurred in the specified location. We then recompute the narrowed parameter type by indexing into the // narrowed tuple type. - if (isParameter(declaration) && !declaration.type && !declaration.initializer && !declaration.dotDotDotToken) { + if ( + isParameter(declaration) && !declaration.type && !declaration.initializer && !declaration.dotDotDotToken + ) { const func = declaration.parent; if (func.parameters.length >= 2 && isContextSensitiveFunctionOrObjectLiteralMethod(func)) { const contextualSignature = getContextualSignature(func); - if (contextualSignature && contextualSignature.parameters.length === 1 && signatureHasRestParameter(contextualSignature)) { - const restType = getReducedApparentType(instantiateType(getTypeOfSymbol(contextualSignature.parameters[0]), getInferenceContext(func)?.nonFixingMapper)); - if (restType.flags & TypeFlags.Union && everyType(restType, isTupleType) && !isSymbolAssigned(symbol)) { - const narrowedType = getFlowTypeOfReference(func, restType, restType, /*flowContainer*/ undefined, location.flowNode); + if ( + contextualSignature && contextualSignature.parameters.length === 1 + && signatureHasRestParameter(contextualSignature) + ) { + const restType = getReducedApparentType( + instantiateType( + getTypeOfSymbol(contextualSignature.parameters[0]), + getInferenceContext(func)?.nonFixingMapper, + ), + ); + if ( + restType.flags & TypeFlags.Union && everyType(restType, isTupleType) + && !isSymbolAssigned(symbol) + ) { + const narrowedType = getFlowTypeOfReference( + func, + restType, + restType, + /*flowContainer*/ undefined, + location.flowNode, + ); const index = func.parameters.indexOf(declaration) - (getThisParameter(func) ? 1 : 0); return getIndexedAccessType(narrowedType, getNumberLiteralType(index)); } @@ -28366,10 +36439,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const container = getContainingFunction(node)!; if (languageVersion < ScriptTarget.ES2015) { if (container.kind === SyntaxKind.ArrowFunction) { - error(node, Diagnostics.The_arguments_object_cannot_be_referenced_in_an_arrow_function_in_ES3_and_ES5_Consider_using_a_standard_function_expression); + error( + node, + Diagnostics + .The_arguments_object_cannot_be_referenced_in_an_arrow_function_in_ES3_and_ES5_Consider_using_a_standard_function_expression, + ); } else if (hasSyntacticModifier(container, ModifierFlags.Async)) { - error(node, Diagnostics.The_arguments_object_cannot_be_referenced_in_an_async_function_or_method_in_ES3_and_ES5_Consider_using_a_standard_function_or_method); + error( + node, + Diagnostics + .The_arguments_object_cannot_be_referenced_in_an_async_function_or_method_in_ES3_and_ES5_Consider_using_a_standard_function_or_method, + ); } } @@ -28383,7 +36464,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const localOrExportSymbol = getExportSymbolOfValueSymbolIfExported(symbol); const targetSymbol = resolveAliasWithDeprecationCheck(localOrExportSymbol, node); - if (isDeprecatedSymbol(targetSymbol) && isUncalledFunctionReference(node, targetSymbol) && targetSymbol.declarations) { + if ( + isDeprecatedSymbol(targetSymbol) && isUncalledFunctionReference(node, targetSymbol) + && targetSymbol.declarations + ) { addDeprecatedSuggestion(node, targetSymbol.declarations, node.escapedText as string); } @@ -28393,9 +36477,17 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // class name is double-bound, we must ensure we mark references to the class name so that we can // emit an alias to the class later. if (isClassLike(declaration) && declaration.name !== node) { - let container = getThisContainer(node, /*includeArrowFunctions*/ false, /*includeClassComputedPropertyName*/ false); + let container = getThisContainer( + node, + /*includeArrowFunctions*/ false, + /*includeClassComputedPropertyName*/ false, + ); while (container.kind !== SyntaxKind.SourceFile && container.parent !== declaration) { - container = getThisContainer(container, /*includeArrowFunctions*/ false, /*includeClassComputedPropertyName*/ false); + container = getThisContainer( + container, + /*includeArrowFunctions*/ false, + /*includeClassComputedPropertyName*/ false, + ); } if (container.kind !== SyntaxKind.SourceFile) { @@ -28413,14 +36505,19 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (assignmentKind) { if ( - !(localOrExportSymbol.flags & SymbolFlags.Variable) && - !(isInJSFile(node) && localOrExportSymbol.flags & SymbolFlags.ValueModule) + !(localOrExportSymbol.flags & SymbolFlags.Variable) + && !(isInJSFile(node) && localOrExportSymbol.flags & SymbolFlags.ValueModule) ) { - const assignmentError = localOrExportSymbol.flags & SymbolFlags.Enum ? Diagnostics.Cannot_assign_to_0_because_it_is_an_enum - : localOrExportSymbol.flags & SymbolFlags.Class ? Diagnostics.Cannot_assign_to_0_because_it_is_a_class - : localOrExportSymbol.flags & SymbolFlags.Module ? Diagnostics.Cannot_assign_to_0_because_it_is_a_namespace - : localOrExportSymbol.flags & SymbolFlags.Function ? Diagnostics.Cannot_assign_to_0_because_it_is_a_function - : localOrExportSymbol.flags & SymbolFlags.Alias ? Diagnostics.Cannot_assign_to_0_because_it_is_an_import + const assignmentError = localOrExportSymbol.flags & SymbolFlags.Enum + ? Diagnostics.Cannot_assign_to_0_because_it_is_an_enum + : localOrExportSymbol.flags & SymbolFlags.Class + ? Diagnostics.Cannot_assign_to_0_because_it_is_a_class + : localOrExportSymbol.flags & SymbolFlags.Module + ? Diagnostics.Cannot_assign_to_0_because_it_is_a_namespace + : localOrExportSymbol.flags & SymbolFlags.Function + ? Diagnostics.Cannot_assign_to_0_because_it_is_a_function + : localOrExportSymbol.flags & SymbolFlags.Alias + ? Diagnostics.Cannot_assign_to_0_because_it_is_an_import : Diagnostics.Cannot_assign_to_0_because_it_is_not_a_variable; error(node, assignmentError, symbolToString(symbol)); @@ -28431,7 +36528,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { error(node, Diagnostics.Cannot_assign_to_0_because_it_is_a_constant, symbolToString(symbol)); } else { - error(node, Diagnostics.Cannot_assign_to_0_because_it_is_a_read_only_property, symbolToString(symbol)); + error( + node, + Diagnostics.Cannot_assign_to_0_because_it_is_a_read_only_property, + symbolToString(symbol), + ); } return errorType; } @@ -28466,7 +36567,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const declarationContainer = getControlFlowContainer(declaration); let flowContainer = getControlFlowContainer(node); const isOuterVariable = flowContainer !== declarationContainer; - const isSpreadDestructuringAssignmentTarget = node.parent && node.parent.parent && isSpreadAssignment(node.parent) && isDestructuringAssignmentTarget(node.parent.parent); + const isSpreadDestructuringAssignmentTarget = node.parent && node.parent.parent + && isSpreadAssignment(node.parent) && isDestructuringAssignmentTarget(node.parent.parent); const isModuleExports = symbol.flags & SymbolFlags.ModuleExports; const typeIsAutomatic = type === autoType || type === autoArrayType; const isAutomaticTypeInNonNull = typeIsAutomatic && node.parent.kind === SyntaxKind.NonNullExpression; @@ -28474,34 +36576,53 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // a const variable or parameter from an outer function, we extend the origin of the control flow // analysis to include the immediately enclosing function. while ( - flowContainer !== declarationContainer && (flowContainer.kind === SyntaxKind.FunctionExpression || - flowContainer.kind === SyntaxKind.ArrowFunction || isObjectLiteralOrClassExpressionMethodOrAccessor(flowContainer)) && - (isConstantVariable(localOrExportSymbol) && type !== autoArrayType || isParameter && !isSymbolAssigned(localOrExportSymbol)) + flowContainer !== declarationContainer && (flowContainer.kind === SyntaxKind.FunctionExpression + || flowContainer.kind === SyntaxKind.ArrowFunction + || isObjectLiteralOrClassExpressionMethodOrAccessor(flowContainer)) + && (isConstantVariable(localOrExportSymbol) && type !== autoArrayType + || isParameter && !isSymbolAssigned(localOrExportSymbol)) ) { flowContainer = getControlFlowContainer(flowContainer); } // We only look for uninitialized variables in strict null checking mode, and only when we can analyze // the entire control flow graph from the variable's declaration (i.e. when the flow container and // declaration container are the same). - const assumeInitialized = isParameter || isAlias || isOuterVariable || isSpreadDestructuringAssignmentTarget || isModuleExports || isSameScopedBindingElement(node, declaration) || - type !== autoType && type !== autoArrayType && (!strictNullChecks || (type.flags & (TypeFlags.AnyOrUnknown | TypeFlags.Void)) !== 0 || - isInTypeQuery(node) || isInAmbientOrTypeNode(node) || node.parent.kind === SyntaxKind.ExportSpecifier) || - node.parent.kind === SyntaxKind.NonNullExpression || - declaration.kind === SyntaxKind.VariableDeclaration && (declaration as VariableDeclaration).exclamationToken || - declaration.flags & NodeFlags.Ambient; - const initialType = isAutomaticTypeInNonNull ? undefinedType : - assumeInitialized ? (isParameter ? removeOptionalityFromDeclaredType(type, declaration as VariableLikeDeclaration) : type) : - typeIsAutomatic ? undefinedType : getOptionalType(type); - const flowType = isAutomaticTypeInNonNull ? getNonNullableType(getFlowTypeOfReference(node, type, initialType, flowContainer)) : - getFlowTypeOfReference(node, type, initialType, flowContainer); + const assumeInitialized = isParameter || isAlias || isOuterVariable || isSpreadDestructuringAssignmentTarget + || isModuleExports || isSameScopedBindingElement(node, declaration) + || type !== autoType && type !== autoArrayType + && (!strictNullChecks || (type.flags & (TypeFlags.AnyOrUnknown | TypeFlags.Void)) !== 0 + || isInTypeQuery(node) || isInAmbientOrTypeNode(node) + || node.parent.kind === SyntaxKind.ExportSpecifier) + || node.parent.kind === SyntaxKind.NonNullExpression + || declaration.kind === SyntaxKind.VariableDeclaration + && (declaration as VariableDeclaration).exclamationToken + || declaration.flags & NodeFlags.Ambient; + const initialType = isAutomaticTypeInNonNull ? undefinedType + : assumeInitialized + ? (isParameter ? removeOptionalityFromDeclaredType(type, declaration as VariableLikeDeclaration) : type) + : typeIsAutomatic ? undefinedType : getOptionalType(type); + const flowType = isAutomaticTypeInNonNull + ? getNonNullableType(getFlowTypeOfReference(node, type, initialType, flowContainer)) + : getFlowTypeOfReference(node, type, initialType, flowContainer); // A variable is considered uninitialized when it is possible to analyze the entire control flow graph // from declaration to use, and when the variable's declared type doesn't include undefined but the // control flow based type does include undefined. if (!isEvolvingArrayOperationTarget(node) && (type === autoType || type === autoArrayType)) { if (flowType === autoType || flowType === autoArrayType) { if (noImplicitAny) { - error(getNameOfDeclaration(declaration), Diagnostics.Variable_0_implicitly_has_type_1_in_some_locations_where_its_type_cannot_be_determined, symbolToString(symbol), typeToString(flowType)); - error(node, Diagnostics.Variable_0_implicitly_has_an_1_type, symbolToString(symbol), typeToString(flowType)); + error( + getNameOfDeclaration(declaration), + Diagnostics + .Variable_0_implicitly_has_type_1_in_some_locations_where_its_type_cannot_be_determined, + symbolToString(symbol), + typeToString(flowType), + ); + error( + node, + Diagnostics.Variable_0_implicitly_has_an_1_type, + symbolToString(symbol), + typeToString(flowType), + ); } return convertAutoToAny(flowType); } @@ -28543,25 +36664,35 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function isInsideFunctionOrInstancePropertyInitializer(node: Node, threshold: Node): boolean { return !!findAncestor(node, n => n === threshold ? "quit" : isFunctionLike(n) || ( - n.parent && isPropertyDeclaration(n.parent) && !hasStaticModifier(n.parent) && n.parent.initializer === n + n.parent && isPropertyDeclaration(n.parent) && !hasStaticModifier(n.parent) + && n.parent.initializer === n )); } function getPartOfForStatementContainingNode(node: Node, container: ForStatement) { - return findAncestor(node, n => n === container ? "quit" : n === container.initializer || n === container.condition || n === container.incrementor || n === container.statement); + return findAncestor( + node, + n => n === container ? "quit" + : n === container.initializer || n === container.condition || n === container.incrementor + || n === container.statement, + ); } function getEnclosingIterationStatement(node: Node): Node | undefined { - return findAncestor(node, n => (!n || nodeStartsNewLexicalEnvironment(n)) ? "quit" : isIterationStatement(n, /*lookInLabeledStatements*/ false)); + return findAncestor( + node, + n => (!n || nodeStartsNewLexicalEnvironment(n)) ? "quit" + : isIterationStatement(n, /*lookInLabeledStatements*/ false), + ); } function checkNestedBlockScopedBinding(node: Identifier, symbol: Symbol): void { if ( - languageVersion >= ScriptTarget.ES2015 || - (symbol.flags & (SymbolFlags.BlockScopedVariable | SymbolFlags.Class)) === 0 || - !symbol.valueDeclaration || - isSourceFile(symbol.valueDeclaration) || - symbol.valueDeclaration.parent.kind === SyntaxKind.CatchClause + languageVersion >= ScriptTarget.ES2015 + || (symbol.flags & (SymbolFlags.BlockScopedVariable | SymbolFlags.Class)) === 0 + || !symbol.valueDeclaration + || isSourceFile(symbol.valueDeclaration) + || symbol.valueDeclaration.parent.kind === SyntaxKind.CatchClause ) { return; } @@ -28587,7 +36718,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const links = getNodeLinks(part); links.flags |= NodeCheckFlags.ContainsCapturedBlockScopeBinding; - const capturedBindings = links.capturedBlockScopeBindings || (links.capturedBlockScopeBindings = []); + const capturedBindings = links.capturedBlockScopeBindings + || (links.capturedBlockScopeBindings = []); pushIfUnique(capturedBindings, symbol); if (part === container.initializer) { @@ -28597,7 +36729,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } if (capturesBlockScopeBindingInLoopBody) { - getNodeLinks(enclosingIterationStatement).flags |= NodeCheckFlags.LoopWithCapturedBlockScopedBinding; + getNodeLinks(enclosingIterationStatement).flags |= + NodeCheckFlags.LoopWithCapturedBlockScopedBinding; } } @@ -28605,7 +36738,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // if body of ForStatement will be converted to function then we'll need a extra machinery to propagate reassigned values back. if (isForStatement(container)) { const varDeclList = getAncestor(symbol.valueDeclaration, SyntaxKind.VariableDeclarationList); - if (varDeclList && varDeclList.parent === container && isAssignedInBodyOfForStatement(node, container)) { + if ( + varDeclList && varDeclList.parent === container && isAssignedInBodyOfForStatement(node, container) + ) { getNodeLinks(symbol.valueDeclaration).flags |= NodeCheckFlags.NeedsLoopOutParameter; } } @@ -28636,7 +36771,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (isAssignmentTarget(current)) { isAssigned = true; } - else if ((current.parent.kind === SyntaxKind.PrefixUnaryExpression || current.parent.kind === SyntaxKind.PostfixUnaryExpression)) { + else if ( + (current.parent.kind === SyntaxKind.PrefixUnaryExpression + || current.parent.kind === SyntaxKind.PostfixUnaryExpression) + ) { const expr = current.parent as PrefixUnaryExpression | PostfixUnaryExpression; isAssigned = expr.operator === SyntaxKind.PlusPlusToken || expr.operator === SyntaxKind.MinusMinusToken; } @@ -28662,9 +36800,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function findFirstSuperCall(node: Node): SuperCall | undefined { - return isSuperCall(node) ? node : - isFunctionLike(node) ? undefined : - forEachChild(node, findFirstSuperCall); + return isSuperCall(node) ? node + : isFunctionLike(node) ? undefined + : forEachChild(node, findFirstSuperCall); } /** @@ -28695,8 +36833,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function checkThisInStaticClassFieldInitializerInDecoratedClass(thisExpression: Node, container: Node) { if ( - isPropertyDeclaration(container) && hasStaticModifier(container) && legacyDecorators && - container.initializer && textRangeContainsPositionInclusive(container.initializer, thisExpression.pos) && hasDecorators(container.parent) + isPropertyDeclaration(container) && hasStaticModifier(container) && legacyDecorators + && container.initializer && textRangeContainsPositionInclusive(container.initializer, thisExpression.pos) + && hasDecorators(container.parent) ) { error(thisExpression, Diagnostics.Cannot_use_this_in_a_static_property_initializer_of_a_decorated_class); } @@ -28706,12 +36845,20 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const isNodeInTypeQuery = isInTypeQuery(node); // Stop at the first arrow function so that we can // tell whether 'this' needs to be captured. - let container = getThisContainer(node, /*includeArrowFunctions*/ true, /*includeClassComputedPropertyName*/ true); + let container = getThisContainer( + node, + /*includeArrowFunctions*/ true, + /*includeClassComputedPropertyName*/ true, + ); let capturedByArrowFunction = false; let thisInComputedPropertyName = false; if (container.kind === SyntaxKind.Constructor) { - checkThisBeforeSuper(node, container, Diagnostics.super_must_be_called_before_accessing_this_in_the_constructor_of_a_derived_class); + checkThisBeforeSuper( + node, + container, + Diagnostics.super_must_be_called_before_accessing_this_in_the_constructor_of_a_derived_class, + ); } while (true) { @@ -28722,7 +36869,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } if (container.kind === SyntaxKind.ComputedPropertyName) { - container = getThisContainer(container, !capturedByArrowFunction, /*includeClassComputedPropertyName*/ false); + container = getThisContainer( + container, + !capturedByArrowFunction, + /*includeClassComputedPropertyName*/ false, + ); thisInComputedPropertyName = true; continue; } @@ -28766,11 +36917,20 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } else if (!type) { // With noImplicitThis, functions may not reference 'this' if it has type 'any' - const diag = error(node, Diagnostics.this_implicitly_has_type_any_because_it_does_not_have_a_type_annotation); + const diag = error( + node, + Diagnostics.this_implicitly_has_type_any_because_it_does_not_have_a_type_annotation, + ); if (!isSourceFile(container)) { const outsideThis = tryGetThisTypeAt(container); if (outsideThis && outsideThis !== globalThisType) { - addRelatedInfo(diag, createDiagnosticForNode(container, Diagnostics.An_outer_value_of_this_is_shadowed_by_this_container)); + addRelatedInfo( + diag, + createDiagnosticForNode( + container, + Diagnostics.An_outer_value_of_this_is_shadowed_by_this_container, + ), + ); } } } @@ -28778,13 +36938,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return type || anyType; } - function tryGetThisTypeAt(node: Node, includeGlobalThis = true, container = getThisContainer(node, /*includeArrowFunctions*/ false, /*includeClassComputedPropertyName*/ false)): Type | undefined { + function tryGetThisTypeAt( + node: Node, + includeGlobalThis = true, + container = getThisContainer(node, /*includeArrowFunctions*/ false, /*includeClassComputedPropertyName*/ false), + ): Type | undefined { const isInJS = isInJSFile(node); if ( - isFunctionLike(container) && - (!isInParameterInitializerBeforeContainingFunction(node) || getThisParameter(container)) + isFunctionLike(container) + && (!isInParameterInitializerBeforeContainingFunction(node) || getThisParameter(container)) ) { - let thisType = getThisTypeOfDeclaration(container) || isInJS && getTypeForThisExpressionFromJSDoc(container); + let thisType = getThisTypeOfDeclaration(container) + || isInJS && getTypeForThisExpressionFromJSDoc(container); // Note: a parameter initializer should refer to class-this unless function-this is explicitly annotated. // If this is a function in a JS file, it might be a class method. if (!thisType) { @@ -28808,7 +36973,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (isClassLike(container.parent)) { const symbol = getSymbolOfDeclaration(container.parent); - const type = isStatic(container) ? getTypeOfSymbol(symbol) : (getDeclaredTypeOfSymbol(symbol) as InterfaceType).thisType!; + const type = isStatic(container) ? getTypeOfSymbol(symbol) + : (getDeclaredTypeOfSymbol(symbol) as InterfaceType).thisType!; return getFlowTypeOfReference(node, type); } @@ -28829,7 +36995,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function getExplicitThisType(node: Expression) { - const container = getThisContainer(node, /*includeArrowFunctions*/ false, /*includeClassComputedPropertyName*/ false); + const container = getThisContainer( + node, + /*includeArrowFunctions*/ false, + /*includeClassComputedPropertyName*/ false, + ); if (isFunctionLike(container)) { const signature = getSignatureFromDeclaration(container); if (signature.thisParameter) { @@ -28838,16 +37008,17 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } if (isClassLike(container.parent)) { const symbol = getSymbolOfDeclaration(container.parent); - return isStatic(container) ? getTypeOfSymbol(symbol) : (getDeclaredTypeOfSymbol(symbol) as InterfaceType).thisType!; + return isStatic(container) ? getTypeOfSymbol(symbol) + : (getDeclaredTypeOfSymbol(symbol) as InterfaceType).thisType!; } } function getClassNameFromPrototypeMethod(container: Node) { // Check if it's the RHS of a x.prototype.y = function [name]() { .... } if ( - container.kind === SyntaxKind.FunctionExpression && - isBinaryExpression(container.parent) && - getAssignmentDeclarationKind(container.parent) === AssignmentDeclarationKind.PrototypeProperty + container.kind === SyntaxKind.FunctionExpression + && isBinaryExpression(container.parent) + && getAssignmentDeclarationKind(container.parent) === AssignmentDeclarationKind.PrototypeProperty ) { // Get the 'x' of 'x.prototype.y = container' return ((container.parent // x.prototype.y = container @@ -28857,20 +37028,20 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } // x.prototype = { method() { } } else if ( - container.kind === SyntaxKind.MethodDeclaration && - container.parent.kind === SyntaxKind.ObjectLiteralExpression && - isBinaryExpression(container.parent.parent) && - getAssignmentDeclarationKind(container.parent.parent) === AssignmentDeclarationKind.Prototype + container.kind === SyntaxKind.MethodDeclaration + && container.parent.kind === SyntaxKind.ObjectLiteralExpression + && isBinaryExpression(container.parent.parent) + && getAssignmentDeclarationKind(container.parent.parent) === AssignmentDeclarationKind.Prototype ) { return (container.parent.parent.left as PropertyAccessExpression).expression; } // x.prototype = { method: function() { } } else if ( - container.kind === SyntaxKind.FunctionExpression && - container.parent.kind === SyntaxKind.PropertyAssignment && - container.parent.parent.kind === SyntaxKind.ObjectLiteralExpression && - isBinaryExpression(container.parent.parent.parent) && - getAssignmentDeclarationKind(container.parent.parent.parent) === AssignmentDeclarationKind.Prototype + container.kind === SyntaxKind.FunctionExpression + && container.parent.kind === SyntaxKind.PropertyAssignment + && container.parent.parent.kind === SyntaxKind.ObjectLiteralExpression + && isBinaryExpression(container.parent.parent.parent) + && getAssignmentDeclarationKind(container.parent.parent.parent) === AssignmentDeclarationKind.Prototype ) { return (container.parent.parent.parent.left as PropertyAccessExpression).expression; } @@ -28878,14 +37049,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // Object.defineProperty(x, "method", { set: (x: () => void) => void }); // Object.defineProperty(x, "method", { get: () => function() { }) }); else if ( - container.kind === SyntaxKind.FunctionExpression && - isPropertyAssignment(container.parent) && - isIdentifier(container.parent.name) && - (container.parent.name.escapedText === "value" || container.parent.name.escapedText === "get" || container.parent.name.escapedText === "set") && - isObjectLiteralExpression(container.parent.parent) && - isCallExpression(container.parent.parent.parent) && - container.parent.parent.parent.arguments[2] === container.parent.parent && - getAssignmentDeclarationKind(container.parent.parent.parent) === AssignmentDeclarationKind.ObjectDefinePrototypeProperty + container.kind === SyntaxKind.FunctionExpression + && isPropertyAssignment(container.parent) + && isIdentifier(container.parent.name) + && (container.parent.name.escapedText === "value" || container.parent.name.escapedText === "get" + || container.parent.name.escapedText === "set") + && isObjectLiteralExpression(container.parent.parent) + && isCallExpression(container.parent.parent.parent) + && container.parent.parent.parent.arguments[2] === container.parent.parent + && getAssignmentDeclarationKind(container.parent.parent.parent) + === AssignmentDeclarationKind.ObjectDefinePrototypeProperty ) { return (container.parent.parent.parent.arguments[0] as PropertyAccessExpression).expression; } @@ -28893,13 +37066,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // Object.defineProperty(x, "method", { set(x: () => void) {} }); // Object.defineProperty(x, "method", { get() { return () => {} } }); else if ( - isMethodDeclaration(container) && - isIdentifier(container.name) && - (container.name.escapedText === "value" || container.name.escapedText === "get" || container.name.escapedText === "set") && - isObjectLiteralExpression(container.parent) && - isCallExpression(container.parent.parent) && - container.parent.parent.arguments[2] === container.parent && - getAssignmentDeclarationKind(container.parent.parent) === AssignmentDeclarationKind.ObjectDefinePrototypeProperty + isMethodDeclaration(container) + && isIdentifier(container.name) + && (container.name.escapedText === "value" || container.name.escapedText === "get" + || container.name.escapedText === "set") + && isObjectLiteralExpression(container.parent) + && isCallExpression(container.parent.parent) + && container.parent.parent.arguments[2] === container.parent + && getAssignmentDeclarationKind(container.parent.parent) + === AssignmentDeclarationKind.ObjectDefinePrototypeProperty ) { return (container.parent.parent.arguments[0] as PropertyAccessExpression).expression; } @@ -28917,11 +37092,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function isInConstructorArgumentInitializer(node: Node, constructorDecl: Node): boolean { - return !!findAncestor(node, n => isFunctionLikeDeclaration(n) ? "quit" : n.kind === SyntaxKind.Parameter && n.parent === constructorDecl); + return !!findAncestor( + node, + n => isFunctionLikeDeclaration(n) ? "quit" + : n.kind === SyntaxKind.Parameter && n.parent === constructorDecl, + ); } function checkSuperExpression(node: Node): Type { - const isCallExpression = node.parent.kind === SyntaxKind.CallExpression && (node.parent as CallExpression).expression === node; + const isCallExpression = node.parent.kind === SyntaxKind.CallExpression + && (node.parent as CallExpression).expression === node; const immediateContainer = getSuperContainer(node, /*stopOnFunctions*/ true); let container = immediateContainer; @@ -28946,32 +37126,55 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // class B { // [super.foo()]() {} // } - const current = findAncestor(node, n => n === container ? "quit" : n.kind === SyntaxKind.ComputedPropertyName); + const current = findAncestor( + node, + n => n === container ? "quit" : n.kind === SyntaxKind.ComputedPropertyName, + ); if (current && current.kind === SyntaxKind.ComputedPropertyName) { error(node, Diagnostics.super_cannot_be_referenced_in_a_computed_property_name); } else if (isCallExpression) { - error(node, Diagnostics.Super_calls_are_not_permitted_outside_constructors_or_in_nested_functions_inside_constructors); + error( + node, + Diagnostics + .Super_calls_are_not_permitted_outside_constructors_or_in_nested_functions_inside_constructors, + ); } - else if (!container || !container.parent || !(isClassLike(container.parent) || container.parent.kind === SyntaxKind.ObjectLiteralExpression)) { - error(node, Diagnostics.super_can_only_be_referenced_in_members_of_derived_classes_or_object_literal_expressions); + else if ( + !container || !container.parent + || !(isClassLike(container.parent) || container.parent.kind === SyntaxKind.ObjectLiteralExpression) + ) { + error( + node, + Diagnostics + .super_can_only_be_referenced_in_members_of_derived_classes_or_object_literal_expressions, + ); } else { - error(node, Diagnostics.super_property_access_is_permitted_only_in_a_constructor_member_function_or_member_accessor_of_a_derived_class); + error( + node, + Diagnostics + .super_property_access_is_permitted_only_in_a_constructor_member_function_or_member_accessor_of_a_derived_class, + ); } return errorType; } if (!isCallExpression && immediateContainer!.kind === SyntaxKind.Constructor) { - checkThisBeforeSuper(node, container, Diagnostics.super_must_be_called_before_accessing_a_property_of_super_in_the_constructor_of_a_derived_class); + checkThisBeforeSuper( + node, + container, + Diagnostics + .super_must_be_called_before_accessing_a_property_of_super_in_the_constructor_of_a_derived_class, + ); } if (isStatic(container) || isCallExpression) { nodeCheckFlag = NodeCheckFlags.SuperStatic; if ( - !isCallExpression && - languageVersion >= ScriptTarget.ES2015 && languageVersion <= ScriptTarget.ES2021 && - (isPropertyDeclaration(container) || isClassStaticBlockDeclaration(container)) + !isCallExpression + && languageVersion >= ScriptTarget.ES2015 && languageVersion <= ScriptTarget.ES2021 + && (isPropertyDeclaration(container) || isClassStaticBlockDeclaration(container)) ) { // for `super.x` or `super[x]` in a static initializer, mark all enclosing // block scope containers so that we can report potential collisions with @@ -29066,7 +37269,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (container.parent.kind === SyntaxKind.ObjectLiteralExpression) { if (languageVersion < ScriptTarget.ES2015) { - error(node, Diagnostics.super_is_only_allowed_in_members_of_object_literal_expressions_when_option_target_is_ES2015_or_higher); + error( + node, + Diagnostics + .super_is_only_allowed_in_members_of_object_literal_expressions_when_option_target_is_ES2015_or_higher, + ); return errorType; } else { @@ -29113,21 +37320,21 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // topmost container must be something that is directly nested in the class declaration\object literal expression if (isClassLike(container.parent) || container.parent.kind === SyntaxKind.ObjectLiteralExpression) { if (isStatic(container)) { - return container.kind === SyntaxKind.MethodDeclaration || - container.kind === SyntaxKind.MethodSignature || - container.kind === SyntaxKind.GetAccessor || - container.kind === SyntaxKind.SetAccessor || - container.kind === SyntaxKind.PropertyDeclaration || - container.kind === SyntaxKind.ClassStaticBlockDeclaration; + return container.kind === SyntaxKind.MethodDeclaration + || container.kind === SyntaxKind.MethodSignature + || container.kind === SyntaxKind.GetAccessor + || container.kind === SyntaxKind.SetAccessor + || container.kind === SyntaxKind.PropertyDeclaration + || container.kind === SyntaxKind.ClassStaticBlockDeclaration; } else { - return container.kind === SyntaxKind.MethodDeclaration || - container.kind === SyntaxKind.MethodSignature || - container.kind === SyntaxKind.GetAccessor || - container.kind === SyntaxKind.SetAccessor || - container.kind === SyntaxKind.PropertyDeclaration || - container.kind === SyntaxKind.PropertySignature || - container.kind === SyntaxKind.Constructor; + return container.kind === SyntaxKind.MethodDeclaration + || container.kind === SyntaxKind.MethodSignature + || container.kind === SyntaxKind.GetAccessor + || container.kind === SyntaxKind.SetAccessor + || container.kind === SyntaxKind.PropertyDeclaration + || container.kind === SyntaxKind.PropertySignature + || container.kind === SyntaxKind.Constructor; } } } @@ -29137,24 +37344,31 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function getContainingObjectLiteral(func: SignatureDeclaration): ObjectLiteralExpression | undefined { - return (func.kind === SyntaxKind.MethodDeclaration || - func.kind === SyntaxKind.GetAccessor || - func.kind === SyntaxKind.SetAccessor) && func.parent.kind === SyntaxKind.ObjectLiteralExpression ? func.parent : - func.kind === SyntaxKind.FunctionExpression && func.parent.kind === SyntaxKind.PropertyAssignment ? func.parent.parent as ObjectLiteralExpression : - undefined; + return (func.kind === SyntaxKind.MethodDeclaration + || func.kind === SyntaxKind.GetAccessor + || func.kind === SyntaxKind.SetAccessor) && func.parent.kind === SyntaxKind.ObjectLiteralExpression + ? func.parent + : func.kind === SyntaxKind.FunctionExpression && func.parent.kind === SyntaxKind.PropertyAssignment + ? func.parent.parent as ObjectLiteralExpression + : undefined; } function getThisTypeArgument(type: Type): Type | undefined { - return getObjectFlags(type) & ObjectFlags.Reference && (type as TypeReference).target === globalThisType ? getTypeArguments(type as TypeReference)[0] : undefined; + return getObjectFlags(type) & ObjectFlags.Reference && (type as TypeReference).target === globalThisType + ? getTypeArguments(type as TypeReference)[0] : undefined; } function getThisTypeFromContextualType(type: Type): Type | undefined { return mapType(type, t => { - return t.flags & TypeFlags.Intersection ? forEach((t as IntersectionType).types, getThisTypeArgument) : getThisTypeArgument(t); + return t.flags & TypeFlags.Intersection ? forEach((t as IntersectionType).types, getThisTypeArgument) + : getThisTypeArgument(t); }); } - function getThisTypeOfObjectLiteralFromContextualType(containingLiteral: ObjectLiteralExpression, contextualType: Type | undefined) { + function getThisTypeOfObjectLiteralFromContextualType( + containingLiteral: ObjectLiteralExpression, + contextualType: Type | undefined, + ) { let literal = containingLiteral; let type = contextualType; while (type) { @@ -29198,12 +37412,17 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // There was no contextual ThisType for the containing object literal, so the contextual type // for 'this' is the non-null form of the contextual type for the containing object literal or // the type of the object literal itself. - return getWidenedType(contextualType ? getNonNullableType(contextualType) : checkExpressionCached(containingLiteral)); + return getWidenedType( + contextualType ? getNonNullableType(contextualType) : checkExpressionCached(containingLiteral), + ); } // In an assignment of the form 'obj.xxx = function(...)' or 'obj[xxx] = function(...)', the // contextual type for 'this' is 'obj'. const parent = walkUpParenthesizedExpressions(func.parent); - if (parent.kind === SyntaxKind.BinaryExpression && (parent as BinaryExpression).operatorToken.kind === SyntaxKind.EqualsToken) { + if ( + parent.kind === SyntaxKind.BinaryExpression + && (parent as BinaryExpression).operatorToken.kind === SyntaxKind.EqualsToken + ) { const target = (parent as BinaryExpression).left; if (isAccessExpression(target)) { const { expression } = target; @@ -29233,28 +37452,39 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const args = getEffectiveCallArguments(iife); const indexOfParameter = func.parameters.indexOf(parameter); if (parameter.dotDotDotToken) { - return getSpreadArgumentType(args, indexOfParameter, args.length, anyType, /*context*/ undefined, CheckMode.Normal); + return getSpreadArgumentType( + args, + indexOfParameter, + args.length, + anyType, + /*context*/ undefined, + CheckMode.Normal, + ); } const links = getNodeLinks(iife); const cached = links.resolvedSignature; links.resolvedSignature = anySignature; - const type = indexOfParameter < args.length ? - getWidenedLiteralType(checkExpression(args[indexOfParameter])) : - parameter.initializer ? undefined : undefinedWideningType; + const type = indexOfParameter < args.length + ? getWidenedLiteralType(checkExpression(args[indexOfParameter])) + : parameter.initializer ? undefined : undefinedWideningType; links.resolvedSignature = cached; return type; } const contextualSignature = getContextualSignature(func); if (contextualSignature) { const index = func.parameters.indexOf(parameter) - (getThisParameter(func) ? 1 : 0); - return parameter.dotDotDotToken && lastOrUndefined(func.parameters) === parameter ? - getRestTypeAtPosition(contextualSignature, index) : - tryGetTypeAtPosition(contextualSignature, index); + return parameter.dotDotDotToken && lastOrUndefined(func.parameters) === parameter + ? getRestTypeAtPosition(contextualSignature, index) + : tryGetTypeAtPosition(contextualSignature, index); } } - function getContextualTypeForVariableLikeDeclaration(declaration: VariableLikeDeclaration, contextFlags: ContextFlags | undefined): Type | undefined { - const typeNode = getEffectiveTypeAnnotationNode(declaration) || (isInJSFile(declaration) ? tryGetJSDocSatisfiesTypeNode(declaration) : undefined); + function getContextualTypeForVariableLikeDeclaration( + declaration: VariableLikeDeclaration, + contextFlags: ContextFlags | undefined, + ): Type | undefined { + const typeNode = getEffectiveTypeAnnotationNode(declaration) + || (isInJSFile(declaration) ? tryGetJSDocSatisfiesTypeNode(declaration) : undefined); if (typeNode) { return getTypeFromTypeNode(typeNode); } @@ -29271,11 +37501,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } - function getContextualTypeForBindingElement(declaration: BindingElement, contextFlags: ContextFlags | undefined): Type | undefined { + function getContextualTypeForBindingElement( + declaration: BindingElement, + contextFlags: ContextFlags | undefined, + ): Type | undefined { const parent = declaration.parent.parent; const name = declaration.propertyName || declaration.name; - const parentType = getContextualTypeForVariableLikeDeclaration(parent, contextFlags) || - parent.kind !== SyntaxKind.BindingElement && parent.initializer && checkDeclarationInitializer(parent, declaration.dotDotDotToken ? CheckMode.RestBindingElement : CheckMode.Normal); + const parentType = getContextualTypeForVariableLikeDeclaration(parent, contextFlags) + || parent.kind !== SyntaxKind.BindingElement && parent.initializer + && checkDeclarationInitializer( + parent, + declaration.dotDotDotToken ? CheckMode.RestBindingElement : CheckMode.Normal, + ); if (!parentType || isBindingPattern(name) || isComputedNonLiteralName(name)) return undefined; if (parent.name.kind === SyntaxKind.ArrayBindingPattern) { const index = indexOfNode(declaration.parent.elements, declaration); @@ -29289,7 +37526,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } - function getContextualTypeForStaticPropertyDeclaration(declaration: PropertyDeclaration, contextFlags: ContextFlags | undefined): Type | undefined { + function getContextualTypeForStaticPropertyDeclaration( + declaration: PropertyDeclaration, + contextFlags: ContextFlags | undefined, + ): Type | undefined { const parentType = isExpression(declaration.parent) && getContextualType(declaration.parent, contextFlags); if (!parentType) return undefined; return getTypeOfPropertyOfContextualType(parentType, getSymbolOfDeclaration(declaration).escapedName); @@ -29303,21 +37543,34 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // the contextual type of an initializer expression is the type implied by the binding pattern. // Otherwise, in a binding pattern inside a variable or parameter declaration, // the contextual type of an initializer expression is the type annotation of the containing declaration, if present. - function getContextualTypeForInitializerExpression(node: Expression, contextFlags: ContextFlags | undefined): Type | undefined { + function getContextualTypeForInitializerExpression( + node: Expression, + contextFlags: ContextFlags | undefined, + ): Type | undefined { const declaration = node.parent as VariableLikeDeclaration; if (hasInitializer(declaration) && node === declaration.initializer) { const result = getContextualTypeForVariableLikeDeclaration(declaration, contextFlags); if (result) { return result; } - if (!(contextFlags! & ContextFlags.SkipBindingPatterns) && isBindingPattern(declaration.name) && declaration.name.elements.length > 0) { - return getTypeFromBindingPattern(declaration.name, /*includePatternInType*/ true, /*reportErrors*/ false); + if ( + !(contextFlags! & ContextFlags.SkipBindingPatterns) && isBindingPattern(declaration.name) + && declaration.name.elements.length > 0 + ) { + return getTypeFromBindingPattern( + declaration.name, + /*includePatternInType*/ true, + /*reportErrors*/ false, + ); } } return undefined; } - function getContextualTypeForReturnExpression(node: Expression, contextFlags: ContextFlags | undefined): Type | undefined { + function getContextualTypeForReturnExpression( + node: Expression, + contextFlags: ContextFlags | undefined, + ): Type | undefined { const func = getContainingFunction(node); if (func) { let contextualReturnType = getContextualReturnType(func, contextFlags); @@ -29326,9 +37579,21 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (functionFlags & FunctionFlags.Generator) { // Generator or AsyncGenerator function const isAsyncGenerator = (functionFlags & FunctionFlags.Async) !== 0; if (contextualReturnType.flags & TypeFlags.Union) { - contextualReturnType = filterType(contextualReturnType, type => !!getIterationTypeOfGeneratorFunctionReturnType(IterationTypeKind.Return, type, isAsyncGenerator)); + contextualReturnType = filterType( + contextualReturnType, + type => + !!getIterationTypeOfGeneratorFunctionReturnType( + IterationTypeKind.Return, + type, + isAsyncGenerator, + ), + ); } - const iterationReturnType = getIterationTypeOfGeneratorFunctionReturnType(IterationTypeKind.Return, contextualReturnType, (functionFlags & FunctionFlags.Async) !== 0); + const iterationReturnType = getIterationTypeOfGeneratorFunctionReturnType( + IterationTypeKind.Return, + contextualReturnType, + (functionFlags & FunctionFlags.Async) !== 0, + ); if (!iterationReturnType) { return undefined; } @@ -29339,7 +37604,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (functionFlags & FunctionFlags.Async) { // Async function or AsyncGenerator function // Get the awaited type without the `Awaited` alias const contextualAwaitedType = mapType(contextualReturnType, getAwaitedTypeNoAlias); - return contextualAwaitedType && getUnionType([contextualAwaitedType, createPromiseLikeType(contextualAwaitedType)]); + return contextualAwaitedType + && getUnionType([contextualAwaitedType, createPromiseLikeType(contextualAwaitedType)]); } return contextualReturnType; // Regular function or Generator function @@ -29348,16 +37614,23 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return undefined; } - function getContextualTypeForAwaitOperand(node: AwaitExpression, contextFlags: ContextFlags | undefined): Type | undefined { + function getContextualTypeForAwaitOperand( + node: AwaitExpression, + contextFlags: ContextFlags | undefined, + ): Type | undefined { const contextualType = getContextualType(node, contextFlags); if (contextualType) { const contextualAwaitedType = getAwaitedTypeNoAlias(contextualType); - return contextualAwaitedType && getUnionType([contextualAwaitedType, createPromiseLikeType(contextualAwaitedType)]); + return contextualAwaitedType + && getUnionType([contextualAwaitedType, createPromiseLikeType(contextualAwaitedType)]); } return undefined; } - function getContextualTypeForYieldOperand(node: YieldExpression, contextFlags: ContextFlags | undefined): Type | undefined { + function getContextualTypeForYieldOperand( + node: YieldExpression, + contextFlags: ContextFlags | undefined, + ): Type | undefined { const func = getContainingFunction(node); if (func) { const functionFlags = getFunctionFlags(func); @@ -29365,11 +37638,23 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (contextualReturnType) { const isAsyncGenerator = (functionFlags & FunctionFlags.Async) !== 0; if (!node.asteriskToken && contextualReturnType.flags & TypeFlags.Union) { - contextualReturnType = filterType(contextualReturnType, type => !!getIterationTypeOfGeneratorFunctionReturnType(IterationTypeKind.Return, type, isAsyncGenerator)); + contextualReturnType = filterType( + contextualReturnType, + type => + !!getIterationTypeOfGeneratorFunctionReturnType( + IterationTypeKind.Return, + type, + isAsyncGenerator, + ), + ); } return node.asteriskToken ? contextualReturnType - : getIterationTypeOfGeneratorFunctionReturnType(IterationTypeKind.Yield, contextualReturnType, isAsyncGenerator); + : getIterationTypeOfGeneratorFunctionReturnType( + IterationTypeKind.Yield, + contextualReturnType, + isAsyncGenerator, + ); } } @@ -29403,7 +37688,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return undefined; } - function getContextualReturnType(functionDecl: SignatureDeclaration, contextFlags: ContextFlags | undefined): Type | undefined { + function getContextualReturnType( + functionDecl: SignatureDeclaration, + contextFlags: ContextFlags | undefined, + ): Type | undefined { // If the containing function has a return type annotation, is a constructor, or is a get accessor whose // corresponding set accessor has a type annotation, return statements in the function are contextually typed const returnType = getReturnTypeFromAnnotation(functionDecl); @@ -29432,22 +37720,27 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function getContextualTypeForArgumentAtIndex(callTarget: CallLikeExpression, argIndex: number): Type { if (isImportCall(callTarget)) { - return argIndex === 0 ? stringType : - argIndex === 1 ? getGlobalImportCallOptionsType(/*reportErrors*/ false) : - anyType; + return argIndex === 0 ? stringType + : argIndex === 1 ? getGlobalImportCallOptionsType(/*reportErrors*/ false) + : anyType; } // If we're already in the process of resolving the given signature, don't resolve again as // that could cause infinite recursion. Instead, return anySignature. - const signature = getNodeLinks(callTarget).resolvedSignature === resolvingSignature ? resolvingSignature : getResolvedSignature(callTarget); + const signature = getNodeLinks(callTarget).resolvedSignature === resolvingSignature ? resolvingSignature + : getResolvedSignature(callTarget); if (isJsxOpeningLikeElement(callTarget) && argIndex === 0) { return getEffectiveFirstArgumentForJsxSignature(signature, callTarget); } const restIndex = signature.parameters.length - 1; - return signatureHasRestParameter(signature) && argIndex >= restIndex ? - getIndexedAccessType(getTypeOfSymbol(signature.parameters[restIndex]), getNumberLiteralType(argIndex - restIndex), AccessFlags.Contextual) : - getTypeAtPosition(signature, argIndex); + return signatureHasRestParameter(signature) && argIndex >= restIndex + ? getIndexedAccessType( + getTypeOfSymbol(signature.parameters[restIndex]), + getNumberLiteralType(argIndex - restIndex), + AccessFlags.Contextual, + ) + : getTypeAtPosition(signature, argIndex); } function getContextualTypeForDecorator(decorator: Decorator): Type | undefined { @@ -29455,7 +37748,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return signature ? getOrCreateTypeFromSignature(signature) : undefined; } - function getContextualTypeForSubstitutionExpression(template: TemplateExpression, substitutionExpression: Expression) { + function getContextualTypeForSubstitutionExpression( + template: TemplateExpression, + substitutionExpression: Expression, + ) { if (template.parent.kind === SyntaxKind.TaggedTemplateExpression) { return getContextualTypeForArgument(template.parent as TaggedTemplateExpression, substitutionExpression); } @@ -29463,7 +37759,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return undefined; } - function getContextualTypeForBinaryOperand(node: Expression, contextFlags: ContextFlags | undefined): Type | undefined { + function getContextualTypeForBinaryOperand( + node: Expression, + contextFlags: ContextFlags | undefined, + ): Type | undefined { const binaryExpression = node.parent as BinaryExpression; const { left, operatorToken, right } = binaryExpression; switch (operatorToken.kind) { @@ -29480,8 +37779,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // by the type of the left operand, except for the special case of Javascript declarations of the form // `namespace.prop = namespace.prop || {}`. const type = getContextualType(binaryExpression, contextFlags); - return node === right && (type && type.pattern || !type && !isDefaultedExpandoInitializer(binaryExpression)) ? - getTypeOfExpression(left) : type; + return node === right + && (type && type.pattern || !type && !isDefaultedExpandoInitializer(binaryExpression)) + ? getTypeOfExpression(left) : type; case SyntaxKind.AmpersandAmpersandToken: case SyntaxKind.CommaToken: return node === right ? getContextualType(binaryExpression, contextFlags) : undefined; @@ -29503,7 +37803,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } if (isPropertyAccessExpression(e)) { const lhsType = getTypeOfExpression(e.expression); - return isPrivateIdentifier(e.name) ? tryGetPrivateIdentifierPropertyOfType(lhsType, e.name) : getPropertyOfType(lhsType, e.name.escapedText); + return isPrivateIdentifier(e.name) ? tryGetPrivateIdentifierPropertyOfType(lhsType, e.name) + : getPropertyOfType(lhsType, e.name.escapedText); } if (isElementAccessExpression(e)) { const propType = checkExpressionCached(e.argumentExpression); @@ -29534,8 +37835,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // We avoid calling back into `getTypeOfExpression` and reentering contextual typing to avoid a bogus circularity error in that case. if (decl && (isPropertyDeclaration(decl) || isPropertySignature(decl))) { const overallAnnotation = getEffectiveTypeAnnotationNode(decl); - return (overallAnnotation && instantiateType(getTypeFromTypeNode(overallAnnotation), getSymbolLinks(lhsSymbol).mapper)) || - (isPropertyDeclaration(decl) ? decl.initializer && getTypeOfExpression(binaryExpression.left) : undefined); + return (overallAnnotation + && instantiateType(getTypeFromTypeNode(overallAnnotation), getSymbolLinks(lhsSymbol).mapper)) + || (isPropertyDeclaration(decl) ? decl.initializer && getTypeOfExpression(binaryExpression.left) + : undefined); } if (kind === AssignmentDeclarationKind.None) { return getTypeOfExpression(binaryExpression.left); @@ -29562,9 +37865,17 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } else if (isIdentifier(lhs.expression)) { const id = lhs.expression; - const parentSymbol = resolveName(id, id.escapedText, SymbolFlags.Value, /*nameNotFoundMessage*/ undefined, id.escapedText, /*isUse*/ true); + const parentSymbol = resolveName( + id, + id.escapedText, + SymbolFlags.Value, + /*nameNotFoundMessage*/ undefined, + id.escapedText, + /*isUse*/ true, + ); if (parentSymbol) { - const annotated = parentSymbol.valueDeclaration && getEffectiveTypeAnnotationNode(parentSymbol.valueDeclaration); + const annotated = parentSymbol.valueDeclaration + && getEffectiveTypeAnnotationNode(parentSymbol.valueDeclaration); if (annotated) { const nameStr = getElementOrPropertyAccessName(lhs); if (nameStr !== undefined) { @@ -29574,7 +37885,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return undefined; } } - return isInJSFile(decl) || decl === binaryExpression.left ? undefined : getTypeOfExpression(binaryExpression.left); + return isInJSFile(decl) || decl === binaryExpression.left ? undefined + : getTypeOfExpression(binaryExpression.left); } case AssignmentDeclarationKind.ExportsProperty: case AssignmentDeclarationKind.Prototype: @@ -29582,7 +37894,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { case AssignmentDeclarationKind.ModuleExports: let valueDeclaration: Declaration | undefined; if (kind !== AssignmentDeclarationKind.ModuleExports) { - valueDeclaration = canHaveSymbol(binaryExpression.left) ? binaryExpression.left.symbol?.valueDeclaration : undefined; + valueDeclaration = canHaveSymbol(binaryExpression.left) + ? binaryExpression.left.symbol?.valueDeclaration : undefined; } valueDeclaration ||= binaryExpression.symbol?.valueDeclaration; const annotated = valueDeclaration && getEffectiveTypeAnnotationNode(valueDeclaration); @@ -29596,15 +37909,29 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } - function isPossiblyAliasedThisProperty(declaration: BinaryExpression, kind = getAssignmentDeclarationKind(declaration)) { + function isPossiblyAliasedThisProperty( + declaration: BinaryExpression, + kind = getAssignmentDeclarationKind(declaration), + ) { if (kind === AssignmentDeclarationKind.ThisProperty) { return true; } - if (!isInJSFile(declaration) || kind !== AssignmentDeclarationKind.Property || !isIdentifier((declaration.left as AccessExpression).expression)) { + if ( + !isInJSFile(declaration) || kind !== AssignmentDeclarationKind.Property + || !isIdentifier((declaration.left as AccessExpression).expression) + ) { return false; } const name = ((declaration.left as AccessExpression).expression as Identifier).escapedText; - const symbol = resolveName(declaration.left, name, SymbolFlags.Value, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ true, /*excludeGlobals*/ true); + const symbol = resolveName( + declaration.left, + name, + SymbolFlags.Value, + /*nameNotFoundMessage*/ undefined, + /*nameArg*/ undefined, + /*isUse*/ true, + /*excludeGlobals*/ true, + ); return isThisInitializedDeclaration(symbol?.valueDeclaration); } @@ -29620,7 +37947,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } const thisAccess = cast(binaryExpression.left, isAccessExpression); - if (!isObjectLiteralMethod(getThisContainer(thisAccess.expression, /*includeArrowFunctions*/ false, /*includeClassComputedPropertyName*/ false))) { + if ( + !isObjectLiteralMethod( + getThisContainer( + thisAccess.expression, + /*includeArrowFunctions*/ false, + /*includeClassComputedPropertyName*/ false, + ), + ) + ) { return undefined; } const thisType = checkThisExpression(thisAccess.expression); @@ -29629,7 +37964,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function isCircularMappedProperty(symbol: Symbol) { - return !!(getCheckFlags(symbol) & CheckFlags.Mapped && !(symbol as MappedSymbol).links.type && findResolutionCycleStartIndex(symbol, TypeSystemPropertyName.Type) >= 0); + return !!(getCheckFlags(symbol) & CheckFlags.Mapped && !(symbol as MappedSymbol).links.type + && findResolutionCycleStartIndex(symbol, TypeSystemPropertyName.Type) >= 0); } function getTypeOfPropertyOfContextualType(type: Type, name: __String, nameType?: Type) { @@ -29645,15 +37981,25 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { else if (t.flags & TypeFlags.StructuredType) { const prop = getPropertyOfType(t, name); if (prop) { - return isCircularMappedProperty(prop) ? undefined : removeMissingType(getTypeOfSymbol(prop), !!(prop && prop.flags & SymbolFlags.Optional)); + return isCircularMappedProperty(prop) ? undefined + : removeMissingType(getTypeOfSymbol(prop), !!(prop && prop.flags & SymbolFlags.Optional)); } if (isTupleType(t) && isNumericLiteralName(name) && +name >= 0) { - const restType = getElementTypeOfSliceOfTupleType(t, t.target.fixedLength, /*endSkipCount*/ 0, /*writing*/ false, /*noReductions*/ true); + const restType = getElementTypeOfSliceOfTupleType( + t, + t.target.fixedLength, + /*endSkipCount*/ 0, + /*writing*/ false, + /*noReductions*/ true, + ); if (restType) { return restType; } } - return findApplicableIndexInfo(getIndexInfosOfStructuredType(t), nameType || getStringLiteralType(unescapeLeadingUnderscores(name)))?.type; + return findApplicableIndexInfo( + getIndexInfosOfStructuredType(t), + nameType || getStringLiteralType(unescapeLeadingUnderscores(name)), + )?.type; } return undefined; }, /*noReductions*/ true); @@ -29662,7 +38008,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // In an object literal contextually typed by a type T, the contextual type of a property assignment is the type of // the matching property in T, if one exists. Otherwise, it is the type of the numeric index signature in T, if one // exists. Otherwise, it is the type of the string index signature in T, if one exists. - function getContextualTypeForObjectLiteralMethod(node: MethodDeclaration, contextFlags: ContextFlags | undefined): Type | undefined { + function getContextualTypeForObjectLiteralMethod( + node: MethodDeclaration, + contextFlags: ContextFlags | undefined, + ): Type | undefined { Debug.assert(isObjectLiteralMethod(node)); if (node.flags & NodeFlags.InWithStatement) { // We cannot answer semantic questions within a with block, do not proceed any further @@ -29671,9 +38020,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return getContextualTypeForObjectLiteralElement(node, contextFlags); } - function getContextualTypeForObjectLiteralElement(element: ObjectLiteralElementLike, contextFlags: ContextFlags | undefined) { + function getContextualTypeForObjectLiteralElement( + element: ObjectLiteralElementLike, + contextFlags: ContextFlags | undefined, + ) { const objectLiteral = element.parent as ObjectLiteralExpression; - const propertyAssignmentType = isPropertyAssignment(element) && getContextualTypeForVariableLikeDeclaration(element, contextFlags); + const propertyAssignmentType = isPropertyAssignment(element) + && getContextualTypeForVariableLikeDeclaration(element, contextFlags); if (propertyAssignmentType) { return propertyAssignmentType; } @@ -29690,7 +38043,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const name = getNameOfDeclaration(element); if (name && isComputedPropertyName(name)) { const exprType = checkExpression(name.expression); - const propType = isTypeUsableAsPropertyName(exprType) && getTypeOfPropertyOfContextualType(type, getPropertyNameFromType(exprType)); + const propType = isTypeUsableAsPropertyName(exprType) + && getTypeOfPropertyOfContextualType(type, getPropertyNameFromType(exprType)); if (propType) { return propType; } @@ -29699,7 +38053,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (element.name) { const nameType = getLiteralTypeFromPropertyName(element.name); // We avoid calling getApplicableIndexInfo here because it performs potentially expensive intersection reduction. - return mapType(type, t => findApplicableIndexInfo(getIndexInfosOfStructuredType(t), nameType)?.type, /*noReductions*/ true); + return mapType( + type, + t => findApplicableIndexInfo(getIndexInfosOfStructuredType(t), nameType)?.type, + /*noReductions*/ true, + ); } } return undefined; @@ -29716,44 +38074,80 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return { first, last }; } - function getContextualTypeForElementExpression(type: Type | undefined, index: number, length?: number, firstSpreadIndex?: number, lastSpreadIndex?: number): Type | undefined { + function getContextualTypeForElementExpression( + type: Type | undefined, + index: number, + length?: number, + firstSpreadIndex?: number, + lastSpreadIndex?: number, + ): Type | undefined { return type && mapType(type, t => { if (isTupleType(t)) { // If index is before any spread element and within the fixed part of the contextual tuple type, return // the type of the contextual tuple element. if ((firstSpreadIndex === undefined || index < firstSpreadIndex) && index < t.target.fixedLength) { - return removeMissingType(getTypeArguments(t)[index], !!(t.target.elementFlags[index] && ElementFlags.Optional)); + return removeMissingType( + getTypeArguments(t)[index], + !!(t.target.elementFlags[index] && ElementFlags.Optional), + ); } // When the length is known and the index is after all spread elements we compute the offset from the element // to the end and the number of ending fixed elements in the contextual tuple type. - const offset = length !== undefined && (lastSpreadIndex === undefined || index > lastSpreadIndex) ? length - index : 0; - const fixedEndLength = offset > 0 && t.target.hasRestElement ? getEndElementCount(t.target, ElementFlags.Fixed) : 0; + const offset = length !== undefined && (lastSpreadIndex === undefined || index > lastSpreadIndex) + ? length - index : 0; + const fixedEndLength = offset > 0 && t.target.hasRestElement + ? getEndElementCount(t.target, ElementFlags.Fixed) : 0; // If the offset is within the ending fixed part of the contextual tuple type, return the type of the contextual // tuple element. if (offset > 0 && offset <= fixedEndLength) { return getTypeArguments(t)[getTypeReferenceArity(t) - offset]; } // Return a union of the possible contextual element types with no subtype reduction. - return getElementTypeOfSliceOfTupleType(t, firstSpreadIndex === undefined ? t.target.fixedLength : Math.min(t.target.fixedLength, firstSpreadIndex), length === undefined || lastSpreadIndex === undefined ? fixedEndLength : Math.min(fixedEndLength, length - lastSpreadIndex), /*writing*/ false, /*noReductions*/ true); + return getElementTypeOfSliceOfTupleType( + t, + firstSpreadIndex === undefined ? t.target.fixedLength + : Math.min(t.target.fixedLength, firstSpreadIndex), + length === undefined || lastSpreadIndex === undefined ? fixedEndLength + : Math.min(fixedEndLength, length - lastSpreadIndex), + /*writing*/ false, + /*noReductions*/ true, + ); } // If element index is known and a contextual property with that name exists, return it. Otherwise return the // iterated or element type of the contextual type. - return (!firstSpreadIndex || index < firstSpreadIndex) && getTypeOfPropertyOfContextualType(t, "" + index as __String) || - getIteratedTypeOrElementType(IterationUse.Element, t, undefinedType, /*errorNode*/ undefined, /*checkAssignability*/ false); + return (!firstSpreadIndex || index < firstSpreadIndex) + && getTypeOfPropertyOfContextualType(t, "" + index as __String) + || getIteratedTypeOrElementType( + IterationUse.Element, + t, + undefinedType, + /*errorNode*/ undefined, + /*checkAssignability*/ false, + ); }, /*noReductions*/ true); } // In a contextually typed conditional expression, the true/false expressions are contextually typed by the same type. - function getContextualTypeForConditionalOperand(node: Expression, contextFlags: ContextFlags | undefined): Type | undefined { + function getContextualTypeForConditionalOperand( + node: Expression, + contextFlags: ContextFlags | undefined, + ): Type | undefined { const conditional = node.parent as ConditionalExpression; - return node === conditional.whenTrue || node === conditional.whenFalse ? getContextualType(conditional, contextFlags) : undefined; + return node === conditional.whenTrue || node === conditional.whenFalse + ? getContextualType(conditional, contextFlags) : undefined; } - function getContextualTypeForChildJsxExpression(node: JsxElement, child: JsxChild, contextFlags: ContextFlags | undefined) { + function getContextualTypeForChildJsxExpression( + node: JsxElement, + child: JsxChild, + contextFlags: ContextFlags | undefined, + ) { const attributesType = getApparentTypeOfContextualType(node.openingElement.attributes, contextFlags); // JSX expression is in children of JSX Element, we will look for an "children" attribute (we get the name from JSX.ElementAttributesProperty) const jsxChildrenPropertyName = getJsxElementChildrenPropertyName(getJsxNamespaceAt(node)); - if (!(attributesType && !isTypeAny(attributesType) && jsxChildrenPropertyName && jsxChildrenPropertyName !== "")) { + if ( + !(attributesType && !isTypeAny(attributesType) && jsxChildrenPropertyName && jsxChildrenPropertyName !== "") + ) { return undefined; } const realChildren = getSemanticJsxChildren(node.children); @@ -29769,7 +38163,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { }, /*noReductions*/ true)); } - function getContextualTypeForJsxExpression(node: JsxExpression, contextFlags: ContextFlags | undefined): Type | undefined { + function getContextualTypeForJsxExpression( + node: JsxExpression, + contextFlags: ContextFlags | undefined, + ): Type | undefined { const exprParent = node.parent; return isJsxAttributeLike(exprParent) ? getContextualType(node, contextFlags) @@ -29778,7 +38175,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { : undefined; } - function getContextualTypeForJsxAttribute(attribute: JsxAttribute | JsxSpreadAttribute, contextFlags: ContextFlags | undefined): Type | undefined { + function getContextualTypeForJsxAttribute( + attribute: JsxAttribute | JsxSpreadAttribute, + contextFlags: ContextFlags | undefined, + ): Type | undefined { // When we trying to resolve JsxOpeningLikeElement as a stateless function element, we will already give its attributes a contextual type // which is a type of the parameter of the signature we are trying out. // If there is no contextual type (e.g. we are trying to resolve stateful component), get attributes type from resolving element's tagName @@ -29812,28 +38212,45 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return true; case SyntaxKind.PropertyAccessExpression: case SyntaxKind.ParenthesizedExpression: - return isPossiblyDiscriminantValue((node as PropertyAccessExpression | ParenthesizedExpression).expression); + return isPossiblyDiscriminantValue( + (node as PropertyAccessExpression | ParenthesizedExpression).expression, + ); case SyntaxKind.JsxExpression: - return !(node as JsxExpression).expression || isPossiblyDiscriminantValue((node as JsxExpression).expression!); + return !(node as JsxExpression).expression + || isPossiblyDiscriminantValue((node as JsxExpression).expression!); } return false; } function discriminateContextualTypeByObjectMembers(node: ObjectLiteralExpression, contextualType: UnionType) { - return getMatchingUnionConstituentForObjectLiteral(contextualType, node) || discriminateTypeByDiscriminableItems( - contextualType, - concatenate( - map( - filter(node.properties, p => !!p.symbol && p.kind === SyntaxKind.PropertyAssignment && isPossiblyDiscriminantValue(p.initializer) && isDiscriminantProperty(contextualType, p.symbol.escapedName)), - prop => ([() => getContextFreeTypeOfExpression((prop as PropertyAssignment).initializer), prop.symbol.escapedName] as [() => Type, __String]), - ), - map( - filter(getPropertiesOfType(contextualType), s => !!(s.flags & SymbolFlags.Optional) && !!node?.symbol?.members && !node.symbol.members.has(s.escapedName) && isDiscriminantProperty(contextualType, s.escapedName)), - s => [() => undefinedType, s.escapedName] as [() => Type, __String], + return getMatchingUnionConstituentForObjectLiteral(contextualType, node) + || discriminateTypeByDiscriminableItems( + contextualType, + concatenate( + map( + filter( + node.properties, + p => !!p.symbol && p.kind === SyntaxKind.PropertyAssignment + && isPossiblyDiscriminantValue(p.initializer) + && isDiscriminantProperty(contextualType, p.symbol.escapedName), + ), + prop => ([ + () => getContextFreeTypeOfExpression((prop as PropertyAssignment).initializer), + prop.symbol.escapedName, + ] as [() => Type, __String]), + ), + map( + filter( + getPropertiesOfType(contextualType), + s => !!(s.flags & SymbolFlags.Optional) && !!node?.symbol?.members + && !node.symbol.members.has(s.escapedName) + && isDiscriminantProperty(contextualType, s.escapedName), + ), + s => [() => undefinedType, s.escapedName] as [() => Type, __String], + ), ), - ), - isTypeAssignableTo, - ); + isTypeAssignableTo, + ); } function discriminateContextualTypeByJSXAttributes(node: JsxAttributes, contextualType: UnionType) { @@ -29842,8 +38259,17 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { contextualType, concatenate( map( - filter(node.properties, p => !!p.symbol && p.kind === SyntaxKind.JsxAttribute && isDiscriminantProperty(contextualType, p.symbol.escapedName) && (!p.initializer || isPossiblyDiscriminantValue(p.initializer))), - prop => ([!(prop as JsxAttribute).initializer ? (() => trueType) : (() => getContextFreeTypeOfExpression((prop as JsxAttribute).initializer!)), prop.symbol.escapedName] as [() => Type, __String]), + filter( + node.properties, + p => !!p.symbol && p.kind === SyntaxKind.JsxAttribute + && isDiscriminantProperty(contextualType, p.symbol.escapedName) + && (!p.initializer || isPossiblyDiscriminantValue(p.initializer)), + ), + prop => ([ + !(prop as JsxAttribute).initializer ? (() => trueType) + : (() => getContextFreeTypeOfExpression((prop as JsxAttribute).initializer!)), + prop.symbol.escapedName, + ] as [() => Type, __String]), ), map( filter(getPropertiesOfType(contextualType), s => { @@ -29851,10 +38277,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return false; } const element = node.parent.parent; - if (s.escapedName === jsxChildrenPropertyName && isJsxElement(element) && getSemanticJsxChildren(element.children).length) { + if ( + s.escapedName === jsxChildrenPropertyName && isJsxElement(element) + && getSemanticJsxChildren(element.children).length + ) { return false; } - return !node.symbol.members.has(s.escapedName) && isDiscriminantProperty(contextualType, s.escapedName); + return !node.symbol.members.has(s.escapedName) + && isDiscriminantProperty(contextualType, s.escapedName); }), s => [() => undefinedType, s.escapedName] as [() => Type, __String], ), @@ -29865,12 +38295,19 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // Return the contextual type for a given expression node. During overload resolution, a contextual type may temporarily // be "pushed" onto a node using the contextualType property. - function getApparentTypeOfContextualType(node: Expression | MethodDeclaration, contextFlags: ContextFlags | undefined): Type | undefined { - const contextualType = isObjectLiteralMethod(node) ? - getContextualTypeForObjectLiteralMethod(node, contextFlags) : - getContextualType(node, contextFlags); + function getApparentTypeOfContextualType( + node: Expression | MethodDeclaration, + contextFlags: ContextFlags | undefined, + ): Type | undefined { + const contextualType = isObjectLiteralMethod(node) + ? getContextualTypeForObjectLiteralMethod(node, contextFlags) + : getContextualType(node, contextFlags); const instantiatedType = instantiateContextualType(contextualType, node, contextFlags); - if (instantiatedType && !(contextFlags && contextFlags & ContextFlags.NoConstraints && instantiatedType.flags & TypeFlags.TypeVariable)) { + if ( + instantiatedType + && !(contextFlags && contextFlags & ContextFlags.NoConstraints + && instantiatedType.flags & TypeFlags.TypeVariable) + ) { const apparentType = mapType( instantiatedType, // When obtaining apparent type of *contextual* type we don't want to get apparent type of mapped types. @@ -29880,21 +38317,30 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { t => getObjectFlags(t) & ObjectFlags.Mapped ? t : getApparentType(t), /*noReductions*/ true, ); - return apparentType.flags & TypeFlags.Union && isObjectLiteralExpression(node) ? discriminateContextualTypeByObjectMembers(node, apparentType as UnionType) : - apparentType.flags & TypeFlags.Union && isJsxAttributes(node) ? discriminateContextualTypeByJSXAttributes(node, apparentType as UnionType) : - apparentType; + return apparentType.flags & TypeFlags.Union && isObjectLiteralExpression(node) + ? discriminateContextualTypeByObjectMembers(node, apparentType as UnionType) + : apparentType.flags & TypeFlags.Union && isJsxAttributes(node) + ? discriminateContextualTypeByJSXAttributes(node, apparentType as UnionType) + : apparentType; } } // If the given contextual type contains instantiable types and if a mapper representing // return type inferences is available, instantiate those types using that mapper. - function instantiateContextualType(contextualType: Type | undefined, node: Node, contextFlags: ContextFlags | undefined): Type | undefined { + function instantiateContextualType( + contextualType: Type | undefined, + node: Node, + contextFlags: ContextFlags | undefined, + ): Type | undefined { if (contextualType && maybeTypeOfKind(contextualType, TypeFlags.Instantiable)) { const inferenceContext = getInferenceContext(node); // If no inferences have been made, and none of the type parameters for which we are inferring // specify default types, nothing is gained from instantiating as type parameters would just be // replaced with their constraints similar to the apparent type. - if (inferenceContext && contextFlags! & ContextFlags.Signature && some(inferenceContext.inferences, hasInferenceCandidatesOrDefault)) { + if ( + inferenceContext && contextFlags! & ContextFlags.Signature + && some(inferenceContext.inferences, hasInferenceCandidatesOrDefault) + ) { // For contextual signatures we incorporate all inferences made so far, e.g. from return // types as well as arguments to the left in a function call. return instantiateInstantiableTypes(contextualType, inferenceContext.nonFixingMapper); @@ -29905,9 +38351,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // the 'boolean' type from the contextual type such that contextually typed boolean // literals actually end up widening to 'boolean' (see #48363). const type = instantiateInstantiableTypes(contextualType, inferenceContext.returnMapper); - return type.flags & TypeFlags.Union && containsType((type as UnionType).types, regularFalseType) && containsType((type as UnionType).types, regularTrueType) ? - filterType(type, t => t !== regularFalseType && t !== regularTrueType) : - type; + return type.flags & TypeFlags.Union && containsType((type as UnionType).types, regularFalseType) + && containsType((type as UnionType).types, regularTrueType) + ? filterType(type, t => t !== regularFalseType && t !== regularTrueType) + : type; } } return contextualType; @@ -29921,10 +38368,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return instantiateType(type, mapper); } if (type.flags & TypeFlags.Union) { - return getUnionType(map((type as UnionType).types, t => instantiateInstantiableTypes(t, mapper)), UnionReduction.None); + return getUnionType( + map((type as UnionType).types, t => instantiateInstantiableTypes(t, mapper)), + UnionReduction.None, + ); } if (type.flags & TypeFlags.Intersection) { - return getIntersectionType(map((type as IntersectionType).types, t => instantiateInstantiableTypes(t, mapper))); + return getIntersectionType( + map((type as IntersectionType).types, t => instantiateInstantiableTypes(t, mapper)), + ); } return type; } @@ -29979,20 +38431,33 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return getContextualTypeForDecorator(parent as Decorator); case SyntaxKind.TypeAssertionExpression: case SyntaxKind.AsExpression: - return isConstTypeReference((parent as AssertionExpression).type) ? getContextualType(parent as AssertionExpression, contextFlags) : getTypeFromTypeNode((parent as AssertionExpression).type); + return isConstTypeReference((parent as AssertionExpression).type) + ? getContextualType(parent as AssertionExpression, contextFlags) + : getTypeFromTypeNode((parent as AssertionExpression).type); case SyntaxKind.BinaryExpression: return getContextualTypeForBinaryOperand(node, contextFlags); case SyntaxKind.PropertyAssignment: case SyntaxKind.ShorthandPropertyAssignment: - return getContextualTypeForObjectLiteralElement(parent as PropertyAssignment | ShorthandPropertyAssignment, contextFlags); + return getContextualTypeForObjectLiteralElement( + parent as PropertyAssignment | ShorthandPropertyAssignment, + contextFlags, + ); case SyntaxKind.SpreadAssignment: return getContextualType(parent.parent as ObjectLiteralExpression, contextFlags); case SyntaxKind.ArrayLiteralExpression: { const arrayLiteral = parent as ArrayLiteralExpression; const type = getApparentTypeOfContextualType(arrayLiteral, contextFlags); const elementIndex = indexOfNode(arrayLiteral.elements, node); - const spreadIndices = getNodeLinks(arrayLiteral).spreadIndices ??= getSpreadIndices(arrayLiteral.elements); - return getContextualTypeForElementExpression(type, elementIndex, arrayLiteral.elements.length, spreadIndices.first, spreadIndices.last); + const spreadIndices = getNodeLinks(arrayLiteral).spreadIndices ??= getSpreadIndices( + arrayLiteral.elements, + ); + return getContextualTypeForElementExpression( + type, + elementIndex, + arrayLiteral.elements.length, + spreadIndices.first, + spreadIndices.last, + ); } case SyntaxKind.ConditionalExpression: return getContextualTypeForConditionalOperand(node, contextFlags); @@ -30072,7 +38537,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } - function getContextualJsxElementAttributesType(node: JsxOpeningLikeElement, contextFlags: ContextFlags | undefined) { + function getContextualJsxElementAttributesType( + node: JsxOpeningLikeElement, + contextFlags: ContextFlags | undefined, + ) { if (isJsxOpeningElement(node) && contextFlags !== ContextFlags.Completions) { const index = findContextualNode(node.parent, /*includeCaches*/ !contextFlags); if (index >= 0) { @@ -30144,11 +38612,20 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return tagType; } - function getJsxManagedAttributesFromLocatedAttributes(context: JsxOpeningLikeElement, ns: Symbol, attributesType: Type) { + function getJsxManagedAttributesFromLocatedAttributes( + context: JsxOpeningLikeElement, + ns: Symbol, + attributesType: Type, + ) { const managedSym = getJsxLibraryManagedAttributes(ns); if (managedSym) { const ctorType = getStaticTypeOfReferencedJsxConstructor(context); - const result = instantiateAliasOrInterfaceWithDefaults(managedSym, isInJSFile(context), ctorType, attributesType); + const result = instantiateAliasOrInterfaceWithDefaults( + managedSym, + isInJSFile(context), + ctorType, + attributesType, + ); if (result) { return result; } @@ -30171,7 +38648,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (!attributesType) { // There is no property named 'props' on this instance type if (!!forcedLookupLocation && !!length(context.attributes.properties)) { - error(context, Diagnostics.JSX_element_class_does_not_support_attributes_because_it_does_not_have_a_0_property, unescapeLeadingUnderscores(forcedLookupLocation)); + error( + context, + Diagnostics.JSX_element_class_does_not_support_attributes_because_it_does_not_have_a_0_property, + unescapeLeadingUnderscores(forcedLookupLocation), + ); } return unknownType; } @@ -30192,8 +38673,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { let libraryManagedAttributeType: Type; if (typeParams) { // apply JSX.IntrinsicClassElements - const inferredArgs = fillMissingTypeArguments([hostClassType], typeParams, getMinTypeArgumentCount(typeParams), isInJSFile(context)); - libraryManagedAttributeType = instantiateType(intrinsicClassAttribs, createTypeMapper(typeParams, inferredArgs)); + const inferredArgs = fillMissingTypeArguments( + [hostClassType], + typeParams, + getMinTypeArgumentCount(typeParams), + isInJSFile(context), + ); + libraryManagedAttributeType = instantiateType( + intrinsicClassAttribs, + createTypeMapper(typeParams, inferredArgs), + ); } // or JSX.IntrinsicClassElements has no generics. else libraryManagedAttributeType = intrinsicClassAttribs; @@ -30215,13 +38704,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { signatures, (left: Signature | undefined, right) => left === right || !left ? left - : compareTypeParametersIdentical(left.typeParameters, right!.typeParameters) ? combineSignaturesOfIntersectionMembers(left, right!) + : compareTypeParametersIdentical(left.typeParameters, right!.typeParameters) + ? combineSignaturesOfIntersectionMembers(left, right!) : undefined, ) : undefined; } - function combineIntersectionThisParam(left: Symbol | undefined, right: Symbol | undefined, mapper: TypeMapper | undefined): Symbol | undefined { + function combineIntersectionThisParam( + left: Symbol | undefined, + right: Symbol | undefined, + mapper: TypeMapper | undefined, + ): Symbol | undefined { if (!left || !right) { return left || right; } @@ -30256,10 +38750,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const leftName = i >= leftCount ? undefined : getParameterNameAtPosition(left, i); const rightName = i >= rightCount ? undefined : getParameterNameAtPosition(right, i); - const paramName = leftName === rightName ? leftName : - !leftName ? rightName : - !rightName ? leftName : - undefined; + const paramName = leftName === rightName ? leftName + : !leftName ? rightName + : !rightName ? leftName + : undefined; const paramSymbol = createSymbol( SymbolFlags.FunctionScopedVariable | (isOptional && !isRestParam ? SymbolFlags.Optional : 0), paramName || `arg${i}` as __String, @@ -30300,9 +38794,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { (left.flags | right.flags) & SignatureFlags.PropagatingFlags, ); result.compositeKind = TypeFlags.Intersection; - result.compositeSignatures = concatenate(left.compositeKind === TypeFlags.Intersection && left.compositeSignatures || [left], [right]); + result.compositeSignatures = concatenate( + left.compositeKind === TypeFlags.Intersection && left.compositeSignatures || [left], + [right], + ); if (paramMapper) { - result.mapper = left.compositeKind === TypeFlags.Intersection && left.mapper && left.compositeSignatures ? combineTypeMappers(left.mapper, paramMapper) : paramMapper; + result.mapper = left.compositeKind === TypeFlags.Intersection && left.mapper && left.compositeSignatures + ? combineTypeMappers(left.mapper, paramMapper) : paramMapper; } return result; } @@ -30342,7 +38840,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // If the contextual type is a union type, get the signature from each type possible and if they are // all identical ignoring their return type, the result is same signature but with return type as // union type of return types from these signatures - function getContextualSignature(node: FunctionExpression | ArrowFunction | MethodDeclaration): Signature | undefined { + function getContextualSignature( + node: FunctionExpression | ArrowFunction | MethodDeclaration, + ): Signature | undefined { Debug.assert(node.kind !== SyntaxKind.MethodDeclaration || isObjectLiteralMethod(node)); const typeTagSignature = getSignatureOfTypeTag(node); if (typeTagSignature) { @@ -30364,7 +38864,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // This signature will contribute to contextual union signature signatureList = [signature]; } - else if (!compareSignaturesIdentical(signatureList[0], signature, /*partialMatch*/ false, /*ignoreThisTypes*/ true, /*ignoreReturnTypes*/ true, compareTypesIdentical)) { + else if ( + !compareSignaturesIdentical( + signatureList[0], + signature, + /*partialMatch*/ false, + /*ignoreThisTypes*/ true, + /*ignoreReturnTypes*/ true, + compareTypesIdentical, + ) + ) { // Signatures aren't identical, do not use return undefined; } @@ -30376,13 +38885,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } // Result is union of signatures collected (return type is union of return types of this signature set) if (signatureList) { - return signatureList.length === 1 ? signatureList[0] : createUnionSignature(signatureList[0], signatureList); + return signatureList.length === 1 ? signatureList[0] + : createUnionSignature(signatureList[0], signatureList); } } function checkSpreadExpression(node: SpreadElement, checkMode?: CheckMode): Type { if (languageVersion < ScriptTarget.ES2015) { - checkExternalEmitHelpers(node, compilerOptions.downlevelIteration ? ExternalEmitHelpers.SpreadIncludes : ExternalEmitHelpers.SpreadArray); + checkExternalEmitHelpers( + node, + compilerOptions.downlevelIteration ? ExternalEmitHelpers.SpreadIncludes + : ExternalEmitHelpers.SpreadArray, + ); } const arrayOrIterableType = checkExpression(node.expression, checkMode); @@ -30394,8 +38908,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function hasDefaultValue(node: BindingElement | Expression): boolean { - return (node.kind === SyntaxKind.BindingElement && !!(node as BindingElement).initializer) || - (node.kind === SyntaxKind.BinaryExpression && (node as BinaryExpression).operatorToken.kind === SyntaxKind.EqualsToken); + return (node.kind === SyntaxKind.BindingElement && !!(node as BindingElement).initializer) + || (node.kind === SyntaxKind.BinaryExpression + && (node as BinaryExpression).operatorToken.kind === SyntaxKind.EqualsToken); } function isSpreadIntoCallOrNew(node: ArrayLiteralExpression) { @@ -30403,7 +38918,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return isSpreadElement(parent) && isCallOrNewExpression(parent.parent); } - function checkArrayLiteral(node: ArrayLiteralExpression, checkMode: CheckMode | undefined, forceTuple: boolean | undefined): Type { + function checkArrayLiteral( + node: ArrayLiteralExpression, + checkMode: CheckMode | undefined, + forceTuple: boolean | undefined, + ): Type { const elements = node.elements; const elementCount = elements.length; const elementTypes: Type[] = []; @@ -30412,13 +38931,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const inDestructuringPattern = isAssignmentTarget(node); const inConstContext = isConstContext(node); const contextualType = getApparentTypeOfContextualType(node, /*contextFlags*/ undefined); - const inTupleContext = isSpreadIntoCallOrNew(node) || !!contextualType && someType(contextualType, isTupleLikeType); + const inTupleContext = isSpreadIntoCallOrNew(node) + || !!contextualType && someType(contextualType, isTupleLikeType); let hasOmittedExpression = false; for (let i = 0; i < elementCount; i++) { const e = elements[i]; if (e.kind === SyntaxKind.SpreadElement) { if (languageVersion < ScriptTarget.ES2015) { - checkExternalEmitHelpers(e, compilerOptions.downlevelIteration ? ExternalEmitHelpers.SpreadIncludes : ExternalEmitHelpers.SpreadArray); + checkExternalEmitHelpers( + e, + compilerOptions.downlevelIteration ? ExternalEmitHelpers.SpreadIncludes + : ExternalEmitHelpers.SpreadArray, + ); } const spreadType = checkExpression((e as SpreadElement).expression, checkMode, forceTuple); if (isArrayLikeType(spreadType)) { @@ -30438,14 +38962,27 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // get the contextual element type from it. So we do something similar to // getContextualTypeForElementExpression, which will crucially not error // if there is no index type / iterated type. - const restElementType = getIndexTypeOfType(spreadType, numberType) || - getIteratedTypeOrElementType(IterationUse.Destructuring, spreadType, undefinedType, /*errorNode*/ undefined, /*checkAssignability*/ false) || - unknownType; + const restElementType = getIndexTypeOfType(spreadType, numberType) + || getIteratedTypeOrElementType( + IterationUse.Destructuring, + spreadType, + undefinedType, + /*errorNode*/ undefined, + /*checkAssignability*/ false, + ) + || unknownType; elementTypes.push(restElementType); elementFlags.push(ElementFlags.Rest); } else { - elementTypes.push(checkIteratedTypeOrElementType(IterationUse.Spread, spreadType, undefinedType, (e as SpreadElement).expression)); + elementTypes.push( + checkIteratedTypeOrElementType( + IterationUse.Spread, + spreadType, + undefinedType, + (e as SpreadElement).expression, + ), + ); elementFlags.push(ElementFlags.Rest); } } @@ -30458,7 +38995,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const type = checkExpressionForMutableLocation(e, checkMode, forceTuple); elementTypes.push(addOptionality(type, /*isProperty*/ true, hasOmittedExpression)); elementFlags.push(hasOmittedExpression ? ElementFlags.Optional : ElementFlags.Required); - if (inTupleContext && checkMode && checkMode & CheckMode.Inferential && !(checkMode & CheckMode.SkipContextSensitive) && isContextSensitive(e)) { + if ( + inTupleContext && checkMode && checkMode & CheckMode.Inferential + && !(checkMode & CheckMode.SkipContextSensitive) && isContextSensitive(e) + ) { const inferenceContext = getInferenceContext(node); Debug.assert(inferenceContext); // In CheckMode.Inferential we should always have an inference context addIntraExpressionInferenceSite(inferenceContext, e, type); @@ -30473,9 +39013,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return createArrayLiteralType(createTupleType(elementTypes, elementFlags, /*readonly*/ inConstContext)); } return createArrayLiteralType(createArrayType( - elementTypes.length ? - getUnionType(sameMap(elementTypes, (t, i) => elementFlags[i] & ElementFlags.Variadic ? getIndexedAccessTypeOrUndefined(t, numberType) || anyType : t), UnionReduction.Subtype) : - strictNullChecks ? implicitNeverType : undefinedWideningType, + elementTypes.length + ? getUnionType( + sameMap(elementTypes, (t, i) => + elementFlags[i] & ElementFlags.Variadic + ? getIndexedAccessTypeOrUndefined(t, numberType) || anyType : t), + UnionReduction.Subtype, + ) + : strictNullChecks ? implicitNeverType : undefinedWideningType, inConstContext, )); } @@ -30516,7 +39061,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const links = getNodeLinks(node.expression); if (!links.resolvedType) { if ( - (isTypeLiteralNode(node.parent.parent) || isClassLike(node.parent.parent) || isInterfaceDeclaration(node.parent.parent)) + (isTypeLiteralNode(node.parent.parent) || isClassLike(node.parent.parent) + || isInterfaceDeclaration(node.parent.parent)) && isBinaryExpression(node.expression) && node.expression.operatorToken.kind === SyntaxKind.InKeyword && node.parent.kind !== SyntaxKind.GetAccessor && node.parent.kind !== SyntaxKind.SetAccessor ) { @@ -30525,12 +39071,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { links.resolvedType = checkExpression(node.expression); // The computed property name of a non-static class field within a loop must be stored in a block-scoped binding. // (It needs to be bound at class evaluation time.) - if (isPropertyDeclaration(node.parent) && !hasStaticModifier(node.parent) && isClassExpression(node.parent.parent)) { + if ( + isPropertyDeclaration(node.parent) && !hasStaticModifier(node.parent) + && isClassExpression(node.parent.parent) + ) { const container = getEnclosingBlockScopeContainer(node.parent.parent); const enclosingIterationStatement = getEnclosingIterationStatement(container); if (enclosingIterationStatement) { // The computed field name will use a block scoped binding which can be unique for each iteration of the loop. - getNodeLinks(enclosingIterationStatement).flags |= NodeCheckFlags.LoopWithCapturedBlockScopedBinding; + getNodeLinks(enclosingIterationStatement).flags |= + NodeCheckFlags.LoopWithCapturedBlockScopedBinding; // The generated variable which stores the computed field name must be block-scoped. getNodeLinks(node).flags |= NodeCheckFlags.BlockScopedBindingInLoop; // The generated variable which stores the class must be block-scoped. @@ -30540,9 +39090,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // This will allow types number, string, symbol or any. It will also allow enums, the unknown // type, and any union of these types (like string | number). if ( - links.resolvedType.flags & TypeFlags.Nullable || - !isTypeAssignableToKind(links.resolvedType, TypeFlags.StringLike | TypeFlags.NumberLike | TypeFlags.ESSymbolLike) && - !isTypeAssignableTo(links.resolvedType, stringNumberSymbolType) + links.resolvedType.flags & TypeFlags.Nullable + || !isTypeAssignableToKind( + links.resolvedType, + TypeFlags.StringLike | TypeFlags.NumberLike | TypeFlags.ESSymbolLike, + ) + && !isTypeAssignableTo(links.resolvedType, stringNumberSymbolType) ) { error(node, Diagnostics.A_computed_property_name_must_be_of_type_string_number_symbol_or_any); } @@ -30553,23 +39106,30 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function isSymbolWithNumericName(symbol: Symbol) { const firstDecl = symbol.declarations?.[0]; - return isNumericLiteralName(symbol.escapedName) || (firstDecl && isNamedDeclaration(firstDecl) && isNumericName(firstDecl.name)); + return isNumericLiteralName(symbol.escapedName) + || (firstDecl && isNamedDeclaration(firstDecl) && isNumericName(firstDecl.name)); } function isSymbolWithSymbolName(symbol: Symbol) { const firstDecl = symbol.declarations?.[0]; - return isKnownSymbol(symbol) || (firstDecl && isNamedDeclaration(firstDecl) && isComputedPropertyName(firstDecl.name) && - isTypeAssignableToKind(checkComputedPropertyName(firstDecl.name), TypeFlags.ESSymbol)); + return isKnownSymbol(symbol) + || (firstDecl && isNamedDeclaration(firstDecl) && isComputedPropertyName(firstDecl.name) + && isTypeAssignableToKind(checkComputedPropertyName(firstDecl.name), TypeFlags.ESSymbol)); } - function getObjectLiteralIndexInfo(node: ObjectLiteralExpression, offset: number, properties: Symbol[], keyType: Type): IndexInfo { + function getObjectLiteralIndexInfo( + node: ObjectLiteralExpression, + offset: number, + properties: Symbol[], + keyType: Type, + ): IndexInfo { const propTypes: Type[] = []; for (let i = offset; i < properties.length; i++) { const prop = properties[i]; if ( - keyType === stringType && !isSymbolWithSymbolName(prop) || - keyType === numberType && isSymbolWithNumericName(prop) || - keyType === esSymbolType && isSymbolWithSymbolName(prop) + keyType === stringType && !isSymbolWithSymbolName(prop) + || keyType === numberType && isSymbolWithNumericName(prop) + || keyType === esSymbolType && isSymbolWithSymbolName(prop) ) { propTypes.push(getTypeOfSymbol(properties[i])); } @@ -30602,8 +39162,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { pushCachedContextualType(node); const contextualType = getApparentTypeOfContextualType(node, /*contextFlags*/ undefined); - const contextualTypeHasPattern = contextualType && contextualType.pattern && - (contextualType.pattern.kind === SyntaxKind.ObjectBindingPattern || contextualType.pattern.kind === SyntaxKind.ObjectLiteralExpression); + const contextualTypeHasPattern = contextualType && contextualType.pattern + && (contextualType.pattern.kind === SyntaxKind.ObjectBindingPattern + || contextualType.pattern.kind === SyntaxKind.ObjectLiteralExpression); const inConstContext = isConstContext(node); const checkFlags = inConstContext ? CheckFlags.Readonly : 0; const isInJavascript = isInJSFile(node) && !isInJsonFile(node); @@ -30627,19 +39188,25 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { let offset = 0; for (const memberDecl of node.properties) { let member = getSymbolOfDeclaration(memberDecl); - const computedNameType = memberDecl.name && memberDecl.name.kind === SyntaxKind.ComputedPropertyName ? - checkComputedPropertyName(memberDecl.name) : undefined; + const computedNameType = memberDecl.name && memberDecl.name.kind === SyntaxKind.ComputedPropertyName + ? checkComputedPropertyName(memberDecl.name) : undefined; if ( - memberDecl.kind === SyntaxKind.PropertyAssignment || - memberDecl.kind === SyntaxKind.ShorthandPropertyAssignment || - isObjectLiteralMethod(memberDecl) + memberDecl.kind === SyntaxKind.PropertyAssignment + || memberDecl.kind === SyntaxKind.ShorthandPropertyAssignment + || isObjectLiteralMethod(memberDecl) ) { - let type = memberDecl.kind === SyntaxKind.PropertyAssignment ? checkPropertyAssignment(memberDecl, checkMode) : + let type = memberDecl.kind === SyntaxKind.PropertyAssignment + ? checkPropertyAssignment(memberDecl, checkMode) // avoid resolving the left side of the ShorthandPropertyAssignment outside of the destructuring // for error recovery purposes. For example, if a user wrote `{ a = 100 }` instead of `{ a: 100 }`. // we don't want to say "could not find 'a'". - memberDecl.kind === SyntaxKind.ShorthandPropertyAssignment ? checkExpressionForMutableLocation(!inDestructuringPattern && memberDecl.objectAssignmentInitializer ? memberDecl.objectAssignmentInitializer : memberDecl.name, checkMode) : - checkObjectLiteralMethod(memberDecl, checkMode); + : memberDecl.kind === SyntaxKind.ShorthandPropertyAssignment + ? checkExpressionForMutableLocation( + !inDestructuringPattern && memberDecl.objectAssignmentInitializer + ? memberDecl.objectAssignmentInitializer : memberDecl.name, + checkMode, + ) + : checkObjectLiteralMethod(memberDecl, checkMode); if (isInJavascript) { const jsDocType = getTypeForDeclarationFromJSDocComment(memberDecl); if (jsDocType) { @@ -30651,10 +39218,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } objectFlags |= getObjectFlags(type) & ObjectFlags.PropagatingFlags; - const nameType = computedNameType && isTypeUsableAsPropertyName(computedNameType) ? computedNameType : undefined; - const prop = nameType ? - createSymbol(SymbolFlags.Property | member.flags, getPropertyNameFromType(nameType), checkFlags | CheckFlags.Late) : - createSymbol(SymbolFlags.Property | member.flags, member.escapedName, checkFlags); + const nameType = computedNameType && isTypeUsableAsPropertyName(computedNameType) ? computedNameType + : undefined; + const prop = nameType + ? createSymbol( + SymbolFlags.Property | member.flags, + getPropertyNameFromType(nameType), + checkFlags | CheckFlags.Late, + ) + : createSymbol(SymbolFlags.Property | member.flags, member.escapedName, checkFlags); if (nameType) { prop.links.nameType = nameType; } @@ -30662,21 +39234,33 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (inDestructuringPattern) { // If object literal is an assignment pattern and if the assignment pattern specifies a default value // for the property, make the property optional. - const isOptional = (memberDecl.kind === SyntaxKind.PropertyAssignment && hasDefaultValue(memberDecl.initializer)) || - (memberDecl.kind === SyntaxKind.ShorthandPropertyAssignment && memberDecl.objectAssignmentInitializer); + const isOptional = + (memberDecl.kind === SyntaxKind.PropertyAssignment && hasDefaultValue(memberDecl.initializer)) + || (memberDecl.kind === SyntaxKind.ShorthandPropertyAssignment + && memberDecl.objectAssignmentInitializer); if (isOptional) { prop.flags |= SymbolFlags.Optional; } } - else if (contextualTypeHasPattern && !(getObjectFlags(contextualType) & ObjectFlags.ObjectLiteralPatternWithComputedProperties)) { + else if ( + contextualTypeHasPattern + && !(getObjectFlags(contextualType) & ObjectFlags.ObjectLiteralPatternWithComputedProperties) + ) { // If object literal is contextually typed by the implied type of a binding pattern, and if the // binding pattern specifies a default value for the property, make the property optional. const impliedProp = getPropertyOfType(contextualType, member.escapedName); if (impliedProp) { prop.flags |= impliedProp.flags & SymbolFlags.Optional; } - else if (!compilerOptions.suppressExcessPropertyErrors && !getIndexInfoOfType(contextualType, stringType)) { - error(memberDecl.name, Diagnostics.Object_literal_may_only_specify_known_properties_and_0_does_not_exist_in_type_1, symbolToString(member), typeToString(contextualType)); + else if ( + !compilerOptions.suppressExcessPropertyErrors && !getIndexInfoOfType(contextualType, stringType) + ) { + error( + memberDecl.name, + Diagnostics.Object_literal_may_only_specify_known_properties_and_0_does_not_exist_in_type_1, + symbolToString(member), + typeToString(contextualType), + ); } } @@ -30692,12 +39276,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { allPropertiesTable?.set(prop.escapedName, prop); if ( - contextualType && checkMode & CheckMode.Inferential && !(checkMode & CheckMode.SkipContextSensitive) && - (memberDecl.kind === SyntaxKind.PropertyAssignment || memberDecl.kind === SyntaxKind.MethodDeclaration) && isContextSensitive(memberDecl) + contextualType && checkMode & CheckMode.Inferential && !(checkMode & CheckMode.SkipContextSensitive) + && (memberDecl.kind === SyntaxKind.PropertyAssignment + || memberDecl.kind === SyntaxKind.MethodDeclaration) + && isContextSensitive(memberDecl) ) { const inferenceContext = getInferenceContext(node); Debug.assert(inferenceContext); // In CheckMode.Inferential we should always have an inference context - const inferenceNode = memberDecl.kind === SyntaxKind.PropertyAssignment ? memberDecl.initializer : memberDecl; + const inferenceNode = memberDecl.kind === SyntaxKind.PropertyAssignment ? memberDecl.initializer + : memberDecl; addIntraExpressionInferenceSite(inferenceContext, inferenceNode, type); } } @@ -30772,19 +39359,25 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // It's not possible to check if the immediate parent node is a spread assignment // since the type flows in non-obvious ways through conditional expressions, IIFEs and more. if (contextualTypeHasPattern) { - const rootPatternParent = findAncestor(contextualType.pattern!.parent, n => - n.kind === SyntaxKind.VariableDeclaration || - n.kind === SyntaxKind.BinaryExpression || - n.kind === SyntaxKind.Parameter); + const rootPatternParent = findAncestor( + contextualType.pattern!.parent, + n => n.kind === SyntaxKind.VariableDeclaration + || n.kind === SyntaxKind.BinaryExpression + || n.kind === SyntaxKind.Parameter, + ); const spreadOrOutsideRootObject = findAncestor(node, n => - n === rootPatternParent || - n.kind === SyntaxKind.SpreadAssignment)!; + n === rootPatternParent + || n.kind === SyntaxKind.SpreadAssignment)!; if (spreadOrOutsideRootObject.kind !== SyntaxKind.SpreadAssignment) { for (const prop of getPropertiesOfType(contextualType)) { if (!propertiesTable.get(prop.escapedName) && !getPropertyOfType(spread, prop.escapedName)) { if (!(prop.flags & SymbolFlags.Optional)) { - error(prop.valueDeclaration || tryCast(prop, isTransientSymbol)?.links.bindingElement, Diagnostics.Initializer_provides_no_value_for_this_binding_element_and_the_binding_element_has_no_default_value); + error( + prop.valueDeclaration || tryCast(prop, isTransientSymbol)?.links.bindingElement, + Diagnostics + .Initializer_provides_no_value_for_this_binding_element_and_the_binding_element_has_no_default_value, + ); } propertiesTable.set(prop.escapedName, prop); propertiesArray.push(prop); @@ -30813,9 +39406,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function createObjectLiteralType() { const indexInfos = []; - if (hasComputedStringProperty) indexInfos.push(getObjectLiteralIndexInfo(node, offset, propertiesArray, stringType)); - if (hasComputedNumberProperty) indexInfos.push(getObjectLiteralIndexInfo(node, offset, propertiesArray, numberType)); - if (hasComputedSymbolProperty) indexInfos.push(getObjectLiteralIndexInfo(node, offset, propertiesArray, esSymbolType)); + if (hasComputedStringProperty) { + indexInfos.push(getObjectLiteralIndexInfo(node, offset, propertiesArray, stringType)); + } + if (hasComputedNumberProperty) { + indexInfos.push(getObjectLiteralIndexInfo(node, offset, propertiesArray, numberType)); + } + if (hasComputedSymbolProperty) { + indexInfos.push(getObjectLiteralIndexInfo(node, offset, propertiesArray, esSymbolType)); + } const result = createAnonymousType(node.symbol, propertiesTable, emptyArray, emptyArray, indexInfos); result.objectFlags |= objectFlags | ObjectFlags.ObjectLiteral | ObjectFlags.ContainsObjectOrArrayLiteral; if (isJSObjectLiteral) { @@ -30833,8 +39432,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function isValidSpreadType(type: Type): boolean { const t = removeDefinitelyFalsyTypes(mapType(type, getBaseConstraintOrType)); - return !!(t.flags & (TypeFlags.Any | TypeFlags.NonPrimitive | TypeFlags.Object | TypeFlags.InstantiableNonPrimitive) || - t.flags & TypeFlags.UnionOrIntersection && every((t as UnionOrIntersectionType).types, isValidSpreadType)); + return !!(t.flags + & (TypeFlags.Any | TypeFlags.NonPrimitive | TypeFlags.Object | TypeFlags.InstantiableNonPrimitive) + || t.flags & TypeFlags.UnionOrIntersection + && every((t as UnionOrIntersectionType).types, isValidSpreadType)); } function checkJsxSelfClosingElementDeferred(node: JsxSelfClosingElement) { @@ -30880,7 +39481,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { error( node, compilerOptions.jsxFactory - ? Diagnostics.The_jsxFragmentFactory_compiler_option_must_be_provided_to_use_JSX_fragments_with_the_jsxFactory_compiler_option + ? Diagnostics + .The_jsxFragmentFactory_compiler_option_must_be_provided_to_use_JSX_fragments_with_the_jsxFactory_compiler_option : Diagnostics.An_jsxFrag_pragma_is_required_when_using_an_jsx_pragma_with_JSX_fragments, ); } @@ -30915,7 +39517,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { * @remarks Because this function calls getSpreadType, it needs to use the same checks as checkObjectLiteral, * which also calls getSpreadType. */ - function createJsxAttributesTypeFromAttributesProperty(openingLikeElement: JsxOpeningLikeElement, checkMode: CheckMode = CheckMode.Normal) { + function createJsxAttributesTypeFromAttributesProperty( + openingLikeElement: JsxOpeningLikeElement, + checkMode: CheckMode = CheckMode.Normal, + ) { const attributes = openingLikeElement.attributes; const contextualType = getContextualType(attributes, ContextFlags.None); const allAttributesTable = strictNullChecks ? createSymbolTable() : undefined; @@ -30949,10 +39554,17 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (contextualType) { const prop = getPropertyOfType(contextualType, member.escapedName); if (prop && prop.declarations && isDeprecatedSymbol(prop) && isIdentifier(attributeDecl.name)) { - addDeprecatedSuggestion(attributeDecl.name, prop.declarations, attributeDecl.name.escapedText as string); + addDeprecatedSuggestion( + attributeDecl.name, + prop.declarations, + attributeDecl.name.escapedText as string, + ); } } - if (contextualType && checkMode & CheckMode.Inferential && !(checkMode & CheckMode.SkipContextSensitive) && isContextSensitive(attributeDecl)) { + if ( + contextualType && checkMode & CheckMode.Inferential && !(checkMode & CheckMode.SkipContextSensitive) + && isContextSensitive(attributeDecl) + ) { const inferenceContext = getInferenceContext(attributes); Debug.assert(inferenceContext); // In CheckMode.Inferential we should always have an inference context const inferenceNode = (attributeDecl.initializer as JsxExpression).expression!; @@ -30962,10 +39574,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { else { Debug.assert(attributeDecl.kind === SyntaxKind.JsxSpreadAttribute); if (attributesTable.size > 0) { - spread = getSpreadType(spread, createJsxAttributesType(), attributes.symbol, objectFlags, /*readonly*/ false); + spread = getSpreadType( + spread, + createJsxAttributesType(), + attributes.symbol, + objectFlags, + /*readonly*/ false, + ); attributesTable = createSymbolTable(); } - const exprType = getReducedType(checkExpression(attributeDecl.expression, checkMode & CheckMode.Inferential)); + const exprType = getReducedType( + checkExpression(attributeDecl.expression, checkMode & CheckMode.Inferential), + ); if (isTypeAny(exprType)) { hasSpreadAnyType = true; } @@ -30984,12 +39604,19 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (!hasSpreadAnyType) { if (attributesTable.size > 0) { - spread = getSpreadType(spread, createJsxAttributesType(), attributes.symbol, objectFlags, /*readonly*/ false); + spread = getSpreadType( + spread, + createJsxAttributesType(), + attributes.symbol, + objectFlags, + /*readonly*/ false, + ); } } // Handle children attribute - const parent = openingLikeElement.parent.kind === SyntaxKind.JsxElement ? openingLikeElement.parent as JsxElement : undefined; + const parent = openingLikeElement.parent.kind === SyntaxKind.JsxElement + ? openingLikeElement.parent as JsxElement : undefined; // We have to check that openingElement of the parent is the one we are visiting as this may not be true for selfClosingElement if (parent && parent.openingElement === openingLikeElement && parent.children.length > 0) { const childrenTypes: Type[] = checkJsxChildren(parent, checkMode); @@ -30999,23 +39626,43 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // This is because children element will overwrite the value from attributes. // Note: we will not warn "children" attribute overwritten if "children" attribute is specified in object spread. if (explicitlySpecifyChildrenAttribute) { - error(attributes, Diagnostics._0_are_specified_twice_The_attribute_named_0_will_be_overwritten, unescapeLeadingUnderscores(jsxChildrenPropertyName)); + error( + attributes, + Diagnostics._0_are_specified_twice_The_attribute_named_0_will_be_overwritten, + unescapeLeadingUnderscores(jsxChildrenPropertyName), + ); } - const contextualType = getApparentTypeOfContextualType(openingLikeElement.attributes, /*contextFlags*/ undefined); - const childrenContextualType = contextualType && getTypeOfPropertyOfContextualType(contextualType, jsxChildrenPropertyName); + const contextualType = getApparentTypeOfContextualType( + openingLikeElement.attributes, + /*contextFlags*/ undefined, + ); + const childrenContextualType = contextualType + && getTypeOfPropertyOfContextualType(contextualType, jsxChildrenPropertyName); // If there are children in the body of JSX element, create dummy attribute "children" with the union of children types so that it will pass the attribute checking process const childrenPropSymbol = createSymbol(SymbolFlags.Property, jsxChildrenPropertyName); - childrenPropSymbol.links.type = childrenTypes.length === 1 ? childrenTypes[0] : - childrenContextualType && someType(childrenContextualType, isTupleLikeType) ? createTupleType(childrenTypes) : - createArrayType(getUnionType(childrenTypes)); + childrenPropSymbol.links.type = childrenTypes.length === 1 ? childrenTypes[0] + : childrenContextualType && someType(childrenContextualType, isTupleLikeType) + ? createTupleType(childrenTypes) + : createArrayType(getUnionType(childrenTypes)); // Fake up a property declaration for the children - childrenPropSymbol.valueDeclaration = factory.createPropertySignature(/*modifiers*/ undefined, unescapeLeadingUnderscores(jsxChildrenPropertyName), /*questionToken*/ undefined, /*type*/ undefined); + childrenPropSymbol.valueDeclaration = factory.createPropertySignature( + /*modifiers*/ undefined, + unescapeLeadingUnderscores(jsxChildrenPropertyName), + /*questionToken*/ undefined, + /*type*/ undefined, + ); setParent(childrenPropSymbol.valueDeclaration, attributes); childrenPropSymbol.valueDeclaration.symbol = childrenPropSymbol; const childPropMap = createSymbolTable(); childPropMap.set(jsxChildrenPropertyName, childrenPropSymbol); - spread = getSpreadType(spread, createAnonymousType(attributes.symbol, childPropMap, emptyArray, emptyArray, emptyArray), attributes.symbol, objectFlags, /*readonly*/ false); + spread = getSpreadType( + spread, + createAnonymousType(attributes.symbol, childPropMap, emptyArray, emptyArray, emptyArray), + attributes.symbol, + objectFlags, + /*readonly*/ false, + ); } } @@ -31065,8 +39712,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (!(right.flags & SymbolFlags.Optional)) { const left = props.get(right.escapedName); if (left) { - const diagnostic = error(left.valueDeclaration, Diagnostics._0_is_specified_more_than_once_so_this_usage_will_be_overwritten, unescapeLeadingUnderscores(left.escapedName)); - addRelatedInfo(diagnostic, createDiagnosticForNode(spread, Diagnostics.This_spread_always_overwrites_this_property)); + const diagnostic = error( + left.valueDeclaration, + Diagnostics._0_is_specified_more_than_once_so_this_usage_will_be_overwritten, + unescapeLeadingUnderscores(left.escapedName), + ); + addRelatedInfo( + diagnostic, + createDiagnosticForNode(spread, Diagnostics.This_spread_always_overwrites_this_property), + ); } } } @@ -31101,7 +39755,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (!isErrorType(intrinsicElementsType)) { // Property case if (!isIdentifier(node.tagName) && !isJsxNamespacedName(node.tagName)) return Debug.fail(); - const propName = isJsxNamespacedName(node.tagName) ? getEscapedTextOfJsxNamespacedName(node.tagName) : node.tagName.escapedText; + const propName = isJsxNamespacedName(node.tagName) ? getEscapedTextOfJsxNamespacedName(node.tagName) + : node.tagName.escapedText; const intrinsicProp = getPropertyOfType(intrinsicElementsType, propName); if (intrinsicProp) { links.jsxFlags |= JsxFlags.IntrinsicNamedElement; @@ -31109,7 +39764,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } // Intrinsic string indexer case - const indexSymbol = getApplicableIndexSymbol(intrinsicElementsType, getStringLiteralType(unescapeLeadingUnderscores(propName))); + const indexSymbol = getApplicableIndexSymbol( + intrinsicElementsType, + getStringLiteralType(unescapeLeadingUnderscores(propName)), + ); if (indexSymbol) { links.jsxFlags |= JsxFlags.IntrinsicIndexedElement; return links.resolvedSymbol = indexSymbol; @@ -31121,12 +39779,21 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } // Wasn't found - error(node, Diagnostics.Property_0_does_not_exist_on_type_1, intrinsicTagNameToString(node.tagName), "JSX." + JsxNames.IntrinsicElements); + error( + node, + Diagnostics.Property_0_does_not_exist_on_type_1, + intrinsicTagNameToString(node.tagName), + "JSX." + JsxNames.IntrinsicElements, + ); return links.resolvedSymbol = unknownSymbol; } else { if (noImplicitAny) { - error(node, Diagnostics.JSX_element_implicitly_has_type_any_because_no_interface_JSX_0_exists, unescapeLeadingUnderscores(JsxNames.IntrinsicElements)); + error( + node, + Diagnostics.JSX_element_implicitly_has_type_any_because_no_interface_JSX_0_exists, + unescapeLeadingUnderscores(JsxNames.IntrinsicElements), + ); } return links.resolvedSymbol = unknownSymbol; } @@ -31143,13 +39810,17 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (links && links.jsxImplicitImportContainer) { return links.jsxImplicitImportContainer; } - const runtimeImportSpecifier = getJSXRuntimeImport(getJSXImplicitImportBase(compilerOptions, file), compilerOptions); + const runtimeImportSpecifier = getJSXRuntimeImport( + getJSXImplicitImportBase(compilerOptions, file), + compilerOptions, + ); if (!runtimeImportSpecifier) { return undefined; } const isClassic = getEmitModuleResolutionKind(compilerOptions) === ModuleResolutionKind.Classic; const errorMessage = isClassic - ? Diagnostics.Cannot_find_module_0_Did_you_mean_to_set_the_moduleResolution_option_to_nodenext_or_to_add_aliases_to_the_paths_option + ? Diagnostics + .Cannot_find_module_0_Did_you_mean_to_set_the_moduleResolution_option_to_nodenext_or_to_add_aliases_to_the_paths_option : Diagnostics.Cannot_find_module_0_or_its_corresponding_type_declarations; const mod = resolveExternalModule(location!, runtimeImportSpecifier, errorMessage, location!); const result = mod && mod !== unknownSymbol ? getMergedSymbol(resolveSymbol(mod)) : undefined; @@ -31169,11 +39840,24 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (!resolvedNamespace || resolvedNamespace === unknownSymbol) { const namespaceName = getJsxNamespace(location); - resolvedNamespace = resolveName(location, namespaceName, SymbolFlags.Namespace, /*nameNotFoundMessage*/ undefined, namespaceName, /*isUse*/ false); + resolvedNamespace = resolveName( + location, + namespaceName, + SymbolFlags.Namespace, + /*nameNotFoundMessage*/ undefined, + namespaceName, + /*isUse*/ false, + ); } if (resolvedNamespace) { - const candidate = resolveSymbol(getSymbol(getExportsOfSymbol(resolveSymbol(resolvedNamespace)), JsxNames.JSX, SymbolFlags.Namespace)); + const candidate = resolveSymbol( + getSymbol( + getExportsOfSymbol(resolveSymbol(resolvedNamespace)), + JsxNames.JSX, + SymbolFlags.Namespace, + ), + ); if (candidate && candidate !== unknownSymbol) { if (links) { links.jsxNamespace = candidate; @@ -31200,13 +39884,19 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { * @param nameOfAttribPropContainer a string of value JsxNames.ElementAttributesPropertyNameContainer or JsxNames.ElementChildrenAttributeNameContainer * if other string is given or the container doesn't exist, return undefined. */ - function getNameFromJsxElementAttributesContainer(nameOfAttribPropContainer: __String, jsxNamespace: Symbol): __String | undefined { + function getNameFromJsxElementAttributesContainer( + nameOfAttribPropContainer: __String, + jsxNamespace: Symbol, + ): __String | undefined { // JSX.ElementAttributesProperty | JSX.ElementChildrenAttribute [symbol] - const jsxElementAttribPropInterfaceSym = jsxNamespace && getSymbol(jsxNamespace.exports!, nameOfAttribPropContainer, SymbolFlags.Type); + const jsxElementAttribPropInterfaceSym = jsxNamespace + && getSymbol(jsxNamespace.exports!, nameOfAttribPropContainer, SymbolFlags.Type); // JSX.ElementAttributesProperty | JSX.ElementChildrenAttribute [type] - const jsxElementAttribPropInterfaceType = jsxElementAttribPropInterfaceSym && getDeclaredTypeOfSymbol(jsxElementAttribPropInterfaceSym); + const jsxElementAttribPropInterfaceType = jsxElementAttribPropInterfaceSym + && getDeclaredTypeOfSymbol(jsxElementAttribPropInterfaceSym); // The properties of JSX.ElementAttributesProperty | JSX.ElementChildrenAttribute - const propertiesOfJsxElementAttribPropInterface = jsxElementAttribPropInterfaceType && getPropertiesOfType(jsxElementAttribPropInterfaceType); + const propertiesOfJsxElementAttribPropInterface = jsxElementAttribPropInterfaceType + && getPropertiesOfType(jsxElementAttribPropInterfaceType); if (propertiesOfJsxElementAttribPropInterface) { // Element Attributes has zero properties, so the element attributes type will be the class instance type if (propertiesOfJsxElementAttribPropInterface.length === 0) { @@ -31217,9 +39907,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { else if (propertiesOfJsxElementAttribPropInterface.length === 1) { return propertiesOfJsxElementAttribPropInterface[0].escapedName; } - else if (propertiesOfJsxElementAttribPropInterface.length > 1 && jsxElementAttribPropInterfaceSym.declarations) { + else if ( + propertiesOfJsxElementAttribPropInterface.length > 1 && jsxElementAttribPropInterfaceSym.declarations + ) { // More than one property on ElementAttributesProperty is an error - error(jsxElementAttribPropInterfaceSym.declarations[0], Diagnostics.The_global_type_JSX_0_may_not_have_more_than_one_property, unescapeLeadingUnderscores(nameOfAttribPropContainer)); + error( + jsxElementAttribPropInterfaceSym.declarations[0], + Diagnostics.The_global_type_JSX_0_may_not_have_more_than_one_property, + unescapeLeadingUnderscores(nameOfAttribPropContainer), + ); } } return undefined; @@ -31248,14 +39944,25 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return getNameFromJsxElementAttributesContainer(JsxNames.ElementChildrenAttributeNameContainer, jsxNamespace); } - function getUninstantiatedJsxSignaturesOfType(elementType: Type, caller: JsxOpeningLikeElement): readonly Signature[] { + function getUninstantiatedJsxSignaturesOfType( + elementType: Type, + caller: JsxOpeningLikeElement, + ): readonly Signature[] { if (elementType.flags & TypeFlags.String) { return [anySignature]; } else if (elementType.flags & TypeFlags.StringLiteral) { - const intrinsicType = getIntrinsicAttributesTypeFromStringLiteralType(elementType as StringLiteralType, caller); + const intrinsicType = getIntrinsicAttributesTypeFromStringLiteralType( + elementType as StringLiteralType, + caller, + ); if (!intrinsicType) { - error(caller, Diagnostics.Property_0_does_not_exist_on_type_1, (elementType as StringLiteralType).value, "JSX." + JsxNames.IntrinsicElements); + error( + caller, + Diagnostics.Property_0_does_not_exist_on_type_1, + (elementType as StringLiteralType).value, + "JSX." + JsxNames.IntrinsicElements, + ); return emptyArray; } else { @@ -31272,12 +39979,17 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } if (signatures.length === 0 && apparentElemType.flags & TypeFlags.Union) { // If each member has some combination of new/call signatures; make a union signature list for those - signatures = getUnionSignatures(map((apparentElemType as UnionType).types, t => getUninstantiatedJsxSignaturesOfType(t, caller))); + signatures = getUnionSignatures( + map((apparentElemType as UnionType).types, t => getUninstantiatedJsxSignaturesOfType(t, caller)), + ); } return signatures; } - function getIntrinsicAttributesTypeFromStringLiteralType(type: StringLiteralType, location: Node): Type | undefined { + function getIntrinsicAttributesTypeFromStringLiteralType( + type: StringLiteralType, + location: Node, + ): Type | undefined { // If the elemType is a stringLiteral type, we can then provide a check to make sure that the string literal type is one of the Jsx intrinsic element type // For example: // var CustomTag: "h1" = "h1"; @@ -31285,7 +39997,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const intrinsicElementsType = getJsxType(JsxNames.IntrinsicElements, location); if (!isErrorType(intrinsicElementsType)) { const stringLiteralTypeName = type.value; - const intrinsicProp = getPropertyOfType(intrinsicElementsType, escapeLeadingUnderscores(stringLiteralTypeName)); + const intrinsicProp = getPropertyOfType( + intrinsicElementsType, + escapeLeadingUnderscores(stringLiteralTypeName), + ); if (intrinsicProp) { return getTypeOfSymbol(intrinsicProp); } @@ -31299,18 +40014,36 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return anyType; } - function checkJsxReturnAssignableToAppropriateBound(refKind: JsxReferenceKind, elemInstanceType: Type, openingLikeElement: JsxOpeningLikeElement) { + function checkJsxReturnAssignableToAppropriateBound( + refKind: JsxReferenceKind, + elemInstanceType: Type, + openingLikeElement: JsxOpeningLikeElement, + ) { if (refKind === JsxReferenceKind.Function) { const sfcReturnConstraint = getJsxStatelessElementTypeAt(openingLikeElement); if (sfcReturnConstraint) { - checkTypeRelatedTo(elemInstanceType, sfcReturnConstraint, assignableRelation, openingLikeElement.tagName, Diagnostics.Its_return_type_0_is_not_a_valid_JSX_element, generateInitialErrorChain); + checkTypeRelatedTo( + elemInstanceType, + sfcReturnConstraint, + assignableRelation, + openingLikeElement.tagName, + Diagnostics.Its_return_type_0_is_not_a_valid_JSX_element, + generateInitialErrorChain, + ); } } else if (refKind === JsxReferenceKind.Component) { const classConstraint = getJsxElementClassTypeAt(openingLikeElement); if (classConstraint) { // Issue an error if this return type isn't assignable to JSX.ElementClass, failing that - checkTypeRelatedTo(elemInstanceType, classConstraint, assignableRelation, openingLikeElement.tagName, Diagnostics.Its_instance_type_0_is_not_a_valid_JSX_element, generateInitialErrorChain); + checkTypeRelatedTo( + elemInstanceType, + classConstraint, + assignableRelation, + openingLikeElement.tagName, + Diagnostics.Its_instance_type_0_is_not_a_valid_JSX_element, + generateInitialErrorChain, + ); } } else { // Mixed @@ -31320,12 +40053,23 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return; } const combined = getUnionType([sfcReturnConstraint, classConstraint]); - checkTypeRelatedTo(elemInstanceType, combined, assignableRelation, openingLikeElement.tagName, Diagnostics.Its_element_type_0_is_not_a_valid_JSX_element, generateInitialErrorChain); + checkTypeRelatedTo( + elemInstanceType, + combined, + assignableRelation, + openingLikeElement.tagName, + Diagnostics.Its_element_type_0_is_not_a_valid_JSX_element, + generateInitialErrorChain, + ); } function generateInitialErrorChain(): DiagnosticMessageChain { const componentName = getTextOfNode(openingLikeElement.tagName); - return chainDiagnosticMessages(/*details*/ undefined, Diagnostics._0_cannot_be_used_as_a_JSX_component, componentName); + return chainDiagnosticMessages( + /*details*/ undefined, + Diagnostics._0_cannot_be_used_as_a_JSX_component, + componentName, + ); } } @@ -31343,8 +40087,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return links.resolvedJsxElementAttributesType = getTypeOfSymbol(symbol) || errorType; } else if (links.jsxFlags & JsxFlags.IntrinsicIndexedElement) { - const propName = isJsxNamespacedName(node.tagName) ? getEscapedTextOfJsxNamespacedName(node.tagName) : node.tagName.escapedText; - return links.resolvedJsxElementAttributesType = getApplicableIndexInfoForName(getJsxType(JsxNames.IntrinsicElements, node), propName)?.type || errorType; + const propName = isJsxNamespacedName(node.tagName) ? getEscapedTextOfJsxNamespacedName(node.tagName) + : node.tagName.escapedText; + return links.resolvedJsxElementAttributesType = + getApplicableIndexInfoForName(getJsxType(JsxNames.IntrinsicElements, node), propName)?.type + || errorType; } else { return links.resolvedJsxElementAttributesType = errorType; @@ -31390,7 +40137,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } if (length((declaredManagedType as GenericType).typeParameters) >= typeArguments.length) { - const args = fillMissingTypeArguments(typeArguments, (declaredManagedType as GenericType).typeParameters, typeArguments.length, inJs); + const args = fillMissingTypeArguments( + typeArguments, + (declaredManagedType as GenericType).typeParameters, + typeArguments.length, + inJs, + ); return createTypeReference(declaredManagedType as GenericType, args); } return undefined; @@ -31412,7 +40164,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (getJsxElementTypeAt(errorNode) === undefined) { if (noImplicitAny) { - error(errorNode, Diagnostics.JSX_element_implicitly_has_type_any_because_the_global_type_JSX_Element_does_not_exist); + error( + errorNode, + Diagnostics.JSX_element_implicitly_has_type_any_because_the_global_type_JSX_Element_does_not_exist, + ); } } } @@ -31429,14 +40184,22 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (!getJsxNamespaceContainerForImplicitImport(node)) { // The reactNamespace/jsxFactory's root symbol should be marked as 'used' so we don't incorrectly elide its import. // And if there is no reactNamespace/jsxFactory's symbol in scope when targeting React emit, we should issue an error. - const jsxFactoryRefErr = diagnostics && compilerOptions.jsx === JsxEmit.React ? Diagnostics.Cannot_find_name_0 : undefined; + const jsxFactoryRefErr = diagnostics && compilerOptions.jsx === JsxEmit.React + ? Diagnostics.Cannot_find_name_0 : undefined; const jsxFactoryNamespace = getJsxNamespace(node); const jsxFactoryLocation = isNodeOpeningLikeElement ? node.tagName : node; // allow null as jsxFragmentFactory let jsxFactorySym: Symbol | undefined; if (!(isJsxOpeningFragment(node) && jsxFactoryNamespace === "null")) { - jsxFactorySym = resolveName(jsxFactoryLocation, jsxFactoryNamespace, SymbolFlags.Value, jsxFactoryRefErr, jsxFactoryNamespace, /*isUse*/ true); + jsxFactorySym = resolveName( + jsxFactoryLocation, + jsxFactoryNamespace, + SymbolFlags.Value, + jsxFactoryRefErr, + jsxFactoryNamespace, + /*isUse*/ true, + ); } if (jsxFactorySym) { @@ -31445,7 +40208,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { jsxFactorySym.isReferenced = SymbolFlags.All; // If react/jsxFactory symbol is alias, mark it as refereced - if (canCollectSymbolAliasAccessabilityData && jsxFactorySym.flags & SymbolFlags.Alias && !getTypeOnlyAliasDeclaration(jsxFactorySym)) { + if ( + canCollectSymbolAliasAccessabilityData && jsxFactorySym.flags & SymbolFlags.Alias + && !getTypeOnlyAliasDeclaration(jsxFactorySym) + ) { markAliasSymbolAsReferenced(jsxFactorySym); } } @@ -31455,7 +40221,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const file = getSourceFileOfNode(node); const localJsxNamespace = getLocalJsxNamespace(file); if (localJsxNamespace) { - resolveName(jsxFactoryLocation, localJsxNamespace, SymbolFlags.Value, jsxFactoryRefErr, localJsxNamespace, /*isUse*/ true); + resolveName( + jsxFactoryLocation, + localJsxNamespace, + SymbolFlags.Value, + jsxFactoryRefErr, + localJsxNamespace, + /*isUse*/ true, + ); } } } @@ -31471,13 +40244,28 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const tagType = isJsxIntrinsicTagName(tagName) ? getStringLiteralType(intrinsicTagNameToString(tagName)) : checkExpression(tagName); - checkTypeRelatedTo(tagType, elementTypeConstraint, assignableRelation, tagName, Diagnostics.Its_type_0_is_not_a_valid_JSX_element_type, () => { - const componentName = getTextOfNode(tagName); - return chainDiagnosticMessages(/*details*/ undefined, Diagnostics._0_cannot_be_used_as_a_JSX_component, componentName); - }); + checkTypeRelatedTo( + tagType, + elementTypeConstraint, + assignableRelation, + tagName, + Diagnostics.Its_type_0_is_not_a_valid_JSX_element_type, + () => { + const componentName = getTextOfNode(tagName); + return chainDiagnosticMessages( + /*details*/ undefined, + Diagnostics._0_cannot_be_used_as_a_JSX_component, + componentName, + ); + }, + ); } else { - checkJsxReturnAssignableToAppropriateBound(getJsxReferenceKind(jsxOpeningLikeNode), getReturnTypeOfSignature(sig), jsxOpeningLikeNode); + checkJsxReturnAssignableToAppropriateBound( + getJsxReferenceKind(jsxOpeningLikeNode), + getReturnTypeOfSignature(sig), + jsxOpeningLikeNode, + ); } } } @@ -31501,10 +40289,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // is incorrect and inconsistent with element access expressions, where it is an error, so eventually // we should remove this exception. if ( - getPropertyOfObjectType(targetType, name) || - getApplicableIndexInfoForName(targetType, name) || - isLateBoundName(name) && getIndexInfoOfType(targetType, stringType) || - isComparingJsxAttributes && isHyphenatedJsxName(name) + getPropertyOfObjectType(targetType, name) + || getApplicableIndexInfoForName(targetType, name) + || isLateBoundName(name) && getIndexInfoOfType(targetType, stringType) + || isComparingJsxAttributes && isHyphenatedJsxName(name) ) { // For JSXAttributes, if the attribute has a hyphenated name, consider that the attribute to be known. return true; @@ -31521,10 +40309,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function isExcessPropertyCheckTarget(type: Type): boolean { - return !!(type.flags & TypeFlags.Object && !(getObjectFlags(type) & ObjectFlags.ObjectLiteralPatternWithComputedProperties) || - type.flags & TypeFlags.NonPrimitive || - type.flags & TypeFlags.Union && some((type as UnionType).types, isExcessPropertyCheckTarget) || - type.flags & TypeFlags.Intersection && every((type as IntersectionType).types, isExcessPropertyCheckTarget)); + return !!(type.flags & TypeFlags.Object + && !(getObjectFlags(type) & ObjectFlags.ObjectLiteralPatternWithComputedProperties) + || type.flags & TypeFlags.NonPrimitive + || type.flags & TypeFlags.Union && some((type as UnionType).types, isExcessPropertyCheckTarget) + || type.flags & TypeFlags.Intersection + && every((type as IntersectionType).types, isExcessPropertyCheckTarget)); } function checkJsxExpression(node: JsxExpression, checkMode?: CheckMode) { @@ -31555,8 +40345,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } if (isInJSFile(symbol.valueDeclaration)) { const parent = symbol.valueDeclaration!.parent; - return parent && isBinaryExpression(parent) && - getAssignmentDeclarationKind(parent) === AssignmentDeclarationKind.PrototypeProperty; + return parent && isBinaryExpression(parent) + && getAssignmentDeclarationKind(parent) === AssignmentDeclarationKind.PrototypeProperty; } } @@ -31569,17 +40359,26 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { * @param prop The symbol for the property being accessed. */ function checkPropertyAccessibility( - node: PropertyAccessExpression | QualifiedName | PropertyAccessExpression | VariableDeclaration | ParameterDeclaration | ImportTypeNode | PropertyAssignment | ShorthandPropertyAssignment | BindingElement, + node: + | PropertyAccessExpression + | QualifiedName + | PropertyAccessExpression + | VariableDeclaration + | ParameterDeclaration + | ImportTypeNode + | PropertyAssignment + | ShorthandPropertyAssignment + | BindingElement, isSuper: boolean, writing: boolean, type: Type, prop: Symbol, reportError = true, ): boolean { - const errorNode = !reportError ? undefined : - node.kind === SyntaxKind.QualifiedName ? node.right : - node.kind === SyntaxKind.ImportType ? node : - node.kind === SyntaxKind.BindingElement && node.propertyName ? node.propertyName : node.name; + const errorNode = !reportError ? undefined + : node.kind === SyntaxKind.QualifiedName ? node.right + : node.kind === SyntaxKind.ImportType ? node + : node.kind === SyntaxKind.BindingElement && node.propertyName ? node.propertyName : node.name; return checkPropertyAccessibilityAtLocation(node, isSuper, writing, type, prop, errorNode); } @@ -31594,7 +40393,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { * @param prop The symbol for the property being accessed. * @param errorNode The node where we should report an invalid property access error, or undefined if we should not report errors. */ - function checkPropertyAccessibilityAtLocation(location: Node, isSuper: boolean, writing: boolean, containingType: Type, prop: Symbol, errorNode?: Node): boolean { + function checkPropertyAccessibilityAtLocation( + location: Node, + isSuper: boolean, + writing: boolean, + containingType: Type, + prop: Symbol, + errorNode?: Node, + ): boolean { const flags = getDeclarationModifierFlagsFromSymbol(prop, writing); if (isSuper) { @@ -31608,7 +40414,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (languageVersion < ScriptTarget.ES2015) { if (symbolHasNonMethodDeclaration(prop)) { if (errorNode) { - error(errorNode, Diagnostics.Only_public_and_protected_methods_of_the_base_class_are_accessible_via_the_super_keyword); + error( + errorNode, + Diagnostics + .Only_public_and_protected_methods_of_the_base_class_are_accessible_via_the_super_keyword, + ); } return false; } @@ -31619,7 +40429,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // cannot simultaneously be private and abstract, so this will trigger an // additional error elsewhere. if (errorNode) { - error(errorNode, Diagnostics.Abstract_method_0_in_class_1_cannot_be_accessed_via_super_expression, symbolToString(prop), typeToString(getDeclaringClass(prop)!)); + error( + errorNode, + Diagnostics.Abstract_method_0_in_class_1_cannot_be_accessed_via_super_expression, + symbolToString(prop), + typeToString(getDeclaringClass(prop)!), + ); } return false; } @@ -31627,13 +40442,19 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // Referencing abstract properties within their own constructors is not allowed if ( - (flags & ModifierFlags.Abstract) && symbolHasNonMethodDeclaration(prop) && - (isThisProperty(location) || isThisInitializedObjectBindingExpression(location) || isObjectBindingPattern(location.parent) && isThisInitializedDeclaration(location.parent.parent)) + (flags & ModifierFlags.Abstract) && symbolHasNonMethodDeclaration(prop) + && (isThisProperty(location) || isThisInitializedObjectBindingExpression(location) + || isObjectBindingPattern(location.parent) && isThisInitializedDeclaration(location.parent.parent)) ) { const declaringClassDeclaration = getClassLikeDeclarationOfSymbol(getParentOfSymbol(prop)!); if (declaringClassDeclaration && isNodeUsedDuringClassInitialization(location)) { if (errorNode) { - error(errorNode, Diagnostics.Abstract_property_0_in_class_1_cannot_be_accessed_in_the_constructor, symbolToString(prop), getTextOfIdentifierOrLiteral(declaringClassDeclaration.name!)); + error( + errorNode, + Diagnostics.Abstract_property_0_in_class_1_cannot_be_accessed_in_the_constructor, + symbolToString(prop), + getTextOfIdentifierOrLiteral(declaringClassDeclaration.name!), + ); } return false; } @@ -31651,7 +40472,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const declaringClassDeclaration = getClassLikeDeclarationOfSymbol(getParentOfSymbol(prop)!)!; if (!isNodeWithinClass(location, declaringClassDeclaration)) { if (errorNode) { - error(errorNode, Diagnostics.Property_0_is_private_and_only_accessible_within_class_1, symbolToString(prop), typeToString(getDeclaringClass(prop)!)); + error( + errorNode, + Diagnostics.Property_0_is_private_and_only_accessible_within_class_1, + symbolToString(prop), + typeToString(getDeclaringClass(prop)!), + ); } return false; } @@ -31668,7 +40494,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // Find the first enclosing class that has the declaring classes of the protected constituents // of the property as base classes let enclosingClass = forEachEnclosingClass(location, enclosingDeclaration => { - const enclosingClass = getDeclaredTypeOfSymbol(getSymbolOfDeclaration(enclosingDeclaration)!) as InterfaceType; + const enclosingClass = getDeclaredTypeOfSymbol( + getSymbolOfDeclaration(enclosingDeclaration)!, + ) as InterfaceType; return isClassDerivedFromDeclaringClasses(enclosingClass, prop, writing); }); // A protected property is accessible if the property is within the declaring class or classes derived from it @@ -31679,7 +40507,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { enclosingClass = enclosingClass && isClassDerivedFromDeclaringClasses(enclosingClass, prop, writing); if (flags & ModifierFlags.Static || !enclosingClass) { if (errorNode) { - error(errorNode, Diagnostics.Property_0_is_protected_and_only_accessible_within_class_1_and_its_subclasses, symbolToString(prop), typeToString(getDeclaringClass(prop) || containingType)); + error( + errorNode, + Diagnostics.Property_0_is_protected_and_only_accessible_within_class_1_and_its_subclasses, + symbolToString(prop), + typeToString(getDeclaringClass(prop) || containingType), + ); } return false; } @@ -31690,11 +40523,20 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } if (containingType.flags & TypeFlags.TypeParameter) { // get the original type -- represented as the type constraint of the 'this' type - containingType = (containingType as TypeParameter).isThisType ? getConstraintOfTypeParameter(containingType as TypeParameter)! : getBaseConstraintOfType(containingType as TypeParameter)!; // TODO: GH#18217 Use a different variable that's allowed to be undefined + containingType = (containingType as TypeParameter).isThisType + ? getConstraintOfTypeParameter(containingType as TypeParameter)! + : getBaseConstraintOfType(containingType as TypeParameter)!; // TODO: GH#18217 Use a different variable that's allowed to be undefined } if (!containingType || !hasBaseType(containingType, enclosingClass)) { if (errorNode) { - error(errorNode, Diagnostics.Property_0_is_protected_and_only_accessible_through_an_instance_of_class_1_This_is_an_instance_of_class_2, symbolToString(prop), typeToString(enclosingClass), typeToString(containingType)); + error( + errorNode, + Diagnostics + .Property_0_is_protected_and_only_accessible_through_an_instance_of_class_1_This_is_an_instance_of_class_2, + symbolToString(prop), + typeToString(enclosingClass), + typeToString(containingType), + ); } return false; } @@ -31714,7 +40556,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function getThisParameterFromNodeContext(node: Node) { - const thisContainer = getThisContainer(node, /*includeArrowFunctions*/ false, /*includeClassComputedPropertyName*/ false); + const thisContainer = getThisContainer( + node, + /*includeArrowFunctions*/ false, + /*includeClassComputedPropertyName*/ false, + ); return thisContainer && isFunctionLike(thisContainer) ? getThisParameter(thisContainer) : undefined; } @@ -31747,20 +40593,20 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } error( node, - facts & TypeFacts.IsUndefined ? facts & TypeFacts.IsNull ? - Diagnostics._0_is_possibly_null_or_undefined : - Diagnostics._0_is_possibly_undefined : - Diagnostics._0_is_possibly_null, + facts & TypeFacts.IsUndefined ? facts & TypeFacts.IsNull + ? Diagnostics._0_is_possibly_null_or_undefined + : Diagnostics._0_is_possibly_undefined + : Diagnostics._0_is_possibly_null, nodeText, ); } else { error( node, - facts & TypeFacts.IsUndefined ? facts & TypeFacts.IsNull ? - Diagnostics.Object_is_possibly_null_or_undefined : - Diagnostics.Object_is_possibly_undefined : - Diagnostics.Object_is_possibly_null, + facts & TypeFacts.IsUndefined ? facts & TypeFacts.IsNull + ? Diagnostics.Object_is_possibly_null_or_undefined + : Diagnostics.Object_is_possibly_undefined + : Diagnostics.Object_is_possibly_null, ); } } @@ -31768,10 +40614,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function reportCannotInvokePossiblyNullOrUndefinedError(node: Node, facts: TypeFacts) { error( node, - facts & TypeFacts.IsUndefined ? facts & TypeFacts.IsNull ? - Diagnostics.Cannot_invoke_an_object_which_is_possibly_null_or_undefined : - Diagnostics.Cannot_invoke_an_object_which_is_possibly_undefined : - Diagnostics.Cannot_invoke_an_object_which_is_possibly_null, + facts & TypeFacts.IsUndefined ? facts & TypeFacts.IsNull + ? Diagnostics.Cannot_invoke_an_object_which_is_possibly_null_or_undefined + : Diagnostics.Cannot_invoke_an_object_which_is_possibly_undefined + : Diagnostics.Cannot_invoke_an_object_which_is_possibly_null, ); } @@ -31823,19 +40669,41 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return nonNullType; } - function checkPropertyAccessExpression(node: PropertyAccessExpression, checkMode: CheckMode | undefined, writeOnly?: boolean) { - return node.flags & NodeFlags.OptionalChain ? checkPropertyAccessChain(node as PropertyAccessChain, checkMode) : - checkPropertyAccessExpressionOrQualifiedName(node, node.expression, checkNonNullExpression(node.expression), node.name, checkMode, writeOnly); + function checkPropertyAccessExpression( + node: PropertyAccessExpression, + checkMode: CheckMode | undefined, + writeOnly?: boolean, + ) { + return node.flags & NodeFlags.OptionalChain ? checkPropertyAccessChain(node as PropertyAccessChain, checkMode) + : checkPropertyAccessExpressionOrQualifiedName( + node, + node.expression, + checkNonNullExpression(node.expression), + node.name, + checkMode, + writeOnly, + ); } function checkPropertyAccessChain(node: PropertyAccessChain, checkMode: CheckMode | undefined) { const leftType = checkExpression(node.expression); const nonOptionalType = getOptionalExpressionType(leftType, node.expression); - return propagateOptionalTypeMarker(checkPropertyAccessExpressionOrQualifiedName(node, node.expression, checkNonNullType(nonOptionalType, node.expression), node.name, checkMode), node, nonOptionalType !== leftType); + return propagateOptionalTypeMarker( + checkPropertyAccessExpressionOrQualifiedName( + node, + node.expression, + checkNonNullType(nonOptionalType, node.expression), + node.name, + checkMode, + ), + node, + nonOptionalType !== leftType, + ); } function checkQualifiedName(node: QualifiedName, checkMode: CheckMode | undefined) { - const leftType = isPartOfTypeQuery(node) && isThisIdentifier(node.left) ? checkNonNullType(checkThisExpression(node.left), node.left) : checkNonNullExpression(node.left); + const leftType = isPartOfTypeQuery(node) && isThisIdentifier(node.left) + ? checkNonNullType(checkThisExpression(node.left), node.left) : checkNonNullExpression(node.left); return checkPropertyAccessExpressionOrQualifiedName(node, node.left, leftType, node.right, checkMode); } @@ -31848,7 +40716,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // Lookup the private identifier lexically. function lookupSymbolForPrivateIdentifierDeclaration(propName: __String, location: Node): Symbol | undefined { - for (let containingClass = getContainingClassExcludingClassDecorators(location); !!containingClass; containingClass = getContainingClass(containingClass)) { + for ( + let containingClass = getContainingClassExcludingClassDecorators(location); + !!containingClass; + containingClass = getContainingClass(containingClass) + ) { const { symbol } = containingClass; const name = getSymbolNameForPrivateIdentifier(symbol, propName); const prop = (symbol.members && symbol.members.get(name)) || (symbol.exports && symbol.exports.get(name)); @@ -31865,10 +40737,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (!isForInStatement(privId.parent)) { if (!isExpressionNode(privId)) { - return grammarErrorOnNode(privId, Diagnostics.Private_identifiers_are_only_allowed_in_class_bodies_and_may_only_be_used_as_part_of_a_class_member_declaration_property_access_or_on_the_left_hand_side_of_an_in_expression); + return grammarErrorOnNode( + privId, + Diagnostics + .Private_identifiers_are_only_allowed_in_class_bodies_and_may_only_be_used_as_part_of_a_class_member_declaration_property_access_or_on_the_left_hand_side_of_an_in_expression, + ); } - const isInOperation = isBinaryExpression(privId.parent) && privId.parent.operatorToken.kind === SyntaxKind.InKeyword; + const isInOperation = isBinaryExpression(privId.parent) + && privId.parent.operatorToken.kind === SyntaxKind.InKeyword; if (!getSymbolForPrivateIdentifierExpression(privId) && !isInOperation) { return grammarErrorOnNode(privId, Diagnostics.Cannot_find_name_0, idText(privId)); } @@ -31902,7 +40779,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return getPropertyOfType(leftType, lexicallyScopedIdentifier.escapedName); } - function checkPrivateIdentifierPropertyAccess(leftType: Type, right: PrivateIdentifier, lexicallyScopedIdentifier: Symbol | undefined): boolean { + function checkPrivateIdentifierPropertyAccess( + leftType: Type, + right: PrivateIdentifier, + lexicallyScopedIdentifier: Symbol | undefined, + ): boolean { // Either the identifier could not be looked up in the lexical scope OR the lexically scoped identifier did not exist on the type. // Find a private identifier with the same description on the type. let propertyOnType: Symbol | undefined; @@ -31910,7 +40791,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (properties) { forEach(properties, (symbol: Symbol) => { const decl = symbol.valueDeclaration; - if (decl && isNamedDeclaration(decl) && isPrivateIdentifier(decl.name) && decl.name.escapedText === right.escapedText) { + if ( + decl && isNamedDeclaration(decl) && isPrivateIdentifier(decl.name) + && decl.name.escapedText === right.escapedText + ) { propertyOnType = symbol; return true; } @@ -31931,7 +40815,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (findAncestor(lexicalClass, n => typeClass === n)) { const diagnostic = error( right, - Diagnostics.The_property_0_cannot_be_accessed_on_type_1_within_this_class_because_it_is_shadowed_by_another_private_identifier_with_the_same_spelling, + Diagnostics + .The_property_0_cannot_be_accessed_on_type_1_within_this_class_because_it_is_shadowed_by_another_private_identifier_with_the_same_spelling, diagName, typeToString(leftType), ); @@ -31963,15 +40848,28 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return false; } - function isThisPropertyAccessInConstructor(node: ElementAccessExpression | PropertyAccessExpression | QualifiedName, prop: Symbol) { + function isThisPropertyAccessInConstructor( + node: ElementAccessExpression | PropertyAccessExpression | QualifiedName, + prop: Symbol, + ) { return (isConstructorDeclaredProperty(prop) || isThisProperty(node) && isAutoTypedProperty(prop)) - && getThisContainer(node, /*includeArrowFunctions*/ true, /*includeClassComputedPropertyName*/ false) === getDeclaringConstructor(prop); + && getThisContainer(node, /*includeArrowFunctions*/ true, /*includeClassComputedPropertyName*/ false) + === getDeclaringConstructor(prop); } - function checkPropertyAccessExpressionOrQualifiedName(node: PropertyAccessExpression | QualifiedName, left: Expression | QualifiedName, leftType: Type, right: Identifier | PrivateIdentifier, checkMode: CheckMode | undefined, writeOnly?: boolean) { + function checkPropertyAccessExpressionOrQualifiedName( + node: PropertyAccessExpression | QualifiedName, + left: Expression | QualifiedName, + leftType: Type, + right: Identifier | PrivateIdentifier, + checkMode: CheckMode | undefined, + writeOnly?: boolean, + ) { const parentSymbol = getNodeLinks(left).resolvedSymbol; const assignmentKind = getAssignmentTargetKind(node); - const apparentType = getApparentType(assignmentKind !== AssignmentKind.None || isMethodAccessForCall(node) ? getWidenedType(leftType) : leftType); + const apparentType = getApparentType( + assignmentKind !== AssignmentKind.None || isMethodAccessForCall(node) ? getWidenedType(leftType) : leftType, + ); const isAnyLike = isTypeAny(apparentType) || apparentType === silentNeverType; let prop: Symbol | undefined; if (isPrivateIdentifier(right)) { @@ -31985,8 +40883,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } const lexicallyScopedSymbol = lookupSymbolForPrivateIdentifierDeclaration(right.escapedText, right); - if (assignmentKind && lexicallyScopedSymbol && lexicallyScopedSymbol.valueDeclaration && isMethodDeclaration(lexicallyScopedSymbol.valueDeclaration)) { - grammarErrorOnNode(right, Diagnostics.Cannot_assign_to_private_method_0_Private_methods_are_not_writable, idText(right)); + if ( + assignmentKind && lexicallyScopedSymbol && lexicallyScopedSymbol.valueDeclaration + && isMethodDeclaration(lexicallyScopedSymbol.valueDeclaration) + ) { + grammarErrorOnNode( + right, + Diagnostics.Cannot_assign_to_private_method_0_Private_methods_are_not_writable, + idText(right), + ); } if (isAnyLike) { if (lexicallyScopedSymbol) { @@ -32006,11 +40911,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } const containingClass = getContainingClassExcludingClassDecorators(right); if (containingClass && isPlainJsFile(getSourceFileOfNode(containingClass), compilerOptions.checkJs)) { - grammarErrorOnNode(right, Diagnostics.Private_field_0_must_be_declared_in_an_enclosing_class, idText(right)); + grammarErrorOnNode( + right, + Diagnostics.Private_field_0_must_be_declared_in_an_enclosing_class, + idText(right), + ); } } else { - const isSetonlyAccessor = prop.flags & SymbolFlags.SetAccessor && !(prop.flags & SymbolFlags.GetAccessor); + const isSetonlyAccessor = prop.flags & SymbolFlags.SetAccessor + && !(prop.flags & SymbolFlags.GetAccessor); if (isSetonlyAccessor && assignmentKind !== AssignmentKind.Definite) { error(node, Diagnostics.Private_accessor_was_defined_without_a_getter); } @@ -32023,7 +40933,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } return isErrorType(apparentType) ? errorType : apparentType; } - prop = getPropertyOfType(apparentType, right.escapedText, /*skipObjectFunctionPropertyAugment*/ false, /*includeTypeOnlyMembers*/ node.kind === SyntaxKind.QualifiedName); + prop = getPropertyOfType( + apparentType, + right.escapedText, + /*skipObjectFunctionPropertyAugment*/ false, + /*includeTypeOnlyMembers*/ node.kind === SyntaxKind.QualifiedName, + ); } // In `Foo.Bar.Baz`, 'Foo' is not referenced if 'Bar' is a const enum or a module containing only const enums. // `Foo` is also not referenced in `enum FooCopy { Bar = Foo.Bar }`, because the enum member value gets inlined @@ -32034,9 +40949,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // 2. if 'preserveConstEnums' is enabled and the expression is itself an export, e.g. `export = Foo.Bar.Baz`. if ( isIdentifier(left) && parentSymbol && ( - getIsolatedModules(compilerOptions) || - !(prop && (isConstEnumOrConstEnumOnlyModule(prop) || prop.flags & SymbolFlags.EnumMember && node.parent.kind === SyntaxKind.EnumMember)) || - shouldPreserveConstEnums(compilerOptions) && isExportOrExportExpression(node) + getIsolatedModules(compilerOptions) + || !(prop + && (isConstEnumOrConstEnumOnlyModule(prop) + || prop.flags & SymbolFlags.EnumMember && node.parent.kind === SyntaxKind.EnumMember)) + || shouldPreserveConstEnums(compilerOptions) && isExportOrExportExpression(node) ) ) { markAliasReferenced(parentSymbol, node); @@ -32044,24 +40961,42 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { let propType: Type; if (!prop) { - const indexInfo = !isPrivateIdentifier(right) && (assignmentKind === AssignmentKind.None || !isGenericObjectType(leftType) || isThisTypeParameter(leftType)) ? - getApplicableIndexInfoForName(apparentType, right.escapedText) : undefined; + const indexInfo = !isPrivateIdentifier(right) + && (assignmentKind === AssignmentKind.None || !isGenericObjectType(leftType) + || isThisTypeParameter(leftType)) + ? getApplicableIndexInfoForName(apparentType, right.escapedText) : undefined; if (!(indexInfo && indexInfo.type)) { const isUncheckedJS = isUncheckedJSSuggestion(node, leftType.symbol, /*excludeClasses*/ true); if (!isUncheckedJS && isJSLiteralType(leftType)) { return anyType; } if (leftType.symbol === globalThisSymbol) { - if (globalThisSymbol.exports!.has(right.escapedText) && (globalThisSymbol.exports!.get(right.escapedText)!.flags & SymbolFlags.BlockScoped)) { - error(right, Diagnostics.Property_0_does_not_exist_on_type_1, unescapeLeadingUnderscores(right.escapedText), typeToString(leftType)); + if ( + globalThisSymbol.exports!.has(right.escapedText) + && (globalThisSymbol.exports!.get(right.escapedText)!.flags & SymbolFlags.BlockScoped) + ) { + error( + right, + Diagnostics.Property_0_does_not_exist_on_type_1, + unescapeLeadingUnderscores(right.escapedText), + typeToString(leftType), + ); } else if (noImplicitAny) { - error(right, Diagnostics.Element_implicitly_has_an_any_type_because_type_0_has_no_index_signature, typeToString(leftType)); + error( + right, + Diagnostics.Element_implicitly_has_an_any_type_because_type_0_has_no_index_signature, + typeToString(leftType), + ); } return anyType; } if (right.escapedText && !checkAndReportErrorForExtendingInterface(node)) { - reportNonexistentProperty(right, isThisTypeParameter(leftType) ? apparentType : leftType, isUncheckedJS); + reportNonexistentProperty( + right, + isThisTypeParameter(leftType) ? apparentType : leftType, + isUncheckedJS, + ); } return errorType; } @@ -32069,9 +41004,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { error(node, Diagnostics.Index_signature_in_type_0_only_permits_reading, typeToString(apparentType)); } - propType = (compilerOptions.noUncheckedIndexedAccess && !isAssignmentTarget(node)) ? getUnionType([indexInfo.type, missingType]) : indexInfo.type; + propType = (compilerOptions.noUncheckedIndexedAccess && !isAssignmentTarget(node)) + ? getUnionType([indexInfo.type, missingType]) : indexInfo.type; if (compilerOptions.noPropertyAccessFromIndexSignature && isPropertyAccessExpression(node)) { - error(right, Diagnostics.Property_0_comes_from_an_index_signature_so_it_must_be_accessed_with_0, unescapeLeadingUnderscores(right.escapedText)); + error( + right, + Diagnostics.Property_0_comes_from_an_index_signature_so_it_must_be_accessed_with_0, + unescapeLeadingUnderscores(right.escapedText), + ); } if (indexInfo.declaration && isDeprecatedDeclaration(indexInfo.declaration)) { addDeprecatedSuggestion(right, [indexInfo.declaration], right.escapedText as string); @@ -32079,19 +41019,29 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } else { const targetPropSymbol = resolveAliasWithDeprecationCheck(prop, right); - if (isDeprecatedSymbol(targetPropSymbol) && isUncalledFunctionReference(node, targetPropSymbol) && targetPropSymbol.declarations) { + if ( + isDeprecatedSymbol(targetPropSymbol) && isUncalledFunctionReference(node, targetPropSymbol) + && targetPropSymbol.declarations + ) { addDeprecatedSuggestion(right, targetPropSymbol.declarations, right.escapedText as string); } checkPropertyNotUsedBeforeDeclaration(prop, node, right); markPropertyAsReferenced(prop, node, isSelfTypeAccess(left, parentSymbol)); getNodeLinks(node).resolvedSymbol = prop; - checkPropertyAccessibility(node, left.kind === SyntaxKind.SuperKeyword, isWriteAccess(node), apparentType, prop); + checkPropertyAccessibility( + node, + left.kind === SyntaxKind.SuperKeyword, + isWriteAccess(node), + apparentType, + prop, + ); if (isAssignmentToReadonlyEntity(node as Expression, prop, assignmentKind)) { error(right, Diagnostics.Cannot_assign_to_0_because_it_is_a_read_only_property, idText(right)); return errorType; } - propType = isThisPropertyAccessInConstructor(node, prop) ? autoType : writeOnly || isWriteOnlyAccess(node) ? getWriteTypeOfSymbol(prop) : getTypeOfSymbol(prop); + propType = isThisPropertyAccessInConstructor(node, prop) ? autoType + : writeOnly || isWriteOnlyAccess(node) ? getWriteTypeOfSymbol(prop) : getTypeOfSymbol(prop); } return getFlowTypeOfAccessExpression(node, prop, propType, right, checkMode); @@ -32104,20 +41054,34 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { * - Is from a global file that is different from the reference file, or * - (optionally) Is a class, or is a this.x property access expression */ - function isUncheckedJSSuggestion(node: Node | undefined, suggestion: Symbol | undefined, excludeClasses: boolean): boolean { + function isUncheckedJSSuggestion( + node: Node | undefined, + suggestion: Symbol | undefined, + excludeClasses: boolean, + ): boolean { const file = getSourceFileOfNode(node); if (file) { - if (compilerOptions.checkJs === undefined && file.checkJsDirective === undefined && (file.scriptKind === ScriptKind.JS || file.scriptKind === ScriptKind.JSX)) { + if ( + compilerOptions.checkJs === undefined && file.checkJsDirective === undefined + && (file.scriptKind === ScriptKind.JS || file.scriptKind === ScriptKind.JSX) + ) { const declarationFile = forEach(suggestion?.declarations, getSourceFileOfNode); return !(file !== declarationFile && !!declarationFile && isGlobalSourceFile(declarationFile)) && !(excludeClasses && suggestion && suggestion.flags & SymbolFlags.Class) - && !(!!node && excludeClasses && isPropertyAccessExpression(node) && node.expression.kind === SyntaxKind.ThisKeyword); + && !(!!node && excludeClasses && isPropertyAccessExpression(node) + && node.expression.kind === SyntaxKind.ThisKeyword); } } return false; } - function getFlowTypeOfAccessExpression(node: ElementAccessExpression | PropertyAccessExpression | QualifiedName, prop: Symbol | undefined, propType: Type, errorNode: Node, checkMode: CheckMode | undefined) { + function getFlowTypeOfAccessExpression( + node: ElementAccessExpression | PropertyAccessExpression | QualifiedName, + prop: Symbol | undefined, + propType: Type, + errorNode: Node, + checkMode: CheckMode | undefined, + ) { // Only compute control flow type if this is a property access expression that isn't an // assignment target, and the referenced property was declared as a variable, property, // accessor, or optional method. @@ -32126,8 +41090,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return removeMissingType(propType, !!(prop && prop.flags & SymbolFlags.Optional)); } if ( - prop && - !(prop.flags & (SymbolFlags.Variable | SymbolFlags.Property | SymbolFlags.Accessor)) + prop + && !(prop.flags & (SymbolFlags.Variable | SymbolFlags.Property | SymbolFlags.Accessor)) && !(prop.flags & SymbolFlags.Method && propType.flags & TypeFlags.Union) && !isDuplicatedCommonJSExport(prop.declarations) ) { @@ -32142,26 +41106,36 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // and if we are in a constructor of the same class as the property declaration, assume that // the property is uninitialized at the top of the control flow. let assumeUninitialized = false; - if (strictNullChecks && strictPropertyInitialization && isAccessExpression(node) && node.expression.kind === SyntaxKind.ThisKeyword) { + if ( + strictNullChecks && strictPropertyInitialization && isAccessExpression(node) + && node.expression.kind === SyntaxKind.ThisKeyword + ) { const declaration = prop && prop.valueDeclaration; if (declaration && isPropertyWithoutInitializer(declaration)) { if (!isStatic(declaration)) { const flowContainer = getControlFlowContainer(node); - if (flowContainer.kind === SyntaxKind.Constructor && flowContainer.parent === declaration.parent && !(declaration.flags & NodeFlags.Ambient)) { + if ( + flowContainer.kind === SyntaxKind.Constructor && flowContainer.parent === declaration.parent + && !(declaration.flags & NodeFlags.Ambient) + ) { assumeUninitialized = true; } } } } else if ( - strictNullChecks && prop && prop.valueDeclaration && - isPropertyAccessExpression(prop.valueDeclaration) && - getAssignmentDeclarationPropertyAccessKind(prop.valueDeclaration) && - getControlFlowContainer(node) === getControlFlowContainer(prop.valueDeclaration) + strictNullChecks && prop && prop.valueDeclaration + && isPropertyAccessExpression(prop.valueDeclaration) + && getAssignmentDeclarationPropertyAccessKind(prop.valueDeclaration) + && getControlFlowContainer(node) === getControlFlowContainer(prop.valueDeclaration) ) { assumeUninitialized = true; } - const flowType = getFlowTypeOfReference(node, propType, assumeUninitialized ? getOptionalType(propType) : propType); + const flowType = getFlowTypeOfReference( + node, + propType, + assumeUninitialized ? getOptionalType(propType) : propType, + ); if (assumeUninitialized && !containsUndefinedType(propType) && containsUndefinedType(flowType)) { error(errorNode, Diagnostics.Property_0_is_used_before_being_assigned, symbolToString(prop!)); // TODO: GH#18217 // Return the declared type to reduce follow-on errors @@ -32170,7 +41144,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return assignmentKind ? getBaseTypeOfLiteralType(flowType) : flowType; } - function checkPropertyNotUsedBeforeDeclaration(prop: Symbol, node: PropertyAccessExpression | QualifiedName, right: Identifier | PrivateIdentifier): void { + function checkPropertyNotUsedBeforeDeclaration( + prop: Symbol, + node: PropertyAccessExpression | QualifiedName, + right: Identifier | PrivateIdentifier, + ): void { const { valueDeclaration } = prop; if (!valueDeclaration || getSourceFileOfNode(node).isDeclarationFile) { return; @@ -32183,22 +41161,26 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { && !isOptionalPropertyDeclaration(valueDeclaration) && !(isAccessExpression(node) && isAccessExpression(node.expression)) && !isBlockScopedNameDeclaredBeforeUse(valueDeclaration, right) - && !(isMethodDeclaration(valueDeclaration) && getCombinedModifierFlagsCached(valueDeclaration) & ModifierFlags.Static) + && !(isMethodDeclaration(valueDeclaration) + && getCombinedModifierFlagsCached(valueDeclaration) & ModifierFlags.Static) && (useDefineForClassFields || !isPropertyDeclaredInAncestorClass(prop)) ) { diagnosticMessage = error(right, Diagnostics.Property_0_is_used_before_its_initialization, declarationName); } else if ( - valueDeclaration.kind === SyntaxKind.ClassDeclaration && - node.parent.kind !== SyntaxKind.TypeReference && - !(valueDeclaration.flags & NodeFlags.Ambient) && - !isBlockScopedNameDeclaredBeforeUse(valueDeclaration, right) + valueDeclaration.kind === SyntaxKind.ClassDeclaration + && node.parent.kind !== SyntaxKind.TypeReference + && !(valueDeclaration.flags & NodeFlags.Ambient) + && !isBlockScopedNameDeclaredBeforeUse(valueDeclaration, right) ) { diagnosticMessage = error(right, Diagnostics.Class_0_used_before_its_declaration, declarationName); } if (diagnosticMessage) { - addRelatedInfo(diagnosticMessage, createDiagnosticForNode(valueDeclaration, Diagnostics._0_is_declared_here, declarationName)); + addRelatedInfo( + diagnosticMessage, + createDiagnosticForNode(valueDeclaration, Diagnostics._0_is_declared_here, declarationName), + ); } } @@ -32260,13 +41242,28 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return getIntersectionType(x); } - function reportNonexistentProperty(propNode: Identifier | PrivateIdentifier, containingType: Type, isUncheckedJS: boolean) { + function reportNonexistentProperty( + propNode: Identifier | PrivateIdentifier, + containingType: Type, + isUncheckedJS: boolean, + ) { let errorInfo: DiagnosticMessageChain | undefined; let relatedInfo: Diagnostic | undefined; - if (!isPrivateIdentifier(propNode) && containingType.flags & TypeFlags.Union && !(containingType.flags & TypeFlags.Primitive)) { + if ( + !isPrivateIdentifier(propNode) && containingType.flags & TypeFlags.Union + && !(containingType.flags & TypeFlags.Primitive) + ) { for (const subtype of (containingType as UnionType).types) { - if (!getPropertyOfType(subtype, propNode.escapedText) && !getApplicableIndexInfoForName(subtype, propNode.escapedText)) { - errorInfo = chainDiagnosticMessages(errorInfo, Diagnostics.Property_0_does_not_exist_on_type_1, declarationNameToString(propNode), typeToString(subtype)); + if ( + !getPropertyOfType(subtype, propNode.escapedText) + && !getApplicableIndexInfoForName(subtype, propNode.escapedText) + ) { + errorInfo = chainDiagnosticMessages( + errorInfo, + Diagnostics.Property_0_does_not_exist_on_type_1, + declarationNameToString(propNode), + typeToString(subtype), + ); break; } } @@ -32274,12 +41271,23 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (typeHasStaticProperty(propNode.escapedText, containingType)) { const propName = declarationNameToString(propNode); const typeName = typeToString(containingType); - errorInfo = chainDiagnosticMessages(errorInfo, Diagnostics.Property_0_does_not_exist_on_type_1_Did_you_mean_to_access_the_static_member_2_instead, propName, typeName, typeName + "." + propName); + errorInfo = chainDiagnosticMessages( + errorInfo, + Diagnostics.Property_0_does_not_exist_on_type_1_Did_you_mean_to_access_the_static_member_2_instead, + propName, + typeName, + typeName + "." + propName, + ); } else { const promisedType = getPromisedTypeOfPromise(containingType); if (promisedType && getPropertyOfType(promisedType, propNode.escapedText)) { - errorInfo = chainDiagnosticMessages(errorInfo, Diagnostics.Property_0_does_not_exist_on_type_1, declarationNameToString(propNode), typeToString(containingType)); + errorInfo = chainDiagnosticMessages( + errorInfo, + Diagnostics.Property_0_does_not_exist_on_type_1, + declarationNameToString(propNode), + typeToString(containingType), + ); relatedInfo = createDiagnosticForNode(propNode, Diagnostics.Did_you_forget_to_use_await); } else { @@ -32287,36 +41295,75 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const container = typeToString(containingType); const libSuggestion = getSuggestedLibForNonExistentProperty(missingProperty, containingType); if (libSuggestion !== undefined) { - errorInfo = chainDiagnosticMessages(errorInfo, Diagnostics.Property_0_does_not_exist_on_type_1_Do_you_need_to_change_your_target_library_Try_changing_the_lib_compiler_option_to_2_or_later, missingProperty, container, libSuggestion); + errorInfo = chainDiagnosticMessages( + errorInfo, + Diagnostics + .Property_0_does_not_exist_on_type_1_Do_you_need_to_change_your_target_library_Try_changing_the_lib_compiler_option_to_2_or_later, + missingProperty, + container, + libSuggestion, + ); } else { const suggestion = getSuggestedSymbolForNonexistentProperty(propNode, containingType); if (suggestion !== undefined) { const suggestedName = symbolName(suggestion); - const message = isUncheckedJS ? Diagnostics.Property_0_may_not_exist_on_type_1_Did_you_mean_2 : Diagnostics.Property_0_does_not_exist_on_type_1_Did_you_mean_2; - errorInfo = chainDiagnosticMessages(errorInfo, message, missingProperty, container, suggestedName); - relatedInfo = suggestion.valueDeclaration && createDiagnosticForNode(suggestion.valueDeclaration, Diagnostics._0_is_declared_here, suggestedName); + const message = isUncheckedJS ? Diagnostics.Property_0_may_not_exist_on_type_1_Did_you_mean_2 + : Diagnostics.Property_0_does_not_exist_on_type_1_Did_you_mean_2; + errorInfo = chainDiagnosticMessages( + errorInfo, + message, + missingProperty, + container, + suggestedName, + ); + relatedInfo = suggestion.valueDeclaration + && createDiagnosticForNode( + suggestion.valueDeclaration, + Diagnostics._0_is_declared_here, + suggestedName, + ); } else { const diagnostic = containerSeemsToBeEmptyDomElement(containingType) - ? Diagnostics.Property_0_does_not_exist_on_type_1_Try_changing_the_lib_compiler_option_to_include_dom + ? Diagnostics + .Property_0_does_not_exist_on_type_1_Try_changing_the_lib_compiler_option_to_include_dom : Diagnostics.Property_0_does_not_exist_on_type_1; - errorInfo = chainDiagnosticMessages(elaborateNeverIntersection(errorInfo, containingType), diagnostic, missingProperty, container); + errorInfo = chainDiagnosticMessages( + elaborateNeverIntersection(errorInfo, containingType), + diagnostic, + missingProperty, + container, + ); } } } } - const resultDiagnostic = createDiagnosticForNodeFromMessageChain(getSourceFileOfNode(propNode), propNode, errorInfo); + const resultDiagnostic = createDiagnosticForNodeFromMessageChain( + getSourceFileOfNode(propNode), + propNode, + errorInfo, + ); if (relatedInfo) { addRelatedInfo(resultDiagnostic, relatedInfo); } - addErrorOrSuggestion(!isUncheckedJS || errorInfo.code !== Diagnostics.Property_0_may_not_exist_on_type_1_Did_you_mean_2.code, resultDiagnostic); + addErrorOrSuggestion( + !isUncheckedJS || errorInfo.code !== Diagnostics.Property_0_may_not_exist_on_type_1_Did_you_mean_2.code, + resultDiagnostic, + ); } function containerSeemsToBeEmptyDomElement(containingType: Type) { - return (compilerOptions.lib && !compilerOptions.lib.includes("dom")) && - everyContainedType(containingType, type => type.symbol && /^(EventTarget|Node|((HTML[a-zA-Z]*)?Element))$/.test(unescapeLeadingUnderscores(type.symbol.escapedName))) && - isEmptyObjectType(containingType); + return (compilerOptions.lib && !compilerOptions.lib.includes("dom")) + && everyContainedType( + containingType, + type => + type.symbol + && /^(EventTarget|Node|((HTML[a-zA-Z]*)?Element))$/.test( + unescapeLeadingUnderscores(type.symbol.escapedName), + ), + ) + && isEmptyObjectType(containingType); } function typeHasStaticProperty(propName: __String, containingType: Type): boolean { @@ -32352,7 +41399,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return getSpellingSuggestionForName(name, getPropertiesOfType(baseType), SymbolFlags.ClassMember); } - function getSuggestedSymbolForNonexistentProperty(name: Identifier | PrivateIdentifier | string, containingType: Type): Symbol | undefined { + function getSuggestedSymbolForNonexistentProperty( + name: Identifier | PrivateIdentifier | string, + containingType: Type, + ): Symbol | undefined { let props = getPropertiesOfType(containingType); if (typeof name !== "string") { const parent = name.parent; @@ -32364,7 +41414,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return getSpellingSuggestionForName(name, props, SymbolFlags.Value); } - function getSuggestedSymbolForNonexistentJSXAttribute(name: Identifier | PrivateIdentifier | string, containingType: Type): Symbol | undefined { + function getSuggestedSymbolForNonexistentJSXAttribute( + name: Identifier | PrivateIdentifier | string, + containingType: Type, + ): Symbol | undefined { const strName = isString(name) ? name : idText(name); const properties = getPropertiesOfType(containingType); const jsxSpecific = strName === "for" ? find(properties, x => symbolName(x) === "htmlFor") @@ -32373,45 +41426,71 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return jsxSpecific ?? getSpellingSuggestionForName(strName, properties, SymbolFlags.Value); } - function getSuggestionForNonexistentProperty(name: Identifier | PrivateIdentifier | string, containingType: Type): string | undefined { + function getSuggestionForNonexistentProperty( + name: Identifier | PrivateIdentifier | string, + containingType: Type, + ): string | undefined { const suggestion = getSuggestedSymbolForNonexistentProperty(name, containingType); return suggestion && symbolName(suggestion); } - function getSuggestedSymbolForNonexistentSymbol(location: Node | undefined, outerName: __String, meaning: SymbolFlags): Symbol | undefined { + function getSuggestedSymbolForNonexistentSymbol( + location: Node | undefined, + outerName: __String, + meaning: SymbolFlags, + ): Symbol | undefined { Debug.assert(outerName !== undefined, "outername should always be defined"); - const result = resolveNameHelper(location, outerName, meaning, /*nameNotFoundMessage*/ undefined, outerName, /*isUse*/ false, /*excludeGlobals*/ false, /*getSpellingSuggestions*/ true, (symbols, name, meaning) => { - Debug.assertEqual(outerName, name, "name should equal outerName"); - const symbol = getSymbol(symbols, name, meaning); - // Sometimes the symbol is found when location is a return type of a function: `typeof x` and `x` is declared in the body of the function - // So the table *contains* `x` but `x` isn't actually in scope. - // However, resolveNameHelper will continue and call this callback again, so we'll eventually get a correct suggestion. - if (symbol) return symbol; - let candidates: Symbol[]; - if (symbols === globals) { - const primitives = mapDefined( - ["string", "number", "boolean", "object", "bigint", "symbol"], - s => symbols.has((s.charAt(0).toUpperCase() + s.slice(1)) as __String) - ? createSymbol(SymbolFlags.TypeAlias, s as __String) as Symbol - : undefined, - ); - candidates = primitives.concat(arrayFrom(symbols.values())); - } - else { - candidates = arrayFrom(symbols.values()); - } - return getSpellingSuggestionForName(unescapeLeadingUnderscores(name), candidates, meaning); - }); + const result = resolveNameHelper( + location, + outerName, + meaning, + /*nameNotFoundMessage*/ undefined, + outerName, + /*isUse*/ false, + /*excludeGlobals*/ false, + /*getSpellingSuggestions*/ true, + (symbols, name, meaning) => { + Debug.assertEqual(outerName, name, "name should equal outerName"); + const symbol = getSymbol(symbols, name, meaning); + // Sometimes the symbol is found when location is a return type of a function: `typeof x` and `x` is declared in the body of the function + // So the table *contains* `x` but `x` isn't actually in scope. + // However, resolveNameHelper will continue and call this callback again, so we'll eventually get a correct suggestion. + if (symbol) return symbol; + let candidates: Symbol[]; + if (symbols === globals) { + const primitives = mapDefined( + ["string", "number", "boolean", "object", "bigint", "symbol"], + s => symbols.has((s.charAt(0).toUpperCase() + s.slice(1)) as __String) + ? createSymbol(SymbolFlags.TypeAlias, s as __String) as Symbol + : undefined, + ); + candidates = primitives.concat(arrayFrom(symbols.values())); + } + else { + candidates = arrayFrom(symbols.values()); + } + return getSpellingSuggestionForName(unescapeLeadingUnderscores(name), candidates, meaning); + }, + ); return result; } - function getSuggestionForNonexistentSymbol(location: Node | undefined, outerName: __String, meaning: SymbolFlags): string | undefined { + function getSuggestionForNonexistentSymbol( + location: Node | undefined, + outerName: __String, + meaning: SymbolFlags, + ): string | undefined { const symbolResult = getSuggestedSymbolForNonexistentSymbol(location, outerName, meaning); return symbolResult && symbolName(symbolResult); } function getSuggestedSymbolForNonexistentModule(name: Identifier, targetModule: Symbol): Symbol | undefined { - return targetModule.exports && getSpellingSuggestionForName(idText(name), getExportsOfModuleAsArray(targetModule), SymbolFlags.ModuleMember); + return targetModule.exports + && getSpellingSuggestionForName( + idText(name), + getExportsOfModuleAsArray(targetModule), + SymbolFlags.ModuleMember, + ); } function getSuggestionForNonexistentExport(name: Identifier, targetModule: Symbol): string | undefined { @@ -32419,7 +41498,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return suggestion && symbolName(suggestion); } - function getSuggestionForNonexistentIndexSignature(objectType: Type, expr: ElementAccessExpression, keyedType: Type): string | undefined { + function getSuggestionForNonexistentIndexSignature( + objectType: Type, + expr: ElementAccessExpression, + keyedType: Type, + ): string | undefined { // check if object type has setter or getter function hasProp(name: "set" | "get") { const prop = getPropertyOfObjectType(objectType, name as __String); @@ -32446,8 +41529,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return suggestion; } - function getSuggestedTypeForNonexistentStringLiteralType(source: StringLiteralType, target: UnionType): StringLiteralType | undefined { - const candidates = target.types.filter((type): type is StringLiteralType => !!(type.flags & TypeFlags.StringLiteral)); + function getSuggestedTypeForNonexistentStringLiteralType( + source: StringLiteralType, + target: UnionType, + ): StringLiteralType | undefined { + const candidates = target.types.filter((type): type is StringLiteralType => + !!(type.flags & TypeFlags.StringLiteral) + ); return getSpellingSuggestion(source.value, candidates, type => type.value); } @@ -32490,17 +41578,24 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } - function markPropertyAsReferenced(prop: Symbol, nodeForCheckWriteOnly: Node | undefined, isSelfTypeAccess: boolean) { + function markPropertyAsReferenced( + prop: Symbol, + nodeForCheckWriteOnly: Node | undefined, + isSelfTypeAccess: boolean, + ) { const valueDeclaration = prop && (prop.flags & SymbolFlags.ClassMember) && prop.valueDeclaration; if (!valueDeclaration) { return; } const hasPrivateModifier = hasEffectiveModifier(valueDeclaration, ModifierFlags.Private); - const hasPrivateIdentifier = prop.valueDeclaration && isNamedDeclaration(prop.valueDeclaration) && isPrivateIdentifier(prop.valueDeclaration.name); + const hasPrivateIdentifier = prop.valueDeclaration && isNamedDeclaration(prop.valueDeclaration) + && isPrivateIdentifier(prop.valueDeclaration.name); if (!hasPrivateModifier && !hasPrivateIdentifier) { return; } - if (nodeForCheckWriteOnly && isWriteOnlyAccess(nodeForCheckWriteOnly) && !(prop.flags & SymbolFlags.SetAccessor)) { + if ( + nodeForCheckWriteOnly && isWriteOnlyAccess(nodeForCheckWriteOnly) && !(prop.flags & SymbolFlags.SetAccessor) + ) { return; } if (isSelfTypeAccess) { @@ -32511,7 +41606,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } - (getCheckFlags(prop) & CheckFlags.Instantiated ? getSymbolLinks(prop).target : prop)!.isReferenced = SymbolFlags.All; + (getCheckFlags(prop) & CheckFlags.Instantiated ? getSymbolLinks(prop).target : prop)!.isReferenced = + SymbolFlags.All; } function isSelfTypeAccess(name: Expression | QualifiedName, parent: Symbol | undefined) { @@ -32519,12 +41615,25 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { || !!parent && isEntityNameExpression(name) && parent === getResolvedSymbol(getFirstIdentifier(name)); } - function isValidPropertyAccess(node: PropertyAccessExpression | QualifiedName | ImportTypeNode, propertyName: __String): boolean { + function isValidPropertyAccess( + node: PropertyAccessExpression | QualifiedName | ImportTypeNode, + propertyName: __String, + ): boolean { switch (node.kind) { case SyntaxKind.PropertyAccessExpression: - return isValidPropertyAccessWithType(node, node.expression.kind === SyntaxKind.SuperKeyword, propertyName, getWidenedType(checkExpression(node.expression))); + return isValidPropertyAccessWithType( + node, + node.expression.kind === SyntaxKind.SuperKeyword, + propertyName, + getWidenedType(checkExpression(node.expression)), + ); case SyntaxKind.QualifiedName: - return isValidPropertyAccessWithType(node, /*isSuper*/ false, propertyName, getWidenedType(checkExpression(node.left))); + return isValidPropertyAccessWithType( + node, + /*isSuper*/ false, + propertyName, + getWidenedType(checkExpression(node.left)), + ); case SyntaxKind.ImportType: return isValidPropertyAccessWithType(node, /*isSuper*/ false, propertyName, getTypeFromTypeNode(node)); } @@ -32540,8 +41649,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { * @param type the type whose property we are checking. * @param property the accessed property's symbol. */ - function isValidPropertyAccessForCompletions(node: PropertyAccessExpression | ImportTypeNode | QualifiedName, type: Type, property: Symbol): boolean { - return isPropertyAccessible(node, node.kind === SyntaxKind.PropertyAccessExpression && node.expression.kind === SyntaxKind.SuperKeyword, /*isWrite*/ false, type, property); + function isValidPropertyAccessForCompletions( + node: PropertyAccessExpression | ImportTypeNode | QualifiedName, + type: Type, + property: Symbol, + ): boolean { + return isPropertyAccessible( + node, + node.kind === SyntaxKind.PropertyAccessExpression && node.expression.kind === SyntaxKind.SuperKeyword, + /*isWrite*/ false, + type, + property, + ); // Previously we validated the 'this' type of methods but this adversely affected performance. See #31377 for more context. } @@ -32629,10 +41748,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { let node = expr.parent; while (node) { if ( - node.kind === SyntaxKind.ForInStatement && - child === (node as ForInStatement).statement && - getForInVariableSymbol(node as ForInStatement) === symbol && - hasNumericPropertyNames(getTypeOfExpression((node as ForInStatement).expression)) + node.kind === SyntaxKind.ForInStatement + && child === (node as ForInStatement).statement + && getForInVariableSymbol(node as ForInStatement) === symbol + && hasNumericPropertyNames(getTypeOfExpression((node as ForInStatement).expression)) ) { return true; } @@ -32645,18 +41764,27 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function checkIndexedAccess(node: ElementAccessExpression, checkMode: CheckMode | undefined): Type { - return node.flags & NodeFlags.OptionalChain ? checkElementAccessChain(node as ElementAccessChain, checkMode) : - checkElementAccessExpression(node, checkNonNullExpression(node.expression), checkMode); + return node.flags & NodeFlags.OptionalChain ? checkElementAccessChain(node as ElementAccessChain, checkMode) + : checkElementAccessExpression(node, checkNonNullExpression(node.expression), checkMode); } function checkElementAccessChain(node: ElementAccessChain, checkMode: CheckMode | undefined) { const exprType = checkExpression(node.expression); const nonOptionalType = getOptionalExpressionType(exprType, node.expression); - return propagateOptionalTypeMarker(checkElementAccessExpression(node, checkNonNullType(nonOptionalType, node.expression), checkMode), node, nonOptionalType !== exprType); + return propagateOptionalTypeMarker( + checkElementAccessExpression(node, checkNonNullType(nonOptionalType, node.expression), checkMode), + node, + nonOptionalType !== exprType, + ); } - function checkElementAccessExpression(node: ElementAccessExpression, exprType: Type, checkMode: CheckMode | undefined): Type { - const objectType = getAssignmentTargetKind(node) !== AssignmentKind.None || isMethodAccessForCall(node) ? getWidenedType(exprType) : exprType; + function checkElementAccessExpression( + node: ElementAccessExpression, + exprType: Type, + checkMode: CheckMode | undefined, + ): Type { + const objectType = getAssignmentTargetKind(node) !== AssignmentKind.None || isMethodAccessForCall(node) + ? getWidenedType(exprType) : exprType; const indexExpression = node.argumentExpression; const indexType = checkExpression(indexExpression); @@ -32670,14 +41798,28 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } const effectiveIndexType = isForInVariableForNumericPropertyNames(indexExpression) ? numberType : indexType; - const accessFlags = isAssignmentTarget(node) ? - AccessFlags.Writing | (isGenericObjectType(objectType) && !isThisTypeParameter(objectType) ? AccessFlags.NoIndexSignatures : 0) : - AccessFlags.ExpressionPosition; - const indexedAccessType = getIndexedAccessTypeOrUndefined(objectType, effectiveIndexType, accessFlags, node) || errorType; - return checkIndexedAccessIndexType(getFlowTypeOfAccessExpression(node, getNodeLinks(node).resolvedSymbol, indexedAccessType, indexExpression, checkMode), node); + const accessFlags = isAssignmentTarget(node) + ? AccessFlags.Writing + | (isGenericObjectType(objectType) && !isThisTypeParameter(objectType) ? AccessFlags.NoIndexSignatures + : 0) + : AccessFlags.ExpressionPosition; + const indexedAccessType = getIndexedAccessTypeOrUndefined(objectType, effectiveIndexType, accessFlags, node) + || errorType; + return checkIndexedAccessIndexType( + getFlowTypeOfAccessExpression( + node, + getNodeLinks(node).resolvedSymbol, + indexedAccessType, + indexExpression, + checkMode, + ), + node, + ); } - function callLikeExpressionMayHaveTypeArguments(node: CallLikeExpression): node is CallExpression | NewExpression | TaggedTemplateExpression | JsxOpeningElement { + function callLikeExpressionMayHaveTypeArguments( + node: CallLikeExpression, + ): node is CallExpression | NewExpression | TaggedTemplateExpression | JsxOpeningElement { return isCallOrNewExpression(node) || isTaggedTemplateExpression(node) || isJsxOpeningLikeElement(node); } @@ -32715,7 +41857,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // interface B extends A { (x: 'foo'): string } // const b: B; // b('foo') // <- here overloads should be processed as [(x:'foo'): string, (x: string): void] - function reorderCandidates(signatures: readonly Signature[], result: Signature[], callChainFlags: SignatureFlags): void { + function reorderCandidates( + signatures: readonly Signature[], + result: Signature[], + callChainFlags: SignatureFlags, + ): void { let lastParent: Node | undefined; let lastSymbol: Symbol | undefined; let cutoffIndex = 0; @@ -32757,12 +41903,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { spliceIndex = index; } - result.splice(spliceIndex, 0, callChainFlags ? getOptionalCallSignature(signature, callChainFlags) : signature); + result.splice( + spliceIndex, + 0, + callChainFlags ? getOptionalCallSignature(signature, callChainFlags) : signature, + ); } } function isSpreadArgument(arg: Expression | undefined): arg is Expression { - return !!arg && (arg.kind === SyntaxKind.SpreadElement || arg.kind === SyntaxKind.SyntheticExpression && (arg as SyntheticExpression).isSpread); + return !!arg + && (arg.kind === SyntaxKind.SpreadElement + || arg.kind === SyntaxKind.SyntheticExpression && (arg as SyntheticExpression).isSpread); } function getSpreadArgumentIndex(args: readonly Expression[]): number { @@ -32777,7 +41929,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return !!(t.flags & (TypeFlags.Void | TypeFlags.Undefined | TypeFlags.Unknown | TypeFlags.Any)); } - function hasCorrectArity(node: CallLikeExpression, args: readonly Expression[], signature: Signature, signatureHelpTrailingComma = false) { + function hasCorrectArity( + node: CallLikeExpression, + args: readonly Expression[], + signature: Signature, + signatureHelpTrailingComma = false, + ) { let argCount: number; let callIsIncomplete = false; // In incomplete call we want to be lenient when we have too few arguments let effectiveParameterCount = getParameterCount(signature); @@ -32826,7 +41983,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // If a spread argument is present, check that it corresponds to a rest parameter or at least that it's in the valid range. const spreadArgIndex = getSpreadArgumentIndex(args); if (spreadArgIndex >= 0) { - return spreadArgIndex >= getMinArgumentCount(signature) && (hasEffectiveRestParameter(signature) || spreadArgIndex < getParameterCount(signature)); + return spreadArgIndex >= getMinArgumentCount(signature) + && (hasEffectiveRestParameter(signature) || spreadArgIndex < getParameterCount(signature)); } } @@ -32842,7 +42000,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } for (let i = argCount; i < effectiveMinimumArguments; i++) { const type = getTypeAtPosition(signature, i); - if (filterType(type, isInJSFile(node) && !strictNullChecks ? acceptsVoidUndefinedUnknownOrAny : acceptsVoid).flags & TypeFlags.Never) { + if ( + filterType(type, isInJSFile(node) && !strictNullChecks ? acceptsVoidUndefinedUnknownOrAny : acceptsVoid) + .flags & TypeFlags.Never + ) { return false; } } @@ -32854,8 +42015,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // the declared number of type parameters, the call has an incorrect arity. const numTypeParameters = length(signature.typeParameters); const minTypeArgumentCount = getMinTypeArgumentCount(signature.typeParameters); - return !some(typeArguments) || - (typeArguments.length >= minTypeArgumentCount && typeArguments.length <= numTypeParameters); + return !some(typeArguments) + || (typeArguments.length >= minTypeArgumentCount && typeArguments.length <= numTypeParameters); } // If type has a single call signature and no other members, return that signature. Otherwise, return undefined. @@ -32864,18 +42025,24 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function getSingleCallOrConstructSignature(type: Type): Signature | undefined { - return getSingleSignature(type, SignatureKind.Call, /*allowMembers*/ false) || - getSingleSignature(type, SignatureKind.Construct, /*allowMembers*/ false); + return getSingleSignature(type, SignatureKind.Call, /*allowMembers*/ false) + || getSingleSignature(type, SignatureKind.Construct, /*allowMembers*/ false); } function getSingleSignature(type: Type, kind: SignatureKind, allowMembers: boolean): Signature | undefined { if (type.flags & TypeFlags.Object) { const resolved = resolveStructuredTypeMembers(type as ObjectType); if (allowMembers || resolved.properties.length === 0 && resolved.indexInfos.length === 0) { - if (kind === SignatureKind.Call && resolved.callSignatures.length === 1 && resolved.constructSignatures.length === 0) { + if ( + kind === SignatureKind.Call && resolved.callSignatures.length === 1 + && resolved.constructSignatures.length === 0 + ) { return resolved.callSignatures[0]; } - if (kind === SignatureKind.Construct && resolved.constructSignatures.length === 1 && resolved.callSignatures.length === 0) { + if ( + kind === SignatureKind.Construct && resolved.constructSignatures.length === 1 + && resolved.callSignatures.length === 0 + ) { return resolved.constructSignatures[0]; } } @@ -32884,13 +42051,20 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } // Instantiate a generic signature in the context of a non-generic signature (section 3.8.5 in TypeScript spec) - function instantiateSignatureInContextOf(signature: Signature, contextualSignature: Signature, inferenceContext?: InferenceContext, compareTypes?: TypeComparer): Signature { + function instantiateSignatureInContextOf( + signature: Signature, + contextualSignature: Signature, + inferenceContext?: InferenceContext, + compareTypes?: TypeComparer, + ): Signature { const context = createInferenceContext(signature.typeParameters!, signature, InferenceFlags.None, compareTypes); // We clone the inferenceContext to avoid fixing. For example, when the source signature is (x: T) => T[] and // the contextual signature is (...args: A) => B, we want to infer the element type of A's constraint (say 'any') // for T but leave it possible to later infer '[any]' back to A. const restType = getEffectiveRestType(contextualSignature); - const mapper = inferenceContext && (restType && restType.flags & TypeFlags.TypeParameter ? inferenceContext.nonFixingMapper : inferenceContext.mapper); + const mapper = inferenceContext + && (restType && restType.flags & TypeFlags.TypeParameter ? inferenceContext.nonFixingMapper + : inferenceContext.mapper); const sourceSignature = mapper ? instantiateSignature(contextualSignature, mapper) : contextualSignature; applyToParameterTypes(sourceSignature, signature, (source, target) => { // Type parameters from outer context referenced by source type are fixed by instantiation of the source type @@ -32901,10 +42075,19 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { inferTypes(context.inferences, source, target, InferencePriority.ReturnType); }); } - return getSignatureInstantiation(signature, getInferredTypes(context), isInJSFile(contextualSignature.declaration)); + return getSignatureInstantiation( + signature, + getInferredTypes(context), + isInJSFile(contextualSignature.declaration), + ); } - function inferJsxTypeArguments(node: JsxOpeningLikeElement, signature: Signature, checkMode: CheckMode, context: InferenceContext): Type[] { + function inferJsxTypeArguments( + node: JsxOpeningLikeElement, + signature: Signature, + checkMode: CheckMode, + context: InferenceContext, + ): Type[] { const paramType = getEffectiveFirstArgumentForJsxSignature(signature, node); const checkAttrType = checkExpressionWithContextualType(node.attributes, paramType, context, checkMode); inferTypes(context.inferences, checkAttrType, paramType); @@ -32916,12 +42099,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return voidType; } const thisArgumentType = checkExpression(thisArgumentNode); - return isOptionalChainRoot(thisArgumentNode.parent) ? getNonNullableType(thisArgumentType) : - isOptionalChain(thisArgumentNode.parent) ? removeOptionalTypeMarker(thisArgumentType) : - thisArgumentType; + return isOptionalChainRoot(thisArgumentNode.parent) ? getNonNullableType(thisArgumentType) + : isOptionalChain(thisArgumentNode.parent) ? removeOptionalTypeMarker(thisArgumentType) + : thisArgumentType; } - function inferTypeArguments(node: CallLikeExpression, signature: Signature, args: readonly Expression[], checkMode: CheckMode, context: InferenceContext): Type[] { + function inferTypeArguments( + node: CallLikeExpression, + signature: Signature, + args: readonly Expression[], + checkMode: CheckMode, + context: InferenceContext, + ): Type[] { if (isJsxOpeningLikeElement(node)) { return inferJsxTypeArguments(node, signature, checkMode, context); } @@ -32932,12 +42121,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // return type of 'wrap'. if (node.kind !== SyntaxKind.Decorator) { const skipBindingPatterns = every(signature.typeParameters, p => !!getDefaultFromTypeParameter(p)); - const contextualType = getContextualType(node, skipBindingPatterns ? ContextFlags.SkipBindingPatterns : ContextFlags.None); + const contextualType = getContextualType( + node, + skipBindingPatterns ? ContextFlags.SkipBindingPatterns : ContextFlags.None, + ); if (contextualType) { const inferenceTargetType = getReturnTypeOfSignature(signature); if (couldContainTypeVariables(inferenceTargetType)) { const outerContext = getInferenceContext(node); - const isFromBindingPattern = !skipBindingPatterns && getContextualType(node, ContextFlags.SkipBindingPatterns) !== contextualType; + const isFromBindingPattern = !skipBindingPatterns + && getContextualType(node, ContextFlags.SkipBindingPatterns) !== contextualType; // A return type inference from a binding pattern can be used in instantiating the contextual // type of an argument later in inference, but cannot stand on its own as the final return type. // It is incorporated into `context.returnMapper` which is used in `instantiateContextualType`, @@ -32952,7 +42145,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // We clone the inference context to avoid disturbing a resolution in progress for an // outer call expression. Effectively we just want a snapshot of whatever has been // inferred for any outer call expression so far. - const outerMapper = getMapperFromContext(cloneInferenceContext(outerContext, InferenceFlags.NoDefault)); + const outerMapper = getMapperFromContext( + cloneInferenceContext(outerContext, InferenceFlags.NoDefault), + ); const instantiatedType = instantiateType(contextualType, outerMapper); // If the contextual type is a generic function type with a single call signature, we // instantiate the type with its own type parameters and type arguments. This ensures that @@ -32962,11 +42157,21 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // const boxElements: (a: A[]) => { value: A }[] = arrayMap(value => ({ value })); // Above, the type of the 'value' parameter is inferred to be 'A'. const contextualSignature = getSingleCallSignature(instantiatedType); - const inferenceSourceType = contextualSignature && contextualSignature.typeParameters ? - getOrCreateTypeFromSignature(getSignatureInstantiationWithoutFillingInTypeArguments(contextualSignature, contextualSignature.typeParameters)) : - instantiatedType; + const inferenceSourceType = contextualSignature && contextualSignature.typeParameters + ? getOrCreateTypeFromSignature( + getSignatureInstantiationWithoutFillingInTypeArguments( + contextualSignature, + contextualSignature.typeParameters, + ), + ) + : instantiatedType; // Inferences made from return types have lower priority than all other inferences. - inferTypes(context.inferences, inferenceSourceType, inferenceTargetType, InferencePriority.ReturnType); + inferTypes( + context.inferences, + inferenceSourceType, + inferenceTargetType, + InferencePriority.ReturnType, + ); } // Create a type mapper for instantiating generic contextual types using the inferences made // from the return type. We need a separate inference pass here because (a) instantiation of @@ -32975,7 +42180,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const returnContext = createInferenceContext(signature.typeParameters!, signature, context.flags); const returnSourceType = instantiateType(contextualType, outerContext && outerContext.returnMapper); inferTypes(returnContext.inferences, returnSourceType, inferenceTargetType); - context.returnMapper = some(returnContext.inferences, hasInferenceCandidates) ? getMapperFromContext(cloneInferredPartOfContext(returnContext)) : undefined; + context.returnMapper = some(returnContext.inferences, hasInferenceCandidates) + ? getMapperFromContext(cloneInferredPartOfContext(returnContext)) : undefined; } } } @@ -32985,7 +42191,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (restType && restType.flags & TypeFlags.TypeParameter) { const info = find(context.inferences, info => info.typeParameter === restType); if (info) { - info.impliedArity = findIndex(args, isSpreadArgument, argCount) < 0 ? args.length - argCount : undefined; + info.impliedArity = findIndex(args, isSpreadArgument, argCount) < 0 ? args.length - argCount + : undefined; } } @@ -33015,13 +42222,26 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function getMutableArrayOrTupleType(type: Type) { - return type.flags & TypeFlags.Union ? mapType(type, getMutableArrayOrTupleType) : - type.flags & TypeFlags.Any || isMutableArrayOrTuple(getBaseConstraintOfType(type) || type) ? type : - isTupleType(type) ? createTupleType(getElementTypes(type), type.target.elementFlags, /*readonly*/ false, type.target.labeledElementDeclarations) : - createTupleType([type], [ElementFlags.Variadic]); + return type.flags & TypeFlags.Union ? mapType(type, getMutableArrayOrTupleType) + : type.flags & TypeFlags.Any || isMutableArrayOrTuple(getBaseConstraintOfType(type) || type) ? type + : isTupleType(type) + ? createTupleType( + getElementTypes(type), + type.target.elementFlags, + /*readonly*/ false, + type.target.labeledElementDeclarations, + ) + : createTupleType([type], [ElementFlags.Variadic]); } - function getSpreadArgumentType(args: readonly Expression[], index: number, argCount: number, restType: Type, context: InferenceContext | undefined, checkMode: CheckMode) { + function getSpreadArgumentType( + args: readonly Expression[], + index: number, + argCount: number, + restType: Type, + context: InferenceContext | undefined, + checkMode: CheckMode, + ) { const inConstContext = isConstTypeVariable(restType); if (index >= argCount - 1) { @@ -33029,14 +42249,27 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (isSpreadArgument(arg)) { // We are inferring from a spread expression in the last argument position, i.e. both the parameter // and the argument are ...x forms. - const spreadType = arg.kind === SyntaxKind.SyntheticExpression ? (arg as SyntheticExpression).type : - checkExpressionWithContextualType((arg as SpreadElement).expression, restType, context, checkMode); + const spreadType = arg.kind === SyntaxKind.SyntheticExpression ? (arg as SyntheticExpression).type + : checkExpressionWithContextualType( + (arg as SpreadElement).expression, + restType, + context, + checkMode, + ); if (isArrayLikeType(spreadType)) { return getMutableArrayOrTupleType(spreadType); } - return createArrayType(checkIteratedTypeOrElementType(IterationUse.Spread, spreadType, undefinedType, arg.kind === SyntaxKind.SpreadElement ? (arg as SpreadElement).expression : arg), inConstContext); + return createArrayType( + checkIteratedTypeOrElementType( + IterationUse.Spread, + spreadType, + undefinedType, + arg.kind === SyntaxKind.SpreadElement ? (arg as SpreadElement).expression : arg, + ), + inConstContext, + ); } } const types = []; @@ -33045,23 +42278,37 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { for (let i = index; i < argCount; i++) { const arg = args[i]; if (isSpreadArgument(arg)) { - const spreadType = arg.kind === SyntaxKind.SyntheticExpression ? (arg as SyntheticExpression).type : checkExpression((arg as SpreadElement).expression); + const spreadType = arg.kind === SyntaxKind.SyntheticExpression ? (arg as SyntheticExpression).type + : checkExpression((arg as SpreadElement).expression); if (isArrayLikeType(spreadType)) { types.push(spreadType); flags.push(ElementFlags.Variadic); } else { - types.push(checkIteratedTypeOrElementType(IterationUse.Spread, spreadType, undefinedType, arg.kind === SyntaxKind.SpreadElement ? (arg as SpreadElement).expression : arg)); + types.push( + checkIteratedTypeOrElementType( + IterationUse.Spread, + spreadType, + undefinedType, + arg.kind === SyntaxKind.SpreadElement ? (arg as SpreadElement).expression : arg, + ), + ); flags.push(ElementFlags.Rest); } } else { - const contextualType = isTupleType(restType) ? - getContextualTypeForElementExpression(restType, i - index, argCount - index) || unknownType : - getIndexedAccessType(restType, getNumberLiteralType(i - index), AccessFlags.Contextual); + const contextualType = isTupleType(restType) + ? getContextualTypeForElementExpression(restType, i - index, argCount - index) || unknownType + : getIndexedAccessType(restType, getNumberLiteralType(i - index), AccessFlags.Contextual); const argType = checkExpressionWithContextualType(arg, contextualType, context, checkMode); - const hasPrimitiveContextualType = inConstContext || maybeTypeOfKind(contextualType, TypeFlags.Primitive | TypeFlags.Index | TypeFlags.TemplateLiteral | TypeFlags.StringMapping); - types.push(hasPrimitiveContextualType ? getRegularTypeOfLiteralType(argType) : getWidenedLiteralType(argType)); + const hasPrimitiveContextualType = inConstContext + || maybeTypeOfKind( + contextualType, + TypeFlags.Primitive | TypeFlags.Index | TypeFlags.TemplateLiteral | TypeFlags.StringMapping, + ); + types.push( + hasPrimitiveContextualType ? getRegularTypeOfLiteralType(argType) : getWidenedLiteralType(argType), + ); flags.push(ElementFlags.Required); } if (arg.kind === SyntaxKind.SyntheticExpression && (arg as SyntheticExpression).tupleNameSource) { @@ -33071,16 +42318,33 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return createTupleType(types, flags, inConstContext, length(names) === length(types) ? names : undefined); } - function checkTypeArguments(signature: Signature, typeArgumentNodes: readonly TypeNode[], reportErrors: boolean, headMessage?: DiagnosticMessage): Type[] | undefined { + function checkTypeArguments( + signature: Signature, + typeArgumentNodes: readonly TypeNode[], + reportErrors: boolean, + headMessage?: DiagnosticMessage, + ): Type[] | undefined { const isJavascript = isInJSFile(signature.declaration); const typeParameters = signature.typeParameters!; - const typeArgumentTypes = fillMissingTypeArguments(map(typeArgumentNodes, getTypeFromTypeNode), typeParameters, getMinTypeArgumentCount(typeParameters), isJavascript); + const typeArgumentTypes = fillMissingTypeArguments( + map(typeArgumentNodes, getTypeFromTypeNode), + typeParameters, + getMinTypeArgumentCount(typeParameters), + isJavascript, + ); let mapper: TypeMapper | undefined; for (let i = 0; i < typeArgumentNodes.length; i++) { - Debug.assert(typeParameters[i] !== undefined, "Should not call checkTypeArguments with too many type arguments"); + Debug.assert( + typeParameters[i] !== undefined, + "Should not call checkTypeArguments with too many type arguments", + ); const constraint = getConstraintOfTypeParameter(typeParameters[i]); if (constraint) { - const errorInfo = reportErrors && headMessage ? (() => chainDiagnosticMessages(/*details*/ undefined, Diagnostics.Type_0_does_not_satisfy_the_constraint_1)) : undefined; + const errorInfo = reportErrors && headMessage ? (() => + chainDiagnosticMessages( + /*details*/ undefined, + Diagnostics.Type_0_does_not_satisfy_the_constraint_1, + )) : undefined; const typeArgumentHeadMessage = headMessage || Diagnostics.Type_0_does_not_satisfy_the_constraint_1; if (!mapper) { mapper = createTypeMapper(typeParameters, typeArgumentTypes); @@ -33135,8 +42399,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // However "context" and "updater" are implicit and can't be specify by users. Only the first parameter, props, // can be specified by users through attributes property. const paramType = getEffectiveFirstArgumentForJsxSignature(signature, node); - const attributesType = checkExpressionWithContextualType(node.attributes, paramType, /*inferenceContext*/ undefined, checkMode); - const checkAttributesType = checkMode & CheckMode.SkipContextSensitive ? getRegularTypeOfObjectLiteral(attributesType) : attributesType; + const attributesType = checkExpressionWithContextualType( + node.attributes, + paramType, + /*inferenceContext*/ undefined, + checkMode, + ); + const checkAttributesType = checkMode & CheckMode.SkipContextSensitive + ? getRegularTypeOfObjectLiteral(attributesType) : attributesType; return checkTagNameDoesNotExpectTooManyArguments() && checkTypeRelatedToAndOptionallyElaborate( checkAttributesType, paramType, @@ -33152,7 +42422,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (getJsxNamespaceContainerForImplicitImport(node)) { return true; // factory is implicitly jsx/jsxdev - assume it fits the bill, since we don't strongly look for the jsx/jsxs/jsxDEV factory APIs anywhere else (at least not yet) } - const tagType = (isJsxOpeningElement(node) || isJsxSelfClosingElement(node)) && !(isJsxIntrinsicTagName(node.tagName) || isJsxNamespacedName(node.tagName)) ? checkExpression(node.tagName) : undefined; + const tagType = (isJsxOpeningElement(node) || isJsxSelfClosingElement(node)) + && !(isJsxIntrinsicTagName(node.tagName) || isJsxNamespacedName(node.tagName)) + ? checkExpression(node.tagName) : undefined; if (!tagType) { return true; } @@ -33164,7 +42436,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (!factory) { return true; } - const factorySymbol = resolveEntityName(factory, SymbolFlags.Value, /*ignoreErrors*/ true, /*dontResolveAlias*/ false, node); + const factorySymbol = resolveEntityName( + factory, + SymbolFlags.Value, + /*ignoreErrors*/ true, + /*dontResolveAlias*/ false, + node, + ); if (!factorySymbol) { return true; } @@ -33210,10 +42488,24 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } if (reportErrors) { - const diag = createDiagnosticForNode(node.tagName, Diagnostics.Tag_0_expects_at_least_1_arguments_but_the_JSX_factory_2_provides_at_most_3, entityNameToString(node.tagName), absoluteMinArgCount, entityNameToString(factory), maxParamCount); + const diag = createDiagnosticForNode( + node.tagName, + Diagnostics.Tag_0_expects_at_least_1_arguments_but_the_JSX_factory_2_provides_at_most_3, + entityNameToString(node.tagName), + absoluteMinArgCount, + entityNameToString(factory), + maxParamCount, + ); const tagNameDeclaration = getSymbolAtLocation(node.tagName)?.valueDeclaration; if (tagNameDeclaration) { - addRelatedInfo(diag, createDiagnosticForNode(tagNameDeclaration, Diagnostics._0_is_declared_here, entityNameToString(node.tagName))); + addRelatedInfo( + diag, + createDiagnosticForNode( + tagNameDeclaration, + Diagnostics._0_is_declared_here, + entityNameToString(node.tagName), + ), + ); } if (errorOutputContainer && errorOutputContainer.skipLogging) { (errorOutputContainer.errors || (errorOutputContainer.errors = [])).push(diag); @@ -33235,16 +42527,35 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { reportErrors: boolean, containingMessageChain: (() => DiagnosticMessageChain | undefined) | undefined, ): readonly Diagnostic[] | undefined { - const errorOutputContainer: { errors?: Diagnostic[]; skipLogging?: boolean; } = { errors: undefined, skipLogging: true }; + const errorOutputContainer: { errors?: Diagnostic[]; skipLogging?: boolean; } = { + errors: undefined, + skipLogging: true, + }; if (isJsxOpeningLikeElement(node)) { - if (!checkApplicableSignatureForJsxOpeningLikeElement(node, signature, relation, checkMode, reportErrors, containingMessageChain, errorOutputContainer)) { - Debug.assert(!reportErrors || !!errorOutputContainer.errors, "jsx should have errors when reporting errors"); + if ( + !checkApplicableSignatureForJsxOpeningLikeElement( + node, + signature, + relation, + checkMode, + reportErrors, + containingMessageChain, + errorOutputContainer, + ) + ) { + Debug.assert( + !reportErrors || !!errorOutputContainer.errors, + "jsx should have errors when reporting errors", + ); return errorOutputContainer.errors || emptyArray; } return undefined; } const thisType = getThisTypeOfSignature(signature); - if (thisType && thisType !== voidType && !(isNewExpression(node) || isCallExpression(node) && isSuperProperty(node.expression))) { + if ( + thisType && thisType !== voidType + && !(isNewExpression(node) || isCallExpression(node) && isSuperProperty(node.expression)) + ) { // If the called expression is not of the form `x.f` or `x["f"]`, then sourceType = voidType // If the signature's 'this' type is voidType, then the check is skipped -- anything is compatible. // If the expression is a new expression or super call expression, then the check is skipped. @@ -33252,8 +42563,21 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const thisArgumentType = getThisArgumentType(thisArgumentNode); const errorNode = reportErrors ? (thisArgumentNode || node) : undefined; const headMessage = Diagnostics.The_this_context_of_type_0_is_not_assignable_to_method_s_this_of_type_1; - if (!checkTypeRelatedTo(thisArgumentType, thisType, relation, errorNode, headMessage, containingMessageChain, errorOutputContainer)) { - Debug.assert(!reportErrors || !!errorOutputContainer.errors, "this parameter should have errors when reporting errors"); + if ( + !checkTypeRelatedTo( + thisArgumentType, + thisType, + relation, + errorNode, + headMessage, + containingMessageChain, + errorOutputContainer, + ) + ) { + Debug.assert( + !reportErrors || !!errorOutputContainer.errors, + "this parameter should have errors when reporting errors", + ); return errorOutputContainer.errors || emptyArray; } } @@ -33264,27 +42588,71 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const arg = args[i]; if (arg.kind !== SyntaxKind.OmittedExpression) { const paramType = getTypeAtPosition(signature, i); - const argType = checkExpressionWithContextualType(arg, paramType, /*inferenceContext*/ undefined, checkMode); + const argType = checkExpressionWithContextualType( + arg, + paramType, + /*inferenceContext*/ undefined, + checkMode, + ); // If one or more arguments are still excluded (as indicated by CheckMode.SkipContextSensitive), // we obtain the regular type of any object literal arguments because we may not have inferred complete // parameter types yet and therefore excess property checks may yield false positives (see #17041). - const checkArgType = checkMode & CheckMode.SkipContextSensitive ? getRegularTypeOfObjectLiteral(argType) : argType; - if (!checkTypeRelatedToAndOptionallyElaborate(checkArgType, paramType, relation, reportErrors ? arg : undefined, arg, headMessage, containingMessageChain, errorOutputContainer)) { - Debug.assert(!reportErrors || !!errorOutputContainer.errors, "parameter should have errors when reporting errors"); + const checkArgType = checkMode & CheckMode.SkipContextSensitive ? getRegularTypeOfObjectLiteral(argType) + : argType; + if ( + !checkTypeRelatedToAndOptionallyElaborate( + checkArgType, + paramType, + relation, + reportErrors ? arg : undefined, + arg, + headMessage, + containingMessageChain, + errorOutputContainer, + ) + ) { + Debug.assert( + !reportErrors || !!errorOutputContainer.errors, + "parameter should have errors when reporting errors", + ); maybeAddMissingAwaitInfo(arg, checkArgType, paramType); return errorOutputContainer.errors || emptyArray; } } } if (restType) { - const spreadType = getSpreadArgumentType(args, argCount, args.length, restType, /*context*/ undefined, checkMode); + const spreadType = getSpreadArgumentType( + args, + argCount, + args.length, + restType, + /*context*/ undefined, + checkMode, + ); const restArgCount = args.length - argCount; - const errorNode = !reportErrors ? undefined : - restArgCount === 0 ? node : - restArgCount === 1 ? args[argCount] : - setTextRangePosEnd(createSyntheticExpression(node, spreadType), args[argCount].pos, args[args.length - 1].end); - if (!checkTypeRelatedTo(spreadType, restType, relation, errorNode, headMessage, /*containingMessageChain*/ undefined, errorOutputContainer)) { - Debug.assert(!reportErrors || !!errorOutputContainer.errors, "rest parameter should have errors when reporting errors"); + const errorNode = !reportErrors ? undefined + : restArgCount === 0 ? node + : restArgCount === 1 ? args[argCount] + : setTextRangePosEnd( + createSyntheticExpression(node, spreadType), + args[argCount].pos, + args[args.length - 1].end, + ); + if ( + !checkTypeRelatedTo( + spreadType, + restType, + relation, + errorNode, + headMessage, + /*containingMessageChain*/ undefined, + errorOutputContainer, + ) + ) { + Debug.assert( + !reportErrors || !!errorOutputContainer.errors, + "rest parameter should have errors when reporting errors", + ); maybeAddMissingAwaitInfo(errorNode, spreadType, restType); return errorOutputContainer.errors || emptyArray; } @@ -33299,7 +42667,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } const awaitedTypeOfSource = getAwaitedTypeOfPromise(source); if (awaitedTypeOfSource && isTypeRelatedTo(awaitedTypeOfSource, target, relation)) { - addRelatedInfo(errorOutputContainer.errors[0], createDiagnosticForNode(errorNode, Diagnostics.Did_you_forget_to_use_await)); + addRelatedInfo( + errorOutputContainer.errors[0], + createDiagnosticForNode(errorNode, Diagnostics.Did_you_forget_to_use_await), + ); } } } @@ -33309,10 +42680,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { * Returns the this argument in calls like x.f(...) and x[f](...). Undefined otherwise. */ function getThisArgumentOfCall(node: CallLikeExpression): LeftHandSideExpression | undefined { - const expression = node.kind === SyntaxKind.CallExpression ? node.expression : - node.kind === SyntaxKind.TaggedTemplateExpression ? node.tag : - node.kind === SyntaxKind.Decorator && !legacyDecorators ? node.expression : - undefined; + const expression = node.kind === SyntaxKind.CallExpression ? node.expression + : node.kind === SyntaxKind.TaggedTemplateExpression ? node.tag + : node.kind === SyntaxKind.Decorator && !legacyDecorators ? node.expression + : undefined; if (expression) { const callee = skipOuterExpressions(expression); if (isAccessExpression(callee)) { @@ -33321,7 +42692,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } - function createSyntheticExpression(parent: Node, type: Type, isSpread?: boolean, tupleNameSource?: ParameterDeclaration | NamedTupleMember) { + function createSyntheticExpression( + parent: Node, + type: Type, + isSpread?: boolean, + tupleNameSource?: ParameterDeclaration | NamedTupleMember, + ) { const result = parseNodeFactory.createSyntheticExpression(type, isSpread, tupleNameSource); setTextRange(result, parent); setParent(result, parent); @@ -33346,7 +42722,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return getEffectiveDecoratorArguments(node); } if (isJsxOpeningLikeElement(node)) { - return node.attributes.properties.length > 0 || (isJsxOpeningElement(node) && node.parent.children.length > 0) ? [node.attributes] : emptyArray; + return node.attributes.properties.length > 0 + || (isJsxOpeningElement(node) && node.parent.children.length > 0) ? [node.attributes] : emptyArray; } const args = node.arguments || emptyArray; const spreadIndex = getSpreadArgumentIndex(args); @@ -33356,11 +42733,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { for (let i = spreadIndex; i < args.length; i++) { const arg = args[i]; // We can call checkExpressionCached because spread expressions never have a contextual type. - const spreadType = arg.kind === SyntaxKind.SpreadElement && (flowLoopCount ? checkExpression((arg as SpreadElement).expression) : checkExpressionCached((arg as SpreadElement).expression)); + const spreadType = arg.kind === SyntaxKind.SpreadElement + && (flowLoopCount ? checkExpression((arg as SpreadElement).expression) + : checkExpressionCached((arg as SpreadElement).expression)); if (spreadType && isTupleType(spreadType)) { forEach(getElementTypes(spreadType), (t, i) => { const flags = spreadType.target.elementFlags[i]; - const syntheticArg = createSyntheticExpression(arg, flags & ElementFlags.Rest ? createArrayType(t) : t, !!(flags & ElementFlags.Variable), spreadType.target.labeledElementDeclarations?.[i]); + const syntheticArg = createSyntheticExpression( + arg, + flags & ElementFlags.Rest ? createArrayType(t) : t, + !!(flags & ElementFlags.Variable), + spreadType.target.labeledElementDeclarations?.[i], + ); effectiveArgs.push(syntheticArg); }); } @@ -33394,9 +42778,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { * Returns the argument count for a decorator node that works like a function invocation. */ function getDecoratorArgumentCount(node: Decorator, signature: Signature) { - return compilerOptions.experimentalDecorators ? - getLegacyDecoratorArgumentCount(node, signature) : - 2; + return compilerOptions.experimentalDecorators + ? getLegacyDecoratorArgumentCount(node, signature) + : 2; } /** @@ -33439,7 +42823,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return { start, length, sourceFile }; } - function getDiagnosticForCallNode(node: CallLikeExpression, message: DiagnosticMessage | DiagnosticMessageChain, ...args: DiagnosticArguments): DiagnosticWithLocation { + function getDiagnosticForCallNode( + node: CallLikeExpression, + message: DiagnosticMessage | DiagnosticMessageChain, + ...args: DiagnosticArguments + ): DiagnosticWithLocation { if (isCallExpression(node)) { const { sourceFile, start, length } = getDiagnosticSpanForCallNode(node); if ("message" in message) { // eslint-disable-line local/no-in-operator @@ -33458,9 +42846,19 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function isPromiseResolveArityError(node: CallLikeExpression) { if (!isCallExpression(node) || !isIdentifier(node.expression)) return false; - const symbol = resolveName(node.expression, node.expression.escapedText, SymbolFlags.Value, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ false); + const symbol = resolveName( + node.expression, + node.expression.escapedText, + SymbolFlags.Value, + /*nameNotFoundMessage*/ undefined, + /*nameArg*/ undefined, + /*isUse*/ false, + ); const decl = symbol?.valueDeclaration; - if (!decl || !isParameter(decl) || !isFunctionExpressionOrArrowFunction(decl.parent) || !isNewExpression(decl.parent.parent) || !isIdentifier(decl.parent.parent.expression)) { + if ( + !decl || !isParameter(decl) || !isFunctionExpressionOrArrowFunction(decl.parent) + || !isNewExpression(decl.parent.parent) || !isIdentifier(decl.parent.parent.expression) + ) { return false; } @@ -33471,10 +42869,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return constructorSymbol === globalPromiseSymbol; } - function getArgumentArityError(node: CallLikeExpression, signatures: readonly Signature[], args: readonly Expression[], headMessage?: DiagnosticMessage) { + function getArgumentArityError( + node: CallLikeExpression, + signatures: readonly Signature[], + args: readonly Expression[], + headMessage?: DiagnosticMessage, + ) { const spreadIndex = getSpreadArgumentIndex(args); if (spreadIndex > -1) { - return createDiagnosticForNode(args[spreadIndex], Diagnostics.A_spread_argument_must_either_have_a_tuple_type_or_be_passed_to_a_rest_parameter); + return createDiagnosticForNode( + args[spreadIndex], + Diagnostics.A_spread_argument_must_either_have_a_tuple_type_or_be_passed_to_a_rest_parameter, + ); } let min = Number.POSITIVE_INFINITY; // smallest parameter count let max = Number.NEGATIVE_INFINITY; // largest parameter count @@ -33499,25 +42905,46 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const parameterRange = hasRestParameter ? min : min < max ? min + "-" + max : min; - const isVoidPromiseError = !hasRestParameter && parameterRange === 1 && args.length === 0 && isPromiseResolveArityError(node); + const isVoidPromiseError = !hasRestParameter && parameterRange === 1 && args.length === 0 + && isPromiseResolveArityError(node); if (isVoidPromiseError && isInJSFile(node)) { - return getDiagnosticForCallNode(node, Diagnostics.Expected_1_argument_but_got_0_new_Promise_needs_a_JSDoc_hint_to_produce_a_resolve_that_can_be_called_without_arguments); + return getDiagnosticForCallNode( + node, + Diagnostics + .Expected_1_argument_but_got_0_new_Promise_needs_a_JSDoc_hint_to_produce_a_resolve_that_can_be_called_without_arguments, + ); } - const error = isDecorator(node) ? - hasRestParameter ? Diagnostics.The_runtime_will_invoke_the_decorator_with_1_arguments_but_the_decorator_expects_at_least_0 : - Diagnostics.The_runtime_will_invoke_the_decorator_with_1_arguments_but_the_decorator_expects_0 : - hasRestParameter ? Diagnostics.Expected_at_least_0_arguments_but_got_1 : - isVoidPromiseError ? Diagnostics.Expected_0_arguments_but_got_1_Did_you_forget_to_include_void_in_your_type_argument_to_Promise : - Diagnostics.Expected_0_arguments_but_got_1; + const error = isDecorator(node) + ? hasRestParameter + ? Diagnostics + .The_runtime_will_invoke_the_decorator_with_1_arguments_but_the_decorator_expects_at_least_0 + : Diagnostics.The_runtime_will_invoke_the_decorator_with_1_arguments_but_the_decorator_expects_0 + : hasRestParameter ? Diagnostics.Expected_at_least_0_arguments_but_got_1 + : isVoidPromiseError + ? Diagnostics.Expected_0_arguments_but_got_1_Did_you_forget_to_include_void_in_your_type_argument_to_Promise + : Diagnostics.Expected_0_arguments_but_got_1; if (min < args.length && args.length < max) { // between min and max, but with no matching overload if (headMessage) { - let chain = chainDiagnosticMessages(/*details*/ undefined, Diagnostics.No_overload_expects_0_arguments_but_overloads_do_exist_that_expect_either_1_or_2_arguments, args.length, maxBelow, minAbove); + let chain = chainDiagnosticMessages( + /*details*/ undefined, + Diagnostics + .No_overload_expects_0_arguments_but_overloads_do_exist_that_expect_either_1_or_2_arguments, + args.length, + maxBelow, + minAbove, + ); chain = chainDiagnosticMessages(chain, headMessage); return getDiagnosticForCallNode(node, chain); } - return getDiagnosticForCallNode(node, Diagnostics.No_overload_expects_0_arguments_but_overloads_do_exist_that_expect_either_1_or_2_arguments, args.length, maxBelow, minAbove); + return getDiagnosticForCallNode( + node, + Diagnostics.No_overload_expects_0_arguments_but_overloads_do_exist_that_expect_either_1_or_2_arguments, + args.length, + maxBelow, + minAbove, + ); } else if (args.length < min) { // too short: put the error span on the call expression, not any of the args @@ -33530,11 +42957,20 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { else { diagnostic = getDiagnosticForCallNode(node, error, parameterRange, args.length); } - const parameter = closestSignature?.declaration?.parameters[closestSignature.thisParameter ? args.length + 1 : args.length]; + const parameter = closestSignature?.declaration + ?.parameters[closestSignature.thisParameter ? args.length + 1 : args.length]; if (parameter) { - const messageAndArgs: DiagnosticAndArguments = isBindingPattern(parameter.name) ? [Diagnostics.An_argument_matching_this_binding_pattern_was_not_provided] - : isRestParameter(parameter) ? [Diagnostics.Arguments_for_the_rest_parameter_0_were_not_provided, idText(getFirstIdentifier(parameter.name))] - : [Diagnostics.An_argument_for_0_was_not_provided, !parameter.name ? args.length : idText(getFirstIdentifier(parameter.name))]; + const messageAndArgs: DiagnosticAndArguments = isBindingPattern(parameter.name) + ? [Diagnostics.An_argument_matching_this_binding_pattern_was_not_provided] + : isRestParameter(parameter) + ? [ + Diagnostics.Arguments_for_the_rest_parameter_0_were_not_provided, + idText(getFirstIdentifier(parameter.name)), + ] + : [ + Diagnostics.An_argument_for_0_was_not_provided, + !parameter.name ? args.length : idText(getFirstIdentifier(parameter.name)), + ]; const parameterError = createDiagnosticForNode(parameter, ...messageAndArgs); return addRelatedInfo(diagnostic, parameterError); } @@ -33554,11 +42990,22 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { chain = chainDiagnosticMessages(chain, headMessage); return createDiagnosticForNodeArrayFromMessageChain(getSourceFileOfNode(node), errorSpan, chain); } - return createDiagnosticForNodeArray(getSourceFileOfNode(node), errorSpan, error, parameterRange, args.length); + return createDiagnosticForNodeArray( + getSourceFileOfNode(node), + errorSpan, + error, + parameterRange, + args.length, + ); } } - function getTypeArgumentArityError(node: Node, signatures: readonly Signature[], typeArguments: NodeArray, headMessage?: DiagnosticMessage) { + function getTypeArgumentArityError( + node: Node, + signatures: readonly Signature[], + typeArguments: NodeArray, + headMessage?: DiagnosticMessage, + ) { const argCount = typeArguments.length; // No overloads exist if (signatures.length === 1) { @@ -33566,11 +43013,22 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const min = getMinTypeArgumentCount(sig.typeParameters); const max = length(sig.typeParameters); if (headMessage) { - let chain = chainDiagnosticMessages(/*details*/ undefined, Diagnostics.Expected_0_type_arguments_but_got_1, min < max ? min + "-" + max : min, argCount); + let chain = chainDiagnosticMessages( + /*details*/ undefined, + Diagnostics.Expected_0_type_arguments_but_got_1, + min < max ? min + "-" + max : min, + argCount, + ); chain = chainDiagnosticMessages(chain, headMessage); return createDiagnosticForNodeArrayFromMessageChain(getSourceFileOfNode(node), typeArguments, chain); } - return createDiagnosticForNodeArray(getSourceFileOfNode(node), typeArguments, Diagnostics.Expected_0_type_arguments_but_got_1, min < max ? min + "-" + max : min, argCount); + return createDiagnosticForNodeArray( + getSourceFileOfNode(node), + typeArguments, + Diagnostics.Expected_0_type_arguments_but_got_1, + min < max ? min + "-" + max : min, + argCount, + ); } // Overloads exist let belowArgCount = -Infinity; @@ -33587,21 +43045,54 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } if (belowArgCount !== -Infinity && aboveArgCount !== Infinity) { if (headMessage) { - let chain = chainDiagnosticMessages(/*details*/ undefined, Diagnostics.No_overload_expects_0_type_arguments_but_overloads_do_exist_that_expect_either_1_or_2_type_arguments, argCount, belowArgCount, aboveArgCount); + let chain = chainDiagnosticMessages( + /*details*/ undefined, + Diagnostics + .No_overload_expects_0_type_arguments_but_overloads_do_exist_that_expect_either_1_or_2_type_arguments, + argCount, + belowArgCount, + aboveArgCount, + ); chain = chainDiagnosticMessages(chain, headMessage); return createDiagnosticForNodeArrayFromMessageChain(getSourceFileOfNode(node), typeArguments, chain); } - return createDiagnosticForNodeArray(getSourceFileOfNode(node), typeArguments, Diagnostics.No_overload_expects_0_type_arguments_but_overloads_do_exist_that_expect_either_1_or_2_type_arguments, argCount, belowArgCount, aboveArgCount); + return createDiagnosticForNodeArray( + getSourceFileOfNode(node), + typeArguments, + Diagnostics + .No_overload_expects_0_type_arguments_but_overloads_do_exist_that_expect_either_1_or_2_type_arguments, + argCount, + belowArgCount, + aboveArgCount, + ); } if (headMessage) { - let chain = chainDiagnosticMessages(/*details*/ undefined, Diagnostics.Expected_0_type_arguments_but_got_1, belowArgCount === -Infinity ? aboveArgCount : belowArgCount, argCount); + let chain = chainDiagnosticMessages( + /*details*/ undefined, + Diagnostics.Expected_0_type_arguments_but_got_1, + belowArgCount === -Infinity ? aboveArgCount : belowArgCount, + argCount, + ); chain = chainDiagnosticMessages(chain, headMessage); return createDiagnosticForNodeArrayFromMessageChain(getSourceFileOfNode(node), typeArguments, chain); } - return createDiagnosticForNodeArray(getSourceFileOfNode(node), typeArguments, Diagnostics.Expected_0_type_arguments_but_got_1, belowArgCount === -Infinity ? aboveArgCount : belowArgCount, argCount); + return createDiagnosticForNodeArray( + getSourceFileOfNode(node), + typeArguments, + Diagnostics.Expected_0_type_arguments_but_got_1, + belowArgCount === -Infinity ? aboveArgCount : belowArgCount, + argCount, + ); } - function resolveCall(node: CallLikeExpression, signatures: readonly Signature[], candidatesOutArray: Signature[] | undefined, checkMode: CheckMode, callChainFlags: SignatureFlags, headMessage?: DiagnosticMessage): Signature { + function resolveCall( + node: CallLikeExpression, + signatures: readonly Signature[], + candidatesOutArray: Signature[] | undefined, + checkMode: CheckMode, + callChainFlags: SignatureFlags, + headMessage?: DiagnosticMessage, + ): Signature { const isTaggedTemplate = node.kind === SyntaxKind.TaggedTemplateExpression; const isDecorator = node.kind === SyntaxKind.Decorator; const isJsxOpeningOrSelfClosingElement = isJsxOpeningLikeElement(node); @@ -33613,7 +43104,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { typeArguments = (node as CallExpression).typeArguments; // We already perform checking on the type arguments on the class declaration itself. - if (isTaggedTemplate || isJsxOpeningOrSelfClosingElement || (node as CallExpression).expression.kind !== SyntaxKind.SuperKeyword) { + if ( + isTaggedTemplate || isJsxOpeningOrSelfClosingElement + || (node as CallExpression).expression.kind !== SyntaxKind.SuperKeyword + ) { forEach(typeArguments, checkSourceElement); } } @@ -33638,7 +43132,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // For a decorator, no arguments are susceptible to contextual typing due to the fact // decorators are applied to a declaration by the emitter, and not to an expression. const isSingleNonGenericCandidate = candidates.length === 1 && !candidates[0].typeParameters; - let argCheckMode = !isDecorator && !isSingleNonGenericCandidate && some(args, isContextSensitive) ? CheckMode.SkipContextSensitive : CheckMode.Normal; + let argCheckMode = !isDecorator && !isSingleNonGenericCandidate && some(args, isContextSensitive) + ? CheckMode.SkipContextSensitive : CheckMode.Normal; // The following variables are captured and modified by calls to chooseOverload. // If overload resolution or type argument inference fails, we want to report the @@ -33668,7 +43163,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // If we are in signature help, a trailing comma indicates that we intend to provide another argument, // so we will only accept overloads with arity at least 1 higher than the current number of provided arguments. - const signatureHelpTrailingComma = !!(checkMode & CheckMode.IsForSignatureHelp) && node.kind === SyntaxKind.CallExpression && node.arguments.hasTrailingComma; + const signatureHelpTrailingComma = !!(checkMode & CheckMode.IsForSignatureHelp) + && node.kind === SyntaxKind.CallExpression && node.arguments.hasTrailingComma; // Section 4.12.1: // if the candidate list contains one or more signatures for which the type of each argument @@ -33681,10 +43177,20 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // is just important for choosing the best signature. So in the case where there is only one // signature, the subtype pass is useless. So skipping it is an optimization. if (candidates.length > 1) { - result = chooseOverload(candidates, subtypeRelation, isSingleNonGenericCandidate, signatureHelpTrailingComma); + result = chooseOverload( + candidates, + subtypeRelation, + isSingleNonGenericCandidate, + signatureHelpTrailingComma, + ); } if (!result) { - result = chooseOverload(candidates, assignableRelation, isSingleNonGenericCandidate, signatureHelpTrailingComma); + result = chooseOverload( + candidates, + assignableRelation, + isSingleNonGenericCandidate, + signatureHelpTrailingComma, + ); } if (result) { return result; @@ -33716,11 +43222,25 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (headMessage) { chain = chainDiagnosticMessages(chain, headMessage); } - const diags = getSignatureApplicabilityError(node, args, last, assignableRelation, CheckMode.Normal, /*reportErrors*/ true, () => chain); + const diags = getSignatureApplicabilityError( + node, + args, + last, + assignableRelation, + CheckMode.Normal, + /*reportErrors*/ true, + () => chain, + ); if (diags) { for (const d of diags) { if (last.declaration && candidatesForArgumentError.length > 3) { - addRelatedInfo(d, createDiagnosticForNode(last.declaration, Diagnostics.The_last_overload_is_declared_here)); + addRelatedInfo( + d, + createDiagnosticForNode( + last.declaration, + Diagnostics.The_last_overload_is_declared_here, + ), + ); } addImplementationSuccessElaboration(last, d); diagnostics.add(d); @@ -33737,8 +43257,23 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { let minIndex = 0; let i = 0; for (const c of candidatesForArgumentError) { - const chain = () => chainDiagnosticMessages(/*details*/ undefined, Diagnostics.Overload_0_of_1_2_gave_the_following_error, i + 1, candidates.length, signatureToString(c)); - const diags = getSignatureApplicabilityError(node, args, c, assignableRelation, CheckMode.Normal, /*reportErrors*/ true, chain); + const chain = () => + chainDiagnosticMessages( + /*details*/ undefined, + Diagnostics.Overload_0_of_1_2_gave_the_following_error, + i + 1, + candidates.length, + signatureToString(c), + ); + const diags = getSignatureApplicabilityError( + node, + args, + c, + assignableRelation, + CheckMode.Normal, + /*reportErrors*/ true, + chain, + ); if (diags) { if (diags.length <= min) { min = diags.length; @@ -33764,11 +43299,26 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } // The below is a spread to guarantee we get a new (mutable) array - our `flatMap` helper tries to do "smart" optimizations where it reuses input // arrays and the emptyArray singleton where possible, which is decidedly not what we want while we're still constructing this diagnostic - const related = [...flatMap(diags, d => (d as Diagnostic).relatedInformation) as DiagnosticRelatedInformation[]]; + const related = [ + ...flatMap(diags, d => (d as Diagnostic).relatedInformation) as DiagnosticRelatedInformation[], + ]; let diag: Diagnostic; - if (every(diags, d => d.start === diags[0].start && d.length === diags[0].length && d.file === diags[0].file)) { + if ( + every( + diags, + d => d.start === diags[0].start && d.length === diags[0].length && d.file === diags[0].file, + ) + ) { const { file, start, length } = diags[0]; - diag = { file, start, length, code: chain.code, category: chain.category, messageText: chain, relatedInformation: related }; + diag = { + file, + start, + length, + code: chain.code, + category: chain.category, + messageText: chain, + relatedInformation: related, + }; } else { diag = createDiagnosticForNodeFromMessageChain(getSourceFileOfNode(node), node, chain, related); @@ -33781,15 +43331,25 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { diagnostics.add(getArgumentArityError(node, [candidateForArgumentArityError], args, headMessage)); } else if (candidateForTypeArgumentError) { - checkTypeArguments(candidateForTypeArgumentError, (node as CallExpression | TaggedTemplateExpression | JsxOpeningLikeElement).typeArguments!, /*reportErrors*/ true, headMessage); + checkTypeArguments( + candidateForTypeArgumentError, + (node as CallExpression | TaggedTemplateExpression | JsxOpeningLikeElement).typeArguments!, + /*reportErrors*/ true, + headMessage, + ); } else { - const signaturesWithCorrectTypeArgumentArity = filter(signatures, s => hasCorrectTypeArgumentArity(s, typeArguments)); + const signaturesWithCorrectTypeArgumentArity = filter( + signatures, + s => hasCorrectTypeArgumentArity(s, typeArguments), + ); if (signaturesWithCorrectTypeArgumentArity.length === 0) { diagnostics.add(getTypeArgumentArityError(node, signatures, typeArguments!, headMessage)); } else { - diagnostics.add(getArgumentArityError(node, signaturesWithCorrectTypeArgumentArity, args, headMessage)); + diagnostics.add( + getArgumentArityError(node, signaturesWithCorrectTypeArgumentArity, args, headMessage), + ); } } } @@ -33803,12 +43363,21 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const failedSignatureDeclarations = failed.declaration?.symbol?.declarations || emptyArray; const isOverload = failedSignatureDeclarations.length > 1; - const implDecl = isOverload ? find(failedSignatureDeclarations, d => isFunctionLikeDeclaration(d) && nodeIsPresent(d.body)) : undefined; + const implDecl = isOverload + ? find(failedSignatureDeclarations, d => isFunctionLikeDeclaration(d) && nodeIsPresent(d.body)) + : undefined; if (implDecl) { const candidate = getSignatureFromDeclaration(implDecl as FunctionLikeDeclaration); const isSingleNonGenericCandidate = !candidate.typeParameters; if (chooseOverload([candidate], assignableRelation, isSingleNonGenericCandidate)) { - addRelatedInfo(diagnostic, createDiagnosticForNode(implDecl, Diagnostics.The_call_would_have_succeeded_against_this_implementation_but_implementation_signatures_of_overloads_are_not_externally_visible)); + addRelatedInfo( + diagnostic, + createDiagnosticForNode( + implDecl, + Diagnostics + .The_call_would_have_succeeded_against_this_implementation_but_implementation_signatures_of_overloads_are_not_externally_visible, + ), + ); } } @@ -33817,7 +43386,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { candidateForTypeArgumentError = oldCandidateForTypeArgumentError; } - function chooseOverload(candidates: Signature[], relation: Map, isSingleNonGenericCandidate: boolean, signatureHelpTrailingComma = false) { + function chooseOverload( + candidates: Signature[], + relation: Map, + isSingleNonGenericCandidate: boolean, + signatureHelpTrailingComma = false, + ) { candidatesForArgumentError = undefined; candidateForArgumentArityError = undefined; candidateForTypeArgumentError = undefined; @@ -33827,7 +43401,17 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (some(typeArguments) || !hasCorrectArity(node, args, candidate, signatureHelpTrailingComma)) { return undefined; } - if (getSignatureApplicabilityError(node, args, candidate, relation, CheckMode.Normal, /*reportErrors*/ false, /*containingMessageChain*/ undefined)) { + if ( + getSignatureApplicabilityError( + node, + args, + candidate, + relation, + CheckMode.Normal, + /*reportErrors*/ false, + /*containingMessageChain*/ undefined, + ) + ) { candidatesForArgumentError = [candidate]; return undefined; } @@ -33836,7 +43420,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { for (let candidateIndex = 0; candidateIndex < candidates.length; candidateIndex++) { const candidate = candidates[candidateIndex]; - if (!hasCorrectTypeArgumentArity(candidate, typeArguments) || !hasCorrectArity(node, args, candidate, signatureHelpTrailingComma)) { + if ( + !hasCorrectTypeArgumentArity(candidate, typeArguments) + || !hasCorrectArity(node, args, candidate, signatureHelpTrailingComma) + ) { continue; } @@ -33853,14 +43440,33 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } else { - inferenceContext = createInferenceContext(candidate.typeParameters, candidate, /*flags*/ isInJSFile(node) ? InferenceFlags.AnyDefault : InferenceFlags.None); - typeArgumentTypes = inferTypeArguments(node, candidate, args, argCheckMode | CheckMode.SkipGenericFunctions, inferenceContext); - argCheckMode |= inferenceContext.flags & InferenceFlags.SkippedGenericFunction ? CheckMode.SkipGenericFunctions : CheckMode.Normal; - } - checkCandidate = getSignatureInstantiation(candidate, typeArgumentTypes, isInJSFile(candidate.declaration), inferenceContext && inferenceContext.inferredTypeParameters); + inferenceContext = createInferenceContext( + candidate.typeParameters, + candidate, + /*flags*/ isInJSFile(node) ? InferenceFlags.AnyDefault : InferenceFlags.None, + ); + typeArgumentTypes = inferTypeArguments( + node, + candidate, + args, + argCheckMode | CheckMode.SkipGenericFunctions, + inferenceContext, + ); + argCheckMode |= inferenceContext.flags & InferenceFlags.SkippedGenericFunction + ? CheckMode.SkipGenericFunctions : CheckMode.Normal; + } + checkCandidate = getSignatureInstantiation( + candidate, + typeArgumentTypes, + isInJSFile(candidate.declaration), + inferenceContext && inferenceContext.inferredTypeParameters, + ); // If the original signature has a generic rest type, instantiation may produce a // signature with different arity and we need to perform another arity check. - if (getNonArrayRestType(candidate) && !hasCorrectArity(node, args, checkCandidate, signatureHelpTrailingComma)) { + if ( + getNonArrayRestType(candidate) + && !hasCorrectArity(node, args, checkCandidate, signatureHelpTrailingComma) + ) { candidateForArgumentArityError = checkCandidate; continue; } @@ -33868,7 +43474,17 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { else { checkCandidate = candidate; } - if (getSignatureApplicabilityError(node, args, checkCandidate, relation, argCheckMode, /*reportErrors*/ false, /*containingMessageChain*/ undefined)) { + if ( + getSignatureApplicabilityError( + node, + args, + checkCandidate, + relation, + argCheckMode, + /*reportErrors*/ false, + /*containingMessageChain*/ undefined, + ) + ) { // Give preference to error candidates that have no rest parameters (as they are more specific) (candidatesForArgumentError || (candidatesForArgumentError = [])).push(checkCandidate); continue; @@ -33879,16 +43495,40 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // round of type inference and applicability checking for this particular candidate. argCheckMode = CheckMode.Normal; if (inferenceContext) { - const typeArgumentTypes = inferTypeArguments(node, candidate, args, argCheckMode, inferenceContext); - checkCandidate = getSignatureInstantiation(candidate, typeArgumentTypes, isInJSFile(candidate.declaration), inferenceContext.inferredTypeParameters); + const typeArgumentTypes = inferTypeArguments( + node, + candidate, + args, + argCheckMode, + inferenceContext, + ); + checkCandidate = getSignatureInstantiation( + candidate, + typeArgumentTypes, + isInJSFile(candidate.declaration), + inferenceContext.inferredTypeParameters, + ); // If the original signature has a generic rest type, instantiation may produce a // signature with different arity and we need to perform another arity check. - if (getNonArrayRestType(candidate) && !hasCorrectArity(node, args, checkCandidate, signatureHelpTrailingComma)) { + if ( + getNonArrayRestType(candidate) + && !hasCorrectArity(node, args, checkCandidate, signatureHelpTrailingComma) + ) { candidateForArgumentArityError = checkCandidate; continue; } } - if (getSignatureApplicabilityError(node, args, checkCandidate, relation, argCheckMode, /*reportErrors*/ false, /*containingMessageChain*/ undefined)) { + if ( + getSignatureApplicabilityError( + node, + args, + checkCandidate, + relation, + argCheckMode, + /*reportErrors*/ false, + /*containingMessageChain*/ undefined, + ) + ) { // Give preference to error candidates that have no rest parameters (as they are more specific) (candidatesForArgumentError || (candidatesForArgumentError = [])).push(checkCandidate); continue; @@ -33930,16 +43570,26 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const parameters: Symbol[] = []; for (let i = 0; i < maxNonRestParam; i++) { const symbols = mapDefined(candidates, s => - signatureHasRestParameter(s) ? - i < s.parameters.length - 1 ? s.parameters[i] : last(s.parameters) : - i < s.parameters.length ? s.parameters[i] : undefined); + signatureHasRestParameter(s) + ? i < s.parameters.length - 1 ? s.parameters[i] : last(s.parameters) + : i < s.parameters.length ? s.parameters[i] : undefined); Debug.assert(symbols.length !== 0); - parameters.push(createCombinedSymbolFromTypes(symbols, mapDefined(candidates, candidate => tryGetTypeAtPosition(candidate, i)))); + parameters.push( + createCombinedSymbolFromTypes( + symbols, + mapDefined(candidates, candidate => tryGetTypeAtPosition(candidate, i)), + ), + ); } - const restParameterSymbols = mapDefined(candidates, c => signatureHasRestParameter(c) ? last(c.parameters) : undefined); + const restParameterSymbols = mapDefined( + candidates, + c => signatureHasRestParameter(c) ? last(c.parameters) : undefined, + ); let flags = SignatureFlags.IsSignatureCandidateForOverloadFailure; if (restParameterSymbols.length !== 0) { - const type = createArrayType(getUnionType(mapDefined(candidates, tryGetRestTypeOfSignature), UnionReduction.Subtype)); + const type = createArrayType( + getUnionType(mapDefined(candidates, tryGetRestTypeOfSignature), UnionReduction.Subtype), + ); parameters.push(createCombinedSymbolForOverloadFailure(restParameterSymbols, type)); flags |= SignatureFlags.HasRestParameter; } @@ -33972,42 +43622,78 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return createSymbolWithType(first(sources), type); } - function pickLongestCandidateSignature(node: CallLikeExpression, candidates: Signature[], args: readonly Expression[], checkMode: CheckMode): Signature { + function pickLongestCandidateSignature( + node: CallLikeExpression, + candidates: Signature[], + args: readonly Expression[], + checkMode: CheckMode, + ): Signature { // Pick the longest signature. This way we can get a contextual type for cases like: // declare function f(a: { xa: number; xb: number; }, b: number); // f({ | // Also, use explicitly-supplied type arguments if they are provided, so we can get a contextual signature in cases like: // declare function f(k: keyof T); // f(" - const bestIndex = getLongestCandidateIndex(candidates, apparentArgumentCount === undefined ? args.length : apparentArgumentCount); + const bestIndex = getLongestCandidateIndex( + candidates, + apparentArgumentCount === undefined ? args.length : apparentArgumentCount, + ); const candidate = candidates[bestIndex]; const { typeParameters } = candidate; if (!typeParameters) { return candidate; } - const typeArgumentNodes: readonly TypeNode[] | undefined = callLikeExpressionMayHaveTypeArguments(node) ? node.typeArguments : undefined; + const typeArgumentNodes: readonly TypeNode[] | undefined = callLikeExpressionMayHaveTypeArguments(node) + ? node.typeArguments : undefined; const instantiated = typeArgumentNodes - ? createSignatureInstantiation(candidate, getTypeArgumentsFromNodes(typeArgumentNodes, typeParameters, isInJSFile(node))) + ? createSignatureInstantiation( + candidate, + getTypeArgumentsFromNodes(typeArgumentNodes, typeParameters, isInJSFile(node)), + ) : inferSignatureInstantiationForOverloadFailure(node, typeParameters, candidate, args, checkMode); candidates[bestIndex] = instantiated; return instantiated; } - function getTypeArgumentsFromNodes(typeArgumentNodes: readonly TypeNode[], typeParameters: readonly TypeParameter[], isJs: boolean): readonly Type[] { + function getTypeArgumentsFromNodes( + typeArgumentNodes: readonly TypeNode[], + typeParameters: readonly TypeParameter[], + isJs: boolean, + ): readonly Type[] { const typeArguments = typeArgumentNodes.map(getTypeOfNode); while (typeArguments.length > typeParameters.length) { typeArguments.pop(); } while (typeArguments.length < typeParameters.length) { - typeArguments.push(getDefaultFromTypeParameter(typeParameters[typeArguments.length]) || getConstraintOfTypeParameter(typeParameters[typeArguments.length]) || getDefaultTypeArgumentType(isJs)); + typeArguments.push( + getDefaultFromTypeParameter(typeParameters[typeArguments.length]) + || getConstraintOfTypeParameter(typeParameters[typeArguments.length]) + || getDefaultTypeArgumentType(isJs), + ); } return typeArguments; } - function inferSignatureInstantiationForOverloadFailure(node: CallLikeExpression, typeParameters: readonly TypeParameter[], candidate: Signature, args: readonly Expression[], checkMode: CheckMode): Signature { - const inferenceContext = createInferenceContext(typeParameters, candidate, /*flags*/ isInJSFile(node) ? InferenceFlags.AnyDefault : InferenceFlags.None); - const typeArgumentTypes = inferTypeArguments(node, candidate, args, checkMode | CheckMode.SkipContextSensitive | CheckMode.SkipGenericFunctions, inferenceContext); + function inferSignatureInstantiationForOverloadFailure( + node: CallLikeExpression, + typeParameters: readonly TypeParameter[], + candidate: Signature, + args: readonly Expression[], + checkMode: CheckMode, + ): Signature { + const inferenceContext = createInferenceContext( + typeParameters, + candidate, + /*flags*/ isInJSFile(node) ? InferenceFlags.AnyDefault : InferenceFlags.None, + ); + const typeArgumentTypes = inferTypeArguments( + node, + candidate, + args, + checkMode | CheckMode.SkipContextSensitive | CheckMode.SkipGenericFunctions, + inferenceContext, + ); return createSignatureInstantiation(candidate, typeArgumentTypes); } @@ -34030,7 +43716,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return maxParamsIndex; } - function resolveCallExpression(node: CallExpression, candidatesOutArray: Signature[] | undefined, checkMode: CheckMode): Signature { + function resolveCallExpression( + node: CallExpression, + candidatesOutArray: Signature[] | undefined, + checkMode: CheckMode, + ): Signature { if (node.expression.kind === SyntaxKind.SuperKeyword) { const superType = checkSuperExpression(node.expression); if (isTypeAny(superType)) { @@ -34044,7 +43734,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // with the type arguments specified in the extends clause. const baseTypeNode = getEffectiveBaseTypeNode(getContainingClass(node)!); if (baseTypeNode) { - const baseConstructors = getInstantiatedConstructorsForTypeArguments(superType, baseTypeNode.typeArguments, baseTypeNode); + const baseConstructors = getInstantiatedConstructorsForTypeArguments( + superType, + baseTypeNode.typeArguments, + baseTypeNode, + ); return resolveCall(node, baseConstructors, candidatesOutArray, checkMode, SignatureFlags.None); } } @@ -34055,9 +43749,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { let funcType = checkExpression(node.expression); if (isCallChain(node)) { const nonOptionalType = getOptionalExpressionType(funcType, node.expression); - callChainFlags = nonOptionalType === funcType ? SignatureFlags.None : - isOutermostOptionalChain(node) ? SignatureFlags.IsOuterCallChain : - SignatureFlags.IsInnerCallChain; + callChainFlags = nonOptionalType === funcType ? SignatureFlags.None + : isOutermostOptionalChain(node) ? SignatureFlags.IsOuterCallChain + : SignatureFlags.IsInnerCallChain; funcType = nonOptionalType; } else { @@ -34103,14 +43797,25 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // with multiple call signatures. if (!callSignatures.length) { if (numConstructSignatures) { - error(node, Diagnostics.Value_of_type_0_is_not_callable_Did_you_mean_to_include_new, typeToString(funcType)); + error( + node, + Diagnostics.Value_of_type_0_is_not_callable_Did_you_mean_to_include_new, + typeToString(funcType), + ); } else { let relatedInformation: DiagnosticRelatedInformation | undefined; if (node.arguments.length === 1) { const text = getSourceFileOfNode(node).text; - if (isLineBreak(text.charCodeAt(skipTrivia(text, node.expression.end, /*stopAfterLineBreak*/ true) - 1))) { - relatedInformation = createDiagnosticForNode(node.expression, Diagnostics.Are_you_missing_a_semicolon); + if ( + isLineBreak( + text.charCodeAt(skipTrivia(text, node.expression.end, /*stopAfterLineBreak*/ true) - 1), + ) + ) { + relatedInformation = createDiagnosticForNode( + node.expression, + Diagnostics.Are_you_missing_a_semicolon, + ); } } invocationError(node.expression, apparentType, SignatureKind.Call, relatedInformation); @@ -34129,13 +43834,20 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // use the resolvingSignature singleton to indicate that we deferred processing. This result will be // propagated out and eventually turned into silentNeverType (a type that is assignable to anything and // from which we never make inferences). - if (checkMode & CheckMode.SkipGenericFunctions && !node.typeArguments && callSignatures.some(isGenericFunctionReturningFunction)) { + if ( + checkMode & CheckMode.SkipGenericFunctions && !node.typeArguments + && callSignatures.some(isGenericFunctionReturningFunction) + ) { skippedGenericFunction(node, checkMode); return resolvingSignature; } // If the function is explicitly marked with `@class`, then it must be constructed. if (callSignatures.some(sig => isInJSFile(sig.declaration) && !!getJSDocClassTag(sig.declaration!))) { - error(node, Diagnostics.Value_of_type_0_is_not_callable_Did_you_mean_to_include_new, typeToString(funcType)); + error( + node, + Diagnostics.Value_of_type_0_is_not_callable_Did_you_mean_to_include_new, + typeToString(funcType), + ); return resolveErrorCall(node); } @@ -34151,17 +43863,32 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { * If FuncExpr is of type Any, or of an object type that has no call or construct signatures * but is a subtype of the Function interface, the call is an untyped function call. */ - function isUntypedFunctionCall(funcType: Type, apparentFuncType: Type, numCallSignatures: number, numConstructSignatures: number): boolean { + function isUntypedFunctionCall( + funcType: Type, + apparentFuncType: Type, + numCallSignatures: number, + numConstructSignatures: number, + ): boolean { // We exclude union types because we may have a union of function types that happen to have no common signatures. - return isTypeAny(funcType) || isTypeAny(apparentFuncType) && !!(funcType.flags & TypeFlags.TypeParameter) || - !numCallSignatures && !numConstructSignatures && !(apparentFuncType.flags & TypeFlags.Union) && !(getReducedType(apparentFuncType).flags & TypeFlags.Never) && isTypeAssignableTo(funcType, globalFunctionType); + return isTypeAny(funcType) || isTypeAny(apparentFuncType) && !!(funcType.flags & TypeFlags.TypeParameter) + || !numCallSignatures && !numConstructSignatures && !(apparentFuncType.flags & TypeFlags.Union) + && !(getReducedType(apparentFuncType).flags & TypeFlags.Never) + && isTypeAssignableTo(funcType, globalFunctionType); } - function resolveNewExpression(node: NewExpression, candidatesOutArray: Signature[] | undefined, checkMode: CheckMode): Signature { + function resolveNewExpression( + node: NewExpression, + candidatesOutArray: Signature[] | undefined, + checkMode: CheckMode, + ): Signature { if (node.arguments && languageVersion < ScriptTarget.ES5) { const spreadIndex = getSpreadArgumentIndex(node.arguments); if (spreadIndex >= 0) { - error(node.arguments[spreadIndex], Diagnostics.Spread_operator_in_new_expressions_is_only_available_when_targeting_ECMAScript_5_and_higher); + error( + node.arguments[spreadIndex], + Diagnostics + .Spread_operator_in_new_expressions_is_only_available_when_targeting_ECMAScript_5_and_higher, + ); } } @@ -34225,11 +43952,17 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (callSignatures.length) { const signature = resolveCall(node, callSignatures, candidatesOutArray, checkMode, SignatureFlags.None); if (!noImplicitAny) { - if (signature.declaration && !isJSConstructor(signature.declaration) && getReturnTypeOfSignature(signature) !== voidType) { + if ( + signature.declaration && !isJSConstructor(signature.declaration) + && getReturnTypeOfSignature(signature) !== voidType + ) { error(node, Diagnostics.Only_a_void_function_can_be_called_with_the_new_keyword); } if (getThisTypeOfSignature(signature) === voidType) { - error(node, Diagnostics.A_function_that_is_called_with_the_new_keyword_cannot_have_a_this_type_that_is_void); + error( + node, + Diagnostics.A_function_that_is_called_with_the_new_keyword_cannot_have_a_this_type_that_is_void, + ); } } return signature; @@ -34304,10 +44037,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } if (modifiers & ModifierFlags.Private) { - error(node, Diagnostics.Constructor_of_class_0_is_private_and_only_accessible_within_the_class_declaration, typeToString(declaringClass)); + error( + node, + Diagnostics.Constructor_of_class_0_is_private_and_only_accessible_within_the_class_declaration, + typeToString(declaringClass), + ); } if (modifiers & ModifierFlags.Protected) { - error(node, Diagnostics.Constructor_of_class_0_is_protected_and_only_accessible_within_the_class_declaration, typeToString(declaringClass)); + error( + node, + Diagnostics.Constructor_of_class_0_is_protected_and_only_accessible_within_the_class_declaration, + typeToString(declaringClass), + ); } return false; } @@ -34315,7 +44056,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return true; } - function invocationErrorDetails(errorTarget: Node, apparentType: Type, kind: SignatureKind): { messageChain: DiagnosticMessageChain; relatedMessage: DiagnosticMessage | undefined; } { + function invocationErrorDetails( + errorTarget: Node, + apparentType: Type, + kind: SignatureKind, + ): { messageChain: DiagnosticMessageChain; relatedMessage: DiagnosticMessage | undefined; } { let errorInfo: DiagnosticMessageChain | undefined; const isCall = kind === SignatureKind.Call; const awaitedType = getAwaitedType(apparentType); @@ -34337,16 +44082,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (!errorInfo) { errorInfo = chainDiagnosticMessages( errorInfo, - isCall ? - Diagnostics.Type_0_has_no_call_signatures : - Diagnostics.Type_0_has_no_construct_signatures, + isCall + ? Diagnostics.Type_0_has_no_call_signatures + : Diagnostics.Type_0_has_no_construct_signatures, typeToString(constituent), ); errorInfo = chainDiagnosticMessages( errorInfo, - isCall ? - Diagnostics.Not_all_constituents_of_type_0_are_callable : - Diagnostics.Not_all_constituents_of_type_0_are_constructable, + isCall + ? Diagnostics.Not_all_constituents_of_type_0_are_callable + : Diagnostics.Not_all_constituents_of_type_0_are_constructable, typeToString(apparentType), ); } @@ -34359,18 +44104,20 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (!hasSignatures) { errorInfo = chainDiagnosticMessages( /*details*/ undefined, - isCall ? - Diagnostics.No_constituent_of_type_0_is_callable : - Diagnostics.No_constituent_of_type_0_is_constructable, + isCall + ? Diagnostics.No_constituent_of_type_0_is_callable + : Diagnostics.No_constituent_of_type_0_is_constructable, typeToString(apparentType), ); } if (!errorInfo) { errorInfo = chainDiagnosticMessages( errorInfo, - isCall ? - Diagnostics.Each_member_of_the_union_type_0_has_signatures_but_none_of_those_signatures_are_compatible_with_each_other : - Diagnostics.Each_member_of_the_union_type_0_has_construct_signatures_but_none_of_those_signatures_are_compatible_with_each_other, + isCall + ? Diagnostics + .Each_member_of_the_union_type_0_has_signatures_but_none_of_those_signatures_are_compatible_with_each_other + : Diagnostics + .Each_member_of_the_union_type_0_has_construct_signatures_but_none_of_those_signatures_are_compatible_with_each_other, typeToString(apparentType), ); } @@ -34378,20 +44125,22 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { else { errorInfo = chainDiagnosticMessages( errorInfo, - isCall ? - Diagnostics.Type_0_has_no_call_signatures : - Diagnostics.Type_0_has_no_construct_signatures, + isCall + ? Diagnostics.Type_0_has_no_call_signatures + : Diagnostics.Type_0_has_no_construct_signatures, typeToString(apparentType), ); } - let headMessage = isCall ? Diagnostics.This_expression_is_not_callable : Diagnostics.This_expression_is_not_constructable; + let headMessage = isCall ? Diagnostics.This_expression_is_not_callable + : Diagnostics.This_expression_is_not_constructable; // Diagnose get accessors incorrectly called as functions if (isCallExpression(errorTarget.parent) && errorTarget.parent.arguments.length === 0) { const { resolvedSymbol } = getNodeLinks(errorTarget); if (resolvedSymbol && resolvedSymbol.flags & SymbolFlags.GetAccessor) { - headMessage = Diagnostics.This_expression_is_not_callable_because_it_is_a_get_accessor_Did_you_mean_to_use_it_without; + headMessage = Diagnostics + .This_expression_is_not_callable_because_it_is_a_get_accessor_Did_you_mean_to_use_it_without; } } @@ -34400,9 +44149,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { relatedMessage: maybeMissingAwait ? Diagnostics.Did_you_forget_to_use_await : undefined, }; } - function invocationError(errorTarget: Node, apparentType: Type, kind: SignatureKind, relatedInformation?: DiagnosticRelatedInformation) { + function invocationError( + errorTarget: Node, + apparentType: Type, + kind: SignatureKind, + relatedInformation?: DiagnosticRelatedInformation, + ) { const { messageChain, relatedMessage: relatedInfo } = invocationErrorDetails(errorTarget, apparentType, kind); - const diagnostic = createDiagnosticForNodeFromMessageChain(getSourceFileOfNode(errorTarget), errorTarget, messageChain); + const diagnostic = createDiagnosticForNodeFromMessageChain( + getSourceFileOfNode(errorTarget), + errorTarget, + messageChain, + ); if (relatedInfo) { addRelatedInfo(diagnostic, createDiagnosticForNode(errorTarget, relatedInfo)); } @@ -34412,7 +44170,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { diagnostic.length = length; } diagnostics.add(diagnostic); - invocationErrorRecovery(apparentType, kind, relatedInformation ? addRelatedInfo(diagnostic, relatedInformation) : diagnostic); + invocationErrorRecovery( + apparentType, + kind, + relatedInformation ? addRelatedInfo(diagnostic, relatedInformation) : diagnostic, + ); } function invocationErrorRecovery(apparentType: Type, kind: SignatureKind, diagnostic: Diagnostic) { @@ -34426,11 +44188,22 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const sigs = getSignaturesOfType(getTypeOfSymbol(getSymbolLinks(apparentType.symbol).target!), kind); if (!sigs || !sigs.length) return; - addRelatedInfo(diagnostic, createDiagnosticForNode(importNode, Diagnostics.Type_originates_at_this_import_A_namespace_style_import_cannot_be_called_or_constructed_and_will_cause_a_failure_at_runtime_Consider_using_a_default_import_or_import_require_here_instead)); + addRelatedInfo( + diagnostic, + createDiagnosticForNode( + importNode, + Diagnostics + .Type_originates_at_this_import_A_namespace_style_import_cannot_be_called_or_constructed_and_will_cause_a_failure_at_runtime_Consider_using_a_default_import_or_import_require_here_instead, + ), + ); } } - function resolveTaggedTemplateExpression(node: TaggedTemplateExpression, candidatesOutArray: Signature[] | undefined, checkMode: CheckMode): Signature { + function resolveTaggedTemplateExpression( + node: TaggedTemplateExpression, + candidatesOutArray: Signature[] | undefined, + checkMode: CheckMode, + ): Signature { const tagType = checkExpression(node.tag); const apparentType = getApparentType(tagType); @@ -34448,7 +44221,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (!callSignatures.length) { if (isArrayLiteralExpression(node.parent)) { - const diagnostic = createDiagnosticForNode(node.tag, Diagnostics.It_is_likely_that_you_are_missing_a_comma_to_separate_these_two_template_expressions_They_form_a_tagged_template_expression_which_cannot_be_invoked); + const diagnostic = createDiagnosticForNode( + node.tag, + Diagnostics + .It_is_likely_that_you_are_missing_a_comma_to_separate_these_two_template_expressions_They_form_a_tagged_template_expression_which_cannot_be_invoked, + ); diagnostics.add(diagnostic); return resolveErrorCall(node); } @@ -34488,7 +44265,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { /** * Resolves a decorator as if it were a call expression. */ - function resolveDecorator(node: Decorator, candidatesOutArray: Signature[] | undefined, checkMode: CheckMode): Signature { + function resolveDecorator( + node: Decorator, + candidatesOutArray: Signature[] | undefined, + checkMode: CheckMode, + ): Signature { const funcType = checkExpression(node.expression); const apparentType = getApparentType(funcType); if (isErrorType(apparentType)) { @@ -34503,7 +44284,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (isPotentiallyUncalledDecorator(node, callSignatures) && !isParenthesizedExpression(node.expression)) { const nodeStr = getTextOfNode(node.expression, /*includeTrivia*/ false); - error(node, Diagnostics._0_accepts_too_few_arguments_to_be_used_as_a_decorator_here_Did_you_mean_to_call_it_first_and_write_0, nodeStr); + error( + node, + Diagnostics + ._0_accepts_too_few_arguments_to_be_used_as_a_decorator_here_Did_you_mean_to_call_it_first_and_write_0, + nodeStr, + ); return resolveErrorCall(node); } @@ -34511,7 +44297,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (!callSignatures.length) { const errorDetails = invocationErrorDetails(node.expression, apparentType, SignatureKind.Call); const messageChain = chainDiagnosticMessages(errorDetails.messageChain, headMessage); - const diag = createDiagnosticForNodeFromMessageChain(getSourceFileOfNode(node.expression), node.expression, messageChain); + const diag = createDiagnosticForNodeFromMessageChain( + getSourceFileOfNode(node.expression), + node.expression, + messageChain, + ); if (errorDetails.relatedMessage) { addRelatedInfo(diag, createDiagnosticForNode(node.expression, errorDetails.relatedMessage)); } @@ -34530,7 +44320,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // file would probably be preferable. const typeSymbol = exports && getSymbol(exports, JsxNames.Element, SymbolFlags.Type); const returnNode = typeSymbol && nodeBuilder.symbolToEntityName(typeSymbol, SymbolFlags.Type, node); - const declaration = factory.createFunctionTypeNode(/*typeParameters*/ undefined, [factory.createParameterDeclaration(/*modifiers*/ undefined, /*dotDotDotToken*/ undefined, "props", /*questionToken*/ undefined, nodeBuilder.typeToTypeNode(result, node))], returnNode ? factory.createTypeReferenceNode(returnNode, /*typeArguments*/ undefined) : factory.createKeywordTypeNode(SyntaxKind.AnyKeyword)); + const declaration = factory.createFunctionTypeNode( + /*typeParameters*/ undefined, + [factory.createParameterDeclaration( + /*modifiers*/ undefined, + /*dotDotDotToken*/ undefined, + "props", + /*questionToken*/ undefined, + nodeBuilder.typeToTypeNode(result, node), + )], + returnNode ? factory.createTypeReferenceNode(returnNode, /*typeArguments*/ undefined) + : factory.createKeywordTypeNode(SyntaxKind.AnyKeyword), + ); const parameterSymbol = createSymbol(SymbolFlags.FunctionScopedVariable, "props" as __String); parameterSymbol.links.type = result; return createSignature( @@ -34545,14 +44346,36 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { ); } - function resolveJsxOpeningLikeElement(node: JsxOpeningLikeElement, candidatesOutArray: Signature[] | undefined, checkMode: CheckMode): Signature { + function resolveJsxOpeningLikeElement( + node: JsxOpeningLikeElement, + candidatesOutArray: Signature[] | undefined, + checkMode: CheckMode, + ): Signature { if (isJsxIntrinsicTagName(node.tagName)) { const result = getIntrinsicAttributesTypeFromJsxOpeningLikeElement(node); const fakeSignature = createSignatureForJSXIntrinsic(node, result); - checkTypeAssignableToAndOptionallyElaborate(checkExpressionWithContextualType(node.attributes, getEffectiveFirstArgumentForJsxSignature(fakeSignature, node), /*inferenceContext*/ undefined, CheckMode.Normal), result, node.tagName, node.attributes); + checkTypeAssignableToAndOptionallyElaborate( + checkExpressionWithContextualType( + node.attributes, + getEffectiveFirstArgumentForJsxSignature(fakeSignature, node), + /*inferenceContext*/ undefined, + CheckMode.Normal, + ), + result, + node.tagName, + node.attributes, + ); if (length(node.typeArguments)) { forEach(node.typeArguments, checkSourceElement); - diagnostics.add(createDiagnosticForNodeArray(getSourceFileOfNode(node), node.typeArguments!, Diagnostics.Expected_0_type_arguments_but_got_1, 0, length(node.typeArguments))); + diagnostics.add( + createDiagnosticForNodeArray( + getSourceFileOfNode(node), + node.typeArguments!, + Diagnostics.Expected_0_type_arguments_but_got_1, + 0, + length(node.typeArguments), + ), + ); } return fakeSignature; } @@ -34569,7 +44392,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (signatures.length === 0) { // We found no signatures at all, which is an error - error(node.tagName, Diagnostics.JSX_element_type_0_does_not_have_any_construct_or_call_signatures, getTextOfNode(node.tagName)); + error( + node.tagName, + Diagnostics.JSX_element_type_0_does_not_have_any_construct_or_call_signatures, + getTextOfNode(node.tagName), + ); return resolveErrorCall(node); } @@ -34583,12 +44410,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { */ function isPotentiallyUncalledDecorator(decorator: Decorator, signatures: readonly Signature[]) { return signatures.length && every(signatures, signature => - signature.minArgumentCount === 0 && - !signatureHasRestParameter(signature) && - signature.parameters.length < getDecoratorArgumentCount(decorator, signature)); + signature.minArgumentCount === 0 + && !signatureHasRestParameter(signature) + && signature.parameters.length < getDecoratorArgumentCount(decorator, signature)); } - function resolveSignature(node: CallLikeExpression, candidatesOutArray: Signature[] | undefined, checkMode: CheckMode): Signature { + function resolveSignature( + node: CallLikeExpression, + candidatesOutArray: Signature[] | undefined, + checkMode: CheckMode, + ): Signature { switch (node.kind) { case SyntaxKind.CallExpression: return resolveCallExpression(node, candidatesOutArray, checkMode); @@ -34612,7 +44443,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { * the function will fill it up with appropriate candidate signatures * @return a signature of the call-like expression or undefined if one can't be found */ - function getResolvedSignature(node: CallLikeExpression, candidatesOutArray?: Signature[] | undefined, checkMode?: CheckMode): Signature { + function getResolvedSignature( + node: CallLikeExpression, + candidatesOutArray?: Signature[] | undefined, + checkMode?: CheckMode, + ): Signature { const links = getNodeLinks(node); // If getResolvedSignature has already been called, we will have cached the resolvedSignature. // However, it is possible that either candidatesOutArray was not passed in the first time, @@ -34651,9 +44486,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (!node || !isInJSFile(node)) { return false; } - const func = isFunctionDeclaration(node) || isFunctionExpression(node) ? node : - (isVariableDeclaration(node) || isPropertyAssignment(node)) && node.initializer && isFunctionExpression(node.initializer) ? node.initializer : - undefined; + const func = isFunctionDeclaration(node) || isFunctionExpression(node) ? node + : (isVariableDeclaration(node) || isPropertyAssignment(node)) && node.initializer + && isFunctionExpression(node.initializer) ? node.initializer + : undefined; if (func) { // If the node has a @class or @constructor tag, treat it like a constructor. if (getJSDocClassTag(node)) return true; @@ -34682,7 +44518,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (source.members?.size) { mergeSymbolTable(inferred.members, source.members); } - (links.inferredClassSymbol || (links.inferredClassSymbol = new Map())).set(getSymbolId(inferred), inferred); + (links.inferredClassSymbol || (links.inferredClassSymbol = new Map())).set( + getSymbolId(inferred), + inferred, + ); return inferred; } return links.inferredClassSymbol.get(getSymbolId(target)); @@ -34716,12 +44555,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { name = parentNode.left; decl = name; } - else if (parentNodeOperator === SyntaxKind.BarBarToken || parentNodeOperator === SyntaxKind.QuestionQuestionToken) { + else if ( + parentNodeOperator === SyntaxKind.BarBarToken || parentNodeOperator === SyntaxKind.QuestionQuestionToken + ) { if (isVariableDeclaration(parentNode.parent) && parentNode.parent.initializer === parentNode) { name = parentNode.parent.name; decl = parentNode.parent; } - else if (isBinaryExpression(parentNode.parent) && parentNode.parent.operatorToken.kind === SyntaxKind.EqualsToken && (allowDeclaration || parentNode.parent.right === parentNode)) { + else if ( + isBinaryExpression(parentNode.parent) + && parentNode.parent.operatorToken.kind === SyntaxKind.EqualsToken + && (allowDeclaration || parentNode.parent.right === parentNode) + ) { name = parentNode.parent.left; decl = name; } @@ -34750,7 +44595,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { while (parent && parent.kind === SyntaxKind.PropertyAccessExpression) { parent = parent.parent; } - if (parent && isBinaryExpression(parent) && isPrototypeAccess(parent.left) && parent.operatorToken.kind === SyntaxKind.EqualsToken) { + if ( + parent && isBinaryExpression(parent) && isPrototypeAccess(parent.left) + && parent.operatorToken.kind === SyntaxKind.EqualsToken + ) { const right = getInitializerOfBinaryExpression(parent); return isObjectLiteralExpression(right) && right; } @@ -34781,17 +44629,21 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const declaration = signature.declaration; if ( - declaration && - declaration.kind !== SyntaxKind.Constructor && - declaration.kind !== SyntaxKind.ConstructSignature && - declaration.kind !== SyntaxKind.ConstructorType && - !(isJSDocSignature(declaration) && getJSDocRoot(declaration)?.parent?.kind === SyntaxKind.Constructor) && - !isJSDocConstructSignature(declaration) && - !isJSConstructor(declaration) + declaration + && declaration.kind !== SyntaxKind.Constructor + && declaration.kind !== SyntaxKind.ConstructSignature + && declaration.kind !== SyntaxKind.ConstructorType + && !(isJSDocSignature(declaration) + && getJSDocRoot(declaration)?.parent?.kind === SyntaxKind.Constructor) + && !isJSDocConstructSignature(declaration) + && !isJSConstructor(declaration) ) { // When resolved signature is a call signature (and not a construct signature) the result type is any if (noImplicitAny) { - error(node, Diagnostics.new_expression_whose_target_lacks_a_construct_signature_implicitly_has_an_any_type); + error( + node, + Diagnostics.new_expression_whose_target_lacks_a_construct_signature_implicitly_has_an_any_type, + ); } return anyType; } @@ -34809,14 +44661,22 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return getESSymbolLikeTypeForNode(walkUpParenthesizedExpressions(node.parent)); } if ( - node.kind === SyntaxKind.CallExpression && !node.questionDotToken && node.parent.kind === SyntaxKind.ExpressionStatement && - returnType.flags & TypeFlags.Void && getTypePredicateOfSignature(signature) + node.kind === SyntaxKind.CallExpression && !node.questionDotToken + && node.parent.kind === SyntaxKind.ExpressionStatement + && returnType.flags & TypeFlags.Void && getTypePredicateOfSignature(signature) ) { if (!isDottedName(node.expression)) { - error(node.expression, Diagnostics.Assertions_require_the_call_target_to_be_an_identifier_or_qualified_name); + error( + node.expression, + Diagnostics.Assertions_require_the_call_target_to_be_an_identifier_or_qualified_name, + ); } else if (!getEffectsSignature(node)) { - const diagnostic = error(node.expression, Diagnostics.Assertions_require_every_name_in_the_call_target_to_be_declared_with_an_explicit_type_annotation); + const diagnostic = error( + node.expression, + Diagnostics + .Assertions_require_every_name_in_the_call_target_to_be_declared_with_an_explicit_type_annotation, + ); getTypeOfDottedName(node.expression, diagnostic); } } @@ -34824,7 +44684,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (isInJSFile(node)) { const jsSymbol = getSymbolOfExpando(node, /*allowDeclaration*/ false); if (jsSymbol?.exports?.size) { - const jsAssignmentType = createAnonymousType(jsSymbol, jsSymbol.exports, emptyArray, emptyArray, emptyArray); + const jsAssignmentType = createAnonymousType( + jsSymbol, + jsSymbol.exports, + emptyArray, + emptyArray, + emptyArray, + ); jsAssignmentType.objectFlags |= ObjectFlags.JSLiteral; return getIntersectionType([returnType, jsAssignmentType]); } @@ -34838,7 +44704,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (signature.declaration && signature.declaration.flags & NodeFlags.Deprecated) { const suggestionNode = getDeprecatedSuggestionNode(node); const name = tryGetPropertyAccessOrIdentifierToString(getInvokedExpression(node)); - addDeprecatedSuggestionWithSignature(suggestionNode, signature.declaration, name, signatureToString(signature)); + addDeprecatedSuggestionWithSignature( + suggestionNode, + signature.declaration, + name, + signatureToString(signature), + ); } } @@ -34882,7 +44753,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return false; } - return globalESSymbol === resolveName(left, "Symbol" as __String, SymbolFlags.Value, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ false); + return globalESSymbol + === resolveName( + left, + "Symbol" as __String, + SymbolFlags.Value, + /*nameNotFoundMessage*/ undefined, + /*nameArg*/ undefined, + /*isUse*/ false, + ); } function checkImportCallExpression(node: ImportCall): Type { @@ -34901,33 +44780,63 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { checkExpressionCached(node.arguments[i]); } - if (specifierType.flags & TypeFlags.Undefined || specifierType.flags & TypeFlags.Null || !isTypeAssignableTo(specifierType, stringType)) { - error(specifier, Diagnostics.Dynamic_import_s_specifier_must_be_of_type_string_but_here_has_type_0, typeToString(specifierType)); + if ( + specifierType.flags & TypeFlags.Undefined || specifierType.flags & TypeFlags.Null + || !isTypeAssignableTo(specifierType, stringType) + ) { + error( + specifier, + Diagnostics.Dynamic_import_s_specifier_must_be_of_type_string_but_here_has_type_0, + typeToString(specifierType), + ); } if (optionsType) { const importCallOptionsType = getGlobalImportCallOptionsType(/*reportErrors*/ true); if (importCallOptionsType !== emptyObjectType) { - checkTypeAssignableTo(optionsType, getNullableType(importCallOptionsType, TypeFlags.Undefined), node.arguments[1]); + checkTypeAssignableTo( + optionsType, + getNullableType(importCallOptionsType, TypeFlags.Undefined), + node.arguments[1], + ); } } // resolveExternalModuleName will return undefined if the moduleReferenceExpression is not a string literal const moduleSymbol = resolveExternalModuleName(node, specifier); if (moduleSymbol) { - const esModuleSymbol = resolveESModuleSymbol(moduleSymbol, specifier, /*dontResolveAlias*/ true, /*suppressInteropError*/ false); + const esModuleSymbol = resolveESModuleSymbol( + moduleSymbol, + specifier, + /*dontResolveAlias*/ true, + /*suppressInteropError*/ false, + ); if (esModuleSymbol) { return createPromiseReturnType( node, - getTypeWithSyntheticDefaultOnly(getTypeOfSymbol(esModuleSymbol), esModuleSymbol, moduleSymbol, specifier) || - getTypeWithSyntheticDefaultImportType(getTypeOfSymbol(esModuleSymbol), esModuleSymbol, moduleSymbol, specifier), + getTypeWithSyntheticDefaultOnly( + getTypeOfSymbol(esModuleSymbol), + esModuleSymbol, + moduleSymbol, + specifier, + ) + || getTypeWithSyntheticDefaultImportType( + getTypeOfSymbol(esModuleSymbol), + esModuleSymbol, + moduleSymbol, + specifier, + ), ); } } return createPromiseReturnType(node, anyType); } - function createDefaultPropertyWrapperForModule(symbol: Symbol, originalSymbol: Symbol | undefined, anonymousSymbol?: Symbol | undefined) { + function createDefaultPropertyWrapperForModule( + symbol: Symbol, + originalSymbol: Symbol | undefined, + anonymousSymbol?: Symbol | undefined, + ) { const memberTable = createSymbolTable(); const newSymbol = createSymbol(SymbolFlags.Alias, InternalSymbolName.Default); newSymbol.parent = originalSymbol; @@ -34937,7 +44846,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return createAnonymousType(anonymousSymbol, memberTable, emptyArray, emptyArray, emptyArray); } - function getTypeWithSyntheticDefaultOnly(type: Type, symbol: Symbol, originalSymbol: Symbol, moduleSpecifier: Expression) { + function getTypeWithSyntheticDefaultOnly( + type: Type, + symbol: Symbol, + originalSymbol: Symbol, + moduleSpecifier: Expression, + ) { const hasDefaultOnly = isOnlyImportedAsDefault(moduleSpecifier); if (hasDefaultOnly && type && !isErrorType(type)) { const synthType = type as SyntheticDefaultModuleType; @@ -34950,17 +44864,38 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return undefined; } - function getTypeWithSyntheticDefaultImportType(type: Type, symbol: Symbol, originalSymbol: Symbol, moduleSpecifier: Expression): Type { + function getTypeWithSyntheticDefaultImportType( + type: Type, + symbol: Symbol, + originalSymbol: Symbol, + moduleSpecifier: Expression, + ): Type { if (allowSyntheticDefaultImports && type && !isErrorType(type)) { const synthType = type as SyntheticDefaultModuleType; if (!synthType.syntheticType) { const file = originalSymbol.declarations?.find(isSourceFile); - const hasSyntheticDefault = canHaveSyntheticDefault(file, originalSymbol, /*dontResolveAlias*/ false, moduleSpecifier); + const hasSyntheticDefault = canHaveSyntheticDefault( + file, + originalSymbol, + /*dontResolveAlias*/ false, + moduleSpecifier, + ); if (hasSyntheticDefault) { const anonymousSymbol = createSymbol(SymbolFlags.TypeLiteral, InternalSymbolName.Type); - const defaultContainingObject = createDefaultPropertyWrapperForModule(symbol, originalSymbol, anonymousSymbol); + const defaultContainingObject = createDefaultPropertyWrapperForModule( + symbol, + originalSymbol, + anonymousSymbol, + ); anonymousSymbol.links.type = defaultContainingObject; - synthType.syntheticType = isValidSpreadType(type) ? getSpreadType(type, defaultContainingObject, anonymousSymbol, /*objectFlags*/ 0, /*readonly*/ false) : defaultContainingObject; + synthType.syntheticType = isValidSpreadType(type) + ? getSpreadType( + type, + defaultContainingObject, + anonymousSymbol, + /*objectFlags*/ 0, + /*readonly*/ false, + ) : defaultContainingObject; } else { synthType.syntheticType = type; @@ -34978,7 +44913,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // Make sure require is not a local function if (!isIdentifier(node.expression)) return Debug.fail(); - const resolvedRequire = resolveName(node.expression, node.expression.escapedText, SymbolFlags.Value, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ true)!; // TODO: GH#18217 + const resolvedRequire = resolveName( + node.expression, + node.expression.escapedText, + SymbolFlags.Value, + /*nameNotFoundMessage*/ undefined, + /*nameArg*/ undefined, + /*isUse*/ true, + )!; // TODO: GH#18217 if (resolvedRequire === requireSymbol) { return true; } @@ -35014,7 +44956,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (node.kind === SyntaxKind.TypeAssertionExpression) { const file = getSourceFileOfNode(node); if (file && fileExtensionIsOneOf(file.fileName, [Extension.Cts, Extension.Mts])) { - grammarErrorOnNode(node, Diagnostics.This_syntax_is_reserved_in_files_with_the_mts_or_cts_extension_Use_an_as_expression_instead); + grammarErrorOnNode( + node, + Diagnostics + .This_syntax_is_reserved_in_files_with_the_mts_or_cts_extension_Use_an_as_expression_instead, + ); } } return checkAssertionWorker(node, checkMode); @@ -35037,12 +44983,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { case SyntaxKind.PrefixUnaryExpression: const op = (node as PrefixUnaryExpression).operator; const arg = (node as PrefixUnaryExpression).operand; - return op === SyntaxKind.MinusToken && (arg.kind === SyntaxKind.NumericLiteral || arg.kind === SyntaxKind.BigIntLiteral) || - op === SyntaxKind.PlusToken && arg.kind === SyntaxKind.NumericLiteral; + return op === SyntaxKind.MinusToken + && (arg.kind === SyntaxKind.NumericLiteral || arg.kind === SyntaxKind.BigIntLiteral) + || op === SyntaxKind.PlusToken && arg.kind === SyntaxKind.NumericLiteral; case SyntaxKind.PropertyAccessExpression: case SyntaxKind.ElementAccessExpression: const expr = skipParentheses((node as PropertyAccessExpression | ElementAccessExpression).expression); - const symbol = isEntityNameExpression(expr) ? resolveEntityName(expr, SymbolFlags.Value, /*ignoreErrors*/ true) : undefined; + const symbol = isEntityNameExpression(expr) + ? resolveEntityName(expr, SymbolFlags.Value, /*ignoreErrors*/ true) : undefined; return !!(symbol && symbol.flags & SymbolFlags.Enum); } return false; @@ -35053,7 +45001,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const exprType = checkExpression(expression, checkMode); if (isConstTypeReference(type)) { if (!isValidConstAssertionArgument(expression)) { - error(expression, Diagnostics.A_const_assertions_can_only_be_applied_to_references_to_enum_members_or_string_number_boolean_array_or_object_literals); + error( + expression, + Diagnostics + .A_const_assertions_can_only_be_applied_to_references_to_enum_members_or_string_number_boolean_array_or_object_literals, + ); } return getRegularTypeOfLiteralType(exprType); } @@ -35093,7 +45045,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { addLazyDiagnostic(() => { const widenedType = getWidenedType(exprType); if (!isTypeComparableTo(targetType, widenedType)) { - checkTypeComparableTo(exprType, targetType, errNode, Diagnostics.Conversion_of_type_0_to_type_1_may_be_a_mistake_because_neither_type_sufficiently_overlaps_with_the_other_If_this_was_intentional_convert_the_expression_to_unknown_first); + checkTypeComparableTo( + exprType, + targetType, + errNode, + Diagnostics + .Conversion_of_type_0_to_type_1_may_be_a_mistake_because_neither_type_sufficiently_overlaps_with_the_other_If_this_was_intentional_convert_the_expression_to_unknown_first, + ); } }); } @@ -35106,8 +45064,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function checkNonNullAssertion(node: NonNullExpression) { - return node.flags & NodeFlags.OptionalChain ? checkNonNullChain(node as NonNullChain) : - getNonNullableType(checkExpression(node.expression)); + return node.flags & NodeFlags.OptionalChain ? checkNonNullChain(node as NonNullChain) + : getNonNullableType(checkExpression(node.expression)); } function checkExpressionWithTypeArguments(node: ExpressionWithTypeArguments | TypeQueryNode) { @@ -35115,13 +45073,20 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { forEach(node.typeArguments, checkSourceElement); if (node.kind === SyntaxKind.ExpressionWithTypeArguments) { const parent = walkUpParenthesizedExpressions(node.parent); - if (parent.kind === SyntaxKind.BinaryExpression && (parent as BinaryExpression).operatorToken.kind === SyntaxKind.InstanceOfKeyword && isNodeDescendantOf(node, (parent as BinaryExpression).right)) { - error(node, Diagnostics.The_right_hand_side_of_an_instanceof_expression_must_not_be_an_instantiation_expression); + if ( + parent.kind === SyntaxKind.BinaryExpression + && (parent as BinaryExpression).operatorToken.kind === SyntaxKind.InstanceOfKeyword + && isNodeDescendantOf(node, (parent as BinaryExpression).right) + ) { + error( + node, + Diagnostics.The_right_hand_side_of_an_instanceof_expression_must_not_be_an_instantiation_expression, + ); } } - const exprType = node.kind === SyntaxKind.ExpressionWithTypeArguments ? checkExpression(node.expression) : - isThisIdentifier(node.exprName) ? checkThisExpression(node.exprName) : - checkExpression(node.exprName); + const exprType = node.kind === SyntaxKind.ExpressionWithTypeArguments ? checkExpression(node.expression) + : isThisIdentifier(node.exprName) ? checkThisExpression(node.exprName) + : checkExpression(node.exprName); return getInstantiationExpressionType(exprType, node); } @@ -35135,7 +45100,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const result = getInstantiatedType(exprType); const errorType = hasSomeApplicableSignature ? nonApplicableType : exprType; if (errorType) { - diagnostics.add(createDiagnosticForNodeArray(getSourceFileOfNode(node), typeArguments, Diagnostics.Type_0_has_no_signatures_for_which_the_type_argument_list_is_applicable, typeToString(errorType))); + diagnostics.add( + createDiagnosticForNodeArray( + getSourceFileOfNode(node), + typeArguments, + Diagnostics.Type_0_has_no_signatures_for_which_the_type_argument_list_is_applicable, + typeToString(errorType), + ), + ); } return result; @@ -35156,8 +45128,17 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const constructSignatures = getInstantiatedSignatures(resolved.constructSignatures); hasSignatures ||= resolved.callSignatures.length !== 0 || resolved.constructSignatures.length !== 0; hasApplicableSignature ||= callSignatures.length !== 0 || constructSignatures.length !== 0; - if (callSignatures !== resolved.callSignatures || constructSignatures !== resolved.constructSignatures) { - const result = createAnonymousType(/*symbol*/ undefined, resolved.members, callSignatures, constructSignatures, resolved.indexInfos) as ResolvedType & InstantiationExpressionType; + if ( + callSignatures !== resolved.callSignatures + || constructSignatures !== resolved.constructSignatures + ) { + const result = createAnonymousType( + /*symbol*/ undefined, + resolved.members, + callSignatures, + constructSignatures, + resolved.indexInfos, + ) as ResolvedType & InstantiationExpressionType; result.objectFlags |= ObjectFlags.InstantiationExpressionType; result.node = node; return result; @@ -35183,10 +45164,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function getInstantiatedSignatures(signatures: readonly Signature[]) { - const applicableSignatures = filter(signatures, sig => !!sig.typeParameters && hasCorrectTypeArgumentArity(sig, typeArguments)); + const applicableSignatures = filter( + signatures, + sig => !!sig.typeParameters && hasCorrectTypeArgumentArity(sig, typeArguments), + ); return sameMap(applicableSignatures, sig => { const typeArgumentTypes = checkTypeArguments(sig, typeArguments!, /*reportErrors*/ true); - return typeArgumentTypes ? getSignatureInstantiation(sig, typeArgumentTypes, isInJSFile(sig.declaration)) : sig; + return typeArgumentTypes + ? getSignatureInstantiation(sig, typeArgumentTypes, isInJSFile(sig.declaration)) : sig; }); } } @@ -35202,8 +45187,17 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (isErrorType(targetType)) { return targetType; } - const errorNode = findAncestor(target.parent, n => n.kind === SyntaxKind.SatisfiesExpression || n.kind === SyntaxKind.JSDocSatisfiesTag); - checkTypeAssignableToAndOptionallyElaborate(exprType, targetType, errorNode, expression, Diagnostics.Type_0_does_not_satisfy_the_expected_type_1); + const errorNode = findAncestor( + target.parent, + n => n.kind === SyntaxKind.SatisfiesExpression || n.kind === SyntaxKind.JSDocSatisfiesTag, + ); + checkTypeAssignableToAndOptionallyElaborate( + exprType, + targetType, + errorNode, + expression, + Diagnostics.Type_0_does_not_satisfy_the_expected_type_1, + ); return exprType; } @@ -35236,7 +45230,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function checkNewTargetMetaProperty(node: MetaProperty) { const container = getNewTargetContainer(node); if (!container) { - error(node, Diagnostics.Meta_property_0_is_only_allowed_in_the_body_of_a_function_declaration_function_expression_or_constructor, "new.target"); + error( + node, + Diagnostics + .Meta_property_0_is_only_allowed_in_the_body_of_a_function_declaration_function_expression_or_constructor, + "new.target", + ); return errorType; } else if (container.kind === SyntaxKind.Constructor) { @@ -35252,14 +45251,25 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function checkImportMetaProperty(node: MetaProperty) { if (moduleKind === ModuleKind.Node16 || moduleKind === ModuleKind.NodeNext) { if (getSourceFileOfNode(node).impliedNodeFormat !== ModuleKind.ESNext) { - error(node, Diagnostics.The_import_meta_meta_property_is_not_allowed_in_files_which_will_build_into_CommonJS_output); + error( + node, + Diagnostics + .The_import_meta_meta_property_is_not_allowed_in_files_which_will_build_into_CommonJS_output, + ); } } else if (moduleKind < ModuleKind.ES2020 && moduleKind !== ModuleKind.System) { - error(node, Diagnostics.The_import_meta_meta_property_is_only_allowed_when_the_module_option_is_es2020_es2022_esnext_system_node16_or_nodenext); + error( + node, + Diagnostics + .The_import_meta_meta_property_is_only_allowed_when_the_module_option_is_es2020_es2022_esnext_system_node16_or_nodenext, + ); } const file = getSourceFileOfNode(node); - Debug.assert(!!(file.flags & NodeFlags.PossiblyContainsImportMeta), "Containing file is missing import meta node flag."); + Debug.assert( + !!(file.flags & NodeFlags.PossiblyContainsImportMeta), + "Containing file is missing import meta node flag.", + ); return node.name.escapedText === "meta" ? getGlobalImportMetaType() : errorType; } @@ -35275,8 +45285,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function getTupleElementLabel(d: ParameterDeclaration | NamedTupleMember): __String; - function getTupleElementLabel(d: ParameterDeclaration | NamedTupleMember | undefined, index: number, restParameterName?: __String): __String; - function getTupleElementLabel(d: ParameterDeclaration | NamedTupleMember | undefined, index?: number, restParameterName = "arg" as __String) { + function getTupleElementLabel( + d: ParameterDeclaration | NamedTupleMember | undefined, + index: number, + restParameterName?: __String, + ): __String; + function getTupleElementLabel( + d: ParameterDeclaration | NamedTupleMember | undefined, + index?: number, + restParameterName = "arg" as __String, + ) { if (!d) { return `${restParameterName}_${index}` as __String; } @@ -35299,7 +45317,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return restParameter.escapedName; } - function getParameterIdentifierInfoAtPosition(signature: Signature, pos: number): { parameter: Identifier; parameterName: __String; isRestParameter: boolean; } | undefined { + function getParameterIdentifierInfoAtPosition( + signature: Signature, + pos: number, + ): { parameter: Identifier; parameterName: __String; isRestParameter: boolean; } | undefined { if (signature.declaration?.kind === SyntaxKind.JSDocFunctionType) { return undefined; } @@ -35329,7 +45350,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (associatedName) { Debug.assert(isIdentifier(associatedName.name)); - return { parameter: associatedName.name, parameterName: associatedName.name.escapedText, isRestParameter: isRestTupleElement }; + return { + parameter: associatedName.name, + parameterName: associatedName.name.escapedText, + isRestParameter: isRestTupleElement, + }; } return undefined; @@ -35342,9 +45367,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function getParameterDeclarationIdentifier(symbol: Symbol) { - return symbol.valueDeclaration && isParameter(symbol.valueDeclaration) && isIdentifier(symbol.valueDeclaration.name) && symbol.valueDeclaration.name; + return symbol.valueDeclaration && isParameter(symbol.valueDeclaration) + && isIdentifier(symbol.valueDeclaration.name) && symbol.valueDeclaration.name; } - function isValidDeclarationForTupleLabel(d: Declaration): d is NamedTupleMember | (ParameterDeclaration & { name: Identifier; }) { + function isValidDeclarationForTupleLabel( + d: Declaration, + ): d is NamedTupleMember | (ParameterDeclaration & { name: Identifier; }) { return d.kind === SyntaxKind.NamedTupleMember || (isParameter(d) && d.name && isIdentifier(d.name)); } @@ -35361,7 +45389,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const index = pos - paramCount; return associatedNames && associatedNames[index]; } - return restParameter.valueDeclaration && isValidDeclarationForTupleLabel(restParameter.valueDeclaration) ? restParameter.valueDeclaration : undefined; + return restParameter.valueDeclaration && isValidDeclarationForTupleLabel(restParameter.valueDeclaration) + ? restParameter.valueDeclaration : undefined; } function getTypeAtPosition(signature: Signature, pos: number): Type { @@ -35436,7 +45465,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (signatureHasRestParameter(signature)) { const restType = getTypeOfSymbol(signature.parameters[signature.parameters.length - 1]); if (isTupleType(restType)) { - const firstOptionalIndex = findIndex(restType.target.elementFlags, f => !(f & ElementFlags.Required)); + const firstOptionalIndex = findIndex( + restType.target.elementFlags, + f => !(f & ElementFlags.Required), + ); const requiredCount = firstOptionalIndex < 0 ? restType.target.fixedLength : firstOptionalIndex; if (requiredCount > 0) { minArgumentCount = signature.parameters.length - 1 + requiredCount; @@ -35498,14 +45530,22 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return signature.parameters.length > 0 ? getTypeAtPosition(signature, 0) : fallbackType; } - function inferFromAnnotatedParameters(signature: Signature, context: Signature, inferenceContext: InferenceContext) { + function inferFromAnnotatedParameters( + signature: Signature, + context: Signature, + inferenceContext: InferenceContext, + ) { const len = signature.parameters.length - (signatureHasRestParameter(signature) ? 1 : 0); for (let i = 0; i < len; i++) { const declaration = signature.parameters[i].valueDeclaration as ParameterDeclaration; if (declaration.type) { const typeNode = getEffectiveTypeAnnotationNode(declaration); if (typeNode) { - inferTypes(inferenceContext.inferences, getTypeFromTypeNode(typeNode), getTypeAtPosition(context, i)); + inferTypes( + inferenceContext.inferences, + getTypeFromTypeNode(typeNode), + getTypeAtPosition(context, i), + ); } } } @@ -35522,7 +45562,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } if (context.thisParameter) { const parameter = signature.thisParameter; - if (!parameter || parameter.valueDeclaration && !(parameter.valueDeclaration as ParameterDeclaration).type) { + if ( + !parameter || parameter.valueDeclaration && !(parameter.valueDeclaration as ParameterDeclaration).type + ) { if (!parameter) { signature.thisParameter = createSymbolWithType(context.thisParameter, /*type*/ undefined); } @@ -35566,7 +45608,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const links = getSymbolLinks(parameter); if (!links.type) { const declaration = parameter.valueDeclaration as ParameterDeclaration | undefined; - links.type = type || (declaration ? getWidenedTypeForVariableLikeDeclaration(declaration, /*reportErrors*/ true) : getTypeOfSymbol(parameter)); + links.type = type + || (declaration ? getWidenedTypeForVariableLikeDeclaration(declaration, /*reportErrors*/ true) + : getTypeOfSymbol(parameter)); if (declaration && declaration.name.kind !== SyntaxKind.Identifier) { // if inference didn't come up with anything but unknown, fall back to the binding pattern if present. if (links.type === unknownType) { @@ -35576,7 +45620,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } else if (type) { - Debug.assertEqual(links.type, type, "Parameter symbol already has a cached type which differs from newly assigned type"); + Debug.assertEqual( + links.type, + type, + "Parameter symbol already has a cached type which differs from newly assigned type", + ); } } @@ -35601,23 +45649,38 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function createClassMethodDecoratorContextType(thisType: Type, valueType: Type) { - return tryCreateTypeReference(getGlobalClassMethodDecoratorContextType(/*reportErrors*/ true), [thisType, valueType]); + return tryCreateTypeReference(getGlobalClassMethodDecoratorContextType(/*reportErrors*/ true), [ + thisType, + valueType, + ]); } function createClassGetterDecoratorContextType(thisType: Type, valueType: Type) { - return tryCreateTypeReference(getGlobalClassGetterDecoratorContextType(/*reportErrors*/ true), [thisType, valueType]); + return tryCreateTypeReference(getGlobalClassGetterDecoratorContextType(/*reportErrors*/ true), [ + thisType, + valueType, + ]); } function createClassSetterDecoratorContextType(thisType: Type, valueType: Type) { - return tryCreateTypeReference(getGlobalClassSetterDecoratorContextType(/*reportErrors*/ true), [thisType, valueType]); + return tryCreateTypeReference(getGlobalClassSetterDecoratorContextType(/*reportErrors*/ true), [ + thisType, + valueType, + ]); } function createClassAccessorDecoratorContextType(thisType: Type, valueType: Type) { - return tryCreateTypeReference(getGlobalClassAccessorDecoratorContextType(/*reportErrors*/ true), [thisType, valueType]); + return tryCreateTypeReference(getGlobalClassAccessorDecoratorContextType(/*reportErrors*/ true), [ + thisType, + valueType, + ]); } function createClassFieldDecoratorContextType(thisType: Type, valueType: Type) { - return tryCreateTypeReference(getGlobalClassFieldDecoratorContextType(/*reportErrors*/ true), [thisType, valueType]); + return tryCreateTypeReference(getGlobalClassFieldDecoratorContextType(/*reportErrors*/ true), [ + thisType, + valueType, + ]); } /** @@ -35638,32 +45701,50 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return overrideType; } - function createClassMemberDecoratorContextTypeForNode(node: MethodDeclaration | AccessorDeclaration | PropertyDeclaration, thisType: Type, valueType: Type) { + function createClassMemberDecoratorContextTypeForNode( + node: MethodDeclaration | AccessorDeclaration | PropertyDeclaration, + thisType: Type, + valueType: Type, + ) { const isStatic = hasStaticModifier(node); const isPrivate = isPrivateIdentifier(node.name); - const nameType = isPrivate ? getStringLiteralType(idText(node.name)) : getLiteralTypeFromPropertyName(node.name); - const contextType = isMethodDeclaration(node) ? createClassMethodDecoratorContextType(thisType, valueType) : - isGetAccessorDeclaration(node) ? createClassGetterDecoratorContextType(thisType, valueType) : - isSetAccessorDeclaration(node) ? createClassSetterDecoratorContextType(thisType, valueType) : - isAutoAccessorPropertyDeclaration(node) ? createClassAccessorDecoratorContextType(thisType, valueType) : - isPropertyDeclaration(node) ? createClassFieldDecoratorContextType(thisType, valueType) : - Debug.failBadSyntaxKind(node); + const nameType = isPrivate ? getStringLiteralType(idText(node.name)) + : getLiteralTypeFromPropertyName(node.name); + const contextType = isMethodDeclaration(node) ? createClassMethodDecoratorContextType(thisType, valueType) + : isGetAccessorDeclaration(node) ? createClassGetterDecoratorContextType(thisType, valueType) + : isSetAccessorDeclaration(node) ? createClassSetterDecoratorContextType(thisType, valueType) + : isAutoAccessorPropertyDeclaration(node) ? createClassAccessorDecoratorContextType(thisType, valueType) + : isPropertyDeclaration(node) ? createClassFieldDecoratorContextType(thisType, valueType) + : Debug.failBadSyntaxKind(node); const overrideType = getClassMemberDecoratorContextOverrideType(nameType, isPrivate, isStatic); return getIntersectionType([contextType, overrideType]); } function createClassAccessorDecoratorTargetType(thisType: Type, valueType: Type) { - return tryCreateTypeReference(getGlobalClassAccessorDecoratorTargetType(/*reportErrors*/ true), [thisType, valueType]); + return tryCreateTypeReference(getGlobalClassAccessorDecoratorTargetType(/*reportErrors*/ true), [ + thisType, + valueType, + ]); } function createClassAccessorDecoratorResultType(thisType: Type, valueType: Type) { - return tryCreateTypeReference(getGlobalClassAccessorDecoratorResultType(/*reportErrors*/ true), [thisType, valueType]); + return tryCreateTypeReference(getGlobalClassAccessorDecoratorResultType(/*reportErrors*/ true), [ + thisType, + valueType, + ]); } function createClassFieldDecoratorInitializerMutatorType(thisType: Type, valueType: Type) { const thisParam = createParameter("this" as __String, thisType); const valueParam = createParameter("value" as __String, valueType); - return createFunctionType(/*typeParameters*/ undefined, thisParam, [valueParam], valueType, /*typePredicate*/ undefined, 1); + return createFunctionType( + /*typeParameters*/ undefined, + thisParam, + [valueParam], + valueType, + /*typePredicate*/ undefined, + 1, + ); } /** @@ -35674,7 +45755,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const targetParam = createParameter("target" as __String, targetType); const contextParam = createParameter("context" as __String, contextType); const returnType = getUnionType([nonOptionalReturnType, voidType]); - return createCallSignature(/*typeParameters*/ undefined, /*thisParameter*/ undefined, [targetParam, contextParam], returnType); + return createCallSignature(/*typeParameters*/ undefined, /*thisParameter*/ undefined, [ + targetParam, + contextParam, + ], returnType); } /** @@ -35800,26 +45884,27 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // In all three cases, the `This` type argument is the "final type" of either the class or // instance, depending on whether the member was `static`. - const valueType = isMethodDeclaration(node) ? getOrCreateTypeFromSignature(getSignatureFromDeclaration(node)) : - getTypeOfNode(node); + const valueType = isMethodDeclaration(node) + ? getOrCreateTypeFromSignature(getSignatureFromDeclaration(node)) + : getTypeOfNode(node); - const thisType = hasStaticModifier(node) ? - getTypeOfSymbol(getSymbolOfDeclaration(node.parent)) : - getDeclaredTypeOfClassOrInterface(getSymbolOfDeclaration(node.parent)); + const thisType = hasStaticModifier(node) + ? getTypeOfSymbol(getSymbolOfDeclaration(node.parent)) + : getDeclaredTypeOfClassOrInterface(getSymbolOfDeclaration(node.parent)); // We wrap the "input type", if necessary, to match the decoration target. For getters this is // something like `() => inputType`, for setters it's `(value: inputType) => void` and for // methods it is just the input type. - const targetType = isGetAccessorDeclaration(node) ? createGetterFunctionType(valueType) : - isSetAccessorDeclaration(node) ? createSetterFunctionType(valueType) : - valueType; + const targetType = isGetAccessorDeclaration(node) ? createGetterFunctionType(valueType) + : isSetAccessorDeclaration(node) ? createSetterFunctionType(valueType) + : valueType; const contextType = createClassMemberDecoratorContextTypeForNode(node, thisType, valueType); // We also wrap the "output type", as needed. - const returnType = isGetAccessorDeclaration(node) ? createGetterFunctionType(valueType) : - isSetAccessorDeclaration(node) ? createSetterFunctionType(valueType) : - valueType; + const returnType = isGetAccessorDeclaration(node) ? createGetterFunctionType(valueType) + : isSetAccessorDeclaration(node) ? createSetterFunctionType(valueType) + : valueType; links.decoratorSignature = createESDecoratorCallSignature(targetType, contextType, returnType); break; @@ -35836,15 +45921,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // the "final type" of the value stored in the field. const valueType = getTypeOfNode(node); - const thisType = hasStaticModifier(node) ? - getTypeOfSymbol(getSymbolOfDeclaration(node.parent)) : - getDeclaredTypeOfClassOrInterface(getSymbolOfDeclaration(node.parent)); + const thisType = hasStaticModifier(node) + ? getTypeOfSymbol(getSymbolOfDeclaration(node.parent)) + : getDeclaredTypeOfClassOrInterface(getSymbolOfDeclaration(node.parent)); // The `target` of an auto-accessor decorator is a `{ get, set }` object, representing the // runtime-generated getter and setter that are added to the class/prototype. The `target` of a // regular field decorator is always `undefined` as it isn't installed until it is initialized. - const targetType = hasAccessorModifier(node) ? createClassAccessorDecoratorTargetType(thisType, valueType) : - undefinedType; + const targetType = hasAccessorModifier(node) + ? createClassAccessorDecoratorTargetType(thisType, valueType) + : undefinedType; const contextType = createClassMemberDecoratorContextTypeForNode(node, thisType, valueType); @@ -35852,8 +45938,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // "output type" in a `ClassAccessorDecoratorResult` type, which allows for // mutation of the runtime-generated getter and setter, as well as the injection of an // initializer mutator. For regular fields, we wrap the "output type" in an initializer mutator. - const returnType = hasAccessorModifier(node) ? createClassAccessorDecoratorResultType(thisType, valueType) : - createClassFieldDecoratorInitializerMutatorType(thisType, valueType); + const returnType = hasAccessorModifier(node) + ? createClassAccessorDecoratorResultType(thisType, valueType) + : createClassFieldDecoratorInitializerMutatorType(thisType, valueType); links.decoratorSignature = createESDecoratorCallSignature(targetType, contextType, returnType); break; @@ -35887,8 +45974,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { case SyntaxKind.Parameter: { const node = parent as ParameterDeclaration; if ( - !isConstructorDeclaration(node.parent) && - !(isMethodDeclaration(node.parent) || isSetAccessorDeclaration(node.parent) && isClassLike(node.parent.parent)) + !isConstructorDeclaration(node.parent) + && !(isMethodDeclaration(node.parent) + || isSetAccessorDeclaration(node.parent) && isClassLike(node.parent.parent)) ) { break; } @@ -35897,19 +45985,20 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { break; } - const index = getThisParameter(node.parent) ? - node.parent.parameters.indexOf(node) - 1 : - node.parent.parameters.indexOf(node); + const index = getThisParameter(node.parent) + ? node.parent.parameters.indexOf(node) - 1 + : node.parent.parameters.indexOf(node); Debug.assert(index >= 0); // A parameter declaration decorator will have three arguments (see `ParameterDecorator` in // core.d.ts). - const targetType = isConstructorDeclaration(node.parent) ? getTypeOfSymbol(getSymbolOfDeclaration(node.parent.parent)) : - getParentTypeOfClassElement(node.parent); + const targetType = isConstructorDeclaration(node.parent) + ? getTypeOfSymbol(getSymbolOfDeclaration(node.parent.parent)) + : getParentTypeOfClassElement(node.parent); - const keyType = isConstructorDeclaration(node.parent) ? undefinedType : - getClassElementPropertyKeyType(node.parent); + const keyType = isConstructorDeclaration(node.parent) ? undefinedType + : getClassElementPropertyKeyType(node.parent); const indexType = getNumberLiteralType(index); @@ -35941,10 +46030,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const keyType = getClassElementPropertyKeyType(node); const keyParam = createParameter("propertyKey" as __String, keyType); - const returnType = isPropertyDeclaration(node) ? voidType : - createTypedPropertyDescriptorType(getTypeOfNode(node)); + const returnType = isPropertyDeclaration(node) ? voidType + : createTypedPropertyDescriptorType(getTypeOfNode(node)); - const hasPropDesc = languageVersion !== ScriptTarget.ES3 && (!isPropertyDeclaration(parent) || hasAccessorModifier(parent)); + const hasPropDesc = languageVersion !== ScriptTarget.ES3 + && (!isPropertyDeclaration(parent) || hasAccessorModifier(parent)); if (hasPropDesc) { const descriptorType = createTypedPropertyDescriptorType(getTypeOfNode(node)); const descriptorParam = createParameter("descriptor" as __String, descriptorType); @@ -35971,8 +46061,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function getDecoratorCallSignature(decorator: Decorator) { - return legacyDecorators ? getLegacyDecoratorCallSignature(decorator) : - getESDecoratorCallSignature(decorator); + return legacyDecorators ? getLegacyDecoratorCallSignature(decorator) + : getESDecoratorCallSignature(decorator); } function createPromiseType(promisedType: Type): Type { @@ -36006,18 +46096,22 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (promiseType === unknownType) { error( func, - isImportCall(func) ? - Diagnostics.A_dynamic_import_call_returns_a_Promise_Make_sure_you_have_a_declaration_for_Promise_or_include_ES2015_in_your_lib_option : - Diagnostics.An_async_function_or_method_must_return_a_Promise_Make_sure_you_have_a_declaration_for_Promise_or_include_ES2015_in_your_lib_option, + isImportCall(func) + ? Diagnostics + .A_dynamic_import_call_returns_a_Promise_Make_sure_you_have_a_declaration_for_Promise_or_include_ES2015_in_your_lib_option + : Diagnostics + .An_async_function_or_method_must_return_a_Promise_Make_sure_you_have_a_declaration_for_Promise_or_include_ES2015_in_your_lib_option, ); return errorType; } else if (!getGlobalPromiseConstructorSymbol(/*reportErrors*/ true)) { error( func, - isImportCall(func) ? - Diagnostics.A_dynamic_import_call_in_ES5_SlashES3_requires_the_Promise_constructor_Make_sure_you_have_a_declaration_for_the_Promise_constructor_or_include_ES2015_in_your_lib_option : - Diagnostics.An_async_function_or_method_in_ES5_SlashES3_requires_the_Promise_constructor_Make_sure_you_have_a_declaration_for_the_Promise_constructor_or_include_ES2015_in_your_lib_option, + isImportCall(func) + ? Diagnostics + .A_dynamic_import_call_in_ES5_SlashES3_requires_the_Promise_constructor_Make_sure_you_have_a_declaration_for_the_Promise_constructor_or_include_ES2015_in_your_lib_option + : Diagnostics + .An_async_function_or_method_in_ES5_SlashES3_requires_the_Promise_constructor_Make_sure_you_have_a_declaration_for_the_Promise_constructor_or_include_ES2015_in_your_lib_option, ); } @@ -36057,7 +46151,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // Promise/A+ compatible implementation will always assimilate any foreign promise, so the // return type of the body should be unwrapped to its awaited type, which we will wrap in // the native Promise type later in this function. - returnType = unwrapAwaitedType(checkAwaitedType(returnType, /*withAlias*/ false, /*errorNode*/ func, Diagnostics.The_return_type_of_an_async_function_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member)); + returnType = unwrapAwaitedType( + checkAwaitedType( + returnType, + /*withAlias*/ false, + /*errorNode*/ func, + Diagnostics + .The_return_type_of_an_async_function_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member, + ), + ); } } else if (isGenerator) { // Generator or AsyncGenerator function @@ -36083,9 +46185,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (types.length === 0) { // For an async function, the return type will not be void/undefined, but rather a Promise for void/undefined. const contextualReturnType = getContextualReturnType(func, /*contextFlags*/ undefined); - const returnType = contextualReturnType && (unwrapReturnType(contextualReturnType, functionFlags) || voidType).flags & TypeFlags.Undefined ? undefinedType : voidType; - return functionFlags & FunctionFlags.Async ? createPromiseReturnType(func, returnType) : // Async function - returnType; // Normal function + const returnType = contextualReturnType + && (unwrapReturnType(contextualReturnType, functionFlags) || voidType).flags + & TypeFlags.Undefined ? undefinedType : voidType; + return functionFlags & FunctionFlags.Async ? createPromiseReturnType(func, returnType) // Async function + : returnType; // Normal function } // Return a union of the return expression types. @@ -36097,21 +46201,44 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (returnType) reportErrorsFromWidening(func, returnType, WideningKind.FunctionReturn); if (nextType) reportErrorsFromWidening(func, nextType, WideningKind.GeneratorNext); if ( - returnType && isUnitType(returnType) || - yieldType && isUnitType(yieldType) || - nextType && isUnitType(nextType) + returnType && isUnitType(returnType) + || yieldType && isUnitType(yieldType) + || nextType && isUnitType(nextType) ) { const contextualSignature = getContextualSignatureForFunctionLikeDeclaration(func); - const contextualType = !contextualSignature ? undefined : - contextualSignature === getSignatureFromDeclaration(func) ? isGenerator ? undefined : returnType : - instantiateContextualType(getReturnTypeOfSignature(contextualSignature), func, /*contextFlags*/ undefined); + const contextualType = !contextualSignature ? undefined + : contextualSignature === getSignatureFromDeclaration(func) ? isGenerator ? undefined : returnType + : instantiateContextualType( + getReturnTypeOfSignature(contextualSignature), + func, + /*contextFlags*/ undefined, + ); if (isGenerator) { - yieldType = getWidenedLiteralLikeTypeForContextualIterationTypeIfNeeded(yieldType, contextualType, IterationTypeKind.Yield, isAsync); - returnType = getWidenedLiteralLikeTypeForContextualIterationTypeIfNeeded(returnType, contextualType, IterationTypeKind.Return, isAsync); - nextType = getWidenedLiteralLikeTypeForContextualIterationTypeIfNeeded(nextType, contextualType, IterationTypeKind.Next, isAsync); + yieldType = getWidenedLiteralLikeTypeForContextualIterationTypeIfNeeded( + yieldType, + contextualType, + IterationTypeKind.Yield, + isAsync, + ); + returnType = getWidenedLiteralLikeTypeForContextualIterationTypeIfNeeded( + returnType, + contextualType, + IterationTypeKind.Return, + isAsync, + ); + nextType = getWidenedLiteralLikeTypeForContextualIterationTypeIfNeeded( + nextType, + contextualType, + IterationTypeKind.Next, + isAsync, + ); } else { - returnType = getWidenedLiteralLikeTypeForContextualReturnTypeIfNeeded(returnType, contextualType, isAsync); + returnType = getWidenedLiteralLikeTypeForContextualReturnTypeIfNeeded( + returnType, + contextualType, + isAsync, + ); } } @@ -36149,12 +46276,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // type of IterableIterator, and the expected next iteration type of IterableIterator is assignable to // nextType. const globalType = resolver.getGlobalIterableIteratorType(/*reportErrors*/ false); - const iterationTypes = globalType !== emptyGenericType ? getIterationTypesOfGlobalIterableType(globalType, resolver) : undefined; + const iterationTypes = globalType !== emptyGenericType + ? getIterationTypesOfGlobalIterableType(globalType, resolver) : undefined; const iterableIteratorReturnType = iterationTypes ? iterationTypes.returnType : anyType; const iterableIteratorNextType = iterationTypes ? iterationTypes.nextType : undefinedType; if ( - isTypeAssignableTo(returnType, iterableIteratorReturnType) && - isTypeAssignableTo(iterableIteratorNextType, nextType) + isTypeAssignableTo(returnType, iterableIteratorReturnType) + && isTypeAssignableTo(iterableIteratorNextType, nextType) ) { if (globalType !== emptyGenericType) { return createTypeFromGenericGlobalType(globalType, [yieldType]); @@ -36178,8 +46306,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const nextTypes: Type[] = []; const isAsync = (getFunctionFlags(func) & FunctionFlags.Async) !== 0; forEachYieldExpression(func.body as Block, yieldExpression => { - const yieldExpressionType = yieldExpression.expression ? checkExpression(yieldExpression.expression, checkMode) : undefinedWideningType; - pushIfUnique(yieldTypes, getYieldedTypeOfYieldExpression(yieldExpression, yieldExpressionType, anyType, isAsync)); + const yieldExpressionType = yieldExpression.expression + ? checkExpression(yieldExpression.expression, checkMode) : undefinedWideningType; + pushIfUnique( + yieldTypes, + getYieldedTypeOfYieldExpression(yieldExpression, yieldExpressionType, anyType, isAsync), + ); let nextType: Type | undefined; if (yieldExpression.asteriskToken) { const iterationTypes = getIterationTypesOfIterable( @@ -36197,21 +46329,38 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return { yieldTypes, nextTypes }; } - function getYieldedTypeOfYieldExpression(node: YieldExpression, expressionType: Type, sentType: Type, isAsync: boolean): Type | undefined { + function getYieldedTypeOfYieldExpression( + node: YieldExpression, + expressionType: Type, + sentType: Type, + isAsync: boolean, + ): Type | undefined { const errorNode = node.expression || node; // A `yield*` expression effectively yields everything that its operand yields - const yieldedType = node.asteriskToken ? checkIteratedTypeOrElementType(isAsync ? IterationUse.AsyncYieldStar : IterationUse.YieldStar, expressionType, sentType, errorNode) : expressionType; + const yieldedType = node.asteriskToken + ? checkIteratedTypeOrElementType( + isAsync ? IterationUse.AsyncYieldStar : IterationUse.YieldStar, + expressionType, + sentType, + errorNode, + ) : expressionType; return !isAsync ? yieldedType : getAwaitedType( yieldedType, errorNode, node.asteriskToken - ? Diagnostics.Type_of_iterated_elements_of_a_yield_Asterisk_operand_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member - : Diagnostics.Type_of_yield_operand_in_an_async_generator_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member, + ? Diagnostics + .Type_of_iterated_elements_of_a_yield_Asterisk_operand_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member + : Diagnostics + .Type_of_yield_operand_in_an_async_generator_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member, ); } // Return the combined not-equal type facts for all cases except those between the start and end indices. - function getNotEqualFactsFromTypeofSwitch(start: number, end: number, witnesses: (string | undefined)[]): TypeFacts { + function getNotEqualFactsFromTypeofSwitch( + start: number, + end: number, + witnesses: (string | undefined)[], + ): TypeFacts { let facts: TypeFacts = TypeFacts.None; for (let i = 0; i < witnesses.length; i++) { const witness = i < start || i >= end ? witnesses[i] : undefined; @@ -36241,7 +46390,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (!witnesses) { return false; } - const operandConstraint = getBaseConstraintOrType(checkExpressionCached((node.expression as TypeOfExpression).expression)); + const operandConstraint = getBaseConstraintOrType( + checkExpressionCached((node.expression as TypeOfExpression).expression), + ); // Get the not-equal flags for all handled cases. const notEqualFacts = getNotEqualFactsFromTypeofSwitch(0, 0, witnesses); if (operandConstraint.flags & TypeFlags.AnyOrUnknown) { @@ -36267,7 +46418,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } /** NOTE: Return value of `[]` means a different thing than `undefined`. `[]` means func returns `void`, `undefined` means it returns `never`. */ - function checkAndAggregateReturnExpressionTypes(func: FunctionLikeDeclaration, checkMode: CheckMode | undefined): Type[] | undefined { + function checkAndAggregateReturnExpressionTypes( + func: FunctionLikeDeclaration, + checkMode: CheckMode | undefined, + ): Type[] | undefined { const functionFlags = getFunctionFlags(func); const aggregatedTypes: Type[] = []; let hasReturnWithNoExpression = functionHasImplicitReturn(func); @@ -36277,9 +46431,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (expr) { // Bare calls to this same function don't contribute to inference if ( - expr.kind === SyntaxKind.CallExpression && - (expr as CallExpression).expression.kind === SyntaxKind.Identifier && - checkExpressionCached((expr as CallExpression).expression).symbol === func.symbol + expr.kind === SyntaxKind.CallExpression + && (expr as CallExpression).expression.kind === SyntaxKind.Identifier + && checkExpressionCached((expr as CallExpression).expression).symbol === func.symbol ) { hasReturnOfTypeNever = true; return; @@ -36291,7 +46445,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // Promise/A+ compatible implementation will always assimilate any foreign promise, so the // return type of the body should be unwrapped to its awaited type, which should be wrapped in // the native Promise type by the caller. - type = unwrapAwaitedType(checkAwaitedType(type, /*withAlias*/ false, func, Diagnostics.The_return_type_of_an_async_function_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member)); + type = unwrapAwaitedType( + checkAwaitedType( + type, + /*withAlias*/ false, + func, + Diagnostics + .The_return_type_of_an_async_function_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member, + ), + ); } if (type.flags & TypeFlags.Never) { hasReturnOfTypeNever = true; @@ -36302,12 +46464,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { hasReturnWithNoExpression = true; } }); - if (aggregatedTypes.length === 0 && !hasReturnWithNoExpression && (hasReturnOfTypeNever || mayReturnNever(func))) { + if ( + aggregatedTypes.length === 0 && !hasReturnWithNoExpression && (hasReturnOfTypeNever || mayReturnNever(func)) + ) { return undefined; } if ( - strictNullChecks && aggregatedTypes.length && hasReturnWithNoExpression && - !(isJSConstructor(func) && aggregatedTypes.some(t => t.symbol === func.symbol)) + strictNullChecks && aggregatedTypes.length && hasReturnWithNoExpression + && !(isJSConstructor(func) && aggregatedTypes.some(t => t.symbol === func.symbol)) ) { // Javascript "callable constructors", containing eg `if (!(this instanceof A)) return new A()` should not add undefined pushIfUnique(aggregatedTypes, undefinedType); @@ -36335,7 +46499,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { * * @param returnType - return type of the function, can be undefined if return type is not explicitly specified */ - function checkAllCodePathsInNonVoidFunctionReturnOrThrow(func: FunctionLikeDeclaration | MethodSignature, returnType: Type | undefined) { + function checkAllCodePathsInNonVoidFunctionReturnOrThrow( + func: FunctionLikeDeclaration | MethodSignature, + returnType: Type | undefined, + ) { addLazyDiagnostic(checkAllCodePathsInNonVoidFunctionReturnOrThrowDiagnostics); return; @@ -36351,7 +46518,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // If all we have is a function signature, or an arrow function with an expression body, then there is nothing to check. // also if HasImplicitReturn flag is not set this means that all codepaths in function body end with return or throw - if (func.kind === SyntaxKind.MethodSignature || nodeIsMissing(func.body) || func.body!.kind !== SyntaxKind.Block || !functionHasImplicitReturn(func)) { + if ( + func.kind === SyntaxKind.MethodSignature || nodeIsMissing(func.body) + || func.body!.kind !== SyntaxKind.Block || !functionHasImplicitReturn(func) + ) { return; } @@ -36364,10 +46534,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { else if (type && !hasExplicitReturn) { // minimal check: function has syntactic return type annotation and no explicit return statements in the body // this function does not conform to the specification. - error(errorNode, Diagnostics.A_function_whose_declared_type_is_neither_undefined_void_nor_any_must_return_a_value); + error( + errorNode, + Diagnostics.A_function_whose_declared_type_is_neither_undefined_void_nor_any_must_return_a_value, + ); } else if (type && strictNullChecks && !isTypeAssignableTo(undefinedType, type)) { - error(errorNode, Diagnostics.Function_lacks_ending_return_statement_and_return_type_does_not_include_undefined); + error( + errorNode, + Diagnostics.Function_lacks_ending_return_statement_and_return_type_does_not_include_undefined, + ); } else if (compilerOptions.noImplicitReturns) { if (!type) { @@ -36387,7 +46563,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } - function checkFunctionExpressionOrObjectLiteralMethod(node: FunctionExpression | ArrowFunction | MethodDeclaration, checkMode?: CheckMode): Type { + function checkFunctionExpressionOrObjectLiteralMethod( + node: FunctionExpression | ArrowFunction | MethodDeclaration, + checkMode?: CheckMode, + ): Type { Debug.assert(node.kind !== SyntaxKind.MethodDeclaration || isObjectLiteralMethod(node)); checkNodeDeferred(node); @@ -36407,8 +46586,23 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return links.contextFreeType; } const returnType = getReturnTypeFromBody(node, checkMode); - const returnOnlySignature = createSignature(/*declaration*/ undefined, /*typeParameters*/ undefined, /*thisParameter*/ undefined, emptyArray, returnType, /*resolvedTypePredicate*/ undefined, 0, SignatureFlags.IsNonInferrable); - const returnOnlyType = createAnonymousType(node.symbol, emptySymbols, [returnOnlySignature], emptyArray, emptyArray); + const returnOnlySignature = createSignature( + /*declaration*/ undefined, + /*typeParameters*/ undefined, + /*thisParameter*/ undefined, + emptyArray, + returnType, + /*resolvedTypePredicate*/ undefined, + 0, + SignatureFlags.IsNonInferrable, + ); + const returnOnlyType = createAnonymousType( + node.symbol, + emptySymbols, + [returnOnlySignature], + emptyArray, + emptyArray, + ); returnOnlyType.objectFlags |= ObjectFlags.NonInferrableType; return links.contextFreeType = returnOnlyType; } @@ -36427,7 +46621,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return getTypeOfSymbol(getSymbolOfDeclaration(node)); } - function contextuallyCheckFunctionExpressionOrObjectLiteralMethod(node: FunctionExpression | ArrowFunction | MethodDeclaration, checkMode?: CheckMode) { + function contextuallyCheckFunctionExpressionOrObjectLiteralMethod( + node: FunctionExpression | ArrowFunction | MethodDeclaration, + checkMode?: CheckMode, + ) { const links = getNodeLinks(node); // Check if function expression is contextually typed and assign parameter types if so. if (!(links.flags & NodeCheckFlags.ContextChecked)) { @@ -36437,7 +46634,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // already assigned contextual types. if (!(links.flags & NodeCheckFlags.ContextChecked)) { links.flags |= NodeCheckFlags.ContextChecked; - const signature = firstOrUndefined(getSignaturesOfType(getTypeOfSymbol(getSymbolOfDeclaration(node)), SignatureKind.Call)); + const signature = firstOrUndefined( + getSignaturesOfType(getTypeOfSymbol(getSymbolOfDeclaration(node)), SignatureKind.Call), + ); if (!signature) { return; } @@ -36449,11 +46648,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { inferFromAnnotatedParameters(signature, contextualSignature, inferenceContext!); const restType = getEffectiveRestType(contextualSignature); if (restType && restType.flags & TypeFlags.TypeParameter) { - instantiatedContextualSignature = instantiateSignature(contextualSignature, inferenceContext!.nonFixingMapper); + instantiatedContextualSignature = instantiateSignature( + contextualSignature, + inferenceContext!.nonFixingMapper, + ); } } - instantiatedContextualSignature ||= inferenceContext ? - instantiateSignature(contextualSignature, inferenceContext.mapper) : contextualSignature; + instantiatedContextualSignature ||= inferenceContext + ? instantiateSignature(contextualSignature, inferenceContext.mapper) : contextualSignature; assignContextualParameterTypes(signature, instantiatedContextualSignature); } else { @@ -36461,7 +46663,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { assignNonContextualParameterTypes(signature); } } - else if (contextualSignature && !node.typeParameters && contextualSignature.parameters.length > node.parameters.length) { + else if ( + contextualSignature && !node.typeParameters + && contextualSignature.parameters.length > node.parameters.length + ) { const inferenceContext = getInferenceContext(node); if (checkMode && checkMode & CheckMode.Inferential) { inferFromAnnotatedParameters(signature, contextualSignature, inferenceContext!); @@ -36478,7 +46683,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } - function checkFunctionExpressionOrObjectLiteralMethodDeferred(node: ArrowFunction | FunctionExpression | MethodDeclaration) { + function checkFunctionExpressionOrObjectLiteralMethodDeferred( + node: ArrowFunction | FunctionExpression | MethodDeclaration, + ) { Debug.assert(node.kind !== SyntaxKind.MethodDeclaration || isObjectLiteralMethod(node)); const functionFlags = getFunctionFlags(node); @@ -36508,18 +46715,39 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const returnOrPromisedType = returnType && unwrapReturnType(returnType, functionFlags); if (returnOrPromisedType) { if ((functionFlags & FunctionFlags.AsyncGenerator) === FunctionFlags.Async) { // Async function - const awaitedType = checkAwaitedType(exprType, /*withAlias*/ false, node.body, Diagnostics.The_return_type_of_an_async_function_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member); - checkTypeAssignableToAndOptionallyElaborate(awaitedType, returnOrPromisedType, node.body, node.body); + const awaitedType = checkAwaitedType( + exprType, + /*withAlias*/ false, + node.body, + Diagnostics + .The_return_type_of_an_async_function_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member, + ); + checkTypeAssignableToAndOptionallyElaborate( + awaitedType, + returnOrPromisedType, + node.body, + node.body, + ); } else { // Normal function - checkTypeAssignableToAndOptionallyElaborate(exprType, returnOrPromisedType, node.body, node.body); + checkTypeAssignableToAndOptionallyElaborate( + exprType, + returnOrPromisedType, + node.body, + node.body, + ); } } } } } - function checkArithmeticOperandType(operand: Node, type: Type, diagnostic: DiagnosticMessage, isAwaitValid = false): boolean { + function checkArithmeticOperandType( + operand: Node, + type: Type, + diagnostic: DiagnosticMessage, + isAwaitValid = false, + ): boolean { if (!isTypeAssignableTo(type, numberOrBigIntType)) { const awaitedType = isAwaitValid && getAwaitedTypeOfPromise(type); errorAndMaybeSuggestAwait( @@ -36571,12 +46799,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // Enum members // Object.defineProperty assignments with writable false or no setter // Unions and intersections of the above (unions and intersections eagerly set isReadonly on creation) - return !!(getCheckFlags(symbol) & CheckFlags.Readonly || - symbol.flags & SymbolFlags.Property && getDeclarationModifierFlagsFromSymbol(symbol) & ModifierFlags.Readonly || - symbol.flags & SymbolFlags.Variable && getDeclarationNodeFlagsFromSymbol(symbol) & NodeFlags.Constant || - symbol.flags & SymbolFlags.Accessor && !(symbol.flags & SymbolFlags.SetAccessor) || - symbol.flags & SymbolFlags.EnumMember || - some(symbol.declarations, isReadonlyAssignmentDeclaration)); + return !!(getCheckFlags(symbol) & CheckFlags.Readonly + || symbol.flags & SymbolFlags.Property + && getDeclarationModifierFlagsFromSymbol(symbol) & ModifierFlags.Readonly + || symbol.flags & SymbolFlags.Variable && getDeclarationNodeFlagsFromSymbol(symbol) & NodeFlags.Constant + || symbol.flags & SymbolFlags.Accessor && !(symbol.flags & SymbolFlags.SetAccessor) + || symbol.flags & SymbolFlags.EnumMember + || some(symbol.declarations, isReadonlyAssignmentDeclaration)); } function isAssignmentToReadonlyEntity(expr: Expression, symbol: Symbol, assignmentKind: AssignmentKind) { @@ -36587,9 +46816,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (isReadonlySymbol(symbol)) { // Allow assignments to readonly properties within constructors of the same class declaration. if ( - symbol.flags & SymbolFlags.Property && - isAccessExpression(expr) && - expr.expression.kind === SyntaxKind.ThisKeyword + symbol.flags & SymbolFlags.Property + && isAccessExpression(expr) + && expr.expression.kind === SyntaxKind.ThisKeyword ) { // Look for if this is the constructor for the class that `symbol` is a property of. const ctor = getContainingFunction(expr); @@ -36600,8 +46829,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const isAssignmentDeclaration = isBinaryExpression(symbol.valueDeclaration); const isLocalPropertyDeclaration = ctor.parent === symbol.valueDeclaration.parent; const isLocalParameterProperty = ctor === symbol.valueDeclaration.parent; - const isLocalThisPropertyAssignment = isAssignmentDeclaration && symbol.parent?.valueDeclaration === ctor.parent; - const isLocalThisPropertyAssignmentConstructorFunction = isAssignmentDeclaration && symbol.parent?.valueDeclaration === ctor; + const isLocalThisPropertyAssignment = isAssignmentDeclaration + && symbol.parent?.valueDeclaration === ctor.parent; + const isLocalThisPropertyAssignmentConstructorFunction = isAssignmentDeclaration + && symbol.parent?.valueDeclaration === ctor; const isWriteableSymbol = isLocalPropertyDeclaration || isLocalParameterProperty || isLocalThisPropertyAssignment @@ -36625,7 +46856,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return false; } - function checkReferenceExpression(expr: Expression, invalidReferenceMessage: DiagnosticMessage, invalidOptionalChainMessage: DiagnosticMessage): boolean { + function checkReferenceExpression( + expr: Expression, + invalidReferenceMessage: DiagnosticMessage, + invalidOptionalChainMessage: DiagnosticMessage, + ): boolean { // References are combinations of identifiers, parentheses, and property accesses. const node = skipOuterExpressions(expr, OuterExpressionKinds.Assertions | OuterExpressionKinds.Parentheses); if (node.kind !== SyntaxKind.Identifier && !isAccessExpression(node)) { @@ -36663,9 +46898,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function checkDeleteExpressionMustBeOptional(expr: AccessExpression, symbol: Symbol) { const type = getTypeOfSymbol(symbol); if ( - strictNullChecks && - !(type.flags & (TypeFlags.AnyOrUnknown | TypeFlags.Never)) && - !(exactOptionalPropertyTypes ? symbol.flags & SymbolFlags.Optional : getTypeFacts(type) & TypeFacts.IsUndefined) + strictNullChecks + && !(type.flags & (TypeFlags.AnyOrUnknown | TypeFlags.Never)) + && !(exactOptionalPropertyTypes ? symbol.flags & SymbolFlags.Optional + : getTypeFacts(type) & TypeFacts.IsUndefined) ) { error(expr, Diagnostics.The_operand_of_a_delete_operator_must_be_optional); } @@ -36687,8 +46923,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const container = getContainingFunctionOrClassStaticBlock(node); if (container && isClassStaticBlockDeclaration(container)) { // NOTE: We report this regardless as to whether there are parse diagnostics. - const message = isAwaitExpression(node) ? Diagnostics.await_expression_cannot_be_used_inside_a_class_static_block : - Diagnostics.await_using_statements_cannot_be_used_inside_a_class_static_block; + const message = isAwaitExpression(node) + ? Diagnostics.await_expression_cannot_be_used_inside_a_class_static_block + : Diagnostics.await_using_statements_cannot_be_used_inside_a_class_static_block; error(node, message); hasError = true; } @@ -36699,8 +46936,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { let span: TextSpan | undefined; if (!isEffectiveExternalModule(sourceFile, compilerOptions)) { span ??= getSpanOfTokenAtPosition(sourceFile, node.pos); - const message = isAwaitExpression(node) ? Diagnostics.await_expressions_are_only_allowed_at_the_top_level_of_a_file_when_that_file_is_a_module_but_this_file_has_no_imports_or_exports_Consider_adding_an_empty_export_to_make_this_file_a_module : - Diagnostics.await_using_statements_are_only_allowed_at_the_top_level_of_a_file_when_that_file_is_a_module_but_this_file_has_no_imports_or_exports_Consider_adding_an_empty_export_to_make_this_file_a_module; + const message = isAwaitExpression(node) + ? Diagnostics + .await_expressions_are_only_allowed_at_the_top_level_of_a_file_when_that_file_is_a_module_but_this_file_has_no_imports_or_exports_Consider_adding_an_empty_export_to_make_this_file_a_module + : Diagnostics + .await_using_statements_are_only_allowed_at_the_top_level_of_a_file_when_that_file_is_a_module_but_this_file_has_no_imports_or_exports_Consider_adding_an_empty_export_to_make_this_file_a_module; const diagnostic = createFileDiagnostic(sourceFile, span.start, span.length, message); diagnostics.add(diagnostic); hasError = true; @@ -36711,7 +46951,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (sourceFile.impliedNodeFormat === ModuleKind.CommonJS) { span ??= getSpanOfTokenAtPosition(sourceFile, node.pos); diagnostics.add( - createFileDiagnostic(sourceFile, span.start, span.length, Diagnostics.The_current_file_is_a_CommonJS_module_and_cannot_use_await_at_the_top_level), + createFileDiagnostic( + sourceFile, + span.start, + span.length, + Diagnostics + .The_current_file_is_a_CommonJS_module_and_cannot_use_await_at_the_top_level, + ), ); hasError = true; break; @@ -36726,8 +46972,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // fallthrough default: span ??= getSpanOfTokenAtPosition(sourceFile, node.pos); - const message = isAwaitExpression(node) ? Diagnostics.Top_level_await_expressions_are_only_allowed_when_the_module_option_is_set_to_es2022_esnext_system_node16_or_nodenext_and_the_target_option_is_set_to_es2017_or_higher : - Diagnostics.Top_level_await_using_statements_are_only_allowed_when_the_module_option_is_set_to_es2022_esnext_system_node16_or_nodenext_and_the_target_option_is_set_to_es2017_or_higher; + const message = isAwaitExpression(node) + ? Diagnostics + .Top_level_await_expressions_are_only_allowed_when_the_module_option_is_set_to_es2022_esnext_system_node16_or_nodenext_and_the_target_option_is_set_to_es2017_or_higher + : Diagnostics + .Top_level_await_using_statements_are_only_allowed_when_the_module_option_is_set_to_es2022_esnext_system_node16_or_nodenext_and_the_target_option_is_set_to_es2017_or_higher; diagnostics.add(createFileDiagnostic(sourceFile, span.start, span.length, message)); hasError = true; break; @@ -36739,11 +46988,20 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const sourceFile = getSourceFileOfNode(node); if (!hasParseDiagnostics(sourceFile)) { const span = getSpanOfTokenAtPosition(sourceFile, node.pos); - const message = isAwaitExpression(node) ? Diagnostics.await_expressions_are_only_allowed_within_async_functions_and_at_the_top_levels_of_modules : - Diagnostics.await_using_statements_are_only_allowed_within_async_functions_and_at_the_top_levels_of_modules; + const message = isAwaitExpression(node) + ? Diagnostics + .await_expressions_are_only_allowed_within_async_functions_and_at_the_top_levels_of_modules + : Diagnostics + .await_using_statements_are_only_allowed_within_async_functions_and_at_the_top_levels_of_modules; const diagnostic = createFileDiagnostic(sourceFile, span.start, span.length, message); - if (container && container.kind !== SyntaxKind.Constructor && (getFunctionFlags(container) & FunctionFlags.Async) === 0) { - const relatedInfo = createDiagnosticForNode(container, Diagnostics.Did_you_mean_to_mark_this_function_as_async); + if ( + container && container.kind !== SyntaxKind.Constructor + && (getFunctionFlags(container) & FunctionFlags.Async) === 0 + ) { + const relatedInfo = createDiagnosticForNode( + container, + Diagnostics.Did_you_mean_to_mark_this_function_as_async, + ); addRelatedInfo(diagnostic, relatedInfo); } diagnostics.add(diagnostic); @@ -36765,9 +47023,17 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { addLazyDiagnostic(() => checkAwaitGrammar(node)); const operandType = checkExpression(node.expression); - const awaitedType = checkAwaitedType(operandType, /*withAlias*/ true, node, Diagnostics.Type_of_await_operand_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member); + const awaitedType = checkAwaitedType( + operandType, + /*withAlias*/ true, + node, + Diagnostics.Type_of_await_operand_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member, + ); if (awaitedType === operandType && !isErrorType(awaitedType) && !(operandType.flags & TypeFlags.AnyOrUnknown)) { - addErrorOrSuggestion(/*isError*/ false, createDiagnosticForNode(node, Diagnostics.await_has_no_effect_on_the_type_of_this_expression)); + addErrorOrSuggestion( + /*isError*/ false, + createDiagnosticForNode(node, Diagnostics.await_has_no_effect_on_the_type_of_this_expression), + ); } return awaitedType; } @@ -36800,11 +47066,20 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { case SyntaxKind.TildeToken: checkNonNullType(operandType, node.operand); if (maybeTypeOfKindConsideringBaseConstraint(operandType, TypeFlags.ESSymbolLike)) { - error(node.operand, Diagnostics.The_0_operator_cannot_be_applied_to_type_symbol, tokenToString(node.operator)); + error( + node.operand, + Diagnostics.The_0_operator_cannot_be_applied_to_type_symbol, + tokenToString(node.operator), + ); } if (node.operator === SyntaxKind.PlusToken) { if (maybeTypeOfKindConsideringBaseConstraint(operandType, TypeFlags.BigIntLike)) { - error(node.operand, Diagnostics.Operator_0_cannot_be_applied_to_type_1, tokenToString(node.operator), typeToString(getBaseTypeOfLiteralType(operandType))); + error( + node.operand, + Diagnostics.Operator_0_cannot_be_applied_to_type_1, + tokenToString(node.operator), + typeToString(getBaseTypeOfLiteralType(operandType)), + ); } return numberType; } @@ -36812,18 +47087,24 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { case SyntaxKind.ExclamationToken: checkTruthinessOfType(operandType, node.operand); const facts = getTypeFacts(operandType) & (TypeFacts.Truthy | TypeFacts.Falsy); - return facts === TypeFacts.Truthy ? falseType : - facts === TypeFacts.Falsy ? trueType : - booleanType; + return facts === TypeFacts.Truthy ? falseType + : facts === TypeFacts.Falsy ? trueType + : booleanType; case SyntaxKind.PlusPlusToken: case SyntaxKind.MinusMinusToken: - const ok = checkArithmeticOperandType(node.operand, checkNonNullType(operandType, node.operand), Diagnostics.An_arithmetic_operand_must_be_of_type_any_number_bigint_or_an_enum_type); + const ok = checkArithmeticOperandType( + node.operand, + checkNonNullType(operandType, node.operand), + Diagnostics.An_arithmetic_operand_must_be_of_type_any_number_bigint_or_an_enum_type, + ); if (ok) { // run check only if former checks succeeded to avoid reporting cascading errors checkReferenceExpression( node.operand, - Diagnostics.The_operand_of_an_increment_or_decrement_operator_must_be_a_variable_or_a_property_access, - Diagnostics.The_operand_of_an_increment_or_decrement_operator_may_not_be_an_optional_property_access, + Diagnostics + .The_operand_of_an_increment_or_decrement_operator_must_be_a_variable_or_a_property_access, + Diagnostics + .The_operand_of_an_increment_or_decrement_operator_may_not_be_an_optional_property_access, ); } return getUnaryResultType(operandType); @@ -36854,7 +47135,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function getUnaryResultType(operandType: Type): Type { if (maybeTypeOfKind(operandType, TypeFlags.BigIntLike)) { - return isTypeAssignableToKind(operandType, TypeFlags.AnyOrUnknown) || maybeTypeOfKind(operandType, TypeFlags.NumberLike) + return isTypeAssignableToKind(operandType, TypeFlags.AnyOrUnknown) + || maybeTypeOfKind(operandType, TypeFlags.NumberLike) ? numberOrBigIntType : bigintType; } @@ -36895,22 +47177,22 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (strict && source.flags & (TypeFlags.AnyOrUnknown | TypeFlags.Void | TypeFlags.Undefined | TypeFlags.Null)) { return false; } - return !!(kind & TypeFlags.NumberLike) && isTypeAssignableTo(source, numberType) || - !!(kind & TypeFlags.BigIntLike) && isTypeAssignableTo(source, bigintType) || - !!(kind & TypeFlags.StringLike) && isTypeAssignableTo(source, stringType) || - !!(kind & TypeFlags.BooleanLike) && isTypeAssignableTo(source, booleanType) || - !!(kind & TypeFlags.Void) && isTypeAssignableTo(source, voidType) || - !!(kind & TypeFlags.Never) && isTypeAssignableTo(source, neverType) || - !!(kind & TypeFlags.Null) && isTypeAssignableTo(source, nullType) || - !!(kind & TypeFlags.Undefined) && isTypeAssignableTo(source, undefinedType) || - !!(kind & TypeFlags.ESSymbol) && isTypeAssignableTo(source, esSymbolType) || - !!(kind & TypeFlags.NonPrimitive) && isTypeAssignableTo(source, nonPrimitiveType); + return !!(kind & TypeFlags.NumberLike) && isTypeAssignableTo(source, numberType) + || !!(kind & TypeFlags.BigIntLike) && isTypeAssignableTo(source, bigintType) + || !!(kind & TypeFlags.StringLike) && isTypeAssignableTo(source, stringType) + || !!(kind & TypeFlags.BooleanLike) && isTypeAssignableTo(source, booleanType) + || !!(kind & TypeFlags.Void) && isTypeAssignableTo(source, voidType) + || !!(kind & TypeFlags.Never) && isTypeAssignableTo(source, neverType) + || !!(kind & TypeFlags.Null) && isTypeAssignableTo(source, nullType) + || !!(kind & TypeFlags.Undefined) && isTypeAssignableTo(source, undefinedType) + || !!(kind & TypeFlags.ESSymbol) && isTypeAssignableTo(source, esSymbolType) + || !!(kind & TypeFlags.NonPrimitive) && isTypeAssignableTo(source, nonPrimitiveType); } function allTypesAssignableToKind(source: Type, kind: TypeFlags, strict?: boolean): boolean { - return source.flags & TypeFlags.Union ? - every((source as UnionType).types, subType => allTypesAssignableToKind(subType, kind, strict)) : - isTypeAssignableToKind(source, kind, strict); + return source.flags & TypeFlags.Union + ? every((source as UnionType).types, subType => allTypesAssignableToKind(subType, kind, strict)) + : isTypeAssignableToKind(source, kind, strict); } function isConstEnumObjectType(type: Type): boolean { @@ -36931,20 +47213,35 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // The result is always of the Boolean primitive type. // NOTE: do not raise error if leftType is unknown as related error was already reported if ( - !isTypeAny(leftType) && - allTypesAssignableToKind(leftType, TypeFlags.Primitive) + !isTypeAny(leftType) + && allTypesAssignableToKind(leftType, TypeFlags.Primitive) ) { - error(left, Diagnostics.The_left_hand_side_of_an_instanceof_expression_must_be_of_type_any_an_object_type_or_a_type_parameter); + error( + left, + Diagnostics + .The_left_hand_side_of_an_instanceof_expression_must_be_of_type_any_an_object_type_or_a_type_parameter, + ); } // NOTE: do not raise error if right is unknown as related error was already reported - if (!(isTypeAny(rightType) || typeHasCallOrConstructSignatures(rightType) || isTypeSubtypeOf(rightType, globalFunctionType))) { - error(right, Diagnostics.The_right_hand_side_of_an_instanceof_expression_must_be_of_type_any_or_of_a_type_assignable_to_the_Function_interface_type); + if ( + !(isTypeAny(rightType) || typeHasCallOrConstructSignatures(rightType) + || isTypeSubtypeOf(rightType, globalFunctionType)) + ) { + error( + right, + Diagnostics + .The_right_hand_side_of_an_instanceof_expression_must_be_of_type_any_or_of_a_type_assignable_to_the_Function_interface_type, + ); } return booleanType; } function hasEmptyObjectIntersection(type: Type): boolean { - return someType(type, t => t === unknownEmptyObjectType || !!(t.flags & TypeFlags.Intersection) && isEmptyAnonymousObjectType(getBaseConstraintOrType(t))); + return someType( + type, + t => t === unknownEmptyObjectType + || !!(t.flags & TypeFlags.Intersection) && isEmptyAnonymousObjectType(getBaseConstraintOrType(t)), + ); } function checkInExpression(left: Expression, right: Expression, leftType: Type, rightType: Type): Type { @@ -36973,14 +47270,23 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // that include {} (we know that the other types in such intersections are assignable to object // since we already checked for that). if (hasEmptyObjectIntersection(rightType)) { - error(right, Diagnostics.Type_0_may_represent_a_primitive_value_which_is_not_permitted_as_the_right_operand_of_the_in_operator, typeToString(rightType)); + error( + right, + Diagnostics + .Type_0_may_represent_a_primitive_value_which_is_not_permitted_as_the_right_operand_of_the_in_operator, + typeToString(rightType), + ); } } // The result is always of the Boolean primitive type. return booleanType; } - function checkObjectLiteralAssignment(node: ObjectLiteralExpression, sourceType: Type, rightIsThis?: boolean): Type { + function checkObjectLiteralAssignment( + node: ObjectLiteralExpression, + sourceType: Type, + rightIsThis?: boolean, + ): Type { const properties = node.properties; if (strictNullChecks && properties.length === 0) { return checkNonNullType(sourceType, node); @@ -36992,10 +47298,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } /** Note: If property cannot be a SpreadAssignment, then allProperties does not need to be provided */ - function checkObjectLiteralDestructuringPropertyAssignment(node: ObjectLiteralExpression, objectLiteralType: Type, propertyIndex: number, allProperties?: NodeArray, rightIsThis = false) { + function checkObjectLiteralDestructuringPropertyAssignment( + node: ObjectLiteralExpression, + objectLiteralType: Type, + propertyIndex: number, + allProperties?: NodeArray, + rightIsThis = false, + ) { const properties = node.properties; const property = properties[propertyIndex]; - if (property.kind === SyntaxKind.PropertyAssignment || property.kind === SyntaxKind.ShorthandPropertyAssignment) { + if ( + property.kind === SyntaxKind.PropertyAssignment || property.kind === SyntaxKind.ShorthandPropertyAssignment + ) { const name = property.name; const exprType = getLiteralTypeFromPropertyName(name); if (isTypeUsableAsPropertyName(exprType)) { @@ -37008,7 +47322,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } const elementType = getIndexedAccessType(objectLiteralType, exprType, AccessFlags.ExpressionPosition, name); const type = getFlowTypeOfDestructuring(property, elementType); - return checkDestructuringAssignment(property.kind === SyntaxKind.ShorthandPropertyAssignment ? property : property.initializer, type); + return checkDestructuringAssignment( + property.kind === SyntaxKind.ShorthandPropertyAssignment ? property : property.initializer, + type, + ); } else if (property.kind === SyntaxKind.SpreadAssignment) { if (propertyIndex < properties.length - 1) { @@ -37027,7 +47344,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } const type = getRestType(objectLiteralType, nonRestNames, objectLiteralType.symbol); - checkGrammarForDisallowedTrailingComma(allProperties, Diagnostics.A_rest_parameter_or_binding_pattern_may_not_have_a_trailing_comma); + checkGrammarForDisallowedTrailingComma( + allProperties, + Diagnostics.A_rest_parameter_or_binding_pattern_may_not_have_a_trailing_comma, + ); return checkDestructuringAssignment(property.expression, type); } } @@ -37044,19 +47364,33 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // This elementType will be used if the specific property corresponding to this index is not // present (aka the tuple element property). This call also checks that the parentType is in // fact an iterable or array (depending on target language). - const possiblyOutOfBoundsType = checkIteratedTypeOrElementType(IterationUse.Destructuring | IterationUse.PossiblyOutOfBounds, sourceType, undefinedType, node) || errorType; - let inBoundsType: Type | undefined = compilerOptions.noUncheckedIndexedAccess ? undefined : possiblyOutOfBoundsType; + const possiblyOutOfBoundsType = checkIteratedTypeOrElementType( + IterationUse.Destructuring | IterationUse.PossiblyOutOfBounds, + sourceType, + undefinedType, + node, + ) || errorType; + let inBoundsType: Type | undefined = compilerOptions.noUncheckedIndexedAccess ? undefined + : possiblyOutOfBoundsType; for (let i = 0; i < elements.length; i++) { let type = possiblyOutOfBoundsType; if (node.elements[i].kind === SyntaxKind.SpreadElement) { - type = inBoundsType = inBoundsType ?? (checkIteratedTypeOrElementType(IterationUse.Destructuring, sourceType, undefinedType, node) || errorType); + type = inBoundsType = inBoundsType + ?? (checkIteratedTypeOrElementType(IterationUse.Destructuring, sourceType, undefinedType, node) + || errorType); } checkArrayLiteralDestructuringElementAssignment(node, sourceType, i, type, checkMode); } return sourceType; } - function checkArrayLiteralDestructuringElementAssignment(node: ArrayLiteralExpression, sourceType: Type, elementIndex: number, elementType: Type, checkMode?: CheckMode) { + function checkArrayLiteralDestructuringElementAssignment( + node: ArrayLiteralExpression, + sourceType: Type, + elementIndex: number, + elementType: Type, + checkMode?: CheckMode, + ) { const elements = node.elements; const element = elements[elementIndex]; if (element.kind !== SyntaxKind.OmittedExpression) { @@ -37065,9 +47399,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (isArrayLikeType(sourceType)) { // We create a synthetic expression so that getIndexedAccessType doesn't get confused // when the element is a SyntaxKind.ElementAccessExpression. - const accessFlags = AccessFlags.ExpressionPosition | (hasDefaultValue(element) ? AccessFlags.NoTupleBoundsCheck : 0); - const elementType = getIndexedAccessTypeOrUndefined(sourceType, indexType, accessFlags, createSyntheticExpression(element, indexType)) || errorType; - const assignedType = hasDefaultValue(element) ? getTypeWithFacts(elementType, TypeFacts.NEUndefined) : elementType; + const accessFlags = AccessFlags.ExpressionPosition + | (hasDefaultValue(element) ? AccessFlags.NoTupleBoundsCheck : 0); + const elementType = getIndexedAccessTypeOrUndefined( + sourceType, + indexType, + accessFlags, + createSyntheticExpression(element, indexType), + ) || errorType; + const assignedType = hasDefaultValue(element) ? getTypeWithFacts(elementType, TypeFacts.NEUndefined) + : elementType; const type = getFlowTypeOfDestructuring(element, assignedType); return checkDestructuringAssignment(element, type, checkMode); } @@ -37078,14 +47419,23 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } else { const restExpression = (element as SpreadElement).expression; - if (restExpression.kind === SyntaxKind.BinaryExpression && (restExpression as BinaryExpression).operatorToken.kind === SyntaxKind.EqualsToken) { - error((restExpression as BinaryExpression).operatorToken, Diagnostics.A_rest_element_cannot_have_an_initializer); + if ( + restExpression.kind === SyntaxKind.BinaryExpression + && (restExpression as BinaryExpression).operatorToken.kind === SyntaxKind.EqualsToken + ) { + error( + (restExpression as BinaryExpression).operatorToken, + Diagnostics.A_rest_element_cannot_have_an_initializer, + ); } else { - checkGrammarForDisallowedTrailingComma(node.elements, Diagnostics.A_rest_parameter_or_binding_pattern_may_not_have_a_trailing_comma); - const type = everyType(sourceType, isTupleType) ? - mapType(sourceType, t => sliceTupleType(t as TupleTypeReference, elementIndex)) : - createArrayType(elementType); + checkGrammarForDisallowedTrailingComma( + node.elements, + Diagnostics.A_rest_parameter_or_binding_pattern_may_not_have_a_trailing_comma, + ); + const type = everyType(sourceType, isTupleType) + ? mapType(sourceType, t => sliceTupleType(t as TupleTypeReference, elementIndex)) + : createArrayType(elementType); return checkDestructuringAssignment(restExpression, type, checkMode); } } @@ -37093,7 +47443,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return undefined; } - function checkDestructuringAssignment(exprOrAssignment: Expression | ShorthandPropertyAssignment, sourceType: Type, checkMode?: CheckMode, rightIsThis?: boolean): Type { + function checkDestructuringAssignment( + exprOrAssignment: Expression | ShorthandPropertyAssignment, + sourceType: Type, + checkMode?: CheckMode, + rightIsThis?: boolean, + ): Type { let target: Expression; if (exprOrAssignment.kind === SyntaxKind.ShorthandPropertyAssignment) { const prop = exprOrAssignment as ShorthandPropertyAssignment; @@ -37101,8 +47456,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // In strict null checking mode, if a default value of a non-undefined type is specified, remove // undefined from the final type. if ( - strictNullChecks && - !(getTypeFacts(checkExpression(prop.objectAssignmentInitializer)) & TypeFacts.IsUndefined) + strictNullChecks + && !(getTypeFacts(checkExpression(prop.objectAssignmentInitializer)) & TypeFacts.IsUndefined) ) { sourceType = getTypeWithFacts(sourceType, TypeFacts.NEUndefined); } @@ -37114,7 +47469,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { target = exprOrAssignment; } - if (target.kind === SyntaxKind.BinaryExpression && (target as BinaryExpression).operatorToken.kind === SyntaxKind.EqualsToken) { + if ( + target.kind === SyntaxKind.BinaryExpression + && (target as BinaryExpression).operatorToken.kind === SyntaxKind.EqualsToken + ) { checkBinaryExpression(target as BinaryExpression, checkMode); target = (target as BinaryExpression).left; // A default value is specified, so remove undefined from the final type. @@ -37133,12 +47491,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function checkReferenceAssignment(target: Expression, sourceType: Type, checkMode?: CheckMode): Type { const targetType = checkExpression(target, checkMode); - const error = target.parent.kind === SyntaxKind.SpreadAssignment ? - Diagnostics.The_target_of_an_object_rest_assignment_must_be_a_variable_or_a_property_access : - Diagnostics.The_left_hand_side_of_an_assignment_expression_must_be_a_variable_or_a_property_access; - const optionalError = target.parent.kind === SyntaxKind.SpreadAssignment ? - Diagnostics.The_target_of_an_object_rest_assignment_may_not_be_an_optional_property_access : - Diagnostics.The_left_hand_side_of_an_assignment_expression_may_not_be_an_optional_property_access; + const error = target.parent.kind === SyntaxKind.SpreadAssignment + ? Diagnostics.The_target_of_an_object_rest_assignment_must_be_a_variable_or_a_property_access + : Diagnostics.The_left_hand_side_of_an_assignment_expression_must_be_a_variable_or_a_property_access; + const optionalError = target.parent.kind === SyntaxKind.SpreadAssignment + ? Diagnostics.The_target_of_an_object_rest_assignment_may_not_be_an_optional_property_access + : Diagnostics.The_left_hand_side_of_an_assignment_expression_may_not_be_an_optional_property_access; if (checkReferenceExpression(target, error, optionalError)) { checkTypeAssignableToAndOptionallyElaborate(sourceType, targetType, target, target); } @@ -37183,15 +47541,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return true; case SyntaxKind.ConditionalExpression: - return isSideEffectFree((node as ConditionalExpression).whenTrue) && - isSideEffectFree((node as ConditionalExpression).whenFalse); + return isSideEffectFree((node as ConditionalExpression).whenTrue) + && isSideEffectFree((node as ConditionalExpression).whenFalse); case SyntaxKind.BinaryExpression: if (isAssignmentOperator((node as BinaryExpression).operatorToken.kind)) { return false; } - return isSideEffectFree((node as BinaryExpression).left) && - isSideEffectFree((node as BinaryExpression).right); + return isSideEffectFree((node as BinaryExpression).left) + && isSideEffectFree((node as BinaryExpression).right); case SyntaxKind.PrefixUnaryExpression: case SyntaxKind.PostfixUnaryExpression: @@ -37265,9 +47623,21 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { checkGrammarNullishCoalesceWithLogicalExpression(node); const operator = node.operatorToken.kind; - if (operator === SyntaxKind.EqualsToken && (node.left.kind === SyntaxKind.ObjectLiteralExpression || node.left.kind === SyntaxKind.ArrayLiteralExpression)) { + if ( + operator === SyntaxKind.EqualsToken + && (node.left.kind === SyntaxKind.ObjectLiteralExpression + || node.left.kind === SyntaxKind.ArrayLiteralExpression) + ) { state.skip = true; - setLastResult(state, checkDestructuringAssignment(node.left, checkExpression(node.right, checkMode), checkMode, node.right.kind === SyntaxKind.ThisKeyword)); + setLastResult( + state, + checkDestructuringAssignment( + node.left, + checkExpression(node.right, checkMode), + checkMode, + node.right.kind === SyntaxKind.ThisKeyword, + ), + ); return state; } @@ -37289,11 +47659,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const operator = operatorToken.kind; if (isLogicalOrCoalescingBinaryOperator(operator)) { let parent = node.parent; - while (parent.kind === SyntaxKind.ParenthesizedExpression || isLogicalOrCoalescingBinaryExpression(parent)) { + while ( + parent.kind === SyntaxKind.ParenthesizedExpression + || isLogicalOrCoalescingBinaryExpression(parent) + ) { parent = parent.parent; } if (operator === SyntaxKind.AmpersandAmpersandToken || isIfStatement(parent)) { - checkTestingKnownTruthyCallableOrAwaitableType(node.left, leftType, isIfStatement(parent) ? parent.thenStatement : undefined); + checkTestingKnownTruthyCallableOrAwaitableType( + node.left, + leftType, + isIfStatement(parent) ? parent.thenStatement : undefined, + ); } checkTruthinessOfType(leftType, node.left); } @@ -37318,7 +47695,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const rightType = getLastResult(state); Debug.assertIsDefined(rightType); - result = checkBinaryLikeExpressionWorker(node.left, node.operatorToken, node.right, leftType, rightType, state.checkMode, node); + result = checkBinaryLikeExpressionWorker( + node.left, + node.operatorToken, + node.right, + leftType, + rightType, + state.checkMode, + node, + ); } state.skip = false; @@ -37364,21 +47749,53 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function checkGrammarNullishCoalesceWithLogicalExpression(node: BinaryExpression) { const { left, operatorToken, right } = node; if (operatorToken.kind === SyntaxKind.QuestionQuestionToken) { - if (isBinaryExpression(left) && (left.operatorToken.kind === SyntaxKind.BarBarToken || left.operatorToken.kind === SyntaxKind.AmpersandAmpersandToken)) { - grammarErrorOnNode(left, Diagnostics._0_and_1_operations_cannot_be_mixed_without_parentheses, tokenToString(left.operatorToken.kind), tokenToString(operatorToken.kind)); + if ( + isBinaryExpression(left) + && (left.operatorToken.kind === SyntaxKind.BarBarToken + || left.operatorToken.kind === SyntaxKind.AmpersandAmpersandToken) + ) { + grammarErrorOnNode( + left, + Diagnostics._0_and_1_operations_cannot_be_mixed_without_parentheses, + tokenToString(left.operatorToken.kind), + tokenToString(operatorToken.kind), + ); } - if (isBinaryExpression(right) && (right.operatorToken.kind === SyntaxKind.BarBarToken || right.operatorToken.kind === SyntaxKind.AmpersandAmpersandToken)) { - grammarErrorOnNode(right, Diagnostics._0_and_1_operations_cannot_be_mixed_without_parentheses, tokenToString(right.operatorToken.kind), tokenToString(operatorToken.kind)); + if ( + isBinaryExpression(right) + && (right.operatorToken.kind === SyntaxKind.BarBarToken + || right.operatorToken.kind === SyntaxKind.AmpersandAmpersandToken) + ) { + grammarErrorOnNode( + right, + Diagnostics._0_and_1_operations_cannot_be_mixed_without_parentheses, + tokenToString(right.operatorToken.kind), + tokenToString(operatorToken.kind), + ); } } } // Note that this and `checkBinaryExpression` above should behave mostly the same, except this elides some // expression-wide checks and does not use a work stack to fold nested binary expressions into the same callstack frame - function checkBinaryLikeExpression(left: Expression, operatorToken: BinaryOperatorToken, right: Expression, checkMode?: CheckMode, errorNode?: Node): Type { + function checkBinaryLikeExpression( + left: Expression, + operatorToken: BinaryOperatorToken, + right: Expression, + checkMode?: CheckMode, + errorNode?: Node, + ): Type { const operator = operatorToken.kind; - if (operator === SyntaxKind.EqualsToken && (left.kind === SyntaxKind.ObjectLiteralExpression || left.kind === SyntaxKind.ArrayLiteralExpression)) { - return checkDestructuringAssignment(left, checkExpression(right, checkMode), checkMode, right.kind === SyntaxKind.ThisKeyword); + if ( + operator === SyntaxKind.EqualsToken + && (left.kind === SyntaxKind.ObjectLiteralExpression || left.kind === SyntaxKind.ArrayLiteralExpression) + ) { + return checkDestructuringAssignment( + left, + checkExpression(right, checkMode), + checkMode, + right.kind === SyntaxKind.ThisKeyword, + ); } let leftType: Type; if (isLogicalOrCoalescingBinaryOperator(operator)) { @@ -37436,23 +47853,42 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // if a user tries to apply a bitwise operator to 2 boolean operands // try and return them a helpful suggestion if ( - (leftType.flags & TypeFlags.BooleanLike) && - (rightType.flags & TypeFlags.BooleanLike) && - (suggestedOperator = getSuggestedBooleanOperator(operatorToken.kind)) !== undefined + (leftType.flags & TypeFlags.BooleanLike) + && (rightType.flags & TypeFlags.BooleanLike) + && (suggestedOperator = getSuggestedBooleanOperator(operatorToken.kind)) !== undefined ) { - error(errorNode || operatorToken, Diagnostics.The_0_operator_is_not_allowed_for_boolean_types_Consider_using_1_instead, tokenToString(operatorToken.kind), tokenToString(suggestedOperator)); + error( + errorNode || operatorToken, + Diagnostics.The_0_operator_is_not_allowed_for_boolean_types_Consider_using_1_instead, + tokenToString(operatorToken.kind), + tokenToString(suggestedOperator), + ); return numberType; } else { // otherwise just check each operand separately and report errors as normal - const leftOk = checkArithmeticOperandType(left, leftType, Diagnostics.The_left_hand_side_of_an_arithmetic_operation_must_be_of_type_any_number_bigint_or_an_enum_type, /*isAwaitValid*/ true); - const rightOk = checkArithmeticOperandType(right, rightType, Diagnostics.The_right_hand_side_of_an_arithmetic_operation_must_be_of_type_any_number_bigint_or_an_enum_type, /*isAwaitValid*/ true); + const leftOk = checkArithmeticOperandType( + left, + leftType, + Diagnostics + .The_left_hand_side_of_an_arithmetic_operation_must_be_of_type_any_number_bigint_or_an_enum_type, + /*isAwaitValid*/ true, + ); + const rightOk = checkArithmeticOperandType( + right, + rightType, + Diagnostics + .The_right_hand_side_of_an_arithmetic_operation_must_be_of_type_any_number_bigint_or_an_enum_type, + /*isAwaitValid*/ true, + ); let resultType: Type; // If both are any or unknown, allow operation; assume it will resolve to number if ( - (isTypeAssignableToKind(leftType, TypeFlags.AnyOrUnknown) && isTypeAssignableToKind(rightType, TypeFlags.AnyOrUnknown)) || + (isTypeAssignableToKind(leftType, TypeFlags.AnyOrUnknown) + && isTypeAssignableToKind(rightType, TypeFlags.AnyOrUnknown)) // Or, if neither could be bigint, implicit coercion results in a number result - !(maybeTypeOfKind(leftType, TypeFlags.BigIntLike) || maybeTypeOfKind(rightType, TypeFlags.BigIntLike)) + || !(maybeTypeOfKind(leftType, TypeFlags.BigIntLike) + || maybeTypeOfKind(rightType, TypeFlags.BigIntLike)) ) { resultType = numberType; } @@ -37466,7 +47902,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { case SyntaxKind.AsteriskAsteriskToken: case SyntaxKind.AsteriskAsteriskEqualsToken: if (languageVersion < ScriptTarget.ES2016) { - error(errorNode, Diagnostics.Exponentiation_cannot_be_performed_on_bigint_values_unless_the_target_option_is_set_to_es2016_or_later); + error( + errorNode, + Diagnostics + .Exponentiation_cannot_be_performed_on_bigint_values_unless_the_target_option_is_set_to_es2016_or_later, + ); } } resultType = bigintType; @@ -37487,22 +47927,34 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return silentNeverType; } - if (!isTypeAssignableToKind(leftType, TypeFlags.StringLike) && !isTypeAssignableToKind(rightType, TypeFlags.StringLike)) { + if ( + !isTypeAssignableToKind(leftType, TypeFlags.StringLike) + && !isTypeAssignableToKind(rightType, TypeFlags.StringLike) + ) { leftType = checkNonNullType(leftType, left); rightType = checkNonNullType(rightType, right); } let resultType: Type | undefined; - if (isTypeAssignableToKind(leftType, TypeFlags.NumberLike, /*strict*/ true) && isTypeAssignableToKind(rightType, TypeFlags.NumberLike, /*strict*/ true)) { + if ( + isTypeAssignableToKind(leftType, TypeFlags.NumberLike, /*strict*/ true) + && isTypeAssignableToKind(rightType, TypeFlags.NumberLike, /*strict*/ true) + ) { // Operands of an enum type are treated as having the primitive type Number. // If both operands are of the Number primitive type, the result is of the Number primitive type. resultType = numberType; } - else if (isTypeAssignableToKind(leftType, TypeFlags.BigIntLike, /*strict*/ true) && isTypeAssignableToKind(rightType, TypeFlags.BigIntLike, /*strict*/ true)) { + else if ( + isTypeAssignableToKind(leftType, TypeFlags.BigIntLike, /*strict*/ true) + && isTypeAssignableToKind(rightType, TypeFlags.BigIntLike, /*strict*/ true) + ) { // If both operands are of the BigInt primitive type, the result is of the BigInt primitive type. resultType = bigintType; } - else if (isTypeAssignableToKind(leftType, TypeFlags.StringLike, /*strict*/ true) || isTypeAssignableToKind(rightType, TypeFlags.StringLike, /*strict*/ true)) { + else if ( + isTypeAssignableToKind(leftType, TypeFlags.StringLike, /*strict*/ true) + || isTypeAssignableToKind(rightType, TypeFlags.StringLike, /*strict*/ true) + ) { // If one or both operands are of the String primitive type, the result is of the String primitive type. resultType = stringType; } @@ -37522,10 +47974,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // If both types have an awaited type of one of these, we'll assume the user // might be missing an await without doing an exhaustive check that inserting // await(s) will actually be a completely valid binary expression. - const closeEnoughKind = TypeFlags.NumberLike | TypeFlags.BigIntLike | TypeFlags.StringLike | TypeFlags.AnyOrUnknown; + const closeEnoughKind = TypeFlags.NumberLike | TypeFlags.BigIntLike | TypeFlags.StringLike + | TypeFlags.AnyOrUnknown; reportOperatorError((left, right) => - isTypeAssignableToKind(left, closeEnoughKind) && - isTypeAssignableToKind(right, closeEnoughKind) + isTypeAssignableToKind(left, closeEnoughKind) + && isTypeAssignableToKind(right, closeEnoughKind) ); return anyType; } @@ -37547,8 +48000,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } const leftAssignableToNumber = isTypeAssignableTo(left, numberOrBigIntType); const rightAssignableToNumber = isTypeAssignableTo(right, numberOrBigIntType); - return leftAssignableToNumber && rightAssignableToNumber || - !leftAssignableToNumber && !rightAssignableToNumber && areTypesComparable(left, right); + return leftAssignableToNumber && rightAssignableToNumber + || !leftAssignableToNumber && !rightAssignableToNumber && areTypesComparable(left, right); }); } return booleanType; @@ -37561,15 +48014,25 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // types may cause the operands to not be comparable. We don't want such errors reported (see #46475). if (!(checkMode && checkMode & CheckMode.TypeOnly)) { if ( - (isLiteralExpressionOfObject(left) || isLiteralExpressionOfObject(right)) && + (isLiteralExpressionOfObject(left) || isLiteralExpressionOfObject(right)) // only report for === and !== in JS, not == or != - (!isInJSFile(left) || (operator === SyntaxKind.EqualsEqualsEqualsToken || operator === SyntaxKind.ExclamationEqualsEqualsToken)) + && (!isInJSFile(left) + || (operator === SyntaxKind.EqualsEqualsEqualsToken + || operator === SyntaxKind.ExclamationEqualsEqualsToken)) ) { - const eqType = operator === SyntaxKind.EqualsEqualsToken || operator === SyntaxKind.EqualsEqualsEqualsToken; - error(errorNode, Diagnostics.This_condition_will_always_return_0_since_JavaScript_compares_objects_by_reference_not_value, eqType ? "false" : "true"); + const eqType = operator === SyntaxKind.EqualsEqualsToken + || operator === SyntaxKind.EqualsEqualsEqualsToken; + error( + errorNode, + Diagnostics + .This_condition_will_always_return_0_since_JavaScript_compares_objects_by_reference_not_value, + eqType ? "false" : "true", + ); } checkNaNEquality(errorNode, operator, left, right); - reportOperatorErrorUnless((left, right) => isTypeEqualityComparableTo(left, right) || isTypeEqualityComparableTo(right, left)); + reportOperatorErrorUnless((left, right) => + isTypeEqualityComparableTo(left, right) || isTypeEqualityComparableTo(right, left) + ); } return booleanType; case SyntaxKind.InstanceOfKeyword: @@ -37578,9 +48041,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return checkInExpression(left, right, leftType, rightType); case SyntaxKind.AmpersandAmpersandToken: case SyntaxKind.AmpersandAmpersandEqualsToken: { - const resultType = getTypeFacts(leftType) & TypeFacts.Truthy ? - getUnionType([extractDefinitelyFalsyTypes(strictNullChecks ? leftType : getBaseTypeOfLiteralType(rightType)), rightType]) : - leftType; + const resultType = getTypeFacts(leftType) & TypeFacts.Truthy + ? getUnionType([ + extractDefinitelyFalsyTypes(strictNullChecks ? leftType : getBaseTypeOfLiteralType(rightType)), + rightType, + ]) + : leftType; if (operator === SyntaxKind.AmpersandAmpersandEqualsToken) { checkAssignmentOperator(rightType); } @@ -37588,9 +48054,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } case SyntaxKind.BarBarToken: case SyntaxKind.BarBarEqualsToken: { - const resultType = getTypeFacts(leftType) & TypeFacts.Falsy ? - getUnionType([getNonNullableType(removeDefinitelyFalsyTypes(leftType)), rightType], UnionReduction.Subtype) : - leftType; + const resultType = getTypeFacts(leftType) & TypeFacts.Falsy + ? getUnionType( + [getNonNullableType(removeDefinitelyFalsyTypes(leftType)), rightType], + UnionReduction.Subtype, + ) + : leftType; if (operator === SyntaxKind.BarBarEqualsToken) { checkAssignmentOperator(rightType); } @@ -37598,25 +48067,26 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } case SyntaxKind.QuestionQuestionToken: case SyntaxKind.QuestionQuestionEqualsToken: { - const resultType = getTypeFacts(leftType) & TypeFacts.EQUndefinedOrNull ? - getUnionType([getNonNullableType(leftType), rightType], UnionReduction.Subtype) : - leftType; + const resultType = getTypeFacts(leftType) & TypeFacts.EQUndefinedOrNull + ? getUnionType([getNonNullableType(leftType), rightType], UnionReduction.Subtype) + : leftType; if (operator === SyntaxKind.QuestionQuestionEqualsToken) { checkAssignmentOperator(rightType); } return resultType; } case SyntaxKind.EqualsToken: - const declKind = isBinaryExpression(left.parent) ? getAssignmentDeclarationKind(left.parent) : AssignmentDeclarationKind.None; + const declKind = isBinaryExpression(left.parent) ? getAssignmentDeclarationKind(left.parent) + : AssignmentDeclarationKind.None; checkAssignmentDeclaration(declKind, rightType); if (isAssignmentDeclaration(declKind)) { if ( - !(rightType.flags & TypeFlags.Object) || - declKind !== AssignmentDeclarationKind.ModuleExports && - declKind !== AssignmentDeclarationKind.Prototype && - !isEmptyObjectType(rightType) && - !isFunctionObjectType(rightType as ObjectType) && - !(getObjectFlags(rightType) & ObjectFlags.Class) + !(rightType.flags & TypeFlags.Object) + || declKind !== AssignmentDeclarationKind.ModuleExports + && declKind !== AssignmentDeclarationKind.Prototype + && !isEmptyObjectType(rightType) + && !isFunctionObjectType(rightType as ObjectType) + && !(getObjectFlags(rightType) & ObjectFlags.Class) ) { // don't check assignability of module.exports=, C.prototype=, or expando types because they will necessarily be incomplete checkAssignmentOperator(rightType); @@ -37628,7 +48098,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return rightType; } case SyntaxKind.CommaToken: - if (!compilerOptions.allowUnreachableCode && isSideEffectFree(left) && !isIndirectCall(left.parent as BinaryExpression)) { + if ( + !compilerOptions.allowUnreachableCode && isSideEffectFree(left) + && !isIndirectCall(left.parent as BinaryExpression) + ) { const sf = getSourceFileOfNode(left); const sourceText = sf.text; const start = skipTrivia(sourceText, left.pos); @@ -37636,7 +48109,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (diag.code !== Diagnostics.JSX_expressions_must_have_one_parent_element.code) return false; return textSpanContainsPosition(diag, start); }); - if (!isInDiag2657) error(left, Diagnostics.Left_side_of_comma_operator_is_unused_and_has_no_side_effects); + if (!isInDiag2657) { + error(left, Diagnostics.Left_side_of_comma_operator_is_unused_and_has_no_side_effects); + } } return rightType; @@ -37645,7 +48120,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function bothAreBigIntLike(left: Type, right: Type): boolean { - return isTypeAssignableToKind(left, TypeFlags.BigIntLike) && isTypeAssignableToKind(right, TypeFlags.BigIntLike); + return isTypeAssignableToKind(left, TypeFlags.BigIntLike) + && isTypeAssignableToKind(right, TypeFlags.BigIntLike); } function checkAssignmentDeclaration(kind: AssignmentDeclarationKind, rightType: Type) { @@ -37654,10 +48130,27 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const propType = getTypeOfSymbol(prop); if (propType.symbol && propType.symbol.flags & SymbolFlags.Class) { const name = prop.escapedName; - const symbol = resolveName(prop.valueDeclaration, name, SymbolFlags.Type, /*nameNotFoundMessage*/ undefined, name, /*isUse*/ false); + const symbol = resolveName( + prop.valueDeclaration, + name, + SymbolFlags.Type, + /*nameNotFoundMessage*/ undefined, + name, + /*isUse*/ false, + ); if (symbol?.declarations && symbol.declarations.some(isJSDocTypedefTag)) { - addDuplicateDeclarationErrorsForSymbols(symbol, Diagnostics.Duplicate_identifier_0, unescapeLeadingUnderscores(name), prop); - addDuplicateDeclarationErrorsForSymbols(prop, Diagnostics.Duplicate_identifier_0, unescapeLeadingUnderscores(name), symbol); + addDuplicateDeclarationErrorsForSymbols( + symbol, + Diagnostics.Duplicate_identifier_0, + unescapeLeadingUnderscores(name), + prop, + ); + addDuplicateDeclarationErrorsForSymbols( + prop, + Diagnostics.Duplicate_identifier_0, + unescapeLeadingUnderscores(name), + symbol, + ); } } } @@ -37666,22 +48159,28 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // Return true for "indirect calls", (i.e. `(0, x.f)(...)` or `(0, eval)(...)`), which prevents passing `this`. function isIndirectCall(node: BinaryExpression): boolean { - return node.parent.kind === SyntaxKind.ParenthesizedExpression && - isNumericLiteral(node.left) && - node.left.text === "0" && - (isCallExpression(node.parent.parent) && node.parent.parent.expression === node.parent || node.parent.parent.kind === SyntaxKind.TaggedTemplateExpression) && + return node.parent.kind === SyntaxKind.ParenthesizedExpression + && isNumericLiteral(node.left) + && node.left.text === "0" + && (isCallExpression(node.parent.parent) && node.parent.parent.expression === node.parent + || node.parent.parent.kind === SyntaxKind.TaggedTemplateExpression) // special-case for "eval" because it's the only non-access case where an indirect call actually affects behavior. - (isAccessExpression(node.right) || isIdentifier(node.right) && node.right.escapedText === "eval"); + && (isAccessExpression(node.right) || isIdentifier(node.right) && node.right.escapedText === "eval"); } // Return true if there was no error, false if there was an error. function checkForDisallowedESSymbolOperand(operator: PunctuationSyntaxKind): boolean { - const offendingSymbolOperand = maybeTypeOfKindConsideringBaseConstraint(leftType, TypeFlags.ESSymbolLike) ? left : - maybeTypeOfKindConsideringBaseConstraint(rightType, TypeFlags.ESSymbolLike) ? right : - undefined; + const offendingSymbolOperand = maybeTypeOfKindConsideringBaseConstraint(leftType, TypeFlags.ESSymbolLike) + ? left + : maybeTypeOfKindConsideringBaseConstraint(rightType, TypeFlags.ESSymbolLike) ? right + : undefined; if (offendingSymbolOperand) { - error(offendingSymbolOperand, Diagnostics.The_0_operator_cannot_be_applied_to_type_symbol, tokenToString(operator)); + error( + offendingSymbolOperand, + Diagnostics.The_0_operator_cannot_be_applied_to_type_symbol, + tokenToString(operator), + ); return false; } @@ -37714,7 +48213,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // getters can be a subtype of setters, so to check for assignability we use the setter's type instead if (isCompoundAssignment(operatorToken.kind) && left.kind === SyntaxKind.PropertyAccessExpression) { - assigneeType = checkPropertyAccessExpression(left as PropertyAccessExpression, /*checkMode*/ undefined, /*writeOnly*/ true); + assigneeType = checkPropertyAccessExpression( + left as PropertyAccessExpression, + /*checkMode*/ undefined, + /*writeOnly*/ true, + ); } // TypeScript 1.0 spec (April 2014): 4.17 @@ -37724,12 +48227,27 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // A compound assignment furthermore requires VarExpr to be classified as a reference (section 4.1) // and the type of the non-compound operation to be assignable to the type of VarExpr. - if (checkReferenceExpression(left, Diagnostics.The_left_hand_side_of_an_assignment_expression_must_be_a_variable_or_a_property_access, Diagnostics.The_left_hand_side_of_an_assignment_expression_may_not_be_an_optional_property_access)) { + if ( + checkReferenceExpression( + left, + Diagnostics + .The_left_hand_side_of_an_assignment_expression_must_be_a_variable_or_a_property_access, + Diagnostics + .The_left_hand_side_of_an_assignment_expression_may_not_be_an_optional_property_access, + ) + ) { let headMessage: DiagnosticMessage | undefined; - if (exactOptionalPropertyTypes && isPropertyAccessExpression(left) && maybeTypeOfKind(valueType, TypeFlags.Undefined)) { - const target = getTypeOfPropertyOfType(getTypeOfExpression(left.expression), left.name.escapedText); + if ( + exactOptionalPropertyTypes && isPropertyAccessExpression(left) + && maybeTypeOfKind(valueType, TypeFlags.Undefined) + ) { + const target = getTypeOfPropertyOfType( + getTypeOfExpression(left.expression), + left.name.escapedText, + ); if (isExactOptionalPropertyMismatch(valueType, target)) { - headMessage = Diagnostics.Type_0_is_not_assignable_to_type_1_with_exactOptionalPropertyTypes_Colon_true_Consider_adding_undefined_to_the_type_of_the_target; + headMessage = Diagnostics + .Type_0_is_not_assignable_to_type_1_with_exactOptionalPropertyTypes_Colon_true_Consider_adding_undefined_to_the_type_of_the_target; } } // to avoid cascading errors check assignability only if 'isReference' check succeeded and no errors were reported @@ -37749,8 +48267,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { case AssignmentDeclarationKind.ThisProperty: const symbol = getSymbolOfNode(left); const init = getAssignedExpandoInitializer(right); - return !!init && isObjectLiteralExpression(init) && - !!symbol?.exports?.size; + return !!init && isObjectLiteralExpression(init) + && !!symbol?.exports?.size; default: return false; } @@ -37796,7 +48314,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } - function tryGiveBetterPrimaryError(errNode: Node, maybeMissingAwait: boolean, leftStr: string, rightStr: string) { + function tryGiveBetterPrimaryError( + errNode: Node, + maybeMissingAwait: boolean, + leftStr: string, + rightStr: string, + ) { switch (operatorToken.kind) { case SyntaxKind.EqualsEqualsEqualsToken: case SyntaxKind.EqualsEqualsToken: @@ -37805,7 +48328,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return errorAndMaybeSuggestAwait( errNode, maybeMissingAwait, - Diagnostics.This_comparison_appears_to_be_unintentional_because_the_types_0_and_1_have_no_overlap, + Diagnostics + .This_comparison_appears_to_be_unintentional_because_the_types_0_and_1_have_no_overlap, leftStr, rightStr, ); @@ -37814,16 +48338,39 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } - function checkNaNEquality(errorNode: Node | undefined, operator: SyntaxKind, left: Expression, right: Expression) { + function checkNaNEquality( + errorNode: Node | undefined, + operator: SyntaxKind, + left: Expression, + right: Expression, + ) { const isLeftNaN = isGlobalNaN(skipParentheses(left)); const isRightNaN = isGlobalNaN(skipParentheses(right)); if (isLeftNaN || isRightNaN) { - const err = error(errorNode, Diagnostics.This_condition_will_always_return_0, tokenToString(operator === SyntaxKind.EqualsEqualsEqualsToken || operator === SyntaxKind.EqualsEqualsToken ? SyntaxKind.FalseKeyword : SyntaxKind.TrueKeyword)); + const err = error( + errorNode, + Diagnostics.This_condition_will_always_return_0, + tokenToString( + operator === SyntaxKind.EqualsEqualsEqualsToken || operator === SyntaxKind.EqualsEqualsToken + ? SyntaxKind.FalseKeyword : SyntaxKind.TrueKeyword, + ), + ); if (isLeftNaN && isRightNaN) return; - const operatorString = operator === SyntaxKind.ExclamationEqualsEqualsToken || operator === SyntaxKind.ExclamationEqualsToken ? tokenToString(SyntaxKind.ExclamationToken) : ""; + const operatorString = operator === SyntaxKind.ExclamationEqualsEqualsToken + || operator === SyntaxKind.ExclamationEqualsToken ? tokenToString(SyntaxKind.ExclamationToken) + : ""; const location = isLeftNaN ? right : left; const expression = skipParentheses(location); - addRelatedInfo(err, createDiagnosticForNode(location, Diagnostics.Did_you_mean_0, `${operatorString}Number.isNaN(${isEntityNameExpression(expression) ? entityNameToString(expression) : "..."})`)); + addRelatedInfo( + err, + createDiagnosticForNode( + location, + Diagnostics.Did_you_mean_0, + `${operatorString}Number.isNaN(${ + isEntityNameExpression(expression) ? entityNameToString(expression) : "..." + })`, + ), + ); } } @@ -37836,7 +48383,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } - function getBaseTypesIfUnrelated(leftType: Type, rightType: Type, isRelated: (left: Type, right: Type) => boolean): [Type, Type] { + function getBaseTypesIfUnrelated( + leftType: Type, + rightType: Type, + isRelated: (left: Type, right: Type) => boolean, + ): [Type, Type] { let effectiveLeft = leftType; let effectiveRight = rightType; const leftBase = getBaseTypeOfLiteralType(leftType); @@ -37883,9 +48434,19 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const signatureNextType = iterationTypes && iterationTypes.nextType || anyType; const resolvedSignatureNextType = isAsync ? getAwaitedType(signatureNextType) || anyType : signatureNextType; const yieldExpressionType = node.expression ? checkExpression(node.expression) : undefinedWideningType; - const yieldedType = getYieldedTypeOfYieldExpression(node, yieldExpressionType, resolvedSignatureNextType, isAsync); + const yieldedType = getYieldedTypeOfYieldExpression( + node, + yieldExpressionType, + resolvedSignatureNextType, + isAsync, + ); if (returnType && yieldedType) { - checkTypeAssignableToAndOptionallyElaborate(yieldedType, signatureYieldType, node.expression || node, node.expression); + checkTypeAssignableToAndOptionallyElaborate( + yieldedType, + signatureYieldType, + node.expression || node, + node.expression, + ); } if (node.asteriskToken) { @@ -37904,7 +48465,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (noImplicitAny && !expressionResultIsUnused(node)) { const contextualType = getContextualType(node, /*contextFlags*/ undefined); if (!contextualType || isTypeAny(contextualType)) { - error(node, Diagnostics.yield_expression_implicitly_results_in_an_any_type_because_its_containing_generator_lacks_a_return_type_annotation); + error( + node, + Diagnostics + .yield_expression_implicitly_results_in_an_any_type_because_its_containing_generator_lacks_a_return_type_annotation, + ); } } }); @@ -37932,8 +48497,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function isTemplateLiteralContext(node: Node): boolean { const parent = node.parent; - return isParenthesizedExpression(parent) && isTemplateLiteralContext(parent) || - isElementAccessExpression(parent) && parent.argumentExpression === node; + return isParenthesizedExpression(parent) && isTemplateLiteralContext(parent) + || isElementAccessExpression(parent) && parent.argumentExpression === node; } function checkTemplateExpression(node: TemplateExpression): Type { @@ -37942,12 +48507,22 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { for (const span of node.templateSpans) { const type = checkExpression(span.expression); if (maybeTypeOfKindConsideringBaseConstraint(type, TypeFlags.ESSymbolLike)) { - error(span.expression, Diagnostics.Implicit_conversion_of_a_symbol_to_a_string_will_fail_at_runtime_Consider_wrapping_this_expression_in_String); + error( + span.expression, + Diagnostics + .Implicit_conversion_of_a_symbol_to_a_string_will_fail_at_runtime_Consider_wrapping_this_expression_in_String, + ); } texts.push(span.literal.text); types.push(isTypeAssignableTo(type, templateConstraintType) ? type : stringType); } - if (isConstContext(node) || isTemplateLiteralContext(node) || someType(getContextualType(node, /*contextFlags*/ undefined) || unknownType, isTemplateLiteralContextualType)) { + if ( + isConstContext(node) || isTemplateLiteralContext(node) + || someType( + getContextualType(node, /*contextFlags*/ undefined) || unknownType, + isTemplateLiteralContextualType, + ) + ) { return getTemplateLiteralType(texts, types); } const evaluated = node.parent.kind !== SyntaxKind.TaggedTemplateExpression && evaluateTemplateExpression(node); @@ -37955,8 +48530,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function isTemplateLiteralContextualType(type: Type): boolean { - return !!(type.flags & (TypeFlags.StringLiteral | TypeFlags.TemplateLiteral) || - type.flags & TypeFlags.InstantiableNonPrimitive && maybeTypeOfKind(getBaseConstraintOfType(type) || unknownType, TypeFlags.StringLike)); + return !!(type.flags & (TypeFlags.StringLiteral | TypeFlags.TemplateLiteral) + || type.flags & TypeFlags.InstantiableNonPrimitive + && maybeTypeOfKind(getBaseConstraintOfType(type) || unknownType, TypeFlags.StringLike)); } function getContextNode(node: Expression): Expression { @@ -37966,11 +48542,19 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return node; } - function checkExpressionWithContextualType(node: Expression, contextualType: Type, inferenceContext: InferenceContext | undefined, checkMode: CheckMode): Type { + function checkExpressionWithContextualType( + node: Expression, + contextualType: Type, + inferenceContext: InferenceContext | undefined, + checkMode: CheckMode, + ): Type { const contextNode = getContextNode(node); pushContextualType(contextNode, contextualType, /*isCache*/ false); pushInferenceContext(contextNode, inferenceContext); - const type = checkExpression(node, checkMode | CheckMode.Contextual | (inferenceContext ? CheckMode.Inferential : 0)); + const type = checkExpression( + node, + checkMode | CheckMode.Contextual | (inferenceContext ? CheckMode.Inferential : 0), + ); // In CheckMode.Inferential we collect intra-expression inference sites to process before fixing any type // parameters. This information is no longer needed after the call to checkExpression. if (inferenceContext && inferenceContext.intraExpressionInferenceSites) { @@ -37979,8 +48563,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // We strip literal freshness when an appropriate contextual type is present such that contextually typed // literals always preserve their literal types (otherwise they might widen during type inference). An alternative // here would be to not mark contextually typed literals as fresh in the first place. - const result = maybeTypeOfKind(type, TypeFlags.Literal) && isLiteralOfContextualType(type, instantiateContextualType(contextualType, node, /*contextFlags*/ undefined)) ? - getRegularTypeOfLiteralType(type) : type; + const result = maybeTypeOfKind(type, TypeFlags.Literal) + && isLiteralOfContextualType( + type, + instantiateContextualType(contextualType, node, /*contextFlags*/ undefined), + ) + ? getRegularTypeOfLiteralType(type) : type; popInferenceContext(); popContextualType(); return result; @@ -38008,9 +48596,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function isTypeAssertion(node: Expression) { node = skipParentheses(node, /*excludeJSDocTypeAssertions*/ true); - return node.kind === SyntaxKind.TypeAssertionExpression || - node.kind === SyntaxKind.AsExpression || - isJSDocTypeAssertion(node); + return node.kind === SyntaxKind.TypeAssertionExpression + || node.kind === SyntaxKind.AsExpression + || isJSDocTypeAssertion(node); } function checkDeclarationInitializer( @@ -38025,13 +48613,19 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return checkSatisfiesExpressionWorker(initializer, typeNode, checkMode); } } - const type = getQuickTypeOfExpression(initializer) || - (contextualType ? - checkExpressionWithContextualType(initializer, contextualType, /*inferenceContext*/ undefined, checkMode || CheckMode.Normal) + const type = getQuickTypeOfExpression(initializer) + || (contextualType + ? checkExpressionWithContextualType( + initializer, + contextualType, + /*inferenceContext*/ undefined, + checkMode || CheckMode.Normal, + ) : checkExpressionCached(initializer, checkMode)); - return isParameter(declaration) && declaration.name.kind === SyntaxKind.ArrayBindingPattern && - isTupleType(type) && !type.target.hasRestElement && getTypeReferenceArity(type) < declaration.name.elements.length ? - padTupleType(type, declaration.name) : type; + return isParameter(declaration) && declaration.name.kind === SyntaxKind.ArrayBindingPattern + && isTupleType(type) && !type.target.hasRestElement + && getTypeReferenceArity(type) < declaration.name.elements.length + ? padTupleType(type, declaration.name) : type; } function padTupleType(type: TupleTypeReference, pattern: ArrayBindingPattern) { @@ -38041,7 +48635,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { for (let i = getTypeReferenceArity(type); i < patternElements.length; i++) { const e = patternElements[i]; if (i < patternElements.length - 1 || !(e.kind === SyntaxKind.BindingElement && e.dotDotDotToken)) { - elementTypes.push(!isOmittedExpression(e) && hasDefaultValue(e) ? getTypeFromBindingElement(e, /*includePatternInType*/ false, /*reportErrors*/ false) : anyType); + elementTypes.push( + !isOmittedExpression(e) && hasDefaultValue(e) + ? getTypeFromBindingElement(e, /*includePatternInType*/ false, /*reportErrors*/ false) + : anyType, + ); elementFlags.push(ElementFlags.Optional); if (!isOmittedExpression(e) && !hasDefaultValue(e)) { reportImplicitAny(e, anyType); @@ -38052,7 +48650,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function widenTypeInferredFromInitializer(declaration: HasExpressionInitializer, type: Type) { - const widened = getCombinedNodeFlagsCached(declaration) & NodeFlags.Constant || isDeclarationReadonly(declaration) ? type : getWidenedLiteralType(type); + const widened = + getCombinedNodeFlagsCached(declaration) & NodeFlags.Constant || isDeclarationReadonly(declaration) ? type + : getWidenedLiteralType(type); if (isInJSFile(declaration)) { if (isEmptyLiteralType(widened)) { reportImplicitAny(declaration, anyType); @@ -38077,37 +48677,60 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // this a literal context for literals of that primitive type. For example, given a // type parameter 'T extends string', infer string literal types for T. const constraint = getBaseConstraintOfType(contextualType) || unknownType; - return maybeTypeOfKind(constraint, TypeFlags.String) && maybeTypeOfKind(candidateType, TypeFlags.StringLiteral) || - maybeTypeOfKind(constraint, TypeFlags.Number) && maybeTypeOfKind(candidateType, TypeFlags.NumberLiteral) || - maybeTypeOfKind(constraint, TypeFlags.BigInt) && maybeTypeOfKind(candidateType, TypeFlags.BigIntLiteral) || - maybeTypeOfKind(constraint, TypeFlags.ESSymbol) && maybeTypeOfKind(candidateType, TypeFlags.UniqueESSymbol) || - isLiteralOfContextualType(candidateType, constraint); + return maybeTypeOfKind(constraint, TypeFlags.String) + && maybeTypeOfKind(candidateType, TypeFlags.StringLiteral) + || maybeTypeOfKind(constraint, TypeFlags.Number) + && maybeTypeOfKind(candidateType, TypeFlags.NumberLiteral) + || maybeTypeOfKind(constraint, TypeFlags.BigInt) + && maybeTypeOfKind(candidateType, TypeFlags.BigIntLiteral) + || maybeTypeOfKind(constraint, TypeFlags.ESSymbol) + && maybeTypeOfKind(candidateType, TypeFlags.UniqueESSymbol) + || isLiteralOfContextualType(candidateType, constraint); } // If the contextual type is a literal of a particular primitive type, we consider this a // literal context for all literals of that primitive type. - return !!(contextualType.flags & (TypeFlags.StringLiteral | TypeFlags.Index | TypeFlags.TemplateLiteral | TypeFlags.StringMapping) && maybeTypeOfKind(candidateType, TypeFlags.StringLiteral) || - contextualType.flags & TypeFlags.NumberLiteral && maybeTypeOfKind(candidateType, TypeFlags.NumberLiteral) || - contextualType.flags & TypeFlags.BigIntLiteral && maybeTypeOfKind(candidateType, TypeFlags.BigIntLiteral) || - contextualType.flags & TypeFlags.BooleanLiteral && maybeTypeOfKind(candidateType, TypeFlags.BooleanLiteral) || - contextualType.flags & TypeFlags.UniqueESSymbol && maybeTypeOfKind(candidateType, TypeFlags.UniqueESSymbol)); + return !!(contextualType.flags + & (TypeFlags.StringLiteral | TypeFlags.Index | TypeFlags.TemplateLiteral + | TypeFlags.StringMapping) && maybeTypeOfKind(candidateType, TypeFlags.StringLiteral) + || contextualType.flags & TypeFlags.NumberLiteral + && maybeTypeOfKind(candidateType, TypeFlags.NumberLiteral) + || contextualType.flags & TypeFlags.BigIntLiteral + && maybeTypeOfKind(candidateType, TypeFlags.BigIntLiteral) + || contextualType.flags & TypeFlags.BooleanLiteral + && maybeTypeOfKind(candidateType, TypeFlags.BooleanLiteral) + || contextualType.flags & TypeFlags.UniqueESSymbol + && maybeTypeOfKind(candidateType, TypeFlags.UniqueESSymbol)); } return false; } function isConstContext(node: Expression): boolean { const parent = node.parent; - return isAssertionExpression(parent) && isConstTypeReference(parent.type) || - isJSDocTypeAssertion(parent) && isConstTypeReference(getJSDocTypeAssertionType(parent)) || - isValidConstAssertionArgument(node) && isConstTypeVariable(getContextualType(node, ContextFlags.None)) || - (isParenthesizedExpression(parent) || isArrayLiteralExpression(parent) || isSpreadElement(parent)) && isConstContext(parent) || - (isPropertyAssignment(parent) || isShorthandPropertyAssignment(parent) || isTemplateSpan(parent)) && isConstContext(parent.parent); + return isAssertionExpression(parent) && isConstTypeReference(parent.type) + || isJSDocTypeAssertion(parent) && isConstTypeReference(getJSDocTypeAssertionType(parent)) + || isValidConstAssertionArgument(node) && isConstTypeVariable(getContextualType(node, ContextFlags.None)) + || (isParenthesizedExpression(parent) || isArrayLiteralExpression(parent) || isSpreadElement(parent)) + && isConstContext(parent) + || (isPropertyAssignment(parent) || isShorthandPropertyAssignment(parent) || isTemplateSpan(parent)) + && isConstContext(parent.parent); } - function checkExpressionForMutableLocation(node: Expression, checkMode: CheckMode | undefined, forceTuple?: boolean): Type { + function checkExpressionForMutableLocation( + node: Expression, + checkMode: CheckMode | undefined, + forceTuple?: boolean, + ): Type { const type = checkExpression(node, checkMode, forceTuple); - return isConstContext(node) || isCommonJsExportedExpression(node) ? getRegularTypeOfLiteralType(type) : - isTypeAssertion(node) ? type : - getWidenedLiteralLikeTypeForContextualType(type, instantiateContextualType(getContextualType(node, /*contextFlags*/ undefined), node, /*contextFlags*/ undefined)); + return isConstContext(node) || isCommonJsExportedExpression(node) ? getRegularTypeOfLiteralType(type) + : isTypeAssertion(node) ? type + : getWidenedLiteralLikeTypeForContextualType( + type, + instantiateContextualType( + getContextualType(node, /*contextFlags*/ undefined), + node, + /*contextFlags*/ undefined, + ), + ); } function checkPropertyAssignment(node: PropertyAssignment, checkMode?: CheckMode): Type { @@ -38136,7 +48759,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return instantiateTypeWithSingleGenericCallSignature(node, uninstantiatedType, checkMode); } - function instantiateTypeWithSingleGenericCallSignature(node: Expression | MethodDeclaration | QualifiedName, type: Type, checkMode?: CheckMode) { + function instantiateTypeWithSingleGenericCallSignature( + node: Expression | MethodDeclaration | QualifiedName, + type: Type, + checkMode?: CheckMode, + ) { if (checkMode && checkMode & (CheckMode.Inferential | CheckMode.SkipGenericFunctions)) { const callSignature = getSingleSignature(type, SignatureKind.Call, /*allowMembers*/ true); const constructSignature = getSingleSignature(type, SignatureKind.Construct, /*allowMembers*/ true); @@ -38144,7 +48771,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (signature && signature.typeParameters) { const contextualType = getApparentTypeOfContextualType(node as Expression, ContextFlags.NoConstraints); if (contextualType) { - const contextualSignature = getSingleSignature(getNonNullableType(contextualType), callSignature ? SignatureKind.Call : SignatureKind.Construct, /*allowMembers*/ false); + const contextualSignature = getSingleSignature( + getNonNullableType(contextualType), + callSignature ? SignatureKind.Call : SignatureKind.Construct, + /*allowMembers*/ false, + ); if (contextualSignature && !contextualSignature.typeParameters) { if (checkMode & CheckMode.SkipGenericFunctions) { skippedGenericFunction(node, checkMode); @@ -38159,11 +48790,17 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // potentially add inferred type parameters to the outer function return type. const returnType = context.signature && getReturnTypeOfSignature(context.signature); const returnSignature = returnType && getSingleCallOrConstructSignature(returnType); - if (returnSignature && !returnSignature.typeParameters && !every(context.inferences, hasInferenceCandidates)) { + if ( + returnSignature && !returnSignature.typeParameters + && !every(context.inferences, hasInferenceCandidates) + ) { // Instantiate the signature with its own type parameters as type arguments, possibly // renaming the type parameters to ensure they have unique names. const uniqueTypeParameters = getUniqueTypeParameters(context, signature.typeParameters); - const instantiatedSignature = getSignatureInstantiationWithoutFillingInTypeArguments(signature, uniqueTypeParameters); + const instantiatedSignature = getSignatureInstantiationWithoutFillingInTypeArguments( + signature, + uniqueTypeParameters, + ); // Infer from the parameters of the instantiated signature to the parameters of the // contextual signature starting with an empty set of inference candidates. const inferences = map(context.inferences, info => createInferenceInfo(info.typeParameter)); @@ -38181,12 +48818,17 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // to the set of inferred type parameters for the outer function return type. if (!hasOverlappingInferences(context.inferences, inferences)) { mergeInferences(context.inferences, inferences); - context.inferredTypeParameters = concatenate(context.inferredTypeParameters, uniqueTypeParameters); + context.inferredTypeParameters = concatenate( + context.inferredTypeParameters, + uniqueTypeParameters, + ); return getOrCreateTypeFromSignature(instantiatedSignature); } } } - return getOrCreateTypeFromSignature(instantiateSignatureInContextOf(signature, contextualSignature, context)); + return getOrCreateTypeFromSignature( + instantiateSignatureInContextOf(signature, contextualSignature, context), + ); } } } @@ -38228,7 +48870,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } - function getUniqueTypeParameters(context: InferenceContext, typeParameters: readonly TypeParameter[]): readonly TypeParameter[] { + function getUniqueTypeParameters( + context: InferenceContext, + typeParameters: readonly TypeParameter[], + ): readonly TypeParameter[] { const result: TypeParameter[] = []; let oldTypeParameters: TypeParameter[] | undefined; let newTypeParameters: TypeParameter[] | undefined; @@ -38262,7 +48907,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function getUniqueTypeParameterName(typeParameters: readonly TypeParameter[], baseName: __String) { let len = (baseName as string).length; - while (len > 1 && (baseName as string).charCodeAt(len - 1) >= CharacterCodes._0 && (baseName as string).charCodeAt(len - 1) <= CharacterCodes._9) len--; + while ( + len > 1 && (baseName as string).charCodeAt(len - 1) >= CharacterCodes._0 + && (baseName as string).charCodeAt(len - 1) <= CharacterCodes._9 + ) len--; const s = (baseName as string).slice(0, len); for (let index = 1; true; index++) { const augmentedName = s + index as __String; @@ -38329,9 +48977,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } // Optimize for the common case of a call to a function with a single non-generic call // signature where we can just fetch the return type without checking the arguments. - if (isCallExpression(expr) && expr.expression.kind !== SyntaxKind.SuperKeyword && !isRequireCall(expr, /*requireStringLiteralLikeArgument*/ true) && !isSymbolOrSymbolForCall(expr)) { - return isCallChain(expr) ? getReturnTypeOfSingleNonGenericSignatureOfCallChain(expr) : - getReturnTypeOfSingleNonGenericCallSignature(checkNonNullExpression(expr.expression)); + if ( + isCallExpression(expr) && expr.expression.kind !== SyntaxKind.SuperKeyword + && !isRequireCall(expr, /*requireStringLiteralLikeArgument*/ true) && !isSymbolOrSymbolForCall(expr) + ) { + return isCallChain(expr) ? getReturnTypeOfSingleNonGenericSignatureOfCallChain(expr) + : getReturnTypeOfSingleNonGenericCallSignature(checkNonNullExpression(expr.expression)); } else if (isAssertionExpression(expr) && !isConstTypeReference(expr.type)) { return getTypeFromTypeNode((expr as TypeAssertion).type); @@ -38361,7 +49012,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function checkExpression(node: Expression | QualifiedName, checkMode?: CheckMode, forceTuple?: boolean): Type { - tracing?.push(tracing.Phase.Check, "checkExpression", { kind: node.kind, pos: node.pos, end: node.end, path: (node as TracingNode).tracingPath }); + tracing?.push(tracing.Phase.Check, "checkExpression", { + kind: node.kind, + pos: node.pos, + end: node.end, + path: (node as TracingNode).tracingPath, + }); const saveCurrentNode = currentNode; currentNode = node; instantiationCount = 0; @@ -38380,21 +49036,32 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // - 'left' in property access // - 'object' in indexed access // - target in rhs of import statement - const ok = (node.parent.kind === SyntaxKind.PropertyAccessExpression && (node.parent as PropertyAccessExpression).expression === node) || - (node.parent.kind === SyntaxKind.ElementAccessExpression && (node.parent as ElementAccessExpression).expression === node) || - ((node.kind === SyntaxKind.Identifier || node.kind === SyntaxKind.QualifiedName) && isInRightSideOfImportOrExportAssignment(node as Identifier) || - (node.parent.kind === SyntaxKind.TypeQuery && (node.parent as TypeQueryNode).exprName === node)) || - (node.parent.kind === SyntaxKind.ExportSpecifier); // We allow reexporting const enums + const ok = (node.parent.kind === SyntaxKind.PropertyAccessExpression + && (node.parent as PropertyAccessExpression).expression === node) + || (node.parent.kind === SyntaxKind.ElementAccessExpression + && (node.parent as ElementAccessExpression).expression === node) + || ((node.kind === SyntaxKind.Identifier || node.kind === SyntaxKind.QualifiedName) + && isInRightSideOfImportOrExportAssignment(node as Identifier) + || (node.parent.kind === SyntaxKind.TypeQuery && (node.parent as TypeQueryNode).exprName === node)) + || (node.parent.kind === SyntaxKind.ExportSpecifier); // We allow reexporting const enums if (!ok) { - error(node, Diagnostics.const_enums_can_only_be_used_in_property_or_index_access_expressions_or_the_right_hand_side_of_an_import_declaration_or_export_assignment_or_type_query); + error( + node, + Diagnostics + .const_enums_can_only_be_used_in_property_or_index_access_expressions_or_the_right_hand_side_of_an_import_declaration_or_export_assignment_or_type_query, + ); } if (getIsolatedModules(compilerOptions)) { Debug.assert(!!(type.symbol.flags & SymbolFlags.ConstEnum)); const constEnumDeclaration = type.symbol.valueDeclaration as EnumDeclaration; if (constEnumDeclaration.flags & NodeFlags.Ambient && !isValidTypeOnlyAliasUseSite(node)) { - error(node, Diagnostics.Cannot_access_ambient_const_enums_when_0_is_enabled, isolatedModulesLikeFlagName); + error( + node, + Diagnostics.Cannot_access_ambient_const_enums_when_0_is_enabled, + isolatedModulesLikeFlagName, + ); } } } @@ -38402,7 +49069,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function checkParenthesizedExpression(node: ParenthesizedExpression, checkMode?: CheckMode): Type { if (hasJSDocNodes(node)) { if (isJSDocSatisfiesExpression(node)) { - return checkSatisfiesExpressionWorker(node.expression, getJSDocSatisfiesExpressionType(node), checkMode); + return checkSatisfiesExpressionWorker( + node.expression, + getJSDocSatisfiesExpressionType(node), + checkMode, + ); } if (isJSDocTypeAssertion(node)) { return checkAssertionWorker(node, checkMode); @@ -38411,7 +49082,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return checkExpression(node.expression, checkMode); } - function checkExpressionWorker(node: Expression | QualifiedName, checkMode: CheckMode | undefined, forceTuple?: boolean): Type { + function checkExpressionWorker( + node: Expression | QualifiedName, + checkMode: CheckMode | undefined, + forceTuple?: boolean, + ): Type { const kind = node.kind; if (cancellationToken) { // Only bother checking on a few construct kinds. We don't want to be excessively @@ -38436,9 +49111,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return nullWideningType; case SyntaxKind.NoSubstitutionTemplateLiteral: case SyntaxKind.StringLiteral: - return hasSkipDirectInferenceFlag(node) ? - wildcardType : - getFreshTypeOfLiteralType(getStringLiteralType((node as StringLiteralLike).text)); + return hasSkipDirectInferenceFlag(node) + ? wildcardType + : getFreshTypeOfLiteralType(getStringLiteralType((node as StringLiteralLike).text)); case SyntaxKind.NumericLiteral: { checkGrammarNumericLiteral(node as NumericLiteral); const value = +(node as NumericLiteral).text; @@ -38486,7 +49161,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return checkClassExpression(node as ClassExpression); case SyntaxKind.FunctionExpression: case SyntaxKind.ArrowFunction: - return checkFunctionExpressionOrObjectLiteralMethod(node as FunctionExpression | ArrowFunction, checkMode); + return checkFunctionExpressionOrObjectLiteralMethod( + node as FunctionExpression | ArrowFunction, + checkMode, + ); case SyntaxKind.TypeOfExpression: return checkTypeOfExpression(node as TypeOfExpression); case SyntaxKind.TypeAssertionExpression: @@ -38558,7 +49236,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const constraintType = getConstraintOfTypeParameter(typeParameter); const defaultType = getDefaultFromTypeParameter(typeParameter); if (constraintType && defaultType) { - checkTypeAssignableTo(defaultType, getTypeWithThisArgument(instantiateType(constraintType, makeUnaryTypeMapper(typeParameter, defaultType)), defaultType), node.default, Diagnostics.Type_0_does_not_satisfy_the_constraint_1); + checkTypeAssignableTo( + defaultType, + getTypeWithThisArgument( + instantiateType(constraintType, makeUnaryTypeMapper(typeParameter, defaultType)), + defaultType, + ), + node.default, + Diagnostics.Type_0_does_not_satisfy_the_constraint_1, + ); } checkNodeDeferred(node); addLazyDiagnostic(() => checkTypeNameIsReserved(node.name, Diagnostics.Type_parameter_name_cannot_be_0)); @@ -38570,16 +49256,39 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const modifiers = getTypeParameterModifiers(typeParameter) & (ModifierFlags.In | ModifierFlags.Out); if (modifiers) { const symbol = getSymbolOfDeclaration(node.parent); - if (isTypeAliasDeclaration(node.parent) && !(getObjectFlags(getDeclaredTypeOfSymbol(symbol)) & (ObjectFlags.Anonymous | ObjectFlags.Mapped))) { - error(node, Diagnostics.Variance_annotations_are_only_supported_in_type_aliases_for_object_function_constructor_and_mapped_types); + if ( + isTypeAliasDeclaration(node.parent) + && !(getObjectFlags(getDeclaredTypeOfSymbol(symbol)) & (ObjectFlags.Anonymous | ObjectFlags.Mapped)) + ) { + error( + node, + Diagnostics + .Variance_annotations_are_only_supported_in_type_aliases_for_object_function_constructor_and_mapped_types, + ); } else if (modifiers === ModifierFlags.In || modifiers === ModifierFlags.Out) { - tracing?.push(tracing.Phase.CheckTypes, "checkTypeParameterDeferred", { parent: getTypeId(getDeclaredTypeOfSymbol(symbol)), id: getTypeId(typeParameter) }); - const source = createMarkerType(symbol, typeParameter, modifiers === ModifierFlags.Out ? markerSubTypeForCheck : markerSuperTypeForCheck); - const target = createMarkerType(symbol, typeParameter, modifiers === ModifierFlags.Out ? markerSuperTypeForCheck : markerSubTypeForCheck); + tracing?.push(tracing.Phase.CheckTypes, "checkTypeParameterDeferred", { + parent: getTypeId(getDeclaredTypeOfSymbol(symbol)), + id: getTypeId(typeParameter), + }); + const source = createMarkerType( + symbol, + typeParameter, + modifiers === ModifierFlags.Out ? markerSubTypeForCheck : markerSuperTypeForCheck, + ); + const target = createMarkerType( + symbol, + typeParameter, + modifiers === ModifierFlags.Out ? markerSuperTypeForCheck : markerSubTypeForCheck, + ); const saveVarianceTypeParameter = typeParameter; varianceTypeParameter = typeParameter; - checkTypeAssignableTo(source, target, node, Diagnostics.Type_0_is_not_assignable_to_type_1_as_implied_by_variance_annotation); + checkTypeAssignableTo( + source, + target, + node, + Diagnostics.Type_0_is_not_assignable_to_type_1_as_implied_by_variance_annotation, + ); varianceTypeParameter = saveVarianceTypeParameter; tracing?.pop(); } @@ -38600,18 +49309,30 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (!(func.kind === SyntaxKind.Constructor && nodeIsPresent(func.body))) { error(node, Diagnostics.A_parameter_property_is_only_allowed_in_a_constructor_implementation); } - if (func.kind === SyntaxKind.Constructor && isIdentifier(node.name) && node.name.escapedText === "constructor") { + if ( + func.kind === SyntaxKind.Constructor && isIdentifier(node.name) + && node.name.escapedText === "constructor" + ) { error(node.name, Diagnostics.constructor_cannot_be_used_as_a_parameter_property_name); } } - if (!node.initializer && isOptionalDeclaration(node) && isBindingPattern(node.name) && (func as FunctionLikeDeclaration).body) { + if ( + !node.initializer && isOptionalDeclaration(node) && isBindingPattern(node.name) + && (func as FunctionLikeDeclaration).body + ) { error(node, Diagnostics.A_binding_pattern_parameter_cannot_be_optional_in_an_implementation_signature); } - if (node.name && isIdentifier(node.name) && (node.name.escapedText === "this" || node.name.escapedText === "new")) { + if ( + node.name && isIdentifier(node.name) + && (node.name.escapedText === "this" || node.name.escapedText === "new") + ) { if (func.parameters.indexOf(node) !== 0) { error(node, Diagnostics.A_0_parameter_must_be_the_first_parameter, node.name.escapedText as string); } - if (func.kind === SyntaxKind.Constructor || func.kind === SyntaxKind.ConstructSignature || func.kind === SyntaxKind.ConstructorType) { + if ( + func.kind === SyntaxKind.Constructor || func.kind === SyntaxKind.ConstructSignature + || func.kind === SyntaxKind.ConstructorType + ) { error(node, Diagnostics.A_constructor_cannot_have_a_this_parameter); } if (func.kind === SyntaxKind.ArrowFunction) { @@ -38624,7 +49345,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // Only check rest parameter type if it's not a binding pattern. Since binding patterns are // not allowed in a rest parameter, we already have an error from checkGrammarParameterList. - if (node.dotDotDotToken && !isBindingPattern(node.name) && !isTypeAssignableTo(getReducedType(getTypeOfSymbol(node.symbol)), anyReadonlyArrayType)) { + if ( + node.dotDotDotToken && !isBindingPattern(node.name) + && !isTypeAssignableTo(getReducedType(getTypeOfSymbol(node.symbol)), anyReadonlyArrayType) + ) { error(node, Diagnostics.A_rest_parameter_must_be_of_an_array_type); } } @@ -38651,13 +49375,26 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } else { if (typePredicate.parameterIndex >= 0) { - if (signatureHasRestParameter(signature) && typePredicate.parameterIndex === signature.parameters.length - 1) { + if ( + signatureHasRestParameter(signature) + && typePredicate.parameterIndex === signature.parameters.length - 1 + ) { error(parameterName, Diagnostics.A_type_predicate_cannot_reference_a_rest_parameter); } else { if (typePredicate.type) { - const leadingError = () => chainDiagnosticMessages(/*details*/ undefined, Diagnostics.A_type_predicate_s_type_must_be_assignable_to_its_parameter_s_type); - checkTypeAssignableTo(typePredicate.type, getTypeOfSymbol(signature.parameters[typePredicate.parameterIndex]), node.type, /*headMessage*/ undefined, leadingError); + const leadingError = () => + chainDiagnosticMessages( + /*details*/ undefined, + Diagnostics.A_type_predicate_s_type_must_be_assignable_to_its_parameter_s_type, + ); + checkTypeAssignableTo( + typePredicate.type, + getTypeOfSymbol(signature.parameters[typePredicate.parameterIndex]), + node.type, + /*headMessage*/ undefined, + leadingError, + ); } } } @@ -38665,8 +49402,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { let hasReportedError = false; for (const { name } of parent.parameters) { if ( - isBindingPattern(name) && - checkIfTypePredicateVariableIsDeclaredInBindingPattern(name, parameterName, typePredicate.parameterName) + isBindingPattern(name) + && checkIfTypePredicateVariableIsDeclaredInBindingPattern( + name, + parameterName, + typePredicate.parameterName, + ) ) { hasReportedError = true; break; @@ -38707,7 +49448,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const name = element.name; if (name.kind === SyntaxKind.Identifier && name.escapedText === predicateVariableName) { - error(predicateVariableNode, Diagnostics.A_type_predicate_cannot_reference_element_0_in_a_binding_pattern, predicateVariableName); + error( + predicateVariableNode, + Diagnostics.A_type_predicate_cannot_reference_element_0_in_a_binding_pattern, + predicateVariableName, + ); return true; } else if (name.kind === SyntaxKind.ArrayBindingPattern || name.kind === SyntaxKind.ObjectBindingPattern) { @@ -38731,9 +49476,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } // TODO (yuisu): Remove this check in else-if when SyntaxKind.Construct is moved and ambient context is handled else if ( - node.kind === SyntaxKind.FunctionType || node.kind === SyntaxKind.FunctionDeclaration || node.kind === SyntaxKind.ConstructorType || - node.kind === SyntaxKind.CallSignature || node.kind === SyntaxKind.Constructor || - node.kind === SyntaxKind.ConstructSignature + node.kind === SyntaxKind.FunctionType || node.kind === SyntaxKind.FunctionDeclaration + || node.kind === SyntaxKind.ConstructorType + || node.kind === SyntaxKind.CallSignature || node.kind === SyntaxKind.Constructor + || node.kind === SyntaxKind.ConstructSignature ) { checkGrammarFunctionLikeDeclaration(node as FunctionLikeDeclaration); } @@ -38741,18 +49487,27 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const functionFlags = getFunctionFlags(node as FunctionLikeDeclaration); if (!(functionFlags & FunctionFlags.Invalid)) { // Async generators prior to ESNext require the __await and __asyncGenerator helpers - if ((functionFlags & FunctionFlags.AsyncGenerator) === FunctionFlags.AsyncGenerator && languageVersion < ScriptTarget.ESNext) { + if ( + (functionFlags & FunctionFlags.AsyncGenerator) === FunctionFlags.AsyncGenerator + && languageVersion < ScriptTarget.ESNext + ) { checkExternalEmitHelpers(node, ExternalEmitHelpers.AsyncGeneratorIncludes); } // Async functions prior to ES2017 require the __awaiter helper - if ((functionFlags & FunctionFlags.AsyncGenerator) === FunctionFlags.Async && languageVersion < ScriptTarget.ES2017) { + if ( + (functionFlags & FunctionFlags.AsyncGenerator) === FunctionFlags.Async + && languageVersion < ScriptTarget.ES2017 + ) { checkExternalEmitHelpers(node, ExternalEmitHelpers.Awaiter); } // Generator functions, Async functions, and Async Generator functions prior to // ES2015 require the __generator helper - if ((functionFlags & FunctionFlags.AsyncGenerator) !== FunctionFlags.Normal && languageVersion < ScriptTarget.ES2015) { + if ( + (functionFlags & FunctionFlags.AsyncGenerator) !== FunctionFlags.Normal + && languageVersion < ScriptTarget.ES2015 + ) { checkExternalEmitHelpers(node, ExternalEmitHelpers.Generator); } } @@ -38789,10 +49544,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (noImplicitAny && !returnTypeNode) { switch (node.kind) { case SyntaxKind.ConstructSignature: - error(node, Diagnostics.Construct_signature_which_lacks_return_type_annotation_implicitly_has_an_any_return_type); + error( + node, + Diagnostics + .Construct_signature_which_lacks_return_type_annotation_implicitly_has_an_any_return_type, + ); break; case SyntaxKind.CallSignature: - error(node, Diagnostics.Call_signature_which_lacks_return_type_annotation_implicitly_has_an_any_return_type); + error( + node, + Diagnostics + .Call_signature_which_lacks_return_type_annotation_implicitly_has_an_any_return_type, + ); break; } } @@ -38811,15 +49574,36 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // interface BadGenerator extends Iterable, Iterator { } // function* g(): BadGenerator { } // Iterable and Iterator have different types! // - const generatorYieldType = getIterationTypeOfGeneratorFunctionReturnType(IterationTypeKind.Yield, returnType, (functionFlags & FunctionFlags.Async) !== 0) || anyType; - const generatorReturnType = getIterationTypeOfGeneratorFunctionReturnType(IterationTypeKind.Return, returnType, (functionFlags & FunctionFlags.Async) !== 0) || generatorYieldType; - const generatorNextType = getIterationTypeOfGeneratorFunctionReturnType(IterationTypeKind.Next, returnType, (functionFlags & FunctionFlags.Async) !== 0) || unknownType; - const generatorInstantiation = createGeneratorReturnType(generatorYieldType, generatorReturnType, generatorNextType, !!(functionFlags & FunctionFlags.Async)); + const generatorYieldType = getIterationTypeOfGeneratorFunctionReturnType( + IterationTypeKind.Yield, + returnType, + (functionFlags & FunctionFlags.Async) !== 0, + ) || anyType; + const generatorReturnType = getIterationTypeOfGeneratorFunctionReturnType( + IterationTypeKind.Return, + returnType, + (functionFlags & FunctionFlags.Async) !== 0, + ) || generatorYieldType; + const generatorNextType = getIterationTypeOfGeneratorFunctionReturnType( + IterationTypeKind.Next, + returnType, + (functionFlags & FunctionFlags.Async) !== 0, + ) || unknownType; + const generatorInstantiation = createGeneratorReturnType( + generatorYieldType, + generatorReturnType, + generatorNextType, + !!(functionFlags & FunctionFlags.Async), + ); checkTypeAssignableTo(generatorInstantiation, returnType, returnTypeErrorLocation); } } else if ((functionFlags & FunctionFlags.AsyncGenerator) === FunctionFlags.Async) { - checkAsyncFunctionReturnType(node as FunctionLikeDeclaration, returnTypeNode, returnTypeErrorLocation); + checkAsyncFunctionReturnType( + node as FunctionLikeDeclaration, + returnTypeNode, + returnTypeErrorLocation, + ); } } if (node.kind !== SyntaxKind.IndexSignature && node.kind !== SyntaxKind.JSDocFunctionType) { @@ -38849,9 +49633,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } const isPrivate = isPrivateIdentifier(name); const privateStaticFlags = isPrivate && isStaticMember ? DeclarationMeaning.PrivateStatic : 0; - const names = isPrivate ? privateIdentifiers : - isStaticMember ? staticNames : - instanceNames; + const names = isPrivate ? privateIdentifiers + : isStaticMember ? staticNames + : instanceNames; const memberName = name && getPropertyNameForPropertyNameNode(name); if (memberName) { @@ -38876,12 +49660,22 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } - function addName(names: Map<__String, DeclarationMeaning>, location: Node, name: __String, meaning: DeclarationMeaning) { + function addName( + names: Map<__String, DeclarationMeaning>, + location: Node, + name: __String, + meaning: DeclarationMeaning, + ) { const prev = names.get(name); if (prev) { // For private identifiers, do not allow mixing of static and instance members with the same name if ((prev & DeclarationMeaning.PrivateStatic) !== (meaning & DeclarationMeaning.PrivateStatic)) { - error(location, Diagnostics.Duplicate_identifier_0_Static_and_instance_elements_cannot_share_the_same_private_name, getTextOfNode(location)); + error( + location, + Diagnostics + .Duplicate_identifier_0_Static_and_instance_elements_cannot_share_the_same_private_name, + getTextOfNode(location), + ); } else { const prevIsMethod = !!(prev & DeclarationMeaning.Method); @@ -38933,7 +49727,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } // fall through case "prototype": - const message = Diagnostics.Static_property_0_conflicts_with_built_in_property_Function_0_of_constructor_function_1; + const message = Diagnostics + .Static_property_0_conflicts_with_built_in_property_Function_0_of_constructor_function_1; const className = getNameOfSymbolAsWritten(getSymbolOfDeclaration(node)); error(memberNameNode, message, memberName, className); break; @@ -38961,7 +49756,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } if (names.get(memberName)) { - error(getNameOfDeclaration(member.symbol.valueDeclaration), Diagnostics.Duplicate_identifier_0, memberName); + error( + getNameOfDeclaration(member.symbol.valueDeclaration), + Diagnostics.Duplicate_identifier_0, + memberName, + ); error(member.name, Diagnostics.Duplicate_identifier_0, memberName); } else { @@ -39018,8 +49817,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { setNodeLinksForPrivateIdentifierScope(node); // property signatures already report "initializer not allowed in ambient context" elsewhere - if (hasSyntacticModifier(node, ModifierFlags.Abstract) && node.kind === SyntaxKind.PropertyDeclaration && node.initializer) { - error(node, Diagnostics.Property_0_cannot_have_an_initializer_because_it_is_marked_abstract, declarationNameToString(node.name)); + if ( + hasSyntacticModifier(node, ModifierFlags.Abstract) && node.kind === SyntaxKind.PropertyDeclaration + && node.initializer + ) { + error( + node, + Diagnostics.Property_0_cannot_have_an_initializer_because_it_is_marked_abstract, + declarationNameToString(node.name), + ); } } @@ -39034,7 +49840,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // Grammar checking if (!checkGrammarMethod(node)) checkGrammarComputedPropertyName(node.name); - if (isMethodDeclaration(node) && node.asteriskToken && isIdentifier(node.name) && idText(node.name) === "constructor") { + if ( + isMethodDeclaration(node) && node.asteriskToken && isIdentifier(node.name) + && idText(node.name) === "constructor" + ) { error(node.name, Diagnostics.Class_constructor_may_not_be_a_generator); } @@ -39042,8 +49851,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { checkFunctionOrMethodDeclaration(node); // method signatures already report "implementation not allowed in ambient context" elsewhere - if (hasSyntacticModifier(node, ModifierFlags.Abstract) && node.kind === SyntaxKind.MethodDeclaration && node.body) { - error(node, Diagnostics.Method_0_cannot_have_an_implementation_because_it_is_marked_abstract, declarationNameToString(node.name)); + if ( + hasSyntacticModifier(node, ModifierFlags.Abstract) && node.kind === SyntaxKind.MethodDeclaration + && node.body + ) { + error( + node, + Diagnostics.Method_0_cannot_have_an_implementation_because_it_is_marked_abstract, + declarationNameToString(node.name), + ); } // Private named methods are only allowed in class declarations @@ -39054,9 +49870,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { setNodeLinksForPrivateIdentifierScope(node); } - function setNodeLinksForPrivateIdentifierScope(node: PropertyDeclaration | PropertySignature | MethodDeclaration | MethodSignature | AccessorDeclaration) { + function setNodeLinksForPrivateIdentifierScope( + node: PropertyDeclaration | PropertySignature | MethodDeclaration | MethodSignature | AccessorDeclaration, + ) { if (isPrivateIdentifier(node.name) && languageVersion < ScriptTarget.ESNext) { - for (let lexicalScope = getEnclosingBlockScopeContainer(node); !!lexicalScope; lexicalScope = getEnclosingBlockScopeContainer(lexicalScope)) { + for ( + let lexicalScope = getEnclosingBlockScopeContainer(node); + !!lexicalScope; + lexicalScope = getEnclosingBlockScopeContainer(lexicalScope) + ) { getNodeLinks(lexicalScope).flags |= NodeCheckFlags.ContainsClassWithPrivateIdentifiers; } @@ -39067,7 +49889,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const enclosingIterationStatement = getEnclosingIterationStatement(node.parent); if (enclosingIterationStatement) { getNodeLinks(node.name).flags |= NodeCheckFlags.BlockScopedBindingInLoop; - getNodeLinks(enclosingIterationStatement).flags |= NodeCheckFlags.LoopWithCapturedBlockScopedBinding; + getNodeLinks(enclosingIterationStatement).flags |= + NodeCheckFlags.LoopWithCapturedBlockScopedBinding; } } } @@ -39108,9 +49931,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (isPrivateIdentifierClassElementDeclaration(n)) { return true; } - return n.kind === SyntaxKind.PropertyDeclaration && - !isStatic(n) && - !!(n as PropertyDeclaration).initializer; + return n.kind === SyntaxKind.PropertyDeclaration + && !isStatic(n) + && !!(n as PropertyDeclaration).initializer; } function checkConstructorDeclarationDiagnostics() { @@ -39124,7 +49947,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const superCall = findFirstSuperCall(node.body!); if (superCall) { if (classExtendsNull) { - error(superCall, Diagnostics.A_constructor_cannot_contain_a_super_call_when_its_class_extends_null); + error( + superCall, + Diagnostics.A_constructor_cannot_contain_a_super_call_when_its_class_extends_null, + ); } // A super call must be root-level in a constructor if both of the following are true: @@ -39132,22 +49958,35 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // - The constructor declares parameter properties // or the containing class declares instance member variables with initializers. - const superCallShouldBeRootLevel = !emitStandardClassFields && - (some((node.parent as ClassDeclaration).members, isInstancePropertyWithInitializerOrPrivateIdentifierProperty) || - some(node.parameters, p => hasSyntacticModifier(p, ModifierFlags.ParameterPropertyModifier))); + const superCallShouldBeRootLevel = !emitStandardClassFields + && (some( + (node.parent as ClassDeclaration).members, + isInstancePropertyWithInitializerOrPrivateIdentifierProperty, + ) + || some( + node.parameters, + p => hasSyntacticModifier(p, ModifierFlags.ParameterPropertyModifier), + )); if (superCallShouldBeRootLevel) { // Until we have better flow analysis, it is an error to place the super call within any kind of block or conditional // See GH #8277 if (!superCallIsRootLevelInConstructor(superCall, node.body!)) { - error(superCall, Diagnostics.A_super_call_must_be_a_root_level_statement_within_a_constructor_of_a_derived_class_that_contains_initialized_properties_parameter_properties_or_private_identifiers); + error( + superCall, + Diagnostics + .A_super_call_must_be_a_root_level_statement_within_a_constructor_of_a_derived_class_that_contains_initialized_properties_parameter_properties_or_private_identifiers, + ); } // Skip past any prologue directives to check statements for referring to 'super' or 'this' before a super call else { let superCallStatement: ExpressionStatement | undefined; for (const statement of node.body!.statements) { - if (isExpressionStatement(statement) && isSuperCall(skipOuterExpressions(statement.expression))) { + if ( + isExpressionStatement(statement) + && isSuperCall(skipOuterExpressions(statement.expression)) + ) { superCallStatement = statement; break; } @@ -39159,7 +49998,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // Until we have better flow analysis, it is an error to place the super call within any kind of block or conditional // See GH #8277 if (superCallStatement === undefined) { - error(node, Diagnostics.A_super_call_must_be_the_first_statement_in_the_constructor_to_refer_to_super_or_this_when_a_derived_class_contains_initialized_properties_parameter_properties_or_private_identifiers); + error( + node, + Diagnostics + .A_super_call_must_be_the_first_statement_in_the_constructor_to_refer_to_super_or_this_when_a_derived_class_contains_initialized_properties_parameter_properties_or_private_identifiers, + ); } } } @@ -39198,12 +50041,17 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function checkAccessorDeclarationDiagnostics() { // Grammar checking accessors - if (!checkGrammarFunctionLikeDeclaration(node) && !checkGrammarAccessor(node)) checkGrammarComputedPropertyName(node.name); + if (!checkGrammarFunctionLikeDeclaration(node) && !checkGrammarAccessor(node)) { + checkGrammarComputedPropertyName(node.name); + } checkDecorators(node); checkSignatureDeclaration(node); if (node.kind === SyntaxKind.GetAccessor) { - if (!(node.flags & NodeFlags.Ambient) && nodeIsPresent(node.body) && (node.flags & NodeFlags.HasImplicitReturn)) { + if ( + !(node.flags & NodeFlags.Ambient) && nodeIsPresent(node.body) + && (node.flags & NodeFlags.HasImplicitReturn) + ) { if (!(node.flags & NodeFlags.HasExplicitReturn)) { error(node.name, Diagnostics.A_get_accessor_must_return_a_value); } @@ -39231,8 +50079,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { error(setter.name, Diagnostics.Accessors_must_both_be_abstract_or_non_abstract); } if ( - ((getterFlags & ModifierFlags.Protected) && !(setterFlags & (ModifierFlags.Protected | ModifierFlags.Private))) || - ((getterFlags & ModifierFlags.Private) && !(setterFlags & ModifierFlags.Private)) + ((getterFlags & ModifierFlags.Protected) + && !(setterFlags & (ModifierFlags.Protected | ModifierFlags.Private))) + || ((getterFlags & ModifierFlags.Private) && !(setterFlags & ModifierFlags.Private)) ) { error(getter.name, Diagnostics.A_get_accessor_must_be_at_least_as_accessible_as_the_setter); error(setter.name, Diagnostics.A_get_accessor_must_be_at_least_as_accessible_as_the_setter); @@ -39250,18 +50099,33 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { checkDecorators(node); } - function getEffectiveTypeArgumentAtIndex(node: TypeReferenceNode | ExpressionWithTypeArguments, typeParameters: readonly TypeParameter[], index: number): Type { + function getEffectiveTypeArgumentAtIndex( + node: TypeReferenceNode | ExpressionWithTypeArguments, + typeParameters: readonly TypeParameter[], + index: number, + ): Type { if (node.typeArguments && index < node.typeArguments.length) { return getTypeFromTypeNode(node.typeArguments[index]); } return getEffectiveTypeArguments(node, typeParameters)[index]; } - function getEffectiveTypeArguments(node: TypeReferenceNode | ExpressionWithTypeArguments | NodeWithTypeArguments, typeParameters: readonly TypeParameter[]): Type[] { - return fillMissingTypeArguments(map(node.typeArguments!, getTypeFromTypeNode), typeParameters, getMinTypeArgumentCount(typeParameters), isInJSFile(node)); + function getEffectiveTypeArguments( + node: TypeReferenceNode | ExpressionWithTypeArguments | NodeWithTypeArguments, + typeParameters: readonly TypeParameter[], + ): Type[] { + return fillMissingTypeArguments( + map(node.typeArguments!, getTypeFromTypeNode), + typeParameters, + getMinTypeArgumentCount(typeParameters), + isInJSFile(node), + ); } - function checkTypeArgumentConstraints(node: TypeReferenceNode | ExpressionWithTypeArguments | NodeWithTypeArguments, typeParameters: readonly TypeParameter[]): boolean { + function checkTypeArgumentConstraints( + node: TypeReferenceNode | ExpressionWithTypeArguments | NodeWithTypeArguments, + typeParameters: readonly TypeParameter[], + ): boolean { let typeArguments: Type[] | undefined; let mapper: TypeMapper | undefined; let result = true; @@ -39285,13 +50149,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function getTypeParametersForTypeAndSymbol(type: Type, symbol: Symbol) { if (!isErrorType(type)) { - return symbol.flags & SymbolFlags.TypeAlias && getSymbolLinks(symbol).typeParameters || - (getObjectFlags(type) & ObjectFlags.Reference ? (type as TypeReference).target.localTypeParameters : undefined); + return symbol.flags & SymbolFlags.TypeAlias && getSymbolLinks(symbol).typeParameters + || (getObjectFlags(type) & ObjectFlags.Reference ? (type as TypeReference).target.localTypeParameters + : undefined); } return undefined; } - function getTypeParametersForTypeReferenceOrImport(node: TypeReferenceNode | ExpressionWithTypeArguments | ImportTypeNode) { + function getTypeParametersForTypeReferenceOrImport( + node: TypeReferenceNode | ExpressionWithTypeArguments | ImportTypeNode, + ) { const type = getTypeFromTypeNode(node); if (!isErrorType(type)) { const symbol = getNodeLinks(node).resolvedSymbol; @@ -39304,11 +50171,19 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function checkTypeReferenceNode(node: TypeReferenceNode | ExpressionWithTypeArguments) { checkGrammarTypeArguments(node, node.typeArguments); - if (node.kind === SyntaxKind.TypeReference && !isInJSFile(node) && !isInJSDoc(node) && node.typeArguments && node.typeName.end !== node.typeArguments.pos) { + if ( + node.kind === SyntaxKind.TypeReference && !isInJSFile(node) && !isInJSDoc(node) && node.typeArguments + && node.typeName.end !== node.typeArguments.pos + ) { // If there was a token between the type name and the type arguments, check if it was a DotToken const sourceFile = getSourceFileOfNode(node); if (scanTokenAtPosition(sourceFile, node.typeName.end) === SyntaxKind.DotToken) { - grammarErrorAtPos(node, skipTrivia(sourceFile.text, node.typeName.end), 1, Diagnostics.JSDoc_types_can_only_be_used_inside_documentation_comments); + grammarErrorAtPos( + node, + skipTrivia(sourceFile.text, node.typeName.end), + 1, + Diagnostics.JSDoc_types_can_only_be_used_inside_documentation_comments, + ); } } forEach(node.typeArguments, checkSourceElement); @@ -39345,7 +50220,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const typeParameters = getTypeParametersForTypeReferenceOrImport(typeReferenceNode); if (!typeParameters) return undefined; const constraint = getConstraintOfTypeParameter(typeParameters[typeReferenceNode.typeArguments!.indexOf(node)]); - return constraint && instantiateType(constraint, createTypeMapper(typeParameters, getEffectiveTypeArguments(typeReferenceNode, typeParameters))); + return constraint + && instantiateType( + constraint, + createTypeMapper(typeParameters, getEffectiveTypeArguments(typeReferenceNode, typeParameters)), + ); } function checkTypeQuery(node: TypeQueryNode) { @@ -39421,8 +50300,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const indexType = (type as IndexedAccessType).indexType; if (isTypeAssignableTo(indexType, getIndexType(objectType, IndexFlags.None))) { if ( - accessNode.kind === SyntaxKind.ElementAccessExpression && isAssignmentTarget(accessNode) && - getObjectFlags(objectType) & ObjectFlags.Mapped && getMappedTypeModifiers(objectType as MappedType) & MappedTypeModifiers.IncludeReadonly + accessNode.kind === SyntaxKind.ElementAccessExpression && isAssignmentTarget(accessNode) + && getObjectFlags(objectType) & ObjectFlags.Mapped + && getMappedTypeModifiers(objectType as MappedType) & MappedTypeModifiers.IncludeReadonly ) { error(accessNode, Diagnostics.Index_signature_in_type_0_only_permits_reading, typeToString(objectType)); } @@ -39431,20 +50311,36 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // Check if we're indexing with a numeric type and if either object or index types // is a generic type with a constraint that has a numeric index signature. const apparentObjectType = getApparentType(objectType); - if (getIndexInfoOfType(apparentObjectType, numberType) && isTypeAssignableToKind(indexType, TypeFlags.NumberLike)) { + if ( + getIndexInfoOfType(apparentObjectType, numberType) + && isTypeAssignableToKind(indexType, TypeFlags.NumberLike) + ) { return type; } if (isGenericObjectType(objectType)) { const propertyName = getPropertyNameFromIndex(indexType, accessNode); if (propertyName) { const propertySymbol = forEachType(apparentObjectType, t => getPropertyOfType(t, propertyName)); - if (propertySymbol && getDeclarationModifierFlagsFromSymbol(propertySymbol) & ModifierFlags.NonPublicAccessibilityModifier) { - error(accessNode, Diagnostics.Private_or_protected_member_0_cannot_be_accessed_on_a_type_parameter, unescapeLeadingUnderscores(propertyName)); + if ( + propertySymbol + && getDeclarationModifierFlagsFromSymbol(propertySymbol) + & ModifierFlags.NonPublicAccessibilityModifier + ) { + error( + accessNode, + Diagnostics.Private_or_protected_member_0_cannot_be_accessed_on_a_type_parameter, + unescapeLeadingUnderscores(propertyName), + ); return errorType; } } } - error(accessNode, Diagnostics.Type_0_cannot_be_used_to_index_type_1, typeToString(indexType), typeToString(objectType)); + error( + accessNode, + Diagnostics.Type_0_cannot_be_used_to_index_type_1, + typeToString(indexType), + typeToString(objectType), + ); return errorType; } @@ -39471,7 +50367,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } else { const constraintType = getConstraintTypeFromMappedType(type); - checkTypeAssignableTo(constraintType, keyofConstraintType, getEffectiveConstraintOfTypeParameter(node.typeParameter)); + checkTypeAssignableTo( + constraintType, + keyofConstraintType, + getEffectiveConstraintOfTypeParameter(node.typeParameter), + ); } } @@ -39495,8 +50395,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function checkInferType(node: InferTypeNode) { - if (!findAncestor(node, n => n.parent && n.parent.kind === SyntaxKind.ConditionalType && (n.parent as ConditionalTypeNode).extendsType === n)) { - grammarErrorOnNode(node, Diagnostics.infer_declarations_are_only_permitted_in_the_extends_clause_of_a_conditional_type); + if ( + !findAncestor(node, n => + n.parent && n.parent.kind === SyntaxKind.ConditionalType + && (n.parent as ConditionalTypeNode).extendsType === n) + ) { + grammarErrorOnNode( + node, + Diagnostics.infer_declarations_are_only_permitted_in_the_extends_clause_of_a_conditional_type, + ); } checkSourceElement(node.typeParameter); const symbol = getSymbolOfDeclaration(node.typeParameter); @@ -39505,12 +50412,19 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (!links.typeParametersChecked) { links.typeParametersChecked = true; const typeParameter = getDeclaredTypeOfTypeParameter(symbol); - const declarations: TypeParameterDeclaration[] = getDeclarationsOfKind(symbol, SyntaxKind.TypeParameter); + const declarations: TypeParameterDeclaration[] = getDeclarationsOfKind( + symbol, + SyntaxKind.TypeParameter, + ); if (!areTypeParametersIdentical(declarations, [typeParameter], decl => [decl])) { // Report an error on every conflicting declaration. const name = symbolToString(symbol); for (const declaration of declarations) { - error(declaration.name, Diagnostics.All_declarations_of_0_must_have_identical_constraints, name); + error( + declaration.name, + Diagnostics.All_declarations_of_0_must_have_identical_constraints, + name, + ); } } } @@ -39534,10 +50448,21 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const override = getResolutionModeOverrideForClause(node.assertions.assertClause, grammarErrorOnNode); if (override) { if (!isNightly()) { - grammarErrorOnNode(node.assertions.assertClause, Diagnostics.resolution_mode_assertions_are_unstable_Use_nightly_TypeScript_to_silence_this_error_Try_updating_with_npm_install_D_typescript_next); + grammarErrorOnNode( + node.assertions.assertClause, + Diagnostics + .resolution_mode_assertions_are_unstable_Use_nightly_TypeScript_to_silence_this_error_Try_updating_with_npm_install_D_typescript_next, + ); } - if (getEmitModuleResolutionKind(compilerOptions) !== ModuleResolutionKind.Node16 && getEmitModuleResolutionKind(compilerOptions) !== ModuleResolutionKind.NodeNext) { - grammarErrorOnNode(node.assertions.assertClause, Diagnostics.resolution_mode_assertions_are_only_supported_when_moduleResolution_is_node16_or_nodenext); + if ( + getEmitModuleResolutionKind(compilerOptions) !== ModuleResolutionKind.Node16 + && getEmitModuleResolutionKind(compilerOptions) !== ModuleResolutionKind.NodeNext + ) { + grammarErrorOnNode( + node.assertions.assertClause, + Diagnostics + .resolution_mode_assertions_are_only_supported_when_moduleResolution_is_node16_or_nodenext, + ); } } } @@ -39550,17 +50475,26 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { grammarErrorOnNode(node, Diagnostics.A_tuple_member_cannot_be_both_optional_and_rest); } if (node.type.kind === SyntaxKind.OptionalType) { - grammarErrorOnNode(node.type, Diagnostics.A_labeled_tuple_element_is_declared_as_optional_with_a_question_mark_after_the_name_and_before_the_colon_rather_than_after_the_type); + grammarErrorOnNode( + node.type, + Diagnostics + .A_labeled_tuple_element_is_declared_as_optional_with_a_question_mark_after_the_name_and_before_the_colon_rather_than_after_the_type, + ); } if (node.type.kind === SyntaxKind.RestType) { - grammarErrorOnNode(node.type, Diagnostics.A_labeled_tuple_element_is_declared_as_rest_with_a_before_the_name_rather_than_before_the_type); + grammarErrorOnNode( + node.type, + Diagnostics + .A_labeled_tuple_element_is_declared_as_rest_with_a_before_the_name_rather_than_before_the_type, + ); } checkSourceElement(node.type); getTypeFromTypeNode(node); } function isPrivateWithinAmbient(node: Node): boolean { - return (hasEffectiveModifier(node, ModifierFlags.Private) || isPrivateIdentifierClassElementDeclaration(node)) && !!(node.flags & NodeFlags.Ambient); + return (hasEffectiveModifier(node, ModifierFlags.Private) || isPrivateIdentifierClassElementDeclaration(node)) + && !!(node.flags & NodeFlags.Ambient); } function getEffectiveDeclarationFlags(n: Declaration, flagsToCheck: ModifierFlags): ModifierFlags { @@ -39569,13 +50503,17 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // children of classes (even ambient classes) should not be marked as ambient or export // because those flags have no useful semantics there. if ( - n.parent.kind !== SyntaxKind.InterfaceDeclaration && - n.parent.kind !== SyntaxKind.ClassDeclaration && - n.parent.kind !== SyntaxKind.ClassExpression && - n.flags & NodeFlags.Ambient + n.parent.kind !== SyntaxKind.InterfaceDeclaration + && n.parent.kind !== SyntaxKind.ClassDeclaration + && n.parent.kind !== SyntaxKind.ClassExpression + && n.flags & NodeFlags.Ambient ) { const container = getEnclosingContainer(n); - if ((container && container.flags & NodeFlags.ExportContext) && !(flags & ModifierFlags.Ambient) && !(isModuleBlock(n.parent) && isModuleDeclaration(n.parent.parent) && isGlobalScopeAugmentation(n.parent.parent))) { + if ( + (container && container.flags & NodeFlags.ExportContext) && !(flags & ModifierFlags.Ambient) + && !(isModuleBlock(n.parent) && isModuleDeclaration(n.parent.parent) + && isGlobalScopeAugmentation(n.parent.parent)) + ) { // It is nested in an ambient export context, which means it is automatically exported flags |= ModifierFlags.Export; } @@ -39590,53 +50528,87 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function checkFunctionOrConstructorSymbolWorker(symbol: Symbol): void { - function getCanonicalOverload(overloads: Declaration[], implementation: FunctionLikeDeclaration | undefined): Declaration { + function getCanonicalOverload( + overloads: Declaration[], + implementation: FunctionLikeDeclaration | undefined, + ): Declaration { // Consider the canonical set of flags to be the flags of the bodyDeclaration or the first declaration // Error on all deviations from this canonical set of flags // The caveat is that if some overloads are defined in lib.d.ts, we don't want to // report the errors on those. To achieve this, we will say that the implementation is // the canonical signature only if it is in the same container as the first overload - const implementationSharesContainerWithFirstOverload = implementation !== undefined && implementation.parent === overloads[0].parent; + const implementationSharesContainerWithFirstOverload = implementation !== undefined + && implementation.parent === overloads[0].parent; return implementationSharesContainerWithFirstOverload ? implementation : overloads[0]; } - function checkFlagAgreementBetweenOverloads(overloads: Declaration[], implementation: FunctionLikeDeclaration | undefined, flagsToCheck: ModifierFlags, someOverloadFlags: ModifierFlags, allOverloadFlags: ModifierFlags): void { + function checkFlagAgreementBetweenOverloads( + overloads: Declaration[], + implementation: FunctionLikeDeclaration | undefined, + flagsToCheck: ModifierFlags, + someOverloadFlags: ModifierFlags, + allOverloadFlags: ModifierFlags, + ): void { // Error if some overloads have a flag that is not shared by all overloads. To find the // deviations, we XOR someOverloadFlags with allOverloadFlags const someButNotAllOverloadFlags = someOverloadFlags ^ allOverloadFlags; if (someButNotAllOverloadFlags !== 0) { - const canonicalFlags = getEffectiveDeclarationFlags(getCanonicalOverload(overloads, implementation), flagsToCheck); + const canonicalFlags = getEffectiveDeclarationFlags( + getCanonicalOverload(overloads, implementation), + flagsToCheck, + ); forEach(overloads, o => { const deviation = getEffectiveDeclarationFlags(o, flagsToCheck) ^ canonicalFlags; if (deviation & ModifierFlags.Export) { - error(getNameOfDeclaration(o), Diagnostics.Overload_signatures_must_all_be_exported_or_non_exported); + error( + getNameOfDeclaration(o), + Diagnostics.Overload_signatures_must_all_be_exported_or_non_exported, + ); } else if (deviation & ModifierFlags.Ambient) { - error(getNameOfDeclaration(o), Diagnostics.Overload_signatures_must_all_be_ambient_or_non_ambient); + error( + getNameOfDeclaration(o), + Diagnostics.Overload_signatures_must_all_be_ambient_or_non_ambient, + ); } else if (deviation & (ModifierFlags.Private | ModifierFlags.Protected)) { - error(getNameOfDeclaration(o) || o, Diagnostics.Overload_signatures_must_all_be_public_private_or_protected); + error( + getNameOfDeclaration(o) || o, + Diagnostics.Overload_signatures_must_all_be_public_private_or_protected, + ); } else if (deviation & ModifierFlags.Abstract) { - error(getNameOfDeclaration(o), Diagnostics.Overload_signatures_must_all_be_abstract_or_non_abstract); + error( + getNameOfDeclaration(o), + Diagnostics.Overload_signatures_must_all_be_abstract_or_non_abstract, + ); } }); } } - function checkQuestionTokenAgreementBetweenOverloads(overloads: Declaration[], implementation: FunctionLikeDeclaration | undefined, someHaveQuestionToken: boolean, allHaveQuestionToken: boolean): void { + function checkQuestionTokenAgreementBetweenOverloads( + overloads: Declaration[], + implementation: FunctionLikeDeclaration | undefined, + someHaveQuestionToken: boolean, + allHaveQuestionToken: boolean, + ): void { if (someHaveQuestionToken !== allHaveQuestionToken) { const canonicalHasQuestionToken = hasQuestionToken(getCanonicalOverload(overloads, implementation)); forEach(overloads, o => { const deviation = hasQuestionToken(o) !== canonicalHasQuestionToken; if (deviation) { - error(getNameOfDeclaration(o), Diagnostics.Overload_signatures_must_all_be_optional_or_required); + error( + getNameOfDeclaration(o), + Diagnostics.Overload_signatures_must_all_be_optional_or_required, + ); } }); } } - const flagsToCheck: ModifierFlags = ModifierFlags.Export | ModifierFlags.Ambient | ModifierFlags.Private | ModifierFlags.Protected | ModifierFlags.Abstract; + const flagsToCheck: ModifierFlags = ModifierFlags.Export | ModifierFlags.Ambient | ModifierFlags.Private + | ModifierFlags.Protected | ModifierFlags.Abstract; let someNodeFlags: ModifierFlags = ModifierFlags.None; let allNodeFlags = flagsToCheck; let someHaveQuestionToken = false; @@ -39672,28 +50644,40 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if ( node.name && subsequentName && ( // both are private identifiers - isPrivateIdentifier(node.name) && isPrivateIdentifier(subsequentName) && node.name.escapedText === subsequentName.escapedText || + isPrivateIdentifier(node.name) && isPrivateIdentifier(subsequentName) + && node.name.escapedText === subsequentName.escapedText // Both are computed property names - isComputedPropertyName(node.name) && isComputedPropertyName(subsequentName) && isTypeIdenticalTo(checkComputedPropertyName(node.name), checkComputedPropertyName(subsequentName)) || + || isComputedPropertyName(node.name) && isComputedPropertyName(subsequentName) + && isTypeIdenticalTo( + checkComputedPropertyName(node.name), + checkComputedPropertyName(subsequentName), + ) // Both are literal property names that are the same. - isPropertyNameLiteral(node.name) && isPropertyNameLiteral(subsequentName) && - getEscapedTextOfIdentifierOrLiteral(node.name) === getEscapedTextOfIdentifierOrLiteral(subsequentName) + || isPropertyNameLiteral(node.name) && isPropertyNameLiteral(subsequentName) + && getEscapedTextOfIdentifierOrLiteral(node.name) + === getEscapedTextOfIdentifierOrLiteral(subsequentName) ) ) { - const reportError = (node.kind === SyntaxKind.MethodDeclaration || node.kind === SyntaxKind.MethodSignature) && - isStatic(node) !== isStatic(subsequentNode); + const reportError = + (node.kind === SyntaxKind.MethodDeclaration || node.kind === SyntaxKind.MethodSignature) + && isStatic(node) !== isStatic(subsequentNode); // we can get here in two cases // 1. mixed static and instance class members // 2. something with the same name was defined before the set of overloads that prevents them from merging // here we'll report error only for the first case since for second we should already report error in binder if (reportError) { - const diagnostic = isStatic(node) ? Diagnostics.Function_overload_must_be_static : Diagnostics.Function_overload_must_not_be_static; + const diagnostic = isStatic(node) ? Diagnostics.Function_overload_must_be_static + : Diagnostics.Function_overload_must_not_be_static; error(errorNode, diagnostic); } return; } if (nodeIsPresent((subsequentNode as FunctionLikeDeclaration).body)) { - error(errorNode, Diagnostics.Function_implementation_name_must_be_0, declarationNameToString(node.name)); + error( + errorNode, + Diagnostics.Function_implementation_name_must_be_0, + declarationNameToString(node.name), + ); return; } } @@ -39709,7 +50693,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { error(errorNode, Diagnostics.All_declarations_of_an_abstract_method_must_be_consecutive); } else { - error(errorNode, Diagnostics.Function_implementation_is_missing_or_not_immediately_following_the_declaration); + error( + errorNode, + Diagnostics.Function_implementation_is_missing_or_not_immediately_following_the_declaration, + ); } } } @@ -39722,7 +50709,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { for (const current of declarations) { const node = current as SignatureDeclaration | ClassDeclaration | ClassExpression; const inAmbientContext = node.flags & NodeFlags.Ambient; - const inAmbientContextOrInterface = node.parent && (node.parent.kind === SyntaxKind.InterfaceDeclaration || node.parent.kind === SyntaxKind.TypeLiteral) || inAmbientContext; + const inAmbientContextOrInterface = node.parent + && (node.parent.kind === SyntaxKind.InterfaceDeclaration + || node.parent.kind === SyntaxKind.TypeLiteral) || inAmbientContext; if (inAmbientContextOrInterface) { // check if declarations are consecutive only if they are non-ambient // 1. ambient declarations can be interleaved @@ -39734,11 +50723,17 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { previousDeclaration = undefined; } - if ((node.kind === SyntaxKind.ClassDeclaration || node.kind === SyntaxKind.ClassExpression) && !inAmbientContext) { + if ( + (node.kind === SyntaxKind.ClassDeclaration || node.kind === SyntaxKind.ClassExpression) + && !inAmbientContext + ) { hasNonAmbientClass = true; } - if (node.kind === SyntaxKind.FunctionDeclaration || node.kind === SyntaxKind.MethodDeclaration || node.kind === SyntaxKind.MethodSignature || node.kind === SyntaxKind.Constructor) { + if ( + node.kind === SyntaxKind.FunctionDeclaration || node.kind === SyntaxKind.MethodDeclaration + || node.kind === SyntaxKind.MethodSignature || node.kind === SyntaxKind.Constructor + ) { functionDeclarations.push(node); const currentNodeFlags = getEffectiveDeclarationFlags(node, flagsToCheck); someNodeFlags |= currentNodeFlags; @@ -39821,16 +50816,28 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // Abstract methods can't have an implementation -- in particular, they don't need one. if ( - lastSeenNonAmbientDeclaration && !lastSeenNonAmbientDeclaration.body && - !hasSyntacticModifier(lastSeenNonAmbientDeclaration, ModifierFlags.Abstract) && !lastSeenNonAmbientDeclaration.questionToken + lastSeenNonAmbientDeclaration && !lastSeenNonAmbientDeclaration.body + && !hasSyntacticModifier(lastSeenNonAmbientDeclaration, ModifierFlags.Abstract) + && !lastSeenNonAmbientDeclaration.questionToken ) { reportImplementationExpectedError(lastSeenNonAmbientDeclaration); } if (hasOverloads) { if (declarations) { - checkFlagAgreementBetweenOverloads(declarations, bodyDeclaration, flagsToCheck, someNodeFlags, allNodeFlags); - checkQuestionTokenAgreementBetweenOverloads(declarations, bodyDeclaration, someHaveQuestionToken, allHaveQuestionToken); + checkFlagAgreementBetweenOverloads( + declarations, + bodyDeclaration, + flagsToCheck, + someNodeFlags, + allNodeFlags, + ); + checkQuestionTokenAgreementBetweenOverloads( + declarations, + bodyDeclaration, + someHaveQuestionToken, + allHaveQuestionToken, + ); } if (bodyDeclaration) { @@ -39842,8 +50849,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { ? (signature.declaration.parent as JSDocOverloadTag | JSDocCallbackTag).tagName : signature.declaration; addRelatedInfo( - error(errorNode, Diagnostics.This_overload_signature_is_not_compatible_with_its_implementation_signature), - createDiagnosticForNode(bodyDeclaration, Diagnostics.The_implementation_signature_is_declared_here), + error( + errorNode, + Diagnostics.This_overload_signature_is_not_compatible_with_its_implementation_signature, + ), + createDiagnosticForNode( + bodyDeclaration, + Diagnostics.The_implementation_signature_is_declared_here, + ), ); break; } @@ -39879,7 +50892,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { let defaultExportedDeclarationSpaces = DeclarationSpaces.None; for (const d of symbol.declarations!) { const declarationSpaces = getDeclarationSpaces(d); - const effectiveDeclarationFlags = getEffectiveDeclarationFlags(d, ModifierFlags.Export | ModifierFlags.Default); + const effectiveDeclarationFlags = getEffectiveDeclarationFlags( + d, + ModifierFlags.Export | ModifierFlags.Default, + ); if (effectiveDeclarationFlags & ModifierFlags.Export) { if (effectiveDeclarationFlags & ModifierFlags.Default) { @@ -39898,7 +50914,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const nonDefaultExportedDeclarationSpaces = exportedDeclarationSpaces | nonExportedDeclarationSpaces; const commonDeclarationSpacesForExportsAndLocals = exportedDeclarationSpaces & nonExportedDeclarationSpaces; - const commonDeclarationSpacesForDefaultAndNonDefault = defaultExportedDeclarationSpaces & nonDefaultExportedDeclarationSpaces; + const commonDeclarationSpacesForDefaultAndNonDefault = defaultExportedDeclarationSpaces + & nonDefaultExportedDeclarationSpaces; if (commonDeclarationSpacesForExportsAndLocals || commonDeclarationSpacesForDefaultAndNonDefault) { // declaration spaces for exported and non-exported declarations intersect @@ -39908,10 +50925,19 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const name = getNameOfDeclaration(d); // Only error on the declarations that contributed to the intersecting spaces. if (declarationSpaces & commonDeclarationSpacesForDefaultAndNonDefault) { - error(name, Diagnostics.Merged_declaration_0_cannot_include_a_default_export_declaration_Consider_adding_a_separate_export_default_0_declaration_instead, declarationNameToString(name)); + error( + name, + Diagnostics + .Merged_declaration_0_cannot_include_a_default_export_declaration_Consider_adding_a_separate_export_default_0_declaration_instead, + declarationNameToString(name), + ); } else if (declarationSpaces & commonDeclarationSpacesForExportsAndLocals) { - error(name, Diagnostics.Individual_declarations_in_merged_declaration_0_must_be_all_exported_or_all_local, declarationNameToString(name)); + error( + name, + Diagnostics.Individual_declarations_in_merged_declaration_0_must_be_all_exported_or_all_local, + declarationNameToString(name), + ); } } } @@ -39929,7 +50955,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { case SyntaxKind.JSDocEnumTag: return DeclarationSpaces.ExportType; case SyntaxKind.ModuleDeclaration: - return isAmbientModule(d as ModuleDeclaration) || getModuleInstanceState(d as ModuleDeclaration) !== ModuleInstanceState.NonInstantiated + return isAmbientModule(d as ModuleDeclaration) + || getModuleInstanceState(d as ModuleDeclaration) !== ModuleInstanceState.NonInstantiated ? DeclarationSpaces.ExportNamespace | DeclarationSpaces.ExportValue : DeclarationSpaces.ExportNamespace; case SyntaxKind.ClassDeclaration: @@ -39937,7 +50964,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { case SyntaxKind.EnumMember: return DeclarationSpaces.ExportType | DeclarationSpaces.ExportValue; case SyntaxKind.SourceFile: - return DeclarationSpaces.ExportType | DeclarationSpaces.ExportValue | DeclarationSpaces.ExportNamespace; + return DeclarationSpaces.ExportType | DeclarationSpaces.ExportValue + | DeclarationSpaces.ExportNamespace; case SyntaxKind.ExportAssignment: case SyntaxKind.BinaryExpression: const node = d as ExportAssignment | BinaryExpression; @@ -39954,7 +50982,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { case SyntaxKind.NamespaceImport: case SyntaxKind.ImportClause: let result = DeclarationSpaces.None; - const target = resolveAlias(getSymbolOfDeclaration(d as ImportEqualsDeclaration | NamespaceImport | ImportClause | ExportAssignment | BinaryExpression)!); + const target = resolveAlias( + getSymbolOfDeclaration( + d as + | ImportEqualsDeclaration + | NamespaceImport + | ImportClause + | ExportAssignment + | BinaryExpression, + )!, + ); forEach(target.declarations, d => { result |= getDeclarationSpaces(d); }); @@ -39980,7 +51017,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } - function getAwaitedTypeOfPromise(type: Type, errorNode?: Node, diagnosticMessage?: DiagnosticMessage, ...args: DiagnosticArguments): Type | undefined { + function getAwaitedTypeOfPromise( + type: Type, + errorNode?: Node, + diagnosticMessage?: DiagnosticMessage, + ...args: DiagnosticArguments + ): Type | undefined { const promisedType = getPromisedTypeOfPromise(type, errorNode); return promisedType && getAwaitedType(promisedType, errorNode, diagnosticMessage, ...args); } @@ -39990,7 +51032,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { * @param type The type of the promise. * @remarks The "promised type" of a type is the type of the "value" parameter of the "onfulfilled" callback. */ - function getPromisedTypeOfPromise(type: Type, errorNode?: Node, thisTypeForErrorOut?: { value?: Type; }): Type | undefined { + function getPromisedTypeOfPromise( + type: Type, + errorNode?: Node, + thisTypeForErrorOut?: { value?: Type; }, + ): Type | undefined { // // { // type // then( // thenFunction @@ -40050,12 +51096,20 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { thisTypeForErrorOut.value = thisTypeForError; } if (errorNode) { - error(errorNode, Diagnostics.The_this_context_of_type_0_is_not_assignable_to_method_s_this_of_type_1, typeToString(type), typeToString(thisTypeForError)); + error( + errorNode, + Diagnostics.The_this_context_of_type_0_is_not_assignable_to_method_s_this_of_type_1, + typeToString(type), + typeToString(thisTypeForError), + ); } return undefined; } - const onfulfilledParameterType = getTypeWithFacts(getUnionType(map(candidates, getTypeOfFirstParameterOfSignature)), TypeFacts.NEUndefinedOrNull); + const onfulfilledParameterType = getTypeWithFacts( + getUnionType(map(candidates, getTypeOfFirstParameterOfSignature)), + TypeFacts.NEUndefinedOrNull, + ); if (isTypeAny(onfulfilledParameterType)) { return undefined; } @@ -40068,7 +51122,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return undefined; } - return typeAsPromise.promisedTypeOfPromise = getUnionType(map(onfulfilledParameterSignatures, getTypeOfFirstParameterOfSignature), UnionReduction.Subtype); + return typeAsPromise.promisedTypeOfPromise = getUnionType( + map(onfulfilledParameterSignatures, getTypeOfFirstParameterOfSignature), + UnionReduction.Subtype, + ); } /** @@ -40079,10 +51136,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { * Promise-like type; otherwise, it is the type of the expression. This is used to reflect * The runtime behavior of the `await` keyword. */ - function checkAwaitedType(type: Type, withAlias: boolean, errorNode: Node, diagnosticMessage: DiagnosticMessage, ...args: DiagnosticArguments): Type { - const awaitedType = withAlias ? - getAwaitedType(type, errorNode, diagnosticMessage, ...args) : - getAwaitedTypeNoAlias(type, errorNode, diagnosticMessage, ...args); + function checkAwaitedType( + type: Type, + withAlias: boolean, + errorNode: Node, + diagnosticMessage: DiagnosticMessage, + ...args: DiagnosticArguments + ): Type { + const awaitedType = withAlias + ? getAwaitedType(type, errorNode, diagnosticMessage, ...args) + : getAwaitedTypeNoAlias(type, errorNode, diagnosticMessage, ...args); return awaitedType || errorType; } @@ -40096,7 +51159,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } const thenFunction = getTypeOfPropertyOfType(type, "then" as __String); - return !!thenFunction && getSignaturesOfType(getTypeWithFacts(thenFunction, TypeFacts.NEUndefinedOrNull), SignatureKind.Call).length > 0; + return !!thenFunction + && getSignaturesOfType(getTypeWithFacts(thenFunction, TypeFacts.NEUndefinedOrNull), SignatureKind.Call) + .length > 0; } interface AwaitedTypeInstantiation extends Type { @@ -40117,9 +51182,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { * For a generic `Awaited`, gets `T`. */ function unwrapAwaitedType(type: Type) { - return type.flags & TypeFlags.Union ? mapType(type, unwrapAwaitedType) : - isAwaitedTypeInstantiation(type) ? type.aliasTypeArguments[0] : - type; + return type.flags & TypeFlags.Union ? mapType(type, unwrapAwaitedType) + : isAwaitedTypeInstantiation(type) ? type.aliasTypeArguments[0] + : type; } function isAwaitedTypeNeeded(type: Type) { @@ -40134,9 +51199,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // We only need `Awaited` if `T` is a type variable that has no base constraint, or the base constraint of `T` is `any`, `unknown`, `{}`, `object`, // or is promise-like. if ( - baseConstraint ? - baseConstraint.flags & TypeFlags.AnyOrUnknown || isEmptyObjectType(baseConstraint) || someType(baseConstraint, isThenableType) : - maybeTypeOfKind(type, TypeFlags.TypeVariable) + baseConstraint + ? baseConstraint.flags & TypeFlags.AnyOrUnknown || isEmptyObjectType(baseConstraint) + || someType(baseConstraint, isThenableType) + : maybeTypeOfKind(type, TypeFlags.TypeVariable) ) { return true; } @@ -40173,7 +51239,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } - Debug.assert(isAwaitedTypeInstantiation(type) || getPromisedTypeOfPromise(type) === undefined, "type provided should not be a non-generic 'promise'-like."); + Debug.assert( + isAwaitedTypeInstantiation(type) || getPromisedTypeOfPromise(type) === undefined, + "type provided should not be a non-generic 'promise'-like.", + ); return type; } @@ -40187,7 +51256,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { * * This is used to reflect the runtime behavior of the `await` keyword. */ - function getAwaitedType(type: Type, errorNode?: Node, diagnosticMessage?: DiagnosticMessage, ...args: DiagnosticArguments): Type | undefined { + function getAwaitedType( + type: Type, + errorNode?: Node, + diagnosticMessage?: DiagnosticMessage, + ...args: DiagnosticArguments + ): Type | undefined { const awaitedType = getAwaitedTypeNoAlias(type, errorNode, diagnosticMessage, ...args); return awaitedType && createAwaitedTypeIfNeeded(awaitedType); } @@ -40197,7 +51271,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { * * @see {@link getAwaitedType} */ - function getAwaitedTypeNoAlias(type: Type, errorNode?: Node, diagnosticMessage?: DiagnosticMessage, ...args: DiagnosticArguments): Type | undefined { + function getAwaitedTypeNoAlias( + type: Type, + errorNode?: Node, + diagnosticMessage?: DiagnosticMessage, + ...args: DiagnosticArguments + ): Type | undefined { if (isTypeAny(type)) { return type; } @@ -40217,12 +51296,17 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (type.flags & TypeFlags.Union) { if (awaitedTypeStack.lastIndexOf(type.id) >= 0) { if (errorNode) { - error(errorNode, Diagnostics.Type_is_referenced_directly_or_indirectly_in_the_fulfillment_callback_of_its_own_then_method); + error( + errorNode, + Diagnostics + .Type_is_referenced_directly_or_indirectly_in_the_fulfillment_callback_of_its_own_then_method, + ); } return undefined; } - const mapper = errorNode ? (constituentType: Type) => getAwaitedTypeNoAlias(constituentType, errorNode, diagnosticMessage, ...args) : getAwaitedTypeNoAlias; + const mapper = errorNode ? (constituentType: Type) => + getAwaitedTypeNoAlias(constituentType, errorNode, diagnosticMessage, ...args) : getAwaitedTypeNoAlias; awaitedTypeStack.push(type.id); const mapped = mapType(type, mapper); @@ -40274,7 +51358,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // } // if (errorNode) { - error(errorNode, Diagnostics.Type_is_referenced_directly_or_indirectly_in_the_fulfillment_callback_of_its_own_then_method); + error( + errorNode, + Diagnostics + .Type_is_referenced_directly_or_indirectly_in_the_fulfillment_callback_of_its_own_then_method, + ); } return undefined; } @@ -40312,10 +51400,17 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { Debug.assertIsDefined(diagnosticMessage); let chain: DiagnosticMessageChain | undefined; if (thisTypeForErrorOut.value) { - chain = chainDiagnosticMessages(chain, Diagnostics.The_this_context_of_type_0_is_not_assignable_to_method_s_this_of_type_1, typeToString(type), typeToString(thisTypeForErrorOut.value)); + chain = chainDiagnosticMessages( + chain, + Diagnostics.The_this_context_of_type_0_is_not_assignable_to_method_s_this_of_type_1, + typeToString(type), + typeToString(thisTypeForErrorOut.value), + ); } chain = chainDiagnosticMessages(chain, diagnosticMessage, ...args); - diagnostics.add(createDiagnosticForNodeFromMessageChain(getSourceFileOfNode(errorNode), errorNode, chain)); + diagnostics.add( + createDiagnosticForNodeFromMessageChain(getSourceFileOfNode(errorNode), errorNode, chain), + ); } return undefined; } @@ -40335,7 +51430,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { * * @param node The signature to check */ - function checkAsyncFunctionReturnType(node: FunctionLikeDeclaration | MethodSignature, returnTypeNode: TypeNode, returnTypeErrorLocation: TypeNode) { + function checkAsyncFunctionReturnType( + node: FunctionLikeDeclaration | MethodSignature, + returnTypeNode: TypeNode, + returnTypeErrorLocation: TypeNode, + ) { // As part of our emit for an async function, we will need to emit the entity name of // the return type annotation as an expression. To meet the necessary runtime semantics // for __awaiter, we must also check that the type of the declaration (e.g. the static @@ -40369,7 +51468,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (globalPromiseType !== emptyGenericType && !isReferenceToType(returnType, globalPromiseType)) { // The promise type was not a valid type reference to the global promise type, so we // report an error and return the unknown type. - reportErrorForInvalidReturnType(Diagnostics.The_return_type_of_an_async_function_or_method_must_be_the_global_Promise_T_type_Did_you_mean_to_write_Promise_0, returnTypeNode, returnTypeErrorLocation, typeToString(getAwaitedTypeNoAlias(returnType) || voidType)); + reportErrorForInvalidReturnType( + Diagnostics + .The_return_type_of_an_async_function_or_method_must_be_the_global_Promise_T_type_Did_you_mean_to_write_Promise_0, + returnTypeNode, + returnTypeErrorLocation, + typeToString(getAwaitedTypeNoAlias(returnType) || voidType), + ); return; } } @@ -40383,18 +51488,43 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const promiseConstructorName = getEntityNameFromTypeNode(returnTypeNode); if (promiseConstructorName === undefined) { - reportErrorForInvalidReturnType(Diagnostics.Type_0_is_not_a_valid_async_function_return_type_in_ES5_SlashES3_because_it_does_not_refer_to_a_Promise_compatible_constructor_value, returnTypeNode, returnTypeErrorLocation, typeToString(returnType)); + reportErrorForInvalidReturnType( + Diagnostics + .Type_0_is_not_a_valid_async_function_return_type_in_ES5_SlashES3_because_it_does_not_refer_to_a_Promise_compatible_constructor_value, + returnTypeNode, + returnTypeErrorLocation, + typeToString(returnType), + ); return; } - const promiseConstructorSymbol = resolveEntityName(promiseConstructorName, SymbolFlags.Value, /*ignoreErrors*/ true); - const promiseConstructorType = promiseConstructorSymbol ? getTypeOfSymbol(promiseConstructorSymbol) : errorType; + const promiseConstructorSymbol = resolveEntityName( + promiseConstructorName, + SymbolFlags.Value, + /*ignoreErrors*/ true, + ); + const promiseConstructorType = promiseConstructorSymbol ? getTypeOfSymbol(promiseConstructorSymbol) + : errorType; if (isErrorType(promiseConstructorType)) { - if (promiseConstructorName.kind === SyntaxKind.Identifier && promiseConstructorName.escapedText === "Promise" && getTargetType(returnType) === getGlobalPromiseType(/*reportErrors*/ false)) { - error(returnTypeErrorLocation, Diagnostics.An_async_function_or_method_in_ES5_SlashES3_requires_the_Promise_constructor_Make_sure_you_have_a_declaration_for_the_Promise_constructor_or_include_ES2015_in_your_lib_option); + if ( + promiseConstructorName.kind === SyntaxKind.Identifier + && promiseConstructorName.escapedText === "Promise" + && getTargetType(returnType) === getGlobalPromiseType(/*reportErrors*/ false) + ) { + error( + returnTypeErrorLocation, + Diagnostics + .An_async_function_or_method_in_ES5_SlashES3_requires_the_Promise_constructor_Make_sure_you_have_a_declaration_for_the_Promise_constructor_or_include_ES2015_in_your_lib_option, + ); } else { - reportErrorForInvalidReturnType(Diagnostics.Type_0_is_not_a_valid_async_function_return_type_in_ES5_SlashES3_because_it_does_not_refer_to_a_Promise_compatible_constructor_value, returnTypeNode, returnTypeErrorLocation, entityNameToString(promiseConstructorName)); + reportErrorForInvalidReturnType( + Diagnostics + .Type_0_is_not_a_valid_async_function_return_type_in_ES5_SlashES3_because_it_does_not_refer_to_a_Promise_compatible_constructor_value, + returnTypeNode, + returnTypeErrorLocation, + entityNameToString(promiseConstructorName), + ); } return; } @@ -40403,13 +51533,33 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (globalPromiseConstructorLikeType === emptyObjectType) { // If we couldn't resolve the global PromiseConstructorLike type we cannot verify // compatibility with __awaiter. - reportErrorForInvalidReturnType(Diagnostics.Type_0_is_not_a_valid_async_function_return_type_in_ES5_SlashES3_because_it_does_not_refer_to_a_Promise_compatible_constructor_value, returnTypeNode, returnTypeErrorLocation, entityNameToString(promiseConstructorName)); + reportErrorForInvalidReturnType( + Diagnostics + .Type_0_is_not_a_valid_async_function_return_type_in_ES5_SlashES3_because_it_does_not_refer_to_a_Promise_compatible_constructor_value, + returnTypeNode, + returnTypeErrorLocation, + entityNameToString(promiseConstructorName), + ); return; } - const headMessage = Diagnostics.Type_0_is_not_a_valid_async_function_return_type_in_ES5_SlashES3_because_it_does_not_refer_to_a_Promise_compatible_constructor_value; - const errorInfo = () => returnTypeNode === returnTypeErrorLocation ? undefined : chainDiagnosticMessages(/*details*/ undefined, Diagnostics.The_return_type_of_an_async_function_or_method_must_be_the_global_Promise_T_type); - if (!checkTypeAssignableTo(promiseConstructorType, globalPromiseConstructorLikeType, returnTypeErrorLocation, headMessage, errorInfo)) { + const headMessage = Diagnostics + .Type_0_is_not_a_valid_async_function_return_type_in_ES5_SlashES3_because_it_does_not_refer_to_a_Promise_compatible_constructor_value; + const errorInfo = () => + returnTypeNode === returnTypeErrorLocation ? undefined + : chainDiagnosticMessages( + /*details*/ undefined, + Diagnostics.The_return_type_of_an_async_function_or_method_must_be_the_global_Promise_T_type, + ); + if ( + !checkTypeAssignableTo( + promiseConstructorType, + globalPromiseConstructorLikeType, + returnTypeErrorLocation, + headMessage, + errorInfo, + ) + ) { return; } @@ -40417,19 +51567,38 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const rootName = promiseConstructorName && getFirstIdentifier(promiseConstructorName); const collidingSymbol = getSymbol(node.locals!, rootName.escapedText, SymbolFlags.Value); if (collidingSymbol) { - error(collidingSymbol.valueDeclaration, Diagnostics.Duplicate_identifier_0_Compiler_uses_declaration_1_to_support_async_functions, idText(rootName), entityNameToString(promiseConstructorName)); + error( + collidingSymbol.valueDeclaration, + Diagnostics.Duplicate_identifier_0_Compiler_uses_declaration_1_to_support_async_functions, + idText(rootName), + entityNameToString(promiseConstructorName), + ); return; } } - checkAwaitedType(returnType, /*withAlias*/ false, node, Diagnostics.The_return_type_of_an_async_function_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member); + checkAwaitedType( + returnType, + /*withAlias*/ false, + node, + Diagnostics + .The_return_type_of_an_async_function_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member, + ); - function reportErrorForInvalidReturnType(message: DiagnosticMessage, returnTypeNode: TypeNode, returnTypeErrorLocation: TypeNode, typeName: string) { + function reportErrorForInvalidReturnType( + message: DiagnosticMessage, + returnTypeNode: TypeNode, + returnTypeErrorLocation: TypeNode, + typeName: string, + ) { if (returnTypeNode === returnTypeErrorLocation) { error(returnTypeErrorLocation, message, typeName); } else { - const diag = error(returnTypeErrorLocation, Diagnostics.The_return_type_of_an_async_function_or_method_must_be_the_global_Promise_T_type); + const diag = error( + returnTypeErrorLocation, + Diagnostics.The_return_type_of_an_async_function_or_method_must_be_the_global_Promise_T_type, + ); addRelatedInfo(diag, createDiagnosticForNode(returnTypeNode, message, typeName)); } } @@ -40492,8 +51661,21 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { minArgumentCount: number = parameters.length, flags: SignatureFlags = SignatureFlags.None, ) { - const decl = factory.createFunctionTypeNode(/*typeParameters*/ undefined, emptyArray, factory.createKeywordTypeNode(SyntaxKind.AnyKeyword)); - return createSignature(decl, typeParameters, thisParameter, parameters, returnType, typePredicate, minArgumentCount, flags); + const decl = factory.createFunctionTypeNode( + /*typeParameters*/ undefined, + emptyArray, + factory.createKeywordTypeNode(SyntaxKind.AnyKeyword), + ); + return createSignature( + decl, + typeParameters, + thisParameter, + parameters, + returnType, + typePredicate, + minArgumentCount, + flags, + ); } /** @@ -40508,7 +51690,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { minArgumentCount?: number, flags?: SignatureFlags, ) { - const signature = createCallSignature(typeParameters, thisParameter, parameters, returnType, typePredicate, minArgumentCount, flags); + const signature = createCallSignature( + typeParameters, + thisParameter, + parameters, + returnType, + typePredicate, + minArgumentCount, + flags, + ); return getOrCreateTypeFromSignature(signature); } @@ -40526,15 +51716,29 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { * marked as referenced to prevent import elision. */ function markTypeNodeAsReferenced(node: TypeNode) { - markEntityNameOrEntityExpressionAsReference(node && getEntityNameFromTypeNode(node), /*forDecoratorMetadata*/ false); + markEntityNameOrEntityExpressionAsReference( + node && getEntityNameFromTypeNode(node), + /*forDecoratorMetadata*/ false, + ); } - function markEntityNameOrEntityExpressionAsReference(typeName: EntityNameOrEntityNameExpression | undefined, forDecoratorMetadata: boolean) { + function markEntityNameOrEntityExpressionAsReference( + typeName: EntityNameOrEntityNameExpression | undefined, + forDecoratorMetadata: boolean, + ) { if (!typeName) return; const rootName = getFirstIdentifier(typeName); - const meaning = (typeName.kind === SyntaxKind.Identifier ? SymbolFlags.Type : SymbolFlags.Namespace) | SymbolFlags.Alias; - const rootSymbol = resolveName(rootName, rootName.escapedText, meaning, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ true); + const meaning = (typeName.kind === SyntaxKind.Identifier ? SymbolFlags.Type : SymbolFlags.Namespace) + | SymbolFlags.Alias; + const rootSymbol = resolveName( + rootName, + rootName.escapedText, + meaning, + /*nameNotFoundMessage*/ undefined, + /*nameArg*/ undefined, + /*isUse*/ true, + ); if (rootSymbol && rootSymbol.flags & SymbolFlags.Alias) { if ( canCollectSymbolAliasAccessabilityData @@ -40551,10 +51755,17 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { && !symbolIsValue(rootSymbol) && !some(rootSymbol.declarations, isTypeOnlyImportOrExportDeclaration) ) { - const diag = error(typeName, Diagnostics.A_type_referenced_in_a_decorated_signature_must_be_imported_with_import_type_or_a_namespace_import_when_isolatedModules_and_emitDecoratorMetadata_are_enabled); + const diag = error( + typeName, + Diagnostics + .A_type_referenced_in_a_decorated_signature_must_be_imported_with_import_type_or_a_namespace_import_when_isolatedModules_and_emitDecoratorMetadata_are_enabled, + ); const aliasDeclaration = find(rootSymbol.declarations || emptyArray, isAliasSymbolDeclaration); if (aliasDeclaration) { - addRelatedInfo(diag, createDiagnosticForNode(aliasDeclaration, Diagnostics._0_was_imported_here, idText(rootName))); + addRelatedInfo( + diag, + createDiagnosticForNode(aliasDeclaration, Diagnostics._0_was_imported_here, idText(rootName)), + ); } } } @@ -40582,7 +51793,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return getEntityNameForDecoratorMetadataFromTypeList((node as UnionOrIntersectionTypeNode).types); case SyntaxKind.ConditionalType: - return getEntityNameForDecoratorMetadataFromTypeList([(node as ConditionalTypeNode).trueType, (node as ConditionalTypeNode).falseType]); + return getEntityNameForDecoratorMetadataFromTypeList([ + (node as ConditionalTypeNode).trueType, + (node as ConditionalTypeNode).falseType, + ]); case SyntaxKind.ParenthesizedType: case SyntaxKind.NamedTupleMember: @@ -40603,7 +51817,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (typeNode.kind === SyntaxKind.NeverKeyword) { continue; // Always elide `never` from the union/intersection if possible } - if (!strictNullChecks && (typeNode.kind === SyntaxKind.LiteralType && (typeNode as LiteralTypeNode).literal.kind === SyntaxKind.NullKeyword || typeNode.kind === SyntaxKind.UndefinedKeyword)) { + if ( + !strictNullChecks + && (typeNode.kind === SyntaxKind.LiteralType + && (typeNode as LiteralTypeNode).literal.kind === SyntaxKind.NullKeyword + || typeNode.kind === SyntaxKind.UndefinedKeyword) + ) { continue; // Elide null and undefined from unions for metadata, just like what we did prior to the implementation of strict null checks } const individualEntityName = getEntityNameForDecoratorMetadata(typeNode); @@ -40620,9 +51839,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // Verify if they refer to same entity and is identifier // return undefined if they dont match because we would emit object if ( - !isIdentifier(commonEntityName) || - !isIdentifier(individualEntityName) || - commonEntityName.escapedText !== individualEntityName.escapedText + !isIdentifier(commonEntityName) + || !isIdentifier(individualEntityName) + || commonEntityName.escapedText !== individualEntityName.escapedText ) { return undefined; } @@ -40643,7 +51862,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function checkDecorators(node: Node): void { // skip this check for nodes that cannot have decorators. These should have already had an error reported by // checkGrammarModifiers. - if (!canHaveDecorators(node) || !hasDecorators(node) || !node.modifiers || !nodeCanBeDecorated(legacyDecorators, node, node.parent, node.parent.parent)) { + if ( + !canHaveDecorators(node) || !hasDecorators(node) || !node.modifiers + || !nodeCanBeDecorated(legacyDecorators, node, node.parent, node.parent.parent) + ) { return; } @@ -40672,7 +51894,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } else if (!isClassExpression(node)) { - if (isPrivateIdentifier(node.name) && (isMethodDeclaration(node) || isAccessor(node) || isAutoAccessorPropertyDeclaration(node))) { + if ( + isPrivateIdentifier(node.name) + && (isMethodDeclaration(node) || isAccessor(node) || isAutoAccessorPropertyDeclaration(node)) + ) { checkExternalEmitHelpers(firstDecorator, ExternalEmitHelpers.SetFunctionName); } if (isComputedPropertyName(node.name)) { @@ -40690,16 +51915,25 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const constructor = getFirstConstructorWithBody(node); if (constructor) { for (const parameter of constructor.parameters) { - markDecoratorMedataDataTypeNodeAsReferenced(getParameterTypeNodeForDecoratorCheck(parameter)); + markDecoratorMedataDataTypeNodeAsReferenced( + getParameterTypeNodeForDecoratorCheck(parameter), + ); } } break; case SyntaxKind.GetAccessor: case SyntaxKind.SetAccessor: - const otherKind = node.kind === SyntaxKind.GetAccessor ? SyntaxKind.SetAccessor : SyntaxKind.GetAccessor; - const otherAccessor = getDeclarationOfKind(getSymbolOfDeclaration(node), otherKind); - markDecoratorMedataDataTypeNodeAsReferenced(getAnnotatedAccessorTypeNode(node) || otherAccessor && getAnnotatedAccessorTypeNode(otherAccessor)); + const otherKind = node.kind === SyntaxKind.GetAccessor ? SyntaxKind.SetAccessor + : SyntaxKind.GetAccessor; + const otherAccessor = getDeclarationOfKind( + getSymbolOfDeclaration(node), + otherKind, + ); + markDecoratorMedataDataTypeNodeAsReferenced( + getAnnotatedAccessorTypeNode(node) + || otherAccessor && getAnnotatedAccessorTypeNode(otherAccessor), + ); break; case SyntaxKind.MethodDeclaration: for (const parameter of node.parameters) { @@ -40744,7 +51978,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function checkJSDocTypeAliasTag(node: JSDocTypedefTag | JSDocCallbackTag) { if (!node.typeExpression) { // If the node had `@property` tags, `typeExpression` would have been set to the first property tag. - error(node.name, Diagnostics.JSDoc_typedef_tag_should_either_have_a_type_annotation_or_be_followed_by_property_or_member_tags); + error( + node.name, + Diagnostics + .JSDoc_typedef_tag_should_either_have_a_type_annotation_or_be_followed_by_property_or_member_tags, + ); } if (node.name) { @@ -40828,7 +52066,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (extend) { const className = getIdentifierFromEntityNameExpression(extend.expression); if (className && name.escapedText !== className.escapedText) { - error(name, Diagnostics.JSDoc_0_1_does_not_match_the_extends_2_clause, idText(node.tagName), idText(name), idText(className)); + error( + name, + Diagnostics.JSDoc_0_1_does_not_match_the_extends_2_clause, + idText(node.tagName), + idText(name), + idText(className), + ); } } } @@ -40840,7 +52084,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } - function getIdentifierFromEntityNameExpression(node: Identifier | PropertyAccessExpression): Identifier | PrivateIdentifier; + function getIdentifierFromEntityNameExpression( + node: Identifier | PropertyAccessExpression, + ): Identifier | PrivateIdentifier; function getIdentifierFromEntityNameExpression(node: Expression): Identifier | PrivateIdentifier | undefined; function getIdentifierFromEntityNameExpression(node: Expression): Identifier | PrivateIdentifier | undefined { switch (node.kind) { @@ -40902,8 +52148,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // A js function declaration can have a @type tag instead of a return type node, but that type must have a call signature if (isInJSFile(node)) { const typeTag = getJSDocTypeTag(node); - if (typeTag && typeTag.typeExpression && !getContextualCallSignature(getTypeFromTypeNode(typeTag.typeExpression), node)) { - error(typeTag.typeExpression.type, Diagnostics.The_type_of_a_function_declaration_must_match_the_function_s_signature); + if ( + typeTag && typeTag.typeExpression + && !getContextualCallSignature(getTypeFromTypeNode(typeTag.typeExpression), node) + ) { + error( + typeTag.typeExpression.type, + Diagnostics.The_type_of_a_function_declaration_must_match_the_function_s_signature, + ); } } @@ -40942,9 +52194,24 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } - type PotentiallyUnusedIdentifier = SourceFile | ModuleDeclaration | ClassLikeDeclaration | InterfaceDeclaration | Block | CaseBlock | ForStatement | ForInStatement | ForOfStatement | Exclude | TypeAliasDeclaration | InferTypeNode; + type PotentiallyUnusedIdentifier = + | SourceFile + | ModuleDeclaration + | ClassLikeDeclaration + | InterfaceDeclaration + | Block + | CaseBlock + | ForStatement + | ForInStatement + | ForOfStatement + | Exclude + | TypeAliasDeclaration + | InferTypeNode; - function checkUnusedIdentifiers(potentiallyUnusedIdentifiers: readonly PotentiallyUnusedIdentifier[], addDiagnostic: AddUnusedDiagnostic) { + function checkUnusedIdentifiers( + potentiallyUnusedIdentifiers: readonly PotentiallyUnusedIdentifier[], + addDiagnostic: AddUnusedDiagnostic, + ) { for (const node of potentiallyUnusedIdentifiers) { switch (node.kind) { case SyntaxKind.ClassDeclaration: @@ -40993,7 +52260,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function errorUnusedLocal(declaration: Declaration, name: string, addDiagnostic: AddUnusedDiagnostic) { const node = getNameOfDeclaration(declaration) || declaration; - const message = isTypeDeclaration(declaration) ? Diagnostics._0_is_declared_but_never_used : Diagnostics._0_is_declared_but_its_value_is_never_read; + const message = isTypeDeclaration(declaration) ? Diagnostics._0_is_declared_but_never_used + : Diagnostics._0_is_declared_but_its_value_is_never_read; addDiagnostic(declaration, UnusedKind.Local, createDiagnosticForNode(node, message, name)); } @@ -41001,7 +52269,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return isIdentifier(node) && idText(node).charCodeAt(0) === CharacterCodes._; } - function checkUnusedClassMembers(node: ClassDeclaration | ClassExpression, addDiagnostic: AddUnusedDiagnostic): void { + function checkUnusedClassMembers( + node: ClassDeclaration | ClassExpression, + addDiagnostic: AddUnusedDiagnostic, + ): void { for (const member of node.members) { switch (member.kind) { case SyntaxKind.MethodDeclaration: @@ -41015,16 +52286,33 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const symbol = getSymbolOfDeclaration(member); if ( !symbol.isReferenced - && (hasEffectiveModifier(member, ModifierFlags.Private) || isNamedDeclaration(member) && isPrivateIdentifier(member.name)) + && (hasEffectiveModifier(member, ModifierFlags.Private) + || isNamedDeclaration(member) && isPrivateIdentifier(member.name)) && !(member.flags & NodeFlags.Ambient) ) { - addDiagnostic(member, UnusedKind.Local, createDiagnosticForNode(member.name!, Diagnostics._0_is_declared_but_its_value_is_never_read, symbolToString(symbol))); + addDiagnostic( + member, + UnusedKind.Local, + createDiagnosticForNode( + member.name!, + Diagnostics._0_is_declared_but_its_value_is_never_read, + symbolToString(symbol), + ), + ); } break; case SyntaxKind.Constructor: for (const parameter of (member as ConstructorDeclaration).parameters) { if (!parameter.symbol.isReferenced && hasSyntacticModifier(parameter, ModifierFlags.Private)) { - addDiagnostic(parameter, UnusedKind.Local, createDiagnosticForNode(parameter.name, Diagnostics.Property_0_is_declared_but_its_value_is_never_read, symbolName(parameter.symbol))); + addDiagnostic( + parameter, + UnusedKind.Local, + createDiagnosticForNode( + parameter.name, + Diagnostics.Property_0_is_declared_but_its_value_is_never_read, + symbolName(parameter.symbol), + ), + ); } } break; @@ -41042,11 +52330,22 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function checkUnusedInferTypeParameter(node: InferTypeNode, addDiagnostic: AddUnusedDiagnostic): void { const { typeParameter } = node; if (isTypeParameterUnused(typeParameter)) { - addDiagnostic(node, UnusedKind.Parameter, createDiagnosticForNode(node, Diagnostics._0_is_declared_but_its_value_is_never_read, idText(typeParameter.name))); + addDiagnostic( + node, + UnusedKind.Parameter, + createDiagnosticForNode( + node, + Diagnostics._0_is_declared_but_its_value_is_never_read, + idText(typeParameter.name), + ), + ); } } - function checkUnusedTypeParameters(node: ClassLikeDeclaration | SignatureDeclaration | InterfaceDeclaration | TypeAliasDeclaration, addDiagnostic: AddUnusedDiagnostic): void { + function checkUnusedTypeParameters( + node: ClassLikeDeclaration | SignatureDeclaration | InterfaceDeclaration | TypeAliasDeclaration, + addDiagnostic: AddUnusedDiagnostic, + ): void { // Only report errors on the last declaration for the type parameter container; // this ensures that all uses have been accounted for. const declarations = getSymbolOfDeclaration(node).declarations; @@ -41073,17 +52372,30 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const messageAndArg: DiagnosticAndArguments = only ? [Diagnostics._0_is_declared_but_its_value_is_never_read, name] : [Diagnostics.All_type_parameters_are_unused]; - addDiagnostic(typeParameter, UnusedKind.Parameter, createFileDiagnostic(sourceFile, range.pos, range.end - range.pos, ...messageAndArg)); + addDiagnostic( + typeParameter, + UnusedKind.Parameter, + createFileDiagnostic(sourceFile, range.pos, range.end - range.pos, ...messageAndArg), + ); } } else { // TODO: following line is possible reason for bug #41974, unusedTypeParameters_TemplateTag - addDiagnostic(typeParameter, UnusedKind.Parameter, createDiagnosticForNode(typeParameter, Diagnostics._0_is_declared_but_its_value_is_never_read, name)); + addDiagnostic( + typeParameter, + UnusedKind.Parameter, + createDiagnosticForNode( + typeParameter, + Diagnostics._0_is_declared_but_its_value_is_never_read, + name, + ), + ); } } } function isTypeParameterUnused(typeParameter: TypeParameterDeclaration): boolean { - return !(getMergedSymbol(typeParameter.symbol).isReferenced! & SymbolFlags.TypeParameter) && !isIdentifierThatStartsWithUnderscore(typeParameter.name); + return !(getMergedSymbol(typeParameter.symbol).isReferenced! & SymbolFlags.TypeParameter) + && !isIdentifierThatStartsWithUnderscore(typeParameter.name); } function addToGroup(map: Map, key: K, value: V, getKey: (key: K) => number | string): void { @@ -41112,8 +52424,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } return isIdentifierThatStartsWithUnderscore(declaration.name); } - return isAmbientModule(declaration) || - (isVariableDeclaration(declaration) && isForInOrOfStatement(declaration.parent.parent) || isImportedDeclaration(declaration)) && isIdentifierThatStartsWithUnderscore(declaration.name!); + return isAmbientModule(declaration) + || (isVariableDeclaration(declaration) && isForInOrOfStatement(declaration.parent.parent) + || isImportedDeclaration(declaration)) && isIdentifierThatStartsWithUnderscore(declaration.name!); } function checkUnusedLocalsAndParameters(nodeWithLocals: HasLocals, addDiagnostic: AddUnusedDiagnostic): void { @@ -41124,7 +52437,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { nodeWithLocals.locals!.forEach(local => { // If it's purely a type parameter, ignore, will be checked in `checkUnusedTypeParameters`. // If it's a type parameter merged with a parameter, check if the parameter-side is used. - if (local.flags & SymbolFlags.TypeParameter ? !(local.flags & SymbolFlags.Variable && !(local.isReferenced! & SymbolFlags.Variable)) : local.isReferenced || local.exportSymbol) { + if ( + local.flags & SymbolFlags.TypeParameter + ? !(local.flags & SymbolFlags.Variable && !(local.isReferenced! & SymbolFlags.Variable)) + : local.isReferenced || local.exportSymbol + ) { return; } @@ -41147,20 +52464,35 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { else if (isVariableDeclaration(declaration)) { const blockScopeKind = getCombinedNodeFlagsCached(declaration) & NodeFlags.BlockScoped; const name = getNameOfDeclaration(declaration); - if (blockScopeKind !== NodeFlags.Using && blockScopeKind !== NodeFlags.AwaitUsing || !name || !isIdentifierThatStartsWithUnderscore(name)) { + if ( + blockScopeKind !== NodeFlags.Using && blockScopeKind !== NodeFlags.AwaitUsing || !name + || !isIdentifierThatStartsWithUnderscore(name) + ) { addToGroup(unusedVariables, declaration.parent, declaration, getNodeId); } } else { - const parameter = local.valueDeclaration && tryGetRootParameterDeclaration(local.valueDeclaration); + const parameter = local.valueDeclaration + && tryGetRootParameterDeclaration(local.valueDeclaration); const name = local.valueDeclaration && getNameOfDeclaration(local.valueDeclaration); if (parameter && name) { - if (!isParameterPropertyDeclaration(parameter, parameter.parent) && !parameterIsThisKeyword(parameter) && !isIdentifierThatStartsWithUnderscore(name)) { + if ( + !isParameterPropertyDeclaration(parameter, parameter.parent) + && !parameterIsThisKeyword(parameter) && !isIdentifierThatStartsWithUnderscore(name) + ) { if (isBindingElement(declaration) && isArrayBindingPattern(declaration.parent)) { addToGroup(unusedDestructures, declaration.parent, declaration, getNodeId); } else { - addDiagnostic(parameter, UnusedKind.Parameter, createDiagnosticForNode(name, Diagnostics._0_is_declared_but_its_value_is_never_read, symbolName(local))); + addDiagnostic( + parameter, + UnusedKind.Parameter, + createDiagnosticForNode( + name, + Diagnostics._0_is_declared_but_its_value_is_never_read, + symbolName(local), + ), + ); } } } @@ -41173,16 +52505,21 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { }); unusedImports.forEach(([importClause, unuseds]) => { const importDecl = importClause.parent; - const nDeclarations = (importClause.name ? 1 : 0) + - (importClause.namedBindings ? - (importClause.namedBindings.kind === SyntaxKind.NamespaceImport ? 1 : importClause.namedBindings.elements.length) + const nDeclarations = (importClause.name ? 1 : 0) + + (importClause.namedBindings + ? (importClause.namedBindings.kind === SyntaxKind.NamespaceImport ? 1 + : importClause.namedBindings.elements.length) : 0); if (nDeclarations === unuseds.length) { addDiagnostic( importDecl, UnusedKind.Local, unuseds.length === 1 - ? createDiagnosticForNode(importDecl, Diagnostics._0_is_declared_but_its_value_is_never_read, idText(first(unuseds).name!)) + ? createDiagnosticForNode( + importDecl, + Diagnostics._0_is_declared_but_its_value_is_never_read, + idText(first(unuseds).name!), + ) : createDiagnosticForNode(importDecl, Diagnostics.All_imports_in_import_declaration_are_unused), ); } @@ -41191,9 +52528,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } }); unusedDestructures.forEach(([bindingPattern, bindingElements]) => { - const kind = tryGetRootParameterDeclaration(bindingPattern.parent) ? UnusedKind.Parameter : UnusedKind.Local; + const kind = tryGetRootParameterDeclaration(bindingPattern.parent) ? UnusedKind.Parameter + : UnusedKind.Local; if (bindingPattern.elements.length === bindingElements.length) { - if (bindingElements.length === 1 && bindingPattern.parent.kind === SyntaxKind.VariableDeclaration && bindingPattern.parent.parent.kind === SyntaxKind.VariableDeclarationList) { + if ( + bindingElements.length === 1 && bindingPattern.parent.kind === SyntaxKind.VariableDeclaration + && bindingPattern.parent.parent.kind === SyntaxKind.VariableDeclarationList + ) { addToGroup(unusedVariables, bindingPattern.parent.parent, bindingPattern.parent, getNodeId); } else { @@ -41201,14 +52542,26 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { bindingPattern, kind, bindingElements.length === 1 - ? createDiagnosticForNode(bindingPattern, Diagnostics._0_is_declared_but_its_value_is_never_read, bindingNameText(first(bindingElements).name)) + ? createDiagnosticForNode( + bindingPattern, + Diagnostics._0_is_declared_but_its_value_is_never_read, + bindingNameText(first(bindingElements).name), + ) : createDiagnosticForNode(bindingPattern, Diagnostics.All_destructured_elements_are_unused), ); } } else { for (const e of bindingElements) { - addDiagnostic(e, kind, createDiagnosticForNode(e, Diagnostics._0_is_declared_but_its_value_is_never_read, bindingNameText(e.name))); + addDiagnostic( + e, + kind, + createDiagnosticForNode( + e, + Diagnostics._0_is_declared_but_its_value_is_never_read, + bindingNameText(e.name), + ), + ); } } }); @@ -41218,13 +52571,29 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { declarationList, UnusedKind.Local, declarations.length === 1 - ? createDiagnosticForNode(first(declarations).name, Diagnostics._0_is_declared_but_its_value_is_never_read, bindingNameText(first(declarations).name)) - : createDiagnosticForNode(declarationList.parent.kind === SyntaxKind.VariableStatement ? declarationList.parent : declarationList, Diagnostics.All_variables_are_unused), + ? createDiagnosticForNode( + first(declarations).name, + Diagnostics._0_is_declared_but_its_value_is_never_read, + bindingNameText(first(declarations).name), + ) + : createDiagnosticForNode( + declarationList.parent.kind === SyntaxKind.VariableStatement ? declarationList.parent + : declarationList, + Diagnostics.All_variables_are_unused, + ), ); } else { for (const decl of declarations) { - addDiagnostic(decl, UnusedKind.Local, createDiagnosticForNode(decl, Diagnostics._0_is_declared_but_its_value_is_never_read, bindingNameText(decl.name))); + addDiagnostic( + decl, + UnusedKind.Local, + createDiagnosticForNode( + decl, + Diagnostics._0_is_declared_but_its_value_is_never_read, + bindingNameText(decl.name), + ), + ); } } }); @@ -41234,13 +52603,27 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { for (const node of potentialUnusedRenamedBindingElementsInTypes) { if (!getSymbolOfDeclaration(node)?.isReferenced) { const wrappingDeclaration = walkUpBindingElementsAndPatterns(node); - Debug.assert(isParameterDeclaration(wrappingDeclaration), "Only parameter declaration should be checked here"); - const diagnostic = createDiagnosticForNode(node.name, Diagnostics._0_is_an_unused_renaming_of_1_Did_you_intend_to_use_it_as_a_type_annotation, declarationNameToString(node.name), declarationNameToString(node.propertyName)); + Debug.assert( + isParameterDeclaration(wrappingDeclaration), + "Only parameter declaration should be checked here", + ); + const diagnostic = createDiagnosticForNode( + node.name, + Diagnostics._0_is_an_unused_renaming_of_1_Did_you_intend_to_use_it_as_a_type_annotation, + declarationNameToString(node.name), + declarationNameToString(node.propertyName), + ); if (!wrappingDeclaration.type) { // entire parameter does not have type annotation, suggest adding an annotation addRelatedInfo( diagnostic, - createFileDiagnostic(getSourceFileOfNode(wrappingDeclaration), wrappingDeclaration.end, 1, Diagnostics.We_can_only_write_a_type_for_0_by_adding_a_type_for_the_entire_parameter_here, declarationNameToString(node.propertyName)), + createFileDiagnostic( + getSourceFileOfNode(wrappingDeclaration), + wrappingDeclaration.end, + 1, + Diagnostics.We_can_only_write_a_type_for_0_by_adding_a_type_for_the_entire_parameter_here, + declarationNameToString(node.propertyName), + ), ); } diagnostics.add(diagnostic); @@ -41262,10 +52645,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { type ImportedDeclaration = ImportClause | ImportSpecifier | NamespaceImport; function isImportedDeclaration(node: Node): node is ImportedDeclaration { - return node.kind === SyntaxKind.ImportClause || node.kind === SyntaxKind.ImportSpecifier || node.kind === SyntaxKind.NamespaceImport; + return node.kind === SyntaxKind.ImportClause || node.kind === SyntaxKind.ImportSpecifier + || node.kind === SyntaxKind.NamespaceImport; } function importClauseFromImported(decl: ImportedDeclaration): ImportClause { - return decl.kind === SyntaxKind.ImportClause ? decl : decl.kind === SyntaxKind.NamespaceImport ? decl.parent : decl.parent.parent; + return decl.kind === SyntaxKind.ImportClause ? decl + : decl.kind === SyntaxKind.NamespaceImport ? decl.parent : decl.parent.parent; } function checkBlock(node: Block) { @@ -41288,13 +52673,20 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function checkCollisionWithArgumentsInGeneratedCode(node: SignatureDeclaration) { // no rest parameters \ declaration context \ overload - no codegen impact - if (languageVersion >= ScriptTarget.ES2015 || !hasRestParameter(node) || node.flags & NodeFlags.Ambient || nodeIsMissing((node as FunctionLikeDeclaration).body)) { + if ( + languageVersion >= ScriptTarget.ES2015 || !hasRestParameter(node) || node.flags & NodeFlags.Ambient + || nodeIsMissing((node as FunctionLikeDeclaration).body) + ) { return; } forEach(node.parameters, p => { if (p.name && !isBindingPattern(p.name) && p.name.escapedText === argumentsSymbol.escapedName) { - errorSkippedOn("noEmit", p, Diagnostics.Duplicate_identifier_arguments_Compiler_uses_arguments_to_initialize_rest_parameters); + errorSkippedOn( + "noEmit", + p, + Diagnostics.Duplicate_identifier_arguments_Compiler_uses_arguments_to_initialize_rest_parameters, + ); } }); } @@ -41310,13 +52702,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } if ( - node.kind === SyntaxKind.PropertyDeclaration || - node.kind === SyntaxKind.PropertySignature || - node.kind === SyntaxKind.MethodDeclaration || - node.kind === SyntaxKind.MethodSignature || - node.kind === SyntaxKind.GetAccessor || - node.kind === SyntaxKind.SetAccessor || - node.kind === SyntaxKind.PropertyAssignment + node.kind === SyntaxKind.PropertyDeclaration + || node.kind === SyntaxKind.PropertySignature + || node.kind === SyntaxKind.MethodDeclaration + || node.kind === SyntaxKind.MethodSignature + || node.kind === SyntaxKind.GetAccessor + || node.kind === SyntaxKind.SetAccessor + || node.kind === SyntaxKind.PropertyAssignment ) { // it is ok to have member named '_super', '_this', `Promise`, etc. - member access is always qualified return false; @@ -41349,10 +52741,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (getNodeCheckFlags(current) & NodeCheckFlags.CaptureThis) { const isDeclaration = node.kind !== SyntaxKind.Identifier; if (isDeclaration) { - error(getNameOfDeclaration(node as Declaration), Diagnostics.Duplicate_identifier_this_Compiler_uses_variable_declaration_this_to_capture_this_reference); + error( + getNameOfDeclaration(node as Declaration), + Diagnostics + .Duplicate_identifier_this_Compiler_uses_variable_declaration_this_to_capture_this_reference, + ); } else { - error(node, Diagnostics.Expression_resolves_to_variable_declaration_this_that_compiler_uses_to_capture_this_reference); + error( + node, + Diagnostics + .Expression_resolves_to_variable_declaration_this_that_compiler_uses_to_capture_this_reference, + ); } return true; } @@ -41365,10 +52765,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (getNodeCheckFlags(current) & NodeCheckFlags.CaptureNewTarget) { const isDeclaration = node.kind !== SyntaxKind.Identifier; if (isDeclaration) { - error(getNameOfDeclaration(node as Declaration), Diagnostics.Duplicate_identifier_newTarget_Compiler_uses_variable_declaration_newTarget_to_capture_new_target_meta_property_reference); + error( + getNameOfDeclaration(node as Declaration), + Diagnostics + .Duplicate_identifier_newTarget_Compiler_uses_variable_declaration_newTarget_to_capture_new_target_meta_property_reference, + ); } else { - error(node, Diagnostics.Expression_resolves_to_variable_declaration_newTarget_that_compiler_uses_to_capture_new_target_meta_property_reference); + error( + node, + Diagnostics + .Expression_resolves_to_variable_declaration_newTarget_that_compiler_uses_to_capture_new_target_meta_property_reference, + ); } return true; } @@ -41378,11 +52786,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function checkCollisionWithRequireExportsInGeneratedCode(node: Node, name: Identifier | undefined) { // No need to check for require or exports for ES6 modules and later - if (moduleKind >= ModuleKind.ES2015 && !(moduleKind >= ModuleKind.Node16 && getSourceFileOfNode(node).impliedNodeFormat === ModuleKind.CommonJS)) { + if ( + moduleKind >= ModuleKind.ES2015 + && !(moduleKind >= ModuleKind.Node16 && getSourceFileOfNode(node).impliedNodeFormat === ModuleKind.CommonJS) + ) { return; } - if (!name || !needCollisionCheckForIdentifier(node, name, "require") && !needCollisionCheckForIdentifier(node, name, "exports")) { + if ( + !name + || !needCollisionCheckForIdentifier(node, name, "require") + && !needCollisionCheckForIdentifier(node, name, "exports") + ) { return; } @@ -41395,12 +52810,20 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const parent = getDeclarationContainer(node); if (parent.kind === SyntaxKind.SourceFile && isExternalOrCommonJsModule(parent as SourceFile)) { // If the declaration happens to be in external module, report error that require and exports are reserved keywords - errorSkippedOn("noEmit", name, Diagnostics.Duplicate_identifier_0_Compiler_reserves_name_1_in_top_level_scope_of_a_module, declarationNameToString(name), declarationNameToString(name)); + errorSkippedOn( + "noEmit", + name, + Diagnostics.Duplicate_identifier_0_Compiler_reserves_name_1_in_top_level_scope_of_a_module, + declarationNameToString(name), + declarationNameToString(name), + ); } } function checkCollisionWithGlobalPromiseInGeneratedCode(node: Node, name: Identifier | undefined): void { - if (!name || languageVersion >= ScriptTarget.ES2017 || !needCollisionCheckForIdentifier(node, name, "Promise")) { + if ( + !name || languageVersion >= ScriptTarget.ES2017 || !needCollisionCheckForIdentifier(node, name, "Promise") + ) { return; } @@ -41411,16 +52834,27 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // In case of variable declaration, node.parent is variable statement so look at the variable statement's parent const parent = getDeclarationContainer(node); - if (parent.kind === SyntaxKind.SourceFile && isExternalOrCommonJsModule(parent as SourceFile) && parent.flags & NodeFlags.HasAsyncFunctions) { + if ( + parent.kind === SyntaxKind.SourceFile && isExternalOrCommonJsModule(parent as SourceFile) + && parent.flags & NodeFlags.HasAsyncFunctions + ) { // If the declaration happens to be in external module, report error that Promise is a reserved identifier. - errorSkippedOn("noEmit", name, Diagnostics.Duplicate_identifier_0_Compiler_reserves_name_1_in_top_level_scope_of_a_module_containing_async_functions, declarationNameToString(name), declarationNameToString(name)); + errorSkippedOn( + "noEmit", + name, + Diagnostics + .Duplicate_identifier_0_Compiler_reserves_name_1_in_top_level_scope_of_a_module_containing_async_functions, + declarationNameToString(name), + declarationNameToString(name), + ); } } function recordPotentialCollisionWithWeakMapSetInGeneratedCode(node: Node, name: Identifier): void { if ( languageVersion <= ScriptTarget.ES2021 - && (needCollisionCheckForIdentifier(node, name, "WeakMap") || needCollisionCheckForIdentifier(node, name, "WeakSet")) + && (needCollisionCheckForIdentifier(node, name, "WeakMap") + || needCollisionCheckForIdentifier(node, name, "WeakSet")) ) { potentialWeakMapSetCollisions.push(node); } @@ -41429,8 +52863,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function checkWeakMapSetCollision(node: Node) { const enclosingBlockScope = getEnclosingBlockScopeContainer(node); if (getNodeCheckFlags(enclosingBlockScope) & NodeCheckFlags.ContainsClassWithPrivateIdentifiers) { - Debug.assert(isNamedDeclaration(node) && isIdentifier(node.name) && typeof node.name.escapedText === "string", "The target of a WeakMap/WeakSet collision check should be an identifier"); - errorSkippedOn("noEmit", node, Diagnostics.Compiler_reserves_name_0_when_emitting_private_identifier_downlevel, node.name.escapedText); + Debug.assert( + isNamedDeclaration(node) && isIdentifier(node.name) && typeof node.name.escapedText === "string", + "The target of a WeakMap/WeakSet collision check should be an identifier", + ); + errorSkippedOn( + "noEmit", + node, + Diagnostics.Compiler_reserves_name_0_when_emitting_private_identifier_downlevel, + node.name.escapedText, + ); } } @@ -41467,8 +52909,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } if (hasCollision) { - Debug.assert(isNamedDeclaration(node) && isIdentifier(node.name), "The target of a Reflect collision check should be an identifier"); - errorSkippedOn("noEmit", node, Diagnostics.Duplicate_identifier_0_Compiler_reserves_name_1_when_emitting_super_references_in_static_initializers, declarationNameToString(node.name), "Reflect"); + Debug.assert( + isNamedDeclaration(node) && isIdentifier(node.name), + "The target of a Reflect collision check should be an identifier", + ); + errorSkippedOn( + "noEmit", + node, + Diagnostics + .Duplicate_identifier_0_Compiler_reserves_name_1_when_emitting_super_references_in_static_initializers, + declarationNameToString(node.name), + "Reflect", + ); } } @@ -41526,31 +52978,48 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const symbol = getSymbolOfDeclaration(node); if (symbol.flags & SymbolFlags.FunctionScopedVariable) { if (!isIdentifier(node.name)) return Debug.fail(); - const localDeclarationSymbol = resolveName(node, node.name.escapedText, SymbolFlags.Variable, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ false); + const localDeclarationSymbol = resolveName( + node, + node.name.escapedText, + SymbolFlags.Variable, + /*nameNotFoundMessage*/ undefined, + /*nameArg*/ undefined, + /*isUse*/ false, + ); if ( - localDeclarationSymbol && - localDeclarationSymbol !== symbol && - localDeclarationSymbol.flags & SymbolFlags.BlockScopedVariable + localDeclarationSymbol + && localDeclarationSymbol !== symbol + && localDeclarationSymbol.flags & SymbolFlags.BlockScopedVariable ) { if (getDeclarationNodeFlagsFromSymbol(localDeclarationSymbol) & NodeFlags.BlockScoped) { - const varDeclList = getAncestor(localDeclarationSymbol.valueDeclaration, SyntaxKind.VariableDeclarationList)!; - const container = varDeclList.parent.kind === SyntaxKind.VariableStatement && varDeclList.parent.parent - ? varDeclList.parent.parent - : undefined; + const varDeclList = getAncestor( + localDeclarationSymbol.valueDeclaration, + SyntaxKind.VariableDeclarationList, + )!; + const container = + varDeclList.parent.kind === SyntaxKind.VariableStatement && varDeclList.parent.parent + ? varDeclList.parent.parent + : undefined; // names of block-scoped and function scoped variables can collide only // if block scoped variable is defined in the function\module\source file scope (because of variable hoisting) - const namesShareScope = container && - (container.kind === SyntaxKind.Block && isFunctionLike(container.parent) || - container.kind === SyntaxKind.ModuleBlock || - container.kind === SyntaxKind.ModuleDeclaration || - container.kind === SyntaxKind.SourceFile); + const namesShareScope = container + && (container.kind === SyntaxKind.Block && isFunctionLike(container.parent) + || container.kind === SyntaxKind.ModuleBlock + || container.kind === SyntaxKind.ModuleDeclaration + || container.kind === SyntaxKind.SourceFile); // here we know that function scoped variable is "shadowed" by block scoped one // a var declatation can't hoist past a lexical declaration and it results in a SyntaxError at runtime if (!namesShareScope) { const name = symbolToString(localDeclarationSymbol); - error(node, Diagnostics.Cannot_initialize_outer_scoped_variable_0_in_the_same_scope_as_block_scoped_declaration_1, name, name); + error( + node, + Diagnostics + .Cannot_initialize_outer_scoped_variable_0_in_the_same_scope_as_block_scoped_declaration_1, + name, + name, + ); } } } @@ -41562,7 +53031,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } // Check variable, parameter, or property declaration - function checkVariableLikeDeclaration(node: ParameterDeclaration | PropertyDeclaration | PropertySignature | VariableDeclaration | BindingElement) { + function checkVariableLikeDeclaration( + node: ParameterDeclaration | PropertyDeclaration | PropertySignature | VariableDeclaration | BindingElement, + ) { checkDecorators(node); if (!isBindingElement(node)) { checkSourceElement(node.type); @@ -41586,10 +53057,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (isBindingElement(node)) { if ( - node.propertyName && - isIdentifier(node.name) && - isParameterDeclaration(node) && - nodeIsMissing((getContainingFunction(node) as FunctionLikeDeclaration).body) + node.propertyName + && isIdentifier(node.name) + && isParameterDeclaration(node) + && nodeIsMissing((getContainingFunction(node) as FunctionLikeDeclaration).body) ) { // type F = ({a: string}) => void; // ^^^^^^ @@ -41618,8 +53089,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const nameText = getPropertyNameFromType(exprType); const property = getPropertyOfType(parentType, nameText); if (property) { - markPropertyAsReferenced(property, /*nodeForCheckWriteOnly*/ undefined, /*isSelfTypeAccess*/ false); // A destructuring is never a write-only reference. - checkPropertyAccessibility(node, !!parent.initializer && parent.initializer.kind === SyntaxKind.SuperKeyword, /*writing*/ false, parentType, property); + markPropertyAsReferenced( + property, + /*nodeForCheckWriteOnly*/ undefined, + /*isSelfTypeAccess*/ false, + ); // A destructuring is never a write-only reference. + checkPropertyAccessibility( + node, + !!parent.initializer && parent.initializer.kind === SyntaxKind.SuperKeyword, + /*writing*/ false, + parentType, + property, + ); } } } @@ -41627,15 +53108,24 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // For a binding pattern, check contained binding elements if (isBindingPattern(node.name)) { - if (node.name.kind === SyntaxKind.ArrayBindingPattern && languageVersion < ScriptTarget.ES2015 && compilerOptions.downlevelIteration) { + if ( + node.name.kind === SyntaxKind.ArrayBindingPattern && languageVersion < ScriptTarget.ES2015 + && compilerOptions.downlevelIteration + ) { checkExternalEmitHelpers(node, ExternalEmitHelpers.Read); } forEach(node.name.elements, checkSourceElement); } // For a parameter declaration with an initializer, error and exit if the containing function doesn't have a body - if (isParameter(node) && node.initializer && nodeIsMissing((getContainingFunction(node) as FunctionLikeDeclaration).body)) { - error(node, Diagnostics.A_parameter_initializer_is_only_allowed_in_a_function_or_constructor_implementation); + if ( + isParameter(node) && node.initializer + && nodeIsMissing((getContainingFunction(node) as FunctionLikeDeclaration).body) + ) { + error( + node, + Diagnostics.A_parameter_initializer_is_only_allowed_in_a_function_or_constructor_implementation, + ); return; } // For a binding pattern, validate the initializer and exit @@ -41643,7 +53133,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (isInAmbientOrTypeNode(node)) { return; } - const needCheckInitializer = hasOnlyExpressionInitializer(node) && node.initializer && node.parent.parent.kind !== SyntaxKind.ForInStatement; + const needCheckInitializer = hasOnlyExpressionInitializer(node) && node.initializer + && node.parent.parent.kind !== SyntaxKind.ForInStatement; const needCheckWidenedType = !some(node.name.elements, not(isOmittedExpression)); if (needCheckInitializer || needCheckWidenedType) { // Don't validate for-in initializer as it is already an error @@ -41654,7 +53145,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { checkNonNullNonVoidType(initializerType, node); } else { - checkTypeAssignableToAndOptionallyElaborate(initializerType, getWidenedTypeForVariableLikeDeclaration(node), node, node.initializer); + checkTypeAssignableToAndOptionallyElaborate( + initializerType, + getWidenedTypeForVariableLikeDeclaration(node), + node, + node.initializer, + ); } } // check the binding pattern with empty elements @@ -41671,7 +53167,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } // For a commonjs `const x = require`, validate the alias and exit const symbol = getSymbolOfDeclaration(node); - if (symbol.flags & SymbolFlags.Alias && (isVariableDeclarationInitializedToBareOrAccessedRequire(node) || isBindingElementOfBareOrAccessedRequire(node))) { + if ( + symbol.flags & SymbolFlags.Alias + && (isVariableDeclarationInitializedToBareOrAccessedRequire(node) + || isBindingElementOfBareOrAccessedRequire(node)) + ) { checkAliasSymbol(node); return; } @@ -41682,34 +53182,70 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // Don't validate for-in initializer as it is already an error const initializer = hasOnlyExpressionInitializer(node) && getEffectiveInitializer(node); if (initializer) { - const isJSObjectLiteralInitializer = isInJSFile(node) && - isObjectLiteralExpression(initializer) && - (initializer.properties.length === 0 || isPrototypeAccess(node.name)) && - !!symbol.exports?.size; + const isJSObjectLiteralInitializer = isInJSFile(node) + && isObjectLiteralExpression(initializer) + && (initializer.properties.length === 0 || isPrototypeAccess(node.name)) + && !!symbol.exports?.size; if (!isJSObjectLiteralInitializer && node.parent.parent.kind !== SyntaxKind.ForInStatement) { const initializerType = checkExpressionCached(initializer); - checkTypeAssignableToAndOptionallyElaborate(initializerType, type, node, initializer, /*headMessage*/ undefined); + checkTypeAssignableToAndOptionallyElaborate( + initializerType, + type, + node, + initializer, + /*headMessage*/ undefined, + ); const blockScopeKind = getCombinedNodeFlagsCached(node) & NodeFlags.BlockScoped; if (blockScopeKind === NodeFlags.AwaitUsing) { const globalAsyncDisposableType = getGlobalAsyncDisposableType(/*reportErrors*/ true); const globalDisposableType = getGlobalDisposableType(/*reportErrors*/ true); if (globalAsyncDisposableType !== emptyObjectType && globalDisposableType !== emptyObjectType) { - const optionalDisposableType = getUnionType([globalAsyncDisposableType, globalDisposableType, nullType, undefinedType]); - checkTypeAssignableTo(initializerType, optionalDisposableType, initializer, Diagnostics.The_initializer_of_an_await_using_declaration_must_be_either_an_object_with_a_Symbol_asyncDispose_or_Symbol_dispose_method_or_be_null_or_undefined); + const optionalDisposableType = getUnionType([ + globalAsyncDisposableType, + globalDisposableType, + nullType, + undefinedType, + ]); + checkTypeAssignableTo( + initializerType, + optionalDisposableType, + initializer, + Diagnostics + .The_initializer_of_an_await_using_declaration_must_be_either_an_object_with_a_Symbol_asyncDispose_or_Symbol_dispose_method_or_be_null_or_undefined, + ); } } else if (blockScopeKind === NodeFlags.Using) { const globalDisposableType = getGlobalDisposableType(/*reportErrors*/ true); if (globalDisposableType !== emptyObjectType) { - const optionalDisposableType = getUnionType([globalDisposableType, nullType, undefinedType]); - checkTypeAssignableTo(initializerType, optionalDisposableType, initializer, Diagnostics.The_initializer_of_a_using_declaration_must_be_either_an_object_with_a_Symbol_dispose_method_or_be_null_or_undefined); + const optionalDisposableType = getUnionType([ + globalDisposableType, + nullType, + undefinedType, + ]); + checkTypeAssignableTo( + initializerType, + optionalDisposableType, + initializer, + Diagnostics + .The_initializer_of_a_using_declaration_must_be_either_an_object_with_a_Symbol_dispose_method_or_be_null_or_undefined, + ); } } } } if (symbol.declarations && symbol.declarations.length > 1) { - if (some(symbol.declarations, d => d !== node && isVariableLike(d) && !areDeclarationFlagsIdentical(d, node))) { - error(node.name, Diagnostics.All_declarations_of_0_must_have_identical_modifiers, declarationNameToString(node.name)); + if ( + some( + symbol.declarations, + d => d !== node && isVariableLike(d) && !areDeclarationFlagsIdentical(d, node), + ) + ) { + error( + node.name, + Diagnostics.All_declarations_of_0_must_have_identical_modifiers, + declarationNameToString(node.name), + ); } } } @@ -41719,17 +53255,32 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const declarationType = convertAutoToAny(getWidenedTypeForVariableLikeDeclaration(node)); if ( - !isErrorType(type) && !isErrorType(declarationType) && - !isTypeIdenticalTo(type, declarationType) && - !(symbol.flags & SymbolFlags.Assignment) + !isErrorType(type) && !isErrorType(declarationType) + && !isTypeIdenticalTo(type, declarationType) + && !(symbol.flags & SymbolFlags.Assignment) ) { - errorNextVariableOrPropertyDeclarationMustHaveSameType(symbol.valueDeclaration, type, node, declarationType); + errorNextVariableOrPropertyDeclarationMustHaveSameType( + symbol.valueDeclaration, + type, + node, + declarationType, + ); } if (hasOnlyExpressionInitializer(node) && node.initializer) { - checkTypeAssignableToAndOptionallyElaborate(checkExpressionCached(node.initializer), declarationType, node, node.initializer, /*headMessage*/ undefined); + checkTypeAssignableToAndOptionallyElaborate( + checkExpressionCached(node.initializer), + declarationType, + node, + node.initializer, + /*headMessage*/ undefined, + ); } if (symbol.valueDeclaration && !areDeclarationFlagsIdentical(node, symbol.valueDeclaration)) { - error(node.name, Diagnostics.All_declarations_of_0_must_have_identical_modifiers, declarationNameToString(node.name)); + error( + node.name, + Diagnostics.All_declarations_of_0_must_have_identical_modifiers, + declarationNameToString(node.name), + ); } } if (node.kind !== SyntaxKind.PropertyDeclaration && node.kind !== SyntaxKind.PropertySignature) { @@ -41742,11 +53293,19 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } - function errorNextVariableOrPropertyDeclarationMustHaveSameType(firstDeclaration: Declaration | undefined, firstType: Type, nextDeclaration: Declaration, nextType: Type): void { + function errorNextVariableOrPropertyDeclarationMustHaveSameType( + firstDeclaration: Declaration | undefined, + firstType: Type, + nextDeclaration: Declaration, + nextType: Type, + ): void { const nextDeclarationName = getNameOfDeclaration(nextDeclaration); - const message = nextDeclaration.kind === SyntaxKind.PropertyDeclaration || nextDeclaration.kind === SyntaxKind.PropertySignature - ? Diagnostics.Subsequent_property_declarations_must_have_the_same_type_Property_0_must_be_of_type_1_but_here_has_type_2 - : Diagnostics.Subsequent_variable_declarations_must_have_the_same_type_Variable_0_must_be_of_type_1_but_here_has_type_2; + const message = nextDeclaration.kind === SyntaxKind.PropertyDeclaration + || nextDeclaration.kind === SyntaxKind.PropertySignature + ? Diagnostics + .Subsequent_property_declarations_must_have_the_same_type_Property_0_must_be_of_type_1_but_here_has_type_2 + : Diagnostics + .Subsequent_variable_declarations_must_have_the_same_type_Variable_0_must_be_of_type_1_but_here_has_type_2; const declName = declarationNameToString(nextDeclarationName); const err = error( nextDeclarationName, @@ -41756,14 +53315,17 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { typeToString(nextType), ); if (firstDeclaration) { - addRelatedInfo(err, createDiagnosticForNode(firstDeclaration, Diagnostics._0_was_also_declared_here, declName)); + addRelatedInfo( + err, + createDiagnosticForNode(firstDeclaration, Diagnostics._0_was_also_declared_here, declName), + ); } } function areDeclarationFlagsIdentical(left: Declaration, right: Declaration) { if ( - (left.kind === SyntaxKind.Parameter && right.kind === SyntaxKind.VariableDeclaration) || - (left.kind === SyntaxKind.VariableDeclaration && right.kind === SyntaxKind.Parameter) + (left.kind === SyntaxKind.Parameter && right.kind === SyntaxKind.VariableDeclaration) + || (left.kind === SyntaxKind.VariableDeclaration && right.kind === SyntaxKind.Parameter) ) { // Differences in optionality between parameters and variables are allowed. return true; @@ -41773,18 +53335,24 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return false; } - const interestingFlags = ModifierFlags.Private | - ModifierFlags.Protected | - ModifierFlags.Async | - ModifierFlags.Abstract | - ModifierFlags.Readonly | - ModifierFlags.Static; + const interestingFlags = ModifierFlags.Private + | ModifierFlags.Protected + | ModifierFlags.Async + | ModifierFlags.Abstract + | ModifierFlags.Readonly + | ModifierFlags.Static; - return getSelectedEffectiveModifierFlags(left, interestingFlags) === getSelectedEffectiveModifierFlags(right, interestingFlags); + return getSelectedEffectiveModifierFlags(left, interestingFlags) + === getSelectedEffectiveModifierFlags(right, interestingFlags); } function checkVariableDeclaration(node: VariableDeclaration) { - tracing?.push(tracing.Phase.Check, "checkVariableDeclaration", { kind: node.kind, pos: node.pos, end: node.end, path: (node as TracingNode).tracingPath }); + tracing?.push(tracing.Phase.Check, "checkVariableDeclaration", { + kind: node.kind, + pos: node.pos, + end: node.end, + path: (node as TracingNode).tracingPath, + }); checkGrammarVariableDeclaration(node); checkVariableLikeDeclaration(node); tracing?.pop(); @@ -41806,7 +53374,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function checkVariableStatement(node: VariableStatement) { // Grammar checking - if (!checkGrammarModifiers(node) && !checkGrammarVariableDeclarationList(node.declarationList)) checkGrammarForDisallowedBlockScopedVariableStatement(node); + if (!checkGrammarModifiers(node) && !checkGrammarVariableDeclarationList(node.declarationList)) { + checkGrammarForDisallowedBlockScopedVariableStatement(node); + } checkVariableDeclarationList(node.declarationList); } @@ -41831,7 +53401,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { checkSourceElement(node.elseStatement); } - function checkTestingKnownTruthyCallableOrAwaitableType(condExpr: Expression, condType: Type, body?: Statement | Expression) { + function checkTestingKnownTruthyCallableOrAwaitableType( + condExpr: Expression, + condType: Type, + body?: Statement | Expression, + ) { if (!strictNullChecks) return; bothHelper(condExpr, body); @@ -41840,14 +53414,19 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { helper(condExpr, body); - while (isBinaryExpression(condExpr) && (condExpr.operatorToken.kind === SyntaxKind.BarBarToken || condExpr.operatorToken.kind === SyntaxKind.QuestionQuestionToken)) { + while ( + isBinaryExpression(condExpr) + && (condExpr.operatorToken.kind === SyntaxKind.BarBarToken + || condExpr.operatorToken.kind === SyntaxKind.QuestionQuestionToken) + ) { condExpr = skipParentheses(condExpr.left); helper(condExpr, body); } } function helper(condExpr: Expression, body: Expression | Statement | undefined) { - const location = isLogicalOrCoalescingBinaryExpression(condExpr) ? skipParentheses(condExpr.right) : condExpr; + const location = isLogicalOrCoalescingBinaryExpression(condExpr) ? skipParentheses(condExpr.right) + : condExpr; if (isModuleExportsAccessExpression(location)) { return; } @@ -41856,7 +53435,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return; } const type = location === condExpr ? condType : checkTruthinessExpression(location); - const isPropertyExpressionCast = isPropertyAccessExpression(location) && isTypeAssertion(location.expression); + const isPropertyExpressionCast = isPropertyAccessExpression(location) + && isTypeAssertion(location.expression); if (!(getTypeFacts(type) & TypeFacts.Truthy) || isPropertyExpressionCast) return; // While it technically should be invalid for any known-truthy value @@ -41878,7 +53458,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return; } - const isUsed = testedSymbol && isBinaryExpression(condExpr.parent) && isSymbolUsedInBinaryExpressionChain(condExpr.parent, testedSymbol) + const isUsed = testedSymbol && isBinaryExpression(condExpr.parent) + && isSymbolUsedInBinaryExpressionChain(condExpr.parent, testedSymbol) || testedSymbol && body && isSymbolUsedInConditionBody(condExpr, body, testedNode, testedSymbol); if (!isUsed) { if (isPromise) { @@ -41890,13 +53471,22 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { ); } else { - error(location, Diagnostics.This_condition_will_always_return_true_since_this_function_is_always_defined_Did_you_mean_to_call_it_instead); + error( + location, + Diagnostics + .This_condition_will_always_return_true_since_this_function_is_always_defined_Did_you_mean_to_call_it_instead, + ); } } } } - function isSymbolUsedInConditionBody(expr: Expression, body: Statement | Expression, testedNode: Node, testedSymbol: Symbol): boolean { + function isSymbolUsedInConditionBody( + expr: Expression, + body: Statement | Expression, + testedNode: Node, + testedSymbol: Symbol, + ): boolean { return !!forEachChild(body, function check(childNode): boolean | undefined { if (isIdentifier(childNode)) { const childSymbol = getSymbolAtLocation(childNode); @@ -41910,13 +53500,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { let childExpression = childNode.parent; while (testedExpression && childExpression) { if ( - isIdentifier(testedExpression) && isIdentifier(childExpression) || - testedExpression.kind === SyntaxKind.ThisKeyword && childExpression.kind === SyntaxKind.ThisKeyword + isIdentifier(testedExpression) && isIdentifier(childExpression) + || testedExpression.kind === SyntaxKind.ThisKeyword + && childExpression.kind === SyntaxKind.ThisKeyword ) { return getSymbolAtLocation(testedExpression) === getSymbolAtLocation(childExpression); } - else if (isPropertyAccessExpression(testedExpression) && isPropertyAccessExpression(childExpression)) { - if (getSymbolAtLocation(testedExpression.name) !== getSymbolAtLocation(childExpression.name)) { + else if ( + isPropertyAccessExpression(testedExpression) && isPropertyAccessExpression(childExpression) + ) { + if ( + getSymbolAtLocation(testedExpression.name) !== getSymbolAtLocation(childExpression.name) + ) { return false; } childExpression = childExpression.expression; @@ -42013,11 +53608,17 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const container = getContainingFunctionOrClassStaticBlock(node); if (node.awaitModifier) { if (container && isClassStaticBlockDeclaration(container)) { - grammarErrorOnNode(node.awaitModifier, Diagnostics.for_await_loops_cannot_be_used_inside_a_class_static_block); + grammarErrorOnNode( + node.awaitModifier, + Diagnostics.for_await_loops_cannot_be_used_inside_a_class_static_block, + ); } else { const functionFlags = getFunctionFlags(container); - if ((functionFlags & (FunctionFlags.Invalid | FunctionFlags.Async)) === FunctionFlags.Async && languageVersion < ScriptTarget.ESNext) { + if ( + (functionFlags & (FunctionFlags.Invalid | FunctionFlags.Async)) === FunctionFlags.Async + && languageVersion < ScriptTarget.ESNext + ) { // for..await..of in an async function or async generator function prior to ESNext requires the __asyncValues helper checkExternalEmitHelpers(node, ExternalEmitHelpers.ForAwaitOfIncludes); } @@ -42041,7 +53642,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const iteratedType = checkRightHandSideOfForOf(node); // There may be a destructuring assignment on the left side - if (varExpr.kind === SyntaxKind.ArrayLiteralExpression || varExpr.kind === SyntaxKind.ObjectLiteralExpression) { + if ( + varExpr.kind === SyntaxKind.ArrayLiteralExpression + || varExpr.kind === SyntaxKind.ObjectLiteralExpression + ) { // iteratedType may be undefined. In this case, we still want to check the structure of // varExpr, in particular making sure it's a valid LeftHandSideExpression. But we'd like // to short circuit the type relation checking as much as possible, so we pass the unknownType. @@ -42084,7 +53688,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (node.initializer.kind === SyntaxKind.VariableDeclarationList) { const variable = (node.initializer as VariableDeclarationList).declarations[0]; if (variable && isBindingPattern(variable.name)) { - error(variable.name, Diagnostics.The_left_hand_side_of_a_for_in_statement_cannot_be_a_destructuring_pattern); + error( + variable.name, + Diagnostics.The_left_hand_side_of_a_for_in_statement_cannot_be_a_destructuring_pattern, + ); } checkVariableDeclarationList(node.initializer as VariableDeclarationList); } @@ -42095,7 +53702,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // and Expr must be an expression of type Any, an object type, or a type parameter type. const varExpr = node.initializer; const leftType = checkExpression(varExpr); - if (varExpr.kind === SyntaxKind.ArrayLiteralExpression || varExpr.kind === SyntaxKind.ObjectLiteralExpression) { + if ( + varExpr.kind === SyntaxKind.ArrayLiteralExpression + || varExpr.kind === SyntaxKind.ObjectLiteralExpression + ) { error(varExpr, Diagnostics.The_left_hand_side_of_a_for_in_statement_cannot_be_a_destructuring_pattern); } else if (!isTypeAssignableTo(getIndexTypeOrString(rightType), leftType)) { @@ -42113,8 +53723,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // unknownType is returned i.e. if node.expression is identifier whose name cannot be resolved // in this case error about missing name is already reported - do not report extra one - if (rightType === neverType || !isTypeAssignableToKind(rightType, TypeFlags.NonPrimitive | TypeFlags.InstantiableNonPrimitive)) { - error(node.expression, Diagnostics.The_right_hand_side_of_a_for_in_statement_must_be_of_type_any_an_object_type_or_a_type_parameter_but_here_has_type_0, typeToString(rightType)); + if ( + rightType === neverType + || !isTypeAssignableToKind(rightType, TypeFlags.NonPrimitive | TypeFlags.InstantiableNonPrimitive) + ) { + error( + node.expression, + Diagnostics + .The_right_hand_side_of_a_for_in_statement_must_be_of_type_any_an_object_type_or_a_type_parameter_but_here_has_type_0, + typeToString(rightType), + ); } checkSourceElement(node.statement); @@ -42125,14 +53743,25 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function checkRightHandSideOfForOf(statement: ForOfStatement): Type { const use = statement.awaitModifier ? IterationUse.ForAwaitOf : IterationUse.ForOf; - return checkIteratedTypeOrElementType(use, checkNonNullExpression(statement.expression), undefinedType, statement.expression); + return checkIteratedTypeOrElementType( + use, + checkNonNullExpression(statement.expression), + undefinedType, + statement.expression, + ); } - function checkIteratedTypeOrElementType(use: IterationUse, inputType: Type, sentType: Type, errorNode: Node | undefined): Type { + function checkIteratedTypeOrElementType( + use: IterationUse, + inputType: Type, + sentType: Type, + errorNode: Node | undefined, + ): Type { if (isTypeAny(inputType)) { return inputType; } - return getIteratedTypeOrElementType(use, inputType, sentType, errorNode, /*checkAssignability*/ true) || anyType; + return getIteratedTypeOrElementType(use, inputType, sentType, errorNode, /*checkAssignability*/ true) + || anyType; } /** @@ -42140,7 +53769,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { * we want to get the iterated type of an iterable for ES2015 or later, or the iterated type * of a iterable (if defined globally) or element type of an array like for ES2015 or earlier. */ - function getIteratedTypeOrElementType(use: IterationUse, inputType: Type, sentType: Type, errorNode: Node | undefined, checkAssignability: boolean): Type | undefined { + function getIteratedTypeOrElementType( + use: IterationUse, + inputType: Type, + sentType: Type, + errorNode: Node | undefined, + checkAssignability: boolean, + ): Type | undefined { const allowAsyncIterables = (use & IterationUse.AllowsAsyncIterablesFlag) !== 0; if (inputType === neverType) { reportTypeNotIterableError(errorNode!, inputType, allowAsyncIterables); // TODO: GH#18217 @@ -42149,28 +53784,43 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const uplevelIteration = languageVersion >= ScriptTarget.ES2015; const downlevelIteration = !uplevelIteration && compilerOptions.downlevelIteration; - const possibleOutOfBounds = compilerOptions.noUncheckedIndexedAccess && !!(use & IterationUse.PossiblyOutOfBounds); + const possibleOutOfBounds = compilerOptions.noUncheckedIndexedAccess + && !!(use & IterationUse.PossiblyOutOfBounds); // Get the iterated type of an `Iterable` or `IterableIterator` only in ES2015 // or higher, when inside of an async generator or for-await-if, or when // downlevelIteration is requested. if (uplevelIteration || downlevelIteration || allowAsyncIterables) { // We only report errors for an invalid iterable type in ES2015 or higher. - const iterationTypes = getIterationTypesOfIterable(inputType, use, uplevelIteration ? errorNode : undefined); + const iterationTypes = getIterationTypesOfIterable( + inputType, + use, + uplevelIteration ? errorNode : undefined, + ); if (checkAssignability) { if (iterationTypes) { - const diagnostic = use & IterationUse.ForOfFlag ? Diagnostics.Cannot_iterate_value_because_the_next_method_of_its_iterator_expects_type_1_but_for_of_will_always_send_0 : - use & IterationUse.SpreadFlag ? Diagnostics.Cannot_iterate_value_because_the_next_method_of_its_iterator_expects_type_1_but_array_spread_will_always_send_0 : - use & IterationUse.DestructuringFlag ? Diagnostics.Cannot_iterate_value_because_the_next_method_of_its_iterator_expects_type_1_but_array_destructuring_will_always_send_0 : - use & IterationUse.YieldStarFlag ? Diagnostics.Cannot_delegate_iteration_to_value_because_the_next_method_of_its_iterator_expects_type_1_but_the_containing_generator_will_always_send_0 : - undefined; + const diagnostic = use & IterationUse.ForOfFlag + ? Diagnostics + .Cannot_iterate_value_because_the_next_method_of_its_iterator_expects_type_1_but_for_of_will_always_send_0 + : use & IterationUse.SpreadFlag + ? Diagnostics + .Cannot_iterate_value_because_the_next_method_of_its_iterator_expects_type_1_but_array_spread_will_always_send_0 + : use & IterationUse.DestructuringFlag + ? Diagnostics + .Cannot_iterate_value_because_the_next_method_of_its_iterator_expects_type_1_but_array_destructuring_will_always_send_0 + : use & IterationUse.YieldStarFlag + ? Diagnostics + .Cannot_delegate_iteration_to_value_because_the_next_method_of_its_iterator_expects_type_1_but_the_containing_generator_will_always_send_0 + : undefined; if (diagnostic) { checkTypeAssignableTo(sentType, iterationTypes.nextType, errorNode, diagnostic); } } } if (iterationTypes || uplevelIteration) { - return possibleOutOfBounds ? includeUndefinedInIndexSignature(iterationTypes && iterationTypes.yieldType) : (iterationTypes && iterationTypes.yieldType); + return possibleOutOfBounds + ? includeUndefinedInIndexSignature(iterationTypes && iterationTypes.yieldType) + : (iterationTypes && iterationTypes.yieldType); } } @@ -42199,7 +53849,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (hasStringConstituent) { if (languageVersion < ScriptTarget.ES5) { if (errorNode) { - error(errorNode, Diagnostics.Using_a_string_in_a_for_of_statement_is_only_supported_in_ECMAScript_5_and_higher); + error( + errorNode, + Diagnostics + .Using_a_string_in_a_for_of_statement_is_only_supported_in_ECMAScript_5_and_higher, + ); reportedError = true; } } @@ -42220,7 +53874,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // number and string input is allowed, we want to say that number is not an // array type or a string type. const allowsStrings = !!(use & IterationUse.AllowsStringInputFlag) && !hasStringConstituent; - const [defaultDiagnostic, maybeMissingAwait] = getIterationDiagnosticDetails(allowsStrings, downlevelIteration); + const [defaultDiagnostic, maybeMissingAwait] = getIterationDiagnosticDetails( + allowsStrings, + downlevelIteration, + ); errorAndMaybeSuggestAwait( errorNode, maybeMissingAwait && !!getAwaitedTypeOfPromise(arrayType), @@ -42228,7 +53885,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { typeToString(arrayType), ); } - return hasStringConstituent ? possibleOutOfBounds ? includeUndefinedInIndexSignature(stringType) : stringType : undefined; + return hasStringConstituent + ? possibleOutOfBounds ? includeUndefinedInIndexSignature(stringType) : stringType : undefined; } const arrayElementType = getIndexTypeOfType(arrayType, numberType); @@ -42238,26 +53896,54 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return stringType; } - return getUnionType(possibleOutOfBounds ? [arrayElementType, stringType, undefinedType] : [arrayElementType, stringType], UnionReduction.Subtype); + return getUnionType( + possibleOutOfBounds ? [arrayElementType, stringType, undefinedType] : [arrayElementType, stringType], + UnionReduction.Subtype, + ); } - return (use & IterationUse.PossiblyOutOfBounds) ? includeUndefinedInIndexSignature(arrayElementType) : arrayElementType; + return (use & IterationUse.PossiblyOutOfBounds) ? includeUndefinedInIndexSignature(arrayElementType) + : arrayElementType; - function getIterationDiagnosticDetails(allowsStrings: boolean, downlevelIteration: boolean | undefined): [error: DiagnosticMessage, maybeMissingAwait: boolean] { + function getIterationDiagnosticDetails( + allowsStrings: boolean, + downlevelIteration: boolean | undefined, + ): [error: DiagnosticMessage, maybeMissingAwait: boolean] { if (downlevelIteration) { return allowsStrings - ? [Diagnostics.Type_0_is_not_an_array_type_or_a_string_type_or_does_not_have_a_Symbol_iterator_method_that_returns_an_iterator, true] - : [Diagnostics.Type_0_is_not_an_array_type_or_does_not_have_a_Symbol_iterator_method_that_returns_an_iterator, true]; + ? [ + Diagnostics + .Type_0_is_not_an_array_type_or_a_string_type_or_does_not_have_a_Symbol_iterator_method_that_returns_an_iterator, + true, + ] + : [ + Diagnostics + .Type_0_is_not_an_array_type_or_does_not_have_a_Symbol_iterator_method_that_returns_an_iterator, + true, + ]; } - const yieldType = getIterationTypeOfIterable(use, IterationTypeKind.Yield, inputType, /*errorNode*/ undefined); + const yieldType = getIterationTypeOfIterable( + use, + IterationTypeKind.Yield, + inputType, + /*errorNode*/ undefined, + ); if (yieldType) { - return [Diagnostics.Type_0_can_only_be_iterated_through_when_using_the_downlevelIteration_flag_or_with_a_target_of_es2015_or_higher, false]; + return [ + Diagnostics + .Type_0_can_only_be_iterated_through_when_using_the_downlevelIteration_flag_or_with_a_target_of_es2015_or_higher, + false, + ]; } if (isES2015OrLaterIterable(inputType.symbol?.escapedName)) { - return [Diagnostics.Type_0_can_only_be_iterated_through_when_using_the_downlevelIteration_flag_or_with_a_target_of_es2015_or_higher, true]; + return [ + Diagnostics + .Type_0_can_only_be_iterated_through_when_using_the_downlevelIteration_flag_or_with_a_target_of_es2015_or_higher, + true, + ]; } return allowsStrings @@ -42286,7 +53972,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { /** * Gets the requested "iteration type" from an `Iterable`-like or `AsyncIterable`-like type. */ - function getIterationTypeOfIterable(use: IterationUse, typeKind: IterationTypeKind, inputType: Type, errorNode: Node | undefined): Type | undefined { + function getIterationTypeOfIterable( + use: IterationUse, + typeKind: IterationTypeKind, + inputType: Type, + errorNode: Node | undefined, + ): Type | undefined { if (isTypeAny(inputType)) { return undefined; } @@ -42295,7 +53986,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return iterationTypes && iterationTypes[getIterationTypesKeyFromIterationTypeKind(typeKind)]; } - function createIterationTypes(yieldType: Type = neverType, returnType: Type = neverType, nextType: Type = unknownType): IterationTypes { + function createIterationTypes( + yieldType: Type = neverType, + returnType: Type = neverType, + nextType: Type = unknownType, + ): IterationTypes { // `yieldType` and `returnType` are defaulted to `neverType` they each will be combined // via `getUnionType` when merging iteration types. `nextType` is defined as `unknownType` // as it is combined via `getIntersectionType` when merging iteration types. @@ -42305,9 +54000,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // are also cached on the type they are requested for, so we shouldn't need to maintain // the cache for less-frequently used types. if ( - yieldType.flags & TypeFlags.Intrinsic && - returnType.flags & (TypeFlags.Any | TypeFlags.Never | TypeFlags.Unknown | TypeFlags.Void | TypeFlags.Undefined) && - nextType.flags & (TypeFlags.Any | TypeFlags.Never | TypeFlags.Unknown | TypeFlags.Void | TypeFlags.Undefined) + yieldType.flags & TypeFlags.Intrinsic + && returnType.flags + & (TypeFlags.Any | TypeFlags.Never | TypeFlags.Unknown | TypeFlags.Void | TypeFlags.Undefined) + && nextType.flags + & (TypeFlags.Any | TypeFlags.Never | TypeFlags.Unknown | TypeFlags.Void | TypeFlags.Undefined) ) { const id = getTypeListId([yieldType, returnType, nextType]); let iterationTypes = iterationTypesCache.get(id); @@ -42352,11 +54049,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return noIterationTypes; } - function getCachedIterationTypes(type: Type, cacheKey: MatchingKeys) { + function getCachedIterationTypes( + type: Type, + cacheKey: MatchingKeys, + ) { return (type as IterableOrIteratorType)[cacheKey]; } - function setCachedIterationTypes(type: Type, cacheKey: MatchingKeys, cachedTypes: IterationTypes) { + function setCachedIterationTypes( + type: Type, + cacheKey: MatchingKeys, + cachedTypes: IterationTypes, + ) { return (type as IterableOrIteratorType)[cacheKey] = cachedTypes; } @@ -42387,11 +54091,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } if (!(type.flags & TypeFlags.Union)) { - const errorOutputContainer: { errors: Diagnostic[] | undefined; } | undefined = errorNode ? { errors: undefined } : undefined; + const errorOutputContainer: { errors: Diagnostic[] | undefined; } | undefined = errorNode + ? { errors: undefined } : undefined; const iterationTypes = getIterationTypesOfIterableWorker(type, use, errorNode, errorOutputContainer); if (iterationTypes === noIterationTypes) { if (errorNode) { - const rootDiag = reportTypeNotIterableError(errorNode, type, !!(use & IterationUse.AllowsAsyncIterablesFlag)); + const rootDiag = reportTypeNotIterableError( + errorNode, + type, + !!(use & IterationUse.AllowsAsyncIterablesFlag), + ); if (errorOutputContainer?.errors) { addRelatedInfo(rootDiag, ...errorOutputContainer.errors); } @@ -42406,17 +54115,23 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return iterationTypes; } - const cacheKey = use & IterationUse.AllowsAsyncIterablesFlag ? "iterationTypesOfAsyncIterable" : "iterationTypesOfIterable"; + const cacheKey = use & IterationUse.AllowsAsyncIterablesFlag ? "iterationTypesOfAsyncIterable" + : "iterationTypesOfIterable"; const cachedTypes = getCachedIterationTypes(type, cacheKey); if (cachedTypes) return cachedTypes === noIterationTypes ? undefined : cachedTypes; let allIterationTypes: IterationTypes[] | undefined; for (const constituent of (type as UnionType).types) { - const errorOutputContainer: { errors: Diagnostic[] | undefined; } | undefined = errorNode ? { errors: undefined } : undefined; + const errorOutputContainer: { errors: Diagnostic[] | undefined; } | undefined = errorNode + ? { errors: undefined } : undefined; const iterationTypes = getIterationTypesOfIterableWorker(constituent, use, errorNode, errorOutputContainer); if (iterationTypes === noIterationTypes) { if (errorNode) { - const rootDiag = reportTypeNotIterableError(errorNode, type, !!(use & IterationUse.AllowsAsyncIterablesFlag)); + const rootDiag = reportTypeNotIterableError( + errorNode, + type, + !!(use & IterationUse.AllowsAsyncIterablesFlag), + ); if (errorOutputContainer?.errors) { addRelatedInfo(rootDiag, ...errorOutputContainer.errors); } @@ -42463,7 +54178,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { * NOTE: You probably don't want to call this directly and should be calling * `getIterationTypesOfIterable` instead. */ - function getIterationTypesOfIterableWorker(type: Type, use: IterationUse, errorNode: Node | undefined, errorOutputContainer: { errors: Diagnostic[] | undefined; } | undefined) { + function getIterationTypesOfIterableWorker( + type: Type, + use: IterationUse, + errorNode: Node | undefined, + errorOutputContainer: { errors: Diagnostic[] | undefined; } | undefined, + ) { if (isTypeAny(type)) { return anyIterationTypes; } @@ -42473,24 +54193,24 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { let noCache = false; if (use & IterationUse.AllowsAsyncIterablesFlag) { - const iterationTypes = getIterationTypesOfIterableCached(type, asyncIterationTypesResolver) || - getIterationTypesOfIterableFast(type, asyncIterationTypesResolver); + const iterationTypes = getIterationTypesOfIterableCached(type, asyncIterationTypesResolver) + || getIterationTypesOfIterableFast(type, asyncIterationTypesResolver); if (iterationTypes) { if (iterationTypes === noIterationTypes && errorNode) { // ignore the cached value noCache = true; } else { - return use & IterationUse.ForOfFlag ? - getAsyncFromSyncIterationTypes(iterationTypes, errorNode) : - iterationTypes; + return use & IterationUse.ForOfFlag + ? getAsyncFromSyncIterationTypes(iterationTypes, errorNode) + : iterationTypes; } } } if (use & IterationUse.AllowsSyncIterablesFlag) { - let iterationTypes = getIterationTypesOfIterableCached(type, syncIterationTypesResolver) || - getIterationTypesOfIterableFast(type, syncIterationTypesResolver); + let iterationTypes = getIterationTypesOfIterableCached(type, syncIterationTypesResolver) + || getIterationTypesOfIterableFast(type, syncIterationTypesResolver); if (iterationTypes) { if (iterationTypes === noIterationTypes && errorNode) { // ignore the cached value @@ -42501,7 +54221,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // for a sync iterable in an async context, only use the cached types if they are valid. if (iterationTypes !== noIterationTypes) { iterationTypes = getAsyncFromSyncIterationTypes(iterationTypes, errorNode); - return noCache ? iterationTypes : setCachedIterationTypes(type, "iterationTypesOfAsyncIterable", iterationTypes); + return noCache ? iterationTypes + : setCachedIterationTypes(type, "iterationTypesOfAsyncIterable", iterationTypes); } } else { @@ -42512,18 +54233,31 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } if (use & IterationUse.AllowsAsyncIterablesFlag) { - const iterationTypes = getIterationTypesOfIterableSlow(type, asyncIterationTypesResolver, errorNode, errorOutputContainer, noCache); + const iterationTypes = getIterationTypesOfIterableSlow( + type, + asyncIterationTypesResolver, + errorNode, + errorOutputContainer, + noCache, + ); if (iterationTypes !== noIterationTypes) { return iterationTypes; } } if (use & IterationUse.AllowsSyncIterablesFlag) { - let iterationTypes = getIterationTypesOfIterableSlow(type, syncIterationTypesResolver, errorNode, errorOutputContainer, noCache); + let iterationTypes = getIterationTypesOfIterableSlow( + type, + syncIterationTypesResolver, + errorNode, + errorOutputContainer, + noCache, + ); if (iterationTypes !== noIterationTypes) { if (use & IterationUse.AllowsAsyncIterablesFlag) { iterationTypes = getAsyncFromSyncIterationTypes(iterationTypes, errorNode); - return noCache ? iterationTypes : setCachedIterationTypes(type, "iterationTypesOfAsyncIterable", iterationTypes); + return noCache ? iterationTypes + : setCachedIterationTypes(type, "iterationTypesOfAsyncIterable", iterationTypes); } else { return iterationTypes; @@ -42546,8 +54280,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function getIterationTypesOfGlobalIterableType(globalType: Type, resolver: IterationTypesResolver) { - const globalIterationTypes = getIterationTypesOfIterableCached(globalType, resolver) || - getIterationTypesOfIterableSlow(globalType, resolver, /*errorNode*/ undefined, /*errorOutputContainer*/ undefined, /*noCache*/ false); + const globalIterationTypes = getIterationTypesOfIterableCached(globalType, resolver) + || getIterationTypesOfIterableSlow( + globalType, + resolver, + /*errorNode*/ undefined, + /*errorOutputContainer*/ undefined, + /*noCache*/ false, + ); return globalIterationTypes === noIterationTypes ? defaultIterationTypes : globalIterationTypes; } @@ -42570,8 +54310,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // - `IterableIterator` or `AsyncIterableIterator` let globalType: Type; if ( - isReferenceToType(type, globalType = resolver.getGlobalIterableType(/*reportErrors*/ false)) || - isReferenceToType(type, globalType = resolver.getGlobalIterableIteratorType(/*reportErrors*/ false)) + isReferenceToType(type, globalType = resolver.getGlobalIterableType(/*reportErrors*/ false)) + || isReferenceToType(type, globalType = resolver.getGlobalIterableIteratorType(/*reportErrors*/ false)) ) { const [yieldType] = getTypeArguments(type as GenericType); // The "return" and "next" types of `Iterable` and `IterableIterator` are defined by the @@ -42579,7 +54319,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // While we define these as `any` and `undefined` in our libs by default, a custom lib *could* use // different definitions. const { returnType, nextType } = getIterationTypesOfGlobalIterableType(globalType, resolver); - return setCachedIterationTypes(type, resolver.iterableCacheKey, createIterationTypes(resolver.resolveIterationType(yieldType, /*errorNode*/ undefined) || yieldType, resolver.resolveIterationType(returnType, /*errorNode*/ undefined) || returnType, nextType)); + return setCachedIterationTypes( + type, + resolver.iterableCacheKey, + createIterationTypes( + resolver.resolveIterationType(yieldType, /*errorNode*/ undefined) || yieldType, + resolver.resolveIterationType(returnType, /*errorNode*/ undefined) || returnType, + nextType, + ), + ); } // As an optimization, if the type is an instantiation of the following global type, then @@ -42587,14 +54335,24 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // - `Generator` or `AsyncGenerator` if (isReferenceToType(type, resolver.getGlobalGeneratorType(/*reportErrors*/ false))) { const [yieldType, returnType, nextType] = getTypeArguments(type as GenericType); - return setCachedIterationTypes(type, resolver.iterableCacheKey, createIterationTypes(resolver.resolveIterationType(yieldType, /*errorNode*/ undefined) || yieldType, resolver.resolveIterationType(returnType, /*errorNode*/ undefined) || returnType, nextType)); + return setCachedIterationTypes( + type, + resolver.iterableCacheKey, + createIterationTypes( + resolver.resolveIterationType(yieldType, /*errorNode*/ undefined) || yieldType, + resolver.resolveIterationType(returnType, /*errorNode*/ undefined) || returnType, + nextType, + ), + ); } } function getPropertyNameForKnownSymbolName(symbolName: string): __String { const ctorType = getGlobalESSymbolConstructorSymbol(/*reportErrors*/ false); - const uniqueType = ctorType && getTypeOfPropertyOfType(getTypeOfSymbol(ctorType), escapeLeadingUnderscores(symbolName)); - return uniqueType && isTypeUsableAsPropertyName(uniqueType) ? getPropertyNameFromType(uniqueType) : `__@${symbolName}` as __String; + const uniqueType = ctorType + && getTypeOfPropertyOfType(getTypeOfSymbol(ctorType), escapeLeadingUnderscores(symbolName)); + return uniqueType && isTypeUsableAsPropertyName(uniqueType) ? getPropertyNameFromType(uniqueType) + : `__@${symbolName}` as __String; } /** @@ -42607,20 +54365,30 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { * NOTE: You probably don't want to call this directly and should be calling * `getIterationTypesOfIterable` instead. */ - function getIterationTypesOfIterableSlow(type: Type, resolver: IterationTypesResolver, errorNode: Node | undefined, errorOutputContainer: { errors: Diagnostic[] | undefined; } | undefined, noCache: boolean) { + function getIterationTypesOfIterableSlow( + type: Type, + resolver: IterationTypesResolver, + errorNode: Node | undefined, + errorOutputContainer: { errors: Diagnostic[] | undefined; } | undefined, + noCache: boolean, + ) { const method = getPropertyOfType(type, getPropertyNameForKnownSymbolName(resolver.iteratorSymbolName)); const methodType = method && !(method.flags & SymbolFlags.Optional) ? getTypeOfSymbol(method) : undefined; if (isTypeAny(methodType)) { - return noCache ? anyIterationTypes : setCachedIterationTypes(type, resolver.iterableCacheKey, anyIterationTypes); + return noCache ? anyIterationTypes + : setCachedIterationTypes(type, resolver.iterableCacheKey, anyIterationTypes); } const signatures = methodType ? getSignaturesOfType(methodType, SignatureKind.Call) : undefined; if (!some(signatures)) { - return noCache ? noIterationTypes : setCachedIterationTypes(type, resolver.iterableCacheKey, noIterationTypes); + return noCache ? noIterationTypes + : setCachedIterationTypes(type, resolver.iterableCacheKey, noIterationTypes); } const iteratorType = getIntersectionType(map(signatures, getReturnTypeOfSignature)); - const iterationTypes = getIterationTypesOfIteratorWorker(iteratorType, resolver, errorNode, errorOutputContainer, noCache) ?? noIterationTypes; + const iterationTypes = + getIterationTypesOfIteratorWorker(iteratorType, resolver, errorNode, errorOutputContainer, noCache) + ?? noIterationTypes; return noCache ? iterationTypes : setCachedIterationTypes(type, resolver.iterableCacheKey, iterationTypes); } @@ -42633,11 +54401,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { !!getAwaitedTypeOfPromise(type) // for (const x of AsyncIterable<...>) || ( - !allowAsyncIterables && - isForOfStatement(errorNode.parent) && - errorNode.parent.expression === errorNode && - getGlobalAsyncIterableType(/*reportErrors*/ false) !== emptyGenericType && - isTypeAssignableTo(type, getGlobalAsyncIterableType(/*reportErrors*/ false)) + !allowAsyncIterables + && isForOfStatement(errorNode.parent) + && errorNode.parent.expression === errorNode + && getGlobalAsyncIterableType(/*reportErrors*/ false) !== emptyGenericType + && isTypeAssignableTo(type, getGlobalAsyncIterableType(/*reportErrors*/ false)) ); return errorAndMaybeSuggestAwait(errorNode, suggestAwait, message, typeToString(type)); } @@ -42648,7 +54416,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { * If we successfully found the *yield*, *return*, and *next* types, an `IterationTypes` * record is returned. Otherwise, `undefined` is returned. */ - function getIterationTypesOfIterator(type: Type, resolver: IterationTypesResolver, errorNode: Node | undefined, errorOutputContainer: { errors: Diagnostic[] | undefined; } | undefined) { + function getIterationTypesOfIterator( + type: Type, + resolver: IterationTypesResolver, + errorNode: Node | undefined, + errorOutputContainer: { errors: Diagnostic[] | undefined; } | undefined, + ) { return getIterationTypesOfIteratorWorker(type, resolver, errorNode, errorOutputContainer, /*noCache*/ false); } @@ -42661,13 +54434,19 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { * NOTE: You probably don't want to call this directly and should be calling * `getIterationTypesOfIterator` instead. */ - function getIterationTypesOfIteratorWorker(type: Type, resolver: IterationTypesResolver, errorNode: Node | undefined, errorOutputContainer: { errors: Diagnostic[] | undefined; } | undefined, noCache: boolean) { + function getIterationTypesOfIteratorWorker( + type: Type, + resolver: IterationTypesResolver, + errorNode: Node | undefined, + errorOutputContainer: { errors: Diagnostic[] | undefined; } | undefined, + noCache: boolean, + ) { if (isTypeAny(type)) { return anyIterationTypes; } - let iterationTypes = getIterationTypesOfIteratorCached(type, resolver) || - getIterationTypesOfIteratorFast(type, resolver); + let iterationTypes = getIterationTypesOfIteratorCached(type, resolver) + || getIterationTypesOfIteratorFast(type, resolver); if (iterationTypes === noIterationTypes && errorNode) { iterationTypes = undefined; @@ -42713,17 +54492,32 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // The "return" and "next" types of `IterableIterator` and `AsyncIterableIterator` are defined by the // iteration types of their `next`, `return`, and `throw` methods. While we define these as `any` // and `undefined` in our libs by default, a custom lib *could* use different definitions. - const globalIterationTypes = getIterationTypesOfIteratorCached(globalType, resolver) || - getIterationTypesOfIteratorSlow(globalType, resolver, /*errorNode*/ undefined, /*errorOutputContainer*/ undefined, /*noCache*/ false); - const { returnType, nextType } = globalIterationTypes === noIterationTypes ? defaultIterationTypes : globalIterationTypes; - return setCachedIterationTypes(type, resolver.iteratorCacheKey, createIterationTypes(yieldType, returnType, nextType)); + const globalIterationTypes = getIterationTypesOfIteratorCached(globalType, resolver) + || getIterationTypesOfIteratorSlow( + globalType, + resolver, + /*errorNode*/ undefined, + /*errorOutputContainer*/ undefined, + /*noCache*/ false, + ); + const { returnType, nextType } = globalIterationTypes === noIterationTypes ? defaultIterationTypes + : globalIterationTypes; + return setCachedIterationTypes( + type, + resolver.iteratorCacheKey, + createIterationTypes(yieldType, returnType, nextType), + ); } if ( - isReferenceToType(type, resolver.getGlobalIteratorType(/*reportErrors*/ false)) || - isReferenceToType(type, resolver.getGlobalGeneratorType(/*reportErrors*/ false)) + isReferenceToType(type, resolver.getGlobalIteratorType(/*reportErrors*/ false)) + || isReferenceToType(type, resolver.getGlobalGeneratorType(/*reportErrors*/ false)) ) { const [yieldType, returnType, nextType] = getTypeArguments(type as GenericType); - return setCachedIterationTypes(type, resolver.iteratorCacheKey, createIterationTypes(yieldType, returnType, nextType)); + return setCachedIterationTypes( + type, + resolver.iteratorCacheKey, + createIterationTypes(yieldType, returnType, nextType), + ); } } @@ -42765,19 +54559,29 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // or `IteratorReturnResult` types, then just grab its type argument. if (isReferenceToType(type, getGlobalIteratorYieldResultType(/*reportErrors*/ false))) { const yieldType = getTypeArguments(type as GenericType)[0]; - return setCachedIterationTypes(type, "iterationTypesOfIteratorResult", createIterationTypes(yieldType, /*returnType*/ undefined, /*nextType*/ undefined)); + return setCachedIterationTypes( + type, + "iterationTypesOfIteratorResult", + createIterationTypes(yieldType, /*returnType*/ undefined, /*nextType*/ undefined), + ); } if (isReferenceToType(type, getGlobalIteratorReturnResultType(/*reportErrors*/ false))) { const returnType = getTypeArguments(type as GenericType)[0]; - return setCachedIterationTypes(type, "iterationTypesOfIteratorResult", createIterationTypes(/*yieldType*/ undefined, returnType, /*nextType*/ undefined)); + return setCachedIterationTypes( + type, + "iterationTypesOfIteratorResult", + createIterationTypes(/*yieldType*/ undefined, returnType, /*nextType*/ undefined), + ); } // Choose any constituents that can produce the requested iteration type. const yieldIteratorResult = filterType(type, isYieldIteratorResult); - const yieldType = yieldIteratorResult !== neverType ? getTypeOfPropertyOfType(yieldIteratorResult, "value" as __String) : undefined; + const yieldType = yieldIteratorResult !== neverType + ? getTypeOfPropertyOfType(yieldIteratorResult, "value" as __String) : undefined; const returnIteratorResult = filterType(type, isReturnIteratorResult); - const returnType = returnIteratorResult !== neverType ? getTypeOfPropertyOfType(returnIteratorResult, "value" as __String) : undefined; + const returnType = returnIteratorResult !== neverType + ? getTypeOfPropertyOfType(returnIteratorResult, "value" as __String) : undefined; if (!yieldType && !returnType) { return setCachedIterationTypes(type, "iterationTypesOfIteratorResult", noIterationTypes); @@ -42787,7 +54591,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // > ... If the iterator does not have a return value, `value` is `undefined`. In that case, the // > `value` property may be absent from the conforming object if it does not inherit an explicit // > `value` property. - return setCachedIterationTypes(type, "iterationTypesOfIteratorResult", createIterationTypes(yieldType, returnType || voidType, /*nextType*/ undefined)); + return setCachedIterationTypes( + type, + "iterationTypesOfIteratorResult", + createIterationTypes(yieldType, returnType || voidType, /*nextType*/ undefined), + ); } /** @@ -42797,7 +54605,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { * If we successfully found the *yield*, *return*, and *next* types, an `IterationTypes` * record is returned. Otherwise, we return `undefined`. */ - function getIterationTypesOfMethod(type: Type, resolver: IterationTypesResolver, methodName: "next" | "return" | "throw", errorNode: Node | undefined, errorOutputContainer: { errors: Diagnostic[] | undefined; } | undefined): IterationTypes | undefined { + function getIterationTypesOfMethod( + type: Type, + resolver: IterationTypesResolver, + methodName: "next" | "return" | "throw", + errorNode: Node | undefined, + errorOutputContainer: { errors: Diagnostic[] | undefined; } | undefined, + ): IterationTypes | undefined { const method = getPropertyOfType(type, methodName as __String); // Ignore 'return' or 'throw' if they are missing. @@ -42806,7 +54620,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } const methodType = method && !(methodName === "next" && (method.flags & SymbolFlags.Optional)) - ? methodName === "next" ? getTypeOfSymbol(method) : getTypeWithFacts(getTypeOfSymbol(method), TypeFacts.NEUndefinedOrNull) + ? methodName === "next" ? getTypeOfSymbol(method) + : getTypeWithFacts(getTypeOfSymbol(method), TypeFacts.NEUndefinedOrNull) : undefined; if (isTypeAny(methodType)) { @@ -42842,8 +54657,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (methodType?.symbol && methodSignatures.length === 1) { const globalGeneratorType = resolver.getGlobalGeneratorType(/*reportErrors*/ false); const globalIteratorType = resolver.getGlobalIteratorType(/*reportErrors*/ false); - const isGeneratorMethod = globalGeneratorType.symbol?.members?.get(methodName as __String) === methodType.symbol; - const isIteratorMethod = !isGeneratorMethod && globalIteratorType.symbol?.members?.get(methodName as __String) === methodType.symbol; + const isGeneratorMethod = + globalGeneratorType.symbol?.members?.get(methodName as __String) === methodType.symbol; + const isIteratorMethod = !isGeneratorMethod + && globalIteratorType.symbol?.members?.get(methodName as __String) === methodType.symbol; if (isGeneratorMethod || isIteratorMethod) { const globalType = isGeneratorMethod ? globalGeneratorType : globalIteratorType; const { mapper } = methodType as AnonymousType; @@ -42877,7 +54694,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } else if (methodName === "return") { // The value of `return(value)` *is* awaited by async generators - const resolvedMethodParameterType = resolver.resolveIterationType(methodParameterType, errorNode) || anyType; + const resolvedMethodParameterType = resolver.resolveIterationType(methodParameterType, errorNode) + || anyType; returnTypes = append(returnTypes, resolvedMethodParameterType); } } @@ -42891,7 +54709,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (errorNode) { if (errorOutputContainer) { errorOutputContainer.errors ??= []; - errorOutputContainer.errors.push(createDiagnosticForNode(errorNode, resolver.mustHaveAValueDiagnostic, methodName)); + errorOutputContainer.errors.push( + createDiagnosticForNode(errorNode, resolver.mustHaveAValueDiagnostic, methodName), + ); } else { error(errorNode, resolver.mustHaveAValueDiagnostic, methodName); @@ -42918,7 +54738,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { * NOTE: You probably don't want to call this directly and should be calling * `getIterationTypesOfIterator` instead. */ - function getIterationTypesOfIteratorSlow(type: Type, resolver: IterationTypesResolver, errorNode: Node | undefined, errorOutputContainer: { errors: Diagnostic[] | undefined; } | undefined, noCache: boolean) { + function getIterationTypesOfIteratorSlow( + type: Type, + resolver: IterationTypesResolver, + errorNode: Node | undefined, + errorOutputContainer: { errors: Diagnostic[] | undefined; } | undefined, + noCache: boolean, + ) { const iterationTypes = combineIterationTypes([ getIterationTypesOfMethod(type, resolver, "next", errorNode, errorOutputContainer), getIterationTypesOfMethod(type, resolver, "return", errorNode, errorOutputContainer), @@ -42932,7 +54758,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { * `IterableIterator`-like, or `Generator`-like (for a non-async generator); or `AsyncIterable`-like, * `AsyncIterator`-like, `AsyncIterableIterator`-like, or `AsyncGenerator`-like (for an async generator). */ - function getIterationTypeOfGeneratorFunctionReturnType(kind: IterationTypeKind, returnType: Type, isAsyncGenerator: boolean): Type | undefined { + function getIterationTypeOfGeneratorFunctionReturnType( + kind: IterationTypeKind, + returnType: Type, + isAsyncGenerator: boolean, + ): Type | undefined { if (isTypeAny(returnType)) { return undefined; } @@ -42948,8 +54778,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const use = isAsyncGenerator ? IterationUse.AsyncGeneratorReturnType : IterationUse.GeneratorReturnType; const resolver = isAsyncGenerator ? asyncIterationTypesResolver : syncIterationTypesResolver; - return getIterationTypesOfIterable(type, use, /*errorNode*/ undefined) || - getIterationTypesOfIterator(type, resolver, /*errorNode*/ undefined, /*errorOutputContainer*/ undefined); + return getIterationTypesOfIterable(type, use, /*errorNode*/ undefined) + || getIterationTypesOfIterator(type, resolver, /*errorNode*/ undefined, /*errorOutputContainer*/ undefined); } function checkBreakOrContinueStatement(node: BreakOrContinueStatement) { @@ -42963,7 +54793,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const isGenerator = !!(functionFlags & FunctionFlags.Generator); const isAsync = !!(functionFlags & FunctionFlags.Async); if (isGenerator) { - const returnIterationType = getIterationTypeOfGeneratorFunctionReturnType(IterationTypeKind.Return, returnType, isAsync); + const returnIterationType = getIterationTypeOfGeneratorFunctionReturnType( + IterationTypeKind.Return, + returnType, + isAsync, + ); if (!returnIterationType) { return errorType; } @@ -42974,7 +54808,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function isUnwrappedReturnTypeUndefinedVoidOrAny(func: SignatureDeclaration, returnType: Type): boolean { const type = unwrapReturnType(returnType, getFunctionFlags(func)); - return !!(type && (maybeTypeOfKind(type, TypeFlags.Void) || type.flags & (TypeFlags.Any | TypeFlags.Undefined))); + return !!(type + && (maybeTypeOfKind(type, TypeFlags.Void) || type.flags & (TypeFlags.Any | TypeFlags.Undefined))); } function checkReturnStatement(node: ReturnStatement) { @@ -43005,24 +54840,45 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } else if (container.kind === SyntaxKind.Constructor) { - if (node.expression && !checkTypeAssignableToAndOptionallyElaborate(exprType, returnType, node, node.expression)) { - error(node, Diagnostics.Return_type_of_constructor_signature_must_be_assignable_to_the_instance_type_of_the_class); + if ( + node.expression + && !checkTypeAssignableToAndOptionallyElaborate(exprType, returnType, node, node.expression) + ) { + error( + node, + Diagnostics + .Return_type_of_constructor_signature_must_be_assignable_to_the_instance_type_of_the_class, + ); } } else if (getReturnTypeFromAnnotation(container)) { const unwrappedReturnType = unwrapReturnType(returnType, functionFlags) ?? returnType; const unwrappedExprType = functionFlags & FunctionFlags.Async - ? checkAwaitedType(exprType, /*withAlias*/ false, node, Diagnostics.The_return_type_of_an_async_function_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member) + ? checkAwaitedType( + exprType, + /*withAlias*/ false, + node, + Diagnostics + .The_return_type_of_an_async_function_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member, + ) : exprType; if (unwrappedReturnType) { // If the function has a return type, but promisedType is // undefined, an error will be reported in checkAsyncFunctionReturnType // so we don't need to report one here. - checkTypeAssignableToAndOptionallyElaborate(unwrappedExprType, unwrappedReturnType, node, node.expression); + checkTypeAssignableToAndOptionallyElaborate( + unwrappedExprType, + unwrappedReturnType, + node, + node.expression, + ); } } } - else if (container.kind !== SyntaxKind.Constructor && compilerOptions.noImplicitReturns && !isUnwrappedReturnTypeUndefinedVoidOrAny(container, returnType)) { + else if ( + container.kind !== SyntaxKind.Constructor && compilerOptions.noImplicitReturns + && !isUnwrappedReturnTypeUndefinedVoidOrAny(container, returnType) + ) { // The function has a return type, but the return statement doesn't have an expression. error(node, Diagnostics.Not_all_code_paths_return_a_value); } @@ -43042,7 +54898,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (!hasParseDiagnostics(sourceFile)) { const start = getSpanOfTokenAtPosition(sourceFile, node.pos).start; const end = node.statement.pos; - grammarErrorAtPos(sourceFile, start, end - start, Diagnostics.The_with_statement_is_not_supported_All_symbols_in_a_with_block_will_have_type_any); + grammarErrorAtPos( + sourceFile, + start, + end - start, + Diagnostics.The_with_statement_is_not_supported_All_symbols_in_a_with_block_will_have_type_any, + ); } } @@ -43062,7 +54923,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { firstDefaultClause = clause; } else { - grammarErrorOnNode(clause, Diagnostics.A_default_clause_cannot_appear_more_than_once_in_a_switch_statement); + grammarErrorOnNode( + clause, + Diagnostics.A_default_clause_cannot_appear_more_than_once_in_a_switch_statement, + ); hasDuplicateDefaultClause = true; } } @@ -43071,7 +54935,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { addLazyDiagnostic(createLazyCaseClauseDiagnostics(clause)); } forEach(clause.statements, checkSourceElement); - if (compilerOptions.noFallthroughCasesInSwitch && clause.fallthroughFlowNode && isReachableFlowNode(clause.fallthroughFlowNode)) { + if ( + compilerOptions.noFallthroughCasesInSwitch && clause.fallthroughFlowNode + && isReachableFlowNode(clause.fallthroughFlowNode) + ) { error(clause, Diagnostics.Fallthrough_case_in_switch); } @@ -43101,7 +54968,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (isFunctionLike(current)) { return "quit"; } - if (current.kind === SyntaxKind.LabeledStatement && (current as LabeledStatement).label.escapedText === node.label.escapedText) { + if ( + current.kind === SyntaxKind.LabeledStatement + && (current as LabeledStatement).label.escapedText === node.label.escapedText + ) { grammarErrorOnNode(node.label, Diagnostics.Duplicate_label_0, getTextOfNode(node.label)); return true; } @@ -43141,19 +55011,32 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (typeNode) { const type = getTypeFromTypeNode(typeNode); if (type && !(type.flags & TypeFlags.AnyOrUnknown)) { - grammarErrorOnFirstToken(typeNode, Diagnostics.Catch_clause_variable_type_annotation_must_be_any_or_unknown_if_specified); + grammarErrorOnFirstToken( + typeNode, + Diagnostics.Catch_clause_variable_type_annotation_must_be_any_or_unknown_if_specified, + ); } } else if (declaration.initializer) { - grammarErrorOnFirstToken(declaration.initializer, Diagnostics.Catch_clause_variable_cannot_have_an_initializer); + grammarErrorOnFirstToken( + declaration.initializer, + Diagnostics.Catch_clause_variable_cannot_have_an_initializer, + ); } else { const blockLocals = catchClause.block.locals; if (blockLocals) { forEachKey(catchClause.locals!, caughtName => { const blockLocal = blockLocals.get(caughtName); - if (blockLocal?.valueDeclaration && (blockLocal.flags & SymbolFlags.BlockScopedVariable) !== 0) { - grammarErrorOnNode(blockLocal.valueDeclaration, Diagnostics.Cannot_redeclare_identifier_0_in_catch_clause, unescapeLeadingUnderscores(caughtName)); + if ( + blockLocal?.valueDeclaration + && (blockLocal.flags & SymbolFlags.BlockScopedVariable) !== 0 + ) { + grammarErrorOnNode( + blockLocal.valueDeclaration, + Diagnostics.Cannot_redeclare_identifier_0_in_catch_clause, + unescapeLeadingUnderscores(caughtName), + ); } }); } @@ -43175,7 +55058,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } for (const prop of getPropertiesOfObjectType(type)) { if (!(isStaticIndex && prop.flags & SymbolFlags.Prototype)) { - checkIndexConstraintForProperty(type, prop, getLiteralTypeFromProperty(prop, TypeFlags.StringOrNumberLiteralOrUnique, /*includeNonPublic*/ true), getNonMissingTypeOfSymbol(prop)); + checkIndexConstraintForProperty( + type, + prop, + getLiteralTypeFromProperty( + prop, + TypeFlags.StringOrNumberLiteralOrUnique, + /*includeNonPublic*/ true, + ), + getNonMissingTypeOfSymbol(prop), + ); } } const typeDeclaration = symbol.valueDeclaration; @@ -43185,7 +55077,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // and properties with literal names were already checked. if (!isStatic(member) && !hasBindableName(member)) { const symbol = getSymbolOfDeclaration(member); - checkIndexConstraintForProperty(type, symbol, getTypeOfExpression((member as DynamicNamedDeclaration).name.expression), getNonMissingTypeOfSymbol(symbol)); + checkIndexConstraintForProperty( + type, + symbol, + getTypeOfExpression((member as DynamicNamedDeclaration).name.expression), + getNonMissingTypeOfSymbol(symbol), + ); } } } @@ -43203,21 +55100,40 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return; } const indexInfos = getApplicableIndexInfos(type, propNameType); - const interfaceDeclaration = getObjectFlags(type) & ObjectFlags.Interface ? getDeclarationOfKind(type.symbol, SyntaxKind.InterfaceDeclaration) : undefined; - const propDeclaration = declaration && declaration.kind === SyntaxKind.BinaryExpression || - name && name.kind === SyntaxKind.ComputedPropertyName ? declaration : undefined; + const interfaceDeclaration = getObjectFlags(type) & ObjectFlags.Interface + ? getDeclarationOfKind(type.symbol, SyntaxKind.InterfaceDeclaration) : undefined; + const propDeclaration = declaration && declaration.kind === SyntaxKind.BinaryExpression + || name && name.kind === SyntaxKind.ComputedPropertyName ? declaration : undefined; const localPropDeclaration = getParentOfSymbol(prop) === type.symbol ? declaration : undefined; for (const info of indexInfos) { - const localIndexDeclaration = info.declaration && getParentOfSymbol(getSymbolOfDeclaration(info.declaration)) === type.symbol ? info.declaration : undefined; + const localIndexDeclaration = + info.declaration && getParentOfSymbol(getSymbolOfDeclaration(info.declaration)) === type.symbol + ? info.declaration : undefined; // We check only when (a) the property is declared in the containing type, or (b) the applicable index signature is declared // in the containing type, or (c) the containing type is an interface and no base interface contains both the property and // the index signature (i.e. property and index signature are declared in separate inherited interfaces). - const errorNode = localPropDeclaration || localIndexDeclaration || - (interfaceDeclaration && !some(getBaseTypes(type as InterfaceType), base => !!getPropertyOfObjectType(base, prop.escapedName) && !!getIndexTypeOfType(base, info.keyType)) ? interfaceDeclaration : undefined); + const errorNode = localPropDeclaration || localIndexDeclaration + || (interfaceDeclaration + && !some( + getBaseTypes(type as InterfaceType), + base => + !!getPropertyOfObjectType(base, prop.escapedName) + && !!getIndexTypeOfType(base, info.keyType), + ) ? interfaceDeclaration : undefined); if (errorNode && !isTypeAssignableTo(propType, info.type)) { - const diagnostic = createError(errorNode, Diagnostics.Property_0_of_type_1_is_not_assignable_to_2_index_type_3, symbolToString(prop), typeToString(propType), typeToString(info.keyType), typeToString(info.type)); + const diagnostic = createError( + errorNode, + Diagnostics.Property_0_of_type_1_is_not_assignable_to_2_index_type_3, + symbolToString(prop), + typeToString(propType), + typeToString(info.keyType), + typeToString(info.type), + ); if (propDeclaration && errorNode !== propDeclaration) { - addRelatedInfo(diagnostic, createDiagnosticForNode(propDeclaration, Diagnostics._0_is_declared_here, symbolToString(prop))); + addRelatedInfo( + diagnostic, + createDiagnosticForNode(propDeclaration, Diagnostics._0_is_declared_here, symbolToString(prop)), + ); } diagnostics.add(diagnostic); } @@ -43227,18 +55143,36 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function checkIndexConstraintForIndexSignature(type: Type, checkInfo: IndexInfo) { const declaration = checkInfo.declaration; const indexInfos = getApplicableIndexInfos(type, checkInfo.keyType); - const interfaceDeclaration = getObjectFlags(type) & ObjectFlags.Interface ? getDeclarationOfKind(type.symbol, SyntaxKind.InterfaceDeclaration) : undefined; - const localCheckDeclaration = declaration && getParentOfSymbol(getSymbolOfDeclaration(declaration)) === type.symbol ? declaration : undefined; + const interfaceDeclaration = getObjectFlags(type) & ObjectFlags.Interface + ? getDeclarationOfKind(type.symbol, SyntaxKind.InterfaceDeclaration) : undefined; + const localCheckDeclaration = + declaration && getParentOfSymbol(getSymbolOfDeclaration(declaration)) === type.symbol ? declaration + : undefined; for (const info of indexInfos) { if (info === checkInfo) continue; - const localIndexDeclaration = info.declaration && getParentOfSymbol(getSymbolOfDeclaration(info.declaration)) === type.symbol ? info.declaration : undefined; + const localIndexDeclaration = + info.declaration && getParentOfSymbol(getSymbolOfDeclaration(info.declaration)) === type.symbol + ? info.declaration : undefined; // We check only when (a) the check index signature is declared in the containing type, or (b) the applicable index // signature is declared in the containing type, or (c) the containing type is an interface and no base interface contains // both index signatures (i.e. the index signatures are declared in separate inherited interfaces). - const errorNode = localCheckDeclaration || localIndexDeclaration || - (interfaceDeclaration && !some(getBaseTypes(type as InterfaceType), base => !!getIndexInfoOfType(base, checkInfo.keyType) && !!getIndexTypeOfType(base, info.keyType)) ? interfaceDeclaration : undefined); + const errorNode = localCheckDeclaration || localIndexDeclaration + || (interfaceDeclaration + && !some( + getBaseTypes(type as InterfaceType), + base => + !!getIndexInfoOfType(base, checkInfo.keyType) + && !!getIndexTypeOfType(base, info.keyType), + ) ? interfaceDeclaration : undefined); if (errorNode && !isTypeAssignableTo(checkInfo.type, info.type)) { - error(errorNode, Diagnostics._0_index_type_1_is_not_assignable_to_2_index_type_3, typeToString(checkInfo.keyType), typeToString(checkInfo.type), typeToString(info.keyType), typeToString(info.type)); + error( + errorNode, + Diagnostics._0_index_type_1_is_not_assignable_to_2_index_type_3, + typeToString(checkInfo.keyType), + typeToString(checkInfo.type), + typeToString(info.keyType), + typeToString(info.type), + ); } } } @@ -43269,7 +55203,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { languageVersion >= ScriptTarget.ES5 && name.escapedText === "Object" && (moduleKind < ModuleKind.ES2015 || getSourceFileOfNode(name).impliedNodeFormat === ModuleKind.CommonJS) ) { - error(name, Diagnostics.Class_name_cannot_be_Object_when_targeting_ES5_with_module_0, ModuleKind[moduleKind]); // https://github.com/Microsoft/TypeScript/issues/17494 + error( + name, + Diagnostics.Class_name_cannot_be_Object_when_targeting_ES5_with_module_0, + ModuleKind[moduleKind], + ); // https://github.com/Microsoft/TypeScript/issues/17494 } } @@ -43294,10 +55232,17 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const lastJSDocParamIndex = jsdocParameters.length - 1; const lastJSDocParam = jsdocParameters[lastJSDocParamIndex]; if ( - isJs && lastJSDocParam && isIdentifier(lastJSDocParam.name) && lastJSDocParam.typeExpression && - lastJSDocParam.typeExpression.type && !parameters.has(lastJSDocParam.name.escapedText) && !excludedParameters.has(lastJSDocParamIndex) && !isArrayType(getTypeFromTypeNode(lastJSDocParam.typeExpression.type)) + isJs && lastJSDocParam && isIdentifier(lastJSDocParam.name) && lastJSDocParam.typeExpression + && lastJSDocParam.typeExpression.type && !parameters.has(lastJSDocParam.name.escapedText) + && !excludedParameters.has(lastJSDocParamIndex) + && !isArrayType(getTypeFromTypeNode(lastJSDocParam.typeExpression.type)) ) { - error(lastJSDocParam.name, Diagnostics.JSDoc_param_tag_has_name_0_but_there_is_no_parameter_with_that_name_It_would_match_arguments_if_it_had_an_array_type, idText(lastJSDocParam.name)); + error( + lastJSDocParam.name, + Diagnostics + .JSDoc_param_tag_has_name_0_but_there_is_no_parameter_with_that_name_It_would_match_arguments_if_it_had_an_array_type, + idText(lastJSDocParam.name), + ); } } else { @@ -43307,12 +55252,22 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } if (isQualifiedName(name)) { if (isJs) { - error(name, Diagnostics.Qualified_name_0_is_not_allowed_without_a_leading_param_object_1, entityNameToString(name), entityNameToString(name.left)); + error( + name, + Diagnostics.Qualified_name_0_is_not_allowed_without_a_leading_param_object_1, + entityNameToString(name), + entityNameToString(name.left), + ); } } else { if (!isNameFirst) { - errorOrSuggestion(isJs, name, Diagnostics.JSDoc_param_tag_has_name_0_but_there_is_no_parameter_with_that_name, idText(name)); + errorOrSuggestion( + isJs, + name, + Diagnostics.JSDoc_param_tag_has_name_0_but_there_is_no_parameter_with_that_name, + idText(name), + ); } } }); @@ -43352,7 +55307,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } /** Check that type parameter defaults only reference previously declared type parameters */ - function checkTypeParametersNotReferenced(root: TypeNode, typeParameters: readonly TypeParameterDeclaration[], index: number) { + function checkTypeParametersNotReferenced( + root: TypeNode, + typeParameters: readonly TypeParameterDeclaration[], + index: number, + ) { visit(root); function visit(node: Node) { if (node.kind === SyntaxKind.TypeReference) { @@ -43360,7 +55319,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (type.flags & TypeFlags.TypeParameter) { for (let i = index; i < typeParameters.length; i++) { if (type.symbol === getSymbolOfDeclaration(typeParameters[i])) { - error(node, Diagnostics.Type_parameter_defaults_can_only_reference_previously_declared_type_parameters); + error( + node, + Diagnostics + .Type_parameter_defaults_can_only_reference_previously_declared_type_parameters, + ); } } } @@ -43384,17 +55347,31 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } const type = getDeclaredTypeOfSymbol(symbol) as InterfaceType; - if (!areTypeParametersIdentical(declarations, type.localTypeParameters!, getEffectiveTypeParameterDeclarations)) { + if ( + !areTypeParametersIdentical( + declarations, + type.localTypeParameters!, + getEffectiveTypeParameterDeclarations, + ) + ) { // Report an error on every conflicting declaration. const name = symbolToString(symbol); for (const declaration of declarations) { - error(declaration.name, Diagnostics.All_declarations_of_0_must_have_identical_type_parameters, name); + error( + declaration.name, + Diagnostics.All_declarations_of_0_must_have_identical_type_parameters, + name, + ); } } } } - function areTypeParametersIdentical(declarations: readonly T[], targetParameters: TypeParameter[], getTypeParameterDeclarations: (node: T) => readonly TypeParameterDeclaration[]) { + function areTypeParametersIdentical( + declarations: readonly T[], + targetParameters: TypeParameter[], + getTypeParameterDeclarations: (node: T) => readonly TypeParameterDeclaration[], + ) { const maxTypeArgumentCount = length(targetParameters); const minTypeArgumentCount = getMinTypeArgumentCount(targetParameters); @@ -43441,13 +55418,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function getFirstTransformableStaticClassElement(node: ClassLikeDeclaration) { - const willTransformStaticElementsOfDecoratedClass = !legacyDecorators && languageVersion < ScriptTarget.ESNext && - classOrConstructorParameterIsDecorated(/*useLegacyDecorators*/ false, node); + const willTransformStaticElementsOfDecoratedClass = !legacyDecorators && languageVersion < ScriptTarget.ESNext + && classOrConstructorParameterIsDecorated(/*useLegacyDecorators*/ false, node); const willTransformPrivateElementsOrClassStaticBlocks = languageVersion <= ScriptTarget.ES2022; const willTransformInitializers = !emitStandardClassFields; if (willTransformStaticElementsOfDecoratedClass || willTransformPrivateElementsOrClassStaticBlocks) { for (const member of node.members) { - if (willTransformStaticElementsOfDecoratedClass && classElementOrClassElementParameterIsDecorated(/*useLegacyDecorators*/ false, member, node)) { + if ( + willTransformStaticElementsOfDecoratedClass + && classElementOrClassElementParameterIsDecorated(/*useLegacyDecorators*/ false, member, node) + ) { return firstOrUndefined(getDecorators(node)) ?? node; } else if (willTransformPrivateElementsOrClassStaticBlocks) { @@ -43456,8 +55436,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } else if (isStatic(member)) { if ( - isPrivateIdentifierClassElementDeclaration(member) || - willTransformInitializers && isInitializedProperty(member) + isPrivateIdentifierClassElementDeclaration(member) + || willTransformInitializers && isInitializedProperty(member) ) { return member; } @@ -43484,7 +55464,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (location) { checkExternalEmitHelpers(location, ExternalEmitHelpers.SetFunctionName); - if ((isPropertyAssignment(parent) || isPropertyDeclaration(parent) || isBindingElement(parent)) && isComputedPropertyName(parent.name)) { + if ( + (isPropertyAssignment(parent) || isPropertyDeclaration(parent) || isBindingElement(parent)) + && isComputedPropertyName(parent.name) + ) { checkExternalEmitHelpers(location, ExternalEmitHelpers.PropKey); } } @@ -43504,11 +55487,21 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function checkClassDeclaration(node: ClassDeclaration) { const firstDecorator = find(node.modifiers, isDecorator); - if (legacyDecorators && firstDecorator && some(node.members, p => hasStaticModifier(p) && isPrivateIdentifierClassElementDeclaration(p))) { - grammarErrorOnNode(firstDecorator, Diagnostics.Class_decorators_can_t_be_used_with_static_private_identifier_Consider_removing_the_experimental_decorator); + if ( + legacyDecorators && firstDecorator + && some(node.members, p => hasStaticModifier(p) && isPrivateIdentifierClassElementDeclaration(p)) + ) { + grammarErrorOnNode( + firstDecorator, + Diagnostics + .Class_decorators_can_t_be_used_with_static_private_identifier_Consider_removing_the_experimental_decorator, + ); } if (!node.name && !hasSyntacticModifier(node, ModifierFlags.Default)) { - grammarErrorOnFirstToken(node, Diagnostics.A_class_declaration_without_the_default_modifier_must_have_a_name); + grammarErrorOnFirstToken( + node, + Diagnostics.A_class_declaration_without_the_default_modifier_must_have_a_name, + ); } checkClassLikeDeclaration(node); forEach(node.members, checkSourceElement); @@ -43558,7 +55551,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { checkSourceElement(baseTypeNode.expression); if (some(baseTypeNode.typeArguments)) { forEach(baseTypeNode.typeArguments, checkSourceElement); - for (const constructor of getConstructorsForTypeArguments(staticBaseType, baseTypeNode.typeArguments, baseTypeNode)) { + for ( + const constructor of getConstructorsForTypeArguments( + staticBaseType, + baseTypeNode.typeArguments, + baseTypeNode, + ) + ) { if (!checkTypeArgumentConstraints(baseTypeNode, constructor.typeParameters!)) { break; } @@ -43566,30 +55565,68 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } const baseWithThis = getTypeWithThisArgument(baseType, type.thisType); if (!checkTypeAssignableTo(typeWithThis, baseWithThis, /*errorNode*/ undefined)) { - issueMemberSpecificError(node, typeWithThis, baseWithThis, Diagnostics.Class_0_incorrectly_extends_base_class_1); + issueMemberSpecificError( + node, + typeWithThis, + baseWithThis, + Diagnostics.Class_0_incorrectly_extends_base_class_1, + ); } else { // Report static side error only when instance type is assignable - checkTypeAssignableTo(staticType, getTypeWithoutSignatures(staticBaseType), node.name || node, Diagnostics.Class_static_side_0_incorrectly_extends_base_class_static_side_1); + checkTypeAssignableTo( + staticType, + getTypeWithoutSignatures(staticBaseType), + node.name || node, + Diagnostics.Class_static_side_0_incorrectly_extends_base_class_static_side_1, + ); } if (baseConstructorType.flags & TypeFlags.TypeVariable) { if (!isMixinConstructorType(staticType)) { - error(node.name || node, Diagnostics.A_mixin_class_must_have_a_constructor_with_a_single_rest_parameter_of_type_any); + error( + node.name || node, + Diagnostics + .A_mixin_class_must_have_a_constructor_with_a_single_rest_parameter_of_type_any, + ); } else { - const constructSignatures = getSignaturesOfType(baseConstructorType, SignatureKind.Construct); - if (constructSignatures.some(signature => signature.flags & SignatureFlags.Abstract) && !hasSyntacticModifier(node, ModifierFlags.Abstract)) { - error(node.name || node, Diagnostics.A_mixin_class_that_extends_from_a_type_variable_containing_an_abstract_construct_signature_must_also_be_declared_abstract); + const constructSignatures = getSignaturesOfType( + baseConstructorType, + SignatureKind.Construct, + ); + if ( + constructSignatures.some(signature => signature.flags & SignatureFlags.Abstract) + && !hasSyntacticModifier(node, ModifierFlags.Abstract) + ) { + error( + node.name || node, + Diagnostics + .A_mixin_class_that_extends_from_a_type_variable_containing_an_abstract_construct_signature_must_also_be_declared_abstract, + ); } } } - if (!(staticBaseType.symbol && staticBaseType.symbol.flags & SymbolFlags.Class) && !(baseConstructorType.flags & TypeFlags.TypeVariable)) { + if ( + !(staticBaseType.symbol && staticBaseType.symbol.flags & SymbolFlags.Class) + && !(baseConstructorType.flags & TypeFlags.TypeVariable) + ) { // When the static base type is a "class-like" constructor function (but not actually a class), we verify // that all instantiated base constructor signatures return the same type. - const constructors = getInstantiatedConstructorsForTypeArguments(staticBaseType, baseTypeNode.typeArguments, baseTypeNode); - if (forEach(constructors, sig => !isJSConstructor(sig.declaration) && !isTypeIdenticalTo(getReturnTypeOfSignature(sig), baseType))) { - error(baseTypeNode.expression, Diagnostics.Base_constructors_must_all_have_the_same_return_type); + const constructors = getInstantiatedConstructorsForTypeArguments( + staticBaseType, + baseTypeNode.typeArguments, + baseTypeNode, + ); + if ( + forEach(constructors, sig => + !isJSConstructor(sig.declaration) + && !isTypeIdenticalTo(getReturnTypeOfSignature(sig), baseType)) + ) { + error( + baseTypeNode.expression, + Diagnostics.Base_constructors_must_all_have_the_same_return_type, + ); } } checkKindsOfPropertyMemberOverrides(type, baseType); @@ -43603,7 +55640,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (implementedTypeNodes) { for (const typeRefNode of implementedTypeNodes) { if (!isEntityNameExpression(typeRefNode.expression) || isOptionalChain(typeRefNode.expression)) { - error(typeRefNode.expression, Diagnostics.A_class_can_only_implement_an_identifier_Slashqualified_name_with_optional_type_arguments); + error( + typeRefNode.expression, + Diagnostics + .A_class_can_only_implement_an_identifier_Slashqualified_name_with_optional_type_arguments, + ); } checkTypeReferenceNode(typeRefNode); addLazyDiagnostic(createImplementsDiagnostics(typeRefNode)); @@ -43622,23 +55663,33 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const t = getReducedType(getTypeFromTypeNode(typeRefNode)); if (!isErrorType(t)) { if (isValidBaseType(t)) { - const genericDiag = t.symbol && t.symbol.flags & SymbolFlags.Class ? - Diagnostics.Class_0_incorrectly_implements_class_1_Did_you_mean_to_extend_1_and_inherit_its_members_as_a_subclass : - Diagnostics.Class_0_incorrectly_implements_interface_1; + const genericDiag = t.symbol && t.symbol.flags & SymbolFlags.Class + ? Diagnostics + .Class_0_incorrectly_implements_class_1_Did_you_mean_to_extend_1_and_inherit_its_members_as_a_subclass + : Diagnostics.Class_0_incorrectly_implements_interface_1; const baseWithThis = getTypeWithThisArgument(t, type.thisType); if (!checkTypeAssignableTo(typeWithThis, baseWithThis, /*errorNode*/ undefined)) { issueMemberSpecificError(node, typeWithThis, baseWithThis, genericDiag); } } else { - error(typeRefNode, Diagnostics.A_class_can_only_implement_an_object_type_or_intersection_of_object_types_with_statically_known_members); + error( + typeRefNode, + Diagnostics + .A_class_can_only_implement_an_object_type_or_intersection_of_object_types_with_statically_known_members, + ); } } }; } } - function checkMembersForOverrideModifier(node: ClassLikeDeclaration, type: InterfaceType, typeWithThis: Type, staticType: ObjectType) { + function checkMembersForOverrideModifier( + node: ClassLikeDeclaration, + type: InterfaceType, + typeWithThis: Type, + staticType: ObjectType, + ) { const baseTypeNode = getEffectiveBaseTypeNode(node); const baseTypes = baseTypeNode && getBaseTypes(type); const baseWithThis = baseTypes?.length ? getTypeWithThisArgument(first(baseTypes), type.thisType) : undefined; @@ -43751,20 +55802,24 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (prop && !baseProp && memberHasOverrideModifier) { if (errorNode) { const suggestion = getSuggestedSymbolForNonexistentClassMember(memberName, baseType); // Again, using symbol name: note that's different from `symbol.escapedName` - suggestion ? - error( + suggestion + ? error( errorNode, - isJs ? - Diagnostics.This_member_cannot_have_a_JSDoc_comment_with_an_override_tag_because_it_is_not_declared_in_the_base_class_0_Did_you_mean_1 : - Diagnostics.This_member_cannot_have_an_override_modifier_because_it_is_not_declared_in_the_base_class_0_Did_you_mean_1, + isJs + ? Diagnostics + .This_member_cannot_have_a_JSDoc_comment_with_an_override_tag_because_it_is_not_declared_in_the_base_class_0_Did_you_mean_1 + : Diagnostics + .This_member_cannot_have_an_override_modifier_because_it_is_not_declared_in_the_base_class_0_Did_you_mean_1, baseClassName, symbolToString(suggestion), - ) : - error( + ) + : error( errorNode, - isJs ? - Diagnostics.This_member_cannot_have_a_JSDoc_comment_with_an_override_tag_because_it_is_not_declared_in_the_base_class_0 : - Diagnostics.This_member_cannot_have_an_override_modifier_because_it_is_not_declared_in_the_base_class_0, + isJs + ? Diagnostics + .This_member_cannot_have_a_JSDoc_comment_with_an_override_tag_because_it_is_not_declared_in_the_base_class_0 + : Diagnostics + .This_member_cannot_have_an_override_modifier_because_it_is_not_declared_in_the_base_class_0, baseClassName, ); } @@ -43778,20 +55833,29 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (!baseHasAbstract) { if (errorNode) { - const diag = memberIsParameterProperty ? - isJs ? - Diagnostics.This_parameter_property_must_have_a_JSDoc_comment_with_an_override_tag_because_it_overrides_a_member_in_the_base_class_0 : - Diagnostics.This_parameter_property_must_have_an_override_modifier_because_it_overrides_a_member_in_base_class_0 : - isJs ? - Diagnostics.This_member_must_have_a_JSDoc_comment_with_an_override_tag_because_it_overrides_a_member_in_the_base_class_0 : - Diagnostics.This_member_must_have_an_override_modifier_because_it_overrides_a_member_in_the_base_class_0; + const diag = memberIsParameterProperty + ? isJs + ? Diagnostics + .This_parameter_property_must_have_a_JSDoc_comment_with_an_override_tag_because_it_overrides_a_member_in_the_base_class_0 + : Diagnostics + .This_parameter_property_must_have_an_override_modifier_because_it_overrides_a_member_in_base_class_0 + : isJs + ? Diagnostics + .This_member_must_have_a_JSDoc_comment_with_an_override_tag_because_it_overrides_a_member_in_the_base_class_0 + : Diagnostics + .This_member_must_have_an_override_modifier_because_it_overrides_a_member_in_the_base_class_0; error(errorNode, diag, baseClassName); } return MemberOverrideStatus.NeedsOverride; } else if (memberHasAbstractModifier && baseHasAbstract) { if (errorNode) { - error(errorNode, Diagnostics.This_member_must_have_an_override_modifier_because_it_overrides_an_abstract_method_that_is_declared_in_the_base_class_0, baseClassName); + error( + errorNode, + Diagnostics + .This_member_must_have_an_override_modifier_because_it_overrides_an_abstract_method_that_is_declared_in_the_base_class_0, + baseClassName, + ); } return MemberOverrideStatus.NeedsOverride; } @@ -43802,9 +55866,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const className = typeToString(type); error( errorNode, - isJs ? - Diagnostics.This_member_cannot_have_a_JSDoc_comment_with_an_override_tag_because_its_containing_class_0_does_not_extend_another_class : - Diagnostics.This_member_cannot_have_an_override_modifier_because_its_containing_class_0_does_not_extend_another_class, + isJs + ? Diagnostics + .This_member_cannot_have_a_JSDoc_comment_with_an_override_tag_because_its_containing_class_0_does_not_extend_another_class + : Diagnostics + .This_member_cannot_have_an_override_modifier_because_its_containing_class_0_does_not_extend_another_class, className, ); } @@ -43814,7 +55880,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return MemberOverrideStatus.Ok; } - function issueMemberSpecificError(node: ClassLikeDeclaration, typeWithThis: Type, baseWithThis: Type, broadDiag: DiagnosticMessage) { + function issueMemberSpecificError( + node: ClassLikeDeclaration, + typeWithThis: Type, + baseWithThis: Type, + broadDiag: DiagnosticMessage, + ) { // iterate over all implemented properties and issue errors on each one which isn't compatible, rather than the class as a whole, if possible let issuedMemberError = false; for (const member of node.members) { @@ -43834,7 +55905,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { typeToString(typeWithThis), typeToString(baseWithThis), ); - if (!checkTypeAssignableTo(getTypeOfSymbol(prop), getTypeOfSymbol(baseProp), member.name || member, /*headMessage*/ undefined, rootChain)) { + if ( + !checkTypeAssignableTo( + getTypeOfSymbol(prop), + getTypeOfSymbol(baseProp), + member.name || member, + /*headMessage*/ undefined, + rootChain, + ) + ) { issuedMemberError = true; } } @@ -43853,7 +55932,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (declaration && hasEffectiveModifier(declaration, ModifierFlags.Private)) { const typeClassDeclaration = getClassLikeDeclarationOfSymbol(type.symbol)!; if (!isNodeWithinClass(node, typeClassDeclaration)) { - error(node, Diagnostics.Cannot_extend_a_class_0_Class_constructor_is_marked_as_private, getFullyQualifiedName(type.symbol)); + error( + node, + Diagnostics.Cannot_extend_a_class_0_Class_constructor_is_marked_as_private, + getFullyQualifiedName(type.symbol), + ); } } } @@ -43866,7 +55949,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { * @param memberSymbol Member symbol. * Note: `member` can be a synthetic node without a parent. */ - function getMemberOverrideModifierStatus(node: ClassLikeDeclaration, member: ClassElement, memberSymbol: Symbol): MemberOverrideStatus { + function getMemberOverrideModifierStatus( + node: ClassLikeDeclaration, + member: ClassElement, + memberSymbol: Symbol, + ): MemberOverrideStatus { if (!member.name) { return MemberOverrideStatus.Ok; } @@ -43908,7 +55995,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function getClassOrInterfaceDeclarationsOfSymbol(symbol: Symbol) { - return filter(symbol.declarations, (d: Declaration): d is ClassDeclaration | InterfaceDeclaration => d.kind === SyntaxKind.ClassDeclaration || d.kind === SyntaxKind.InterfaceDeclaration); + return filter( + symbol.declarations, + (d: Declaration): d is ClassDeclaration | InterfaceDeclaration => + d.kind === SyntaxKind.ClassDeclaration || d.kind === SyntaxKind.InterfaceDeclaration, + ); } function checkKindsOfPropertyMemberOverrides(type: InterfaceType, baseType: BaseType): void { @@ -43955,7 +56046,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // It is an error to inherit an abstract member without implementing it or being declared abstract. // If there is no declaration for the derived class (as in the case of class expressions), // then the class cannot be declared abstract. - if (baseDeclarationFlags & ModifierFlags.Abstract && (!derivedClassDecl || !hasSyntacticModifier(derivedClassDecl, ModifierFlags.Abstract))) { + if ( + baseDeclarationFlags & ModifierFlags.Abstract + && (!derivedClassDecl || !hasSyntacticModifier(derivedClassDecl, ModifierFlags.Abstract)) + ) { // Searches other base types for a declaration that would satisfy the inherited abstract member. // (The class may have more than one base type via declaration merging with an interface with the // same name.) @@ -43980,8 +56074,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { addRelatedInfo( inheritedAbstractMemberNotImplementedError, createDiagnosticForNode( - baseProperty.valueDeclaration ?? (baseProperty.declarations && first(baseProperty.declarations)) ?? derivedClassDecl, - Diagnostics.Non_abstract_class_expression_does_not_implement_inherited_abstract_member_0_from_class_1, + baseProperty.valueDeclaration + ?? (baseProperty.declarations && first(baseProperty.declarations)) + ?? derivedClassDecl, + Diagnostics + .Non_abstract_class_expression_does_not_implement_inherited_abstract_member_0_from_class_1, symbolToString(baseProperty), typeToString(baseType), ), @@ -43991,8 +56088,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { addRelatedInfo( inheritedAbstractMemberNotImplementedError, createDiagnosticForNode( - baseProperty.valueDeclaration ?? (baseProperty.declarations && first(baseProperty.declarations)) ?? derivedClassDecl, - Diagnostics.Non_abstract_class_0_does_not_implement_inherited_abstract_member_1_from_class_2, + baseProperty.valueDeclaration + ?? (baseProperty.declarations && first(baseProperty.declarations)) + ?? derivedClassDecl, + Diagnostics + .Non_abstract_class_0_does_not_implement_inherited_abstract_member_1_from_class_2, typeToString(type), symbolToString(baseProperty), typeToString(baseType), @@ -44027,16 +56127,28 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { continue; } - const overriddenInstanceProperty = basePropertyFlags !== SymbolFlags.Property && derivedPropertyFlags === SymbolFlags.Property; - const overriddenInstanceAccessor = basePropertyFlags === SymbolFlags.Property && derivedPropertyFlags !== SymbolFlags.Property; + const overriddenInstanceProperty = basePropertyFlags !== SymbolFlags.Property + && derivedPropertyFlags === SymbolFlags.Property; + const overriddenInstanceAccessor = basePropertyFlags === SymbolFlags.Property + && derivedPropertyFlags !== SymbolFlags.Property; if (overriddenInstanceProperty || overriddenInstanceAccessor) { - const errorMessage = overriddenInstanceProperty ? - Diagnostics._0_is_defined_as_an_accessor_in_class_1_but_is_overridden_here_in_2_as_an_instance_property : - Diagnostics._0_is_defined_as_a_property_in_class_1_but_is_overridden_here_in_2_as_an_accessor; - error(getNameOfDeclaration(derived.valueDeclaration) || derived.valueDeclaration, errorMessage, symbolToString(base), typeToString(baseType), typeToString(type)); + const errorMessage = overriddenInstanceProperty + ? Diagnostics + ._0_is_defined_as_an_accessor_in_class_1_but_is_overridden_here_in_2_as_an_instance_property + : Diagnostics + ._0_is_defined_as_a_property_in_class_1_but_is_overridden_here_in_2_as_an_accessor; + error( + getNameOfDeclaration(derived.valueDeclaration) || derived.valueDeclaration, + errorMessage, + symbolToString(base), + typeToString(baseType), + typeToString(type), + ); } else if (useDefineForClassFields) { - const uninitialized = derived.declarations?.find(d => d.kind === SyntaxKind.PropertyDeclaration && !(d as PropertyDeclaration).initializer); + const uninitialized = derived.declarations?.find(d => + d.kind === SyntaxKind.PropertyDeclaration && !(d as PropertyDeclaration).initializer + ); if ( uninitialized && !(derived.flags & SymbolFlags.Transient) @@ -44044,7 +56156,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { && !(derivedDeclarationFlags & ModifierFlags.Abstract) && !derived.declarations?.some(d => !!(d.flags & NodeFlags.Ambient)) ) { - const constructor = findConstructorDeclaration(getClassLikeDeclarationOfSymbol(type.symbol)!); + const constructor = findConstructorDeclaration( + getClassLikeDeclarationOfSymbol(type.symbol)!, + ); const propName = (uninitialized as PropertyDeclaration).name; if ( (uninitialized as PropertyDeclaration).exclamationToken @@ -44053,8 +56167,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { || !strictNullChecks || !isPropertyInitializedInConstructor(propName, type, constructor) ) { - const errorMessage = Diagnostics.Property_0_will_overwrite_the_base_property_in_1_If_this_is_intentional_add_an_initializer_Otherwise_add_a_declare_modifier_or_remove_the_redundant_declaration; - error(getNameOfDeclaration(derived.valueDeclaration) || derived.valueDeclaration, errorMessage, symbolToString(base), typeToString(baseType)); + const errorMessage = Diagnostics + .Property_0_will_overwrite_the_base_property_in_1_If_this_is_intentional_add_an_initializer_Otherwise_add_a_declare_modifier_or_remove_the_redundant_declaration; + error( + getNameOfDeclaration(derived.valueDeclaration) || derived.valueDeclaration, + errorMessage, + symbolToString(base), + typeToString(baseType), + ); } } } @@ -44069,23 +56189,33 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } else { Debug.assert(!!(derived.flags & SymbolFlags.Accessor)); - errorMessage = Diagnostics.Class_0_defines_instance_member_function_1_but_extended_class_2_defines_it_as_instance_member_accessor; + errorMessage = Diagnostics + .Class_0_defines_instance_member_function_1_but_extended_class_2_defines_it_as_instance_member_accessor; } } else if (base.flags & SymbolFlags.Accessor) { - errorMessage = Diagnostics.Class_0_defines_instance_member_accessor_1_but_extended_class_2_defines_it_as_instance_member_function; + errorMessage = Diagnostics + .Class_0_defines_instance_member_accessor_1_but_extended_class_2_defines_it_as_instance_member_function; } else { - errorMessage = Diagnostics.Class_0_defines_instance_member_property_1_but_extended_class_2_defines_it_as_instance_member_function; + errorMessage = Diagnostics + .Class_0_defines_instance_member_property_1_but_extended_class_2_defines_it_as_instance_member_function; } - error(getNameOfDeclaration(derived.valueDeclaration) || derived.valueDeclaration, errorMessage, typeToString(baseType), symbolToString(base), typeToString(type)); + error( + getNameOfDeclaration(derived.valueDeclaration) || derived.valueDeclaration, + errorMessage, + typeToString(baseType), + symbolToString(base), + typeToString(type), + ); } } } function isPropertyAbstractOrInterface(declaration: Declaration, baseDeclarationFlags: ModifierFlags) { - return baseDeclarationFlags & ModifierFlags.Abstract && (!isPropertyDeclaration(declaration) || !declaration.initializer) + return baseDeclarationFlags & ModifierFlags.Abstract + && (!isPropertyDeclaration(declaration) || !declaration.initializer) || isInterfaceDeclaration(declaration.parent); } @@ -44142,9 +56272,23 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const typeName1 = typeToString(existing.containingType); const typeName2 = typeToString(base); - let errorInfo = chainDiagnosticMessages(/*details*/ undefined, Diagnostics.Named_property_0_of_types_1_and_2_are_not_identical, symbolToString(prop), typeName1, typeName2); - errorInfo = chainDiagnosticMessages(errorInfo, Diagnostics.Interface_0_cannot_simultaneously_extend_types_1_and_2, typeToString(type), typeName1, typeName2); - diagnostics.add(createDiagnosticForNodeFromMessageChain(getSourceFileOfNode(typeNode), typeNode, errorInfo)); + let errorInfo = chainDiagnosticMessages( + /*details*/ undefined, + Diagnostics.Named_property_0_of_types_1_and_2_are_not_identical, + symbolToString(prop), + typeName1, + typeName2, + ); + errorInfo = chainDiagnosticMessages( + errorInfo, + Diagnostics.Interface_0_cannot_simultaneously_extend_types_1_and_2, + typeToString(type), + typeName1, + typeName2, + ); + diagnostics.add( + createDiagnosticForNodeFromMessageChain(getSourceFileOfNode(typeNode), typeNode, errorInfo), + ); } } } @@ -44168,7 +56312,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const type = getTypeOfSymbol(getSymbolOfDeclaration(member)); if (!(type.flags & TypeFlags.AnyOrUnknown || containsUndefinedType(type))) { if (!constructor || !isPropertyInitializedInConstructor(propName, type, constructor)) { - error(member.name, Diagnostics.Property_0_has_no_initializer_and_is_not_definitely_assigned_in_the_constructor, declarationNameToString(propName)); + error( + member.name, + Diagnostics + .Property_0_has_no_initializer_and_is_not_definitely_assigned_in_the_constructor, + declarationNameToString(propName), + ); } } } @@ -44177,13 +56326,19 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function isPropertyWithoutInitializer(node: Node) { - return node.kind === SyntaxKind.PropertyDeclaration && - !hasAbstractModifier(node) && - !(node as PropertyDeclaration).exclamationToken && - !(node as PropertyDeclaration).initializer; - } - - function isPropertyInitializedInStaticBlocks(propName: Identifier | PrivateIdentifier, propType: Type, staticBlocks: readonly ClassStaticBlockDeclaration[], startPos: number, endPos: number) { + return node.kind === SyntaxKind.PropertyDeclaration + && !hasAbstractModifier(node) + && !(node as PropertyDeclaration).exclamationToken + && !(node as PropertyDeclaration).initializer; + } + + function isPropertyInitializedInStaticBlocks( + propName: Identifier | PrivateIdentifier, + propType: Type, + staticBlocks: readonly ClassStaticBlockDeclaration[], + startPos: number, + endPos: number, + ) { for (const staticBlock of staticBlocks) { // static block must be within the provided range as they are evaluated in document order (unlike constructors) if (staticBlock.pos >= startPos && staticBlock.pos <= endPos) { @@ -44200,7 +56355,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return false; } - function isPropertyInitializedInConstructor(propName: Identifier | PrivateIdentifier | ComputedPropertyName, propType: Type, constructor: ConstructorDeclaration) { + function isPropertyInitializedInConstructor( + propName: Identifier | PrivateIdentifier | ComputedPropertyName, + propType: Type, + constructor: ConstructorDeclaration, + ) { const reference = isComputedPropertyName(propName) ? factory.createElementAccessExpression(factory.createThis(), propName.expression) : factory.createPropertyAccessExpression(factory.createThis(), propName); @@ -44224,14 +56383,22 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { checkTypeParameterListsIdentical(symbol); // Only check this symbol once - const firstInterfaceDecl = getDeclarationOfKind(symbol, SyntaxKind.InterfaceDeclaration); + const firstInterfaceDecl = getDeclarationOfKind( + symbol, + SyntaxKind.InterfaceDeclaration, + ); if (node === firstInterfaceDecl) { const type = getDeclaredTypeOfSymbol(symbol) as InterfaceType; const typeWithThis = getTypeWithThisArgument(type); // run subsequent checks only if first set succeeded if (checkInheritedPropertiesAreIdentical(type, node.name)) { for (const baseType of getBaseTypes(type)) { - checkTypeAssignableTo(typeWithThis, getTypeWithThisArgument(baseType, type.thisType), node.name, Diagnostics.Interface_0_incorrectly_extends_interface_1); + checkTypeAssignableTo( + typeWithThis, + getTypeWithThisArgument(baseType, type.thisType), + node.name, + Diagnostics.Interface_0_incorrectly_extends_interface_1, + ); } checkIndexConstraints(type, symbol); } @@ -44240,7 +56407,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { }); forEach(getInterfaceBaseTypeNodes(node), heritageElement => { if (!isEntityNameExpression(heritageElement.expression) || isOptionalChain(heritageElement.expression)) { - error(heritageElement.expression, Diagnostics.An_interface_can_only_extend_an_identifier_Slashqualified_name_with_optional_type_arguments); + error( + heritageElement.expression, + Diagnostics + .An_interface_can_only_extend_an_identifier_Slashqualified_name_with_optional_type_arguments, + ); } checkTypeReferenceNode(heritageElement); }); @@ -44261,7 +56432,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { checkTypeParameters(node.typeParameters); if (node.type.kind === SyntaxKind.IntrinsicKeyword) { if (!intrinsicTypeKinds.has(node.name.escapedText as string) || length(node.typeParameters) !== 1) { - error(node.type, Diagnostics.The_intrinsic_keyword_can_only_be_used_to_declare_compiler_provided_intrinsic_types); + error( + node.type, + Diagnostics.The_intrinsic_keyword_can_only_be_used_to_declare_compiler_provided_intrinsic_types, + ); } } else { @@ -44320,9 +56494,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (isConstEnum && typeof value === "number" && !isFinite(value)) { error( initializer, - isNaN(value) ? - Diagnostics.const_enum_member_initializer_was_evaluated_to_disallowed_value_NaN : - Diagnostics.const_enum_member_initializer_was_evaluated_to_a_non_finite_value, + isNaN(value) + ? Diagnostics.const_enum_member_initializer_was_evaluated_to_disallowed_value_NaN + : Diagnostics.const_enum_member_initializer_was_evaluated_to_a_non_finite_value, ); } } @@ -44333,7 +56507,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { error(initializer, Diagnostics.In_ambient_enum_declarations_member_initializer_must_be_constant_expression); } else { - checkTypeAssignableTo(checkExpression(initializer), numberType, initializer, Diagnostics.Type_0_is_not_assignable_to_type_1_as_required_for_computed_enum_member_values); + checkTypeAssignableTo( + checkExpression(initializer), + numberType, + initializer, + Diagnostics.Type_0_is_not_assignable_to_type_1_as_required_for_computed_enum_member_values, + ); } return value; } @@ -44385,9 +56564,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } else if ( - (typeof left === "string" || typeof left === "number") && - (typeof right === "string" || typeof right === "number") && - (expr as BinaryExpression).operatorToken.kind === SyntaxKind.PlusToken + (typeof left === "string" || typeof left === "number") + && (typeof right === "string" || typeof right === "number") + && (expr as BinaryExpression).operatorToken.kind === SyntaxKind.PlusToken ) { return "" + left + right; } @@ -44404,7 +56583,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return evaluate((expr as ParenthesizedExpression).expression, location); case SyntaxKind.Identifier: { const identifier = expr as Identifier; - if (isInfinityOrNaNString(identifier.escapedText) && (resolveEntityName(identifier, SymbolFlags.Value, /*ignoreErrors*/ true) === getGlobalSymbol(identifier.escapedText, SymbolFlags.Value, /*diagnostic*/ undefined))) { + if ( + isInfinityOrNaNString(identifier.escapedText) + && (resolveEntityName(identifier, SymbolFlags.Value, /*ignoreErrors*/ true) + === getGlobalSymbol(identifier.escapedText, SymbolFlags.Value, /*diagnostic*/ undefined)) + ) { return +(identifier.escapedText); } // falls through @@ -44414,11 +56597,17 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const symbol = resolveEntityName(expr, SymbolFlags.Value, /*ignoreErrors*/ true); if (symbol) { if (symbol.flags & SymbolFlags.EnumMember) { - return location ? evaluateEnumMember(expr, symbol, location) : getEnumMemberValue(symbol.valueDeclaration as EnumMember); + return location ? evaluateEnumMember(expr, symbol, location) + : getEnumMemberValue(symbol.valueDeclaration as EnumMember); } if (isConstantVariable(symbol)) { const declaration = symbol.valueDeclaration as VariableDeclaration | undefined; - if (declaration && !declaration.type && declaration.initializer && (!location || declaration !== location && isBlockScopedNameDeclaredBeforeUse(declaration, location))) { + if ( + declaration && !declaration.type && declaration.initializer + && (!location + || declaration !== location + && isBlockScopedNameDeclaredBeforeUse(declaration, location)) + ) { return evaluate(declaration.initializer, declaration); } } @@ -44427,13 +56616,19 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { break; case SyntaxKind.ElementAccessExpression: const root = (expr as ElementAccessExpression).expression; - if (isEntityNameExpression(root) && isStringLiteralLike((expr as ElementAccessExpression).argumentExpression)) { + if ( + isEntityNameExpression(root) + && isStringLiteralLike((expr as ElementAccessExpression).argumentExpression) + ) { const rootSymbol = resolveEntityName(root, SymbolFlags.Value, /*ignoreErrors*/ true); if (rootSymbol && rootSymbol.flags & SymbolFlags.Enum) { - const name = escapeLeadingUnderscores(((expr as ElementAccessExpression).argumentExpression as StringLiteralLike).text); + const name = escapeLeadingUnderscores( + ((expr as ElementAccessExpression).argumentExpression as StringLiteralLike).text, + ); const member = rootSymbol.exports!.get(name); if (member) { - return location ? evaluateEnumMember(expr, member, location) : getEnumMemberValue(member.valueDeclaration as EnumMember); + return location ? evaluateEnumMember(expr, member, location) + : getEnumMemberValue(member.valueDeclaration as EnumMember); } } } @@ -44449,7 +56644,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return undefined; } if (!isBlockScopedNameDeclaredBeforeUse(declaration, location)) { - error(expr, Diagnostics.A_member_initializer_in_a_enum_declaration_cannot_reference_members_declared_after_it_including_members_defined_in_other_enums); + error( + expr, + Diagnostics + .A_member_initializer_in_a_enum_declaration_cannot_reference_members_declared_after_it_including_members_defined_in_other_enums, + ); return 0; } return getEnumMemberValue(declaration as EnumMember); @@ -44516,7 +56715,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const firstEnumMember = enumDeclaration.members[0]; if (!firstEnumMember.initializer) { if (seenEnumMissingInitialInitializer) { - error(firstEnumMember.name, Diagnostics.In_an_enum_with_multiple_declarations_only_one_declaration_can_omit_an_initializer_for_its_first_enum_element); + error( + firstEnumMember.name, + Diagnostics + .In_an_enum_with_multiple_declarations_only_one_declaration_can_omit_an_initializer_for_its_first_enum_element, + ); } else { seenEnumMissingInitialInitializer = true; @@ -44540,9 +56743,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (declarations) { for (const declaration of declarations) { if ( - (declaration.kind === SyntaxKind.ClassDeclaration || - (declaration.kind === SyntaxKind.FunctionDeclaration && nodeIsPresent((declaration as FunctionLikeDeclaration).body))) && - !(declaration.flags & NodeFlags.Ambient) + (declaration.kind === SyntaxKind.ClassDeclaration + || (declaration.kind === SyntaxKind.FunctionDeclaration + && nodeIsPresent((declaration as FunctionLikeDeclaration).body))) + && !(declaration.flags & NodeFlags.Ambient) ) { return declaration; } @@ -44580,7 +56784,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const isGlobalAugmentation = isGlobalScopeAugmentation(node); const inAmbientContext = node.flags & NodeFlags.Ambient; if (isGlobalAugmentation && !inAmbientContext) { - error(node.name, Diagnostics.Augmentations_for_the_global_scope_should_have_declare_modifier_unless_they_appear_in_already_ambient_context); + error( + node.name, + Diagnostics + .Augmentations_for_the_global_scope_should_have_declare_modifier_unless_they_appear_in_already_ambient_context, + ); } const isAmbientExternalModule: boolean = isAmbientModule(node); @@ -44615,16 +56823,29 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // This could be loosened a little if needed. The only problem we are trying to avoid is unqualified // references to namespace members declared in other files. But use of namespaces is discouraged anyway, // so for now we will just not allow them in scripts, which is the only place they can merge cross-file. - error(node.name, Diagnostics.Namespaces_are_not_allowed_in_global_script_files_when_0_is_enabled_If_this_file_is_not_intended_to_be_a_global_script_set_moduleDetection_to_force_or_add_an_empty_export_statement, isolatedModulesLikeFlagName); + error( + node.name, + Diagnostics + .Namespaces_are_not_allowed_in_global_script_files_when_0_is_enabled_If_this_file_is_not_intended_to_be_a_global_script_set_moduleDetection_to_force_or_add_an_empty_export_statement, + isolatedModulesLikeFlagName, + ); } if (symbol.declarations?.length! > 1) { const firstNonAmbientClassOrFunc = getFirstNonAmbientClassOrFunctionDeclaration(symbol); if (firstNonAmbientClassOrFunc) { if (getSourceFileOfNode(node) !== getSourceFileOfNode(firstNonAmbientClassOrFunc)) { - error(node.name, Diagnostics.A_namespace_declaration_cannot_be_in_a_different_file_from_a_class_or_function_with_which_it_is_merged); + error( + node.name, + Diagnostics + .A_namespace_declaration_cannot_be_in_a_different_file_from_a_class_or_function_with_which_it_is_merged, + ); } else if (node.pos < firstNonAmbientClassOrFunc.pos) { - error(node.name, Diagnostics.A_namespace_declaration_cannot_be_located_prior_to_a_class_or_function_with_which_it_is_merged); + error( + node.name, + Diagnostics + .A_namespace_declaration_cannot_be_located_prior_to_a_class_or_function_with_which_it_is_merged, + ); } } @@ -44632,20 +56853,24 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // we need to track this to ensure the correct emit. const mergedClass = getDeclarationOfKind(symbol, SyntaxKind.ClassDeclaration); if ( - mergedClass && - inSameLexicalScope(node, mergedClass) + mergedClass + && inSameLexicalScope(node, mergedClass) ) { getNodeLinks(node).flags |= NodeCheckFlags.LexicalModuleMergesWithClass; } } if ( - compilerOptions.verbatimModuleSyntax && - node.parent.kind === SyntaxKind.SourceFile && - (moduleKind === ModuleKind.CommonJS || node.parent.impliedNodeFormat === ModuleKind.CommonJS) + compilerOptions.verbatimModuleSyntax + && node.parent.kind === SyntaxKind.SourceFile + && (moduleKind === ModuleKind.CommonJS || node.parent.impliedNodeFormat === ModuleKind.CommonJS) ) { const exportModifier = node.modifiers?.find(m => m.kind === SyntaxKind.ExportKeyword); if (exportModifier) { - error(exportModifier, Diagnostics.A_top_level_export_modifier_cannot_be_used_on_value_declarations_in_a_CommonJS_module_when_verbatimModuleSyntax_is_enabled); + error( + exportModifier, + Diagnostics + .A_top_level_export_modifier_cannot_be_used_on_value_declarations_in_a_CommonJS_module_when_verbatimModuleSyntax_is_enabled, + ); } } } @@ -44657,7 +56882,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // We can detect if augmentation was applied using following rules: // - augmentation for a global scope is always applied // - augmentation for some external module is applied if symbol for augmentation is merged (it was combined with target module). - const checkBody = isGlobalAugmentation || (getSymbolOfDeclaration(node).flags & SymbolFlags.Transient); + const checkBody = isGlobalAugmentation + || (getSymbolOfDeclaration(node).flags & SymbolFlags.Transient); if (checkBody && node.body) { for (const statement of node.body.statements) { checkModuleAugmentationElement(statement, isGlobalAugmentation); @@ -44666,7 +56892,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } else if (isGlobalSourceFile(node.parent)) { if (isGlobalAugmentation) { - error(node.name, Diagnostics.Augmentations_for_the_global_scope_can_only_be_directly_nested_in_external_modules_or_ambient_module_declarations); + error( + node.name, + Diagnostics + .Augmentations_for_the_global_scope_can_only_be_directly_nested_in_external_modules_or_ambient_module_declarations, + ); } else if (isExternalModuleNameRelative(getTextOfIdentifierOrLiteral(node.name))) { error(node.name, Diagnostics.Ambient_module_declaration_cannot_specify_relative_module_name); @@ -44674,7 +56904,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } else { if (isGlobalAugmentation) { - error(node.name, Diagnostics.Augmentations_for_the_global_scope_can_only_be_directly_nested_in_external_modules_or_ambient_module_declarations); + error( + node.name, + Diagnostics + .Augmentations_for_the_global_scope_can_only_be_directly_nested_in_external_modules_or_ambient_module_declarations, + ); } else { // Node is not an augmentation and is not located on the script level. @@ -44696,11 +56930,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { break; case SyntaxKind.ExportAssignment: case SyntaxKind.ExportDeclaration: - grammarErrorOnFirstToken(node, Diagnostics.Exports_and_export_assignments_are_not_permitted_in_module_augmentations); + grammarErrorOnFirstToken( + node, + Diagnostics.Exports_and_export_assignments_are_not_permitted_in_module_augmentations, + ); break; case SyntaxKind.ImportEqualsDeclaration: case SyntaxKind.ImportDeclaration: - grammarErrorOnFirstToken(node, Diagnostics.Imports_are_not_permitted_in_module_augmentations_Consider_moving_them_to_the_enclosing_external_module); + grammarErrorOnFirstToken( + node, + Diagnostics + .Imports_are_not_permitted_in_module_augmentations_Consider_moving_them_to_the_enclosing_external_module, + ); break; case SyntaxKind.BindingElement: case SyntaxKind.VariableDeclaration: @@ -44748,7 +56989,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } - function checkExternalImportOrExportDeclaration(node: ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration): boolean { + function checkExternalImportOrExportDeclaration( + node: ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration, + ): boolean { const moduleName = getExternalModuleName(node); if (!moduleName || nodeIsMissing(moduleName)) { // Should be a parse error. @@ -44758,13 +57001,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { error(moduleName, Diagnostics.String_literal_expected); return false; } - const inAmbientExternalModule = node.parent.kind === SyntaxKind.ModuleBlock && isAmbientModule(node.parent.parent); + const inAmbientExternalModule = node.parent.kind === SyntaxKind.ModuleBlock + && isAmbientModule(node.parent.parent); if (node.parent.kind !== SyntaxKind.SourceFile && !inAmbientExternalModule) { error( moduleName, - node.kind === SyntaxKind.ExportDeclaration ? - Diagnostics.Export_declarations_are_not_permitted_in_a_namespace : - Diagnostics.Import_declarations_in_a_namespace_cannot_reference_a_module, + node.kind === SyntaxKind.ExportDeclaration + ? Diagnostics.Export_declarations_are_not_permitted_in_a_namespace + : Diagnostics.Import_declarations_in_a_namespace_cannot_reference_a_module, ); return false; } @@ -44776,7 +57020,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // An ExternalImportDeclaration in an AmbientExternalModuleDeclaration may reference // other external modules only through top - level external module names. // Relative external module names are not permitted. - error(node, Diagnostics.Import_or_export_declaration_in_an_ambient_module_declaration_cannot_reference_module_through_relative_module_name); + error( + node, + Diagnostics + .Import_or_export_declaration_in_an_ambient_module_declaration_cannot_reference_module_through_relative_module_name, + ); return false; } } @@ -44808,14 +57056,19 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // A type-only import/export will already have a grammar error in a JS file, so no need to issue more errors within if (isInJSFile(node) && !(target.flags & SymbolFlags.Value) && !isTypeOnlyImportOrExportDeclaration(node)) { - const errorNode = isImportOrExportSpecifier(node) ? node.propertyName || node.name : - isNamedDeclaration(node) ? node.name : - node; + const errorNode = isImportOrExportSpecifier(node) ? node.propertyName || node.name + : isNamedDeclaration(node) ? node.name + : node; Debug.assert(node.kind !== SyntaxKind.NamespaceExport); if (node.kind === SyntaxKind.ExportSpecifier) { - const diag = error(errorNode, Diagnostics.Types_cannot_appear_in_export_declarations_in_JavaScript_files); - const alreadyExportedSymbol = getSourceFileOfNode(node).symbol?.exports?.get((node.propertyName || node.name).escapedText); + const diag = error( + errorNode, + Diagnostics.Types_cannot_appear_in_export_declarations_in_JavaScript_files, + ); + const alreadyExportedSymbol = getSourceFileOfNode(node).symbol?.exports?.get( + (node.propertyName || node.name).escapedText, + ); if (alreadyExportedSymbol === target) { const exportingDeclaration = alreadyExportedSymbol.declarations?.find(isJSDocNode); if (exportingDeclaration) { @@ -44833,11 +57086,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { else { Debug.assert(node.kind !== SyntaxKind.VariableDeclaration); const importDeclaration = findAncestor(node, or(isImportDeclaration, isImportEqualsDeclaration)); - const moduleSpecifier = (importDeclaration && tryGetModuleSpecifierFromDeclaration(importDeclaration)?.text) ?? "..."; - const importedIdentifier = unescapeLeadingUnderscores(isIdentifier(errorNode) ? errorNode.escapedText : symbol.escapedName); + const moduleSpecifier = + (importDeclaration && tryGetModuleSpecifierFromDeclaration(importDeclaration)?.text) ?? "..."; + const importedIdentifier = unescapeLeadingUnderscores( + isIdentifier(errorNode) ? errorNode.escapedText : symbol.escapedName, + ); error( errorNode, - Diagnostics._0_is_a_type_and_cannot_be_imported_in_JavaScript_files_Use_1_in_a_JSDoc_type_annotation, + Diagnostics + ._0_is_a_type_and_cannot_be_imported_in_JavaScript_files_Use_1_in_a_JSDoc_type_annotation, importedIdentifier, `import("${moduleSpecifier}").${importedIdentifier}`, ); @@ -44846,13 +57103,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } const targetFlags = getSymbolFlags(target); - const excludedMeanings = (symbol.flags & (SymbolFlags.Value | SymbolFlags.ExportValue) ? SymbolFlags.Value : 0) | - (symbol.flags & SymbolFlags.Type ? SymbolFlags.Type : 0) | - (symbol.flags & SymbolFlags.Namespace ? SymbolFlags.Namespace : 0); + const excludedMeanings = + (symbol.flags & (SymbolFlags.Value | SymbolFlags.ExportValue) ? SymbolFlags.Value : 0) + | (symbol.flags & SymbolFlags.Type ? SymbolFlags.Type : 0) + | (symbol.flags & SymbolFlags.Namespace ? SymbolFlags.Namespace : 0); if (targetFlags & excludedMeanings) { - const message = node.kind === SyntaxKind.ExportSpecifier ? - Diagnostics.Export_declaration_conflicts_with_exported_declaration_of_0 : - Diagnostics.Import_declaration_conflicts_with_local_declaration_of_0; + const message = node.kind === SyntaxKind.ExportSpecifier + ? Diagnostics.Export_declaration_conflicts_with_exported_declaration_of_0 + : Diagnostics.Import_declaration_conflicts_with_local_declaration_of_0; error(node, message, symbolToString(symbol)); } @@ -44870,24 +57128,41 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { case SyntaxKind.ImportEqualsDeclaration: { if (compilerOptions.preserveValueImports || compilerOptions.verbatimModuleSyntax) { Debug.assertIsDefined(node.name, "An ImportClause with a symbol should have a name"); - const message = compilerOptions.verbatimModuleSyntax && isInternalModuleImportEqualsDeclaration(node) - ? Diagnostics.An_import_alias_cannot_resolve_to_a_type_or_type_only_declaration_when_verbatimModuleSyntax_is_enabled + const message = compilerOptions.verbatimModuleSyntax + && isInternalModuleImportEqualsDeclaration(node) + ? Diagnostics + .An_import_alias_cannot_resolve_to_a_type_or_type_only_declaration_when_verbatimModuleSyntax_is_enabled : isType ? compilerOptions.verbatimModuleSyntax - ? Diagnostics._0_is_a_type_and_must_be_imported_using_a_type_only_import_when_verbatimModuleSyntax_is_enabled - : Diagnostics._0_is_a_type_and_must_be_imported_using_a_type_only_import_when_preserveValueImports_and_isolatedModules_are_both_enabled + ? Diagnostics + ._0_is_a_type_and_must_be_imported_using_a_type_only_import_when_verbatimModuleSyntax_is_enabled + : Diagnostics + ._0_is_a_type_and_must_be_imported_using_a_type_only_import_when_preserveValueImports_and_isolatedModules_are_both_enabled : compilerOptions.verbatimModuleSyntax - ? Diagnostics._0_resolves_to_a_type_only_declaration_and_must_be_imported_using_a_type_only_import_when_verbatimModuleSyntax_is_enabled - : Diagnostics._0_resolves_to_a_type_only_declaration_and_must_be_imported_using_a_type_only_import_when_preserveValueImports_and_isolatedModules_are_both_enabled; - const name = idText(node.kind === SyntaxKind.ImportSpecifier ? node.propertyName || node.name : node.name); + ? Diagnostics + ._0_resolves_to_a_type_only_declaration_and_must_be_imported_using_a_type_only_import_when_verbatimModuleSyntax_is_enabled + : Diagnostics + ._0_resolves_to_a_type_only_declaration_and_must_be_imported_using_a_type_only_import_when_preserveValueImports_and_isolatedModules_are_both_enabled; + const name = idText( + node.kind === SyntaxKind.ImportSpecifier ? node.propertyName || node.name + : node.name, + ); addTypeOnlyDeclarationRelatedInfo( error(node, message, name), isType ? undefined : typeOnlyAlias, name, ); } - if (isType && node.kind === SyntaxKind.ImportEqualsDeclaration && hasEffectiveModifier(node, ModifierFlags.Export)) { - error(node, Diagnostics.Cannot_use_export_import_on_a_type_or_type_only_namespace_when_0_is_enabled, isolatedModulesLikeFlagName); + if ( + isType && node.kind === SyntaxKind.ImportEqualsDeclaration + && hasEffectiveModifier(node, ModifierFlags.Export) + ) { + error( + node, + Diagnostics + .Cannot_use_export_import_on_a_type_or_type_only_namespace_when_0_is_enabled, + isolatedModulesLikeFlagName, + ); } break; } @@ -44895,11 +57170,24 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // Don't allow re-exporting an export that will be elided when `--isolatedModules` is set. // The exception is that `import type { A } from './a'; export { A }` is allowed // because single-file analysis can determine that the export should be dropped. - if (compilerOptions.verbatimModuleSyntax || getSourceFileOfNode(typeOnlyAlias) !== getSourceFileOfNode(node)) { + if ( + compilerOptions.verbatimModuleSyntax + || getSourceFileOfNode(typeOnlyAlias) !== getSourceFileOfNode(node) + ) { const name = idText(node.propertyName || node.name); const diagnostic = isType - ? error(node, Diagnostics.Re_exporting_a_type_when_0_is_enabled_requires_using_export_type, isolatedModulesLikeFlagName) - : error(node, Diagnostics._0_resolves_to_a_type_only_declaration_and_must_be_re_exported_using_a_type_only_re_export_when_1_is_enabled, name, isolatedModulesLikeFlagName); + ? error( + node, + Diagnostics.Re_exporting_a_type_when_0_is_enabled_requires_using_export_type, + isolatedModulesLikeFlagName, + ) + : error( + node, + Diagnostics + ._0_resolves_to_a_type_only_declaration_and_must_be_re_exported_using_a_type_only_re_export_when_1_is_enabled, + name, + isolatedModulesLikeFlagName, + ); addTypeOnlyDeclarationRelatedInfo(diagnostic, isType ? undefined : typeOnlyAlias, name); break; } @@ -44908,12 +57196,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } if ( - compilerOptions.verbatimModuleSyntax && - node.kind !== SyntaxKind.ImportEqualsDeclaration && - !isInJSFile(node) && - (moduleKind === ModuleKind.CommonJS || getSourceFileOfNode(node).impliedNodeFormat === ModuleKind.CommonJS) + compilerOptions.verbatimModuleSyntax + && node.kind !== SyntaxKind.ImportEqualsDeclaration + && !isInJSFile(node) + && (moduleKind === ModuleKind.CommonJS + || getSourceFileOfNode(node).impliedNodeFormat === ModuleKind.CommonJS) ) { - error(node, Diagnostics.ESM_syntax_is_not_allowed_in_a_CommonJS_module_when_verbatimModuleSyntax_is_enabled); + error( + node, + Diagnostics.ESM_syntax_is_not_allowed_in_a_CommonJS_module_when_verbatimModuleSyntax_is_enabled, + ); } } @@ -44960,10 +57252,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { checkCollisionsForDeclarationName(node, node.name); checkAliasSymbol(node); if ( - node.kind === SyntaxKind.ImportSpecifier && - idText(node.propertyName || node.name) === "default" && - getESModuleInterop(compilerOptions) && - moduleKind !== ModuleKind.System && (moduleKind < ModuleKind.ES2015 || getSourceFileOfNode(node).impliedNodeFormat === ModuleKind.CommonJS) + node.kind === SyntaxKind.ImportSpecifier + && idText(node.propertyName || node.name) === "default" + && getESModuleInterop(compilerOptions) + && moduleKind !== ModuleKind.System + && (moduleKind < ModuleKind.ES2015 || getSourceFileOfNode(node).impliedNodeFormat === ModuleKind.CommonJS) ) { checkExternalEmitHelpers(node, ExternalEmitHelpers.ImportDefault); } @@ -44972,40 +57265,69 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function checkAssertClause(declaration: ImportDeclaration | ExportDeclaration) { if (declaration.assertClause) { const validForTypeAssertions = isExclusivelyTypeOnlyImportOrExport(declaration); - const override = getResolutionModeOverrideForClause(declaration.assertClause, validForTypeAssertions ? grammarErrorOnNode : undefined); + const override = getResolutionModeOverrideForClause( + declaration.assertClause, + validForTypeAssertions ? grammarErrorOnNode : undefined, + ); if (validForTypeAssertions && override) { if (!isNightly()) { - grammarErrorOnNode(declaration.assertClause, Diagnostics.resolution_mode_assertions_are_unstable_Use_nightly_TypeScript_to_silence_this_error_Try_updating_with_npm_install_D_typescript_next); + grammarErrorOnNode( + declaration.assertClause, + Diagnostics + .resolution_mode_assertions_are_unstable_Use_nightly_TypeScript_to_silence_this_error_Try_updating_with_npm_install_D_typescript_next, + ); } - if (getEmitModuleResolutionKind(compilerOptions) !== ModuleResolutionKind.Node16 && getEmitModuleResolutionKind(compilerOptions) !== ModuleResolutionKind.NodeNext) { - return grammarErrorOnNode(declaration.assertClause, Diagnostics.resolution_mode_assertions_are_only_supported_when_moduleResolution_is_node16_or_nodenext); + if ( + getEmitModuleResolutionKind(compilerOptions) !== ModuleResolutionKind.Node16 + && getEmitModuleResolutionKind(compilerOptions) !== ModuleResolutionKind.NodeNext + ) { + return grammarErrorOnNode( + declaration.assertClause, + Diagnostics + .resolution_mode_assertions_are_only_supported_when_moduleResolution_is_node16_or_nodenext, + ); } return; // Other grammar checks do not apply to type-only imports with resolution mode assertions } - const mode = (moduleKind === ModuleKind.NodeNext) && declaration.moduleSpecifier && getUsageModeForExpression(declaration.moduleSpecifier); + const mode = (moduleKind === ModuleKind.NodeNext) && declaration.moduleSpecifier + && getUsageModeForExpression(declaration.moduleSpecifier); if (mode !== ModuleKind.ESNext && moduleKind !== ModuleKind.ESNext) { return grammarErrorOnNode( declaration.assertClause, moduleKind === ModuleKind.NodeNext - ? Diagnostics.Import_assertions_are_not_allowed_on_statements_that_transpile_to_commonjs_require_calls - : Diagnostics.Import_assertions_are_only_supported_when_the_module_option_is_set_to_esnext_or_nodenext, + ? Diagnostics + .Import_assertions_are_not_allowed_on_statements_that_transpile_to_commonjs_require_calls + : Diagnostics + .Import_assertions_are_only_supported_when_the_module_option_is_set_to_esnext_or_nodenext, ); } if (isImportDeclaration(declaration) ? declaration.importClause?.isTypeOnly : declaration.isTypeOnly) { - return grammarErrorOnNode(declaration.assertClause, Diagnostics.Import_assertions_cannot_be_used_with_type_only_imports_or_exports); + return grammarErrorOnNode( + declaration.assertClause, + Diagnostics.Import_assertions_cannot_be_used_with_type_only_imports_or_exports, + ); } if (override) { - return grammarErrorOnNode(declaration.assertClause, Diagnostics.resolution_mode_can_only_be_set_for_type_only_imports); + return grammarErrorOnNode( + declaration.assertClause, + Diagnostics.resolution_mode_can_only_be_set_for_type_only_imports, + ); } } } function checkImportDeclaration(node: ImportDeclaration) { - if (checkGrammarModuleElementContext(node, isInJSFile(node) ? Diagnostics.An_import_declaration_can_only_be_used_at_the_top_level_of_a_module : Diagnostics.An_import_declaration_can_only_be_used_at_the_top_level_of_a_namespace_or_module)) { + if ( + checkGrammarModuleElementContext( + node, + isInJSFile(node) ? Diagnostics.An_import_declaration_can_only_be_used_at_the_top_level_of_a_module + : Diagnostics.An_import_declaration_can_only_be_used_at_the_top_level_of_a_namespace_or_module, + ) + ) { // If we hit an import declaration in an illegal context, just bail out to avoid cascading errors. return; } @@ -45021,7 +57343,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (importClause.namedBindings) { if (importClause.namedBindings.kind === SyntaxKind.NamespaceImport) { checkImportBinding(importClause.namedBindings); - if (moduleKind !== ModuleKind.System && (moduleKind < ModuleKind.ES2015 || getSourceFileOfNode(node).impliedNodeFormat === ModuleKind.CommonJS) && getESModuleInterop(compilerOptions)) { + if ( + moduleKind !== ModuleKind.System + && (moduleKind < ModuleKind.ES2015 + || getSourceFileOfNode(node).impliedNodeFormat === ModuleKind.CommonJS) + && getESModuleInterop(compilerOptions) + ) { // import * as ns from "foo"; checkExternalEmitHelpers(node, ExternalEmitHelpers.ImportStar); } @@ -45039,7 +57366,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function checkImportEqualsDeclaration(node: ImportEqualsDeclaration) { - if (checkGrammarModuleElementContext(node, isInJSFile(node) ? Diagnostics.An_import_declaration_can_only_be_used_at_the_top_level_of_a_module : Diagnostics.An_import_declaration_can_only_be_used_at_the_top_level_of_a_namespace_or_module)) { + if ( + checkGrammarModuleElementContext( + node, + isInJSFile(node) ? Diagnostics.An_import_declaration_can_only_be_used_at_the_top_level_of_a_module + : Diagnostics.An_import_declaration_can_only_be_used_at_the_top_level_of_a_namespace_or_module, + ) + ) { // If we hit an import declaration in an illegal context, just bail out to avoid cascading errors. return; } @@ -45057,8 +57390,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (targetFlags & SymbolFlags.Value) { // Target is a value symbol, check that it is not hidden by a local declaration with the same name const moduleName = getFirstIdentifier(node.moduleReference); - if (!(resolveEntityName(moduleName, SymbolFlags.Value | SymbolFlags.Namespace)!.flags & SymbolFlags.Namespace)) { - error(moduleName, Diagnostics.Module_0_is_hidden_by_a_local_declaration_with_the_same_name, declarationNameToString(moduleName)); + if ( + !(resolveEntityName(moduleName, SymbolFlags.Value | SymbolFlags.Namespace)!.flags + & SymbolFlags.Namespace) + ) { + error( + moduleName, + Diagnostics.Module_0_is_hidden_by_a_local_declaration_with_the_same_name, + declarationNameToString(moduleName), + ); } } if (targetFlags & SymbolFlags.Type) { @@ -45070,16 +57410,29 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } else { - if (moduleKind >= ModuleKind.ES2015 && getSourceFileOfNode(node).impliedNodeFormat === undefined && !node.isTypeOnly && !(node.flags & NodeFlags.Ambient)) { + if ( + moduleKind >= ModuleKind.ES2015 && getSourceFileOfNode(node).impliedNodeFormat === undefined + && !node.isTypeOnly && !(node.flags & NodeFlags.Ambient) + ) { // Import equals declaration is deprecated in es6 or above - grammarErrorOnNode(node, Diagnostics.Import_assignment_cannot_be_used_when_targeting_ECMAScript_modules_Consider_using_import_Asterisk_as_ns_from_mod_import_a_from_mod_import_d_from_mod_or_another_module_format_instead); + grammarErrorOnNode( + node, + Diagnostics + .Import_assignment_cannot_be_used_when_targeting_ECMAScript_modules_Consider_using_import_Asterisk_as_ns_from_mod_import_a_from_mod_import_d_from_mod_or_another_module_format_instead, + ); } } } } function checkExportDeclaration(node: ExportDeclaration) { - if (checkGrammarModuleElementContext(node, isInJSFile(node) ? Diagnostics.An_export_declaration_can_only_be_used_at_the_top_level_of_a_module : Diagnostics.An_export_declaration_can_only_be_used_at_the_top_level_of_a_namespace_or_module)) { + if ( + checkGrammarModuleElementContext( + node, + isInJSFile(node) ? Diagnostics.An_export_declaration_can_only_be_used_at_the_top_level_of_a_module + : Diagnostics.An_export_declaration_can_only_be_used_at_the_top_level_of_a_namespace_or_module, + ) + ) { // If we hit an export in an illegal context, just bail out to avoid cascading errors. return; } @@ -45088,7 +57441,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { grammarErrorOnFirstToken(node, Diagnostics.An_export_declaration_cannot_have_modifiers); } - if (node.moduleSpecifier && node.exportClause && isNamedExports(node.exportClause) && length(node.exportClause.elements) && languageVersion === ScriptTarget.ES3) { + if ( + node.moduleSpecifier && node.exportClause && isNamedExports(node.exportClause) + && length(node.exportClause.elements) && languageVersion === ScriptTarget.ES3 + ) { checkExternalEmitHelpers(node, ExternalEmitHelpers.CreateBinding); } @@ -45098,10 +57454,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // export { x, y } // export { x, y } from "foo" forEach(node.exportClause.elements, checkExportSpecifier); - const inAmbientExternalModule = node.parent.kind === SyntaxKind.ModuleBlock && isAmbientModule(node.parent.parent); - const inAmbientNamespaceDeclaration = !inAmbientExternalModule && node.parent.kind === SyntaxKind.ModuleBlock && - !node.moduleSpecifier && node.flags & NodeFlags.Ambient; - if (node.parent.kind !== SyntaxKind.SourceFile && !inAmbientExternalModule && !inAmbientNamespaceDeclaration) { + const inAmbientExternalModule = node.parent.kind === SyntaxKind.ModuleBlock + && isAmbientModule(node.parent.parent); + const inAmbientNamespaceDeclaration = !inAmbientExternalModule + && node.parent.kind === SyntaxKind.ModuleBlock + && !node.moduleSpecifier && node.flags & NodeFlags.Ambient; + if ( + node.parent.kind !== SyntaxKind.SourceFile && !inAmbientExternalModule + && !inAmbientNamespaceDeclaration + ) { error(node, Diagnostics.Export_declarations_are_not_permitted_in_a_namespace); } } @@ -45110,12 +57471,20 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // export * as ns from "foo"; const moduleSymbol = resolveExternalModuleName(node, node.moduleSpecifier!); if (moduleSymbol && hasExportAssignmentSymbol(moduleSymbol)) { - error(node.moduleSpecifier, Diagnostics.Module_0_uses_export_and_cannot_be_used_with_export_Asterisk, symbolToString(moduleSymbol)); + error( + node.moduleSpecifier, + Diagnostics.Module_0_uses_export_and_cannot_be_used_with_export_Asterisk, + symbolToString(moduleSymbol), + ); } else if (node.exportClause) { checkAliasSymbol(node.exportClause); } - if (moduleKind !== ModuleKind.System && (moduleKind < ModuleKind.ES2015 || getSourceFileOfNode(node).impliedNodeFormat === ModuleKind.CommonJS)) { + if ( + moduleKind !== ModuleKind.System + && (moduleKind < ModuleKind.ES2015 + || getSourceFileOfNode(node).impliedNodeFormat === ModuleKind.CommonJS) + ) { if (node.exportClause) { // export * as ns from "foo"; // For ES2015 modules, we emit it as a pair of `import * as a_1 ...; export { a_1 as ns }` and don't need the helper. @@ -45142,7 +57511,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function checkGrammarModuleElementContext(node: Statement, errorMessage: DiagnosticMessage): boolean { - const isInAppropriateContext = node.parent.kind === SyntaxKind.SourceFile || node.parent.kind === SyntaxKind.ModuleBlock || node.parent.kind === SyntaxKind.ModuleDeclaration; + const isInAppropriateContext = node.parent.kind === SyntaxKind.SourceFile + || node.parent.kind === SyntaxKind.ModuleBlock || node.parent.kind === SyntaxKind.ModuleDeclaration; if (!isInAppropriateContext) { grammarErrorOnFirstToken(node, errorMessage); } @@ -45162,21 +57532,21 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function canConvertImportDeclarationToTypeOnly(statement: Statement) { - return isImportDeclaration(statement) && - statement.importClause && - !statement.importClause.isTypeOnly && - importClauseContainsReferencedImport(statement.importClause) && - !isReferencedAliasDeclaration(statement.importClause, /*checkChildren*/ true) && - !importClauseContainsConstEnumUsedAsValue(statement.importClause); + return isImportDeclaration(statement) + && statement.importClause + && !statement.importClause.isTypeOnly + && importClauseContainsReferencedImport(statement.importClause) + && !isReferencedAliasDeclaration(statement.importClause, /*checkChildren*/ true) + && !importClauseContainsConstEnumUsedAsValue(statement.importClause); } function canConvertImportEqualsDeclarationToTypeOnly(statement: Statement) { - return isImportEqualsDeclaration(statement) && - isExternalModuleReference(statement.moduleReference) && - !statement.isTypeOnly && - getSymbolOfDeclaration(statement).isReferenced && - !isReferencedAliasDeclaration(statement, /*checkChildren*/ false) && - !getSymbolLinks(getSymbolOfDeclaration(statement)).constEnumReferenced; + return isImportEqualsDeclaration(statement) + && isExternalModuleReference(statement.moduleReference) + && !statement.isTypeOnly + && getSymbolOfDeclaration(statement).isReferenced + && !isReferencedAliasDeclaration(statement, /*checkChildren*/ false) + && !getSymbolLinks(getSymbolOfDeclaration(statement)).constEnumReferenced; } function checkImportsForTypeOnlyConversion(sourceFile: SourceFile) { @@ -45184,10 +57554,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return; } for (const statement of sourceFile.statements) { - if (canConvertImportDeclarationToTypeOnly(statement) || canConvertImportEqualsDeclarationToTypeOnly(statement)) { + if ( + canConvertImportDeclarationToTypeOnly(statement) + || canConvertImportEqualsDeclarationToTypeOnly(statement) + ) { error( statement, - Diagnostics.This_import_is_never_used_as_a_value_and_must_use_import_type_because_importsNotUsedAsValues_is_set_to_error, + Diagnostics + .This_import_is_never_used_as_a_value_and_must_use_import_type_because_importsNotUsedAsValues_is_set_to_error, ); } } @@ -45201,9 +57575,24 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (!node.parent.parent.moduleSpecifier) { const exportedName = node.propertyName || node.name; // find immediate value referenced by exported name (SymbolFlags.Alias is set so we don't chase down aliases) - const symbol = resolveName(exportedName, exportedName.escapedText, SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace | SymbolFlags.Alias, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ true); - if (symbol && (symbol === undefinedSymbol || symbol === globalThisSymbol || symbol.declarations && isGlobalSourceFile(getDeclarationContainer(symbol.declarations[0])))) { - error(exportedName, Diagnostics.Cannot_export_0_Only_local_declarations_can_be_exported_from_a_module, idText(exportedName)); + const symbol = resolveName( + exportedName, + exportedName.escapedText, + SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace | SymbolFlags.Alias, + /*nameNotFoundMessage*/ undefined, + /*nameArg*/ undefined, + /*isUse*/ true, + ); + if ( + symbol + && (symbol === undefinedSymbol || symbol === globalThisSymbol + || symbol.declarations && isGlobalSourceFile(getDeclarationContainer(symbol.declarations[0]))) + ) { + error( + exportedName, + Diagnostics.Cannot_export_0_Only_local_declarations_can_be_exported_from_a_module, + idText(exportedName), + ); } else { if (!node.isTypeOnly && !node.parent.parent.isTypeOnly) { @@ -45217,10 +57606,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } else { if ( - getESModuleInterop(compilerOptions) && - moduleKind !== ModuleKind.System && - (moduleKind < ModuleKind.ES2015 || getSourceFileOfNode(node).impliedNodeFormat === ModuleKind.CommonJS) && - idText(node.propertyName || node.name) === "default" + getESModuleInterop(compilerOptions) + && moduleKind !== ModuleKind.System + && (moduleKind < ModuleKind.ES2015 + || getSourceFileOfNode(node).impliedNodeFormat === ModuleKind.CommonJS) + && idText(node.propertyName || node.name) === "default" ) { checkExternalEmitHelpers(node, ExternalEmitHelpers.ImportDefault); } @@ -45236,7 +57626,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return; } - const container = node.parent.kind === SyntaxKind.SourceFile ? node.parent : node.parent.parent as ModuleDeclaration; + const container = node.parent.kind === SyntaxKind.SourceFile ? node.parent + : node.parent.parent as ModuleDeclaration; if (container.kind === SyntaxKind.ModuleDeclaration && !isAmbientModule(container)) { if (node.isExportEquals) { error(node, Diagnostics.An_export_assignment_cannot_be_used_in_a_namespace); @@ -45254,39 +57645,56 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const typeAnnotationNode = getEffectiveTypeAnnotationNode(node); if (typeAnnotationNode) { - checkTypeAssignableTo(checkExpressionCached(node.expression), getTypeFromTypeNode(typeAnnotationNode), node.expression); + checkTypeAssignableTo( + checkExpressionCached(node.expression), + getTypeFromTypeNode(typeAnnotationNode), + node.expression, + ); } - const isIllegalExportDefaultInCJS = !node.isExportEquals && - !(node.flags & NodeFlags.Ambient) && - compilerOptions.verbatimModuleSyntax && - (moduleKind === ModuleKind.CommonJS || getSourceFileOfNode(node).impliedNodeFormat === ModuleKind.CommonJS); + const isIllegalExportDefaultInCJS = !node.isExportEquals + && !(node.flags & NodeFlags.Ambient) + && compilerOptions.verbatimModuleSyntax + && (moduleKind === ModuleKind.CommonJS + || getSourceFileOfNode(node).impliedNodeFormat === ModuleKind.CommonJS); if (node.expression.kind === SyntaxKind.Identifier) { const id = node.expression as Identifier; - const sym = getExportSymbolOfValueSymbolIfExported(resolveEntityName(id, SymbolFlags.All, /*ignoreErrors*/ true, /*dontResolveAlias*/ true, node)); + const sym = getExportSymbolOfValueSymbolIfExported( + resolveEntityName(id, SymbolFlags.All, /*ignoreErrors*/ true, /*dontResolveAlias*/ true, node), + ); if (sym) { markAliasReferenced(sym, id); // If not a value, we're interpreting the identifier as a type export, along the lines of (`export { Id as default }`) if (getSymbolFlags(sym) & SymbolFlags.Value) { // However if it is a value, we need to check it's being used correctly checkExpressionCached(id); - if (!isIllegalExportDefaultInCJS && !(node.flags & NodeFlags.Ambient) && compilerOptions.verbatimModuleSyntax && getTypeOnlyAliasDeclaration(sym, SymbolFlags.Value)) { + if ( + !isIllegalExportDefaultInCJS && !(node.flags & NodeFlags.Ambient) + && compilerOptions.verbatimModuleSyntax && getTypeOnlyAliasDeclaration(sym, SymbolFlags.Value) + ) { error( id, node.isExportEquals - ? Diagnostics.An_export_declaration_must_reference_a_real_value_when_verbatimModuleSyntax_is_enabled_but_0_resolves_to_a_type_only_declaration - : Diagnostics.An_export_default_must_reference_a_real_value_when_verbatimModuleSyntax_is_enabled_but_0_resolves_to_a_type_only_declaration, + ? Diagnostics + .An_export_declaration_must_reference_a_real_value_when_verbatimModuleSyntax_is_enabled_but_0_resolves_to_a_type_only_declaration + : Diagnostics + .An_export_default_must_reference_a_real_value_when_verbatimModuleSyntax_is_enabled_but_0_resolves_to_a_type_only_declaration, idText(id), ); } } - else if (!isIllegalExportDefaultInCJS && !(node.flags & NodeFlags.Ambient) && compilerOptions.verbatimModuleSyntax) { + else if ( + !isIllegalExportDefaultInCJS && !(node.flags & NodeFlags.Ambient) + && compilerOptions.verbatimModuleSyntax + ) { error( id, node.isExportEquals - ? Diagnostics.An_export_declaration_must_reference_a_value_when_verbatimModuleSyntax_is_enabled_but_0_only_refers_to_a_type - : Diagnostics.An_export_default_must_reference_a_value_when_verbatimModuleSyntax_is_enabled_but_0_only_refers_to_a_type, + ? Diagnostics + .An_export_declaration_must_reference_a_value_when_verbatimModuleSyntax_is_enabled_but_0_only_refers_to_a_type + : Diagnostics + .An_export_default_must_reference_a_value_when_verbatimModuleSyntax_is_enabled_but_0_only_refers_to_a_type, idText(id), ); } @@ -45304,24 +57712,37 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } if (isIllegalExportDefaultInCJS) { - error(node, Diagnostics.ESM_syntax_is_not_allowed_in_a_CommonJS_module_when_verbatimModuleSyntax_is_enabled); + error( + node, + Diagnostics.ESM_syntax_is_not_allowed_in_a_CommonJS_module_when_verbatimModuleSyntax_is_enabled, + ); } checkExternalModuleExports(container); if ((node.flags & NodeFlags.Ambient) && !isEntityNameExpression(node.expression)) { - grammarErrorOnNode(node.expression, Diagnostics.The_expression_of_an_export_assignment_must_be_an_identifier_or_qualified_name_in_an_ambient_context); + grammarErrorOnNode( + node.expression, + Diagnostics + .The_expression_of_an_export_assignment_must_be_an_identifier_or_qualified_name_in_an_ambient_context, + ); } if (node.isExportEquals) { // Forbid export= in esm implementation files, and esm mode declaration files if ( - moduleKind >= ModuleKind.ES2015 && - ((node.flags & NodeFlags.Ambient && getSourceFileOfNode(node).impliedNodeFormat === ModuleKind.ESNext) || - (!(node.flags & NodeFlags.Ambient) && getSourceFileOfNode(node).impliedNodeFormat !== ModuleKind.CommonJS)) + moduleKind >= ModuleKind.ES2015 + && ((node.flags & NodeFlags.Ambient + && getSourceFileOfNode(node).impliedNodeFormat === ModuleKind.ESNext) + || (!(node.flags & NodeFlags.Ambient) + && getSourceFileOfNode(node).impliedNodeFormat !== ModuleKind.CommonJS)) ) { // export assignment is not supported in es6 modules - grammarErrorOnNode(node, Diagnostics.Export_assignment_cannot_be_used_when_targeting_ECMAScript_modules_Consider_using_export_default_or_another_module_format_instead); + grammarErrorOnNode( + node, + Diagnostics + .Export_assignment_cannot_be_used_when_targeting_ECMAScript_modules_Consider_using_export_default_or_another_module_format_instead, + ); } else if (moduleKind === ModuleKind.System && !(node.flags & NodeFlags.Ambient)) { // system modules does not support export assignment @@ -45340,9 +57761,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (!links.exportsChecked) { const exportEqualsSymbol = moduleSymbol.exports!.get("export=" as __String); if (exportEqualsSymbol && hasExportedMembers(moduleSymbol)) { - const declaration = getDeclarationOfAliasSymbol(exportEqualsSymbol) || exportEqualsSymbol.valueDeclaration; + const declaration = getDeclarationOfAliasSymbol(exportEqualsSymbol) + || exportEqualsSymbol.valueDeclaration; if (declaration && !isTopLevelInExternalModuleAugmentation(declaration) && !isInJSFile(declaration)) { - error(declaration, Diagnostics.An_export_assignment_cannot_be_used_in_a_module_with_other_exported_elements); + error( + declaration, + Diagnostics.An_export_assignment_cannot_be_used_in_a_module_with_other_exported_elements, + ); } } // Checks for export * conflicts @@ -45357,7 +57782,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (flags & (SymbolFlags.Namespace | SymbolFlags.Enum)) { return; } - const exportedDeclarationsCount = countWhere(declarations, and(isNotOverloadAndNotAccessor, not(isInterfaceDeclaration))); + const exportedDeclarationsCount = countWhere( + declarations, + and(isNotOverloadAndNotAccessor, not(isInterfaceDeclaration)), + ); if (flags & SymbolFlags.TypeAlias && exportedDeclarationsCount <= 2) { // it is legal to merge type alias with other values // so count should be either 1 (just type alias) or 2 (type alias + merged value) @@ -45367,7 +57795,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (!isDuplicatedCommonJSExport(declarations)) { for (const declaration of declarations!) { if (isNotOverload(declaration)) { - diagnostics.add(createDiagnosticForNode(declaration, Diagnostics.Cannot_redeclare_exported_variable_0, unescapeLeadingUnderscores(id))); + diagnostics.add( + createDiagnosticForNode( + declaration, + Diagnostics.Cannot_redeclare_exported_variable_0, + unescapeLeadingUnderscores(id), + ), + ); } } } @@ -45381,7 +57815,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function isDuplicatedCommonJSExport(declarations: Declaration[] | undefined) { return declarations && declarations.length > 1 - && declarations.every(d => isInJSFile(d) && isAccessExpression(d) && (isExportsIdentifier(d.expression) || isModuleExportsAccessExpression(d.expression))); + && declarations.every(d => + isInJSFile(d) && isAccessExpression(d) + && (isExportsIdentifier(d.expression) || isModuleExportsAccessExpression(d.expression)) + ); } function checkSourceElement(node: Node | undefined): void { @@ -45419,8 +57856,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { cancellationToken.throwIfCancellationRequested(); } } - if (kind >= SyntaxKind.FirstStatement && kind <= SyntaxKind.LastStatement && canHaveFlowNode(node) && node.flowNode && !isReachableFlowNode(node.flowNode)) { - errorOrSuggestion(compilerOptions.allowUnreachableCode === false, node, Diagnostics.Unreachable_code_detected); + if ( + kind >= SyntaxKind.FirstStatement && kind <= SyntaxKind.LastStatement && canHaveFlowNode(node) + && node.flowNode && !isReachableFlowNode(node.flowNode) + ) { + errorOrSuggestion( + compilerOptions.allowUnreachableCode === false, + node, + Diagnostics.Unreachable_code_detected, + ); } switch (kind) { @@ -45607,7 +58051,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function checkJSDocTypeIsInJsFile(node: Node): void { if (!isInJSFile(node)) { if (isJSDocNonNullableType(node) || isJSDocNullableType(node)) { - const token = tokenToString(isJSDocNonNullableType(node) ? SyntaxKind.ExclamationToken : SyntaxKind.QuestionToken); + const token = tokenToString( + isJSDocNonNullableType(node) ? SyntaxKind.ExclamationToken : SyntaxKind.QuestionToken, + ); const diagnostic = node.postfix ? Diagnostics._0_at_the_end_of_a_type_is_not_valid_TypeScript_syntax_Did_you_mean_to_write_1 : Diagnostics._0_at_the_start_of_a_type_is_not_valid_TypeScript_syntax_Did_you_mean_to_write_1; @@ -45685,8 +58131,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { : lastOrUndefined(host!.parameters); const symbol = getParameterSymbolFromJSDoc(paramTag); if ( - !lastParamDeclaration || - symbol && lastParamDeclaration.symbol === symbol && isRestParameter(lastParamDeclaration) + !lastParamDeclaration + || symbol && lastParamDeclaration.symbol === symbol && isRestParameter(lastParamDeclaration) ) { return createArrayType(type); } @@ -45728,7 +58174,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function checkDeferredNode(node: Node) { - tracing?.push(tracing.Phase.Check, "checkDeferredNode", { kind: node.kind, pos: node.pos, end: node.end, path: (node as TracingNode).tracingPath }); + tracing?.push(tracing.Phase.Check, "checkDeferredNode", { + kind: node.kind, + pos: node.pos, + end: node.end, + path: (node as TracingNode).tracingPath, + }); const saveCurrentNode = currentNode; currentNode = node; instantiationCount = 0; @@ -45831,7 +58282,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // This relies on the results of other lazy diagnostics, so must be computed after them if (!node.isDeclarationFile && (compilerOptions.noUnusedLocals || compilerOptions.noUnusedParameters)) { checkUnusedIdentifiers(getPotentiallyUnusedIdentifiers(node), (containingNode, kind, diag) => { - if (!containsParseError(containingNode) && unusedIsError(kind, !!(containingNode.flags & NodeFlags.Ambient))) { + if ( + !containsParseError(containingNode) + && unusedIsError(kind, !!(containingNode.flags & NodeFlags.Ambient)) + ) { diagnostics.add(diag); } }); @@ -45842,9 +58296,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { }); if ( - compilerOptions.importsNotUsedAsValues === ImportsNotUsedAsValues.Error && - !node.isDeclarationFile && - isExternalModule(node) + compilerOptions.importsNotUsedAsValues === ImportsNotUsedAsValues.Error + && !node.isDeclarationFile + && isExternalModule(node) ) { checkImportsForTypeOnlyConversion(node); } @@ -45926,7 +58380,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const currentGlobalDiagnostics = diagnostics.getGlobalDiagnostics(); if (currentGlobalDiagnostics !== previousGlobalDiagnostics) { // If the arrays are not the same reference, new diagnostics were added. - const deferredGlobalDiagnostics = relativeComplement(previousGlobalDiagnostics, currentGlobalDiagnostics, compareDiagnostics); + const deferredGlobalDiagnostics = relativeComplement( + previousGlobalDiagnostics, + currentGlobalDiagnostics, + compareDiagnostics, + ); return concatenate(deferredGlobalDiagnostics, semanticDiagnostics); } else if (previousGlobalDiagnosticsSize === 0 && currentGlobalDiagnostics.length > 0) { @@ -45977,10 +58435,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (!isExternalModule(location as SourceFile)) break; // falls through case SyntaxKind.ModuleDeclaration: - copyLocallyVisibleExportSymbols(getSymbolOfDeclaration(location as ModuleDeclaration | SourceFile).exports!, meaning & SymbolFlags.ModuleMember); + copyLocallyVisibleExportSymbols( + getSymbolOfDeclaration(location as ModuleDeclaration | SourceFile).exports!, + meaning & SymbolFlags.ModuleMember, + ); break; case SyntaxKind.EnumDeclaration: - copySymbols(getSymbolOfDeclaration(location as EnumDeclaration).exports!, meaning & SymbolFlags.EnumMember); + copySymbols( + getSymbolOfDeclaration(location as EnumDeclaration).exports!, + meaning & SymbolFlags.EnumMember, + ); break; case SyntaxKind.ClassExpression: const className = (location as ClassExpression).name; @@ -45998,7 +58462,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // (type parameters of classDeclaration/classExpression and interface are in member property of the symbol. // Note: that the memberFlags come from previous iteration. if (!isStaticSymbol) { - copySymbols(getMembersOfSymbol(getSymbolOfDeclaration(location as ClassDeclaration | InterfaceDeclaration)), meaning & SymbolFlags.Type); + copySymbols( + getMembersOfSymbol( + getSymbolOfDeclaration(location as ClassDeclaration | InterfaceDeclaration), + ), + meaning & SymbolFlags.Type, + ); } break; case SyntaxKind.FunctionExpression: @@ -46051,7 +58520,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (meaning) { source.forEach(symbol => { // Similar condition as in `resolveNameHelper` - if (!getDeclarationOfKind(symbol, SyntaxKind.ExportSpecifier) && !getDeclarationOfKind(symbol, SyntaxKind.NamespaceExport) && symbol.escapedName !== InternalSymbolName.Default) { + if ( + !getDeclarationOfKind(symbol, SyntaxKind.ExportSpecifier) + && !getDeclarationOfKind(symbol, SyntaxKind.NamespaceExport) + && symbol.escapedName !== InternalSymbolName.Default + ) { copySymbol(symbol, meaning); } }); @@ -46060,9 +58533,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function isTypeDeclarationName(name: Node): boolean { - return name.kind === SyntaxKind.Identifier && - isTypeDeclaration(name.parent) && - getNameOfDeclaration(name.parent) === name; + return name.kind === SyntaxKind.Identifier + && isTypeDeclaration(name.parent) + && getNameOfDeclaration(name.parent) === name; } // True if the given identifier is part of a type reference @@ -46082,7 +58555,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return node.parent.kind === SyntaxKind.ExpressionWithTypeArguments; } - function forEachEnclosingClass(node: Node, callback: (node: ClassLikeDeclaration) => T | undefined): T | undefined { + function forEachEnclosingClass( + node: Node, + callback: (node: ClassLikeDeclaration) => T | undefined, + ): T | undefined { let result: T | undefined; let containingClass = getContainingClass(node); while (containingClass) { @@ -46110,17 +58586,21 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return !!forEachEnclosingClass(node, n => n === classDeclaration); } - function getLeftSideOfImportEqualsOrExportAssignment(nodeOnRightSide: EntityName): ImportEqualsDeclaration | ExportAssignment | undefined { + function getLeftSideOfImportEqualsOrExportAssignment( + nodeOnRightSide: EntityName, + ): ImportEqualsDeclaration | ExportAssignment | undefined { while (nodeOnRightSide.parent.kind === SyntaxKind.QualifiedName) { nodeOnRightSide = nodeOnRightSide.parent as QualifiedName; } if (nodeOnRightSide.parent.kind === SyntaxKind.ImportEqualsDeclaration) { - return (nodeOnRightSide.parent as ImportEqualsDeclaration).moduleReference === nodeOnRightSide ? nodeOnRightSide.parent as ImportEqualsDeclaration : undefined; + return (nodeOnRightSide.parent as ImportEqualsDeclaration).moduleReference === nodeOnRightSide + ? nodeOnRightSide.parent as ImportEqualsDeclaration : undefined; } if (nodeOnRightSide.parent.kind === SyntaxKind.ExportAssignment) { - return (nodeOnRightSide.parent as ExportAssignment).expression === nodeOnRightSide as Node ? nodeOnRightSide.parent as ExportAssignment : undefined; + return (nodeOnRightSide.parent as ExportAssignment).expression === nodeOnRightSide as Node + ? nodeOnRightSide.parent as ExportAssignment : undefined; } return undefined; @@ -46131,7 +58611,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function getSpecialPropertyAssignmentSymbolFromEntityName(entityName: EntityName | PropertyAccessExpression) { - const specialPropertyAssignmentKind = getAssignmentDeclarationKind(entityName.parent.parent as BinaryExpression); + const specialPropertyAssignmentKind = getAssignmentDeclarationKind( + entityName.parent.parent as BinaryExpression, + ); switch (specialPropertyAssignmentKind) { case AssignmentDeclarationKind.ExportsProperty: case AssignmentDeclarationKind.PrototypeProperty: @@ -46157,11 +58639,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function isThisPropertyAndThisTyped(node: PropertyAccessExpression) { if (node.expression.kind === SyntaxKind.ThisKeyword) { - const container = getThisContainer(node, /*includeArrowFunctions*/ false, /*includeClassComputedPropertyName*/ false); + const container = getThisContainer( + node, + /*includeArrowFunctions*/ false, + /*includeClassComputedPropertyName*/ false, + ); if (isFunctionLike(container)) { const containingLiteral = getContainingObjectLiteral(container); if (containingLiteral) { - const contextualType = getApparentTypeOfContextualType(containingLiteral, /*contextFlags*/ undefined); + const contextualType = getApparentTypeOfContextualType( + containingLiteral, + /*contextFlags*/ undefined, + ); const type = getThisTypeOfObjectLiteralFromContextualType(containingLiteral, contextualType); return type && !isTypeAny(type); } @@ -46169,18 +58658,23 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } - function getSymbolOfNameOrPropertyAccessExpression(name: EntityName | PrivateIdentifier | PropertyAccessExpression | JSDocMemberName): Symbol | undefined { + function getSymbolOfNameOrPropertyAccessExpression( + name: EntityName | PrivateIdentifier | PropertyAccessExpression | JSDocMemberName, + ): Symbol | undefined { if (isDeclarationName(name)) { return getSymbolOfNode(name.parent); } if ( - isInJSFile(name) && - name.parent.kind === SyntaxKind.PropertyAccessExpression && - name.parent === (name.parent.parent as BinaryExpression).left + isInJSFile(name) + && name.parent.kind === SyntaxKind.PropertyAccessExpression + && name.parent === (name.parent.parent as BinaryExpression).left ) { // Check if this is a special property assignment - if (!isPrivateIdentifier(name) && !isJSDocMemberName(name) && !isThisPropertyAndThisTyped(name.parent as PropertyAccessExpression)) { + if ( + !isPrivateIdentifier(name) && !isJSDocMemberName(name) + && !isThisPropertyAndThisTyped(name.parent as PropertyAccessExpression) + ) { const specialPropertyAssignmentSymbol = getSpecialPropertyAssignmentSymbolFromEntityName(name); if (specialPropertyAssignmentSymbol) { return specialPropertyAssignmentSymbol; @@ -46190,7 +58684,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (name.parent.kind === SyntaxKind.ExportAssignment && isEntityNameExpression(name)) { // Even an entity name expression that doesn't resolve as an entityname may still typecheck as a property access expression - const success = resolveEntityName(name, /*all meanings*/ SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace | SymbolFlags.Alias, /*ignoreErrors*/ true); + const success = resolveEntityName( + name, + /*all meanings*/ SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace | SymbolFlags.Alias, + /*ignoreErrors*/ true, + ); if (success && success !== unknownSymbol) { return success; } @@ -46232,7 +58730,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } meaning |= SymbolFlags.Alias; - const entityNameSymbol = isEntityNameExpression(name) ? resolveEntityName(name, meaning, /*ignoreErrors*/ true) : undefined; + const entityNameSymbol = isEntityNameExpression(name) + ? resolveEntityName(name, meaning, /*ignoreErrors*/ true) : undefined; if (entityNameSymbol) { return entityNameSymbol; } @@ -46244,7 +58743,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (name.parent.kind === SyntaxKind.TypeParameter && name.parent.parent.kind === SyntaxKind.JSDocTemplateTag) { Debug.assert(!isInJSFile(name)); // Otherwise `isDeclarationName` would have been true. - const typeParameter = getTypeParameterFromJsDoc(name.parent as TypeParameterDeclaration & { parent: JSDocTemplateTag; }); + const typeParameter = getTypeParameterFromJsDoc( + name.parent as TypeParameterDeclaration & { parent: JSDocTemplateTag; }, + ); return typeParameter && typeParameter.symbol; } @@ -46261,7 +58762,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const symbol = getIntrinsicTagSymbol(name.parent as JsxOpeningLikeElement); return symbol === unknownSymbol ? undefined : symbol; } - const result = resolveEntityName(name, meaning, /*ignoreErrors*/ true, /*dontResolveAlias*/ true, getHostSignatureFromJSDoc(name)); + const result = resolveEntityName( + name, + meaning, + /*ignoreErrors*/ true, + /*dontResolveAlias*/ true, + getHostSignatureFromJSDoc(name), + ); if (!result && isJSDoc) { const container = findAncestor(name, or(isClassLike, isInterfaceDeclaration)); if (container) { @@ -46271,7 +58778,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (result && isJSDoc) { const container = getJSDocHost(name); if (container && isEnumMember(container) && container === result.valueDeclaration) { - return resolveEntityName(name, meaning, /*ignoreErrors*/ true, /*dontResolveAlias*/ true, getSourceFileOfNode(container)) || result; + return resolveEntityName( + name, + meaning, + /*ignoreErrors*/ true, + /*dontResolveAlias*/ true, + getSourceFileOfNode(container), + ) || result; } } return result; @@ -46288,7 +58801,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (name.kind === SyntaxKind.PropertyAccessExpression) { checkPropertyAccessExpression(name, CheckMode.Normal); if (!links.resolvedSymbol) { - links.resolvedSymbol = getApplicableIndexSymbol(checkExpressionCached(name.expression), getLiteralTypeFromPropertyName(name.name)); + links.resolvedSymbol = getApplicableIndexSymbol( + checkExpressionCached(name.expression), + getLiteralTypeFromPropertyName(name.name), + ); } } else { @@ -46305,7 +58821,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } else if (isTypeReferenceIdentifier(name as EntityName)) { const meaning = name.parent.kind === SyntaxKind.TypeReference ? SymbolFlags.Type : SymbolFlags.Namespace; - const symbol = resolveEntityName(name as EntityName, meaning, /*ignoreErrors*/ false, /*dontResolveAlias*/ true); + const symbol = resolveEntityName( + name as EntityName, + meaning, + /*ignoreErrors*/ false, + /*dontResolveAlias*/ true, + ); return symbol && symbol !== unknownSymbol ? symbol : getUnresolvedSymbolForEntityName(name as EntityName); } if (name.parent.kind === SyntaxKind.TypePredicate) { @@ -46335,7 +58856,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { else { const copy = createSymbol(SymbolFlags.Signature, InternalSymbolName.Index); copy.declarations = mapDefined(infos, i => i.declaration); - copy.parent = type.aliasSymbol ? type.aliasSymbol : type.symbol ? type.symbol : getSymbolAtLocation(copy.declarations[0].parent); + copy.parent = type.aliasSymbol ? type.aliasSymbol + : type.symbol ? type.symbol : getSymbolAtLocation(copy.declarations[0].parent); symbolLinks.filteredIndexSymbolCache.set(nodeListId, copy); return copy; } @@ -46351,11 +58873,21 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { * * For unqualified names, a container K may be provided as a second argument. */ - function resolveJSDocMemberName(name: EntityName | JSDocMemberName, ignoreErrors?: boolean, container?: Symbol): Symbol | undefined { + function resolveJSDocMemberName( + name: EntityName | JSDocMemberName, + ignoreErrors?: boolean, + container?: Symbol, + ): Symbol | undefined { if (isEntityName(name)) { // resolve static values first const meaning = SymbolFlags.Type | SymbolFlags.Namespace | SymbolFlags.Value; - let symbol = resolveEntityName(name, meaning, ignoreErrors, /*dontResolveAlias*/ true, getHostSignatureFromJSDoc(name)); + let symbol = resolveEntityName( + name, + meaning, + ignoreErrors, + /*dontResolveAlias*/ true, + getHostSignatureFromJSDoc(name), + ); if (!symbol && isIdentifier(name) && container) { symbol = getMergedSymbol(getSymbol(getExportsOfSymbol(container), name.escapedText, meaning)); } @@ -46366,7 +58898,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const left = isIdentifier(name) ? container : resolveJSDocMemberName(name.left, ignoreErrors, container); const right = isIdentifier(name) ? name.escapedText : name.right.escapedText; if (left) { - const proto = left.flags & SymbolFlags.Value && getPropertyOfType(getTypeOfSymbol(left), "prototype" as __String); + const proto = left.flags & SymbolFlags.Value + && getPropertyOfType(getTypeOfSymbol(left), "prototype" as __String); const t = proto ? getTypeOfSymbol(proto) : getDeclaredTypeOfSymbol(left); return getPropertyOfType(t, right); } @@ -46400,9 +58933,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return getSymbolOfNameOrPropertyAccessExpression(node as Identifier); } else if ( - parent.kind === SyntaxKind.BindingElement && - grandParent.kind === SyntaxKind.ObjectBindingPattern && - node === (parent as BindingElement).propertyName + parent.kind === SyntaxKind.BindingElement + && grandParent.kind === SyntaxKind.ObjectBindingPattern + && node === (parent as BindingElement).propertyName ) { const typeOfPattern = getTypeOfNode(grandParent); const propertyDeclaration = getPropertyOfType(typeOfPattern, (node as Identifier).escapedText); @@ -46434,12 +58967,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { case SyntaxKind.PropertyAccessExpression: case SyntaxKind.QualifiedName: if (!isThisInTypeQuery(node)) { - return getSymbolOfNameOrPropertyAccessExpression(node as EntityName | PrivateIdentifier | PropertyAccessExpression); + return getSymbolOfNameOrPropertyAccessExpression( + node as EntityName | PrivateIdentifier | PropertyAccessExpression, + ); } // falls through case SyntaxKind.ThisKeyword: - const container = getThisContainer(node, /*includeArrowFunctions*/ false, /*includeClassComputedPropertyName*/ false); + const container = getThisContainer( + node, + /*includeArrowFunctions*/ false, + /*includeClassComputedPropertyName*/ false, + ); if (isFunctionLike(container)) { const sig = getSignatureFromDeclaration(container); if (sig.thisParameter) { @@ -46472,14 +59011,24 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // 3). Dynamic import call or require in javascript // 4). type A = import("./f/*gotToDefinitionHere*/oo") if ( - (isExternalModuleImportEqualsDeclaration(node.parent.parent) && getExternalModuleImportEqualsDeclarationExpression(node.parent.parent) === node) || - ((node.parent.kind === SyntaxKind.ImportDeclaration || node.parent.kind === SyntaxKind.ExportDeclaration) && (node.parent as ImportDeclaration).moduleSpecifier === node) || - ((isInJSFile(node) && getEmitModuleResolutionKind(compilerOptions) !== ModuleResolutionKind.Bundler && isRequireCall(node.parent, /*requireStringLiteralLikeArgument*/ false)) || isImportCall(node.parent)) || - (isLiteralTypeNode(node.parent) && isLiteralImportTypeNode(node.parent.parent) && node.parent.parent.argument === node.parent) + (isExternalModuleImportEqualsDeclaration(node.parent.parent) + && getExternalModuleImportEqualsDeclarationExpression(node.parent.parent) === node) + || ((node.parent.kind === SyntaxKind.ImportDeclaration + || node.parent.kind === SyntaxKind.ExportDeclaration) + && (node.parent as ImportDeclaration).moduleSpecifier === node) + || ((isInJSFile(node) + && getEmitModuleResolutionKind(compilerOptions) !== ModuleResolutionKind.Bundler + && isRequireCall(node.parent, /*requireStringLiteralLikeArgument*/ false)) + || isImportCall(node.parent)) + || (isLiteralTypeNode(node.parent) && isLiteralImportTypeNode(node.parent.parent) + && node.parent.parent.argument === node.parent) ) { return resolveExternalModuleName(node, node as LiteralExpression, ignoreErrors); } - if (isCallExpression(parent) && isBindableObjectDefinePropertyCall(parent) && parent.arguments[1] === node) { + if ( + isCallExpression(parent) && isBindableObjectDefinePropertyCall(parent) + && parent.arguments[1] === node + ) { return getSymbolOfDeclaration(parent); } // falls through @@ -46491,7 +59040,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { : isLiteralTypeNode(parent) && isIndexedAccessTypeNode(grandParent) ? getTypeFromTypeNode(grandParent.objectType) : undefined; - return objectType && getPropertyOfType(objectType, escapeLeadingUnderscores((node as StringLiteral | NumericLiteral).text)); + return objectType + && getPropertyOfType( + objectType, + escapeLeadingUnderscores((node as StringLiteral | NumericLiteral).text), + ); case SyntaxKind.DefaultKeyword: case SyntaxKind.FunctionKeyword: @@ -46499,7 +59052,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { case SyntaxKind.ClassKeyword: return getSymbolOfNode(node.parent); case SyntaxKind.ImportType: - return isLiteralImportTypeNode(node) ? getSymbolAtLocation(node.argument.literal, ignoreErrors) : undefined; + return isLiteralImportTypeNode(node) ? getSymbolAtLocation(node.argument.literal, ignoreErrors) + : undefined; case SyntaxKind.ExportKeyword: return isExportAssignment(node.parent) ? Debug.checkDefined(node.parent.symbol) : undefined; @@ -46526,14 +59080,20 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const keyType = getLiteralTypeFromPropertyName(node); const objectType = getTypeOfExpression(node.parent.expression); const objectTypes = objectType.flags & TypeFlags.Union ? (objectType as UnionType).types : [objectType]; - return flatMap(objectTypes, t => filter(getIndexInfosOfType(t), info => isApplicableIndexType(keyType, info.keyType))); + return flatMap( + objectTypes, + t => filter(getIndexInfosOfType(t), info => isApplicableIndexType(keyType, info.keyType)), + ); } return undefined; } function getShorthandAssignmentValueSymbol(location: Node | undefined): Symbol | undefined { if (location && location.kind === SyntaxKind.ShorthandPropertyAssignment) { - return resolveEntityName((location as ShorthandPropertyAssignment).name, SymbolFlags.Value | SymbolFlags.Alias); + return resolveEntityName( + (location as ShorthandPropertyAssignment).name, + SymbolFlags.Value | SymbolFlags.Alias, + ); } return undefined; } @@ -46541,12 +59101,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { /** Returns the target of an export specifier without following aliases */ function getExportSpecifierLocalTargetSymbol(node: ExportSpecifier | Identifier): Symbol | undefined { if (isExportSpecifier(node)) { - return node.parent.parent.moduleSpecifier ? - getExternalModuleMember(node.parent.parent, node) : - resolveEntityName(node.propertyName || node.name, SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace | SymbolFlags.Alias); + return node.parent.parent.moduleSpecifier + ? getExternalModuleMember(node.parent.parent, node) + : resolveEntityName( + node.propertyName || node.name, + SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace | SymbolFlags.Alias, + ); } else { - return resolveEntityName(node, SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace | SymbolFlags.Alias); + return resolveEntityName( + node, + SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace | SymbolFlags.Alias, + ); } } @@ -46608,7 +59174,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } if (isBindingPattern(node)) { - return getTypeForVariableLikeDeclaration(node.parent, /*includeOptionality*/ true, CheckMode.Normal) || errorType; + return getTypeForVariableLikeDeclaration(node.parent, /*includeOptionality*/ true, CheckMode.Normal) + || errorType; } if (isInRightSideOfImportOrExportAssignment(node as Identifier)) { @@ -46633,7 +59200,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // [ a ] from // [a] = [ some array ...] function getTypeOfAssignmentPattern(expr: AssignmentPattern): Type | undefined { - Debug.assert(expr.kind === SyntaxKind.ObjectLiteralExpression || expr.kind === SyntaxKind.ArrayLiteralExpression); + Debug.assert( + expr.kind === SyntaxKind.ObjectLiteralExpression || expr.kind === SyntaxKind.ArrayLiteralExpression, + ); // If this is from "for of" // for ( { a } of elems) { // } @@ -46659,8 +59228,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const node = cast(expr.parent, isArrayLiteralExpression); // [{ property1: p1, property2 }] = elems; const typeOfArrayLiteral = getTypeOfAssignmentPattern(node) || errorType; - const elementType = checkIteratedTypeOrElementType(IterationUse.Destructuring, typeOfArrayLiteral, undefinedType, expr.parent) || errorType; - return checkArrayLiteralDestructuringElementAssignment(node, typeOfArrayLiteral, node.elements.indexOf(expr), elementType); + const elementType = + checkIteratedTypeOrElementType(IterationUse.Destructuring, typeOfArrayLiteral, undefinedType, expr.parent) + || errorType; + return checkArrayLiteralDestructuringElementAssignment( + node, + typeOfArrayLiteral, + node.elements.indexOf(expr), + elementType, + ); } // Gets the property symbol corresponding to the property in destructuring assignment @@ -46714,9 +59290,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function getAugmentedPropertiesOfType(type: Type): Symbol[] { type = getApparentType(type); const propsByName = createSymbolTable(getPropertiesOfType(type)); - const functionType = getSignaturesOfType(type, SignatureKind.Call).length ? globalCallableFunctionType : - getSignaturesOfType(type, SignatureKind.Construct).length ? globalNewableFunctionType : - undefined; + const functionType = getSignaturesOfType(type, SignatureKind.Call).length ? globalCallableFunctionType + : getSignaturesOfType(type, SignatureKind.Construct).length ? globalNewableFunctionType + : undefined; if (functionType) { forEach(getPropertiesOfType(functionType), p => { if (!propsByName.has(p.escapedName)) { @@ -46728,7 +59304,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function typeHasCallOrConstructSignatures(type: Type): boolean { - return getSignaturesOfType(type, SignatureKind.Call).length !== 0 || getSignaturesOfType(type, SignatureKind.Construct).length !== 0; + return getSignaturesOfType(type, SignatureKind.Call).length !== 0 + || getSignaturesOfType(type, SignatureKind.Construct).length !== 0; } function getRootSymbols(symbol: Symbol): readonly Symbol[] { @@ -46737,7 +59314,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function getImmediateRootSymbols(symbol: Symbol): readonly Symbol[] | undefined { if (getCheckFlags(symbol) & CheckFlags.Synthetic) { - return mapDefined(getSymbolLinks(symbol).containingType!.types, type => getPropertyOfType(type, symbol.escapedName)); + return mapDefined( + getSymbolLinks(symbol).containingType!.types, + type => getPropertyOfType(type, symbol.escapedName), + ); } else if (symbol.flags & SymbolFlags.Transient) { const { links: { leftSpread, rightSpread, syntheticOrigin } } = symbol as TransientSymbol; @@ -46806,35 +59386,51 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // When resolved as an expression identifier, if the given node references an exported entity, return the declaration // node of the exported entity's container. Otherwise, return undefined. - function getReferencedExportContainer(nodeIn: Identifier, prefixLocals?: boolean): SourceFile | ModuleDeclaration | EnumDeclaration | undefined { + function getReferencedExportContainer( + nodeIn: Identifier, + prefixLocals?: boolean, + ): SourceFile | ModuleDeclaration | EnumDeclaration | undefined { const node = getParseTreeNode(nodeIn, isIdentifier); if (node) { // When resolving the export container for the name of a module or enum // declaration, we need to start resolution at the declaration's container. // Otherwise, we could incorrectly resolve the export container as the // declaration if it contains an exported member with the same name. - let symbol = getReferencedValueSymbol(node, /*startInDeclarationContainer*/ isNameOfModuleOrEnumDeclaration(node)); + let symbol = getReferencedValueSymbol( + node, + /*startInDeclarationContainer*/ isNameOfModuleOrEnumDeclaration(node), + ); if (symbol) { if (symbol.flags & SymbolFlags.ExportValue) { // If we reference an exported entity within the same module declaration, then whether // we prefix depends on the kind of entity. SymbolFlags.ExportHasLocal encompasses all the // kinds that we do NOT prefix. const exportSymbol = getMergedSymbol(symbol.exportSymbol!); - if (!prefixLocals && exportSymbol.flags & SymbolFlags.ExportHasLocal && !(exportSymbol.flags & SymbolFlags.Variable)) { + if ( + !prefixLocals && exportSymbol.flags & SymbolFlags.ExportHasLocal + && !(exportSymbol.flags & SymbolFlags.Variable) + ) { return undefined; } symbol = exportSymbol; } const parentSymbol = getParentOfSymbol(symbol); if (parentSymbol) { - if (parentSymbol.flags & SymbolFlags.ValueModule && parentSymbol.valueDeclaration?.kind === SyntaxKind.SourceFile) { + if ( + parentSymbol.flags & SymbolFlags.ValueModule + && parentSymbol.valueDeclaration?.kind === SyntaxKind.SourceFile + ) { const symbolFile = parentSymbol.valueDeclaration as SourceFile; const referenceFile = getSourceFileOfNode(node); // If `node` accesses an export and that export isn't in the same file, then symbol is a namespace export, so return undefined. const symbolIsUmdExport = symbolFile !== referenceFile; return symbolIsUmdExport ? undefined : symbolFile; } - return findAncestor(node.parent, (n): n is ModuleDeclaration | EnumDeclaration => isModuleOrEnumDeclaration(n) && getSymbolOfDeclaration(n) === parentSymbol); + return findAncestor( + node.parent, + (n): n is ModuleDeclaration | EnumDeclaration => + isModuleOrEnumDeclaration(n) && getSymbolOfDeclaration(n) === parentSymbol, + ); } } } @@ -46853,7 +59449,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // We should only get the declaration of an alias if there isn't a local value // declaration for the symbol - if (isNonLocalAlias(symbol, /*excludes*/ SymbolFlags.Value) && !getTypeOnlyAliasDeclaration(symbol, SymbolFlags.Value)) { + if ( + isNonLocalAlias(symbol, /*excludes*/ SymbolFlags.Value) + && !getTypeOnlyAliasDeclaration(symbol, SymbolFlags.Value) + ) { return getDeclarationOfAliasSymbol(symbol); } } @@ -46868,13 +59467,24 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function isSymbolOfDeclarationWithCollidingName(symbol: Symbol): boolean { - if (symbol.flags & SymbolFlags.BlockScoped && symbol.valueDeclaration && !isSourceFile(symbol.valueDeclaration)) { + if ( + symbol.flags & SymbolFlags.BlockScoped && symbol.valueDeclaration && !isSourceFile(symbol.valueDeclaration) + ) { const links = getSymbolLinks(symbol); if (links.isDeclarationWithCollidingName === undefined) { const container = getEnclosingBlockScopeContainer(symbol.valueDeclaration); if (isStatementWithLocals(container) || isSymbolOfDestructuredElementOfCatchBinding(symbol)) { const nodeLinks = getNodeLinks(symbol.valueDeclaration); - if (resolveName(container.parent, symbol.escapedName, SymbolFlags.Value, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ false)) { + if ( + resolveName( + container.parent, + symbol.escapedName, + SymbolFlags.Value, + /*nameNotFoundMessage*/ undefined, + /*nameArg*/ undefined, + /*isUse*/ false, + ) + ) { // redeclaration - always should be renamed links.isDeclarationWithCollidingName = true; } @@ -46896,9 +59506,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // they will not collide with anything const isDeclaredInLoop = nodeLinks.flags & NodeCheckFlags.BlockScopedBindingInLoop; const inLoopInitializer = isIterationStatement(container, /*lookInLabeledStatements*/ false); - const inLoopBodyBlock = container.kind === SyntaxKind.Block && isIterationStatement(container.parent, /*lookInLabeledStatements*/ false); + const inLoopBodyBlock = container.kind === SyntaxKind.Block + && isIterationStatement(container.parent, /*lookInLabeledStatements*/ false); - links.isDeclarationWithCollidingName = !isBlockScopedContainerTopLevel(container) && (!isDeclaredInLoop || (!inLoopInitializer && !inLoopBodyBlock)); + links.isDeclarationWithCollidingName = !isBlockScopedContainerTopLevel(container) + && (!isDeclaredInLoop || (!inLoopInitializer && !inLoopBodyBlock)); } else { links.isDeclarationWithCollidingName = false; @@ -46950,25 +59562,31 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { case SyntaxKind.NamespaceImport: case SyntaxKind.ImportSpecifier: case SyntaxKind.ExportSpecifier: - const symbol = getSymbolOfDeclaration(node as ImportClause | NamespaceImport | ImportSpecifier | ExportSpecifier); + const symbol = getSymbolOfDeclaration( + node as ImportClause | NamespaceImport | ImportSpecifier | ExportSpecifier, + ); return !!symbol && isAliasResolvedToValue(symbol, /*excludeTypeOnlyValues*/ true); case SyntaxKind.ExportDeclaration: const exportClause = (node as ExportDeclaration).exportClause; return !!exportClause && ( - isNamespaceExport(exportClause) || - some(exportClause.elements, isValueAliasDeclaration) + isNamespaceExport(exportClause) + || some(exportClause.elements, isValueAliasDeclaration) ); case SyntaxKind.ExportAssignment: - return (node as ExportAssignment).expression && (node as ExportAssignment).expression.kind === SyntaxKind.Identifier ? - isAliasResolvedToValue(getSymbolOfDeclaration(node as ExportAssignment)) : - true; + return (node as ExportAssignment).expression + && (node as ExportAssignment).expression.kind === SyntaxKind.Identifier + ? isAliasResolvedToValue(getSymbolOfDeclaration(node as ExportAssignment)) + : true; } return false; } function isTopLevelValueImportEqualsWithEntityName(nodeIn: ImportEqualsDeclaration): boolean { const node = getParseTreeNode(nodeIn, isImportEqualsDeclaration); - if (node === undefined || node.parent.kind !== SyntaxKind.SourceFile || !isInternalModuleImportEqualsDeclaration(node)) { + if ( + node === undefined || node.parent.kind !== SyntaxKind.SourceFile + || !isInternalModuleImportEqualsDeclaration(node) + ) { // parent is not source file or it is not reference to internal module return false; } @@ -46987,8 +59605,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } // const enums and modules that contain only const enums are not considered values from the emit perspective // unless 'preserveConstEnums' option is set to true - return !!(getSymbolFlags(symbol, excludeTypeOnlyValues, /*excludeLocalMeanings*/ true) & SymbolFlags.Value) && - (shouldPreserveConstEnums(compilerOptions) || !isConstEnumOrConstEnumOnlyModule(target)); + return !!(getSymbolFlags(symbol, excludeTypeOnlyValues, /*excludeLocalMeanings*/ true) & SymbolFlags.Value) + && (shouldPreserveConstEnums(compilerOptions) || !isConstEnumOrConstEnumOnlyModule(target)); } function isConstEnumOrConstEnumOnlyModule(s: Symbol): boolean { @@ -47005,9 +59623,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } const target = getSymbolLinks(symbol).aliasTarget; if ( - target && getEffectiveModifierFlags(node) & ModifierFlags.Export && - getSymbolFlags(target) & SymbolFlags.Value && - (shouldPreserveConstEnums(compilerOptions) || !isConstEnumOrConstEnumOnlyModule(target)) + target && getEffectiveModifierFlags(node) & ModifierFlags.Export + && getSymbolFlags(target) & SymbolFlags.Value + && (shouldPreserveConstEnums(compilerOptions) || !isConstEnumOrConstEnumOnlyModule(target)) ) { // An `export import ... =` of a value symbol is always considered referenced return true; @@ -47031,30 +59649,30 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // function foo(a: any) { // This is implementation of the overloads // return a; // } - return signaturesOfSymbol.length > 1 || + return signaturesOfSymbol.length > 1 // If there is single signature for the symbol, it is overload if that signature isn't coming from the node // e.g.: function foo(a: string): string; // function foo(a: any) { // This is implementation of the overloads // return a; // } - (signaturesOfSymbol.length === 1 && signaturesOfSymbol[0].declaration !== node); + || (signaturesOfSymbol.length === 1 && signaturesOfSymbol[0].declaration !== node); } return false; } function isRequiredInitializedParameter(parameter: ParameterDeclaration | JSDocParameterTag): boolean { - return !!strictNullChecks && - !isOptionalParameter(parameter) && - !isJSDocParameterTag(parameter) && - !!parameter.initializer && - !hasSyntacticModifier(parameter, ModifierFlags.ParameterPropertyModifier); + return !!strictNullChecks + && !isOptionalParameter(parameter) + && !isJSDocParameterTag(parameter) + && !!parameter.initializer + && !hasSyntacticModifier(parameter, ModifierFlags.ParameterPropertyModifier); } function isOptionalUninitializedParameterProperty(parameter: ParameterDeclaration) { - return strictNullChecks && - isOptionalParameter(parameter) && - !parameter.initializer && - hasSyntacticModifier(parameter, ModifierFlags.ParameterPropertyModifier); + return strictNullChecks + && isOptionalParameter(parameter) + && !parameter.initializer + && hasSyntacticModifier(parameter, ModifierFlags.ParameterPropertyModifier); } function isExpandoFunctionDeclaration(node: Declaration): boolean { @@ -47066,7 +59684,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (!symbol || !(symbol.flags & SymbolFlags.Function)) { return false; } - return !!forEachEntry(getExportsOfSymbol(symbol), p => p.flags & SymbolFlags.Value && p.valueDeclaration && isPropertyAccessExpression(p.valueDeclaration)); + return !!forEachEntry( + getExportsOfSymbol(symbol), + p => p.flags & SymbolFlags.Value && p.valueDeclaration && isPropertyAccessExpression(p.valueDeclaration), + ); } function getPropertiesOfContainerFunction(node: Declaration): Symbol[] { @@ -47120,7 +59741,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return !!(type.flags & TypeFlags.Object) && getSignaturesOfType(type, SignatureKind.Call).length > 0; } - function getTypeReferenceSerializationKind(typeNameIn: EntityName, location?: Node): TypeReferenceSerializationKind { + function getTypeReferenceSerializationKind( + typeNameIn: EntityName, + location?: Node, + ): TypeReferenceSerializationKind { // ensure both `typeName` and `location` are parse tree nodes. const typeName = getParseTreeNode(typeNameIn, isEntityName); if (!typeName) return TypeReferenceSerializationKind.Unknown; @@ -47133,15 +59757,34 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // Resolve the symbol as a value to ensure the type can be reached at runtime during emit. let isTypeOnly = false; if (isQualifiedName(typeName)) { - const rootValueSymbol = resolveEntityName(getFirstIdentifier(typeName), SymbolFlags.Value, /*ignoreErrors*/ true, /*dontResolveAlias*/ true, location); + const rootValueSymbol = resolveEntityName( + getFirstIdentifier(typeName), + SymbolFlags.Value, + /*ignoreErrors*/ true, + /*dontResolveAlias*/ true, + location, + ); isTypeOnly = !!rootValueSymbol?.declarations?.every(isTypeOnlyImportOrExportDeclaration); } - const valueSymbol = resolveEntityName(typeName, SymbolFlags.Value, /*ignoreErrors*/ true, /*dontResolveAlias*/ true, location); - const resolvedSymbol = valueSymbol && valueSymbol.flags & SymbolFlags.Alias ? resolveAlias(valueSymbol) : valueSymbol; + const valueSymbol = resolveEntityName( + typeName, + SymbolFlags.Value, + /*ignoreErrors*/ true, + /*dontResolveAlias*/ true, + location, + ); + const resolvedSymbol = valueSymbol && valueSymbol.flags & SymbolFlags.Alias ? resolveAlias(valueSymbol) + : valueSymbol; isTypeOnly ||= !!(valueSymbol && getTypeOnlyAliasDeclaration(valueSymbol, SymbolFlags.Value)); // Resolve the symbol as a type so that we can provide a more useful hint for the type serializer. - const typeSymbol = resolveEntityName(typeName, SymbolFlags.Type, /*ignoreErrors*/ true, /*dontResolveAlias*/ false, location); + const typeSymbol = resolveEntityName( + typeName, + SymbolFlags.Type, + /*ignoreErrors*/ true, + /*dontResolveAlias*/ false, + location, + ); if (resolvedSymbol && resolvedSymbol === typeSymbol) { const globalPromiseSymbol = getGlobalPromiseConstructorSymbol(/*reportErrors*/ false); if (globalPromiseSymbol && resolvedSymbol === globalPromiseSymbol) { @@ -47150,7 +59793,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const constructorType = getTypeOfSymbol(resolvedSymbol); if (constructorType && isConstructorType(constructorType)) { - return isTypeOnly ? TypeReferenceSerializationKind.TypeWithCallSignature : TypeReferenceSerializationKind.TypeWithConstructSignatureAndValue; + return isTypeOnly ? TypeReferenceSerializationKind.TypeWithCallSignature + : TypeReferenceSerializationKind.TypeWithConstructSignatureAndValue; } } @@ -47197,7 +59841,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } - function createTypeOfDeclaration(declarationIn: AccessorDeclaration | VariableLikeDeclaration | PropertyAccessExpression, enclosingDeclaration: Node, flags: NodeBuilderFlags, tracker: SymbolTracker, addUndefined?: boolean) { + function createTypeOfDeclaration( + declarationIn: AccessorDeclaration | VariableLikeDeclaration | PropertyAccessExpression, + enclosingDeclaration: Node, + flags: NodeBuilderFlags, + tracker: SymbolTracker, + addUndefined?: boolean, + ) { const declaration = getParseTreeNode(declarationIn, isVariableLikeOrAccessor); if (!declaration) { return factory.createToken(SyntaxKind.AnyKeyword) as KeywordTypeNode; @@ -47208,40 +59858,68 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { ? getWidenedLiteralType(getTypeOfSymbol(symbol)) : errorType; if ( - type.flags & TypeFlags.UniqueESSymbol && - type.symbol === symbol + type.flags & TypeFlags.UniqueESSymbol + && type.symbol === symbol ) { flags |= NodeBuilderFlags.AllowUniqueESSymbolType; } if (addUndefined) { type = getOptionalType(type); } - return nodeBuilder.typeToTypeNode(type, enclosingDeclaration, flags | NodeBuilderFlags.MultilineObjectLiterals, tracker); + return nodeBuilder.typeToTypeNode( + type, + enclosingDeclaration, + flags | NodeBuilderFlags.MultilineObjectLiterals, + tracker, + ); } - function createReturnTypeOfSignatureDeclaration(signatureDeclarationIn: SignatureDeclaration, enclosingDeclaration: Node, flags: NodeBuilderFlags, tracker: SymbolTracker) { + function createReturnTypeOfSignatureDeclaration( + signatureDeclarationIn: SignatureDeclaration, + enclosingDeclaration: Node, + flags: NodeBuilderFlags, + tracker: SymbolTracker, + ) { const signatureDeclaration = getParseTreeNode(signatureDeclarationIn, isFunctionLike); if (!signatureDeclaration) { return factory.createToken(SyntaxKind.AnyKeyword) as KeywordTypeNode; } const signature = getSignatureFromDeclaration(signatureDeclaration); - return nodeBuilder.typeToTypeNode(getReturnTypeOfSignature(signature), enclosingDeclaration, flags | NodeBuilderFlags.MultilineObjectLiterals, tracker); + return nodeBuilder.typeToTypeNode( + getReturnTypeOfSignature(signature), + enclosingDeclaration, + flags | NodeBuilderFlags.MultilineObjectLiterals, + tracker, + ); } - function createTypeOfExpression(exprIn: Expression, enclosingDeclaration: Node, flags: NodeBuilderFlags, tracker: SymbolTracker) { + function createTypeOfExpression( + exprIn: Expression, + enclosingDeclaration: Node, + flags: NodeBuilderFlags, + tracker: SymbolTracker, + ) { const expr = getParseTreeNode(exprIn, isExpression); if (!expr) { return factory.createToken(SyntaxKind.AnyKeyword) as KeywordTypeNode; } const type = getWidenedType(getRegularTypeOfExpression(expr)); - return nodeBuilder.typeToTypeNode(type, enclosingDeclaration, flags | NodeBuilderFlags.MultilineObjectLiterals, tracker); + return nodeBuilder.typeToTypeNode( + type, + enclosingDeclaration, + flags | NodeBuilderFlags.MultilineObjectLiterals, + tracker, + ); } function hasGlobalName(name: string): boolean { return globals.has(escapeLeadingUnderscores(name)); } - function getReferencedValueSymbol(reference: Identifier, startInDeclarationContainer?: boolean): Symbol | undefined { + function getReferencedValueSymbol( + reference: Identifier, + startInDeclarationContainer?: boolean, + ): Symbol | undefined { const resolvedSymbol = getNodeLinks(reference).resolvedSymbol; if (resolvedSymbol) { return resolvedSymbol; @@ -47257,7 +59935,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } - return resolveName(location, reference.escapedText, SymbolFlags.Value | SymbolFlags.ExportValue | SymbolFlags.Alias, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ true); + return resolveName( + location, + reference.escapedText, + SymbolFlags.Value | SymbolFlags.ExportValue | SymbolFlags.Alias, + /*nameNotFoundMessage*/ undefined, + /*nameArg*/ undefined, + /*isUse*/ true, + ); } /** @@ -47336,7 +60021,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return undefined; } - function isLiteralConstDeclaration(node: VariableDeclaration | PropertyDeclaration | PropertySignature | ParameterDeclaration): boolean { + function isLiteralConstDeclaration( + node: VariableDeclaration | PropertyDeclaration | PropertySignature | ParameterDeclaration, + ): boolean { if (isDeclarationReadonly(node) || isVariableDeclaration(node) && isVarConstLike(node)) { return isFreshLiteralType(getTypeOfSymbol(getSymbolOfDeclaration(node))); } @@ -47344,23 +60031,33 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function literalTypeToNode(type: FreshableType, enclosing: Node, tracker: SymbolTracker): Expression { - const enumResult = type.flags & TypeFlags.EnumLike ? nodeBuilder.symbolToExpression(type.symbol, SymbolFlags.Value, enclosing, /*flags*/ undefined, tracker) + const enumResult = type.flags & TypeFlags.EnumLike + ? nodeBuilder.symbolToExpression(type.symbol, SymbolFlags.Value, enclosing, /*flags*/ undefined, tracker) : type === trueType ? factory.createTrue() : type === falseType && factory.createFalse(); if (enumResult) return enumResult; const literalValue = (type as LiteralType).value; - return typeof literalValue === "object" ? factory.createBigIntLiteral(literalValue) : - typeof literalValue === "string" ? factory.createStringLiteral(literalValue) : - literalValue < 0 ? factory.createPrefixUnaryExpression(SyntaxKind.MinusToken, factory.createNumericLiteral(Math.abs(literalValue))) : - factory.createNumericLiteral(literalValue); + return typeof literalValue === "object" ? factory.createBigIntLiteral(literalValue) + : typeof literalValue === "string" ? factory.createStringLiteral(literalValue) + : literalValue < 0 + ? factory.createPrefixUnaryExpression( + SyntaxKind.MinusToken, + factory.createNumericLiteral(Math.abs(literalValue)), + ) + : factory.createNumericLiteral(literalValue); } - function createLiteralConstValue(node: VariableDeclaration | PropertyDeclaration | PropertySignature | ParameterDeclaration, tracker: SymbolTracker) { + function createLiteralConstValue( + node: VariableDeclaration | PropertyDeclaration | PropertySignature | ParameterDeclaration, + tracker: SymbolTracker, + ) { const type = getTypeOfSymbol(getSymbolOfDeclaration(node)); return literalTypeToNode(type as FreshableType, node, tracker); } function getJsxFactoryEntity(location: Node): EntityName | undefined { - return location ? (getJsxNamespace(location), (getSourceFileOfNode(location).localJsxFactory || _jsxFactoryEntity)) : _jsxFactoryEntity; + return location + ? (getJsxNamespace(location), (getSourceFileOfNode(location).localJsxFactory || _jsxFactoryEntity)) + : _jsxFactoryEntity; } function getJsxFragmentFactoryEntity(location: Node): EntityName | undefined { @@ -47373,7 +60070,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const jsxFragPragmas = file.pragmas.get("jsxfrag"); const jsxFragPragma = isArray(jsxFragPragmas) ? jsxFragPragmas[0] : jsxFragPragmas; if (jsxFragPragma) { - file.localJsxFragmentFactory = parseIsolatedEntityName(jsxFragPragma.arguments.factory, languageVersion); + file.localJsxFragmentFactory = parseIsolatedEntityName( + jsxFragPragma.arguments.factory, + languageVersion, + ); return file.localJsxFragmentFactory; } } @@ -47419,7 +60119,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { isReferencedAliasDeclaration: (nodeIn, checkChildren?) => { const node = getParseTreeNode(nodeIn); // Synthesized nodes are always treated as referenced. - return node && canCollectSymbolAliasAccessabilityData ? isReferencedAliasDeclaration(node, checkChildren) : true; + return node && canCollectSymbolAliasAccessabilityData + ? isReferencedAliasDeclaration(node, checkChildren) : true; }, getNodeCheckFlags: nodeIn => { const node = getParseTreeNode(nodeIn); @@ -47465,12 +60166,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { getJsxFragmentFactoryEntity, getAllAccessorDeclarations(accessor: AccessorDeclaration): AllAccessorDeclarations { accessor = getParseTreeNode(accessor, isGetOrSetAccessorDeclaration)!; // TODO: GH#18217 - const otherKind = accessor.kind === SyntaxKind.SetAccessor ? SyntaxKind.GetAccessor : SyntaxKind.SetAccessor; - const otherAccessor = getDeclarationOfKind(getSymbolOfDeclaration(accessor), otherKind); + const otherKind = accessor.kind === SyntaxKind.SetAccessor ? SyntaxKind.GetAccessor + : SyntaxKind.SetAccessor; + const otherAccessor = getDeclarationOfKind( + getSymbolOfDeclaration(accessor), + otherKind, + ); const firstAccessor = otherAccessor && (otherAccessor.pos < accessor.pos) ? otherAccessor : accessor; const secondAccessor = otherAccessor && (otherAccessor.pos < accessor.pos) ? accessor : otherAccessor; - const setAccessor = accessor.kind === SyntaxKind.SetAccessor ? accessor : otherAccessor as SetAccessorDeclaration; - const getAccessor = accessor.kind === SyntaxKind.GetAccessor ? accessor : otherAccessor as GetAccessorDeclaration; + const setAccessor = accessor.kind === SyntaxKind.SetAccessor ? accessor + : otherAccessor as SetAccessorDeclaration; + const getAccessor = accessor.kind === SyntaxKind.GetAccessor ? accessor + : otherAccessor as GetAccessorDeclaration; return { firstAccessor, secondAccessor, @@ -47478,20 +60185,27 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { getAccessor, }; }, - getSymbolOfExternalModuleSpecifier: moduleName => resolveExternalModuleNameWorker(moduleName, moduleName, /*moduleNotFoundError*/ undefined), + getSymbolOfExternalModuleSpecifier: moduleName => + resolveExternalModuleNameWorker(moduleName, moduleName, /*moduleNotFoundError*/ undefined), isBindingCapturedByNode: (node, decl) => { const parseNode = getParseTreeNode(node); const parseDecl = getParseTreeNode(decl); - return !!parseNode && !!parseDecl && (isVariableDeclaration(parseDecl) || isBindingElement(parseDecl)) && isBindingCapturedByNode(parseNode, parseDecl); + return !!parseNode && !!parseDecl && (isVariableDeclaration(parseDecl) || isBindingElement(parseDecl)) + && isBindingCapturedByNode(parseNode, parseDecl); }, getDeclarationStatementsForSourceFile: (node, flags, tracker, bundled) => { const n = getParseTreeNode(node) as SourceFile; - Debug.assert(n && n.kind === SyntaxKind.SourceFile, "Non-sourcefile node passed into getDeclarationsForSourceFile"); + Debug.assert( + n && n.kind === SyntaxKind.SourceFile, + "Non-sourcefile node passed into getDeclarationsForSourceFile", + ); const sym = getSymbolOfDeclaration(node); if (!sym) { - return !node.locals ? [] : nodeBuilder.symbolTableToDeclarationStatements(node.locals, node, flags, tracker, bundled); + return !node.locals ? [] + : nodeBuilder.symbolTableToDeclarationStatements(node.locals, node, flags, tracker, bundled); } - return !sym.exports ? [] : nodeBuilder.symbolTableToDeclarationStatements(sym.exports, node, flags, tracker, bundled); + return !sym.exports ? [] + : nodeBuilder.symbolTableToDeclarationStatements(sym.exports, node, flags, tracker, bundled); }, isImportRequiredByAugmentation, }; @@ -47520,11 +60234,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function isInHeritageClause(node: PropertyAccessEntityNameExpression) { - return node.parent && node.parent.kind === SyntaxKind.ExpressionWithTypeArguments && node.parent.parent && node.parent.parent.kind === SyntaxKind.HeritageClause; + return node.parent && node.parent.kind === SyntaxKind.ExpressionWithTypeArguments && node.parent.parent + && node.parent.parent.kind === SyntaxKind.HeritageClause; } // defined here to avoid outer scope pollution - function getTypeReferenceDirectivesForEntityName(node: EntityNameOrEntityNameExpression): [specifier: string, mode: ResolutionMode][] | undefined { + function getTypeReferenceDirectivesForEntityName( + node: EntityNameOrEntityNameExpression, + ): [specifier: string, mode: ResolutionMode][] | undefined { // program does not have any files with type reference directives - bail out if (!fileToDirective) { return undefined; @@ -47539,17 +60256,24 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } else { meaning = SymbolFlags.Type | SymbolFlags.Namespace; - if ((node.kind === SyntaxKind.Identifier && isInTypeQuery(node)) || (node.kind === SyntaxKind.PropertyAccessExpression && !isInHeritageClause(node))) { + if ( + (node.kind === SyntaxKind.Identifier && isInTypeQuery(node)) + || (node.kind === SyntaxKind.PropertyAccessExpression && !isInHeritageClause(node)) + ) { meaning = SymbolFlags.Value | SymbolFlags.ExportValue; } } const symbol = resolveEntityName(node, meaning, /*ignoreErrors*/ true); - return symbol && symbol !== unknownSymbol ? getTypeReferenceDirectivesForSymbol(symbol, meaning) : undefined; + return symbol && symbol !== unknownSymbol ? getTypeReferenceDirectivesForSymbol(symbol, meaning) + : undefined; } // defined here to avoid outer scope pollution - function getTypeReferenceDirectivesForSymbol(symbol: Symbol, meaning?: SymbolFlags): [specifier: string, mode: ResolutionMode][] | undefined { + function getTypeReferenceDirectivesForSymbol( + symbol: Symbol, + meaning?: SymbolFlags, + ): [specifier: string, mode: ResolutionMode][] | undefined { // program does not have any files with type reference directives - bail out if (!fileToDirective || !isSymbolFromTypeDeclarationFile(symbol)) { return undefined; @@ -47592,7 +60316,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } - if (current.valueDeclaration && current.valueDeclaration.kind === SyntaxKind.SourceFile && current.flags & SymbolFlags.ValueModule) { + if ( + current.valueDeclaration && current.valueDeclaration.kind === SyntaxKind.SourceFile + && current.flags & SymbolFlags.ValueModule + ) { return false; } @@ -47619,8 +60346,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } - function getExternalModuleFileFromDeclaration(declaration: AnyImportOrReExport | ModuleDeclaration | ImportTypeNode | ImportCall): SourceFile | undefined { - const specifier = declaration.kind === SyntaxKind.ModuleDeclaration ? tryCast(declaration.name, isStringLiteral) : getExternalModuleName(declaration); + function getExternalModuleFileFromDeclaration( + declaration: AnyImportOrReExport | ModuleDeclaration | ImportTypeNode | ImportCall, + ): SourceFile | undefined { + const specifier = declaration.kind === SyntaxKind.ModuleDeclaration ? tryCast(declaration.name, isStringLiteral) + : getExternalModuleName(declaration); const moduleSymbol = resolveExternalModuleNameWorker(specifier!, specifier!, /*moduleNotFoundError*/ undefined); // TODO: GH#18217 if (!moduleSymbol) { return undefined; @@ -47648,7 +60378,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const fileGlobalThisSymbol = file.locals!.get("globalThis" as __String); if (fileGlobalThisSymbol?.declarations) { for (const declaration of fileGlobalThisSymbol.declarations) { - diagnostics.add(createDiagnosticForNode(declaration, Diagnostics.Declaration_name_conflicts_with_built_in_global_identifier_0, "globalThis")); + diagnostics.add( + createDiagnosticForNode( + declaration, + Diagnostics.Declaration_name_conflicts_with_built_in_global_identifier_0, + "globalThis", + ), + ); } } mergeSymbolTable(globals, file.locals!); @@ -47691,10 +60427,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } // Setup global builtins - addToSymbolTable(globals, builtinGlobals, Diagnostics.Declaration_name_conflicts_with_built_in_global_identifier_0); + addToSymbolTable( + globals, + builtinGlobals, + Diagnostics.Declaration_name_conflicts_with_built_in_global_identifier_0, + ); getSymbolLinks(undefinedSymbol).type = undefinedWideningType; - getSymbolLinks(argumentsSymbol).type = getGlobalType("IArguments" as __String, /*arity*/ 0, /*reportErrors*/ true); + getSymbolLinks(argumentsSymbol).type = getGlobalType( + "IArguments" as __String, + /*arity*/ 0, + /*reportErrors*/ true, + ); getSymbolLinks(unknownSymbol).type = errorType; getSymbolLinks(globalThisSymbol).type = createObjectType(ObjectFlags.Anonymous, globalThisSymbol); @@ -47702,8 +60446,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { globalArrayType = getGlobalType("Array" as __String, /*arity*/ 1, /*reportErrors*/ true); globalObjectType = getGlobalType("Object" as __String, /*arity*/ 0, /*reportErrors*/ true); globalFunctionType = getGlobalType("Function" as __String, /*arity*/ 0, /*reportErrors*/ true); - globalCallableFunctionType = strictBindCallApply && getGlobalType("CallableFunction" as __String, /*arity*/ 0, /*reportErrors*/ true) || globalFunctionType; - globalNewableFunctionType = strictBindCallApply && getGlobalType("NewableFunction" as __String, /*arity*/ 0, /*reportErrors*/ true) || globalFunctionType; + globalCallableFunctionType = + strictBindCallApply && getGlobalType("CallableFunction" as __String, /*arity*/ 0, /*reportErrors*/ true) + || globalFunctionType; + globalNewableFunctionType = + strictBindCallApply && getGlobalType("NewableFunction" as __String, /*arity*/ 0, /*reportErrors*/ true) + || globalFunctionType; globalStringType = getGlobalType("String" as __String, /*arity*/ 0, /*reportErrors*/ true); globalNumberType = getGlobalType("Number" as __String, /*arity*/ 0, /*reportErrors*/ true); globalBooleanType = getGlobalType("Boolean" as __String, /*arity*/ 0, /*reportErrors*/ true); @@ -47716,8 +60464,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { autoArrayType = createAnonymousType(/*symbol*/ undefined, emptySymbols, emptyArray, emptyArray, emptyArray); } - globalReadonlyArrayType = getGlobalTypeOrUndefined("ReadonlyArray" as __String, /*arity*/ 1) as GenericType || globalArrayType; - anyReadonlyArrayType = globalReadonlyArrayType ? createTypeFromGenericGlobalType(globalReadonlyArrayType, [anyType]) : anyArrayType; + globalReadonlyArrayType = getGlobalTypeOrUndefined("ReadonlyArray" as __String, /*arity*/ 1) as GenericType + || globalArrayType; + anyReadonlyArrayType = globalReadonlyArrayType + ? createTypeFromGenericGlobalType(globalReadonlyArrayType, [anyType]) : anyArrayType; globalThisType = getGlobalTypeOrUndefined("ThisType" as __String, /*arity*/ 1) as GenericType; if (augmentations) { @@ -47735,7 +60485,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // If not many things conflict, issue individual errors if (conflictingSymbols.size < 8) { conflictingSymbols.forEach(({ isBlockScoped, firstFileLocations, secondFileLocations }, symbolName) => { - const message = isBlockScoped ? Diagnostics.Cannot_redeclare_block_scoped_variable_0 : Diagnostics.Duplicate_identifier_0; + const message = isBlockScoped ? Diagnostics.Cannot_redeclare_block_scoped_variable_0 + : Diagnostics.Duplicate_identifier_0; for (const node of firstFileLocations) { addDuplicateDeclarationError(node, message, symbolName, secondFileLocations); } @@ -47748,11 +60499,21 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // Otherwise issue top-level error since the files appear very identical in terms of what they contain const list = arrayFrom(conflictingSymbols.keys()).join(", "); diagnostics.add(addRelatedInfo( - createDiagnosticForNode(firstFile, Diagnostics.Definitions_of_the_following_identifiers_conflict_with_those_in_another_file_Colon_0, list), + createDiagnosticForNode( + firstFile, + Diagnostics + .Definitions_of_the_following_identifiers_conflict_with_those_in_another_file_Colon_0, + list, + ), createDiagnosticForNode(secondFile, Diagnostics.Conflicts_are_in_this_file), )); diagnostics.add(addRelatedInfo( - createDiagnosticForNode(secondFile, Diagnostics.Definitions_of_the_following_identifiers_conflict_with_those_in_another_file_Colon_0, list), + createDiagnosticForNode( + secondFile, + Diagnostics + .Definitions_of_the_following_identifiers_conflict_with_those_in_another_file_Colon_0, + list, + ), createDiagnosticForNode(firstFile, Diagnostics.Conflicts_are_in_this_file), )); } @@ -47767,29 +60528,81 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const helpersModule = resolveHelpersModule(sourceFile, location); if (helpersModule !== unknownSymbol) { const uncheckedHelpers = helpers & ~requestedExternalEmitHelpers; - for (let helper = ExternalEmitHelpers.FirstEmitHelper; helper <= ExternalEmitHelpers.LastEmitHelper; helper <<= 1) { + for ( + let helper = ExternalEmitHelpers.FirstEmitHelper; + helper <= ExternalEmitHelpers.LastEmitHelper; + helper <<= 1 + ) { if (uncheckedHelpers & helper) { for (const name of getHelperNames(helper)) { if (requestedExternalEmitHelperNames.has(name)) continue; requestedExternalEmitHelperNames.add(name); - const symbol = resolveSymbol(getSymbol(getExportsOfModule(helpersModule), escapeLeadingUnderscores(name), SymbolFlags.Value)); + const symbol = resolveSymbol( + getSymbol( + getExportsOfModule(helpersModule), + escapeLeadingUnderscores(name), + SymbolFlags.Value, + ), + ); if (!symbol) { - error(location, Diagnostics.This_syntax_requires_an_imported_helper_named_1_which_does_not_exist_in_0_Consider_upgrading_your_version_of_0, externalHelpersModuleNameText, name); + error( + location, + Diagnostics + .This_syntax_requires_an_imported_helper_named_1_which_does_not_exist_in_0_Consider_upgrading_your_version_of_0, + externalHelpersModuleNameText, + name, + ); } else if (helper & ExternalEmitHelpers.ClassPrivateFieldGet) { - if (!some(getSignaturesOfSymbol(symbol), signature => getParameterCount(signature) > 3)) { - error(location, Diagnostics.This_syntax_requires_an_imported_helper_named_1_with_2_parameters_which_is_not_compatible_with_the_one_in_0_Consider_upgrading_your_version_of_0, externalHelpersModuleNameText, name, 4); + if ( + !some( + getSignaturesOfSymbol(symbol), + signature => getParameterCount(signature) > 3, + ) + ) { + error( + location, + Diagnostics + .This_syntax_requires_an_imported_helper_named_1_with_2_parameters_which_is_not_compatible_with_the_one_in_0_Consider_upgrading_your_version_of_0, + externalHelpersModuleNameText, + name, + 4, + ); } } else if (helper & ExternalEmitHelpers.ClassPrivateFieldSet) { - if (!some(getSignaturesOfSymbol(symbol), signature => getParameterCount(signature) > 4)) { - error(location, Diagnostics.This_syntax_requires_an_imported_helper_named_1_with_2_parameters_which_is_not_compatible_with_the_one_in_0_Consider_upgrading_your_version_of_0, externalHelpersModuleNameText, name, 5); + if ( + !some( + getSignaturesOfSymbol(symbol), + signature => getParameterCount(signature) > 4, + ) + ) { + error( + location, + Diagnostics + .This_syntax_requires_an_imported_helper_named_1_with_2_parameters_which_is_not_compatible_with_the_one_in_0_Consider_upgrading_your_version_of_0, + externalHelpersModuleNameText, + name, + 5, + ); } } else if (helper & ExternalEmitHelpers.SpreadArray) { - if (!some(getSignaturesOfSymbol(symbol), signature => getParameterCount(signature) > 2)) { - error(location, Diagnostics.This_syntax_requires_an_imported_helper_named_1_with_2_parameters_which_is_not_compatible_with_the_one_in_0_Consider_upgrading_your_version_of_0, externalHelpersModuleNameText, name, 3); + if ( + !some( + getSignaturesOfSymbol(symbol), + signature => getParameterCount(signature) > 2, + ) + ) { + error( + location, + Diagnostics + .This_syntax_requires_an_imported_helper_named_1_with_2_parameters_which_is_not_compatible_with_the_one_in_0_Consider_upgrading_your_version_of_0, + externalHelpersModuleNameText, + name, + 3, + ); } } } @@ -47862,25 +60675,40 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function resolveHelpersModule(node: SourceFile, errorNode: Node) { if (!externalHelpersModule) { - externalHelpersModule = resolveExternalModule(node, externalHelpersModuleNameText, Diagnostics.This_syntax_requires_an_imported_helper_but_module_0_cannot_be_found, errorNode) || unknownSymbol; + externalHelpersModule = resolveExternalModule( + node, + externalHelpersModuleNameText, + Diagnostics.This_syntax_requires_an_imported_helper_but_module_0_cannot_be_found, + errorNode, + ) || unknownSymbol; } return externalHelpersModule; } // GRAMMAR CHECKING - function checkGrammarModifiers(node: HasModifiers | HasDecorators | HasIllegalModifiers | HasIllegalDecorators): boolean { + function checkGrammarModifiers( + node: HasModifiers | HasDecorators | HasIllegalModifiers | HasIllegalDecorators, + ): boolean { const quickResult = reportObviousDecoratorErrors(node) || reportObviousModifierErrors(node); if (quickResult !== undefined) { return quickResult; } if (isParameter(node) && parameterIsThisKeyword(node)) { - return grammarErrorOnFirstToken(node, Diagnostics.Neither_decorators_nor_modifiers_may_be_applied_to_this_parameters); + return grammarErrorOnFirstToken( + node, + Diagnostics.Neither_decorators_nor_modifiers_may_be_applied_to_this_parameters, + ); } - const blockScopeKind = isVariableStatement(node) ? node.declarationList.flags & NodeFlags.BlockScoped : NodeFlags.None; - let lastStatic: Node | undefined, lastDeclare: Node | undefined, lastAsync: Node | undefined, lastOverride: Node | undefined, firstDecorator: Decorator | undefined; + const blockScopeKind = isVariableStatement(node) ? node.declarationList.flags & NodeFlags.BlockScoped + : NodeFlags.None; + let lastStatic: Node | undefined, + lastDeclare: Node | undefined, + lastAsync: Node | undefined, + lastOverride: Node | undefined, + firstDecorator: Decorator | undefined; let flags = ModifierFlags.None; let sawExportBeforeDecorators = false; // We parse decorators and modifiers in four contiguous chunks: @@ -47891,16 +60719,28 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (isDecorator(modifier)) { if (!nodeCanBeDecorated(legacyDecorators, node, node.parent, node.parent.parent)) { if (node.kind === SyntaxKind.MethodDeclaration && !nodeIsPresent(node.body)) { - return grammarErrorOnFirstToken(node, Diagnostics.A_decorator_can_only_decorate_a_method_implementation_not_an_overload); + return grammarErrorOnFirstToken( + node, + Diagnostics.A_decorator_can_only_decorate_a_method_implementation_not_an_overload, + ); } else { return grammarErrorOnFirstToken(node, Diagnostics.Decorators_are_not_valid_here); } } - else if (legacyDecorators && (node.kind === SyntaxKind.GetAccessor || node.kind === SyntaxKind.SetAccessor)) { - const accessors = getAllAccessorDeclarations((node.parent as ClassDeclaration).members, node as AccessorDeclaration); + else if ( + legacyDecorators && (node.kind === SyntaxKind.GetAccessor || node.kind === SyntaxKind.SetAccessor) + ) { + const accessors = getAllAccessorDeclarations( + (node.parent as ClassDeclaration).members, + node as AccessorDeclaration, + ); if (hasDecorators(accessors.firstAccessor) && node === accessors.secondAccessor) { - return grammarErrorOnFirstToken(node, Diagnostics.Decorators_cannot_be_applied_to_multiple_get_Slashset_accessors_of_the_same_name); + return grammarErrorOnFirstToken( + node, + Diagnostics + .Decorators_cannot_be_applied_to_multiple_get_Slashset_accessors_of_the_same_name, + ); } } @@ -47915,7 +60755,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const sourceFile = getSourceFileOfNode(modifier); if (!hasParseDiagnostics(sourceFile)) { addRelatedInfo( - error(modifier, Diagnostics.Decorators_may_not_appear_after_export_or_export_default_if_they_also_appear_before_export), + error( + modifier, + Diagnostics + .Decorators_may_not_appear_after_export_or_export_default_if_they_also_appear_before_export, + ), createDiagnosticForNode(firstDecorator, Diagnostics.Decorator_used_before_export_here), ); return true; @@ -47938,28 +60782,57 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { else { if (modifier.kind !== SyntaxKind.ReadonlyKeyword) { if (node.kind === SyntaxKind.PropertySignature || node.kind === SyntaxKind.MethodSignature) { - return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_appear_on_a_type_member, tokenToString(modifier.kind)); + return grammarErrorOnNode( + modifier, + Diagnostics._0_modifier_cannot_appear_on_a_type_member, + tokenToString(modifier.kind), + ); } - if (node.kind === SyntaxKind.IndexSignature && (modifier.kind !== SyntaxKind.StaticKeyword || !isClassLike(node.parent))) { - return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_appear_on_an_index_signature, tokenToString(modifier.kind)); + if ( + node.kind === SyntaxKind.IndexSignature + && (modifier.kind !== SyntaxKind.StaticKeyword || !isClassLike(node.parent)) + ) { + return grammarErrorOnNode( + modifier, + Diagnostics._0_modifier_cannot_appear_on_an_index_signature, + tokenToString(modifier.kind), + ); } } - if (modifier.kind !== SyntaxKind.InKeyword && modifier.kind !== SyntaxKind.OutKeyword && modifier.kind !== SyntaxKind.ConstKeyword) { + if ( + modifier.kind !== SyntaxKind.InKeyword && modifier.kind !== SyntaxKind.OutKeyword + && modifier.kind !== SyntaxKind.ConstKeyword + ) { if (node.kind === SyntaxKind.TypeParameter) { - return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_appear_on_a_type_parameter, tokenToString(modifier.kind)); + return grammarErrorOnNode( + modifier, + Diagnostics._0_modifier_cannot_appear_on_a_type_parameter, + tokenToString(modifier.kind), + ); } } switch (modifier.kind) { case SyntaxKind.ConstKeyword: if (node.kind !== SyntaxKind.EnumDeclaration && node.kind !== SyntaxKind.TypeParameter) { - return grammarErrorOnNode(node, Diagnostics.A_class_member_cannot_have_the_0_keyword, tokenToString(SyntaxKind.ConstKeyword)); + return grammarErrorOnNode( + node, + Diagnostics.A_class_member_cannot_have_the_0_keyword, + tokenToString(SyntaxKind.ConstKeyword), + ); } const parent = node.parent; if ( - node.kind === SyntaxKind.TypeParameter && !(isFunctionLikeDeclaration(parent) || isClassLike(parent) || isFunctionTypeNode(parent) || - isConstructorTypeNode(parent) || isCallSignatureDeclaration(parent) || isConstructSignatureDeclaration(parent) || isMethodSignature(parent)) + node.kind === SyntaxKind.TypeParameter + && !(isFunctionLikeDeclaration(parent) || isClassLike(parent) || isFunctionTypeNode(parent) + || isConstructorTypeNode(parent) || isCallSignatureDeclaration(parent) + || isConstructSignatureDeclaration(parent) || isMethodSignature(parent)) ) { - return grammarErrorOnNode(modifier, Diagnostics._0_modifier_can_only_appear_on_a_type_parameter_of_a_function_method_or_class, tokenToString(modifier.kind)); + return grammarErrorOnNode( + modifier, + Diagnostics + ._0_modifier_can_only_appear_on_a_type_parameter_of_a_function_method_or_class, + tokenToString(modifier.kind), + ); } break; case SyntaxKind.OverrideKeyword: @@ -47968,16 +60841,36 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return grammarErrorOnNode(modifier, Diagnostics._0_modifier_already_seen, "override"); } else if (flags & ModifierFlags.Ambient) { - return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_be_used_with_1_modifier, "override", "declare"); + return grammarErrorOnNode( + modifier, + Diagnostics._0_modifier_cannot_be_used_with_1_modifier, + "override", + "declare", + ); } else if (flags & ModifierFlags.Readonly) { - return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, "override", "readonly"); + return grammarErrorOnNode( + modifier, + Diagnostics._0_modifier_must_precede_1_modifier, + "override", + "readonly", + ); } else if (flags & ModifierFlags.Accessor) { - return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, "override", "accessor"); + return grammarErrorOnNode( + modifier, + Diagnostics._0_modifier_must_precede_1_modifier, + "override", + "accessor", + ); } else if (flags & ModifierFlags.Async) { - return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, "override", "async"); + return grammarErrorOnNode( + modifier, + Diagnostics._0_modifier_must_precede_1_modifier, + "override", + "async", + ); } flags |= ModifierFlags.Override; lastOverride = modifier; @@ -47992,33 +60885,77 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return grammarErrorOnNode(modifier, Diagnostics.Accessibility_modifier_already_seen); } else if (flags & ModifierFlags.Override) { - return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, text, "override"); + return grammarErrorOnNode( + modifier, + Diagnostics._0_modifier_must_precede_1_modifier, + text, + "override", + ); } else if (flags & ModifierFlags.Static) { - return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, text, "static"); + return grammarErrorOnNode( + modifier, + Diagnostics._0_modifier_must_precede_1_modifier, + text, + "static", + ); } else if (flags & ModifierFlags.Accessor) { - return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, text, "accessor"); + return grammarErrorOnNode( + modifier, + Diagnostics._0_modifier_must_precede_1_modifier, + text, + "accessor", + ); } else if (flags & ModifierFlags.Readonly) { - return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, text, "readonly"); + return grammarErrorOnNode( + modifier, + Diagnostics._0_modifier_must_precede_1_modifier, + text, + "readonly", + ); } else if (flags & ModifierFlags.Async) { - return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, text, "async"); + return grammarErrorOnNode( + modifier, + Diagnostics._0_modifier_must_precede_1_modifier, + text, + "async", + ); } - else if (node.parent.kind === SyntaxKind.ModuleBlock || node.parent.kind === SyntaxKind.SourceFile) { - return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_appear_on_a_module_or_namespace_element, text); + else if ( + node.parent.kind === SyntaxKind.ModuleBlock || node.parent.kind === SyntaxKind.SourceFile + ) { + return grammarErrorOnNode( + modifier, + Diagnostics._0_modifier_cannot_appear_on_a_module_or_namespace_element, + text, + ); } else if (flags & ModifierFlags.Abstract) { if (modifier.kind === SyntaxKind.PrivateKeyword) { - return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_be_used_with_1_modifier, text, "abstract"); + return grammarErrorOnNode( + modifier, + Diagnostics._0_modifier_cannot_be_used_with_1_modifier, + text, + "abstract", + ); } else { - return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, text, "abstract"); + return grammarErrorOnNode( + modifier, + Diagnostics._0_modifier_must_precede_1_modifier, + text, + "abstract", + ); } } else if (isPrivateIdentifierClassElementDeclaration(node)) { - return grammarErrorOnNode(modifier, Diagnostics.An_accessibility_modifier_cannot_be_used_with_a_private_identifier); + return grammarErrorOnNode( + modifier, + Diagnostics.An_accessibility_modifier_cannot_be_used_with_a_private_identifier, + ); } flags |= modifierToFlag(modifier.kind); break; @@ -48028,25 +60965,60 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return grammarErrorOnNode(modifier, Diagnostics._0_modifier_already_seen, "static"); } else if (flags & ModifierFlags.Readonly) { - return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, "static", "readonly"); + return grammarErrorOnNode( + modifier, + Diagnostics._0_modifier_must_precede_1_modifier, + "static", + "readonly", + ); } else if (flags & ModifierFlags.Async) { - return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, "static", "async"); + return grammarErrorOnNode( + modifier, + Diagnostics._0_modifier_must_precede_1_modifier, + "static", + "async", + ); } else if (flags & ModifierFlags.Accessor) { - return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, "static", "accessor"); + return grammarErrorOnNode( + modifier, + Diagnostics._0_modifier_must_precede_1_modifier, + "static", + "accessor", + ); } - else if (node.parent.kind === SyntaxKind.ModuleBlock || node.parent.kind === SyntaxKind.SourceFile) { - return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_appear_on_a_module_or_namespace_element, "static"); + else if ( + node.parent.kind === SyntaxKind.ModuleBlock || node.parent.kind === SyntaxKind.SourceFile + ) { + return grammarErrorOnNode( + modifier, + Diagnostics._0_modifier_cannot_appear_on_a_module_or_namespace_element, + "static", + ); } else if (node.kind === SyntaxKind.Parameter) { - return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_appear_on_a_parameter, "static"); + return grammarErrorOnNode( + modifier, + Diagnostics._0_modifier_cannot_appear_on_a_parameter, + "static", + ); } else if (flags & ModifierFlags.Abstract) { - return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_be_used_with_1_modifier, "static", "abstract"); + return grammarErrorOnNode( + modifier, + Diagnostics._0_modifier_cannot_be_used_with_1_modifier, + "static", + "abstract", + ); } else if (flags & ModifierFlags.Override) { - return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, "static", "override"); + return grammarErrorOnNode( + modifier, + Diagnostics._0_modifier_must_precede_1_modifier, + "static", + "override", + ); } flags |= ModifierFlags.Static; lastStatic = modifier; @@ -48057,13 +61029,26 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return grammarErrorOnNode(modifier, Diagnostics._0_modifier_already_seen, "accessor"); } else if (flags & ModifierFlags.Readonly) { - return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_be_used_with_1_modifier, "accessor", "readonly"); + return grammarErrorOnNode( + modifier, + Diagnostics._0_modifier_cannot_be_used_with_1_modifier, + "accessor", + "readonly", + ); } else if (flags & ModifierFlags.Ambient) { - return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_be_used_with_1_modifier, "accessor", "declare"); + return grammarErrorOnNode( + modifier, + Diagnostics._0_modifier_cannot_be_used_with_1_modifier, + "accessor", + "declare", + ); } else if (node.kind !== SyntaxKind.PropertyDeclaration) { - return grammarErrorOnNode(modifier, Diagnostics.accessor_modifier_can_only_appear_on_a_property_declaration); + return grammarErrorOnNode( + modifier, + Diagnostics.accessor_modifier_can_only_appear_on_a_property_declaration, + ); } flags |= ModifierFlags.Accessor; @@ -48073,68 +61058,132 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (flags & ModifierFlags.Readonly) { return grammarErrorOnNode(modifier, Diagnostics._0_modifier_already_seen, "readonly"); } - else if (node.kind !== SyntaxKind.PropertyDeclaration && node.kind !== SyntaxKind.PropertySignature && node.kind !== SyntaxKind.IndexSignature && node.kind !== SyntaxKind.Parameter) { + else if ( + node.kind !== SyntaxKind.PropertyDeclaration && node.kind !== SyntaxKind.PropertySignature + && node.kind !== SyntaxKind.IndexSignature && node.kind !== SyntaxKind.Parameter + ) { // If node.kind === SyntaxKind.Parameter, checkParameter reports an error if it's not a parameter property. - return grammarErrorOnNode(modifier, Diagnostics.readonly_modifier_can_only_appear_on_a_property_declaration_or_index_signature); + return grammarErrorOnNode( + modifier, + Diagnostics + .readonly_modifier_can_only_appear_on_a_property_declaration_or_index_signature, + ); } else if (flags & ModifierFlags.Accessor) { - return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_be_used_with_1_modifier, "readonly", "accessor"); + return grammarErrorOnNode( + modifier, + Diagnostics._0_modifier_cannot_be_used_with_1_modifier, + "readonly", + "accessor", + ); } flags |= ModifierFlags.Readonly; break; case SyntaxKind.ExportKeyword: if ( - compilerOptions.verbatimModuleSyntax && - !(node.flags & NodeFlags.Ambient) && - node.kind !== SyntaxKind.TypeAliasDeclaration && - node.kind !== SyntaxKind.InterfaceDeclaration && + compilerOptions.verbatimModuleSyntax + && !(node.flags & NodeFlags.Ambient) + && node.kind !== SyntaxKind.TypeAliasDeclaration + && node.kind !== SyntaxKind.InterfaceDeclaration // ModuleDeclaration needs to be checked that it is uninstantiated later - node.kind !== SyntaxKind.ModuleDeclaration && - node.parent.kind === SyntaxKind.SourceFile && - (moduleKind === ModuleKind.CommonJS || getSourceFileOfNode(node).impliedNodeFormat === ModuleKind.CommonJS) + && node.kind !== SyntaxKind.ModuleDeclaration + && node.parent.kind === SyntaxKind.SourceFile + && (moduleKind === ModuleKind.CommonJS + || getSourceFileOfNode(node).impliedNodeFormat === ModuleKind.CommonJS) ) { - return grammarErrorOnNode(modifier, Diagnostics.A_top_level_export_modifier_cannot_be_used_on_value_declarations_in_a_CommonJS_module_when_verbatimModuleSyntax_is_enabled); + return grammarErrorOnNode( + modifier, + Diagnostics + .A_top_level_export_modifier_cannot_be_used_on_value_declarations_in_a_CommonJS_module_when_verbatimModuleSyntax_is_enabled, + ); } if (flags & ModifierFlags.Export) { return grammarErrorOnNode(modifier, Diagnostics._0_modifier_already_seen, "export"); } else if (flags & ModifierFlags.Ambient) { - return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, "export", "declare"); + return grammarErrorOnNode( + modifier, + Diagnostics._0_modifier_must_precede_1_modifier, + "export", + "declare", + ); } else if (flags & ModifierFlags.Abstract) { - return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, "export", "abstract"); + return grammarErrorOnNode( + modifier, + Diagnostics._0_modifier_must_precede_1_modifier, + "export", + "abstract", + ); } else if (flags & ModifierFlags.Async) { - return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, "export", "async"); + return grammarErrorOnNode( + modifier, + Diagnostics._0_modifier_must_precede_1_modifier, + "export", + "async", + ); } else if (isClassLike(node.parent)) { - return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_appear_on_class_elements_of_this_kind, "export"); + return grammarErrorOnNode( + modifier, + Diagnostics._0_modifier_cannot_appear_on_class_elements_of_this_kind, + "export", + ); } else if (node.kind === SyntaxKind.Parameter) { - return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_appear_on_a_parameter, "export"); + return grammarErrorOnNode( + modifier, + Diagnostics._0_modifier_cannot_appear_on_a_parameter, + "export", + ); } else if (blockScopeKind === NodeFlags.Using) { - return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_appear_on_a_using_declaration, "export"); + return grammarErrorOnNode( + modifier, + Diagnostics._0_modifier_cannot_appear_on_a_using_declaration, + "export", + ); } else if (blockScopeKind === NodeFlags.AwaitUsing) { - return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_appear_on_an_await_using_declaration, "export"); + return grammarErrorOnNode( + modifier, + Diagnostics._0_modifier_cannot_appear_on_an_await_using_declaration, + "export", + ); } flags |= ModifierFlags.Export; break; case SyntaxKind.DefaultKeyword: const container = node.parent.kind === SyntaxKind.SourceFile ? node.parent : node.parent.parent; if (container.kind === SyntaxKind.ModuleDeclaration && !isAmbientModule(container)) { - return grammarErrorOnNode(modifier, Diagnostics.A_default_export_can_only_be_used_in_an_ECMAScript_style_module); + return grammarErrorOnNode( + modifier, + Diagnostics.A_default_export_can_only_be_used_in_an_ECMAScript_style_module, + ); } else if (blockScopeKind === NodeFlags.Using) { - return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_appear_on_a_using_declaration, "default"); + return grammarErrorOnNode( + modifier, + Diagnostics._0_modifier_cannot_appear_on_a_using_declaration, + "default", + ); } else if (blockScopeKind === NodeFlags.AwaitUsing) { - return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_appear_on_an_await_using_declaration, "default"); + return grammarErrorOnNode( + modifier, + Diagnostics._0_modifier_cannot_appear_on_an_await_using_declaration, + "default", + ); } else if (!(flags & ModifierFlags.Export)) { - return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, "export", "default"); + return grammarErrorOnNode( + modifier, + Diagnostics._0_modifier_must_precede_1_modifier, + "export", + "default", + ); } else if (sawExportBeforeDecorators) { return grammarErrorOnNode(firstDecorator!, Diagnostics.Decorators_are_not_valid_here); @@ -48147,31 +61196,69 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return grammarErrorOnNode(modifier, Diagnostics._0_modifier_already_seen, "declare"); } else if (flags & ModifierFlags.Async) { - return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_be_used_in_an_ambient_context, "async"); + return grammarErrorOnNode( + modifier, + Diagnostics._0_modifier_cannot_be_used_in_an_ambient_context, + "async", + ); } else if (flags & ModifierFlags.Override) { - return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_be_used_in_an_ambient_context, "override"); + return grammarErrorOnNode( + modifier, + Diagnostics._0_modifier_cannot_be_used_in_an_ambient_context, + "override", + ); } else if (isClassLike(node.parent) && !isPropertyDeclaration(node)) { - return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_appear_on_class_elements_of_this_kind, "declare"); + return grammarErrorOnNode( + modifier, + Diagnostics._0_modifier_cannot_appear_on_class_elements_of_this_kind, + "declare", + ); } else if (node.kind === SyntaxKind.Parameter) { - return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_appear_on_a_parameter, "declare"); + return grammarErrorOnNode( + modifier, + Diagnostics._0_modifier_cannot_appear_on_a_parameter, + "declare", + ); } else if (blockScopeKind === NodeFlags.Using) { - return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_appear_on_a_using_declaration, "declare"); + return grammarErrorOnNode( + modifier, + Diagnostics._0_modifier_cannot_appear_on_a_using_declaration, + "declare", + ); } else if (blockScopeKind === NodeFlags.AwaitUsing) { - return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_appear_on_an_await_using_declaration, "declare"); + return grammarErrorOnNode( + modifier, + Diagnostics._0_modifier_cannot_appear_on_an_await_using_declaration, + "declare", + ); } - else if ((node.parent.flags & NodeFlags.Ambient) && node.parent.kind === SyntaxKind.ModuleBlock) { - return grammarErrorOnNode(modifier, Diagnostics.A_declare_modifier_cannot_be_used_in_an_already_ambient_context); + else if ( + (node.parent.flags & NodeFlags.Ambient) && node.parent.kind === SyntaxKind.ModuleBlock + ) { + return grammarErrorOnNode( + modifier, + Diagnostics.A_declare_modifier_cannot_be_used_in_an_already_ambient_context, + ); } else if (isPrivateIdentifierClassElementDeclaration(node)) { - return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_be_used_with_a_private_identifier, "declare"); + return grammarErrorOnNode( + modifier, + Diagnostics._0_modifier_cannot_be_used_with_a_private_identifier, + "declare", + ); } else if (flags & ModifierFlags.Accessor) { - return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_be_used_with_1_modifier, "declare", "accessor"); + return grammarErrorOnNode( + modifier, + Diagnostics._0_modifier_cannot_be_used_with_1_modifier, + "declare", + "accessor", + ); } flags |= ModifierFlags.Ambient; lastDeclare = modifier; @@ -48182,41 +61269,77 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return grammarErrorOnNode(modifier, Diagnostics._0_modifier_already_seen, "abstract"); } if ( - node.kind !== SyntaxKind.ClassDeclaration && - node.kind !== SyntaxKind.ConstructorType + node.kind !== SyntaxKind.ClassDeclaration + && node.kind !== SyntaxKind.ConstructorType ) { if ( - node.kind !== SyntaxKind.MethodDeclaration && - node.kind !== SyntaxKind.PropertyDeclaration && - node.kind !== SyntaxKind.GetAccessor && - node.kind !== SyntaxKind.SetAccessor + node.kind !== SyntaxKind.MethodDeclaration + && node.kind !== SyntaxKind.PropertyDeclaration + && node.kind !== SyntaxKind.GetAccessor + && node.kind !== SyntaxKind.SetAccessor ) { - return grammarErrorOnNode(modifier, Diagnostics.abstract_modifier_can_only_appear_on_a_class_method_or_property_declaration); + return grammarErrorOnNode( + modifier, + Diagnostics + .abstract_modifier_can_only_appear_on_a_class_method_or_property_declaration, + ); } - if (!(node.parent.kind === SyntaxKind.ClassDeclaration && hasSyntacticModifier(node.parent, ModifierFlags.Abstract))) { + if ( + !(node.parent.kind === SyntaxKind.ClassDeclaration + && hasSyntacticModifier(node.parent, ModifierFlags.Abstract)) + ) { const message = node.kind === SyntaxKind.PropertyDeclaration ? Diagnostics.Abstract_properties_can_only_appear_within_an_abstract_class : Diagnostics.Abstract_methods_can_only_appear_within_an_abstract_class; return grammarErrorOnNode(modifier, message); } if (flags & ModifierFlags.Static) { - return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_be_used_with_1_modifier, "static", "abstract"); + return grammarErrorOnNode( + modifier, + Diagnostics._0_modifier_cannot_be_used_with_1_modifier, + "static", + "abstract", + ); } if (flags & ModifierFlags.Private) { - return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_be_used_with_1_modifier, "private", "abstract"); + return grammarErrorOnNode( + modifier, + Diagnostics._0_modifier_cannot_be_used_with_1_modifier, + "private", + "abstract", + ); } if (flags & ModifierFlags.Async && lastAsync) { - return grammarErrorOnNode(lastAsync, Diagnostics._0_modifier_cannot_be_used_with_1_modifier, "async", "abstract"); + return grammarErrorOnNode( + lastAsync, + Diagnostics._0_modifier_cannot_be_used_with_1_modifier, + "async", + "abstract", + ); } if (flags & ModifierFlags.Override) { - return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, "abstract", "override"); + return grammarErrorOnNode( + modifier, + Diagnostics._0_modifier_must_precede_1_modifier, + "abstract", + "override", + ); } if (flags & ModifierFlags.Accessor) { - return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, "abstract", "accessor"); + return grammarErrorOnNode( + modifier, + Diagnostics._0_modifier_must_precede_1_modifier, + "abstract", + "accessor", + ); } } if (isNamedDeclaration(node) && node.name.kind === SyntaxKind.PrivateIdentifier) { - return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_be_used_with_a_private_identifier, "abstract"); + return grammarErrorOnNode( + modifier, + Diagnostics._0_modifier_cannot_be_used_with_a_private_identifier, + "abstract", + ); } flags |= ModifierFlags.Abstract; @@ -48227,13 +61350,26 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return grammarErrorOnNode(modifier, Diagnostics._0_modifier_already_seen, "async"); } else if (flags & ModifierFlags.Ambient || node.parent.flags & NodeFlags.Ambient) { - return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_be_used_in_an_ambient_context, "async"); + return grammarErrorOnNode( + modifier, + Diagnostics._0_modifier_cannot_be_used_in_an_ambient_context, + "async", + ); } else if (node.kind === SyntaxKind.Parameter) { - return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_appear_on_a_parameter, "async"); + return grammarErrorOnNode( + modifier, + Diagnostics._0_modifier_cannot_appear_on_a_parameter, + "async", + ); } if (flags & ModifierFlags.Abstract) { - return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_be_used_with_1_modifier, "async", "abstract"); + return grammarErrorOnNode( + modifier, + Diagnostics._0_modifier_cannot_be_used_with_1_modifier, + "async", + "abstract", + ); } flags |= ModifierFlags.Async; lastAsync = modifier; @@ -48243,14 +61379,28 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { case SyntaxKind.OutKeyword: const inOutFlag = modifier.kind === SyntaxKind.InKeyword ? ModifierFlags.In : ModifierFlags.Out; const inOutText = modifier.kind === SyntaxKind.InKeyword ? "in" : "out"; - if (node.kind !== SyntaxKind.TypeParameter || !(isInterfaceDeclaration(node.parent) || isClassLike(node.parent) || isTypeAliasDeclaration(node.parent))) { - return grammarErrorOnNode(modifier, Diagnostics._0_modifier_can_only_appear_on_a_type_parameter_of_a_class_interface_or_type_alias, inOutText); + if ( + node.kind !== SyntaxKind.TypeParameter + || !(isInterfaceDeclaration(node.parent) || isClassLike(node.parent) + || isTypeAliasDeclaration(node.parent)) + ) { + return grammarErrorOnNode( + modifier, + Diagnostics + ._0_modifier_can_only_appear_on_a_type_parameter_of_a_class_interface_or_type_alias, + inOutText, + ); } if (flags & inOutFlag) { return grammarErrorOnNode(modifier, Diagnostics._0_modifier_already_seen, inOutText); } if (inOutFlag & ModifierFlags.In && flags & ModifierFlags.Out) { - return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, "in", "out"); + return grammarErrorOnNode( + modifier, + Diagnostics._0_modifier_must_precede_1_modifier, + "in", + "out", + ); } flags |= inOutFlag; break; @@ -48260,23 +61410,51 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (node.kind === SyntaxKind.Constructor) { if (flags & ModifierFlags.Static) { - return grammarErrorOnNode(lastStatic!, Diagnostics._0_modifier_cannot_appear_on_a_constructor_declaration, "static"); + return grammarErrorOnNode( + lastStatic!, + Diagnostics._0_modifier_cannot_appear_on_a_constructor_declaration, + "static", + ); } if (flags & ModifierFlags.Override) { - return grammarErrorOnNode(lastOverride!, Diagnostics._0_modifier_cannot_appear_on_a_constructor_declaration, "override"); // TODO: GH#18217 + return grammarErrorOnNode( + lastOverride!, + Diagnostics._0_modifier_cannot_appear_on_a_constructor_declaration, + "override", + ); // TODO: GH#18217 } if (flags & ModifierFlags.Async) { - return grammarErrorOnNode(lastAsync!, Diagnostics._0_modifier_cannot_appear_on_a_constructor_declaration, "async"); + return grammarErrorOnNode( + lastAsync!, + Diagnostics._0_modifier_cannot_appear_on_a_constructor_declaration, + "async", + ); } return false; } - else if ((node.kind === SyntaxKind.ImportDeclaration || node.kind === SyntaxKind.ImportEqualsDeclaration) && flags & ModifierFlags.Ambient) { - return grammarErrorOnNode(lastDeclare!, Diagnostics.A_0_modifier_cannot_be_used_with_an_import_declaration, "declare"); + else if ( + (node.kind === SyntaxKind.ImportDeclaration || node.kind === SyntaxKind.ImportEqualsDeclaration) + && flags & ModifierFlags.Ambient + ) { + return grammarErrorOnNode( + lastDeclare!, + Diagnostics.A_0_modifier_cannot_be_used_with_an_import_declaration, + "declare", + ); } - else if (node.kind === SyntaxKind.Parameter && (flags & ModifierFlags.ParameterPropertyModifier) && isBindingPattern(node.name)) { - return grammarErrorOnNode(node, Diagnostics.A_parameter_property_may_not_be_declared_using_a_binding_pattern); + else if ( + node.kind === SyntaxKind.Parameter && (flags & ModifierFlags.ParameterPropertyModifier) + && isBindingPattern(node.name) + ) { + return grammarErrorOnNode( + node, + Diagnostics.A_parameter_property_may_not_be_declared_using_a_binding_pattern, + ); } - else if (node.kind === SyntaxKind.Parameter && (flags & ModifierFlags.ParameterPropertyModifier) && node.dotDotDotToken) { + else if ( + node.kind === SyntaxKind.Parameter && (flags & ModifierFlags.ParameterPropertyModifier) + && node.dotDotDotToken + ) { return grammarErrorOnNode(node, Diagnostics.A_parameter_property_cannot_be_declared_using_a_rest_parameter); } if (flags & ModifierFlags.Async) { @@ -48342,9 +61520,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { case SyntaxKind.TypeAliasDeclaration: return find(node.modifiers, isModifier); case SyntaxKind.VariableStatement: - return node.declarationList.flags & NodeFlags.Using ? - findFirstModifierExcept(node, SyntaxKind.AwaitKeyword) : - find(node.modifiers, isModifier); + return node.declarationList.flags & NodeFlags.Using + ? findFirstModifierExcept(node, SyntaxKind.AwaitKeyword) + : find(node.modifiers, isModifier); case SyntaxKind.EnumDeclaration: return findFirstModifierExcept(node, SyntaxKind.ConstKeyword); default: @@ -48353,12 +61531,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } - function reportObviousDecoratorErrors(node: HasModifiers | HasDecorators | HasIllegalModifiers | HasIllegalDecorators) { + function reportObviousDecoratorErrors( + node: HasModifiers | HasDecorators | HasIllegalModifiers | HasIllegalDecorators, + ) { const decorator = findFirstIllegalDecorator(node); return decorator && grammarErrorOnFirstToken(decorator, Diagnostics.Decorators_are_not_valid_here); } - function findFirstIllegalDecorator(node: HasModifiers | HasDecorators | HasIllegalModifiers | HasIllegalDecorators): Decorator | undefined { + function findFirstIllegalDecorator( + node: HasModifiers | HasDecorators | HasIllegalModifiers | HasIllegalDecorators, + ): Decorator | undefined { return canHaveIllegalDecorators(node) ? find(node.modifiers, isDecorator) : undefined; } @@ -48374,14 +61556,20 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return grammarErrorOnNode(asyncModifier, Diagnostics._0_modifier_cannot_be_used_here, "async"); } - function checkGrammarForDisallowedTrailingComma(list: NodeArray | undefined, diag = Diagnostics.Trailing_comma_not_allowed): boolean { + function checkGrammarForDisallowedTrailingComma( + list: NodeArray | undefined, + diag = Diagnostics.Trailing_comma_not_allowed, + ): boolean { if (list && list.hasTrailingComma) { return grammarErrorAtPos(list[0], list.end - ",".length, ",".length, diag); } return false; } - function checkGrammarTypeParameterList(typeParameters: NodeArray | undefined, file: SourceFile): boolean { + function checkGrammarTypeParameterList( + typeParameters: NodeArray | undefined, + file: SourceFile, + ): boolean { if (typeParameters && typeParameters.length === 0) { const start = typeParameters.pos - "<".length; const end = skipTrivia(file.text, typeParameters.end) + ">".length; @@ -48398,10 +61586,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const parameter = parameters[i]; if (parameter.dotDotDotToken) { if (i !== (parameterCount - 1)) { - return grammarErrorOnNode(parameter.dotDotDotToken, Diagnostics.A_rest_parameter_must_be_last_in_a_parameter_list); + return grammarErrorOnNode( + parameter.dotDotDotToken, + Diagnostics.A_rest_parameter_must_be_last_in_a_parameter_list, + ); } if (!(parameter.flags & NodeFlags.Ambient)) { // Allow `...foo,` in ambient declarations; see GH#23070 - checkGrammarForDisallowedTrailingComma(parameters, Diagnostics.A_rest_parameter_or_binding_pattern_may_not_have_a_trailing_comma); + checkGrammarForDisallowedTrailingComma( + parameters, + Diagnostics.A_rest_parameter_or_binding_pattern_may_not_have_a_trailing_comma, + ); } if (parameter.questionToken) { @@ -48415,17 +61609,26 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { else if (isOptionalParameter(parameter)) { seenOptionalParameter = true; if (parameter.questionToken && parameter.initializer) { - return grammarErrorOnNode(parameter.name, Diagnostics.Parameter_cannot_have_question_mark_and_initializer); + return grammarErrorOnNode( + parameter.name, + Diagnostics.Parameter_cannot_have_question_mark_and_initializer, + ); } } else if (seenOptionalParameter && !parameter.initializer) { - return grammarErrorOnNode(parameter.name, Diagnostics.A_required_parameter_cannot_follow_an_optional_parameter); + return grammarErrorOnNode( + parameter.name, + Diagnostics.A_required_parameter_cannot_follow_an_optional_parameter, + ); } } } function getNonSimpleParameters(parameters: readonly ParameterDeclaration[]): readonly ParameterDeclaration[] { - return filter(parameters, parameter => !!parameter.initializer || isBindingPattern(parameter.name) || isRestParameter(parameter)); + return filter( + parameters, + parameter => !!parameter.initializer || isBindingPattern(parameter.name) || isRestParameter(parameter), + ); } function checkGrammarForUseStrictSimpleParameterList(node: FunctionLikeDeclaration): boolean { @@ -48442,9 +61645,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { }); const diagnostics = nonSimpleParameters.map((parameter, index) => ( - index === 0 ? createDiagnosticForNode(parameter, Diagnostics.Non_simple_parameter_declared_here) : createDiagnosticForNode(parameter, Diagnostics.and_here) + index === 0 ? createDiagnosticForNode(parameter, Diagnostics.Non_simple_parameter_declared_here) + : createDiagnosticForNode(parameter, Diagnostics.and_here) )) as [DiagnosticWithLocation, ...DiagnosticWithLocation[]]; - addRelatedInfo(error(useStrictDirective, Diagnostics.use_strict_directive_cannot_be_used_with_non_simple_parameter_list), ...diagnostics); + addRelatedInfo( + error( + useStrictDirective, + Diagnostics.use_strict_directive_cannot_be_used_with_non_simple_parameter_list, + ), + ...diagnostics, + ); return true; } } @@ -48455,17 +61665,17 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function checkGrammarFunctionLikeDeclaration(node: FunctionLikeDeclaration | MethodSignature): boolean { // Prevent cascading error by short-circuit const file = getSourceFileOfNode(node); - return checkGrammarModifiers(node) || - checkGrammarTypeParameterList(node.typeParameters, file) || - checkGrammarParameterList(node.parameters) || - checkGrammarArrowFunction(node, file) || - (isFunctionLikeDeclaration(node) && checkGrammarForUseStrictSimpleParameterList(node)); + return checkGrammarModifiers(node) + || checkGrammarTypeParameterList(node.typeParameters, file) + || checkGrammarParameterList(node.parameters) + || checkGrammarArrowFunction(node, file) + || (isFunctionLikeDeclaration(node) && checkGrammarForUseStrictSimpleParameterList(node)); } function checkGrammarClassLikeDeclaration(node: ClassLikeDeclaration): boolean { const file = getSourceFileOfNode(node); - return checkGrammarClassDeclarationHeritageClauses(node) || - checkGrammarTypeParameterList(node.typeParameters, file); + return checkGrammarClassDeclarationHeritageClauses(node) + || checkGrammarTypeParameterList(node.typeParameters, file); } function checkGrammarArrowFunction(node: Node, file: SourceFile): boolean { @@ -48473,50 +61683,87 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return false; } - if (node.typeParameters && !(length(node.typeParameters) > 1 || node.typeParameters.hasTrailingComma || node.typeParameters[0].constraint)) { + if ( + node.typeParameters + && !(length(node.typeParameters) > 1 || node.typeParameters.hasTrailingComma + || node.typeParameters[0].constraint) + ) { if (file && fileExtensionIsOneOf(file.fileName, [Extension.Mts, Extension.Cts])) { - grammarErrorOnNode(node.typeParameters[0], Diagnostics.This_syntax_is_reserved_in_files_with_the_mts_or_cts_extension_Add_a_trailing_comma_or_explicit_constraint); + grammarErrorOnNode( + node.typeParameters[0], + Diagnostics + .This_syntax_is_reserved_in_files_with_the_mts_or_cts_extension_Add_a_trailing_comma_or_explicit_constraint, + ); } } const { equalsGreaterThanToken } = node; const startLine = getLineAndCharacterOfPosition(file, equalsGreaterThanToken.pos).line; const endLine = getLineAndCharacterOfPosition(file, equalsGreaterThanToken.end).line; - return startLine !== endLine && grammarErrorOnNode(equalsGreaterThanToken, Diagnostics.Line_terminator_not_permitted_before_arrow); + return startLine !== endLine + && grammarErrorOnNode(equalsGreaterThanToken, Diagnostics.Line_terminator_not_permitted_before_arrow); } function checkGrammarIndexSignatureParameters(node: SignatureDeclaration): boolean { const parameter = node.parameters[0]; if (node.parameters.length !== 1) { if (parameter) { - return grammarErrorOnNode(parameter.name, Diagnostics.An_index_signature_must_have_exactly_one_parameter); + return grammarErrorOnNode( + parameter.name, + Diagnostics.An_index_signature_must_have_exactly_one_parameter, + ); } else { return grammarErrorOnNode(node, Diagnostics.An_index_signature_must_have_exactly_one_parameter); } } - checkGrammarForDisallowedTrailingComma(node.parameters, Diagnostics.An_index_signature_cannot_have_a_trailing_comma); + checkGrammarForDisallowedTrailingComma( + node.parameters, + Diagnostics.An_index_signature_cannot_have_a_trailing_comma, + ); if (parameter.dotDotDotToken) { - return grammarErrorOnNode(parameter.dotDotDotToken, Diagnostics.An_index_signature_cannot_have_a_rest_parameter); + return grammarErrorOnNode( + parameter.dotDotDotToken, + Diagnostics.An_index_signature_cannot_have_a_rest_parameter, + ); } if (hasEffectiveModifiers(parameter)) { - return grammarErrorOnNode(parameter.name, Diagnostics.An_index_signature_parameter_cannot_have_an_accessibility_modifier); + return grammarErrorOnNode( + parameter.name, + Diagnostics.An_index_signature_parameter_cannot_have_an_accessibility_modifier, + ); } if (parameter.questionToken) { - return grammarErrorOnNode(parameter.questionToken, Diagnostics.An_index_signature_parameter_cannot_have_a_question_mark); + return grammarErrorOnNode( + parameter.questionToken, + Diagnostics.An_index_signature_parameter_cannot_have_a_question_mark, + ); } if (parameter.initializer) { - return grammarErrorOnNode(parameter.name, Diagnostics.An_index_signature_parameter_cannot_have_an_initializer); + return grammarErrorOnNode( + parameter.name, + Diagnostics.An_index_signature_parameter_cannot_have_an_initializer, + ); } if (!parameter.type) { - return grammarErrorOnNode(parameter.name, Diagnostics.An_index_signature_parameter_must_have_a_type_annotation); + return grammarErrorOnNode( + parameter.name, + Diagnostics.An_index_signature_parameter_must_have_a_type_annotation, + ); } const type = getTypeFromTypeNode(parameter.type); if (someType(type, t => !!(t.flags & TypeFlags.StringOrNumberLiteralOrUnique)) || isGenericType(type)) { - return grammarErrorOnNode(parameter.name, Diagnostics.An_index_signature_parameter_type_cannot_be_a_literal_type_or_generic_type_Consider_using_a_mapped_object_type_instead); + return grammarErrorOnNode( + parameter.name, + Diagnostics + .An_index_signature_parameter_type_cannot_be_a_literal_type_or_generic_type_Consider_using_a_mapped_object_type_instead, + ); } if (!everyType(type, isValidIndexKeyType)) { - return grammarErrorOnNode(parameter.name, Diagnostics.An_index_signature_parameter_type_must_be_string_number_symbol_or_a_template_literal_type); + return grammarErrorOnNode( + parameter.name, + Diagnostics.An_index_signature_parameter_type_must_be_string_number_symbol_or_a_template_literal_type, + ); } if (!node.type) { return grammarErrorOnNode(node, Diagnostics.An_index_signature_must_have_a_type_annotation); @@ -48529,7 +61776,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return checkGrammarModifiers(node) || checkGrammarIndexSignatureParameters(node); } - function checkGrammarForAtLeastOneTypeArgument(node: Node, typeArguments: NodeArray | undefined): boolean { + function checkGrammarForAtLeastOneTypeArgument( + node: Node, + typeArguments: NodeArray | undefined, + ): boolean { if (typeArguments && typeArguments.length === 0) { const sourceFile = getSourceFileOfNode(node); const start = typeArguments.pos - "<".length; @@ -48540,13 +61790,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function checkGrammarTypeArguments(node: Node, typeArguments: NodeArray | undefined): boolean { - return checkGrammarForDisallowedTrailingComma(typeArguments) || - checkGrammarForAtLeastOneTypeArgument(node, typeArguments); + return checkGrammarForDisallowedTrailingComma(typeArguments) + || checkGrammarForAtLeastOneTypeArgument(node, typeArguments); } function checkGrammarTaggedTemplateChain(node: TaggedTemplateExpression): boolean { if (node.questionDotToken || node.flags & NodeFlags.OptionalChain) { - return grammarErrorOnNode(node.template, Diagnostics.Tagged_template_expressions_are_not_permitted_in_an_optional_chain); + return grammarErrorOnNode( + node.template, + Diagnostics.Tagged_template_expressions_are_not_permitted_in_an_optional_chain, + ); } return false; } @@ -48565,7 +61818,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function checkGrammarExpressionWithTypeArguments(node: ExpressionWithTypeArguments | TypeQueryNode) { if (isExpressionWithTypeArguments(node) && isImportKeyword(node.expression) && node.typeArguments) { - return grammarErrorOnNode(node, Diagnostics.This_use_of_import_is_invalid_import_calls_can_be_written_but_they_must_have_parentheses_and_cannot_have_type_arguments); + return grammarErrorOnNode( + node, + Diagnostics + .This_use_of_import_is_invalid_import_calls_can_be_written_but_they_must_have_parentheses_and_cannot_have_type_arguments, + ); } return checkGrammarTypeArguments(node, node.typeArguments); } @@ -48582,11 +61839,17 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } if (seenImplementsClause) { - return grammarErrorOnFirstToken(heritageClause, Diagnostics.extends_clause_must_precede_implements_clause); + return grammarErrorOnFirstToken( + heritageClause, + Diagnostics.extends_clause_must_precede_implements_clause, + ); } if (heritageClause.types.length > 1) { - return grammarErrorOnFirstToken(heritageClause.types[1], Diagnostics.Classes_can_only_extend_a_single_class); + return grammarErrorOnFirstToken( + heritageClause.types[1], + Diagnostics.Classes_can_only_extend_a_single_class, + ); } seenExtendsClause = true; @@ -48620,7 +61883,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } else { Debug.assert(heritageClause.token === SyntaxKind.ImplementsKeyword); - return grammarErrorOnFirstToken(heritageClause, Diagnostics.Interface_declaration_cannot_have_implements_clause); + return grammarErrorOnFirstToken( + heritageClause, + Diagnostics.Interface_declaration_cannot_have_implements_clause, + ); } // Grammar checking heritageClause inside class declaration @@ -48637,8 +61903,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } const computedPropertyName = node as ComputedPropertyName; - if (computedPropertyName.expression.kind === SyntaxKind.BinaryExpression && (computedPropertyName.expression as BinaryExpression).operatorToken.kind === SyntaxKind.CommaToken) { - return grammarErrorOnNode(computedPropertyName.expression, Diagnostics.A_comma_expression_is_not_allowed_in_a_computed_property_name); + if ( + computedPropertyName.expression.kind === SyntaxKind.BinaryExpression + && (computedPropertyName.expression as BinaryExpression).operatorToken.kind === SyntaxKind.CommaToken + ) { + return grammarErrorOnNode( + computedPropertyName.expression, + Diagnostics.A_comma_expression_is_not_allowed_in_a_computed_property_name, + ); } return false; } @@ -48646,24 +61918,36 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function checkGrammarForGenerator(node: FunctionLikeDeclaration) { if (node.asteriskToken) { Debug.assert( - node.kind === SyntaxKind.FunctionDeclaration || - node.kind === SyntaxKind.FunctionExpression || - node.kind === SyntaxKind.MethodDeclaration, + node.kind === SyntaxKind.FunctionDeclaration + || node.kind === SyntaxKind.FunctionExpression + || node.kind === SyntaxKind.MethodDeclaration, ); if (node.flags & NodeFlags.Ambient) { - return grammarErrorOnNode(node.asteriskToken, Diagnostics.Generators_are_not_allowed_in_an_ambient_context); + return grammarErrorOnNode( + node.asteriskToken, + Diagnostics.Generators_are_not_allowed_in_an_ambient_context, + ); } if (!node.body) { - return grammarErrorOnNode(node.asteriskToken, Diagnostics.An_overload_signature_cannot_be_declared_as_a_generator); + return grammarErrorOnNode( + node.asteriskToken, + Diagnostics.An_overload_signature_cannot_be_declared_as_a_generator, + ); } } } - function checkGrammarForInvalidQuestionMark(questionToken: QuestionToken | undefined, message: DiagnosticMessage): boolean { + function checkGrammarForInvalidQuestionMark( + questionToken: QuestionToken | undefined, + message: DiagnosticMessage, + ): boolean { return !!questionToken && grammarErrorOnNode(questionToken, message); } - function checkGrammarForInvalidExclamationToken(exclamationToken: ExclamationToken | undefined, message: DiagnosticMessage): boolean { + function checkGrammarForInvalidExclamationToken( + exclamationToken: ExclamationToken | undefined, + message: DiagnosticMessage, + ): boolean { return !!exclamationToken && grammarErrorOnNode(exclamationToken, message); } @@ -48676,7 +61960,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // a rest property cannot be destructured any further const expression = skipParentheses(prop.expression); if (isArrayLiteralExpression(expression) || isObjectLiteralExpression(expression)) { - return grammarErrorOnNode(prop.expression, Diagnostics.A_rest_element_cannot_contain_a_binding_pattern); + return grammarErrorOnNode( + prop.expression, + Diagnostics.A_rest_element_cannot_contain_a_binding_pattern, + ); } } continue; @@ -48687,10 +61974,17 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { checkGrammarComputedPropertyName(name); } - if (prop.kind === SyntaxKind.ShorthandPropertyAssignment && !inDestructuring && prop.objectAssignmentInitializer) { + if ( + prop.kind === SyntaxKind.ShorthandPropertyAssignment && !inDestructuring + && prop.objectAssignmentInitializer + ) { // having objectAssignmentInitializer is only valid in ObjectAssignmentPattern // outside of destructuring it is a syntax error - grammarErrorOnNode(prop.equalsToken!, Diagnostics.Did_you_mean_to_use_a_Colon_An_can_only_follow_a_property_name_when_the_containing_object_literal_is_part_of_a_destructuring_pattern); + grammarErrorOnNode( + prop.equalsToken!, + Diagnostics + .Did_you_mean_to_use_a_Colon_An_can_only_follow_a_property_name_when_the_containing_object_literal_is_part_of_a_destructuring_pattern, + ); } if (name.kind === SyntaxKind.PrivateIdentifier) { @@ -48700,7 +61994,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // Modifiers are never allowed on properties except for 'async' on a method declaration if (canHaveModifiers(prop) && prop.modifiers) { for (const mod of prop.modifiers) { - if (isModifier(mod) && (mod.kind !== SyntaxKind.AsyncKeyword || prop.kind !== SyntaxKind.MethodDeclaration)) { + if ( + isModifier(mod) + && (mod.kind !== SyntaxKind.AsyncKeyword || prop.kind !== SyntaxKind.MethodDeclaration) + ) { grammarErrorOnNode(mod, Diagnostics._0_modifier_cannot_be_used_here, getTextOfNode(mod)); } } @@ -48726,8 +62023,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { case SyntaxKind.ShorthandPropertyAssignment: case SyntaxKind.PropertyAssignment: // Grammar checking for computedPropertyName and shorthandPropertyAssignment - checkGrammarForInvalidExclamationToken(prop.exclamationToken, Diagnostics.A_definite_assignment_assertion_is_not_permitted_in_this_context); - checkGrammarForInvalidQuestionMark(prop.questionToken, Diagnostics.An_object_member_cannot_be_declared_optional); + checkGrammarForInvalidExclamationToken( + prop.exclamationToken, + Diagnostics.A_definite_assignment_assertion_is_not_permitted_in_this_context, + ); + checkGrammarForInvalidQuestionMark( + prop.questionToken, + Diagnostics.An_object_member_cannot_be_declared_optional, + ); if (name.kind === SyntaxKind.NumericLiteral) { checkGrammarNumericLiteral(name); } @@ -48760,19 +62063,36 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if ((currentKind & DeclarationMeaning.Method) && (existingKind & DeclarationMeaning.Method)) { grammarErrorOnNode(name, Diagnostics.Duplicate_identifier_0, getTextOfNode(name)); } - else if ((currentKind & DeclarationMeaning.PropertyAssignment) && (existingKind & DeclarationMeaning.PropertyAssignment)) { - grammarErrorOnNode(name, Diagnostics.An_object_literal_cannot_have_multiple_properties_with_the_same_name, getTextOfNode(name)); + else if ( + (currentKind & DeclarationMeaning.PropertyAssignment) + && (existingKind & DeclarationMeaning.PropertyAssignment) + ) { + grammarErrorOnNode( + name, + Diagnostics.An_object_literal_cannot_have_multiple_properties_with_the_same_name, + getTextOfNode(name), + ); } - else if ((currentKind & DeclarationMeaning.GetOrSetAccessor) && (existingKind & DeclarationMeaning.GetOrSetAccessor)) { + else if ( + (currentKind & DeclarationMeaning.GetOrSetAccessor) + && (existingKind & DeclarationMeaning.GetOrSetAccessor) + ) { if (existingKind !== DeclarationMeaning.GetOrSetAccessor && currentKind !== existingKind) { seen.set(effectiveName, currentKind | existingKind); } else { - return grammarErrorOnNode(name, Diagnostics.An_object_literal_cannot_have_multiple_get_Slashset_accessors_with_the_same_name); + return grammarErrorOnNode( + name, + Diagnostics + .An_object_literal_cannot_have_multiple_get_Slashset_accessors_with_the_same_name, + ); } } else { - return grammarErrorOnNode(name, Diagnostics.An_object_literal_cannot_have_property_and_accessor_with_the_same_name); + return grammarErrorOnNode( + name, + Diagnostics.An_object_literal_cannot_have_property_and_accessor_with_the_same_name, + ); } } } @@ -48795,27 +62115,42 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { seen.set(escapedText, true); } else { - return grammarErrorOnNode(name, Diagnostics.JSX_elements_cannot_have_multiple_attributes_with_the_same_name); + return grammarErrorOnNode( + name, + Diagnostics.JSX_elements_cannot_have_multiple_attributes_with_the_same_name, + ); } if (initializer && initializer.kind === SyntaxKind.JsxExpression && !initializer.expression) { - return grammarErrorOnNode(initializer, Diagnostics.JSX_attributes_must_only_be_assigned_a_non_empty_expression); + return grammarErrorOnNode( + initializer, + Diagnostics.JSX_attributes_must_only_be_assigned_a_non_empty_expression, + ); } } } function checkGrammarJsxName(node: JsxTagNameExpression) { if (isPropertyAccessExpression(node) && isJsxNamespacedName(node.expression)) { - return grammarErrorOnNode(node.expression, Diagnostics.JSX_property_access_expressions_cannot_include_JSX_namespace_names); + return grammarErrorOnNode( + node.expression, + Diagnostics.JSX_property_access_expressions_cannot_include_JSX_namespace_names, + ); } - if (isJsxNamespacedName(node) && getJSXTransformEnabled(compilerOptions) && !isIntrinsicJsxName(node.namespace.escapedText)) { + if ( + isJsxNamespacedName(node) && getJSXTransformEnabled(compilerOptions) + && !isIntrinsicJsxName(node.namespace.escapedText) + ) { return grammarErrorOnNode(node, Diagnostics.React_components_cannot_include_JSX_namespace_names); } } function checkGrammarJsxExpression(node: JsxExpression) { if (node.expression && isCommaSequence(node.expression)) { - return grammarErrorOnNode(node.expression, Diagnostics.JSX_expressions_may_not_use_the_comma_operator_Did_you_mean_to_write_an_array); + return grammarErrorOnNode( + node.expression, + Diagnostics.JSX_expressions_may_not_use_the_comma_operator_Did_you_mean_to_write_an_array, + ); } } @@ -48830,14 +62165,24 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (isInTopLevelContext(forInOrOfStatement)) { if (!hasParseDiagnostics(sourceFile)) { if (!isEffectiveExternalModule(sourceFile, compilerOptions)) { - diagnostics.add(createDiagnosticForNode(forInOrOfStatement.awaitModifier, Diagnostics.for_await_loops_are_only_allowed_at_the_top_level_of_a_file_when_that_file_is_a_module_but_this_file_has_no_imports_or_exports_Consider_adding_an_empty_export_to_make_this_file_a_module)); + diagnostics.add( + createDiagnosticForNode( + forInOrOfStatement.awaitModifier, + Diagnostics + .for_await_loops_are_only_allowed_at_the_top_level_of_a_file_when_that_file_is_a_module_but_this_file_has_no_imports_or_exports_Consider_adding_an_empty_export_to_make_this_file_a_module, + ), + ); } switch (moduleKind) { case ModuleKind.Node16: case ModuleKind.NodeNext: if (sourceFile.impliedNodeFormat === ModuleKind.CommonJS) { diagnostics.add( - createDiagnosticForNode(forInOrOfStatement.awaitModifier, Diagnostics.The_current_file_is_a_CommonJS_module_and_cannot_use_await_at_the_top_level), + createDiagnosticForNode( + forInOrOfStatement.awaitModifier, + Diagnostics + .The_current_file_is_a_CommonJS_module_and_cannot_use_await_at_the_top_level, + ), ); break; } @@ -48851,7 +62196,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // fallthrough default: diagnostics.add( - createDiagnosticForNode(forInOrOfStatement.awaitModifier, Diagnostics.Top_level_for_await_loops_are_only_allowed_when_the_module_option_is_set_to_es2022_esnext_system_node16_or_nodenext_and_the_target_option_is_set_to_es2017_or_higher), + createDiagnosticForNode( + forInOrOfStatement.awaitModifier, + Diagnostics + .Top_level_for_await_loops_are_only_allowed_when_the_module_option_is_set_to_es2022_esnext_system_node16_or_nodenext_and_the_target_option_is_set_to_es2017_or_higher, + ), ); break; } @@ -48860,11 +62209,21 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { else { // use of 'for-await-of' in non-async function if (!hasParseDiagnostics(sourceFile)) { - const diagnostic = createDiagnosticForNode(forInOrOfStatement.awaitModifier, Diagnostics.for_await_loops_are_only_allowed_within_async_functions_and_at_the_top_levels_of_modules); + const diagnostic = createDiagnosticForNode( + forInOrOfStatement.awaitModifier, + Diagnostics + .for_await_loops_are_only_allowed_within_async_functions_and_at_the_top_levels_of_modules, + ); const func = getContainingFunction(forInOrOfStatement); if (func && func.kind !== SyntaxKind.Constructor) { - Debug.assert((getFunctionFlags(func) & FunctionFlags.Async) === 0, "Enclosing function should never be an async function."); - const relatedInfo = createDiagnosticForNode(func, Diagnostics.Did_you_mean_to_mark_this_function_as_async); + Debug.assert( + (getFunctionFlags(func) & FunctionFlags.Async) === 0, + "Enclosing function should never be an async function.", + ); + const relatedInfo = createDiagnosticForNode( + func, + Diagnostics.Did_you_mean_to_mark_this_function_as_async, + ); addRelatedInfo(diagnostic, relatedInfo); } diagnostics.add(diagnostic); @@ -48876,10 +62235,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } if ( - isForOfStatement(forInOrOfStatement) && !(forInOrOfStatement.flags & NodeFlags.AwaitContext) && - isIdentifier(forInOrOfStatement.initializer) && forInOrOfStatement.initializer.escapedText === "async" + isForOfStatement(forInOrOfStatement) && !(forInOrOfStatement.flags & NodeFlags.AwaitContext) + && isIdentifier(forInOrOfStatement.initializer) && forInOrOfStatement.initializer.escapedText === "async" ) { - grammarErrorOnNode(forInOrOfStatement.initializer, Diagnostics.The_left_hand_side_of_a_for_of_statement_may_not_be_async); + grammarErrorOnNode( + forInOrOfStatement.initializer, + Diagnostics.The_left_hand_side_of_a_for_of_statement_may_not_be_async, + ); return false; } @@ -48926,12 +62288,21 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function checkGrammarAccessor(accessor: AccessorDeclaration): boolean { - if (!(accessor.flags & NodeFlags.Ambient) && (accessor.parent.kind !== SyntaxKind.TypeLiteral) && (accessor.parent.kind !== SyntaxKind.InterfaceDeclaration)) { + if ( + !(accessor.flags & NodeFlags.Ambient) && (accessor.parent.kind !== SyntaxKind.TypeLiteral) + && (accessor.parent.kind !== SyntaxKind.InterfaceDeclaration) + ) { if (languageVersion < ScriptTarget.ES5) { - return grammarErrorOnNode(accessor.name, Diagnostics.Accessors_are_only_available_when_targeting_ECMAScript_5_and_higher); + return grammarErrorOnNode( + accessor.name, + Diagnostics.Accessors_are_only_available_when_targeting_ECMAScript_5_and_higher, + ); } if (languageVersion < ScriptTarget.ES2015 && isPrivateIdentifier(accessor.name)) { - return grammarErrorOnNode(accessor.name, Diagnostics.Private_identifiers_are_only_available_when_targeting_ECMAScript_2015_and_higher); + return grammarErrorOnNode( + accessor.name, + Diagnostics.Private_identifiers_are_only_available_when_targeting_ECMAScript_2015_and_higher, + ); } if (accessor.body === undefined && !hasSyntacticModifier(accessor, ModifierFlags.Abstract)) { return grammarErrorAtPos(accessor, accessor.end - 1, ";".length, Diagnostics._0_expected, "{"); @@ -48941,8 +62312,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (hasSyntacticModifier(accessor, ModifierFlags.Abstract)) { return grammarErrorOnNode(accessor, Diagnostics.An_abstract_accessor_cannot_have_an_implementation); } - if (accessor.parent.kind === SyntaxKind.TypeLiteral || accessor.parent.kind === SyntaxKind.InterfaceDeclaration) { - return grammarErrorOnNode(accessor.body, Diagnostics.An_implementation_cannot_be_declared_in_ambient_contexts); + if ( + accessor.parent.kind === SyntaxKind.TypeLiteral + || accessor.parent.kind === SyntaxKind.InterfaceDeclaration + ) { + return grammarErrorOnNode( + accessor.body, + Diagnostics.An_implementation_cannot_be_declared_in_ambient_contexts, + ); } } if (accessor.typeParameters) { @@ -48951,24 +62328,39 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (!doesAccessorHaveCorrectParameterCount(accessor)) { return grammarErrorOnNode( accessor.name, - accessor.kind === SyntaxKind.GetAccessor ? - Diagnostics.A_get_accessor_cannot_have_parameters : - Diagnostics.A_set_accessor_must_have_exactly_one_parameter, + accessor.kind === SyntaxKind.GetAccessor + ? Diagnostics.A_get_accessor_cannot_have_parameters + : Diagnostics.A_set_accessor_must_have_exactly_one_parameter, ); } if (accessor.kind === SyntaxKind.SetAccessor) { if (accessor.type) { - return grammarErrorOnNode(accessor.name, Diagnostics.A_set_accessor_cannot_have_a_return_type_annotation); + return grammarErrorOnNode( + accessor.name, + Diagnostics.A_set_accessor_cannot_have_a_return_type_annotation, + ); } - const parameter = Debug.checkDefined(getSetAccessorValueParameter(accessor), "Return value does not match parameter count assertion."); + const parameter = Debug.checkDefined( + getSetAccessorValueParameter(accessor), + "Return value does not match parameter count assertion.", + ); if (parameter.dotDotDotToken) { - return grammarErrorOnNode(parameter.dotDotDotToken, Diagnostics.A_set_accessor_cannot_have_rest_parameter); + return grammarErrorOnNode( + parameter.dotDotDotToken, + Diagnostics.A_set_accessor_cannot_have_rest_parameter, + ); } if (parameter.questionToken) { - return grammarErrorOnNode(parameter.questionToken, Diagnostics.A_set_accessor_cannot_have_an_optional_parameter); + return grammarErrorOnNode( + parameter.questionToken, + Diagnostics.A_set_accessor_cannot_have_an_optional_parameter, + ); } if (parameter.initializer) { - return grammarErrorOnNode(accessor.name, Diagnostics.A_set_accessor_parameter_cannot_have_an_initializer); + return grammarErrorOnNode( + accessor.name, + Diagnostics.A_set_accessor_parameter_cannot_have_an_initializer, + ); } } return false; @@ -48979,7 +62371,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { * A set accessor has one parameter or a `this` parameter and one more parameter. */ function doesAccessorHaveCorrectParameterCount(accessor: AccessorDeclaration) { - return getAccessorThisParameter(accessor) || accessor.parameters.length === (accessor.kind === SyntaxKind.GetAccessor ? 0 : 1); + return getAccessorThisParameter(accessor) + || accessor.parameters.length === (accessor.kind === SyntaxKind.GetAccessor ? 0 : 1); } function getAccessorThisParameter(accessor: AccessorDeclaration): ParameterDeclaration | undefined { @@ -49004,28 +62397,46 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { case SyntaxKind.VariableDeclaration: const decl = parent as VariableDeclaration; if (decl.name.kind !== SyntaxKind.Identifier) { - return grammarErrorOnNode(node, Diagnostics.unique_symbol_types_may_not_be_used_on_a_variable_declaration_with_a_binding_name); + return grammarErrorOnNode( + node, + Diagnostics + .unique_symbol_types_may_not_be_used_on_a_variable_declaration_with_a_binding_name, + ); } if (!isVariableDeclarationInVariableStatement(decl)) { - return grammarErrorOnNode(node, Diagnostics.unique_symbol_types_are_only_allowed_on_variables_in_a_variable_statement); + return grammarErrorOnNode( + node, + Diagnostics.unique_symbol_types_are_only_allowed_on_variables_in_a_variable_statement, + ); } if (!(decl.parent.flags & NodeFlags.Const)) { - return grammarErrorOnNode((parent as VariableDeclaration).name, Diagnostics.A_variable_whose_type_is_a_unique_symbol_type_must_be_const); + return grammarErrorOnNode( + (parent as VariableDeclaration).name, + Diagnostics.A_variable_whose_type_is_a_unique_symbol_type_must_be_const, + ); } break; case SyntaxKind.PropertyDeclaration: if ( - !isStatic(parent) || - !hasEffectiveReadonlyModifier(parent) + !isStatic(parent) + || !hasEffectiveReadonlyModifier(parent) ) { - return grammarErrorOnNode((parent as PropertyDeclaration).name, Diagnostics.A_property_of_a_class_whose_type_is_a_unique_symbol_type_must_be_both_static_and_readonly); + return grammarErrorOnNode( + (parent as PropertyDeclaration).name, + Diagnostics + .A_property_of_a_class_whose_type_is_a_unique_symbol_type_must_be_both_static_and_readonly, + ); } break; case SyntaxKind.PropertySignature: if (!hasSyntacticModifier(parent, ModifierFlags.Readonly)) { - return grammarErrorOnNode((parent as PropertySignature).name, Diagnostics.A_property_of_an_interface_or_type_literal_whose_type_is_a_unique_symbol_type_must_be_readonly); + return grammarErrorOnNode( + (parent as PropertySignature).name, + Diagnostics + .A_property_of_an_interface_or_type_literal_whose_type_is_a_unique_symbol_type_must_be_readonly, + ); } break; @@ -49035,7 +62446,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } else if (node.operator === SyntaxKind.ReadonlyKeyword) { if (node.type.kind !== SyntaxKind.ArrayType && node.type.kind !== SyntaxKind.TupleType) { - return grammarErrorOnFirstToken(node, Diagnostics.readonly_type_modifier_is_only_permitted_on_array_and_tuple_literal_types, tokenToString(SyntaxKind.SymbolKeyword)); + return grammarErrorOnFirstToken( + node, + Diagnostics.readonly_type_modifier_is_only_permitted_on_array_and_tuple_literal_types, + tokenToString(SyntaxKind.SymbolKeyword), + ); } } } @@ -49054,13 +62469,26 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (node.kind === SyntaxKind.MethodDeclaration) { if (node.parent.kind === SyntaxKind.ObjectLiteralExpression) { // We only disallow modifier on a method declaration if it is a property of object-literal-expression - if (node.modifiers && !(node.modifiers.length === 1 && first(node.modifiers).kind === SyntaxKind.AsyncKeyword)) { + if ( + node.modifiers + && !(node.modifiers.length === 1 && first(node.modifiers).kind === SyntaxKind.AsyncKeyword) + ) { return grammarErrorOnFirstToken(node, Diagnostics.Modifiers_cannot_appear_here); } - else if (checkGrammarForInvalidQuestionMark(node.questionToken, Diagnostics.An_object_member_cannot_be_declared_optional)) { + else if ( + checkGrammarForInvalidQuestionMark( + node.questionToken, + Diagnostics.An_object_member_cannot_be_declared_optional, + ) + ) { return true; } - else if (checkGrammarForInvalidExclamationToken(node.exclamationToken, Diagnostics.A_definite_assignment_assertion_is_not_permitted_in_this_context)) { + else if ( + checkGrammarForInvalidExclamationToken( + node.exclamationToken, + Diagnostics.A_definite_assignment_assertion_is_not_permitted_in_this_context, + ) + ) { return true; } else if (node.body === undefined) { @@ -49074,7 +62502,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (isClassLike(node.parent)) { if (languageVersion < ScriptTarget.ES2015 && isPrivateIdentifier(node.name)) { - return grammarErrorOnNode(node.name, Diagnostics.Private_identifiers_are_only_available_when_targeting_ECMAScript_2015_and_higher); + return grammarErrorOnNode( + node.name, + Diagnostics.Private_identifiers_are_only_available_when_targeting_ECMAScript_2015_and_higher, + ); } // Technically, computed properties in ambient contexts is disallowed // for property declarations and accessors too, not just methods. @@ -49082,17 +62513,33 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // and accessors are not allowed in ambient contexts in general, // so this error only really matters for methods. if (node.flags & NodeFlags.Ambient) { - return checkGrammarForInvalidDynamicName(node.name, Diagnostics.A_computed_property_name_in_an_ambient_context_must_refer_to_an_expression_whose_type_is_a_literal_type_or_a_unique_symbol_type); + return checkGrammarForInvalidDynamicName( + node.name, + Diagnostics + .A_computed_property_name_in_an_ambient_context_must_refer_to_an_expression_whose_type_is_a_literal_type_or_a_unique_symbol_type, + ); } else if (node.kind === SyntaxKind.MethodDeclaration && !node.body) { - return checkGrammarForInvalidDynamicName(node.name, Diagnostics.A_computed_property_name_in_a_method_overload_must_refer_to_an_expression_whose_type_is_a_literal_type_or_a_unique_symbol_type); + return checkGrammarForInvalidDynamicName( + node.name, + Diagnostics + .A_computed_property_name_in_a_method_overload_must_refer_to_an_expression_whose_type_is_a_literal_type_or_a_unique_symbol_type, + ); } } else if (node.parent.kind === SyntaxKind.InterfaceDeclaration) { - return checkGrammarForInvalidDynamicName(node.name, Diagnostics.A_computed_property_name_in_an_interface_must_refer_to_an_expression_whose_type_is_a_literal_type_or_a_unique_symbol_type); + return checkGrammarForInvalidDynamicName( + node.name, + Diagnostics + .A_computed_property_name_in_an_interface_must_refer_to_an_expression_whose_type_is_a_literal_type_or_a_unique_symbol_type, + ); } else if (node.parent.kind === SyntaxKind.TypeLiteral) { - return checkGrammarForInvalidDynamicName(node.name, Diagnostics.A_computed_property_name_in_a_type_literal_must_refer_to_an_expression_whose_type_is_a_literal_type_or_a_unique_symbol_type); + return checkGrammarForInvalidDynamicName( + node.name, + Diagnostics + .A_computed_property_name_in_a_type_literal_must_refer_to_an_expression_whose_type_is_a_literal_type_or_a_unique_symbol_type, + ); } } @@ -49109,10 +62556,17 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // found matching label - verify that label usage is correct // continue can only target labels that are on iteration statements const isMisplacedContinueLabel = node.kind === SyntaxKind.ContinueStatement - && !isIterationStatement((current as LabeledStatement).statement, /*lookInLabeledStatements*/ true); + && !isIterationStatement( + (current as LabeledStatement).statement, + /*lookInLabeledStatements*/ true, + ); if (isMisplacedContinueLabel) { - return grammarErrorOnNode(node, Diagnostics.A_continue_statement_can_only_jump_to_a_label_of_an_enclosing_iteration_statement); + return grammarErrorOnNode( + node, + Diagnostics + .A_continue_statement_can_only_jump_to_a_label_of_an_enclosing_iteration_statement, + ); } return false; @@ -49156,7 +62610,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (node !== last(elements)) { return grammarErrorOnNode(node, Diagnostics.A_rest_element_must_be_last_in_a_destructuring_pattern); } - checkGrammarForDisallowedTrailingComma(elements, Diagnostics.A_rest_parameter_or_binding_pattern_may_not_have_a_trailing_comma); + checkGrammarForDisallowedTrailingComma( + elements, + Diagnostics.A_rest_parameter_or_binding_pattern_may_not_have_a_trailing_comma, + ); if (node.propertyName) { return grammarErrorOnNode(node.name, Diagnostics.A_rest_element_cannot_have_a_property_name); @@ -49165,26 +62622,34 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (node.dotDotDotToken && node.initializer) { // Error on equals token which immediately precedes the initializer - return grammarErrorAtPos(node, node.initializer.pos - 1, 1, Diagnostics.A_rest_element_cannot_have_an_initializer); + return grammarErrorAtPos( + node, + node.initializer.pos - 1, + 1, + Diagnostics.A_rest_element_cannot_have_an_initializer, + ); } } function isStringOrNumberLiteralExpression(expr: Expression) { - return isStringOrNumericLiteralLike(expr) || - expr.kind === SyntaxKind.PrefixUnaryExpression && (expr as PrefixUnaryExpression).operator === SyntaxKind.MinusToken && - (expr as PrefixUnaryExpression).operand.kind === SyntaxKind.NumericLiteral; + return isStringOrNumericLiteralLike(expr) + || expr.kind === SyntaxKind.PrefixUnaryExpression + && (expr as PrefixUnaryExpression).operator === SyntaxKind.MinusToken + && (expr as PrefixUnaryExpression).operand.kind === SyntaxKind.NumericLiteral; } function isBigIntLiteralExpression(expr: Expression) { - return expr.kind === SyntaxKind.BigIntLiteral || - expr.kind === SyntaxKind.PrefixUnaryExpression && (expr as PrefixUnaryExpression).operator === SyntaxKind.MinusToken && - (expr as PrefixUnaryExpression).operand.kind === SyntaxKind.BigIntLiteral; + return expr.kind === SyntaxKind.BigIntLiteral + || expr.kind === SyntaxKind.PrefixUnaryExpression + && (expr as PrefixUnaryExpression).operator === SyntaxKind.MinusToken + && (expr as PrefixUnaryExpression).operand.kind === SyntaxKind.BigIntLiteral; } function isSimpleLiteralEnumReference(expr: Expression) { if ( - (isPropertyAccessExpression(expr) || (isElementAccessExpression(expr) && isStringOrNumberLiteralExpression(expr.argumentExpression))) && - isEntityNameExpression(expr.expression) + (isPropertyAccessExpression(expr) + || (isElementAccessExpression(expr) && isStringOrNumberLiteralExpression(expr.argumentExpression))) + && isEntityNameExpression(expr.expression) ) { return !!(checkExpressionCached(expr).flags & TypeFlags.EnumLike); } @@ -49194,15 +62659,20 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const initializer = node.initializer; if (initializer) { const isInvalidInitializer = !( - isStringOrNumberLiteralExpression(initializer) || - isSimpleLiteralEnumReference(initializer) || - initializer.kind === SyntaxKind.TrueKeyword || initializer.kind === SyntaxKind.FalseKeyword || - isBigIntLiteralExpression(initializer) + isStringOrNumberLiteralExpression(initializer) + || isSimpleLiteralEnumReference(initializer) + || initializer.kind === SyntaxKind.TrueKeyword || initializer.kind === SyntaxKind.FalseKeyword + || isBigIntLiteralExpression(initializer) ); - const isConstOrReadonly = isDeclarationReadonly(node) || isVariableDeclaration(node) && (isVarConstLike(node)); + const isConstOrReadonly = isDeclarationReadonly(node) + || isVariableDeclaration(node) && (isVarConstLike(node)); if (isConstOrReadonly && !node.type) { if (isInvalidInitializer) { - return grammarErrorOnNode(initializer, Diagnostics.A_const_initializer_in_an_ambient_context_must_be_a_string_or_numeric_literal_or_literal_enum_reference); + return grammarErrorOnNode( + initializer, + Diagnostics + .A_const_initializer_in_an_ambient_context_must_be_a_string_or_numeric_literal_or_literal_enum_reference, + ); } } else { @@ -49217,13 +62687,20 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (isBindingPattern(node.name)) { switch (blockScopeKind) { case NodeFlags.AwaitUsing: - return grammarErrorOnNode(node, Diagnostics._0_declarations_may_not_have_binding_patterns, "await using"); + return grammarErrorOnNode( + node, + Diagnostics._0_declarations_may_not_have_binding_patterns, + "await using", + ); case NodeFlags.Using: return grammarErrorOnNode(node, Diagnostics._0_declarations_may_not_have_binding_patterns, "using"); } } - if (node.parent.parent.kind !== SyntaxKind.ForInStatement && node.parent.parent.kind !== SyntaxKind.ForOfStatement) { + if ( + node.parent.parent.kind !== SyntaxKind.ForInStatement + && node.parent.parent.kind !== SyntaxKind.ForOfStatement + ) { if (nodeFlags & NodeFlags.Ambient) { checkAmbientInitializer(node); } @@ -49242,7 +62719,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } - if (node.exclamationToken && (node.parent.parent.kind !== SyntaxKind.VariableStatement || !node.type || node.initializer || nodeFlags & NodeFlags.Ambient)) { + if ( + node.exclamationToken + && (node.parent.parent.kind !== SyntaxKind.VariableStatement || !node.type || node.initializer + || nodeFlags & NodeFlags.Ambient) + ) { const message = node.initializer ? Diagnostics.Declarations_with_initializers_cannot_also_have_definite_assignment_assertions : !node.type @@ -49252,8 +62733,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } if ( - (moduleKind < ModuleKind.ES2015 || getSourceFileOfNode(node).impliedNodeFormat === ModuleKind.CommonJS) && moduleKind !== ModuleKind.System && - !(node.parent.parent.flags & NodeFlags.Ambient) && hasSyntacticModifier(node.parent.parent, ModifierFlags.Export) + (moduleKind < ModuleKind.ES2015 || getSourceFileOfNode(node).impliedNodeFormat === ModuleKind.CommonJS) + && moduleKind !== ModuleKind.System + && !(node.parent.parent.flags & NodeFlags.Ambient) + && hasSyntacticModifier(node.parent.parent, ModifierFlags.Export) ) { checkESModuleMarker(node.name); } @@ -49271,7 +62754,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function checkESModuleMarker(name: Identifier | BindingPattern): boolean { if (name.kind === SyntaxKind.Identifier) { if (idText(name) === "__esModule") { - return grammarErrorOnNodeSkippedOn("noEmit", name, Diagnostics.Identifier_expected_esModule_is_reserved_as_an_exported_marker_when_transforming_ECMAScript_modules); + return grammarErrorOnNodeSkippedOn( + "noEmit", + name, + Diagnostics + .Identifier_expected_esModule_is_reserved_as_an_exported_marker_when_transforming_ECMAScript_modules, + ); } } else { @@ -49288,7 +62776,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function checkGrammarNameInLetOrConstDeclarations(name: Identifier | BindingPattern): boolean { if (name.kind === SyntaxKind.Identifier) { if (name.escapedText === "let") { - return grammarErrorOnNode(name, Diagnostics.let_is_not_allowed_to_be_used_as_a_name_in_let_or_const_declarations); + return grammarErrorOnNode( + name, + Diagnostics.let_is_not_allowed_to_be_used_as_a_name_in_let_or_const_declarations, + ); } } else { @@ -49309,16 +62800,24 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } if (!declarationList.declarations.length) { - return grammarErrorAtPos(declarationList, declarations.pos, declarations.end - declarations.pos, Diagnostics.Variable_declaration_list_cannot_be_empty); + return grammarErrorAtPos( + declarationList, + declarations.pos, + declarations.end - declarations.pos, + Diagnostics.Variable_declaration_list_cannot_be_empty, + ); } const blockScopeFlags = declarationList.flags & NodeFlags.BlockScoped; - if ((blockScopeFlags === NodeFlags.Using || blockScopeFlags === NodeFlags.AwaitUsing) && isForInStatement(declarationList.parent)) { + if ( + (blockScopeFlags === NodeFlags.Using || blockScopeFlags === NodeFlags.AwaitUsing) + && isForInStatement(declarationList.parent) + ) { return grammarErrorOnNode( declarationList, - blockScopeFlags === NodeFlags.Using ? - Diagnostics.The_left_hand_side_of_a_for_in_statement_cannot_be_a_using_declaration : - Diagnostics.The_left_hand_side_of_a_for_in_statement_cannot_be_an_await_using_declaration, + blockScopeFlags === NodeFlags.Using + ? Diagnostics.The_left_hand_side_of_a_for_in_statement_cannot_be_a_using_declaration + : Diagnostics.The_left_hand_side_of_a_for_in_statement_cannot_be_an_await_using_declaration, ); } @@ -49350,12 +62849,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (!allowLetAndConstDeclarations(node.parent)) { const blockScopeKind = getCombinedNodeFlagsCached(node.declarationList) & NodeFlags.BlockScoped; if (blockScopeKind) { - const keyword = blockScopeKind === NodeFlags.Let ? "let" : - blockScopeKind === NodeFlags.Const ? "const" : - blockScopeKind === NodeFlags.Using ? "using" : - blockScopeKind === NodeFlags.AwaitUsing ? "await using" : - Debug.fail("Unknown BlockScope flag"); - return grammarErrorOnNode(node, Diagnostics._0_declarations_can_only_be_declared_inside_a_block, keyword); + const keyword = blockScopeKind === NodeFlags.Let ? "let" + : blockScopeKind === NodeFlags.Const ? "const" + : blockScopeKind === NodeFlags.Using ? "using" + : blockScopeKind === NodeFlags.AwaitUsing ? "await using" + : Debug.fail("Unknown BlockScope flag"); + return grammarErrorOnNode( + node, + Diagnostics._0_declarations_can_only_be_declared_inside_a_block, + keyword, + ); } } } @@ -49365,12 +62868,24 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { switch (node.keywordToken) { case SyntaxKind.NewKeyword: if (escapedText !== "target") { - return grammarErrorOnNode(node.name, Diagnostics._0_is_not_a_valid_meta_property_for_keyword_1_Did_you_mean_2, unescapeLeadingUnderscores(node.name.escapedText), tokenToString(node.keywordToken), "target"); + return grammarErrorOnNode( + node.name, + Diagnostics._0_is_not_a_valid_meta_property_for_keyword_1_Did_you_mean_2, + unescapeLeadingUnderscores(node.name.escapedText), + tokenToString(node.keywordToken), + "target", + ); } break; case SyntaxKind.ImportKeyword: if (escapedText !== "meta") { - return grammarErrorOnNode(node.name, Diagnostics._0_is_not_a_valid_meta_property_for_keyword_1_Did_you_mean_2, unescapeLeadingUnderscores(node.name.escapedText), tokenToString(node.keywordToken), "meta"); + return grammarErrorOnNode( + node.name, + Diagnostics._0_is_not_a_valid_meta_property_for_keyword_1_Did_you_mean_2, + unescapeLeadingUnderscores(node.name.escapedText), + tokenToString(node.keywordToken), + "meta", + ); } break; } @@ -49390,7 +62905,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return false; } - function grammarErrorAtPos(nodeForSourceFile: Node, start: number, length: number, message: DiagnosticMessage, ...args: DiagnosticArguments): boolean { + function grammarErrorAtPos( + nodeForSourceFile: Node, + start: number, + length: number, + message: DiagnosticMessage, + ...args: DiagnosticArguments + ): boolean { const sourceFile = getSourceFileOfNode(nodeForSourceFile); if (!hasParseDiagnostics(sourceFile)) { diagnostics.add(createFileDiagnostic(sourceFile, start, length, message, ...args)); @@ -49399,7 +62920,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return false; } - function grammarErrorOnNodeSkippedOn(key: keyof CompilerOptions, node: Node, message: DiagnosticMessage, ...args: DiagnosticArguments): boolean { + function grammarErrorOnNodeSkippedOn( + key: keyof CompilerOptions, + node: Node, + message: DiagnosticMessage, + ...args: DiagnosticArguments + ): boolean { const sourceFile = getSourceFileOfNode(node); if (!hasParseDiagnostics(sourceFile)) { errorSkippedOn(key, node, message, ...args); @@ -49422,7 +62948,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const range = node.typeParameters || jsdocTypeParameters && firstOrUndefined(jsdocTypeParameters); if (range) { const pos = range.pos === range.end ? range.pos : skipTrivia(getSourceFileOfNode(node).text, range.pos); - return grammarErrorAtPos(node, pos, range.end - pos, Diagnostics.Type_parameters_cannot_appear_on_a_constructor_declaration); + return grammarErrorAtPos( + node, + pos, + range.end - pos, + Diagnostics.Type_parameters_cannot_appear_on_a_constructor_declaration, + ); } } @@ -49434,45 +62965,88 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function checkGrammarProperty(node: PropertyDeclaration | PropertySignature) { - if (isComputedPropertyName(node.name) && isBinaryExpression(node.name.expression) && node.name.expression.operatorToken.kind === SyntaxKind.InKeyword) { - return grammarErrorOnNode(node.parent.members[0], Diagnostics.A_mapped_type_may_not_declare_properties_or_methods); + if ( + isComputedPropertyName(node.name) && isBinaryExpression(node.name.expression) + && node.name.expression.operatorToken.kind === SyntaxKind.InKeyword + ) { + return grammarErrorOnNode( + node.parent.members[0], + Diagnostics.A_mapped_type_may_not_declare_properties_or_methods, + ); } if (isClassLike(node.parent)) { if (isStringLiteral(node.name) && node.name.text === "constructor") { return grammarErrorOnNode(node.name, Diagnostics.Classes_may_not_have_a_field_named_constructor); } - if (checkGrammarForInvalidDynamicName(node.name, Diagnostics.A_computed_property_name_in_a_class_property_declaration_must_have_a_simple_literal_type_or_a_unique_symbol_type)) { + if ( + checkGrammarForInvalidDynamicName( + node.name, + Diagnostics + .A_computed_property_name_in_a_class_property_declaration_must_have_a_simple_literal_type_or_a_unique_symbol_type, + ) + ) { return true; } if (languageVersion < ScriptTarget.ES2015 && isPrivateIdentifier(node.name)) { - return grammarErrorOnNode(node.name, Diagnostics.Private_identifiers_are_only_available_when_targeting_ECMAScript_2015_and_higher); + return grammarErrorOnNode( + node.name, + Diagnostics.Private_identifiers_are_only_available_when_targeting_ECMAScript_2015_and_higher, + ); } if (languageVersion < ScriptTarget.ES2015 && isAutoAccessorPropertyDeclaration(node)) { - return grammarErrorOnNode(node.name, Diagnostics.Properties_with_the_accessor_modifier_are_only_available_when_targeting_ECMAScript_2015_and_higher); + return grammarErrorOnNode( + node.name, + Diagnostics + .Properties_with_the_accessor_modifier_are_only_available_when_targeting_ECMAScript_2015_and_higher, + ); } - if (isAutoAccessorPropertyDeclaration(node) && checkGrammarForInvalidQuestionMark(node.questionToken, Diagnostics.An_accessor_property_cannot_be_declared_optional)) { + if ( + isAutoAccessorPropertyDeclaration(node) + && checkGrammarForInvalidQuestionMark( + node.questionToken, + Diagnostics.An_accessor_property_cannot_be_declared_optional, + ) + ) { return true; } } else if (node.parent.kind === SyntaxKind.InterfaceDeclaration) { - if (checkGrammarForInvalidDynamicName(node.name, Diagnostics.A_computed_property_name_in_an_interface_must_refer_to_an_expression_whose_type_is_a_literal_type_or_a_unique_symbol_type)) { + if ( + checkGrammarForInvalidDynamicName( + node.name, + Diagnostics + .A_computed_property_name_in_an_interface_must_refer_to_an_expression_whose_type_is_a_literal_type_or_a_unique_symbol_type, + ) + ) { return true; } // Interfaces cannot contain property declarations Debug.assertNode(node, isPropertySignature); if (node.initializer) { - return grammarErrorOnNode(node.initializer, Diagnostics.An_interface_property_cannot_have_an_initializer); + return grammarErrorOnNode( + node.initializer, + Diagnostics.An_interface_property_cannot_have_an_initializer, + ); } } else if (isTypeLiteralNode(node.parent)) { - if (checkGrammarForInvalidDynamicName(node.name, Diagnostics.A_computed_property_name_in_a_type_literal_must_refer_to_an_expression_whose_type_is_a_literal_type_or_a_unique_symbol_type)) { + if ( + checkGrammarForInvalidDynamicName( + node.name, + Diagnostics + .A_computed_property_name_in_a_type_literal_must_refer_to_an_expression_whose_type_is_a_literal_type_or_a_unique_symbol_type, + ) + ) { return true; } // Type literals cannot contain property declarations Debug.assertNode(node, isPropertySignature); if (node.initializer) { - return grammarErrorOnNode(node.initializer, Diagnostics.A_type_literal_property_cannot_have_an_initializer); + return grammarErrorOnNode( + node.initializer, + Diagnostics.A_type_literal_property_cannot_have_an_initializer, + ); } } @@ -49481,8 +63055,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } if ( - isPropertyDeclaration(node) && node.exclamationToken && (!isClassLike(node.parent) || !node.type || node.initializer || - node.flags & NodeFlags.Ambient || isStatic(node) || hasAbstractModifier(node)) + isPropertyDeclaration(node) && node.exclamationToken + && (!isClassLike(node.parent) || !node.type || node.initializer + || node.flags & NodeFlags.Ambient || isStatic(node) || hasAbstractModifier(node)) ) { const message = node.initializer ? Diagnostics.Declarations_with_initializers_cannot_also_have_definite_assignment_assertions @@ -49507,19 +63082,22 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // // TODO: The spec needs to be amended to reflect this grammar. if ( - node.kind === SyntaxKind.InterfaceDeclaration || - node.kind === SyntaxKind.TypeAliasDeclaration || - node.kind === SyntaxKind.ImportDeclaration || - node.kind === SyntaxKind.ImportEqualsDeclaration || - node.kind === SyntaxKind.ExportDeclaration || - node.kind === SyntaxKind.ExportAssignment || - node.kind === SyntaxKind.NamespaceExportDeclaration || - hasSyntacticModifier(node, ModifierFlags.Ambient | ModifierFlags.Export | ModifierFlags.Default) + node.kind === SyntaxKind.InterfaceDeclaration + || node.kind === SyntaxKind.TypeAliasDeclaration + || node.kind === SyntaxKind.ImportDeclaration + || node.kind === SyntaxKind.ImportEqualsDeclaration + || node.kind === SyntaxKind.ExportDeclaration + || node.kind === SyntaxKind.ExportAssignment + || node.kind === SyntaxKind.NamespaceExportDeclaration + || hasSyntacticModifier(node, ModifierFlags.Ambient | ModifierFlags.Export | ModifierFlags.Default) ) { return false; } - return grammarErrorOnFirstToken(node, Diagnostics.Top_level_declarations_in_d_ts_files_must_start_with_either_a_declare_or_export_modifier); + return grammarErrorOnFirstToken( + node, + Diagnostics.Top_level_declarations_in_d_ts_files_must_start_with_either_a_declare_or_export_modifier, + ); } function checkGrammarTopLevelElementsForRequiredDeclareModifier(file: SourceFile): boolean { @@ -49541,8 +63119,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (node.flags & NodeFlags.Ambient) { // Find containing block which is either Block, ModuleBlock, SourceFile const links = getNodeLinks(node); - if (!links.hasReportedStatementInAmbientContext && (isFunctionLike(node.parent) || isAccessor(node.parent))) { - return getNodeLinks(node).hasReportedStatementInAmbientContext = grammarErrorOnFirstToken(node, Diagnostics.An_implementation_cannot_be_declared_in_ambient_contexts); + if ( + !links.hasReportedStatementInAmbientContext && (isFunctionLike(node.parent) || isAccessor(node.parent)) + ) { + return getNodeLinks(node).hasReportedStatementInAmbientContext = grammarErrorOnFirstToken( + node, + Diagnostics.An_implementation_cannot_be_declared_in_ambient_contexts, + ); } // We are either parented by another statement, or some sort of block. @@ -49550,11 +63133,17 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // to prevent noisiness. So use a bit on the block to indicate if // this has already been reported, and don't report if it has. // - if (node.parent.kind === SyntaxKind.Block || node.parent.kind === SyntaxKind.ModuleBlock || node.parent.kind === SyntaxKind.SourceFile) { + if ( + node.parent.kind === SyntaxKind.Block || node.parent.kind === SyntaxKind.ModuleBlock + || node.parent.kind === SyntaxKind.SourceFile + ) { const links = getNodeLinks(node.parent); // Check if the containing block ever report this error if (!links.hasReportedStatementInAmbientContext) { - return links.hasReportedStatementInAmbientContext = grammarErrorOnFirstToken(node, Diagnostics.Statements_are_not_allowed_in_ambient_contexts); + return links.hasReportedStatementInAmbientContext = grammarErrorOnFirstToken( + node, + Diagnostics.Statements_are_not_allowed_in_ambient_contexts, + ); } } else { @@ -49589,15 +63178,27 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return; } - addErrorOrSuggestion(/*isError*/ false, createDiagnosticForNode(node, Diagnostics.Numeric_literals_with_absolute_values_equal_to_2_53_or_greater_are_too_large_to_be_represented_accurately_as_integers)); + addErrorOrSuggestion( + /*isError*/ false, + createDiagnosticForNode( + node, + Diagnostics + .Numeric_literals_with_absolute_values_equal_to_2_53_or_greater_are_too_large_to_be_represented_accurately_as_integers, + ), + ); } function checkGrammarBigIntLiteral(node: BigIntLiteral): boolean { - const literalType = isLiteralTypeNode(node.parent) || - isPrefixUnaryExpression(node.parent) && isLiteralTypeNode(node.parent.parent); + const literalType = isLiteralTypeNode(node.parent) + || isPrefixUnaryExpression(node.parent) && isLiteralTypeNode(node.parent.parent); if (!literalType) { if (languageVersion < ScriptTarget.ES2020) { - if (grammarErrorOnNode(node, Diagnostics.BigInt_literals_are_not_available_when_targeting_lower_than_ES2020)) { + if ( + grammarErrorOnNode( + node, + Diagnostics.BigInt_literals_are_not_available_when_targeting_lower_than_ES2020, + ) + ) { return true; } } @@ -49605,7 +63206,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return false; } - function grammarErrorAfterFirstToken(node: Node, message: DiagnosticMessage, ...args: DiagnosticArguments): boolean { + function grammarErrorAfterFirstToken( + node: Node, + message: DiagnosticMessage, + ...args: DiagnosticArguments + ): boolean { const sourceFile = getSourceFileOfNode(node); if (!hasParseDiagnostics(sourceFile)) { const span = getSpanOfTokenAtPosition(sourceFile, node.pos); @@ -49630,7 +63235,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function checkGrammarImportClause(node: ImportClause): boolean { if (node.isTypeOnly && node.name && node.namedBindings) { - return grammarErrorOnNode(node, Diagnostics.A_type_only_import_can_specify_a_default_import_or_named_bindings_but_not_both); + return grammarErrorOnNode( + node, + Diagnostics.A_type_only_import_can_specify_a_default_import_or_named_bindings_but_not_both, + ); } if (node.isTypeOnly && node.namedBindings?.kind === SyntaxKind.NamedImports) { return checkGrammarNamedImportsOrExports(node.namedBindings); @@ -49644,8 +63252,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return grammarErrorOnFirstToken( specifier, specifier.kind === SyntaxKind.ImportSpecifier - ? Diagnostics.The_type_modifier_cannot_be_used_on_a_named_import_when_import_type_is_used_on_its_import_statement - : Diagnostics.The_type_modifier_cannot_be_used_on_a_named_export_when_export_type_is_used_on_its_export_statement, + ? Diagnostics + .The_type_modifier_cannot_be_used_on_a_named_import_when_import_type_is_used_on_its_import_statement + : Diagnostics + .The_type_modifier_cannot_be_used_on_a_named_export_when_export_type_is_used_on_its_export_statement, ); } }); @@ -49653,30 +63263,50 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function checkGrammarImportCallExpression(node: ImportCall): boolean { if (compilerOptions.verbatimModuleSyntax && moduleKind === ModuleKind.CommonJS) { - return grammarErrorOnNode(node, Diagnostics.ESM_syntax_is_not_allowed_in_a_CommonJS_module_when_verbatimModuleSyntax_is_enabled); + return grammarErrorOnNode( + node, + Diagnostics.ESM_syntax_is_not_allowed_in_a_CommonJS_module_when_verbatimModuleSyntax_is_enabled, + ); } if (moduleKind === ModuleKind.ES2015) { - return grammarErrorOnNode(node, Diagnostics.Dynamic_imports_are_only_supported_when_the_module_flag_is_set_to_es2020_es2022_esnext_commonjs_amd_system_umd_node16_or_nodenext); + return grammarErrorOnNode( + node, + Diagnostics + .Dynamic_imports_are_only_supported_when_the_module_flag_is_set_to_es2020_es2022_esnext_commonjs_amd_system_umd_node16_or_nodenext, + ); } if (node.typeArguments) { - return grammarErrorOnNode(node, Diagnostics.This_use_of_import_is_invalid_import_calls_can_be_written_but_they_must_have_parentheses_and_cannot_have_type_arguments); + return grammarErrorOnNode( + node, + Diagnostics + .This_use_of_import_is_invalid_import_calls_can_be_written_but_they_must_have_parentheses_and_cannot_have_type_arguments, + ); } const nodeArguments = node.arguments; - if (moduleKind !== ModuleKind.ESNext && moduleKind !== ModuleKind.NodeNext && moduleKind !== ModuleKind.Node16) { + if ( + moduleKind !== ModuleKind.ESNext && moduleKind !== ModuleKind.NodeNext && moduleKind !== ModuleKind.Node16 + ) { // We are allowed trailing comma after proposal-import-assertions. checkGrammarForDisallowedTrailingComma(nodeArguments); if (nodeArguments.length > 1) { const assertionArgument = nodeArguments[1]; - return grammarErrorOnNode(assertionArgument, Diagnostics.Dynamic_imports_only_support_a_second_argument_when_the_module_option_is_set_to_esnext_node16_or_nodenext); + return grammarErrorOnNode( + assertionArgument, + Diagnostics + .Dynamic_imports_only_support_a_second_argument_when_the_module_option_is_set_to_esnext_node16_or_nodenext, + ); } } if (nodeArguments.length === 0 || nodeArguments.length > 2) { - return grammarErrorOnNode(node, Diagnostics.Dynamic_imports_can_only_accept_a_module_specifier_and_an_optional_assertion_as_arguments); + return grammarErrorOnNode( + node, + Diagnostics.Dynamic_imports_can_only_accept_a_module_specifier_and_an_optional_assertion_as_arguments, + ); } // see: parseArgumentOrArrayLiteralElement...we use this function which parse arguments of callExpression to parse specifier for dynamic import. @@ -49690,7 +63320,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function findMatchingTypeReferenceOrTypeAliasReference(source: Type, unionTarget: UnionOrIntersectionType) { const sourceObjectFlags = getObjectFlags(source); - if (sourceObjectFlags & (ObjectFlags.Reference | ObjectFlags.Anonymous) && unionTarget.flags & TypeFlags.Union) { + if ( + sourceObjectFlags & (ObjectFlags.Reference | ObjectFlags.Anonymous) && unionTarget.flags & TypeFlags.Union + ) { return find(unionTarget.types, target => { if (target.flags & TypeFlags.Object) { const overlapObjFlags = sourceObjectFlags & getObjectFlags(target); @@ -49698,7 +63330,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return (source as TypeReference).target === (target as TypeReference).target; } if (overlapObjFlags & ObjectFlags.Anonymous) { - return !!(source as AnonymousType).aliasSymbol && (source as AnonymousType).aliasSymbol === (target as AnonymousType).aliasSymbol; + return !!(source as AnonymousType).aliasSymbol + && (source as AnonymousType).aliasSymbol === (target as AnonymousType).aliasSymbol; } } return false; @@ -49714,8 +63347,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function findBestTypeForInvokable(source: Type, unionTarget: UnionOrIntersectionType) { let signatureKind = SignatureKind.Call; - const hasSignatures = getSignaturesOfType(source, signatureKind).length > 0 || - (signatureKind = SignatureKind.Construct, getSignaturesOfType(source, signatureKind).length > 0); + const hasSignatures = getSignaturesOfType(source, signatureKind).length > 0 + || (signatureKind = SignatureKind.Construct, getSignaturesOfType(source, signatureKind).length > 0); if (hasSignatures) { return find(unionTarget.types, t => getSignaturesOfType(t, signatureKind).length > 0); } @@ -49736,7 +63369,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // We only want to account for literal types otherwise. // If we have a union of index types, it seems likely that we // needed to elaborate between two generic mapped types anyway. - const len = overlap.flags & TypeFlags.Union ? countWhere((overlap as UnionType).types, isUnitType) : 1; + const len = overlap.flags & TypeFlags.Union + ? countWhere((overlap as UnionType).types, isUnitType) : 1; if (len >= matchingCount) { bestMatch = target; matchingCount = len; @@ -49759,7 +63393,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } // Keep this up-to-date with the same logic within `getApparentTypeOfContextualType`, since they should behave similarly - function findMatchingDiscriminantType(source: Type, target: Type, isRelatedTo: (source: Type, target: Type) => Ternary) { + function findMatchingDiscriminantType( + source: Type, + target: Type, + isRelatedTo: (source: Type, target: Type) => Ternary, + ) { if (target.flags & TypeFlags.Union && source.flags & (TypeFlags.Intersection | TypeFlags.Object)) { const match = getMatchingUnionConstituentForType(target as UnionType, source); if (match) { @@ -49769,7 +63407,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (sourceProperties) { const sourcePropertiesFiltered = findDiscriminantProperties(sourceProperties, target); if (sourcePropertiesFiltered) { - const discriminated = discriminateTypeByDiscriminableItems(target as UnionType, map(sourcePropertiesFiltered, p => ([() => getTypeOfSymbol(p), p.escapedName] as [() => Type, __String])), isRelatedTo); + const discriminated = discriminateTypeByDiscriminableItems( + target as UnionType, + map( + sourcePropertiesFiltered, + p => ([() => getTypeOfSymbol(p), p.escapedName] as [() => Type, __String]), + ), + isRelatedTo, + ); if (discriminated !== target) { return discriminated; } @@ -49781,8 +63426,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function getEffectivePropertyNameForPropertyNameNode(node: PropertyName) { const name = getPropertyNameForPropertyNameNode(node); - return name ? name : - isComputedPropertyName(node) && isEntityNameExpression(node.expression) ? tryGetNameFromEntityNameExpression(node.expression) : undefined; + return name ? name + : isComputedPropertyName(node) && isEntityNameExpression(node.expression) + ? tryGetNameFromEntityNameExpression(node.expression) : undefined; } function getCombinedModifierFlagsCached(node: Declaration) { @@ -49808,9 +63454,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function isVarConstLike(node: VariableDeclaration | VariableDeclarationList) { const blockScopeKind = getCombinedNodeFlagsCached(node) & NodeFlags.BlockScoped; - return blockScopeKind === NodeFlags.Const || - blockScopeKind === NodeFlags.Using || - blockScopeKind === NodeFlags.AwaitUsing; + return blockScopeKind === NodeFlags.Const + || blockScopeKind === NodeFlags.Using + || blockScopeKind === NodeFlags.AwaitUsing; } } @@ -49820,8 +63466,8 @@ function isNotAccessor(declaration: Declaration): boolean { } function isNotOverload(declaration: Declaration): boolean { - return (declaration.kind !== SyntaxKind.FunctionDeclaration && declaration.kind !== SyntaxKind.MethodDeclaration) || - !!(declaration as FunctionDeclaration).body; + return (declaration.kind !== SyntaxKind.FunctionDeclaration && declaration.kind !== SyntaxKind.MethodDeclaration) + || !!(declaration as FunctionDeclaration).body; } /** Like 'isDeclarationName', but returns true for LHS of `import { x as y }` or `export { x as y }`. */ @@ -49869,9 +63515,12 @@ export function signatureHasLiteralTypes(s: Signature) { return !!(s.flags & SignatureFlags.HasLiteralTypes); } -function createBasicNodeBuilderModuleSpecifierResolutionHost(host: TypeCheckerHost): ModuleSpecifierResolutionHost & { getCommonSourceDirectory(): string; } { +function createBasicNodeBuilderModuleSpecifierResolutionHost( + host: TypeCheckerHost, +): ModuleSpecifierResolutionHost & { getCommonSourceDirectory(): string; } { return { - getCommonSourceDirectory: !!(host as Program).getCommonSourceDirectory ? () => (host as Program).getCommonSourceDirectory() : () => "", + getCommonSourceDirectory: !!(host as Program).getCommonSourceDirectory + ? () => (host as Program).getCommonSourceDirectory() : () => "", getCurrentDirectory: () => host.getCurrentDirectory(), getSymlinkCache: maybeBind(host, host.getSymlinkCache), getPackageJsonInfoCache: () => host.getPackageJsonInfoCache?.(), @@ -49915,7 +63564,11 @@ class SymbolTrackerImpl implements SymbolTracker { readonly canTrackSymbol: boolean; disableTrackSymbol = false; - constructor(context: NodeBuilderContext, tracker: SymbolTracker | undefined, moduleResolverHost: ModuleSpecifierResolutionHost & { getCommonSourceDirectory(): string; } | undefined) { + constructor( + context: NodeBuilderContext, + tracker: SymbolTracker | undefined, + moduleResolverHost: ModuleSpecifierResolutionHost & { getCommonSourceDirectory(): string; } | undefined, + ) { while (tracker instanceof SymbolTrackerImpl) { tracker = tracker.inner; } diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index c341fc10b4751..e340f56f139e3 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -137,7 +137,9 @@ const jsxOptionMap = new Map(Object.entries({ })); /** @internal */ -export const inverseJsxOptionMap = new Map(mapIterator(jsxOptionMap.entries(), ([key, value]: [string, JsxEmit]) => ["" + value, key] as const)); +export const inverseJsxOptionMap = new Map( + mapIterator(jsxOptionMap.entries(), ([key, value]: [string, JsxEmit]) => ["" + value, key] as const), +); // NOTE: The order here is important to default lib ordering as entries will have the same // order in the generated program (see `getDefaultLibPriority` in program.ts). This @@ -271,7 +273,8 @@ export const optionsForWatch: CommandLineOption[] = [ fixedchunksizepolling: WatchDirectoryKind.FixedChunkSizePolling, })), category: Diagnostics.Watch_and_Build_Modes, - description: Diagnostics.Specify_how_directories_are_watched_on_systems_that_lack_recursive_file_watching_functionality, + description: + Diagnostics.Specify_how_directories_are_watched_on_systems_that_lack_recursive_file_watching_functionality, defaultValueDescription: WatchDirectoryKind.UseFsEvents, }, { @@ -283,14 +286,16 @@ export const optionsForWatch: CommandLineOption[] = [ fixedchunksize: PollingWatchKind.FixedChunkSize, })), category: Diagnostics.Watch_and_Build_Modes, - description: Diagnostics.Specify_what_approach_the_watcher_should_use_if_the_system_runs_out_of_native_file_watchers, + description: + Diagnostics.Specify_what_approach_the_watcher_should_use_if_the_system_runs_out_of_native_file_watchers, defaultValueDescription: PollingWatchKind.PriorityInterval, }, { name: "synchronousWatchDirectory", type: "boolean", category: Diagnostics.Watch_and_Build_Modes, - description: Diagnostics.Synchronously_call_callbacks_and_update_the_state_of_directory_watchers_on_platforms_that_don_t_support_recursive_watching_natively, + description: Diagnostics + .Synchronously_call_callbacks_and_update_the_state_of_directory_watchers_on_platforms_that_don_t_support_recursive_watching_natively, defaultValueDescription: false, }, { @@ -383,7 +388,8 @@ export const commonOptionsWithBuild: CommandLineOption[] = [ type: "boolean", showInSimplifiedHelpView: true, category: Diagnostics.Output_Formatting, - description: Diagnostics.Enable_color_and_formatting_in_TypeScript_s_output_to_make_compiler_errors_easier_to_read, + description: + Diagnostics.Enable_color_and_formatting_in_TypeScript_s_output_to_make_compiler_errors_easier_to_read, defaultValueDescription: true, }, { @@ -494,7 +500,8 @@ export const commonOptionsWithBuild: CommandLineOption[] = [ affectsEmit: true, affectsBuildInfo: true, category: Diagnostics.Watch_and_Build_Modes, - description: Diagnostics.Have_recompiles_in_projects_that_use_incremental_and_watch_mode_assume_that_changes_within_a_file_will_only_affect_files_directly_depending_on_it, + description: Diagnostics + .Have_recompiles_in_projects_that_use_incremental_and_watch_mode_assume_that_changes_within_a_file_will_only_affect_files_directly_depending_on_it, defaultValueDescription: false, }, { @@ -532,7 +539,8 @@ export const targetOptionDeclaration: CommandLineOptionOfCustomType = { paramType: Diagnostics.VERSION, showInSimplifiedHelpView: true, category: Diagnostics.Language_and_Environment, - description: Diagnostics.Set_the_JavaScript_language_version_for_emitted_JavaScript_and_include_compatible_library_declarations, + description: Diagnostics + .Set_the_JavaScript_language_version_for_emitted_JavaScript_and_include_compatible_library_declarations, defaultValueDescription: ScriptTarget.ES5, }; @@ -599,7 +607,8 @@ const commandOptionsWithoutBuild: CommandLineOption[] = [ showInSimplifiedHelpView: true, category: Diagnostics.Command_line_Options, paramType: Diagnostics.FILE_OR_DIRECTORY, - description: Diagnostics.Compile_the_project_given_the_path_to_its_configuration_file_or_to_a_folder_with_a_tsconfig_json, + description: Diagnostics + .Compile_the_project_given_the_path_to_its_configuration_file_or_to_a_folder_with_a_tsconfig_json, }, { name: "build", @@ -642,7 +651,8 @@ const commandOptionsWithoutBuild: CommandLineOption[] = [ affectsProgramStructure: true, showInSimplifiedHelpView: true, category: Diagnostics.Language_and_Environment, - description: Diagnostics.Specify_a_set_of_bundled_library_declaration_files_that_describe_the_target_runtime_environment, + description: + Diagnostics.Specify_a_set_of_bundled_library_declaration_files_that_describe_the_target_runtime_environment, transpileOptionValue: undefined, }, { @@ -651,7 +661,8 @@ const commandOptionsWithoutBuild: CommandLineOption[] = [ affectsModuleResolution: true, showInSimplifiedHelpView: true, category: Diagnostics.JavaScript_Support, - description: Diagnostics.Allow_JavaScript_files_to_be_a_part_of_your_program_Use_the_checkJS_option_to_get_errors_from_these_files, + description: Diagnostics + .Allow_JavaScript_files_to_be_a_part_of_your_program_Use_the_checkJS_option_to_get_errors_from_these_files, defaultValueDescription: false, }, { @@ -686,7 +697,8 @@ const commandOptionsWithoutBuild: CommandLineOption[] = [ paramType: Diagnostics.FILE, showInSimplifiedHelpView: true, category: Diagnostics.Emit, - description: Diagnostics.Specify_a_file_that_bundles_all_outputs_into_one_JavaScript_file_If_declaration_is_true_also_designates_a_file_that_bundles_all_d_ts_output, + description: Diagnostics + .Specify_a_file_that_bundles_all_outputs_into_one_JavaScript_file_If_declaration_is_true_also_designates_a_file_that_bundles_all_d_ts_output, transpileOptionValue: undefined, }, { @@ -761,7 +773,8 @@ const commandOptionsWithoutBuild: CommandLineOption[] = [ affectsEmit: true, affectsBuildInfo: true, category: Diagnostics.Emit, - description: Diagnostics.Allow_importing_helper_functions_from_tslib_once_per_project_instead_of_including_them_per_file, + description: + Diagnostics.Allow_importing_helper_functions_from_tslib_once_per_project_instead_of_including_them_per_file, defaultValueDescription: false, }, { @@ -799,7 +812,8 @@ const commandOptionsWithoutBuild: CommandLineOption[] = [ name: "verbatimModuleSyntax", type: "boolean", category: Diagnostics.Interop_Constraints, - description: Diagnostics.Do_not_transform_or_elide_any_imports_or_exports_not_marked_as_type_only_ensuring_they_are_written_in_the_output_file_s_format_based_on_the_module_setting, + description: Diagnostics + .Do_not_transform_or_elide_any_imports_or_exports_not_marked_as_type_only_ensuring_they_are_written_in_the_output_file_s_format_based_on_the_module_setting, defaultValueDescription: false, }, @@ -844,7 +858,8 @@ const commandOptionsWithoutBuild: CommandLineOption[] = [ affectsBuildInfo: true, strictFlag: true, category: Diagnostics.Type_Checking, - description: Diagnostics.When_assigning_functions_check_to_ensure_parameters_and_the_return_values_are_subtype_compatible, + description: Diagnostics + .When_assigning_functions_check_to_ensure_parameters_and_the_return_values_are_subtype_compatible, defaultValueDescription: Diagnostics.false_unless_strict_is_set, }, { @@ -1072,7 +1087,8 @@ const commandOptionsWithoutBuild: CommandLineOption[] = [ affectsBuildInfo: true, showInSimplifiedHelpView: true, category: Diagnostics.Interop_Constraints, - description: Diagnostics.Emit_additional_JavaScript_to_ease_support_for_importing_CommonJS_modules_This_enables_allowSyntheticDefaultImports_for_type_compatibility, + description: Diagnostics + .Emit_additional_JavaScript_to_ease_support_for_importing_CommonJS_modules_This_enables_allowSyntheticDefaultImports_for_type_compatibility, defaultValueDescription: false, }, { @@ -1109,7 +1125,8 @@ const commandOptionsWithoutBuild: CommandLineOption[] = [ affectsSemanticDiagnostics: true, affectsBuildInfo: true, category: Diagnostics.Modules, - description: Diagnostics.Allow_imports_to_include_TypeScript_file_extensions_Requires_moduleResolution_bundler_and_either_noEmit_or_emitDeclarationOnly_to_be_set, + description: Diagnostics + .Allow_imports_to_include_TypeScript_file_extensions_Requires_moduleResolution_bundler_and_either_noEmit_or_emitDeclarationOnly_to_be_set, defaultValueDescription: false, transpileOptionValue: undefined, }, @@ -1158,7 +1175,8 @@ const commandOptionsWithoutBuild: CommandLineOption[] = [ affectsBuildInfo: true, paramType: Diagnostics.LOCATION, category: Diagnostics.Emit, - description: Diagnostics.Specify_the_location_where_debugger_should_locate_map_files_instead_of_generated_locations, + description: + Diagnostics.Specify_the_location_where_debugger_should_locate_map_files_instead_of_generated_locations, }, { name: "inlineSources", @@ -1197,14 +1215,16 @@ const commandOptionsWithoutBuild: CommandLineOption[] = [ name: "jsxFactory", type: "string", category: Diagnostics.Language_and_Environment, - description: Diagnostics.Specify_the_JSX_factory_function_used_when_targeting_React_JSX_emit_e_g_React_createElement_or_h, + description: Diagnostics + .Specify_the_JSX_factory_function_used_when_targeting_React_JSX_emit_e_g_React_createElement_or_h, defaultValueDescription: "`React.createElement`", }, { name: "jsxFragmentFactory", type: "string", category: Diagnostics.Language_and_Environment, - description: Diagnostics.Specify_the_JSX_Fragment_reference_used_for_fragments_when_targeting_React_JSX_emit_e_g_React_Fragment_or_Fragment, + description: Diagnostics + .Specify_the_JSX_Fragment_reference_used_for_fragments_when_targeting_React_JSX_emit_e_g_React_Fragment_or_Fragment, defaultValueDescription: "React.Fragment", }, { @@ -1215,7 +1235,8 @@ const commandOptionsWithoutBuild: CommandLineOption[] = [ affectsBuildInfo: true, affectsModuleResolution: true, category: Diagnostics.Language_and_Environment, - description: Diagnostics.Specify_module_specifier_used_to_import_the_JSX_factory_functions_when_using_jsx_Colon_react_jsx_Asterisk, + description: Diagnostics + .Specify_module_specifier_used_to_import_the_JSX_factory_functions_when_using_jsx_Colon_react_jsx_Asterisk, defaultValueDescription: "react", }, { @@ -1254,7 +1275,8 @@ const commandOptionsWithoutBuild: CommandLineOption[] = [ affectsEmit: true, affectsBuildInfo: true, category: Diagnostics.Language_and_Environment, - description: Diagnostics.Specify_the_object_invoked_for_createElement_This_only_applies_when_targeting_react_JSX_emit, + description: + Diagnostics.Specify_the_object_invoked_for_createElement_This_only_applies_when_targeting_react_JSX_emit, defaultValueDescription: "`React`", }, { @@ -1320,7 +1342,8 @@ const commandOptionsWithoutBuild: CommandLineOption[] = [ type: "boolean", affectsModuleResolution: true, category: Diagnostics.Modules, - description: Diagnostics.Disallow_import_s_require_s_or_reference_s_from_expanding_the_number_of_files_TypeScript_should_add_to_a_project, + description: Diagnostics + .Disallow_import_s_require_s_or_reference_s_from_expanding_the_number_of_files_TypeScript_should_add_to_a_project, // We are not doing a full typecheck, we are not resolving the whole context, // so pass --noResolve to avoid reporting missing file errors. transpileOptionValue: true, @@ -1340,7 +1363,8 @@ const commandOptionsWithoutBuild: CommandLineOption[] = [ type: "boolean", affectsProgramStructure: true, category: Diagnostics.Editor_Support, - description: Diagnostics.Remove_the_20mb_cap_on_total_source_code_size_for_JavaScript_files_in_the_TypeScript_language_server, + description: Diagnostics + .Remove_the_20mb_cap_on_total_source_code_size_for_JavaScript_files_in_the_TypeScript_language_server, defaultValueDescription: false, }, { @@ -1348,7 +1372,8 @@ const commandOptionsWithoutBuild: CommandLineOption[] = [ type: "boolean", isTSConfigOnly: true, category: Diagnostics.Projects, - description: Diagnostics.Disable_preferring_source_files_instead_of_declaration_files_when_referencing_composite_projects, + description: Diagnostics + .Disable_preferring_source_files_instead_of_declaration_files_when_referencing_composite_projects, defaultValueDescription: false, }, { @@ -1476,7 +1501,8 @@ const commandOptionsWithoutBuild: CommandLineOption[] = [ type: "number", affectsModuleResolution: true, category: Diagnostics.JavaScript_Support, - description: Diagnostics.Specify_the_maximum_folder_depth_used_for_checking_JavaScript_files_from_node_modules_Only_applicable_with_allowJs, + description: Diagnostics + .Specify_the_maximum_folder_depth_used_for_checking_JavaScript_files_from_node_modules_Only_applicable_with_allowJs, defaultValueDescription: 0, }, { @@ -1504,7 +1530,8 @@ const commandOptionsWithoutBuild: CommandLineOption[] = [ affectsEmit: true, affectsBuildInfo: true, category: Diagnostics.Emit, - description: Diagnostics.Preserve_unused_imported_values_in_the_JavaScript_output_that_would_otherwise_be_removed, + description: + Diagnostics.Preserve_unused_imported_values_in_the_JavaScript_output_that_would_otherwise_be_removed, defaultValueDescription: false, }, @@ -1537,7 +1564,8 @@ const commandOptionsWithoutBuild: CommandLineOption[] = [ affectsModuleResolution: true, description: Diagnostics.Control_what_method_is_used_to_detect_module_format_JS_files, category: Diagnostics.Language_and_Environment, - defaultValueDescription: Diagnostics.auto_Colon_Treat_files_with_imports_exports_import_meta_jsx_with_jsx_Colon_react_jsx_or_esm_format_with_module_Colon_node16_as_modules, + defaultValueDescription: Diagnostics + .auto_Colon_Treat_files_with_imports_exports_import_meta_jsx_with_jsx_Colon_react_jsx_or_esm_format_with_module_Colon_node16_as_modules, }, { name: "ignoreDeprecations", @@ -1553,25 +1581,39 @@ export const optionDeclarations: CommandLineOption[] = [ ]; /** @internal */ -export const semanticDiagnosticsOptionDeclarations: readonly CommandLineOption[] = optionDeclarations.filter(option => !!option.affectsSemanticDiagnostics); +export const semanticDiagnosticsOptionDeclarations: readonly CommandLineOption[] = optionDeclarations.filter(option => + !!option.affectsSemanticDiagnostics +); /** @internal */ -export const affectsEmitOptionDeclarations: readonly CommandLineOption[] = optionDeclarations.filter(option => !!option.affectsEmit); +export const affectsEmitOptionDeclarations: readonly CommandLineOption[] = optionDeclarations.filter(option => + !!option.affectsEmit +); /** @internal */ -export const affectsDeclarationPathOptionDeclarations: readonly CommandLineOption[] = optionDeclarations.filter(option => !!option.affectsDeclarationPath); +export const affectsDeclarationPathOptionDeclarations: readonly CommandLineOption[] = optionDeclarations.filter( + option => !!option.affectsDeclarationPath, +); /** @internal */ -export const moduleResolutionOptionDeclarations: readonly CommandLineOption[] = optionDeclarations.filter(option => !!option.affectsModuleResolution); +export const moduleResolutionOptionDeclarations: readonly CommandLineOption[] = optionDeclarations.filter(option => + !!option.affectsModuleResolution +); /** @internal */ -export const sourceFileAffectingCompilerOptions: readonly CommandLineOption[] = optionDeclarations.filter(option => !!option.affectsSourceFile || !!option.affectsModuleResolution || !!option.affectsBindDiagnostics); +export const sourceFileAffectingCompilerOptions: readonly CommandLineOption[] = optionDeclarations.filter(option => + !!option.affectsSourceFile || !!option.affectsModuleResolution || !!option.affectsBindDiagnostics +); /** @internal */ -export const optionsAffectingProgramStructure: readonly CommandLineOption[] = optionDeclarations.filter(option => !!option.affectsProgramStructure); +export const optionsAffectingProgramStructure: readonly CommandLineOption[] = optionDeclarations.filter(option => + !!option.affectsProgramStructure +); /** @internal */ -export const transpileOptionValueCompilerOptions: readonly CommandLineOption[] = optionDeclarations.filter(option => hasProperty(option, "transpileOptionValue")); +export const transpileOptionValueCompilerOptions: readonly CommandLineOption[] = optionDeclarations.filter(option => + hasProperty(option, "transpileOptionValue") +); // Build related options /** @internal */ @@ -1692,9 +1734,14 @@ export function createCompilerDiagnosticForInvalidCustomType(opt: CommandLineOpt return createDiagnosticForInvalidCustomType(opt, createCompilerDiagnostic); } -function createDiagnosticForInvalidCustomType(opt: CommandLineOptionOfCustomType, createDiagnostic: (message: DiagnosticMessage, ...args: DiagnosticArguments) => Diagnostic): Diagnostic { +function createDiagnosticForInvalidCustomType( + opt: CommandLineOptionOfCustomType, + createDiagnostic: (message: DiagnosticMessage, ...args: DiagnosticArguments) => Diagnostic, +): Diagnostic { const namesOfType = arrayFrom(opt.type.keys()); - const stringNames = (opt.deprecatedKeys ? namesOfType.filter(k => !opt.deprecatedKeys!.has(k)) : namesOfType).map(key => `'${key}'`).join(", "); + const stringNames = (opt.deprecatedKeys ? namesOfType.filter(k => !opt.deprecatedKeys!.has(k)) : namesOfType).map( + key => `'${key}'`, + ).join(", "); return createDiagnostic(Diagnostics.Argument_for_0_option_must_be_Colon_1, `--${opt.name}`, stringNames); } @@ -1704,7 +1751,11 @@ export function parseCustomTypeOption(opt: CommandLineOptionOfCustomType, value: } /** @internal */ -export function parseListTypeOption(opt: CommandLineOptionOfListType, value = "", errors: Diagnostic[]): string | (string | number)[] | undefined { +export function parseListTypeOption( + opt: CommandLineOptionOfListType, + value = "", + errors: Diagnostic[], +): string | (string | number)[] | undefined { value = trimString(value); if (startsWith(value, "-")) { return undefined; @@ -1725,7 +1776,10 @@ export function parseListTypeOption(opt: CommandLineOptionOfListType, value = "" case "object": return Debug.fail(`List of ${opt.element.type} is not yet supported.`); default: - return mapDefined(values, v => parseCustomTypeOption(opt.element as CommandLineOptionOfCustomType, v, errors)); + return mapDefined( + values, + v => parseCustomTypeOption(opt.element as CommandLineOptionOfCustomType, v, errors), + ); } } @@ -1752,13 +1806,29 @@ function createUnknownOptionError( sourceFile?: TsConfigSourceFile, ) { if (diagnostics.alternateMode?.getOptionsNameMap().optionsNameMap.has(unknownOption.toLowerCase())) { - return createDiagnosticForNodeInSourceFileOrCompilerDiagnostic(sourceFile, node, diagnostics.alternateMode.diagnostic, unknownOption); + return createDiagnosticForNodeInSourceFileOrCompilerDiagnostic( + sourceFile, + node, + diagnostics.alternateMode.diagnostic, + unknownOption, + ); } const possibleOption = getSpellingSuggestion(unknownOption, diagnostics.optionDeclarations, getOptionName); - return possibleOption ? - createDiagnosticForNodeInSourceFileOrCompilerDiagnostic(sourceFile, node, diagnostics.unknownDidYouMeanDiagnostic, unknownOptionErrorText || unknownOption, possibleOption.name) : - createDiagnosticForNodeInSourceFileOrCompilerDiagnostic(sourceFile, node, diagnostics.unknownOptionDiagnostic, unknownOptionErrorText || unknownOption); + return possibleOption + ? createDiagnosticForNodeInSourceFileOrCompilerDiagnostic( + sourceFile, + node, + diagnostics.unknownDidYouMeanDiagnostic, + unknownOptionErrorText || unknownOption, + possibleOption.name, + ) + : createDiagnosticForNodeInSourceFileOrCompilerDiagnostic( + sourceFile, + node, + diagnostics.unknownOptionDiagnostic, + unknownOptionErrorText || unknownOption, + ); } /** @internal */ @@ -1790,14 +1860,29 @@ export function parseCommandLineWorker( } else if (s.charCodeAt(0) === CharacterCodes.minus) { const inputOptionName = s.slice(s.charCodeAt(1) === CharacterCodes.minus ? 2 : 1); - const opt = getOptionDeclarationFromName(diagnostics.getOptionsNameMap, inputOptionName, /*allowShort*/ true); + const opt = getOptionDeclarationFromName( + diagnostics.getOptionsNameMap, + inputOptionName, + /*allowShort*/ true, + ); if (opt) { i = parseOptionValue(args, i, diagnostics, opt, options, errors); } else { - const watchOpt = getOptionDeclarationFromName(watchOptionsDidYouMeanDiagnostics.getOptionsNameMap, inputOptionName, /*allowShort*/ true); + const watchOpt = getOptionDeclarationFromName( + watchOptionsDidYouMeanDiagnostics.getOptionsNameMap, + inputOptionName, + /*allowShort*/ true, + ); if (watchOpt) { - i = parseOptionValue(args, i, watchOptionsDidYouMeanDiagnostics, watchOpt, watchOptions || (watchOptions = {}), errors); + i = parseOptionValue( + args, + i, + watchOptionsDidYouMeanDiagnostics, + watchOpt, + watchOptions || (watchOptions = {}), + errors, + ); } else { errors.push(createUnknownOptionError(inputOptionName, diagnostics, s)); @@ -1831,7 +1916,9 @@ export function parseCommandLineWorker( pos++; } else { - errors.push(createCompilerDiagnostic(Diagnostics.Unterminated_quoted_string_in_response_file_0, fileName)); + errors.push( + createCompilerDiagnostic(Diagnostics.Unterminated_quoted_string_in_response_file_0, fileName), + ); } } else { @@ -1864,18 +1951,35 @@ function parseOptionValue( } else { if (optValue === "true") i++; - errors.push(createCompilerDiagnostic(Diagnostics.Option_0_can_only_be_specified_in_tsconfig_json_file_or_set_to_false_or_null_on_command_line, opt.name)); + errors.push( + createCompilerDiagnostic( + Diagnostics + .Option_0_can_only_be_specified_in_tsconfig_json_file_or_set_to_false_or_null_on_command_line, + opt.name, + ), + ); } } else { - errors.push(createCompilerDiagnostic(Diagnostics.Option_0_can_only_be_specified_in_tsconfig_json_file_or_set_to_null_on_command_line, opt.name)); + errors.push( + createCompilerDiagnostic( + Diagnostics.Option_0_can_only_be_specified_in_tsconfig_json_file_or_set_to_null_on_command_line, + opt.name, + ), + ); if (optValue && !startsWith(optValue, "-")) i++; } } else { // Check to see if no argument was provided (e.g. "--locale" is the last command-line argument). if (!args[i] && opt.type !== "boolean") { - errors.push(createCompilerDiagnostic(diagnostics.optionTypeMismatchDiagnostic, opt.name, getCompilerOptionValueTypeString(opt))); + errors.push( + createCompilerDiagnostic( + diagnostics.optionTypeMismatchDiagnostic, + opt.name, + getCompilerOptionValueTypeString(opt), + ), + ); } if (args[i] !== "null") { @@ -1931,7 +2035,10 @@ export const compilerOptionsDidYouMeanDiagnostics: ParseCommandLineWorkerDiagnos unknownDidYouMeanDiagnostic: Diagnostics.Unknown_compiler_option_0_Did_you_mean_1, optionTypeMismatchDiagnostic: Diagnostics.Compiler_option_0_expects_an_argument, }; -export function parseCommandLine(commandLine: readonly string[], readFile?: (path: string) => string | undefined): ParsedCommandLine { +export function parseCommandLine( + commandLine: readonly string[], + readFile?: (path: string) => string | undefined, +): ParsedCommandLine { return parseCommandLineWorker(compilerOptionsDidYouMeanDiagnostics, commandLine, readFile); } @@ -1940,7 +2047,11 @@ export function getOptionFromName(optionName: string, allowShort?: boolean): Com return getOptionDeclarationFromName(getOptionsNameMap, optionName, allowShort); } -function getOptionDeclarationFromName(getOptionNameMap: () => OptionsNameMap, optionName: string, allowShort = false): CommandLineOption | undefined { +function getOptionDeclarationFromName( + getOptionNameMap: () => OptionsNameMap, + optionName: string, + allowShort = false, +): CommandLineOption | undefined { optionName = optionName.toLowerCase(); const { optionsNameMap, shortOptionNames } = getOptionNameMap(); // Try to translate short option names to their full equivalents. @@ -2073,9 +2184,13 @@ export function getParsedCommandLineOfConfigFile( * Read tsconfig.json file * @param fileName The path to the config file */ -export function readConfigFile(fileName: string, readFile: (path: string) => string | undefined): { config?: any; error?: Diagnostic; } { +export function readConfigFile( + fileName: string, + readFile: (path: string) => string | undefined, +): { config?: any; error?: Diagnostic; } { const textOrDiagnostic = tryReadFile(fileName, readFile); - return isString(textOrDiagnostic) ? parseConfigFileTextToJson(fileName, textOrDiagnostic) : { config: {}, error: textOrDiagnostic }; + return isString(textOrDiagnostic) ? parseConfigFileTextToJson(fileName, textOrDiagnostic) + : { config: {}, error: textOrDiagnostic }; } /** @@ -2086,7 +2201,11 @@ export function readConfigFile(fileName: string, readFile: (path: string) => str export function parseConfigFileTextToJson(fileName: string, jsonText: string): { config?: any; error?: Diagnostic; } { const jsonSourceFile = parseJsonText(fileName, jsonText); return { - config: convertConfigFileToObject(jsonSourceFile, jsonSourceFile.parseDiagnostics, /*jsonConversionNotifier*/ undefined), + config: convertConfigFileToObject( + jsonSourceFile, + jsonSourceFile.parseDiagnostics, + /*jsonConversionNotifier*/ undefined, + ), error: jsonSourceFile.parseDiagnostics.length ? jsonSourceFile.parseDiagnostics[0] : undefined, }; } @@ -2095,9 +2214,13 @@ export function parseConfigFileTextToJson(fileName: string, jsonText: string): { * Read tsconfig.json file * @param fileName The path to the config file */ -export function readJsonConfigFile(fileName: string, readFile: (path: string) => string | undefined): TsConfigSourceFile { +export function readJsonConfigFile( + fileName: string, + readFile: (path: string) => string | undefined, +): TsConfigSourceFile { const textOrDiagnostic = tryReadFile(fileName, readFile); - return isString(textOrDiagnostic) ? parseJsonText(fileName, textOrDiagnostic) : { fileName, parseDiagnostics: [textOrDiagnostic] } as TsConfigSourceFile; + return isString(textOrDiagnostic) ? parseJsonText(fileName, textOrDiagnostic) + : { fileName, parseDiagnostics: [textOrDiagnostic] } as TsConfigSourceFile; } /** @internal */ @@ -2136,15 +2259,18 @@ const watchOptionsDidYouMeanDiagnostics: ParseCommandLineWorkerDiagnostics = { let commandLineCompilerOptionsMapCache: Map; function getCommandLineCompilerOptionsMap() { - return commandLineCompilerOptionsMapCache || (commandLineCompilerOptionsMapCache = commandLineOptionsToMap(optionDeclarations)); + return commandLineCompilerOptionsMapCache + || (commandLineCompilerOptionsMapCache = commandLineOptionsToMap(optionDeclarations)); } let commandLineWatchOptionsMapCache: Map; function getCommandLineWatchOptionsMap() { - return commandLineWatchOptionsMapCache || (commandLineWatchOptionsMapCache = commandLineOptionsToMap(optionsForWatch)); + return commandLineWatchOptionsMapCache + || (commandLineWatchOptionsMapCache = commandLineOptionsToMap(optionsForWatch)); } let commandLineTypeAcquisitionMapCache: Map; function getCommandLineTypeAcquisitionMap() { - return commandLineTypeAcquisitionMapCache || (commandLineTypeAcquisitionMapCache = commandLineOptionsToMap(typeAcquisitionDeclarations)); + return commandLineTypeAcquisitionMapCache + || (commandLineTypeAcquisitionMapCache = commandLineOptionsToMap(typeAcquisitionDeclarations)); } const extendsOptionDeclaration: CommandLineOptionOfListType = { @@ -2212,7 +2338,8 @@ function getTsconfigRootOptionsMap() { type: "string", }, category: Diagnostics.File_Management, - defaultValueDescription: Diagnostics.if_files_is_specified_otherwise_Asterisk_Asterisk_Slash_Asterisk, + defaultValueDescription: + Diagnostics.if_files_is_specified_otherwise_Asterisk_Asterisk_Slash_Asterisk, }, { name: "exclude", @@ -2222,7 +2349,8 @@ function getTsconfigRootOptionsMap() { type: "string", }, category: Diagnostics.File_Management, - defaultValueDescription: Diagnostics.node_modules_bower_components_jspm_packages_plus_the_value_of_outDir_if_one_is_specified, + defaultValueDescription: Diagnostics + .node_modules_bower_components_jspm_packages_plus_the_value_of_outDir_if_one_is_specified, }, compileOnSaveCommandLineOption, ]), @@ -2274,7 +2402,13 @@ function convertConfigFileToObject( * Convert the json syntax tree into the json value */ export function convertToObject(sourceFile: JsonSourceFile, errors: Diagnostic[]): any { - return convertToJson(sourceFile, sourceFile.statements[0]?.expression, errors, /*returnValue*/ true, /*jsonConversionNotifier*/ undefined); + return convertToJson( + sourceFile, + sourceFile.statements[0]?.expression, + errors, + /*returnValue*/ true, + /*jsonConversionNotifier*/ undefined, + ); } /** @@ -2304,15 +2438,30 @@ export function convertToJson( const result: any = returnValue ? {} : undefined; for (const element of node.properties) { if (element.kind !== SyntaxKind.PropertyAssignment) { - errors.push(createDiagnosticForNodeInSourceFile(sourceFile, element, Diagnostics.Property_assignment_expected)); + errors.push( + createDiagnosticForNodeInSourceFile(sourceFile, element, Diagnostics.Property_assignment_expected), + ); continue; } if (element.questionToken) { - errors.push(createDiagnosticForNodeInSourceFile(sourceFile, element.questionToken, Diagnostics.The_0_modifier_can_only_be_used_in_TypeScript_files, "?")); + errors.push( + createDiagnosticForNodeInSourceFile( + sourceFile, + element.questionToken, + Diagnostics.The_0_modifier_can_only_be_used_in_TypeScript_files, + "?", + ), + ); } if (!isDoubleQuotedString(element.name)) { - errors.push(createDiagnosticForNodeInSourceFile(sourceFile, element.name, Diagnostics.String_literal_with_double_quotes_expected)); + errors.push( + createDiagnosticForNodeInSourceFile( + sourceFile, + element.name, + Diagnostics.String_literal_with_double_quotes_expected, + ), + ); } const textOfKey = isComputedNonLiteralName(element.name) ? undefined : getTextOfPropertyName(element.name); @@ -2341,7 +2490,10 @@ export function convertToJson( } // Filter out invalid values - return filter(elements.map(element => convertPropertyValueToJson(element, elementOption)), v => v !== undefined); + return filter( + elements.map(element => convertPropertyValueToJson(element, elementOption)), + v => v !== undefined, + ); } function convertPropertyValueToJson(valueExpression: Expression, option: CommandLineOption | undefined): any { @@ -2357,7 +2509,13 @@ export function convertToJson( case SyntaxKind.StringLiteral: if (!isDoubleQuotedString(valueExpression)) { - errors.push(createDiagnosticForNodeInSourceFile(sourceFile, valueExpression, Diagnostics.String_literal_with_double_quotes_expected)); + errors.push( + createDiagnosticForNodeInSourceFile( + sourceFile, + valueExpression, + Diagnostics.String_literal_with_double_quotes_expected, + ), + ); } return (valueExpression as StringLiteral).text; @@ -2365,7 +2523,10 @@ export function convertToJson( return Number((valueExpression as NumericLiteral).text); case SyntaxKind.PrefixUnaryExpression: - if ((valueExpression as PrefixUnaryExpression).operator !== SyntaxKind.MinusToken || (valueExpression as PrefixUnaryExpression).operand.kind !== SyntaxKind.NumericLiteral) { + if ( + (valueExpression as PrefixUnaryExpression).operator !== SyntaxKind.MinusToken + || (valueExpression as PrefixUnaryExpression).operand.kind !== SyntaxKind.NumericLiteral + ) { break; // not valid JSON syntax } return -Number(((valueExpression as PrefixUnaryExpression).operand as NumericLiteral).text); @@ -2390,10 +2551,25 @@ export function convertToJson( // Not in expected format if (option) { - errors.push(createDiagnosticForNodeInSourceFile(sourceFile, valueExpression, Diagnostics.Compiler_option_0_requires_a_value_of_type_1, option.name, getCompilerOptionValueTypeString(option))); + errors.push( + createDiagnosticForNodeInSourceFile( + sourceFile, + valueExpression, + Diagnostics.Compiler_option_0_requires_a_value_of_type_1, + option.name, + getCompilerOptionValueTypeString(option), + ), + ); } else { - errors.push(createDiagnosticForNodeInSourceFile(sourceFile, valueExpression, Diagnostics.Property_value_can_only_be_string_literal_numeric_literal_true_false_null_object_literal_or_array_literal)); + errors.push( + createDiagnosticForNodeInSourceFile( + sourceFile, + valueExpression, + Diagnostics + .Property_value_can_only_be_string_literal_numeric_literal_true_false_null_object_literal_or_array_literal, + ), + ); } return undefined; @@ -2405,11 +2581,11 @@ export function convertToJson( } function getCompilerOptionValueTypeString(option: CommandLineOption): string { - return (option.type === "listOrElement") ? - `${getCompilerOptionValueTypeString(option.element)} or Array` : - option.type === "list" ? - "Array" : - isString(option.type) ? option.type : "string"; + return (option.type === "listOrElement") + ? `${getCompilerOptionValueTypeString(option.element)} or Array` + : option.type === "list" + ? "Array" + : isString(option.type) ? option.type : "string"; } function isCompilerOptionsValue(option: CommandLineOption | undefined, value: any): value is CompilerOptionsValue { @@ -2451,7 +2627,11 @@ export interface ConvertToTSConfigHost { * * @internal */ -export function convertToTSConfig(configParseResult: ParsedCommandLine, configFileName: string, host: ConvertToTSConfigHost): TSConfig { +export function convertToTSConfig( + configParseResult: ParsedCommandLine, + configFileName: string, + host: ConvertToTSConfigHost, +): TSConfig { const getCanonicalFileName = createGetCanonicalFileName(host.useCaseSensitiveFileNames); const files = map( filter( @@ -2463,9 +2643,16 @@ export function convertToTSConfig(configParseResult: ParsedCommandLine, configFi host, ), ), - f => getRelativePathFromFile(getNormalizedAbsolutePath(configFileName, host.getCurrentDirectory()), getNormalizedAbsolutePath(f, host.getCurrentDirectory()), getCanonicalFileName), + f => getRelativePathFromFile( + getNormalizedAbsolutePath(configFileName, host.getCurrentDirectory()), + getNormalizedAbsolutePath(f, host.getCurrentDirectory()), + getCanonicalFileName, + ), ); - const optionMap = serializeCompilerOptions(configParseResult.options, { configFilePath: getNormalizedAbsolutePath(configFileName, host.getCurrentDirectory()), useCaseSensitiveFileNames: host.useCaseSensitiveFileNames }); + const optionMap = serializeCompilerOptions(configParseResult.options, { + configFilePath: getNormalizedAbsolutePath(configFileName, host.getCurrentDirectory()), + useCaseSensitiveFileNames: host.useCaseSensitiveFileNames, + }); const watchOptionMap = configParseResult.watchOptions && serializeWatchOptions(configParseResult.watchOptions); const config = { compilerOptions: { @@ -2482,10 +2669,15 @@ export function convertToTSConfig(configParseResult: ParsedCommandLine, configFi version: undefined, }, watchOptions: watchOptionMap && optionMapToObject(watchOptionMap), - references: map(configParseResult.projectReferences, r => ({ ...r, path: r.originalPath ? r.originalPath : "", originalPath: undefined })), + references: map( + configParseResult.projectReferences, + r => ({ ...r, path: r.originalPath ? r.originalPath : "", originalPath: undefined }), + ), files: length(files) ? files : undefined, ...(configParseResult.options.configFile?.configFileSpecs ? { - include: filterSameAsDefaultInclude(configParseResult.options.configFile.configFileSpecs.validatedIncludeSpecs), + include: filterSameAsDefaultInclude( + configParseResult.options.configFile.configFileSpecs.validatedIncludeSpecs, + ), exclude: configParseResult.options.configFile.configFileSpecs.validatedExcludeSpecs, } : {}), compileOnSave: !!configParseResult.compileOnSave ? true : undefined, @@ -2507,11 +2699,24 @@ function filterSameAsDefaultInclude(specs: readonly string[] | undefined) { return specs; } -function matchesSpecs(path: string, includeSpecs: readonly string[] | undefined, excludeSpecs: readonly string[] | undefined, host: ConvertToTSConfigHost): (path: string) => boolean { +function matchesSpecs( + path: string, + includeSpecs: readonly string[] | undefined, + excludeSpecs: readonly string[] | undefined, + host: ConvertToTSConfigHost, +): (path: string) => boolean { if (!includeSpecs) return returnTrue; - const patterns = getFileMatcherPatterns(path, excludeSpecs, includeSpecs, host.useCaseSensitiveFileNames, host.getCurrentDirectory()); - const excludeRe = patterns.excludePattern && getRegexFromPattern(patterns.excludePattern, host.useCaseSensitiveFileNames); - const includeRe = patterns.includeFilePattern && getRegexFromPattern(patterns.includeFilePattern, host.useCaseSensitiveFileNames); + const patterns = getFileMatcherPatterns( + path, + excludeSpecs, + includeSpecs, + host.useCaseSensitiveFileNames, + host.getCurrentDirectory(), + ); + const excludeRe = patterns.excludePattern + && getRegexFromPattern(patterns.excludePattern, host.useCaseSensitiveFileNames); + const includeRe = patterns.includeFilePattern + && getRegexFromPattern(patterns.includeFilePattern, host.useCaseSensitiveFileNames); if (includeRe) { if (excludeRe) { return path => !(includeRe.test(path) && !excludeRe.test(path)); @@ -2524,7 +2729,9 @@ function matchesSpecs(path: string, includeSpecs: readonly string[] | undefined, return returnTrue; } -function getCustomTypeMapOfCommandLineOption(optionDefinition: CommandLineOption): Map | undefined { +function getCustomTypeMapOfCommandLineOption( + optionDefinition: CommandLineOption, +): Map | undefined { switch (optionDefinition.type) { case "string": case "number": @@ -2541,7 +2748,10 @@ function getCustomTypeMapOfCommandLineOption(optionDefinition: CommandLineOption } /** @internal */ -export function getNameOfCompilerOptionValue(value: CompilerOptionsValue, customTypeMap: Map): string | undefined { +export function getNameOfCompilerOptionValue( + value: CompilerOptionsValue, + customTypeMap: Map, +): string | undefined { // There is a typeMap associated with this command-line option so use it to map value back to its name return forEachEntry(customTypeMap, (mapValue, key) => { if (mapValue === value) { @@ -2574,7 +2784,11 @@ function serializeOptionBaseObject( if (hasProperty(options, name)) { // tsconfig only options cannot be specified via command line, // so we can assume that only types that can appear here string | number | boolean - if (optionsNameMap.has(name) && (optionsNameMap.get(name)!.category === Diagnostics.Command_line_Options || optionsNameMap.get(name)!.category === Diagnostics.Output_Formatting)) { + if ( + optionsNameMap.has(name) + && (optionsNameMap.get(name)!.category === Diagnostics.Command_line_Options + || optionsNameMap.get(name)!.category === Diagnostics.Output_Formatting) + ) { continue; } const value = options[name] as CompilerOptionsValue; @@ -2586,7 +2800,17 @@ function serializeOptionBaseObject( // There is no map associated with this compiler option then use the value as-is // This is the case if the value is expect to be string, number, boolean or list of string if (pathOptions && optionDefinition.isFilePath) { - result.set(name, getRelativePathFromFile(pathOptions.configFilePath, getNormalizedAbsolutePath(value as string, getDirectoryPath(pathOptions.configFilePath)), getCanonicalFileName!)); + result.set( + name, + getRelativePathFromFile( + pathOptions.configFilePath, + getNormalizedAbsolutePath( + value as string, + getDirectoryPath(pathOptions.configFilePath), + ), + getCanonicalFileName!, + ), + ); } else { result.set(name, value); @@ -2594,7 +2818,12 @@ function serializeOptionBaseObject( } else { if (optionDefinition.type === "list") { - result.set(name, (value as readonly (string | number)[]).map(element => getNameOfCompilerOptionValue(element, customTypeMap)!)); // TODO: GH#18217 + result.set( + name, + (value as readonly (string | number)[]).map(element => + getNameOfCompilerOptionValue(element, customTypeMap)! + ), + ); // TODO: GH#18217 } else { // There is a typeMap associated with this command-line option so use it to map value back to its name @@ -2665,8 +2894,16 @@ export function generateTSConfig(options: CompilerOptions, fileNames: readonly s function isAllowedOptionForOutput({ category, name, isCommandLineOnly }: CommandLineOption): boolean { // Skip options which do not have a category or have categories which are more niche - const categoriesToSkip = [Diagnostics.Command_line_Options, Diagnostics.Editor_Support, Diagnostics.Compiler_Diagnostics, Diagnostics.Backwards_Compatibility, Diagnostics.Watch_and_Build_Modes, Diagnostics.Output_Formatting]; - return !isCommandLineOnly && category !== undefined && (!categoriesToSkip.includes(category) || compilerOptionsMap.has(name)); + const categoriesToSkip = [ + Diagnostics.Command_line_Options, + Diagnostics.Editor_Support, + Diagnostics.Compiler_Diagnostics, + Diagnostics.Backwards_Compatibility, + Diagnostics.Watch_and_Build_Modes, + Diagnostics.Output_Formatting, + ]; + return !isCommandLineOnly && category !== undefined + && (!categoriesToSkip.includes(category) || compilerOptionsMap.has(name)); } function writeConfigurations() { @@ -2701,14 +2938,18 @@ export function generateTSConfig(options: CompilerOptions, fileNames: readonly s for (const option of options) { let optionName; if (compilerOptionsMap.has(option.name)) { - optionName = `"${option.name}": ${JSON.stringify(compilerOptionsMap.get(option.name))}${(seenKnownKeys += 1) === compilerOptionsMap.size ? "" : ","}`; + optionName = `"${option.name}": ${JSON.stringify(compilerOptionsMap.get(option.name))}${ + (seenKnownKeys += 1) === compilerOptionsMap.size ? "" : "," + }`; } else { optionName = `// "${option.name}": ${JSON.stringify(getDefaultValueForOption(option))},`; } entries.push({ value: optionName, - description: `/* ${option.description && getLocaleSpecificMessage(option.description) || option.name} */`, + description: `/* ${ + option.description && getLocaleSpecificMessage(option.description) || option.name + } */`, }); marginLength = Math.max(optionName.length, marginLength); } @@ -2719,12 +2960,23 @@ export function generateTSConfig(options: CompilerOptions, fileNames: readonly s const result: string[] = []; result.push(`{`); result.push(`${tab}"compilerOptions": {`); - result.push(`${tab}${tab}/* ${getLocaleSpecificMessage(Diagnostics.Visit_https_Colon_Slash_Slashaka_ms_Slashtsconfig_to_read_more_about_this_file)} */`); + result.push( + `${tab}${tab}/* ${ + getLocaleSpecificMessage( + Diagnostics.Visit_https_Colon_Slash_Slashaka_ms_Slashtsconfig_to_read_more_about_this_file, + ) + } */`, + ); result.push(""); // Print out each row, aligning all the descriptions on the same column. for (const entry of entries) { const { value, description = "" } = entry; - result.push(value && `${tab}${tab}${value}${description && (makePadding(marginLength - value.length + 2) + description)}`); + result.push( + value + && `${tab}${tab}${value}${ + description && (makePadding(marginLength - value.length + 2) + description) + }`, + ); } if (fileNames.length) { result.push(`${tab}},`); @@ -2763,7 +3015,11 @@ export function convertToOptionsWithAbsolutePaths(options: CompilerOptions, toAb return result; } -function convertToOptionValueWithAbsolutePaths(option: CommandLineOption | undefined, value: CompilerOptionsValue, toAbsolutePath: (path: string) => string) { +function convertToOptionValueWithAbsolutePaths( + option: CommandLineOption | undefined, + value: CompilerOptionsValue, + toAbsolutePath: (path: string) => string, +) { if (option && !isNullOrUndefined(value)) { if (option.type === "list") { const values = value as readonly string[]; @@ -2786,8 +3042,29 @@ function convertToOptionValueWithAbsolutePaths(option: CommandLineOption | undef * @param basePath A root directory to resolve relative path entries in the config * file to. e.g. outDir */ -export function parseJsonConfigFileContent(json: any, host: ParseConfigHost, basePath: string, existingOptions?: CompilerOptions, configFileName?: string, resolutionStack?: Path[], extraFileExtensions?: readonly FileExtensionInfo[], extendedConfigCache?: Map, existingWatchOptions?: WatchOptions): ParsedCommandLine { - return parseJsonConfigFileContentWorker(json, /*sourceFile*/ undefined, host, basePath, existingOptions, existingWatchOptions, configFileName, resolutionStack, extraFileExtensions, extendedConfigCache); +export function parseJsonConfigFileContent( + json: any, + host: ParseConfigHost, + basePath: string, + existingOptions?: CompilerOptions, + configFileName?: string, + resolutionStack?: Path[], + extraFileExtensions?: readonly FileExtensionInfo[], + extendedConfigCache?: Map, + existingWatchOptions?: WatchOptions, +): ParsedCommandLine { + return parseJsonConfigFileContentWorker( + json, + /*sourceFile*/ undefined, + host, + basePath, + existingOptions, + existingWatchOptions, + configFileName, + resolutionStack, + extraFileExtensions, + extendedConfigCache, + ); } /** @@ -2797,9 +3074,30 @@ export function parseJsonConfigFileContent(json: any, host: ParseConfigHost, bas * @param basePath A root directory to resolve relative path entries in the config * file to. e.g. outDir */ -export function parseJsonSourceFileConfigFileContent(sourceFile: TsConfigSourceFile, host: ParseConfigHost, basePath: string, existingOptions?: CompilerOptions, configFileName?: string, resolutionStack?: Path[], extraFileExtensions?: readonly FileExtensionInfo[], extendedConfigCache?: Map, existingWatchOptions?: WatchOptions): ParsedCommandLine { +export function parseJsonSourceFileConfigFileContent( + sourceFile: TsConfigSourceFile, + host: ParseConfigHost, + basePath: string, + existingOptions?: CompilerOptions, + configFileName?: string, + resolutionStack?: Path[], + extraFileExtensions?: readonly FileExtensionInfo[], + extendedConfigCache?: Map, + existingWatchOptions?: WatchOptions, +): ParsedCommandLine { tracing?.push(tracing.Phase.Parse, "parseJsonSourceFileConfigFileContent", { path: sourceFile.fileName }); - const result = parseJsonConfigFileContentWorker(/*json*/ undefined, sourceFile, host, basePath, existingOptions, existingWatchOptions, configFileName, resolutionStack, extraFileExtensions, extendedConfigCache); + const result = parseJsonConfigFileContentWorker( + /*json*/ undefined, + sourceFile, + host, + basePath, + existingOptions, + existingWatchOptions, + configFileName, + resolutionStack, + extraFileExtensions, + extendedConfigCache, + ); tracing?.pop(); return result; } @@ -2848,19 +3146,30 @@ function parseJsonConfigFileContentWorker( Debug.assert((json === undefined && sourceFile !== undefined) || (json !== undefined && sourceFile === undefined)); const errors: Diagnostic[] = []; - const parsedConfig = parseConfig(json, sourceFile, host, basePath, configFileName, resolutionStack, errors, extendedConfigCache); + const parsedConfig = parseConfig( + json, + sourceFile, + host, + basePath, + configFileName, + resolutionStack, + errors, + extendedConfigCache, + ); const { raw } = parsedConfig; const options = extend(existingOptions, parsedConfig.options || {}); - const watchOptions = existingWatchOptions && parsedConfig.watchOptions ? - extend(existingWatchOptions, parsedConfig.watchOptions) : - parsedConfig.watchOptions || existingWatchOptions; + const watchOptions = existingWatchOptions && parsedConfig.watchOptions + ? extend(existingWatchOptions, parsedConfig.watchOptions) + : parsedConfig.watchOptions || existingWatchOptions; options.configFilePath = configFileName && normalizeSlashes(configFileName); const configFileSpecs = getConfigFileSpecs(); if (sourceFile) sourceFile.configFileSpecs = configFileSpecs; setConfigFileInOptions(options, sourceFile); - const basePathForFileNames = normalizePath(configFileName ? directoryOfCombinedPath(configFileName, basePath) : basePath); + const basePathForFileNames = normalizePath( + configFileName ? directoryOfCombinedPath(configFileName, basePath) : basePath, + ); return { options, watchOptions, @@ -2873,26 +3182,43 @@ function parseJsonConfigFileContentWorker( // file map that marks whether it was a regular wildcard match (with a `*` or `?` token), // or a recursive directory. This information is used by filesystem watchers to monitor for // new entries in these paths. - wildcardDirectories: getWildcardDirectories(configFileSpecs, basePathForFileNames, host.useCaseSensitiveFileNames), + wildcardDirectories: getWildcardDirectories( + configFileSpecs, + basePathForFileNames, + host.useCaseSensitiveFileNames, + ), compileOnSave: !!raw.compileOnSave, }; function getConfigFileSpecs(): ConfigFileSpecs { - const referencesOfRaw = getPropFromRaw("references", element => typeof element === "object", "object"); + const referencesOfRaw = getPropFromRaw( + "references", + element => typeof element === "object", + "object", + ); const filesSpecs = toPropValue(getSpecsFromRaw("files")); if (filesSpecs) { - const hasZeroOrNoReferences = referencesOfRaw === "no-prop" || isArray(referencesOfRaw) && referencesOfRaw.length === 0; + const hasZeroOrNoReferences = referencesOfRaw === "no-prop" + || isArray(referencesOfRaw) && referencesOfRaw.length === 0; const hasExtends = hasProperty(raw, "extends"); if (filesSpecs.length === 0 && hasZeroOrNoReferences && !hasExtends) { if (sourceFile) { const fileName = configFileName || "tsconfig.json"; const diagnosticMessage = Diagnostics.The_files_list_in_config_file_0_is_empty; const nodeValue = forEachTsConfigPropArray(sourceFile, "files", property => property.initializer); - const error = createDiagnosticForNodeInSourceFileOrCompilerDiagnostic(sourceFile, nodeValue, diagnosticMessage, fileName); + const error = createDiagnosticForNodeInSourceFileOrCompilerDiagnostic( + sourceFile, + nodeValue, + diagnosticMessage, + fileName, + ); errors.push(error); } else { - createCompilerDiagnosticOnlyIfJson(Diagnostics.The_files_list_in_config_file_0_is_empty, configFileName || "tsconfig.json"); + createCompilerDiagnosticOnlyIfJson( + Diagnostics.The_files_list_in_config_file_0_is_empty, + configFileName || "tsconfig.json", + ); } } } @@ -2922,11 +3248,23 @@ function parseJsonConfigFileContentWorker( // file system. if (includeSpecs) { - validatedIncludeSpecs = validateSpecs(includeSpecs, errors, /*disallowTrailingRecursion*/ true, sourceFile, "include"); + validatedIncludeSpecs = validateSpecs( + includeSpecs, + errors, + /*disallowTrailingRecursion*/ true, + sourceFile, + "include", + ); } if (excludeSpecs) { - validatedExcludeSpecs = validateSpecs(excludeSpecs, errors, /*disallowTrailingRecursion*/ false, sourceFile, "exclude"); + validatedExcludeSpecs = validateSpecs( + excludeSpecs, + errors, + /*disallowTrailingRecursion*/ false, + sourceFile, + "exclude", + ); } return { @@ -2951,11 +3289,19 @@ function parseJsonConfigFileContentWorker( function getProjectReferences(basePath: string): readonly ProjectReference[] | undefined { let projectReferences: ProjectReference[] | undefined; - const referencesOfRaw = getPropFromRaw("references", element => typeof element === "object", "object"); + const referencesOfRaw = getPropFromRaw( + "references", + element => typeof element === "object", + "object", + ); if (isArray(referencesOfRaw)) { for (const ref of referencesOfRaw) { if (typeof ref.path !== "string") { - createCompilerDiagnosticOnlyIfJson(Diagnostics.Compiler_option_0_requires_a_value_of_type_1, "reference.path", "string"); + createCompilerDiagnosticOnlyIfJson( + Diagnostics.Compiler_option_0_requires_a_value_of_type_1, + "reference.path", + "string", + ); } else { (projectReferences || (projectReferences = [])).push({ @@ -2979,17 +3325,31 @@ function parseJsonConfigFileContentWorker( return getPropFromRaw(prop, isString, "string"); } - function getPropFromRaw(prop: "files" | "include" | "exclude" | "references", validateElement: (value: unknown) => boolean, elementTypeName: string): PropOfRaw { + function getPropFromRaw( + prop: "files" | "include" | "exclude" | "references", + validateElement: (value: unknown) => boolean, + elementTypeName: string, + ): PropOfRaw { if (hasProperty(raw, prop) && !isNullOrUndefined(raw[prop])) { if (isArray(raw[prop])) { const result = raw[prop] as T[]; if (!sourceFile && !every(result, validateElement)) { - errors.push(createCompilerDiagnostic(Diagnostics.Compiler_option_0_requires_a_value_of_type_1, prop, elementTypeName)); + errors.push( + createCompilerDiagnostic( + Diagnostics.Compiler_option_0_requires_a_value_of_type_1, + prop, + elementTypeName, + ), + ); } return result; } else { - createCompilerDiagnosticOnlyIfJson(Diagnostics.Compiler_option_0_requires_a_value_of_type_1, prop, "Array"); + createCompilerDiagnosticOnlyIfJson( + Diagnostics.Compiler_option_0_requires_a_value_of_type_1, + prop, + "Array", + ); return "not-array"; } } @@ -3004,7 +3364,9 @@ function parseJsonConfigFileContentWorker( } function isErrorNoInputFiles(error: Diagnostic) { - return error.code === Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2.code; + return error.code + === Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2 + .code; } function getErrorForNoInputFiles({ includeSpecs, excludeSpecs }: ConfigFileSpecs, configFileName: string | undefined) { @@ -3026,7 +3388,13 @@ export function canJsonReportNoInputFiles(raw: any) { } /** @internal */ -export function updateErrorForNoInputFiles(fileNames: string[], configFileName: string, configFileSpecs: ConfigFileSpecs, configParseDiagnostics: Diagnostic[], canJsonReportNoInutFiles: boolean) { +export function updateErrorForNoInputFiles( + fileNames: string[], + configFileName: string, + configFileSpecs: ConfigFileSpecs, + configParseDiagnostics: Diagnostic[], + canJsonReportNoInutFiles: boolean, +) { const existingErrors = configParseDiagnostics.length; if (shouldReportNoInputFiles(fileNames, canJsonReportNoInutFiles)) { configParseDiagnostics.push(getErrorForNoInputFiles(configFileSpecs, configFileName)); @@ -3079,13 +3447,18 @@ function parseConfig( const resolvedPath = getNormalizedAbsolutePath(configFileName || "", basePath); if (resolutionStack.indexOf(resolvedPath) >= 0) { - errors.push(createCompilerDiagnostic(Diagnostics.Circularity_detected_while_resolving_configuration_Colon_0, [...resolutionStack, resolvedPath].join(" -> "))); + errors.push( + createCompilerDiagnostic( + Diagnostics.Circularity_detected_while_resolving_configuration_Colon_0, + [...resolutionStack, resolvedPath].join(" -> "), + ), + ); return { raw: json || convertToObject(sourceFile!, errors) }; } - const ownConfig = json ? - parseOwnConfigOfJson(json, host, basePath, configFileName, errors) : - parseOwnConfigOfJsonSourceFile(sourceFile!, host, basePath, configFileName, errors); + const ownConfig = json + ? parseOwnConfigOfJson(json, host, basePath, configFileName, errors) + : parseOwnConfigOfJsonSourceFile(sourceFile!, host, basePath, configFileName, errors); if (ownConfig.options?.paths) { // If we end up needing to resolve relative paths from 'paths' relative to @@ -3107,28 +3480,47 @@ function parseConfig( if (!ownConfig.raw.include && result.include) ownConfig.raw.include = result.include; if (!ownConfig.raw.exclude && result.exclude) ownConfig.raw.exclude = result.exclude; if (!ownConfig.raw.files && result.files) ownConfig.raw.files = result.files; - if (ownConfig.raw.compileOnSave === undefined && result.compileOnSave) ownConfig.raw.compileOnSave = result.compileOnSave; - if (sourceFile && result.extendedSourceFiles) sourceFile.extendedSourceFiles = arrayFrom(result.extendedSourceFiles.keys()); + if (ownConfig.raw.compileOnSave === undefined && result.compileOnSave) { + ownConfig.raw.compileOnSave = result.compileOnSave; + } + if (sourceFile && result.extendedSourceFiles) { + sourceFile.extendedSourceFiles = arrayFrom(result.extendedSourceFiles.keys()); + } ownConfig.options = assign(result.options, ownConfig.options); - ownConfig.watchOptions = ownConfig.watchOptions && result.watchOptions ? - assign(result.watchOptions, ownConfig.watchOptions) : - ownConfig.watchOptions || result.watchOptions; + ownConfig.watchOptions = ownConfig.watchOptions && result.watchOptions + ? assign(result.watchOptions, ownConfig.watchOptions) + : ownConfig.watchOptions || result.watchOptions; } return ownConfig; function applyExtendedConfig(result: ExtendsResult, extendedConfigPath: string) { - const extendedConfig = getExtendedConfig(sourceFile, extendedConfigPath, host, resolutionStack, errors, extendedConfigCache, result); + const extendedConfig = getExtendedConfig( + sourceFile, + extendedConfigPath, + host, + resolutionStack, + errors, + extendedConfigCache, + result, + ); if (extendedConfig && isSuccessfulParsedTsconfig(extendedConfig)) { const extendsRaw = extendedConfig.raw; let relativeDifference: string | undefined; const setPropertyInResultIfNotUndefined = (propertyName: "include" | "exclude" | "files") => { if (extendsRaw[propertyName]) { - result[propertyName] = map(extendsRaw[propertyName], (path: string) => - isRootedDiskPath(path) ? path : combinePaths( - relativeDifference ||= convertToRelativePath(getDirectoryPath(extendedConfigPath), basePath, createGetCanonicalFileName(host.useCaseSensitiveFileNames)), - path, - )); + result[propertyName] = map( + extendsRaw[propertyName], + (path: string) => + isRootedDiskPath(path) ? path : combinePaths( + relativeDifference ||= convertToRelativePath( + getDirectoryPath(extendedConfigPath), + basePath, + createGetCanonicalFileName(host.useCaseSensitiveFileNames), + ), + path, + ), + ); } }; setPropertyInResultIfNotUndefined("include"); @@ -3138,9 +3530,9 @@ function parseConfig( result.compileOnSave = extendsRaw.compileOnSave; } assign(result.options, extendedConfig.options); - result.watchOptions = result.watchOptions && extendedConfig.watchOptions ? - assign({}, result.watchOptions, extendedConfig.watchOptions) : - result.watchOptions || extendedConfig.watchOptions; + result.watchOptions = result.watchOptions && extendedConfig.watchOptions + ? assign({}, result.watchOptions, extendedConfig.watchOptions) + : result.watchOptions || extendedConfig.watchOptions; // TODO extend type typeAcquisition } } @@ -3158,12 +3550,17 @@ function parseOwnConfigOfJson( } const options = convertCompilerOptionsFromJsonWorker(json.compilerOptions, basePath, errors, configFileName); - const typeAcquisition = convertTypeAcquisitionFromJsonWorker(json.typeAcquisition, basePath, errors, configFileName); + const typeAcquisition = convertTypeAcquisitionFromJsonWorker( + json.typeAcquisition, + basePath, + errors, + configFileName, + ); const watchOptions = convertWatchOptionsFromJsonWorker(json.watchOptions, basePath, errors); json.compileOnSave = convertCompileOnSaveOptionFromJson(json, basePath, errors); - const extendedConfigPath = json.extends || json.extends === "" ? - getExtendsConfigPathOrArray(json.extends, host, basePath, configFileName, errors) : - undefined; + const extendedConfigPath = json.extends || json.extends === "" + ? getExtendsConfigPathOrArray(json.extends, host, basePath, configFileName, errors) + : undefined; return { raw: json, options, watchOptions, typeAcquisition, extendedConfigPath }; } @@ -3207,12 +3604,28 @@ function getExtendsConfigPathOrArray( ); } else { - convertJsonOption(extendsOptionDeclaration.element, value, basePath, errors, propertyAssignment, (valueExpression as ArrayLiteralExpression | undefined)?.elements[index], sourceFile); + convertJsonOption( + extendsOptionDeclaration.element, + value, + basePath, + errors, + propertyAssignment, + (valueExpression as ArrayLiteralExpression | undefined)?.elements[index], + sourceFile, + ); } } } else { - convertJsonOption(extendsOptionDeclaration, value, basePath, errors, propertyAssignment, valueExpression, sourceFile); + convertJsonOption( + extendsOptionDeclaration, + value, + basePath, + errors, + propertyAssignment, + valueExpression, + sourceFile, + ); } return extendedConfigPath; } @@ -3242,7 +3655,14 @@ function parseOwnConfigOfJsonSourceFile( } if (rootCompilerOptions && json && json.compilerOptions === undefined) { - errors.push(createDiagnosticForNodeInSourceFile(sourceFile, rootCompilerOptions[0], Diagnostics._0_should_be_set_inside_the_compilerOptions_object_of_the_config_json_file, getTextOfPropertyName(rootCompilerOptions[0]) as string)); + errors.push( + createDiagnosticForNodeInSourceFile( + sourceFile, + rootCompilerOptions[0], + Diagnostics._0_should_be_set_inside_the_compilerOptions_object_of_the_config_json_file, + getTextOfPropertyName(rootCompilerOptions[0]) as string, + ), + ); } return { raw: json, options, watchOptions, typeAcquisition, extendedConfigPath }; @@ -3255,13 +3675,25 @@ function parseOwnConfigOfJsonSourceFile( option: CommandLineOption | undefined, ) { // Ensure value is verified except for extends which is handled in its own way for error reporting - if (option && option !== extendsOptionDeclaration) value = convertJsonOption(option, value, basePath, errors, propertyAssignment, propertyAssignment.initializer, sourceFile); + if (option && option !== extendsOptionDeclaration) { + value = convertJsonOption( + option, + value, + basePath, + errors, + propertyAssignment, + propertyAssignment.initializer, + sourceFile, + ); + } if (parentOption?.name) { if (option) { let currentOption; if (parentOption === compilerOptionsDeclaration) currentOption = options; else if (parentOption === watchOptionsDeclaration) currentOption = watchOptions ??= {}; - else if (parentOption === typeAcquisitionDeclaration) currentOption = typeAcquisition ??= getDefaultTypeAcquisition(configFileName); + else if (parentOption === typeAcquisitionDeclaration) { + currentOption = typeAcquisition ??= getDefaultTypeAcquisition(configFileName); + } else Debug.fail("Unknown option"); currentOption[option.name] = value; } @@ -3276,17 +3708,39 @@ function parseOwnConfigOfJsonSourceFile( )); } else { - errors.push(createDiagnosticForNodeInSourceFile(sourceFile, propertyAssignment.name, parentOption.extraKeyDiagnostics.unknownOptionDiagnostic, keyText)); + errors.push( + createDiagnosticForNodeInSourceFile( + sourceFile, + propertyAssignment.name, + parentOption.extraKeyDiagnostics.unknownOptionDiagnostic, + keyText, + ), + ); } } } else if (parentOption === rootOptions) { if (option === extendsOptionDeclaration) { - extendedConfigPath = getExtendsConfigPathOrArray(value, host, basePath, configFileName, errors, propertyAssignment, propertyAssignment.initializer, sourceFile); + extendedConfigPath = getExtendsConfigPathOrArray( + value, + host, + basePath, + configFileName, + errors, + propertyAssignment, + propertyAssignment.initializer, + sourceFile, + ); } else if (!option) { if (keyText === "excludes") { - errors.push(createDiagnosticForNodeInSourceFile(sourceFile, propertyAssignment.name, Diagnostics.Unknown_option_excludes_Did_you_mean_exclude)); + errors.push( + createDiagnosticForNodeInSourceFile( + sourceFile, + propertyAssignment.name, + Diagnostics.Unknown_option_excludes_Did_you_mean_exclude, + ), + ); } if (find(commandOptionsWithoutBuild, opt => opt.name === keyText)) { rootCompilerOptions = append(rootCompilerOptions, propertyAssignment.name); @@ -3310,7 +3764,14 @@ function getExtendsConfigPath( if (!host.fileExists(extendedConfigPath) && !endsWith(extendedConfigPath, Extension.Json)) { extendedConfigPath = `${extendedConfigPath}.json`; if (!host.fileExists(extendedConfigPath)) { - errors.push(createDiagnosticForNodeInSourceFileOrCompilerDiagnostic(sourceFile, valueExpression, Diagnostics.File_0_not_found, extendedConfig)); + errors.push( + createDiagnosticForNodeInSourceFileOrCompilerDiagnostic( + sourceFile, + valueExpression, + Diagnostics.File_0_not_found, + extendedConfig, + ), + ); return undefined; } } @@ -3322,10 +3783,24 @@ function getExtendsConfigPath( return resolved.resolvedModule.resolvedFileName; } if (extendedConfig === "") { - errors.push(createDiagnosticForNodeInSourceFileOrCompilerDiagnostic(sourceFile, valueExpression, Diagnostics.Compiler_option_0_cannot_be_given_an_empty_string, "extends")); + errors.push( + createDiagnosticForNodeInSourceFileOrCompilerDiagnostic( + sourceFile, + valueExpression, + Diagnostics.Compiler_option_0_cannot_be_given_an_empty_string, + "extends", + ), + ); } else { - errors.push(createDiagnosticForNodeInSourceFileOrCompilerDiagnostic(sourceFile, valueExpression, Diagnostics.File_0_not_found, extendedConfig)); + errors.push( + createDiagnosticForNodeInSourceFileOrCompilerDiagnostic( + sourceFile, + valueExpression, + Diagnostics.File_0_not_found, + extendedConfig, + ), + ); } return undefined; } @@ -3354,7 +3829,16 @@ function getExtendedConfig( else { extendedResult = readJsonConfigFile(extendedConfigPath, path => host.readFile(path)); if (!extendedResult.parseDiagnostics.length) { - extendedConfig = parseConfig(/*json*/ undefined, extendedResult, host, getDirectoryPath(extendedConfigPath), getBaseFileName(extendedConfigPath), resolutionStack, errors, extendedConfigCache); + extendedConfig = parseConfig( + /*json*/ undefined, + extendedResult, + host, + getDirectoryPath(extendedConfigPath), + getBaseFileName(extendedConfigPath), + resolutionStack, + errors, + extendedConfigCache, + ); } if (extendedConfigCache) { extendedConfigCache.set(path, { extendedResult, extendedConfig }); @@ -3383,13 +3867,21 @@ function convertCompileOnSaveOptionFromJson(jsonOption: any, basePath: string, e return typeof result === "boolean" && result; } -export function convertCompilerOptionsFromJson(jsonOptions: any, basePath: string, configFileName?: string): { options: CompilerOptions; errors: Diagnostic[]; } { +export function convertCompilerOptionsFromJson( + jsonOptions: any, + basePath: string, + configFileName?: string, +): { options: CompilerOptions; errors: Diagnostic[]; } { const errors: Diagnostic[] = []; const options = convertCompilerOptionsFromJsonWorker(jsonOptions, basePath, errors, configFileName); return { options, errors }; } -export function convertTypeAcquisitionFromJson(jsonOptions: any, basePath: string, configFileName?: string): { options: TypeAcquisition; errors: Diagnostic[]; } { +export function convertTypeAcquisitionFromJson( + jsonOptions: any, + basePath: string, + configFileName?: string, +): { options: TypeAcquisition; errors: Diagnostic[]; } { const errors: Diagnostic[] = []; const options = convertTypeAcquisitionFromJsonWorker(jsonOptions, basePath, errors, configFileName); return { options, errors }; @@ -3397,14 +3889,32 @@ export function convertTypeAcquisitionFromJson(jsonOptions: any, basePath: strin function getDefaultCompilerOptions(configFileName?: string) { const options: CompilerOptions = configFileName && getBaseFileName(configFileName) === "jsconfig.json" - ? { allowJs: true, maxNodeModuleJsDepth: 2, allowSyntheticDefaultImports: true, skipLibCheck: true, noEmit: true } + ? { + allowJs: true, + maxNodeModuleJsDepth: 2, + allowSyntheticDefaultImports: true, + skipLibCheck: true, + noEmit: true, + } : {}; return options; } -function convertCompilerOptionsFromJsonWorker(jsonOptions: any, basePath: string, errors: Diagnostic[], configFileName?: string): CompilerOptions { +function convertCompilerOptionsFromJsonWorker( + jsonOptions: any, + basePath: string, + errors: Diagnostic[], + configFileName?: string, +): CompilerOptions { const options = getDefaultCompilerOptions(configFileName); - convertOptionsFromJson(getCommandLineCompilerOptionsMap(), jsonOptions, basePath, options, compilerOptionsDidYouMeanDiagnostics, errors); + convertOptionsFromJson( + getCommandLineCompilerOptionsMap(), + jsonOptions, + basePath, + options, + compilerOptionsDidYouMeanDiagnostics, + errors, + ); if (configFileName) { options.configFilePath = normalizeSlashes(configFileName); } @@ -3412,22 +3922,70 @@ function convertCompilerOptionsFromJsonWorker(jsonOptions: any, basePath: string } function getDefaultTypeAcquisition(configFileName?: string): TypeAcquisition { - return { enable: !!configFileName && getBaseFileName(configFileName) === "jsconfig.json", include: [], exclude: [] }; + return { + enable: !!configFileName && getBaseFileName(configFileName) === "jsconfig.json", + include: [], + exclude: [], + }; } -function convertTypeAcquisitionFromJsonWorker(jsonOptions: any, basePath: string, errors: Diagnostic[], configFileName?: string): TypeAcquisition { +function convertTypeAcquisitionFromJsonWorker( + jsonOptions: any, + basePath: string, + errors: Diagnostic[], + configFileName?: string, +): TypeAcquisition { const options = getDefaultTypeAcquisition(configFileName); - convertOptionsFromJson(getCommandLineTypeAcquisitionMap(), jsonOptions, basePath, options, typeAcquisitionDidYouMeanDiagnostics, errors); + convertOptionsFromJson( + getCommandLineTypeAcquisitionMap(), + jsonOptions, + basePath, + options, + typeAcquisitionDidYouMeanDiagnostics, + errors, + ); return options; } -function convertWatchOptionsFromJsonWorker(jsonOptions: any, basePath: string, errors: Diagnostic[]): WatchOptions | undefined { - return convertOptionsFromJson(getCommandLineWatchOptionsMap(), jsonOptions, basePath, /*defaultOptions*/ undefined, watchOptionsDidYouMeanDiagnostics, errors); +function convertWatchOptionsFromJsonWorker( + jsonOptions: any, + basePath: string, + errors: Diagnostic[], +): WatchOptions | undefined { + return convertOptionsFromJson( + getCommandLineWatchOptionsMap(), + jsonOptions, + basePath, + /*defaultOptions*/ undefined, + watchOptionsDidYouMeanDiagnostics, + errors, + ); } -function convertOptionsFromJson(optionsNameMap: Map, jsonOptions: any, basePath: string, defaultOptions: undefined, diagnostics: DidYouMeanOptionsDiagnostics, errors: Diagnostic[]): WatchOptions | undefined; -function convertOptionsFromJson(optionsNameMap: Map, jsonOptions: any, basePath: string, defaultOptions: CompilerOptions | TypeAcquisition, diagnostics: DidYouMeanOptionsDiagnostics, errors: Diagnostic[]): CompilerOptions | TypeAcquisition; -function convertOptionsFromJson(optionsNameMap: Map, jsonOptions: any, basePath: string, defaultOptions: CompilerOptions | TypeAcquisition | WatchOptions | undefined, diagnostics: DidYouMeanOptionsDiagnostics, errors: Diagnostic[]) { +function convertOptionsFromJson( + optionsNameMap: Map, + jsonOptions: any, + basePath: string, + defaultOptions: undefined, + diagnostics: DidYouMeanOptionsDiagnostics, + errors: Diagnostic[], +): WatchOptions | undefined; +function convertOptionsFromJson( + optionsNameMap: Map, + jsonOptions: any, + basePath: string, + defaultOptions: CompilerOptions | TypeAcquisition, + diagnostics: DidYouMeanOptionsDiagnostics, + errors: Diagnostic[], +): CompilerOptions | TypeAcquisition; +function convertOptionsFromJson( + optionsNameMap: Map, + jsonOptions: any, + basePath: string, + defaultOptions: CompilerOptions | TypeAcquisition | WatchOptions | undefined, + diagnostics: DidYouMeanOptionsDiagnostics, + errors: Diagnostic[], +) { if (!jsonOptions) { return; } @@ -3435,7 +3993,12 @@ function convertOptionsFromJson(optionsNameMap: Map, for (const id in jsonOptions) { const opt = optionsNameMap.get(id); if (opt) { - (defaultOptions || (defaultOptions = {}))[opt.name] = convertJsonOption(opt, jsonOptions[id], basePath, errors); + (defaultOptions || (defaultOptions = {}))[opt.name] = convertJsonOption( + opt, + jsonOptions[id], + basePath, + errors, + ); } else { errors.push(createUnknownOptionError(id, diagnostics)); @@ -3444,10 +4007,15 @@ function convertOptionsFromJson(optionsNameMap: Map, return defaultOptions; } -function createDiagnosticForNodeInSourceFileOrCompilerDiagnostic(sourceFile: TsConfigSourceFile | undefined, node: Node | undefined, message: DiagnosticMessage, ...args: DiagnosticArguments) { - return sourceFile && node ? - createDiagnosticForNodeInSourceFile(sourceFile, node, message, ...args) : - createCompilerDiagnostic(message, ...args); +function createDiagnosticForNodeInSourceFileOrCompilerDiagnostic( + sourceFile: TsConfigSourceFile | undefined, + node: Node | undefined, + message: DiagnosticMessage, + ...args: DiagnosticArguments +) { + return sourceFile && node + ? createDiagnosticForNodeInSourceFile(sourceFile, node, message, ...args) + : createCompilerDiagnostic(message, ...args); } /** @internal */ @@ -3461,27 +4029,73 @@ export function convertJsonOption( sourceFile?: TsConfigSourceFile, ): CompilerOptionsValue { if (opt.isCommandLineOnly) { - errors.push(createDiagnosticForNodeInSourceFileOrCompilerDiagnostic(sourceFile, propertyAssignment?.name, Diagnostics.Option_0_can_only_be_specified_on_command_line, opt.name)); + errors.push( + createDiagnosticForNodeInSourceFileOrCompilerDiagnostic( + sourceFile, + propertyAssignment?.name, + Diagnostics.Option_0_can_only_be_specified_on_command_line, + opt.name, + ), + ); return undefined; } if (isCompilerOptionsValue(opt, value)) { const optType = opt.type; if ((optType === "list") && isArray(value)) { - return convertJsonOptionOfListType(opt, value, basePath, errors, propertyAssignment, valueExpression as ArrayLiteralExpression | undefined, sourceFile); + return convertJsonOptionOfListType( + opt, + value, + basePath, + errors, + propertyAssignment, + valueExpression as ArrayLiteralExpression | undefined, + sourceFile, + ); } else if (optType === "listOrElement") { - return isArray(value) ? - convertJsonOptionOfListType(opt, value, basePath, errors, propertyAssignment, valueExpression as ArrayLiteralExpression | undefined, sourceFile) : - convertJsonOption(opt.element, value, basePath, errors, propertyAssignment, valueExpression, sourceFile); + return isArray(value) + ? convertJsonOptionOfListType( + opt, + value, + basePath, + errors, + propertyAssignment, + valueExpression as ArrayLiteralExpression | undefined, + sourceFile, + ) + : convertJsonOption( + opt.element, + value, + basePath, + errors, + propertyAssignment, + valueExpression, + sourceFile, + ); } else if (!isString(opt.type)) { - return convertJsonOptionOfCustomType(opt as CommandLineOptionOfCustomType, value as string, errors, valueExpression, sourceFile); + return convertJsonOptionOfCustomType( + opt as CommandLineOptionOfCustomType, + value as string, + errors, + valueExpression, + sourceFile, + ); } const validatedValue = validateJsonOptionValue(opt, value, errors, valueExpression, sourceFile); - return isNullOrUndefined(validatedValue) ? validatedValue : normalizeNonListOptionValue(opt, basePath, validatedValue); + return isNullOrUndefined(validatedValue) ? validatedValue + : normalizeNonListOptionValue(opt, basePath, validatedValue); } else { - errors.push(createDiagnosticForNodeInSourceFileOrCompilerDiagnostic(sourceFile, valueExpression, Diagnostics.Compiler_option_0_requires_a_value_of_type_1, opt.name, getCompilerOptionValueTypeString(opt))); + errors.push( + createDiagnosticForNodeInSourceFileOrCompilerDiagnostic( + sourceFile, + valueExpression, + Diagnostics.Compiler_option_0_requires_a_value_of_type_1, + opt.name, + getCompilerOptionValueTypeString(opt), + ), + ); } } @@ -3523,7 +4137,18 @@ function convertJsonOptionOfCustomType( return validateJsonOptionValue(opt, val, errors, valueExpression, sourceFile); } else { - errors.push(createDiagnosticForInvalidCustomType(opt, (message, ...args) => createDiagnosticForNodeInSourceFileOrCompilerDiagnostic(sourceFile, valueExpression, message, ...args))); + errors.push( + createDiagnosticForInvalidCustomType( + opt, + (message, ...args) => + createDiagnosticForNodeInSourceFileOrCompilerDiagnostic( + sourceFile, + valueExpression, + message, + ...args, + ), + ), + ); } } @@ -3536,7 +4161,19 @@ function convertJsonOptionOfListType( valueExpression: ArrayLiteralExpression | undefined, sourceFile: TsConfigSourceFile | undefined, ): any[] { - return filter(map(values, (v, index) => convertJsonOption(option.element, v, basePath, errors, propertyAssignment, valueExpression?.elements[index], sourceFile)), v => option.listPreserveFalsyValues ? true : !!v); + return filter( + map(values, (v, index) => + convertJsonOption( + option.element, + v, + basePath, + errors, + propertyAssignment, + valueExpression?.elements[index], + sourceFile, + )), + v => option.listPreserveFalsyValues ? true : !!v, + ); } /** @@ -3607,7 +4244,10 @@ export function getFileNamesFromConfigSpecs( // Rather than re-query this for each file and filespec, we query the supported extensions // once and store it on the expansion context. const supportedExtensions = getSupportedExtensions(options, extraFileExtensions); - const supportedExtensionsWithJsonIfResolveJsonModule = getSupportedExtensionsWithJsonIfResolveJsonModule(options, supportedExtensions); + const supportedExtensionsWithJsonIfResolveJsonModule = getSupportedExtensionsWithJsonIfResolveJsonModule( + options, + supportedExtensions, + ); // Literal files are always included verbatim. An "include" or "exclude" specification cannot // remove a literal file. @@ -3620,13 +4260,26 @@ export function getFileNamesFromConfigSpecs( let jsonOnlyIncludeRegexes: readonly RegExp[] | undefined; if (validatedIncludeSpecs && validatedIncludeSpecs.length > 0) { - for (const file of host.readDirectory(basePath, flatten(supportedExtensionsWithJsonIfResolveJsonModule), validatedExcludeSpecs, validatedIncludeSpecs, /*depth*/ undefined)) { + for ( + const file of host.readDirectory( + basePath, + flatten(supportedExtensionsWithJsonIfResolveJsonModule), + validatedExcludeSpecs, + validatedIncludeSpecs, + /*depth*/ undefined, + ) + ) { if (fileExtensionIs(file, Extension.Json)) { // Valid only if *.json specified if (!jsonOnlyIncludeRegexes) { const includes = validatedIncludeSpecs.filter(s => endsWith(s, Extension.Json)); - const includeFilePatterns = map(getRegularExpressionsForWildcards(includes, basePath, "files"), pattern => `^${pattern}$`); - jsonOnlyIncludeRegexes = includeFilePatterns ? includeFilePatterns.map(pattern => getRegexFromPattern(pattern, host.useCaseSensitiveFileNames)) : emptyArray; + const includeFilePatterns = map( + getRegularExpressionsForWildcards(includes, basePath, "files"), + pattern => `^${pattern}$`, + ); + jsonOnlyIncludeRegexes = includeFilePatterns ? includeFilePatterns.map(pattern => + getRegexFromPattern(pattern, host.useCaseSensitiveFileNames) + ) : emptyArray; } const includeIndex = findIndex(jsonOnlyIncludeRegexes, re => re.test(file)); if (includeIndex !== -1) { @@ -3643,7 +4296,15 @@ export function getFileNamesFromConfigSpecs( // This handles cases where we may encounter both .ts and // .d.ts (or .js if "allowJs" is enabled) in the same // directory when they are compilation outputs. - if (hasFileWithHigherPriorityExtension(file, literalFileMap, wildcardFileMap, supportedExtensions, keyMapper)) { + if ( + hasFileWithHigherPriorityExtension( + file, + literalFileMap, + wildcardFileMap, + supportedExtensions, + keyMapper, + ) + ) { continue; } @@ -3686,7 +4347,13 @@ export function isExcludedFile( } } - return matchesExcludeWorker(pathToCheck, validatedExcludeSpecs, useCaseSensitiveFileNames, currentDirectory, basePath); + return matchesExcludeWorker( + pathToCheck, + validatedExcludeSpecs, + useCaseSensitiveFileNames, + currentDirectory, + basePath, + ); } function invalidDotDotAfterRecursiveWildcard(s: string) { @@ -3725,14 +4392,24 @@ function matchesExcludeWorker( currentDirectory: string, basePath?: string, ) { - const excludePattern = getRegularExpressionForWildcard(excludeSpecs, combinePaths(normalizePath(currentDirectory), basePath), "exclude"); + const excludePattern = getRegularExpressionForWildcard( + excludeSpecs, + combinePaths(normalizePath(currentDirectory), basePath), + "exclude", + ); const excludeRegex = excludePattern && getRegexFromPattern(excludePattern, useCaseSensitiveFileNames); if (!excludeRegex) return false; if (excludeRegex.test(pathToCheck)) return true; return !hasExtension(pathToCheck) && excludeRegex.test(ensureTrailingDirectorySeparator(pathToCheck)); } -function validateSpecs(specs: readonly string[], errors: Diagnostic[], disallowTrailingRecursion: boolean, jsonSourceFile: TsConfigSourceFile | undefined, specKey: string): readonly string[] { +function validateSpecs( + specs: readonly string[], + errors: Diagnostic[], + disallowTrailingRecursion: boolean, + jsonSourceFile: TsConfigSourceFile | undefined, + specKey: string, +): readonly string[] { return specs.filter(spec => { if (!isString(spec)) return false; const diag = specToDiagnostic(spec, disallowTrailingRecursion); @@ -3748,20 +4425,34 @@ function validateSpecs(specs: readonly string[], errors: Diagnostic[], disallowT } } -function specToDiagnostic(spec: CompilerOptionsValue, disallowTrailingRecursion?: boolean): [DiagnosticMessage, string] | undefined { +function specToDiagnostic( + spec: CompilerOptionsValue, + disallowTrailingRecursion?: boolean, +): [DiagnosticMessage, string] | undefined { Debug.assert(typeof spec === "string"); if (disallowTrailingRecursion && invalidTrailingRecursionPattern.test(spec)) { - return [Diagnostics.File_specification_cannot_end_in_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0, spec]; + return [ + Diagnostics.File_specification_cannot_end_in_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0, + spec, + ]; } else if (invalidDotDotAfterRecursiveWildcard(spec)) { - return [Diagnostics.File_specification_cannot_contain_a_parent_directory_that_appears_after_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0, spec]; + return [ + Diagnostics + .File_specification_cannot_contain_a_parent_directory_that_appears_after_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0, + spec, + ]; } } /** * Gets directories in a set of include patterns that should be watched for changes. */ -function getWildcardDirectories({ validatedIncludeSpecs: include, validatedExcludeSpecs: exclude }: ConfigFileSpecs, path: string, useCaseSensitiveFileNames: boolean): MapLike { +function getWildcardDirectories( + { validatedIncludeSpecs: include, validatedExcludeSpecs: exclude }: ConfigFileSpecs, + path: string, + useCaseSensitiveFileNames: boolean, +): MapLike { // We watch a directory recursively if it contains a wildcard anywhere in a directory segment // of the pattern: // @@ -3813,7 +4504,10 @@ function getWildcardDirectories({ validatedIncludeSpecs: include, validatedExclu return wildcardDirectories; } -function getWildcardDirectoryFromSpec(spec: string, useCaseSensitiveFileNames: boolean): { key: string; flags: WatchDirectoryFlags; } | undefined { +function getWildcardDirectoryFromSpec( + spec: string, + useCaseSensitiveFileNames: boolean, +): { key: string; flags: WatchDirectoryFlags; } | undefined { const match = wildcardDirectoryPattern.exec(spec); if (match) { // We check this with a few `indexOf` calls because 3 `indexOf`/`lastIndexOf` calls is @@ -3845,7 +4539,13 @@ function getWildcardDirectoryFromSpec(spec: string, useCaseSensitiveFileNames: b * * @param file The path to the file. */ -function hasFileWithHigherPriorityExtension(file: string, literalFiles: Map, wildcardFiles: Map, extensions: readonly string[][], keyMapper: (value: string) => string) { +function hasFileWithHigherPriorityExtension( + file: string, + literalFiles: Map, + wildcardFiles: Map, + extensions: readonly string[][], + keyMapper: (value: string) => string, +) { const extensionGroup = forEach(extensions, group => fileExtensionIsOneOf(file, group) ? group : undefined); if (!extensionGroup) { return false; @@ -3856,7 +4556,9 @@ function hasFileWithHigherPriorityExtension(file: string, literalFiles: Map, extensions: readonly string[][], keyMapper: (value: string) => string) { +function removeWildcardFilesWithLowerPriorityExtension( + file: string, + wildcardFiles: Map, + extensions: readonly string[][], + keyMapper: (value: string) => string, +) { const extensionGroup = forEach(extensions, group => fileExtensionIsOneOf(file, group) ? group : undefined); if (!extensionGroup) { return; diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 96857857c2a0b..77f99d7fc1f21 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -32,7 +32,10 @@ export function length(array: readonly any[] | undefined): number { * * @internal */ -export function forEach(array: readonly T[] | undefined, callback: (element: T, index: number) => U | undefined): U | undefined { +export function forEach( + array: readonly T[] | undefined, + callback: (element: T, index: number) => U | undefined, +): U | undefined { if (array) { for (let i = 0; i < array.length; i++) { const result = callback(array[i], i); @@ -49,7 +52,10 @@ export function forEach(array: readonly T[] | undefined, callback: (elemen * * @internal */ -export function forEachRight(array: readonly T[] | undefined, callback: (element: T, index: number) => U | undefined): U | undefined { +export function forEachRight( + array: readonly T[] | undefined, + callback: (element: T, index: number) => U | undefined, +): U | undefined { if (array) { for (let i = array.length - 1; i >= 0; i--) { const result = callback(array[i], i); @@ -66,7 +72,10 @@ export function forEachRight(array: readonly T[] | undefined, callback: (e * * @internal */ -export function firstDefined(array: readonly T[] | undefined, callback: (element: T, index: number) => U | undefined): U | undefined { +export function firstDefined( + array: readonly T[] | undefined, + callback: (element: T, index: number) => U | undefined, +): U | undefined { if (array === undefined) { return undefined; } @@ -92,7 +101,11 @@ export function firstDefinedIterator(iter: Iterable, callback: (element } /** @internal */ -export function reduceLeftIterator(iterator: Iterable | undefined, f: (memo: U, value: T, i: number) => U, initial: U): U { +export function reduceLeftIterator( + iterator: Iterable | undefined, + f: (memo: U, value: T, i: number) => U, + initial: U, +): U { let result = initial; if (iterator) { let pos = 0; @@ -105,7 +118,11 @@ export function reduceLeftIterator(iterator: Iterable | undefined, f: ( } /** @internal */ -export function zipWith(arrayA: readonly T[], arrayB: readonly U[], callback: (a: T, b: U, index: number) => V): V[] { +export function zipWith( + arrayA: readonly T[], + arrayB: readonly U[], + callback: (a: T, b: U, index: number) => V, +): V[] { const result: V[] = []; Debug.assertEqual(arrayA.length, arrayB.length); for (let i = 0; i < arrayA.length; i++) { @@ -139,9 +156,15 @@ export function intersperse(input: T[], element: T): T[] { * * @internal */ -export function every(array: readonly T[], callback: (element: T, index: number) => element is U): array is readonly U[]; +export function every( + array: readonly T[], + callback: (element: T, index: number) => element is U, +): array is readonly U[]; /** @internal */ -export function every(array: readonly T[] | undefined, callback: (element: T, index: number) => element is U): array is readonly U[] | undefined; +export function every( + array: readonly T[] | undefined, + callback: (element: T, index: number) => element is U, +): array is readonly U[] | undefined; /** @internal */ export function every(array: readonly T[] | undefined, callback: (element: T, index: number) => boolean): boolean; export function every(array: readonly T[] | undefined, callback: (element: T, index: number) => boolean): boolean { @@ -161,11 +184,23 @@ export function every(array: readonly T[] | undefined, callback: (element: T, * * @internal */ -export function find(array: readonly T[] | undefined, predicate: (element: T, index: number) => element is U, startIndex?: number): U | undefined; +export function find( + array: readonly T[] | undefined, + predicate: (element: T, index: number) => element is U, + startIndex?: number, +): U | undefined; /** @internal */ -export function find(array: readonly T[] | undefined, predicate: (element: T, index: number) => boolean, startIndex?: number): T | undefined; +export function find( + array: readonly T[] | undefined, + predicate: (element: T, index: number) => boolean, + startIndex?: number, +): T | undefined; /** @internal */ -export function find(array: readonly T[] | undefined, predicate: (element: T, index: number) => boolean, startIndex?: number): T | undefined { +export function find( + array: readonly T[] | undefined, + predicate: (element: T, index: number) => boolean, + startIndex?: number, +): T | undefined { if (array === undefined) return undefined; for (let i = startIndex ?? 0; i < array.length; i++) { const value = array[i]; @@ -177,11 +212,23 @@ export function find(array: readonly T[] | undefined, predicate: (element: T, } /** @internal */ -export function findLast(array: readonly T[] | undefined, predicate: (element: T, index: number) => element is U, startIndex?: number): U | undefined; +export function findLast( + array: readonly T[] | undefined, + predicate: (element: T, index: number) => element is U, + startIndex?: number, +): U | undefined; /** @internal */ -export function findLast(array: readonly T[] | undefined, predicate: (element: T, index: number) => boolean, startIndex?: number): T | undefined; +export function findLast( + array: readonly T[] | undefined, + predicate: (element: T, index: number) => boolean, + startIndex?: number, +): T | undefined; /** @internal */ -export function findLast(array: readonly T[] | undefined, predicate: (element: T, index: number) => boolean, startIndex?: number): T | undefined { +export function findLast( + array: readonly T[] | undefined, + predicate: (element: T, index: number) => boolean, + startIndex?: number, +): T | undefined { if (array === undefined) return undefined; for (let i = startIndex ?? array.length - 1; i >= 0; i--) { const value = array[i]; @@ -197,7 +244,11 @@ export function findLast(array: readonly T[] | undefined, predicate: (element * * @internal */ -export function findIndex(array: readonly T[] | undefined, predicate: (element: T, index: number) => boolean, startIndex?: number): number { +export function findIndex( + array: readonly T[] | undefined, + predicate: (element: T, index: number) => boolean, + startIndex?: number, +): number { if (array === undefined) return -1; for (let i = startIndex ?? 0; i < array.length; i++) { if (predicate(array[i], i)) { @@ -208,7 +259,11 @@ export function findIndex(array: readonly T[] | undefined, predicate: (elemen } /** @internal */ -export function findLastIndex(array: readonly T[] | undefined, predicate: (element: T, index: number) => boolean, startIndex?: number): number { +export function findLastIndex( + array: readonly T[] | undefined, + predicate: (element: T, index: number) => boolean, + startIndex?: number, +): number { if (array === undefined) return -1; for (let i = startIndex ?? array.length - 1; i >= 0; i--) { if (predicate(array[i], i)) { @@ -235,7 +290,11 @@ export function findMap(array: readonly T[], callback: (element: T, index: } /** @internal */ -export function contains(array: readonly T[] | undefined, value: T, equalityComparer: EqualityComparer = equateValues): boolean { +export function contains( + array: readonly T[] | undefined, + value: T, + equalityComparer: EqualityComparer = equateValues, +): boolean { if (array) { for (const v of array) { if (equalityComparer(v, value)) { @@ -247,7 +306,11 @@ export function contains(array: readonly T[] | undefined, value: T, equalityC } /** @internal */ -export function arraysEqual(a: readonly T[], b: readonly T[], equalityComparer: EqualityComparer = equateValues): boolean { +export function arraysEqual( + a: readonly T[], + b: readonly T[], + equalityComparer: EqualityComparer = equateValues, +): boolean { return a.length === b.length && a.every((x, i) => equalityComparer(x, b[i])); } @@ -370,7 +433,10 @@ export function sameMap(array: T[] | undefined, f: (x: T, i: number) = /** @internal */ export function sameMap(array: readonly T[] | undefined, f: (x: T, i: number) => U): readonly U[] | undefined; /** @internal */ -export function sameMap(array: readonly T[] | undefined, f: (x: T, i: number) => U): readonly U[] | undefined { +export function sameMap( + array: readonly T[] | undefined, + f: (x: T, i: number) => U, +): readonly U[] | undefined { if (array) { for (let i = 0; i < array.length; i++) { const item = array[i]; @@ -418,7 +484,10 @@ export function flatten(array: T[][] | readonly (T | readonly T[] | undefined * * @internal */ -export function flatMap(array: readonly T[] | undefined, mapfn: (x: T, i: number) => U | readonly U[] | undefined): readonly U[] { +export function flatMap( + array: readonly T[] | undefined, + mapfn: (x: T, i: number) => U | readonly U[] | undefined, +): readonly U[] { let result: U[] | undefined; if (array) { for (let i = 0; i < array.length; i++) { @@ -437,7 +506,10 @@ export function flatMap(array: readonly T[] | undefined, mapfn: (x: T, i: } /** @internal */ -export function flatMapToMutable(array: readonly T[] | undefined, mapfn: (x: T, i: number) => U | readonly U[] | undefined): U[] { +export function flatMapToMutable( + array: readonly T[] | undefined, + mapfn: (x: T, i: number) => U | readonly U[] | undefined, +): U[] { const result: U[] = []; if (array) { for (let i = 0; i < array.length; i++) { @@ -537,11 +609,20 @@ export function* mapDefinedIterator(iter: Iterable, mapFn: (x: T) => U } /** @internal */ -export function mapDefinedEntries(map: ReadonlyMap, f: (key: K1, value: V1) => readonly [K2, V2] | undefined): Map; +export function mapDefinedEntries( + map: ReadonlyMap, + f: (key: K1, value: V1) => readonly [K2, V2] | undefined, +): Map; /** @internal */ -export function mapDefinedEntries(map: ReadonlyMap | undefined, f: (key: K1, value: V1) => readonly [K2 | undefined, V2 | undefined] | undefined): Map | undefined; +export function mapDefinedEntries( + map: ReadonlyMap | undefined, + f: (key: K1, value: V1) => readonly [K2 | undefined, V2 | undefined] | undefined, +): Map | undefined; /** @internal */ -export function mapDefinedEntries(map: ReadonlyMap | undefined, f: (key: K1, value: V1) => readonly [K2 | undefined, V2 | undefined] | undefined): Map | undefined { +export function mapDefinedEntries( + map: ReadonlyMap | undefined, + f: (key: K1, value: V1) => readonly [K2 | undefined, V2 | undefined] | undefined, +): Map | undefined { if (!map) { return undefined; } @@ -593,11 +674,23 @@ export function* singleIterator(value: T) { * * @internal */ -export function spanMap(array: readonly T[], keyfn: (x: T, i: number) => K, mapfn: (chunk: T[], key: K, start: number, end: number) => U): U[]; -/** @internal */ -export function spanMap(array: readonly T[] | undefined, keyfn: (x: T, i: number) => K, mapfn: (chunk: T[], key: K, start: number, end: number) => U): U[] | undefined; -/** @internal */ -export function spanMap(array: readonly T[] | undefined, keyfn: (x: T, i: number) => K, mapfn: (chunk: T[], key: K, start: number, end: number) => U): U[] | undefined { +export function spanMap( + array: readonly T[], + keyfn: (x: T, i: number) => K, + mapfn: (chunk: T[], key: K, start: number, end: number) => U, +): U[]; +/** @internal */ +export function spanMap( + array: readonly T[] | undefined, + keyfn: (x: T, i: number) => K, + mapfn: (chunk: T[], key: K, start: number, end: number) => U, +): U[] | undefined; +/** @internal */ +export function spanMap( + array: readonly T[] | undefined, + keyfn: (x: T, i: number) => K, + mapfn: (chunk: T[], key: K, start: number, end: number) => U, +): U[] | undefined { let result: U[] | undefined; if (array) { result = []; @@ -638,11 +731,20 @@ export function spanMap(array: readonly T[] | undefined, keyfn: (x: T, } /** @internal */ -export function mapEntries(map: ReadonlyMap, f: (key: K1, value: V1) => readonly [K2, V2]): Map; +export function mapEntries( + map: ReadonlyMap, + f: (key: K1, value: V1) => readonly [K2, V2], +): Map; /** @internal */ -export function mapEntries(map: ReadonlyMap | undefined, f: (key: K1, value: V1) => readonly [K2, V2]): Map | undefined; +export function mapEntries( + map: ReadonlyMap | undefined, + f: (key: K1, value: V1) => readonly [K2, V2], +): Map | undefined; /** @internal */ -export function mapEntries(map: ReadonlyMap | undefined, f: (key: K1, value: V1) => readonly [K2, V2]): Map | undefined { +export function mapEntries( + map: ReadonlyMap | undefined, + f: (key: K1, value: V1) => readonly [K2, V2], +): Map | undefined { if (!map) { return undefined; } @@ -681,7 +783,11 @@ export function some(array: readonly T[] | undefined, predicate?: (value: T) * * @internal */ -export function getRangesWhere(arr: readonly T[], pred: (t: T) => boolean, cb: (start: number, afterEnd: number) => void): void { +export function getRangesWhere( + arr: readonly T[], + pred: (t: T) => boolean, + cb: (start: number, afterEnd: number) => void, +): void { let start: number | undefined; for (let i = 0; i < arr.length; i++) { if (pred(arr[i])) { @@ -712,9 +818,15 @@ export function concatenate(array1: readonly T[] | undefined, array2: readonl /** @internal */ export function concatenate(array1: T[] | undefined, array2: T[] | undefined): T[] | undefined; /** @internal */ -export function concatenate(array1: readonly T[] | undefined, array2: readonly T[] | undefined): readonly T[] | undefined; +export function concatenate( + array1: readonly T[] | undefined, + array2: readonly T[] | undefined, +): readonly T[] | undefined; /** @internal */ -export function concatenate(array1: readonly T[] | undefined, array2: readonly T[] | undefined): readonly T[] | undefined { +export function concatenate( + array1: readonly T[] | undefined, + array2: readonly T[] | undefined, +): readonly T[] | undefined { if (!some(array2)) return array1; if (!some(array1)) return array2; return [...array1, ...array2]; @@ -767,17 +879,24 @@ function deduplicateEquality(array: readonly T[], equalityComparer: EqualityC * * @internal */ -export function deduplicate(array: readonly T[], equalityComparer: EqualityComparer, comparer?: Comparer): T[] { - return array.length === 0 ? [] : - array.length === 1 ? array.slice() : - comparer ? deduplicateRelational(array, equalityComparer, comparer) : - deduplicateEquality(array, equalityComparer); +export function deduplicate( + array: readonly T[], + equalityComparer: EqualityComparer, + comparer?: Comparer, +): T[] { + return array.length === 0 ? [] + : array.length === 1 ? array.slice() + : comparer ? deduplicateRelational(array, equalityComparer, comparer) + : deduplicateEquality(array, equalityComparer); } /** * Deduplicates an array that has already been sorted. */ -function deduplicateSorted(array: SortedReadonlyArray, comparer: EqualityComparer | Comparer): SortedReadonlyArray { +function deduplicateSorted( + array: SortedReadonlyArray, + comparer: EqualityComparer | Comparer, +): SortedReadonlyArray { if (array.length === 0) return emptyArray as any as SortedReadonlyArray; let last = array[0]; @@ -810,7 +929,12 @@ export function createSortedArray(): SortedArray { } /** @internal */ -export function insertSorted(array: SortedArray, insert: T, compare: Comparer, allowDuplicates?: boolean): boolean { +export function insertSorted( + array: SortedArray, + insert: T, + compare: Comparer, + allowDuplicates?: boolean, +): boolean { if (array.length === 0) { array.push(insert); return true; @@ -833,10 +957,21 @@ export function insertSorted(array: SortedArray, insert: T, compare: Compa /** @internal */ export function sortAndDeduplicate(array: readonly string[]): SortedReadonlyArray; /** @internal */ -export function sortAndDeduplicate(array: readonly T[], comparer: Comparer, equalityComparer?: EqualityComparer): SortedReadonlyArray; +export function sortAndDeduplicate( + array: readonly T[], + comparer: Comparer, + equalityComparer?: EqualityComparer, +): SortedReadonlyArray; /** @internal */ -export function sortAndDeduplicate(array: readonly T[], comparer?: Comparer, equalityComparer?: EqualityComparer): SortedReadonlyArray { - return deduplicateSorted(sort(array, comparer), equalityComparer || comparer || compareStringsCaseSensitive as any as Comparer); +export function sortAndDeduplicate( + array: readonly T[], + comparer?: Comparer, + equalityComparer?: EqualityComparer, +): SortedReadonlyArray { + return deduplicateSorted( + sort(array, comparer), + equalityComparer || comparer || compareStringsCaseSensitive as any as Comparer, + ); } /** @internal */ @@ -883,7 +1018,11 @@ export function detectSortCaseSensitivity( } /** @internal */ -export function arrayIsEqualTo(array1: readonly T[] | undefined, array2: readonly T[] | undefined, equalityComparer: (a: T, b: T, index: number) => boolean = equateValues): boolean { +export function arrayIsEqualTo( + array1: readonly T[] | undefined, + array2: readonly T[] | undefined, + equalityComparer: (a: T, b: T, index: number) => boolean = equateValues, +): boolean { if (!array1 || !array2) { return array1 === array2; } @@ -940,7 +1079,11 @@ export function compact(array: readonly T[]): readonly T[] { * * @internal */ -export function relativeComplement(arrayA: T[] | undefined, arrayB: T[] | undefined, comparer: Comparer): T[] | undefined { +export function relativeComplement( + arrayA: T[] | undefined, + arrayB: T[] | undefined, + comparer: Comparer, +): T[] | undefined { if (!arrayB || !arrayA || arrayB.length === 0 || arrayA.length === 0) return arrayB; const result: T[] = []; loopB: @@ -990,7 +1133,10 @@ export function relativeComplement(arrayA: T[] | undefined, arrayB: T[] | und * * @internal */ -export function append[number] | undefined>(to: TArray, value: TValue): [undefined, undefined] extends [TArray, TValue] ? TArray : NonNullable[number][]; +export function append[number] | undefined>( + to: TArray, + value: TValue, +): [undefined, undefined] extends [TArray, TValue] ? TArray : NonNullable[number][]; /** @internal */ export function append(to: T[], value: T | undefined): T[]; /** @internal */ @@ -1023,7 +1169,10 @@ export function append(to: T[] | undefined, value: T | undefined): T[] | unde */ export function combine(xs: T[] | undefined, ys: T[] | undefined): T[] | undefined; /** @internal */ -export function combine(xs: T | readonly T[] | undefined, ys: T | readonly T[] | undefined): T | readonly T[] | undefined; +export function combine( + xs: T | readonly T[] | undefined, + ys: T | readonly T[] | undefined, +): T | readonly T[] | undefined; /** @internal */ export function combine(xs: T | T[] | undefined, ys: T | T[] | undefined): T | T[] | undefined; /** @internal */ @@ -1057,9 +1206,19 @@ function toOffset(array: readonly any[], offset: number) { */ export function addRange(to: T[], from: readonly T[] | undefined, start?: number, end?: number): T[]; /** @internal */ -export function addRange(to: T[] | undefined, from: readonly T[] | undefined, start?: number, end?: number): T[] | undefined; -/** @internal */ -export function addRange(to: T[] | undefined, from: readonly T[] | undefined, start?: number, end?: number): T[] | undefined { +export function addRange( + to: T[] | undefined, + from: readonly T[] | undefined, + start?: number, + end?: number, +): T[] | undefined; +/** @internal */ +export function addRange( + to: T[] | undefined, + from: readonly T[] | undefined, + start?: number, + end?: number, +): T[] | undefined { if (from === undefined || from.length === 0) return to; if (to === undefined) return from.slice(start, end); start = start === undefined ? 0 : toOffset(from, start); @@ -1271,7 +1430,13 @@ export function replaceElement(array: readonly T[], index: number, value: T): * * @internal */ -export function binarySearch(array: readonly T[], value: T, keySelector: (v: T) => U, keyComparer: Comparer, offset?: number): number { +export function binarySearch( + array: readonly T[], + value: T, + keySelector: (v: T) => U, + keyComparer: Comparer, + offset?: number, +): number { return binarySearchKey(array, keySelector(value), keySelector, keyComparer, offset); } @@ -1287,7 +1452,13 @@ export function binarySearch(array: readonly T[], value: T, keySelector: ( * * @internal */ -export function binarySearchKey(array: readonly T[], key: U, keySelector: (v: T, i: number) => U, keyComparer: Comparer, offset?: number): number { +export function binarySearchKey( + array: readonly T[], + key: U, + keySelector: (v: T, i: number) => U, + keyComparer: Comparer, + offset?: number, +): number { if (!some(array)) { return -1; } @@ -1313,11 +1484,23 @@ export function binarySearchKey(array: readonly T[], key: U, keySelector: } /** @internal */ -export function reduceLeft(array: readonly T[] | undefined, f: (memo: U, value: T, i: number) => U, initial: U, start?: number, count?: number): U; +export function reduceLeft( + array: readonly T[] | undefined, + f: (memo: U, value: T, i: number) => U, + initial: U, + start?: number, + count?: number, +): U; /** @internal */ export function reduceLeft(array: readonly T[], f: (memo: T, value: T, i: number) => T): T | undefined; /** @internal */ -export function reduceLeft(array: readonly T[] | undefined, f: (memo: T, value: T, i: number) => T, initial?: T, start?: number, count?: number): T | undefined { +export function reduceLeft( + array: readonly T[] | undefined, + f: (memo: T, value: T, i: number) => T, + initial?: T, + start?: number, + count?: number, +): T | undefined { if (array && array.length > 0) { const size = array.length; if (size > 0) { @@ -1455,7 +1638,11 @@ export function assign(t: T, ...args: (T | undefined)[]) { * * @internal */ -export function equalOwnProperties(left: MapLike | undefined, right: MapLike | undefined, equalityComparer: EqualityComparer = equateValues) { +export function equalOwnProperties( + left: MapLike | undefined, + right: MapLike | undefined, + equalityComparer: EqualityComparer = equateValues, +) { if (left === right) return true; if (!left || !right) return false; for (const key in left) { @@ -1488,13 +1675,25 @@ export function equalOwnProperties(left: MapLike | undefined, right: MapLi */ export function arrayToMap(array: readonly V[], makeKey: (value: V) => K | undefined): Map; /** @internal */ -export function arrayToMap(array: readonly V1[], makeKey: (value: V1) => K | undefined, makeValue: (value: V1) => V2): Map; +export function arrayToMap( + array: readonly V1[], + makeKey: (value: V1) => K | undefined, + makeValue: (value: V1) => V2, +): Map; /** @internal */ export function arrayToMap(array: readonly T[], makeKey: (value: T) => string | undefined): Map; /** @internal */ -export function arrayToMap(array: readonly T[], makeKey: (value: T) => string | undefined, makeValue: (value: T) => U): Map; -/** @internal */ -export function arrayToMap(array: readonly V1[], makeKey: (value: V1) => K | undefined, makeValue: (value: V1) => V1 | V2 = identity): Map { +export function arrayToMap( + array: readonly T[], + makeKey: (value: T) => string | undefined, + makeValue: (value: T) => U, +): Map; +/** @internal */ +export function arrayToMap( + array: readonly V1[], + makeKey: (value: V1) => K | undefined, + makeValue: (value: V1) => V1 | V2 = identity, +): Map { const result = new Map(); for (const value of array) { const key = makeKey(value); @@ -1506,9 +1705,17 @@ export function arrayToMap(array: readonly V1[], makeKey: (value: V1) /** @internal */ export function arrayToNumericMap(array: readonly T[], makeKey: (value: T) => number): T[]; /** @internal */ -export function arrayToNumericMap(array: readonly T[], makeKey: (value: T) => number, makeValue: (value: T) => U): U[]; +export function arrayToNumericMap( + array: readonly T[], + makeKey: (value: T) => number, + makeValue: (value: T) => U, +): U[]; /** @internal */ -export function arrayToNumericMap(array: readonly T[], makeKey: (value: T) => number, makeValue: (value: T) => T | U = identity): (T | U)[] { +export function arrayToNumericMap( + array: readonly T[], + makeKey: (value: T) => number, + makeValue: (value: T) => T | U = identity, +): (T | U)[] { const result: (T | U)[] = []; for (const value of array) { result[makeKey(value)] = makeValue(value); @@ -1519,9 +1726,17 @@ export function arrayToNumericMap(array: readonly T[], makeKey: (value: T) /** @internal */ export function arrayToMultiMap(values: readonly V[], makeKey: (value: V) => K): MultiMap; /** @internal */ -export function arrayToMultiMap(values: readonly V[], makeKey: (value: V) => K, makeValue: (value: V) => U): MultiMap; -/** @internal */ -export function arrayToMultiMap(values: readonly V[], makeKey: (value: V) => K, makeValue: (value: V) => V | U = identity): MultiMap { +export function arrayToMultiMap( + values: readonly V[], + makeKey: (value: V) => K, + makeValue: (value: V) => U, +): MultiMap; +/** @internal */ +export function arrayToMultiMap( + values: readonly V[], + makeKey: (value: V) => K, + makeValue: (value: V) => V | U = identity, +): MultiMap { const result = createMultiMap(); for (const value of values) { result.add(makeKey(value), makeValue(value)); @@ -1532,21 +1747,42 @@ export function arrayToMultiMap(values: readonly V[], makeKey: (value: /** @internal */ export function group(values: readonly T[], getGroupId: (value: T) => K): readonly (readonly T[])[]; /** @internal */ -export function group(values: readonly T[], getGroupId: (value: T) => K, resultSelector: (values: readonly T[]) => R): R[]; +export function group( + values: readonly T[], + getGroupId: (value: T) => K, + resultSelector: (values: readonly T[]) => R, +): R[]; /** @internal */ export function group(values: readonly T[], getGroupId: (value: T) => string): readonly (readonly T[])[]; /** @internal */ -export function group(values: readonly T[], getGroupId: (value: T) => string, resultSelector: (values: readonly T[]) => R): R[]; -/** @internal */ -export function group(values: readonly T[], getGroupId: (value: T) => K, resultSelector: (values: readonly T[]) => readonly T[] = identity): readonly (readonly T[])[] { +export function group( + values: readonly T[], + getGroupId: (value: T) => string, + resultSelector: (values: readonly T[]) => R, +): R[]; +/** @internal */ +export function group( + values: readonly T[], + getGroupId: (value: T) => K, + resultSelector: (values: readonly T[]) => readonly T[] = identity, +): readonly (readonly T[])[] { return arrayFrom(arrayToMultiMap(values, getGroupId).values(), resultSelector); } /** @internal */ -export function groupBy(values: readonly T[] | undefined, keySelector: (value: T) => value is U): { true?: U[]; false?: Exclude[]; }; +export function groupBy( + values: readonly T[] | undefined, + keySelector: (value: T) => value is U, +): { true?: U[]; false?: Exclude[]; }; /** @internal */ -export function groupBy(values: readonly T[] | undefined, keySelector: (value: T) => K): { [P in K as `${P}`]?: T[]; }; -export function groupBy(values: readonly T[] | undefined, keySelector: (value: T) => K): { [P in K as `${P}`]?: T[]; } { +export function groupBy( + values: readonly T[] | undefined, + keySelector: (value: T) => K, +): { [P in K as `${P}`]?: T[]; }; +export function groupBy( + values: readonly T[] | undefined, + keySelector: (value: T) => K, +): { [P in K as `${P}`]?: T[]; } { const result: Record = {}; if (values) { for (const value of values) { @@ -1603,7 +1839,10 @@ export function copyProperties(first: T1, second: T2) { } /** @internal */ -export function maybeBind(obj: T, fn: ((this: T, ...args: A) => R) | undefined): ((...args: A) => R) | undefined { +export function maybeBind( + obj: T, + fn: ((this: T, ...args: A) => R) | undefined, +): ((...args: A) => R) | undefined { return fn ? fn.bind(obj) : undefined; } @@ -1703,7 +1942,10 @@ export function createQueue(items?: readonly T[]): Queue { * * @internal */ -export function createSet(getHashCode: (element: TElement) => THash, equals: EqualityComparer): Set { +export function createSet( + getHashCode: (element: TElement) => THash, + equals: EqualityComparer, +): Set { const multiMap = new Map(); let size = 0; @@ -1862,7 +2104,10 @@ export function isNumber(x: unknown): x is number { } /** @internal */ -export function tryCast(value: TIn | undefined, test: (value: TIn) => value is TOut): TOut | undefined { +export function tryCast( + value: TIn | undefined, + test: (value: TIn) => value is TOut, +): TOut | undefined { return value !== undefined && test(value) ? value : undefined; } @@ -1870,7 +2115,9 @@ export function tryCast(value: TIn | undefined, tes export function cast(value: TIn | undefined, test: (value: TIn) => value is TOut): TOut { if (value !== undefined && test(value)) return value; - return Debug.fail(`Invalid cast. The supplied value ${value} did not pass the test '${Debug.getFunctionName(test)}'.`); + return Debug.fail( + `Invalid cast. The supplied value ${value} did not pass the test '${Debug.getFunctionName(test)}'.`, + ); } /** @@ -1962,9 +2209,9 @@ const fileNameLowerCaseRegExp = /[^\u0130\u0131\u00DFa-z0-9\\/:\-_. ]+/g; * @internal */ export function toFileNameLowerCase(x: string) { - return fileNameLowerCaseRegExp.test(x) ? - x.replace(fileNameLowerCaseRegExp, toLowerCase) : - x; + return fileNameLowerCaseRegExp.test(x) + ? x.replace(fileNameLowerCaseRegExp, toLowerCase) + : x; } /** @@ -2035,7 +2282,10 @@ export interface MemoizeCache { * * @internal */ -export function memoizeCached(callback: (...args: A) => T, cache: MemoizeCache): (...args: A) => T { +export function memoizeCached( + callback: (...args: A) => T, + cache: MemoizeCache, +): (...args: A) => T { return (...args: A) => { let value = cache.get(args); if (value === undefined && !cache.has(args)) { @@ -2056,7 +2306,13 @@ export function memoizeCached(callback: (...args: A) => T, c */ export function compose(...args: ((t: T) => T)[]): (t: T) => T; /** @internal */ -export function compose(a: (t: T) => T, b: (t: T) => T, c: (t: T) => T, d: (t: T) => T, e: (t: T) => T): (t: T) => T { +export function compose( + a: (t: T) => T, + b: (t: T) => T, + c: (t: T) => T, + d: (t: T) => T, + e: (t: T) => T, +): (t: T) => T { if (!!e) { const args: ((t: T) => T)[] = []; for (let i = 0; i < arguments.length; i++) { @@ -2136,11 +2392,11 @@ export function equateStringsCaseSensitive(a: string, b: string) { function compareComparableValues(a: string | undefined, b: string | undefined): Comparison; function compareComparableValues(a: number | undefined, b: number | undefined): Comparison; function compareComparableValues(a: string | number | undefined, b: string | number | undefined) { - return a === b ? Comparison.EqualTo : - a === undefined ? Comparison.LessThan : - b === undefined ? Comparison.GreaterThan : - a < b ? Comparison.LessThan : - Comparison.GreaterThan; + return a === b ? Comparison.EqualTo + : a === undefined ? Comparison.LessThan + : b === undefined ? Comparison.GreaterThan + : a < b ? Comparison.LessThan + : Comparison.GreaterThan; } /** @@ -2246,7 +2502,11 @@ const createUIStringComparer = (() => { const stringComparerFactory = getStringComparerFactory(); return createStringComparer; - function compareWithCallback(a: string | undefined, b: string | undefined, comparer: (a: string, b: string) => number) { + function compareWithCallback( + a: string | undefined, + b: string | undefined, + comparer: (a: string, b: string) => number, + ) { if (a === b) return Comparison.EqualTo; if (a === undefined) return Comparison.LessThan; if (b === undefined) return Comparison.GreaterThan; @@ -2300,9 +2560,9 @@ const createUIStringComparer = (() => { // If the host does not support Intl, we fall back to localeCompare. // localeCompare in Node v0.10 is just an ordinal comparison, so don't use it. if ( - typeof String.prototype.localeCompare === "function" && - typeof String.prototype.toLocaleUpperCase === "function" && - "a".localeCompare("B") < 0 + typeof String.prototype.localeCompare === "function" + && typeof String.prototype.toLocaleUpperCase === "function" + && "a".localeCompare("B") < 0 ) { return createLocaleCompareStringComparer; } @@ -2360,11 +2620,16 @@ export function compareStringsCaseSensitiveUI(a: string, b: string) { } /** @internal */ -export function compareProperties(a: T | undefined, b: T | undefined, key: K, comparer: Comparer): Comparison { - return a === b ? Comparison.EqualTo : - a === undefined ? Comparison.LessThan : - b === undefined ? Comparison.GreaterThan : - comparer(a[key], b[key]); +export function compareProperties( + a: T | undefined, + b: T | undefined, + key: K, + comparer: Comparer, +): Comparison { + return a === b ? Comparison.EqualTo + : a === undefined ? Comparison.LessThan + : b === undefined ? Comparison.GreaterThan + : comparer(a[key], b[key]); } /** @@ -2390,7 +2655,11 @@ export function compareBooleans(a: boolean, b: boolean): Comparison { * * @internal */ -export function getSpellingSuggestion(name: string, candidates: T[], getName: (candidate: T) => string | undefined): T | undefined { +export function getSpellingSuggestion( + name: string, + candidates: T[], + getName: (candidate: T) => string | undefined, +): T | undefined { const maximumLengthDifference = Math.max(2, Math.floor(name.length * 0.34)); let bestDistance = Math.floor(name.length * 0.4) + 1; // If the best result is worse than this, don't bother. let bestCandidate: T | undefined; @@ -2446,7 +2715,11 @@ function levenshteinWithMax(s1: string, s2: string, max: number): number | undef : (previous[j - 1] + 2); const dist = c1 === s2.charCodeAt(j - 1) ? previous[j - 1] - : Math.min(/*delete*/ previous[j] + 1, /*insert*/ current[j - 1] + 1, /*substitute*/ substitutionDistance); + : Math.min( + /*delete*/ previous[j] + 1, + /*insert*/ current[j - 1] + 1, + /*substitute*/ substitutionDistance, + ); current[j] = dist; colMin = Math.min(colMin, dist); } @@ -2635,7 +2908,11 @@ export function matchedText(pattern: Pattern, candidate: string): string { * * @internal */ -export function findBestPatternMatch(values: readonly T[], getPattern: (value: T) => Pattern, candidate: string): T | undefined { +export function findBestPatternMatch( + values: readonly T[], + getPattern: (value: T) => Pattern, + candidate: string, +): T | undefined { let matchedValue: T | undefined; // use length of prefix as betterness criteria let longestMatchPrefixLength = -1; @@ -2662,15 +2939,20 @@ export function removePrefix(str: string, prefix: string): string { } /** @internal */ -export function tryRemovePrefix(str: string, prefix: string, getCanonicalFileName: GetCanonicalFileName = identity): string | undefined { - return startsWith(getCanonicalFileName(str), getCanonicalFileName(prefix)) ? str.substring(prefix.length) : undefined; +export function tryRemovePrefix( + str: string, + prefix: string, + getCanonicalFileName: GetCanonicalFileName = identity, +): string | undefined { + return startsWith(getCanonicalFileName(str), getCanonicalFileName(prefix)) ? str.substring(prefix.length) + : undefined; } /** @internal */ export function isPatternMatch({ prefix, suffix }: Pattern, candidate: string) { - return candidate.length >= prefix.length + suffix.length && - startsWith(candidate, prefix) && - endsWith(candidate, suffix); + return candidate.length >= prefix.length + suffix.length + && startsWith(candidate, prefix) + && endsWith(candidate, suffix); } /** @internal */ @@ -2679,9 +2961,16 @@ export function and(f: (arg: T) => boolean, g: (arg: T) => boolean) { } /** @internal */ -export function or(f1: (p1: P) => p1 is R1, f2: (p2: P) => p2 is R2): (p: P) => p is R1 | R2; +export function or( + f1: (p1: P) => p1 is R1, + f2: (p2: P) => p2 is R2, +): (p: P) => p is R1 | R2; /** @internal */ -export function or(f1: (p1: P) => p1 is R1, f2: (p2: P) => p2 is R2, f3: (p3: P) => p3 is R3): (p: P) => p is R1 | R2 | R3; +export function or( + f1: (p1: P) => p1 is R1, + f2: (p2: P) => p2 is R2, + f3: (p3: P) => p3 is R3, +): (p: P) => p is R1 | R2 | R3; /** @internal */ export function or(...fs: ((...args: T) => U)[]): (...args: T) => U; /** @internal */ @@ -2712,7 +3001,14 @@ export function singleElementArray(t: T | undefined): T[] | undefined { } /** @internal */ -export function enumerateInsertsAndDeletes(newItems: readonly T[], oldItems: readonly U[], comparer: (a: T, b: U) => Comparison, inserted: (newItem: T) => void, deleted: (oldItem: U) => void, unchanged?: (oldItem: U, newItem: T) => void) { +export function enumerateInsertsAndDeletes( + newItems: readonly T[], + oldItems: readonly U[], + comparer: (a: T, b: U) => Comparison, + inserted: (newItem: T) => void, + deleted: (oldItem: U) => void, + unchanged?: (oldItem: U, newItem: T) => void, +) { unchanged = unchanged || noop; let newIndex = 0; let oldIndex = 0; @@ -2757,7 +3053,12 @@ export function cartesianProduct(arrays: readonly T[][]) { return result; } -function cartesianProductWorker(arrays: readonly (readonly T[])[], result: (readonly T[])[], outer: readonly T[] | undefined, index: number) { +function cartesianProductWorker( + arrays: readonly (readonly T[])[], + result: (readonly T[])[], + outer: readonly T[] | undefined, + index: number, +) { for (const element of arrays[index]) { let inner: T[]; if (outer) { @@ -2805,8 +3106,14 @@ export function padRight(s: string, length: number, padString: " " = " ") { /** @internal */ export function takeWhile(array: readonly T[], predicate: (element: T) => element is U): U[]; /** @internal */ -export function takeWhile(array: readonly T[] | undefined, predicate: (element: T) => element is U): U[] | undefined; -export function takeWhile(array: readonly T[] | undefined, predicate: (element: T) => element is U): U[] | undefined { +export function takeWhile( + array: readonly T[] | undefined, + predicate: (element: T) => element is U, +): U[] | undefined; +export function takeWhile( + array: readonly T[] | undefined, + predicate: (element: T) => element is U, +): U[] | undefined { if (array) { const len = array.length; let index = 0; @@ -2818,11 +3125,20 @@ export function takeWhile(array: readonly T[] | undefined, predi } /** @internal */ -export function skipWhile(array: readonly T[], predicate: (element: T) => element is U): Exclude[]; -/** @internal */ -export function skipWhile(array: readonly T[] | undefined, predicate: (element: T) => element is U): Exclude[] | undefined; -/** @internal */ -export function skipWhile(array: readonly T[] | undefined, predicate: (element: T) => element is U): Exclude[] | undefined { +export function skipWhile( + array: readonly T[], + predicate: (element: T) => element is U, +): Exclude[]; +/** @internal */ +export function skipWhile( + array: readonly T[] | undefined, + predicate: (element: T) => element is U, +): Exclude[] | undefined; +/** @internal */ +export function skipWhile( + array: readonly T[] | undefined, + predicate: (element: T) => element is U, +): Exclude[] | undefined { if (array) { const len = array.length; let index = 0; @@ -2838,7 +3154,8 @@ export function skipWhile(array: readonly T[] | undefined, predi * * @internal */ -export const trimString = !!String.prototype.trim ? ((s: string) => s.trim()) : (s: string) => trimStringEnd(trimStringStart(s)); +export const trimString = !!String.prototype.trim ? ((s: string) => s.trim()) + : (s: string) => trimStringEnd(trimStringStart(s)); /** * Returns a copy with trailing whitespace removed. @@ -2852,7 +3169,8 @@ export const trimStringEnd = !!String.prototype.trimEnd ? ((s: string) => s.trim * * @internal */ -export const trimStringStart = !!String.prototype.trimStart ? ((s: string) => s.trimStart()) : (s: string) => s.replace(/^\s+/g, ""); +export const trimStringStart = !!String.prototype.trimStart ? ((s: string) => s.trimStart()) + : (s: string) => s.replace(/^\s+/g, ""); /** * https://jsbench.me/gjkoxld4au/1 diff --git a/src/compiler/debug.ts b/src/compiler/debug.ts index 7b5a81d93a89d..a6adda4ecf18d 100644 --- a/src/compiler/debug.ts +++ b/src/compiler/debug.ts @@ -209,11 +209,17 @@ export namespace Debug { ); } - export function assert(expression: unknown, message?: string, verboseDebugInfo?: string | (() => string), stackCrawlMark?: AnyFunction): asserts expression { + export function assert( + expression: unknown, + message?: string, + verboseDebugInfo?: string | (() => string), + stackCrawlMark?: AnyFunction, + ): asserts expression { if (!expression) { message = message ? `False expression: ${message}` : "False expression."; if (verboseDebugInfo) { - message += "\r\nVerbose Debug Information: " + (typeof verboseDebugInfo === "string" ? verboseDebugInfo : verboseDebugInfo()); + message += "\r\nVerbose Debug Information: " + + (typeof verboseDebugInfo === "string" ? verboseDebugInfo : verboseDebugInfo()); } fail(message, stackCrawlMark || assert); } @@ -244,7 +250,11 @@ export namespace Debug { } } - export function assertIsDefined(value: T, message?: string, stackCrawlMark?: AnyFunction): asserts value is NonNullable { + export function assertIsDefined( + value: T, + message?: string, + stackCrawlMark?: AnyFunction, + ): asserts value is NonNullable { // eslint-disable-next-line no-null/no-null if (value === undefined || value === null) { fail(message, stackCrawlMark || assertIsDefined); @@ -256,30 +266,73 @@ export namespace Debug { return value; } - export function assertEachIsDefined(value: NodeArray, message?: string, stackCrawlMark?: AnyFunction): asserts value is NodeArray; - export function assertEachIsDefined(value: readonly T[], message?: string, stackCrawlMark?: AnyFunction): asserts value is readonly NonNullable[]; + export function assertEachIsDefined( + value: NodeArray, + message?: string, + stackCrawlMark?: AnyFunction, + ): asserts value is NodeArray; + export function assertEachIsDefined( + value: readonly T[], + message?: string, + stackCrawlMark?: AnyFunction, + ): asserts value is readonly NonNullable[]; export function assertEachIsDefined(value: readonly T[], message?: string, stackCrawlMark?: AnyFunction) { for (const v of value) { assertIsDefined(v, message, stackCrawlMark || assertEachIsDefined); } } - export function checkEachDefined(value: A, message?: string, stackCrawlMark?: AnyFunction): A { + export function checkEachDefined( + value: A, + message?: string, + stackCrawlMark?: AnyFunction, + ): A { assertEachIsDefined(value, message, stackCrawlMark || checkEachDefined); return value; } export function assertNever(member: never, message = "Illegal value:", stackCrawlMark?: AnyFunction): never { - const detail = typeof member === "object" && hasProperty(member, "kind") && hasProperty(member, "pos") ? "SyntaxKind: " + formatSyntaxKind((member as Node).kind) : JSON.stringify(member); + const detail = typeof member === "object" && hasProperty(member, "kind") && hasProperty(member, "pos") + ? "SyntaxKind: " + formatSyntaxKind((member as Node).kind) : JSON.stringify(member); return fail(`${message} ${detail}`, stackCrawlMark || assertNever); } - export function assertEachNode(nodes: NodeArray, test: (node: T) => node is U, message?: string, stackCrawlMark?: AnyFunction): asserts nodes is NodeArray; - export function assertEachNode(nodes: readonly T[], test: (node: T) => node is U, message?: string, stackCrawlMark?: AnyFunction): asserts nodes is readonly U[]; - export function assertEachNode(nodes: NodeArray | undefined, test: (node: T) => node is U, message?: string, stackCrawlMark?: AnyFunction): asserts nodes is NodeArray | undefined; - export function assertEachNode(nodes: readonly T[] | undefined, test: (node: T) => node is U, message?: string, stackCrawlMark?: AnyFunction): asserts nodes is readonly U[] | undefined; - export function assertEachNode(nodes: readonly Node[], test: ((node: Node) => boolean) | undefined, message?: string, stackCrawlMark?: AnyFunction): void; - export function assertEachNode(nodes: readonly Node[] | undefined, test: ((node: Node) => boolean) | undefined, message?: string, stackCrawlMark?: AnyFunction) { + export function assertEachNode( + nodes: NodeArray, + test: (node: T) => node is U, + message?: string, + stackCrawlMark?: AnyFunction, + ): asserts nodes is NodeArray; + export function assertEachNode( + nodes: readonly T[], + test: (node: T) => node is U, + message?: string, + stackCrawlMark?: AnyFunction, + ): asserts nodes is readonly U[]; + export function assertEachNode( + nodes: NodeArray | undefined, + test: (node: T) => node is U, + message?: string, + stackCrawlMark?: AnyFunction, + ): asserts nodes is NodeArray | undefined; + export function assertEachNode( + nodes: readonly T[] | undefined, + test: (node: T) => node is U, + message?: string, + stackCrawlMark?: AnyFunction, + ): asserts nodes is readonly U[] | undefined; + export function assertEachNode( + nodes: readonly Node[], + test: ((node: Node) => boolean) | undefined, + message?: string, + stackCrawlMark?: AnyFunction, + ): void; + export function assertEachNode( + nodes: readonly Node[] | undefined, + test: ((node: Node) => boolean) | undefined, + message?: string, + stackCrawlMark?: AnyFunction, + ) { if (shouldAssertFunction(AssertionLevel.Normal, "assertEachNode")) { assert( test === undefined || every(nodes, test), @@ -290,9 +343,24 @@ export namespace Debug { } } - export function assertNode(node: T | undefined, test: (node: T) => node is U, message?: string, stackCrawlMark?: AnyFunction): asserts node is U; - export function assertNode(node: Node | undefined, test: ((node: Node) => boolean) | undefined, message?: string, stackCrawlMark?: AnyFunction): void; - export function assertNode(node: Node | undefined, test: ((node: Node) => boolean) | undefined, message?: string, stackCrawlMark?: AnyFunction) { + export function assertNode( + node: T | undefined, + test: (node: T) => node is U, + message?: string, + stackCrawlMark?: AnyFunction, + ): asserts node is U; + export function assertNode( + node: Node | undefined, + test: ((node: Node) => boolean) | undefined, + message?: string, + stackCrawlMark?: AnyFunction, + ): void; + export function assertNode( + node: Node | undefined, + test: ((node: Node) => boolean) | undefined, + message?: string, + stackCrawlMark?: AnyFunction, + ) { if (shouldAssertFunction(AssertionLevel.Normal, "assertNode")) { assert( node !== undefined && (test === undefined || test(node)), @@ -303,9 +371,24 @@ export namespace Debug { } } - export function assertNotNode(node: T | undefined, test: (node: Node) => node is U, message?: string, stackCrawlMark?: AnyFunction): asserts node is Exclude; - export function assertNotNode(node: Node | undefined, test: ((node: Node) => boolean) | undefined, message?: string, stackCrawlMark?: AnyFunction): void; - export function assertNotNode(node: Node | undefined, test: ((node: Node) => boolean) | undefined, message?: string, stackCrawlMark?: AnyFunction) { + export function assertNotNode( + node: T | undefined, + test: (node: Node) => node is U, + message?: string, + stackCrawlMark?: AnyFunction, + ): asserts node is Exclude; + export function assertNotNode( + node: Node | undefined, + test: ((node: Node) => boolean) | undefined, + message?: string, + stackCrawlMark?: AnyFunction, + ): void; + export function assertNotNode( + node: Node | undefined, + test: ((node: Node) => boolean) | undefined, + message?: string, + stackCrawlMark?: AnyFunction, + ) { if (shouldAssertFunction(AssertionLevel.Normal, "assertNotNode")) { assert( node === undefined || test === undefined || !test(node), @@ -316,10 +399,30 @@ export namespace Debug { } } - export function assertOptionalNode(node: T, test: (node: T) => node is U, message?: string, stackCrawlMark?: AnyFunction): asserts node is U; - export function assertOptionalNode(node: T | undefined, test: (node: T) => node is U, message?: string, stackCrawlMark?: AnyFunction): asserts node is U | undefined; - export function assertOptionalNode(node: Node | undefined, test: ((node: Node) => boolean) | undefined, message?: string, stackCrawlMark?: AnyFunction): void; - export function assertOptionalNode(node: Node | undefined, test: ((node: Node) => boolean) | undefined, message?: string, stackCrawlMark?: AnyFunction) { + export function assertOptionalNode( + node: T, + test: (node: T) => node is U, + message?: string, + stackCrawlMark?: AnyFunction, + ): asserts node is U; + export function assertOptionalNode( + node: T | undefined, + test: (node: T) => node is U, + message?: string, + stackCrawlMark?: AnyFunction, + ): asserts node is U | undefined; + export function assertOptionalNode( + node: Node | undefined, + test: ((node: Node) => boolean) | undefined, + message?: string, + stackCrawlMark?: AnyFunction, + ): void; + export function assertOptionalNode( + node: Node | undefined, + test: ((node: Node) => boolean) | undefined, + message?: string, + stackCrawlMark?: AnyFunction, + ) { if (shouldAssertFunction(AssertionLevel.Normal, "assertOptionalNode")) { assert( test === undefined || node === undefined || test(node), @@ -330,10 +433,30 @@ export namespace Debug { } } - export function assertOptionalToken(node: T, kind: K, message?: string, stackCrawlMark?: AnyFunction): asserts node is Extract; - export function assertOptionalToken(node: T | undefined, kind: K, message?: string, stackCrawlMark?: AnyFunction): asserts node is Extract | undefined; - export function assertOptionalToken(node: Node | undefined, kind: SyntaxKind | undefined, message?: string, stackCrawlMark?: AnyFunction): void; - export function assertOptionalToken(node: Node | undefined, kind: SyntaxKind | undefined, message?: string, stackCrawlMark?: AnyFunction) { + export function assertOptionalToken( + node: T, + kind: K, + message?: string, + stackCrawlMark?: AnyFunction, + ): asserts node is Extract; + export function assertOptionalToken( + node: T | undefined, + kind: K, + message?: string, + stackCrawlMark?: AnyFunction, + ): asserts node is Extract | undefined; + export function assertOptionalToken( + node: Node | undefined, + kind: SyntaxKind | undefined, + message?: string, + stackCrawlMark?: AnyFunction, + ): void; + export function assertOptionalToken( + node: Node | undefined, + kind: SyntaxKind | undefined, + message?: string, + stackCrawlMark?: AnyFunction, + ) { if (shouldAssertFunction(AssertionLevel.Normal, "assertOptionalToken")) { assert( kind === undefined || node === undefined || node.kind === kind, @@ -344,7 +467,11 @@ export namespace Debug { } } - export function assertMissingNode(node: Node | undefined, message?: string, stackCrawlMark?: AnyFunction): asserts node is undefined; + export function assertMissingNode( + node: Node | undefined, + message?: string, + stackCrawlMark?: AnyFunction, + ): asserts node is undefined; export function assertMissingNode(node: Node | undefined, message?: string, stackCrawlMark?: AnyFunction) { if (shouldAssertFunction(AssertionLevel.Normal, "assertMissingNode")) { assert( @@ -379,7 +506,9 @@ export namespace Debug { } export function formatSymbol(symbol: Symbol): string { - return `{ name: ${unescapeLeadingUnderscores(symbol.escapedName)}; flags: ${formatSymbolFlags(symbol.flags)}; declarations: ${map(symbol.declarations, node => formatSyntaxKind(node.kind))} }`; + return `{ name: ${unescapeLeadingUnderscores(symbol.escapedName)}; flags: ${ + formatSymbolFlags(symbol.flags) + }; declarations: ${map(symbol.declarations, node => formatSyntaxKind(node.kind))} }`; } /** @@ -514,18 +643,18 @@ export namespace Debug { // for use with vscode-js-debug's new customDescriptionGenerator in launch.json __tsDebuggerDisplay: { value(this: FlowNodeBase) { - const flowHeader = this.flags & FlowFlags.Start ? "FlowStart" : - this.flags & FlowFlags.BranchLabel ? "FlowBranchLabel" : - this.flags & FlowFlags.LoopLabel ? "FlowLoopLabel" : - this.flags & FlowFlags.Assignment ? "FlowAssignment" : - this.flags & FlowFlags.TrueCondition ? "FlowTrueCondition" : - this.flags & FlowFlags.FalseCondition ? "FlowFalseCondition" : - this.flags & FlowFlags.SwitchClause ? "FlowSwitchClause" : - this.flags & FlowFlags.ArrayMutation ? "FlowArrayMutation" : - this.flags & FlowFlags.Call ? "FlowCall" : - this.flags & FlowFlags.ReduceLabel ? "FlowReduceLabel" : - this.flags & FlowFlags.Unreachable ? "FlowUnreachable" : - "UnknownFlow"; + const flowHeader = this.flags & FlowFlags.Start ? "FlowStart" + : this.flags & FlowFlags.BranchLabel ? "FlowBranchLabel" + : this.flags & FlowFlags.LoopLabel ? "FlowLoopLabel" + : this.flags & FlowFlags.Assignment ? "FlowAssignment" + : this.flags & FlowFlags.TrueCondition ? "FlowTrueCondition" + : this.flags & FlowFlags.FalseCondition ? "FlowFalseCondition" + : this.flags & FlowFlags.SwitchClause ? "FlowSwitchClause" + : this.flags & FlowFlags.ArrayMutation ? "FlowArrayMutation" + : this.flags & FlowFlags.Call ? "FlowCall" + : this.flags & FlowFlags.ReduceLabel ? "FlowReduceLabel" + : this.flags & FlowFlags.Unreachable ? "FlowUnreachable" + : "UnknownFlow"; const remainingFlags = this.flags & ~(FlowFlags.Referenced - 1); return `${flowHeader}${remainingFlags ? ` (${formatFlowFlags(remainingFlags)})` : ""}`; }, @@ -616,10 +745,12 @@ export namespace Debug { // for use with vscode-js-debug's new customDescriptionGenerator in launch.json __tsDebuggerDisplay: { value(this: Symbol) { - const symbolHeader = this.flags & SymbolFlags.Transient ? "TransientSymbol" : - "Symbol"; + const symbolHeader = this.flags & SymbolFlags.Transient ? "TransientSymbol" + : "Symbol"; const remainingSymbolFlags = this.flags & ~SymbolFlags.Transient; - return `${symbolHeader} '${symbolName(this)}'${remainingSymbolFlags ? ` (${formatSymbolFlags(remainingSymbolFlags)})` : ""}`; + return `${symbolHeader} '${symbolName(this)}'${ + remainingSymbolFlags ? ` (${formatSymbolFlags(remainingSymbolFlags)})` : "" + }`; }, }, __debugFlags: { @@ -633,31 +764,38 @@ export namespace Debug { // for use with vscode-js-debug's new customDescriptionGenerator in launch.json __tsDebuggerDisplay: { value(this: Type) { - const typeHeader = this.flags & TypeFlags.Nullable ? "NullableType" : - this.flags & TypeFlags.StringOrNumberLiteral ? `LiteralType ${JSON.stringify((this as LiteralType).value)}` : - this.flags & TypeFlags.BigIntLiteral ? `LiteralType ${(this as BigIntLiteralType).value.negative ? "-" : ""}${(this as BigIntLiteralType).value.base10Value}n` : - this.flags & TypeFlags.UniqueESSymbol ? "UniqueESSymbolType" : - this.flags & TypeFlags.Enum ? "EnumType" : - this.flags & TypeFlags.Intrinsic ? `IntrinsicType ${(this as IntrinsicType).intrinsicName}` : - this.flags & TypeFlags.Union ? "UnionType" : - this.flags & TypeFlags.Intersection ? "IntersectionType" : - this.flags & TypeFlags.Index ? "IndexType" : - this.flags & TypeFlags.IndexedAccess ? "IndexedAccessType" : - this.flags & TypeFlags.Conditional ? "ConditionalType" : - this.flags & TypeFlags.Substitution ? "SubstitutionType" : - this.flags & TypeFlags.TypeParameter ? "TypeParameter" : - this.flags & TypeFlags.Object ? - (this as ObjectType).objectFlags & ObjectFlags.ClassOrInterface ? "InterfaceType" : - (this as ObjectType).objectFlags & ObjectFlags.Reference ? "TypeReference" : - (this as ObjectType).objectFlags & ObjectFlags.Tuple ? "TupleType" : - (this as ObjectType).objectFlags & ObjectFlags.Anonymous ? "AnonymousType" : - (this as ObjectType).objectFlags & ObjectFlags.Mapped ? "MappedType" : - (this as ObjectType).objectFlags & ObjectFlags.ReverseMapped ? "ReverseMappedType" : - (this as ObjectType).objectFlags & ObjectFlags.EvolvingArray ? "EvolvingArrayType" : - "ObjectType" : - "Type"; - const remainingObjectFlags = this.flags & TypeFlags.Object ? (this as ObjectType).objectFlags & ~ObjectFlags.ObjectTypeKindMask : 0; - return `${typeHeader}${this.symbol ? ` '${symbolName(this.symbol)}'` : ""}${remainingObjectFlags ? ` (${formatObjectFlags(remainingObjectFlags)})` : ""}`; + const typeHeader = this.flags & TypeFlags.Nullable ? "NullableType" + : this.flags & TypeFlags.StringOrNumberLiteral + ? `LiteralType ${JSON.stringify((this as LiteralType).value)}` + : this.flags & TypeFlags.BigIntLiteral + ? `LiteralType ${(this as BigIntLiteralType).value.negative ? "-" : ""}${ + (this as BigIntLiteralType).value.base10Value + }n` + : this.flags & TypeFlags.UniqueESSymbol ? "UniqueESSymbolType" + : this.flags & TypeFlags.Enum ? "EnumType" + : this.flags & TypeFlags.Intrinsic ? `IntrinsicType ${(this as IntrinsicType).intrinsicName}` + : this.flags & TypeFlags.Union ? "UnionType" + : this.flags & TypeFlags.Intersection ? "IntersectionType" + : this.flags & TypeFlags.Index ? "IndexType" + : this.flags & TypeFlags.IndexedAccess ? "IndexedAccessType" + : this.flags & TypeFlags.Conditional ? "ConditionalType" + : this.flags & TypeFlags.Substitution ? "SubstitutionType" + : this.flags & TypeFlags.TypeParameter ? "TypeParameter" + : this.flags & TypeFlags.Object + ? (this as ObjectType).objectFlags & ObjectFlags.ClassOrInterface ? "InterfaceType" + : (this as ObjectType).objectFlags & ObjectFlags.Reference ? "TypeReference" + : (this as ObjectType).objectFlags & ObjectFlags.Tuple ? "TupleType" + : (this as ObjectType).objectFlags & ObjectFlags.Anonymous ? "AnonymousType" + : (this as ObjectType).objectFlags & ObjectFlags.Mapped ? "MappedType" + : (this as ObjectType).objectFlags & ObjectFlags.ReverseMapped ? "ReverseMappedType" + : (this as ObjectType).objectFlags & ObjectFlags.EvolvingArray ? "EvolvingArrayType" + : "ObjectType" + : "Type"; + const remainingObjectFlags = this.flags & TypeFlags.Object + ? (this as ObjectType).objectFlags & ~ObjectFlags.ObjectTypeKindMask : 0; + return `${typeHeader}${this.symbol ? ` '${symbolName(this.symbol)}'` : ""}${ + remainingObjectFlags ? ` (${formatObjectFlags(remainingObjectFlags)})` : "" + }`; }, }, __debugFlags: { @@ -709,43 +847,46 @@ export namespace Debug { // for use with vscode-js-debug's new customDescriptionGenerator in launch.json __tsDebuggerDisplay: { value(this: Node) { - const nodeHeader = isGeneratedIdentifier(this) ? "GeneratedIdentifier" : - isIdentifier(this) ? `Identifier '${idText(this)}'` : - isPrivateIdentifier(this) ? `PrivateIdentifier '${idText(this)}'` : - isStringLiteral(this) ? `StringLiteral ${JSON.stringify(this.text.length < 10 ? this.text : this.text.slice(10) + "...")}` : - isNumericLiteral(this) ? `NumericLiteral ${this.text}` : - isBigIntLiteral(this) ? `BigIntLiteral ${this.text}n` : - isTypeParameterDeclaration(this) ? "TypeParameterDeclaration" : - isParameter(this) ? "ParameterDeclaration" : - isConstructorDeclaration(this) ? "ConstructorDeclaration" : - isGetAccessorDeclaration(this) ? "GetAccessorDeclaration" : - isSetAccessorDeclaration(this) ? "SetAccessorDeclaration" : - isCallSignatureDeclaration(this) ? "CallSignatureDeclaration" : - isConstructSignatureDeclaration(this) ? "ConstructSignatureDeclaration" : - isIndexSignatureDeclaration(this) ? "IndexSignatureDeclaration" : - isTypePredicateNode(this) ? "TypePredicateNode" : - isTypeReferenceNode(this) ? "TypeReferenceNode" : - isFunctionTypeNode(this) ? "FunctionTypeNode" : - isConstructorTypeNode(this) ? "ConstructorTypeNode" : - isTypeQueryNode(this) ? "TypeQueryNode" : - isTypeLiteralNode(this) ? "TypeLiteralNode" : - isArrayTypeNode(this) ? "ArrayTypeNode" : - isTupleTypeNode(this) ? "TupleTypeNode" : - isOptionalTypeNode(this) ? "OptionalTypeNode" : - isRestTypeNode(this) ? "RestTypeNode" : - isUnionTypeNode(this) ? "UnionTypeNode" : - isIntersectionTypeNode(this) ? "IntersectionTypeNode" : - isConditionalTypeNode(this) ? "ConditionalTypeNode" : - isInferTypeNode(this) ? "InferTypeNode" : - isParenthesizedTypeNode(this) ? "ParenthesizedTypeNode" : - isThisTypeNode(this) ? "ThisTypeNode" : - isTypeOperatorNode(this) ? "TypeOperatorNode" : - isIndexedAccessTypeNode(this) ? "IndexedAccessTypeNode" : - isMappedTypeNode(this) ? "MappedTypeNode" : - isLiteralTypeNode(this) ? "LiteralTypeNode" : - isNamedTupleMember(this) ? "NamedTupleMember" : - isImportTypeNode(this) ? "ImportTypeNode" : - formatSyntaxKind(this.kind); + const nodeHeader = isGeneratedIdentifier(this) ? "GeneratedIdentifier" + : isIdentifier(this) ? `Identifier '${idText(this)}'` + : isPrivateIdentifier(this) ? `PrivateIdentifier '${idText(this)}'` + : isStringLiteral(this) + ? `StringLiteral ${ + JSON.stringify(this.text.length < 10 ? this.text : this.text.slice(10) + "...") + }` + : isNumericLiteral(this) ? `NumericLiteral ${this.text}` + : isBigIntLiteral(this) ? `BigIntLiteral ${this.text}n` + : isTypeParameterDeclaration(this) ? "TypeParameterDeclaration" + : isParameter(this) ? "ParameterDeclaration" + : isConstructorDeclaration(this) ? "ConstructorDeclaration" + : isGetAccessorDeclaration(this) ? "GetAccessorDeclaration" + : isSetAccessorDeclaration(this) ? "SetAccessorDeclaration" + : isCallSignatureDeclaration(this) ? "CallSignatureDeclaration" + : isConstructSignatureDeclaration(this) ? "ConstructSignatureDeclaration" + : isIndexSignatureDeclaration(this) ? "IndexSignatureDeclaration" + : isTypePredicateNode(this) ? "TypePredicateNode" + : isTypeReferenceNode(this) ? "TypeReferenceNode" + : isFunctionTypeNode(this) ? "FunctionTypeNode" + : isConstructorTypeNode(this) ? "ConstructorTypeNode" + : isTypeQueryNode(this) ? "TypeQueryNode" + : isTypeLiteralNode(this) ? "TypeLiteralNode" + : isArrayTypeNode(this) ? "ArrayTypeNode" + : isTupleTypeNode(this) ? "TupleTypeNode" + : isOptionalTypeNode(this) ? "OptionalTypeNode" + : isRestTypeNode(this) ? "RestTypeNode" + : isUnionTypeNode(this) ? "UnionTypeNode" + : isIntersectionTypeNode(this) ? "IntersectionTypeNode" + : isConditionalTypeNode(this) ? "ConditionalTypeNode" + : isInferTypeNode(this) ? "InferTypeNode" + : isParenthesizedTypeNode(this) ? "ParenthesizedTypeNode" + : isThisTypeNode(this) ? "ThisTypeNode" + : isTypeOperatorNode(this) ? "TypeOperatorNode" + : isIndexedAccessTypeNode(this) ? "IndexedAccessTypeNode" + : isMappedTypeNode(this) ? "MappedTypeNode" + : isLiteralTypeNode(this) ? "LiteralTypeNode" + : isNamedTupleMember(this) ? "NamedTupleMember" + : isImportTypeNode(this) ? "ImportTypeNode" + : formatSyntaxKind(this.kind); return `${nodeHeader}${this.flags ? ` (${formatNodeFlags(this.flags)})` : ""}`; }, }, @@ -787,7 +928,8 @@ export namespace Debug { if (text === undefined) { const parseNode = getParseTreeNode(this); const sourceFile = parseNode && getSourceFileOfNode(parseNode); - text = sourceFile ? getSourceTextOfNodeFromSourceFile(sourceFile, parseNode, includeTrivia) : ""; + text = sourceFile + ? getSourceTextOfNodeFromSourceFile(sourceFile, parseNode, includeTrivia) : ""; weakNodeTextMap.set(this, text); } return text; @@ -802,11 +944,11 @@ export namespace Debug { export function formatVariance(varianceFlags: VarianceFlags) { const variance = varianceFlags & VarianceFlags.VarianceMask; - let result = variance === VarianceFlags.Invariant ? "in out" : - variance === VarianceFlags.Bivariant ? "[bivariant]" : - variance === VarianceFlags.Contravariant ? "in" : - variance === VarianceFlags.Covariant ? "out" : - variance === VarianceFlags.Independent ? "[independent]" : ""; + let result = variance === VarianceFlags.Invariant ? "in out" + : variance === VarianceFlags.Bivariant ? "[bivariant]" + : variance === VarianceFlags.Contravariant ? "in" + : variance === VarianceFlags.Covariant ? "out" + : variance === VarianceFlags.Independent ? "[independent]" : ""; if (varianceFlags & VarianceFlags.Unmeasurable) { result += " (unmeasurable)"; } @@ -825,22 +967,28 @@ export namespace Debug { case TypeMapKind.Function: return this.debugInfo?.() || "(function mapper)"; case TypeMapKind.Simple: - return `${(this.source as DebugType).__debugTypeToString()} -> ${(this.target as DebugType).__debugTypeToString()}`; + return `${(this.source as DebugType).__debugTypeToString()} -> ${ + (this.target as DebugType).__debugTypeToString() + }`; case TypeMapKind.Array: return zipWith( this.sources as readonly DebugType[], this.targets as readonly DebugType[] || map(this.sources, () => "any"), - (s, t) => `${s.__debugTypeToString()} -> ${typeof t === "string" ? t : t.__debugTypeToString()}`, + (s, t) => + `${s.__debugTypeToString()} -> ${typeof t === "string" ? t : t.__debugTypeToString()}`, ).join(", "); case TypeMapKind.Deferred: return zipWith( this.sources, this.targets, - (s, t) => `${(s as DebugType).__debugTypeToString()} -> ${(t() as DebugType).__debugTypeToString()}`, + (s, t) => + `${(s as DebugType).__debugTypeToString()} -> ${(t() as DebugType).__debugTypeToString()}`, ).join(", "); case TypeMapKind.Merged: case TypeMapKind.Composite: - return `m1: ${(this.mapper1 as unknown as DebugTypeMapper).__debugToString().split("\n").join("\n ")} + return `m1: ${ + (this.mapper1 as unknown as DebugTypeMapper).__debugToString().split("\n").join("\n ") + } m2: ${(this.mapper2 as unknown as DebugTypeMapper).__debugToString().split("\n").join("\n ")}`; default: return assertNever(this); @@ -922,18 +1070,18 @@ m2: ${(this.mapper2 as unknown as DebugTypeMapper).__debugToString().split("\n") target: FlowGraphNode; } - const hasAntecedentFlags = FlowFlags.Assignment | - FlowFlags.Condition | - FlowFlags.SwitchClause | - FlowFlags.ArrayMutation | - FlowFlags.Call | - FlowFlags.ReduceLabel; + const hasAntecedentFlags = FlowFlags.Assignment + | FlowFlags.Condition + | FlowFlags.SwitchClause + | FlowFlags.ArrayMutation + | FlowFlags.Call + | FlowFlags.ReduceLabel; - const hasNodeFlags = FlowFlags.Start | - FlowFlags.Assignment | - FlowFlags.Call | - FlowFlags.Condition | - FlowFlags.ArrayMutation; + const hasNodeFlags = FlowFlags.Start + | FlowFlags.Assignment + | FlowFlags.Call + | FlowFlags.Condition + | FlowFlags.ArrayMutation; const links: Record = Object.create(/*o*/ null); // eslint-disable-line no-null/no-null const nodes: FlowGraphNode[] = []; @@ -1005,7 +1153,16 @@ m2: ${(this.mapper2 as unknown as DebugTypeMapper).__debugToString().split("\n") } seen.add(flowNode); if (!graphNode) { - links[id] = graphNode = { id, flowNode, edges: [], text: "", lane: -1, endLane: -1, level: -1, circular: false }; + links[id] = graphNode = { + id, + flowNode, + edges: [], + text: "", + lane: -1, + endLane: -1, + level: -1, + circular: false, + }; nodes.push(graphNode); if (hasAntecedents(flowNode)) { for (const antecedent of flowNode.antecedents) { @@ -1182,7 +1339,11 @@ m2: ${(this.mapper2 as unknown as DebugTypeMapper).__debugToString().split("\n") } } writeLane(lane, getBoxCharacter(connector)); - writeLane(lane, connector & Connection.Right && column < columnCount - 1 && !grid[column + 1][lane] ? BoxCharacter.lr : " "); + writeLane( + lane, + connector & Connection.Right && column < columnCount - 1 && !grid[column + 1][lane] + ? BoxCharacter.lr : " ", + ); } } diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index d407dadc246ae..a122c6503febb 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -490,7 +490,8 @@ export function forEachEmittedFile( onlyBuildInfo?: boolean, includeBuildInfo?: boolean, ) { - const sourceFiles = isArray(sourceFilesOrTargetSourceFile) ? sourceFilesOrTargetSourceFile : getSourceFilesToEmit(host, sourceFilesOrTargetSourceFile, forceDtsEmit); + const sourceFiles = isArray(sourceFilesOrTargetSourceFile) ? sourceFilesOrTargetSourceFile + : getSourceFilesToEmit(host, sourceFilesOrTargetSourceFile, forceDtsEmit); const options = host.getCompilerOptions(); if (outFile(options)) { const prepends = host.getPrependNodes(); @@ -530,11 +531,14 @@ export function getTsBuildInfoEmitOutputFilePath(options: CompilerOptions) { else { if (!configFile) return undefined; const configFileExtensionLess = removeFileExtension(configFile); - buildInfoExtensionLess = options.outDir ? - options.rootDir ? - resolvePath(options.outDir, getRelativePathFromDirectory(options.rootDir, configFileExtensionLess, /*ignoreCase*/ true)) : - combinePaths(options.outDir, getBaseFileName(configFileExtensionLess)) : - configFileExtensionLess; + buildInfoExtensionLess = options.outDir + ? options.rootDir + ? resolvePath( + options.outDir, + getRelativePathFromDirectory(options.rootDir, configFileExtensionLess, /*ignoreCase*/ true), + ) + : combinePaths(options.outDir, getBaseFileName(configFileExtensionLess)) + : configFileExtensionLess; } return buildInfoExtensionLess + Extension.TsBuildInfo; } @@ -544,28 +548,46 @@ export function getOutputPathsForBundle(options: CompilerOptions, forceDtsPaths: const outPath = outFile(options)!; const jsFilePath = options.emitDeclarationOnly ? undefined : outPath; const sourceMapFilePath = jsFilePath && getSourceMapFilePath(jsFilePath, options); - const declarationFilePath = (forceDtsPaths || getEmitDeclarations(options)) ? removeFileExtension(outPath) + Extension.Dts : undefined; - const declarationMapPath = declarationFilePath && getAreDeclarationMapsEnabled(options) ? declarationFilePath + ".map" : undefined; + const declarationFilePath = (forceDtsPaths || getEmitDeclarations(options)) + ? removeFileExtension(outPath) + Extension.Dts : undefined; + const declarationMapPath = declarationFilePath && getAreDeclarationMapsEnabled(options) + ? declarationFilePath + ".map" : undefined; const buildInfoPath = getTsBuildInfoEmitOutputFilePath(options); return { jsFilePath, sourceMapFilePath, declarationFilePath, declarationMapPath, buildInfoPath }; } /** @internal */ -export function getOutputPathsFor(sourceFile: SourceFile | Bundle, host: EmitHost, forceDtsPaths: boolean): EmitFileNames { +export function getOutputPathsFor( + sourceFile: SourceFile | Bundle, + host: EmitHost, + forceDtsPaths: boolean, +): EmitFileNames { const options = host.getCompilerOptions(); if (sourceFile.kind === SyntaxKind.Bundle) { return getOutputPathsForBundle(options, forceDtsPaths); } else { - const ownOutputFilePath = getOwnEmitOutputFilePath(sourceFile.fileName, host, getOutputExtension(sourceFile.fileName, options)); + const ownOutputFilePath = getOwnEmitOutputFilePath( + sourceFile.fileName, + host, + getOutputExtension(sourceFile.fileName, options), + ); const isJsonFile = isJsonSourceFile(sourceFile); // If json file emits to the same location skip writing it, if emitDeclarationOnly skip writing it - const isJsonEmittedToSameLocation = isJsonFile && - comparePaths(sourceFile.fileName, ownOutputFilePath, host.getCurrentDirectory(), !host.useCaseSensitiveFileNames()) === Comparison.EqualTo; + const isJsonEmittedToSameLocation = isJsonFile + && comparePaths( + sourceFile.fileName, + ownOutputFilePath, + host.getCurrentDirectory(), + !host.useCaseSensitiveFileNames(), + ) === Comparison.EqualTo; const jsFilePath = options.emitDeclarationOnly || isJsonEmittedToSameLocation ? undefined : ownOutputFilePath; - const sourceMapFilePath = !jsFilePath || isJsonSourceFile(sourceFile) ? undefined : getSourceMapFilePath(jsFilePath, options); - const declarationFilePath = (forceDtsPaths || (getEmitDeclarations(options) && !isJsonFile)) ? getDeclarationEmitOutputFilePath(sourceFile.fileName, host) : undefined; - const declarationMapPath = declarationFilePath && getAreDeclarationMapsEnabled(options) ? declarationFilePath + ".map" : undefined; + const sourceMapFilePath = !jsFilePath || isJsonSourceFile(sourceFile) ? undefined + : getSourceMapFilePath(jsFilePath, options); + const declarationFilePath = (forceDtsPaths || (getEmitDeclarations(options) && !isJsonFile)) + ? getDeclarationEmitOutputFilePath(sourceFile.fileName, host) : undefined; + const declarationMapPath = declarationFilePath && getAreDeclarationMapsEnabled(options) + ? declarationFilePath + ".map" : undefined; return { jsFilePath, sourceMapFilePath, declarationFilePath, declarationMapPath, buildInfoPath: undefined }; } } @@ -576,40 +598,80 @@ function getSourceMapFilePath(jsFilePath: string, options: CompilerOptions) { /** @internal */ export function getOutputExtension(fileName: string, options: CompilerOptions): Extension { - return fileExtensionIs(fileName, Extension.Json) ? Extension.Json : - options.jsx === JsxEmit.Preserve && fileExtensionIsOneOf(fileName, [Extension.Jsx, Extension.Tsx]) ? Extension.Jsx : - fileExtensionIsOneOf(fileName, [Extension.Mts, Extension.Mjs]) ? Extension.Mjs : - fileExtensionIsOneOf(fileName, [Extension.Cts, Extension.Cjs]) ? Extension.Cjs : - Extension.Js; + return fileExtensionIs(fileName, Extension.Json) ? Extension.Json + : options.jsx === JsxEmit.Preserve && fileExtensionIsOneOf(fileName, [Extension.Jsx, Extension.Tsx]) + ? Extension.Jsx + : fileExtensionIsOneOf(fileName, [Extension.Mts, Extension.Mjs]) ? Extension.Mjs + : fileExtensionIsOneOf(fileName, [Extension.Cts, Extension.Cjs]) ? Extension.Cjs + : Extension.Js; } -function getOutputPathWithoutChangingExt(inputFileName: string, configFile: ParsedCommandLine, ignoreCase: boolean, outputDir: string | undefined, getCommonSourceDirectory?: () => string) { - return outputDir ? - resolvePath( +function getOutputPathWithoutChangingExt( + inputFileName: string, + configFile: ParsedCommandLine, + ignoreCase: boolean, + outputDir: string | undefined, + getCommonSourceDirectory?: () => string, +) { + return outputDir + ? resolvePath( outputDir, - getRelativePathFromDirectory(getCommonSourceDirectory ? getCommonSourceDirectory() : getCommonSourceDirectoryOfConfig(configFile, ignoreCase), inputFileName, ignoreCase), - ) : - inputFileName; + getRelativePathFromDirectory( + getCommonSourceDirectory ? getCommonSourceDirectory() + : getCommonSourceDirectoryOfConfig(configFile, ignoreCase), + inputFileName, + ignoreCase, + ), + ) + : inputFileName; } /** @internal */ -export function getOutputDeclarationFileName(inputFileName: string, configFile: ParsedCommandLine, ignoreCase: boolean, getCommonSourceDirectory?: () => string) { +export function getOutputDeclarationFileName( + inputFileName: string, + configFile: ParsedCommandLine, + ignoreCase: boolean, + getCommonSourceDirectory?: () => string, +) { return changeExtension( - getOutputPathWithoutChangingExt(inputFileName, configFile, ignoreCase, configFile.options.declarationDir || configFile.options.outDir, getCommonSourceDirectory), + getOutputPathWithoutChangingExt( + inputFileName, + configFile, + ignoreCase, + configFile.options.declarationDir || configFile.options.outDir, + getCommonSourceDirectory, + ), getDeclarationEmitExtensionForPath(inputFileName), ); } -function getOutputJSFileName(inputFileName: string, configFile: ParsedCommandLine, ignoreCase: boolean, getCommonSourceDirectory?: () => string) { +function getOutputJSFileName( + inputFileName: string, + configFile: ParsedCommandLine, + ignoreCase: boolean, + getCommonSourceDirectory?: () => string, +) { if (configFile.options.emitDeclarationOnly) return undefined; const isJsonFile = fileExtensionIs(inputFileName, Extension.Json); const outputFileName = changeExtension( - getOutputPathWithoutChangingExt(inputFileName, configFile, ignoreCase, configFile.options.outDir, getCommonSourceDirectory), + getOutputPathWithoutChangingExt( + inputFileName, + configFile, + ignoreCase, + configFile.options.outDir, + getCommonSourceDirectory, + ), getOutputExtension(inputFileName, configFile.options), ); - return !isJsonFile || comparePaths(inputFileName, outputFileName, Debug.checkDefined(configFile.options.configFilePath), ignoreCase) !== Comparison.EqualTo ? - outputFileName : - undefined; + return !isJsonFile + || comparePaths( + inputFileName, + outputFileName, + Debug.checkDefined(configFile.options.configFilePath), + ignoreCase, + ) !== Comparison.EqualTo + ? outputFileName + : undefined; } function createAddOutput() { @@ -625,8 +687,12 @@ function createAddOutput() { } } -function getSingleOutputFileNames(configFile: ParsedCommandLine, addOutput: ReturnType["addOutput"]) { - const { jsFilePath, sourceMapFilePath, declarationFilePath, declarationMapPath, buildInfoPath } = getOutputPathsForBundle(configFile.options, /*forceDtsPaths*/ false); +function getSingleOutputFileNames( + configFile: ParsedCommandLine, + addOutput: ReturnType["addOutput"], +) { + const { jsFilePath, sourceMapFilePath, declarationFilePath, declarationMapPath, buildInfoPath } = + getOutputPathsForBundle(configFile.options, /*forceDtsPaths*/ false); addOutput(jsFilePath); addOutput(sourceMapFilePath); addOutput(declarationFilePath); @@ -634,7 +700,13 @@ function getSingleOutputFileNames(configFile: ParsedCommandLine, addOutput: Retu addOutput(buildInfoPath); } -function getOwnOutputFileNames(configFile: ParsedCommandLine, inputFileName: string, ignoreCase: boolean, addOutput: ReturnType["addOutput"], getCommonSourceDirectory?: () => string) { +function getOwnOutputFileNames( + configFile: ParsedCommandLine, + inputFileName: string, + ignoreCase: boolean, + addOutput: ReturnType["addOutput"], + getCommonSourceDirectory?: () => string, +) { if (isDeclarationFileName(inputFileName)) return; const js = getOutputJSFileName(inputFileName, configFile, ignoreCase, getCommonSourceDirectory); addOutput(js); @@ -671,7 +743,11 @@ export function getCommonSourceDirectory( checkSourceFilesBelongToPath?.(commonSourceDirectory); } else { - commonSourceDirectory = computeCommonSourceDirectoryOfFilenames(emittedFiles(), currentDirectory, getCanonicalFileName); + commonSourceDirectory = computeCommonSourceDirectoryOfFilenames( + emittedFiles(), + currentDirectory, + getCanonicalFileName, + ); } if (commonSourceDirectory && commonSourceDirectory[commonSourceDirectory.length - 1] !== directorySeparator) { @@ -684,10 +760,19 @@ export function getCommonSourceDirectory( } /** @internal */ -export function getCommonSourceDirectoryOfConfig({ options, fileNames }: ParsedCommandLine, ignoreCase: boolean): string { +export function getCommonSourceDirectoryOfConfig( + { options, fileNames }: ParsedCommandLine, + ignoreCase: boolean, +): string { return getCommonSourceDirectory( options, - () => filter(fileNames, file => !(options.noEmitForJsFiles && fileExtensionIsOneOf(file, supportedJSExtensionsFlat)) && !isDeclarationFileName(file)), + () => + filter( + fileNames, + file => + !(options.noEmitForJsFiles && fileExtensionIsOneOf(file, supportedJSExtensionsFlat)) + && !isDeclarationFileName(file), + ), getDirectoryPath(normalizeSlashes(Debug.checkDefined(options.configFilePath))), createGetCanonicalFileName(!ignoreCase), ); @@ -709,7 +794,11 @@ export function getAllProjectOutputs(configFile: ParsedCommandLine, ignoreCase: return getOutputs(); } -export function getOutputFileNames(commandLine: ParsedCommandLine, inputFileName: string, ignoreCase: boolean): readonly string[] { +export function getOutputFileNames( + commandLine: ParsedCommandLine, + inputFileName: string, + ignoreCase: boolean, +): readonly string[] { inputFileName = normalizePath(inputFileName); Debug.assert(contains(commandLine.fileNames, inputFileName), `Expected fileName to be present in command line`); const { addOutput, getOutputs } = createAddOutput(); @@ -725,8 +814,14 @@ export function getOutputFileNames(commandLine: ParsedCommandLine, inputFileName /** @internal */ export function getFirstProjectOutput(configFile: ParsedCommandLine, ignoreCase: boolean): string { if (outFile(configFile.options)) { - const { jsFilePath, declarationFilePath } = getOutputPathsForBundle(configFile.options, /*forceDtsPaths*/ false); - return Debug.checkDefined(jsFilePath || declarationFilePath, `project ${configFile.options.configFilePath} expected to have at least one output`); + const { jsFilePath, declarationFilePath } = getOutputPathsForBundle( + configFile.options, + /*forceDtsPaths*/ false, + ); + return Debug.checkDefined( + jsFilePath || declarationFilePath, + `project ${configFile.options.configFilePath} expected to have at least one output`, + ); } const getCommonSourceDirectory = memoize(() => getCommonSourceDirectoryOfConfig(configFile, ignoreCase)); @@ -746,12 +841,22 @@ export function getFirstProjectOutput(configFile: ParsedCommandLine, ignoreCase: /** @internal */ // targetSourceFile is when users only want one file in entire project to be emitted. This is used in compileOnSave feature -export function emitFiles(resolver: EmitResolver, host: EmitHost, targetSourceFile: SourceFile | undefined, { scriptTransformers, declarationTransformers }: EmitTransformers, emitOnly?: boolean | EmitOnly, onlyBuildInfo?: boolean, forceDtsEmit?: boolean): EmitResult { +export function emitFiles( + resolver: EmitResolver, + host: EmitHost, + targetSourceFile: SourceFile | undefined, + { scriptTransformers, declarationTransformers }: EmitTransformers, + emitOnly?: boolean | EmitOnly, + onlyBuildInfo?: boolean, + forceDtsEmit?: boolean, +): EmitResult { // Why var? It avoids TDZ checks in the runtime which can be costly. // See: https://github.com/microsoft/TypeScript/issues/52924 /* eslint-disable no-var */ var compilerOptions = host.getCompilerOptions(); - var sourceMapDataList: SourceMapEmitResult[] | undefined = (compilerOptions.sourceMap || compilerOptions.inlineSourceMap || getAreDeclarationMapsEnabled(compilerOptions)) ? [] : undefined; + var sourceMapDataList: SourceMapEmitResult[] | undefined = + (compilerOptions.sourceMap || compilerOptions.inlineSourceMap || getAreDeclarationMapsEnabled(compilerOptions)) + ? [] : undefined; var emittedFilesList: string[] | undefined = compilerOptions.listEmittedFiles ? [] : undefined; var emitterDiagnostics = createDiagnosticCollection(); var newLine = getNewLineCharacter(compilerOptions); @@ -780,13 +885,18 @@ export function emitFiles(resolver: EmitResolver, host: EmitHost, targetSourceFi sourceMaps: sourceMapDataList, }; - function emitSourceFileOrBundle({ jsFilePath, sourceMapFilePath, declarationFilePath, declarationMapPath, buildInfoPath }: EmitFileNames, sourceFileOrBundle: SourceFile | Bundle | undefined) { + function emitSourceFileOrBundle( + { jsFilePath, sourceMapFilePath, declarationFilePath, declarationMapPath, buildInfoPath }: EmitFileNames, + sourceFileOrBundle: SourceFile | Bundle | undefined, + ) { let buildInfoDirectory: string | undefined; if (buildInfoPath && sourceFileOrBundle && isBundle(sourceFileOrBundle)) { buildInfoDirectory = getDirectoryPath(getNormalizedAbsolutePath(buildInfoPath, host.getCurrentDirectory())); bundleBuildInfo = { commonSourceDirectory: relativeToBuildInfo(host.getCommonSourceDirectory()), - sourceFiles: sourceFileOrBundle.sourceFiles.map(file => relativeToBuildInfo(getNormalizedAbsolutePath(file.fileName, host.getCurrentDirectory()))), + sourceFiles: sourceFileOrBundle.sourceFiles.map(file => + relativeToBuildInfo(getNormalizedAbsolutePath(file.fileName, host.getCurrentDirectory())) + ), }; } tracing?.push(tracing.Phase.Emit, "emitJsFileOrBundle", { jsFilePath }); @@ -824,7 +934,9 @@ export function emitFiles(resolver: EmitResolver, host: EmitHost, targetSourceFi } function relativeToBuildInfo(path: string) { - return ensurePathIsNonModuleName(getRelativePathFromDirectory(buildInfoDirectory!, path, host.getCanonicalFileName)); + return ensurePathIsNonModuleName( + getRelativePathFromDirectory(buildInfoDirectory!, path, host.getCanonicalFileName), + ); } } @@ -837,7 +949,15 @@ export function emitFiles(resolver: EmitResolver, host: EmitHost, targetSourceFi } const buildInfo = host.getBuildInfo(bundle) || createBuildInfo(/*program*/ undefined, bundle); // Pass buildinfo as additional data to avoid having to reparse - writeFile(host, emitterDiagnostics, buildInfoPath, getBuildInfoText(buildInfo), /*writeByteOrderMark*/ false, /*sourceFiles*/ undefined, { buildInfo }); + writeFile( + host, + emitterDiagnostics, + buildInfoPath, + getBuildInfoText(buildInfo), + /*writeByteOrderMark*/ false, + /*sourceFiles*/ undefined, + { buildInfo }, + ); } function emitJsFileOrBundle( @@ -856,7 +976,15 @@ export function emitFiles(resolver: EmitResolver, host: EmitHost, targetSourceFi return; } // Transform the source files - const transform = transformNodes(resolver, host, factory, compilerOptions, [sourceFileOrBundle], scriptTransformers, /*allowDtsFiles*/ false); + const transform = transformNodes( + resolver, + host, + factory, + compilerOptions, + [sourceFileOrBundle], + scriptTransformers, + /*allowDtsFiles*/ false, + ); const printerOptions: PrinterOptions = { removeComments: compilerOptions.removeComments, @@ -905,13 +1033,25 @@ export function emitFiles(resolver: EmitResolver, host: EmitHost, targetSourceFi const sourceFiles = isSourceFile(sourceFileOrBundle) ? [sourceFileOrBundle] : sourceFileOrBundle.sourceFiles; const filesForEmit = forceDtsEmit ? sourceFiles : filter(sourceFiles, isSourceFileNotJson); // Setup and perform the transformation to retrieve declarations from the input files - const inputListOrBundle = outFile(compilerOptions) ? [factory.createBundle(filesForEmit, !isSourceFile(sourceFileOrBundle) ? sourceFileOrBundle.prepends : undefined)] : filesForEmit; + const inputListOrBundle = outFile(compilerOptions) + ? [factory.createBundle( + filesForEmit, + !isSourceFile(sourceFileOrBundle) ? sourceFileOrBundle.prepends : undefined, + )] : filesForEmit; if (emitOnly && !getEmitDeclarations(compilerOptions)) { // Checker wont collect the linked aliases since thats only done when declaration is enabled. // Do that here when emitting only dts files filesForEmit.forEach(collectLinkedAliases); } - const declarationTransform = transformNodes(resolver, host, factory, compilerOptions, inputListOrBundle, declarationTransformers, /*allowDtsFiles*/ false); + const declarationTransform = transformNodes( + resolver, + host, + factory, + compilerOptions, + inputListOrBundle, + declarationTransformers, + /*allowDtsFiles*/ false, + ); if (length(declarationTransform.diagnostics)) { for (const diagnostic of declarationTransform.diagnostics!) { emitterDiagnostics.add(diagnostic); @@ -942,10 +1082,14 @@ export function emitFiles(resolver: EmitResolver, host: EmitHost, targetSourceFi isEmitNotificationEnabled: declarationTransform.isEmitNotificationEnabled, substituteNode: declarationTransform.substituteNode, }); - const declBlocked = (!!declarationTransform.diagnostics && !!declarationTransform.diagnostics.length) || !!host.isEmitBlocked(declarationFilePath) || !!compilerOptions.noEmit; + const declBlocked = (!!declarationTransform.diagnostics && !!declarationTransform.diagnostics.length) + || !!host.isEmitBlocked(declarationFilePath) || !!compilerOptions.noEmit; emitSkipped = emitSkipped || declBlocked; if (!declBlocked || forceDtsEmit) { - Debug.assert(declarationTransform.transformed.length === 1, "Should only see one output from the decl transform"); + Debug.assert( + declarationTransform.transformed.length === 1, + "Should only see one output from the decl transform", + ); printSourceFileOrBundle( declarationFilePath, declarationMapPath, @@ -978,7 +1122,13 @@ export function emitFiles(resolver: EmitResolver, host: EmitHost, targetSourceFi forEachChild(node, collectLinkedAliases); } - function printSourceFileOrBundle(jsFilePath: string, sourceMapFilePath: string | undefined, transform: TransformationResult, printer: Printer, mapOptions: SourceMapOptions) { + function printSourceFileOrBundle( + jsFilePath: string, + sourceMapFilePath: string | undefined, + transform: TransformationResult, + printer: Printer, + mapOptions: SourceMapOptions, + ) { const sourceFileOrBundle = transform.transformed[0]; const bundle = sourceFileOrBundle.kind === SyntaxKind.Bundle ? sourceFileOrBundle : undefined; const sourceFile = sourceFileOrBundle.kind === SyntaxKind.SourceFile ? sourceFileOrBundle : undefined; @@ -1028,7 +1178,14 @@ export function emitFiles(resolver: EmitResolver, host: EmitHost, targetSourceFi // Write the source map if (sourceMapFilePath) { const sourceMap = sourceMapGenerator.toString(); - writeFile(host, emitterDiagnostics, sourceMapFilePath, sourceMap, /*writeByteOrderMark*/ false, sourceFiles); + writeFile( + host, + emitterDiagnostics, + sourceMapFilePath, + sourceMap, + /*writeByteOrderMark*/ false, + sourceFiles, + ); if (printer.bundleFileInfo) printer.bundleFileInfo.mapHash = computeSignature(sourceMap, host); } } @@ -1038,7 +1195,10 @@ export function emitFiles(resolver: EmitResolver, host: EmitHost, targetSourceFi // Write the output file const text = writer.getText(); - writeFile(host, emitterDiagnostics, jsFilePath, text, !!compilerOptions.emitBOM, sourceFiles, { sourceMapUrlPos, diagnostics: transform.diagnostics }); + writeFile(host, emitterDiagnostics, jsFilePath, text, !!compilerOptions.emitBOM, sourceFiles, { + sourceMapUrlPos, + diagnostics: transform.diagnostics, + }); // We store the hash of the text written in the buildinfo to ensure that text of the referenced d.ts file is same as whats in the buildinfo // This is needed because incremental can be toggled between two runs and we might use stale file text to do text manipulation in prepend mode if (printer.bundleFileInfo) printer.bundleFileInfo.hash = computeSignature(text, host); @@ -1058,7 +1218,8 @@ export function emitFiles(resolver: EmitResolver, host: EmitHost, targetSourceFi function shouldEmitSourceMaps(mapOptions: SourceMapOptions, sourceFileOrBundle: SourceFile | Bundle) { return (mapOptions.sourceMap || mapOptions.inlineSourceMap) - && (sourceFileOrBundle.kind !== SyntaxKind.SourceFile || !fileExtensionIs(sourceFileOrBundle.fileName, Extension.Json)); + && (sourceFileOrBundle.kind !== SyntaxKind.SourceFile + || !fileExtensionIs(sourceFileOrBundle.fileName, Extension.Json)); } function getSourceRoot(mapOptions: SourceMapOptions) { @@ -1086,7 +1247,13 @@ export function emitFiles(resolver: EmitResolver, host: EmitHost, targetSourceFi return getDirectoryPath(normalizePath(filePath)); } - function getSourceMappingURL(mapOptions: SourceMapOptions, sourceMapGenerator: SourceMapGenerator, filePath: string, sourceMapFilePath: string | undefined, sourceFile: SourceFile | undefined) { + function getSourceMappingURL( + mapOptions: SourceMapOptions, + sourceMapGenerator: SourceMapGenerator, + filePath: string, + sourceMapFilePath: string | undefined, + sourceFile: SourceFile | undefined, + ) { if (mapOptions.inlineSourceMap) { // Encode the sourceMap into the sourceMap url const sourceMapText = sourceMapGenerator.toString(); @@ -1192,9 +1359,14 @@ export const notImplementedResolver: EmitResolver = { */ export type EmitUsingBuildInfoResult = string | readonly OutputFile[]; -function createSourceFilesFromBundleBuildInfo(bundle: BundleBuildInfo, buildInfoDirectory: string, host: CompilerHost): readonly SourceFile[] { +function createSourceFilesFromBundleBuildInfo( + bundle: BundleBuildInfo, + buildInfoDirectory: string, + host: CompilerHost, +): readonly SourceFile[] { const jsBundle = Debug.checkDefined(bundle.js); - const prologueMap = jsBundle.sources?.prologues && arrayToMap(jsBundle.sources.prologues, prologueInfo => prologueInfo.file); + const prologueMap = jsBundle.sources?.prologues + && arrayToMap(jsBundle.sources.prologues, prologueInfo => prologueInfo.file); return bundle.sourceFiles.map((fileName, index) => { const prologueInfo = prologueMap?.get(index); const statements = prologueInfo?.directives.map(directive => { @@ -1241,11 +1413,14 @@ function emitUsingBuildInfoWorker( getCommandLine: (ref: ProjectReference) => ParsedCommandLine | undefined, customTransformers?: CustomTransformers, ): EmitUsingBuildInfoResult { - const { buildInfoPath, jsFilePath, sourceMapFilePath, declarationFilePath, declarationMapPath } = getOutputPathsForBundle(config.options, /*forceDtsPaths*/ false); + const { buildInfoPath, jsFilePath, sourceMapFilePath, declarationFilePath, declarationMapPath } = + getOutputPathsForBundle(config.options, /*forceDtsPaths*/ false); // If host directly provides buildinfo we can get it directly. This allows host to cache the buildinfo const buildInfo = host.getBuildInfo!(buildInfoPath!, config.options.configFilePath); if (!buildInfo) return buildInfoPath!; - if (!buildInfo.bundle || !buildInfo.bundle.js || (declarationFilePath && !buildInfo.bundle.dts)) return buildInfoPath!; + if (!buildInfo.bundle || !buildInfo.bundle.js || (declarationFilePath && !buildInfo.bundle.dts)) { + return buildInfoPath!; + } const jsFileText = host.readFile(Debug.checkDefined(jsFilePath)); if (!jsFileText) return jsFilePath!; @@ -1253,17 +1428,27 @@ function emitUsingBuildInfoWorker( if (computeSignature(jsFileText, host) !== buildInfo.bundle.js.hash) return jsFilePath!; const sourceMapText = sourceMapFilePath && host.readFile(sourceMapFilePath); // error if no source map or for now if inline sourcemap - if ((sourceMapFilePath && !sourceMapText) || config.options.inlineSourceMap) return sourceMapFilePath || "inline sourcemap decoding"; - if (sourceMapFilePath && computeSignature(sourceMapText!, host) !== buildInfo.bundle.js.mapHash) return sourceMapFilePath; + if ((sourceMapFilePath && !sourceMapText) || config.options.inlineSourceMap) { + return sourceMapFilePath || "inline sourcemap decoding"; + } + if (sourceMapFilePath && computeSignature(sourceMapText!, host) !== buildInfo.bundle.js.mapHash) { + return sourceMapFilePath; + } // read declaration text const declarationText = declarationFilePath && host.readFile(declarationFilePath); if (declarationFilePath && !declarationText) return declarationFilePath; - if (declarationFilePath && computeSignature(declarationText!, host) !== buildInfo.bundle.dts!.hash) return declarationFilePath; + if (declarationFilePath && computeSignature(declarationText!, host) !== buildInfo.bundle.dts!.hash) { + return declarationFilePath; + } const declarationMapText = declarationMapPath && host.readFile(declarationMapPath); // error if no source map or for now if inline sourcemap - if ((declarationMapPath && !declarationMapText) || config.options.inlineSourceMap) return declarationMapPath || "inline sourcemap decoding"; - if (declarationMapPath && computeSignature(declarationMapText!, host) !== buildInfo.bundle.dts!.mapHash) return declarationMapPath; + if ((declarationMapPath && !declarationMapText) || config.options.inlineSourceMap) { + return declarationMapPath || "inline sourcemap decoding"; + } + if (declarationMapPath && computeSignature(declarationMapText!, host) !== buildInfo.bundle.dts!.mapHash) { + return declarationMapPath; + } const buildInfoDirectory = getDirectoryPath(getNormalizedAbsolutePath(buildInfoPath!, host.getCurrentDirectory())); const ownPrependInput = createInputFilesWithFileTexts( @@ -1287,7 +1472,8 @@ function emitUsingBuildInfoWorker( const emitHost: EmitHost = { getPrependNodes: memoize(() => [...prependNodes, ownPrependInput]), getCanonicalFileName: host.getCanonicalFileName, - getCommonSourceDirectory: () => getNormalizedAbsolutePath(buildInfo.bundle!.commonSourceDirectory, buildInfoDirectory), + getCommonSourceDirectory: () => + getNormalizedAbsolutePath(buildInfo.bundle!.commonSourceDirectory, buildInfoDirectory), getCompilerOptions: () => config.options, getCurrentDirectory: () => host.getCurrentDirectory(), getSourceFile: returnUndefined, @@ -1329,7 +1515,11 @@ function emitUsingBuildInfoWorker( const program = buildInfo.program; if (program && changedDtsText !== undefined && config.options.composite) { // Update the output signature - (program as ProgramBundleEmitBuildInfo).outSignature = computeSignature(changedDtsText, host, changedDtsData); + (program as ProgramBundleEmitBuildInfo).outSignature = computeSignature( + changedDtsText, + host, + changedDtsData, + ); } // Update sourceFileInfo const { js, dts, sourceFiles } = buildInfo.bundle!; @@ -1369,10 +1559,14 @@ export const createPrinterWithDefaults = /* @__PURE__ */ memoize(() => createPri export const createPrinterWithRemoveComments = /* @__PURE__ */ memoize(() => createPrinter({ removeComments: true })); /** @internal */ -export const createPrinterWithRemoveCommentsNeverAsciiEscape = /* @__PURE__ */ memoize(() => createPrinter({ removeComments: true, neverAsciiEscape: true })); +export const createPrinterWithRemoveCommentsNeverAsciiEscape = /* @__PURE__ */ memoize(() => + createPrinter({ removeComments: true, neverAsciiEscape: true }) +); /** @internal */ -export const createPrinterWithRemoveCommentsOmitTrailingSemicolon = /* @__PURE__ */ memoize(() => createPrinter({ removeComments: true, omitTrailingSemicolon: true })); +export const createPrinterWithRemoveCommentsOmitTrailingSemicolon = /* @__PURE__ */ memoize(() => + createPrinter({ removeComments: true, omitTrailingSemicolon: true }) +); export function createPrinter(printerOptions: PrinterOptions = {}, handlers: PrintHandlers = {}): Printer { // Why var? It avoids TDZ checks in the runtime which can be costly. @@ -1442,7 +1636,12 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri var commentsDisabled = !!printerOptions.removeComments; var lastSubstitution: Node | undefined; var currentParenthesizerRule: ParenthesizerRule | undefined; - var { enter: enterComment, exit: exitComment } = performance.createTimerIf(extendedDiagnostics, "commentTime", "beforeComment", "afterComment"); + var { enter: enterComment, exit: exitComment } = performance.createTimerIf( + extendedDiagnostics, + "commentTime", + "beforeComment", + "afterComment", + ); var parenthesizer = factory.parenthesizer; var typeArgumentParenthesizerRuleSelector: OrdinalParentheizerRuleSelector = { select: index => index === 0 ? parenthesizer.parenthesizeLeadingTypeArgument : undefined, @@ -1523,7 +1722,12 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri writer = previousWriter; } - function writeList(format: ListFormat, nodes: NodeArray, sourceFile: SourceFile | undefined, output: EmitTextWriter) { + function writeList( + format: ListFormat, + nodes: NodeArray, + sourceFile: SourceFile | undefined, + output: EmitTextWriter, + ) { const previousWriter = writer; setWriter(output, /*_sourceMapGenerator*/ undefined); if (sourceFile) { @@ -1550,12 +1754,12 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri function recordBundleFileInternalSectionStart(node: Node) { if ( - recordInternalSection && - bundleFileInfo && - currentSourceFile && - (isDeclaration(node) || isVariableStatement(node)) && - isInternalDeclaration(node, currentSourceFile) && - sourceFileTextKind !== BundleFileSectionKind.Internal + recordInternalSection + && bundleFileInfo + && currentSourceFile + && (isDeclaration(node) || isVariableStatement(node)) + && isInternalDeclaration(node, currentSourceFile) + && sourceFileTextKind !== BundleFileSectionKind.Internal ) { const prevSourceFileTextKind = sourceFileTextKind; recordBundleFileTextLikeSection(writer.getTextPos()); @@ -1566,7 +1770,9 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri return undefined; } - function recordBundleFileInternalSectionEnd(prevSourceFileTextKind: ReturnType) { + function recordBundleFileInternalSectionEnd( + prevSourceFileTextKind: ReturnType, + ) { if (prevSourceFileTextKind) { recordBundleFileTextLikeSection(writer.getTextPos()); sourceFileTextPos = getTextPosWithWriteLine(); @@ -1649,7 +1855,11 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri writer = previousWriter; } - function writeFile(sourceFile: SourceFile, output: EmitTextWriter, sourceMapGenerator: SourceMapGenerator | undefined) { + function writeFile( + sourceFile: SourceFile, + output: EmitTextWriter, + sourceMapGenerator: SourceMapGenerator | undefined, + ) { isOwnFileEmit = true; const previousWriter = writer; setWriter(output, sourceMapGenerator); @@ -1771,22 +1981,27 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri } function shouldEmitSourceMaps(node: Node) { - return !sourceMapsDisabled && - !isSourceFile(node) && - !isInJsonFile(node) && - !isUnparsedSource(node) && - !isUnparsedPrepend(node); + return !sourceMapsDisabled + && !isSourceFile(node) + && !isInJsonFile(node) + && !isUnparsedSource(node) + && !isUnparsedPrepend(node); } function getPipelinePhase(phase: PipelinePhase, emitHint: EmitHint, node: Node) { switch (phase) { case PipelinePhase.Notification: - if (onEmitNode !== noEmitNotification && (!isEmitNotificationEnabled || isEmitNotificationEnabled(node))) { + if ( + onEmitNode !== noEmitNotification && (!isEmitNotificationEnabled || isEmitNotificationEnabled(node)) + ) { return pipelineEmitWithNotification; } // falls through case PipelinePhase.Substitution: - if (substituteNode !== noEmitSubstitution && (lastSubstitution = substituteNode(emitHint, node) || node) !== node) { + if ( + substituteNode !== noEmitSubstitution + && (lastSubstitution = substituteNode(emitHint, node) || node) !== node + ) { if (currentParenthesizerRule) { lastSubstitution = currentParenthesizerRule(lastSubstitution); } @@ -1844,8 +2059,12 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri } if (hint === EmitHint.SourceFile) return emitSourceFile(cast(node, isSourceFile)); if (hint === EmitHint.IdentifierName) return emitIdentifier(cast(node, isIdentifier)); - if (hint === EmitHint.JsxAttributeValue) return emitLiteral(cast(node, isStringLiteral), /*jsxAttributeEscape*/ true); - if (hint === EmitHint.MappedTypeParameter) return emitMappedTypeParameter(cast(node, isTypeParameterDeclaration)); + if (hint === EmitHint.JsxAttributeValue) { + return emitLiteral(cast(node, isStringLiteral), /*jsxAttributeEscape*/ true); + } + if (hint === EmitHint.MappedTypeParameter) { + return emitMappedTypeParameter(cast(node, isTypeParameterDeclaration)); + } if (hint === EmitHint.EmbeddedStatement) { Debug.assertNode(node, isEmptyStatement); return emitEmptyStatement(/*isEmbeddedStatement*/ true); @@ -2186,7 +2405,15 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri case SyntaxKind.JSDocTypeTag: case SyntaxKind.JSDocThrowsTag: case SyntaxKind.JSDocSatisfiesTag: - return emitJSDocSimpleTypedTag(node as JSDocTypeTag | JSDocReturnTag | JSDocThisTag | JSDocTypeTag | JSDocThrowsTag | JSDocSatisfiesTag); + return emitJSDocSimpleTypedTag( + node as + | JSDocTypeTag + | JSDocReturnTag + | JSDocThisTag + | JSDocTypeTag + | JSDocThrowsTag + | JSDocSatisfiesTag, + ); case SyntaxKind.JSDocTemplateTag: return emitJSDocTemplateTag(node as JSDocTemplateTag); case SyntaxKind.JSDocTypedefTag: @@ -2368,8 +2595,10 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri const numPrepends = bundle ? bundle.prepends.length : 0; const numNodes = bundle ? bundle.sourceFiles.length + numPrepends : 1; for (let i = 0; i < numNodes; i++) { - const currentNode = bundle ? i < numPrepends ? bundle.prepends[i] : bundle.sourceFiles[i - numPrepends] : node; - const sourceFile = isSourceFile(currentNode) ? currentNode : isUnparsedSource(currentNode) ? undefined : currentSourceFile; + const currentNode = bundle ? i < numPrepends ? bundle.prepends[i] : bundle.sourceFiles[i - numPrepends] + : node; + const sourceFile = isSourceFile(currentNode) ? currentNode + : isUnparsedSource(currentNode) ? undefined : currentSourceFile; const shouldSkip = printerOptions.noEmitHelpers || (!!sourceFile && hasRecordedExternalHelpers(sourceFile)); const shouldBundle = (isSourceFile(currentNode) || isUnparsedSource(currentNode)) && !isOwnFileEmit; const helpers = isUnparsedSource(currentNode) ? currentNode.helpers : getSortedEmitHelpers(currentNode); @@ -2402,7 +2631,14 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri else { writeLines(helper.text(makeFileLevelOptimisticUniqueName)); } - if (bundleFileInfo) bundleFileInfo.sections.push({ pos, end: writer.getTextPos(), kind: BundleFileSectionKind.EmitHelpers, data: helper.name }); + if (bundleFileInfo) { + bundleFileInfo.sections.push({ + pos, + end: writer.getTextPos(), + kind: BundleFileSectionKind.EmitHelpers, + data: helper.name, + }); + } helpersEmitted = true; } } @@ -2472,9 +2708,9 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri updateOrPushBundleFileTextLike( pos, writer.getTextPos(), - unparsed.kind === SyntaxKind.UnparsedText ? - BundleFileSectionKind.Text : - BundleFileSectionKind.Internal, + unparsed.kind === SyntaxKind.UnparsedText + ? BundleFileSectionKind.Text + : BundleFileSectionKind.Internal, ); } } @@ -2515,7 +2751,10 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri function emitTabStop(hint: EmitHint, node: Node, snippet: TabStop) { // A tab stop should only be attached to an empty node, i.e. a node that doesn't emit any text. - Debug.assert(node.kind === SyntaxKind.EmptyStatement, `A tab stop cannot be attached to a node of kind ${Debug.formatSyntaxKind(node.kind)}.`); + Debug.assert( + node.kind === SyntaxKind.EmptyStatement, + `A tab stop cannot be attached to a node of kind ${Debug.formatSyntaxKind(node.kind)}.`, + ); Debug.assert(hint !== EmitHint.EmbeddedStatement, `A tab stop cannot be attached to an embedded statement.`); nonEscapingWrite(`$${snippet.order}`); } @@ -2596,7 +2835,14 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri emitTypeAnnotation(node.type); } // The comment position has to fallback to any present node within the parameterdeclaration because as it turns out, the parser can make parameter declarations with _just_ an initializer. - emitInitializer(node.initializer, node.type ? node.type.end : node.questionToken ? node.questionToken.end : node.name ? node.name.end : node.modifiers ? node.modifiers.end : node.pos, node, parenthesizer.parenthesizeExpressionForDisallowedComma); + emitInitializer( + node.initializer, + node.type ? node.type.end + : node.questionToken ? node.questionToken.end + : node.name ? node.name.end : node.modifiers ? node.modifiers.end : node.pos, + node, + parenthesizer.parenthesizeExpressionForDisallowedComma, + ); } function emitDecorator(decorator: Decorator) { @@ -2622,7 +2868,11 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri emit(node.questionToken); emit(node.exclamationToken); emitTypeAnnotation(node.type); - emitInitializer(node.initializer, node.type ? node.type.end : node.questionToken ? node.questionToken.end : node.name.end, node); + emitInitializer( + node.initializer, + node.type ? node.type.end : node.questionToken ? node.questionToken.end : node.name.end, + node, + ); writeTrailingSemicolon(); } @@ -2785,7 +3035,8 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri pushPrivateNameGenerationScope(TempFlags.Auto, /*newReservedMemberNames*/ undefined); writePunctuation("{"); - const flags = getEmitFlags(node) & EmitFlags.SingleLine ? ListFormat.SingleLineTypeLiteralMembers : ListFormat.MultiLineTypeLiteralMembers; + const flags = getEmitFlags(node) & EmitFlags.SingleLine ? ListFormat.SingleLineTypeLiteralMembers + : ListFormat.MultiLineTypeLiteralMembers; emitList(node, node.members, flags | ListFormat.NoSpaceIfEmpty); writePunctuation("}"); @@ -2805,8 +3056,14 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri function emitTupleType(node: TupleTypeNode) { emitTokenWithComment(SyntaxKind.OpenBracketToken, node.pos, writePunctuation, node); - const flags = getEmitFlags(node) & EmitFlags.SingleLine ? ListFormat.SingleLineTupleTypeElements : ListFormat.MultiLineTupleTypeElements; - emitList(node, node.elements, flags | ListFormat.NoSpaceIfEmpty, parenthesizer.parenthesizeElementTypeOfTupleType); + const flags = getEmitFlags(node) & EmitFlags.SingleLine ? ListFormat.SingleLineTupleTypeElements + : ListFormat.MultiLineTupleTypeElements; + emitList( + node, + node.elements, + flags | ListFormat.NoSpaceIfEmpty, + parenthesizer.parenthesizeElementTypeOfTupleType, + ); emitTokenWithComment(SyntaxKind.CloseBracketToken, node.elements.end, writePunctuation, node); } @@ -2825,11 +3082,21 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri } function emitUnionType(node: UnionTypeNode) { - emitList(node, node.types, ListFormat.UnionTypeConstituents, parenthesizer.parenthesizeConstituentTypeOfUnionType); + emitList( + node, + node.types, + ListFormat.UnionTypeConstituents, + parenthesizer.parenthesizeConstituentTypeOfUnionType, + ); } function emitIntersectionType(node: IntersectionTypeNode) { - emitList(node, node.types, ListFormat.IntersectionTypeConstituents, parenthesizer.parenthesizeConstituentTypeOfIntersectionType); + emitList( + node, + node.types, + ListFormat.IntersectionTypeConstituents, + parenthesizer.parenthesizeConstituentTypeOfIntersectionType, + ); } function emitConditionalType(node: ConditionalTypeNode) { @@ -2868,9 +3135,9 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri writeTokenText(node.operator, writeKeyword); writeSpace(); - const parenthesizerRule = node.operator === SyntaxKind.ReadonlyKeyword ? - parenthesizer.parenthesizeOperandOfReadonlyTypeOperator : - parenthesizer.parenthesizeOperandOfTypeOperator; + const parenthesizerRule = node.operator === SyntaxKind.ReadonlyKeyword + ? parenthesizer.parenthesizeOperandOfReadonlyTypeOperator + : parenthesizer.parenthesizeOperandOfTypeOperator; emit(node.type, parenthesizerRule); } @@ -3002,7 +3269,12 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri function emitArrayLiteralExpression(node: ArrayLiteralExpression) { const elements = node.elements; const preferNewLine = node.multiLine ? ListFormat.PreferNewLine : ListFormat.None; - emitExpressionList(node, elements, ListFormat.ArrayLiteralExpressionElements | preferNewLine, parenthesizer.parenthesizeExpressionForDisallowedComma); + emitExpressionList( + node, + elements, + ListFormat.ArrayLiteralExpressionElements | preferNewLine, + parenthesizer.parenthesizeExpressionForDisallowedComma, + ); } function emitObjectLiteralExpression(node: ObjectLiteralExpression) { @@ -3017,8 +3289,13 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri } const preferNewLine = node.multiLine ? ListFormat.PreferNewLine : ListFormat.None; - const allowTrailingComma = currentSourceFile && currentSourceFile.languageVersion >= ScriptTarget.ES5 && !isJsonSourceFile(currentSourceFile) ? ListFormat.AllowTrailingComma : ListFormat.None; - emitList(node, node.properties, ListFormat.ObjectLiteralExpressionProperties | allowTrailingComma | preferNewLine); + const allowTrailingComma = currentSourceFile && currentSourceFile.languageVersion >= ScriptTarget.ES5 + && !isJsonSourceFile(currentSourceFile) ? ListFormat.AllowTrailingComma : ListFormat.None; + emitList( + node, + node.properties, + ListFormat.ObjectLiteralExpressionProperties | allowTrailingComma | preferNewLine, + ); if (indentedFlag) { decreaseIndent(); @@ -3029,16 +3306,21 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri function emitPropertyAccessExpression(node: PropertyAccessExpression) { emitExpression(node.expression, parenthesizer.parenthesizeLeftSideOfAccess); - const token = node.questionDotToken || setTextRangePosEnd(factory.createToken(SyntaxKind.DotToken) as DotToken, node.expression.end, node.name.pos); + const token = node.questionDotToken + || setTextRangePosEnd( + factory.createToken(SyntaxKind.DotToken) as DotToken, + node.expression.end, + node.name.pos, + ); const linesBeforeDot = getLinesBetweenNodes(node, node.expression, token); const linesAfterDot = getLinesBetweenNodes(node, token, node.name); writeLinesAndIndent(linesBeforeDot, /*writeSpaceIfNotIndenting*/ false); - const shouldEmitDotDot = token.kind !== SyntaxKind.QuestionDotToken && - mayNeedDotDotForPropertyAccess(node.expression) && - !writer.hasTrailingComment() && - !writer.hasTrailingWhitespace(); + const shouldEmitDotDot = token.kind !== SyntaxKind.QuestionDotToken + && mayNeedDotDotForPropertyAccess(node.expression) + && !writer.hasTrailingComment() + && !writer.hasTrailingWhitespace(); if (shouldEmitDotDot) { writePunctuation("."); @@ -3061,7 +3343,11 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri expression = skipPartiallyEmittedExpressions(expression); if (isNumericLiteral(expression)) { // check if numeric literal is a decimal literal that was originally written with a dot - const text = getLiteralTextOfNode(expression as LiteralExpression, /*neverAsciiEscape*/ true, /*jsxAttributeEscape*/ false); + const text = getLiteralTextOfNode( + expression as LiteralExpression, + /*neverAsciiEscape*/ true, + /*jsxAttributeEscape*/ false, + ); // If the number will be printed verbatim and it doesn't already contain a dot or an exponent indicator, add one // if the expression doesn't have any comments that will be emitted. return !(expression.numericLiteralFlags & TokenFlags.WithSpecifier) @@ -3100,7 +3386,12 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri } emit(node.questionDotToken); emitTypeArguments(node, node.typeArguments); - emitExpressionList(node, node.arguments, ListFormat.CallExpressionArguments, parenthesizer.parenthesizeExpressionForDisallowedComma); + emitExpressionList( + node, + node.arguments, + ListFormat.CallExpressionArguments, + parenthesizer.parenthesizeExpressionForDisallowedComma, + ); } function emitNewExpression(node: NewExpression) { @@ -3108,7 +3399,12 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri writeSpace(); emitExpression(node.expression, parenthesizer.parenthesizeExpressionOfNew); emitTypeArguments(node, node.typeArguments); - emitExpressionList(node, node.arguments, ListFormat.NewExpressionArguments, parenthesizer.parenthesizeExpressionForDisallowedComma); + emitExpressionList( + node, + node.arguments, + ListFormat.NewExpressionArguments, + parenthesizer.parenthesizeExpressionForDisallowedComma, + ); } function emitTaggedTemplateExpression(node: TaggedTemplateExpression) { @@ -3141,7 +3437,12 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri emitExpression(node.expression, /*parenthesizerRule*/ undefined); writeLineSeparatorsAfter(node.expression, node); decreaseIndentIf(indented); - emitTokenWithComment(SyntaxKind.CloseParenToken, node.expression ? node.expression.end : openParenPos, writePunctuation, node); + emitTokenWithComment( + SyntaxKind.CloseParenToken, + node.expression ? node.expression.end : openParenPos, + writePunctuation, + node, + ); } function emitFunctionExpression(node: FunctionExpression) { @@ -3209,8 +3510,12 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri // The same is true of minus of course. const operand = node.operand; return operand.kind === SyntaxKind.PrefixUnaryExpression - && ((node.operator === SyntaxKind.PlusToken && ((operand as PrefixUnaryExpression).operator === SyntaxKind.PlusToken || (operand as PrefixUnaryExpression).operator === SyntaxKind.PlusPlusToken)) - || (node.operator === SyntaxKind.MinusToken && ((operand as PrefixUnaryExpression).operator === SyntaxKind.MinusToken || (operand as PrefixUnaryExpression).operator === SyntaxKind.MinusMinusToken))); + && ((node.operator === SyntaxKind.PlusToken + && ((operand as PrefixUnaryExpression).operator === SyntaxKind.PlusToken + || (operand as PrefixUnaryExpression).operator === SyntaxKind.PlusPlusToken)) + || (node.operator === SyntaxKind.MinusToken + && ((operand as PrefixUnaryExpression).operator === SyntaxKind.MinusToken + || (operand as PrefixUnaryExpression).operator === SyntaxKind.MinusMinusToken))); } function emitPostfixUnaryExpression(node: PostfixUnaryExpression) { @@ -3291,16 +3596,18 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri const shouldEmitSourceMaps = state.shouldEmitSourceMapsStack[state.stackIndex]; afterEmitNode(savedPreserveSourceNewlines); if (shouldEmitSourceMaps) emitSourceMapsAfterNode(node); - if (shouldEmitComments) emitCommentsAfterNode(node, savedContainerPos, savedContainerEnd, savedDeclarationListContainerEnd); + if (shouldEmitComments) { + emitCommentsAfterNode(node, savedContainerPos, savedContainerEnd, savedDeclarationListContainerEnd); + } onAfterEmitNode?.(node); state.stackIndex--; } } function maybeEmitExpression(next: Expression, parent: BinaryExpression, side: "left" | "right") { - const parenthesizerRule = side === "left" ? - parenthesizer.getParenthesizeLeftSideOfBinaryForOperator(parent.operatorToken.kind) : - parenthesizer.getParenthesizeRightSideOfBinaryForOperator(parent.operatorToken.kind); + const parenthesizerRule = side === "left" + ? parenthesizer.getParenthesizeLeftSideOfBinaryForOperator(parent.operatorToken.kind) + : parenthesizer.getParenthesizeRightSideOfBinaryForOperator(parent.operatorToken.kind); let pipelinePhase = getPipelinePhase(PipelinePhase.Notification, EmitHint.Expression, next); if (pipelinePhase === pipelineEmitWithSubstitution) { @@ -3311,9 +3618,9 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri } if ( - pipelinePhase === pipelineEmitWithComments || - pipelinePhase === pipelineEmitWithSourceMaps || - pipelinePhase === pipelineEmitWithHint + pipelinePhase === pipelineEmitWithComments + || pipelinePhase === pipelineEmitWithSourceMaps + || pipelinePhase === pipelineEmitWithHint ) { if (isBinaryExpression(next)) { return next; @@ -3353,7 +3660,10 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri function emitYieldExpression(node: YieldExpression) { emitTokenWithComment(SyntaxKind.YieldKeyword, node.pos, writeKeyword, node); emit(node.asteriskToken); - emitExpressionWithLeadingSpace(node.expression && parenthesizeExpressionForNoAsi(node.expression), parenthesizeExpressionForNoAsiAndDisallowedComma); + emitExpressionWithLeadingSpace( + node.expression && parenthesizeExpressionForNoAsi(node.expression), + parenthesizeExpressionForNoAsiAndDisallowedComma, + ); } function emitSpreadElement(node: SpreadElement) { @@ -3421,9 +3731,16 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri function emitBlockStatements(node: BlockLike, forceSingleLine: boolean) { emitTokenWithComment(SyntaxKind.OpenBraceToken, node.pos, writePunctuation, /*contextNode*/ node); - const format = forceSingleLine || getEmitFlags(node) & EmitFlags.SingleLine ? ListFormat.SingleLineBlockStatements : ListFormat.MultiLineBlockStatements; + const format = forceSingleLine || getEmitFlags(node) & EmitFlags.SingleLine + ? ListFormat.SingleLineBlockStatements : ListFormat.MultiLineBlockStatements; emitList(node, node.statements, format); - emitTokenWithComment(SyntaxKind.CloseBraceToken, node.statements.end, writePunctuation, /*contextNode*/ node, /*indentLeading*/ !!(format & ListFormat.MultiLine)); + emitTokenWithComment( + SyntaxKind.CloseBraceToken, + node.statements.end, + writePunctuation, + /*contextNode*/ node, + /*indentLeading*/ !!(format & ListFormat.MultiLine), + ); } function emitVariableStatement(node: VariableStatement) { @@ -3504,11 +3821,26 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri writeSpace(); let pos = emitTokenWithComment(SyntaxKind.OpenParenToken, openParenPos, writePunctuation, /*contextNode*/ node); emitForBinding(node.initializer); - pos = emitTokenWithComment(SyntaxKind.SemicolonToken, node.initializer ? node.initializer.end : pos, writePunctuation, node); + pos = emitTokenWithComment( + SyntaxKind.SemicolonToken, + node.initializer ? node.initializer.end : pos, + writePunctuation, + node, + ); emitExpressionWithLeadingSpace(node.condition); - pos = emitTokenWithComment(SyntaxKind.SemicolonToken, node.condition ? node.condition.end : pos, writePunctuation, node); + pos = emitTokenWithComment( + SyntaxKind.SemicolonToken, + node.condition ? node.condition.end : pos, + writePunctuation, + node, + ); emitExpressionWithLeadingSpace(node.incrementor); - emitTokenWithComment(SyntaxKind.CloseParenToken, node.incrementor ? node.incrementor.end : pos, writePunctuation, node); + emitTokenWithComment( + SyntaxKind.CloseParenToken, + node.incrementor ? node.incrementor.end : pos, + writePunctuation, + node, + ); emitEmbeddedStatement(node, node.statement); } @@ -3562,7 +3894,13 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri writeTrailingSemicolon(); } - function emitTokenWithComment(token: SyntaxKind, pos: number, writer: (s: string) => void, contextNode: Node, indentLeading?: boolean) { + function emitTokenWithComment( + token: SyntaxKind, + pos: number, + writer: (s: string) => void, + contextNode: Node, + indentLeading?: boolean, + ) { const node = getParseTreeNode(contextNode); const isSimilarNode = node && node.kind === contextNode.kind; const startPos = pos; @@ -3570,7 +3908,8 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri pos = skipTrivia(currentSourceFile.text, pos); } if (isSimilarNode && contextNode.pos !== startPos) { - const needsIndent = indentLeading && currentSourceFile && !positionsAreOnSameLine(startPos, pos, currentSourceFile); + const needsIndent = indentLeading && currentSourceFile + && !positionsAreOnSameLine(startPos, pos, currentSourceFile); if (needsIndent) { increaseIndent(); } @@ -3597,7 +3936,9 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri if (some(getSyntheticLeadingComments(node), commentWillEmitNewLine)) return true; if (isPartiallyEmittedExpression(node)) { if (node.pos !== node.expression.pos) { - if (some(getTrailingCommentRanges(currentSourceFile.text, node.expression.pos), commentWillEmitNewLine)) return true; + if ( + some(getTrailingCommentRanges(currentSourceFile.text, node.expression.pos), commentWillEmitNewLine) + ) return true; } return willEmitLeadingNewLine(node.expression); } @@ -3629,7 +3970,10 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri function emitReturnStatement(node: ReturnStatement) { emitTokenWithComment(SyntaxKind.ReturnKeyword, node.pos, writeKeyword, /*contextNode*/ node); - emitExpressionWithLeadingSpace(node.expression && parenthesizeExpressionForNoAsi(node.expression), parenthesizeExpressionForNoAsi); + emitExpressionWithLeadingSpace( + node.expression && parenthesizeExpressionForNoAsi(node.expression), + parenthesizeExpressionForNoAsi, + ); writeTrailingSemicolon(); } @@ -3675,7 +4019,12 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri } if (node.finallyBlock) { writeLineOrSpace(node, node.catchClause || node.tryBlock, node.finallyBlock); - emitTokenWithComment(SyntaxKind.FinallyKeyword, (node.catchClause || node.tryBlock).end, writeKeyword, node); + emitTokenWithComment( + SyntaxKind.FinallyKeyword, + (node.catchClause || node.tryBlock).end, + writeKeyword, + node, + ); writeSpace(); emit(node.finallyBlock); } @@ -3694,7 +4043,12 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri emit(node.name); emit(node.exclamationToken); emitTypeAnnotation(node.type); - emitInitializer(node.initializer, node.type?.end ?? node.name.emitNode?.typeNode?.end ?? node.name.end, node, parenthesizer.parenthesizeExpressionForDisallowedComma); + emitInitializer( + node.initializer, + node.type?.end ?? node.name.emitNode?.typeNode?.end ?? node.name.end, + node, + parenthesizer.parenthesizeExpressionForDisallowedComma, + ); } function emitVariableDeclarationList(node: VariableDeclarationList) { @@ -3704,10 +4058,10 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri writeKeyword("using"); } else { - const head = isLet(node) ? "let" : - isVarConst(node) ? "const" : - isVarUsing(node) ? "using" : - "var"; + const head = isLet(node) ? "let" + : isVarConst(node) ? "const" + : isVarUsing(node) ? "using" + : "var"; writeKeyword(head); } writeSpace(); @@ -3789,7 +4143,12 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri if ( getLeadingLineTerminatorCount(body, firstOrUndefined(body.statements), ListFormat.PreserveLines) - || getClosingLineTerminatorCount(body, lastOrUndefined(body.statements), ListFormat.PreserveLines, body.statements) + || getClosingLineTerminatorCount( + body, + lastOrUndefined(body.statements), + ListFormat.PreserveLines, + body.statements, + ) ) { return false; } @@ -3838,7 +4197,13 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri increaseIndent(); } else { - emitList(body, body.statements, ListFormat.MultiLineFunctionBodyStatements, /*parenthesizerRule*/ undefined, statementOffset); + emitList( + body, + body.statements, + ListFormat.MultiLineFunctionBodyStatements, + /*parenthesizerRule*/ undefined, + statementOffset, + ); } } @@ -3952,12 +4317,23 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri function emitCaseBlock(node: CaseBlock) { emitTokenWithComment(SyntaxKind.OpenBraceToken, node.pos, writePunctuation, node); emitList(node, node.clauses, ListFormat.CaseBlockClauses); - emitTokenWithComment(SyntaxKind.CloseBraceToken, node.clauses.end, writePunctuation, node, /*indentLeading*/ true); + emitTokenWithComment( + SyntaxKind.CloseBraceToken, + node.clauses.end, + writePunctuation, + node, + /*indentLeading*/ true, + ); } function emitImportEqualsDeclaration(node: ImportEqualsDeclaration) { emitDecoratorsAndModifiers(node, node.modifiers, /*allowDecorators*/ false); - emitTokenWithComment(SyntaxKind.ImportKeyword, node.modifiers ? node.modifiers.end : node.pos, writeKeyword, node); + emitTokenWithComment( + SyntaxKind.ImportKeyword, + node.modifiers ? node.modifiers.end : node.pos, + writeKeyword, + node, + ); writeSpace(); if (node.isTypeOnly) { emitTokenWithComment(SyntaxKind.TypeKeyword, node.pos, writeKeyword, node); @@ -3982,7 +4358,12 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri function emitImportDeclaration(node: ImportDeclaration) { emitDecoratorsAndModifiers(node, node.modifiers, /*allowDecorators*/ false); - emitTokenWithComment(SyntaxKind.ImportKeyword, node.modifiers ? node.modifiers.end : node.pos, writeKeyword, node); + emitTokenWithComment( + SyntaxKind.ImportKeyword, + node.modifiers ? node.modifiers.end : node.pos, + writeKeyword, + node, + ); writeSpace(); if (node.importClause) { emit(node.importClause); @@ -4038,9 +4419,9 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri writeSpace(); emitExpression( node.expression, - node.isExportEquals ? - parenthesizer.getParenthesizeRightSideOfBinaryForOperator(SyntaxKind.EqualsToken) : - parenthesizer.parenthesizeExpressionOfExportDefault, + node.isExportEquals + ? parenthesizer.getParenthesizeRightSideOfBinaryForOperator(SyntaxKind.EqualsToken) + : parenthesizer.parenthesizeExpressionOfExportDefault, ); writeTrailingSemicolon(); } @@ -4240,7 +4621,9 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri function emitJsxExpression(node: JsxExpression) { if (node.expression || (!commentsDisabled && !nodeIsSynthesized(node) && hasCommentsAtPosition(node.pos))) { // preserve empty expressions if they contain comments! - const isMultiline = currentSourceFile && !nodeIsSynthesized(node) && getLineAndCharacterOfPosition(currentSourceFile, node.pos).line !== getLineAndCharacterOfPosition(currentSourceFile, node.end).line; + const isMultiline = currentSourceFile && !nodeIsSynthesized(node) + && getLineAndCharacterOfPosition(currentSourceFile, node.pos).line + !== getLineAndCharacterOfPosition(currentSourceFile, node.end).line; if (isMultiline) { writer.increaseIndent(); } @@ -4287,13 +4670,13 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri } function emitCaseOrDefaultClauseRest(parentNode: Node, statements: NodeArray, colonPos: number) { - const emitAsSingleStatement = statements.length === 1 && - ( + const emitAsSingleStatement = statements.length === 1 + && ( // treat synthesized nodes as located on the same line for emit purposes - !currentSourceFile || - nodeIsSynthesized(parentNode) || - nodeIsSynthesized(statements[0]) || - rangeStartPositionsAreOnSameLine(parentNode, statements[0], currentSourceFile) + !currentSourceFile + || nodeIsSynthesized(parentNode) + || nodeIsSynthesized(statements[0]) + || rangeStartPositionsAreOnSameLine(parentNode, statements[0], currentSourceFile) ); let format = ListFormat.CaseOrDefaultClauseStatements; @@ -4407,7 +4790,9 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri write("*/"); } - function emitJSDocSimpleTypedTag(tag: JSDocTypeTag | JSDocThisTag | JSDocEnumTag | JSDocReturnTag | JSDocThrowsTag | JSDocSatisfiesTag) { + function emitJSDocSimpleTypedTag( + tag: JSDocTypeTag | JSDocThisTag | JSDocEnumTag | JSDocReturnTag | JSDocThrowsTag | JSDocSatisfiesTag, + ) { emitJSDocTagName(tag.tagName); emitJSDocTypeExpression(tag.typeExpression); emitJSDocComment(tag.comment); @@ -4555,9 +4940,9 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri const statements = node.statements; // Emit detached comment if there are no prologue directives or if the first node is synthesized. // The synthesized node will have no leading comment so some comments may be missed. - const shouldEmitDetachedComment = statements.length === 0 || - !isPrologueDirective(statements[0]) || - nodeIsSynthesized(statements[0]); + const shouldEmitDetachedComment = statements.length === 0 + || !isPrologueDirective(statements[0]) + || nodeIsSynthesized(statements[0]); if (shouldEmitDetachedComment) { emitBodyWithDetachedComments(node, statements, emitSourceFileWorker); return; @@ -4566,7 +4951,12 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri } function emitSyntheticTripleSlashReferencesIfNeeded(node: Bundle) { - emitTripleSlashDirectives(!!node.hasNoDefaultLib, node.syntheticFileReferences || [], node.syntheticTypeReferences || [], node.syntheticLibReferences || []); + emitTripleSlashDirectives( + !!node.hasNoDefaultLib, + node.syntheticFileReferences || [], + node.syntheticTypeReferences || [], + node.syntheticLibReferences || [], + ); for (const prepend of node.prepends) { if (isUnparsedSource(prepend) && prepend.syntheticReferences) { for (const ref of prepend.syntheticReferences) { @@ -4578,14 +4968,32 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri } function emitTripleSlashDirectivesIfNeeded(node: SourceFile) { - if (node.isDeclarationFile) emitTripleSlashDirectives(node.hasNoDefaultLib, node.referencedFiles, node.typeReferenceDirectives, node.libReferenceDirectives); + if (node.isDeclarationFile) { + emitTripleSlashDirectives( + node.hasNoDefaultLib, + node.referencedFiles, + node.typeReferenceDirectives, + node.libReferenceDirectives, + ); + } } - function emitTripleSlashDirectives(hasNoDefaultLib: boolean, files: readonly FileReference[], types: readonly FileReference[], libs: readonly FileReference[]) { + function emitTripleSlashDirectives( + hasNoDefaultLib: boolean, + files: readonly FileReference[], + types: readonly FileReference[], + libs: readonly FileReference[], + ) { if (hasNoDefaultLib) { const pos = writer.getTextPos(); writeComment(`/// `); - if (bundleFileInfo) bundleFileInfo.sections.push({ pos, end: writer.getTextPos(), kind: BundleFileSectionKind.NoDefaultLib }); + if (bundleFileInfo) { + bundleFileInfo.sections.push({ + pos, + end: writer.getTextPos(), + kind: BundleFileSectionKind.NoDefaultLib, + }); + } writeLine(); } if (currentSourceFile && currentSourceFile.moduleName) { @@ -4606,22 +5014,47 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri for (const directive of files) { const pos = writer.getTextPos(); writeComment(`/// `); - if (bundleFileInfo) bundleFileInfo.sections.push({ pos, end: writer.getTextPos(), kind: BundleFileSectionKind.Reference, data: directive.fileName }); + if (bundleFileInfo) { + bundleFileInfo.sections.push({ + pos, + end: writer.getTextPos(), + kind: BundleFileSectionKind.Reference, + data: directive.fileName, + }); + } writeLine(); } for (const directive of types) { const pos = writer.getTextPos(); - const resolutionMode = directive.resolutionMode && directive.resolutionMode !== currentSourceFile?.impliedNodeFormat - ? `resolution-mode="${directive.resolutionMode === ModuleKind.ESNext ? "import" : "require"}"` - : ""; + const resolutionMode = + directive.resolutionMode && directive.resolutionMode !== currentSourceFile?.impliedNodeFormat + ? `resolution-mode="${directive.resolutionMode === ModuleKind.ESNext ? "import" : "require"}"` + : ""; writeComment(`/// `); - if (bundleFileInfo) bundleFileInfo.sections.push({ pos, end: writer.getTextPos(), kind: !directive.resolutionMode ? BundleFileSectionKind.Type : directive.resolutionMode === ModuleKind.ESNext ? BundleFileSectionKind.TypeResolutionModeImport : BundleFileSectionKind.TypeResolutionModeRequire, data: directive.fileName }); + if (bundleFileInfo) { + bundleFileInfo.sections.push({ + pos, + end: writer.getTextPos(), + kind: !directive.resolutionMode ? BundleFileSectionKind.Type + : directive.resolutionMode === ModuleKind.ESNext + ? BundleFileSectionKind.TypeResolutionModeImport + : BundleFileSectionKind.TypeResolutionModeRequire, + data: directive.fileName, + }); + } writeLine(); } for (const directive of libs) { const pos = writer.getTextPos(); writeComment(`/// `); - if (bundleFileInfo) bundleFileInfo.sections.push({ pos, end: writer.getTextPos(), kind: BundleFileSectionKind.Lib, data: directive.fileName }); + if (bundleFileInfo) { + bundleFileInfo.sections.push({ + pos, + end: writer.getTextPos(), + kind: BundleFileSectionKind.Lib, + data: directive.fileName, + }); + } writeLine(); } } @@ -4633,7 +5066,13 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri emitHelpers(node); const index = findIndex(statements, statement => !isPrologueDirective(statement)); emitTripleSlashDirectivesIfNeeded(node); - emitList(node, statements, ListFormat.MultiLine, /*parenthesizerRule*/ undefined, index === -1 ? statements.length : index); + emitList( + node, + statements, + ListFormat.MultiLine, + /*parenthesizerRule*/ undefined, + index === -1 ? statements.length : index, + ); popNameGenerationScope(node); } @@ -4658,12 +5097,18 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri * Emits any prologue directives at the start of a Statement list, returning the * number of prologue directives written to the output. */ - function emitPrologueDirectives(statements: readonly Node[], sourceFile?: SourceFile, seenPrologueDirectives?: Set, recordBundleFileSection?: true): number { + function emitPrologueDirectives( + statements: readonly Node[], + sourceFile?: SourceFile, + seenPrologueDirectives?: Set, + recordBundleFileSection?: true, + ): number { let needsToSetSourceFile = !!sourceFile; for (let i = 0; i < statements.length; i++) { const statement = statements[i]; if (isPrologueDirective(statement)) { - const shouldEmitPrologueDirective = seenPrologueDirectives ? !seenPrologueDirectives.has(statement.expression.text) : true; + const shouldEmitPrologueDirective = seenPrologueDirectives + ? !seenPrologueDirectives.has(statement.expression.text) : true; if (shouldEmitPrologueDirective) { if (needsToSetSourceFile) { needsToSetSourceFile = false; @@ -4672,7 +5117,14 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri writeLine(); const pos = writer.getTextPos(); emit(statement); - if (recordBundleFileSection && bundleFileInfo) bundleFileInfo.sections.push({ pos, end: writer.getTextPos(), kind: BundleFileSectionKind.Prologue, data: statement.expression.text }); + if (recordBundleFileSection && bundleFileInfo) { + bundleFileInfo.sections.push({ + pos, + end: writer.getTextPos(), + kind: BundleFileSectionKind.Prologue, + data: statement.expression.text, + }); + } if (seenPrologueDirectives) { seenPrologueDirectives.add(statement.expression.text); } @@ -4693,7 +5145,14 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri writeLine(); const pos = writer.getTextPos(); emit(prologue); - if (bundleFileInfo) bundleFileInfo.sections.push({ pos, end: writer.getTextPos(), kind: BundleFileSectionKind.Prologue, data: prologue.data }); + if (bundleFileInfo) { + bundleFileInfo.sections.push({ + pos, + end: writer.getTextPos(), + kind: BundleFileSectionKind.Prologue, + data: prologue.data, + }); + } if (seenPrologueDirectives) { seenPrologueDirectives.add(prologue.data); } @@ -4711,7 +5170,12 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri emitUnparsedPrologues((prepend as UnparsedSource).prologues, seenPrologueDirectives); } for (const sourceFile of sourceFileOrBundle.sourceFiles) { - emitPrologueDirectives(sourceFile.statements, sourceFile, seenPrologueDirectives, /*recordBundleFileSection*/ true); + emitPrologueDirectives( + sourceFile.statements, + sourceFile, + seenPrologueDirectives, + /*recordBundleFileSection*/ true, + ); } setSourceFile(undefined); } @@ -4739,7 +5203,13 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri }); end = end < statement.end ? statement.end : end; } - if (directives) (prologues || (prologues = [])).push({ file: index, text: sourceFile.text.substring(0, end), directives }); + if (directives) { + (prologues || (prologues = [])).push({ + file: index, + text: sourceFile.text.substring(0, end), + directives, + }); + } } return prologues; } @@ -4781,7 +5251,11 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri write = savedWrite; } - function emitDecoratorsAndModifiers(node: Node, modifiers: NodeArray | undefined, allowDecorators: boolean) { + function emitDecoratorsAndModifiers( + node: Node, + modifiers: NodeArray | undefined, + allowDecorators: boolean, + ) { if (modifiers?.length) { if (every(modifiers, isModifier)) { // if all modifier-likes are `Modifier`, simply emit the array as modifiers. @@ -4863,7 +5337,12 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri } } - function emitInitializer(node: Expression | undefined, equalCommentStartPos: number, container: Node, parenthesizerRule?: (node: Expression) => Expression) { + function emitInitializer( + node: Expression | undefined, + equalCommentStartPos: number, + container: Node, + parenthesizerRule?: (node: Expression) => Expression, + ) { if (node) { writeSpace(); emitTokenWithComment(SyntaxKind.EqualsToken, equalCommentStartPos, writeOperator, container); @@ -4872,7 +5351,12 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri } } - function emitNodeWithPrefix(prefix: string, prefixWriter: (s: string) => void, node: T | undefined, emit: (node: T) => void) { + function emitNodeWithPrefix( + prefix: string, + prefixWriter: (s: string) => void, + node: T | undefined, + emit: (node: T) => void, + ) { if (node) { prefixWriter(prefix); emit(node); @@ -4886,7 +5370,10 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri } } - function emitExpressionWithLeadingSpace(node: Expression | undefined, parenthesizerRule?: (node: Expression) => Expression) { + function emitExpressionWithLeadingSpace( + node: Expression | undefined, + parenthesizerRule?: (node: Expression) => Expression, + ) { if (node) { writeSpace(); emitExpression(node, parenthesizerRule); @@ -4902,9 +5389,9 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri function emitEmbeddedStatement(parent: Node, node: Statement) { if ( - isBlock(node) || - getEmitFlags(parent) & EmitFlags.SingleLine || - preserveSourceNewlines && !getLeadingLineTerminatorCount(parent, node, ListFormat.None) + isBlock(node) + || getEmitFlags(parent) & EmitFlags.SingleLine + || preserveSourceNewlines && !getLeadingLineTerminatorCount(parent, node, ListFormat.None) ) { writeSpace(); emit(node); @@ -4932,7 +5419,15 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri emitList(parentNode, typeArguments, ListFormat.TypeArguments, typeArgumentParenthesizerRuleSelector); } - function emitTypeParameters(parentNode: SignatureDeclaration | InterfaceDeclaration | TypeAliasDeclaration | ClassDeclaration | ClassExpression, typeParameters: NodeArray | undefined) { + function emitTypeParameters( + parentNode: + | SignatureDeclaration + | InterfaceDeclaration + | TypeAliasDeclaration + | ClassDeclaration + | ClassExpression, + typeParameters: NodeArray | undefined, + ) { if (isFunctionLike(parentNode) && parentNode.typeArguments) { // Quick info uses type arguments in place of type parameters on instantiated signatures return emitTypeArguments(parentNode, parentNode.typeArguments); } @@ -4943,7 +5438,10 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri emitList(parentNode, parameters, ListFormat.Parameters); } - function canEmitSimpleArrowHead(parentNode: FunctionTypeNode | ArrowFunction, parameters: NodeArray) { + function canEmitSimpleArrowHead( + parentNode: FunctionTypeNode | ArrowFunction, + parameters: NodeArray, + ) { const parameter = singleOrUndefined(parameters); return parameter && parameter.pos === parentNode.pos // may not have parsed tokens between parent and parameter @@ -4959,7 +5457,10 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri && isIdentifier(parameter.name); // parameter name must be identifier } - function emitParametersForArrow(parentNode: FunctionTypeNode | ArrowFunction, parameters: NodeArray) { + function emitParametersForArrow( + parentNode: FunctionTypeNode | ArrowFunction, + parameters: NodeArray, + ) { if (canEmitSimpleArrowHead(parentNode, parameters)) { emitList(parentNode, parameters, ListFormat.Parameters & ~ListFormat.Parenthesis); } @@ -4995,7 +5496,14 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri } } - function emitList>(parentNode: Node | undefined, children: Children | undefined, format: ListFormat, parenthesizerRule?: ParenthesizerRuleOrSelector, start?: number, count?: number) { + function emitList>( + parentNode: Node | undefined, + children: Children | undefined, + format: ListFormat, + parenthesizerRule?: ParenthesizerRuleOrSelector, + start?: number, + count?: number, + ) { emitNodeList( emit, parentNode, @@ -5007,11 +5515,26 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri ); } - function emitExpressionList>(parentNode: Node | undefined, children: Children | undefined, format: ListFormat, parenthesizerRule?: ParenthesizerRuleOrSelector, start?: number, count?: number) { + function emitExpressionList>( + parentNode: Node | undefined, + children: Children | undefined, + format: ListFormat, + parenthesizerRule?: ParenthesizerRuleOrSelector, + start?: number, + count?: number, + ) { emitNodeList(emitExpression, parentNode, children, format, parenthesizerRule, start, count); } - function emitNodeList>(emit: EmitFunction, parentNode: Node | undefined, children: Children | undefined, format: ListFormat, parenthesizerRule: ParenthesizerRuleOrSelector | undefined, start = 0, count = children ? children.length - start : 0) { + function emitNodeList>( + emit: EmitFunction, + parentNode: Node | undefined, + children: Children | undefined, + format: ListFormat, + parenthesizerRule: ParenthesizerRuleOrSelector | undefined, + start = 0, + count = children ? children.length - start : 0, + ) { const isUndefined = children === undefined; if (isUndefined && format & ListFormat.OptionalIfUndefined) { return; @@ -5035,7 +5558,11 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri if (isEmpty) { // Write a line terminator if the parent node was multi-line - if (format & ListFormat.MultiLine && !(preserveSourceNewlines && (!parentNode || currentSourceFile && rangeIsOnSingleLine(parentNode, currentSourceFile)))) { + if ( + format & ListFormat.MultiLine + && !(preserveSourceNewlines + && (!parentNode || currentSourceFile && rangeIsOnSingleLine(parentNode, currentSourceFile))) + ) { writeLine(); } else if (format & ListFormat.SpaceBetweenBraces && !(format & ListFormat.NoSpaceIfEmpty)) { @@ -5043,7 +5570,17 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri } } else { - emitNodeListItems(emit, parentNode, children, format, parenthesizerRule, start, count, children.hasTrailingComma, children); + emitNodeListItems( + emit, + parentNode, + children, + format, + parenthesizerRule, + start, + count, + children.hasTrailingComma, + children, + ); } onAfterEmitNodeArray?.(children); @@ -5061,7 +5598,17 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri * * NOTE: You probably don't want to call this directly and should be using `emitList` or `emitExpressionList` instead. */ - function emitNodeListItems(emit: EmitFunction, parentNode: Node | undefined, children: readonly Child[], format: ListFormat, parenthesizerRule: ParenthesizerRuleOrSelector | undefined, start: number, count: number, hasTrailingComma: boolean, childrenTextRange: TextRange | undefined) { + function emitNodeListItems( + emit: EmitFunction, + parentNode: Node | undefined, + children: readonly Child[], + format: ListFormat, + parenthesizerRule: ParenthesizerRuleOrSelector | undefined, + start: number, + count: number, + hasTrailingComma: boolean, + childrenTextRange: TextRange | undefined, + ) { // Write the opening line terminator or leading whitespace. const mayEmitInterveningComments = (format & ListFormat.NoInterveningComments) === 0; let shouldEmitInterveningComments = mayEmitInterveningComments; @@ -5154,7 +5701,8 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri // Write a trailing comma, if requested. const emitFlags = previousSibling ? getEmitFlags(previousSibling) : 0; const skipTrailingComments = commentsDisabled || !!(emitFlags & EmitFlags.NoTrailingComments); - const emitTrailingComma = hasTrailingComma && (format & ListFormat.AllowTrailingComma) && (format & ListFormat.CommaDelimited); + const emitTrailingComma = hasTrailingComma && (format & ListFormat.AllowTrailingComma) + && (format & ListFormat.CommaDelimited); if (emitTrailingComma) { if (previousSibling && !skipTrailingComments) { emitTokenWithComment(SyntaxKind.CommaToken, previousSibling.end, writePunctuation, previousSibling); @@ -5170,8 +5718,13 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri // 2 // /* end of element 2 */ // ]; - if (previousSibling && (parentNode ? parentNode.end : -1) !== previousSibling.end && (format & ListFormat.DelimitersMask) && !skipTrailingComments) { - emitLeadingCommentsOfPosition(emitTrailingComma && childrenTextRange?.end ? childrenTextRange.end : previousSibling.end); + if ( + previousSibling && (parentNode ? parentNode.end : -1) !== previousSibling.end + && (format & ListFormat.DelimitersMask) && !skipTrailingComments + ) { + emitLeadingCommentsOfPosition( + emitTrailingComma && childrenTextRange?.end ? childrenTextRange.end : previousSibling.end, + ); } // Decrease the indent, if requested. @@ -5182,7 +5735,12 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri recordBundleFileInternalSectionEnd(previousSourceFileTextKind); // Write the closing line terminator or closing whitespace. - const closingLineTerminatorCount = getClosingLineTerminatorCount(parentNode, children[start + count - 1], format, childrenTextRange); + const closingLineTerminatorCount = getClosingLineTerminatorCount( + parentNode, + children[start + count - 1], + format, + childrenTextRange, + ); if (closingLineTerminatorCount) { writeLine(closingLineTerminatorCount); } @@ -5342,7 +5900,11 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri } } - function getLeadingLineTerminatorCount(parentNode: Node | undefined, firstChild: Node | undefined, format: ListFormat): number { + function getLeadingLineTerminatorCount( + parentNode: Node | undefined, + firstChild: Node | undefined, + format: ListFormat, + ): number { if (format & ListFormat.PreserveLines || preserveSourceNewlines) { if (format & ListFormat.PreferNewLine) { return 1; @@ -5374,10 +5936,10 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri return 0; } if ( - currentSourceFile && parentNode && - !positionIsSynthesized(parentNode.pos) && - !nodeIsSynthesized(firstChild) && - (!firstChild.parent || getOriginalNode(firstChild.parent) === getOriginalNode(parentNode)) + currentSourceFile && parentNode + && !positionIsSynthesized(parentNode.pos) + && !nodeIsSynthesized(firstChild) + && (!firstChild.parent || getOriginalNode(firstChild.parent) === getOriginalNode(parentNode)) ) { if (preserveSourceNewlines) { return getEffectiveLines( @@ -5399,7 +5961,11 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri return format & ListFormat.MultiLine ? 1 : 0; } - function getSeparatingLineTerminatorCount(previousNode: Node | undefined, nextNode: Node, format: ListFormat): number { + function getSeparatingLineTerminatorCount( + previousNode: Node | undefined, + nextNode: Node, + format: ListFormat, + ): number { if (format & ListFormat.PreserveLines || preserveSourceNewlines) { if (previousNode === undefined || nextNode === undefined) { return 0; @@ -5432,7 +5998,9 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri // whether new lines are preferred or not. return format & ListFormat.PreferNewLine ? 1 : 0; } - else if (synthesizedNodeStartsOnNewLine(previousNode, format) || synthesizedNodeStartsOnNewLine(nextNode, format)) { + else if ( + synthesizedNodeStartsOnNewLine(previousNode, format) || synthesizedNodeStartsOnNewLine(nextNode, format) + ) { return 1; } } @@ -5442,7 +6010,12 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri return format & ListFormat.MultiLine ? 1 : 0; } - function getClosingLineTerminatorCount(parentNode: Node | undefined, lastChild: Node | undefined, format: ListFormat, childrenTextRange: TextRange | undefined): number { + function getClosingLineTerminatorCount( + parentNode: Node | undefined, + lastChild: Node | undefined, + format: ListFormat, + childrenTextRange: TextRange | undefined, + ): number { if (format & ListFormat.PreserveLines || preserveSourceNewlines) { if (format & ListFormat.PreferNewLine) { return 1; @@ -5451,9 +6024,13 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri if (lastChild === undefined) { return !parentNode || currentSourceFile && rangeIsOnSingleLine(parentNode, currentSourceFile) ? 0 : 1; } - if (currentSourceFile && parentNode && !positionIsSynthesized(parentNode.pos) && !nodeIsSynthesized(lastChild) && (!lastChild.parent || lastChild.parent === parentNode)) { + if ( + currentSourceFile && parentNode && !positionIsSynthesized(parentNode.pos) + && !nodeIsSynthesized(lastChild) && (!lastChild.parent || lastChild.parent === parentNode) + ) { if (preserveSourceNewlines) { - const end = childrenTextRange && !positionIsSynthesized(childrenTextRange.end) ? childrenTextRange.end : lastChild.end; + const end = childrenTextRange && !positionIsSynthesized(childrenTextRange.end) + ? childrenTextRange.end : lastChild.end; return getEffectiveLines( includeComments => getLinesBetweenPositionAndNextNonWhitespaceCharacter( @@ -5509,7 +6086,8 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri } function writeLineSeparatorsAfter(node: Node, parent: Node) { - const trailingNewlines = preserveSourceNewlines && getClosingLineTerminatorCount(parent, node, ListFormat.None, /*childrenTextRange*/ undefined); + const trailingNewlines = preserveSourceNewlines + && getClosingLineTerminatorCount(parent, node, ListFormat.None, /*childrenTextRange*/ undefined); if (trailingNewlines) { writeLine(trailingNewlines); } @@ -5573,7 +6151,10 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri return node; } - function getTextOfNode(node: Identifier | PrivateIdentifier | LiteralExpression | JsxNamespacedName, includeTrivia?: boolean): string { + function getTextOfNode( + node: Identifier | PrivateIdentifier | LiteralExpression | JsxNamespacedName, + includeTrivia?: boolean, + ): string { if (isGeneratedIdentifier(node) || isGeneratedPrivateIdentifier(node)) { return generateName(node); } @@ -5601,14 +6182,21 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri return getSourceTextOfNodeFromSourceFile(sourceFile, node, includeTrivia); } - function getLiteralTextOfNode(node: LiteralLikeNode, neverAsciiEscape: boolean | undefined, jsxAttributeEscape: boolean): string { + function getLiteralTextOfNode( + node: LiteralLikeNode, + neverAsciiEscape: boolean | undefined, + jsxAttributeEscape: boolean, + ): string { if (node.kind === SyntaxKind.StringLiteral && (node as StringLiteral).textSourceNode) { const textSourceNode = (node as StringLiteral).textSourceNode!; - if (isIdentifier(textSourceNode) || isPrivateIdentifier(textSourceNode) || isNumericLiteral(textSourceNode) || isJsxNamespacedName(textSourceNode)) { + if ( + isIdentifier(textSourceNode) || isPrivateIdentifier(textSourceNode) || isNumericLiteral(textSourceNode) + || isJsxNamespacedName(textSourceNode) + ) { const text = isNumericLiteral(textSourceNode) ? textSourceNode.text : getTextOfNode(textSourceNode); - return jsxAttributeEscape ? `"${escapeJsxAttributeString(text)}"` : - neverAsciiEscape || (getEmitFlags(node) & EmitFlags.NoAsciiEscaping) ? `"${escapeString(text)}"` : - `"${escapeNonAsciiString(text)}"`; + return jsxAttributeEscape ? `"${escapeJsxAttributeString(text)}"` + : neverAsciiEscape || (getEmitFlags(node) & EmitFlags.NoAsciiEscaping) ? `"${escapeString(text)}"` + : `"${escapeNonAsciiString(text)}"`; } else { return getLiteralTextOfNode(textSourceNode, neverAsciiEscape, jsxAttributeEscape); @@ -5618,7 +6206,8 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri const flags = (neverAsciiEscape ? GetLiteralTextFlags.NeverAsciiEscape : 0) | (jsxAttributeEscape ? GetLiteralTextFlags.JsxAttributeEscape : 0) | (printerOptions.terminateUnterminatedLiterals ? GetLiteralTextFlags.TerminateUnterminatedLiterals : 0) - | (printerOptions.target && printerOptions.target === ScriptTarget.ESNext ? GetLiteralTextFlags.AllowNumericSeparator : 0); + | (printerOptions.target && printerOptions.target === ScriptTarget.ESNext + ? GetLiteralTextFlags.AllowNumericSeparator : 0); return getLiteralText(node, currentSourceFile, flags); } @@ -5659,7 +6248,10 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri /** * Push a new member name generation scope. */ - function pushPrivateNameGenerationScope(newPrivateNameTempFlags: TempFlags, newReservedMemberNames: Set | undefined) { + function pushPrivateNameGenerationScope( + newPrivateNameTempFlags: TempFlags, + newReservedMemberNames: Set | undefined, + ) { privateNameTempFlagsStack.push(privateNameTempFlags); privateNameTempFlags = newPrivateNameTempFlags; reservedPrivateNamesStack.push(reservedNames); @@ -5800,20 +6392,40 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri if ((autoGenerate.flags & GeneratedIdentifierFlags.KindMask) === GeneratedIdentifierFlags.Node) { // Node names generate unique names based on their original node // and are cached based on that node's id. - return generateNameCached(getNodeForGeneratedName(name), isPrivateIdentifier(name), autoGenerate.flags, autoGenerate.prefix, autoGenerate.suffix); + return generateNameCached( + getNodeForGeneratedName(name), + isPrivateIdentifier(name), + autoGenerate.flags, + autoGenerate.prefix, + autoGenerate.suffix, + ); } else { // Auto, Loop, and Unique names are cached based on their unique // autoGenerateId. const autoGenerateId = autoGenerate.id; - return autoGeneratedIdToGeneratedName[autoGenerateId] || (autoGeneratedIdToGeneratedName[autoGenerateId] = makeName(name)); + return autoGeneratedIdToGeneratedName[autoGenerateId] + || (autoGeneratedIdToGeneratedName[autoGenerateId] = makeName(name)); } } - function generateNameCached(node: Node, privateName: boolean, flags?: GeneratedIdentifierFlags, prefix?: string | GeneratedNamePart, suffix?: string) { + function generateNameCached( + node: Node, + privateName: boolean, + flags?: GeneratedIdentifierFlags, + prefix?: string | GeneratedNamePart, + suffix?: string, + ) { const nodeId = getNodeId(node); const cache = privateName ? nodeIdToGeneratedPrivateName : nodeIdToGeneratedName; - return cache[nodeId] || (cache[nodeId] = generateNameForNode(node, privateName, flags ?? GeneratedIdentifierFlags.None, formatGeneratedNamePart(prefix, generateName), formatGeneratedNamePart(suffix))); + return cache[nodeId] + || (cache[nodeId] = generateNameForNode( + node, + privateName, + flags ?? GeneratedIdentifierFlags.None, + formatGeneratedNamePart(prefix, generateName), + formatGeneratedNamePart(suffix), + )); } /** @@ -5887,7 +6499,13 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri * TempFlags._i or TempFlags._n may be used to express a preference for that dedicated name. * Note that names generated by makeTempVariableName and makeUniqueName will never conflict. */ - function makeTempVariableName(flags: TempFlags, reservedInNestedScopes: boolean, privateName: boolean, prefix: string, suffix: string): string { + function makeTempVariableName( + flags: TempFlags, + reservedInNestedScopes: boolean, + privateName: boolean, + prefix: string, + suffix: string, + ): string { if (prefix.length > 0 && prefix.charCodeAt(0) === CharacterCodes.hash) { prefix = prefix.slice(1); } @@ -5942,7 +6560,15 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri * makeUniqueName are guaranteed to never conflict. * If `optimistic` is set, the first instance will use 'baseName' verbatim instead of 'baseName_1' */ - function makeUniqueName(baseName: string, checkFn: (name: string, privateName: boolean) => boolean = isUniqueName, optimistic: boolean, scoped: boolean, privateName: boolean, prefix: string, suffix: string): string { + function makeUniqueName( + baseName: string, + checkFn: (name: string, privateName: boolean) => boolean = isUniqueName, + optimistic: boolean, + scoped: boolean, + privateName: boolean, + prefix: string, + suffix: string, + ): string { if (baseName.length > 0 && baseName.charCodeAt(0) === CharacterCodes.hash) { baseName = baseName.slice(1); } @@ -5988,7 +6614,15 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri } function makeFileLevelOptimisticUniqueName(name: string) { - return makeUniqueName(name, isFileLevelUniqueNameInCurrentFile, /*optimistic*/ true, /*scoped*/ false, /*privateName*/ false, /*prefix*/ "", /*suffix*/ ""); + return makeUniqueName( + name, + isFileLevelUniqueNameInCurrentFile, + /*optimistic*/ true, + /*scoped*/ false, + /*privateName*/ false, + /*prefix*/ "", + /*suffix*/ "", + ); } /** @@ -5997,7 +6631,16 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri function generateNameForModuleOrEnum(node: ModuleDeclaration | EnumDeclaration) { const name = getTextOfNode(node.name); // Use module/enum name itself if it is unique, otherwise make a unique variation - return isUniqueLocalName(name, tryCast(node, canHaveLocals)) ? name : makeUniqueName(name, isUniqueName, /*optimistic*/ false, /*scoped*/ false, /*privateName*/ false, /*prefix*/ "", /*suffix*/ ""); + return isUniqueLocalName(name, tryCast(node, canHaveLocals)) ? name + : makeUniqueName( + name, + isUniqueName, + /*optimistic*/ false, + /*scoped*/ false, + /*privateName*/ false, + /*prefix*/ "", + /*suffix*/ "", + ); } /** @@ -6005,26 +6648,55 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri */ function generateNameForImportOrExportDeclaration(node: ImportDeclaration | ExportDeclaration) { const expr = getExternalModuleName(node)!; // TODO: GH#18217 - const baseName = isStringLiteral(expr) ? - makeIdentifierFromModuleName(expr.text) : "module"; - return makeUniqueName(baseName, isUniqueName, /*optimistic*/ false, /*scoped*/ false, /*privateName*/ false, /*prefix*/ "", /*suffix*/ ""); + const baseName = isStringLiteral(expr) + ? makeIdentifierFromModuleName(expr.text) : "module"; + return makeUniqueName( + baseName, + isUniqueName, + /*optimistic*/ false, + /*scoped*/ false, + /*privateName*/ false, + /*prefix*/ "", + /*suffix*/ "", + ); } /** * Generates a unique name for a default export. */ function generateNameForExportDefault() { - return makeUniqueName("default", isUniqueName, /*optimistic*/ false, /*scoped*/ false, /*privateName*/ false, /*prefix*/ "", /*suffix*/ ""); + return makeUniqueName( + "default", + isUniqueName, + /*optimistic*/ false, + /*scoped*/ false, + /*privateName*/ false, + /*prefix*/ "", + /*suffix*/ "", + ); } /** * Generates a unique name for a class expression. */ function generateNameForClassExpression() { - return makeUniqueName("class", isUniqueName, /*optimistic*/ false, /*scoped*/ false, /*privateName*/ false, /*prefix*/ "", /*suffix*/ ""); + return makeUniqueName( + "class", + isUniqueName, + /*optimistic*/ false, + /*scoped*/ false, + /*privateName*/ false, + /*prefix*/ "", + /*suffix*/ "", + ); } - function generateNameForMethodOrAccessor(node: MethodDeclaration | AccessorDeclaration, privateName: boolean, prefix: string, suffix: string) { + function generateNameForMethodOrAccessor( + node: MethodDeclaration | AccessorDeclaration, + privateName: boolean, + prefix: string, + suffix: string, + ) { if (isIdentifier(node.name)) { return generateNameCached(node.name, privateName); } @@ -6034,7 +6706,13 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri /** * Generates a unique name from a node. */ - function generateNameForNode(node: Node, privateName: boolean, flags: GeneratedIdentifierFlags, prefix: string, suffix: string): string { + function generateNameForNode( + node: Node, + privateName: boolean, + flags: GeneratedIdentifierFlags, + prefix: string, + suffix: string, + ): string { switch (node.kind) { case SyntaxKind.Identifier: case SyntaxKind.PrivateIdentifier: @@ -6073,11 +6751,28 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri case SyntaxKind.MethodDeclaration: case SyntaxKind.GetAccessor: case SyntaxKind.SetAccessor: - return generateNameForMethodOrAccessor(node as MethodDeclaration | AccessorDeclaration, privateName, prefix, suffix); + return generateNameForMethodOrAccessor( + node as MethodDeclaration | AccessorDeclaration, + privateName, + prefix, + suffix, + ); case SyntaxKind.ComputedPropertyName: - return makeTempVariableName(TempFlags.Auto, /*reservedInNestedScopes*/ true, privateName, prefix, suffix); + return makeTempVariableName( + TempFlags.Auto, + /*reservedInNestedScopes*/ true, + privateName, + prefix, + suffix, + ); default: - return makeTempVariableName(TempFlags.Auto, /*reservedInNestedScopes*/ false, privateName, prefix, suffix); + return makeTempVariableName( + TempFlags.Auto, + /*reservedInNestedScopes*/ false, + privateName, + prefix, + suffix, + ); } } @@ -6090,14 +6785,27 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri const suffix = formatGeneratedNamePart(autoGenerate.suffix); switch (autoGenerate.flags & GeneratedIdentifierFlags.KindMask) { case GeneratedIdentifierFlags.Auto: - return makeTempVariableName(TempFlags.Auto, !!(autoGenerate.flags & GeneratedIdentifierFlags.ReservedInNestedScopes), isPrivateIdentifier(name), prefix, suffix); + return makeTempVariableName( + TempFlags.Auto, + !!(autoGenerate.flags & GeneratedIdentifierFlags.ReservedInNestedScopes), + isPrivateIdentifier(name), + prefix, + suffix, + ); case GeneratedIdentifierFlags.Loop: Debug.assertNode(name, isIdentifier); - return makeTempVariableName(TempFlags._i, !!(autoGenerate.flags & GeneratedIdentifierFlags.ReservedInNestedScopes), /*privateName*/ false, prefix, suffix); + return makeTempVariableName( + TempFlags._i, + !!(autoGenerate.flags & GeneratedIdentifierFlags.ReservedInNestedScopes), + /*privateName*/ false, + prefix, + suffix, + ); case GeneratedIdentifierFlags.Unique: return makeUniqueName( idText(name), - (autoGenerate.flags & GeneratedIdentifierFlags.FileLevel) ? isFileLevelUniqueNameInCurrentFile : isUniqueName, + (autoGenerate.flags & GeneratedIdentifierFlags.FileLevel) ? isFileLevelUniqueNameInCurrentFile + : isUniqueName, !!(autoGenerate.flags & GeneratedIdentifierFlags.Optimistic), !!(autoGenerate.flags & GeneratedIdentifierFlags.ReservedInNestedScopes), isPrivateIdentifier(name), @@ -6106,7 +6814,15 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri ); } - return Debug.fail(`Unsupported GeneratedIdentifierKind: ${Debug.formatEnum(autoGenerate.flags & GeneratedIdentifierFlags.KindMask, (ts as any).GeneratedIdentifierFlags, /*isFlags*/ true)}.`); + return Debug.fail( + `Unsupported GeneratedIdentifierKind: ${ + Debug.formatEnum( + autoGenerate.flags & GeneratedIdentifierFlags.KindMask, + (ts as any).GeneratedIdentifierFlags, + /*isFlags*/ true, + ) + }.`, + ); } // Comments @@ -6132,7 +6848,12 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri } } - function emitCommentsAfterNode(node: Node, savedContainerPos: number, savedContainerEnd: number, savedDeclarationListContainerEnd: number) { + function emitCommentsAfterNode( + node: Node, + savedContainerPos: number, + savedContainerEnd: number, + savedDeclarationListContainerEnd: number, + ) { const emitFlags = getEmitFlags(node); const commentRange = getCommentRange(node); @@ -6140,10 +6861,26 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri if (emitFlags & EmitFlags.NoNestedComments) { commentsDisabled = false; } - emitTrailingCommentsOfNode(node, emitFlags, commentRange.pos, commentRange.end, savedContainerPos, savedContainerEnd, savedDeclarationListContainerEnd); + emitTrailingCommentsOfNode( + node, + emitFlags, + commentRange.pos, + commentRange.end, + savedContainerPos, + savedContainerEnd, + savedDeclarationListContainerEnd, + ); const typeNode = getTypeNode(node); if (typeNode) { - emitTrailingCommentsOfNode(node, emitFlags, typeNode.pos, typeNode.end, savedContainerPos, savedContainerEnd, savedDeclarationListContainerEnd); + emitTrailingCommentsOfNode( + node, + emitFlags, + typeNode.pos, + typeNode.end, + savedContainerPos, + savedContainerEnd, + savedDeclarationListContainerEnd, + ); } } @@ -6153,8 +6890,10 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri // We have to explicitly check that the node is JsxText because if the compilerOptions.jsx is "preserve" we will not do any transformation. // It is expensive to walk entire tree just to set one kind of node to have no comments. - const skipLeadingComments = pos < 0 || (emitFlags & EmitFlags.NoLeadingComments) !== 0 || node.kind === SyntaxKind.JsxText; - const skipTrailingComments = end < 0 || (emitFlags & EmitFlags.NoTrailingComments) !== 0 || node.kind === SyntaxKind.JsxText; + const skipLeadingComments = pos < 0 || (emitFlags & EmitFlags.NoLeadingComments) !== 0 + || node.kind === SyntaxKind.JsxText; + const skipTrailingComments = end < 0 || (emitFlags & EmitFlags.NoTrailingComments) !== 0 + || node.kind === SyntaxKind.JsxText; // Save current container state on the stack. if ((pos > 0 || end > 0) && pos !== end) { @@ -6184,9 +6923,18 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri exitComment(); } - function emitTrailingCommentsOfNode(node: Node, emitFlags: EmitFlags, pos: number, end: number, savedContainerPos: number, savedContainerEnd: number, savedDeclarationListContainerEnd: number) { + function emitTrailingCommentsOfNode( + node: Node, + emitFlags: EmitFlags, + pos: number, + end: number, + savedContainerPos: number, + savedContainerEnd: number, + savedDeclarationListContainerEnd: number, + ) { enterComment(); - const skipTrailingComments = end < 0 || (emitFlags & EmitFlags.NoTrailingComments) !== 0 || node.kind === SyntaxKind.JsxText; + const skipTrailingComments = end < 0 || (emitFlags & EmitFlags.NoTrailingComments) !== 0 + || node.kind === SyntaxKind.JsxText; forEach(getSyntheticTrailingComments(node), emitTrailingSynthesizedComment); if ((pos > 0 || end > 0) && pos !== end) { // Restore previous container state. @@ -6238,7 +6986,11 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri : `//${comment.text}`; } - function emitBodyWithDetachedComments(node: T, detachedRange: TextRange, emitCallback: (node: T) => void) { + function emitBodyWithDetachedComments( + node: T, + detachedRange: TextRange, + emitCallback: (node: T) => void, + ) { enterComment(); const { pos, end } = detachedRange; const emitFlags = getEmitFlags(node); @@ -6289,7 +7041,8 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri const parentNodeArray = getContainingNodeArray(previousNode); const prevNodeIndex = parentNodeArray?.indexOf(previousNode); - return prevNodeIndex !== undefined && prevNodeIndex > -1 && parentNodeArray!.indexOf(nextNode) === prevNodeIndex + 1; + return prevNodeIndex !== undefined && prevNodeIndex > -1 + && parentNodeArray!.indexOf(nextNode) === prevNodeIndex + 1; } function emitLeadingComments(pos: number, isEmittedNode: boolean) { @@ -6316,13 +7069,25 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri } } - function emitTripleSlashLeadingComment(commentPos: number, commentEnd: number, kind: SyntaxKind, hasTrailingNewLine: boolean, rangePos: number) { + function emitTripleSlashLeadingComment( + commentPos: number, + commentEnd: number, + kind: SyntaxKind, + hasTrailingNewLine: boolean, + rangePos: number, + ) { if (isTripleSlashComment(commentPos, commentEnd)) { emitLeadingComment(commentPos, commentEnd, kind, hasTrailingNewLine, rangePos); } } - function emitNonTripleSlashLeadingComment(commentPos: number, commentEnd: number, kind: SyntaxKind, hasTrailingNewLine: boolean, rangePos: number) { + function emitNonTripleSlashLeadingComment( + commentPos: number, + commentEnd: number, + kind: SyntaxKind, + hasTrailingNewLine: boolean, + rangePos: number, + ) { if (!isTripleSlashComment(commentPos, commentEnd)) { emitLeadingComment(commentPos, commentEnd, kind, hasTrailingNewLine, rangePos); } @@ -6335,7 +7100,13 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri return true; } - function emitLeadingComment(commentPos: number, commentEnd: number, kind: SyntaxKind, hasTrailingNewLine: boolean, rangePos: number) { + function emitLeadingComment( + commentPos: number, + commentEnd: number, + kind: SyntaxKind, + hasTrailingNewLine: boolean, + rangePos: number, + ) { if (!currentSourceFile || !shouldWriteComment(currentSourceFile.text, commentPos)) return; if (!hasWrittenComment) { emitNewLineBeforeLeadingCommentOfPosition(getCurrentLineMap(), writer, rangePos, commentPos); @@ -6367,7 +7138,12 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri forEachTrailingCommentToEmit(pos, emitTrailingComment); } - function emitTrailingComment(commentPos: number, commentEnd: number, _kind: SyntaxKind, hasTrailingNewLine: boolean) { + function emitTrailingComment( + commentPos: number, + commentEnd: number, + _kind: SyntaxKind, + hasTrailingNewLine: boolean, + ) { if (!currentSourceFile || !shouldWriteComment(currentSourceFile.text, commentPos)) return; // trailing comments are emitted at space/*trailing comment1 */space/*trailing comment2*/ if (!writer.isAtStartOfLine()) { @@ -6388,7 +7164,11 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri return; } enterComment(); - forEachTrailingCommentToEmit(pos, prefixSpace ? emitTrailingComment : forceNoNewline ? emitTrailingCommentOfPositionNoNewline : emitTrailingCommentOfPosition); + forEachTrailingCommentToEmit( + pos, + prefixSpace ? emitTrailingComment + : forceNoNewline ? emitTrailingCommentOfPositionNoNewline : emitTrailingCommentOfPosition, + ); exitComment(); } @@ -6405,7 +7185,12 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri } } - function emitTrailingCommentOfPosition(commentPos: number, commentEnd: number, _kind: SyntaxKind, hasTrailingNewLine: boolean) { + function emitTrailingCommentOfPosition( + commentPos: number, + commentEnd: number, + _kind: SyntaxKind, + hasTrailingNewLine: boolean, + ) { if (!currentSourceFile) return; // trailing comments of a position are emitted at /*trailing comment1 */space/*trailing comment*/space @@ -6421,7 +7206,16 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri } } - function forEachLeadingCommentToEmit(pos: number, cb: (commentPos: number, commentEnd: number, kind: SyntaxKind, hasTrailingNewLine: boolean, rangePos: number) => void) { + function forEachLeadingCommentToEmit( + pos: number, + cb: ( + commentPos: number, + commentEnd: number, + kind: SyntaxKind, + hasTrailingNewLine: boolean, + rangePos: number, + ) => void, + ) { // Emit the leading comments only if the container's pos doesn't match because the container should take care of emitting these comments if (currentSourceFile && (containerPos === -1 || pos !== containerPos)) { if (hasDetachedComments(pos)) { @@ -6433,9 +7227,14 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri } } - function forEachTrailingCommentToEmit(end: number, cb: (commentPos: number, commentEnd: number, kind: SyntaxKind, hasTrailingNewLine: boolean) => void) { + function forEachTrailingCommentToEmit( + end: number, + cb: (commentPos: number, commentEnd: number, kind: SyntaxKind, hasTrailingNewLine: boolean) => void, + ) { // Emit the trailing comments only if the container's end doesn't match because the container should take care of emitting these comments - if (currentSourceFile && (containerEnd === -1 || (end !== containerEnd && end !== declarationListContainerEnd))) { + if ( + currentSourceFile && (containerEnd === -1 || (end !== containerEnd && end !== declarationListContainerEnd)) + ) { forEachTrailingCommentRange(currentSourceFile.text, end, cb); } } @@ -6444,7 +7243,15 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri return detachedCommentsInfo !== undefined && last(detachedCommentsInfo).nodePos === pos; } - function forEachLeadingCommentWithoutDetachedComments(cb: (commentPos: number, commentEnd: number, kind: SyntaxKind, hasTrailingNewLine: boolean, rangePos: number) => void) { + function forEachLeadingCommentWithoutDetachedComments( + cb: ( + commentPos: number, + commentEnd: number, + kind: SyntaxKind, + hasTrailingNewLine: boolean, + rangePos: number, + ) => void, + ) { if (!currentSourceFile) return; // get the leading comments from detachedPos const pos = last(detachedCommentsInfo!).detachedCommentEndPos; @@ -6459,7 +7266,16 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri } function emitDetachedCommentsAndUpdateCommentsInfo(range: TextRange) { - const currentDetachedCommentInfo = currentSourceFile && emitDetachedComments(currentSourceFile.text, getCurrentLineMap(), writer, emitComment, range, newLine, commentsDisabled); + const currentDetachedCommentInfo = currentSourceFile + && emitDetachedComments( + currentSourceFile.text, + getCurrentLineMap(), + writer, + emitComment, + range, + newLine, + commentsDisabled, + ); if (currentDetachedCommentInfo) { if (detachedCommentsInfo) { detachedCommentsInfo.push(currentDetachedCommentInfo); @@ -6470,7 +7286,14 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri } } - function emitComment(text: string, lineMap: readonly number[], writer: EmitTextWriter, commentPos: number, commentEnd: number, newLine: string) { + function emitComment( + text: string, + lineMap: readonly number[], + writer: EmitTextWriter, + commentPos: number, + commentEnd: number, + newLine: string, + ) { if (!currentSourceFile || !shouldWriteComment(currentSourceFile.text, commentPos)) return; emitPos(commentPos); writeCommentRange(text, lineMap, writer, commentPos, commentEnd, newLine); @@ -6607,7 +7430,13 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri * @param tokenStartPos The start pos of the token. * @param emitCallback The callback used to emit the token. */ - function emitTokenWithSourceMap(node: Node | undefined, token: SyntaxKind, writer: (s: string) => void, tokenPos: number, emitCallback: (token: SyntaxKind, writer: (s: string) => void, tokenStartPos: number) => number) { + function emitTokenWithSourceMap( + node: Node | undefined, + token: SyntaxKind, + writer: (s: string) => void, + tokenPos: number, + emitCallback: (token: SyntaxKind, writer: (s: string) => void, tokenStartPos: number) => number, + ) { if (sourceMapsDisabled || node && isInJsonFile(node)) { return emitCallback(token, writer, tokenPos); } @@ -6702,22 +7531,45 @@ type ParenthesizerRule = (node: T) => T; type ParenthesizerRuleOrSelector = OrdinalParentheizerRuleSelector | ParenthesizerRule; type EmitFunction = (node: T, parenthesizerRule?: ParenthesizerRule) => void; -type EmitListItemFunction = (node: Node, emit: EmitFunction, parenthesizerRule: ParenthesizerRuleOrSelector | undefined, index: number) => void; - -function emitListItemNoParenthesizer(node: Node, emit: EmitFunction, _parenthesizerRule: ParenthesizerRuleOrSelector | undefined, _index: number) { +type EmitListItemFunction = ( + node: Node, + emit: EmitFunction, + parenthesizerRule: ParenthesizerRuleOrSelector | undefined, + index: number, +) => void; + +function emitListItemNoParenthesizer( + node: Node, + emit: EmitFunction, + _parenthesizerRule: ParenthesizerRuleOrSelector | undefined, + _index: number, +) { emit(node); } -function emitListItemWithParenthesizerRuleSelector(node: Node, emit: EmitFunction, parenthesizerRuleSelector: OrdinalParentheizerRuleSelector | undefined, index: number) { +function emitListItemWithParenthesizerRuleSelector( + node: Node, + emit: EmitFunction, + parenthesizerRuleSelector: OrdinalParentheizerRuleSelector | undefined, + index: number, +) { emit(node, parenthesizerRuleSelector!.select(index)); } -function emitListItemWithParenthesizerRule(node: Node, emit: EmitFunction, parenthesizerRule: ParenthesizerRule | undefined, _index: number) { +function emitListItemWithParenthesizerRule( + node: Node, + emit: EmitFunction, + parenthesizerRule: ParenthesizerRule | undefined, + _index: number, +) { emit(node, parenthesizerRule); } -function getEmitListItem(emit: EmitFunction, parenthesizerRule: ParenthesizerRuleOrSelector | undefined): EmitListItemFunction { - return emit.length === 1 ? emitListItemNoParenthesizer as EmitListItemFunction : - typeof parenthesizerRule === "object" ? emitListItemWithParenthesizerRuleSelector as EmitListItemFunction : - emitListItemWithParenthesizerRule as EmitListItemFunction; +function getEmitListItem( + emit: EmitFunction, + parenthesizerRule: ParenthesizerRuleOrSelector | undefined, +): EmitListItemFunction { + return emit.length === 1 ? emitListItemNoParenthesizer as EmitListItemFunction + : typeof parenthesizerRule === "object" ? emitListItemWithParenthesizerRuleSelector as EmitListItemFunction + : emitListItemWithParenthesizerRule as EmitListItemFunction; } diff --git a/src/compiler/factory/baseNodeFactory.ts b/src/compiler/factory/baseNodeFactory.ts index 9ea81cdf5632b..5fe2d2488ab3b 100644 --- a/src/compiler/factory/baseNodeFactory.ts +++ b/src/compiler/factory/baseNodeFactory.ts @@ -39,22 +39,43 @@ export function createBaseNodeFactory(): BaseNodeFactory { }; function createBaseSourceFileNode(kind: SyntaxKind.SourceFile): Node { - return new (SourceFileConstructor || (SourceFileConstructor = objectAllocator.getSourceFileConstructor()))(kind, /*pos*/ -1, /*end*/ -1); + return new (SourceFileConstructor || (SourceFileConstructor = objectAllocator.getSourceFileConstructor()))( + kind, + /*pos*/ -1, + /*end*/ -1, + ); } function createBaseIdentifierNode(kind: SyntaxKind.Identifier): Node { - return new (IdentifierConstructor || (IdentifierConstructor = objectAllocator.getIdentifierConstructor()))(kind, /*pos*/ -1, /*end*/ -1); + return new (IdentifierConstructor || (IdentifierConstructor = objectAllocator.getIdentifierConstructor()))( + kind, + /*pos*/ -1, + /*end*/ -1, + ); } function createBasePrivateIdentifierNode(kind: SyntaxKind.PrivateIdentifier): Node { - return new (PrivateIdentifierConstructor || (PrivateIdentifierConstructor = objectAllocator.getPrivateIdentifierConstructor()))(kind, /*pos*/ -1, /*end*/ -1); + return new (PrivateIdentifierConstructor + || (PrivateIdentifierConstructor = objectAllocator.getPrivateIdentifierConstructor()))( + kind, + /*pos*/ -1, + /*end*/ -1, + ); } function createBaseTokenNode(kind: SyntaxKind): Node { - return new (TokenConstructor || (TokenConstructor = objectAllocator.getTokenConstructor()))(kind, /*pos*/ -1, /*end*/ -1); + return new (TokenConstructor || (TokenConstructor = objectAllocator.getTokenConstructor()))( + kind, + /*pos*/ -1, + /*end*/ -1, + ); } function createBaseNode(kind: SyntaxKind): Node { - return new (NodeConstructor || (NodeConstructor = objectAllocator.getNodeConstructor()))(kind, /*pos*/ -1, /*end*/ -1); + return new (NodeConstructor || (NodeConstructor = objectAllocator.getNodeConstructor()))( + kind, + /*pos*/ -1, + /*end*/ -1, + ); } } diff --git a/src/compiler/factory/emitHelpers.ts b/src/compiler/factory/emitHelpers.ts index f3a49d77cb04f..64e59d7b33510 100644 --- a/src/compiler/factory/emitHelpers.ts +++ b/src/compiler/factory/emitHelpers.ts @@ -100,11 +100,23 @@ export type ESDecorateContext = export interface EmitHelperFactory { getUnscopedHelperName(name: string): Identifier; // TypeScript Helpers - createDecorateHelper(decoratorExpressions: readonly Expression[], target: Expression, memberName?: Expression, descriptor?: Expression): Expression; + createDecorateHelper( + decoratorExpressions: readonly Expression[], + target: Expression, + memberName?: Expression, + descriptor?: Expression, + ): Expression; createMetadataHelper(metadataKey: string, metadataValue: Expression): Expression; createParamHelper(expression: Expression, parameterOffset: number): Expression; // ES Decorators Helpers - createESDecorateHelper(ctor: Expression, descriptorIn: Expression, decorators: Expression, contextIn: ESDecorateContext, initializers: Expression, extraInitializers: Expression): Expression; + createESDecorateHelper( + ctor: Expression, + descriptorIn: Expression, + decorators: Expression, + contextIn: ESDecorateContext, + initializers: Expression, + extraInitializers: Expression, + ): Expression; createRunInitializersHelper(thisArg: Expression, initializers: Expression, value?: Expression): Expression; // ES2018 Helpers createAssignHelper(attributesSegments: readonly Expression[]): Expression; @@ -113,9 +125,19 @@ export interface EmitHelperFactory { createAsyncDelegatorHelper(expression: Expression): Expression; createAsyncValuesHelper(expression: Expression): Expression; // ES2018 Destructuring Helpers - createRestHelper(value: Expression, elements: readonly BindingOrAssignmentElement[], computedTempVariables: readonly Expression[] | undefined, location: TextRange): Expression; + createRestHelper( + value: Expression, + elements: readonly BindingOrAssignmentElement[], + computedTempVariables: readonly Expression[] | undefined, + location: TextRange, + ): Expression; // ES2017 Helpers - createAwaiterHelper(hasLexicalThis: boolean, hasLexicalArguments: boolean, promiseConstructor: EntityName | Expression | undefined, body: Block): Expression; + createAwaiterHelper( + hasLexicalThis: boolean, + hasLexicalArguments: boolean, + promiseConstructor: EntityName | Expression | undefined, + body: Block, + ): Expression; // ES2015 Helpers createExtendsHelper(name: Identifier): Expression; createTemplateObjectHelper(cooked: ArrayLiteralExpression, raw: ArrayLiteralExpression): Expression; @@ -128,14 +150,29 @@ export interface EmitHelperFactory { // ES2015 Generator Helpers createGeneratorHelper(body: FunctionExpression): Expression; // ES Module Helpers - createCreateBindingHelper(module: Expression, inputName: Expression, outputName: Expression | undefined): Expression; + createCreateBindingHelper( + module: Expression, + inputName: Expression, + outputName: Expression | undefined, + ): Expression; createImportStarHelper(expression: Expression): Expression; createImportStarCallbackHelper(): Expression; createImportDefaultHelper(expression: Expression): Expression; createExportStarHelper(moduleExpression: Expression, exportsExpression?: Expression): Expression; // Class Fields Helpers - createClassPrivateFieldGetHelper(receiver: Expression, state: Identifier, kind: PrivateIdentifierKind, f: Identifier | undefined): Expression; - createClassPrivateFieldSetHelper(receiver: Expression, state: Identifier, value: Expression, kind: PrivateIdentifierKind, f: Identifier | undefined): Expression; + createClassPrivateFieldGetHelper( + receiver: Expression, + state: Identifier, + kind: PrivateIdentifierKind, + f: Identifier | undefined, + ): Expression; + createClassPrivateFieldSetHelper( + receiver: Expression, + state: Identifier, + value: Expression, + kind: PrivateIdentifierKind, + f: Identifier | undefined, + ): Expression; createClassPrivateFieldInHelper(state: Identifier, receiver: Expression): Expression; // 'using' helpers createAddDisposableResourceHelper(envBinding: Expression, value: Expression, async: boolean): Expression; @@ -202,7 +239,12 @@ export function createEmitHelperFactory(context: TransformationContext): EmitHel // TypeScript Helpers - function createDecorateHelper(decoratorExpressions: Expression[], target: Expression, memberName?: Expression, descriptor?: Expression) { + function createDecorateHelper( + decoratorExpressions: Expression[], + target: Expression, + memberName?: Expression, + descriptor?: Expression, + ) { context.requestEmitHelper(decorateHelper); const argumentsArray: Expression[] = []; @@ -262,9 +304,9 @@ export function createEmitHelperFactory(context: TransformationContext): EmitHel } function createESDecorateClassElementAccessGetMethod(elementName: ESDecorateName) { - const accessor = elementName.computed ? - factory.createElementAccessExpression(factory.createIdentifier("obj"), elementName.name) : - factory.createPropertyAccessExpression(factory.createIdentifier("obj"), elementName.name); + const accessor = elementName.computed + ? factory.createElementAccessExpression(factory.createIdentifier("obj"), elementName.name) + : factory.createPropertyAccessExpression(factory.createIdentifier("obj"), elementName.name); return factory.createPropertyAssignment( "get", @@ -284,9 +326,9 @@ export function createEmitHelperFactory(context: TransformationContext): EmitHel } function createESDecorateClassElementAccessSetMethod(elementName: ESDecorateName) { - const accessor = elementName.computed ? - factory.createElementAccessExpression(factory.createIdentifier("obj"), elementName.name) : - factory.createPropertyAccessExpression(factory.createIdentifier("obj"), elementName.name); + const accessor = elementName.computed + ? factory.createElementAccessExpression(factory.createIdentifier("obj"), elementName.name) + : factory.createPropertyAccessExpression(factory.createIdentifier("obj"), elementName.name); return factory.createPropertyAssignment( "set", @@ -320,9 +362,9 @@ export function createEmitHelperFactory(context: TransformationContext): EmitHel } function createESDecorateClassElementAccessHasMethod(elementName: ESDecorateName) { - const propertyName = elementName.computed ? elementName.name : - isIdentifier(elementName.name) ? factory.createStringLiteralFromNode(elementName.name) : - elementName.name; + const propertyName = elementName.computed ? elementName.name + : isIdentifier(elementName.name) ? factory.createStringLiteralFromNode(elementName.name) + : elementName.name; return factory.createPropertyAssignment( "has", @@ -355,22 +397,45 @@ export function createEmitHelperFactory(context: TransformationContext): EmitHel function createESDecorateClassElementContextObject(contextIn: ESDecorateClassElementContext) { const properties = [ - factory.createPropertyAssignment(factory.createIdentifier("kind"), factory.createStringLiteral(contextIn.kind)), - factory.createPropertyAssignment(factory.createIdentifier("name"), contextIn.name.computed ? contextIn.name.name : factory.createStringLiteralFromNode(contextIn.name.name)), - factory.createPropertyAssignment(factory.createIdentifier("static"), contextIn.static ? factory.createTrue() : factory.createFalse()), - factory.createPropertyAssignment(factory.createIdentifier("private"), contextIn.private ? factory.createTrue() : factory.createFalse()), - factory.createPropertyAssignment(factory.createIdentifier("access"), createESDecorateClassElementAccessObject(contextIn.name, contextIn.access)), + factory.createPropertyAssignment( + factory.createIdentifier("kind"), + factory.createStringLiteral(contextIn.kind), + ), + factory.createPropertyAssignment( + factory.createIdentifier("name"), + contextIn.name.computed ? contextIn.name.name + : factory.createStringLiteralFromNode(contextIn.name.name), + ), + factory.createPropertyAssignment( + factory.createIdentifier("static"), + contextIn.static ? factory.createTrue() : factory.createFalse(), + ), + factory.createPropertyAssignment( + factory.createIdentifier("private"), + contextIn.private ? factory.createTrue() : factory.createFalse(), + ), + factory.createPropertyAssignment( + factory.createIdentifier("access"), + createESDecorateClassElementAccessObject(contextIn.name, contextIn.access), + ), factory.createPropertyAssignment(factory.createIdentifier("metadata"), contextIn.metadata), ]; return factory.createObjectLiteralExpression(properties); } function createESDecorateContextObject(contextIn: ESDecorateContext) { - return contextIn.kind === "class" ? createESDecorateClassContextObject(contextIn) : - createESDecorateClassElementContextObject(contextIn); + return contextIn.kind === "class" ? createESDecorateClassContextObject(contextIn) + : createESDecorateClassElementContextObject(contextIn); } - function createESDecorateHelper(ctor: Expression, descriptorIn: Expression, decorators: Expression, contextIn: ESDecorateContext, initializers: Expression, extraInitializers: Expression) { + function createESDecorateHelper( + ctor: Expression, + descriptorIn: Expression, + decorators: Expression, + contextIn: ESDecorateContext, + initializers: Expression, + extraInitializers: Expression, + ) { context.requestEmitHelper(esDecorateHelper); return factory.createCallExpression( getUnscopedHelperName("__esDecorate"), @@ -398,7 +463,11 @@ export function createEmitHelperFactory(context: TransformationContext): EmitHel function createAssignHelper(attributesSegments: Expression[]) { if (getEmitScriptTarget(context.getCompilerOptions()) >= ScriptTarget.ES2015) { - return factory.createCallExpression(factory.createPropertyAccessExpression(factory.createIdentifier("Object"), "assign"), /*typeArguments*/ undefined, attributesSegments); + return factory.createCallExpression( + factory.createPropertyAccessExpression(factory.createIdentifier("Object"), "assign"), + /*typeArguments*/ undefined, + attributesSegments, + ); } context.requestEmitHelper(assignHelper); return factory.createCallExpression( @@ -410,7 +479,9 @@ export function createEmitHelperFactory(context: TransformationContext): EmitHel function createAwaitHelper(expression: Expression) { context.requestEmitHelper(awaitHelper); - return factory.createCallExpression(getUnscopedHelperName("__await"), /*typeArguments*/ undefined, [expression]); + return factory.createCallExpression(getUnscopedHelperName("__await"), /*typeArguments*/ undefined, [ + expression, + ]); } function createAsyncGeneratorHelper(generatorFunc: FunctionExpression, hasLexicalThis: boolean) { @@ -418,7 +489,8 @@ export function createEmitHelperFactory(context: TransformationContext): EmitHel context.requestEmitHelper(asyncGeneratorHelper); // Mark this node as originally an async function - (generatorFunc.emitNode || (generatorFunc.emitNode = {} as EmitNode)).flags |= EmitFlags.AsyncFunctionBody | EmitFlags.ReuseTempVariableScope; + (generatorFunc.emitNode || (generatorFunc.emitNode = {} as EmitNode)).flags |= EmitFlags.AsyncFunctionBody + | EmitFlags.ReuseTempVariableScope; return factory.createCallExpression( getUnscopedHelperName("__asyncGenerator"), @@ -455,7 +527,12 @@ export function createEmitHelperFactory(context: TransformationContext): EmitHel /** Given value: o, propName: p, pattern: { a, b, ...p } from the original statement * `{ a, b, ...p } = o`, create `p = __rest(o, ["a", "b"]);` */ - function createRestHelper(value: Expression, elements: readonly BindingOrAssignmentElement[], computedTempVariables: readonly Expression[] | undefined, location: TextRange): Expression { + function createRestHelper( + value: Expression, + elements: readonly BindingOrAssignmentElement[], + computedTempVariables: readonly Expression[] | undefined, + location: TextRange, + ): Expression { context.requestEmitHelper(restHelper); const propertyNames: Expression[] = []; let computedTempVariableOffset = 0; @@ -463,7 +540,10 @@ export function createEmitHelperFactory(context: TransformationContext): EmitHel const propertyName = getPropertyNameOfBindingOrAssignmentElement(elements[i]); if (propertyName) { if (isComputedPropertyName(propertyName)) { - Debug.assertIsDefined(computedTempVariables, "Encountered computed property name but 'computedTempVariables' argument was not provided."); + Debug.assertIsDefined( + computedTempVariables, + "Encountered computed property name but 'computedTempVariables' argument was not provided.", + ); const temp = computedTempVariables[computedTempVariableOffset]; computedTempVariableOffset++; // typeof _tmp === "symbol" ? _tmp : _tmp + "" @@ -497,7 +577,12 @@ export function createEmitHelperFactory(context: TransformationContext): EmitHel // ES2017 Helpers - function createAwaiterHelper(hasLexicalThis: boolean, hasLexicalArguments: boolean, promiseConstructor: EntityName | Expression | undefined, body: Block) { + function createAwaiterHelper( + hasLexicalThis: boolean, + hasLexicalArguments: boolean, + promiseConstructor: EntityName | Expression | undefined, + body: Block, + ) { context.requestEmitHelper(awaiterHelper); const generatorFunc = factory.createFunctionExpression( @@ -511,7 +596,8 @@ export function createEmitHelperFactory(context: TransformationContext): EmitHel ); // Mark this node as originally an async function - (generatorFunc.emitNode || (generatorFunc.emitNode = {} as EmitNode)).flags |= EmitFlags.AsyncFunctionBody | EmitFlags.ReuseTempVariableScope; + (generatorFunc.emitNode || (generatorFunc.emitNode = {} as EmitNode)).flags |= EmitFlags.AsyncFunctionBody + | EmitFlags.ReuseTempVariableScope; return factory.createCallExpression( getUnscopedHelperName("__awaiter"), @@ -519,7 +605,8 @@ export function createEmitHelperFactory(context: TransformationContext): EmitHel [ hasLexicalThis ? factory.createThis() : factory.createVoidZero(), hasLexicalArguments ? factory.createIdentifier("arguments") : factory.createVoidZero(), - promiseConstructor ? createExpressionFromEntityName(factory, promiseConstructor) : factory.createVoidZero(), + promiseConstructor ? createExpressionFromEntityName(factory, promiseConstructor) + : factory.createVoidZero(), generatorFunc, ], ); @@ -532,7 +619,13 @@ export function createEmitHelperFactory(context: TransformationContext): EmitHel return factory.createCallExpression( getUnscopedHelperName("__extends"), /*typeArguments*/ undefined, - [name, factory.createUniqueName("_super", GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel)], + [ + name, + factory.createUniqueName( + "_super", + GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel, + ), + ], ); } @@ -639,7 +732,10 @@ export function createEmitHelperFactory(context: TransformationContext): EmitHel ); } - function createExportStarHelper(moduleExpression: Expression, exportsExpression: Expression = factory.createIdentifier("exports")) { + function createExportStarHelper( + moduleExpression: Expression, + exportsExpression: Expression = factory.createIdentifier("exports"), + ) { context.requestEmitHelper(exportStarHelper); context.requestEmitHelper(createBindingHelper); return factory.createCallExpression( @@ -651,7 +747,12 @@ export function createEmitHelperFactory(context: TransformationContext): EmitHel // Class Fields Helpers - function createClassPrivateFieldGetHelper(receiver: Expression, state: Identifier, kind: PrivateIdentifierKind, f: Identifier | undefined) { + function createClassPrivateFieldGetHelper( + receiver: Expression, + state: Identifier, + kind: PrivateIdentifierKind, + f: Identifier | undefined, + ) { context.requestEmitHelper(classPrivateFieldGetHelper); let args; if (!f) { @@ -660,10 +761,20 @@ export function createEmitHelperFactory(context: TransformationContext): EmitHel else { args = [receiver, state, factory.createStringLiteral(kind), f]; } - return factory.createCallExpression(getUnscopedHelperName("__classPrivateFieldGet"), /*typeArguments*/ undefined, args); + return factory.createCallExpression( + getUnscopedHelperName("__classPrivateFieldGet"), + /*typeArguments*/ undefined, + args, + ); } - function createClassPrivateFieldSetHelper(receiver: Expression, state: Identifier, value: Expression, kind: PrivateIdentifierKind, f: Identifier | undefined) { + function createClassPrivateFieldSetHelper( + receiver: Expression, + state: Identifier, + value: Expression, + kind: PrivateIdentifierKind, + f: Identifier | undefined, + ) { context.requestEmitHelper(classPrivateFieldSetHelper); let args; if (!f) { @@ -672,12 +783,20 @@ export function createEmitHelperFactory(context: TransformationContext): EmitHel else { args = [receiver, state, value, factory.createStringLiteral(kind), f]; } - return factory.createCallExpression(getUnscopedHelperName("__classPrivateFieldSet"), /*typeArguments*/ undefined, args); + return factory.createCallExpression( + getUnscopedHelperName("__classPrivateFieldSet"), + /*typeArguments*/ undefined, + args, + ); } function createClassPrivateFieldInHelper(state: Identifier, receiver: Expression) { context.requestEmitHelper(classPrivateFieldInHelper); - return factory.createCallExpression(getUnscopedHelperName("__classPrivateFieldIn"), /*typeArguments*/ undefined, [state, receiver]); + return factory.createCallExpression( + getUnscopedHelperName("__classPrivateFieldIn"), + /*typeArguments*/ undefined, + [state, receiver], + ); } function createAddDisposableResourceHelper(envBinding: Expression, value: Expression, async: boolean): Expression { @@ -691,7 +810,9 @@ export function createEmitHelperFactory(context: TransformationContext): EmitHel function createDisposeResourcesHelper(envBinding: Expression) { context.requestEmitHelper(disposeResourcesHelper); - return factory.createCallExpression(getUnscopedHelperName("__disposeResources"), /*typeArguments*/ undefined, [envBinding]); + return factory.createCallExpression(getUnscopedHelperName("__disposeResources"), /*typeArguments*/ undefined, [ + envBinding, + ]); } } diff --git a/src/compiler/factory/emitNode.ts b/src/compiler/factory/emitNode.ts index fba507d899ea7..edcbbd0cfb245 100644 --- a/src/compiler/factory/emitNode.ts +++ b/src/compiler/factory/emitNode.ts @@ -43,14 +43,18 @@ export function getOrCreateEmitNode(node: Node): EmitNode { return node.emitNode = { annotatedNodes: [node] } as EmitNode; } - const sourceFile = getSourceFileOfNode(getParseTreeNode(getSourceFileOfNode(node))) ?? Debug.fail("Could not determine parsed source file."); + const sourceFile = getSourceFileOfNode(getParseTreeNode(getSourceFileOfNode(node))) + ?? Debug.fail("Could not determine parsed source file."); getOrCreateEmitNode(sourceFile).annotatedNodes!.push(node); } node.emitNode = {} as EmitNode; } else { - Debug.assert(!(node.emitNode.internalFlags & InternalEmitFlags.Immutable), "Invalid attempt to mutate an immutable node."); + Debug.assert( + !(node.emitNode.internalFlags & InternalEmitFlags.Immutable), + "Invalid attempt to mutate an immutable node.", + ); } return node.emitNode; } @@ -201,8 +205,22 @@ export function setSyntheticLeadingComments(node: T, comments: S return node; } -export function addSyntheticLeadingComment(node: T, kind: SyntaxKind.SingleLineCommentTrivia | SyntaxKind.MultiLineCommentTrivia, text: string, hasTrailingNewLine?: boolean) { - return setSyntheticLeadingComments(node, append(getSyntheticLeadingComments(node), { kind, pos: -1, end: -1, hasTrailingNewLine, text })); +export function addSyntheticLeadingComment( + node: T, + kind: SyntaxKind.SingleLineCommentTrivia | SyntaxKind.MultiLineCommentTrivia, + text: string, + hasTrailingNewLine?: boolean, +) { + return setSyntheticLeadingComments( + node, + append(getSyntheticLeadingComments(node), { + kind, + pos: -1, + end: -1, + hasTrailingNewLine, + text, + }), + ); } export function getSyntheticTrailingComments(node: Node): SynthesizedComment[] | undefined { @@ -214,8 +232,22 @@ export function setSyntheticTrailingComments(node: T, comments: return node; } -export function addSyntheticTrailingComment(node: T, kind: SyntaxKind.SingleLineCommentTrivia | SyntaxKind.MultiLineCommentTrivia, text: string, hasTrailingNewLine?: boolean) { - return setSyntheticTrailingComments(node, append(getSyntheticTrailingComments(node), { kind, pos: -1, end: -1, hasTrailingNewLine, text })); +export function addSyntheticTrailingComment( + node: T, + kind: SyntaxKind.SingleLineCommentTrivia | SyntaxKind.MultiLineCommentTrivia, + text: string, + hasTrailingNewLine?: boolean, +) { + return setSyntheticTrailingComments( + node, + append(getSyntheticTrailingComments(node), { + kind, + pos: -1, + end: -1, + hasTrailingNewLine, + text, + }), + ); } export function moveSyntheticComments(node: T, original: Node): T { @@ -348,18 +380,26 @@ export function getTypeNode(node: T): TypeNode | undefined { } /** @internal */ -export function setIdentifierTypeArguments(node: T, typeArguments: NodeArray | undefined) { +export function setIdentifierTypeArguments( + node: T, + typeArguments: NodeArray | undefined, +) { getOrCreateEmitNode(node).identifierTypeArguments = typeArguments; return node; } /** @internal */ -export function getIdentifierTypeArguments(node: Identifier): NodeArray | undefined { +export function getIdentifierTypeArguments( + node: Identifier, +): NodeArray | undefined { return node.emitNode?.identifierTypeArguments; } /** @internal */ -export function setIdentifierAutoGenerate(node: T, autoGenerate: AutoGenerateInfo | undefined) { +export function setIdentifierAutoGenerate( + node: T, + autoGenerate: AutoGenerateInfo | undefined, +) { getOrCreateEmitNode(node).autoGenerate = autoGenerate; return node; } @@ -370,12 +410,17 @@ export function getIdentifierAutoGenerate(node: Identifier | PrivateIdentifier): } /** @internal */ -export function setIdentifierGeneratedImportReference(node: T, value: ImportSpecifier | undefined) { +export function setIdentifierGeneratedImportReference( + node: T, + value: ImportSpecifier | undefined, +) { getOrCreateEmitNode(node).generatedImportReference = value; return node; } /** @internal */ -export function getIdentifierGeneratedImportReference(node: Identifier | PrivateIdentifier): ImportSpecifier | undefined { +export function getIdentifierGeneratedImportReference( + node: Identifier | PrivateIdentifier, +): ImportSpecifier | undefined { return node.emitNode?.generatedImportReference; } diff --git a/src/compiler/factory/nodeConverters.ts b/src/compiler/factory/nodeConverters.ts index 33ab7b4b598ad..00736b0d1c319 100644 --- a/src/compiler/factory/nodeConverters.ts +++ b/src/compiler/factory/nodeConverters.ts @@ -123,10 +123,23 @@ export function createNodeConverters(factory: NodeFactory): NodeConverters { } if (element.propertyName) { const expression = convertToAssignmentElementTarget(element.name); - return setOriginalNode(setTextRange(factory.createPropertyAssignment(element.propertyName, element.initializer ? factory.createAssignment(expression, element.initializer) : expression), element), element); + return setOriginalNode( + setTextRange( + factory.createPropertyAssignment( + element.propertyName, + element.initializer ? factory.createAssignment(expression, element.initializer) + : expression, + ), + element, + ), + element, + ); } Debug.assertNode(element.name, isIdentifier); - return setOriginalNode(setTextRange(factory.createShorthandPropertyAssignment(element.name, element.initializer), element), element); + return setOriginalNode( + setTextRange(factory.createShorthandPropertyAssignment(element.name, element.initializer), element), + element, + ); } return cast(element, isObjectLiteralElementLike); diff --git a/src/compiler/factory/nodeFactory.ts b/src/compiler/factory/nodeFactory.ts index ededdbd057ab9..1ecfad4277956 100644 --- a/src/compiler/factory/nodeFactory.ts +++ b/src/compiler/factory/nodeFactory.ts @@ -509,22 +509,65 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode const update = flags & NodeFactoryFlags.NoOriginalNode ? updateWithoutOriginal : updateWithOriginal; // Lazily load the parenthesizer, node converters, and some factory methods until they are used. - const parenthesizerRules = memoize(() => flags & NodeFactoryFlags.NoParenthesizerRules ? nullParenthesizerRules : createParenthesizerRules(factory)); - const converters = memoize(() => flags & NodeFactoryFlags.NoNodeConverters ? nullNodeConverters : createNodeConverters(factory)); + const parenthesizerRules = memoize(() => + flags & NodeFactoryFlags.NoParenthesizerRules ? nullParenthesizerRules : createParenthesizerRules(factory) + ); + const converters = memoize(() => + flags & NodeFactoryFlags.NoNodeConverters ? nullNodeConverters : createNodeConverters(factory) + ); // lazy initializaton of common operator factories - const getBinaryCreateFunction = memoizeOne((operator: BinaryOperator) => (left: Expression, right: Expression) => createBinaryExpression(left, operator, right)); - const getPrefixUnaryCreateFunction = memoizeOne((operator: PrefixUnaryOperator) => (operand: Expression) => createPrefixUnaryExpression(operator, operand)); - const getPostfixUnaryCreateFunction = memoizeOne((operator: PostfixUnaryOperator) => (operand: Expression) => createPostfixUnaryExpression(operand, operator)); - const getJSDocPrimaryTypeCreateFunction = memoizeOne((kind: T["kind"]) => () => createJSDocPrimaryTypeWorker(kind)); - const getJSDocUnaryTypeCreateFunction = memoizeOne((kind: T["kind"]) => (type: T["type"]) => createJSDocUnaryTypeWorker(kind, type)); - const getJSDocUnaryTypeUpdateFunction = memoizeOne((kind: T["kind"]) => (node: T, type: T["type"]) => updateJSDocUnaryTypeWorker(kind, node, type)); - const getJSDocPrePostfixUnaryTypeCreateFunction = memoizeOne((kind: T["kind"]) => (type: T["type"], postfix?: boolean) => createJSDocPrePostfixUnaryTypeWorker(kind, type, postfix)); - const getJSDocPrePostfixUnaryTypeUpdateFunction = memoizeOne((kind: T["kind"]) => (node: T, type: T["type"]) => updateJSDocPrePostfixUnaryTypeWorker(kind, node, type)); - const getJSDocSimpleTagCreateFunction = memoizeOne((kind: T["kind"]) => (tagName: Identifier | undefined, comment?: NodeArray) => createJSDocSimpleTagWorker(kind, tagName, comment)); - const getJSDocSimpleTagUpdateFunction = memoizeOne((kind: T["kind"]) => (node: T, tagName: Identifier | undefined, comment?: NodeArray) => updateJSDocSimpleTagWorker(kind, node, tagName, comment)); - const getJSDocTypeLikeTagCreateFunction = memoizeOne((kind: T["kind"]) => (tagName: Identifier | undefined, typeExpression?: JSDocTypeExpression, comment?: NodeArray) => createJSDocTypeLikeTagWorker(kind, tagName, typeExpression, comment)); - const getJSDocTypeLikeTagUpdateFunction = memoizeOne((kind: T["kind"]) => (node: T, tagName: Identifier | undefined, typeExpression?: JSDocTypeExpression, comment?: NodeArray) => updateJSDocTypeLikeTagWorker(kind, node, tagName, typeExpression, comment)); + const getBinaryCreateFunction = memoizeOne((operator: BinaryOperator) => (left: Expression, right: Expression) => + createBinaryExpression(left, operator, right) + ); + const getPrefixUnaryCreateFunction = memoizeOne((operator: PrefixUnaryOperator) => (operand: Expression) => + createPrefixUnaryExpression(operator, operand) + ); + const getPostfixUnaryCreateFunction = memoizeOne((operator: PostfixUnaryOperator) => (operand: Expression) => + createPostfixUnaryExpression(operand, operator) + ); + const getJSDocPrimaryTypeCreateFunction = memoizeOne((kind: T["kind"]) => () => + createJSDocPrimaryTypeWorker(kind) + ); + const getJSDocUnaryTypeCreateFunction = memoizeOne( + (kind: T["kind"]) => (type: T["type"]) => + createJSDocUnaryTypeWorker(kind, type), + ); + const getJSDocUnaryTypeUpdateFunction = memoizeOne( + (kind: T["kind"]) => + (node: T, type: T["type"]) => updateJSDocUnaryTypeWorker(kind, node, type), + ); + const getJSDocPrePostfixUnaryTypeCreateFunction = memoizeOne( + (kind: T["kind"]) => + (type: T["type"], postfix?: boolean) => createJSDocPrePostfixUnaryTypeWorker(kind, type, postfix), + ); + const getJSDocPrePostfixUnaryTypeUpdateFunction = memoizeOne( + (kind: T["kind"]) => + (node: T, type: T["type"]) => updateJSDocPrePostfixUnaryTypeWorker(kind, node, type), + ); + const getJSDocSimpleTagCreateFunction = memoizeOne( + (kind: T["kind"]) => (tagName: Identifier | undefined, comment?: NodeArray) => + createJSDocSimpleTagWorker(kind, tagName, comment), + ); + const getJSDocSimpleTagUpdateFunction = memoizeOne( + (kind: T["kind"]) => + (node: T, tagName: Identifier | undefined, comment?: NodeArray) => + updateJSDocSimpleTagWorker(kind, node, tagName, comment), + ); + const getJSDocTypeLikeTagCreateFunction = memoizeOne( + (kind: T["kind"]) => + (tagName: Identifier | undefined, typeExpression?: JSDocTypeExpression, comment?: NodeArray) => + createJSDocTypeLikeTagWorker(kind, tagName, typeExpression, comment), + ); + const getJSDocTypeLikeTagUpdateFunction = memoizeOne( + (kind: T["kind"]) => + ( + node: T, + tagName: Identifier | undefined, + typeExpression?: JSDocTypeExpression, + comment?: NodeArray, + ) => updateJSDocTypeLikeTagWorker(kind, node, tagName, typeExpression, comment), + ); const factory: NodeFactory = { get parenthesizer() { @@ -648,13 +691,15 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode updateArrayLiteralExpression, createObjectLiteralExpression, updateObjectLiteralExpression, - createPropertyAccessExpression: flags & NodeFactoryFlags.NoIndentationOnFreshPropertyAccess ? - (expression, name) => setEmitFlags(createPropertyAccessExpression(expression, name), EmitFlags.NoIndentation) : - createPropertyAccessExpression, + createPropertyAccessExpression: flags & NodeFactoryFlags.NoIndentationOnFreshPropertyAccess + ? (expression, name) => + setEmitFlags(createPropertyAccessExpression(expression, name), EmitFlags.NoIndentation) + : createPropertyAccessExpression, updatePropertyAccessExpression, - createPropertyAccessChain: flags & NodeFactoryFlags.NoIndentationOnFreshPropertyAccess ? - (expression, questionDotToken, name: string) => setEmitFlags(createPropertyAccessChain(expression, questionDotToken, name), EmitFlags.NoIndentation) : - createPropertyAccessChain, + createPropertyAccessChain: flags & NodeFactoryFlags.NoIndentationOnFreshPropertyAccess + ? (expression, questionDotToken, name: string) => + setEmitFlags(createPropertyAccessChain(expression, questionDotToken, name), EmitFlags.NoIndentation) + : createPropertyAccessChain, updatePropertyAccessChain, createElementAccessExpression, updateElementAccessExpression, @@ -1231,7 +1276,10 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode return node; } - function finishUpdateBaseSignatureDeclaration(updated: Mutable, original: T) { + function finishUpdateBaseSignatureDeclaration( + updated: Mutable, + original: T, + ) { if (updated !== original) { // copy children used for quick info updated.typeArguments = original.typeArguments; @@ -1244,13 +1292,21 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode // // @api - function createNumericLiteral(value: string | number, numericLiteralFlags: TokenFlags = TokenFlags.None): NumericLiteral { + function createNumericLiteral( + value: string | number, + numericLiteralFlags: TokenFlags = TokenFlags.None, + ): NumericLiteral { const text = typeof value === "number" ? value + "" : value; - Debug.assert(text.charCodeAt(0) !== CharacterCodes.minus, "Negative numbers should be created in combination with createPrefixUnaryExpression"); + Debug.assert( + text.charCodeAt(0) !== CharacterCodes.minus, + "Negative numbers should be created in combination with createPrefixUnaryExpression", + ); const node = createBaseDeclaration(SyntaxKind.NumericLiteral); node.text = text; node.numericLiteralFlags = numericLiteralFlags; - if (numericLiteralFlags & TokenFlags.BinaryOrOctalSpecifier) node.transformFlags |= TransformFlags.ContainsES2015; + if (numericLiteralFlags & TokenFlags.BinaryOrOctalSpecifier) { + node.transformFlags |= TransformFlags.ContainsES2015; + } return node; } @@ -1270,7 +1326,11 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } // @api - function createStringLiteral(text: string, isSingleQuote?: boolean, hasExtendedUnicodeEscape?: boolean): StringLiteral { + function createStringLiteral( + text: string, + isSingleQuote?: boolean, + hasExtendedUnicodeEscape?: boolean, + ): StringLiteral { const node = createBaseStringLiteral(text, isSingleQuote); node.hasExtendedUnicodeEscape = hasExtendedUnicodeEscape; if (hasExtendedUnicodeEscape) node.transformFlags |= TransformFlags.ContainsES2015; @@ -1292,7 +1352,10 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } // @api - function createLiteralLikeNode(kind: LiteralToken["kind"] | SyntaxKind.JsxTextAllWhiteSpaces, text: string): LiteralToken { + function createLiteralLikeNode( + kind: LiteralToken["kind"] | SyntaxKind.JsxTextAllWhiteSpaces, + text: string, + ): LiteralToken { switch (kind) { case SyntaxKind.NumericLiteral: return createNumericLiteral(text, /*numericLiteralFlags*/ 0); @@ -1307,7 +1370,12 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode case SyntaxKind.RegularExpressionLiteral: return createRegularExpressionLiteral(text); case SyntaxKind.NoSubstitutionTemplateLiteral: - return createTemplateLiteralLikeNode(kind, text, /*rawText*/ undefined, /*templateFlags*/ 0) as NoSubstitutionTemplateLiteral; + return createTemplateLiteralLikeNode( + kind, + text, + /*rawText*/ undefined, + /*templateFlags*/ 0, + ) as NoSubstitutionTemplateLiteral; } } @@ -1324,7 +1392,12 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode return node; } - function createBaseGeneratedIdentifier(text: string, autoGenerateFlags: GeneratedIdentifierFlags, prefix: string | GeneratedNamePart | undefined, suffix: string | undefined) { + function createBaseGeneratedIdentifier( + text: string, + autoGenerateFlags: GeneratedIdentifierFlags, + prefix: string | GeneratedNamePart | undefined, + suffix: string | undefined, + ) { const node = createBaseIdentifier(escapeLeadingUnderscores(text)) as Mutable; setIdentifierAutoGenerate(node, { flags: autoGenerateFlags, @@ -1337,7 +1410,11 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } // @api - function createIdentifier(text: string, originalKeywordKind?: SyntaxKind, hasExtendedUnicodeEscape?: boolean): Identifier { + function createIdentifier( + text: string, + originalKeywordKind?: SyntaxKind, + hasExtendedUnicodeEscape?: boolean, + ): Identifier { if (originalKeywordKind === undefined && text) { originalKeywordKind = stringToToken(text); } @@ -1360,7 +1437,12 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } // @api - function createTempVariable(recordTempVariable: ((node: Identifier) => void) | undefined, reservedInNestedScopes?: boolean, prefix?: string | GeneratedNamePart, suffix?: string): GeneratedIdentifier { + function createTempVariable( + recordTempVariable: ((node: Identifier) => void) | undefined, + reservedInNestedScopes?: boolean, + prefix?: string | GeneratedNamePart, + suffix?: string, + ): GeneratedIdentifier { let flags = GeneratedIdentifierFlags.Auto; if (reservedInNestedScopes) flags |= GeneratedIdentifierFlags.ReservedInNestedScopes; const name = createBaseGeneratedIdentifier("", flags, prefix, suffix); @@ -1380,19 +1462,33 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode /** Create a unique name based on the supplied text. */ // @api - function createUniqueName(text: string, flags: GeneratedIdentifierFlags = GeneratedIdentifierFlags.None, prefix?: string | GeneratedNamePart, suffix?: string): Identifier { + function createUniqueName( + text: string, + flags: GeneratedIdentifierFlags = GeneratedIdentifierFlags.None, + prefix?: string | GeneratedNamePart, + suffix?: string, + ): Identifier { Debug.assert(!(flags & GeneratedIdentifierFlags.KindMask), "Argument out of range: flags"); - Debug.assert((flags & (GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel)) !== GeneratedIdentifierFlags.FileLevel, "GeneratedIdentifierFlags.FileLevel cannot be set without also setting GeneratedIdentifierFlags.Optimistic"); + Debug.assert( + (flags & (GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel)) + !== GeneratedIdentifierFlags.FileLevel, + "GeneratedIdentifierFlags.FileLevel cannot be set without also setting GeneratedIdentifierFlags.Optimistic", + ); return createBaseGeneratedIdentifier(text, GeneratedIdentifierFlags.Unique | flags, prefix, suffix); } /** Create a unique name generated for a node. */ // @api - function getGeneratedNameForNode(node: Node | undefined, flags: GeneratedIdentifierFlags = 0, prefix?: string | GeneratedNamePart, suffix?: string): Identifier { + function getGeneratedNameForNode( + node: Node | undefined, + flags: GeneratedIdentifierFlags = 0, + prefix?: string | GeneratedNamePart, + suffix?: string, + ): Identifier { Debug.assert(!(flags & GeneratedIdentifierFlags.KindMask), "Argument out of range: flags"); - const text = !node ? "" : - isMemberName(node) ? formatGeneratedName(/*privateName*/ false, prefix, node, suffix, idText) : - `generated@${getNodeId(node)}`; + const text = !node ? "" + : isMemberName(node) ? formatGeneratedName(/*privateName*/ false, prefix, node, suffix, idText) + : `generated@${getNodeId(node)}`; if (prefix || suffix) flags |= GeneratedIdentifierFlags.Optimistic; const name = createBaseGeneratedIdentifier(text, GeneratedIdentifierFlags.Node | flags, prefix, suffix); name.original = node; @@ -1400,7 +1496,9 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } function createBasePrivateIdentifier(escapedText: __String) { - const node = baseFactory.createBasePrivateIdentifierNode(SyntaxKind.PrivateIdentifier) as Mutable; + const node = baseFactory.createBasePrivateIdentifierNode(SyntaxKind.PrivateIdentifier) as Mutable< + PrivateIdentifier + >; node.escapedText = escapedText; node.transformFlags |= TransformFlags.ContainsClassFields; return node; @@ -1412,7 +1510,12 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode return createBasePrivateIdentifier(escapeLeadingUnderscores(text)); } - function createBaseGeneratedPrivateIdentifier(text: string, autoGenerateFlags: GeneratedIdentifierFlags, prefix: string | GeneratedNamePart | undefined, suffix: string | undefined) { + function createBaseGeneratedPrivateIdentifier( + text: string, + autoGenerateFlags: GeneratedIdentifierFlags, + prefix: string | GeneratedNamePart | undefined, + suffix: string | undefined, + ) { const node = createBasePrivateIdentifier(escapeLeadingUnderscores(text)); setIdentifierAutoGenerate(node, { flags: autoGenerateFlags, @@ -1426,17 +1529,25 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode /** Create a unique name based on the supplied text. */ // @api - function createUniquePrivateName(text?: string, prefix?: string | GeneratedNamePart, suffix?: string): PrivateIdentifier { + function createUniquePrivateName( + text?: string, + prefix?: string | GeneratedNamePart, + suffix?: string, + ): PrivateIdentifier { if (text && !startsWith(text, "#")) Debug.fail("First character of private identifier must be #: " + text); - const autoGenerateFlags = GeneratedIdentifierFlags.ReservedInNestedScopes | - (text ? GeneratedIdentifierFlags.Unique : GeneratedIdentifierFlags.Auto); + const autoGenerateFlags = GeneratedIdentifierFlags.ReservedInNestedScopes + | (text ? GeneratedIdentifierFlags.Unique : GeneratedIdentifierFlags.Auto); return createBaseGeneratedPrivateIdentifier(text ?? "", autoGenerateFlags, prefix, suffix); } // @api - function getGeneratedPrivateNameForNode(node: Node, prefix?: string | GeneratedNamePart, suffix?: string): PrivateIdentifier { - const text = isMemberName(node) ? formatGeneratedName(/*privateName*/ true, prefix, node, suffix, idText) : - `#generated@${getNodeId(node)}`; + function getGeneratedPrivateNameForNode( + node: Node, + prefix?: string | GeneratedNamePart, + suffix?: string, + ): PrivateIdentifier { + const text = isMemberName(node) ? formatGeneratedName(/*privateName*/ true, prefix, node, suffix, idText) + : `#generated@${getNodeId(node)}`; const flags = prefix || suffix ? GeneratedIdentifierFlags.Optimistic : GeneratedIdentifierFlags.None; const name = createBaseGeneratedPrivateIdentifier(text, GeneratedIdentifierFlags.Node | flags, prefix, suffix); name.original = node; @@ -1466,16 +1577,22 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode function createToken(token: TKind): Token; function createToken(token: TKind) { Debug.assert(token >= SyntaxKind.FirstToken && token <= SyntaxKind.LastToken, "Invalid token"); - Debug.assert(token <= SyntaxKind.FirstTemplateToken || token >= SyntaxKind.LastTemplateToken, "Invalid token. Use 'createTemplateLiteralLikeNode' to create template literals."); - Debug.assert(token <= SyntaxKind.FirstLiteralToken || token >= SyntaxKind.LastLiteralToken, "Invalid token. Use 'createLiteralLikeNode' to create literals."); + Debug.assert( + token <= SyntaxKind.FirstTemplateToken || token >= SyntaxKind.LastTemplateToken, + "Invalid token. Use 'createTemplateLiteralLikeNode' to create template literals.", + ); + Debug.assert( + token <= SyntaxKind.FirstLiteralToken || token >= SyntaxKind.LastLiteralToken, + "Invalid token. Use 'createLiteralLikeNode' to create literals.", + ); Debug.assert(token !== SyntaxKind.Identifier, "Invalid token. Use 'createIdentifier' to create identifiers"); const node = createBaseToken>(token); let transformFlags = TransformFlags.None; switch (token) { case SyntaxKind.AsyncKeyword: // 'async' modifier is ES2017 (async functions) or ES2018 (async generators) - transformFlags = TransformFlags.ContainsES2017 | - TransformFlags.ContainsES2018; + transformFlags = TransformFlags.ContainsES2017 + | TransformFlags.ContainsES2018; break; case SyntaxKind.UsingKeyword: @@ -1595,8 +1712,8 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode const node = createBaseNode(SyntaxKind.QualifiedName); node.left = left; node.right = asName(right); - node.transformFlags |= propagateChildFlags(node.left) | - propagateIdentifierNameFlags(node.right); + node.transformFlags |= propagateChildFlags(node.left) + | propagateIdentifierNameFlags(node.right); node.flowNode = undefined; // initialized by binder (FlowContainer) return node; @@ -1614,9 +1731,9 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode function createComputedPropertyName(expression: Expression) { const node = createBaseNode(SyntaxKind.ComputedPropertyName); node.expression = parenthesizerRules().parenthesizeExpressionOfComputedPropertyName(expression); - node.transformFlags |= propagateChildFlags(node.expression) | - TransformFlags.ContainsES2015 | - TransformFlags.ContainsComputedPropertyName; + node.transformFlags |= propagateChildFlags(node.expression) + | TransformFlags.ContainsES2015 + | TransformFlags.ContainsComputedPropertyName; return node; } @@ -1632,7 +1749,12 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode // // @api - function createTypeParameterDeclaration(modifiers: readonly Modifier[] | undefined, name: string | Identifier, constraint?: TypeNode, defaultType?: TypeNode): TypeParameterDeclaration { + function createTypeParameterDeclaration( + modifiers: readonly Modifier[] | undefined, + name: string | Identifier, + constraint?: TypeNode, + defaultType?: TypeNode, + ): TypeParameterDeclaration { const node = createBaseDeclaration(SyntaxKind.TypeParameter); node.modifiers = asNodeArray(modifiers); node.name = asName(name); @@ -1646,7 +1768,13 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } // @api - function updateTypeParameterDeclaration(node: TypeParameterDeclaration, modifiers: readonly Modifier[] | undefined, name: Identifier, constraint: TypeNode | undefined, defaultType: TypeNode | undefined): TypeParameterDeclaration { + function updateTypeParameterDeclaration( + node: TypeParameterDeclaration, + modifiers: readonly Modifier[] | undefined, + name: Identifier, + constraint: TypeNode | undefined, + defaultType: TypeNode | undefined, + ): TypeParameterDeclaration { return node.modifiers !== modifiers || node.name !== name || node.constraint !== constraint @@ -1676,14 +1804,15 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode node.transformFlags = TransformFlags.ContainsTypeScript; } else { - node.transformFlags = propagateChildrenFlags(node.modifiers) | - propagateChildFlags(node.dotDotDotToken) | - propagateNameFlags(node.name) | - propagateChildFlags(node.questionToken) | - propagateChildFlags(node.initializer) | - (node.questionToken ?? node.type ? TransformFlags.ContainsTypeScript : TransformFlags.None) | - (node.dotDotDotToken ?? node.initializer ? TransformFlags.ContainsES2015 : TransformFlags.None) | - (modifiersToFlags(node.modifiers) & ModifierFlags.ParameterPropertyModifier ? TransformFlags.ContainsTypeScriptClassSyntax : TransformFlags.None); + node.transformFlags = propagateChildrenFlags(node.modifiers) + | propagateChildFlags(node.dotDotDotToken) + | propagateNameFlags(node.name) + | propagateChildFlags(node.questionToken) + | propagateChildFlags(node.initializer) + | (node.questionToken ?? node.type ? TransformFlags.ContainsTypeScript : TransformFlags.None) + | (node.dotDotDotToken ?? node.initializer ? TransformFlags.ContainsES2015 : TransformFlags.None) + | (modifiersToFlags(node.modifiers) & ModifierFlags.ParameterPropertyModifier + ? TransformFlags.ContainsTypeScriptClassSyntax : TransformFlags.None); } node.jsDoc = undefined; // initialized by parser (JsDocContainer) @@ -1706,7 +1835,10 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode || node.questionToken !== questionToken || node.type !== type || node.initializer !== initializer - ? update(createParameterDeclaration(modifiers, dotDotDotToken, name, questionToken, type, initializer), node) + ? update( + createParameterDeclaration(modifiers, dotDotDotToken, name, questionToken, type, initializer), + node, + ) : node; } @@ -1714,10 +1846,10 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode function createDecorator(expression: Expression) { const node = createBaseNode(SyntaxKind.Decorator); node.expression = parenthesizerRules().parenthesizeLeftSideOfAccess(expression, /*optionalChain*/ false); - node.transformFlags |= propagateChildFlags(node.expression) | - TransformFlags.ContainsTypeScript | - TransformFlags.ContainsTypeScriptClassSyntax | - TransformFlags.ContainsDecorators; + node.transformFlags |= propagateChildFlags(node.expression) + | TransformFlags.ContainsTypeScript + | TransformFlags.ContainsTypeScriptClassSyntax + | TransformFlags.ContainsDecorators; return node; } @@ -1786,19 +1918,24 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode const node = createBaseDeclaration(SyntaxKind.PropertyDeclaration); node.modifiers = asNodeArray(modifiers); node.name = asName(name); - node.questionToken = questionOrExclamationToken && isQuestionToken(questionOrExclamationToken) ? questionOrExclamationToken : undefined; - node.exclamationToken = questionOrExclamationToken && isExclamationToken(questionOrExclamationToken) ? questionOrExclamationToken : undefined; + node.questionToken = questionOrExclamationToken && isQuestionToken(questionOrExclamationToken) + ? questionOrExclamationToken : undefined; + node.exclamationToken = questionOrExclamationToken && isExclamationToken(questionOrExclamationToken) + ? questionOrExclamationToken : undefined; node.type = type; node.initializer = asInitializer(initializer); const isAmbient = node.flags & NodeFlags.Ambient || modifiersToFlags(node.modifiers) & ModifierFlags.Ambient; - node.transformFlags = propagateChildrenFlags(node.modifiers) | - propagateNameFlags(node.name) | - propagateChildFlags(node.initializer) | - (isAmbient || node.questionToken || node.exclamationToken || node.type ? TransformFlags.ContainsTypeScript : TransformFlags.None) | - (isComputedPropertyName(node.name) || modifiersToFlags(node.modifiers) & ModifierFlags.Static && node.initializer ? TransformFlags.ContainsTypeScriptClassSyntax : TransformFlags.None) | - TransformFlags.ContainsClassFields; + node.transformFlags = propagateChildrenFlags(node.modifiers) + | propagateNameFlags(node.name) + | propagateChildFlags(node.initializer) + | (isAmbient || node.questionToken || node.exclamationToken || node.type ? TransformFlags.ContainsTypeScript + : TransformFlags.None) + | (isComputedPropertyName(node.name) + || modifiersToFlags(node.modifiers) & ModifierFlags.Static && node.initializer + ? TransformFlags.ContainsTypeScriptClassSyntax : TransformFlags.None) + | TransformFlags.ContainsClassFields; node.jsDoc = undefined; // initialized by parser (JsDocContainer) return node; @@ -1815,8 +1952,12 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode ) { return node.modifiers !== modifiers || node.name !== name - || node.questionToken !== (questionOrExclamationToken !== undefined && isQuestionToken(questionOrExclamationToken) ? questionOrExclamationToken : undefined) - || node.exclamationToken !== (questionOrExclamationToken !== undefined && isExclamationToken(questionOrExclamationToken) ? questionOrExclamationToken : undefined) + || node.questionToken + !== (questionOrExclamationToken !== undefined && isQuestionToken(questionOrExclamationToken) + ? questionOrExclamationToken : undefined) + || node.exclamationToken + !== (questionOrExclamationToken !== undefined && isExclamationToken(questionOrExclamationToken) + ? questionOrExclamationToken : undefined) || node.type !== type || node.initializer !== initializer ? update(createPropertyDeclaration(modifiers, name, questionOrExclamationToken, type, initializer), node) @@ -1864,7 +2005,10 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode || node.typeParameters !== typeParameters || node.parameters !== parameters || node.type !== type - ? finishUpdateBaseSignatureDeclaration(createMethodSignature(modifiers, name, questionToken, typeParameters, parameters, type), node) + ? finishUpdateBaseSignatureDeclaration( + createMethodSignature(modifiers, name, questionToken, typeParameters, parameters, type), + node, + ) : node; } @@ -1898,20 +2042,21 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode const isGenerator = !!node.asteriskToken; const isAsyncGenerator = isAsync && isGenerator; - node.transformFlags = propagateChildrenFlags(node.modifiers) | - propagateChildFlags(node.asteriskToken) | - propagateNameFlags(node.name) | - propagateChildFlags(node.questionToken) | - propagateChildrenFlags(node.typeParameters) | - propagateChildrenFlags(node.parameters) | - propagateChildFlags(node.type) | - (propagateChildFlags(node.body) & ~TransformFlags.ContainsPossibleTopLevelAwait) | - (isAsyncGenerator ? TransformFlags.ContainsES2018 : - isAsync ? TransformFlags.ContainsES2017 : - isGenerator ? TransformFlags.ContainsGenerator : - TransformFlags.None) | - (node.questionToken || node.typeParameters || node.type ? TransformFlags.ContainsTypeScript : TransformFlags.None) | - TransformFlags.ContainsES2015; + node.transformFlags = propagateChildrenFlags(node.modifiers) + | propagateChildFlags(node.asteriskToken) + | propagateNameFlags(node.name) + | propagateChildFlags(node.questionToken) + | propagateChildrenFlags(node.typeParameters) + | propagateChildrenFlags(node.parameters) + | propagateChildFlags(node.type) + | (propagateChildFlags(node.body) & ~TransformFlags.ContainsPossibleTopLevelAwait) + | (isAsyncGenerator ? TransformFlags.ContainsES2018 + : isAsync ? TransformFlags.ContainsES2017 + : isGenerator ? TransformFlags.ContainsGenerator + : TransformFlags.None) + | (node.questionToken || node.typeParameters || node.type ? TransformFlags.ContainsTypeScript + : TransformFlags.None) + | TransformFlags.ContainsES2015; } node.typeArguments = undefined; // used in quick info @@ -1944,7 +2089,19 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode || node.parameters !== parameters || node.type !== type || node.body !== body - ? finishUpdateMethodDeclaration(createMethodDeclaration(modifiers, asteriskToken, name, questionToken, typeParameters, parameters, type, body), node) + ? finishUpdateMethodDeclaration( + createMethodDeclaration( + modifiers, + asteriskToken, + name, + questionToken, + typeParameters, + parameters, + type, + body, + ), + node, + ) : node; } @@ -1983,7 +2140,10 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode : node; } - function finishUpdateClassStaticBlockDeclaration(updated: Mutable, original: ClassStaticBlockDeclaration) { + function finishUpdateClassStaticBlockDeclaration( + updated: Mutable, + original: ClassStaticBlockDeclaration, + ) { if (updated !== original) { // copy children used only for error reporting updated.modifiers = original.modifiers; @@ -2002,10 +2162,10 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode node.parameters = createNodeArray(parameters); node.body = body; - node.transformFlags = propagateChildrenFlags(node.modifiers) | - propagateChildrenFlags(node.parameters) | - (propagateChildFlags(node.body) & ~TransformFlags.ContainsPossibleTopLevelAwait) | - TransformFlags.ContainsES2015; + node.transformFlags = propagateChildrenFlags(node.modifiers) + | propagateChildrenFlags(node.parameters) + | (propagateChildFlags(node.body) & ~TransformFlags.ContainsPossibleTopLevelAwait) + | TransformFlags.ContainsES2015; node.typeParameters = undefined; // initialized by parser for grammar errors node.type = undefined; // initialized by parser for grammar errors @@ -2032,7 +2192,10 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode : node; } - function finishUpdateConstructorDeclaration(updated: Mutable, original: ConstructorDeclaration) { + function finishUpdateConstructorDeclaration( + updated: Mutable, + original: ConstructorDeclaration, + ) { if (updated !== original) { updated.typeParameters = original.typeParameters; updated.type = original.type; @@ -2059,12 +2222,12 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode node.transformFlags = TransformFlags.ContainsTypeScript; } else { - node.transformFlags = propagateChildrenFlags(node.modifiers) | - propagateNameFlags(node.name) | - propagateChildrenFlags(node.parameters) | - propagateChildFlags(node.type) | - (propagateChildFlags(node.body) & ~TransformFlags.ContainsPossibleTopLevelAwait) | - (node.type ? TransformFlags.ContainsTypeScript : TransformFlags.None); + node.transformFlags = propagateChildrenFlags(node.modifiers) + | propagateNameFlags(node.name) + | propagateChildrenFlags(node.parameters) + | propagateChildFlags(node.type) + | (propagateChildFlags(node.body) & ~TransformFlags.ContainsPossibleTopLevelAwait) + | (node.type ? TransformFlags.ContainsTypeScript : TransformFlags.None); } node.typeArguments = undefined; // used in quick info @@ -2092,11 +2255,17 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode || node.parameters !== parameters || node.type !== type || node.body !== body - ? finishUpdateGetAccessorDeclaration(createGetAccessorDeclaration(modifiers, name, parameters, type, body), node) + ? finishUpdateGetAccessorDeclaration( + createGetAccessorDeclaration(modifiers, name, parameters, type, body), + node, + ) : node; } - function finishUpdateGetAccessorDeclaration(updated: Mutable, original: GetAccessorDeclaration) { + function finishUpdateGetAccessorDeclaration( + updated: Mutable, + original: GetAccessorDeclaration, + ) { if (updated !== original) { // copy children used only for error reporting updated.typeParameters = original.typeParameters; @@ -2121,11 +2290,11 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode node.transformFlags = TransformFlags.ContainsTypeScript; } else { - node.transformFlags = propagateChildrenFlags(node.modifiers) | - propagateNameFlags(node.name) | - propagateChildrenFlags(node.parameters) | - (propagateChildFlags(node.body) & ~TransformFlags.ContainsPossibleTopLevelAwait) | - (node.type ? TransformFlags.ContainsTypeScript : TransformFlags.None); + node.transformFlags = propagateChildrenFlags(node.modifiers) + | propagateNameFlags(node.name) + | propagateChildrenFlags(node.parameters) + | (propagateChildFlags(node.body) & ~TransformFlags.ContainsPossibleTopLevelAwait) + | (node.type ? TransformFlags.ContainsTypeScript : TransformFlags.None); } node.typeArguments = undefined; // used in quick info @@ -2156,7 +2325,10 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode : node; } - function finishUpdateSetAccessorDeclaration(updated: Mutable, original: SetAccessorDeclaration) { + function finishUpdateSetAccessorDeclaration( + updated: Mutable, + original: SetAccessorDeclaration, + ) { if (updated !== original) { // copy children used only for error reporting updated.typeParameters = original.typeParameters; @@ -2274,7 +2446,11 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } // @api - function updateTemplateLiteralTypeSpan(node: TemplateLiteralTypeSpan, type: TypeNode, literal: TemplateMiddle | TemplateTail) { + function updateTemplateLiteralTypeSpan( + node: TemplateLiteralTypeSpan, + type: TypeNode, + literal: TemplateMiddle | TemplateTail, + ) { return node.type !== type || node.literal !== literal ? update(createTemplateLiteralTypeSpan(type, literal), node) @@ -2291,7 +2467,11 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } // @api - function createTypePredicateNode(assertsModifier: AssertsKeyword | undefined, parameterName: Identifier | ThisTypeNode | string, type: TypeNode | undefined) { + function createTypePredicateNode( + assertsModifier: AssertsKeyword | undefined, + parameterName: Identifier | ThisTypeNode | string, + type: TypeNode | undefined, + ) { const node = createBaseNode(SyntaxKind.TypePredicate); node.assertsModifier = assertsModifier; node.parameterName = asName(parameterName); @@ -2301,7 +2481,12 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } // @api - function updateTypePredicateNode(node: TypePredicateNode, assertsModifier: AssertsKeyword | undefined, parameterName: Identifier | ThisTypeNode, type: TypeNode | undefined) { + function updateTypePredicateNode( + node: TypePredicateNode, + assertsModifier: AssertsKeyword | undefined, + parameterName: Identifier | ThisTypeNode, + type: TypeNode | undefined, + ) { return node.assertsModifier !== assertsModifier || node.parameterName !== parameterName || node.type !== type @@ -2313,13 +2498,18 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode function createTypeReferenceNode(typeName: string | EntityName, typeArguments: readonly TypeNode[] | undefined) { const node = createBaseNode(SyntaxKind.TypeReference); node.typeName = asName(typeName); - node.typeArguments = typeArguments && parenthesizerRules().parenthesizeTypeArguments(createNodeArray(typeArguments)); + node.typeArguments = typeArguments + && parenthesizerRules().parenthesizeTypeArguments(createNodeArray(typeArguments)); node.transformFlags = TransformFlags.ContainsTypeScript; return node; } // @api - function updateTypeReferenceNode(node: TypeReferenceNode, typeName: EntityName, typeArguments: NodeArray | undefined) { + function updateTypeReferenceNode( + node: TypeReferenceNode, + typeName: EntityName, + typeArguments: NodeArray | undefined, + ) { return node.typeName !== typeName || node.typeArguments !== typeArguments ? update(createTypeReferenceNode(typeName, typeArguments), node) @@ -2369,10 +2559,12 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } // @api - function createConstructorTypeNode(...args: Parameters) { - return args.length === 4 ? createConstructorTypeNode1(...args) : - args.length === 3 ? createConstructorTypeNode2(...args) : - Debug.fail("Incorrect number of arguments specified."); + function createConstructorTypeNode( + ...args: Parameters + ) { + return args.length === 4 ? createConstructorTypeNode1(...args) + : args.length === 3 ? createConstructorTypeNode2(...args) + : Debug.fail("Incorrect number of arguments specified."); } function createConstructorTypeNode1( @@ -2405,10 +2597,12 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } // @api - function updateConstructorTypeNode(...args: Parameters) { - return args.length === 5 ? updateConstructorTypeNode1(...args) : - args.length === 4 ? updateConstructorTypeNode2(...args) : - Debug.fail("Incorrect number of arguments specified."); + function updateConstructorTypeNode( + ...args: Parameters + ) { + return args.length === 5 ? updateConstructorTypeNode1(...args) + : args.length === 4 ? updateConstructorTypeNode2(...args) + : Debug.fail("Incorrect number of arguments specified."); } function updateConstructorTypeNode1( @@ -2422,7 +2616,10 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode || node.typeParameters !== typeParameters || node.parameters !== parameters || node.type !== type - ? finishUpdateBaseSignatureDeclaration(createConstructorTypeNode(modifiers, typeParameters, parameters, type), node) + ? finishUpdateBaseSignatureDeclaration( + createConstructorTypeNode(modifiers, typeParameters, parameters, type), + node, + ) : node; } @@ -2499,7 +2696,12 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } // @api - function createNamedTupleMember(dotDotDotToken: DotDotDotToken | undefined, name: Identifier, questionToken: QuestionToken | undefined, type: TypeNode) { + function createNamedTupleMember( + dotDotDotToken: DotDotDotToken | undefined, + name: Identifier, + questionToken: QuestionToken | undefined, + type: TypeNode, + ) { const node = createBaseDeclaration(SyntaxKind.NamedTupleMember); node.dotDotDotToken = dotDotDotToken; node.name = name; @@ -2512,7 +2714,13 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } // @api - function updateNamedTupleMember(node: NamedTupleMember, dotDotDotToken: DotDotDotToken | undefined, name: Identifier, questionToken: QuestionToken | undefined, type: TypeNode) { + function updateNamedTupleMember( + node: NamedTupleMember, + dotDotDotToken: DotDotDotToken | undefined, + name: Identifier, + questionToken: QuestionToken | undefined, + type: TypeNode, + ) { return node.dotDotDotToken !== dotDotDotToken || node.name !== name || node.questionToken !== questionToken @@ -2551,14 +2759,22 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode : node; } - function createUnionOrIntersectionTypeNode(kind: SyntaxKind.UnionType | SyntaxKind.IntersectionType, types: readonly TypeNode[], parenthesize: (nodes: readonly TypeNode[]) => readonly TypeNode[]) { + function createUnionOrIntersectionTypeNode( + kind: SyntaxKind.UnionType | SyntaxKind.IntersectionType, + types: readonly TypeNode[], + parenthesize: (nodes: readonly TypeNode[]) => readonly TypeNode[], + ) { const node = createBaseNode(kind); node.types = factory.createNodeArray(parenthesize(types)); node.transformFlags = TransformFlags.ContainsTypeScript; return node; } - function updateUnionOrIntersectionTypeNode(node: T, types: NodeArray, parenthesize: (nodes: readonly TypeNode[]) => readonly TypeNode[]): T { + function updateUnionOrIntersectionTypeNode( + node: T, + types: NodeArray, + parenthesize: (nodes: readonly TypeNode[]) => readonly TypeNode[], + ): T { return node.types !== types ? update(createUnionOrIntersectionTypeNode(node.kind, types, parenthesize) as T, node) : node; @@ -2566,26 +2782,47 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode // @api function createUnionTypeNode(types: readonly TypeNode[]): UnionTypeNode { - return createUnionOrIntersectionTypeNode(SyntaxKind.UnionType, types, parenthesizerRules().parenthesizeConstituentTypesOfUnionType) as UnionTypeNode; + return createUnionOrIntersectionTypeNode( + SyntaxKind.UnionType, + types, + parenthesizerRules().parenthesizeConstituentTypesOfUnionType, + ) as UnionTypeNode; } // @api function updateUnionTypeNode(node: UnionTypeNode, types: NodeArray) { - return updateUnionOrIntersectionTypeNode(node, types, parenthesizerRules().parenthesizeConstituentTypesOfUnionType); + return updateUnionOrIntersectionTypeNode( + node, + types, + parenthesizerRules().parenthesizeConstituentTypesOfUnionType, + ); } // @api function createIntersectionTypeNode(types: readonly TypeNode[]): IntersectionTypeNode { - return createUnionOrIntersectionTypeNode(SyntaxKind.IntersectionType, types, parenthesizerRules().parenthesizeConstituentTypesOfIntersectionType) as IntersectionTypeNode; + return createUnionOrIntersectionTypeNode( + SyntaxKind.IntersectionType, + types, + parenthesizerRules().parenthesizeConstituentTypesOfIntersectionType, + ) as IntersectionTypeNode; } // @api function updateIntersectionTypeNode(node: IntersectionTypeNode, types: NodeArray) { - return updateUnionOrIntersectionTypeNode(node, types, parenthesizerRules().parenthesizeConstituentTypesOfIntersectionType); + return updateUnionOrIntersectionTypeNode( + node, + types, + parenthesizerRules().parenthesizeConstituentTypesOfIntersectionType, + ); } // @api - function createConditionalTypeNode(checkType: TypeNode, extendsType: TypeNode, trueType: TypeNode, falseType: TypeNode) { + function createConditionalTypeNode( + checkType: TypeNode, + extendsType: TypeNode, + trueType: TypeNode, + falseType: TypeNode, + ) { const node = createBaseNode(SyntaxKind.ConditionalType); node.checkType = parenthesizerRules().parenthesizeCheckTypeOfConditionalType(checkType); node.extendsType = parenthesizerRules().parenthesizeExtendsTypeOfConditionalType(extendsType); @@ -2599,7 +2836,13 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } // @api - function updateConditionalTypeNode(node: ConditionalTypeNode, checkType: TypeNode, extendsType: TypeNode, trueType: TypeNode, falseType: TypeNode) { + function updateConditionalTypeNode( + node: ConditionalTypeNode, + checkType: TypeNode, + extendsType: TypeNode, + trueType: TypeNode, + falseType: TypeNode, + ) { return node.checkType !== checkType || node.extendsType !== extendsType || node.trueType !== trueType @@ -2633,7 +2876,11 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } // @api - function updateTemplateLiteralType(node: TemplateLiteralTypeNode, head: TemplateHead, templateSpans: readonly TemplateLiteralTypeSpan[]) { + function updateTemplateLiteralType( + node: TemplateLiteralTypeNode, + head: TemplateHead, + templateSpans: readonly TemplateLiteralTypeSpan[], + ) { return node.head !== head || node.templateSpans !== templateSpans ? update(createTemplateLiteralType(head, templateSpans), node) @@ -2699,12 +2946,15 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } // @api - function createTypeOperatorNode(operator: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.ReadonlyKeyword, type: TypeNode): TypeOperatorNode { + function createTypeOperatorNode( + operator: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.ReadonlyKeyword, + type: TypeNode, + ): TypeOperatorNode { const node = createBaseNode(SyntaxKind.TypeOperator); node.operator = operator; - node.type = operator === SyntaxKind.ReadonlyKeyword ? - parenthesizerRules().parenthesizeOperandOfReadonlyTypeOperator(type) : - parenthesizerRules().parenthesizeOperandOfTypeOperator(type); + node.type = operator === SyntaxKind.ReadonlyKeyword + ? parenthesizerRules().parenthesizeOperandOfReadonlyTypeOperator(type) + : parenthesizerRules().parenthesizeOperandOfTypeOperator(type); node.transformFlags = TransformFlags.ContainsTypeScript; return node; } @@ -2734,7 +2984,14 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } // @api - function createMappedTypeNode(readonlyToken: ReadonlyKeyword | PlusToken | MinusToken | undefined, typeParameter: TypeParameterDeclaration, nameType: TypeNode | undefined, questionToken: QuestionToken | PlusToken | MinusToken | undefined, type: TypeNode | undefined, members: readonly TypeElement[] | undefined): MappedTypeNode { + function createMappedTypeNode( + readonlyToken: ReadonlyKeyword | PlusToken | MinusToken | undefined, + typeParameter: TypeParameterDeclaration, + nameType: TypeNode | undefined, + questionToken: QuestionToken | PlusToken | MinusToken | undefined, + type: TypeNode | undefined, + members: readonly TypeElement[] | undefined, + ): MappedTypeNode { const node = createBaseDeclaration(SyntaxKind.MappedType); node.readonlyToken = readonlyToken; node.typeParameter = typeParameter; @@ -2750,7 +3007,15 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } // @api - function updateMappedTypeNode(node: MappedTypeNode, readonlyToken: ReadonlyKeyword | PlusToken | MinusToken | undefined, typeParameter: TypeParameterDeclaration, nameType: TypeNode | undefined, questionToken: QuestionToken | PlusToken | MinusToken | undefined, type: TypeNode | undefined, members: readonly TypeElement[] | undefined): MappedTypeNode { + function updateMappedTypeNode( + node: MappedTypeNode, + readonlyToken: ReadonlyKeyword | PlusToken | MinusToken | undefined, + typeParameter: TypeParameterDeclaration, + nameType: TypeNode | undefined, + questionToken: QuestionToken | PlusToken | MinusToken | undefined, + type: TypeNode | undefined, + members: readonly TypeElement[] | undefined, + ): MappedTypeNode { return node.readonlyToken !== readonlyToken || node.typeParameter !== typeParameter || node.nameType !== nameType @@ -2784,12 +3049,12 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode function createObjectBindingPattern(elements: readonly BindingElement[]) { const node = createBaseNode(SyntaxKind.ObjectBindingPattern); node.elements = createNodeArray(elements); - node.transformFlags |= propagateChildrenFlags(node.elements) | - TransformFlags.ContainsES2015 | - TransformFlags.ContainsBindingPattern; + node.transformFlags |= propagateChildrenFlags(node.elements) + | TransformFlags.ContainsES2015 + | TransformFlags.ContainsBindingPattern; if (node.transformFlags & TransformFlags.ContainsRestOrSpread) { - node.transformFlags |= TransformFlags.ContainsES2018 | - TransformFlags.ContainsObjectRestOrSpread; + node.transformFlags |= TransformFlags.ContainsES2018 + | TransformFlags.ContainsObjectRestOrSpread; } return node; } @@ -2805,9 +3070,9 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode function createArrayBindingPattern(elements: readonly ArrayBindingElement[]) { const node = createBaseNode(SyntaxKind.ArrayBindingPattern); node.elements = createNodeArray(elements); - node.transformFlags |= propagateChildrenFlags(node.elements) | - TransformFlags.ContainsES2015 | - TransformFlags.ContainsBindingPattern; + node.transformFlags |= propagateChildrenFlags(node.elements) + | TransformFlags.ContainsES2015 + | TransformFlags.ContainsBindingPattern; return node; } @@ -2819,25 +3084,36 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } // @api - function createBindingElement(dotDotDotToken: DotDotDotToken | undefined, propertyName: string | PropertyName | undefined, name: string | BindingName, initializer?: Expression) { + function createBindingElement( + dotDotDotToken: DotDotDotToken | undefined, + propertyName: string | PropertyName | undefined, + name: string | BindingName, + initializer?: Expression, + ) { const node = createBaseDeclaration(SyntaxKind.BindingElement); node.dotDotDotToken = dotDotDotToken; node.propertyName = asName(propertyName); node.name = asName(name); node.initializer = asInitializer(initializer); - node.transformFlags |= propagateChildFlags(node.dotDotDotToken) | - propagateNameFlags(node.propertyName) | - propagateNameFlags(node.name) | - propagateChildFlags(node.initializer) | - (node.dotDotDotToken ? TransformFlags.ContainsRestOrSpread : TransformFlags.None) | - TransformFlags.ContainsES2015; + node.transformFlags |= propagateChildFlags(node.dotDotDotToken) + | propagateNameFlags(node.propertyName) + | propagateNameFlags(node.name) + | propagateChildFlags(node.initializer) + | (node.dotDotDotToken ? TransformFlags.ContainsRestOrSpread : TransformFlags.None) + | TransformFlags.ContainsES2015; node.flowNode = undefined; // initialized by binder (FlowContainer) return node; } // @api - function updateBindingElement(node: BindingElement, dotDotDotToken: DotDotDotToken | undefined, propertyName: PropertyName | undefined, name: BindingName, initializer: Expression | undefined) { + function updateBindingElement( + node: BindingElement, + dotDotDotToken: DotDotDotToken | undefined, + propertyName: PropertyName | undefined, + name: BindingName, + initializer: Expression | undefined, + ) { return node.propertyName !== propertyName || node.dotDotDotToken !== dotDotDotToken || node.name !== name @@ -2857,7 +3133,10 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode // we end up with `[1, 2, ,]` instead of `[1, 2, ]` otherwise the `OmittedExpression` will just end up being treated like // a trailing comma. const lastElement = elements && lastOrUndefined(elements); - const elementsArray = createNodeArray(elements, lastElement && isOmittedExpression(lastElement) ? true : undefined); + const elementsArray = createNodeArray( + elements, + lastElement && isOmittedExpression(lastElement) ? true : undefined, + ); node.elements = parenthesizerRules().parenthesizeExpressionsOfCommaDelimitedList(elementsArray); node.multiLine = multiLine; node.transformFlags |= propagateChildrenFlags(node.elements); @@ -2883,22 +3162,29 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } // @api - function updateObjectLiteralExpression(node: ObjectLiteralExpression, properties: readonly ObjectLiteralElementLike[]) { + function updateObjectLiteralExpression( + node: ObjectLiteralExpression, + properties: readonly ObjectLiteralElementLike[], + ) { return node.properties !== properties ? update(createObjectLiteralExpression(properties, node.multiLine), node) : node; } - function createBasePropertyAccessExpression(expression: LeftHandSideExpression, questionDotToken: QuestionDotToken | undefined, name: MemberName) { + function createBasePropertyAccessExpression( + expression: LeftHandSideExpression, + questionDotToken: QuestionDotToken | undefined, + name: MemberName, + ) { const node = createBaseDeclaration(SyntaxKind.PropertyAccessExpression); node.expression = expression; node.questionDotToken = questionDotToken; node.name = name; - node.transformFlags = propagateChildFlags(node.expression) | - propagateChildFlags(node.questionDotToken) | - (isIdentifier(node.name) ? - propagateIdentifierNameFlags(node.name) : - propagateChildFlags(node.name) | TransformFlags.ContainsPrivateIdentifierInExpression); + node.transformFlags = propagateChildFlags(node.expression) + | propagateChildFlags(node.questionDotToken) + | (isIdentifier(node.name) + ? propagateIdentifierNameFlags(node.name) + : propagateChildFlags(node.name) | TransformFlags.ContainsPrivateIdentifierInExpression); node.jsDoc = undefined; // initialized by parser (JsDocContainer) node.flowNode = undefined; // initialized by binder (FlowContainer) @@ -2915,14 +3201,18 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode if (isSuperKeyword(expression)) { // super method calls require a lexical 'this' // super method calls require 'super' hoisting in ES2017 and ES2018 async functions and async generators - node.transformFlags |= TransformFlags.ContainsES2017 | - TransformFlags.ContainsES2018; + node.transformFlags |= TransformFlags.ContainsES2017 + | TransformFlags.ContainsES2018; } return node; } // @api - function updatePropertyAccessExpression(node: PropertyAccessExpression, expression: Expression, name: Identifier | PrivateIdentifier) { + function updatePropertyAccessExpression( + node: PropertyAccessExpression, + expression: Expression, + name: Identifier | PrivateIdentifier, + ) { if (isPropertyAccessChain(node)) { return updatePropertyAccessChain(node, expression, node.questionDotToken, cast(name, isIdentifier)); } @@ -2933,7 +3223,11 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } // @api - function createPropertyAccessChain(expression: Expression, questionDotToken: QuestionDotToken | undefined, name: string | Identifier | PrivateIdentifier) { + function createPropertyAccessChain( + expression: Expression, + questionDotToken: QuestionDotToken | undefined, + name: string | Identifier | PrivateIdentifier, + ) { const node = createBasePropertyAccessExpression( parenthesizerRules().parenthesizeLeftSideOfAccess(expression, /*optionalChain*/ true), questionDotToken, @@ -2945,8 +3239,16 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } // @api - function updatePropertyAccessChain(node: PropertyAccessChain, expression: Expression, questionDotToken: QuestionDotToken | undefined, name: Identifier | PrivateIdentifier) { - Debug.assert(!!(node.flags & NodeFlags.OptionalChain), "Cannot update a PropertyAccessExpression using updatePropertyAccessChain. Use updatePropertyAccess instead."); + function updatePropertyAccessChain( + node: PropertyAccessChain, + expression: Expression, + questionDotToken: QuestionDotToken | undefined, + name: Identifier | PrivateIdentifier, + ) { + Debug.assert( + !!(node.flags & NodeFlags.OptionalChain), + "Cannot update a PropertyAccessExpression using updatePropertyAccessChain. Use updatePropertyAccess instead.", + ); // Because we are updating an existing PropertyAccessChain we want to inherit its emitFlags // instead of using the default from createPropertyAccess return node.expression !== expression @@ -2956,14 +3258,18 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode : node; } - function createBaseElementAccessExpression(expression: LeftHandSideExpression, questionDotToken: QuestionDotToken | undefined, argumentExpression: Expression) { + function createBaseElementAccessExpression( + expression: LeftHandSideExpression, + questionDotToken: QuestionDotToken | undefined, + argumentExpression: Expression, + ) { const node = createBaseDeclaration(SyntaxKind.ElementAccessExpression); node.expression = expression; node.questionDotToken = questionDotToken; node.argumentExpression = argumentExpression; - node.transformFlags |= propagateChildFlags(node.expression) | - propagateChildFlags(node.questionDotToken) | - propagateChildFlags(node.argumentExpression); + node.transformFlags |= propagateChildFlags(node.expression) + | propagateChildFlags(node.questionDotToken) + | propagateChildFlags(node.argumentExpression); node.jsDoc = undefined; // initialized by parser (JsDocContainer) node.flowNode = undefined; // initialized by binder (FlowContainer) @@ -2980,14 +3286,18 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode if (isSuperKeyword(expression)) { // super method calls require a lexical 'this' // super method calls require 'super' hoisting in ES2017 and ES2018 async functions and async generators - node.transformFlags |= TransformFlags.ContainsES2017 | - TransformFlags.ContainsES2018; + node.transformFlags |= TransformFlags.ContainsES2017 + | TransformFlags.ContainsES2018; } return node; } // @api - function updateElementAccessExpression(node: ElementAccessExpression, expression: Expression, argumentExpression: Expression) { + function updateElementAccessExpression( + node: ElementAccessExpression, + expression: Expression, + argumentExpression: Expression, + ) { if (isElementAccessChain(node)) { return updateElementAccessChain(node, expression, node.questionDotToken, argumentExpression); } @@ -2998,7 +3308,11 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } // @api - function createElementAccessChain(expression: Expression, questionDotToken: QuestionDotToken | undefined, index: number | Expression) { + function createElementAccessChain( + expression: Expression, + questionDotToken: QuestionDotToken | undefined, + index: number | Expression, + ) { const node = createBaseElementAccessExpression( parenthesizerRules().parenthesizeLeftSideOfAccess(expression, /*optionalChain*/ true), questionDotToken, @@ -3010,8 +3324,16 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } // @api - function updateElementAccessChain(node: ElementAccessChain, expression: Expression, questionDotToken: QuestionDotToken | undefined, argumentExpression: Expression) { - Debug.assert(!!(node.flags & NodeFlags.OptionalChain), "Cannot update a ElementAccessExpression using updateElementAccessChain. Use updateElementAccess instead."); + function updateElementAccessChain( + node: ElementAccessChain, + expression: Expression, + questionDotToken: QuestionDotToken | undefined, + argumentExpression: Expression, + ) { + Debug.assert( + !!(node.flags & NodeFlags.OptionalChain), + "Cannot update a ElementAccessExpression using updateElementAccessChain. Use updateElementAccess instead.", + ); // Because we are updating an existing ElementAccessChain we want to inherit its emitFlags // instead of using the default from createElementAccess return node.expression !== expression @@ -3021,16 +3343,21 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode : node; } - function createBaseCallExpression(expression: LeftHandSideExpression, questionDotToken: QuestionDotToken | undefined, typeArguments: NodeArray | undefined, argumentsArray: NodeArray) { + function createBaseCallExpression( + expression: LeftHandSideExpression, + questionDotToken: QuestionDotToken | undefined, + typeArguments: NodeArray | undefined, + argumentsArray: NodeArray, + ) { const node = createBaseDeclaration(SyntaxKind.CallExpression); node.expression = expression; node.questionDotToken = questionDotToken; node.typeArguments = typeArguments; node.arguments = argumentsArray; - node.transformFlags |= propagateChildFlags(node.expression) | - propagateChildFlags(node.questionDotToken) | - propagateChildrenFlags(node.typeArguments) | - propagateChildrenFlags(node.arguments); + node.transformFlags |= propagateChildFlags(node.expression) + | propagateChildFlags(node.questionDotToken) + | propagateChildrenFlags(node.typeArguments) + | propagateChildrenFlags(node.arguments); if (node.typeArguments) { node.transformFlags |= TransformFlags.ContainsTypeScript; } @@ -3041,7 +3368,11 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } // @api - function createCallExpression(expression: Expression, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[] | undefined) { + function createCallExpression( + expression: Expression, + typeArguments: readonly TypeNode[] | undefined, + argumentsArray: readonly Expression[] | undefined, + ) { const node = createBaseCallExpression( parenthesizerRules().parenthesizeLeftSideOfAccess(expression, /*optionalChain*/ false), /*questionDotToken*/ undefined, @@ -3055,7 +3386,12 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } // @api - function updateCallExpression(node: CallExpression, expression: Expression, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[]) { + function updateCallExpression( + node: CallExpression, + expression: Expression, + typeArguments: readonly TypeNode[] | undefined, + argumentsArray: readonly Expression[], + ) { if (isCallChain(node)) { return updateCallChain(node, expression, node.questionDotToken, typeArguments, argumentsArray); } @@ -3067,7 +3403,12 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } // @api - function createCallChain(expression: Expression, questionDotToken: QuestionDotToken | undefined, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[] | undefined) { + function createCallChain( + expression: Expression, + questionDotToken: QuestionDotToken | undefined, + typeArguments: readonly TypeNode[] | undefined, + argumentsArray: readonly Expression[] | undefined, + ) { const node = createBaseCallExpression( parenthesizerRules().parenthesizeLeftSideOfAccess(expression, /*optionalChain*/ true), questionDotToken, @@ -3080,8 +3421,17 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } // @api - function updateCallChain(node: CallChain, expression: Expression, questionDotToken: QuestionDotToken | undefined, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[]) { - Debug.assert(!!(node.flags & NodeFlags.OptionalChain), "Cannot update a CallExpression using updateCallChain. Use updateCall instead."); + function updateCallChain( + node: CallChain, + expression: Expression, + questionDotToken: QuestionDotToken | undefined, + typeArguments: readonly TypeNode[] | undefined, + argumentsArray: readonly Expression[], + ) { + Debug.assert( + !!(node.flags & NodeFlags.OptionalChain), + "Cannot update a CallExpression using updateCallChain. Use updateCall instead.", + ); return node.expression !== expression || node.questionDotToken !== questionDotToken || node.typeArguments !== typeArguments @@ -3091,15 +3441,20 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } // @api - function createNewExpression(expression: Expression, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[] | undefined) { + function createNewExpression( + expression: Expression, + typeArguments: readonly TypeNode[] | undefined, + argumentsArray: readonly Expression[] | undefined, + ) { const node = createBaseDeclaration(SyntaxKind.NewExpression); node.expression = parenthesizerRules().parenthesizeExpressionOfNew(expression); node.typeArguments = asNodeArray(typeArguments); - node.arguments = argumentsArray ? parenthesizerRules().parenthesizeExpressionsOfCommaDelimitedList(argumentsArray) : undefined; - node.transformFlags |= propagateChildFlags(node.expression) | - propagateChildrenFlags(node.typeArguments) | - propagateChildrenFlags(node.arguments) | - TransformFlags.ContainsES2020; + node.arguments = argumentsArray + ? parenthesizerRules().parenthesizeExpressionsOfCommaDelimitedList(argumentsArray) : undefined; + node.transformFlags |= propagateChildFlags(node.expression) + | propagateChildrenFlags(node.typeArguments) + | propagateChildrenFlags(node.arguments) + | TransformFlags.ContainsES2020; if (node.typeArguments) { node.transformFlags |= TransformFlags.ContainsTypeScript; } @@ -3107,7 +3462,12 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } // @api - function updateNewExpression(node: NewExpression, expression: Expression, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[] | undefined) { + function updateNewExpression( + node: NewExpression, + expression: Expression, + typeArguments: readonly TypeNode[] | undefined, + argumentsArray: readonly Expression[] | undefined, + ) { return node.expression !== expression || node.typeArguments !== typeArguments || node.arguments !== argumentsArray @@ -3116,15 +3476,19 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } // @api - function createTaggedTemplateExpression(tag: Expression, typeArguments: readonly TypeNode[] | undefined, template: TemplateLiteral) { + function createTaggedTemplateExpression( + tag: Expression, + typeArguments: readonly TypeNode[] | undefined, + template: TemplateLiteral, + ) { const node = createBaseNode(SyntaxKind.TaggedTemplateExpression); node.tag = parenthesizerRules().parenthesizeLeftSideOfAccess(tag, /*optionalChain*/ false); node.typeArguments = asNodeArray(typeArguments); node.template = template; - node.transformFlags |= propagateChildFlags(node.tag) | - propagateChildrenFlags(node.typeArguments) | - propagateChildFlags(node.template) | - TransformFlags.ContainsES2015; + node.transformFlags |= propagateChildFlags(node.tag) + | propagateChildrenFlags(node.typeArguments) + | propagateChildFlags(node.template) + | TransformFlags.ContainsES2015; if (node.typeArguments) { node.transformFlags |= TransformFlags.ContainsTypeScript; } @@ -3135,7 +3499,12 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } // @api - function updateTaggedTemplateExpression(node: TaggedTemplateExpression, tag: Expression, typeArguments: readonly TypeNode[] | undefined, template: TemplateLiteral) { + function updateTaggedTemplateExpression( + node: TaggedTemplateExpression, + tag: Expression, + typeArguments: readonly TypeNode[] | undefined, + template: TemplateLiteral, + ) { return node.tag !== tag || node.typeArguments !== typeArguments || node.template !== template @@ -3148,9 +3517,9 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode const node = createBaseNode(SyntaxKind.TypeAssertionExpression); node.expression = parenthesizerRules().parenthesizeOperandOfPrefixUnary(expression); node.type = type; - node.transformFlags |= propagateChildFlags(node.expression) | - propagateChildFlags(node.type) | - TransformFlags.ContainsTypeScript; + node.transformFlags |= propagateChildFlags(node.expression) + | propagateChildFlags(node.type) + | TransformFlags.ContainsTypeScript; return node; } @@ -3202,19 +3571,19 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode const isGenerator = !!node.asteriskToken; const isAsyncGenerator = isAsync && isGenerator; - node.transformFlags = propagateChildrenFlags(node.modifiers) | - propagateChildFlags(node.asteriskToken) | - propagateNameFlags(node.name) | - propagateChildrenFlags(node.typeParameters) | - propagateChildrenFlags(node.parameters) | - propagateChildFlags(node.type) | - (propagateChildFlags(node.body) & ~TransformFlags.ContainsPossibleTopLevelAwait) | - (isAsyncGenerator ? TransformFlags.ContainsES2018 : - isAsync ? TransformFlags.ContainsES2017 : - isGenerator ? TransformFlags.ContainsGenerator : - TransformFlags.None) | - (node.typeParameters || node.type ? TransformFlags.ContainsTypeScript : TransformFlags.None) | - TransformFlags.ContainsHoistedDeclarationOrCompletion; + node.transformFlags = propagateChildrenFlags(node.modifiers) + | propagateChildFlags(node.asteriskToken) + | propagateNameFlags(node.name) + | propagateChildrenFlags(node.typeParameters) + | propagateChildrenFlags(node.parameters) + | propagateChildFlags(node.type) + | (propagateChildFlags(node.body) & ~TransformFlags.ContainsPossibleTopLevelAwait) + | (isAsyncGenerator ? TransformFlags.ContainsES2018 + : isAsync ? TransformFlags.ContainsES2017 + : isGenerator ? TransformFlags.ContainsGenerator + : TransformFlags.None) + | (node.typeParameters || node.type ? TransformFlags.ContainsTypeScript : TransformFlags.None) + | TransformFlags.ContainsHoistedDeclarationOrCompletion; node.typeArguments = undefined; // used in quick info node.jsDoc = undefined; // initialized by parser (JsDocContainer) @@ -3244,7 +3613,10 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode || node.parameters !== parameters || node.type !== type || node.body !== body - ? finishUpdateBaseSignatureDeclaration(createFunctionExpression(modifiers, asteriskToken, name, typeParameters, parameters, type, body), node) + ? finishUpdateBaseSignatureDeclaration( + createFunctionExpression(modifiers, asteriskToken, name, typeParameters, parameters, type, body), + node, + ) : node; } @@ -3267,15 +3639,15 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode const isAsync = modifiersToFlags(node.modifiers) & ModifierFlags.Async; - node.transformFlags = propagateChildrenFlags(node.modifiers) | - propagateChildrenFlags(node.typeParameters) | - propagateChildrenFlags(node.parameters) | - propagateChildFlags(node.type) | - propagateChildFlags(node.equalsGreaterThanToken) | - (propagateChildFlags(node.body) & ~TransformFlags.ContainsPossibleTopLevelAwait) | - (node.typeParameters || node.type ? TransformFlags.ContainsTypeScript : TransformFlags.None) | - (isAsync ? TransformFlags.ContainsES2017 | TransformFlags.ContainsLexicalThis : TransformFlags.None) | - TransformFlags.ContainsES2015; + node.transformFlags = propagateChildrenFlags(node.modifiers) + | propagateChildrenFlags(node.typeParameters) + | propagateChildrenFlags(node.parameters) + | propagateChildFlags(node.type) + | propagateChildFlags(node.equalsGreaterThanToken) + | (propagateChildFlags(node.body) & ~TransformFlags.ContainsPossibleTopLevelAwait) + | (node.typeParameters || node.type ? TransformFlags.ContainsTypeScript : TransformFlags.None) + | (isAsync ? TransformFlags.ContainsES2017 | TransformFlags.ContainsLexicalThis : TransformFlags.None) + | TransformFlags.ContainsES2015; node.typeArguments = undefined; // used in quick info node.jsDoc = undefined; // initialized by parser (JsDocContainer) @@ -3303,7 +3675,10 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode || node.type !== type || node.equalsGreaterThanToken !== equalsGreaterThanToken || node.body !== body - ? finishUpdateBaseSignatureDeclaration(createArrowFunction(modifiers, typeParameters, parameters, type, equalsGreaterThanToken, body), node) + ? finishUpdateBaseSignatureDeclaration( + createArrowFunction(modifiers, typeParameters, parameters, type, equalsGreaterThanToken, body), + node, + ) : node; } @@ -3356,10 +3731,10 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode function createAwaitExpression(expression: Expression) { const node = createBaseNode(SyntaxKind.AwaitExpression); node.expression = parenthesizerRules().parenthesizeOperandOfPrefixUnary(expression); - node.transformFlags |= propagateChildFlags(node.expression) | - TransformFlags.ContainsES2017 | - TransformFlags.ContainsES2018 | - TransformFlags.ContainsAwait; + node.transformFlags |= propagateChildFlags(node.expression) + | TransformFlags.ContainsES2017 + | TransformFlags.ContainsES2018 + | TransformFlags.ContainsAwait; return node; } @@ -3379,10 +3754,10 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode // Only set this flag for non-generated identifiers and non-"local" names. See the // comment in `visitPreOrPostfixUnaryExpression` in module.ts if ( - (operator === SyntaxKind.PlusPlusToken || operator === SyntaxKind.MinusMinusToken) && - isIdentifier(node.operand) && - !isGeneratedIdentifier(node.operand) && - !isLocalName(node.operand) + (operator === SyntaxKind.PlusPlusToken || operator === SyntaxKind.MinusMinusToken) + && isIdentifier(node.operand) + && !isGeneratedIdentifier(node.operand) + && !isLocalName(node.operand) ) { node.transformFlags |= TransformFlags.ContainsUpdateExpressionForIdentifier; } @@ -3405,9 +3780,9 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode // Only set this flag for non-generated identifiers and non-"local" names. See the // comment in `visitPreOrPostfixUnaryExpression` in module.ts if ( - isIdentifier(node.operand) && - !isGeneratedIdentifier(node.operand) && - !isLocalName(node.operand) + isIdentifier(node.operand) + && !isGeneratedIdentifier(node.operand) + && !isLocalName(node.operand) ) { node.transformFlags |= TransformFlags.ContainsUpdateExpressionForIdentifier; } @@ -3422,33 +3797,39 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } // @api - function createBinaryExpression(left: Expression, operator: BinaryOperator | BinaryOperatorToken, right: Expression) { + function createBinaryExpression( + left: Expression, + operator: BinaryOperator | BinaryOperatorToken, + right: Expression, + ) { const node = createBaseDeclaration(SyntaxKind.BinaryExpression); const operatorToken = asToken(operator); const operatorKind = operatorToken.kind; node.left = parenthesizerRules().parenthesizeLeftSideOfBinary(operatorKind, left); node.operatorToken = operatorToken; node.right = parenthesizerRules().parenthesizeRightSideOfBinary(operatorKind, node.left, right); - node.transformFlags |= propagateChildFlags(node.left) | - propagateChildFlags(node.operatorToken) | - propagateChildFlags(node.right); + node.transformFlags |= propagateChildFlags(node.left) + | propagateChildFlags(node.operatorToken) + | propagateChildFlags(node.right); if (operatorKind === SyntaxKind.QuestionQuestionToken) { node.transformFlags |= TransformFlags.ContainsES2020; } else if (operatorKind === SyntaxKind.EqualsToken) { if (isObjectLiteralExpression(node.left)) { - node.transformFlags |= TransformFlags.ContainsES2015 | - TransformFlags.ContainsES2018 | - TransformFlags.ContainsDestructuringAssignment | - propagateAssignmentPatternFlags(node.left); + node.transformFlags |= TransformFlags.ContainsES2015 + | TransformFlags.ContainsES2018 + | TransformFlags.ContainsDestructuringAssignment + | propagateAssignmentPatternFlags(node.left); } else if (isArrayLiteralExpression(node.left)) { - node.transformFlags |= TransformFlags.ContainsES2015 | - TransformFlags.ContainsDestructuringAssignment | - propagateAssignmentPatternFlags(node.left); + node.transformFlags |= TransformFlags.ContainsES2015 + | TransformFlags.ContainsDestructuringAssignment + | propagateAssignmentPatternFlags(node.left); } } - else if (operatorKind === SyntaxKind.AsteriskAsteriskToken || operatorKind === SyntaxKind.AsteriskAsteriskEqualsToken) { + else if ( + operatorKind === SyntaxKind.AsteriskAsteriskToken || operatorKind === SyntaxKind.AsteriskAsteriskEqualsToken + ) { node.transformFlags |= TransformFlags.ContainsES2016; } else if (isLogicalOrCoalescingAssignmentOperator(operatorKind)) { @@ -3467,7 +3848,12 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } // @api - function updateBinaryExpression(node: BinaryExpression, left: Expression, operator: BinaryOperatorToken, right: Expression) { + function updateBinaryExpression( + node: BinaryExpression, + left: Expression, + operator: BinaryOperatorToken, + right: Expression, + ) { return node.left !== left || node.operatorToken !== operator || node.right !== right @@ -3476,18 +3862,24 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } // @api - function createConditionalExpression(condition: Expression, questionToken: QuestionToken | undefined, whenTrue: Expression, colonToken: ColonToken | undefined, whenFalse: Expression) { + function createConditionalExpression( + condition: Expression, + questionToken: QuestionToken | undefined, + whenTrue: Expression, + colonToken: ColonToken | undefined, + whenFalse: Expression, + ) { const node = createBaseNode(SyntaxKind.ConditionalExpression); node.condition = parenthesizerRules().parenthesizeConditionOfConditionalExpression(condition); node.questionToken = questionToken ?? createToken(SyntaxKind.QuestionToken); node.whenTrue = parenthesizerRules().parenthesizeBranchOfConditionalExpression(whenTrue); node.colonToken = colonToken ?? createToken(SyntaxKind.ColonToken); node.whenFalse = parenthesizerRules().parenthesizeBranchOfConditionalExpression(whenFalse); - node.transformFlags |= propagateChildFlags(node.condition) | - propagateChildFlags(node.questionToken) | - propagateChildFlags(node.whenTrue) | - propagateChildFlags(node.colonToken) | - propagateChildFlags(node.whenFalse); + node.transformFlags |= propagateChildFlags(node.condition) + | propagateChildFlags(node.questionToken) + | propagateChildFlags(node.whenTrue) + | propagateChildFlags(node.colonToken) + | propagateChildFlags(node.whenFalse); return node; } @@ -3514,21 +3906,30 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode const node = createBaseNode(SyntaxKind.TemplateExpression); node.head = head; node.templateSpans = createNodeArray(templateSpans); - node.transformFlags |= propagateChildFlags(node.head) | - propagateChildrenFlags(node.templateSpans) | - TransformFlags.ContainsES2015; + node.transformFlags |= propagateChildFlags(node.head) + | propagateChildrenFlags(node.templateSpans) + | TransformFlags.ContainsES2015; return node; } // @api - function updateTemplateExpression(node: TemplateExpression, head: TemplateHead, templateSpans: readonly TemplateSpan[]) { + function updateTemplateExpression( + node: TemplateExpression, + head: TemplateHead, + templateSpans: readonly TemplateSpan[], + ) { return node.head !== head || node.templateSpans !== templateSpans ? update(createTemplateExpression(head, templateSpans), node) : node; } - function checkTemplateLiteralLikeNode(kind: TemplateLiteralToken["kind"], text: string | undefined, rawText: string | undefined, templateFlags = TokenFlags.None) { + function checkTemplateLiteralLikeNode( + kind: TemplateLiteralToken["kind"], + text: string | undefined, + rawText: string | undefined, + templateFlags = TokenFlags.None, + ) { Debug.assert(!(templateFlags & ~TokenFlags.TemplateLiteralLikeFlags), "Unsupported template flags."); // NOTE: without the assignment to `undefined`, we don't narrow the initial type of `cooked`. // eslint-disable-next-line no-undef-init @@ -3546,7 +3947,10 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode text = cooked; } else if (cooked !== undefined) { - Debug.assert(text === cooked, "Expected argument 'text' to be the normalized (i.e. 'cooked') version of argument 'rawText'."); + Debug.assert( + text === cooked, + "Expected argument 'text' to be the normalized (i.e. 'cooked') version of argument 'rawText'.", + ); } return text; } @@ -3562,7 +3966,12 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode // NOTE: `createTemplateLiteralLikeToken` and `createTemplateLiteralLikeDeclaration` are identical except for // the underlying nodes they create. To avoid polymorphism due to two different node shapes, these // functions are intentionally duplicated. - function createTemplateLiteralLikeToken(kind: TemplateLiteralToken["kind"], text: string, rawText: string | undefined, templateFlags: TokenFlags | undefined) { + function createTemplateLiteralLikeToken( + kind: TemplateLiteralToken["kind"], + text: string, + rawText: string | undefined, + templateFlags: TokenFlags | undefined, + ) { const node = createBaseToken(kind); node.text = text; node.rawText = rawText; @@ -3571,7 +3980,12 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode return node; } - function createTemplateLiteralLikeDeclaration(kind: SyntaxKind.NoSubstitutionTemplateLiteral, text: string, rawText: string | undefined, templateFlags: TokenFlags | undefined) { + function createTemplateLiteralLikeDeclaration( + kind: SyntaxKind.NoSubstitutionTemplateLiteral, + text: string, + rawText: string | undefined, + templateFlags: TokenFlags | undefined, + ) { const node = createBaseDeclaration(kind); node.text = text; node.rawText = rawText; @@ -3581,7 +3995,12 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } // @api - function createTemplateLiteralLikeNode(kind: TemplateLiteralToken["kind"], text: string, rawText: string | undefined, templateFlags: TokenFlags | undefined) { + function createTemplateLiteralLikeNode( + kind: TemplateLiteralToken["kind"], + text: string, + rawText: string | undefined, + templateFlags: TokenFlags | undefined, + ) { if (kind === SyntaxKind.NoSubstitutionTemplateLiteral) { return createTemplateLiteralLikeDeclaration(kind, text, rawText, templateFlags); } @@ -3607,27 +4026,46 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } // @api - function createNoSubstitutionTemplateLiteral(text: string | undefined, rawText?: string, templateFlags?: TokenFlags) { + function createNoSubstitutionTemplateLiteral( + text: string | undefined, + rawText?: string, + templateFlags?: TokenFlags, + ) { text = checkTemplateLiteralLikeNode(SyntaxKind.TemplateHead, text, rawText, templateFlags); - return createTemplateLiteralLikeDeclaration(SyntaxKind.NoSubstitutionTemplateLiteral, text, rawText, templateFlags) as NoSubstitutionTemplateLiteral; + return createTemplateLiteralLikeDeclaration( + SyntaxKind.NoSubstitutionTemplateLiteral, + text, + rawText, + templateFlags, + ) as NoSubstitutionTemplateLiteral; } // @api - function createYieldExpression(asteriskToken: AsteriskToken | undefined, expression: Expression | undefined): YieldExpression { - Debug.assert(!asteriskToken || !!expression, "A `YieldExpression` with an asteriskToken must have an expression."); + function createYieldExpression( + asteriskToken: AsteriskToken | undefined, + expression: Expression | undefined, + ): YieldExpression { + Debug.assert( + !asteriskToken || !!expression, + "A `YieldExpression` with an asteriskToken must have an expression.", + ); const node = createBaseNode(SyntaxKind.YieldExpression); node.expression = expression && parenthesizerRules().parenthesizeExpressionForDisallowedComma(expression); node.asteriskToken = asteriskToken; - node.transformFlags |= propagateChildFlags(node.expression) | - propagateChildFlags(node.asteriskToken) | - TransformFlags.ContainsES2015 | - TransformFlags.ContainsES2018 | - TransformFlags.ContainsYield; + node.transformFlags |= propagateChildFlags(node.expression) + | propagateChildFlags(node.asteriskToken) + | TransformFlags.ContainsES2015 + | TransformFlags.ContainsES2018 + | TransformFlags.ContainsYield; return node; } // @api - function updateYieldExpression(node: YieldExpression, asteriskToken: AsteriskToken | undefined, expression: Expression) { + function updateYieldExpression( + node: YieldExpression, + asteriskToken: AsteriskToken | undefined, + expression: Expression, + ) { return node.expression !== expression || node.asteriskToken !== asteriskToken ? update(createYieldExpression(asteriskToken, expression), node) @@ -3638,9 +4076,9 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode function createSpreadElement(expression: Expression) { const node = createBaseNode(SyntaxKind.SpreadElement); node.expression = parenthesizerRules().parenthesizeExpressionForDisallowedComma(expression); - node.transformFlags |= propagateChildFlags(node.expression) | - TransformFlags.ContainsES2015 | - TransformFlags.ContainsRestOrSpread; + node.transformFlags |= propagateChildFlags(node.expression) + | TransformFlags.ContainsES2015 + | TransformFlags.ContainsRestOrSpread; return node; } @@ -3665,13 +4103,13 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode node.typeParameters = asNodeArray(typeParameters); node.heritageClauses = asNodeArray(heritageClauses); node.members = createNodeArray(members); - node.transformFlags |= propagateChildrenFlags(node.modifiers) | - propagateNameFlags(node.name) | - propagateChildrenFlags(node.typeParameters) | - propagateChildrenFlags(node.heritageClauses) | - propagateChildrenFlags(node.members) | - (node.typeParameters ? TransformFlags.ContainsTypeScript : TransformFlags.None) | - TransformFlags.ContainsES2015; + node.transformFlags |= propagateChildrenFlags(node.modifiers) + | propagateNameFlags(node.name) + | propagateChildrenFlags(node.typeParameters) + | propagateChildrenFlags(node.heritageClauses) + | propagateChildrenFlags(node.members) + | (node.typeParameters ? TransformFlags.ContainsTypeScript : TransformFlags.None) + | TransformFlags.ContainsES2015; node.jsDoc = undefined; // initialized by parser (JsDocContainer) return node; @@ -3705,14 +4143,18 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode const node = createBaseNode(SyntaxKind.ExpressionWithTypeArguments); node.expression = parenthesizerRules().parenthesizeLeftSideOfAccess(expression, /*optionalChain*/ false); node.typeArguments = typeArguments && parenthesizerRules().parenthesizeTypeArguments(typeArguments); - node.transformFlags |= propagateChildFlags(node.expression) | - propagateChildrenFlags(node.typeArguments) | - TransformFlags.ContainsES2015; + node.transformFlags |= propagateChildFlags(node.expression) + | propagateChildrenFlags(node.typeArguments) + | TransformFlags.ContainsES2015; return node; } // @api - function updateExpressionWithTypeArguments(node: ExpressionWithTypeArguments, expression: Expression, typeArguments: readonly TypeNode[] | undefined) { + function updateExpressionWithTypeArguments( + node: ExpressionWithTypeArguments, + expression: Expression, + typeArguments: readonly TypeNode[] | undefined, + ) { return node.expression !== expression || node.typeArguments !== typeArguments ? update(createExpressionWithTypeArguments(expression, typeArguments), node) @@ -3724,9 +4166,9 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode const node = createBaseNode(SyntaxKind.AsExpression); node.expression = expression; node.type = type; - node.transformFlags |= propagateChildFlags(node.expression) | - propagateChildFlags(node.type) | - TransformFlags.ContainsTypeScript; + node.transformFlags |= propagateChildFlags(node.expression) + | propagateChildFlags(node.type) + | TransformFlags.ContainsTypeScript; return node; } @@ -3742,8 +4184,8 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode function createNonNullExpression(expression: Expression) { const node = createBaseNode(SyntaxKind.NonNullExpression); node.expression = parenthesizerRules().parenthesizeLeftSideOfAccess(expression, /*optionalChain*/ false); - node.transformFlags |= propagateChildFlags(node.expression) | - TransformFlags.ContainsTypeScript; + node.transformFlags |= propagateChildFlags(node.expression) + | TransformFlags.ContainsTypeScript; return node; } @@ -3762,9 +4204,9 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode const node = createBaseNode(SyntaxKind.SatisfiesExpression); node.expression = expression; node.type = type; - node.transformFlags |= propagateChildFlags(node.expression) | - propagateChildFlags(node.type) | - TransformFlags.ContainsTypeScript; + node.transformFlags |= propagateChildFlags(node.expression) + | propagateChildFlags(node.type) + | TransformFlags.ContainsTypeScript; return node; } @@ -3781,14 +4223,17 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode const node = createBaseNode(SyntaxKind.NonNullExpression); node.flags |= NodeFlags.OptionalChain; node.expression = parenthesizerRules().parenthesizeLeftSideOfAccess(expression, /*optionalChain*/ true); - node.transformFlags |= propagateChildFlags(node.expression) | - TransformFlags.ContainsTypeScript; + node.transformFlags |= propagateChildFlags(node.expression) + | TransformFlags.ContainsTypeScript; return node; } // @api function updateNonNullChain(node: NonNullChain, expression: Expression) { - Debug.assert(!!(node.flags & NodeFlags.OptionalChain), "Cannot update a NonNullExpression using updateNonNullChain. Use updateNonNullExpression instead."); + Debug.assert( + !!(node.flags & NodeFlags.OptionalChain), + "Cannot update a NonNullExpression using updateNonNullChain. Use updateNonNullExpression instead.", + ); return node.expression !== expression ? update(createNonNullChain(expression), node) : node; @@ -3831,9 +4276,9 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode const node = createBaseNode(SyntaxKind.TemplateSpan); node.expression = expression; node.literal = literal; - node.transformFlags |= propagateChildFlags(node.expression) | - propagateChildFlags(node.literal) | - TransformFlags.ContainsES2015; + node.transformFlags |= propagateChildFlags(node.expression) + | propagateChildFlags(node.literal) + | TransformFlags.ContainsES2015; return node; } @@ -3877,12 +4322,16 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } // @api - function createVariableStatement(modifiers: readonly ModifierLike[] | undefined, declarationList: VariableDeclarationList | readonly VariableDeclaration[]) { + function createVariableStatement( + modifiers: readonly ModifierLike[] | undefined, + declarationList: VariableDeclarationList | readonly VariableDeclaration[], + ) { const node = createBaseNode(SyntaxKind.VariableStatement); node.modifiers = asNodeArray(modifiers); - node.declarationList = isArray(declarationList) ? createVariableDeclarationList(declarationList) : declarationList; - node.transformFlags |= propagateChildrenFlags(node.modifiers) | - propagateChildFlags(node.declarationList); + node.declarationList = isArray(declarationList) ? createVariableDeclarationList(declarationList) + : declarationList; + node.transformFlags |= propagateChildrenFlags(node.modifiers) + | propagateChildFlags(node.declarationList); if (modifiersToFlags(node.modifiers) & ModifierFlags.Ambient) { node.transformFlags = TransformFlags.ContainsTypeScript; } @@ -3893,7 +4342,11 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } // @api - function updateVariableStatement(node: VariableStatement, modifiers: readonly ModifierLike[] | undefined, declarationList: VariableDeclarationList) { + function updateVariableStatement( + node: VariableStatement, + modifiers: readonly ModifierLike[] | undefined, + declarationList: VariableDeclarationList, + ) { return node.modifiers !== modifiers || node.declarationList !== declarationList ? update(createVariableStatement(modifiers, declarationList), node) @@ -3931,9 +4384,9 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode node.expression = expression; node.thenStatement = asEmbeddedStatement(thenStatement); node.elseStatement = asEmbeddedStatement(elseStatement); - node.transformFlags |= propagateChildFlags(node.expression) | - propagateChildFlags(node.thenStatement) | - propagateChildFlags(node.elseStatement); + node.transformFlags |= propagateChildFlags(node.expression) + | propagateChildFlags(node.thenStatement) + | propagateChildFlags(node.elseStatement); node.jsDoc = undefined; // initialized by parser (JsDocContainer) node.flowNode = undefined; // initialized by binder (FlowContainer) @@ -3941,7 +4394,12 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } // @api - function updateIfStatement(node: IfStatement, expression: Expression, thenStatement: Statement, elseStatement: Statement | undefined) { + function updateIfStatement( + node: IfStatement, + expression: Expression, + thenStatement: Statement, + elseStatement: Statement | undefined, + ) { return node.expression !== expression || node.thenStatement !== thenStatement || node.elseStatement !== elseStatement @@ -3954,8 +4412,8 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode const node = createBaseNode(SyntaxKind.DoStatement); node.statement = asEmbeddedStatement(statement); node.expression = expression; - node.transformFlags |= propagateChildFlags(node.statement) | - propagateChildFlags(node.expression); + node.transformFlags |= propagateChildFlags(node.statement) + | propagateChildFlags(node.expression); node.jsDoc = undefined; // initialized by parser (JsDocContainer) node.flowNode = undefined; // initialized by binder (FlowContainer) @@ -3975,8 +4433,8 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode const node = createBaseNode(SyntaxKind.WhileStatement); node.expression = expression; node.statement = asEmbeddedStatement(statement); - node.transformFlags |= propagateChildFlags(node.expression) | - propagateChildFlags(node.statement); + node.transformFlags |= propagateChildFlags(node.expression) + | propagateChildFlags(node.statement); node.jsDoc = undefined; // initialized by parser (JsDocContainer) node.flowNode = undefined; // initialized by binder (FlowContainer) @@ -3992,16 +4450,21 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } // @api - function createForStatement(initializer: ForInitializer | undefined, condition: Expression | undefined, incrementor: Expression | undefined, statement: Statement) { + function createForStatement( + initializer: ForInitializer | undefined, + condition: Expression | undefined, + incrementor: Expression | undefined, + statement: Statement, + ) { const node = createBaseNode(SyntaxKind.ForStatement); node.initializer = initializer; node.condition = condition; node.incrementor = incrementor; node.statement = asEmbeddedStatement(statement); - node.transformFlags |= propagateChildFlags(node.initializer) | - propagateChildFlags(node.condition) | - propagateChildFlags(node.incrementor) | - propagateChildFlags(node.statement); + node.transformFlags |= propagateChildFlags(node.initializer) + | propagateChildFlags(node.condition) + | propagateChildFlags(node.incrementor) + | propagateChildFlags(node.statement); node.jsDoc = undefined; // initialized by parser (JsDocContainer) node.locals = undefined; // initialized by binder (LocalsContainer) @@ -4011,7 +4474,13 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } // @api - function updateForStatement(node: ForStatement, initializer: ForInitializer | undefined, condition: Expression | undefined, incrementor: Expression | undefined, statement: Statement) { + function updateForStatement( + node: ForStatement, + initializer: ForInitializer | undefined, + condition: Expression | undefined, + incrementor: Expression | undefined, + statement: Statement, + ) { return node.initializer !== initializer || node.condition !== condition || node.incrementor !== incrementor @@ -4026,9 +4495,9 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode node.initializer = initializer; node.expression = expression; node.statement = asEmbeddedStatement(statement); - node.transformFlags |= propagateChildFlags(node.initializer) | - propagateChildFlags(node.expression) | - propagateChildFlags(node.statement); + node.transformFlags |= propagateChildFlags(node.initializer) + | propagateChildFlags(node.expression) + | propagateChildFlags(node.statement); node.jsDoc = undefined; // initialized by parser (JsDocContainer) node.locals = undefined; // initialized by binder (LocalsContainer) @@ -4038,7 +4507,12 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } // @api - function updateForInStatement(node: ForInStatement, initializer: ForInitializer, expression: Expression, statement: Statement) { + function updateForInStatement( + node: ForInStatement, + initializer: ForInitializer, + expression: Expression, + statement: Statement, + ) { return node.initializer !== initializer || node.expression !== expression || node.statement !== statement @@ -4047,17 +4521,22 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } // @api - function createForOfStatement(awaitModifier: AwaitKeyword | undefined, initializer: ForInitializer, expression: Expression, statement: Statement) { + function createForOfStatement( + awaitModifier: AwaitKeyword | undefined, + initializer: ForInitializer, + expression: Expression, + statement: Statement, + ) { const node = createBaseNode(SyntaxKind.ForOfStatement); node.awaitModifier = awaitModifier; node.initializer = initializer; node.expression = parenthesizerRules().parenthesizeExpressionForDisallowedComma(expression); node.statement = asEmbeddedStatement(statement); - node.transformFlags |= propagateChildFlags(node.awaitModifier) | - propagateChildFlags(node.initializer) | - propagateChildFlags(node.expression) | - propagateChildFlags(node.statement) | - TransformFlags.ContainsES2015; + node.transformFlags |= propagateChildFlags(node.awaitModifier) + | propagateChildFlags(node.initializer) + | propagateChildFlags(node.expression) + | propagateChildFlags(node.statement) + | TransformFlags.ContainsES2015; if (awaitModifier) node.transformFlags |= TransformFlags.ContainsES2018; node.jsDoc = undefined; // initialized by parser (JsDocContainer) @@ -4068,7 +4547,13 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } // @api - function updateForOfStatement(node: ForOfStatement, awaitModifier: AwaitKeyword | undefined, initializer: ForInitializer, expression: Expression, statement: Statement) { + function updateForOfStatement( + node: ForOfStatement, + awaitModifier: AwaitKeyword | undefined, + initializer: ForInitializer, + expression: Expression, + statement: Statement, + ) { return node.awaitModifier !== awaitModifier || node.initializer !== initializer || node.expression !== expression @@ -4081,8 +4566,8 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode function createContinueStatement(label?: string | Identifier): ContinueStatement { const node = createBaseNode(SyntaxKind.ContinueStatement); node.label = asName(label); - node.transformFlags |= propagateChildFlags(node.label) | - TransformFlags.ContainsHoistedDeclarationOrCompletion; + node.transformFlags |= propagateChildFlags(node.label) + | TransformFlags.ContainsHoistedDeclarationOrCompletion; node.jsDoc = undefined; // initialized by parser (JsDocContainer) node.flowNode = undefined; // initialized by binder (FlowContainer) @@ -4100,8 +4585,8 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode function createBreakStatement(label?: string | Identifier): BreakStatement { const node = createBaseNode(SyntaxKind.BreakStatement); node.label = asName(label); - node.transformFlags |= propagateChildFlags(node.label) | - TransformFlags.ContainsHoistedDeclarationOrCompletion; + node.transformFlags |= propagateChildFlags(node.label) + | TransformFlags.ContainsHoistedDeclarationOrCompletion; node.jsDoc = undefined; // initialized by parser (JsDocContainer) node.flowNode = undefined; // initialized by binder (FlowContainer) @@ -4120,9 +4605,9 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode const node = createBaseNode(SyntaxKind.ReturnStatement); node.expression = expression; // return in an ES2018 async generator must be awaited - node.transformFlags |= propagateChildFlags(node.expression) | - TransformFlags.ContainsES2018 | - TransformFlags.ContainsHoistedDeclarationOrCompletion; + node.transformFlags |= propagateChildFlags(node.expression) + | TransformFlags.ContainsES2018 + | TransformFlags.ContainsHoistedDeclarationOrCompletion; node.jsDoc = undefined; // initialized by parser (JsDocContainer) node.flowNode = undefined; // initialized by binder (FlowContainer) @@ -4141,8 +4626,8 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode const node = createBaseNode(SyntaxKind.WithStatement); node.expression = expression; node.statement = asEmbeddedStatement(statement); - node.transformFlags |= propagateChildFlags(node.expression) | - propagateChildFlags(node.statement); + node.transformFlags |= propagateChildFlags(node.expression) + | propagateChildFlags(node.statement); node.jsDoc = undefined; // initialized by parser (JsDocContainer) node.flowNode = undefined; // initialized by binder (FlowContainer) @@ -4162,8 +4647,8 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode const node = createBaseNode(SyntaxKind.SwitchStatement); node.expression = parenthesizerRules().parenthesizeExpressionForDisallowedComma(expression); node.caseBlock = caseBlock; - node.transformFlags |= propagateChildFlags(node.expression) | - propagateChildFlags(node.caseBlock); + node.transformFlags |= propagateChildFlags(node.expression) + | propagateChildFlags(node.caseBlock); node.jsDoc = undefined; // initialized by parser (JsDocContainer) node.flowNode = undefined; // initialized by binder (FlowContainer) @@ -4184,8 +4669,8 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode const node = createBaseNode(SyntaxKind.LabeledStatement); node.label = asName(label); node.statement = asEmbeddedStatement(statement); - node.transformFlags |= propagateChildFlags(node.label) | - propagateChildFlags(node.statement); + node.transformFlags |= propagateChildFlags(node.label) + | propagateChildFlags(node.statement); node.jsDoc = undefined; // initialized by parser (JsDocContainer) node.flowNode = undefined; // initialized by binder (FlowContainer) @@ -4219,14 +4704,18 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } // @api - function createTryStatement(tryBlock: Block, catchClause: CatchClause | undefined, finallyBlock: Block | undefined) { + function createTryStatement( + tryBlock: Block, + catchClause: CatchClause | undefined, + finallyBlock: Block | undefined, + ) { const node = createBaseNode(SyntaxKind.TryStatement); node.tryBlock = tryBlock; node.catchClause = catchClause; node.finallyBlock = finallyBlock; - node.transformFlags |= propagateChildFlags(node.tryBlock) | - propagateChildFlags(node.catchClause) | - propagateChildFlags(node.finallyBlock); + node.transformFlags |= propagateChildFlags(node.tryBlock) + | propagateChildFlags(node.catchClause) + | propagateChildFlags(node.finallyBlock); node.jsDoc = undefined; // initialized by parser (JsDocContainer) node.flowNode = undefined; // initialized by binder (FlowContainer) @@ -4234,7 +4723,12 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } // @api - function updateTryStatement(node: TryStatement, tryBlock: Block, catchClause: CatchClause | undefined, finallyBlock: Block | undefined) { + function updateTryStatement( + node: TryStatement, + tryBlock: Block, + catchClause: CatchClause | undefined, + finallyBlock: Block | undefined, + ) { return node.tryBlock !== tryBlock || node.catchClause !== catchClause || node.finallyBlock !== finallyBlock @@ -4252,22 +4746,33 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } // @api - function createVariableDeclaration(name: string | BindingName, exclamationToken: ExclamationToken | undefined, type: TypeNode | undefined, initializer: Expression | undefined) { + function createVariableDeclaration( + name: string | BindingName, + exclamationToken: ExclamationToken | undefined, + type: TypeNode | undefined, + initializer: Expression | undefined, + ) { const node = createBaseDeclaration(SyntaxKind.VariableDeclaration); node.name = asName(name); node.exclamationToken = exclamationToken; node.type = type; node.initializer = asInitializer(initializer); - node.transformFlags |= propagateNameFlags(node.name) | - propagateChildFlags(node.initializer) | - (node.exclamationToken ?? node.type ? TransformFlags.ContainsTypeScript : TransformFlags.None); + node.transformFlags |= propagateNameFlags(node.name) + | propagateChildFlags(node.initializer) + | (node.exclamationToken ?? node.type ? TransformFlags.ContainsTypeScript : TransformFlags.None); node.jsDoc = undefined; // initialized by parser (JsDocContainer) return node; } // @api - function updateVariableDeclaration(node: VariableDeclaration, name: BindingName, exclamationToken: ExclamationToken | undefined, type: TypeNode | undefined, initializer: Expression | undefined) { + function updateVariableDeclaration( + node: VariableDeclaration, + name: BindingName, + exclamationToken: ExclamationToken | undefined, + type: TypeNode | undefined, + initializer: Expression | undefined, + ) { return node.name !== name || node.type !== type || node.exclamationToken !== exclamationToken @@ -4281,11 +4786,11 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode const node = createBaseNode(SyntaxKind.VariableDeclarationList); node.flags |= flags & NodeFlags.BlockScoped; node.declarations = createNodeArray(declarations); - node.transformFlags |= propagateChildrenFlags(node.declarations) | - TransformFlags.ContainsHoistedDeclarationOrCompletion; + node.transformFlags |= propagateChildrenFlags(node.declarations) + | TransformFlags.ContainsHoistedDeclarationOrCompletion; if (flags & NodeFlags.BlockScoped) { - node.transformFlags |= TransformFlags.ContainsES2015 | - TransformFlags.ContainsBlockScopedBinding; + node.transformFlags |= TransformFlags.ContainsES2015 + | TransformFlags.ContainsBlockScopedBinding; } if (flags & NodeFlags.Using) { node.transformFlags |= TransformFlags.ContainsESNext; @@ -4294,7 +4799,10 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } // @api - function updateVariableDeclarationList(node: VariableDeclarationList, declarations: readonly VariableDeclaration[]) { + function updateVariableDeclarationList( + node: VariableDeclarationList, + declarations: readonly VariableDeclaration[], + ) { return node.declarations !== declarations ? update(createVariableDeclarationList(declarations, node.flags), node) : node; @@ -4327,19 +4835,19 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode const isGenerator = !!node.asteriskToken; const isAsyncGenerator = isAsync && isGenerator; - node.transformFlags = propagateChildrenFlags(node.modifiers) | - propagateChildFlags(node.asteriskToken) | - propagateNameFlags(node.name) | - propagateChildrenFlags(node.typeParameters) | - propagateChildrenFlags(node.parameters) | - propagateChildFlags(node.type) | - (propagateChildFlags(node.body) & ~TransformFlags.ContainsPossibleTopLevelAwait) | - (isAsyncGenerator ? TransformFlags.ContainsES2018 : - isAsync ? TransformFlags.ContainsES2017 : - isGenerator ? TransformFlags.ContainsGenerator : - TransformFlags.None) | - (node.typeParameters || node.type ? TransformFlags.ContainsTypeScript : TransformFlags.None) | - TransformFlags.ContainsHoistedDeclarationOrCompletion; + node.transformFlags = propagateChildrenFlags(node.modifiers) + | propagateChildFlags(node.asteriskToken) + | propagateNameFlags(node.name) + | propagateChildrenFlags(node.typeParameters) + | propagateChildrenFlags(node.parameters) + | propagateChildFlags(node.type) + | (propagateChildFlags(node.body) & ~TransformFlags.ContainsPossibleTopLevelAwait) + | (isAsyncGenerator ? TransformFlags.ContainsES2018 + : isAsync ? TransformFlags.ContainsES2017 + : isGenerator ? TransformFlags.ContainsGenerator + : TransformFlags.None) + | (node.typeParameters || node.type ? TransformFlags.ContainsTypeScript : TransformFlags.None) + | TransformFlags.ContainsHoistedDeclarationOrCompletion; } node.typeArguments = undefined; // used in quick info @@ -4369,7 +4877,10 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode || node.parameters !== parameters || node.type !== type || node.body !== body - ? finishUpdateFunctionDeclaration(createFunctionDeclaration(modifiers, asteriskToken, name, typeParameters, parameters, type, body), node) + ? finishUpdateFunctionDeclaration( + createFunctionDeclaration(modifiers, asteriskToken, name, typeParameters, parameters, type, body), + node, + ) : node; } @@ -4402,13 +4913,13 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode node.transformFlags = TransformFlags.ContainsTypeScript; } else { - node.transformFlags |= propagateChildrenFlags(node.modifiers) | - propagateNameFlags(node.name) | - propagateChildrenFlags(node.typeParameters) | - propagateChildrenFlags(node.heritageClauses) | - propagateChildrenFlags(node.members) | - (node.typeParameters ? TransformFlags.ContainsTypeScript : TransformFlags.None) | - TransformFlags.ContainsES2015; + node.transformFlags |= propagateChildrenFlags(node.modifiers) + | propagateNameFlags(node.name) + | propagateChildrenFlags(node.typeParameters) + | propagateChildrenFlags(node.heritageClauses) + | propagateChildrenFlags(node.members) + | (node.typeParameters ? TransformFlags.ContainsTypeScript : TransformFlags.None) + | TransformFlags.ContainsES2015; if (node.transformFlags & TransformFlags.ContainsTypeScriptClassSyntax) { node.transformFlags |= TransformFlags.ContainsTypeScript; } @@ -4520,10 +5031,10 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode node.modifiers = asNodeArray(modifiers); node.name = asName(name); node.members = createNodeArray(members); - node.transformFlags |= propagateChildrenFlags(node.modifiers) | - propagateChildFlags(node.name) | - propagateChildrenFlags(node.members) | - TransformFlags.ContainsTypeScript; + node.transformFlags |= propagateChildrenFlags(node.modifiers) + | propagateChildFlags(node.name) + | propagateChildrenFlags(node.members) + | TransformFlags.ContainsTypeScript; node.transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // Enum declarations cannot contain `await` node.jsDoc = undefined; // initialized by parser (JsDocContainer) @@ -4560,10 +5071,10 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode node.transformFlags = TransformFlags.ContainsTypeScript; } else { - node.transformFlags |= propagateChildrenFlags(node.modifiers) | - propagateChildFlags(node.name) | - propagateChildFlags(node.body) | - TransformFlags.ContainsTypeScript; + node.transformFlags |= propagateChildrenFlags(node.modifiers) + | propagateChildFlags(node.name) + | propagateChildFlags(node.body) + | TransformFlags.ContainsTypeScript; } node.transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // Module declarations cannot contain `await`. @@ -4626,8 +5137,8 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode function createNamespaceExportDeclaration(name: string | Identifier) { const node = createBaseDeclaration(SyntaxKind.NamespaceExportDeclaration); node.name = asName(name); - node.transformFlags |= propagateIdentifierNameFlags(node.name) | - TransformFlags.ContainsTypeScript; + node.transformFlags |= propagateIdentifierNameFlags(node.name) + | TransformFlags.ContainsTypeScript; node.modifiers = undefined; // initialized by parser to report grammar errors node.jsDoc = undefined; // initialized by parser (JsDocContainer) @@ -4641,7 +5152,10 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode : node; } - function finishUpdateNamespaceExportDeclaration(updated: Mutable, original: NamespaceExportDeclaration) { + function finishUpdateNamespaceExportDeclaration( + updated: Mutable, + original: NamespaceExportDeclaration, + ) { if (updated !== original) { // copy children used only for error reporting updated.modifiers = original.modifiers; @@ -4661,9 +5175,9 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode node.name = asName(name); node.isTypeOnly = isTypeOnly; node.moduleReference = moduleReference; - node.transformFlags |= propagateChildrenFlags(node.modifiers) | - propagateIdentifierNameFlags(node.name) | - propagateChildFlags(node.moduleReference); + node.transformFlags |= propagateChildrenFlags(node.modifiers) + | propagateIdentifierNameFlags(node.name) + | propagateChildFlags(node.moduleReference); if (!isExternalModuleReference(node.moduleReference)) { node.transformFlags |= TransformFlags.ContainsTypeScript; @@ -4703,8 +5217,8 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode node.importClause = importClause; node.moduleSpecifier = moduleSpecifier; node.assertClause = assertClause; - node.transformFlags |= propagateChildFlags(node.importClause) | - propagateChildFlags(node.moduleSpecifier); + node.transformFlags |= propagateChildFlags(node.importClause) + | propagateChildFlags(node.moduleSpecifier); node.transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // always parsed in an Await context node.jsDoc = undefined; // initialized by parser (JsDocContainer) @@ -4728,13 +5242,17 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } // @api - function createImportClause(isTypeOnly: boolean, name: Identifier | undefined, namedBindings: NamedImportBindings | undefined): ImportClause { + function createImportClause( + isTypeOnly: boolean, + name: Identifier | undefined, + namedBindings: NamedImportBindings | undefined, + ): ImportClause { const node = createBaseDeclaration(SyntaxKind.ImportClause); node.isTypeOnly = isTypeOnly; node.name = name; node.namedBindings = namedBindings; - node.transformFlags |= propagateChildFlags(node.name) | - propagateChildFlags(node.namedBindings); + node.transformFlags |= propagateChildFlags(node.name) + | propagateChildFlags(node.namedBindings); if (isTypeOnly) { node.transformFlags |= TransformFlags.ContainsTypeScript; } @@ -4743,7 +5261,12 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } // @api - function updateImportClause(node: ImportClause, isTypeOnly: boolean, name: Identifier | undefined, namedBindings: NamedImportBindings | undefined) { + function updateImportClause( + node: ImportClause, + isTypeOnly: boolean, + name: Identifier | undefined, + namedBindings: NamedImportBindings | undefined, + ) { return node.isTypeOnly !== isTypeOnly || node.name !== name || node.namedBindings !== namedBindings @@ -4761,7 +5284,11 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } // @api - function updateAssertClause(node: AssertClause, elements: readonly AssertEntry[], multiLine?: boolean): AssertClause { + function updateAssertClause( + node: AssertClause, + elements: readonly AssertEntry[], + multiLine?: boolean, + ): AssertClause { return node.elements !== elements || node.multiLine !== multiLine ? update(createAssertClause(elements, multiLine), node) @@ -4786,7 +5313,10 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } // @api - function createImportTypeAssertionContainer(clause: AssertClause, multiLine?: boolean): ImportTypeAssertionContainer { + function createImportTypeAssertionContainer( + clause: AssertClause, + multiLine?: boolean, + ): ImportTypeAssertionContainer { const node = createBaseNode(SyntaxKind.ImportTypeAssertionContainer); node.assertClause = clause; node.multiLine = multiLine; @@ -4794,7 +5324,11 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } // @api - function updateImportTypeAssertionContainer(node: ImportTypeAssertionContainer, clause: AssertClause, multiLine?: boolean): ImportTypeAssertionContainer { + function updateImportTypeAssertionContainer( + node: ImportTypeAssertionContainer, + clause: AssertClause, + multiLine?: boolean, + ): ImportTypeAssertionContainer { return node.assertClause !== clause || node.multiLine !== multiLine ? update(createImportTypeAssertionContainer(clause, multiLine), node) @@ -4821,8 +5355,8 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode function createNamespaceExport(name: Identifier): NamespaceExport { const node = createBaseDeclaration(SyntaxKind.NamespaceExport); node.name = name; - node.transformFlags |= propagateChildFlags(node.name) | - TransformFlags.ContainsES2020; + node.transformFlags |= propagateChildFlags(node.name) + | TransformFlags.ContainsES2020; node.transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // always parsed in an Await context return node; } @@ -4856,14 +5390,19 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode node.isTypeOnly = isTypeOnly; node.propertyName = propertyName; node.name = name; - node.transformFlags |= propagateChildFlags(node.propertyName) | - propagateChildFlags(node.name); + node.transformFlags |= propagateChildFlags(node.propertyName) + | propagateChildFlags(node.name); node.transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // always parsed in an Await context return node; } // @api - function updateImportSpecifier(node: ImportSpecifier, isTypeOnly: boolean, propertyName: Identifier | undefined, name: Identifier) { + function updateImportSpecifier( + node: ImportSpecifier, + isTypeOnly: boolean, + propertyName: Identifier | undefined, + name: Identifier, + ) { return node.isTypeOnly !== isTypeOnly || node.propertyName !== propertyName || node.name !== name @@ -4881,7 +5420,11 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode node.modifiers = asNodeArray(modifiers); node.isExportEquals = isExportEquals; node.expression = isExportEquals - ? parenthesizerRules().parenthesizeRightSideOfBinary(SyntaxKind.EqualsToken, /*leftSide*/ undefined, expression) + ? parenthesizerRules().parenthesizeRightSideOfBinary( + SyntaxKind.EqualsToken, + /*leftSide*/ undefined, + expression, + ) : parenthesizerRules().parenthesizeExpressionOfExportDefault(expression); node.transformFlags |= propagateChildrenFlags(node.modifiers) | propagateChildFlags(node.expression); node.transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // always parsed in an Await context @@ -4916,9 +5459,9 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode node.exportClause = exportClause; node.moduleSpecifier = moduleSpecifier; node.assertClause = assertClause; - node.transformFlags |= propagateChildrenFlags(node.modifiers) | - propagateChildFlags(node.exportClause) | - propagateChildFlags(node.moduleSpecifier); + node.transformFlags |= propagateChildrenFlags(node.modifiers) + | propagateChildFlags(node.exportClause) + | propagateChildFlags(node.moduleSpecifier); node.transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // always parsed in an Await context node.jsDoc = undefined; // initialized by parser (JsDocContainer) @@ -4939,7 +5482,10 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode || node.exportClause !== exportClause || node.moduleSpecifier !== moduleSpecifier || node.assertClause !== assertClause - ? finishUpdateExportDeclaration(createExportDeclaration(modifiers, isTypeOnly, exportClause, moduleSpecifier, assertClause), node) + ? finishUpdateExportDeclaration( + createExportDeclaration(modifiers, isTypeOnly, exportClause, moduleSpecifier, assertClause), + node, + ) : node; } @@ -4970,13 +5516,17 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } // @api - function createExportSpecifier(isTypeOnly: boolean, propertyName: string | Identifier | undefined, name: string | Identifier) { + function createExportSpecifier( + isTypeOnly: boolean, + propertyName: string | Identifier | undefined, + name: string | Identifier, + ) { const node = createBaseNode(SyntaxKind.ExportSpecifier); node.isTypeOnly = isTypeOnly; node.propertyName = asName(propertyName); node.name = asName(name); - node.transformFlags |= propagateChildFlags(node.propertyName) | - propagateChildFlags(node.name); + node.transformFlags |= propagateChildFlags(node.propertyName) + | propagateChildFlags(node.name); node.transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // always parsed in an Await context node.jsDoc = undefined; // initialized by parser (JsDocContainer) @@ -4984,7 +5534,12 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } // @api - function updateExportSpecifier(node: ExportSpecifier, isTypeOnly: boolean, propertyName: Identifier | undefined, name: Identifier) { + function updateExportSpecifier( + node: ExportSpecifier, + isTypeOnly: boolean, + propertyName: Identifier | undefined, + name: Identifier, + ) { return node.isTypeOnly !== isTypeOnly || node.propertyName !== propertyName || node.name !== name @@ -5034,7 +5589,9 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode // @api // createJSDocNullableType // createJSDocNonNullableType - function createJSDocPrePostfixUnaryTypeWorker(kind: T["kind"], type: T["type"], postfix = false): T { + function createJSDocPrePostfixUnaryTypeWorker< + T extends JSDocType & { readonly type: TypeNode | undefined; readonly postfix: boolean; }, + >(kind: T["kind"], type: T["type"], postfix = false): T { const node = createJSDocUnaryTypeWorker( kind, postfix ? type && parenthesizerRules().parenthesizeNonArrayTypeOfPostfixType(type) : type, @@ -5047,7 +5604,10 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode // createJSDocOptionalType // createJSDocVariadicType // createJSDocNamepathType - function createJSDocUnaryTypeWorker(kind: T["kind"], type: T["type"]): T { + function createJSDocUnaryTypeWorker( + kind: T["kind"], + type: T["type"], + ): T { const node = createBaseNode(kind); node.type = type; return node; @@ -5056,7 +5616,9 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode // @api // updateJSDocNonNullableType // updateJSDocNullableType - function updateJSDocPrePostfixUnaryTypeWorker(kind: T["kind"], node: T, type: T["type"]): T { + function updateJSDocPrePostfixUnaryTypeWorker< + T extends JSDocType & { readonly type: TypeNode | undefined; readonly postfix: boolean; }, + >(kind: T["kind"], node: T, type: T["type"]): T { return node.type !== type ? update(createJSDocPrePostfixUnaryTypeWorker(kind, type, node.postfix), node) : node; @@ -5066,19 +5628,26 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode // updateJSDocOptionalType // updateJSDocVariadicType // updateJSDocNamepathType - function updateJSDocUnaryTypeWorker(kind: T["kind"], node: T, type: T["type"]): T { + function updateJSDocUnaryTypeWorker( + kind: T["kind"], + node: T, + type: T["type"], + ): T { return node.type !== type ? update(createJSDocUnaryTypeWorker(kind, type), node) : node; } // @api - function createJSDocFunctionType(parameters: readonly ParameterDeclaration[], type: TypeNode | undefined): JSDocFunctionType { + function createJSDocFunctionType( + parameters: readonly ParameterDeclaration[], + type: TypeNode | undefined, + ): JSDocFunctionType { const node = createBaseDeclaration(SyntaxKind.JSDocFunctionType); node.parameters = asNodeArray(parameters); node.type = type; - node.transformFlags = propagateChildrenFlags(node.parameters) | - (node.type ? TransformFlags.ContainsTypeScript : TransformFlags.None); + node.transformFlags = propagateChildrenFlags(node.parameters) + | (node.type ? TransformFlags.ContainsTypeScript : TransformFlags.None); node.jsDoc = undefined; // initialized by parser (JsDocContainer) node.locals = undefined; // initialized by binder (LocalsContainer) @@ -5088,7 +5657,11 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } // @api - function updateJSDocFunctionType(node: JSDocFunctionType, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined): JSDocFunctionType { + function updateJSDocFunctionType( + node: JSDocFunctionType, + parameters: readonly ParameterDeclaration[], + type: TypeNode | undefined, + ): JSDocFunctionType { return node.parameters !== parameters || node.type !== type ? update(createJSDocFunctionType(parameters, type), node) @@ -5096,7 +5669,10 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } // @api - function createJSDocTypeLiteral(propertyTags?: readonly JSDocPropertyLikeTag[], isArrayType = false): JSDocTypeLiteral { + function createJSDocTypeLiteral( + propertyTags?: readonly JSDocPropertyLikeTag[], + isArrayType = false, + ): JSDocTypeLiteral { const node = createBaseDeclaration(SyntaxKind.JSDocTypeLiteral); node.jsDocPropertyTags = asNodeArray(propertyTags); node.isArrayType = isArrayType; @@ -5104,7 +5680,11 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } // @api - function updateJSDocTypeLiteral(node: JSDocTypeLiteral, propertyTags: readonly JSDocPropertyLikeTag[] | undefined, isArrayType: boolean): JSDocTypeLiteral { + function updateJSDocTypeLiteral( + node: JSDocTypeLiteral, + propertyTags: readonly JSDocPropertyLikeTag[] | undefined, + isArrayType: boolean, + ): JSDocTypeLiteral { return node.jsDocPropertyTags !== propertyTags || node.isArrayType !== isArrayType ? update(createJSDocTypeLiteral(propertyTags, isArrayType), node) @@ -5126,7 +5706,11 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } // @api - function createJSDocSignature(typeParameters: readonly JSDocTemplateTag[] | undefined, parameters: readonly JSDocParameterTag[], type?: JSDocReturnTag): JSDocSignature { + function createJSDocSignature( + typeParameters: readonly JSDocTemplateTag[] | undefined, + parameters: readonly JSDocParameterTag[], + type?: JSDocReturnTag, + ): JSDocSignature { const node = createBaseDeclaration(SyntaxKind.JSDocSignature); node.typeParameters = asNodeArray(typeParameters); node.parameters = createNodeArray(parameters); @@ -5139,7 +5723,12 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } // @api - function updateJSDocSignature(node: JSDocSignature, typeParameters: readonly JSDocTemplateTag[] | undefined, parameters: readonly JSDocParameterTag[], type: JSDocReturnTag | undefined): JSDocSignature { + function updateJSDocSignature( + node: JSDocSignature, + typeParameters: readonly JSDocTemplateTag[] | undefined, + parameters: readonly JSDocParameterTag[], + type: JSDocReturnTag | undefined, + ): JSDocSignature { return node.typeParameters !== typeParameters || node.parameters !== parameters || node.type !== type @@ -5155,14 +5744,22 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } // @api - function createBaseJSDocTag(kind: T["kind"], tagName: Identifier, comment: string | NodeArray | undefined) { + function createBaseJSDocTag( + kind: T["kind"], + tagName: Identifier, + comment: string | NodeArray | undefined, + ) { const node = createBaseNode(kind); node.tagName = tagName; node.comment = comment; return node; } - function createBaseJSDocTagDeclaration(kind: T["kind"], tagName: Identifier, comment: string | NodeArray | undefined) { + function createBaseJSDocTagDeclaration( + kind: T["kind"], + tagName: Identifier, + comment: string | NodeArray | undefined, + ) { const node = createBaseDeclaration(kind); node.tagName = tagName; node.comment = comment; @@ -5170,15 +5767,30 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } // @api - function createJSDocTemplateTag(tagName: Identifier | undefined, constraint: JSDocTypeExpression | undefined, typeParameters: readonly TypeParameterDeclaration[], comment?: string | NodeArray): JSDocTemplateTag { - const node = createBaseJSDocTag(SyntaxKind.JSDocTemplateTag, tagName ?? createIdentifier("template"), comment); + function createJSDocTemplateTag( + tagName: Identifier | undefined, + constraint: JSDocTypeExpression | undefined, + typeParameters: readonly TypeParameterDeclaration[], + comment?: string | NodeArray, + ): JSDocTemplateTag { + const node = createBaseJSDocTag( + SyntaxKind.JSDocTemplateTag, + tagName ?? createIdentifier("template"), + comment, + ); node.constraint = constraint; node.typeParameters = createNodeArray(typeParameters); return node; } // @api - function updateJSDocTemplateTag(node: JSDocTemplateTag, tagName: Identifier = getDefaultTagName(node), constraint: JSDocTypeExpression | undefined, typeParameters: readonly TypeParameterDeclaration[], comment: string | NodeArray | undefined): JSDocTemplateTag { + function updateJSDocTemplateTag( + node: JSDocTemplateTag, + tagName: Identifier = getDefaultTagName(node), + constraint: JSDocTypeExpression | undefined, + typeParameters: readonly TypeParameterDeclaration[], + comment: string | NodeArray | undefined, + ): JSDocTemplateTag { return node.tagName !== tagName || node.constraint !== constraint || node.typeParameters !== typeParameters @@ -5188,8 +5800,17 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } // @api - function createJSDocTypedefTag(tagName: Identifier | undefined, typeExpression?: JSDocTypeExpression, fullName?: Identifier | JSDocNamespaceDeclaration, comment?: string | NodeArray): JSDocTypedefTag { - const node = createBaseJSDocTagDeclaration(SyntaxKind.JSDocTypedefTag, tagName ?? createIdentifier("typedef"), comment); + function createJSDocTypedefTag( + tagName: Identifier | undefined, + typeExpression?: JSDocTypeExpression, + fullName?: Identifier | JSDocNamespaceDeclaration, + comment?: string | NodeArray, + ): JSDocTypedefTag { + const node = createBaseJSDocTagDeclaration( + SyntaxKind.JSDocTypedefTag, + tagName ?? createIdentifier("typedef"), + comment, + ); node.typeExpression = typeExpression; node.fullName = fullName; node.name = getJSDocTypeAliasName(fullName); @@ -5200,7 +5821,13 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } // @api - function updateJSDocTypedefTag(node: JSDocTypedefTag, tagName: Identifier = getDefaultTagName(node), typeExpression: JSDocTypeExpression | undefined, fullName: Identifier | JSDocNamespaceDeclaration | undefined, comment: string | NodeArray | undefined): JSDocTypedefTag { + function updateJSDocTypedefTag( + node: JSDocTypedefTag, + tagName: Identifier = getDefaultTagName(node), + typeExpression: JSDocTypeExpression | undefined, + fullName: Identifier | JSDocNamespaceDeclaration | undefined, + comment: string | NodeArray | undefined, + ): JSDocTypedefTag { return node.tagName !== tagName || node.typeExpression !== typeExpression || node.fullName !== fullName @@ -5210,8 +5837,19 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } // @api - function createJSDocParameterTag(tagName: Identifier | undefined, name: EntityName, isBracketed: boolean, typeExpression?: JSDocTypeExpression, isNameFirst?: boolean, comment?: string | NodeArray): JSDocParameterTag { - const node = createBaseJSDocTagDeclaration(SyntaxKind.JSDocParameterTag, tagName ?? createIdentifier("param"), comment); + function createJSDocParameterTag( + tagName: Identifier | undefined, + name: EntityName, + isBracketed: boolean, + typeExpression?: JSDocTypeExpression, + isNameFirst?: boolean, + comment?: string | NodeArray, + ): JSDocParameterTag { + const node = createBaseJSDocTagDeclaration( + SyntaxKind.JSDocParameterTag, + tagName ?? createIdentifier("param"), + comment, + ); node.typeExpression = typeExpression; node.name = name; node.isNameFirst = !!isNameFirst; @@ -5220,7 +5858,15 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } // @api - function updateJSDocParameterTag(node: JSDocParameterTag, tagName: Identifier = getDefaultTagName(node), name: EntityName, isBracketed: boolean, typeExpression: JSDocTypeExpression | undefined, isNameFirst: boolean, comment: string | NodeArray | undefined): JSDocParameterTag { + function updateJSDocParameterTag( + node: JSDocParameterTag, + tagName: Identifier = getDefaultTagName(node), + name: EntityName, + isBracketed: boolean, + typeExpression: JSDocTypeExpression | undefined, + isNameFirst: boolean, + comment: string | NodeArray | undefined, + ): JSDocParameterTag { return node.tagName !== tagName || node.name !== name || node.isBracketed !== isBracketed @@ -5232,8 +5878,19 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } // @api - function createJSDocPropertyTag(tagName: Identifier | undefined, name: EntityName, isBracketed: boolean, typeExpression?: JSDocTypeExpression, isNameFirst?: boolean, comment?: string | NodeArray): JSDocPropertyTag { - const node = createBaseJSDocTagDeclaration(SyntaxKind.JSDocPropertyTag, tagName ?? createIdentifier("prop"), comment); + function createJSDocPropertyTag( + tagName: Identifier | undefined, + name: EntityName, + isBracketed: boolean, + typeExpression?: JSDocTypeExpression, + isNameFirst?: boolean, + comment?: string | NodeArray, + ): JSDocPropertyTag { + const node = createBaseJSDocTagDeclaration( + SyntaxKind.JSDocPropertyTag, + tagName ?? createIdentifier("prop"), + comment, + ); node.typeExpression = typeExpression; node.name = name; node.isNameFirst = !!isNameFirst; @@ -5242,7 +5899,15 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } // @api - function updateJSDocPropertyTag(node: JSDocPropertyTag, tagName: Identifier = getDefaultTagName(node), name: EntityName, isBracketed: boolean, typeExpression: JSDocTypeExpression | undefined, isNameFirst: boolean, comment: string | NodeArray | undefined): JSDocPropertyTag { + function updateJSDocPropertyTag( + node: JSDocPropertyTag, + tagName: Identifier = getDefaultTagName(node), + name: EntityName, + isBracketed: boolean, + typeExpression: JSDocTypeExpression | undefined, + isNameFirst: boolean, + comment: string | NodeArray | undefined, + ): JSDocPropertyTag { return node.tagName !== tagName || node.name !== name || node.isBracketed !== isBracketed @@ -5254,8 +5919,17 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } // @api - function createJSDocCallbackTag(tagName: Identifier | undefined, typeExpression: JSDocSignature, fullName?: Identifier | JSDocNamespaceDeclaration, comment?: string | NodeArray): JSDocCallbackTag { - const node = createBaseJSDocTagDeclaration(SyntaxKind.JSDocCallbackTag, tagName ?? createIdentifier("callback"), comment); + function createJSDocCallbackTag( + tagName: Identifier | undefined, + typeExpression: JSDocSignature, + fullName?: Identifier | JSDocNamespaceDeclaration, + comment?: string | NodeArray, + ): JSDocCallbackTag { + const node = createBaseJSDocTagDeclaration( + SyntaxKind.JSDocCallbackTag, + tagName ?? createIdentifier("callback"), + comment, + ); node.typeExpression = typeExpression; node.fullName = fullName; node.name = getJSDocTypeAliasName(fullName); @@ -5266,7 +5940,13 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } // @api - function updateJSDocCallbackTag(node: JSDocCallbackTag, tagName: Identifier = getDefaultTagName(node), typeExpression: JSDocSignature, fullName: Identifier | JSDocNamespaceDeclaration | undefined, comment: string | NodeArray | undefined): JSDocCallbackTag { + function updateJSDocCallbackTag( + node: JSDocCallbackTag, + tagName: Identifier = getDefaultTagName(node), + typeExpression: JSDocSignature, + fullName: Identifier | JSDocNamespaceDeclaration | undefined, + comment: string | NodeArray | undefined, + ): JSDocCallbackTag { return node.tagName !== tagName || node.typeExpression !== typeExpression || node.fullName !== fullName @@ -5276,14 +5956,27 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } // @api - function createJSDocOverloadTag(tagName: Identifier | undefined, typeExpression: JSDocSignature, comment?: string | NodeArray): JSDocOverloadTag { - const node = createBaseJSDocTag(SyntaxKind.JSDocOverloadTag, tagName ?? createIdentifier("overload"), comment); + function createJSDocOverloadTag( + tagName: Identifier | undefined, + typeExpression: JSDocSignature, + comment?: string | NodeArray, + ): JSDocOverloadTag { + const node = createBaseJSDocTag( + SyntaxKind.JSDocOverloadTag, + tagName ?? createIdentifier("overload"), + comment, + ); node.typeExpression = typeExpression; return node; } // @api - function updateJSDocOverloadTag(node: JSDocOverloadTag, tagName: Identifier = getDefaultTagName(node), typeExpression: JSDocSignature, comment: string | NodeArray | undefined): JSDocOverloadTag { + function updateJSDocOverloadTag( + node: JSDocOverloadTag, + tagName: Identifier = getDefaultTagName(node), + typeExpression: JSDocSignature, + comment: string | NodeArray | undefined, + ): JSDocOverloadTag { return node.tagName !== tagName || node.typeExpression !== typeExpression || node.comment !== comment @@ -5292,14 +5985,27 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } // @api - function createJSDocAugmentsTag(tagName: Identifier | undefined, className: JSDocAugmentsTag["class"], comment?: string | NodeArray): JSDocAugmentsTag { - const node = createBaseJSDocTag(SyntaxKind.JSDocAugmentsTag, tagName ?? createIdentifier("augments"), comment); + function createJSDocAugmentsTag( + tagName: Identifier | undefined, + className: JSDocAugmentsTag["class"], + comment?: string | NodeArray, + ): JSDocAugmentsTag { + const node = createBaseJSDocTag( + SyntaxKind.JSDocAugmentsTag, + tagName ?? createIdentifier("augments"), + comment, + ); node.class = className; return node; } // @api - function updateJSDocAugmentsTag(node: JSDocAugmentsTag, tagName: Identifier = getDefaultTagName(node), className: JSDocAugmentsTag["class"], comment: string | NodeArray | undefined): JSDocAugmentsTag { + function updateJSDocAugmentsTag( + node: JSDocAugmentsTag, + tagName: Identifier = getDefaultTagName(node), + className: JSDocAugmentsTag["class"], + comment: string | NodeArray | undefined, + ): JSDocAugmentsTag { return node.tagName !== tagName || node.class !== className || node.comment !== comment @@ -5308,21 +6014,42 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } // @api - function createJSDocImplementsTag(tagName: Identifier | undefined, className: JSDocImplementsTag["class"], comment?: string | NodeArray): JSDocImplementsTag { - const node = createBaseJSDocTag(SyntaxKind.JSDocImplementsTag, tagName ?? createIdentifier("implements"), comment); + function createJSDocImplementsTag( + tagName: Identifier | undefined, + className: JSDocImplementsTag["class"], + comment?: string | NodeArray, + ): JSDocImplementsTag { + const node = createBaseJSDocTag( + SyntaxKind.JSDocImplementsTag, + tagName ?? createIdentifier("implements"), + comment, + ); node.class = className; return node; } // @api - function createJSDocSeeTag(tagName: Identifier | undefined, name: JSDocNameReference | undefined, comment?: string | NodeArray): JSDocSeeTag { - const node = createBaseJSDocTag(SyntaxKind.JSDocSeeTag, tagName ?? createIdentifier("see"), comment); + function createJSDocSeeTag( + tagName: Identifier | undefined, + name: JSDocNameReference | undefined, + comment?: string | NodeArray, + ): JSDocSeeTag { + const node = createBaseJSDocTag( + SyntaxKind.JSDocSeeTag, + tagName ?? createIdentifier("see"), + comment, + ); node.name = name; return node; } // @api - function updateJSDocSeeTag(node: JSDocSeeTag, tagName: Identifier | undefined, name: JSDocNameReference | undefined, comment?: string | NodeArray): JSDocSeeTag { + function updateJSDocSeeTag( + node: JSDocSeeTag, + tagName: Identifier | undefined, + name: JSDocNameReference | undefined, + comment?: string | NodeArray, + ): JSDocSeeTag { return node.tagName !== tagName || node.name !== name || node.comment !== comment @@ -5338,7 +6065,10 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } // @api - function updateJSDocNameReference(node: JSDocNameReference, name: EntityName | JSDocMemberName): JSDocNameReference { + function updateJSDocNameReference( + node: JSDocNameReference, + name: EntityName | JSDocMemberName, + ): JSDocNameReference { return node.name !== name ? update(createJSDocNameReference(name), node) : node; @@ -5349,8 +6079,8 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode const node = createBaseNode(SyntaxKind.JSDocMemberName); node.left = left; node.right = right; - node.transformFlags |= propagateChildFlags(node.left) | - propagateChildFlags(node.right); + node.transformFlags |= propagateChildFlags(node.left) + | propagateChildFlags(node.right); return node; } @@ -5386,7 +6116,11 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } // @api - function updateJSDocLinkCode(node: JSDocLinkCode, name: EntityName | JSDocMemberName | undefined, text: string): JSDocLinkCode { + function updateJSDocLinkCode( + node: JSDocLinkCode, + name: EntityName | JSDocMemberName | undefined, + text: string, + ): JSDocLinkCode { return node.name !== name ? update(createJSDocLinkCode(name, text), node) : node; @@ -5401,14 +6135,23 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } // @api - function updateJSDocLinkPlain(node: JSDocLinkPlain, name: EntityName | JSDocMemberName | undefined, text: string): JSDocLinkPlain { + function updateJSDocLinkPlain( + node: JSDocLinkPlain, + name: EntityName | JSDocMemberName | undefined, + text: string, + ): JSDocLinkPlain { return node.name !== name ? update(createJSDocLinkPlain(name, text), node) : node; } // @api - function updateJSDocImplementsTag(node: JSDocImplementsTag, tagName: Identifier = getDefaultTagName(node), className: JSDocImplementsTag["class"], comment: string | NodeArray | undefined): JSDocImplementsTag { + function updateJSDocImplementsTag( + node: JSDocImplementsTag, + tagName: Identifier = getDefaultTagName(node), + className: JSDocImplementsTag["class"], + comment: string | NodeArray | undefined, + ): JSDocImplementsTag { return node.tagName !== tagName || node.class !== className || node.comment !== comment @@ -5424,7 +6167,11 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode // createJSDocProtectedTag // createJSDocReadonlyTag // createJSDocDeprecatedTag - function createJSDocSimpleTagWorker(kind: T["kind"], tagName: Identifier | undefined, comment?: string | NodeArray) { + function createJSDocSimpleTagWorker( + kind: T["kind"], + tagName: Identifier | undefined, + comment?: string | NodeArray, + ) { const node = createBaseJSDocTag(kind, tagName ?? createIdentifier(getDefaultTagNameForKind(kind)), comment); return node; } @@ -5437,11 +6184,16 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode // updateJSDocProtectedTag // updateJSDocReadonlyTag // updateJSDocDeprecatedTag - function updateJSDocSimpleTagWorker(kind: T["kind"], node: T, tagName: Identifier = getDefaultTagName(node), comment: string | NodeArray | undefined) { + function updateJSDocSimpleTagWorker( + kind: T["kind"], + node: T, + tagName: Identifier = getDefaultTagName(node), + comment: string | NodeArray | undefined, + ) { return node.tagName !== tagName || node.comment !== comment - ? update(createJSDocSimpleTagWorker(kind, tagName, comment), node) : - node; + ? update(createJSDocSimpleTagWorker(kind, tagName, comment), node) + : node; } // @api @@ -5450,7 +6202,12 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode // createJSDocThisTag // createJSDocEnumTag // createJSDocSatisfiesTag - function createJSDocTypeLikeTagWorker(kind: T["kind"], tagName: Identifier | undefined, typeExpression?: JSDocTypeExpression, comment?: string | NodeArray) { + function createJSDocTypeLikeTagWorker( + kind: T["kind"], + tagName: Identifier | undefined, + typeExpression?: JSDocTypeExpression, + comment?: string | NodeArray, + ) { const node = createBaseJSDocTag(kind, tagName ?? createIdentifier(getDefaultTagNameForKind(kind)), comment); node.typeExpression = typeExpression; return node; @@ -5462,7 +6219,13 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode // updateJSDocThisTag // updateJSDocEnumTag // updateJSDocSatisfiesTag - function updateJSDocTypeLikeTagWorker(kind: T["kind"], node: T, tagName: Identifier = getDefaultTagName(node), typeExpression: JSDocTypeExpression | undefined, comment: string | NodeArray | undefined) { + function updateJSDocTypeLikeTagWorker( + kind: T["kind"], + node: T, + tagName: Identifier = getDefaultTagName(node), + typeExpression: JSDocTypeExpression | undefined, + comment: string | NodeArray | undefined, + ) { return node.tagName !== tagName || node.typeExpression !== typeExpression || node.comment !== comment @@ -5477,7 +6240,11 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } // @api - function updateJSDocUnknownTag(node: JSDocUnknownTag, tagName: Identifier, comment: string | NodeArray | undefined): JSDocUnknownTag { + function updateJSDocUnknownTag( + node: JSDocUnknownTag, + tagName: Identifier, + comment: string | NodeArray | undefined, + ): JSDocUnknownTag { return node.tagName !== tagName || node.comment !== comment ? update(createJSDocUnknownTag(tagName, comment), node) @@ -5485,8 +6252,16 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } // @api - function createJSDocEnumTag(tagName: Identifier | undefined, typeExpression: JSDocTypeExpression, comment?: string | NodeArray) { - const node = createBaseJSDocTagDeclaration(SyntaxKind.JSDocEnumTag, tagName ?? createIdentifier(getDefaultTagNameForKind(SyntaxKind.JSDocEnumTag)), comment); + function createJSDocEnumTag( + tagName: Identifier | undefined, + typeExpression: JSDocTypeExpression, + comment?: string | NodeArray, + ) { + const node = createBaseJSDocTagDeclaration( + SyntaxKind.JSDocEnumTag, + tagName ?? createIdentifier(getDefaultTagNameForKind(SyntaxKind.JSDocEnumTag)), + comment, + ); node.typeExpression = typeExpression; node.locals = undefined; // initialized by binder (LocalsContainer) @@ -5495,7 +6270,12 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } // @api - function updateJSDocEnumTag(node: JSDocEnumTag, tagName: Identifier = getDefaultTagName(node), typeExpression: JSDocTypeExpression, comment: string | NodeArray | undefined) { + function updateJSDocEnumTag( + node: JSDocEnumTag, + tagName: Identifier = getDefaultTagName(node), + typeExpression: JSDocTypeExpression, + comment: string | NodeArray | undefined, + ) { return node.tagName !== tagName || node.typeExpression !== typeExpression || node.comment !== comment @@ -5518,7 +6298,10 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } // @api - function createJSDocComment(comment?: string | NodeArray | undefined, tags?: readonly JSDocTag[] | undefined) { + function createJSDocComment( + comment?: string | NodeArray | undefined, + tags?: readonly JSDocTag[] | undefined, + ) { const node = createBaseNode(SyntaxKind.JSDoc); node.comment = comment; node.tags = asNodeArray(tags); @@ -5526,7 +6309,11 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } // @api - function updateJSDocComment(node: JSDoc, comment: string | NodeArray | undefined, tags: readonly JSDocTag[] | undefined) { + function updateJSDocComment( + node: JSDoc, + comment: string | NodeArray | undefined, + tags: readonly JSDocTag[] | undefined, + ) { return node.comment !== comment || node.tags !== tags ? update(createJSDocComment(comment, tags), node) @@ -5538,20 +6325,29 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode // // @api - function createJsxElement(openingElement: JsxOpeningElement, children: readonly JsxChild[], closingElement: JsxClosingElement) { + function createJsxElement( + openingElement: JsxOpeningElement, + children: readonly JsxChild[], + closingElement: JsxClosingElement, + ) { const node = createBaseNode(SyntaxKind.JsxElement); node.openingElement = openingElement; node.children = createNodeArray(children); node.closingElement = closingElement; - node.transformFlags |= propagateChildFlags(node.openingElement) | - propagateChildrenFlags(node.children) | - propagateChildFlags(node.closingElement) | - TransformFlags.ContainsJsx; + node.transformFlags |= propagateChildFlags(node.openingElement) + | propagateChildrenFlags(node.children) + | propagateChildFlags(node.closingElement) + | TransformFlags.ContainsJsx; return node; } // @api - function updateJsxElement(node: JsxElement, openingElement: JsxOpeningElement, children: readonly JsxChild[], closingElement: JsxClosingElement) { + function updateJsxElement( + node: JsxElement, + openingElement: JsxOpeningElement, + children: readonly JsxChild[], + closingElement: JsxClosingElement, + ) { return node.openingElement !== openingElement || node.children !== children || node.closingElement !== closingElement @@ -5560,15 +6356,19 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } // @api - function createJsxSelfClosingElement(tagName: JsxTagNameExpression, typeArguments: readonly TypeNode[] | undefined, attributes: JsxAttributes) { + function createJsxSelfClosingElement( + tagName: JsxTagNameExpression, + typeArguments: readonly TypeNode[] | undefined, + attributes: JsxAttributes, + ) { const node = createBaseNode(SyntaxKind.JsxSelfClosingElement); node.tagName = tagName; node.typeArguments = asNodeArray(typeArguments); node.attributes = attributes; - node.transformFlags |= propagateChildFlags(node.tagName) | - propagateChildrenFlags(node.typeArguments) | - propagateChildFlags(node.attributes) | - TransformFlags.ContainsJsx; + node.transformFlags |= propagateChildFlags(node.tagName) + | propagateChildrenFlags(node.typeArguments) + | propagateChildFlags(node.attributes) + | TransformFlags.ContainsJsx; if (node.typeArguments) { node.transformFlags |= TransformFlags.ContainsTypeScript; } @@ -5576,7 +6376,12 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } // @api - function updateJsxSelfClosingElement(node: JsxSelfClosingElement, tagName: JsxTagNameExpression, typeArguments: readonly TypeNode[] | undefined, attributes: JsxAttributes) { + function updateJsxSelfClosingElement( + node: JsxSelfClosingElement, + tagName: JsxTagNameExpression, + typeArguments: readonly TypeNode[] | undefined, + attributes: JsxAttributes, + ) { return node.tagName !== tagName || node.typeArguments !== typeArguments || node.attributes !== attributes @@ -5585,15 +6390,19 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } // @api - function createJsxOpeningElement(tagName: JsxTagNameExpression, typeArguments: readonly TypeNode[] | undefined, attributes: JsxAttributes) { + function createJsxOpeningElement( + tagName: JsxTagNameExpression, + typeArguments: readonly TypeNode[] | undefined, + attributes: JsxAttributes, + ) { const node = createBaseNode(SyntaxKind.JsxOpeningElement); node.tagName = tagName; node.typeArguments = asNodeArray(typeArguments); node.attributes = attributes; - node.transformFlags |= propagateChildFlags(node.tagName) | - propagateChildrenFlags(node.typeArguments) | - propagateChildFlags(node.attributes) | - TransformFlags.ContainsJsx; + node.transformFlags |= propagateChildFlags(node.tagName) + | propagateChildrenFlags(node.typeArguments) + | propagateChildFlags(node.attributes) + | TransformFlags.ContainsJsx; if (typeArguments) { node.transformFlags |= TransformFlags.ContainsTypeScript; } @@ -5601,7 +6410,12 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } // @api - function updateJsxOpeningElement(node: JsxOpeningElement, tagName: JsxTagNameExpression, typeArguments: readonly TypeNode[] | undefined, attributes: JsxAttributes) { + function updateJsxOpeningElement( + node: JsxOpeningElement, + tagName: JsxTagNameExpression, + typeArguments: readonly TypeNode[] | undefined, + attributes: JsxAttributes, + ) { return node.tagName !== tagName || node.typeArguments !== typeArguments || node.attributes !== attributes @@ -5613,8 +6427,8 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode function createJsxClosingElement(tagName: JsxTagNameExpression) { const node = createBaseNode(SyntaxKind.JsxClosingElement); node.tagName = tagName; - node.transformFlags |= propagateChildFlags(node.tagName) | - TransformFlags.ContainsJsx; + node.transformFlags |= propagateChildFlags(node.tagName) + | TransformFlags.ContainsJsx; return node; } @@ -5626,20 +6440,29 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } // @api - function createJsxFragment(openingFragment: JsxOpeningFragment, children: readonly JsxChild[], closingFragment: JsxClosingFragment) { + function createJsxFragment( + openingFragment: JsxOpeningFragment, + children: readonly JsxChild[], + closingFragment: JsxClosingFragment, + ) { const node = createBaseNode(SyntaxKind.JsxFragment); node.openingFragment = openingFragment; node.children = createNodeArray(children); node.closingFragment = closingFragment; - node.transformFlags |= propagateChildFlags(node.openingFragment) | - propagateChildrenFlags(node.children) | - propagateChildFlags(node.closingFragment) | - TransformFlags.ContainsJsx; + node.transformFlags |= propagateChildFlags(node.openingFragment) + | propagateChildrenFlags(node.children) + | propagateChildFlags(node.closingFragment) + | TransformFlags.ContainsJsx; return node; } // @api - function updateJsxFragment(node: JsxFragment, openingFragment: JsxOpeningFragment, children: readonly JsxChild[], closingFragment: JsxClosingFragment) { + function updateJsxFragment( + node: JsxFragment, + openingFragment: JsxOpeningFragment, + children: readonly JsxChild[], + closingFragment: JsxClosingFragment, + ) { return node.openingFragment !== openingFragment || node.children !== children || node.closingFragment !== closingFragment @@ -5683,14 +6506,18 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode const node = createBaseDeclaration(SyntaxKind.JsxAttribute); node.name = name; node.initializer = initializer; - node.transformFlags |= propagateChildFlags(node.name) | - propagateChildFlags(node.initializer) | - TransformFlags.ContainsJsx; + node.transformFlags |= propagateChildFlags(node.name) + | propagateChildFlags(node.initializer) + | TransformFlags.ContainsJsx; return node; } // @api - function updateJsxAttribute(node: JsxAttribute, name: JsxAttributeName, initializer: JsxAttributeValue | undefined) { + function updateJsxAttribute( + node: JsxAttribute, + name: JsxAttributeName, + initializer: JsxAttributeValue | undefined, + ) { return node.name !== name || node.initializer !== initializer ? update(createJsxAttribute(name, initializer), node) @@ -5701,8 +6528,8 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode function createJsxAttributes(properties: readonly JsxAttributeLike[]) { const node = createBaseDeclaration(SyntaxKind.JsxAttributes); node.properties = createNodeArray(properties); - node.transformFlags |= propagateChildrenFlags(node.properties) | - TransformFlags.ContainsJsx; + node.transformFlags |= propagateChildrenFlags(node.properties) + | TransformFlags.ContainsJsx; return node; } @@ -5717,8 +6544,8 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode function createJsxSpreadAttribute(expression: Expression) { const node = createBaseNode(SyntaxKind.JsxSpreadAttribute); node.expression = expression; - node.transformFlags |= propagateChildFlags(node.expression) | - TransformFlags.ContainsJsx; + node.transformFlags |= propagateChildFlags(node.expression) + | TransformFlags.ContainsJsx; return node; } @@ -5734,9 +6561,9 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode const node = createBaseNode(SyntaxKind.JsxExpression); node.dotDotDotToken = dotDotDotToken; node.expression = expression; - node.transformFlags |= propagateChildFlags(node.dotDotDotToken) | - propagateChildFlags(node.expression) | - TransformFlags.ContainsJsx; + node.transformFlags |= propagateChildFlags(node.dotDotDotToken) + | propagateChildFlags(node.expression) + | TransformFlags.ContainsJsx; return node; } @@ -5752,9 +6579,9 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode const node = createBaseNode(SyntaxKind.JsxNamespacedName); node.namespace = namespace; node.name = name; - node.transformFlags |= propagateChildFlags(node.namespace) | - propagateChildFlags(node.name) | - TransformFlags.ContainsJsx; + node.transformFlags |= propagateChildFlags(node.namespace) + | propagateChildFlags(node.name) + | TransformFlags.ContainsJsx; return node; } @@ -5775,8 +6602,8 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode const node = createBaseNode(SyntaxKind.CaseClause); node.expression = parenthesizerRules().parenthesizeExpressionForDisallowedComma(expression); node.statements = createNodeArray(statements); - node.transformFlags |= propagateChildFlags(node.expression) | - propagateChildrenFlags(node.statements); + node.transformFlags |= propagateChildFlags(node.expression) + | propagateChildrenFlags(node.statements); node.jsDoc = undefined; // initialized by parser (JsDocContainer) return node; @@ -5832,14 +6659,17 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } // @api - function createCatchClause(variableDeclaration: string | BindingName | VariableDeclaration | undefined, block: Block) { + function createCatchClause( + variableDeclaration: string | BindingName | VariableDeclaration | undefined, + block: Block, + ) { const node = createBaseNode(SyntaxKind.CatchClause); node.variableDeclaration = asVariableDeclaration(variableDeclaration); node.block = block; - node.transformFlags |= propagateChildFlags(node.variableDeclaration) | - propagateChildFlags(node.block) | - (!variableDeclaration ? TransformFlags.ContainsES2019 : TransformFlags.None); + node.transformFlags |= propagateChildFlags(node.variableDeclaration) + | propagateChildFlags(node.block) + | (!variableDeclaration ? TransformFlags.ContainsES2019 : TransformFlags.None); node.locals = undefined; // initialized by binder (LocalsContainer) node.nextContainer = undefined; // initialized by binder (LocalsContainer) @@ -5863,8 +6693,8 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode const node = createBaseDeclaration(SyntaxKind.PropertyAssignment); node.name = asName(name); node.initializer = parenthesizerRules().parenthesizeExpressionForDisallowedComma(initializer); - node.transformFlags |= propagateNameFlags(node.name) | - propagateChildFlags(node.initializer); + node.transformFlags |= propagateNameFlags(node.name) + | propagateChildFlags(node.initializer); node.modifiers = undefined; // initialized by parser to report grammar errors node.questionToken = undefined; // initialized by parser to report grammar errors @@ -5896,10 +6726,11 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode function createShorthandPropertyAssignment(name: string | Identifier, objectAssignmentInitializer?: Expression) { const node = createBaseDeclaration(SyntaxKind.ShorthandPropertyAssignment); node.name = asName(name); - node.objectAssignmentInitializer = objectAssignmentInitializer && parenthesizerRules().parenthesizeExpressionForDisallowedComma(objectAssignmentInitializer); - node.transformFlags |= propagateIdentifierNameFlags(node.name) | - propagateChildFlags(node.objectAssignmentInitializer) | - TransformFlags.ContainsES2015; + node.objectAssignmentInitializer = objectAssignmentInitializer + && parenthesizerRules().parenthesizeExpressionForDisallowedComma(objectAssignmentInitializer); + node.transformFlags |= propagateIdentifierNameFlags(node.name) + | propagateChildFlags(node.objectAssignmentInitializer) + | TransformFlags.ContainsES2015; node.equalsToken = undefined; // initialized by parser to report grammar errors node.modifiers = undefined; // initialized by parser to report grammar errors @@ -5910,14 +6741,24 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } // @api - function updateShorthandPropertyAssignment(node: ShorthandPropertyAssignment, name: Identifier, objectAssignmentInitializer: Expression | undefined) { + function updateShorthandPropertyAssignment( + node: ShorthandPropertyAssignment, + name: Identifier, + objectAssignmentInitializer: Expression | undefined, + ) { return node.name !== name || node.objectAssignmentInitializer !== objectAssignmentInitializer - ? finishUpdateShorthandPropertyAssignment(createShorthandPropertyAssignment(name, objectAssignmentInitializer), node) + ? finishUpdateShorthandPropertyAssignment( + createShorthandPropertyAssignment(name, objectAssignmentInitializer), + node, + ) : node; } - function finishUpdateShorthandPropertyAssignment(updated: Mutable, original: ShorthandPropertyAssignment) { + function finishUpdateShorthandPropertyAssignment( + updated: Mutable, + original: ShorthandPropertyAssignment, + ) { if (updated !== original) { // copy children used only for error reporting updated.modifiers = original.modifiers; @@ -5932,9 +6773,9 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode function createSpreadAssignment(expression: Expression) { const node = createBaseDeclaration(SyntaxKind.SpreadAssignment); node.expression = parenthesizerRules().parenthesizeExpressionForDisallowedComma(expression); - node.transformFlags |= propagateChildFlags(node.expression) | - TransformFlags.ContainsES2018 | - TransformFlags.ContainsObjectRestOrSpread; + node.transformFlags |= propagateChildFlags(node.expression) + | TransformFlags.ContainsES2018 + | TransformFlags.ContainsObjectRestOrSpread; node.jsDoc = undefined; // initialized by parser (JsDocContainer) return node; @@ -5956,9 +6797,9 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode const node = createBaseDeclaration(SyntaxKind.EnumMember); node.name = asName(name); node.initializer = initializer && parenthesizerRules().parenthesizeExpressionForDisallowedComma(initializer); - node.transformFlags |= propagateChildFlags(node.name) | - propagateChildFlags(node.initializer) | - TransformFlags.ContainsTypeScript; + node.transformFlags |= propagateChildFlags(node.name) + | propagateChildFlags(node.initializer) + | TransformFlags.ContainsTypeScript; node.jsDoc = undefined; // initialized by parser (JsDocContainer) return node; @@ -5997,8 +6838,8 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode node.isDeclarationFile = false; node.hasNoDefaultLib = false; - node.transformFlags |= propagateChildrenFlags(node.statements) | - propagateChildFlags(node.endOfFileToken); + node.transformFlags |= propagateChildrenFlags(node.statements) + | propagateChildFlags(node.endOfFileToken); node.locals = undefined; // initialized by binder (LocalsContainer) node.nextContainer = undefined; // initialized by binder (LocalsContainer) @@ -6109,8 +6950,8 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode node.typeReferenceDirectives = typeReferences; node.hasNoDefaultLib = hasNoDefaultLib; node.libReferenceDirectives = libReferences; - node.transformFlags = propagateChildrenFlags(node.statements) | - propagateChildFlags(node.endOfFileToken); + node.transformFlags = propagateChildrenFlags(node.statements) + | propagateChildFlags(node.endOfFileToken); return node; } @@ -6130,12 +6971,26 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode || node.typeReferenceDirectives !== typeReferenceDirectives || node.hasNoDefaultLib !== hasNoDefaultLib || node.libReferenceDirectives !== libReferenceDirectives - ? update(cloneSourceFileWithChanges(node, statements, isDeclarationFile, referencedFiles, typeReferenceDirectives, hasNoDefaultLib, libReferenceDirectives), node) + ? update( + cloneSourceFileWithChanges( + node, + statements, + isDeclarationFile, + referencedFiles, + typeReferenceDirectives, + hasNoDefaultLib, + libReferenceDirectives, + ), + node, + ) : node; } // @api - function createBundle(sourceFiles: readonly SourceFile[], prepends: readonly (UnparsedSource | InputFiles)[] = emptyArray) { + function createBundle( + sourceFiles: readonly SourceFile[], + prepends: readonly (UnparsedSource | InputFiles)[] = emptyArray, + ) { const node = createBaseNode(SyntaxKind.Bundle); node.prepends = prepends; node.sourceFiles = sourceFiles; @@ -6147,7 +7002,11 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } // @api - function updateBundle(node: Bundle, sourceFiles: readonly SourceFile[], prepends: readonly (UnparsedSource | InputFiles)[] = emptyArray) { + function updateBundle( + node: Bundle, + sourceFiles: readonly SourceFile[], + prepends: readonly (UnparsedSource | InputFiles)[] = emptyArray, + ) { return node.sourceFiles !== sourceFiles || node.prepends !== prepends ? update(createBundle(sourceFiles, prepends), node) @@ -6155,7 +7014,11 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } // @api - function createUnparsedSource(prologues: readonly UnparsedPrologue[], syntheticReferences: readonly UnparsedSyntheticReference[] | undefined, texts: readonly UnparsedSourceText[]) { + function createUnparsedSource( + prologues: readonly UnparsedPrologue[], + syntheticReferences: readonly UnparsedSyntheticReference[] | undefined, + texts: readonly UnparsedSourceText[], + ) { const node = createBaseNode(SyntaxKind.UnparsedSource); node.prologues = prologues; node.syntheticReferences = syntheticReferences; @@ -6192,7 +7055,9 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } // @api - function createUnparsedSyntheticReference(section: BundleFileHasNoDefaultLib | BundleFileReference): UnparsedSyntheticReference { + function createUnparsedSyntheticReference( + section: BundleFileHasNoDefaultLib | BundleFileReference, + ): UnparsedSyntheticReference { const node = createBaseNode(SyntaxKind.UnparsedSyntheticReference); node.data = section.data; node.section = section; @@ -6212,7 +7077,11 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode // // @api - function createSyntheticExpression(type: Type, isSpread = false, tupleNameSource?: ParameterDeclaration | NamedTupleMember) { + function createSyntheticExpression( + type: Type, + isSpread = false, + tupleNameSource?: ParameterDeclaration | NamedTupleMember, + ) { const node = createBaseNode(SyntaxKind.SyntheticExpression); node.type = type; node.isSpread = isSpread; @@ -6257,8 +7126,8 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode const node = createBaseNode(SyntaxKind.PartiallyEmittedExpression); node.expression = expression; node.original = original; - node.transformFlags |= propagateChildFlags(node.expression) | - TransformFlags.ContainsTypeScript; + node.transformFlags |= propagateChildFlags(node.expression) + | TransformFlags.ContainsTypeScript; setTextRange(node, original); return node; } @@ -6302,13 +7171,17 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode const node = createBaseNode(SyntaxKind.SyntheticReferenceExpression); node.expression = expression; node.thisArg = thisArg; - node.transformFlags |= propagateChildFlags(node.expression) | - propagateChildFlags(node.thisArg); + node.transformFlags |= propagateChildFlags(node.expression) + | propagateChildFlags(node.thisArg); return node; } // @api - function updateSyntheticReferenceExpression(node: SyntheticReferenceExpression, expression: Expression, thisArg: Expression) { + function updateSyntheticReferenceExpression( + node: SyntheticReferenceExpression, + expression: Expression, + thisArg: Expression, + ) { return node.expression !== expression || node.thisArg !== thisArg ? update(createSyntheticReferenceExpression(expression, thisArg), node) @@ -6381,8 +7254,8 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode return clonePrivateIdentifier(node) as T & PrivateIdentifier; } - const clone = !isNodeKind(node.kind) ? baseFactory.createBaseTokenNode(node.kind) as T : - baseFactory.createBaseNode(node.kind) as T; + const clone = !isNodeKind(node.kind) ? baseFactory.createBaseTokenNode(node.kind) as T + : baseFactory.createBaseNode(node.kind) as T; (clone as Mutable).flags |= node.flags & ~NodeFlags.Synthesized; (clone as Mutable).transformFlags = node.transformFlags; @@ -6400,9 +7273,19 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } // compound nodes - function createImmediatelyInvokedFunctionExpression(statements: readonly Statement[]): ImmediatelyInvokedFunctionExpression; - function createImmediatelyInvokedFunctionExpression(statements: readonly Statement[], param: ParameterDeclaration, paramValue: Expression): ImmediatelyInvokedFunctionExpression; - function createImmediatelyInvokedFunctionExpression(statements: readonly Statement[], param?: ParameterDeclaration, paramValue?: Expression) { + function createImmediatelyInvokedFunctionExpression( + statements: readonly Statement[], + ): ImmediatelyInvokedFunctionExpression; + function createImmediatelyInvokedFunctionExpression( + statements: readonly Statement[], + param: ParameterDeclaration, + paramValue: Expression, + ): ImmediatelyInvokedFunctionExpression; + function createImmediatelyInvokedFunctionExpression( + statements: readonly Statement[], + param?: ParameterDeclaration, + paramValue?: Expression, + ) { return createCallExpression( createFunctionExpression( /*modifiers*/ undefined, @@ -6419,8 +7302,16 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } function createImmediatelyInvokedArrowFunction(statements: readonly Statement[]): ImmediatelyInvokedArrowFunction; - function createImmediatelyInvokedArrowFunction(statements: readonly Statement[], param: ParameterDeclaration, paramValue: Expression): ImmediatelyInvokedArrowFunction; - function createImmediatelyInvokedArrowFunction(statements: readonly Statement[], param?: ParameterDeclaration, paramValue?: Expression) { + function createImmediatelyInvokedArrowFunction( + statements: readonly Statement[], + param: ParameterDeclaration, + paramValue: Expression, + ): ImmediatelyInvokedArrowFunction; + function createImmediatelyInvokedArrowFunction( + statements: readonly Statement[], + param?: ParameterDeclaration, + paramValue?: Expression, + ) { return createCallExpression( createArrowFunction( /*modifiers*/ undefined, @@ -6462,18 +7353,22 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode // function createTypeCheck(value: Expression, tag: TypeOfTag) { - return tag === "null" ? factory.createStrictEquality(value, createNull()) : - tag === "undefined" ? factory.createStrictEquality(value, createVoidZero()) : - factory.createStrictEquality(createTypeOfExpression(value), createStringLiteral(tag)); + return tag === "null" ? factory.createStrictEquality(value, createNull()) + : tag === "undefined" ? factory.createStrictEquality(value, createVoidZero()) + : factory.createStrictEquality(createTypeOfExpression(value), createStringLiteral(tag)); } function createIsNotTypeCheck(value: Expression, tag: TypeOfTag) { - return tag === "null" ? factory.createStrictInequality(value, createNull()) : - tag === "undefined" ? factory.createStrictInequality(value, createVoidZero()) : - factory.createStrictInequality(createTypeOfExpression(value), createStringLiteral(tag)); + return tag === "null" ? factory.createStrictInequality(value, createNull()) + : tag === "undefined" ? factory.createStrictInequality(value, createVoidZero()) + : factory.createStrictInequality(createTypeOfExpression(value), createStringLiteral(tag)); } - function createMethodCall(object: Expression, methodName: string | Identifier, argumentsList: readonly Expression[]) { + function createMethodCall( + object: Expression, + methodName: string | Identifier, + argumentsList: readonly Expression[], + ) { // Preserve the optionality of `object`. if (isCallChain(object)) { return createCallChain( @@ -6502,7 +7397,11 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode return createMethodCall(target, "apply", [thisArg, argumentsExpression]); } - function createGlobalMethodCall(globalObjectName: string, methodName: string, argumentsList: readonly Expression[]) { + function createGlobalMethodCall( + globalObjectName: string, + methodName: string, + argumentsList: readonly Expression[], + ) { return createMethodCall(createIdentifier(globalObjectName), methodName, argumentsList); } @@ -6514,7 +7413,11 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode return createMethodCall(array, "concat", argumentsList); } - function createObjectDefinePropertyCall(target: Expression, propertyName: string | Expression, attributes: Expression) { + function createObjectDefinePropertyCall( + target: Expression, + propertyName: string | Expression, + attributes: Expression, + ) { return createGlobalMethodCall("Object", "defineProperty", [target, asExpression(propertyName), attributes]); } @@ -6523,14 +7426,31 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } function createReflectGetCall(target: Expression, propertyKey: Expression, receiver?: Expression): CallExpression { - return createGlobalMethodCall("Reflect", "get", receiver ? [target, propertyKey, receiver] : [target, propertyKey]); + return createGlobalMethodCall( + "Reflect", + "get", + receiver ? [target, propertyKey, receiver] : [target, propertyKey], + ); } - function createReflectSetCall(target: Expression, propertyKey: Expression, value: Expression, receiver?: Expression): CallExpression { - return createGlobalMethodCall("Reflect", "set", receiver ? [target, propertyKey, value, receiver] : [target, propertyKey, value]); + function createReflectSetCall( + target: Expression, + propertyKey: Expression, + value: Expression, + receiver?: Expression, + ): CallExpression { + return createGlobalMethodCall( + "Reflect", + "set", + receiver ? [target, propertyKey, value, receiver] : [target, propertyKey, value], + ); } - function tryAddPropertyAssignment(properties: PropertyAssignment[], propertyName: string, expression: Expression | undefined) { + function tryAddPropertyAssignment( + properties: PropertyAssignment[], + propertyName: string, + expression: Expression | undefined, + ) { if (expression) { properties.push(createPropertyAssignment(propertyName, expression)); return true; @@ -6549,7 +7469,10 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode let isAccessor = tryAddPropertyAssignment(properties, "get", attributes.get); isAccessor = tryAddPropertyAssignment(properties, "set", attributes.set) || isAccessor; - Debug.assert(!(isData && isAccessor), "A PropertyDescriptor may not be both an accessor descriptor and a data descriptor."); + Debug.assert( + !(isData && isAccessor), + "A PropertyDescriptor may not be both an accessor descriptor and a data descriptor.", + ); return createObjectLiteralExpression(properties, !singleLine); } @@ -6593,7 +7516,11 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode && !some(getSyntheticTrailingComments(node)); } - function restoreOuterExpressions(outerExpression: Expression | undefined, innerExpression: Expression, kinds = OuterExpressionKinds.All): Expression { + function restoreOuterExpressions( + outerExpression: Expression | undefined, + innerExpression: Expression, + kinds = OuterExpressionKinds.All, + ): Expression { if (outerExpression && isOuterExpression(outerExpression, kinds) && !isIgnorableParen(outerExpression)) { return updateOuterExpression( outerExpression, @@ -6603,7 +7530,11 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode return innerExpression; } - function restoreEnclosingLabel(node: Statement, outermostLabeledStatement: LabeledStatement | undefined, afterRestoreLabelCallback?: (node: LabeledStatement) => void): Statement { + function restoreEnclosingLabel( + node: Statement, + outermostLabeledStatement: LabeledStatement | undefined, + afterRestoreLabelCallback?: (node: LabeledStatement) => void, + ): Statement { if (!outermostLabeledStatement) { return node; } @@ -6643,7 +7574,12 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } } - function createCallBinding(expression: Expression, recordTempVariable: (temp: Identifier) => void, languageVersion?: ScriptTarget, cacheIdentifiers = false): CallBinding { + function createCallBinding( + expression: Expression, + recordTempVariable: (temp: Identifier) => void, + languageVersion?: ScriptTarget, + cacheIdentifiers = false, + ): CallBinding { const callee = skipOuterExpressions(expression, OuterExpressionKinds.All); let thisArg: Expression; let target: LeftHandSideExpression; @@ -6746,8 +7682,15 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode : reduceLeft(expressions, factory.createComma)!; } - function getName(node: Declaration | undefined, allowComments?: boolean, allowSourceMaps?: boolean, emitFlags: EmitFlags = 0, ignoreAssignedName?: boolean) { - const nodeName = ignoreAssignedName ? node && getNonAssignedNameOfDeclaration(node) : getNameOfDeclaration(node); + function getName( + node: Declaration | undefined, + allowComments?: boolean, + allowSourceMaps?: boolean, + emitFlags: EmitFlags = 0, + ignoreAssignedName?: boolean, + ) { + const nodeName = ignoreAssignedName ? node && getNonAssignedNameOfDeclaration(node) + : getNameOfDeclaration(node); if (nodeName && isIdentifier(nodeName) && !isGeneratedIdentifier(nodeName)) { // TODO(rbuckton): Does this need to be parented? const name = setParent(setTextRange(cloneNode(nodeName), nodeName), nodeName.parent); @@ -6786,7 +7729,12 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode * @param allowSourceMaps A value indicating whether source maps may be emitted for the name. * @param ignoreAssignedName Indicates that the assigned name of a declaration shouldn't be considered. */ - function getLocalName(node: Declaration, allowComments?: boolean, allowSourceMaps?: boolean, ignoreAssignedName?: boolean) { + function getLocalName( + node: Declaration, + allowComments?: boolean, + allowSourceMaps?: boolean, + ignoreAssignedName?: boolean, + ) { return getName(node, allowComments, allowSourceMaps, EmitFlags.LocalName, ignoreAssignedName); } @@ -6823,7 +7771,12 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode * @param allowComments A value indicating whether comments may be emitted for the name. * @param allowSourceMaps A value indicating whether source maps may be emitted for the name. */ - function getNamespaceMemberName(ns: Identifier, name: Identifier, allowComments?: boolean, allowSourceMaps?: boolean): PropertyAccessExpression { + function getNamespaceMemberName( + ns: Identifier, + name: Identifier, + allowComments?: boolean, + allowSourceMaps?: boolean, + ): PropertyAccessExpression { const qualifiedName = createPropertyAccessExpression(ns, nodeIsSynthesized(name) ? name : cloneNode(name)); setTextRange(qualifiedName, name); let emitFlags: EmitFlags = 0; @@ -6844,7 +7797,12 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode * @param allowComments A value indicating whether comments may be emitted for the name. * @param allowSourceMaps A value indicating whether source maps may be emitted for the name. */ - function getExternalModuleOrNamespaceExportName(ns: Identifier | undefined, node: Declaration, allowComments?: boolean, allowSourceMaps?: boolean): Identifier | PropertyAccessExpression { + function getExternalModuleOrNamespaceExportName( + ns: Identifier | undefined, + node: Declaration, + allowComments?: boolean, + allowSourceMaps?: boolean, + ): Identifier | PropertyAccessExpression { if (ns && hasSyntacticModifier(node, ModifierFlags.Export)) { return getNamespaceMemberName(ns, getName(node), allowComments, allowSourceMaps); } @@ -6858,7 +7816,12 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode * @param ensureUseStrict boolean determining whether the function need to add prologue-directives * @param visitor Optional callback used to visit any custom prologue directives. */ - function copyPrologue(source: readonly Statement[], target: Statement[], ensureUseStrict?: boolean, visitor?: (node: Node) => VisitResult): number { + function copyPrologue( + source: readonly Statement[], + target: Statement[], + ensureUseStrict?: boolean, + visitor?: (node: Node) => VisitResult, + ): number { const offset = copyStandardPrologue(source, target, 0, ensureUseStrict); return copyCustomPrologue(source, target, offset, visitor); } @@ -6879,8 +7842,16 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode * @param ensureUseStrict boolean determining whether the function need to add prologue-directives * @returns Count of how many directive statements were copied. */ - function copyStandardPrologue(source: readonly Statement[], target: Statement[], statementOffset = 0, ensureUseStrict?: boolean): number { - Debug.assert(target.length === 0, "Prologue directives should be at the first statement in the target statements array"); + function copyStandardPrologue( + source: readonly Statement[], + target: Statement[], + statementOffset = 0, + ensureUseStrict?: boolean, + ): number { + Debug.assert( + target.length === 0, + "Prologue directives should be at the first statement in the target statements array", + ); let foundUseStrict = false; const numStatements = source.length; while (statementOffset < numStatements) { @@ -6909,9 +7880,27 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode * @param statementOffset The offset at which to begin the copy. * @param visitor Optional callback used to visit any custom prologue directives. */ - function copyCustomPrologue(source: readonly Statement[], target: Statement[], statementOffset: number, visitor?: (node: Node) => VisitResult, filter?: (node: Statement) => boolean): number; - function copyCustomPrologue(source: readonly Statement[], target: Statement[], statementOffset: number | undefined, visitor?: (node: Node) => VisitResult, filter?: (node: Statement) => boolean): number | undefined; - function copyCustomPrologue(source: readonly Statement[], target: Statement[], statementOffset: number | undefined, visitor?: (node: Node) => VisitResult, filter: (node: Statement) => boolean = returnTrue): number | undefined { + function copyCustomPrologue( + source: readonly Statement[], + target: Statement[], + statementOffset: number, + visitor?: (node: Node) => VisitResult, + filter?: (node: Statement) => boolean, + ): number; + function copyCustomPrologue( + source: readonly Statement[], + target: Statement[], + statementOffset: number | undefined, + visitor?: (node: Node) => VisitResult, + filter?: (node: Statement) => boolean, + ): number | undefined; + function copyCustomPrologue( + source: readonly Statement[], + target: Statement[], + statementOffset: number | undefined, + visitor?: (node: Node) => VisitResult, + filter: (node: Statement) => boolean = returnTrue, + ): number | undefined { const numStatements = source.length; while (statementOffset !== undefined && statementOffset < numStatements) { const statement = source[statementOffset]; @@ -6959,9 +7948,18 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode return i; } - function mergeLexicalEnvironment(statements: NodeArray, declarations: readonly Statement[] | undefined): NodeArray; - function mergeLexicalEnvironment(statements: Statement[], declarations: readonly Statement[] | undefined): Statement[]; - function mergeLexicalEnvironment(statements: Statement[] | NodeArray, declarations: readonly Statement[] | undefined) { + function mergeLexicalEnvironment( + statements: NodeArray, + declarations: readonly Statement[] | undefined, + ): NodeArray; + function mergeLexicalEnvironment( + statements: Statement[], + declarations: readonly Statement[] | undefined, + ): Statement[]; + function mergeLexicalEnvironment( + statements: Statement[] | NodeArray, + declarations: readonly Statement[] | undefined, + ) { if (!some(declarations)) { return statements; } @@ -7003,9 +8001,16 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode // find standard prologues on right in the following order: standard directives, hoisted functions, hoisted variables, other custom const rightStandardPrologueEnd = findSpanEnd(declarations, isPrologueDirective, 0); const rightHoistedFunctionsEnd = findSpanEnd(declarations, isHoistedFunction, rightStandardPrologueEnd); - const rightHoistedVariablesEnd = findSpanEnd(declarations, isHoistedVariableStatement, rightHoistedFunctionsEnd); + const rightHoistedVariablesEnd = findSpanEnd( + declarations, + isHoistedVariableStatement, + rightHoistedFunctionsEnd, + ); const rightCustomPrologueEnd = findSpanEnd(declarations, isCustomPrologue, rightHoistedVariablesEnd); - Debug.assert(rightCustomPrologueEnd === declarations.length, "Expected declarations to be valid standard or custom prologues"); + Debug.assert( + rightCustomPrologueEnd === declarations.length, + "Expected declarations to be valid standard or custom prologues", + ); // splice prologues from the right into the left. We do this in reverse order // so that we don't need to recompute the index on the left when we insert items. @@ -7013,17 +8018,29 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode // splice other custom prologues from right into left if (rightCustomPrologueEnd > rightHoistedVariablesEnd) { - left.splice(leftHoistedVariablesEnd, 0, ...declarations.slice(rightHoistedVariablesEnd, rightCustomPrologueEnd)); + left.splice( + leftHoistedVariablesEnd, + 0, + ...declarations.slice(rightHoistedVariablesEnd, rightCustomPrologueEnd), + ); } // splice hoisted variables from right into left if (rightHoistedVariablesEnd > rightHoistedFunctionsEnd) { - left.splice(leftHoistedFunctionsEnd, 0, ...declarations.slice(rightHoistedFunctionsEnd, rightHoistedVariablesEnd)); + left.splice( + leftHoistedFunctionsEnd, + 0, + ...declarations.slice(rightHoistedFunctionsEnd, rightHoistedVariablesEnd), + ); } // splice hoisted functions from right into left if (rightHoistedFunctionsEnd > rightStandardPrologueEnd) { - left.splice(leftStandardPrologueEnd, 0, ...declarations.slice(rightStandardPrologueEnd, rightHoistedFunctionsEnd)); + left.splice( + leftStandardPrologueEnd, + 0, + ...declarations.slice(rightStandardPrologueEnd, rightHoistedFunctionsEnd), + ); } // splice standard prologues from right into left (that are not already in left) @@ -7062,44 +8079,197 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode else { modifierArray = modifiers; } - return isTypeParameterDeclaration(node) ? updateTypeParameterDeclaration(node, modifierArray, node.name, node.constraint, node.default) : - isParameter(node) ? updateParameterDeclaration(node, modifierArray, node.dotDotDotToken, node.name, node.questionToken, node.type, node.initializer) : - isConstructorTypeNode(node) ? updateConstructorTypeNode1(node, modifierArray, node.typeParameters, node.parameters, node.type) : - isPropertySignature(node) ? updatePropertySignature(node, modifierArray, node.name, node.questionToken, node.type) : - isPropertyDeclaration(node) ? updatePropertyDeclaration(node, modifierArray, node.name, node.questionToken ?? node.exclamationToken, node.type, node.initializer) : - isMethodSignature(node) ? updateMethodSignature(node, modifierArray, node.name, node.questionToken, node.typeParameters, node.parameters, node.type) : - isMethodDeclaration(node) ? updateMethodDeclaration(node, modifierArray, node.asteriskToken, node.name, node.questionToken, node.typeParameters, node.parameters, node.type, node.body) : - isConstructorDeclaration(node) ? updateConstructorDeclaration(node, modifierArray, node.parameters, node.body) : - isGetAccessorDeclaration(node) ? updateGetAccessorDeclaration(node, modifierArray, node.name, node.parameters, node.type, node.body) : - isSetAccessorDeclaration(node) ? updateSetAccessorDeclaration(node, modifierArray, node.name, node.parameters, node.body) : - isIndexSignatureDeclaration(node) ? updateIndexSignature(node, modifierArray, node.parameters, node.type) : - isFunctionExpression(node) ? updateFunctionExpression(node, modifierArray, node.asteriskToken, node.name, node.typeParameters, node.parameters, node.type, node.body) : - isArrowFunction(node) ? updateArrowFunction(node, modifierArray, node.typeParameters, node.parameters, node.type, node.equalsGreaterThanToken, node.body) : - isClassExpression(node) ? updateClassExpression(node, modifierArray, node.name, node.typeParameters, node.heritageClauses, node.members) : - isVariableStatement(node) ? updateVariableStatement(node, modifierArray, node.declarationList) : - isFunctionDeclaration(node) ? updateFunctionDeclaration(node, modifierArray, node.asteriskToken, node.name, node.typeParameters, node.parameters, node.type, node.body) : - isClassDeclaration(node) ? updateClassDeclaration(node, modifierArray, node.name, node.typeParameters, node.heritageClauses, node.members) : - isInterfaceDeclaration(node) ? updateInterfaceDeclaration(node, modifierArray, node.name, node.typeParameters, node.heritageClauses, node.members) : - isTypeAliasDeclaration(node) ? updateTypeAliasDeclaration(node, modifierArray, node.name, node.typeParameters, node.type) : - isEnumDeclaration(node) ? updateEnumDeclaration(node, modifierArray, node.name, node.members) : - isModuleDeclaration(node) ? updateModuleDeclaration(node, modifierArray, node.name, node.body) : - isImportEqualsDeclaration(node) ? updateImportEqualsDeclaration(node, modifierArray, node.isTypeOnly, node.name, node.moduleReference) : - isImportDeclaration(node) ? updateImportDeclaration(node, modifierArray, node.importClause, node.moduleSpecifier, node.assertClause) : - isExportAssignment(node) ? updateExportAssignment(node, modifierArray, node.expression) : - isExportDeclaration(node) ? updateExportDeclaration(node, modifierArray, node.isTypeOnly, node.exportClause, node.moduleSpecifier, node.assertClause) : - Debug.assertNever(node); + return isTypeParameterDeclaration(node) + ? updateTypeParameterDeclaration(node, modifierArray, node.name, node.constraint, node.default) + : isParameter(node) + ? updateParameterDeclaration( + node, + modifierArray, + node.dotDotDotToken, + node.name, + node.questionToken, + node.type, + node.initializer, + ) + : isConstructorTypeNode(node) + ? updateConstructorTypeNode1(node, modifierArray, node.typeParameters, node.parameters, node.type) + : isPropertySignature(node) + ? updatePropertySignature(node, modifierArray, node.name, node.questionToken, node.type) + : isPropertyDeclaration(node) + ? updatePropertyDeclaration( + node, + modifierArray, + node.name, + node.questionToken ?? node.exclamationToken, + node.type, + node.initializer, + ) + : isMethodSignature(node) + ? updateMethodSignature( + node, + modifierArray, + node.name, + node.questionToken, + node.typeParameters, + node.parameters, + node.type, + ) + : isMethodDeclaration(node) + ? updateMethodDeclaration( + node, + modifierArray, + node.asteriskToken, + node.name, + node.questionToken, + node.typeParameters, + node.parameters, + node.type, + node.body, + ) + : isConstructorDeclaration(node) + ? updateConstructorDeclaration(node, modifierArray, node.parameters, node.body) + : isGetAccessorDeclaration(node) + ? updateGetAccessorDeclaration(node, modifierArray, node.name, node.parameters, node.type, node.body) + : isSetAccessorDeclaration(node) + ? updateSetAccessorDeclaration(node, modifierArray, node.name, node.parameters, node.body) + : isIndexSignatureDeclaration(node) ? updateIndexSignature(node, modifierArray, node.parameters, node.type) + : isFunctionExpression(node) + ? updateFunctionExpression( + node, + modifierArray, + node.asteriskToken, + node.name, + node.typeParameters, + node.parameters, + node.type, + node.body, + ) + : isArrowFunction(node) + ? updateArrowFunction( + node, + modifierArray, + node.typeParameters, + node.parameters, + node.type, + node.equalsGreaterThanToken, + node.body, + ) + : isClassExpression(node) + ? updateClassExpression( + node, + modifierArray, + node.name, + node.typeParameters, + node.heritageClauses, + node.members, + ) + : isVariableStatement(node) ? updateVariableStatement(node, modifierArray, node.declarationList) + : isFunctionDeclaration(node) + ? updateFunctionDeclaration( + node, + modifierArray, + node.asteriskToken, + node.name, + node.typeParameters, + node.parameters, + node.type, + node.body, + ) + : isClassDeclaration(node) + ? updateClassDeclaration( + node, + modifierArray, + node.name, + node.typeParameters, + node.heritageClauses, + node.members, + ) + : isInterfaceDeclaration(node) + ? updateInterfaceDeclaration( + node, + modifierArray, + node.name, + node.typeParameters, + node.heritageClauses, + node.members, + ) + : isTypeAliasDeclaration(node) + ? updateTypeAliasDeclaration(node, modifierArray, node.name, node.typeParameters, node.type) + : isEnumDeclaration(node) ? updateEnumDeclaration(node, modifierArray, node.name, node.members) + : isModuleDeclaration(node) ? updateModuleDeclaration(node, modifierArray, node.name, node.body) + : isImportEqualsDeclaration(node) + ? updateImportEqualsDeclaration(node, modifierArray, node.isTypeOnly, node.name, node.moduleReference) + : isImportDeclaration(node) + ? updateImportDeclaration(node, modifierArray, node.importClause, node.moduleSpecifier, node.assertClause) + : isExportAssignment(node) ? updateExportAssignment(node, modifierArray, node.expression) + : isExportDeclaration(node) + ? updateExportDeclaration( + node, + modifierArray, + node.isTypeOnly, + node.exportClause, + node.moduleSpecifier, + node.assertClause, + ) + : Debug.assertNever(node); } function updateModifierLike(node: T, modifiers: readonly ModifierLike[]): T; function updateModifierLike(node: HasModifiers & HasDecorators, modifierArray: readonly ModifierLike[]) { - return isParameter(node) ? updateParameterDeclaration(node, modifierArray, node.dotDotDotToken, node.name, node.questionToken, node.type, node.initializer) : - isPropertyDeclaration(node) ? updatePropertyDeclaration(node, modifierArray, node.name, node.questionToken ?? node.exclamationToken, node.type, node.initializer) : - isMethodDeclaration(node) ? updateMethodDeclaration(node, modifierArray, node.asteriskToken, node.name, node.questionToken, node.typeParameters, node.parameters, node.type, node.body) : - isGetAccessorDeclaration(node) ? updateGetAccessorDeclaration(node, modifierArray, node.name, node.parameters, node.type, node.body) : - isSetAccessorDeclaration(node) ? updateSetAccessorDeclaration(node, modifierArray, node.name, node.parameters, node.body) : - isClassExpression(node) ? updateClassExpression(node, modifierArray, node.name, node.typeParameters, node.heritageClauses, node.members) : - isClassDeclaration(node) ? updateClassDeclaration(node, modifierArray, node.name, node.typeParameters, node.heritageClauses, node.members) : - Debug.assertNever(node); + return isParameter(node) + ? updateParameterDeclaration( + node, + modifierArray, + node.dotDotDotToken, + node.name, + node.questionToken, + node.type, + node.initializer, + ) + : isPropertyDeclaration(node) + ? updatePropertyDeclaration( + node, + modifierArray, + node.name, + node.questionToken ?? node.exclamationToken, + node.type, + node.initializer, + ) + : isMethodDeclaration(node) + ? updateMethodDeclaration( + node, + modifierArray, + node.asteriskToken, + node.name, + node.questionToken, + node.typeParameters, + node.parameters, + node.type, + node.body, + ) + : isGetAccessorDeclaration(node) + ? updateGetAccessorDeclaration(node, modifierArray, node.name, node.parameters, node.type, node.body) + : isSetAccessorDeclaration(node) + ? updateSetAccessorDeclaration(node, modifierArray, node.name, node.parameters, node.body) + : isClassExpression(node) + ? updateClassExpression( + node, + modifierArray, + node.name, + node.typeParameters, + node.heritageClauses, + node.members, + ) + : isClassDeclaration(node) + ? updateClassDeclaration( + node, + modifierArray, + node.name, + node.typeParameters, + node.heritageClauses, + node.members, + ) + : Debug.assertNever(node); } function asNodeArray(array: readonly T[]): NodeArray; @@ -7108,16 +8278,28 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode return array ? createNodeArray(array) : undefined; } - function asName(name: string | T): T | Identifier { - return typeof name === "string" ? createIdentifier(name) : - name; + function asName< + T extends + | DeclarationName + | Identifier + | BindingName + | PropertyName + | NoSubstitutionTemplateLiteral + | EntityName + | ThisTypeNode + | undefined, + >(name: string | T): T | Identifier { + return typeof name === "string" ? createIdentifier(name) + : name; } - function asExpression(value: string | number | boolean | T): T | StringLiteral | NumericLiteral | BooleanLiteral { - return typeof value === "string" ? createStringLiteral(value) : - typeof value === "number" ? createNumericLiteral(value) : - typeof value === "boolean" ? value ? createTrue() : createFalse() : - value; + function asExpression( + value: string | number | boolean | T, + ): T | StringLiteral | NumericLiteral | BooleanLiteral { + return typeof value === "string" ? createStringLiteral(value) + : typeof value === "number" ? createNumericLiteral(value) + : typeof value === "boolean" ? value ? createTrue() : createFalse() + : value; } function asInitializer(node: Expression | undefined) { @@ -7131,11 +8313,15 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode function asEmbeddedStatement(statement: T): T | EmptyStatement; function asEmbeddedStatement(statement: T | undefined): T | EmptyStatement | undefined; function asEmbeddedStatement(statement: T | undefined): T | EmptyStatement | undefined { - return statement && isNotEmittedStatement(statement) ? setTextRange(setOriginalNode(createEmptyStatement(), statement), statement) : statement; + return statement && isNotEmittedStatement(statement) + ? setTextRange(setOriginalNode(createEmptyStatement(), statement), statement) : statement; } function asVariableDeclaration(variableDeclaration: string | BindingName | VariableDeclaration | undefined) { - if (typeof variableDeclaration === "string" || variableDeclaration && !isVariableDeclaration(variableDeclaration)) { + if ( + typeof variableDeclaration === "string" + || variableDeclaration && !isVariableDeclaration(variableDeclaration) + ) { return createVariableDeclaration( variableDeclaration, /*exclamationToken*/ undefined, @@ -7274,7 +8460,8 @@ function propagatePropertyNameFlagsOfChild(node: PropertyName, transformFlags: T function propagateChildFlags(child: Node | undefined): TransformFlags { if (!child) return TransformFlags.None; const childFlags = child.transformFlags & ~getTransformFlagsSubtreeExclusions(child.kind); - return isNamedDeclaration(child) && isPropertyName(child.name) ? propagatePropertyNameFlagsOfChild(child.name, childFlags) : childFlags; + return isNamedDeclaration(child) && isPropertyName(child.name) + ? propagatePropertyNameFlagsOfChild(child.name, childFlags) : childFlags; } function propagateChildrenFlags(children: NodeArray | undefined): TransformFlags { @@ -7386,10 +8573,22 @@ export const factory = createNodeFactory(NodeFactoryFlags.NoIndentationOnFreshPr /** @deprecated */ export function createUnparsedSourceFile(text: string): UnparsedSource; /** @deprecated */ -export function createUnparsedSourceFile(inputFile: InputFiles, type: "js" | "dts", stripInternal?: boolean): UnparsedSource; +export function createUnparsedSourceFile( + inputFile: InputFiles, + type: "js" | "dts", + stripInternal?: boolean, +): UnparsedSource; /** @deprecated */ -export function createUnparsedSourceFile(text: string, mapPath: string | undefined, map: string | undefined): UnparsedSource; -export function createUnparsedSourceFile(textOrInputFiles: string | InputFiles, mapPathOrType?: string, mapTextOrStripInternal?: string | boolean): UnparsedSource { +export function createUnparsedSourceFile( + text: string, + mapPath: string | undefined, + map: string | undefined, +): UnparsedSource; +export function createUnparsedSourceFile( + textOrInputFiles: string | InputFiles, + mapPathOrType?: string, + mapTextOrStripInternal?: string | boolean, +): UnparsedSource { let stripInternal: boolean | undefined; let bundleFileInfo: BundleFileInfo | undefined; let fileName: string; @@ -7404,14 +8603,17 @@ export function createUnparsedSourceFile(textOrInputFiles: string | InputFiles, if (!isString(textOrInputFiles)) { Debug.assert(mapPathOrType === "js" || mapPathOrType === "dts"); fileName = (mapPathOrType === "js" ? textOrInputFiles.javascriptPath : textOrInputFiles.declarationPath) || ""; - sourceMapPath = mapPathOrType === "js" ? textOrInputFiles.javascriptMapPath : textOrInputFiles.declarationMapPath; + sourceMapPath = mapPathOrType === "js" ? textOrInputFiles.javascriptMapPath + : textOrInputFiles.declarationMapPath; getText = () => mapPathOrType === "js" ? textOrInputFiles.javascriptText : textOrInputFiles.declarationText; - getSourceMapText = () => mapPathOrType === "js" ? textOrInputFiles.javascriptMapText : textOrInputFiles.declarationMapText; + getSourceMapText = () => + mapPathOrType === "js" ? textOrInputFiles.javascriptMapText : textOrInputFiles.declarationMapText; length = () => getText!().length; if (textOrInputFiles.buildInfo && textOrInputFiles.buildInfo.bundle) { Debug.assert(mapTextOrStripInternal === undefined || typeof mapTextOrStripInternal === "boolean"); stripInternal = mapTextOrStripInternal; - bundleFileInfo = mapPathOrType === "js" ? textOrInputFiles.buildInfo.bundle.js : textOrInputFiles.buildInfo.bundle.dts; + bundleFileInfo = mapPathOrType === "js" ? textOrInputFiles.buildInfo.bundle.js + : textOrInputFiles.buildInfo.bundle.dts; oldFileOfCurrentEmit = textOrInputFiles.oldFileOfCurrentEmit; } } @@ -7422,9 +8624,9 @@ export function createUnparsedSourceFile(textOrInputFiles: string | InputFiles, sourceMapPath = mapPathOrType; sourceMapText = mapTextOrStripInternal as string; } - const node = oldFileOfCurrentEmit ? - parseOldFileOfCurrentEmit(Debug.checkDefined(bundleFileInfo)) : - parseUnparsedSourceFile(bundleFileInfo, stripInternal, length); + const node = oldFileOfCurrentEmit + ? parseOldFileOfCurrentEmit(Debug.checkDefined(bundleFileInfo)) + : parseUnparsedSourceFile(bundleFileInfo, stripInternal, length); node.fileName = fileName; node.sourceMapPath = sourceMapPath; node.oldFileOfCurrentEmit = oldFileOfCurrentEmit; @@ -7441,7 +8643,11 @@ export function createUnparsedSourceFile(textOrInputFiles: string | InputFiles, return node; } -function parseUnparsedSourceFile(bundleFileInfo: BundleFileInfo | undefined, stripInternal: boolean | undefined, length: number | (() => number)) { +function parseUnparsedSourceFile( + bundleFileInfo: BundleFileInfo | undefined, + stripInternal: boolean | undefined, + length: number | (() => number), +) { let prologues: UnparsedPrologue[] | undefined; let helpers: UnscopedEmitHelper[] | undefined; let referencedFiles: FileReference[] | undefined; @@ -7469,10 +8675,20 @@ function parseUnparsedSourceFile(bundleFileInfo: BundleFileInfo | undefined, str typeReferenceDirectives = append(typeReferenceDirectives, { pos: -1, end: -1, fileName: section.data }); break; case BundleFileSectionKind.TypeResolutionModeImport: - typeReferenceDirectives = append(typeReferenceDirectives, { pos: -1, end: -1, fileName: section.data, resolutionMode: ModuleKind.ESNext }); + typeReferenceDirectives = append(typeReferenceDirectives, { + pos: -1, + end: -1, + fileName: section.data, + resolutionMode: ModuleKind.ESNext, + }); break; case BundleFileSectionKind.TypeResolutionModeRequire: - typeReferenceDirectives = append(typeReferenceDirectives, { pos: -1, end: -1, fileName: section.data, resolutionMode: ModuleKind.CommonJS }); + typeReferenceDirectives = append(typeReferenceDirectives, { + pos: -1, + end: -1, + fileName: section.data, + resolutionMode: ModuleKind.CommonJS, + }); break; case BundleFileSectionKind.Lib: libReferenceDirectives = append(libReferenceDirectives, { pos: -1, end: -1, fileName: section.data }); @@ -7481,7 +8697,13 @@ function parseUnparsedSourceFile(bundleFileInfo: BundleFileInfo | undefined, str let prependTexts: UnparsedTextLike[] | undefined; for (const text of section.texts) { if (!stripInternal || text.kind !== BundleFileSectionKind.Internal) { - prependTexts = append(prependTexts, setTextRange(factory.createUnparsedTextLike(text.data, text.kind === BundleFileSectionKind.Internal), text)); + prependTexts = append( + prependTexts, + setTextRange( + factory.createUnparsedTextLike(text.data, text.kind === BundleFileSectionKind.Internal), + text, + ), + ); } } prependChildren = addRange(prependChildren, prependTexts); @@ -7495,7 +8717,13 @@ function parseUnparsedSourceFile(bundleFileInfo: BundleFileInfo | undefined, str // falls through case BundleFileSectionKind.Text: - texts = append(texts, setTextRange(factory.createUnparsedTextLike(section.data, section.kind === BundleFileSectionKind.Internal), section)); + texts = append( + texts, + setTextRange( + factory.createUnparsedTextLike(section.data, section.kind === BundleFileSectionKind.Internal), + section, + ), + ); break; default: Debug.assertNever(section); @@ -7508,7 +8736,11 @@ function parseUnparsedSourceFile(bundleFileInfo: BundleFileInfo | undefined, str texts = [textNode]; } - const node = parseNodeFactory.createUnparsedSource(prologues ?? emptyArray, /*syntheticReferences*/ undefined, texts); + const node = parseNodeFactory.createUnparsedSource( + prologues ?? emptyArray, + /*syntheticReferences*/ undefined, + texts, + ); setEachParent(prologues, node); setEachParent(texts, node); setEachParent(prependChildren, node); @@ -7527,7 +8759,13 @@ function parseOldFileOfCurrentEmit(bundleFileInfo: BundleFileInfo) { switch (section.kind) { case BundleFileSectionKind.Internal: case BundleFileSectionKind.Text: - texts = append(texts, setTextRange(factory.createUnparsedTextLike(section.data, section.kind === BundleFileSectionKind.Internal), section)); + texts = append( + texts, + setTextRange( + factory.createUnparsedTextLike(section.data, section.kind === BundleFileSectionKind.Internal), + section, + ), + ); break; case BundleFileSectionKind.NoDefaultLib: @@ -7536,7 +8774,10 @@ function parseOldFileOfCurrentEmit(bundleFileInfo: BundleFileInfo) { case BundleFileSectionKind.TypeResolutionModeImport: case BundleFileSectionKind.TypeResolutionModeRequire: case BundleFileSectionKind.Lib: - syntheticReferences = append(syntheticReferences, setTextRange(factory.createUnparsedSyntheticReference(section), section)); + syntheticReferences = append( + syntheticReferences, + setTextRange(factory.createUnparsedSyntheticReference(section), section), + ); break; // Ignore @@ -7553,7 +8794,10 @@ function parseOldFileOfCurrentEmit(bundleFileInfo: BundleFileInfo) { const node = factory.createUnparsedSource(emptyArray, syntheticReferences, texts ?? emptyArray); setEachParent(syntheticReferences, node); setEachParent(texts, node); - node.helpers = map(bundleFileInfo.sources && bundleFileInfo.sources.helpers, name => getAllUnscopedEmitHelpers().get(name)!); + node.helpers = map( + bundleFileInfo.sources && bundleFileInfo.sources.helpers, + name => getAllUnscopedEmitHelpers().get(name)!, + ); return node; } @@ -7589,16 +8833,16 @@ export function createInputFiles( declarationMapPath?: string, declarationMapTextOrBuildInfoPath?: string, ): InputFiles { - return !isString(javascriptTextOrReadFileText) ? - createInputFilesWithFilePaths( + return !isString(javascriptTextOrReadFileText) + ? createInputFilesWithFilePaths( javascriptTextOrReadFileText, declarationTextOrJavascriptPath, javascriptMapPath, javascriptMapTextOrDeclarationPath!, declarationMapPath, declarationMapTextOrBuildInfoPath, - ) : - createInputFilesWithFileTexts( + ) + : createInputFilesWithFileTexts( /*javascriptPath*/ undefined, javascriptTextOrReadFileText, javascriptMapPath, @@ -7696,8 +8940,16 @@ let SourceMapSource: new (fileName: string, text: string, skipTrivia?: (pos: num /** * Create an external source map source file reference */ -export function createSourceMapSource(fileName: string, text: string, skipTrivia?: (pos: number) => number): SourceMapSource { - return new (SourceMapSource || (SourceMapSource = objectAllocator.getSourceMapSourceConstructor()))(fileName, text, skipTrivia); +export function createSourceMapSource( + fileName: string, + text: string, + skipTrivia?: (pos: number) => number, +): SourceMapSource { + return new (SourceMapSource || (SourceMapSource = objectAllocator.getSourceMapSourceConstructor()))( + fileName, + text, + skipTrivia, + ); } // Utilities @@ -7770,7 +9022,10 @@ function mergeEmitNode(sourceEmitNode: EmitNode, destEmitNode: EmitNode | undefi // `tokenSourceMapRanges` are merged with the destination if (tokenSourceMapRanges) { - destEmitNode.tokenSourceMapRanges = mergeTokenSourceMapRanges(tokenSourceMapRanges, destEmitNode.tokenSourceMapRanges!); + destEmitNode.tokenSourceMapRanges = mergeTokenSourceMapRanges( + tokenSourceMapRanges, + destEmitNode.tokenSourceMapRanges!, + ); } // `constantValue` overwrites the destination diff --git a/src/compiler/factory/parenthesizerRules.ts b/src/compiler/factory/parenthesizerRules.ts index b90cc220fb616..736259e17837b 100644 --- a/src/compiler/factory/parenthesizerRules.ts +++ b/src/compiler/factory/parenthesizerRules.ts @@ -120,7 +120,12 @@ export function createParenthesizerRules(factory: NodeFactory): ParenthesizerRul * @param isLeftSideOfBinary A value indicating whether the operand is the left side of the * BinaryExpression. */ - function binaryOperandNeedsParentheses(binaryOperator: SyntaxKind, operand: Expression, isLeftSideOfBinary: boolean, leftOperand: Expression | undefined) { + function binaryOperandNeedsParentheses( + binaryOperator: SyntaxKind, + operand: Expression, + isLeftSideOfBinary: boolean, + leftOperand: Expression | undefined, + ) { // If the operand has lower precedence, then it needs to be parenthesized to preserve the // intent of the expression. For example, if the operand is `a + b` and the operator is // `*`, then we need to parenthesize the operand to preserve the intended order of @@ -141,7 +146,10 @@ export function createParenthesizerRules(factory: NodeFactory): ParenthesizerRul const binaryOperatorPrecedence = getOperatorPrecedence(SyntaxKind.BinaryExpression, binaryOperator); const binaryOperatorAssociativity = getOperatorAssociativity(SyntaxKind.BinaryExpression, binaryOperator); const emittedOperand = skipPartiallyEmittedExpressions(operand); - if (!isLeftSideOfBinary && operand.kind === SyntaxKind.ArrowFunction && binaryOperatorPrecedence > OperatorPrecedence.Assignment) { + if ( + !isLeftSideOfBinary && operand.kind === SyntaxKind.ArrowFunction + && binaryOperatorPrecedence > OperatorPrecedence.Assignment + ) { // We need to parenthesize arrow functions on the right side to avoid it being // parsed as parenthesized expression: `a && (() => {})` return true; @@ -199,8 +207,12 @@ export function createParenthesizerRules(factory: NodeFactory): ParenthesizerRul // "a"+(1+2) => "a"+(1+2) // "a"+("b"+"c") => "a"+"b"+"c" if (binaryOperator === SyntaxKind.PlusToken) { - const leftKind = leftOperand ? getLiteralKindOfBinaryPlusOperand(leftOperand) : SyntaxKind.Unknown; - if (isLiteralKind(leftKind) && leftKind === getLiteralKindOfBinaryPlusOperand(emittedOperand)) { + const leftKind = leftOperand ? getLiteralKindOfBinaryPlusOperand(leftOperand) + : SyntaxKind.Unknown; + if ( + isLiteralKind(leftKind) + && leftKind === getLiteralKindOfBinaryPlusOperand(emittedOperand) + ) { return false; } } @@ -256,7 +268,10 @@ export function createParenthesizerRules(factory: NodeFactory): ParenthesizerRul return node.kind; } - if (node.kind === SyntaxKind.BinaryExpression && (node as BinaryExpression).operatorToken.kind === SyntaxKind.PlusToken) { + if ( + node.kind === SyntaxKind.BinaryExpression + && (node as BinaryExpression).operatorToken.kind === SyntaxKind.PlusToken + ) { if ((node as BinaryPlusExpression).cachedLiteralKind !== undefined) { return (node as BinaryPlusExpression).cachedLiteralKind; } @@ -283,7 +298,12 @@ export function createParenthesizerRules(factory: NodeFactory): ParenthesizerRul * @param isLeftSideOfBinary A value indicating whether the operand is the left side of the * BinaryExpression. */ - function parenthesizeBinaryOperand(binaryOperator: SyntaxKind, operand: Expression, isLeftSideOfBinary: boolean, leftOperand?: Expression) { + function parenthesizeBinaryOperand( + binaryOperator: SyntaxKind, + operand: Expression, + isLeftSideOfBinary: boolean, + leftOperand?: Expression, + ) { const skipped = skipPartiallyEmittedExpressions(operand); // If the resulting expression is already parenthesized, we do not need to do any further processing. @@ -300,7 +320,11 @@ export function createParenthesizerRules(factory: NodeFactory): ParenthesizerRul return parenthesizeBinaryOperand(binaryOperator, leftSide, /*isLeftSideOfBinary*/ true); } - function parenthesizeRightSideOfBinary(binaryOperator: SyntaxKind, leftSide: Expression | undefined, rightSide: Expression): Expression { + function parenthesizeRightSideOfBinary( + binaryOperator: SyntaxKind, + leftSide: Expression | undefined, + rightSide: Expression, + ): Expression { return parenthesizeBinaryOperand(binaryOperator, rightSide, /*isLeftSideOfBinary*/ false, leftSide); } @@ -398,12 +422,14 @@ export function createParenthesizerRules(factory: NodeFactory): ParenthesizerRul function parenthesizeOperandOfPostfixUnary(operand: Expression): LeftHandSideExpression { // TODO(rbuckton): Verifiy whether `setTextRange` is needed. - return isLeftHandSideExpression(operand) ? operand : setTextRange(factory.createParenthesizedExpression(operand), operand); + return isLeftHandSideExpression(operand) ? operand + : setTextRange(factory.createParenthesizedExpression(operand), operand); } function parenthesizeOperandOfPrefixUnary(operand: Expression): UnaryExpression { // TODO(rbuckton): Verifiy whether `setTextRange` is needed. - return isUnaryExpression(operand) ? operand : setTextRange(factory.createParenthesizedExpression(operand), operand); + return isUnaryExpression(operand) ? operand + : setTextRange(factory.createParenthesizedExpression(operand), operand); } function parenthesizeExpressionsOfCommaDelimitedList(elements: NodeArray): NodeArray { @@ -416,7 +442,8 @@ export function createParenthesizerRules(factory: NodeFactory): ParenthesizerRul const expressionPrecedence = getExpressionPrecedence(emittedExpression); const commaPrecedence = getOperatorPrecedence(SyntaxKind.BinaryExpression, SyntaxKind.CommaToken); // TODO(rbuckton): Verifiy whether `setTextRange` is needed. - return expressionPrecedence > commaPrecedence ? expression : setTextRange(factory.createParenthesizedExpression(expression), expression); + return expressionPrecedence > commaPrecedence ? expression + : setTextRange(factory.createParenthesizedExpression(expression), expression); } function parenthesizeExpressionOfExpressionStatement(expression: Expression): Expression { @@ -432,12 +459,19 @@ export function createParenthesizerRules(factory: NodeFactory): ParenthesizerRul emittedExpression.typeArguments, emittedExpression.arguments, ); - return factory.restoreOuterExpressions(expression, updated, OuterExpressionKinds.PartiallyEmittedExpressions); + return factory.restoreOuterExpressions( + expression, + updated, + OuterExpressionKinds.PartiallyEmittedExpressions, + ); } } const leftmostExpressionKind = getLeftmostExpression(emittedExpression, /*stopAtCallExpressions*/ false).kind; - if (leftmostExpressionKind === SyntaxKind.ObjectLiteralExpression || leftmostExpressionKind === SyntaxKind.FunctionExpression) { + if ( + leftmostExpressionKind === SyntaxKind.ObjectLiteralExpression + || leftmostExpressionKind === SyntaxKind.FunctionExpression + ) { // TODO(rbuckton): Verifiy whether `setTextRange` is needed. return setTextRange(factory.createParenthesizedExpression(expression), expression); } @@ -448,7 +482,12 @@ export function createParenthesizerRules(factory: NodeFactory): ParenthesizerRul function parenthesizeConciseBodyOfArrowFunction(body: Expression): Expression; function parenthesizeConciseBodyOfArrowFunction(body: ConciseBody): ConciseBody; function parenthesizeConciseBodyOfArrowFunction(body: ConciseBody): ConciseBody { - if (!isBlock(body) && (isCommaSequence(body) || getLeftmostExpression(body, /*stopAtCallExpressions*/ false).kind === SyntaxKind.ObjectLiteralExpression)) { + if ( + !isBlock(body) + && (isCommaSequence(body) + || getLeftmostExpression(body, /*stopAtCallExpressions*/ false).kind + === SyntaxKind.ObjectLiteralExpression) + ) { // TODO(rbuckton): Verifiy whether `setTextRange` is needed. return setTextRange(factory.createParenthesizedExpression(body), body); } @@ -609,11 +648,15 @@ export function createParenthesizerRules(factory: NodeFactory): ParenthesizerRul function hasJSDocPostfixQuestion(type: TypeNode | NamedTupleMember): boolean { if (isJSDocNullableType(type)) return type.postfix; if (isNamedTupleMember(type)) return hasJSDocPostfixQuestion(type.type); - if (isFunctionTypeNode(type) || isConstructorTypeNode(type) || isTypeOperatorNode(type)) return hasJSDocPostfixQuestion(type.type); + if (isFunctionTypeNode(type) || isConstructorTypeNode(type) || isTypeOperatorNode(type)) { + return hasJSDocPostfixQuestion(type.type); + } if (isConditionalTypeNode(type)) return hasJSDocPostfixQuestion(type.falseType); if (isUnionTypeNode(type)) return hasJSDocPostfixQuestion(last(type.types)); if (isIntersectionTypeNode(type)) return hasJSDocPostfixQuestion(last(type.types)); - if (isInferTypeNode(type)) return !!type.typeParameter.constraint && hasJSDocPostfixQuestion(type.typeParameter.constraint); + if (isInferTypeNode(type)) { + return !!type.typeParameter.constraint && hasJSDocPostfixQuestion(type.typeParameter.constraint); + } return false; } @@ -644,14 +687,17 @@ export function createParenthesizerRules(factory: NodeFactory): ParenthesizerRul // } function parenthesizeLeadingTypeArgument(node: TypeNode) { - return isFunctionOrConstructorTypeNode(node) && node.typeParameters ? factory.createParenthesizedType(node) : node; + return isFunctionOrConstructorTypeNode(node) && node.typeParameters ? factory.createParenthesizedType(node) + : node; } function parenthesizeOrdinalTypeArgument(node: TypeNode, i: number) { return i === 0 ? parenthesizeLeadingTypeArgument(node) : node; } - function parenthesizeTypeArguments(typeArguments: NodeArray | undefined): NodeArray | undefined { + function parenthesizeTypeArguments( + typeArguments: NodeArray | undefined, + ): NodeArray | undefined { if (some(typeArguments)) { return factory.createNodeArray(sameMap(typeArguments, parenthesizeOrdinalTypeArgument)); } diff --git a/src/compiler/factory/utilities.ts b/src/compiler/factory/utilities.ts index 779696dd36320..8fe52b3cdfdbe 100644 --- a/src/compiler/factory/utilities.ts +++ b/src/compiler/factory/utilities.ts @@ -185,11 +185,21 @@ import { /** @internal */ export function createEmptyExports(factory: NodeFactory) { - return factory.createExportDeclaration(/*modifiers*/ undefined, /*isTypeOnly*/ false, factory.createNamedExports([]), /*moduleSpecifier*/ undefined); + return factory.createExportDeclaration( + /*modifiers*/ undefined, + /*isTypeOnly*/ false, + factory.createNamedExports([]), + /*moduleSpecifier*/ undefined, + ); } /** @internal */ -export function createMemberAccessForPropertyName(factory: NodeFactory, target: Expression, memberName: PropertyName, location?: TextRange): MemberExpression { +export function createMemberAccessForPropertyName( + factory: NodeFactory, + target: Expression, + memberName: PropertyName, + location?: TextRange, +): MemberExpression { if (isComputedPropertyName(memberName)) { return setTextRange(factory.createElementAccessExpression(target, memberName.expression), location); } @@ -216,7 +226,11 @@ function createReactNamespace(reactNamespace: string, parent: JsxOpeningLikeElem return react; } -function createJsxFactoryExpressionFromEntityName(factory: NodeFactory, jsxFactory: EntityName, parent: JsxOpeningLikeElement | JsxOpeningFragment): Expression { +function createJsxFactoryExpressionFromEntityName( + factory: NodeFactory, + jsxFactory: EntityName, + parent: JsxOpeningLikeElement | JsxOpeningFragment, +): Expression { if (isQualifiedName(jsxFactory)) { const left = createJsxFactoryExpressionFromEntityName(factory, jsxFactory.left, parent); const right = factory.createIdentifier(idText(jsxFactory.right)) as Mutable; @@ -229,26 +243,43 @@ function createJsxFactoryExpressionFromEntityName(factory: NodeFactory, jsxFacto } /** @internal */ -export function createJsxFactoryExpression(factory: NodeFactory, jsxFactoryEntity: EntityName | undefined, reactNamespace: string, parent: JsxOpeningLikeElement | JsxOpeningFragment): Expression { - return jsxFactoryEntity ? - createJsxFactoryExpressionFromEntityName(factory, jsxFactoryEntity, parent) : - factory.createPropertyAccessExpression( +export function createJsxFactoryExpression( + factory: NodeFactory, + jsxFactoryEntity: EntityName | undefined, + reactNamespace: string, + parent: JsxOpeningLikeElement | JsxOpeningFragment, +): Expression { + return jsxFactoryEntity + ? createJsxFactoryExpressionFromEntityName(factory, jsxFactoryEntity, parent) + : factory.createPropertyAccessExpression( createReactNamespace(reactNamespace, parent), "createElement", ); } -function createJsxFragmentFactoryExpression(factory: NodeFactory, jsxFragmentFactoryEntity: EntityName | undefined, reactNamespace: string, parent: JsxOpeningLikeElement | JsxOpeningFragment): Expression { - return jsxFragmentFactoryEntity ? - createJsxFactoryExpressionFromEntityName(factory, jsxFragmentFactoryEntity, parent) : - factory.createPropertyAccessExpression( +function createJsxFragmentFactoryExpression( + factory: NodeFactory, + jsxFragmentFactoryEntity: EntityName | undefined, + reactNamespace: string, + parent: JsxOpeningLikeElement | JsxOpeningFragment, +): Expression { + return jsxFragmentFactoryEntity + ? createJsxFactoryExpressionFromEntityName(factory, jsxFragmentFactoryEntity, parent) + : factory.createPropertyAccessExpression( createReactNamespace(reactNamespace, parent), "Fragment", ); } /** @internal */ -export function createExpressionForJsxElement(factory: NodeFactory, callee: Expression, tagName: Expression, props: Expression | undefined, children: readonly Expression[] | undefined, location: TextRange): LeftHandSideExpression { +export function createExpressionForJsxElement( + factory: NodeFactory, + callee: Expression, + tagName: Expression, + props: Expression | undefined, + children: readonly Expression[] | undefined, + location: TextRange, +): LeftHandSideExpression { const argumentsList = [tagName]; if (props) { argumentsList.push(props); @@ -281,8 +312,21 @@ export function createExpressionForJsxElement(factory: NodeFactory, callee: Expr } /** @internal */ -export function createExpressionForJsxFragment(factory: NodeFactory, jsxFactoryEntity: EntityName | undefined, jsxFragmentFactoryEntity: EntityName | undefined, reactNamespace: string, children: readonly Expression[], parentElement: JsxOpeningFragment, location: TextRange): LeftHandSideExpression { - const tagName = createJsxFragmentFactoryExpression(factory, jsxFragmentFactoryEntity, reactNamespace, parentElement); +export function createExpressionForJsxFragment( + factory: NodeFactory, + jsxFactoryEntity: EntityName | undefined, + jsxFragmentFactoryEntity: EntityName | undefined, + reactNamespace: string, + children: readonly Expression[], + parentElement: JsxOpeningFragment, + location: TextRange, +): LeftHandSideExpression { + const tagName = createJsxFragmentFactoryExpression( + factory, + jsxFragmentFactoryEntity, + reactNamespace, + parentElement, + ); const argumentsList = [tagName, factory.createNull()]; if (children && children.length > 0) { @@ -310,7 +354,11 @@ export function createExpressionForJsxFragment(factory: NodeFactory, jsxFactoryE // Utilities /** @internal */ -export function createForOfBindingStatement(factory: NodeFactory, node: ForInitializer, boundValue: Expression): Statement { +export function createForOfBindingStatement( + factory: NodeFactory, + node: ForInitializer, + boundValue: Expression, +): Statement { if (isVariableDeclarationList(node)) { const firstDeclaration = first(node.declarations); const updatedDeclaration = factory.updateVariableDeclaration( @@ -337,7 +385,10 @@ export function createForOfBindingStatement(factory: NodeFactory, node: ForIniti /** @internal */ export function insertLeadingStatement(factory: NodeFactory, dest: Statement, source: Statement): Block { if (isBlock(dest)) { - return factory.updateBlock(dest, setTextRange(factory.createNodeArray([source, ...dest.statements]), dest.statements)); + return factory.updateBlock( + dest, + setTextRange(factory.createNodeArray([source, ...dest.statements]), dest.statements), + ); } else { return factory.createBlock(factory.createNodeArray([dest, source]), /*multiLine*/ true); @@ -359,13 +410,19 @@ export function createExpressionFromEntityName(factory: NodeFactory, node: Entit } /** @internal */ -export function createExpressionForPropertyName(factory: NodeFactory, memberName: Exclude): Expression { +export function createExpressionForPropertyName( + factory: NodeFactory, + memberName: Exclude, +): Expression { if (isIdentifier(memberName)) { return factory.createStringLiteralFromNode(memberName); } else if (isComputedPropertyName(memberName)) { // TODO(rbuckton): Does this need to be parented? - return setParent(setTextRange(factory.cloneNode(memberName.expression), memberName.expression), memberName.expression.parent); + return setParent( + setTextRange(factory.cloneNode(memberName.expression), memberName.expression), + memberName.expression.parent, + ); } else { // TODO(rbuckton): Does this need to be parented? @@ -373,7 +430,13 @@ export function createExpressionForPropertyName(factory: NodeFactory, memberName } } -function createExpressionForAccessorDeclaration(factory: NodeFactory, properties: NodeArray, property: AccessorDeclaration & { readonly name: Exclude; }, receiver: Expression, multiLine: boolean) { +function createExpressionForAccessorDeclaration( + factory: NodeFactory, + properties: NodeArray, + property: AccessorDeclaration & { readonly name: Exclude; }, + receiver: Expression, + multiLine: boolean, +) { const { firstAccessor, getAccessor, setAccessor } = getAllAccessorDeclarations(properties, property); if (property === firstAccessor) { return setTextRange( @@ -422,7 +485,11 @@ function createExpressionForAccessorDeclaration(factory: NodeFactory, properties return undefined; } -function createExpressionForPropertyAssignment(factory: NodeFactory, property: PropertyAssignment, receiver: Expression) { +function createExpressionForPropertyAssignment( + factory: NodeFactory, + property: PropertyAssignment, + receiver: Expression, +) { return setOriginalNode( setTextRange( factory.createAssignment( @@ -435,7 +502,11 @@ function createExpressionForPropertyAssignment(factory: NodeFactory, property: P ); } -function createExpressionForShorthandPropertyAssignment(factory: NodeFactory, property: ShorthandPropertyAssignment, receiver: Expression) { +function createExpressionForShorthandPropertyAssignment( + factory: NodeFactory, + property: ShorthandPropertyAssignment, + receiver: Expression, +) { return setOriginalNode( setTextRange( factory.createAssignment( @@ -476,14 +547,25 @@ function createExpressionForMethodDeclaration(factory: NodeFactory, method: Meth } /** @internal */ -export function createExpressionForObjectLiteralElementLike(factory: NodeFactory, node: ObjectLiteralExpression, property: ObjectLiteralElementLike, receiver: Expression): Expression | undefined { +export function createExpressionForObjectLiteralElementLike( + factory: NodeFactory, + node: ObjectLiteralExpression, + property: ObjectLiteralElementLike, + receiver: Expression, +): Expression | undefined { if (property.name && isPrivateIdentifier(property.name)) { Debug.failBadSyntaxKind(property.name, "Private identifiers are not allowed in object literals."); } switch (property.kind) { case SyntaxKind.GetAccessor: case SyntaxKind.SetAccessor: - return createExpressionForAccessorDeclaration(factory, node.properties, property as typeof property & { readonly name: Exclude; }, receiver, !!node.multiLine); + return createExpressionForAccessorDeclaration( + factory, + node.properties, + property as typeof property & { readonly name: Exclude; }, + receiver, + !!node.multiLine, + ); case SyntaxKind.PropertyAssignment: return createExpressionForPropertyAssignment(factory, property, receiver); case SyntaxKind.ShorthandPropertyAssignment: @@ -527,17 +609,26 @@ export function createExpressionForObjectLiteralElementLike(factory: NodeFactory * * @internal */ -export function expandPreOrPostfixIncrementOrDecrementExpression(factory: NodeFactory, node: PrefixUnaryExpression | PostfixUnaryExpression, expression: Expression, recordTempVariable: (node: Identifier) => void, resultVariable: Identifier | undefined) { +export function expandPreOrPostfixIncrementOrDecrementExpression( + factory: NodeFactory, + node: PrefixUnaryExpression | PostfixUnaryExpression, + expression: Expression, + recordTempVariable: (node: Identifier) => void, + resultVariable: Identifier | undefined, +) { const operator = node.operator; - Debug.assert(operator === SyntaxKind.PlusPlusToken || operator === SyntaxKind.MinusMinusToken, "Expected 'node' to be a pre- or post-increment or pre- or post-decrement expression"); + Debug.assert( + operator === SyntaxKind.PlusPlusToken || operator === SyntaxKind.MinusMinusToken, + "Expected 'node' to be a pre- or post-increment or pre- or post-decrement expression", + ); const temp = factory.createTempVariable(recordTempVariable); expression = factory.createAssignment(temp, expression); setTextRange(expression, node.operand); - let operation: Expression = isPrefixUnaryExpression(node) ? - factory.createPrefixUnaryExpression(operator, temp) : - factory.createPostfixUnaryExpression(temp, operator); + let operation: Expression = isPrefixUnaryExpression(node) + ? factory.createPrefixUnaryExpression(operator, temp) + : factory.createPostfixUnaryExpression(temp, operator); setTextRange(operation, node); if (resultVariable) { @@ -612,12 +703,17 @@ export function startsWithUseStrict(statements: readonly Statement[]) { } /** @internal */ -export function isCommaExpression(node: Expression): node is BinaryExpression & { operatorToken: Token; } { - return node.kind === SyntaxKind.BinaryExpression && (node as BinaryExpression).operatorToken.kind === SyntaxKind.CommaToken; +export function isCommaExpression( + node: Expression, +): node is BinaryExpression & { operatorToken: Token; } { + return node.kind === SyntaxKind.BinaryExpression + && (node as BinaryExpression).operatorToken.kind === SyntaxKind.CommaToken; } /** @internal */ -export function isCommaSequence(node: Expression): node is BinaryExpression & { operatorToken: Token; } | CommaListExpression { +export function isCommaSequence( + node: Expression, +): node is BinaryExpression & { operatorToken: Token; } | CommaListExpression { return isCommaExpression(node) || isCommaListExpression(node); } @@ -709,11 +805,22 @@ export function hasRecordedExternalHelpers(sourceFile: SourceFile) { } /** @internal */ -export function createExternalHelpersImportDeclarationIfNeeded(nodeFactory: NodeFactory, helperFactory: EmitHelperFactory, sourceFile: SourceFile, compilerOptions: CompilerOptions, hasExportStarsToExportValues?: boolean, hasImportStar?: boolean, hasImportDefault?: boolean) { +export function createExternalHelpersImportDeclarationIfNeeded( + nodeFactory: NodeFactory, + helperFactory: EmitHelperFactory, + sourceFile: SourceFile, + compilerOptions: CompilerOptions, + hasExportStarsToExportValues?: boolean, + hasImportStar?: boolean, + hasImportDefault?: boolean, +) { if (compilerOptions.importHelpers && isEffectiveExternalModule(sourceFile, compilerOptions)) { let namedBindings: NamedImportBindings | undefined; const moduleKind = getEmitModuleKind(compilerOptions); - if ((moduleKind >= ModuleKind.ES2015 && moduleKind <= ModuleKind.ESNext) || sourceFile.impliedNodeFormat === ModuleKind.ESNext) { + if ( + (moduleKind >= ModuleKind.ES2015 && moduleKind <= ModuleKind.ESNext) + || sourceFile.impliedNodeFormat === ModuleKind.ESNext + ) { // use named imports const helpers = getEmitHelpers(sourceFile); if (helpers) { @@ -733,8 +840,16 @@ export function createExternalHelpersImportDeclarationIfNeeded(nodeFactory: Node namedBindings = nodeFactory.createNamedImports( map(helperNames, name => isFileLevelUniqueName(sourceFile, name) - ? nodeFactory.createImportSpecifier(/*isTypeOnly*/ false, /*propertyName*/ undefined, nodeFactory.createIdentifier(name)) - : nodeFactory.createImportSpecifier(/*isTypeOnly*/ false, nodeFactory.createIdentifier(name), helperFactory.getUnscopedHelperName(name))), + ? nodeFactory.createImportSpecifier( + /*isTypeOnly*/ false, + /*propertyName*/ undefined, + nodeFactory.createIdentifier(name), + ) + : nodeFactory.createImportSpecifier( + /*isTypeOnly*/ false, + nodeFactory.createIdentifier(name), + helperFactory.getUnscopedHelperName(name), + )), ); const parseNode = getOriginalNode(sourceFile, isSourceFile); const emitNode = getOrCreateEmitNode(parseNode); @@ -744,7 +859,13 @@ export function createExternalHelpersImportDeclarationIfNeeded(nodeFactory: Node } else { // use a namespace import - const externalHelpersModuleName = getOrCreateExternalHelpersModuleNameIfNeeded(nodeFactory, sourceFile, compilerOptions, hasExportStarsToExportValues, hasImportStar || hasImportDefault); + const externalHelpersModuleName = getOrCreateExternalHelpersModuleNameIfNeeded( + nodeFactory, + sourceFile, + compilerOptions, + hasExportStarsToExportValues, + hasImportStar || hasImportDefault, + ); if (externalHelpersModuleName) { namedBindings = nodeFactory.createNamespaceImport(externalHelpersModuleName); } @@ -763,7 +884,13 @@ export function createExternalHelpersImportDeclarationIfNeeded(nodeFactory: Node } /** @internal */ -export function getOrCreateExternalHelpersModuleNameIfNeeded(factory: NodeFactory, node: SourceFile, compilerOptions: CompilerOptions, hasExportStarsToExportValues?: boolean, hasImportStarOrImportDefault?: boolean) { +export function getOrCreateExternalHelpersModuleNameIfNeeded( + factory: NodeFactory, + node: SourceFile, + compilerOptions: CompilerOptions, + hasExportStarsToExportValues?: boolean, + hasImportStarOrImportDefault?: boolean, +) { if (compilerOptions.importHelpers && isEffectiveExternalModule(node, compilerOptions)) { const externalHelpersModuleName = getExternalHelpersModuleName(node); if (externalHelpersModuleName) { @@ -771,7 +898,8 @@ export function getOrCreateExternalHelpersModuleNameIfNeeded(factory: NodeFactor } const moduleKind = getEmitModuleKind(compilerOptions); - let create = (hasExportStarsToExportValues || (getESModuleInterop(compilerOptions) && hasImportStarOrImportDefault)) + let create = + (hasExportStarsToExportValues || (getESModuleInterop(compilerOptions) && hasImportStarOrImportDefault)) && moduleKind !== ModuleKind.System && (moduleKind < ModuleKind.ES2015 || node.impliedNodeFormat === ModuleKind.CommonJS); if (!create) { @@ -789,7 +917,8 @@ export function getOrCreateExternalHelpersModuleNameIfNeeded(factory: NodeFactor if (create) { const parseNode = getOriginalNode(node, isSourceFile); const emitNode = getOrCreateEmitNode(parseNode); - return emitNode.externalHelpersModuleName || (emitNode.externalHelpersModuleName = factory.createUniqueName(externalHelpersModuleNameText)); + return emitNode.externalHelpersModuleName + || (emitNode.externalHelpersModuleName = factory.createUniqueName(externalHelpersModuleNameText)); } } } @@ -799,11 +928,16 @@ export function getOrCreateExternalHelpersModuleNameIfNeeded(factory: NodeFactor * * @internal */ -export function getLocalNameForExternalImport(factory: NodeFactory, node: ImportDeclaration | ExportDeclaration | ImportEqualsDeclaration, sourceFile: SourceFile): Identifier | undefined { +export function getLocalNameForExternalImport( + factory: NodeFactory, + node: ImportDeclaration | ExportDeclaration | ImportEqualsDeclaration, + sourceFile: SourceFile, +): Identifier | undefined { const namespaceDeclaration = getNamespaceDeclarationNode(node); if (namespaceDeclaration && !isDefaultImport(node) && !isExportNamespaceAsDefaultDeclaration(node)) { const name = namespaceDeclaration.name; - return isGeneratedIdentifier(name) ? name : factory.createIdentifier(getSourceTextOfNodeFromSourceFile(sourceFile, name) || idText(name)); + return isGeneratedIdentifier(name) ? name + : factory.createIdentifier(getSourceTextOfNodeFromSourceFile(sourceFile, name) || idText(name)); } if (node.kind === SyntaxKind.ImportDeclaration && node.importClause) { return factory.getGeneratedNameForNode(node); @@ -824,7 +958,14 @@ export function getLocalNameForExternalImport(factory: NodeFactory, node: Import * * @internal */ -export function getExternalModuleNameLiteral(factory: NodeFactory, importNode: ImportDeclaration | ExportDeclaration | ImportEqualsDeclaration | ImportCall, sourceFile: SourceFile, host: EmitHost, resolver: EmitResolver, compilerOptions: CompilerOptions) { +export function getExternalModuleNameLiteral( + factory: NodeFactory, + importNode: ImportDeclaration | ExportDeclaration | ImportEqualsDeclaration | ImportCall, + sourceFile: SourceFile, + host: EmitHost, + resolver: EmitResolver, + compilerOptions: CompilerOptions, +) { const moduleName = getExternalModuleName(importNode); if (moduleName && isStringLiteral(moduleName)) { return tryGetModuleNameFromDeclaration(importNode, host, factory, resolver, compilerOptions) @@ -853,7 +994,12 @@ function tryRenameExternalModule(factory: NodeFactory, moduleName: LiteralExpres * * @internal */ -export function tryGetModuleNameFromFile(factory: NodeFactory, file: SourceFile | undefined, host: EmitHost, options: CompilerOptions): StringLiteral | undefined { +export function tryGetModuleNameFromFile( + factory: NodeFactory, + file: SourceFile | undefined, + host: EmitHost, + options: CompilerOptions, +): StringLiteral | undefined { if (!file) { return undefined; } @@ -866,8 +1012,19 @@ export function tryGetModuleNameFromFile(factory: NodeFactory, file: SourceFile return undefined; } -function tryGetModuleNameFromDeclaration(declaration: ImportEqualsDeclaration | ImportDeclaration | ExportDeclaration | ImportCall, host: EmitHost, factory: NodeFactory, resolver: EmitResolver, compilerOptions: CompilerOptions) { - return tryGetModuleNameFromFile(factory, resolver.getExternalModuleFileFromDeclaration(declaration), host, compilerOptions); +function tryGetModuleNameFromDeclaration( + declaration: ImportEqualsDeclaration | ImportDeclaration | ExportDeclaration | ImportCall, + host: EmitHost, + factory: NodeFactory, + resolver: EmitResolver, + compilerOptions: CompilerOptions, +) { + return tryGetModuleNameFromFile( + factory, + resolver.getExternalModuleFileFromDeclaration(declaration), + host, + compilerOptions, + ); } /** @@ -875,7 +1032,9 @@ function tryGetModuleNameFromDeclaration(declaration: ImportEqualsDeclaration | * * @internal */ -export function getInitializerOfBindingOrAssignmentElement(bindingElement: BindingOrAssignmentElement): Expression | undefined { +export function getInitializerOfBindingOrAssignmentElement( + bindingElement: BindingOrAssignmentElement, +): Expression | undefined { if (isDeclarationBindingElement(bindingElement)) { // `1` in `let { a = 1 } = ...` // `1` in `let { a: b = 1 } = ...` @@ -920,7 +1079,9 @@ export function getInitializerOfBindingOrAssignmentElement(bindingElement: Bindi * * @internal */ -export function getTargetOfBindingOrAssignmentElement(bindingElement: BindingOrAssignmentElement): BindingOrAssignmentElementTarget | undefined { +export function getTargetOfBindingOrAssignmentElement( + bindingElement: BindingOrAssignmentElement, +): BindingOrAssignmentElementTarget | undefined { if (isDeclarationBindingElement(bindingElement)) { // `a` in `let { a } = ...` // `a` in `let { a = 1 } = ...` @@ -997,7 +1158,9 @@ export function getTargetOfBindingOrAssignmentElement(bindingElement: BindingOrA * * @internal */ -export function getRestIndicatorOfBindingOrAssignmentElement(bindingElement: BindingOrAssignmentElement): BindingOrAssignmentElementRestIndicator | undefined { +export function getRestIndicatorOfBindingOrAssignmentElement( + bindingElement: BindingOrAssignmentElement, +): BindingOrAssignmentElementRestIndicator | undefined { switch (bindingElement.kind) { case SyntaxKind.Parameter: case SyntaxKind.BindingElement: @@ -1018,14 +1181,18 @@ export function getRestIndicatorOfBindingOrAssignmentElement(bindingElement: Bin * * @internal */ -export function getPropertyNameOfBindingOrAssignmentElement(bindingElement: BindingOrAssignmentElement): Exclude | undefined { +export function getPropertyNameOfBindingOrAssignmentElement( + bindingElement: BindingOrAssignmentElement, +): Exclude | undefined { const propertyName = tryGetPropertyNameOfBindingOrAssignmentElement(bindingElement); Debug.assert(!!propertyName || isSpreadAssignment(bindingElement), "Invalid property name for binding element."); return propertyName; } /** @internal */ -export function tryGetPropertyNameOfBindingOrAssignmentElement(bindingElement: BindingOrAssignmentElement): Exclude | undefined { +export function tryGetPropertyNameOfBindingOrAssignmentElement( + bindingElement: BindingOrAssignmentElement, +): Exclude | undefined { switch (bindingElement.kind) { case SyntaxKind.BindingElement: // `a` in `let { a: b } = ...` @@ -1086,7 +1253,9 @@ function isStringOrNumericLiteral(node: Node): node is StringLiteral | NumericLi * * @internal */ -export function getElementsOfBindingOrAssignmentPattern(name: BindingOrAssignmentPattern): readonly BindingOrAssignmentElement[] { +export function getElementsOfBindingOrAssignmentPattern( + name: BindingOrAssignmentPattern, +): readonly BindingOrAssignmentElement[] { switch (name.kind) { case SyntaxKind.ObjectBindingPattern: case SyntaxKind.ArrayBindingPattern: @@ -1182,7 +1351,9 @@ export function isModuleName(node: Node): node is ModuleName { } /** @internal */ -export function isLiteralTypeLikeExpression(node: Node): node is NullLiteral | BooleanLiteral | LiteralExpression | PrefixUnaryExpression { +export function isLiteralTypeLikeExpression( + node: Node, +): node is NullLiteral | BooleanLiteral | LiteralExpression | PrefixUnaryExpression { const kind = node.kind; return kind === SyntaxKind.NullKeyword || kind === SyntaxKind.TrueKeyword @@ -1290,7 +1461,15 @@ export function isBinaryOperatorToken(node: Node): node is BinaryOperatorToken { return isBinaryOperator(node.kind); } -type BinaryExpressionState = (machine: BinaryExpressionStateMachine, stackIndex: number, stateStack: BinaryExpressionState[], nodeStack: BinaryExpression[], userStateStack: TState[], resultHolder: { value: TResult; }, outerState: TOuterState) => number; +type BinaryExpressionState = ( + machine: BinaryExpressionStateMachine, + stackIndex: number, + stateStack: BinaryExpressionState[], + nodeStack: BinaryExpression[], + userStateStack: TState[], + resultHolder: { value: TResult; }, + outerState: TOuterState, +) => number; namespace BinaryExpressionState { /** @@ -1299,7 +1478,15 @@ namespace BinaryExpressionState { * @param frame The current frame * @returns The new frame */ - export function enter(machine: BinaryExpressionStateMachine, stackIndex: number, stateStack: BinaryExpressionState[], nodeStack: BinaryExpression[], userStateStack: TState[], _resultHolder: { value: TResult; }, outerState: TOuterState): number { + export function enter( + machine: BinaryExpressionStateMachine, + stackIndex: number, + stateStack: BinaryExpressionState[], + nodeStack: BinaryExpression[], + userStateStack: TState[], + _resultHolder: { value: TResult; }, + outerState: TOuterState, + ): number { const prevUserState = stackIndex > 0 ? userStateStack[stackIndex - 1] : undefined; Debug.assertEqual(stateStack[stackIndex], enter); userStateStack[stackIndex] = machine.onEnter(nodeStack[stackIndex], prevUserState, outerState); @@ -1313,7 +1500,15 @@ namespace BinaryExpressionState { * @param frame The current frame * @returns The new frame */ - export function left(machine: BinaryExpressionStateMachine, stackIndex: number, stateStack: BinaryExpressionState[], nodeStack: BinaryExpression[], userStateStack: TState[], _resultHolder: { value: TResult; }, _outerState: TOuterState): number { + export function left( + machine: BinaryExpressionStateMachine, + stackIndex: number, + stateStack: BinaryExpressionState[], + nodeStack: BinaryExpression[], + userStateStack: TState[], + _resultHolder: { value: TResult; }, + _outerState: TOuterState, + ): number { Debug.assertEqual(stateStack[stackIndex], left); Debug.assertIsDefined(machine.onLeft); stateStack[stackIndex] = nextState(machine, left); @@ -1331,7 +1526,15 @@ namespace BinaryExpressionState { * @param frame The current frame * @returns The new frame */ - export function operator(machine: BinaryExpressionStateMachine, stackIndex: number, stateStack: BinaryExpressionState[], nodeStack: BinaryExpression[], userStateStack: TState[], _resultHolder: { value: TResult; }, _outerState: TOuterState): number { + export function operator( + machine: BinaryExpressionStateMachine, + stackIndex: number, + stateStack: BinaryExpressionState[], + nodeStack: BinaryExpression[], + userStateStack: TState[], + _resultHolder: { value: TResult; }, + _outerState: TOuterState, + ): number { Debug.assertEqual(stateStack[stackIndex], operator); Debug.assertIsDefined(machine.onOperator); stateStack[stackIndex] = nextState(machine, operator); @@ -1345,11 +1548,23 @@ namespace BinaryExpressionState { * @param frame The current frame * @returns The new frame */ - export function right(machine: BinaryExpressionStateMachine, stackIndex: number, stateStack: BinaryExpressionState[], nodeStack: BinaryExpression[], userStateStack: TState[], _resultHolder: { value: TResult; }, _outerState: TOuterState): number { + export function right( + machine: BinaryExpressionStateMachine, + stackIndex: number, + stateStack: BinaryExpressionState[], + nodeStack: BinaryExpression[], + userStateStack: TState[], + _resultHolder: { value: TResult; }, + _outerState: TOuterState, + ): number { Debug.assertEqual(stateStack[stackIndex], right); Debug.assertIsDefined(machine.onRight); stateStack[stackIndex] = nextState(machine, right); - const nextNode = machine.onRight(nodeStack[stackIndex].right, userStateStack[stackIndex], nodeStack[stackIndex]); + const nextNode = machine.onRight( + nodeStack[stackIndex].right, + userStateStack[stackIndex], + nodeStack[stackIndex], + ); if (nextNode) { checkCircularity(stackIndex, nodeStack, nextNode); return pushStack(stackIndex, stateStack, nodeStack, userStateStack, nextNode); @@ -1363,7 +1578,15 @@ namespace BinaryExpressionState { * @param frame The current frame * @returns The new frame */ - export function exit(machine: BinaryExpressionStateMachine, stackIndex: number, stateStack: BinaryExpressionState[], nodeStack: BinaryExpression[], userStateStack: TState[], resultHolder: { value: TResult; }, _outerState: TOuterState): number { + export function exit( + machine: BinaryExpressionStateMachine, + stackIndex: number, + stateStack: BinaryExpressionState[], + nodeStack: BinaryExpression[], + userStateStack: TState[], + resultHolder: { value: TResult; }, + _outerState: TOuterState, + ): number { Debug.assertEqual(stateStack[stackIndex], exit); stateStack[stackIndex] = nextState(machine, exit); const result = machine.onExit(nodeStack[stackIndex], userStateStack[stackIndex]); @@ -1384,12 +1607,23 @@ namespace BinaryExpressionState { * Handles a frame that is already done. * @returns The `done` state. */ - export function done(_machine: BinaryExpressionStateMachine, stackIndex: number, stateStack: BinaryExpressionState[], _nodeStack: BinaryExpression[], _userStateStack: TState[], _resultHolder: { value: TResult; }, _outerState: TOuterState): number { + export function done( + _machine: BinaryExpressionStateMachine, + stackIndex: number, + stateStack: BinaryExpressionState[], + _nodeStack: BinaryExpression[], + _userStateStack: TState[], + _resultHolder: { value: TResult; }, + _outerState: TOuterState, + ): number { Debug.assertEqual(stateStack[stackIndex], done); return stackIndex; } - export function nextState(machine: BinaryExpressionStateMachine, currentState: BinaryExpressionState) { + export function nextState( + machine: BinaryExpressionStateMachine, + currentState: BinaryExpressionState, + ) { switch (currentState) { case enter: if (machine.onLeft) return left; @@ -1411,7 +1645,13 @@ namespace BinaryExpressionState { } } - function pushStack(stackIndex: number, stateStack: BinaryExpressionState[], nodeStack: BinaryExpression[], userStateStack: TState[], node: BinaryExpression) { + function pushStack( + stackIndex: number, + stateStack: BinaryExpressionState[], + nodeStack: BinaryExpression[], + userStateStack: TState[], + node: BinaryExpression, + ) { stackIndex++; stateStack[stackIndex] = enter; nodeStack[stackIndex] = node; @@ -1435,9 +1675,15 @@ namespace BinaryExpressionState { class BinaryExpressionStateMachine { constructor( readonly onEnter: (node: BinaryExpression, prev: TState | undefined, outerState: TOuterState) => TState, - readonly onLeft: ((left: Expression, userState: TState, node: BinaryExpression) => BinaryExpression | void) | undefined, - readonly onOperator: ((operatorToken: BinaryOperatorToken, userState: TState, node: BinaryExpression) => void) | undefined, - readonly onRight: ((right: Expression, userState: TState, node: BinaryExpression) => BinaryExpression | void) | undefined, + readonly onLeft: + | ((left: Expression, userState: TState, node: BinaryExpression) => BinaryExpression | void) + | undefined, + readonly onOperator: + | ((operatorToken: BinaryOperatorToken, userState: TState, node: BinaryExpression) => void) + | undefined, + readonly onRight: + | ((right: Expression, userState: TState, node: BinaryExpression) => BinaryExpression | void) + | undefined, readonly onExit: (node: BinaryExpression, userState: TState) => TResult, readonly foldState: ((userState: TState, result: TResult, side: "left" | "right") => TState) | undefined, ) { @@ -1501,7 +1747,15 @@ export function createBinaryExpressionTrampoline( const userStateStack: TState[] = [undefined!]; let stackIndex = 0; while (stateStack[stackIndex] !== BinaryExpressionState.done) { - stackIndex = stateStack[stackIndex](machine, stackIndex, stateStack, nodeStack, userStateStack, resultHolder, outerState); + stackIndex = stateStack[stackIndex]( + machine, + stackIndex, + stateStack, + nodeStack, + userStateStack, + resultHolder, + outerState, + ); } Debug.assertEqual(stackIndex, 0); return resultHolder.value; @@ -1530,9 +1784,15 @@ export function isNonExportDefaultModifier(node: Node): node is Exclude(factory: NodeFactory, nodes: NodeArray): NodeArray; /** @internal */ -export function elideNodes(factory: NodeFactory, nodes: NodeArray | undefined): NodeArray | undefined; +export function elideNodes( + factory: NodeFactory, + nodes: NodeArray | undefined, +): NodeArray | undefined; /** @internal */ -export function elideNodes(factory: NodeFactory, nodes: NodeArray | undefined): NodeArray | undefined { +export function elideNodes( + factory: NodeFactory, + nodes: NodeArray | undefined, +): NodeArray | undefined { if (nodes === undefined) return undefined; if (nodes.length === 0) return nodes; return setTextRange(factory.createNodeArray([], nodes.hasTrailingComma), nodes); @@ -1555,9 +1815,9 @@ export function getNodeForGeneratedName(name: GeneratedIdentifier | GeneratedPri // if "node" is a different generated name (having a different "autoGenerateId"), use it and stop traversing. if ( isMemberName(node) && ( - autoGenerate === undefined || - !!(autoGenerate.flags & GeneratedIdentifierFlags.Node) && - autoGenerate.id !== autoGenerateId + autoGenerate === undefined + || !!(autoGenerate.flags & GeneratedIdentifierFlags.Node) + && autoGenerate.id !== autoGenerateId ) ) { break; @@ -1582,24 +1842,38 @@ export function formatGeneratedNamePart(part: string | undefined): string; * * @internal */ -export function formatGeneratedNamePart(part: string | GeneratedNamePart | undefined, generateName: (name: GeneratedIdentifier | GeneratedPrivateIdentifier) => string): string; +export function formatGeneratedNamePart( + part: string | GeneratedNamePart | undefined, + generateName: (name: GeneratedIdentifier | GeneratedPrivateIdentifier) => string, +): string; /** @internal */ -export function formatGeneratedNamePart(part: string | GeneratedNamePart | undefined, generateName?: (name: GeneratedIdentifier | GeneratedPrivateIdentifier) => string): string { - return typeof part === "object" ? formatGeneratedName(/*privateName*/ false, part.prefix, part.node, part.suffix, generateName!) : - typeof part === "string" ? part.length > 0 && part.charCodeAt(0) === CharacterCodes.hash ? part.slice(1) : part : - ""; -} - -function formatIdentifier(name: string | Identifier | PrivateIdentifier, generateName?: (name: GeneratedIdentifier | GeneratedPrivateIdentifier) => string) { - return typeof name === "string" ? name : - formatIdentifierWorker(name, Debug.checkDefined(generateName)); +export function formatGeneratedNamePart( + part: string | GeneratedNamePart | undefined, + generateName?: (name: GeneratedIdentifier | GeneratedPrivateIdentifier) => string, +): string { + return typeof part === "object" + ? formatGeneratedName(/*privateName*/ false, part.prefix, part.node, part.suffix, generateName!) + : typeof part === "string" + ? part.length > 0 && part.charCodeAt(0) === CharacterCodes.hash ? part.slice(1) : part + : ""; +} + +function formatIdentifier( + name: string | Identifier | PrivateIdentifier, + generateName?: (name: GeneratedIdentifier | GeneratedPrivateIdentifier) => string, +) { + return typeof name === "string" ? name + : formatIdentifierWorker(name, Debug.checkDefined(generateName)); } -function formatIdentifierWorker(node: Identifier | PrivateIdentifier, generateName: (name: GeneratedIdentifier | GeneratedPrivateIdentifier) => string) { - return isGeneratedPrivateIdentifier(node) ? generateName(node).slice(1) : - isGeneratedIdentifier(node) ? generateName(node) : - isPrivateIdentifier(node) ? (node.escapedText as string).slice(1) : - idText(node); +function formatIdentifierWorker( + node: Identifier | PrivateIdentifier, + generateName: (name: GeneratedIdentifier | GeneratedPrivateIdentifier) => string, +) { + return isGeneratedPrivateIdentifier(node) ? generateName(node).slice(1) + : isGeneratedIdentifier(node) ? generateName(node) + : isPrivateIdentifier(node) ? (node.escapedText as string).slice(1) + : idText(node); } /** @@ -1611,7 +1885,12 @@ function formatIdentifierWorker(node: Identifier | PrivateIdentifier, generateNa * * @internal */ -export function formatGeneratedName(privateName: boolean, prefix: string | undefined, baseName: string, suffix: string | undefined): string; +export function formatGeneratedName( + privateName: boolean, + prefix: string | undefined, + baseName: string, + suffix: string | undefined, +): string; /** * Formats a generated name. * @param privateName When `true`, inserts a `#` character at the start of the result. @@ -1622,9 +1901,21 @@ export function formatGeneratedName(privateName: boolean, prefix: string | undef * * @internal */ -export function formatGeneratedName(privateName: boolean, prefix: string | GeneratedNamePart | undefined, baseName: string | Identifier | PrivateIdentifier, suffix: string | GeneratedNamePart | undefined, generateName: (name: GeneratedIdentifier | GeneratedPrivateIdentifier) => string): string; +export function formatGeneratedName( + privateName: boolean, + prefix: string | GeneratedNamePart | undefined, + baseName: string | Identifier | PrivateIdentifier, + suffix: string | GeneratedNamePart | undefined, + generateName: (name: GeneratedIdentifier | GeneratedPrivateIdentifier) => string, +): string; /** @internal */ -export function formatGeneratedName(privateName: boolean, prefix: string | GeneratedNamePart | undefined, baseName: string | Identifier | PrivateIdentifier, suffix: string | GeneratedNamePart | undefined, generateName?: (name: GeneratedIdentifier | GeneratedPrivateIdentifier) => string) { +export function formatGeneratedName( + privateName: boolean, + prefix: string | GeneratedNamePart | undefined, + baseName: string | Identifier | PrivateIdentifier, + suffix: string | GeneratedNamePart | undefined, + generateName?: (name: GeneratedIdentifier | GeneratedPrivateIdentifier) => string, +) { prefix = formatGeneratedNamePart(prefix, generateName!); suffix = formatGeneratedNamePart(suffix, generateName!); baseName = formatIdentifier(baseName, generateName); @@ -1636,7 +1927,12 @@ export function formatGeneratedName(privateName: boolean, prefix: string | Gener * * @internal */ -export function createAccessorPropertyBackingField(factory: NodeFactory, node: PropertyDeclaration, modifiers: ModifiersArray | undefined, initializer: Expression | undefined) { +export function createAccessorPropertyBackingField( + factory: NodeFactory, + node: PropertyDeclaration, + modifiers: ModifiersArray | undefined, + initializer: Expression | undefined, +) { return factory.updatePropertyDeclaration( node, modifiers, @@ -1652,7 +1948,13 @@ export function createAccessorPropertyBackingField(factory: NodeFactory, node: P * * @internal */ -export function createAccessorPropertyGetRedirector(factory: NodeFactory, node: PropertyDeclaration, modifiers: readonly Modifier[] | undefined, name: PropertyName, receiver: Expression = factory.createThis()): GetAccessorDeclaration { +export function createAccessorPropertyGetRedirector( + factory: NodeFactory, + node: PropertyDeclaration, + modifiers: readonly Modifier[] | undefined, + name: PropertyName, + receiver: Expression = factory.createThis(), +): GetAccessorDeclaration { return factory.createGetAccessorDeclaration( modifiers, name, @@ -1674,7 +1976,13 @@ export function createAccessorPropertyGetRedirector(factory: NodeFactory, node: * * @internal */ -export function createAccessorPropertySetRedirector(factory: NodeFactory, node: PropertyDeclaration, modifiers: readonly Modifier[] | undefined, name: PropertyName, receiver: Expression = factory.createThis()) { +export function createAccessorPropertySetRedirector( + factory: NodeFactory, + node: PropertyDeclaration, + modifiers: readonly Modifier[] | undefined, + name: PropertyName, + receiver: Expression = factory.createThis(), +) { return factory.createSetAccessorDeclaration( modifiers, name, diff --git a/src/compiler/moduleNameResolver.ts b/src/compiler/moduleNameResolver.ts index 6ca4df2d97a3e..250612c2b904b 100644 --- a/src/compiler/moduleNameResolver.ts +++ b/src/compiler/moduleNameResolver.ts @@ -125,7 +125,10 @@ export function isTraceEnabled(compilerOptions: CompilerOptions, host: ModuleRes return !!compilerOptions.traceResolution && host.trace !== undefined; } -function withPackageId(packageInfo: PackageJsonInfo | undefined, r: PathAndExtension | undefined): Resolved | undefined { +function withPackageId( + packageInfo: PackageJsonInfo | undefined, + r: PathAndExtension | undefined, +): Resolved | undefined { let packageId: PackageId | undefined; if (r && packageInfo) { const packageJsonContent = packageInfo.contents.packageJsonContent as PackageJson; @@ -232,14 +235,18 @@ function createResolvedModuleWithFailedLookupLocationsHandlingSymlink( ): ResolvedModuleWithFailedLookupLocations { // If this is from node_modules for non relative name, always respect preserveSymlinks if ( - !state.resultFromCache && - !state.compilerOptions.preserveSymlinks && - resolved && - isExternalLibraryImport && - !resolved.originalPath && - !isExternalModuleNameRelative(moduleName) + !state.resultFromCache + && !state.compilerOptions.preserveSymlinks + && resolved + && isExternalLibraryImport + && !resolved.originalPath + && !isExternalModuleNameRelative(moduleName) ) { - const { resolvedFileName, originalPath } = getOriginalAndResolvedFileName(resolved.path, state.host, state.traceEnabled); + const { resolvedFileName, originalPath } = getOriginalAndResolvedFileName( + resolved.path, + state.host, + state.traceEnabled, + ); if (originalPath) resolved = { ...resolved, path: resolvedFileName, originalPath }; } return createResolvedModuleWithFailedLookupLocations( @@ -263,9 +270,18 @@ function createResolvedModuleWithFailedLookupLocations( legacyResult?: string, ): ResolvedModuleWithFailedLookupLocations { if (resultFromCache) { - resultFromCache.failedLookupLocations = updateResolutionField(resultFromCache.failedLookupLocations, failedLookupLocations); - resultFromCache.affectingLocations = updateResolutionField(resultFromCache.affectingLocations, affectingLocations); - resultFromCache.resolutionDiagnostics = updateResolutionField(resultFromCache.resolutionDiagnostics, diagnostics); + resultFromCache.failedLookupLocations = updateResolutionField( + resultFromCache.failedLookupLocations, + failedLookupLocations, + ); + resultFromCache.affectingLocations = updateResolutionField( + resultFromCache.affectingLocations, + affectingLocations, + ); + resultFromCache.resolutionDiagnostics = updateResolutionField( + resultFromCache.resolutionDiagnostics, + diagnostics, + ); return resultFromCache; } return { @@ -332,9 +348,24 @@ interface PackageJson extends PackageJsonPathFields { version?: string; } -function readPackageJsonField>(jsonContent: PackageJson, fieldName: K, typeOfTag: "string", state: ModuleResolutionState): PackageJson[K] | undefined; -function readPackageJsonField>(jsonContent: PackageJson, fieldName: K, typeOfTag: "object", state: ModuleResolutionState): PackageJson[K] | undefined; -function readPackageJsonField(jsonContent: PackageJson, fieldName: K, typeOfTag: "string" | "object", state: ModuleResolutionState): PackageJson[K] | undefined { +function readPackageJsonField>( + jsonContent: PackageJson, + fieldName: K, + typeOfTag: "string", + state: ModuleResolutionState, +): PackageJson[K] | undefined; +function readPackageJsonField>( + jsonContent: PackageJson, + fieldName: K, + typeOfTag: "object", + state: ModuleResolutionState, +): PackageJson[K] | undefined; +function readPackageJsonField( + jsonContent: PackageJson, + fieldName: K, + typeOfTag: "string" | "object", + state: ModuleResolutionState, +): PackageJson[K] | undefined { if (!hasProperty(jsonContent, fieldName)) { if (state.traceEnabled) { trace(state.host, Diagnostics.package_json_does_not_have_a_0_field, fieldName); @@ -345,14 +376,25 @@ function readPackageJsonField(jsonContent: PackageJ if (typeof value !== typeOfTag || value === null) { // eslint-disable-line no-null/no-null if (state.traceEnabled) { // eslint-disable-next-line no-null/no-null - trace(state.host, Diagnostics.Expected_type_of_0_field_in_package_json_to_be_1_got_2, fieldName, typeOfTag, value === null ? "null" : typeof value); + trace( + state.host, + Diagnostics.Expected_type_of_0_field_in_package_json_to_be_1_got_2, + fieldName, + typeOfTag, + value === null ? "null" : typeof value, + ); } return; } return value; } -function readPackageJsonPathField(jsonContent: PackageJson, fieldName: K, baseDirectory: string, state: ModuleResolutionState): PackageJson[K] | undefined { +function readPackageJsonPathField( + jsonContent: PackageJson, + fieldName: K, + baseDirectory: string, + state: ModuleResolutionState, +): PackageJson[K] | undefined { const fileName = readPackageJsonField(jsonContent, fieldName, "string", state); if (fileName === undefined) { return; @@ -400,14 +442,21 @@ export interface VersionPaths { paths: MapLike; } -function readPackageJsonTypesVersionPaths(jsonContent: PackageJson, state: ModuleResolutionState): VersionPaths | undefined { +function readPackageJsonTypesVersionPaths( + jsonContent: PackageJson, + state: ModuleResolutionState, +): VersionPaths | undefined { const typesVersions = readPackageJsonTypesVersionsField(jsonContent, state); if (typesVersions === undefined) return; if (state.traceEnabled) { for (const key in typesVersions) { if (hasProperty(typesVersions, key) && !VersionRange.tryParse(key)) { - trace(state.host, Diagnostics.package_json_has_a_typesVersions_entry_0_that_is_not_a_valid_semver_range, key); + trace( + state.host, + Diagnostics.package_json_has_a_typesVersions_entry_0_that_is_not_a_valid_semver_range, + key, + ); } } } @@ -415,7 +464,11 @@ function readPackageJsonTypesVersionPaths(jsonContent: PackageJson, state: Modul const result = getPackageJsonTypesVersionsPaths(typesVersions); if (!result) { if (state.traceEnabled) { - trace(state.host, Diagnostics.package_json_does_not_have_a_typesVersions_entry_that_matches_version_0, versionMajorMinor); + trace( + state.host, + Diagnostics.package_json_does_not_have_a_typesVersions_entry_that_matches_version_0, + versionMajorMinor, + ); } return; } @@ -423,7 +476,13 @@ function readPackageJsonTypesVersionPaths(jsonContent: PackageJson, state: Modul const { version: bestVersionKey, paths: bestVersionPaths } = result; if (typeof bestVersionPaths !== "object") { if (state.traceEnabled) { - trace(state.host, Diagnostics.Expected_type_of_0_field_in_package_json_to_be_1_got_2, `typesVersions['${bestVersionKey}']`, "object", typeof bestVersionPaths); + trace( + state.host, + Diagnostics.Expected_type_of_0_field_in_package_json_to_be_1_got_2, + `typesVersions['${bestVersionKey}']`, + "object", + typeof bestVersionPaths, + ); } return; } @@ -485,7 +544,8 @@ function getDefaultTypeRoots(currentDirectory: string): string[] | undefined { const nodeModulesAtTypes = combinePaths("node_modules", "@types"); function arePathsEqual(path1: string, path2: string, host: ModuleResolutionHost): boolean { - const useCaseSensitiveFileNames = typeof host.useCaseSensitiveFileNames === "function" ? host.useCaseSensitiveFileNames() : host.useCaseSensitiveFileNames; + const useCaseSensitiveFileNames = typeof host.useCaseSensitiveFileNames === "function" + ? host.useCaseSensitiveFileNames() : host.useCaseSensitiveFileNames; return comparePaths(path1, path2, !useCaseSensitiveFileNames) === Comparison.EqualTo; } @@ -499,10 +559,14 @@ function getOriginalAndResolvedFileName(fileName: string, host: ModuleResolution }; } -function getCandidateFromTypeRoot(typeRoot: string, typeReferenceDirectiveName: string, moduleResolutionState: ModuleResolutionState) { - const nameForLookup = endsWith(typeRoot, "/node_modules/@types") || endsWith(typeRoot, "/node_modules/@types/") ? - mangleScopedPackageNameWithTrace(typeReferenceDirectiveName, moduleResolutionState) : - typeReferenceDirectiveName; +function getCandidateFromTypeRoot( + typeRoot: string, + typeReferenceDirectiveName: string, + moduleResolutionState: ModuleResolutionState, +) { + const nameForLookup = endsWith(typeRoot, "/node_modules/@types") || endsWith(typeRoot, "/node_modules/@types/") + ? mangleScopedPackageNameWithTrace(typeReferenceDirectiveName, moduleResolutionState) + : typeReferenceDirectiveName; return combinePaths(typeRoot, nameForLookup); } @@ -511,24 +575,62 @@ function getCandidateFromTypeRoot(typeRoot: string, typeReferenceDirectiveName: * This is possible in case if resolution is performed for directives specified via 'types' parameter. In this case initial path for secondary lookups * is assumed to be the same as root directory of the project. */ -export function resolveTypeReferenceDirective(typeReferenceDirectiveName: string, containingFile: string | undefined, options: CompilerOptions, host: ModuleResolutionHost, redirectedReference?: ResolvedProjectReference, cache?: TypeReferenceDirectiveResolutionCache, resolutionMode?: ResolutionMode): ResolvedTypeReferenceDirectiveWithFailedLookupLocations { - Debug.assert(typeof typeReferenceDirectiveName === "string", "Non-string value passed to `ts.resolveTypeReferenceDirective`, likely by a wrapping package working with an outdated `resolveTypeReferenceDirectives` signature. This is probably not a problem in TS itself."); +export function resolveTypeReferenceDirective( + typeReferenceDirectiveName: string, + containingFile: string | undefined, + options: CompilerOptions, + host: ModuleResolutionHost, + redirectedReference?: ResolvedProjectReference, + cache?: TypeReferenceDirectiveResolutionCache, + resolutionMode?: ResolutionMode, +): ResolvedTypeReferenceDirectiveWithFailedLookupLocations { + Debug.assert( + typeof typeReferenceDirectiveName === "string", + "Non-string value passed to `ts.resolveTypeReferenceDirective`, likely by a wrapping package working with an outdated `resolveTypeReferenceDirectives` signature. This is probably not a problem in TS itself.", + ); const traceEnabled = isTraceEnabled(options, host); if (redirectedReference) { options = redirectedReference.commandLine.options; } const containingDirectory = containingFile ? getDirectoryPath(containingFile) : undefined; - let result = containingDirectory ? cache?.getFromDirectoryCache(typeReferenceDirectiveName, resolutionMode, containingDirectory, redirectedReference) : undefined; + let result = containingDirectory + ? cache?.getFromDirectoryCache( + typeReferenceDirectiveName, + resolutionMode, + containingDirectory, + redirectedReference, + ) : undefined; if (!result && containingDirectory && !isExternalModuleNameRelative(typeReferenceDirectiveName)) { - result = cache?.getFromNonRelativeNameCache(typeReferenceDirectiveName, resolutionMode, containingDirectory, redirectedReference); + result = cache?.getFromNonRelativeNameCache( + typeReferenceDirectiveName, + resolutionMode, + containingDirectory, + redirectedReference, + ); } if (result) { if (traceEnabled) { - trace(host, Diagnostics.Resolving_type_reference_directive_0_containing_file_1, typeReferenceDirectiveName, containingFile); - if (redirectedReference) trace(host, Diagnostics.Using_compiler_options_of_project_reference_redirect_0, redirectedReference.sourceFile.fileName); - trace(host, Diagnostics.Resolution_for_type_reference_directive_0_was_found_in_cache_from_location_1, typeReferenceDirectiveName, containingDirectory); + trace( + host, + Diagnostics.Resolving_type_reference_directive_0_containing_file_1, + typeReferenceDirectiveName, + containingFile, + ); + if (redirectedReference) { + trace( + host, + Diagnostics.Using_compiler_options_of_project_reference_redirect_0, + redirectedReference.sourceFile.fileName, + ); + } + trace( + host, + Diagnostics.Resolution_for_type_reference_directive_0_was_found_in_cache_from_location_1, + typeReferenceDirectiveName, + containingDirectory, + ); traceResult(result); } return result; @@ -538,22 +640,46 @@ export function resolveTypeReferenceDirective(typeReferenceDirectiveName: string if (traceEnabled) { if (containingFile === undefined) { if (typeRoots === undefined) { - trace(host, Diagnostics.Resolving_type_reference_directive_0_containing_file_not_set_root_directory_not_set, typeReferenceDirectiveName); + trace( + host, + Diagnostics.Resolving_type_reference_directive_0_containing_file_not_set_root_directory_not_set, + typeReferenceDirectiveName, + ); } else { - trace(host, Diagnostics.Resolving_type_reference_directive_0_containing_file_not_set_root_directory_1, typeReferenceDirectiveName, typeRoots); + trace( + host, + Diagnostics.Resolving_type_reference_directive_0_containing_file_not_set_root_directory_1, + typeReferenceDirectiveName, + typeRoots, + ); } } else { if (typeRoots === undefined) { - trace(host, Diagnostics.Resolving_type_reference_directive_0_containing_file_1_root_directory_not_set, typeReferenceDirectiveName, containingFile); + trace( + host, + Diagnostics.Resolving_type_reference_directive_0_containing_file_1_root_directory_not_set, + typeReferenceDirectiveName, + containingFile, + ); } else { - trace(host, Diagnostics.Resolving_type_reference_directive_0_containing_file_1_root_directory_2, typeReferenceDirectiveName, containingFile, typeRoots); + trace( + host, + Diagnostics.Resolving_type_reference_directive_0_containing_file_1_root_directory_2, + typeReferenceDirectiveName, + containingFile, + typeRoots, + ); } } if (redirectedReference) { - trace(host, Diagnostics.Using_compiler_options_of_project_reference_redirect_0, redirectedReference.sourceFile.fileName); + trace( + host, + Diagnostics.Using_compiler_options_of_project_reference_redirect_0, + redirectedReference.sourceFile.fileName, + ); } } @@ -567,10 +693,15 @@ export function resolveTypeReferenceDirective(typeReferenceDirectiveName: string // in practice, not every cache has the options available to intelligently make the choice to ignore the mode request, and it's unclear how modern "faithful modern // resolution" should be (`node16`? `nodenext`?). As such, witnessing a mode-overriding triple-slash reference in a non-modal module resolution // context should _probably_ be an error - and that should likely be handled by the `Program` (which is what we do). - if (resolutionMode === ModuleKind.ESNext && (getEmitModuleResolutionKind(options) === ModuleResolutionKind.Node16 || getEmitModuleResolutionKind(options) === ModuleResolutionKind.NodeNext)) { + if ( + resolutionMode === ModuleKind.ESNext + && (getEmitModuleResolutionKind(options) === ModuleResolutionKind.Node16 + || getEmitModuleResolutionKind(options) === ModuleResolutionKind.NodeNext) + ) { features |= NodeResolutionFeatures.EsmMode; } - const conditions = features & NodeResolutionFeatures.Exports ? getConditions(options, !!(features & NodeResolutionFeatures.EsmMode)) : []; + const conditions = features & NodeResolutionFeatures.Exports + ? getConditions(options, !!(features & NodeResolutionFeatures.EsmMode)) : []; const diagnostics: Diagnostic[] = []; const moduleResolutionState: ModuleResolutionState = { compilerOptions: options, @@ -597,7 +728,9 @@ export function resolveTypeReferenceDirective(typeReferenceDirectiveName: string if (resolved) { const { fileName, packageId } = resolved; let resolvedFileName = fileName, originalPath: string | undefined; - if (!options.preserveSymlinks) ({ resolvedFileName, originalPath } = getOriginalAndResolvedFileName(fileName, host, traceEnabled)); + if (!options.preserveSymlinks) { + ({ resolvedFileName, originalPath } = getOriginalAndResolvedFileName(fileName, host, traceEnabled)); + } resolvedTypeReferenceDirective = { primary, resolvedFileName, @@ -613,9 +746,14 @@ export function resolveTypeReferenceDirective(typeReferenceDirectiveName: string resolutionDiagnostics: initializeResolutionField(diagnostics), }; if (containingDirectory) { - cache?.getOrCreateCacheForDirectory(containingDirectory, redirectedReference).set(typeReferenceDirectiveName, /*mode*/ resolutionMode, result); + cache?.getOrCreateCacheForDirectory(containingDirectory, redirectedReference).set( + typeReferenceDirectiveName, + /*mode*/ resolutionMode, + result, + ); if (!isExternalModuleNameRelative(typeReferenceDirectiveName)) { - cache?.getOrCreateCacheForNonRelativeName(typeReferenceDirectiveName, resolutionMode, redirectedReference).set(containingDirectory, result); + cache?.getOrCreateCacheForNonRelativeName(typeReferenceDirectiveName, resolutionMode, redirectedReference) + .set(containingDirectory, result); } } if (traceEnabled) traceResult(result); @@ -626,10 +764,23 @@ export function resolveTypeReferenceDirective(typeReferenceDirectiveName: string trace(host, Diagnostics.Type_reference_directive_0_was_not_resolved, typeReferenceDirectiveName); } else if (result.resolvedTypeReferenceDirective.packageId) { - trace(host, Diagnostics.Type_reference_directive_0_was_successfully_resolved_to_1_with_Package_ID_2_primary_Colon_3, typeReferenceDirectiveName, result.resolvedTypeReferenceDirective.resolvedFileName, packageIdToString(result.resolvedTypeReferenceDirective.packageId), result.resolvedTypeReferenceDirective.primary); + trace( + host, + Diagnostics.Type_reference_directive_0_was_successfully_resolved_to_1_with_Package_ID_2_primary_Colon_3, + typeReferenceDirectiveName, + result.resolvedTypeReferenceDirective.resolvedFileName, + packageIdToString(result.resolvedTypeReferenceDirective.packageId), + result.resolvedTypeReferenceDirective.primary, + ); } else { - trace(host, Diagnostics.Type_reference_directive_0_was_successfully_resolved_to_1_primary_Colon_2, typeReferenceDirectiveName, result.resolvedTypeReferenceDirective.resolvedFileName, result.resolvedTypeReferenceDirective.primary); + trace( + host, + Diagnostics.Type_reference_directive_0_was_successfully_resolved_to_1_primary_Colon_2, + typeReferenceDirectiveName, + result.resolvedTypeReferenceDirective.resolvedFileName, + result.resolvedTypeReferenceDirective.primary, + ); } } @@ -647,15 +798,27 @@ export function resolveTypeReferenceDirective(typeReferenceDirectiveName: string } if (options.typeRoots) { // Custom typeRoots resolve as file or directory just like we do modules - const resolvedFromFile = loadModuleFromFile(Extensions.Declaration, candidate, !directoryExists, moduleResolutionState); + const resolvedFromFile = loadModuleFromFile( + Extensions.Declaration, + candidate, + !directoryExists, + moduleResolutionState, + ); if (resolvedFromFile) { const packageDirectory = parseNodeModuleFromPath(resolvedFromFile.path); - const packageInfo = packageDirectory ? getPackageJsonInfo(packageDirectory, /*onlyRecordFailures*/ false, moduleResolutionState) : undefined; + const packageInfo = packageDirectory + ? getPackageJsonInfo(packageDirectory, /*onlyRecordFailures*/ false, moduleResolutionState) + : undefined; return resolvedTypeScriptOnly(withPackageId(packageInfo, resolvedFromFile)); } } return resolvedTypeScriptOnly( - loadNodeModuleFromDirectory(Extensions.Declaration, candidate, !directoryExists, moduleResolutionState), + loadNodeModuleFromDirectory( + Extensions.Declaration, + candidate, + !directoryExists, + moduleResolutionState, + ), ); }); } @@ -673,25 +836,53 @@ export function resolveTypeReferenceDirective(typeReferenceDirectiveName: string if (!options.typeRoots || !endsWith(containingFile!, inferredTypesContainingFile)) { // check secondary locations if (traceEnabled) { - trace(host, Diagnostics.Looking_up_in_node_modules_folder_initial_location_0, initialLocationForSecondaryLookup); + trace( + host, + Diagnostics.Looking_up_in_node_modules_folder_initial_location_0, + initialLocationForSecondaryLookup, + ); } if (!isExternalModuleNameRelative(typeReferenceDirectiveName)) { - const searchResult = loadModuleFromNearestNodeModulesDirectory(Extensions.Declaration, typeReferenceDirectiveName, initialLocationForSecondaryLookup, moduleResolutionState, /*cache*/ undefined, /*redirectedReference*/ undefined); + const searchResult = loadModuleFromNearestNodeModulesDirectory( + Extensions.Declaration, + typeReferenceDirectiveName, + initialLocationForSecondaryLookup, + moduleResolutionState, + /*cache*/ undefined, + /*redirectedReference*/ undefined, + ); result = searchResult && searchResult.value; } else { - const { path: candidate } = normalizePathForCJSResolution(initialLocationForSecondaryLookup, typeReferenceDirectiveName); - result = nodeLoadModuleByRelativeName(Extensions.Declaration, candidate, /*onlyRecordFailures*/ false, moduleResolutionState, /*considerPackageJson*/ true); + const { path: candidate } = normalizePathForCJSResolution( + initialLocationForSecondaryLookup, + typeReferenceDirectiveName, + ); + result = nodeLoadModuleByRelativeName( + Extensions.Declaration, + candidate, + /*onlyRecordFailures*/ false, + moduleResolutionState, + /*considerPackageJson*/ true, + ); } } else if (traceEnabled) { - trace(host, Diagnostics.Resolving_type_reference_directive_for_program_that_specifies_custom_typeRoots_skipping_lookup_in_node_modules_folder); + trace( + host, + Diagnostics + .Resolving_type_reference_directive_for_program_that_specifies_custom_typeRoots_skipping_lookup_in_node_modules_folder, + ); } return resolvedTypeScriptOnly(result); } else { if (traceEnabled) { - trace(host, Diagnostics.Containing_file_is_not_specified_and_root_directory_cannot_be_determined_skipping_lookup_in_node_modules_folder); + trace( + host, + Diagnostics + .Containing_file_is_not_specified_and_root_directory_cannot_be_determined_skipping_lookup_in_node_modules_folder, + ); } } } @@ -790,7 +981,8 @@ export function getAutomaticTypeDirectiveNames(options: CompilerOptions, host: M // `types-publisher` sometimes creates packages with `"typings": null` for packages that don't provide their own types. // See `createNotNeededPackageJSON` in the types-publisher` repo. // eslint-disable-next-line no-null/no-null - const isNotNeededPackage = host.fileExists(packageJsonPath) && (readJson(packageJsonPath, host) as PackageJson).typings === null; + const isNotNeededPackage = host.fileExists(packageJsonPath) + && (readJson(packageJsonPath, host) as PackageJson).typings === null; if (!isNotNeededPackage) { const baseFileName = getBaseFileName(normalized); @@ -808,7 +1000,12 @@ export function getAutomaticTypeDirectiveNames(options: CompilerOptions, host: M return result; } -export interface TypeReferenceDirectiveResolutionCache extends PerDirectoryResolutionCache, NonRelativeNameResolutionCache, PackageJsonInfoCache { +export interface TypeReferenceDirectiveResolutionCache + extends + PerDirectoryResolutionCache, + NonRelativeNameResolutionCache, + PackageJsonInfoCache +{ /** @internal */ clearAllExceptPackageJsonInfoCache(): void; } @@ -826,8 +1023,16 @@ export interface ModeAwareCache { * This assumes that any module id will have the same resolution for sibling files located in the same folder. */ export interface PerDirectoryResolutionCache { - getFromDirectoryCache(name: string, mode: ResolutionMode, directoryName: string, redirectedReference: ResolvedProjectReference | undefined): T | undefined; - getOrCreateCacheForDirectory(directoryName: string, redirectedReference?: ResolvedProjectReference): ModeAwareCache; + getFromDirectoryCache( + name: string, + mode: ResolutionMode, + directoryName: string, + redirectedReference: ResolvedProjectReference | undefined, + ): T | undefined; + getOrCreateCacheForDirectory( + directoryName: string, + redirectedReference?: ResolvedProjectReference, + ): ModeAwareCache; clear(): void; /** * Updates with the current compilerOptions the cache will operate with. @@ -837,8 +1042,17 @@ export interface PerDirectoryResolutionCache { } export interface NonRelativeNameResolutionCache { - getFromNonRelativeNameCache(nonRelativeName: string, mode: ResolutionMode, directoryName: string, redirectedReference: ResolvedProjectReference | undefined): T | undefined; - getOrCreateCacheForNonRelativeName(nonRelativeName: string, mode: ResolutionMode, redirectedReference?: ResolvedProjectReference): PerNonRelativeNameCache; + getFromNonRelativeNameCache( + nonRelativeName: string, + mode: ResolutionMode, + directoryName: string, + redirectedReference: ResolvedProjectReference | undefined, + ): T | undefined; + getOrCreateCacheForNonRelativeName( + nonRelativeName: string, + mode: ResolutionMode, + redirectedReference?: ResolvedProjectReference, + ): PerNonRelativeNameCache; clear(): void; /** * Updates with the current compilerOptions the cache will operate with. @@ -852,7 +1066,12 @@ export interface PerNonRelativeNameCache { set(directory: string, result: T): void; } -export interface ModuleResolutionCache extends PerDirectoryResolutionCache, NonRelativeModuleNameResolutionCache, PackageJsonInfoCache { +export interface ModuleResolutionCache + extends + PerDirectoryResolutionCache, + NonRelativeModuleNameResolutionCache, + PackageJsonInfoCache +{ getPackageJsonInfoCache(): PackageJsonInfoCache; /** @internal */ clearAllExceptPackageJsonInfoCache(): void; } @@ -861,9 +1080,15 @@ export interface ModuleResolutionCache extends PerDirectoryResolutionCache result of module lookup in this directory * We support only non-relative module names because resolution of relative module names is usually more deterministic and thus less expensive. */ -export interface NonRelativeModuleNameResolutionCache extends NonRelativeNameResolutionCache, PackageJsonInfoCache { +export interface NonRelativeModuleNameResolutionCache + extends NonRelativeNameResolutionCache, PackageJsonInfoCache +{ /** @deprecated Use getOrCreateCacheForNonRelativeName */ - getOrCreateCacheForModuleName(nonRelativeModuleName: string, mode: ResolutionMode, redirectedReference?: ResolvedProjectReference): PerModuleNameCache; + getOrCreateCacheForModuleName( + nonRelativeModuleName: string, + mode: ResolutionMode, + redirectedReference?: ResolvedProjectReference, + ): PerModuleNameCache; } export interface PackageJsonInfoCache { @@ -893,8 +1118,13 @@ function compilerOptionValueToString(value: unknown): string { } /** @internal */ -export function getKeyForCompilerOptions(options: CompilerOptions, affectingOptionDeclarations: readonly CommandLineOption[]) { - return affectingOptionDeclarations.map(option => compilerOptionValueToString(getCompilerOptionValue(options, option))).join("|") + `|${options.pathsBasePath}`; +export function getKeyForCompilerOptions( + options: CompilerOptions, + affectingOptionDeclarations: readonly CommandLineOption[], +) { + return affectingOptionDeclarations.map(option => + compilerOptionValueToString(getCompilerOptionValue(options, option)) + ).join("|") + `|${options.pathsBasePath}`; } /** @internal */ @@ -921,15 +1151,15 @@ export function createCacheWithRedirects(ownOptions: CompilerOptions | und }; function getMapOfCacheRedirects(redirectedReference: ResolvedProjectReference | undefined): Map | undefined { - return redirectedReference ? - getOrCreateMap(redirectedReference.commandLine.options, /*create*/ false) : - ownMap; + return redirectedReference + ? getOrCreateMap(redirectedReference.commandLine.options, /*create*/ false) + : ownMap; } function getOrCreateMapOfCacheRedirects(redirectedReference: ResolvedProjectReference | undefined): Map { - return redirectedReference ? - getOrCreateMap(redirectedReference.commandLine.options, /*create*/ true) : - ownMap; + return redirectedReference + ? getOrCreateMap(redirectedReference.commandLine.options, /*create*/ true) + : ownMap; } function update(newOptions: CompilerOptions) { @@ -975,13 +1205,19 @@ export function createCacheWithRedirects(ownOptions: CompilerOptions | und function getRedirectsCacheKey(options: CompilerOptions) { let result = optionsToRedirectsKey.get(options); if (!result) { - optionsToRedirectsKey.set(options, result = getKeyForCompilerOptions(options, moduleResolutionOptionDeclarations) as RedirectsCacheKey); + optionsToRedirectsKey.set( + options, + result = getKeyForCompilerOptions(options, moduleResolutionOptionDeclarations) as RedirectsCacheKey, + ); } return result; } } -function createPackageJsonInfoCache(currentDirectory: string, getCanonicalFileName: (s: string) => string): PackageJsonInfoCache { +function createPackageJsonInfoCache( + currentDirectory: string, + getCanonicalFileName: (s: string) => string, +): PackageJsonInfoCache { let cache: Map | undefined; return { getPackageJsonInfo, setPackageJsonInfo, clear, entries, getInternalMap }; function getPackageJsonInfo(packageJsonPath: string) { @@ -1002,7 +1238,12 @@ function createPackageJsonInfoCache(currentDirectory: string, getCanonicalFileNa } } -function getOrCreateCache(cacheWithRedirects: CacheWithRedirects, redirectedReference: ResolvedProjectReference | undefined, key: K, create: () => V): V { +function getOrCreateCache( + cacheWithRedirects: CacheWithRedirects, + redirectedReference: ResolvedProjectReference | undefined, + key: K, + create: () => V, +): V { const cache = cacheWithRedirects.getOrCreateMapOfCacheRedirects(redirectedReference); let result = cache.get(key); if (!result) { @@ -1012,7 +1253,11 @@ function getOrCreateCache(cacheWithRedirects: CacheWithRedirects, re return result; } -function createPerDirectoryResolutionCache(currentDirectory: string, getCanonicalFileName: GetCanonicalFileName, options: CompilerOptions | undefined): PerDirectoryResolutionCache { +function createPerDirectoryResolutionCache( + currentDirectory: string, + getCanonicalFileName: GetCanonicalFileName, + options: CompilerOptions | undefined, +): PerDirectoryResolutionCache { const directoryToModuleNameMap = createCacheWithRedirects>(options); return { getFromDirectoryCache, @@ -1034,7 +1279,12 @@ function createPerDirectoryResolutionCache(currentDirectory: string, getCanon return getOrCreateCache(directoryToModuleNameMap, redirectedReference, path, () => createModeAwareCache()); } - function getFromDirectoryCache(name: string, mode: ResolutionMode, directoryName: string, redirectedReference: ResolvedProjectReference | undefined) { + function getFromDirectoryCache( + name: string, + mode: ResolutionMode, + directoryName: string, + redirectedReference: ResolvedProjectReference | undefined, + ) { const path = toPath(directoryName, currentDirectory, getCanonicalFileName); return directoryToModuleNameMap.getMapOfCacheRedirects(redirectedReference)?.get(path)?.get(name, mode); } @@ -1106,8 +1356,9 @@ function getOriginalOrResolvedModuleFileName(result: ResolvedModuleWithFailedLoo } function getOriginalOrResolvedTypeReferenceFileName(result: ResolvedTypeReferenceDirectiveWithFailedLookupLocations) { - return result.resolvedTypeReferenceDirective && - (result.resolvedTypeReferenceDirective.originalPath || result.resolvedTypeReferenceDirective.resolvedFileName); + return result.resolvedTypeReferenceDirective + && (result.resolvedTypeReferenceDirective.originalPath + || result.resolvedTypeReferenceDirective.resolvedFileName); } function createNonRelativeNameResolutionCache( @@ -1132,14 +1383,30 @@ function createNonRelativeNameResolutionCache( moduleNameToDirectoryMap.update(options); } - function getFromNonRelativeNameCache(nonRelativeModuleName: string, mode: ResolutionMode, directoryName: string, redirectedReference?: ResolvedProjectReference): T | undefined { + function getFromNonRelativeNameCache( + nonRelativeModuleName: string, + mode: ResolutionMode, + directoryName: string, + redirectedReference?: ResolvedProjectReference, + ): T | undefined { Debug.assert(!isExternalModuleNameRelative(nonRelativeModuleName)); - return moduleNameToDirectoryMap.getMapOfCacheRedirects(redirectedReference)?.get(createModeAwareCacheKey(nonRelativeModuleName, mode))?.get(directoryName); + return moduleNameToDirectoryMap.getMapOfCacheRedirects(redirectedReference)?.get( + createModeAwareCacheKey(nonRelativeModuleName, mode), + )?.get(directoryName); } - function getOrCreateCacheForNonRelativeName(nonRelativeModuleName: string, mode: ResolutionMode, redirectedReference?: ResolvedProjectReference): PerNonRelativeNameCache { + function getOrCreateCacheForNonRelativeName( + nonRelativeModuleName: string, + mode: ResolutionMode, + redirectedReference?: ResolvedProjectReference, + ): PerNonRelativeNameCache { Debug.assert(!isExternalModuleNameRelative(nonRelativeModuleName)); - return getOrCreateCache(moduleNameToDirectoryMap, redirectedReference, createModeAwareCacheKey(nonRelativeModuleName, mode), createPerModuleNameCache); + return getOrCreateCache( + moduleNameToDirectoryMap, + redirectedReference, + createModeAwareCacheKey(nonRelativeModuleName, mode), + createPerModuleNameCache, + ); } function createPerModuleNameCache(): PerNonRelativeNameCache { @@ -1198,7 +1465,10 @@ function createNonRelativeNameResolutionCache( while (i < limit && directory.charCodeAt(i) === resolutionDirectory.charCodeAt(i)) { i++; } - if (i === directory.length && (resolutionDirectory.length === i || resolutionDirectory[i] === directorySeparator)) { + if ( + i === directory.length + && (resolutionDirectory.length === i || resolutionDirectory[i] === directorySeparator) + ) { return directory; } const rootLength = getRootLength(directory); @@ -1214,7 +1484,9 @@ function createNonRelativeNameResolutionCache( } } -interface ModuleOrTypeReferenceResolutionCache extends PerDirectoryResolutionCache, NonRelativeNameResolutionCache, PackageJsonInfoCache { +interface ModuleOrTypeReferenceResolutionCache + extends PerDirectoryResolutionCache, NonRelativeNameResolutionCache, PackageJsonInfoCache +{ getPackageJsonInfoCache(): PackageJsonInfoCache; clearAllExceptPackageJsonInfoCache(): void; } @@ -1225,7 +1497,11 @@ function createModuleOrTypeReferenceResolutionCache( packageJsonInfoCache: PackageJsonInfoCache | undefined, getResolvedFileName: (result: T) => string | undefined, ): ModuleOrTypeReferenceResolutionCache { - const perDirectoryResolutionCache = createPerDirectoryResolutionCache(currentDirectory, getCanonicalFileName, options); + const perDirectoryResolutionCache = createPerDirectoryResolutionCache( + currentDirectory, + getCanonicalFileName, + options, + ); const nonRelativeNameResolutionCache = createNonRelativeNameResolutionCache( currentDirectory, getCanonicalFileName, @@ -1273,7 +1549,8 @@ export function createModuleResolutionCache( packageJsonInfoCache, getOriginalOrResolvedModuleFileName, ) as ModuleResolutionCache; - result.getOrCreateCacheForModuleName = (nonRelativeName, mode, redirectedReference) => result.getOrCreateCacheForNonRelativeName(nonRelativeName, mode, redirectedReference); + result.getOrCreateCacheForModuleName = (nonRelativeName, mode, redirectedReference) => + result.getOrCreateCacheForNonRelativeName(nonRelativeName, mode, redirectedReference); return result; } @@ -1298,16 +1575,35 @@ export function getOptionsForLibraryResolution(options: CompilerOptions) { } /** @internal */ -export function resolveLibrary(libraryName: string, resolveFrom: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache?: ModuleResolutionCache): ResolvedModuleWithFailedLookupLocations { +export function resolveLibrary( + libraryName: string, + resolveFrom: string, + compilerOptions: CompilerOptions, + host: ModuleResolutionHost, + cache?: ModuleResolutionCache, +): ResolvedModuleWithFailedLookupLocations { return resolveModuleName(libraryName, resolveFrom, getOptionsForLibraryResolution(compilerOptions), host, cache); } -export function resolveModuleNameFromCache(moduleName: string, containingFile: string, cache: ModuleResolutionCache, mode?: ResolutionMode): ResolvedModuleWithFailedLookupLocations | undefined { +export function resolveModuleNameFromCache( + moduleName: string, + containingFile: string, + cache: ModuleResolutionCache, + mode?: ResolutionMode, +): ResolvedModuleWithFailedLookupLocations | undefined { const containingDirectory = getDirectoryPath(containingFile); return cache.getFromDirectoryCache(moduleName, mode, containingDirectory, /*redirectedReference*/ undefined); } -export function resolveModuleName(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache?: ModuleResolutionCache, redirectedReference?: ResolvedProjectReference, resolutionMode?: ResolutionMode): ResolvedModuleWithFailedLookupLocations { +export function resolveModuleName( + moduleName: string, + containingFile: string, + compilerOptions: CompilerOptions, + host: ModuleResolutionHost, + cache?: ModuleResolutionCache, + redirectedReference?: ResolvedProjectReference, + resolutionMode?: ResolutionMode, +): ResolvedModuleWithFailedLookupLocations { const traceEnabled = isTraceEnabled(compilerOptions, host); if (redirectedReference) { compilerOptions = redirectedReference.commandLine.options; @@ -1315,7 +1611,11 @@ export function resolveModuleName(moduleName: string, containingFile: string, co if (traceEnabled) { trace(host, Diagnostics.Resolving_module_0_from_1, moduleName, containingFile); if (redirectedReference) { - trace(host, Diagnostics.Using_compiler_options_of_project_reference_redirect_0, redirectedReference.sourceFile.fileName); + trace( + host, + Diagnostics.Using_compiler_options_of_project_reference_redirect_0, + redirectedReference.sourceFile.fileName, + ); } } const containingDirectory = getDirectoryPath(containingFile); @@ -1323,7 +1623,12 @@ export function resolveModuleName(moduleName: string, containingFile: string, co if (result) { if (traceEnabled) { - trace(host, Diagnostics.Resolution_for_module_0_was_found_in_cache_from_location_1, moduleName, containingDirectory); + trace( + host, + Diagnostics.Resolution_for_module_0_was_found_in_cache_from_location_1, + moduleName, + containingDirectory, + ); } } else { @@ -1344,52 +1649,119 @@ export function resolveModuleName(moduleName: string, containingFile: string, co break; } if (traceEnabled) { - trace(host, Diagnostics.Module_resolution_kind_is_not_specified_using_0, ModuleResolutionKind[moduleResolution]); + trace( + host, + Diagnostics.Module_resolution_kind_is_not_specified_using_0, + ModuleResolutionKind[moduleResolution], + ); } } else { if (traceEnabled) { - trace(host, Diagnostics.Explicitly_specified_module_resolution_kind_Colon_0, ModuleResolutionKind[moduleResolution]); + trace( + host, + Diagnostics.Explicitly_specified_module_resolution_kind_Colon_0, + ModuleResolutionKind[moduleResolution], + ); } } perfLogger?.logStartResolveModule(moduleName /* , containingFile, ModuleResolutionKind[moduleResolution]*/); switch (moduleResolution) { case ModuleResolutionKind.Node16: - result = node16ModuleNameResolver(moduleName, containingFile, compilerOptions, host, cache, redirectedReference, resolutionMode); + result = node16ModuleNameResolver( + moduleName, + containingFile, + compilerOptions, + host, + cache, + redirectedReference, + resolutionMode, + ); break; case ModuleResolutionKind.NodeNext: - result = nodeNextModuleNameResolver(moduleName, containingFile, compilerOptions, host, cache, redirectedReference, resolutionMode); + result = nodeNextModuleNameResolver( + moduleName, + containingFile, + compilerOptions, + host, + cache, + redirectedReference, + resolutionMode, + ); break; case ModuleResolutionKind.Node10: - result = nodeModuleNameResolver(moduleName, containingFile, compilerOptions, host, cache, redirectedReference); + result = nodeModuleNameResolver( + moduleName, + containingFile, + compilerOptions, + host, + cache, + redirectedReference, + ); break; case ModuleResolutionKind.Classic: - result = classicNameResolver(moduleName, containingFile, compilerOptions, host, cache, redirectedReference); + result = classicNameResolver( + moduleName, + containingFile, + compilerOptions, + host, + cache, + redirectedReference, + ); break; case ModuleResolutionKind.Bundler: - result = bundlerModuleNameResolver(moduleName, containingFile, compilerOptions, host, cache, redirectedReference); + result = bundlerModuleNameResolver( + moduleName, + containingFile, + compilerOptions, + host, + cache, + redirectedReference, + ); break; default: return Debug.fail(`Unexpected moduleResolution: ${moduleResolution}`); } - if (result && result.resolvedModule) perfLogger?.logInfoEvent(`Module "${moduleName}" resolved to "${result.resolvedModule.resolvedFileName}"`); - perfLogger?.logStopResolveModule((result && result.resolvedModule) ? "" + result.resolvedModule.resolvedFileName : "null"); + if (result && result.resolvedModule) { + perfLogger?.logInfoEvent(`Module "${moduleName}" resolved to "${result.resolvedModule.resolvedFileName}"`); + } + perfLogger?.logStopResolveModule( + (result && result.resolvedModule) ? "" + result.resolvedModule.resolvedFileName : "null", + ); - cache?.getOrCreateCacheForDirectory(containingDirectory, redirectedReference).set(moduleName, resolutionMode, result); + cache?.getOrCreateCacheForDirectory(containingDirectory, redirectedReference).set( + moduleName, + resolutionMode, + result, + ); if (!isExternalModuleNameRelative(moduleName)) { // put result in per-module name cache - cache?.getOrCreateCacheForNonRelativeName(moduleName, resolutionMode, redirectedReference).set(containingDirectory, result); + cache?.getOrCreateCacheForNonRelativeName(moduleName, resolutionMode, redirectedReference).set( + containingDirectory, + result, + ); } } if (traceEnabled) { if (result.resolvedModule) { if (result.resolvedModule.packageId) { - trace(host, Diagnostics.Module_name_0_was_successfully_resolved_to_1_with_Package_ID_2, moduleName, result.resolvedModule.resolvedFileName, packageIdToString(result.resolvedModule.packageId)); + trace( + host, + Diagnostics.Module_name_0_was_successfully_resolved_to_1_with_Package_ID_2, + moduleName, + result.resolvedModule.resolvedFileName, + packageIdToString(result.resolvedModule.packageId), + ); } else { - trace(host, Diagnostics.Module_name_0_was_successfully_resolved_to_1, moduleName, result.resolvedModule.resolvedFileName); + trace( + host, + Diagnostics.Module_name_0_was_successfully_resolved_to_1, + moduleName, + result.resolvedModule.resolvedFileName, + ); } } else { @@ -1408,7 +1780,12 @@ export function resolveModuleName(moduleName: string, containingFile: string, co * 'typings' entry or file 'index' with some supported extension * - Classic loader will only try to interpret '/a/b/c' as file. */ -type ResolutionKindSpecificLoader = (extensions: Extensions, candidate: string, onlyRecordFailures: boolean, state: ModuleResolutionState) => Resolved | undefined; +type ResolutionKindSpecificLoader = ( + extensions: Extensions, + candidate: string, + onlyRecordFailures: boolean, + state: ModuleResolutionState, +) => Resolved | undefined; /** * Any module resolution kind can be augmented with optional settings: 'baseUrl', 'paths' and 'rootDirs' - they are used to @@ -1470,7 +1847,13 @@ type ResolutionKindSpecificLoader = (extensions: Extensions, candidate: string, * be converted to a path relative to found rootDir entry './content/protocols/file2' (*). As a last step compiler will check all remaining * entries in 'rootDirs', use them to build absolute path out of (*) and try to resolve module from this location. */ -function tryLoadModuleUsingOptionalResolutionSettings(extensions: Extensions, moduleName: string, containingDirectory: string, loader: ResolutionKindSpecificLoader, state: ModuleResolutionState): Resolved | undefined { +function tryLoadModuleUsingOptionalResolutionSettings( + extensions: Extensions, + moduleName: string, + containingDirectory: string, + loader: ResolutionKindSpecificLoader, + state: ModuleResolutionState, +): Resolved | undefined { const resolved = tryLoadModuleUsingPathsIfEligible(extensions, moduleName, loader, state); if (resolved) return resolved.value; @@ -1482,22 +1865,52 @@ function tryLoadModuleUsingOptionalResolutionSettings(extensions: Extensions, mo } } -function tryLoadModuleUsingPathsIfEligible(extensions: Extensions, moduleName: string, loader: ResolutionKindSpecificLoader, state: ModuleResolutionState) { +function tryLoadModuleUsingPathsIfEligible( + extensions: Extensions, + moduleName: string, + loader: ResolutionKindSpecificLoader, + state: ModuleResolutionState, +) { const { baseUrl, paths, configFile } = state.compilerOptions; if (paths && !pathIsRelative(moduleName)) { if (state.traceEnabled) { if (baseUrl) { - trace(state.host, Diagnostics.baseUrl_option_is_set_to_0_using_this_value_to_resolve_non_relative_module_name_1, baseUrl, moduleName); + trace( + state.host, + Diagnostics.baseUrl_option_is_set_to_0_using_this_value_to_resolve_non_relative_module_name_1, + baseUrl, + moduleName, + ); } - trace(state.host, Diagnostics.paths_option_is_specified_looking_for_a_pattern_to_match_module_name_0, moduleName); + trace( + state.host, + Diagnostics.paths_option_is_specified_looking_for_a_pattern_to_match_module_name_0, + moduleName, + ); } const baseDirectory = getPathsBasePath(state.compilerOptions, state.host)!; // Always defined when 'paths' is defined - const pathPatterns = configFile?.configFileSpecs ? configFile.configFileSpecs.pathPatterns ||= tryParsePatterns(paths) : undefined; - return tryLoadModuleUsingPaths(extensions, moduleName, baseDirectory, paths, pathPatterns, loader, /*onlyRecordFailures*/ false, state); + const pathPatterns = configFile?.configFileSpecs + ? configFile.configFileSpecs.pathPatterns ||= tryParsePatterns(paths) : undefined; + return tryLoadModuleUsingPaths( + extensions, + moduleName, + baseDirectory, + paths, + pathPatterns, + loader, + /*onlyRecordFailures*/ false, + state, + ); } } -function tryLoadModuleUsingRootDirs(extensions: Extensions, moduleName: string, containingDirectory: string, loader: ResolutionKindSpecificLoader, state: ModuleResolutionState): Resolved | undefined { +function tryLoadModuleUsingRootDirs( + extensions: Extensions, + moduleName: string, + containingDirectory: string, + loader: ResolutionKindSpecificLoader, + state: ModuleResolutionState, +): Resolved | undefined { if (!state.compilerOptions.rootDirs) { return undefined; } @@ -1518,11 +1931,17 @@ function tryLoadModuleUsingRootDirs(extensions: Extensions, moduleName: string, if (!endsWith(normalizedRoot, directorySeparator)) { normalizedRoot += directorySeparator; } - const isLongestMatchingPrefix = startsWith(candidate, normalizedRoot) && - (matchedNormalizedPrefix === undefined || matchedNormalizedPrefix.length < normalizedRoot.length); + const isLongestMatchingPrefix = startsWith(candidate, normalizedRoot) + && (matchedNormalizedPrefix === undefined || matchedNormalizedPrefix.length < normalizedRoot.length); if (state.traceEnabled) { - trace(state.host, Diagnostics.Checking_if_0_is_the_longest_matching_prefix_for_1_2, normalizedRoot, candidate, isLongestMatchingPrefix); + trace( + state.host, + Diagnostics.Checking_if_0_is_the_longest_matching_prefix_for_1_2, + normalizedRoot, + candidate, + isLongestMatchingPrefix, + ); } if (isLongestMatchingPrefix) { @@ -1538,9 +1957,20 @@ function tryLoadModuleUsingRootDirs(extensions: Extensions, moduleName: string, // first - try to load from a initial location if (state.traceEnabled) { - trace(state.host, Diagnostics.Loading_0_from_the_root_dir_1_candidate_location_2, suffix, matchedNormalizedPrefix, candidate); + trace( + state.host, + Diagnostics.Loading_0_from_the_root_dir_1_candidate_location_2, + suffix, + matchedNormalizedPrefix, + candidate, + ); } - const resolvedFileName = loader(extensions, candidate, !directoryProbablyExists(containingDirectory, state.host), state); + const resolvedFileName = loader( + extensions, + candidate, + !directoryProbablyExists(containingDirectory, state.host), + state, + ); if (resolvedFileName) { return resolvedFileName; } @@ -1556,10 +1986,21 @@ function tryLoadModuleUsingRootDirs(extensions: Extensions, moduleName: string, } const candidate = combinePaths(normalizePath(rootDir), suffix); if (state.traceEnabled) { - trace(state.host, Diagnostics.Loading_0_from_the_root_dir_1_candidate_location_2, suffix, rootDir, candidate); + trace( + state.host, + Diagnostics.Loading_0_from_the_root_dir_1_candidate_location_2, + suffix, + rootDir, + candidate, + ); } const baseDirectory = getDirectoryPath(candidate); - const resolvedFileName = loader(extensions, candidate, !directoryProbablyExists(baseDirectory, state.host), state); + const resolvedFileName = loader( + extensions, + candidate, + !directoryProbablyExists(baseDirectory, state.host), + state, + ); if (resolvedFileName) { return resolvedFileName; } @@ -1571,13 +2012,23 @@ function tryLoadModuleUsingRootDirs(extensions: Extensions, moduleName: string, return undefined; } -function tryLoadModuleUsingBaseUrl(extensions: Extensions, moduleName: string, loader: ResolutionKindSpecificLoader, state: ModuleResolutionState): Resolved | undefined { +function tryLoadModuleUsingBaseUrl( + extensions: Extensions, + moduleName: string, + loader: ResolutionKindSpecificLoader, + state: ModuleResolutionState, +): Resolved | undefined { const { baseUrl } = state.compilerOptions; if (!baseUrl) { return undefined; } if (state.traceEnabled) { - trace(state.host, Diagnostics.baseUrl_option_is_set_to_0_using_this_value_to_resolve_non_relative_module_name_1, baseUrl, moduleName); + trace( + state.host, + Diagnostics.baseUrl_option_is_set_to_0_using_this_value_to_resolve_non_relative_module_name_1, + baseUrl, + moduleName, + ); } const candidate = normalizePath(combinePaths(baseUrl, moduleName)); if (state.traceEnabled) { @@ -1596,7 +2047,11 @@ function tryLoadModuleUsingBaseUrl(extensions: Extensions, moduleName: string, l export function resolveJSModule(moduleName: string, initialDir: string, host: ModuleResolutionHost): string { const { resolvedModule, failedLookupLocations } = tryResolveJSModuleWorker(moduleName, initialDir, host); if (!resolvedModule) { - throw new Error(`Could not resolve JS module '${moduleName}' starting at '${initialDir}'. Looked in: ${failedLookupLocations?.join(", ")}`); + throw new Error( + `Could not resolve JS module '${moduleName}' starting at '${initialDir}'. Looked in: ${ + failedLookupLocations?.join(", ") + }`, + ); } return resolvedModule.resolvedFileName; } @@ -1624,7 +2079,15 @@ export enum NodeResolutionFeatures { EsmMode = 1 << 5, } -function node16ModuleNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache?: ModuleResolutionCache, redirectedReference?: ResolvedProjectReference, resolutionMode?: ResolutionMode): ResolvedModuleWithFailedLookupLocations { +function node16ModuleNameResolver( + moduleName: string, + containingFile: string, + compilerOptions: CompilerOptions, + host: ModuleResolutionHost, + cache?: ModuleResolutionCache, + redirectedReference?: ResolvedProjectReference, + resolutionMode?: ResolutionMode, +): ResolvedModuleWithFailedLookupLocations { return nodeNextModuleNameResolverWorker( NodeResolutionFeatures.Node16Default, moduleName, @@ -1637,7 +2100,15 @@ function node16ModuleNameResolver(moduleName: string, containingFile: string, co ); } -function nodeNextModuleNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache?: ModuleResolutionCache, redirectedReference?: ResolvedProjectReference, resolutionMode?: ResolutionMode): ResolvedModuleWithFailedLookupLocations { +function nodeNextModuleNameResolver( + moduleName: string, + containingFile: string, + compilerOptions: CompilerOptions, + host: ModuleResolutionHost, + cache?: ModuleResolutionCache, + redirectedReference?: ResolvedProjectReference, + resolutionMode?: ResolutionMode, +): ResolvedModuleWithFailedLookupLocations { return nodeNextModuleNameResolverWorker( NodeResolutionFeatures.NodeNextDefault, moduleName, @@ -1650,19 +2121,43 @@ function nodeNextModuleNameResolver(moduleName: string, containingFile: string, ); } -function nodeNextModuleNameResolverWorker(features: NodeResolutionFeatures, moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache?: ModuleResolutionCache, redirectedReference?: ResolvedProjectReference, resolutionMode?: ResolutionMode): ResolvedModuleWithFailedLookupLocations { +function nodeNextModuleNameResolverWorker( + features: NodeResolutionFeatures, + moduleName: string, + containingFile: string, + compilerOptions: CompilerOptions, + host: ModuleResolutionHost, + cache?: ModuleResolutionCache, + redirectedReference?: ResolvedProjectReference, + resolutionMode?: ResolutionMode, +): ResolvedModuleWithFailedLookupLocations { const containingDirectory = getDirectoryPath(containingFile); // es module file or cjs-like input file, use a variant of the legacy cjs resolver that supports the selected modern features const esmMode = resolutionMode === ModuleKind.ESNext ? NodeResolutionFeatures.EsmMode : 0; - let extensions = compilerOptions.noDtsResolution ? Extensions.ImplementationFiles : Extensions.TypeScript | Extensions.JavaScript | Extensions.Declaration; + let extensions = compilerOptions.noDtsResolution ? Extensions.ImplementationFiles + : Extensions.TypeScript | Extensions.JavaScript | Extensions.Declaration; if (getResolveJsonModule(compilerOptions)) { extensions |= Extensions.Json; } - return nodeModuleNameResolverWorker(features | esmMode, moduleName, containingDirectory, compilerOptions, host, cache, extensions, /*isConfigLookup*/ false, redirectedReference); + return nodeModuleNameResolverWorker( + features | esmMode, + moduleName, + containingDirectory, + compilerOptions, + host, + cache, + extensions, + /*isConfigLookup*/ false, + redirectedReference, + ); } -function tryResolveJSModuleWorker(moduleName: string, initialDir: string, host: ModuleResolutionHost): ResolvedModuleWithFailedLookupLocations { +function tryResolveJSModuleWorker( + moduleName: string, + initialDir: string, + host: ModuleResolutionHost, +): ResolvedModuleWithFailedLookupLocations { return nodeModuleNameResolverWorker( NodeResolutionFeatures.None, moduleName, @@ -1676,18 +2171,59 @@ function tryResolveJSModuleWorker(moduleName: string, initialDir: string, host: ); } -export function bundlerModuleNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache?: ModuleResolutionCache, redirectedReference?: ResolvedProjectReference): ResolvedModuleWithFailedLookupLocations { +export function bundlerModuleNameResolver( + moduleName: string, + containingFile: string, + compilerOptions: CompilerOptions, + host: ModuleResolutionHost, + cache?: ModuleResolutionCache, + redirectedReference?: ResolvedProjectReference, +): ResolvedModuleWithFailedLookupLocations { const containingDirectory = getDirectoryPath(containingFile); - let extensions = compilerOptions.noDtsResolution ? Extensions.ImplementationFiles : Extensions.TypeScript | Extensions.JavaScript | Extensions.Declaration; + let extensions = compilerOptions.noDtsResolution ? Extensions.ImplementationFiles + : Extensions.TypeScript | Extensions.JavaScript | Extensions.Declaration; if (getResolveJsonModule(compilerOptions)) { extensions |= Extensions.Json; } - return nodeModuleNameResolverWorker(getNodeResolutionFeatures(compilerOptions), moduleName, containingDirectory, compilerOptions, host, cache, extensions, /*isConfigLookup*/ false, redirectedReference); + return nodeModuleNameResolverWorker( + getNodeResolutionFeatures(compilerOptions), + moduleName, + containingDirectory, + compilerOptions, + host, + cache, + extensions, + /*isConfigLookup*/ false, + redirectedReference, + ); } -export function nodeModuleNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache?: ModuleResolutionCache, redirectedReference?: ResolvedProjectReference): ResolvedModuleWithFailedLookupLocations; -/** @internal */ export function nodeModuleNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache?: ModuleResolutionCache, redirectedReference?: ResolvedProjectReference, lookupConfig?: boolean): ResolvedModuleWithFailedLookupLocations; // eslint-disable-line @typescript-eslint/unified-signatures -export function nodeModuleNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache?: ModuleResolutionCache, redirectedReference?: ResolvedProjectReference, isConfigLookup?: boolean): ResolvedModuleWithFailedLookupLocations { +export function nodeModuleNameResolver( + moduleName: string, + containingFile: string, + compilerOptions: CompilerOptions, + host: ModuleResolutionHost, + cache?: ModuleResolutionCache, + redirectedReference?: ResolvedProjectReference, +): ResolvedModuleWithFailedLookupLocations; +/** @internal */ export function nodeModuleNameResolver( + moduleName: string, + containingFile: string, + compilerOptions: CompilerOptions, + host: ModuleResolutionHost, + cache?: ModuleResolutionCache, + redirectedReference?: ResolvedProjectReference, + lookupConfig?: boolean, +): ResolvedModuleWithFailedLookupLocations; // eslint-disable-line @typescript-eslint/unified-signatures +export function nodeModuleNameResolver( + moduleName: string, + containingFile: string, + compilerOptions: CompilerOptions, + host: ModuleResolutionHost, + cache?: ModuleResolutionCache, + redirectedReference?: ResolvedProjectReference, + isConfigLookup?: boolean, +): ResolvedModuleWithFailedLookupLocations { let extensions; if (isConfigLookup) { extensions = Extensions.Json; @@ -1701,15 +2237,49 @@ export function nodeModuleNameResolver(moduleName: string, containingFile: strin ? Extensions.TypeScript | Extensions.JavaScript | Extensions.Declaration | Extensions.Json : Extensions.TypeScript | Extensions.JavaScript | Extensions.Declaration; } - return nodeModuleNameResolverWorker(NodeResolutionFeatures.None, moduleName, getDirectoryPath(containingFile), compilerOptions, host, cache, extensions, !!isConfigLookup, redirectedReference); + return nodeModuleNameResolverWorker( + NodeResolutionFeatures.None, + moduleName, + getDirectoryPath(containingFile), + compilerOptions, + host, + cache, + extensions, + !!isConfigLookup, + redirectedReference, + ); } /** @internal */ -export function nodeNextJsonConfigResolver(moduleName: string, containingFile: string, host: ModuleResolutionHost): ResolvedModuleWithFailedLookupLocations { - return nodeModuleNameResolverWorker(NodeResolutionFeatures.NodeNextDefault, moduleName, getDirectoryPath(containingFile), { moduleResolution: ModuleResolutionKind.NodeNext }, host, /*cache*/ undefined, Extensions.Json, /*isConfigLookup*/ true, /*redirectedReference*/ undefined); +export function nodeNextJsonConfigResolver( + moduleName: string, + containingFile: string, + host: ModuleResolutionHost, +): ResolvedModuleWithFailedLookupLocations { + return nodeModuleNameResolverWorker( + NodeResolutionFeatures.NodeNextDefault, + moduleName, + getDirectoryPath(containingFile), + { moduleResolution: ModuleResolutionKind.NodeNext }, + host, + /*cache*/ undefined, + Extensions.Json, + /*isConfigLookup*/ true, + /*redirectedReference*/ undefined, + ); } -function nodeModuleNameResolverWorker(features: NodeResolutionFeatures, moduleName: string, containingDirectory: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache: ModuleResolutionCache | undefined, extensions: Extensions, isConfigLookup: boolean, redirectedReference: ResolvedProjectReference | undefined): ResolvedModuleWithFailedLookupLocations { +function nodeModuleNameResolverWorker( + features: NodeResolutionFeatures, + moduleName: string, + containingDirectory: string, + compilerOptions: CompilerOptions, + host: ModuleResolutionHost, + cache: ModuleResolutionCache | undefined, + extensions: Extensions, + isConfigLookup: boolean, + redirectedReference: ResolvedProjectReference | undefined, +): ResolvedModuleWithFailedLookupLocations { const traceEnabled = isTraceEnabled(compilerOptions, host); const failedLookupLocations: string[] = []; @@ -1732,17 +2302,25 @@ function nodeModuleNameResolverWorker(features: NodeResolutionFeatures, moduleNa candidateIsFromPackageJsonField: false, }; - if (traceEnabled && moduleResolutionSupportsPackageJsonExportsAndImports(getEmitModuleResolutionKind(compilerOptions))) { - trace(host, Diagnostics.Resolving_in_0_mode_with_conditions_1, features & NodeResolutionFeatures.EsmMode ? "ESM" : "CJS", conditions.map(c => `'${c}'`).join(", ")); + if ( + traceEnabled + && moduleResolutionSupportsPackageJsonExportsAndImports(getEmitModuleResolutionKind(compilerOptions)) + ) { + trace( + host, + Diagnostics.Resolving_in_0_mode_with_conditions_1, + features & NodeResolutionFeatures.EsmMode ? "ESM" : "CJS", + conditions.map(c => `'${c}'`).join(", "), + ); } let result; if (getEmitModuleResolutionKind(compilerOptions) === ModuleResolutionKind.Node10) { const priorityExtensions = extensions & (Extensions.TypeScript | Extensions.Declaration); const secondaryExtensions = extensions & ~(Extensions.TypeScript | Extensions.Declaration); - result = priorityExtensions && tryResolve(priorityExtensions, state) || - secondaryExtensions && tryResolve(secondaryExtensions, state) || - undefined; + result = priorityExtensions && tryResolve(priorityExtensions, state) + || secondaryExtensions && tryResolve(secondaryExtensions, state) + || undefined; } else { result = tryResolve(extensions, state); @@ -1760,13 +2338,20 @@ function nodeModuleNameResolverWorker(features: NodeResolutionFeatures, moduleNa && !extensionIsOk(Extensions.TypeScript | Extensions.Declaration, result.value.resolved.extension) && conditions.indexOf("import") > -1 ) { - traceIfEnabled(state, Diagnostics.Resolution_of_non_relative_name_failed_trying_with_modern_Node_resolution_features_disabled_to_see_if_npm_library_needs_configuration_update); + traceIfEnabled( + state, + Diagnostics + .Resolution_of_non_relative_name_failed_trying_with_modern_Node_resolution_features_disabled_to_see_if_npm_library_needs_configuration_update, + ); const diagnosticState = { ...state, features: state.features & ~NodeResolutionFeatures.Exports, reportDiagnostic: noop, }; - const diagnosticResult = tryResolve(extensions & (Extensions.TypeScript | Extensions.Declaration), diagnosticState); + const diagnosticResult = tryResolve( + extensions & (Extensions.TypeScript | Extensions.Declaration), + diagnosticState, + ); if (diagnosticResult?.value?.isExternalLibraryImport) { legacyResult = diagnosticResult.value.resolved.path; } @@ -1783,9 +2368,25 @@ function nodeModuleNameResolverWorker(features: NodeResolutionFeatures, moduleNa legacyResult, ); - function tryResolve(extensions: Extensions, state: ModuleResolutionState): SearchResult<{ resolved: Resolved; isExternalLibraryImport: boolean; }> { - const loader: ResolutionKindSpecificLoader = (extensions, candidate, onlyRecordFailures, state) => nodeLoadModuleByRelativeName(extensions, candidate, onlyRecordFailures, state, /*considerPackageJson*/ true); - const resolved = tryLoadModuleUsingOptionalResolutionSettings(extensions, moduleName, containingDirectory, loader, state); + function tryResolve( + extensions: Extensions, + state: ModuleResolutionState, + ): SearchResult<{ resolved: Resolved; isExternalLibraryImport: boolean; }> { + const loader: ResolutionKindSpecificLoader = (extensions, candidate, onlyRecordFailures, state) => + nodeLoadModuleByRelativeName( + extensions, + candidate, + onlyRecordFailures, + state, + /*considerPackageJson*/ true, + ); + const resolved = tryLoadModuleUsingOptionalResolutionSettings( + extensions, + moduleName, + containingDirectory, + loader, + state, + ); if (resolved) { return toSearchResult({ resolved, isExternalLibraryImport: pathContainsNodeModules(resolved.path) }); } @@ -1793,22 +2394,53 @@ function nodeModuleNameResolverWorker(features: NodeResolutionFeatures, moduleNa if (!isExternalModuleNameRelative(moduleName)) { let resolved: SearchResult | undefined; if (features & NodeResolutionFeatures.Imports && startsWith(moduleName, "#")) { - resolved = loadModuleFromImports(extensions, moduleName, containingDirectory, state, cache, redirectedReference); + resolved = loadModuleFromImports( + extensions, + moduleName, + containingDirectory, + state, + cache, + redirectedReference, + ); } if (!resolved && features & NodeResolutionFeatures.SelfName) { - resolved = loadModuleFromSelfNameReference(extensions, moduleName, containingDirectory, state, cache, redirectedReference); + resolved = loadModuleFromSelfNameReference( + extensions, + moduleName, + containingDirectory, + state, + cache, + redirectedReference, + ); } if (!resolved) { if (moduleName.indexOf(":") > -1) { if (traceEnabled) { - trace(host, Diagnostics.Skipping_module_0_that_looks_like_an_absolute_URI_target_file_types_Colon_1, moduleName, formatExtensions(extensions)); + trace( + host, + Diagnostics.Skipping_module_0_that_looks_like_an_absolute_URI_target_file_types_Colon_1, + moduleName, + formatExtensions(extensions), + ); } return undefined; } if (traceEnabled) { - trace(host, Diagnostics.Loading_module_0_from_node_modules_folder_target_file_types_Colon_1, moduleName, formatExtensions(extensions)); + trace( + host, + Diagnostics.Loading_module_0_from_node_modules_folder_target_file_types_Colon_1, + moduleName, + formatExtensions(extensions), + ); } - resolved = loadModuleFromNearestNodeModulesDirectory(extensions, moduleName, containingDirectory, state, cache, redirectedReference); + resolved = loadModuleFromNearestNodeModulesDirectory( + extensions, + moduleName, + containingDirectory, + state, + cache, + redirectedReference, + ); } if (extensions & Extensions.Declaration) { resolved ??= resolveFromTypeRoot(moduleName, state); @@ -1818,7 +2450,13 @@ function nodeModuleNameResolverWorker(features: NodeResolutionFeatures, moduleNa } else { const { path: candidate, parts } = normalizePathForCJSResolution(containingDirectory, moduleName); - const resolved = nodeLoadModuleByRelativeName(extensions, candidate, /*onlyRecordFailures*/ false, state, /*considerPackageJson*/ true); + const resolved = nodeLoadModuleByRelativeName( + extensions, + candidate, + /*onlyRecordFailures*/ false, + state, + /*considerPackageJson*/ true, + ); // Treat explicit "node_modules" import as an external library import. return resolved && toSearchResult({ resolved, isExternalLibraryImport: contains(parts, "node_modules") }); } @@ -1834,7 +2472,8 @@ function normalizePathForCJSResolution(containingDirectory: string, moduleName: const combined = combinePaths(containingDirectory, moduleName); const parts = getPathComponents(combined); const lastPart = lastOrUndefined(parts); - const path = lastPart === "." || lastPart === ".." ? ensureTrailingDirectorySeparator(normalizePath(combined)) : normalizePath(combined); + const path = lastPart === "." || lastPart === ".." ? ensureTrailingDirectorySeparator(normalizePath(combined)) + : normalizePath(combined); return { path, parts }; } @@ -1851,16 +2490,31 @@ function realPath(path: string, host: ModuleResolutionHost, traceEnabled: boolea return real; } -function nodeLoadModuleByRelativeName(extensions: Extensions, candidate: string, onlyRecordFailures: boolean, state: ModuleResolutionState, considerPackageJson: boolean): Resolved | undefined { +function nodeLoadModuleByRelativeName( + extensions: Extensions, + candidate: string, + onlyRecordFailures: boolean, + state: ModuleResolutionState, + considerPackageJson: boolean, +): Resolved | undefined { if (state.traceEnabled) { - trace(state.host, Diagnostics.Loading_module_as_file_Slash_folder_candidate_module_location_0_target_file_types_Colon_1, candidate, formatExtensions(extensions)); + trace( + state.host, + Diagnostics.Loading_module_as_file_Slash_folder_candidate_module_location_0_target_file_types_Colon_1, + candidate, + formatExtensions(extensions), + ); } if (!hasTrailingDirectorySeparator(candidate)) { if (!onlyRecordFailures) { const parentOfCandidate = getDirectoryPath(candidate); if (!directoryProbablyExists(parentOfCandidate, state.host)) { if (state.traceEnabled) { - trace(state.host, Diagnostics.Directory_0_does_not_exist_skipping_all_lookups_in_it, parentOfCandidate); + trace( + state.host, + Diagnostics.Directory_0_does_not_exist_skipping_all_lookups_in_it, + parentOfCandidate, + ); } onlyRecordFailures = true; } @@ -1868,7 +2522,8 @@ function nodeLoadModuleByRelativeName(extensions: Extensions, candidate: string, const resolvedFromFile = loadModuleFromFile(extensions, candidate, onlyRecordFailures, state); if (resolvedFromFile) { const packageDirectory = considerPackageJson ? parseNodeModuleFromPath(resolvedFromFile.path) : undefined; - const packageInfo = packageDirectory ? getPackageJsonInfo(packageDirectory, /*onlyRecordFailures*/ false, state) : undefined; + const packageInfo = packageDirectory + ? getPackageJsonInfo(packageDirectory, /*onlyRecordFailures*/ false, state) : undefined; return withPackageId(packageInfo, resolvedFromFile); } } @@ -1924,12 +2579,21 @@ export function parseNodeModuleFromPath(resolved: string, isFolder?: boolean): s return path.slice(0, indexAfterPackageName); } -function moveToNextDirectorySeparatorIfAvailable(path: string, prevSeparatorIndex: number, isFolder: boolean | undefined): number { +function moveToNextDirectorySeparatorIfAvailable( + path: string, + prevSeparatorIndex: number, + isFolder: boolean | undefined, +): number { const nextSeparatorIndex = path.indexOf(directorySeparator, prevSeparatorIndex + 1); return nextSeparatorIndex === -1 ? isFolder ? path.length : prevSeparatorIndex : nextSeparatorIndex; } -function loadModuleFromFileNoPackageId(extensions: Extensions, candidate: string, onlyRecordFailures: boolean, state: ModuleResolutionState): Resolved | undefined { +function loadModuleFromFileNoPackageId( + extensions: Extensions, + candidate: string, + onlyRecordFailures: boolean, + state: ModuleResolutionState, +): Resolved | undefined { return noPackageId(loadModuleFromFile(extensions, candidate, onlyRecordFailures, state)); } @@ -1937,9 +2601,19 @@ function loadModuleFromFileNoPackageId(extensions: Extensions, candidate: string * @param {boolean} onlyRecordFailures - if true then function won't try to actually load files but instead record all attempts as failures. This flag is necessary * in cases when we know upfront that all load attempts will fail (because containing folder does not exists) however we still need to record all failed lookup locations. */ -function loadModuleFromFile(extensions: Extensions, candidate: string, onlyRecordFailures: boolean, state: ModuleResolutionState): PathAndExtension | undefined { +function loadModuleFromFile( + extensions: Extensions, + candidate: string, + onlyRecordFailures: boolean, + state: ModuleResolutionState, +): PathAndExtension | undefined { // ./foo.js -> ./foo.ts - const resolvedByReplacingExtension = loadModuleFromFileNoImplicitExtensions(extensions, candidate, onlyRecordFailures, state); + const resolvedByReplacingExtension = loadModuleFromFileNoImplicitExtensions( + extensions, + candidate, + onlyRecordFailures, + state, + ); if (resolvedByReplacingExtension) { return resolvedByReplacingExtension; } @@ -1954,7 +2628,12 @@ function loadModuleFromFile(extensions: Extensions, candidate: string, onlyRecor } } -function loadModuleFromFileNoImplicitExtensions(extensions: Extensions, candidate: string, onlyRecordFailures: boolean, state: ModuleResolutionState): PathAndExtension | undefined { +function loadModuleFromFileNoImplicitExtensions( + extensions: Extensions, + candidate: string, + onlyRecordFailures: boolean, + state: ModuleResolutionState, +): PathAndExtension | undefined { const filename = getBaseFileName(candidate); if (filename.indexOf(".") === -1) { return undefined; // extensionless import, no lookups performed, since we don't support extensionless files @@ -1978,25 +2657,42 @@ function loadModuleFromFileNoImplicitExtensions(extensions: Extensions, candidat * candidate to end with a TS extension (but will also try substituting a JS extension for a TS extension). */ -function loadFileNameFromPackageJsonField(extensions: Extensions, candidate: string, onlyRecordFailures: boolean, state: ModuleResolutionState): PathAndExtension | undefined { +function loadFileNameFromPackageJsonField( + extensions: Extensions, + candidate: string, + onlyRecordFailures: boolean, + state: ModuleResolutionState, +): PathAndExtension | undefined { if ( - extensions & Extensions.TypeScript && fileExtensionIsOneOf(candidate, supportedTSImplementationExtensions) || - extensions & Extensions.Declaration && fileExtensionIsOneOf(candidate, supportedDeclarationExtensions) + extensions & Extensions.TypeScript && fileExtensionIsOneOf(candidate, supportedTSImplementationExtensions) + || extensions & Extensions.Declaration && fileExtensionIsOneOf(candidate, supportedDeclarationExtensions) ) { const result = tryFile(candidate, onlyRecordFailures, state); - return result !== undefined ? { path: candidate, ext: tryExtractTSExtension(candidate) as Extension, resolvedUsingTsExtension: undefined } : undefined; + return result !== undefined + ? { + path: candidate, + ext: tryExtractTSExtension(candidate) as Extension, + resolvedUsingTsExtension: undefined, + } : undefined; } if (state.isConfigLookup && extensions === Extensions.Json && fileExtensionIs(candidate, Extension.Json)) { const result = tryFile(candidate, onlyRecordFailures, state); - return result !== undefined ? { path: candidate, ext: Extension.Json, resolvedUsingTsExtension: undefined } : undefined; + return result !== undefined ? { path: candidate, ext: Extension.Json, resolvedUsingTsExtension: undefined } + : undefined; } return loadModuleFromFileNoImplicitExtensions(extensions, candidate, onlyRecordFailures, state); } /** Try to return an existing file that adds one of the `extensions` to `candidate`. */ -function tryAddingExtensions(candidate: string, extensions: Extensions, originalExtension: string, onlyRecordFailures: boolean, state: ModuleResolutionState): PathAndExtension | undefined { +function tryAddingExtensions( + candidate: string, + extensions: Extensions, + originalExtension: string, + onlyRecordFailures: boolean, + state: ModuleResolutionState, +): PathAndExtension | undefined { if (!onlyRecordFailures) { // check if containing folder exists - if it doesn't then just record failures for all supported extensions without disk probing const directory = getDirectoryPath(candidate); @@ -2009,15 +2705,31 @@ function tryAddingExtensions(candidate: string, extensions: Extensions, original case Extension.Mjs: case Extension.Mts: case Extension.Dmts: - return extensions & Extensions.TypeScript && tryExtension(Extension.Mts, originalExtension === Extension.Mts || originalExtension === Extension.Dmts) - || extensions & Extensions.Declaration && tryExtension(Extension.Dmts, originalExtension === Extension.Mts || originalExtension === Extension.Dmts) + return extensions & Extensions.TypeScript + && tryExtension( + Extension.Mts, + originalExtension === Extension.Mts || originalExtension === Extension.Dmts, + ) + || extensions & Extensions.Declaration + && tryExtension( + Extension.Dmts, + originalExtension === Extension.Mts || originalExtension === Extension.Dmts, + ) || extensions & Extensions.JavaScript && tryExtension(Extension.Mjs) || undefined; case Extension.Cjs: case Extension.Cts: case Extension.Dcts: - return extensions & Extensions.TypeScript && tryExtension(Extension.Cts, originalExtension === Extension.Cts || originalExtension === Extension.Dcts) - || extensions & Extensions.Declaration && tryExtension(Extension.Dcts, originalExtension === Extension.Cts || originalExtension === Extension.Dcts) + return extensions & Extensions.TypeScript + && tryExtension( + Extension.Cts, + originalExtension === Extension.Cts || originalExtension === Extension.Dcts, + ) + || extensions & Extensions.Declaration + && tryExtension( + Extension.Dcts, + originalExtension === Extension.Cts || originalExtension === Extension.Dcts, + ) || extensions & Extensions.JavaScript && tryExtension(Extension.Cjs) || undefined; case Extension.Json: @@ -2029,27 +2741,48 @@ function tryAddingExtensions(candidate: string, extensions: Extensions, original // basically idendical to the ts/js case below, but prefers matching tsx and jsx files exactly before falling back to the ts or js file path // (historically, we disallow having both a a.ts and a.tsx file in the same compilation, since their outputs clash) // TODO: We should probably error if `"./a.tsx"` resolved to `"./a.ts"`, right? - return extensions & Extensions.TypeScript && (tryExtension(Extension.Tsx, originalExtension === Extension.Tsx) || tryExtension(Extension.Ts, originalExtension === Extension.Tsx)) - || extensions & Extensions.Declaration && tryExtension(Extension.Dts, originalExtension === Extension.Tsx) + return extensions & Extensions.TypeScript + && (tryExtension(Extension.Tsx, originalExtension === Extension.Tsx) + || tryExtension(Extension.Ts, originalExtension === Extension.Tsx)) + || extensions & Extensions.Declaration + && tryExtension(Extension.Dts, originalExtension === Extension.Tsx) || extensions & Extensions.JavaScript && (tryExtension(Extension.Jsx) || tryExtension(Extension.Js)) || undefined; case Extension.Ts: case Extension.Dts: case Extension.Js: case "": - return extensions & Extensions.TypeScript && (tryExtension(Extension.Ts, originalExtension === Extension.Ts || originalExtension === Extension.Dts) || tryExtension(Extension.Tsx, originalExtension === Extension.Ts || originalExtension === Extension.Dts)) - || extensions & Extensions.Declaration && tryExtension(Extension.Dts, originalExtension === Extension.Ts || originalExtension === Extension.Dts) + return extensions & Extensions.TypeScript + && (tryExtension( + Extension.Ts, + originalExtension === Extension.Ts || originalExtension === Extension.Dts, + ) + || tryExtension( + Extension.Tsx, + originalExtension === Extension.Ts || originalExtension === Extension.Dts, + )) + || extensions & Extensions.Declaration + && tryExtension( + Extension.Dts, + originalExtension === Extension.Ts || originalExtension === Extension.Dts, + ) || extensions & Extensions.JavaScript && (tryExtension(Extension.Js) || tryExtension(Extension.Jsx)) || state.isConfigLookup && tryExtension(Extension.Json) || undefined; default: - return extensions & Extensions.Declaration && !isDeclarationFileName(candidate + originalExtension) && tryExtension(`.d${originalExtension}.ts`) + return extensions & Extensions.Declaration && !isDeclarationFileName(candidate + originalExtension) + && tryExtension(`.d${originalExtension}.ts`) || undefined; } function tryExtension(ext: string, resolvedUsingTsExtension?: boolean): PathAndExtension | undefined { const path = tryFile(candidate + ext, onlyRecordFailures, state); - return path === undefined ? undefined : { path, ext, resolvedUsingTsExtension: !state.candidateIsFromPackageJsonField && resolvedUsingTsExtension }; + return path === undefined ? undefined + : { + path, + ext, + resolvedUsingTsExtension: !state.candidateIsFromPackageJsonField && resolvedUsingTsExtension, + }; } } @@ -2061,10 +2794,17 @@ function tryFile(fileName: string, onlyRecordFailures: boolean, state: ModuleRes const ext = tryGetExtensionFromPath(fileName) ?? ""; const fileNameNoExtension = ext ? removeExtension(fileName, ext) : fileName; - return forEach(state.compilerOptions.moduleSuffixes, suffix => tryFileLookup(fileNameNoExtension + suffix + ext, onlyRecordFailures, state)); + return forEach( + state.compilerOptions.moduleSuffixes, + suffix => tryFileLookup(fileNameNoExtension + suffix + ext, onlyRecordFailures, state), + ); } -function tryFileLookup(fileName: string, onlyRecordFailures: boolean, state: ModuleResolutionState): string | undefined { +function tryFileLookup( + fileName: string, + onlyRecordFailures: boolean, + state: ModuleResolutionState, +): string | undefined { if (!onlyRecordFailures) { if (state.host.fileExists(fileName)) { if (state.traceEnabled) { @@ -2082,11 +2822,27 @@ function tryFileLookup(fileName: string, onlyRecordFailures: boolean, state: Mod return undefined; } -function loadNodeModuleFromDirectory(extensions: Extensions, candidate: string, onlyRecordFailures: boolean, state: ModuleResolutionState, considerPackageJson = true) { +function loadNodeModuleFromDirectory( + extensions: Extensions, + candidate: string, + onlyRecordFailures: boolean, + state: ModuleResolutionState, + considerPackageJson = true, +) { const packageInfo = considerPackageJson ? getPackageJsonInfo(candidate, onlyRecordFailures, state) : undefined; const packageJsonContent = packageInfo && packageInfo.contents.packageJsonContent; const versionPaths = packageInfo && getVersionPathsOfPackageJsonInfo(packageInfo, state); - return withPackageId(packageInfo, loadNodeModuleFromDirectoryWorker(extensions, candidate, onlyRecordFailures, state, packageJsonContent, versionPaths)); + return withPackageId( + packageInfo, + loadNodeModuleFromDirectoryWorker( + extensions, + candidate, + onlyRecordFailures, + state, + packageJsonContent, + versionPaths, + ), + ); } /** @internal */ @@ -2130,7 +2886,12 @@ export function getEntrypointsFromPackageJsonInfo( arrayIsEqualTo, ); for (const conditions of conditionSets) { - const loadPackageJsonExportsState = { ...loadPackageJsonMainState, failedLookupLocations: [], conditions, host }; + const loadPackageJsonExportsState = { + ...loadPackageJsonMainState, + failedLookupLocations: [], + conditions, + host, + }; const exportResolutions = loadEntrypointsFromExportMap( packageJsonInfo, packageJsonInfo.contents.packageJsonContent.exports, @@ -2193,12 +2954,20 @@ function loadEntrypointsFromExportMap( } else { const partsAfterFirst = getPathComponents(target).slice(2); - if (partsAfterFirst.indexOf("..") >= 0 || partsAfterFirst.indexOf(".") >= 0 || partsAfterFirst.indexOf("node_modules") >= 0) { + if ( + partsAfterFirst.indexOf("..") >= 0 || partsAfterFirst.indexOf(".") >= 0 + || partsAfterFirst.indexOf("node_modules") >= 0 + ) { return false; } const resolvedTarget = combinePaths(scope.packageDirectory, target); const finalPath = getNormalizedAbsolutePath(resolvedTarget, state.host.getCurrentDirectory?.()); - const result = loadFileNameFromPackageJsonField(extensions, finalPath, /*onlyRecordFailures*/ false, state); + const result = loadFileNameFromPackageJsonField( + extensions, + finalPath, + /*onlyRecordFailures*/ false, + state, + ); if (result) { entrypoints = appendIfUnique(entrypoints, result, (a, b) => a.path === b.path); return true; @@ -2216,7 +2985,10 @@ function loadEntrypointsFromExportMap( // eslint-disable-next-line no-null/no-null else if (typeof target === "object" && target !== null) { return forEach(getOwnKeys(target as MapLike), key => { - if (key === "default" || contains(state.conditions, key) || isApplicableVersionedTypesKey(state.conditions, key)) { + if ( + key === "default" || contains(state.conditions, key) + || isApplicableVersionedTypesKey(state.conditions, key) + ) { loadEntrypointsFromTargetExports((target as MapLike)[key]); return true; } @@ -2226,7 +2998,11 @@ function loadEntrypointsFromExportMap( } /** @internal */ -export function getTemporaryModuleResolutionState(packageJsonInfoCache: PackageJsonInfoCache | undefined, host: ModuleResolutionHost, options: CompilerOptions): ModuleResolutionState { +export function getTemporaryModuleResolutionState( + packageJsonInfoCache: PackageJsonInfoCache | undefined, + host: ModuleResolutionHost, + options: CompilerOptions, +): ModuleResolutionState { return { host, compilerOptions: options, @@ -2275,15 +3051,23 @@ export function getPackageScopeForPath(fileName: string, state: ModuleResolution return undefined; } -function getVersionPathsOfPackageJsonInfo(packageJsonInfo: PackageJsonInfo, state: ModuleResolutionState): VersionPaths | undefined { +function getVersionPathsOfPackageJsonInfo( + packageJsonInfo: PackageJsonInfo, + state: ModuleResolutionState, +): VersionPaths | undefined { if (packageJsonInfo.contents.versionPaths === undefined) { - packageJsonInfo.contents.versionPaths = readPackageJsonTypesVersionPaths(packageJsonInfo.contents.packageJsonContent, state) || false; + packageJsonInfo.contents.versionPaths = + readPackageJsonTypesVersionPaths(packageJsonInfo.contents.packageJsonContent, state) || false; } return packageJsonInfo.contents.versionPaths || undefined; } /** @internal */ -export function getPackageJsonInfo(packageDirectory: string, onlyRecordFailures: boolean, state: ModuleResolutionState): PackageJsonInfo | undefined { +export function getPackageJsonInfo( + packageDirectory: string, + onlyRecordFailures: boolean, + state: ModuleResolutionState, +): PackageJsonInfo | undefined { const { host, traceEnabled } = state; const packageJsonPath = combinePaths(packageDirectory, "package.json"); if (onlyRecordFailures) { @@ -2294,14 +3078,18 @@ export function getPackageJsonInfo(packageDirectory: string, onlyRecordFailures: const existing = state.packageJsonInfoCache?.getPackageJsonInfo(packageJsonPath); if (existing !== undefined) { if (typeof existing !== "boolean") { - if (traceEnabled) trace(host, Diagnostics.File_0_exists_according_to_earlier_cached_lookups, packageJsonPath); + if (traceEnabled) { + trace(host, Diagnostics.File_0_exists_according_to_earlier_cached_lookups, packageJsonPath); + } state.affectingLocations?.push(packageJsonPath); - return existing.packageDirectory === packageDirectory ? - existing : - { packageDirectory, contents: existing.contents }; + return existing.packageDirectory === packageDirectory + ? existing + : { packageDirectory, contents: existing.contents }; } else { - if (existing && traceEnabled) trace(host, Diagnostics.File_0_does_not_exist_according_to_earlier_cached_lookups, packageJsonPath); + if (existing && traceEnabled) { + trace(host, Diagnostics.File_0_does_not_exist_according_to_earlier_cached_lookups, packageJsonPath); + } state.failedLookupLocations?.push(packageJsonPath); return undefined; } @@ -2312,7 +3100,10 @@ export function getPackageJsonInfo(packageDirectory: string, onlyRecordFailures: if (traceEnabled) { trace(host, Diagnostics.Found_package_json_at_0, packageJsonPath); } - const result: PackageJsonInfo = { packageDirectory, contents: { packageJsonContent, versionPaths: undefined, resolvedEntrypoints: undefined } }; + const result: PackageJsonInfo = { + packageDirectory, + contents: { packageJsonContent, versionPaths: undefined, resolvedEntrypoints: undefined }, + }; state.packageJsonInfoCache?.setPackageJsonInfo(packageJsonPath, result); state.affectingLocations?.push(packageJsonPath); return result; @@ -2327,16 +3118,25 @@ export function getPackageJsonInfo(packageDirectory: string, onlyRecordFailures: } } -function loadNodeModuleFromDirectoryWorker(extensions: Extensions, candidate: string, onlyRecordFailures: boolean, state: ModuleResolutionState, jsonContent: PackageJsonPathFields | undefined, versionPaths: VersionPaths | undefined): PathAndExtension | undefined { +function loadNodeModuleFromDirectoryWorker( + extensions: Extensions, + candidate: string, + onlyRecordFailures: boolean, + state: ModuleResolutionState, + jsonContent: PackageJsonPathFields | undefined, + versionPaths: VersionPaths | undefined, +): PathAndExtension | undefined { let packageFile: string | undefined; if (jsonContent) { if (state.isConfigLookup) { packageFile = readPackageJsonTSConfigField(jsonContent, candidate, state); } else { - packageFile = extensions & Extensions.Declaration && readPackageJsonTypesFields(jsonContent, candidate, state) || - extensions & (Extensions.ImplementationFiles | Extensions.Declaration) && readPackageJsonMainField(jsonContent, candidate, state) || - undefined; + packageFile = + extensions & Extensions.Declaration && readPackageJsonTypesFields(jsonContent, candidate, state) + || extensions & (Extensions.ImplementationFiles | Extensions.Declaration) + && readPackageJsonMainField(jsonContent, candidate, state) + || undefined; } } @@ -2353,7 +3153,8 @@ function loadNodeModuleFromDirectoryWorker(extensions: Extensions, candidate: st } // Even if extensions is DtsOnly, we can still look up a .ts file as a result of package.json "types" - const expandedExtensions = extensions === Extensions.Declaration ? Extensions.TypeScript | Extensions.Declaration : extensions; + const expandedExtensions = extensions === Extensions.Declaration + ? Extensions.TypeScript | Extensions.Declaration : extensions; // Don't do package.json lookup recursively, because Node.js' package lookup doesn't. // Disable `EsmMode` for the resolution of the package path for cjs-mode packages (so the `main` field can omit extensions) @@ -2365,29 +3166,53 @@ function loadNodeModuleFromDirectoryWorker(extensions: Extensions, candidate: st if (jsonContent?.type !== "module") { state.features &= ~NodeResolutionFeatures.EsmMode; } - const result = nodeLoadModuleByRelativeName(expandedExtensions, candidate, onlyRecordFailures, state, /*considerPackageJson*/ false); + const result = nodeLoadModuleByRelativeName( + expandedExtensions, + candidate, + onlyRecordFailures, + state, + /*considerPackageJson*/ false, + ); state.features = features; state.candidateIsFromPackageJsonField = candidateIsFromPackageJsonField; return result; }; - const onlyRecordFailuresForPackageFile = packageFile ? !directoryProbablyExists(getDirectoryPath(packageFile), state.host) : undefined; + const onlyRecordFailuresForPackageFile = packageFile + ? !directoryProbablyExists(getDirectoryPath(packageFile), state.host) : undefined; const onlyRecordFailuresForIndex = onlyRecordFailures || !directoryProbablyExists(candidate, state.host); const indexPath = combinePaths(candidate, state.isConfigLookup ? "tsconfig" : "index"); if (versionPaths && (!packageFile || containsPath(candidate, packageFile))) { const moduleName = getRelativePathFromDirectory(candidate, packageFile || indexPath, /*ignoreCase*/ false); if (state.traceEnabled) { - trace(state.host, Diagnostics.package_json_has_a_typesVersions_entry_0_that_matches_compiler_version_1_looking_for_a_pattern_to_match_module_name_2, versionPaths.version, version, moduleName); + trace( + state.host, + Diagnostics + .package_json_has_a_typesVersions_entry_0_that_matches_compiler_version_1_looking_for_a_pattern_to_match_module_name_2, + versionPaths.version, + version, + moduleName, + ); } - const result = tryLoadModuleUsingPaths(extensions, moduleName, candidate, versionPaths.paths, /*pathPatterns*/ undefined, loader, onlyRecordFailuresForPackageFile || onlyRecordFailuresForIndex, state); + const result = tryLoadModuleUsingPaths( + extensions, + moduleName, + candidate, + versionPaths.paths, + /*pathPatterns*/ undefined, + loader, + onlyRecordFailuresForPackageFile || onlyRecordFailuresForIndex, + state, + ); if (result) { return removeIgnoredPackageId(result.value); } } // It won't have a `packageId` set, because we disabled `considerPackageJson`. - const packageFileResult = packageFile && removeIgnoredPackageId(loader(extensions, packageFile, onlyRecordFailuresForPackageFile!, state)); + const packageFileResult = packageFile + && removeIgnoredPackageId(loader(extensions, packageFile, onlyRecordFailuresForPackageFile!, state)); if (packageFileResult) return packageFileResult; // esm mode resolutions don't do package `index` lookups @@ -2397,16 +3222,25 @@ function loadNodeModuleFromDirectoryWorker(extensions: Extensions, candidate: st } /** Resolve from an arbitrarily specified file. Return `undefined` if it has an unsupported extension. */ -function resolvedIfExtensionMatches(extensions: Extensions, path: string, resolvedUsingTsExtension?: boolean): PathAndExtension | undefined { +function resolvedIfExtensionMatches( + extensions: Extensions, + path: string, + resolvedUsingTsExtension?: boolean, +): PathAndExtension | undefined { const ext = tryGetExtensionFromPath(path); return ext !== undefined && extensionIsOk(extensions, ext) ? { path, ext, resolvedUsingTsExtension } : undefined; } /** True if `extension` is one of the supported `extensions`. */ function extensionIsOk(extensions: Extensions, extension: string): boolean { - return extensions & Extensions.JavaScript && (extension === Extension.Js || extension === Extension.Jsx || extension === Extension.Mjs || extension === Extension.Cjs) - || extensions & Extensions.TypeScript && (extension === Extension.Ts || extension === Extension.Tsx || extension === Extension.Mts || extension === Extension.Cts) - || extensions & Extensions.Declaration && (extension === Extension.Dts || extension === Extension.Dmts || extension === Extension.Dcts) + return extensions & Extensions.JavaScript + && (extension === Extension.Js || extension === Extension.Jsx || extension === Extension.Mjs + || extension === Extension.Cjs) + || extensions & Extensions.TypeScript + && (extension === Extension.Ts || extension === Extension.Tsx || extension === Extension.Mts + || extension === Extension.Cts) + || extensions & Extensions.Declaration + && (extension === Extension.Dts || extension === Extension.Dmts || extension === Extension.Dcts) || extensions & Extensions.Json && extension === Extension.Json || false; } @@ -2417,7 +3251,8 @@ export function parsePackageName(moduleName: string): { packageName: string; res if (moduleName[0] === "@") { idx = moduleName.indexOf(directorySeparator, idx + 1); } - return idx === -1 ? { packageName: moduleName, rest: "" } : { packageName: moduleName.slice(0, idx), rest: moduleName.slice(idx + 1) }; + return idx === -1 ? { packageName: moduleName, rest: "" } + : { packageName: moduleName.slice(0, idx), rest: moduleName.slice(idx + 1) }; } /** @internal */ @@ -2429,8 +3264,18 @@ function noKeyStartsWithDot(obj: MapLike) { return !some(getOwnKeys(obj), k => startsWith(k, ".")); } -function loadModuleFromSelfNameReference(extensions: Extensions, moduleName: string, directory: string, state: ModuleResolutionState, cache: ModuleResolutionCache | undefined, redirectedReference: ResolvedProjectReference | undefined): SearchResult { - const directoryPath = getNormalizedAbsolutePath(combinePaths(directory, "dummy"), state.host.getCurrentDirectory?.()); +function loadModuleFromSelfNameReference( + extensions: Extensions, + moduleName: string, + directory: string, + state: ModuleResolutionState, + cache: ModuleResolutionCache | undefined, + redirectedReference: ResolvedProjectReference | undefined, +): SearchResult { + const directoryPath = getNormalizedAbsolutePath( + combinePaths(directory, "dummy"), + state.host.getCurrentDirectory?.(), + ); const scope = getPackageScopeForPath(directoryPath, state); if (!scope || !scope.contents.packageJsonContent.exports) { return undefined; @@ -2467,55 +3312,108 @@ function loadModuleFromSelfNameReference(extensions: Extensions, moduleName: str || loadModuleFromExports(scope, secondaryExtensions, subpath, state, cache, redirectedReference); } -function loadModuleFromExports(scope: PackageJsonInfo, extensions: Extensions, subpath: string, state: ModuleResolutionState, cache: ModuleResolutionCache | undefined, redirectedReference: ResolvedProjectReference | undefined): SearchResult { +function loadModuleFromExports( + scope: PackageJsonInfo, + extensions: Extensions, + subpath: string, + state: ModuleResolutionState, + cache: ModuleResolutionCache | undefined, + redirectedReference: ResolvedProjectReference | undefined, +): SearchResult { if (!scope.contents.packageJsonContent.exports) { return undefined; } if (subpath === ".") { let mainExport; - if (typeof scope.contents.packageJsonContent.exports === "string" || Array.isArray(scope.contents.packageJsonContent.exports) || (typeof scope.contents.packageJsonContent.exports === "object" && noKeyStartsWithDot(scope.contents.packageJsonContent.exports as MapLike))) { + if ( + typeof scope.contents.packageJsonContent.exports === "string" + || Array.isArray(scope.contents.packageJsonContent.exports) + || (typeof scope.contents.packageJsonContent.exports === "object" + && noKeyStartsWithDot(scope.contents.packageJsonContent.exports as MapLike)) + ) { mainExport = scope.contents.packageJsonContent.exports; } else if (hasProperty(scope.contents.packageJsonContent.exports as MapLike, ".")) { mainExport = (scope.contents.packageJsonContent.exports as MapLike)["."]; } if (mainExport) { - const loadModuleFromTargetImportOrExport = getLoadModuleFromTargetImportOrExport(extensions, state, cache, redirectedReference, subpath, scope, /*isImports*/ false); + const loadModuleFromTargetImportOrExport = getLoadModuleFromTargetImportOrExport( + extensions, + state, + cache, + redirectedReference, + subpath, + scope, + /*isImports*/ false, + ); return loadModuleFromTargetImportOrExport(mainExport, "", /*pattern*/ false, "."); } } else if (allKeysStartWithDot(scope.contents.packageJsonContent.exports as MapLike)) { if (typeof scope.contents.packageJsonContent.exports !== "object") { if (state.traceEnabled) { - trace(state.host, Diagnostics.Export_specifier_0_does_not_exist_in_package_json_scope_at_path_1, subpath, scope.packageDirectory); + trace( + state.host, + Diagnostics.Export_specifier_0_does_not_exist_in_package_json_scope_at_path_1, + subpath, + scope.packageDirectory, + ); } return toSearchResult(/*value*/ undefined); } - const result = loadModuleFromImportsOrExports(extensions, state, cache, redirectedReference, subpath, scope.contents.packageJsonContent.exports, scope, /*isImports*/ false); + const result = loadModuleFromImportsOrExports( + extensions, + state, + cache, + redirectedReference, + subpath, + scope.contents.packageJsonContent.exports, + scope, + /*isImports*/ false, + ); if (result) { return result; } } if (state.traceEnabled) { - trace(state.host, Diagnostics.Export_specifier_0_does_not_exist_in_package_json_scope_at_path_1, subpath, scope.packageDirectory); + trace( + state.host, + Diagnostics.Export_specifier_0_does_not_exist_in_package_json_scope_at_path_1, + subpath, + scope.packageDirectory, + ); } return toSearchResult(/*value*/ undefined); } -function loadModuleFromImports(extensions: Extensions, moduleName: string, directory: string, state: ModuleResolutionState, cache: ModuleResolutionCache | undefined, redirectedReference: ResolvedProjectReference | undefined): SearchResult { +function loadModuleFromImports( + extensions: Extensions, + moduleName: string, + directory: string, + state: ModuleResolutionState, + cache: ModuleResolutionCache | undefined, + redirectedReference: ResolvedProjectReference | undefined, +): SearchResult { if (moduleName === "#" || startsWith(moduleName, "#/")) { if (state.traceEnabled) { trace(state.host, Diagnostics.Invalid_import_specifier_0_has_no_possible_resolutions, moduleName); } return toSearchResult(/*value*/ undefined); } - const directoryPath = getNormalizedAbsolutePath(combinePaths(directory, "dummy"), state.host.getCurrentDirectory?.()); + const directoryPath = getNormalizedAbsolutePath( + combinePaths(directory, "dummy"), + state.host.getCurrentDirectory?.(), + ); const scope = getPackageScopeForPath(directoryPath, state); if (!scope) { if (state.traceEnabled) { - trace(state.host, Diagnostics.Directory_0_has_no_containing_package_json_scope_Imports_will_not_resolve, directoryPath); + trace( + state.host, + Diagnostics.Directory_0_has_no_containing_package_json_scope_Imports_will_not_resolve, + directoryPath, + ); } return toSearchResult(/*value*/ undefined); } @@ -2526,13 +3424,27 @@ function loadModuleFromImports(extensions: Extensions, moduleName: string, direc return toSearchResult(/*value*/ undefined); } - const result = loadModuleFromImportsOrExports(extensions, state, cache, redirectedReference, moduleName, scope.contents.packageJsonContent.imports, scope, /*isImports*/ true); + const result = loadModuleFromImportsOrExports( + extensions, + state, + cache, + redirectedReference, + moduleName, + scope.contents.packageJsonContent.imports, + scope, + /*isImports*/ true, + ); if (result) { return result; } if (state.traceEnabled) { - trace(state.host, Diagnostics.Import_specifier_0_does_not_exist_in_package_json_scope_at_path_1, moduleName, scope.packageDirectory); + trace( + state.host, + Diagnostics.Import_specifier_0_does_not_exist_in_package_json_scope_at_path_1, + moduleName, + scope.packageDirectory, + ); } return toSearchResult(/*value*/ undefined); } @@ -2556,22 +3468,54 @@ export function comparePatternKeys(a: string, b: string) { return 0; } -function loadModuleFromImportsOrExports(extensions: Extensions, state: ModuleResolutionState, cache: ModuleResolutionCache | undefined, redirectedReference: ResolvedProjectReference | undefined, moduleName: string, lookupTable: object, scope: PackageJsonInfo, isImports: boolean): SearchResult | undefined { - const loadModuleFromTargetImportOrExport = getLoadModuleFromTargetImportOrExport(extensions, state, cache, redirectedReference, moduleName, scope, isImports); +function loadModuleFromImportsOrExports( + extensions: Extensions, + state: ModuleResolutionState, + cache: ModuleResolutionCache | undefined, + redirectedReference: ResolvedProjectReference | undefined, + moduleName: string, + lookupTable: object, + scope: PackageJsonInfo, + isImports: boolean, +): SearchResult | undefined { + const loadModuleFromTargetImportOrExport = getLoadModuleFromTargetImportOrExport( + extensions, + state, + cache, + redirectedReference, + moduleName, + scope, + isImports, + ); - if (!endsWith(moduleName, directorySeparator) && moduleName.indexOf("*") === -1 && hasProperty(lookupTable, moduleName)) { + if ( + !endsWith(moduleName, directorySeparator) && moduleName.indexOf("*") === -1 + && hasProperty(lookupTable, moduleName) + ) { const target = (lookupTable as { [idx: string]: unknown; })[moduleName]; return loadModuleFromTargetImportOrExport(target, /*subpath*/ "", /*pattern*/ false, moduleName); } - const expandingKeys = sort(filter(getOwnKeys(lookupTable as MapLike), k => k.indexOf("*") !== -1 || endsWith(k, "/")), comparePatternKeys); + const expandingKeys = sort( + filter(getOwnKeys(lookupTable as MapLike), k => k.indexOf("*") !== -1 || endsWith(k, "/")), + comparePatternKeys, + ); for (const potentialTarget of expandingKeys) { - if (state.features & NodeResolutionFeatures.ExportsPatternTrailers && matchesPatternWithTrailer(potentialTarget, moduleName)) { + if ( + state.features & NodeResolutionFeatures.ExportsPatternTrailers + && matchesPatternWithTrailer(potentialTarget, moduleName) + ) { const target = (lookupTable as { [idx: string]: unknown; })[potentialTarget]; const starPos = potentialTarget.indexOf("*"); - const subpath = moduleName.substring(potentialTarget.substring(0, starPos).length, moduleName.length - (potentialTarget.length - 1 - starPos)); + const subpath = moduleName.substring( + potentialTarget.substring(0, starPos).length, + moduleName.length - (potentialTarget.length - 1 - starPos), + ); return loadModuleFromTargetImportOrExport(target, subpath, /*pattern*/ true, potentialTarget); } - else if (endsWith(potentialTarget, "*") && startsWith(moduleName, potentialTarget.substring(0, potentialTarget.length - 1))) { + else if ( + endsWith(potentialTarget, "*") + && startsWith(moduleName, potentialTarget.substring(0, potentialTarget.length - 1)) + ) { const target = (lookupTable as { [idx: string]: unknown; })[potentialTarget]; const subpath = moduleName.substring(potentialTarget.length - 1); return loadModuleFromTargetImportOrExport(target, subpath, /*pattern*/ true, potentialTarget); @@ -2594,13 +3538,31 @@ function loadModuleFromImportsOrExports(extensions: Extensions, state: ModuleRes /** * Gets the self-recursive function specialized to retrieving the targeted import/export element for the given resolution configuration */ -function getLoadModuleFromTargetImportOrExport(extensions: Extensions, state: ModuleResolutionState, cache: ModuleResolutionCache | undefined, redirectedReference: ResolvedProjectReference | undefined, moduleName: string, scope: PackageJsonInfo, isImports: boolean) { +function getLoadModuleFromTargetImportOrExport( + extensions: Extensions, + state: ModuleResolutionState, + cache: ModuleResolutionCache | undefined, + redirectedReference: ResolvedProjectReference | undefined, + moduleName: string, + scope: PackageJsonInfo, + isImports: boolean, +) { return loadModuleFromTargetImportOrExport; - function loadModuleFromTargetImportOrExport(target: unknown, subpath: string, pattern: boolean, key: string): SearchResult | undefined { + function loadModuleFromTargetImportOrExport( + target: unknown, + subpath: string, + pattern: boolean, + key: string, + ): SearchResult | undefined { if (typeof target === "string") { if (!pattern && subpath.length > 0 && !endsWith(target, "/")) { if (state.traceEnabled) { - trace(state.host, Diagnostics.package_json_scope_0_has_invalid_type_for_target_of_specifier_1, scope.packageDirectory, moduleName); + trace( + state.host, + Diagnostics.package_json_scope_0_has_invalid_type_for_target_of_specifier_1, + scope.packageDirectory, + moduleName, + ); } return toSearchResult(/*value*/ undefined); } @@ -2608,8 +3570,23 @@ function getLoadModuleFromTargetImportOrExport(extensions: Extensions, state: Mo if (isImports && !startsWith(target, "../") && !startsWith(target, "/") && !isRootedDiskPath(target)) { const combinedLookup = pattern ? target.replace(/\*/g, subpath) : target + subpath; traceIfEnabled(state, Diagnostics.Using_0_subpath_1_with_target_2, "imports", key, combinedLookup); - traceIfEnabled(state, Diagnostics.Resolving_module_0_from_1, combinedLookup, scope.packageDirectory + "/"); - const result = nodeModuleNameResolverWorker(state.features, combinedLookup, scope.packageDirectory + "/", state.compilerOptions, state.host, cache, extensions, /*isConfigLookup*/ false, redirectedReference); + traceIfEnabled( + state, + Diagnostics.Resolving_module_0_from_1, + combinedLookup, + scope.packageDirectory + "/", + ); + const result = nodeModuleNameResolverWorker( + state.features, + combinedLookup, + scope.packageDirectory + "/", + state.compilerOptions, + state.host, + cache, + extensions, + /*isConfigLookup*/ false, + redirectedReference, + ); return toSearchResult( result.resolvedModule ? { path: result.resolvedModule.resolvedFileName, @@ -2621,15 +3598,28 @@ function getLoadModuleFromTargetImportOrExport(extensions: Extensions, state: Mo ); } if (state.traceEnabled) { - trace(state.host, Diagnostics.package_json_scope_0_has_invalid_type_for_target_of_specifier_1, scope.packageDirectory, moduleName); + trace( + state.host, + Diagnostics.package_json_scope_0_has_invalid_type_for_target_of_specifier_1, + scope.packageDirectory, + moduleName, + ); } return toSearchResult(/*value*/ undefined); } const parts = pathIsRelative(target) ? getPathComponents(target).slice(1) : getPathComponents(target); const partsAfterFirst = parts.slice(1); - if (partsAfterFirst.indexOf("..") >= 0 || partsAfterFirst.indexOf(".") >= 0 || partsAfterFirst.indexOf("node_modules") >= 0) { + if ( + partsAfterFirst.indexOf("..") >= 0 || partsAfterFirst.indexOf(".") >= 0 + || partsAfterFirst.indexOf("node_modules") >= 0 + ) { if (state.traceEnabled) { - trace(state.host, Diagnostics.package_json_scope_0_has_invalid_type_for_target_of_specifier_1, scope.packageDirectory, moduleName); + trace( + state.host, + Diagnostics.package_json_scope_0_has_invalid_type_for_target_of_specifier_1, + scope.packageDirectory, + moduleName, + ); } return toSearchResult(/*value*/ undefined); } @@ -2637,27 +3627,61 @@ function getLoadModuleFromTargetImportOrExport(extensions: Extensions, state: Mo // TODO: Assert that `resolvedTarget` is actually within the package directory? That's what the spec says.... but I'm not sure we need // to be in the business of validating everyone's import and export map correctness. const subpathParts = getPathComponents(subpath); - if (subpathParts.indexOf("..") >= 0 || subpathParts.indexOf(".") >= 0 || subpathParts.indexOf("node_modules") >= 0) { + if ( + subpathParts.indexOf("..") >= 0 || subpathParts.indexOf(".") >= 0 + || subpathParts.indexOf("node_modules") >= 0 + ) { if (state.traceEnabled) { - trace(state.host, Diagnostics.package_json_scope_0_has_invalid_type_for_target_of_specifier_1, scope.packageDirectory, moduleName); + trace( + state.host, + Diagnostics.package_json_scope_0_has_invalid_type_for_target_of_specifier_1, + scope.packageDirectory, + moduleName, + ); } return toSearchResult(/*value*/ undefined); } if (state.traceEnabled) { - trace(state.host, Diagnostics.Using_0_subpath_1_with_target_2, isImports ? "imports" : "exports", key, pattern ? target.replace(/\*/g, subpath) : target + subpath); + trace( + state.host, + Diagnostics.Using_0_subpath_1_with_target_2, + isImports ? "imports" : "exports", + key, + pattern ? target.replace(/\*/g, subpath) : target + subpath, + ); } - const finalPath = toAbsolutePath(pattern ? resolvedTarget.replace(/\*/g, subpath) : resolvedTarget + subpath); - const inputLink = tryLoadInputFileForPath(finalPath, subpath, combinePaths(scope.packageDirectory, "package.json"), isImports); + const finalPath = toAbsolutePath( + pattern ? resolvedTarget.replace(/\*/g, subpath) : resolvedTarget + subpath, + ); + const inputLink = tryLoadInputFileForPath( + finalPath, + subpath, + combinePaths(scope.packageDirectory, "package.json"), + isImports, + ); if (inputLink) return inputLink; - return toSearchResult(withPackageId(scope, loadFileNameFromPackageJsonField(extensions, finalPath, /*onlyRecordFailures*/ false, state))); + return toSearchResult( + withPackageId( + scope, + loadFileNameFromPackageJsonField(extensions, finalPath, /*onlyRecordFailures*/ false, state), + ), + ); } else if (typeof target === "object" && target !== null) { // eslint-disable-line no-null/no-null if (!Array.isArray(target)) { traceIfEnabled(state, Diagnostics.Entering_conditional_exports); for (const condition of getOwnKeys(target as MapLike)) { - if (condition === "default" || state.conditions.indexOf(condition) >= 0 || isApplicableVersionedTypesKey(state.conditions, condition)) { - traceIfEnabled(state, Diagnostics.Matched_0_condition_1, isImports ? "imports" : "exports", condition); + if ( + condition === "default" || state.conditions.indexOf(condition) >= 0 + || isApplicableVersionedTypesKey(state.conditions, condition) + ) { + traceIfEnabled( + state, + Diagnostics.Matched_0_condition_1, + isImports ? "imports" : "exports", + condition, + ); const subTarget = (target as MapLike)[condition]; const result = loadModuleFromTargetImportOrExport(subTarget, subpath, pattern, key); if (result) { @@ -2679,7 +3703,12 @@ function getLoadModuleFromTargetImportOrExport(extensions: Extensions, state: Mo else { if (!length(target)) { if (state.traceEnabled) { - trace(state.host, Diagnostics.package_json_scope_0_has_invalid_type_for_target_of_specifier_1, scope.packageDirectory, moduleName); + trace( + state.host, + Diagnostics.package_json_scope_0_has_invalid_type_for_target_of_specifier_1, + scope.packageDirectory, + moduleName, + ); } return toSearchResult(/*value*/ undefined); } @@ -2693,12 +3722,22 @@ function getLoadModuleFromTargetImportOrExport(extensions: Extensions, state: Mo } else if (target === null) { // eslint-disable-line no-null/no-null if (state.traceEnabled) { - trace(state.host, Diagnostics.package_json_scope_0_explicitly_maps_specifier_1_to_null, scope.packageDirectory, moduleName); + trace( + state.host, + Diagnostics.package_json_scope_0_explicitly_maps_specifier_1_to_null, + scope.packageDirectory, + moduleName, + ); } return toSearchResult(/*value*/ undefined); } if (state.traceEnabled) { - trace(state.host, Diagnostics.package_json_scope_0_has_invalid_type_for_target_of_specifier_1, scope.packageDirectory, moduleName); + trace( + state.host, + Diagnostics.package_json_scope_0_has_invalid_type_for_target_of_specifier_1, + scope.packageDirectory, + moduleName, + ); } return toSearchResult(/*value*/ undefined); @@ -2723,18 +3762,35 @@ function getLoadModuleFromTargetImportOrExport(extensions: Extensions, state: Mo !state.isConfigLookup && (state.compilerOptions.declarationDir || state.compilerOptions.outDir) && finalPath.indexOf("/node_modules/") === -1 - && (state.compilerOptions.configFile ? containsPath(scope.packageDirectory, toAbsolutePath(state.compilerOptions.configFile.fileName), !useCaseSensitiveFileNames(state)) : true) + && (state.compilerOptions.configFile + ? containsPath( + scope.packageDirectory, + toAbsolutePath(state.compilerOptions.configFile.fileName), + !useCaseSensitiveFileNames(state), + ) : true) ) { // So that all means we'll only try these guesses for files outside `node_modules` in a directory where the `package.json` and `tsconfig.json` are siblings. // Even with all that, we still don't know if the root of the output file structure will be (relative to the package file) // `.`, `./src` or any other deeper directory structure. (If project references are used, it's definitely `.` by fiat, so that should be pretty common.) - const getCanonicalFileName = hostGetCanonicalFileName({ useCaseSensitiveFileNames: () => useCaseSensitiveFileNames(state) }); + const getCanonicalFileName = hostGetCanonicalFileName({ + useCaseSensitiveFileNames: () => useCaseSensitiveFileNames(state), + }); const commonSourceDirGuesses: string[] = []; // A `rootDir` compiler option strongly indicates the root location // A `composite` project is using project references and has it's common src dir set to `.`, so it shouldn't need to check any other locations - if (state.compilerOptions.rootDir || (state.compilerOptions.composite && state.compilerOptions.configFilePath)) { - const commonDir = toAbsolutePath(getCommonSourceDirectory(state.compilerOptions, () => [], state.host.getCurrentDirectory?.() || "", getCanonicalFileName)); + if ( + state.compilerOptions.rootDir + || (state.compilerOptions.composite && state.compilerOptions.configFilePath) + ) { + const commonDir = toAbsolutePath( + getCommonSourceDirectory( + state.compilerOptions, + () => [], + state.host.getCurrentDirectory?.() || "", + getCanonicalFileName, + ), + ); commonSourceDirGuesses.push(commonDir); } else if (state.requestContainingDirectory) { @@ -2760,7 +3816,14 @@ function getLoadModuleFromTargetImportOrExport(extensions: Extensions, state: Mo // be a file outside of `./src/sub` in the program (the file we resolved to), making us de-facto right. So this fallback lookup // logic may influence what files are pulled in by self-names, which in turn influences the output path shape, but it's all // internally consistent so the paths should be stable so long as we prefer the "most general" (meaning: top-most-level directory) possible results first. - const commonDir = toAbsolutePath(getCommonSourceDirectory(state.compilerOptions, () => [requestingFile, toAbsolutePath(packagePath)], state.host.getCurrentDirectory?.() || "", getCanonicalFileName)); + const commonDir = toAbsolutePath( + getCommonSourceDirectory( + state.compilerOptions, + () => [requestingFile, toAbsolutePath(packagePath)], + state.host.getCurrentDirectory?.() || "", + getCanonicalFileName, + ), + ); commonSourceDirGuesses.push(commonDir); let fragment = ensureTrailingDirectorySeparator(commonDir); @@ -2775,8 +3838,10 @@ function getLoadModuleFromTargetImportOrExport(extensions: Extensions, state: Mo if (commonSourceDirGuesses.length > 1) { state.reportDiagnostic(createCompilerDiagnostic( isImports - ? Diagnostics.The_project_root_is_ambiguous_but_is_required_to_resolve_import_map_entry_0_in_file_1_Supply_the_rootDir_compiler_option_to_disambiguate - : Diagnostics.The_project_root_is_ambiguous_but_is_required_to_resolve_export_map_entry_0_in_file_1_Supply_the_rootDir_compiler_option_to_disambiguate, + ? Diagnostics + .The_project_root_is_ambiguous_but_is_required_to_resolve_import_map_entry_0_in_file_1_Supply_the_rootDir_compiler_option_to_disambiguate + : Diagnostics + .The_project_root_is_ambiguous_but_is_required_to_resolve_export_map_entry_0_in_file_1_Supply_the_rootDir_compiler_option_to_disambiguate, entry === "" ? "." : entry, // replace empty string with `.` - the reverse of the operation done when entries are built - so main entrypoint errors don't look weird packagePath, )); @@ -2788,15 +3853,38 @@ function getLoadModuleFromTargetImportOrExport(extensions: Extensions, state: Mo // The matched export is looking up something in either the out declaration or js dir, now map the written path back into the source dir and source extension const pathFragment = finalPath.slice(candidateDir.length + 1); // +1 to also remove directory seperator const possibleInputBase = combinePaths(commonSourceDirGuess, pathFragment); - const jsAndDtsExtensions = [Extension.Mjs, Extension.Cjs, Extension.Js, Extension.Json, Extension.Dmts, Extension.Dcts, Extension.Dts]; + const jsAndDtsExtensions = [ + Extension.Mjs, + Extension.Cjs, + Extension.Js, + Extension.Json, + Extension.Dmts, + Extension.Dcts, + Extension.Dts, + ]; for (const ext of jsAndDtsExtensions) { if (fileExtensionIs(possibleInputBase, ext)) { const inputExts = getPossibleOriginalInputExtensionForExtension(possibleInputBase); for (const possibleExt of inputExts) { if (!extensionIsOk(extensions, possibleExt)) continue; - const possibleInputWithInputExtension = changeAnyExtension(possibleInputBase, possibleExt, ext, !useCaseSensitiveFileNames(state)); + const possibleInputWithInputExtension = changeAnyExtension( + possibleInputBase, + possibleExt, + ext, + !useCaseSensitiveFileNames(state), + ); if (state.host.fileExists(possibleInputWithInputExtension)) { - return toSearchResult(withPackageId(scope, loadFileNameFromPackageJsonField(extensions, possibleInputWithInputExtension, /*onlyRecordFailures*/ false, state))); + return toSearchResult( + withPackageId( + scope, + loadFileNameFromPackageJsonField( + extensions, + possibleInputWithInputExtension, + /*onlyRecordFailures*/ false, + state, + ), + ), + ); } } } @@ -2810,13 +3898,21 @@ function getLoadModuleFromTargetImportOrExport(extensions: Extensions, state: Mo function getOutputDirectoriesForBaseDirectory(commonSourceDirGuess: string) { // Config file ouput paths are processed to be relative to the host's current directory, while // otherwise the paths are resolved relative to the common source dir the compiler puts together - const currentDir = state.compilerOptions.configFile ? state.host.getCurrentDirectory?.() || "" : commonSourceDirGuess; + const currentDir = state.compilerOptions.configFile ? state.host.getCurrentDirectory?.() || "" + : commonSourceDirGuess; const candidateDirectories = []; if (state.compilerOptions.declarationDir) { - candidateDirectories.push(toAbsolutePath(combineDirectoryPath(currentDir, state.compilerOptions.declarationDir))); + candidateDirectories.push( + toAbsolutePath(combineDirectoryPath(currentDir, state.compilerOptions.declarationDir)), + ); } - if (state.compilerOptions.outDir && state.compilerOptions.outDir !== state.compilerOptions.declarationDir) { - candidateDirectories.push(toAbsolutePath(combineDirectoryPath(currentDir, state.compilerOptions.outDir))); + if ( + state.compilerOptions.outDir + && state.compilerOptions.outDir !== state.compilerOptions.declarationDir + ) { + candidateDirectories.push( + toAbsolutePath(combineDirectoryPath(currentDir, state.compilerOptions.outDir)), + ); } return candidateDirectories; } @@ -2833,17 +3929,53 @@ export function isApplicableVersionedTypesKey(conditions: readonly string[], key return range.test(version); } -function loadModuleFromNearestNodeModulesDirectory(extensions: Extensions, moduleName: string, directory: string, state: ModuleResolutionState, cache: ModuleResolutionCache | undefined, redirectedReference: ResolvedProjectReference | undefined): SearchResult { - return loadModuleFromNearestNodeModulesDirectoryWorker(extensions, moduleName, directory, state, /*typesScopeOnly*/ false, cache, redirectedReference); +function loadModuleFromNearestNodeModulesDirectory( + extensions: Extensions, + moduleName: string, + directory: string, + state: ModuleResolutionState, + cache: ModuleResolutionCache | undefined, + redirectedReference: ResolvedProjectReference | undefined, +): SearchResult { + return loadModuleFromNearestNodeModulesDirectoryWorker( + extensions, + moduleName, + directory, + state, + /*typesScopeOnly*/ false, + cache, + redirectedReference, + ); } -function loadModuleFromNearestNodeModulesDirectoryTypesScope(moduleName: string, directory: string, state: ModuleResolutionState): SearchResult { +function loadModuleFromNearestNodeModulesDirectoryTypesScope( + moduleName: string, + directory: string, + state: ModuleResolutionState, +): SearchResult { // Extensions parameter here doesn't actually matter, because typesOnly ensures we're just doing @types lookup, which is always DtsOnly. - return loadModuleFromNearestNodeModulesDirectoryWorker(Extensions.Declaration, moduleName, directory, state, /*typesScopeOnly*/ true, /*cache*/ undefined, /*redirectedReference*/ undefined); + return loadModuleFromNearestNodeModulesDirectoryWorker( + Extensions.Declaration, + moduleName, + directory, + state, + /*typesScopeOnly*/ true, + /*cache*/ undefined, + /*redirectedReference*/ undefined, + ); } -function loadModuleFromNearestNodeModulesDirectoryWorker(extensions: Extensions, moduleName: string, directory: string, state: ModuleResolutionState, typesScopeOnly: boolean, cache: ModuleResolutionCache | undefined, redirectedReference: ResolvedProjectReference | undefined): SearchResult { - const mode = state.features === 0 ? undefined : state.features & NodeResolutionFeatures.EsmMode ? ModuleKind.ESNext : ModuleKind.CommonJS; +function loadModuleFromNearestNodeModulesDirectoryWorker( + extensions: Extensions, + moduleName: string, + directory: string, + state: ModuleResolutionState, + typesScopeOnly: boolean, + cache: ModuleResolutionCache | undefined, + redirectedReference: ResolvedProjectReference | undefined, +): SearchResult { + const mode = state.features === 0 ? undefined + : state.features & NodeResolutionFeatures.EsmMode ? ModuleKind.ESNext : ModuleKind.CommonJS; // Do (up to) two passes through node_modules: // 1. For each ancestor node_modules directory, try to find: // i. TS/DTS files in the implementation package @@ -2854,30 +3986,63 @@ function loadModuleFromNearestNodeModulesDirectoryWorker(extensions: Extensions, const secondaryExtensions = extensions & ~(Extensions.TypeScript | Extensions.Declaration); // (1) if (priorityExtensions) { - traceIfEnabled(state, Diagnostics.Searching_all_ancestor_node_modules_directories_for_preferred_extensions_Colon_0, formatExtensions(priorityExtensions)); + traceIfEnabled( + state, + Diagnostics.Searching_all_ancestor_node_modules_directories_for_preferred_extensions_Colon_0, + formatExtensions(priorityExtensions), + ); const result = lookup(priorityExtensions); if (result) return result; } // (2) if (secondaryExtensions && !typesScopeOnly) { - traceIfEnabled(state, Diagnostics.Searching_all_ancestor_node_modules_directories_for_fallback_extensions_Colon_0, formatExtensions(secondaryExtensions)); + traceIfEnabled( + state, + Diagnostics.Searching_all_ancestor_node_modules_directories_for_fallback_extensions_Colon_0, + formatExtensions(secondaryExtensions), + ); return lookup(secondaryExtensions); } function lookup(extensions: Extensions) { return forEachAncestorDirectory(normalizeSlashes(directory), ancestorDirectory => { if (getBaseFileName(ancestorDirectory) !== "node_modules") { - const resolutionFromCache = tryFindNonRelativeModuleNameInCache(cache, moduleName, mode, ancestorDirectory, redirectedReference, state); + const resolutionFromCache = tryFindNonRelativeModuleNameInCache( + cache, + moduleName, + mode, + ancestorDirectory, + redirectedReference, + state, + ); if (resolutionFromCache) { return resolutionFromCache; } - return toSearchResult(loadModuleFromImmediateNodeModulesDirectory(extensions, moduleName, ancestorDirectory, state, typesScopeOnly, cache, redirectedReference)); + return toSearchResult( + loadModuleFromImmediateNodeModulesDirectory( + extensions, + moduleName, + ancestorDirectory, + state, + typesScopeOnly, + cache, + redirectedReference, + ), + ); } }); } } -function loadModuleFromImmediateNodeModulesDirectory(extensions: Extensions, moduleName: string, directory: string, state: ModuleResolutionState, typesScopeOnly: boolean, cache: ModuleResolutionCache | undefined, redirectedReference: ResolvedProjectReference | undefined): Resolved | undefined { +function loadModuleFromImmediateNodeModulesDirectory( + extensions: Extensions, + moduleName: string, + directory: string, + state: ModuleResolutionState, + typesScopeOnly: boolean, + cache: ModuleResolutionCache | undefined, + redirectedReference: ResolvedProjectReference | undefined, +): Resolved | undefined { const nodeModulesFolder = combinePaths(directory, "node_modules"); const nodeModulesFolderExists = directoryProbablyExists(nodeModulesFolder, state.host); if (!nodeModulesFolderExists && state.traceEnabled) { @@ -2885,7 +4050,15 @@ function loadModuleFromImmediateNodeModulesDirectory(extensions: Extensions, mod } if (!typesScopeOnly) { - const packageResult = loadModuleFromSpecificNodeModulesDirectory(extensions, moduleName, nodeModulesFolder, nodeModulesFolderExists, state, cache, redirectedReference); + const packageResult = loadModuleFromSpecificNodeModulesDirectory( + extensions, + moduleName, + nodeModulesFolder, + nodeModulesFolderExists, + state, + cache, + redirectedReference, + ); if (packageResult) { return packageResult; } @@ -2896,15 +4069,35 @@ function loadModuleFromImmediateNodeModulesDirectory(extensions: Extensions, mod let nodeModulesAtTypesExists = nodeModulesFolderExists; if (nodeModulesFolderExists && !directoryProbablyExists(nodeModulesAtTypes, state.host)) { if (state.traceEnabled) { - trace(state.host, Diagnostics.Directory_0_does_not_exist_skipping_all_lookups_in_it, nodeModulesAtTypes); + trace( + state.host, + Diagnostics.Directory_0_does_not_exist_skipping_all_lookups_in_it, + nodeModulesAtTypes, + ); } nodeModulesAtTypesExists = false; } - return loadModuleFromSpecificNodeModulesDirectory(Extensions.Declaration, mangleScopedPackageNameWithTrace(moduleName, state), nodeModulesAtTypes, nodeModulesAtTypesExists, state, cache, redirectedReference); + return loadModuleFromSpecificNodeModulesDirectory( + Extensions.Declaration, + mangleScopedPackageNameWithTrace(moduleName, state), + nodeModulesAtTypes, + nodeModulesAtTypesExists, + state, + cache, + redirectedReference, + ); } } -function loadModuleFromSpecificNodeModulesDirectory(extensions: Extensions, moduleName: string, nodeModulesDirectory: string, nodeModulesDirectoryExists: boolean, state: ModuleResolutionState, cache: ModuleResolutionCache | undefined, redirectedReference: ResolvedProjectReference | undefined): Resolved | undefined { +function loadModuleFromSpecificNodeModulesDirectory( + extensions: Extensions, + moduleName: string, + nodeModulesDirectory: string, + nodeModulesDirectoryExists: boolean, + state: ModuleResolutionState, + cache: ModuleResolutionCache | undefined, + redirectedReference: ResolvedProjectReference | undefined, +): Resolved | undefined { const candidate = normalizePath(combinePaths(nodeModulesDirectory, moduleName)); const { packageName, rest } = parsePackageName(moduleName); const packageDirectory = combinePaths(nodeModulesDirectory, packageName); @@ -2915,8 +4108,12 @@ function loadModuleFromSpecificNodeModulesDirectory(extensions: Extensions, modu // But only if we're not respecting export maps (if we are, we might redirect around this location) if ( rest !== "" && packageInfo && ( - !(state.features & NodeResolutionFeatures.Exports) || - !hasProperty((rootPackageInfo = getPackageJsonInfo(packageDirectory, !nodeModulesDirectoryExists, state))?.contents.packageJsonContent ?? emptyArray, "exports") + !(state.features & NodeResolutionFeatures.Exports) + || !hasProperty( + (rootPackageInfo = getPackageJsonInfo(packageDirectory, !nodeModulesDirectoryExists, state))?.contents + .packageJsonContent ?? emptyArray, + "exports", + ) ) ) { const fromFile = loadModuleFromFile(extensions, candidate, !nodeModulesDirectoryExists, state); @@ -2936,8 +4133,9 @@ function loadModuleFromSpecificNodeModulesDirectory(extensions: Extensions, modu } const loader: ResolutionKindSpecificLoader = (extensions, candidate, onlyRecordFailures, state) => { - let pathAndExtension = (rest || !(state.features & NodeResolutionFeatures.EsmMode)) && loadModuleFromFile(extensions, candidate, onlyRecordFailures, state) || - loadNodeModuleFromDirectoryWorker( + let pathAndExtension = (rest || !(state.features & NodeResolutionFeatures.EsmMode)) + && loadModuleFromFile(extensions, candidate, onlyRecordFailures, state) + || loadNodeModuleFromDirectoryWorker( extensions, candidate, onlyRecordFailures, @@ -2948,12 +4146,18 @@ function loadModuleFromSpecificNodeModulesDirectory(extensions: Extensions, modu if ( !pathAndExtension && packageInfo // eslint-disable-next-line no-null/no-null - && (packageInfo.contents.packageJsonContent.exports === undefined || packageInfo.contents.packageJsonContent.exports === null) + && (packageInfo.contents.packageJsonContent.exports === undefined + || packageInfo.contents.packageJsonContent.exports === null) && state.features & NodeResolutionFeatures.EsmMode ) { // EsmMode disables index lookup in `loadNodeModuleFromDirectoryWorker` generally, however non-relative package resolutions still assume // a default `index.js` entrypoint if no `main` or `exports` are present - pathAndExtension = loadModuleFromFile(extensions, combinePaths(candidate, "index.js"), onlyRecordFailures, state); + pathAndExtension = loadModuleFromFile( + extensions, + combinePaths(candidate, "index.js"), + onlyRecordFailures, + state, + ); } return withPackageId(packageInfo, pathAndExtension); }; @@ -2963,16 +4167,43 @@ function loadModuleFromSpecificNodeModulesDirectory(extensions: Extensions, modu packageInfo = rootPackageInfo ?? getPackageJsonInfo(packageDirectory, !nodeModulesDirectoryExists, state); } // package exports are higher priority than file/directory/typesVersions lookups and (and, if there's exports present, blocks them) - if (packageInfo && packageInfo.contents.packageJsonContent.exports && state.features & NodeResolutionFeatures.Exports) { - return loadModuleFromExports(packageInfo, extensions, combinePaths(".", rest), state, cache, redirectedReference)?.value; + if ( + packageInfo && packageInfo.contents.packageJsonContent.exports + && state.features & NodeResolutionFeatures.Exports + ) { + return loadModuleFromExports( + packageInfo, + extensions, + combinePaths(".", rest), + state, + cache, + redirectedReference, + )?.value; } const versionPaths = rest !== "" && packageInfo ? getVersionPathsOfPackageJsonInfo(packageInfo, state) : undefined; if (versionPaths) { if (state.traceEnabled) { - trace(state.host, Diagnostics.package_json_has_a_typesVersions_entry_0_that_matches_compiler_version_1_looking_for_a_pattern_to_match_module_name_2, versionPaths.version, version, rest); + trace( + state.host, + Diagnostics + .package_json_has_a_typesVersions_entry_0_that_matches_compiler_version_1_looking_for_a_pattern_to_match_module_name_2, + versionPaths.version, + version, + rest, + ); } - const packageDirectoryExists = nodeModulesDirectoryExists && directoryProbablyExists(packageDirectory, state.host); - const fromPaths = tryLoadModuleUsingPaths(extensions, rest, packageDirectory, versionPaths.paths, /*pathPatterns*/ undefined, loader, !packageDirectoryExists, state); + const packageDirectoryExists = nodeModulesDirectoryExists + && directoryProbablyExists(packageDirectory, state.host); + const fromPaths = tryLoadModuleUsingPaths( + extensions, + rest, + packageDirectory, + versionPaths.paths, + /*pathPatterns*/ undefined, + loader, + !packageDirectoryExists, + state, + ); if (fromPaths) { return fromPaths.value; } @@ -2980,7 +4211,16 @@ function loadModuleFromSpecificNodeModulesDirectory(extensions: Extensions, modu return loader(extensions, candidate, !nodeModulesDirectoryExists, state); } -function tryLoadModuleUsingPaths(extensions: Extensions, moduleName: string, baseDirectory: string, paths: MapLike, pathPatterns: readonly (string | Pattern)[] | undefined, loader: ResolutionKindSpecificLoader, onlyRecordFailures: boolean, state: ModuleResolutionState): SearchResult { +function tryLoadModuleUsingPaths( + extensions: Extensions, + moduleName: string, + baseDirectory: string, + paths: MapLike, + pathPatterns: readonly (string | Pattern)[] | undefined, + loader: ResolutionKindSpecificLoader, + onlyRecordFailures: boolean, + state: ModuleResolutionState, +): SearchResult { pathPatterns ||= tryParsePatterns(paths); const matchedPattern = matchPatternOrExact(pathPatterns, moduleName); if (matchedPattern) { @@ -3004,7 +4244,12 @@ function tryLoadModuleUsingPaths(extensions: Extensions, moduleName: string, bas return noPackageId({ path, ext: extension, resolvedUsingTsExtension: undefined }); } } - return loader(extensions, candidate, onlyRecordFailures || !directoryProbablyExists(getDirectoryPath(candidate), state.host), state); + return loader( + extensions, + candidate, + onlyRecordFailures || !directoryProbablyExists(getDirectoryPath(candidate), state.host), + state, + ); }); return { value: resolved }; } @@ -3049,16 +4294,29 @@ export function getPackageNameFromTypesPackageName(mangledName: string): string /** @internal */ export function unmangleScopedPackageName(typesPackageName: string): string { - return stringContains(typesPackageName, mangledScopedPackageSeparator) ? - "@" + typesPackageName.replace(mangledScopedPackageSeparator, directorySeparator) : - typesPackageName; + return stringContains(typesPackageName, mangledScopedPackageSeparator) + ? "@" + typesPackageName.replace(mangledScopedPackageSeparator, directorySeparator) + : typesPackageName; } -function tryFindNonRelativeModuleNameInCache(cache: NonRelativeModuleNameResolutionCache | undefined, moduleName: string, mode: ResolutionMode, containingDirectory: string, redirectedReference: ResolvedProjectReference | undefined, state: ModuleResolutionState): SearchResult { - const result = cache && cache.getFromNonRelativeNameCache(moduleName, mode, containingDirectory, redirectedReference); +function tryFindNonRelativeModuleNameInCache( + cache: NonRelativeModuleNameResolutionCache | undefined, + moduleName: string, + mode: ResolutionMode, + containingDirectory: string, + redirectedReference: ResolvedProjectReference | undefined, + state: ModuleResolutionState, +): SearchResult { + const result = cache + && cache.getFromNonRelativeNameCache(moduleName, mode, containingDirectory, redirectedReference); if (result) { if (state.traceEnabled) { - trace(state.host, Diagnostics.Resolution_for_module_0_was_found_in_cache_from_location_1, moduleName, containingDirectory); + trace( + state.host, + Diagnostics.Resolution_for_module_0_was_found_in_cache_from_location_1, + moduleName, + containingDirectory, + ); } state.resultFromCache = result; return { @@ -3073,7 +4331,14 @@ function tryFindNonRelativeModuleNameInCache(cache: NonRelativeModuleNameResolut } } -export function classicNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache?: NonRelativeModuleNameResolutionCache, redirectedReference?: ResolvedProjectReference): ResolvedModuleWithFailedLookupLocations { +export function classicNameResolver( + moduleName: string, + containingFile: string, + compilerOptions: CompilerOptions, + host: ModuleResolutionHost, + cache?: NonRelativeModuleNameResolutionCache, + redirectedReference?: ResolvedProjectReference, +): ResolvedModuleWithFailedLookupLocations { const traceEnabled = isTraceEnabled(compilerOptions, host); const failedLookupLocations: string[] = []; const affectingLocations: string[] = []; @@ -3094,8 +4359,8 @@ export function classicNameResolver(moduleName: string, containingFile: string, candidateIsFromPackageJsonField: false, }; - const resolved = tryResolve(Extensions.TypeScript | Extensions.Declaration) || - tryResolve(Extensions.JavaScript | (compilerOptions.resolveJsonModule ? Extensions.Json : 0)); + const resolved = tryResolve(Extensions.TypeScript | Extensions.Declaration) + || tryResolve(Extensions.JavaScript | (compilerOptions.resolveJsonModule ? Extensions.Json : 0)); // No originalPath because classic resolution doesn't resolve realPath return createResolvedModuleWithFailedLookupLocationsHandlingSymlink( moduleName, @@ -3108,7 +4373,13 @@ export function classicNameResolver(moduleName: string, containingFile: string, ); function tryResolve(extensions: Extensions): SearchResult { - const resolvedUsingSettings = tryLoadModuleUsingOptionalResolutionSettings(extensions, moduleName, containingDirectory, loadModuleFromFileNoPackageId, state); + const resolvedUsingSettings = tryLoadModuleUsingOptionalResolutionSettings( + extensions, + moduleName, + containingDirectory, + loadModuleFromFileNoPackageId, + state, + ); if (resolvedUsingSettings) { return { value: resolvedUsingSettings }; } @@ -3116,24 +4387,39 @@ export function classicNameResolver(moduleName: string, containingFile: string, if (!isExternalModuleNameRelative(moduleName)) { // Climb up parent directories looking for a module. const resolved = forEachAncestorDirectory(containingDirectory, directory => { - const resolutionFromCache = tryFindNonRelativeModuleNameInCache(cache, moduleName, /*mode*/ undefined, directory, redirectedReference, state); + const resolutionFromCache = tryFindNonRelativeModuleNameInCache( + cache, + moduleName, + /*mode*/ undefined, + directory, + redirectedReference, + state, + ); if (resolutionFromCache) { return resolutionFromCache; } const searchName = normalizePath(combinePaths(directory, moduleName)); - return toSearchResult(loadModuleFromFileNoPackageId(extensions, searchName, /*onlyRecordFailures*/ false, state)); + return toSearchResult( + loadModuleFromFileNoPackageId(extensions, searchName, /*onlyRecordFailures*/ false, state), + ); }); if (resolved) return resolved; if (extensions & (Extensions.TypeScript | Extensions.Declaration)) { // If we didn't find the file normally, look it up in @types. - let resolved = loadModuleFromNearestNodeModulesDirectoryTypesScope(moduleName, containingDirectory, state); + let resolved = loadModuleFromNearestNodeModulesDirectoryTypesScope( + moduleName, + containingDirectory, + state, + ); if (extensions & Extensions.Declaration) resolved ??= resolveFromTypeRoot(moduleName, state); return resolved; } } else { const candidate = normalizePath(combinePaths(containingDirectory, moduleName)); - return toSearchResult(loadModuleFromFileNoPackageId(extensions, candidate, /*onlyRecordFailures*/ false, state)); + return toSearchResult( + loadModuleFromFileNoPackageId(extensions, candidate, /*onlyRecordFailures*/ false, state), + ); } } } @@ -3149,7 +4435,8 @@ function resolveFromTypeRoot(moduleName: string, state: ModuleResolutionState) { const resolvedFromFile = loadModuleFromFile(Extensions.Declaration, candidate, !directoryExists, state); if (resolvedFromFile) { const packageDirectory = parseNodeModuleFromPath(resolvedFromFile.path); - const packageInfo = packageDirectory ? getPackageJsonInfo(packageDirectory, /*onlyRecordFailures*/ false, state) : undefined; + const packageInfo = packageDirectory + ? getPackageJsonInfo(packageDirectory, /*onlyRecordFailures*/ false, state) : undefined; return toSearchResult(withPackageId(packageInfo, resolvedFromFile)); } const resolved = loadNodeModuleFromDirectory(Extensions.Declaration, candidate, !directoryExists, state); @@ -3170,10 +4457,24 @@ export function shouldAllowImportingTsExtension(compilerOptions: CompilerOptions * * @internal */ -export function loadModuleFromGlobalCache(moduleName: string, projectName: string | undefined, compilerOptions: CompilerOptions, host: ModuleResolutionHost, globalCache: string, packageJsonInfoCache: PackageJsonInfoCache): ResolvedModuleWithFailedLookupLocations { +export function loadModuleFromGlobalCache( + moduleName: string, + projectName: string | undefined, + compilerOptions: CompilerOptions, + host: ModuleResolutionHost, + globalCache: string, + packageJsonInfoCache: PackageJsonInfoCache, +): ResolvedModuleWithFailedLookupLocations { const traceEnabled = isTraceEnabled(compilerOptions, host); if (traceEnabled) { - trace(host, Diagnostics.Auto_discovery_for_typings_is_enabled_in_project_0_Running_extra_resolution_pass_for_module_1_using_cache_location_2, projectName, moduleName, globalCache); + trace( + host, + Diagnostics + .Auto_discovery_for_typings_is_enabled_in_project_0_Running_extra_resolution_pass_for_module_1_using_cache_location_2, + projectName, + moduleName, + globalCache, + ); } const failedLookupLocations: string[] = []; const affectingLocations: string[] = []; @@ -3192,7 +4493,15 @@ export function loadModuleFromGlobalCache(moduleName: string, projectName: strin isConfigLookup: false, candidateIsFromPackageJsonField: false, }; - const resolved = loadModuleFromImmediateNodeModulesDirectory(Extensions.Declaration, moduleName, globalCache, state, /*typesScopeOnly*/ false, /*cache*/ undefined, /*redirectedReference*/ undefined); + const resolved = loadModuleFromImmediateNodeModulesDirectory( + Extensions.Declaration, + moduleName, + globalCache, + state, + /*typesScopeOnly*/ false, + /*cache*/ undefined, + /*redirectedReference*/ undefined, + ); return createResolvedModuleWithFailedLookupLocations( resolved, /*isExternalLibraryImport*/ true, @@ -3229,7 +4538,7 @@ function traceIfEnabled(state: ModuleResolutionState, diagnostic: DiagnosticMess } function useCaseSensitiveFileNames(state: ModuleResolutionState) { - return !state.host.useCaseSensitiveFileNames ? true : - typeof state.host.useCaseSensitiveFileNames === "boolean" ? state.host.useCaseSensitiveFileNames : - state.host.useCaseSensitiveFileNames(); + return !state.host.useCaseSensitiveFileNames ? true + : typeof state.host.useCaseSensitiveFileNames === "boolean" ? state.host.useCaseSensitiveFileNames + : state.host.useCaseSensitiveFileNames(); } diff --git a/src/compiler/moduleSpecifiers.ts b/src/compiler/moduleSpecifiers.ts index b4a78c190872b..cde52328aa045 100644 --- a/src/compiler/moduleSpecifiers.ts +++ b/src/compiler/moduleSpecifiers.ts @@ -127,7 +127,9 @@ interface Preferences { /** * @param syntaxImpliedNodeFormat Used when the import syntax implies ESM or CJS irrespective of the mode of the file. */ - getAllowedEndingsInPreferredOrder(syntaxImpliedNodeFormat?: SourceFile["impliedNodeFormat"]): ModuleSpecifierEnding[]; + getAllowedEndingsInPreferredOrder( + syntaxImpliedNodeFormat?: SourceFile["impliedNodeFormat"], + ): ModuleSpecifierEnding[]; } function getPreferences( @@ -138,13 +140,13 @@ function getPreferences( ): Preferences { const preferredEnding = getPreferredEnding(); return { - relativePreference: oldImportSpecifier !== undefined ? (isExternalModuleNameRelative(oldImportSpecifier) ? - RelativePreference.Relative : - RelativePreference.NonRelative) : - importModuleSpecifierPreference === "relative" ? RelativePreference.Relative : - importModuleSpecifierPreference === "non-relative" ? RelativePreference.NonRelative : - importModuleSpecifierPreference === "project-relative" ? RelativePreference.ExternalNonRelative : - RelativePreference.Shortest, + relativePreference: oldImportSpecifier !== undefined ? (isExternalModuleNameRelative(oldImportSpecifier) + ? RelativePreference.Relative + : RelativePreference.NonRelative) + : importModuleSpecifierPreference === "relative" ? RelativePreference.Relative + : importModuleSpecifierPreference === "non-relative" ? RelativePreference.NonRelative + : importModuleSpecifierPreference === "project-relative" ? RelativePreference.ExternalNonRelative + : RelativePreference.Shortest, getAllowedEndingsInPreferredOrder: syntaxImpliedNodeFormat => { if ((syntaxImpliedNodeFormat ?? importingSourceFile.impliedNodeFormat) === ModuleKind.ESNext) { if (shouldAllowImportingTsExtension(compilerOptions, importingSourceFile.fileName)) { @@ -157,22 +159,57 @@ function getPreferences( ? [ModuleSpecifierEnding.JsExtension, ModuleSpecifierEnding.Index] : [ModuleSpecifierEnding.Index, ModuleSpecifierEnding.JsExtension]; } - const allowImportingTsExtension = shouldAllowImportingTsExtension(compilerOptions, importingSourceFile.fileName); + const allowImportingTsExtension = shouldAllowImportingTsExtension( + compilerOptions, + importingSourceFile.fileName, + ); switch (preferredEnding) { case ModuleSpecifierEnding.JsExtension: return allowImportingTsExtension - ? [ModuleSpecifierEnding.JsExtension, ModuleSpecifierEnding.TsExtension, ModuleSpecifierEnding.Minimal, ModuleSpecifierEnding.Index] - : [ModuleSpecifierEnding.JsExtension, ModuleSpecifierEnding.Minimal, ModuleSpecifierEnding.Index]; + ? [ + ModuleSpecifierEnding.JsExtension, + ModuleSpecifierEnding.TsExtension, + ModuleSpecifierEnding.Minimal, + ModuleSpecifierEnding.Index, + ] + : [ + ModuleSpecifierEnding.JsExtension, + ModuleSpecifierEnding.Minimal, + ModuleSpecifierEnding.Index, + ]; case ModuleSpecifierEnding.TsExtension: - return [ModuleSpecifierEnding.TsExtension, ModuleSpecifierEnding.Minimal, ModuleSpecifierEnding.JsExtension, ModuleSpecifierEnding.Index]; + return [ + ModuleSpecifierEnding.TsExtension, + ModuleSpecifierEnding.Minimal, + ModuleSpecifierEnding.JsExtension, + ModuleSpecifierEnding.Index, + ]; case ModuleSpecifierEnding.Index: return allowImportingTsExtension - ? [ModuleSpecifierEnding.Index, ModuleSpecifierEnding.Minimal, ModuleSpecifierEnding.TsExtension, ModuleSpecifierEnding.JsExtension] - : [ModuleSpecifierEnding.Index, ModuleSpecifierEnding.Minimal, ModuleSpecifierEnding.JsExtension]; + ? [ + ModuleSpecifierEnding.Index, + ModuleSpecifierEnding.Minimal, + ModuleSpecifierEnding.TsExtension, + ModuleSpecifierEnding.JsExtension, + ] + : [ + ModuleSpecifierEnding.Index, + ModuleSpecifierEnding.Minimal, + ModuleSpecifierEnding.JsExtension, + ]; case ModuleSpecifierEnding.Minimal: return allowImportingTsExtension - ? [ModuleSpecifierEnding.Minimal, ModuleSpecifierEnding.Index, ModuleSpecifierEnding.TsExtension, ModuleSpecifierEnding.JsExtension] - : [ModuleSpecifierEnding.Minimal, ModuleSpecifierEnding.Index, ModuleSpecifierEnding.JsExtension]; + ? [ + ModuleSpecifierEnding.Minimal, + ModuleSpecifierEnding.Index, + ModuleSpecifierEnding.TsExtension, + ModuleSpecifierEnding.JsExtension, + ] + : [ + ModuleSpecifierEnding.Minimal, + ModuleSpecifierEnding.Index, + ModuleSpecifierEnding.JsExtension, + ]; default: Debug.assertNever(preferredEnding); } @@ -207,7 +244,16 @@ export function updateModuleSpecifier( oldImportSpecifier: string, options: ModuleSpecifierOptions = {}, ): string | undefined { - const res = getModuleSpecifierWorker(compilerOptions, importingSourceFile, importingSourceFileName, toFileName, host, getPreferences({}, compilerOptions, importingSourceFile, oldImportSpecifier), {}, options); + const res = getModuleSpecifierWorker( + compilerOptions, + importingSourceFile, + importingSourceFileName, + toFileName, + host, + getPreferences({}, compilerOptions, importingSourceFile, oldImportSpecifier), + {}, + options, + ); if (res === oldImportSpecifier) return undefined; return res; } @@ -227,7 +273,16 @@ export function getModuleSpecifier( host: ModuleSpecifierResolutionHost, options: ModuleSpecifierOptions = {}, ): string { - return getModuleSpecifierWorker(compilerOptions, importingSourceFile, importingSourceFileName, toFileName, host, getPreferences({}, compilerOptions, importingSourceFile), {}, options); + return getModuleSpecifierWorker( + compilerOptions, + importingSourceFile, + importingSourceFileName, + toFileName, + host, + getPreferences({}, compilerOptions, importingSourceFile), + {}, + options, + ); } /** @internal */ @@ -241,7 +296,20 @@ export function getNodeModulesPackageName( ): string | undefined { const info = getInfo(importingSourceFile.path, host); const modulePaths = getAllModulePaths(importingSourceFile.path, nodeModulesFileName, host, preferences, options); - return firstDefined(modulePaths, modulePath => tryGetModuleNameAsNodeModule(modulePath, info, importingSourceFile, host, compilerOptions, preferences, /*packageNameOnly*/ true, options.overrideImportMode)); + return firstDefined( + modulePaths, + modulePath => + tryGetModuleNameAsNodeModule( + modulePath, + info, + importingSourceFile, + host, + compilerOptions, + preferences, + /*packageNameOnly*/ true, + options.overrideImportMode, + ), + ); } function getModuleSpecifierWorker( @@ -256,8 +324,28 @@ function getModuleSpecifierWorker( ): string { const info = getInfo(importingSourceFileName, host); const modulePaths = getAllModulePaths(importingSourceFileName, toFileName, host, userPreferences, options); - return firstDefined(modulePaths, modulePath => tryGetModuleNameAsNodeModule(modulePath, info, importingSourceFile, host, compilerOptions, userPreferences, /*packageNameOnly*/ undefined, options.overrideImportMode)) || - getLocalModuleSpecifier(toFileName, info, compilerOptions, host, options.overrideImportMode || importingSourceFile.impliedNodeFormat, preferences); + return firstDefined( + modulePaths, + modulePath => + tryGetModuleNameAsNodeModule( + modulePath, + info, + importingSourceFile, + host, + compilerOptions, + userPreferences, + /*packageNameOnly*/ undefined, + options.overrideImportMode, + ), + ) + || getLocalModuleSpecifier( + toFileName, + info, + compilerOptions, + host, + options.overrideImportMode || importingSourceFile.impliedNodeFormat, + preferences, + ); } /** @internal */ @@ -283,7 +371,12 @@ function tryGetModuleSpecifiersFromCacheWorker( host: ModuleSpecifierResolutionHost, userPreferences: UserPreferences, options: ModuleSpecifierOptions = {}, -): readonly [specifiers?: readonly string[], moduleFile?: SourceFile, modulePaths?: readonly ModulePath[], cache?: ModuleSpecifierCache] { +): readonly [ + specifiers?: readonly string[], + moduleFile?: SourceFile, + modulePaths?: readonly ModulePath[], + cache?: ModuleSpecifierCache, +] { const moduleSourceFile = getSourceFileOfModule(moduleSymbol); if (!moduleSourceFile) { return emptyArray as []; @@ -346,7 +439,14 @@ export function getModuleSpecifiersWithCacheInfo( computedWithoutCache = true; modulePaths ||= getAllModulePathsWorker(importingSourceFile.path, moduleSourceFile.originalFileName, host); - const result = computeModuleSpecifiers(modulePaths, compilerOptions, importingSourceFile, host, userPreferences, options); + const result = computeModuleSpecifiers( + modulePaths, + compilerOptions, + importingSourceFile, + host, + userPreferences, + options, + ); cache?.set(importingSourceFile.path, moduleSourceFile.path, userPreferences, options, modulePaths, result); return { moduleSpecifiers: result, computedWithoutCache }; } @@ -363,17 +463,25 @@ function computeModuleSpecifiers( const preferences = getPreferences(userPreferences, compilerOptions, importingSourceFile); const existingSpecifier = forEach(modulePaths, modulePath => forEach( - host.getFileIncludeReasons().get(toPath(modulePath.path, host.getCurrentDirectory(), info.getCanonicalFileName)), + host.getFileIncludeReasons().get( + toPath(modulePath.path, host.getCurrentDirectory(), info.getCanonicalFileName), + ), reason => { - if (reason.kind !== FileIncludeKind.Import || reason.file !== importingSourceFile.path) return undefined; + if (reason.kind !== FileIncludeKind.Import || reason.file !== importingSourceFile.path) { + return undefined; + } // If the candidate import mode doesn't match the mode we're generating for, don't consider it // TODO: maybe useful to keep around as an alternative option for certain contexts where the mode is overridable - if (importingSourceFile.impliedNodeFormat && importingSourceFile.impliedNodeFormat !== getModeForResolutionAtIndex(importingSourceFile, reason.index)) return undefined; + if ( + importingSourceFile.impliedNodeFormat + && importingSourceFile.impliedNodeFormat + !== getModeForResolutionAtIndex(importingSourceFile, reason.index) + ) return undefined; const specifier = getModuleNameStringLiteralAt(importingSourceFile, reason.index).text; // If the preference is for non relative and the module specifier is relative, ignore it - return preferences.relativePreference !== RelativePreference.NonRelative || !pathIsRelative(specifier) ? - specifier : - undefined; + return preferences.relativePreference !== RelativePreference.NonRelative || !pathIsRelative(specifier) + ? specifier + : undefined; }, )); if (existingSpecifier) { @@ -394,7 +502,16 @@ function computeModuleSpecifiers( let relativeSpecifiers: string[] | undefined; for (const modulePath of modulePaths) { const specifier = modulePath.isInNodeModules - ? tryGetModuleNameAsNodeModule(modulePath, info, importingSourceFile, host, compilerOptions, userPreferences, /*packageNameOnly*/ undefined, options.overrideImportMode) + ? tryGetModuleNameAsNodeModule( + modulePath, + info, + importingSourceFile, + host, + compilerOptions, + userPreferences, + /*packageNameOnly*/ undefined, + options.overrideImportMode, + ) : undefined; nodeModulesSpecifiers = append(nodeModulesSpecifiers, specifier); if (specifier && modulePath.isRedirect) { @@ -437,10 +554,10 @@ function computeModuleSpecifiers( } } - return pathsSpecifiers?.length ? pathsSpecifiers : - redirectPathsSpecifiers?.length ? redirectPathsSpecifiers : - nodeModulesSpecifiers?.length ? nodeModulesSpecifiers : - Debug.checkDefined(relativeSpecifiers); + return pathsSpecifiers?.length ? pathsSpecifiers + : redirectPathsSpecifiers?.length ? redirectPathsSpecifiers + : nodeModulesSpecifiers?.length ? nodeModulesSpecifiers + : Debug.checkDefined(relativeSpecifiers); } interface Info { @@ -450,14 +567,39 @@ interface Info { } // importingSourceFileName is separate because getEditsForFileRename may need to specify an updated path function getInfo(importingSourceFileName: Path, host: ModuleSpecifierResolutionHost): Info { - const getCanonicalFileName = createGetCanonicalFileName(host.useCaseSensitiveFileNames ? host.useCaseSensitiveFileNames() : true); + const getCanonicalFileName = createGetCanonicalFileName( + host.useCaseSensitiveFileNames ? host.useCaseSensitiveFileNames() : true, + ); const sourceDirectory = getDirectoryPath(importingSourceFileName); return { getCanonicalFileName, importingSourceFileName, sourceDirectory }; } -function getLocalModuleSpecifier(moduleFileName: string, info: Info, compilerOptions: CompilerOptions, host: ModuleSpecifierResolutionHost, importMode: ResolutionMode, preferences: Preferences): string; -function getLocalModuleSpecifier(moduleFileName: string, info: Info, compilerOptions: CompilerOptions, host: ModuleSpecifierResolutionHost, importMode: ResolutionMode, preferences: Preferences, pathsOnly?: boolean): string | undefined; -function getLocalModuleSpecifier(moduleFileName: string, info: Info, compilerOptions: CompilerOptions, host: ModuleSpecifierResolutionHost, importMode: ResolutionMode, { getAllowedEndingsInPreferredOrder: getAllowedEndingsInPrefererredOrder, relativePreference }: Preferences, pathsOnly?: boolean): string | undefined { +function getLocalModuleSpecifier( + moduleFileName: string, + info: Info, + compilerOptions: CompilerOptions, + host: ModuleSpecifierResolutionHost, + importMode: ResolutionMode, + preferences: Preferences, +): string; +function getLocalModuleSpecifier( + moduleFileName: string, + info: Info, + compilerOptions: CompilerOptions, + host: ModuleSpecifierResolutionHost, + importMode: ResolutionMode, + preferences: Preferences, + pathsOnly?: boolean, +): string | undefined; +function getLocalModuleSpecifier( + moduleFileName: string, + info: Info, + compilerOptions: CompilerOptions, + host: ModuleSpecifierResolutionHost, + importMode: ResolutionMode, + { getAllowedEndingsInPreferredOrder: getAllowedEndingsInPrefererredOrder, relativePreference }: Preferences, + pathsOnly?: boolean, +): string | undefined { const { baseUrl, paths, rootDirs } = compilerOptions; if (pathsOnly && !paths) { return undefined; @@ -465,24 +607,43 @@ function getLocalModuleSpecifier(moduleFileName: string, info: Info, compilerOpt const { sourceDirectory, getCanonicalFileName } = info; const allowedEndings = getAllowedEndingsInPrefererredOrder(importMode); - const relativePath = rootDirs && tryGetModuleNameFromRootDirs(rootDirs, moduleFileName, sourceDirectory, getCanonicalFileName, allowedEndings, compilerOptions) || - processEnding(ensurePathIsNonModuleName(getRelativePathFromDirectory(sourceDirectory, moduleFileName, getCanonicalFileName)), allowedEndings, compilerOptions); + const relativePath = rootDirs + && tryGetModuleNameFromRootDirs( + rootDirs, + moduleFileName, + sourceDirectory, + getCanonicalFileName, + allowedEndings, + compilerOptions, + ) + || processEnding( + ensurePathIsNonModuleName( + getRelativePathFromDirectory(sourceDirectory, moduleFileName, getCanonicalFileName), + ), + allowedEndings, + compilerOptions, + ); if (!baseUrl && !paths || relativePreference === RelativePreference.Relative) { return pathsOnly ? undefined : relativePath; } - const baseDirectory = getNormalizedAbsolutePath(getPathsBasePath(compilerOptions, host) || baseUrl!, host.getCurrentDirectory()); + const baseDirectory = getNormalizedAbsolutePath( + getPathsBasePath(compilerOptions, host) || baseUrl!, + host.getCurrentDirectory(), + ); const relativeToBaseUrl = getRelativePathIfInSameVolume(moduleFileName, baseDirectory, getCanonicalFileName); if (!relativeToBaseUrl) { return pathsOnly ? undefined : relativePath; } - const fromPaths = paths && tryGetModuleNameFromPaths(relativeToBaseUrl, paths, allowedEndings, host, compilerOptions); + const fromPaths = paths + && tryGetModuleNameFromPaths(relativeToBaseUrl, paths, allowedEndings, host, compilerOptions); if (pathsOnly) { return fromPaths; } - const maybeNonRelative = fromPaths === undefined && baseUrl !== undefined ? processEnding(relativeToBaseUrl, allowedEndings, compilerOptions) : fromPaths; + const maybeNonRelative = fromPaths === undefined && baseUrl !== undefined + ? processEnding(relativeToBaseUrl, allowedEndings, compilerOptions) : fromPaths; if (!maybeNonRelative) { return relativePath; } @@ -492,9 +653,13 @@ function getLocalModuleSpecifier(moduleFileName: string, info: Info, compilerOpt } if (relativePreference === RelativePreference.ExternalNonRelative && !pathIsRelative(maybeNonRelative)) { - const projectDirectory = compilerOptions.configFilePath ? - toPath(getDirectoryPath(compilerOptions.configFilePath), host.getCurrentDirectory(), info.getCanonicalFileName) : - info.getCanonicalFileName(host.getCurrentDirectory()); + const projectDirectory = compilerOptions.configFilePath + ? toPath( + getDirectoryPath(compilerOptions.configFilePath), + host.getCurrentDirectory(), + info.getCanonicalFileName, + ) + : info.getCanonicalFileName(host.getCurrentDirectory()); const modulePath = toPath(moduleFileName, projectDirectory, getCanonicalFileName); const sourceIsInternal = startsWith(sourceDirectory, projectDirectory); const targetIsInternal = startsWith(modulePath, projectDirectory); @@ -529,7 +694,9 @@ function getLocalModuleSpecifier(moduleFileName: string, info: Info, compilerOpt } // Prefer a relative import over a baseUrl import if it has fewer components. - return isPathRelativeToParent(maybeNonRelative) || countPathComponents(relativePath) < countPathComponents(maybeNonRelative) ? relativePath : maybeNonRelative; + return isPathRelativeToParent(maybeNonRelative) + || countPathComponents(relativePath) < countPathComponents(maybeNonRelative) ? relativePath + : maybeNonRelative; } /** @internal */ @@ -564,47 +731,61 @@ export function forEachFileNameOfModule( ): T | undefined { const getCanonicalFileName = hostGetCanonicalFileName(host); const cwd = host.getCurrentDirectory(); - const referenceRedirect = host.isSourceOfProjectReferenceRedirect(importedFileName) ? host.getProjectReferenceRedirect(importedFileName) : undefined; + const referenceRedirect = host.isSourceOfProjectReferenceRedirect(importedFileName) + ? host.getProjectReferenceRedirect(importedFileName) : undefined; const importedPath = toPath(importedFileName, cwd, getCanonicalFileName); const redirects = host.redirectTargetsMap.get(importedPath) || emptyArray; - const importedFileNames = [...(referenceRedirect ? [referenceRedirect] : emptyArray), importedFileName, ...redirects]; + const importedFileNames = [ + ...(referenceRedirect ? [referenceRedirect] : emptyArray), + importedFileName, + ...redirects, + ]; const targets = importedFileNames.map(f => getNormalizedAbsolutePath(f, cwd)); let shouldFilterIgnoredPaths = !every(targets, containsIgnoredPath); if (!preferSymlinks) { // Symlinks inside ignored paths are already filtered out of the symlink cache, // so we only need to remove them from the realpath filenames. - const result = forEach(targets, p => !(shouldFilterIgnoredPaths && containsIgnoredPath(p)) && cb(p, referenceRedirect === p)); + const result = forEach( + targets, + p => !(shouldFilterIgnoredPaths && containsIgnoredPath(p)) && cb(p, referenceRedirect === p), + ); if (result) return result; } const symlinkedDirectories = host.getSymlinkCache?.().getSymlinkedDirectoriesByRealpath(); const fullImportedFileName = getNormalizedAbsolutePath(importedFileName, cwd); - const result = symlinkedDirectories && forEachAncestorDirectory(getDirectoryPath(fullImportedFileName), realPathDirectory => { - const symlinkDirectories = symlinkedDirectories.get(ensureTrailingDirectorySeparator(toPath(realPathDirectory, cwd, getCanonicalFileName))); - if (!symlinkDirectories) return undefined; // Continue to ancestor directory - - // Don't want to a package to globally import from itself (importNameCodeFix_symlink_own_package.ts) - if (startsWithDirectory(importingFileName, realPathDirectory, getCanonicalFileName)) { - return false; // Stop search, each ancestor directory will also hit this condition - } + const result = symlinkedDirectories + && forEachAncestorDirectory(getDirectoryPath(fullImportedFileName), realPathDirectory => { + const symlinkDirectories = symlinkedDirectories.get( + ensureTrailingDirectorySeparator(toPath(realPathDirectory, cwd, getCanonicalFileName)), + ); + if (!symlinkDirectories) return undefined; // Continue to ancestor directory - return forEach(targets, target => { - if (!startsWithDirectory(target, realPathDirectory, getCanonicalFileName)) { - return; + // Don't want to a package to globally import from itself (importNameCodeFix_symlink_own_package.ts) + if (startsWithDirectory(importingFileName, realPathDirectory, getCanonicalFileName)) { + return false; // Stop search, each ancestor directory will also hit this condition } - const relative = getRelativePathFromDirectory(realPathDirectory, target, getCanonicalFileName); - for (const symlinkDirectory of symlinkDirectories) { - const option = resolvePath(symlinkDirectory, relative); - const result = cb(option, target === referenceRedirect); - shouldFilterIgnoredPaths = true; // We found a non-ignored path in symlinks, so we can reject ignored-path realpaths - if (result) return result; - } + return forEach(targets, target => { + if (!startsWithDirectory(target, realPathDirectory, getCanonicalFileName)) { + return; + } + + const relative = getRelativePathFromDirectory(realPathDirectory, target, getCanonicalFileName); + for (const symlinkDirectory of symlinkDirectories) { + const option = resolvePath(symlinkDirectory, relative); + const result = cb(option, target === referenceRedirect); + shouldFilterIgnoredPaths = true; // We found a non-ignored path in symlinks, so we can reject ignored-path realpaths + if (result) return result; + } + }); }); - }); return result || (preferSymlinks - ? forEach(targets, p => shouldFilterIgnoredPaths && containsIgnoredPath(p) ? undefined : cb(p, p === referenceRedirect)) + ? forEach( + targets, + p => shouldFilterIgnoredPaths && containsIgnoredPath(p) ? undefined : cb(p, p === referenceRedirect), + ) : undefined); } @@ -632,7 +813,11 @@ function getAllModulePaths( return modulePaths; } -function getAllModulePathsWorker(importingFileName: Path, importedFileName: string, host: ModuleSpecifierResolutionHost): readonly ModulePath[] { +function getAllModulePathsWorker( + importingFileName: Path, + importedFileName: string, + host: ModuleSpecifierResolutionHost, +): readonly ModulePath[] { const getCanonicalFileName = hostGetCanonicalFileName(host); const allFileNames = new Map(); let importedFileFromNodeModules = false; @@ -684,7 +869,9 @@ function getAllModulePathsWorker(importingFileName: Path, importedFileName: stri function tryGetModuleNameFromAmbientModule(moduleSymbol: Symbol, checker: TypeChecker): string | undefined { const decl = moduleSymbol.declarations?.find( - d => isNonGlobalAmbientModule(d) && (!isExternalModuleAugmentation(d) || !isExternalModuleNameRelative(getTextOfIdentifierOrLiteral(d.name))), + d => isNonGlobalAmbientModule(d) + && (!isExternalModuleAugmentation(d) + || !isExternalModuleNameRelative(getTextOfIdentifierOrLiteral(d.name))), ) as (ModuleDeclaration & { name: StringLiteral; }) | undefined; if (decl) { return decl.name.text; @@ -705,13 +892,16 @@ function tryGetModuleNameFromAmbientModule(moduleSymbol: Symbol, checker: TypeCh const topNamespace = getTopNamespace(d); if ( !(topNamespace?.parent?.parent - && isModuleBlock(topNamespace.parent) && isAmbientModule(topNamespace.parent.parent) && isSourceFile(topNamespace.parent.parent.parent)) + && isModuleBlock(topNamespace.parent) && isAmbientModule(topNamespace.parent.parent) + && isSourceFile(topNamespace.parent.parent.parent)) ) return; - const exportAssignment = (topNamespace.parent.parent.symbol.exports?.get("export=" as __String)?.valueDeclaration as ExportAssignment)?.expression as PropertyAccessExpression | Identifier; + const exportAssignment = (topNamespace.parent.parent.symbol.exports?.get("export=" as __String) + ?.valueDeclaration as ExportAssignment)?.expression as PropertyAccessExpression | Identifier; if (!exportAssignment) return; const exportSymbol = checker.getSymbolAtLocation(exportAssignment); if (!exportSymbol) return; - const originalExportSymbol = exportSymbol?.flags & SymbolFlags.Alias ? checker.getAliasedSymbol(exportSymbol) : exportSymbol; + const originalExportSymbol = exportSymbol?.flags & SymbolFlags.Alias ? checker.getAliasedSymbol(exportSymbol) + : exportSymbol; if (originalExportSymbol === d.symbol) return topNamespace.parent.parent; function getTopNamespace(namespaceDeclaration: ModuleDeclaration) { @@ -721,13 +911,21 @@ function tryGetModuleNameFromAmbientModule(moduleSymbol: Symbol, checker: TypeCh return namespaceDeclaration; } }); - const ambientModuleDeclare = ambientModuleDeclareCandidates[0] as (AmbientModuleDeclaration & { name: StringLiteral; }) | undefined; + const ambientModuleDeclare = ambientModuleDeclareCandidates[0] as + | (AmbientModuleDeclaration & { name: StringLiteral; }) + | undefined; if (ambientModuleDeclare) { return ambientModuleDeclare.name.text; } } -function tryGetModuleNameFromPaths(relativeToBaseUrl: string, paths: MapLike, allowedEndings: ModuleSpecifierEnding[], host: ModuleSpecifierResolutionHost, compilerOptions: CompilerOptions): string | undefined { +function tryGetModuleNameFromPaths( + relativeToBaseUrl: string, + paths: MapLike, + allowedEndings: ModuleSpecifierEnding[], + host: ModuleSpecifierResolutionHost, + compilerOptions: CompilerOptions, +): string | undefined { for (const key in paths) { for (const patternText of paths[key]) { const pattern = normalizePath(patternText); @@ -768,10 +966,12 @@ function tryGetModuleNameFromPaths(relativeToBaseUrl: string, paths: MapLike ({ - ending, - value: processEnding(relativeToBaseUrl, [ending], compilerOptions), - })); + const candidates: { ending: ModuleSpecifierEnding | undefined; value: string; }[] = allowedEndings.map( + ending => ({ + ending, + value: processEnding(relativeToBaseUrl, [ending], compilerOptions), + }), + ); if (tryGetExtensionFromPath(pattern)) { candidates.push({ ending: undefined, value: relativeToBaseUrl }); } @@ -781,10 +981,10 @@ function tryGetModuleNameFromPaths(relativeToBaseUrl: string, paths: MapLike= prefix.length + suffix.length && - startsWith(value, prefix) && - endsWith(value, suffix) && - validateEnding({ ending, value }) + value.length >= prefix.length + suffix.length + && startsWith(value, prefix) + && endsWith(value, suffix) + && validateEnding({ ending, value }) ) { const matchedStar = value.substring(prefix.length, value.length - suffix.length); if (!pathIsRelative(matchedStar)) { @@ -794,8 +994,11 @@ function tryGetModuleNameFromPaths(relativeToBaseUrl: string, paths: MapLike c.ending !== ModuleSpecifierEnding.Minimal && pattern === c.value) || - some(candidates, c => c.ending === ModuleSpecifierEnding.Minimal && pattern === c.value && validateEnding(c)) + some(candidates, c => c.ending !== ModuleSpecifierEnding.Minimal && pattern === c.value) + || some( + candidates, + c => c.ending === ModuleSpecifierEnding.Minimal && pattern === c.value && validateEnding(c), + ) ) { return key; } @@ -810,7 +1013,8 @@ function tryGetModuleNameFromPaths(relativeToBaseUrl: string, paths: MapLike tryGetModuleNameFromExports(options, targetFilePath, packageDirectory, packageName, e, conditions)); + return forEach( + exports, + e => tryGetModuleNameFromExports(options, targetFilePath, packageDirectory, packageName, e, conditions), + ); } else if (typeof exports === "object" && exports !== null) { // eslint-disable-line no-null/no-null if (allKeysStartWithDot(exports as MapLike)) { @@ -862,19 +1099,40 @@ function tryGetModuleNameFromExports(options: CompilerOptions, targetFilePath: s // * pattern mappings (contains a *) // * exact mappings (no *, does not end with /) return forEach(getOwnKeys(exports as MapLike), k => { - const subPackageName = getNormalizedAbsolutePath(combinePaths(packageName, k), /*currentDirectory*/ undefined); + const subPackageName = getNormalizedAbsolutePath( + combinePaths(packageName, k), + /*currentDirectory*/ undefined, + ); const mode = endsWith(k, "/") ? MatchingMode.Directory : stringContains(k, "*") ? MatchingMode.Pattern : MatchingMode.Exact; - return tryGetModuleNameFromExports(options, targetFilePath, packageDirectory, subPackageName, (exports as MapLike)[k], conditions, mode); + return tryGetModuleNameFromExports( + options, + targetFilePath, + packageDirectory, + subPackageName, + (exports as MapLike)[k], + conditions, + mode, + ); }); } else { // conditional mapping for (const key of getOwnKeys(exports as MapLike)) { - if (key === "default" || conditions.indexOf(key) >= 0 || isApplicableVersionedTypesKey(conditions, key)) { + if ( + key === "default" || conditions.indexOf(key) >= 0 || isApplicableVersionedTypesKey(conditions, key) + ) { const subTarget = (exports as MapLike)[key]; - const result = tryGetModuleNameFromExports(options, targetFilePath, packageDirectory, packageName, subTarget, conditions, mode); + const result = tryGetModuleNameFromExports( + options, + targetFilePath, + packageDirectory, + packageName, + subTarget, + conditions, + mode, + ); if (result) { return result; } @@ -885,7 +1143,14 @@ function tryGetModuleNameFromExports(options: CompilerOptions, targetFilePath: s return undefined; } -function tryGetModuleNameFromRootDirs(rootDirs: readonly string[], moduleFileName: string, sourceDirectory: string, getCanonicalFileName: (file: string) => string, allowedEndings: readonly ModuleSpecifierEnding[], compilerOptions: CompilerOptions): string | undefined { +function tryGetModuleNameFromRootDirs( + rootDirs: readonly string[], + moduleFileName: string, + sourceDirectory: string, + getCanonicalFileName: (file: string) => string, + allowedEndings: readonly ModuleSpecifierEnding[], + compilerOptions: CompilerOptions, +): string | undefined { const normalizedTargetPaths = getPathsRelativeToRootDirs(moduleFileName, rootDirs, getCanonicalFileName); if (normalizedTargetPaths === undefined) { return undefined; @@ -893,7 +1158,11 @@ function tryGetModuleNameFromRootDirs(rootDirs: readonly string[], moduleFileNam const normalizedSourcePaths = getPathsRelativeToRootDirs(sourceDirectory, rootDirs, getCanonicalFileName); const relativePaths = flatMap(normalizedSourcePaths, sourcePath => { - return map(normalizedTargetPaths, targetPath => ensurePathIsNonModuleName(getRelativePathFromDirectory(sourcePath, targetPath, getCanonicalFileName))); + return map( + normalizedTargetPaths, + targetPath => + ensurePathIsNonModuleName(getRelativePathFromDirectory(sourcePath, targetPath, getCanonicalFileName)), + ); }); const shortest = min(relativePaths, compareNumberOfDirectorySeparators); if (!shortest) { @@ -902,7 +1171,16 @@ function tryGetModuleNameFromRootDirs(rootDirs: readonly string[], moduleFileNam return processEnding(shortest, allowedEndings, compilerOptions); } -function tryGetModuleNameAsNodeModule({ path, isRedirect }: ModulePath, { getCanonicalFileName, sourceDirectory }: Info, importingSourceFile: SourceFile, host: ModuleSpecifierResolutionHost, options: CompilerOptions, userPreferences: UserPreferences, packageNameOnly?: boolean, overrideMode?: ResolutionMode): string | undefined { +function tryGetModuleNameAsNodeModule( + { path, isRedirect }: ModulePath, + { getCanonicalFileName, sourceDirectory }: Info, + importingSourceFile: SourceFile, + host: ModuleSpecifierResolutionHost, + options: CompilerOptions, + userPreferences: UserPreferences, + packageNameOnly?: boolean, + overrideMode?: ResolutionMode, +): string | undefined { if (!host.fileExists || !host.readFile) { return undefined; } @@ -922,7 +1200,8 @@ function tryGetModuleNameAsNodeModule({ path, isRedirect }: ModulePath, { getCan let moduleFileName: string | undefined; while (true) { // If the module could be imported by a directory name, use that directory's name - const { moduleFileToTry, packageRootPath, blockedByExports, verbatimFromExports } = tryDirectoryWithPackageJson(packageRootIndex); + const { moduleFileToTry, packageRootPath, blockedByExports, verbatimFromExports } = + tryDirectoryWithPackageJson(packageRootIndex); if (getEmitModuleResolutionKind(options) !== ModuleResolutionKind.Classic) { if (blockedByExports) { return undefined; // File is under this package.json, but is not publicly exported - there's no way to name it via `node_modules` resolution @@ -954,8 +1233,14 @@ function tryGetModuleNameAsNodeModule({ path, isRedirect }: ModulePath, { getCan const globalTypingsCacheLocation = host.getGlobalTypingsCacheLocation && host.getGlobalTypingsCacheLocation(); // Get a path that's relative to node_modules or the importing file's path // if node_modules folder is in this folder or any of its parent folders, no need to keep it. - const pathToTopLevelNodeModules = getCanonicalFileName(moduleSpecifier.substring(0, parts.topLevelNodeModulesIndex)); - if (!(startsWith(sourceDirectory, pathToTopLevelNodeModules) || globalTypingsCacheLocation && startsWith(getCanonicalFileName(globalTypingsCacheLocation), pathToTopLevelNodeModules))) { + const pathToTopLevelNodeModules = getCanonicalFileName( + moduleSpecifier.substring(0, parts.topLevelNodeModulesIndex), + ); + if ( + !(startsWith(sourceDirectory, pathToTopLevelNodeModules) + || globalTypingsCacheLocation + && startsWith(getCanonicalFileName(globalTypingsCacheLocation), pathToTopLevelNodeModules)) + ) { return undefined; } @@ -963,16 +1248,22 @@ function tryGetModuleNameAsNodeModule({ path, isRedirect }: ModulePath, { getCan const nodeModulesDirectoryName = moduleSpecifier.substring(parts.topLevelPackageNameIndex + 1); const packageName = getPackageNameFromTypesPackageName(nodeModulesDirectoryName); // For classic resolution, only allow importing from node_modules/@types, not other node_modules - return getEmitModuleResolutionKind(options) === ModuleResolutionKind.Classic && packageName === nodeModulesDirectoryName ? undefined : packageName; + return getEmitModuleResolutionKind(options) === ModuleResolutionKind.Classic + && packageName === nodeModulesDirectoryName ? undefined : packageName; - function tryDirectoryWithPackageJson(packageRootIndex: number): { moduleFileToTry: string; packageRootPath?: string; blockedByExports?: true; verbatimFromExports?: true; } { + function tryDirectoryWithPackageJson( + packageRootIndex: number, + ): { moduleFileToTry: string; packageRootPath?: string; blockedByExports?: true; verbatimFromExports?: true; } { const packageRootPath = path.substring(0, packageRootIndex); const packageJsonPath = combinePaths(packageRootPath, "package.json"); let moduleFileToTry = path; let maybeBlockedByTypesVersions = false; const cachedPackageJson = host.getPackageJsonInfoCache?.()?.getPackageJsonInfo(packageJsonPath); - if (typeof cachedPackageJson === "object" || cachedPackageJson === undefined && host.fileExists(packageJsonPath)) { - const packageJsonContent = cachedPackageJson?.contents.packageJsonContent || JSON.parse(host.readFile!(packageJsonPath)!); + if ( + typeof cachedPackageJson === "object" || cachedPackageJson === undefined && host.fileExists(packageJsonPath) + ) { + const packageJsonContent = cachedPackageJson?.contents.packageJsonContent + || JSON.parse(host.readFile!(packageJsonPath)!); const importMode = overrideMode || importingSourceFile.impliedNodeFormat; if (getResolvePackageJsonExports(options)) { // The package name that we found in node_modules could be different from the package @@ -982,12 +1273,22 @@ function tryGetModuleNameAsNodeModule({ path, isRedirect }: ModulePath, { getCan const packageName = getPackageNameFromTypesPackageName(nodeModulesDirectoryName); const conditions = getConditions(options, importMode === ModuleKind.ESNext); const fromExports = packageJsonContent.exports - ? tryGetModuleNameFromExports(options, path, packageRootPath, packageName, packageJsonContent.exports, conditions) + ? tryGetModuleNameFromExports( + options, + path, + packageRootPath, + packageName, + packageJsonContent.exports, + conditions, + ) : undefined; if (fromExports) { const withJsExtension = !hasTSFileExtension(fromExports.moduleFileToTry) ? fromExports - : { moduleFileToTry: removeFileExtension(fromExports.moduleFileToTry) + tryGetJSExtensionForFile(fromExports.moduleFileToTry, options) }; + : { + moduleFileToTry: removeFileExtension(fromExports.moduleFileToTry) + + tryGetJSExtensionForFile(fromExports.moduleFileToTry, options), + }; return { ...withJsExtension, verbatimFromExports: true }; } if (packageJsonContent.exports) { @@ -1014,8 +1315,13 @@ function tryGetModuleNameAsNodeModule({ path, isRedirect }: ModulePath, { getCan } } // If the file is the main module, it can be imported by the package name - const mainFileRelative = packageJsonContent.typings || packageJsonContent.types || packageJsonContent.main || "index.js"; - if (isString(mainFileRelative) && !(maybeBlockedByTypesVersions && matchPatternOrExact(tryParsePatterns(versionPaths!.paths), mainFileRelative))) { + const mainFileRelative = packageJsonContent.typings || packageJsonContent.types || packageJsonContent.main + || "index.js"; + if ( + isString(mainFileRelative) + && !(maybeBlockedByTypesVersions + && matchPatternOrExact(tryParsePatterns(versionPaths!.paths), mainFileRelative)) + ) { // The 'main' file is also subject to mapping through typesVersions, and we couldn't come up with a path // explicitly through typesVersions, so if it matches a key in typesVersions now, it's not reachable. // (The only way this can happen is if some file in a package that's not resolvable from outside the @@ -1029,11 +1335,11 @@ function tryGetModuleNameAsNodeModule({ path, isRedirect }: ModulePath, { getCan return { packageRootPath, moduleFileToTry }; } else if ( - packageJsonContent.type !== "module" && - !fileExtensionIsOneOf(canonicalModuleFileToTry, extensionsNotSupportingExtensionlessResolution) && - startsWith(canonicalModuleFileToTry, mainExportFile) && - getDirectoryPath(canonicalModuleFileToTry) === removeTrailingDirectorySeparator(mainExportFile) && - removeFileExtension(getBaseFileName(canonicalModuleFileToTry)) === "index" + packageJsonContent.type !== "module" + && !fileExtensionIsOneOf(canonicalModuleFileToTry, extensionsNotSupportingExtensionlessResolution) + && startsWith(canonicalModuleFileToTry, mainExportFile) + && getDirectoryPath(canonicalModuleFileToTry) === removeTrailingDirectorySeparator(mainExportFile) + && removeFileExtension(getBaseFileName(canonicalModuleFileToTry)) === "index" ) { // if mainExportFile is a directory, which contains moduleFileToTry, we just try index file // example mainExportFile: `pkg/lib` and moduleFileToTry: `pkg/lib/index`, we can use packageRootPath @@ -1046,7 +1352,10 @@ function tryGetModuleNameAsNodeModule({ path, isRedirect }: ModulePath, { getCan else { // No package.json exists; an index.js will still resolve as the package name const fileName = getCanonicalFileName(moduleFileToTry.substring(parts.packageRootIndex + 1)); - if (fileName === "index.d.ts" || fileName === "index.js" || fileName === "index.ts" || fileName === "index.tsx") { + if ( + fileName === "index.d.ts" || fileName === "index.js" || fileName === "index.ts" + || fileName === "index.tsx" + ) { return { moduleFileToTry, packageRootPath }; } } @@ -1057,7 +1366,13 @@ function tryGetModuleNameAsNodeModule({ path, isRedirect }: ModulePath, { getCan function tryGetAnyFileFromPath(host: ModuleSpecifierResolutionHost, path: string) { if (!host.fileExists) return; // We check all js, `node` and `json` extensions in addition to TS, since node module resolution would also choose those over the directory - const extensions = flatten(getSupportedExtensions({ allowJs: true }, [{ extension: "node", isMixedContent: false }, { extension: "json", isMixedContent: false, scriptKind: ScriptKind.JSON }])); + const extensions = flatten( + getSupportedExtensions({ allowJs: true }, [{ extension: "node", isMixedContent: false }, { + extension: "json", + isMixedContent: false, + scriptKind: ScriptKind.JSON, + }]), + ); for (const e of extensions) { const fullPath = path + e; if (host.fileExists(fullPath)) { @@ -1066,14 +1381,23 @@ function tryGetAnyFileFromPath(host: ModuleSpecifierResolutionHost, path: string } } -function getPathsRelativeToRootDirs(path: string, rootDirs: readonly string[], getCanonicalFileName: GetCanonicalFileName): string[] | undefined { +function getPathsRelativeToRootDirs( + path: string, + rootDirs: readonly string[], + getCanonicalFileName: GetCanonicalFileName, +): string[] | undefined { return mapDefined(rootDirs, rootDir => { const relativePath = getRelativePathIfInSameVolume(path, rootDir, getCanonicalFileName); return relativePath !== undefined && isPathRelativeToParent(relativePath) ? undefined : relativePath; }); } -function processEnding(fileName: string, allowedEndings: readonly ModuleSpecifierEnding[], options: CompilerOptions, host?: ModuleSpecifierResolutionHost): string { +function processEnding( + fileName: string, + allowedEndings: readonly ModuleSpecifierEnding[], + options: CompilerOptions, + host?: ModuleSpecifierResolutionHost, +): string { if (fileExtensionIsOneOf(fileName, [Extension.Json, Extension.Mjs, Extension.Cjs])) { return fileName; } @@ -1085,13 +1409,18 @@ function processEnding(fileName: string, allowedEndings: readonly ModuleSpecifie const jsPriority = allowedEndings.indexOf(ModuleSpecifierEnding.JsExtension); const tsPriority = allowedEndings.indexOf(ModuleSpecifierEnding.TsExtension); - if (fileExtensionIsOneOf(fileName, [Extension.Mts, Extension.Cts]) && tsPriority !== -1 && tsPriority < jsPriority) { + if ( + fileExtensionIsOneOf(fileName, [Extension.Mts, Extension.Cts]) && tsPriority !== -1 && tsPriority < jsPriority + ) { return fileName; } else if (fileExtensionIsOneOf(fileName, [Extension.Dmts, Extension.Mts, Extension.Dcts, Extension.Cts])) { return noExtension + getJSExtensionForFile(fileName, options); } - else if (!fileExtensionIsOneOf(fileName, [Extension.Dts]) && fileExtensionIsOneOf(fileName, [Extension.Ts]) && stringContains(fileName, ".d.")) { + else if ( + !fileExtensionIsOneOf(fileName, [Extension.Dts]) && fileExtensionIsOneOf(fileName, [Extension.Ts]) + && stringContains(fileName, ".d.") + ) { // `foo.d.json.ts` and the like - remap back to `foo.json` return tryGetRealFileNameForNonJsDeclarationFileName(fileName)!; } @@ -1113,7 +1442,9 @@ function processEnding(fileName: string, allowedEndings: readonly ModuleSpecifie // For now, we don't know if this import is going to be type-only, which means we don't // know if a .d.ts extension is valid, so use no extension or a .js extension if (isDeclarationFileName(fileName)) { - const extensionlessPriority = allowedEndings.findIndex(e => e === ModuleSpecifierEnding.Minimal || e === ModuleSpecifierEnding.Index); + const extensionlessPriority = allowedEndings.findIndex(e => + e === ModuleSpecifierEnding.Minimal || e === ModuleSpecifierEnding.Index + ); return extensionlessPriority !== -1 && extensionlessPriority < jsPriority ? noExtension : noExtension + getJSExtensionForFile(fileName, options); @@ -1127,14 +1458,18 @@ function processEnding(fileName: string, allowedEndings: readonly ModuleSpecifie /** @internal */ export function tryGetRealFileNameForNonJsDeclarationFileName(fileName: string) { const baseName = getBaseFileName(fileName); - if (!endsWith(fileName, Extension.Ts) || !stringContains(baseName, ".d.") || fileExtensionIsOneOf(baseName, [Extension.Dts])) return undefined; + if ( + !endsWith(fileName, Extension.Ts) || !stringContains(baseName, ".d.") + || fileExtensionIsOneOf(baseName, [Extension.Dts]) + ) return undefined; const noExtension = removeExtension(fileName, Extension.Ts); const ext = noExtension.substring(noExtension.lastIndexOf(".")); return noExtension.substring(0, noExtension.indexOf(".d.")) + ext; } function getJSExtensionForFile(fileName: string, options: CompilerOptions): Extension { - return tryGetJSExtensionForFile(fileName, options) ?? Debug.fail(`Extension ${extensionFromPath(fileName)} is unsupported:: FileName:: ${fileName}`); + return tryGetJSExtensionForFile(fileName, options) + ?? Debug.fail(`Extension ${extensionFromPath(fileName)} is unsupported:: FileName:: ${fileName}`); } /** @internal */ @@ -1163,8 +1498,18 @@ export function tryGetJSExtensionForFile(fileName: string, options: CompilerOpti } } -function getRelativePathIfInSameVolume(path: string, directoryPath: string, getCanonicalFileName: GetCanonicalFileName): string | undefined { - const relativePath = getRelativePathToDirectoryOrUrl(directoryPath, path, directoryPath, getCanonicalFileName, /*isAbsolutePathAnUrl*/ false); +function getRelativePathIfInSameVolume( + path: string, + directoryPath: string, + getCanonicalFileName: GetCanonicalFileName, +): string | undefined { + const relativePath = getRelativePathToDirectoryOrUrl( + directoryPath, + path, + directoryPath, + getCanonicalFileName, + /*isAbsolutePathAnUrl*/ false, + ); return isRootedDiskPath(relativePath) ? undefined : relativePath; } diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 8ba717d21d775..132a4c21ed270 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -426,21 +426,42 @@ let SourceFileConstructor: new (kind: SyntaxKind.SourceFile, pos: number, end: n * @internal */ export const parseBaseNodeFactory: BaseNodeFactory = { - createBaseSourceFileNode: kind => new (SourceFileConstructor || (SourceFileConstructor = objectAllocator.getSourceFileConstructor()))(kind, -1, -1), - createBaseIdentifierNode: kind => new (IdentifierConstructor || (IdentifierConstructor = objectAllocator.getIdentifierConstructor()))(kind, -1, -1), - createBasePrivateIdentifierNode: kind => new (PrivateIdentifierConstructor || (PrivateIdentifierConstructor = objectAllocator.getPrivateIdentifierConstructor()))(kind, -1, -1), - createBaseTokenNode: kind => new (TokenConstructor || (TokenConstructor = objectAllocator.getTokenConstructor()))(kind, -1, -1), - createBaseNode: kind => new (NodeConstructor || (NodeConstructor = objectAllocator.getNodeConstructor()))(kind, -1, -1), + createBaseSourceFileNode: kind => + new (SourceFileConstructor || (SourceFileConstructor = objectAllocator.getSourceFileConstructor()))( + kind, + -1, + -1, + ), + createBaseIdentifierNode: kind => + new (IdentifierConstructor || (IdentifierConstructor = objectAllocator.getIdentifierConstructor()))( + kind, + -1, + -1, + ), + createBasePrivateIdentifierNode: kind => + new (PrivateIdentifierConstructor + || (PrivateIdentifierConstructor = objectAllocator.getPrivateIdentifierConstructor()))(kind, -1, -1), + createBaseTokenNode: kind => + new (TokenConstructor || (TokenConstructor = objectAllocator.getTokenConstructor()))(kind, -1, -1), + createBaseNode: kind => + new (NodeConstructor || (NodeConstructor = objectAllocator.getNodeConstructor()))(kind, -1, -1), }; /** @internal */ -export const parseNodeFactory: NodeFactory = createNodeFactory(NodeFactoryFlags.NoParenthesizerRules, parseBaseNodeFactory); +export const parseNodeFactory: NodeFactory = createNodeFactory( + NodeFactoryFlags.NoParenthesizerRules, + parseBaseNodeFactory, +); function visitNode(cbNode: (node: Node) => T, node: Node | undefined): T | undefined { return node && cbNode(node); } -function visitNodes(cbNode: (node: Node) => T, cbNodes: ((node: NodeArray) => T | undefined) | undefined, nodes: NodeArray | undefined): T | undefined { +function visitNodes( + cbNode: (node: Node) => T, + cbNodes: ((node: NodeArray) => T | undefined) | undefined, + nodes: NodeArray | undefined, +): T | undefined { if (nodes) { if (cbNodes) { return cbNodes(nodes); @@ -456,17 +477,17 @@ function visitNodes(cbNode: (node: Node) => T, cbNodes: ((node: NodeArray = (node: TNode, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined) => T | undefined; +type ForEachChildFunction = ( + node: TNode, + cbNode: (node: Node) => T | undefined, + cbNodes?: (nodes: NodeArray) => T | undefined, +) => T | undefined; type ForEachChildTable = { [TNode in ForEachChildNodes as TNode["kind"]]: ForEachChildFunction; }; const forEachChildTable: ForEachChildTable = { - [SyntaxKind.QualifiedName]: function forEachChildInQualifiedName(node: QualifiedName, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.left) || - visitNode(cbNode, node.right); + [SyntaxKind.QualifiedName]: function forEachChildInQualifiedName( + node: QualifiedName, + cbNode: (node: Node) => T | undefined, + _cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { + return visitNode(cbNode, node.left) + || visitNode(cbNode, node.right); }, - [SyntaxKind.TypeParameter]: function forEachChildInTypeParameter(node: TypeParameterDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNodes(cbNode, cbNodes, node.modifiers) || - visitNode(cbNode, node.name) || - visitNode(cbNode, node.constraint) || - visitNode(cbNode, node.default) || - visitNode(cbNode, node.expression); + [SyntaxKind.TypeParameter]: function forEachChildInTypeParameter( + node: TypeParameterDeclaration, + cbNode: (node: Node) => T | undefined, + cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { + return visitNodes(cbNode, cbNodes, node.modifiers) + || visitNode(cbNode, node.name) + || visitNode(cbNode, node.constraint) + || visitNode(cbNode, node.default) + || visitNode(cbNode, node.expression); }, - [SyntaxKind.ShorthandPropertyAssignment]: function forEachChildInShorthandPropertyAssignment(node: ShorthandPropertyAssignment, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNodes(cbNode, cbNodes, node.modifiers) || - visitNode(cbNode, node.name) || - visitNode(cbNode, node.questionToken) || - visitNode(cbNode, node.exclamationToken) || - visitNode(cbNode, node.equalsToken) || - visitNode(cbNode, node.objectAssignmentInitializer); + [SyntaxKind.ShorthandPropertyAssignment]: function forEachChildInShorthandPropertyAssignment( + node: ShorthandPropertyAssignment, + cbNode: (node: Node) => T | undefined, + cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { + return visitNodes(cbNode, cbNodes, node.modifiers) + || visitNode(cbNode, node.name) + || visitNode(cbNode, node.questionToken) + || visitNode(cbNode, node.exclamationToken) + || visitNode(cbNode, node.equalsToken) + || visitNode(cbNode, node.objectAssignmentInitializer); }, - [SyntaxKind.SpreadAssignment]: function forEachChildInSpreadAssignment(node: SpreadAssignment, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + [SyntaxKind.SpreadAssignment]: function forEachChildInSpreadAssignment( + node: SpreadAssignment, + cbNode: (node: Node) => T | undefined, + _cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { return visitNode(cbNode, node.expression); }, - [SyntaxKind.Parameter]: function forEachChildInParameter(node: ParameterDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNodes(cbNode, cbNodes, node.modifiers) || - visitNode(cbNode, node.dotDotDotToken) || - visitNode(cbNode, node.name) || - visitNode(cbNode, node.questionToken) || - visitNode(cbNode, node.type) || - visitNode(cbNode, node.initializer); + [SyntaxKind.Parameter]: function forEachChildInParameter( + node: ParameterDeclaration, + cbNode: (node: Node) => T | undefined, + cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { + return visitNodes(cbNode, cbNodes, node.modifiers) + || visitNode(cbNode, node.dotDotDotToken) + || visitNode(cbNode, node.name) + || visitNode(cbNode, node.questionToken) + || visitNode(cbNode, node.type) + || visitNode(cbNode, node.initializer); }, - [SyntaxKind.PropertyDeclaration]: function forEachChildInPropertyDeclaration(node: PropertyDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNodes(cbNode, cbNodes, node.modifiers) || - visitNode(cbNode, node.name) || - visitNode(cbNode, node.questionToken) || - visitNode(cbNode, node.exclamationToken) || - visitNode(cbNode, node.type) || - visitNode(cbNode, node.initializer); + [SyntaxKind.PropertyDeclaration]: function forEachChildInPropertyDeclaration( + node: PropertyDeclaration, + cbNode: (node: Node) => T | undefined, + cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { + return visitNodes(cbNode, cbNodes, node.modifiers) + || visitNode(cbNode, node.name) + || visitNode(cbNode, node.questionToken) + || visitNode(cbNode, node.exclamationToken) + || visitNode(cbNode, node.type) + || visitNode(cbNode, node.initializer); }, - [SyntaxKind.PropertySignature]: function forEachChildInPropertySignature(node: PropertySignature, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNodes(cbNode, cbNodes, node.modifiers) || - visitNode(cbNode, node.name) || - visitNode(cbNode, node.questionToken) || - visitNode(cbNode, node.type) || - visitNode(cbNode, node.initializer); + [SyntaxKind.PropertySignature]: function forEachChildInPropertySignature( + node: PropertySignature, + cbNode: (node: Node) => T | undefined, + cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { + return visitNodes(cbNode, cbNodes, node.modifiers) + || visitNode(cbNode, node.name) + || visitNode(cbNode, node.questionToken) + || visitNode(cbNode, node.type) + || visitNode(cbNode, node.initializer); }, - [SyntaxKind.PropertyAssignment]: function forEachChildInPropertyAssignment(node: PropertyAssignment, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNodes(cbNode, cbNodes, node.modifiers) || - visitNode(cbNode, node.name) || - visitNode(cbNode, node.questionToken) || - visitNode(cbNode, node.exclamationToken) || - visitNode(cbNode, node.initializer); + [SyntaxKind.PropertyAssignment]: function forEachChildInPropertyAssignment( + node: PropertyAssignment, + cbNode: (node: Node) => T | undefined, + cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { + return visitNodes(cbNode, cbNodes, node.modifiers) + || visitNode(cbNode, node.name) + || visitNode(cbNode, node.questionToken) + || visitNode(cbNode, node.exclamationToken) + || visitNode(cbNode, node.initializer); }, - [SyntaxKind.VariableDeclaration]: function forEachChildInVariableDeclaration(node: VariableDeclaration, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.name) || - visitNode(cbNode, node.exclamationToken) || - visitNode(cbNode, node.type) || - visitNode(cbNode, node.initializer); + [SyntaxKind.VariableDeclaration]: function forEachChildInVariableDeclaration( + node: VariableDeclaration, + cbNode: (node: Node) => T | undefined, + _cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { + return visitNode(cbNode, node.name) + || visitNode(cbNode, node.exclamationToken) + || visitNode(cbNode, node.type) + || visitNode(cbNode, node.initializer); }, - [SyntaxKind.BindingElement]: function forEachChildInBindingElement(node: BindingElement, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.dotDotDotToken) || - visitNode(cbNode, node.propertyName) || - visitNode(cbNode, node.name) || - visitNode(cbNode, node.initializer); + [SyntaxKind.BindingElement]: function forEachChildInBindingElement( + node: BindingElement, + cbNode: (node: Node) => T | undefined, + _cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { + return visitNode(cbNode, node.dotDotDotToken) + || visitNode(cbNode, node.propertyName) + || visitNode(cbNode, node.name) + || visitNode(cbNode, node.initializer); }, - [SyntaxKind.IndexSignature]: function forEachChildInIndexSignature(node: IndexSignatureDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNodes(cbNode, cbNodes, node.modifiers) || - visitNodes(cbNode, cbNodes, node.typeParameters) || - visitNodes(cbNode, cbNodes, node.parameters) || - visitNode(cbNode, node.type); + [SyntaxKind.IndexSignature]: function forEachChildInIndexSignature( + node: IndexSignatureDeclaration, + cbNode: (node: Node) => T | undefined, + cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { + return visitNodes(cbNode, cbNodes, node.modifiers) + || visitNodes(cbNode, cbNodes, node.typeParameters) + || visitNodes(cbNode, cbNodes, node.parameters) + || visitNode(cbNode, node.type); }, - [SyntaxKind.ConstructorType]: function forEachChildInConstructorType(node: ConstructorTypeNode, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNodes(cbNode, cbNodes, node.modifiers) || - visitNodes(cbNode, cbNodes, node.typeParameters) || - visitNodes(cbNode, cbNodes, node.parameters) || - visitNode(cbNode, node.type); + [SyntaxKind.ConstructorType]: function forEachChildInConstructorType( + node: ConstructorTypeNode, + cbNode: (node: Node) => T | undefined, + cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { + return visitNodes(cbNode, cbNodes, node.modifiers) + || visitNodes(cbNode, cbNodes, node.typeParameters) + || visitNodes(cbNode, cbNodes, node.parameters) + || visitNode(cbNode, node.type); }, - [SyntaxKind.FunctionType]: function forEachChildInFunctionType(node: FunctionTypeNode, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNodes(cbNode, cbNodes, node.modifiers) || - visitNodes(cbNode, cbNodes, node.typeParameters) || - visitNodes(cbNode, cbNodes, node.parameters) || - visitNode(cbNode, node.type); + [SyntaxKind.FunctionType]: function forEachChildInFunctionType( + node: FunctionTypeNode, + cbNode: (node: Node) => T | undefined, + cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { + return visitNodes(cbNode, cbNodes, node.modifiers) + || visitNodes(cbNode, cbNodes, node.typeParameters) + || visitNodes(cbNode, cbNodes, node.parameters) + || visitNode(cbNode, node.type); }, [SyntaxKind.CallSignature]: forEachChildInCallOrConstructSignature, [SyntaxKind.ConstructSignature]: forEachChildInCallOrConstructSignature, - [SyntaxKind.MethodDeclaration]: function forEachChildInMethodDeclaration(node: MethodDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNodes(cbNode, cbNodes, node.modifiers) || - visitNode(cbNode, node.asteriskToken) || - visitNode(cbNode, node.name) || - visitNode(cbNode, node.questionToken) || - visitNode(cbNode, node.exclamationToken) || - visitNodes(cbNode, cbNodes, node.typeParameters) || - visitNodes(cbNode, cbNodes, node.parameters) || - visitNode(cbNode, node.type) || - visitNode(cbNode, node.body); + [SyntaxKind.MethodDeclaration]: function forEachChildInMethodDeclaration( + node: MethodDeclaration, + cbNode: (node: Node) => T | undefined, + cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { + return visitNodes(cbNode, cbNodes, node.modifiers) + || visitNode(cbNode, node.asteriskToken) + || visitNode(cbNode, node.name) + || visitNode(cbNode, node.questionToken) + || visitNode(cbNode, node.exclamationToken) + || visitNodes(cbNode, cbNodes, node.typeParameters) + || visitNodes(cbNode, cbNodes, node.parameters) + || visitNode(cbNode, node.type) + || visitNode(cbNode, node.body); }, - [SyntaxKind.MethodSignature]: function forEachChildInMethodSignature(node: MethodSignature, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNodes(cbNode, cbNodes, node.modifiers) || - visitNode(cbNode, node.name) || - visitNode(cbNode, node.questionToken) || - visitNodes(cbNode, cbNodes, node.typeParameters) || - visitNodes(cbNode, cbNodes, node.parameters) || - visitNode(cbNode, node.type); + [SyntaxKind.MethodSignature]: function forEachChildInMethodSignature( + node: MethodSignature, + cbNode: (node: Node) => T | undefined, + cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { + return visitNodes(cbNode, cbNodes, node.modifiers) + || visitNode(cbNode, node.name) + || visitNode(cbNode, node.questionToken) + || visitNodes(cbNode, cbNodes, node.typeParameters) + || visitNodes(cbNode, cbNodes, node.parameters) + || visitNode(cbNode, node.type); }, - [SyntaxKind.Constructor]: function forEachChildInConstructor(node: ConstructorDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNodes(cbNode, cbNodes, node.modifiers) || - visitNode(cbNode, node.name) || - visitNodes(cbNode, cbNodes, node.typeParameters) || - visitNodes(cbNode, cbNodes, node.parameters) || - visitNode(cbNode, node.type) || - visitNode(cbNode, node.body); + [SyntaxKind.Constructor]: function forEachChildInConstructor( + node: ConstructorDeclaration, + cbNode: (node: Node) => T | undefined, + cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { + return visitNodes(cbNode, cbNodes, node.modifiers) + || visitNode(cbNode, node.name) + || visitNodes(cbNode, cbNodes, node.typeParameters) + || visitNodes(cbNode, cbNodes, node.parameters) + || visitNode(cbNode, node.type) + || visitNode(cbNode, node.body); }, - [SyntaxKind.GetAccessor]: function forEachChildInGetAccessor(node: GetAccessorDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNodes(cbNode, cbNodes, node.modifiers) || - visitNode(cbNode, node.name) || - visitNodes(cbNode, cbNodes, node.typeParameters) || - visitNodes(cbNode, cbNodes, node.parameters) || - visitNode(cbNode, node.type) || - visitNode(cbNode, node.body); + [SyntaxKind.GetAccessor]: function forEachChildInGetAccessor( + node: GetAccessorDeclaration, + cbNode: (node: Node) => T | undefined, + cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { + return visitNodes(cbNode, cbNodes, node.modifiers) + || visitNode(cbNode, node.name) + || visitNodes(cbNode, cbNodes, node.typeParameters) + || visitNodes(cbNode, cbNodes, node.parameters) + || visitNode(cbNode, node.type) + || visitNode(cbNode, node.body); }, - [SyntaxKind.SetAccessor]: function forEachChildInSetAccessor(node: SetAccessorDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNodes(cbNode, cbNodes, node.modifiers) || - visitNode(cbNode, node.name) || - visitNodes(cbNode, cbNodes, node.typeParameters) || - visitNodes(cbNode, cbNodes, node.parameters) || - visitNode(cbNode, node.type) || - visitNode(cbNode, node.body); + [SyntaxKind.SetAccessor]: function forEachChildInSetAccessor( + node: SetAccessorDeclaration, + cbNode: (node: Node) => T | undefined, + cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { + return visitNodes(cbNode, cbNodes, node.modifiers) + || visitNode(cbNode, node.name) + || visitNodes(cbNode, cbNodes, node.typeParameters) + || visitNodes(cbNode, cbNodes, node.parameters) + || visitNode(cbNode, node.type) + || visitNode(cbNode, node.body); }, - [SyntaxKind.FunctionDeclaration]: function forEachChildInFunctionDeclaration(node: FunctionDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNodes(cbNode, cbNodes, node.modifiers) || - visitNode(cbNode, node.asteriskToken) || - visitNode(cbNode, node.name) || - visitNodes(cbNode, cbNodes, node.typeParameters) || - visitNodes(cbNode, cbNodes, node.parameters) || - visitNode(cbNode, node.type) || - visitNode(cbNode, node.body); + [SyntaxKind.FunctionDeclaration]: function forEachChildInFunctionDeclaration( + node: FunctionDeclaration, + cbNode: (node: Node) => T | undefined, + cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { + return visitNodes(cbNode, cbNodes, node.modifiers) + || visitNode(cbNode, node.asteriskToken) + || visitNode(cbNode, node.name) + || visitNodes(cbNode, cbNodes, node.typeParameters) + || visitNodes(cbNode, cbNodes, node.parameters) + || visitNode(cbNode, node.type) + || visitNode(cbNode, node.body); }, - [SyntaxKind.FunctionExpression]: function forEachChildInFunctionExpression(node: FunctionExpression, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNodes(cbNode, cbNodes, node.modifiers) || - visitNode(cbNode, node.asteriskToken) || - visitNode(cbNode, node.name) || - visitNodes(cbNode, cbNodes, node.typeParameters) || - visitNodes(cbNode, cbNodes, node.parameters) || - visitNode(cbNode, node.type) || - visitNode(cbNode, node.body); + [SyntaxKind.FunctionExpression]: function forEachChildInFunctionExpression( + node: FunctionExpression, + cbNode: (node: Node) => T | undefined, + cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { + return visitNodes(cbNode, cbNodes, node.modifiers) + || visitNode(cbNode, node.asteriskToken) + || visitNode(cbNode, node.name) + || visitNodes(cbNode, cbNodes, node.typeParameters) + || visitNodes(cbNode, cbNodes, node.parameters) + || visitNode(cbNode, node.type) + || visitNode(cbNode, node.body); }, - [SyntaxKind.ArrowFunction]: function forEachChildInArrowFunction(node: ArrowFunction, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNodes(cbNode, cbNodes, node.modifiers) || - visitNodes(cbNode, cbNodes, node.typeParameters) || - visitNodes(cbNode, cbNodes, node.parameters) || - visitNode(cbNode, node.type) || - visitNode(cbNode, node.equalsGreaterThanToken) || - visitNode(cbNode, node.body); + [SyntaxKind.ArrowFunction]: function forEachChildInArrowFunction( + node: ArrowFunction, + cbNode: (node: Node) => T | undefined, + cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { + return visitNodes(cbNode, cbNodes, node.modifiers) + || visitNodes(cbNode, cbNodes, node.typeParameters) + || visitNodes(cbNode, cbNodes, node.parameters) + || visitNode(cbNode, node.type) + || visitNode(cbNode, node.equalsGreaterThanToken) + || visitNode(cbNode, node.body); }, - [SyntaxKind.ClassStaticBlockDeclaration]: function forEachChildInClassStaticBlockDeclaration(node: ClassStaticBlockDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNodes(cbNode, cbNodes, node.modifiers) || - visitNode(cbNode, node.body); + [SyntaxKind.ClassStaticBlockDeclaration]: function forEachChildInClassStaticBlockDeclaration( + node: ClassStaticBlockDeclaration, + cbNode: (node: Node) => T | undefined, + cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { + return visitNodes(cbNode, cbNodes, node.modifiers) + || visitNode(cbNode, node.body); }, - [SyntaxKind.TypeReference]: function forEachChildInTypeReference(node: TypeReferenceNode, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.typeName) || - visitNodes(cbNode, cbNodes, node.typeArguments); + [SyntaxKind.TypeReference]: function forEachChildInTypeReference( + node: TypeReferenceNode, + cbNode: (node: Node) => T | undefined, + cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { + return visitNode(cbNode, node.typeName) + || visitNodes(cbNode, cbNodes, node.typeArguments); }, - [SyntaxKind.TypePredicate]: function forEachChildInTypePredicate(node: TypePredicateNode, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.assertsModifier) || - visitNode(cbNode, node.parameterName) || - visitNode(cbNode, node.type); + [SyntaxKind.TypePredicate]: function forEachChildInTypePredicate( + node: TypePredicateNode, + cbNode: (node: Node) => T | undefined, + _cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { + return visitNode(cbNode, node.assertsModifier) + || visitNode(cbNode, node.parameterName) + || visitNode(cbNode, node.type); }, - [SyntaxKind.TypeQuery]: function forEachChildInTypeQuery(node: TypeQueryNode, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.exprName) || - visitNodes(cbNode, cbNodes, node.typeArguments); + [SyntaxKind.TypeQuery]: function forEachChildInTypeQuery( + node: TypeQueryNode, + cbNode: (node: Node) => T | undefined, + cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { + return visitNode(cbNode, node.exprName) + || visitNodes(cbNode, cbNodes, node.typeArguments); }, - [SyntaxKind.TypeLiteral]: function forEachChildInTypeLiteral(node: TypeLiteralNode, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + [SyntaxKind.TypeLiteral]: function forEachChildInTypeLiteral( + node: TypeLiteralNode, + cbNode: (node: Node) => T | undefined, + cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { return visitNodes(cbNode, cbNodes, node.members); }, - [SyntaxKind.ArrayType]: function forEachChildInArrayType(node: ArrayTypeNode, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + [SyntaxKind.ArrayType]: function forEachChildInArrayType( + node: ArrayTypeNode, + cbNode: (node: Node) => T | undefined, + _cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { return visitNode(cbNode, node.elementType); }, - [SyntaxKind.TupleType]: function forEachChildInTupleType(node: TupleTypeNode, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + [SyntaxKind.TupleType]: function forEachChildInTupleType( + node: TupleTypeNode, + cbNode: (node: Node) => T | undefined, + cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { return visitNodes(cbNode, cbNodes, node.elements); }, [SyntaxKind.UnionType]: forEachChildInUnionOrIntersectionType, [SyntaxKind.IntersectionType]: forEachChildInUnionOrIntersectionType, - [SyntaxKind.ConditionalType]: function forEachChildInConditionalType(node: ConditionalTypeNode, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.checkType) || - visitNode(cbNode, node.extendsType) || - visitNode(cbNode, node.trueType) || - visitNode(cbNode, node.falseType); + [SyntaxKind.ConditionalType]: function forEachChildInConditionalType( + node: ConditionalTypeNode, + cbNode: (node: Node) => T | undefined, + _cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { + return visitNode(cbNode, node.checkType) + || visitNode(cbNode, node.extendsType) + || visitNode(cbNode, node.trueType) + || visitNode(cbNode, node.falseType); }, - [SyntaxKind.InferType]: function forEachChildInInferType(node: InferTypeNode, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + [SyntaxKind.InferType]: function forEachChildInInferType( + node: InferTypeNode, + cbNode: (node: Node) => T | undefined, + _cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { return visitNode(cbNode, node.typeParameter); }, - [SyntaxKind.ImportType]: function forEachChildInImportType(node: ImportTypeNode, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.argument) || - visitNode(cbNode, node.assertions) || - visitNode(cbNode, node.qualifier) || - visitNodes(cbNode, cbNodes, node.typeArguments); + [SyntaxKind.ImportType]: function forEachChildInImportType( + node: ImportTypeNode, + cbNode: (node: Node) => T | undefined, + cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { + return visitNode(cbNode, node.argument) + || visitNode(cbNode, node.assertions) + || visitNode(cbNode, node.qualifier) + || visitNodes(cbNode, cbNodes, node.typeArguments); }, - [SyntaxKind.ImportTypeAssertionContainer]: function forEachChildInImportTypeAssertionContainer(node: ImportTypeAssertionContainer, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + [SyntaxKind.ImportTypeAssertionContainer]: function forEachChildInImportTypeAssertionContainer( + node: ImportTypeAssertionContainer, + cbNode: (node: Node) => T | undefined, + _cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { return visitNode(cbNode, node.assertClause); }, [SyntaxKind.ParenthesizedType]: forEachChildInParenthesizedTypeOrTypeOperator, [SyntaxKind.TypeOperator]: forEachChildInParenthesizedTypeOrTypeOperator, - [SyntaxKind.IndexedAccessType]: function forEachChildInIndexedAccessType(node: IndexedAccessTypeNode, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.objectType) || - visitNode(cbNode, node.indexType); + [SyntaxKind.IndexedAccessType]: function forEachChildInIndexedAccessType( + node: IndexedAccessTypeNode, + cbNode: (node: Node) => T | undefined, + _cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { + return visitNode(cbNode, node.objectType) + || visitNode(cbNode, node.indexType); }, - [SyntaxKind.MappedType]: function forEachChildInMappedType(node: MappedTypeNode, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.readonlyToken) || - visitNode(cbNode, node.typeParameter) || - visitNode(cbNode, node.nameType) || - visitNode(cbNode, node.questionToken) || - visitNode(cbNode, node.type) || - visitNodes(cbNode, cbNodes, node.members); + [SyntaxKind.MappedType]: function forEachChildInMappedType( + node: MappedTypeNode, + cbNode: (node: Node) => T | undefined, + cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { + return visitNode(cbNode, node.readonlyToken) + || visitNode(cbNode, node.typeParameter) + || visitNode(cbNode, node.nameType) + || visitNode(cbNode, node.questionToken) + || visitNode(cbNode, node.type) + || visitNodes(cbNode, cbNodes, node.members); }, - [SyntaxKind.LiteralType]: function forEachChildInLiteralType(node: LiteralTypeNode, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + [SyntaxKind.LiteralType]: function forEachChildInLiteralType( + node: LiteralTypeNode, + cbNode: (node: Node) => T | undefined, + _cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { return visitNode(cbNode, node.literal); }, - [SyntaxKind.NamedTupleMember]: function forEachChildInNamedTupleMember(node: NamedTupleMember, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.dotDotDotToken) || - visitNode(cbNode, node.name) || - visitNode(cbNode, node.questionToken) || - visitNode(cbNode, node.type); + [SyntaxKind.NamedTupleMember]: function forEachChildInNamedTupleMember( + node: NamedTupleMember, + cbNode: (node: Node) => T | undefined, + _cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { + return visitNode(cbNode, node.dotDotDotToken) + || visitNode(cbNode, node.name) + || visitNode(cbNode, node.questionToken) + || visitNode(cbNode, node.type); }, [SyntaxKind.ObjectBindingPattern]: forEachChildInObjectOrArrayBindingPattern, [SyntaxKind.ArrayBindingPattern]: forEachChildInObjectOrArrayBindingPattern, - [SyntaxKind.ArrayLiteralExpression]: function forEachChildInArrayLiteralExpression(node: ArrayLiteralExpression, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + [SyntaxKind.ArrayLiteralExpression]: function forEachChildInArrayLiteralExpression( + node: ArrayLiteralExpression, + cbNode: (node: Node) => T | undefined, + cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { return visitNodes(cbNode, cbNodes, node.elements); }, - [SyntaxKind.ObjectLiteralExpression]: function forEachChildInObjectLiteralExpression(node: ObjectLiteralExpression, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + [SyntaxKind.ObjectLiteralExpression]: function forEachChildInObjectLiteralExpression( + node: ObjectLiteralExpression, + cbNode: (node: Node) => T | undefined, + cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { return visitNodes(cbNode, cbNodes, node.properties); }, - [SyntaxKind.PropertyAccessExpression]: function forEachChildInPropertyAccessExpression(node: PropertyAccessExpression, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.expression) || - visitNode(cbNode, node.questionDotToken) || - visitNode(cbNode, node.name); + [SyntaxKind.PropertyAccessExpression]: function forEachChildInPropertyAccessExpression( + node: PropertyAccessExpression, + cbNode: (node: Node) => T | undefined, + _cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { + return visitNode(cbNode, node.expression) + || visitNode(cbNode, node.questionDotToken) + || visitNode(cbNode, node.name); }, - [SyntaxKind.ElementAccessExpression]: function forEachChildInElementAccessExpression(node: ElementAccessExpression, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.expression) || - visitNode(cbNode, node.questionDotToken) || - visitNode(cbNode, node.argumentExpression); + [SyntaxKind.ElementAccessExpression]: function forEachChildInElementAccessExpression( + node: ElementAccessExpression, + cbNode: (node: Node) => T | undefined, + _cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { + return visitNode(cbNode, node.expression) + || visitNode(cbNode, node.questionDotToken) + || visitNode(cbNode, node.argumentExpression); }, [SyntaxKind.CallExpression]: forEachChildInCallOrNewExpression, [SyntaxKind.NewExpression]: forEachChildInCallOrNewExpression, - [SyntaxKind.TaggedTemplateExpression]: function forEachChildInTaggedTemplateExpression(node: TaggedTemplateExpression, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.tag) || - visitNode(cbNode, node.questionDotToken) || - visitNodes(cbNode, cbNodes, node.typeArguments) || - visitNode(cbNode, node.template); + [SyntaxKind.TaggedTemplateExpression]: function forEachChildInTaggedTemplateExpression( + node: TaggedTemplateExpression, + cbNode: (node: Node) => T | undefined, + cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { + return visitNode(cbNode, node.tag) + || visitNode(cbNode, node.questionDotToken) + || visitNodes(cbNode, cbNodes, node.typeArguments) + || visitNode(cbNode, node.template); }, - [SyntaxKind.TypeAssertionExpression]: function forEachChildInTypeAssertionExpression(node: TypeAssertion, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.type) || - visitNode(cbNode, node.expression); + [SyntaxKind.TypeAssertionExpression]: function forEachChildInTypeAssertionExpression( + node: TypeAssertion, + cbNode: (node: Node) => T | undefined, + _cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { + return visitNode(cbNode, node.type) + || visitNode(cbNode, node.expression); }, - [SyntaxKind.ParenthesizedExpression]: function forEachChildInParenthesizedExpression(node: ParenthesizedExpression, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + [SyntaxKind.ParenthesizedExpression]: function forEachChildInParenthesizedExpression( + node: ParenthesizedExpression, + cbNode: (node: Node) => T | undefined, + _cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { return visitNode(cbNode, node.expression); }, - [SyntaxKind.DeleteExpression]: function forEachChildInDeleteExpression(node: DeleteExpression, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + [SyntaxKind.DeleteExpression]: function forEachChildInDeleteExpression( + node: DeleteExpression, + cbNode: (node: Node) => T | undefined, + _cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { return visitNode(cbNode, node.expression); }, - [SyntaxKind.TypeOfExpression]: function forEachChildInTypeOfExpression(node: TypeOfExpression, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + [SyntaxKind.TypeOfExpression]: function forEachChildInTypeOfExpression( + node: TypeOfExpression, + cbNode: (node: Node) => T | undefined, + _cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { return visitNode(cbNode, node.expression); }, - [SyntaxKind.VoidExpression]: function forEachChildInVoidExpression(node: VoidExpression, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + [SyntaxKind.VoidExpression]: function forEachChildInVoidExpression( + node: VoidExpression, + cbNode: (node: Node) => T | undefined, + _cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { return visitNode(cbNode, node.expression); }, - [SyntaxKind.PrefixUnaryExpression]: function forEachChildInPrefixUnaryExpression(node: PrefixUnaryExpression, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + [SyntaxKind.PrefixUnaryExpression]: function forEachChildInPrefixUnaryExpression( + node: PrefixUnaryExpression, + cbNode: (node: Node) => T | undefined, + _cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { return visitNode(cbNode, node.operand); }, - [SyntaxKind.YieldExpression]: function forEachChildInYieldExpression(node: YieldExpression, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.asteriskToken) || - visitNode(cbNode, node.expression); + [SyntaxKind.YieldExpression]: function forEachChildInYieldExpression( + node: YieldExpression, + cbNode: (node: Node) => T | undefined, + _cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { + return visitNode(cbNode, node.asteriskToken) + || visitNode(cbNode, node.expression); }, - [SyntaxKind.AwaitExpression]: function forEachChildInAwaitExpression(node: AwaitExpression, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + [SyntaxKind.AwaitExpression]: function forEachChildInAwaitExpression( + node: AwaitExpression, + cbNode: (node: Node) => T | undefined, + _cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { return visitNode(cbNode, node.expression); }, - [SyntaxKind.PostfixUnaryExpression]: function forEachChildInPostfixUnaryExpression(node: PostfixUnaryExpression, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + [SyntaxKind.PostfixUnaryExpression]: function forEachChildInPostfixUnaryExpression( + node: PostfixUnaryExpression, + cbNode: (node: Node) => T | undefined, + _cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { return visitNode(cbNode, node.operand); }, - [SyntaxKind.BinaryExpression]: function forEachChildInBinaryExpression(node: BinaryExpression, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.left) || - visitNode(cbNode, node.operatorToken) || - visitNode(cbNode, node.right); + [SyntaxKind.BinaryExpression]: function forEachChildInBinaryExpression( + node: BinaryExpression, + cbNode: (node: Node) => T | undefined, + _cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { + return visitNode(cbNode, node.left) + || visitNode(cbNode, node.operatorToken) + || visitNode(cbNode, node.right); }, - [SyntaxKind.AsExpression]: function forEachChildInAsExpression(node: AsExpression, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.expression) || - visitNode(cbNode, node.type); + [SyntaxKind.AsExpression]: function forEachChildInAsExpression( + node: AsExpression, + cbNode: (node: Node) => T | undefined, + _cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { + return visitNode(cbNode, node.expression) + || visitNode(cbNode, node.type); }, - [SyntaxKind.NonNullExpression]: function forEachChildInNonNullExpression(node: NonNullExpression, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + [SyntaxKind.NonNullExpression]: function forEachChildInNonNullExpression( + node: NonNullExpression, + cbNode: (node: Node) => T | undefined, + _cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { return visitNode(cbNode, node.expression); }, - [SyntaxKind.SatisfiesExpression]: function forEachChildInSatisfiesExpression(node: SatisfiesExpression, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + [SyntaxKind.SatisfiesExpression]: function forEachChildInSatisfiesExpression( + node: SatisfiesExpression, + cbNode: (node: Node) => T | undefined, + _cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { return visitNode(cbNode, node.expression) || visitNode(cbNode, node.type); }, - [SyntaxKind.MetaProperty]: function forEachChildInMetaProperty(node: MetaProperty, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + [SyntaxKind.MetaProperty]: function forEachChildInMetaProperty( + node: MetaProperty, + cbNode: (node: Node) => T | undefined, + _cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { return visitNode(cbNode, node.name); }, - [SyntaxKind.ConditionalExpression]: function forEachChildInConditionalExpression(node: ConditionalExpression, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.condition) || - visitNode(cbNode, node.questionToken) || - visitNode(cbNode, node.whenTrue) || - visitNode(cbNode, node.colonToken) || - visitNode(cbNode, node.whenFalse); + [SyntaxKind.ConditionalExpression]: function forEachChildInConditionalExpression( + node: ConditionalExpression, + cbNode: (node: Node) => T | undefined, + _cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { + return visitNode(cbNode, node.condition) + || visitNode(cbNode, node.questionToken) + || visitNode(cbNode, node.whenTrue) + || visitNode(cbNode, node.colonToken) + || visitNode(cbNode, node.whenFalse); }, - [SyntaxKind.SpreadElement]: function forEachChildInSpreadElement(node: SpreadElement, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + [SyntaxKind.SpreadElement]: function forEachChildInSpreadElement( + node: SpreadElement, + cbNode: (node: Node) => T | undefined, + _cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { return visitNode(cbNode, node.expression); }, [SyntaxKind.Block]: forEachChildInBlock, [SyntaxKind.ModuleBlock]: forEachChildInBlock, - [SyntaxKind.SourceFile]: function forEachChildInSourceFile(node: SourceFile, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNodes(cbNode, cbNodes, node.statements) || - visitNode(cbNode, node.endOfFileToken); + [SyntaxKind.SourceFile]: function forEachChildInSourceFile( + node: SourceFile, + cbNode: (node: Node) => T | undefined, + cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { + return visitNodes(cbNode, cbNodes, node.statements) + || visitNode(cbNode, node.endOfFileToken); }, - [SyntaxKind.VariableStatement]: function forEachChildInVariableStatement(node: VariableStatement, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNodes(cbNode, cbNodes, node.modifiers) || - visitNode(cbNode, node.declarationList); + [SyntaxKind.VariableStatement]: function forEachChildInVariableStatement( + node: VariableStatement, + cbNode: (node: Node) => T | undefined, + cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { + return visitNodes(cbNode, cbNodes, node.modifiers) + || visitNode(cbNode, node.declarationList); }, - [SyntaxKind.VariableDeclarationList]: function forEachChildInVariableDeclarationList(node: VariableDeclarationList, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + [SyntaxKind.VariableDeclarationList]: function forEachChildInVariableDeclarationList( + node: VariableDeclarationList, + cbNode: (node: Node) => T | undefined, + cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { return visitNodes(cbNode, cbNodes, node.declarations); }, - [SyntaxKind.ExpressionStatement]: function forEachChildInExpressionStatement(node: ExpressionStatement, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + [SyntaxKind.ExpressionStatement]: function forEachChildInExpressionStatement( + node: ExpressionStatement, + cbNode: (node: Node) => T | undefined, + _cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { return visitNode(cbNode, node.expression); }, - [SyntaxKind.IfStatement]: function forEachChildInIfStatement(node: IfStatement, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.expression) || - visitNode(cbNode, node.thenStatement) || - visitNode(cbNode, node.elseStatement); + [SyntaxKind.IfStatement]: function forEachChildInIfStatement( + node: IfStatement, + cbNode: (node: Node) => T | undefined, + _cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { + return visitNode(cbNode, node.expression) + || visitNode(cbNode, node.thenStatement) + || visitNode(cbNode, node.elseStatement); }, - [SyntaxKind.DoStatement]: function forEachChildInDoStatement(node: DoStatement, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.statement) || - visitNode(cbNode, node.expression); + [SyntaxKind.DoStatement]: function forEachChildInDoStatement( + node: DoStatement, + cbNode: (node: Node) => T | undefined, + _cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { + return visitNode(cbNode, node.statement) + || visitNode(cbNode, node.expression); }, - [SyntaxKind.WhileStatement]: function forEachChildInWhileStatement(node: WhileStatement, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.expression) || - visitNode(cbNode, node.statement); + [SyntaxKind.WhileStatement]: function forEachChildInWhileStatement( + node: WhileStatement, + cbNode: (node: Node) => T | undefined, + _cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { + return visitNode(cbNode, node.expression) + || visitNode(cbNode, node.statement); }, - [SyntaxKind.ForStatement]: function forEachChildInForStatement(node: ForStatement, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.initializer) || - visitNode(cbNode, node.condition) || - visitNode(cbNode, node.incrementor) || - visitNode(cbNode, node.statement); + [SyntaxKind.ForStatement]: function forEachChildInForStatement( + node: ForStatement, + cbNode: (node: Node) => T | undefined, + _cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { + return visitNode(cbNode, node.initializer) + || visitNode(cbNode, node.condition) + || visitNode(cbNode, node.incrementor) + || visitNode(cbNode, node.statement); }, - [SyntaxKind.ForInStatement]: function forEachChildInForInStatement(node: ForInStatement, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.initializer) || - visitNode(cbNode, node.expression) || - visitNode(cbNode, node.statement); + [SyntaxKind.ForInStatement]: function forEachChildInForInStatement( + node: ForInStatement, + cbNode: (node: Node) => T | undefined, + _cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { + return visitNode(cbNode, node.initializer) + || visitNode(cbNode, node.expression) + || visitNode(cbNode, node.statement); }, - [SyntaxKind.ForOfStatement]: function forEachChildInForOfStatement(node: ForOfStatement, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.awaitModifier) || - visitNode(cbNode, node.initializer) || - visitNode(cbNode, node.expression) || - visitNode(cbNode, node.statement); + [SyntaxKind.ForOfStatement]: function forEachChildInForOfStatement( + node: ForOfStatement, + cbNode: (node: Node) => T | undefined, + _cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { + return visitNode(cbNode, node.awaitModifier) + || visitNode(cbNode, node.initializer) + || visitNode(cbNode, node.expression) + || visitNode(cbNode, node.statement); }, [SyntaxKind.ContinueStatement]: forEachChildInContinueOrBreakStatement, [SyntaxKind.BreakStatement]: forEachChildInContinueOrBreakStatement, - [SyntaxKind.ReturnStatement]: function forEachChildInReturnStatement(node: ReturnStatement, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + [SyntaxKind.ReturnStatement]: function forEachChildInReturnStatement( + node: ReturnStatement, + cbNode: (node: Node) => T | undefined, + _cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { return visitNode(cbNode, node.expression); }, - [SyntaxKind.WithStatement]: function forEachChildInWithStatement(node: WithStatement, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.expression) || - visitNode(cbNode, node.statement); + [SyntaxKind.WithStatement]: function forEachChildInWithStatement( + node: WithStatement, + cbNode: (node: Node) => T | undefined, + _cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { + return visitNode(cbNode, node.expression) + || visitNode(cbNode, node.statement); }, - [SyntaxKind.SwitchStatement]: function forEachChildInSwitchStatement(node: SwitchStatement, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.expression) || - visitNode(cbNode, node.caseBlock); + [SyntaxKind.SwitchStatement]: function forEachChildInSwitchStatement( + node: SwitchStatement, + cbNode: (node: Node) => T | undefined, + _cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { + return visitNode(cbNode, node.expression) + || visitNode(cbNode, node.caseBlock); }, - [SyntaxKind.CaseBlock]: function forEachChildInCaseBlock(node: CaseBlock, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + [SyntaxKind.CaseBlock]: function forEachChildInCaseBlock( + node: CaseBlock, + cbNode: (node: Node) => T | undefined, + cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { return visitNodes(cbNode, cbNodes, node.clauses); }, - [SyntaxKind.CaseClause]: function forEachChildInCaseClause(node: CaseClause, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.expression) || - visitNodes(cbNode, cbNodes, node.statements); + [SyntaxKind.CaseClause]: function forEachChildInCaseClause( + node: CaseClause, + cbNode: (node: Node) => T | undefined, + cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { + return visitNode(cbNode, node.expression) + || visitNodes(cbNode, cbNodes, node.statements); }, - [SyntaxKind.DefaultClause]: function forEachChildInDefaultClause(node: DefaultClause, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + [SyntaxKind.DefaultClause]: function forEachChildInDefaultClause( + node: DefaultClause, + cbNode: (node: Node) => T | undefined, + cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { return visitNodes(cbNode, cbNodes, node.statements); }, - [SyntaxKind.LabeledStatement]: function forEachChildInLabeledStatement(node: LabeledStatement, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.label) || - visitNode(cbNode, node.statement); + [SyntaxKind.LabeledStatement]: function forEachChildInLabeledStatement( + node: LabeledStatement, + cbNode: (node: Node) => T | undefined, + _cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { + return visitNode(cbNode, node.label) + || visitNode(cbNode, node.statement); }, - [SyntaxKind.ThrowStatement]: function forEachChildInThrowStatement(node: ThrowStatement, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + [SyntaxKind.ThrowStatement]: function forEachChildInThrowStatement( + node: ThrowStatement, + cbNode: (node: Node) => T | undefined, + _cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { return visitNode(cbNode, node.expression); }, - [SyntaxKind.TryStatement]: function forEachChildInTryStatement(node: TryStatement, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.tryBlock) || - visitNode(cbNode, node.catchClause) || - visitNode(cbNode, node.finallyBlock); + [SyntaxKind.TryStatement]: function forEachChildInTryStatement( + node: TryStatement, + cbNode: (node: Node) => T | undefined, + _cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { + return visitNode(cbNode, node.tryBlock) + || visitNode(cbNode, node.catchClause) + || visitNode(cbNode, node.finallyBlock); }, - [SyntaxKind.CatchClause]: function forEachChildInCatchClause(node: CatchClause, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.variableDeclaration) || - visitNode(cbNode, node.block); + [SyntaxKind.CatchClause]: function forEachChildInCatchClause( + node: CatchClause, + cbNode: (node: Node) => T | undefined, + _cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { + return visitNode(cbNode, node.variableDeclaration) + || visitNode(cbNode, node.block); }, - [SyntaxKind.Decorator]: function forEachChildInDecorator(node: Decorator, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + [SyntaxKind.Decorator]: function forEachChildInDecorator( + node: Decorator, + cbNode: (node: Node) => T | undefined, + _cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { return visitNode(cbNode, node.expression); }, [SyntaxKind.ClassDeclaration]: forEachChildInClassDeclarationOrExpression, [SyntaxKind.ClassExpression]: forEachChildInClassDeclarationOrExpression, - [SyntaxKind.InterfaceDeclaration]: function forEachChildInInterfaceDeclaration(node: InterfaceDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNodes(cbNode, cbNodes, node.modifiers) || - visitNode(cbNode, node.name) || - visitNodes(cbNode, cbNodes, node.typeParameters) || - visitNodes(cbNode, cbNodes, node.heritageClauses) || - visitNodes(cbNode, cbNodes, node.members); + [SyntaxKind.InterfaceDeclaration]: function forEachChildInInterfaceDeclaration( + node: InterfaceDeclaration, + cbNode: (node: Node) => T | undefined, + cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { + return visitNodes(cbNode, cbNodes, node.modifiers) + || visitNode(cbNode, node.name) + || visitNodes(cbNode, cbNodes, node.typeParameters) + || visitNodes(cbNode, cbNodes, node.heritageClauses) + || visitNodes(cbNode, cbNodes, node.members); }, - [SyntaxKind.TypeAliasDeclaration]: function forEachChildInTypeAliasDeclaration(node: TypeAliasDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNodes(cbNode, cbNodes, node.modifiers) || - visitNode(cbNode, node.name) || - visitNodes(cbNode, cbNodes, node.typeParameters) || - visitNode(cbNode, node.type); + [SyntaxKind.TypeAliasDeclaration]: function forEachChildInTypeAliasDeclaration( + node: TypeAliasDeclaration, + cbNode: (node: Node) => T | undefined, + cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { + return visitNodes(cbNode, cbNodes, node.modifiers) + || visitNode(cbNode, node.name) + || visitNodes(cbNode, cbNodes, node.typeParameters) + || visitNode(cbNode, node.type); }, - [SyntaxKind.EnumDeclaration]: function forEachChildInEnumDeclaration(node: EnumDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNodes(cbNode, cbNodes, node.modifiers) || - visitNode(cbNode, node.name) || - visitNodes(cbNode, cbNodes, node.members); + [SyntaxKind.EnumDeclaration]: function forEachChildInEnumDeclaration( + node: EnumDeclaration, + cbNode: (node: Node) => T | undefined, + cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { + return visitNodes(cbNode, cbNodes, node.modifiers) + || visitNode(cbNode, node.name) + || visitNodes(cbNode, cbNodes, node.members); }, - [SyntaxKind.EnumMember]: function forEachChildInEnumMember(node: EnumMember, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.name) || - visitNode(cbNode, node.initializer); + [SyntaxKind.EnumMember]: function forEachChildInEnumMember( + node: EnumMember, + cbNode: (node: Node) => T | undefined, + _cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { + return visitNode(cbNode, node.name) + || visitNode(cbNode, node.initializer); }, - [SyntaxKind.ModuleDeclaration]: function forEachChildInModuleDeclaration(node: ModuleDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNodes(cbNode, cbNodes, node.modifiers) || - visitNode(cbNode, node.name) || - visitNode(cbNode, node.body); + [SyntaxKind.ModuleDeclaration]: function forEachChildInModuleDeclaration( + node: ModuleDeclaration, + cbNode: (node: Node) => T | undefined, + cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { + return visitNodes(cbNode, cbNodes, node.modifiers) + || visitNode(cbNode, node.name) + || visitNode(cbNode, node.body); }, - [SyntaxKind.ImportEqualsDeclaration]: function forEachChildInImportEqualsDeclaration(node: ImportEqualsDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNodes(cbNode, cbNodes, node.modifiers) || - visitNode(cbNode, node.name) || - visitNode(cbNode, node.moduleReference); + [SyntaxKind.ImportEqualsDeclaration]: function forEachChildInImportEqualsDeclaration( + node: ImportEqualsDeclaration, + cbNode: (node: Node) => T | undefined, + cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { + return visitNodes(cbNode, cbNodes, node.modifiers) + || visitNode(cbNode, node.name) + || visitNode(cbNode, node.moduleReference); }, - [SyntaxKind.ImportDeclaration]: function forEachChildInImportDeclaration(node: ImportDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNodes(cbNode, cbNodes, node.modifiers) || - visitNode(cbNode, node.importClause) || - visitNode(cbNode, node.moduleSpecifier) || - visitNode(cbNode, node.assertClause); + [SyntaxKind.ImportDeclaration]: function forEachChildInImportDeclaration( + node: ImportDeclaration, + cbNode: (node: Node) => T | undefined, + cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { + return visitNodes(cbNode, cbNodes, node.modifiers) + || visitNode(cbNode, node.importClause) + || visitNode(cbNode, node.moduleSpecifier) + || visitNode(cbNode, node.assertClause); }, - [SyntaxKind.ImportClause]: function forEachChildInImportClause(node: ImportClause, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.name) || - visitNode(cbNode, node.namedBindings); + [SyntaxKind.ImportClause]: function forEachChildInImportClause( + node: ImportClause, + cbNode: (node: Node) => T | undefined, + _cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { + return visitNode(cbNode, node.name) + || visitNode(cbNode, node.namedBindings); }, - [SyntaxKind.AssertClause]: function forEachChildInAssertClause(node: AssertClause, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + [SyntaxKind.AssertClause]: function forEachChildInAssertClause( + node: AssertClause, + cbNode: (node: Node) => T | undefined, + cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { return visitNodes(cbNode, cbNodes, node.elements); }, - [SyntaxKind.AssertEntry]: function forEachChildInAssertEntry(node: AssertEntry, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.name) || - visitNode(cbNode, node.value); + [SyntaxKind.AssertEntry]: function forEachChildInAssertEntry( + node: AssertEntry, + cbNode: (node: Node) => T | undefined, + _cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { + return visitNode(cbNode, node.name) + || visitNode(cbNode, node.value); }, - [SyntaxKind.NamespaceExportDeclaration]: function forEachChildInNamespaceExportDeclaration(node: NamespaceExportDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNodes(cbNode, cbNodes, node.modifiers) || - visitNode(cbNode, node.name); + [SyntaxKind.NamespaceExportDeclaration]: function forEachChildInNamespaceExportDeclaration( + node: NamespaceExportDeclaration, + cbNode: (node: Node) => T | undefined, + cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { + return visitNodes(cbNode, cbNodes, node.modifiers) + || visitNode(cbNode, node.name); }, - [SyntaxKind.NamespaceImport]: function forEachChildInNamespaceImport(node: NamespaceImport, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + [SyntaxKind.NamespaceImport]: function forEachChildInNamespaceImport( + node: NamespaceImport, + cbNode: (node: Node) => T | undefined, + _cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { return visitNode(cbNode, node.name); }, - [SyntaxKind.NamespaceExport]: function forEachChildInNamespaceExport(node: NamespaceExport, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + [SyntaxKind.NamespaceExport]: function forEachChildInNamespaceExport( + node: NamespaceExport, + cbNode: (node: Node) => T | undefined, + _cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { return visitNode(cbNode, node.name); }, [SyntaxKind.NamedImports]: forEachChildInNamedImportsOrExports, [SyntaxKind.NamedExports]: forEachChildInNamedImportsOrExports, - [SyntaxKind.ExportDeclaration]: function forEachChildInExportDeclaration(node: ExportDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNodes(cbNode, cbNodes, node.modifiers) || - visitNode(cbNode, node.exportClause) || - visitNode(cbNode, node.moduleSpecifier) || - visitNode(cbNode, node.assertClause); + [SyntaxKind.ExportDeclaration]: function forEachChildInExportDeclaration( + node: ExportDeclaration, + cbNode: (node: Node) => T | undefined, + cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { + return visitNodes(cbNode, cbNodes, node.modifiers) + || visitNode(cbNode, node.exportClause) + || visitNode(cbNode, node.moduleSpecifier) + || visitNode(cbNode, node.assertClause); }, [SyntaxKind.ImportSpecifier]: forEachChildInImportOrExportSpecifier, [SyntaxKind.ExportSpecifier]: forEachChildInImportOrExportSpecifier, - [SyntaxKind.ExportAssignment]: function forEachChildInExportAssignment(node: ExportAssignment, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNodes(cbNode, cbNodes, node.modifiers) || - visitNode(cbNode, node.expression); + [SyntaxKind.ExportAssignment]: function forEachChildInExportAssignment( + node: ExportAssignment, + cbNode: (node: Node) => T | undefined, + cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { + return visitNodes(cbNode, cbNodes, node.modifiers) + || visitNode(cbNode, node.expression); }, - [SyntaxKind.TemplateExpression]: function forEachChildInTemplateExpression(node: TemplateExpression, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.head) || - visitNodes(cbNode, cbNodes, node.templateSpans); + [SyntaxKind.TemplateExpression]: function forEachChildInTemplateExpression( + node: TemplateExpression, + cbNode: (node: Node) => T | undefined, + cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { + return visitNode(cbNode, node.head) + || visitNodes(cbNode, cbNodes, node.templateSpans); }, - [SyntaxKind.TemplateSpan]: function forEachChildInTemplateSpan(node: TemplateSpan, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.expression) || - visitNode(cbNode, node.literal); + [SyntaxKind.TemplateSpan]: function forEachChildInTemplateSpan( + node: TemplateSpan, + cbNode: (node: Node) => T | undefined, + _cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { + return visitNode(cbNode, node.expression) + || visitNode(cbNode, node.literal); }, - [SyntaxKind.TemplateLiteralType]: function forEachChildInTemplateLiteralType(node: TemplateLiteralTypeNode, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.head) || - visitNodes(cbNode, cbNodes, node.templateSpans); + [SyntaxKind.TemplateLiteralType]: function forEachChildInTemplateLiteralType( + node: TemplateLiteralTypeNode, + cbNode: (node: Node) => T | undefined, + cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { + return visitNode(cbNode, node.head) + || visitNodes(cbNode, cbNodes, node.templateSpans); }, - [SyntaxKind.TemplateLiteralTypeSpan]: function forEachChildInTemplateLiteralTypeSpan(node: TemplateLiteralTypeSpan, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.type) || - visitNode(cbNode, node.literal); + [SyntaxKind.TemplateLiteralTypeSpan]: function forEachChildInTemplateLiteralTypeSpan( + node: TemplateLiteralTypeSpan, + cbNode: (node: Node) => T | undefined, + _cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { + return visitNode(cbNode, node.type) + || visitNode(cbNode, node.literal); }, - [SyntaxKind.ComputedPropertyName]: function forEachChildInComputedPropertyName(node: ComputedPropertyName, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + [SyntaxKind.ComputedPropertyName]: function forEachChildInComputedPropertyName( + node: ComputedPropertyName, + cbNode: (node: Node) => T | undefined, + _cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { return visitNode(cbNode, node.expression); }, - [SyntaxKind.HeritageClause]: function forEachChildInHeritageClause(node: HeritageClause, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + [SyntaxKind.HeritageClause]: function forEachChildInHeritageClause( + node: HeritageClause, + cbNode: (node: Node) => T | undefined, + cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { return visitNodes(cbNode, cbNodes, node.types); }, - [SyntaxKind.ExpressionWithTypeArguments]: function forEachChildInExpressionWithTypeArguments(node: ExpressionWithTypeArguments, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.expression) || - visitNodes(cbNode, cbNodes, node.typeArguments); + [SyntaxKind.ExpressionWithTypeArguments]: function forEachChildInExpressionWithTypeArguments( + node: ExpressionWithTypeArguments, + cbNode: (node: Node) => T | undefined, + cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { + return visitNode(cbNode, node.expression) + || visitNodes(cbNode, cbNodes, node.typeArguments); }, - [SyntaxKind.ExternalModuleReference]: function forEachChildInExternalModuleReference(node: ExternalModuleReference, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + [SyntaxKind.ExternalModuleReference]: function forEachChildInExternalModuleReference( + node: ExternalModuleReference, + cbNode: (node: Node) => T | undefined, + _cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { return visitNode(cbNode, node.expression); }, - [SyntaxKind.MissingDeclaration]: function forEachChildInMissingDeclaration(node: MissingDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + [SyntaxKind.MissingDeclaration]: function forEachChildInMissingDeclaration( + node: MissingDeclaration, + cbNode: (node: Node) => T | undefined, + cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { return visitNodes(cbNode, cbNodes, node.modifiers); }, - [SyntaxKind.CommaListExpression]: function forEachChildInCommaListExpression(node: CommaListExpression, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + [SyntaxKind.CommaListExpression]: function forEachChildInCommaListExpression( + node: CommaListExpression, + cbNode: (node: Node) => T | undefined, + cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { return visitNodes(cbNode, cbNodes, node.elements); }, - [SyntaxKind.JsxElement]: function forEachChildInJsxElement(node: JsxElement, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.openingElement) || - visitNodes(cbNode, cbNodes, node.children) || - visitNode(cbNode, node.closingElement); + [SyntaxKind.JsxElement]: function forEachChildInJsxElement( + node: JsxElement, + cbNode: (node: Node) => T | undefined, + cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { + return visitNode(cbNode, node.openingElement) + || visitNodes(cbNode, cbNodes, node.children) + || visitNode(cbNode, node.closingElement); }, - [SyntaxKind.JsxFragment]: function forEachChildInJsxFragment(node: JsxFragment, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.openingFragment) || - visitNodes(cbNode, cbNodes, node.children) || - visitNode(cbNode, node.closingFragment); + [SyntaxKind.JsxFragment]: function forEachChildInJsxFragment( + node: JsxFragment, + cbNode: (node: Node) => T | undefined, + cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { + return visitNode(cbNode, node.openingFragment) + || visitNodes(cbNode, cbNodes, node.children) + || visitNode(cbNode, node.closingFragment); }, [SyntaxKind.JsxSelfClosingElement]: forEachChildInJsxOpeningOrSelfClosingElement, [SyntaxKind.JsxOpeningElement]: forEachChildInJsxOpeningOrSelfClosingElement, - [SyntaxKind.JsxAttributes]: function forEachChildInJsxAttributes(node: JsxAttributes, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + [SyntaxKind.JsxAttributes]: function forEachChildInJsxAttributes( + node: JsxAttributes, + cbNode: (node: Node) => T | undefined, + cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { return visitNodes(cbNode, cbNodes, node.properties); }, - [SyntaxKind.JsxAttribute]: function forEachChildInJsxAttribute(node: JsxAttribute, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.name) || - visitNode(cbNode, node.initializer); + [SyntaxKind.JsxAttribute]: function forEachChildInJsxAttribute( + node: JsxAttribute, + cbNode: (node: Node) => T | undefined, + _cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { + return visitNode(cbNode, node.name) + || visitNode(cbNode, node.initializer); }, - [SyntaxKind.JsxSpreadAttribute]: function forEachChildInJsxSpreadAttribute(node: JsxSpreadAttribute, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + [SyntaxKind.JsxSpreadAttribute]: function forEachChildInJsxSpreadAttribute( + node: JsxSpreadAttribute, + cbNode: (node: Node) => T | undefined, + _cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { return visitNode(cbNode, node.expression); }, - [SyntaxKind.JsxExpression]: function forEachChildInJsxExpression(node: JsxExpression, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.dotDotDotToken) || - visitNode(cbNode, node.expression); + [SyntaxKind.JsxExpression]: function forEachChildInJsxExpression( + node: JsxExpression, + cbNode: (node: Node) => T | undefined, + _cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { + return visitNode(cbNode, node.dotDotDotToken) + || visitNode(cbNode, node.expression); }, - [SyntaxKind.JsxClosingElement]: function forEachChildInJsxClosingElement(node: JsxClosingElement, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + [SyntaxKind.JsxClosingElement]: function forEachChildInJsxClosingElement( + node: JsxClosingElement, + cbNode: (node: Node) => T | undefined, + _cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { return visitNode(cbNode, node.tagName); }, - [SyntaxKind.JsxNamespacedName]: function forEachChildInJsxNamespacedName(node: JsxNamespacedName, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.namespace) || - visitNode(cbNode, node.name); + [SyntaxKind.JsxNamespacedName]: function forEachChildInJsxNamespacedName( + node: JsxNamespacedName, + cbNode: (node: Node) => T | undefined, + _cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { + return visitNode(cbNode, node.namespace) + || visitNode(cbNode, node.name); }, [SyntaxKind.OptionalType]: forEachChildInOptionalRestOrJSDocParameterModifier, [SyntaxKind.RestType]: forEachChildInOptionalRestOrJSDocParameterModifier, @@ -1042,64 +1511,108 @@ const forEachChildTable: ForEachChildTable = { [SyntaxKind.JSDocNullableType]: forEachChildInOptionalRestOrJSDocParameterModifier, [SyntaxKind.JSDocOptionalType]: forEachChildInOptionalRestOrJSDocParameterModifier, [SyntaxKind.JSDocVariadicType]: forEachChildInOptionalRestOrJSDocParameterModifier, - [SyntaxKind.JSDocFunctionType]: function forEachChildInJSDocFunctionType(node: JSDocFunctionType, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNodes(cbNode, cbNodes, node.parameters) || - visitNode(cbNode, node.type); + [SyntaxKind.JSDocFunctionType]: function forEachChildInJSDocFunctionType( + node: JSDocFunctionType, + cbNode: (node: Node) => T | undefined, + cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { + return visitNodes(cbNode, cbNodes, node.parameters) + || visitNode(cbNode, node.type); }, - [SyntaxKind.JSDoc]: function forEachChildInJSDoc(node: JSDoc, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + [SyntaxKind.JSDoc]: function forEachChildInJSDoc( + node: JSDoc, + cbNode: (node: Node) => T | undefined, + cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { return (typeof node.comment === "string" ? undefined : visitNodes(cbNode, cbNodes, node.comment)) || visitNodes(cbNode, cbNodes, node.tags); }, - [SyntaxKind.JSDocSeeTag]: function forEachChildInJSDocSeeTag(node: JSDocSeeTag, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.tagName) || - visitNode(cbNode, node.name) || - (typeof node.comment === "string" ? undefined : visitNodes(cbNode, cbNodes, node.comment)); + [SyntaxKind.JSDocSeeTag]: function forEachChildInJSDocSeeTag( + node: JSDocSeeTag, + cbNode: (node: Node) => T | undefined, + cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { + return visitNode(cbNode, node.tagName) + || visitNode(cbNode, node.name) + || (typeof node.comment === "string" ? undefined : visitNodes(cbNode, cbNodes, node.comment)); }, - [SyntaxKind.JSDocNameReference]: function forEachChildInJSDocNameReference(node: JSDocNameReference, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + [SyntaxKind.JSDocNameReference]: function forEachChildInJSDocNameReference( + node: JSDocNameReference, + cbNode: (node: Node) => T | undefined, + _cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { return visitNode(cbNode, node.name); }, - [SyntaxKind.JSDocMemberName]: function forEachChildInJSDocMemberName(node: JSDocMemberName, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.left) || - visitNode(cbNode, node.right); + [SyntaxKind.JSDocMemberName]: function forEachChildInJSDocMemberName( + node: JSDocMemberName, + cbNode: (node: Node) => T | undefined, + _cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { + return visitNode(cbNode, node.left) + || visitNode(cbNode, node.right); }, [SyntaxKind.JSDocParameterTag]: forEachChildInJSDocParameterOrPropertyTag, [SyntaxKind.JSDocPropertyTag]: forEachChildInJSDocParameterOrPropertyTag, - [SyntaxKind.JSDocAuthorTag]: function forEachChildInJSDocAuthorTag(node: JSDocAuthorTag, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.tagName) || - (typeof node.comment === "string" ? undefined : visitNodes(cbNode, cbNodes, node.comment)); + [SyntaxKind.JSDocAuthorTag]: function forEachChildInJSDocAuthorTag( + node: JSDocAuthorTag, + cbNode: (node: Node) => T | undefined, + cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { + return visitNode(cbNode, node.tagName) + || (typeof node.comment === "string" ? undefined : visitNodes(cbNode, cbNodes, node.comment)); }, - [SyntaxKind.JSDocImplementsTag]: function forEachChildInJSDocImplementsTag(node: JSDocImplementsTag, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.tagName) || - visitNode(cbNode, node.class) || - (typeof node.comment === "string" ? undefined : visitNodes(cbNode, cbNodes, node.comment)); + [SyntaxKind.JSDocImplementsTag]: function forEachChildInJSDocImplementsTag( + node: JSDocImplementsTag, + cbNode: (node: Node) => T | undefined, + cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { + return visitNode(cbNode, node.tagName) + || visitNode(cbNode, node.class) + || (typeof node.comment === "string" ? undefined : visitNodes(cbNode, cbNodes, node.comment)); }, - [SyntaxKind.JSDocAugmentsTag]: function forEachChildInJSDocAugmentsTag(node: JSDocAugmentsTag, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.tagName) || - visitNode(cbNode, node.class) || - (typeof node.comment === "string" ? undefined : visitNodes(cbNode, cbNodes, node.comment)); + [SyntaxKind.JSDocAugmentsTag]: function forEachChildInJSDocAugmentsTag( + node: JSDocAugmentsTag, + cbNode: (node: Node) => T | undefined, + cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { + return visitNode(cbNode, node.tagName) + || visitNode(cbNode, node.class) + || (typeof node.comment === "string" ? undefined : visitNodes(cbNode, cbNodes, node.comment)); }, - [SyntaxKind.JSDocTemplateTag]: function forEachChildInJSDocTemplateTag(node: JSDocTemplateTag, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.tagName) || - visitNode(cbNode, node.constraint) || - visitNodes(cbNode, cbNodes, node.typeParameters) || - (typeof node.comment === "string" ? undefined : visitNodes(cbNode, cbNodes, node.comment)); + [SyntaxKind.JSDocTemplateTag]: function forEachChildInJSDocTemplateTag( + node: JSDocTemplateTag, + cbNode: (node: Node) => T | undefined, + cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { + return visitNode(cbNode, node.tagName) + || visitNode(cbNode, node.constraint) + || visitNodes(cbNode, cbNodes, node.typeParameters) + || (typeof node.comment === "string" ? undefined : visitNodes(cbNode, cbNodes, node.comment)); }, - [SyntaxKind.JSDocTypedefTag]: function forEachChildInJSDocTypedefTag(node: JSDocTypedefTag, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.tagName) || - (node.typeExpression && - node.typeExpression.kind === SyntaxKind.JSDocTypeExpression - ? visitNode(cbNode, node.typeExpression) || - visitNode(cbNode, node.fullName) || - (typeof node.comment === "string" ? undefined : visitNodes(cbNode, cbNodes, node.comment)) - : visitNode(cbNode, node.fullName) || - visitNode(cbNode, node.typeExpression) || - (typeof node.comment === "string" ? undefined : visitNodes(cbNode, cbNodes, node.comment))); + [SyntaxKind.JSDocTypedefTag]: function forEachChildInJSDocTypedefTag( + node: JSDocTypedefTag, + cbNode: (node: Node) => T | undefined, + cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { + return visitNode(cbNode, node.tagName) + || (node.typeExpression + && node.typeExpression.kind === SyntaxKind.JSDocTypeExpression + ? visitNode(cbNode, node.typeExpression) + || visitNode(cbNode, node.fullName) + || (typeof node.comment === "string" ? undefined : visitNodes(cbNode, cbNodes, node.comment)) + : visitNode(cbNode, node.fullName) + || visitNode(cbNode, node.typeExpression) + || (typeof node.comment === "string" ? undefined : visitNodes(cbNode, cbNodes, node.comment))); }, - [SyntaxKind.JSDocCallbackTag]: function forEachChildInJSDocCallbackTag(node: JSDocCallbackTag, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.tagName) || - visitNode(cbNode, node.fullName) || - visitNode(cbNode, node.typeExpression) || - (typeof node.comment === "string" ? undefined : visitNodes(cbNode, cbNodes, node.comment)); + [SyntaxKind.JSDocCallbackTag]: function forEachChildInJSDocCallbackTag( + node: JSDocCallbackTag, + cbNode: (node: Node) => T | undefined, + cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { + return visitNode(cbNode, node.tagName) + || visitNode(cbNode, node.fullName) + || visitNode(cbNode, node.typeExpression) + || (typeof node.comment === "string" ? undefined : visitNodes(cbNode, cbNodes, node.comment)); }, [SyntaxKind.JSDocReturnTag]: forEachChildInJSDocTypeLikeTag, [SyntaxKind.JSDocTypeTag]: forEachChildInJSDocTypeLikeTag, @@ -1108,15 +1621,23 @@ const forEachChildTable: ForEachChildTable = { [SyntaxKind.JSDocSatisfiesTag]: forEachChildInJSDocTypeLikeTag, [SyntaxKind.JSDocThrowsTag]: forEachChildInJSDocTypeLikeTag, [SyntaxKind.JSDocOverloadTag]: forEachChildInJSDocTypeLikeTag, - [SyntaxKind.JSDocSignature]: function forEachChildInJSDocSignature(node: JSDocSignature, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return forEach(node.typeParameters, cbNode) || - forEach(node.parameters, cbNode) || - visitNode(cbNode, node.type); + [SyntaxKind.JSDocSignature]: function forEachChildInJSDocSignature( + node: JSDocSignature, + cbNode: (node: Node) => T | undefined, + _cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { + return forEach(node.typeParameters, cbNode) + || forEach(node.parameters, cbNode) + || visitNode(cbNode, node.type); }, [SyntaxKind.JSDocLink]: forEachChildInJSDocLinkCodeOrPlain, [SyntaxKind.JSDocLinkCode]: forEachChildInJSDocLinkCodeOrPlain, [SyntaxKind.JSDocLinkPlain]: forEachChildInJSDocLinkCodeOrPlain, - [SyntaxKind.JSDocTypeLiteral]: function forEachChildInJSDocTypeLiteral(node: JSDocTypeLiteral, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + [SyntaxKind.JSDocTypeLiteral]: function forEachChildInJSDocTypeLiteral( + node: JSDocTypeLiteral, + cbNode: (node: Node) => T | undefined, + _cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined { return forEach(node.jsDocPropertyTags, cbNode); }, [SyntaxKind.JSDocTag]: forEachChildInJSDocTag, @@ -1132,91 +1653,181 @@ const forEachChildTable: ForEachChildTable = { // shared -function forEachChildInCallOrConstructSignature(node: CallSignatureDeclaration | ConstructSignatureDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNodes(cbNode, cbNodes, node.typeParameters) || - visitNodes(cbNode, cbNodes, node.parameters) || - visitNode(cbNode, node.type); +function forEachChildInCallOrConstructSignature( + node: CallSignatureDeclaration | ConstructSignatureDeclaration, + cbNode: (node: Node) => T | undefined, + cbNodes?: (nodes: NodeArray) => T | undefined, +): T | undefined { + return visitNodes(cbNode, cbNodes, node.typeParameters) + || visitNodes(cbNode, cbNodes, node.parameters) + || visitNode(cbNode, node.type); } -function forEachChildInUnionOrIntersectionType(node: UnionTypeNode | IntersectionTypeNode, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { +function forEachChildInUnionOrIntersectionType( + node: UnionTypeNode | IntersectionTypeNode, + cbNode: (node: Node) => T | undefined, + cbNodes?: (nodes: NodeArray) => T | undefined, +): T | undefined { return visitNodes(cbNode, cbNodes, node.types); } -function forEachChildInParenthesizedTypeOrTypeOperator(node: ParenthesizedTypeNode | TypeOperatorNode, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { +function forEachChildInParenthesizedTypeOrTypeOperator( + node: ParenthesizedTypeNode | TypeOperatorNode, + cbNode: (node: Node) => T | undefined, + _cbNodes?: (nodes: NodeArray) => T | undefined, +): T | undefined { return visitNode(cbNode, node.type); } -function forEachChildInObjectOrArrayBindingPattern(node: BindingPattern, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { +function forEachChildInObjectOrArrayBindingPattern( + node: BindingPattern, + cbNode: (node: Node) => T | undefined, + cbNodes?: (nodes: NodeArray) => T | undefined, +): T | undefined { return visitNodes(cbNode, cbNodes, node.elements); } -function forEachChildInCallOrNewExpression(node: CallExpression | NewExpression, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.expression) || +function forEachChildInCallOrNewExpression( + node: CallExpression | NewExpression, + cbNode: (node: Node) => T | undefined, + cbNodes?: (nodes: NodeArray) => T | undefined, +): T | undefined { + return visitNode(cbNode, node.expression) // TODO: should we separate these branches out? - visitNode(cbNode, (node as CallExpression).questionDotToken) || - visitNodes(cbNode, cbNodes, node.typeArguments) || - visitNodes(cbNode, cbNodes, node.arguments); + || visitNode(cbNode, (node as CallExpression).questionDotToken) + || visitNodes(cbNode, cbNodes, node.typeArguments) + || visitNodes(cbNode, cbNodes, node.arguments); } -function forEachChildInBlock(node: Block | ModuleBlock, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { +function forEachChildInBlock( + node: Block | ModuleBlock, + cbNode: (node: Node) => T | undefined, + cbNodes?: (nodes: NodeArray) => T | undefined, +): T | undefined { return visitNodes(cbNode, cbNodes, node.statements); } -function forEachChildInContinueOrBreakStatement(node: ContinueStatement | BreakStatement, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { +function forEachChildInContinueOrBreakStatement( + node: ContinueStatement | BreakStatement, + cbNode: (node: Node) => T | undefined, + _cbNodes?: (nodes: NodeArray) => T | undefined, +): T | undefined { return visitNode(cbNode, node.label); } -function forEachChildInClassDeclarationOrExpression(node: ClassDeclaration | ClassExpression, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNodes(cbNode, cbNodes, node.modifiers) || - visitNode(cbNode, node.name) || - visitNodes(cbNode, cbNodes, node.typeParameters) || - visitNodes(cbNode, cbNodes, node.heritageClauses) || - visitNodes(cbNode, cbNodes, node.members); +function forEachChildInClassDeclarationOrExpression( + node: ClassDeclaration | ClassExpression, + cbNode: (node: Node) => T | undefined, + cbNodes?: (nodes: NodeArray) => T | undefined, +): T | undefined { + return visitNodes(cbNode, cbNodes, node.modifiers) + || visitNode(cbNode, node.name) + || visitNodes(cbNode, cbNodes, node.typeParameters) + || visitNodes(cbNode, cbNodes, node.heritageClauses) + || visitNodes(cbNode, cbNodes, node.members); } -function forEachChildInNamedImportsOrExports(node: NamedImports | NamedExports, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { +function forEachChildInNamedImportsOrExports( + node: NamedImports | NamedExports, + cbNode: (node: Node) => T | undefined, + cbNodes?: (nodes: NodeArray) => T | undefined, +): T | undefined { return visitNodes(cbNode, cbNodes, node.elements); } -function forEachChildInImportOrExportSpecifier(node: ImportSpecifier | ExportSpecifier, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.propertyName) || - visitNode(cbNode, node.name); +function forEachChildInImportOrExportSpecifier( + node: ImportSpecifier | ExportSpecifier, + cbNode: (node: Node) => T | undefined, + _cbNodes?: (nodes: NodeArray) => T | undefined, +): T | undefined { + return visitNode(cbNode, node.propertyName) + || visitNode(cbNode, node.name); } -function forEachChildInJsxOpeningOrSelfClosingElement(node: JsxOpeningLikeElement, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.tagName) || - visitNodes(cbNode, cbNodes, node.typeArguments) || - visitNode(cbNode, node.attributes); +function forEachChildInJsxOpeningOrSelfClosingElement( + node: JsxOpeningLikeElement, + cbNode: (node: Node) => T | undefined, + cbNodes?: (nodes: NodeArray) => T | undefined, +): T | undefined { + return visitNode(cbNode, node.tagName) + || visitNodes(cbNode, cbNodes, node.typeArguments) + || visitNode(cbNode, node.attributes); } -function forEachChildInOptionalRestOrJSDocParameterModifier(node: OptionalTypeNode | RestTypeNode | JSDocTypeExpression | JSDocNullableType | JSDocNonNullableType | JSDocOptionalType | JSDocVariadicType, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { +function forEachChildInOptionalRestOrJSDocParameterModifier( + node: + | OptionalTypeNode + | RestTypeNode + | JSDocTypeExpression + | JSDocNullableType + | JSDocNonNullableType + | JSDocOptionalType + | JSDocVariadicType, + cbNode: (node: Node) => T | undefined, + _cbNodes?: (nodes: NodeArray) => T | undefined, +): T | undefined { return visitNode(cbNode, node.type); } -function forEachChildInJSDocParameterOrPropertyTag(node: JSDocParameterTag | JSDocPropertyTag, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.tagName) || - (node.isNameFirst +function forEachChildInJSDocParameterOrPropertyTag( + node: JSDocParameterTag | JSDocPropertyTag, + cbNode: (node: Node) => T | undefined, + cbNodes?: (nodes: NodeArray) => T | undefined, +): T | undefined { + return visitNode(cbNode, node.tagName) + || (node.isNameFirst ? visitNode(cbNode, node.name) || visitNode(cbNode, node.typeExpression) - : visitNode(cbNode, node.typeExpression) || visitNode(cbNode, node.name)) || - (typeof node.comment === "string" ? undefined : visitNodes(cbNode, cbNodes, node.comment)); + : visitNode(cbNode, node.typeExpression) || visitNode(cbNode, node.name)) + || (typeof node.comment === "string" ? undefined : visitNodes(cbNode, cbNodes, node.comment)); } -function forEachChildInJSDocTypeLikeTag(node: JSDocReturnTag | JSDocTypeTag | JSDocThisTag | JSDocEnumTag | JSDocThrowsTag | JSDocOverloadTag | JSDocSatisfiesTag, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.tagName) || - visitNode(cbNode, node.typeExpression) || - (typeof node.comment === "string" ? undefined : visitNodes(cbNode, cbNodes, node.comment)); +function forEachChildInJSDocTypeLikeTag( + node: + | JSDocReturnTag + | JSDocTypeTag + | JSDocThisTag + | JSDocEnumTag + | JSDocThrowsTag + | JSDocOverloadTag + | JSDocSatisfiesTag, + cbNode: (node: Node) => T | undefined, + cbNodes?: (nodes: NodeArray) => T | undefined, +): T | undefined { + return visitNode(cbNode, node.tagName) + || visitNode(cbNode, node.typeExpression) + || (typeof node.comment === "string" ? undefined : visitNodes(cbNode, cbNodes, node.comment)); } -function forEachChildInJSDocLinkCodeOrPlain(node: JSDocLink | JSDocLinkCode | JSDocLinkPlain, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { +function forEachChildInJSDocLinkCodeOrPlain( + node: JSDocLink | JSDocLinkCode | JSDocLinkPlain, + cbNode: (node: Node) => T | undefined, + _cbNodes?: (nodes: NodeArray) => T | undefined, +): T | undefined { return visitNode(cbNode, node.name); } -function forEachChildInJSDocTag(node: JSDocUnknownTag | JSDocClassTag | JSDocPublicTag | JSDocPrivateTag | JSDocProtectedTag | JSDocReadonlyTag | JSDocDeprecatedTag | JSDocOverrideTag, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { +function forEachChildInJSDocTag( + node: + | JSDocUnknownTag + | JSDocClassTag + | JSDocPublicTag + | JSDocPrivateTag + | JSDocProtectedTag + | JSDocReadonlyTag + | JSDocDeprecatedTag + | JSDocOverrideTag, + cbNode: (node: Node) => T | undefined, + cbNodes?: (nodes: NodeArray) => T | undefined, +): T | undefined { return visitNode(cbNode, node.tagName) || (typeof node.comment === "string" ? undefined : visitNodes(cbNode, cbNodes, node.comment)); } -function forEachChildInPartiallyEmittedExpression(node: PartiallyEmittedExpression, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { +function forEachChildInPartiallyEmittedExpression( + node: PartiallyEmittedExpression, + cbNode: (node: Node) => T | undefined, + _cbNodes?: (nodes: NodeArray) => T | undefined, +): T | undefined { return visitNode(cbNode, node.expression); } @@ -1233,7 +1844,11 @@ function forEachChildInPartiallyEmittedExpression(node: PartiallyEmittedExpre * @remarks `forEachChild` must visit the children of a node in the order * that they appear in the source code. The language service depends on this property to locate nodes by position. */ -export function forEachChild(node: Node, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { +export function forEachChild( + node: Node, + cbNode: (node: Node) => T | undefined, + cbNodes?: (nodes: NodeArray) => T | undefined, +): T | undefined { if (node === undefined || node.kind <= SyntaxKind.LastToken) { return; } @@ -1256,7 +1871,11 @@ export function forEachChild(node: Node, cbNode: (node: Node) => T | undefine * * @internal */ -export function forEachChildRecursively(rootNode: Node, cbNode: (node: Node, parent: Node) => T | "skip" | undefined, cbNodes?: (nodes: NodeArray, parent: Node) => T | "skip" | undefined): T | undefined { +export function forEachChildRecursively( + rootNode: Node, + cbNode: (node: Node, parent: Node) => T | "skip" | undefined, + cbNodes?: (nodes: NodeArray, parent: Node) => T | "skip" | undefined, +): T | undefined { const queue: (Node | NodeArray)[] = gatherPossibleChildren(rootNode); const parents: Node[] = []; // tracks parent references for elements in queue while (parents.length < queue.length) { @@ -1327,7 +1946,13 @@ function setExternalModuleIndicator(sourceFile: SourceFile) { sourceFile.externalModuleIndicator = isFileProbablyExternalModule(sourceFile); } -export function createSourceFile(fileName: string, sourceText: string, languageVersionOrOptions: ScriptTarget | CreateSourceFileOptions, setParentNodes = false, scriptKind?: ScriptKind): SourceFile { +export function createSourceFile( + fileName: string, + sourceText: string, + languageVersionOrOptions: ScriptTarget | CreateSourceFileOptions, + setParentNodes = false, + scriptKind?: ScriptKind, +): SourceFile { tracing?.push(tracing.Phase.Parse, "createSourceFile", { path: fileName }, /*separateBeginAndEnd*/ true); performance.mark("beforeParse"); let result: SourceFile; @@ -1337,16 +1962,33 @@ export function createSourceFile(fileName: string, sourceText: string, languageV languageVersion, setExternalModuleIndicator: overrideSetExternalModuleIndicator, impliedNodeFormat: format, - } = typeof languageVersionOrOptions === "object" ? languageVersionOrOptions : ({ languageVersion: languageVersionOrOptions } as CreateSourceFileOptions); + } = typeof languageVersionOrOptions === "object" ? languageVersionOrOptions + : ({ languageVersion: languageVersionOrOptions } as CreateSourceFileOptions); if (languageVersion === ScriptTarget.JSON) { - result = Parser.parseSourceFile(fileName, sourceText, languageVersion, /*syntaxCursor*/ undefined, setParentNodes, ScriptKind.JSON, noop); + result = Parser.parseSourceFile( + fileName, + sourceText, + languageVersion, + /*syntaxCursor*/ undefined, + setParentNodes, + ScriptKind.JSON, + noop, + ); } else { const setIndicator = format === undefined ? overrideSetExternalModuleIndicator : (file: SourceFile) => { file.impliedNodeFormat = format; return (overrideSetExternalModuleIndicator || setExternalModuleIndicator)(file); }; - result = Parser.parseSourceFile(fileName, sourceText, languageVersion, /*syntaxCursor*/ undefined, setParentNodes, scriptKind, setIndicator); + result = Parser.parseSourceFile( + fileName, + sourceText, + languageVersion, + /*syntaxCursor*/ undefined, + setParentNodes, + scriptKind, + setIndicator, + ); } perfLogger?.logStopParseSourceFile(); @@ -1383,7 +2025,12 @@ export function isExternalModule(file: SourceFile): boolean { // from this SourceFile that are being held onto may change as a result (including // becoming detached from any SourceFile). It is recommended that this SourceFile not // be used once 'update' is called on it. -export function updateSourceFile(sourceFile: SourceFile, newText: string, textChangeRange: TextChangeRange, aggressiveChecks = false): SourceFile { +export function updateSourceFile( + sourceFile: SourceFile, + newText: string, + textChangeRange: TextChangeRange, + aggressiveChecks = false, +): SourceFile { const newSourceFile = IncrementalParser.updateSourceFile(sourceFile, newText, textChangeRange, aggressiveChecks); // Because new source file node is created, it may not have the flag PossiblyContainDynamicImport. This is the case if there is no new edit to add dynamic import. // We will manually port the flag to the new source file. @@ -1427,7 +2074,11 @@ namespace Parser { var NodeConstructor: new (kind: SyntaxKind, pos: number, end: number) => Node; var TokenConstructor: new (kind: SyntaxKind, pos: number, end: number) => Node; var IdentifierConstructor: new (kind: SyntaxKind.Identifier, pos: number, end: number) => Identifier; - var PrivateIdentifierConstructor: new (kind: SyntaxKind.PrivateIdentifier, pos: number, end: number) => PrivateIdentifier; + var PrivateIdentifierConstructor: new ( + kind: SyntaxKind.PrivateIdentifier, + pos: number, + end: number, + ) => PrivateIdentifier; var SourceFileConstructor: new (kind: SyntaxKind.SourceFile, pos: number, end: number) => SourceFile; function countNode(node: Node) { @@ -1440,12 +2091,16 @@ namespace Parser { var baseNodeFactory: BaseNodeFactory = { createBaseSourceFileNode: kind => countNode(new SourceFileConstructor(kind, /*pos*/ 0, /*end*/ 0)), createBaseIdentifierNode: kind => countNode(new IdentifierConstructor(kind, /*pos*/ 0, /*end*/ 0)), - createBasePrivateIdentifierNode: kind => countNode(new PrivateIdentifierConstructor(kind, /*pos*/ 0, /*end*/ 0)), + createBasePrivateIdentifierNode: kind => + countNode(new PrivateIdentifierConstructor(kind, /*pos*/ 0, /*end*/ 0)), createBaseTokenNode: kind => countNode(new TokenConstructor(kind, /*pos*/ 0, /*end*/ 0)), createBaseNode: kind => countNode(new NodeConstructor(kind, /*pos*/ 0, /*end*/ 0)), }; - var factory = createNodeFactory(NodeFactoryFlags.NoParenthesizerRules | NodeFactoryFlags.NoNodeConverters | NodeFactoryFlags.NoOriginalNode, baseNodeFactory); + var factory = createNodeFactory( + NodeFactoryFlags.NoParenthesizerRules | NodeFactoryFlags.NoNodeConverters | NodeFactoryFlags.NoOriginalNode, + baseNodeFactory, + ); var { createNodeArray: factoryCreateNodeArray, @@ -1578,11 +2233,25 @@ namespace Parser { var parseErrorBeforeNextFinishedNode = false; /* eslint-enable no-var */ - export function parseSourceFile(fileName: string, sourceText: string, languageVersion: ScriptTarget, syntaxCursor: IncrementalParser.SyntaxCursor | undefined, setParentNodes = false, scriptKind?: ScriptKind, setExternalModuleIndicatorOverride?: (file: SourceFile) => void): SourceFile { + export function parseSourceFile( + fileName: string, + sourceText: string, + languageVersion: ScriptTarget, + syntaxCursor: IncrementalParser.SyntaxCursor | undefined, + setParentNodes = false, + scriptKind?: ScriptKind, + setExternalModuleIndicatorOverride?: (file: SourceFile) => void, + ): SourceFile { scriptKind = ensureScriptKind(fileName, scriptKind); if (scriptKind === ScriptKind.JSON) { const result = parseJsonText(fileName, sourceText, languageVersion, syntaxCursor, setParentNodes); - convertToJson(result, result.statements[0]?.expression, result.parseDiagnostics, /*returnValue*/ false, /*jsonConversionNotifier*/ undefined); + convertToJson( + result, + result.statements[0]?.expression, + result.parseDiagnostics, + /*returnValue*/ false, + /*jsonConversionNotifier*/ undefined, + ); result.referencedFiles = emptyArray; result.typeReferenceDirectives = emptyArray; result.libReferenceDirectives = emptyArray; @@ -1594,7 +2263,12 @@ namespace Parser { initializeState(fileName, sourceText, languageVersion, syntaxCursor, scriptKind); - const result = parseSourceFileWorker(languageVersion, setParentNodes, scriptKind, setExternalModuleIndicatorOverride || setExternalModuleIndicator); + const result = parseSourceFileWorker( + languageVersion, + setParentNodes, + scriptKind, + setExternalModuleIndicatorOverride || setExternalModuleIndicator, + ); clearState(); @@ -1612,7 +2286,13 @@ namespace Parser { return isInvalid ? entityName : undefined; } - export function parseJsonText(fileName: string, sourceText: string, languageVersion: ScriptTarget = ScriptTarget.ES2015, syntaxCursor?: IncrementalParser.SyntaxCursor, setParentNodes = false): JsonSourceFile { + export function parseJsonText( + fileName: string, + sourceText: string, + languageVersion: ScriptTarget = ScriptTarget.ES2015, + syntaxCursor?: IncrementalParser.SyntaxCursor, + setParentNodes = false, + ): JsonSourceFile { initializeState(fileName, sourceText, languageVersion, syntaxCursor, ScriptKind.JSON); sourceFlags = contextFlags; @@ -1640,7 +2320,11 @@ namespace Parser { expression = parseTokenNode(); break; case SyntaxKind.MinusToken: - if (lookAhead(() => nextToken() === SyntaxKind.NumericLiteral && nextToken() !== SyntaxKind.ColonToken)) { + if ( + lookAhead(() => + nextToken() === SyntaxKind.NumericLiteral && nextToken() !== SyntaxKind.ColonToken + ) + ) { expression = parsePrefixUnaryExpression() as JsonMinusNumericLiteral; } else { @@ -1674,15 +2358,28 @@ namespace Parser { } } - const expression = isArray(expressions) ? finishNode(factoryCreateArrayLiteralExpression(expressions), pos) : Debug.checkDefined(expressions); + const expression = isArray(expressions) ? finishNode(factoryCreateArrayLiteralExpression(expressions), pos) + : Debug.checkDefined(expressions); const statement = factoryCreateExpressionStatement(expression) as JsonObjectExpressionStatement; finishNode(statement, pos); statements = createNodeArray([statement], pos); - endOfFileToken = parseExpectedToken(SyntaxKind.EndOfFileToken, Diagnostics.Unexpected_token) as EndOfFileToken; + endOfFileToken = parseExpectedToken( + SyntaxKind.EndOfFileToken, + Diagnostics.Unexpected_token, + ) as EndOfFileToken; } // Set source file so that errors will be reported with this file name - const sourceFile = createSourceFile(fileName, ScriptTarget.ES2015, ScriptKind.JSON, /*isDeclarationFile*/ false, statements, endOfFileToken, sourceFlags, noop); + const sourceFile = createSourceFile( + fileName, + ScriptTarget.ES2015, + ScriptKind.JSON, + /*isDeclarationFile*/ false, + statements, + endOfFileToken, + sourceFlags, + noop, + ); if (setParentNodes) { fixupParentReferences(sourceFile); @@ -1701,7 +2398,13 @@ namespace Parser { return result; } - function initializeState(_fileName: string, _sourceText: string, _languageVersion: ScriptTarget, _syntaxCursor: IncrementalParser.SyntaxCursor | undefined, _scriptKind: ScriptKind) { + function initializeState( + _fileName: string, + _sourceText: string, + _languageVersion: ScriptTarget, + _syntaxCursor: IncrementalParser.SyntaxCursor | undefined, + _scriptKind: ScriptKind, + ) { NodeConstructor = objectAllocator.getNodeConstructor(); TokenConstructor = objectAllocator.getTokenConstructor(); IdentifierConstructor = objectAllocator.getIdentifierConstructor(); @@ -1765,7 +2468,12 @@ namespace Parser { topLevel = true; } - function parseSourceFileWorker(languageVersion: ScriptTarget, setParentNodes: boolean, scriptKind: ScriptKind, setExternalModuleIndicator: (file: SourceFile) => void): SourceFile { + function parseSourceFileWorker( + languageVersion: ScriptTarget, + setParentNodes: boolean, + scriptKind: ScriptKind, + setExternalModuleIndicator: (file: SourceFile) => void, + ): SourceFile { const isDeclarationFile = isDeclarationFileName(fileName); if (isDeclarationFile) { contextFlags |= NodeFlags.Ambient; @@ -1781,7 +2489,16 @@ namespace Parser { const endHasJSDoc = hasPrecedingJSDocComment(); const endOfFileToken = withJSDoc(parseTokenNode(), endHasJSDoc); - const sourceFile = createSourceFile(fileName, languageVersion, scriptKind, isDeclarationFile, statements, endOfFileToken, sourceFlags, setExternalModuleIndicator); + const sourceFile = createSourceFile( + fileName, + languageVersion, + scriptKind, + isDeclarationFile, + statements, + endOfFileToken, + sourceFlags, + setExternalModuleIndicator, + ); // A member of ReadonlyArray isn't assignable to a member of T[] (and prevents a direct cast) - but this is where we set up those members so they can be readonly in the future processCommentPragmas(sourceFile as {} as PragmaContext, sourceText); @@ -1814,7 +2531,10 @@ namespace Parser { } Debug.assert(!node.jsDoc); // Should only be called once per node - const jsDoc = mapDefined(getJSDocCommentRanges(node, sourceText), comment => JSDocParser.parseJSDocComment(node, comment.pos, comment.end - comment.pos)); + const jsDoc = mapDefined( + getJSDocCommentRanges(node, sourceText), + comment => JSDocParser.parseJSDocComment(node, comment.pos, comment.end - comment.pos), + ); if (jsDoc.length) node.jsDoc = jsDoc; if (hasDeprecatedTag) { hasDeprecatedTag = false; @@ -1843,10 +2563,19 @@ namespace Parser { pos = findNextStatementWithoutAwait(sourceFile.statements, start); // append all diagnostics associated with the copied range - const diagnosticStart = findIndex(savedParseDiagnostics, diagnostic => diagnostic.start >= prevStatement.pos); - const diagnosticEnd = diagnosticStart >= 0 ? findIndex(savedParseDiagnostics, diagnostic => diagnostic.start >= nextStatement.pos, diagnosticStart) : -1; + const diagnosticStart = findIndex( + savedParseDiagnostics, + diagnostic => diagnostic.start >= prevStatement.pos, + ); + const diagnosticEnd = diagnosticStart >= 0 ? findIndex(savedParseDiagnostics, diagnostic => + diagnostic.start >= nextStatement.pos, diagnosticStart) : -1; if (diagnosticStart >= 0) { - addRange(parseDiagnostics, savedParseDiagnostics, diagnosticStart, diagnosticEnd >= 0 ? diagnosticEnd : undefined); + addRange( + parseDiagnostics, + savedParseDiagnostics, + diagnosticStart, + diagnosticEnd >= 0 ? diagnosticEnd : undefined, + ); } // reparse all statements between start and pos. We skip existing diagnostics for the same range and allow the parser to generate new ones. @@ -1890,14 +2619,20 @@ namespace Parser { addRange(statements, sourceFile.statements, pos); // append all diagnostics associated with the copied range - const diagnosticStart = findIndex(savedParseDiagnostics, diagnostic => diagnostic.start >= prevStatement.pos); + const diagnosticStart = findIndex( + savedParseDiagnostics, + diagnostic => diagnostic.start >= prevStatement.pos, + ); if (diagnosticStart >= 0) { addRange(parseDiagnostics, savedParseDiagnostics, diagnosticStart); } } syntaxCursor = savedSyntaxCursor; - return factory.updateSourceFile(sourceFile, setTextRange(factoryCreateNodeArray(statements), sourceFile.statements)); + return factory.updateSourceFile( + sourceFile, + setTextRange(factoryCreateNodeArray(statements), sourceFile.statements), + ); function containsPossibleTopLevelAwait(node: Node) { return !(node.flags & NodeFlags.AwaitContext) @@ -1956,7 +2691,10 @@ namespace Parser { setFields(sourceFile); // If we parsed this as an external module, it may contain top-level await - if (!isDeclarationFile && isExternalModule(sourceFile) && sourceFile.transformFlags & TransformFlags.ContainsPossibleTopLevelAwait) { + if ( + !isDeclarationFile && isExternalModule(sourceFile) + && sourceFile.transformFlags & TransformFlags.ContainsPossibleTopLevelAwait + ) { sourceFile = reparseTopLevelAwait(sourceFile); setFields(sourceFile); } @@ -2109,11 +2847,19 @@ namespace Parser { return inContext(NodeFlags.AwaitContext); } - function parseErrorAtCurrentToken(message: DiagnosticMessage, ...args: DiagnosticArguments): DiagnosticWithDetachedLocation | undefined { + function parseErrorAtCurrentToken( + message: DiagnosticMessage, + ...args: DiagnosticArguments + ): DiagnosticWithDetachedLocation | undefined { return parseErrorAt(scanner.getTokenStart(), scanner.getTokenEnd(), message, ...args); } - function parseErrorAtPosition(start: number, length: number, message: DiagnosticMessage, ...args: DiagnosticArguments): DiagnosticWithDetachedLocation | undefined { + function parseErrorAtPosition( + start: number, + length: number, + message: DiagnosticMessage, + ...args: DiagnosticArguments + ): DiagnosticWithDetachedLocation | undefined { // Don't report another error if it would just be at the same position as the last error. const lastError = lastOrUndefined(parseDiagnostics); let result: DiagnosticWithDetachedLocation | undefined; @@ -2128,7 +2874,12 @@ namespace Parser { return result; } - function parseErrorAt(start: number, end: number, message: DiagnosticMessage, ...args: DiagnosticArguments): DiagnosticWithDetachedLocation | undefined { + function parseErrorAt( + start: number, + end: number, + message: DiagnosticMessage, + ...args: DiagnosticArguments + ): DiagnosticWithDetachedLocation | undefined { return parseErrorAtPosition(start, end - start, message, ...args); } @@ -2171,7 +2922,11 @@ namespace Parser { // if the keyword had an escape if (isKeyword(currentToken) && (scanner.hasUnicodeEscape() || scanner.hasExtendedUnicodeEscape())) { // issue a parse error for the escape - parseErrorAt(scanner.getTokenStart(), scanner.getTokenEnd(), Diagnostics.Keywords_cannot_contain_escape_characters); + parseErrorAt( + scanner.getTokenStart(), + scanner.getTokenEnd(), + Diagnostics.Keywords_cannot_contain_escape_characters, + ); } return nextTokenWithoutCheck(); } @@ -2298,7 +3053,11 @@ namespace Parser { return token() > SyntaxKind.LastReservedWord; } - function parseExpected(kind: PunctuationOrKeywordSyntaxKind, diagnosticMessage?: DiagnosticMessage, shouldAdvance = true): boolean { + function parseExpected( + kind: PunctuationOrKeywordSyntaxKind, + diagnosticMessage?: DiagnosticMessage, + shouldAdvance = true, + ): boolean { if (token() === kind) { if (shouldAdvance) { nextToken(); @@ -2329,7 +3088,11 @@ namespace Parser { // module `M1` { // ^^^^^^^^^^^ This block is parsed as a template literal like module`M1`. if (isTaggedTemplateExpression(node)) { - parseErrorAt(skipTrivia(sourceText, node.template.pos), node.template.end, Diagnostics.Module_declaration_names_may_only_use_or_quoted_strings); + parseErrorAt( + skipTrivia(sourceText, node.template.pos), + node.template.end, + Diagnostics.Module_declaration_names_may_only_use_or_quoted_strings, + ); return; } @@ -2355,25 +3118,42 @@ namespace Parser { return; case "interface": - parseErrorForInvalidName(Diagnostics.Interface_name_cannot_be_0, Diagnostics.Interface_must_be_given_a_name, SyntaxKind.OpenBraceToken); + parseErrorForInvalidName( + Diagnostics.Interface_name_cannot_be_0, + Diagnostics.Interface_must_be_given_a_name, + SyntaxKind.OpenBraceToken, + ); return; case "is": - parseErrorAt(pos, scanner.getTokenStart(), Diagnostics.A_type_predicate_is_only_allowed_in_return_type_position_for_functions_and_methods); + parseErrorAt( + pos, + scanner.getTokenStart(), + Diagnostics.A_type_predicate_is_only_allowed_in_return_type_position_for_functions_and_methods, + ); return; case "module": case "namespace": - parseErrorForInvalidName(Diagnostics.Namespace_name_cannot_be_0, Diagnostics.Namespace_must_be_given_a_name, SyntaxKind.OpenBraceToken); + parseErrorForInvalidName( + Diagnostics.Namespace_name_cannot_be_0, + Diagnostics.Namespace_must_be_given_a_name, + SyntaxKind.OpenBraceToken, + ); return; case "type": - parseErrorForInvalidName(Diagnostics.Type_alias_name_cannot_be_0, Diagnostics.Type_alias_must_be_given_a_name, SyntaxKind.EqualsToken); + parseErrorForInvalidName( + Diagnostics.Type_alias_name_cannot_be_0, + Diagnostics.Type_alias_must_be_given_a_name, + SyntaxKind.EqualsToken, + ); return; } // The user alternatively might have misspelled or forgotten to add a space after a common keyword. - const suggestion = getSpellingSuggestion(expressionText, viableKeywordSuggestions, n => n) ?? getSpaceSuggestion(expressionText); + const suggestion = getSpellingSuggestion(expressionText, viableKeywordSuggestions, n => n) + ?? getSpaceSuggestion(expressionText); if (suggestion) { parseErrorAt(pos, node.end, Diagnostics.Unknown_keyword_or_identifier_Did_you_mean_0, suggestion); return; @@ -2395,7 +3175,11 @@ namespace Parser { * @param nameDiagnostic Diagnostic to report for all other cases. * @param tokenIfBlankName Current token if the name was invalid for being blank (not provided / skipped). */ - function parseErrorForInvalidName(nameDiagnostic: DiagnosticMessage, blankDiagnostic: DiagnosticMessage, tokenIfBlankName: SyntaxKind) { + function parseErrorForInvalidName( + nameDiagnostic: DiagnosticMessage, + blankDiagnostic: DiagnosticMessage, + tokenIfBlankName: SyntaxKind, + ) { if (token() === tokenIfBlankName) { parseErrorAtCurrentToken(blankDiagnostic); } @@ -2414,9 +3198,15 @@ namespace Parser { return undefined; } - function parseSemicolonAfterPropertyName(name: PropertyName, type: TypeNode | undefined, initializer: Expression | undefined) { + function parseSemicolonAfterPropertyName( + name: PropertyName, + type: TypeNode | undefined, + initializer: Expression | undefined, + ) { if (token() === SyntaxKind.AtToken && !scanner.hasPrecedingLineBreak()) { - parseErrorAtCurrentToken(Diagnostics.Decorators_must_precede_the_name_and_all_keywords_of_property_declarations); + parseErrorAtCurrentToken( + Diagnostics.Decorators_must_precede_the_name_and_all_keywords_of_property_declarations, + ); return; } @@ -2458,7 +3248,12 @@ namespace Parser { return false; } - function parseExpectedMatchingBrackets(openKind: PunctuationSyntaxKind, closeKind: PunctuationSyntaxKind, openParsed: boolean, openPosition: number) { + function parseExpectedMatchingBrackets( + openKind: PunctuationSyntaxKind, + closeKind: PunctuationSyntaxKind, + openParsed: boolean, + openPosition: number, + ) { if (token() === closeKind) { nextToken(); return; @@ -2470,7 +3265,14 @@ namespace Parser { if (lastError) { addRelatedInfo( lastError, - createDetachedDiagnostic(fileName, openPosition, 1, Diagnostics.The_parser_expected_to_find_a_1_to_match_the_0_token_here, tokenToString(openKind), tokenToString(closeKind)), + createDetachedDiagnostic( + fileName, + openPosition, + 1, + Diagnostics.The_parser_expected_to_find_a_1_to_match_the_0_token_here, + tokenToString(openKind), + tokenToString(closeKind), + ), ); } } @@ -2499,10 +3301,19 @@ namespace Parser { return undefined; } - function parseExpectedToken(t: TKind, diagnosticMessage?: DiagnosticMessage, arg0?: string): Token; + function parseExpectedToken( + t: TKind, + diagnosticMessage?: DiagnosticMessage, + arg0?: string, + ): Token; function parseExpectedToken(t: SyntaxKind, diagnosticMessage?: DiagnosticMessage, arg0?: string): Node { - return parseOptionalToken(t) || - createMissingNode(t, /*reportAtCurrentPosition*/ false, diagnosticMessage || Diagnostics._0_expected, arg0 || tokenToString(t)!); + return parseOptionalToken(t) + || createMissingNode( + t, + /*reportAtCurrentPosition*/ false, + diagnosticMessage || Diagnostics._0_expected, + arg0 || tokenToString(t)!, + ); } function parseExpectedTokenJSDoc(t: TKind): Token; @@ -2534,7 +3345,8 @@ namespace Parser { } // We can parse out an optional semicolon in ASI cases in the following cases. - return token() === SyntaxKind.CloseBraceToken || token() === SyntaxKind.EndOfFileToken || scanner.hasPrecedingLineBreak(); + return token() === SyntaxKind.CloseBraceToken || token() === SyntaxKind.EndOfFileToken + || scanner.hasPrecedingLineBreak(); } function tryParseSemicolon() { @@ -2554,7 +3366,12 @@ namespace Parser { return tryParseSemicolon() || parseExpected(SyntaxKind.SemicolonToken); } - function createNodeArray(elements: T[], pos: number, end?: number, hasTrailingComma?: boolean): NodeArray { + function createNodeArray( + elements: T[], + pos: number, + end?: number, + hasTrailingComma?: boolean, + ): NodeArray { const array = factoryCreateNodeArray(elements, hasTrailingComma); setTextRangePosEnd(array, pos, end ?? scanner.getTokenFullStart()); return array; @@ -2577,9 +3394,24 @@ namespace Parser { return node; } - function createMissingNode(kind: T["kind"], reportAtCurrentPosition: false, diagnosticMessage?: DiagnosticMessage, ...args: DiagnosticArguments): T; - function createMissingNode(kind: T["kind"], reportAtCurrentPosition: boolean, diagnosticMessage: DiagnosticMessage, ...args: DiagnosticArguments): T; - function createMissingNode(kind: T["kind"], reportAtCurrentPosition: boolean, diagnosticMessage?: DiagnosticMessage, ...args: DiagnosticArguments): T { + function createMissingNode( + kind: T["kind"], + reportAtCurrentPosition: false, + diagnosticMessage?: DiagnosticMessage, + ...args: DiagnosticArguments + ): T; + function createMissingNode( + kind: T["kind"], + reportAtCurrentPosition: boolean, + diagnosticMessage: DiagnosticMessage, + ...args: DiagnosticArguments + ): T; + function createMissingNode( + kind: T["kind"], + reportAtCurrentPosition: boolean, + diagnosticMessage?: DiagnosticMessage, + ...args: DiagnosticArguments + ): T { if (reportAtCurrentPosition) { parseErrorAtPosition(scanner.getTokenFullStart(), 0, diagnosticMessage!, ...args); } @@ -2588,12 +3420,13 @@ namespace Parser { } const pos = getNodePos(); - const result = kind === SyntaxKind.Identifier ? factoryCreateIdentifier("", /*originalKeywordKind*/ undefined) : - isTemplateLiteralKind(kind) ? factory.createTemplateLiteralLikeNode(kind, "", "", /*templateFlags*/ undefined) : - kind === SyntaxKind.NumericLiteral ? factoryCreateNumericLiteral("", /*numericLiteralFlags*/ undefined) : - kind === SyntaxKind.StringLiteral ? factoryCreateStringLiteral("", /*isSingleQuote*/ undefined) : - kind === SyntaxKind.MissingDeclaration ? factory.createMissingDeclaration() : - factoryCreateToken(kind); + const result = kind === SyntaxKind.Identifier ? factoryCreateIdentifier("", /*originalKeywordKind*/ undefined) + : isTemplateLiteralKind(kind) + ? factory.createTemplateLiteralLikeNode(kind, "", "", /*templateFlags*/ undefined) + : kind === SyntaxKind.NumericLiteral ? factoryCreateNumericLiteral("", /*numericLiteralFlags*/ undefined) + : kind === SyntaxKind.StringLiteral ? factoryCreateStringLiteral("", /*isSingleQuote*/ undefined) + : kind === SyntaxKind.MissingDeclaration ? factory.createMissingDeclaration() + : factoryCreateToken(kind); return finishNode(result, pos) as T; } @@ -2608,7 +3441,11 @@ namespace Parser { // An identifier that starts with two underscores has an extra underscore character prepended to it to avoid issues // with magic property names like '__proto__'. The 'identifiers' object is used to share a single string instance for // each identifier in order to reduce memory consumption. - function createIdentifier(isIdentifier: boolean, diagnosticMessage?: DiagnosticMessage, privateIdentifierDiagnosticMessage?: DiagnosticMessage): Identifier { + function createIdentifier( + isIdentifier: boolean, + diagnosticMessage?: DiagnosticMessage, + privateIdentifierDiagnosticMessage?: DiagnosticMessage, + ): Identifier { if (isIdentifier) { identifierCount++; const pos = getNodePos(); @@ -2621,11 +3458,17 @@ namespace Parser { } if (token() === SyntaxKind.PrivateIdentifier) { - parseErrorAtCurrentToken(privateIdentifierDiagnosticMessage || Diagnostics.Private_identifiers_are_not_allowed_outside_class_bodies); + parseErrorAtCurrentToken( + privateIdentifierDiagnosticMessage + || Diagnostics.Private_identifiers_are_not_allowed_outside_class_bodies, + ); return createIdentifier(/*isIdentifier*/ true); } - if (token() === SyntaxKind.Unknown && scanner.tryScan(() => scanner.reScanInvalidIdentifier() === SyntaxKind.Identifier)) { + if ( + token() === SyntaxKind.Unknown + && scanner.tryScan(() => scanner.reScanInvalidIdentifier() === SyntaxKind.Identifier) + ) { // Scanner has already recorded an 'Invalid character' error, so no need to add another from the parser. return createIdentifier(/*isIdentifier*/ true); } @@ -2637,18 +3480,30 @@ namespace Parser { const isReservedWord = scanner.isReservedWord(); const msgArg = scanner.getTokenText(); - const defaultMessage = isReservedWord ? - Diagnostics.Identifier_expected_0_is_a_reserved_word_that_cannot_be_used_here : - Diagnostics.Identifier_expected; + const defaultMessage = isReservedWord + ? Diagnostics.Identifier_expected_0_is_a_reserved_word_that_cannot_be_used_here + : Diagnostics.Identifier_expected; - return createMissingNode(SyntaxKind.Identifier, reportAtCurrentPosition, diagnosticMessage || defaultMessage, msgArg); + return createMissingNode( + SyntaxKind.Identifier, + reportAtCurrentPosition, + diagnosticMessage || defaultMessage, + msgArg, + ); } function parseBindingIdentifier(privateIdentifierDiagnosticMessage?: DiagnosticMessage) { - return createIdentifier(isBindingIdentifier(), /*diagnosticMessage*/ undefined, privateIdentifierDiagnosticMessage); + return createIdentifier( + isBindingIdentifier(), + /*diagnosticMessage*/ undefined, + privateIdentifierDiagnosticMessage, + ); } - function parseIdentifier(diagnosticMessage?: DiagnosticMessage, privateIdentifierDiagnosticMessage?: DiagnosticMessage): Identifier { + function parseIdentifier( + diagnosticMessage?: DiagnosticMessage, + privateIdentifierDiagnosticMessage?: DiagnosticMessage, + ): Identifier { return createIdentifier(isIdentifier(), diagnosticMessage, privateIdentifierDiagnosticMessage); } @@ -2664,14 +3519,14 @@ namespace Parser { } function isLiteralPropertyName(): boolean { - return tokenIsIdentifierOrKeyword(token()) || - token() === SyntaxKind.StringLiteral || - token() === SyntaxKind.NumericLiteral; + return tokenIsIdentifierOrKeyword(token()) + || token() === SyntaxKind.StringLiteral + || token() === SyntaxKind.NumericLiteral; } function isAssertionKey(): boolean { - return tokenIsIdentifierOrKeyword(token()) || - token() === SyntaxKind.StringLiteral; + return tokenIsIdentifierOrKeyword(token()) + || token() === SyntaxKind.StringLiteral; } function parsePropertyNameWorker(allowComputedPropertyNames: boolean): PropertyName { @@ -2832,7 +3687,8 @@ namespace Parser { case ParsingContext.RestProperties: return isLiteralPropertyName(); case ParsingContext.ObjectBindingElements: - return token() === SyntaxKind.OpenBracketToken || token() === SyntaxKind.DotDotDotToken || isLiteralPropertyName(); + return token() === SyntaxKind.OpenBracketToken || token() === SyntaxKind.DotDotDotToken + || isLiteralPropertyName(); case ParsingContext.AssertEntries: return isAssertionKey(); case ParsingContext.HeritageClauseElement: @@ -2854,7 +3710,8 @@ namespace Parser { case ParsingContext.VariableDeclarations: return isBindingIdentifierOrPrivateIdentifierOrPattern(); case ParsingContext.ArrayBindingElements: - return token() === SyntaxKind.CommaToken || token() === SyntaxKind.DotDotDotToken || isBindingIdentifierOrPrivateIdentifierOrPattern(); + return token() === SyntaxKind.CommaToken || token() === SyntaxKind.DotDotDotToken + || isBindingIdentifierOrPrivateIdentifierOrPattern(); case ParsingContext.TypeParameters: return token() === SyntaxKind.InKeyword || token() === SyntaxKind.ConstKeyword || isIdentifier(); case ParsingContext.ArrayLiteralMembers: @@ -2907,7 +3764,8 @@ namespace Parser { // extends {} implements const next = nextToken(); - return next === SyntaxKind.CommaToken || next === SyntaxKind.OpenBraceToken || next === SyntaxKind.ExtendsKeyword || next === SyntaxKind.ImplementsKeyword; + return next === SyntaxKind.CommaToken || next === SyntaxKind.OpenBraceToken + || next === SyntaxKind.ExtendsKeyword || next === SyntaxKind.ImplementsKeyword; } return true; @@ -2930,8 +3788,8 @@ namespace Parser { function isHeritageClauseExtendsOrImplementsKeyword(): boolean { if ( - token() === SyntaxKind.ImplementsKeyword || - token() === SyntaxKind.ExtendsKeyword + token() === SyntaxKind.ImplementsKeyword + || token() === SyntaxKind.ExtendsKeyword ) { return lookAhead(nextTokenIsStartOfExpression); } @@ -2968,14 +3826,18 @@ namespace Parser { case ParsingContext.AssertEntries: return token() === SyntaxKind.CloseBraceToken; case ParsingContext.SwitchClauseStatements: - return token() === SyntaxKind.CloseBraceToken || token() === SyntaxKind.CaseKeyword || token() === SyntaxKind.DefaultKeyword; + return token() === SyntaxKind.CloseBraceToken || token() === SyntaxKind.CaseKeyword + || token() === SyntaxKind.DefaultKeyword; case ParsingContext.HeritageClauseElement: - return token() === SyntaxKind.OpenBraceToken || token() === SyntaxKind.ExtendsKeyword || token() === SyntaxKind.ImplementsKeyword; + return token() === SyntaxKind.OpenBraceToken || token() === SyntaxKind.ExtendsKeyword + || token() === SyntaxKind.ImplementsKeyword; case ParsingContext.VariableDeclarations: return isVariableDeclaratorListTerminator(); case ParsingContext.TypeParameters: // Tokens other than '>' are here for better error recovery - return token() === SyntaxKind.GreaterThanToken || token() === SyntaxKind.OpenParenToken || token() === SyntaxKind.OpenBraceToken || token() === SyntaxKind.ExtendsKeyword || token() === SyntaxKind.ImplementsKeyword; + return token() === SyntaxKind.GreaterThanToken || token() === SyntaxKind.OpenParenToken + || token() === SyntaxKind.OpenBraceToken || token() === SyntaxKind.ExtendsKeyword + || token() === SyntaxKind.ImplementsKeyword; case ParsingContext.ArgumentExpressions: // Tokens other than ')' are here for better error recovery return token() === SyntaxKind.CloseParenToken || token() === SyntaxKind.SemicolonToken; @@ -2987,7 +3849,8 @@ namespace Parser { case ParsingContext.Parameters: case ParsingContext.RestProperties: // Tokens other than ')' and ']' (the latter for index signatures) are here for better error recovery - return token() === SyntaxKind.CloseParenToken || token() === SyntaxKind.CloseBracketToken /*|| token === SyntaxKind.OpenBraceToken*/; + return token() === SyntaxKind.CloseParenToken + || token() === SyntaxKind.CloseBracketToken /*|| token === SyntaxKind.OpenBraceToken*/; case ParsingContext.TypeArguments: // All other tokens should cause the type-argument to terminate except comma token return token() !== SyntaxKind.CommaToken; @@ -3246,8 +4109,8 @@ namespace Parser { // may have a method calls "constructor(...)" and we must reparse that // into an actual .ConstructorDeclaration. const methodDeclaration = node as MethodDeclaration; - const nameIsConstructor = methodDeclaration.name.kind === SyntaxKind.Identifier && - methodDeclaration.name.escapedText === "constructor"; + const nameIsConstructor = methodDeclaration.name.kind === SyntaxKind.Identifier + && methodDeclaration.name.escapedText === "constructor"; return !nameIsConstructor; } @@ -3386,14 +4249,19 @@ namespace Parser { case ParsingContext.TypeMembers: return parseErrorAtCurrentToken(Diagnostics.Property_or_signature_expected); case ParsingContext.ClassMembers: - return parseErrorAtCurrentToken(Diagnostics.Unexpected_token_A_constructor_method_accessor_or_property_was_expected); + return parseErrorAtCurrentToken( + Diagnostics.Unexpected_token_A_constructor_method_accessor_or_property_was_expected, + ); case ParsingContext.EnumMembers: return parseErrorAtCurrentToken(Diagnostics.Enum_member_expected); case ParsingContext.HeritageClauseElement: return parseErrorAtCurrentToken(Diagnostics.Expression_expected); case ParsingContext.VariableDeclarations: return isKeyword(token()) - ? parseErrorAtCurrentToken(Diagnostics._0_is_not_allowed_as_a_variable_declaration_name, tokenToString(token())!) + ? parseErrorAtCurrentToken( + Diagnostics._0_is_not_allowed_as_a_variable_declaration_name, + tokenToString(token())!, + ) : parseErrorAtCurrentToken(Diagnostics.Variable_declaration_expected); case ParsingContext.ObjectBindingElements: return parseErrorAtCurrentToken(Diagnostics.Property_destructuring_pattern_expected); @@ -3409,7 +4277,10 @@ namespace Parser { return parseErrorAtCurrentToken(Diagnostics.Parameter_declaration_expected); case ParsingContext.Parameters: return isKeyword(token()) - ? parseErrorAtCurrentToken(Diagnostics._0_is_not_allowed_as_a_parameter_name, tokenToString(token())!) + ? parseErrorAtCurrentToken( + Diagnostics._0_is_not_allowed_as_a_parameter_name, + tokenToString(token())!, + ) : parseErrorAtCurrentToken(Diagnostics.Parameter_declaration_expected); case ParsingContext.TypeParameters: return parseErrorAtCurrentToken(Diagnostics.Type_parameter_declaration_expected); @@ -3440,9 +4311,21 @@ namespace Parser { } // Parses a comma-delimited list of elements - function parseDelimitedList(kind: ParsingContext, parseElement: () => T, considerSemicolonAsDelimiter?: boolean): NodeArray; - function parseDelimitedList(kind: ParsingContext, parseElement: () => T, considerSemicolonAsDelimiter?: boolean): NodeArray> | undefined; - function parseDelimitedList(kind: ParsingContext, parseElement: () => T, considerSemicolonAsDelimiter?: boolean): NodeArray> | undefined { + function parseDelimitedList( + kind: ParsingContext, + parseElement: () => T, + considerSemicolonAsDelimiter?: boolean, + ): NodeArray; + function parseDelimitedList( + kind: ParsingContext, + parseElement: () => T, + considerSemicolonAsDelimiter?: boolean, + ): NodeArray> | undefined; + function parseDelimitedList( + kind: ParsingContext, + parseElement: () => T, + considerSemicolonAsDelimiter?: boolean, + ): NodeArray> | undefined { const saveParsingContext = parsingContext; parsingContext |= 1 << kind; const list: NonNullable[] = []; @@ -3479,7 +4362,10 @@ namespace Parser { // parse errors. For example, this can happen when people do things like use // a semicolon to delimit object literal members. Note: we'll have already // reported an error when we called parseExpected above. - if (considerSemicolonAsDelimiter && token() === SyntaxKind.SemicolonToken && !scanner.hasPrecedingLineBreak()) { + if ( + considerSemicolonAsDelimiter && token() === SyntaxKind.SemicolonToken + && !scanner.hasPrecedingLineBreak() + ) { nextToken(); } if (startPos === scanner.getTokenFullStart()) { @@ -3512,7 +4398,8 @@ namespace Parser { } function getExpectedCommaDiagnostic(kind: ParsingContext) { - return kind === ParsingContext.EnumMembers ? Diagnostics.An_enum_member_name_must_be_followed_by_a_or : undefined; + return kind === ParsingContext.EnumMembers ? Diagnostics.An_enum_member_name_must_be_followed_by_a_or + : undefined; } interface MissingList extends NodeArray { @@ -3529,7 +4416,12 @@ namespace Parser { return !!(arr as MissingList).isMissingList; } - function parseBracketedList(kind: ParsingContext, parseElement: () => T, open: PunctuationSyntaxKind, close: PunctuationSyntaxKind): NodeArray { + function parseBracketedList( + kind: ParsingContext, + parseElement: () => T, + open: PunctuationSyntaxKind, + close: PunctuationSyntaxKind, + ): NodeArray { if (parseExpected(open)) { const result = parseDelimitedList(kind, parseElement); parseExpected(close); @@ -3541,7 +4433,8 @@ namespace Parser { function parseEntityName(allowReservedWords: boolean, diagnosticMessage?: DiagnosticMessage): EntityName { const pos = getNodePos(); - let entity: EntityName = allowReservedWords ? parseIdentifierName(diagnosticMessage) : parseIdentifier(diagnosticMessage); + let entity: EntityName = allowReservedWords ? parseIdentifierName(diagnosticMessage) + : parseIdentifier(diagnosticMessage); while (parseOptional(SyntaxKind.DotToken)) { if (token() === SyntaxKind.LessThanToken) { // The entity is part of a JSDoc-style generic. We will use the gap between `typeName` and @@ -3551,7 +4444,11 @@ namespace Parser { entity = finishNode( factory.createQualifiedName( entity, - parseRightSideOfDot(allowReservedWords, /*allowPrivateIdentifiers*/ false, /*allowUnicodeEscapeSequenceInIdentifierName*/ true) as Identifier, + parseRightSideOfDot( + allowReservedWords, + /*allowPrivateIdentifiers*/ false, + /*allowUnicodeEscapeSequenceInIdentifierName*/ true, + ) as Identifier, ), pos, ); @@ -3563,7 +4460,11 @@ namespace Parser { return finishNode(factory.createQualifiedName(entity, name), entity.pos); } - function parseRightSideOfDot(allowIdentifierNames: boolean, allowPrivateIdentifiers: boolean, allowUnicodeEscapeSequenceInIdentifierName: boolean): Identifier | PrivateIdentifier { + function parseRightSideOfDot( + allowIdentifierNames: boolean, + allowPrivateIdentifiers: boolean, + allowUnicodeEscapeSequenceInIdentifierName: boolean, + ): Identifier | PrivateIdentifier { // Technically a keyword is valid here as all identifiers and keywords are identifier names. // However, often we'll encounter this in error situations when the identifier or keyword // is actually starting another valid construct. @@ -3590,17 +4491,27 @@ namespace Parser { // Report that we need an identifier. However, report it right after the dot, // and not on the next token. This is because the next token might actually // be an identifier and the error would be quite confusing. - return createMissingNode(SyntaxKind.Identifier, /*reportAtCurrentPosition*/ true, Diagnostics.Identifier_expected); + return createMissingNode( + SyntaxKind.Identifier, + /*reportAtCurrentPosition*/ true, + Diagnostics.Identifier_expected, + ); } } if (token() === SyntaxKind.PrivateIdentifier) { const node = parsePrivateIdentifier(); - return allowPrivateIdentifiers ? node : createMissingNode(SyntaxKind.Identifier, /*reportAtCurrentPosition*/ true, Diagnostics.Identifier_expected); + return allowPrivateIdentifiers ? node + : createMissingNode( + SyntaxKind.Identifier, + /*reportAtCurrentPosition*/ true, + Diagnostics.Identifier_expected, + ); } if (allowIdentifierNames) { - return allowUnicodeEscapeSequenceInIdentifierName ? parseIdentifierName() : parseIdentifierNameErrorOnUnicodeEscapeSequence(); + return allowUnicodeEscapeSequenceInIdentifierName ? parseIdentifierName() + : parseIdentifierNameErrorOnUnicodeEscapeSequence(); } return parseIdentifier(); @@ -3670,7 +4581,11 @@ namespace Parser { } else { // TODO(rbuckton): Do we need to call `parseExpectedToken` or can we just call `createMissingNode` directly? - return parseExpectedToken(SyntaxKind.TemplateTail, Diagnostics._0_expected, tokenToString(SyntaxKind.CloseBraceToken)) as TemplateTail; + return parseExpectedToken( + SyntaxKind.TemplateTail, + Diagnostics._0_expected, + tokenToString(SyntaxKind.CloseBraceToken), + ) as TemplateTail; } } @@ -3700,7 +4615,10 @@ namespace Parser { function parseTemplateMiddleOrTemplateTail(): TemplateMiddle | TemplateTail { const fragment = parseLiteralLikeNode(token()); - Debug.assert(fragment.kind === SyntaxKind.TemplateMiddle || fragment.kind === SyntaxKind.TemplateTail, "Template fragment has wrong token kind"); + Debug.assert( + fragment.kind === SyntaxKind.TemplateMiddle || fragment.kind === SyntaxKind.TemplateTail, + "Template fragment has wrong token kind", + ); return fragment as TemplateMiddle | TemplateTail; } @@ -3712,16 +4630,28 @@ namespace Parser { function parseLiteralLikeNode(kind: SyntaxKind): LiteralLikeNode { const pos = getNodePos(); - const node = isTemplateLiteralKind(kind) ? factory.createTemplateLiteralLikeNode(kind, scanner.getTokenValue(), getTemplateLiteralRawText(kind), scanner.getTokenFlags() & TokenFlags.TemplateLiteralLikeFlags) : + const node = isTemplateLiteralKind(kind) + ? factory.createTemplateLiteralLikeNode( + kind, + scanner.getTokenValue(), + getTemplateLiteralRawText(kind), + scanner.getTokenFlags() & TokenFlags.TemplateLiteralLikeFlags, + ) // Note that theoretically the following condition would hold true literals like 009, // which is not octal. But because of how the scanner separates the tokens, we would // never get a token like this. Instead, we would get 00 and 9 as two separate tokens. // We also do not need to check for negatives because any prefix operator would be part of a // parent unary expression. - kind === SyntaxKind.NumericLiteral ? factoryCreateNumericLiteral(scanner.getTokenValue(), scanner.getNumericLiteralFlags()) : - kind === SyntaxKind.StringLiteral ? factoryCreateStringLiteral(scanner.getTokenValue(), /*isSingleQuote*/ undefined, scanner.hasExtendedUnicodeEscape()) : - isLiteralKind(kind) ? factoryCreateLiteralLikeNode(kind, scanner.getTokenValue()) : - Debug.fail(); + : kind === SyntaxKind.NumericLiteral + ? factoryCreateNumericLiteral(scanner.getTokenValue(), scanner.getNumericLiteralFlags()) + : kind === SyntaxKind.StringLiteral + ? factoryCreateStringLiteral( + scanner.getTokenValue(), + /*isSingleQuote*/ undefined, + scanner.hasExtendedUnicodeEscape(), + ) + : isLiteralKind(kind) ? factoryCreateLiteralLikeNode(kind, scanner.getTokenValue()) + : Debug.fail(); if (scanner.hasExtendedUnicodeEscape()) { node.hasExtendedUnicodeEscape = true; @@ -3743,7 +4673,12 @@ namespace Parser { function parseTypeArgumentsOfTypeReference() { if (!scanner.hasPrecedingLineBreak() && reScanLessThanToken() === SyntaxKind.LessThanToken) { - return parseBracketedList(ParsingContext.TypeArguments, parseType, SyntaxKind.LessThanToken, SyntaxKind.GreaterThanToken); + return parseBracketedList( + ParsingContext.TypeArguments, + parseType, + SyntaxKind.LessThanToken, + SyntaxKind.GreaterThanToken, + ); } } @@ -3814,12 +4749,12 @@ namespace Parser { // Foo(?= // (?| if ( - token() === SyntaxKind.CommaToken || - token() === SyntaxKind.CloseBraceToken || - token() === SyntaxKind.CloseParenToken || - token() === SyntaxKind.GreaterThanToken || - token() === SyntaxKind.EqualsToken || - token() === SyntaxKind.BarToken + token() === SyntaxKind.CommaToken + || token() === SyntaxKind.CloseBraceToken + || token() === SyntaxKind.CloseParenToken + || token() === SyntaxKind.GreaterThanToken + || token() === SyntaxKind.EqualsToken + || token() === SyntaxKind.BarToken ) { return finishNode(factory.createJSDocUnknownType(), pos); } @@ -3940,16 +4875,21 @@ namespace Parser { function parseTypeParameters(): NodeArray | undefined { if (token() === SyntaxKind.LessThanToken) { - return parseBracketedList(ParsingContext.TypeParameters, parseTypeParameter, SyntaxKind.LessThanToken, SyntaxKind.GreaterThanToken); + return parseBracketedList( + ParsingContext.TypeParameters, + parseTypeParameter, + SyntaxKind.LessThanToken, + SyntaxKind.GreaterThanToken, + ); } } function isStartOfParameter(isJSDocParameter: boolean): boolean { - return token() === SyntaxKind.DotDotDotToken || - isBindingIdentifierOrPrivateIdentifierOrPattern() || - isModifierKind(token()) || - token() === SyntaxKind.AtToken || - isStartOfType(/*inStartOfParameter*/ !isJSDocParameter); + return token() === SyntaxKind.DotDotDotToken + || isBindingIdentifierOrPrivateIdentifierOrPattern() + || isModifierKind(token()) + || token() === SyntaxKind.AtToken + || isStartOfType(/*inStartOfParameter*/ !isJSDocParameter); } function parseNameOfParameter(modifiers: NodeArray | undefined) { @@ -3974,7 +4914,8 @@ namespace Parser { // Be permissive about await and yield by calling isBindingIdentifier instead of isIdentifier; disallowing // them during a speculative parse leads to many more follow-on errors than allowing the function to parse then later // complaining about the use of the keywords. - return isBindingIdentifier() || token() === SyntaxKind.OpenBracketToken || token() === SyntaxKind.OpenBraceToken; + return isBindingIdentifier() || token() === SyntaxKind.OpenBracketToken + || token() === SyntaxKind.OpenBraceToken; } function parseParameter(inOuterAwaitContext: boolean): ParameterDeclaration { @@ -3986,8 +4927,14 @@ namespace Parser { } function parseParameterWorker(inOuterAwaitContext: boolean): ParameterDeclaration; - function parseParameterWorker(inOuterAwaitContext: boolean, allowAmbiguity: false): ParameterDeclaration | undefined; - function parseParameterWorker(inOuterAwaitContext: boolean, allowAmbiguity = true): ParameterDeclaration | undefined { + function parseParameterWorker( + inOuterAwaitContext: boolean, + allowAmbiguity: false, + ): ParameterDeclaration | undefined; + function parseParameterWorker( + inOuterAwaitContext: boolean, + allowAmbiguity = true, + ): ParameterDeclaration | undefined { const pos = getNodePos(); const hasJSDoc = hasPrecedingJSDocComment(); @@ -3995,9 +4942,9 @@ namespace Parser { // BindingElement[?Yield,?Await] // Decorators are parsed in the outer [Await] context, the rest of the parameter is parsed in the function's [Await] context. - const modifiers = inOuterAwaitContext ? - doInAwaitContext(() => parseModifiers(/*allowDecorators*/ true)) : - doOutsideOfAwaitContext(() => parseModifiers(/*allowDecorators*/ true)); + const modifiers = inOuterAwaitContext + ? doInAwaitContext(() => parseModifiers(/*allowDecorators*/ true)) + : doOutsideOfAwaitContext(() => parseModifiers(/*allowDecorators*/ true)); if (token() === SyntaxKind.ThisKeyword) { const node = factory.createParameterDeclaration( @@ -4011,7 +4958,10 @@ namespace Parser { const modifier = firstOrUndefined(modifiers); if (modifier) { - parseErrorAtRange(modifier, Diagnostics.Neither_decorators_nor_modifiers_may_be_applied_to_this_parameters); + parseErrorAtRange( + modifier, + Diagnostics.Neither_decorators_nor_modifiers_may_be_applied_to_this_parameters, + ); } return withJSDoc(finishNode(node, pos), hasJSDoc); @@ -4045,14 +4995,20 @@ namespace Parser { } function parseReturnType(returnToken: SyntaxKind.EqualsGreaterThanToken, isType: boolean): TypeNode; - function parseReturnType(returnToken: SyntaxKind.ColonToken | SyntaxKind.EqualsGreaterThanToken, isType: boolean): TypeNode | undefined; + function parseReturnType( + returnToken: SyntaxKind.ColonToken | SyntaxKind.EqualsGreaterThanToken, + isType: boolean, + ): TypeNode | undefined; function parseReturnType(returnToken: SyntaxKind.ColonToken | SyntaxKind.EqualsGreaterThanToken, isType: boolean) { if (shouldParseReturnType(returnToken, isType)) { return allowConditionalTypesAnd(parseTypeOrTypePredicate); } } - function shouldParseReturnType(returnToken: SyntaxKind.ColonToken | SyntaxKind.EqualsGreaterThanToken, isType: boolean): boolean { + function shouldParseReturnType( + returnToken: SyntaxKind.ColonToken | SyntaxKind.EqualsGreaterThanToken, + isType: boolean, + ): boolean { if (returnToken === SyntaxKind.EqualsGreaterThanToken) { parseExpected(returnToken); return true; @@ -4070,8 +5026,14 @@ namespace Parser { } function parseParametersWorker(flags: SignatureFlags, allowAmbiguity: true): NodeArray; - function parseParametersWorker(flags: SignatureFlags, allowAmbiguity: false): NodeArray | undefined; - function parseParametersWorker(flags: SignatureFlags, allowAmbiguity: boolean): NodeArray | undefined { + function parseParametersWorker( + flags: SignatureFlags, + allowAmbiguity: false, + ): NodeArray | undefined; + function parseParametersWorker( + flags: SignatureFlags, + allowAmbiguity: boolean, + ): NodeArray | undefined { // FormalParameters [Yield,Await]: (modified) // [empty] // FormalParameterList[?Yield,Await] @@ -4091,9 +5053,14 @@ namespace Parser { setYieldContext(!!(flags & SignatureFlags.Yield)); setAwaitContext(!!(flags & SignatureFlags.Await)); - const parameters = flags & SignatureFlags.JSDoc ? - parseDelimitedList(ParsingContext.JSDocParameters, parseJSDocParameter) : - parseDelimitedList(ParsingContext.Parameters, () => allowAmbiguity ? parseParameter(savedAwaitContext) : parseParameterForSpeculation(savedAwaitContext)); + const parameters = flags & SignatureFlags.JSDoc + ? parseDelimitedList(ParsingContext.JSDocParameters, parseJSDocParameter) + : parseDelimitedList( + ParsingContext.Parameters, + () => + allowAmbiguity ? parseParameter(savedAwaitContext) + : parseParameterForSpeculation(savedAwaitContext), + ); setYieldContext(savedYieldContext); setAwaitContext(savedAwaitContext); @@ -4135,7 +5102,9 @@ namespace Parser { parseSemicolon(); } - function parseSignatureMember(kind: SyntaxKind.CallSignature | SyntaxKind.ConstructSignature): CallSignatureDeclaration | ConstructSignatureDeclaration { + function parseSignatureMember( + kind: SyntaxKind.CallSignature | SyntaxKind.ConstructSignature, + ): CallSignatureDeclaration | ConstructSignatureDeclaration { const pos = getNodePos(); const hasJSDoc = hasPrecedingJSDocComment(); if (kind === SyntaxKind.ConstructSignature) { @@ -4208,18 +5177,32 @@ namespace Parser { // If any of the following tokens are after the question mark, it cannot // be a conditional expression, so treat it as an indexer. nextToken(); - return token() === SyntaxKind.ColonToken || token() === SyntaxKind.CommaToken || token() === SyntaxKind.CloseBracketToken; + return token() === SyntaxKind.ColonToken || token() === SyntaxKind.CommaToken + || token() === SyntaxKind.CloseBracketToken; } - function parseIndexSignatureDeclaration(pos: number, hasJSDoc: boolean, modifiers: NodeArray | undefined): IndexSignatureDeclaration { - const parameters = parseBracketedList(ParsingContext.Parameters, () => parseParameter(/*inOuterAwaitContext*/ false), SyntaxKind.OpenBracketToken, SyntaxKind.CloseBracketToken); + function parseIndexSignatureDeclaration( + pos: number, + hasJSDoc: boolean, + modifiers: NodeArray | undefined, + ): IndexSignatureDeclaration { + const parameters = parseBracketedList( + ParsingContext.Parameters, + () => parseParameter(/*inOuterAwaitContext*/ false), + SyntaxKind.OpenBracketToken, + SyntaxKind.CloseBracketToken, + ); const type = parseTypeAnnotation(); parseTypeMemberSemicolon(); const node = factory.createIndexSignature(modifiers, parameters, type); return withJSDoc(finishNode(node, pos), hasJSDoc); } - function parsePropertyOrMethodSignature(pos: number, hasJSDoc: boolean, modifiers: NodeArray | undefined): PropertySignature | MethodSignature { + function parsePropertyOrMethodSignature( + pos: number, + hasJSDoc: boolean, + modifiers: NodeArray | undefined, + ): PropertySignature | MethodSignature { const name = parsePropertyName(); const questionToken = parseOptionalToken(SyntaxKind.QuestionToken); let node: PropertySignature | MethodSignature; @@ -4237,7 +5220,9 @@ namespace Parser { // Although type literal properties cannot not have initializers, we attempt // to parse an initializer so we can report in the checker that an interface // property or type literal property cannot have an initializer. - if (token() === SyntaxKind.EqualsToken) (node as Mutable).initializer = parseInitializer(); + if (token() === SyntaxKind.EqualsToken) { + (node as Mutable).initializer = parseInitializer(); + } } parseTypeMemberSemicolon(); return withJSDoc(finishNode(node, pos), hasJSDoc); @@ -4246,10 +5231,10 @@ namespace Parser { function isTypeMemberStart(): boolean { // Return true if we have the start of a signature member if ( - token() === SyntaxKind.OpenParenToken || - token() === SyntaxKind.LessThanToken || - token() === SyntaxKind.GetKeyword || - token() === SyntaxKind.SetKeyword + token() === SyntaxKind.OpenParenToken + || token() === SyntaxKind.LessThanToken + || token() === SyntaxKind.GetKeyword + || token() === SyntaxKind.SetKeyword ) { return true; } @@ -4271,12 +5256,12 @@ namespace Parser { // If we were able to get any potential identifier, check that it is // the start of a member declaration if (idToken) { - return token() === SyntaxKind.OpenParenToken || - token() === SyntaxKind.LessThanToken || - token() === SyntaxKind.QuestionToken || - token() === SyntaxKind.ColonToken || - token() === SyntaxKind.CommaToken || - canParseSemicolon(); + return token() === SyntaxKind.OpenParenToken + || token() === SyntaxKind.LessThanToken + || token() === SyntaxKind.QuestionToken + || token() === SyntaxKind.ColonToken + || token() === SyntaxKind.CommaToken + || canParseSemicolon(); } return false; } @@ -4350,7 +5335,8 @@ namespace Parser { if (token() === SyntaxKind.ReadonlyKeyword) { nextToken(); } - return token() === SyntaxKind.OpenBracketToken && nextTokenIsIdentifier() && nextToken() === SyntaxKind.InKeyword; + return token() === SyntaxKind.OpenBracketToken && nextTokenIsIdentifier() + && nextToken() === SyntaxKind.InKeyword; } function parseMappedTypeParameter() { @@ -4358,14 +5344,20 @@ namespace Parser { const name = parseIdentifierName(); parseExpected(SyntaxKind.InKeyword); const type = parseType(); - return finishNode(factory.createTypeParameterDeclaration(/*modifiers*/ undefined, name, type, /*defaultType*/ undefined), pos); + return finishNode( + factory.createTypeParameterDeclaration(/*modifiers*/ undefined, name, type, /*defaultType*/ undefined), + pos, + ); } function parseMappedType() { const pos = getNodePos(); parseExpected(SyntaxKind.OpenBraceToken); let readonlyToken: ReadonlyKeyword | PlusToken | MinusToken | undefined; - if (token() === SyntaxKind.ReadonlyKeyword || token() === SyntaxKind.PlusToken || token() === SyntaxKind.MinusToken) { + if ( + token() === SyntaxKind.ReadonlyKeyword || token() === SyntaxKind.PlusToken + || token() === SyntaxKind.MinusToken + ) { readonlyToken = parseTokenNode(); if (readonlyToken.kind !== SyntaxKind.ReadonlyKeyword) { parseExpected(SyntaxKind.ReadonlyKeyword); @@ -4376,7 +5368,10 @@ namespace Parser { const nameType = parseOptional(SyntaxKind.AsKeyword) ? parseType() : undefined; parseExpected(SyntaxKind.CloseBracketToken); let questionToken: QuestionToken | PlusToken | MinusToken | undefined; - if (token() === SyntaxKind.QuestionToken || token() === SyntaxKind.PlusToken || token() === SyntaxKind.MinusToken) { + if ( + token() === SyntaxKind.QuestionToken || token() === SyntaxKind.PlusToken + || token() === SyntaxKind.MinusToken + ) { questionToken = parseTokenNode(); if (questionToken.kind !== SyntaxKind.QuestionToken) { parseExpected(SyntaxKind.QuestionToken); @@ -4386,7 +5381,10 @@ namespace Parser { parseSemicolon(); const members = parseList(ParsingContext.TypeMembers, parseTypeMember); parseExpected(SyntaxKind.CloseBraceToken); - return finishNode(factory.createMappedTypeNode(readonlyToken, typeParameter, nameType, questionToken, type, members), pos); + return finishNode( + factory.createMappedTypeNode(readonlyToken, typeParameter, nameType, questionToken, type, members), + pos, + ); } function parseTupleElementType() { @@ -4405,7 +5403,8 @@ namespace Parser { } function isNextTokenColonOrQuestionColon() { - return nextToken() === SyntaxKind.ColonToken || (token() === SyntaxKind.QuestionToken && nextToken() === SyntaxKind.ColonToken); + return nextToken() === SyntaxKind.ColonToken + || (token() === SyntaxKind.QuestionToken && nextToken() === SyntaxKind.ColonToken); } function isTupleElementName() { @@ -4434,7 +5433,12 @@ namespace Parser { const pos = getNodePos(); return finishNode( factory.createTupleTypeNode( - parseBracketedList(ParsingContext.TupleElementTypes, parseTupleElementNameOrTupleElementType, SyntaxKind.OpenBracketToken, SyntaxKind.CloseBracketToken), + parseBracketedList( + ParsingContext.TupleElementTypes, + parseTupleElementNameOrTupleElementType, + SyntaxKind.OpenBracketToken, + SyntaxKind.CloseBracketToken, + ), ), pos, ); @@ -4464,7 +5468,10 @@ namespace Parser { const hasJSDoc = hasPrecedingJSDocComment(); const modifiers = parseModifiersForConstructorType(); const isConstructorType = parseOptional(SyntaxKind.NewKeyword); - Debug.assert(!modifiers || isConstructorType, "Per isStartOfFunctionOrConstructorType, a function type cannot have modifiers."); + Debug.assert( + !modifiers || isConstructorType, + "Per isStartOfFunctionOrConstructorType, a function type cannot have modifiers.", + ); const typeParameters = parseTypeParameters(); const parameters = parseParameters(SignatureFlags.Type); const type = parseReturnType(SyntaxKind.EqualsGreaterThanToken, /*isType*/ false); @@ -4484,9 +5491,11 @@ namespace Parser { if (negative) { nextToken(); } - let expression: BooleanLiteral | NullLiteral | LiteralExpression | PrefixUnaryExpression = token() === SyntaxKind.TrueKeyword || token() === SyntaxKind.FalseKeyword || token() === SyntaxKind.NullKeyword ? - parseTokenNode() : - parseLiteralLikeNode(token()) as LiteralExpression; + let expression: BooleanLiteral | NullLiteral | LiteralExpression | PrefixUnaryExpression = + token() === SyntaxKind.TrueKeyword || token() === SyntaxKind.FalseKeyword + || token() === SyntaxKind.NullKeyword + ? parseTokenNode() + : parseLiteralLikeNode(token()) as LiteralExpression; if (negative) { expression = finishNode(factory.createPrefixUnaryExpression(SyntaxKind.MinusToken, expression), pos); } @@ -4511,7 +5520,14 @@ namespace Parser { if (lastError && lastError.code === Diagnostics._0_expected.code) { addRelatedInfo( lastError, - createDetachedDiagnostic(fileName, openBracePosition, 1, Diagnostics.The_parser_expected_to_find_a_1_to_match_the_0_token_here, "{", "}"), + createDetachedDiagnostic( + fileName, + openBracePosition, + 1, + Diagnostics.The_parser_expected_to_find_a_1_to_match_the_0_token_here, + "{", + "}", + ), ); } } @@ -4579,7 +5595,8 @@ namespace Parser { case SyntaxKind.NullKeyword: return parseLiteralTypeNode(); case SyntaxKind.MinusToken: - return lookAhead(nextTokenIsNumericOrBigIntLiteral) ? parseLiteralTypeNode(/*negative*/ true) : parseTypeReference(); + return lookAhead(nextTokenIsNumericOrBigIntLiteral) ? parseLiteralTypeNode(/*negative*/ true) + : parseTypeReference(); case SyntaxKind.VoidKeyword: return parseTokenNode(); case SyntaxKind.ThisKeyword: { @@ -4602,7 +5619,8 @@ namespace Parser { case SyntaxKind.ImportKeyword: return parseImportType(); case SyntaxKind.AssertsKeyword: - return lookAhead(nextTokenIsIdentifierOrKeywordOnSameLine) ? parseAssertsTypePredicate() : parseTypeReference(); + return lookAhead(nextTokenIsIdentifierOrKeywordOnSameLine) ? parseAssertsTypePredicate() + : parseTypeReference(); case SyntaxKind.TemplateHead: return parseTemplateType(); default: @@ -4664,7 +5682,8 @@ namespace Parser { function isStartOfParenthesizedOrFunctionType() { nextToken(); - return token() === SyntaxKind.CloseParenToken || isStartOfParameter(/*isJSDocParameter*/ false) || isStartOfType(); + return token() === SyntaxKind.CloseParenToken || isStartOfParameter(/*isJSDocParameter*/ false) + || isStartOfType(); } function parsePostfixTypeOrHigher(): TypeNode { @@ -4703,7 +5722,9 @@ namespace Parser { return type; } - function parseTypeOperator(operator: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.ReadonlyKeyword) { + function parseTypeOperator( + operator: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.ReadonlyKeyword, + ) { const pos = getNodePos(); parseExpected(operator); return finishNode(factory.createTypeOperatorNode(operator, parseTypeOperatorOrHigher()), pos); @@ -4791,11 +5812,19 @@ namespace Parser { } function parseIntersectionTypeOrHigher(): TypeNode { - return parseUnionOrIntersectionType(SyntaxKind.AmpersandToken, parseTypeOperatorOrHigher, factory.createIntersectionTypeNode); + return parseUnionOrIntersectionType( + SyntaxKind.AmpersandToken, + parseTypeOperatorOrHigher, + factory.createIntersectionTypeNode, + ); } function parseUnionTypeOrHigher(): TypeNode { - return parseUnionOrIntersectionType(SyntaxKind.BarToken, parseIntersectionTypeOrHigher, factory.createUnionTypeNode); + return parseUnionOrIntersectionType( + SyntaxKind.BarToken, + parseIntersectionTypeOrHigher, + factory.createUnionTypeNode, + ); } function nextTokenIsNewKeyword(): boolean { @@ -4810,8 +5839,8 @@ namespace Parser { if (token() === SyntaxKind.OpenParenToken && lookAhead(isUnambiguouslyStartOfFunctionType)) { return true; } - return token() === SyntaxKind.NewKeyword || - token() === SyntaxKind.AbstractKeyword && lookAhead(nextTokenIsNewKeyword); + return token() === SyntaxKind.NewKeyword + || token() === SyntaxKind.AbstractKeyword && lookAhead(nextTokenIsNewKeyword); } function skipParameterStart(): boolean { @@ -4843,8 +5872,8 @@ namespace Parser { // We successfully skipped modifiers (if any) and an identifier or binding pattern, // now see if we have something that indicates a parameter declaration if ( - token() === SyntaxKind.ColonToken || token() === SyntaxKind.CommaToken || - token() === SyntaxKind.QuestionToken || token() === SyntaxKind.EqualsToken + token() === SyntaxKind.ColonToken || token() === SyntaxKind.CommaToken + || token() === SyntaxKind.QuestionToken || token() === SyntaxKind.EqualsToken ) { // ( xxx : // ( xxx , @@ -4868,7 +5897,10 @@ namespace Parser { const typePredicateVariable = isIdentifier() && tryParse(parseTypePredicatePrefix); const type = parseType(); if (typePredicateVariable) { - return finishNode(factory.createTypePredicateNode(/*assertsModifier*/ undefined, typePredicateVariable, type), pos); + return finishNode( + factory.createTypePredicateNode(/*assertsModifier*/ undefined, typePredicateVariable, type), + pos, + ); } else { return type; @@ -4900,7 +5932,10 @@ namespace Parser { } const pos = getNodePos(); const type = parseUnionTypeOrHigher(); - if (!inDisallowConditionalTypesContext() && !scanner.hasPrecedingLineBreak() && parseOptional(SyntaxKind.ExtendsKeyword)) { + if ( + !inDisallowConditionalTypesContext() && !scanner.hasPrecedingLineBreak() + && parseOptional(SyntaxKind.ExtendsKeyword) + ) { // The type following 'extends' is not permitted to be another conditional type const extendsType = disallowConditionalTypesAnd(parseType); parseExpected(SyntaxKind.QuestionToken); @@ -4985,11 +6020,11 @@ namespace Parser { function isStartOfExpressionStatement(): boolean { // As per the grammar, none of '{' or 'function' or 'class' can start an expression statement. - return token() !== SyntaxKind.OpenBraceToken && - token() !== SyntaxKind.FunctionKeyword && - token() !== SyntaxKind.ClassKeyword && - token() !== SyntaxKind.AtToken && - isStartOfExpression(); + return token() !== SyntaxKind.OpenBraceToken + && token() !== SyntaxKind.FunctionKeyword + && token() !== SyntaxKind.ClassKeyword + && token() !== SyntaxKind.AtToken + && isStartOfExpression(); } function parseExpression(): Expression { @@ -5007,7 +6042,12 @@ namespace Parser { let expr = parseAssignmentExpressionOrHigher(/*allowReturnTypeInArrowFunction*/ true); let operatorToken: BinaryOperatorToken; while ((operatorToken = parseOptionalToken(SyntaxKind.CommaToken))) { - expr = makeBinaryExpression(expr, operatorToken, parseAssignmentExpressionOrHigher(/*allowReturnTypeInArrowFunction*/ true), pos); + expr = makeBinaryExpression( + expr, + operatorToken, + parseAssignmentExpressionOrHigher(/*allowReturnTypeInArrowFunction*/ true), + pos, + ); } if (saveDecoratorContext) { @@ -5017,7 +6057,8 @@ namespace Parser { } function parseInitializer(): Expression | undefined { - return parseOptional(SyntaxKind.EqualsToken) ? parseAssignmentExpressionOrHigher(/*allowReturnTypeInArrowFunction*/ true) : undefined; + return parseOptional(SyntaxKind.EqualsToken) + ? parseAssignmentExpressionOrHigher(/*allowReturnTypeInArrowFunction*/ true) : undefined; } function parseAssignmentExpressionOrHigher(allowReturnTypeInArrowFunction: boolean): Expression { @@ -5048,7 +6089,8 @@ namespace Parser { // If we do successfully parse arrow-function, we must *not* recurse for productions 1, 2 or 3. An ArrowFunction is // not a LeftHandSideExpression, nor does it start a ConditionalExpression. So we are done // with AssignmentExpression if we see one. - const arrowExpression = tryParseParenthesizedArrowFunctionExpression(allowReturnTypeInArrowFunction) || tryParseAsyncSimpleArrowFunctionExpression(allowReturnTypeInArrowFunction); + const arrowExpression = tryParseParenthesizedArrowFunctionExpression(allowReturnTypeInArrowFunction) + || tryParseAsyncSimpleArrowFunctionExpression(allowReturnTypeInArrowFunction); if (arrowExpression) { return arrowExpression; } @@ -5070,7 +6112,13 @@ namespace Parser { // parameter ('x => ...') above. We handle it here by checking if the parsed expression was a single // identifier and the current token is an arrow. if (expr.kind === SyntaxKind.Identifier && token() === SyntaxKind.EqualsGreaterThanToken) { - return parseSimpleArrowFunctionExpression(pos, expr as Identifier, allowReturnTypeInArrowFunction, hasJSDoc, /*asyncModifier*/ undefined); + return parseSimpleArrowFunctionExpression( + pos, + expr as Identifier, + allowReturnTypeInArrowFunction, + hasJSDoc, + /*asyncModifier*/ undefined, + ); } // Now see if we might be in cases '2' or '3'. @@ -5080,7 +6128,12 @@ namespace Parser { // Note: we call reScanGreaterToken so that we get an appropriately merged token // for cases like `> > =` becoming `>>=` if (isLeftHandSideExpression(expr) && isAssignmentOperator(reScanGreaterToken())) { - return makeBinaryExpression(expr, parseTokenNode(), parseAssignmentExpressionOrHigher(allowReturnTypeInArrowFunction), pos); + return makeBinaryExpression( + expr, + parseTokenNode(), + parseAssignmentExpressionOrHigher(allowReturnTypeInArrowFunction), + pos, + ); } // It wasn't an assignment or a lambda. This is a conditional expression: @@ -5130,8 +6183,8 @@ namespace Parser { nextToken(); if ( - !scanner.hasPrecedingLineBreak() && - (token() === SyntaxKind.AsteriskToken || isStartOfExpression()) + !scanner.hasPrecedingLineBreak() + && (token() === SyntaxKind.AsteriskToken || isStartOfExpression()) ) { return finishNode( factory.createYieldExpression( @@ -5144,12 +6197,24 @@ namespace Parser { else { // if the next token is not on the same line as yield. or we don't have an '*' or // the start of an expression, then this is just a simple "yield" expression. - return finishNode(factory.createYieldExpression(/*asteriskToken*/ undefined, /*expression*/ undefined), pos); + return finishNode( + factory.createYieldExpression(/*asteriskToken*/ undefined, /*expression*/ undefined), + pos, + ); } } - function parseSimpleArrowFunctionExpression(pos: number, identifier: Identifier, allowReturnTypeInArrowFunction: boolean, hasJSDoc: boolean, asyncModifier?: NodeArray | undefined): ArrowFunction { - Debug.assert(token() === SyntaxKind.EqualsGreaterThanToken, "parseSimpleArrowFunctionExpression should only have been called if we had a =>"); + function parseSimpleArrowFunctionExpression( + pos: number, + identifier: Identifier, + allowReturnTypeInArrowFunction: boolean, + hasJSDoc: boolean, + asyncModifier?: NodeArray | undefined, + ): ArrowFunction { + Debug.assert( + token() === SyntaxKind.EqualsGreaterThanToken, + "parseSimpleArrowFunctionExpression should only have been called if we had a =>", + ); const parameter = factory.createParameterDeclaration( /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, @@ -5163,11 +6228,20 @@ namespace Parser { const parameters = createNodeArray([parameter], parameter.pos, parameter.end); const equalsGreaterThanToken = parseExpectedToken(SyntaxKind.EqualsGreaterThanToken); const body = parseArrowFunctionExpressionBody(/*isAsync*/ !!asyncModifier, allowReturnTypeInArrowFunction); - const node = factory.createArrowFunction(asyncModifier, /*typeParameters*/ undefined, parameters, /*type*/ undefined, equalsGreaterThanToken, body); + const node = factory.createArrowFunction( + asyncModifier, + /*typeParameters*/ undefined, + parameters, + /*type*/ undefined, + equalsGreaterThanToken, + body, + ); return withJSDoc(finishNode(node, pos), hasJSDoc); } - function tryParseParenthesizedArrowFunctionExpression(allowReturnTypeInArrowFunction: boolean): Expression | undefined { + function tryParseParenthesizedArrowFunctionExpression( + allowReturnTypeInArrowFunction: boolean, + ): Expression | undefined { const triState = isParenthesizedArrowFunctionExpression(); if (triState === Tristate.False) { // It's definitely not a parenthesized arrow function expression. @@ -5178,9 +6252,12 @@ namespace Parser { // following => or { token. Otherwise, we *might* have an arrow function. Try to parse // it out, but don't allow any ambiguity, and return 'undefined' if this could be an // expression instead. - return triState === Tristate.True ? - parseParenthesizedArrowFunctionExpression(/*allowAmbiguity*/ true, /*allowReturnTypeInArrowFunction*/ true) : - tryParse(() => parsePossibleParenthesizedArrowFunctionExpression(allowReturnTypeInArrowFunction)); + return triState === Tristate.True + ? parseParenthesizedArrowFunctionExpression( + /*allowAmbiguity*/ true, + /*allowReturnTypeInArrowFunction*/ true, + ) + : tryParse(() => parsePossibleParenthesizedArrowFunctionExpression(allowReturnTypeInArrowFunction)); } // True -> We definitely expect a parenthesized arrow function here. @@ -5188,7 +6265,10 @@ namespace Parser { // Unknown -> There *might* be a parenthesized arrow function here. // Speculatively look ahead to be sure, and rollback if not. function isParenthesizedArrowFunctionExpression(): Tristate { - if (token() === SyntaxKind.OpenParenToken || token() === SyntaxKind.LessThanToken || token() === SyntaxKind.AsyncKeyword) { + if ( + token() === SyntaxKind.OpenParenToken || token() === SyntaxKind.LessThanToken + || token() === SyntaxKind.AsyncKeyword + ) { return lookAhead(isParenthesizedArrowFunctionExpressionWorker); } @@ -5275,7 +6355,10 @@ namespace Parser { case SyntaxKind.QuestionToken: nextToken(); // If we have "(a?:" or "(a?," or "(a?=" or "(a?)" then it is definitely a lambda. - if (token() === SyntaxKind.ColonToken || token() === SyntaxKind.CommaToken || token() === SyntaxKind.EqualsToken || token() === SyntaxKind.CloseParenToken) { + if ( + token() === SyntaxKind.ColonToken || token() === SyntaxKind.CommaToken + || token() === SyntaxKind.EqualsToken || token() === SyntaxKind.CloseParenToken + ) { return Tristate.True; } // Otherwise it is definitely not a lambda. @@ -5332,13 +6415,18 @@ namespace Parser { } } - function parsePossibleParenthesizedArrowFunctionExpression(allowReturnTypeInArrowFunction: boolean): ArrowFunction | undefined { + function parsePossibleParenthesizedArrowFunctionExpression( + allowReturnTypeInArrowFunction: boolean, + ): ArrowFunction | undefined { const tokenPos = scanner.getTokenStart(); if (notParenthesizedArrow?.has(tokenPos)) { return undefined; } - const result = parseParenthesizedArrowFunctionExpression(/*allowAmbiguity*/ false, allowReturnTypeInArrowFunction); + const result = parseParenthesizedArrowFunctionExpression( + /*allowAmbiguity*/ false, + allowReturnTypeInArrowFunction, + ); if (!result) { (notParenthesizedArrow || (notParenthesizedArrow = new Set())).add(tokenPos); } @@ -5346,7 +6434,9 @@ namespace Parser { return result; } - function tryParseAsyncSimpleArrowFunctionExpression(allowReturnTypeInArrowFunction: boolean): ArrowFunction | undefined { + function tryParseAsyncSimpleArrowFunctionExpression( + allowReturnTypeInArrowFunction: boolean, + ): ArrowFunction | undefined { // We do a check here so that we won't be doing unnecessarily call to "lookAhead" if (token() === SyntaxKind.AsyncKeyword) { if (lookAhead(isUnParenthesizedAsyncArrowFunctionWorker) === Tristate.True) { @@ -5354,7 +6444,13 @@ namespace Parser { const hasJSDoc = hasPrecedingJSDocComment(); const asyncModifier = parseModifiersForArrowFunction(); const expr = parseBinaryExpressionOrHigher(OperatorPrecedence.Lowest); - return parseSimpleArrowFunctionExpression(pos, expr as Identifier, allowReturnTypeInArrowFunction, hasJSDoc, asyncModifier); + return parseSimpleArrowFunctionExpression( + pos, + expr as Identifier, + allowReturnTypeInArrowFunction, + hasJSDoc, + asyncModifier, + ); } } return undefined; @@ -5373,7 +6469,10 @@ namespace Parser { } // Check for un-parenthesized AsyncArrowFunction const expr = parseBinaryExpressionOrHigher(OperatorPrecedence.Lowest); - if (!scanner.hasPrecedingLineBreak() && expr.kind === SyntaxKind.Identifier && token() === SyntaxKind.EqualsGreaterThanToken) { + if ( + !scanner.hasPrecedingLineBreak() && expr.kind === SyntaxKind.Identifier + && token() === SyntaxKind.EqualsGreaterThanToken + ) { return Tristate.True; } } @@ -5381,7 +6480,10 @@ namespace Parser { return Tristate.False; } - function parseParenthesizedArrowFunctionExpression(allowAmbiguity: boolean, allowReturnTypeInArrowFunction: boolean): ArrowFunction | undefined { + function parseParenthesizedArrowFunctionExpression( + allowAmbiguity: boolean, + allowReturnTypeInArrowFunction: boolean, + ): ArrowFunction | undefined { const pos = getNodePos(); const hasJSDoc = hasPrecedingJSDocComment(); const modifiers = parseModifiersForArrowFunction(); @@ -5441,7 +6543,10 @@ namespace Parser { } const hasJSDocFunctionType = unwrappedType && isJSDocFunctionType(unwrappedType); - if (!allowAmbiguity && token() !== SyntaxKind.EqualsGreaterThanToken && (hasJSDocFunctionType || token() !== SyntaxKind.OpenBraceToken)) { + if ( + !allowAmbiguity && token() !== SyntaxKind.EqualsGreaterThanToken + && (hasJSDocFunctionType || token() !== SyntaxKind.OpenBraceToken) + ) { // Returning undefined here will cause our caller to rewind to where we started from. return undefined; } @@ -5480,21 +6585,31 @@ namespace Parser { } } - const node = factory.createArrowFunction(modifiers, typeParameters, parameters, type, equalsGreaterThanToken, body); + const node = factory.createArrowFunction( + modifiers, + typeParameters, + parameters, + type, + equalsGreaterThanToken, + body, + ); return withJSDoc(finishNode(node, pos), hasJSDoc); } - function parseArrowFunctionExpressionBody(isAsync: boolean, allowReturnTypeInArrowFunction: boolean): Block | Expression { + function parseArrowFunctionExpressionBody( + isAsync: boolean, + allowReturnTypeInArrowFunction: boolean, + ): Block | Expression { if (token() === SyntaxKind.OpenBraceToken) { return parseFunctionBlock(isAsync ? SignatureFlags.Await : SignatureFlags.None); } if ( - token() !== SyntaxKind.SemicolonToken && - token() !== SyntaxKind.FunctionKeyword && - token() !== SyntaxKind.ClassKeyword && - isStartOfStatement() && - !isStartOfExpressionStatement() + token() !== SyntaxKind.SemicolonToken + && token() !== SyntaxKind.FunctionKeyword + && token() !== SyntaxKind.ClassKeyword + && isStartOfStatement() + && !isStartOfExpressionStatement() ) { // Check if we got a plain statement (i.e. no expression-statements, no function/class expressions/declarations) // @@ -5510,7 +6625,9 @@ namespace Parser { // up preemptively closing the containing construct. // // Note: even when 'IgnoreMissingOpenBrace' is passed, parseBody will still error. - return parseFunctionBlock(SignatureFlags.IgnoreMissingOpenBrace | (isAsync ? SignatureFlags.Await : SignatureFlags.None)); + return parseFunctionBlock( + SignatureFlags.IgnoreMissingOpenBrace | (isAsync ? SignatureFlags.Await : SignatureFlags.None), + ); } const savedTopLevel = topLevel; @@ -5522,7 +6639,11 @@ namespace Parser { return node; } - function parseConditionalExpressionRest(leftOperand: Expression, pos: number, allowReturnTypeInArrowFunction: boolean): Expression { + function parseConditionalExpressionRest( + leftOperand: Expression, + pos: number, + allowReturnTypeInArrowFunction: boolean, + ): Expression { // Note: we are passed in an expression which was produced from parseBinaryExpressionOrHigher. const questionToken = parseOptionalToken(SyntaxKind.QuestionToken); if (!questionToken) { @@ -5536,11 +6657,19 @@ namespace Parser { factory.createConditionalExpression( leftOperand, questionToken, - doOutsideOfContext(disallowInAndDecoratorContext, () => parseAssignmentExpressionOrHigher(/*allowReturnTypeInArrowFunction*/ false)), + doOutsideOfContext( + disallowInAndDecoratorContext, + () => parseAssignmentExpressionOrHigher(/*allowReturnTypeInArrowFunction*/ false), + ), colonToken = parseExpectedToken(SyntaxKind.ColonToken), nodeIsPresent(colonToken) ? parseAssignmentExpressionOrHigher(allowReturnTypeInArrowFunction) - : createMissingNode(SyntaxKind.Identifier, /*reportAtCurrentPosition*/ false, Diagnostics._0_expected, tokenToString(SyntaxKind.ColonToken)), + : createMissingNode( + SyntaxKind.Identifier, + /*reportAtCurrentPosition*/ false, + Diagnostics._0_expected, + tokenToString(SyntaxKind.ColonToken), + ), ), pos, ); @@ -5556,7 +6685,11 @@ namespace Parser { return t === SyntaxKind.InKeyword || t === SyntaxKind.OfKeyword; } - function parseBinaryExpressionRest(precedence: OperatorPrecedence, leftOperand: Expression, pos: number): Expression { + function parseBinaryExpressionRest( + precedence: OperatorPrecedence, + leftOperand: Expression, + pos: number, + ): Expression { while (true) { // We either have a binary operator here, or we're finished. We call // reScanGreaterToken so that we merge token sequences like > and = into >= @@ -5585,9 +6718,9 @@ namespace Parser { // ^^token; leftOperand = b. Return b ** c to the caller as a rightOperand // a ** b - c // ^token; leftOperand = b. Return b to the caller as a rightOperand - const consumeCurrentOperator = token() === SyntaxKind.AsteriskAsteriskToken ? - newPrecedence >= precedence : - newPrecedence > precedence; + const consumeCurrentOperator = token() === SyntaxKind.AsteriskAsteriskToken + ? newPrecedence >= precedence + : newPrecedence > precedence; if (!consumeCurrentOperator) { break; @@ -5609,12 +6742,18 @@ namespace Parser { else { const keywordKind = token(); nextToken(); - leftOperand = keywordKind === SyntaxKind.SatisfiesKeyword ? makeSatisfiesExpression(leftOperand, parseType()) : - makeAsExpression(leftOperand, parseType()); + leftOperand = keywordKind === SyntaxKind.SatisfiesKeyword + ? makeSatisfiesExpression(leftOperand, parseType()) + : makeAsExpression(leftOperand, parseType()); } } else { - leftOperand = makeBinaryExpression(leftOperand, parseTokenNode(), parseBinaryExpressionOrHigher(newPrecedence), pos); + leftOperand = makeBinaryExpression( + leftOperand, + parseTokenNode(), + parseBinaryExpressionOrHigher(newPrecedence), + pos, + ); } } @@ -5633,7 +6772,12 @@ namespace Parser { return finishNode(factory.createSatisfiesExpression(left, right), left.pos); } - function makeBinaryExpression(left: Expression, operatorToken: BinaryOperatorToken, right: Expression, pos: number): BinaryExpression { + function makeBinaryExpression( + left: Expression, + operatorToken: BinaryOperatorToken, + right: Expression, + pos: number, + ): BinaryExpression { return finishNode(factory.createBinaryExpression(left, operatorToken, right), pos); } @@ -5643,7 +6787,13 @@ namespace Parser { function parsePrefixUnaryExpression() { const pos = getNodePos(); - return finishNode(factory.createPrefixUnaryExpression(token() as PrefixUnaryOperator, nextTokenAnd(parseSimpleUnaryExpression)), pos); + return finishNode( + factory.createPrefixUnaryExpression( + token() as PrefixUnaryOperator, + nextTokenAnd(parseSimpleUnaryExpression), + ), + pos, + ); } function parseDeleteExpression() { @@ -5698,9 +6848,13 @@ namespace Parser { if (isUpdateExpression()) { const pos = getNodePos(); const updateExpression = parseUpdateExpression(); - return token() === SyntaxKind.AsteriskAsteriskToken ? - parseBinaryExpressionRest(getBinaryOperatorPrecedence(token()), updateExpression, pos) as BinaryExpression : - updateExpression; + return token() === SyntaxKind.AsteriskAsteriskToken + ? parseBinaryExpressionRest( + getBinaryOperatorPrecedence(token()), + updateExpression, + pos, + ) as BinaryExpression + : updateExpression; } /** @@ -5720,11 +6874,22 @@ namespace Parser { const pos = skipTrivia(sourceText, simpleUnaryExpression.pos); const { end } = simpleUnaryExpression; if (simpleUnaryExpression.kind === SyntaxKind.TypeAssertionExpression) { - parseErrorAt(pos, end, Diagnostics.A_type_assertion_expression_is_not_allowed_in_the_left_hand_side_of_an_exponentiation_expression_Consider_enclosing_the_expression_in_parentheses); + parseErrorAt( + pos, + end, + Diagnostics + .A_type_assertion_expression_is_not_allowed_in_the_left_hand_side_of_an_exponentiation_expression_Consider_enclosing_the_expression_in_parentheses, + ); } else { Debug.assert(isKeywordOrPunctuation(unaryOperator)); - parseErrorAt(pos, end, Diagnostics.An_unary_expression_with_the_0_operator_is_not_allowed_in_the_left_hand_side_of_an_exponentiation_expression_Consider_enclosing_the_expression_in_parentheses, tokenToString(unaryOperator)); + parseErrorAt( + pos, + end, + Diagnostics + .An_unary_expression_with_the_0_operator_is_not_allowed_in_the_left_hand_side_of_an_exponentiation_expression_Consider_enclosing_the_expression_in_parentheses, + tokenToString(unaryOperator), + ); } } return simpleUnaryExpression; @@ -5761,7 +6926,12 @@ namespace Parser { // Just like in parseUpdateExpression, we need to avoid parsing type assertions when // in JSX and we see an expression like "+ bar". if (languageVariant === LanguageVariant.JSX) { - return parseJsxElementOrSelfClosingElementOrFragment(/*inExpressionContext*/ true, /*topInvalidNodePosition*/ undefined, /*openingTag*/ undefined, /*mustBeUnary*/ true); + return parseJsxElementOrSelfClosingElementOrFragment( + /*inExpressionContext*/ true, + /*topInvalidNodePosition*/ undefined, + /*openingTag*/ undefined, + /*mustBeUnary*/ true, + ); } // This is modified UnaryExpression grammar in TypeScript // UnaryExpression (modified): @@ -5826,9 +6996,18 @@ namespace Parser { function parseUpdateExpression(): UpdateExpression { if (token() === SyntaxKind.PlusPlusToken || token() === SyntaxKind.MinusMinusToken) { const pos = getNodePos(); - return finishNode(factory.createPrefixUnaryExpression(token() as PrefixUnaryOperator, nextTokenAnd(parseLeftHandSideExpressionOrHigher)), pos); + return finishNode( + factory.createPrefixUnaryExpression( + token() as PrefixUnaryOperator, + nextTokenAnd(parseLeftHandSideExpressionOrHigher), + ), + pos, + ); } - else if (languageVariant === LanguageVariant.JSX && token() === SyntaxKind.LessThanToken && lookAhead(nextTokenIsIdentifierOrKeywordOrGreaterThan)) { + else if ( + languageVariant === LanguageVariant.JSX && token() === SyntaxKind.LessThanToken + && lookAhead(nextTokenIsIdentifierOrKeywordOrGreaterThan) + ) { // JSXElement is part of primaryExpression return parseJsxElementOrSelfClosingElementOrFragment(/*inExpressionContext*/ true); } @@ -5836,7 +7015,10 @@ namespace Parser { const expression = parseLeftHandSideExpressionOrHigher(); Debug.assert(isLeftHandSideExpression(expression)); - if ((token() === SyntaxKind.PlusPlusToken || token() === SyntaxKind.MinusMinusToken) && !scanner.hasPrecedingLineBreak()) { + if ( + (token() === SyntaxKind.PlusPlusToken || token() === SyntaxKind.MinusMinusToken) + && !scanner.hasPrecedingLineBreak() + ) { const operator = token() as PostfixUnaryOperator; nextToken(); return finishNode(factory.createPostfixUnaryExpression(expression, operator), expression.pos); @@ -5893,7 +7075,10 @@ namespace Parser { // This is an 'import.*' metaproperty (i.e. 'import.meta') nextToken(); // advance past the 'import' nextToken(); // advance past the dot - expression = finishNode(factory.createMetaProperty(SyntaxKind.ImportKeyword, parseIdentifierName()), pos); + expression = finishNode( + factory.createMetaProperty(SyntaxKind.ImportKeyword, parseIdentifierName()), + pos, + ); sourceFlags |= NodeFlags.PossiblyContainsImportMeta; } else { @@ -5977,18 +7162,39 @@ namespace Parser { } } - if (token() === SyntaxKind.OpenParenToken || token() === SyntaxKind.DotToken || token() === SyntaxKind.OpenBracketToken) { + if ( + token() === SyntaxKind.OpenParenToken || token() === SyntaxKind.DotToken + || token() === SyntaxKind.OpenBracketToken + ) { return expression; } // If we have seen "super" it must be followed by '(' or '.'. // If it wasn't then just try to parse out a '.' and report an error. - parseExpectedToken(SyntaxKind.DotToken, Diagnostics.super_must_be_followed_by_an_argument_list_or_member_access); + parseExpectedToken( + SyntaxKind.DotToken, + Diagnostics.super_must_be_followed_by_an_argument_list_or_member_access, + ); // private names will never work with `super` (`super.#foo`), but that's a semantic error, not syntactic - return finishNode(factoryCreatePropertyAccessExpression(expression, parseRightSideOfDot(/*allowIdentifierNames*/ true, /*allowPrivateIdentifiers*/ true, /*allowUnicodeEscapeSequenceInIdentifierName*/ true)), pos); + return finishNode( + factoryCreatePropertyAccessExpression( + expression, + parseRightSideOfDot( + /*allowIdentifierNames*/ true, + /*allowPrivateIdentifiers*/ true, + /*allowUnicodeEscapeSequenceInIdentifierName*/ true, + ), + ), + pos, + ); } - function parseJsxElementOrSelfClosingElementOrFragment(inExpressionContext: boolean, topInvalidNodePosition?: number, openingTag?: JsxOpeningElement | JsxOpeningFragment, mustBeUnary = false): JsxElement | JsxSelfClosingElement | JsxFragment { + function parseJsxElementOrSelfClosingElementOrFragment( + inExpressionContext: boolean, + topInvalidNodePosition?: number, + openingTag?: JsxOpeningElement | JsxOpeningFragment, + mustBeUnary = false, + ): JsxElement | JsxSelfClosingElement | JsxFragment { const pos = getNodePos(); const opening = parseJsxOpeningOrSelfClosingElementOrOpeningFragment(inExpressionContext); let result: JsxElement | JsxSelfClosingElement | JsxFragment; @@ -6010,7 +7216,11 @@ namespace Parser { factory.createJsxElement( lastChild.openingElement, lastChild.children, - finishNode(factory.createJsxClosingElement(finishNode(factoryCreateIdentifier(""), end, end)), end, end), + finishNode( + factory.createJsxClosingElement(finishNode(factoryCreateIdentifier(""), end, end)), + end, + end, + ), ), lastChild.openingElement.pos, end, @@ -6022,20 +7232,38 @@ namespace Parser { else { closingElement = parseJsxClosingElement(opening, inExpressionContext); if (!tagNamesAreEquivalent(opening.tagName, closingElement.tagName)) { - if (openingTag && isJsxOpeningElement(openingTag) && tagNamesAreEquivalent(closingElement.tagName, openingTag.tagName)) { + if ( + openingTag && isJsxOpeningElement(openingTag) + && tagNamesAreEquivalent(closingElement.tagName, openingTag.tagName) + ) { // opening incorrectly matched with its parent's closing -- put error on opening - parseErrorAtRange(opening.tagName, Diagnostics.JSX_element_0_has_no_corresponding_closing_tag, getTextOfNodeFromSourceText(sourceText, opening.tagName)); + parseErrorAtRange( + opening.tagName, + Diagnostics.JSX_element_0_has_no_corresponding_closing_tag, + getTextOfNodeFromSourceText(sourceText, opening.tagName), + ); } else { // other opening/closing mismatches -- put error on closing - parseErrorAtRange(closingElement.tagName, Diagnostics.Expected_corresponding_JSX_closing_tag_for_0, getTextOfNodeFromSourceText(sourceText, opening.tagName)); + parseErrorAtRange( + closingElement.tagName, + Diagnostics.Expected_corresponding_JSX_closing_tag_for_0, + getTextOfNodeFromSourceText(sourceText, opening.tagName), + ); } } } result = finishNode(factory.createJsxElement(opening, children, closingElement), pos); } else if (opening.kind === SyntaxKind.JsxOpeningFragment) { - result = finishNode(factory.createJsxFragment(opening, parseJsxChildren(opening), parseJsxClosingFragment(inExpressionContext)), pos); + result = finishNode( + factory.createJsxFragment( + opening, + parseJsxChildren(opening), + parseJsxClosingFragment(inExpressionContext), + ), + pos, + ); } else { Debug.assert(opening.kind === SyntaxKind.JsxSelfClosingElement); @@ -6054,12 +7282,25 @@ namespace Parser { // a valid UnaryExpression and will cause problems later. if (!mustBeUnary && inExpressionContext && token() === SyntaxKind.LessThanToken) { const topBadPos = typeof topInvalidNodePosition === "undefined" ? result.pos : topInvalidNodePosition; - const invalidElement = tryParse(() => parseJsxElementOrSelfClosingElementOrFragment(/*inExpressionContext*/ true, topBadPos)); + const invalidElement = tryParse(() => + parseJsxElementOrSelfClosingElementOrFragment(/*inExpressionContext*/ true, topBadPos) + ); if (invalidElement) { const operatorToken = createMissingNode(SyntaxKind.CommaToken, /*reportAtCurrentPosition*/ false); setTextRangePosWidth(operatorToken, invalidElement.pos, 0); - parseErrorAt(skipTrivia(sourceText, topBadPos), invalidElement.end, Diagnostics.JSX_expressions_must_have_one_parent_element); - return finishNode(factory.createBinaryExpression(result, operatorToken as Token, invalidElement), pos) as Node as JsxElement; + parseErrorAt( + skipTrivia(sourceText, topBadPos), + invalidElement.end, + Diagnostics.JSX_expressions_must_have_one_parent_element, + ); + return finishNode( + factory.createBinaryExpression( + result, + operatorToken as Token, + invalidElement, + ), + pos, + ) as Node as JsxElement; } } @@ -6073,7 +7314,10 @@ namespace Parser { return finishNode(node, pos); } - function parseJsxChild(openingTag: JsxOpeningElement | JsxOpeningFragment, token: JsxTokenSyntaxKind): JsxChild | undefined { + function parseJsxChild( + openingTag: JsxOpeningElement | JsxOpeningFragment, + token: JsxTokenSyntaxKind, + ): JsxChild | undefined { switch (token) { case SyntaxKind.EndOfFileToken: // If we hit EOF, issue the error at the tag that lacks the closing element @@ -6086,7 +7330,12 @@ namespace Parser { // or to cover only 'Foo' in < Foo > const tag = openingTag.tagName; const start = Math.min(skipTrivia(sourceText, tag.pos), tag.end); - parseErrorAt(start, tag.end, Diagnostics.JSX_element_0_has_no_corresponding_closing_tag, getTextOfNodeFromSourceText(sourceText, openingTag.tagName)); + parseErrorAt( + start, + tag.end, + Diagnostics.JSX_element_0_has_no_corresponding_closing_tag, + getTextOfNodeFromSourceText(sourceText, openingTag.tagName), + ); } return undefined; case SyntaxKind.LessThanSlashToken: @@ -6098,7 +7347,11 @@ namespace Parser { case SyntaxKind.OpenBraceToken: return parseJsxExpression(/*inExpressionContext*/ false); case SyntaxKind.LessThanToken: - return parseJsxElementOrSelfClosingElementOrFragment(/*inExpressionContext*/ false, /*topInvalidNodePosition*/ undefined, openingTag); + return parseJsxElementOrSelfClosingElementOrFragment( + /*inExpressionContext*/ false, + /*topInvalidNodePosition*/ undefined, + openingTag, + ); default: return Debug.assertNever(token); } @@ -6134,7 +7387,9 @@ namespace Parser { return finishNode(factory.createJsxAttributes(parseList(ParsingContext.JsxAttributes, parseJsxAttribute)), pos); } - function parseJsxOpeningOrSelfClosingElementOrOpeningFragment(inExpressionContext: boolean): JsxOpeningElement | JsxSelfClosingElement | JsxOpeningFragment { + function parseJsxOpeningOrSelfClosingElementOrOpeningFragment( + inExpressionContext: boolean, + ): JsxOpeningElement | JsxSelfClosingElement | JsxOpeningFragment { const pos = getNodePos(); parseExpected(SyntaxKind.LessThanToken); @@ -6187,7 +7442,17 @@ namespace Parser { } let expression: PropertyAccessExpression | Identifier | ThisExpression = initialExpression; while (parseOptional(SyntaxKind.DotToken)) { - expression = finishNode(factoryCreatePropertyAccessExpression(expression, parseRightSideOfDot(/*allowIdentifierNames*/ true, /*allowPrivateIdentifiers*/ false, /*allowUnicodeEscapeSequenceInIdentifierName*/ false)), pos); + expression = finishNode( + factoryCreatePropertyAccessExpression( + expression, + parseRightSideOfDot( + /*allowIdentifierNames*/ true, + /*allowPrivateIdentifiers*/ false, + /*allowUnicodeEscapeSequenceInIdentifierName*/ false, + ), + ), + pos, + ); } return expression as JsxTagNameExpression; } @@ -6200,7 +7465,10 @@ namespace Parser { const tagName = parseIdentifierNameErrorOnUnicodeEscapeSequence(); if (parseOptional(SyntaxKind.ColonToken)) { scanJsxIdentifier(); - return finishNode(factory.createJsxNamespacedName(tagName, parseIdentifierNameErrorOnUnicodeEscapeSequence()), pos); + return finishNode( + factory.createJsxNamespacedName(tagName, parseIdentifierNameErrorOnUnicodeEscapeSequence()), + pos, + ); } return isThis ? finishNode(factory.createToken(SyntaxKind.ThisKeyword), pos) : tagName; } @@ -6264,7 +7532,10 @@ namespace Parser { const attrName = parseIdentifierNameErrorOnUnicodeEscapeSequence(); if (parseOptional(SyntaxKind.ColonToken)) { scanJsxIdentifier(); - return finishNode(factory.createJsxNamespacedName(attrName, parseIdentifierNameErrorOnUnicodeEscapeSequence()), pos); + return finishNode( + factory.createJsxNamespacedName(attrName, parseIdentifierNameErrorOnUnicodeEscapeSequence()), + pos, + ); } return attrName; } @@ -6297,7 +7568,13 @@ namespace Parser { function parseJsxClosingFragment(inExpressionContext: boolean): JsxClosingFragment { const pos = getNodePos(); parseExpected(SyntaxKind.LessThanSlashToken); - if (parseExpected(SyntaxKind.GreaterThanToken, Diagnostics.Expected_corresponding_closing_tag_for_JSX_fragment, /*shouldAdvance*/ false)) { + if ( + parseExpected( + SyntaxKind.GreaterThanToken, + Diagnostics.Expected_corresponding_closing_tag_for_JSX_fragment, + /*shouldAdvance*/ false, + ) + ) { // manually advance the scanner in order to look for jsx text inside jsx if (inExpressionContext) { nextToken(); @@ -6310,7 +7587,10 @@ namespace Parser { } function parseTypeAssertion(): TypeAssertion { - Debug.assert(languageVariant !== LanguageVariant.JSX, "Type assertions should never be parsed in JSX; they should be parsed as comparisons or JSX elements/fragments."); + Debug.assert( + languageVariant !== LanguageVariant.JSX, + "Type assertions should never be parsed in JSX; they should be parsed as comparisons or JSX elements/fragments.", + ); const pos = getNodePos(); parseExpected(SyntaxKind.LessThanToken); const type = parseType(); @@ -6353,12 +7633,20 @@ namespace Parser { return false; } - function parsePropertyAccessExpressionRest(pos: number, expression: LeftHandSideExpression, questionDotToken: QuestionDotToken | undefined) { - const name = parseRightSideOfDot(/*allowIdentifierNames*/ true, /*allowPrivateIdentifiers*/ true, /*allowUnicodeEscapeSequenceInIdentifierName*/ true); + function parsePropertyAccessExpressionRest( + pos: number, + expression: LeftHandSideExpression, + questionDotToken: QuestionDotToken | undefined, + ) { + const name = parseRightSideOfDot( + /*allowIdentifierNames*/ true, + /*allowPrivateIdentifiers*/ true, + /*allowUnicodeEscapeSequenceInIdentifierName*/ true, + ); const isOptionalChain = questionDotToken || tryReparseOptionalChain(expression); - const propertyAccess = isOptionalChain ? - factoryCreatePropertyAccessChain(expression, questionDotToken, name) : - factoryCreatePropertyAccessExpression(expression, name); + const propertyAccess = isOptionalChain + ? factoryCreatePropertyAccessChain(expression, questionDotToken, name) + : factoryCreatePropertyAccessExpression(expression, name); if (isOptionalChain && isPrivateIdentifier(propertyAccess.name)) { parseErrorAtRange(propertyAccess.name, Diagnostics.An_optional_chain_cannot_contain_private_identifiers); } @@ -6370,10 +7658,18 @@ namespace Parser { return finishNode(propertyAccess, pos); } - function parseElementAccessExpressionRest(pos: number, expression: LeftHandSideExpression, questionDotToken: QuestionDotToken | undefined) { + function parseElementAccessExpressionRest( + pos: number, + expression: LeftHandSideExpression, + questionDotToken: QuestionDotToken | undefined, + ) { let argumentExpression: Expression; if (token() === SyntaxKind.CloseBracketToken) { - argumentExpression = createMissingNode(SyntaxKind.Identifier, /*reportAtCurrentPosition*/ true, Diagnostics.An_element_access_expression_should_take_an_argument); + argumentExpression = createMissingNode( + SyntaxKind.Identifier, + /*reportAtCurrentPosition*/ true, + Diagnostics.An_element_access_expression_should_take_an_argument, + ); } else { const argument = allowInAnd(parseExpression); @@ -6385,13 +7681,17 @@ namespace Parser { parseExpected(SyntaxKind.CloseBracketToken); - const indexedAccess = questionDotToken || tryReparseOptionalChain(expression) ? - factoryCreateElementAccessChain(expression, questionDotToken, argumentExpression) : - factoryCreateElementAccessExpression(expression, argumentExpression); + const indexedAccess = questionDotToken || tryReparseOptionalChain(expression) + ? factoryCreateElementAccessChain(expression, questionDotToken, argumentExpression) + : factoryCreateElementAccessExpression(expression, argumentExpression); return finishNode(indexedAccess, pos); } - function parseMemberExpressionRest(pos: number, expression: LeftHandSideExpression, allowOptionalChain: boolean): MemberExpression { + function parseMemberExpressionRest( + pos: number, + expression: LeftHandSideExpression, + allowOptionalChain: boolean, + ): MemberExpression { while (true) { let questionDotToken: QuestionDotToken | undefined; let isPropertyAccess = false; @@ -6416,9 +7716,14 @@ namespace Parser { if (isTemplateStartOfTaggedTemplate()) { // Absorb type arguments into TemplateExpression when preceding expression is ExpressionWithTypeArguments - expression = !questionDotToken && expression.kind === SyntaxKind.ExpressionWithTypeArguments ? - parseTaggedTemplateRest(pos, (expression as ExpressionWithTypeArguments).expression, questionDotToken, (expression as ExpressionWithTypeArguments).typeArguments) : - parseTaggedTemplateRest(pos, expression, questionDotToken, /*typeArguments*/ undefined); + expression = !questionDotToken && expression.kind === SyntaxKind.ExpressionWithTypeArguments + ? parseTaggedTemplateRest( + pos, + (expression as ExpressionWithTypeArguments).expression, + questionDotToken, + (expression as ExpressionWithTypeArguments).typeArguments, + ) + : parseTaggedTemplateRest(pos, expression, questionDotToken, /*typeArguments*/ undefined); continue; } @@ -6443,13 +7748,18 @@ namespace Parser { return token() === SyntaxKind.NoSubstitutionTemplateLiteral || token() === SyntaxKind.TemplateHead; } - function parseTaggedTemplateRest(pos: number, tag: LeftHandSideExpression, questionDotToken: QuestionDotToken | undefined, typeArguments: NodeArray | undefined) { + function parseTaggedTemplateRest( + pos: number, + tag: LeftHandSideExpression, + questionDotToken: QuestionDotToken | undefined, + typeArguments: NodeArray | undefined, + ) { const tagExpression = factory.createTaggedTemplateExpression( tag, typeArguments, - token() === SyntaxKind.NoSubstitutionTemplateLiteral ? - (reScanTemplateToken(/*isTaggedTemplate*/ true), parseLiteralNode() as NoSubstitutionTemplateLiteral) : - parseTemplateExpression(/*isTaggedTemplate*/ true), + token() === SyntaxKind.NoSubstitutionTemplateLiteral + ? (reScanTemplateToken(/*isTaggedTemplate*/ true), parseLiteralNode() as NoSubstitutionTemplateLiteral) + : parseTemplateExpression(/*isTaggedTemplate*/ true), ); if (questionDotToken || tag.flags & NodeFlags.OptionalChain) { (tagExpression as Mutable).flags |= NodeFlags.OptionalChain; @@ -6477,15 +7787,19 @@ namespace Parser { expression = (expression as ExpressionWithTypeArguments).expression; } const argumentList = parseArgumentList(); - const callExpr = questionDotToken || tryReparseOptionalChain(expression) ? - factoryCreateCallChain(expression, questionDotToken, typeArguments, argumentList) : - factoryCreateCallExpression(expression, typeArguments, argumentList); + const callExpr = questionDotToken || tryReparseOptionalChain(expression) + ? factoryCreateCallChain(expression, questionDotToken, typeArguments, argumentList) + : factoryCreateCallExpression(expression, typeArguments, argumentList); expression = finishNode(callExpr, pos); continue; } if (questionDotToken) { // We parsed `?.` but then failed to parse anything, so report a missing identifier here. - const name = createMissingNode(SyntaxKind.Identifier, /*reportAtCurrentPosition*/ false, Diagnostics.Identifier_expected); + const name = createMissingNode( + SyntaxKind.Identifier, + /*reportAtCurrentPosition*/ false, + Diagnostics.Identifier_expected, + ); expression = finishNode(factoryCreatePropertyAccessChain(expression, questionDotToken, name), pos); } break; @@ -6618,9 +7932,9 @@ namespace Parser { } function parseArgumentOrArrayLiteralElement(): Expression { - return token() === SyntaxKind.DotDotDotToken ? parseSpreadElement() : - token() === SyntaxKind.CommaToken ? finishNode(factory.createOmittedExpression(), getNodePos()) : - parseAssignmentExpressionOrHigher(/*allowReturnTypeInArrowFunction*/ true); + return token() === SyntaxKind.DotDotDotToken ? parseSpreadElement() + : token() === SyntaxKind.CommaToken ? finishNode(factory.createOmittedExpression(), getNodePos()) + : parseAssignmentExpressionOrHigher(/*allowReturnTypeInArrowFunction*/ true); } function parseArgumentExpression(): Expression { @@ -6633,7 +7947,12 @@ namespace Parser { const openBracketParsed = parseExpected(SyntaxKind.OpenBracketToken); const multiLine = scanner.hasPrecedingLineBreak(); const elements = parseDelimitedList(ParsingContext.ArrayLiteralMembers, parseArgumentOrArrayLiteralElement); - parseExpectedMatchingBrackets(SyntaxKind.OpenBracketToken, SyntaxKind.CloseBracketToken, openBracketParsed, openBracketPosition); + parseExpectedMatchingBrackets( + SyntaxKind.OpenBracketToken, + SyntaxKind.CloseBracketToken, + openBracketParsed, + openBracketPosition, + ); return finishNode(factoryCreateArrayLiteralExpression(elements, multiLine), pos); } @@ -6663,7 +7982,15 @@ namespace Parser { const exclamationToken = parseOptionalToken(SyntaxKind.ExclamationToken); if (asteriskToken || token() === SyntaxKind.OpenParenToken || token() === SyntaxKind.LessThanToken) { - return parseMethodDeclaration(pos, hasJSDoc, modifiers, asteriskToken, name, questionToken, exclamationToken); + return parseMethodDeclaration( + pos, + hasJSDoc, + modifiers, + asteriskToken, + name, + questionToken, + exclamationToken, + ); } // check if it is short-hand property assignment or normal property assignment @@ -6675,7 +8002,9 @@ namespace Parser { const isShorthandPropertyAssignment = tokenIsIdentifier && (token() !== SyntaxKind.ColonToken); if (isShorthandPropertyAssignment) { const equalsToken = parseOptionalToken(SyntaxKind.EqualsToken); - const objectAssignmentInitializer = equalsToken ? allowInAnd(() => parseAssignmentExpressionOrHigher(/*allowReturnTypeInArrowFunction*/ true)) : undefined; + const objectAssignmentInitializer = equalsToken ? allowInAnd(() => + parseAssignmentExpressionOrHigher(/*allowReturnTypeInArrowFunction*/ true) + ) : undefined; node = factory.createShorthandPropertyAssignment(name as Identifier, objectAssignmentInitializer); // Save equals token for error reporting. // TODO(rbuckton): Consider manufacturing this when we need to report an error as it is otherwise not useful. @@ -6683,7 +8012,9 @@ namespace Parser { } else { parseExpected(SyntaxKind.ColonToken); - const initializer = allowInAnd(() => parseAssignmentExpressionOrHigher(/*allowReturnTypeInArrowFunction*/ true)); + const initializer = allowInAnd(() => + parseAssignmentExpressionOrHigher(/*allowReturnTypeInArrowFunction*/ true) + ); node = factory.createPropertyAssignment(name, initializer); } // Decorators, Modifiers, questionToken, and exclamationToken are not supported by property assignments and are reported in the grammar checker @@ -6698,8 +8029,17 @@ namespace Parser { const openBracePosition = scanner.getTokenStart(); const openBraceParsed = parseExpected(SyntaxKind.OpenBraceToken); const multiLine = scanner.hasPrecedingLineBreak(); - const properties = parseDelimitedList(ParsingContext.ObjectLiteralMembers, parseObjectLiteralElement, /*considerSemicolonAsDelimiter*/ true); - parseExpectedMatchingBrackets(SyntaxKind.OpenBraceToken, SyntaxKind.CloseBraceToken, openBraceParsed, openBracePosition); + const properties = parseDelimitedList( + ParsingContext.ObjectLiteralMembers, + parseObjectLiteralElement, + /*considerSemicolonAsDelimiter*/ true, + ); + parseExpectedMatchingBrackets( + SyntaxKind.OpenBraceToken, + SyntaxKind.CloseBraceToken, + openBraceParsed, + openBracePosition, + ); return finishNode(factoryCreateObjectLiteralExpression(properties, multiLine), pos); } @@ -6719,10 +8059,10 @@ namespace Parser { const asteriskToken = parseOptionalToken(SyntaxKind.AsteriskToken); const isGenerator = asteriskToken ? SignatureFlags.Yield : SignatureFlags.None; const isAsync = some(modifiers, isAsyncModifier) ? SignatureFlags.Await : SignatureFlags.None; - const name = isGenerator && isAsync ? doInYieldAndAwaitContext(parseOptionalBindingIdentifier) : - isGenerator ? doInYieldContext(parseOptionalBindingIdentifier) : - isAsync ? doInAwaitContext(parseOptionalBindingIdentifier) : - parseOptionalBindingIdentifier(); + const name = isGenerator && isAsync ? doInYieldAndAwaitContext(parseOptionalBindingIdentifier) + : isGenerator ? doInYieldContext(parseOptionalBindingIdentifier) + : isAsync ? doInAwaitContext(parseOptionalBindingIdentifier) + : parseOptionalBindingIdentifier(); const typeParameters = parseTypeParameters(); const parameters = parseParameters(isGenerator | isAsync); @@ -6731,7 +8071,15 @@ namespace Parser { setDecoratorContext(savedDecoratorContext); - const node = factory.createFunctionExpression(modifiers, asteriskToken, name, typeParameters, parameters, type, body); + const node = factory.createFunctionExpression( + modifiers, + asteriskToken, + name, + typeParameters, + parameters, + type, + body, + ); return withJSDoc(finishNode(node, pos), hasJSDoc); } @@ -6747,7 +8095,11 @@ namespace Parser { return finishNode(factory.createMetaProperty(SyntaxKind.NewKeyword, name), pos); } const expressionPos = getNodePos(); - let expression: LeftHandSideExpression = parseMemberExpressionRest(expressionPos, parsePrimaryExpression(), /*allowOptionalChain*/ false); + let expression: LeftHandSideExpression = parseMemberExpressionRest( + expressionPos, + parsePrimaryExpression(), + /*allowOptionalChain*/ false, + ); let typeArguments: NodeArray | undefined; // Absorb type arguments into NewExpression when preceding expression is ExpressionWithTypeArguments if (expression.kind === SyntaxKind.ExpressionWithTypeArguments) { @@ -6755,7 +8107,10 @@ namespace Parser { expression = (expression as ExpressionWithTypeArguments).expression; } if (token() === SyntaxKind.QuestionDotToken) { - parseErrorAtCurrentToken(Diagnostics.Invalid_optional_chain_from_new_expression_Did_you_mean_to_call_0, getTextOfNodeFromSourceText(sourceText, expression)); + parseErrorAtCurrentToken( + Diagnostics.Invalid_optional_chain_from_new_expression_Did_you_mean_to_call_0, + getTextOfNodeFromSourceText(sourceText, expression), + ); } const argumentList = token() === SyntaxKind.OpenParenToken ? parseArgumentList() : undefined; return finishNode(factoryCreateNewExpression(expression, typeArguments, argumentList), pos); @@ -6770,10 +8125,18 @@ namespace Parser { if (openBraceParsed || ignoreMissingOpenBrace) { const multiLine = scanner.hasPrecedingLineBreak(); const statements = parseList(ParsingContext.BlockStatements, parseStatement); - parseExpectedMatchingBrackets(SyntaxKind.OpenBraceToken, SyntaxKind.CloseBraceToken, openBraceParsed, openBracePosition); + parseExpectedMatchingBrackets( + SyntaxKind.OpenBraceToken, + SyntaxKind.CloseBraceToken, + openBraceParsed, + openBracePosition, + ); const result = withJSDoc(finishNode(factoryCreateBlock(statements, multiLine), pos), hasJSDoc); if (token() === SyntaxKind.EqualsToken) { - parseErrorAtCurrentToken(Diagnostics.Declaration_or_statement_expected_This_follows_a_block_of_statements_so_if_you_intended_to_write_a_destructuring_assignment_you_might_need_to_wrap_the_whole_assignment_in_parentheses); + parseErrorAtCurrentToken( + Diagnostics + .Declaration_or_statement_expected_This_follows_a_block_of_statements_so_if_you_intended_to_write_a_destructuring_assignment_you_might_need_to_wrap_the_whole_assignment_in_parentheses, + ); nextToken(); } @@ -6829,7 +8192,12 @@ namespace Parser { const openParenPosition = scanner.getTokenStart(); const openParenParsed = parseExpected(SyntaxKind.OpenParenToken); const expression = allowInAnd(parseExpression); - parseExpectedMatchingBrackets(SyntaxKind.OpenParenToken, SyntaxKind.CloseParenToken, openParenParsed, openParenPosition); + parseExpectedMatchingBrackets( + SyntaxKind.OpenParenToken, + SyntaxKind.CloseParenToken, + openParenParsed, + openParenPosition, + ); const thenStatement = parseStatement(); const elseStatement = parseOptional(SyntaxKind.ElseKeyword) ? parseStatement() : undefined; return withJSDoc(finishNode(factoryCreateIfStatement(expression, thenStatement, elseStatement), pos), hasJSDoc); @@ -6844,7 +8212,12 @@ namespace Parser { const openParenPosition = scanner.getTokenStart(); const openParenParsed = parseExpected(SyntaxKind.OpenParenToken); const expression = allowInAnd(parseExpression); - parseExpectedMatchingBrackets(SyntaxKind.OpenParenToken, SyntaxKind.CloseParenToken, openParenParsed, openParenPosition); + parseExpectedMatchingBrackets( + SyntaxKind.OpenParenToken, + SyntaxKind.CloseParenToken, + openParenParsed, + openParenPosition, + ); // From: https://mail.mozilla.org/pipermail/es-discuss/2011-August/016188.html // 157 min --- All allen at wirfs-brock.com CONF --- "do{;}while(false)false" prohibited in @@ -6861,7 +8234,12 @@ namespace Parser { const openParenPosition = scanner.getTokenStart(); const openParenParsed = parseExpected(SyntaxKind.OpenParenToken); const expression = allowInAnd(parseExpression); - parseExpectedMatchingBrackets(SyntaxKind.OpenParenToken, SyntaxKind.CloseParenToken, openParenParsed, openParenPosition); + parseExpectedMatchingBrackets( + SyntaxKind.OpenParenToken, + SyntaxKind.CloseParenToken, + openParenParsed, + openParenPosition, + ); const statement = parseStatement(); return withJSDoc(finishNode(factoryCreateWhileStatement(expression, statement), pos), hasJSDoc); } @@ -6876,9 +8254,14 @@ namespace Parser { let initializer!: VariableDeclarationList | Expression; if (token() !== SyntaxKind.SemicolonToken) { if ( - token() === SyntaxKind.VarKeyword || token() === SyntaxKind.LetKeyword || token() === SyntaxKind.ConstKeyword || - token() === SyntaxKind.UsingKeyword && lookAhead(nextTokenIsBindingIdentifierOrStartOfDestructuringOnSameLineDisallowOf) || - token() === SyntaxKind.AwaitKeyword && lookAhead(nextTokenIsUsingKeywordThenBindingIdentifierOrStartOfObjectDestructuringOnSameLineDisallowOf) + token() === SyntaxKind.VarKeyword || token() === SyntaxKind.LetKeyword + || token() === SyntaxKind.ConstKeyword + || token() === SyntaxKind.UsingKeyword + && lookAhead(nextTokenIsBindingIdentifierOrStartOfDestructuringOnSameLineDisallowOf) + || token() === SyntaxKind.AwaitKeyword + && lookAhead( + nextTokenIsUsingKeywordThenBindingIdentifierOrStartOfObjectDestructuringOnSameLineDisallowOf, + ) ) { initializer = parseVariableDeclarationList(/*inForStatementInitializer*/ true); } @@ -6889,7 +8272,9 @@ namespace Parser { let node: IterationStatement; if (awaitToken ? parseExpected(SyntaxKind.OfKeyword) : parseOptional(SyntaxKind.OfKeyword)) { - const expression = allowInAnd(() => parseAssignmentExpressionOrHigher(/*allowReturnTypeInArrowFunction*/ true)); + const expression = allowInAnd(() => + parseAssignmentExpressionOrHigher(/*allowReturnTypeInArrowFunction*/ true) + ); parseExpected(SyntaxKind.CloseParenToken); node = factoryCreateForOfStatement(awaitToken, initializer, expression, parseStatement()); } @@ -6944,7 +8329,12 @@ namespace Parser { const openParenPosition = scanner.getTokenStart(); const openParenParsed = parseExpected(SyntaxKind.OpenParenToken); const expression = allowInAnd(parseExpression); - parseExpectedMatchingBrackets(SyntaxKind.OpenParenToken, SyntaxKind.CloseParenToken, openParenParsed, openParenPosition); + parseExpectedMatchingBrackets( + SyntaxKind.OpenParenToken, + SyntaxKind.CloseParenToken, + openParenParsed, + openParenPosition, + ); const statement = doInsideOfContext(NodeFlags.InWithStatement, parseStatement); return withJSDoc(finishNode(factory.createWithStatement(expression, statement), pos), hasJSDoc); } @@ -7102,7 +8492,9 @@ namespace Parser { function nextTokenIsIdentifierOrKeywordOrLiteralOnSameLine() { nextToken(); - return (tokenIsIdentifierOrKeyword(token()) || token() === SyntaxKind.NumericLiteral || token() === SyntaxKind.BigIntLiteral || token() === SyntaxKind.StringLiteral) && !scanner.hasPrecedingLineBreak(); + return (tokenIsIdentifierOrKeyword(token()) || token() === SyntaxKind.NumericLiteral + || token() === SyntaxKind.BigIntLiteral || token() === SyntaxKind.StringLiteral) + && !scanner.hasPrecedingLineBreak(); } function isDeclaration(): boolean { @@ -7170,21 +8562,22 @@ namespace Parser { case SyntaxKind.GlobalKeyword: nextToken(); - return token() === SyntaxKind.OpenBraceToken || token() === SyntaxKind.Identifier || token() === SyntaxKind.ExportKeyword; + return token() === SyntaxKind.OpenBraceToken || token() === SyntaxKind.Identifier + || token() === SyntaxKind.ExportKeyword; case SyntaxKind.ImportKeyword: nextToken(); - return token() === SyntaxKind.StringLiteral || token() === SyntaxKind.AsteriskToken || - token() === SyntaxKind.OpenBraceToken || tokenIsIdentifierOrKeyword(token()); + return token() === SyntaxKind.StringLiteral || token() === SyntaxKind.AsteriskToken + || token() === SyntaxKind.OpenBraceToken || tokenIsIdentifierOrKeyword(token()); case SyntaxKind.ExportKeyword: let currentToken = nextToken(); if (currentToken === SyntaxKind.TypeKeyword) { currentToken = lookAhead(nextToken); } if ( - currentToken === SyntaxKind.EqualsToken || currentToken === SyntaxKind.AsteriskToken || - currentToken === SyntaxKind.OpenBraceToken || currentToken === SyntaxKind.DefaultKeyword || - currentToken === SyntaxKind.AsKeyword || currentToken === SyntaxKind.AtToken + currentToken === SyntaxKind.EqualsToken || currentToken === SyntaxKind.AsteriskToken + || currentToken === SyntaxKind.OpenBraceToken || currentToken === SyntaxKind.DefaultKeyword + || currentToken === SyntaxKind.AsKeyword || currentToken === SyntaxKind.AtToken ) { return true; } @@ -7268,7 +8661,8 @@ namespace Parser { function nextTokenIsBindingIdentifierOrStartOfDestructuring() { nextToken(); - return isBindingIdentifier() || token() === SyntaxKind.OpenBraceToken || token() === SyntaxKind.OpenBracketToken; + return isBindingIdentifier() || token() === SyntaxKind.OpenBraceToken + || token() === SyntaxKind.OpenBracketToken; } function isLetDeclaration() { @@ -7434,7 +8828,11 @@ namespace Parser { }); } - function parseDeclarationWorker(pos: number, hasJSDoc: boolean, modifiersIn: NodeArray | undefined): Statement { + function parseDeclarationWorker( + pos: number, + hasJSDoc: boolean, + modifiersIn: NodeArray | undefined, + ): Statement { switch (token()) { case SyntaxKind.VarKeyword: case SyntaxKind.LetKeyword: @@ -7473,7 +8871,11 @@ namespace Parser { if (modifiersIn) { // We reached this point because we encountered decorators and/or modifiers and assumed a declaration // would follow. For recovery and error reporting purposes, return an incomplete declaration. - const missing = createMissingNode(SyntaxKind.MissingDeclaration, /*reportAtCurrentPosition*/ true, Diagnostics.Declaration_expected); + const missing = createMissingNode( + SyntaxKind.MissingDeclaration, + /*reportAtCurrentPosition*/ true, + Diagnostics.Declaration_expected, + ); setTextRangePos(missing, pos); (missing as Mutable).modifiers = modifiersIn; return missing; @@ -7490,7 +8892,10 @@ namespace Parser { return !scanner.hasPrecedingLineBreak() && (isIdentifier() || token() === SyntaxKind.StringLiteral); } - function parseFunctionBlockOrSemicolon(flags: SignatureFlags, diagnosticMessage?: DiagnosticMessage): Block | undefined { + function parseFunctionBlockOrSemicolon( + flags: SignatureFlags, + diagnosticMessage?: DiagnosticMessage, + ): Block | undefined { if (token() !== SyntaxKind.OpenBraceToken) { if (flags & SignatureFlags.Type) { parseTypeMemberSemicolon(); @@ -7514,7 +8919,10 @@ namespace Parser { const dotDotDotToken = parseOptionalToken(SyntaxKind.DotDotDotToken); const name = parseIdentifierOrPattern(); const initializer = parseInitializer(); - return finishNode(factory.createBindingElement(dotDotDotToken, /*propertyName*/ undefined, name, initializer), pos); + return finishNode( + factory.createBindingElement(dotDotDotToken, /*propertyName*/ undefined, name, initializer), + pos, + ); } function parseObjectBindingElement(): BindingElement { @@ -7538,7 +8946,9 @@ namespace Parser { function parseObjectBindingPattern(): ObjectBindingPattern { const pos = getNodePos(); parseExpected(SyntaxKind.OpenBraceToken); - const elements = allowInAnd(() => parseDelimitedList(ParsingContext.ObjectBindingElements, parseObjectBindingElement)); + const elements = allowInAnd(() => + parseDelimitedList(ParsingContext.ObjectBindingElements, parseObjectBindingElement) + ); parseExpected(SyntaxKind.CloseBraceToken); return finishNode(factory.createObjectBindingPattern(elements), pos); } @@ -7546,7 +8956,9 @@ namespace Parser { function parseArrayBindingPattern(): ArrayBindingPattern { const pos = getNodePos(); parseExpected(SyntaxKind.OpenBracketToken); - const elements = allowInAnd(() => parseDelimitedList(ParsingContext.ArrayBindingElements, parseArrayBindingElement)); + const elements = allowInAnd(() => + parseDelimitedList(ParsingContext.ArrayBindingElements, parseArrayBindingElement) + ); parseExpected(SyntaxKind.CloseBracketToken); return finishNode(factory.createArrayBindingPattern(elements), pos); } @@ -7558,7 +8970,9 @@ namespace Parser { || isBindingIdentifier(); } - function parseIdentifierOrPattern(privateIdentifierDiagnosticMessage?: DiagnosticMessage): Identifier | BindingPattern { + function parseIdentifierOrPattern( + privateIdentifierDiagnosticMessage?: DiagnosticMessage, + ): Identifier | BindingPattern { if (token() === SyntaxKind.OpenBracketToken) { return parseArrayBindingPattern(); } @@ -7578,8 +8992,8 @@ namespace Parser { const name = parseIdentifierOrPattern(Diagnostics.Private_identifiers_are_not_allowed_in_variable_declarations); let exclamationToken: ExclamationToken | undefined; if ( - allowExclamation && name.kind === SyntaxKind.Identifier && - token() === SyntaxKind.ExclamationToken && !scanner.hasPrecedingLineBreak() + allowExclamation && name.kind === SyntaxKind.Identifier + && token() === SyntaxKind.ExclamationToken && !scanner.hasPrecedingLineBreak() ) { exclamationToken = parseTokenNode>(); } @@ -7633,7 +9047,10 @@ namespace Parser { const savedDisallowIn = inDisallowInContext(); setDisallowInContext(inForStatementInitializer); - declarations = parseDelimitedList(ParsingContext.VariableDeclarations, inForStatementInitializer ? parseVariableDeclaration : parseVariableDeclarationAllowExclamation); + declarations = parseDelimitedList( + ParsingContext.VariableDeclarations, + inForStatementInitializer ? parseVariableDeclaration : parseVariableDeclarationAllowExclamation, + ); setDisallowInContext(savedDisallowIn); } @@ -7645,20 +9062,29 @@ namespace Parser { return nextTokenIsIdentifier() && nextToken() === SyntaxKind.CloseParenToken; } - function parseVariableStatement(pos: number, hasJSDoc: boolean, modifiers: NodeArray | undefined): VariableStatement { + function parseVariableStatement( + pos: number, + hasJSDoc: boolean, + modifiers: NodeArray | undefined, + ): VariableStatement { const declarationList = parseVariableDeclarationList(/*inForStatementInitializer*/ false); parseSemicolon(); const node = factoryCreateVariableStatement(modifiers, declarationList); return withJSDoc(finishNode(node, pos), hasJSDoc); } - function parseFunctionDeclaration(pos: number, hasJSDoc: boolean, modifiers: NodeArray | undefined): FunctionDeclaration { + function parseFunctionDeclaration( + pos: number, + hasJSDoc: boolean, + modifiers: NodeArray | undefined, + ): FunctionDeclaration { const savedAwaitContext = inAwaitContext(); const modifierFlags = modifiersToFlags(modifiers); parseExpected(SyntaxKind.FunctionKeyword); const asteriskToken = parseOptionalToken(SyntaxKind.AsteriskToken); // We don't parse the name here in await context, instead we will report a grammar error in the checker. - const name = modifierFlags & ModifierFlags.Default ? parseOptionalBindingIdentifier() : parseBindingIdentifier(); + const name = modifierFlags & ModifierFlags.Default ? parseOptionalBindingIdentifier() + : parseBindingIdentifier(); const isGenerator = asteriskToken ? SignatureFlags.Yield : SignatureFlags.None; const isAsync = modifierFlags & ModifierFlags.Async ? SignatureFlags.Await : SignatureFlags.None; const typeParameters = parseTypeParameters(); @@ -7667,7 +9093,15 @@ namespace Parser { const type = parseReturnType(SyntaxKind.ColonToken, /*isType*/ false); const body = parseFunctionBlockOrSemicolon(isGenerator | isAsync, Diagnostics.or_expected); setAwaitContext(savedAwaitContext); - const node = factory.createFunctionDeclaration(modifiers, asteriskToken, name, typeParameters, parameters, type, body); + const node = factory.createFunctionDeclaration( + modifiers, + asteriskToken, + name, + typeParameters, + parameters, + type, + body, + ); return withJSDoc(finishNode(node, pos), hasJSDoc); } @@ -7683,7 +9117,11 @@ namespace Parser { } } - function tryParseConstructorDeclaration(pos: number, hasJSDoc: boolean, modifiers: NodeArray | undefined): ConstructorDeclaration | undefined { + function tryParseConstructorDeclaration( + pos: number, + hasJSDoc: boolean, + modifiers: NodeArray | undefined, + ): ConstructorDeclaration | undefined { return tryParse(() => { if (parseConstructorName()) { const typeParameters = parseTypeParameters(); @@ -7739,9 +9177,13 @@ namespace Parser { name: PropertyName, questionToken: QuestionToken | undefined, ): PropertyDeclaration { - const exclamationToken = !questionToken && !scanner.hasPrecedingLineBreak() ? parseOptionalToken(SyntaxKind.ExclamationToken) : undefined; + const exclamationToken = !questionToken && !scanner.hasPrecedingLineBreak() + ? parseOptionalToken(SyntaxKind.ExclamationToken) : undefined; const type = parseTypeAnnotation(); - const initializer = doOutsideOfContext(NodeFlags.YieldContext | NodeFlags.AwaitContext | NodeFlags.DisallowInContext, parseInitializer); + const initializer = doOutsideOfContext( + NodeFlags.YieldContext | NodeFlags.AwaitContext | NodeFlags.DisallowInContext, + parseInitializer, + ); parseSemicolonAfterPropertyName(name, type, initializer); const node = factory.createPropertyDeclaration( modifiers, @@ -7764,12 +9206,27 @@ namespace Parser { // report an error in the grammar checker. const questionToken = parseOptionalToken(SyntaxKind.QuestionToken); if (asteriskToken || token() === SyntaxKind.OpenParenToken || token() === SyntaxKind.LessThanToken) { - return parseMethodDeclaration(pos, hasJSDoc, modifiers, asteriskToken, name, questionToken, /*exclamationToken*/ undefined, Diagnostics.or_expected); + return parseMethodDeclaration( + pos, + hasJSDoc, + modifiers, + asteriskToken, + name, + questionToken, + /*exclamationToken*/ undefined, + Diagnostics.or_expected, + ); } return parsePropertyDeclaration(pos, hasJSDoc, modifiers, name, questionToken); } - function parseAccessorDeclaration(pos: number, hasJSDoc: boolean, modifiers: NodeArray | undefined, kind: AccessorDeclaration["kind"], flags: SignatureFlags): AccessorDeclaration { + function parseAccessorDeclaration( + pos: number, + hasJSDoc: boolean, + modifiers: NodeArray | undefined, + kind: AccessorDeclaration["kind"], + flags: SignatureFlags, + ): AccessorDeclaration { const name = parsePropertyName(); const typeParameters = parseTypeParameters(); const parameters = parseParameters(SignatureFlags.None); @@ -7853,7 +9310,11 @@ namespace Parser { return false; } - function parseClassStaticBlockDeclaration(pos: number, hasJSDoc: boolean, modifiers: NodeArray | undefined): ClassStaticBlockDeclaration { + function parseClassStaticBlockDeclaration( + pos: number, + hasJSDoc: boolean, + modifiers: NodeArray | undefined, + ): ClassStaticBlockDeclaration { parseExpectedToken(SyntaxKind.StaticKeyword); const body = parseClassStaticBlockBody(); const node = withJSDoc(finishNode(factory.createClassStaticBlockDeclaration(body), pos), hasJSDoc); @@ -7898,7 +9359,11 @@ namespace Parser { return finishNode(factory.createDecorator(expression), pos); } - function tryParseModifier(hasSeenStaticModifier: boolean, permitConstAsModifier?: boolean, stopOnStartOfClassStaticBlock?: boolean): Modifier | undefined { + function tryParseModifier( + hasSeenStaticModifier: boolean, + permitConstAsModifier?: boolean, + stopOnStartOfClassStaticBlock?: boolean, + ): Modifier | undefined { const pos = getNodePos(); const kind = token(); @@ -7909,7 +9374,9 @@ namespace Parser { return undefined; } } - else if (stopOnStartOfClassStaticBlock && token() === SyntaxKind.StaticKeyword && lookAhead(nextTokenIsOpenBrace)) { + else if ( + stopOnStartOfClassStaticBlock && token() === SyntaxKind.StaticKeyword && lookAhead(nextTokenIsOpenBrace) + ) { return undefined; } else if (hasSeenStaticModifier && token() === SyntaxKind.StaticKeyword) { @@ -7931,12 +9398,28 @@ namespace Parser { * * In such situations, 'permitConstAsModifier' should be set to true. */ - function parseModifiers(allowDecorators: false, permitConstAsModifier?: boolean, stopOnStartOfClassStaticBlock?: boolean): NodeArray | undefined; - function parseModifiers(allowDecorators: true, permitConstAsModifier?: boolean, stopOnStartOfClassStaticBlock?: boolean): NodeArray | undefined; - function parseModifiers(allowDecorators: boolean, permitConstAsModifier?: boolean, stopOnStartOfClassStaticBlock?: boolean): NodeArray | undefined { + function parseModifiers( + allowDecorators: false, + permitConstAsModifier?: boolean, + stopOnStartOfClassStaticBlock?: boolean, + ): NodeArray | undefined; + function parseModifiers( + allowDecorators: true, + permitConstAsModifier?: boolean, + stopOnStartOfClassStaticBlock?: boolean, + ): NodeArray | undefined; + function parseModifiers( + allowDecorators: boolean, + permitConstAsModifier?: boolean, + stopOnStartOfClassStaticBlock?: boolean, + ): NodeArray | undefined { const pos = getNodePos(); let list: ModifierLike[] | undefined; - let decorator, modifier, hasSeenStaticModifier = false, hasLeadingModifier = false, hasTrailingDecorator = false; + let decorator, + modifier, + hasSeenStaticModifier = false, + hasLeadingModifier = false, + hasTrailingDecorator = false; // Decorators should be contiguous in a list of modifiers but can potentially appear in two places (i.e., `[...leadingDecorators, ...leadingModifiers, ...trailingDecorators, ...trailingModifiers]`). // The leading modifiers *should* only contain `export` and `default` when trailingDecorators are present, but we'll handle errors for any other leading modifiers in the checker. @@ -7950,7 +9433,9 @@ namespace Parser { } // parse leading modifiers - while (modifier = tryParseModifier(hasSeenStaticModifier, permitConstAsModifier, stopOnStartOfClassStaticBlock)) { + while ( + modifier = tryParseModifier(hasSeenStaticModifier, permitConstAsModifier, stopOnStartOfClassStaticBlock) + ) { if (modifier.kind === SyntaxKind.StaticKeyword) hasSeenStaticModifier = true; list = append(list, modifier); hasLeadingModifier = true; @@ -7966,7 +9451,9 @@ namespace Parser { // parse trailing modifiers, but only if we parsed any trailing decorators if (hasTrailingDecorator) { - while (modifier = tryParseModifier(hasSeenStaticModifier, permitConstAsModifier, stopOnStartOfClassStaticBlock)) { + while ( + modifier = tryParseModifier(hasSeenStaticModifier, permitConstAsModifier, stopOnStartOfClassStaticBlock) + ) { if (modifier.kind === SyntaxKind.StaticKeyword) hasSeenStaticModifier = true; list = append(list, modifier); } @@ -7994,7 +9481,11 @@ namespace Parser { return withJSDoc(finishNode(factory.createSemicolonClassElement(), pos), hasJSDoc); } - const modifiers = parseModifiers(/*allowDecorators*/ true, /*permitConstAsModifier*/ true, /*stopOnStartOfClassStaticBlock*/ true); + const modifiers = parseModifiers( + /*allowDecorators*/ true, + /*permitConstAsModifier*/ true, + /*stopOnStartOfClassStaticBlock*/ true, + ); if (token() === SyntaxKind.StaticKeyword && lookAhead(nextTokenIsOpenBrace)) { return parseClassStaticBlockDeclaration(pos, hasJSDoc, modifiers); } @@ -8021,18 +9512,21 @@ namespace Parser { // It is very important that we check this *after* checking indexers because // the [ token can start an index signature or a computed property name if ( - tokenIsIdentifierOrKeyword(token()) || - token() === SyntaxKind.StringLiteral || - token() === SyntaxKind.NumericLiteral || - token() === SyntaxKind.AsteriskToken || - token() === SyntaxKind.OpenBracketToken + tokenIsIdentifierOrKeyword(token()) + || token() === SyntaxKind.StringLiteral + || token() === SyntaxKind.NumericLiteral + || token() === SyntaxKind.AsteriskToken + || token() === SyntaxKind.OpenBracketToken ) { const isAmbient = some(modifiers, isDeclareModifier); if (isAmbient) { for (const m of modifiers!) { (m as Mutable).flags |= NodeFlags.Ambient; } - return doInsideOfContext(NodeFlags.Ambient, () => parsePropertyOrMethodDeclaration(pos, hasJSDoc, modifiers)); + return doInsideOfContext( + NodeFlags.Ambient, + () => parsePropertyOrMethodDeclaration(pos, hasJSDoc, modifiers), + ); } else { return parsePropertyOrMethodDeclaration(pos, hasJSDoc, modifiers); @@ -8041,7 +9535,11 @@ namespace Parser { if (modifiers) { // treat this as a property declaration with a missing name. - const name = createMissingNode(SyntaxKind.Identifier, /*reportAtCurrentPosition*/ true, Diagnostics.Declaration_expected); + const name = createMissingNode( + SyntaxKind.Identifier, + /*reportAtCurrentPosition*/ true, + Diagnostics.Declaration_expected, + ); return parsePropertyDeclaration(pos, hasJSDoc, modifiers, name, /*questionToken*/ undefined); } @@ -8054,24 +9552,52 @@ namespace Parser { const hasJSDoc = hasPrecedingJSDocComment(); const modifiers = parseModifiers(/*allowDecorators*/ true); if (token() === SyntaxKind.ClassKeyword) { - return parseClassDeclarationOrExpression(pos, hasJSDoc, modifiers, SyntaxKind.ClassExpression) as ClassExpression; + return parseClassDeclarationOrExpression( + pos, + hasJSDoc, + modifiers, + SyntaxKind.ClassExpression, + ) as ClassExpression; } - const missing = createMissingNode(SyntaxKind.MissingDeclaration, /*reportAtCurrentPosition*/ true, Diagnostics.Expression_expected); + const missing = createMissingNode( + SyntaxKind.MissingDeclaration, + /*reportAtCurrentPosition*/ true, + Diagnostics.Expression_expected, + ); setTextRangePos(missing, pos); (missing as Mutable).modifiers = modifiers; return missing; } function parseClassExpression(): ClassExpression { - return parseClassDeclarationOrExpression(getNodePos(), hasPrecedingJSDocComment(), /*modifiers*/ undefined, SyntaxKind.ClassExpression) as ClassExpression; + return parseClassDeclarationOrExpression( + getNodePos(), + hasPrecedingJSDocComment(), + /*modifiers*/ undefined, + SyntaxKind.ClassExpression, + ) as ClassExpression; } - function parseClassDeclaration(pos: number, hasJSDoc: boolean, modifiers: NodeArray | undefined): ClassDeclaration { - return parseClassDeclarationOrExpression(pos, hasJSDoc, modifiers, SyntaxKind.ClassDeclaration) as ClassDeclaration; + function parseClassDeclaration( + pos: number, + hasJSDoc: boolean, + modifiers: NodeArray | undefined, + ): ClassDeclaration { + return parseClassDeclarationOrExpression( + pos, + hasJSDoc, + modifiers, + SyntaxKind.ClassDeclaration, + ) as ClassDeclaration; } - function parseClassDeclarationOrExpression(pos: number, hasJSDoc: boolean, modifiers: NodeArray | undefined, kind: ClassLikeDeclaration["kind"]): ClassLikeDeclaration { + function parseClassDeclarationOrExpression( + pos: number, + hasJSDoc: boolean, + modifiers: NodeArray | undefined, + kind: ClassLikeDeclaration["kind"], + ): ClassLikeDeclaration { const savedAwaitContext = inAwaitContext(); parseExpected(SyntaxKind.ClassKeyword); @@ -8144,8 +9670,13 @@ namespace Parser { } function tryParseTypeArguments(): NodeArray | undefined { - return token() === SyntaxKind.LessThanToken ? - parseBracketedList(ParsingContext.TypeArguments, parseType, SyntaxKind.LessThanToken, SyntaxKind.GreaterThanToken) : undefined; + return token() === SyntaxKind.LessThanToken + ? parseBracketedList( + ParsingContext.TypeArguments, + parseType, + SyntaxKind.LessThanToken, + SyntaxKind.GreaterThanToken, + ) : undefined; } function isHeritageClause(): boolean { @@ -8156,7 +9687,11 @@ namespace Parser { return parseList(ParsingContext.ClassMembers, parseClassElement); } - function parseInterfaceDeclaration(pos: number, hasJSDoc: boolean, modifiers: NodeArray | undefined): InterfaceDeclaration { + function parseInterfaceDeclaration( + pos: number, + hasJSDoc: boolean, + modifiers: NodeArray | undefined, + ): InterfaceDeclaration { parseExpected(SyntaxKind.InterfaceKeyword); const name = parseIdentifier(); const typeParameters = parseTypeParameters(); @@ -8166,7 +9701,11 @@ namespace Parser { return withJSDoc(finishNode(node, pos), hasJSDoc); } - function parseTypeAliasDeclaration(pos: number, hasJSDoc: boolean, modifiers: NodeArray | undefined): TypeAliasDeclaration { + function parseTypeAliasDeclaration( + pos: number, + hasJSDoc: boolean, + modifiers: NodeArray | undefined, + ): TypeAliasDeclaration { parseExpected(SyntaxKind.TypeKeyword); if (scanner.hasPrecedingLineBreak()) { parseErrorAtCurrentToken(Diagnostics.Line_break_not_permitted_here); @@ -8192,12 +9731,18 @@ namespace Parser { return withJSDoc(finishNode(factory.createEnumMember(name, initializer), pos), hasJSDoc); } - function parseEnumDeclaration(pos: number, hasJSDoc: boolean, modifiers: NodeArray | undefined): EnumDeclaration { + function parseEnumDeclaration( + pos: number, + hasJSDoc: boolean, + modifiers: NodeArray | undefined, + ): EnumDeclaration { parseExpected(SyntaxKind.EnumKeyword); const name = parseIdentifier(); let members; if (parseExpected(SyntaxKind.OpenBraceToken)) { - members = doOutsideOfYieldAndAwaitContext(() => parseDelimitedList(ParsingContext.EnumMembers, parseEnumMember)); + members = doOutsideOfYieldAndAwaitContext(() => + parseDelimitedList(ParsingContext.EnumMembers, parseEnumMember) + ); parseExpected(SyntaxKind.CloseBraceToken); } else { @@ -8220,19 +9765,33 @@ namespace Parser { return finishNode(factory.createModuleBlock(statements), pos); } - function parseModuleOrNamespaceDeclaration(pos: number, hasJSDoc: boolean, modifiers: NodeArray | undefined, flags: NodeFlags): ModuleDeclaration { + function parseModuleOrNamespaceDeclaration( + pos: number, + hasJSDoc: boolean, + modifiers: NodeArray | undefined, + flags: NodeFlags, + ): ModuleDeclaration { // If we are parsing a dotted namespace name, we want to // propagate the 'Namespace' flag across the names if set. const namespaceFlag = flags & NodeFlags.Namespace; const name = parseIdentifier(); const body = parseOptional(SyntaxKind.DotToken) - ? parseModuleOrNamespaceDeclaration(getNodePos(), /*hasJSDoc*/ false, /*modifiers*/ undefined, NodeFlags.NestedNamespace | namespaceFlag) as NamespaceDeclaration + ? parseModuleOrNamespaceDeclaration( + getNodePos(), + /*hasJSDoc*/ false, + /*modifiers*/ undefined, + NodeFlags.NestedNamespace | namespaceFlag, + ) as NamespaceDeclaration : parseModuleBlock(); const node = factory.createModuleDeclaration(modifiers, name, body, flags); return withJSDoc(finishNode(node, pos), hasJSDoc); } - function parseAmbientExternalModuleDeclaration(pos: number, hasJSDoc: boolean, modifiersIn: NodeArray | undefined): ModuleDeclaration { + function parseAmbientExternalModuleDeclaration( + pos: number, + hasJSDoc: boolean, + modifiersIn: NodeArray | undefined, + ): ModuleDeclaration { let flags: NodeFlags = 0; let name; if (token() === SyntaxKind.GlobalKeyword) { @@ -8255,7 +9814,11 @@ namespace Parser { return withJSDoc(finishNode(node, pos), hasJSDoc); } - function parseModuleDeclaration(pos: number, hasJSDoc: boolean, modifiersIn: NodeArray | undefined): ModuleDeclaration { + function parseModuleDeclaration( + pos: number, + hasJSDoc: boolean, + modifiersIn: NodeArray | undefined, + ): ModuleDeclaration { let flags: NodeFlags = 0; if (token() === SyntaxKind.GlobalKeyword) { // global augmentation @@ -8274,8 +9837,8 @@ namespace Parser { } function isExternalModuleReference() { - return token() === SyntaxKind.RequireKeyword && - lookAhead(nextTokenIsOpenParen); + return token() === SyntaxKind.RequireKeyword + && lookAhead(nextTokenIsOpenParen); } function nextTokenIsOpenParen() { @@ -8290,7 +9853,11 @@ namespace Parser { return nextToken() === SyntaxKind.SlashToken; } - function parseNamespaceExportDeclaration(pos: number, hasJSDoc: boolean, modifiers: NodeArray | undefined): NamespaceExportDeclaration { + function parseNamespaceExportDeclaration( + pos: number, + hasJSDoc: boolean, + modifiers: NodeArray | undefined, + ): NamespaceExportDeclaration { parseExpected(SyntaxKind.AsKeyword); parseExpected(SyntaxKind.NamespaceKeyword); const name = parseIdentifier(); @@ -8301,7 +9868,11 @@ namespace Parser { return withJSDoc(finishNode(node, pos), hasJSDoc); } - function parseImportDeclarationOrImportEqualsDeclaration(pos: number, hasJSDoc: boolean, modifiers: NodeArray | undefined): ImportEqualsDeclaration | ImportDeclaration { + function parseImportDeclarationOrImportEqualsDeclaration( + pos: number, + hasJSDoc: boolean, + modifiers: NodeArray | undefined, + ): ImportEqualsDeclaration | ImportDeclaration { parseExpected(SyntaxKind.ImportKeyword); const afterImportPos = scanner.getTokenFullStart(); @@ -8314,9 +9885,9 @@ namespace Parser { let isTypeOnly = false; if ( - token() !== SyntaxKind.FromKeyword && - identifier?.escapedText === "type" && - (isIdentifier() || tokenAfterImportDefinitelyProducesImportDeclaration()) + token() !== SyntaxKind.FromKeyword + && identifier?.escapedText === "type" + && (isIdentifier() || tokenAfterImportDefinitelyProducesImportDeclaration()) ) { isTypeOnly = true; identifier = isIdentifier() ? parseIdentifier() : undefined; @@ -8331,9 +9902,9 @@ namespace Parser { // import ModuleSpecifier; let importClause: ImportClause | undefined; if ( - identifier || // import id - token() === SyntaxKind.AsteriskToken || // import * - token() === SyntaxKind.OpenBraceToken // import { + identifier // import id + || token() === SyntaxKind.AsteriskToken // import * + || token() === SyntaxKind.OpenBraceToken // import { ) { importClause = parseImportClause(identifier, afterImportPos, isTypeOnly); parseExpected(SyntaxKind.FromKeyword); @@ -8352,7 +9923,8 @@ namespace Parser { function parseAssertEntry() { const pos = getNodePos(); - const name = tokenIsIdentifierOrKeyword(token()) ? parseIdentifierName() : parseLiteralLikeNode(SyntaxKind.StringLiteral) as StringLiteral; + const name = tokenIsIdentifierOrKeyword(token()) ? parseIdentifierName() + : parseLiteralLikeNode(SyntaxKind.StringLiteral) as StringLiteral; parseExpected(SyntaxKind.ColonToken); const value = parseAssignmentExpressionOrHigher(/*allowReturnTypeInArrowFunction*/ true); return finishNode(factory.createAssertEntry(name, value), pos); @@ -8366,13 +9938,24 @@ namespace Parser { const openBracePosition = scanner.getTokenStart(); if (parseExpected(SyntaxKind.OpenBraceToken)) { const multiLine = scanner.hasPrecedingLineBreak(); - const elements = parseDelimitedList(ParsingContext.AssertEntries, parseAssertEntry, /*considerSemicolonAsDelimiter*/ true); + const elements = parseDelimitedList( + ParsingContext.AssertEntries, + parseAssertEntry, + /*considerSemicolonAsDelimiter*/ true, + ); if (!parseExpected(SyntaxKind.CloseBraceToken)) { const lastError = lastOrUndefined(parseDiagnostics); if (lastError && lastError.code === Diagnostics._0_expected.code) { addRelatedInfo( lastError, - createDetachedDiagnostic(fileName, openBracePosition, 1, Diagnostics.The_parser_expected_to_find_a_1_to_match_the_0_token_here, "{", "}"), + createDetachedDiagnostic( + fileName, + openBracePosition, + 1, + Diagnostics.The_parser_expected_to_find_a_1_to_match_the_0_token_here, + "{", + "}", + ), ); } } @@ -8394,7 +9977,13 @@ namespace Parser { return token() === SyntaxKind.CommaToken || token() === SyntaxKind.FromKeyword; } - function parseImportEqualsDeclaration(pos: number, hasJSDoc: boolean, modifiers: NodeArray | undefined, identifier: Identifier, isTypeOnly: boolean): ImportEqualsDeclaration { + function parseImportEqualsDeclaration( + pos: number, + hasJSDoc: boolean, + modifiers: NodeArray | undefined, + identifier: Identifier, + isTypeOnly: boolean, + ): ImportEqualsDeclaration { parseExpected(SyntaxKind.EqualsToken); const moduleReference = parseModuleReference(); parseSemicolon(); @@ -8415,10 +10004,11 @@ namespace Parser { // parse namespace or named imports let namedBindings: NamespaceImport | NamedImports | undefined; if ( - !identifier || - parseOptional(SyntaxKind.CommaToken) + !identifier + || parseOptional(SyntaxKind.CommaToken) ) { - namedBindings = token() === SyntaxKind.AsteriskToken ? parseNamespaceImport() : parseNamedImportsOrExports(SyntaxKind.NamedImports); + namedBindings = token() === SyntaxKind.AsteriskToken ? parseNamespaceImport() + : parseNamedImportsOrExports(SyntaxKind.NamedImports); } return finishNode(factory.createImportClause(isTypeOnly, identifier, namedBindings), pos); @@ -8477,8 +10067,22 @@ namespace Parser { // ImportSpecifier // ImportsList, ImportSpecifier const node = kind === SyntaxKind.NamedImports - ? factory.createNamedImports(parseBracketedList(ParsingContext.ImportOrExportSpecifiers, parseImportSpecifier, SyntaxKind.OpenBraceToken, SyntaxKind.CloseBraceToken)) - : factory.createNamedExports(parseBracketedList(ParsingContext.ImportOrExportSpecifiers, parseExportSpecifier, SyntaxKind.OpenBraceToken, SyntaxKind.CloseBraceToken)); + ? factory.createNamedImports( + parseBracketedList( + ParsingContext.ImportOrExportSpecifiers, + parseImportSpecifier, + SyntaxKind.OpenBraceToken, + SyntaxKind.CloseBraceToken, + ), + ) + : factory.createNamedExports( + parseBracketedList( + ParsingContext.ImportOrExportSpecifiers, + parseExportSpecifier, + SyntaxKind.OpenBraceToken, + SyntaxKind.CloseBraceToken, + ), + ); return finishNode(node, pos); } @@ -8578,7 +10182,11 @@ namespace Parser { return finishNode(factory.createNamespaceExport(parseIdentifierName()), pos); } - function parseExportDeclaration(pos: number, hasJSDoc: boolean, modifiers: NodeArray | undefined): ExportDeclaration { + function parseExportDeclaration( + pos: number, + hasJSDoc: boolean, + modifiers: NodeArray | undefined, + ): ExportDeclaration { const savedAwaitContext = inAwaitContext(); setAwaitContext(/*value*/ true); let exportClause: NamedExportBindings | undefined; @@ -8598,7 +10206,10 @@ namespace Parser { // It is not uncommon to accidentally omit the 'from' keyword. Additionally, in editing scenarios, // the 'from' keyword can be parsed as a named export when the export clause is unterminated (i.e. `export { from "moduleName";`) // If we don't have a 'from' keyword, see if we have a string literal such that ASI won't take effect. - if (token() === SyntaxKind.FromKeyword || (token() === SyntaxKind.StringLiteral && !scanner.hasPrecedingLineBreak())) { + if ( + token() === SyntaxKind.FromKeyword + || (token() === SyntaxKind.StringLiteral && !scanner.hasPrecedingLineBreak()) + ) { parseExpected(SyntaxKind.FromKeyword); moduleSpecifier = parseModuleSpecifier(); } @@ -8608,11 +10219,21 @@ namespace Parser { } parseSemicolon(); setAwaitContext(savedAwaitContext); - const node = factory.createExportDeclaration(modifiers, isTypeOnly, exportClause, moduleSpecifier, assertClause); + const node = factory.createExportDeclaration( + modifiers, + isTypeOnly, + exportClause, + moduleSpecifier, + assertClause, + ); return withJSDoc(finishNode(node, pos), hasJSDoc); } - function parseExportAssignment(pos: number, hasJSDoc: boolean, modifiers: NodeArray | undefined): ExportAssignment { + function parseExportAssignment( + pos: number, + hasJSDoc: boolean, + modifiers: NodeArray | undefined, + ): ExportAssignment { const savedAwaitContext = inAwaitContext(); setAwaitContext(/*value*/ true); let isExportEquals: boolean | undefined; @@ -8666,13 +10287,26 @@ namespace Parser { } export namespace JSDocParser { - export function parseJSDocTypeExpressionForTests(content: string, start: number | undefined, length: number | undefined): { jsDocTypeExpression: JSDocTypeExpression; diagnostics: Diagnostic[]; } | undefined { + export function parseJSDocTypeExpressionForTests( + content: string, + start: number | undefined, + length: number | undefined, + ): { jsDocTypeExpression: JSDocTypeExpression; diagnostics: Diagnostic[]; } | undefined { initializeState("file.js", content, ScriptTarget.Latest, /*syntaxCursor*/ undefined, ScriptKind.JS); scanner.setText(content, start, length); currentToken = scanner.scan(); const jsDocTypeExpression = parseJSDocTypeExpression(); - const sourceFile = createSourceFile("file.js", ScriptTarget.Latest, ScriptKind.JS, /*isDeclarationFile*/ false, [], factoryCreateToken(SyntaxKind.EndOfFileToken), NodeFlags.None, noop); + const sourceFile = createSourceFile( + "file.js", + ScriptTarget.Latest, + ScriptKind.JS, + /*isDeclarationFile*/ false, + [], + factoryCreateToken(SyntaxKind.EndOfFileToken), + NodeFlags.None, + noop, + ); const diagnostics = attachFileToDiagnostics(parseDiagnostics, sourceFile); if (jsDocDiagnostics) { sourceFile.jsDocDiagnostics = attachFileToDiagnostics(jsDocDiagnostics, sourceFile); @@ -8716,7 +10350,11 @@ namespace Parser { return finishNode(result, pos); } - export function parseIsolatedJSDocComment(content: string, start: number | undefined, length: number | undefined): { jsDoc: JSDoc; diagnostics: Diagnostic[]; } | undefined { + export function parseIsolatedJSDocComment( + content: string, + start: number | undefined, + length: number | undefined, + ): { jsDoc: JSDoc; diagnostics: Diagnostic[]; } | undefined { initializeState("", content, ScriptTarget.Latest, /*syntaxCursor*/ undefined, ScriptKind.JS); const jsDoc = doInsideOfContext(NodeFlags.JSDoc, () => parseJSDocCommentWorker(start, length)); @@ -8845,7 +10483,10 @@ namespace Parser { } break; case SyntaxKind.WhitespaceTrivia: - Debug.assert(state !== JSDocState.SavingComments, "whitespace shouldn't come from the scanner while saving top-level comment text"); + Debug.assert( + state !== JSDocState.SavingComments, + "whitespace shouldn't come from the scanner while saving top-level comment text", + ); // only collect whitespace if we're already saving comments or have just crossed the comment indent margin const whitespace = scanner.getTokenText(); if (margin !== undefined && indent + whitespace.length > margin) { @@ -8868,7 +10509,13 @@ namespace Parser { if (!linkEnd) { removeLeadingNewlines(comments); } - parts.push(finishNode(factory.createJSDocText(comments.join("")), linkEnd ?? start, commentEnd)); + parts.push( + finishNode( + factory.createJSDocText(comments.join("")), + linkEnd ?? start, + commentEnd, + ), + ); parts.push(link); comments = []; linkEnd = scanner.getTokenEnd(); @@ -8894,9 +10541,22 @@ namespace Parser { if (parts.length && trimmedComments.length) { parts.push(finishNode(factory.createJSDocText(trimmedComments), linkEnd ?? start, commentsPos)); } - if (parts.length && tags) Debug.assertIsDefined(commentsPos, "having parsed tags implies that the end of the comment span should be set"); + if (parts.length && tags) { + Debug.assertIsDefined( + commentsPos, + "having parsed tags implies that the end of the comment span should be set", + ); + } const tagsArray = tags && createNodeArray(tags, tagsPos, tagsEnd); - return finishNode(factory.createJSDocComment(parts.length ? createNodeArray(parts, start, commentsPos) : trimmedComments.length ? trimmedComments : undefined, tagsArray), start, end); + return finishNode( + factory.createJSDocComment( + parts.length ? createNodeArray(parts, start, commentsPos) + : trimmedComments.length ? trimmedComments : undefined, + tagsArray, + ), + start, + end, + ); } function removeLeadingNewlines(comments: string[]) { @@ -8955,7 +10615,10 @@ namespace Parser { let precedingLineBreak = scanner.hasPrecedingLineBreak(); let seenLineBreak = false; let indentText = ""; - while ((precedingLineBreak && token() === SyntaxKind.AsteriskToken) || token() === SyntaxKind.WhitespaceTrivia || token() === SyntaxKind.NewLineTrivia) { + while ( + (precedingLineBreak && token() === SyntaxKind.AsteriskToken) + || token() === SyntaxKind.WhitespaceTrivia || token() === SyntaxKind.NewLineTrivia + ) { indentText += scanner.getTokenText(); if (token() === SyntaxKind.NewLineTrivia) { precedingLineBreak = true; @@ -9067,7 +10730,10 @@ namespace Parser { return parseTagComments(margin, indentText.slice(margin)); } - function parseTagComments(indent: number, initialMargin?: string): string | NodeArray | undefined { + function parseTagComments( + indent: number, + initialMargin?: string, + ): string | NodeArray | undefined { const commentsPos = getNodePos(); let comments: string[] = []; const parts: JSDocComment[] = []; @@ -9105,7 +10771,10 @@ namespace Parser { // Done break loop; case SyntaxKind.WhitespaceTrivia: - Debug.assert(state !== JSDocState.SavingComments && state !== JSDocState.SavingBackticks, "whitespace shouldn't come from the scanner while saving comment text"); + Debug.assert( + state !== JSDocState.SavingComments && state !== JSDocState.SavingBackticks, + "whitespace shouldn't come from the scanner while saving comment text", + ); const whitespace = scanner.getTokenText(); // if the whitespace crosses the margin, take only the whitespace that passes the margin if (margin !== undefined && indent + whitespace.length > margin) { @@ -9120,7 +10789,13 @@ namespace Parser { const linkStart = scanner.getTokenEnd() - 1; const link = parseJSDocLink(linkStart); if (link) { - parts.push(finishNode(factory.createJSDocText(comments.join("")), linkEnd ?? commentsPos, commentEnd)); + parts.push( + finishNode( + factory.createJSDocText(comments.join("")), + linkEnd ?? commentsPos, + commentEnd, + ), + ); parts.push(link); comments = []; linkEnd = scanner.getTokenEnd(); @@ -9201,7 +10876,10 @@ namespace Parser { } } const text = []; - while (token() !== SyntaxKind.CloseBraceToken && token() !== SyntaxKind.NewLineTrivia && token() !== SyntaxKind.EndOfFileToken) { + while ( + token() !== SyntaxKind.CloseBraceToken && token() !== SyntaxKind.NewLineTrivia + && token() !== SyntaxKind.EndOfFileToken + ) { text.push(scanner.getTokenText()); nextTokenJSDoc(); } @@ -9228,7 +10906,13 @@ namespace Parser { } function parseUnknownTag(start: number, tagName: Identifier, indent: number, indentText: string) { - return finishNode(factory.createJSDocUnknownTag(tagName, parseTrailingTagComments(start, getNodePos(), indent, indentText)), start); + return finishNode( + factory.createJSDocUnknownTag( + tagName, + parseTrailingTagComments(start, getNodePos(), indent, indentText), + ), + start, + ); } function addTag(tag: JSDocTag | undefined): void { @@ -9282,11 +10966,17 @@ namespace Parser { case SyntaxKind.ArrayType: return isObjectOrObjectArrayTypeReference((node as ArrayTypeNode).elementType); default: - return isTypeReferenceNode(node) && isIdentifierNode(node.typeName) && node.typeName.escapedText === "Object" && !node.typeArguments; + return isTypeReferenceNode(node) && isIdentifierNode(node.typeName) + && node.typeName.escapedText === "Object" && !node.typeArguments; } } - function parseParameterOrPropertyTag(start: number, tagName: Identifier, target: PropertyLikeParse, indent: number): JSDocParameterTag | JSDocPropertyTag { + function parseParameterOrPropertyTag( + start: number, + tagName: Identifier, + target: PropertyLikeParse, + indent: number, + ): JSDocParameterTag | JSDocPropertyTag { let typeExpression = tryParseTypeExpression(); let isNameFirst = !typeExpression; skipWhitespaceOrAsterisk(); @@ -9311,7 +11001,12 @@ namespace Parser { return finishNode(result, start); } - function parseNestedTypeLiteral(typeExpression: JSDocTypeExpression | undefined, name: EntityName, target: PropertyLikeParse, indent: number) { + function parseNestedTypeLiteral( + typeExpression: JSDocTypeExpression | undefined, + name: EntityName, + target: PropertyLikeParse, + indent: number, + ) { if (typeExpression && isObjectOrObjectArrayTypeReference(typeExpression.type)) { const pos = getNodePos(); let child: JSDocPropertyLikeTag | JSDocTypeTag | JSDocTemplateTag | false; @@ -9321,50 +11016,103 @@ namespace Parser { children = append(children, child); } else if (child.kind === SyntaxKind.JSDocTemplateTag) { - parseErrorAtRange(child.tagName, Diagnostics.A_JSDoc_template_tag_may_not_follow_a_typedef_callback_or_overload_tag); + parseErrorAtRange( + child.tagName, + Diagnostics.A_JSDoc_template_tag_may_not_follow_a_typedef_callback_or_overload_tag, + ); } } if (children) { - const literal = finishNode(factory.createJSDocTypeLiteral(children, typeExpression.type.kind === SyntaxKind.ArrayType), pos); + const literal = finishNode( + factory.createJSDocTypeLiteral(children, typeExpression.type.kind === SyntaxKind.ArrayType), + pos, + ); return finishNode(factory.createJSDocTypeExpression(literal), pos); } } } - function parseReturnTag(start: number, tagName: Identifier, indent: number, indentText: string): JSDocReturnTag { + function parseReturnTag( + start: number, + tagName: Identifier, + indent: number, + indentText: string, + ): JSDocReturnTag { if (some(tags, isJSDocReturnTag)) { - parseErrorAt(tagName.pos, scanner.getTokenStart(), Diagnostics._0_tag_already_specified, unescapeLeadingUnderscores(tagName.escapedText)); + parseErrorAt( + tagName.pos, + scanner.getTokenStart(), + Diagnostics._0_tag_already_specified, + unescapeLeadingUnderscores(tagName.escapedText), + ); } const typeExpression = tryParseTypeExpression(); - return finishNode(factory.createJSDocReturnTag(tagName, typeExpression, parseTrailingTagComments(start, getNodePos(), indent, indentText)), start); + return finishNode( + factory.createJSDocReturnTag( + tagName, + typeExpression, + parseTrailingTagComments(start, getNodePos(), indent, indentText), + ), + start, + ); } - function parseTypeTag(start: number, tagName: Identifier, indent?: number, indentText?: string): JSDocTypeTag { + function parseTypeTag( + start: number, + tagName: Identifier, + indent?: number, + indentText?: string, + ): JSDocTypeTag { if (some(tags, isJSDocTypeTag)) { - parseErrorAt(tagName.pos, scanner.getTokenStart(), Diagnostics._0_tag_already_specified, unescapeLeadingUnderscores(tagName.escapedText)); + parseErrorAt( + tagName.pos, + scanner.getTokenStart(), + Diagnostics._0_tag_already_specified, + unescapeLeadingUnderscores(tagName.escapedText), + ); } const typeExpression = parseJSDocTypeExpression(/*mayOmitBraces*/ true); - const comments = indent !== undefined && indentText !== undefined ? parseTrailingTagComments(start, getNodePos(), indent, indentText) : undefined; + const comments = indent !== undefined && indentText !== undefined + ? parseTrailingTagComments(start, getNodePos(), indent, indentText) : undefined; return finishNode(factory.createJSDocTypeTag(tagName, typeExpression, comments), start); } - function parseSeeTag(start: number, tagName: Identifier, indent?: number, indentText?: string): JSDocSeeTag { + function parseSeeTag( + start: number, + tagName: Identifier, + indent?: number, + indentText?: string, + ): JSDocSeeTag { const isMarkdownOrJSDocLink = token() === SyntaxKind.OpenBracketToken - || lookAhead(() => nextTokenJSDoc() === SyntaxKind.AtToken && tokenIsIdentifierOrKeyword(nextTokenJSDoc()) && isJSDocLinkTag(scanner.getTokenValue())); + || lookAhead(() => + nextTokenJSDoc() === SyntaxKind.AtToken && tokenIsIdentifierOrKeyword(nextTokenJSDoc()) + && isJSDocLinkTag(scanner.getTokenValue()) + ); const nameExpression = isMarkdownOrJSDocLink ? undefined : parseJSDocNameReference(); - const comments = indent !== undefined && indentText !== undefined ? parseTrailingTagComments(start, getNodePos(), indent, indentText) : undefined; + const comments = indent !== undefined && indentText !== undefined + ? parseTrailingTagComments(start, getNodePos(), indent, indentText) : undefined; return finishNode(factory.createJSDocSeeTag(tagName, nameExpression, comments), start); } - function parseThrowsTag(start: number, tagName: Identifier, indent: number, indentText: string): JSDocThrowsTag { + function parseThrowsTag( + start: number, + tagName: Identifier, + indent: number, + indentText: string, + ): JSDocThrowsTag { const typeExpression = tryParseTypeExpression(); const comment = parseTrailingTagComments(start, getNodePos(), indent, indentText); return finishNode(factory.createJSDocThrowsTag(tagName, typeExpression, comment), start); } - function parseAuthorTag(start: number, tagName: Identifier, indent: number, indentText: string): JSDocAuthorTag { + function parseAuthorTag( + start: number, + tagName: Identifier, + indent: number, + indentText: string, + ): JSDocAuthorTag { const commentStart = getNodePos(); const textOnly = parseAuthorNameAndEmail(); let commentEnd = scanner.getTokenFullStart(); @@ -9373,7 +11121,10 @@ namespace Parser { commentEnd = scanner.getTokenFullStart(); } const allParts = typeof comments !== "string" - ? createNodeArray(concatenate([finishNode(textOnly, commentStart, commentEnd)], comments) as JSDocComment[], commentStart) // cast away readonly + ? createNodeArray( + concatenate([finishNode(textOnly, commentStart, commentEnd)], comments) as JSDocComment[], + commentStart, + ) // cast away readonly : textOnly.text + comments; return finishNode(factory.createJSDocAuthorTag(tagName, allParts), start); } @@ -9401,30 +11152,64 @@ namespace Parser { return factory.createJSDocText(comments.join("")); } - function parseImplementsTag(start: number, tagName: Identifier, margin: number, indentText: string): JSDocImplementsTag { + function parseImplementsTag( + start: number, + tagName: Identifier, + margin: number, + indentText: string, + ): JSDocImplementsTag { const className = parseExpressionWithTypeArgumentsForAugments(); - return finishNode(factory.createJSDocImplementsTag(tagName, className, parseTrailingTagComments(start, getNodePos(), margin, indentText)), start); + return finishNode( + factory.createJSDocImplementsTag( + tagName, + className, + parseTrailingTagComments(start, getNodePos(), margin, indentText), + ), + start, + ); } - function parseAugmentsTag(start: number, tagName: Identifier, margin: number, indentText: string): JSDocAugmentsTag { + function parseAugmentsTag( + start: number, + tagName: Identifier, + margin: number, + indentText: string, + ): JSDocAugmentsTag { const className = parseExpressionWithTypeArgumentsForAugments(); - return finishNode(factory.createJSDocAugmentsTag(tagName, className, parseTrailingTagComments(start, getNodePos(), margin, indentText)), start); + return finishNode( + factory.createJSDocAugmentsTag( + tagName, + className, + parseTrailingTagComments(start, getNodePos(), margin, indentText), + ), + start, + ); } - function parseSatisfiesTag(start: number, tagName: Identifier, margin: number, indentText: string): JSDocSatisfiesTag { + function parseSatisfiesTag( + start: number, + tagName: Identifier, + margin: number, + indentText: string, + ): JSDocSatisfiesTag { const typeExpression = parseJSDocTypeExpression(/*mayOmitBraces*/ false); - const comments = margin !== undefined && indentText !== undefined ? parseTrailingTagComments(start, getNodePos(), margin, indentText) : undefined; + const comments = margin !== undefined && indentText !== undefined + ? parseTrailingTagComments(start, getNodePos(), margin, indentText) : undefined; return finishNode(factory.createJSDocSatisfiesTag(tagName, typeExpression, comments), start); } - function parseExpressionWithTypeArgumentsForAugments(): ExpressionWithTypeArguments & { expression: Identifier | PropertyAccessEntityNameExpression; } { + function parseExpressionWithTypeArgumentsForAugments(): ExpressionWithTypeArguments & { + expression: Identifier | PropertyAccessEntityNameExpression; + } { const usedBrace = parseOptional(SyntaxKind.OpenBraceToken); const pos = getNodePos(); const expression = parsePropertyAccessEntityNameExpression(); scanner.setInJSDocType(true); const typeArguments = tryParseTypeArguments(); scanner.setInJSDocType(false); - const node = factory.createExpressionWithTypeArguments(expression, typeArguments) as ExpressionWithTypeArguments & { expression: Identifier | PropertyAccessEntityNameExpression; }; + const node = factory.createExpressionWithTypeArguments(expression, typeArguments) as + & ExpressionWithTypeArguments + & { expression: Identifier | PropertyAccessEntityNameExpression; }; const res = finishNode(node, pos); if (usedBrace) { parseExpected(SyntaxKind.CloseBraceToken); @@ -9437,28 +11222,69 @@ namespace Parser { let node: Identifier | PropertyAccessEntityNameExpression = parseJSDocIdentifierName(); while (parseOptional(SyntaxKind.DotToken)) { const name = parseJSDocIdentifierName(); - node = finishNode(factoryCreatePropertyAccessExpression(node, name), pos) as PropertyAccessEntityNameExpression; + node = finishNode( + factoryCreatePropertyAccessExpression(node, name), + pos, + ) as PropertyAccessEntityNameExpression; } return node; } - function parseSimpleTag(start: number, createTag: (tagName: Identifier | undefined, comment?: string | NodeArray) => JSDocTag, tagName: Identifier, margin: number, indentText: string): JSDocTag { - return finishNode(createTag(tagName, parseTrailingTagComments(start, getNodePos(), margin, indentText)), start); + function parseSimpleTag( + start: number, + createTag: (tagName: Identifier | undefined, comment?: string | NodeArray) => JSDocTag, + tagName: Identifier, + margin: number, + indentText: string, + ): JSDocTag { + return finishNode( + createTag(tagName, parseTrailingTagComments(start, getNodePos(), margin, indentText)), + start, + ); } - function parseThisTag(start: number, tagName: Identifier, margin: number, indentText: string): JSDocThisTag { + function parseThisTag( + start: number, + tagName: Identifier, + margin: number, + indentText: string, + ): JSDocThisTag { const typeExpression = parseJSDocTypeExpression(/*mayOmitBraces*/ true); skipWhitespace(); - return finishNode(factory.createJSDocThisTag(tagName, typeExpression, parseTrailingTagComments(start, getNodePos(), margin, indentText)), start); + return finishNode( + factory.createJSDocThisTag( + tagName, + typeExpression, + parseTrailingTagComments(start, getNodePos(), margin, indentText), + ), + start, + ); } - function parseEnumTag(start: number, tagName: Identifier, margin: number, indentText: string): JSDocEnumTag { + function parseEnumTag( + start: number, + tagName: Identifier, + margin: number, + indentText: string, + ): JSDocEnumTag { const typeExpression = parseJSDocTypeExpression(/*mayOmitBraces*/ true); skipWhitespace(); - return finishNode(factory.createJSDocEnumTag(tagName, typeExpression, parseTrailingTagComments(start, getNodePos(), margin, indentText)), start); + return finishNode( + factory.createJSDocEnumTag( + tagName, + typeExpression, + parseTrailingTagComments(start, getNodePos(), margin, indentText), + ), + start, + ); } - function parseTypedefTag(start: number, tagName: Identifier, indent: number, indentText: string): JSDocTypedefTag { + function parseTypedefTag( + start: number, + tagName: Identifier, + indent: number, + indentText: string, + ): JSDocTypedefTag { let typeExpression: JSDocTypeExpression | JSDocTypeLiteral | undefined = tryParseTypeExpression(); skipWhitespaceOrAsterisk(); @@ -9479,9 +11305,19 @@ namespace Parser { hasChildren = true; if (child.kind === SyntaxKind.JSDocTypeTag) { if (childTypeTag) { - const lastError = parseErrorAtCurrentToken(Diagnostics.A_JSDoc_typedef_comment_may_not_contain_multiple_type_tags); + const lastError = parseErrorAtCurrentToken( + Diagnostics.A_JSDoc_typedef_comment_may_not_contain_multiple_type_tags, + ); if (lastError) { - addRelatedInfo(lastError, createDetachedDiagnostic(fileName, 0, 0, Diagnostics.The_tag_was_first_specified_here)); + addRelatedInfo( + lastError, + createDetachedDiagnostic( + fileName, + 0, + 0, + Diagnostics.The_tag_was_first_specified_here, + ), + ); } break; } @@ -9496,17 +11332,18 @@ namespace Parser { if (hasChildren) { const isArrayType = typeExpression && typeExpression.type.kind === SyntaxKind.ArrayType; const jsdocTypeLiteral = factory.createJSDocTypeLiteral(jsDocPropertyTags, isArrayType); - typeExpression = childTypeTag && childTypeTag.typeExpression && !isObjectOrObjectArrayTypeReference(childTypeTag.typeExpression.type) ? - childTypeTag.typeExpression : - finishNode(jsdocTypeLiteral, start); + typeExpression = childTypeTag && childTypeTag.typeExpression + && !isObjectOrObjectArrayTypeReference(childTypeTag.typeExpression.type) + ? childTypeTag.typeExpression + : finishNode(jsdocTypeLiteral, start); end = typeExpression.end; } } // Only include the characters between the name end and the next token if a comment was actually parsed out - otherwise it's just whitespace - end = end || comment !== undefined ? - getNodePos() : - (fullName ?? typeExpression ?? tagName).end; + end = end || comment !== undefined + ? getNodePos() + : (fullName ?? typeExpression ?? tagName).end; if (!comment) { comment = parseTrailingTagComments(start, end, indent, indentText); @@ -9543,9 +11380,18 @@ namespace Parser { const pos = getNodePos(); let child: JSDocParameterTag | JSDocTemplateTag | false; let parameters; - while (child = tryParse(() => parseChildParameterOrPropertyTag(PropertyLikeParse.CallbackParameter, indent) as JSDocParameterTag | JSDocTemplateTag)) { + while ( + child = tryParse(() => + parseChildParameterOrPropertyTag(PropertyLikeParse.CallbackParameter, indent) as + | JSDocParameterTag + | JSDocTemplateTag + ) + ) { if (child.kind === SyntaxKind.JSDocTemplateTag) { - parseErrorAtRange(child.tagName, Diagnostics.A_JSDoc_template_tag_may_not_follow_a_typedef_callback_or_overload_tag); + parseErrorAtRange( + child.tagName, + Diagnostics.A_JSDoc_template_tag_may_not_follow_a_typedef_callback_or_overload_tag, + ); break; } parameters = append(parameters, child); @@ -9563,10 +11409,18 @@ namespace Parser { } } }); - return finishNode(factory.createJSDocSignature(/*typeParameters*/ undefined, parameters, returnTag), start); + return finishNode( + factory.createJSDocSignature(/*typeParameters*/ undefined, parameters, returnTag), + start, + ); } - function parseCallbackTag(start: number, tagName: Identifier, indent: number, indentText: string): JSDocCallbackTag { + function parseCallbackTag( + start: number, + tagName: Identifier, + indent: number, + indentText: string, + ): JSDocCallbackTag { const fullName = parseJSDocTypeNameWithNamespace(); skipWhitespace(); let comment = parseTagComments(indent); @@ -9575,10 +11429,19 @@ namespace Parser { comment = parseTrailingTagComments(start, getNodePos(), indent, indentText); } const end = comment !== undefined ? getNodePos() : typeExpression.end; - return finishNode(factory.createJSDocCallbackTag(tagName, typeExpression, fullName, comment), start, end); + return finishNode( + factory.createJSDocCallbackTag(tagName, typeExpression, fullName, comment), + start, + end, + ); } - function parseOverloadTag(start: number, tagName: Identifier, indent: number, indentText: string): JSDocOverloadTag { + function parseOverloadTag( + start: number, + tagName: Identifier, + indent: number, + indentText: string, + ): JSDocOverloadTag { skipWhitespace(); let comment = parseTagComments(indent); const typeExpression = parseJSDocSignature(start, indent); @@ -9603,10 +11466,18 @@ namespace Parser { } function parseChildPropertyTag(indent: number) { - return parseChildParameterOrPropertyTag(PropertyLikeParse.Property, indent) as JSDocTypeTag | JSDocPropertyTag | JSDocTemplateTag | false; - } - - function parseChildParameterOrPropertyTag(target: PropertyLikeParse, indent: number, name?: EntityName): JSDocTypeTag | JSDocPropertyTag | JSDocParameterTag | JSDocTemplateTag | false { + return parseChildParameterOrPropertyTag(PropertyLikeParse.Property, indent) as + | JSDocTypeTag + | JSDocPropertyTag + | JSDocTemplateTag + | false; + } + + function parseChildParameterOrPropertyTag( + target: PropertyLikeParse, + indent: number, + name?: EntityName, + ): JSDocTypeTag | JSDocPropertyTag | JSDocParameterTag | JSDocTemplateTag | false { let canParseTag = true; let seenAsterisk = false; while (true) { @@ -9615,8 +11486,11 @@ namespace Parser { if (canParseTag) { const child = tryParseChildTag(target, indent); if ( - child && (child.kind === SyntaxKind.JSDocParameterTag || child.kind === SyntaxKind.JSDocPropertyTag) && - name && (isIdentifierNode(child.name) || !escapedTextsEqual(name, child.name.left)) + child + && (child.kind === SyntaxKind.JSDocParameterTag + || child.kind === SyntaxKind.JSDocPropertyTag) + && name + && (isIdentifierNode(child.name) || !escapedTextsEqual(name, child.name.left)) ) { return false; } @@ -9643,7 +11517,10 @@ namespace Parser { } } - function tryParseChildTag(target: PropertyLikeParse, indent: number): JSDocTypeTag | JSDocPropertyTag | JSDocParameterTag | JSDocTemplateTag | false { + function tryParseChildTag( + target: PropertyLikeParse, + indent: number, + ): JSDocTypeTag | JSDocPropertyTag | JSDocParameterTag | JSDocTemplateTag | false { Debug.assert(token() === SyntaxKind.AtToken); const start = scanner.getTokenFullStart(); nextTokenJSDoc(); @@ -9680,7 +11557,9 @@ namespace Parser { if (isBracketed) { skipWhitespace(); } - const name = parseJSDocIdentifierName(Diagnostics.Unexpected_token_A_type_parameter_name_was_expected_without_curly_braces); + const name = parseJSDocIdentifierName( + Diagnostics.Unexpected_token_A_type_parameter_name_was_expected_without_curly_braces, + ); let defaultType: TypeNode | undefined; if (isBracketed) { @@ -9693,7 +11572,15 @@ namespace Parser { if (nodeIsMissing(name)) { return undefined; } - return finishNode(factory.createTypeParameterDeclaration(/*modifiers*/ undefined, name, /*constraint*/ undefined, defaultType), typeParameterPos); + return finishNode( + factory.createTypeParameterDeclaration( + /*modifiers*/ undefined, + name, + /*constraint*/ undefined, + defaultType, + ), + typeParameterPos, + ); } function parseTemplateTagTypeParameters() { @@ -9711,7 +11598,12 @@ namespace Parser { return createNodeArray(typeParameters, pos); } - function parseTemplateTag(start: number, tagName: Identifier, indent: number, indentText: string): JSDocTemplateTag { + function parseTemplateTag( + start: number, + tagName: Identifier, + indent: number, + indentText: string, + ): JSDocTemplateTag { // The template tag looks like one of the following: // @template T,U,V // @template {Constraint} T @@ -9725,7 +11617,15 @@ namespace Parser { // TODO: Consider only parsing a single type parameter if there is a constraint. const constraint = token() === SyntaxKind.OpenBraceToken ? parseJSDocTypeExpression() : undefined; const typeParameters = parseTemplateTagTypeParameters(); - return finishNode(factory.createJSDocTemplateTag(tagName, constraint, typeParameters, parseTrailingTagComments(start, getNodePos(), indent, indentText)), start); + return finishNode( + factory.createJSDocTemplateTag( + tagName, + constraint, + typeParameters, + parseTrailingTagComments(start, getNodePos(), indent, indentText), + ), + start, + ); } function parseOptionalJsdoc(t: JSDocSyntaxKind): boolean { @@ -9756,7 +11656,11 @@ namespace Parser { function parseJSDocIdentifierName(message?: DiagnosticMessage): Identifier { if (!tokenIsIdentifierOrKeyword(token())) { - return createMissingNode(SyntaxKind.Identifier, /*reportAtCurrentPosition*/ !message, message || Diagnostics.Identifier_expected); + return createMissingNode( + SyntaxKind.Identifier, + /*reportAtCurrentPosition*/ !message, + message || Diagnostics.Identifier_expected, + ); } identifierCount++; @@ -9773,7 +11677,12 @@ namespace Parser { } namespace IncrementalParser { - export function updateSourceFile(sourceFile: SourceFile, newText: string, textChangeRange: TextChangeRange, aggressiveChecks: boolean): SourceFile { + export function updateSourceFile( + sourceFile: SourceFile, + newText: string, + textChangeRange: TextChangeRange, + aggressiveChecks: boolean, + ): SourceFile { aggressiveChecks = aggressiveChecks || Debug.shouldAssert(AssertionLevel.Aggressive); checkChangeRange(sourceFile, newText, textChangeRange, aggressiveChecks); @@ -9785,7 +11694,15 @@ namespace IncrementalParser { if (sourceFile.statements.length === 0) { // If we don't have any statements in the current source file, then there's no real // way to incrementally parse. So just do a full parse instead. - return Parser.parseSourceFile(sourceFile.fileName, newText, sourceFile.languageVersion, /*syntaxCursor*/ undefined, /*setParentNodes*/ true, sourceFile.scriptKind, sourceFile.setExternalModuleIndicator); + return Parser.parseSourceFile( + sourceFile.fileName, + newText, + sourceFile.languageVersion, + /*syntaxCursor*/ undefined, + /*setParentNodes*/ true, + sourceFile.scriptKind, + sourceFile.setExternalModuleIndicator, + ); } // Make sure we're not trying to incrementally update a source file more than once. Once @@ -9810,7 +11727,9 @@ namespace IncrementalParser { // earlier in the file. Debug.assert(changeRange.span.start <= textChangeRange.span.start); Debug.assert(textSpanEnd(changeRange.span) === textSpanEnd(textChangeRange.span)); - Debug.assert(textSpanEnd(textChangeRangeNewSpan(changeRange)) === textSpanEnd(textChangeRangeNewSpan(textChangeRange))); + Debug.assert( + textSpanEnd(textChangeRangeNewSpan(changeRange)) === textSpanEnd(textChangeRangeNewSpan(textChangeRange)), + ); // The is the amount the nodes after the edit range need to be adjusted. It can be // positive (if the edit added characters), negative (if the edit deleted characters) @@ -9836,7 +11755,16 @@ namespace IncrementalParser { // // Also, mark any syntax elements that intersect the changed span. We know, up front, // that we cannot reuse these elements. - updateTokenPositionsAndMarkElements(incrementalSourceFile, changeRange.span.start, textSpanEnd(changeRange.span), textSpanEnd(textChangeRangeNewSpan(changeRange)), delta, oldText, newText, aggressiveChecks); + updateTokenPositionsAndMarkElements( + incrementalSourceFile, + changeRange.span.start, + textSpanEnd(changeRange.span), + textSpanEnd(textChangeRangeNewSpan(changeRange)), + delta, + oldText, + newText, + aggressiveChecks, + ); // Now that we've set up our internal incremental state just proceed and parse the // source file in the normal fashion. When possible the parser will retrieve and @@ -9848,7 +11776,15 @@ namespace IncrementalParser { // inconsistent tree. Setting the parents on the new tree should be very fast. We // will immediately bail out of walking any subtrees when we can see that their parents // are already correct. - const result = Parser.parseSourceFile(sourceFile.fileName, newText, sourceFile.languageVersion, syntaxCursor, /*setParentNodes*/ true, sourceFile.scriptKind, sourceFile.setExternalModuleIndicator); + const result = Parser.parseSourceFile( + sourceFile.fileName, + newText, + sourceFile.languageVersion, + syntaxCursor, + /*setParentNodes*/ true, + sourceFile.scriptKind, + sourceFile.setExternalModuleIndicator, + ); result.commentDirectives = getNewCommentDirectives( sourceFile.commentDirectives, result.commentDirectives, @@ -9892,7 +11828,10 @@ namespace IncrementalParser { }; commentDirectives = append(commentDirectives, updatedDirective); if (aggressiveChecks) { - Debug.assert(oldText.substring(range.pos, range.end) === newText.substring(updatedDirective.range.pos, updatedDirective.range.end)); + Debug.assert( + oldText.substring(range.pos, range.end) + === newText.substring(updatedDirective.range.pos, updatedDirective.range.end), + ); } } // Ignore ranges that fall in change range @@ -9912,9 +11851,30 @@ namespace IncrementalParser { } } - function moveElementEntirelyPastChangeRange(element: IncrementalNode, isArray: false, delta: number, oldText: string, newText: string, aggressiveChecks: boolean): void; - function moveElementEntirelyPastChangeRange(element: IncrementalNodeArray, isArray: true, delta: number, oldText: string, newText: string, aggressiveChecks: boolean): void; - function moveElementEntirelyPastChangeRange(element: IncrementalNode | IncrementalNodeArray, isArray: boolean, delta: number, oldText: string, newText: string, aggressiveChecks: boolean) { + function moveElementEntirelyPastChangeRange( + element: IncrementalNode, + isArray: false, + delta: number, + oldText: string, + newText: string, + aggressiveChecks: boolean, + ): void; + function moveElementEntirelyPastChangeRange( + element: IncrementalNodeArray, + isArray: true, + delta: number, + oldText: string, + newText: string, + aggressiveChecks: boolean, + ): void; + function moveElementEntirelyPastChangeRange( + element: IncrementalNode | IncrementalNodeArray, + isArray: boolean, + delta: number, + oldText: string, + newText: string, + aggressiveChecks: boolean, + ) { if (isArray) { visitArray(element as IncrementalNodeArray); } @@ -9971,7 +11931,13 @@ namespace IncrementalParser { return false; } - function adjustIntersectingElement(element: IncrementalElement, changeStart: number, changeRangeOldEnd: number, changeRangeNewEnd: number, delta: number) { + function adjustIntersectingElement( + element: IncrementalElement, + changeStart: number, + changeRangeOldEnd: number, + changeRangeNewEnd: number, + delta: number, + ) { Debug.assert(element.end >= changeStart, "Adjusting an element that was entirely before the change range"); Debug.assert(element.pos <= changeRangeOldEnd, "Adjusting an element that was entirely after the change range"); Debug.assert(element.pos <= element.end); @@ -10029,12 +11995,12 @@ namespace IncrementalParser { // However any element that ended after that will have their pos adjusted to be // at the end of the new range. i.e. any node that ended in the 'Y' range will // be adjusted to have their end at the end of the 'Z' range. - const end = element.end >= changeRangeOldEnd ? + const end = element.end >= changeRangeOldEnd // Element ends after the change range. Always adjust the end pos. - element.end + delta : + ? element.end + delta // Element ends in the change range. The element will keep its position if // possible. Or Move backward to the new-end if it's in the 'Y' range. - Math.min(element.end, changeRangeNewEnd); + : Math.min(element.end, changeRangeNewEnd); Debug.assert(pos <= end); if (element.parent) { @@ -10255,7 +12221,12 @@ namespace IncrementalParser { } } - function checkChangeRange(sourceFile: SourceFile, newText: string, textChangeRange: TextChangeRange, aggressiveChecks: boolean) { + function checkChangeRange( + sourceFile: SourceFile, + newText: string, + textChangeRange: TextChangeRange, + aggressiveChecks: boolean, + ) { const oldText = sourceFile.text; if (textChangeRange) { Debug.assert((oldText.length - textChangeRange.span.length + textChangeRange.newLength) === newText.length); @@ -10266,7 +12237,10 @@ namespace IncrementalParser { Debug.assert(oldTextPrefix === newTextPrefix); const oldTextSuffix = oldText.substring(textSpanEnd(textChangeRange.span), oldText.length); - const newTextSuffix = newText.substring(textSpanEnd(textChangeRangeNewSpan(textChangeRange)), newText.length); + const newTextSuffix = newText.substring( + textSpanEnd(textChangeRangeNewSpan(textChangeRange)), + newText.length, + ); Debug.assert(oldTextSuffix === newTextSuffix); } } @@ -10402,10 +12376,16 @@ namespace IncrementalParser { /** @internal */ export function isDeclarationFileName(fileName: string): boolean { - return fileExtensionIsOneOf(fileName, supportedDeclarationExtensions) || (fileExtensionIs(fileName, Extension.Ts) && stringContains(getBaseFileName(fileName), ".d.")); + return fileExtensionIsOneOf(fileName, supportedDeclarationExtensions) + || (fileExtensionIs(fileName, Extension.Ts) && stringContains(getBaseFileName(fileName), ".d.")); } -function parseResolutionMode(mode: string | undefined, pos: number, end: number, reportDiagnostic: PragmaDiagnosticReporter): ResolutionMode { +function parseResolutionMode( + mode: string | undefined, + pos: number, + end: number, + reportDiagnostic: PragmaDiagnosticReporter, +): ResolutionMode { if (!mode) { return undefined; } @@ -10470,7 +12450,12 @@ export function processPragmasIntoFields(context: PragmaContext, reportDiagnosti } else if (types) { const parsed = parseResolutionMode(res, types.pos, types.end, reportDiagnostic); - typeReferenceDirectives.push({ pos: types.pos, end: types.end, fileName: types.value, ...(parsed ? { resolutionMode: parsed } : {}) }); + typeReferenceDirectives.push({ + pos: types.pos, + end: types.end, + fileName: types.value, + ...(parsed ? { resolutionMode: parsed } : {}), + }); } else if (lib) { libReferenceDirectives.push({ pos: lib.pos, end: lib.end, fileName: lib.value }); @@ -10479,7 +12464,11 @@ export function processPragmasIntoFields(context: PragmaContext, reportDiagnosti referencedFiles.push({ pos: path.pos, end: path.end, fileName: path.value }); } else { - reportDiagnostic(arg.range.pos, arg.range.end - arg.range.pos, Diagnostics.Invalid_reference_directive_syntax); + reportDiagnostic( + arg.range.pos, + arg.range.end - arg.range.pos, + Diagnostics.Invalid_reference_directive_syntax, + ); } }); break; @@ -10496,7 +12485,11 @@ export function processPragmasIntoFields(context: PragmaContext, reportDiagnosti for (const entry of entryOrList) { if (context.moduleName) { // TODO: It's probably fine to issue this diagnostic on all instances of the pragma - reportDiagnostic(entry.range.pos, entry.range.end - entry.range.pos, Diagnostics.An_AMD_module_cannot_have_multiple_name_assignments); + reportDiagnostic( + entry.range.pos, + entry.range.end - entry.range.pos, + Diagnostics.An_AMD_module_cannot_have_multiple_name_assignments, + ); } context.moduleName = (entry as PragmaPseudoMap["amd-module"]).arguments.name; } @@ -10596,7 +12589,12 @@ function extractPragmas(pragmas: PragmaPseudoMapEntry[], range: CommentRange, te } } -function addPragmaForMatch(pragmas: PragmaPseudoMapEntry[], range: CommentRange, kind: PragmaKindFlags, match: RegExpExecArray) { +function addPragmaForMatch( + pragmas: PragmaPseudoMapEntry[], + range: CommentRange, + kind: PragmaKindFlags, + match: RegExpExecArray, +) { if (!match) return; const name = match[1].toLowerCase() as keyof PragmaPseudoMap; // Technically unsafe cast, but we do it so they below check to make it safe typechecks const pragma = commentPragmas[name] as PragmaDefinition; @@ -10610,7 +12608,10 @@ function addPragmaForMatch(pragmas: PragmaPseudoMapEntry[], range: CommentRange, return; } -function getNamedPragmaArguments(pragma: PragmaDefinition, text: string | undefined): { [index: string]: string; } | "fail" { +function getNamedPragmaArguments( + pragma: PragmaDefinition, + text: string | undefined, +): { [index: string]: string; } | "fail" { if (!text) return {}; if (!pragma.args) return {}; const args = trimString(text).split(/\s+/); @@ -10643,13 +12644,16 @@ export function tagNamesAreEquivalent(lhs: JsxTagNameExpression, rhs: JsxTagName } if (lhs.kind === SyntaxKind.JsxNamespacedName) { - return lhs.namespace.escapedText === (rhs as JsxNamespacedName).namespace.escapedText && - lhs.name.escapedText === (rhs as JsxNamespacedName).name.escapedText; + return lhs.namespace.escapedText === (rhs as JsxNamespacedName).namespace.escapedText + && lhs.name.escapedText === (rhs as JsxNamespacedName).name.escapedText; } // If we are at this statement then we must have PropertyAccessExpression and because tag name in Jsx element can only // take forms of JsxTagNameExpression which includes an identifier, "this" expression, or another propertyAccessExpression // it is safe to case the expression property as such. See parseJsxElementName for how we parse tag name in Jsx element - return (lhs as PropertyAccessExpression).name.escapedText === (rhs as PropertyAccessExpression).name.escapedText && - tagNamesAreEquivalent((lhs as PropertyAccessExpression).expression as JsxTagNameExpression, (rhs as PropertyAccessExpression).expression as JsxTagNameExpression); + return (lhs as PropertyAccessExpression).name.escapedText === (rhs as PropertyAccessExpression).name.escapedText + && tagNamesAreEquivalent( + (lhs as PropertyAccessExpression).expression as JsxTagNameExpression, + (rhs as PropertyAccessExpression).expression as JsxTagNameExpression, + ); } diff --git a/src/compiler/path.ts b/src/compiler/path.ts index c77fa141f071d..e4856aaf259f2 100644 --- a/src/compiler/path.ts +++ b/src/compiler/path.ts @@ -144,8 +144,8 @@ export function hasTrailingDirectorySeparator(path: string) { //// Path Parsing function isVolumeCharacter(charCode: number) { - return (charCode >= CharacterCodes.a && charCode <= CharacterCodes.z) || - (charCode >= CharacterCodes.A && charCode <= CharacterCodes.Z); + return (charCode >= CharacterCodes.a && charCode <= CharacterCodes.z) + || (charCode >= CharacterCodes.A && charCode <= CharacterCodes.Z); } function getFileUrlVolumeSeparatorEnd(url: string, start: number) { @@ -195,8 +195,8 @@ function getEncodedRootLength(path: string): number { const scheme = path.slice(0, schemeEnd); const authority = path.slice(authorityStart, authorityEnd); if ( - scheme === "file" && (authority === "" || authority === "localhost") && - isVolumeCharacter(path.charCodeAt(authorityEnd + 1)) + scheme === "file" && (authority === "" || authority === "localhost") + && isVolumeCharacter(path.charCodeAt(authorityEnd + 1)) ) { const volumeSeparatorEnd = getFileUrlVolumeSeparatorEnd(path, authorityEnd + 2); if (volumeSeparatorEnd !== -1) { @@ -381,11 +381,16 @@ export function getBaseFileName(path: string, extensions?: string | readonly str // separator but not including any trailing directory separator. path = removeTrailingDirectorySeparator(path); const name = path.slice(Math.max(getRootLength(path), path.lastIndexOf(directorySeparator) + 1)); - const extension = extensions !== undefined && ignoreCase !== undefined ? getAnyExtensionFromPath(name, extensions, ignoreCase) : undefined; + const extension = extensions !== undefined && ignoreCase !== undefined + ? getAnyExtensionFromPath(name, extensions, ignoreCase) : undefined; return extension ? name.slice(0, name.length - extension.length) : name; } -function tryGetExtensionFromPath(path: string, extension: string, stringEqualityComparer: (a: string, b: string) => boolean) { +function tryGetExtensionFromPath( + path: string, + extension: string, + stringEqualityComparer: (a: string, b: string) => boolean, +) { if (!startsWith(extension, ".")) extension = "." + extension; if (path.length >= extension.length && path.charCodeAt(path.length - extension.length) === CharacterCodes.dot) { const pathExtension = path.slice(path.length - extension.length); @@ -395,7 +400,11 @@ function tryGetExtensionFromPath(path: string, extension: string, stringEquality } } -function getAnyExtensionFromPathWorker(path: string, extensions: string | readonly string[], stringEqualityComparer: (a: string, b: string) => boolean) { +function getAnyExtensionFromPathWorker( + path: string, + extensions: string | readonly string[], + stringEqualityComparer: (a: string, b: string) => boolean, +) { if (typeof extensions === "string") { return tryGetExtensionFromPath(path, extensions, stringEqualityComparer) || ""; } @@ -430,13 +439,25 @@ export function getAnyExtensionFromPath(path: string): string; * * @internal */ -export function getAnyExtensionFromPath(path: string, extensions: string | readonly string[], ignoreCase: boolean): string; +export function getAnyExtensionFromPath( + path: string, + extensions: string | readonly string[], + ignoreCase: boolean, +): string; /** @internal */ -export function getAnyExtensionFromPath(path: string, extensions?: string | readonly string[], ignoreCase?: boolean): string { +export function getAnyExtensionFromPath( + path: string, + extensions?: string | readonly string[], + ignoreCase?: boolean, +): string { // Retrieves any string from the final "." onwards from a base file name. // Unlike extensionFromPath, which throws an exception on unrecognized extensions. if (extensions) { - return getAnyExtensionFromPathWorker(removeTrailingDirectorySeparator(path), extensions, ignoreCase ? equateStringsCaseInsensitive : equateStringsCaseSensitive); + return getAnyExtensionFromPathWorker( + removeTrailingDirectorySeparator(path), + extensions, + ignoreCase ? equateStringsCaseInsensitive : equateStringsCaseSensitive, + ); } const baseFileName = getBaseFileName(path); const extensionIndex = baseFileName.lastIndexOf("."); @@ -645,7 +666,8 @@ export function normalizePath(path: string): string { } // Other paths require full normalization const normalized = getPathFromPathComponents(reducePathComponents(getPathComponents(path))); - return normalized && hasTrailingDirectorySeparator(path) ? ensureTrailingDirectorySeparator(normalized) : normalized; + return normalized && hasTrailingDirectorySeparator(path) ? ensureTrailingDirectorySeparator(normalized) + : normalized; } function getPathWithoutRoot(pathComponents: readonly string[]) { @@ -659,7 +681,11 @@ export function getNormalizedAbsolutePathWithoutRoot(fileName: string, currentDi } /** @internal */ -export function toPath(fileName: string, basePath: string | undefined, getCanonicalFileName: (path: string) => string): Path { +export function toPath( + fileName: string, + basePath: string | undefined, + getCanonicalFileName: (path: string) => string, +): Path { const nonCanonicalizedPath = isRootedDiskPath(fileName) ? normalizePath(fileName) : getNormalizedAbsolutePath(fileName, basePath); @@ -750,10 +776,21 @@ export function changeAnyExtension(path: string, ext: string): string; * * @internal */ -export function changeAnyExtension(path: string, ext: string, extensions: string | readonly string[], ignoreCase: boolean): string; +export function changeAnyExtension( + path: string, + ext: string, + extensions: string | readonly string[], + ignoreCase: boolean, +): string; /** @internal */ -export function changeAnyExtension(path: string, ext: string, extensions?: string | readonly string[], ignoreCase?: boolean) { - const pathext = extensions !== undefined && ignoreCase !== undefined ? getAnyExtensionFromPath(path, extensions, ignoreCase) : getAnyExtensionFromPath(path); +export function changeAnyExtension( + path: string, + ext: string, + extensions?: string | readonly string[], + ignoreCase?: boolean, +) { + const pathext = extensions !== undefined && ignoreCase !== undefined + ? getAnyExtensionFromPath(path, extensions, ignoreCase) : getAnyExtensionFromPath(path); return pathext ? path.slice(0, path.length - pathext.length) + (startsWith(ext, ".") ? ext : "." + ext) : path; } @@ -880,16 +917,26 @@ export function containsPath(parent: string, child: string, currentDirectory?: s * * @internal */ -export function startsWithDirectory(fileName: string, directoryName: string, getCanonicalFileName: GetCanonicalFileName): boolean { +export function startsWithDirectory( + fileName: string, + directoryName: string, + getCanonicalFileName: GetCanonicalFileName, +): boolean { const canonicalFileName = getCanonicalFileName(fileName); const canonicalDirectoryName = getCanonicalFileName(directoryName); - return startsWith(canonicalFileName, canonicalDirectoryName + "/") || startsWith(canonicalFileName, canonicalDirectoryName + "\\"); + return startsWith(canonicalFileName, canonicalDirectoryName + "/") + || startsWith(canonicalFileName, canonicalDirectoryName + "\\"); } //// Relative Paths /** @internal */ -export function getPathComponentsRelativeTo(from: string, to: string, stringEqualityComparer: (a: string, b: string) => boolean, getCanonicalFileName: GetCanonicalFileName) { +export function getPathComponentsRelativeTo( + from: string, + to: string, + stringEqualityComparer: (a: string, b: string) => boolean, + getCanonicalFileName: GetCanonicalFileName, +) { const fromComponents = reducePathComponents(getPathComponents(from)); const toComponents = reducePathComponents(getPathComponents(to)); @@ -924,21 +971,48 @@ export function getRelativePathFromDirectory(from: string, to: string, ignoreCas * * @internal */ -export function getRelativePathFromDirectory(fromDirectory: string, to: string, getCanonicalFileName: GetCanonicalFileName): string; // eslint-disable-line @typescript-eslint/unified-signatures +export function getRelativePathFromDirectory( + fromDirectory: string, + to: string, + getCanonicalFileName: GetCanonicalFileName, +): string; // eslint-disable-line @typescript-eslint/unified-signatures /** @internal */ -export function getRelativePathFromDirectory(fromDirectory: string, to: string, getCanonicalFileNameOrIgnoreCase: GetCanonicalFileName | boolean) { - Debug.assert((getRootLength(fromDirectory) > 0) === (getRootLength(to) > 0), "Paths must either both be absolute or both be relative"); - const getCanonicalFileName = typeof getCanonicalFileNameOrIgnoreCase === "function" ? getCanonicalFileNameOrIgnoreCase : identity; +export function getRelativePathFromDirectory( + fromDirectory: string, + to: string, + getCanonicalFileNameOrIgnoreCase: GetCanonicalFileName | boolean, +) { + Debug.assert( + (getRootLength(fromDirectory) > 0) === (getRootLength(to) > 0), + "Paths must either both be absolute or both be relative", + ); + const getCanonicalFileName = typeof getCanonicalFileNameOrIgnoreCase === "function" + ? getCanonicalFileNameOrIgnoreCase : identity; const ignoreCase = typeof getCanonicalFileNameOrIgnoreCase === "boolean" ? getCanonicalFileNameOrIgnoreCase : false; - const pathComponents = getPathComponentsRelativeTo(fromDirectory, to, ignoreCase ? equateStringsCaseInsensitive : equateStringsCaseSensitive, getCanonicalFileName); + const pathComponents = getPathComponentsRelativeTo( + fromDirectory, + to, + ignoreCase ? equateStringsCaseInsensitive : equateStringsCaseSensitive, + getCanonicalFileName, + ); return getPathFromPathComponents(pathComponents); } /** @internal */ -export function convertToRelativePath(absoluteOrRelativePath: string, basePath: string, getCanonicalFileName: (path: string) => string): string { +export function convertToRelativePath( + absoluteOrRelativePath: string, + basePath: string, + getCanonicalFileName: (path: string) => string, +): string { return !isRootedDiskPath(absoluteOrRelativePath) ? absoluteOrRelativePath - : getRelativePathToDirectoryOrUrl(basePath, absoluteOrRelativePath, basePath, getCanonicalFileName, /*isAbsolutePathAnUrl*/ false); + : getRelativePathToDirectoryOrUrl( + basePath, + absoluteOrRelativePath, + basePath, + getCanonicalFileName, + /*isAbsolutePathAnUrl*/ false, + ); } /** @internal */ @@ -947,7 +1021,13 @@ export function getRelativePathFromFile(from: string, to: string, getCanonicalFi } /** @internal */ -export function getRelativePathToDirectoryOrUrl(directoryPathOrUrl: string, relativeOrAbsolutePath: string, currentDirectory: string, getCanonicalFileName: GetCanonicalFileName, isAbsolutePathAnUrl: boolean) { +export function getRelativePathToDirectoryOrUrl( + directoryPathOrUrl: string, + relativeOrAbsolutePath: string, + currentDirectory: string, + getCanonicalFileName: GetCanonicalFileName, + isAbsolutePathAnUrl: boolean, +) { const pathComponents = getPathComponentsRelativeTo( resolvePath(currentDirectory, directoryPathOrUrl), resolvePath(currentDirectory, relativeOrAbsolutePath), @@ -971,11 +1051,20 @@ export function getRelativePathToDirectoryOrUrl(directoryPathOrUrl: string, rela * * @internal */ -export function forEachAncestorDirectory(directory: Path, callback: (directory: Path) => T | undefined): T | undefined; +export function forEachAncestorDirectory( + directory: Path, + callback: (directory: Path) => T | undefined, +): T | undefined; /** @internal */ -export function forEachAncestorDirectory(directory: string, callback: (directory: string) => T | undefined): T | undefined; +export function forEachAncestorDirectory( + directory: string, + callback: (directory: string) => T | undefined, +): T | undefined; /** @internal */ -export function forEachAncestorDirectory(directory: P, callback: (directory: P) => T | undefined): T | undefined { +export function forEachAncestorDirectory( + directory: P, + callback: (directory: P) => T | undefined, +): T | undefined { while (true) { const result = callback(directory); if (result !== undefined) { diff --git a/src/compiler/performanceCore.ts b/src/compiler/performanceCore.ts index a214ced47ef2c..022ba21d44938 100644 --- a/src/compiler/performanceCore.ts +++ b/src/compiler/performanceCore.ts @@ -45,7 +45,9 @@ export interface PerformanceObserver { } /** @internal */ -export type PerformanceObserverConstructor = new (callback: (list: PerformanceObserverEntryList, observer: PerformanceObserver) => void) => PerformanceObserver; +export type PerformanceObserverConstructor = new ( + callback: (list: PerformanceObserverEntryList, observer: PerformanceObserver) => void, +) => PerformanceObserver; /** @internal */ export type PerformanceEntryList = PerformanceEntry[]; @@ -54,22 +56,25 @@ declare const performance: Performance | undefined; declare const PerformanceObserver: PerformanceObserverConstructor | undefined; // eslint-disable-next-line @typescript-eslint/naming-convention -function hasRequiredAPI(performance: Performance | undefined, PerformanceObserver: PerformanceObserverConstructor | undefined) { - return typeof performance === "object" && - typeof performance.timeOrigin === "number" && - typeof performance.mark === "function" && - typeof performance.measure === "function" && - typeof performance.now === "function" && - typeof performance.clearMarks === "function" && - typeof performance.clearMeasures === "function" && - typeof PerformanceObserver === "function"; +function hasRequiredAPI( + performance: Performance | undefined, + PerformanceObserver: PerformanceObserverConstructor | undefined, +) { + return typeof performance === "object" + && typeof performance.timeOrigin === "number" + && typeof performance.mark === "function" + && typeof performance.measure === "function" + && typeof performance.now === "function" + && typeof performance.clearMarks === "function" + && typeof performance.clearMeasures === "function" + && typeof PerformanceObserver === "function"; } function tryGetWebPerformanceHooks(): PerformanceHooks | undefined { if ( - typeof performance === "object" && - typeof PerformanceObserver === "function" && - hasRequiredAPI(performance, PerformanceObserver) + typeof performance === "object" + && typeof PerformanceObserver === "function" + && hasRequiredAPI(performance, PerformanceObserver) ) { return { // For now we always write native performance events when running in the browser. We may @@ -116,6 +121,6 @@ export function tryGetNativePerformanceHooks() { * * @internal */ -export const timestamp = nativePerformance ? () => nativePerformance.now() : - Date.now ? Date.now : - () => +(new Date()); +export const timestamp = nativePerformance ? () => nativePerformance.now() + : Date.now ? Date.now + : () => +(new Date()); diff --git a/src/compiler/program.ts b/src/compiler/program.ts index e1052f5f47cb5..d05be9ccd0754 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -337,7 +337,11 @@ import { } from "./_namespaces/ts"; import * as performance from "./_namespaces/ts.performance"; -export function findConfigFile(searchPath: string, fileExists: (fileName: string) => boolean, configName = "tsconfig.json"): string | undefined { +export function findConfigFile( + searchPath: string, + fileExists: (fileName: string) => boolean, + configName = "tsconfig.json", +): string | undefined { return forEachAncestorDirectory(searchPath, ancestor => { const fileName = combinePaths(ancestor, configName); return fileExists(fileName) ? fileName : undefined; @@ -351,7 +355,11 @@ export function resolveTripleslashReference(moduleName: string, containingFile: } /** @internal */ -export function computeCommonSourceDirectoryOfFilenames(fileNames: readonly string[], currentDirectory: string, getCanonicalFileName: GetCanonicalFileName): string { +export function computeCommonSourceDirectoryOfFilenames( + fileNames: readonly string[], + currentDirectory: string, + getCanonicalFileName: GetCanonicalFileName, +): string { let commonPathComponents: string[] | undefined; const failed = forEach(fileNames, sourceFile => { // Each file contributes into common source file path @@ -420,7 +428,8 @@ export function createGetSourceFile( } text = ""; } - return text !== undefined ? createSourceFile(fileName, text, languageVersionOrOptions, setParentNodes) : undefined; + return text !== undefined ? createSourceFile(fileName, text, languageVersionOrOptions, setParentNodes) + : undefined; }; } @@ -458,7 +467,11 @@ export function createWriteFileMeasuringIO( } /** @internal */ -export function createCompilerHostWorker(options: CompilerOptions, setParentNodes?: boolean, system: System = sys): CompilerHost { +export function createCompilerHostWorker( + options: CompilerOptions, + setParentNodes?: boolean, + system: System = sys, +): CompilerHost { const existingDirectories = new Map(); const getCanonicalFileName = createGetCanonicalFileName(system.useCaseSensitiveFileNames); function directoryExists(directoryPath: string): boolean { @@ -498,7 +511,8 @@ export function createCompilerHostWorker(options: CompilerOptions, setParentNode getEnvironmentVariable: name => system.getEnvironmentVariable ? system.getEnvironmentVariable(name) : "", getDirectories: (path: string) => system.getDirectories(path), realpath, - readDirectory: (path, extensions, include, exclude, depth) => system.readDirectory(path, extensions, include, exclude, depth), + readDirectory: (path, extensions, include, exclude, depth) => + system.readDirectory(path, extensions, include, exclude, depth), createDirectory: d => system.createDirectory(d), createHash: maybeBind(system, system.createHash), }; @@ -553,19 +567,21 @@ export function changeCompilerHostLikeToUseCache( return setReadFileCache(key, fileName); }; - const getSourceFileWithCache: CompilerHost["getSourceFile"] | undefined = getSourceFile ? (fileName, languageVersionOrOptions, onError, shouldCreateNewSourceFile) => { - const key = toPath(fileName); - const impliedNodeFormat: ResolutionMode = typeof languageVersionOrOptions === "object" ? languageVersionOrOptions.impliedNodeFormat : undefined; - const forImpliedNodeFormat = sourceFileCache.get(impliedNodeFormat); - const value = forImpliedNodeFormat?.get(key); - if (value) return value; + const getSourceFileWithCache: CompilerHost["getSourceFile"] | undefined = getSourceFile + ? (fileName, languageVersionOrOptions, onError, shouldCreateNewSourceFile) => { + const key = toPath(fileName); + const impliedNodeFormat: ResolutionMode = typeof languageVersionOrOptions === "object" + ? languageVersionOrOptions.impliedNodeFormat : undefined; + const forImpliedNodeFormat = sourceFileCache.get(impliedNodeFormat); + const value = forImpliedNodeFormat?.get(key); + if (value) return value; - const sourceFile = getSourceFile(fileName, languageVersionOrOptions, onError, shouldCreateNewSourceFile); - if (sourceFile && (isDeclarationFileName(fileName) || fileExtensionIs(fileName, Extension.Json))) { - sourceFileCache.set(impliedNodeFormat, (forImpliedNodeFormat || new Map()).set(key, sourceFile)); - } - return sourceFile; - } : undefined; + const sourceFile = getSourceFile(fileName, languageVersionOrOptions, onError, shouldCreateNewSourceFile); + if (sourceFile && (isDeclarationFileName(fileName) || fileExtensionIs(fileName, Extension.Json))) { + sourceFileCache.set(impliedNodeFormat, (forImpliedNodeFormat || new Map()).set(key, sourceFile)); + } + return sourceFile; + } : undefined; // fileExists for any kind of extension host.fileExists = fileName => { @@ -629,9 +645,21 @@ export function changeCompilerHostLikeToUseCache( }; } -export function getPreEmitDiagnostics(program: Program, sourceFile?: SourceFile, cancellationToken?: CancellationToken): readonly Diagnostic[]; -/** @internal */ export function getPreEmitDiagnostics(program: BuilderProgram, sourceFile?: SourceFile, cancellationToken?: CancellationToken): readonly Diagnostic[]; // eslint-disable-line @typescript-eslint/unified-signatures -export function getPreEmitDiagnostics(program: Program | BuilderProgram, sourceFile?: SourceFile, cancellationToken?: CancellationToken): readonly Diagnostic[] { +export function getPreEmitDiagnostics( + program: Program, + sourceFile?: SourceFile, + cancellationToken?: CancellationToken, +): readonly Diagnostic[]; +/** @internal */ export function getPreEmitDiagnostics( + program: BuilderProgram, + sourceFile?: SourceFile, + cancellationToken?: CancellationToken, +): readonly Diagnostic[]; // eslint-disable-line @typescript-eslint/unified-signatures +export function getPreEmitDiagnostics( + program: Program | BuilderProgram, + sourceFile?: SourceFile, + cancellationToken?: CancellationToken, +): readonly Diagnostic[] { let diagnostics: Diagnostic[] | undefined; diagnostics = addRange(diagnostics, program.getConfigFileParsingDiagnostics()); diagnostics = addRange(diagnostics, program.getOptionsDiagnostics(cancellationToken)); @@ -662,12 +690,18 @@ export function formatDiagnostics(diagnostics: readonly Diagnostic[], host: Form } export function formatDiagnostic(diagnostic: Diagnostic, host: FormatDiagnosticsHost): string { - const errorMessage = `${diagnosticCategoryName(diagnostic)} TS${diagnostic.code}: ${flattenDiagnosticMessageText(diagnostic.messageText, host.getNewLine())}${host.getNewLine()}`; + const errorMessage = `${diagnosticCategoryName(diagnostic)} TS${diagnostic.code}: ${ + flattenDiagnosticMessageText(diagnostic.messageText, host.getNewLine()) + }${host.getNewLine()}`; if (diagnostic.file) { const { line, character } = getLineAndCharacterOfPosition(diagnostic.file, diagnostic.start!); // TODO: GH#18217 const fileName = diagnostic.file.fileName; - const relativeFileName = convertToRelativePath(fileName, host.getCurrentDirectory(), fileName => host.getCanonicalFileName(fileName)); + const relativeFileName = convertToRelativePath( + fileName, + host.getCurrentDirectory(), + fileName => host.getCanonicalFileName(fileName), + ); return `${relativeFileName}(${line + 1},${character + 1}): ` + errorMessage; } @@ -706,7 +740,14 @@ export function formatColorAndReset(text: string, formatStyle: string) { return formatStyle + text + resetEscapeSequence; } -function formatCodeSpan(file: SourceFile, start: number, length: number, indent: string, squiggleColor: ForegroundColorEscapeSequences, host: FormatDiagnosticsHost) { +function formatCodeSpan( + file: SourceFile, + start: number, + length: number, + indent: string, + squiggleColor: ForegroundColorEscapeSequences, + host: FormatDiagnosticsHost, +) { const { line: firstLine, character: firstLineChar } = getLineAndCharacterOfPosition(file, start); const { line: lastLine, character: lastLineChar } = getLineAndCharacterOfPosition(file, start + length); const lastLineInFile = getLineAndCharacterOfPosition(file, file.text.length).line; @@ -723,7 +764,8 @@ function formatCodeSpan(file: SourceFile, start: number, length: number, indent: // If the error spans over 5 lines, we'll only show the first 2 and last 2 lines, // so we'll skip ahead to the second-to-last line. if (hasMoreThanFiveLines && firstLine + 1 < i && i < lastLine - 1) { - context += indent + formatColorAndReset(padLeft(ellipsis, gutterWidth), gutterStyleSequence) + gutterSeparator + host.getNewLine(); + context += indent + formatColorAndReset(padLeft(ellipsis, gutterWidth), gutterStyleSequence) + + gutterSeparator + host.getNewLine(); i = lastLine - 1; } @@ -734,7 +776,8 @@ function formatCodeSpan(file: SourceFile, start: number, length: number, indent: lineContent = lineContent.replace(/\t/g, " "); // convert tabs to single spaces // Output the gutter and the actual contents of the line. - context += indent + formatColorAndReset(padLeft(i + 1 + "", gutterWidth), gutterStyleSequence) + gutterSeparator; + context += indent + formatColorAndReset(padLeft(i + 1 + "", gutterWidth), gutterStyleSequence) + + gutterSeparator; context += lineContent + host.getNewLine(); // Output the gutter and the error span for the line using tildes. @@ -761,9 +804,19 @@ function formatCodeSpan(file: SourceFile, start: number, length: number, indent: } /** @internal */ -export function formatLocation(file: SourceFile, start: number, host: FormatDiagnosticsHost, color = formatColorAndReset) { +export function formatLocation( + file: SourceFile, + start: number, + host: FormatDiagnosticsHost, + color = formatColorAndReset, +) { const { line: firstLine, character: firstLineChar } = getLineAndCharacterOfPosition(file, start); // TODO: GH#18217 - const relativeFileName = host ? convertToRelativePath(file.fileName, host.getCurrentDirectory(), fileName => host.getCanonicalFileName(fileName)) : file.fileName; + const relativeFileName = host + ? convertToRelativePath( + file.fileName, + host.getCurrentDirectory(), + fileName => host.getCanonicalFileName(fileName), + ) : file.fileName; let output = ""; output += color(relativeFileName, ForegroundColorEscapeSequences.Cyan); @@ -774,7 +827,10 @@ export function formatLocation(file: SourceFile, start: number, host: FormatDiag return output; } -export function formatDiagnosticsWithColorAndContext(diagnostics: readonly Diagnostic[], host: FormatDiagnosticsHost): string { +export function formatDiagnosticsWithColorAndContext( + diagnostics: readonly Diagnostic[], + host: FormatDiagnosticsHost, +): string { let output = ""; for (const diagnostic of diagnostics) { if (diagnostic.file) { @@ -789,7 +845,14 @@ export function formatDiagnosticsWithColorAndContext(diagnostics: readonly Diagn if (diagnostic.file && diagnostic.code !== Diagnostics.File_appears_to_be_binary.code) { output += host.getNewLine(); - output += formatCodeSpan(diagnostic.file, diagnostic.start!, diagnostic.length!, "", getCategoryFormat(diagnostic.category), host); // TODO: GH#18217 + output += formatCodeSpan( + diagnostic.file, + diagnostic.start!, + diagnostic.length!, + "", + getCategoryFormat(diagnostic.category), + host, + ); // TODO: GH#18217 } if (diagnostic.relatedInformation) { output += host.getNewLine(); @@ -808,7 +871,11 @@ export function formatDiagnosticsWithColorAndContext(diagnostics: readonly Diagn return output; } -export function flattenDiagnosticMessageText(diag: string | DiagnosticMessageChain | undefined, newLine: string, indent = 0): string { +export function flattenDiagnosticMessageText( + diag: string | DiagnosticMessageChain | undefined, + newLine: string, + indent = 0, +): string { if (isString(diag)) { return diag; } @@ -920,10 +987,16 @@ export function getModeForUsageLocation(file: { impliedNodeFormat?: ResolutionMo } /** @internal */ -export function getResolutionModeOverrideForClause(clause: AssertClause | undefined, grammarErrorOnNode?: (node: Node, diagnostic: DiagnosticMessage) => void) { +export function getResolutionModeOverrideForClause( + clause: AssertClause | undefined, + grammarErrorOnNode?: (node: Node, diagnostic: DiagnosticMessage) => void, +) { if (!clause) return undefined; if (length(clause.elements) !== 1) { - grammarErrorOnNode?.(clause, Diagnostics.Type_import_assertions_should_have_exactly_one_key_resolution_mode_with_value_import_or_require); + grammarErrorOnNode?.( + clause, + Diagnostics.Type_import_assertions_should_have_exactly_one_key_resolution_mode_with_value_import_or_require, + ); return undefined; } const elem = clause.elements[0]; @@ -940,10 +1013,12 @@ export function getResolutionModeOverrideForClause(clause: AssertClause | undefi return elem.value.text === "import" ? ModuleKind.ESNext : ModuleKind.CommonJS; } -const emptyResolution: ResolvedModuleWithFailedLookupLocations & ResolvedTypeReferenceDirectiveWithFailedLookupLocations = { - resolvedModule: undefined, - resolvedTypeReferenceDirective: undefined, -}; +const emptyResolution: + & ResolvedModuleWithFailedLookupLocations + & ResolvedTypeReferenceDirectiveWithFailedLookupLocations = { + resolvedModule: undefined, + resolvedTypeReferenceDirective: undefined, + }; /** @internal */ export interface ResolutionNameAndModeGetter { @@ -996,7 +1071,10 @@ function getTypeReferenceResolutionName(entry: } /** @internal */ -export const typeReferenceResolutionNameAndModeGetter: ResolutionNameAndModeGetter = { +export const typeReferenceResolutionNameAndModeGetter: ResolutionNameAndModeGetter< + FileReference | string, + SourceFile | undefined +> = { getName: getTypeReferenceResolutionName, getMode: (entry, file) => getModeForFileReference(entry, file?.impliedNodeFormat), }; @@ -1061,16 +1139,30 @@ export function loadWithModeAwareCache( resolvedProjectReferences: readonly (ResolvedProjectReference | undefined)[] | undefined, - cb: (resolvedProjectReference: ResolvedProjectReference, parent: ResolvedProjectReference | undefined) => T | undefined, + cb: ( + resolvedProjectReference: ResolvedProjectReference, + parent: ResolvedProjectReference | undefined, + ) => T | undefined, ): T | undefined { - return forEachProjectReference(/*projectReferences*/ undefined, resolvedProjectReferences, (resolvedRef, parent) => resolvedRef && cb(resolvedRef, parent)); + return forEachProjectReference( + /*projectReferences*/ undefined, + resolvedProjectReferences, + (resolvedRef, parent) => resolvedRef && cb(resolvedRef, parent), + ); } function forEachProjectReference( projectReferences: readonly ProjectReference[] | undefined, resolvedProjectReferences: readonly (ResolvedProjectReference | undefined)[] | undefined, - cbResolvedRef: (resolvedRef: ResolvedProjectReference | undefined, parent: ResolvedProjectReference | undefined, index: number) => T | undefined, - cbRef?: (projectReferences: readonly ProjectReference[] | undefined, parent: ResolvedProjectReference | undefined) => T | undefined, + cbResolvedRef: ( + resolvedRef: ResolvedProjectReference | undefined, + parent: ResolvedProjectReference | undefined, + index: number, + ) => T | undefined, + cbRef?: ( + projectReferences: readonly ProjectReference[] | undefined, + parent: ResolvedProjectReference | undefined, + ) => T | undefined, ): T | undefined { let seenResolvedRefs: Set | undefined; @@ -1106,7 +1198,11 @@ function forEachProjectReference( export const inferredTypesContainingFile = "__inferred type names__.ts"; /** @internal */ -export function getInferredLibraryNameResolveFrom(options: CompilerOptions, currentDirectory: string, libFileName: string) { +export function getInferredLibraryNameResolveFrom( + options: CompilerOptions, + currentDirectory: string, + libFileName: string, +) { const containingDirectory = options.configFilePath ? getDirectoryPath(options.configFilePath) : currentDirectory; return combinePaths(containingDirectory, `__lib_node_modules_lookup_${libFileName}__.ts`); } @@ -1165,19 +1261,28 @@ export interface SyntheticReferenceFileLocation { } /** @internal */ -export function isReferenceFileLocation(location: ReferenceFileLocation | SyntheticReferenceFileLocation): location is ReferenceFileLocation { +export function isReferenceFileLocation( + location: ReferenceFileLocation | SyntheticReferenceFileLocation, +): location is ReferenceFileLocation { return (location as ReferenceFileLocation).pos !== undefined; } /** @internal */ -export function getReferencedFileLocation(getSourceFileByPath: (path: Path) => SourceFile | undefined, ref: ReferencedFile): ReferenceFileLocation | SyntheticReferenceFileLocation { +export function getReferencedFileLocation( + getSourceFileByPath: (path: Path) => SourceFile | undefined, + ref: ReferencedFile, +): ReferenceFileLocation | SyntheticReferenceFileLocation { const file = Debug.checkDefined(getSourceFileByPath(ref.file)); const { kind, index } = ref; - let pos: number | undefined, end: number | undefined, packageId: PackageId | undefined, resolutionMode: FileReference["resolutionMode"] | undefined; + let pos: number | undefined, + end: number | undefined, + packageId: PackageId | undefined, + resolutionMode: FileReference["resolutionMode"] | undefined; switch (kind) { case FileIncludeKind.Import: const importLiteral = getModuleNameStringLiteralAt(file, index); - packageId = file.resolvedModules?.get(importLiteral.text, getModeForResolutionAtIndex(file, index))?.resolvedModule?.packageId; + packageId = file.resolvedModules?.get(importLiteral.text, getModeForResolutionAtIndex(file, index)) + ?.resolvedModule?.packageId; if (importLiteral.pos === -1) return { file, packageId, text: importLiteral.text }; pos = skipTrivia(file.text, importLiteral.pos); end = importLiteral.end; @@ -1187,7 +1292,10 @@ export function getReferencedFileLocation(getSourceFileByPath: (path: Path) => S break; case FileIncludeKind.TypeReferenceDirective: ({ pos, end, resolutionMode } = file.typeReferenceDirectives[index]); - packageId = file.resolvedTypeReferenceDirectiveNames?.get(toFileNameLowerCase(file.typeReferenceDirectives[index].fileName), resolutionMode || file.impliedNodeFormat)?.resolvedTypeReferenceDirective?.packageId; + packageId = file.resolvedTypeReferenceDirectiveNames?.get( + toFileNameLowerCase(file.typeReferenceDirectives[index].fileName), + resolutionMode || file.impliedNodeFormat, + )?.resolvedTypeReferenceDirective?.packageId; break; case FileIncludeKind.LibReferenceDirective: ({ pos, end } = file.libReferenceDirectives[index]); @@ -1237,17 +1345,25 @@ export function isProgramUptoDate( if (!compareDataObjects(currentOptions, newOptions)) return false; // If library resolution is invalidated, then the program is not up-to-date - if (program.resolvedLibReferences && forEachEntry(program.resolvedLibReferences, (_value, libFileName) => hasInvalidatedLibResolutions(libFileName))) return false; + if ( + program.resolvedLibReferences + && forEachEntry( + program.resolvedLibReferences, + (_value, libFileName) => hasInvalidatedLibResolutions(libFileName), + ) + ) return false; // If everything matches but the text of config file is changed, // error locations can change for program options, so update the program - if (currentOptions.configFile && newOptions.configFile) return currentOptions.configFile.text === newOptions.configFile.text; + if (currentOptions.configFile && newOptions.configFile) { + return currentOptions.configFile.text === newOptions.configFile.text; + } return true; function sourceFileNotUptoDate(sourceFile: SourceFile) { - return !sourceFileVersionUptoDate(sourceFile) || - hasInvalidatedResolutions(sourceFile.path); + return !sourceFileVersionUptoDate(sourceFile) + || hasInvalidatedResolutions(sourceFile.path); } function sourceFileVersionUptoDate(sourceFile: SourceFile) { @@ -1255,11 +1371,14 @@ export function isProgramUptoDate( } function projectReferenceUptoDate(oldRef: ProjectReference, newRef: ProjectReference, index: number) { - return projectReferenceIsEqualTo(oldRef, newRef) && - resolvedProjectReferenceUptoDate(program!.getResolvedProjectReferences()![index], oldRef); + return projectReferenceIsEqualTo(oldRef, newRef) + && resolvedProjectReferenceUptoDate(program!.getResolvedProjectReferences()![index], oldRef); } - function resolvedProjectReferenceUptoDate(oldResolvedRef: ResolvedProjectReference | undefined, oldRef: ProjectReference): boolean { + function resolvedProjectReferenceUptoDate( + oldResolvedRef: ResolvedProjectReference | undefined, + oldRef: ProjectReference, + ): boolean { if (oldResolvedRef) { // Assume true if (contains(seenResolvedRefs, oldResolvedRef)) return true; @@ -1280,7 +1399,14 @@ export function isProgramUptoDate( (seenResolvedRefs || (seenResolvedRefs = [])).push(oldResolvedRef); // If child project references are upto date, this project reference is uptodate - return !forEach(oldResolvedRef.references, (childResolvedRef, index) => !resolvedProjectReferenceUptoDate(childResolvedRef, oldResolvedRef.commandLine.projectReferences![index])); + return !forEach( + oldResolvedRef.references, + (childResolvedRef, index) => + !resolvedProjectReferenceUptoDate( + childResolvedRef, + oldResolvedRef.commandLine.projectReferences![index], + ), + ); } // In old program, not able to resolve project reference path, @@ -1291,9 +1417,9 @@ export function isProgramUptoDate( } export function getConfigFileParsingDiagnostics(configFileParseResult: ParsedCommandLine): readonly Diagnostic[] { - return configFileParseResult.options.configFile ? - [...configFileParseResult.options.configFile.parseDiagnostics, ...configFileParseResult.errors] : - configFileParseResult.errors; + return configFileParseResult.options.configFile + ? [...configFileParseResult.options.configFile.parseDiagnostics, ...configFileParseResult.errors] + : configFileParseResult.errors; } /** @@ -1306,7 +1432,12 @@ export function getConfigFileParsingDiagnostics(configFileParseResult: ParsedCom * @param options The compiler options to perform the analysis under - relevant options are `moduleResolution` and `traceResolution` * @returns `undefined` if the path has no relevant implied format, `ModuleKind.ESNext` for esm format, and `ModuleKind.CommonJS` for cjs format */ -export function getImpliedNodeFormatForFile(fileName: Path, packageJsonInfoCache: PackageJsonInfoCache | undefined, host: ModuleResolutionHost, options: CompilerOptions): ResolutionMode { +export function getImpliedNodeFormatForFile( + fileName: Path, + packageJsonInfoCache: PackageJsonInfoCache | undefined, + host: ModuleResolutionHost, + options: CompilerOptions, +): ResolutionMode { const result = getImpliedNodeFormatForFileWorker(fileName, packageJsonInfoCache, host, options); return typeof result === "object" ? result.impliedNodeFormat : result; } @@ -1321,10 +1452,16 @@ export function getImpliedNodeFormatForFileWorker( switch (getEmitModuleResolutionKind(options)) { case ModuleResolutionKind.Node16: case ModuleResolutionKind.NodeNext: - return fileExtensionIsOneOf(fileName, [Extension.Dmts, Extension.Mts, Extension.Mjs]) ? ModuleKind.ESNext : - fileExtensionIsOneOf(fileName, [Extension.Dcts, Extension.Cts, Extension.Cjs]) ? ModuleKind.CommonJS : - fileExtensionIsOneOf(fileName, [Extension.Dts, Extension.Ts, Extension.Tsx, Extension.Js, Extension.Jsx]) ? lookupFromPackageJson() : - undefined; // other extensions, like `json` or `tsbuildinfo`, are set as `undefined` here but they should never be fed through the transformer pipeline + return fileExtensionIsOneOf(fileName, [Extension.Dmts, Extension.Mts, Extension.Mjs]) ? ModuleKind.ESNext + : fileExtensionIsOneOf(fileName, [Extension.Dcts, Extension.Cts, Extension.Cjs]) ? ModuleKind.CommonJS + : fileExtensionIsOneOf(fileName, [ + Extension.Dts, + Extension.Ts, + Extension.Tsx, + Extension.Js, + Extension.Jsx, + ]) ? lookupFromPackageJson() + : undefined; // other extensions, like `json` or `tsbuildinfo`, are set as `undefined` here but they should never be fed through the transformer pipeline default: return undefined; } @@ -1334,7 +1471,8 @@ export function getImpliedNodeFormatForFileWorker( state.failedLookupLocations = packageJsonLocations; state.affectingLocations = packageJsonLocations; const packageJsonScope = getPackageScopeForPath(fileName, state); - const impliedNodeFormat = packageJsonScope?.contents.packageJsonContent.type === "module" ? ModuleKind.ESNext : ModuleKind.CommonJS; + const impliedNodeFormat = packageJsonScope?.contents.packageJsonContent.type === "module" ? ModuleKind.ESNext + : ModuleKind.CommonJS; return { impliedNodeFormat, packageJsonLocations, packageJsonScope }; } } @@ -1351,7 +1489,9 @@ export const plainJSErrors = new Set([ Diagnostics.Identifier_expected_0_is_a_reserved_word_that_cannot_be_used_here.code, Diagnostics.constructor_is_a_reserved_word.code, Diagnostics.delete_cannot_be_called_on_an_identifier_in_strict_mode.code, - Diagnostics.Code_contained_in_a_class_is_evaluated_in_JavaScript_s_strict_mode_which_does_not_allow_this_use_of_0_For_more_information_see_https_Colon_Slash_Slashdeveloper_mozilla_org_Slashen_US_Slashdocs_SlashWeb_SlashJavaScript_SlashReference_SlashStrict_mode.code, + Diagnostics + .Code_contained_in_a_class_is_evaluated_in_JavaScript_s_strict_mode_which_does_not_allow_this_use_of_0_For_more_information_see_https_Colon_Slash_Slashdeveloper_mozilla_org_Slashen_US_Slashdocs_SlashWeb_SlashJavaScript_SlashReference_SlashStrict_mode + .code, Diagnostics.Invalid_use_of_0_Modules_are_automatically_in_strict_mode.code, Diagnostics.Invalid_use_of_0_in_strict_mode.code, Diagnostics.A_label_is_not_allowed_here.code, @@ -1389,10 +1529,14 @@ export const plainJSErrors = new Set([ Diagnostics.Cannot_assign_to_private_method_0_Private_methods_are_not_writable.code, Diagnostics.Cannot_redeclare_identifier_0_in_catch_clause.code, Diagnostics.Catch_clause_variable_cannot_have_an_initializer.code, - Diagnostics.Class_decorators_can_t_be_used_with_static_private_identifier_Consider_removing_the_experimental_decorator.code, + Diagnostics + .Class_decorators_can_t_be_used_with_static_private_identifier_Consider_removing_the_experimental_decorator + .code, Diagnostics.Classes_can_only_extend_a_single_class.code, Diagnostics.Classes_may_not_have_a_field_named_constructor.code, - Diagnostics.Did_you_mean_to_use_a_Colon_An_can_only_follow_a_property_name_when_the_containing_object_literal_is_part_of_a_destructuring_pattern.code, + Diagnostics + .Did_you_mean_to_use_a_Colon_An_can_only_follow_a_property_name_when_the_containing_object_literal_is_part_of_a_destructuring_pattern + .code, Diagnostics.Duplicate_label_0.code, Diagnostics.Dynamic_imports_can_only_accept_a_module_specifier_and_an_optional_assertion_as_arguments.code, Diagnostics.for_await_loops_cannot_be_used_inside_a_class_static_block.code, @@ -1406,7 +1550,9 @@ export const plainJSErrors = new Set([ Diagnostics.Only_a_single_variable_declaration_is_allowed_in_a_for_in_statement.code, Diagnostics.Only_a_single_variable_declaration_is_allowed_in_a_for_of_statement.code, Diagnostics.Private_identifiers_are_not_allowed_outside_class_bodies.code, - Diagnostics.Private_identifiers_are_only_allowed_in_class_bodies_and_may_only_be_used_as_part_of_a_class_member_declaration_property_access_or_on_the_left_hand_side_of_an_in_expression.code, + Diagnostics + .Private_identifiers_are_only_allowed_in_class_bodies_and_may_only_be_used_as_part_of_a_class_member_declaration_property_access_or_on_the_left_hand_side_of_an_in_expression + .code, Diagnostics.Property_0_is_not_accessible_outside_class_1_because_it_has_a_private_identifier.code, Diagnostics.Tagged_template_expressions_are_not_permitted_in_an_optional_chain.code, Diagnostics.The_left_hand_side_of_a_for_of_statement_may_not_be_async.code, @@ -1448,7 +1594,14 @@ function shouldProgramCreateNewSourceFiles(program: Program | undefined, newOpti return optionsHaveChanges(program.getCompilerOptions(), newOptions, sourceFileAffectingCompilerOptions); } -function createCreateProgramOptions(rootNames: readonly string[], options: CompilerOptions, host?: CompilerHost, oldProgram?: Program, configFileParsingDiagnostics?: readonly Diagnostic[], typeScriptVersion?: string): CreateProgramOptions { +function createCreateProgramOptions( + rootNames: readonly string[], + options: CompilerOptions, + host?: CompilerHost, + oldProgram?: Program, + configFileParsingDiagnostics?: readonly Diagnostic[], + typeScriptVersion?: string, +): CreateProgramOptions { return { rootNames, options, @@ -1484,13 +1637,30 @@ export function createProgram(createProgramOptions: CreateProgramOptions): Progr * @param configFileParsingDiagnostics - error during config file parsing * @returns A 'Program' object. */ -export function createProgram(rootNames: readonly string[], options: CompilerOptions, host?: CompilerHost, oldProgram?: Program, configFileParsingDiagnostics?: readonly Diagnostic[]): Program; -export function createProgram(rootNamesOrOptions: readonly string[] | CreateProgramOptions, _options?: CompilerOptions, _host?: CompilerHost, _oldProgram?: Program, _configFileParsingDiagnostics?: readonly Diagnostic[]): Program { - const createProgramOptions = isArray(rootNamesOrOptions) ? createCreateProgramOptions(rootNamesOrOptions, _options!, _host, _oldProgram, _configFileParsingDiagnostics) : rootNamesOrOptions; // TODO: GH#18217 - const { rootNames, options, configFileParsingDiagnostics, projectReferences, typeScriptVersion } = createProgramOptions; +export function createProgram( + rootNames: readonly string[], + options: CompilerOptions, + host?: CompilerHost, + oldProgram?: Program, + configFileParsingDiagnostics?: readonly Diagnostic[], +): Program; +export function createProgram( + rootNamesOrOptions: readonly string[] | CreateProgramOptions, + _options?: CompilerOptions, + _host?: CompilerHost, + _oldProgram?: Program, + _configFileParsingDiagnostics?: readonly Diagnostic[], +): Program { + const createProgramOptions = isArray(rootNamesOrOptions) + ? createCreateProgramOptions(rootNamesOrOptions, _options!, _host, _oldProgram, _configFileParsingDiagnostics) + : rootNamesOrOptions; // TODO: GH#18217 + const { rootNames, options, configFileParsingDiagnostics, projectReferences, typeScriptVersion } = + createProgramOptions; let { oldProgram } = createProgramOptions; - const reportInvalidIgnoreDeprecations = memoize(() => createOptionValueDiagnostic("ignoreDeprecations", Diagnostics.Invalid_value_for_ignoreDeprecations)); + const reportInvalidIgnoreDeprecations = memoize(() => + createOptionValueDiagnostic("ignoreDeprecations", Diagnostics.Invalid_value_for_ignoreDeprecations) + ); let processingDefaultLibFiles: SourceFile[] | undefined; let processingOtherFiles: SourceFile[] | undefined; @@ -1504,7 +1674,9 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg const cachedBindAndCheckDiagnosticsForFile: DiagnosticCache = {}; const cachedDeclarationDiagnosticsForFile: DiagnosticCache = {}; - let resolvedTypeReferenceDirectives = createModeAwareCache(); + let resolvedTypeReferenceDirectives = createModeAwareCache< + ResolvedTypeReferenceDirectiveWithFailedLookupLocations + >(); let fileProcessingDiagnostics: FilePreprocessingDiagnostics[] | undefined; let automaticTypeDirectiveNames: string[] | undefined; let automaticTypeDirectiveResolutions: ModeAwareCache; @@ -1531,7 +1703,10 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg // Track source files that are source files found by searching under node_modules, as these shouldn't be compiled. const sourceFilesFoundSearchingNodeModules = new Map(); - tracing?.push(tracing.Phase.Program, "createProgram", { configFilePath: options.configFilePath, rootDir: options.rootDir }, /*separateBeginAndEnd*/ true); + tracing?.push(tracing.Phase.Program, "createProgram", { + configFilePath: options.configFilePath, + rootDir: options.rootDir, + }, /*separateBeginAndEnd*/ true); performance.mark("beforeProgram"); const host = createProgramOptions.host || createCompilerHost(options); @@ -1539,7 +1714,8 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg let skipDefaultLib = options.noLib; const getDefaultLibraryFileName = memoize(() => host.getDefaultLibFileName(options)); - const defaultLibraryPath = host.getDefaultLibLocation ? host.getDefaultLibLocation() : getDirectoryPath(getDefaultLibraryFileName()); + const defaultLibraryPath = host.getDefaultLibLocation ? host.getDefaultLibLocation() + : getDirectoryPath(getDefaultLibraryFileName()); /** * Diagnostics for the program * Only add diagnostics directly if it always would be done irrespective of program structure reuse. @@ -1548,7 +1724,10 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg const programDiagnostics = createDiagnosticCollection(); const currentDirectory = host.getCurrentDirectory(); const supportedExtensions = getSupportedExtensions(options); - const supportedExtensionsWithJsonIfResolveJsonModule = getSupportedExtensionsWithJsonIfResolveJsonModule(options, supportedExtensions); + const supportedExtensionsWithJsonIfResolveJsonModule = getSupportedExtensionsWithJsonIfResolveJsonModule( + options, + supportedExtensions, + ); // Map storing if there is emit blocking diagnostics for given input const hasEmitBlockingDiagnostics = new Map(); @@ -1569,37 +1748,48 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg moduleResolutionCache = host.getModuleResolutionCache?.(); } else if (host.resolveModuleNames) { - actualResolveModuleNamesWorker = (moduleNames, containingFile, redirectedReference, options, containingSourceFile, reusedNames) => - host.resolveModuleNames!( - moduleNames.map(getModuleResolutionName), - containingFile, - reusedNames?.map(getModuleResolutionName), - redirectedReference, - options, - containingSourceFile, - ).map(resolved => - resolved ? - ((resolved as ResolvedModuleFull).extension !== undefined) ? - { resolvedModule: resolved as ResolvedModuleFull } : - // An older host may have omitted extension, in which case we should infer it from the file extension of resolvedFileName. - { resolvedModule: { ...resolved, extension: extensionFromPath(resolved.resolvedFileName) } } : - emptyResolution - ); + actualResolveModuleNamesWorker = ( + moduleNames, + containingFile, + redirectedReference, + options, + containingSourceFile, + reusedNames, + ) => host.resolveModuleNames!( + moduleNames.map(getModuleResolutionName), + containingFile, + reusedNames?.map(getModuleResolutionName), + redirectedReference, + options, + containingSourceFile, + ).map(resolved => + resolved + ? ((resolved as ResolvedModuleFull).extension !== undefined) + ? { resolvedModule: resolved as ResolvedModuleFull } + // An older host may have omitted extension, in which case we should infer it from the file extension of resolvedFileName. + : { resolvedModule: { ...resolved, extension: extensionFromPath(resolved.resolvedFileName) } } + : emptyResolution + ); moduleResolutionCache = host.getModuleResolutionCache?.(); } else { moduleResolutionCache = createModuleResolutionCache(currentDirectory, getCanonicalFileName, options); - actualResolveModuleNamesWorker = (moduleNames, containingFile, redirectedReference, options, containingSourceFile) => - loadWithModeAwareCache( - moduleNames, - containingFile, - redirectedReference, - options, - containingSourceFile, - host, - moduleResolutionCache, - createModuleResolutionLoader, - ); + actualResolveModuleNamesWorker = ( + moduleNames, + containingFile, + redirectedReference, + options, + containingSourceFile, + ) => loadWithModeAwareCache( + moduleNames, + containingFile, + redirectedReference, + options, + containingSourceFile, + host, + moduleResolutionCache, + createModuleResolutionLoader, + ); } let actualResolveTypeReferenceDirectiveNamesWorker: ( @@ -1614,38 +1804,64 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg actualResolveTypeReferenceDirectiveNamesWorker = host.resolveTypeReferenceDirectiveReferences.bind(host); } else if (host.resolveTypeReferenceDirectives) { - actualResolveTypeReferenceDirectiveNamesWorker = (typeDirectiveNames, containingFile, redirectedReference, options, containingSourceFile) => - host.resolveTypeReferenceDirectives!( - typeDirectiveNames.map(getTypeReferenceResolutionName), - containingFile, - redirectedReference, - options, - containingSourceFile?.impliedNodeFormat, - ).map(resolvedTypeReferenceDirective => ({ resolvedTypeReferenceDirective })); + actualResolveTypeReferenceDirectiveNamesWorker = ( + typeDirectiveNames, + containingFile, + redirectedReference, + options, + containingSourceFile, + ) => host.resolveTypeReferenceDirectives!( + typeDirectiveNames.map(getTypeReferenceResolutionName), + containingFile, + redirectedReference, + options, + containingSourceFile?.impliedNodeFormat, + ).map(resolvedTypeReferenceDirective => ({ resolvedTypeReferenceDirective })); } else { - const typeReferenceDirectiveResolutionCache = createTypeReferenceDirectiveResolutionCache(currentDirectory, getCanonicalFileName, /*options*/ undefined, moduleResolutionCache?.getPackageJsonInfoCache()); - actualResolveTypeReferenceDirectiveNamesWorker = (typeDirectiveNames, containingFile, redirectedReference, options, containingSourceFile) => - loadWithModeAwareCache( - typeDirectiveNames, - containingFile, - redirectedReference, - options, - containingSourceFile, - host, - typeReferenceDirectiveResolutionCache, - createTypeReferenceResolutionLoader, - ); + const typeReferenceDirectiveResolutionCache = createTypeReferenceDirectiveResolutionCache( + currentDirectory, + getCanonicalFileName, + /*options*/ undefined, + moduleResolutionCache?.getPackageJsonInfoCache(), + ); + actualResolveTypeReferenceDirectiveNamesWorker = ( + typeDirectiveNames, + containingFile, + redirectedReference, + options, + containingSourceFile, + ) => loadWithModeAwareCache( + typeDirectiveNames, + containingFile, + redirectedReference, + options, + containingSourceFile, + host, + typeReferenceDirectiveResolutionCache, + createTypeReferenceResolutionLoader, + ); } const hasInvalidatedLibResolutions = host.hasInvalidatedLibResolutions || returnFalse; - let actualResolveLibrary: (libraryName: string, resolveFrom: string, options: CompilerOptions, libFileName: string) => ResolvedModuleWithFailedLookupLocations; + let actualResolveLibrary: ( + libraryName: string, + resolveFrom: string, + options: CompilerOptions, + libFileName: string, + ) => ResolvedModuleWithFailedLookupLocations; if (host.resolveLibrary) { actualResolveLibrary = host.resolveLibrary.bind(host); } else { - const libraryResolutionCache = createModuleResolutionCache(currentDirectory, getCanonicalFileName, options, moduleResolutionCache?.getPackageJsonInfoCache()); - actualResolveLibrary = (libraryName, resolveFrom, options) => resolveLibrary(libraryName, resolveFrom, options, host, libraryResolutionCache); + const libraryResolutionCache = createModuleResolutionCache( + currentDirectory, + getCanonicalFileName, + options, + moduleResolutionCache?.getPackageJsonInfoCache(), + ); + actualResolveLibrary = (libraryName, resolveFrom, options) => + resolveLibrary(libraryName, resolveFrom, options, host, libraryResolutionCache); } // Map from a stringified PackageId to the source file with that id. @@ -1676,8 +1892,8 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg let mapFromFileToProjectReferenceRedirects: Map | undefined; let mapFromToProjectReferenceRedirectSource: Map | undefined; - const useSourceOfProjectReferenceRedirect = !!host.useSourceOfProjectReferenceRedirect?.() && - !options.disableSourceOfProjectReferenceRedirect; + const useSourceOfProjectReferenceRedirect = !!host.useSourceOfProjectReferenceRedirect?.() + && !options.disableSourceOfProjectReferenceRedirect; const { onProgramCreateComplete, fileExists, directoryExists } = updateHostForUseSourceOfProjectReferenceRedirect({ compilerHost: host, getSymlinkCache, @@ -1713,19 +1929,38 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg if (useSourceOfProjectReferenceRedirect) { if (out || getEmitModuleKind(parsedRef.commandLine.options) === ModuleKind.None) { for (const fileName of parsedRef.commandLine.fileNames) { - processProjectReferenceFile(fileName, { kind: FileIncludeKind.SourceFromProjectReference, index }); + processProjectReferenceFile(fileName, { + kind: FileIncludeKind.SourceFromProjectReference, + index, + }); } } } else { if (out) { - processProjectReferenceFile(changeExtension(out, ".d.ts"), { kind: FileIncludeKind.OutputFromProjectReference, index }); + processProjectReferenceFile(changeExtension(out, ".d.ts"), { + kind: FileIncludeKind.OutputFromProjectReference, + index, + }); } else if (getEmitModuleKind(parsedRef.commandLine.options) === ModuleKind.None) { - const getCommonSourceDirectory = memoize(() => getCommonSourceDirectoryOfConfig(parsedRef.commandLine, !host.useCaseSensitiveFileNames())); + const getCommonSourceDirectory = memoize(() => + getCommonSourceDirectoryOfConfig( + parsedRef.commandLine, + !host.useCaseSensitiveFileNames(), + ) + ); for (const fileName of parsedRef.commandLine.fileNames) { if (!isDeclarationFileName(fileName) && !fileExtensionIs(fileName, Extension.Json)) { - processProjectReferenceFile(getOutputDeclarationFileName(fileName, parsedRef.commandLine, !host.useCaseSensitiveFileNames(), getCommonSourceDirectory), { kind: FileIncludeKind.OutputFromProjectReference, index }); + processProjectReferenceFile( + getOutputDeclarationFileName( + fileName, + parsedRef.commandLine, + !host.useCaseSensitiveFileNames(), + getCommonSourceDirectory, + ), + { kind: FileIncludeKind.OutputFromProjectReference, index }, + ); } } } @@ -1735,21 +1970,38 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg } tracing?.push(tracing.Phase.Program, "processRootFiles", { count: rootNames.length }); - forEach(rootNames, (name, index) => processRootFile(name, /*isDefaultLib*/ false, /*ignoreNoDefaultLib*/ false, { kind: FileIncludeKind.RootFile, index })); + forEach( + rootNames, + (name, index) => + processRootFile(name, /*isDefaultLib*/ false, /*ignoreNoDefaultLib*/ false, { + kind: FileIncludeKind.RootFile, + index, + }), + ); tracing?.pop(); // load type declarations specified via 'types' argument or implicitly from types/ and node_modules/@types folders automaticTypeDirectiveNames ??= rootNames.length ? getAutomaticTypeDirectiveNames(options, host) : emptyArray; automaticTypeDirectiveResolutions = createModeAwareCache(); if (automaticTypeDirectiveNames.length) { - tracing?.push(tracing.Phase.Program, "processTypeReferences", { count: automaticTypeDirectiveNames.length }); + tracing?.push(tracing.Phase.Program, "processTypeReferences", { + count: automaticTypeDirectiveNames.length, + }); // This containingFilename needs to match with the one used in managed-side - const containingDirectory = options.configFilePath ? getDirectoryPath(options.configFilePath) : currentDirectory; + const containingDirectory = options.configFilePath ? getDirectoryPath(options.configFilePath) + : currentDirectory; const containingFilename = combinePaths(containingDirectory, inferredTypesContainingFile); - const resolutions = resolveTypeReferenceDirectiveNamesReusingOldState(automaticTypeDirectiveNames, containingFilename); + const resolutions = resolveTypeReferenceDirectiveNamesReusingOldState( + automaticTypeDirectiveNames, + containingFilename, + ); for (let i = 0; i < automaticTypeDirectiveNames.length; i++) { // under node16/nodenext module resolution, load `types`/ata include names as cjs resolution results by passing an `undefined` mode - automaticTypeDirectiveResolutions.set(automaticTypeDirectiveNames[i], /*mode*/ undefined, resolutions[i]); + automaticTypeDirectiveResolutions.set( + automaticTypeDirectiveNames[i], + /*mode*/ undefined, + resolutions[i], + ); processTypeReferenceDirective( automaticTypeDirectiveNames[i], /*mode*/ undefined, @@ -1773,16 +2025,23 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg // otherwise, using options specified in '--lib' instead of '--target' default library file const defaultLibraryFileName = getDefaultLibraryFileName(); if (!options.lib && defaultLibraryFileName) { - processRootFile(defaultLibraryFileName, /*isDefaultLib*/ true, /*ignoreNoDefaultLib*/ false, { kind: FileIncludeKind.LibFile }); + processRootFile(defaultLibraryFileName, /*isDefaultLib*/ true, /*ignoreNoDefaultLib*/ false, { + kind: FileIncludeKind.LibFile, + }); } else { forEach(options.lib, (libFileName, index) => { - processRootFile(pathForLibFile(libFileName), /*isDefaultLib*/ true, /*ignoreNoDefaultLib*/ false, { kind: FileIncludeKind.LibFile, index }); + processRootFile(pathForLibFile(libFileName), /*isDefaultLib*/ true, /*ignoreNoDefaultLib*/ false, { + kind: FileIncludeKind.LibFile, + index, + }); }); } } - missingFilePaths = arrayFrom(mapDefinedIterator(filesByName.entries(), ([path, file]) => file === undefined ? path as Path : undefined)); + missingFilePaths = arrayFrom( + mapDefinedIterator(filesByName.entries(), ([path, file]) => file === undefined ? path as Path : undefined), + ); files = stableSort(processingDefaultLibFiles, compareDefaultLibFiles).concat(processingOtherFiles); processingDefaultLibFiles = undefined; processingOtherFiles = undefined; @@ -1797,17 +2056,25 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg for (const oldSourceFile of oldSourceFiles) { const newFile = getSourceFileByPath(oldSourceFile.resolvedPath); if ( - shouldCreateNewSourceFile || !newFile || newFile.impliedNodeFormat !== oldSourceFile.impliedNodeFormat || + shouldCreateNewSourceFile || !newFile || newFile.impliedNodeFormat !== oldSourceFile.impliedNodeFormat // old file wasn't redirect but new file is - (oldSourceFile.resolvedPath === oldSourceFile.path && newFile.resolvedPath !== oldSourceFile.path) + || (oldSourceFile.resolvedPath === oldSourceFile.path && newFile.resolvedPath !== oldSourceFile.path) ) { - host.onReleaseOldSourceFile(oldSourceFile, oldProgram.getCompilerOptions(), !!getSourceFileByPath(oldSourceFile.path)); + host.onReleaseOldSourceFile( + oldSourceFile, + oldProgram.getCompilerOptions(), + !!getSourceFileByPath(oldSourceFile.path), + ); } } if (!host.getParsedCommandLine) { oldProgram.forEachResolvedProjectReference(resolvedProjectReference => { if (!getResolvedProjectReferenceByPath(resolvedProjectReference.sourceFile.path)) { - host.onReleaseOldSourceFile!(resolvedProjectReference.sourceFile, oldProgram!.getCompilerOptions(), /*hasSourceFileByPath*/ false); + host.onReleaseOldSourceFile!( + resolvedProjectReference.sourceFile, + oldProgram!.getCompilerOptions(), + /*hasSourceFileByPath*/ false, + ); } }); } @@ -1819,7 +2086,8 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg oldProgram.getProjectReferences(), oldProgram.getResolvedProjectReferences(), (oldResolvedRef, parent, index) => { - const oldReference = parent?.commandLine.projectReferences![index] || oldProgram!.getProjectReferences()![index]; + const oldReference = parent?.commandLine.projectReferences![index] + || oldProgram!.getProjectReferences()![index]; const oldRefPath = resolveProjectReferencePath(oldReference); if (!projectReferenceRedirects?.has(toPath(oldRefPath))) { host.onReleaseParsedCommandLine!(oldRefPath, oldResolvedRef, oldProgram!.getCompilerOptions()); @@ -1904,10 +2172,28 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg fileProcessingDiagnostics?.forEach(diagnostic => { switch (diagnostic.kind) { case FilePreprocessingDiagnosticsKind.FilePreprocessingFileExplainingDiagnostic: - return programDiagnostics.add(createDiagnosticExplainingFile(diagnostic.file && getSourceFileByPath(diagnostic.file), diagnostic.fileProcessingReason, diagnostic.diagnostic, diagnostic.args || emptyArray)); + return programDiagnostics.add( + createDiagnosticExplainingFile( + diagnostic.file && getSourceFileByPath(diagnostic.file), + diagnostic.fileProcessingReason, + diagnostic.diagnostic, + diagnostic.args || emptyArray, + ), + ); case FilePreprocessingDiagnosticsKind.FilePreprocessingReferencedDiagnostic: - const { file, pos, end } = getReferencedFileLocation(getSourceFileByPath, diagnostic.reason) as ReferenceFileLocation; - return programDiagnostics.add(createFileDiagnostic(file, Debug.checkDefined(pos), Debug.checkDefined(end) - pos, diagnostic.diagnostic, ...diagnostic.args || emptyArray)); + const { file, pos, end } = getReferencedFileLocation( + getSourceFileByPath, + diagnostic.reason, + ) as ReferenceFileLocation; + return programDiagnostics.add( + createFileDiagnostic( + file, + Debug.checkDefined(pos), + Debug.checkDefined(end) - pos, + diagnostic.diagnostic, + ...diagnostic.args || emptyArray, + ), + ); case FilePreprocessingDiagnosticsKind.ResolutionDiagnostics: return diagnostic.diagnostics.forEach(d => programDiagnostics.add(d)); default: @@ -1933,7 +2219,12 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg if (!sf.resolvedModules) return; sf.resolvedModules.forEach(({ resolvedModule }) => { - if (resolvedModule?.packageId) packageMap!.set(resolvedModule.packageId.name, resolvedModule.extension === Extension.Dts || !!packageMap!.get(resolvedModule.packageId.name)); + if (resolvedModule?.packageId) { + packageMap!.set( + resolvedModule.packageId.name, + resolvedModule.extension === Extension.Dts || !!packageMap!.get(resolvedModule.packageId.name), + ); + } }); }); return packageMap; @@ -1946,7 +2237,9 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg return !!getPackagesMap().get(packageName); } - function addResolutionDiagnostics(resolution: ResolvedModuleWithFailedLookupLocations | ResolvedTypeReferenceDirectiveWithFailedLookupLocations) { + function addResolutionDiagnostics( + resolution: ResolvedModuleWithFailedLookupLocations | ResolvedTypeReferenceDirectiveWithFailedLookupLocations, + ) { if (!resolution.resolutionDiagnostics?.length) return; (fileProcessingDiagnostics ??= []).push({ kind: FilePreprocessingDiagnosticsKind.ResolutionDiagnostics, @@ -1954,7 +2247,12 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg }); } - function addResolutionDiagnosticsFromResolutionOrCache(containingFile: SourceFile, name: string, resolution: ResolvedModuleWithFailedLookupLocations, mode: ResolutionMode) { + function addResolutionDiagnosticsFromResolutionOrCache( + containingFile: SourceFile, + name: string, + resolution: ResolvedModuleWithFailedLookupLocations, + mode: ResolutionMode, + ) { // diagnostics directly from the resolution if (host.resolveModuleNameLiterals || !host.resolveModuleNames) return addResolutionDiagnostics(resolution); if (!moduleResolutionCache || isExternalModuleNameRelative(name)) return; @@ -1966,31 +2264,59 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg // This may totally change if/when the issue of output paths not mapping to input files is fixed in a broader context // When it is, how we extract diagnostics from the module name resolver will have the be refined - the current cache // APIs wrapping the underlying resolver make it almost impossible to smuggle the diagnostics out in a generalized way - const fromCache = moduleResolutionCache.getFromNonRelativeNameCache(name, mode, containingDir, redirectedReference); + const fromCache = moduleResolutionCache.getFromNonRelativeNameCache( + name, + mode, + containingDir, + redirectedReference, + ); if (fromCache) addResolutionDiagnostics(fromCache); } - function resolveModuleNamesWorker(moduleNames: readonly StringLiteralLike[], containingFile: SourceFile, reusedNames: readonly StringLiteralLike[] | undefined): readonly ResolvedModuleWithFailedLookupLocations[] { + function resolveModuleNamesWorker( + moduleNames: readonly StringLiteralLike[], + containingFile: SourceFile, + reusedNames: readonly StringLiteralLike[] | undefined, + ): readonly ResolvedModuleWithFailedLookupLocations[] { if (!moduleNames.length) return emptyArray; const containingFileName = getNormalizedAbsolutePath(containingFile.originalFileName, currentDirectory); const redirectedReference = getRedirectReferenceForResolution(containingFile); tracing?.push(tracing.Phase.Program, "resolveModuleNamesWorker", { containingFileName }); performance.mark("beforeResolveModule"); - const result = actualResolveModuleNamesWorker(moduleNames, containingFileName, redirectedReference, options, containingFile, reusedNames); + const result = actualResolveModuleNamesWorker( + moduleNames, + containingFileName, + redirectedReference, + options, + containingFile, + reusedNames, + ); performance.mark("afterResolveModule"); performance.measure("ResolveModule", "beforeResolveModule", "afterResolveModule"); tracing?.pop(); return result; } - function resolveTypeReferenceDirectiveNamesWorker(typeDirectiveNames: readonly T[], containingFile: string | SourceFile, reusedNames: readonly T[] | undefined): readonly ResolvedTypeReferenceDirectiveWithFailedLookupLocations[] { + function resolveTypeReferenceDirectiveNamesWorker( + typeDirectiveNames: readonly T[], + containingFile: string | SourceFile, + reusedNames: readonly T[] | undefined, + ): readonly ResolvedTypeReferenceDirectiveWithFailedLookupLocations[] { if (!typeDirectiveNames.length) return []; const containingSourceFile = !isString(containingFile) ? containingFile : undefined; - const containingFileName = !isString(containingFile) ? getNormalizedAbsolutePath(containingFile.originalFileName, currentDirectory) : containingFile; + const containingFileName = !isString(containingFile) + ? getNormalizedAbsolutePath(containingFile.originalFileName, currentDirectory) : containingFile; const redirectedReference = containingSourceFile && getRedirectReferenceForResolution(containingSourceFile); tracing?.push(tracing.Phase.Program, "resolveTypeReferenceDirectiveNamesWorker", { containingFileName }); performance.mark("beforeResolveTypeReference"); - const result = actualResolveTypeReferenceDirectiveNamesWorker(typeDirectiveNames, containingFileName, redirectedReference, options, containingSourceFile, reusedNames); + const result = actualResolveTypeReferenceDirectiveNamesWorker( + typeDirectiveNames, + containingFileName, + redirectedReference, + options, + containingSourceFile, + reusedNames, + ); performance.mark("afterResolveTypeReference"); performance.measure("ResolveTypeReference", "beforeResolveTypeReference", "afterResolveTypeReference"); tracing?.pop(); @@ -2010,9 +2336,12 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg // but the resolved real path may be the .d.ts from project reference // Note:: Currently we try the real path only if the // file is from node_modules to avoid having to run real path on all file paths - if (!host.realpath || !options.preserveSymlinks || !stringContains(file.originalFileName, nodeModulesPathPart)) return undefined; + if ( + !host.realpath || !options.preserveSymlinks || !stringContains(file.originalFileName, nodeModulesPathPart) + ) return undefined; const realDeclarationPath = toPath(host.realpath(file.originalFileName)); - return realDeclarationPath === file.path ? undefined : getRedirectReferenceForResolutionFromSourceOfProject(realDeclarationPath); + return realDeclarationPath === file.path ? undefined + : getRedirectReferenceForResolutionFromSourceOfProject(realDeclarationPath); } function getRedirectReferenceForResolutionFromSourceOfProject(filePath: Path) { @@ -2074,7 +2403,10 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg return classifiableNames; } - function resolveModuleNamesReusingOldState(moduleNames: readonly StringLiteralLike[], file: SourceFile): readonly ResolvedModuleWithFailedLookupLocations[] { + function resolveModuleNamesReusingOldState( + moduleNames: readonly StringLiteralLike[], + file: SourceFile, + ): readonly ResolvedModuleWithFailedLookupLocations[] { if (structureIsReused === StructureIsReused.Not && !file.ambientModuleNames.length) { // If the old program state does not permit reusing resolutions and `file` does not contain locally defined ambient modules, // the best we can do is fallback to the default logic. @@ -2093,7 +2425,10 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg // it is safe to reuse resolutions from the earlier call. const result: ResolvedModuleWithFailedLookupLocations[] = []; for (const moduleName of moduleNames) { - const resolvedModule = file.resolvedModules.get(moduleName.text, getModeForUsageLocation(file, moduleName))!; + const resolvedModule = file.resolvedModules.get( + moduleName.text, + getModeForUsageLocation(file, moduleName), + )!; result.push(resolvedModule); } return result; @@ -2129,13 +2464,16 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg if (isTraceEnabled(options, host)) { trace( host, - oldResolution.resolvedModule.packageId ? - Diagnostics.Reusing_resolution_of_module_0_from_1_of_old_program_it_was_successfully_resolved_to_2_with_Package_ID_3 : - Diagnostics.Reusing_resolution_of_module_0_from_1_of_old_program_it_was_successfully_resolved_to_2, + oldResolution.resolvedModule.packageId + ? Diagnostics + .Reusing_resolution_of_module_0_from_1_of_old_program_it_was_successfully_resolved_to_2_with_Package_ID_3 + : Diagnostics + .Reusing_resolution_of_module_0_from_1_of_old_program_it_was_successfully_resolved_to_2, moduleName.text, getNormalizedAbsolutePath(file.originalFileName, currentDirectory), oldResolution.resolvedModule.resolvedFileName, - oldResolution.resolvedModule.packageId && packageIdToString(oldResolution.resolvedModule.packageId), + oldResolution.resolvedModule.packageId + && packageIdToString(oldResolution.resolvedModule.packageId), ); } (result ??= new Array(moduleNames.length))[i] = oldResolution; @@ -2151,11 +2489,18 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg if (contains(file.ambientModuleNames, moduleName.text)) { resolvesToAmbientModuleInNonModifiedFile = true; if (isTraceEnabled(options, host)) { - trace(host, Diagnostics.Module_0_was_resolved_as_locally_declared_ambient_module_in_file_1, moduleName.text, getNormalizedAbsolutePath(file.originalFileName, currentDirectory)); + trace( + host, + Diagnostics.Module_0_was_resolved_as_locally_declared_ambient_module_in_file_1, + moduleName.text, + getNormalizedAbsolutePath(file.originalFileName, currentDirectory), + ); } } else { - resolvesToAmbientModuleInNonModifiedFile = moduleNameResolvesToAmbientModuleInNonModifiedFile(moduleName); + resolvesToAmbientModuleInNonModifiedFile = moduleNameResolvesToAmbientModuleInNonModifiedFile( + moduleName, + ); } if (resolvesToAmbientModuleInNonModifiedFile) { @@ -2192,7 +2537,11 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg // If we change our policy of rechecking failed lookups on each program create, // we should adjust the value returned here. function moduleNameResolvesToAmbientModuleInNonModifiedFile(moduleName: StringLiteralLike): boolean { - const resolutionToFile = getResolvedModule(oldSourceFile, moduleName.text, getModeForUsageLocation(file, moduleName)); + const resolutionToFile = getResolvedModule( + oldSourceFile, + moduleName.text, + getModeForUsageLocation(file, moduleName), + ); const resolvedFile = resolutionToFile && oldProgram!.getSourceFile(resolutionToFile.resolvedFileName); if (resolutionToFile && resolvedFile) { // In the old program, we resolved to an ambient module that was in the same @@ -2210,22 +2559,41 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg } if (isTraceEnabled(options, host)) { - trace(host, Diagnostics.Module_0_was_resolved_as_ambient_module_declared_in_1_since_this_file_was_not_modified, moduleName.text, unmodifiedFile); + trace( + host, + Diagnostics.Module_0_was_resolved_as_ambient_module_declared_in_1_since_this_file_was_not_modified, + moduleName.text, + unmodifiedFile, + ); } return true; } } - function resolveTypeReferenceDirectiveNamesReusingOldState(typeDirectiveNames: readonly FileReference[], containingFile: SourceFile): readonly ResolvedTypeReferenceDirectiveWithFailedLookupLocations[]; - function resolveTypeReferenceDirectiveNamesReusingOldState(typeDirectiveNames: string[], containingFile: string): readonly ResolvedTypeReferenceDirectiveWithFailedLookupLocations[]; - function resolveTypeReferenceDirectiveNamesReusingOldState(typeDirectiveNames: readonly T[], containingFile: string | SourceFile): readonly ResolvedTypeReferenceDirectiveWithFailedLookupLocations[] { + function resolveTypeReferenceDirectiveNamesReusingOldState( + typeDirectiveNames: readonly FileReference[], + containingFile: SourceFile, + ): readonly ResolvedTypeReferenceDirectiveWithFailedLookupLocations[]; + function resolveTypeReferenceDirectiveNamesReusingOldState( + typeDirectiveNames: string[], + containingFile: string, + ): readonly ResolvedTypeReferenceDirectiveWithFailedLookupLocations[]; + function resolveTypeReferenceDirectiveNamesReusingOldState( + typeDirectiveNames: readonly T[], + containingFile: string | SourceFile, + ): readonly ResolvedTypeReferenceDirectiveWithFailedLookupLocations[] { if (structureIsReused === StructureIsReused.Not) { // If the old program state does not permit reusing resolutions and `file` does not contain locally defined ambient modules, // the best we can do is fallback to the default logic. - return resolveTypeReferenceDirectiveNamesWorker(typeDirectiveNames, containingFile, /*reusedNames*/ undefined); + return resolveTypeReferenceDirectiveNamesWorker( + typeDirectiveNames, + containingFile, + /*reusedNames*/ undefined, + ); } - const oldSourceFile = !isString(containingFile) ? oldProgram && oldProgram.getSourceFile(containingFile.fileName) : undefined; + const oldSourceFile = !isString(containingFile) + ? oldProgram && oldProgram.getSourceFile(containingFile.fileName) : undefined; if (!isString(containingFile)) { if (oldSourceFile !== containingFile && containingFile.resolvedTypeReferenceDirectiveNames) { // `file` was created for the new program. @@ -2239,7 +2607,10 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg const result: ResolvedTypeReferenceDirectiveWithFailedLookupLocations[] = []; for (const typeDirectiveName of typeDirectiveNames as readonly FileReference[]) { // We lower-case all type references because npm automatically lowercases all packages. See GH#9824. - const resolvedTypeReferenceDirective = containingFile.resolvedTypeReferenceDirectiveNames.get(getTypeReferenceResolutionName(typeDirectiveName), getModeForFileReference(typeDirectiveName, containingFile.impliedNodeFormat))!; + const resolvedTypeReferenceDirective = containingFile.resolvedTypeReferenceDirectiveNames.get( + getTypeReferenceResolutionName(typeDirectiveName), + getModeForFileReference(typeDirectiveName, containingFile.impliedNodeFormat), + )!; result.push(resolvedTypeReferenceDirective); } return result; @@ -2251,26 +2622,32 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg let result: ResolvedTypeReferenceDirectiveWithFailedLookupLocations[] | undefined; let reusedNames: T[] | undefined; const containingSourceFile = !isString(containingFile) ? containingFile : undefined; - const canReuseResolutions = !isString(containingFile) ? - containingFile === oldSourceFile && !hasInvalidatedResolutions(oldSourceFile.path) : - !hasInvalidatedResolutions(toPath(containingFile)); + const canReuseResolutions = !isString(containingFile) + ? containingFile === oldSourceFile && !hasInvalidatedResolutions(oldSourceFile.path) + : !hasInvalidatedResolutions(toPath(containingFile)); for (let i = 0; i < typeDirectiveNames.length; i++) { const entry = typeDirectiveNames[i]; if (canReuseResolutions) { const typeDirectiveName = getTypeReferenceResolutionName(entry); const mode = getModeForFileReference(entry, containingSourceFile?.impliedNodeFormat); - const oldResolution = (!isString(containingFile) ? oldSourceFile?.resolvedTypeReferenceDirectiveNames : oldProgram?.getAutomaticTypeDirectiveResolutions())?.get(typeDirectiveName, mode); + const oldResolution = (!isString(containingFile) ? oldSourceFile?.resolvedTypeReferenceDirectiveNames + : oldProgram?.getAutomaticTypeDirectiveResolutions())?.get(typeDirectiveName, mode); if (oldResolution?.resolvedTypeReferenceDirective) { if (isTraceEnabled(options, host)) { trace( host, - oldResolution.resolvedTypeReferenceDirective.packageId ? - Diagnostics.Reusing_resolution_of_type_reference_directive_0_from_1_of_old_program_it_was_successfully_resolved_to_2_with_Package_ID_3 : - Diagnostics.Reusing_resolution_of_type_reference_directive_0_from_1_of_old_program_it_was_successfully_resolved_to_2, + oldResolution.resolvedTypeReferenceDirective.packageId + ? Diagnostics + .Reusing_resolution_of_type_reference_directive_0_from_1_of_old_program_it_was_successfully_resolved_to_2_with_Package_ID_3 + : Diagnostics + .Reusing_resolution_of_type_reference_directive_0_from_1_of_old_program_it_was_successfully_resolved_to_2, typeDirectiveName, - !isString(containingFile) ? getNormalizedAbsolutePath(containingFile.originalFileName, currentDirectory) : containingFile, + !isString(containingFile) + ? getNormalizedAbsolutePath(containingFile.originalFileName, currentDirectory) + : containingFile, oldResolution.resolvedTypeReferenceDirective.resolvedFileName, - oldResolution.resolvedTypeReferenceDirective.packageId && packageIdToString(oldResolution.resolvedTypeReferenceDirective.packageId), + oldResolution.resolvedTypeReferenceDirective.packageId + && packageIdToString(oldResolution.resolvedTypeReferenceDirective.packageId), ); } (result ??= new Array(typeDirectiveNames.length))[i] = oldResolution; @@ -2316,9 +2693,9 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg const newResolvedRef = parseProjectReferenceConfigFile(newRef); if (oldResolvedRef) { // Resolved project reference has gone missing or changed - return !newResolvedRef || - newResolvedRef.sourceFile !== oldResolvedRef.sourceFile || - !arrayIsEqualTo(oldResolvedRef.commandLine.fileNames, newResolvedRef.commandLine.fileNames); + return !newResolvedRef + || newResolvedRef.sourceFile !== oldResolvedRef.sourceFile + || !arrayIsEqualTo(oldResolvedRef.commandLine.fileNames, newResolvedRef.commandLine.fileNames); } else { // A previously-unresolved reference may be resolved now @@ -2327,7 +2704,9 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg }, (oldProjectReferences, parent) => { // If array of references is changed, we cant resue old program - const newReferences = parent ? getResolvedProjectReferenceByPath(parent.sourceFile.path)!.commandLine.projectReferences : projectReferences; + const newReferences = parent + ? getResolvedProjectReferenceByPath(parent.sourceFile.path)!.commandLine.projectReferences + : projectReferences; return !arrayIsEqualTo(oldProjectReferences, newReferences, projectReferenceIsEqualTo); }, ); @@ -2379,18 +2758,38 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg const seenPackageNames = new Map(); for (const oldSourceFile of oldSourceFiles) { - const sourceFileOptions = getCreateSourceFileOptions(oldSourceFile.fileName, moduleResolutionCache, host, options); + const sourceFileOptions = getCreateSourceFileOptions( + oldSourceFile.fileName, + moduleResolutionCache, + host, + options, + ); let newSourceFile = host.getSourceFileByPath - ? host.getSourceFileByPath(oldSourceFile.fileName, oldSourceFile.resolvedPath, sourceFileOptions, /*onError*/ undefined, shouldCreateNewSourceFile) - : host.getSourceFile(oldSourceFile.fileName, sourceFileOptions, /*onError*/ undefined, shouldCreateNewSourceFile); // TODO: GH#18217 + ? host.getSourceFileByPath( + oldSourceFile.fileName, + oldSourceFile.resolvedPath, + sourceFileOptions, + /*onError*/ undefined, + shouldCreateNewSourceFile, + ) + : host.getSourceFile( + oldSourceFile.fileName, + sourceFileOptions, + /*onError*/ undefined, + shouldCreateNewSourceFile, + ); // TODO: GH#18217 if (!newSourceFile) { return StructureIsReused.Not; } - newSourceFile.packageJsonLocations = sourceFileOptions.packageJsonLocations?.length ? sourceFileOptions.packageJsonLocations : undefined; + newSourceFile.packageJsonLocations = sourceFileOptions.packageJsonLocations?.length + ? sourceFileOptions.packageJsonLocations : undefined; newSourceFile.packageJsonScope = sourceFileOptions.packageJsonScope; - Debug.assert(!newSourceFile.redirectInfo, "Host should not return a redirect source file from `getSourceFile`"); + Debug.assert( + !newSourceFile.redirectInfo, + "Host should not return a redirect source file from `getSourceFile`", + ); let fileChanged: boolean; if (oldSourceFile.redirectInfo) { @@ -2426,7 +2825,10 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg // they might become redirects. So we must rebuild the program. const prevKind = seenPackageNames.get(packageName); const newKind = fileChanged ? SeenPackageName.Modified : SeenPackageName.Exists; - if ((prevKind !== undefined && newKind === SeenPackageName.Modified) || prevKind === SeenPackageName.Modified) { + if ( + (prevKind !== undefined && newKind === SeenPackageName.Modified) + || prevKind === SeenPackageName.Modified + ) { return StructureIsReused.Not; } seenPackageNames.set(packageName, newKind); @@ -2437,7 +2839,13 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg structureIsReused = StructureIsReused.SafeModules; } // The `newSourceFile` object was created for the new program. - else if (!arrayIsEqualTo(oldSourceFile.libReferenceDirectives, newSourceFile.libReferenceDirectives, fileReferenceIsEqualTo)) { + else if ( + !arrayIsEqualTo( + oldSourceFile.libReferenceDirectives, + newSourceFile.libReferenceDirectives, + fileReferenceIsEqualTo, + ) + ) { // 'lib' references has changed. Matches behavior in changesAffectModuleResolution structureIsReused = StructureIsReused.SafeModules; } @@ -2447,7 +2855,13 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg structureIsReused = StructureIsReused.SafeModules; } // check tripleslash references - else if (!arrayIsEqualTo(oldSourceFile.referencedFiles, newSourceFile.referencedFiles, fileReferenceIsEqualTo)) { + else if ( + !arrayIsEqualTo( + oldSourceFile.referencedFiles, + newSourceFile.referencedFiles, + fileReferenceIsEqualTo, + ) + ) { // tripleslash references has changed structureIsReused = StructureIsReused.SafeModules; } @@ -2458,15 +2872,30 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg // imports has changed structureIsReused = StructureIsReused.SafeModules; } - else if (!arrayIsEqualTo(oldSourceFile.moduleAugmentations, newSourceFile.moduleAugmentations, moduleNameIsEqualTo)) { + else if ( + !arrayIsEqualTo( + oldSourceFile.moduleAugmentations, + newSourceFile.moduleAugmentations, + moduleNameIsEqualTo, + ) + ) { // moduleAugmentations has changed structureIsReused = StructureIsReused.SafeModules; } - else if ((oldSourceFile.flags & NodeFlags.PermanentlySetIncrementalFlags) !== (newSourceFile.flags & NodeFlags.PermanentlySetIncrementalFlags)) { + else if ( + (oldSourceFile.flags & NodeFlags.PermanentlySetIncrementalFlags) + !== (newSourceFile.flags & NodeFlags.PermanentlySetIncrementalFlags) + ) { // dynamicImport has changed structureIsReused = StructureIsReused.SafeModules; } - else if (!arrayIsEqualTo(oldSourceFile.typeReferenceDirectives, newSourceFile.typeReferenceDirectives, fileReferenceIsEqualTo)) { + else if ( + !arrayIsEqualTo( + oldSourceFile.typeReferenceDirectives, + newSourceFile.typeReferenceDirectives, + fileReferenceIsEqualTo, + ) + ) { // 'types' references has changed structureIsReused = StructureIsReused.SafeModules; } @@ -2504,21 +2933,48 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg const moduleNames = getModuleNames(newSourceFile); const resolutions = resolveModuleNamesReusingOldState(moduleNames, newSourceFile); // ensure that module resolution results are still correct - const resolutionsChanged = hasChangesInResolutions(moduleNames, newSourceFile, resolutions, oldSourceFile.resolvedModules, moduleResolutionIsEqualTo, moduleResolutionNameAndModeGetter); + const resolutionsChanged = hasChangesInResolutions( + moduleNames, + newSourceFile, + resolutions, + oldSourceFile.resolvedModules, + moduleResolutionIsEqualTo, + moduleResolutionNameAndModeGetter, + ); if (resolutionsChanged) { structureIsReused = StructureIsReused.SafeModules; - newSourceFile.resolvedModules = zipToModeAwareCache(newSourceFile, moduleNames, resolutions, moduleResolutionNameAndModeGetter); + newSourceFile.resolvedModules = zipToModeAwareCache( + newSourceFile, + moduleNames, + resolutions, + moduleResolutionNameAndModeGetter, + ); } else { newSourceFile.resolvedModules = oldSourceFile.resolvedModules; } const typesReferenceDirectives = newSourceFile.typeReferenceDirectives; - const typeReferenceResolutions = resolveTypeReferenceDirectiveNamesReusingOldState(typesReferenceDirectives, newSourceFile); + const typeReferenceResolutions = resolveTypeReferenceDirectiveNamesReusingOldState( + typesReferenceDirectives, + newSourceFile, + ); // ensure that types resolutions are still correct - const typeReferenceResolutionsChanged = hasChangesInResolutions(typesReferenceDirectives, newSourceFile, typeReferenceResolutions, oldSourceFile.resolvedTypeReferenceDirectiveNames, typeDirectiveIsEqualTo, typeReferenceResolutionNameAndModeGetter); + const typeReferenceResolutionsChanged = hasChangesInResolutions( + typesReferenceDirectives, + newSourceFile, + typeReferenceResolutions, + oldSourceFile.resolvedTypeReferenceDirectiveNames, + typeDirectiveIsEqualTo, + typeReferenceResolutionNameAndModeGetter, + ); if (typeReferenceResolutionsChanged) { structureIsReused = StructureIsReused.SafeModules; - newSourceFile.resolvedTypeReferenceDirectiveNames = zipToModeAwareCache(newSourceFile, typesReferenceDirectives, typeReferenceResolutions, typeReferenceResolutionNameAndModeGetter); + newSourceFile.resolvedTypeReferenceDirectiveNames = zipToModeAwareCache( + newSourceFile, + typesReferenceDirectives, + typeReferenceResolutions, + typeReferenceResolutionNameAndModeGetter, + ); } else { newSourceFile.resolvedTypeReferenceDirectiveNames = oldSourceFile.resolvedTypeReferenceDirectiveNames; @@ -2534,8 +2990,11 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg } if ( - oldProgram.resolvedLibReferences && - forEachEntry(oldProgram.resolvedLibReferences, (resolution, libFileName) => pathForLibFileWorker(libFileName).actual !== resolution.actual) + oldProgram.resolvedLibReferences + && forEachEntry( + oldProgram.resolvedLibReferences, + (resolution, libFileName) => pathForLibFileWorker(libFileName).actual !== resolution.actual, + ) ) { return StructureIsReused.SafeModules; } @@ -2545,7 +3004,9 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg } else { automaticTypeDirectiveNames = getAutomaticTypeDirectiveNames(options, host); - if (!arrayIsEqualTo(oldProgram.getAutomaticTypeDirectiveNames(), automaticTypeDirectiveNames)) return StructureIsReused.SafeModules; + if (!arrayIsEqualTo(oldProgram.getAutomaticTypeDirectiveNames(), automaticTypeDirectiveNames)) { + return StructureIsReused.SafeModules; + } } missingFilePaths = oldProgram.getMissingFilePaths(); @@ -2692,12 +3153,16 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg // If '--lib' is not specified, include default library file according to '--target' // otherwise, using options specified in '--lib' instead of '--target' default library file - const equalityComparer = host.useCaseSensitiveFileNames() ? equateStringsCaseSensitive : equateStringsCaseInsensitive; + const equalityComparer = host.useCaseSensitiveFileNames() ? equateStringsCaseSensitive + : equateStringsCaseInsensitive; if (!options.lib) { return equalityComparer(file.fileName, getDefaultLibraryFileName()); } else { - return some(options.lib, libFileName => equalityComparer(file.fileName, resolvedLibReferences!.get(libFileName)!.actual)); + return some( + options.lib, + libFileName => equalityComparer(file.fileName, resolvedLibReferences!.get(libFileName)!.actual), + ); } } @@ -2705,9 +3170,18 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg return typeChecker || (typeChecker = createTypeChecker(program)); } - function emit(sourceFile?: SourceFile, writeFileCallback?: WriteFileCallback, cancellationToken?: CancellationToken, emitOnly?: boolean | EmitOnly, transformers?: CustomTransformers, forceDtsEmit?: boolean): EmitResult { + function emit( + sourceFile?: SourceFile, + writeFileCallback?: WriteFileCallback, + cancellationToken?: CancellationToken, + emitOnly?: boolean | EmitOnly, + transformers?: CustomTransformers, + forceDtsEmit?: boolean, + ): EmitResult { tracing?.push(tracing.Phase.Emit, "emit", { path: sourceFile?.path }, /*separateBeginAndEnd*/ true); - const result = runWithCancellationToken(() => emitWorker(program, sourceFile, writeFileCallback, cancellationToken, emitOnly, transformers, forceDtsEmit)); + const result = runWithCancellationToken(() => + emitWorker(program, sourceFile, writeFileCallback, cancellationToken, emitOnly, transformers, forceDtsEmit) + ); tracing?.pop(); return result; } @@ -2716,7 +3190,15 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg return hasEmitBlockingDiagnostics.has(toPath(emitFileName)); } - function emitWorker(program: Program, sourceFile: SourceFile | undefined, writeFileCallback: WriteFileCallback | undefined, cancellationToken: CancellationToken | undefined, emitOnly?: boolean | EmitOnly, customTransformers?: CustomTransformers, forceDtsEmit?: boolean): EmitResult { + function emitWorker( + program: Program, + sourceFile: SourceFile | undefined, + writeFileCallback: WriteFileCallback | undefined, + cancellationToken: CancellationToken | undefined, + emitOnly?: boolean | EmitOnly, + customTransformers?: CustomTransformers, + forceDtsEmit?: boolean, + ): EmitResult { if (!forceDtsEmit) { const result = handleNoEmitOptions(program, sourceFile, writeFileCallback, cancellationToken); if (result) return result; @@ -2730,7 +3212,10 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg // This is because in the -out scenario all files need to be emitted, and therefore all // files need to be type checked. And the way to specify that all files need to be type // checked is to not pass the file to getEmitResolver. - const emitResolver = getTypeChecker().getEmitResolver(outFile(options) ? undefined : sourceFile, cancellationToken); + const emitResolver = getTypeChecker().getEmitResolver( + outFile(options) ? undefined : sourceFile, + cancellationToken, + ); performance.mark("beforeEmit"); @@ -2773,11 +3258,17 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg })); } - function getSyntacticDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): readonly DiagnosticWithLocation[] { + function getSyntacticDiagnostics( + sourceFile?: SourceFile, + cancellationToken?: CancellationToken, + ): readonly DiagnosticWithLocation[] { return getDiagnosticsHelper(sourceFile, getSyntacticDiagnosticsForFile, cancellationToken); } - function getSemanticDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): readonly Diagnostic[] { + function getSemanticDiagnostics( + sourceFile?: SourceFile, + cancellationToken?: CancellationToken, + ): readonly Diagnostic[] { return getDiagnosticsHelper(sourceFile, getSemanticDiagnosticsForFile, cancellationToken); } @@ -2787,7 +3278,10 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg : cachedBindAndCheckDiagnosticsForFile.allDiagnostics; } - function getBindAndCheckDiagnostics(sourceFile: SourceFile, cancellationToken?: CancellationToken): readonly Diagnostic[] { + function getBindAndCheckDiagnostics( + sourceFile: SourceFile, + cancellationToken?: CancellationToken, + ): readonly Diagnostic[] { return getBindAndCheckDiagnosticsForFile(sourceFile, cancellationToken); } @@ -2801,10 +3295,14 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg return programDiagnosticsInFile; } - return getDiagnosticsWithPrecedingDirectives(sourceFile, sourceFile.commentDirectives, programDiagnosticsInFile).diagnostics; + return getDiagnosticsWithPrecedingDirectives(sourceFile, sourceFile.commentDirectives, programDiagnosticsInFile) + .diagnostics; } - function getDeclarationDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): readonly DiagnosticWithLocation[] { + function getDeclarationDiagnostics( + sourceFile?: SourceFile, + cancellationToken?: CancellationToken, + ): readonly DiagnosticWithLocation[] { const options = program.getCompilerOptions(); // collect diagnostics from the program only once if either no source file was specified or out/outFile is set (bundled emit) if (!sourceFile || outFile(options)) { @@ -2842,18 +3340,32 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg } } - function getSemanticDiagnosticsForFile(sourceFile: SourceFile, cancellationToken: CancellationToken | undefined): readonly Diagnostic[] { + function getSemanticDiagnosticsForFile( + sourceFile: SourceFile, + cancellationToken: CancellationToken | undefined, + ): readonly Diagnostic[] { return concatenate( filterSemanticDiagnostics(getBindAndCheckDiagnosticsForFile(sourceFile, cancellationToken), options), getProgramDiagnostics(sourceFile), ); } - function getBindAndCheckDiagnosticsForFile(sourceFile: SourceFile, cancellationToken: CancellationToken | undefined): readonly Diagnostic[] { - return getAndCacheDiagnostics(sourceFile, cancellationToken, cachedBindAndCheckDiagnosticsForFile, getBindAndCheckDiagnosticsForFileNoCache); + function getBindAndCheckDiagnosticsForFile( + sourceFile: SourceFile, + cancellationToken: CancellationToken | undefined, + ): readonly Diagnostic[] { + return getAndCacheDiagnostics( + sourceFile, + cancellationToken, + cachedBindAndCheckDiagnosticsForFile, + getBindAndCheckDiagnosticsForFileNoCache, + ); } - function getBindAndCheckDiagnosticsForFileNoCache(sourceFile: SourceFile, cancellationToken: CancellationToken | undefined): readonly Diagnostic[] { + function getBindAndCheckDiagnosticsForFileNoCache( + sourceFile: SourceFile, + cancellationToken: CancellationToken | undefined, + ): readonly Diagnostic[] { return runWithCancellationToken(() => { if (skipTypeChecking(sourceFile, options, program)) { return emptyArray; @@ -2872,29 +3384,53 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg // - plain JS: .js files with no // ts-check and checkJs: undefined // - check JS: .js files with either // ts-check or checkJs: true // - external: files that are added by plugins - const includeBindAndCheckDiagnostics = !isTsNoCheck && (sourceFile.scriptKind === ScriptKind.TS || sourceFile.scriptKind === ScriptKind.TSX - || sourceFile.scriptKind === ScriptKind.External || isPlainJs || isCheckJs || sourceFile.scriptKind === ScriptKind.Deferred); - let bindDiagnostics: readonly Diagnostic[] = includeBindAndCheckDiagnostics ? sourceFile.bindDiagnostics : emptyArray; - let checkDiagnostics = includeBindAndCheckDiagnostics ? typeChecker.getDiagnostics(sourceFile, cancellationToken) : emptyArray; + const includeBindAndCheckDiagnostics = !isTsNoCheck + && (sourceFile.scriptKind === ScriptKind.TS || sourceFile.scriptKind === ScriptKind.TSX + || sourceFile.scriptKind === ScriptKind.External || isPlainJs || isCheckJs + || sourceFile.scriptKind === ScriptKind.Deferred); + let bindDiagnostics: readonly Diagnostic[] = includeBindAndCheckDiagnostics ? sourceFile.bindDiagnostics + : emptyArray; + let checkDiagnostics = includeBindAndCheckDiagnostics + ? typeChecker.getDiagnostics(sourceFile, cancellationToken) : emptyArray; if (isPlainJs) { bindDiagnostics = filter(bindDiagnostics, d => plainJSErrors.has(d.code)); checkDiagnostics = filter(checkDiagnostics, d => plainJSErrors.has(d.code)); } // skip ts-expect-error errors in plain JS files, and skip JSDoc errors except in checked JS - return getMergedBindAndCheckDiagnostics(sourceFile, includeBindAndCheckDiagnostics && !isPlainJs, bindDiagnostics, checkDiagnostics, isCheckJs ? sourceFile.jsDocDiagnostics : undefined); + return getMergedBindAndCheckDiagnostics( + sourceFile, + includeBindAndCheckDiagnostics && !isPlainJs, + bindDiagnostics, + checkDiagnostics, + isCheckJs ? sourceFile.jsDocDiagnostics : undefined, + ); }); } - function getMergedBindAndCheckDiagnostics(sourceFile: SourceFile, includeBindAndCheckDiagnostics: boolean, ...allDiagnostics: (readonly Diagnostic[] | undefined)[]) { + function getMergedBindAndCheckDiagnostics( + sourceFile: SourceFile, + includeBindAndCheckDiagnostics: boolean, + ...allDiagnostics: (readonly Diagnostic[] | undefined)[] + ) { const flatDiagnostics = flatten(allDiagnostics); if (!includeBindAndCheckDiagnostics || !sourceFile.commentDirectives?.length) { return flatDiagnostics; } - const { diagnostics, directives } = getDiagnosticsWithPrecedingDirectives(sourceFile, sourceFile.commentDirectives, flatDiagnostics); + const { diagnostics, directives } = getDiagnosticsWithPrecedingDirectives( + sourceFile, + sourceFile.commentDirectives, + flatDiagnostics, + ); for (const errorExpectation of directives.getUnusedExpectations()) { - diagnostics.push(createDiagnosticForRange(sourceFile, errorExpectation.range, Diagnostics.Unused_ts_expect_error_directive)); + diagnostics.push( + createDiagnosticForRange( + sourceFile, + errorExpectation.range, + Diagnostics.Unused_ts_expect_error_directive, + ), + ); } return diagnostics; @@ -2904,16 +3440,25 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg * Creates a map of comment directives along with the diagnostics immediately preceded by one of them. * Comments that match to any of those diagnostics are marked as used. */ - function getDiagnosticsWithPrecedingDirectives(sourceFile: SourceFile, commentDirectives: CommentDirective[], flatDiagnostics: Diagnostic[]) { + function getDiagnosticsWithPrecedingDirectives( + sourceFile: SourceFile, + commentDirectives: CommentDirective[], + flatDiagnostics: Diagnostic[], + ) { // Diagnostics are only reported if there is no comment directive preceding them // This will modify the directives map by marking "used" ones with a corresponding diagnostic const directives = createCommentDirectivesMap(sourceFile, commentDirectives); - const diagnostics = flatDiagnostics.filter(diagnostic => markPrecedingCommentDirectiveLine(diagnostic, directives) === -1); + const diagnostics = flatDiagnostics.filter(diagnostic => + markPrecedingCommentDirectiveLine(diagnostic, directives) === -1 + ); return { diagnostics, directives }; } - function getSuggestionDiagnostics(sourceFile: SourceFile, cancellationToken: CancellationToken): readonly DiagnosticWithLocation[] { + function getSuggestionDiagnostics( + sourceFile: SourceFile, + cancellationToken: CancellationToken, + ): readonly DiagnosticWithLocation[] { return runWithCancellationToken(() => { return getTypeChecker().getSuggestionDiagnostics(sourceFile, cancellationToken); }); @@ -2965,8 +3510,17 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg case SyntaxKind.Parameter: case SyntaxKind.PropertyDeclaration: case SyntaxKind.MethodDeclaration: - if ((parent as ParameterDeclaration | PropertyDeclaration | MethodDeclaration).questionToken === node) { - diagnostics.push(createDiagnosticForNode(node, Diagnostics.The_0_modifier_can_only_be_used_in_TypeScript_files, "?")); + if ( + (parent as ParameterDeclaration | PropertyDeclaration | MethodDeclaration).questionToken + === node + ) { + diagnostics.push( + createDiagnosticForNode( + node, + Diagnostics.The_0_modifier_can_only_be_used_in_TypeScript_files, + "?", + ), + ); return "skip"; } // falls through @@ -2979,8 +3533,19 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg case SyntaxKind.ArrowFunction: case SyntaxKind.VariableDeclaration: // type annotation - if ((parent as FunctionLikeDeclaration | VariableDeclaration | ParameterDeclaration | PropertyDeclaration).type === node) { - diagnostics.push(createDiagnosticForNode(node, Diagnostics.Type_annotations_can_only_be_used_in_TypeScript_files)); + if ( + (parent as + | FunctionLikeDeclaration + | VariableDeclaration + | ParameterDeclaration + | PropertyDeclaration).type === node + ) { + diagnostics.push( + createDiagnosticForNode( + node, + Diagnostics.Type_annotations_can_only_be_used_in_TypeScript_files, + ), + ); return "skip"; } } @@ -2988,72 +3553,143 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg switch (node.kind) { case SyntaxKind.ImportClause: if ((node as ImportClause).isTypeOnly) { - diagnostics.push(createDiagnosticForNode(parent, Diagnostics._0_declarations_can_only_be_used_in_TypeScript_files, "import type")); + diagnostics.push( + createDiagnosticForNode( + parent, + Diagnostics._0_declarations_can_only_be_used_in_TypeScript_files, + "import type", + ), + ); return "skip"; } break; case SyntaxKind.ExportDeclaration: if ((node as ExportDeclaration).isTypeOnly) { - diagnostics.push(createDiagnosticForNode(node, Diagnostics._0_declarations_can_only_be_used_in_TypeScript_files, "export type")); + diagnostics.push( + createDiagnosticForNode( + node, + Diagnostics._0_declarations_can_only_be_used_in_TypeScript_files, + "export type", + ), + ); return "skip"; } break; case SyntaxKind.ImportSpecifier: case SyntaxKind.ExportSpecifier: if ((node as ImportOrExportSpecifier).isTypeOnly) { - diagnostics.push(createDiagnosticForNode(node, Diagnostics._0_declarations_can_only_be_used_in_TypeScript_files, isImportSpecifier(node) ? "import...type" : "export...type")); + diagnostics.push( + createDiagnosticForNode( + node, + Diagnostics._0_declarations_can_only_be_used_in_TypeScript_files, + isImportSpecifier(node) ? "import...type" : "export...type", + ), + ); return "skip"; } break; case SyntaxKind.ImportEqualsDeclaration: - diagnostics.push(createDiagnosticForNode(node, Diagnostics.import_can_only_be_used_in_TypeScript_files)); + diagnostics.push( + createDiagnosticForNode(node, Diagnostics.import_can_only_be_used_in_TypeScript_files), + ); return "skip"; case SyntaxKind.ExportAssignment: if ((node as ExportAssignment).isExportEquals) { - diagnostics.push(createDiagnosticForNode(node, Diagnostics.export_can_only_be_used_in_TypeScript_files)); + diagnostics.push( + createDiagnosticForNode(node, Diagnostics.export_can_only_be_used_in_TypeScript_files), + ); return "skip"; } break; case SyntaxKind.HeritageClause: const heritageClause = node as HeritageClause; if (heritageClause.token === SyntaxKind.ImplementsKeyword) { - diagnostics.push(createDiagnosticForNode(node, Diagnostics.implements_clauses_can_only_be_used_in_TypeScript_files)); + diagnostics.push( + createDiagnosticForNode( + node, + Diagnostics.implements_clauses_can_only_be_used_in_TypeScript_files, + ), + ); return "skip"; } break; case SyntaxKind.InterfaceDeclaration: const interfaceKeyword = tokenToString(SyntaxKind.InterfaceKeyword); Debug.assertIsDefined(interfaceKeyword); - diagnostics.push(createDiagnosticForNode(node, Diagnostics._0_declarations_can_only_be_used_in_TypeScript_files, interfaceKeyword)); + diagnostics.push( + createDiagnosticForNode( + node, + Diagnostics._0_declarations_can_only_be_used_in_TypeScript_files, + interfaceKeyword, + ), + ); return "skip"; case SyntaxKind.ModuleDeclaration: - const moduleKeyword = node.flags & NodeFlags.Namespace ? tokenToString(SyntaxKind.NamespaceKeyword) : tokenToString(SyntaxKind.ModuleKeyword); + const moduleKeyword = node.flags & NodeFlags.Namespace + ? tokenToString(SyntaxKind.NamespaceKeyword) : tokenToString(SyntaxKind.ModuleKeyword); Debug.assertIsDefined(moduleKeyword); - diagnostics.push(createDiagnosticForNode(node, Diagnostics._0_declarations_can_only_be_used_in_TypeScript_files, moduleKeyword)); + diagnostics.push( + createDiagnosticForNode( + node, + Diagnostics._0_declarations_can_only_be_used_in_TypeScript_files, + moduleKeyword, + ), + ); return "skip"; case SyntaxKind.TypeAliasDeclaration: - diagnostics.push(createDiagnosticForNode(node, Diagnostics.Type_aliases_can_only_be_used_in_TypeScript_files)); + diagnostics.push( + createDiagnosticForNode( + node, + Diagnostics.Type_aliases_can_only_be_used_in_TypeScript_files, + ), + ); return "skip"; case SyntaxKind.Constructor: case SyntaxKind.MethodDeclaration: case SyntaxKind.FunctionDeclaration: if (!(node as FunctionLikeDeclaration).body) { - diagnostics.push(createDiagnosticForNode(node, Diagnostics.Signature_declarations_can_only_be_used_in_TypeScript_files)); + diagnostics.push( + createDiagnosticForNode( + node, + Diagnostics.Signature_declarations_can_only_be_used_in_TypeScript_files, + ), + ); return "skip"; } return; case SyntaxKind.EnumDeclaration: const enumKeyword = Debug.checkDefined(tokenToString(SyntaxKind.EnumKeyword)); - diagnostics.push(createDiagnosticForNode(node, Diagnostics._0_declarations_can_only_be_used_in_TypeScript_files, enumKeyword)); + diagnostics.push( + createDiagnosticForNode( + node, + Diagnostics._0_declarations_can_only_be_used_in_TypeScript_files, + enumKeyword, + ), + ); return "skip"; case SyntaxKind.NonNullExpression: - diagnostics.push(createDiagnosticForNode(node, Diagnostics.Non_null_assertions_can_only_be_used_in_TypeScript_files)); + diagnostics.push( + createDiagnosticForNode( + node, + Diagnostics.Non_null_assertions_can_only_be_used_in_TypeScript_files, + ), + ); return "skip"; case SyntaxKind.AsExpression: - diagnostics.push(createDiagnosticForNode((node as AsExpression).type, Diagnostics.Type_assertion_expressions_can_only_be_used_in_TypeScript_files)); + diagnostics.push( + createDiagnosticForNode( + (node as AsExpression).type, + Diagnostics.Type_assertion_expressions_can_only_be_used_in_TypeScript_files, + ), + ); return "skip"; case SyntaxKind.SatisfiesExpression: - diagnostics.push(createDiagnosticForNode((node as SatisfiesExpression).type, Diagnostics.Type_satisfaction_expressions_can_only_be_used_in_TypeScript_files)); + diagnostics.push( + createDiagnosticForNode( + (node as SatisfiesExpression).type, + Diagnostics.Type_satisfaction_expressions_can_only_be_used_in_TypeScript_files, + ), + ); return "skip"; case SyntaxKind.TypeAssertionExpression: Debug.fail(); // Won't parse these in a JS file anyway, as they are interpreted as JSX. @@ -3073,22 +3709,45 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg if (decoratorIndex >= 0) { if (isParameter(parent) && !options.experimentalDecorators) { // report illegall decorator on parameter - diagnostics.push(createDiagnosticForNode(parent.modifiers[decoratorIndex], Diagnostics.Decorators_are_not_valid_here)); + diagnostics.push( + createDiagnosticForNode( + parent.modifiers[decoratorIndex], + Diagnostics.Decorators_are_not_valid_here, + ), + ); } else if (isClassDeclaration(parent)) { const exportIndex = findIndex(parent.modifiers, isExportModifier); if (exportIndex >= 0) { const defaultIndex = findIndex(parent.modifiers, isDefaultModifier); - if (decoratorIndex > exportIndex && defaultIndex >= 0 && decoratorIndex < defaultIndex) { + if ( + decoratorIndex > exportIndex && defaultIndex >= 0 && decoratorIndex < defaultIndex + ) { // report illegal decorator between `export` and `default` - diagnostics.push(createDiagnosticForNode(parent.modifiers[decoratorIndex], Diagnostics.Decorators_are_not_valid_here)); + diagnostics.push( + createDiagnosticForNode( + parent.modifiers[decoratorIndex], + Diagnostics.Decorators_are_not_valid_here, + ), + ); } else if (exportIndex >= 0 && decoratorIndex < exportIndex) { - const trailingDecoratorIndex = findIndex(parent.modifiers, isDecorator, exportIndex); + const trailingDecoratorIndex = findIndex( + parent.modifiers, + isDecorator, + exportIndex, + ); if (trailingDecoratorIndex >= 0) { diagnostics.push(addRelatedInfo( - createDiagnosticForNode(parent.modifiers[trailingDecoratorIndex], Diagnostics.Decorators_may_not_appear_after_export_or_export_default_if_they_also_appear_before_export), - createDiagnosticForNode(parent.modifiers[decoratorIndex], Diagnostics.Decorator_used_before_export_here), + createDiagnosticForNode( + parent.modifiers[trailingDecoratorIndex], + Diagnostics + .Decorators_may_not_appear_after_export_or_export_default_if_they_also_appear_before_export, + ), + createDiagnosticForNode( + parent.modifiers[decoratorIndex], + Diagnostics.Decorator_used_before_export_here, + ), )); } } @@ -3109,7 +3768,12 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg case SyntaxKind.ArrowFunction: // Check type parameters if (nodes === (parent as DeclarationWithTypeParameterChildren).typeParameters) { - diagnostics.push(createDiagnosticForNodeArray(nodes, Diagnostics.Type_parameter_declarations_can_only_be_used_in_TypeScript_files)); + diagnostics.push( + createDiagnosticForNodeArray( + nodes, + Diagnostics.Type_parameter_declarations_can_only_be_used_in_TypeScript_files, + ), + ); return "skip"; } // falls through @@ -3117,7 +3781,10 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg case SyntaxKind.VariableStatement: // Check modifiers if (nodes === (parent as VariableStatement).modifiers) { - checkModifiers((parent as VariableStatement).modifiers!, parent.kind === SyntaxKind.VariableStatement); + checkModifiers( + (parent as VariableStatement).modifiers!, + parent.kind === SyntaxKind.VariableStatement, + ); return "skip"; } break; @@ -3130,7 +3797,13 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg && modifier.kind !== SyntaxKind.StaticKeyword && modifier.kind !== SyntaxKind.AccessorKeyword ) { - diagnostics.push(createDiagnosticForNode(modifier, Diagnostics.The_0_modifier_can_only_be_used_in_TypeScript_files, tokenToString(modifier.kind))); + diagnostics.push( + createDiagnosticForNode( + modifier, + Diagnostics.The_0_modifier_can_only_be_used_in_TypeScript_files, + tokenToString(modifier.kind), + ), + ); } } return "skip"; @@ -3139,7 +3812,12 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg case SyntaxKind.Parameter: // Check modifiers of parameter declaration if (nodes === (parent as ParameterDeclaration).modifiers && some(nodes, isModifier)) { - diagnostics.push(createDiagnosticForNodeArray(nodes, Diagnostics.Parameter_modifiers_can_only_be_used_in_TypeScript_files)); + diagnostics.push( + createDiagnosticForNodeArray( + nodes, + Diagnostics.Parameter_modifiers_can_only_be_used_in_TypeScript_files, + ), + ); return "skip"; } break; @@ -3151,7 +3829,12 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg case SyntaxKind.TaggedTemplateExpression: // Check type arguments if (nodes === (parent as NodeWithTypeArguments).typeArguments) { - diagnostics.push(createDiagnosticForNodeArray(nodes, Diagnostics.Type_arguments_can_only_be_used_in_TypeScript_files)); + diagnostics.push( + createDiagnosticForNodeArray( + nodes, + Diagnostics.Type_arguments_can_only_be_used_in_TypeScript_files, + ), + ); return "skip"; } break; @@ -3176,7 +3859,13 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg case SyntaxKind.OverrideKeyword: case SyntaxKind.InKeyword: case SyntaxKind.OutKeyword: - diagnostics.push(createDiagnosticForNode(modifier, Diagnostics.The_0_modifier_can_only_be_used_in_TypeScript_files, tokenToString(modifier.kind))); + diagnostics.push( + createDiagnosticForNode( + modifier, + Diagnostics.The_0_modifier_can_only_be_used_in_TypeScript_files, + tokenToString(modifier.kind), + ), + ); break; // These are all legal modifiers. @@ -3188,24 +3877,43 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg } } - function createDiagnosticForNodeArray(nodes: NodeArray, message: DiagnosticMessage, ...args: DiagnosticArguments): DiagnosticWithLocation { + function createDiagnosticForNodeArray( + nodes: NodeArray, + message: DiagnosticMessage, + ...args: DiagnosticArguments + ): DiagnosticWithLocation { const start = nodes.pos; return createFileDiagnostic(sourceFile, start, nodes.end - start, message, ...args); } // Since these are syntactic diagnostics, parent might not have been set // this means the sourceFile cannot be infered from the node - function createDiagnosticForNode(node: Node, message: DiagnosticMessage, ...args: DiagnosticArguments): DiagnosticWithLocation { + function createDiagnosticForNode( + node: Node, + message: DiagnosticMessage, + ...args: DiagnosticArguments + ): DiagnosticWithLocation { return createDiagnosticForNodeInSourceFile(sourceFile, node, message, ...args); } }); } - function getDeclarationDiagnosticsWorker(sourceFile: SourceFile | undefined, cancellationToken: CancellationToken | undefined): readonly DiagnosticWithLocation[] { - return getAndCacheDiagnostics(sourceFile, cancellationToken, cachedDeclarationDiagnosticsForFile, getDeclarationDiagnosticsForFileNoCache); + function getDeclarationDiagnosticsWorker( + sourceFile: SourceFile | undefined, + cancellationToken: CancellationToken | undefined, + ): readonly DiagnosticWithLocation[] { + return getAndCacheDiagnostics( + sourceFile, + cancellationToken, + cachedDeclarationDiagnosticsForFile, + getDeclarationDiagnosticsForFileNoCache, + ); } - function getDeclarationDiagnosticsForFileNoCache(sourceFile: SourceFile | undefined, cancellationToken: CancellationToken | undefined): readonly DiagnosticWithLocation[] { + function getDeclarationDiagnosticsForFileNoCache( + sourceFile: SourceFile | undefined, + cancellationToken: CancellationToken | undefined, + ): readonly DiagnosticWithLocation[] { return runWithCancellationToken(() => { const resolver = getTypeChecker().getEmitResolver(sourceFile, cancellationToken); // Don't actually write any files since we're just getting diagnostics. @@ -3236,7 +3944,10 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg return result; } - function getDeclarationDiagnosticsForFile(sourceFile: SourceFile, cancellationToken: CancellationToken | undefined): readonly DiagnosticWithLocation[] { + function getDeclarationDiagnosticsForFile( + sourceFile: SourceFile, + cancellationToken: CancellationToken | undefined, + ): readonly DiagnosticWithLocation[] { return sourceFile.isDeclarationFile ? [] : getDeclarationDiagnosticsWorker(sourceFile, cancellationToken); } @@ -3257,14 +3968,20 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg } function getGlobalDiagnostics(): SortedReadonlyArray { - return rootNames.length ? sortAndDeduplicateDiagnostics(getTypeChecker().getGlobalDiagnostics().slice()) : emptyArray as any as SortedReadonlyArray; + return rootNames.length ? sortAndDeduplicateDiagnostics(getTypeChecker().getGlobalDiagnostics().slice()) + : emptyArray as any as SortedReadonlyArray; } function getConfigFileParsingDiagnostics(): readonly Diagnostic[] { return configFileParsingDiagnostics || emptyArray; } - function processRootFile(fileName: string, isDefaultLib: boolean, ignoreNoDefaultLib: boolean, reason: FileIncludeReason) { + function processRootFile( + fileName: string, + isDefaultLib: boolean, + ignoreNoDefaultLib: boolean, + reason: FileIncludeReason, + ) { processSourceFile(normalizePath(fileName), isDefaultLib, ignoreNoDefaultLib, /*packageId*/ undefined, reason); } @@ -3280,7 +3997,12 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg function createSyntheticImport(text: string, file: SourceFile) { const externalHelpersModuleReference = factory.createStringLiteral(text); - const importDecl = factory.createImportDeclaration(/*modifiers*/ undefined, /*importClause*/ undefined, externalHelpersModuleReference, /*assertClause*/ undefined); + const importDecl = factory.createImportDeclaration( + /*modifiers*/ undefined, + /*importClause*/ undefined, + externalHelpersModuleReference, + /*assertClause*/ undefined, + ); addInternalEmitFlags(importDecl, InternalEmitFlags.NeverApplyImportHelper); setParent(externalHelpersModuleReference, importDecl); setParent(importDecl, file); @@ -3342,7 +4064,10 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg // TypeScript 1.0 spec (April 2014): 12.1.6 // An ExternalImportDeclaration in an AmbientExternalModuleDeclaration may reference other external modules // only through top - level external module names. Relative external module names are not permitted. - if (moduleNameExpr && isStringLiteral(moduleNameExpr) && moduleNameExpr.text && (!inAmbientModule || !isExternalModuleNameRelative(moduleNameExpr.text))) { + if ( + moduleNameExpr && isStringLiteral(moduleNameExpr) && moduleNameExpr.text + && (!inAmbientModule || !isExternalModuleNameRelative(moduleNameExpr.text)) + ) { setParentRecursive(node, /*incremental*/ false); // we need parent data on imports before the program is fully bound, so we ensure it's set here imports = append(imports, moduleNameExpr); if (!usesUriStyleNodeCoreModules && currentNodeModulesDepth === 0 && !file.isDeclarationFile) { @@ -3351,7 +4076,10 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg } } else if (isModuleDeclaration(node)) { - if (isAmbientModule(node) && (inAmbientModule || hasSyntacticModifier(node, ModifierFlags.Ambient) || file.isDeclarationFile)) { + if ( + isAmbientModule(node) + && (inAmbientModule || hasSyntacticModifier(node, ModifierFlags.Ambient) || file.isDeclarationFile) + ) { (node.name as Mutable).parent = node; const nameText = getTextOfIdentifierOrLiteral(node.name); // Ambient module declarations can be interpreted as augmentations for some existing external modules. @@ -3408,12 +4136,16 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg function getNodeAtPosition(sourceFile: SourceFile, position: number): Node { let current: Node = sourceFile; const getContainingChild = (child: Node) => { - if (child.pos <= position && (position < child.end || (position === child.end && (child.kind === SyntaxKind.EndOfFileToken)))) { + if ( + child.pos <= position + && (position < child.end || (position === child.end && (child.kind === SyntaxKind.EndOfFileToken))) + ) { return child; } }; while (true) { - const child = isJavaScriptFile && hasJSDocNodes(current) && forEach(current.jsDoc, getContainingChild) || forEachChild(current, getContainingChild); + const child = isJavaScriptFile && hasJSDocNodes(current) && forEach(current.jsDoc, getContainingChild) + || forEachChild(current, getContainingChild); if (!child) { return current; } @@ -3429,8 +4161,14 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg } /** This should have similar behavior to 'processSourceFile' without diagnostics or mutation. */ - function getSourceFileFromReference(referencingFile: SourceFile | UnparsedSource, ref: FileReference): SourceFile | undefined { - return getSourceFileFromReferenceWorker(resolveTripleslashReference(ref.fileName, referencingFile.fileName), getSourceFile); + function getSourceFileFromReference( + referencingFile: SourceFile | UnparsedSource, + ref: FileReference, + ): SourceFile | undefined { + return getSourceFileFromReferenceWorker( + resolveTripleslashReference(ref.fileName, referencingFile.fileName), + getSourceFile, + ); } function getSourceFileFromReferenceWorker( @@ -3441,13 +4179,26 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg ): SourceFile | undefined { if (hasExtension(fileName)) { const canonicalFileName = host.getCanonicalFileName(fileName); - if (!options.allowNonTsExtensions && !forEach(flatten(supportedExtensionsWithJsonIfResolveJsonModule), extension => fileExtensionIs(canonicalFileName, extension))) { + if ( + !options.allowNonTsExtensions + && !forEach( + flatten(supportedExtensionsWithJsonIfResolveJsonModule), + extension => fileExtensionIs(canonicalFileName, extension), + ) + ) { if (fail) { if (hasJSFileExtension(canonicalFileName)) { - fail(Diagnostics.File_0_is_a_JavaScript_file_Did_you_mean_to_enable_the_allowJs_option, fileName); + fail( + Diagnostics.File_0_is_a_JavaScript_file_Did_you_mean_to_enable_the_allowJs_option, + fileName, + ); } else { - fail(Diagnostics.File_0_has_an_unsupported_extension_The_only_supported_extensions_are_1, fileName, "'" + flatten(supportedExtensions).join("', '") + "'"); + fail( + Diagnostics.File_0_has_an_unsupported_extension_The_only_supported_extensions_are_1, + fileName, + "'" + flatten(supportedExtensions).join("', '") + "'", + ); } } return undefined; @@ -3464,7 +4215,10 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg fail(Diagnostics.File_0_not_found, fileName); } } - else if (isReferencedFile(reason) && canonicalFileName === host.getCanonicalFileName(getSourceFileByPath(reason.file)!.fileName)) { + else if ( + isReferencedFile(reason) + && canonicalFileName === host.getCanonicalFileName(getSourceFileByPath(reason.file)!.fileName) + ) { fail(Diagnostics.A_file_cannot_have_a_reference_to_itself); } } @@ -3480,50 +4234,102 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg } // Only try adding extensions from the first supported group (which should be .ts/.tsx/.d.ts) - const sourceFileWithAddedExtension = forEach(supportedExtensions[0], extension => getSourceFile(fileName + extension)); - if (fail && !sourceFileWithAddedExtension) fail(Diagnostics.Could_not_resolve_the_path_0_with_the_extensions_Colon_1, fileName, "'" + flatten(supportedExtensions).join("', '") + "'"); + const sourceFileWithAddedExtension = forEach( + supportedExtensions[0], + extension => getSourceFile(fileName + extension), + ); + if (fail && !sourceFileWithAddedExtension) { + fail( + Diagnostics.Could_not_resolve_the_path_0_with_the_extensions_Colon_1, + fileName, + "'" + flatten(supportedExtensions).join("', '") + "'", + ); + } return sourceFileWithAddedExtension; } } /** This has side effects through `findSourceFile`. */ - function processSourceFile(fileName: string, isDefaultLib: boolean, ignoreNoDefaultLib: boolean, packageId: PackageId | undefined, reason: FileIncludeReason): void { + function processSourceFile( + fileName: string, + isDefaultLib: boolean, + ignoreNoDefaultLib: boolean, + packageId: PackageId | undefined, + reason: FileIncludeReason, + ): void { getSourceFileFromReferenceWorker( fileName, fileName => findSourceFile(fileName, isDefaultLib, ignoreNoDefaultLib, reason, packageId), // TODO: GH#18217 - (diagnostic, ...args) => addFilePreprocessingFileExplainingDiagnostic(/*file*/ undefined, reason, diagnostic, args), + (diagnostic, ...args) => + addFilePreprocessingFileExplainingDiagnostic(/*file*/ undefined, reason, diagnostic, args), reason, ); } function processProjectReferenceFile(fileName: string, reason: ProjectReferenceFile) { - return processSourceFile(fileName, /*isDefaultLib*/ false, /*ignoreNoDefaultLib*/ false, /*packageId*/ undefined, reason); + return processSourceFile( + fileName, + /*isDefaultLib*/ false, + /*ignoreNoDefaultLib*/ false, + /*packageId*/ undefined, + reason, + ); } - function reportFileNamesDifferOnlyInCasingError(fileName: string, existingFile: SourceFile, reason: FileIncludeReason): void { - const hasExistingReasonToReportErrorOn = !isReferencedFile(reason) && some(fileReasons.get(existingFile.path), isReferencedFile); + function reportFileNamesDifferOnlyInCasingError( + fileName: string, + existingFile: SourceFile, + reason: FileIncludeReason, + ): void { + const hasExistingReasonToReportErrorOn = !isReferencedFile(reason) + && some(fileReasons.get(existingFile.path), isReferencedFile); if (hasExistingReasonToReportErrorOn) { - addFilePreprocessingFileExplainingDiagnostic(existingFile, reason, Diagnostics.Already_included_file_name_0_differs_from_file_name_1_only_in_casing, [existingFile.fileName, fileName]); + addFilePreprocessingFileExplainingDiagnostic( + existingFile, + reason, + Diagnostics.Already_included_file_name_0_differs_from_file_name_1_only_in_casing, + [existingFile.fileName, fileName], + ); } else { - addFilePreprocessingFileExplainingDiagnostic(existingFile, reason, Diagnostics.File_name_0_differs_from_already_included_file_name_1_only_in_casing, [fileName, existingFile.fileName]); + addFilePreprocessingFileExplainingDiagnostic( + existingFile, + reason, + Diagnostics.File_name_0_differs_from_already_included_file_name_1_only_in_casing, + [fileName, existingFile.fileName], + ); } } - function createRedirectedSourceFile(redirectTarget: SourceFile, unredirected: SourceFile, fileName: string, path: Path, resolvedPath: Path, originalFileName: string, sourceFileOptions: CreateSourceFileOptions): SourceFile { + function createRedirectedSourceFile( + redirectTarget: SourceFile, + unredirected: SourceFile, + fileName: string, + path: Path, + resolvedPath: Path, + originalFileName: string, + sourceFileOptions: CreateSourceFileOptions, + ): SourceFile { const redirect = parseNodeFactory.createRedirectedSourceFile({ redirectTarget, unredirected }); redirect.fileName = fileName; redirect.path = path; redirect.resolvedPath = resolvedPath; redirect.originalFileName = originalFileName; - redirect.packageJsonLocations = sourceFileOptions.packageJsonLocations?.length ? sourceFileOptions.packageJsonLocations : undefined; + redirect.packageJsonLocations = sourceFileOptions.packageJsonLocations?.length + ? sourceFileOptions.packageJsonLocations : undefined; redirect.packageJsonScope = sourceFileOptions.packageJsonScope; sourceFilesFoundSearchingNodeModules.set(path, currentNodeModulesDepth > 0); return redirect; } // Get source file from normalized fileName - function findSourceFile(fileName: string, isDefaultLib: boolean, ignoreNoDefaultLib: boolean, reason: FileIncludeReason, packageId: PackageId | undefined): SourceFile | undefined { + function findSourceFile( + fileName: string, + isDefaultLib: boolean, + ignoreNoDefaultLib: boolean, + reason: FileIncludeReason, + packageId: PackageId | undefined, + ): SourceFile | undefined { tracing?.push(tracing.Phase.Program, "findSourceFile", { fileName, isDefaultLib: isDefaultLib || undefined, @@ -3534,19 +4340,35 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg return result; } - function getCreateSourceFileOptions(fileName: string, moduleResolutionCache: ModuleResolutionCache | undefined, host: CompilerHost, options: CompilerOptions): CreateSourceFileOptions { + function getCreateSourceFileOptions( + fileName: string, + moduleResolutionCache: ModuleResolutionCache | undefined, + host: CompilerHost, + options: CompilerOptions, + ): CreateSourceFileOptions { // It's a _little odd_ that we can't set `impliedNodeFormat` until the program step - but it's the first and only time we have a resolution cache // and a freshly made source file node on hand at the same time, and we need both to set the field. Persisting the resolution cache all the way // to the check and emit steps would be bad - so we much prefer detecting and storing the format information on the source file node upfront. - const result = getImpliedNodeFormatForFileWorker(getNormalizedAbsolutePath(fileName, currentDirectory), moduleResolutionCache?.getPackageJsonInfoCache(), host, options); + const result = getImpliedNodeFormatForFileWorker( + getNormalizedAbsolutePath(fileName, currentDirectory), + moduleResolutionCache?.getPackageJsonInfoCache(), + host, + options, + ); const languageVersion = getEmitScriptTarget(options); const setExternalModuleIndicator = getSetExternalModuleIndicator(options); - return typeof result === "object" ? - { ...result, languageVersion, setExternalModuleIndicator } : - { languageVersion, impliedNodeFormat: result, setExternalModuleIndicator }; + return typeof result === "object" + ? { ...result, languageVersion, setExternalModuleIndicator } + : { languageVersion, impliedNodeFormat: result, setExternalModuleIndicator }; } - function findSourceFileWorker(fileName: string, isDefaultLib: boolean, ignoreNoDefaultLib: boolean, reason: FileIncludeReason, packageId: PackageId | undefined): SourceFile | undefined { + function findSourceFileWorker( + fileName: string, + isDefaultLib: boolean, + ignoreNoDefaultLib: boolean, + reason: FileIncludeReason, + packageId: PackageId | undefined, + ): SourceFile | undefined { const path = toPath(fileName); if (useSourceOfProjectReferenceRedirect) { let source = getSourceOfProjectReferenceRedirect(path); @@ -3555,19 +4377,19 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg // Note:: Currently we try the real path only if the // file is from node_modules to avoid having to run real path on all file paths if ( - !source && - host.realpath && - options.preserveSymlinks && - isDeclarationFileName(fileName) && - stringContains(fileName, nodeModulesPathPart) + !source + && host.realpath + && options.preserveSymlinks + && isDeclarationFileName(fileName) + && stringContains(fileName, nodeModulesPathPart) ) { const realPath = toPath(host.realpath(fileName)); if (realPath !== path) source = getSourceOfProjectReferenceRedirect(realPath); } if (source) { - const file = isString(source) ? - findSourceFile(source, isDefaultLib, ignoreNoDefaultLib, reason, packageId) : - undefined; + const file = isString(source) + ? findSourceFile(source, isDefaultLib, ignoreNoDefaultLib, reason, packageId) + : undefined; if (file) addFileToFilesByName(file, path, /*redirectedPath*/ undefined); return file; } @@ -3642,7 +4464,13 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg const file = host.getSourceFile( fileName, sourceFileOptions, - hostErrorMessage => addFilePreprocessingFileExplainingDiagnostic(/*file*/ undefined, reason, Diagnostics.Cannot_read_file_0_Colon_1, [fileName, hostErrorMessage]), + hostErrorMessage => + addFilePreprocessingFileExplainingDiagnostic( + /*file*/ undefined, + reason, + Diagnostics.Cannot_read_file_0_Colon_1, + [fileName, hostErrorMessage], + ), shouldCreateNewSourceFile, ); @@ -3652,7 +4480,15 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg if (fileFromPackageId) { // Some other SourceFile already exists with this package name and version. // Instead of creating a duplicate, just redirect to the existing one. - const dupFile = createRedirectedSourceFile(fileFromPackageId, file!, fileName, path, toPath(fileName), originalFileName, sourceFileOptions); + const dupFile = createRedirectedSourceFile( + fileFromPackageId, + file!, + fileName, + path, + toPath(fileName), + originalFileName, + sourceFileOptions, + ); redirectTargetsMap.add(fileFromPackageId.path, fileName); addFileToFilesByName(dupFile, path, redirectedPath); addFileIncludeReason(dupFile, reason); @@ -3674,7 +4510,8 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg file.path = path; file.resolvedPath = toPath(fileName); file.originalFileName = originalFileName; - file.packageJsonLocations = sourceFileOptions.packageJsonLocations?.length ? sourceFileOptions.packageJsonLocations : undefined; + file.packageJsonLocations = sourceFileOptions.packageJsonLocations?.length + ? sourceFileOptions.packageJsonLocations : undefined; file.packageJsonScope = sourceFileOptions.packageJsonScope; addFileIncludeReason(file, reason); @@ -3734,7 +4571,10 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg function getProjectReferenceRedirectProject(fileName: string) { // Ignore dts or any json files - if (!resolvedProjectReferences || !resolvedProjectReferences.length || isDeclarationFileName(fileName) || fileExtensionIs(fileName, Extension.Json)) { + if ( + !resolvedProjectReferences || !resolvedProjectReferences.length || isDeclarationFileName(fileName) + || fileExtensionIs(fileName, Extension.Json) + ) { return undefined; } @@ -3745,9 +4585,9 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg function getProjectReferenceOutputName(referencedProject: ResolvedProjectReference, fileName: string) { const out = outFile(referencedProject.commandLine.options); - return out ? - changeExtension(out, Extension.Dts) : - getOutputDeclarationFileName(fileName, referencedProject.commandLine, !host.useCaseSensitiveFileNames()); + return out + ? changeExtension(out, Extension.Dts) + : getOutputDeclarationFileName(fileName, referencedProject.commandLine, !host.useCaseSensitiveFileNames()); } /** @@ -3759,7 +4599,9 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg forEachResolvedProjectReference(referencedProject => { // not input file from the referenced project, ignore if (toPath(options.configFilePath!) !== referencedProject.sourceFile.path) { - referencedProject.commandLine.fileNames.forEach(f => mapFromFileToProjectReferenceRedirects!.set(toPath(f), referencedProject.sourceFile.path)); + referencedProject.commandLine.fileNames.forEach(f => + mapFromFileToProjectReferenceRedirects!.set(toPath(f), referencedProject.sourceFile.path) + ); } }); } @@ -3786,10 +4628,17 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg mapFromToProjectReferenceRedirectSource!.set(toPath(outputDts), true); } else { - const getCommonSourceDirectory = memoize(() => getCommonSourceDirectoryOfConfig(resolvedRef.commandLine, !host.useCaseSensitiveFileNames())); + const getCommonSourceDirectory = memoize(() => + getCommonSourceDirectoryOfConfig(resolvedRef.commandLine, !host.useCaseSensitiveFileNames()) + ); forEach(resolvedRef.commandLine.fileNames, fileName => { if (!isDeclarationFileName(fileName) && !fileExtensionIs(fileName, Extension.Json)) { - const outputDts = getOutputDeclarationFileName(fileName, resolvedRef.commandLine, !host.useCaseSensitiveFileNames(), getCommonSourceDirectory); + const outputDts = getOutputDeclarationFileName( + fileName, + resolvedRef.commandLine, + !host.useCaseSensitiveFileNames(), + getCommonSourceDirectory, + ); mapFromToProjectReferenceRedirectSource!.set(toPath(outputDts), fileName); } }); @@ -3836,17 +4685,34 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg const resolvedTypeReferenceDirective = resolutions[index]; // store resolved type directive on the file const fileName = toFileNameLowerCase(ref.fileName); - setResolvedTypeReferenceDirective(file, fileName, resolvedTypeReferenceDirective, getModeForFileReference(ref, file.impliedNodeFormat)); + setResolvedTypeReferenceDirective( + file, + fileName, + resolvedTypeReferenceDirective, + getModeForFileReference(ref, file.impliedNodeFormat), + ); const mode = ref.resolutionMode || file.impliedNodeFormat; - if (mode && getEmitModuleResolutionKind(options) !== ModuleResolutionKind.Node16 && getEmitModuleResolutionKind(options) !== ModuleResolutionKind.NodeNext) { + if ( + mode && getEmitModuleResolutionKind(options) !== ModuleResolutionKind.Node16 + && getEmitModuleResolutionKind(options) !== ModuleResolutionKind.NodeNext + ) { (fileProcessingDiagnostics ??= []).push({ kind: FilePreprocessingDiagnosticsKind.ResolutionDiagnostics, diagnostics: [ - createDiagnosticForRange(file, ref, Diagnostics.resolution_mode_assertions_are_only_supported_when_moduleResolution_is_node16_or_nodenext), + createDiagnosticForRange( + file, + ref, + Diagnostics + .resolution_mode_assertions_are_only_supported_when_moduleResolution_is_node16_or_nodenext, + ), ], }); } - processTypeReferenceDirective(fileName, mode, resolvedTypeReferenceDirective, { kind: FileIncludeKind.TypeReferenceDirective, file: file.path, index }); + processTypeReferenceDirective(fileName, mode, resolvedTypeReferenceDirective, { + kind: FileIncludeKind.TypeReferenceDirective, + file: file.path, + index, + }); } } @@ -3856,7 +4722,12 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg resolution: ResolvedTypeReferenceDirectiveWithFailedLookupLocations, reason: FileIncludeReason, ): void { - tracing?.push(tracing.Phase.Program, "processTypeReferenceDirective", { directive: typeReferenceDirective, hasResolved: !!resolution.resolvedTypeReferenceDirective, refKind: reason.kind, refPath: isReferencedFile(reason) ? reason.file : undefined }); + tracing?.push(tracing.Phase.Program, "processTypeReferenceDirective", { + directive: typeReferenceDirective, + hasResolved: !!resolution.resolvedTypeReferenceDirective, + refKind: reason.kind, + refPath: isReferencedFile(reason) ? reason.file : undefined, + }); processTypeReferenceDirectiveWorker(typeReferenceDirective, mode, resolution, reason); tracing?.pop(); } @@ -3869,7 +4740,8 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg ): void { addResolutionDiagnostics(resolution); // If we already found this library as a primary reference - nothing to do - const previousResolution = resolvedTypeReferenceDirectives.get(typeReferenceDirective, mode)?.resolvedTypeReferenceDirective; + const previousResolution = resolvedTypeReferenceDirectives.get(typeReferenceDirective, mode) + ?.resolvedTypeReferenceDirective; if (previousResolution && previousResolution.primary) { return; } @@ -3880,7 +4752,13 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg if (resolvedTypeReferenceDirective.primary) { // resolved from the primary path - processSourceFile(resolvedTypeReferenceDirective.resolvedFileName!, /*isDefaultLib*/ false, /*ignoreNoDefaultLib*/ false, resolvedTypeReferenceDirective.packageId, reason); // TODO: GH#18217 + processSourceFile( + resolvedTypeReferenceDirective.resolvedFileName!, + /*isDefaultLib*/ false, + /*ignoreNoDefaultLib*/ false, + resolvedTypeReferenceDirective.packageId, + reason, + ); // TODO: GH#18217 } else { // If we already resolved to this file, it must have been a secondary reference. Check file contents @@ -3894,8 +4772,13 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg addFilePreprocessingFileExplainingDiagnostic( existingFile, reason, - Diagnostics.Conflicting_definitions_for_0_found_at_1_and_2_Consider_installing_a_specific_version_of_this_library_to_resolve_the_conflict, - [typeReferenceDirective, resolvedTypeReferenceDirective.resolvedFileName!, previousResolution.resolvedFileName!], + Diagnostics + .Conflicting_definitions_for_0_found_at_1_and_2_Consider_installing_a_specific_version_of_this_library_to_resolve_the_conflict, + [ + typeReferenceDirective, + resolvedTypeReferenceDirective.resolvedFileName!, + previousResolution.resolvedFileName!, + ], ); } } @@ -3904,14 +4787,25 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg } else { // First resolution of this library - processSourceFile(resolvedTypeReferenceDirective.resolvedFileName!, /*isDefaultLib*/ false, /*ignoreNoDefaultLib*/ false, resolvedTypeReferenceDirective.packageId, reason); + processSourceFile( + resolvedTypeReferenceDirective.resolvedFileName!, + /*isDefaultLib*/ false, + /*ignoreNoDefaultLib*/ false, + resolvedTypeReferenceDirective.packageId, + reason, + ); } } if (resolvedTypeReferenceDirective.isExternalLibraryImport) currentNodeModulesDepth--; } else { - addFilePreprocessingFileExplainingDiagnostic(/*file*/ undefined, reason, Diagnostics.Cannot_find_type_definition_file_for_0, [typeReferenceDirective]); + addFilePreprocessingFileExplainingDiagnostic( + /*file*/ undefined, + reason, + Diagnostics.Cannot_find_type_definition_file_for_0, + [typeReferenceDirective], + ); } if (saveResolution) { @@ -3939,15 +4833,18 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg const resolveFrom = getInferredLibraryNameResolveFrom(options, currentDirectory, libFileName); trace( host, - oldResolution.resolution.resolvedModule ? - oldResolution.resolution.resolvedModule.packageId ? - Diagnostics.Reusing_resolution_of_module_0_from_1_of_old_program_it_was_successfully_resolved_to_2_with_Package_ID_3 : - Diagnostics.Reusing_resolution_of_module_0_from_1_of_old_program_it_was_successfully_resolved_to_2 : - Diagnostics.Reusing_resolution_of_module_0_from_1_of_old_program_it_was_not_resolved, + oldResolution.resolution.resolvedModule + ? oldResolution.resolution.resolvedModule.packageId + ? Diagnostics + .Reusing_resolution_of_module_0_from_1_of_old_program_it_was_successfully_resolved_to_2_with_Package_ID_3 + : Diagnostics + .Reusing_resolution_of_module_0_from_1_of_old_program_it_was_successfully_resolved_to_2 + : Diagnostics.Reusing_resolution_of_module_0_from_1_of_old_program_it_was_not_resolved, libraryName, getNormalizedAbsolutePath(resolveFrom, currentDirectory), oldResolution.resolution.resolvedModule?.resolvedFileName, - oldResolution.resolution.resolvedModule?.packageId && packageIdToString(oldResolution.resolution.resolvedModule.packageId), + oldResolution.resolution.resolvedModule?.packageId + && packageIdToString(oldResolution.resolution.resolvedModule.packageId), ); } (resolvedLibProcessing ??= new Map()).set(libFileName, oldResolution); @@ -3965,9 +4862,9 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg tracing?.pop(); const result: LibResolution = { resolution, - actual: resolution.resolvedModule ? - resolution.resolvedModule.resolvedFileName : - combinePaths(defaultLibraryPath, libFileName), + actual: resolution.resolvedModule + ? resolution.resolvedModule.resolvedFileName + : combinePaths(defaultLibraryPath, libFileName), }; (resolvedLibProcessing ??= new Map()).set(libFileName, result); return result; @@ -3978,12 +4875,17 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg const { libName, libFileName } = getLibFileNameFromLibReference(libReference); if (libFileName) { // we ignore any 'no-default-lib' reference set on this file. - processRootFile(pathForLibFile(libFileName), /*isDefaultLib*/ true, /*ignoreNoDefaultLib*/ true, { kind: FileIncludeKind.LibReferenceDirective, file: file.path, index }); + processRootFile(pathForLibFile(libFileName), /*isDefaultLib*/ true, /*ignoreNoDefaultLib*/ true, { + kind: FileIncludeKind.LibReferenceDirective, + file: file.path, + index, + }); } else { const unqualifiedLibName = removeSuffix(removePrefix(libName, "lib."), ".d.ts"); const suggestion = getSpellingSuggestion(unqualifiedLibName, libs, identity); - const diagnostic = suggestion ? Diagnostics.Cannot_find_lib_definition_for_0_Did_you_mean_1 : Diagnostics.Cannot_find_lib_definition_for_0; + const diagnostic = suggestion ? Diagnostics.Cannot_find_lib_definition_for_0_Did_you_mean_1 + : Diagnostics.Cannot_find_lib_definition_for_0; const args = suggestion ? [libName, suggestion] : [libName]; (fileProcessingDiagnostics ||= []).push({ kind: FilePreprocessingDiagnosticsKind.FilePreprocessingReferencedDiagnostic, @@ -4006,7 +4908,9 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg const moduleNames = getModuleNames(file); const resolutions = resolveModuleNamesReusingOldState(moduleNames, file); Debug.assert(resolutions.length === moduleNames.length); - const optionsForFile = (useSourceOfProjectReferenceRedirect ? getRedirectReferenceForResolution(file)?.commandLine.options : undefined) || options; + const optionsForFile = + (useSourceOfProjectReferenceRedirect ? getRedirectReferenceForResolution(file)?.commandLine.options + : undefined) || options; for (let index = 0; index < moduleNames.length; index++) { const resolution = resolutions[index].resolvedModule; const moduleName = moduleNames[index].text; @@ -4069,10 +4973,14 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg function checkSourceFilesBelongToPath(sourceFiles: readonly SourceFile[], rootDirectory: string): boolean { let allFilesBelongToPath = true; - const absoluteRootDirectoryPath = host.getCanonicalFileName(getNormalizedAbsolutePath(rootDirectory, currentDirectory)); + const absoluteRootDirectoryPath = host.getCanonicalFileName( + getNormalizedAbsolutePath(rootDirectory, currentDirectory), + ); for (const sourceFile of sourceFiles) { if (!sourceFile.isDeclarationFile) { - const absoluteSourceFilePath = host.getCanonicalFileName(getNormalizedAbsolutePath(sourceFile.fileName, currentDirectory)); + const absoluteSourceFilePath = host.getCanonicalFileName( + getNormalizedAbsolutePath(sourceFile.fileName, currentDirectory), + ); if (absoluteSourceFilePath.indexOf(absoluteRootDirectoryPath) !== 0) { addProgramDiagnosticExplainingFile( sourceFile, @@ -4122,7 +5030,13 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg projectReferenceRedirects.set(sourceFilePath, false); return undefined; } - commandLine = parseJsonSourceFileConfigFileContent(sourceFile, configParsingHost, basePath, /*existingOptions*/ undefined, refPath); + commandLine = parseJsonSourceFileConfigFileContent( + sourceFile, + configParsingHost, + basePath, + /*existingOptions*/ undefined, + refPath, + ); } sourceFile.fileName = refPath; sourceFile.path = sourceFilePath; @@ -4139,48 +5053,88 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg function verifyCompilerOptions() { if (options.strictPropertyInitialization && !getStrictOptionValue(options, "strictNullChecks")) { - createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1, "strictPropertyInitialization", "strictNullChecks"); + createDiagnosticForOptionName( + Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1, + "strictPropertyInitialization", + "strictNullChecks", + ); } if (options.exactOptionalPropertyTypes && !getStrictOptionValue(options, "strictNullChecks")) { - createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1, "exactOptionalPropertyTypes", "strictNullChecks"); + createDiagnosticForOptionName( + Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1, + "exactOptionalPropertyTypes", + "strictNullChecks", + ); } if (options.isolatedModules || options.verbatimModuleSyntax) { if (options.out) { - createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_with_option_1, "out", options.verbatimModuleSyntax ? "verbatimModuleSyntax" : "isolatedModules"); + createDiagnosticForOptionName( + Diagnostics.Option_0_cannot_be_specified_with_option_1, + "out", + options.verbatimModuleSyntax ? "verbatimModuleSyntax" : "isolatedModules", + ); } if (options.outFile) { - createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_with_option_1, "outFile", options.verbatimModuleSyntax ? "verbatimModuleSyntax" : "isolatedModules"); + createDiagnosticForOptionName( + Diagnostics.Option_0_cannot_be_specified_with_option_1, + "outFile", + options.verbatimModuleSyntax ? "verbatimModuleSyntax" : "isolatedModules", + ); } } if (options.inlineSourceMap) { if (options.sourceMap) { - createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_with_option_1, "sourceMap", "inlineSourceMap"); + createDiagnosticForOptionName( + Diagnostics.Option_0_cannot_be_specified_with_option_1, + "sourceMap", + "inlineSourceMap", + ); } if (options.mapRoot) { - createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_with_option_1, "mapRoot", "inlineSourceMap"); + createDiagnosticForOptionName( + Diagnostics.Option_0_cannot_be_specified_with_option_1, + "mapRoot", + "inlineSourceMap", + ); } } if (options.composite) { if (options.declaration === false) { - createDiagnosticForOptionName(Diagnostics.Composite_projects_may_not_disable_declaration_emit, "declaration"); + createDiagnosticForOptionName( + Diagnostics.Composite_projects_may_not_disable_declaration_emit, + "declaration", + ); } if (options.incremental === false) { - createDiagnosticForOptionName(Diagnostics.Composite_projects_may_not_disable_incremental_compilation, "declaration"); + createDiagnosticForOptionName( + Diagnostics.Composite_projects_may_not_disable_incremental_compilation, + "declaration", + ); } } const outputFile = outFile(options); if (options.tsBuildInfoFile) { if (!isIncrementalCompilation(options)) { - createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1_or_option_2, "tsBuildInfoFile", "incremental", "composite"); + createDiagnosticForOptionName( + Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1_or_option_2, + "tsBuildInfoFile", + "incremental", + "composite", + ); } } else if (options.incremental && !outputFile && !options.configFilePath) { - programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Option_incremental_can_only_be_specified_using_tsconfig_emitting_to_single_file_or_when_option_tsBuildInfoFile_is_specified)); + programDiagnostics.add( + createCompilerDiagnostic( + Diagnostics + .Option_incremental_can_only_be_specified_using_tsconfig_emitting_to_single_file_or_when_option_tsBuildInfoFile_is_specified, + ), + ); } verifyDeprecatedCompilerOptions(); @@ -4194,7 +5148,8 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg if (sourceFileMayBeEmitted(file, program) && !rootPaths.has(file.path)) { addProgramDiagnosticExplainingFile( file, - Diagnostics.File_0_is_not_listed_within_the_file_list_of_project_1_Projects_must_list_all_files_or_use_an_include_pattern, + Diagnostics + .File_0_is_not_listed_within_the_file_list_of_project_1_Projects_must_list_all_files_or_use_an_include_pattern, [file.fileName, options.configFilePath || ""], ); } @@ -4207,41 +5162,82 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg continue; } if (!hasZeroOrOneAsteriskCharacter(key)) { - createDiagnosticForOptionPaths(/*onKey*/ true, key, Diagnostics.Pattern_0_can_have_at_most_one_Asterisk_character, key); + createDiagnosticForOptionPaths( + /*onKey*/ true, + key, + Diagnostics.Pattern_0_can_have_at_most_one_Asterisk_character, + key, + ); } if (isArray(options.paths[key])) { const len = options.paths[key].length; if (len === 0) { - createDiagnosticForOptionPaths(/*onKey*/ false, key, Diagnostics.Substitutions_for_pattern_0_shouldn_t_be_an_empty_array, key); + createDiagnosticForOptionPaths( + /*onKey*/ false, + key, + Diagnostics.Substitutions_for_pattern_0_shouldn_t_be_an_empty_array, + key, + ); } for (let i = 0; i < len; i++) { const subst = options.paths[key][i]; const typeOfSubst = typeof subst; if (typeOfSubst === "string") { if (!hasZeroOrOneAsteriskCharacter(subst)) { - createDiagnosticForOptionPathKeyValue(key, i, Diagnostics.Substitution_0_in_pattern_1_can_have_at_most_one_Asterisk_character, subst, key); + createDiagnosticForOptionPathKeyValue( + key, + i, + Diagnostics.Substitution_0_in_pattern_1_can_have_at_most_one_Asterisk_character, + subst, + key, + ); } if (!options.baseUrl && !pathIsRelative(subst) && !pathIsAbsolute(subst)) { - createDiagnosticForOptionPathKeyValue(key, i, Diagnostics.Non_relative_paths_are_not_allowed_when_baseUrl_is_not_set_Did_you_forget_a_leading_Slash); + createDiagnosticForOptionPathKeyValue( + key, + i, + Diagnostics + .Non_relative_paths_are_not_allowed_when_baseUrl_is_not_set_Did_you_forget_a_leading_Slash, + ); } } else { - createDiagnosticForOptionPathKeyValue(key, i, Diagnostics.Substitution_0_for_pattern_1_has_incorrect_type_expected_string_got_2, subst, key, typeOfSubst); + createDiagnosticForOptionPathKeyValue( + key, + i, + Diagnostics.Substitution_0_for_pattern_1_has_incorrect_type_expected_string_got_2, + subst, + key, + typeOfSubst, + ); } } } else { - createDiagnosticForOptionPaths(/*onKey*/ false, key, Diagnostics.Substitutions_for_pattern_0_should_be_an_array, key); + createDiagnosticForOptionPaths( + /*onKey*/ false, + key, + Diagnostics.Substitutions_for_pattern_0_should_be_an_array, + key, + ); } } } if (!options.sourceMap && !options.inlineSourceMap) { if (options.inlineSources) { - createDiagnosticForOptionName(Diagnostics.Option_0_can_only_be_used_when_either_option_inlineSourceMap_or_option_sourceMap_is_provided, "inlineSources"); + createDiagnosticForOptionName( + Diagnostics + .Option_0_can_only_be_used_when_either_option_inlineSourceMap_or_option_sourceMap_is_provided, + "inlineSources", + ); } if (options.sourceRoot) { - createDiagnosticForOptionName(Diagnostics.Option_0_can_only_be_used_when_either_option_inlineSourceMap_or_option_sourceMap_is_provided, "sourceRoot"); + createDiagnosticForOptionName( + Diagnostics + .Option_0_can_only_be_used_when_either_option_inlineSourceMap_or_option_sourceMap_is_provided, + "sourceRoot", + ); } } @@ -4251,20 +5247,39 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg if (options.mapRoot && !(options.sourceMap || options.declarationMap)) { // Error to specify --mapRoot without --sourcemap - createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1_or_option_2, "mapRoot", "sourceMap", "declarationMap"); + createDiagnosticForOptionName( + Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1_or_option_2, + "mapRoot", + "sourceMap", + "declarationMap", + ); } if (options.declarationDir) { if (!getEmitDeclarations(options)) { - createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1_or_option_2, "declarationDir", "declaration", "composite"); + createDiagnosticForOptionName( + Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1_or_option_2, + "declarationDir", + "declaration", + "composite", + ); } if (outputFile) { - createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_with_option_1, "declarationDir", options.out ? "out" : "outFile"); + createDiagnosticForOptionName( + Diagnostics.Option_0_cannot_be_specified_with_option_1, + "declarationDir", + options.out ? "out" : "outFile", + ); } } if (options.declarationMap && !getEmitDeclarations(options)) { - createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1_or_option_2, "declarationMap", "declaration", "composite"); + createDiagnosticForOptionName( + Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1_or_option_2, + "declarationMap", + "declaration", + "composite", + ); } if (options.lib && options.noLib) { @@ -4272,137 +5287,259 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg } if (options.noImplicitUseStrict && getStrictOptionValue(options, "alwaysStrict")) { - createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_with_option_1, "noImplicitUseStrict", "alwaysStrict"); + createDiagnosticForOptionName( + Diagnostics.Option_0_cannot_be_specified_with_option_1, + "noImplicitUseStrict", + "alwaysStrict", + ); } const languageVersion = getEmitScriptTarget(options); const firstNonAmbientExternalModuleSourceFile = find(files, f => isExternalModule(f) && !f.isDeclarationFile); if (options.isolatedModules || options.verbatimModuleSyntax) { - if (options.module === ModuleKind.None && languageVersion < ScriptTarget.ES2015 && options.isolatedModules) { - createDiagnosticForOptionName(Diagnostics.Option_isolatedModules_can_only_be_used_when_either_option_module_is_provided_or_option_target_is_ES2015_or_higher, "isolatedModules", "target"); + if ( + options.module === ModuleKind.None && languageVersion < ScriptTarget.ES2015 && options.isolatedModules + ) { + createDiagnosticForOptionName( + Diagnostics + .Option_isolatedModules_can_only_be_used_when_either_option_module_is_provided_or_option_target_is_ES2015_or_higher, + "isolatedModules", + "target", + ); } if (options.preserveConstEnums === false) { - createDiagnosticForOptionName(Diagnostics.Option_preserveConstEnums_cannot_be_disabled_when_0_is_enabled, options.verbatimModuleSyntax ? "verbatimModuleSyntax" : "isolatedModules", "preserveConstEnums"); + createDiagnosticForOptionName( + Diagnostics.Option_preserveConstEnums_cannot_be_disabled_when_0_is_enabled, + options.verbatimModuleSyntax ? "verbatimModuleSyntax" : "isolatedModules", + "preserveConstEnums", + ); } } - else if (firstNonAmbientExternalModuleSourceFile && languageVersion < ScriptTarget.ES2015 && options.module === ModuleKind.None) { + else if ( + firstNonAmbientExternalModuleSourceFile && languageVersion < ScriptTarget.ES2015 + && options.module === ModuleKind.None + ) { // We cannot use createDiagnosticFromNode because nodes do not have parents yet - const span = getErrorSpanForNode(firstNonAmbientExternalModuleSourceFile, typeof firstNonAmbientExternalModuleSourceFile.externalModuleIndicator === "boolean" ? firstNonAmbientExternalModuleSourceFile : firstNonAmbientExternalModuleSourceFile.externalModuleIndicator!); - programDiagnostics.add(createFileDiagnostic(firstNonAmbientExternalModuleSourceFile, span.start, span.length, Diagnostics.Cannot_use_imports_exports_or_module_augmentations_when_module_is_none)); + const span = getErrorSpanForNode( + firstNonAmbientExternalModuleSourceFile, + typeof firstNonAmbientExternalModuleSourceFile.externalModuleIndicator === "boolean" + ? firstNonAmbientExternalModuleSourceFile + : firstNonAmbientExternalModuleSourceFile.externalModuleIndicator!, + ); + programDiagnostics.add( + createFileDiagnostic( + firstNonAmbientExternalModuleSourceFile, + span.start, + span.length, + Diagnostics.Cannot_use_imports_exports_or_module_augmentations_when_module_is_none, + ), + ); } // Cannot specify module gen that isn't amd or system with --out if (outputFile && !options.emitDeclarationOnly) { if (options.module && !(options.module === ModuleKind.AMD || options.module === ModuleKind.System)) { - createDiagnosticForOptionName(Diagnostics.Only_amd_and_system_modules_are_supported_alongside_0, options.out ? "out" : "outFile", "module"); + createDiagnosticForOptionName( + Diagnostics.Only_amd_and_system_modules_are_supported_alongside_0, + options.out ? "out" : "outFile", + "module", + ); } else if (options.module === undefined && firstNonAmbientExternalModuleSourceFile) { - const span = getErrorSpanForNode(firstNonAmbientExternalModuleSourceFile, typeof firstNonAmbientExternalModuleSourceFile.externalModuleIndicator === "boolean" ? firstNonAmbientExternalModuleSourceFile : firstNonAmbientExternalModuleSourceFile.externalModuleIndicator!); - programDiagnostics.add(createFileDiagnostic(firstNonAmbientExternalModuleSourceFile, span.start, span.length, Diagnostics.Cannot_compile_modules_using_option_0_unless_the_module_flag_is_amd_or_system, options.out ? "out" : "outFile")); + const span = getErrorSpanForNode( + firstNonAmbientExternalModuleSourceFile, + typeof firstNonAmbientExternalModuleSourceFile.externalModuleIndicator === "boolean" + ? firstNonAmbientExternalModuleSourceFile + : firstNonAmbientExternalModuleSourceFile.externalModuleIndicator!, + ); + programDiagnostics.add( + createFileDiagnostic( + firstNonAmbientExternalModuleSourceFile, + span.start, + span.length, + Diagnostics.Cannot_compile_modules_using_option_0_unless_the_module_flag_is_amd_or_system, + options.out ? "out" : "outFile", + ), + ); } } if (getResolveJsonModule(options)) { if (getEmitModuleResolutionKind(options) === ModuleResolutionKind.Classic) { - createDiagnosticForOptionName(Diagnostics.Option_resolveJsonModule_cannot_be_specified_when_moduleResolution_is_set_to_classic, "resolveJsonModule"); + createDiagnosticForOptionName( + Diagnostics.Option_resolveJsonModule_cannot_be_specified_when_moduleResolution_is_set_to_classic, + "resolveJsonModule", + ); } // Any emit other than common js, amd, es2015 or esnext is error else if (!hasJsonModuleEmitEnabled(options)) { - createDiagnosticForOptionName(Diagnostics.Option_resolveJsonModule_can_only_be_specified_when_module_code_generation_is_commonjs_amd_es2015_or_esNext, "resolveJsonModule", "module"); + createDiagnosticForOptionName( + Diagnostics + .Option_resolveJsonModule_can_only_be_specified_when_module_code_generation_is_commonjs_amd_es2015_or_esNext, + "resolveJsonModule", + "module", + ); } } // there has to be common source directory if user specified --outdir || --rootDir || --sourceRoot // if user specified --mapRoot, there needs to be common source directory if there would be multiple files being emitted if ( - options.outDir || // there is --outDir specified - options.rootDir || // there is --rootDir specified - options.sourceRoot || // there is --sourceRoot specified - options.mapRoot + options.outDir // there is --outDir specified + || options.rootDir // there is --rootDir specified + || options.sourceRoot // there is --sourceRoot specified + || options.mapRoot ) { // there is --mapRoot specified // Precalculate and cache the common source directory const dir = getCommonSourceDirectory(); // If we failed to find a good common directory, but outDir is specified and at least one of our files is on a windows drive/URL/other resource, add a failure if (options.outDir && dir === "" && files.some(file => getRootLength(file.fileName) > 1)) { - createDiagnosticForOptionName(Diagnostics.Cannot_find_the_common_subdirectory_path_for_the_input_files, "outDir"); + createDiagnosticForOptionName( + Diagnostics.Cannot_find_the_common_subdirectory_path_for_the_input_files, + "outDir", + ); } } if (options.useDefineForClassFields && languageVersion === ScriptTarget.ES3) { - createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_when_option_target_is_ES3, "useDefineForClassFields"); + createDiagnosticForOptionName( + Diagnostics.Option_0_cannot_be_specified_when_option_target_is_ES3, + "useDefineForClassFields", + ); } if (options.checkJs && !getAllowJSCompilerOption(options)) { - programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1, "checkJs", "allowJs")); + programDiagnostics.add( + createCompilerDiagnostic( + Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1, + "checkJs", + "allowJs", + ), + ); } if (options.emitDeclarationOnly) { if (!getEmitDeclarations(options)) { - createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1_or_option_2, "emitDeclarationOnly", "declaration", "composite"); + createDiagnosticForOptionName( + Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1_or_option_2, + "emitDeclarationOnly", + "declaration", + "composite", + ); } if (options.noEmit) { - createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_with_option_1, "emitDeclarationOnly", "noEmit"); + createDiagnosticForOptionName( + Diagnostics.Option_0_cannot_be_specified_with_option_1, + "emitDeclarationOnly", + "noEmit", + ); } } if ( - options.emitDecoratorMetadata && - !options.experimentalDecorators + options.emitDecoratorMetadata + && !options.experimentalDecorators ) { - createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1, "emitDecoratorMetadata", "experimentalDecorators"); + createDiagnosticForOptionName( + Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1, + "emitDecoratorMetadata", + "experimentalDecorators", + ); } if (options.jsxFactory) { if (options.reactNamespace) { - createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_with_option_1, "reactNamespace", "jsxFactory"); + createDiagnosticForOptionName( + Diagnostics.Option_0_cannot_be_specified_with_option_1, + "reactNamespace", + "jsxFactory", + ); } if (options.jsx === JsxEmit.ReactJSX || options.jsx === JsxEmit.ReactJSXDev) { - createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_when_option_jsx_is_1, "jsxFactory", inverseJsxOptionMap.get("" + options.jsx)); + createDiagnosticForOptionName( + Diagnostics.Option_0_cannot_be_specified_when_option_jsx_is_1, + "jsxFactory", + inverseJsxOptionMap.get("" + options.jsx), + ); } if (!parseIsolatedEntityName(options.jsxFactory, languageVersion)) { - createOptionValueDiagnostic("jsxFactory", Diagnostics.Invalid_value_for_jsxFactory_0_is_not_a_valid_identifier_or_qualified_name, options.jsxFactory); + createOptionValueDiagnostic( + "jsxFactory", + Diagnostics.Invalid_value_for_jsxFactory_0_is_not_a_valid_identifier_or_qualified_name, + options.jsxFactory, + ); } } else if (options.reactNamespace && !isIdentifierText(options.reactNamespace, languageVersion)) { - createOptionValueDiagnostic("reactNamespace", Diagnostics.Invalid_value_for_reactNamespace_0_is_not_a_valid_identifier, options.reactNamespace); + createOptionValueDiagnostic( + "reactNamespace", + Diagnostics.Invalid_value_for_reactNamespace_0_is_not_a_valid_identifier, + options.reactNamespace, + ); } if (options.jsxFragmentFactory) { if (!options.jsxFactory) { - createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1, "jsxFragmentFactory", "jsxFactory"); + createDiagnosticForOptionName( + Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1, + "jsxFragmentFactory", + "jsxFactory", + ); } if (options.jsx === JsxEmit.ReactJSX || options.jsx === JsxEmit.ReactJSXDev) { - createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_when_option_jsx_is_1, "jsxFragmentFactory", inverseJsxOptionMap.get("" + options.jsx)); + createDiagnosticForOptionName( + Diagnostics.Option_0_cannot_be_specified_when_option_jsx_is_1, + "jsxFragmentFactory", + inverseJsxOptionMap.get("" + options.jsx), + ); } if (!parseIsolatedEntityName(options.jsxFragmentFactory, languageVersion)) { - createOptionValueDiagnostic("jsxFragmentFactory", Diagnostics.Invalid_value_for_jsxFragmentFactory_0_is_not_a_valid_identifier_or_qualified_name, options.jsxFragmentFactory); + createOptionValueDiagnostic( + "jsxFragmentFactory", + Diagnostics.Invalid_value_for_jsxFragmentFactory_0_is_not_a_valid_identifier_or_qualified_name, + options.jsxFragmentFactory, + ); } } if (options.reactNamespace) { if (options.jsx === JsxEmit.ReactJSX || options.jsx === JsxEmit.ReactJSXDev) { - createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_when_option_jsx_is_1, "reactNamespace", inverseJsxOptionMap.get("" + options.jsx)); + createDiagnosticForOptionName( + Diagnostics.Option_0_cannot_be_specified_when_option_jsx_is_1, + "reactNamespace", + inverseJsxOptionMap.get("" + options.jsx), + ); } } if (options.jsxImportSource) { if (options.jsx === JsxEmit.React) { - createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_when_option_jsx_is_1, "jsxImportSource", inverseJsxOptionMap.get("" + options.jsx)); + createDiagnosticForOptionName( + Diagnostics.Option_0_cannot_be_specified_when_option_jsx_is_1, + "jsxImportSource", + inverseJsxOptionMap.get("" + options.jsx), + ); } } if (options.preserveValueImports && getEmitModuleKind(options) < ModuleKind.ES2015) { - createDiagnosticForOptionName(Diagnostics.Option_0_can_only_be_used_when_module_is_set_to_es2015_or_later, "preserveValueImports"); + createDiagnosticForOptionName( + Diagnostics.Option_0_can_only_be_used_when_module_is_set_to_es2015_or_later, + "preserveValueImports", + ); } const moduleKind = getEmitModuleKind(options); if (options.verbatimModuleSyntax) { if (moduleKind === ModuleKind.AMD || moduleKind === ModuleKind.UMD || moduleKind === ModuleKind.System) { - createDiagnosticForOptionName(Diagnostics.Option_verbatimModuleSyntax_cannot_be_used_when_module_is_set_to_UMD_AMD_or_System, "verbatimModuleSyntax"); + createDiagnosticForOptionName( + Diagnostics.Option_verbatimModuleSyntax_cannot_be_used_when_module_is_set_to_UMD_AMD_or_System, + "verbatimModuleSyntax", + ); } if (options.preserveValueImports) { createRedundantOptionDiagnostic("preserveValueImports", "verbatimModuleSyntax"); @@ -4413,39 +5550,70 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg } if (options.allowImportingTsExtensions && !(options.noEmit || options.emitDeclarationOnly)) { - createOptionValueDiagnostic("allowImportingTsExtensions", Diagnostics.Option_allowImportingTsExtensions_can_only_be_used_when_either_noEmit_or_emitDeclarationOnly_is_set); + createOptionValueDiagnostic( + "allowImportingTsExtensions", + Diagnostics + .Option_allowImportingTsExtensions_can_only_be_used_when_either_noEmit_or_emitDeclarationOnly_is_set, + ); } const moduleResolution = getEmitModuleResolutionKind(options); - if (options.resolvePackageJsonExports && !moduleResolutionSupportsPackageJsonExportsAndImports(moduleResolution)) { - createDiagnosticForOptionName(Diagnostics.Option_0_can_only_be_used_when_moduleResolution_is_set_to_node16_nodenext_or_bundler, "resolvePackageJsonExports"); + if ( + options.resolvePackageJsonExports && !moduleResolutionSupportsPackageJsonExportsAndImports(moduleResolution) + ) { + createDiagnosticForOptionName( + Diagnostics.Option_0_can_only_be_used_when_moduleResolution_is_set_to_node16_nodenext_or_bundler, + "resolvePackageJsonExports", + ); } - if (options.resolvePackageJsonImports && !moduleResolutionSupportsPackageJsonExportsAndImports(moduleResolution)) { - createDiagnosticForOptionName(Diagnostics.Option_0_can_only_be_used_when_moduleResolution_is_set_to_node16_nodenext_or_bundler, "resolvePackageJsonImports"); + if ( + options.resolvePackageJsonImports && !moduleResolutionSupportsPackageJsonExportsAndImports(moduleResolution) + ) { + createDiagnosticForOptionName( + Diagnostics.Option_0_can_only_be_used_when_moduleResolution_is_set_to_node16_nodenext_or_bundler, + "resolvePackageJsonImports", + ); } if (options.customConditions && !moduleResolutionSupportsPackageJsonExportsAndImports(moduleResolution)) { - createDiagnosticForOptionName(Diagnostics.Option_0_can_only_be_used_when_moduleResolution_is_set_to_node16_nodenext_or_bundler, "customConditions"); + createDiagnosticForOptionName( + Diagnostics.Option_0_can_only_be_used_when_moduleResolution_is_set_to_node16_nodenext_or_bundler, + "customConditions", + ); } if (moduleResolution === ModuleResolutionKind.Bundler && !emitModuleKindIsNonNodeESM(moduleKind)) { - createOptionValueDiagnostic("moduleResolution", Diagnostics.Option_0_can_only_be_used_when_module_is_set_to_es2015_or_later, "bundler"); + createOptionValueDiagnostic( + "moduleResolution", + Diagnostics.Option_0_can_only_be_used_when_module_is_set_to_es2015_or_later, + "bundler", + ); } if ( - ModuleKind[moduleKind] && - (ModuleKind.Node16 <= moduleKind && moduleKind <= ModuleKind.NodeNext) && - !(ModuleResolutionKind.Node16 <= moduleResolution && moduleResolution <= ModuleResolutionKind.NodeNext) + ModuleKind[moduleKind] + && (ModuleKind.Node16 <= moduleKind && moduleKind <= ModuleKind.NodeNext) + && !(ModuleResolutionKind.Node16 <= moduleResolution && moduleResolution <= ModuleResolutionKind.NodeNext) ) { const moduleKindName = ModuleKind[moduleKind]; - createOptionValueDiagnostic("moduleResolution", Diagnostics.Option_moduleResolution_must_be_set_to_0_or_left_unspecified_when_option_module_is_set_to_1, moduleKindName, moduleKindName); + createOptionValueDiagnostic( + "moduleResolution", + Diagnostics.Option_moduleResolution_must_be_set_to_0_or_left_unspecified_when_option_module_is_set_to_1, + moduleKindName, + moduleKindName, + ); } else if ( - ModuleResolutionKind[moduleResolution] && - (ModuleResolutionKind.Node16 <= moduleResolution && moduleResolution <= ModuleResolutionKind.NodeNext) && - !(ModuleKind.Node16 <= moduleKind && moduleKind <= ModuleKind.NodeNext) + ModuleResolutionKind[moduleResolution] + && (ModuleResolutionKind.Node16 <= moduleResolution && moduleResolution <= ModuleResolutionKind.NodeNext) + && !(ModuleKind.Node16 <= moduleKind && moduleKind <= ModuleKind.NodeNext) ) { const moduleResolutionName = ModuleResolutionKind[moduleResolution]; - createOptionValueDiagnostic("module", Diagnostics.Option_module_must_be_set_to_0_when_option_moduleResolution_is_set_to_1, moduleResolutionName, moduleResolutionName); + createOptionValueDiagnostic( + "module", + Diagnostics.Option_module_must_be_set_to_0_when_option_moduleResolution_is_set_to_1, + moduleResolutionName, + moduleResolutionName, + ); } // If the emit is enabled make sure that every output file is unique and not overwriting any of the input files @@ -4469,17 +5637,32 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg let chain: DiagnosticMessageChain | undefined; if (!options.configFilePath) { // The program is from either an inferred project or an external project - chain = chainDiagnosticMessages(/*details*/ undefined, Diagnostics.Adding_a_tsconfig_json_file_will_help_organize_projects_that_contain_both_TypeScript_and_JavaScript_files_Learn_more_at_https_Colon_Slash_Slashaka_ms_Slashtsconfig); + chain = chainDiagnosticMessages( + /*details*/ undefined, + Diagnostics + .Adding_a_tsconfig_json_file_will_help_organize_projects_that_contain_both_TypeScript_and_JavaScript_files_Learn_more_at_https_Colon_Slash_Slashaka_ms_Slashtsconfig, + ); } - chain = chainDiagnosticMessages(chain, Diagnostics.Cannot_write_file_0_because_it_would_overwrite_input_file, emitFileName); + chain = chainDiagnosticMessages( + chain, + Diagnostics.Cannot_write_file_0_because_it_would_overwrite_input_file, + emitFileName, + ); blockEmittingOfFile(emitFileName, createCompilerDiagnosticFromMessageChain(chain)); } - const emitFileKey = !host.useCaseSensitiveFileNames() ? toFileNameLowerCase(emitFilePath) : emitFilePath; + const emitFileKey = !host.useCaseSensitiveFileNames() ? toFileNameLowerCase(emitFilePath) + : emitFilePath; // Report error if multiple files write into same file if (emitFilesSeen.has(emitFileKey)) { // Already seen the same emit file - report error - blockEmittingOfFile(emitFileName, createCompilerDiagnostic(Diagnostics.Cannot_write_file_0_because_it_would_be_overwritten_by_multiple_input_files, emitFileName)); + blockEmittingOfFile( + emitFileName, + createCompilerDiagnostic( + Diagnostics.Cannot_write_file_0_because_it_would_be_overwritten_by_multiple_input_files, + emitFileName, + ), + ); } else { emitFilesSeen.add(emitFileKey); @@ -4505,7 +5688,13 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg function checkDeprecations( deprecatedIn: string, removedIn: string, - createDiagnostic: (name: string, value: string | undefined, useInstead: string | undefined, message: DiagnosticMessage, ...args: DiagnosticArguments) => void, + createDiagnostic: ( + name: string, + value: string | undefined, + useInstead: string | undefined, + message: DiagnosticMessage, + ...args: DiagnosticArguments + ) => void, fn: (createDeprecatedDiagnostic: (name: string, value?: string, useInstead?: string) => void) => void, ) { const deprecatedInVersion = new Version(deprecatedIn); @@ -4514,24 +5703,57 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg const ignoreDeprecationsVersion = getIgnoreDeprecationsVersion(); const mustBeRemoved = !(removedInVersion.compareTo(typescriptVersion) === Comparison.GreaterThan); - const canBeSilenced = !mustBeRemoved && ignoreDeprecationsVersion.compareTo(deprecatedInVersion) === Comparison.LessThan; + const canBeSilenced = !mustBeRemoved + && ignoreDeprecationsVersion.compareTo(deprecatedInVersion) === Comparison.LessThan; if (mustBeRemoved || canBeSilenced) { fn((name, value, useInstead) => { if (mustBeRemoved) { if (value === undefined) { - createDiagnostic(name, value, useInstead, Diagnostics.Option_0_has_been_removed_Please_remove_it_from_your_configuration, name); + createDiagnostic( + name, + value, + useInstead, + Diagnostics.Option_0_has_been_removed_Please_remove_it_from_your_configuration, + name, + ); } else { - createDiagnostic(name, value, useInstead, Diagnostics.Option_0_1_has_been_removed_Please_remove_it_from_your_configuration, name, value); + createDiagnostic( + name, + value, + useInstead, + Diagnostics.Option_0_1_has_been_removed_Please_remove_it_from_your_configuration, + name, + value, + ); } } else { if (value === undefined) { - createDiagnostic(name, value, useInstead, Diagnostics.Option_0_is_deprecated_and_will_stop_functioning_in_TypeScript_1_Specify_compilerOption_ignoreDeprecations_Colon_2_to_silence_this_error, name, removedIn, deprecatedIn); + createDiagnostic( + name, + value, + useInstead, + Diagnostics + .Option_0_is_deprecated_and_will_stop_functioning_in_TypeScript_1_Specify_compilerOption_ignoreDeprecations_Colon_2_to_silence_this_error, + name, + removedIn, + deprecatedIn, + ); } else { - createDiagnostic(name, value, useInstead, Diagnostics.Option_0_1_is_deprecated_and_will_stop_functioning_in_TypeScript_2_Specify_compilerOption_ignoreDeprecations_Colon_3_to_silence_this_error, name, value, removedIn, deprecatedIn); + createDiagnostic( + name, + value, + useInstead, + Diagnostics + .Option_0_1_is_deprecated_and_will_stop_functioning_in_TypeScript_2_Specify_compilerOption_ignoreDeprecations_Colon_3_to_silence_this_error, + name, + value, + removedIn, + deprecatedIn, + ); } } }); @@ -4539,7 +5761,13 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg } function verifyDeprecatedCompilerOptions() { - function createDiagnostic(name: string, value: string | undefined, useInstead: string | undefined, message: DiagnosticMessage, ...args: DiagnosticArguments) { + function createDiagnostic( + name: string, + value: string | undefined, + useInstead: string | undefined, + message: DiagnosticMessage, + ...args: DiagnosticArguments + ) { if (useInstead) { const details = chainDiagnosticMessages(/*details*/ undefined, Diagnostics.Use_0_instead, useInstead); const chain = chainDiagnosticMessages(details, message, ...args); @@ -4584,8 +5812,18 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg }); } - function verifyDeprecatedProjectReference(ref: ProjectReference, parentFile: JsonSourceFile | undefined, index: number) { - function createDiagnostic(_name: string, _value: string | undefined, _useInstead: string | undefined, message: DiagnosticMessage, ...args: DiagnosticArguments) { + function verifyDeprecatedProjectReference( + ref: ProjectReference, + parentFile: JsonSourceFile | undefined, + index: number, + ) { + function createDiagnostic( + _name: string, + _value: string | undefined, + _useInstead: string | undefined, + message: DiagnosticMessage, + ...args: DiagnosticArguments + ) { createDiagnosticForReference(parentFile, index, message, ...args); } @@ -4596,7 +5834,12 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg }); } - function createDiagnosticExplainingFile(file: SourceFile | undefined, fileProcessingReason: FileIncludeReason | undefined, diagnostic: DiagnosticMessage, args: DiagnosticArguments | undefined): Diagnostic { + function createDiagnosticExplainingFile( + file: SourceFile | undefined, + fileProcessingReason: FileIncludeReason | undefined, + diagnostic: DiagnosticMessage, + args: DiagnosticArguments | undefined, + ): Diagnostic { let fileIncludeReasons: DiagnosticMessageChain[] | undefined; let relatedInfo: Diagnostic[] | undefined; let locationReason = isReferencedFile(fileProcessingReason) ? fileProcessingReason : undefined; @@ -4605,12 +5848,24 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg // If we have location and there is only one reason file is in which is the location, dont add details for file include if (locationReason && fileIncludeReasons?.length === 1) fileIncludeReasons = undefined; const location = locationReason && getReferencedFileLocation(getSourceFileByPath, locationReason); - const fileIncludeReasonDetails = fileIncludeReasons && chainDiagnosticMessages(fileIncludeReasons, Diagnostics.The_file_is_in_the_program_because_Colon); + const fileIncludeReasonDetails = fileIncludeReasons + && chainDiagnosticMessages(fileIncludeReasons, Diagnostics.The_file_is_in_the_program_because_Colon); const redirectInfo = file && explainIfFileIsRedirectAndImpliedFormat(file); - const chain = chainDiagnosticMessages(redirectInfo ? fileIncludeReasonDetails ? [fileIncludeReasonDetails, ...redirectInfo] : redirectInfo : fileIncludeReasonDetails, diagnostic, ...args || emptyArray); - return location && isReferenceFileLocation(location) ? - createFileDiagnosticFromMessageChain(location.file, location.pos, location.end - location.pos, chain, relatedInfo) : - createCompilerDiagnosticFromMessageChain(chain, relatedInfo); + const chain = chainDiagnosticMessages( + redirectInfo ? fileIncludeReasonDetails ? [fileIncludeReasonDetails, ...redirectInfo] : redirectInfo + : fileIncludeReasonDetails, + diagnostic, + ...args || emptyArray, + ); + return location && isReferenceFileLocation(location) + ? createFileDiagnosticFromMessageChain( + location.file, + location.pos, + location.end - location.pos, + chain, + relatedInfo, + ) + : createCompilerDiagnosticFromMessageChain(chain, relatedInfo); function processReason(reason: FileIncludeReason) { (fileIncludeReasons ||= []).push(fileIncludeReasonToDiagnostics(program, reason)); @@ -4626,7 +5881,12 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg } } - function addFilePreprocessingFileExplainingDiagnostic(file: SourceFile | undefined, fileProcessingReason: FileIncludeReason, diagnostic: DiagnosticMessage, args?: DiagnosticArguments) { + function addFilePreprocessingFileExplainingDiagnostic( + file: SourceFile | undefined, + fileProcessingReason: FileIncludeReason, + diagnostic: DiagnosticMessage, + args?: DiagnosticArguments, + ) { (fileProcessingDiagnostics ||= []).push({ kind: FilePreprocessingDiagnosticsKind.FilePreprocessingFileExplainingDiagnostic, file: file && file.path, @@ -4636,8 +5896,14 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg }); } - function addProgramDiagnosticExplainingFile(file: SourceFile, diagnostic: DiagnosticMessage, args?: DiagnosticArguments) { - programDiagnostics.add(createDiagnosticExplainingFile(file, /*fileProcessingReason*/ undefined, diagnostic, args)); + function addProgramDiagnosticExplainingFile( + file: SourceFile, + diagnostic: DiagnosticMessage, + args?: DiagnosticArguments, + ) { + programDiagnostics.add( + createDiagnosticExplainingFile(file, /*fileProcessingReason*/ undefined, diagnostic, args), + ); } function fileIncludeReasonToRelatedInformation(reason: FileIncludeReason): DiagnosticWithLocation | undefined { @@ -4690,19 +5956,29 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg case FileIncludeKind.SourceFromProjectReference: case FileIncludeKind.OutputFromProjectReference: const referencedResolvedRef = Debug.checkDefined(resolvedProjectReferences?.[reason.index]); - const referenceInfo = forEachProjectReference(projectReferences, resolvedProjectReferences, (resolvedRef, parent, index) => resolvedRef === referencedResolvedRef ? { sourceFile: parent?.sourceFile || options.configFile!, index } : undefined); + const referenceInfo = forEachProjectReference( + projectReferences, + resolvedProjectReferences, + (resolvedRef, parent, index) => + resolvedRef === referencedResolvedRef + ? { sourceFile: parent?.sourceFile || options.configFile!, index } : undefined, + ); if (!referenceInfo) return undefined; const { sourceFile, index } = referenceInfo; - const referencesSyntax = forEachTsConfigPropArray(sourceFile as TsConfigSourceFile, "references", property => isArrayLiteralExpression(property.initializer) ? property.initializer : undefined); - return referencesSyntax && referencesSyntax.elements.length > index ? - createDiagnosticForNodeInSourceFile( + const referencesSyntax = forEachTsConfigPropArray( + sourceFile as TsConfigSourceFile, + "references", + property => isArrayLiteralExpression(property.initializer) ? property.initializer : undefined, + ); + return referencesSyntax && referencesSyntax.elements.length > index + ? createDiagnosticForNodeInSourceFile( sourceFile, referencesSyntax.elements[index], - reason.kind === FileIncludeKind.OutputFromProjectReference ? - Diagnostics.File_is_output_from_referenced_project_specified_here : - Diagnostics.File_is_source_from_referenced_project_specified_here, - ) : - undefined; + reason.kind === FileIncludeKind.OutputFromProjectReference + ? Diagnostics.File_is_output_from_referenced_project_specified_here + : Diagnostics.File_is_source_from_referenced_project_specified_here, + ) + : undefined; case FileIncludeKind.AutomaticTypeDirectiveFile: if (!options.types) return undefined; configFileNode = getOptionsSyntaxByArrayElementValue("types", reason.typeReference); @@ -4714,7 +5990,10 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg message = Diagnostics.File_is_library_specified_here; break; } - const target = forEachEntry(targetOptionDeclaration.type, (value, key) => value === getEmitScriptTarget(options) ? key : undefined); + const target = forEachEntry( + targetOptionDeclaration.type, + (value, key) => value === getEmitScriptTarget(options) ? key : undefined, + ); configFileNode = target ? getOptionsSyntaxByValue("target", target) : undefined; message = Diagnostics.File_is_default_library_for_target_specified_here; break; @@ -4743,36 +6022,80 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg // ok to not have composite if the current program is container only const inputs = parent ? parent.commandLine.fileNames : rootNames; if (inputs.length) { - if (!options.composite) createDiagnosticForReference(parentFile, index, Diagnostics.Referenced_project_0_must_have_setting_composite_Colon_true, ref.path); - if (options.noEmit) createDiagnosticForReference(parentFile, index, Diagnostics.Referenced_project_0_may_not_disable_emit, ref.path); + if (!options.composite) { + createDiagnosticForReference( + parentFile, + index, + Diagnostics.Referenced_project_0_must_have_setting_composite_Colon_true, + ref.path, + ); + } + if (options.noEmit) { + createDiagnosticForReference( + parentFile, + index, + Diagnostics.Referenced_project_0_may_not_disable_emit, + ref.path, + ); + } } } if (ref.prepend) { const out = outFile(options); if (out) { if (!host.fileExists(out)) { - createDiagnosticForReference(parentFile, index, Diagnostics.Output_file_0_from_project_1_does_not_exist, out, ref.path); + createDiagnosticForReference( + parentFile, + index, + Diagnostics.Output_file_0_from_project_1_does_not_exist, + out, + ref.path, + ); } } else { - createDiagnosticForReference(parentFile, index, Diagnostics.Cannot_prepend_project_0_because_it_does_not_have_outFile_set, ref.path); + createDiagnosticForReference( + parentFile, + index, + Diagnostics.Cannot_prepend_project_0_because_it_does_not_have_outFile_set, + ref.path, + ); } } if (!parent && buildInfoPath && buildInfoPath === getTsBuildInfoEmitOutputFilePath(options)) { - createDiagnosticForReference(parentFile, index, Diagnostics.Cannot_write_file_0_because_it_will_overwrite_tsbuildinfo_file_generated_by_referenced_project_1, buildInfoPath, ref.path); + createDiagnosticForReference( + parentFile, + index, + Diagnostics + .Cannot_write_file_0_because_it_will_overwrite_tsbuildinfo_file_generated_by_referenced_project_1, + buildInfoPath, + ref.path, + ); hasEmitBlockingDiagnostics.set(toPath(buildInfoPath), true); } }); } - function createDiagnosticForOptionPathKeyValue(key: string, valueIndex: number, message: DiagnosticMessage, ...args: DiagnosticArguments) { + function createDiagnosticForOptionPathKeyValue( + key: string, + valueIndex: number, + message: DiagnosticMessage, + ...args: DiagnosticArguments + ) { let needCompilerDiagnostic = true; forEachOptionPathsSyntax(pathProp => { if (isObjectLiteralExpression(pathProp.initializer)) { forEachPropertyAssignment(pathProp.initializer, key, keyProps => { const initializer = keyProps.initializer; if (isArrayLiteralExpression(initializer) && initializer.elements.length > valueIndex) { - programDiagnostics.add(createDiagnosticForNodeInSourceFile(options.configFile!, initializer.elements[valueIndex], message, ...args)); + programDiagnostics.add( + createDiagnosticForNodeInSourceFile( + options.configFile!, + initializer.elements[valueIndex], + message, + ...args, + ), + ); needCompilerDiagnostic = false; } }); @@ -4783,12 +6106,17 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg } } - function createDiagnosticForOptionPaths(onKey: boolean, key: string, message: DiagnosticMessage, ...args: DiagnosticArguments) { + function createDiagnosticForOptionPaths( + onKey: boolean, + key: string, + message: DiagnosticMessage, + ...args: DiagnosticArguments + ) { let needCompilerDiagnostic = true; forEachOptionPathsSyntax(pathProp => { if ( - isObjectLiteralExpression(pathProp.initializer) && - createOptionDiagnosticInObjectLiteralSyntax( + isObjectLiteralExpression(pathProp.initializer) + && createOptionDiagnosticInObjectLiteralSyntax( pathProp.initializer, onKey, key, @@ -4805,7 +6133,10 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg } } - function forEachOptionsSyntaxByName(name: string, callback: (prop: PropertyAssignment) => T | undefined): T | undefined { + function forEachOptionsSyntaxByName( + name: string, + callback: (prop: PropertyAssignment) => T | undefined, + ): T | undefined { return forEachPropertyAssignment(getCompilerOptionsObjectLiteralSyntax(), name, callback); } @@ -4814,15 +6145,26 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg } function getOptionsSyntaxByValue(name: string, value: string) { - return forEachOptionsSyntaxByName(name, property => isStringLiteral(property.initializer) && property.initializer.text === value ? property.initializer : undefined); + return forEachOptionsSyntaxByName( + name, + property => + isStringLiteral(property.initializer) && property.initializer.text === value ? property.initializer + : undefined, + ); } function getOptionsSyntaxByArrayElementValue(name: string, value: string) { const compilerOptionsObjectLiteralSyntax = getCompilerOptionsObjectLiteralSyntax(); - return compilerOptionsObjectLiteralSyntax && getPropertyArrayElementValue(compilerOptionsObjectLiteralSyntax, name, value); + return compilerOptionsObjectLiteralSyntax + && getPropertyArrayElementValue(compilerOptionsObjectLiteralSyntax, name, value); } - function createDiagnosticForOptionName(message: DiagnosticMessage, option1: string, option2?: string, option3?: string) { + function createDiagnosticForOptionName( + message: DiagnosticMessage, + option1: string, + option2?: string, + option3?: string, + ) { // TODO(jakebailey): this code makes assumptions about the format of the diagnostic messages. createDiagnosticForOption(/*onKey*/ true, option1, option2, message, option1, option2!, option3!); } @@ -4831,22 +6173,62 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg createDiagnosticForOption(/*onKey*/ false, option1, /*option2*/ undefined, message, ...args); } - function createDiagnosticForReference(sourceFile: JsonSourceFile | undefined, index: number, message: DiagnosticMessage, ...args: DiagnosticArguments) { - const referencesSyntax = forEachTsConfigPropArray(sourceFile || options.configFile, "references", property => isArrayLiteralExpression(property.initializer) ? property.initializer : undefined); + function createDiagnosticForReference( + sourceFile: JsonSourceFile | undefined, + index: number, + message: DiagnosticMessage, + ...args: DiagnosticArguments + ) { + const referencesSyntax = forEachTsConfigPropArray( + sourceFile || options.configFile, + "references", + property => isArrayLiteralExpression(property.initializer) ? property.initializer : undefined, + ); if (referencesSyntax && referencesSyntax.elements.length > index) { - programDiagnostics.add(createDiagnosticForNodeInSourceFile(sourceFile || options.configFile!, referencesSyntax.elements[index], message, ...args)); + programDiagnostics.add( + createDiagnosticForNodeInSourceFile( + sourceFile || options.configFile!, + referencesSyntax.elements[index], + message, + ...args, + ), + ); } else { programDiagnostics.add(createCompilerDiagnostic(message, ...args)); } } - function createDiagnosticForOption(onKey: boolean, option1: string, option2: string | undefined, message: DiagnosticMessageChain): void; - function createDiagnosticForOption(onKey: boolean, option1: string, option2: string | undefined, message: DiagnosticMessage, ...args: DiagnosticArguments): void; - function createDiagnosticForOption(onKey: boolean, option1: string, option2: string | undefined, message: DiagnosticMessage | DiagnosticMessageChain, ...args: DiagnosticArguments): void { + function createDiagnosticForOption( + onKey: boolean, + option1: string, + option2: string | undefined, + message: DiagnosticMessageChain, + ): void; + function createDiagnosticForOption( + onKey: boolean, + option1: string, + option2: string | undefined, + message: DiagnosticMessage, + ...args: DiagnosticArguments + ): void; + function createDiagnosticForOption( + onKey: boolean, + option1: string, + option2: string | undefined, + message: DiagnosticMessage | DiagnosticMessageChain, + ...args: DiagnosticArguments + ): void { const compilerOptionsObjectLiteralSyntax = getCompilerOptionsObjectLiteralSyntax(); - const needCompilerDiagnostic = !compilerOptionsObjectLiteralSyntax || - !createOptionDiagnosticInObjectLiteralSyntax(compilerOptionsObjectLiteralSyntax, onKey, option1, option2, message, ...args); + const needCompilerDiagnostic = !compilerOptionsObjectLiteralSyntax + || !createOptionDiagnosticInObjectLiteralSyntax( + compilerOptionsObjectLiteralSyntax, + onKey, + option1, + option2, + message, + ...args, + ); if (needCompilerDiagnostic) { // eslint-disable-next-line local/no-in-operator @@ -4870,18 +6252,58 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg return _compilerOptionsObjectLiteralSyntax || undefined; } - function createOptionDiagnosticInObjectLiteralSyntax(objectLiteral: ObjectLiteralExpression, onKey: boolean, key1: string, key2: string | undefined, messageChain: DiagnosticMessageChain): boolean; - function createOptionDiagnosticInObjectLiteralSyntax(objectLiteral: ObjectLiteralExpression, onKey: boolean, key1: string, key2: string | undefined, message: DiagnosticMessage, ...args: DiagnosticArguments): boolean; - function createOptionDiagnosticInObjectLiteralSyntax(objectLiteral: ObjectLiteralExpression, onKey: boolean, key1: string, key2: string | undefined, message: DiagnosticMessage | DiagnosticMessageChain, ...args: DiagnosticArguments): boolean; - function createOptionDiagnosticInObjectLiteralSyntax(objectLiteral: ObjectLiteralExpression, onKey: boolean, key1: string, key2: string | undefined, message: DiagnosticMessage | DiagnosticMessageChain, ...args: DiagnosticArguments): boolean { + function createOptionDiagnosticInObjectLiteralSyntax( + objectLiteral: ObjectLiteralExpression, + onKey: boolean, + key1: string, + key2: string | undefined, + messageChain: DiagnosticMessageChain, + ): boolean; + function createOptionDiagnosticInObjectLiteralSyntax( + objectLiteral: ObjectLiteralExpression, + onKey: boolean, + key1: string, + key2: string | undefined, + message: DiagnosticMessage, + ...args: DiagnosticArguments + ): boolean; + function createOptionDiagnosticInObjectLiteralSyntax( + objectLiteral: ObjectLiteralExpression, + onKey: boolean, + key1: string, + key2: string | undefined, + message: DiagnosticMessage | DiagnosticMessageChain, + ...args: DiagnosticArguments + ): boolean; + function createOptionDiagnosticInObjectLiteralSyntax( + objectLiteral: ObjectLiteralExpression, + onKey: boolean, + key1: string, + key2: string | undefined, + message: DiagnosticMessage | DiagnosticMessageChain, + ...args: DiagnosticArguments + ): boolean { let needsCompilerDiagnostic = false; forEachPropertyAssignment(objectLiteral, key1, prop => { // eslint-disable-next-line local/no-in-operator if ("messageText" in message) { - programDiagnostics.add(createDiagnosticForNodeFromMessageChain(options.configFile!, onKey ? prop.name : prop.initializer, message)); + programDiagnostics.add( + createDiagnosticForNodeFromMessageChain( + options.configFile!, + onKey ? prop.name : prop.initializer, + message, + ), + ); } else { - programDiagnostics.add(createDiagnosticForNodeInSourceFile(options.configFile!, onKey ? prop.name : prop.initializer, message, ...args)); + programDiagnostics.add( + createDiagnosticForNodeInSourceFile( + options.configFile!, + onKey ? prop.name : prop.initializer, + message, + ...args, + ), + ); } needsCompilerDiagnostic = true; }, key2); @@ -4900,11 +6322,23 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg const compilerOptionsObjectLiteralSyntax = getCompilerOptionsObjectLiteralSyntax(); if (compilerOptionsObjectLiteralSyntax) { // This is a no-op if `errorOnOption` isn't present in the leaf config file. - createOptionDiagnosticInObjectLiteralSyntax(compilerOptionsObjectLiteralSyntax, /*onKey*/ true, errorOnOption, /*key2*/ undefined, Diagnostics.Option_0_is_redundant_and_cannot_be_specified_with_option_1, errorOnOption, redundantWithOption); + createOptionDiagnosticInObjectLiteralSyntax( + compilerOptionsObjectLiteralSyntax, + /*onKey*/ true, + errorOnOption, + /*key2*/ undefined, + Diagnostics.Option_0_is_redundant_and_cannot_be_specified_with_option_1, + errorOnOption, + redundantWithOption, + ); } else { // There was no config file, so both options were specified on the command line. - createDiagnosticForOptionName(Diagnostics.Option_0_is_redundant_and_cannot_be_specified_with_option_1, errorOnOption, redundantWithOption); + createDiagnosticForOptionName( + Diagnostics.Option_0_is_redundant_and_cannot_be_specified_with_option_1, + errorOnOption, + redundantWithOption, + ); } } @@ -4931,7 +6365,10 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg } // If declarationDir is specified, return if its a file in that directory - if (options.declarationDir && containsPath(options.declarationDir, filePath, currentDirectory, !host.useCaseSensitiveFileNames())) { + if ( + options.declarationDir + && containsPath(options.declarationDir, filePath, currentDirectory, !host.useCaseSensitiveFileNames()) + ) { return true; } @@ -4943,8 +6380,8 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg if (fileExtensionIsOneOf(filePath, supportedJSExtensionsFlat) || isDeclarationFileName(filePath)) { // Otherwise just check if sourceFile with the name exists const filePathWithoutExtension = removeFileExtension(filePath); - return !!getSourceFileByPath((filePathWithoutExtension + Extension.Ts) as Path) || - !!getSourceFileByPath((filePathWithoutExtension + Extension.Tsx) as Path); + return !!getSourceFileByPath((filePathWithoutExtension + Extension.Ts) as Path) + || !!getSourceFileByPath((filePathWithoutExtension + Extension.Tsx) as Path); } return false; } @@ -4974,7 +6411,9 @@ interface HostForUseSourceOfProjectReferenceRedirect { toPath(fileName: string): Path; getResolvedProjectReferences(): readonly (ResolvedProjectReference | undefined)[] | undefined; getSourceOfProjectReferenceRedirect(path: Path): SourceOfProjectReferenceRedirect | undefined; - forEachResolvedProjectReference(cb: (resolvedProjectReference: ResolvedProjectReference) => T | undefined): T | undefined; + forEachResolvedProjectReference( + cb: (resolvedProjectReference: ResolvedProjectReference) => T | undefined, + ): T | undefined; } function updateHostForUseSourceOfProjectReferenceRedirect(host: HostForUseSourceOfProjectReferenceRedirect) { @@ -5026,16 +6465,17 @@ function updateHostForUseSourceOfProjectReferenceRedirect(host: HostForUseSource // Call getDirectories only if directory actually present on the host // This is needed to ensure that we arent getting directories that we fake about presence for host.compilerHost.getDirectories = path => - !host.getResolvedProjectReferences() || (originalDirectoryExists && originalDirectoryExists.call(host.compilerHost, path)) ? - originalGetDirectories.call(host.compilerHost, path) : - []; + !host.getResolvedProjectReferences() + || (originalDirectoryExists && originalDirectoryExists.call(host.compilerHost, path)) + ? originalGetDirectories.call(host.compilerHost, path) + : []; } // This is something we keep for life time of the host if (originalRealpath) { host.compilerHost.realpath = s => - host.getSymlinkCache().getSymlinkedFiles()?.get(host.toPath(s)) || - originalRealpath.call(host.compilerHost, s); + host.getSymlinkCache().getSymlinkedFiles()?.get(host.toPath(s)) + || originalRealpath.call(host.compilerHost, s); } return { onProgramCreateComplete, fileExists, directoryExists }; @@ -5061,9 +6501,9 @@ function updateHostForUseSourceOfProjectReferenceRedirect(host: HostForUseSource function fileExistsIfProjectReferenceDts(file: string) { const source = host.getSourceOfProjectReferenceRedirect(host.toPath(file)); - return source !== undefined ? - isString(source) ? originalFileExists.call(host.compilerHost, source) as boolean : true : - undefined; + return source !== undefined + ? isString(source) ? originalFileExists.call(host.compilerHost, source) as boolean : true + : undefined; } function directoryExistsIfProjectReferenceDeclDir(dir: string) { @@ -5072,11 +6512,11 @@ function updateHostForUseSourceOfProjectReferenceRedirect(host: HostForUseSource return forEachKey( setOfDeclarationDirectories!, declDirPath => - dirPath === declDirPath || + dirPath === declDirPath // Any parent directory of declaration dir - startsWith(declDirPath, dirPathWithTrailingDirectorySeparator) || + || startsWith(declDirPath, dirPathWithTrailingDirectorySeparator) // Any directory inside declaration dir - startsWith(dirPath, `${declDirPath}/`), + || startsWith(dirPath, `${declDirPath}/`), ); } @@ -5092,8 +6532,8 @@ function updateHostForUseSourceOfProjectReferenceRedirect(host: HostForUseSource const real = normalizePath(originalRealpath.call(host.compilerHost, directory)); let realPath: Path; if ( - real === directory || - (realPath = ensureTrailingDirectorySeparator(host.toPath(real))) === directoryPath + real === directory + || (realPath = ensureTrailingDirectorySeparator(host.toPath(real))) === directoryPath ) { // not symlinked symlinkCache.setSymlinkedDirectory(directoryPath, false); @@ -5107,9 +6547,9 @@ function updateHostForUseSourceOfProjectReferenceRedirect(host: HostForUseSource } function fileOrDirectoryExistsUsingSource(fileOrDirectory: string, isFile: boolean): boolean { - const fileOrDirectoryExistsUsingSource = isFile ? - (file: string) => fileExistsIfProjectReferenceDts(file) : - (dir: string) => directoryExistsIfProjectReferenceDeclDir(dir); + const fileOrDirectoryExistsUsingSource = isFile + ? (file: string) => fileExistsIfProjectReferenceDts(file) + : (dir: string) => directoryExistsIfProjectReferenceDeclDir(dir); // Check current directory or file const result = fileOrDirectoryExistsUsingSource(fileOrDirectory); if (result !== undefined) return result; @@ -5126,10 +6566,15 @@ function updateHostForUseSourceOfProjectReferenceRedirect(host: HostForUseSource symlinkedDirectories.entries(), ([directoryPath, symlinkedDirectory]) => { if (!symlinkedDirectory || !startsWith(fileOrDirectoryPath, directoryPath)) return undefined; - const result = fileOrDirectoryExistsUsingSource(fileOrDirectoryPath.replace(directoryPath, symlinkedDirectory.realPath)); + const result = fileOrDirectoryExistsUsingSource( + fileOrDirectoryPath.replace(directoryPath, symlinkedDirectory.realPath), + ); if (isFile && result) { // Store the real path for the file' - const absolutePath = getNormalizedAbsolutePath(fileOrDirectory, host.compilerHost.getCurrentDirectory()); + const absolutePath = getNormalizedAbsolutePath( + fileOrDirectory, + host.compilerHost.getCurrentDirectory(), + ); symlinkCache.setSymlinkedFile( fileOrDirectoryPath, `${symlinkedDirectory.real}${absolutePath.replace(new RegExp(directoryPath, "i"), "")}`, @@ -5142,7 +6587,12 @@ function updateHostForUseSourceOfProjectReferenceRedirect(host: HostForUseSource } /** @internal */ -export const emitSkippedWithNoDiagnostics: EmitResult = { diagnostics: emptyArray, sourceMaps: undefined, emittedFiles: undefined, emitSkipped: true }; +export const emitSkippedWithNoDiagnostics: EmitResult = { + diagnostics: emptyArray, + sourceMaps: undefined, + emittedFiles: undefined, + emitSkipped: true, +}; /** @internal */ export function handleNoEmitOptions( @@ -5155,9 +6605,9 @@ export function handleNoEmitOptions( if (options.noEmit) { // Cache the semantic diagnostics program.getSemanticDiagnostics(sourceFile, cancellationToken); - return sourceFile || outFile(options) ? - emitSkippedWithNoDiagnostics : - program.emitBuildInfo(writeFile, cancellationToken); + return sourceFile || outFile(options) + ? emitSkippedWithNoDiagnostics + : program.emitBuildInfo(writeFile, cancellationToken); } // If the noEmitOnError flag is set, then check if we have any errors so far. If so, @@ -5186,7 +6636,10 @@ export function handleNoEmitOptions( } /** @internal */ -export function filterSemanticDiagnostics(diagnostic: readonly Diagnostic[], option: CompilerOptions): readonly Diagnostic[] { +export function filterSemanticDiagnostics( + diagnostic: readonly Diagnostic[], + option: CompilerOptions, +): readonly Diagnostic[] { return filter(diagnostic, d => !d.skippedOn || !option[d.skippedOn]); } @@ -5198,7 +6651,10 @@ export function parseConfigHostFromCompilerHostLike( return { fileExists: f => directoryStructureHost.fileExists(f), readDirectory(root, extensions, excludes, includes, depth) { - Debug.assertIsDefined(directoryStructureHost.readDirectory, "'CompilerHost.readDirectory' must be implemented to correctly process 'projectReferences'"); + Debug.assertIsDefined( + directoryStructureHost.readDirectory, + "'CompilerHost.readDirectory' must be implemented to correctly process 'projectReferences'", + ); return directoryStructureHost.readDirectory(root, extensions, excludes, includes, depth); }, readFile: f => directoryStructureHost.readFile(f), @@ -5229,8 +6685,18 @@ export function createPrependNodes( // Upstream project didn't have outFile set -- skip (error will have been issued earlier) if (!out) continue; - const { jsFilePath, sourceMapFilePath, declarationFilePath, declarationMapPath, buildInfoPath } = getOutputPathsForBundle(resolvedRefOpts.options, /*forceDtsPaths*/ true); - const node = createInputFilesWithFilePaths(readFile, jsFilePath!, sourceMapFilePath, declarationFilePath!, declarationMapPath, buildInfoPath, host, resolvedRefOpts.options); + const { jsFilePath, sourceMapFilePath, declarationFilePath, declarationMapPath, buildInfoPath } = + getOutputPathsForBundle(resolvedRefOpts.options, /*forceDtsPaths*/ true); + const node = createInputFilesWithFilePaths( + readFile, + jsFilePath!, + sourceMapFilePath, + declarationFilePath!, + declarationMapPath, + buildInfoPath, + host, + resolvedRefOpts.options, + ); (nodes || (nodes = [])).push(node); } } @@ -5251,7 +6717,11 @@ export function resolveProjectReferencePath(ref: ProjectReference): ResolvedConf * * @internal */ -export function getResolutionDiagnostic(options: CompilerOptions, { extension }: ResolvedModuleFull, { isDeclarationFile }: { isDeclarationFile: SourceFile["isDeclarationFile"]; }): DiagnosticMessage | undefined { +export function getResolutionDiagnostic( + options: CompilerOptions, + { extension }: ResolvedModuleFull, + { isDeclarationFile }: { isDeclarationFile: SourceFile["isDeclarationFile"]; }, +): DiagnosticMessage | undefined { switch (extension) { case Extension.Ts: case Extension.Dts: @@ -5279,14 +6749,17 @@ export function getResolutionDiagnostic(options: CompilerOptions, { extension }: return options.jsx ? undefined : Diagnostics.Module_0_was_resolved_to_1_but_jsx_is_not_set; } function needAllowJs() { - return getAllowJSCompilerOption(options) || !getStrictOptionValue(options, "noImplicitAny") ? undefined : Diagnostics.Could_not_find_a_declaration_file_for_module_0_1_implicitly_has_an_any_type; + return getAllowJSCompilerOption(options) || !getStrictOptionValue(options, "noImplicitAny") ? undefined + : Diagnostics.Could_not_find_a_declaration_file_for_module_0_1_implicitly_has_an_any_type; } function needResolveJsonModule() { - return getResolveJsonModule(options) ? undefined : Diagnostics.Module_0_was_resolved_to_1_but_resolveJsonModule_is_not_used; + return getResolveJsonModule(options) ? undefined + : Diagnostics.Module_0_was_resolved_to_1_but_resolveJsonModule_is_not_used; } function needAllowArbitraryExtensions() { // But don't report the allowArbitraryExtensions error from declaration files (no reason to report it, since the import doesn't have a runtime component) - return isDeclarationFile || options.allowArbitraryExtensions ? undefined : Diagnostics.Module_0_was_resolved_to_1_but_allowArbitraryExtensions_is_not_set; + return isDeclarationFile || options.allowArbitraryExtensions ? undefined + : Diagnostics.Module_0_was_resolved_to_1_but_allowArbitraryExtensions_is_not_set; } } @@ -5302,7 +6775,10 @@ function getModuleNames({ imports, moduleAugmentations }: SourceFile): StringLit } /** @internal */ -export function getModuleNameStringLiteralAt({ imports, moduleAugmentations }: SourceFileImportsList, index: number): StringLiteralLike { +export function getModuleNameStringLiteralAt( + { imports, moduleAugmentations }: SourceFileImportsList, + index: number, +): StringLiteralLike { if (index < imports.length) return imports[index]; let augIndex = imports.length; for (const aug of moduleAugmentations) { diff --git a/src/compiler/resolutionCache.ts b/src/compiler/resolutionCache.ts index b0d4c35fbb93d..f5f96c76b13aa 100644 --- a/src/compiler/resolutionCache.ts +++ b/src/compiler/resolutionCache.ts @@ -161,10 +161,14 @@ interface ResolutionWithResolvedFileName { } /** @internal */ -export interface CachedResolvedModuleWithFailedLookupLocations extends ResolvedModuleWithFailedLookupLocations, ResolutionWithFailedLookupLocations { +export interface CachedResolvedModuleWithFailedLookupLocations + extends ResolvedModuleWithFailedLookupLocations, ResolutionWithFailedLookupLocations +{ } -interface CachedResolvedTypeReferenceDirectiveWithFailedLookupLocations extends ResolvedTypeReferenceDirectiveWithFailedLookupLocations, ResolutionWithFailedLookupLocations { +interface CachedResolvedTypeReferenceDirectiveWithFailedLookupLocations + extends ResolvedTypeReferenceDirectiveWithFailedLookupLocations, ResolutionWithFailedLookupLocations +{ } /** @internal */ @@ -172,7 +176,11 @@ export interface ResolutionCacheHost extends MinimalResolutionCacheHost { toPath(fileName: string): Path; getCanonicalFileName: GetCanonicalFileName; getCompilationSettings(): CompilerOptions; - watchDirectoryOfFailedLookupLocation(directory: string, cb: DirectoryWatcherCallback, flags: WatchDirectoryFlags): FileWatcher; + watchDirectoryOfFailedLookupLocation( + directory: string, + cb: DirectoryWatcherCallback, + flags: WatchDirectoryFlags, + ): FileWatcher; watchAffectingFileLocation(file: string, cb: FileWatcherCallback): FileWatcher; onInvalidatedResolution(): void; watchTypeRootsDirectory(directory: string, cb: DirectoryWatcherCallback, flags: WatchDirectoryFlags): FileWatcher; @@ -219,9 +227,9 @@ export function removeIgnoredPath(path: Path): Path | undefined { return removeSuffix(path, "/.staging") as Path; } - return some(ignoredPaths, searchPath => stringContains(path, searchPath)) ? - undefined : - path; + return some(ignoredPaths, searchPath => stringContains(path, searchPath)) + ? undefined + : path; } function perceivedOsRootLengthForWatching(pathComponents: Readonly, length: number) { @@ -230,9 +238,9 @@ function perceivedOsRootLengthForWatching(pathComponents: Readonly, fileOrDirComponents: Readonly) { +function isInDirectoryPath( + dirComponents: Readonly, + fileOrDirComponents: Readonly, +) { if (fileOrDirComponents.length < fileOrDirComponents.length) return false; for (let i = 0; i < dirComponents.length; i++) { if (fileOrDirComponents[i] !== dirComponents[i]) return false; @@ -303,9 +314,13 @@ export function getDirectoryToWatchFailedLookupLocation( ): DirectoryOfFailedLookupWatch | undefined { const failedLookupPathComponents: Readonly = getPathComponents(failedLookupLocationPath); // Ensure failed look up is normalized path - failedLookupLocation = isRootedDiskPath(failedLookupLocation) ? normalizePath(failedLookupLocation) : getNormalizedAbsolutePath(failedLookupLocation, getCurrentDirectory()); + failedLookupLocation = isRootedDiskPath(failedLookupLocation) ? normalizePath(failedLookupLocation) + : getNormalizedAbsolutePath(failedLookupLocation, getCurrentDirectory()); const failedLookupComponents: readonly string[] = getPathComponents(failedLookupLocation); - const perceivedOsRootLength = perceivedOsRootLengthForWatching(failedLookupPathComponents, failedLookupPathComponents.length); + const perceivedOsRootLength = perceivedOsRootLengthForWatching( + failedLookupPathComponents, + failedLookupPathComponents.length, + ); if (failedLookupPathComponents.length <= perceivedOsRootLength + 1) return undefined; // If directory path contains node module, get the most parent node_modules directory for watching const nodeModulesIndex = failedLookupPathComponents.indexOf("node_modules" as Path); @@ -313,7 +328,11 @@ export function getDirectoryToWatchFailedLookupLocation( if (isInDirectoryPath(rootPathComponents, failedLookupPathComponents)) { if (failedLookupPathComponents.length > rootPathComponents.length + 1) { // Instead of watching root, watch directory in root to avoid watching excluded directories not needed for module resolution - return getDirectoryOfFailedLookupWatch(failedLookupComponents, failedLookupPathComponents, Math.max(rootPathComponents.length + 1, perceivedOsRootLength + 1)); + return getDirectoryOfFailedLookupWatch( + failedLookupComponents, + failedLookupPathComponents, + Math.max(rootPathComponents.length + 1, perceivedOsRootLength + 1), + ); } else { // Always watch root directory non recursively @@ -388,7 +407,8 @@ export function getDirectoryToWatchFailedLookupLocationFromTypeRoot( // Because this is called when we are watching typeRoot, we dont need additional check whether typeRoot is not say c:/users/node_modules/@types when root is c:/ return rootPath; } - typeRoot = isRootedDiskPath(typeRoot) ? normalizePath(typeRoot) : getNormalizedAbsolutePath(typeRoot, getCurrentDirectory()); + typeRoot = isRootedDiskPath(typeRoot) ? normalizePath(typeRoot) + : getNormalizedAbsolutePath(typeRoot, getCurrentDirectory()); const toWatch = getDirectoryToWatchFromFailedLookupLocationDirectory( getPathComponents(typeRoot), typeRootPathComponents, @@ -401,11 +421,14 @@ export function getDirectoryToWatchFailedLookupLocationFromTypeRoot( } /** @internal */ -export function getRootDirectoryOfResolutionCache(rootDirForResolution: string, getCurrentDirectory: () => string | undefined) { +export function getRootDirectoryOfResolutionCache( + rootDirForResolution: string, + getCurrentDirectory: () => string | undefined, +) { const normalized = getNormalizedAbsolutePath(rootDirForResolution, getCurrentDirectory()); - return !isDiskPathRoot(normalized) ? - removeTrailingDirectorySeparator(normalized) : - normalized; + return !isDiskPathRoot(normalized) + ? removeTrailingDirectorySeparator(normalized) + : normalized; } /** @internal */ @@ -413,10 +436,17 @@ export function getRootPathSplitLength(rootPath: Path) { return rootPath.split(directorySeparator).length - (hasTrailingDirectorySeparator(rootPath) ? 1 : 0); } -type GetResolutionWithResolvedFileName = (resolution: T) => R | undefined; +type GetResolutionWithResolvedFileName< + T extends ResolutionWithFailedLookupLocations = ResolutionWithFailedLookupLocations, + R extends ResolutionWithResolvedFileName = ResolutionWithResolvedFileName, +> = (resolution: T) => R | undefined; /** @internal */ -export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootDirForResolution: string, logChangesWhenResolvingModule: boolean): ResolutionCache { +export function createResolutionCache( + resolutionHost: ResolutionCacheHost, + rootDirForResolution: string, + logChangesWhenResolvingModule: boolean, +): ResolutionCache { let filesWithChangedSetOfUnresolvedImports: Path[] | undefined; let filesWithInvalidatedResolutions: Set | undefined; let filesWithInvalidatedNonRelativeUnresolvedImports: ReadonlyMap | undefined; @@ -448,7 +478,10 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD resolutionHost.getCompilationSettings(), ); - const resolvedTypeReferenceDirectives = new Map>(); + const resolvedTypeReferenceDirectives = new Map< + Path, + ModeAwareCache + >(); const typeReferenceDirectiveResolutionCache = createTypeReferenceDirectiveResolutionCache( getCurrentDirectory(), resolutionHost.getCanonicalFileName, @@ -503,7 +536,9 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD return resolution.resolvedModule; } - function getResolvedTypeReferenceDirective(resolution: CachedResolvedTypeReferenceDirectiveWithFailedLookupLocations) { + function getResolvedTypeReferenceDirective( + resolution: CachedResolvedTypeReferenceDirectiveWithFailedLookupLocations, + ) { return resolution.resolvedTypeReferenceDirective; } @@ -571,13 +606,13 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD filesWithInvalidatedResolutions = undefined; return { hasInvalidatedResolutions: path => - customHasInvalidatedResolutions(path) || - allModuleAndTypeResolutionsAreInvalidated || - !!collected?.has(path) || - isFileWithInvalidatedNonRelativeUnresolvedImports(path), + customHasInvalidatedResolutions(path) + || allModuleAndTypeResolutionsAreInvalidated + || !!collected?.has(path) + || isFileWithInvalidatedNonRelativeUnresolvedImports(path), hasInvalidatedLibResolutions: libFileName => - customHasInvalidatedLibResolutions(libFileName) || - !!resolvedLibraries?.get(libFileName)?.isInvalidated, + customHasInvalidatedLibResolutions(libFileName) + || !!resolvedLibraries?.get(libFileName)?.isInvalidated, }; } @@ -596,7 +631,13 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD if (!newProgram?.resolvedLibReferences?.has(libFileName)) { stopWatchFailedLookupLocationOfResolution( resolution, - resolutionHost.toPath(getInferredLibraryNameResolveFrom(newProgram!.getCompilerOptions(), getCurrentDirectory(), libFileName)), + resolutionHost.toPath( + getInferredLibraryNameResolveFrom( + newProgram!.getCompilerOptions(), + getCurrentDirectory(), + libFileName, + ), + ), getResolvedModule, ); resolvedLibraries.delete(libFileName); @@ -649,9 +690,23 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD hasChangedAutomaticTypeDirectiveNames = false; } - function resolveModuleName(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, redirectedReference?: ResolvedProjectReference, mode?: ResolutionMode): CachedResolvedModuleWithFailedLookupLocations { + function resolveModuleName( + moduleName: string, + containingFile: string, + compilerOptions: CompilerOptions, + redirectedReference?: ResolvedProjectReference, + mode?: ResolutionMode, + ): CachedResolvedModuleWithFailedLookupLocations { const host = resolutionHost.getCompilerHost?.() || resolutionHost; - const primaryResult = ts_resolveModuleName(moduleName, containingFile, compilerOptions, host, moduleResolutionCache, redirectedReference, mode); + const primaryResult = ts_resolveModuleName( + moduleName, + containingFile, + compilerOptions, + host, + moduleResolutionCache, + redirectedReference, + mode, + ); // return result immediately only if global cache support is not enabled or if it is .ts, .tsx or .d.ts if (!resolutionHost.getGlobalCache) { return primaryResult; @@ -659,23 +714,36 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD // otherwise try to load typings from @types const globalCache = resolutionHost.getGlobalCache(); - if (globalCache !== undefined && !isExternalModuleNameRelative(moduleName) && !(primaryResult.resolvedModule && extensionIsTS(primaryResult.resolvedModule.extension))) { + if ( + globalCache !== undefined && !isExternalModuleNameRelative(moduleName) + && !(primaryResult.resolvedModule && extensionIsTS(primaryResult.resolvedModule.extension)) + ) { // create different collection of failed lookup locations for second pass // if it will fail and we've already found something during the first pass - we don't want to pollute its results - const { resolvedModule, failedLookupLocations, affectingLocations, resolutionDiagnostics } = loadModuleFromGlobalCache( - Debug.checkDefined(resolutionHost.globalCacheResolutionModuleName)(moduleName), - resolutionHost.projectName, - compilerOptions, - host, - globalCache, - moduleResolutionCache, - ); + const { resolvedModule, failedLookupLocations, affectingLocations, resolutionDiagnostics } = + loadModuleFromGlobalCache( + Debug.checkDefined(resolutionHost.globalCacheResolutionModuleName)(moduleName), + resolutionHost.projectName, + compilerOptions, + host, + globalCache, + moduleResolutionCache, + ); if (resolvedModule) { // Modify existing resolution so its saved in the directory cache as well (primaryResult.resolvedModule as any) = resolvedModule; - primaryResult.failedLookupLocations = updateResolutionField(primaryResult.failedLookupLocations, failedLookupLocations); - primaryResult.affectingLocations = updateResolutionField(primaryResult.affectingLocations, affectingLocations); - primaryResult.resolutionDiagnostics = updateResolutionField(primaryResult.resolutionDiagnostics, resolutionDiagnostics); + primaryResult.failedLookupLocations = updateResolutionField( + primaryResult.failedLookupLocations, + failedLookupLocations, + ); + primaryResult.affectingLocations = updateResolutionField( + primaryResult.affectingLocations, + affectingLocations, + ); + primaryResult.resolutionDiagnostics = updateResolutionField( + primaryResult.resolutionDiagnostics, + resolutionDiagnostics, + ); return primaryResult; } } @@ -702,7 +770,12 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD }; } - interface ResolveNamesWithLocalCacheInput { + interface ResolveNamesWithLocalCacheInput< + Entry, + SourceFile, + T extends ResolutionWithFailedLookupLocations, + R extends ResolutionWithResolvedFileName, + > { entries: readonly Entry[]; containingFile: string; containingSourceFile: SourceFile; @@ -716,7 +789,12 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD logChanges?: boolean; deferWatchingNonRelativeResolution: boolean; } - function resolveNamesWithLocalCache({ + function resolveNamesWithLocalCache< + Entry, + SourceFile, + T extends ResolutionWithFailedLookupLocations, + R extends ResolutionWithResolvedFileName, + >({ entries, containingFile, containingSourceFile, @@ -733,14 +811,15 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD const path = resolutionHost.toPath(containingFile); const resolutionsInFile = perFileCache.get(path) || perFileCache.set(path, createModeAwareCache()).get(path)!; const resolvedModules: T[] = []; - const hasInvalidatedNonRelativeUnresolvedImport = logChanges && isFileWithInvalidatedNonRelativeUnresolvedImports(path); + const hasInvalidatedNonRelativeUnresolvedImport = logChanges + && isFileWithInvalidatedNonRelativeUnresolvedImports(path); // All the resolutions in this file are invalidated if this file wasn't resolved using same redirect const program = resolutionHost.getCurrentProgram(); const oldRedirect = program && program.getResolvedProjectReferenceToRedirect(containingFile); - const unmatchedRedirects = oldRedirect ? - !redirectedReference || redirectedReference.sourceFile.path !== oldRedirect.sourceFile.path : - !!redirectedReference; + const unmatchedRedirects = oldRedirect + ? !redirectedReference || redirectedReference.sourceFile.path !== oldRedirect.sourceFile.path + : !!redirectedReference; const seenNamesInFile = createModeAwareCache(); for (const entry of entries) { @@ -749,10 +828,12 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD let resolution = resolutionsInFile.get(name, mode); // Resolution is valid if it is present and not invalidated if ( - !seenNamesInFile.has(name, mode) && - (allModuleAndTypeResolutionsAreInvalidated || unmatchedRedirects || !resolution || resolution.isInvalidated || + !seenNamesInFile.has(name, mode) + && (allModuleAndTypeResolutionsAreInvalidated || unmatchedRedirects || !resolution + || resolution.isInvalidated // If the name is unresolved import that was invalidated, recalculate - (hasInvalidatedNonRelativeUnresolvedImport && !isExternalModuleNameRelative(name) && shouldRetryResolution(resolution))) + || (hasInvalidatedNonRelativeUnresolvedImport && !isExternalModuleNameRelative(name) + && shouldRetryResolution(resolution))) ) { const existingResolution = resolution; resolution = loader.resolve(name, mode); @@ -760,12 +841,25 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD resolutionHost.onDiscoveredSymlink(); } resolutionsInFile.set(name, mode, resolution); - watchFailedLookupLocationsOfExternalModuleResolutions(name, resolution, path, getResolutionWithResolvedFileName, deferWatchingNonRelativeResolution); + watchFailedLookupLocationsOfExternalModuleResolutions( + name, + resolution, + path, + getResolutionWithResolvedFileName, + deferWatchingNonRelativeResolution, + ); if (existingResolution) { - stopWatchFailedLookupLocationOfResolution(existingResolution, path, getResolutionWithResolvedFileName); + stopWatchFailedLookupLocationOfResolution( + existingResolution, + path, + getResolutionWithResolvedFileName, + ); } - if (logChanges && filesWithChangedSetOfUnresolvedImports && !resolutionIsEqualTo(existingResolution, resolution)) { + if ( + logChanges && filesWithChangedSetOfUnresolvedImports + && !resolutionIsEqualTo(existingResolution, resolution) + ) { filesWithChangedSetOfUnresolvedImports.push(path); // reset log changes to avoid recording the same file multiple times logChanges = false; @@ -777,17 +871,22 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD const resolved = getResolutionWithResolvedFileName(resolution!); trace( host, - perFileCache === resolvedModuleNames as unknown ? - resolved?.resolvedFileName ? - resolved.packageId ? - Diagnostics.Reusing_resolution_of_module_0_from_1_of_old_program_it_was_successfully_resolved_to_2_with_Package_ID_3 : - Diagnostics.Reusing_resolution_of_module_0_from_1_of_old_program_it_was_successfully_resolved_to_2 : - Diagnostics.Reusing_resolution_of_module_0_from_1_of_old_program_it_was_not_resolved : - resolved?.resolvedFileName ? - resolved.packageId ? - Diagnostics.Reusing_resolution_of_type_reference_directive_0_from_1_of_old_program_it_was_successfully_resolved_to_2_with_Package_ID_3 : - Diagnostics.Reusing_resolution_of_type_reference_directive_0_from_1_of_old_program_it_was_successfully_resolved_to_2 : - Diagnostics.Reusing_resolution_of_type_reference_directive_0_from_1_of_old_program_it_was_not_resolved, + perFileCache === resolvedModuleNames as unknown + ? resolved?.resolvedFileName + ? resolved.packageId + ? Diagnostics + .Reusing_resolution_of_module_0_from_1_of_old_program_it_was_successfully_resolved_to_2_with_Package_ID_3 + : Diagnostics + .Reusing_resolution_of_module_0_from_1_of_old_program_it_was_successfully_resolved_to_2 + : Diagnostics.Reusing_resolution_of_module_0_from_1_of_old_program_it_was_not_resolved + : resolved?.resolvedFileName + ? resolved.packageId + ? Diagnostics + .Reusing_resolution_of_type_reference_directive_0_from_1_of_old_program_it_was_successfully_resolved_to_2_with_Package_ID_3 + : Diagnostics + .Reusing_resolution_of_type_reference_directive_0_from_1_of_old_program_it_was_successfully_resolved_to_2 + : Diagnostics + .Reusing_resolution_of_type_reference_directive_0_from_1_of_old_program_it_was_not_resolved, name, containingFile, resolved?.resolvedFileName, @@ -887,7 +986,8 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD options, ), getResolutionWithResolvedFileName: getResolvedModule, - shouldRetryResolution: resolution => !resolution.resolvedModule || !resolutionExtensionIsTSOrJson(resolution.resolvedModule.extension), + shouldRetryResolution: resolution => + !resolution.resolvedModule || !resolutionExtensionIsTSOrJson(resolution.resolvedModule.extension), logChanges: logChangesWhenResolvingModule, deferWatchingNonRelativeResolution: true, // Defer non relative resolution watch because we could be using ambient modules }); @@ -905,7 +1005,13 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD const existingResolution = resolution; resolution = ts_resolveLibrary(libraryName, resolveFrom, options, host, libraryResolutionCache); const path = resolutionHost.toPath(resolveFrom); - watchFailedLookupLocationsOfExternalModuleResolutions(libraryName, resolution, path, getResolvedModule, /*deferWatchingNonRelativeResolution*/ false); + watchFailedLookupLocationsOfExternalModuleResolutions( + libraryName, + resolution, + path, + getResolvedModule, + /*deferWatchingNonRelativeResolution*/ false, + ); resolvedLibraries.set(libFileName, resolution); if (existingResolution) { stopWatchFailedLookupLocationOfResolution(existingResolution, path, getResolvedModule); @@ -916,11 +1022,13 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD const resolved = getResolvedModule(resolution); trace( host, - resolved?.resolvedFileName ? - resolved.packageId ? - Diagnostics.Reusing_resolution_of_module_0_from_1_of_old_program_it_was_successfully_resolved_to_2_with_Package_ID_3 : - Diagnostics.Reusing_resolution_of_module_0_from_1_of_old_program_it_was_successfully_resolved_to_2 : - Diagnostics.Reusing_resolution_of_module_0_from_1_of_old_program_it_was_not_resolved, + resolved?.resolvedFileName + ? resolved.packageId + ? Diagnostics + .Reusing_resolution_of_module_0_from_1_of_old_program_it_was_successfully_resolved_to_2_with_Package_ID_3 + : Diagnostics + .Reusing_resolution_of_module_0_from_1_of_old_program_it_was_successfully_resolved_to_2 + : Diagnostics.Reusing_resolution_of_module_0_from_1_of_old_program_it_was_not_resolved, libraryName, resolveFrom, resolved?.resolvedFileName, @@ -943,7 +1051,10 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD return endsWith(dirPath, "/node_modules/@types"); } - function watchFailedLookupLocationsOfExternalModuleResolutions( + function watchFailedLookupLocationsOfExternalModuleResolutions< + T extends ResolutionWithFailedLookupLocations, + R extends ResolutionWithResolvedFileName, + >( name: string, resolution: T, filePath: Path, @@ -1018,7 +1129,10 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD watchAffectingLocationsOfResolution(resolution, !failedLookupLocations?.length && !node10Result); } - function watchAffectingLocationsOfResolution(resolution: ResolutionWithFailedLookupLocations, addToResolutionsWithOnlyAffectingLocations: boolean) { + function watchAffectingLocationsOfResolution( + resolution: ResolutionWithFailedLookupLocations, + addToResolutionsWithOnlyAffectingLocations: boolean, + ) { Debug.assert(!!resolution.refCount); const { affectingLocations } = resolution; if (!affectingLocations?.length) return; @@ -1052,9 +1166,13 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD } const paths = new Set(); paths.add(locationToWatch); - let actualWatcher = canWatchAffectingLocation(resolutionHost.toPath(locationToWatch)) ? - resolutionHost.watchAffectingFileLocation(locationToWatch, (fileName, eventKind) => { - cachedDirectoryStructureHost?.addOrDeleteFile(fileName, resolutionHost.toPath(locationToWatch), eventKind); + let actualWatcher = canWatchAffectingLocation(resolutionHost.toPath(locationToWatch)) + ? resolutionHost.watchAffectingFileLocation(locationToWatch, (fileName, eventKind) => { + cachedDirectoryStructureHost?.addOrDeleteFile( + fileName, + resolutionHost.toPath(locationToWatch), + eventKind, + ); const packageJsonMap = moduleResolutionCache.getPackageJsonInfoCache().getInternalMap(); paths.forEach(path => { if (watcher.resolutions) (affectingPathChecks ??= new Set()).add(path); @@ -1082,13 +1200,18 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD } } - function watchFailedLookupLocationOfNonRelativeModuleResolutions(resolutions: ResolutionWithFailedLookupLocations[], name: string) { + function watchFailedLookupLocationOfNonRelativeModuleResolutions( + resolutions: ResolutionWithFailedLookupLocations[], + name: string, + ) { const program = resolutionHost.getCurrentProgram(); if (!program || !program.getTypeChecker().tryFindAmbientModuleWithoutAugmentations(name)) { resolutions.forEach(watchFailedLookupLocationOfResolution); } else { - resolutions.forEach(resolution => watchAffectingLocationsOfResolution(resolution, /*addToResolutionsWithOnlyAffectingLocations*/ true)); + resolutions.forEach(resolution => + watchAffectingLocationsOfResolution(resolution, /*addToResolutionsWithOnlyAffectingLocations*/ true) + ); } } @@ -1099,7 +1222,11 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD dirWatcher.refCount++; } else { - directoryWatchesOfFailedLookups.set(dirPath, { watcher: createDirectoryWatcher(dir, dirPath, nonRecursive), refCount: 1, nonRecursive }); + directoryWatchesOfFailedLookups.set(dirPath, { + watcher: createDirectoryWatcher(dir, dirPath, nonRecursive), + refCount: 1, + nonRecursive, + }); } } @@ -1125,7 +1252,10 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD return removeAtRoot; } - function stopWatchFailedLookupLocationOfResolution( + function stopWatchFailedLookupLocationOfResolution< + T extends ResolutionWithFailedLookupLocations, + R extends ResolutionWithResolvedFileName, + >( resolution: T, filePath: Path, getResolutionWithResolvedFileName: GetResolutionWithResolvedFileName, @@ -1183,7 +1313,10 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD }, nonRecursive ? WatchDirectoryFlags.None : WatchDirectoryFlags.Recursive); } - function removeResolutionsOfFileFromCache( + function removeResolutionsOfFileFromCache< + T extends ResolutionWithFailedLookupLocations, + R extends ResolutionWithResolvedFileName, + >( cache: Map>, filePath: Path, getResolutionWithResolvedFileName: GetResolutionWithResolvedFileName, @@ -1191,7 +1324,9 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD // Deleted file, stop watching failed lookups for all the resolutions in the file const resolutions = cache.get(filePath); if (resolutions) { - resolutions.forEach(resolution => stopWatchFailedLookupLocationOfResolution(resolution, filePath, getResolutionWithResolvedFileName)); + resolutions.forEach(resolution => + stopWatchFailedLookupLocationOfResolution(resolution, filePath, getResolutionWithResolvedFileName) + ); cache.delete(filePath); } } @@ -1215,7 +1350,13 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD removeResolutionsOfFileFromCache(resolvedTypeReferenceDirectives, filePath, getResolvedTypeReferenceDirective); } - function invalidateResolutions(resolutions: Set | Map | undefined, canInvalidate: (resolution: ResolutionWithFailedLookupLocations) => boolean | undefined) { + function invalidateResolutions( + resolutions: + | Set + | Map + | undefined, + canInvalidate: (resolution: ResolutionWithFailedLookupLocations) => boolean | undefined, + ) { if (!resolutions) return false; let invalidated = false; resolutions.forEach(resolution => { @@ -1224,7 +1365,8 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD for (const containingFilePath of Debug.checkDefined(resolution.files)) { (filesWithInvalidatedResolutions ??= new Set()).add(containingFilePath); // When its a file with inferred types resolution, invalidate type reference directive resolution - hasChangedAutomaticTypeDirectiveNames = hasChangedAutomaticTypeDirectiveNames || endsWith(containingFilePath, inferredTypesContainingFile); + hasChangedAutomaticTypeDirectiveNames = hasChangedAutomaticTypeDirectiveNames + || endsWith(containingFilePath, inferredTypesContainingFile); } }); return invalidated; @@ -1235,20 +1377,26 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD // Resolution is invalidated if the resulting file name is same as the deleted file path const prevHasChangedAutomaticTypeDirectiveNames = hasChangedAutomaticTypeDirectiveNames; if ( - invalidateResolutions(resolvedFileToResolution.get(filePath), returnTrue) && - hasChangedAutomaticTypeDirectiveNames && - !prevHasChangedAutomaticTypeDirectiveNames + invalidateResolutions(resolvedFileToResolution.get(filePath), returnTrue) + && hasChangedAutomaticTypeDirectiveNames + && !prevHasChangedAutomaticTypeDirectiveNames ) { resolutionHost.onChangedAutomaticTypeDirectiveNames(); } } function setFilesWithInvalidatedNonRelativeUnresolvedImports(filesMap: ReadonlyMap) { - Debug.assert(filesWithInvalidatedNonRelativeUnresolvedImports === filesMap || filesWithInvalidatedNonRelativeUnresolvedImports === undefined); + Debug.assert( + filesWithInvalidatedNonRelativeUnresolvedImports === filesMap + || filesWithInvalidatedNonRelativeUnresolvedImports === undefined, + ); filesWithInvalidatedNonRelativeUnresolvedImports = filesMap; } - function scheduleInvalidateResolutionOfFailedLookupLocation(fileOrDirectoryPath: Path, isCreatingWatchedDirectory: boolean) { + function scheduleInvalidateResolutionOfFailedLookupLocation( + fileOrDirectoryPath: Path, + isCreatingWatchedDirectory: boolean, + ) { if (isCreatingWatchedDirectory) { // Watching directory is created // Invalidate any resolution has failed lookup in this directory @@ -1269,8 +1417,8 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD // Return early if it does not have any of the watching extension or not the custom failed lookup path const dirOfFileOrDirectory = getDirectoryPath(fileOrDirectoryPath); if ( - isNodeModulesAtTypesDirectory(fileOrDirectoryPath) || isNodeModulesDirectory(fileOrDirectoryPath) || - isNodeModulesAtTypesDirectory(dirOfFileOrDirectory) || isNodeModulesDirectory(dirOfFileOrDirectory) + isNodeModulesAtTypesDirectory(fileOrDirectoryPath) || isNodeModulesDirectory(fileOrDirectoryPath) + || isNodeModulesAtTypesDirectory(dirOfFileOrDirectory) || isNodeModulesDirectory(dirOfFileOrDirectory) ) { // Invalidate any resolution from this directory (failedLookupChecks ||= new Set()).add(fileOrDirectoryPath); @@ -1301,7 +1449,9 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD function invalidatePackageJsonMap() { const packageJsonMap = moduleResolutionCache.getPackageJsonInfoCache().getInternalMap(); if (packageJsonMap && (failedLookupChecks || startsWithPathChecks || isInDirectoryChecks)) { - packageJsonMap.forEach((_value, path) => isInvalidatedFailedLookup(path) ? packageJsonMap.delete(path) : undefined); + packageJsonMap.forEach((_value, path) => + isInvalidatedFailedLookup(path) ? packageJsonMap.delete(path) : undefined + ); } } @@ -1333,12 +1483,16 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD return invalidated; } - invalidated = invalidateResolutions(resolutionsWithFailedLookups, canInvalidateFailedLookupResolution) || invalidated; + invalidated = invalidateResolutions(resolutionsWithFailedLookups, canInvalidateFailedLookupResolution) + || invalidated; invalidatePackageJsonMap(); failedLookupChecks = undefined; startsWithPathChecks = undefined; isInDirectoryChecks = undefined; - invalidated = invalidateResolutions(resolutionsWithOnlyAffectingLocations, canInvalidatedFailedLookupResolutionWithAffectingLocation) || invalidated; + invalidated = invalidateResolutions( + resolutionsWithOnlyAffectingLocations, + canInvalidatedFailedLookupResolutionWithAffectingLocation, + ) || invalidated; affectingPathChecks = undefined; return invalidated; } @@ -1346,20 +1500,30 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD function canInvalidateFailedLookupResolution(resolution: ResolutionWithFailedLookupLocations) { if (canInvalidatedFailedLookupResolutionWithAffectingLocation(resolution)) return true; if (!failedLookupChecks && !startsWithPathChecks && !isInDirectoryChecks) return false; - return resolution.failedLookupLocations?.some(location => isInvalidatedFailedLookup(resolutionHost.toPath(location))) || - (!!resolution.node10Result && isInvalidatedFailedLookup(resolutionHost.toPath(resolution.node10Result))); + return resolution.failedLookupLocations?.some(location => + isInvalidatedFailedLookup(resolutionHost.toPath(location)) + ) + || (!!resolution.node10Result && isInvalidatedFailedLookup(resolutionHost.toPath(resolution.node10Result))); } function isInvalidatedFailedLookup(locationPath: Path) { - return failedLookupChecks?.has(locationPath) || - firstDefinedIterator(startsWithPathChecks?.keys() || [], fileOrDirectoryPath => startsWith(locationPath, fileOrDirectoryPath) ? true : undefined) || - firstDefinedIterator(isInDirectoryChecks?.keys() || [], dirPath => - locationPath.length > dirPath.length && - startsWith(locationPath, dirPath) && (isDiskPathRoot(dirPath) || locationPath[dirPath.length] === directorySeparator) ? true : undefined); + return failedLookupChecks?.has(locationPath) + || firstDefinedIterator( + startsWithPathChecks?.keys() || [], + fileOrDirectoryPath => startsWith(locationPath, fileOrDirectoryPath) ? true : undefined, + ) + || firstDefinedIterator(isInDirectoryChecks?.keys() || [], dirPath => + locationPath.length > dirPath.length + && startsWith(locationPath, dirPath) + && (isDiskPathRoot(dirPath) || locationPath[dirPath.length] === directorySeparator) ? true + : undefined); } - function canInvalidatedFailedLookupResolutionWithAffectingLocation(resolution: ResolutionWithFailedLookupLocations) { - return !!affectingPathChecks && resolution.affectingLocations?.some(location => affectingPathChecks!.has(location)); + function canInvalidatedFailedLookupResolutionWithAffectingLocation( + resolution: ResolutionWithFailedLookupLocations, + ) { + return !!affectingPathChecks + && resolution.affectingLocations?.some(location => affectingPathChecks!.has(location)); } function closeTypeRootsWatch() { @@ -1368,8 +1532,8 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD function createTypeRootsWatch(typeRootPath: Path, typeRoot: string): FileWatcher { // Create new watch and recursive info - return canWatchTypeRootPath(typeRootPath) ? - resolutionHost.watchTypeRootsDirectory(typeRoot, fileOrDirectory => { + return canWatchTypeRootPath(typeRootPath) + ? resolutionHost.watchTypeRootsDirectory(typeRoot, fileOrDirectory => { const fileOrDirectoryPath = resolutionHost.toPath(fileOrDirectory); if (cachedDirectoryStructureHost) { // Since the file existence changed, update the sourceFiles cache @@ -1393,10 +1557,13 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD dirPath => directoryWatchesOfFailedLookups.has(dirPath), ); if (dirPath) { - scheduleInvalidateResolutionOfFailedLookupLocation(fileOrDirectoryPath, dirPath === fileOrDirectoryPath); + scheduleInvalidateResolutionOfFailedLookupLocation( + fileOrDirectoryPath, + dirPath === fileOrDirectoryPath, + ); } - }, WatchDirectoryFlags.Recursive) : - noopFileWatcher; + }, WatchDirectoryFlags.Recursive) + : noopFileWatcher; } /** @@ -1441,7 +1608,8 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD function resolutionIsSymlink(resolution: ResolutionWithFailedLookupLocations) { return !!( - (resolution as ResolvedModuleWithFailedLookupLocations).resolvedModule?.originalPath || - (resolution as ResolvedTypeReferenceDirectiveWithFailedLookupLocations).resolvedTypeReferenceDirective?.originalPath + (resolution as ResolvedModuleWithFailedLookupLocations).resolvedModule?.originalPath + || (resolution as ResolvedTypeReferenceDirectiveWithFailedLookupLocations).resolvedTypeReferenceDirective + ?.originalPath ); } diff --git a/src/compiler/scanner.ts b/src/compiler/scanner.ts index bb4dd028f65d7..7eb9cdf35bafa 100644 --- a/src/compiler/scanner.ts +++ b/src/compiler/scanner.ts @@ -376,17 +376,17 @@ function lookupInUnicodeMap(code: number, map: readonly number[]): boolean { } /** @internal */ export function isUnicodeIdentifierStart(code: number, languageVersion: ScriptTarget | undefined) { - return languageVersion! >= ScriptTarget.ES2015 ? - lookupInUnicodeMap(code, unicodeESNextIdentifierStart) : - languageVersion === ScriptTarget.ES5 ? lookupInUnicodeMap(code, unicodeES5IdentifierStart) : - lookupInUnicodeMap(code, unicodeES3IdentifierStart); + return languageVersion! >= ScriptTarget.ES2015 + ? lookupInUnicodeMap(code, unicodeESNextIdentifierStart) + : languageVersion === ScriptTarget.ES5 ? lookupInUnicodeMap(code, unicodeES5IdentifierStart) + : lookupInUnicodeMap(code, unicodeES3IdentifierStart); } function isUnicodeIdentifierPart(code: number, languageVersion: ScriptTarget | undefined) { - return languageVersion! >= ScriptTarget.ES2015 ? - lookupInUnicodeMap(code, unicodeESNextIdentifierPart) : - languageVersion === ScriptTarget.ES5 ? lookupInUnicodeMap(code, unicodeES5IdentifierPart) : - lookupInUnicodeMap(code, unicodeES3IdentifierPart); + return languageVersion! >= ScriptTarget.ES2015 + ? lookupInUnicodeMap(code, unicodeESNextIdentifierPart) + : languageVersion === ScriptTarget.ES5 ? lookupInUnicodeMap(code, unicodeES5IdentifierPart) + : lookupInUnicodeMap(code, unicodeES3IdentifierPart); } function makeReverseMap(source: Map): string[] { @@ -443,22 +443,42 @@ export function computeLineStarts(text: string): number[] { export function getPositionOfLineAndCharacter(sourceFile: SourceFileLike, line: number, character: number): number; /** @internal */ -export function getPositionOfLineAndCharacter(sourceFile: SourceFileLike, line: number, character: number, allowEdits?: true): number; // eslint-disable-line @typescript-eslint/unified-signatures -export function getPositionOfLineAndCharacter(sourceFile: SourceFileLike, line: number, character: number, allowEdits?: true): number { - return sourceFile.getPositionOfLineAndCharacter ? - sourceFile.getPositionOfLineAndCharacter(line, character, allowEdits) : - computePositionOfLineAndCharacter(getLineStarts(sourceFile), line, character, sourceFile.text, allowEdits); +export function getPositionOfLineAndCharacter( + sourceFile: SourceFileLike, + line: number, + character: number, + allowEdits?: true, +): number; // eslint-disable-line @typescript-eslint/unified-signatures +export function getPositionOfLineAndCharacter( + sourceFile: SourceFileLike, + line: number, + character: number, + allowEdits?: true, +): number { + return sourceFile.getPositionOfLineAndCharacter + ? sourceFile.getPositionOfLineAndCharacter(line, character, allowEdits) + : computePositionOfLineAndCharacter(getLineStarts(sourceFile), line, character, sourceFile.text, allowEdits); } /** @internal */ -export function computePositionOfLineAndCharacter(lineStarts: readonly number[], line: number, character: number, debugText?: string, allowEdits?: true): number { +export function computePositionOfLineAndCharacter( + lineStarts: readonly number[], + line: number, + character: number, + debugText?: string, + allowEdits?: true, +): number { if (line < 0 || line >= lineStarts.length) { if (allowEdits) { // Clamp line to nearest allowable value line = line < 0 ? 0 : line >= lineStarts.length ? lineStarts.length - 1 : line; } else { - Debug.fail(`Bad line number. Line: ${line}, lineStarts.length: ${lineStarts.length} , line map is correct? ${debugText !== undefined ? arraysEqual(lineStarts, computeLineStarts(debugText)) : "unknown"}`); + Debug.fail( + `Bad line number. Line: ${line}, lineStarts.length: ${lineStarts.length} , line map is correct? ${ + debugText !== undefined ? arraysEqual(lineStarts, computeLineStarts(debugText)) : "unknown" + }`, + ); } } @@ -467,7 +487,8 @@ export function computePositionOfLineAndCharacter(lineStarts: readonly number[], // Clamp to nearest allowable values to allow the underlying to be edited without crashing (accuracy is lost, instead) // TODO: Somehow track edits between file as it was during the creation of sourcemap we have and the current file and // apply them to the computed position to improve accuracy - return res > lineStarts[line + 1] ? lineStarts[line + 1] : typeof debugText === "string" && res > debugText.length ? debugText.length : res; + return res > lineStarts[line + 1] ? lineStarts[line + 1] + : typeof debugText === "string" && res > debugText.length ? debugText.length : res; } if (line < lineStarts.length - 1) { Debug.assert(res < lineStarts[line + 1]); @@ -536,18 +557,18 @@ export function isWhiteSpaceLike(ch: number): boolean { export function isWhiteSpaceSingleLine(ch: number): boolean { // Note: nextLine is in the Zs space, and should be considered to be a whitespace. // It is explicitly not a line-break as it isn't in the exact set specified by EcmaScript. - return ch === CharacterCodes.space || - ch === CharacterCodes.tab || - ch === CharacterCodes.verticalTab || - ch === CharacterCodes.formFeed || - ch === CharacterCodes.nonBreakingSpace || - ch === CharacterCodes.nextLine || - ch === CharacterCodes.ogham || - ch >= CharacterCodes.enQuad && ch <= CharacterCodes.zeroWidthSpace || - ch === CharacterCodes.narrowNoBreakSpace || - ch === CharacterCodes.mathematicalSpace || - ch === CharacterCodes.ideographicSpace || - ch === CharacterCodes.byteOrderMark; + return ch === CharacterCodes.space + || ch === CharacterCodes.tab + || ch === CharacterCodes.verticalTab + || ch === CharacterCodes.formFeed + || ch === CharacterCodes.nonBreakingSpace + || ch === CharacterCodes.nextLine + || ch === CharacterCodes.ogham + || ch >= CharacterCodes.enQuad && ch <= CharacterCodes.zeroWidthSpace + || ch === CharacterCodes.narrowNoBreakSpace + || ch === CharacterCodes.mathematicalSpace + || ch === CharacterCodes.ideographicSpace + || ch === CharacterCodes.byteOrderMark; } export function isLineBreak(ch: number): boolean { @@ -562,10 +583,10 @@ export function isLineBreak(ch: number): boolean { // Only the characters in Table 3 are treated as line terminators. Other new line or line // breaking characters are treated as white space but not as line terminators. - return ch === CharacterCodes.lineFeed || - ch === CharacterCodes.carriageReturn || - ch === CharacterCodes.lineSeparator || - ch === CharacterCodes.paragraphSeparator; + return ch === CharacterCodes.lineFeed + || ch === CharacterCodes.carriageReturn + || ch === CharacterCodes.lineSeparator + || ch === CharacterCodes.paragraphSeparator; } function isDigit(ch: number): boolean { @@ -573,7 +594,8 @@ function isDigit(ch: number): boolean { } function isHexDigit(ch: number): boolean { - return isDigit(ch) || ch >= CharacterCodes.A && ch <= CharacterCodes.F || ch >= CharacterCodes.a && ch <= CharacterCodes.f; + return isDigit(ch) || ch >= CharacterCodes.A && ch <= CharacterCodes.F + || ch >= CharacterCodes.a && ch <= CharacterCodes.f; } function isCodePoint(code: number): boolean { @@ -613,7 +635,13 @@ export function couldStartTrivia(text: string, pos: number): boolean { } /** @internal */ -export function skipTrivia(text: string, pos: number, stopAfterLineBreak?: boolean, stopAtComments?: boolean, inJSDoc?: boolean): number { +export function skipTrivia( + text: string, + pos: number, + stopAfterLineBreak?: boolean, + stopAtComments?: boolean, + inJSDoc?: boolean, +): number { if (positionIsSynthesized(pos)) { return pos; } @@ -659,7 +687,10 @@ export function skipTrivia(text: string, pos: number, stopAfterLineBreak?: boole if (text.charCodeAt(pos + 1) === CharacterCodes.asterisk) { pos += 2; while (pos < text.length) { - if (text.charCodeAt(pos) === CharacterCodes.asterisk && text.charCodeAt(pos + 1) === CharacterCodes.slash) { + if ( + text.charCodeAt(pos) === CharacterCodes.asterisk + && text.charCodeAt(pos + 1) === CharacterCodes.slash + ) { pos += 2; break; } @@ -726,15 +757,19 @@ function isConflictMarkerTrivia(text: string, pos: number) { } } - return ch === CharacterCodes.equals || - text.charCodeAt(pos + mergeConflictMarkerLength) === CharacterCodes.space; + return ch === CharacterCodes.equals + || text.charCodeAt(pos + mergeConflictMarkerLength) === CharacterCodes.space; } } return false; } -function scanConflictMarkerTrivia(text: string, pos: number, error?: (diag: DiagnosticMessage, pos?: number, len?: number) => void) { +function scanConflictMarkerTrivia( + text: string, + pos: number, + error?: (diag: DiagnosticMessage, pos?: number, len?: number) => void, +) { if (error) { error(Diagnostics.Merge_conflict_marker_encountered, pos, mergeConflictMarkerLength); } @@ -753,7 +788,10 @@ function scanConflictMarkerTrivia(text: string, pos: number, error?: (diag: Diag // of the next ======= or >>>>>>> marker. while (pos < len) { const currentChar = text.charCodeAt(pos); - if ((currentChar === CharacterCodes.equals || currentChar === CharacterCodes.greaterThan) && currentChar !== ch && isConflictMarkerTrivia(text, pos)) { + if ( + (currentChar === CharacterCodes.equals || currentChar === CharacterCodes.greaterThan) + && currentChar !== ch && isConflictMarkerTrivia(text, pos) + ) { break; } @@ -800,7 +838,15 @@ export function scanShebangTrivia(text: string, pos: number) { * @returns If "reduce" is true, the accumulated value. If "reduce" is false, the first truthy * return value of the callback. */ -function iterateCommentRanges(reduce: boolean, text: string, pos: number, trailing: boolean, cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean, state: T, memo: U | undefined) => U, state: T, initial?: U): U | undefined { +function iterateCommentRanges( + reduce: boolean, + text: string, + pos: number, + trailing: boolean, + cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean, state: T, memo: U | undefined) => U, + state: T, + initial?: U, +): U | undefined { let pendingPos!: number; let pendingEnd!: number; let pendingKind!: CommentKind; @@ -846,7 +892,8 @@ function iterateCommentRanges(reduce: boolean, text: string, pos: number, const nextChar = text.charCodeAt(pos + 1); let hasTrailingNewLine = false; if (nextChar === CharacterCodes.slash || nextChar === CharacterCodes.asterisk) { - const kind = nextChar === CharacterCodes.slash ? SyntaxKind.SingleLineCommentTrivia : SyntaxKind.MultiLineCommentTrivia; + const kind = nextChar === CharacterCodes.slash ? SyntaxKind.SingleLineCommentTrivia + : SyntaxKind.MultiLineCommentTrivia; const startPos = pos; pos += 2; if (nextChar === CharacterCodes.slash) { @@ -860,7 +907,10 @@ function iterateCommentRanges(reduce: boolean, text: string, pos: number, } else { while (pos < text.length) { - if (text.charCodeAt(pos) === CharacterCodes.asterisk && text.charCodeAt(pos + 1) === CharacterCodes.slash) { + if ( + text.charCodeAt(pos) === CharacterCodes.asterisk + && text.charCodeAt(pos + 1) === CharacterCodes.slash + ) { pos += 2; break; } @@ -870,7 +920,14 @@ function iterateCommentRanges(reduce: boolean, text: string, pos: number, if (collecting) { if (hasPendingCommentRange) { - accumulator = cb(pendingPos, pendingEnd, pendingKind, pendingHasTrailingNewLine, state, accumulator); + accumulator = cb( + pendingPos, + pendingEnd, + pendingKind, + pendingHasTrailingNewLine, + state, + accumulator, + ); if (!reduce && accumulator) { // If we are not reducing and we have a truthy result, return it. return accumulator; @@ -906,27 +963,74 @@ function iterateCommentRanges(reduce: boolean, text: string, pos: number, return accumulator; } -export function forEachLeadingCommentRange(text: string, pos: number, cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean) => U): U | undefined; -export function forEachLeadingCommentRange(text: string, pos: number, cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean, state: T) => U, state: T): U | undefined; -export function forEachLeadingCommentRange(text: string, pos: number, cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean, state: T) => U, state?: T): U | undefined { +export function forEachLeadingCommentRange( + text: string, + pos: number, + cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean) => U, +): U | undefined; +export function forEachLeadingCommentRange( + text: string, + pos: number, + cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean, state: T) => U, + state: T, +): U | undefined; +export function forEachLeadingCommentRange( + text: string, + pos: number, + cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean, state: T) => U, + state?: T, +): U | undefined { return iterateCommentRanges(/*reduce*/ false, text, pos, /*trailing*/ false, cb, state!); } -export function forEachTrailingCommentRange(text: string, pos: number, cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean) => U): U | undefined; -export function forEachTrailingCommentRange(text: string, pos: number, cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean, state: T) => U, state: T): U | undefined; -export function forEachTrailingCommentRange(text: string, pos: number, cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean, state: T) => U, state?: T): U | undefined { +export function forEachTrailingCommentRange( + text: string, + pos: number, + cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean) => U, +): U | undefined; +export function forEachTrailingCommentRange( + text: string, + pos: number, + cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean, state: T) => U, + state: T, +): U | undefined; +export function forEachTrailingCommentRange( + text: string, + pos: number, + cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean, state: T) => U, + state?: T, +): U | undefined { return iterateCommentRanges(/*reduce*/ false, text, pos, /*trailing*/ true, cb, state!); } -export function reduceEachLeadingCommentRange(text: string, pos: number, cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean, state: T) => U, state: T, initial: U) { +export function reduceEachLeadingCommentRange( + text: string, + pos: number, + cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean, state: T) => U, + state: T, + initial: U, +) { return iterateCommentRanges(/*reduce*/ true, text, pos, /*trailing*/ false, cb, state, initial); } -export function reduceEachTrailingCommentRange(text: string, pos: number, cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean, state: T) => U, state: T, initial: U) { +export function reduceEachTrailingCommentRange( + text: string, + pos: number, + cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean, state: T) => U, + state: T, + initial: U, +) { return iterateCommentRanges(/*reduce*/ true, text, pos, /*trailing*/ true, cb, state, initial); } -function appendCommentRange(pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean, _state: any, comments: CommentRange[] = []) { +function appendCommentRange( + pos: number, + end: number, + kind: CommentKind, + hasTrailingNewLine: boolean, + _state: any, + comments: CommentRange[] = [], +) { comments.push({ kind, pos, end, hasTrailingNewLine }); return comments; } @@ -948,21 +1052,30 @@ export function getShebang(text: string): string | undefined { } export function isIdentifierStart(ch: number, languageVersion: ScriptTarget | undefined): boolean { - return ch >= CharacterCodes.A && ch <= CharacterCodes.Z || ch >= CharacterCodes.a && ch <= CharacterCodes.z || - ch === CharacterCodes.$ || ch === CharacterCodes._ || - ch > CharacterCodes.maxAsciiCharacter && isUnicodeIdentifierStart(ch, languageVersion); + return ch >= CharacterCodes.A && ch <= CharacterCodes.Z || ch >= CharacterCodes.a && ch <= CharacterCodes.z + || ch === CharacterCodes.$ || ch === CharacterCodes._ + || ch > CharacterCodes.maxAsciiCharacter && isUnicodeIdentifierStart(ch, languageVersion); } -export function isIdentifierPart(ch: number, languageVersion: ScriptTarget | undefined, identifierVariant?: LanguageVariant): boolean { - return ch >= CharacterCodes.A && ch <= CharacterCodes.Z || ch >= CharacterCodes.a && ch <= CharacterCodes.z || - ch >= CharacterCodes._0 && ch <= CharacterCodes._9 || ch === CharacterCodes.$ || ch === CharacterCodes._ || +export function isIdentifierPart( + ch: number, + languageVersion: ScriptTarget | undefined, + identifierVariant?: LanguageVariant, +): boolean { + return ch >= CharacterCodes.A && ch <= CharacterCodes.Z || ch >= CharacterCodes.a && ch <= CharacterCodes.z + || ch >= CharacterCodes._0 && ch <= CharacterCodes._9 || ch === CharacterCodes.$ || ch === CharacterCodes._ // "-" and ":" are valid in JSX Identifiers - (identifierVariant === LanguageVariant.JSX ? (ch === CharacterCodes.minus || ch === CharacterCodes.colon) : false) || - ch > CharacterCodes.maxAsciiCharacter && isUnicodeIdentifierPart(ch, languageVersion); + || (identifierVariant === LanguageVariant.JSX ? (ch === CharacterCodes.minus || ch === CharacterCodes.colon) + : false) + || ch > CharacterCodes.maxAsciiCharacter && isUnicodeIdentifierPart(ch, languageVersion); } /** @internal */ -export function isIdentifierText(name: string, languageVersion: ScriptTarget | undefined, identifierVariant?: LanguageVariant): boolean { +export function isIdentifierText( + name: string, + languageVersion: ScriptTarget | undefined, + identifierVariant?: LanguageVariant, +): boolean { let ch = codePointAt(name, 0); if (!isIdentifierStart(ch, languageVersion)) { return false; @@ -978,7 +1091,15 @@ export function isIdentifierText(name: string, languageVersion: ScriptTarget | u } // Creates a scanner over a (possibly unspecified) range of a piece of text. -export function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean, languageVariant = LanguageVariant.Standard, textInitial?: string, onError?: ErrorCallback, start?: number, length?: number): Scanner { +export function createScanner( + languageVersion: ScriptTarget, + skipTrivia: boolean, + languageVariant = LanguageVariant.Standard, + textInitial?: string, + onError?: ErrorCallback, + start?: number, + length?: number, +): Scanner { // Why var? It avoids TDZ checks in the runtime which can be costly. // See: https://github.com/microsoft/TypeScript/issues/52924 /* eslint-disable no-var */ @@ -1221,7 +1342,10 @@ export function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean } if (decimalFragment !== undefined || tokenFlags & TokenFlags.Scientific) { - checkForIdentifierStartAfterNumericLiteral(start, decimalFragment === undefined && !!(tokenFlags & TokenFlags.Scientific)); + checkForIdentifierStartAfterNumericLiteral( + start, + decimalFragment === undefined && !!(tokenFlags & TokenFlags.Scientific), + ); // if value is not an integer, it can be safely coerced to a number tokenValue = "" + +result; return SyntaxKind.NumericLiteral; @@ -1244,14 +1368,26 @@ export function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean if (length === 1 && text[identifierStart] === "n") { if (isScientific) { - error(Diagnostics.A_bigint_literal_cannot_use_exponential_notation, numericStart, identifierStart - numericStart + 1); + error( + Diagnostics.A_bigint_literal_cannot_use_exponential_notation, + numericStart, + identifierStart - numericStart + 1, + ); } else { - error(Diagnostics.A_bigint_literal_must_be_an_integer, numericStart, identifierStart - numericStart + 1); + error( + Diagnostics.A_bigint_literal_must_be_an_integer, + numericStart, + identifierStart - numericStart + 1, + ); } } else { - error(Diagnostics.An_identifier_or_keyword_cannot_immediately_follow_a_numeric_literal, identifierStart, length); + error( + Diagnostics.An_identifier_or_keyword_cannot_immediately_follow_a_numeric_literal, + identifierStart, + length, + ); pos = identifierStart; } } @@ -1312,8 +1448,8 @@ export function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean ch += CharacterCodes.a - CharacterCodes.A; // standardize hex literals to lowercase } else if ( - !((ch >= CharacterCodes._0 && ch <= CharacterCodes._9) || - (ch >= CharacterCodes.a && ch <= CharacterCodes.f)) + !((ch >= CharacterCodes._0 && ch <= CharacterCodes._9) + || (ch >= CharacterCodes.a && ch <= CharacterCodes.f)) ) { break; } @@ -1382,7 +1518,8 @@ export function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean contents += text.substring(start, pos); tokenFlags |= TokenFlags.Unterminated; error(Diagnostics.Unterminated_template_literal); - resultingToken = startedWithBacktick ? SyntaxKind.NoSubstitutionTemplateLiteral : SyntaxKind.TemplateTail; + resultingToken = startedWithBacktick ? SyntaxKind.NoSubstitutionTemplateLiteral + : SyntaxKind.TemplateTail; break; } @@ -1392,12 +1529,15 @@ export function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean if (currChar === CharacterCodes.backtick) { contents += text.substring(start, pos); pos++; - resultingToken = startedWithBacktick ? SyntaxKind.NoSubstitutionTemplateLiteral : SyntaxKind.TemplateTail; + resultingToken = startedWithBacktick ? SyntaxKind.NoSubstitutionTemplateLiteral + : SyntaxKind.TemplateTail; break; } // '${' - if (currChar === CharacterCodes.$ && pos + 1 < end && text.charCodeAt(pos + 1) === CharacterCodes.openBrace) { + if ( + currChar === CharacterCodes.$ && pos + 1 < end && text.charCodeAt(pos + 1) === CharacterCodes.openBrace + ) { contents += text.substring(start, pos); pos += 2; resultingToken = startedWithBacktick ? SyntaxKind.TemplateHead : SyntaxKind.TemplateMiddle; @@ -1490,7 +1630,12 @@ export function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean tokenFlags |= TokenFlags.ContainsInvalidEscape; if (shouldEmitInvalidEscapeError) { const code = parseInt(text.substring(start + 1, pos), 8); - error(Diagnostics.Octal_escape_sequences_are_not_allowed_Use_the_syntax_0, start, pos - start, "\\x" + padLeft(code.toString(16), 2, "0")); + error( + Diagnostics.Octal_escape_sequences_are_not_allowed_Use_the_syntax_0, + start, + pos - start, + "\\x" + padLeft(code.toString(16), 2, "0"), + ); return String.fromCharCode(code); } return text.substring(start, pos); @@ -1536,7 +1681,9 @@ export function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean if (!isCodePoint(escapedValue)) { tokenFlags |= TokenFlags.ContainsInvalidEscape; if (shouldEmitInvalidEscapeError) { - error(Diagnostics.An_extended_Unicode_escape_value_must_be_between_0x0_and_0x10FFFF_inclusive); + error( + Diagnostics.An_extended_Unicode_escape_value_must_be_between_0x0_and_0x10FFFF_inclusive, + ); } return text.substring(start, pos); } @@ -1650,7 +1797,9 @@ export function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean } function peekExtendedUnicodeEscape(): number { - if (codePointAt(text, pos + 1) === CharacterCodes.u && codePointAt(text, pos + 2) === CharacterCodes.openBrace) { + if ( + codePointAt(text, pos + 1) === CharacterCodes.u && codePointAt(text, pos + 2) === CharacterCodes.openBrace + ) { const start = pos; pos += 3; const escapedValueString = scanMinimumNumberOfHexDigits(1, /*canHaveSeparators*/ false); @@ -1816,7 +1965,10 @@ export function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean continue; } else { - if (ch === CharacterCodes.carriageReturn && pos + 1 < end && text.charCodeAt(pos + 1) === CharacterCodes.lineFeed) { + if ( + ch === CharacterCodes.carriageReturn && pos + 1 < end + && text.charCodeAt(pos + 1) === CharacterCodes.lineFeed + ) { // consume both CR and LF pos += 2; } @@ -1939,7 +2091,10 @@ export function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean scanNumber(); return token = SyntaxKind.NumericLiteral; } - if (text.charCodeAt(pos + 1) === CharacterCodes.dot && text.charCodeAt(pos + 2) === CharacterCodes.dot) { + if ( + text.charCodeAt(pos + 1) === CharacterCodes.dot + && text.charCodeAt(pos + 2) === CharacterCodes.dot + ) { return pos += 3, token = SyntaxKind.DotDotDotToken; } pos++; @@ -1973,7 +2128,10 @@ export function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean // Multi-line comment if (text.charCodeAt(pos + 1) === CharacterCodes.asterisk) { pos += 2; - if (text.charCodeAt(pos) === CharacterCodes.asterisk && text.charCodeAt(pos + 1) !== CharacterCodes.slash) { + if ( + text.charCodeAt(pos) === CharacterCodes.asterisk + && text.charCodeAt(pos + 1) !== CharacterCodes.slash + ) { tokenFlags |= TokenFlags.PrecedingJSDocComment; } @@ -1996,7 +2154,12 @@ export function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean } } - commentDirectives = appendIfCommentDirective(commentDirectives, text.slice(lastLineStart, pos), commentDirectiveRegExMultiLine, lastLineStart); + commentDirectives = appendIfCommentDirective( + commentDirectives, + text.slice(lastLineStart, pos), + commentDirectiveRegExMultiLine, + lastLineStart, + ); if (!commentClosed) { error(Diagnostics.Asterisk_Slash_expected); @@ -2021,7 +2184,11 @@ export function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean return token = SyntaxKind.SlashToken; case CharacterCodes._0: - if (pos + 2 < end && (text.charCodeAt(pos + 1) === CharacterCodes.X || text.charCodeAt(pos + 1) === CharacterCodes.x)) { + if ( + pos + 2 < end + && (text.charCodeAt(pos + 1) === CharacterCodes.X + || text.charCodeAt(pos + 1) === CharacterCodes.x) + ) { pos += 2; tokenValue = scanMinimumNumberOfHexDigits(1, /*canHaveSeparators*/ true); if (!tokenValue) { @@ -2032,7 +2199,11 @@ export function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean tokenFlags |= TokenFlags.HexSpecifier; return token = checkBigIntSuffix(); } - else if (pos + 2 < end && (text.charCodeAt(pos + 1) === CharacterCodes.B || text.charCodeAt(pos + 1) === CharacterCodes.b)) { + else if ( + pos + 2 < end + && (text.charCodeAt(pos + 1) === CharacterCodes.B + || text.charCodeAt(pos + 1) === CharacterCodes.b) + ) { pos += 2; tokenValue = scanBinaryOrOctalDigits(/* base */ 2); if (!tokenValue) { @@ -2043,7 +2214,11 @@ export function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean tokenFlags |= TokenFlags.BinarySpecifier; return token = checkBigIntSuffix(); } - else if (pos + 2 < end && (text.charCodeAt(pos + 1) === CharacterCodes.O || text.charCodeAt(pos + 1) === CharacterCodes.o)) { + else if ( + pos + 2 < end + && (text.charCodeAt(pos + 1) === CharacterCodes.O + || text.charCodeAt(pos + 1) === CharacterCodes.o) + ) { pos += 2; tokenValue = scanBinaryOrOctalDigits(/* base */ 8); if (!tokenValue) { @@ -2092,9 +2267,9 @@ export function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean return pos += 2, token = SyntaxKind.LessThanEqualsToken; } if ( - languageVariant === LanguageVariant.JSX && - text.charCodeAt(pos + 1) === CharacterCodes.slash && - text.charCodeAt(pos + 2) !== CharacterCodes.asterisk + languageVariant === LanguageVariant.JSX + && text.charCodeAt(pos + 1) === CharacterCodes.slash + && text.charCodeAt(pos + 2) !== CharacterCodes.asterisk ) { return pos += 2, token = SyntaxKind.LessThanSlashToken; } @@ -2278,7 +2453,10 @@ export function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean } function reScanInvalidIdentifier(): SyntaxKind { - Debug.assert(token === SyntaxKind.Unknown, "'reScanInvalidIdentifier' should only be called when the current token is 'SyntaxKind.Unknown'."); + Debug.assert( + token === SyntaxKind.Unknown, + "'reScanInvalidIdentifier' should only be called when the current token is 'SyntaxKind.Unknown'.", + ); pos = tokenStart = fullStartPos; tokenFlags = 0; const ch = codePointAt(text, pos); @@ -2327,7 +2505,10 @@ export function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean } function reScanAsteriskEqualsToken(): SyntaxKind { - Debug.assert(token === SyntaxKind.AsteriskEqualsToken, "'reScanAsteriskEqualsToken' should only be called on a '*='"); + Debug.assert( + token === SyntaxKind.AsteriskEqualsToken, + "'reScanAsteriskEqualsToken' should only be called on a '*='", + ); pos = tokenStart + 1; return token = SyntaxKind.EqualsToken; } @@ -2458,7 +2639,10 @@ export function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean } function reScanQuestionToken(): SyntaxKind { - Debug.assert(token === SyntaxKind.QuestionQuestionToken, "'reScanQuestionToken' should only be called on a '??'"); + Debug.assert( + token === SyntaxKind.QuestionQuestionToken, + "'reScanQuestionToken' should only be called on a '??'", + ); pos = tokenStart + 1; return token = SyntaxKind.QuestionToken; } @@ -2587,7 +2771,11 @@ export function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean if (pos >= end) { return token = SyntaxKind.EndOfFileToken; } - for (let ch = text.charCodeAt(pos); pos < end && (!isLineBreak(ch) && ch !== CharacterCodes.backtick); ch = codePointAt(text, ++pos)) { + for ( + let ch = text.charCodeAt(pos); + pos < end && (!isLineBreak(ch) && ch !== CharacterCodes.backtick); + ch = codePointAt(text, ++pos) + ) { if (!inBackticks) { if (ch === CharacterCodes.openBrace) { break; @@ -2684,7 +2872,10 @@ export function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean if (isIdentifierStart(ch, languageVersion)) { let char = ch; - while (pos < end && isIdentifierPart(char = codePointAt(text, pos), languageVersion) || text.charCodeAt(pos) === CharacterCodes.minus) pos += charSize(char); + while ( + pos < end && isIdentifierPart(char = codePointAt(text, pos), languageVersion) + || text.charCodeAt(pos) === CharacterCodes.minus + ) pos += charSize(char); tokenValue = text.substring(tokenStart, pos); if (char === CharacterCodes.backslash) { tokenValue += scanIdentifierParts(); @@ -2793,25 +2984,26 @@ export function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean } /** @internal */ -const codePointAt: (s: string, i: number) => number = (String.prototype as any).codePointAt ? (s, i) => (s as any).codePointAt(i) : function codePointAt(str, i): number { - // from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/codePointAt - const size = str.length; - // Account for out-of-bounds indices: - if (i < 0 || i >= size) { - return undefined!; // String.codePointAt returns `undefined` for OOB indexes - } - // Get the first code unit - const first = str.charCodeAt(i); - // check if it's the start of a surrogate pair - if (first >= 0xD800 && first <= 0xDBFF && size > i + 1) { // high surrogate and there is a next code unit - const second = str.charCodeAt(i + 1); - if (second >= 0xDC00 && second <= 0xDFFF) { // low surrogate - // https://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae - return (first - 0xD800) * 0x400 + second - 0xDC00 + 0x10000; - } - } - return first; -}; +const codePointAt: (s: string, i: number) => number = (String.prototype as any).codePointAt + ? (s, i) => (s as any).codePointAt(i) : function codePointAt(str, i): number { + // from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/codePointAt + const size = str.length; + // Account for out-of-bounds indices: + if (i < 0 || i >= size) { + return undefined!; // String.codePointAt returns `undefined` for OOB indexes + } + // Get the first code unit + const first = str.charCodeAt(i); + // check if it's the start of a surrogate pair + if (first >= 0xD800 && first <= 0xDBFF && size > i + 1) { // high surrogate and there is a next code unit + const second = str.charCodeAt(i + 1); + if (second >= 0xDC00 && second <= 0xDFFF) { // low surrogate + // https://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae + return (first - 0xD800) * 0x400 + second - 0xDC00 + 0x10000; + } + } + return first; + }; /** @internal */ function charSize(ch: number) { @@ -2835,7 +3027,8 @@ function utf16EncodeAsStringFallback(codePoint: number) { return String.fromCharCode(codeUnit1, codeUnit2); } -const utf16EncodeAsStringWorker: (codePoint: number) => string = (String as any).fromCodePoint ? codePoint => (String as any).fromCodePoint(codePoint) : utf16EncodeAsStringFallback; +const utf16EncodeAsStringWorker: (codePoint: number) => string = (String as any).fromCodePoint + ? codePoint => (String as any).fromCodePoint(codePoint) : utf16EncodeAsStringFallback; /** @internal */ export function utf16EncodeAsString(codePoint: number) { diff --git a/src/compiler/semver.ts b/src/compiler/semver.ts index 1c8af4fccab61..84f10fb86939d 100644 --- a/src/compiler/semver.ts +++ b/src/compiler/semver.ts @@ -54,8 +54,20 @@ export class Version { readonly build: readonly string[]; constructor(text: string); - constructor(major: number, minor?: number, patch?: number, prerelease?: string | readonly string[], build?: string | readonly string[]); - constructor(major: number | string, minor = 0, patch = 0, prerelease: string | readonly string[] = "", build: string | readonly string[] = "") { + constructor( + major: number, + minor?: number, + patch?: number, + prerelease?: string | readonly string[], + build?: string | readonly string[], + ); + constructor( + major: number | string, + minor = 0, + patch = 0, + prerelease: string | readonly string[] = "", + build: string | readonly string[] = "", + ) { if (typeof major === "string") { const result = Debug.checkDefined(tryParseComponents(major), "Invalid version"); ({ major, minor, patch, prerelease, build } = result); @@ -120,7 +132,15 @@ export class Version { } } - with(fields: { major?: number; minor?: number; patch?: number; prerelease?: string | readonly string[]; build?: string | readonly string[]; }) { + with( + fields: { + major?: number; + minor?: number; + patch?: number; + prerelease?: string | readonly string[]; + build?: string | readonly string[]; + }, + ) { const { major = this.major, minor = this.minor, @@ -258,7 +278,8 @@ const whitespaceRegExp = /\s+/g; // build ::= parts // parts ::= part ( '.' part ) * // part ::= nr | [-0-9A-Za-z]+ -const partialRegExp = /^([xX*0]|[1-9]\d*)(?:\.([xX*0]|[1-9]\d*)(?:\.([xX*0]|[1-9]\d*)(?:-([a-z0-9-.]+))?(?:\+([a-z0-9-.]+))?)?)?$/i; +const partialRegExp = + /^([xX*0]|[1-9]\d*)(?:\.([xX*0]|[1-9]\d*)(?:\.([xX*0]|[1-9]\d*)(?:-([a-z0-9-.]+))?(?:\+([a-z0-9-.]+))?)?)?$/i; // https://github.com/npm/node-semver#range-grammar // @@ -323,9 +344,9 @@ function parseHyphen(left: string, right: string, comparators: Comparator[]) { if (!isWildcard(rightResult.major)) { comparators.push( - isWildcard(rightResult.minor) ? createComparator("<", rightResult.version.increment("major")) : - isWildcard(rightResult.patch) ? createComparator("<", rightResult.version.increment("minor")) : - createComparator("<=", rightResult.version), + isWildcard(rightResult.minor) ? createComparator("<", rightResult.version.increment("major")) + : isWildcard(rightResult.patch) ? createComparator("<", rightResult.version.increment("minor")) + : createComparator("<=", rightResult.version), ); } @@ -344,8 +365,8 @@ function parseComparator(operator: string, text: string, comparators: Comparator comparators.push(createComparator( "<", version.increment( - isWildcard(minor) ? "major" : - "minor", + isWildcard(minor) ? "major" + : "minor", ), )); break; @@ -354,32 +375,46 @@ function parseComparator(operator: string, text: string, comparators: Comparator comparators.push(createComparator( "<", version.increment( - version.major > 0 || isWildcard(minor) ? "major" : - version.minor > 0 || isWildcard(patch) ? "minor" : - "patch", + version.major > 0 || isWildcard(minor) ? "major" + : version.minor > 0 || isWildcard(patch) ? "minor" + : "patch", ), )); break; case "<": case ">=": comparators.push( - isWildcard(minor) || isWildcard(patch) ? createComparator(operator, version.with({ prerelease: "0" })) : - createComparator(operator, version), + isWildcard(minor) || isWildcard(patch) + ? createComparator(operator, version.with({ prerelease: "0" })) + : createComparator(operator, version), ); break; case "<=": case ">": comparators.push( - isWildcard(minor) ? createComparator(operator === "<=" ? "<" : ">=", version.increment("major").with({ prerelease: "0" })) : - isWildcard(patch) ? createComparator(operator === "<=" ? "<" : ">=", version.increment("minor").with({ prerelease: "0" })) : - createComparator(operator, version), + isWildcard(minor) + ? createComparator( + operator === "<=" ? "<" : ">=", + version.increment("major").with({ prerelease: "0" }), + ) + : isWildcard(patch) + ? createComparator( + operator === "<=" ? "<" : ">=", + version.increment("minor").with({ prerelease: "0" }), + ) + : createComparator(operator, version), ); break; case "=": case undefined: if (isWildcard(minor) || isWildcard(patch)) { comparators.push(createComparator(">=", version.with({ prerelease: "0" }))); - comparators.push(createComparator("<", version.increment(isWildcard(minor) ? "major" : "minor").with({ prerelease: "0" }))); + comparators.push( + createComparator( + "<", + version.increment(isWildcard(minor) ? "major" : "minor").with({ prerelease: "0" }), + ), + ); } else { comparators.push(createComparator("=", version)); diff --git a/src/compiler/sourcemap.ts b/src/compiler/sourcemap.ts index fedc66d6e77c9..6be26771c586c 100644 --- a/src/compiler/sourcemap.ts +++ b/src/compiler/sourcemap.ts @@ -34,7 +34,13 @@ export interface SourceMapGeneratorOptions { } /** @internal */ -export function createSourceMapGenerator(host: EmitHost, file: string, sourceRoot: string, sourcesDirectoryPath: string, generatorOptions: SourceMapGeneratorOptions): SourceMapGenerator { +export function createSourceMapGenerator( + host: EmitHost, + file: string, + sourceRoot: string, + sourcesDirectoryPath: string, + generatorOptions: SourceMapGeneratorOptions, +): SourceMapGenerator { // Why var? It avoids TDZ checks in the runtime which can be costly. // See: https://github.com/microsoft/TypeScript/issues/52924 /* eslint-disable no-var */ @@ -86,7 +92,13 @@ export function createSourceMapGenerator(host: EmitHost, file: string, sourceRoo function addSource(fileName: string) { enter(); - const source = getRelativePathToDirectoryOrUrl(sourcesDirectoryPath, fileName, host.getCurrentDirectory(), host.getCanonicalFileName, /*isAbsolutePathAnUrl*/ true); + const source = getRelativePathToDirectoryOrUrl( + sourcesDirectoryPath, + fileName, + host.getCurrentDirectory(), + host.getCanonicalFileName, + /*isAbsolutePathAnUrl*/ true, + ); let sourceIndex = sourceToSourceIndexMap.get(source); if (sourceIndex === undefined) { @@ -132,7 +144,11 @@ export function createSourceMapGenerator(host: EmitHost, file: string, sourceRoo || pendingGeneratedCharacter !== generatedCharacter; } - function isBacktrackingSourcePosition(sourceIndex: number | undefined, sourceLine: number | undefined, sourceCharacter: number | undefined) { + function isBacktrackingSourcePosition( + sourceIndex: number | undefined, + sourceLine: number | undefined, + sourceCharacter: number | undefined, + ) { return sourceIndex !== undefined && sourceLine !== undefined && sourceCharacter !== undefined @@ -141,7 +157,14 @@ export function createSourceMapGenerator(host: EmitHost, file: string, sourceRoo || pendingSourceLine === sourceLine && pendingSourceCharacter > sourceCharacter); } - function addMapping(generatedLine: number, generatedCharacter: number, sourceIndex?: number, sourceLine?: number, sourceCharacter?: number, nameIndex?: number) { + function addMapping( + generatedLine: number, + generatedCharacter: number, + sourceIndex?: number, + sourceLine?: number, + sourceCharacter?: number, + nameIndex?: number, + ) { Debug.assert(generatedLine >= pendingGeneratedLine, "generatedLine cannot backtrack"); Debug.assert(generatedCharacter >= 0, "generatedCharacter cannot be negative"); Debug.assert(sourceIndex === undefined || sourceIndex >= 0, "sourceIndex cannot be negative"); @@ -150,8 +173,8 @@ export function createSourceMapGenerator(host: EmitHost, file: string, sourceRoo enter(); // If this location wasn't recorded or the location in source is going backwards, record the mapping if ( - isNewGeneratedPosition(generatedLine, generatedCharacter) || - isBacktrackingSourcePosition(sourceIndex, sourceLine, sourceCharacter) + isNewGeneratedPosition(generatedLine, generatedCharacter) + || isBacktrackingSourcePosition(sourceIndex, sourceLine, sourceCharacter) ) { commitPendingMapping(); pendingGeneratedLine = generatedLine; @@ -174,7 +197,14 @@ export function createSourceMapGenerator(host: EmitHost, file: string, sourceRoo exit(); } - function appendSourceMap(generatedLine: number, generatedCharacter: number, map: RawSourceMap, sourceMapPath: string, start?: LineAndCharacter, end?: LineAndCharacter) { + function appendSourceMap( + generatedLine: number, + generatedCharacter: number, + map: RawSourceMap, + sourceMapPath: string, + start?: LineAndCharacter, + end?: LineAndCharacter, + ) { Debug.assert(generatedLine >= pendingGeneratedLine, "generatedLine cannot backtrack"); Debug.assert(generatedCharacter >= 0, "generatedCharacter cannot be negative"); enter(); @@ -185,8 +215,8 @@ export function createSourceMapGenerator(host: EmitHost, file: string, sourceRoo for (const raw of mappingIterator) { if ( end && ( - raw.generatedLine > end.line || - (raw.generatedLine === end.line && raw.generatedCharacter > end.character) + raw.generatedLine > end.line + || (raw.generatedLine === end.line && raw.generatedCharacter > end.character) ) ) { break; @@ -194,8 +224,8 @@ export function createSourceMapGenerator(host: EmitHost, file: string, sourceRoo if ( start && ( - raw.generatedLine < start.line || - (start.line === raw.generatedLine && raw.generatedCharacter < start.character) + raw.generatedLine < start.line + || (start.line === raw.generatedLine && raw.generatedCharacter < start.character) ) ) { continue; @@ -231,9 +261,18 @@ export function createSourceMapGenerator(host: EmitHost, file: string, sourceRoo const rawGeneratedLine = raw.generatedLine - (start ? start.line : 0); const newGeneratedLine = rawGeneratedLine + generatedLine; - const rawGeneratedCharacter = start && start.line === raw.generatedLine ? raw.generatedCharacter - start.character : raw.generatedCharacter; - const newGeneratedCharacter = rawGeneratedLine === 0 ? rawGeneratedCharacter + generatedCharacter : rawGeneratedCharacter; - addMapping(newGeneratedLine, newGeneratedCharacter, newSourceIndex, newSourceLine, newSourceCharacter, newNameIndex); + const rawGeneratedCharacter = start && start.line === raw.generatedLine + ? raw.generatedCharacter - start.character : raw.generatedCharacter; + const newGeneratedCharacter = rawGeneratedLine === 0 ? rawGeneratedCharacter + generatedCharacter + : rawGeneratedCharacter; + addMapping( + newGeneratedLine, + newGeneratedCharacter, + newSourceIndex, + newSourceLine, + newSourceCharacter, + newNameIndex, + ); } exit(); } @@ -415,7 +454,8 @@ export function isRawSourceMap(x: any): x is RawSourceMap { && typeof x.mappings === "string" && isArray(x.sources) && every(x.sources, isString) && (x.sourceRoot === undefined || x.sourceRoot === null || typeof x.sourceRoot === "string") - && (x.sourcesContent === undefined || x.sourcesContent === null || isArray(x.sourcesContent) && every(x.sourcesContent, isStringOrNull)) + && (x.sourcesContent === undefined || x.sourcesContent === null + || isArray(x.sourcesContent) && every(x.sourcesContent, isStringOrNull)) && (x.names === undefined || x.names === null || isArray(x.names) && every(x.names, isString)); } /* eslint-enable no-null/no-null */ @@ -512,12 +552,16 @@ export function decodeMappings(mappings: string): MappingsDecoder { sourceIndex += base64VLQFormatDecode(); if (hasReportedError()) return stopIterating(); if (sourceIndex < 0) return setErrorAndStopIterating("Invalid sourceIndex found"); - if (isSourceMappingSegmentEnd()) return setErrorAndStopIterating("Unsupported Format: No entries after sourceIndex"); + if (isSourceMappingSegmentEnd()) { + return setErrorAndStopIterating("Unsupported Format: No entries after sourceIndex"); + } sourceLine += base64VLQFormatDecode(); if (hasReportedError()) return stopIterating(); if (sourceLine < 0) return setErrorAndStopIterating("Invalid sourceLine found"); - if (isSourceMappingSegmentEnd()) return setErrorAndStopIterating("Unsupported Format: No entries after sourceLine"); + if (isSourceMappingSegmentEnd()) { + return setErrorAndStopIterating("Unsupported Format: No entries after sourceLine"); + } sourceCharacter += base64VLQFormatDecode(); if (hasReportedError()) return stopIterating(); @@ -529,7 +573,9 @@ export function decodeMappings(mappings: string): MappingsDecoder { if (hasReportedError()) return stopIterating(); if (nameIndex < 0) return setErrorAndStopIterating("Invalid nameIndex found"); - if (!isSourceMappingSegmentEnd()) return setErrorAndStopIterating("Unsupported Error Format: Entries after nameIndex"); + if (!isSourceMappingSegmentEnd()) { + return setErrorAndStopIterating("Unsupported Error Format: Entries after nameIndex"); + } } } @@ -577,9 +623,9 @@ export function decodeMappings(mappings: string): MappingsDecoder { } function isSourceMappingSegmentEnd() { - return (pos === mappings.length || - mappings.charCodeAt(pos) === CharacterCodes.comma || - mappings.charCodeAt(pos) === CharacterCodes.semicolon); + return (pos === mappings.length + || mappings.charCodeAt(pos) === CharacterCodes.comma + || mappings.charCodeAt(pos) === CharacterCodes.semicolon); } function base64VLQFormatDecode(): number { @@ -588,7 +634,9 @@ export function decodeMappings(mappings: string): MappingsDecoder { let value = 0; for (; moreDigits; pos++) { - if (pos >= mappings.length) return setError("Error in decoding base64VLQFormatDecode, past the mapping string"), -1; + if (pos >= mappings.length) { + return setError("Error in decoding base64VLQFormatDecode, past the mapping string"), -1; + } // 6 digit number const currentByte = base64FormatDecode(mappings.charCodeAt(pos)); @@ -636,21 +684,21 @@ export function isSourceMapping(mapping: Mapping): mapping is SourceMapping { } function base64FormatEncode(value: number) { - return value >= 0 && value < 26 ? CharacterCodes.A + value : - value >= 26 && value < 52 ? CharacterCodes.a + value - 26 : - value >= 52 && value < 62 ? CharacterCodes._0 + value - 52 : - value === 62 ? CharacterCodes.plus : - value === 63 ? CharacterCodes.slash : - Debug.fail(`${value}: not a base64 value`); + return value >= 0 && value < 26 ? CharacterCodes.A + value + : value >= 26 && value < 52 ? CharacterCodes.a + value - 26 + : value >= 52 && value < 62 ? CharacterCodes._0 + value - 52 + : value === 62 ? CharacterCodes.plus + : value === 63 ? CharacterCodes.slash + : Debug.fail(`${value}: not a base64 value`); } function base64FormatDecode(ch: number) { - return ch >= CharacterCodes.A && ch <= CharacterCodes.Z ? ch - CharacterCodes.A : - ch >= CharacterCodes.a && ch <= CharacterCodes.z ? ch - CharacterCodes.a + 26 : - ch >= CharacterCodes._0 && ch <= CharacterCodes._9 ? ch - CharacterCodes._0 + 52 : - ch === CharacterCodes.plus ? 62 : - ch === CharacterCodes.slash ? 63 : - -1; + return ch >= CharacterCodes.A && ch <= CharacterCodes.Z ? ch - CharacterCodes.A + : ch >= CharacterCodes.a && ch <= CharacterCodes.z ? ch - CharacterCodes.a + 26 + : ch >= CharacterCodes._0 && ch <= CharacterCodes._9 ? ch - CharacterCodes._0 + 52 + : ch === CharacterCodes.plus ? 62 + : ch === CharacterCodes.slash ? 63 + : -1; } interface MappedPosition { @@ -698,13 +746,19 @@ function getGeneratedPositionOfMapping(value: MappedPosition) { } /** @internal */ -export function createDocumentPositionMapper(host: DocumentPositionMapperHost, map: RawSourceMap, mapPath: string): DocumentPositionMapper { +export function createDocumentPositionMapper( + host: DocumentPositionMapperHost, + map: RawSourceMap, + mapPath: string, +): DocumentPositionMapper { const mapDirectory = getDirectoryPath(mapPath); const sourceRoot = map.sourceRoot ? getNormalizedAbsolutePath(map.sourceRoot, mapDirectory) : mapDirectory; const generatedAbsoluteFilePath = getNormalizedAbsolutePath(map.file, mapDirectory); const generatedFile = host.getSourceFileLike(generatedAbsoluteFilePath); const sourceFileAbsolutePaths = map.sources.map(source => getNormalizedAbsolutePath(source, sourceRoot)); - const sourceToSourceIndexMap = new Map(sourceFileAbsolutePaths.map((source, i) => [host.getCanonicalFileName(source), i])); + const sourceToSourceIndexMap = new Map( + sourceFileAbsolutePaths.map((source, i) => [host.getCanonicalFileName(source), i]), + ); let decodedMappings: readonly MappedPosition[] | undefined; let generatedMappings: SortedReadonlyArray | undefined; let sourceMappings: readonly SortedReadonlyArray[] | undefined; @@ -716,7 +770,12 @@ export function createDocumentPositionMapper(host: DocumentPositionMapperHost, m function processMapping(mapping: Mapping): MappedPosition { const generatedPosition = generatedFile !== undefined - ? getPositionOfLineAndCharacter(generatedFile, mapping.generatedLine, mapping.generatedCharacter, /*allowEdits*/ true) + ? getPositionOfLineAndCharacter( + generatedFile, + mapping.generatedLine, + mapping.generatedCharacter, + /*allowEdits*/ true, + ) : -1; let source: string | undefined; let sourcePosition: number | undefined; @@ -724,7 +783,12 @@ export function createDocumentPositionMapper(host: DocumentPositionMapperHost, m const sourceFile = host.getSourceFileLike(sourceFileAbsolutePaths[mapping.sourceIndex]); source = map.sources[mapping.sourceIndex]; sourcePosition = sourceFile !== undefined - ? getPositionOfLineAndCharacter(sourceFile, mapping.sourceLine, mapping.sourceCharacter, /*allowEdits*/ true) + ? getPositionOfLineAndCharacter( + sourceFile, + mapping.sourceLine, + mapping.sourceCharacter, + /*allowEdits*/ true, + ) : -1; } return { @@ -762,7 +826,9 @@ export function createDocumentPositionMapper(host: DocumentPositionMapperHost, m if (!list) lists[mapping.sourceIndex] = list = []; list.push(mapping); } - sourceMappings = lists.map(list => sortAndDeduplicate(list, compareSourcePositions, sameMappedPosition)); + sourceMappings = lists.map(list => + sortAndDeduplicate(list, compareSourcePositions, sameMappedPosition) + ); } return sourceMappings[sourceIndex]; } diff --git a/src/compiler/sys.ts b/src/compiler/sys.ts index 14e6f04b77afa..7ed73946a6e38 100644 --- a/src/compiler/sys.ts +++ b/src/compiler/sys.ts @@ -100,9 +100,19 @@ export enum PollingInterval { } /** @internal */ -export type HostWatchFile = (fileName: string, callback: FileWatcherCallback, pollingInterval: PollingInterval, options: WatchOptions | undefined) => FileWatcher; +export type HostWatchFile = ( + fileName: string, + callback: FileWatcherCallback, + pollingInterval: PollingInterval, + options: WatchOptions | undefined, +) => FileWatcher; /** @internal */ -export type HostWatchDirectory = (fileName: string, callback: DirectoryWatcherCallback, recursive: boolean, options: WatchOptions | undefined) => FileWatcher; +export type HostWatchDirectory = ( + fileName: string, + callback: DirectoryWatcherCallback, + recursive: boolean, + options: WatchOptions | undefined, +) => FileWatcher; /** @internal */ export const missingFileModifiedTime = new Date(0); // Any subsequent modification will occur after this time @@ -136,8 +146,10 @@ function setCustomPollingValues(system: System) { return; } const pollingIntervalChanged = setCustomLevels("TSC_WATCH_POLLINGINTERVAL", PollingInterval); - pollingChunkSize = getCustomPollingBasedLevels("TSC_WATCH_POLLINGCHUNKSIZE", defaultChunkLevels) || pollingChunkSize; - unchangedPollThresholds = getCustomPollingBasedLevels("TSC_WATCH_UNCHANGEDPOLLTHRESHOLDS", defaultChunkLevels) || unchangedPollThresholds; + pollingChunkSize = getCustomPollingBasedLevels("TSC_WATCH_POLLINGCHUNKSIZE", defaultChunkLevels) + || pollingChunkSize; + unchangedPollThresholds = getCustomPollingBasedLevels("TSC_WATCH_UNCHANGEDPOLLTHRESHOLDS", defaultChunkLevels) + || unchangedPollThresholds; function getLevel(envVar: string, level: keyof Levels) { return system.getEnvironmentVariable(`${envVar}_${level.toUpperCase()}`); @@ -175,8 +187,8 @@ function setCustomPollingValues(system: System) { function getCustomPollingBasedLevels(baseVariable: string, defaultLevels: Levels) { const customLevels = getCustomLevels(baseVariable); - return (pollingIntervalChanged || customLevels) && - createPollingIntervalBasedLevels(customLevels ? { ...defaultLevels, ...customLevels } : defaultLevels); + return (pollingIntervalChanged || customLevels) + && createPollingIntervalBasedLevels(customLevels ? { ...defaultLevels, ...customLevels } : defaultLevels); } } @@ -259,7 +271,11 @@ function createDynamicPriorityPollingWatchFile(host: { const highPollingIntervalQueue = createPollingIntervalQueue(PollingInterval.High); return watchFile; - function watchFile(fileName: string, callback: FileWatcherCallback, defaultPollingInterval: PollingInterval): FileWatcher { + function watchFile( + fileName: string, + callback: FileWatcherCallback, + defaultPollingInterval: PollingInterval, + ): FileWatcher { const file: WatchedFileWithUnchangedPolls = { fileName, callback, @@ -288,7 +304,12 @@ function createDynamicPriorityPollingWatchFile(host: { } function pollPollingIntervalQueue(_timeoutType: string, queue: PollingIntervalQueue) { - queue.pollIndex = pollQueue(queue, queue.pollingInterval, queue.pollIndex, pollingChunkSize[queue.pollingInterval]); + queue.pollIndex = pollQueue( + queue, + queue.pollingInterval, + queue.pollIndex, + pollingChunkSize[queue.pollingInterval], + ); // Set the next polling index and timeout if (queue.length) { scheduleNextPoll(queue.pollingInterval); @@ -312,7 +333,12 @@ function createDynamicPriorityPollingWatchFile(host: { } } - function pollQueue(queue: (WatchedFileWithUnchangedPolls | undefined)[], pollingInterval: PollingInterval, pollIndex: number, chunkSize: number) { + function pollQueue( + queue: (WatchedFileWithUnchangedPolls | undefined)[], + pollingInterval: PollingInterval, + pollIndex: number, + chunkSize: number, + ) { return pollWatchedFileQueue( host, queue, @@ -342,7 +368,10 @@ function createDynamicPriorityPollingWatchFile(host: { else if (pollingInterval !== PollingInterval.High) { watchedFile.unchangedPolls++; queue[pollIndex] = undefined; - addToPollingIntervalQueue(watchedFile, pollingInterval === PollingInterval.Low ? PollingInterval.Medium : PollingInterval.High); + addToPollingIntervalQueue( + watchedFile, + pollingInterval === PollingInterval.Low ? PollingInterval.Medium : PollingInterval.High, + ); } } } @@ -375,23 +404,36 @@ function createDynamicPriorityPollingWatchFile(host: { } function scheduleNextPoll(pollingInterval: PollingInterval) { - pollingIntervalQueue(pollingInterval).pollScheduled = host.setTimeout(pollingInterval === PollingInterval.Low ? pollLowPollingIntervalQueue : pollPollingIntervalQueue, pollingInterval, pollingInterval === PollingInterval.Low ? "pollLowPollingIntervalQueue" : "pollPollingIntervalQueue", pollingIntervalQueue(pollingInterval)); + pollingIntervalQueue(pollingInterval).pollScheduled = host.setTimeout( + pollingInterval === PollingInterval.Low ? pollLowPollingIntervalQueue : pollPollingIntervalQueue, + pollingInterval, + pollingInterval === PollingInterval.Low ? "pollLowPollingIntervalQueue" : "pollPollingIntervalQueue", + pollingIntervalQueue(pollingInterval), + ); } } -function createUseFsEventsOnParentDirectoryWatchFile(fsWatch: FsWatch, useCaseSensitiveFileNames: boolean): HostWatchFile { +function createUseFsEventsOnParentDirectoryWatchFile( + fsWatch: FsWatch, + useCaseSensitiveFileNames: boolean, +): HostWatchFile { // One file can have multiple watchers const fileWatcherCallbacks = createMultiMap(); const dirWatchers = new Map(); const toCanonicalName = createGetCanonicalFileName(useCaseSensitiveFileNames); return nonPollingWatchFile; - function nonPollingWatchFile(fileName: string, callback: FileWatcherCallback, _pollingInterval: PollingInterval, fallbackOptions: WatchOptions | undefined): FileWatcher { + function nonPollingWatchFile( + fileName: string, + callback: FileWatcherCallback, + _pollingInterval: PollingInterval, + fallbackOptions: WatchOptions | undefined, + ): FileWatcher { const filePath = toCanonicalName(fileName); fileWatcherCallbacks.add(filePath, callback); const dirPath = getDirectoryPath(filePath) || "."; - const watcher = dirWatchers.get(dirPath) || - createDirectoryWatcher(getDirectoryPath(fileName) || ".", dirPath, fallbackOptions); + const watcher = dirWatchers.get(dirPath) + || createDirectoryWatcher(getDirectoryPath(fileName) || ".", dirPath, fallbackOptions); watcher.referenceCount++; return { close: () => { @@ -492,7 +534,8 @@ function createSingleWatcherPerName cache.get(path)?.callbacks.slice().forEach(cb => cb(param1, param2, param3)) + (param1: any, param2: never, param3: any) => + cache.get(path)?.callbacks.slice().forEach(cb => cb(param1, param2, param3)) ) as T, ), callbacks: [callback], @@ -590,21 +633,28 @@ function createDirectoryWatcherSupportingRecursive({ const cache = new Map(); const callbackCache = createMultiMap(); - const cacheToUpdateChildWatches = new Map(); + const cacheToUpdateChildWatches = new Map< + Path, + { dirName: string; options: WatchOptions | undefined; fileNames: string[]; } + >(); let timerToUpdateChildWatches: any; const filePathComparer = getStringComparer(!useCaseSensitiveFileNames); const toCanonicalFilePath = createGetCanonicalFileName(useCaseSensitiveFileNames); return (dirName, callback, recursive, options) => - recursive ? - createDirectoryWatcher(dirName, options, callback) : - watchDirectory(dirName, callback, recursive, options); + recursive + ? createDirectoryWatcher(dirName, options, callback) + : watchDirectory(dirName, callback, recursive, options); /** * Create the directory watcher for the dirPath. */ - function createDirectoryWatcher(dirName: string, options: WatchOptions | undefined, callback?: DirectoryWatcherCallback): ChildDirectoryWatcher { + function createDirectoryWatcher( + dirName: string, + options: WatchOptions | undefined, + callback?: DirectoryWatcherCallback, + ): ChildDirectoryWatcher { const dirPath = toCanonicalFilePath(dirName) as Path; let directoryWatcher = cache.get(dirPath); if (directoryWatcher) { @@ -674,7 +724,10 @@ function createDirectoryWatcherSupportingRecursive({ // Call the actual callback callbackCache.forEach((callbacks, rootDirName) => { if (invokeMap && invokeMap.get(rootDirName) === true) return; - if (rootDirName === dirPath || (startsWith(dirPath, rootDirName) && dirPath[rootDirName.length] === directorySeparator)) { + if ( + rootDirName === dirPath + || (startsWith(dirPath, rootDirName) && dirPath[rootDirName.length] === directorySeparator) + ) { if (invokeMap) { if (fileNames) { const existing = invokeMap.get(rootDirName); @@ -696,7 +749,12 @@ function createDirectoryWatcherSupportingRecursive({ }); } - function nonSyncUpdateChildWatches(dirName: string, dirPath: Path, fileName: string, options: WatchOptions | undefined) { + function nonSyncUpdateChildWatches( + dirName: string, + dirPath: Path, + fileName: string, + options: WatchOptions | undefined, + ) { // Iterate through existing children and update the watches if needed const parentWatcher = cache.get(dirPath); if (parentWatcher && fileSystemEntryExists(dirName, FileSystemEntryKind.Directory)) { @@ -710,7 +768,12 @@ function createDirectoryWatcherSupportingRecursive({ removeChildWatches(parentWatcher); } - function scheduleUpdateChildWatches(dirName: string, dirPath: Path, fileName: string, options: WatchOptions | undefined) { + function scheduleUpdateChildWatches( + dirName: string, + dirPath: Path, + fileName: string, + options: WatchOptions | undefined, + ) { const existing = cacheToUpdateChildWatches.get(dirPath); if (existing) { existing.fileNames.push(fileName); @@ -758,7 +821,9 @@ function createDirectoryWatcherSupportingRecursive({ }); const elapsed = timestamp() - start; - sysLog(`sysLog:: Elapsed:: ${elapsed}ms:: onTimerToUpdateChildWatches:: ${cacheToUpdateChildWatches.size} ${timerToUpdateChildWatches}`); + sysLog( + `sysLog:: Elapsed:: ${elapsed}ms:: onTimerToUpdateChildWatches:: ${cacheToUpdateChildWatches.size} ${timerToUpdateChildWatches}`, + ); } function removeChildWatches(parentWatcher: HostDirectoryWatcher | undefined) { @@ -777,12 +842,15 @@ function createDirectoryWatcherSupportingRecursive({ if (!parentWatcher) return false; let newChildWatches: ChildDirectoryWatcher[] | undefined; const hasChanges = enumerateInsertsAndDeletes( - fileSystemEntryExists(parentDir, FileSystemEntryKind.Directory) ? mapDefined(getAccessibleSortedChildDirectories(parentDir), child => { - const childFullName = getNormalizedAbsolutePath(child, parentDir); - // Filter our the symbolic link directories since those arent included in recursive watch - // which is same behaviour when recursive: true is passed to fs.watch - return !isIgnoredPath(childFullName, options) && filePathComparer(childFullName, normalizePath(realpath(childFullName))) === Comparison.EqualTo ? childFullName : undefined; - }) : emptyArray, + fileSystemEntryExists(parentDir, FileSystemEntryKind.Directory) + ? mapDefined(getAccessibleSortedChildDirectories(parentDir), child => { + const childFullName = getNormalizedAbsolutePath(child, parentDir); + // Filter our the symbolic link directories since those arent included in recursive watch + // which is same behaviour when recursive: true is passed to fs.watch + return !isIgnoredPath(childFullName, options) + && filePathComparer(childFullName, normalizePath(realpath(childFullName))) + === Comparison.EqualTo ? childFullName : undefined; + }) : emptyArray, parentWatcher.childWatches, (child, childWatcher) => filePathComparer(child, childWatcher.dirName), createAndAddChildDirectoryWatcher, @@ -809,8 +877,8 @@ function createDirectoryWatcherSupportingRecursive({ } function isIgnoredPath(path: string, options: WatchOptions | undefined) { - return some(ignoredPaths, searchPath => isInPath(path, searchPath)) || - isIgnoredByWatchOptions(path, options, useCaseSensitiveFileNames, getCurrentDirectory); + return some(ignoredPaths, searchPath => isInPath(path, searchPath)) + || isIgnoredByWatchOptions(path, options, useCaseSensitiveFileNames, getCurrentDirectory); } function isInPath(path: string, searchPath: string) { @@ -821,15 +889,30 @@ function createDirectoryWatcherSupportingRecursive({ } /** @internal */ -export type FsWatchCallback = (eventName: "rename" | "change", relativeFileName: string | undefined | null, modifiedTime?: Date) => void; +export type FsWatchCallback = ( + eventName: "rename" | "change", + relativeFileName: string | undefined | null, + modifiedTime?: Date, +) => void; /** @internal */ -export type FsWatch = (fileOrDirectory: string, entryKind: FileSystemEntryKind, callback: FsWatchCallback, recursive: boolean, fallbackPollingInterval: PollingInterval, fallbackOptions: WatchOptions | undefined) => FileWatcher; +export type FsWatch = ( + fileOrDirectory: string, + entryKind: FileSystemEntryKind, + callback: FsWatchCallback, + recursive: boolean, + fallbackPollingInterval: PollingInterval, + fallbackOptions: WatchOptions | undefined, +) => FileWatcher; /** @internal */ export interface FsWatchWorkerWatcher extends FileWatcher { on(eventName: string, listener: () => void): void; } /** @internal */ -export type FsWatchWorker = (fileOrDirectory: string, recursive: boolean, callback: FsWatchCallback) => FsWatchWorkerWatcher; +export type FsWatchWorker = ( + fileOrDirectory: string, + recursive: boolean, + callback: FsWatchCallback, +) => FsWatchWorkerWatcher; /** @internal */ export const enum FileSystemEntryKind { File, @@ -837,7 +920,8 @@ export const enum FileSystemEntryKind { } function createFileWatcherCallback(callback: FsWatchCallback): FileWatcherCallback { - return (_fileName, eventKind, modifiedTime) => callback(eventKind === FileWatcherEventKind.Changed ? "change" : "rename", "", modifiedTime); + return (_fileName, eventKind, modifiedTime) => + callback(eventKind === FileWatcherEventKind.Changed ? "change" : "rename", "", modifiedTime); } function createFsWatchCallbackForFileWatcherCallback( @@ -849,7 +933,11 @@ function createFsWatchCallbackForFileWatcherCallback( if (eventName === "rename") { // Check time stamps rather than file system entry checks modifiedTime ||= getModifiedTime(fileName) || missingFileModifiedTime; - callback(fileName, modifiedTime !== missingFileModifiedTime ? FileWatcherEventKind.Created : FileWatcherEventKind.Deleted, modifiedTime); + callback( + fileName, + modifiedTime !== missingFileModifiedTime ? FileWatcherEventKind.Created : FileWatcherEventKind.Deleted, + modifiedTime, + ); } else { // Change @@ -865,8 +953,8 @@ function isIgnoredByWatchOptions( getCurrentDirectory: System["getCurrentDirectory"], ) { return (options?.excludeDirectories || options?.excludeFiles) && ( - matchesExclude(pathToCheck, options?.excludeFiles, useCaseSensitiveFileNames, getCurrentDirectory()) || - matchesExclude(pathToCheck, options?.excludeDirectories, useCaseSensitiveFileNames, getCurrentDirectory()) + matchesExclude(pathToCheck, options?.excludeFiles, useCaseSensitiveFileNames, getCurrentDirectory()) + || matchesExclude(pathToCheck, options?.excludeDirectories, useCaseSensitiveFileNames, getCurrentDirectory()) ); } @@ -883,8 +971,12 @@ function createFsWatchCallbackForDirectoryWatcherCallback( // event name is "change") if (eventName === "rename") { // When deleting a file, the passed baseFileName is null - const fileName = !relativeFileName ? directoryName : normalizePath(combinePaths(directoryName, relativeFileName)); - if (!relativeFileName || !isIgnoredByWatchOptions(fileName, options, useCaseSensitiveFileNames, getCurrentDirectory)) { + const fileName = !relativeFileName ? directoryName + : normalizePath(combinePaths(directoryName, relativeFileName)); + if ( + !relativeFileName + || !isIgnoredByWatchOptions(fileName, options, useCaseSensitiveFileNames, getCurrentDirectory) + ) { callback(fileName); } } @@ -950,7 +1042,12 @@ export function createSystemWatchFunctions({ watchDirectory, }; - function watchFile(fileName: string, callback: FileWatcherCallback, pollingInterval: PollingInterval, options: WatchOptions | undefined): FileWatcher { + function watchFile( + fileName: string, + callback: FileWatcherCallback, + pollingInterval: PollingInterval, + options: WatchOptions | undefined, + ): FileWatcher { options = updateOptionsForWatchFile(options, useNonPollingWatchers); const watchFileKind = Debug.checkDefined(options.watchFile); switch (watchFileKind) { @@ -961,7 +1058,12 @@ export function createSystemWatchFunctions({ case WatchFileKind.DynamicPriorityPolling: return ensureDynamicPollingWatchFile()(fileName, callback, pollingInterval, /*options*/ undefined); case WatchFileKind.FixedChunkSizePolling: - return ensureFixedChunkSizePollingWatchFile()(fileName, callback, /* pollingInterval */ undefined!, /*options*/ undefined); + return ensureFixedChunkSizePollingWatchFile()( + fileName, + callback, + /* pollingInterval */ undefined!, + /*options*/ undefined, + ); case WatchFileKind.UseFsEvents: return fsWatch( fileName, @@ -973,7 +1075,10 @@ export function createSystemWatchFunctions({ ); case WatchFileKind.UseFsEventsOnParentDirectory: if (!nonPollingWatchFile) { - nonPollingWatchFile = createUseFsEventsOnParentDirectoryWatchFile(fsWatch, useCaseSensitiveFileNames); + nonPollingWatchFile = createUseFsEventsOnParentDirectoryWatchFile( + fsWatch, + useCaseSensitiveFileNames, + ); } return nonPollingWatchFile(fileName, callback, pollingInterval, getFallbackOptions(options)); default: @@ -989,7 +1094,10 @@ export function createSystemWatchFunctions({ return fixedChunkSizePollingWatchFile ||= createFixedChunkSizePollingWatchFile({ getModifiedTime, setTimeout }); } - function updateOptionsForWatchFile(options: WatchOptions | undefined, useNonPollingWatchers?: boolean): WatchOptions { + function updateOptionsForWatchFile( + options: WatchOptions | undefined, + useNonPollingWatchers?: boolean, + ): WatchOptions { if (options && options.watchFile !== undefined) return options; switch (tscWatchFile) { case "PriorityPollingInterval": @@ -1008,11 +1116,15 @@ export function createSystemWatchFunctions({ useNonPollingWatchers = true; // fall through default: - return useNonPollingWatchers ? + return useNonPollingWatchers // Use notifications from FS to watch with falling back to fs.watchFile - generateWatchFileOptions(WatchFileKind.UseFsEventsOnParentDirectory, PollingWatchKind.PriorityInterval, options) : + ? generateWatchFileOptions( + WatchFileKind.UseFsEventsOnParentDirectory, + PollingWatchKind.PriorityInterval, + options, + ) // Default to using fs events - { watchFile: WatchFileKind.UseFsEvents }; + : { watchFile: WatchFileKind.UseFsEvents }; } } @@ -1024,18 +1136,29 @@ export function createSystemWatchFunctions({ const defaultFallbackPolling = options?.fallbackPolling; return { watchFile, - fallbackPolling: defaultFallbackPolling === undefined ? - fallbackPolling : - defaultFallbackPolling, + fallbackPolling: defaultFallbackPolling === undefined + ? fallbackPolling + : defaultFallbackPolling, }; } - function watchDirectory(directoryName: string, callback: DirectoryWatcherCallback, recursive: boolean, options: WatchOptions | undefined): FileWatcher { + function watchDirectory( + directoryName: string, + callback: DirectoryWatcherCallback, + recursive: boolean, + options: WatchOptions | undefined, + ): FileWatcher { if (fsSupportsRecursiveFsWatch) { return fsWatch( directoryName, FileSystemEntryKind.Directory, - createFsWatchCallbackForDirectoryWatcherCallback(directoryName, callback, options, useCaseSensitiveFileNames, getCurrentDirectory), + createFsWatchCallbackForDirectoryWatcherCallback( + directoryName, + callback, + options, + useCaseSensitiveFileNames, + getCurrentDirectory, + ), recursive, PollingInterval.Medium, getFallbackOptions(options), @@ -1057,7 +1180,12 @@ export function createSystemWatchFunctions({ return hostRecursiveDirectoryWatcher(directoryName, callback, recursive, options); } - function nonRecursiveWatchDirectory(directoryName: string, callback: DirectoryWatcherCallback, recursive: boolean, options: WatchOptions | undefined): FileWatcher { + function nonRecursiveWatchDirectory( + directoryName: string, + callback: DirectoryWatcherCallback, + recursive: boolean, + options: WatchOptions | undefined, + ): FileWatcher { Debug.assert(!recursive); const watchDirectoryOptions = updateOptionsForWatchDirectory(options); const watchDirectoryKind = Debug.checkDefined(watchDirectoryOptions.watchDirectory); @@ -1087,7 +1215,13 @@ export function createSystemWatchFunctions({ return fsWatch( directoryName, FileSystemEntryKind.Directory, - createFsWatchCallbackForDirectoryWatcherCallback(directoryName, callback, options, useCaseSensitiveFileNames, getCurrentDirectory), + createFsWatchCallbackForDirectoryWatcherCallback( + directoryName, + callback, + options, + useCaseSensitiveFileNames, + getCurrentDirectory, + ), recursive, PollingInterval.Medium, getFallbackOptions(watchDirectoryOptions), @@ -1110,14 +1244,19 @@ export function createSystemWatchFunctions({ const defaultFallbackPolling = options?.fallbackPolling; return { watchDirectory: WatchDirectoryKind.UseFsEvents, - fallbackPolling: defaultFallbackPolling !== undefined ? - defaultFallbackPolling : - undefined, + fallbackPolling: defaultFallbackPolling !== undefined + ? defaultFallbackPolling + : undefined, }; } } - function pollingWatchFile(fileName: string, callback: FileWatcherCallback, pollingInterval: PollingInterval, options: WatchOptions | undefined) { + function pollingWatchFile( + fileName: string, + callback: FileWatcherCallback, + pollingInterval: PollingInterval, + options: WatchOptions | undefined, + ) { return createSingleWatcherPerName( pollingWatches, useCaseSensitiveFileNames, @@ -1139,7 +1278,15 @@ export function createSystemWatchFunctions({ useCaseSensitiveFileNames, fileOrDirectory, callback, - cb => fsWatchHandlingExistenceOnHost(fileOrDirectory, entryKind, cb, recursive, fallbackPollingInterval, fallbackOptions), + cb => + fsWatchHandlingExistenceOnHost( + fileOrDirectory, + entryKind, + cb, + recursive, + fallbackPollingInterval, + fallbackOptions, + ), ); } @@ -1154,13 +1301,15 @@ export function createSystemWatchFunctions({ let lastDirectoryPartWithDirectorySeparator: string | undefined; let lastDirectoryPart: string | undefined; if (inodeWatching) { - lastDirectoryPartWithDirectorySeparator = fileOrDirectory.substring(fileOrDirectory.lastIndexOf(directorySeparator)); + lastDirectoryPartWithDirectorySeparator = fileOrDirectory.substring( + fileOrDirectory.lastIndexOf(directorySeparator), + ); lastDirectoryPart = lastDirectoryPartWithDirectorySeparator.slice(directorySeparator.length); } /** Watcher for the file system entry depending on whether it is missing or present */ - let watcher: FileWatcher | undefined = !fileSystemEntryExists(fileOrDirectory, entryKind) ? - watchMissingFileSystemEntry() : - watchPresentFileSystemEntry(); + let watcher: FileWatcher | undefined = !fileSystemEntryExists(fileOrDirectory, entryKind) + ? watchMissingFileSystemEntry() + : watchPresentFileSystemEntry(); return { close: () => { // Close the watcher (either existing file system entry watcher or missing file system entry watcher) @@ -1174,7 +1323,11 @@ export function createSystemWatchFunctions({ function updateWatcher(createWatcher: () => FileWatcher) { // If watcher is not closed, update it if (watcher) { - sysLog(`sysLog:: ${fileOrDirectory}:: Changing watcher to ${createWatcher === watchPresentFileSystemEntry ? "Present" : "Missing"}FileSystemEntryWatcher`); + sysLog( + `sysLog:: ${fileOrDirectory}:: Changing watcher to ${ + createWatcher === watchPresentFileSystemEntry ? "Present" : "Missing" + }FileSystemEntryWatcher`, + ); watcher.close(); watcher = createWatcher(); } @@ -1193,9 +1346,9 @@ export function createSystemWatchFunctions({ const presentWatcher = fsWatchWorker( fileOrDirectory, recursive, - inodeWatching ? - callbackChangingToMissingFileSystemEntry : - callback, + inodeWatching + ? callbackChangingToMissingFileSystemEntry + : callback, ); // Watch the missing file or directory or error presentWatcher.on("error", () => { @@ -1214,7 +1367,10 @@ export function createSystemWatchFunctions({ } } - function callbackChangingToMissingFileSystemEntry(event: "rename" | "change", relativeName: string | undefined | null) { + function callbackChangingToMissingFileSystemEntry( + event: "rename" | "change", + relativeName: string | undefined | null, + ) { // In some scenarios, file save operation fires event with fileName.ext~ instead of fileName.ext // To ensure we see the file going missing and coming back up (file delete and then recreated) // and watches being updated correctly we are calling back with fileName.ext as well as fileName.ext~ @@ -1228,17 +1384,20 @@ export function createSystemWatchFunctions({ // because relativeName is not guaranteed to be correct we need to check on each rename with few combinations // Eg on ubuntu while watching app/node_modules the relativeName is "node_modules" which is neither relative nor full path if ( - event === "rename" && - (!relativeName || - relativeName === lastDirectoryPart || - endsWith(relativeName, lastDirectoryPartWithDirectorySeparator!)) + event === "rename" + && (!relativeName + || relativeName === lastDirectoryPart + || endsWith(relativeName, lastDirectoryPartWithDirectorySeparator!)) ) { const modifiedTime = getModifiedTime(fileOrDirectory) || missingFileModifiedTime; if (originalRelativeName) callback(event, originalRelativeName, modifiedTime); callback(event, relativeName, modifiedTime); if (inodeWatching) { // If this was rename event, inode has changed means we need to update watcher - updateWatcher(modifiedTime === missingFileModifiedTime ? watchMissingFileSystemEntry : watchPresentFileSystemEntry); + updateWatcher( + modifiedTime === missingFileModifiedTime ? watchMissingFileSystemEntry + : watchPresentFileSystemEntry, + ); } else if (modifiedTime === missingFileModifiedTime) { updateWatcher(watchMissingFileSystemEntry); @@ -1308,7 +1467,17 @@ export function patchWriteFileEnsuringDirectory(sys: System) { ); } -export type BufferEncoding = "ascii" | "utf8" | "utf-8" | "utf16le" | "ucs2" | "ucs-2" | "base64" | "latin1" | "binary" | "hex"; +export type BufferEncoding = + | "ascii" + | "utf8" + | "utf-8" + | "utf16le" + | "ucs2" + | "ucs-2" + | "base64" + | "latin1" + | "binary" + | "hex"; /** @internal */ export interface NodeBuffer extends Uint8Array { @@ -1405,8 +1574,18 @@ export interface System { * @pollingInterval - this parameter is used in polling-based watchers and ignored in watchers that * use native OS file watching */ - watchFile?(path: string, callback: FileWatcherCallback, pollingInterval?: number, options?: WatchOptions): FileWatcher; - watchDirectory?(path: string, callback: DirectoryWatcherCallback, recursive?: boolean, options?: WatchOptions): FileWatcher; + watchFile?( + path: string, + callback: FileWatcherCallback, + pollingInterval?: number, + options?: WatchOptions, + ): FileWatcher; + watchDirectory?( + path: string, + callback: DirectoryWatcherCallback, + recursive?: boolean, + options?: WatchOptions, + ): FileWatcher; resolvePath(path: string): string; fileExists(path: string): boolean; directoryExists(path: string): boolean; @@ -1414,7 +1593,13 @@ export interface System { getExecutingFilePath(): string; getCurrentDirectory(): string; getDirectories(path: string): string[]; - readDirectory(path: string, extensions?: readonly string[], exclude?: readonly string[], include?: readonly string[], depth?: number): string[]; + readDirectory( + path: string, + extensions?: readonly string[], + exclude?: readonly string[], + include?: readonly string[], + depth?: number, + ): string[]; getModifiedTime?(path: string): Date | undefined; setModifiedTime?(path: string, time: Date): void; deleteFile?(path: string): void; @@ -1487,14 +1672,16 @@ export let sys: System = (() => { const platform: string = _os.platform(); const useCaseSensitiveFileNames = isFileSystemCaseSensitive(); - const fsRealpath = !!_fs.realpathSync.native ? process.platform === "win32" ? fsRealPathHandlingLongPath : _fs.realpathSync.native : _fs.realpathSync; + const fsRealpath = !!_fs.realpathSync.native + ? process.platform === "win32" ? fsRealPathHandlingLongPath : _fs.realpathSync.native : _fs.realpathSync; // If our filename is "sys.js", then we are executing unbundled on the raw tsc output. // In that case, simulate a faked path in the directory where a bundle would normally // appear (e.g. the directory containing lib.*.d.ts files). // // Note that if we ever emit as files like cjs/mjs, this check will be wrong. - const executingFilePath = __filename.endsWith("sys.js") ? _path.join(_path.dirname(__dirname), "__fake__.js") : __filename; + const executingFilePath = __filename.endsWith("sys.js") ? _path.join(_path.dirname(__dirname), "__fake__.js") + : __filename; const fsSupportsRecursiveFsWatch = process.platform === "win32" || process.platform === "darwin"; const getCurrentDirectory = memoize(() => process.cwd()); @@ -1588,9 +1775,12 @@ export let sys: System = (() => { }, enableCPUProfiler, disableCPUProfiler, - cpuProfilingEnabled: () => !!activeSession || contains(process.execArgv, "--cpu-prof") || contains(process.execArgv, "--prof"), + cpuProfilingEnabled: () => + !!activeSession || contains(process.execArgv, "--cpu-prof") || contains(process.execArgv, "--prof"), realpath, - debugMode: !!process.env.NODE_INSPECTOR_IPC || !!process.env.VSCODE_INSPECTOR_OPTIONS || some(process.execArgv, arg => /^--(inspect|debug)(-brk)?(=\d+)?$/i.test(arg)) || !!(process as any).recordreplay, + debugMode: !!process.env.NODE_INSPECTOR_IPC || !!process.env.VSCODE_INSPECTOR_OPTIONS + || some(process.execArgv, arg => /^--(inspect|debug)(-brk)?(=\d+)?$/i.test(arg)) + || !!(process as any).recordreplay, tryEnableSourceMapsForHost() { try { (require("source-map-support") as typeof import("source-map-support")).install(); @@ -1676,10 +1866,17 @@ export let sys: System = (() => { if (node.callFrame.url) { const url = normalizeSlashes(node.callFrame.url); if (containsPath(fileUrlRoot, url, useCaseSensitiveFileNames)) { - node.callFrame.url = getRelativePathToDirectoryOrUrl(fileUrlRoot, url, fileUrlRoot, createGetCanonicalFileName(useCaseSensitiveFileNames), /*isAbsolutePathAnUrl*/ true); + node.callFrame.url = getRelativePathToDirectoryOrUrl( + fileUrlRoot, + url, + fileUrlRoot, + createGetCanonicalFileName(useCaseSensitiveFileNames), + /*isAbsolutePathAnUrl*/ true, + ); } else if (!nativePattern.test(url)) { - node.callFrame.url = (remappedPaths.has(url) ? remappedPaths : remappedPaths.set(url, `external${externalFileCounter}.js`)).get(url)!; + node.callFrame.url = (remappedPaths.has(url) ? remappedPaths + : remappedPaths.set(url, `external${externalFileCounter}.js`)).get(url)!; externalFileCounter++; } } @@ -1694,7 +1891,10 @@ export let sys: System = (() => { if (!err) { try { if (statSync(profilePath)?.isDirectory()) { - profilePath = _path.join(profilePath, `${(new Date()).toISOString().replace(/:/g, "-")}+P${process.pid}.cpuprofile`); + profilePath = _path.join( + profilePath, + `${(new Date()).toISOString().replace(/:/g, "-")}+P${process.pid}.cpuprofile`, + ); } } catch { @@ -1745,7 +1945,11 @@ export let sys: System = (() => { }); } - function fsWatchFileWorker(fileName: string, callback: FileWatcherCallback, pollingInterval: number): FileWatcher { + function fsWatchFileWorker( + fileName: string, + callback: FileWatcherCallback, + pollingInterval: number, + ): FileWatcher { _fs.watchFile(fileName, { persistent: true, interval: pollingInterval }, fileChanged); let eventKind: FileWatcherEventKind; return { @@ -1787,8 +1991,8 @@ export let sys: System = (() => { // (ref: https://github.com/nodejs/node/pull/2649 and https://github.com/Microsoft/TypeScript/issues/4643) return _fs.watch( fileOrDirectory, - fsSupportsRecursiveFsWatch ? - { persistent: true, recursive: !!recursive } : { persistent: true }, + fsSupportsRecursiveFsWatch + ? { persistent: true, recursive: !!recursive } : { persistent: true }, callback, ); } @@ -1902,8 +2106,24 @@ export let sys: System = (() => { } } - function readDirectory(path: string, extensions?: readonly string[], excludes?: readonly string[], includes?: readonly string[], depth?: number): string[] { - return matchFiles(path, extensions, excludes, includes, useCaseSensitiveFileNames, process.cwd(), depth, getAccessibleFileSystemEntries, realpath); + function readDirectory( + path: string, + extensions?: readonly string[], + excludes?: readonly string[], + includes?: readonly string[], + depth?: number, + ): string[] { + return matchFiles( + path, + extensions, + excludes, + includes, + useCaseSensitiveFileNames, + process.cwd(), + depth, + getAccessibleFileSystemEntries, + realpath, + ); } function fileSystemEntryExists(path: string, entryKind: FileSystemEntryKind): boolean { diff --git a/src/compiler/tracing.ts b/src/compiler/tracing.ts index 42b69e0f7bce0..af53078fc7b28 100644 --- a/src/compiler/tracing.ts +++ b/src/compiler/tracing.ts @@ -51,7 +51,14 @@ export namespace tracingEnabled { // The actual constraint is that JSON.stringify be able to serialize it without throwing. interface Args { - [key: string]: string | number | boolean | null | undefined | Args | readonly (string | number | boolean | null | undefined | Args)[]; + [key: string]: + | string + | number + | boolean + | null + | undefined + | Args + | readonly (string | number | boolean | null | undefined | Args)[]; } /** Starts tracing for the given project. */ @@ -99,7 +106,11 @@ export namespace tracingEnabled { fs.writeSync( traceFd, "[\n" - + [{ name: "process_name", args: { name: "tsc" }, ...meta }, { name: "thread_name", args: { name: "Main" }, ...meta }, { name: "TracingStartedInBrowser", ...meta, cat: "disabled-by-default-devtools.timeline" }] + + [{ name: "process_name", args: { name: "tsc" }, ...meta }, { + name: "thread_name", + args: { name: "Main" }, + ...meta, + }, { name: "TracingStartedInBrowser", ...meta, cat: "disabled-by-default-devtools.timeline" }] .map(v => JSON.stringify(v)).join(",\n"), ); } @@ -183,7 +194,14 @@ export namespace tracingEnabled { } } - function writeEvent(eventType: string, phase: Phase, name: string, args: Args | undefined, extras?: string, time: number = 1000 * timestamp()) { + function writeEvent( + eventType: string, + phase: Phase, + name: string, + args: Args | undefined, + extras?: string, + time: number = 1000 * timestamp(), + ) { // In server mode, there's no easy way to dump type information, so we drop events that would require it. if (mode === "server" && phase === Phase.CheckTypes) return; @@ -319,7 +337,9 @@ export namespace tracingEnabled { recursionId: recursionToken, isTuple: objectFlags & ObjectFlags.Tuple ? true : undefined, unionTypes: (type.flags & TypeFlags.Union) ? (type as UnionType).types?.map(t => t.id) : undefined, - intersectionTypes: (type.flags & TypeFlags.Intersection) ? (type as IntersectionType).types.map(t => t.id) : undefined, + intersectionTypes: (type.flags & TypeFlags.Intersection) ? (type as IntersectionType).types.map(t => + t.id + ) : undefined, aliasTypeArguments: type.aliasTypeArguments?.map(t => t.id), keyofType: (type.flags & TypeFlags.Index) ? (type as IndexType).type?.id : undefined, ...indexedAccessProperties, diff --git a/src/compiler/transformer.ts b/src/compiler/transformer.ts index 3a37fe0f2d3f4..7272a6b4805ef 100644 --- a/src/compiler/transformer.ts +++ b/src/compiler/transformer.ts @@ -109,14 +109,22 @@ const enum SyntaxKindFeatureFlags { export const noTransformers: EmitTransformers = { scriptTransformers: emptyArray, declarationTransformers: emptyArray }; /** @internal */ -export function getTransformers(compilerOptions: CompilerOptions, customTransformers?: CustomTransformers, emitOnly?: boolean | EmitOnly): EmitTransformers { +export function getTransformers( + compilerOptions: CompilerOptions, + customTransformers?: CustomTransformers, + emitOnly?: boolean | EmitOnly, +): EmitTransformers { return { scriptTransformers: getScriptTransformers(compilerOptions, customTransformers, emitOnly), declarationTransformers: getDeclarationTransformers(customTransformers), }; } -function getScriptTransformers(compilerOptions: CompilerOptions, customTransformers?: CustomTransformers, emitOnly?: boolean | EmitOnly) { +function getScriptTransformers( + compilerOptions: CompilerOptions, + customTransformers?: CustomTransformers, + emitOnly?: boolean | EmitOnly, +) { if (emitOnly) return emptyArray; const languageVersion = getEmitScriptTarget(compilerOptions); @@ -140,7 +148,9 @@ function getScriptTransformers(compilerOptions: CompilerOptions, customTransform transformers.push(transformESNext); } - if (!compilerOptions.experimentalDecorators && (languageVersion < ScriptTarget.ESNext || !useDefineForClassFields)) { + if ( + !compilerOptions.experimentalDecorators && (languageVersion < ScriptTarget.ESNext || !useDefineForClassFields) + ) { transformers.push(transformESDecorators); } @@ -190,7 +200,10 @@ function getScriptTransformers(compilerOptions: CompilerOptions, customTransform function getDeclarationTransformers(customTransformers?: CustomTransformers) { const transformers: TransformerFactory[] = []; transformers.push(transformDeclarations); - addRange(transformers, customTransformers && map(customTransformers.afterDeclarations, wrapDeclarationTransformerFactory)); + addRange( + transformers, + customTransformers && map(customTransformers.afterDeclarations, wrapDeclarationTransformerFactory), + ); return transformers; } @@ -204,7 +217,10 @@ function wrapCustomTransformer(transformer: CustomTransformer): Transformer(transformer: TransformerFactory | CustomTransformerFactory, handleDefault: (context: TransformationContext, tx: Transformer) => Transformer): TransformerFactory { +function wrapCustomTransformerFactory( + transformer: TransformerFactory | CustomTransformerFactory, + handleDefault: (context: TransformationContext, tx: Transformer) => Transformer, +): TransformerFactory { return context => { const customTransformer = transformer(context); return typeof customTransformer === "function" @@ -213,11 +229,15 @@ function wrapCustomTransformerFactory(transformer }; } -function wrapScriptTransformerFactory(transformer: TransformerFactory | CustomTransformerFactory): TransformerFactory { +function wrapScriptTransformerFactory( + transformer: TransformerFactory | CustomTransformerFactory, +): TransformerFactory { return wrapCustomTransformerFactory(transformer, chainBundle); } -function wrapDeclarationTransformerFactory(transformer: TransformerFactory | CustomTransformerFactory): TransformerFactory { +function wrapDeclarationTransformerFactory( + transformer: TransformerFactory | CustomTransformerFactory, +): TransformerFactory { return wrapCustomTransformerFactory(transformer, (_, node) => node); } @@ -243,7 +263,15 @@ export function noEmitNotification(hint: EmitHint, node: Node, callback: (hint: * * @internal */ -export function transformNodes(resolver: EmitResolver | undefined, host: EmitHost | undefined, factory: NodeFactory, options: CompilerOptions, nodes: readonly T[], transformers: readonly TransformerFactory[], allowDtsFiles: boolean): TransformationResult { +export function transformNodes( + resolver: EmitResolver | undefined, + host: EmitHost | undefined, + factory: NodeFactory, + options: CompilerOptions, + nodes: readonly T[], + transformers: readonly TransformerFactory[], + allowDtsFiles: boolean, +): TransformationResult { const enabledSyntaxKindFeatures = new Array(SyntaxKind.Count); let lexicalEnvironmentVariableDeclarations: VariableDeclaration[]; let lexicalEnvironmentFunctionDeclarations: FunctionDeclaration[]; @@ -294,7 +322,10 @@ export function transformNodes(resolver: EmitResolver | undefine return onSubstituteNode; }, set onSubstituteNode(value) { - Debug.assert(state < TransformationState.Initialized, "Cannot modify transformation hooks after initialization has completed."); + Debug.assert( + state < TransformationState.Initialized, + "Cannot modify transformation hooks after initialization has completed.", + ); Debug.assert(value !== undefined, "Value must not be 'undefined'"); onSubstituteNode = value; }, @@ -302,7 +333,10 @@ export function transformNodes(resolver: EmitResolver | undefine return onEmitNode; }, set onEmitNode(value) { - Debug.assert(state < TransformationState.Initialized, "Cannot modify transformation hooks after initialization has completed."); + Debug.assert( + state < TransformationState.Initialized, + "Cannot modify transformation hooks after initialization has completed.", + ); Debug.assert(value !== undefined, "Value must not be 'undefined'"); onEmitNode = value; }, @@ -333,7 +367,12 @@ export function transformNodes(resolver: EmitResolver | undefine // Transform each node. const transformed: T[] = []; for (const node of nodes) { - tracing?.push(tracing.Phase.Emit, "transformNodes", node.kind === SyntaxKind.SourceFile ? { path: (node as any as SourceFile).path } : { kind: node.kind, pos: node.pos, end: node.end }); + tracing?.push( + tracing.Phase.Emit, + "transformNodes", + node.kind === SyntaxKind.SourceFile ? { path: (node as any as SourceFile).path } + : { kind: node.kind, pos: node.pos, end: node.end }, + ); transformed.push((allowDtsFiles ? transformation : transformRoot)(node)); tracing?.pop(); } @@ -361,7 +400,10 @@ export function transformNodes(resolver: EmitResolver | undefine * Enables expression substitutions in the pretty printer for the provided SyntaxKind. */ function enableSubstitution(kind: SyntaxKind) { - Debug.assert(state < TransformationState.Completed, "Cannot modify the transformation context after transformation has completed."); + Debug.assert( + state < TransformationState.Completed, + "Cannot modify the transformation context after transformation has completed.", + ); enabledSyntaxKindFeatures[kind] |= SyntaxKindFeatureFlags.Substitution; } @@ -389,7 +431,10 @@ export function transformNodes(resolver: EmitResolver | undefine * Enables before/after emit notifications in the pretty printer for the provided SyntaxKind. */ function enableEmitNotification(kind: SyntaxKind) { - Debug.assert(state < TransformationState.Completed, "Cannot modify the transformation context after transformation has completed."); + Debug.assert( + state < TransformationState.Completed, + "Cannot modify the transformation context after transformation has completed.", + ); enabledSyntaxKindFeatures[kind] |= SyntaxKindFeatureFlags.EmitNotifications; } @@ -410,7 +455,10 @@ export function transformNodes(resolver: EmitResolver | undefine * @param emitCallback The callback used to emit the node. */ function emitNodeWithNotification(hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void) { - Debug.assert(state < TransformationState.Disposed, "Cannot invoke TransformationResult callbacks after the result is disposed."); + Debug.assert( + state < TransformationState.Disposed, + "Cannot invoke TransformationResult callbacks after the result is disposed.", + ); if (node) { // TODO: Remove check and unconditionally use onEmitNode when API is breakingly changed // (see https://github.com/microsoft/TypeScript/pull/36248/files/5062623f39120171b98870c71344b3242eb03d23#r369766739) @@ -427,8 +475,14 @@ export function transformNodes(resolver: EmitResolver | undefine * Records a hoisted variable declaration for the provided name within a lexical environment. */ function hoistVariableDeclaration(name: Identifier): void { - Debug.assert(state > TransformationState.Uninitialized, "Cannot modify the lexical environment during initialization."); - Debug.assert(state < TransformationState.Completed, "Cannot modify the lexical environment after transformation has completed."); + Debug.assert( + state > TransformationState.Uninitialized, + "Cannot modify the lexical environment during initialization.", + ); + Debug.assert( + state < TransformationState.Completed, + "Cannot modify the lexical environment after transformation has completed.", + ); const decl = setEmitFlags(factory.createVariableDeclaration(name), EmitFlags.NoNestedSourceMaps); if (!lexicalEnvironmentVariableDeclarations) { lexicalEnvironmentVariableDeclarations = [decl]; @@ -445,8 +499,14 @@ export function transformNodes(resolver: EmitResolver | undefine * Records a hoisted function declaration within a lexical environment. */ function hoistFunctionDeclaration(func: FunctionDeclaration): void { - Debug.assert(state > TransformationState.Uninitialized, "Cannot modify the lexical environment during initialization."); - Debug.assert(state < TransformationState.Completed, "Cannot modify the lexical environment after transformation has completed."); + Debug.assert( + state > TransformationState.Uninitialized, + "Cannot modify the lexical environment during initialization.", + ); + Debug.assert( + state < TransformationState.Completed, + "Cannot modify the lexical environment after transformation has completed.", + ); setEmitFlags(func, EmitFlags.CustomPrologue); if (!lexicalEnvironmentFunctionDeclarations) { lexicalEnvironmentFunctionDeclarations = [func]; @@ -460,8 +520,14 @@ export function transformNodes(resolver: EmitResolver | undefine * Adds an initialization statement to the top of the lexical environment. */ function addInitializationStatement(node: Statement): void { - Debug.assert(state > TransformationState.Uninitialized, "Cannot modify the lexical environment during initialization."); - Debug.assert(state < TransformationState.Completed, "Cannot modify the lexical environment after transformation has completed."); + Debug.assert( + state > TransformationState.Uninitialized, + "Cannot modify the lexical environment during initialization.", + ); + Debug.assert( + state < TransformationState.Completed, + "Cannot modify the lexical environment after transformation has completed.", + ); setEmitFlags(node, EmitFlags.CustomPrologue); if (!lexicalEnvironmentStatements) { lexicalEnvironmentStatements = [node]; @@ -476,16 +542,24 @@ export function transformNodes(resolver: EmitResolver | undefine * are pushed onto a stack, and the related storage variables are reset. */ function startLexicalEnvironment(): void { - Debug.assert(state > TransformationState.Uninitialized, "Cannot modify the lexical environment during initialization."); - Debug.assert(state < TransformationState.Completed, "Cannot modify the lexical environment after transformation has completed."); + Debug.assert( + state > TransformationState.Uninitialized, + "Cannot modify the lexical environment during initialization.", + ); + Debug.assert( + state < TransformationState.Completed, + "Cannot modify the lexical environment after transformation has completed.", + ); Debug.assert(!lexicalEnvironmentSuspended, "Lexical environment is suspended."); // Save the current lexical environment. Rather than resizing the array we adjust the // stack size variable. This allows us to reuse existing array slots we've // already allocated between transformations to avoid allocation and GC overhead during // transformation. - lexicalEnvironmentVariableDeclarationsStack[lexicalEnvironmentStackOffset] = lexicalEnvironmentVariableDeclarations; - lexicalEnvironmentFunctionDeclarationsStack[lexicalEnvironmentStackOffset] = lexicalEnvironmentFunctionDeclarations; + lexicalEnvironmentVariableDeclarationsStack[lexicalEnvironmentStackOffset] = + lexicalEnvironmentVariableDeclarations; + lexicalEnvironmentFunctionDeclarationsStack[lexicalEnvironmentStackOffset] = + lexicalEnvironmentFunctionDeclarations; lexicalEnvironmentStatementsStack[lexicalEnvironmentStackOffset] = lexicalEnvironmentStatements; lexicalEnvironmentFlagsStack[lexicalEnvironmentStackOffset] = lexicalEnvironmentFlags; lexicalEnvironmentStackOffset++; @@ -497,16 +571,28 @@ export function transformNodes(resolver: EmitResolver | undefine /** Suspends the current lexical environment, usually after visiting a parameter list. */ function suspendLexicalEnvironment(): void { - Debug.assert(state > TransformationState.Uninitialized, "Cannot modify the lexical environment during initialization."); - Debug.assert(state < TransformationState.Completed, "Cannot modify the lexical environment after transformation has completed."); + Debug.assert( + state > TransformationState.Uninitialized, + "Cannot modify the lexical environment during initialization.", + ); + Debug.assert( + state < TransformationState.Completed, + "Cannot modify the lexical environment after transformation has completed.", + ); Debug.assert(!lexicalEnvironmentSuspended, "Lexical environment is already suspended."); lexicalEnvironmentSuspended = true; } /** Resumes a suspended lexical environment, usually before visiting a function body. */ function resumeLexicalEnvironment(): void { - Debug.assert(state > TransformationState.Uninitialized, "Cannot modify the lexical environment during initialization."); - Debug.assert(state < TransformationState.Completed, "Cannot modify the lexical environment after transformation has completed."); + Debug.assert( + state > TransformationState.Uninitialized, + "Cannot modify the lexical environment during initialization.", + ); + Debug.assert( + state < TransformationState.Completed, + "Cannot modify the lexical environment after transformation has completed.", + ); Debug.assert(lexicalEnvironmentSuspended, "Lexical environment is not suspended."); lexicalEnvironmentSuspended = false; } @@ -516,15 +602,21 @@ export function transformNodes(resolver: EmitResolver | undefine * any hoisted declarations added in this environment are returned. */ function endLexicalEnvironment(): Statement[] | undefined { - Debug.assert(state > TransformationState.Uninitialized, "Cannot modify the lexical environment during initialization."); - Debug.assert(state < TransformationState.Completed, "Cannot modify the lexical environment after transformation has completed."); + Debug.assert( + state > TransformationState.Uninitialized, + "Cannot modify the lexical environment during initialization.", + ); + Debug.assert( + state < TransformationState.Completed, + "Cannot modify the lexical environment after transformation has completed.", + ); Debug.assert(!lexicalEnvironmentSuspended, "Lexical environment is suspended."); let statements: Statement[] | undefined; if ( - lexicalEnvironmentVariableDeclarations || - lexicalEnvironmentFunctionDeclarations || - lexicalEnvironmentStatements + lexicalEnvironmentVariableDeclarations + || lexicalEnvironmentFunctionDeclarations + || lexicalEnvironmentStatements ) { if (lexicalEnvironmentFunctionDeclarations) { statements = [...lexicalEnvironmentFunctionDeclarations]; @@ -558,8 +650,10 @@ export function transformNodes(resolver: EmitResolver | undefine // Restore the previous lexical environment. lexicalEnvironmentStackOffset--; - lexicalEnvironmentVariableDeclarations = lexicalEnvironmentVariableDeclarationsStack[lexicalEnvironmentStackOffset]; - lexicalEnvironmentFunctionDeclarations = lexicalEnvironmentFunctionDeclarationsStack[lexicalEnvironmentStackOffset]; + lexicalEnvironmentVariableDeclarations = + lexicalEnvironmentVariableDeclarationsStack[lexicalEnvironmentStackOffset]; + lexicalEnvironmentFunctionDeclarations = + lexicalEnvironmentFunctionDeclarationsStack[lexicalEnvironmentStackOffset]; lexicalEnvironmentStatements = lexicalEnvironmentStatementsStack[lexicalEnvironmentStackOffset]; lexicalEnvironmentFlags = lexicalEnvironmentFlagsStack[lexicalEnvironmentStackOffset]; if (lexicalEnvironmentStackOffset === 0) { @@ -572,9 +666,9 @@ export function transformNodes(resolver: EmitResolver | undefine } function setLexicalEnvironmentFlags(flags: LexicalEnvironmentFlags, value: boolean): void { - lexicalEnvironmentFlags = value ? - lexicalEnvironmentFlags | flags : - lexicalEnvironmentFlags & ~flags; + lexicalEnvironmentFlags = value + ? lexicalEnvironmentFlags | flags + : lexicalEnvironmentFlags & ~flags; } function getLexicalEnvironmentFlags(): LexicalEnvironmentFlags { @@ -586,7 +680,10 @@ export function transformNodes(resolver: EmitResolver | undefine */ function startBlockScope() { Debug.assert(state > TransformationState.Uninitialized, "Cannot start a block scope during initialization."); - Debug.assert(state < TransformationState.Completed, "Cannot start a block scope after transformation has completed."); + Debug.assert( + state < TransformationState.Completed, + "Cannot start a block scope after transformation has completed.", + ); blockScopedVariableDeclarationsStack[blockScopeStackOffset] = blockScopedVariableDeclarations; blockScopeStackOffset++; blockScopedVariableDeclarations = undefined!; @@ -597,13 +694,18 @@ export function transformNodes(resolver: EmitResolver | undefine */ function endBlockScope() { Debug.assert(state > TransformationState.Uninitialized, "Cannot end a block scope during initialization."); - Debug.assert(state < TransformationState.Completed, "Cannot end a block scope after transformation has completed."); - const statements: Statement[] | undefined = some(blockScopedVariableDeclarations) ? - [ + Debug.assert( + state < TransformationState.Completed, + "Cannot end a block scope after transformation has completed.", + ); + const statements: Statement[] | undefined = some(blockScopedVariableDeclarations) + ? [ factory.createVariableStatement( /*modifiers*/ undefined, factory.createVariableDeclarationList( - blockScopedVariableDeclarations.map(identifier => factory.createVariableDeclaration(identifier)), + blockScopedVariableDeclarations.map(identifier => + factory.createVariableDeclaration(identifier) + ), NodeFlags.Let, ), ), @@ -622,8 +724,14 @@ export function transformNodes(resolver: EmitResolver | undefine } function requestEmitHelper(helper: EmitHelper): void { - Debug.assert(state > TransformationState.Uninitialized, "Cannot modify the transformation context during initialization."); - Debug.assert(state < TransformationState.Completed, "Cannot modify the transformation context after transformation has completed."); + Debug.assert( + state > TransformationState.Uninitialized, + "Cannot modify the transformation context during initialization.", + ); + Debug.assert( + state < TransformationState.Completed, + "Cannot modify the transformation context after transformation has completed.", + ); Debug.assert(!helper.scoped, "Cannot request a scoped emit helper."); if (helper.dependencies) { for (const h of helper.dependencies) { @@ -634,8 +742,14 @@ export function transformNodes(resolver: EmitResolver | undefine } function readEmitHelpers(): EmitHelper[] | undefined { - Debug.assert(state > TransformationState.Uninitialized, "Cannot modify the transformation context during initialization."); - Debug.assert(state < TransformationState.Completed, "Cannot modify the transformation context after transformation has completed."); + Debug.assert( + state > TransformationState.Uninitialized, + "Cannot modify the transformation context during initialization.", + ); + Debug.assert( + state < TransformationState.Completed, + "Cannot modify the transformation context after transformation has completed.", + ); const helpers = emitHelpers; emitHelpers = undefined; return helpers; diff --git a/src/compiler/transformers/classFields.ts b/src/compiler/transformers/classFields.ts index ede44357f242d..a87fdfb492505 100644 --- a/src/compiler/transformers/classFields.ts +++ b/src/compiler/transformers/classFields.ts @@ -338,7 +338,11 @@ const enum ClassFacts { WillHoistInitializersToConstructor = 1 << 4, } -type LexicalEnv = LexicalEnvironment; +type LexicalEnv = LexicalEnvironment< + ClassLexicalEnvironment | undefined, + PrivateEnvironmentData, + PrivateIdentifierInfo +>; type PrivateEnv = PrivateEnvironment; /** @@ -378,9 +382,9 @@ export function transformClassFields(context: TransformationContext): (x: Source // We need to transform `accessor` fields when target < ESNext. // We may need to transform `accessor` fields when `useDefineForClassFields: false` - const shouldTransformAutoAccessors = languageVersion < ScriptTarget.ESNext ? Ternary.True : - !useDefineForClassFields ? Ternary.Maybe : - Ternary.False; + const shouldTransformAutoAccessors = languageVersion < ScriptTarget.ESNext ? Ternary.True + : !useDefineForClassFields ? Ternary.Maybe + : Ternary.False; // We need to transform `this` in a static initializer into a reference to the class // when target < ES2022 since the assignment will be moved outside of the class body. @@ -388,11 +392,12 @@ export function transformClassFields(context: TransformationContext): (x: Source // We don't need to transform `super` property access when target <= ES5 because // the es2015 transformation handles those. - const shouldTransformSuperInStaticInitializers = shouldTransformThisInStaticInitializers && languageVersion >= ScriptTarget.ES2015; + const shouldTransformSuperInStaticInitializers = shouldTransformThisInStaticInitializers + && languageVersion >= ScriptTarget.ES2015; - const shouldTransformAnything = shouldTransformInitializers || - shouldTransformPrivateElementsOrClassStaticBlocks || - shouldTransformAutoAccessors === Ternary.True; + const shouldTransformAnything = shouldTransformInitializers + || shouldTransformPrivateElementsOrClassStaticBlocks + || shouldTransformAutoAccessors === Ternary.True; const previousOnSubstituteNode = context.onSubstituteNode; context.onSubstituteNode = onSubstituteNode; @@ -436,7 +441,8 @@ export function transformClassFields(context: TransformationContext): (x: Source } lexicalEnvironment = undefined; - shouldTransformPrivateStaticElementsInFile = !!(getInternalEmitFlags(node) & InternalEmitFlags.TransformPrivateStaticElements); + shouldTransformPrivateStaticElementsInFile = + !!(getInternalEmitFlags(node) & InternalEmitFlags.TransformPrivateStaticElements); if (!shouldTransformAnything && !shouldTransformPrivateStaticElementsInFile) { return node; } @@ -457,8 +463,8 @@ export function transformClassFields(context: TransformationContext): (x: Source function visitor(node: Node): VisitResult { if ( - !(node.transformFlags & TransformFlags.ContainsClassFields) && - !(node.transformFlags & TransformFlags.ContainsLexicalThisOrSuper) + !(node.transformFlags & TransformFlags.ContainsClassFields) + && !(node.transformFlags & TransformFlags.ContainsLexicalThisOrSuper) ) { return node; } @@ -493,7 +499,10 @@ export function transformClassFields(context: TransformationContext): (x: Source return visitElementAccessExpression(node as ElementAccessExpression); case SyntaxKind.PrefixUnaryExpression: case SyntaxKind.PostfixUnaryExpression: - return visitPreOrPostfixUnaryExpression(node as PrefixUnaryExpression | PostfixUnaryExpression, /*discarded*/ false); + return visitPreOrPostfixUnaryExpression( + node as PrefixUnaryExpression | PostfixUnaryExpression, + /*discarded*/ false, + ); case SyntaxKind.BinaryExpression: return visitBinaryExpression(node as BinaryExpression, /*discarded*/ false); case SyntaxKind.ParenthesizedExpression: @@ -522,7 +531,11 @@ export function transformClassFields(context: TransformationContext): (x: Source case SyntaxKind.SetAccessor: { // If we are descending into a class element, set the class element return setCurrentClassElementAnd( - node as ConstructorDeclaration | MethodDeclaration | GetAccessorDeclaration | SetAccessorDeclaration, + node as + | ConstructorDeclaration + | MethodDeclaration + | GetAccessorDeclaration + | SetAccessorDeclaration, fallbackVisitor, node, ); @@ -543,7 +556,10 @@ export function transformClassFields(context: TransformationContext): (x: Source switch (node.kind) { case SyntaxKind.PrefixUnaryExpression: case SyntaxKind.PostfixUnaryExpression: - return visitPreOrPostfixUnaryExpression(node as PrefixUnaryExpression | PostfixUnaryExpression, /*discarded*/ true); + return visitPreOrPostfixUnaryExpression( + node as PrefixUnaryExpression | PostfixUnaryExpression, + /*discarded*/ true, + ); case SyntaxKind.BinaryExpression: return visitBinaryExpression(node as BinaryExpression, /*discarded*/ true); case SyntaxKind.CommaListExpression: @@ -645,7 +661,10 @@ export function transformClassFields(context: TransformationContext): (x: Source case SyntaxKind.SetAccessor: return classElementVisitor(node); default: - Debug.assertMissingNode(node, "Expected node to either be a PropertyDeclaration, GetAccessorDeclaration, or SetAccessorDeclaration"); + Debug.assertMissingNode( + node, + "Expected node to either be a PropertyDeclaration, GetAccessorDeclaration, or SetAccessorDeclaration", + ); break; } } @@ -703,9 +722,9 @@ export function transformClassFields(context: TransformationContext): (x: Source pendingStatements = []; const visitedNode = visitEachChild(node, visitor, context); - const statement = some(pendingStatements) ? - [visitedNode, ...pendingStatements] : - visitedNode; + const statement = some(pendingStatements) + ? [visitedNode, ...pendingStatements] + : visitedNode; pendingStatements = savedPendingStatements; return statement; @@ -792,7 +811,12 @@ export function transformClassFields(context: TransformationContext): (x: Source // is `""`. if (isNamedEvaluation(node, isAnonymousClassNeedingAssignedName)) { - node = transformNamedEvaluation(context, node, /*ignoreEmptyStringLiteral*/ true, node.isExportEquals ? "" : "default"); + node = transformNamedEvaluation( + context, + node, + /*ignoreEmptyStringLiteral*/ true, + node.isExportEquals ? "" : "default", + ); } return visitEachChild(node, visitor, context); @@ -802,7 +826,10 @@ export function transformClassFields(context: TransformationContext): (x: Source if (some(pendingExpressions)) { if (isParenthesizedExpression(expression)) { pendingExpressions.push(expression.expression); - expression = factory.updateParenthesizedExpression(expression, factory.inlineExpressions(pendingExpressions)); + expression = factory.updateParenthesizedExpression( + expression, + factory.inlineExpressions(pendingExpressions), + ); } else { pendingExpressions.push(expression); @@ -825,9 +852,16 @@ export function transformClassFields(context: TransformationContext): (x: Source return fallbackVisitor(node); } - function shouldTransformClassElementToWeakMap(node: PrivateIdentifierMethodDeclaration | PrivateIdentifierAccessorDeclaration | PrivateIdentifierPropertyDeclaration) { + function shouldTransformClassElementToWeakMap( + node: + | PrivateIdentifierMethodDeclaration + | PrivateIdentifierAccessorDeclaration + | PrivateIdentifierPropertyDeclaration, + ) { if (shouldTransformPrivateElementsOrClassStaticBlocks) return true; - if (hasStaticModifier(node) && getInternalEmitFlags(node) & InternalEmitFlags.TransformPrivateStaticElements) return true; + if (hasStaticModifier(node) && getInternalEmitFlags(node) & InternalEmitFlags.TransformPrivateStaticElements) { + return true; + } return false; } @@ -851,7 +885,10 @@ export function transformClassFields(context: TransformationContext): (x: Source factory.createAssignment( functionName, factory.createFunctionExpression( - filter(node.modifiers, (m): m is Modifier => isModifier(m) && !isStaticModifier(m) && !isAccessorModifier(m)), + filter( + node.modifiers, + (m): m is Modifier => isModifier(m) && !isStaticModifier(m) && !isAccessorModifier(m), + ), node.asteriskToken, functionName, /*typeParameters*/ undefined, @@ -926,7 +963,10 @@ export function transformClassFields(context: TransformationContext): (x: Source if (isComputedPropertyName(name) && !isSimpleInlineableExpression(name.expression)) { const cacheAssignment = findComputedPropertyNameCacheAssignment(name); if (cacheAssignment) { - getterName = factory.updateComputedPropertyName(name, visitNode(name.expression, visitor, isExpression)); + getterName = factory.updateComputedPropertyName( + name, + visitNode(name.expression, visitor, isExpression), + ); setterName = factory.updateComputedPropertyName(name, cacheAssignment.left); } else { @@ -979,14 +1019,19 @@ export function transformClassFields(context: TransformationContext): (x: Source // TODO: fix const statement = transformPropertyOrClassStaticBlock(node, factory.createThis()); if (statement) { - return factory.createClassStaticBlockDeclaration(factory.createBlock([statement], /*multiLine*/ true)); + return factory.createClassStaticBlockDeclaration( + factory.createBlock([statement], /*multiLine*/ true), + ); } } return undefined; } - if (shouldTransformInitializersUsingSet && !isStatic(node) && lexicalEnvironment?.data && lexicalEnvironment.data.facts & ClassFacts.WillHoistInitializersToConstructor) { + if ( + shouldTransformInitializersUsingSet && !isStatic(node) && lexicalEnvironment?.data + && lexicalEnvironment.data.facts & ClassFacts.WillHoistInitializersToConstructor + ) { // If we are transforming initializers using Set semantics we will elide the initializer as it will // be moved to the constructor to preserve evaluation order next to public instance fields. We don't // need to do this transformation for private static fields since public static fields can be @@ -1063,23 +1108,25 @@ export function transformClassFields(context: TransformationContext): (x: Source function transformFieldInitializer(node: PropertyDeclaration) { Debug.assert(!hasDecorators(node), "Decorators should already have been transformed and elided."); - return isPrivateIdentifierClassElementDeclaration(node) ? - transformPrivateFieldInitializer(node) : - transformPublicFieldInitializer(node); + return isPrivateIdentifierClassElementDeclaration(node) + ? transformPrivateFieldInitializer(node) + : transformPublicFieldInitializer(node); } function shouldTransformAutoAccessorsInCurrentClass() { - return shouldTransformAutoAccessors === Ternary.True || - shouldTransformAutoAccessors === Ternary.Maybe && - !!lexicalEnvironment?.data && !!(lexicalEnvironment.data.facts & ClassFacts.WillHoistInitializersToConstructor); + return shouldTransformAutoAccessors === Ternary.True + || shouldTransformAutoAccessors === Ternary.Maybe + && !!lexicalEnvironment?.data + && !!(lexicalEnvironment.data.facts & ClassFacts.WillHoistInitializersToConstructor); } function visitPropertyDeclaration(node: PropertyDeclaration) { // If this is an auto-accessor, we defer to `transformAutoAccessor`. That function // will in turn call `transformFieldInitializer` as needed. if ( - isAutoAccessorPropertyDeclaration(node) && (shouldTransformAutoAccessorsInCurrentClass() || - hasStaticModifier(node) && getInternalEmitFlags(node) & InternalEmitFlags.TransformPrivateStaticElements) + isAutoAccessorPropertyDeclaration(node) && (shouldTransformAutoAccessorsInCurrentClass() + || hasStaticModifier(node) + && getInternalEmitFlags(node) & InternalEmitFlags.TransformPrivateStaticElements) ) { return transformAutoAccessor(node); } @@ -1088,10 +1135,10 @@ export function transformClassFields(context: TransformationContext): (x: Source } function shouldForceDynamicThis() { - return !!currentClassElement && - hasStaticModifier(currentClassElement) && - isAccessor(currentClassElement) && - isAutoAccessorPropertyDeclaration(getOriginalNode(currentClassElement)); + return !!currentClassElement + && hasStaticModifier(currentClassElement) + && isAccessor(currentClassElement) + && isAutoAccessorPropertyDeclaration(getOriginalNode(currentClassElement)); } /** @@ -1161,12 +1208,12 @@ export function transformClassFields(context: TransformationContext): (x: Source } } if ( - shouldTransformSuperInStaticInitializers && - currentClassElement && - isSuperProperty(node) && - isIdentifier(node.name) && - isStaticPropertyDeclarationOrClassStaticBlock(currentClassElement) && - lexicalEnvironment?.data + shouldTransformSuperInStaticInitializers + && currentClassElement + && isSuperProperty(node) + && isIdentifier(node.name) + && isStaticPropertyDeclarationOrClassStaticBlock(currentClassElement) + && lexicalEnvironment?.data ) { const { classConstructor, superClassReference, facts } = lexicalEnvironment.data; if (facts & ClassFacts.ClassWasDecorated) { @@ -1189,11 +1236,11 @@ export function transformClassFields(context: TransformationContext): (x: Source function visitElementAccessExpression(node: ElementAccessExpression) { if ( - shouldTransformSuperInStaticInitializers && - currentClassElement && - isSuperProperty(node) && - isStaticPropertyDeclarationOrClassStaticBlock(currentClassElement) && - lexicalEnvironment?.data + shouldTransformSuperInStaticInitializers + && currentClassElement + && isSuperProperty(node) + && isStaticPropertyDeclarationOrClassStaticBlock(currentClassElement) + && lexicalEnvironment?.data ) { const { classConstructor, superClassReference, facts } = lexicalEnvironment.data; if (facts & ClassFacts.ClassWasDecorated) { @@ -1215,10 +1262,13 @@ export function transformClassFields(context: TransformationContext): (x: Source return visitEachChild(node, visitor, context); } - function visitPreOrPostfixUnaryExpression(node: PrefixUnaryExpression | PostfixUnaryExpression, discarded: boolean) { + function visitPreOrPostfixUnaryExpression( + node: PrefixUnaryExpression | PostfixUnaryExpression, + discarded: boolean, + ) { if ( - node.operator === SyntaxKind.PlusPlusToken || - node.operator === SyntaxKind.MinusMinusToken + node.operator === SyntaxKind.PlusPlusToken + || node.operator === SyntaxKind.MinusMinusToken ) { const operand = skipParentheses(node.operand); @@ -1230,8 +1280,15 @@ export function transformClassFields(context: TransformationContext): (x: Source const { readExpression, initializeExpression } = createCopiableReceiverExpr(receiver); let expression: Expression = createPrivateIdentifierAccess(info, readExpression); - const temp = isPrefixUnaryExpression(node) || discarded ? undefined : factory.createTempVariable(hoistVariableDeclaration); - expression = expandPreOrPostfixIncrementOrDecrementExpression(factory, node, expression, hoistVariableDeclaration, temp); + const temp = isPrefixUnaryExpression(node) || discarded ? undefined + : factory.createTempVariable(hoistVariableDeclaration); + expression = expandPreOrPostfixIncrementOrDecrementExpression( + factory, + node, + expression, + hoistVariableDeclaration, + temp, + ); expression = createPrivateIdentifierAssignment( info, initializeExpression || readExpression, @@ -1248,11 +1305,11 @@ export function transformClassFields(context: TransformationContext): (x: Source } } else if ( - shouldTransformSuperInStaticInitializers && - currentClassElement && - isSuperProperty(operand) && - isStaticPropertyDeclarationOrClassStaticBlock(currentClassElement) && - lexicalEnvironment?.data + shouldTransformSuperInStaticInitializers + && currentClassElement + && isSuperProperty(operand) + && isStaticPropertyDeclarationOrClassStaticBlock(currentClassElement) + && lexicalEnvironment?.data ) { // converts `++super.a` into `(Reflect.set(_baseTemp, "a", (_a = Reflect.get(_baseTemp, "a", _classTemp), _b = ++_a), _classTemp), _b)` // converts `++super[f()]` into `(Reflect.set(_baseTemp, _a = f(), (_b = Reflect.get(_baseTemp, _a, _classTemp), _c = ++_b), _classTemp), _c)` @@ -1265,9 +1322,9 @@ export function transformClassFields(context: TransformationContext): (x: Source const { classConstructor, superClassReference, facts } = lexicalEnvironment.data; if (facts & ClassFacts.ClassWasDecorated) { const expression = visitInvalidSuperProperty(operand); - return isPrefixUnaryExpression(node) ? - factory.updatePrefixUnaryExpression(node, expression) : - factory.updatePostfixUnaryExpression(node, expression); + return isPrefixUnaryExpression(node) + ? factory.updatePrefixUnaryExpression(node, expression) + : factory.updatePostfixUnaryExpression(node, expression); } if (classConstructor && superClassReference) { let setterName: Expression | undefined; @@ -1283,16 +1340,34 @@ export function transformClassFields(context: TransformationContext): (x: Source } else { getterName = factory.createTempVariable(hoistVariableDeclaration); - setterName = factory.createAssignment(getterName, visitNode(operand.argumentExpression, visitor, isExpression)); + setterName = factory.createAssignment( + getterName, + visitNode(operand.argumentExpression, visitor, isExpression), + ); } } if (setterName && getterName) { - let expression: Expression = factory.createReflectGetCall(superClassReference, getterName, classConstructor); + let expression: Expression = factory.createReflectGetCall( + superClassReference, + getterName, + classConstructor, + ); setTextRange(expression, operand); const temp = discarded ? undefined : factory.createTempVariable(hoistVariableDeclaration); - expression = expandPreOrPostfixIncrementOrDecrementExpression(factory, node, expression, hoistVariableDeclaration, temp); - expression = factory.createReflectSetCall(superClassReference, setterName, expression, classConstructor); + expression = expandPreOrPostfixIncrementOrDecrementExpression( + factory, + node, + expression, + hoistVariableDeclaration, + temp, + ); + expression = factory.createReflectSetCall( + superClassReference, + setterName, + expression, + classConstructor, + ); setOriginalNode(expression, node); setTextRange(expression, node); if (temp) { @@ -1324,7 +1399,9 @@ export function transformClassFields(context: TransformationContext): (x: Source ); } - function createCopiableReceiverExpr(receiver: Expression): { readExpression: Expression; initializeExpression: Expression | undefined; } { + function createCopiableReceiverExpr( + receiver: Expression, + ): { readExpression: Expression; initializeExpression: Expression | undefined; } { const clone = nodeIsSynthesized(receiver) ? receiver : factory.cloneNode(receiver); if (receiver.kind === SyntaxKind.ThisKeyword && noSubstitution.has(receiver)) { noSubstitution.add(clone); @@ -1339,17 +1416,25 @@ export function transformClassFields(context: TransformationContext): (x: Source function visitCallExpression(node: CallExpression) { if ( - isPrivateIdentifierPropertyAccessExpression(node.expression) && - accessPrivateIdentifier(node.expression.name) + isPrivateIdentifierPropertyAccessExpression(node.expression) + && accessPrivateIdentifier(node.expression.name) ) { // obj.#x() // Transform call expressions of private names to properly bind the `this` parameter. - const { thisArg, target } = factory.createCallBinding(node.expression, hoistVariableDeclaration, languageVersion); + const { thisArg, target } = factory.createCallBinding( + node.expression, + hoistVariableDeclaration, + languageVersion, + ); if (isCallChain(node)) { return factory.updateCallChain( node, - factory.createPropertyAccessChain(visitNode(target, visitor, isExpression), node.questionDotToken, "call"), + factory.createPropertyAccessChain( + visitNode(target, visitor, isExpression), + node.questionDotToken, + "call", + ), /*questionDotToken*/ undefined, /*typeArguments*/ undefined, [visitNode(thisArg, visitor, isExpression), ...visitNodes(node.arguments, visitor, isExpression)], @@ -1364,11 +1449,11 @@ export function transformClassFields(context: TransformationContext): (x: Source } if ( - shouldTransformSuperInStaticInitializers && - currentClassElement && - isSuperProperty(node.expression) && - isStaticPropertyDeclarationOrClassStaticBlock(currentClassElement) && - lexicalEnvironment?.data?.classConstructor + shouldTransformSuperInStaticInitializers + && currentClassElement + && isSuperProperty(node.expression) + && isStaticPropertyDeclarationOrClassStaticBlock(currentClassElement) + && lexicalEnvironment?.data?.classConstructor ) { // super.x() // super[x]() @@ -1389,8 +1474,8 @@ export function transformClassFields(context: TransformationContext): (x: Source function visitTaggedTemplateExpression(node: TaggedTemplateExpression) { if ( - isPrivateIdentifierPropertyAccessExpression(node.tag) && - accessPrivateIdentifier(node.tag.name) + isPrivateIdentifierPropertyAccessExpression(node.tag) + && accessPrivateIdentifier(node.tag.name) ) { // Bind the `this` correctly for tagged template literals when the tag is a private identifier property access. const { thisArg, target } = factory.createCallBinding(node.tag, hoistVariableDeclaration, languageVersion); @@ -1406,11 +1491,11 @@ export function transformClassFields(context: TransformationContext): (x: Source ); } if ( - shouldTransformSuperInStaticInitializers && - currentClassElement && - isSuperProperty(node.tag) && - isStaticPropertyDeclarationOrClassStaticBlock(currentClassElement) && - lexicalEnvironment?.data?.classConstructor + shouldTransformSuperInStaticInitializers + && currentClassElement + && isSuperProperty(node.tag) + && isStaticPropertyDeclarationOrClassStaticBlock(currentClassElement) + && lexicalEnvironment?.data?.classConstructor ) { // converts `` super.f`x` `` into `` Reflect.get(_baseTemp, "f", _classTemp).bind(_classTemp)`x` `` const invocation = factory.createFunctionBindCall( @@ -1441,8 +1526,8 @@ export function transformClassFields(context: TransformationContext): (x: Source // If the generated `_classThis` assignment is a noop (i.e., `_classThis = _classThis`), we can // eliminate the expression if ( - isAssignmentExpression(result, /*excludeCompoundAssignment*/ true) && - result.left === result.right + isAssignmentExpression(result, /*excludeCompoundAssignment*/ true) + && result.left === result.right ) { return undefined; } @@ -1477,12 +1562,12 @@ export function transformClassFields(context: TransformationContext): (x: Source return false; } - const hasTransformableStatics = (shouldTransformPrivateElementsOrClassStaticBlocks || - !!(getInternalEmitFlags(node) && InternalEmitFlags.TransformPrivateStaticElements)) && - some(staticPropertiesOrClassStaticBlocks, node => - isClassStaticBlockDeclaration(node) || - isPrivateIdentifierClassElementDeclaration(node) || - shouldTransformInitializers && isInitializedProperty(node)); + const hasTransformableStatics = (shouldTransformPrivateElementsOrClassStaticBlocks + || !!(getInternalEmitFlags(node) && InternalEmitFlags.TransformPrivateStaticElements)) + && some(staticPropertiesOrClassStaticBlocks, node => + isClassStaticBlockDeclaration(node) + || isPrivateIdentifierClassElementDeclaration(node) + || shouldTransformInitializers && isInitializedProperty(node)); return hasTransformableStatics; } return false; @@ -1501,9 +1586,9 @@ export function transformClassFields(context: TransformationContext): (x: Source node.operatorToken, visitNode(node.right, visitor, isExpression), ); - const expr = some(pendingExpressions) ? - factory.inlineExpressions(compact([...pendingExpressions, node])) : - node; + const expr = some(pendingExpressions) + ? factory.inlineExpressions(compact([...pendingExpressions, node])) + : node; pendingExpressions = savedPendingExpressions; return expr; } @@ -1539,14 +1624,22 @@ export function transformClassFields(context: TransformationContext): (x: Source Debug.assertNode(node, isAssignmentExpression); } - const left = skipOuterExpressions(node.left, OuterExpressionKinds.PartiallyEmittedExpressions | OuterExpressionKinds.Parentheses); + const left = skipOuterExpressions( + node.left, + OuterExpressionKinds.PartiallyEmittedExpressions | OuterExpressionKinds.Parentheses, + ); if (isPrivateIdentifierPropertyAccessExpression(left)) { // obj.#x = ... const info = accessPrivateIdentifier(left.name); if (info) { return setTextRange( setOriginalNode( - createPrivateIdentifierAssignment(info, left.expression, node.right, node.operatorToken.kind), + createPrivateIdentifierAssignment( + info, + left.expression, + node.right, + node.operatorToken.kind, + ), node, ), node, @@ -1554,11 +1647,11 @@ export function transformClassFields(context: TransformationContext): (x: Source } } else if ( - shouldTransformSuperInStaticInitializers && - currentClassElement && - isSuperProperty(node.left) && - isStaticPropertyDeclarationOrClassStaticBlock(currentClassElement) && - lexicalEnvironment?.data + shouldTransformSuperInStaticInitializers + && currentClassElement + && isSuperProperty(node.left) + && isStaticPropertyDeclarationOrClassStaticBlock(currentClassElement) + && lexicalEnvironment?.data ) { // super.x = ... // super[x] = ... @@ -1574,9 +1667,10 @@ export function transformClassFields(context: TransformationContext): (x: Source ); } if (classConstructor && superClassReference) { - let setterName = isElementAccessExpression(node.left) ? visitNode(node.left.argumentExpression, visitor, isExpression) : - isIdentifier(node.left.name) ? factory.createStringLiteralFromNode(node.left.name) : - undefined; + let setterName = isElementAccessExpression(node.left) + ? visitNode(node.left.argumentExpression, visitor, isExpression) + : isIdentifier(node.left.name) ? factory.createStringLiteralFromNode(node.left.name) + : undefined; if (setterName) { // converts `super.x = 1` into `(Reflect.set(_baseTemp, "x", _a = 1, _classTemp), _a)` // converts `super[f()] = 1` into `(Reflect.set(_baseTemp, f(), _a = 1, _classTemp), _a)` @@ -1638,9 +1732,9 @@ export function transformClassFields(context: TransformationContext): (x: Source } function visitCommaListExpression(node: CommaListExpression, discarded: boolean) { - const elements = discarded ? - visitCommaListElements(node.elements, discardedValueVisitor) : - visitCommaListElements(node.elements, visitor, discardedValueVisitor); + const elements = discarded + ? visitCommaListElements(node.elements, discardedValueVisitor) + : visitCommaListElements(node.elements, visitor, discardedValueVisitor); return factory.updateCommaListExpression(node, elements); } @@ -1650,13 +1744,18 @@ export function transformClassFields(context: TransformationContext): (x: Source // ... // 2. Return ? NamedEvaluation of |Expression| with argument _name_. - const visitorFunc: Visitor = discarded ? discardedValueVisitor : - visitor; + const visitorFunc: Visitor = discarded ? discardedValueVisitor + : visitor; const expression = visitNode(node.expression, visitorFunc, isExpression); return factory.updateParenthesizedExpression(node, expression); } - function createPrivateIdentifierAssignment(info: PrivateIdentifierInfo, receiver: Expression, right: Expression, operator: AssignmentOperator): Expression { + function createPrivateIdentifierAssignment( + info: PrivateIdentifierInfo, + receiver: Expression, + right: Expression, + operator: AssignmentOperator, + ): Expression { receiver = visitNode(receiver, visitor, isExpression); right = visitNode(right, visitor, isExpression); ensureDynamicThisIfNeeded(receiver); @@ -1716,7 +1815,10 @@ export function transformClassFields(context: TransformationContext): (x: Source if (isClassDeclaration(original) && classOrConstructorParameterIsDecorated(legacyDecorators, original)) { facts |= ClassFacts.ClassWasDecorated; } - if (shouldTransformPrivateElementsOrClassStaticBlocks && (classHasClassThisAssignment(node) || classHasExplicitlyAssignedName(node))) { + if ( + shouldTransformPrivateElementsOrClassStaticBlocks + && (classHasClassThisAssignment(node) || classHasExplicitlyAssignedName(node)) + ) { facts |= ClassFacts.NeedsClassConstructorReference; } let containsPublicInstanceFields = false; @@ -1726,22 +1828,31 @@ export function transformClassFields(context: TransformationContext): (x: Source for (const member of node.members) { if (isStatic(member)) { if ( - member.name && (isPrivateIdentifier(member.name) || isAutoAccessorPropertyDeclaration(member)) && - shouldTransformPrivateElementsOrClassStaticBlocks + member.name && (isPrivateIdentifier(member.name) || isAutoAccessorPropertyDeclaration(member)) + && shouldTransformPrivateElementsOrClassStaticBlocks ) { facts |= ClassFacts.NeedsClassConstructorReference; } - else if (isAutoAccessorPropertyDeclaration(member) && shouldTransformAutoAccessors === Ternary.True && !node.name && !node.emitNode?.classThis) { + else if ( + isAutoAccessorPropertyDeclaration(member) && shouldTransformAutoAccessors === Ternary.True + && !node.name && !node.emitNode?.classThis + ) { facts |= ClassFacts.NeedsClassConstructorReference; } if (isPropertyDeclaration(member) || isClassStaticBlockDeclaration(member)) { - if (shouldTransformThisInStaticInitializers && member.transformFlags & TransformFlags.ContainsLexicalThis) { + if ( + shouldTransformThisInStaticInitializers + && member.transformFlags & TransformFlags.ContainsLexicalThis + ) { facts |= ClassFacts.NeedsSubstitutionForThisInClassStaticField; if (!(facts & ClassFacts.ClassWasDecorated)) { facts |= ClassFacts.NeedsClassConstructorReference; } } - if (shouldTransformSuperInStaticInitializers && member.transformFlags & TransformFlags.ContainsLexicalSuper) { + if ( + shouldTransformSuperInStaticInitializers + && member.transformFlags & TransformFlags.ContainsLexicalSuper + ) { if (!(facts & ClassFacts.ClassWasDecorated)) { facts |= ClassFacts.NeedsClassConstructorReference | ClassFacts.NeedsClassSuperReference; } @@ -1766,10 +1877,12 @@ export function transformClassFields(context: TransformationContext): (x: Source } } - const willHoistInitializersToConstructor = shouldTransformInitializersUsingDefine && containsPublicInstanceFields || - shouldTransformInitializersUsingSet && containsInitializedPublicInstanceFields || - shouldTransformPrivateElementsOrClassStaticBlocks && containsInstancePrivateElements || - shouldTransformPrivateElementsOrClassStaticBlocks && containsInstanceAutoAccessors && shouldTransformAutoAccessors === Ternary.True; + const willHoistInitializersToConstructor = + shouldTransformInitializersUsingDefine && containsPublicInstanceFields + || shouldTransformInitializersUsingSet && containsInitializedPublicInstanceFields + || shouldTransformPrivateElementsOrClassStaticBlocks && containsInstancePrivateElements + || shouldTransformPrivateElementsOrClassStaticBlocks && containsInstanceAutoAccessors + && shouldTransformAutoAccessors === Ternary.True; if (willHoistInitializersToConstructor) { facts |= ClassFacts.WillHoistInitializersToConstructor; @@ -1795,7 +1908,10 @@ export function transformClassFields(context: TransformationContext): (x: Source return visitEachChild(node, visitor, context); } - function visitInNewClassLexicalEnvironment(node: T, visitor: (node: T, facts: ClassFacts) => U) { + function visitInNewClassLexicalEnvironment( + node: T, + visitor: (node: T, facts: ClassFacts) => U, + ) { const savedCurrentClassContainer = currentClassContainer; const savedPendingExpressions = pendingExpressions; const savedLexicalEnvironment = lexicalEnvironment; @@ -1803,7 +1919,8 @@ export function transformClassFields(context: TransformationContext): (x: Source pendingExpressions = undefined; startClassLexicalEnvironment(); - const shouldAlwaysTransformPrivateStaticElements = getInternalEmitFlags(node) & InternalEmitFlags.TransformPrivateStaticElements; + const shouldAlwaysTransformPrivateStaticElements = getInternalEmitFlags(node) + & InternalEmitFlags.TransformPrivateStaticElements; if (shouldTransformPrivateElementsOrClassStaticBlocks || shouldAlwaysTransformPrivateStaticElements) { const name = getNameOfDeclaration(node); if (name && isIdentifier(name)) { @@ -1814,8 +1931,8 @@ export function transformClassFields(context: TransformationContext): (x: Source // If the class name was assigned from a string literal based on an Identifier, use the Identifier // as the prefix. if ( - node.emitNode.assignedName.textSourceNode && - isIdentifier(node.emitNode.assignedName.textSourceNode) + node.emitNode.assignedName.textSourceNode + && isIdentifier(node.emitNode.assignedName.textSourceNode) ) { getPrivateIdentifierEnvironment().data.className = node.emitNode.assignedName.textSourceNode; } @@ -1876,7 +1993,10 @@ export function transformClassFields(context: TransformationContext): (x: Source if (shouldTransformPrivateElementsOrClassStaticBlocks && node.emitNode?.classThis) { getClassLexicalEnvironment().classConstructor = node.emitNode.classThis; - pendingClassReferenceAssignment = factory.createAssignment(node.emitNode.classThis, factory.getInternalName(node)); + pendingClassReferenceAssignment = factory.createAssignment( + node.emitNode.classThis, + factory.getInternalName(node), + ); } else { const temp = factory.createTempVariable(hoistVariableDeclaration, /*reservedInNestedScopes*/ true); @@ -1889,7 +2009,8 @@ export function transformClassFields(context: TransformationContext): (x: Source getClassLexicalEnvironment().classThis = node.emitNode.classThis; } - const isClassWithConstructorReference = resolver.getNodeCheckFlags(node) & NodeCheckFlags.ContainsConstructorReference; + const isClassWithConstructorReference = resolver.getNodeCheckFlags(node) + & NodeCheckFlags.ContainsConstructorReference; const isExport = hasSyntacticModifier(node, ModifierFlags.Export); const isDefault = hasSyntacticModifier(node, ModifierFlags.Default); let modifiers = visitNodes(node.modifiers, modifierVisitor, isModifier); @@ -1906,7 +2027,10 @@ export function transformClassFields(context: TransformationContext): (x: Source statements.push(factory.createExpressionStatement(factory.inlineExpressions(pendingExpressions))); } - if (shouldTransformInitializersUsingSet || shouldTransformPrivateElementsOrClassStaticBlocks || getInternalEmitFlags(node) & InternalEmitFlags.TransformPrivateStaticElements) { + if ( + shouldTransformInitializersUsingSet || shouldTransformPrivateElementsOrClassStaticBlocks + || getInternalEmitFlags(node) & InternalEmitFlags.TransformPrivateStaticElements + ) { // Emit static property assignment. Because classDeclaration is lexically evaluated, // it is safe to emit static property assignment after classDeclaration // From ES6 specification: @@ -1984,7 +2108,10 @@ export function transformClassFields(context: TransformationContext): (x: Source } const requiresBlockScopedVar = classCheckFlags & NodeCheckFlags.BlockScopedBindingInLoop; - const temp = factory.createTempVariable(requiresBlockScopedVar ? addBlockScopedVariable : hoistVariableDeclaration, /*reservedInNestedScopes*/ true); + const temp = factory.createTempVariable( + requiresBlockScopedVar ? addBlockScopedVariable : hoistVariableDeclaration, + /*reservedInNestedScopes*/ true, + ); getClassLexicalEnvironment().classConstructor = factory.cloneNode(temp); return temp; } @@ -2016,15 +2143,19 @@ export function transformClassFields(context: TransformationContext): (x: Source // Static initializers are transformed to `static {}` blocks when `useDefineForClassFields: false` // and not also transforming static blocks. - const hasTransformableStatics = (shouldTransformPrivateElementsOrClassStaticBlocks || getInternalEmitFlags(node) & InternalEmitFlags.TransformPrivateStaticElements) && - some(staticPropertiesOrClassStaticBlocks, node => - isClassStaticBlockDeclaration(node) || - isPrivateIdentifierClassElementDeclaration(node) || - shouldTransformInitializers && isInitializedProperty(node)); + const hasTransformableStatics = (shouldTransformPrivateElementsOrClassStaticBlocks + || getInternalEmitFlags(node) & InternalEmitFlags.TransformPrivateStaticElements) + && some(staticPropertiesOrClassStaticBlocks, node => + isClassStaticBlockDeclaration(node) + || isPrivateIdentifierClassElementDeclaration(node) + || shouldTransformInitializers && isInitializedProperty(node)); if (hasTransformableStatics || some(pendingExpressions)) { if (isDecoratedClassDeclaration) { - Debug.assertIsDefined(pendingStatements, "Decorated classes transformed by TypeScript are expected to be within a variable declaration."); + Debug.assertIsDefined( + pendingStatements, + "Decorated classes transformed by TypeScript are expected to be within a variable declaration.", + ); // Write any pending expressions from elided or moved computed property names if (some(pendingExpressions)) { @@ -2032,7 +2163,11 @@ export function transformClassFields(context: TransformationContext): (x: Source } if (some(staticPropertiesOrClassStaticBlocks)) { - addPropertyOrClassStaticBlockStatements(pendingStatements, staticPropertiesOrClassStaticBlocks, node.emitNode?.classThis ?? factory.getInternalName(node)); + addPropertyOrClassStaticBlockStatements( + pendingStatements, + staticPropertiesOrClassStaticBlocks, + node.emitNode?.classThis ?? factory.getInternalName(node), + ); } if (temp) { @@ -2059,7 +2194,10 @@ export function transformClassFields(context: TransformationContext): (x: Source // Add any pending expressions leftover from elided or relocated computed property names addRange(expressions, pendingExpressions); - addRange(expressions, generateInitializedPropertyExpressionsOrClassStaticBlock(staticPropertiesOrClassStaticBlocks, temp)); + addRange( + expressions, + generateInitializedPropertyExpressionsOrClassStaticBlock(staticPropertiesOrClassStaticBlocks, temp), + ); expressions.push(factory.cloneNode(temp)); } } @@ -2087,9 +2225,9 @@ export function transformClassFields(context: TransformationContext): (x: Source function visitThisExpression(node: ThisExpression) { if ( - shouldTransformThisInStaticInitializers && currentClassElement && - isClassStaticBlockDeclaration(currentClassElement) && - lexicalEnvironment?.data + shouldTransformThisInStaticInitializers && currentClassElement + && isClassStaticBlockDeclaration(currentClassElement) + && lexicalEnvironment?.data ) { const { classThis, classConstructor } = lexicalEnvironment.data; return classThis ?? classConstructor ?? node; @@ -2099,14 +2237,19 @@ export function transformClassFields(context: TransformationContext): (x: Source } function transformClassMembers(node: ClassDeclaration | ClassExpression) { - const shouldTransformPrivateStaticElementsInClass = !!(getInternalEmitFlags(node) & InternalEmitFlags.TransformPrivateStaticElements); + const shouldTransformPrivateStaticElementsInClass = + !!(getInternalEmitFlags(node) & InternalEmitFlags.TransformPrivateStaticElements); // Declare private names if (shouldTransformPrivateElementsOrClassStaticBlocks || shouldTransformPrivateStaticElementsInFile) { for (const member of node.members) { if (isPrivateIdentifierClassElementDeclaration(member)) { if (shouldTransformClassElementToWeakMap(member)) { - addPrivateIdentifierToEnvironment(member, member.name, addPrivateIdentifierClassElementToEnvironment); + addPrivateIdentifierToEnvironment( + member, + member.name, + addPrivateIdentifierClassElementToEnvironment, + ); } else { const privateEnv = getPrivateIdentifierEnvironment(); @@ -2124,12 +2267,20 @@ export function transformClassFields(context: TransformationContext): (x: Source if (shouldTransformAutoAccessorsInCurrentClass()) { for (const member of node.members) { if (isAutoAccessorPropertyDeclaration(member)) { - const storageName = factory.getGeneratedPrivateNameForNode(member.name, /*prefix*/ undefined, "_accessor_storage"); + const storageName = factory.getGeneratedPrivateNameForNode( + member.name, + /*prefix*/ undefined, + "_accessor_storage", + ); if ( - shouldTransformPrivateElementsOrClassStaticBlocks || - shouldTransformPrivateStaticElementsInClass && hasStaticModifier(member) + shouldTransformPrivateElementsOrClassStaticBlocks + || shouldTransformPrivateStaticElementsInClass && hasStaticModifier(member) ) { - addPrivateIdentifierToEnvironment(member, storageName, addPrivateIdentifierPropertyDeclarationToEnvironment); + addPrivateIdentifierToEnvironment( + member, + storageName, + addPrivateIdentifierPropertyDeclarationToEnvironment, + ); } else { const privateEnv = getPrivateIdentifierEnvironment(); @@ -2171,7 +2322,9 @@ export function transformClassFields(context: TransformationContext): (x: Source factory.createBlock([statement]), ); prologue = factory.createAssignment(temp, arrow); - statement = factory.createExpressionStatement(factory.createCallExpression(temp, /*typeArguments*/ undefined, [])); + statement = factory.createExpressionStatement( + factory.createCallExpression(temp, /*typeArguments*/ undefined, []), + ); } const block = factory.createBlock([statement]); @@ -2189,9 +2342,12 @@ export function transformClassFields(context: TransformationContext): (x: Source membersArray = append(membersArray, classNamedEvaluationHelperBlock); membersArray = append(membersArray, syntheticConstructor); membersArray = append(membersArray, syntheticStaticBlock); - const remainingMembers = classThisAssignmentBlock || classNamedEvaluationHelperBlock ? - filter(members, member => member !== classThisAssignmentBlock && member !== classNamedEvaluationHelperBlock) : - members; + const remainingMembers = classThisAssignmentBlock || classNamedEvaluationHelperBlock + ? filter( + members, + member => member !== classThisAssignmentBlock && member !== classNamedEvaluationHelperBlock, + ) + : members; membersArray = addRange(membersArray, remainingMembers); members = setTextRange(factory.createNodeArray(membersArray), /*location*/ node.members); } @@ -2215,14 +2371,21 @@ export function transformClassFields(context: TransformationContext): (x: Source ); } - function transformConstructor(constructor: ConstructorDeclaration | undefined, container: ClassDeclaration | ClassExpression) { + function transformConstructor( + constructor: ConstructorDeclaration | undefined, + container: ClassDeclaration | ClassExpression, + ) { constructor = visitNode(constructor, visitor, isConstructorDeclaration); - if (!lexicalEnvironment?.data || !(lexicalEnvironment.data.facts & ClassFacts.WillHoistInitializersToConstructor)) { + if ( + !lexicalEnvironment?.data + || !(lexicalEnvironment.data.facts & ClassFacts.WillHoistInitializersToConstructor) + ) { return constructor; } const extendsClauseElement = getEffectiveBaseTypeNode(container); - const isDerivedClass = !!(extendsClauseElement && skipOuterExpressions(extendsClauseElement.expression).kind !== SyntaxKind.NullKeyword); + const isDerivedClass = !!(extendsClauseElement + && skipOuterExpressions(extendsClauseElement.expression).kind !== SyntaxKind.NullKeyword); const parameters = visitParameterList(constructor ? constructor.parameters : undefined, visitor, context); const body = transformConstructorBody(container, constructor, isDerivedClass); if (!body) { @@ -2249,10 +2412,21 @@ export function transformClassFields(context: TransformationContext): (x: Source ); } - function transformConstructorBodyWorker(statementsOut: Statement[], statementsIn: NodeArray, statementOffset: number, superPath: readonly number[], superPathDepth: number, initializerStatements: readonly Statement[], constructor: ConstructorDeclaration) { + function transformConstructorBodyWorker( + statementsOut: Statement[], + statementsIn: NodeArray, + statementOffset: number, + superPath: readonly number[], + superPathDepth: number, + initializerStatements: readonly Statement[], + constructor: ConstructorDeclaration, + ) { const superStatementIndex = superPath[superPathDepth]; const superStatement = statementsIn[superStatementIndex]; - addRange(statementsOut, visitNodes(statementsIn, visitor, isStatement, statementOffset, superStatementIndex - statementOffset)); + addRange( + statementsOut, + visitNodes(statementsIn, visitor, isStatement, statementOffset, superStatementIndex - statementOffset), + ); statementOffset = superStatementIndex + 1; if (isTryStatement(superStatement)) { const tryBlockStatements: Statement[] = []; @@ -2311,11 +2485,19 @@ export function transformClassFields(context: TransformationContext): (x: Source addRange(statementsOut, visitNodes(statementsIn, visitor, isStatement, statementOffset)); } - function transformConstructorBody(node: ClassDeclaration | ClassExpression, constructor: ConstructorDeclaration | undefined, isDerivedClass: boolean) { + function transformConstructorBody( + node: ClassDeclaration | ClassExpression, + constructor: ConstructorDeclaration | undefined, + isDerivedClass: boolean, + ) { const instanceProperties = getProperties(node, /*requireInitializer*/ false, /*isStatic*/ false); let properties = instanceProperties; if (!useDefineForClassFields) { - properties = filter(properties, property => !!property.initializer || isPrivateIdentifier(property.name) || hasAccessorModifier(property)); + properties = filter( + properties, + property => + !!property.initializer || isPrivateIdentifier(property.name) || hasAccessorModifier(property), + ); } const privateMethodsAndAccessors = getPrivateInstanceMethodsAndAccessors(node); @@ -2348,8 +2530,14 @@ export function transformClassFields(context: TransformationContext): (x: Source // private methods can be called in property initializers, they should execute first. addInstanceMethodStatements(initializerStatements, privateMethodsAndAccessors, receiver); if (constructor) { - const parameterProperties = filter(instanceProperties, prop => isParameterPropertyDeclaration(getOriginalNode(prop), constructor)); - const nonParameterProperties = filter(properties, prop => !isParameterPropertyDeclaration(getOriginalNode(prop), constructor)); + const parameterProperties = filter( + instanceProperties, + prop => isParameterPropertyDeclaration(getOriginalNode(prop), constructor), + ); + const nonParameterProperties = filter( + properties, + prop => !isParameterPropertyDeclaration(getOriginalNode(prop), constructor), + ); addPropertyOrClassStaticBlockStatements(initializerStatements, parameterProperties, receiver); addPropertyOrClassStaticBlockStatements(initializerStatements, nonParameterProperties, receiver); } @@ -2358,7 +2546,12 @@ export function transformClassFields(context: TransformationContext): (x: Source } if (constructor?.body) { - statementOffset = factory.copyPrologue(constructor.body.statements, statements, /*ensureUseStrict*/ false, visitor); + statementOffset = factory.copyPrologue( + constructor.body.statements, + statements, + /*ensureUseStrict*/ false, + visitor, + ); const superStatementIndices = findSuperStatementIndexPath(constructor.body.statements, statementOffset); if (superStatementIndices.length) { transformConstructorBodyWorker( @@ -2412,9 +2605,9 @@ export function transformClassFields(context: TransformationContext): (x: Source return undefined; } - const multiLine = constructor?.body && constructor.body.statements.length >= statements.length ? - constructor.body.multiLine ?? statements.length > 0 : - statements.length > 0; + const multiLine = constructor?.body && constructor.body.statements.length >= statements.length + ? constructor.body.multiLine ?? statements.length > 0 + : statements.length > 0; return setTextRange( factory.createBlock( @@ -2434,7 +2627,11 @@ export function transformClassFields(context: TransformationContext): (x: Source * @param properties An array of property declarations to transform. * @param receiver The receiver on which each property should be assigned. */ - function addPropertyOrClassStaticBlockStatements(statements: Statement[], properties: readonly (PropertyDeclaration | ClassStaticBlockDeclaration)[], receiver: LeftHandSideExpression) { + function addPropertyOrClassStaticBlockStatements( + statements: Statement[], + properties: readonly (PropertyDeclaration | ClassStaticBlockDeclaration)[], + receiver: LeftHandSideExpression, + ) { for (const property of properties) { if (isStatic(property) && !shouldTransformPrivateElementsOrClassStaticBlocks) { continue; @@ -2449,10 +2646,13 @@ export function transformClassFields(context: TransformationContext): (x: Source } } - function transformPropertyOrClassStaticBlock(property: PropertyDeclaration | ClassStaticBlockDeclaration, receiver: LeftHandSideExpression) { - const expression = isClassStaticBlockDeclaration(property) ? - setCurrentClassElementAnd(property, transformClassStaticBlockDeclaration, property) : - transformProperty(property, receiver); + function transformPropertyOrClassStaticBlock( + property: PropertyDeclaration | ClassStaticBlockDeclaration, + receiver: LeftHandSideExpression, + ) { + const expression = isClassStaticBlockDeclaration(property) + ? setCurrentClassElementAnd(property, transformClassStaticBlockDeclaration, property) + : transformProperty(property, receiver); if (!expression) { return undefined; } @@ -2493,12 +2693,15 @@ export function transformClassFields(context: TransformationContext): (x: Source * @param propertiesOrClassStaticBlocks An array of property declarations to transform. * @param receiver The receiver on which each property should be assigned. */ - function generateInitializedPropertyExpressionsOrClassStaticBlock(propertiesOrClassStaticBlocks: readonly (PropertyDeclaration | ClassStaticBlockDeclaration)[], receiver: LeftHandSideExpression) { + function generateInitializedPropertyExpressionsOrClassStaticBlock( + propertiesOrClassStaticBlocks: readonly (PropertyDeclaration | ClassStaticBlockDeclaration)[], + receiver: LeftHandSideExpression, + ) { const expressions: Expression[] = []; for (const property of propertiesOrClassStaticBlocks) { - const expression = isClassStaticBlockDeclaration(property) ? - setCurrentClassElementAnd(property, transformClassStaticBlockDeclaration, property) : - setCurrentClassElementAnd(property, () => transformProperty(property, receiver), /*arg*/ undefined); + const expression = isClassStaticBlockDeclaration(property) + ? setCurrentClassElementAnd(property, transformClassStaticBlockDeclaration, property) + : setCurrentClassElementAnd(property, () => transformProperty(property, receiver), /*arg*/ undefined); if (!expression) { continue; } @@ -2541,17 +2744,20 @@ export function transformClassFields(context: TransformationContext): (x: Source property = transformNamedEvaluation(context, property); } - const propertyName = hasAccessorModifier(property) ? - factory.getGeneratedPrivateNameForNode(property.name) : - isComputedPropertyName(property.name) && !isSimpleInlineableExpression(property.name.expression) ? - factory.updateComputedPropertyName(property.name, factory.getGeneratedNameForNode(property.name)) : - property.name; + const propertyName = hasAccessorModifier(property) + ? factory.getGeneratedPrivateNameForNode(property.name) + : isComputedPropertyName(property.name) && !isSimpleInlineableExpression(property.name.expression) + ? factory.updateComputedPropertyName(property.name, factory.getGeneratedNameForNode(property.name)) + : property.name; if (hasStaticModifier(property)) { currentClassElement = property; } - if (isPrivateIdentifier(propertyName) && shouldTransformClassElementToWeakMap(property as PrivateIdentifierPropertyDeclaration)) { + if ( + isPrivateIdentifier(propertyName) + && shouldTransformClassElementToWeakMap(property as PrivateIdentifierPropertyDeclaration) + ) { const privateIdentifierInfo = accessPrivateIdentifier(propertyName); if (privateIdentifierInfo) { if (privateIdentifierInfo.kind === PrivateIdentifierKind.Field) { @@ -2589,7 +2795,10 @@ export function transformClassFields(context: TransformationContext): (x: Source } let initializer = visitNode(property.initializer, visitor, isExpression); - if (isParameterPropertyDeclaration(propertyOriginalNode, propertyOriginalNode.parent) && isIdentifier(propertyName)) { + if ( + isParameterPropertyDeclaration(propertyOriginalNode, propertyOriginalNode.parent) + && isIdentifier(propertyName) + ) { // A parameter-property declaration always overrides the initializer. The only time a parameter-property // declaration *should* have an initializer is when decorators have added initializers that need to run before // any other initializer @@ -2597,11 +2806,11 @@ export function transformClassFields(context: TransformationContext): (x: Source if (initializer) { // unwrap `(__runInitializers(this, _instanceExtraInitializers), void 0)` if ( - isParenthesizedExpression(initializer) && - isCommaExpression(initializer.expression) && - isCallToHelper(initializer.expression.left, "___runInitializers" as __String) && - isVoidExpression(initializer.expression.right) && - isNumericLiteral(initializer.expression.right.expression) + isParenthesizedExpression(initializer) + && isCommaExpression(initializer.expression) + && isCallToHelper(initializer.expression.left, "___runInitializers" as __String) + && isVoidExpression(initializer.expression.right) + && isNumericLiteral(initializer.expression.right.expression) ) { initializer = initializer.expression.left; } @@ -2619,16 +2828,27 @@ export function transformClassFields(context: TransformationContext): (x: Source } if (emitAssignment || isPrivateIdentifier(propertyName)) { - const memberAccess = createMemberAccessForPropertyName(factory, receiver, propertyName, /*location*/ propertyName); + const memberAccess = createMemberAccessForPropertyName( + factory, + receiver, + propertyName, + /*location*/ propertyName, + ); addEmitFlags(memberAccess, EmitFlags.NoLeadingComments); const expression = factory.createAssignment(memberAccess, initializer); return expression; } else { const name = isComputedPropertyName(propertyName) ? propertyName.expression - : isIdentifier(propertyName) ? factory.createStringLiteral(unescapeLeadingUnderscores(propertyName.escapedText)) + : isIdentifier(propertyName) + ? factory.createStringLiteral(unescapeLeadingUnderscores(propertyName.escapedText)) : propertyName; - const descriptor = factory.createPropertyDescriptor({ value: initializer, configurable: true, writable: true, enumerable: true }); + const descriptor = factory.createPropertyDescriptor({ + value: initializer, + configurable: true, + writable: true, + enumerable: true, + }); return factory.createObjectDefinePropertyCall(receiver, name, descriptor); } } @@ -2670,7 +2890,11 @@ export function transformClassFields(context: TransformationContext): (x: Source * @param methods An array of method declarations. * @param receiver The receiver on which each method should be assigned. */ - function addInstanceMethodStatements(statements: Statement[], methods: readonly (MethodDeclaration | AccessorDeclaration | AutoAccessorPropertyDeclaration)[], receiver: LeftHandSideExpression) { + function addInstanceMethodStatements( + statements: Statement[], + methods: readonly (MethodDeclaration | AccessorDeclaration | AutoAccessorPropertyDeclaration)[], + receiver: LeftHandSideExpression, + ) { if (!shouldTransformPrivateElementsOrClassStaticBlocks || !some(methods)) { return; } @@ -2685,13 +2909,13 @@ export function transformClassFields(context: TransformationContext): (x: Source } function visitInvalidSuperProperty(node: SuperProperty) { - return isPropertyAccessExpression(node) ? - factory.updatePropertyAccessExpression( + return isPropertyAccessExpression(node) + ? factory.updatePropertyAccessExpression( node, factory.createVoidZero(), node.name, - ) : - factory.updateElementAccessExpression( + ) + : factory.updateElementAccessExpression( node, factory.createVoidZero(), visitNode(node.argumentExpression, visitor, isExpression), @@ -2709,7 +2933,8 @@ export function transformClassFields(context: TransformationContext): (x: Source const expression = visitNode(name.expression, visitor, isExpression); const innerExpression = skipPartiallyEmittedExpressions(expression); const inlinable = isSimpleInlineableExpression(innerExpression); - const alreadyTransformed = !!cacheAssignment || isAssignmentExpression(innerExpression) && isGeneratedIdentifier(innerExpression.left); + const alreadyTransformed = !!cacheAssignment + || isAssignmentExpression(innerExpression) && isGeneratedIdentifier(innerExpression.left); if (!alreadyTransformed && !inlinable && shouldHoist) { const generatedName = factory.getGeneratedNameForNode(name); if (resolver.getNodeCheckFlags(name) & NodeCheckFlags.BlockScopedBindingInLoop) { @@ -2765,19 +2990,59 @@ export function transformClassFields(context: TransformationContext): (x: Source previousInfo: PrivateIdentifierInfo | undefined, ) { if (isAutoAccessorPropertyDeclaration(node)) { - addPrivateIdentifierAutoAccessorPropertyDeclarationToEnvironment(node, name, lex, privateEnv, isStatic, isValid, previousInfo); + addPrivateIdentifierAutoAccessorPropertyDeclarationToEnvironment( + node, + name, + lex, + privateEnv, + isStatic, + isValid, + previousInfo, + ); } else if (isPropertyDeclaration(node)) { - addPrivateIdentifierPropertyDeclarationToEnvironment(node, name, lex, privateEnv, isStatic, isValid, previousInfo); + addPrivateIdentifierPropertyDeclarationToEnvironment( + node, + name, + lex, + privateEnv, + isStatic, + isValid, + previousInfo, + ); } else if (isMethodDeclaration(node)) { - addPrivateIdentifierMethodDeclarationToEnvironment(node, name, lex, privateEnv, isStatic, isValid, previousInfo); + addPrivateIdentifierMethodDeclarationToEnvironment( + node, + name, + lex, + privateEnv, + isStatic, + isValid, + previousInfo, + ); } else if (isGetAccessorDeclaration(node)) { - addPrivateIdentifierGetAccessorDeclarationToEnvironment(node, name, lex, privateEnv, isStatic, isValid, previousInfo); + addPrivateIdentifierGetAccessorDeclarationToEnvironment( + node, + name, + lex, + privateEnv, + isStatic, + isValid, + previousInfo, + ); } else if (isSetAccessorDeclaration(node)) { - addPrivateIdentifierSetAccessorDeclarationToEnvironment(node, name, lex, privateEnv, isStatic, isValid, previousInfo); + addPrivateIdentifierSetAccessorDeclarationToEnvironment( + node, + name, + lex, + privateEnv, + isStatic, + isValid, + previousInfo, + ); } } @@ -2791,7 +3056,10 @@ export function transformClassFields(context: TransformationContext): (x: Source _previousInfo: PrivateIdentifierInfo | undefined, ) { if (isStatic) { - const brandCheckIdentifier = Debug.checkDefined(lex.classThis ?? lex.classConstructor, "classConstructor should be set in private identifier environment"); + const brandCheckIdentifier = Debug.checkDefined( + lex.classThis ?? lex.classConstructor, + "classConstructor should be set in private identifier environment", + ); const variableName = createHoistedVariableForPrivateName(name); setPrivateIdentifier(privateEnv, name, { @@ -2833,9 +3101,15 @@ export function transformClassFields(context: TransformationContext): (x: Source _previousInfo: PrivateIdentifierInfo | undefined, ) { const methodName = createHoistedVariableForPrivateName(name); - const brandCheckIdentifier = isStatic ? - Debug.checkDefined(lex.classThis ?? lex.classConstructor, "classConstructor should be set in private identifier environment") : - Debug.checkDefined(privateEnv.data.weakSetName, "weakSetName should be set in private identifier environment"); + const brandCheckIdentifier = isStatic + ? Debug.checkDefined( + lex.classThis ?? lex.classConstructor, + "classConstructor should be set in private identifier environment", + ) + : Debug.checkDefined( + privateEnv.data.weakSetName, + "weakSetName should be set in private identifier environment", + ); setPrivateIdentifier(privateEnv, name, { kind: PrivateIdentifierKind.Method, @@ -2856,11 +3130,20 @@ export function transformClassFields(context: TransformationContext): (x: Source previousInfo: PrivateIdentifierInfo | undefined, ) { const getterName = createHoistedVariableForPrivateName(name, "_get"); - const brandCheckIdentifier = isStatic ? - Debug.checkDefined(lex.classThis ?? lex.classConstructor, "classConstructor should be set in private identifier environment") : - Debug.checkDefined(privateEnv.data.weakSetName, "weakSetName should be set in private identifier environment"); + const brandCheckIdentifier = isStatic + ? Debug.checkDefined( + lex.classThis ?? lex.classConstructor, + "classConstructor should be set in private identifier environment", + ) + : Debug.checkDefined( + privateEnv.data.weakSetName, + "weakSetName should be set in private identifier environment", + ); - if (previousInfo?.kind === PrivateIdentifierKind.Accessor && previousInfo.isStatic === isStatic && !previousInfo.getterName) { + if ( + previousInfo?.kind === PrivateIdentifierKind.Accessor && previousInfo.isStatic === isStatic + && !previousInfo.getterName + ) { previousInfo.getterName = getterName; } else { @@ -2885,13 +3168,19 @@ export function transformClassFields(context: TransformationContext): (x: Source previousInfo: PrivateIdentifierInfo | undefined, ) { const setterName = createHoistedVariableForPrivateName(name, "_set"); - const brandCheckIdentifier = isStatic ? - Debug.checkDefined(lex.classThis ?? lex.classConstructor, "classConstructor should be set in private identifier environment") : - Debug.checkDefined(privateEnv.data.weakSetName, "weakSetName should be set in private identifier environment"); + const brandCheckIdentifier = isStatic + ? Debug.checkDefined( + lex.classThis ?? lex.classConstructor, + "classConstructor should be set in private identifier environment", + ) + : Debug.checkDefined( + privateEnv.data.weakSetName, + "weakSetName should be set in private identifier environment", + ); if ( - previousInfo?.kind === PrivateIdentifierKind.Accessor && - previousInfo.isStatic === isStatic && !previousInfo.setterName + previousInfo?.kind === PrivateIdentifierKind.Accessor + && previousInfo.isStatic === isStatic && !previousInfo.setterName ) { previousInfo.setterName = setterName; } @@ -2918,9 +3207,15 @@ export function transformClassFields(context: TransformationContext): (x: Source ) { const getterName = createHoistedVariableForPrivateName(name, "_get"); const setterName = createHoistedVariableForPrivateName(name, "_set"); - const brandCheckIdentifier = isStatic ? - Debug.checkDefined(lex.classThis ?? lex.classConstructor, "classConstructor should be set in private identifier environment") : - Debug.checkDefined(privateEnv.data.weakSetName, "weakSetName should be set in private identifier environment"); + const brandCheckIdentifier = isStatic + ? Debug.checkDefined( + lex.classThis ?? lex.classConstructor, + "classConstructor should be set in private identifier environment", + ) + : Debug.checkDefined( + privateEnv.data.weakSetName, + "weakSetName should be set in private identifier environment", + ); setPrivateIdentifier(privateEnv, name, { kind: PrivateIdentifierKind.Accessor, @@ -2932,7 +3227,9 @@ export function transformClassFields(context: TransformationContext): (x: Source }); } - function addPrivateIdentifierToEnvironment( + function addPrivateIdentifierToEnvironment< + T extends PropertyDeclaration | MethodDeclaration | GetAccessorDeclaration | SetAccessorDeclaration, + >( node: T, name: PrivateIdentifier, addDeclaration: ( @@ -2953,12 +3250,28 @@ export function transformClassFields(context: TransformationContext): (x: Source addDeclaration(node, name, lex, privateEnv, isStatic, isValid, previousInfo); } - function createHoistedVariableForClass(name: string | PrivateIdentifier | undefined, node: PrivateIdentifier | ClassStaticBlockDeclaration, suffix?: string): Identifier { + function createHoistedVariableForClass( + name: string | PrivateIdentifier | undefined, + node: PrivateIdentifier | ClassStaticBlockDeclaration, + suffix?: string, + ): Identifier { const { className } = getPrivateIdentifierEnvironment().data; const prefix: GeneratedNamePart | string = className ? { prefix: "_", node: className, suffix: "_" } : "_"; - const identifier = typeof name === "object" ? factory.getGeneratedNameForNode(name, GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.ReservedInNestedScopes, prefix, suffix) : - typeof name === "string" ? factory.createUniqueName(name, GeneratedIdentifierFlags.Optimistic, prefix, suffix) : - factory.createTempVariable(/*recordTempVariable*/ undefined, /*reservedInNestedScopes*/ true, prefix, suffix); + const identifier = typeof name === "object" + ? factory.getGeneratedNameForNode( + name, + GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.ReservedInNestedScopes, + prefix, + suffix, + ) + : typeof name === "string" + ? factory.createUniqueName(name, GeneratedIdentifierFlags.Optimistic, prefix, suffix) + : factory.createTempVariable( + /*recordTempVariable*/ undefined, + /*reservedInNestedScopes*/ true, + prefix, + suffix, + ); if (resolver.getNodeCheckFlags(node) & NodeCheckFlags.BlockScopedBindingInLoop) { addBlockScopedVariable(identifier); @@ -2996,7 +3309,13 @@ export function transformClassFields(context: TransformationContext): (x: Source // differently inside the function. if (isThisProperty(node) || isSuperProperty(node) || !isSimpleCopiableExpression(node.expression)) { receiver = factory.createTempVariable(hoistVariableDeclaration, /*reservedInNestedScopes*/ true); - getPendingExpressions().push(factory.createBinaryExpression(receiver, SyntaxKind.EqualsToken, visitNode(node.expression, visitor, isExpression))); + getPendingExpressions().push( + factory.createBinaryExpression( + receiver, + SyntaxKind.EqualsToken, + visitNode(node.expression, visitor, isExpression), + ), + ); } return factory.createAssignmentTargetWrapper( parameter, @@ -3018,20 +3337,20 @@ export function transformClassFields(context: TransformationContext): (x: Source return wrapPrivateIdentifierForDestructuringTarget(node); } else if ( - shouldTransformSuperInStaticInitializers && - currentClassElement && - isSuperProperty(node) && - isStaticPropertyDeclarationOrClassStaticBlock(currentClassElement) && - lexicalEnvironment?.data + shouldTransformSuperInStaticInitializers + && currentClassElement + && isSuperProperty(node) + && isStaticPropertyDeclarationOrClassStaticBlock(currentClassElement) + && lexicalEnvironment?.data ) { const { classConstructor, superClassReference, facts } = lexicalEnvironment.data; if (facts & ClassFacts.ClassWasDecorated) { return visitInvalidSuperProperty(node); } else if (classConstructor && superClassReference) { - const name = isElementAccessExpression(node) ? visitNode(node.argumentExpression, visitor, isExpression) : - isIdentifier(node.name) ? factory.createStringLiteralFromNode(node.name) : - undefined; + const name = isElementAccessExpression(node) ? visitNode(node.argumentExpression, visitor, isExpression) + : isIdentifier(node.name) ? factory.createStringLiteralFromNode(node.name) + : undefined; if (name) { const temp = factory.createTempVariable(/*recordTempVariable*/ undefined); return factory.createAssignmentTargetWrapper( @@ -3049,7 +3368,9 @@ export function transformClassFields(context: TransformationContext): (x: Source return visitEachChild(node, visitor, context); } - function visitAssignmentElement(node: Exclude): ArrayAssignmentElement { + function visitAssignmentElement( + node: Exclude, + ): ArrayAssignmentElement { // 13.15.5.5 RS: IteratorDestructuringAssignmentEvaluation // AssignmentElement : DestructuringAssignmentTarget Initializer? // ... @@ -3064,7 +3385,9 @@ export function transformClassFields(context: TransformationContext): (x: Source if (isAssignmentExpression(node, /*excludeCompoundAssignment*/ true)) { const left = visitDestructuringAssignmentTarget(node.left); const right = visitNode(node.right, visitor, isExpression); - return factory.updateBinaryExpression(node, left, node.operatorToken, right) as AssignmentExpression; + return factory.updateBinaryExpression(node, left, node.operatorToken, right) as AssignmentExpression< + EqualsToken + >; } return visitDestructuringAssignmentTarget(node) as ArrayAssignmentElement; } @@ -3187,7 +3510,8 @@ export function transformClassFields(context: TransformationContext): (x: Source const savedPreviousShouldSubstituteThisWithClassThis = previousShouldSubstituteThisWithClassThis; lexicalEnvironment = lex; previousShouldSubstituteThisWithClassThis = shouldSubstituteThisWithClassThis; - shouldSubstituteThisWithClassThis = !isClassStaticBlockDeclaration(original) || !(getInternalEmitFlags(original) & InternalEmitFlags.TransformPrivateStaticElements); + shouldSubstituteThisWithClassThis = !isClassStaticBlockDeclaration(original) + || !(getInternalEmitFlags(original) & InternalEmitFlags.TransformPrivateStaticElements); previousOnEmitNode(hint, node, emitCallback); shouldSubstituteThisWithClassThis = previousShouldSubstituteThisWithClassThis; previousShouldSubstituteThisWithClassThis = savedPreviousShouldSubstituteThisWithClassThis; @@ -3267,9 +3591,9 @@ export function transformClassFields(context: TransformationContext): (x: Source function substituteThisExpression(node: ThisExpression) { if ( - enabledSubstitutions & ClassPropertySubstitutionFlags.ClassStaticThisOrSuperReference && - lexicalEnvironment?.data && - !noSubstitution.has(node) + enabledSubstitutions & ClassPropertySubstitutionFlags.ClassStaticThisOrSuperReference + && lexicalEnvironment?.data + && !noSubstitution.has(node) ) { const { facts, classConstructor, classThis } = lexicalEnvironment.data; const substituteThis = shouldSubstituteThisWithClassThis ? classThis ?? classConstructor : classConstructor; @@ -3318,7 +3642,11 @@ export function transformClassFields(context: TransformationContext): (x: Source } } -function createPrivateStaticFieldInitializer(factory: NodeFactory, variableName: Identifier, initializer: Expression | undefined) { +function createPrivateStaticFieldInitializer( + factory: NodeFactory, + variableName: Identifier, + initializer: Expression | undefined, +) { return factory.createAssignment( variableName, factory.createObjectLiteralExpression([ @@ -3327,7 +3655,12 @@ function createPrivateStaticFieldInitializer(factory: NodeFactory, variableName: ); } -function createPrivateInstanceFieldInitializer(factory: NodeFactory, receiver: LeftHandSideExpression, initializer: Expression | undefined, weakMapName: Identifier) { +function createPrivateInstanceFieldInitializer( + factory: NodeFactory, + receiver: LeftHandSideExpression, + initializer: Expression | undefined, + weakMapName: Identifier, +) { return factory.createCallExpression( factory.createPropertyAccessExpression(weakMapName, "set"), /*typeArguments*/ undefined, @@ -3335,7 +3668,11 @@ function createPrivateInstanceFieldInitializer(factory: NodeFactory, receiver: L ); } -function createPrivateInstanceMethodInitializer(factory: NodeFactory, receiver: LeftHandSideExpression, weakSetName: Identifier) { +function createPrivateInstanceMethodInitializer( + factory: NodeFactory, + receiver: LeftHandSideExpression, + weakSetName: Identifier, +) { return factory.createCallExpression( factory.createPropertyAccessExpression(weakSetName, "add"), /*typeArguments*/ undefined, @@ -3347,7 +3684,10 @@ function isReservedPrivateName(node: PrivateIdentifier) { return !isGeneratedPrivateIdentifier(node) && node.escapedText === "#constructor"; } -type PrivateIdentifierInExpression = BinaryExpression & { readonly left: PrivateIdentifier; readonly token: InKeyword; }; +type PrivateIdentifierInExpression = BinaryExpression & { + readonly left: PrivateIdentifier; + readonly token: InKeyword; +}; function isPrivateIdentifierInExpression(node: BinaryExpression): node is PrivateIdentifierInExpression { return isPrivateIdentifier(node.left) @@ -3358,6 +3698,8 @@ function isStaticPropertyDeclaration(node: Node): node is PropertyDeclaration { return isPropertyDeclaration(node) && hasStaticModifier(node); } -function isStaticPropertyDeclarationOrClassStaticBlock(node: Node): node is ClassStaticBlockDeclaration | PropertyDeclaration { +function isStaticPropertyDeclarationOrClassStaticBlock( + node: Node, +): node is ClassStaticBlockDeclaration | PropertyDeclaration { return isClassStaticBlockDeclaration(node) || isStaticPropertyDeclaration(node); } diff --git a/src/compiler/transformers/classThis.ts b/src/compiler/transformers/classThis.ts index 48f51ea8477c4..59a5082795630 100644 --- a/src/compiler/transformers/classThis.ts +++ b/src/compiler/transformers/classThis.ts @@ -31,7 +31,11 @@ import { * expression that has already had its `EmitFlags` set or may have been tracked to prevent substitution. * @internal */ -export function createClassThisAssignmentBlock(factory: NodeFactory, classThis: Identifier, thisExpression = factory.createThis()): ClassThisAssignmentBlock { +export function createClassThisAssignmentBlock( + factory: NodeFactory, + classThis: Identifier, + thisExpression = factory.createThis(), +): ClassThisAssignmentBlock { // produces: // // static { _classThis = this; } @@ -76,11 +80,11 @@ export function isClassThisAssignmentBlock(node: Node): node is ClassThisAssignm } const statement = node.body.statements[0]; - return isExpressionStatement(statement) && - isAssignmentExpression(statement.expression, /*excludeCompoundAssignment*/ true) && - isIdentifier(statement.expression.left) && - node.emitNode?.classThis === statement.expression.left && - statement.expression.right.kind === SyntaxKind.ThisKeyword; + return isExpressionStatement(statement) + && isAssignmentExpression(statement.expression, /*excludeCompoundAssignment*/ true) + && isIdentifier(statement.expression.left) + && node.emitNode?.classThis === statement.expression.left + && statement.expression.right.kind === SyntaxKind.ThisKeyword; } /** @@ -101,8 +105,18 @@ export function classHasClassThisAssignment(node: ClassLikeDeclaration) { * expression that has already had its `EmitFlags` set or may have been tracked to prevent substitution. * @internal */ -export function injectClassThisAssignmentIfMissing(factory: NodeFactory, node: T, classThis: Identifier, thisExpression?: ThisExpression): Extract>; -export function injectClassThisAssignmentIfMissing(factory: NodeFactory, node: T, classThis: Identifier, thisExpression?: ThisExpression) { +export function injectClassThisAssignmentIfMissing( + factory: NodeFactory, + node: T, + classThis: Identifier, + thisExpression?: ThisExpression, +): Extract>; +export function injectClassThisAssignmentIfMissing( + factory: NodeFactory, + node: T, + classThis: Identifier, + thisExpression?: ThisExpression, +) { // given: // // class C { @@ -126,16 +140,16 @@ export function injectClassThisAssignmentIfMissing 0 ? (parseTreeNode.parent as SignatureDeclaration).parameters[paramIdx - 1] : undefined; + const paramIdx = (parseTreeNode.parent as SignatureDeclaration).parameters.indexOf( + parseTreeNode as ParameterDeclaration, + ); + const previousSibling = paramIdx > 0 ? (parseTreeNode.parent as SignatureDeclaration).parameters[paramIdx - 1] + : undefined; const text = currentSourceFile.text; const commentRanges = previousSibling ? concatenate( // to handle // ... parameters, /** @internal */ // public param: string - getTrailingCommentRanges(text, skipTrivia(text, previousSibling.end + 1, /*stopAfterLineBreak*/ false, /*stopAtComments*/ true)), + getTrailingCommentRanges( + text, + skipTrivia(text, previousSibling.end + 1, /*stopAfterLineBreak*/ false, /*stopAtComments*/ true), + ), getLeadingCommentRanges(text, node.pos), ) - : getTrailingCommentRanges(text, skipTrivia(text, node.pos, /*stopAfterLineBreak*/ false, /*stopAtComments*/ true)); + : getTrailingCommentRanges( + text, + skipTrivia(text, node.pos, /*stopAfterLineBreak*/ false, /*stopAtComments*/ true), + ); return commentRanges && commentRanges.length && hasInternalAnnotation(last(commentRanges), currentSourceFile); } const leadingCommentRanges = parseTreeNode && getLeadingCommentRangesOfNode(parseTreeNode, currentSourceFile); @@ -268,13 +289,13 @@ export function isInternalDeclaration(node: Node, currentSourceFile: SourceFile) }); } -const declarationEmitNodeBuilderFlags = NodeBuilderFlags.MultilineObjectLiterals | - NodeBuilderFlags.WriteClassExpressionAsTypeLiteral | - NodeBuilderFlags.UseTypeOfFunction | - NodeBuilderFlags.UseStructuralFallback | - NodeBuilderFlags.AllowEmptyTuple | - NodeBuilderFlags.GenerateNamesForShadowedTypeParams | - NodeBuilderFlags.NoTruncation; +const declarationEmitNodeBuilderFlags = NodeBuilderFlags.MultilineObjectLiterals + | NodeBuilderFlags.WriteClassExpressionAsTypeLiteral + | NodeBuilderFlags.UseTypeOfFunction + | NodeBuilderFlags.UseStructuralFallback + | NodeBuilderFlags.AllowEmptyTuple + | NodeBuilderFlags.GenerateNamesForShadowedTypeParams + | NodeBuilderFlags.NoTruncation; /** * Transforms a ts file into a .d.ts file @@ -295,7 +316,10 @@ export function transformDeclarations(context: TransformationContext) { let enclosingDeclaration: Node; let necessaryTypeReferences: Set<[specifier: string, mode: ResolutionMode]> | undefined; let lateMarkedStatements: LateVisibilityPaintedStatement[] | undefined; - let lateStatementReplacementMap: Map>; + let lateStatementReplacementMap: Map< + NodeId, + VisitResult + >; let suppressNewDiagnosticContexts: boolean; let exportedModulesFromDeclarationEmit: Symbol[] | undefined; @@ -328,7 +352,9 @@ export function transformDeclarations(context: TransformationContext) { const { noResolve, stripInternal } = options; return transformRoot; - function recordTypeReferenceDirectivesIfNecessary(typeReferenceDirectives: readonly [specifier: string, mode: ResolutionMode][] | undefined): void { + function recordTypeReferenceDirectivesIfNecessary( + typeReferenceDirectives: readonly [specifier: string, mode: ResolutionMode][] | undefined, + ): void { if (!typeReferenceDirectives) { return; } @@ -370,10 +396,25 @@ export function transformDeclarations(context: TransformationContext) { const errorInfo = getSymbolAccessibilityDiagnostic(symbolAccessibilityResult); if (errorInfo) { if (errorInfo.typeName) { - context.addDiagnostic(createDiagnosticForNode(symbolAccessibilityResult.errorNode || errorInfo.errorNode, errorInfo.diagnosticMessage, getTextOfNode(errorInfo.typeName), symbolAccessibilityResult.errorSymbolName!, symbolAccessibilityResult.errorModuleName!)); + context.addDiagnostic( + createDiagnosticForNode( + symbolAccessibilityResult.errorNode || errorInfo.errorNode, + errorInfo.diagnosticMessage, + getTextOfNode(errorInfo.typeName), + symbolAccessibilityResult.errorSymbolName!, + symbolAccessibilityResult.errorModuleName!, + ), + ); } else { - context.addDiagnostic(createDiagnosticForNode(symbolAccessibilityResult.errorNode || errorInfo.errorNode, errorInfo.diagnosticMessage, symbolAccessibilityResult.errorSymbolName!, symbolAccessibilityResult.errorModuleName!)); + context.addDiagnostic( + createDiagnosticForNode( + symbolAccessibilityResult.errorNode || errorInfo.errorNode, + errorInfo.diagnosticMessage, + symbolAccessibilityResult.errorSymbolName!, + symbolAccessibilityResult.errorModuleName!, + ), + ); } return true; } @@ -389,7 +430,14 @@ export function transformDeclarations(context: TransformationContext) { function trackSymbol(symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags) { if (symbol.flags & SymbolFlags.TypeParameter) return false; - const issuedDiagnostic = handleSymbolAccessibilityError(resolver.isSymbolAccessible(symbol, enclosingDeclaration, meaning, /*shouldComputeAliasToMarkVisible*/ true)); + const issuedDiagnostic = handleSymbolAccessibilityError( + resolver.isSymbolAccessible( + symbol, + enclosingDeclaration, + meaning, + /*shouldComputeAliasToMarkVisible*/ true, + ), + ); recordTypeReferenceDirectivesIfNecessary(resolver.getTypeReferenceDirectivesForSymbol(symbol, meaning)); return issuedDiagnostic; } @@ -397,45 +445,86 @@ export function transformDeclarations(context: TransformationContext) { function reportPrivateInBaseOfClassExpression(propertyName: string) { if (errorNameNode || errorFallbackNode) { context.addDiagnostic( - createDiagnosticForNode((errorNameNode || errorFallbackNode)!, Diagnostics.Property_0_of_exported_class_expression_may_not_be_private_or_protected, propertyName), + createDiagnosticForNode( + (errorNameNode || errorFallbackNode)!, + Diagnostics.Property_0_of_exported_class_expression_may_not_be_private_or_protected, + propertyName, + ), ); } } function errorDeclarationNameWithFallback() { - return errorNameNode ? declarationNameToString(errorNameNode) : - errorFallbackNode && getNameOfDeclaration(errorFallbackNode) ? declarationNameToString(getNameOfDeclaration(errorFallbackNode)) : - errorFallbackNode && isExportAssignment(errorFallbackNode) ? errorFallbackNode.isExportEquals ? "export=" : "default" : - "(Missing)"; // same fallback declarationNameToString uses when node is zero-width (ie, nameless) + return errorNameNode ? declarationNameToString(errorNameNode) + : errorFallbackNode && getNameOfDeclaration(errorFallbackNode) + ? declarationNameToString(getNameOfDeclaration(errorFallbackNode)) + : errorFallbackNode && isExportAssignment(errorFallbackNode) + ? errorFallbackNode.isExportEquals ? "export=" : "default" + : "(Missing)"; // same fallback declarationNameToString uses when node is zero-width (ie, nameless) } function reportInaccessibleUniqueSymbolError() { if (errorNameNode || errorFallbackNode) { - context.addDiagnostic(createDiagnosticForNode((errorNameNode || errorFallbackNode)!, Diagnostics.The_inferred_type_of_0_references_an_inaccessible_1_type_A_type_annotation_is_necessary, errorDeclarationNameWithFallback(), "unique symbol")); + context.addDiagnostic( + createDiagnosticForNode( + (errorNameNode || errorFallbackNode)!, + Diagnostics.The_inferred_type_of_0_references_an_inaccessible_1_type_A_type_annotation_is_necessary, + errorDeclarationNameWithFallback(), + "unique symbol", + ), + ); } } function reportCyclicStructureError() { if (errorNameNode || errorFallbackNode) { - context.addDiagnostic(createDiagnosticForNode((errorNameNode || errorFallbackNode)!, Diagnostics.The_inferred_type_of_0_references_a_type_with_a_cyclic_structure_which_cannot_be_trivially_serialized_A_type_annotation_is_necessary, errorDeclarationNameWithFallback())); + context.addDiagnostic( + createDiagnosticForNode( + (errorNameNode || errorFallbackNode)!, + Diagnostics + .The_inferred_type_of_0_references_a_type_with_a_cyclic_structure_which_cannot_be_trivially_serialized_A_type_annotation_is_necessary, + errorDeclarationNameWithFallback(), + ), + ); } } function reportInaccessibleThisError() { if (errorNameNode || errorFallbackNode) { - context.addDiagnostic(createDiagnosticForNode((errorNameNode || errorFallbackNode)!, Diagnostics.The_inferred_type_of_0_references_an_inaccessible_1_type_A_type_annotation_is_necessary, errorDeclarationNameWithFallback(), "this")); + context.addDiagnostic( + createDiagnosticForNode( + (errorNameNode || errorFallbackNode)!, + Diagnostics.The_inferred_type_of_0_references_an_inaccessible_1_type_A_type_annotation_is_necessary, + errorDeclarationNameWithFallback(), + "this", + ), + ); } } function reportLikelyUnsafeImportRequiredError(specifier: string) { if (errorNameNode || errorFallbackNode) { - context.addDiagnostic(createDiagnosticForNode((errorNameNode || errorFallbackNode)!, Diagnostics.The_inferred_type_of_0_cannot_be_named_without_a_reference_to_1_This_is_likely_not_portable_A_type_annotation_is_necessary, errorDeclarationNameWithFallback(), specifier)); + context.addDiagnostic( + createDiagnosticForNode( + (errorNameNode || errorFallbackNode)!, + Diagnostics + .The_inferred_type_of_0_cannot_be_named_without_a_reference_to_1_This_is_likely_not_portable_A_type_annotation_is_necessary, + errorDeclarationNameWithFallback(), + specifier, + ), + ); } } function reportTruncationError() { if (errorNameNode || errorFallbackNode) { - context.addDiagnostic(createDiagnosticForNode((errorNameNode || errorFallbackNode)!, Diagnostics.The_inferred_type_of_this_node_exceeds_the_maximum_length_the_compiler_will_serialize_An_explicit_type_annotation_is_needed)); + context.addDiagnostic( + createDiagnosticForNode( + (errorNameNode || errorFallbackNode)!, + Diagnostics + .The_inferred_type_of_this_node_exceeds_the_maximum_length_the_compiler_will_serialize_An_explicit_type_annotation_is_needed, + ), + ); } } @@ -445,8 +534,15 @@ export function transformDeclarations(context: TransformationContext) { if (primaryDeclaration && augmentingDeclarations) { for (const augmentations of augmentingDeclarations) { context.addDiagnostic(addRelatedInfo( - createDiagnosticForNode(augmentations, Diagnostics.Declaration_augments_declaration_in_another_file_This_cannot_be_serialized), - createDiagnosticForNode(primaryDeclaration, Diagnostics.This_is_the_declaration_being_augmented_Consider_moving_the_augmenting_declaration_into_the_same_file), + createDiagnosticForNode( + augmentations, + Diagnostics.Declaration_augments_declaration_in_another_file_This_cannot_be_serialized, + ), + createDiagnosticForNode( + primaryDeclaration, + Diagnostics + .This_is_the_declaration_being_augmented_Consider_moving_the_augmenting_declaration_into_the_same_file, + ), )); } } @@ -454,25 +550,45 @@ export function transformDeclarations(context: TransformationContext) { function reportNonSerializableProperty(propertyName: string) { if (errorNameNode || errorFallbackNode) { - context.addDiagnostic(createDiagnosticForNode((errorNameNode || errorFallbackNode)!, Diagnostics.The_type_of_this_node_cannot_be_serialized_because_its_property_0_cannot_be_serialized, propertyName)); + context.addDiagnostic( + createDiagnosticForNode( + (errorNameNode || errorFallbackNode)!, + Diagnostics.The_type_of_this_node_cannot_be_serialized_because_its_property_0_cannot_be_serialized, + propertyName, + ), + ); } } function reportImportTypeNodeResolutionModeOverride() { if (!isNightly() && (errorNameNode || errorFallbackNode)) { - context.addDiagnostic(createDiagnosticForNode((errorNameNode || errorFallbackNode)!, Diagnostics.The_type_of_this_expression_cannot_be_named_without_a_resolution_mode_assertion_which_is_an_unstable_feature_Use_nightly_TypeScript_to_silence_this_error_Try_updating_with_npm_install_D_typescript_next)); + context.addDiagnostic( + createDiagnosticForNode( + (errorNameNode || errorFallbackNode)!, + Diagnostics + .The_type_of_this_expression_cannot_be_named_without_a_resolution_mode_assertion_which_is_an_unstable_feature_Use_nightly_TypeScript_to_silence_this_error_Try_updating_with_npm_install_D_typescript_next, + ), + ); } } function transformDeclarationsForJS(sourceFile: SourceFile, bundled?: boolean) { const oldDiag = getSymbolAccessibilityDiagnostic; - getSymbolAccessibilityDiagnostic = s => (s.errorNode && canProduceDiagnostics(s.errorNode) ? createGetSymbolAccessibilityDiagnosticForNode(s.errorNode)(s) : ({ - diagnosticMessage: s.errorModuleName - ? Diagnostics.Declaration_emit_for_this_file_requires_using_private_name_0_from_module_1_An_explicit_type_annotation_may_unblock_declaration_emit - : Diagnostics.Declaration_emit_for_this_file_requires_using_private_name_0_An_explicit_type_annotation_may_unblock_declaration_emit, - errorNode: s.errorNode || sourceFile, - })); - const result = resolver.getDeclarationStatementsForSourceFile(sourceFile, declarationEmitNodeBuilderFlags, symbolTracker, bundled); + getSymbolAccessibilityDiagnostic = s => (s.errorNode && canProduceDiagnostics(s.errorNode) + ? createGetSymbolAccessibilityDiagnosticForNode(s.errorNode)(s) : ({ + diagnosticMessage: s.errorModuleName + ? Diagnostics + .Declaration_emit_for_this_file_requires_using_private_name_0_from_module_1_An_explicit_type_annotation_may_unblock_declaration_emit + : Diagnostics + .Declaration_emit_for_this_file_requires_using_private_name_0_An_explicit_type_annotation_may_unblock_declaration_emit, + errorNode: s.errorNode || sourceFile, + })); + const result = resolver.getDeclarationStatementsForSourceFile( + sourceFile, + declarationEmitNodeBuilderFlags, + symbolTracker, + bundled, + ); getSymbolAccessibilityDiagnostic = oldDiag; return result; } @@ -507,13 +623,22 @@ export function transformDeclarations(context: TransformationContext) { if (isExternalOrCommonJsModule(sourceFile) || isJsonSourceFile(sourceFile)) { resultHasExternalModuleIndicator = false; // unused in external module bundle emit (all external modules are within module blocks, therefore are known to be modules) needsDeclare = false; - const statements = isSourceFileJS(sourceFile) ? factory.createNodeArray(transformDeclarationsForJS(sourceFile, /*bundled*/ true)) : visitNodes(sourceFile.statements, visitDeclarationStatements, isStatement); + const statements = isSourceFileJS(sourceFile) + ? factory.createNodeArray(transformDeclarationsForJS(sourceFile, /*bundled*/ true)) + : visitNodes(sourceFile.statements, visitDeclarationStatements, isStatement); const newFile = factory.updateSourceFile( sourceFile, [factory.createModuleDeclaration( [factory.createModifier(SyntaxKind.DeclareKeyword)], - factory.createStringLiteral(getResolvedExternalModuleName(context.getEmitHost(), sourceFile)), - factory.createModuleBlock(setTextRange(factory.createNodeArray(transformAndReplaceLatePaintedStatements(statements)), sourceFile.statements)), + factory.createStringLiteral( + getResolvedExternalModuleName(context.getEmitHost(), sourceFile), + ), + factory.createModuleBlock( + setTextRange( + factory.createNodeArray(transformAndReplaceLatePaintedStatements(statements)), + sourceFile.statements, + ), + ), )], /*isDeclarationFile*/ true, /*referencedFiles*/ [], @@ -524,15 +649,27 @@ export function transformDeclarations(context: TransformationContext) { return newFile; } needsDeclare = true; - const updated = isSourceFileJS(sourceFile) ? factory.createNodeArray(transformDeclarationsForJS(sourceFile)) : visitNodes(sourceFile.statements, visitDeclarationStatements, isStatement); - return factory.updateSourceFile(sourceFile, transformAndReplaceLatePaintedStatements(updated), /*isDeclarationFile*/ true, /*referencedFiles*/ [], /*typeReferences*/ [], /*hasNoDefaultLib*/ false, /*libReferences*/ []); + const updated = isSourceFileJS(sourceFile) + ? factory.createNodeArray(transformDeclarationsForJS(sourceFile)) + : visitNodes(sourceFile.statements, visitDeclarationStatements, isStatement); + return factory.updateSourceFile( + sourceFile, + transformAndReplaceLatePaintedStatements(updated), + /*isDeclarationFile*/ true, + /*referencedFiles*/ [], + /*typeReferences*/ [], + /*hasNoDefaultLib*/ false, + /*libReferences*/ [], + ); }), mapDefined(node.prepends, prepend => { if (prepend.kind === SyntaxKind.InputFiles) { const sourceFile = createUnparsedSourceFile(prepend, "dts", stripInternal); hasNoDefaultLib = hasNoDefaultLib || !!sourceFile.hasNoDefaultLib; collectReferences(sourceFile, refs); - recordTypeReferenceDirectivesIfNecessary(map(sourceFile.typeReferenceDirectives, ref => [ref.fileName, ref.resolutionMode])); + recordTypeReferenceDirectivesIfNecessary( + map(sourceFile.typeReferenceDirectives, ref => [ref.fileName, ref.resolutionMode]), + ); collectLibs(sourceFile, libs); return sourceFile; } @@ -543,8 +680,13 @@ export function transformDeclarations(context: TransformationContext) { bundle.syntheticTypeReferences = getFileReferencesForUsedTypeReferences(); bundle.syntheticLibReferences = getLibReferences(); bundle.hasNoDefaultLib = hasNoDefaultLib; - const outputFilePath = getDirectoryPath(normalizeSlashes(getOutputPathsFor(node, host, /*forceDtsPaths*/ true).declarationFilePath!)); - const referenceVisitor = mapReferencesIntoArray(bundle.syntheticFileReferences as FileReference[], outputFilePath); + const outputFilePath = getDirectoryPath( + normalizeSlashes(getOutputPathsFor(node, host, /*forceDtsPaths*/ true).declarationFilePath!), + ); + const referenceVisitor = mapReferencesIntoArray( + bundle.syntheticFileReferences as FileReference[], + outputFilePath, + ); refs.forEach(referenceVisitor); return bundle; } @@ -565,7 +707,9 @@ export function transformDeclarations(context: TransformationContext) { refs = collectReferences(currentSourceFile, new Map()); libs = collectLibs(currentSourceFile, new Map()); const references: FileReference[] = []; - const outputFilePath = getDirectoryPath(normalizeSlashes(getOutputPathsFor(node, host, /*forceDtsPaths*/ true).declarationFilePath!)); + const outputFilePath = getDirectoryPath( + normalizeSlashes(getOutputPathsFor(node, host, /*forceDtsPaths*/ true).declarationFilePath!), + ); const referenceVisitor = mapReferencesIntoArray(references, outputFilePath); let combinedStatements: NodeArray; if (isSourceFileJS(currentSourceFile)) { @@ -575,14 +719,31 @@ export function transformDeclarations(context: TransformationContext) { } else { const statements = visitNodes(node.statements, visitDeclarationStatements, isStatement); - combinedStatements = setTextRange(factory.createNodeArray(transformAndReplaceLatePaintedStatements(statements)), node.statements); + combinedStatements = setTextRange( + factory.createNodeArray(transformAndReplaceLatePaintedStatements(statements)), + node.statements, + ); refs.forEach(referenceVisitor); emittedImports = filter(combinedStatements, isAnyImportSyntax); - if (isExternalModule(node) && (!resultHasExternalModuleIndicator || (needsScopeFixMarker && !resultHasScopeMarker))) { - combinedStatements = setTextRange(factory.createNodeArray([...combinedStatements, createEmptyExports(factory)]), combinedStatements); + if ( + isExternalModule(node) + && (!resultHasExternalModuleIndicator || (needsScopeFixMarker && !resultHasScopeMarker)) + ) { + combinedStatements = setTextRange( + factory.createNodeArray([...combinedStatements, createEmptyExports(factory)]), + combinedStatements, + ); } } - const updated = factory.updateSourceFile(node, combinedStatements, /*isDeclarationFile*/ true, references, getFileReferencesForUsedTypeReferences(), node.hasNoDefaultLib, getLibReferences()); + const updated = factory.updateSourceFile( + node, + combinedStatements, + /*isDeclarationFile*/ true, + references, + getFileReferencesForUsedTypeReferences(), + node.hasNoDefaultLib, + getLibReferences(), + ); updated.exportedModulesFromDeclarationEmit = exportedModulesFromDeclarationEmit; return updated; @@ -591,20 +752,29 @@ export function transformDeclarations(context: TransformationContext) { } function getFileReferencesForUsedTypeReferences() { - return necessaryTypeReferences ? mapDefined(arrayFrom(necessaryTypeReferences.keys()), getFileReferenceForSpecifierModeTuple) : []; + return necessaryTypeReferences + ? mapDefined(arrayFrom(necessaryTypeReferences.keys()), getFileReferenceForSpecifierModeTuple) : []; } - function getFileReferenceForSpecifierModeTuple([typeName, mode]: [specifier: string, mode: ResolutionMode]): FileReference | undefined { + function getFileReferenceForSpecifierModeTuple( + [typeName, mode]: [specifier: string, mode: ResolutionMode], + ): FileReference | undefined { // Elide type references for which we have imports if (emittedImports) { for (const importStatement of emittedImports) { - if (isImportEqualsDeclaration(importStatement) && isExternalModuleReference(importStatement.moduleReference)) { + if ( + isImportEqualsDeclaration(importStatement) + && isExternalModuleReference(importStatement.moduleReference) + ) { const expr = importStatement.moduleReference.expression; if (isStringLiteralLike(expr) && expr.text === typeName) { return undefined; } } - else if (isImportDeclaration(importStatement) && isStringLiteral(importStatement.moduleSpecifier) && importStatement.moduleSpecifier.text === typeName) { + else if ( + isImportDeclaration(importStatement) && isStringLiteral(importStatement.moduleSpecifier) + && importStatement.moduleSpecifier.text === typeName + ) { return undefined; } } @@ -612,7 +782,10 @@ export function transformDeclarations(context: TransformationContext) { return { fileName: typeName, pos: -1, end: -1, ...(mode ? { resolutionMode: mode } : undefined) }; } - function mapReferencesIntoArray(references: FileReference[], outputFilePath: string): (file: SourceFile) => void { + function mapReferencesIntoArray( + references: FileReference[], + outputFilePath: string, + ): (file: SourceFile) => void { return file => { let declFileName: string; if (file.isDeclarationFile) { // Neither decl files or js should have their refs changed @@ -690,10 +863,16 @@ export function transformDeclarations(context: TransformationContext) { } else { if (name.kind === SyntaxKind.ArrayBindingPattern) { - return factory.updateArrayBindingPattern(name, visitNodes(name.elements, visitBindingElement, isArrayBindingElement)); + return factory.updateArrayBindingPattern( + name, + visitNodes(name.elements, visitBindingElement, isArrayBindingElement), + ); } else { - return factory.updateObjectBindingPattern(name, visitNodes(name.elements, visitBindingElement, isBindingElement)); + return factory.updateObjectBindingPattern( + name, + visitNodes(name.elements, visitBindingElement, isBindingElement), + ); } } @@ -702,7 +881,10 @@ export function transformDeclarations(context: TransformationContext) { if (elem.kind === SyntaxKind.OmittedExpression) { return elem; } - if (elem.propertyName && isIdentifier(elem.propertyName) && isIdentifier(elem.name) && !elem.symbol.isReferenced && !isIdentifierANonContextualKeyword(elem.propertyName)) { + if ( + elem.propertyName && isIdentifier(elem.propertyName) && isIdentifier(elem.name) + && !elem.symbol.isReferenced && !isIdentifierANonContextualKeyword(elem.propertyName) + ) { // Unnecessary property renaming is forbidden in types, so remove renaming return factory.updateBindingElement( elem, @@ -722,7 +904,11 @@ export function transformDeclarations(context: TransformationContext) { } } - function ensureParameter(p: ParameterDeclaration, modifierMask?: ModifierFlags, type?: TypeNode): ParameterDeclaration { + function ensureParameter( + p: ParameterDeclaration, + modifierMask?: ModifierFlags, + type?: TypeNode, + ): ParameterDeclaration { let oldDiag: typeof getSymbolAccessibilityDiagnostic | undefined; if (!suppressNewDiagnosticContexts) { oldDiag = getSymbolAccessibilityDiagnostic; @@ -733,7 +919,8 @@ export function transformDeclarations(context: TransformationContext) { maskModifiers(factory, p, modifierMask), p.dotDotDotToken, filterBindingPatternInitializersAndRenamings(p.name), - resolver.isOptionalParameter(p) ? (p.questionToken || factory.createToken(SyntaxKind.QuestionToken)) : undefined, + resolver.isOptionalParameter(p) ? (p.questionToken || factory.createToken(SyntaxKind.QuestionToken)) + : undefined, ensureType(p, type || p.type, /*ignorePrivate*/ true), // Ignore private param props, since this type is going straight back into a param ensureNoInitializer(p), ); @@ -744,7 +931,8 @@ export function transformDeclarations(context: TransformationContext) { } function shouldPrintWithInitializer(node: Node) { - return canHaveLiteralInitializer(node) && resolver.isLiteralConstDeclaration(getParseTreeNode(node) as CanHaveLiteralInitializer); // TODO: Make safe + return canHaveLiteralInitializer(node) + && resolver.isLiteralConstDeclaration(getParseTreeNode(node) as CanHaveLiteralInitializer); // TODO: Make safe } function ensureNoInitializer(node: CanHaveLiteralInitializer) { @@ -768,7 +956,11 @@ export function transformDeclarations(context: TransformationContext) { | PropertyDeclaration | PropertySignature; - function ensureType(node: HasInferredType, type: TypeNode | undefined, ignorePrivate?: boolean): TypeNode | undefined { + function ensureType( + node: HasInferredType, + type: TypeNode | undefined, + ignorePrivate?: boolean, + ): TypeNode | undefined { if (!ignorePrivate && hasEffectiveModifier(node, ModifierFlags.Private)) { // Private nodes emit no types (except private parameter properties, whose parameter types are actually visible) return; @@ -777,14 +969,15 @@ export function transformDeclarations(context: TransformationContext) { // Literal const declarations will have an initializer ensured rather than a type return; } - const shouldUseResolverType = node.kind === SyntaxKind.Parameter && - (resolver.isRequiredInitializedParameter(node) || - resolver.isOptionalUninitializedParameterProperty(node)); + const shouldUseResolverType = node.kind === SyntaxKind.Parameter + && (resolver.isRequiredInitializedParameter(node) + || resolver.isOptionalUninitializedParameterProperty(node)); if (type && !shouldUseResolverType) { return visitNode(type, visitDeclarationSubtree, isTypeNode); } if (!getParseTreeNode(node)) { - return type ? visitNode(type, visitDeclarationSubtree, isTypeNode) : factory.createKeywordTypeNode(SyntaxKind.AnyKeyword); + return type ? visitNode(type, visitDeclarationSubtree, isTypeNode) + : factory.createKeywordTypeNode(SyntaxKind.AnyKeyword); } if (node.kind === SyntaxKind.SetAccessor) { // Set accessors with no associated type node (from it's param or get accessor return) are `any` since they are never contextually typed right now @@ -798,17 +991,55 @@ export function transformDeclarations(context: TransformationContext) { getSymbolAccessibilityDiagnostic = createGetSymbolAccessibilityDiagnosticForNode(node); } if (node.kind === SyntaxKind.VariableDeclaration || node.kind === SyntaxKind.BindingElement) { - return cleanup(resolver.createTypeOfDeclaration(node, enclosingDeclaration, declarationEmitNodeBuilderFlags, symbolTracker)); + return cleanup( + resolver.createTypeOfDeclaration( + node, + enclosingDeclaration, + declarationEmitNodeBuilderFlags, + symbolTracker, + ), + ); } if ( node.kind === SyntaxKind.Parameter || node.kind === SyntaxKind.PropertyDeclaration || node.kind === SyntaxKind.PropertySignature ) { - if (isPropertySignature(node) || !node.initializer) return cleanup(resolver.createTypeOfDeclaration(node, enclosingDeclaration, declarationEmitNodeBuilderFlags, symbolTracker, shouldUseResolverType)); - return cleanup(resolver.createTypeOfDeclaration(node, enclosingDeclaration, declarationEmitNodeBuilderFlags, symbolTracker, shouldUseResolverType) || resolver.createTypeOfExpression(node.initializer, enclosingDeclaration, declarationEmitNodeBuilderFlags, symbolTracker)); + if (isPropertySignature(node) || !node.initializer) { + return cleanup( + resolver.createTypeOfDeclaration( + node, + enclosingDeclaration, + declarationEmitNodeBuilderFlags, + symbolTracker, + shouldUseResolverType, + ), + ); + } + return cleanup( + resolver.createTypeOfDeclaration( + node, + enclosingDeclaration, + declarationEmitNodeBuilderFlags, + symbolTracker, + shouldUseResolverType, + ) + || resolver.createTypeOfExpression( + node.initializer, + enclosingDeclaration, + declarationEmitNodeBuilderFlags, + symbolTracker, + ), + ); } - return cleanup(resolver.createReturnTypeOfSignatureDeclaration(node, enclosingDeclaration, declarationEmitNodeBuilderFlags, symbolTracker)); + return cleanup( + resolver.createReturnTypeOfSignatureDeclaration( + node, + enclosingDeclaration, + declarationEmitNodeBuilderFlags, + symbolTracker, + ), + ); function cleanup(returnValue: TypeNode | undefined) { errorNameNode = undefined; @@ -866,7 +1097,11 @@ export function transformDeclarations(context: TransformationContext) { } } - function updateParamsList(node: Node, params: NodeArray, modifierMask?: ModifierFlags): NodeArray { + function updateParamsList( + node: Node, + params: NodeArray, + modifierMask?: ModifierFlags, + ): NodeArray { if (hasEffectiveModifier(node, ModifierFlags.Private)) { return factory.createNodeArray(); } @@ -890,7 +1125,10 @@ export function transformDeclarations(context: TransformationContext) { if (!isPrivate) { const valueParameter = getSetAccessorValueParameter(input); if (valueParameter) { - const accessorType = getTypeAnnotationFromAllAccessorDeclarations(input, resolver.getAllAccessorDeclarations(input)); + const accessorType = getTypeAnnotationFromAllAccessorDeclarations( + input, + resolver.getAllAccessorDeclarations(input), + ); newValueParameter = ensureParameter(valueParameter, /*modifierMask*/ undefined, accessorType); } } @@ -907,7 +1145,8 @@ export function transformDeclarations(context: TransformationContext) { } function ensureTypeParams(node: Node, params: NodeArray | undefined) { - return hasEffectiveModifier(node, ModifierFlags.Private) ? undefined : visitNodes(params, visitDeclarationSubtree, isTypeParameterDeclaration); + return hasEffectiveModifier(node, ModifierFlags.Private) ? undefined + : visitNodes(params, visitDeclarationSubtree, isTypeParameterDeclaration); } function isEnclosingDeclaration(node: Node) { @@ -934,9 +1173,13 @@ export function transformDeclarations(context: TransformationContext) { return setCommentRange(updated, getCommentRange(original)); } - function rewriteModuleSpecifier(parent: ImportEqualsDeclaration | ImportDeclaration | ExportDeclaration | ModuleDeclaration | ImportTypeNode, input: T | undefined): T | StringLiteral { + function rewriteModuleSpecifier( + parent: ImportEqualsDeclaration | ImportDeclaration | ExportDeclaration | ModuleDeclaration | ImportTypeNode, + input: T | undefined, + ): T | StringLiteral { if (!input) return undefined!; // TODO: GH#18217 - resultHasExternalModuleIndicator = resultHasExternalModuleIndicator || (parent.kind !== SyntaxKind.ModuleDeclaration && parent.kind !== SyntaxKind.ImportType); + resultHasExternalModuleIndicator = resultHasExternalModuleIndicator + || (parent.kind !== SyntaxKind.ModuleDeclaration && parent.kind !== SyntaxKind.ImportType); if (isStringLiteralLike(input)) { if (isBundledEmit) { const newName = getExternalModuleNameFromDeclaration(context.getEmitHost(), resolver, parent); @@ -988,7 +1231,9 @@ export function transformDeclarations(context: TransformationContext) { ); } // The `importClause` visibility corresponds to the default's visibility. - const visibleDefaultBinding = decl.importClause && decl.importClause.name && resolver.isDeclarationVisible(decl.importClause) ? decl.importClause.name : undefined; + const visibleDefaultBinding = + decl.importClause && decl.importClause.name && resolver.isDeclarationVisible(decl.importClause) + ? decl.importClause.name : undefined; if (!decl.importClause.namedBindings) { // No named bindings (either namespace or list), meaning the import is just default or should be elided return visibleDefaultBinding && factory.updateImportDeclaration( @@ -1006,7 +1251,8 @@ export function transformDeclarations(context: TransformationContext) { } if (decl.importClause.namedBindings.kind === SyntaxKind.NamespaceImport) { // Namespace import (optionally with visible default) - const namedBindings = resolver.isDeclarationVisible(decl.importClause.namedBindings) ? decl.importClause.namedBindings : /*namedBindings*/ undefined; + const namedBindings = resolver.isDeclarationVisible(decl.importClause.namedBindings) + ? decl.importClause.namedBindings : /*namedBindings*/ undefined; return visibleDefaultBinding || namedBindings ? factory.updateImportDeclaration( decl, decl.modifiers, @@ -1021,7 +1267,10 @@ export function transformDeclarations(context: TransformationContext) { ) : undefined; } // Named imports (optionally with visible default) - const bindingList = mapDefined(decl.importClause.namedBindings.elements, b => resolver.isDeclarationVisible(b) ? b : undefined); + const bindingList = mapDefined( + decl.importClause.namedBindings.elements, + b => resolver.isDeclarationVisible(b) ? b : undefined, + ); if ((bindingList && bindingList.length) || visibleDefaultBinding) { return factory.updateImportDeclaration( decl, @@ -1030,7 +1279,8 @@ export function transformDeclarations(context: TransformationContext) { decl.importClause, decl.importClause.isTypeOnly, visibleDefaultBinding, - bindingList && bindingList.length ? factory.updateNamedImports(decl.importClause.namedBindings, bindingList) : undefined, + bindingList && bindingList.length + ? factory.updateNamedImports(decl.importClause.namedBindings, bindingList) : undefined, ), rewriteModuleSpecifier(decl, decl.moduleSpecifier), getResolutionModeOverrideForClauseInNightly(decl.assertClause), @@ -1053,7 +1303,13 @@ export function transformDeclarations(context: TransformationContext) { const mode = getResolutionModeOverrideForClause(assertClause); if (mode !== undefined) { if (!isNightly()) { - context.addDiagnostic(createDiagnosticForNode(assertClause!, Diagnostics.resolution_mode_assertions_are_unstable_Use_nightly_TypeScript_to_silence_this_error_Try_updating_with_npm_install_D_typescript_next)); + context.addDiagnostic( + createDiagnosticForNode( + assertClause!, + Diagnostics + .resolution_mode_assertions_are_unstable_Use_nightly_TypeScript_to_silence_this_error_Try_updating_with_npm_install_D_typescript_next, + ), + ); } return assertClause; } @@ -1078,7 +1334,11 @@ export function transformDeclarations(context: TransformationContext) { while (length(lateMarkedStatements)) { const i = lateMarkedStatements!.shift()!; if (!isLateVisibilityPaintedStatement(i)) { - return Debug.fail(`Late replaced statement was found which is not handled by the declaration transformer!: ${Debug.formatSyntaxKind((i as Node).kind)}`); + return Debug.fail( + `Late replaced statement was found which is not handled by the declaration transformer!: ${ + Debug.formatSyntaxKind((i as Node).kind) + }`, + ); } const priorNeedsDeclare = needsDeclare; needsDeclare = i.parent && isSourceFile(i.parent) && !(isExternalModule(i.parent) && isBundledEmit); @@ -1102,7 +1362,11 @@ export function transformDeclarations(context: TransformationContext) { // Top-level declarations in .d.ts files are always considered exported even without a modifier unless there's an export assignment or specifier needsScopeFixMarker = true; } - if (isSourceFile(statement.parent) && (isArray(result) ? some(result, isExternalModuleIndicator) : isExternalModuleIndicator(result))) { + if ( + isSourceFile(statement.parent) + && (isArray(result) ? some(result, isExternalModuleIndicator) + : isExternalModuleIndicator(result)) + ) { resultHasExternalModuleIndicator = true; } } @@ -1139,13 +1403,23 @@ export function transformDeclarations(context: TransformationContext) { // We'd see a TDZ violation at runtime const canProduceDiagnostic = canProduceDiagnostics(input); const oldWithinObjectLiteralType = suppressNewDiagnosticContexts; - let shouldEnterSuppressNewDiagnosticsContextContext = (input.kind === SyntaxKind.TypeLiteral || input.kind === SyntaxKind.MappedType) && input.parent.kind !== SyntaxKind.TypeAliasDeclaration; + let shouldEnterSuppressNewDiagnosticsContextContext = + (input.kind === SyntaxKind.TypeLiteral || input.kind === SyntaxKind.MappedType) + && input.parent.kind !== SyntaxKind.TypeAliasDeclaration; // Emit methods which are private as properties with no type information if (isMethodDeclaration(input) || isMethodSignature(input)) { if (hasEffectiveModifier(input, ModifierFlags.Private)) { if (input.symbol && input.symbol.declarations && input.symbol.declarations[0] !== input) return; // Elide all but the first overload - return cleanup(factory.createPropertyDeclaration(ensureModifiers(input), input.name, /*questionOrExclamationToken*/ undefined, /*type*/ undefined, /*initializer*/ undefined)); + return cleanup( + factory.createPropertyDeclaration( + ensureModifiers(input), + input.name, + /*questionOrExclamationToken*/ undefined, + /*type*/ undefined, + /*initializer*/ undefined, + ), + ); } } @@ -1169,7 +1443,9 @@ export function transformDeclarations(context: TransformationContext) { checkEntityNameVisibility(input.expression, enclosingDeclaration); } const node = visitEachChild(input, visitDeclarationSubtree, context); - return cleanup(factory.updateExpressionWithTypeArguments(node, node.expression, node.typeArguments)); + return cleanup( + factory.updateExpressionWithTypeArguments(node, node.expression, node.typeArguments), + ); } case SyntaxKind.TypeReference: { checkEntityNameVisibility(input.typeName, enclosingDeclaration); @@ -1212,7 +1488,10 @@ export function transformDeclarations(context: TransformationContext) { if (isPrivateIdentifier(input.name)) { return cleanup(/*returnValue*/ undefined); } - const accessorType = getTypeAnnotationFromAllAccessorDeclarations(input, resolver.getAllAccessorDeclarations(input)); + const accessorType = getTypeAnnotationFromAllAccessorDeclarations( + input, + resolver.getAllAccessorDeclarations(input), + ); return cleanup(factory.updateGetAccessorDeclaration( input, ensureModifiers(input), @@ -1284,7 +1563,8 @@ export function transformDeclarations(context: TransformationContext) { input, ensureModifiers(input), updateParamsList(input, input.parameters), - visitNode(input.type, visitDeclarationSubtree, isTypeNode) || factory.createKeywordTypeNode(SyntaxKind.AnyKeyword), + visitNode(input.type, visitDeclarationSubtree, isTypeNode) + || factory.createKeywordTypeNode(SyntaxKind.AnyKeyword), )); } case SyntaxKind.VariableDeclaration: { @@ -1293,11 +1573,27 @@ export function transformDeclarations(context: TransformationContext) { } shouldEnterSuppressNewDiagnosticsContextContext = true; suppressNewDiagnosticContexts = true; // Variable declaration types also suppress new diagnostic contexts, provided the contexts wouldn't be made for binding pattern types - return cleanup(factory.updateVariableDeclaration(input, input.name, /*exclamationToken*/ undefined, ensureType(input, input.type), ensureNoInitializer(input))); + return cleanup( + factory.updateVariableDeclaration( + input, + input.name, + /*exclamationToken*/ undefined, + ensureType(input, input.type), + ensureNoInitializer(input), + ), + ); } case SyntaxKind.TypeParameter: { if (isPrivateMethodTypeParameter(input) && (input.default || input.constraint)) { - return cleanup(factory.updateTypeParameterDeclaration(input, input.modifiers, input.name, /*constraint*/ undefined, /*defaultType*/ undefined)); + return cleanup( + factory.updateTypeParameterDeclaration( + input, + input.modifiers, + input.name, + /*constraint*/ undefined, + /*defaultType*/ undefined, + ), + ); } return cleanup(visitEachChild(input, visitDeclarationSubtree, context)); } @@ -1315,19 +1611,39 @@ export function transformDeclarations(context: TransformationContext) { Debug.assert(extendsType); Debug.assert(trueType); Debug.assert(falseType); - return cleanup(factory.updateConditionalTypeNode(input, checkType, extendsType, trueType, falseType)); + return cleanup( + factory.updateConditionalTypeNode(input, checkType, extendsType, trueType, falseType), + ); } case SyntaxKind.FunctionType: { - return cleanup(factory.updateFunctionTypeNode(input, visitNodes(input.typeParameters, visitDeclarationSubtree, isTypeParameterDeclaration), updateParamsList(input, input.parameters), Debug.checkDefined(visitNode(input.type, visitDeclarationSubtree, isTypeNode)))); + return cleanup( + factory.updateFunctionTypeNode( + input, + visitNodes(input.typeParameters, visitDeclarationSubtree, isTypeParameterDeclaration), + updateParamsList(input, input.parameters), + Debug.checkDefined(visitNode(input.type, visitDeclarationSubtree, isTypeNode)), + ), + ); } case SyntaxKind.ConstructorType: { - return cleanup(factory.updateConstructorTypeNode(input, ensureModifiers(input), visitNodes(input.typeParameters, visitDeclarationSubtree, isTypeParameterDeclaration), updateParamsList(input, input.parameters), Debug.checkDefined(visitNode(input.type, visitDeclarationSubtree, isTypeNode)))); + return cleanup( + factory.updateConstructorTypeNode( + input, + ensureModifiers(input), + visitNodes(input.typeParameters, visitDeclarationSubtree, isTypeParameterDeclaration), + updateParamsList(input, input.parameters), + Debug.checkDefined(visitNode(input.type, visitDeclarationSubtree, isTypeNode)), + ), + ); } case SyntaxKind.ImportType: { if (!isLiteralImportTypeNode(input)) return cleanup(input); return cleanup(factory.updateImportTypeNode( input, - factory.updateLiteralTypeNode(input.argument, rewriteModuleSpecifier(input, input.argument.literal)), + factory.updateLiteralTypeNode( + input.argument, + rewriteModuleSpecifier(input, input.argument.literal), + ), input.assertions, input.qualifier, visitNodes(input.typeArguments, visitDeclarationSubtree, isTypeNode), @@ -1335,11 +1651,18 @@ export function transformDeclarations(context: TransformationContext) { )); } default: - Debug.assertNever(input, `Attempted to process unhandled node kind: ${Debug.formatSyntaxKind((input as Node).kind)}`); + Debug.assertNever( + input, + `Attempted to process unhandled node kind: ${Debug.formatSyntaxKind((input as Node).kind)}`, + ); } } - if (isTupleTypeNode(input) && (getLineAndCharacterOfPosition(currentSourceFile, input.pos).line === getLineAndCharacterOfPosition(currentSourceFile, input.end).line)) { + if ( + isTupleTypeNode(input) + && (getLineAndCharacterOfPosition(currentSourceFile, input.pos).line + === getLineAndCharacterOfPosition(currentSourceFile, input.end).line) + ) { setEmitFlags(input, EmitFlags.SingleLine); } @@ -1366,7 +1689,8 @@ export function transformDeclarations(context: TransformationContext) { } function isPrivateMethodTypeParameter(node: TypeParameterDeclaration) { - return node.parent.kind === SyntaxKind.MethodDeclaration && hasEffectiveModifier(node.parent, ModifierFlags.Private); + return node.parent.kind === SyntaxKind.MethodDeclaration + && hasEffectiveModifier(node.parent, ModifierFlags.Private); } function visitDeclarationStatements(input: Node): VisitResult { @@ -1409,9 +1733,22 @@ export function transformDeclarations(context: TransformationContext) { errorNode: input, }); errorFallbackNode = input; - const varDecl = factory.createVariableDeclaration(newId, /*exclamationToken*/ undefined, resolver.createTypeOfExpression(input.expression, input, declarationEmitNodeBuilderFlags, symbolTracker), /*initializer*/ undefined); + const varDecl = factory.createVariableDeclaration( + newId, + /*exclamationToken*/ undefined, + resolver.createTypeOfExpression( + input.expression, + input, + declarationEmitNodeBuilderFlags, + symbolTracker, + ), + /*initializer*/ undefined, + ); errorFallbackNode = undefined; - const statement = factory.createVariableStatement(needsDeclare ? [factory.createModifier(SyntaxKind.DeclareKeyword)] : [], factory.createVariableDeclarationList([varDecl], NodeFlags.Const)); + const statement = factory.createVariableStatement( + needsDeclare ? [factory.createModifier(SyntaxKind.DeclareKeyword)] : [], + factory.createVariableDeclarationList([varDecl], NodeFlags.Const), + ); preserveJsDoc(statement, input); removeAllComments(input); @@ -1427,13 +1764,18 @@ export function transformDeclarations(context: TransformationContext) { } function stripExportModifiers(statement: Statement): Statement { - if (isImportEqualsDeclaration(statement) || hasEffectiveModifier(statement, ModifierFlags.Default) || !canHaveModifiers(statement)) { + if ( + isImportEqualsDeclaration(statement) || hasEffectiveModifier(statement, ModifierFlags.Default) + || !canHaveModifiers(statement) + ) { // `export import` statements should remain as-is, as imports are _not_ implicitly exported in an ambient namespace // Likewise, `export default` classes and the like and just be `default`, so we preserve their `export` modifiers, too return statement; } - const modifiers = factory.createModifiersFromModifierFlags(getEffectiveModifierFlags(statement) & (ModifierFlags.All ^ ModifierFlags.Export)); + const modifiers = factory.createModifiersFromModifierFlags( + getEffectiveModifierFlags(statement) & (ModifierFlags.All ^ ModifierFlags.Export), + ); return factory.updateModifiers(statement, modifiers); } @@ -1489,7 +1831,9 @@ export function transformDeclarations(context: TransformationContext) { const canProdiceDiagnostic = canProduceDiagnostics(input); const oldDiag = getSymbolAccessibilityDiagnostic; if (canProdiceDiagnostic) { - getSymbolAccessibilityDiagnostic = createGetSymbolAccessibilityDiagnosticForNode(input as DeclarationDiagnosticProducing); + getSymbolAccessibilityDiagnostic = createGetSymbolAccessibilityDiagnosticForNode( + input as DeclarationDiagnosticProducing, + ); } const previousNeedsDeclare = needsDeclare; @@ -1531,32 +1875,61 @@ export function transformDeclarations(context: TransformationContext) { if (clean && resolver.isExpandoFunctionDeclaration(input) && shouldEmitFunctionProperties(input)) { const props = resolver.getPropertiesOfContainerFunction(input); // Use parseNodeFactory so it is usable as an enclosing declaration - const fakespace = parseNodeFactory.createModuleDeclaration(/*modifiers*/ undefined, clean.name || factory.createIdentifier("_default"), factory.createModuleBlock([]), NodeFlags.Namespace); + const fakespace = parseNodeFactory.createModuleDeclaration( + /*modifiers*/ undefined, + clean.name || factory.createIdentifier("_default"), + factory.createModuleBlock([]), + NodeFlags.Namespace, + ); setParent(fakespace, enclosingDeclaration as SourceFile | NamespaceDeclaration); fakespace.locals = createSymbolTable(props); fakespace.symbol = props[0].parent!; const exportMappings: [Identifier, string][] = []; let declarations: (VariableStatement | ExportDeclaration)[] = mapDefined(props, p => { - if (!p.valueDeclaration || !(isPropertyAccessExpression(p.valueDeclaration) || isElementAccessExpression(p.valueDeclaration) || isBinaryExpression(p.valueDeclaration))) { + if ( + !p.valueDeclaration + || !(isPropertyAccessExpression(p.valueDeclaration) + || isElementAccessExpression(p.valueDeclaration) + || isBinaryExpression(p.valueDeclaration)) + ) { return undefined; } const nameStr = unescapeLeadingUnderscores(p.escapedName); if (!isIdentifierText(nameStr, ScriptTarget.ESNext)) { return undefined; // unique symbol or non-identifier name - omit, since there's no syntax that can preserve it } - getSymbolAccessibilityDiagnostic = createGetSymbolAccessibilityDiagnosticForNode(p.valueDeclaration); - const type = resolver.createTypeOfDeclaration(p.valueDeclaration, fakespace, declarationEmitNodeBuilderFlags, symbolTracker); + getSymbolAccessibilityDiagnostic = createGetSymbolAccessibilityDiagnosticForNode( + p.valueDeclaration, + ); + const type = resolver.createTypeOfDeclaration( + p.valueDeclaration, + fakespace, + declarationEmitNodeBuilderFlags, + symbolTracker, + ); getSymbolAccessibilityDiagnostic = oldDiag; const isNonContextualKeywordName = isStringANonContextualKeyword(nameStr); - const name = isNonContextualKeywordName ? factory.getGeneratedNameForNode(p.valueDeclaration) : factory.createIdentifier(nameStr); + const name = isNonContextualKeywordName ? factory.getGeneratedNameForNode(p.valueDeclaration) + : factory.createIdentifier(nameStr); if (isNonContextualKeywordName) { exportMappings.push([name, nameStr]); } - const varDecl = factory.createVariableDeclaration(name, /*exclamationToken*/ undefined, type, /*initializer*/ undefined); - return factory.createVariableStatement(isNonContextualKeywordName ? undefined : [factory.createToken(SyntaxKind.ExportKeyword)], factory.createVariableDeclarationList([varDecl])); + const varDecl = factory.createVariableDeclaration( + name, + /*exclamationToken*/ undefined, + type, + /*initializer*/ undefined, + ); + return factory.createVariableStatement( + isNonContextualKeywordName ? undefined : [factory.createToken(SyntaxKind.ExportKeyword)], + factory.createVariableDeclarationList([varDecl]), + ); }); if (!exportMappings.length) { - declarations = mapDefined(declarations, declaration => factory.updateModifiers(declaration, ModifierFlags.None)); + declarations = mapDefined( + declarations, + declaration => factory.updateModifiers(declaration, ModifierFlags.None), + ); } else { declarations.push(factory.createExportDeclaration( @@ -1567,12 +1940,19 @@ export function transformDeclarations(context: TransformationContext) { })), )); } - const namespaceDecl = factory.createModuleDeclaration(ensureModifiers(input), input.name!, factory.createModuleBlock(declarations), NodeFlags.Namespace); + const namespaceDecl = factory.createModuleDeclaration( + ensureModifiers(input), + input.name!, + factory.createModuleBlock(declarations), + NodeFlags.Namespace, + ); if (!hasEffectiveModifier(clean, ModifierFlags.Default)) { return [clean, namespaceDecl]; } - const modifiers = factory.createModifiersFromModifierFlags((getEffectiveModifierFlags(clean) & ~ModifierFlags.ExportDefault) | ModifierFlags.Ambient); + const modifiers = factory.createModifiersFromModifierFlags( + (getEffectiveModifierFlags(clean) & ~ModifierFlags.ExportDefault) | ModifierFlags.Ambient, + ); const cleanDeclaration = factory.updateFunctionDeclaration( clean, modifiers, @@ -1673,7 +2053,10 @@ export function transformDeclarations(context: TransformationContext) { if (ctor) { const oldDiag = getSymbolAccessibilityDiagnostic; parameterProperties = compact(flatMap(ctor.parameters, param => { - if (!hasSyntacticModifier(param, ModifierFlags.ParameterPropertyModifier) || shouldStripInternal(param)) return; + if ( + !hasSyntacticModifier(param, ModifierFlags.ParameterPropertyModifier) + || shouldStripInternal(param) + ) return; getSymbolAccessibilityDiagnostic = createGetSymbolAccessibilityDiagnosticForNode(param); if (param.name.kind === SyntaxKind.Identifier) { return preserveJsDoc( @@ -1714,7 +2097,10 @@ export function transformDeclarations(context: TransformationContext) { getSymbolAccessibilityDiagnostic = oldDiag; } - const hasPrivateIdentifier = some(input.members, member => !!member.name && isPrivateIdentifier(member.name)); + const hasPrivateIdentifier = some( + input.members, + member => !!member.name && isPrivateIdentifier(member.name), + ); // When the class has at least one private identifier, create a unique constant identifier to retain the nominal typing behavior // Prevents other classes with the same public members from being used in place of the current class const privateIdentifier = hasPrivateIdentifier ? [ @@ -1726,31 +2112,72 @@ export function transformDeclarations(context: TransformationContext) { /*initializer*/ undefined, ), ] : undefined; - const memberNodes = concatenate(concatenate(privateIdentifier, parameterProperties), visitNodes(input.members, visitDeclarationSubtree, isClassElement)); + const memberNodes = concatenate( + concatenate(privateIdentifier, parameterProperties), + visitNodes(input.members, visitDeclarationSubtree, isClassElement), + ); const members = factory.createNodeArray(memberNodes); const extendsClause = getEffectiveBaseTypeNode(input); - if (extendsClause && !isEntityNameExpression(extendsClause.expression) && extendsClause.expression.kind !== SyntaxKind.NullKeyword) { + if ( + extendsClause && !isEntityNameExpression(extendsClause.expression) + && extendsClause.expression.kind !== SyntaxKind.NullKeyword + ) { // We must add a temporary declaration for the extends clause expression const oldId = input.name ? unescapeLeadingUnderscores(input.name.escapedText) : "default"; const newId = factory.createUniqueName(`${oldId}_base`, GeneratedIdentifierFlags.Optimistic); getSymbolAccessibilityDiagnostic = () => ({ - diagnosticMessage: Diagnostics.extends_clause_of_exported_class_0_has_or_is_using_private_name_1, + diagnosticMessage: + Diagnostics.extends_clause_of_exported_class_0_has_or_is_using_private_name_1, errorNode: extendsClause, typeName: input.name, }); - const varDecl = factory.createVariableDeclaration(newId, /*exclamationToken*/ undefined, resolver.createTypeOfExpression(extendsClause.expression, input, declarationEmitNodeBuilderFlags, symbolTracker), /*initializer*/ undefined); - const statement = factory.createVariableStatement(needsDeclare ? [factory.createModifier(SyntaxKind.DeclareKeyword)] : [], factory.createVariableDeclarationList([varDecl], NodeFlags.Const)); + const varDecl = factory.createVariableDeclaration( + newId, + /*exclamationToken*/ undefined, + resolver.createTypeOfExpression( + extendsClause.expression, + input, + declarationEmitNodeBuilderFlags, + symbolTracker, + ), + /*initializer*/ undefined, + ); + const statement = factory.createVariableStatement( + needsDeclare ? [factory.createModifier(SyntaxKind.DeclareKeyword)] : [], + factory.createVariableDeclarationList([varDecl], NodeFlags.Const), + ); const heritageClauses = factory.createNodeArray(map(input.heritageClauses, clause => { if (clause.token === SyntaxKind.ExtendsKeyword) { const oldDiag = getSymbolAccessibilityDiagnostic; - getSymbolAccessibilityDiagnostic = createGetSymbolAccessibilityDiagnosticForNode(clause.types[0]); - const newClause = factory.updateHeritageClause(clause, map(clause.types, t => factory.updateExpressionWithTypeArguments(t, newId, visitNodes(t.typeArguments, visitDeclarationSubtree, isTypeNode)))); + getSymbolAccessibilityDiagnostic = createGetSymbolAccessibilityDiagnosticForNode( + clause.types[0], + ); + const newClause = factory.updateHeritageClause( + clause, + map(clause.types, t => + factory.updateExpressionWithTypeArguments( + t, + newId, + visitNodes(t.typeArguments, visitDeclarationSubtree, isTypeNode), + )), + ); getSymbolAccessibilityDiagnostic = oldDiag; return newClause; } - return factory.updateHeritageClause(clause, visitNodes(factory.createNodeArray(filter(clause.types, t => isEntityNameExpression(t.expression) || t.expression.kind === SyntaxKind.NullKeyword)), visitDeclarationSubtree, isExpressionWithTypeArguments)); + return factory.updateHeritageClause( + clause, + visitNodes( + factory.createNodeArray( + filter(clause.types, t => + isEntityNameExpression(t.expression) + || t.expression.kind === SyntaxKind.NullKeyword), + ), + visitDeclarationSubtree, + isExpressionWithTypeArguments, + ), + ); })); return [ statement, @@ -1793,7 +2220,10 @@ export function transformDeclarations(context: TransformationContext) { : typeof constValue === "string" ? factory.createStringLiteral(constValue) : constValue < 0 - ? factory.createPrefixUnaryExpression(SyntaxKind.MinusToken, factory.createNumericLiteral(Math.abs(constValue))) + ? factory.createPrefixUnaryExpression( + SyntaxKind.MinusToken, + factory.createNumericLiteral(Math.abs(constValue)), + ) : factory.createNumericLiteral(constValue); return preserveJsDoc(factory.updateEnumMember(m, m.name, newInitializer), m); })), @@ -1801,7 +2231,10 @@ export function transformDeclarations(context: TransformationContext) { } } // Anything left unhandled is an error, so this should be unreachable - return Debug.assertNever(input, `Unhandled top-level node in declaration emit: ${Debug.formatSyntaxKind((input as Node).kind)}`); + return Debug.assertNever( + input, + `Unhandled top-level node in declaration emit: ${Debug.formatSyntaxKind((input as Node).kind)}`, + ); function cleanup(node: T | undefined): T | undefined { if (isEnclosingDeclaration(input)) { @@ -1855,7 +2288,12 @@ export function transformDeclarations(context: TransformationContext) { return recreateBindingPattern(e.name); } else { - return factory.createVariableDeclaration(e.name, /*exclamationToken*/ undefined, ensureType(e, /*type*/ undefined), /*initializer*/ undefined); + return factory.createVariableDeclaration( + e.name, + /*exclamationToken*/ undefined, + ensureType(e, /*type*/ undefined), + /*initializer*/ undefined, + ); } } } @@ -1909,7 +2347,10 @@ export function transformDeclarations(context: TransformationContext) { return maskModifierFlags(node, mask, additions); } - function getTypeAnnotationFromAllAccessorDeclarations(node: AccessorDeclaration, accessors: AllAccessorDeclarations) { + function getTypeAnnotationFromAllAccessorDeclarations( + node: AccessorDeclaration, + accessors: AllAccessorDeclarations, + ) { let accessorType = getTypeAnnotationFromAccessor(node); if (!accessorType && node !== accessors.firstAccessor) { accessorType = getTypeAnnotationFromAccessor(accessors.firstAccessor); @@ -1931,7 +2372,9 @@ export function transformDeclarations(context: TransformationContext) { clause, visitNodes( factory.createNodeArray(filter(clause.types, t => { - return isEntityNameExpression(t.expression) || (clause.token === SyntaxKind.ExtendsKeyword && t.expression.kind === SyntaxKind.NullKeyword); + return isEntityNameExpression(t.expression) + || (clause.token === SyntaxKind.ExtendsKeyword + && t.expression.kind === SyntaxKind.NullKeyword); })), visitDeclarationSubtree, isExpressionWithTypeArguments, @@ -1950,11 +2393,20 @@ function isAlwaysType(node: Node) { } // Elide "public" modifier, as it is the default -function maskModifiers(factory: NodeFactory, node: Node, modifierMask?: ModifierFlags, modifierAdditions?: ModifierFlags): Modifier[] | undefined { +function maskModifiers( + factory: NodeFactory, + node: Node, + modifierMask?: ModifierFlags, + modifierAdditions?: ModifierFlags, +): Modifier[] | undefined { return factory.createModifiersFromModifierFlags(maskModifierFlags(node, modifierMask, modifierAdditions)); } -function maskModifierFlags(node: Node, modifierMask: ModifierFlags = ModifierFlags.All ^ ModifierFlags.Public, modifierAdditions: ModifierFlags = ModifierFlags.None): ModifierFlags { +function maskModifierFlags( + node: Node, + modifierMask: ModifierFlags = ModifierFlags.All ^ ModifierFlags.Public, + modifierAdditions: ModifierFlags = ModifierFlags.None, +): ModifierFlags { let flags = (getEffectiveModifierFlags(node) & modifierMask) | modifierAdditions; if (flags & ModifierFlags.Default && !(flags & ModifierFlags.Export)) { // A non-exported default is a nonsequitor - we usually try to remove all export modifiers diff --git a/src/compiler/transformers/declarations/diagnostics.ts b/src/compiler/transformers/declarations/diagnostics.ts index 09c388378bd5c..771c40ba031cb 100644 --- a/src/compiler/transformers/declarations/diagnostics.ts +++ b/src/compiler/transformers/declarations/diagnostics.ts @@ -66,7 +66,9 @@ import { } from "../../_namespaces/ts"; /** @internal */ -export type GetSymbolAccessibilityDiagnostic = (symbolAccessibilityResult: SymbolAccessibilityResult) => SymbolAccessibilityDiagnostic | undefined; +export type GetSymbolAccessibilityDiagnostic = ( + symbolAccessibilityResult: SymbolAccessibilityResult, +) => SymbolAccessibilityDiagnostic | undefined; /** @internal */ export interface SymbolAccessibilityDiagnostic { @@ -104,28 +106,28 @@ export type DeclarationDiagnosticProducing = /** @internal */ export function canProduceDiagnostics(node: Node): node is DeclarationDiagnosticProducing { - return isVariableDeclaration(node) || - isPropertyDeclaration(node) || - isPropertySignature(node) || - isBindingElement(node) || - isSetAccessor(node) || - isGetAccessor(node) || - isConstructSignatureDeclaration(node) || - isCallSignatureDeclaration(node) || - isMethodDeclaration(node) || - isMethodSignature(node) || - isFunctionDeclaration(node) || - isParameter(node) || - isTypeParameterDeclaration(node) || - isExpressionWithTypeArguments(node) || - isImportEqualsDeclaration(node) || - isTypeAliasDeclaration(node) || - isConstructorDeclaration(node) || - isIndexSignatureDeclaration(node) || - isPropertyAccessExpression(node) || - isElementAccessExpression(node) || - isBinaryExpression(node) || - isJSDocTypeAlias(node); + return isVariableDeclaration(node) + || isPropertyDeclaration(node) + || isPropertySignature(node) + || isBindingElement(node) + || isSetAccessor(node) + || isGetAccessor(node) + || isConstructSignatureDeclaration(node) + || isCallSignatureDeclaration(node) + || isMethodDeclaration(node) + || isMethodSignature(node) + || isFunctionDeclaration(node) + || isParameter(node) + || isTypeParameterDeclaration(node) + || isExpressionWithTypeArguments(node) + || isImportEqualsDeclaration(node) + || isTypeAliasDeclaration(node) + || isConstructorDeclaration(node) + || isIndexSignatureDeclaration(node) + || isPropertyAccessExpression(node) + || isElementAccessExpression(node) + || isBinaryExpression(node) + || isJSDocTypeAlias(node); } /** @internal */ @@ -150,27 +152,32 @@ export function createGetSymbolAccessibilityDiagnosticForNodeName(node: Declarat function getAccessorNameVisibilityDiagnosticMessage(symbolAccessibilityResult: SymbolAccessibilityResult) { if (isStatic(node)) { - return symbolAccessibilityResult.errorModuleName ? - symbolAccessibilityResult.accessibility === SymbolAccessibility.CannotBeNamed ? - Diagnostics.Public_static_property_0_of_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : - Diagnostics.Public_static_property_0_of_exported_class_has_or_is_using_name_1_from_private_module_2 : - Diagnostics.Public_static_property_0_of_exported_class_has_or_is_using_private_name_1; + return symbolAccessibilityResult.errorModuleName + ? symbolAccessibilityResult.accessibility === SymbolAccessibility.CannotBeNamed + ? Diagnostics + .Public_static_property_0_of_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named + : Diagnostics + .Public_static_property_0_of_exported_class_has_or_is_using_name_1_from_private_module_2 + : Diagnostics.Public_static_property_0_of_exported_class_has_or_is_using_private_name_1; } else if (node.parent.kind === SyntaxKind.ClassDeclaration) { - return symbolAccessibilityResult.errorModuleName ? - symbolAccessibilityResult.accessibility === SymbolAccessibility.CannotBeNamed ? - Diagnostics.Public_property_0_of_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : - Diagnostics.Public_property_0_of_exported_class_has_or_is_using_name_1_from_private_module_2 : - Diagnostics.Public_property_0_of_exported_class_has_or_is_using_private_name_1; + return symbolAccessibilityResult.errorModuleName + ? symbolAccessibilityResult.accessibility === SymbolAccessibility.CannotBeNamed + ? Diagnostics + .Public_property_0_of_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named + : Diagnostics.Public_property_0_of_exported_class_has_or_is_using_name_1_from_private_module_2 + : Diagnostics.Public_property_0_of_exported_class_has_or_is_using_private_name_1; } else { - return symbolAccessibilityResult.errorModuleName ? - Diagnostics.Property_0_of_exported_interface_has_or_is_using_name_1_from_private_module_2 : - Diagnostics.Property_0_of_exported_interface_has_or_is_using_private_name_1; + return symbolAccessibilityResult.errorModuleName + ? Diagnostics.Property_0_of_exported_interface_has_or_is_using_name_1_from_private_module_2 + : Diagnostics.Property_0_of_exported_interface_has_or_is_using_private_name_1; } } - function getMethodNameVisibilityError(symbolAccessibilityResult: SymbolAccessibilityResult): SymbolAccessibilityDiagnostic | undefined { + function getMethodNameVisibilityError( + symbolAccessibilityResult: SymbolAccessibilityResult, + ): SymbolAccessibilityDiagnostic | undefined { const diagnosticMessage = getMethodNameVisibilityDiagnosticMessage(symbolAccessibilityResult); return diagnosticMessage !== undefined ? { diagnosticMessage, @@ -181,40 +188,54 @@ export function createGetSymbolAccessibilityDiagnosticForNodeName(node: Declarat function getMethodNameVisibilityDiagnosticMessage(symbolAccessibilityResult: SymbolAccessibilityResult) { if (isStatic(node)) { - return symbolAccessibilityResult.errorModuleName ? - symbolAccessibilityResult.accessibility === SymbolAccessibility.CannotBeNamed ? - Diagnostics.Public_static_method_0_of_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : - Diagnostics.Public_static_method_0_of_exported_class_has_or_is_using_name_1_from_private_module_2 : - Diagnostics.Public_static_method_0_of_exported_class_has_or_is_using_private_name_1; + return symbolAccessibilityResult.errorModuleName + ? symbolAccessibilityResult.accessibility === SymbolAccessibility.CannotBeNamed + ? Diagnostics + .Public_static_method_0_of_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named + : Diagnostics.Public_static_method_0_of_exported_class_has_or_is_using_name_1_from_private_module_2 + : Diagnostics.Public_static_method_0_of_exported_class_has_or_is_using_private_name_1; } else if (node.parent.kind === SyntaxKind.ClassDeclaration) { - return symbolAccessibilityResult.errorModuleName ? - symbolAccessibilityResult.accessibility === SymbolAccessibility.CannotBeNamed ? - Diagnostics.Public_method_0_of_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : - Diagnostics.Public_method_0_of_exported_class_has_or_is_using_name_1_from_private_module_2 : - Diagnostics.Public_method_0_of_exported_class_has_or_is_using_private_name_1; + return symbolAccessibilityResult.errorModuleName + ? symbolAccessibilityResult.accessibility === SymbolAccessibility.CannotBeNamed + ? Diagnostics + .Public_method_0_of_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named + : Diagnostics.Public_method_0_of_exported_class_has_or_is_using_name_1_from_private_module_2 + : Diagnostics.Public_method_0_of_exported_class_has_or_is_using_private_name_1; } else { - return symbolAccessibilityResult.errorModuleName ? - Diagnostics.Method_0_of_exported_interface_has_or_is_using_name_1_from_private_module_2 : - Diagnostics.Method_0_of_exported_interface_has_or_is_using_private_name_1; + return symbolAccessibilityResult.errorModuleName + ? Diagnostics.Method_0_of_exported_interface_has_or_is_using_name_1_from_private_module_2 + : Diagnostics.Method_0_of_exported_interface_has_or_is_using_private_name_1; } } } /** @internal */ -export function createGetSymbolAccessibilityDiagnosticForNode(node: DeclarationDiagnosticProducing): GetSymbolAccessibilityDiagnostic { - if (isVariableDeclaration(node) || isPropertyDeclaration(node) || isPropertySignature(node) || isPropertyAccessExpression(node) || isElementAccessExpression(node) || isBinaryExpression(node) || isBindingElement(node) || isConstructorDeclaration(node)) { +export function createGetSymbolAccessibilityDiagnosticForNode( + node: DeclarationDiagnosticProducing, +): GetSymbolAccessibilityDiagnostic { + if ( + isVariableDeclaration(node) || isPropertyDeclaration(node) || isPropertySignature(node) + || isPropertyAccessExpression(node) || isElementAccessExpression(node) || isBinaryExpression(node) + || isBindingElement(node) || isConstructorDeclaration(node) + ) { return getVariableDeclarationTypeVisibilityError; } else if (isSetAccessor(node) || isGetAccessor(node)) { return getAccessorDeclarationTypeVisibilityError; } - else if (isConstructSignatureDeclaration(node) || isCallSignatureDeclaration(node) || isMethodDeclaration(node) || isMethodSignature(node) || isFunctionDeclaration(node) || isIndexSignatureDeclaration(node)) { + else if ( + isConstructSignatureDeclaration(node) || isCallSignatureDeclaration(node) || isMethodDeclaration(node) + || isMethodSignature(node) || isFunctionDeclaration(node) || isIndexSignatureDeclaration(node) + ) { return getReturnTypeVisibilityError; } else if (isParameter(node)) { - if (isParameterPropertyDeclaration(node, node.parent) && hasSyntacticModifier(node.parent, ModifierFlags.Private)) { + if ( + isParameterPropertyDeclaration(node, node.parent) + && hasSyntacticModifier(node.parent, ModifierFlags.Private) + ) { return getVariableDeclarationTypeVisibilityError; } return getParameterDeclarationTypeVisibilityError; @@ -232,48 +253,62 @@ export function createGetSymbolAccessibilityDiagnosticForNode(node: DeclarationD return getTypeAliasDeclarationVisibilityError; } else { - return Debug.assertNever(node, `Attempted to set a declaration diagnostic context for unhandled node kind: ${Debug.formatSyntaxKind((node as Node).kind)}`); + return Debug.assertNever( + node, + `Attempted to set a declaration diagnostic context for unhandled node kind: ${ + Debug.formatSyntaxKind((node as Node).kind) + }`, + ); } - function getVariableDeclarationTypeVisibilityDiagnosticMessage(symbolAccessibilityResult: SymbolAccessibilityResult) { + function getVariableDeclarationTypeVisibilityDiagnosticMessage( + symbolAccessibilityResult: SymbolAccessibilityResult, + ) { if (node.kind === SyntaxKind.VariableDeclaration || node.kind === SyntaxKind.BindingElement) { - return symbolAccessibilityResult.errorModuleName ? - symbolAccessibilityResult.accessibility === SymbolAccessibility.CannotBeNamed ? - Diagnostics.Exported_variable_0_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : - Diagnostics.Exported_variable_0_has_or_is_using_name_1_from_private_module_2 : - Diagnostics.Exported_variable_0_has_or_is_using_private_name_1; + return symbolAccessibilityResult.errorModuleName + ? symbolAccessibilityResult.accessibility === SymbolAccessibility.CannotBeNamed + ? Diagnostics.Exported_variable_0_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named + : Diagnostics.Exported_variable_0_has_or_is_using_name_1_from_private_module_2 + : Diagnostics.Exported_variable_0_has_or_is_using_private_name_1; } // This check is to ensure we don't report error on constructor parameter property as that error would be reported during parameter emit // The only exception here is if the constructor was marked as private. we are not emitting the constructor parameters at all. else if ( - node.kind === SyntaxKind.PropertyDeclaration || node.kind === SyntaxKind.PropertyAccessExpression || node.kind === SyntaxKind.ElementAccessExpression || node.kind === SyntaxKind.BinaryExpression || node.kind === SyntaxKind.PropertySignature || - (node.kind === SyntaxKind.Parameter && hasSyntacticModifier(node.parent, ModifierFlags.Private)) + node.kind === SyntaxKind.PropertyDeclaration || node.kind === SyntaxKind.PropertyAccessExpression + || node.kind === SyntaxKind.ElementAccessExpression || node.kind === SyntaxKind.BinaryExpression + || node.kind === SyntaxKind.PropertySignature + || (node.kind === SyntaxKind.Parameter && hasSyntacticModifier(node.parent, ModifierFlags.Private)) ) { // TODO(jfreeman): Deal with computed properties in error reporting. if (isStatic(node)) { - return symbolAccessibilityResult.errorModuleName ? - symbolAccessibilityResult.accessibility === SymbolAccessibility.CannotBeNamed ? - Diagnostics.Public_static_property_0_of_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : - Diagnostics.Public_static_property_0_of_exported_class_has_or_is_using_name_1_from_private_module_2 : - Diagnostics.Public_static_property_0_of_exported_class_has_or_is_using_private_name_1; + return symbolAccessibilityResult.errorModuleName + ? symbolAccessibilityResult.accessibility === SymbolAccessibility.CannotBeNamed + ? Diagnostics + .Public_static_property_0_of_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named + : Diagnostics + .Public_static_property_0_of_exported_class_has_or_is_using_name_1_from_private_module_2 + : Diagnostics.Public_static_property_0_of_exported_class_has_or_is_using_private_name_1; } else if (node.parent.kind === SyntaxKind.ClassDeclaration || node.kind === SyntaxKind.Parameter) { - return symbolAccessibilityResult.errorModuleName ? - symbolAccessibilityResult.accessibility === SymbolAccessibility.CannotBeNamed ? - Diagnostics.Public_property_0_of_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : - Diagnostics.Public_property_0_of_exported_class_has_or_is_using_name_1_from_private_module_2 : - Diagnostics.Public_property_0_of_exported_class_has_or_is_using_private_name_1; + return symbolAccessibilityResult.errorModuleName + ? symbolAccessibilityResult.accessibility === SymbolAccessibility.CannotBeNamed + ? Diagnostics + .Public_property_0_of_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named + : Diagnostics.Public_property_0_of_exported_class_has_or_is_using_name_1_from_private_module_2 + : Diagnostics.Public_property_0_of_exported_class_has_or_is_using_private_name_1; } else { // Interfaces cannot have types that cannot be named - return symbolAccessibilityResult.errorModuleName ? - Diagnostics.Property_0_of_exported_interface_has_or_is_using_name_1_from_private_module_2 : - Diagnostics.Property_0_of_exported_interface_has_or_is_using_private_name_1; + return symbolAccessibilityResult.errorModuleName + ? Diagnostics.Property_0_of_exported_interface_has_or_is_using_name_1_from_private_module_2 + : Diagnostics.Property_0_of_exported_interface_has_or_is_using_private_name_1; } } } - function getVariableDeclarationTypeVisibilityError(symbolAccessibilityResult: SymbolAccessibilityResult): SymbolAccessibilityDiagnostic | undefined { + function getVariableDeclarationTypeVisibilityError( + symbolAccessibilityResult: SymbolAccessibilityResult, + ): SymbolAccessibilityDiagnostic | undefined { const diagnosticMessage = getVariableDeclarationTypeVisibilityDiagnosticMessage(symbolAccessibilityResult); return diagnosticMessage !== undefined ? { diagnosticMessage, @@ -282,36 +317,46 @@ export function createGetSymbolAccessibilityDiagnosticForNode(node: DeclarationD } : undefined; } - function getAccessorDeclarationTypeVisibilityError(symbolAccessibilityResult: SymbolAccessibilityResult): SymbolAccessibilityDiagnostic { + function getAccessorDeclarationTypeVisibilityError( + symbolAccessibilityResult: SymbolAccessibilityResult, + ): SymbolAccessibilityDiagnostic { let diagnosticMessage: DiagnosticMessage; if (node.kind === SyntaxKind.SetAccessor) { // Getters can infer the return type from the returned expression, but setters cannot, so the // "_from_external_module_1_but_cannot_be_named" case cannot occur. if (isStatic(node)) { - diagnosticMessage = symbolAccessibilityResult.errorModuleName ? - Diagnostics.Parameter_type_of_public_static_setter_0_from_exported_class_has_or_is_using_name_1_from_private_module_2 : - Diagnostics.Parameter_type_of_public_static_setter_0_from_exported_class_has_or_is_using_private_name_1; + diagnosticMessage = symbolAccessibilityResult.errorModuleName + ? Diagnostics + .Parameter_type_of_public_static_setter_0_from_exported_class_has_or_is_using_name_1_from_private_module_2 + : Diagnostics + .Parameter_type_of_public_static_setter_0_from_exported_class_has_or_is_using_private_name_1; } else { - diagnosticMessage = symbolAccessibilityResult.errorModuleName ? - Diagnostics.Parameter_type_of_public_setter_0_from_exported_class_has_or_is_using_name_1_from_private_module_2 : - Diagnostics.Parameter_type_of_public_setter_0_from_exported_class_has_or_is_using_private_name_1; + diagnosticMessage = symbolAccessibilityResult.errorModuleName + ? Diagnostics + .Parameter_type_of_public_setter_0_from_exported_class_has_or_is_using_name_1_from_private_module_2 + : Diagnostics.Parameter_type_of_public_setter_0_from_exported_class_has_or_is_using_private_name_1; } } else { if (isStatic(node)) { - diagnosticMessage = symbolAccessibilityResult.errorModuleName ? - symbolAccessibilityResult.accessibility === SymbolAccessibility.CannotBeNamed ? - Diagnostics.Return_type_of_public_static_getter_0_from_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : - Diagnostics.Return_type_of_public_static_getter_0_from_exported_class_has_or_is_using_name_1_from_private_module_2 : - Diagnostics.Return_type_of_public_static_getter_0_from_exported_class_has_or_is_using_private_name_1; + diagnosticMessage = symbolAccessibilityResult.errorModuleName + ? symbolAccessibilityResult.accessibility === SymbolAccessibility.CannotBeNamed + ? Diagnostics + .Return_type_of_public_static_getter_0_from_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named + : Diagnostics + .Return_type_of_public_static_getter_0_from_exported_class_has_or_is_using_name_1_from_private_module_2 + : Diagnostics + .Return_type_of_public_static_getter_0_from_exported_class_has_or_is_using_private_name_1; } else { - diagnosticMessage = symbolAccessibilityResult.errorModuleName ? - symbolAccessibilityResult.accessibility === SymbolAccessibility.CannotBeNamed ? - Diagnostics.Return_type_of_public_getter_0_from_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : - Diagnostics.Return_type_of_public_getter_0_from_exported_class_has_or_is_using_name_1_from_private_module_2 : - Diagnostics.Return_type_of_public_getter_0_from_exported_class_has_or_is_using_private_name_1; + diagnosticMessage = symbolAccessibilityResult.errorModuleName + ? symbolAccessibilityResult.accessibility === SymbolAccessibility.CannotBeNamed + ? Diagnostics + .Return_type_of_public_getter_0_from_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named + : Diagnostics + .Return_type_of_public_getter_0_from_exported_class_has_or_is_using_name_1_from_private_module_2 + : Diagnostics.Return_type_of_public_getter_0_from_exported_class_has_or_is_using_private_name_1; } } return { @@ -321,60 +366,73 @@ export function createGetSymbolAccessibilityDiagnosticForNode(node: DeclarationD }; } - function getReturnTypeVisibilityError(symbolAccessibilityResult: SymbolAccessibilityResult): SymbolAccessibilityDiagnostic { + function getReturnTypeVisibilityError( + symbolAccessibilityResult: SymbolAccessibilityResult, + ): SymbolAccessibilityDiagnostic { let diagnosticMessage: DiagnosticMessage; switch (node.kind) { case SyntaxKind.ConstructSignature: // Interfaces cannot have return types that cannot be named - diagnosticMessage = symbolAccessibilityResult.errorModuleName ? - Diagnostics.Return_type_of_constructor_signature_from_exported_interface_has_or_is_using_name_0_from_private_module_1 : - Diagnostics.Return_type_of_constructor_signature_from_exported_interface_has_or_is_using_private_name_0; + diagnosticMessage = symbolAccessibilityResult.errorModuleName + ? Diagnostics + .Return_type_of_constructor_signature_from_exported_interface_has_or_is_using_name_0_from_private_module_1 + : Diagnostics + .Return_type_of_constructor_signature_from_exported_interface_has_or_is_using_private_name_0; break; case SyntaxKind.CallSignature: // Interfaces cannot have return types that cannot be named - diagnosticMessage = symbolAccessibilityResult.errorModuleName ? - Diagnostics.Return_type_of_call_signature_from_exported_interface_has_or_is_using_name_0_from_private_module_1 : - Diagnostics.Return_type_of_call_signature_from_exported_interface_has_or_is_using_private_name_0; + diagnosticMessage = symbolAccessibilityResult.errorModuleName + ? Diagnostics + .Return_type_of_call_signature_from_exported_interface_has_or_is_using_name_0_from_private_module_1 + : Diagnostics.Return_type_of_call_signature_from_exported_interface_has_or_is_using_private_name_0; break; case SyntaxKind.IndexSignature: // Interfaces cannot have return types that cannot be named - diagnosticMessage = symbolAccessibilityResult.errorModuleName ? - Diagnostics.Return_type_of_index_signature_from_exported_interface_has_or_is_using_name_0_from_private_module_1 : - Diagnostics.Return_type_of_index_signature_from_exported_interface_has_or_is_using_private_name_0; + diagnosticMessage = symbolAccessibilityResult.errorModuleName + ? Diagnostics + .Return_type_of_index_signature_from_exported_interface_has_or_is_using_name_0_from_private_module_1 + : Diagnostics.Return_type_of_index_signature_from_exported_interface_has_or_is_using_private_name_0; break; case SyntaxKind.MethodDeclaration: case SyntaxKind.MethodSignature: if (isStatic(node)) { - diagnosticMessage = symbolAccessibilityResult.errorModuleName ? - symbolAccessibilityResult.accessibility === SymbolAccessibility.CannotBeNamed ? - Diagnostics.Return_type_of_public_static_method_from_exported_class_has_or_is_using_name_0_from_external_module_1_but_cannot_be_named : - Diagnostics.Return_type_of_public_static_method_from_exported_class_has_or_is_using_name_0_from_private_module_1 : - Diagnostics.Return_type_of_public_static_method_from_exported_class_has_or_is_using_private_name_0; + diagnosticMessage = symbolAccessibilityResult.errorModuleName + ? symbolAccessibilityResult.accessibility === SymbolAccessibility.CannotBeNamed + ? Diagnostics + .Return_type_of_public_static_method_from_exported_class_has_or_is_using_name_0_from_external_module_1_but_cannot_be_named + : Diagnostics + .Return_type_of_public_static_method_from_exported_class_has_or_is_using_name_0_from_private_module_1 + : Diagnostics + .Return_type_of_public_static_method_from_exported_class_has_or_is_using_private_name_0; } else if (node.parent.kind === SyntaxKind.ClassDeclaration) { - diagnosticMessage = symbolAccessibilityResult.errorModuleName ? - symbolAccessibilityResult.accessibility === SymbolAccessibility.CannotBeNamed ? - Diagnostics.Return_type_of_public_method_from_exported_class_has_or_is_using_name_0_from_external_module_1_but_cannot_be_named : - Diagnostics.Return_type_of_public_method_from_exported_class_has_or_is_using_name_0_from_private_module_1 : - Diagnostics.Return_type_of_public_method_from_exported_class_has_or_is_using_private_name_0; + diagnosticMessage = symbolAccessibilityResult.errorModuleName + ? symbolAccessibilityResult.accessibility === SymbolAccessibility.CannotBeNamed + ? Diagnostics + .Return_type_of_public_method_from_exported_class_has_or_is_using_name_0_from_external_module_1_but_cannot_be_named + : Diagnostics + .Return_type_of_public_method_from_exported_class_has_or_is_using_name_0_from_private_module_1 + : Diagnostics.Return_type_of_public_method_from_exported_class_has_or_is_using_private_name_0; } else { // Interfaces cannot have return types that cannot be named - diagnosticMessage = symbolAccessibilityResult.errorModuleName ? - Diagnostics.Return_type_of_method_from_exported_interface_has_or_is_using_name_0_from_private_module_1 : - Diagnostics.Return_type_of_method_from_exported_interface_has_or_is_using_private_name_0; + diagnosticMessage = symbolAccessibilityResult.errorModuleName + ? Diagnostics + .Return_type_of_method_from_exported_interface_has_or_is_using_name_0_from_private_module_1 + : Diagnostics.Return_type_of_method_from_exported_interface_has_or_is_using_private_name_0; } break; case SyntaxKind.FunctionDeclaration: - diagnosticMessage = symbolAccessibilityResult.errorModuleName ? - symbolAccessibilityResult.accessibility === SymbolAccessibility.CannotBeNamed ? - Diagnostics.Return_type_of_exported_function_has_or_is_using_name_0_from_external_module_1_but_cannot_be_named : - Diagnostics.Return_type_of_exported_function_has_or_is_using_name_0_from_private_module_1 : - Diagnostics.Return_type_of_exported_function_has_or_is_using_private_name_0; + diagnosticMessage = symbolAccessibilityResult.errorModuleName + ? symbolAccessibilityResult.accessibility === SymbolAccessibility.CannotBeNamed + ? Diagnostics + .Return_type_of_exported_function_has_or_is_using_name_0_from_external_module_1_but_cannot_be_named + : Diagnostics.Return_type_of_exported_function_has_or_is_using_name_0_from_private_module_1 + : Diagnostics.Return_type_of_exported_function_has_or_is_using_private_name_0; break; default: @@ -387,8 +445,12 @@ export function createGetSymbolAccessibilityDiagnosticForNode(node: DeclarationD }; } - function getParameterDeclarationTypeVisibilityError(symbolAccessibilityResult: SymbolAccessibilityResult): SymbolAccessibilityDiagnostic | undefined { - const diagnosticMessage: DiagnosticMessage = getParameterDeclarationTypeVisibilityDiagnosticMessage(symbolAccessibilityResult); + function getParameterDeclarationTypeVisibilityError( + symbolAccessibilityResult: SymbolAccessibilityResult, + ): SymbolAccessibilityDiagnostic | undefined { + const diagnosticMessage: DiagnosticMessage = getParameterDeclarationTypeVisibilityDiagnosticMessage( + symbolAccessibilityResult, + ); return diagnosticMessage !== undefined ? { diagnosticMessage, errorNode: node, @@ -396,71 +458,87 @@ export function createGetSymbolAccessibilityDiagnosticForNode(node: DeclarationD } : undefined; } - function getParameterDeclarationTypeVisibilityDiagnosticMessage(symbolAccessibilityResult: SymbolAccessibilityResult): DiagnosticMessage { + function getParameterDeclarationTypeVisibilityDiagnosticMessage( + symbolAccessibilityResult: SymbolAccessibilityResult, + ): DiagnosticMessage { switch (node.parent.kind) { case SyntaxKind.Constructor: - return symbolAccessibilityResult.errorModuleName ? - symbolAccessibilityResult.accessibility === SymbolAccessibility.CannotBeNamed ? - Diagnostics.Parameter_0_of_constructor_from_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : - Diagnostics.Parameter_0_of_constructor_from_exported_class_has_or_is_using_name_1_from_private_module_2 : - Diagnostics.Parameter_0_of_constructor_from_exported_class_has_or_is_using_private_name_1; + return symbolAccessibilityResult.errorModuleName + ? symbolAccessibilityResult.accessibility === SymbolAccessibility.CannotBeNamed + ? Diagnostics + .Parameter_0_of_constructor_from_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named + : Diagnostics + .Parameter_0_of_constructor_from_exported_class_has_or_is_using_name_1_from_private_module_2 + : Diagnostics.Parameter_0_of_constructor_from_exported_class_has_or_is_using_private_name_1; case SyntaxKind.ConstructSignature: case SyntaxKind.ConstructorType: // Interfaces cannot have parameter types that cannot be named - return symbolAccessibilityResult.errorModuleName ? - Diagnostics.Parameter_0_of_constructor_signature_from_exported_interface_has_or_is_using_name_1_from_private_module_2 : - Diagnostics.Parameter_0_of_constructor_signature_from_exported_interface_has_or_is_using_private_name_1; + return symbolAccessibilityResult.errorModuleName + ? Diagnostics + .Parameter_0_of_constructor_signature_from_exported_interface_has_or_is_using_name_1_from_private_module_2 + : Diagnostics + .Parameter_0_of_constructor_signature_from_exported_interface_has_or_is_using_private_name_1; case SyntaxKind.CallSignature: // Interfaces cannot have parameter types that cannot be named - return symbolAccessibilityResult.errorModuleName ? - Diagnostics.Parameter_0_of_call_signature_from_exported_interface_has_or_is_using_name_1_from_private_module_2 : - Diagnostics.Parameter_0_of_call_signature_from_exported_interface_has_or_is_using_private_name_1; + return symbolAccessibilityResult.errorModuleName + ? Diagnostics + .Parameter_0_of_call_signature_from_exported_interface_has_or_is_using_name_1_from_private_module_2 + : Diagnostics.Parameter_0_of_call_signature_from_exported_interface_has_or_is_using_private_name_1; case SyntaxKind.IndexSignature: // Interfaces cannot have parameter types that cannot be named - return symbolAccessibilityResult.errorModuleName ? - Diagnostics.Parameter_0_of_index_signature_from_exported_interface_has_or_is_using_name_1_from_private_module_2 : - Diagnostics.Parameter_0_of_index_signature_from_exported_interface_has_or_is_using_private_name_1; + return symbolAccessibilityResult.errorModuleName + ? Diagnostics + .Parameter_0_of_index_signature_from_exported_interface_has_or_is_using_name_1_from_private_module_2 + : Diagnostics.Parameter_0_of_index_signature_from_exported_interface_has_or_is_using_private_name_1; case SyntaxKind.MethodDeclaration: case SyntaxKind.MethodSignature: if (isStatic(node.parent)) { - return symbolAccessibilityResult.errorModuleName ? - symbolAccessibilityResult.accessibility === SymbolAccessibility.CannotBeNamed ? - Diagnostics.Parameter_0_of_public_static_method_from_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : - Diagnostics.Parameter_0_of_public_static_method_from_exported_class_has_or_is_using_name_1_from_private_module_2 : - Diagnostics.Parameter_0_of_public_static_method_from_exported_class_has_or_is_using_private_name_1; + return symbolAccessibilityResult.errorModuleName + ? symbolAccessibilityResult.accessibility === SymbolAccessibility.CannotBeNamed + ? Diagnostics + .Parameter_0_of_public_static_method_from_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named + : Diagnostics + .Parameter_0_of_public_static_method_from_exported_class_has_or_is_using_name_1_from_private_module_2 + : Diagnostics + .Parameter_0_of_public_static_method_from_exported_class_has_or_is_using_private_name_1; } else if (node.parent.parent.kind === SyntaxKind.ClassDeclaration) { - return symbolAccessibilityResult.errorModuleName ? - symbolAccessibilityResult.accessibility === SymbolAccessibility.CannotBeNamed ? - Diagnostics.Parameter_0_of_public_method_from_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : - Diagnostics.Parameter_0_of_public_method_from_exported_class_has_or_is_using_name_1_from_private_module_2 : - Diagnostics.Parameter_0_of_public_method_from_exported_class_has_or_is_using_private_name_1; + return symbolAccessibilityResult.errorModuleName + ? symbolAccessibilityResult.accessibility === SymbolAccessibility.CannotBeNamed + ? Diagnostics + .Parameter_0_of_public_method_from_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named + : Diagnostics + .Parameter_0_of_public_method_from_exported_class_has_or_is_using_name_1_from_private_module_2 + : Diagnostics.Parameter_0_of_public_method_from_exported_class_has_or_is_using_private_name_1; } else { // Interfaces cannot have parameter types that cannot be named - return symbolAccessibilityResult.errorModuleName ? - Diagnostics.Parameter_0_of_method_from_exported_interface_has_or_is_using_name_1_from_private_module_2 : - Diagnostics.Parameter_0_of_method_from_exported_interface_has_or_is_using_private_name_1; + return symbolAccessibilityResult.errorModuleName + ? Diagnostics + .Parameter_0_of_method_from_exported_interface_has_or_is_using_name_1_from_private_module_2 + : Diagnostics.Parameter_0_of_method_from_exported_interface_has_or_is_using_private_name_1; } case SyntaxKind.FunctionDeclaration: case SyntaxKind.FunctionType: - return symbolAccessibilityResult.errorModuleName ? - symbolAccessibilityResult.accessibility === SymbolAccessibility.CannotBeNamed ? - Diagnostics.Parameter_0_of_exported_function_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : - Diagnostics.Parameter_0_of_exported_function_has_or_is_using_name_1_from_private_module_2 : - Diagnostics.Parameter_0_of_exported_function_has_or_is_using_private_name_1; + return symbolAccessibilityResult.errorModuleName + ? symbolAccessibilityResult.accessibility === SymbolAccessibility.CannotBeNamed + ? Diagnostics + .Parameter_0_of_exported_function_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named + : Diagnostics.Parameter_0_of_exported_function_has_or_is_using_name_1_from_private_module_2 + : Diagnostics.Parameter_0_of_exported_function_has_or_is_using_private_name_1; case SyntaxKind.SetAccessor: case SyntaxKind.GetAccessor: - return symbolAccessibilityResult.errorModuleName ? - symbolAccessibilityResult.accessibility === SymbolAccessibility.CannotBeNamed ? - Diagnostics.Parameter_0_of_accessor_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : - Diagnostics.Parameter_0_of_accessor_has_or_is_using_name_1_from_private_module_2 : - Diagnostics.Parameter_0_of_accessor_has_or_is_using_private_name_1; + return symbolAccessibilityResult.errorModuleName + ? symbolAccessibilityResult.accessibility === SymbolAccessibility.CannotBeNamed + ? Diagnostics + .Parameter_0_of_accessor_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named + : Diagnostics.Parameter_0_of_accessor_has_or_is_using_name_1_from_private_module_2 + : Diagnostics.Parameter_0_of_accessor_has_or_is_using_private_name_1; default: return Debug.fail(`Unknown parent for parameter: ${Debug.formatSyntaxKind(node.parent.kind)}`); @@ -485,23 +563,28 @@ export function createGetSymbolAccessibilityDiagnosticForNode(node: DeclarationD case SyntaxKind.ConstructorType: case SyntaxKind.ConstructSignature: - diagnosticMessage = Diagnostics.Type_parameter_0_of_constructor_signature_from_exported_interface_has_or_is_using_private_name_1; + diagnosticMessage = Diagnostics + .Type_parameter_0_of_constructor_signature_from_exported_interface_has_or_is_using_private_name_1; break; case SyntaxKind.CallSignature: - diagnosticMessage = Diagnostics.Type_parameter_0_of_call_signature_from_exported_interface_has_or_is_using_private_name_1; + diagnosticMessage = Diagnostics + .Type_parameter_0_of_call_signature_from_exported_interface_has_or_is_using_private_name_1; break; case SyntaxKind.MethodDeclaration: case SyntaxKind.MethodSignature: if (isStatic(node.parent)) { - diagnosticMessage = Diagnostics.Type_parameter_0_of_public_static_method_from_exported_class_has_or_is_using_private_name_1; + diagnosticMessage = Diagnostics + .Type_parameter_0_of_public_static_method_from_exported_class_has_or_is_using_private_name_1; } else if (node.parent.parent.kind === SyntaxKind.ClassDeclaration) { - diagnosticMessage = Diagnostics.Type_parameter_0_of_public_method_from_exported_class_has_or_is_using_private_name_1; + diagnosticMessage = Diagnostics + .Type_parameter_0_of_public_method_from_exported_class_has_or_is_using_private_name_1; } else { - diagnosticMessage = Diagnostics.Type_parameter_0_of_method_from_exported_interface_has_or_is_using_private_name_1; + diagnosticMessage = + Diagnostics.Type_parameter_0_of_method_from_exported_interface_has_or_is_using_private_name_1; } break; @@ -534,10 +617,11 @@ export function createGetSymbolAccessibilityDiagnosticForNode(node: DeclarationD // Heritage clause is written by user so it can always be named if (isClassDeclaration(node.parent.parent)) { // Class or Interface implemented/extended is inaccessible - diagnosticMessage = isHeritageClause(node.parent) && node.parent.token === SyntaxKind.ImplementsKeyword ? - Diagnostics.Implements_clause_of_exported_class_0_has_or_is_using_private_name_1 : - node.parent.parent.name ? Diagnostics.extends_clause_of_exported_class_0_has_or_is_using_private_name_1 : - Diagnostics.extends_clause_of_exported_class_has_or_is_using_private_name_0; + diagnosticMessage = isHeritageClause(node.parent) && node.parent.token === SyntaxKind.ImplementsKeyword + ? Diagnostics.Implements_clause_of_exported_class_0_has_or_is_using_private_name_1 + : node.parent.parent.name + ? Diagnostics.extends_clause_of_exported_class_0_has_or_is_using_private_name_1 + : Diagnostics.extends_clause_of_exported_class_has_or_is_using_private_name_0; } else { // interface is inaccessible @@ -559,12 +643,15 @@ export function createGetSymbolAccessibilityDiagnosticForNode(node: DeclarationD }; } - function getTypeAliasDeclarationVisibilityError(symbolAccessibilityResult: SymbolAccessibilityResult): SymbolAccessibilityDiagnostic { + function getTypeAliasDeclarationVisibilityError( + symbolAccessibilityResult: SymbolAccessibilityResult, + ): SymbolAccessibilityDiagnostic { return { diagnosticMessage: symbolAccessibilityResult.errorModuleName ? Diagnostics.Exported_type_alias_0_has_or_is_using_private_name_1_from_module_2 : Diagnostics.Exported_type_alias_0_has_or_is_using_private_name_1, - errorNode: isJSDocTypeAlias(node) ? Debug.checkDefined(node.typeExpression) : (node as TypeAliasDeclaration).type, + errorNode: isJSDocTypeAlias(node) ? Debug.checkDefined(node.typeExpression) + : (node as TypeAliasDeclaration).type, typeName: isJSDocTypeAlias(node) ? getNameOfDeclaration(node) : (node as TypeAliasDeclaration).name, }; } diff --git a/src/compiler/transformers/destructuring.ts b/src/compiler/transformers/destructuring.ts index 1a3b93e8b77fa..d095fcb158797 100644 --- a/src/compiler/transformers/destructuring.ts +++ b/src/compiler/transformers/destructuring.ts @@ -69,9 +69,16 @@ interface FlattenContext { hoistTempVariables: boolean; hasTransformedPriorElement?: boolean; // indicates whether we've transformed a prior declaration emitExpression: (value: Expression) => void; - emitBindingOrAssignment: (target: BindingOrAssignmentElementTarget, value: Expression, location: TextRange, original: Node | undefined) => void; + emitBindingOrAssignment: ( + target: BindingOrAssignmentElementTarget, + value: Expression, + location: TextRange, + original: Node | undefined, + ) => void; createArrayBindingOrAssignmentPattern: (elements: BindingOrAssignmentElement[]) => ArrayBindingOrAssignmentPattern; - createObjectBindingOrAssignmentPattern: (elements: BindingOrAssignmentElement[]) => ObjectBindingOrAssignmentPattern; + createObjectBindingOrAssignmentPattern: ( + elements: BindingOrAssignmentElement[], + ) => ObjectBindingOrAssignmentPattern; createArrayBindingOrAssignmentElement: (node: Identifier) => BindingOrAssignmentElement; visitor: (node: Node) => VisitResult; } @@ -137,8 +144,8 @@ export function flattenDestructuringAssignment( Debug.assert(value); if ( - isIdentifier(value) && bindingOrAssignmentElementAssignsToName(node, value.escapedText) || - bindingOrAssignmentElementContainsNonLiteralComputedName(node) + isIdentifier(value) && bindingOrAssignmentElementAssignsToName(node, value.escapedText) + || bindingOrAssignmentElementContainsNonLiteralComputedName(node) ) { // If the right-hand value of the assignment is also an assignment target then // we need to cache the right-hand value. @@ -164,7 +171,13 @@ export function flattenDestructuringAssignment( } } - flattenBindingOrAssignmentElement(flattenContext, node, value, location, /*skipInitializer*/ isDestructuringAssignment(node)); + flattenBindingOrAssignmentElement( + flattenContext, + node, + value, + location, + /*skipInitializer*/ isDestructuringAssignment(node), + ); if (value && needsValue) { if (!some(expressions)) { @@ -180,12 +193,20 @@ export function flattenDestructuringAssignment( expressions = append(expressions, expression); } - function emitBindingOrAssignment(target: BindingOrAssignmentElementTarget, value: Expression, location: TextRange, original: Node | undefined) { + function emitBindingOrAssignment( + target: BindingOrAssignmentElementTarget, + value: Expression, + location: TextRange, + original: Node | undefined, + ) { Debug.assertNode(target, createAssignmentCallback ? isIdentifier : isExpression); const expression = createAssignmentCallback ? createAssignmentCallback(target as Identifier, value, location) : setTextRange( - context.factory.createAssignment(Debug.checkDefined(visitNode(target as Expression, visitor, isExpression)), value), + context.factory.createAssignment( + Debug.checkDefined(visitNode(target as Expression, visitor, isExpression)), + value, + ), location, ); expression.original = original; @@ -220,11 +241,15 @@ function bindingOrAssignmentElementContainsNonLiteralComputedName(element: Bindi return true; } const target = getTargetOfBindingOrAssignmentElement(element); - return !!target && isBindingOrAssignmentPattern(target) && bindingOrAssignmentPatternContainsNonLiteralComputedName(target); + return !!target && isBindingOrAssignmentPattern(target) + && bindingOrAssignmentPatternContainsNonLiteralComputedName(target); } function bindingOrAssignmentPatternContainsNonLiteralComputedName(pattern: BindingOrAssignmentPattern): boolean { - return !!forEach(getElementsOfBindingOrAssignmentPattern(pattern), bindingOrAssignmentElementContainsNonLiteralComputedName); + return !!forEach( + getElementsOfBindingOrAssignmentPattern(pattern), + bindingOrAssignmentElementContainsNonLiteralComputedName, + ); } /** @@ -250,7 +275,13 @@ export function flattenDestructuringBinding( skipInitializer?: boolean, ): VariableDeclaration[] { let pendingExpressions: Expression[] | undefined; - const pendingDeclarations: { pendingExpressions?: Expression[]; name: BindingName; value: Expression; location?: TextRange; original?: Node; }[] = []; + const pendingDeclarations: { + pendingExpressions?: Expression[]; + name: BindingName; + value: Expression; + location?: TextRange; + original?: Node; + }[] = []; const declarations: VariableDeclaration[] = []; const flattenContext: FlattenContext = { context, @@ -268,13 +299,25 @@ export function flattenDestructuringBinding( if (isVariableDeclaration(node)) { let initializer = getInitializerOfBindingOrAssignmentElement(node); if ( - initializer && (isIdentifier(initializer) && bindingOrAssignmentElementAssignsToName(node, initializer.escapedText) || - bindingOrAssignmentElementContainsNonLiteralComputedName(node)) + initializer + && (isIdentifier(initializer) && bindingOrAssignmentElementAssignsToName(node, initializer.escapedText) + || bindingOrAssignmentElementContainsNonLiteralComputedName(node)) ) { // If the right-hand value of the assignment is also an assignment target then // we need to cache the right-hand value. - initializer = ensureIdentifier(flattenContext, Debug.checkDefined(visitNode(initializer, flattenContext.visitor, isExpression)), /*reuseIdentifierExpressions*/ false, initializer); - node = context.factory.updateVariableDeclaration(node, node.name, /*exclamationToken*/ undefined, /*type*/ undefined, initializer); + initializer = ensureIdentifier( + flattenContext, + Debug.checkDefined(visitNode(initializer, flattenContext.visitor, isExpression)), + /*reuseIdentifierExpressions*/ false, + initializer, + ); + node = context.factory.updateVariableDeclaration( + node, + node.name, + /*exclamationToken*/ undefined, + /*type*/ undefined, + initializer, + ); } } @@ -314,7 +357,12 @@ export function flattenDestructuringBinding( pendingExpressions = append(pendingExpressions, value); } - function emitBindingOrAssignment(target: BindingOrAssignmentElementTarget, value: Expression, location: TextRange | undefined, original: Node | undefined) { + function emitBindingOrAssignment( + target: BindingOrAssignmentElementTarget, + value: Expression, + location: TextRange | undefined, + original: Node | undefined, + ) { Debug.assertNode(target, isBindingName); if (pendingExpressions) { value = context.factory.inlineExpressions(append(pendingExpressions, value)); @@ -343,7 +391,11 @@ function flattenBindingOrAssignmentElement( ) { const bindingTarget = getTargetOfBindingOrAssignmentElement(element)!; // TODO: GH#18217 if (!skipInitializer) { - const initializer = visitNode(getInitializerOfBindingOrAssignmentElement(element), flattenContext.visitor, isExpression); + const initializer = visitNode( + getInitializerOfBindingOrAssignmentElement(element), + flattenContext.visitor, + isExpression, + ); if (initializer) { // Combine value and initializer if (value) { @@ -382,7 +434,13 @@ function flattenBindingOrAssignmentElement( * @param value The current RHS value to assign to the element. * @param location The location to use for source maps and comments. */ -function flattenObjectBindingOrAssignmentPattern(flattenContext: FlattenContext, parent: BindingOrAssignmentElement, pattern: ObjectBindingOrAssignmentPattern, value: Expression, location: TextRange) { +function flattenObjectBindingOrAssignmentPattern( + flattenContext: FlattenContext, + parent: BindingOrAssignmentElement, + pattern: ObjectBindingOrAssignmentPattern, + value: Expression, + location: TextRange, +) { const elements = getElementsOfBindingOrAssignmentPattern(pattern); const numElements = elements.length; if (numElements !== 1) { @@ -401,35 +459,63 @@ function flattenObjectBindingOrAssignmentPattern(flattenContext: FlattenContext, const propertyName = getPropertyNameOfBindingOrAssignmentElement(element)!; if ( flattenContext.level >= FlattenLevel.ObjectRest - && !(element.transformFlags & (TransformFlags.ContainsRestOrSpread | TransformFlags.ContainsObjectRestOrSpread)) - && !(getTargetOfBindingOrAssignmentElement(element)!.transformFlags & (TransformFlags.ContainsRestOrSpread | TransformFlags.ContainsObjectRestOrSpread)) + && !(element.transformFlags + & (TransformFlags.ContainsRestOrSpread | TransformFlags.ContainsObjectRestOrSpread)) + && !(getTargetOfBindingOrAssignmentElement(element)!.transformFlags + & (TransformFlags.ContainsRestOrSpread | TransformFlags.ContainsObjectRestOrSpread)) && !isComputedPropertyName(propertyName) ) { - bindingElements = append(bindingElements, visitNode(element, flattenContext.visitor, isBindingOrAssignmentElement)); + bindingElements = append( + bindingElements, + visitNode(element, flattenContext.visitor, isBindingOrAssignmentElement), + ); } else { if (bindingElements) { - flattenContext.emitBindingOrAssignment(flattenContext.createObjectBindingOrAssignmentPattern(bindingElements), value, location, pattern); + flattenContext.emitBindingOrAssignment( + flattenContext.createObjectBindingOrAssignmentPattern(bindingElements), + value, + location, + pattern, + ); bindingElements = undefined; } const rhsValue = createDestructuringPropertyAccess(flattenContext, value, propertyName); if (isComputedPropertyName(propertyName)) { - computedTempVariables = append(computedTempVariables, (rhsValue as ElementAccessExpression).argumentExpression); + computedTempVariables = append( + computedTempVariables, + (rhsValue as ElementAccessExpression).argumentExpression, + ); } flattenBindingOrAssignmentElement(flattenContext, element, rhsValue, /*location*/ element); } } else if (i === numElements - 1) { if (bindingElements) { - flattenContext.emitBindingOrAssignment(flattenContext.createObjectBindingOrAssignmentPattern(bindingElements), value, location, pattern); + flattenContext.emitBindingOrAssignment( + flattenContext.createObjectBindingOrAssignmentPattern(bindingElements), + value, + location, + pattern, + ); bindingElements = undefined; } - const rhsValue = flattenContext.context.getEmitHelperFactory().createRestHelper(value, elements, computedTempVariables, pattern); + const rhsValue = flattenContext.context.getEmitHelperFactory().createRestHelper( + value, + elements, + computedTempVariables, + pattern, + ); flattenBindingOrAssignmentElement(flattenContext, element, rhsValue, element); } } if (bindingElements) { - flattenContext.emitBindingOrAssignment(flattenContext.createObjectBindingOrAssignmentPattern(bindingElements), value, location, pattern); + flattenContext.emitBindingOrAssignment( + flattenContext.createObjectBindingOrAssignmentPattern(bindingElements), + value, + location, + pattern, + ); } } @@ -442,7 +528,13 @@ function flattenObjectBindingOrAssignmentPattern(flattenContext: FlattenContext, * @param value The current RHS value to assign to the element. * @param location The location to use for source maps and comments. */ -function flattenArrayBindingOrAssignmentPattern(flattenContext: FlattenContext, parent: BindingOrAssignmentElement, pattern: ArrayBindingOrAssignmentPattern, value: Expression, location: TextRange) { +function flattenArrayBindingOrAssignmentPattern( + flattenContext: FlattenContext, + parent: BindingOrAssignmentElement, + pattern: ArrayBindingOrAssignmentPattern, + value: Expression, + location: TextRange, +) { const elements = getElementsOfBindingOrAssignmentPattern(pattern); const numElements = elements.length; if (flattenContext.level < FlattenLevel.ObjectRest && flattenContext.downlevelIteration) { @@ -482,14 +574,20 @@ function flattenArrayBindingOrAssignmentPattern(flattenContext: FlattenContext, if (flattenContext.level >= FlattenLevel.ObjectRest) { // If an array pattern contains an ObjectRest, we must cache the result so that we // can perform the ObjectRest destructuring in a different declaration - if (element.transformFlags & TransformFlags.ContainsObjectRestOrSpread || flattenContext.hasTransformedPriorElement && !isSimpleBindingOrAssignmentElement(element)) { + if ( + element.transformFlags & TransformFlags.ContainsObjectRestOrSpread + || flattenContext.hasTransformedPriorElement && !isSimpleBindingOrAssignmentElement(element) + ) { flattenContext.hasTransformedPriorElement = true; const temp = flattenContext.context.factory.createTempVariable(/*recordTempVariable*/ undefined); if (flattenContext.hoistTempVariables) { flattenContext.context.hoistVariableDeclaration(temp); } - restContainingElements = append(restContainingElements, [temp, element] as [Identifier, BindingOrAssignmentElement]); + restContainingElements = append( + restContainingElements, + [temp, element] as [Identifier, BindingOrAssignmentElement], + ); bindingElements = append(bindingElements, flattenContext.createArrayBindingOrAssignmentElement(temp)); } else { @@ -509,7 +607,12 @@ function flattenArrayBindingOrAssignmentPattern(flattenContext: FlattenContext, } } if (bindingElements) { - flattenContext.emitBindingOrAssignment(flattenContext.createArrayBindingOrAssignmentPattern(bindingElements), value, location, pattern); + flattenContext.emitBindingOrAssignment( + flattenContext.createArrayBindingOrAssignmentPattern(bindingElements), + value, + location, + pattern, + ); } if (restContainingElements) { for (const [id, element] of restContainingElements) { @@ -525,7 +628,9 @@ function isSimpleBindingOrAssignmentElement(element: BindingOrAssignmentElement) if (propertyName && !isPropertyNameLiteral(propertyName)) return false; const initializer = getInitializerOfBindingOrAssignmentElement(element); if (initializer && !isSimpleInlineableExpression(initializer)) return false; - if (isBindingOrAssignmentPattern(target)) return every(getElementsOfBindingOrAssignmentPattern(target), isSimpleBindingOrAssignmentElement); + if (isBindingOrAssignmentPattern(target)) { + return every(getElementsOfBindingOrAssignmentPattern(target), isSimpleBindingOrAssignmentElement); + } return isIdentifier(target); } @@ -537,9 +642,20 @@ function isSimpleBindingOrAssignmentElement(element: BindingOrAssignmentElement) * @param defaultValue The default value to use if `value` is `undefined` at runtime. * @param location The location to use for source maps and comments. */ -function createDefaultValueCheck(flattenContext: FlattenContext, value: Expression, defaultValue: Expression, location: TextRange): Expression { +function createDefaultValueCheck( + flattenContext: FlattenContext, + value: Expression, + defaultValue: Expression, + location: TextRange, +): Expression { value = ensureIdentifier(flattenContext, value, /*reuseIdentifierExpressions*/ true, location); - return flattenContext.context.factory.createConditionalExpression(flattenContext.context.factory.createTypeCheck(value, "undefined"), /*questionToken*/ undefined, defaultValue, /*colonToken*/ undefined, value); + return flattenContext.context.factory.createConditionalExpression( + flattenContext.context.factory.createTypeCheck(value, "undefined"), + /*questionToken*/ undefined, + defaultValue, + /*colonToken*/ undefined, + value, + ); } /** @@ -552,10 +668,19 @@ function createDefaultValueCheck(flattenContext: FlattenContext, value: Expressi * @param value The RHS value that is the source of the property. * @param propertyName The destructuring property name. */ -function createDestructuringPropertyAccess(flattenContext: FlattenContext, value: Expression, propertyName: PropertyName): LeftHandSideExpression { +function createDestructuringPropertyAccess( + flattenContext: FlattenContext, + value: Expression, + propertyName: PropertyName, +): LeftHandSideExpression { const { factory } = flattenContext.context; if (isComputedPropertyName(propertyName)) { - const argumentExpression = ensureIdentifier(flattenContext, Debug.checkDefined(visitNode(propertyName.expression, flattenContext.visitor, isExpression)), /*reuseIdentifierExpressions*/ false, /*location*/ propertyName); + const argumentExpression = ensureIdentifier( + flattenContext, + Debug.checkDefined(visitNode(propertyName.expression, flattenContext.visitor, isExpression)), + /*reuseIdentifierExpressions*/ false, + /*location*/ propertyName, + ); return flattenContext.context.factory.createElementAccessExpression(value, argumentExpression); } else if (isStringOrNumericLiteralLike(propertyName)) { @@ -579,7 +704,12 @@ function createDestructuringPropertyAccess(flattenContext: FlattenContext, value * false if it is necessary to always emit an identifier. * @param location The location to use for source maps and comments. */ -function ensureIdentifier(flattenContext: FlattenContext, value: Expression, reuseIdentifierExpressions: boolean, location: TextRange) { +function ensureIdentifier( + flattenContext: FlattenContext, + value: Expression, + reuseIdentifierExpressions: boolean, + location: TextRange, +) { if (isIdentifier(value) && reuseIdentifierExpressions) { return value; } @@ -587,7 +717,9 @@ function ensureIdentifier(flattenContext: FlattenContext, value: Expression, reu const temp = flattenContext.context.factory.createTempVariable(/*recordTempVariable*/ undefined); if (flattenContext.hoistTempVariables) { flattenContext.context.hoistVariableDeclaration(temp); - flattenContext.emitExpression(setTextRange(flattenContext.context.factory.createAssignment(temp, value), location)); + flattenContext.emitExpression( + setTextRange(flattenContext.context.factory.createAssignment(temp, value), location), + ); } else { flattenContext.emitBindingOrAssignment(temp, value, location, /*original*/ undefined); diff --git a/src/compiler/transformers/es2015.ts b/src/compiler/transformers/es2015.ts index 2b267c0908407..92fdc0fa93515 100644 --- a/src/compiler/transformers/es2015.ts +++ b/src/compiler/transformers/es2015.ts @@ -357,7 +357,12 @@ interface ConvertedLoopState { loopOutParameters: LoopOutParameter[]; } -type LoopConverter = (node: T, outermostLabeledStatement: LabeledStatement | undefined, convertedLoopBodyStatements: Statement[] | undefined, ancestorFacts: HierarchyFacts) => Statement; +type LoopConverter = ( + node: T, + outermostLabeledStatement: LabeledStatement | undefined, + convertedLoopBodyStatements: Statement[] | undefined, + ancestorFacts: HierarchyFacts, +) => Statement; // Facts we track as we traverse the tree const enum HierarchyFacts { @@ -395,7 +400,8 @@ const enum HierarchyFacts { // We are always in *some* kind of block scope, but only specific block-scope containers are // top-level or Blocks. BlockScopeIncludes = None, - BlockScopeExcludes = TopLevel | Block | IterationStatement | IterationStatementBlock | ForStatement | ForInOrForOfStatement, + BlockScopeExcludes = TopLevel | Block | IterationStatement | IterationStatementBlock | ForStatement + | ForInOrForOfStatement, // A source file is a top-level block scope. SourceFileIncludes = TopLevel, @@ -403,7 +409,8 @@ const enum HierarchyFacts { // Functions, methods, and accessors are both new lexical scopes and new block scopes. FunctionIncludes = Function | TopLevel, - FunctionExcludes = BlockScopeExcludes & ~TopLevel | ArrowFunction | AsyncFunctionBody | CapturesThis | NonStaticClassElement | ConstructorWithCapturedSuper | IterationContainer | StaticInitializer, + FunctionExcludes = BlockScopeExcludes & ~TopLevel | ArrowFunction | AsyncFunctionBody | CapturesThis + | NonStaticClassElement | ConstructorWithCapturedSuper | IterationContainer | StaticInitializer, AsyncFunctionBodyIncludes = FunctionIncludes | AsyncFunctionBody, AsyncFunctionBodyExcludes = FunctionExcludes & ~NonStaticClassElement, @@ -555,7 +562,8 @@ export function transformES2015(context: TransformationContext): (x: SourceFile * @param includeFacts The new `HierarchyFacts` of the subtree that should be propagated. */ function exitSubtree(ancestorFacts: HierarchyFacts, excludeFacts: HierarchyFacts, includeFacts: HierarchyFacts) { - hierarchyFacts = (hierarchyFacts & ~excludeFacts | includeFacts) & HierarchyFacts.SubtreeFactsMask | ancestorFacts; + hierarchyFacts = (hierarchyFacts & ~excludeFacts | includeFacts) & HierarchyFacts.SubtreeFactsMask + | ancestorFacts; } function isReturnVoidStatementInConstructorWithCapturedSuper(node: Node): boolean { @@ -670,7 +678,10 @@ export function transformES2015(context: TransformationContext): (x: SourceFile case SyntaxKind.DoStatement: case SyntaxKind.WhileStatement: - return visitDoOrWhileStatement(node as DoStatement | WhileStatement, /*outermostLabeledStatement*/ undefined); + return visitDoOrWhileStatement( + node as DoStatement | WhileStatement, + /*outermostLabeledStatement*/ undefined, + ); case SyntaxKind.ForStatement: return visitForStatement(node as ForStatement, /*outermostLabeledStatement*/ undefined); @@ -777,7 +788,10 @@ export function transformES2015(context: TransformationContext): (x: SourceFile addRange(statements, visitNodes(node.statements, visitor, isStatement, statementOffset)); if (taggedTemplateStringDeclarations) { statements.push( - factory.createVariableStatement(/*modifiers*/ undefined, factory.createVariableDeclarationList(taggedTemplateStringDeclarations)), + factory.createVariableStatement( + /*modifiers*/ undefined, + factory.createVariableDeclarationList(taggedTemplateStringDeclarations), + ), ); } factory.mergeLexicalEnvironment(prologue, endLexicalEnvironment()); @@ -809,7 +823,15 @@ export function transformES2015(context: TransformationContext): (x: SourceFile } function returnCapturedThis(node: Node): ReturnStatement { - return setOriginalNode(factory.createReturnStatement(factory.createUniqueName("_this", GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel)), node); + return setOriginalNode( + factory.createReturnStatement( + factory.createUniqueName( + "_this", + GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel, + ), + ), + node, + ); } function visitReturnStatement(node: ReturnStatement): Statement { @@ -859,7 +881,8 @@ export function transformES2015(context: TransformationContext): (x: SourceFile function visitIdentifier(node: Identifier): Identifier { if (convertedLoopState) { if (resolver.isArgumentsLocalBinding(node)) { - return convertedLoopState.argumentsName || (convertedLoopState.argumentsName = factory.createUniqueName("arguments")); + return convertedLoopState.argumentsName + || (convertedLoopState.argumentsName = factory.createUniqueName("arguments")); } } if (node.flags & NodeFlags.IdentifierHasExtendedUnicodeEscape) { @@ -881,8 +904,9 @@ export function transformES2015(context: TransformationContext): (x: SourceFile // - break/continue is labeled and label is located inside the converted loop // - break/continue is non-labeled and located in non-converted loop/switch statement const jump = node.kind === SyntaxKind.BreakStatement ? Jump.Break : Jump.Continue; - const canUseBreakOrContinue = (node.label && convertedLoopState.labels && convertedLoopState.labels.get(idText(node.label))) || - (!node.label && (convertedLoopState.allowedNonLabeledJumps! & jump)); + const canUseBreakOrContinue = + (node.label && convertedLoopState.labels && convertedLoopState.labels.get(idText(node.label))) + || (!node.label && (convertedLoopState.allowedNonLabeledJumps! & jump)); if (!canUseBreakOrContinue) { let labelMarker: string; @@ -955,7 +979,10 @@ export function transformES2015(context: TransformationContext): (x: SourceFile setOriginalNode(variable, node); const statements: Statement[] = []; - const statement = factory.createVariableStatement(/*modifiers*/ undefined, factory.createVariableDeclarationList([variable])); + const statement = factory.createVariableStatement( + /*modifiers*/ undefined, + factory.createVariableDeclarationList([variable]), + ); setOriginalNode(statement, node); setTextRange(statement, node); @@ -1033,7 +1060,15 @@ export function transformES2015(context: TransformationContext): (x: SourceFile /*asteriskToken*/ undefined, /*name*/ undefined, /*typeParameters*/ undefined, - extendsClauseElement ? [factory.createParameterDeclaration(/*modifiers*/ undefined, /*dotDotDotToken*/ undefined, factory.createUniqueName("_super", GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel))] : [], + extendsClauseElement + ? [factory.createParameterDeclaration( + /*modifiers*/ undefined, + /*dotDotDotToken*/ undefined, + factory.createUniqueName( + "_super", + GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel, + ), + )] : [], /*type*/ undefined, transformClassBody(node, extendsClauseElement), ); @@ -1072,17 +1107,24 @@ export function transformES2015(context: TransformationContext): (x: SourceFile * @param node A ClassExpression or ClassDeclaration node. * @param extendsClauseElement The expression for the class `extends` clause. */ - function transformClassBody(node: ClassExpression | ClassDeclaration, extendsClauseElement: ExpressionWithTypeArguments | undefined): Block { + function transformClassBody( + node: ClassExpression | ClassDeclaration, + extendsClauseElement: ExpressionWithTypeArguments | undefined, + ): Block { const statements: Statement[] = []; const name = factory.getInternalName(node); - const constructorLikeName = isIdentifierANonContextualKeyword(name) ? factory.getGeneratedNameForNode(name) : name; + const constructorLikeName = isIdentifierANonContextualKeyword(name) ? factory.getGeneratedNameForNode(name) + : name; startLexicalEnvironment(); addExtendsHelperIfNeeded(statements, node, extendsClauseElement); addConstructor(statements, node, constructorLikeName, extendsClauseElement); addClassMembers(statements, node); // Create a synthetic text range for the return statement. - const closingBraceLocation = createTokenRange(skipTrivia(currentText, node.members.end), SyntaxKind.CloseBraceToken); + const closingBraceLocation = createTokenRange( + skipTrivia(currentText, node.members.end), + SyntaxKind.CloseBraceToken, + ); // The following partially-emitted expression exists purely to align our sourcemap // emit with the original emitter. @@ -1097,7 +1139,10 @@ export function transformES2015(context: TransformationContext): (x: SourceFile insertStatementsAfterStandardPrologue(statements, endLexicalEnvironment()); - const block = factory.createBlock(setTextRange(factory.createNodeArray(statements), /*location*/ node.members), /*multiLine*/ true); + const block = factory.createBlock( + setTextRange(factory.createNodeArray(statements), /*location*/ node.members), + /*multiLine*/ true, + ); setEmitFlags(block, EmitFlags.NoComments); return block; } @@ -1109,7 +1154,11 @@ export function transformES2015(context: TransformationContext): (x: SourceFile * @param node The ClassExpression or ClassDeclaration node. * @param extendsClauseElement The expression for the class `extends` clause. */ - function addExtendsHelperIfNeeded(statements: Statement[], node: ClassExpression | ClassDeclaration, extendsClauseElement: ExpressionWithTypeArguments | undefined): void { + function addExtendsHelperIfNeeded( + statements: Statement[], + node: ClassExpression | ClassDeclaration, + extendsClauseElement: ExpressionWithTypeArguments | undefined, + ): void { if (extendsClauseElement) { statements.push( setTextRange( @@ -1129,7 +1178,12 @@ export function transformES2015(context: TransformationContext): (x: SourceFile * @param node The ClassExpression or ClassDeclaration node. * @param extendsClauseElement The expression for the class `extends` clause. */ - function addConstructor(statements: Statement[], node: ClassExpression | ClassDeclaration, name: Identifier, extendsClauseElement: ExpressionWithTypeArguments | undefined): void { + function addConstructor( + statements: Statement[], + node: ClassExpression | ClassDeclaration, + name: Identifier, + extendsClauseElement: ExpressionWithTypeArguments | undefined, + ): void { const savedConvertedLoopState = convertedLoopState; convertedLoopState = undefined; const ancestorFacts = enterSubtree(HierarchyFacts.ConstructorExcludes, HierarchyFacts.ConstructorIncludes); @@ -1162,13 +1216,20 @@ export function transformES2015(context: TransformationContext): (x: SourceFile * @param hasSynthesizedSuper A value indicating whether the constructor starts with a * synthesized `super` call. */ - function transformConstructorParameters(constructor: ConstructorDeclaration | undefined, hasSynthesizedSuper: boolean) { + function transformConstructorParameters( + constructor: ConstructorDeclaration | undefined, + hasSynthesizedSuper: boolean, + ) { // If the TypeScript transformer needed to synthesize a constructor for property // initializers, it would have also added a synthetic `...args` parameter and // `super` call. // If this is the case, we do not include the synthetic `...args` parameter and // will instead use the `arguments` object in ES5/3. - return visitParameterList(constructor && !hasSynthesizedSuper ? constructor.parameters : undefined, visitor, context) + return visitParameterList( + constructor && !hasSynthesizedSuper ? constructor.parameters : undefined, + visitor, + context, + ) || [] as ParameterDeclaration[]; } @@ -1216,7 +1277,9 @@ export function transformES2015(context: TransformationContext): (x: SourceFile let firstMaterialIndex = statementOffset; while (isFirstStatement && firstMaterialIndex < superStatementIndex) { const statement = constructor.body.statements[firstMaterialIndex]; - if (!isUninitializedVariableStatement(statement) && !isUsingDeclarationStateVariableStatement(statement)) break; + if ( + !isUninitializedVariableStatement(statement) && !isUsingDeclarationStateVariableStatement(statement) + ) break; firstMaterialIndex++; } @@ -1224,7 +1287,10 @@ export function transformES2015(context: TransformationContext): (x: SourceFile } // visit everything prior to the statement containing `super()`. - addRange(statementsOut, visitNodes(statementsIn, visitor, isStatement, statementOffset, leadingStatementsEnd - statementOffset)); + addRange( + statementsOut, + visitNodes(statementsIn, visitor, isStatement, statementOffset, leadingStatementsEnd - statementOffset), + ); const superStatement = superStatementIndex >= 0 ? statementsIn[superStatementIndex] : undefined; if (superStatement && isTryStatement(superStatement)) { @@ -1267,9 +1333,9 @@ export function transformES2015(context: TransformationContext): (x: SourceFile if (isDerivedClass || superCallExpression) { if ( - superCallExpression && - superStatementIndex === statementsIn.length - 1 && - !(constructor.body.transformFlags & TransformFlags.ContainsLexicalThis) + superCallExpression + && superStatementIndex === statementsIn.length - 1 + && !(constructor.body.transformFlags & TransformFlags.ContainsLexicalThis) ) { // If the subclass constructor does *not* contain `this` and *ends* with a `super()` call, we will use the // following representation: @@ -1366,7 +1432,8 @@ export function transformES2015(context: TransformationContext): (x: SourceFile } function isUninitializedVariableStatement(node: Statement) { - return isVariableStatement(node) && every(node.declarationList.declarations, decl => isIdentifier(decl.name) && !decl.initializer); + return isVariableStatement(node) + && every(node.declarationList.declarations, decl => isIdentifier(decl.name) && !decl.initializer); } function isUsingDeclarationStateVariableStatement(node: Statement) { @@ -1376,9 +1443,18 @@ export function transformES2015(context: TransformationContext): (x: SourceFile const initializer = varDecl.initializer; if (!isObjectLiteralExpression(initializer) || initializer.properties.length !== 3) return false; const [stackProp, errorProp, hasErrorProp] = initializer.properties; - if (!isPropertyAssignment(stackProp) || !isIdentifier(stackProp.name) || idText(stackProp.name) !== "stack" || !isArrayLiteralExpression(stackProp.initializer)) return false; - if (!isPropertyAssignment(errorProp) || !isIdentifier(errorProp.name) || idText(errorProp.name) !== "error" || !isVoidExpression(errorProp.initializer) || !isNumericLiteral(errorProp.initializer.expression)) return false; - if (!isPropertyAssignment(hasErrorProp) || !isIdentifier(hasErrorProp.name) || idText(hasErrorProp.name) !== "hasError" || hasErrorProp.initializer.kind !== SyntaxKind.FalseKeyword) return false; + if ( + !isPropertyAssignment(stackProp) || !isIdentifier(stackProp.name) || idText(stackProp.name) !== "stack" + || !isArrayLiteralExpression(stackProp.initializer) + ) return false; + if ( + !isPropertyAssignment(errorProp) || !isIdentifier(errorProp.name) || idText(errorProp.name) !== "error" + || !isVoidExpression(errorProp.initializer) || !isNumericLiteral(errorProp.initializer.expression) + ) return false; + if ( + !isPropertyAssignment(hasErrorProp) || !isIdentifier(hasErrorProp.name) + || idText(hasErrorProp.name) !== "hasError" || hasErrorProp.initializer.kind !== SyntaxKind.FalseKeyword + ) return false; return true; } @@ -1391,10 +1467,16 @@ export function transformES2015(context: TransformationContext): (x: SourceFile * @param hasSynthesizedSuper A value indicating whether the constructor starts with a * synthesized `super` call. */ - function transformConstructorBody(constructor: ConstructorDeclaration & { body: FunctionBody; } | undefined, node: ClassDeclaration | ClassExpression, extendsClauseElement: ExpressionWithTypeArguments | undefined, hasSynthesizedSuper: boolean) { + function transformConstructorBody( + constructor: ConstructorDeclaration & { body: FunctionBody; } | undefined, + node: ClassDeclaration | ClassExpression, + extendsClauseElement: ExpressionWithTypeArguments | undefined, + hasSynthesizedSuper: boolean, + ) { // determine whether the class is known syntactically to be a derived class (e.g. a // class that extends a value that is not syntactically known to be `null`). - const isDerivedClass = !!extendsClauseElement && skipOuterExpressions(extendsClauseElement.expression).kind !== SyntaxKind.NullKeyword; + const isDerivedClass = !!extendsClauseElement + && skipOuterExpressions(extendsClauseElement.expression).kind !== SyntaxKind.NullKeyword; // When the subclass does not have a constructor, we synthesize a *default* constructor using the following // representation: @@ -1420,7 +1502,11 @@ export function transformES2015(context: TransformationContext): (x: SourceFile // In derived classes, there may be code before the necessary super() call // We'll remove pre-super statements to be tacked on after the rest of the body - const standardPrologueEnd = factory.copyStandardPrologue(constructor.body.statements, prologue, /*statementOffset*/ 0); + const standardPrologueEnd = factory.copyStandardPrologue( + constructor.body.statements, + prologue, + /*statementOffset*/ 0, + ); const superStatementIndices = findSuperStatementIndexPath(constructor.body.statements, standardPrologueEnd); if (hasSynthesizedSuper || superStatementIndices.length > 0) { hierarchyFacts |= HierarchyFacts.ConstructorWithCapturedSuper; @@ -1446,7 +1532,14 @@ export function transformES2015(context: TransformationContext): (x: SourceFile factory.mergeLexicalEnvironment(prologue, endLexicalEnvironment()); if (mayReplaceThis && !isSufficientlyCoveredByReturnStatements(constructor.body)) { - statements.push(factory.createReturnStatement(factory.createUniqueName("_this", GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel))); + statements.push( + factory.createReturnStatement( + factory.createUniqueName( + "_this", + GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel, + ), + ), + ); } const body = factory.createBlock( @@ -1480,8 +1573,8 @@ export function transformES2015(context: TransformationContext): (x: SourceFile else if (statement.kind === SyntaxKind.IfStatement) { const ifStatement = statement as IfStatement; if (ifStatement.elseStatement) { - return isSufficientlyCoveredByReturnStatements(ifStatement.thenStatement) && - isSufficientlyCoveredByReturnStatements(ifStatement.elseStatement); + return isSufficientlyCoveredByReturnStatements(ifStatement.thenStatement) + && isSufficientlyCoveredByReturnStatements(ifStatement.elseStatement); } } // A block is covered if it has a last statement which is covered. @@ -1503,11 +1596,17 @@ export function transformES2015(context: TransformationContext): (x: SourceFile return factory.createLogicalOr( factory.createLogicalAnd( factory.createStrictInequality( - factory.createUniqueName("_super", GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel), + factory.createUniqueName( + "_super", + GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel, + ), factory.createNull(), ), factory.createFunctionApplyCall( - factory.createUniqueName("_super", GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel), + factory.createUniqueName( + "_super", + GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel, + ), createActualThis(), factory.createIdentifier("arguments"), ), @@ -1594,7 +1693,8 @@ export function transformES2015(context: TransformationContext): (x: SourceFile } if (isBindingPattern(name)) { - added = insertDefaultValueAssignmentForBindingPattern(statements, parameter, name, initializer) || added; + added = insertDefaultValueAssignmentForBindingPattern(statements, parameter, name, initializer) + || added; } else if (initializer) { insertDefaultValueAssignmentForInitializer(statements, parameter, name, initializer); @@ -1612,7 +1712,12 @@ export function transformES2015(context: TransformationContext): (x: SourceFile * @param name The name of the parameter. * @param initializer The initializer for the parameter. */ - function insertDefaultValueAssignmentForBindingPattern(statements: Statement[], parameter: ParameterDeclaration, name: BindingPattern, initializer: Expression | undefined): boolean { + function insertDefaultValueAssignmentForBindingPattern( + statements: Statement[], + parameter: ParameterDeclaration, + name: BindingPattern, + initializer: Expression | undefined, + ): boolean { // In cases where a binding pattern is simply '[]' or '{}', // we usually don't want to emit a var declaration; however, in the presence // of an initializer, we must emit that expression to preserve side effects. @@ -1663,7 +1768,12 @@ export function transformES2015(context: TransformationContext): (x: SourceFile * @param name The name of the parameter. * @param initializer The initializer for the parameter. */ - function insertDefaultValueAssignmentForInitializer(statements: Statement[], parameter: ParameterDeclaration, name: Identifier, initializer: Expression): void { + function insertDefaultValueAssignmentForInitializer( + statements: Statement[], + parameter: ParameterDeclaration, + name: Identifier, + initializer: Expression, + ): void { initializer = Debug.checkDefined(visitNode(initializer, visitor, isExpression)); const statement = factory.createIfStatement( factory.createTypeCheck(factory.cloneNode(name), "undefined"), @@ -1675,8 +1785,14 @@ export function transformES2015(context: TransformationContext): (x: SourceFile setTextRange( factory.createAssignment( // TODO(rbuckton): Does this need to be parented? - setEmitFlags(setParent(setTextRange(factory.cloneNode(name), name), name.parent), EmitFlags.NoSourceMap), - setEmitFlags(initializer, EmitFlags.NoSourceMap | getEmitFlags(initializer) | EmitFlags.NoComments), + setEmitFlags( + setParent(setTextRange(factory.cloneNode(name), name), name.parent), + EmitFlags.NoSourceMap, + ), + setEmitFlags( + initializer, + EmitFlags.NoSourceMap | getEmitFlags(initializer) | EmitFlags.NoComments, + ), ), parameter, ), @@ -1686,13 +1802,18 @@ export function transformES2015(context: TransformationContext): (x: SourceFile ]), parameter, ), - EmitFlags.SingleLine | EmitFlags.NoTrailingSourceMap | EmitFlags.NoTokenSourceMaps | EmitFlags.NoComments, + EmitFlags.SingleLine | EmitFlags.NoTrailingSourceMap | EmitFlags.NoTokenSourceMaps + | EmitFlags.NoComments, ), ); startOnNewLine(statement); setTextRange(statement, parameter); - setEmitFlags(statement, EmitFlags.NoTokenSourceMaps | EmitFlags.NoTrailingSourceMap | EmitFlags.CustomPrologue | EmitFlags.NoComments); + setEmitFlags( + statement, + EmitFlags.NoTokenSourceMaps | EmitFlags.NoTrailingSourceMap | EmitFlags.CustomPrologue + | EmitFlags.NoComments, + ); insertStatementAfterCustomPrologue(statements, statement); } @@ -1704,7 +1825,10 @@ export function transformES2015(context: TransformationContext): (x: SourceFile * part of a constructor declaration with a * synthesized call to `super` */ - function shouldAddRestParameter(node: ParameterDeclaration | undefined, inConstructorWithSynthesizedSuper: boolean): node is ParameterDeclaration { + function shouldAddRestParameter( + node: ParameterDeclaration | undefined, + inConstructorWithSynthesizedSuper: boolean, + ): node is ParameterDeclaration { return !!(node && node.dotDotDotToken && !inConstructorWithSynthesizedSuper); } @@ -1717,7 +1841,11 @@ export function transformES2015(context: TransformationContext): (x: SourceFile * part of a constructor declaration with a * synthesized call to `super` */ - function addRestParameterIfNeeded(statements: Statement[], node: FunctionLikeDeclaration, inConstructorWithSynthesizedSuper: boolean): boolean { + function addRestParameterIfNeeded( + statements: Statement[], + node: FunctionLikeDeclaration, + inConstructorWithSynthesizedSuper: boolean, + ): boolean { const prologueStatements: Statement[] = []; const parameter = lastOrUndefined(node.parameters); if (!shouldAddRestParameter(parameter, inConstructorWithSynthesizedSuper)) { @@ -1726,11 +1854,14 @@ export function transformES2015(context: TransformationContext): (x: SourceFile // `declarationName` is the name of the local declaration for the parameter. // TODO(rbuckton): Does this need to be parented? - const declarationName = parameter.name.kind === SyntaxKind.Identifier ? setParent(setTextRange(factory.cloneNode(parameter.name), parameter.name), parameter.name.parent) : factory.createTempVariable(/*recordTempVariable*/ undefined); + const declarationName = parameter.name.kind === SyntaxKind.Identifier + ? setParent(setTextRange(factory.cloneNode(parameter.name), parameter.name), parameter.name.parent) + : factory.createTempVariable(/*recordTempVariable*/ undefined); setEmitFlags(declarationName, EmitFlags.NoSourceMap); // `expressionName` is the name of the parameter used in expressions. - const expressionName = parameter.name.kind === SyntaxKind.Identifier ? factory.cloneNode(parameter.name) : declarationName; + const expressionName = parameter.name.kind === SyntaxKind.Identifier ? factory.cloneNode(parameter.name) + : declarationName; const restIndex = node.parameters.length - 1; const temp = factory.createLoopVariable(); @@ -1761,7 +1892,12 @@ export function transformES2015(context: TransformationContext): (x: SourceFile const forStatement = factory.createForStatement( setTextRange( factory.createVariableDeclarationList([ - factory.createVariableDeclaration(temp, /*exclamationToken*/ undefined, /*type*/ undefined, factory.createNumericLiteral(restIndex)), + factory.createVariableDeclaration( + temp, + /*exclamationToken*/ undefined, + /*type*/ undefined, + factory.createNumericLiteral(restIndex), + ), ]), parameter, ), @@ -1805,7 +1941,13 @@ export function transformES2015(context: TransformationContext): (x: SourceFile factory.createVariableStatement( /*modifiers*/ undefined, factory.createVariableDeclarationList( - flattenDestructuringBinding(parameter, visitor, context, FlattenLevel.All, expressionName), + flattenDestructuringBinding( + parameter, + visitor, + context, + FlattenLevel.All, + expressionName, + ), ), ), parameter, @@ -1859,7 +2001,10 @@ export function transformES2015(context: TransformationContext): (x: SourceFile /*modifiers*/ undefined, factory.createVariableDeclarationList([ factory.createVariableDeclaration( - factory.createUniqueName("_this", GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel), + factory.createUniqueName( + "_this", + GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel, + ), /*exclamationToken*/ undefined, /*type*/ undefined, initializer, @@ -1926,7 +2071,10 @@ export function transformES2015(context: TransformationContext): (x: SourceFile /*modifiers*/ undefined, factory.createVariableDeclarationList([ factory.createVariableDeclaration( - factory.createUniqueName("_newTarget", GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel), + factory.createUniqueName( + "_newTarget", + GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel, + ), /*exclamationToken*/ undefined, /*type*/ undefined, newTarget, @@ -1956,14 +2104,22 @@ export function transformES2015(context: TransformationContext): (x: SourceFile break; case SyntaxKind.MethodDeclaration: - statements.push(transformClassMethodDeclarationToStatement(getClassMemberPrefix(node, member), member as MethodDeclaration, node)); + statements.push( + transformClassMethodDeclarationToStatement( + getClassMemberPrefix(node, member), + member as MethodDeclaration, + node, + ), + ); break; case SyntaxKind.GetAccessor: case SyntaxKind.SetAccessor: const accessors = getAllAccessorDeclarations(node.members, member as AccessorDeclaration); if (member === accessors.firstAccessor) { - statements.push(transformAccessorsToStatement(getClassMemberPrefix(node, member), accessors, node)); + statements.push( + transformAccessorsToStatement(getClassMemberPrefix(node, member), accessors, node), + ); } break; @@ -1995,21 +2151,45 @@ export function transformES2015(context: TransformationContext): (x: SourceFile * @param receiver The receiver for the member. * @param member The MethodDeclaration node. */ - function transformClassMethodDeclarationToStatement(receiver: LeftHandSideExpression, member: MethodDeclaration, container: Node) { + function transformClassMethodDeclarationToStatement( + receiver: LeftHandSideExpression, + member: MethodDeclaration, + container: Node, + ) { const commentRange = getCommentRange(member); const sourceMapRange = getSourceMapRange(member); - const memberFunction = transformFunctionLikeToExpression(member, /*location*/ member, /*name*/ undefined, container); + const memberFunction = transformFunctionLikeToExpression( + member, + /*location*/ member, + /*name*/ undefined, + container, + ); const propertyName = visitNode(member.name, visitor, isPropertyName); Debug.assert(propertyName); let e: Expression; if (!isPrivateIdentifier(propertyName) && getUseDefineForClassFields(context.getCompilerOptions())) { const name = isComputedPropertyName(propertyName) ? propertyName.expression - : isIdentifier(propertyName) ? factory.createStringLiteral(unescapeLeadingUnderscores(propertyName.escapedText)) + : isIdentifier(propertyName) + ? factory.createStringLiteral(unescapeLeadingUnderscores(propertyName.escapedText)) : propertyName; - e = factory.createObjectDefinePropertyCall(receiver, name, factory.createPropertyDescriptor({ value: memberFunction, enumerable: false, writable: true, configurable: true })); + e = factory.createObjectDefinePropertyCall( + receiver, + name, + factory.createPropertyDescriptor({ + value: memberFunction, + enumerable: false, + writable: true, + configurable: true, + }), + ); } else { - const memberName = createMemberAccessForPropertyName(factory, receiver, propertyName, /*location*/ member.name); + const memberName = createMemberAccessForPropertyName( + factory, + receiver, + propertyName, + /*location*/ member.name, + ); e = factory.createAssignment(memberName, memberFunction); } setEmitFlags(memberFunction, EmitFlags.NoComments); @@ -2032,8 +2212,14 @@ export function transformES2015(context: TransformationContext): (x: SourceFile * @param receiver The receiver for the member. * @param accessors The set of related get/set accessors. */ - function transformAccessorsToStatement(receiver: LeftHandSideExpression, accessors: AllAccessorDeclarations, container: Node): Statement { - const statement = factory.createExpressionStatement(transformAccessorsToExpression(receiver, accessors, container, /*startsOnNewLine*/ false)); + function transformAccessorsToStatement( + receiver: LeftHandSideExpression, + accessors: AllAccessorDeclarations, + container: Node, + ): Statement { + const statement = factory.createExpressionStatement( + transformAccessorsToExpression(receiver, accessors, container, /*startsOnNewLine*/ false), + ); // The location for the statement is used to emit source maps only. // No comments should be emitted for this statement to align with the // old emitter. @@ -2048,7 +2234,12 @@ export function transformES2015(context: TransformationContext): (x: SourceFile * * @param receiver The receiver for the member. */ - function transformAccessorsToExpression(receiver: LeftHandSideExpression, { firstAccessor, getAccessor, setAccessor }: AllAccessorDeclarations, container: Node, startsOnNewLine: boolean): Expression { + function transformAccessorsToExpression( + receiver: LeftHandSideExpression, + { firstAccessor, getAccessor, setAccessor }: AllAccessorDeclarations, + container: Node, + startsOnNewLine: boolean, + ): Expression { // To align with source maps in the old emitter, the receiver and property name // arguments are both mapped contiguously to the accessor name. // TODO(rbuckton): Does this need to be parented? @@ -2059,7 +2250,10 @@ export function transformES2015(context: TransformationContext): (x: SourceFile const visitedAccessorName = visitNode(firstAccessor.name, visitor, isPropertyName); Debug.assert(visitedAccessorName); if (isPrivateIdentifier(visitedAccessorName)) { - return Debug.failBadSyntaxKind(visitedAccessorName, "Encountered unhandled private identifier while transforming ES2015."); + return Debug.failBadSyntaxKind( + visitedAccessorName, + "Encountered unhandled private identifier while transforming ES2015.", + ); } const propertyName = createExpressionForPropertyName(factory, visitedAccessorName); setEmitFlags(propertyName, EmitFlags.NoComments | EmitFlags.NoLeadingSourceMap); @@ -2067,7 +2261,12 @@ export function transformES2015(context: TransformationContext): (x: SourceFile const properties: ObjectLiteralElementLike[] = []; if (getAccessor) { - const getterFunction = transformFunctionLikeToExpression(getAccessor, /*location*/ undefined, /*name*/ undefined, container); + const getterFunction = transformFunctionLikeToExpression( + getAccessor, + /*location*/ undefined, + /*name*/ undefined, + container, + ); setSourceMapRange(getterFunction, getSourceMapRange(getAccessor)); setEmitFlags(getterFunction, EmitFlags.NoLeadingComments); const getter = factory.createPropertyAssignment("get", getterFunction); @@ -2076,7 +2275,12 @@ export function transformES2015(context: TransformationContext): (x: SourceFile } if (setAccessor) { - const setterFunction = transformFunctionLikeToExpression(setAccessor, /*location*/ undefined, /*name*/ undefined, container); + const setterFunction = transformFunctionLikeToExpression( + setAccessor, + /*location*/ undefined, + /*name*/ undefined, + container, + ); setSourceMapRange(setterFunction, getSourceMapRange(setAccessor)); setEmitFlags(setterFunction, EmitFlags.NoLeadingComments); const setter = factory.createPropertyAssignment("set", setterFunction); @@ -2085,7 +2289,10 @@ export function transformES2015(context: TransformationContext): (x: SourceFile } properties.push( - factory.createPropertyAssignment("enumerable", getAccessor || setAccessor ? factory.createFalse() : factory.createTrue()), + factory.createPropertyAssignment( + "enumerable", + getAccessor || setAccessor ? factory.createFalse() : factory.createTrue(), + ), factory.createPropertyAssignment("configurable", factory.createTrue()), ); @@ -2111,7 +2318,10 @@ export function transformES2015(context: TransformationContext): (x: SourceFile * @param node An ArrowFunction node. */ function visitArrowFunction(node: ArrowFunction) { - if (node.transformFlags & TransformFlags.ContainsLexicalThis && !(hierarchyFacts & HierarchyFacts.StaticInitializer)) { + if ( + node.transformFlags & TransformFlags.ContainsLexicalThis + && !(hierarchyFacts & HierarchyFacts.StaticInitializer) + ) { hierarchyFacts |= HierarchyFacts.CapturedLexicalThis; } @@ -2206,15 +2416,26 @@ export function transformES2015(context: TransformationContext): (x: SourceFile * @param location The source-map location for the new FunctionExpression. * @param name The name of the new FunctionExpression. */ - function transformFunctionLikeToExpression(node: FunctionLikeDeclaration, location: TextRange | undefined, name: Identifier | undefined, container: Node | undefined): FunctionExpression { + function transformFunctionLikeToExpression( + node: FunctionLikeDeclaration, + location: TextRange | undefined, + name: Identifier | undefined, + container: Node | undefined, + ): FunctionExpression { const savedConvertedLoopState = convertedLoopState; convertedLoopState = undefined; const ancestorFacts = container && isClassLike(container) && !isStatic(node) - ? enterSubtree(HierarchyFacts.FunctionExcludes, HierarchyFacts.FunctionIncludes | HierarchyFacts.NonStaticClassElement) + ? enterSubtree( + HierarchyFacts.FunctionExcludes, + HierarchyFacts.FunctionIncludes | HierarchyFacts.NonStaticClassElement, + ) : enterSubtree(HierarchyFacts.FunctionExcludes, HierarchyFacts.FunctionIncludes); const parameters = visitParameterList(node.parameters, visitor, context); const body = transformFunctionBody(node); - if (hierarchyFacts & HierarchyFacts.NewTarget && !name && (node.kind === SyntaxKind.FunctionDeclaration || node.kind === SyntaxKind.FunctionExpression)) { + if ( + hierarchyFacts & HierarchyFacts.NewTarget && !name + && (node.kind === SyntaxKind.FunctionDeclaration || node.kind === SyntaxKind.FunctionExpression) + ) { name = factory.getGeneratedNameForNode(node); } @@ -2258,12 +2479,25 @@ export function transformES2015(context: TransformationContext): (x: SourceFile // ensureUseStrict is false because no new prologue-directive should be added. // addStandardPrologue will put already-existing directives at the beginning of the target statement-array statementOffset = factory.copyStandardPrologue(body.statements, prologue, 0, /*ensureUseStrict*/ false); - statementOffset = factory.copyCustomPrologue(body.statements, statements, statementOffset, visitor, isHoistedFunction); - statementOffset = factory.copyCustomPrologue(body.statements, statements, statementOffset, visitor, isHoistedVariableStatement); + statementOffset = factory.copyCustomPrologue( + body.statements, + statements, + statementOffset, + visitor, + isHoistedFunction, + ); + statementOffset = factory.copyCustomPrologue( + body.statements, + statements, + statementOffset, + visitor, + isHoistedVariableStatement, + ); } multiLine = addDefaultValueAssignmentsIfNeeded(statements, node) || multiLine; - multiLine = addRestParameterIfNeeded(statements, node, /*inConstructorWithSynthesizedSuper*/ false) || multiLine; + multiLine = addRestParameterIfNeeded(statements, node, /*inConstructorWithSynthesizedSuper*/ false) + || multiLine; if (isBlock(body)) { // addCustomPrologue puts already-existing directives at the beginning of the target statement-array @@ -2300,7 +2534,10 @@ export function transformES2015(context: TransformationContext): (x: SourceFile const returnStatement = factory.createReturnStatement(expression); setTextRange(returnStatement, body); moveSyntheticComments(returnStatement, body); - setEmitFlags(returnStatement, EmitFlags.NoTokenSourceMaps | EmitFlags.NoTrailingSourceMap | EmitFlags.NoTrailingComments); + setEmitFlags( + returnStatement, + EmitFlags.NoTokenSourceMaps | EmitFlags.NoTrailingSourceMap | EmitFlags.NoTrailingComments, + ); statements.push(returnStatement); // To align with the source map emit for the old emitter, we set a custom @@ -2323,7 +2560,10 @@ export function transformES2015(context: TransformationContext): (x: SourceFile return body; } - const block = factory.createBlock(setTextRange(factory.createNodeArray(statements), statementsLocation), multiLine); + const block = factory.createBlock( + setTextRange(factory.createNodeArray(statements), statementsLocation), + multiLine, + ); setTextRange(block, node.body); if (!multiLine && singleLine) { setEmitFlags(block, EmitFlags.SingleLine); @@ -2343,7 +2583,10 @@ export function transformES2015(context: TransformationContext): (x: SourceFile return visitEachChild(node, visitor, context); } const ancestorFacts = hierarchyFacts & HierarchyFacts.IterationStatement - ? enterSubtree(HierarchyFacts.IterationStatementBlockExcludes, HierarchyFacts.IterationStatementBlockIncludes) + ? enterSubtree( + HierarchyFacts.IterationStatementBlockExcludes, + HierarchyFacts.IterationStatementBlockIncludes, + ) : enterSubtree(HierarchyFacts.BlockExcludes, HierarchyFacts.BlockIncludes); const updated = visitEachChild(node, visitor, context); exitSubtree(ancestorFacts, HierarchyFacts.None, HierarchyFacts.None); @@ -2366,7 +2609,10 @@ export function transformES2015(context: TransformationContext): (x: SourceFile * @param expressionResultIsUnused Indicates the result of an expression is unused by the parent node (i.e., the left side of a comma or the * expression of an `ExpressionStatement`). */ - function visitParenthesizedExpression(node: ParenthesizedExpression, expressionResultIsUnused: boolean): ParenthesizedExpression { + function visitParenthesizedExpression( + node: ParenthesizedExpression, + expressionResultIsUnused: boolean, + ): ParenthesizedExpression { return visitEachChild(node, expressionResultIsUnused ? visitorWithUnusedExpressionResult : visitor, context); } @@ -2393,7 +2639,13 @@ export function transformES2015(context: TransformationContext): (x: SourceFile node, Debug.checkDefined(visitNode(node.left, visitorWithUnusedExpressionResult, isExpression)), node.operatorToken, - Debug.checkDefined(visitNode(node.right, expressionResultIsUnused ? visitorWithUnusedExpressionResult : visitor, isExpression)), + Debug.checkDefined( + visitNode( + node.right, + expressionResultIsUnused ? visitorWithUnusedExpressionResult : visitor, + isExpression, + ), + ), ); } return visitEachChild(node, visitor, context); @@ -2410,7 +2662,11 @@ export function transformES2015(context: TransformationContext): (x: SourceFile let result: Expression[] | undefined; for (let i = 0; i < node.elements.length; i++) { const element = node.elements[i]; - const visited = visitNode(element, i < node.elements.length - 1 ? visitorWithUnusedExpressionResult : visitor, isExpression); + const visited = visitNode( + element, + i < node.elements.length - 1 ? visitorWithUnusedExpressionResult : visitor, + isExpression, + ); if (result || visited !== element) { result ||= node.elements.slice(0, i); Debug.assert(visited); @@ -2424,13 +2680,21 @@ export function transformES2015(context: TransformationContext): (x: SourceFile function isVariableStatementOfTypeScriptClassWrapper(node: VariableStatement) { return node.declarationList.declarations.length === 1 && !!node.declarationList.declarations[0].initializer - && !!(getInternalEmitFlags(node.declarationList.declarations[0].initializer) & InternalEmitFlags.TypeScriptClassWrapper); + && !!(getInternalEmitFlags(node.declarationList.declarations[0].initializer) + & InternalEmitFlags.TypeScriptClassWrapper); } function visitVariableStatement(node: VariableStatement): Statement | undefined { - const ancestorFacts = enterSubtree(HierarchyFacts.None, hasSyntacticModifier(node, ModifierFlags.Export) ? HierarchyFacts.ExportedVariableStatement : HierarchyFacts.None); + const ancestorFacts = enterSubtree( + HierarchyFacts.None, + hasSyntacticModifier(node, ModifierFlags.Export) ? HierarchyFacts.ExportedVariableStatement + : HierarchyFacts.None, + ); let updated: Statement | undefined; - if (convertedLoopState && (node.declarationList.flags & NodeFlags.BlockScoped) === 0 && !isVariableStatementOfTypeScriptClassWrapper(node)) { + if ( + convertedLoopState && (node.declarationList.flags & NodeFlags.BlockScoped) === 0 + && !isVariableStatementOfTypeScriptClassWrapper(node) + ) { // we are inside a converted loop - hoist variable declarations let assignments: Expression[] | undefined; for (const decl of node.declarationList.declarations) { @@ -2446,7 +2710,11 @@ export function transformES2015(context: TransformationContext): (x: SourceFile ); } else { - assignment = factory.createBinaryExpression(decl.name, SyntaxKind.EqualsToken, Debug.checkDefined(visitNode(decl.initializer, visitor, isExpression))); + assignment = factory.createBinaryExpression( + decl.name, + SyntaxKind.EqualsToken, + Debug.checkDefined(visitNode(decl.initializer, visitor, isExpression)), + ); setTextRange(assignment, decl); } @@ -2598,7 +2866,13 @@ export function transformES2015(context: TransformationContext): (x: SourceFile } if (!node.initializer && shouldEmitExplicitInitializerForLetDeclaration(node)) { - return factory.updateVariableDeclaration(node, node.name, /*exclamationToken*/ undefined, /*type*/ undefined, factory.createVoidZero()); + return factory.updateVariableDeclaration( + node, + node.name, + /*exclamationToken*/ undefined, + /*type*/ undefined, + factory.createVoidZero(), + ); } return visitEachChild(node, visitor, context); @@ -2645,7 +2919,11 @@ export function transformES2015(context: TransformationContext): (x: SourceFile const statement = unwrapInnermostStatementOfLabel(node, convertedLoopState && recordLabel); return isIterationStatement(statement, /*lookInLabeledStatements*/ false) ? visitIterationStatement(statement, /*outermostLabeledStatement*/ node) - : factory.restoreEnclosingLabel(Debug.checkDefined(visitNode(statement, visitor, isStatement, factory.liftToBlock)), node, convertedLoopState && resetLabel); + : factory.restoreEnclosingLabel( + Debug.checkDefined(visitNode(statement, visitor, isStatement, factory.liftToBlock)), + node, + convertedLoopState && resetLabel, + ); } function visitIterationStatement(node: IterationStatement, outermostLabeledStatement: LabeledStatement) { @@ -2662,14 +2940,28 @@ export function transformES2015(context: TransformationContext): (x: SourceFile } } - function visitIterationStatementWithFacts(excludeFacts: HierarchyFacts, includeFacts: HierarchyFacts, node: T, outermostLabeledStatement: LabeledStatement | undefined, convert?: LoopConverter) { + function visitIterationStatementWithFacts( + excludeFacts: HierarchyFacts, + includeFacts: HierarchyFacts, + node: T, + outermostLabeledStatement: LabeledStatement | undefined, + convert?: LoopConverter, + ) { const ancestorFacts = enterSubtree(excludeFacts, includeFacts); - const updated = convertIterationStatementBodyIfNecessary(node, outermostLabeledStatement, ancestorFacts, convert); + const updated = convertIterationStatementBodyIfNecessary( + node, + outermostLabeledStatement, + ancestorFacts, + convert, + ); exitSubtree(ancestorFacts, HierarchyFacts.None, HierarchyFacts.None); return updated; } - function visitDoOrWhileStatement(node: DoStatement | WhileStatement, outermostLabeledStatement: LabeledStatement | undefined) { + function visitDoOrWhileStatement( + node: DoStatement | WhileStatement, + outermostLabeledStatement: LabeledStatement | undefined, + ) { return visitIterationStatementWithFacts( HierarchyFacts.DoOrWhileStatementExcludes, HierarchyFacts.DoOrWhileStatementIncludes, @@ -2706,7 +2998,10 @@ export function transformES2015(context: TransformationContext): (x: SourceFile ); } - function visitForOfStatement(node: ForOfStatement, outermostLabeledStatement: LabeledStatement | undefined): VisitResult { + function visitForOfStatement( + node: ForOfStatement, + outermostLabeledStatement: LabeledStatement | undefined, + ): VisitResult { return visitIterationStatementWithFacts( HierarchyFacts.ForInOrForOfStatementExcludes, HierarchyFacts.ForInOrForOfStatementIncludes, @@ -2716,7 +3011,11 @@ export function transformES2015(context: TransformationContext): (x: SourceFile ); } - function convertForOfStatementHead(node: ForOfStatement, boundValue: Expression, convertedLoopBodyStatements: Statement[] | undefined) { + function convertForOfStatementHead( + node: ForOfStatement, + boundValue: Expression, + convertedLoopBodyStatements: Statement[] | undefined, + ) { const statements: Statement[] = []; const initializer = node.initializer; if (isVariableDeclarationList(initializer)) { @@ -2736,7 +3035,10 @@ export function transformES2015(context: TransformationContext): (x: SourceFile boundValue, ); - const declarationList = setTextRange(factory.createVariableDeclarationList(declarations), node.initializer); + const declarationList = setTextRange( + factory.createVariableDeclarationList(declarations), + node.initializer, + ); setOriginalNode(declarationList, node.initializer); // Adjust the source map range for the first declaration to align with the old @@ -2761,7 +3063,8 @@ export function transformES2015(context: TransformationContext): (x: SourceFile setTextRange( factory.createVariableDeclarationList([ factory.createVariableDeclaration( - firstOriginalDeclaration ? firstOriginalDeclaration.name : factory.createTempVariable(/*recordTempVariable*/ undefined), + firstOriginalDeclaration ? firstOriginalDeclaration.name + : factory.createTempVariable(/*recordTempVariable*/ undefined), /*exclamationToken*/ undefined, /*type*/ undefined, boundValue, @@ -2782,11 +3085,22 @@ export function transformES2015(context: TransformationContext): (x: SourceFile // evaluated on every iteration. const assignment = factory.createAssignment(initializer, boundValue); if (isDestructuringAssignment(assignment)) { - statements.push(factory.createExpressionStatement(visitBinaryExpression(assignment, /*expressionResultIsUnused*/ true))); + statements.push( + factory.createExpressionStatement( + visitBinaryExpression(assignment, /*expressionResultIsUnused*/ true), + ), + ); } else { setTextRangeEnd(assignment, initializer.end); - statements.push(setTextRange(factory.createExpressionStatement(Debug.checkDefined(visitNode(assignment, visitor, isExpression))), moveRangeEnd(initializer, -1))); + statements.push( + setTextRange( + factory.createExpressionStatement( + Debug.checkDefined(visitNode(assignment, visitor, isExpression)), + ), + moveRangeEnd(initializer, -1), + ), + ); } } @@ -2797,7 +3111,13 @@ export function transformES2015(context: TransformationContext): (x: SourceFile const statement = visitNode(node.statement, visitor, isStatement, factory.liftToBlock); Debug.assert(statement); if (isBlock(statement)) { - return factory.updateBlock(statement, setTextRange(factory.createNodeArray(concatenate(statements, statement.statements)), statement.statements)); + return factory.updateBlock( + statement, + setTextRange( + factory.createNodeArray(concatenate(statements, statement.statements)), + statement.statements, + ), + ); } else { statements.push(statement); @@ -2816,7 +3136,11 @@ export function transformES2015(context: TransformationContext): (x: SourceFile ); } - function convertForOfStatementForArray(node: ForOfStatement, outermostLabeledStatement: LabeledStatement | undefined, convertedLoopBodyStatements: Statement[] | undefined): Statement { + function convertForOfStatementForArray( + node: ForOfStatement, + outermostLabeledStatement: LabeledStatement | undefined, + convertedLoopBodyStatements: Statement[] | undefined, + ): Statement { // The following ES6 code: // // for (let v of expr) { } @@ -2847,7 +3171,8 @@ export function transformES2015(context: TransformationContext): (x: SourceFile // // we don't want to emit a temporary variable for the RHS, just use it directly. const counter = factory.createLoopVariable(); - const rhsReference = isIdentifier(expression) ? factory.getGeneratedNameForNode(expression) : factory.createTempVariable(/*recordTempVariable*/ undefined); + const rhsReference = isIdentifier(expression) ? factory.getGeneratedNameForNode(expression) + : factory.createTempVariable(/*recordTempVariable*/ undefined); // The old emitter does not emit source maps for the expression setEmitFlags(expression, EmitFlags.NoSourceMap | getEmitFlags(expression)); @@ -2857,8 +3182,24 @@ export function transformES2015(context: TransformationContext): (x: SourceFile /*initializer*/ setEmitFlags( setTextRange( factory.createVariableDeclarationList([ - setTextRange(factory.createVariableDeclaration(counter, /*exclamationToken*/ undefined, /*type*/ undefined, factory.createNumericLiteral(0)), moveRangePos(node.expression, -1)), - setTextRange(factory.createVariableDeclaration(rhsReference, /*exclamationToken*/ undefined, /*type*/ undefined, expression), node.expression), + setTextRange( + factory.createVariableDeclaration( + counter, + /*exclamationToken*/ undefined, + /*type*/ undefined, + factory.createNumericLiteral(0), + ), + moveRangePos(node.expression, -1), + ), + setTextRange( + factory.createVariableDeclaration( + rhsReference, + /*exclamationToken*/ undefined, + /*type*/ undefined, + expression, + ), + node.expression, + ), ]), node.expression, ), @@ -2887,16 +3228,27 @@ export function transformES2015(context: TransformationContext): (x: SourceFile return factory.restoreEnclosingLabel(forStatement, outermostLabeledStatement, convertedLoopState && resetLabel); } - function convertForOfStatementForIterable(node: ForOfStatement, outermostLabeledStatement: LabeledStatement | undefined, convertedLoopBodyStatements: Statement[] | undefined, ancestorFacts: HierarchyFacts): Statement { + function convertForOfStatementForIterable( + node: ForOfStatement, + outermostLabeledStatement: LabeledStatement | undefined, + convertedLoopBodyStatements: Statement[] | undefined, + ancestorFacts: HierarchyFacts, + ): Statement { const expression = visitNode(node.expression, visitor, isExpression); Debug.assert(expression); - const iterator = isIdentifier(expression) ? factory.getGeneratedNameForNode(expression) : factory.createTempVariable(/*recordTempVariable*/ undefined); - const result = isIdentifier(expression) ? factory.getGeneratedNameForNode(iterator) : factory.createTempVariable(/*recordTempVariable*/ undefined); + const iterator = isIdentifier(expression) ? factory.getGeneratedNameForNode(expression) + : factory.createTempVariable(/*recordTempVariable*/ undefined); + const result = isIdentifier(expression) ? factory.getGeneratedNameForNode(iterator) + : factory.createTempVariable(/*recordTempVariable*/ undefined); const errorRecord = factory.createUniqueName("e"); const catchVariable = factory.getGeneratedNameForNode(errorRecord); const returnMethod = factory.createTempVariable(/*recordTempVariable*/ undefined); const values = setTextRange(emitHelpers().createValuesHelper(expression), node.expression); - const next = factory.createCallExpression(factory.createPropertyAccessExpression(iterator, "next"), /*typeArguments*/ undefined, []); + const next = factory.createCallExpression( + factory.createPropertyAccessExpression(iterator, "next"), + /*typeArguments*/ undefined, + [], + ); hoistVariableDeclaration(errorRecord); hoistVariableDeclaration(returnMethod); @@ -2912,8 +3264,21 @@ export function transformES2015(context: TransformationContext): (x: SourceFile /*initializer*/ setEmitFlags( setTextRange( factory.createVariableDeclarationList([ - setTextRange(factory.createVariableDeclaration(iterator, /*exclamationToken*/ undefined, /*type*/ undefined, initializer), node.expression), - factory.createVariableDeclaration(result, /*exclamationToken*/ undefined, /*type*/ undefined, next), + setTextRange( + factory.createVariableDeclaration( + iterator, + /*exclamationToken*/ undefined, + /*type*/ undefined, + initializer, + ), + node.expression, + ), + factory.createVariableDeclaration( + result, + /*exclamationToken*/ undefined, + /*type*/ undefined, + next, + ), ]), node.expression, ), @@ -3014,8 +3379,8 @@ export function transformES2015(context: TransformationContext): (x: SourceFile for (let i = 0; i < properties.length; i++) { const property = properties[i]; if ( - (property.transformFlags & TransformFlags.ContainsYield && - hierarchyFacts & HierarchyFacts.AsyncFunctionBody) + (property.transformFlags & TransformFlags.ContainsYield + && hierarchyFacts & HierarchyFacts.AsyncFunctionBody) || (hasComputed = Debug.checkDefined(property.name).kind === SyntaxKind.ComputedPropertyName) ) { numInitialProperties = i; @@ -3054,7 +3419,9 @@ export function transformES2015(context: TransformationContext): (x: SourceFile // We need to clone the temporary identifier so that we can write it on a // new line - expressions.push(node.multiLine ? startOnNewLine(setParent(setTextRange(factory.cloneNode(temp), temp), temp.parent)) : temp); + expressions.push( + node.multiLine ? startOnNewLine(setParent(setTextRange(factory.cloneNode(temp), temp), temp.parent)) : temp, + ); return factory.inlineExpressions(expressions); } @@ -3074,15 +3441,21 @@ export function transformES2015(context: TransformationContext): (x: SourceFile return (resolver.getNodeCheckFlags(node) & NodeCheckFlags.ContainsCapturedBlockScopeBinding) !== 0; } - function shouldConvertInitializerOfForStatement(node: IterationStatement): node is ForStatementWithConvertibleInitializer { + function shouldConvertInitializerOfForStatement( + node: IterationStatement, + ): node is ForStatementWithConvertibleInitializer { return isForStatement(node) && !!node.initializer && shouldConvertPartOfIterationStatement(node.initializer); } - function shouldConvertConditionOfForStatement(node: IterationStatement): node is ForStatementWithConvertibleCondition { + function shouldConvertConditionOfForStatement( + node: IterationStatement, + ): node is ForStatementWithConvertibleCondition { return isForStatement(node) && !!node.condition && shouldConvertPartOfIterationStatement(node.condition); } - function shouldConvertIncrementorOfForStatement(node: IterationStatement): node is ForStatementWithConvertibleIncrementor { + function shouldConvertIncrementorOfForStatement( + node: IterationStatement, + ): node is ForStatementWithConvertibleIncrementor { return isForStatement(node) && !!node.incrementor && shouldConvertPartOfIterationStatement(node.incrementor); } @@ -3098,7 +3471,10 @@ export function transformES2015(context: TransformationContext): (x: SourceFile /** * Records constituents of name for the given variable to be hoisted in the outer scope. */ - function hoistVariableDeclarationDeclaredInConvertedLoop(state: ConvertedLoopState, node: VariableDeclaration): void { + function hoistVariableDeclarationDeclaredInConvertedLoop( + state: ConvertedLoopState, + node: VariableDeclaration, + ): void { if (!state.hoistedLocalVariables) { state.hoistedLocalVariables = []; } @@ -3119,7 +3495,12 @@ export function transformES2015(context: TransformationContext): (x: SourceFile } } - function convertIterationStatementBodyIfNecessary(node: T, outermostLabeledStatement: LabeledStatement | undefined, ancestorFacts: HierarchyFacts, convert?: LoopConverter): VisitResult { + function convertIterationStatementBodyIfNecessary( + node: T, + outermostLabeledStatement: LabeledStatement | undefined, + ancestorFacts: HierarchyFacts, + convert?: LoopConverter, + ): VisitResult { if (!shouldConvertIterationStatement(node)) { let saveAllowedNonLabeledJumps: Jump | undefined; if (convertedLoopState) { @@ -3149,8 +3530,10 @@ export function transformES2015(context: TransformationContext): (x: SourceFile const outerConvertedLoopState = convertedLoopState; convertedLoopState = currentState; - const initializerFunction = shouldConvertInitializerOfForStatement(node) ? createFunctionForInitializerOfForStatement(node, currentState) : undefined; - const bodyFunction = shouldConvertBodyOfIterationStatement(node) ? createFunctionForBodyOfIterationStatement(node, currentState, outerConvertedLoopState) : undefined; + const initializerFunction = shouldConvertInitializerOfForStatement(node) + ? createFunctionForInitializerOfForStatement(node, currentState) : undefined; + const bodyFunction = shouldConvertBodyOfIterationStatement(node) + ? createFunctionForBodyOfIterationStatement(node, currentState, outerConvertedLoopState) : undefined; convertedLoopState = outerConvertedLoopState; @@ -3160,7 +3543,12 @@ export function transformES2015(context: TransformationContext): (x: SourceFile addExtraDeclarationsForConvertedLoop(statements, currentState, outerConvertedLoopState); if (initializerFunction) { - statements.push(generateCallToConvertedLoopInitializer(initializerFunction.functionName, initializerFunction.containsYield)); + statements.push( + generateCallToConvertedLoopInitializer( + initializerFunction.functionName, + initializerFunction.containsYield, + ), + ); } let loop: Statement; @@ -3169,12 +3557,24 @@ export function transformES2015(context: TransformationContext): (x: SourceFile loop = convert(node, outermostLabeledStatement, bodyFunction.part, ancestorFacts); } else { - const clone = convertIterationStatementCore(node, initializerFunction, factory.createBlock(bodyFunction.part, /*multiLine*/ true)); - loop = factory.restoreEnclosingLabel(clone, outermostLabeledStatement, convertedLoopState && resetLabel); + const clone = convertIterationStatementCore( + node, + initializerFunction, + factory.createBlock(bodyFunction.part, /*multiLine*/ true), + ); + loop = factory.restoreEnclosingLabel( + clone, + outermostLabeledStatement, + convertedLoopState && resetLabel, + ); } } else { - const clone = convertIterationStatementCore(node, initializerFunction, Debug.checkDefined(visitNode(node.statement, visitor, isStatement, factory.liftToBlock))); + const clone = convertIterationStatementCore( + node, + initializerFunction, + Debug.checkDefined(visitNode(node.statement, visitor, isStatement, factory.liftToBlock)), + ); loop = factory.restoreEnclosingLabel(clone, outermostLabeledStatement, convertedLoopState && resetLabel); } @@ -3182,7 +3582,11 @@ export function transformES2015(context: TransformationContext): (x: SourceFile return statements; } - function convertIterationStatementCore(node: IterationStatement, initializerFunction: IterationStatementPartFunction | undefined, convertedLoopBody: Statement) { + function convertIterationStatementCore( + node: IterationStatement, + initializerFunction: IterationStatementPartFunction | undefined, + convertedLoopBody: Statement, + ) { switch (node.kind) { case SyntaxKind.ForStatement: return convertForStatement(node as ForStatement, initializerFunction, convertedLoopBody); @@ -3199,14 +3603,27 @@ export function transformES2015(context: TransformationContext): (x: SourceFile } } - function convertForStatement(node: ForStatement, initializerFunction: IterationStatementPartFunction | undefined, convertedLoopBody: Statement) { + function convertForStatement( + node: ForStatement, + initializerFunction: IterationStatementPartFunction | undefined, + convertedLoopBody: Statement, + ) { const shouldConvertCondition = node.condition && shouldConvertPartOfIterationStatement(node.condition); - const shouldConvertIncrementor = shouldConvertCondition || node.incrementor && shouldConvertPartOfIterationStatement(node.incrementor); + const shouldConvertIncrementor = shouldConvertCondition + || node.incrementor && shouldConvertPartOfIterationStatement(node.incrementor); return factory.updateForStatement( node, - visitNode(initializerFunction ? initializerFunction.part : node.initializer, visitorWithUnusedExpressionResult, isForInitializer), + visitNode( + initializerFunction ? initializerFunction.part : node.initializer, + visitorWithUnusedExpressionResult, + isForInitializer, + ), visitNode(shouldConvertCondition ? undefined : node.condition, visitor, isExpression), - visitNode(shouldConvertIncrementor ? undefined : node.incrementor, visitorWithUnusedExpressionResult, isExpression), + visitNode( + shouldConvertIncrementor ? undefined : node.incrementor, + visitorWithUnusedExpressionResult, + isExpression, + ), convertedLoopBody, ); } @@ -3264,11 +3681,17 @@ export function transformES2015(context: TransformationContext): (x: SourceFile // variables declared in the loop initializer that will be changed inside the loop const loopOutParameters: LoopOutParameter[] = []; if (loopInitializer && (getCombinedNodeFlags(loopInitializer) & NodeFlags.BlockScoped)) { - const hasCapturedBindingsInForHead = shouldConvertInitializerOfForStatement(node) || - shouldConvertConditionOfForStatement(node) || - shouldConvertIncrementorOfForStatement(node); + const hasCapturedBindingsInForHead = shouldConvertInitializerOfForStatement(node) + || shouldConvertConditionOfForStatement(node) + || shouldConvertIncrementorOfForStatement(node); for (const decl of loopInitializer.declarations) { - processLoopVariableDeclaration(node, decl, loopParameters, loopOutParameters, hasCapturedBindingsInForHead); + processLoopVariableDeclaration( + node, + decl, + loopParameters, + loopOutParameters, + hasCapturedBindingsInForHead, + ); } } @@ -3295,7 +3718,11 @@ export function transformES2015(context: TransformationContext): (x: SourceFile return currentState; } - function addExtraDeclarationsForConvertedLoop(statements: Statement[], state: ConvertedLoopState, outerState: ConvertedLoopState | undefined) { + function addExtraDeclarationsForConvertedLoop( + statements: Statement[], + state: ConvertedLoopState, + outerState: ConvertedLoopState | undefined, + ) { let extraVariableDeclarations: VariableDeclaration[] | undefined; // propagate state from the inner loop to the outer loop if necessary if (state.argumentsName) { @@ -3370,7 +3797,14 @@ export function transformES2015(context: TransformationContext): (x: SourceFile if (!extraVariableDeclarations) { extraVariableDeclarations = []; } - extraVariableDeclarations.push(factory.createVariableDeclaration(state.conditionVariable, /*exclamationToken*/ undefined, /*type*/ undefined, factory.createFalse())); + extraVariableDeclarations.push( + factory.createVariableDeclaration( + state.conditionVariable, + /*exclamationToken*/ undefined, + /*type*/ undefined, + factory.createFalse(), + ), + ); } // create variable statement to hold all introduced variable declarations @@ -3390,7 +3824,12 @@ export function transformES2015(context: TransformationContext): (x: SourceFile } function createOutVariable(p: LoopOutParameter) { - return factory.createVariableDeclaration(p.originalName, /*exclamationToken*/ undefined, /*type*/ undefined, p.outParamName); + return factory.createVariableDeclaration( + p.originalName, + /*exclamationToken*/ undefined, + /*type*/ undefined, + p.outParamName, + ); } /** @@ -3399,17 +3838,27 @@ export function transformES2015(context: TransformationContext): (x: SourceFile * used to preserve the per-iteration environment semantics of * [13.7.4.8 RS: ForBodyEvaluation](https://tc39.github.io/ecma262/#sec-forbodyevaluation). */ - function createFunctionForInitializerOfForStatement(node: ForStatementWithConvertibleInitializer, currentState: ConvertedLoopState): IterationStatementPartFunction { + function createFunctionForInitializerOfForStatement( + node: ForStatementWithConvertibleInitializer, + currentState: ConvertedLoopState, + ): IterationStatementPartFunction { const functionName = factory.createUniqueName("_loop_init"); const containsYield = (node.initializer.transformFlags & TransformFlags.ContainsYield) !== 0; let emitFlags = EmitFlags.None; if (currentState.containsLexicalThis) emitFlags |= EmitFlags.CapturesThis; - if (containsYield && hierarchyFacts & HierarchyFacts.AsyncFunctionBody) emitFlags |= EmitFlags.AsyncFunctionBody; + if (containsYield && hierarchyFacts & HierarchyFacts.AsyncFunctionBody) { + emitFlags |= EmitFlags.AsyncFunctionBody; + } const statements: Statement[] = []; statements.push(factory.createVariableStatement(/*modifiers*/ undefined, node.initializer)); - copyOutParameters(currentState.loopOutParameters, LoopOutParameterFlags.Initializer, CopyDirection.ToOutParameter, statements); + copyOutParameters( + currentState.loopOutParameters, + LoopOutParameterFlags.Initializer, + CopyDirection.ToOutParameter, + statements, + ); // This transforms the following ES2015 syntax: // @@ -3472,7 +3921,11 @@ export function transformES2015(context: TransformationContext): (x: SourceFile * preserve the per-iteration environment semantics of * [13.7.4.8 RS: ForBodyEvaluation](https://tc39.github.io/ecma262/#sec-forbodyevaluation). */ - function createFunctionForBodyOfIterationStatement(node: IterationStatement, currentState: ConvertedLoopState, outerState: ConvertedLoopState | undefined): IterationStatementPartFunction { + function createFunctionForBodyOfIterationStatement( + node: IterationStatement, + currentState: ConvertedLoopState, + outerState: ConvertedLoopState | undefined, + ): IterationStatementPartFunction { const functionName = factory.createUniqueName("_loop"); startLexicalEnvironment(); const statement = visitNode(node.statement, visitor, isStatement, factory.liftToBlock); @@ -3522,20 +3975,29 @@ export function transformES2015(context: TransformationContext): (x: SourceFile if (node.incrementor) { statements.push(factory.createIfStatement( currentState.conditionVariable, - factory.createExpressionStatement(Debug.checkDefined(visitNode(node.incrementor, visitor, isExpression))), - factory.createExpressionStatement(factory.createAssignment(currentState.conditionVariable, factory.createTrue())), + factory.createExpressionStatement( + Debug.checkDefined(visitNode(node.incrementor, visitor, isExpression)), + ), + factory.createExpressionStatement( + factory.createAssignment(currentState.conditionVariable, factory.createTrue()), + ), )); } else { statements.push(factory.createIfStatement( factory.createLogicalNot(currentState.conditionVariable), - factory.createExpressionStatement(factory.createAssignment(currentState.conditionVariable, factory.createTrue())), + factory.createExpressionStatement( + factory.createAssignment(currentState.conditionVariable, factory.createTrue()), + ), )); } if (shouldConvertConditionOfForStatement(node)) { statements.push(factory.createIfStatement( - factory.createPrefixUnaryExpression(SyntaxKind.ExclamationToken, Debug.checkDefined(visitNode(node.condition, visitor, isExpression))), + factory.createPrefixUnaryExpression( + SyntaxKind.ExclamationToken, + Debug.checkDefined(visitNode(node.condition, visitor, isExpression)), + ), Debug.checkDefined(visitNode(factory.createBreakStatement(), visitor, isStatement)), )); } @@ -3549,7 +4011,12 @@ export function transformES2015(context: TransformationContext): (x: SourceFile statements.push(statement); } - copyOutParameters(currentState.loopOutParameters, LoopOutParameterFlags.Body, CopyDirection.ToOutParameter, statements); + copyOutParameters( + currentState.loopOutParameters, + LoopOutParameterFlags.Body, + CopyDirection.ToOutParameter, + statements, + ); insertStatementsAfterStandardPrologue(statements, lexicalEnvironment); const loopBody = factory.createBlock(statements, /*multiLine*/ true); @@ -3559,7 +4026,9 @@ export function transformES2015(context: TransformationContext): (x: SourceFile let emitFlags: EmitFlags = EmitFlags.ReuseTempVariableScope; if (currentState.containsLexicalThis) emitFlags |= EmitFlags.CapturesThis; - if (containsYield && (hierarchyFacts & HierarchyFacts.AsyncFunctionBody) !== 0) emitFlags |= EmitFlags.AsyncFunctionBody; + if (containsYield && (hierarchyFacts & HierarchyFacts.AsyncFunctionBody) !== 0) { + emitFlags |= EmitFlags.AsyncFunctionBody; + } // This transforms the following ES2015 syntax (in addition to other variations): // @@ -3614,7 +4083,12 @@ export function transformES2015(context: TransformationContext): (x: SourceFile return factory.createBinaryExpression(target, SyntaxKind.EqualsToken, source); } - function copyOutParameters(outParams: LoopOutParameter[], partFlags: LoopOutParameterFlags, copyDirection: CopyDirection, statements: Statement[]): void { + function copyOutParameters( + outParams: LoopOutParameter[], + partFlags: LoopOutParameterFlags, + copyDirection: CopyDirection, + statements: Statement[], + ): void { for (const outParam of outParams) { if (outParam.flags & partFlags) { statements.push(factory.createExpressionStatement(copyOutParameter(outParam, copyDirection))); @@ -3622,7 +4096,10 @@ export function transformES2015(context: TransformationContext): (x: SourceFile } } - function generateCallToConvertedLoopInitializer(initFunctionExpressionName: Identifier, containsYield: boolean): Statement { + function generateCallToConvertedLoopInitializer( + initFunctionExpressionName: Identifier, + containsYield: boolean, + ): Statement { const call = factory.createCallExpression(initFunctionExpressionName, /*typeArguments*/ undefined, []); const callResult = containsYield ? factory.createYieldExpression( @@ -3633,16 +4110,25 @@ export function transformES2015(context: TransformationContext): (x: SourceFile return factory.createExpressionStatement(callResult); } - function generateCallToConvertedLoop(loopFunctionExpressionName: Identifier, state: ConvertedLoopState, outerState: ConvertedLoopState | undefined, containsYield: boolean): Statement[] { + function generateCallToConvertedLoop( + loopFunctionExpressionName: Identifier, + state: ConvertedLoopState, + outerState: ConvertedLoopState | undefined, + containsYield: boolean, + ): Statement[] { const statements: Statement[] = []; // loop is considered simple if it does not have any return statements or break\continue that transfer control outside of the loop // simple loops are emitted as just 'loop()'; // NOTE: if loop uses only 'continue' it still will be emitted as simple loop - const isSimpleLoop = !(state.nonLocalJumps! & ~Jump.Continue) && - !state.labeledNonLocalBreaks && - !state.labeledNonLocalContinues; + const isSimpleLoop = !(state.nonLocalJumps! & ~Jump.Continue) + && !state.labeledNonLocalBreaks + && !state.labeledNonLocalContinues; - const call = factory.createCallExpression(loopFunctionExpressionName, /*typeArguments*/ undefined, map(state.loopParameters, p => p.name as Identifier)); + const call = factory.createCallExpression( + loopFunctionExpressionName, + /*typeArguments*/ undefined, + map(state.loopParameters, p => p.name as Identifier), + ); const callResult = containsYield ? factory.createYieldExpression( factory.createToken(SyntaxKind.AsteriskToken), @@ -3651,18 +4137,33 @@ export function transformES2015(context: TransformationContext): (x: SourceFile : call; if (isSimpleLoop) { statements.push(factory.createExpressionStatement(callResult)); - copyOutParameters(state.loopOutParameters, LoopOutParameterFlags.Body, CopyDirection.ToOriginal, statements); + copyOutParameters( + state.loopOutParameters, + LoopOutParameterFlags.Body, + CopyDirection.ToOriginal, + statements, + ); } else { const loopResultName = factory.createUniqueName("state"); const stateVariable = factory.createVariableStatement( /*modifiers*/ undefined, factory.createVariableDeclarationList( - [factory.createVariableDeclaration(loopResultName, /*exclamationToken*/ undefined, /*type*/ undefined, callResult)], + [factory.createVariableDeclaration( + loopResultName, + /*exclamationToken*/ undefined, + /*type*/ undefined, + callResult, + )], ), ); statements.push(stateVariable); - copyOutParameters(state.loopOutParameters, LoopOutParameterFlags.Body, CopyDirection.ToOriginal, statements); + copyOutParameters( + state.loopOutParameters, + LoopOutParameterFlags.Body, + CopyDirection.ToOriginal, + statements, + ); if (state.nonLocalJumps! & Jump.Return) { let returnStatement: ReturnStatement; @@ -3671,7 +4172,9 @@ export function transformES2015(context: TransformationContext): (x: SourceFile returnStatement = factory.createReturnStatement(loopResultName); } else { - returnStatement = factory.createReturnStatement(factory.createPropertyAccessExpression(loopResultName, "value")); + returnStatement = factory.createReturnStatement( + factory.createPropertyAccessExpression(loopResultName, "value"), + ); } statements.push( factory.createIfStatement( @@ -3695,8 +4198,20 @@ export function transformES2015(context: TransformationContext): (x: SourceFile if (state.labeledNonLocalBreaks || state.labeledNonLocalContinues) { const caseClauses: CaseClause[] = []; - processLabeledJumps(state.labeledNonLocalBreaks!, /*isBreak*/ true, loopResultName, outerState, caseClauses); - processLabeledJumps(state.labeledNonLocalContinues!, /*isBreak*/ false, loopResultName, outerState, caseClauses); + processLabeledJumps( + state.labeledNonLocalBreaks!, + /*isBreak*/ true, + loopResultName, + outerState, + caseClauses, + ); + processLabeledJumps( + state.labeledNonLocalContinues!, + /*isBreak*/ false, + loopResultName, + outerState, + caseClauses, + ); statements.push( factory.createSwitchStatement( loopResultName, @@ -3723,7 +4238,13 @@ export function transformES2015(context: TransformationContext): (x: SourceFile } } - function processLabeledJumps(table: Map, isBreak: boolean, loopResultName: Identifier, outerLoop: ConvertedLoopState | undefined, caseClauses: CaseClause[]): void { + function processLabeledJumps( + table: Map, + isBreak: boolean, + loopResultName: Identifier, + outerLoop: ConvertedLoopState | undefined, + caseClauses: CaseClause[], + ): void { if (!table) { return; } @@ -3744,17 +4265,31 @@ export function transformES2015(context: TransformationContext): (x: SourceFile }); } - function processLoopVariableDeclaration(container: IterationStatement, decl: VariableDeclaration | BindingElement, loopParameters: ParameterDeclaration[], loopOutParameters: LoopOutParameter[], hasCapturedBindingsInForHead: boolean) { + function processLoopVariableDeclaration( + container: IterationStatement, + decl: VariableDeclaration | BindingElement, + loopParameters: ParameterDeclaration[], + loopOutParameters: LoopOutParameter[], + hasCapturedBindingsInForHead: boolean, + ) { const name = decl.name; if (isBindingPattern(name)) { for (const element of name.elements) { if (!isOmittedExpression(element)) { - processLoopVariableDeclaration(container, element, loopParameters, loopOutParameters, hasCapturedBindingsInForHead); + processLoopVariableDeclaration( + container, + element, + loopParameters, + loopOutParameters, + hasCapturedBindingsInForHead, + ); } } } else { - loopParameters.push(factory.createParameterDeclaration(/*modifiers*/ undefined, /*dotDotDotToken*/ undefined, name)); + loopParameters.push( + factory.createParameterDeclaration(/*modifiers*/ undefined, /*dotDotDotToken*/ undefined, name), + ); const checkFlags = resolver.getNodeCheckFlags(decl); if (checkFlags & NodeCheckFlags.NeedsLoopOutParameter || hasCapturedBindingsInForHead) { const outParamName = factory.createUniqueName("out_" + idText(name)); @@ -3767,8 +4302,8 @@ export function transformES2015(context: TransformationContext): (x: SourceFile flags |= LoopOutParameterFlags.Initializer; } if ( - container.condition && resolver.isBindingCapturedByNode(container.condition, decl) || - container.incrementor && resolver.isBindingCapturedByNode(container.incrementor, decl) + container.condition && resolver.isBindingCapturedByNode(container.condition, decl) + || container.incrementor && resolver.isBindingCapturedByNode(container.incrementor, decl) ) { flags |= LoopOutParameterFlags.Body; } @@ -3787,7 +4322,12 @@ export function transformES2015(context: TransformationContext): (x: SourceFile * @param numInitialNonComputedProperties The number of initial properties without * computed property names. */ - function addObjectLiteralMembers(expressions: Expression[], node: ObjectLiteralExpression, receiver: Identifier, start: number) { + function addObjectLiteralMembers( + expressions: Expression[], + node: ObjectLiteralExpression, + receiver: Identifier, + start: number, + ) { const properties = node.properties; const numProperties = properties.length; for (let i = start; i < numProperties; i++) { @@ -3803,7 +4343,9 @@ export function transformES2015(context: TransformationContext): (x: SourceFile break; case SyntaxKind.MethodDeclaration: - expressions.push(transformObjectLiteralMethodDeclarationToExpression(property, receiver, node, node.multiLine!)); + expressions.push( + transformObjectLiteralMethodDeclarationToExpression(property, receiver, node, node.multiLine!), + ); break; case SyntaxKind.PropertyAssignment: @@ -3811,7 +4353,9 @@ export function transformES2015(context: TransformationContext): (x: SourceFile break; case SyntaxKind.ShorthandPropertyAssignment: - expressions.push(transformShorthandPropertyAssignmentToExpression(property, receiver, node.multiLine!)); + expressions.push( + transformShorthandPropertyAssignmentToExpression(property, receiver, node.multiLine!), + ); break; default: @@ -3828,7 +4372,11 @@ export function transformES2015(context: TransformationContext): (x: SourceFile * @param property The PropertyAssignment node. * @param receiver The receiver for the assignment. */ - function transformPropertyAssignmentToExpression(property: PropertyAssignment, receiver: Expression, startsOnNewLine: boolean) { + function transformPropertyAssignmentToExpression( + property: PropertyAssignment, + receiver: Expression, + startsOnNewLine: boolean, + ) { const expression = factory.createAssignment( createMemberAccessForPropertyName( factory, @@ -3851,7 +4399,11 @@ export function transformES2015(context: TransformationContext): (x: SourceFile * @param property The ShorthandPropertyAssignment node. * @param receiver The receiver for the assignment. */ - function transformShorthandPropertyAssignmentToExpression(property: ShorthandPropertyAssignment, receiver: Expression, startsOnNewLine: boolean) { + function transformShorthandPropertyAssignmentToExpression( + property: ShorthandPropertyAssignment, + receiver: Expression, + startsOnNewLine: boolean, + ) { const expression = factory.createAssignment( createMemberAccessForPropertyName( factory, @@ -3874,7 +4426,12 @@ export function transformES2015(context: TransformationContext): (x: SourceFile * @param method The MethodDeclaration node. * @param receiver The receiver for the assignment. */ - function transformObjectLiteralMethodDeclarationToExpression(method: MethodDeclaration, receiver: Expression, container: Node, startsOnNewLine: boolean) { + function transformObjectLiteralMethodDeclarationToExpression( + method: MethodDeclaration, + receiver: Expression, + container: Node, + startsOnNewLine: boolean, + ) { const expression = factory.createAssignment( createMemberAccessForPropertyName( factory, @@ -3893,7 +4450,10 @@ export function transformES2015(context: TransformationContext): (x: SourceFile function visitCatchClause(node: CatchClause): CatchClause { const ancestorFacts = enterSubtree(HierarchyFacts.BlockScopeExcludes, HierarchyFacts.BlockScopeIncludes); let updated: CatchClause; - Debug.assert(!!node.variableDeclaration, "Catch clause variable should always be present when downleveling ES2015."); + Debug.assert( + !!node.variableDeclaration, + "Catch clause variable should always be present when downleveling ES2015.", + ); if (isBindingPattern(node.variableDeclaration.name)) { const temp = factory.createTempVariable(/*recordTempVariable*/ undefined); const newVariableDeclaration = factory.createVariableDeclaration(temp); @@ -3908,7 +4468,11 @@ export function transformES2015(context: TransformationContext): (x: SourceFile const list = factory.createVariableDeclarationList(vars); setTextRange(list, node.variableDeclaration); const destructure = factory.createVariableStatement(/*modifiers*/ undefined, list); - updated = factory.updateCatchClause(node, newVariableDeclaration, addStatementToStartOfBlock(node.block, destructure)); + updated = factory.updateCatchClause( + node, + newVariableDeclaration, + addStatementToStartOfBlock(node.block, destructure), + ); } else { updated = visitEachChild(node, visitor, context); @@ -3934,7 +4498,12 @@ export function transformES2015(context: TransformationContext): (x: SourceFile // Methods on classes are handled in visitClassDeclaration/visitClassExpression. // Methods with computed property names are handled in visitObjectLiteralExpression. Debug.assert(!isComputedPropertyName(node.name)); - const functionExpression = transformFunctionLikeToExpression(node, /*location*/ moveRangePos(node, -1), /*name*/ undefined, /*container*/ undefined); + const functionExpression = transformFunctionLikeToExpression( + node, + /*location*/ moveRangePos(node, -1), + /*name*/ undefined, + /*container*/ undefined, + ); setEmitFlags(functionExpression, EmitFlags.NoLeadingComments | getEmitFlags(functionExpression)); return setTextRange( factory.createPropertyAssignment( @@ -3959,7 +4528,14 @@ export function transformES2015(context: TransformationContext): (x: SourceFile const parameters = visitParameterList(node.parameters, visitor, context); const body = transformFunctionBody(node); if (node.kind === SyntaxKind.GetAccessor) { - updated = factory.updateGetAccessorDeclaration(node, node.modifiers, node.name, parameters, node.type, body); + updated = factory.updateGetAccessorDeclaration( + node, + node.modifiers, + node.name, + parameters, + node.type, + body, + ); } else { updated = factory.updateSetAccessorDeclaration(node, node.modifiers, node.name, parameters, body); @@ -4006,7 +4582,12 @@ export function transformES2015(context: TransformationContext): (x: SourceFile function visitArrayLiteralExpression(node: ArrayLiteralExpression): Expression { if (some(node.elements, isSpreadElement)) { // We are here because we contain a SpreadElementExpression. - return transformAndSpreadElements(node.elements, /*isArgumentList*/ false, !!node.multiLine, /*hasTrailingComma*/ !!node.elements.hasTrailingComma); + return transformAndSpreadElements( + node.elements, + /*isArgumentList*/ false, + !!node.multiLine, + /*hasTrailingComma*/ !!node.elements.hasTrailingComma, + ); } return visitEachChild(node, visitor, context); } @@ -4023,9 +4604,9 @@ export function transformES2015(context: TransformationContext): (x: SourceFile const expression = skipOuterExpressions(node.expression); if ( - expression.kind === SyntaxKind.SuperKeyword || - isSuperProperty(expression) || - some(node.arguments, isSpreadElement) + expression.kind === SyntaxKind.SuperKeyword + || isSuperProperty(expression) + || some(node.arguments, isSpreadElement) ) { return visitCallExpressionWithPotentialCapturedThisAssignment(node, /*assignToCapturedThis*/ true); } @@ -4076,7 +4657,8 @@ export function transformES2015(context: TransformationContext): (x: SourceFile // The class statements are the statements generated by visiting the first statement with initializer of the // body (1), while all other statements are added to remainingStatements (2) - const isVariableStatementWithInitializer = (stmt: Statement) => isVariableStatement(stmt) && !!first(stmt.declarationList.declarations).initializer; + const isVariableStatementWithInitializer = (stmt: Statement) => + isVariableStatement(stmt) && !!first(stmt.declarationList.declarations).initializer; // visit the class body statements outside of any converted loop body. const savedConvertedLoopState = convertedLoopState; @@ -4109,12 +4691,18 @@ export function transformES2015(context: TransformationContext): (x: SourceFile // }()) // let aliasAssignment = tryCast(initializer, isAssignmentExpression); - if (!aliasAssignment && isBinaryExpression(initializer) && initializer.operatorToken.kind === SyntaxKind.CommaToken) { + if ( + !aliasAssignment && isBinaryExpression(initializer) + && initializer.operatorToken.kind === SyntaxKind.CommaToken + ) { aliasAssignment = tryCast(initializer.left, isAssignmentExpression); } // The underlying call (3) is another IIFE that may contain a '_super' argument. - const call = cast(aliasAssignment ? skipOuterExpressions(aliasAssignment.right) : initializer, isCallExpression); + const call = cast( + aliasAssignment ? skipOuterExpressions(aliasAssignment.right) : initializer, + isCallExpression, + ); const func = cast(skipOuterExpressions(call.expression), isFunctionExpression); const funcStatements = func.body.statements; @@ -4169,8 +4757,8 @@ export function transformES2015(context: TransformationContext): (x: SourceFile const returnStatement = tryCast(elementAt(funcStatements, classBodyEnd), isReturnStatement); for (const statement of remainingStatements) { if ( - isReturnStatement(statement) && returnStatement?.expression && - !isIdentifier(returnStatement.expression) + isReturnStatement(statement) && returnStatement?.expression + && !isIdentifier(returnStatement.expression) ) { statements.push(returnStatement); } @@ -4221,13 +4809,16 @@ export function transformES2015(context: TransformationContext): (x: SourceFile return visitCallExpressionWithPotentialCapturedThisAssignment(node, /*assignToCapturedThis*/ false); } - function visitCallExpressionWithPotentialCapturedThisAssignment(node: CallExpression, assignToCapturedThis: boolean): CallExpression | BinaryExpression { + function visitCallExpressionWithPotentialCapturedThisAssignment( + node: CallExpression, + assignToCapturedThis: boolean, + ): CallExpression | BinaryExpression { // We are here either because SuperKeyword was used somewhere in the expression, or // because we contain a SpreadElementExpression. if ( - node.transformFlags & TransformFlags.ContainsRestOrSpread || - node.expression.kind === SyntaxKind.SuperKeyword || - isSuperProperty(skipOuterExpressions(node.expression)) + node.transformFlags & TransformFlags.ContainsRestOrSpread + || node.expression.kind === SyntaxKind.SuperKeyword + || isSuperProperty(skipOuterExpressions(node.expression)) ) { const { target, thisArg } = factory.createCallBinding(node.expression, hoistVariableDeclaration); if (node.expression.kind === SyntaxKind.SuperKeyword) { @@ -4252,8 +4843,14 @@ export function transformES2015(context: TransformationContext): (x: SourceFile resultingCall = factory.createFunctionApplyCall( Debug.checkDefined(visitNode(target, callExpressionVisitor, isExpression)), - node.expression.kind === SyntaxKind.SuperKeyword ? thisArg : Debug.checkDefined(visitNode(thisArg, visitor, isExpression)), - transformAndSpreadElements(node.arguments, /*isArgumentList*/ true, /*multiLine*/ false, /*hasTrailingComma*/ false), + node.expression.kind === SyntaxKind.SuperKeyword ? thisArg + : Debug.checkDefined(visitNode(thisArg, visitor, isExpression)), + transformAndSpreadElements( + node.arguments, + /*isArgumentList*/ true, + /*multiLine*/ false, + /*hasTrailingComma*/ false, + ), ); } else { @@ -4269,7 +4866,8 @@ export function transformES2015(context: TransformationContext): (x: SourceFile resultingCall = setTextRange( factory.createFunctionCallCall( Debug.checkDefined(visitNode(target, callExpressionVisitor, isExpression)), - node.expression.kind === SyntaxKind.SuperKeyword ? thisArg : Debug.checkDefined(visitNode(thisArg, visitor, isExpression)), + node.expression.kind === SyntaxKind.SuperKeyword ? thisArg + : Debug.checkDefined(visitNode(thisArg, visitor, isExpression)), visitNodes(node.arguments, visitor, isExpression), ), node, @@ -4282,7 +4880,13 @@ export function transformES2015(context: TransformationContext): (x: SourceFile createActualThis(), ); resultingCall = assignToCapturedThis - ? factory.createAssignment(factory.createUniqueName("_this", GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel), initializer) + ? factory.createAssignment( + factory.createUniqueName( + "_this", + GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel, + ), + initializer, + ) : initializer; } return setOriginalNode(resultingCall, node); @@ -4305,12 +4909,20 @@ export function transformES2015(context: TransformationContext): (x: SourceFile // [output] // new ((_a = C).bind.apply(_a, [void 0].concat(a)))() - const { target, thisArg } = factory.createCallBinding(factory.createPropertyAccessExpression(node.expression, "bind"), hoistVariableDeclaration); + const { target, thisArg } = factory.createCallBinding( + factory.createPropertyAccessExpression(node.expression, "bind"), + hoistVariableDeclaration, + ); return factory.createNewExpression( factory.createFunctionApplyCall( Debug.checkDefined(visitNode(target, visitor, isExpression)), thisArg, - transformAndSpreadElements(factory.createNodeArray([factory.createVoidZero(), ...node.arguments!]), /*isArgumentList*/ true, /*multiLine*/ false, /*hasTrailingComma*/ false), + transformAndSpreadElements( + factory.createNodeArray([factory.createVoidZero(), ...node.arguments!]), + /*isArgumentList*/ true, + /*multiLine*/ false, + /*hasTrailingComma*/ false, + ), ), /*typeArguments*/ undefined, [], @@ -4328,7 +4940,12 @@ export function transformES2015(context: TransformationContext): (x: SourceFile * argument list. * @param multiLine A value indicating whether the result should be emitted on multiple lines. */ - function transformAndSpreadElements(elements: NodeArray, isArgumentList: boolean, multiLine: boolean, hasTrailingComma: boolean): Expression { + function transformAndSpreadElements( + elements: NodeArray, + isArgumentList: boolean, + multiLine: boolean, + hasTrailingComma: boolean, + ): Expression { // When there is no leading SpreadElement: // // [source] @@ -4367,7 +4984,12 @@ export function transformES2015(context: TransformationContext): (x: SourceFile // As we visit each element, we return one of two functions to use as the "key": // - `visitSpanOfSpreads` for one or more contiguous `...` spread expressions, i.e. `...a, ...b` in `[1, 2, ...a, ...b]` // - `visitSpanOfNonSpreads` for one or more contiguous non-spread elements, i.e. `1, 2`, in `[1, 2, ...a, ...b]` - spanMap(elements, partitionSpread, (partition, visitPartition, _start, end) => visitPartition(partition, multiLine, hasTrailingComma && end === numElements)), + spanMap( + elements, + partitionSpread, + (partition, visitPartition, _start, end) => + visitPartition(partition, multiLine, hasTrailingComma && end === numElements), + ), ); if (segments.length === 1) { @@ -4387,8 +5009,8 @@ export function transformES2015(context: TransformationContext): (x: SourceFile const helpers = emitHelpers(); const startsWithSpread = segments[0].kind !== SpreadSegmentKind.None; - let expression: Expression = startsWithSpread ? factory.createArrayLiteralExpression() : - segments[0].expression; + let expression: Expression = startsWithSpread ? factory.createArrayLiteralExpression() + : segments[0].expression; for (let i = startsWithSpread ? 0 : 1; i < segments.length; i++) { const segment = segments[i]; // If this is for an argument list, it doesn't matter if the array is packed or sparse @@ -4418,10 +5040,14 @@ export function transformES2015(context: TransformationContext): (x: SourceFile // We don't need to pack already packed array literals, or existing calls to the `__read` helper. const isCallToReadHelper = isCallToHelper(expression, "___read" as __String); - let kind = isCallToReadHelper || isPackedArrayLiteral(expression) ? SpreadSegmentKind.PackedSpread : SpreadSegmentKind.UnpackedSpread; + let kind = isCallToReadHelper || isPackedArrayLiteral(expression) ? SpreadSegmentKind.PackedSpread + : SpreadSegmentKind.UnpackedSpread; // We don't need the `__read` helper for array literals. Array packing will be performed by `__spreadArray`. - if (compilerOptions.downlevelIteration && kind === SpreadSegmentKind.UnpackedSpread && !isArrayLiteralExpression(expression) && !isCallToReadHelper) { + if ( + compilerOptions.downlevelIteration && kind === SpreadSegmentKind.UnpackedSpread + && !isArrayLiteralExpression(expression) && !isCallToReadHelper + ) { expression = emitHelpers().createReadHelper(expression, /*count*/ undefined); // the `__read` helper returns a packed array, so we don't need to ensure a packed array kind = SpreadSegmentKind.PackedSpread; @@ -4524,14 +5150,26 @@ export function transformES2015(context: TransformationContext): (x: SourceFile function visitSuperKeyword(isExpressionOfCall: boolean): LeftHandSideExpression { return hierarchyFacts & HierarchyFacts.NonStaticClassElement && !isExpressionOfCall - ? factory.createPropertyAccessExpression(factory.createUniqueName("_super", GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel), "prototype") - : factory.createUniqueName("_super", GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel); + ? factory.createPropertyAccessExpression( + factory.createUniqueName( + "_super", + GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel, + ), + "prototype", + ) + : factory.createUniqueName( + "_super", + GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel, + ); } function visitMetaProperty(node: MetaProperty) { if (node.keywordToken === SyntaxKind.NewKeyword && node.name.escapedText === "target") { hierarchyFacts |= HierarchyFacts.NewTarget; - return factory.createUniqueName("_newTarget", GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel); + return factory.createUniqueName( + "_newTarget", + GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel, + ); } return node; } @@ -4678,7 +5316,10 @@ export function transformES2015(context: TransformationContext): (x: SourceFile function isPartOfClassBody(declaration: ClassLikeDeclaration, node: Identifier) { let currentNode: Node | undefined = getParseTreeNode(node); - if (!currentNode || currentNode === declaration || currentNode.end <= declaration.pos || currentNode.pos >= declaration.end) { + if ( + !currentNode || currentNode === declaration || currentNode.end <= declaration.pos + || currentNode.pos >= declaration.end + ) { // if the node has no correlation to a parse tree node, its definitely not // part of the body. // if the node is outside of the document range of the declaration, its @@ -4710,7 +5351,13 @@ export function transformES2015(context: TransformationContext): (x: SourceFile enabledSubstitutions & ES2015SubstitutionFlags.CapturedThis && hierarchyFacts & HierarchyFacts.CapturesThis ) { - return setTextRange(factory.createUniqueName("_this", GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel), node); + return setTextRange( + factory.createUniqueName( + "_this", + GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel, + ), + node, + ); } return node; } @@ -4721,7 +5368,10 @@ export function transformES2015(context: TransformationContext): (x: SourceFile : factory.createPropertyAccessExpression(factory.getInternalName(node), "prototype"); } - function hasSynthesizedDefaultSuperCall(constructor: ConstructorDeclaration | undefined, hasExtendsClause: boolean) { + function hasSynthesizedDefaultSuperCall( + constructor: ConstructorDeclaration | undefined, + hasExtendsClause: boolean, + ) { if (!constructor || !hasExtendsClause) { return false; } diff --git a/src/compiler/transformers/es2016.ts b/src/compiler/transformers/es2016.ts index 39d3e05a27d65..7a2d623d15a90 100644 --- a/src/compiler/transformers/es2016.ts +++ b/src/compiler/transformers/es2016.ts @@ -69,7 +69,10 @@ export function transformES2016(context: TransformationContext): (x: SourceFile target = setTextRange( factory.createElementAccessExpression( setTextRange(factory.createAssignment(expressionTemp, left.expression), left.expression), - setTextRange(factory.createAssignment(argumentExpressionTemp, left.argumentExpression), left.argumentExpression), + setTextRange( + factory.createAssignment(argumentExpressionTemp, left.argumentExpression), + left.argumentExpression, + ), ), left, ); diff --git a/src/compiler/transformers/es2017.ts b/src/compiler/transformers/es2017.ts index d30b25e2a4580..a42b0b2afe11e 100644 --- a/src/compiler/transformers/es2017.ts +++ b/src/compiler/transformers/es2017.ts @@ -98,7 +98,12 @@ import { VisitResult, } from "../_namespaces/ts"; -type SuperContainer = ClassDeclaration | MethodDeclaration | GetAccessorDeclaration | SetAccessorDeclaration | ConstructorDeclaration; +type SuperContainer = + | ClassDeclaration + | MethodDeclaration + | GetAccessorDeclaration + | SetAccessorDeclaration + | ConstructorDeclaration; const enum ES2017SubstitutionFlags { /** Enables substitutions for async methods with `super` calls. */ @@ -216,35 +221,65 @@ export function transformES2017(context: TransformationContext): (x: SourceFile return visitAwaitExpression(node as AwaitExpression); case SyntaxKind.MethodDeclaration: - return doWithContext(ContextFlags.NonTopLevel | ContextFlags.HasLexicalThis, visitMethodDeclaration, node as MethodDeclaration); + return doWithContext( + ContextFlags.NonTopLevel | ContextFlags.HasLexicalThis, + visitMethodDeclaration, + node as MethodDeclaration, + ); case SyntaxKind.FunctionDeclaration: - return doWithContext(ContextFlags.NonTopLevel | ContextFlags.HasLexicalThis, visitFunctionDeclaration, node as FunctionDeclaration); + return doWithContext( + ContextFlags.NonTopLevel | ContextFlags.HasLexicalThis, + visitFunctionDeclaration, + node as FunctionDeclaration, + ); case SyntaxKind.FunctionExpression: - return doWithContext(ContextFlags.NonTopLevel | ContextFlags.HasLexicalThis, visitFunctionExpression, node as FunctionExpression); + return doWithContext( + ContextFlags.NonTopLevel | ContextFlags.HasLexicalThis, + visitFunctionExpression, + node as FunctionExpression, + ); case SyntaxKind.ArrowFunction: return doWithContext(ContextFlags.NonTopLevel, visitArrowFunction, node as ArrowFunction); case SyntaxKind.PropertyAccessExpression: - if (capturedSuperProperties && isPropertyAccessExpression(node) && node.expression.kind === SyntaxKind.SuperKeyword) { + if ( + capturedSuperProperties && isPropertyAccessExpression(node) + && node.expression.kind === SyntaxKind.SuperKeyword + ) { capturedSuperProperties.add(node.name.escapedText); } return visitEachChild(node, visitor, context); case SyntaxKind.ElementAccessExpression: - if (capturedSuperProperties && (node as ElementAccessExpression).expression.kind === SyntaxKind.SuperKeyword) { + if ( + capturedSuperProperties + && (node as ElementAccessExpression).expression.kind === SyntaxKind.SuperKeyword + ) { hasSuperElementAccess = true; } return visitEachChild(node, visitor, context); case SyntaxKind.GetAccessor: - return doWithContext(ContextFlags.NonTopLevel | ContextFlags.HasLexicalThis, visitGetAccessorDeclaration, node as GetAccessorDeclaration); + return doWithContext( + ContextFlags.NonTopLevel | ContextFlags.HasLexicalThis, + visitGetAccessorDeclaration, + node as GetAccessorDeclaration, + ); case SyntaxKind.SetAccessor: - return doWithContext(ContextFlags.NonTopLevel | ContextFlags.HasLexicalThis, visitSetAccessorDeclaration, node as SetAccessorDeclaration); + return doWithContext( + ContextFlags.NonTopLevel | ContextFlags.HasLexicalThis, + visitSetAccessorDeclaration, + node as SetAccessorDeclaration, + ); case SyntaxKind.Constructor: - return doWithContext(ContextFlags.NonTopLevel | ContextFlags.HasLexicalThis, visitConstructorDeclaration, node as ConstructorDeclaration); + return doWithContext( + ContextFlags.NonTopLevel | ContextFlags.HasLexicalThis, + visitConstructorDeclaration, + node as ConstructorDeclaration, + ); case SyntaxKind.ClassDeclaration: case SyntaxKind.ClassExpression: return doWithContext(ContextFlags.NonTopLevel | ContextFlags.HasLexicalThis, visitDefault, node); @@ -315,7 +350,10 @@ export function transformES2017(context: TransformationContext): (x: SourceFile function visitVariableStatementInAsyncBody(node: VariableStatement) { if (isVariableDeclarationListWithCollidingName(node.declarationList)) { - const expression = visitVariableDeclarationListWithCollidingNames(node.declarationList, /*hasReceiver*/ false); + const expression = visitVariableDeclarationListWithCollidingNames( + node.declarationList, + /*hasReceiver*/ false, + ); return expression ? factory.createExpressionStatement(expression) : undefined; } return visitEachChild(node, visitor, context); @@ -503,7 +541,10 @@ export function transformES2017(context: TransformationContext): (x: SourceFile ); } - function recordDeclarationName({ name }: ParameterDeclaration | VariableDeclaration | BindingElement, names: Set<__String>) { + function recordDeclarationName( + { name }: ParameterDeclaration | VariableDeclaration | BindingElement, + names: Set<__String>, + ) { if (isIdentifier(name)) { names.add(name.escapedText); } @@ -529,7 +570,11 @@ export function transformES2017(context: TransformationContext): (x: SourceFile const variables = getInitializedVariables(node); if (variables.length === 0) { if (hasReceiver) { - return visitNode(factory.converters.convertToAssignmentElementTarget(node.declarations[0].name), visitor, isExpression); + return visitNode( + factory.converters.convertToAssignmentElementTarget(node.declarations[0].name), + visitor, + isExpression, + ); } return undefined; } @@ -579,7 +624,9 @@ export function transformES2017(context: TransformationContext): (x: SourceFile return false; } - function transformMethodBody(node: MethodDeclaration | AccessorDeclaration | ConstructorDeclaration): FunctionBody | undefined { + function transformMethodBody( + node: MethodDeclaration | AccessorDeclaration | ConstructorDeclaration, + ): FunctionBody | undefined { Debug.assertIsDefined(node.body); const savedCapturedSuperProperties = capturedSuperProperties; @@ -592,14 +639,21 @@ export function transformES2017(context: TransformationContext): (x: SourceFile // Minor optimization, emit `_super` helper to capture `super` access in an arrow. // This step isn't needed if we eventually transform this to ES5. const originalMethod = getOriginalNode(node, isFunctionLikeDeclaration); - const emitSuperHelpers = languageVersion >= ScriptTarget.ES2015 && - resolver.getNodeCheckFlags(node) & (NodeCheckFlags.MethodWithSuperPropertyAssignmentInAsync | NodeCheckFlags.MethodWithSuperPropertyAccessInAsync) && - (getFunctionFlags(originalMethod) & FunctionFlags.AsyncGenerator) !== FunctionFlags.AsyncGenerator; + const emitSuperHelpers = languageVersion >= ScriptTarget.ES2015 + && resolver.getNodeCheckFlags(node) + & (NodeCheckFlags.MethodWithSuperPropertyAssignmentInAsync + | NodeCheckFlags.MethodWithSuperPropertyAccessInAsync) + && (getFunctionFlags(originalMethod) & FunctionFlags.AsyncGenerator) !== FunctionFlags.AsyncGenerator; if (emitSuperHelpers) { enableSubstitutionForAsyncMethodsWithSuper(); if (capturedSuperProperties.size) { - const variableStatement = createSuperAccessVariableStatement(factory, resolver, node, capturedSuperProperties); + const variableStatement = createSuperAccessVariableStatement( + factory, + resolver, + node, + capturedSuperProperties, + ); substitutedSuperAccessors[getNodeId(variableStatement)] = true; const statements = updated.statements.slice(); @@ -623,7 +677,9 @@ export function transformES2017(context: TransformationContext): (x: SourceFile return updated; } - function transformAsyncFunctionBody(node: MethodDeclaration | AccessorDeclaration | FunctionDeclaration | FunctionExpression): FunctionBody; + function transformAsyncFunctionBody( + node: MethodDeclaration | AccessorDeclaration | FunctionDeclaration | FunctionExpression, + ): FunctionBody; function transformAsyncFunctionBody(node: ArrowFunction): ConciseBody; function transformAsyncFunctionBody(node: FunctionLikeDeclaration): ConciseBody { resumeLexicalEnvironment(); @@ -656,7 +712,12 @@ export function transformES2017(context: TransformationContext): (x: SourceFile let result: ConciseBody; if (!isArrowFunction) { const statements: Statement[] = []; - const statementOffset = factory.copyPrologue((node.body as Block).statements, statements, /*ensureUseStrict*/ false, visitor); + const statementOffset = factory.copyPrologue( + (node.body as Block).statements, + statements, + /*ensureUseStrict*/ false, + visitor, + ); statements.push( factory.createReturnStatement( emitHelpers().createAwaiterHelper( @@ -672,12 +733,20 @@ export function transformES2017(context: TransformationContext): (x: SourceFile // Minor optimization, emit `_super` helper to capture `super` access in an arrow. // This step isn't needed if we eventually transform this to ES5. - const emitSuperHelpers = languageVersion >= ScriptTarget.ES2015 && resolver.getNodeCheckFlags(node) & (NodeCheckFlags.MethodWithSuperPropertyAssignmentInAsync | NodeCheckFlags.MethodWithSuperPropertyAccessInAsync); + const emitSuperHelpers = languageVersion >= ScriptTarget.ES2015 + && resolver.getNodeCheckFlags(node) + & (NodeCheckFlags.MethodWithSuperPropertyAssignmentInAsync + | NodeCheckFlags.MethodWithSuperPropertyAccessInAsync); if (emitSuperHelpers) { enableSubstitutionForAsyncMethodsWithSuper(); if (capturedSuperProperties.size) { - const variableStatement = createSuperAccessVariableStatement(factory, resolver, node, capturedSuperProperties); + const variableStatement = createSuperAccessVariableStatement( + factory, + resolver, + node, + capturedSuperProperties, + ); substitutedSuperAccessors[getNodeId(variableStatement)] = true; insertStatementsAfterStandardPrologue(statements, [variableStatement]); } @@ -709,7 +778,13 @@ export function transformES2017(context: TransformationContext): (x: SourceFile const declarations = endLexicalEnvironment(); if (some(declarations)) { const block = factory.converters.convertToFunctionBlock(expression); - result = factory.updateBlock(block, setTextRange(factory.createNodeArray(concatenate(declarations, block.statements)), block.statements)); + result = factory.updateBlock( + block, + setTextRange( + factory.createNodeArray(concatenate(declarations, block.statements)), + block.statements, + ), + ); } else { result = expression; @@ -729,7 +804,9 @@ export function transformES2017(context: TransformationContext): (x: SourceFile return factory.updateBlock(body, visitNodes(body.statements, asyncBodyVisitor, isStatement, start)); } else { - return factory.converters.convertToFunctionBlock(Debug.checkDefined(visitNode(body, asyncBodyVisitor, isConciseBody))); + return factory.converters.convertToFunctionBlock( + Debug.checkDefined(visitNode(body, asyncBodyVisitor, isConciseBody)), + ); } } @@ -780,7 +857,9 @@ export function transformES2017(context: TransformationContext): (x: SourceFile // If we need to support substitutions for `super` in an async method, // we should track it here. if (enabledSubstitutions & ES2017SubstitutionFlags.AsyncMethodsWithSuper && isSuperContainer(node)) { - const superContainerFlags = resolver.getNodeCheckFlags(node) & (NodeCheckFlags.MethodWithSuperPropertyAccessInAsync | NodeCheckFlags.MethodWithSuperPropertyAssignmentInAsync); + const superContainerFlags = resolver.getNodeCheckFlags(node) + & (NodeCheckFlags.MethodWithSuperPropertyAccessInAsync + | NodeCheckFlags.MethodWithSuperPropertyAssignmentInAsync); if (superContainerFlags !== enclosingSuperContainerFlags) { const savedEnclosingSuperContainerFlags = enclosingSuperContainerFlags; enclosingSuperContainerFlags = superContainerFlags; @@ -831,7 +910,10 @@ export function transformES2017(context: TransformationContext): (x: SourceFile if (node.expression.kind === SyntaxKind.SuperKeyword) { return setTextRange( factory.createPropertyAccessExpression( - factory.createUniqueName("_super", GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel), + factory.createUniqueName( + "_super", + GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel, + ), node.name, ), node, @@ -877,12 +959,18 @@ export function transformES2017(context: TransformationContext): (x: SourceFile || kind === SyntaxKind.SetAccessor; } - function createSuperElementAccessInAsyncMethod(argumentExpression: Expression, location: TextRange): LeftHandSideExpression { + function createSuperElementAccessInAsyncMethod( + argumentExpression: Expression, + location: TextRange, + ): LeftHandSideExpression { if (enclosingSuperContainerFlags & NodeCheckFlags.MethodWithSuperPropertyAssignmentInAsync) { return setTextRange( factory.createPropertyAccessExpression( factory.createCallExpression( - factory.createUniqueName("_superIndex", GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel), + factory.createUniqueName( + "_superIndex", + GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel, + ), /*typeArguments*/ undefined, [argumentExpression], ), @@ -894,7 +982,10 @@ export function transformES2017(context: TransformationContext): (x: SourceFile else { return setTextRange( factory.createCallExpression( - factory.createUniqueName("_superIndex", GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel), + factory.createUniqueName( + "_superIndex", + GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel, + ), /*typeArguments*/ undefined, [argumentExpression], ), @@ -909,10 +1000,16 @@ export function transformES2017(context: TransformationContext): (x: SourceFile * * @internal */ -export function createSuperAccessVariableStatement(factory: NodeFactory, resolver: EmitResolver, node: FunctionLikeDeclaration, names: Set<__String>) { +export function createSuperAccessVariableStatement( + factory: NodeFactory, + resolver: EmitResolver, + node: FunctionLikeDeclaration, + names: Set<__String>, +) { // Create a variable declaration with a getter/setter (if binding) definition for each name: // const _super = Object.create(null, { x: { get: () => super.x, set: (v) => super.x = v }, ... }); - const hasBinding = (resolver.getNodeCheckFlags(node) & NodeCheckFlags.MethodWithSuperPropertyAssignmentInAsync) !== 0; + const hasBinding = + (resolver.getNodeCheckFlags(node) & NodeCheckFlags.MethodWithSuperPropertyAssignmentInAsync) !== 0; const accessors: PropertyAssignment[] = []; names.forEach((_, key) => { const name = unescapeLeadingUnderscores(key); @@ -985,7 +1082,10 @@ export function createSuperAccessVariableStatement(factory: NodeFactory, resolve factory.createVariableDeclarationList( [ factory.createVariableDeclaration( - factory.createUniqueName("_super", GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel), + factory.createUniqueName( + "_super", + GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel, + ), /*exclamationToken*/ undefined, /*type*/ undefined, factory.createCallExpression( diff --git a/src/compiler/transformers/es2018.ts b/src/compiler/transformers/es2018.ts index e04d1c679e848..b08ad043a12ec 100644 --- a/src/compiler/transformers/es2018.ts +++ b/src/compiler/transformers/es2018.ts @@ -248,7 +248,12 @@ export function transformES2018(context: TransformationContext): (x: SourceFile return node; } - function doWithHierarchyFacts(cb: (value: T) => U, value: T, excludeFacts: HierarchyFacts, includeFacts: HierarchyFacts) { + function doWithHierarchyFacts( + cb: (value: T) => U, + value: T, + excludeFacts: HierarchyFacts, + includeFacts: HierarchyFacts, + ) { if (affectsSubtree(excludeFacts, includeFacts)) { const ancestorFacts = enterSubtree(excludeFacts, includeFacts); const result = cb(value); @@ -369,12 +374,18 @@ export function transformES2018(context: TransformationContext): (x: SourceFile case SyntaxKind.TaggedTemplateExpression: return visitTaggedTemplateExpression(node as TaggedTemplateExpression); case SyntaxKind.PropertyAccessExpression: - if (capturedSuperProperties && isPropertyAccessExpression(node) && node.expression.kind === SyntaxKind.SuperKeyword) { + if ( + capturedSuperProperties && isPropertyAccessExpression(node) + && node.expression.kind === SyntaxKind.SuperKeyword + ) { capturedSuperProperties.add(node.name.escapedText); } return visitEachChild(node, visitor, context); case SyntaxKind.ElementAccessExpression: - if (capturedSuperProperties && (node as ElementAccessExpression).expression.kind === SyntaxKind.SuperKeyword) { + if ( + capturedSuperProperties + && (node as ElementAccessExpression).expression.kind === SyntaxKind.SuperKeyword + ) { hasSuperElementAccess = true; } return visitEachChild(node, visitor, context); @@ -395,7 +406,10 @@ export function transformES2018(context: TransformationContext): (x: SourceFile if (enclosingFunctionFlags & FunctionFlags.Async && enclosingFunctionFlags & FunctionFlags.Generator) { return setOriginalNode( setTextRange( - factory.createYieldExpression(/*asteriskToken*/ undefined, emitHelpers().createAwaitHelper(visitNode(node.expression, visitor, isExpression))), + factory.createYieldExpression( + /*asteriskToken*/ undefined, + emitHelpers().createAwaitHelper(visitNode(node.expression, visitor, isExpression)), + ), /*location*/ node, ), node, @@ -555,26 +569,35 @@ export function transformES2018(context: TransformationContext): (x: SourceFile * @param expressionResultIsUnused Indicates the result of an expression is unused by the parent node (i.e., the left side of a comma or the * expression of an `ExpressionStatement`). */ - function visitParenthesizedExpression(node: ParenthesizedExpression, expressionResultIsUnused: boolean): ParenthesizedExpression { + function visitParenthesizedExpression( + node: ParenthesizedExpression, + expressionResultIsUnused: boolean, + ): ParenthesizedExpression { return visitEachChild(node, expressionResultIsUnused ? visitorWithUnusedExpressionResult : visitor, context); } function visitSourceFile(node: SourceFile): SourceFile { const ancestorFacts = enterSubtree( HierarchyFacts.SourceFileExcludes, - isEffectiveStrictModeSourceFile(node, compilerOptions) ? - HierarchyFacts.StrictModeSourceFileIncludes : - HierarchyFacts.SourceFileIncludes, + isEffectiveStrictModeSourceFile(node, compilerOptions) + ? HierarchyFacts.StrictModeSourceFileIncludes + : HierarchyFacts.SourceFileIncludes, ); exportedVariableStatement = false; const visited = visitEachChild(node, visitor, context); const statement = concatenate( visited.statements, taggedTemplateStringDeclarations && [ - factory.createVariableStatement(/*modifiers*/ undefined, factory.createVariableDeclarationList(taggedTemplateStringDeclarations)), + factory.createVariableStatement( + /*modifiers*/ undefined, + factory.createVariableDeclarationList(taggedTemplateStringDeclarations), + ), ], ); - const result = factory.updateSourceFile(visited, setTextRange(factory.createNodeArray(statement), node.statements)); + const result = factory.updateSourceFile( + visited, + setTextRange(factory.createNodeArray(statement), node.statements), + ); exitSubtree(ancestorFacts); return result; } @@ -612,7 +635,11 @@ export function transformES2018(context: TransformationContext): (x: SourceFile node, visitNode(node.left, visitorWithUnusedExpressionResult, isExpression), node.operatorToken, - visitNode(node.right, expressionResultIsUnused ? visitorWithUnusedExpressionResult : visitor, isExpression), + visitNode( + node.right, + expressionResultIsUnused ? visitorWithUnusedExpressionResult : visitor, + isExpression, + ), ); } return visitEachChild(node, visitor, context); @@ -629,7 +656,11 @@ export function transformES2018(context: TransformationContext): (x: SourceFile let result: Expression[] | undefined; for (let i = 0; i < node.elements.length; i++) { const element = node.elements[i]; - const visited = visitNode(element, i < node.elements.length - 1 ? visitorWithUnusedExpressionResult : visitor, isExpression); + const visited = visitNode( + element, + i < node.elements.length - 1 ? visitorWithUnusedExpressionResult : visitor, + isExpression, + ); if (result || visited !== element) { result ||= node.elements.slice(0, i); result.push(visited); @@ -641,12 +672,18 @@ export function transformES2018(context: TransformationContext): (x: SourceFile function visitCatchClause(node: CatchClause) { if ( - node.variableDeclaration && - isBindingPattern(node.variableDeclaration.name) && - node.variableDeclaration.name.transformFlags & TransformFlags.ContainsObjectRestOrSpread + node.variableDeclaration + && isBindingPattern(node.variableDeclaration.name) + && node.variableDeclaration.name.transformFlags & TransformFlags.ContainsObjectRestOrSpread ) { const name = factory.getGeneratedNameForNode(node.variableDeclaration.name); - const updatedDecl = factory.updateVariableDeclaration(node.variableDeclaration, node.variableDeclaration.name, /*exclamationToken*/ undefined, /*type*/ undefined, name); + const updatedDecl = factory.updateVariableDeclaration( + node.variableDeclaration, + node.variableDeclaration.name, + /*exclamationToken*/ undefined, + /*type*/ undefined, + name, + ); const visitedBindings = flattenDestructuringBinding(updatedDecl, visitor, context, FlattenLevel.ObjectRest); let block = visitNode(node.block, visitor, isBlock); if (some(visitedBindings)) { @@ -657,7 +694,13 @@ export function transformES2018(context: TransformationContext): (x: SourceFile } return factory.updateCatchClause( node, - factory.updateVariableDeclaration(node.variableDeclaration, name, /*exclamationToken*/ undefined, /*type*/ undefined, /*initializer*/ undefined), + factory.updateVariableDeclaration( + node.variableDeclaration, + name, + /*exclamationToken*/ undefined, + /*type*/ undefined, + /*initializer*/ undefined, + ), block, ); } @@ -691,7 +734,10 @@ export function transformES2018(context: TransformationContext): (x: SourceFile return visitVariableDeclarationWorker(node, /*exportedVariableStatement*/ false); } - function visitVariableDeclarationWorker(node: VariableDeclaration, exportedVariableStatement: boolean): VisitResult { + function visitVariableDeclarationWorker( + node: VariableDeclaration, + exportedVariableStatement: boolean, + ): VisitResult { // If we are here it is because the name contains a binding pattern with a rest somewhere in it. if (isBindingPattern(node.name) && node.name.transformFlags & TransformFlags.ContainsObjectRestOrSpread) { return flattenDestructuringBinding( @@ -725,17 +771,23 @@ export function transformES2018(context: TransformationContext): (x: SourceFile * * @param node A ForOfStatement. */ - function visitForOfStatement(node: ForOfStatement, outermostLabeledStatement: LabeledStatement | undefined): VisitResult { - const ancestorFacts = enterSubtree(HierarchyFacts.IterationStatementExcludes, HierarchyFacts.IterationStatementIncludes); + function visitForOfStatement( + node: ForOfStatement, + outermostLabeledStatement: LabeledStatement | undefined, + ): VisitResult { + const ancestorFacts = enterSubtree( + HierarchyFacts.IterationStatementExcludes, + HierarchyFacts.IterationStatementIncludes, + ); if ( - node.initializer.transformFlags & TransformFlags.ContainsObjectRestOrSpread || - isAssignmentPattern(node.initializer) && containsObjectRestOrSpread(node.initializer) + node.initializer.transformFlags & TransformFlags.ContainsObjectRestOrSpread + || isAssignmentPattern(node.initializer) && containsObjectRestOrSpread(node.initializer) ) { node = transformForOfStatementWithObjectRest(node); } - const result = node.awaitModifier ? - transformForAwaitOfStatement(node, outermostLabeledStatement, ancestorFacts) : - factory.restoreEnclosingLabel(visitEachChild(node, visitor, context), outermostLabeledStatement); + const result = node.awaitModifier + ? transformForAwaitOfStatement(node, outermostLabeledStatement, ancestorFacts) + : factory.restoreEnclosingLabel(visitEachChild(node, visitor, context), outermostLabeledStatement); exitSubtree(ancestorFacts); return result; } @@ -823,17 +875,27 @@ export function transformES2018(context: TransformationContext): (x: SourceFile : factory.createAwaitExpression(expression); } - function transformForAwaitOfStatement(node: ForOfStatement, outermostLabeledStatement: LabeledStatement | undefined, ancestorFacts: HierarchyFacts) { + function transformForAwaitOfStatement( + node: ForOfStatement, + outermostLabeledStatement: LabeledStatement | undefined, + ancestorFacts: HierarchyFacts, + ) { const expression = visitNode(node.expression, visitor, isExpression); - const iterator = isIdentifier(expression) ? factory.getGeneratedNameForNode(expression) : factory.createTempVariable(/*recordTempVariable*/ undefined); - const result = isIdentifier(expression) ? factory.getGeneratedNameForNode(iterator) : factory.createTempVariable(/*recordTempVariable*/ undefined); + const iterator = isIdentifier(expression) ? factory.getGeneratedNameForNode(expression) + : factory.createTempVariable(/*recordTempVariable*/ undefined); + const result = isIdentifier(expression) ? factory.getGeneratedNameForNode(iterator) + : factory.createTempVariable(/*recordTempVariable*/ undefined); const nonUserCode = factory.createTempVariable(/*recordTempVariable*/ undefined); const done = factory.createTempVariable(hoistVariableDeclaration); const errorRecord = factory.createUniqueName("e"); const catchVariable = factory.getGeneratedNameForNode(errorRecord); const returnMethod = factory.createTempVariable(/*recordTempVariable*/ undefined); const callValues = setTextRange(emitHelpers().createAsyncValuesHelper(expression), node.expression); - const callNext = factory.createCallExpression(factory.createPropertyAccessExpression(iterator, "next"), /*typeArguments*/ undefined, []); + const callNext = factory.createCallExpression( + factory.createPropertyAccessExpression(iterator, "next"), + /*typeArguments*/ undefined, + [], + ); const getDone = factory.createPropertyAccessExpression(result, "done"); const getValue = factory.createPropertyAccessExpression(result, "value"); const callReturn = factory.createFunctionCallCall(returnMethod, iterator, []); @@ -842,9 +904,9 @@ export function transformES2018(context: TransformationContext): (x: SourceFile hoistVariableDeclaration(returnMethod); // if we are enclosed in an outer loop ensure we reset 'errorRecord' per each iteration - const initializer = ancestorFacts & HierarchyFacts.IterationContainer ? - factory.inlineExpressions([factory.createAssignment(errorRecord, factory.createVoidZero()), callValues]) : - callValues; + const initializer = ancestorFacts & HierarchyFacts.IterationContainer + ? factory.inlineExpressions([factory.createAssignment(errorRecord, factory.createVoidZero()), callValues]) + : callValues; const forStatement = setEmitFlags( setTextRange( @@ -852,8 +914,21 @@ export function transformES2018(context: TransformationContext): (x: SourceFile /*initializer*/ setEmitFlags( setTextRange( factory.createVariableDeclarationList([ - factory.createVariableDeclaration(nonUserCode, /*exclamationToken*/ undefined, /*type*/ undefined, factory.createTrue()), - setTextRange(factory.createVariableDeclaration(iterator, /*exclamationToken*/ undefined, /*type*/ undefined, initializer), node.expression), + factory.createVariableDeclaration( + nonUserCode, + /*exclamationToken*/ undefined, + /*type*/ undefined, + factory.createTrue(), + ), + setTextRange( + factory.createVariableDeclaration( + iterator, + /*exclamationToken*/ undefined, + /*type*/ undefined, + initializer, + ), + node.expression, + ), factory.createVariableDeclaration(result), ]), node.expression, @@ -1132,10 +1207,17 @@ export function transformES2018(context: TransformationContext): (x: SourceFile return updated; } - function transformAsyncGeneratorFunctionBody(node: MethodDeclaration | AccessorDeclaration | FunctionDeclaration | FunctionExpression): FunctionBody { + function transformAsyncGeneratorFunctionBody( + node: MethodDeclaration | AccessorDeclaration | FunctionDeclaration | FunctionExpression, + ): FunctionBody { resumeLexicalEnvironment(); const statements: Statement[] = []; - const statementOffset = factory.copyPrologue(node.body!.statements, statements, /*ensureUseStrict*/ false, visitor); + const statementOffset = factory.copyPrologue( + node.body!.statements, + statements, + /*ensureUseStrict*/ false, + visitor, + ); appendObjectRestAssignmentsIfNeeded(statements, node); const savedCapturedSuperProperties = capturedSuperProperties; @@ -1163,11 +1245,19 @@ export function transformES2018(context: TransformationContext): (x: SourceFile // Minor optimization, emit `_super` helper to capture `super` access in an arrow. // This step isn't needed if we eventually transform this to ES5. - const emitSuperHelpers = languageVersion >= ScriptTarget.ES2015 && resolver.getNodeCheckFlags(node) & (NodeCheckFlags.MethodWithSuperPropertyAssignmentInAsync | NodeCheckFlags.MethodWithSuperPropertyAccessInAsync); + const emitSuperHelpers = languageVersion >= ScriptTarget.ES2015 + && resolver.getNodeCheckFlags(node) + & (NodeCheckFlags.MethodWithSuperPropertyAssignmentInAsync + | NodeCheckFlags.MethodWithSuperPropertyAccessInAsync); if (emitSuperHelpers) { enableSubstitutionForAsyncMethodsWithSuper(); - const variableStatement = createSuperAccessVariableStatement(factory, resolver, node, capturedSuperProperties); + const variableStatement = createSuperAccessVariableStatement( + factory, + resolver, + node, + capturedSuperProperties, + ); substitutedSuperAccessors[getNodeId(variableStatement)] = true; insertStatementsAfterStandardPrologue(statements, [variableStatement]); } @@ -1192,7 +1282,14 @@ export function transformES2018(context: TransformationContext): (x: SourceFile return block; } - function transformFunctionBody(node: FunctionDeclaration | FunctionExpression | ConstructorDeclaration | MethodDeclaration | AccessorDeclaration): FunctionBody; + function transformFunctionBody( + node: + | FunctionDeclaration + | FunctionExpression + | ConstructorDeclaration + | MethodDeclaration + | AccessorDeclaration, + ): FunctionBody; function transformFunctionBody(node: ArrowFunction): ConciseBody; function transformFunctionBody(node: FunctionLikeDeclaration): ConciseBody { resumeLexicalEnvironment(); @@ -1214,7 +1311,10 @@ export function transformES2018(context: TransformationContext): (x: SourceFile return body; } - function appendObjectRestAssignmentsIfNeeded(statements: Statement[] | undefined, node: FunctionLikeDeclaration): Statement[] | undefined { + function appendObjectRestAssignmentsIfNeeded( + statements: Statement[] | undefined, + node: FunctionLikeDeclaration, + ): Statement[] | undefined { let containsPrecedingObjectRestOrSpread = false; for (const parameter of node.parameters) { if (containsPrecedingObjectRestOrSpread) { @@ -1272,13 +1372,21 @@ export function transformES2018(context: TransformationContext): (x: SourceFile const block = factory.createBlock([factory.createExpressionStatement(assignment)]); setTextRange(block, parameter); - setEmitFlags(block, EmitFlags.SingleLine | EmitFlags.NoTrailingSourceMap | EmitFlags.NoTokenSourceMaps | EmitFlags.NoComments); + setEmitFlags( + block, + EmitFlags.SingleLine | EmitFlags.NoTrailingSourceMap | EmitFlags.NoTokenSourceMaps + | EmitFlags.NoComments, + ); const typeCheck = factory.createTypeCheck(factory.cloneNode(parameter.name), "undefined"); const statement = factory.createIfStatement(typeCheck, block); startOnNewLine(statement); setTextRange(statement, parameter); - setEmitFlags(statement, EmitFlags.NoTokenSourceMaps | EmitFlags.NoTrailingSourceMap | EmitFlags.CustomPrologue | EmitFlags.NoComments); + setEmitFlags( + statement, + EmitFlags.NoTokenSourceMaps | EmitFlags.NoTrailingSourceMap | EmitFlags.CustomPrologue + | EmitFlags.NoComments, + ); statements = append(statements, statement); } } @@ -1336,7 +1444,9 @@ export function transformES2018(context: TransformationContext): (x: SourceFile // If we need to support substitutions for `super` in an async method, // we should track it here. if (enabledSubstitutions & ESNextSubstitutionFlags.AsyncMethodsWithSuper && isSuperContainer(node)) { - const superContainerFlags = resolver.getNodeCheckFlags(node) & (NodeCheckFlags.MethodWithSuperPropertyAccessInAsync | NodeCheckFlags.MethodWithSuperPropertyAssignmentInAsync); + const superContainerFlags = resolver.getNodeCheckFlags(node) + & (NodeCheckFlags.MethodWithSuperPropertyAccessInAsync + | NodeCheckFlags.MethodWithSuperPropertyAssignmentInAsync); if (superContainerFlags !== enclosingSuperContainerFlags) { const savedEnclosingSuperContainerFlags = enclosingSuperContainerFlags; enclosingSuperContainerFlags = superContainerFlags; @@ -1387,7 +1497,10 @@ export function transformES2018(context: TransformationContext): (x: SourceFile if (node.expression.kind === SyntaxKind.SuperKeyword) { return setTextRange( factory.createPropertyAccessExpression( - factory.createUniqueName("_super", GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel), + factory.createUniqueName( + "_super", + GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel, + ), node.name, ), node, @@ -1433,7 +1546,10 @@ export function transformES2018(context: TransformationContext): (x: SourceFile || kind === SyntaxKind.SetAccessor; } - function createSuperElementAccessInAsyncMethod(argumentExpression: Expression, location: TextRange): LeftHandSideExpression { + function createSuperElementAccessInAsyncMethod( + argumentExpression: Expression, + location: TextRange, + ): LeftHandSideExpression { if (enclosingSuperContainerFlags & NodeCheckFlags.MethodWithSuperPropertyAssignmentInAsync) { return setTextRange( factory.createPropertyAccessExpression( diff --git a/src/compiler/transformers/es2020.ts b/src/compiler/transformers/es2020.ts index c3eb99351fde9..985fccde13555 100644 --- a/src/compiler/transformers/es2020.ts +++ b/src/compiler/transformers/es2020.ts @@ -96,17 +96,28 @@ export function transformES2020(context: TransformationContext): (x: SourceFile return { expression: chain.expression, chain: links }; } - function visitNonOptionalParenthesizedExpression(node: ParenthesizedExpression, captureThisArg: boolean, isDelete: boolean): Expression { + function visitNonOptionalParenthesizedExpression( + node: ParenthesizedExpression, + captureThisArg: boolean, + isDelete: boolean, + ): Expression { const expression = visitNonOptionalExpression(node.expression, captureThisArg, isDelete); if (isSyntheticReference(expression)) { // `(a.b)` -> { expression `((_a = a).b)`, thisArg: `_a` } // `(a[b])` -> { expression `((_a = a)[b])`, thisArg: `_a` } - return factory.createSyntheticReferenceExpression(factory.updateParenthesizedExpression(node, expression.expression), expression.thisArg); + return factory.createSyntheticReferenceExpression( + factory.updateParenthesizedExpression(node, expression.expression), + expression.thisArg, + ); } return factory.updateParenthesizedExpression(node, expression); } - function visitNonOptionalPropertyOrElementAccessExpression(node: AccessExpression, captureThisArg: boolean, isDelete: boolean): Expression { + function visitNonOptionalPropertyOrElementAccessExpression( + node: AccessExpression, + captureThisArg: boolean, + isDelete: boolean, + ): Expression { if (isOptionalChain(node)) { // If `node` is an optional chain, then it is the outermost chain of an optional expression. return visitOptionalExpression(node, captureThisArg, isDelete); @@ -128,7 +139,11 @@ export function transformES2020(context: TransformationContext): (x: SourceFile expression = node.kind === SyntaxKind.PropertyAccessExpression ? factory.updatePropertyAccessExpression(node, expression, visitNode(node.name, visitor, isIdentifier)) - : factory.updateElementAccessExpression(node, expression, visitNode(node.argumentExpression, visitor, isExpression)); + : factory.updateElementAccessExpression( + node, + expression, + visitNode(node.argumentExpression, visitor, isExpression), + ); return thisArg ? factory.createSyntheticReferenceExpression(expression, thisArg) : expression; } @@ -139,10 +154,17 @@ export function transformES2020(context: TransformationContext): (x: SourceFile } if (isParenthesizedExpression(node.expression) && isOptionalChain(skipParentheses(node.expression))) { // capture thisArg for calls of parenthesized optional chains like `(foo?.bar)()` - const expression = visitNonOptionalParenthesizedExpression(node.expression, /*captureThisArg*/ true, /*isDelete*/ false); + const expression = visitNonOptionalParenthesizedExpression( + node.expression, + /*captureThisArg*/ true, + /*isDelete*/ false, + ); const args = visitNodes(node.arguments, visitor, isExpression); if (isSyntheticReference(expression)) { - return setTextRange(factory.createFunctionCallCall(expression.expression, expression.thisArg, args), node); + return setTextRange( + factory.createFunctionCallCall(expression.expression, expression.thisArg, args), + node, + ); } return factory.updateCallExpression(node, expression, /*typeArguments*/ undefined, args); } @@ -152,10 +174,18 @@ export function transformES2020(context: TransformationContext): (x: SourceFile function visitNonOptionalExpression(node: Expression, captureThisArg: boolean, isDelete: boolean): Expression { switch (node.kind) { case SyntaxKind.ParenthesizedExpression: - return visitNonOptionalParenthesizedExpression(node as ParenthesizedExpression, captureThisArg, isDelete); + return visitNonOptionalParenthesizedExpression( + node as ParenthesizedExpression, + captureThisArg, + isDelete, + ); case SyntaxKind.PropertyAccessExpression: case SyntaxKind.ElementAccessExpression: - return visitNonOptionalPropertyOrElementAccessExpression(node as AccessExpression, captureThisArg, isDelete); + return visitNonOptionalPropertyOrElementAccessExpression( + node as AccessExpression, + captureThisArg, + isDelete, + ); case SyntaxKind.CallExpression: return visitNonOptionalCallExpression(node as CallExpression, captureThisArg); default: @@ -165,10 +195,18 @@ export function transformES2020(context: TransformationContext): (x: SourceFile function visitOptionalExpression(node: OptionalChain, captureThisArg: boolean, isDelete: boolean): Expression { const { expression, chain } = flattenChain(node); - const left = visitNonOptionalExpression(skipPartiallyEmittedExpressions(expression), isCallChain(chain[0]), /*isDelete*/ false); + const left = visitNonOptionalExpression( + skipPartiallyEmittedExpressions(expression), + isCallChain(chain[0]), + /*isDelete*/ false, + ); let leftThisArg = isSyntheticReference(left) ? left.thisArg : undefined; let capturedLeft = isSyntheticReference(left) ? left.expression : left; - let leftExpression = factory.restoreOuterExpressions(expression, capturedLeft, OuterExpressionKinds.PartiallyEmittedExpressions); + let leftExpression = factory.restoreOuterExpressions( + expression, + capturedLeft, + OuterExpressionKinds.PartiallyEmittedExpressions, + ); if (!isSimpleCopiableExpression(capturedLeft)) { capturedLeft = factory.createTempVariable(hoistVariableDeclaration); leftExpression = factory.createAssignment(capturedLeft, leftExpression); @@ -190,8 +228,14 @@ export function transformES2020(context: TransformationContext): (x: SourceFile } } rightExpression = segment.kind === SyntaxKind.PropertyAccessExpression - ? factory.createPropertyAccessExpression(rightExpression, visitNode(segment.name, visitor, isIdentifier)) - : factory.createElementAccessExpression(rightExpression, visitNode(segment.argumentExpression, visitor, isExpression)); + ? factory.createPropertyAccessExpression( + rightExpression, + visitNode(segment.name, visitor, isIdentifier), + ) + : factory.createElementAccessExpression( + rightExpression, + visitNode(segment.argumentExpression, visitor, isExpression), + ); break; case SyntaxKind.CallExpression: if (i === 0 && leftThisArg) { @@ -218,8 +262,20 @@ export function transformES2020(context: TransformationContext): (x: SourceFile } const target = isDelete - ? factory.createConditionalExpression(createNotNullCondition(leftExpression, capturedLeft, /*invert*/ true), /*questionToken*/ undefined, factory.createTrue(), /*colonToken*/ undefined, factory.createDeleteExpression(rightExpression)) - : factory.createConditionalExpression(createNotNullCondition(leftExpression, capturedLeft, /*invert*/ true), /*questionToken*/ undefined, factory.createVoidZero(), /*colonToken*/ undefined, rightExpression); + ? factory.createConditionalExpression( + createNotNullCondition(leftExpression, capturedLeft, /*invert*/ true), + /*questionToken*/ undefined, + factory.createTrue(), + /*colonToken*/ undefined, + factory.createDeleteExpression(rightExpression), + ) + : factory.createConditionalExpression( + createNotNullCondition(leftExpression, capturedLeft, /*invert*/ true), + /*questionToken*/ undefined, + factory.createVoidZero(), + /*colonToken*/ undefined, + rightExpression, + ); setTextRange(target, node); return thisArg ? factory.createSyntheticReferenceExpression(target, thisArg) : target; } @@ -228,13 +284,17 @@ export function transformES2020(context: TransformationContext): (x: SourceFile return factory.createBinaryExpression( factory.createBinaryExpression( left, - factory.createToken(invert ? SyntaxKind.EqualsEqualsEqualsToken : SyntaxKind.ExclamationEqualsEqualsToken), + factory.createToken( + invert ? SyntaxKind.EqualsEqualsEqualsToken : SyntaxKind.ExclamationEqualsEqualsToken, + ), factory.createNull(), ), factory.createToken(invert ? SyntaxKind.BarBarToken : SyntaxKind.AmpersandAmpersandToken), factory.createBinaryExpression( right, - factory.createToken(invert ? SyntaxKind.EqualsEqualsEqualsToken : SyntaxKind.ExclamationEqualsEqualsToken), + factory.createToken( + invert ? SyntaxKind.EqualsEqualsEqualsToken : SyntaxKind.ExclamationEqualsEqualsToken, + ), factory.createVoidZero(), ), ); @@ -261,7 +321,10 @@ export function transformES2020(context: TransformationContext): (x: SourceFile function visitDeleteExpression(node: DeleteExpression) { return isOptionalChain(skipParentheses(node.expression)) - ? setOriginalNode(visitNonOptionalExpression(node.expression, /*captureThisArg*/ false, /*isDelete*/ true), node) + ? setOriginalNode( + visitNonOptionalExpression(node.expression, /*captureThisArg*/ false, /*isDelete*/ true), + node, + ) : factory.updateDeleteExpression(node, visitNode(node.expression, visitor, isExpression)); } } diff --git a/src/compiler/transformers/es2021.ts b/src/compiler/transformers/es2021.ts index 08ab7af2a239b..13fc315f6d70e 100644 --- a/src/compiler/transformers/es2021.ts +++ b/src/compiler/transformers/es2021.ts @@ -47,7 +47,9 @@ export function transformES2021(context: TransformationContext): (x: SourceFile return visitEachChild(node, visitor, context); } - function transformLogicalAssignment(binaryExpression: AssignmentExpression>): VisitResult { + function transformLogicalAssignment( + binaryExpression: AssignmentExpression>, + ): VisitResult { const operator = binaryExpression.operatorToken; const nonAssignmentOperator = getNonAssignmentOperatorForCompoundAssignment(operator.kind); let left = skipParentheses(visitNode(binaryExpression.left, visitor, isLeftHandSideExpression)); @@ -56,12 +58,13 @@ export function transformES2021(context: TransformationContext): (x: SourceFile if (isAccessExpression(left)) { const propertyAccessTargetSimpleCopiable = isSimpleCopiableExpression(left.expression); - const propertyAccessTarget = propertyAccessTargetSimpleCopiable ? left.expression : - factory.createTempVariable(hoistVariableDeclaration); - const propertyAccessTargetAssignment = propertyAccessTargetSimpleCopiable ? left.expression : factory.createAssignment( - propertyAccessTarget, - left.expression, - ); + const propertyAccessTarget = propertyAccessTargetSimpleCopiable ? left.expression + : factory.createTempVariable(hoistVariableDeclaration); + const propertyAccessTargetAssignment = propertyAccessTargetSimpleCopiable ? left.expression + : factory.createAssignment( + propertyAccessTarget, + left.expression, + ); if (isPropertyAccessExpression(left)) { assignmentTarget = factory.createPropertyAccessExpression( @@ -75,8 +78,8 @@ export function transformES2021(context: TransformationContext): (x: SourceFile } else { const elementAccessArgumentSimpleCopiable = isSimpleCopiableExpression(left.argumentExpression); - const elementAccessArgument = elementAccessArgumentSimpleCopiable ? left.argumentExpression : - factory.createTempVariable(hoistVariableDeclaration); + const elementAccessArgument = elementAccessArgumentSimpleCopiable ? left.argumentExpression + : factory.createTempVariable(hoistVariableDeclaration); assignmentTarget = factory.createElementAccessExpression( propertyAccessTarget, diff --git a/src/compiler/transformers/esDecorators.ts b/src/compiler/transformers/esDecorators.ts index a356421c191ae..ad12a937a5085 100644 --- a/src/compiler/transformers/esDecorators.ts +++ b/src/compiler/transformers/esDecorators.ts @@ -343,14 +343,22 @@ export function transformESDecorators(context: TransformationContext): (x: Sourc } function exitClass() { - Debug.assert(top?.kind === "class", "Incorrect value for top.kind.", () => `Expected top.kind to be 'class' but got '${top?.kind}' instead.`); + Debug.assert( + top?.kind === "class", + "Incorrect value for top.kind.", + () => `Expected top.kind to be 'class' but got '${top?.kind}' instead.`, + ); pendingExpressions = top.savedPendingExpressions; top = top.next; updateState(); } function enterClassElement(node: ClassElement) { - Debug.assert(top?.kind === "class", "Incorrect value for top.kind.", () => `Expected top.kind to be 'class' but got '${top?.kind}' instead.`); + Debug.assert( + top?.kind === "class", + "Incorrect value for top.kind.", + () => `Expected top.kind to be 'class' but got '${top?.kind}' instead.`, + ); top = { kind: "class-element", next: top }; if (isClassStaticBlockDeclaration(node) || isPropertyDeclaration(node) && hasStaticModifier(node)) { top.classThis = top.next.classInfo?.classThis; @@ -360,20 +368,36 @@ export function transformESDecorators(context: TransformationContext): (x: Sourc } function exitClassElement() { - Debug.assert(top?.kind === "class-element", "Incorrect value for top.kind.", () => `Expected top.kind to be 'class-element' but got '${top?.kind}' instead.`); - Debug.assert(top.next?.kind === "class", "Incorrect value for top.next.kind.", () => `Expected top.next.kind to be 'class' but got '${top!.next?.kind}' instead.`); + Debug.assert( + top?.kind === "class-element", + "Incorrect value for top.kind.", + () => `Expected top.kind to be 'class-element' but got '${top?.kind}' instead.`, + ); + Debug.assert( + top.next?.kind === "class", + "Incorrect value for top.next.kind.", + () => `Expected top.next.kind to be 'class' but got '${top!.next?.kind}' instead.`, + ); top = top.next; updateState(); } function enterName() { - Debug.assert(top?.kind === "class-element", "Incorrect value for top.kind.", () => `Expected top.kind to be 'class-element' but got '${top?.kind}' instead.`); + Debug.assert( + top?.kind === "class-element", + "Incorrect value for top.kind.", + () => `Expected top.kind to be 'class-element' but got '${top?.kind}' instead.`, + ); top = { kind: "name", next: top }; updateState(); } function exitName() { - Debug.assert(top?.kind === "name", "Incorrect value for top.kind.", () => `Expected top.kind to be 'name' but got '${top?.kind}' instead.`); + Debug.assert( + top?.kind === "name", + "Incorrect value for top.kind.", + () => `Expected top.kind to be 'name' but got '${top?.kind}' instead.`, + ); top = top.next; updateState(); } @@ -391,7 +415,11 @@ export function transformESDecorators(context: TransformationContext): (x: Sourc } function exitOther() { - Debug.assert(top?.kind === "other", "Incorrect value for top.kind.", () => `Expected top.kind to be 'other' but got '${top?.kind}' instead.`); + Debug.assert( + top?.kind === "other", + "Incorrect value for top.kind.", + () => `Expected top.kind to be 'other' but got '${top?.kind}' instead.`, + ); if (top.depth > 0) { Debug.assert(!pendingExpressions); top.depth--; @@ -457,7 +485,10 @@ export function transformESDecorators(context: TransformationContext): (x: Sourc return visitTaggedTemplateExpression(node as TaggedTemplateExpression); case SyntaxKind.PrefixUnaryExpression: case SyntaxKind.PostfixUnaryExpression: - return visitPreOrPostfixUnaryExpression(node as PrefixUnaryExpression | PostfixUnaryExpression, /*discarded*/ false); + return visitPreOrPostfixUnaryExpression( + node as PrefixUnaryExpression | PostfixUnaryExpression, + /*discarded*/ false, + ); case SyntaxKind.PropertyAccessExpression: return visitPropertyAccessExpression(node as PropertyAccessExpression); case SyntaxKind.ElementAccessExpression: @@ -522,7 +553,10 @@ export function transformESDecorators(context: TransformationContext): (x: Sourc switch (node.kind) { case SyntaxKind.PrefixUnaryExpression: case SyntaxKind.PostfixUnaryExpression: - return visitPreOrPostfixUnaryExpression(node as PrefixUnaryExpression | PostfixUnaryExpression, /*discarded*/ true); + return visitPreOrPostfixUnaryExpression( + node as PrefixUnaryExpression | PostfixUnaryExpression, + /*discarded*/ true, + ); case SyntaxKind.BinaryExpression: return visitBinaryExpression(node as BinaryExpression, /*discarded*/ true); case SyntaxKind.CommaListExpression: @@ -535,10 +569,13 @@ export function transformESDecorators(context: TransformationContext): (x: Sourc } function getHelperVariableName(node: ClassLikeDeclaration | ClassElement) { - let declarationName = node.name && isIdentifier(node.name) && !isGeneratedIdentifier(node.name) ? idText(node.name) : - node.name && isPrivateIdentifier(node.name) && !isGeneratedIdentifier(node.name) ? idText(node.name).slice(1) : - node.name && isStringLiteral(node.name) && isIdentifierText(node.name.text, ScriptTarget.ESNext) ? node.name.text : - isClassLike(node) ? "class" : "member"; + let declarationName = node.name && isIdentifier(node.name) && !isGeneratedIdentifier(node.name) + ? idText(node.name) + : node.name && isPrivateIdentifier(node.name) && !isGeneratedIdentifier(node.name) + ? idText(node.name).slice(1) + : node.name && isStringLiteral(node.name) && isIdentifierText(node.name.text, ScriptTarget.ESNext) + ? node.name.text + : isClassLike(node) ? "class" : "member"; if (isGetAccessor(node)) declarationName = `get_${declarationName}`; if (isSetAccessor(node)) declarationName = `set_${declarationName}`; if (node.name && isPrivateIdentifier(node.name)) declarationName = `private_${declarationName}`; @@ -547,7 +584,10 @@ export function transformESDecorators(context: TransformationContext): (x: Sourc } function createHelperVariable(node: ClassLikeDeclaration | ClassElement, suffix: string) { - return factory.createUniqueName(`${getHelperVariableName(node)}_${suffix}`, GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.ReservedInNestedScopes); + return factory.createUniqueName( + `${getHelperVariableName(node)}_${suffix}`, + GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.ReservedInNestedScopes, + ); } function createLet(name: Identifier, initializer?: Expression) { @@ -565,7 +605,10 @@ export function transformESDecorators(context: TransformationContext): (x: Sourc } function createClassInfo(node: ClassLikeDeclaration): ClassInfo { - const metadataReference = factory.createUniqueName("_metadata", GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel); + const metadataReference = factory.createUniqueName( + "_metadata", + GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel, + ); let instanceExtraInitializersName: Identifier | undefined; let staticExtraInitializersName: Identifier | undefined; let hasStaticInitializers = false; @@ -578,10 +621,16 @@ export function transformESDecorators(context: TransformationContext): (x: Sourc for (const member of node.members) { if (isNamedClassElement(member) && nodeOrChildIsDecorated(/*useLegacyDecorators*/ false, member, node)) { if (hasStaticModifier(member)) { - staticExtraInitializersName ??= factory.createUniqueName("_staticExtraInitializers", GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel); + staticExtraInitializersName ??= factory.createUniqueName( + "_staticExtraInitializers", + GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel, + ); } else { - instanceExtraInitializersName ??= factory.createUniqueName("_instanceExtraInitializers", GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel); + instanceExtraInitializersName ??= factory.createUniqueName( + "_instanceExtraInitializers", + GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel, + ); } } if (isClassStaticBlockDeclaration(member)) { @@ -598,17 +647,20 @@ export function transformESDecorators(context: TransformationContext): (x: Sourc } } - if ((isPrivateIdentifierClassElementDeclaration(member) || isAutoAccessorPropertyDeclaration(member)) && hasStaticModifier(member)) { + if ( + (isPrivateIdentifierClassElementDeclaration(member) || isAutoAccessorPropertyDeclaration(member)) + && hasStaticModifier(member) + ) { hasStaticPrivateClassElements = true; } // exit early if possible if ( - staticExtraInitializersName && - instanceExtraInitializersName && - hasStaticInitializers && - hasNonAmbientInstanceFields && - hasStaticPrivateClassElements + staticExtraInitializersName + && instanceExtraInitializersName + && hasStaticInitializers + && hasNonAmbientInstanceFields + && hasStaticPrivateClassElements ) { break; } @@ -630,11 +682,19 @@ export function transformESDecorators(context: TransformationContext): (x: Sourc // When a class has class decorators we end up transforming it into a statement that would otherwise give it an // assigned name. If the class doesn't have an assigned name, we'll give it an assigned name of `""`) - if (!classHasDeclaredOrExplicitlyAssignedName(node) && classOrConstructorParameterIsDecorated(/*useLegacyDecorators*/ false, node)) { + if ( + !classHasDeclaredOrExplicitlyAssignedName(node) + && classOrConstructorParameterIsDecorated(/*useLegacyDecorators*/ false, node) + ) { node = injectClassNamedEvaluationHelperBlockIfMissing(context, node, factory.createStringLiteral("")); } - const classReference = factory.getLocalName(node, /*allowComments*/ false, /*allowSourceMaps*/ false, /*ignoreAssignedName*/ true); + const classReference = factory.getLocalName( + node, + /*allowComments*/ false, + /*allowSourceMaps*/ false, + /*ignoreAssignedName*/ true, + ); const classInfo = createClassInfo(node); const classDefinitionStatements: Statement[] = []; let leadingBlockStatements: Statement[] | undefined; @@ -652,17 +712,31 @@ export function transformESDecorators(context: TransformationContext): (x: Sourc // of the mutated class. // - Since a class decorator can add extra initializers, we must define a variable to keep track of // extra initializers. - classInfo.classDecoratorsName = factory.createUniqueName("_classDecorators", GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel); - classInfo.classDescriptorName = factory.createUniqueName("_classDescriptor", GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel); - classInfo.classExtraInitializersName = factory.createUniqueName("_classExtraInitializers", GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel); + classInfo.classDecoratorsName = factory.createUniqueName( + "_classDecorators", + GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel, + ); + classInfo.classDescriptorName = factory.createUniqueName( + "_classDescriptor", + GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel, + ); + classInfo.classExtraInitializersName = factory.createUniqueName( + "_classExtraInitializers", + GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel, + ); // We do not mark _classThis as FileLevel if it may be reused by class private fields, which requires the // ability access the captured `_classThis` of outer scopes. - const needsUniqueClassThis = some(node.members, member => (isPrivateIdentifierClassElementDeclaration(member) || isAutoAccessorPropertyDeclaration(member)) && hasStaticModifier(member)); + const needsUniqueClassThis = some( + node.members, + member => + (isPrivateIdentifierClassElementDeclaration(member) || isAutoAccessorPropertyDeclaration(member)) + && hasStaticModifier(member), + ); classInfo.classThis = factory.createUniqueName( "_classThis", - needsUniqueClassThis ? - GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.ReservedInNestedScopes : - GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel, + needsUniqueClassThis + ? GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.ReservedInNestedScopes + : GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel, ); classDefinitionStatements.push( createLet(classInfo.classDecoratorsName, factory.createArrayLiteralExpression(classDecorators)), @@ -682,18 +756,25 @@ export function transformESDecorators(context: TransformationContext): (x: Sourc const extendsElement = extendsClause && firstOrUndefined(extendsClause.types); const extendsExpression = extendsElement && visitNode(extendsElement.expression, visitor, isExpression); if (extendsExpression) { - classInfo.classSuper = factory.createUniqueName("_classSuper", GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel); + classInfo.classSuper = factory.createUniqueName( + "_classSuper", + GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel, + ); // Ensure we do not give the class or function an assigned name due to the variable by prefixing it // with `0, `. const unwrapped = skipOuterExpressions(extendsExpression); - const safeExtendsExpression = isClassExpression(unwrapped) && !unwrapped.name || - isFunctionExpression(unwrapped) && !unwrapped.name || - isArrowFunction(unwrapped) ? - factory.createComma(factory.createNumericLiteral(0), extendsExpression) : - extendsExpression; + const safeExtendsExpression = isClassExpression(unwrapped) && !unwrapped.name + || isFunctionExpression(unwrapped) && !unwrapped.name + || isArrowFunction(unwrapped) + ? factory.createComma(factory.createNumericLiteral(0), extendsExpression) + : extendsExpression; classDefinitionStatements.push(createLet(classInfo.classSuper, safeExtendsExpression)); - const updatedExtendsElement = factory.updateExpressionWithTypeArguments(extendsElement, classInfo.classSuper, /*typeArguments*/ undefined); + const updatedExtendsElement = factory.updateExpressionWithTypeArguments( + extendsElement, + classInfo.classSuper, + /*typeArguments*/ undefined, + ); const updatedExtendsClause = factory.updateHeritageClause(extendsClause, [updatedExtendsElement]); heritageClauses = factory.createNodeArray([updatedExtendsClause]); } @@ -716,7 +797,10 @@ export function transformESDecorators(context: TransformationContext): (x: Sourc // NOTE: If there are no constructors, but there are instance initializers, a synthetic constructor is added. enterClass(classInfo); - leadingBlockStatements = append(leadingBlockStatements, createMetadata(classInfo.metadataReference, classInfo.classSuper)); + leadingBlockStatements = append( + leadingBlockStatements, + createMetadata(classInfo.metadataReference, classInfo.classSuper), + ); let members = visitNodes(node.members, classElementVisitor, isClassElement); if (pendingExpressions) { @@ -755,18 +839,25 @@ export function transformESDecorators(context: TransformationContext): (x: Sourc const initializerStatements = prepareConstructor(node, classInfo); if (initializerStatements) { const extendsClauseElement = getEffectiveBaseTypeNode(node); - const isDerivedClass = !!(extendsClauseElement && skipOuterExpressions(extendsClauseElement.expression).kind !== SyntaxKind.NullKeyword); + const isDerivedClass = !!(extendsClauseElement + && skipOuterExpressions(extendsClauseElement.expression).kind !== SyntaxKind.NullKeyword); const constructorStatements: Statement[] = []; if (isDerivedClass) { const spreadArguments = factory.createSpreadElement(factory.createIdentifier("arguments")); - const superCall = factory.createCallExpression(factory.createSuper(), /*typeArguments*/ undefined, [spreadArguments]); + const superCall = factory.createCallExpression(factory.createSuper(), /*typeArguments*/ undefined, [ + spreadArguments, + ]); constructorStatements.push(factory.createExpressionStatement(superCall)); } addRange(constructorStatements, initializerStatements); const constructorBody = factory.createBlock(constructorStatements, /*multiLine*/ true); - syntheticConstructor = factory.createConstructorDeclaration(/*modifiers*/ undefined, [], constructorBody); + syntheticConstructor = factory.createConstructorDeclaration( + /*modifiers*/ undefined, + [], + constructorBody, + ); } } @@ -790,7 +881,9 @@ export function transformESDecorators(context: TransformationContext): (x: Sourc if (isStatic(member)) { classDefinitionStatements.push(createLet(memberInfo.memberDecoratorsName)); if (memberInfo.memberInitializersName) { - classDefinitionStatements.push(createLet(memberInfo.memberInitializersName, factory.createArrayLiteralExpression())); + classDefinitionStatements.push( + createLet(memberInfo.memberInitializersName, factory.createArrayLiteralExpression()), + ); } if (memberInfo.memberDescriptorName) { classDefinitionStatements.push(createLet(memberInfo.memberDescriptorName)); @@ -805,7 +898,9 @@ export function transformESDecorators(context: TransformationContext): (x: Sourc if (!isStatic(member)) { classDefinitionStatements.push(createLet(memberInfo.memberDecoratorsName)); if (memberInfo.memberInitializersName) { - classDefinitionStatements.push(createLet(memberInfo.memberInitializersName, factory.createArrayLiteralExpression())); + classDefinitionStatements.push( + createLet(memberInfo.memberInitializersName, factory.createArrayLiteralExpression()), + ); } if (memberInfo.memberDescriptorName) { classDefinitionStatements.push(createLet(memberInfo.memberDescriptorName)); @@ -828,7 +923,10 @@ export function transformESDecorators(context: TransformationContext): (x: Sourc // 9. Class decorators are applied // 10. Class binding is initialized - if (classInfo.classDescriptorName && classInfo.classDecoratorsName && classInfo.classExtraInitializersName && classInfo.classThis) { + if ( + classInfo.classDescriptorName && classInfo.classDecoratorsName && classInfo.classExtraInitializersName + && classInfo.classThis + ) { leadingBlockStatements ??= []; // produces: @@ -851,7 +949,10 @@ export function transformESDecorators(context: TransformationContext): (x: Sourc // produces: // C = _classThis = _classDescriptor.value; - const classDescriptorValueReference = factory.createPropertyAccessExpression(classInfo.classDescriptorName, "value"); + const classDescriptorValueReference = factory.createPropertyAccessExpression( + classInfo.classDescriptorName, + "value", + ); const classThisAssignment = factory.createAssignment(classInfo.classThis, classDescriptorValueReference); const classReferenceAssignment = factory.createAssignment(classReference, classThisAssignment); leadingBlockStatements.push(factory.createExpressionStatement(classReferenceAssignment)); @@ -862,7 +963,10 @@ export function transformESDecorators(context: TransformationContext): (x: Sourc // 11. Static extra initializers are evaluated if (classInfo.staticExtraInitializersName) { - const runStaticInitializersHelper = emitHelpers().createRunInitializersHelper(renamedClassThis, classInfo.staticExtraInitializersName); + const runStaticInitializersHelper = emitHelpers().createRunInitializersHelper( + renamedClassThis, + classInfo.staticExtraInitializersName, + ); const runStaticInitializersStatement = factory.createExpressionStatement(runStaticInitializersHelper); setSourceMapRange(runStaticInitializersStatement, node.name ?? moveRangePastDecorators(node)); leadingBlockStatements = append(leadingBlockStatements, runStaticInitializersStatement); @@ -872,7 +976,10 @@ export function transformESDecorators(context: TransformationContext): (x: Sourc // 13. Class extra initializers are evaluated if (classInfo.classExtraInitializersName) { - const runClassInitializersHelper = emitHelpers().createRunInitializersHelper(renamedClassThis, classInfo.classExtraInitializersName); + const runClassInitializersHelper = emitHelpers().createRunInitializersHelper( + renamedClassThis, + classInfo.classExtraInitializersName, + ); const runClassInitializersStatement = factory.createExpressionStatement(runClassInitializersHelper); setSourceMapRange(runClassInitializersStatement, node.name ?? moveRangePastDecorators(node)); trailingBlockStatements = append(trailingBlockStatements, runClassInitializersStatement); @@ -891,8 +998,10 @@ export function transformESDecorators(context: TransformationContext): (x: Sourc // static { ... } // ... // } - const leadingStaticBlock = leadingBlockStatements && - factory.createClassStaticBlockDeclaration(factory.createBlock(leadingBlockStatements, /*multiLine*/ true)); + const leadingStaticBlock = leadingBlockStatements + && factory.createClassStaticBlockDeclaration( + factory.createBlock(leadingBlockStatements, /*multiLine*/ true), + ); if (leadingStaticBlock && shouldTransformPrivateStaticElementsInClass) { // We use `InternalEmitFlags.TransformPrivateStaticElements` as a marker on a class static block @@ -908,8 +1017,10 @@ export function transformESDecorators(context: TransformationContext): (x: Sourc // ... // static { ... } // } - const trailingStaticBlock = trailingBlockStatements && - factory.createClassStaticBlockDeclaration(factory.createBlock(trailingBlockStatements, /*multiLine*/ true)); + const trailingStaticBlock = trailingBlockStatements + && factory.createClassStaticBlockDeclaration( + factory.createBlock(trailingBlockStatements, /*multiLine*/ true), + ); if (leadingStaticBlock || syntheticConstructor || trailingStaticBlock) { const newMembers: ClassElement[] = []; @@ -967,14 +1078,26 @@ export function transformESDecorators(context: TransformationContext): (x: Sourc // return C; // })(); - classExpression = factory.createClassExpression(/*modifiers*/ undefined, /*name*/ undefined, /*typeParameters*/ undefined, heritageClauses, members); + classExpression = factory.createClassExpression( + /*modifiers*/ undefined, + /*name*/ undefined, + /*typeParameters*/ undefined, + heritageClauses, + members, + ); if (classInfo.classThis) { classExpression = injectClassThisAssignmentIfMissing(factory, classExpression, classInfo.classThis); } - const classReferenceDeclaration = factory.createVariableDeclaration(classReference, /*exclamationToken*/ undefined, /*type*/ undefined, classExpression); + const classReferenceDeclaration = factory.createVariableDeclaration( + classReference, + /*exclamationToken*/ undefined, + /*type*/ undefined, + classExpression, + ); const classReferenceVarDeclList = factory.createVariableDeclarationList([classReferenceDeclaration]); - const returnExpr = classInfo.classThis ? factory.createAssignment(classReference, classInfo.classThis) : classReference; + const returnExpr = classInfo.classThis ? factory.createAssignment(classReference, classInfo.classThis) + : classReference; classDefinitionStatements.push( factory.createVariableStatement(/*modifiers*/ undefined, classReferenceVarDeclList), factory.createReturnStatement(returnExpr), @@ -983,33 +1106,45 @@ export function transformESDecorators(context: TransformationContext): (x: Sourc else { // produces: // return ; - classExpression = factory.createClassExpression(/*modifiers*/ undefined, node.name, /*typeParameters*/ undefined, heritageClauses, members); + classExpression = factory.createClassExpression( + /*modifiers*/ undefined, + node.name, + /*typeParameters*/ undefined, + heritageClauses, + members, + ); classDefinitionStatements.push(factory.createReturnStatement(classExpression)); } if (shouldTransformPrivateStaticElementsInClass) { addInternalEmitFlags(classExpression, InternalEmitFlags.TransformPrivateStaticElements); for (const member of classExpression.members) { - if ((isPrivateIdentifierClassElementDeclaration(member) || isAutoAccessorPropertyDeclaration(member)) && hasStaticModifier(member)) { + if ( + (isPrivateIdentifierClassElementDeclaration(member) || isAutoAccessorPropertyDeclaration(member)) + && hasStaticModifier(member) + ) { addInternalEmitFlags(member, InternalEmitFlags.TransformPrivateStaticElements); } } } setOriginalNode(classExpression, node); - return factory.createImmediatelyInvokedArrowFunction(factory.mergeLexicalEnvironment(classDefinitionStatements, lexicalEnvironment)); + return factory.createImmediatelyInvokedArrowFunction( + factory.mergeLexicalEnvironment(classDefinitionStatements, lexicalEnvironment), + ); } function isDecoratedClassLike(node: ClassLikeDeclaration) { - return classOrConstructorParameterIsDecorated(/*useLegacyDecorators*/ false, node) || - childIsDecorated(/*useLegacyDecorators*/ false, node); + return classOrConstructorParameterIsDecorated(/*useLegacyDecorators*/ false, node) + || childIsDecorated(/*useLegacyDecorators*/ false, node); } function visitClassDeclaration(node: ClassDeclaration): VisitResult { if (isDecoratedClassLike(node)) { const statements: Statement[] = []; const originalClass = getOriginalNode(node, isClassLike) ?? node; - const className = originalClass.name ? factory.createStringLiteralFromNode(originalClass.name) : factory.createStringLiteral("default"); + const className = originalClass.name ? factory.createStringLiteralFromNode(originalClass.name) + : factory.createStringLiteral("default"); const isExport = hasSyntacticModifier(node, ModifierFlags.Export); const isDefault = hasSyntacticModifier(node, ModifierFlags.Default); if (!node.name) { @@ -1020,7 +1155,12 @@ export function transformESDecorators(context: TransformationContext): (x: Sourc if (node.name) { // let C = (() => { ... })(); // export default C; - const varDecl = factory.createVariableDeclaration(factory.getLocalName(node), /*exclamationToken*/ undefined, /*type*/ undefined, iife); + const varDecl = factory.createVariableDeclaration( + factory.getLocalName(node), + /*exclamationToken*/ undefined, + /*type*/ undefined, + iife, + ); setOriginalNode(varDecl, node); const varDecls = factory.createVariableDeclarationList([varDecl], NodeFlags.Let); @@ -1046,10 +1186,16 @@ export function transformESDecorators(context: TransformationContext): (x: Sourc // let C = (() => { ... })(); Debug.assertIsDefined(node.name, "A class declaration that is not a default export must have a name."); const iife = transformClassLike(node); - const modifierVisitorNoExport = isExport ? ((node: ModifierLike) => isExportModifier(node) ? undefined : modifierVisitor(node)) : modifierVisitor; + const modifierVisitorNoExport = isExport ? ((node: ModifierLike) => + isExportModifier(node) ? undefined : modifierVisitor(node)) : modifierVisitor; const modifiers = visitNodes(node.modifiers, modifierVisitorNoExport, isModifier); const declName = factory.getLocalName(node, /*allowComments*/ false, /*allowSourceMaps*/ true); - const varDecl = factory.createVariableDeclaration(declName, /*exclamationToken*/ undefined, /*type*/ undefined, iife); + const varDecl = factory.createVariableDeclaration( + declName, + /*exclamationToken*/ undefined, + /*type*/ undefined, + iife, + ); setOriginalNode(varDecl, node); const varDecls = factory.createVariableDeclarationList([varDecl], NodeFlags.Let); @@ -1072,7 +1218,14 @@ export function transformESDecorators(context: TransformationContext): (x: Sourc enterClass(/*classInfo*/ undefined); const members = visitNodes(node.members, classElementVisitor, isClassElement); exitClass(); - return factory.updateClassDeclaration(node, modifiers, node.name, /*typeParameters*/ undefined, heritageClauses, members); + return factory.updateClassDeclaration( + node, + modifiers, + node.name, + /*typeParameters*/ undefined, + heritageClauses, + members, + ); } } @@ -1088,7 +1241,14 @@ export function transformESDecorators(context: TransformationContext): (x: Sourc enterClass(/*classInfo*/ undefined); const members = visitNodes(node.members, classElementVisitor, isClassElement); exitClass(); - return factory.updateClassExpression(node, modifiers, node.name, /*typeParameters*/ undefined, heritageClauses, members); + return factory.updateClassExpression( + node, + modifiers, + node.name, + /*typeParameters*/ undefined, + heritageClauses, + members, + ); } } @@ -1115,10 +1275,20 @@ export function transformESDecorators(context: TransformationContext): (x: Sourc } } - function transformConstructorBodyWorker(statementsOut: Statement[], statementsIn: NodeArray, statementOffset: number, superPath: readonly number[], superPathDepth: number, initializerStatements: readonly Statement[]) { + function transformConstructorBodyWorker( + statementsOut: Statement[], + statementsIn: NodeArray, + statementOffset: number, + superPath: readonly number[], + superPathDepth: number, + initializerStatements: readonly Statement[], + ) { const superStatementIndex = superPath[superPathDepth]; const superStatement = statementsIn[superStatementIndex]; - addRange(statementsOut, visitNodes(statementsIn, visitor, isStatement, statementOffset, superStatementIndex - statementOffset)); + addRange( + statementsOut, + visitNodes(statementsIn, visitor, isStatement, statementOffset, superStatementIndex - statementOffset), + ); if (isTryStatement(superStatement)) { const tryBlockStatements: Statement[] = []; @@ -1159,10 +1329,22 @@ export function transformESDecorators(context: TransformationContext): (x: Sourc const initializerStatements = prepareConstructor(classInfo.class, classInfo); if (initializerStatements) { const statements: Statement[] = []; - const nonPrologueStart = factory.copyPrologue(node.body.statements, statements, /*ensureUseStrict*/ false, visitor); + const nonPrologueStart = factory.copyPrologue( + node.body.statements, + statements, + /*ensureUseStrict*/ false, + visitor, + ); const superStatementIndices = findSuperStatementIndexPath(node.body.statements, nonPrologueStart); if (superStatementIndices.length > 0) { - transformConstructorBodyWorker(statements, node.body.statements, nonPrologueStart, superStatementIndices, 0, initializerStatements); + transformConstructorBodyWorker( + statements, + node.body.statements, + nonPrologueStart, + superStatementIndices, + 0, + initializerStatements, + ); } else { addRange(statements, initializerStatements); @@ -1194,7 +1376,10 @@ export function transformESDecorators(context: TransformationContext): (x: Sourc >( member: TNode, classInfo: ClassInfo | undefined, - createDescriptor?: (node: TNode & { readonly name: PrivateIdentifier; }, modifiers: ModifiersArray | undefined) => Expression, + createDescriptor?: ( + node: TNode & { readonly name: PrivateIdentifier; }, + modifiers: ModifiersArray | undefined, + ) => Expression, ) { let referencedName: Expression | undefined; let name: PropertyName | undefined; @@ -1212,7 +1397,9 @@ export function transformESDecorators(context: TransformationContext): (x: Sourc // Member decorators require privileged access to private names. However, computed property // evaluation occurs interspersed with decorator evaluation. This means that if we encounter // a computed property name we must inline decorator evaluation. - const memberDecorators = transformAllDecoratorsOfDeclaration(getAllDecoratorsOfClassElement(member, classInfo.class, /*useLegacyDecorators*/ false)); + const memberDecorators = transformAllDecoratorsOfDeclaration( + getAllDecoratorsOfClassElement(member, classInfo.class, /*useLegacyDecorators*/ false), + ); const modifiers = visitNodes(member.modifiers, modifierVisitor, isModifier); if (memberDecorators) { @@ -1229,22 +1416,22 @@ export function transformESDecorators(context: TransformationContext): (x: Sourc // 6. Non-static non-field (method/getter/setter/auto-accessor) element decorators are applied // 7. Static field (excl. auto-accessor) element decorators are applied // 8. Non-static field (excl. auto-accessor) element decorators are applied - const statements = isMethodOrAccessor(member) || isAutoAccessorPropertyDeclaration(member) ? - isStatic(member) ? - classInfo.staticNonFieldDecorationStatements ??= [] : - classInfo.nonStaticNonFieldDecorationStatements ??= [] : - isPropertyDeclaration(member) && !isAutoAccessorPropertyDeclaration(member) ? - isStatic(member) ? - classInfo.staticFieldDecorationStatements ??= [] : - classInfo.nonStaticFieldDecorationStatements ??= [] : - Debug.fail(); - - const kind = isGetAccessorDeclaration(member) ? "getter" : - isSetAccessorDeclaration(member) ? "setter" : - isMethodDeclaration(member) ? "method" : - isAutoAccessorPropertyDeclaration(member) ? "accessor" : - isPropertyDeclaration(member) ? "field" : - Debug.fail(); + const statements = isMethodOrAccessor(member) || isAutoAccessorPropertyDeclaration(member) + ? isStatic(member) + ? classInfo.staticNonFieldDecorationStatements ??= [] + : classInfo.nonStaticNonFieldDecorationStatements ??= [] + : isPropertyDeclaration(member) && !isAutoAccessorPropertyDeclaration(member) + ? isStatic(member) + ? classInfo.staticFieldDecorationStatements ??= [] + : classInfo.nonStaticFieldDecorationStatements ??= [] + : Debug.fail(); + + const kind = isGetAccessorDeclaration(member) ? "getter" + : isSetAccessorDeclaration(member) ? "setter" + : isMethodDeclaration(member) ? "method" + : isAutoAccessorPropertyDeclaration(member) ? "accessor" + : isPropertyDeclaration(member) ? "field" + : Debug.fail(); let propertyName: ESDecorateName; if (isIdentifier(member.name) || isPrivateIdentifier(member.name)) { @@ -1274,16 +1461,23 @@ export function transformESDecorators(context: TransformationContext): (x: Sourc access: { // 15.7.3 CreateDecoratorAccessObject (kind, name) // 2. If _kind_ is ~field~, ~method~, ~accessor~, or ~getter~, then ... - get: isPropertyDeclaration(member) || isGetAccessorDeclaration(member) || isMethodDeclaration(member), + get: isPropertyDeclaration(member) || isGetAccessorDeclaration(member) + || isMethodDeclaration(member), // 3. If _kind_ is ~field~, ~accessor~, or ~setter~, then ... set: isPropertyDeclaration(member) || isSetAccessorDeclaration(member), }, metadata: classInfo.metadataReference, }; - const extraInitializers = isStatic(member) ? - classInfo.staticExtraInitializersName ??= factory.createUniqueName("_staticExtraInitializers", GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel) : - classInfo.instanceExtraInitializersName ??= factory.createUniqueName("_instanceExtraInitializers", GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel); + const extraInitializers = isStatic(member) + ? classInfo.staticExtraInitializersName ??= factory.createUniqueName( + "_staticExtraInitializers", + GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel, + ) + : classInfo.instanceExtraInitializersName ??= factory.createUniqueName( + "_instanceExtraInitializers", + GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel, + ); if (isMethodOrAccessor(member)) { // __esDecorate(this, null, _static_member_decorators, { kind: "method", name: "...", static: true, private: false, access: { ... } }, _staticExtraInitializers); @@ -1302,12 +1496,22 @@ export function transformESDecorators(context: TransformationContext): (x: Sourc let descriptor: Expression | undefined; if (isPrivateIdentifierClassElementDeclaration(member) && createDescriptor) { - descriptor = createDescriptor(member, visitNodes(modifiers, node => tryCast(node, isAsyncModifier), isModifier)); + descriptor = createDescriptor( + member, + visitNodes(modifiers, node => tryCast(node, isAsyncModifier), isModifier), + ); memberInfo.memberDescriptorName = descriptorName = createHelperVariable(member, "descriptor"); descriptor = factory.createAssignment(descriptorName, descriptor); } - const esDecorateExpression = emitHelpers().createESDecorateHelper(factory.createThis(), descriptor ?? factory.createNull(), memberDecoratorsName, context, factory.createNull(), extraInitializers); + const esDecorateExpression = emitHelpers().createESDecorateHelper( + factory.createThis(), + descriptor ?? factory.createNull(), + memberDecoratorsName, + context, + factory.createNull(), + extraInitializers, + ); const esDecorateStatement = factory.createExpressionStatement(esDecorateExpression); setSourceMapRange(esDecorateStatement, moveRangePastDecorators(member)); statements.push(esDecorateStatement); @@ -1320,7 +1524,10 @@ export function transformESDecorators(context: TransformationContext): (x: Sourc } let descriptor: Expression | undefined; - if (isPrivateIdentifierClassElementDeclaration(member) && hasAccessorModifier(member) && createDescriptor) { + if ( + isPrivateIdentifierClassElementDeclaration(member) && hasAccessorModifier(member) + && createDescriptor + ) { descriptor = createDescriptor(member, /*modifiers*/ undefined); memberInfo.memberDescriptorName = descriptorName = createHelperVariable(member, "descriptor"); descriptor = factory.createAssignment(descriptorName, descriptor); @@ -1329,9 +1536,9 @@ export function transformESDecorators(context: TransformationContext): (x: Sourc // _static_field_initializers = __esDecorate(null, null, _static_member_decorators, { kind: "field", name: "...", static: true, private: ..., access: { ... } }, _staticExtraInitializers); // _field_initializers = __esDecorate(null, null, _member_decorators, { kind: "field", name: "...", static: false, private: ..., access: { ... } }, _instanceExtraInitializers); const esDecorateExpression = emitHelpers().createESDecorateHelper( - isAutoAccessorPropertyDeclaration(member) ? - factory.createThis() : - factory.createNull(), + isAutoAccessorPropertyDeclaration(member) + ? factory.createThis() + : factory.createNull(), descriptor ?? factory.createNull(), memberDecoratorsName, context, @@ -1361,7 +1568,11 @@ export function transformESDecorators(context: TransformationContext): (x: Sourc function visitMethodDeclaration(node: MethodDeclaration) { enterClassElement(node); - const { modifiers, name, descriptorName } = partialTransformClassElement(node, classInfo, createMethodDescriptorObject); + const { modifiers, name, descriptorName } = partialTransformClassElement( + node, + classInfo, + createMethodDescriptorObject, + ); if (descriptorName) { exitClassElement(); return finishClassElement(createMethodDescriptorForwarder(modifiers, name, descriptorName), node); @@ -1370,13 +1581,30 @@ export function transformESDecorators(context: TransformationContext): (x: Sourc const parameters = visitNodes(node.parameters, visitor, isParameter); const body = visitNode(node.body, visitor, isBlock); exitClassElement(); - return finishClassElement(factory.updateMethodDeclaration(node, modifiers, node.asteriskToken, name, /*questionToken*/ undefined, /*typeParameters*/ undefined, parameters, /*type*/ undefined, body), node); + return finishClassElement( + factory.updateMethodDeclaration( + node, + modifiers, + node.asteriskToken, + name, + /*questionToken*/ undefined, + /*typeParameters*/ undefined, + parameters, + /*type*/ undefined, + body, + ), + node, + ); } } function visitGetAccessorDeclaration(node: GetAccessorDeclaration) { enterClassElement(node); - const { modifiers, name, descriptorName } = partialTransformClassElement(node, classInfo, createGetAccessorDescriptorObject); + const { modifiers, name, descriptorName } = partialTransformClassElement( + node, + classInfo, + createGetAccessorDescriptorObject, + ); if (descriptorName) { exitClassElement(); return finishClassElement(createGetAccessorDescriptorForwarder(modifiers, name, descriptorName), node); @@ -1385,13 +1613,20 @@ export function transformESDecorators(context: TransformationContext): (x: Sourc const parameters = visitNodes(node.parameters, visitor, isParameter); const body = visitNode(node.body, visitor, isBlock); exitClassElement(); - return finishClassElement(factory.updateGetAccessorDeclaration(node, modifiers, name, parameters, /*type*/ undefined, body), node); + return finishClassElement( + factory.updateGetAccessorDeclaration(node, modifiers, name, parameters, /*type*/ undefined, body), + node, + ); } } function visitSetAccessorDeclaration(node: SetAccessorDeclaration) { enterClassElement(node); - const { modifiers, name, descriptorName } = partialTransformClassElement(node, classInfo, createSetAccessorDescriptorObject); + const { modifiers, name, descriptorName } = partialTransformClassElement( + node, + classInfo, + createSetAccessorDescriptorObject, + ); if (descriptorName) { exitClassElement(); return finishClassElement(createSetAccessorDescriptorForwarder(modifiers, name, descriptorName), node); @@ -1400,7 +1635,10 @@ export function transformESDecorators(context: TransformationContext): (x: Sourc const parameters = visitNodes(node.parameters, visitor, isParameter); const body = visitNode(node.body, visitor, isBlock); exitClassElement(); - return finishClassElement(factory.updateSetAccessorDeclaration(node, modifiers, name, parameters, body), node); + return finishClassElement( + factory.updateSetAccessorDeclaration(node, modifiers, name, parameters, body), + node, + ); } } @@ -1445,7 +1683,11 @@ export function transformESDecorators(context: TransformationContext): (x: Sourc // a. Let _value_ be ? NamedEvaluation of |Initializer| with argument _functionObject_.[[ClassFieldInitializerName]]. // ... - const { modifiers, name, initializersName, descriptorName, thisArg } = partialTransformClassElement(node, classInfo, hasAccessorModifier(node) ? createAccessorPropertyDescriptorObject : undefined); + const { modifiers, name, initializersName, descriptorName, thisArg } = partialTransformClassElement( + node, + classInfo, + hasAccessorModifier(node) ? createAccessorPropertyDescriptorObject : undefined, + ); startLexicalEnvironment(); @@ -1458,7 +1700,9 @@ export function transformESDecorators(context: TransformationContext): (x: Sourc ); } - if (!isStatic(node) && classInfo?.instanceExtraInitializersName && !classInfo?.hasInjectedInstanceInitializers) { + if ( + !isStatic(node) && classInfo?.instanceExtraInitializersName && !classInfo?.hasInjectedInstanceInitializers + ) { // for the first non-static field initializer, inject a call to `__runInitializers`. classInfo.hasInjectedInstanceInitializers = true; initializer ??= factory.createVoidZero(); @@ -1509,7 +1753,10 @@ export function transformESDecorators(context: TransformationContext): (x: Sourc if (isComputedPropertyName(name) && !isSimpleInlineableExpression(name.expression)) { const cacheAssignment = findComputedPropertyNameCacheAssignment(name); if (cacheAssignment) { - getterName = factory.updateComputedPropertyName(name, visitNode(name.expression, visitor, isExpression)); + getterName = factory.updateComputedPropertyName( + name, + visitNode(name.expression, visitor, isExpression), + ); setterName = factory.updateComputedPropertyName(name, cacheAssignment.left); } else { @@ -1523,9 +1770,18 @@ export function transformESDecorators(context: TransformationContext): (x: Sourc } } - const modifiersWithoutAccessor = visitNodes(modifiers, node => node.kind !== SyntaxKind.AccessorKeyword ? node : undefined, isModifier); + const modifiersWithoutAccessor = visitNodes( + modifiers, + node => node.kind !== SyntaxKind.AccessorKeyword ? node : undefined, + isModifier, + ); - const backingField = createAccessorPropertyBackingField(factory, node, modifiersWithoutAccessor, initializer); + const backingField = createAccessorPropertyBackingField( + factory, + node, + modifiersWithoutAccessor, + initializer, + ); setOriginalNode(backingField, node); setEmitFlags(backingField, EmitFlags.NoComments); setSourceMapRange(backingField, sourceMapRange); @@ -1544,7 +1800,17 @@ export function transformESDecorators(context: TransformationContext): (x: Sourc return [backingField, getter, setter]; } - return finishClassElement(factory.updatePropertyDeclaration(node, modifiers, name, /*questionOrExclamationToken*/ undefined, /*type*/ undefined, initializer), node); + return finishClassElement( + factory.updatePropertyDeclaration( + node, + modifiers, + name, + /*questionOrExclamationToken*/ undefined, + /*type*/ undefined, + initializer, + ), + node, + ); } function visitThisExpression(node: ThisExpression) { @@ -1654,7 +1920,8 @@ export function transformESDecorators(context: TransformationContext): (x: Sourc // transforms to `return class { };`, and thus the empty string *can* be ignored. const innerExpression = skipOuterExpressions(node); - return isClassExpression(innerExpression) && !innerExpression.name && !classOrConstructorParameterIsDecorated(/*useLegacyDecorators*/ false, innerExpression); + return isClassExpression(innerExpression) && !innerExpression.name + && !classOrConstructorParameterIsDecorated(/*useLegacyDecorators*/ false, innerExpression); } function visitForStatement(node: ForStatement) { @@ -1711,9 +1978,10 @@ export function transformESDecorators(context: TransformationContext): (x: Sourc } if (isSuperProperty(node.left) && classThis && classSuper) { - let setterName = isElementAccessExpression(node.left) ? visitNode(node.left.argumentExpression, visitor, isExpression) : - isIdentifier(node.left.name) ? factory.createStringLiteralFromNode(node.left.name) : - undefined; + let setterName = isElementAccessExpression(node.left) + ? visitNode(node.left.argumentExpression, visitor, isExpression) + : isIdentifier(node.left.name) ? factory.createStringLiteralFromNode(node.left.name) + : undefined; if (setterName) { // super.x = ... // super.x += ... @@ -1777,16 +2045,20 @@ export function transformESDecorators(context: TransformationContext): (x: Sourc return visitEachChild(node, visitor, context); } - function visitPreOrPostfixUnaryExpression(node: PrefixUnaryExpression | PostfixUnaryExpression, discarded: boolean) { + function visitPreOrPostfixUnaryExpression( + node: PrefixUnaryExpression | PostfixUnaryExpression, + discarded: boolean, + ) { if ( - node.operator === SyntaxKind.PlusPlusToken || - node.operator === SyntaxKind.MinusMinusToken + node.operator === SyntaxKind.PlusPlusToken + || node.operator === SyntaxKind.MinusMinusToken ) { const operand = skipParentheses(node.operand); if (isSuperProperty(operand) && classThis && classSuper) { - let setterName = isElementAccessExpression(operand) ? visitNode(operand.argumentExpression, visitor, isExpression) : - isIdentifier(operand.name) ? factory.createStringLiteralFromNode(operand.name) : - undefined; + let setterName = isElementAccessExpression(operand) + ? visitNode(operand.argumentExpression, visitor, isExpression) + : isIdentifier(operand.name) ? factory.createStringLiteralFromNode(operand.name) + : undefined; if (setterName) { let getterName = setterName; if (!isSimpleInlineableExpression(setterName)) { @@ -1820,7 +2092,13 @@ export function transformESDecorators(context: TransformationContext): (x: Sourc // result of the operation so that we can provide it to `y` when the assignment is complete. const temp = discarded ? undefined : factory.createTempVariable(hoistVariableDeclaration); - expression = expandPreOrPostfixIncrementOrDecrementExpression(factory, node, expression, hoistVariableDeclaration, temp); + expression = expandPreOrPostfixIncrementOrDecrementExpression( + factory, + node, + expression, + hoistVariableDeclaration, + temp, + ); expression = factory.createReflectSetCall(classSuper, setterName, expression, classThis); setOriginalNode(expression, node); setTextRange(expression, node); @@ -1839,9 +2117,9 @@ export function transformESDecorators(context: TransformationContext): (x: Sourc } function visitCommaListExpression(node: CommaListExpression, discarded: boolean) { - const elements = discarded ? - visitCommaListElements(node.elements, discardedValueVisitor) : - visitCommaListElements(node.elements, visitor, discardedValueVisitor); + const elements = discarded + ? visitCommaListElements(node.elements, discardedValueVisitor) + : visitCommaListElements(node.elements, visitor, discardedValueVisitor); return factory.updateCommaListExpression(node, elements); } @@ -1949,9 +2227,10 @@ export function transformESDecorators(context: TransformationContext): (x: Sourc } if (isSuperProperty(node) && classThis && classSuper) { - const propertyName = isElementAccessExpression(node) ? visitNode(node.argumentExpression, visitor, isExpression) : - isIdentifier(node.name) ? factory.createStringLiteralFromNode(node.name) : - undefined; + const propertyName = isElementAccessExpression(node) + ? visitNode(node.argumentExpression, visitor, isExpression) + : isIdentifier(node.name) ? factory.createStringLiteralFromNode(node.name) + : undefined; if (propertyName) { const paramName = factory.createTempVariable(/*recordTempVariable*/ undefined); const expression = factory.createAssignmentTargetWrapper( @@ -1972,7 +2251,9 @@ export function transformESDecorators(context: TransformationContext): (x: Sourc return visitEachChild(node, visitor, context); } - function visitAssignmentElement(node: Exclude): ArrayAssignmentElement { + function visitAssignmentElement( + node: Exclude, + ): ArrayAssignmentElement { // 13.15.5.5 RS: IteratorDestructuringAssignmentEvaluation // AssignmentElement : DestructuringAssignmentTarget Initializer? // ... @@ -1988,7 +2269,12 @@ export function transformESDecorators(context: TransformationContext): (x: Sourc const assignmentTarget = visitDestructuringAssignmentTarget(node.left); const initializer = visitNode(node.right, visitor, isExpression); - return factory.updateBinaryExpression(node, assignmentTarget, node.operatorToken, initializer) as ArrayAssignmentElement; + return factory.updateBinaryExpression( + node, + assignmentTarget, + node.operatorToken, + initializer, + ) as ArrayAssignmentElement; } else { return visitDestructuringAssignmentTarget(node) as ArrayAssignmentElement; @@ -2049,7 +2335,11 @@ export function transformESDecorators(context: TransformationContext): (x: Sourc // ... if (isNamedEvaluation(node, isAnonymousClassNeedingAssignedName)) { - node = transformNamedEvaluation(context, node, canIgnoreEmptyStringLiteralInAssignedName(node.objectAssignmentInitializer)); + node = transformNamedEvaluation( + context, + node, + canIgnoreEmptyStringLiteralInAssignedName(node.objectAssignmentInitializer), + ); } return visitEachChild(node, visitor, context); @@ -2120,7 +2410,10 @@ export function transformESDecorators(context: TransformationContext): (x: Sourc if (some(pendingExpressions)) { if (isParenthesizedExpression(expression)) { pendingExpressions.push(expression.expression); - expression = factory.updateParenthesizedExpression(expression, factory.inlineExpressions(pendingExpressions)); + expression = factory.updateParenthesizedExpression( + expression, + factory.inlineExpressions(pendingExpressions), + ); } else { pendingExpressions.push(expression); @@ -2158,7 +2451,12 @@ export function transformESDecorators(context: TransformationContext): (x: Sourc // preserve the 'this' binding for an access expression const innerExpression = skipOuterExpressions(expression); if (isAccessExpression(innerExpression)) { - const { target, thisArg } = factory.createCallBinding(expression, hoistVariableDeclaration, languageVersion, /*cacheIdentifiers*/ true); + const { target, thisArg } = factory.createCallBinding( + expression, + hoistVariableDeclaration, + languageVersion, + /*cacheIdentifiers*/ true, + ); return factory.restoreOuterExpressions(expression, factory.createFunctionBindCall(target, thisArg, [])); } return expression; @@ -2167,7 +2465,15 @@ export function transformESDecorators(context: TransformationContext): (x: Sourc /** * Creates a `value`, `get`, or `set` method for a pseudo-{@link PropertyDescriptor} object created for a private element. */ - function createDescriptorMethod(original: Node, name: PrivateIdentifier, modifiers: ModifiersArray | undefined, asteriskToken: AsteriskToken | undefined, kind: "value" | "get" | "set", parameters: readonly ParameterDeclaration[], body: Block | undefined) { + function createDescriptorMethod( + original: Node, + name: PrivateIdentifier, + modifiers: ModifiersArray | undefined, + asteriskToken: AsteriskToken | undefined, + kind: "value" | "get" | "set", + parameters: readonly ParameterDeclaration[], + body: Block | undefined, + ) { const func = factory.createFunctionExpression( modifiers, asteriskToken, @@ -2194,7 +2500,10 @@ export function transformESDecorators(context: TransformationContext): (x: Sourc /** * Creates a pseudo-{@link PropertyDescriptor} object used when decorating a private {@link MethodDeclaration}. */ - function createMethodDescriptorObject(node: PrivateIdentifierMethodDeclaration, modifiers: ModifiersArray | undefined) { + function createMethodDescriptorObject( + node: PrivateIdentifierMethodDeclaration, + modifiers: ModifiersArray | undefined, + ) { return factory.createObjectLiteralExpression([ createDescriptorMethod( node, @@ -2211,7 +2520,10 @@ export function transformESDecorators(context: TransformationContext): (x: Sourc /** * Creates a pseudo-{@link PropertyDescriptor} object used when decorating a private {@link GetAccessorDeclaration}. */ - function createGetAccessorDescriptorObject(node: PrivateIdentifierGetAccessorDeclaration, modifiers: ModifiersArray | undefined) { + function createGetAccessorDescriptorObject( + node: PrivateIdentifierGetAccessorDeclaration, + modifiers: ModifiersArray | undefined, + ) { return factory.createObjectLiteralExpression([ createDescriptorMethod( node, @@ -2228,7 +2540,10 @@ export function transformESDecorators(context: TransformationContext): (x: Sourc /** * Creates a pseudo-{@link PropertyDescriptor} object used when decorating a private {@link SetAccessorDeclaration}. */ - function createSetAccessorDescriptorObject(node: PrivateIdentifierSetAccessorDeclaration, modifiers: ModifiersArray | undefined) { + function createSetAccessorDescriptorObject( + node: PrivateIdentifierSetAccessorDeclaration, + modifiers: ModifiersArray | undefined, + ) { return factory.createObjectLiteralExpression([ createDescriptorMethod( node, @@ -2245,7 +2560,10 @@ export function transformESDecorators(context: TransformationContext): (x: Sourc /** * Creates a pseudo-{@link PropertyDescriptor} object used when decorating an `accessor` {@link PropertyDeclaration} with a private name. */ - function createAccessorPropertyDescriptorObject(node: PrivateIdentifierPropertyDeclaration, modifiers: ModifiersArray | undefined) { + function createAccessorPropertyDescriptorObject( + node: PrivateIdentifierPropertyDeclaration, + modifiers: ModifiersArray | undefined, + ) { // { // get() { return this.${privateName}; }, // set(value) { this.${privateName} = value; }, @@ -2300,7 +2618,11 @@ export function transformESDecorators(context: TransformationContext): (x: Sourc * @param name The name for the resulting declaration. * @param descriptorName The name of the descriptor variable. */ - function createMethodDescriptorForwarder(modifiers: ModifiersArray | undefined, name: PropertyName, descriptorName: Identifier) { + function createMethodDescriptorForwarder( + modifiers: ModifiersArray | undefined, + name: PropertyName, + descriptorName: Identifier, + ) { // strip off all but the `static` modifier modifiers = visitNodes(modifiers, node => isStaticModifier(node) ? node : undefined, isModifier); return factory.createGetAccessorDeclaration( @@ -2325,7 +2647,11 @@ export function transformESDecorators(context: TransformationContext): (x: Sourc * @param name The name for the resulting declaration. * @param descriptorName The name of the descriptor variable. */ - function createGetAccessorDescriptorForwarder(modifiers: ModifiersArray | undefined, name: PropertyName, descriptorName: Identifier) { + function createGetAccessorDescriptorForwarder( + modifiers: ModifiersArray | undefined, + name: PropertyName, + descriptorName: Identifier, + ) { // strip off all but the `static` modifier modifiers = visitNodes(modifiers, node => isStaticModifier(node) ? node : undefined, isModifier); return factory.createGetAccessorDeclaration( @@ -2354,7 +2680,11 @@ export function transformESDecorators(context: TransformationContext): (x: Sourc * @param name The name for the resulting declaration. * @param descriptorName The name of the descriptor variable. */ - function createSetAccessorDescriptorForwarder(modifiers: ModifiersArray | undefined, name: PropertyName, descriptorName: Identifier) { + function createSetAccessorDescriptorForwarder( + modifiers: ModifiersArray | undefined, + name: PropertyName, + descriptorName: Identifier, + ) { // strip off all but the `static` modifier modifiers = visitNodes(modifiers, node => isStaticModifier(node) ? node : undefined, isModifier); return factory.createSetAccessorDeclaration( @@ -2399,14 +2729,20 @@ export function transformESDecorators(context: TransformationContext): (x: Sourc factory.createVoidZero(), ), ); - return factory.createVariableStatement(/*modifiers*/ undefined, factory.createVariableDeclarationList([varDecl], NodeFlags.Const)); + return factory.createVariableStatement( + /*modifiers*/ undefined, + factory.createVariableDeclarationList([varDecl], NodeFlags.Const), + ); } function createSymbolMetadata(target: Identifier | ThisExpression, value: Identifier) { const defineProperty = factory.createObjectDefinePropertyCall( target, factory.createPropertyAccessExpression(factory.createIdentifier("Symbol"), "metadata"), - factory.createPropertyDescriptor({ configurable: true, writable: true, enumerable: true, value }, /*singleLine*/ true), + factory.createPropertyDescriptor( + { configurable: true, writable: true, enumerable: true, value }, + /*singleLine*/ true, + ), ); return setEmitFlags( factory.createIfStatement(value, factory.createExpressionStatement(defineProperty)), diff --git a/src/compiler/transformers/esnext.ts b/src/compiler/transformers/esnext.ts index 04b79d250eaad..0c6e56dbd0a6e 100644 --- a/src/compiler/transformers/esnext.ts +++ b/src/compiler/transformers/esnext.ts @@ -182,7 +182,10 @@ export function transformESNext(context: TransformationContext): (x: SourceFile const statement = node.statements[pos]; if (getUsingKind(statement) !== UsingKind.None) { if (pos > prologueCount) { - addRange(topLevelStatements, visitNodes(node.statements, visitor, isStatement, prologueCount, pos - prologueCount)); + addRange( + topLevelStatements, + visitNodes(node.statements, visitor, isStatement, prologueCount, pos - prologueCount), + ); } break; } @@ -193,7 +196,13 @@ export function transformESNext(context: TransformationContext): (x: SourceFile // transform the rest of the body const envBinding = createEnvBinding(); - const bodyStatements = transformUsingDeclarations(node.statements, pos, node.statements.length, envBinding, topLevelStatements); + const bodyStatements = transformUsingDeclarations( + node.statements, + pos, + node.statements.length, + envBinding, + topLevelStatements, + ); // add `export {}` declarations for any hoisted bindings. if (exportBindings.size) { @@ -217,7 +226,10 @@ export function transformESNext(context: TransformationContext): (x: SourceFile ), )); } - addRange(topLevelStatements, createDownlevelUsingStatements(bodyStatements, envBinding, usingKind === UsingKind.Async)); + addRange( + topLevelStatements, + createDownlevelUsingStatements(bodyStatements, envBinding, usingKind === UsingKind.Async), + ); if (exportEqualsBinding) { topLevelStatements.push(factory.createExportAssignment( @@ -243,7 +255,13 @@ export function transformESNext(context: TransformationContext): (x: SourceFile [ ...visitArray(node.statements, visitor, isStatement, 0, prologueCount), ...createDownlevelUsingStatements( - transformUsingDeclarations(node.statements, prologueCount, node.statements.length, envBinding, /*topLevelStatements*/ undefined), + transformUsingDeclarations( + node.statements, + prologueCount, + node.statements.length, + envBinding, + /*topLevelStatements*/ undefined, + ), envBinding, usingKind === UsingKind.Async, ), @@ -309,8 +327,17 @@ export function transformESNext(context: TransformationContext): (x: SourceFile const isAwaitUsing = getUsingKindOfVariableDeclarationList(forInitializer) === UsingKind.Async; const temp = factory.getGeneratedNameForNode(forDecl.name); - const usingVar = factory.updateVariableDeclaration(forDecl, forDecl.name, /*exclamationToken*/ undefined, /*type*/ undefined, temp); - const usingVarList = factory.createVariableDeclarationList([usingVar], isAwaitUsing ? NodeFlags.AwaitUsing : NodeFlags.Using); + const usingVar = factory.updateVariableDeclaration( + forDecl, + forDecl.name, + /*exclamationToken*/ undefined, + /*type*/ undefined, + temp, + ); + const usingVarList = factory.createVariableDeclarationList( + [usingVar], + isAwaitUsing ? NodeFlags.AwaitUsing : NodeFlags.Using, + ); const usingVarStatement = factory.createVariableStatement(/*modifiers*/ undefined, usingVarList); return visitNode( factory.updateForOfStatement( @@ -320,12 +347,12 @@ export function transformESNext(context: TransformationContext): (x: SourceFile factory.createVariableDeclaration(temp), ], NodeFlags.Const), node.expression, - isBlock(node.statement) ? - factory.updateBlock(node.statement, [ + isBlock(node.statement) + ? factory.updateBlock(node.statement, [ usingVarStatement, ...node.statement.statements, - ]) : - factory.createBlock([ + ]) + : factory.createBlock([ usingVarStatement, node.statement, ], /*multiLine*/ true), @@ -343,13 +370,25 @@ export function transformESNext(context: TransformationContext): (x: SourceFile return factory.updateCaseClause( node, visitNode(node.expression, visitor, isExpression), - transformUsingDeclarations(node.statements, /*start*/ 0, node.statements.length, envBinding, /*topLevelStatements*/ undefined), + transformUsingDeclarations( + node.statements, + /*start*/ 0, + node.statements.length, + envBinding, + /*topLevelStatements*/ undefined, + ), ); } else { return factory.updateDefaultClause( node, - transformUsingDeclarations(node.statements, /*start*/ 0, node.statements.length, envBinding, /*topLevelStatements*/ undefined), + transformUsingDeclarations( + node.statements, + /*start*/ 0, + node.statements.length, + envBinding, + /*topLevelStatements*/ undefined, + ), ); } } @@ -406,7 +445,13 @@ export function transformESNext(context: TransformationContext): (x: SourceFile /** * Transform `using` declarations in a statement list. */ - function transformUsingDeclarations(statementsIn: readonly Statement[], start: number, end: number, envBinding: Identifier, topLevelStatements: Statement[] | undefined) { + function transformUsingDeclarations( + statementsIn: readonly Statement[], + start: number, + end: number, + envBinding: Identifier, + topLevelStatements: Statement[] | undefined, + ) { const statements: Statement[] = []; for (let i = start; i < end; i++) { @@ -427,7 +472,8 @@ export function transformESNext(context: TransformationContext): (x: SourceFile declaration = transformNamedEvaluation(context, declaration); } - const initializer = visitNode(declaration.initializer, visitor, isExpression) ?? factory.createVoidZero(); + const initializer = visitNode(declaration.initializer, visitor, isExpression) + ?? factory.createVoidZero(); declarations.push(factory.updateVariableDeclaration( declaration, declaration.name, @@ -518,14 +564,23 @@ export function transformESNext(context: TransformationContext): (x: SourceFile // // body // default_1 = expr; - defaultExportBinding = factory.createUniqueName("_default", GeneratedIdentifierFlags.ReservedInNestedScopes | GeneratedIdentifierFlags.FileLevel | GeneratedIdentifierFlags.Optimistic); + defaultExportBinding = factory.createUniqueName( + "_default", + GeneratedIdentifierFlags.ReservedInNestedScopes | GeneratedIdentifierFlags.FileLevel + | GeneratedIdentifierFlags.Optimistic, + ); hoistBindingIdentifier(defaultExportBinding, /*isExport*/ true, "default", node); // give a class or function expression an assigned name, if needed. let expression = node.expression; let innerExpression = skipOuterExpressions(expression); if (isNamedEvaluation(innerExpression)) { - innerExpression = transformNamedEvaluation(context, innerExpression, /*ignoreEmptyStringLiteral*/ false, "default"); + innerExpression = transformNamedEvaluation( + context, + innerExpression, + /*ignoreEmptyStringLiteral*/ false, + "default", + ); expression = factory.restoreOuterExpressions(expression, innerExpression); } @@ -557,7 +612,11 @@ export function transformESNext(context: TransformationContext): (x: SourceFile // // top level suffix // export = default_1; - exportEqualsBinding = factory.createUniqueName("_default", GeneratedIdentifierFlags.ReservedInNestedScopes | GeneratedIdentifierFlags.FileLevel | GeneratedIdentifierFlags.Optimistic); + exportEqualsBinding = factory.createUniqueName( + "_default", + GeneratedIdentifierFlags.ReservedInNestedScopes | GeneratedIdentifierFlags.FileLevel + | GeneratedIdentifierFlags.Optimistic, + ); hoistVariableDeclaration(exportEqualsBinding); // give a class or function expression an assigned name, if needed. @@ -601,7 +660,12 @@ export function transformESNext(context: TransformationContext): (x: SourceFile // } // // If the class is exported, we also produce an `export { C };` - hoistBindingIdentifier(factory.getLocalName(node), isExported && !isDefault, /*exportAlias*/ undefined, node); + hoistBindingIdentifier( + factory.getLocalName(node), + isExported && !isDefault, + /*exportAlias*/ undefined, + node, + ); expression = factory.createAssignment(factory.getDeclarationName(node), expression); if (isNamedEvaluation(expression)) { expression = transformNamedEvaluation(context, expression, /*ignoreEmptyStringLiteral*/ false); @@ -638,11 +702,20 @@ export function transformESNext(context: TransformationContext): (x: SourceFile // } // // Though we will never reassign `default_1`, this most closely matches the specified runtime semantics. - defaultExportBinding = factory.createUniqueName("_default", GeneratedIdentifierFlags.ReservedInNestedScopes | GeneratedIdentifierFlags.FileLevel | GeneratedIdentifierFlags.Optimistic); + defaultExportBinding = factory.createUniqueName( + "_default", + GeneratedIdentifierFlags.ReservedInNestedScopes | GeneratedIdentifierFlags.FileLevel + | GeneratedIdentifierFlags.Optimistic, + ); hoistBindingIdentifier(defaultExportBinding, /*isExport*/ true, "default", node); expression = factory.createAssignment(defaultExportBinding, expression); if (isNamedEvaluation(expression)) { - expression = transformNamedEvaluation(context, expression, /*ignoreEmptyStringLiteral*/ false, "default"); + expression = transformNamedEvaluation( + context, + expression, + /*ignoreEmptyStringLiteral*/ false, + "default", + ); } setOriginalNode(expression, node); } @@ -676,7 +749,10 @@ export function transformESNext(context: TransformationContext): (x: SourceFile let target: Expression; if (isIdentifier(node.name)) { target = factory.cloneNode(node.name); - setEmitFlags(target, getEmitFlags(target) & ~(EmitFlags.LocalName | EmitFlags.ExportName | EmitFlags.InternalName)); + setEmitFlags( + target, + getEmitFlags(target) & ~(EmitFlags.LocalName | EmitFlags.ExportName | EmitFlags.InternalName), + ); } else { target = factory.converters.convertToAssignmentPattern(node.name); @@ -689,7 +765,11 @@ export function transformESNext(context: TransformationContext): (x: SourceFile return assignment; } - function hoistBindingElement(node: VariableDeclaration | BindingElement, isExportedDeclaration: boolean, original: Node | undefined) { + function hoistBindingElement( + node: VariableDeclaration | BindingElement, + isExportedDeclaration: boolean, + original: Node | undefined, + ) { // NOTE: `node` has already been visited if (isBindingPattern(node.name)) { for (const element of node.name.elements) { @@ -703,7 +783,12 @@ export function transformESNext(context: TransformationContext): (x: SourceFile } } - function hoistBindingIdentifier(node: Identifier, isExport: boolean, exportAlias: string | Identifier | undefined, original: Node | undefined) { + function hoistBindingIdentifier( + node: Identifier, + isExport: boolean, + exportAlias: string | Identifier | undefined, + original: Node | undefined, + ) { // NOTE: `node` has already been visited const name = isGeneratedIdentifier(node) ? node : factory.cloneNode(node); if (isExport) { @@ -731,7 +816,11 @@ export function transformESNext(context: TransformationContext): (x: SourceFile return factory.createUniqueName("env"); } - function createDownlevelUsingStatements(bodyStatements: readonly Statement[], envBinding: Identifier, async: boolean) { + function createDownlevelUsingStatements( + bodyStatements: readonly Statement[], + envBinding: Identifier, + async: boolean, + ) { const statements: Statement[] = []; // produces: @@ -743,7 +832,12 @@ export function transformESNext(context: TransformationContext): (x: SourceFile factory.createPropertyAssignment("error", factory.createVoidZero()), factory.createPropertyAssignment("hasError", factory.createFalse()), ]); - const envVar = factory.createVariableDeclaration(envBinding, /*exclamationToken*/ undefined, /*type*/ undefined, envObject); + const envVar = factory.createVariableDeclaration( + envBinding, + /*exclamationToken*/ undefined, + /*type*/ undefined, + envObject, + ); const envVarList = factory.createVariableDeclarationList([envVar], NodeFlags.Const); const envVarStatement = factory.createVariableStatement(/*modifiers*/ undefined, envVarList); statements.push(envVarStatement); @@ -814,7 +908,10 @@ export function transformESNext(context: TransformationContext): (x: SourceFile ), ], NodeFlags.Const), ), - factory.createIfStatement(result, factory.createExpressionStatement(factory.createAwaitExpression(result))), + factory.createIfStatement( + result, + factory.createExpressionStatement(factory.createAwaitExpression(result)), + ), ], /*multiLine*/ true); } else { @@ -846,9 +943,9 @@ function isUsingVariableDeclarationList(node: Node): node is VariableDeclaration } function getUsingKindOfVariableDeclarationList(node: VariableDeclarationList) { - return (node.flags & NodeFlags.BlockScoped) === NodeFlags.AwaitUsing ? UsingKind.Async : - (node.flags & NodeFlags.BlockScoped) === NodeFlags.Using ? UsingKind.Sync : - UsingKind.None; + return (node.flags & NodeFlags.BlockScoped) === NodeFlags.AwaitUsing ? UsingKind.Async + : (node.flags & NodeFlags.BlockScoped) === NodeFlags.Using ? UsingKind.Sync + : UsingKind.None; } function getUsingKindOfVariableStatement(node: VariableStatement) { diff --git a/src/compiler/transformers/generators.ts b/src/compiler/transformers/generators.ts index a49f2fca2ff12..b45310b3758b2 100644 --- a/src/compiler/transformers/generators.ts +++ b/src/compiler/transformers/generators.ts @@ -232,7 +232,10 @@ const enum OpCode { Endfinally, // Marks the end of a `finally` block } -type OperationArguments = [Label] | [Label, Expression] | [Statement] | [Expression | undefined] | [Expression, Expression]; +type OperationArguments = [Label] | [Label, Expression] | [Statement] | [Expression | undefined] | [ + Expression, + Expression, +]; // whether a generated code block is opening or closing at the current operation for a FunctionBuilder const enum BlockAction { @@ -482,7 +485,10 @@ export function transformGenerators(context: TransformationContext): (x: SourceF if (node.transformFlags & TransformFlags.ContainsYield) { return visitJavaScriptContainingYield(node); } - else if (node.transformFlags & (TransformFlags.ContainsGenerator | TransformFlags.ContainsHoistedDeclarationOrCompletion)) { + else if ( + node.transformFlags + & (TransformFlags.ContainsGenerator | TransformFlags.ContainsHoistedDeclarationOrCompletion) + ) { return visitEachChild(node, visitor, context); } else { @@ -796,7 +802,15 @@ export function transformGenerators(context: TransformationContext): (x: SourceF target = factory.updatePropertyAccessExpression( left as PropertyAccessExpression, - cacheExpression(Debug.checkDefined(visitNode((left as PropertyAccessExpression).expression, visitor, isLeftHandSideExpression))), + cacheExpression( + Debug.checkDefined( + visitNode( + (left as PropertyAccessExpression).expression, + visitor, + isLeftHandSideExpression, + ), + ), + ), (left as PropertyAccessExpression).name, ); break; @@ -813,7 +827,23 @@ export function transformGenerators(context: TransformationContext): (x: SourceF // .mark resumeLabel // _a[_b] = %sent%; - target = factory.updateElementAccessExpression(left as ElementAccessExpression, cacheExpression(Debug.checkDefined(visitNode((left as ElementAccessExpression).expression, visitor, isLeftHandSideExpression))), cacheExpression(Debug.checkDefined(visitNode((left as ElementAccessExpression).argumentExpression, visitor, isExpression)))); + target = factory.updateElementAccessExpression( + left as ElementAccessExpression, + cacheExpression( + Debug.checkDefined( + visitNode( + (left as ElementAccessExpression).expression, + visitor, + isLeftHandSideExpression, + ), + ), + ), + cacheExpression( + Debug.checkDefined( + visitNode((left as ElementAccessExpression).argumentExpression, visitor, isExpression), + ), + ), + ); break; default: @@ -839,7 +869,12 @@ export function transformGenerators(context: TransformationContext): (x: SourceF ); } else { - return factory.updateBinaryExpression(node, target, node.operatorToken, Debug.checkDefined(visitNode(right, visitor, isExpression))); + return factory.updateBinaryExpression( + node, + target, + node.operatorToken, + Debug.checkDefined(visitNode(right, visitor, isExpression)), + ); } } @@ -864,7 +899,12 @@ export function transformGenerators(context: TransformationContext): (x: SourceF // .yield resumeLabel // _a + %sent% + c() - return factory.updateBinaryExpression(node, cacheExpression(Debug.checkDefined(visitNode(node.left, visitor, isExpression))), node.operatorToken, Debug.checkDefined(visitNode(node.right, visitor, isExpression))); + return factory.updateBinaryExpression( + node, + cacheExpression(Debug.checkDefined(visitNode(node.left, visitor, isExpression))), + node.operatorToken, + Debug.checkDefined(visitNode(node.right, visitor, isExpression)), + ); } return visitEachChild(node, visitor, context); @@ -897,7 +937,9 @@ export function transformGenerators(context: TransformationContext): (x: SourceF } else { if (containsYield(node) && pendingExpressions.length > 0) { - emitWorker(OpCode.Statement, [factory.createExpressionStatement(factory.inlineExpressions(pendingExpressions))]); + emitWorker(OpCode.Statement, [ + factory.createExpressionStatement(factory.inlineExpressions(pendingExpressions)), + ]); pendingExpressions = []; } @@ -920,7 +962,9 @@ export function transformGenerators(context: TransformationContext): (x: SourceF } else { if (containsYield(elem) && pendingExpressions.length > 0) { - emitWorker(OpCode.Statement, [factory.createExpressionStatement(factory.inlineExpressions(pendingExpressions))]); + emitWorker(OpCode.Statement, [ + factory.createExpressionStatement(factory.inlineExpressions(pendingExpressions)), + ]); pendingExpressions = []; } pendingExpressions.push(Debug.checkDefined(visitNode(elem, visitor, isExpression))); @@ -967,7 +1011,11 @@ export function transformGenerators(context: TransformationContext): (x: SourceF const resultLabel = defineLabel(); const resultLocal = declareLocal(); - emitAssignment(resultLocal, Debug.checkDefined(visitNode(node.left, visitor, isExpression)), /*location*/ node.left); + emitAssignment( + resultLocal, + Debug.checkDefined(visitNode(node.left, visitor, isExpression)), + /*location*/ node.left, + ); if (node.operatorToken.kind === SyntaxKind.AmpersandAmpersandToken) { // Logical `&&` shortcuts when the left-hand operand is falsey. emitBreakWhenFalse(resultLabel, resultLocal, /*location*/ node.left); @@ -977,7 +1025,11 @@ export function transformGenerators(context: TransformationContext): (x: SourceF emitBreakWhenTrue(resultLabel, resultLocal, /*location*/ node.left); } - emitAssignment(resultLocal, Debug.checkDefined(visitNode(node.right, visitor, isExpression)), /*location*/ node.right); + emitAssignment( + resultLocal, + Debug.checkDefined(visitNode(node.right, visitor, isExpression)), + /*location*/ node.right, + ); markLabel(resultLabel); return resultLocal; } @@ -1010,11 +1062,23 @@ export function transformGenerators(context: TransformationContext): (x: SourceF const whenFalseLabel = defineLabel(); const resultLabel = defineLabel(); const resultLocal = declareLocal(); - emitBreakWhenFalse(whenFalseLabel, Debug.checkDefined(visitNode(node.condition, visitor, isExpression)), /*location*/ node.condition); - emitAssignment(resultLocal, Debug.checkDefined(visitNode(node.whenTrue, visitor, isExpression)), /*location*/ node.whenTrue); + emitBreakWhenFalse( + whenFalseLabel, + Debug.checkDefined(visitNode(node.condition, visitor, isExpression)), + /*location*/ node.condition, + ); + emitAssignment( + resultLocal, + Debug.checkDefined(visitNode(node.whenTrue, visitor, isExpression)), + /*location*/ node.whenTrue, + ); emitBreak(resultLabel); markLabel(whenFalseLabel); - emitAssignment(resultLocal, Debug.checkDefined(visitNode(node.whenFalse, visitor, isExpression)), /*location*/ node.whenFalse); + emitAssignment( + resultLocal, + Debug.checkDefined(visitNode(node.whenFalse, visitor, isExpression)), + /*location*/ node.whenFalse, + ); markLabel(resultLabel); return resultLocal; } @@ -1069,7 +1133,12 @@ export function transformGenerators(context: TransformationContext): (x: SourceF * @param elements The elements to visit. * @param multiLine Whether array literals created should be emitted on multiple lines. */ - function visitElements(elements: NodeArray, leadingElement?: Expression, location?: TextRange, multiLine?: boolean) { + function visitElements( + elements: NodeArray, + leadingElement?: Expression, + location?: TextRange, + multiLine?: boolean, + ) { // [source] // ar = [1, yield, 2]; // @@ -1101,7 +1170,10 @@ export function transformGenerators(context: TransformationContext): (x: SourceF return temp ? factory.createArrayConcatCall(temp, [factory.createArrayLiteralExpression(expressions, multiLine)]) : setTextRange( - factory.createArrayLiteralExpression(leadingElement ? [leadingElement, ...expressions] : expressions, multiLine), + factory.createArrayLiteralExpression( + leadingElement ? [leadingElement, ...expressions] : expressions, + multiLine, + ), location, ); @@ -1167,7 +1239,9 @@ export function transformGenerators(context: TransformationContext): (x: SourceF const expressions = reduceLeft(properties, reduceProperty, [] as Expression[], numInitialProperties); // TODO(rbuckton): Does this need to be parented? - expressions.push(multiLine ? startOnNewLine(setParent(setTextRange(factory.cloneNode(temp), temp), temp.parent)) : temp); + expressions.push( + multiLine ? startOnNewLine(setParent(setTextRange(factory.cloneNode(temp), temp), temp.parent)) : temp, + ); return factory.inlineExpressions(expressions); function reduceProperty(expressions: Expression[], property: ObjectLiteralElementLike) { @@ -1205,7 +1279,11 @@ export function transformGenerators(context: TransformationContext): (x: SourceF // .mark resumeLabel // a = _a[%sent%] - return factory.updateElementAccessExpression(node, cacheExpression(Debug.checkDefined(visitNode(node.expression, visitor, isLeftHandSideExpression))), Debug.checkDefined(visitNode(node.argumentExpression, visitor, isExpression))); + return factory.updateElementAccessExpression( + node, + cacheExpression(Debug.checkDefined(visitNode(node.expression, visitor, isLeftHandSideExpression))), + Debug.checkDefined(visitNode(node.argumentExpression, visitor, isExpression)), + ); } return visitEachChild(node, visitor, context); @@ -1223,7 +1301,12 @@ export function transformGenerators(context: TransformationContext): (x: SourceF // .yield resumeLabel // .mark resumeLabel // _b.apply(_a, _c.concat([%sent%, 2])); - const { target, thisArg } = factory.createCallBinding(node.expression, hoistVariableDeclaration, languageVersion, /*cacheIdentifiers*/ true); + const { target, thisArg } = factory.createCallBinding( + node.expression, + hoistVariableDeclaration, + languageVersion, + /*cacheIdentifiers*/ true, + ); return setOriginalNode( setTextRange( factory.createFunctionApplyCall( @@ -1253,7 +1336,10 @@ export function transformGenerators(context: TransformationContext): (x: SourceF // .mark resumeLabel // new (_b.apply(_a, _c.concat([%sent%, 2]))); - const { target, thisArg } = factory.createCallBinding(factory.createPropertyAccessExpression(node.expression, "bind"), hoistVariableDeclaration); + const { target, thisArg } = factory.createCallBinding( + factory.createPropertyAccessExpression(node.expression, "bind"), + hoistVariableDeclaration, + ); return setOriginalNode( setTextRange( factory.createNewExpression( @@ -1352,7 +1438,9 @@ export function transformGenerators(context: TransformationContext): (x: SourceF emitStatement(visitNode(node, visitor, isStatement)); } - function transformAndEmitVariableDeclarationList(node: VariableDeclarationList): VariableDeclarationList | undefined { + function transformAndEmitVariableDeclarationList( + node: VariableDeclarationList, + ): VariableDeclarationList | undefined { for (const variable of node.declarations) { const name = factory.cloneNode(variable.name as Identifier); setCommentRange(name, variable.name); @@ -1412,7 +1500,11 @@ export function transformGenerators(context: TransformationContext): (x: SourceF if (containsYield(node.thenStatement) || containsYield(node.elseStatement)) { const endLabel = defineLabel(); const elseLabel = node.elseStatement ? defineLabel() : undefined; - emitBreakWhenFalse(node.elseStatement ? elseLabel! : endLabel, Debug.checkDefined(visitNode(node.expression, visitor, isExpression)), /*location*/ node.expression); + emitBreakWhenFalse( + node.elseStatement ? elseLabel! : endLabel, + Debug.checkDefined(visitNode(node.expression, visitor, isExpression)), + /*location*/ node.expression, + ); transformAndEmitEmbeddedStatement(node.thenStatement); if (node.elseStatement) { emitBreak(endLabel); @@ -1669,7 +1761,10 @@ export function transformGenerators(context: TransformationContext): (x: SourceF const endLoopLabel = beginLoopBlock(incrementLabel); markLabel(conditionLabel); - emitBreakWhenFalse(endLoopLabel, factory.createLessThan(keysIndex, factory.createPropertyAccessExpression(keysArray, "length"))); + emitBreakWhenFalse( + endLoopLabel, + factory.createLessThan(keysIndex, factory.createPropertyAccessExpression(keysArray, "length")), + ); emitAssignment(key, factory.createElementAccessExpression(keysArray, keysIndex)); emitBreakWhenFalse(incrementLabel, factory.createBinaryExpression(key, SyntaxKind.InKeyword, obj)); @@ -1725,7 +1820,12 @@ export function transformGenerators(context: TransformationContext): (x: SourceF hoistVariableDeclaration(variable.name as Identifier); } - node = factory.updateForInStatement(node, initializer.declarations[0].name as Identifier, Debug.checkDefined(visitNode(node.expression, visitor, isExpression)), Debug.checkDefined(visitNode(node.statement, visitor, isStatement, factory.liftToBlock))); + node = factory.updateForInStatement( + node, + initializer.declarations[0].name as Identifier, + Debug.checkDefined(visitNode(node.expression, visitor, isExpression)), + Debug.checkDefined(visitNode(node.statement, visitor, isStatement, factory.liftToBlock)), + ); } else { node = visitEachChild(node, visitor, context); @@ -2257,7 +2357,14 @@ export function transformGenerators(context: TransformationContext): (x: SourceF exception.catchVariable = name; exception.catchLabel = catchLabel; - emitAssignment(name, factory.createCallExpression(factory.createPropertyAccessExpression(state, "sent"), /*typeArguments*/ undefined, [])); + emitAssignment( + name, + factory.createCallExpression( + factory.createPropertyAccessExpression(state, "sent"), + /*typeArguments*/ undefined, + [], + ), + ); emitNop(); } @@ -2888,7 +2995,10 @@ export function transformGenerators(context: TransformationContext): (x: SourceF statements.unshift( factory.createExpressionStatement( factory.createCallExpression( - factory.createPropertyAccessExpression(factory.createPropertyAccessExpression(state, "trys"), "push"), + factory.createPropertyAccessExpression( + factory.createPropertyAccessExpression(state, "trys"), + "push", + ), /*typeArguments*/ undefined, [ factory.createArrayLiteralExpression([ @@ -3093,7 +3203,9 @@ export function transformGenerators(context: TransformationContext): (x: SourceF * @param operationLocation The source map location for the operation. */ function writeAssign(left: Expression, right: Expression, operationLocation: TextRange | undefined): void { - writeStatement(setTextRange(factory.createExpressionStatement(factory.createAssignment(left, right)), operationLocation)); + writeStatement( + setTextRange(factory.createExpressionStatement(factory.createAssignment(left, right)), operationLocation), + ); } /** diff --git a/src/compiler/transformers/jsx.ts b/src/compiler/transformers/jsx.ts index d0e191d537ad0..9483a81a8b61c 100644 --- a/src/compiler/transformers/jsx.ts +++ b/src/compiler/transformers/jsx.ts @@ -106,7 +106,15 @@ export function transformJsx(context: TransformationContext): (x: SourceFile | B if (currentFileState.filenameDeclaration) { return currentFileState.filenameDeclaration.name; } - const declaration = factory.createVariableDeclaration(factory.createUniqueName("_jsxFileName", GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel), /*exclamationToken*/ undefined, /*type*/ undefined, factory.createStringLiteral(currentSourceFile.fileName)); + const declaration = factory.createVariableDeclaration( + factory.createUniqueName( + "_jsxFileName", + GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel, + ), + /*exclamationToken*/ undefined, + /*type*/ undefined, + factory.createStringLiteral(currentSourceFile.fileName), + ); currentFileState.filenameDeclaration = declaration as VariableDeclaration & { name: Identifier; }; return currentFileState.filenameDeclaration.name; } @@ -140,8 +148,16 @@ export function transformJsx(context: TransformationContext): (x: SourceFile | B specifierSourceImports = new Map(); currentFileState.utilizedImplicitRuntimeImports.set(importSource, specifierSourceImports); } - const generatedName = factory.createUniqueName(`_${name}`, GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel | GeneratedIdentifierFlags.AllowNameSubstitution); - const specifier = factory.createImportSpecifier(/*isTypeOnly*/ false, factory.createIdentifier(name), generatedName); + const generatedName = factory.createUniqueName( + `_${name}`, + GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel + | GeneratedIdentifierFlags.AllowNameSubstitution, + ); + const specifier = factory.createImportSpecifier( + /*isTypeOnly*/ false, + factory.createIdentifier(name), + generatedName, + ); setIdentifierGeneratedImportReference(generatedName, specifier); specifierSourceImports.set(name, specifier); return generatedName; @@ -164,13 +180,32 @@ export function transformJsx(context: TransformationContext): (x: SourceFile | B addEmitHelpers(visited, context.readEmitHelpers()); let statements: readonly Statement[] = visited.statements; if (currentFileState.filenameDeclaration) { - statements = insertStatementAfterCustomPrologue(statements.slice(), factory.createVariableStatement(/*modifiers*/ undefined, factory.createVariableDeclarationList([currentFileState.filenameDeclaration], NodeFlags.Const))); + statements = insertStatementAfterCustomPrologue( + statements.slice(), + factory.createVariableStatement( + /*modifiers*/ undefined, + factory.createVariableDeclarationList([currentFileState.filenameDeclaration], NodeFlags.Const), + ), + ); } if (currentFileState.utilizedImplicitRuntimeImports) { - for (const [importSource, importSpecifiersMap] of arrayFrom(currentFileState.utilizedImplicitRuntimeImports.entries())) { + for ( + const [importSource, importSpecifiersMap] of arrayFrom( + currentFileState.utilizedImplicitRuntimeImports.entries(), + ) + ) { if (isExternalModule(node)) { // Add `import` statement - const importStatement = factory.createImportDeclaration(/*modifiers*/ undefined, factory.createImportClause(/*isTypeOnly*/ false, /*name*/ undefined, factory.createNamedImports(arrayFrom(importSpecifiersMap.values()))), factory.createStringLiteral(importSource), /*assertClause*/ undefined); + const importStatement = factory.createImportDeclaration( + /*modifiers*/ undefined, + factory.createImportClause( + /*isTypeOnly*/ false, + /*name*/ undefined, + factory.createNamedImports(arrayFrom(importSpecifiersMap.values())), + ), + factory.createStringLiteral(importSource), + /*assertClause*/ undefined, + ); setParentRecursive(importStatement, /*incremental*/ false); statements = insertStatementAfterCustomPrologue(statements.slice(), importStatement); } @@ -180,10 +215,21 @@ export function transformJsx(context: TransformationContext): (x: SourceFile | B /*modifiers*/ undefined, factory.createVariableDeclarationList([ factory.createVariableDeclaration( - factory.createObjectBindingPattern(arrayFrom(importSpecifiersMap.values(), s => factory.createBindingElement(/*dotDotDotToken*/ undefined, s.propertyName, s.name))), + factory.createObjectBindingPattern( + arrayFrom(importSpecifiersMap.values(), s => + factory.createBindingElement( + /*dotDotDotToken*/ undefined, + s.propertyName, + s.name, + )), + ), /*exclamationToken*/ undefined, /*type*/ undefined, - factory.createCallExpression(factory.createIdentifier("require"), /*typeArguments*/ undefined, [factory.createStringLiteral(importSource)]), + factory.createCallExpression( + factory.createIdentifier("require"), + /*typeArguments*/ undefined, + [factory.createStringLiteral(importSource)], + ), ), ], NodeFlags.Const), ); @@ -254,8 +300,9 @@ export function transformJsx(context: TransformationContext): (x: SourceFile | B function hasProto(obj: ObjectLiteralExpression) { return obj.properties.some(p => - isPropertyAssignment(p) && - (isIdentifier(p.name) && idText(p.name) === "__proto__" || isStringLiteral(p.name) && p.name.text === "__proto__") + isPropertyAssignment(p) + && (isIdentifier(p.name) && idText(p.name) === "__proto__" + || isStringLiteral(p.name) && p.name.text === "__proto__") ); } @@ -265,7 +312,10 @@ export function transformJsx(context: TransformationContext): (x: SourceFile | B function hasKeyAfterPropsSpread(node: JsxOpeningLikeElement) { let spread = false; for (const elem of node.attributes.properties) { - if (isJsxSpreadAttribute(elem) && (!isObjectLiteralExpression(elem.expression) || elem.expression.properties.some(isSpreadAssignment))) { + if ( + isJsxSpreadAttribute(elem) + && (!isObjectLiteralExpression(elem.expression) || elem.expression.properties.some(isSpreadAssignment)) + ) { spread = true; } else if (spread && isJsxAttribute(elem) && isIdentifier(elem.name) && elem.name.escapedText === "key") { @@ -280,17 +330,20 @@ export function transformJsx(context: TransformationContext): (x: SourceFile | B } function visitJsxElement(node: JsxElement, isChild: boolean) { - const tagTransform = shouldUseCreateElement(node.openingElement) ? visitJsxOpeningLikeElementCreateElement : visitJsxOpeningLikeElementJSX; + const tagTransform = shouldUseCreateElement(node.openingElement) ? visitJsxOpeningLikeElementCreateElement + : visitJsxOpeningLikeElementJSX; return tagTransform(node.openingElement, node.children, isChild, /*location*/ node); } function visitJsxSelfClosingElement(node: JsxSelfClosingElement, isChild: boolean) { - const tagTransform = shouldUseCreateElement(node) ? visitJsxOpeningLikeElementCreateElement : visitJsxOpeningLikeElementJSX; + const tagTransform = shouldUseCreateElement(node) ? visitJsxOpeningLikeElementCreateElement + : visitJsxOpeningLikeElementJSX; return tagTransform(node, /*children*/ undefined, isChild, /*location*/ node); } function visitJsxFragment(node: JsxFragment, isChild: boolean) { - const tagTransform = currentFileState.importSpecifier === undefined ? visitJsxOpeningFragmentCreateElement : visitJsxOpeningFragmentJSX; + const tagTransform = currentFileState.importSpecifier === undefined ? visitJsxOpeningFragmentCreateElement + : visitJsxOpeningFragmentJSX; return tagTransform(node.openingFragment, node.children, isChild, /*location*/ node); } @@ -306,16 +359,26 @@ export function transformJsx(context: TransformationContext): (x: SourceFile | B return result && factory.createPropertyAssignment("children", result); } const result = mapDefined(children, transformJsxChildToExpression); - return length(result) ? factory.createPropertyAssignment("children", factory.createArrayLiteralExpression(result)) : undefined; + return length(result) + ? factory.createPropertyAssignment("children", factory.createArrayLiteralExpression(result)) : undefined; } - function visitJsxOpeningLikeElementJSX(node: JsxOpeningLikeElement, children: readonly JsxChild[] | undefined, isChild: boolean, location: TextRange) { + function visitJsxOpeningLikeElementJSX( + node: JsxOpeningLikeElement, + children: readonly JsxChild[] | undefined, + isChild: boolean, + location: TextRange, + ) { const tagName = getTagName(node); - const childrenProp = children && children.length ? convertJsxChildrenToChildrenPropAssignment(children) : undefined; - const keyAttr = find(node.attributes.properties, p => !!p.name && isIdentifier(p.name) && p.name.escapedText === "key") as JsxAttribute | undefined; + const childrenProp = children && children.length ? convertJsxChildrenToChildrenPropAssignment(children) + : undefined; + const keyAttr = find( + node.attributes.properties, + p => !!p.name && isIdentifier(p.name) && p.name.escapedText === "key", + ) as JsxAttribute | undefined; const attrs = keyAttr ? filter(node.attributes.properties, p => p !== keyAttr) : node.attributes.properties; - const objectProperties = length(attrs) ? transformJsxAttributesToObjectProps(attrs, childrenProp) : - factory.createObjectLiteralExpression(childrenProp ? [childrenProp] : emptyArray); // When there are no attributes, React wants {} + const objectProperties = length(attrs) ? transformJsxAttributesToObjectProps(attrs, childrenProp) + : factory.createObjectLiteralExpression(childrenProp ? [childrenProp] : emptyArray); // When there are no attributes, React wants {} return visitJsxOpeningLikeElementOrFragmentJSX( tagName, objectProperties, @@ -335,7 +398,8 @@ export function transformJsx(context: TransformationContext): (x: SourceFile | B location: TextRange, ) { const nonWhitespaceChildren = getSemanticJsxChildren(children); - const isStaticChildren = length(nonWhitespaceChildren) > 1 || !!(nonWhitespaceChildren[0] as JsxExpression)?.dotDotDotToken; + const isStaticChildren = length(nonWhitespaceChildren) > 1 + || !!(nonWhitespaceChildren[0] as JsxExpression)?.dotDotDotToken; const args: Expression[] = [tagName, objectProperties]; // function jsx(type, config, maybeKey) {} // "maybeKey" is optional. It is acceptable to use "_jsx" without a third argument @@ -356,7 +420,10 @@ export function transformJsx(context: TransformationContext): (x: SourceFile | B args.push(factory.createObjectLiteralExpression([ factory.createPropertyAssignment("fileName", getCurrentFileNameExpression()), factory.createPropertyAssignment("lineNumber", factory.createNumericLiteral(lineCol.line + 1)), - factory.createPropertyAssignment("columnNumber", factory.createNumericLiteral(lineCol.character + 1)), + factory.createPropertyAssignment( + "columnNumber", + factory.createNumericLiteral(lineCol.character + 1), + ), ])); // __self development flag args.push(factory.createThis()); @@ -375,11 +442,16 @@ export function transformJsx(context: TransformationContext): (x: SourceFile | B return element; } - function visitJsxOpeningLikeElementCreateElement(node: JsxOpeningLikeElement, children: readonly JsxChild[] | undefined, isChild: boolean, location: TextRange) { + function visitJsxOpeningLikeElementCreateElement( + node: JsxOpeningLikeElement, + children: readonly JsxChild[] | undefined, + isChild: boolean, + location: TextRange, + ) { const tagName = getTagName(node); const attrs = node.attributes.properties; - const objectProperties = length(attrs) ? transformJsxAttributesToObjectProps(attrs) : - factory.createNull(); // When there are no attributes, React wants "null" + const objectProperties = length(attrs) ? transformJsxAttributesToObjectProps(attrs) + : factory.createNull(); // When there are no attributes, React wants "null" const callee = currentFileState.importSpecifier === undefined ? createJsxFactoryExpression( @@ -406,7 +478,12 @@ export function transformJsx(context: TransformationContext): (x: SourceFile | B return element; } - function visitJsxOpeningFragmentJSX(_node: JsxOpeningFragment, children: readonly JsxChild[], isChild: boolean, location: TextRange) { + function visitJsxOpeningFragmentJSX( + _node: JsxOpeningFragment, + children: readonly JsxChild[], + isChild: boolean, + location: TextRange, + ) { let childrenProps: Expression | undefined; if (children && children.length) { const result = convertJsxChildrenToChildrenPropObject(children); @@ -424,7 +501,12 @@ export function transformJsx(context: TransformationContext): (x: SourceFile | B ); } - function visitJsxOpeningFragmentCreateElement(node: JsxOpeningFragment, children: readonly JsxChild[], isChild: boolean, location: TextRange) { + function visitJsxOpeningFragmentCreateElement( + node: JsxOpeningFragment, + children: readonly JsxChild[], + isChild: boolean, + location: TextRange, + ) { const element = createExpressionForJsxFragment( factory, context.getEmitResolver().getJsxFactoryEntity(currentSourceFile), @@ -449,21 +531,40 @@ export function transformJsx(context: TransformationContext): (x: SourceFile | B return factory.createSpreadAssignment(Debug.checkDefined(visitNode(node.expression, visitor, isExpression))); } - function transformJsxAttributesToObjectProps(attrs: readonly (JsxSpreadAttribute | JsxAttribute)[], children?: PropertyAssignment) { + function transformJsxAttributesToObjectProps( + attrs: readonly (JsxSpreadAttribute | JsxAttribute)[], + children?: PropertyAssignment, + ) { const target = getEmitScriptTarget(compilerOptions); - return target && target >= ScriptTarget.ES2018 ? factory.createObjectLiteralExpression(transformJsxAttributesToProps(attrs, children)) : - transformJsxAttributesToExpression(attrs, children); + return target && target >= ScriptTarget.ES2018 + ? factory.createObjectLiteralExpression(transformJsxAttributesToProps(attrs, children)) + : transformJsxAttributesToExpression(attrs, children); } - function transformJsxAttributesToProps(attrs: readonly (JsxSpreadAttribute | JsxAttribute)[], children?: PropertyAssignment) { - const props = flatten(spanMap(attrs, isJsxSpreadAttribute, (attrs, isSpread) => flatten(map(attrs, attr => isSpread ? transformJsxSpreadAttributeToProps(attr as JsxSpreadAttribute) : transformJsxAttributeToObjectLiteralElement(attr as JsxAttribute))))); + function transformJsxAttributesToProps( + attrs: readonly (JsxSpreadAttribute | JsxAttribute)[], + children?: PropertyAssignment, + ) { + const props = flatten( + spanMap( + attrs, + isJsxSpreadAttribute, + (attrs, isSpread) => + flatten(map(attrs, attr => + isSpread ? transformJsxSpreadAttributeToProps(attr as JsxSpreadAttribute) + : transformJsxAttributeToObjectLiteralElement(attr as JsxAttribute))), + ), + ); if (children) { props.push(children); } return props; } - function transformJsxAttributesToExpression(attrs: readonly (JsxSpreadAttribute | JsxAttribute)[], children?: PropertyAssignment) { + function transformJsxAttributesToExpression( + attrs: readonly (JsxSpreadAttribute | JsxAttribute)[], + children?: PropertyAssignment, + ) { const expressions: Expression[] = []; let properties: ObjectLiteralElementLike[] = []; @@ -525,7 +626,8 @@ export function transformJsx(context: TransformationContext): (x: SourceFile | B if (node.kind === SyntaxKind.StringLiteral) { // Always recreate the literal to escape any escape sequences or newlines which may be in the original jsx string and which // Need to be escaped to be handled correctly in a normal string - const singleQuote = node.singleQuote !== undefined ? node.singleQuote : !isStringDoubleQuoted(node, currentSourceFile); + const singleQuote = node.singleQuote !== undefined ? node.singleQuote + : !isStringDoubleQuoted(node, currentSourceFile); const literal = factory.createStringLiteral(tryDecodeEntities(node.text) || node.text, singleQuote); return setTextRange(literal, node); } @@ -583,7 +685,10 @@ export function transformJsx(context: TransformationContext): (x: SourceFile | B // If we've seen any non-whitespace characters on this line, add the 'trim' of the line. // (lastNonWhitespace === -1 is a special flag to detect whether the first line is all whitespace.) if (firstNonWhitespace !== -1 && lastNonWhitespace !== -1) { - acc = addLineOfJsxText(acc, text.substr(firstNonWhitespace, lastNonWhitespace - firstNonWhitespace + 1)); + acc = addLineOfJsxText( + acc, + text.substr(firstNonWhitespace, lastNonWhitespace - firstNonWhitespace + 1), + ); } // Reset firstNonWhitespace for the next line. @@ -617,19 +722,22 @@ export function transformJsx(context: TransformationContext): (x: SourceFile | B * See https://en.wikipedia.org/wiki/List_of_XML_and_HTML_character_entity_references */ function decodeEntities(text: string): string { - return text.replace(/&((#((\d+)|x([\da-fA-F]+)))|(\w+));/g, (match, _all, _number, _digits, decimal, hex, word) => { - if (decimal) { - return utf16EncodeAsString(parseInt(decimal, 10)); - } - else if (hex) { - return utf16EncodeAsString(parseInt(hex, 16)); - } - else { - const ch = entities.get(word); - // If this is not a valid entity, then just use `match` (replace it with itself, i.e. don't replace) - return ch ? utf16EncodeAsString(ch) : match; - } - }); + return text.replace( + /&((#((\d+)|x([\da-fA-F]+)))|(\w+));/g, + (match, _all, _number, _digits, decimal, hex, word) => { + if (decimal) { + return utf16EncodeAsString(parseInt(decimal, 10)); + } + else if (hex) { + return utf16EncodeAsString(parseInt(hex, 16)); + } + else { + const ch = entities.get(word); + // If this is not a valid entity, then just use `match` (replace it with itself, i.e. don't replace) + return ch ? utf16EncodeAsString(ch) : match; + } + }, + ); } /** Like `decodeEntities` but returns `undefined` if there were no entities to decode. */ diff --git a/src/compiler/transformers/legacyDecorators.ts b/src/compiler/transformers/legacyDecorators.ts index 0039c44f499c4..a722c2dfa7d14 100644 --- a/src/compiler/transformers/legacyDecorators.ts +++ b/src/compiler/transformers/legacyDecorators.ts @@ -85,7 +85,9 @@ import { } from "../_namespaces/ts"; /** @internal */ -export function transformLegacyDecorators(context: TransformationContext): (x: SourceFile | Bundle) => SourceFile | Bundle { +export function transformLegacyDecorators( + context: TransformationContext, +): (x: SourceFile | Bundle) => SourceFile | Bundle { const { factory, getEmitHelperFactory: emitHelpers, @@ -151,13 +153,16 @@ export function transformLegacyDecorators(context: TransformationContext): (x: S } function visitClassDeclaration(node: ClassDeclaration): VisitResult { - if (!(classOrConstructorParameterIsDecorated(/*useLegacyDecorators*/ true, node) || childIsDecorated(/*useLegacyDecorators*/ true, node))) { + if ( + !(classOrConstructorParameterIsDecorated(/*useLegacyDecorators*/ true, node) + || childIsDecorated(/*useLegacyDecorators*/ true, node)) + ) { return visitEachChild(node, visitor, context); } - const statements = classOrConstructorParameterIsDecorated(/*useLegacyDecorators*/ true, node) ? - transformClassDeclarationWithClassDecorators(node, node.name) : - transformClassDeclarationWithoutClassDecorators(node, node.name); + const statements = classOrConstructorParameterIsDecorated(/*useLegacyDecorators*/ true, node) + ? transformClassDeclarationWithClassDecorators(node, node.name) + : transformClassDeclarationWithoutClassDecorators(node, node.name); return singleOrMany(statements); } @@ -166,7 +171,9 @@ export function transformLegacyDecorators(context: TransformationContext): (x: S return !!(decorator.transformFlags & TransformFlags.ContainsPrivateIdentifierInExpression); } - function parameterDecoratorsContainPrivateIdentifierInExpression(parameterDecorators: readonly Decorator[] | undefined) { + function parameterDecoratorsContainPrivateIdentifierInExpression( + parameterDecorators: readonly Decorator[] | undefined, + ) { return some(parameterDecorators, decoratorContainsPrivateIdentifierInExpression); } @@ -322,16 +329,20 @@ export function transformLegacyDecorators(context: TransformationContext): (x: S const isExport = hasSyntacticModifier(node, ModifierFlags.Export); const isDefault = hasSyntacticModifier(node, ModifierFlags.Default); - const modifiers = visitNodes(node.modifiers, node => isExportOrDefaultModifier(node) || isDecorator(node) ? undefined : node, isModifierLike); + const modifiers = visitNodes( + node.modifiers, + node => isExportOrDefaultModifier(node) || isDecorator(node) ? undefined : node, + isModifierLike, + ); const location = moveRangePastModifiers(node); const classAlias = getClassAliasIfNeeded(node); // When we transform to ES5/3 this will be moved inside an IIFE and should reference the name // without any block-scoped variable collision handling - const declName = languageVersion < ScriptTarget.ES2015 ? - factory.getInternalName(node, /*allowComments*/ false, /*allowSourceMaps*/ true) : - factory.getLocalName(node, /*allowComments*/ false, /*allowSourceMaps*/ true); + const declName = languageVersion < ScriptTarget.ES2015 + ? factory.getInternalName(node, /*allowComments*/ false, /*allowSourceMaps*/ true) + : factory.getLocalName(node, /*allowComments*/ false, /*allowSourceMaps*/ true); // ... = class ${name} ${heritageClauses} { // ${members} @@ -344,11 +355,14 @@ export function transformLegacyDecorators(context: TransformationContext): (x: S // If we're emitting to ES2022 or later then we need to reassign the class alias before // static initializers are evaluated. - const assignClassAliasInStaticBlock = languageVersion >= ScriptTarget.ES2022 && - !!classAlias && - some(members, member => - isPropertyDeclaration(member) && hasSyntacticModifier(member, ModifierFlags.Static) || - isClassStaticBlockDeclaration(member)); + const assignClassAliasInStaticBlock = languageVersion >= ScriptTarget.ES2022 + && !!classAlias + && some( + members, + member => + isPropertyDeclaration(member) && hasSyntacticModifier(member, ModifierFlags.Static) + || isClassStaticBlockDeclaration(member), + ); if (assignClassAliasInStaticBlock) { members = setTextRange( factory.createNodeArray([ @@ -378,8 +392,14 @@ export function transformLegacyDecorators(context: TransformationContext): (x: S // let ${name} = ${classExpression} where name is either declaredName if the class doesn't contain self-reference // or decoratedClassAlias if the class contain self-reference. - const varInitializer = classAlias && !assignClassAliasInStaticBlock ? factory.createAssignment(classAlias, classExpression) : classExpression; - const varDecl = factory.createVariableDeclaration(declName, /*exclamationToken*/ undefined, /*type*/ undefined, varInitializer); + const varInitializer = classAlias && !assignClassAliasInStaticBlock + ? factory.createAssignment(classAlias, classExpression) : classExpression; + const varDecl = factory.createVariableDeclaration( + declName, + /*exclamationToken*/ undefined, + /*type*/ undefined, + varInitializer, + ); setOriginalNode(varDecl, node); const varDeclList = factory.createVariableDeclarationList([varDecl], NodeFlags.Let); @@ -552,7 +572,13 @@ export function transformLegacyDecorators(context: TransformationContext): (x: S * instance members. */ function addClassElementDecorationStatements(statements: Statement[], node: ClassDeclaration, isStatic: boolean) { - addRange(statements, map(generateClassElementDecorationExpressions(node, isStatic), expr => factory.createExpressionStatement(expr))); + addRange( + statements, + map( + generateClassElementDecorationExpressions(node, isStatic), + expr => factory.createExpressionStatement(expr), + ), + ); } /** @@ -574,7 +600,10 @@ export function transformLegacyDecorators(context: TransformationContext): (x: S * @param isStatic A value indicating whether to retrieve static or instance members of * the class. */ - function getDecoratedClassElements(node: ClassExpression | ClassDeclaration, isStatic: boolean): readonly ClassElement[] { + function getDecoratedClassElements( + node: ClassExpression | ClassDeclaration, + isStatic: boolean, + ): readonly ClassElement[] { return filter(node.members, m => isDecoratedClassElement(m, isStatic, node)); } @@ -640,7 +669,10 @@ export function transformLegacyDecorators(context: TransformationContext): (x: S // const prefix = getClassMemberPrefix(node, member); - const memberName = getExpressionForPropertyName(member, /*generateNameForComputedPropertyName*/ !hasSyntacticModifier(member, ModifierFlags.Ambient)); + const memberName = getExpressionForPropertyName( + member, + /*generateNameForComputedPropertyName*/ !hasSyntacticModifier(member, ModifierFlags.Ambient), + ); const descriptor = languageVersion > ScriptTarget.ES3 ? isPropertyDeclaration(member) && !hasAccessorModifier(member) // We emit `void 0` here to indicate to `__decorate` that it can invoke `Object.defineProperty` directly, but that it @@ -691,11 +723,14 @@ export function transformLegacyDecorators(context: TransformationContext): (x: S // When we transform to ES5/3 this will be moved inside an IIFE and should reference the name // without any block-scoped variable collision handling - const localName = languageVersion < ScriptTarget.ES2015 ? - factory.getInternalName(node, /*allowComments*/ false, /*allowSourceMaps*/ true) : - factory.getDeclarationName(node, /*allowComments*/ false, /*allowSourceMaps*/ true); + const localName = languageVersion < ScriptTarget.ES2015 + ? factory.getInternalName(node, /*allowComments*/ false, /*allowSourceMaps*/ true) + : factory.getDeclarationName(node, /*allowComments*/ false, /*allowSourceMaps*/ true); const decorate = emitHelpers().createDecorateHelper(decoratorExpressions, localName); - const expression = factory.createAssignment(localName, classAlias ? factory.createAssignment(classAlias, decorate) : decorate); + const expression = factory.createAssignment( + localName, + classAlias ? factory.createAssignment(classAlias, decorate) : decorate, + ); setEmitFlags(expression, EmitFlags.NoComments); setSourceMapRange(expression, moveRangePastModifiers(node)); return expression; @@ -740,7 +775,10 @@ export function transformLegacyDecorators(context: TransformationContext): (x: S * * @param member The member whose name should be converted into an expression. */ - function getExpressionForPropertyName(member: ClassElement | EnumMember, generateNameForComputedPropertyName: boolean): Expression { + function getExpressionForPropertyName( + member: ClassElement | EnumMember, + generateNameForComputedPropertyName: boolean, + ): Expression { const name = member.name!; if (isPrivateIdentifier(name)) { return factory.createIdentifier(""); @@ -777,7 +815,9 @@ export function transformLegacyDecorators(context: TransformationContext): (x: S function getClassAliasIfNeeded(node: ClassDeclaration) { if (resolver.getNodeCheckFlags(node) & NodeCheckFlags.ContainsConstructorReference) { enableSubstitutionForClassAliases(); - const classAlias = factory.createUniqueName(node.name && !isGeneratedIdentifier(node.name) ? idText(node.name) : "default"); + const classAlias = factory.createUniqueName( + node.name && !isGeneratedIdentifier(node.name) ? idText(node.name) : "default", + ); classAliases[getOriginalNodeId(node)] = classAlias; hoistVariableDeclaration(classAlias); return classAlias; diff --git a/src/compiler/transformers/module/esnextAnd2015.ts b/src/compiler/transformers/module/esnextAnd2015.ts index 9e41ffc75de04..3d0f6f7439c33 100644 --- a/src/compiler/transformers/module/esnextAnd2015.ts +++ b/src/compiler/transformers/module/esnextAnd2015.ts @@ -51,7 +51,9 @@ import { } from "../../_namespaces/ts"; /** @internal */ -export function transformECMAScriptModule(context: TransformationContext): (x: SourceFile | Bundle) => SourceFile | Bundle { +export function transformECMAScriptModule( + context: TransformationContext, +): (x: SourceFile | Bundle) => SourceFile | Bundle { const { factory, getEmitHelperFactory: emitHelpers, @@ -85,7 +87,12 @@ export function transformECMAScriptModule(context: TransformationContext): (x: S if (importRequireStatements) { result = factory.updateSourceFile( result, - setTextRange(factory.createNodeArray(insertStatementsAfterCustomPrologue(result.statements.slice(), importRequireStatements)), result.statements), + setTextRange( + factory.createNodeArray( + insertStatementsAfterCustomPrologue(result.statements.slice(), importRequireStatements), + ), + result.statements, + ), ); } if (!isExternalModule(node) || some(result.statements, isExternalModuleIndicator)) { @@ -93,7 +100,10 @@ export function transformECMAScriptModule(context: TransformationContext): (x: S } return factory.updateSourceFile( result, - setTextRange(factory.createNodeArray([...result.statements, createEmptyExports(factory)]), result.statements), + setTextRange( + factory.createNodeArray([...result.statements, createEmptyExports(factory)]), + result.statements, + ), ); } @@ -101,7 +111,12 @@ export function transformECMAScriptModule(context: TransformationContext): (x: S } function updateExternalModule(node: SourceFile) { - const externalHelpersImportDeclaration = createExternalHelpersImportDeclarationIfNeeded(factory, emitHelpers(), node, compilerOptions); + const externalHelpersImportDeclaration = createExternalHelpersImportDeclarationIfNeeded( + factory, + emitHelpers(), + node, + compilerOptions, + ); if (externalHelpersImportDeclaration) { const statements: Statement[] = []; const statementOffset = factory.copyPrologue(node.statements, statements); @@ -124,7 +139,8 @@ export function transformECMAScriptModule(context: TransformationContext): (x: S // Though an error in es2020 modules, in node-flavor es2020 modules, we can helpfully transform this to a synthetic `require` call // To give easy access to a synchronous `require` in node-flavor esm. We do the transform even in scenarios where we error, but `import.meta.url` // is available, just because the output is reasonable for a node-like runtime. - return getEmitModuleKind(compilerOptions) >= ModuleKind.Node16 ? visitImportEqualsDeclaration(node as ImportEqualsDeclaration) : undefined; + return getEmitModuleKind(compilerOptions) >= ModuleKind.Node16 + ? visitImportEqualsDeclaration(node as ImportEqualsDeclaration) : undefined; case SyntaxKind.ExportAssignment: return visitExportAssignment(node as ExportAssignment); case SyntaxKind.ExportDeclaration: @@ -141,26 +157,43 @@ export function transformECMAScriptModule(context: TransformationContext): (x: S * @param importNode The declaration to import. */ function createRequireCall(importNode: ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration) { - const moduleName = getExternalModuleNameLiteral(factory, importNode, Debug.checkDefined(currentSourceFile), host, resolver, compilerOptions); + const moduleName = getExternalModuleNameLiteral( + factory, + importNode, + Debug.checkDefined(currentSourceFile), + host, + resolver, + compilerOptions, + ); const args: Expression[] = []; if (moduleName) { args.push(moduleName); } if (!importRequireStatements) { - const createRequireName = factory.createUniqueName("_createRequire", GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel); + const createRequireName = factory.createUniqueName( + "_createRequire", + GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel, + ); const importStatement = factory.createImportDeclaration( /*modifiers*/ undefined, factory.createImportClause( /*isTypeOnly*/ false, /*name*/ undefined, factory.createNamedImports([ - factory.createImportSpecifier(/*isTypeOnly*/ false, factory.createIdentifier("createRequire"), createRequireName), + factory.createImportSpecifier( + /*isTypeOnly*/ false, + factory.createIdentifier("createRequire"), + createRequireName, + ), ]), ), factory.createStringLiteral("module"), ); - const requireHelperName = factory.createUniqueName("__require", GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel); + const requireHelperName = factory.createUniqueName( + "__require", + GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel, + ); const requireStatement = factory.createVariableStatement( /*modifiers*/ undefined, factory.createVariableDeclarationList( @@ -169,9 +202,19 @@ export function transformECMAScriptModule(context: TransformationContext): (x: S requireHelperName, /*exclamationToken*/ undefined, /*type*/ undefined, - factory.createCallExpression(factory.cloneNode(createRequireName), /*typeArguments*/ undefined, [ - factory.createPropertyAccessExpression(factory.createMetaProperty(SyntaxKind.ImportKeyword, factory.createIdentifier("meta")), factory.createIdentifier("url")), - ]), + factory.createCallExpression( + factory.cloneNode(createRequireName), + /*typeArguments*/ undefined, + [ + factory.createPropertyAccessExpression( + factory.createMetaProperty( + SyntaxKind.ImportKeyword, + factory.createIdentifier("meta"), + ), + factory.createIdentifier("url"), + ), + ], + ), ), ], /*flags*/ languageVersion >= ScriptTarget.ES2015 ? NodeFlags.Const : NodeFlags.None, @@ -191,7 +234,10 @@ export function transformECMAScriptModule(context: TransformationContext): (x: S * @param node The node to visit. */ function visitImportEqualsDeclaration(node: ImportEqualsDeclaration): VisitResult { - Debug.assert(isExternalModuleImportEqualsDeclaration(node), "import= for internal module references should be handled in an earlier transformer."); + Debug.assert( + isExternalModuleImportEqualsDeclaration(node), + "import= for internal module references should be handled in an earlier transformer.", + ); let statements: Statement[] | undefined; statements = append( @@ -223,14 +269,23 @@ export function transformECMAScriptModule(context: TransformationContext): (x: S return singleOrMany(statements); } - function appendExportsOfImportEqualsDeclaration(statements: Statement[] | undefined, node: ImportEqualsDeclaration) { + function appendExportsOfImportEqualsDeclaration( + statements: Statement[] | undefined, + node: ImportEqualsDeclaration, + ) { if (hasSyntacticModifier(node, ModifierFlags.Export)) { statements = append( statements, factory.createExportDeclaration( /*modifiers*/ undefined, node.isTypeOnly, - factory.createNamedExports([factory.createExportSpecifier(/*isTypeOnly*/ false, /*propertyName*/ undefined, idText(node.name))]), + factory.createNamedExports([ + factory.createExportSpecifier( + /*isTypeOnly*/ false, + /*propertyName*/ undefined, + idText(node.name), + ), + ]), ), ); } @@ -269,11 +324,14 @@ export function transformECMAScriptModule(context: TransformationContext): (x: S ); setOriginalNode(importDecl, node.exportClause); - const exportDecl = isExportNamespaceAsDefaultDeclaration(node) ? factory.createExportDefault(synthName) : factory.createExportDeclaration( - /*modifiers*/ undefined, - /*isTypeOnly*/ false, - factory.createNamedExports([factory.createExportSpecifier(/*isTypeOnly*/ false, synthName, oldIdentifier)]), - ); + const exportDecl = isExportNamespaceAsDefaultDeclaration(node) ? factory.createExportDefault(synthName) + : factory.createExportDeclaration( + /*modifiers*/ undefined, + /*isTypeOnly*/ false, + factory.createNamedExports([ + factory.createExportSpecifier(/*isTypeOnly*/ false, synthName, oldIdentifier), + ]), + ); setOriginalNode(exportDecl, node); return [importDecl, exportDecl]; @@ -326,7 +384,13 @@ export function transformECMAScriptModule(context: TransformationContext): (x: S const name = idText(node); let substitution = helperNameSubstitutions!.get(name); if (!substitution) { - helperNameSubstitutions!.set(name, substitution = factory.createUniqueName(name, GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel)); + helperNameSubstitutions!.set( + name, + substitution = factory.createUniqueName( + name, + GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel, + ), + ); } return substitution; } diff --git a/src/compiler/transformers/module/module.ts b/src/compiler/transformers/module/module.ts index 6b60336995975..86665501c1940 100644 --- a/src/compiler/transformers/module/module.ts +++ b/src/compiler/transformers/module/module.ts @@ -222,10 +222,10 @@ export function transformModule(context: TransformationContext): (x: SourceFile */ function transformSourceFile(node: SourceFile) { if ( - node.isDeclarationFile || - !(isEffectiveExternalModule(node, compilerOptions) || - node.transformFlags & TransformFlags.ContainsDynamicImport || - (isJsonSourceFile(node) && hasJsonModuleEmitEnabled(compilerOptions) && outFile(compilerOptions))) + node.isDeclarationFile + || !(isEffectiveExternalModule(node, compilerOptions) + || node.transformFlags & TransformFlags.ContainsDynamicImport + || (isJsonSourceFile(node) && hasJsonModuleEmitEnabled(compilerOptions) && outFile(compilerOptions))) ) { return node; } @@ -259,8 +259,14 @@ export function transformModule(context: TransformationContext): (x: SourceFile startLexicalEnvironment(); const statements: Statement[] = []; - const ensureUseStrict = getStrictOptionValue(compilerOptions, "alwaysStrict") || (!compilerOptions.noImplicitUseStrict && isExternalModule(currentSourceFile)); - const statementOffset = factory.copyPrologue(node.statements, statements, ensureUseStrict && !isJsonSourceFile(node), topLevelVisitor); + const ensureUseStrict = getStrictOptionValue(compilerOptions, "alwaysStrict") + || (!compilerOptions.noImplicitUseStrict && isExternalModule(currentSourceFile)); + const statementOffset = factory.copyPrologue( + node.statements, + statements, + ensureUseStrict && !isJsonSourceFile(node), + topLevelVisitor, + ); if (shouldEmitUnderscoreUnderscoreESModule()) { append(statements, createUnderscoreUnderscoreESModule()); @@ -273,7 +279,14 @@ export function transformModule(context: TransformationContext): (x: SourceFile factory.createExpressionStatement( reduceLeft( currentModuleInfo.exportedNames!.slice(i, i + chunkSize), - (prev, nextId) => factory.createAssignment(factory.createPropertyAccessExpression(factory.createIdentifier("exports"), factory.createIdentifier(idText(nextId))), prev), + (prev, nextId) => + factory.createAssignment( + factory.createPropertyAccessExpression( + factory.createIdentifier("exports"), + factory.createIdentifier(idText(nextId)), + ), + prev, + ), factory.createVoidZero() as Expression, ), ), @@ -286,7 +299,10 @@ export function transformModule(context: TransformationContext): (x: SourceFile addExportEqualsIfNeeded(statements, /*emitAsReturn*/ false); insertStatementsAfterStandardPrologue(statements, endLexicalEnvironment()); - const updated = factory.updateSourceFile(node, setTextRange(factory.createNodeArray(statements), node.statements)); + const updated = factory.updateSourceFile( + node, + setTextRange(factory.createNodeArray(statements), node.statements), + ); addEmitHelpers(updated, context.readEmitHelpers()); return updated; } @@ -322,7 +338,10 @@ export function transformModule(context: TransformationContext): (x: SourceFile // // we need to add modules without alias names to the end of the dependencies list - const { aliasedModuleNames, unaliasedModuleNames, importAliasNames } = collectAsynchronousDependencies(node, /*includeNonAmdDependencies*/ true); + const { aliasedModuleNames, unaliasedModuleNames, importAliasNames } = collectAsynchronousDependencies( + node, + /*includeNonAmdDependencies*/ true, + ); // Create an updated SourceFile: // @@ -354,16 +373,25 @@ export function transformModule(context: TransformationContext): (x: SourceFile // Add the module body function argument: // // function (require, exports, module1, module2) ... - jsonSourceFile ? - jsonSourceFile.statements.length ? jsonSourceFile.statements[0].expression : factory.createObjectLiteralExpression() : - factory.createFunctionExpression( + jsonSourceFile + ? jsonSourceFile.statements.length ? jsonSourceFile.statements[0].expression + : factory.createObjectLiteralExpression() + : factory.createFunctionExpression( /*modifiers*/ undefined, /*asteriskToken*/ undefined, /*name*/ undefined, /*typeParameters*/ undefined, [ - factory.createParameterDeclaration(/*modifiers*/ undefined, /*dotDotDotToken*/ undefined, "require"), - factory.createParameterDeclaration(/*modifiers*/ undefined, /*dotDotDotToken*/ undefined, "exports"), + factory.createParameterDeclaration( + /*modifiers*/ undefined, + /*dotDotDotToken*/ undefined, + "require", + ), + factory.createParameterDeclaration( + /*modifiers*/ undefined, + /*dotDotDotToken*/ undefined, + "exports", + ), ...importAliasNames, ], /*type*/ undefined, @@ -387,7 +415,10 @@ export function transformModule(context: TransformationContext): (x: SourceFile * @param node The SourceFile node. */ function transformUMDModule(node: SourceFile) { - const { aliasedModuleNames, unaliasedModuleNames, importAliasNames } = collectAsynchronousDependencies(node, /*includeNonAmdDependencies*/ false); + const { aliasedModuleNames, unaliasedModuleNames, importAliasNames } = collectAsynchronousDependencies( + node, + /*includeNonAmdDependencies*/ false, + ); const moduleName = tryGetModuleNameFromFile(factory, node, host, compilerOptions); const umdHeader = factory.createFunctionExpression( /*modifiers*/ undefined, @@ -402,7 +433,13 @@ export function transformModule(context: TransformationContext): (x: SourceFile factory.createIfStatement( factory.createLogicalAnd( factory.createTypeCheck(factory.createIdentifier("module"), "object"), - factory.createTypeCheck(factory.createPropertyAccessExpression(factory.createIdentifier("module"), "exports"), "object"), + factory.createTypeCheck( + factory.createPropertyAccessExpression( + factory.createIdentifier("module"), + "exports", + ), + "object", + ), ), factory.createBlock([ factory.createVariableStatement( @@ -431,7 +468,10 @@ export function transformModule(context: TransformationContext): (x: SourceFile ), factory.createExpressionStatement( factory.createAssignment( - factory.createPropertyAccessExpression(factory.createIdentifier("module"), "exports"), + factory.createPropertyAccessExpression( + factory.createIdentifier("module"), + "exports", + ), factory.createIdentifier("v"), ), ), @@ -502,8 +542,16 @@ export function transformModule(context: TransformationContext): (x: SourceFile /*name*/ undefined, /*typeParameters*/ undefined, [ - factory.createParameterDeclaration(/*modifiers*/ undefined, /*dotDotDotToken*/ undefined, "require"), - factory.createParameterDeclaration(/*modifiers*/ undefined, /*dotDotDotToken*/ undefined, "exports"), + factory.createParameterDeclaration( + /*modifiers*/ undefined, + /*dotDotDotToken*/ undefined, + "require", + ), + factory.createParameterDeclaration( + /*modifiers*/ undefined, + /*dotDotDotToken*/ undefined, + "exports", + ), ...importAliasNames, ], /*type*/ undefined, @@ -527,7 +575,10 @@ export function transformModule(context: TransformationContext): (x: SourceFile * @param node The source file. * @param includeNonAmdDependencies A value indicating whether to include non-AMD dependencies. */ - function collectAsynchronousDependencies(node: SourceFile, includeNonAmdDependencies: boolean): AsynchronousDependencies { + function collectAsynchronousDependencies( + node: SourceFile, + includeNonAmdDependencies: boolean, + ): AsynchronousDependencies { // names of modules with corresponding parameter in the factory function const aliasedModuleNames: Expression[] = []; @@ -543,7 +594,13 @@ export function transformModule(context: TransformationContext): (x: SourceFile for (const amdDependency of node.amdDependencies) { if (amdDependency.name) { aliasedModuleNames.push(factory.createStringLiteral(amdDependency.path)); - importAliasNames.push(factory.createParameterDeclaration(/*modifiers*/ undefined, /*dotDotDotToken*/ undefined, amdDependency.name)); + importAliasNames.push( + factory.createParameterDeclaration( + /*modifiers*/ undefined, + /*dotDotDotToken*/ undefined, + amdDependency.name, + ), + ); } else { unaliasedModuleNames.push(factory.createStringLiteral(amdDependency.path)); @@ -552,7 +609,14 @@ export function transformModule(context: TransformationContext): (x: SourceFile for (const importNode of currentModuleInfo.externalImports) { // Find the name of the external module - const externalModuleName = getExternalModuleNameLiteral(factory, importNode, currentSourceFile, host, resolver, compilerOptions); + const externalModuleName = getExternalModuleNameLiteral( + factory, + importNode, + currentSourceFile, + host, + resolver, + compilerOptions, + ); // Find the name of the module alias, if there is one const importAliasName = getLocalNameForExternalImport(factory, importNode, currentSourceFile); @@ -565,7 +629,13 @@ export function transformModule(context: TransformationContext): (x: SourceFile // This is so that when printer will not substitute the identifier setEmitFlags(importAliasName, EmitFlags.NoSubstitution); aliasedModuleNames.push(externalModuleName); - importAliasNames.push(factory.createParameterDeclaration(/*modifiers*/ undefined, /*dotDotDotToken*/ undefined, importAliasName)); + importAliasNames.push( + factory.createParameterDeclaration( + /*modifiers*/ undefined, + /*dotDotDotToken*/ undefined, + importAliasName, + ), + ); } else { unaliasedModuleNames.push(externalModuleName); @@ -577,7 +647,10 @@ export function transformModule(context: TransformationContext): (x: SourceFile } function getAMDImportExpressionForImport(node: ImportDeclaration | ExportDeclaration | ImportEqualsDeclaration) { - if (isImportEqualsDeclaration(node) || isExportDeclaration(node) || !getExternalModuleNameLiteral(factory, node, currentSourceFile, host, resolver, compilerOptions)) { + if ( + isImportEqualsDeclaration(node) || isExportDeclaration(node) + || !getExternalModuleNameLiteral(factory, node, currentSourceFile, host, resolver, compilerOptions) + ) { return undefined; } const name = getLocalNameForExternalImport(factory, node, currentSourceFile)!; // TODO: GH#18217 @@ -597,13 +670,30 @@ export function transformModule(context: TransformationContext): (x: SourceFile startLexicalEnvironment(); const statements: Statement[] = []; - const statementOffset = factory.copyPrologue(node.statements, statements, /*ensureUseStrict*/ !compilerOptions.noImplicitUseStrict, topLevelVisitor); + const statementOffset = factory.copyPrologue( + node.statements, + statements, + /*ensureUseStrict*/ !compilerOptions.noImplicitUseStrict, + topLevelVisitor, + ); if (shouldEmitUnderscoreUnderscoreESModule()) { append(statements, createUnderscoreUnderscoreESModule()); } if (length(currentModuleInfo.exportedNames)) { - append(statements, factory.createExpressionStatement(reduceLeft(currentModuleInfo.exportedNames, (prev, nextId) => factory.createAssignment(factory.createPropertyAccessExpression(factory.createIdentifier("exports"), factory.createIdentifier(idText(nextId))), prev), factory.createVoidZero() as Expression))); + append( + statements, + factory.createExpressionStatement( + reduceLeft(currentModuleInfo.exportedNames, (prev, nextId) => + factory.createAssignment( + factory.createPropertyAccessExpression( + factory.createIdentifier("exports"), + factory.createIdentifier(idText(nextId)), + ), + prev, + ), factory.createVoidZero() as Expression), + ), + ); } // Visit each statement of the module body. @@ -762,7 +852,11 @@ export function transformModule(context: TransformationContext): (x: SourceFile function visitorWorker(node: Node, valueIsDiscarded: boolean): VisitResult { // This visitor does not need to descend into the tree if there is no dynamic import, destructuring assignment, or update expression // as export/import statements are only transformed at the top level of a file. - if (!(node.transformFlags & (TransformFlags.ContainsDynamicImport | TransformFlags.ContainsDestructuringAssignment | TransformFlags.ContainsUpdateExpressionForIdentifier))) { + if ( + !(node.transformFlags + & (TransformFlags.ContainsDynamicImport | TransformFlags.ContainsDestructuringAssignment + | TransformFlags.ContainsUpdateExpressionForIdentifier)) + ) { return node; } @@ -787,7 +881,10 @@ export function transformModule(context: TransformationContext): (x: SourceFile break; case SyntaxKind.PrefixUnaryExpression: case SyntaxKind.PostfixUnaryExpression: - return visitPreOrPostfixUnaryExpression(node as PrefixUnaryExpression | PostfixUnaryExpression, valueIsDiscarded); + return visitPreOrPostfixUnaryExpression( + node as PrefixUnaryExpression | PostfixUnaryExpression, + valueIsDiscarded, + ); } return visitEachChild(node, visitor, context); @@ -849,18 +946,29 @@ export function transformModule(context: TransformationContext): (x: SourceFile function visitDestructuringAssignment(node: DestructuringAssignment, valueIsDiscarded: boolean): Expression { if (destructuringNeedsFlattening(node.left)) { - return flattenDestructuringAssignment(node, visitor, context, FlattenLevel.All, !valueIsDiscarded, createAllExportExpressions); + return flattenDestructuringAssignment( + node, + visitor, + context, + FlattenLevel.All, + !valueIsDiscarded, + createAllExportExpressions, + ); } return visitEachChild(node, visitor, context); } function visitForStatement(node: ForStatement, isTopLevel: boolean) { if ( - isTopLevel && node.initializer && - isVariableDeclarationList(node.initializer) && - !(node.initializer.flags & NodeFlags.BlockScoped) + isTopLevel && node.initializer + && isVariableDeclarationList(node.initializer) + && !(node.initializer.flags & NodeFlags.BlockScoped) ) { - const exportStatements = appendExportsOfVariableDeclarationList(/*statements*/ undefined, node.initializer, /*isForInOrOfInitializer*/ false); + const exportStatements = appendExportsOfVariableDeclarationList( + /*statements*/ undefined, + node.initializer, + /*isForInOrOfInitializer*/ false, + ); if (exportStatements) { const statements: Statement[] = []; const varDeclList = visitNode(node.initializer, discardedValueVisitor, isVariableDeclarationList); @@ -871,7 +979,9 @@ export function transformModule(context: TransformationContext): (x: SourceFile const condition = visitNode(node.condition, visitor, isExpression); const incrementor = visitNode(node.incrementor, discardedValueVisitor, isExpression); const body = visitIterationBody(node.statement, isTopLevel ? topLevelNestedVisitor : visitor, context); - statements.push(factory.updateForStatement(node, /*initializer*/ undefined, condition, incrementor, body)); + statements.push( + factory.updateForStatement(node, /*initializer*/ undefined, condition, incrementor, body), + ); return statements; } } @@ -891,14 +1001,18 @@ export function transformModule(context: TransformationContext): (x: SourceFile */ function visitForInStatement(node: ForInStatement): VisitResult { if (isVariableDeclarationList(node.initializer) && !(node.initializer.flags & NodeFlags.BlockScoped)) { - const exportStatements = appendExportsOfVariableDeclarationList(/*statements*/ undefined, node.initializer, /*isForInOrOfInitializer*/ true); + const exportStatements = appendExportsOfVariableDeclarationList( + /*statements*/ undefined, + node.initializer, + /*isForInOrOfInitializer*/ true, + ); if (some(exportStatements)) { const initializer = visitNode(node.initializer, discardedValueVisitor, isForInitializer); const expression = visitNode(node.expression, visitor, isExpression); const body = visitIterationBody(node.statement, topLevelNestedVisitor, context); - const mergedBody = isBlock(body) ? - factory.updateBlock(body, [...exportStatements, ...body.statements]) : - factory.createBlock([...exportStatements, body], /*multiLine*/ true); + const mergedBody = isBlock(body) + ? factory.updateBlock(body, [...exportStatements, ...body.statements]) + : factory.createBlock([...exportStatements, body], /*multiLine*/ true); return factory.updateForInStatement(node, initializer, expression, mergedBody); } } @@ -917,14 +1031,18 @@ export function transformModule(context: TransformationContext): (x: SourceFile */ function visitForOfStatement(node: ForOfStatement): VisitResult { if (isVariableDeclarationList(node.initializer) && !(node.initializer.flags & NodeFlags.BlockScoped)) { - const exportStatements = appendExportsOfVariableDeclarationList(/*statements*/ undefined, node.initializer, /*isForInOrOfInitializer*/ true); + const exportStatements = appendExportsOfVariableDeclarationList( + /*statements*/ undefined, + node.initializer, + /*isForInOrOfInitializer*/ true, + ); const initializer = visitNode(node.initializer, discardedValueVisitor, isForInitializer); const expression = visitNode(node.expression, visitor, isExpression); let body = visitIterationBody(node.statement, topLevelNestedVisitor, context); if (some(exportStatements)) { - body = isBlock(body) ? - factory.updateBlock(body, [...exportStatements, ...body.statements]) : - factory.createBlock([...exportStatements, body], /*multiLine*/ true); + body = isBlock(body) + ? factory.updateBlock(body, [...exportStatements, ...body.statements]) + : factory.createBlock([...exportStatements, body], /*multiLine*/ true); } return factory.updateForOfStatement(node, node.awaitModifier, initializer, expression, body); } @@ -1090,14 +1208,23 @@ export function transformModule(context: TransformationContext): (x: SourceFile } function visitParenthesizedExpression(node: ParenthesizedExpression, valueIsDiscarded: boolean) { - return factory.updateParenthesizedExpression(node, visitNode(node.expression, valueIsDiscarded ? discardedValueVisitor : visitor, isExpression)); + return factory.updateParenthesizedExpression( + node, + visitNode(node.expression, valueIsDiscarded ? discardedValueVisitor : visitor, isExpression), + ); } function visitPartiallyEmittedExpression(node: PartiallyEmittedExpression, valueIsDiscarded: boolean) { - return factory.updatePartiallyEmittedExpression(node, visitNode(node.expression, valueIsDiscarded ? discardedValueVisitor : visitor, isExpression)); + return factory.updatePartiallyEmittedExpression( + node, + visitNode(node.expression, valueIsDiscarded ? discardedValueVisitor : visitor, isExpression), + ); } - function visitPreOrPostfixUnaryExpression(node: PrefixUnaryExpression | PostfixUnaryExpression, valueIsDiscarded: boolean) { + function visitPreOrPostfixUnaryExpression( + node: PrefixUnaryExpression | PostfixUnaryExpression, + valueIsDiscarded: boolean, + ) { // When we see a prefix or postfix increment expression whose operand is an exported // symbol, we should ensure all exports of that symbol are updated with the correct // value. @@ -1153,10 +1280,19 @@ export function transformModule(context: TransformationContext): (x: SourceFile if (moduleKind === ModuleKind.None && languageVersion >= ScriptTarget.ES2020) { return visitEachChild(node, visitor, context); } - const externalModuleName = getExternalModuleNameLiteral(factory, node, currentSourceFile, host, resolver, compilerOptions); + const externalModuleName = getExternalModuleNameLiteral( + factory, + node, + currentSourceFile, + host, + resolver, + compilerOptions, + ); const firstArgument = visitNode(firstOrUndefined(node.arguments), visitor, isExpression); // Only use the external module name if it differs from the first argument. This allows us to preserve the quote style of the argument on output. - const argument = externalModuleName && (!firstArgument || !isStringLiteral(firstArgument) || firstArgument.text !== externalModuleName.text) ? externalModuleName : firstArgument; + const argument = externalModuleName + && (!firstArgument || !isStringLiteral(firstArgument) || firstArgument.text !== externalModuleName.text) + ? externalModuleName : firstArgument; const containsLexicalThis = !!(node.transformFlags & TransformFlags.ContainsLexicalThis); switch (compilerOptions.module) { case ModuleKind.AMD: @@ -1185,7 +1321,9 @@ export function transformModule(context: TransformationContext): (x: SourceFile // }); needUMDDynamicImportHelper = true; if (isSimpleCopiableExpression(arg)) { - const argClone = isGeneratedIdentifier(arg) ? arg : isStringLiteral(arg) ? factory.createStringLiteralFromNode(arg) : setEmitFlags(setTextRange(factory.cloneNode(arg), arg), EmitFlags.NoComments); + const argClone = isGeneratedIdentifier(arg) ? arg + : isStringLiteral(arg) ? factory.createStringLiteralFromNode(arg) + : setEmitFlags(setTextRange(factory.cloneNode(arg), arg), EmitFlags.NoComments); return factory.createConditionalExpression( /*condition*/ factory.createIdentifier("__syncRequire"), /*questionToken*/ undefined, @@ -1262,9 +1400,15 @@ export function transformModule(context: TransformationContext): (x: SourceFile } } - const promise = factory.createNewExpression(factory.createIdentifier("Promise"), /*typeArguments*/ undefined, [func]); + const promise = factory.createNewExpression(factory.createIdentifier("Promise"), /*typeArguments*/ undefined, [ + func, + ]); if (getESModuleInterop(compilerOptions)) { - return factory.createCallExpression(factory.createPropertyAccessExpression(promise, factory.createIdentifier("then")), /*typeArguments*/ undefined, [emitHelpers().createImportStarCallbackHelper()]); + return factory.createCallExpression( + factory.createPropertyAccessExpression(promise, factory.createIdentifier("then")), + /*typeArguments*/ undefined, + [emitHelpers().createImportStarCallbackHelper()], + ); } return promise; } @@ -1341,13 +1485,20 @@ export function transformModule(context: TransformationContext): (x: SourceFile ); } - const downleveledImport = factory.createCallExpression(factory.createPropertyAccessExpression(promiseResolveCall, "then"), /*typeArguments*/ undefined, [func]); + const downleveledImport = factory.createCallExpression( + factory.createPropertyAccessExpression(promiseResolveCall, "then"), + /*typeArguments*/ undefined, + [func], + ); return downleveledImport; } function getHelperExpressionForExport(node: ExportDeclaration, innerExpr: Expression) { - if (!getESModuleInterop(compilerOptions) || getInternalEmitFlags(node) & InternalEmitFlags.NeverApplyImportHelper) { + if ( + !getESModuleInterop(compilerOptions) + || getInternalEmitFlags(node) & InternalEmitFlags.NeverApplyImportHelper + ) { return innerExpr; } if (getExportNeedsImportStarHelper(node)) { @@ -1357,7 +1508,10 @@ export function transformModule(context: TransformationContext): (x: SourceFile } function getHelperExpressionForImport(node: ImportDeclaration, innerExpr: Expression) { - if (!getESModuleInterop(compilerOptions) || getInternalEmitFlags(node) & InternalEmitFlags.NeverApplyImportHelper) { + if ( + !getESModuleInterop(compilerOptions) + || getInternalEmitFlags(node) & InternalEmitFlags.NeverApplyImportHelper + ) { return innerExpr; } if (getImportNeedsImportStarHelper(node)) { @@ -1380,7 +1534,10 @@ export function transformModule(context: TransformationContext): (x: SourceFile if (moduleKind !== ModuleKind.AMD) { if (!node.importClause) { // import "mod"; - return setOriginalNode(setTextRange(factory.createExpressionStatement(createRequireCall(node)), node), node); + return setOriginalNode( + setTextRange(factory.createExpressionStatement(createRequireCall(node)), node), + node, + ); } else { const variables: VariableDeclaration[] = []; @@ -1476,7 +1633,14 @@ export function transformModule(context: TransformationContext): (x: SourceFile * @param importNode The declararation to import. */ function createRequireCall(importNode: ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration) { - const moduleName = getExternalModuleNameLiteral(factory, importNode, currentSourceFile, host, resolver, compilerOptions); + const moduleName = getExternalModuleNameLiteral( + factory, + importNode, + currentSourceFile, + host, + resolver, + compilerOptions, + ); const args: Expression[] = []; if (moduleName) { args.push(moduleName); @@ -1491,7 +1655,10 @@ export function transformModule(context: TransformationContext): (x: SourceFile * @param node The node to visit. */ function visitTopLevelImportEqualsDeclaration(node: ImportEqualsDeclaration): VisitResult { - Debug.assert(isExternalModuleImportEqualsDeclaration(node), "import= for internal module references should be handled in an earlier transformer."); + Debug.assert( + isExternalModuleImportEqualsDeclaration(node), + "import= for internal module references should be handled in an earlier transformer.", + ); let statements: Statement[] | undefined; if (moduleKind !== ModuleKind.AMD) { @@ -1603,7 +1770,12 @@ export function transformModule(context: TransformationContext): (x: SourceFile setOriginalNode( setTextRange( factory.createExpressionStatement( - emitHelpers().createCreateBindingHelper(generatedName, factory.createStringLiteralFromNode(specifier.propertyName || specifier.name), specifier.propertyName ? factory.createStringLiteralFromNode(specifier.name) : undefined), + emitHelpers().createCreateBindingHelper( + generatedName, + factory.createStringLiteralFromNode(specifier.propertyName || specifier.name), + specifier.propertyName ? factory.createStringLiteralFromNode(specifier.name) + : undefined, + ), ), specifier, ), @@ -1612,18 +1784,24 @@ export function transformModule(context: TransformationContext): (x: SourceFile ); } else { - const exportNeedsImportDefault = !!getESModuleInterop(compilerOptions) && - !(getInternalEmitFlags(node) & InternalEmitFlags.NeverApplyImportHelper) && - idText(specifier.propertyName || specifier.name) === "default"; + const exportNeedsImportDefault = !!getESModuleInterop(compilerOptions) + && !(getInternalEmitFlags(node) & InternalEmitFlags.NeverApplyImportHelper) + && idText(specifier.propertyName || specifier.name) === "default"; const exportedValue = factory.createPropertyAccessExpression( - exportNeedsImportDefault ? emitHelpers().createImportDefaultHelper(generatedName) : generatedName, + exportNeedsImportDefault ? emitHelpers().createImportDefaultHelper(generatedName) + : generatedName, specifier.propertyName || specifier.name, ); statements.push( setOriginalNode( setTextRange( factory.createExpressionStatement( - createExportExpression(factory.getExportName(specifier), exportedValue, /*location*/ undefined, /*liveBinding*/ true), + createExportExpression( + factory.getExportName(specifier), + exportedValue, + /*location*/ undefined, + /*liveBinding*/ true, + ), ), specifier, ), @@ -1647,10 +1825,10 @@ export function transformModule(context: TransformationContext): (x: SourceFile factory.cloneNode(node.exportClause.name), getHelperExpressionForExport( node, - moduleKind !== ModuleKind.AMD ? - createRequireCall(node) : - isExportNamespaceAsDefaultDeclaration(node) ? generatedName : - factory.createIdentifier(idText(node.exportClause.name)), + moduleKind !== ModuleKind.AMD + ? createRequireCall(node) + : isExportNamespaceAsDefaultDeclaration(node) ? generatedName + : factory.createIdentifier(idText(node.exportClause.name)), ), ), ), @@ -1667,7 +1845,9 @@ export function transformModule(context: TransformationContext): (x: SourceFile return setOriginalNode( setTextRange( factory.createExpressionStatement( - emitHelpers().createExportStarHelper(moduleKind !== ModuleKind.AMD ? createRequireCall(node) : generatedName), + emitHelpers().createExportStarHelper( + moduleKind !== ModuleKind.AMD ? createRequireCall(node) : generatedName, + ), ), node, ), @@ -1686,7 +1866,12 @@ export function transformModule(context: TransformationContext): (x: SourceFile return undefined; } - return createExportStatement(factory.createIdentifier("default"), visitNode(node.expression, visitor, isExpression), /*location*/ node, /*allowComments*/ true); + return createExportStatement( + factory.createIdentifier("default"), + visitNode(node.expression, visitor, isExpression), + /*location*/ node, + /*allowComments*/ true, + ); } /** @@ -1802,7 +1987,11 @@ export function transformModule(context: TransformationContext): (x: SourceFile } } else if (variable.initializer) { - if (!isBindingPattern(variable.name) && (isArrowFunction(variable.initializer) || isFunctionExpression(variable.initializer) || isClassExpression(variable.initializer))) { + if ( + !isBindingPattern(variable.name) + && (isArrowFunction(variable.initializer) || isFunctionExpression(variable.initializer) + || isClassExpression(variable.initializer)) + ) { const expression = factory.createAssignment( setTextRange( factory.createPropertyAccessExpression( @@ -1825,17 +2014,30 @@ export function transformModule(context: TransformationContext): (x: SourceFile removeCommentsOnExpressions = true; } else { - expressions = append(expressions, transformInitializedVariable(variable as InitializedVariableDeclaration)); + expressions = append( + expressions, + transformInitializedVariable(variable as InitializedVariableDeclaration), + ); } } } if (variables) { - statements = append(statements, factory.updateVariableStatement(node, modifiers, factory.updateVariableDeclarationList(node.declarationList, variables))); + statements = append( + statements, + factory.updateVariableStatement( + node, + modifiers, + factory.updateVariableDeclarationList(node.declarationList, variables), + ), + ); } if (expressions) { - const statement = setOriginalNode(setTextRange(factory.createExpressionStatement(factory.inlineExpressions(expressions)), node), node); + const statement = setOriginalNode( + setTextRange(factory.createExpressionStatement(factory.inlineExpressions(expressions)), node), + node, + ); if (removeCommentsOnExpressions) { removeAllComments(statement); } @@ -1905,7 +2107,10 @@ export function transformModule(context: TransformationContext): (x: SourceFile * appended. * @param decl The declaration whose exports are to be recorded. */ - function appendExportsOfImportDeclaration(statements: Statement[] | undefined, decl: ImportDeclaration): Statement[] | undefined { + function appendExportsOfImportDeclaration( + statements: Statement[] | undefined, + decl: ImportDeclaration, + ): Statement[] | undefined { if (currentModuleInfo.exportEquals) { return statements; } @@ -1948,7 +2153,10 @@ export function transformModule(context: TransformationContext): (x: SourceFile * appended. * @param decl The declaration whose exports are to be recorded. */ - function appendExportsOfImportEqualsDeclaration(statements: Statement[] | undefined, decl: ImportEqualsDeclaration): Statement[] | undefined { + function appendExportsOfImportEqualsDeclaration( + statements: Statement[] | undefined, + decl: ImportEqualsDeclaration, + ): Statement[] | undefined { if (currentModuleInfo.exportEquals) { return statements; } @@ -1965,8 +2173,15 @@ export function transformModule(context: TransformationContext): (x: SourceFile * appended. * @param node The VariableStatement whose exports are to be recorded. */ - function appendExportsOfVariableStatement(statements: Statement[] | undefined, node: VariableStatement): Statement[] | undefined { - return appendExportsOfVariableDeclarationList(statements, node.declarationList, /*isForInOrOfInitializer*/ false); + function appendExportsOfVariableStatement( + statements: Statement[] | undefined, + node: VariableStatement, + ): Statement[] | undefined { + return appendExportsOfVariableDeclarationList( + statements, + node.declarationList, + /*isForInOrOfInitializer*/ false, + ); } /** @@ -1978,7 +2193,11 @@ export function transformModule(context: TransformationContext): (x: SourceFile * appended. * @param node The VariableDeclarationList whose exports are to be recorded. */ - function appendExportsOfVariableDeclarationList(statements: Statement[] | undefined, node: VariableDeclarationList, isForInOrOfInitializer: boolean): Statement[] | undefined { + function appendExportsOfVariableDeclarationList( + statements: Statement[] | undefined, + node: VariableDeclarationList, + isForInOrOfInitializer: boolean, + ): Statement[] | undefined { if (currentModuleInfo.exportEquals) { return statements; } @@ -1999,7 +2218,11 @@ export function transformModule(context: TransformationContext): (x: SourceFile * appended. * @param decl The declaration whose exports are to be recorded. */ - function appendExportsOfBindingElement(statements: Statement[] | undefined, decl: VariableDeclaration | BindingElement, isForInOrOfInitializer: boolean): Statement[] | undefined { + function appendExportsOfBindingElement( + statements: Statement[] | undefined, + decl: VariableDeclaration | BindingElement, + isForInOrOfInitializer: boolean, + ): Statement[] | undefined { if (currentModuleInfo.exportEquals) { return statements; } @@ -2011,7 +2234,10 @@ export function transformModule(context: TransformationContext): (x: SourceFile } } } - else if (!isGeneratedIdentifier(decl.name) && (!isVariableDeclaration(decl) || decl.initializer || isForInOrOfInitializer)) { + else if ( + !isGeneratedIdentifier(decl.name) + && (!isVariableDeclaration(decl) || decl.initializer || isForInOrOfInitializer) + ) { statements = appendExportsOfDeclaration(statements, new IdentifierNameMap(), decl); } @@ -2027,15 +2253,25 @@ export function transformModule(context: TransformationContext): (x: SourceFile * appended. * @param decl The declaration whose exports are to be recorded. */ - function appendExportsOfHoistedDeclaration(statements: Statement[] | undefined, decl: ClassDeclaration | FunctionDeclaration): Statement[] | undefined { + function appendExportsOfHoistedDeclaration( + statements: Statement[] | undefined, + decl: ClassDeclaration | FunctionDeclaration, + ): Statement[] | undefined { if (currentModuleInfo.exportEquals) { return statements; } const seen = new IdentifierNameMap(); if (hasSyntacticModifier(decl, ModifierFlags.Export)) { - const exportName = hasSyntacticModifier(decl, ModifierFlags.Default) ? factory.createIdentifier("default") : factory.getDeclarationName(decl); - statements = appendExportStatement(statements, seen, exportName, factory.getLocalName(decl), /*location*/ decl); + const exportName = hasSyntacticModifier(decl, ModifierFlags.Default) ? factory.createIdentifier("default") + : factory.getDeclarationName(decl); + statements = appendExportStatement( + statements, + seen, + exportName, + factory.getLocalName(decl), + /*location*/ decl, + ); } if (decl.name) { @@ -2053,12 +2289,25 @@ export function transformModule(context: TransformationContext): (x: SourceFile * appended. * @param decl The declaration to export. */ - function appendExportsOfDeclaration(statements: Statement[] | undefined, seen: IdentifierNameMap, decl: Declaration, liveBinding?: boolean): Statement[] | undefined { + function appendExportsOfDeclaration( + statements: Statement[] | undefined, + seen: IdentifierNameMap, + decl: Declaration, + liveBinding?: boolean, + ): Statement[] | undefined { const name = factory.getDeclarationName(decl); const exportSpecifiers = currentModuleInfo.exportSpecifiers.get(name); if (exportSpecifiers) { for (const exportSpecifier of exportSpecifiers) { - statements = appendExportStatement(statements, seen, exportSpecifier.name, name, /*location*/ exportSpecifier.name, /*allowComments*/ undefined, liveBinding); + statements = appendExportStatement( + statements, + seen, + exportSpecifier.name, + name, + /*location*/ exportSpecifier.name, + /*allowComments*/ undefined, + liveBinding, + ); } } return statements; @@ -2076,10 +2325,21 @@ export function transformModule(context: TransformationContext): (x: SourceFile * @param location The location to use for source maps and comments for the export. * @param allowComments Whether to allow comments on the export. */ - function appendExportStatement(statements: Statement[] | undefined, seen: IdentifierNameMap, exportName: Identifier, expression: Expression, location?: TextRange, allowComments?: boolean, liveBinding?: boolean): Statement[] | undefined { + function appendExportStatement( + statements: Statement[] | undefined, + seen: IdentifierNameMap, + exportName: Identifier, + expression: Expression, + location?: TextRange, + allowComments?: boolean, + liveBinding?: boolean, + ): Statement[] | undefined { if (!seen.has(exportName)) { seen.set(exportName, true); - statements = append(statements, createExportStatement(exportName, expression, location, allowComments, liveBinding)); + statements = append( + statements, + createExportStatement(exportName, expression, location, allowComments, liveBinding), + ); } return statements; } @@ -2121,8 +2381,17 @@ export function transformModule(context: TransformationContext): (x: SourceFile * @param location The location to use for source maps and comments for the export. * @param allowComments An optional value indicating whether to emit comments for the statement. */ - function createExportStatement(name: Identifier, value: Expression, location?: TextRange, allowComments?: boolean, liveBinding?: boolean) { - const statement = setTextRange(factory.createExpressionStatement(createExportExpression(name, value, /*location*/ undefined, liveBinding)), location); + function createExportStatement( + name: Identifier, + value: Expression, + location?: TextRange, + allowComments?: boolean, + liveBinding?: boolean, + ) { + const statement = setTextRange( + factory.createExpressionStatement(createExportExpression(name, value, /*location*/ undefined, liveBinding)), + location, + ); startOnNewLine(statement); if (!allowComments) { setEmitFlags(statement, EmitFlags.NoComments); @@ -2331,7 +2600,11 @@ export function transformModule(context: TransformationContext): (x: SourceFile } return node; } - else if (!(isGeneratedIdentifier(node) && !(node.emitNode.autoGenerate.flags & GeneratedIdentifierFlags.AllowNameSubstitution)) && !isLocalName(node)) { + else if ( + !(isGeneratedIdentifier(node) + && !(node.emitNode.autoGenerate.flags & GeneratedIdentifierFlags.AllowNameSubstitution)) + && !isLocalName(node) + ) { const exportContainer = resolver.getReferencedExportContainer(node, isExportName(node)); if (exportContainer && exportContainer.kind === SyntaxKind.SourceFile) { return setTextRange( @@ -2357,7 +2630,9 @@ export function transformModule(context: TransformationContext): (x: SourceFile const name = importDeclaration.propertyName || importDeclaration.name; return setTextRange( factory.createPropertyAccessExpression( - factory.getGeneratedNameForNode(importDeclaration.parent?.parent?.parent || importDeclaration), + factory.getGeneratedNameForNode( + importDeclaration.parent?.parent?.parent || importDeclaration, + ), factory.cloneNode(name), ), /*location*/ node, diff --git a/src/compiler/transformers/module/system.ts b/src/compiler/transformers/module/system.ts index 61ff103dac829..128cdc8d2ce82 100644 --- a/src/compiler/transformers/module/system.ts +++ b/src/compiler/transformers/module/system.ts @@ -179,7 +179,11 @@ export function transformSystemModule(context: TransformationContext): (x: Sourc * @param node The SourceFile node. */ function transformSourceFile(node: SourceFile) { - if (node.isDeclarationFile || !(isEffectiveExternalModule(node, compilerOptions) || node.transformFlags & TransformFlags.ContainsDynamicImport)) { + if ( + node.isDeclarationFile + || !(isEffectiveExternalModule(node, compilerOptions) + || node.transformFlags & TransformFlags.ContainsDynamicImport) + ) { return node; } @@ -218,8 +222,16 @@ export function transformSystemModule(context: TransformationContext): (x: Sourc /*name*/ undefined, /*typeParameters*/ undefined, [ - factory.createParameterDeclaration(/*modifiers*/ undefined, /*dotDotDotToken*/ undefined, exportFunction), - factory.createParameterDeclaration(/*modifiers*/ undefined, /*dotDotDotToken*/ undefined, contextObject), + factory.createParameterDeclaration( + /*modifiers*/ undefined, + /*dotDotDotToken*/ undefined, + exportFunction, + ), + factory.createParameterDeclaration( + /*modifiers*/ undefined, + /*dotDotDotToken*/ undefined, + contextObject, + ), ], /*type*/ undefined, moduleBodyBlock, @@ -229,7 +241,9 @@ export function transformSystemModule(context: TransformationContext): (x: Sourc // Clear the emit-helpers flag for later passes since we'll have already used it in the module body // So the helper will be emit at the correct position instead of at the top of the source-file const moduleName = tryGetModuleNameFromFile(factory, node, host, compilerOptions); - const dependencies = factory.createArrayLiteralExpression(map(dependencyGroups, dependencyGroup => dependencyGroup.name)); + const dependencies = factory.createArrayLiteralExpression( + map(dependencyGroups, dependencyGroup => dependencyGroup.name), + ); const updated = setEmitFlags( factory.updateSourceFile( node, @@ -274,11 +288,20 @@ export function transformSystemModule(context: TransformationContext): (x: Sourc * * @param externalImports The imports for the file. */ - function collectDependencyGroups(externalImports: (ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration)[]) { + function collectDependencyGroups( + externalImports: (ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration)[], + ) { const groupIndices = new Map(); const dependencyGroups: DependencyGroup[] = []; for (const externalImport of externalImports) { - const externalModuleName = getExternalModuleNameLiteral(factory, externalImport, currentSourceFile, host, resolver, compilerOptions); + const externalModuleName = getExternalModuleNameLiteral( + factory, + externalImport, + currentSourceFile, + host, + resolver, + compilerOptions, + ); if (externalModuleName) { const text = externalModuleName.text; const groupIndex = groupIndices.get(text); @@ -355,7 +378,8 @@ export function transformSystemModule(context: TransformationContext): (x: Sourc startLexicalEnvironment(); // Add any prologue directives. - const ensureUseStrict = getStrictOptionValue(compilerOptions, "alwaysStrict") || (!compilerOptions.noImplicitUseStrict && isExternalModule(currentSourceFile)); + const ensureUseStrict = getStrictOptionValue(compilerOptions, "alwaysStrict") + || (!compilerOptions.noImplicitUseStrict && isExternalModule(currentSourceFile)); const statementOffset = factory.copyPrologue(node.statements, statements, ensureUseStrict, topLevelVisitor); // var __moduleName = context_1 && context_1.id; @@ -395,9 +419,9 @@ export function transformSystemModule(context: TransformationContext): (x: Sourc insertStatementsAfterStandardPrologue(statements, endLexicalEnvironment()); const exportStarFunction = addExportStarIfNeeded(statements)!; // TODO: GH#18217 - const modifiers = node.transformFlags & TransformFlags.ContainsAwait ? - factory.createModifiersFromModifierFlags(ModifierFlags.Async) : - undefined; + const modifiers = node.transformFlags & TransformFlags.ContainsAwait + ? factory.createModifiersFromModifierFlags(ModifierFlags.Async) + : undefined; const moduleObject = factory.createObjectLiteralExpression([ factory.createPropertyAssignment("setters", createSettersArray(exportStarFunction, dependencyGroups)), factory.createPropertyAssignment( @@ -576,7 +600,10 @@ export function transformSystemModule(context: TransformationContext): (x: Sourc const setters: Expression[] = []; for (const group of dependencyGroups) { // derive a unique name for parameter from the first named entry in the group - const localName = forEach(group.externalImports, i => getLocalNameForExternalImport(factory, i, currentSourceFile)); + const localName = forEach( + group.externalImports, + i => getLocalNameForExternalImport(factory, i, currentSourceFile), + ); const parameterName = localName ? factory.getGeneratedNameForNode(localName) : factory.createUniqueName(""); const statements: Statement[] = []; for (const entry of group.externalImports) { @@ -690,7 +717,11 @@ export function transformSystemModule(context: TransformationContext): (x: Sourc /*asteriskToken*/ undefined, /*name*/ undefined, /*typeParameters*/ undefined, - [factory.createParameterDeclaration(/*modifiers*/ undefined, /*dotDotDotToken*/ undefined, parameterName)], + [factory.createParameterDeclaration( + /*modifiers*/ undefined, + /*dotDotDotToken*/ undefined, + parameterName, + )], /*type*/ undefined, factory.createBlock(statements, /*multiLine*/ true), ), @@ -752,7 +783,10 @@ export function transformSystemModule(context: TransformationContext): (x: Sourc * @param node The node to visit. */ function visitImportEqualsDeclaration(node: ImportEqualsDeclaration): VisitResult { - Debug.assert(isExternalModuleImportEqualsDeclaration(node), "import= for internal module references should be handled in an earlier transformer."); + Debug.assert( + isExternalModuleImportEqualsDeclaration(node), + "import= for internal module references should be handled in an earlier transformer.", + ); let statements: Statement[] | undefined; hoistVariableDeclaration(getLocalNameForExternalImport(factory, node, currentSourceFile)!); // TODO: GH#18217 @@ -889,7 +923,10 @@ export function transformSystemModule(context: TransformationContext): (x: Sourc } if (expressions) { - statements = append(statements, setTextRange(factory.createExpressionStatement(factory.inlineExpressions(expressions)), node)); + statements = append( + statements, + setTextRange(factory.createExpressionStatement(factory.inlineExpressions(expressions)), node), + ); } } @@ -934,7 +971,8 @@ export function transformSystemModule(context: TransformationContext): (x: Sourc * @param isExportedDeclaration A value indicating whether the variable is exported. */ function transformInitializedVariable(node: VariableDeclaration, isExportedDeclaration: boolean): Expression { - const createAssignment = isExportedDeclaration ? createExportedVariableAssignment : createNonExportedVariableAssignment; + const createAssignment = isExportedDeclaration ? createExportedVariableAssignment + : createNonExportedVariableAssignment; return isBindingPattern(node.name) ? flattenDestructuringAssignment( node, @@ -944,7 +982,8 @@ export function transformSystemModule(context: TransformationContext): (x: Sourc /*needsValue*/ false, createAssignment, ) - : node.initializer ? createAssignment(node.name, visitNode(node.initializer, visitor, isExpression)) : node.name; + : node.initializer ? createAssignment(node.name, visitNode(node.initializer, visitor, isExpression)) + : node.name; } /** @@ -977,10 +1016,18 @@ export function transformSystemModule(context: TransformationContext): (x: Sourc * @param location The source map location for the assignment. * @param isExportedDeclaration A value indicating whether the variable is exported. */ - function createVariableAssignment(name: Identifier, value: Expression, location: TextRange | undefined, isExportedDeclaration: boolean) { + function createVariableAssignment( + name: Identifier, + value: Expression, + location: TextRange | undefined, + isExportedDeclaration: boolean, + ) { hoistVariableDeclaration(factory.cloneNode(name)); return isExportedDeclaration - ? createExportExpression(name, preventSubstitution(setTextRange(factory.createAssignment(name, value), location))) + ? createExportExpression( + name, + preventSubstitution(setTextRange(factory.createAssignment(name, value), location)), + ) : preventSubstitution(setTextRange(factory.createAssignment(name, value), location)); } @@ -1035,7 +1082,10 @@ export function transformSystemModule(context: TransformationContext): (x: Sourc * appended. * @param decl The declaration whose exports are to be recorded. */ - function appendExportsOfImportEqualsDeclaration(statements: Statement[] | undefined, decl: ImportEqualsDeclaration): Statement[] | undefined { + function appendExportsOfImportEqualsDeclaration( + statements: Statement[] | undefined, + decl: ImportEqualsDeclaration, + ): Statement[] | undefined { if (moduleInfo.exportEquals) { return statements; } @@ -1054,7 +1104,11 @@ export function transformSystemModule(context: TransformationContext): (x: Sourc * @param exportSelf A value indicating whether to also export each VariableDeclaration of * `nodes` declaration list. */ - function appendExportsOfVariableStatement(statements: Statement[] | undefined, node: VariableStatement, exportSelf: boolean): Statement[] | undefined { + function appendExportsOfVariableStatement( + statements: Statement[] | undefined, + node: VariableStatement, + exportSelf: boolean, + ): Statement[] | undefined { if (moduleInfo.exportEquals) { return statements; } @@ -1078,7 +1132,11 @@ export function transformSystemModule(context: TransformationContext): (x: Sourc * @param decl The declaration whose exports are to be recorded. * @param exportSelf A value indicating whether to also export the declaration itself. */ - function appendExportsOfBindingElement(statements: Statement[] | undefined, decl: VariableDeclaration | BindingElement, exportSelf: boolean): Statement[] | undefined { + function appendExportsOfBindingElement( + statements: Statement[] | undefined, + decl: VariableDeclaration | BindingElement, + exportSelf: boolean, + ): Statement[] | undefined { if (moduleInfo.exportEquals) { return statements; } @@ -1112,14 +1170,18 @@ export function transformSystemModule(context: TransformationContext): (x: Sourc * appended. * @param decl The declaration whose exports are to be recorded. */ - function appendExportsOfHoistedDeclaration(statements: Statement[] | undefined, decl: ClassDeclaration | FunctionDeclaration): Statement[] | undefined { + function appendExportsOfHoistedDeclaration( + statements: Statement[] | undefined, + decl: ClassDeclaration | FunctionDeclaration, + ): Statement[] | undefined { if (moduleInfo.exportEquals) { return statements; } let excludeName: string | undefined; if (hasSyntacticModifier(decl, ModifierFlags.Export)) { - const exportName = hasSyntacticModifier(decl, ModifierFlags.Default) ? factory.createStringLiteral("default") : decl.name!; + const exportName = hasSyntacticModifier(decl, ModifierFlags.Default) + ? factory.createStringLiteral("default") : decl.name!; statements = appendExportStatement(statements, exportName, factory.getLocalName(decl)); excludeName = getTextOfIdentifierOrLiteral(exportName); } @@ -1140,7 +1202,11 @@ export function transformSystemModule(context: TransformationContext): (x: Sourc * @param decl The declaration to export. * @param excludeName An optional name to exclude from exports. */ - function appendExportsOfDeclaration(statements: Statement[] | undefined, decl: Declaration, excludeName?: string): Statement[] | undefined { + function appendExportsOfDeclaration( + statements: Statement[] | undefined, + decl: Declaration, + excludeName?: string, + ): Statement[] | undefined { if (moduleInfo.exportEquals) { return statements; } @@ -1168,7 +1234,12 @@ export function transformSystemModule(context: TransformationContext): (x: Sourc * @param expression The expression to export. * @param allowComments Whether to allow comments on the export. */ - function appendExportStatement(statements: Statement[] | undefined, exportName: Identifier | StringLiteral, expression: Expression, allowComments?: boolean): Statement[] | undefined { + function appendExportStatement( + statements: Statement[] | undefined, + exportName: Identifier | StringLiteral, + expression: Expression, + allowComments?: boolean, + ): Statement[] | undefined { statements = append(statements, createExportStatement(exportName, expression, allowComments)); return statements; } @@ -1199,7 +1270,10 @@ export function transformSystemModule(context: TransformationContext): (x: Sourc function createExportExpression(name: Identifier | StringLiteral, value: Expression) { const exportName = isIdentifier(name) ? factory.createStringLiteralFromNode(name) : name; setEmitFlags(value, getEmitFlags(value) | EmitFlags.NoComments); - return setCommentRange(factory.createCallExpression(exportFunction, /*typeArguments*/ undefined, [exportName, value]), value); + return setCommentRange( + factory.createCallExpression(exportFunction, /*typeArguments*/ undefined, [exportName, value]), + value, + ); } // @@ -1354,7 +1428,10 @@ export function transformSystemModule(context: TransformationContext): (x: Sourc if (shouldHoistForInitializer(node)) { let expressions: Expression[] | undefined; for (const variable of node.declarations) { - expressions = append(expressions, transformInitializedVariable(variable, /*isExportedDeclaration*/ false)); + expressions = append( + expressions, + transformInitializedVariable(variable, /*isExportedDeclaration*/ false), + ); if (!variable.initializer) { hoistBindingElement(variable); } @@ -1539,7 +1616,11 @@ export function transformSystemModule(context: TransformationContext): (x: Sourc * @param node The node to visit. */ function visitorWorker(node: Node, valueIsDiscarded: boolean): VisitResult { - if (!(node.transformFlags & (TransformFlags.ContainsDestructuringAssignment | TransformFlags.ContainsDynamicImport | TransformFlags.ContainsUpdateExpressionForIdentifier))) { + if ( + !(node.transformFlags + & (TransformFlags.ContainsDestructuringAssignment | TransformFlags.ContainsDynamicImport + | TransformFlags.ContainsUpdateExpressionForIdentifier)) + ) { return node; } switch (node.kind) { @@ -1563,7 +1644,10 @@ export function transformSystemModule(context: TransformationContext): (x: Sourc break; case SyntaxKind.PrefixUnaryExpression: case SyntaxKind.PostfixUnaryExpression: - return visitPrefixOrPostfixUnaryExpression(node as PrefixUnaryExpression | PostfixUnaryExpression, valueIsDiscarded); + return visitPrefixOrPostfixUnaryExpression( + node as PrefixUnaryExpression | PostfixUnaryExpression, + valueIsDiscarded, + ); } return visitEachChild(node, visitor, context); } @@ -1586,11 +1670,17 @@ export function transformSystemModule(context: TransformationContext): (x: Sourc } function visitParenthesizedExpression(node: ParenthesizedExpression, valueIsDiscarded: boolean) { - return factory.updateParenthesizedExpression(node, visitNode(node.expression, valueIsDiscarded ? discardedValueVisitor : visitor, isExpression)); + return factory.updateParenthesizedExpression( + node, + visitNode(node.expression, valueIsDiscarded ? discardedValueVisitor : visitor, isExpression), + ); } function visitPartiallyEmittedExpression(node: PartiallyEmittedExpression, valueIsDiscarded: boolean) { - return factory.updatePartiallyEmittedExpression(node, visitNode(node.expression, valueIsDiscarded ? discardedValueVisitor : visitor, isExpression)); + return factory.updatePartiallyEmittedExpression( + node, + visitNode(node.expression, valueIsDiscarded ? discardedValueVisitor : visitor, isExpression), + ); } function visitImportCallExpression(node: ImportCall): Expression { @@ -1604,10 +1694,19 @@ export function transformSystemModule(context: TransformationContext): (x: Sourc // } // }; // }); - const externalModuleName = getExternalModuleNameLiteral(factory, node, currentSourceFile, host, resolver, compilerOptions); + const externalModuleName = getExternalModuleNameLiteral( + factory, + node, + currentSourceFile, + host, + resolver, + compilerOptions, + ); const firstArgument = visitNode(firstOrUndefined(node.arguments), visitor, isExpression); // Only use the external module name if it differs from the first argument. This allows us to preserve the quote style of the argument on output. - const argument = externalModuleName && (!firstArgument || !isStringLiteral(firstArgument) || firstArgument.text !== externalModuleName.text) ? externalModuleName : firstArgument; + const argument = externalModuleName + && (!firstArgument || !isStringLiteral(firstArgument) || firstArgument.text !== externalModuleName.text) + ? externalModuleName : firstArgument; return factory.createCallExpression( factory.createPropertyAccessExpression( contextObject, @@ -1623,7 +1722,10 @@ export function transformSystemModule(context: TransformationContext): (x: Sourc * * @param node The node to visit. */ - function visitDestructuringAssignment(node: DestructuringAssignment, valueIsDiscarded: boolean): VisitResult { + function visitDestructuringAssignment( + node: DestructuringAssignment, + valueIsDiscarded: boolean, + ): VisitResult { if (hasExportedReferenceInDestructuringTarget(node.left)) { return flattenDestructuringAssignment( node, @@ -1670,7 +1772,10 @@ export function transformSystemModule(context: TransformationContext): (x: Sourc } } - function visitPrefixOrPostfixUnaryExpression(node: PrefixUnaryExpression | PostfixUnaryExpression, valueIsDiscarded: boolean) { + function visitPrefixOrPostfixUnaryExpression( + node: PrefixUnaryExpression | PostfixUnaryExpression, + valueIsDiscarded: boolean, + ) { // When we see a prefix or postfix increment expression whose operand is an exported // symbol, we should ensure all exports of that symbol are updated with the correct // value. @@ -1841,7 +1946,9 @@ export function transformSystemModule(context: TransformationContext): (x: Sourc factory.createPropertyAssignment( factory.cloneNode(name), factory.createPropertyAccessExpression( - factory.getGeneratedNameForNode(importDeclaration.parent?.parent?.parent || importDeclaration), + factory.getGeneratedNameForNode( + importDeclaration.parent?.parent?.parent || importDeclaration, + ), factory.cloneNode(importDeclaration.propertyName || importDeclaration.name), ), ), @@ -1907,7 +2014,9 @@ export function transformSystemModule(context: TransformationContext): (x: Sourc else if (isImportSpecifier(importDeclaration)) { return setTextRange( factory.createPropertyAccessExpression( - factory.getGeneratedNameForNode(importDeclaration.parent?.parent?.parent || importDeclaration), + factory.getGeneratedNameForNode( + importDeclaration.parent?.parent?.parent || importDeclaration, + ), factory.cloneNode(importDeclaration.propertyName || importDeclaration.name), ), /*location*/ node, @@ -1994,14 +2103,18 @@ export function transformSystemModule(context: TransformationContext): (x: Sourc if (importDeclaration) return importDeclaration; const valueDeclaration = resolver.getReferencedValueDeclaration(name); - if (valueDeclaration && moduleInfo?.exportedBindings[getOriginalNodeId(valueDeclaration)]) return valueDeclaration; + if (valueDeclaration && moduleInfo?.exportedBindings[getOriginalNodeId(valueDeclaration)]) { + return valueDeclaration; + } // An exported namespace or enum may merge with an ambient declaration, which won't show up in // .js emit. When that happens, try to find bindings associated with a non-ambient declaration. const declarations = resolver.getReferencedValueDeclarations(name); if (declarations) { for (const declaration of declarations) { - if (declaration !== valueDeclaration && moduleInfo?.exportedBindings[getOriginalNodeId(declaration)]) return declaration; + if ( + declaration !== valueDeclaration && moduleInfo?.exportedBindings[getOriginalNodeId(declaration)] + ) return declaration; } } diff --git a/src/compiler/transformers/namedEvaluation.ts b/src/compiler/transformers/namedEvaluation.ts index 34123cf560080..b21df6b0b5f65 100644 --- a/src/compiler/transformers/namedEvaluation.ts +++ b/src/compiler/transformers/namedEvaluation.ts @@ -54,18 +54,26 @@ import { * Gets a string literal to use as the assigned name of an anonymous class or function declaration. * @internal */ -export function getAssignedNameOfIdentifier(factory: NodeFactory, name: Identifier, expression: WrappedExpression): StringLiteral { +export function getAssignedNameOfIdentifier( + factory: NodeFactory, + name: Identifier, + expression: WrappedExpression, +): StringLiteral { const original = getOriginalNode(skipOuterExpressions(expression)); if ( - (isClassDeclaration(original) || isFunctionDeclaration(original)) && - !original.name && hasSyntacticModifier(original, ModifierFlags.Default) + (isClassDeclaration(original) || isFunctionDeclaration(original)) + && !original.name && hasSyntacticModifier(original, ModifierFlags.Default) ) { return factory.createStringLiteral("default"); } return factory.createStringLiteralFromNode(name); } -function getAssignedNameOfPropertyName(context: TransformationContext, name: PropertyName, assignedNameText: string | undefined) { +function getAssignedNameOfPropertyName( + context: TransformationContext, + name: PropertyName, + assignedNameText: string | undefined, +) { const { factory } = context; if (assignedNameText !== undefined) { const assignedName = factory.createStringLiteral(assignedNameText); @@ -100,7 +108,11 @@ function getAssignedNameOfPropertyName(context: TransformationContext, name: Pro * expression that has already had its `EmitFlags` set or may have been tracked to prevent substitution. * @internal */ -export function createClassNamedEvaluationHelperBlock(context: TransformationContext, assignedName: Expression, thisExpression: Expression = context.factory.createThis()): ClassNamedEvaluationHelperBlock { +export function createClassNamedEvaluationHelperBlock( + context: TransformationContext, + assignedName: Expression, + thisExpression: Expression = context.factory.createThis(), +): ClassNamedEvaluationHelperBlock { // produces: // // static { __setFunctionName(this, "C"); } @@ -144,10 +156,10 @@ export function isClassNamedEvaluationHelperBlock(node: Node): node is ClassName } const statement = node.body.statements[0]; - return isExpressionStatement(statement) && - isCallToHelper(statement.expression, "___setFunctionName" as __String) && - (statement.expression as CallExpression).arguments.length >= 2 && - (statement.expression as CallExpression).arguments[1] === node.emitNode?.assignedName; + return isExpressionStatement(statement) + && isCallToHelper(statement.expression, "___setFunctionName" as __String) + && (statement.expression as CallExpression).arguments.length >= 2 + && (statement.expression as CallExpression).arguments[1] === node.emitNode?.assignedName; } /** @@ -213,16 +225,16 @@ export function injectClassNamedEvaluationHelperBlockIfMissing( const members = factory.createNodeArray([...leading, namedEvaluationBlock, ...trailing]); setTextRange(members, node.members); - node = isClassDeclaration(node) ? - factory.updateClassDeclaration( + node = isClassDeclaration(node) + ? factory.updateClassDeclaration( node, node.modifiers, node.name, node.typeParameters, node.heritageClauses, members, - ) : - factory.updateClassExpression( + ) + : factory.updateClassExpression( node, node.modifiers, node.name, @@ -248,14 +260,22 @@ function finishTransformNamedEvaluation( const { factory } = context; const innerExpression = skipOuterExpressions(expression); - const updatedExpression = isClassExpression(innerExpression) ? - cast(injectClassNamedEvaluationHelperBlockIfMissing(context, innerExpression, assignedName), isClassExpression) : - context.getEmitHelperFactory().createSetFunctionNameHelper(innerExpression, assignedName); + const updatedExpression = isClassExpression(innerExpression) + ? cast( + injectClassNamedEvaluationHelperBlockIfMissing(context, innerExpression, assignedName), + isClassExpression, + ) + : context.getEmitHelperFactory().createSetFunctionNameHelper(innerExpression, assignedName); return factory.restoreOuterExpressions(expression, updatedExpression); } -function transformNamedEvaluationOfPropertyAssignment(context: TransformationContext, node: NamedEvaluation & PropertyAssignment, ignoreEmptyStringLiteral?: boolean, assignedNameText?: string) { +function transformNamedEvaluationOfPropertyAssignment( + context: TransformationContext, + node: NamedEvaluation & PropertyAssignment, + ignoreEmptyStringLiteral?: boolean, + assignedNameText?: string, +) { // 13.2.5.5 RS: PropertyDefinitionEvaluation // PropertyAssignment : PropertyName `:` AssignmentExpression // ... @@ -265,7 +285,12 @@ function transformNamedEvaluationOfPropertyAssignment(context: TransformationCon const { factory } = context; const { assignedName, name } = getAssignedNameOfPropertyName(context, node.name, assignedNameText); - const initializer = finishTransformNamedEvaluation(context, node.initializer, assignedName, ignoreEmptyStringLiteral); + const initializer = finishTransformNamedEvaluation( + context, + node.initializer, + assignedName, + ignoreEmptyStringLiteral, + ); return factory.updatePropertyAssignment( node, name, @@ -273,7 +298,12 @@ function transformNamedEvaluationOfPropertyAssignment(context: TransformationCon ); } -function transformNamedEvaluationOfShorthandAssignmentProperty(context: TransformationContext, node: NamedEvaluation & ShorthandPropertyAssignment, ignoreEmptyStringLiteral?: boolean, assignedNameText?: string) { +function transformNamedEvaluationOfShorthandAssignmentProperty( + context: TransformationContext, + node: NamedEvaluation & ShorthandPropertyAssignment, + ignoreEmptyStringLiteral?: boolean, + assignedNameText?: string, +) { // 13.15.5.3 RS: PropertyDestructuringAssignmentEvaluation // AssignmentProperty : IdentifierReference Initializer? // ... @@ -283,9 +313,14 @@ function transformNamedEvaluationOfShorthandAssignmentProperty(context: Transfor // ... const { factory } = context; - const assignedName = assignedNameText !== undefined ? factory.createStringLiteral(assignedNameText) : - getAssignedNameOfIdentifier(factory, node.name, node.objectAssignmentInitializer); - const objectAssignmentInitializer = finishTransformNamedEvaluation(context, node.objectAssignmentInitializer, assignedName, ignoreEmptyStringLiteral); + const assignedName = assignedNameText !== undefined ? factory.createStringLiteral(assignedNameText) + : getAssignedNameOfIdentifier(factory, node.name, node.objectAssignmentInitializer); + const objectAssignmentInitializer = finishTransformNamedEvaluation( + context, + node.objectAssignmentInitializer, + assignedName, + ignoreEmptyStringLiteral, + ); return factory.updateShorthandPropertyAssignment( node, node.name, @@ -293,7 +328,12 @@ function transformNamedEvaluationOfShorthandAssignmentProperty(context: Transfor ); } -function transformNamedEvaluationOfVariableDeclaration(context: TransformationContext, node: NamedEvaluation & VariableDeclaration, ignoreEmptyStringLiteral?: boolean, assignedNameText?: string) { +function transformNamedEvaluationOfVariableDeclaration( + context: TransformationContext, + node: NamedEvaluation & VariableDeclaration, + ignoreEmptyStringLiteral?: boolean, + assignedNameText?: string, +) { // 14.3.1.2 RS: Evaluation // LexicalBinding : BindingIdentifier Initializer // ... @@ -309,9 +349,14 @@ function transformNamedEvaluationOfVariableDeclaration(context: TransformationCo // ... const { factory } = context; - const assignedName = assignedNameText !== undefined ? factory.createStringLiteral(assignedNameText) : - getAssignedNameOfIdentifier(factory, node.name, node.initializer); - const initializer = finishTransformNamedEvaluation(context, node.initializer, assignedName, ignoreEmptyStringLiteral); + const assignedName = assignedNameText !== undefined ? factory.createStringLiteral(assignedNameText) + : getAssignedNameOfIdentifier(factory, node.name, node.initializer); + const initializer = finishTransformNamedEvaluation( + context, + node.initializer, + assignedName, + ignoreEmptyStringLiteral, + ); return factory.updateVariableDeclaration( node, node.name, @@ -321,7 +366,12 @@ function transformNamedEvaluationOfVariableDeclaration(context: TransformationCo ); } -function transformNamedEvaluationOfParameterDeclaration(context: TransformationContext, node: NamedEvaluation & ParameterDeclaration, ignoreEmptyStringLiteral?: boolean, assignedNameText?: string) { +function transformNamedEvaluationOfParameterDeclaration( + context: TransformationContext, + node: NamedEvaluation & ParameterDeclaration, + ignoreEmptyStringLiteral?: boolean, + assignedNameText?: string, +) { // 8.6.3 RS: IteratorBindingInitialization // SingleNameBinding : BindingIdentifier Initializer? // ... @@ -339,9 +389,14 @@ function transformNamedEvaluationOfParameterDeclaration(context: TransformationC // ... const { factory } = context; - const assignedName = assignedNameText !== undefined ? factory.createStringLiteral(assignedNameText) : - getAssignedNameOfIdentifier(factory, node.name, node.initializer); - const initializer = finishTransformNamedEvaluation(context, node.initializer, assignedName, ignoreEmptyStringLiteral); + const assignedName = assignedNameText !== undefined ? factory.createStringLiteral(assignedNameText) + : getAssignedNameOfIdentifier(factory, node.name, node.initializer); + const initializer = finishTransformNamedEvaluation( + context, + node.initializer, + assignedName, + ignoreEmptyStringLiteral, + ); return factory.updateParameterDeclaration( node, node.modifiers, @@ -353,7 +408,12 @@ function transformNamedEvaluationOfParameterDeclaration(context: TransformationC ); } -function transformNamedEvaluationOfBindingElement(context: TransformationContext, node: NamedEvaluation & BindingElement, ignoreEmptyStringLiteral?: boolean, assignedNameText?: string) { +function transformNamedEvaluationOfBindingElement( + context: TransformationContext, + node: NamedEvaluation & BindingElement, + ignoreEmptyStringLiteral?: boolean, + assignedNameText?: string, +) { // 8.6.3 RS: IteratorBindingInitialization // SingleNameBinding : BindingIdentifier Initializer? // ... @@ -371,9 +431,14 @@ function transformNamedEvaluationOfBindingElement(context: TransformationContext // ... const { factory } = context; - const assignedName = assignedNameText !== undefined ? factory.createStringLiteral(assignedNameText) : - getAssignedNameOfIdentifier(factory, node.name, node.initializer); - const initializer = finishTransformNamedEvaluation(context, node.initializer, assignedName, ignoreEmptyStringLiteral); + const assignedName = assignedNameText !== undefined ? factory.createStringLiteral(assignedNameText) + : getAssignedNameOfIdentifier(factory, node.name, node.initializer); + const initializer = finishTransformNamedEvaluation( + context, + node.initializer, + assignedName, + ignoreEmptyStringLiteral, + ); return factory.updateBindingElement( node, node.dotDotDotToken, @@ -383,7 +448,12 @@ function transformNamedEvaluationOfBindingElement(context: TransformationContext ); } -function transformNamedEvaluationOfPropertyDeclaration(context: TransformationContext, node: NamedEvaluation & PropertyDeclaration, ignoreEmptyStringLiteral?: boolean, assignedNameText?: string) { +function transformNamedEvaluationOfPropertyDeclaration( + context: TransformationContext, + node: NamedEvaluation & PropertyDeclaration, + ignoreEmptyStringLiteral?: boolean, + assignedNameText?: string, +) { // 10.2.1.3 RS: EvaluateBody // Initializer : `=` AssignmentExpression // ... @@ -393,7 +463,12 @@ function transformNamedEvaluationOfPropertyDeclaration(context: TransformationCo const { factory } = context; const { assignedName, name } = getAssignedNameOfPropertyName(context, node.name, assignedNameText); - const initializer = finishTransformNamedEvaluation(context, node.initializer, assignedName, ignoreEmptyStringLiteral); + const initializer = finishTransformNamedEvaluation( + context, + node.initializer, + assignedName, + ignoreEmptyStringLiteral, + ); return factory.updatePropertyDeclaration( node, node.modifiers, @@ -404,7 +479,12 @@ function transformNamedEvaluationOfPropertyDeclaration(context: TransformationCo ); } -function transformNamedEvaluationOfAssignmentExpression(context: TransformationContext, node: NamedEvaluation & BinaryExpression, ignoreEmptyStringLiteral?: boolean, assignedNameText?: string) { +function transformNamedEvaluationOfAssignmentExpression( + context: TransformationContext, + node: NamedEvaluation & BinaryExpression, + ignoreEmptyStringLiteral?: boolean, + assignedNameText?: string, +) { // 13.15.2 RS: Evaluation // AssignmentExpression : LeftHandSideExpression `=` AssignmentExpression // 1. If |LeftHandSideExpression| is neither an |ObjectLiteral| nor an |ArrayLiteral|, then @@ -432,8 +512,8 @@ function transformNamedEvaluationOfAssignmentExpression(context: TransformationC // ... const { factory } = context; - const assignedName = assignedNameText !== undefined ? factory.createStringLiteral(assignedNameText) : - getAssignedNameOfIdentifier(factory, node.left, node.right); + const assignedName = assignedNameText !== undefined ? factory.createStringLiteral(assignedNameText) + : getAssignedNameOfIdentifier(factory, node.left, node.right); const right = finishTransformNamedEvaluation(context, node.right, assignedName, ignoreEmptyStringLiteral); return factory.updateBinaryExpression( node, @@ -443,7 +523,12 @@ function transformNamedEvaluationOfAssignmentExpression(context: TransformationC ); } -function transformNamedEvaluationOfExportAssignment(context: TransformationContext, node: NamedEvaluation & ExportAssignment, ignoreEmptyStringLiteral?: boolean, assignedNameText?: string) { +function transformNamedEvaluationOfExportAssignment( + context: TransformationContext, + node: NamedEvaluation & ExportAssignment, + ignoreEmptyStringLiteral?: boolean, + assignedNameText?: string, +) { // 16.2.3.7 RS: Evaluation // ExportDeclaration : `export` `default` AssignmentExpression `;` // 1. If IsAnonymousFunctionDefinition(|AssignmentExpression|) is *true*, then @@ -454,8 +539,8 @@ function transformNamedEvaluationOfExportAssignment(context: TransformationConte // is `""`. const { factory } = context; - const assignedName = assignedNameText !== undefined ? factory.createStringLiteral(assignedNameText) : - factory.createStringLiteral(node.isExportEquals ? "" : "default"); + const assignedName = assignedNameText !== undefined ? factory.createStringLiteral(assignedNameText) + : factory.createStringLiteral(node.isExportEquals ? "" : "default"); const expression = finishTransformNamedEvaluation(context, node.expression, assignedName, ignoreEmptyStringLiteral); return factory.updateExportAssignment( node, @@ -468,23 +553,48 @@ function transformNamedEvaluationOfExportAssignment(context: TransformationConte * Performs a shallow transformation of a `NamedEvaluation` node, such that a valid name will be assigned. * @internal */ -export function transformNamedEvaluation(context: TransformationContext, node: T, ignoreEmptyStringLiteral?: boolean, assignedName?: string): Extract>; -export function transformNamedEvaluation(context: TransformationContext, node: NamedEvaluation, ignoreEmptyStringLiteral?: boolean, assignedName?: string) { +export function transformNamedEvaluation( + context: TransformationContext, + node: T, + ignoreEmptyStringLiteral?: boolean, + assignedName?: string, +): Extract>; +export function transformNamedEvaluation( + context: TransformationContext, + node: NamedEvaluation, + ignoreEmptyStringLiteral?: boolean, + assignedName?: string, +) { switch (node.kind) { case SyntaxKind.PropertyAssignment: return transformNamedEvaluationOfPropertyAssignment(context, node, ignoreEmptyStringLiteral, assignedName); case SyntaxKind.ShorthandPropertyAssignment: - return transformNamedEvaluationOfShorthandAssignmentProperty(context, node, ignoreEmptyStringLiteral, assignedName); + return transformNamedEvaluationOfShorthandAssignmentProperty( + context, + node, + ignoreEmptyStringLiteral, + assignedName, + ); case SyntaxKind.VariableDeclaration: return transformNamedEvaluationOfVariableDeclaration(context, node, ignoreEmptyStringLiteral, assignedName); case SyntaxKind.Parameter: - return transformNamedEvaluationOfParameterDeclaration(context, node, ignoreEmptyStringLiteral, assignedName); + return transformNamedEvaluationOfParameterDeclaration( + context, + node, + ignoreEmptyStringLiteral, + assignedName, + ); case SyntaxKind.BindingElement: return transformNamedEvaluationOfBindingElement(context, node, ignoreEmptyStringLiteral, assignedName); case SyntaxKind.PropertyDeclaration: return transformNamedEvaluationOfPropertyDeclaration(context, node, ignoreEmptyStringLiteral, assignedName); case SyntaxKind.BinaryExpression: - return transformNamedEvaluationOfAssignmentExpression(context, node, ignoreEmptyStringLiteral, assignedName); + return transformNamedEvaluationOfAssignmentExpression( + context, + node, + ignoreEmptyStringLiteral, + assignedName, + ); case SyntaxKind.ExportAssignment: return transformNamedEvaluationOfExportAssignment(context, node, ignoreEmptyStringLiteral, assignedName); } diff --git a/src/compiler/transformers/taggedTemplate.ts b/src/compiler/transformers/taggedTemplate.ts index a905dcb26ecb8..aa4120d7750ef 100644 --- a/src/compiler/transformers/taggedTemplate.ts +++ b/src/compiler/transformers/taggedTemplate.ts @@ -98,8 +98,12 @@ export function processTaggedTemplateExpression( return factory.createCallExpression(tag, /*typeArguments*/ undefined, templateArguments); } -function createTemplateCooked(factory: NodeFactory, template: TemplateHead | TemplateMiddle | TemplateTail | NoSubstitutionTemplateLiteral) { - return template.templateFlags! & TokenFlags.IsInvalid ? factory.createVoidZero() : factory.createStringLiteral(template.text); +function createTemplateCooked( + factory: NodeFactory, + template: TemplateHead | TemplateMiddle | TemplateTail | NoSubstitutionTemplateLiteral, +) { + return template.templateFlags! & TokenFlags.IsInvalid ? factory.createVoidZero() + : factory.createStringLiteral(template.text); } /** @@ -113,7 +117,10 @@ function getRawLiteral(factory: NodeFactory, node: TemplateLiteralLikeNode, curr // Examples: `\n` is converted to "\\n", a template string with a newline to "\n". let text = node.rawText; if (text === undefined) { - Debug.assertIsDefined(currentSourceFile, "Template literal node is missing 'rawText' and does not have a source file. Possibly bad transform."); + Debug.assertIsDefined( + currentSourceFile, + "Template literal node is missing 'rawText' and does not have a source file. Possibly bad transform.", + ); text = getSourceTextOfNodeFromSourceFile(currentSourceFile, node); // text contains the original source, it will also contain quotes ("`"), dolar signs and braces ("${" and "}"), diff --git a/src/compiler/transformers/ts.ts b/src/compiler/transformers/ts.ts index 00eb218342e00..ce3cc9f812552 100644 --- a/src/compiler/transformers/ts.ts +++ b/src/compiler/transformers/ts.ts @@ -371,7 +371,9 @@ export function transformTypeScript(context: TransformationContext) { // These nodes should always have names unless they are default-exports; // however, class declaration parsing allows for undefined names, so syntactically invalid // programs may also have an undefined name. - Debug.assert(node.kind === SyntaxKind.ClassDeclaration || hasSyntacticModifier(node, ModifierFlags.Default)); + Debug.assert( + node.kind === SyntaxKind.ClassDeclaration || hasSyntacticModifier(node, ModifierFlags.Default), + ); } break; @@ -419,13 +421,17 @@ export function transformTypeScript(context: TransformationContext) { case SyntaxKind.ImportEqualsDeclaration: case SyntaxKind.ExportAssignment: case SyntaxKind.ExportDeclaration: - return visitElidableStatement(node as ImportDeclaration | ImportEqualsDeclaration | ExportAssignment | ExportDeclaration); + return visitElidableStatement( + node as ImportDeclaration | ImportEqualsDeclaration | ExportAssignment | ExportDeclaration, + ); default: return visitorWorker(node); } } - function visitElidableStatement(node: ImportDeclaration | ImportEqualsDeclaration | ExportAssignment | ExportDeclaration): VisitResult { + function visitElidableStatement( + node: ImportDeclaration | ImportEqualsDeclaration | ExportAssignment | ExportDeclaration, + ): VisitResult { const parsed = getParseTreeNode(node); if (parsed !== node) { // If the node has been transformed by a `before` transformer, perform no ellision on it @@ -469,16 +475,18 @@ export function transformTypeScript(context: TransformationContext) { */ function namespaceElementVisitorWorker(node: Node): VisitResult { if ( - node.kind === SyntaxKind.ExportDeclaration || - node.kind === SyntaxKind.ImportDeclaration || - node.kind === SyntaxKind.ImportClause || - (node.kind === SyntaxKind.ImportEqualsDeclaration && - (node as ImportEqualsDeclaration).moduleReference.kind === SyntaxKind.ExternalModuleReference) + node.kind === SyntaxKind.ExportDeclaration + || node.kind === SyntaxKind.ImportDeclaration + || node.kind === SyntaxKind.ImportClause + || (node.kind === SyntaxKind.ImportEqualsDeclaration + && (node as ImportEqualsDeclaration).moduleReference.kind === SyntaxKind.ExternalModuleReference) ) { // do not emit ES6 imports and exports since they are illegal inside a namespace return undefined; } - else if (node.transformFlags & TransformFlags.ContainsTypeScript || hasSyntacticModifier(node, ModifierFlags.Export)) { + else if ( + node.transformFlags & TransformFlags.ContainsTypeScript || hasSyntacticModifier(node, ModifierFlags.Export) + ) { return visitTypeScript(node); } @@ -537,11 +545,16 @@ export function transformTypeScript(context: TransformationContext) { } } - function getObjectLiteralElementVisitor(parent: ObjectLiteralExpression): (node: T) => VisitResult { + function getObjectLiteralElementVisitor( + parent: ObjectLiteralExpression, + ): (node: T) => VisitResult { return node => saveStateAndInvoke(node, n => objectLiteralElementVisitorWorker(n, parent)); } - function objectLiteralElementVisitorWorker(node: Node, parent: ObjectLiteralExpression): VisitResult { + function objectLiteralElementVisitorWorker( + node: Node, + parent: ObjectLiteralExpression, + ): VisitResult { switch (node.kind) { case SyntaxKind.PropertyAssignment: case SyntaxKind.ShorthandPropertyAssignment: @@ -788,9 +801,9 @@ export function transformTypeScript(context: TransformationContext) { } function visitSourceFile(node: SourceFile) { - const alwaysStrict = getStrictOptionValue(compilerOptions, "alwaysStrict") && - !(isExternalModule(node) && moduleKind >= ModuleKind.ES2015) && - !isJsonSourceFile(node); + const alwaysStrict = getStrictOptionValue(compilerOptions, "alwaysStrict") + && !(isExternalModule(node) && moduleKind >= ModuleKind.ES2015) + && !isJsonSourceFile(node); return factory.updateSourceFile( node, @@ -807,10 +820,17 @@ export function transformTypeScript(context: TransformationContext) { function getClassFacts(node: ClassDeclaration) { let facts = ClassFacts.None; - if (some(getProperties(node, /*requireInitializer*/ true, /*isStatic*/ true))) facts |= ClassFacts.HasStaticInitializedProperties; + if (some(getProperties(node, /*requireInitializer*/ true, /*isStatic*/ true))) { + facts |= ClassFacts.HasStaticInitializedProperties; + } const extendsClauseElement = getEffectiveBaseTypeNode(node); - if (extendsClauseElement && skipOuterExpressions(extendsClauseElement.expression).kind !== SyntaxKind.NullKeyword) facts |= ClassFacts.IsDerivedClass; - if (classOrConstructorParameterIsDecorated(legacyDecorators, node)) facts |= ClassFacts.HasClassOrConstructorParameterDecorators; + if ( + extendsClauseElement + && skipOuterExpressions(extendsClauseElement.expression).kind !== SyntaxKind.NullKeyword + ) facts |= ClassFacts.IsDerivedClass; + if (classOrConstructorParameterIsDecorated(legacyDecorators, node)) { + facts |= ClassFacts.HasClassOrConstructorParameterDecorators; + } if (childIsDecorated(legacyDecorators, node)) facts |= ClassFacts.HasMemberDecorators; if (isExportOfNamespace(node)) facts |= ClassFacts.IsExportOfNamespace; else if (isDefaultExternalModuleExport(node)) facts |= ClassFacts.IsDefaultExternalExport; @@ -831,13 +851,13 @@ export function transformTypeScript(context: TransformationContext) { function visitClassDeclaration(node: ClassDeclaration): VisitResult { const facts = getClassFacts(node); - const promoteToIIFE = languageVersion <= ScriptTarget.ES5 && - !!(facts & ClassFacts.MayNeedImmediatelyInvokedFunctionExpression); + const promoteToIIFE = languageVersion <= ScriptTarget.ES5 + && !!(facts & ClassFacts.MayNeedImmediatelyInvokedFunctionExpression); if ( - !isClassLikeDeclarationWithTypeScriptSyntax(node) && - !classOrConstructorParameterIsDecorated(legacyDecorators, node) && - !isExportOfNamespace(node) + !isClassLikeDeclarationWithTypeScriptSyntax(node) + && !classOrConstructorParameterIsDecorated(legacyDecorators, node) + && !isExportOfNamespace(node) ) { return factory.updateClassDeclaration( node, @@ -853,27 +873,27 @@ export function transformTypeScript(context: TransformationContext) { context.startLexicalEnvironment(); } - const moveModifiers = promoteToIIFE || - facts & ClassFacts.IsExportOfNamespace; + const moveModifiers = promoteToIIFE + || facts & ClassFacts.IsExportOfNamespace; // elide modifiers on the declaration if we are emitting an IIFE or the class is // a namespace export - let modifiers = moveModifiers ? - visitNodes(node.modifiers, modifierElidingVisitor, isModifierLike) : - visitNodes(node.modifiers, visitor, isModifierLike); + let modifiers = moveModifiers + ? visitNodes(node.modifiers, modifierElidingVisitor, isModifierLike) + : visitNodes(node.modifiers, visitor, isModifierLike); // inject metadata only if the class is decorated if (facts & ClassFacts.HasClassOrConstructorParameterDecorators) { modifiers = injectClassTypeMetadata(modifiers, node); } - const needsName = moveModifiers && !node.name || - facts & ClassFacts.HasMemberDecorators || - facts & ClassFacts.HasStaticInitializedProperties; + const needsName = moveModifiers && !node.name + || facts & ClassFacts.HasMemberDecorators + || facts & ClassFacts.HasStaticInitializedProperties; - const name = needsName ? - node.name ?? factory.getGeneratedNameForNode(node) : - node.name; + const name = needsName + ? node.name ?? factory.getGeneratedNameForNode(node) + : node.name; // ${modifiers} class ${name} ${heritageClauses} { // ${members} @@ -910,7 +930,10 @@ export function transformTypeScript(context: TransformationContext) { // }(); // const statements: Statement[] = [classDeclaration]; - const closingBraceLocation = createTokenRange(skipTrivia(currentSourceFile.text, node.members.end), SyntaxKind.CloseBraceToken); + const closingBraceLocation = createTokenRange( + skipTrivia(currentSourceFile.text, node.members.end), + SyntaxKind.CloseBraceToken, + ); const localName = factory.getInternalName(node); // The following partially-emitted expression exists purely to align our sourcemap @@ -962,13 +985,17 @@ export function transformTypeScript(context: TransformationContext) { if (facts & ClassFacts.IsDefaultExternalExport) { return [ statement, - factory.createExportDefault(factory.getLocalName(node, /*allowComments*/ false, /*allowSourceMaps*/ true)), + factory.createExportDefault( + factory.getLocalName(node, /*allowComments*/ false, /*allowSourceMaps*/ true), + ), ]; } if (facts & ClassFacts.IsNamedExternalExport) { return [ statement, - factory.createExternalModuleExport(factory.getDeclarationName(node, /*allowComments*/ false, /*allowSourceMaps*/ true)), + factory.createExternalModuleExport( + factory.getDeclarationName(node, /*allowComments*/ false, /*allowSourceMaps*/ true), + ), ]; } } @@ -1002,8 +1029,11 @@ export function transformTypeScript(context: TransformationContext) { let newMembers: ClassElement[] | undefined; const constructor = getFirstConstructorWithBody(node); - const parametersWithPropertyAssignments = constructor && - filter(constructor.parameters, (p): p is ParameterPropertyDeclaration => isParameterPropertyDeclaration(p, constructor)); + const parametersWithPropertyAssignments = constructor + && filter( + constructor.parameters, + (p): p is ParameterPropertyDeclaration => isParameterPropertyDeclaration(p, constructor), + ); if (parametersWithPropertyAssignments) { for (const parameter of parametersWithPropertyAssignments) { @@ -1041,8 +1071,14 @@ export function transformTypeScript(context: TransformationContext) { return modifiers; } - function injectClassElementTypeMetadata(modifiers: NodeArray | undefined, node: ClassElement, container: ClassLikeDeclaration | ObjectLiteralExpression) { - if (isClassLike(container) && classElementOrClassElementParameterIsDecorated(legacyDecorators, node, container)) { + function injectClassElementTypeMetadata( + modifiers: NodeArray | undefined, + node: ClassElement, + container: ClassLikeDeclaration | ObjectLiteralExpression, + ) { + if ( + isClassLike(container) && classElementOrClassElementParameterIsDecorated(legacyDecorators, node, container) + ) { const metadata = getTypeMetadata(node, container); if (some(metadata)) { const modifiersArray: ModifierLike[] = []; @@ -1063,24 +1099,40 @@ export function transformTypeScript(context: TransformationContext) { function getTypeMetadata(node: Declaration, container: ClassLikeDeclaration) { // Decorator metadata is not yet supported for ES decorators. if (!legacyDecorators) return undefined; - return USE_NEW_TYPE_METADATA_FORMAT ? - getNewTypeMetadata(node, container) : - getOldTypeMetadata(node, container); + return USE_NEW_TYPE_METADATA_FORMAT + ? getNewTypeMetadata(node, container) + : getOldTypeMetadata(node, container); } function getOldTypeMetadata(node: Declaration, container: ClassLikeDeclaration) { if (typeSerializer) { let decorators: Decorator[] | undefined; if (shouldAddTypeMetadata(node)) { - const typeMetadata = emitHelpers().createMetadataHelper("design:type", typeSerializer.serializeTypeOfNode({ currentLexicalScope, currentNameScope: container }, node)); + const typeMetadata = emitHelpers().createMetadataHelper( + "design:type", + typeSerializer.serializeTypeOfNode({ currentLexicalScope, currentNameScope: container }, node), + ); decorators = append(decorators, factory.createDecorator(typeMetadata)); } if (shouldAddParamTypesMetadata(node)) { - const paramTypesMetadata = emitHelpers().createMetadataHelper("design:paramtypes", typeSerializer.serializeParameterTypesOfNode({ currentLexicalScope, currentNameScope: container }, node, container)); + const paramTypesMetadata = emitHelpers().createMetadataHelper( + "design:paramtypes", + typeSerializer.serializeParameterTypesOfNode( + { currentLexicalScope, currentNameScope: container }, + node, + container, + ), + ); decorators = append(decorators, factory.createDecorator(paramTypesMetadata)); } if (shouldAddReturnTypeMetadata(node)) { - const returnTypeMetadata = emitHelpers().createMetadataHelper("design:returntype", typeSerializer.serializeReturnTypeOfNode({ currentLexicalScope, currentNameScope: container }, node)); + const returnTypeMetadata = emitHelpers().createMetadataHelper( + "design:returntype", + typeSerializer.serializeReturnTypeOfNode( + { currentLexicalScope, currentNameScope: container }, + node, + ), + ); decorators = append(decorators, factory.createDecorator(returnTypeMetadata)); } return decorators; @@ -1091,19 +1143,59 @@ export function transformTypeScript(context: TransformationContext) { if (typeSerializer) { let properties: ObjectLiteralElementLike[] | undefined; if (shouldAddTypeMetadata(node)) { - const typeProperty = factory.createPropertyAssignment("type", factory.createArrowFunction(/*modifiers*/ undefined, /*typeParameters*/ undefined, [], /*type*/ undefined, factory.createToken(SyntaxKind.EqualsGreaterThanToken), typeSerializer.serializeTypeOfNode({ currentLexicalScope, currentNameScope: container }, node))); + const typeProperty = factory.createPropertyAssignment( + "type", + factory.createArrowFunction( + /*modifiers*/ undefined, + /*typeParameters*/ undefined, + [], + /*type*/ undefined, + factory.createToken(SyntaxKind.EqualsGreaterThanToken), + typeSerializer.serializeTypeOfNode({ currentLexicalScope, currentNameScope: container }, node), + ), + ); properties = append(properties, typeProperty); } if (shouldAddParamTypesMetadata(node)) { - const paramTypeProperty = factory.createPropertyAssignment("paramTypes", factory.createArrowFunction(/*modifiers*/ undefined, /*typeParameters*/ undefined, [], /*type*/ undefined, factory.createToken(SyntaxKind.EqualsGreaterThanToken), typeSerializer.serializeParameterTypesOfNode({ currentLexicalScope, currentNameScope: container }, node, container))); + const paramTypeProperty = factory.createPropertyAssignment( + "paramTypes", + factory.createArrowFunction( + /*modifiers*/ undefined, + /*typeParameters*/ undefined, + [], + /*type*/ undefined, + factory.createToken(SyntaxKind.EqualsGreaterThanToken), + typeSerializer.serializeParameterTypesOfNode( + { currentLexicalScope, currentNameScope: container }, + node, + container, + ), + ), + ); properties = append(properties, paramTypeProperty); } if (shouldAddReturnTypeMetadata(node)) { - const returnTypeProperty = factory.createPropertyAssignment("returnType", factory.createArrowFunction(/*modifiers*/ undefined, /*typeParameters*/ undefined, [], /*type*/ undefined, factory.createToken(SyntaxKind.EqualsGreaterThanToken), typeSerializer.serializeReturnTypeOfNode({ currentLexicalScope, currentNameScope: container }, node))); + const returnTypeProperty = factory.createPropertyAssignment( + "returnType", + factory.createArrowFunction( + /*modifiers*/ undefined, + /*typeParameters*/ undefined, + [], + /*type*/ undefined, + factory.createToken(SyntaxKind.EqualsGreaterThanToken), + typeSerializer.serializeReturnTypeOfNode( + { currentLexicalScope, currentNameScope: container }, + node, + ), + ), + ); properties = append(properties, returnTypeProperty); } if (properties) { - const typeInfoMetadata = emitHelpers().createMetadataHelper("design:typeinfo", factory.createObjectLiteralExpression(properties, /*multiLine*/ true)); + const typeInfoMetadata = emitHelpers().createMetadataHelper( + "design:typeinfo", + factory.createObjectLiteralExpression(properties, /*multiLine*/ true), + ); return [factory.createDecorator(typeInfoMetadata)]; } } @@ -1116,7 +1208,9 @@ export function transformTypeScript(context: TransformationContext) { * * @param node The node to test. */ - function shouldAddTypeMetadata(node: Declaration): node is MethodDeclaration | AccessorDeclaration | PropertyDeclaration { + function shouldAddTypeMetadata( + node: Declaration, + ): node is MethodDeclaration | AccessorDeclaration | PropertyDeclaration { const kind = node.kind; return kind === SyntaxKind.MethodDeclaration || kind === SyntaxKind.GetAccessor @@ -1142,7 +1236,9 @@ export function transformTypeScript(context: TransformationContext) { * * @param node The node to test. */ - function shouldAddParamTypesMetadata(node: Declaration): node is ClassLikeDeclaration & { _hasConstructorBrand: never; } | MethodDeclaration | AccessorDeclaration { + function shouldAddParamTypesMetadata( + node: Declaration, + ): node is ClassLikeDeclaration & { _hasConstructorBrand: never; } | MethodDeclaration | AccessorDeclaration { switch (node.kind) { case SyntaxKind.ClassDeclaration: case SyntaxKind.ClassExpression: @@ -1161,7 +1257,10 @@ export function transformTypeScript(context: TransformationContext) { * * @param member The member whose name should be converted into an expression. */ - function getExpressionForPropertyName(member: ClassElement | EnumMember, generateNameForComputedPropertyName: boolean): Expression { + function getExpressionForPropertyName( + member: ClassElement | EnumMember, + generateNameForComputedPropertyName: boolean, + ): Expression { const name = member.name!; if (isPrivateIdentifier(name)) { return factory.createIdentifier(""); @@ -1192,7 +1291,11 @@ export function transformTypeScript(context: TransformationContext) { // The names are used more than once when: // - the property is non-static and its initializer is moved to the constructor (when there are parameter property assignments). // - the property has a decorator. - if (isComputedPropertyName(name) && ((!hasStaticModifier(member) && currentClassHasParameterProperties) || hasDecorators(member) && legacyDecorators)) { + if ( + isComputedPropertyName(name) + && ((!hasStaticModifier(member) && currentClassHasParameterProperties) + || hasDecorators(member) && legacyDecorators) + ) { const expression = visitNode(name.expression, visitor, isExpression); Debug.assert(expression); const innerExpression = skipPartiallyEmittedExpressions(expression); @@ -1244,7 +1347,9 @@ export function transformTypeScript(context: TransformationContext) { * * @param node The declaration node. */ - function shouldEmitFunctionLikeDeclaration(node: T): node is T & { body: NonNullable; } { + function shouldEmitFunctionLikeDeclaration( + node: T, + ): node is T & { body: NonNullable; } { return !nodeIsMissing(node.body); } @@ -1254,10 +1359,10 @@ export function transformTypeScript(context: TransformationContext) { return undefined; } - let modifiers = isClassLike(parent) ? !isAmbient ? - visitNodes(node.modifiers, visitor, isModifierLike) : - visitNodes(node.modifiers, modifierElidingVisitor, isModifierLike) : - visitNodes(node.modifiers, decoratorElidingVisitor, isModifierLike); + let modifiers = isClassLike(parent) ? !isAmbient + ? visitNodes(node.modifiers, visitor, isModifierLike) + : visitNodes(node.modifiers, modifierElidingVisitor, isModifierLike) + : visitNodes(node.modifiers, decoratorElidingVisitor, isModifierLike); modifiers = injectClassElementTypeMetadata(modifiers, node, parent); @@ -1296,10 +1401,20 @@ export function transformTypeScript(context: TransformationContext) { ); } - function transformConstructorBodyWorker(statementsOut: Statement[], statementsIn: NodeArray, statementOffset: number, superPath: readonly number[], superPathDepth: number, initializerStatements: readonly Statement[]) { + function transformConstructorBodyWorker( + statementsOut: Statement[], + statementsIn: NodeArray, + statementOffset: number, + superPath: readonly number[], + superPathDepth: number, + initializerStatements: readonly Statement[], + ) { const superStatementIndex = superPath[superPathDepth]; const superStatement = statementsIn[superStatementIndex]; - addRange(statementsOut, visitNodes(statementsIn, visitor, isStatement, statementOffset, superStatementIndex - statementOffset)); + addRange( + statementsOut, + visitNodes(statementsIn, visitor, isStatement, statementOffset, superStatementIndex - statementOffset), + ); if (isTryStatement(superStatement)) { const tryBlockStatements: Statement[] = []; @@ -1330,8 +1445,10 @@ export function transformTypeScript(context: TransformationContext) { } function transformConstructorBody(body: Block, constructor: ConstructorDeclaration) { - const parametersWithPropertyAssignments = constructor && - filter(constructor.parameters, p => isParameterPropertyDeclaration(p, constructor)) as readonly ParameterPropertyDeclaration[] | undefined; + const parametersWithPropertyAssignments = constructor + && filter(constructor.parameters, p => isParameterPropertyDeclaration(p, constructor)) as + | readonly ParameterPropertyDeclaration[] + | undefined; if (!some(parametersWithPropertyAssignments)) { return visitFunctionBody(body, visitor, context); } @@ -1340,7 +1457,12 @@ export function transformTypeScript(context: TransformationContext) { resumeLexicalEnvironment(); - const prologueStatementCount = factory.copyPrologue(body.statements, statements, /*ensureUseStrict*/ false, visitor); + const prologueStatementCount = factory.copyPrologue( + body.statements, + statements, + /*ensureUseStrict*/ false, + visitor, + ); const superPath = findSuperStatementIndexPath(body.statements, prologueStatementCount); // Transform parameters into property assignments. Transforms this: @@ -1355,9 +1477,19 @@ export function transformTypeScript(context: TransformationContext) { // this.y = y; // } // - const parameterPropertyAssignments = mapDefined(parametersWithPropertyAssignments, transformParameterWithPropertyAssignment); + const parameterPropertyAssignments = mapDefined( + parametersWithPropertyAssignments, + transformParameterWithPropertyAssignment, + ); if (superPath.length) { - transformConstructorBodyWorker(statements, body.statements, prologueStatementCount, superPath, /*superPathDepth*/ 0, parameterPropertyAssignments); + transformConstructorBodyWorker( + statements, + body.statements, + prologueStatementCount, + superPath, + /*superPathDepth*/ 0, + parameterPropertyAssignments, + ); } else { addRange(statements, parameterPropertyAssignments); @@ -1366,7 +1498,10 @@ export function transformTypeScript(context: TransformationContext) { // End the lexical environment. statements = factory.mergeLexicalEnvironment(statements, endLexicalEnvironment()); - const block = factory.createBlock(setTextRange(factory.createNodeArray(statements), body.statements), /*multiLine*/ true); + const block = factory.createBlock( + setTextRange(factory.createNodeArray(statements), body.statements), + /*multiLine*/ true, + ); setTextRange(block, /*location*/ body); setOriginalNode(block, body); return block; @@ -1424,9 +1559,9 @@ export function transformTypeScript(context: TransformationContext) { return undefined; } - let modifiers = isClassLike(parent) ? - visitNodes(node.modifiers, visitor, isModifierLike) : - visitNodes(node.modifiers, decoratorElidingVisitor, isModifierLike); + let modifiers = isClassLike(parent) + ? visitNodes(node.modifiers, visitor, isModifierLike) + : visitNodes(node.modifiers, decoratorElidingVisitor, isModifierLike); modifiers = injectClassElementTypeMetadata(modifiers, node, parent); @@ -1462,9 +1597,9 @@ export function transformTypeScript(context: TransformationContext) { return undefined; } - let modifiers = isClassLike(parent) ? - visitNodes(node.modifiers, visitor, isModifierLike) : - visitNodes(node.modifiers, decoratorElidingVisitor, isModifierLike); + let modifiers = isClassLike(parent) + ? visitNodes(node.modifiers, visitor, isModifierLike) + : visitNodes(node.modifiers, decoratorElidingVisitor, isModifierLike); modifiers = injectClassElementTypeMetadata(modifiers, node, parent); @@ -1487,9 +1622,9 @@ export function transformTypeScript(context: TransformationContext) { return undefined; } - let modifiers = isClassLike(parent) ? - visitNodes(node.modifiers, visitor, isModifierLike) : - visitNodes(node.modifiers, decoratorElidingVisitor, isModifierLike); + let modifiers = isClassLike(parent) + ? visitNodes(node.modifiers, visitor, isModifierLike) + : visitNodes(node.modifiers, decoratorElidingVisitor, isModifierLike); modifiers = injectClassElementTypeMetadata(modifiers, node, parent); @@ -1779,7 +1914,12 @@ export function transformTypeScript(context: TransformationContext) { // `exportName` is the expression used within this node's container for any exported references. const exportName = isExportOfNamespace(node) - ? factory.getExternalModuleOrNamespaceExportName(currentNamespaceContainerName, node, /*allowComments*/ false, /*allowSourceMaps*/ true) + ? factory.getExternalModuleOrNamespaceExportName( + currentNamespaceContainerName, + node, + /*allowComments*/ false, + /*allowSourceMaps*/ true, + ) : factory.getDeclarationName(node, /*allowComments*/ false, /*allowSourceMaps*/ true); // x || (x = {}) @@ -1811,7 +1951,11 @@ export function transformTypeScript(context: TransformationContext) { /*asteriskToken*/ undefined, /*name*/ undefined, /*typeParameters*/ undefined, - [factory.createParameterDeclaration(/*modifiers*/ undefined, /*dotDotDotToken*/ undefined, parameterName)], + [factory.createParameterDeclaration( + /*modifiers*/ undefined, + /*dotDotDotToken*/ undefined, + parameterName, + )], /*type*/ undefined, transformEnumBody(node, containerName), ), @@ -1873,9 +2017,9 @@ export function transformTypeScript(context: TransformationContext) { ), valueExpression, ); - const outerAssignment = valueExpression.kind === SyntaxKind.StringLiteral ? - innerAssignment : - factory.createAssignment( + const outerAssignment = valueExpression.kind === SyntaxKind.StringLiteral + ? innerAssignment + : factory.createAssignment( factory.createElementAccessExpression( currentNamespaceContainerName, innerAssignment, @@ -1901,9 +2045,13 @@ export function transformTypeScript(context: TransformationContext) { function transformEnumMemberDeclarationValue(member: EnumMember): Expression { const value = resolver.getConstantValue(member); if (value !== undefined) { - return typeof value === "string" ? factory.createStringLiteral(value) : - value < 0 ? factory.createPrefixUnaryExpression(SyntaxKind.MinusToken, factory.createNumericLiteral(Math.abs(value))) : - factory.createNumericLiteral(value); + return typeof value === "string" ? factory.createStringLiteral(value) + : value < 0 + ? factory.createPrefixUnaryExpression( + SyntaxKind.MinusToken, + factory.createNumericLiteral(Math.abs(value)), + ) + : factory.createNumericLiteral(value); } else { enableSubstitutionForNonQualifiedEnumMembers(); @@ -1934,7 +2082,9 @@ export function transformTypeScript(context: TransformationContext) { * Records that a declaration was emitted in the current scope, if it was the first * declaration for the provided symbol. */ - function recordEmittedDeclarationInScope(node: FunctionDeclaration | ClassDeclaration | ModuleDeclaration | EnumDeclaration) { + function recordEmittedDeclarationInScope( + node: FunctionDeclaration | ClassDeclaration | ModuleDeclaration | EnumDeclaration, + ) { if (!currentScopeFirstDeclarationsOfName) { currentScopeFirstDeclarationsOfName = new Map(); } @@ -1957,7 +2107,9 @@ export function transformTypeScript(context: TransformationContext) { return true; } - function declaredNameInScope(node: FunctionDeclaration | ClassDeclaration | ModuleDeclaration | EnumDeclaration): __String { + function declaredNameInScope( + node: FunctionDeclaration | ClassDeclaration | ModuleDeclaration | EnumDeclaration, + ): __String { Debug.assertNode(node.name, isIdentifier); return node.name.escapedText; } @@ -1969,7 +2121,9 @@ export function transformTypeScript(context: TransformationContext) { // Emit a variable statement for the module. We emit top-level enums as a `var` // declaration to avoid static errors in global scripts scripts due to redeclaration. // enums in any other scope are emitted as a `let` declaration. - const varDecl = factory.createVariableDeclaration(factory.getLocalName(node, /*allowComments*/ false, /*allowSourceMaps*/ true)); + const varDecl = factory.createVariableDeclaration( + factory.getLocalName(node, /*allowComments*/ false, /*allowSourceMaps*/ true), + ); const varFlags = currentLexicalScope.kind === SyntaxKind.SourceFile ? NodeFlags.None : NodeFlags.Let; const statement = factory.createVariableStatement( visitNodes(node.modifiers, modifierVisitor, isModifier), @@ -2061,7 +2215,12 @@ export function transformTypeScript(context: TransformationContext) { // `exportName` is the expression used within this node's container for any exported references. const exportName = isExportOfNamespace(node) - ? factory.getExternalModuleOrNamespaceExportName(currentNamespaceContainerName, node, /*allowComments*/ false, /*allowSourceMaps*/ true) + ? factory.getExternalModuleOrNamespaceExportName( + currentNamespaceContainerName, + node, + /*allowComments*/ false, + /*allowSourceMaps*/ true, + ) : factory.getDeclarationName(node, /*allowComments*/ false, /*allowSourceMaps*/ true); // x || (x = {}) @@ -2092,7 +2251,11 @@ export function transformTypeScript(context: TransformationContext) { /*asteriskToken*/ undefined, /*name*/ undefined, /*typeParameters*/ undefined, - [factory.createParameterDeclaration(/*modifiers*/ undefined, /*dotDotDotToken*/ undefined, parameterName)], + [factory.createParameterDeclaration( + /*modifiers*/ undefined, + /*dotDotDotToken*/ undefined, + parameterName, + )], /*type*/ undefined, transformModuleBody(node, containerName), ), @@ -2134,7 +2297,10 @@ export function transformTypeScript(context: TransformationContext) { let blockLocation: TextRange | undefined; if (node.body) { if (node.body.kind === SyntaxKind.ModuleBlock) { - saveStateAndInvoke(node.body, body => addRange(statements, visitNodes(body.statements, namespaceElementVisitor, isStatement))); + saveStateAndInvoke( + node.body, + body => addRange(statements, visitNodes(body.statements, namespaceElementVisitor, isStatement)), + ); statementsLocation = node.body.statements; blockLocation = node.body; } @@ -2194,9 +2360,13 @@ export function transformTypeScript(context: TransformationContext) { return block; } - function getInnerMostModuleDeclarationFromDottedModule(moduleDeclaration: ModuleDeclaration): ModuleDeclaration | undefined { + function getInnerMostModuleDeclarationFromDottedModule( + moduleDeclaration: ModuleDeclaration, + ): ModuleDeclaration | undefined { if (moduleDeclaration.body!.kind === SyntaxKind.ModuleDeclaration) { - const recursiveInnerModule = getInnerMostModuleDeclarationFromDottedModule(moduleDeclaration.body as ModuleDeclaration); + const recursiveInnerModule = getInnerMostModuleDeclarationFromDottedModule( + moduleDeclaration.body as ModuleDeclaration, + ); return recursiveInnerModule || moduleDeclaration.body as ModuleDeclaration; } } @@ -2219,9 +2389,9 @@ export function transformTypeScript(context: TransformationContext) { // Elide the declaration if the import clause was elided. const importClause = visitNode(node.importClause, visitImportClause, isImportClause); - return importClause || - compilerOptions.importsNotUsedAsValues === ImportsNotUsedAsValues.Preserve || - compilerOptions.importsNotUsedAsValues === ImportsNotUsedAsValues.Error + return importClause + || compilerOptions.importsNotUsedAsValues === ImportsNotUsedAsValues.Preserve + || compilerOptions.importsNotUsedAsValues === ImportsNotUsedAsValues.Error ? factory.updateImportDeclaration( node, /*modifiers*/ undefined, @@ -2242,7 +2412,8 @@ export function transformTypeScript(context: TransformationContext) { // Elide the import clause if we elide both its name and its named bindings. const name = shouldEmitAliasDeclaration(node) ? node.name : undefined; const namedBindings = visitNode(node.namedBindings, visitNamedImportBindings, isNamedImportBindings); - return (name || namedBindings) ? factory.updateImportClause(node, /*isTypeOnly*/ false, name, namedBindings) : undefined; + return (name || namedBindings) ? factory.updateImportClause(node, /*isTypeOnly*/ false, name, namedBindings) + : undefined; } /** @@ -2258,8 +2429,8 @@ export function transformTypeScript(context: TransformationContext) { else { // Elide named imports if all of its import specifiers are elided and settings allow. const allowEmpty = compilerOptions.verbatimModuleSyntax || compilerOptions.preserveValueImports && ( - compilerOptions.importsNotUsedAsValues === ImportsNotUsedAsValues.Preserve || - compilerOptions.importsNotUsedAsValues === ImportsNotUsedAsValues.Error + compilerOptions.importsNotUsedAsValues === ImportsNotUsedAsValues.Preserve + || compilerOptions.importsNotUsedAsValues === ImportsNotUsedAsValues.Error ); const elements = visitNodes(node.elements, visitImportSpecifier, isImportSpecifier); return allowEmpty || some(elements) ? factory.updateNamedImports(node, elements) : undefined; @@ -2307,8 +2478,8 @@ export function transformTypeScript(context: TransformationContext) { // Elide the export declaration if all of its named exports are elided. const allowEmpty = compilerOptions.verbatimModuleSyntax || !!node.moduleSpecifier && ( - compilerOptions.importsNotUsedAsValues === ImportsNotUsedAsValues.Preserve || - compilerOptions.importsNotUsedAsValues === ImportsNotUsedAsValues.Error + compilerOptions.importsNotUsedAsValues === ImportsNotUsedAsValues.Preserve + || compilerOptions.importsNotUsedAsValues === ImportsNotUsedAsValues.Error ); const exportClause = visitNode( node.exportClause, @@ -2344,7 +2515,10 @@ export function transformTypeScript(context: TransformationContext) { return factory.updateNamespaceExport(node, Debug.checkDefined(visitNode(node.name, visitor, isIdentifier))); } - function visitNamedExportBindings(node: NamedExportBindings, allowEmpty: boolean): VisitResult | undefined { + function visitNamedExportBindings( + node: NamedExportBindings, + allowEmpty: boolean, + ): VisitResult | undefined { return isNamespaceExport(node) ? visitNamespaceExports(node) : visitNamedExports(node, allowEmpty); } @@ -2355,7 +2529,8 @@ export function transformTypeScript(context: TransformationContext) { */ function visitExportSpecifier(node: ExportSpecifier): VisitResult | undefined { // Elide an export specifier if it does not reference a value. - return !node.isTypeOnly && (compilerOptions.verbatimModuleSyntax || resolver.isValueAliasDeclaration(node)) ? node : undefined; + return !node.isTypeOnly && (compilerOptions.verbatimModuleSyntax || resolver.isValueAliasDeclaration(node)) + ? node : undefined; } /** @@ -2488,7 +2663,12 @@ export function transformTypeScript(context: TransformationContext) { function createExportMemberAssignmentStatement(node: ClassDeclaration | FunctionDeclaration) { const expression = factory.createAssignment( - factory.getExternalModuleOrNamespaceExportName(currentNamespaceContainerName, node, /*allowComments*/ false, /*allowSourceMaps*/ true), + factory.getExternalModuleOrNamespaceExportName( + currentNamespaceContainerName, + node, + /*allowComments*/ false, + /*allowSourceMaps*/ true, + ), factory.getLocalName(node), ); setSourceMapRange(expression, createRange(node.name ? node.name.pos : node.pos, node.end)); @@ -2506,7 +2686,12 @@ export function transformTypeScript(context: TransformationContext) { return setTextRange( factory.createExpressionStatement( factory.createAssignment( - factory.getNamespaceMemberName(currentNamespaceContainerName, exportName, /*allowComments*/ false, /*allowSourceMaps*/ true), + factory.getNamespaceMemberName( + currentNamespaceContainerName, + exportName, + /*allowComments*/ false, + /*allowSourceMaps*/ true, + ), exportValue, ), ), @@ -2515,11 +2700,19 @@ export function transformTypeScript(context: TransformationContext) { } function createNamespaceExportExpression(exportName: Identifier, exportValue: Expression, location?: TextRange) { - return setTextRange(factory.createAssignment(getNamespaceMemberNameWithSourceMapsAndWithoutComments(exportName), exportValue), location); + return setTextRange( + factory.createAssignment(getNamespaceMemberNameWithSourceMapsAndWithoutComments(exportName), exportValue), + location, + ); } function getNamespaceMemberNameWithSourceMapsAndWithoutComments(name: Identifier) { - return factory.getNamespaceMemberName(currentNamespaceContainerName, name, /*allowComments*/ false, /*allowSourceMaps*/ true); + return factory.getNamespaceMemberName( + currentNamespaceContainerName, + name, + /*allowComments*/ false, + /*allowSourceMaps*/ true, + ); } /** @@ -2583,11 +2776,16 @@ export function transformTypeScript(context: TransformationContext) { currentSourceFile = node; } - if (enabledSubstitutions & TypeScriptSubstitutionFlags.NamespaceExports && isTransformedModuleDeclaration(node)) { + if ( + enabledSubstitutions & TypeScriptSubstitutionFlags.NamespaceExports && isTransformedModuleDeclaration(node) + ) { applicableSubstitutions |= TypeScriptSubstitutionFlags.NamespaceExports; } - if (enabledSubstitutions & TypeScriptSubstitutionFlags.NonQualifiedEnumMembers && isTransformedEnumDeclaration(node)) { + if ( + enabledSubstitutions & TypeScriptSubstitutionFlags.NonQualifiedEnumMembers + && isTransformedEnumDeclaration(node) + ) { applicableSubstitutions |= TypeScriptSubstitutionFlags.NonQualifiedEnumMembers; } @@ -2657,8 +2855,10 @@ export function transformTypeScript(context: TransformationContext) { // an identifier that is exported from a merged namespace. const container = resolver.getReferencedExportContainer(node, /*prefixLocals*/ false); if (container && container.kind !== SyntaxKind.SourceFile) { - const substitute = (applicableSubstitutions & TypeScriptSubstitutionFlags.NamespaceExports && container.kind === SyntaxKind.ModuleDeclaration) || - (applicableSubstitutions & TypeScriptSubstitutionFlags.NonQualifiedEnumMembers && container.kind === SyntaxKind.EnumDeclaration); + const substitute = (applicableSubstitutions & TypeScriptSubstitutionFlags.NamespaceExports + && container.kind === SyntaxKind.ModuleDeclaration) + || (applicableSubstitutions & TypeScriptSubstitutionFlags.NonQualifiedEnumMembers + && container.kind === SyntaxKind.EnumDeclaration); if (substitute) { return setTextRange( factory.createPropertyAccessExpression(factory.getGeneratedNameForNode(container), node), @@ -2688,13 +2888,21 @@ export function transformTypeScript(context: TransformationContext) { if (constantValue !== undefined) { // track the constant value on the node for the printer in mayNeedDotDotForPropertyAccess setConstantValue(node, constantValue); - const substitute = typeof constantValue === "string" ? factory.createStringLiteral(constantValue) : - constantValue < 0 ? factory.createPrefixUnaryExpression(SyntaxKind.MinusToken, factory.createNumericLiteral(Math.abs(constantValue))) : - factory.createNumericLiteral(constantValue); + const substitute = typeof constantValue === "string" ? factory.createStringLiteral(constantValue) + : constantValue < 0 + ? factory.createPrefixUnaryExpression( + SyntaxKind.MinusToken, + factory.createNumericLiteral(Math.abs(constantValue)), + ) + : factory.createNumericLiteral(constantValue); if (!compilerOptions.removeComments) { const originalNode = getOriginalNode(node, isAccessExpression); - addSyntheticTrailingComment(substitute, SyntaxKind.MultiLineCommentTrivia, ` ${safeMultiLineComment(getTextOfNode(originalNode))} `); + addSyntheticTrailingComment( + substitute, + SyntaxKind.MultiLineCommentTrivia, + ` ${safeMultiLineComment(getTextOfNode(originalNode))} `, + ); } return substitute; } @@ -2706,12 +2914,13 @@ export function transformTypeScript(context: TransformationContext) { return undefined; } - return isPropertyAccessExpression(node) || isElementAccessExpression(node) ? resolver.getConstantValue(node) : undefined; + return isPropertyAccessExpression(node) || isElementAccessExpression(node) ? resolver.getConstantValue(node) + : undefined; } function shouldEmitAliasDeclaration(node: Node): boolean { - return compilerOptions.verbatimModuleSyntax || isInJSFile(node) || - (compilerOptions.preserveValueImports + return compilerOptions.verbatimModuleSyntax || isInJSFile(node) + || (compilerOptions.preserveValueImports ? resolver.isValueAliasDeclaration(node) : resolver.isReferencedAliasDeclaration(node)); } diff --git a/src/compiler/transformers/typeSerializer.ts b/src/compiler/transformers/typeSerializer.ts index 6b0b0ad87e3e5..4eef4f419ee17 100644 --- a/src/compiler/transformers/typeSerializer.ts +++ b/src/compiler/transformers/typeSerializer.ts @@ -117,12 +117,24 @@ export interface RuntimeTypeSerializer { * Serializes the type of a node for use with decorator type metadata. * @param node The node that should have its type serialized. */ - serializeTypeOfNode(serializerContext: RuntimeTypeSerializerContext, node: PropertyDeclaration | ParameterDeclaration | AccessorDeclaration | ClassLikeDeclaration | MethodDeclaration): Expression; + serializeTypeOfNode( + serializerContext: RuntimeTypeSerializerContext, + node: + | PropertyDeclaration + | ParameterDeclaration + | AccessorDeclaration + | ClassLikeDeclaration + | MethodDeclaration, + ): Expression; /** * Serializes the types of the parameters of a node for use with decorator type metadata. * @param node The node that should have its parameter types serialized. */ - serializeParameterTypesOfNode(serializerContext: RuntimeTypeSerializerContext, node: Node, container: ClassLikeDeclaration): ArrayLiteralExpression; + serializeParameterTypesOfNode( + serializerContext: RuntimeTypeSerializerContext, + node: Node, + container: ClassLikeDeclaration, + ): ArrayLiteralExpression; /** * Serializes the return type of a node for use with decorator type metadata. * @param node The node that should have its return type serialized. @@ -146,15 +158,33 @@ export function createRuntimeTypeSerializer(context: TransformationContext): Run let currentNameScope: ClassLikeDeclaration | undefined; return { - serializeTypeNode: (serializerContext, node) => setSerializerContextAnd(serializerContext, serializeTypeNode, node), - serializeTypeOfNode: (serializerContext, node) => setSerializerContextAnd(serializerContext, serializeTypeOfNode, node), - serializeParameterTypesOfNode: (serializerContext, node, container) => setSerializerContextAnd(serializerContext, serializeParameterTypesOfNode, node, container), - serializeReturnTypeOfNode: (serializerContext, node) => setSerializerContextAnd(serializerContext, serializeReturnTypeOfNode, node), + serializeTypeNode: (serializerContext, node) => + setSerializerContextAnd(serializerContext, serializeTypeNode, node), + serializeTypeOfNode: (serializerContext, node) => + setSerializerContextAnd(serializerContext, serializeTypeOfNode, node), + serializeParameterTypesOfNode: (serializerContext, node, container) => + setSerializerContextAnd(serializerContext, serializeParameterTypesOfNode, node, container), + serializeReturnTypeOfNode: (serializerContext, node) => + setSerializerContextAnd(serializerContext, serializeReturnTypeOfNode, node), }; - function setSerializerContextAnd(serializerContext: RuntimeTypeSerializerContext, cb: (node: TNode) => R, node: TNode): R; - function setSerializerContextAnd(serializerContext: RuntimeTypeSerializerContext, cb: (node: TNode, arg: T) => R, node: TNode, arg: T): R; - function setSerializerContextAnd(serializerContext: RuntimeTypeSerializerContext, cb: (node: TNode, arg?: T) => R, node: TNode, arg?: T) { + function setSerializerContextAnd( + serializerContext: RuntimeTypeSerializerContext, + cb: (node: TNode) => R, + node: TNode, + ): R; + function setSerializerContextAnd( + serializerContext: RuntimeTypeSerializerContext, + cb: (node: TNode, arg: T) => R, + node: TNode, + arg: T, + ): R; + function setSerializerContextAnd( + serializerContext: RuntimeTypeSerializerContext, + cb: (node: TNode, arg?: T) => R, + node: TNode, + arg?: T, + ) { const savedCurrentLexicalScope = currentLexicalScope; const savedCurrentNameScope = currentNameScope; @@ -178,7 +208,14 @@ export function createRuntimeTypeSerializer(context: TransformationContext): Run * Serializes the type of a node for use with decorator type metadata. * @param node The node that should have its type serialized. */ - function serializeTypeOfNode(node: PropertyDeclaration | ParameterDeclaration | AccessorDeclaration | ClassLikeDeclaration | MethodDeclaration): SerializedTypeNode { + function serializeTypeOfNode( + node: + | PropertyDeclaration + | ParameterDeclaration + | AccessorDeclaration + | ClassLikeDeclaration + | MethodDeclaration, + ): SerializedTypeNode { switch (node.kind) { case SyntaxKind.PropertyDeclaration: case SyntaxKind.Parameter: @@ -292,9 +329,9 @@ export function createRuntimeTypeSerializer(context: TransformationContext): Run return factory.createIdentifier("Array"); case SyntaxKind.TypePredicate: - return (node as TypePredicateNode).assertsModifier ? - factory.createVoidZero() : - factory.createIdentifier("Boolean"); + return (node as TypePredicateNode).assertsModifier + ? factory.createVoidZero() + : factory.createIdentifier("Boolean"); case SyntaxKind.BooleanKeyword: return factory.createIdentifier("Boolean"); @@ -322,13 +359,22 @@ export function createRuntimeTypeSerializer(context: TransformationContext): Run return serializeTypeReferenceNode(node as TypeReferenceNode); case SyntaxKind.IntersectionType: - return serializeUnionOrIntersectionConstituents((node as UnionOrIntersectionTypeNode).types, /*isIntersection*/ true); + return serializeUnionOrIntersectionConstituents( + (node as UnionOrIntersectionTypeNode).types, + /*isIntersection*/ true, + ); case SyntaxKind.UnionType: - return serializeUnionOrIntersectionConstituents((node as UnionOrIntersectionTypeNode).types, /*isIntersection*/ false); + return serializeUnionOrIntersectionConstituents( + (node as UnionOrIntersectionTypeNode).types, + /*isIntersection*/ false, + ); case SyntaxKind.ConditionalType: - return serializeUnionOrIntersectionConstituents([(node as ConditionalTypeNode).trueType, (node as ConditionalTypeNode).falseType], /*isIntersection*/ false); + return serializeUnionOrIntersectionConstituents([ + (node as ConditionalTypeNode).trueType, + (node as ConditionalTypeNode).falseType, + ], /*isIntersection*/ false); case SyntaxKind.TypeOperator: if ((node as TypeOperatorNode).operator === SyntaxKind.ReadonlyKeyword) { @@ -401,7 +447,10 @@ export function createRuntimeTypeSerializer(context: TransformationContext): Run } } - function serializeUnionOrIntersectionConstituents(types: readonly TypeNode[], isIntersection: boolean): SerializedTypeNode { + function serializeUnionOrIntersectionConstituents( + types: readonly TypeNode[], + isIntersection: boolean, + ): SerializedTypeNode { // Note when updating logic here also update `getEntityNameForDecoratorMetadata` in checker.ts so that aliases can be marked as referenced let serializedType: SerializedTypeNode | undefined; for (let typeNode of types) { @@ -420,7 +469,11 @@ export function createRuntimeTypeSerializer(context: TransformationContext): Run return factory.createIdentifier("Object"); // Reduce to `any` in a union or intersection } - if (!strictNullChecks && ((isLiteralTypeNode(typeNode) && typeNode.literal.kind === SyntaxKind.NullKeyword) || typeNode.kind === SyntaxKind.UndefinedKeyword)) { + if ( + !strictNullChecks + && ((isLiteralTypeNode(typeNode) && typeNode.literal.kind === SyntaxKind.NullKeyword) + || typeNode.kind === SyntaxKind.UndefinedKeyword) + ) { continue; // Elide null and undefined from unions for metadata, just like what we did prior to the implementation of strict null checks } @@ -451,37 +504,37 @@ export function createRuntimeTypeSerializer(context: TransformationContext): Run function equateSerializedTypeNodes(left: Expression, right: Expression): boolean { return ( // temp vars used in fallback - isGeneratedIdentifier(left) ? isGeneratedIdentifier(right) : + isGeneratedIdentifier(left) ? isGeneratedIdentifier(right) // entity names - isIdentifier(left) ? isIdentifier(right) - && left.escapedText === right.escapedText : - isPropertyAccessExpression(left) ? isPropertyAccessExpression(right) + : isIdentifier(left) ? isIdentifier(right) + && left.escapedText === right.escapedText + : isPropertyAccessExpression(left) ? isPropertyAccessExpression(right) && equateSerializedTypeNodes(left.expression, right.expression) - && equateSerializedTypeNodes(left.name, right.name) : + && equateSerializedTypeNodes(left.name, right.name) // `void 0` - isVoidExpression(left) ? isVoidExpression(right) + : isVoidExpression(left) ? isVoidExpression(right) && isNumericLiteral(left.expression) && left.expression.text === "0" - && isNumericLiteral(right.expression) && right.expression.text === "0" : + && isNumericLiteral(right.expression) && right.expression.text === "0" // `"undefined"` or `"function"` in `typeof` checks - isStringLiteral(left) ? isStringLiteral(right) - && left.text === right.text : + : isStringLiteral(left) ? isStringLiteral(right) + && left.text === right.text // used in `typeof` checks for fallback - isTypeOfExpression(left) ? isTypeOfExpression(right) - && equateSerializedTypeNodes(left.expression, right.expression) : + : isTypeOfExpression(left) ? isTypeOfExpression(right) + && equateSerializedTypeNodes(left.expression, right.expression) // parens in `typeof` checks with temps - isParenthesizedExpression(left) ? isParenthesizedExpression(right) - && equateSerializedTypeNodes(left.expression, right.expression) : + : isParenthesizedExpression(left) ? isParenthesizedExpression(right) + && equateSerializedTypeNodes(left.expression, right.expression) // conditionals used in fallback - isConditionalExpression(left) ? isConditionalExpression(right) + : isConditionalExpression(left) ? isConditionalExpression(right) && equateSerializedTypeNodes(left.condition, right.condition) && equateSerializedTypeNodes(left.whenTrue, right.whenTrue) - && equateSerializedTypeNodes(left.whenFalse, right.whenFalse) : + && equateSerializedTypeNodes(left.whenFalse, right.whenFalse) // logical binary and assignments used in fallback - isBinaryExpression(left) ? isBinaryExpression(right) + : isBinaryExpression(left) ? isBinaryExpression(right) && left.operatorToken.kind === right.operatorToken.kind && equateSerializedTypeNodes(left.left, right.left) - && equateSerializedTypeNodes(left.right, right.right) : - false + && equateSerializedTypeNodes(left.right, right.right) + : false ); } @@ -494,7 +547,11 @@ export function createRuntimeTypeSerializer(context: TransformationContext): Run switch (kind) { case TypeReferenceSerializationKind.Unknown: // From conditional type type reference that cannot be resolved is Similar to any or unknown - if (findAncestor(node, n => n.parent && isConditionalTypeNode(n.parent) && (n.parent.trueType === n || n.parent.falseType === n))) { + if ( + findAncestor(node, n => + n.parent && isConditionalTypeNode(n.parent) + && (n.parent.trueType === n || n.parent.falseType === n)) + ) { return factory.createIdentifier("Object"); } @@ -559,7 +616,10 @@ export function createRuntimeTypeSerializer(context: TransformationContext): Run */ function createCheckedValue(left: Expression, right: Expression) { return factory.createLogicalAnd( - factory.createStrictInequality(factory.createTypeOfExpression(left), factory.createStringLiteral("undefined")), + factory.createStrictInequality( + factory.createTypeOfExpression(left), + factory.createStringLiteral("undefined"), + ), right, ); } @@ -576,7 +636,10 @@ export function createRuntimeTypeSerializer(context: TransformationContext): Run } if (node.left.kind === SyntaxKind.Identifier) { // A.B -> typeof A !== "undefined" && A.B - return createCheckedValue(serializeEntityNameAsExpression(node.left), serializeEntityNameAsExpression(node)); + return createCheckedValue( + serializeEntityNameAsExpression(node.left), + serializeEntityNameAsExpression(node), + ); } // A.B.C -> typeof A !== "undefined" && (_a = A.B) !== void 0 && _a.C const left = serializeEntityNameAsExpressionFallback(node.left); @@ -614,7 +677,10 @@ export function createRuntimeTypeSerializer(context: TransformationContext): Run * @param node The qualified name to serialize. */ function serializeQualifiedNameAsExpression(node: QualifiedName): SerializedEntityName { - return factory.createPropertyAccessExpression(serializeEntityNameAsExpression(node.left), node.right) as PropertyAccessEntityNameExpression; + return factory.createPropertyAccessExpression( + serializeEntityNameAsExpression(node.left), + node.right, + ) as PropertyAccessEntityNameExpression; } function getGlobalConstructorWithFallback(name: string) { @@ -628,8 +694,8 @@ export function createRuntimeTypeSerializer(context: TransformationContext): Run } function getGlobalConstructor(name: string, minLanguageVersion: ScriptTarget): SerializedTypeNode { - return languageVersion < minLanguageVersion ? - getGlobalConstructorWithFallback(name) : - factory.createIdentifier(name); + return languageVersion < minLanguageVersion + ? getGlobalConstructorWithFallback(name) + : factory.createIdentifier(name); } } diff --git a/src/compiler/transformers/utilities.ts b/src/compiler/transformers/utilities.ts index 900a409ee9681..c57aa675e81cc 100644 --- a/src/compiler/transformers/utilities.ts +++ b/src/compiler/transformers/utilities.ts @@ -117,7 +117,10 @@ function isNamedDefaultReference(e: ImportSpecifier): boolean { } /** @internal */ -export function chainBundle(context: CoreTransformationContext, transformSourceFile: (x: SourceFile) => SourceFile): (x: SourceFile | Bundle) => SourceFile | Bundle { +export function chainBundle( + context: CoreTransformationContext, + transformSourceFile: (x: SourceFile) => SourceFile, +): (x: SourceFile | Bundle) => SourceFile | Bundle { return transformSourceFileOrBundle; function transformSourceFileOrBundle(node: SourceFile | Bundle) { @@ -151,13 +154,17 @@ export function getImportNeedsImportStarHelper(node: ImportDeclaration): boolean } } // Import star is required if there's default named refs mixed with non-default refs, or if theres non-default refs and it has a default import - return (defaultRefCount > 0 && defaultRefCount !== bindings.elements.length) || (!!(bindings.elements.length - defaultRefCount) && isDefaultImport(node)); + return (defaultRefCount > 0 && defaultRefCount !== bindings.elements.length) + || (!!(bindings.elements.length - defaultRefCount) && isDefaultImport(node)); } /** @internal */ export function getImportNeedsImportDefaultHelper(node: ImportDeclaration): boolean { // Import default is needed if there's a default import or a default ref and no other refs (meaning an import star helper wasn't requested) - return !getImportNeedsImportStarHelper(node) && (isDefaultImport(node) || (!!node.importClause && isNamedImports(node.importClause.namedBindings!) && containsDefaultReference(node.importClause.namedBindings))); // TODO: GH#18217 + return !getImportNeedsImportStarHelper(node) + && (isDefaultImport(node) + || (!!node.importClause && isNamedImports(node.importClause.namedBindings!) + && containsDefaultReference(node.importClause.namedBindings))); // TODO: GH#18217 } /** @internal */ @@ -241,7 +248,12 @@ export function collectExternalModuleInfo(context: TransformationContext, source case SyntaxKind.VariableStatement: if (hasSyntacticModifier(node, ModifierFlags.Export)) { for (const decl of (node as VariableStatement).declarationList.declarations) { - exportedNames = collectExportedVariableInfo(decl, uniqueExports, exportedNames, exportedBindings); + exportedNames = collectExportedVariableInfo( + decl, + uniqueExports, + exportedNames, + exportedBindings, + ); } } break; @@ -251,7 +263,11 @@ export function collectExternalModuleInfo(context: TransformationContext, source if (hasSyntacticModifier(node, ModifierFlags.Default)) { // export default function() { } if (!hasExportDefault) { - multiMapSparseArrayAdd(exportedBindings, getOriginalNodeId(node), context.factory.getDeclarationName(node as FunctionDeclaration)); + multiMapSparseArrayAdd( + exportedBindings, + getOriginalNodeId(node), + context.factory.getDeclarationName(node as FunctionDeclaration), + ); hasExportDefault = true; } } @@ -272,7 +288,11 @@ export function collectExternalModuleInfo(context: TransformationContext, source if (hasSyntacticModifier(node, ModifierFlags.Default)) { // export default class { } if (!hasExportDefault) { - multiMapSparseArrayAdd(exportedBindings, getOriginalNodeId(node), context.factory.getDeclarationName(node as ClassDeclaration)); + multiMapSparseArrayAdd( + exportedBindings, + getOriginalNodeId(node), + context.factory.getDeclarationName(node as ClassDeclaration), + ); hasExportDefault = true; } } @@ -290,12 +310,28 @@ export function collectExternalModuleInfo(context: TransformationContext, source } } - const externalHelpersImportDeclaration = createExternalHelpersImportDeclarationIfNeeded(context.factory, context.getEmitHelperFactory(), sourceFile, compilerOptions, hasExportStarsToExportValues, hasImportStar, hasImportDefault); + const externalHelpersImportDeclaration = createExternalHelpersImportDeclarationIfNeeded( + context.factory, + context.getEmitHelperFactory(), + sourceFile, + compilerOptions, + hasExportStarsToExportValues, + hasImportStar, + hasImportDefault, + ); if (externalHelpersImportDeclaration) { externalImports.unshift(externalHelpersImportDeclaration); } - return { externalImports, exportSpecifiers, exportEquals, hasExportStarsToExportValues, exportedBindings, exportedNames, externalHelpersImportDeclaration }; + return { + externalImports, + exportSpecifiers, + exportEquals, + hasExportStarsToExportValues, + exportedBindings, + exportedNames, + externalHelpersImportDeclaration, + }; function addExportedNamesForExportDeclaration(node: ExportDeclaration) { for (const specifier of cast(node.exportClause, isNamedExports).elements) { @@ -319,7 +355,12 @@ export function collectExternalModuleInfo(context: TransformationContext, source } } -function collectExportedVariableInfo(decl: VariableDeclaration | BindingElement, uniqueExports: Map, exportedNames: Identifier[] | undefined, exportedBindings: Identifier[][]) { +function collectExportedVariableInfo( + decl: VariableDeclaration | BindingElement, + uniqueExports: Map, + exportedNames: Identifier[] | undefined, + exportedBindings: Identifier[][], +) { if (isBindingPattern(decl.name)) { for (const element of decl.name.elements) { if (!isOmittedExpression(element)) { @@ -390,12 +431,25 @@ export class IdentifierNameMap { const autoGenerate = name.emitNode.autoGenerate; if ((autoGenerate.flags & GeneratedIdentifierFlags.KindMask) === GeneratedIdentifierFlags.Node) { const node = getNodeForGeneratedName(name); - const baseName = isMemberName(node) && node !== name ? IdentifierNameMap.toKey(node) : `(generated@${getNodeId(node)})`; - return formatGeneratedName(/*privateName*/ false, autoGenerate.prefix, baseName, autoGenerate.suffix, IdentifierNameMap.toKey); + const baseName = isMemberName(node) && node !== name ? IdentifierNameMap.toKey(node) + : `(generated@${getNodeId(node)})`; + return formatGeneratedName( + /*privateName*/ false, + autoGenerate.prefix, + baseName, + autoGenerate.suffix, + IdentifierNameMap.toKey, + ); } else { const baseName = `(auto@${autoGenerate.id})`; - return formatGeneratedName(/*privateName*/ false, autoGenerate.prefix, baseName, autoGenerate.suffix, IdentifierNameMap.toKey); + return formatGeneratedName( + /*privateName*/ false, + autoGenerate.prefix, + baseName, + autoGenerate.suffix, + IdentifierNameMap.toKey, + ); } } if (isPrivateIdentifier(name)) { @@ -437,10 +491,10 @@ export class IdentifierNameMultiMap extends IdentifierNameMap { * @internal */ export function isSimpleCopiableExpression(expression: Expression) { - return isStringLiteralLike(expression) || - expression.kind === SyntaxKind.NumericLiteral || - isKeyword(expression.kind) || - isIdentifier(expression); + return isStringLiteralLike(expression) + || expression.kind === SyntaxKind.NumericLiteral + || isKeyword(expression.kind) + || isIdentifier(expression); } /** @@ -461,7 +515,9 @@ export function isCompoundAssignment(kind: BinaryOperator): kind is CompoundAssi } /** @internal */ -export function getNonAssignmentOperatorForCompoundAssignment(kind: CompoundAssignmentOperator): LogicalOperatorOrHigher | SyntaxKind.QuestionQuestionToken { +export function getNonAssignmentOperatorForCompoundAssignment( + kind: CompoundAssignmentOperator, +): LogicalOperatorOrHigher | SyntaxKind.QuestionQuestionToken { switch (kind) { case SyntaxKind.PlusEqualsToken: return SyntaxKind.PlusToken; @@ -519,7 +575,9 @@ function findSuperStatementIndexPathWorker(statements: NodeArray, sta indices.unshift(i); return true; } - else if (isTryStatement(statement) && findSuperStatementIndexPathWorker(statement.tryBlock.statements, 0, indices)) { + else if ( + isTryStatement(statement) && findSuperStatementIndexPathWorker(statement.tryBlock.statements, 0, indices) + ) { indices.unshift(i); return true; } @@ -550,24 +608,47 @@ export function findSuperStatementIndexPath(statements: NodeArray, st * * @internal */ -export function getProperties(node: ClassExpression | ClassDeclaration, requireInitializer: true, isStatic: boolean): readonly InitializedPropertyDeclaration[]; +export function getProperties( + node: ClassExpression | ClassDeclaration, + requireInitializer: true, + isStatic: boolean, +): readonly InitializedPropertyDeclaration[]; /** @internal */ -export function getProperties(node: ClassExpression | ClassDeclaration, requireInitializer: boolean, isStatic: boolean): readonly PropertyDeclaration[]; +export function getProperties( + node: ClassExpression | ClassDeclaration, + requireInitializer: boolean, + isStatic: boolean, +): readonly PropertyDeclaration[]; /** @internal */ -export function getProperties(node: ClassExpression | ClassDeclaration, requireInitializer: boolean, isStatic: boolean): readonly PropertyDeclaration[] { - return filter(node.members, m => isInitializedOrStaticProperty(m, requireInitializer, isStatic)) as PropertyDeclaration[]; -} - -function isStaticPropertyDeclarationOrClassStaticBlockDeclaration(element: ClassElement): element is PropertyDeclaration | ClassStaticBlockDeclaration { +export function getProperties( + node: ClassExpression | ClassDeclaration, + requireInitializer: boolean, + isStatic: boolean, +): readonly PropertyDeclaration[] { + return filter( + node.members, + m => isInitializedOrStaticProperty(m, requireInitializer, isStatic), + ) as PropertyDeclaration[]; +} + +function isStaticPropertyDeclarationOrClassStaticBlockDeclaration( + element: ClassElement, +): element is PropertyDeclaration | ClassStaticBlockDeclaration { return isStaticPropertyDeclaration(element) || isClassStaticBlockDeclaration(element); } /** @internal */ -export function getStaticPropertiesAndClassStaticBlock(node: ClassExpression | ClassDeclaration): readonly (PropertyDeclaration | ClassStaticBlockDeclaration)[]; +export function getStaticPropertiesAndClassStaticBlock( + node: ClassExpression | ClassDeclaration, +): readonly (PropertyDeclaration | ClassStaticBlockDeclaration)[]; /** @internal */ -export function getStaticPropertiesAndClassStaticBlock(node: ClassExpression | ClassDeclaration): readonly (PropertyDeclaration | ClassStaticBlockDeclaration)[]; +export function getStaticPropertiesAndClassStaticBlock( + node: ClassExpression | ClassDeclaration, +): readonly (PropertyDeclaration | ClassStaticBlockDeclaration)[]; /** @internal */ -export function getStaticPropertiesAndClassStaticBlock(node: ClassExpression | ClassDeclaration): readonly (PropertyDeclaration | ClassStaticBlockDeclaration)[] { +export function getStaticPropertiesAndClassStaticBlock( + node: ClassExpression | ClassDeclaration, +): readonly (PropertyDeclaration | ClassStaticBlockDeclaration)[] { return filter(node.members, isStaticPropertyDeclarationOrClassStaticBlockDeclaration); } @@ -595,7 +676,9 @@ function isStaticPropertyDeclaration(member: ClassElement) { * * @internal */ -export function isInitializedProperty(member: ClassElement): member is PropertyDeclaration & { initializer: Expression; } { +export function isInitializedProperty( + member: ClassElement, +): member is PropertyDeclaration & { initializer: Expression; } { return member.kind === SyntaxKind.PropertyDeclaration && (member as PropertyDeclaration).initializer !== undefined; } @@ -607,8 +690,15 @@ export function isInitializedProperty(member: ClassElement): member is PropertyD * * @internal */ -export function isNonStaticMethodOrAccessorWithPrivateName(member: ClassElement): member is PrivateIdentifierMethodDeclaration | PrivateIdentifierAccessorDeclaration | PrivateIdentifierAutoAccessorPropertyDeclaration { - return !isStatic(member) && (isMethodOrAccessor(member) || isAutoAccessorPropertyDeclaration(member)) && isPrivateIdentifier(member.name); +export function isNonStaticMethodOrAccessorWithPrivateName( + member: ClassElement, +): member is + | PrivateIdentifierMethodDeclaration + | PrivateIdentifierAccessorDeclaration + | PrivateIdentifierAutoAccessorPropertyDeclaration +{ + return !isStatic(member) && (isMethodOrAccessor(member) || isAutoAccessorPropertyDeclaration(member)) + && isPrivateIdentifier(member.name); } /** @@ -668,7 +758,11 @@ export function getAllDecoratorsOfClass(node: ClassLikeDeclaration): AllDecorato * * @internal */ -export function getAllDecoratorsOfClassElement(member: ClassElement, parent: ClassLikeDeclaration, useLegacyDecorators: boolean): AllDecorators | undefined { +export function getAllDecoratorsOfClassElement( + member: ClassElement, + parent: ClassLikeDeclaration, + useLegacyDecorators: boolean, +): AllDecorators | undefined { switch (member.kind) { case SyntaxKind.GetAccessor: case SyntaxKind.SetAccessor: @@ -694,15 +788,21 @@ export function getAllDecoratorsOfClassElement(member: ClassElement, parent: Cla * @param parent The class node that contains the accessor. * @param accessor The class accessor member. */ -function getAllDecoratorsOfAccessors(accessor: AccessorDeclaration, parent: ClassExpression | ClassDeclaration): AllDecorators | undefined { +function getAllDecoratorsOfAccessors( + accessor: AccessorDeclaration, + parent: ClassExpression | ClassDeclaration, +): AllDecorators | undefined { if (!accessor.body) { return undefined; } - const { firstAccessor, secondAccessor, getAccessor, setAccessor } = getAllAccessorDeclarations(parent.members, accessor); - const firstAccessorWithDecorators = hasDecorators(firstAccessor) ? firstAccessor : - secondAccessor && hasDecorators(secondAccessor) ? secondAccessor : - undefined; + const { firstAccessor, secondAccessor, getAccessor, setAccessor } = getAllAccessorDeclarations( + parent.members, + accessor, + ); + const firstAccessorWithDecorators = hasDecorators(firstAccessor) ? firstAccessor + : secondAccessor && hasDecorators(secondAccessor) ? secondAccessor + : undefined; if (!firstAccessorWithDecorators || accessor !== firstAccessorWithDecorators) { return undefined; @@ -799,9 +899,9 @@ export function getPrivateIdentifier( privateEnv: PrivateEnvironment | undefined, name: PrivateIdentifier, ) { - return isGeneratedPrivateIdentifier(name) ? - privateEnv?.generatedIdentifiers?.get(getNodeForGeneratedName(name)) : - privateEnv?.identifiers?.get(name.escapedText); + return isGeneratedPrivateIdentifier(name) + ? privateEnv?.generatedIdentifiers?.get(getNodeForGeneratedName(name)) + : privateEnv?.identifiers?.get(name.escapedText); } /** @internal */ diff --git a/src/compiler/tsbuild.ts b/src/compiler/tsbuild.ts index 0e89b75351622..74f2a164bb2a4 100644 --- a/src/compiler/tsbuild.ts +++ b/src/compiler/tsbuild.ts @@ -84,7 +84,10 @@ export namespace Status { * We track what the newest input file is. */ export interface UpToDate { - type: UpToDateStatusType.UpToDate | UpToDateStatusType.UpToDateWithUpstreamTypes | UpToDateStatusType.UpToDateWithInputFileText; + type: + | UpToDateStatusType.UpToDate + | UpToDateStatusType.UpToDateWithUpstreamTypes + | UpToDateStatusType.UpToDateWithInputFileText; newestInputFileTime?: Date; newestInputFileName?: string; oldestOutputFileName: string; diff --git a/src/compiler/tsbuildPublic.ts b/src/compiler/tsbuildPublic.ts index 068f3341f849b..f3c05ca32d41c 100644 --- a/src/compiler/tsbuildPublic.ts +++ b/src/compiler/tsbuildPublic.ts @@ -191,7 +191,11 @@ enum BuildResultFlags { /** @internal */ export type ResolvedConfigFilePath = ResolvedConfigFileName & Path; -function getOrCreateValueFromConfigFileMap(configFileMap: Map, resolved: ResolvedConfigFilePath, createT: () => T): T { +function getOrCreateValueFromConfigFileMap( + configFileMap: Map, + resolved: ResolvedConfigFilePath, + createT: () => T, +): T { const existingValue = configFileMap.get(resolved); let newValue: T | undefined; if (!existingValue) { @@ -201,7 +205,10 @@ function getOrCreateValueFromConfigFileMap(configFileMap: Map(configFileMap: Map>, resolved: ResolvedConfigFilePath): Map { +function getOrCreateValueMapFromConfigFileMap( + configFileMap: Map>, + resolved: ResolvedConfigFilePath, +): Map { return getOrCreateValueFromConfigFileMap(configFileMap, resolved, () => new Map()); } @@ -276,9 +283,19 @@ export function getBuildOrderFromAnyBuildOrder(anyBuildOrder: AnyBuildOrder): Bu } export interface SolutionBuilder { - build(project?: string, cancellationToken?: CancellationToken, writeFile?: WriteFileCallback, getCustomTransformers?: (project: string) => CustomTransformers): ExitStatus; + build( + project?: string, + cancellationToken?: CancellationToken, + writeFile?: WriteFileCallback, + getCustomTransformers?: (project: string) => CustomTransformers, + ): ExitStatus; clean(project?: string): ExitStatus; - buildReferences(project: string, cancellationToken?: CancellationToken, writeFile?: WriteFileCallback, getCustomTransformers?: (project: string) => CustomTransformers): ExitStatus; + buildReferences( + project: string, + cancellationToken?: CancellationToken, + writeFile?: WriteFileCallback, + getCustomTransformers?: (project: string) => CustomTransformers, + ): ExitStatus; cleanReferences(project?: string): ExitStatus; getNextInvalidatedProject(cancellationToken?: CancellationToken): InvalidatedProject | undefined; @@ -287,7 +304,10 @@ export interface SolutionBuilder { // Testing only /** @internal */ getUpToDateStatusOfProject(project: string): UpToDateStatus; - /** @internal */ invalidateProject(configFilePath: ResolvedConfigFilePath, reloadLevel?: ConfigFileProgramReloadLevel): void; + /** @internal */ invalidateProject( + configFilePath: ResolvedConfigFilePath, + reloadLevel?: ConfigFileProgramReloadLevel, + ): void; /** @internal */ close(): void; } @@ -296,13 +316,22 @@ export interface SolutionBuilder { */ export function createBuilderStatusReporter(system: System, pretty?: boolean): DiagnosticReporter { return diagnostic => { - let output = pretty ? `[${formatColorAndReset(getLocaleTimeString(system), ForegroundColorEscapeSequences.Grey)}] ` : `${getLocaleTimeString(system)} - `; - output += `${flattenDiagnosticMessageText(diagnostic.messageText, system.newLine)}${system.newLine + system.newLine}`; + let output = pretty + ? `[${formatColorAndReset(getLocaleTimeString(system), ForegroundColorEscapeSequences.Grey)}] ` + : `${getLocaleTimeString(system)} - `; + output += `${flattenDiagnosticMessageText(diagnostic.messageText, system.newLine)}${ + system.newLine + system.newLine + }`; system.write(output); }; } -function createSolutionBuilderHostBase(system: System, createProgram: CreateProgram | undefined, reportDiagnostic?: DiagnosticReporter, reportSolutionBuilderStatus?: DiagnosticReporter) { +function createSolutionBuilderHostBase( + system: System, + createProgram: CreateProgram | undefined, + reportDiagnostic?: DiagnosticReporter, + reportSolutionBuilderStatus?: DiagnosticReporter, +) { const host = createProgramHost(system, createProgram) as SolutionBuilderHostBase; host.getModifiedTime = system.getModifiedTime ? path => system.getModifiedTime!(path) : returnUndefined; host.setModifiedTime = system.setModifiedTime ? (path, date) => system.setModifiedTime!(path, date) : noop; @@ -313,14 +342,36 @@ function createSolutionBuilderHostBase(system: System, return host; } -export function createSolutionBuilderHost(system = sys, createProgram?: CreateProgram, reportDiagnostic?: DiagnosticReporter, reportSolutionBuilderStatus?: DiagnosticReporter, reportErrorSummary?: ReportEmitErrorSummary) { - const host = createSolutionBuilderHostBase(system, createProgram, reportDiagnostic, reportSolutionBuilderStatus) as SolutionBuilderHost; +export function createSolutionBuilderHost( + system = sys, + createProgram?: CreateProgram, + reportDiagnostic?: DiagnosticReporter, + reportSolutionBuilderStatus?: DiagnosticReporter, + reportErrorSummary?: ReportEmitErrorSummary, +) { + const host = createSolutionBuilderHostBase( + system, + createProgram, + reportDiagnostic, + reportSolutionBuilderStatus, + ) as SolutionBuilderHost; host.reportErrorSummary = reportErrorSummary; return host; } -export function createSolutionBuilderWithWatchHost(system = sys, createProgram?: CreateProgram, reportDiagnostic?: DiagnosticReporter, reportSolutionBuilderStatus?: DiagnosticReporter, reportWatchStatus?: WatchStatusReporter) { - const host = createSolutionBuilderHostBase(system, createProgram, reportDiagnostic, reportSolutionBuilderStatus) as SolutionBuilderWithWatchHost; +export function createSolutionBuilderWithWatchHost( + system = sys, + createProgram?: CreateProgram, + reportDiagnostic?: DiagnosticReporter, + reportSolutionBuilderStatus?: DiagnosticReporter, + reportWatchStatus?: WatchStatusReporter, +) { + const host = createSolutionBuilderHostBase( + system, + createProgram, + reportDiagnostic, + reportSolutionBuilderStatus, + ) as SolutionBuilderWithWatchHost; const watchHost = createWatchHost(system, reportWatchStatus); copyProperties(host, watchHost); return host; @@ -334,11 +385,20 @@ function getCompilerOptionsOfBuildOptions(buildOptions: BuildOptions): CompilerO return result; } -export function createSolutionBuilder(host: SolutionBuilderHost, rootNames: readonly string[], defaultOptions: BuildOptions): SolutionBuilder { +export function createSolutionBuilder( + host: SolutionBuilderHost, + rootNames: readonly string[], + defaultOptions: BuildOptions, +): SolutionBuilder { return createSolutionBuilderWorker(/*watch*/ false, host, rootNames, defaultOptions); } -export function createSolutionBuilderWithWatch(host: SolutionBuilderWithWatchHost, rootNames: readonly string[], defaultOptions: BuildOptions, baseWatchOptions?: WatchOptions): SolutionBuilder { +export function createSolutionBuilderWithWatch( + host: SolutionBuilderWithWatchHost, + rootNames: readonly string[], + defaultOptions: BuildOptions, + baseWatchOptions?: WatchOptions, +): SolutionBuilder { return createSolutionBuilderWorker(/*watch*/ true, host, rootNames, defaultOptions, baseWatchOptions); } @@ -416,61 +476,104 @@ interface SolutionBuilderState extends WatchFactory; readonly outputTimeStamps: Map>; - readonly lastCachedPackageJsonLookups: Map; + readonly lastCachedPackageJsonLookups: Map< + ResolvedConfigFilePath, + readonly (readonly [Path, object | boolean])[] | undefined + >; timerToBuildInvalidatedProject: any; reportFileChangeDetected: boolean; writeLog: (s: string) => void; } -function createSolutionBuilderState(watch: boolean, hostOrHostWithWatch: SolutionBuilderHost | SolutionBuilderWithWatchHost, rootNames: readonly string[], options: BuildOptions, baseWatchOptions: WatchOptions | undefined): SolutionBuilderState { +function createSolutionBuilderState( + watch: boolean, + hostOrHostWithWatch: SolutionBuilderHost | SolutionBuilderWithWatchHost, + rootNames: readonly string[], + options: BuildOptions, + baseWatchOptions: WatchOptions | undefined, +): SolutionBuilderState { const host = hostOrHostWithWatch as SolutionBuilderHost; const hostWithWatch = hostOrHostWithWatch as SolutionBuilderWithWatchHost; // State of the solution const baseCompilerOptions = getCompilerOptionsOfBuildOptions(options); - const compilerHost = createCompilerHostFromProgramHost(host, () => state.projectCompilerOptions) as CompilerHost & ReadBuildProgramHost; + const compilerHost = createCompilerHostFromProgramHost(host, () => state.projectCompilerOptions) as + & CompilerHost + & ReadBuildProgramHost; setGetSourceFileAsHashVersioned(compilerHost); - compilerHost.getParsedCommandLine = fileName => parseConfigFile(state, fileName as ResolvedConfigFileName, toResolvedConfigFilePath(state, fileName as ResolvedConfigFileName)); + compilerHost.getParsedCommandLine = fileName => + parseConfigFile( + state, + fileName as ResolvedConfigFileName, + toResolvedConfigFilePath(state, fileName as ResolvedConfigFileName), + ); compilerHost.resolveModuleNameLiterals = maybeBind(host, host.resolveModuleNameLiterals); - compilerHost.resolveTypeReferenceDirectiveReferences = maybeBind(host, host.resolveTypeReferenceDirectiveReferences); + compilerHost.resolveTypeReferenceDirectiveReferences = maybeBind( + host, + host.resolveTypeReferenceDirectiveReferences, + ); compilerHost.resolveLibrary = maybeBind(host, host.resolveLibrary); compilerHost.resolveModuleNames = maybeBind(host, host.resolveModuleNames); compilerHost.resolveTypeReferenceDirectives = maybeBind(host, host.resolveTypeReferenceDirectives); compilerHost.getModuleResolutionCache = maybeBind(host, host.getModuleResolutionCache); - let moduleResolutionCache: ModuleResolutionCache | undefined, typeReferenceDirectiveResolutionCache: TypeReferenceDirectiveResolutionCache | undefined; + let moduleResolutionCache: ModuleResolutionCache | undefined, + typeReferenceDirectiveResolutionCache: TypeReferenceDirectiveResolutionCache | undefined; if (!compilerHost.resolveModuleNameLiterals && !compilerHost.resolveModuleNames) { - moduleResolutionCache = createModuleResolutionCache(compilerHost.getCurrentDirectory(), compilerHost.getCanonicalFileName); - compilerHost.resolveModuleNameLiterals = (moduleNames, containingFile, redirectedReference, options, containingSourceFile) => - loadWithModeAwareCache( - moduleNames, - containingFile, - redirectedReference, - options, - containingSourceFile, - host, - moduleResolutionCache, - createModuleResolutionLoader, - ); + moduleResolutionCache = createModuleResolutionCache( + compilerHost.getCurrentDirectory(), + compilerHost.getCanonicalFileName, + ); + compilerHost.resolveModuleNameLiterals = ( + moduleNames, + containingFile, + redirectedReference, + options, + containingSourceFile, + ) => loadWithModeAwareCache( + moduleNames, + containingFile, + redirectedReference, + options, + containingSourceFile, + host, + moduleResolutionCache, + createModuleResolutionLoader, + ); compilerHost.getModuleResolutionCache = () => moduleResolutionCache; } if (!compilerHost.resolveTypeReferenceDirectiveReferences && !compilerHost.resolveTypeReferenceDirectives) { - typeReferenceDirectiveResolutionCache = createTypeReferenceDirectiveResolutionCache(compilerHost.getCurrentDirectory(), compilerHost.getCanonicalFileName, /*options*/ undefined, moduleResolutionCache?.getPackageJsonInfoCache()); - compilerHost.resolveTypeReferenceDirectiveReferences = (typeDirectiveNames, containingFile, redirectedReference, options, containingSourceFile) => - loadWithModeAwareCache( - typeDirectiveNames, - containingFile, - redirectedReference, - options, - containingSourceFile, - host, - typeReferenceDirectiveResolutionCache, - createTypeReferenceResolutionLoader, - ); + typeReferenceDirectiveResolutionCache = createTypeReferenceDirectiveResolutionCache( + compilerHost.getCurrentDirectory(), + compilerHost.getCanonicalFileName, + /*options*/ undefined, + moduleResolutionCache?.getPackageJsonInfoCache(), + ); + compilerHost.resolveTypeReferenceDirectiveReferences = ( + typeDirectiveNames, + containingFile, + redirectedReference, + options, + containingSourceFile, + ) => loadWithModeAwareCache( + typeDirectiveNames, + containingFile, + redirectedReference, + options, + containingSourceFile, + host, + typeReferenceDirectiveResolutionCache, + createTypeReferenceResolutionLoader, + ); } let libraryResolutionCache: ModuleResolutionCache | undefined; if (!compilerHost.resolveLibrary) { - libraryResolutionCache = createModuleResolutionCache(compilerHost.getCurrentDirectory(), compilerHost.getCanonicalFileName, /*options*/ undefined, moduleResolutionCache?.getPackageJsonInfoCache()); + libraryResolutionCache = createModuleResolutionCache( + compilerHost.getCurrentDirectory(), + compilerHost.getCanonicalFileName, + /*options*/ undefined, + moduleResolutionCache?.getPackageJsonInfoCache(), + ); compilerHost.resolveLibrary = (libraryName, resolveFrom, options) => resolveLibrary( libraryName, @@ -480,7 +583,13 @@ function createSolutionBuilderState(watch: boolean, ho libraryResolutionCache, ); } - compilerHost.getBuildInfo = (fileName, configFilePath) => getBuildInfo(state, fileName, toResolvedConfigFilePath(state, configFilePath as ResolvedConfigFileName), /*modifiedTime*/ undefined); + compilerHost.getBuildInfo = (fileName, configFilePath) => + getBuildInfo( + state, + fileName, + toResolvedConfigFilePath(state, configFilePath as ResolvedConfigFileName), + /*modifiedTime*/ undefined, + ); const { watchFile, watchDirectory, writeLog } = createWatchFactory(hostWithWatch, options); @@ -547,7 +656,10 @@ function toPath(state: SolutionBuilderState, fileNa return ts_toPath(fileName, state.compilerHost.getCurrentDirectory(), state.compilerHost.getCanonicalFileName); } -function toResolvedConfigFilePath(state: SolutionBuilderState, fileName: ResolvedConfigFileName): ResolvedConfigFilePath { +function toResolvedConfigFilePath( + state: SolutionBuilderState, + fileName: ResolvedConfigFileName, +): ResolvedConfigFilePath { const { resolvedConfigFilePaths } = state; const path = resolvedConfigFilePaths.get(fileName); if (path !== undefined) return path; @@ -561,12 +673,19 @@ function isParsedCommandLine(entry: ConfigFileCacheEntry): entry is ParsedComman return !!(entry as ParsedCommandLine).options; } -function getCachedParsedConfigFile(state: SolutionBuilderState, configFilePath: ResolvedConfigFilePath): ParsedCommandLine | undefined { +function getCachedParsedConfigFile( + state: SolutionBuilderState, + configFilePath: ResolvedConfigFilePath, +): ParsedCommandLine | undefined { const value = state.configFileCache.get(configFilePath); return value && isParsedCommandLine(value) ? value : undefined; } -function parseConfigFile(state: SolutionBuilderState, configFileName: ResolvedConfigFileName, configFilePath: ResolvedConfigFilePath): ParsedCommandLine | undefined { +function parseConfigFile( + state: SolutionBuilderState, + configFileName: ResolvedConfigFileName, + configFilePath: ResolvedConfigFilePath, +): ParsedCommandLine | undefined { const { configFileCache } = state; const value = configFileCache.get(configFilePath); if (value) { @@ -583,20 +702,36 @@ function parseConfigFile(state: SolutionBuilderState diagnostic = d; - parsed = getParsedCommandLineOfConfigFile(configFileName, baseCompilerOptions, parseConfigFileHost, extendedConfigCache, baseWatchOptions); + parsed = getParsedCommandLineOfConfigFile( + configFileName, + baseCompilerOptions, + parseConfigFileHost, + extendedConfigCache, + baseWatchOptions, + ); parseConfigFileHost.onUnRecoverableConfigFileDiagnostic = noop; } configFileCache.set(configFilePath, parsed || diagnostic!); performance.mark("SolutionBuilder::afterConfigFileParsing"); - performance.measure("SolutionBuilder::Config file parsing", "SolutionBuilder::beforeConfigFileParsing", "SolutionBuilder::afterConfigFileParsing"); + performance.measure( + "SolutionBuilder::Config file parsing", + "SolutionBuilder::beforeConfigFileParsing", + "SolutionBuilder::afterConfigFileParsing", + ); return parsed; } -function resolveProjectName(state: SolutionBuilderState, name: string): ResolvedConfigFileName { +function resolveProjectName( + state: SolutionBuilderState, + name: string, +): ResolvedConfigFileName { return resolveConfigFileProjectName(resolvePath(state.compilerHost.getCurrentDirectory(), name)); } -function createBuildOrder(state: SolutionBuilderState, roots: readonly ResolvedConfigFileName[]): AnyBuildOrder { +function createBuildOrder( + state: SolutionBuilderState, + roots: readonly ResolvedConfigFileName[], +): AnyBuildOrder { const temporaryMarks = new Map(); const permanentMarks = new Map(); const circularityReportStack: string[] = []; @@ -606,9 +741,9 @@ function createBuildOrder(state: SolutionBuilderState< visit(root); } - return circularDiagnostics ? - { buildOrder: buildOrder || emptyArray, circularDiagnostics } : - buildOrder || emptyArray; + return circularDiagnostics + ? { buildOrder: buildOrder || emptyArray, circularDiagnostics } + : buildOrder || emptyArray; function visit(configFileName: ResolvedConfigFileName, inCircularContext?: boolean) { const projPath = toResolvedConfigFilePath(state, configFileName); @@ -709,7 +844,11 @@ function createStateBuildOrder(state: SolutionBuilderS return state.buildOrder = buildOrder; } -function getBuildOrderFor(state: SolutionBuilderState, project: string | undefined, onlyReferences: boolean | undefined): AnyBuildOrder | undefined { +function getBuildOrderFor( + state: SolutionBuilderState, + project: string | undefined, + onlyReferences: boolean | undefined, +): AnyBuildOrder | undefined { const resolvedProject = project && resolveProjectName(state, project); const buildOrderFromState = getBuildOrder(state); if (isCircularBuildOrder(buildOrderFromState)) return buildOrderFromState; @@ -768,7 +907,15 @@ function enableCache(state: SolutionBuilderState) { function disableCache(state: SolutionBuilderState) { if (!state.cache) return; - const { cache, host, compilerHost, extendedConfigCache, moduleResolutionCache, typeReferenceDirectiveResolutionCache, libraryResolutionCache } = state; + const { + cache, + host, + compilerHost, + extendedConfigCache, + moduleResolutionCache, + typeReferenceDirectiveResolutionCache, + libraryResolutionCache, + } = state; host.readFile = cache.originalReadFile; host.fileExists = cache.originalFileExists; @@ -784,12 +931,19 @@ function disableCache(state: SolutionBuilderState) state.cache = undefined; } -function clearProjectStatus(state: SolutionBuilderState, resolved: ResolvedConfigFilePath) { +function clearProjectStatus( + state: SolutionBuilderState, + resolved: ResolvedConfigFilePath, +) { state.projectStatus.delete(resolved); state.diagnostics.delete(resolved); } -function addProjToQueue({ projectPendingBuild }: SolutionBuilderState, proj: ResolvedConfigFilePath, reloadLevel: ConfigFileProgramReloadLevel) { +function addProjToQueue( + { projectPendingBuild }: SolutionBuilderState, + proj: ResolvedConfigFilePath, + reloadLevel: ConfigFileProgramReloadLevel, +) { const value = projectPendingBuild.get(proj); if (value === undefined) { projectPendingBuild.set(proj, reloadLevel); @@ -799,7 +953,10 @@ function addProjToQueue({ projectPendingBuild }: Solut } } -function setupInitialBuild(state: SolutionBuilderState, cancellationToken: CancellationToken | undefined) { +function setupInitialBuild( + state: SolutionBuilderState, + cancellationToken: CancellationToken | undefined, +) { // Set initial build if not already built if (!state.allProjectBuildPending) return; state.allProjectBuildPending = false; @@ -832,7 +989,11 @@ export interface InvalidatedProjectBase { /** * To dispose this project and ensure that all the necessary actions are taken and state is updated accordingly */ - done(cancellationToken?: CancellationToken, writeFile?: WriteFileCallback, customTransformers?: CustomTransformers): ExitStatus; + done( + cancellationToken?: CancellationToken, + writeFile?: WriteFileCallback, + customTransformers?: CustomTransformers, + ): ExitStatus; getCompilerOptions(): CompilerOptions; getCurrentDirectory(): string; } @@ -858,7 +1019,10 @@ export interface BuildInvalidedProject extends Invalid getSyntacticDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): readonly Diagnostic[]; getAllDependencies(sourceFile: SourceFile): readonly string[]; getSemanticDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): readonly Diagnostic[]; - getSemanticDiagnosticsOfNextAffectedFile(cancellationToken?: CancellationToken, ignoreSourceFile?: (sourceFile: SourceFile) => boolean): AffectedFileResult; + getSemanticDiagnosticsOfNextAffectedFile( + cancellationToken?: CancellationToken, + ignoreSourceFile?: (sourceFile: SourceFile) => boolean, + ): AffectedFileResult; /* * Calling emit directly with targetSourceFile and emitOnlyDtsFiles set to true is not advised since * emit in build system is responsible in updating status of the project @@ -867,7 +1031,13 @@ export interface BuildInvalidedProject extends Invalid * (if that emit of that source file is required it would be emitted again when making sure invalidated project is completed) * This emit is not considered actual emit (and hence uptodate status is not reflected if */ - emit(targetSourceFile?: SourceFile, writeFile?: WriteFileCallback, cancellationToken?: CancellationToken, emitOnlyDtsFiles?: boolean, customTransformers?: CustomTransformers): EmitResult | undefined; + emit( + targetSourceFile?: SourceFile, + writeFile?: WriteFileCallback, + cancellationToken?: CancellationToken, + emitOnlyDtsFiles?: boolean, + customTransformers?: CustomTransformers, + ): EmitResult | undefined; // TODO(shkamat):: investigate later if we can emit even when there are declaration diagnostics // emitNextAffectedFile(writeFile?: WriteFileCallback, cancellationToken?: CancellationToken, customTransformers?: CustomTransformers): AffectedFileResult; } @@ -875,19 +1045,25 @@ export interface BuildInvalidedProject extends Invalid /** @deprecated */ export interface UpdateBundleProject extends InvalidatedProjectBase { readonly kind: InvalidatedProjectKind.UpdateBundle; - emit(writeFile?: WriteFileCallback, customTransformers?: CustomTransformers): EmitResult | BuildInvalidedProject | undefined; + emit( + writeFile?: WriteFileCallback, + customTransformers?: CustomTransformers, + ): EmitResult | BuildInvalidedProject | undefined; } -export type InvalidatedProject = UpdateOutputFileStampsProject | BuildInvalidedProject | UpdateBundleProject; +export type InvalidatedProject = + | UpdateOutputFileStampsProject + | BuildInvalidedProject + | UpdateBundleProject; function doneInvalidatedProject( state: SolutionBuilderState, projectPath: ResolvedConfigFilePath, ) { state.projectPendingBuild.delete(projectPath); - return state.diagnostics.has(projectPath) ? - ExitStatus.DiagnosticsPresent_OutputsSkipped : - ExitStatus.Success; + return state.diagnostics.has(projectPath) + ? ExitStatus.DiagnosticsPresent_OutputsSkipped + : ExitStatus.Success; } function createUpdateOutputFileStampsProject( @@ -945,8 +1121,8 @@ function createBuildOrUpdateInvalidedProject( let buildResult: BuildResultFlags | undefined; let invalidatedProjectOfBundle: BuildInvalidedProject | undefined; - return kind === InvalidatedProjectKind.Build ? - { + return kind === InvalidatedProjectKind.Build + ? { kind, project, projectPath, @@ -993,13 +1169,21 @@ function createBuildOrUpdateInvalidedProject( getSemanticDiagnosticsOfNextAffectedFile: (cancellationToken, ignoreSourceFile) => withProgramOrUndefined( program => - ((program as any as SemanticDiagnosticsBuilderProgram).getSemanticDiagnosticsOfNextAffectedFile) && - (program as any as SemanticDiagnosticsBuilderProgram).getSemanticDiagnosticsOfNextAffectedFile(cancellationToken, ignoreSourceFile), + ((program as any as SemanticDiagnosticsBuilderProgram).getSemanticDiagnosticsOfNextAffectedFile) + && (program as any as SemanticDiagnosticsBuilderProgram) + .getSemanticDiagnosticsOfNextAffectedFile(cancellationToken, ignoreSourceFile), ), emit: (targetSourceFile, writeFile, cancellationToken, emitOnlyDtsFiles, customTransformers) => { if (targetSourceFile || emitOnlyDtsFiles) { return withProgramOrUndefined( - program => program.emit(targetSourceFile, writeFile, cancellationToken, emitOnlyDtsFiles, customTransformers || state.host.getCustomTransformers?.(project)), + program => + program.emit( + targetSourceFile, + writeFile, + cancellationToken, + emitOnlyDtsFiles, + customTransformers || state.host.getCustomTransformers?.(project), + ), ); } executeSteps(BuildStep.SemanticDiagnostics, cancellationToken); @@ -1010,8 +1194,8 @@ function createBuildOrUpdateInvalidedProject( return emit(writeFile, cancellationToken, customTransformers); }, done, - } : - { + } + : { kind, project, projectPath, @@ -1025,7 +1209,11 @@ function createBuildOrUpdateInvalidedProject( done, }; - function done(cancellationToken?: CancellationToken, writeFile?: WriteFileCallback, customTransformers?: CustomTransformers) { + function done( + cancellationToken?: CancellationToken, + writeFile?: WriteFileCallback, + customTransformers?: CustomTransformers, + ) { executeSteps(BuildStep.Done, cancellationToken, writeFile, customTransformers); if (kind === InvalidatedProjectKind.Build) performance.mark("SolutionBuilder::Projects built"); else performance.mark("SolutionBuilder::Bundles updated"); @@ -1081,7 +1269,12 @@ function createBuildOrUpdateInvalidedProject( projectPath, state.moduleResolutionCache && map( state.moduleResolutionCache.getPackageJsonInfoCache().entries(), - ([path, data]) => ([state.host.realpath && data ? toPath(state, state.host.realpath(path)) : path, data] as const), + ( + [path, data], + ) => ([ + state.host.realpath && data ? toPath(state, state.host.realpath(path)) : path, + data, + ] as const), ), ); @@ -1129,7 +1322,11 @@ function createBuildOrUpdateInvalidedProject( ); } - function emit(writeFileCallback?: WriteFileCallback, cancellationToken?: CancellationToken, customTransformers?: CustomTransformers): EmitResult { + function emit( + writeFileCallback?: WriteFileCallback, + cancellationToken?: CancellationToken, + customTransformers?: CustomTransformers, + ): EmitResult { Debug.assertIsDefined(program); Debug.assert(step === BuildStep.Emit); // Before emitting lets backup state, so we can revert it back if there are declaration errors to handle emit and declaration errors correctly @@ -1142,7 +1339,8 @@ function createBuildOrUpdateInvalidedProject( reportDeclarationDiagnostics, /*write*/ undefined, /*reportSummary*/ undefined, - (name, text, writeByteOrderMark, _onError, _sourceFiles, data) => outputFiles.push({ name, text, writeByteOrderMark, data }), + (name, text, writeByteOrderMark, _onError, _sourceFiles, data) => + outputFiles.push({ name, text, writeByteOrderMark, data }), cancellationToken, /*emitOnlyDtsFiles*/ false, customTransformers || state.host.getCustomTransformers?.(project), @@ -1167,7 +1365,8 @@ function createBuildOrUpdateInvalidedProject( // Actual Emit const { host, compilerHost } = state; - const resultFlags = program.hasChangedEmitSignature?.() ? BuildResultFlags.None : BuildResultFlags.DeclarationOutputUnchanged; + const resultFlags = program.hasChangedEmitSignature?.() ? BuildResultFlags.None + : BuildResultFlags.DeclarationOutputUnchanged; const emitterDiagnostics = createDiagnosticCollection(); const emittedOutputs = new Map(); const options = program.getCompilerOptions(); @@ -1179,11 +1378,20 @@ function createBuildOrUpdateInvalidedProject( emittedOutputs.set(toPath(state, name), name); if (data?.buildInfo) setBuildInfo(state, data.buildInfo, projectPath, options, resultFlags); const modifiedTime = data?.differsOnlyInMap ? ts_getModifiedTime(state.host, name) : undefined; - writeFile(writeFileCallback ? { writeFile: writeFileCallback } : compilerHost, emitterDiagnostics, name, text, writeByteOrderMark); + writeFile( + writeFileCallback ? { writeFile: writeFileCallback } : compilerHost, + emitterDiagnostics, + name, + text, + writeByteOrderMark, + ); // Revert the timestamp for the d.ts that is same if (data?.differsOnlyInMap) state.host.setModifiedTime(name, modifiedTime!); else if (!isIncremental && state.watch) { - (outputTimeStampMap ||= getOutputTimeStampMap(state, projectPath)!).set(path, now ||= getCurrentTime(state.host)); + (outputTimeStampMap ||= getOutputTimeStampMap(state, projectPath)!).set( + path, + now ||= getCurrentTime(state.host), + ); } }); @@ -1200,7 +1408,15 @@ function createBuildOrUpdateInvalidedProject( Debug.assertIsDefined(program); Debug.assert(step === BuildStep.EmitBuildInfo); const emitResult = program.emitBuildInfo((name, text, writeByteOrderMark, onError, sourceFiles, data) => { - if (data?.buildInfo) setBuildInfo(state, data.buildInfo, projectPath, program!.getCompilerOptions(), BuildResultFlags.DeclarationOutputUnchanged); + if (data?.buildInfo) { + setBuildInfo( + state, + data.buildInfo, + projectPath, + program!.getCompilerOptions(), + BuildResultFlags.DeclarationOutputUnchanged, + ); + } if (writeFileCallback) writeFileCallback(name, text, writeByteOrderMark, onError, sourceFiles, data); else state.compilerHost.writeFile(name, text, writeByteOrderMark, onError, sourceFiles, data); }, cancellationToken); @@ -1243,7 +1459,13 @@ function createBuildOrUpdateInvalidedProject( } // Update time stamps for rest of the outputs - updateOutputTimestampsWorker(state, config, projectPath, Diagnostics.Updating_unchanged_output_timestamps_of_project_0, emittedOutputs); + updateOutputTimestampsWorker( + state, + config, + projectPath, + Diagnostics.Updating_unchanged_output_timestamps_of_project_0, + emittedOutputs, + ); state.diagnostics.delete(projectPath); state.projectStatus.set(projectPath, { type: UpToDateStatusType.UpToDate, @@ -1255,7 +1477,10 @@ function createBuildOrUpdateInvalidedProject( return emitDiagnostics; } - function emitBundle(writeFileCallback?: WriteFileCallback, customTransformers?: CustomTransformers): EmitResult | BuildInvalidedProject | undefined { + function emitBundle( + writeFileCallback?: WriteFileCallback, + customTransformers?: CustomTransformers, + ): EmitResult | BuildInvalidedProject | undefined { Debug.assert(kind === InvalidatedProjectKind.UpdateBundle); if (state.options.dry) { reportStatus(state, Diagnostics.A_non_dry_build_would_update_output_of_project_0, project); @@ -1281,7 +1506,12 @@ function createBuildOrUpdateInvalidedProject( ); if (isString(outputFiles)) { - reportStatus(state, Diagnostics.Cannot_update_output_of_project_0_because_there_was_error_reading_file_1, project, relName(state, outputFiles)); + reportStatus( + state, + Diagnostics.Cannot_update_output_of_project_0_because_there_was_error_reading_file_1, + project, + relName(state, outputFiles), + ); step = BuildStep.BuildInvalidatedProjectOfBundle; return invalidatedProjectOfBundle = createBuildOrUpdateInvalidedProject( InvalidatedProjectKind.Build, @@ -1303,12 +1533,21 @@ function createBuildOrUpdateInvalidedProject( outputFiles.forEach(({ name, text, writeByteOrderMark, data }) => { emittedOutputs.set(toPath(state, name), name); if (data?.buildInfo) { - if ((data.buildInfo.program as ProgramBundleEmitBuildInfo)?.outSignature !== (existingBuildInfo?.program as ProgramBundleEmitBuildInfo)?.outSignature) { + if ( + (data.buildInfo.program as ProgramBundleEmitBuildInfo)?.outSignature + !== (existingBuildInfo?.program as ProgramBundleEmitBuildInfo)?.outSignature + ) { resultFlags &= ~BuildResultFlags.DeclarationOutputUnchanged; } setBuildInfo(state, data.buildInfo, projectPath, config.options, resultFlags); } - writeFile(writeFileCallback ? { writeFile: writeFileCallback } : compilerHost, emitterDiagnostics, name, text, writeByteOrderMark); + writeFile( + writeFileCallback ? { writeFile: writeFileCallback } : compilerHost, + emitterDiagnostics, + name, + text, + writeByteOrderMark, + ); }); const emitDiagnostics = finishEmit( @@ -1320,7 +1559,12 @@ function createBuildOrUpdateInvalidedProject( return { emitSkipped: false, diagnostics: emitDiagnostics }; } - function executeSteps(till: BuildStep, cancellationToken?: CancellationToken, writeFile?: WriteFileCallback, customTransformers?: CustomTransformers) { + function executeSteps( + till: BuildStep, + cancellationToken?: CancellationToken, + writeFile?: WriteFileCallback, + customTransformers?: CustomTransformers, + ) { while (step <= till && step < BuildStep.Done) { const currentStep = step; switch (step) { @@ -1349,12 +1593,24 @@ function createBuildOrUpdateInvalidedProject( break; case BuildStep.BuildInvalidatedProjectOfBundle: - Debug.checkDefined(invalidatedProjectOfBundle).done(cancellationToken, writeFile, customTransformers); + Debug.checkDefined(invalidatedProjectOfBundle).done( + cancellationToken, + writeFile, + customTransformers, + ); step = BuildStep.Done; break; case BuildStep.QueueReferencingProjects: - queueReferencingProjects(state, project, projectPath, projectIndex, config, buildOrder, Debug.checkDefined(buildResult)); + queueReferencingProjects( + state, + project, + projectPath, + projectIndex, + config, + buildOrder, + Debug.checkDefined(buildResult), + ); step++; break; @@ -1368,11 +1624,15 @@ function createBuildOrUpdateInvalidedProject( } } -function needsBuild({ options }: SolutionBuilderState, status: UpToDateStatus, config: ParsedCommandLine) { +function needsBuild( + { options }: SolutionBuilderState, + status: UpToDateStatus, + config: ParsedCommandLine, +) { if (status.type !== UpToDateStatusType.OutOfDateWithPrepend || options.force) return true; - return config.fileNames.length === 0 || - !!getConfigFileParsingDiagnostics(config).length || - !isIncrementalCompilation(config.options); + return config.fileNames.length === 0 + || !!getConfigFileParsingDiagnostics(config).length + || !isIncrementalCompilation(config.options); } interface InvalidateProjectCreateInfo { @@ -1420,8 +1680,19 @@ function getNextInvalidatedProjectCreateInfo( } else if (reloadLevel === ConfigFileProgramReloadLevel.Partial) { // Update file names - config.fileNames = getFileNamesFromConfigSpecs(config.options.configFile!.configFileSpecs!, getDirectoryPath(project), config.options, state.parseConfigFileHost); - updateErrorForNoInputFiles(config.fileNames, project, config.options.configFile!.configFileSpecs!, config.errors, canJsonReportNoInputFiles(config.raw)); + config.fileNames = getFileNamesFromConfigSpecs( + config.options.configFile!.configFileSpecs!, + getDirectoryPath(project), + config.options, + state.parseConfigFileHost, + ); + updateErrorForNoInputFiles( + config.fileNames, + project, + config.options.configFile!.configFileSpecs!, + config.errors, + canJsonReportNoInputFiles(config.raw), + ); watchInputFiles(state, project, projectPath, config); watchPackageJsonFiles(state, project, projectPath, config); } @@ -1440,7 +1711,10 @@ function getNextInvalidatedProjectCreateInfo( continue; } - if (status.type === UpToDateStatusType.UpToDateWithUpstreamTypes || status.type === UpToDateStatusType.UpToDateWithInputFileText) { + if ( + status.type === UpToDateStatusType.UpToDateWithUpstreamTypes + || status.type === UpToDateStatusType.UpToDateWithInputFileText + ) { reportAndStoreErrors(state, projectPath, getConfigFileParsingDiagnostics(config)); return { kind: InvalidatedProjectKind.UpdateOutputFileStamps, @@ -1460,9 +1734,9 @@ function getNextInvalidatedProjectCreateInfo( if (options.verbose) { reportStatus( state, - status.upstreamProjectBlocked ? - Diagnostics.Skipping_build_of_project_0_because_its_dependency_1_was_not_built : - Diagnostics.Skipping_build_of_project_0_because_its_dependency_1_has_errors, + status.upstreamProjectBlocked + ? Diagnostics.Skipping_build_of_project_0_because_its_dependency_1_was_not_built + : Diagnostics.Skipping_build_of_project_0_because_its_dependency_1_has_errors, project, status.upstreamProjectName, ); @@ -1479,9 +1753,9 @@ function getNextInvalidatedProjectCreateInfo( } return { - kind: needsBuild(state, status, config) ? - InvalidatedProjectKind.Build : - InvalidatedProjectKind.UpdateBundle, + kind: needsBuild(state, status, config) + ? InvalidatedProjectKind.Build + : InvalidatedProjectKind.UpdateBundle, status, project, projectPath, @@ -1499,8 +1773,8 @@ function createInvalidatedProjectWithInfo( buildOrder: AnyBuildOrder, ) { verboseReportProjectStatus(state, info.project, info.status); - return info.kind !== InvalidatedProjectKind.UpdateOutputFileStamps ? - createBuildOrUpdateInvalidedProject( + return info.kind !== InvalidatedProjectKind.UpdateOutputFileStamps + ? createBuildOrUpdateInvalidedProject( info.kind, state, info.project, @@ -1508,8 +1782,8 @@ function createInvalidatedProjectWithInfo( info.projectIndex, info.config, buildOrder as BuildOrder, - ) : - createUpdateOutputFileStampsProject( + ) + : createUpdateOutputFileStampsProject( state, info.project, info.projectPath, @@ -1528,13 +1802,21 @@ function getNextInvalidatedProject( return createInvalidatedProjectWithInfo(state, info, buildOrder); } -function listEmittedFile({ write }: SolutionBuilderState, proj: ParsedCommandLine, file: string) { +function listEmittedFile( + { write }: SolutionBuilderState, + proj: ParsedCommandLine, + file: string, +) { if (write && proj.options.listEmittedFiles) { write(`TSFILE: ${file}`); } } -function getOldProgram({ options, builderPrograms, compilerHost }: SolutionBuilderState, proj: ResolvedConfigFilePath, parsed: ParsedCommandLine) { +function getOldProgram( + { options, builderPrograms, compilerHost }: SolutionBuilderState, + proj: ResolvedConfigFilePath, + parsed: ParsedCommandLine, +) { if (options.force) return undefined; const value = builderPrograms.get(proj); if (value) return value; @@ -1578,7 +1860,9 @@ function buildErrors( return { buildResult, step: BuildStep.QueueReferencingProjects }; } -function isFileWatcherWithModifiedTime(value: FileWatcherWithModifiedTime | Date): value is FileWatcherWithModifiedTime { +function isFileWatcherWithModifiedTime( + value: FileWatcherWithModifiedTime | Date, +): value is FileWatcherWithModifiedTime { return !!(value as FileWatcherWithModifiedTime).watcher; } @@ -1600,7 +1884,15 @@ function getModifiedTime(state: SolutionBuilderState(state: SolutionBuilderState, file: string, callback: FileWatcherCallback, pollingInterval: PollingInterval, options: WatchOptions | undefined, watchType: WatchType, project?: ResolvedConfigFileName): FileWatcher { +function watchFile( + state: SolutionBuilderState, + file: string, + callback: FileWatcherCallback, + pollingInterval: PollingInterval, + options: WatchOptions | undefined, + watchType: WatchType, + project?: ResolvedConfigFileName, +): FileWatcher { const path = toPath(state, file); const existing = state.filesWatched.get(path); if (existing && isFileWatcherWithModifiedTime(existing)) { @@ -1638,7 +1930,10 @@ function watchFile(state: SolutionBuilderState, fil }; } -function getOutputTimeStampMap(state: SolutionBuilderState, resolvedConfigFilePath: ResolvedConfigFilePath) { +function getOutputTimeStampMap( + state: SolutionBuilderState, + resolvedConfigFilePath: ResolvedConfigFilePath, +) { // Output timestamps are stored only in watch mode if (!state.watch) return undefined; let result = state.outputTimeStamps.get(resolvedConfigFilePath); @@ -1671,13 +1966,22 @@ function setBuildInfo( } } -function getBuildInfoCacheEntry(state: SolutionBuilderState, buildInfoPath: string, resolvedConfigPath: ResolvedConfigFilePath) { +function getBuildInfoCacheEntry( + state: SolutionBuilderState, + buildInfoPath: string, + resolvedConfigPath: ResolvedConfigFilePath, +) { const path = toPath(state, buildInfoPath); const existing = state.buildInfoCache.get(resolvedConfigPath); return existing?.path === path ? existing : undefined; } -function getBuildInfo(state: SolutionBuilderState, buildInfoPath: string, resolvedConfigPath: ResolvedConfigFilePath, modifiedTime: Date | undefined): BuildInfo | undefined { +function getBuildInfo( + state: SolutionBuilderState, + buildInfoPath: string, + resolvedConfigPath: ResolvedConfigFilePath, + modifiedTime: Date | undefined, +): BuildInfo | undefined { const path = toPath(state, buildInfoPath); const existing = state.buildInfoCache.get(resolvedConfigPath); if (existing !== undefined && existing.path === path) { @@ -1685,11 +1989,20 @@ function getBuildInfo(state: SolutionBuilderState, } const value = state.readFileWithCache(buildInfoPath); const buildInfo = value ? ts_getBuildInfo(buildInfoPath, value) : undefined; - state.buildInfoCache.set(resolvedConfigPath, { path, buildInfo: buildInfo || false, modifiedTime: modifiedTime || missingFileModifiedTime }); + state.buildInfoCache.set(resolvedConfigPath, { + path, + buildInfo: buildInfo || false, + modifiedTime: modifiedTime || missingFileModifiedTime, + }); return buildInfo; } -function checkConfigFileUpToDateStatus(state: SolutionBuilderState, configFile: string, oldestOutputFileTime: Date, oldestOutputFileName: string): Status.OutOfDateWithSelf | undefined { +function checkConfigFileUpToDateStatus( + state: SolutionBuilderState, + configFile: string, + oldestOutputFileTime: Date, + oldestOutputFileName: string, +): Status.OutOfDateWithSelf | undefined { // Check tsconfig time const tsconfigTime = getModifiedTime(state, configFile); if (oldestOutputFileTime < tsconfigTime) { @@ -1701,7 +2014,11 @@ function checkConfigFileUpToDateStatus(state: Solution } } -function getUpToDateStatusWorker(state: SolutionBuilderState, project: ParsedCommandLine, resolvedPath: ResolvedConfigFilePath): UpToDateStatus { +function getUpToDateStatusWorker( + state: SolutionBuilderState, + project: ParsedCommandLine, + resolvedPath: ResolvedConfigFilePath, +): UpToDateStatus { // Container if no files are specified in the project if (!project.fileNames.length && !canJsonReportNoInputFiles(project.raw)) { return { @@ -1722,16 +2039,16 @@ function getUpToDateStatusWorker(state: SolutionBuilde // Its a circular reference ignore the status of this project if ( - refStatus.type === UpToDateStatusType.ComputingUpstream || - refStatus.type === UpToDateStatusType.ContainerOnly + refStatus.type === UpToDateStatusType.ComputingUpstream + || refStatus.type === UpToDateStatusType.ContainerOnly ) { // Container only ignore this project continue; } // An upstream project is blocked if ( - refStatus.type === UpToDateStatusType.Unbuildable || - refStatus.type === UpToDateStatusType.UpstreamBlocked + refStatus.type === UpToDateStatusType.Unbuildable + || refStatus.type === UpToDateStatusType.UpstreamBlocked ) { return { type: UpToDateStatusType.UpstreamBlocked, @@ -1801,10 +2118,10 @@ function getUpToDateStatusWorker(state: SolutionBuilde // But if noEmit is true, affectedFilesPendingEmit will have file list even if there are no semantic errors to preserve list of files to be emitted when running with noEmit false // So with noEmit set to true, check on semantic diagnostics needs to be explicit as oppose to when it is false when only files pending emit is sufficient if ( - (buildInfo.program as ProgramMultiFileEmitBuildInfo).changeFileSet?.length || - (!project.options.noEmit ? - (buildInfo.program as ProgramMultiFileEmitBuildInfo).affectedFilesPendingEmit?.length : - some((buildInfo.program as ProgramMultiFileEmitBuildInfo).semanticDiagnosticsPerFile, isArray)) + (buildInfo.program as ProgramMultiFileEmitBuildInfo).changeFileSet?.length + || (!project.options.noEmit + ? (buildInfo.program as ProgramMultiFileEmitBuildInfo).affectedFilesPendingEmit?.length + : some((buildInfo.program as ProgramMultiFileEmitBuildInfo).semanticDiagnosticsPerFile, isArray)) ) { return { type: UpToDateStatusType.OutOfDateBuildInfo, @@ -1847,7 +2164,9 @@ function getUpToDateStatusWorker(state: SolutionBuilde let currentVersion: string | undefined; if (buildInfoProgram) { // Read files and see if they are same, read is anyways cached - if (!buildInfoVersionMap) buildInfoVersionMap = getBuildInfoFileVersionMap(buildInfoProgram, buildInfoPath!, host); + if (!buildInfoVersionMap) { + buildInfoVersionMap = getBuildInfoFileVersionMap(buildInfoProgram, buildInfoPath!, host); + } version = buildInfoVersionMap.fileInfos.get(toPath(state, inputFile)); const text = version ? state.readFileWithCache(inputFile) : undefined; currentVersion = text !== undefined ? getSourceFileVersionAsHashFromText(host, text) : undefined; @@ -1872,7 +2191,9 @@ function getUpToDateStatusWorker(state: SolutionBuilde } if (buildInfoProgram) { - if (!buildInfoVersionMap) buildInfoVersionMap = getBuildInfoFileVersionMap(buildInfoProgram, buildInfoPath!, host); + if (!buildInfoVersionMap) { + buildInfoVersionMap = getBuildInfoFileVersionMap(buildInfoProgram, buildInfoPath!, host); + } for (const existingRoot of buildInfoVersionMap.roots) { if (!seenRoots.has(existingRoot)) { // File was root file when project was built but its not any more @@ -1950,8 +2271,15 @@ function getUpToDateStatusWorker(state: SolutionBuilde // If the upstream project has only change .d.ts files, and we've built // *after* those files, then we're "psuedo up to date" and eligible for a fast rebuild - const newestDeclarationFileContentChangedTime = getLatestChangedDtsTime(state, resolvedConfig.options, resolvedRefPath); - if (newestDeclarationFileContentChangedTime && newestDeclarationFileContentChangedTime <= oldestOutputFileTime) { + const newestDeclarationFileContentChangedTime = getLatestChangedDtsTime( + state, + resolvedConfig.options, + resolvedRefPath, + ); + if ( + newestDeclarationFileContentChangedTime + && newestDeclarationFileContentChangedTime <= oldestOutputFileTime + ) { pseudoUpToDate = true; upstreamChangedProject = ref.path; continue; @@ -1968,11 +2296,19 @@ function getUpToDateStatusWorker(state: SolutionBuilde } // Check tsconfig time - const configStatus = checkConfigFileUpToDateStatus(state, project.options.configFilePath!, oldestOutputFileTime, oldestOutputFileName!); + const configStatus = checkConfigFileUpToDateStatus( + state, + project.options.configFilePath!, + oldestOutputFileTime, + oldestOutputFileName!, + ); if (configStatus) return configStatus; // Check extended config time - const extendedConfigStatus = forEach(project.options.configFile!.extendedSourceFiles || emptyArray, configFile => checkConfigFileUpToDateStatus(state, configFile, oldestOutputFileTime, oldestOutputFileName!)); + const extendedConfigStatus = forEach( + project.options.configFile!.extendedSourceFiles || emptyArray, + configFile => checkConfigFileUpToDateStatus(state, configFile, oldestOutputFileTime, oldestOutputFileName!), + ); if (extendedConfigStatus) return extendedConfigStatus; // Check package file time @@ -1992,23 +2328,31 @@ function getUpToDateStatusWorker(state: SolutionBuilde // Up to date return { - type: pseudoUpToDate ? - UpToDateStatusType.UpToDateWithUpstreamTypes : - pseudoInputUpToDate ? - UpToDateStatusType.UpToDateWithInputFileText : - UpToDateStatusType.UpToDate, + type: pseudoUpToDate + ? UpToDateStatusType.UpToDateWithUpstreamTypes + : pseudoInputUpToDate + ? UpToDateStatusType.UpToDateWithInputFileText + : UpToDateStatusType.UpToDate, newestInputFileTime, newestInputFileName, oldestOutputFileName: oldestOutputFileName!, }; } -function hasSameBuildInfo(state: SolutionBuilderState, buildInfoCacheEntry: BuildInfoCacheEntry, resolvedRefPath: ResolvedConfigFilePath) { +function hasSameBuildInfo( + state: SolutionBuilderState, + buildInfoCacheEntry: BuildInfoCacheEntry, + resolvedRefPath: ResolvedConfigFilePath, +) { const refBuildInfo = state.buildInfoCache.get(resolvedRefPath)!; return refBuildInfo.path === buildInfoCacheEntry.path; } -function getUpToDateStatus(state: SolutionBuilderState, project: ParsedCommandLine | undefined, resolvedPath: ResolvedConfigFilePath): UpToDateStatus { +function getUpToDateStatus( + state: SolutionBuilderState, + project: ParsedCommandLine | undefined, + resolvedPath: ResolvedConfigFilePath, +): UpToDateStatus { if (project === undefined) { return { type: UpToDateStatusType.Unbuildable, reason: "File deleted mid-build" }; } @@ -2021,7 +2365,11 @@ function getUpToDateStatus(state: SolutionBuilderState performance.mark("SolutionBuilder::beforeUpToDateCheck"); const actual = getUpToDateStatusWorker(state, project, resolvedPath); performance.mark("SolutionBuilder::afterUpToDateCheck"); - performance.measure("SolutionBuilder::Up-to-date check", "SolutionBuilder::beforeUpToDateCheck", "SolutionBuilder::afterUpToDateCheck"); + performance.measure( + "SolutionBuilder::Up-to-date check", + "SolutionBuilder::beforeUpToDateCheck", + "SolutionBuilder::afterUpToDateCheck", + ); state.projectStatus.set(resolvedPath, actual); return actual; } @@ -2076,20 +2424,35 @@ function updateOutputTimestampsWorker( }); } -function getLatestChangedDtsTime(state: SolutionBuilderState, options: CompilerOptions, resolvedConfigPath: ResolvedConfigFilePath) { +function getLatestChangedDtsTime( + state: SolutionBuilderState, + options: CompilerOptions, + resolvedConfigPath: ResolvedConfigFilePath, +) { if (!options.composite) return undefined; const entry = Debug.checkDefined(state.buildInfoCache.get(resolvedConfigPath)); if (entry.latestChangedDtsTime !== undefined) return entry.latestChangedDtsTime || undefined; - const latestChangedDtsTime = entry.buildInfo && entry.buildInfo.program && entry.buildInfo.program.latestChangedDtsFile ? - state.host.getModifiedTime(getNormalizedAbsolutePath(entry.buildInfo.program.latestChangedDtsFile, getDirectoryPath(entry.path))) : - undefined; + const latestChangedDtsTime = + entry.buildInfo && entry.buildInfo.program && entry.buildInfo.program.latestChangedDtsFile + ? state.host.getModifiedTime( + getNormalizedAbsolutePath(entry.buildInfo.program.latestChangedDtsFile, getDirectoryPath(entry.path)), + ) + : undefined; entry.latestChangedDtsTime = latestChangedDtsTime || false; return latestChangedDtsTime; } -function updateOutputTimestamps(state: SolutionBuilderState, proj: ParsedCommandLine, resolvedPath: ResolvedConfigFilePath) { +function updateOutputTimestamps( + state: SolutionBuilderState, + proj: ParsedCommandLine, + resolvedPath: ResolvedConfigFilePath, +) { if (state.options.dry) { - return reportStatus(state, Diagnostics.A_non_dry_build_would_update_timestamps_for_output_of_project_0, proj.options.configFilePath!); + return reportStatus( + state, + Diagnostics.A_non_dry_build_would_update_timestamps_for_output_of_project_0, + proj.options.configFilePath!, + ); } updateOutputTimestampsWorker(state, proj, resolvedPath, Diagnostics.Updating_output_timestamps_of_project_0); state.projectStatus.set(resolvedPath, { @@ -2150,14 +2513,18 @@ function queueReferencingProjects( if (!(buildResult & BuildResultFlags.DeclarationOutputUnchanged)) { state.projectStatus.set(nextProjectPath, { type: UpToDateStatusType.OutOfDateWithUpstream, - outOfDateOutputFileName: status.type === UpToDateStatusType.OutOfDateWithPrepend ? status.outOfDateOutputFileName : status.oldestOutputFileName, + outOfDateOutputFileName: status.type === UpToDateStatusType.OutOfDateWithPrepend + ? status.outOfDateOutputFileName : status.oldestOutputFileName, newerProjectName: project, }); } break; case UpToDateStatusType.UpstreamBlocked: - if (toResolvedConfigFilePath(state, resolveProjectName(state, status.upstreamProjectName)) === projectPath) { + if ( + toResolvedConfigFilePath(state, resolveProjectName(state, status.upstreamProjectName)) + === projectPath + ) { clearProjectStatus(state, nextProjectPath); } break; @@ -2169,7 +2536,14 @@ function queueReferencingProjects( } } -function build(state: SolutionBuilderState, project?: string, cancellationToken?: CancellationToken, writeFile?: WriteFileCallback, getCustomTransformers?: (project: string) => CustomTransformers, onlyReferences?: boolean): ExitStatus { +function build( + state: SolutionBuilderState, + project?: string, + cancellationToken?: CancellationToken, + writeFile?: WriteFileCallback, + getCustomTransformers?: (project: string) => CustomTransformers, + onlyReferences?: boolean, +): ExitStatus { performance.mark("SolutionBuilder::beforeBuild"); const result = buildWorker(state, project, cancellationToken, writeFile, getCustomTransformers, onlyReferences); performance.mark("SolutionBuilder::afterBuild"); @@ -2177,7 +2551,14 @@ function build(state: SolutionBuilderState, project return result; } -function buildWorker(state: SolutionBuilderState, project: string | undefined, cancellationToken: CancellationToken | undefined, writeFile: WriteFileCallback | undefined, getCustomTransformers: ((project: string) => CustomTransformers) | undefined, onlyReferences: boolean | undefined): ExitStatus { +function buildWorker( + state: SolutionBuilderState, + project: string | undefined, + cancellationToken: CancellationToken | undefined, + writeFile: WriteFileCallback | undefined, + getCustomTransformers: ((project: string) => CustomTransformers) | undefined, + onlyReferences: boolean | undefined, +): ExitStatus { const buildOrder = getBuildOrderFor(state, project, onlyReferences); if (!buildOrder) return ExitStatus.InvalidProject_OutputsSkipped; @@ -2206,7 +2587,11 @@ function buildWorker(state: SolutionBuilderState, p : ExitStatus.DiagnosticsPresent_OutputsSkipped; } -function clean(state: SolutionBuilderState, project?: string, onlyReferences?: boolean): ExitStatus { +function clean( + state: SolutionBuilderState, + project?: string, + onlyReferences?: boolean, +): ExitStatus { performance.mark("SolutionBuilder::beforeClean"); const result = cleanWorker(state, project, onlyReferences); performance.mark("SolutionBuilder::afterClean"); @@ -2214,7 +2599,11 @@ function clean(state: SolutionBuilderState, project return result; } -function cleanWorker(state: SolutionBuilderState, project: string | undefined, onlyReferences: boolean | undefined) { +function cleanWorker( + state: SolutionBuilderState, + project: string | undefined, + onlyReferences: boolean | undefined, +) { const buildOrder = getBuildOrderFor(state, project, onlyReferences); if (!buildOrder) return ExitStatus.InvalidProject_OutputsSkipped; @@ -2252,13 +2641,21 @@ function cleanWorker(state: SolutionBuilderState, p } if (filesToDelete) { - reportStatus(state, Diagnostics.A_non_dry_build_would_delete_the_following_files_Colon_0, filesToDelete.map(f => `\r\n * ${f}`).join("")); + reportStatus( + state, + Diagnostics.A_non_dry_build_would_delete_the_following_files_Colon_0, + filesToDelete.map(f => `\r\n * ${f}`).join(""), + ); } return ExitStatus.Success; } -function invalidateProject(state: SolutionBuilderState, resolved: ResolvedConfigFilePath, reloadLevel: ConfigFileProgramReloadLevel) { +function invalidateProject( + state: SolutionBuilderState, + resolved: ResolvedConfigFilePath, + reloadLevel: ConfigFileProgramReloadLevel, +) { // If host implements getParsedCommandLine, we cant get list of files from parseConfigFileHost if (state.host.getParsedCommandLine && reloadLevel === ConfigFileProgramReloadLevel.Partial) { reloadLevel = ConfigFileProgramReloadLevel.Full; @@ -2273,13 +2670,21 @@ function invalidateProject(state: SolutionBuilderState enableCache(state); } -function invalidateProjectAndScheduleBuilds(state: SolutionBuilderState, resolvedPath: ResolvedConfigFilePath, reloadLevel: ConfigFileProgramReloadLevel) { +function invalidateProjectAndScheduleBuilds( + state: SolutionBuilderState, + resolvedPath: ResolvedConfigFilePath, + reloadLevel: ConfigFileProgramReloadLevel, +) { state.reportFileChangeDetected = true; invalidateProject(state, resolvedPath, reloadLevel); scheduleBuildInvalidatedProject(state, 250, /*changeDetected*/ true); } -function scheduleBuildInvalidatedProject(state: SolutionBuilderState, time: number, changeDetected: boolean) { +function scheduleBuildInvalidatedProject( + state: SolutionBuilderState, + time: number, + changeDetected: boolean, +) { const { hostWithWatch } = state; if (!hostWithWatch.setTimeout || !hostWithWatch.clearTimeout) { return; @@ -2287,10 +2692,20 @@ function scheduleBuildInvalidatedProject(state: Soluti if (state.timerToBuildInvalidatedProject) { hostWithWatch.clearTimeout(state.timerToBuildInvalidatedProject); } - state.timerToBuildInvalidatedProject = hostWithWatch.setTimeout(buildNextInvalidatedProject, time, "timerToBuildInvalidatedProject", state, changeDetected); + state.timerToBuildInvalidatedProject = hostWithWatch.setTimeout( + buildNextInvalidatedProject, + time, + "timerToBuildInvalidatedProject", + state, + changeDetected, + ); } -function buildNextInvalidatedProject(_timeoutType: string, state: SolutionBuilderState, changeDetected: boolean) { +function buildNextInvalidatedProject( + _timeoutType: string, + state: SolutionBuilderState, + changeDetected: boolean, +) { performance.mark("SolutionBuilder::beforeBuild"); const buildOrder = buildNextInvalidatedProjectWorker(state, changeDetected); performance.mark("SolutionBuilder::afterBuild"); @@ -2298,7 +2713,10 @@ function buildNextInvalidatedProject(_timeoutType: str if (buildOrder) reportErrorSummary(state, buildOrder); } -function buildNextInvalidatedProjectWorker(state: SolutionBuilderState, changeDetected: boolean) { +function buildNextInvalidatedProjectWorker( + state: SolutionBuilderState, + changeDetected: boolean, +) { state.timerToBuildInvalidatedProject = undefined; if (state.reportFileChangeDetected) { state.reportFileChangeDetected = false; @@ -2317,7 +2735,9 @@ function buildNextInvalidatedProjectWorker(state: Solu // Before scheduling check if the next project needs build const info = getNextInvalidatedProjectCreateInfo(state, buildOrder, /*reportQueue*/ false); if (!info) break; // Nothing to build any more - if (info.kind !== InvalidatedProjectKind.UpdateOutputFileStamps && (changeDetected || projectsBuilt === 5)) { + if ( + info.kind !== InvalidatedProjectKind.UpdateOutputFileStamps && (changeDetected || projectsBuilt === 5) + ) { // Schedule next project for build scheduleBuildInvalidatedProject(state, 100, /*changeDetected*/ false); return; @@ -2331,7 +2751,12 @@ function buildNextInvalidatedProjectWorker(state: Solu return buildOrder; } -function watchConfigFile(state: SolutionBuilderState, resolved: ResolvedConfigFileName, resolvedPath: ResolvedConfigFilePath, parsed: ParsedCommandLine | undefined) { +function watchConfigFile( + state: SolutionBuilderState, + resolved: ResolvedConfigFileName, + resolvedPath: ResolvedConfigFilePath, + parsed: ParsedCommandLine | undefined, +) { if (!state.watch || state.allWatchedConfigFiles.has(resolvedPath)) return; state.allWatchedConfigFiles.set( resolvedPath, @@ -2347,7 +2772,11 @@ function watchConfigFile(state: SolutionBuilderState(state: SolutionBuilderState, resolvedPath: ResolvedConfigFilePath, parsed: ParsedCommandLine | undefined) { +function watchExtendedConfigFiles( + state: SolutionBuilderState, + resolvedPath: ResolvedConfigFilePath, + parsed: ParsedCommandLine | undefined, +) { updateSharedExtendedConfigFileWatcher( resolvedPath, parsed?.options, @@ -2356,7 +2785,15 @@ function watchExtendedConfigFiles(state: SolutionBuild watchFile( state, extendedConfigFileName, - () => state.allWatchedExtendedConfigFiles.get(extendedConfigFilePath)?.projects.forEach(projectConfigFilePath => invalidateProjectAndScheduleBuilds(state, projectConfigFilePath, ConfigFileProgramReloadLevel.Full)), + () => + state.allWatchedExtendedConfigFiles.get(extendedConfigFilePath)?.projects.forEach( + projectConfigFilePath => + invalidateProjectAndScheduleBuilds( + state, + projectConfigFilePath, + ConfigFileProgramReloadLevel.Full, + ), + ), PollingInterval.High, parsed?.watchOptions, WatchType.ExtendedConfigFile, @@ -2365,7 +2802,12 @@ function watchExtendedConfigFiles(state: SolutionBuild ); } -function watchWildCardDirectories(state: SolutionBuilderState, resolved: ResolvedConfigFileName, resolvedPath: ResolvedConfigFilePath, parsed: ParsedCommandLine) { +function watchWildCardDirectories( + state: SolutionBuilderState, + resolved: ResolvedConfigFileName, + resolvedPath: ResolvedConfigFilePath, + parsed: ParsedCommandLine, +) { if (!state.watch) return; updateWatchingWildcardDirectories( getOrCreateValueMapFromConfigFileMap(state.allWatchedWildcardDirectories, resolvedPath), @@ -2382,7 +2824,8 @@ function watchWildCardDirectories(state: SolutionBuild configFileName: resolved, currentDirectory: state.compilerHost.getCurrentDirectory(), options: parsed.options, - program: state.builderPrograms.get(resolvedPath) || getCachedParsedConfigFile(state, resolvedPath)?.fileNames, + program: state.builderPrograms.get(resolvedPath) + || getCachedParsedConfigFile(state, resolvedPath)?.fileNames, useCaseSensitiveFileNames: state.parseConfigFileHost.useCaseSensitiveFileNames, writeLog: s => state.writeLog(s), toPath: fileName => toPath(state, fileName), @@ -2399,7 +2842,12 @@ function watchWildCardDirectories(state: SolutionBuild ); } -function watchInputFiles(state: SolutionBuilderState, resolved: ResolvedConfigFileName, resolvedPath: ResolvedConfigFilePath, parsed: ParsedCommandLine) { +function watchInputFiles( + state: SolutionBuilderState, + resolved: ResolvedConfigFileName, + resolvedPath: ResolvedConfigFilePath, + parsed: ParsedCommandLine, +) { if (!state.watch) return; mutateMap( getOrCreateValueMapFromConfigFileMap(state.allWatchedInputFiles, resolvedPath), @@ -2420,7 +2868,12 @@ function watchInputFiles(state: SolutionBuilderState(state: SolutionBuilderState, resolved: ResolvedConfigFileName, resolvedPath: ResolvedConfigFilePath, parsed: ParsedCommandLine) { +function watchPackageJsonFiles( + state: SolutionBuilderState, + resolved: ResolvedConfigFileName, + resolvedPath: ResolvedConfigFilePath, + parsed: ParsedCommandLine, +) { if (!state.watch || !state.lastCachedPackageJsonLookups) return; mutateMap( getOrCreateValueMapFromConfigFileMap(state.allWatchedPackageJsonFiles, resolvedPath), @@ -2463,29 +2916,61 @@ function startWatching(state: SolutionBuilderState, } } performance.mark("SolutionBuilder::afterWatcherCreation"); - performance.measure("SolutionBuilder::Watcher creation", "SolutionBuilder::beforeWatcherCreation", "SolutionBuilder::afterWatcherCreation"); + performance.measure( + "SolutionBuilder::Watcher creation", + "SolutionBuilder::beforeWatcherCreation", + "SolutionBuilder::afterWatcherCreation", + ); } function stopWatching(state: SolutionBuilderState) { clearMap(state.allWatchedConfigFiles, closeFileWatcher); clearMap(state.allWatchedExtendedConfigFiles, closeFileWatcherOf); - clearMap(state.allWatchedWildcardDirectories, watchedWildcardDirectories => clearMap(watchedWildcardDirectories, closeFileWatcherOf)); - clearMap(state.allWatchedInputFiles, watchedWildcardDirectories => clearMap(watchedWildcardDirectories, closeFileWatcher)); - clearMap(state.allWatchedPackageJsonFiles, watchedPacageJsonFiles => clearMap(watchedPacageJsonFiles, closeFileWatcher)); + clearMap( + state.allWatchedWildcardDirectories, + watchedWildcardDirectories => clearMap(watchedWildcardDirectories, closeFileWatcherOf), + ); + clearMap( + state.allWatchedInputFiles, + watchedWildcardDirectories => clearMap(watchedWildcardDirectories, closeFileWatcher), + ); + clearMap( + state.allWatchedPackageJsonFiles, + watchedPacageJsonFiles => clearMap(watchedPacageJsonFiles, closeFileWatcher), + ); } /** * A SolutionBuilder has an immutable set of rootNames that are the "entry point" projects, but * can dynamically add/remove other projects based on changes on the rootNames' references */ -function createSolutionBuilderWorker(watch: false, host: SolutionBuilderHost, rootNames: readonly string[], defaultOptions: BuildOptions): SolutionBuilder; -function createSolutionBuilderWorker(watch: true, host: SolutionBuilderWithWatchHost, rootNames: readonly string[], defaultOptions: BuildOptions, baseWatchOptions?: WatchOptions): SolutionBuilder; -function createSolutionBuilderWorker(watch: boolean, hostOrHostWithWatch: SolutionBuilderHost | SolutionBuilderWithWatchHost, rootNames: readonly string[], options: BuildOptions, baseWatchOptions?: WatchOptions): SolutionBuilder { +function createSolutionBuilderWorker( + watch: false, + host: SolutionBuilderHost, + rootNames: readonly string[], + defaultOptions: BuildOptions, +): SolutionBuilder; +function createSolutionBuilderWorker( + watch: true, + host: SolutionBuilderWithWatchHost, + rootNames: readonly string[], + defaultOptions: BuildOptions, + baseWatchOptions?: WatchOptions, +): SolutionBuilder; +function createSolutionBuilderWorker( + watch: boolean, + hostOrHostWithWatch: SolutionBuilderHost | SolutionBuilderWithWatchHost, + rootNames: readonly string[], + options: BuildOptions, + baseWatchOptions?: WatchOptions, +): SolutionBuilder { const state = createSolutionBuilderState(watch, hostOrHostWithWatch, rootNames, options, baseWatchOptions); return { - build: (project, cancellationToken, writeFile, getCustomTransformers) => build(state, project, cancellationToken, writeFile, getCustomTransformers), + build: (project, cancellationToken, writeFile, getCustomTransformers) => + build(state, project, cancellationToken, writeFile, getCustomTransformers), clean: project => clean(state, project), - buildReferences: (project, cancellationToken, writeFile, getCustomTransformers) => build(state, project, cancellationToken, writeFile, getCustomTransformers, /*onlyReferences*/ true), + buildReferences: (project, cancellationToken, writeFile, getCustomTransformers) => + build(state, project, cancellationToken, writeFile, getCustomTransformers, /*onlyReferences*/ true), cleanReferences: project => clean(state, project, /*onlyReferences*/ true), getNextInvalidatedProject: cancellationToken => { setupInitialBuild(state, cancellationToken); @@ -2497,28 +2982,49 @@ function createSolutionBuilderWorker(watch: boolean, h const configFilePath = toResolvedConfigFilePath(state, configFileName); return getUpToDateStatus(state, parseConfigFile(state, configFileName, configFilePath), configFilePath); }, - invalidateProject: (configFilePath, reloadLevel) => invalidateProject(state, configFilePath, reloadLevel || ConfigFileProgramReloadLevel.None), + invalidateProject: (configFilePath, reloadLevel) => + invalidateProject(state, configFilePath, reloadLevel || ConfigFileProgramReloadLevel.None), close: () => stopWatching(state), }; } function relName(state: SolutionBuilderState, path: string): string { - return convertToRelativePath(path, state.compilerHost.getCurrentDirectory(), state.compilerHost.getCanonicalFileName); + return convertToRelativePath( + path, + state.compilerHost.getCurrentDirectory(), + state.compilerHost.getCanonicalFileName, + ); } -function reportStatus(state: SolutionBuilderState, message: DiagnosticMessage, ...args: DiagnosticArguments) { +function reportStatus( + state: SolutionBuilderState, + message: DiagnosticMessage, + ...args: DiagnosticArguments +) { state.host.reportSolutionBuilderStatus(createCompilerDiagnostic(message, ...args)); } -function reportWatchStatus(state: SolutionBuilderState, message: DiagnosticMessage, ...args: DiagnosticArguments) { - state.hostWithWatch.onWatchStatusChange?.(createCompilerDiagnostic(message, ...args), state.host.getNewLine(), state.baseCompilerOptions); +function reportWatchStatus( + state: SolutionBuilderState, + message: DiagnosticMessage, + ...args: DiagnosticArguments +) { + state.hostWithWatch.onWatchStatusChange?.( + createCompilerDiagnostic(message, ...args), + state.host.getNewLine(), + state.baseCompilerOptions, + ); } function reportErrors({ host }: SolutionBuilderState, errors: readonly Diagnostic[]) { errors.forEach(err => host.reportDiagnostic(err)); } -function reportAndStoreErrors(state: SolutionBuilderState, proj: ResolvedConfigFilePath, errors: readonly Diagnostic[]) { +function reportAndStoreErrors( + state: SolutionBuilderState, + proj: ResolvedConfigFilePath, + errors: readonly Diagnostic[], +) { reportErrors(state, errors); state.projectErrorsReported.set(proj, true); if (errors.length) { @@ -2526,7 +3032,10 @@ function reportAndStoreErrors(state: SolutionBuilderSt } } -function reportParseConfigFileDiagnostic(state: SolutionBuilderState, proj: ResolvedConfigFilePath) { +function reportParseConfigFileDiagnostic( + state: SolutionBuilderState, + proj: ResolvedConfigFilePath, +) { reportAndStoreErrors(state, proj, [state.configFileCache.get(proj) as Diagnostic]); } @@ -2541,7 +3050,9 @@ function reportErrorSummary(state: SolutionBuilderStat reportBuildQueue(state, buildOrder.buildOrder); reportErrors(state, buildOrder.circularDiagnostics); if (canReportSummary) totalErrors += getErrorCountForSummary(buildOrder.circularDiagnostics); - if (canReportSummary) filesInError = [...filesInError, ...getFilesInErrorForSummary(buildOrder.circularDiagnostics)]; + if (canReportSummary) { + filesInError = [...filesInError, ...getFilesInErrorForSummary(buildOrder.circularDiagnostics)]; + } } else { // Report errors from the other projects @@ -2551,8 +3062,14 @@ function reportErrorSummary(state: SolutionBuilderStat reportErrors(state, diagnostics.get(projectPath) || emptyArray); } }); - if (canReportSummary) diagnostics.forEach(singleProjectErrors => totalErrors += getErrorCountForSummary(singleProjectErrors)); - if (canReportSummary) diagnostics.forEach(singleProjectErrors => [...filesInError, ...getFilesInErrorForSummary(singleProjectErrors)]); + if (canReportSummary) { + diagnostics.forEach(singleProjectErrors => totalErrors += getErrorCountForSummary(singleProjectErrors)); + } + if (canReportSummary) { + diagnostics.forEach( + singleProjectErrors => [...filesInError, ...getFilesInErrorForSummary(singleProjectErrors)], + ); + } } if (state.watch) { @@ -2566,13 +3083,24 @@ function reportErrorSummary(state: SolutionBuilderStat /** * Report the build ordering inferred from the current project graph if we're in verbose mode */ -function reportBuildQueue(state: SolutionBuilderState, buildQueue: readonly ResolvedConfigFileName[]) { +function reportBuildQueue( + state: SolutionBuilderState, + buildQueue: readonly ResolvedConfigFileName[], +) { if (state.options.verbose) { - reportStatus(state, Diagnostics.Projects_in_this_build_Colon_0, buildQueue.map(s => "\r\n * " + relName(state, s)).join("")); + reportStatus( + state, + Diagnostics.Projects_in_this_build_Colon_0, + buildQueue.map(s => "\r\n * " + relName(state, s)).join(""), + ); } } -function reportUpToDateStatus(state: SolutionBuilderState, configFileName: string, status: UpToDateStatus) { +function reportUpToDateStatus( + state: SolutionBuilderState, + configFileName: string, + status: UpToDateStatus, +) { switch (status.type) { case UpToDateStatusType.OutOfDateWithSelf: return reportStatus( @@ -2607,21 +3135,24 @@ function reportUpToDateStatus(state: SolutionBuilderSt case UpToDateStatusType.OutOfDateBuildInfo: return reportStatus( state, - Diagnostics.Project_0_is_out_of_date_because_buildinfo_file_1_indicates_that_some_of_the_changes_were_not_emitted, + Diagnostics + .Project_0_is_out_of_date_because_buildinfo_file_1_indicates_that_some_of_the_changes_were_not_emitted, relName(state, configFileName), relName(state, status.buildInfoFile), ); case UpToDateStatusType.OutOfDateOptions: return reportStatus( state, - Diagnostics.Project_0_is_out_of_date_because_buildinfo_file_1_indicates_there_is_change_in_compilerOptions, + Diagnostics + .Project_0_is_out_of_date_because_buildinfo_file_1_indicates_there_is_change_in_compilerOptions, relName(state, configFileName), relName(state, status.buildInfoFile), ); case UpToDateStatusType.OutOfDateRoots: return reportStatus( state, - Diagnostics.Project_0_is_out_of_date_because_buildinfo_file_1_indicates_that_file_2_was_root_file_of_compilation_but_not_any_more, + Diagnostics + .Project_0_is_out_of_date_because_buildinfo_file_1_indicates_that_file_2_was_root_file_of_compilation_but_not_any_more, relName(state, configFileName), relName(state, status.buildInfoFile), relName(state, status.inputFile), @@ -2654,7 +3185,8 @@ function reportUpToDateStatus(state: SolutionBuilderSt case UpToDateStatusType.UpToDateWithInputFileText: return reportStatus( state, - Diagnostics.Project_0_is_up_to_date_but_needs_to_update_timestamps_of_output_files_that_are_older_than_input_files, + Diagnostics + .Project_0_is_up_to_date_but_needs_to_update_timestamps_of_output_files_that_are_older_than_input_files, relName(state, configFileName), ); case UpToDateStatusType.UpstreamOutOfDate: @@ -2667,9 +3199,9 @@ function reportUpToDateStatus(state: SolutionBuilderSt case UpToDateStatusType.UpstreamBlocked: return reportStatus( state, - status.upstreamProjectBlocked ? - Diagnostics.Project_0_can_t_be_built_because_its_dependency_1_was_not_built : - Diagnostics.Project_0_can_t_be_built_because_its_dependency_1_has_errors, + status.upstreamProjectBlocked + ? Diagnostics.Project_0_can_t_be_built_because_its_dependency_1_was_not_built + : Diagnostics.Project_0_can_t_be_built_because_its_dependency_1_has_errors, relName(state, configFileName), relName(state, status.upstreamProjectName), ); @@ -2683,7 +3215,8 @@ function reportUpToDateStatus(state: SolutionBuilderSt case UpToDateStatusType.TsVersionOutputOfDate: return reportStatus( state, - Diagnostics.Project_0_is_out_of_date_because_output_for_it_was_generated_with_version_1_that_differs_with_current_version_2, + Diagnostics + .Project_0_is_out_of_date_because_output_for_it_was_generated_with_version_1_that_differs_with_current_version_2, relName(state, configFileName), status.version, version, @@ -2708,7 +3241,11 @@ function reportUpToDateStatus(state: SolutionBuilderSt /** * Report the up-to-date status of a project if we're in verbose mode */ -function verboseReportProjectStatus(state: SolutionBuilderState, configFileName: string, status: UpToDateStatus) { +function verboseReportProjectStatus( + state: SolutionBuilderState, + configFileName: string, + status: UpToDateStatus, +) { if (state.options.verbose) { reportUpToDateStatus(state, configFileName, status); } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index defa7bcca706b..9744ff8cc5c7e 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -24,7 +24,8 @@ import { export type Path = string & { __pathBrand: any; }; /** @internal */ -export type MatchingKeys = K extends (TRecord[K] extends TMatch ? K : never) ? K : never; +export type MatchingKeys = K extends + (TRecord[K] extends TMatch ? K : never) ? K : never; export interface TextRange { pos: number; @@ -830,7 +831,8 @@ export const enum NodeFlags { ReachabilityAndEmitFlags = ReachabilityCheckFlags | HasAsyncFunctions, // Parsing context flags - ContextFlags = DisallowInContext | DisallowConditionalTypesContext | YieldContext | DecoratorContext | AwaitContext | JavaScriptFile | InWithStatement | Ambient, + ContextFlags = DisallowInContext | DisallowConditionalTypesContext | YieldContext | DecoratorContext | AwaitContext + | JavaScriptFile | InWithStatement | Ambient, // Exclude these flags when parsing a Type TypeExcludesFlags = YieldContext | AwaitContext, @@ -875,7 +877,8 @@ export const enum ModifierFlags { TypeScriptModifier = Ambient | Public | Private | Protected | Readonly | Abstract | Const | Override | In | Out, ExportDefault = Export | Default, - All = Export | Ambient | Public | Private | Protected | Static | Readonly | Abstract | Accessor | Async | Default | Const | Deprecated | Override | In | Out | Decorator, + All = Export | Ambient | Public | Private | Protected | Static | Readonly | Abstract | Accessor | Async | Default + | Const | Deprecated | Override | In | Out | Decorator, Modifier = All & ~Decorator, } @@ -1902,7 +1905,9 @@ export interface PrivateIdentifierSetAccessorDeclaration extends SetAccessorDecl name: PrivateIdentifier; } /** @internal */ -export type PrivateIdentifierAccessorDeclaration = PrivateIdentifierGetAccessorDeclaration | PrivateIdentifierSetAccessorDeclaration; +export type PrivateIdentifierAccessorDeclaration = + | PrivateIdentifierGetAccessorDeclaration + | PrivateIdentifierSetAccessorDeclaration; /** @internal */ export type PrivateClassElementDeclaration = | PrivateIdentifierPropertyDeclaration @@ -2042,7 +2047,15 @@ export interface MethodSignature extends SignatureDeclarationBase, TypeElement, // Because of this, it may be necessary to determine what sort of MethodDeclaration you have // at later stages of the compiler pipeline. In that case, you can either check the parent kind // of the method, or use helpers like isObjectLiteralMethodDeclaration -export interface MethodDeclaration extends FunctionLikeDeclarationBase, ClassElement, ObjectLiteralElement, JSDocContainer, LocalsContainer, FlowContainer { +export interface MethodDeclaration + extends + FunctionLikeDeclarationBase, + ClassElement, + ObjectLiteralElement, + JSDocContainer, + LocalsContainer, + FlowContainer +{ readonly kind: SyntaxKind.MethodDeclaration; readonly parent: ClassLikeDeclaration | ObjectLiteralExpression; readonly modifiers?: NodeArray | undefined; @@ -2053,7 +2066,9 @@ export interface MethodDeclaration extends FunctionLikeDeclarationBase, ClassEle /** @internal */ readonly exclamationToken?: ExclamationToken | undefined; // A method cannot have an exclamation token } -export interface ConstructorDeclaration extends FunctionLikeDeclarationBase, ClassElement, JSDocContainer, LocalsContainer { +export interface ConstructorDeclaration + extends FunctionLikeDeclarationBase, ClassElement, JSDocContainer, LocalsContainer +{ readonly kind: SyntaxKind.Constructor; readonly parent: ClassLikeDeclaration; readonly modifiers?: NodeArray | undefined; @@ -2072,7 +2087,16 @@ export interface SemicolonClassElement extends ClassElement, JSDocContainer { // See the comment on MethodDeclaration for the intuition behind GetAccessorDeclaration being a // ClassElement and an ObjectLiteralElement. -export interface GetAccessorDeclaration extends FunctionLikeDeclarationBase, ClassElement, TypeElement, ObjectLiteralElement, JSDocContainer, LocalsContainer, FlowContainer { +export interface GetAccessorDeclaration + extends + FunctionLikeDeclarationBase, + ClassElement, + TypeElement, + ObjectLiteralElement, + JSDocContainer, + LocalsContainer, + FlowContainer +{ readonly kind: SyntaxKind.GetAccessor; readonly parent: ClassLikeDeclaration | ObjectLiteralExpression | TypeLiteralNode | InterfaceDeclaration; readonly modifiers?: NodeArray; @@ -2085,7 +2109,16 @@ export interface GetAccessorDeclaration extends FunctionLikeDeclarationBase, Cla // See the comment on MethodDeclaration for the intuition behind SetAccessorDeclaration being a // ClassElement and an ObjectLiteralElement. -export interface SetAccessorDeclaration extends FunctionLikeDeclarationBase, ClassElement, TypeElement, ObjectLiteralElement, JSDocContainer, LocalsContainer, FlowContainer { +export interface SetAccessorDeclaration + extends + FunctionLikeDeclarationBase, + ClassElement, + TypeElement, + ObjectLiteralElement, + JSDocContainer, + LocalsContainer, + FlowContainer +{ readonly kind: SyntaxKind.SetAccessor; readonly parent: ClassLikeDeclaration | ObjectLiteralExpression | TypeLiteralNode | InterfaceDeclaration; readonly modifiers?: NodeArray; @@ -2099,7 +2132,9 @@ export interface SetAccessorDeclaration extends FunctionLikeDeclarationBase, Cla export type AccessorDeclaration = GetAccessorDeclaration | SetAccessorDeclaration; -export interface IndexSignatureDeclaration extends SignatureDeclarationBase, ClassElement, TypeElement, LocalsContainer { +export interface IndexSignatureDeclaration + extends SignatureDeclarationBase, ClassElement, TypeElement, LocalsContainer +{ readonly kind: SyntaxKind.IndexSignature; readonly parent: ObjectTypeDeclaration; readonly modifiers?: NodeArray; @@ -2127,7 +2162,9 @@ export interface TypeNode extends Node { readonly kind: TypeNodeSyntaxKind; } -export interface KeywordTypeNode extends KeywordToken, TypeNode { +export interface KeywordTypeNode + extends KeywordToken, TypeNode +{ readonly kind: TKind; } @@ -2147,7 +2184,9 @@ export interface ImportTypeNode extends NodeWithTypeArguments { } /** @internal */ -export type LiteralImportTypeNode = ImportTypeNode & { readonly argument: LiteralTypeNode & { readonly literal: StringLiteral; }; }; +export type LiteralImportTypeNode = ImportTypeNode & { + readonly argument: LiteralTypeNode & { readonly literal: StringLiteral; }; +}; export interface ThisTypeNode extends TypeNode { readonly kind: SyntaxKind.ThisType; @@ -2295,7 +2334,12 @@ export interface LiteralTypeNode extends TypeNode { export interface StringLiteral extends LiteralExpression, Declaration { readonly kind: SyntaxKind.StringLiteral; - /** @internal */ readonly textSourceNode?: Identifier | StringLiteralLike | NumericLiteral | PrivateIdentifier | JsxNamespacedName; // Allows a StringLiteral to get its text from another node (used by transforms). + /** @internal */ readonly textSourceNode?: + | Identifier + | StringLiteralLike + | NumericLiteral + | PrivateIdentifier + | JsxNamespacedName; // Allows a StringLiteral to get its text from another node (used by transforms). /** * Note: this is only set when synthesizing a node, not during parsing. * @@ -2678,14 +2722,18 @@ export interface ConditionalExpression extends Expression { export type FunctionBody = Block; export type ConciseBody = FunctionBody | Expression; -export interface FunctionExpression extends PrimaryExpression, FunctionLikeDeclarationBase, JSDocContainer, LocalsContainer, FlowContainer { +export interface FunctionExpression + extends PrimaryExpression, FunctionLikeDeclarationBase, JSDocContainer, LocalsContainer, FlowContainer +{ readonly kind: SyntaxKind.FunctionExpression; readonly modifiers?: NodeArray; readonly name?: Identifier; readonly body: FunctionBody; // Required, whereas the member inherited from FunctionDeclaration is optional } -export interface ArrowFunction extends Expression, FunctionLikeDeclarationBase, JSDocContainer, LocalsContainer, FlowContainer { +export interface ArrowFunction + extends Expression, FunctionLikeDeclarationBase, JSDocContainer, LocalsContainer, FlowContainer +{ readonly kind: SyntaxKind.ArrowFunction; readonly modifiers?: NodeArray; readonly equalsGreaterThanToken: EqualsGreaterThanToken; @@ -2759,7 +2807,8 @@ export const enum TokenFlags { /** @internal */ StringLiteralFlags = HexEscape | UnicodeEscape | ExtendedUnicodeEscape | ContainsInvalidEscape, /** @internal */ - NumericLiteralFlags = Scientific | Octal | ContainsLeadingZero | WithSpecifier | ContainsSeparator | ContainsInvalidSeparator, + NumericLiteralFlags = Scientific | Octal | ContainsLeadingZero | WithSpecifier | ContainsSeparator + | ContainsInvalidSeparator, /** @internal */ TemplateLiteralLikeFlags = HexEscape | UnicodeEscape | ExtendedUnicodeEscape | ContainsInvalidEscape, /** @internal */ @@ -2964,7 +3013,9 @@ export type OptionalChainRoot = /** @internal */ export type BindableObjectDefinePropertyCall = CallExpression & { - readonly arguments: readonly [BindableStaticNameExpression, StringLiteralLike | NumericLiteral, ObjectLiteralExpression] & Readonly; + readonly arguments: + & readonly [BindableStaticNameExpression, StringLiteralLike | NumericLiteral, ObjectLiteralExpression] + & Readonly; }; /** @internal */ @@ -3710,12 +3761,20 @@ export type TypeOnlyImportDeclaration = | ImportClause & { readonly isTypeOnly: true; readonly name: Identifier; } | ImportEqualsDeclaration & { readonly isTypeOnly: true; } | NamespaceImport & { readonly parent: ImportClause & { readonly isTypeOnly: true; }; } - | ImportSpecifier & ({ readonly isTypeOnly: true; } | { readonly parent: NamedImports & { readonly parent: ImportClause & { readonly isTypeOnly: true; }; }; }); + | ImportSpecifier + & ({ readonly isTypeOnly: true; } | { + readonly parent: NamedImports & { readonly parent: ImportClause & { readonly isTypeOnly: true; }; }; + }); export type TypeOnlyExportDeclaration = - | ExportSpecifier & ({ readonly isTypeOnly: true; } | { readonly parent: NamedExports & { readonly parent: ExportDeclaration & { readonly isTypeOnly: true; }; }; }) + | ExportSpecifier + & ({ readonly isTypeOnly: true; } | { + readonly parent: NamedExports & { readonly parent: ExportDeclaration & { readonly isTypeOnly: true; }; }; + }) | ExportDeclaration & { readonly isTypeOnly: true; readonly moduleSpecifier: Expression; } // export * from "mod" - | NamespaceExport & { readonly parent: ExportDeclaration & { readonly isTypeOnly: true; readonly moduleSpecifier: Expression; }; } // export * as ns from "mod" + | NamespaceExport & { + readonly parent: ExportDeclaration & { readonly isTypeOnly: true; readonly moduleSpecifier: Expression; }; + } // export * as ns from "mod" ; export type TypeOnlyAliasDeclaration = TypeOnlyImportDeclaration | TypeOnlyExportDeclaration; @@ -3870,12 +3929,16 @@ export interface JSDocUnknownTag extends JSDocTag { */ export interface JSDocAugmentsTag extends JSDocTag { readonly kind: SyntaxKind.JSDocAugmentsTag; - readonly class: ExpressionWithTypeArguments & { readonly expression: Identifier | PropertyAccessEntityNameExpression; }; + readonly class: ExpressionWithTypeArguments & { + readonly expression: Identifier | PropertyAccessEntityNameExpression; + }; } export interface JSDocImplementsTag extends JSDocTag { readonly kind: SyntaxKind.JSDocImplementsTag; - readonly class: ExpressionWithTypeArguments & { readonly expression: Identifier | PropertyAccessEntityNameExpression; }; + readonly class: ExpressionWithTypeArguments & { + readonly expression: Identifier | PropertyAccessEntityNameExpression; + }; } export interface JSDocAuthorTag extends JSDocTag { @@ -4267,7 +4330,9 @@ export interface SourceFile extends Declaration, LocalsContainer { // It is used to resolve module names in the checker. // Content of this field should never be used directly - use getResolvedModuleFileName/setResolvedModuleFileName functions instead /** @internal */ resolvedModules?: ModeAwareCache; - /** @internal */ resolvedTypeReferenceDirectiveNames?: ModeAwareCache; + /** @internal */ resolvedTypeReferenceDirectiveNames?: ModeAwareCache< + ResolvedTypeReferenceDirectiveWithFailedLookupLocations + >; /** @internal */ imports: readonly StringLiteralLike[]; // Identifier only if `declare global` /** @internal */ moduleAugmentations: readonly (StringLiteral | Identifier)[]; @@ -4460,7 +4525,13 @@ export interface ScriptReferenceHost { export interface ParseConfigHost extends ModuleResolutionHost { useCaseSensitiveFileNames: boolean; - readDirectory(rootDir: string, extensions: readonly string[], excludes: readonly string[] | undefined, includes: readonly string[], depth?: number): readonly string[]; + readDirectory( + rootDir: string, + extensions: readonly string[], + excludes: readonly string[] | undefined, + includes: readonly string[], + depth?: number, + ): readonly string[]; /** * Gets a value indicating whether the specified path exists and is a file. @@ -4599,7 +4670,10 @@ export interface ResolutionDiagnostics { } /** @internal */ -export type FilePreprocessingDiagnostics = FilePreprocessingReferencedDiagnostic | FilePreprocessingFileExplainingDiagnostic | ResolutionDiagnostics; +export type FilePreprocessingDiagnostics = + | FilePreprocessingReferencedDiagnostic + | FilePreprocessingFileExplainingDiagnostic + | ResolutionDiagnostics; /** @internal */ export const enum EmitOnly { @@ -4608,7 +4682,9 @@ export const enum EmitOnly { } /** @internal */ -export interface LibResolution { +export interface LibResolution< + T extends ResolvedModuleWithFailedLookupLocations = ResolvedModuleWithFailedLookupLocations, +> { resolution: T; actual: string; } @@ -4646,21 +4722,49 @@ export interface Program extends ScriptReferenceHost { * used for writing the JavaScript and declaration files. Otherwise, the writeFile parameter * will be invoked when writing the JavaScript and declaration files. */ - emit(targetSourceFile?: SourceFile, writeFile?: WriteFileCallback, cancellationToken?: CancellationToken, emitOnlyDtsFiles?: boolean, customTransformers?: CustomTransformers): EmitResult; - /** @internal */ - emit(targetSourceFile?: SourceFile, writeFile?: WriteFileCallback, cancellationToken?: CancellationToken, emitOnly?: boolean | EmitOnly, customTransformers?: CustomTransformers, forceDtsEmit?: boolean): EmitResult; + emit( + targetSourceFile?: SourceFile, + writeFile?: WriteFileCallback, + cancellationToken?: CancellationToken, + emitOnlyDtsFiles?: boolean, + customTransformers?: CustomTransformers, + ): EmitResult; + /** @internal */ + emit( + targetSourceFile?: SourceFile, + writeFile?: WriteFileCallback, + cancellationToken?: CancellationToken, + emitOnly?: boolean | EmitOnly, + customTransformers?: CustomTransformers, + forceDtsEmit?: boolean, + ): EmitResult; getOptionsDiagnostics(cancellationToken?: CancellationToken): readonly Diagnostic[]; getGlobalDiagnostics(cancellationToken?: CancellationToken): readonly Diagnostic[]; - getSyntacticDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): readonly DiagnosticWithLocation[]; + getSyntacticDiagnostics( + sourceFile?: SourceFile, + cancellationToken?: CancellationToken, + ): readonly DiagnosticWithLocation[]; /** The first time this is called, it will return global diagnostics (no location). */ getSemanticDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): readonly Diagnostic[]; - getDeclarationDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): readonly DiagnosticWithLocation[]; + getDeclarationDiagnostics( + sourceFile?: SourceFile, + cancellationToken?: CancellationToken, + ): readonly DiagnosticWithLocation[]; getConfigFileParsingDiagnostics(): readonly Diagnostic[]; - /** @internal */ getSuggestionDiagnostics(sourceFile: SourceFile, cancellationToken?: CancellationToken): readonly DiagnosticWithLocation[]; - - /** @internal */ getBindAndCheckDiagnostics(sourceFile: SourceFile, cancellationToken?: CancellationToken): readonly Diagnostic[]; - /** @internal */ getProgramDiagnostics(sourceFile: SourceFile, cancellationToken?: CancellationToken): readonly Diagnostic[]; + /** @internal */ getSuggestionDiagnostics( + sourceFile: SourceFile, + cancellationToken?: CancellationToken, + ): readonly DiagnosticWithLocation[]; + + /** @internal */ getBindAndCheckDiagnostics( + sourceFile: SourceFile, + cancellationToken?: CancellationToken, + ): readonly Diagnostic[]; + /** @internal */ getProgramDiagnostics( + sourceFile: SourceFile, + cancellationToken?: CancellationToken, + ): readonly Diagnostic[]; /** * Gets a type checker that can be used to semantically analyze source files in the program. @@ -4681,9 +4785,13 @@ export interface Program extends ScriptReferenceHost { getRelationCacheSizes(): { assignable: number; identity: number; subtype: number; strictSubtype: number; }; /** @internal */ getFileProcessingDiagnostics(): FilePreprocessingDiagnostics[] | undefined; - /** @internal */ getResolvedTypeReferenceDirectives(): ModeAwareCache; + /** @internal */ getResolvedTypeReferenceDirectives(): ModeAwareCache< + ResolvedTypeReferenceDirectiveWithFailedLookupLocations + >; /** @internal */ getAutomaticTypeDirectiveNames(): string[]; - /** @internal */ getAutomaticTypeDirectiveResolutions(): ModeAwareCache; + /** @internal */ getAutomaticTypeDirectiveResolutions(): ModeAwareCache< + ResolvedTypeReferenceDirectiveWithFailedLookupLocations + >; isSourceFileFromExternalLibrary(file: SourceFile): boolean; isSourceFileDefaultLibrary(file: SourceFile): boolean; @@ -4691,7 +4799,10 @@ export interface Program extends ScriptReferenceHost { // This is set on created program to let us know how the program was created using old program /** @internal */ readonly structureIsReused: StructureIsReused; - /** @internal */ getSourceFileFromReference(referencingFile: SourceFile | UnparsedSource, ref: FileReference): SourceFile | undefined; + /** @internal */ getSourceFileFromReference( + referencingFile: SourceFile | UnparsedSource, + ref: FileReference, + ): SourceFile | undefined; /** @internal */ getLibFileFromReference(ref: FileReference): SourceFile | undefined; /** @@ -4732,8 +4843,12 @@ export interface Program extends ScriptReferenceHost { getResolvedProjectReferences(): readonly (ResolvedProjectReference | undefined)[] | undefined; /** @internal */ getProjectReferenceRedirect(fileName: string): string | undefined; /** @internal */ getResolvedProjectReferenceToRedirect(fileName: string): ResolvedProjectReference | undefined; - /** @internal */ forEachResolvedProjectReference(cb: (resolvedProjectReference: ResolvedProjectReference) => T | undefined): T | undefined; - /** @internal */ getResolvedProjectReferenceByPath(projectReferencePath: Path): ResolvedProjectReference | undefined; + /** @internal */ forEachResolvedProjectReference( + cb: (resolvedProjectReference: ResolvedProjectReference) => T | undefined, + ): T | undefined; + /** @internal */ getResolvedProjectReferenceByPath( + projectReferencePath: Path, + ): ResolvedProjectReference | undefined; /** @internal */ isSourceOfProjectReferenceRedirect(fileName: string): boolean; /** @internal */ getBuildInfo?(bundle: BundleBuildInfo | undefined): BuildInfo; /** @internal */ emitBuildInfo(writeFile?: WriteFileCallback, cancellationToken?: CancellationToken): EmitResult; @@ -4889,7 +5004,10 @@ export interface TypeChecker { * @internal */ getParameterType(signature: Signature, parameterIndex: number): Type; - /** @internal */ getParameterIdentifierInfoAtPosition(signature: Signature, parameterIndex: number): { parameter: Identifier; parameterName: __String; isRestParameter: boolean; } | undefined; + /** @internal */ getParameterIdentifierInfoAtPosition( + signature: Signature, + parameterIndex: number, + ): { parameter: Identifier; parameterName: __String; isRestParameter: boolean; } | undefined; getNullableType(type: Type, flags: TypeFlags): Type; getNonNullableType(type: Type): Type; /** @internal */ getNonOptionalType(type: Type): Type; @@ -4898,30 +5016,86 @@ export interface TypeChecker { // TODO: GH#18217 `xToDeclaration` calls are frequently asserted as defined. /** Note that the resulting nodes cannot be checked. */ - typeToTypeNode(type: Type, enclosingDeclaration: Node | undefined, flags: NodeBuilderFlags | undefined): TypeNode | undefined; - /** @internal */ typeToTypeNode(type: Type, enclosingDeclaration: Node | undefined, flags: NodeBuilderFlags | undefined, tracker?: SymbolTracker): TypeNode | undefined; // eslint-disable-line @typescript-eslint/unified-signatures + typeToTypeNode( + type: Type, + enclosingDeclaration: Node | undefined, + flags: NodeBuilderFlags | undefined, + ): TypeNode | undefined; + /** @internal */ typeToTypeNode( + type: Type, + enclosingDeclaration: Node | undefined, + flags: NodeBuilderFlags | undefined, + tracker?: SymbolTracker, + ): TypeNode | undefined; // eslint-disable-line @typescript-eslint/unified-signatures /** Note that the resulting nodes cannot be checked. */ - signatureToSignatureDeclaration(signature: Signature, kind: SyntaxKind, enclosingDeclaration: Node | undefined, flags: NodeBuilderFlags | undefined): SignatureDeclaration & { typeArguments?: NodeArray; } | undefined; - /** @internal */ signatureToSignatureDeclaration(signature: Signature, kind: SyntaxKind, enclosingDeclaration: Node | undefined, flags: NodeBuilderFlags | undefined, tracker?: SymbolTracker): SignatureDeclaration & { typeArguments?: NodeArray; } | undefined; // eslint-disable-line @typescript-eslint/unified-signatures + signatureToSignatureDeclaration( + signature: Signature, + kind: SyntaxKind, + enclosingDeclaration: Node | undefined, + flags: NodeBuilderFlags | undefined, + ): SignatureDeclaration & { typeArguments?: NodeArray; } | undefined; + /** @internal */ signatureToSignatureDeclaration( + signature: Signature, + kind: SyntaxKind, + enclosingDeclaration: Node | undefined, + flags: NodeBuilderFlags | undefined, + tracker?: SymbolTracker, + ): SignatureDeclaration & { typeArguments?: NodeArray; } | undefined; // eslint-disable-line @typescript-eslint/unified-signatures /** Note that the resulting nodes cannot be checked. */ - indexInfoToIndexSignatureDeclaration(indexInfo: IndexInfo, enclosingDeclaration: Node | undefined, flags: NodeBuilderFlags | undefined): IndexSignatureDeclaration | undefined; - /** @internal */ indexInfoToIndexSignatureDeclaration(indexInfo: IndexInfo, enclosingDeclaration: Node | undefined, flags: NodeBuilderFlags | undefined, tracker?: SymbolTracker): IndexSignatureDeclaration | undefined; // eslint-disable-line @typescript-eslint/unified-signatures + indexInfoToIndexSignatureDeclaration( + indexInfo: IndexInfo, + enclosingDeclaration: Node | undefined, + flags: NodeBuilderFlags | undefined, + ): IndexSignatureDeclaration | undefined; + /** @internal */ indexInfoToIndexSignatureDeclaration( + indexInfo: IndexInfo, + enclosingDeclaration: Node | undefined, + flags: NodeBuilderFlags | undefined, + tracker?: SymbolTracker, + ): IndexSignatureDeclaration | undefined; // eslint-disable-line @typescript-eslint/unified-signatures /** Note that the resulting nodes cannot be checked. */ - symbolToEntityName(symbol: Symbol, meaning: SymbolFlags, enclosingDeclaration: Node | undefined, flags: NodeBuilderFlags | undefined): EntityName | undefined; + symbolToEntityName( + symbol: Symbol, + meaning: SymbolFlags, + enclosingDeclaration: Node | undefined, + flags: NodeBuilderFlags | undefined, + ): EntityName | undefined; /** Note that the resulting nodes cannot be checked. */ - symbolToExpression(symbol: Symbol, meaning: SymbolFlags, enclosingDeclaration: Node | undefined, flags: NodeBuilderFlags | undefined): Expression | undefined; + symbolToExpression( + symbol: Symbol, + meaning: SymbolFlags, + enclosingDeclaration: Node | undefined, + flags: NodeBuilderFlags | undefined, + ): Expression | undefined; /** * Note that the resulting nodes cannot be checked. * * @internal */ - symbolToNode(symbol: Symbol, meaning: SymbolFlags, enclosingDeclaration: Node | undefined, flags: NodeBuilderFlags | undefined): Node | undefined; + symbolToNode( + symbol: Symbol, + meaning: SymbolFlags, + enclosingDeclaration: Node | undefined, + flags: NodeBuilderFlags | undefined, + ): Node | undefined; /** Note that the resulting nodes cannot be checked. */ - symbolToTypeParameterDeclarations(symbol: Symbol, enclosingDeclaration: Node | undefined, flags: NodeBuilderFlags | undefined): NodeArray | undefined; + symbolToTypeParameterDeclarations( + symbol: Symbol, + enclosingDeclaration: Node | undefined, + flags: NodeBuilderFlags | undefined, + ): NodeArray | undefined; /** Note that the resulting nodes cannot be checked. */ - symbolToParameterDeclaration(symbol: Symbol, enclosingDeclaration: Node | undefined, flags: NodeBuilderFlags | undefined): ParameterDeclaration | undefined; + symbolToParameterDeclaration( + symbol: Symbol, + enclosingDeclaration: Node | undefined, + flags: NodeBuilderFlags | undefined, + ): ParameterDeclaration | undefined; /** Note that the resulting nodes cannot be checked. */ - typeParameterToDeclaration(parameter: TypeParameter, enclosingDeclaration: Node | undefined, flags: NodeBuilderFlags | undefined): TypeParameterDeclaration | undefined; + typeParameterToDeclaration( + parameter: TypeParameter, + enclosingDeclaration: Node | undefined, + flags: NodeBuilderFlags | undefined, + ): TypeParameterDeclaration | undefined; getSymbolsInScope(location: Node, meaning: SymbolFlags): Symbol[]; getSymbolAtLocation(node: Node): Symbol | undefined; @@ -4948,15 +5122,47 @@ export interface TypeChecker { getTypeAtLocation(node: Node): Type; getTypeFromTypeNode(node: TypeNode): Type; - signatureToString(signature: Signature, enclosingDeclaration?: Node, flags?: TypeFormatFlags, kind?: SignatureKind): string; + signatureToString( + signature: Signature, + enclosingDeclaration?: Node, + flags?: TypeFormatFlags, + kind?: SignatureKind, + ): string; typeToString(type: Type, enclosingDeclaration?: Node, flags?: TypeFormatFlags): string; - symbolToString(symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags, flags?: SymbolFormatFlags): string; + symbolToString( + symbol: Symbol, + enclosingDeclaration?: Node, + meaning?: SymbolFlags, + flags?: SymbolFormatFlags, + ): string; typePredicateToString(predicate: TypePredicate, enclosingDeclaration?: Node, flags?: TypeFormatFlags): string; - /** @internal */ writeSignature(signature: Signature, enclosingDeclaration?: Node, flags?: TypeFormatFlags, kind?: SignatureKind, writer?: EmitTextWriter): string; - /** @internal */ writeType(type: Type, enclosingDeclaration?: Node, flags?: TypeFormatFlags, writer?: EmitTextWriter): string; - /** @internal */ writeSymbol(symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags, flags?: SymbolFormatFlags, writer?: EmitTextWriter): string; - /** @internal */ writeTypePredicate(predicate: TypePredicate, enclosingDeclaration?: Node, flags?: TypeFormatFlags, writer?: EmitTextWriter): string; + /** @internal */ writeSignature( + signature: Signature, + enclosingDeclaration?: Node, + flags?: TypeFormatFlags, + kind?: SignatureKind, + writer?: EmitTextWriter, + ): string; + /** @internal */ writeType( + type: Type, + enclosingDeclaration?: Node, + flags?: TypeFormatFlags, + writer?: EmitTextWriter, + ): string; + /** @internal */ writeSymbol( + symbol: Symbol, + enclosingDeclaration?: Node, + meaning?: SymbolFlags, + flags?: SymbolFormatFlags, + writer?: EmitTextWriter, + ): string; + /** @internal */ writeTypePredicate( + predicate: TypePredicate, + enclosingDeclaration?: Node, + flags?: TypeFormatFlags, + writer?: EmitTextWriter, + ): string; getFullyQualifiedName(symbol: Symbol): string; getAugmentedPropertiesOfType(type: Type): Symbol[]; @@ -4968,7 +5174,9 @@ export interface TypeChecker { /** @internal */ getContextualTypeForObjectLiteralElement(element: ObjectLiteralElementLike): Type | undefined; /** @internal */ getContextualTypeForArgumentAtIndex(call: CallLikeExpression, argIndex: number): Type | undefined; /** @internal */ getContextualTypeForJsxAttribute(attribute: JsxAttribute | JsxSpreadAttribute): Type | undefined; - /** @internal */ isContextSensitive(node: Expression | MethodDeclaration | ObjectLiteralElementLike | JsxAttributeLike): boolean; + /** @internal */ isContextSensitive( + node: Expression | MethodDeclaration | ObjectLiteralElementLike | JsxAttributeLike, + ): boolean; /** @internal */ getTypeOfPropertyOfContextualType(type: Type, name: __String): Type | undefined; /** @@ -4976,9 +5184,22 @@ export interface TypeChecker { * returns undefined if the node is not valid. * @param argumentCount Apparent number of arguments, passed in case of a possibly incomplete call. This should come from an ArgumentListInfo. See `signatureHelp.ts`. */ - getResolvedSignature(node: CallLikeExpression, candidatesOutArray?: Signature[], argumentCount?: number): Signature | undefined; - /** @internal */ getResolvedSignatureForSignatureHelp(node: CallLikeExpression, candidatesOutArray?: Signature[], argumentCount?: number): Signature | undefined; - /** @internal */ getResolvedSignatureForStringLiteralCompletions(call: CallLikeExpression, editingArgument: Node, candidatesOutArray: Signature[], checkMode?: CheckMode): Signature | undefined; + getResolvedSignature( + node: CallLikeExpression, + candidatesOutArray?: Signature[], + argumentCount?: number, + ): Signature | undefined; + /** @internal */ getResolvedSignatureForSignatureHelp( + node: CallLikeExpression, + candidatesOutArray?: Signature[], + argumentCount?: number, + ): Signature | undefined; + /** @internal */ getResolvedSignatureForStringLiteralCompletions( + call: CallLikeExpression, + editingArgument: Node, + candidatesOutArray: Signature[], + checkMode?: CheckMode, + ): Signature | undefined; /** @internal */ getExpandedParameters(sig: Signature): readonly (readonly Symbol[])[]; /** @internal */ hasEffectiveRestParameter(sig: Signature): boolean; /** @internal */ containsArgumentsReference(declaration: SignatureDeclaration): boolean; @@ -4990,14 +5211,23 @@ export interface TypeChecker { isUnknownSymbol(symbol: Symbol): boolean; /** @internal */ getMergedSymbol(symbol: Symbol): Symbol; - getConstantValue(node: EnumMember | PropertyAccessExpression | ElementAccessExpression): string | number | undefined; - isValidPropertyAccess(node: PropertyAccessExpression | QualifiedName | ImportTypeNode, propertyName: string): boolean; + getConstantValue( + node: EnumMember | PropertyAccessExpression | ElementAccessExpression, + ): string | number | undefined; + isValidPropertyAccess( + node: PropertyAccessExpression | QualifiedName | ImportTypeNode, + propertyName: string, + ): boolean; /** * Exclude accesses to private properties. * * @internal */ - isValidPropertyAccessForCompletions(node: PropertyAccessExpression | ImportTypeNode | QualifiedName, type: Type, property: Symbol): boolean; + isValidPropertyAccessForCompletions( + node: PropertyAccessExpression | ImportTypeNode | QualifiedName, + type: Type, + property: Symbol, + ): boolean; /** Follow all aliases to get the original symbol. */ getAliasedSymbol(symbol: Symbol): Symbol; /** Follow a *single* alias to get the immediately aliased symbol. */ @@ -5009,7 +5239,10 @@ export interface TypeChecker { * @internal */ getExportsAndPropertiesOfModule(moduleSymbol: Symbol): Symbol[]; - /** @internal */ forEachExportAndPropertyOfModule(moduleSymbol: Symbol, cb: (symbol: Symbol, key: __String) => void): void; + /** @internal */ forEachExportAndPropertyOfModule( + moduleSymbol: Symbol, + cb: (symbol: Symbol, key: __String) => void, + ): void; getJsxIntrinsicTagNamesAt(location: Node): Symbol[]; isOptionalParameter(node: ParameterDeclaration): boolean; getAmbientModules(): Symbol[]; @@ -5023,11 +5256,28 @@ export interface TypeChecker { */ tryGetMemberInModuleExportsAndProperties(memberName: string, moduleSymbol: Symbol): Symbol | undefined; getApparentType(type: Type): Type; - /** @internal */ getSuggestedSymbolForNonexistentProperty(name: MemberName | string, containingType: Type): Symbol | undefined; - /** @internal */ getSuggestedSymbolForNonexistentJSXAttribute(name: Identifier | string, containingType: Type): Symbol | undefined; - /** @internal */ getSuggestionForNonexistentProperty(name: MemberName | string, containingType: Type): string | undefined; - /** @internal */ getSuggestedSymbolForNonexistentSymbol(location: Node, name: string, meaning: SymbolFlags): Symbol | undefined; - /** @internal */ getSuggestionForNonexistentSymbol(location: Node, name: string, meaning: SymbolFlags): string | undefined; + /** @internal */ getSuggestedSymbolForNonexistentProperty( + name: MemberName | string, + containingType: Type, + ): Symbol | undefined; + /** @internal */ getSuggestedSymbolForNonexistentJSXAttribute( + name: Identifier | string, + containingType: Type, + ): Symbol | undefined; + /** @internal */ getSuggestionForNonexistentProperty( + name: MemberName | string, + containingType: Type, + ): string | undefined; + /** @internal */ getSuggestedSymbolForNonexistentSymbol( + location: Node, + name: string, + meaning: SymbolFlags, + ): Symbol | undefined; + /** @internal */ getSuggestionForNonexistentSymbol( + location: Node, + name: string, + meaning: SymbolFlags, + ): string | undefined; /** @internal */ getSuggestedSymbolForNonexistentModule(node: Identifier, target: Symbol): Symbol | undefined; /** @internal */ getSuggestedSymbolForNonexistentClassMember(name: string, baseType: Type): Symbol | undefined; /** @internal */ getSuggestionForNonexistentExport(node: Identifier, target: Symbol): string | undefined; @@ -5084,7 +5334,13 @@ export interface TypeChecker { /** @internal */ getAsyncIterableType(): Type | undefined; /** @internal */ isTypeAssignableTo(source: Type, target: Type): boolean; - /** @internal */ createAnonymousType(symbol: Symbol | undefined, members: SymbolTable, callSignatures: Signature[], constructSignatures: Signature[], indexInfos: IndexInfo[]): Type; + /** @internal */ createAnonymousType( + symbol: Symbol | undefined, + members: SymbolTable, + callSignatures: Signature[], + constructSignatures: Signature[], + indexInfos: IndexInfo[], + ): Type; /** @internal */ createSignature( declaration: SignatureDeclaration | undefined, typeParameters: readonly TypeParameter[] | undefined, @@ -5096,8 +5352,18 @@ export interface TypeChecker { flags: SignatureFlags, ): Signature; /** @internal */ createSymbol(flags: SymbolFlags, name: __String): TransientSymbol; - /** @internal */ createIndexInfo(keyType: Type, type: Type, isReadonly: boolean, declaration?: SignatureDeclaration): IndexInfo; - /** @internal */ isSymbolAccessible(symbol: Symbol, enclosingDeclaration: Node | undefined, meaning: SymbolFlags, shouldComputeAliasToMarkVisible: boolean): SymbolAccessibilityResult; + /** @internal */ createIndexInfo( + keyType: Type, + type: Type, + isReadonly: boolean, + declaration?: SignatureDeclaration, + ): IndexInfo; + /** @internal */ isSymbolAccessible( + symbol: Symbol, + enclosingDeclaration: Node | undefined, + meaning: SymbolFlags, + shouldComputeAliasToMarkVisible: boolean, + ): SymbolAccessibilityResult; /** @internal */ tryFindAmbientModule(moduleName: string): Symbol | undefined; /** @internal */ tryFindAmbientModuleWithoutAugmentations(moduleName: string): Symbol | undefined; @@ -5113,9 +5379,19 @@ export interface TypeChecker { /** @internal */ getSymbolCount(): number; /** @internal */ getTypeCount(): number; /** @internal */ getInstantiationCount(): number; - /** @internal */ getRelationCacheSizes(): { assignable: number; identity: number; subtype: number; strictSubtype: number; }; + /** @internal */ getRelationCacheSizes(): { + assignable: number; + identity: number; + subtype: number; + strictSubtype: number; + }; /** @internal */ getRecursionIdentity(type: Type): object | undefined; - /** @internal */ getUnmatchedProperties(source: Type, target: Type, requireOptionalProperties: boolean, matchDiscriminantProperties: boolean): IterableIterator; + /** @internal */ getUnmatchedProperties( + source: Type, + target: Type, + requireOptionalProperties: boolean, + matchDiscriminantProperties: boolean, + ): IterableIterator; /** * True if this type is the `Array` or `ReadonlyArray` type from lib.d.ts. @@ -5149,7 +5425,12 @@ export interface TypeChecker { * @internal */ getAllPossiblePropertiesOfTypes(type: readonly Type[]): Symbol[]; - /** @internal */ resolveName(name: string, location: Node | undefined, meaning: SymbolFlags, excludeGlobals: boolean): Symbol | undefined; + /** @internal */ resolveName( + name: string, + location: Node | undefined, + meaning: SymbolFlags, + excludeGlobals: boolean, + ): Symbol | undefined; /** @internal */ getJsxNamespace(location?: Node): string; /** @internal */ getJsxFragmentFactory(location: Node): string | undefined; @@ -5164,7 +5445,12 @@ export interface TypeChecker { * * @internal */ - getAccessibleSymbolChain(symbol: Symbol, enclosingDeclaration: Node | undefined, meaning: SymbolFlags, useOnlyExternalAliasing: boolean): Symbol[] | undefined; + getAccessibleSymbolChain( + symbol: Symbol, + enclosingDeclaration: Node | undefined, + meaning: SymbolFlags, + useOnlyExternalAliasing: boolean, + ): Symbol[] | undefined; getTypePredicateOfSignature(signature: Signature): TypePredicate | undefined; /** @internal */ resolveExternalModuleName(moduleSpecifier: Expression): Symbol | undefined; /** @@ -5188,7 +5474,10 @@ export interface TypeChecker { * * @internal */ - getSuggestionDiagnostics(file: SourceFile, cancellationToken?: CancellationToken): readonly DiagnosticWithLocation[]; + getSuggestionDiagnostics( + file: SourceFile, + cancellationToken?: CancellationToken, + ): readonly DiagnosticWithLocation[]; /** * Depending on the operation performed, it may be appropriate to throw away the checker @@ -5197,11 +5486,23 @@ export interface TypeChecker { */ runWithCancellationToken(token: CancellationToken, cb: (checker: TypeChecker) => T): T; - /** @internal */ getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(symbol: Symbol): readonly TypeParameter[] | undefined; + /** @internal */ getLocalTypeParametersOfClassOrInterfaceOrTypeAlias( + symbol: Symbol, + ): readonly TypeParameter[] | undefined; /** @internal */ isDeclarationVisible(node: Declaration | AnyImportSyntax): boolean; - /** @internal */ isPropertyAccessible(node: Node, isSuper: boolean, isWrite: boolean, containingType: Type, property: Symbol): boolean; + /** @internal */ isPropertyAccessible( + node: Node, + isSuper: boolean, + isWrite: boolean, + containingType: Type, + property: Symbol, + ): boolean; /** @internal */ getTypeOnlyAliasDeclaration(symbol: Symbol): TypeOnlyAliasDeclaration | undefined; - /** @internal */ getMemberOverrideModifierStatus(node: ClassLikeDeclaration, member: ClassElement, memberSymbol: Symbol): MemberOverrideStatus; + /** @internal */ getMemberOverrideModifierStatus( + node: ClassLikeDeclaration, + member: ClassElement, + memberSymbol: Symbol, + ): MemberOverrideStatus; /** @internal */ isTypeParameterPossiblyReferenced(tp: TypeParameter, node: Node): boolean; /** @internal */ typeHasCallOrConstructSignatures(type: Type): boolean; } @@ -5266,7 +5567,8 @@ export const enum NodeBuilderFlags { AllowNodeModulesRelativePaths = 1 << 26, /** @internal */ DoNotIncludeSymbolChain = 1 << 27, // Skip looking up and printing an accessible symbol chain - IgnoreErrors = AllowThisInObjectLiteral | AllowQualifiedNameInPlaceOfIdentifier | AllowAnonymousIdentifier | AllowEmptyUnionOrIntersection | AllowEmptyTuple | AllowEmptyIndexInfoType | AllowNodeModulesRelativePaths, + IgnoreErrors = AllowThisInObjectLiteral | AllowQualifiedNameInPlaceOfIdentifier | AllowAnonymousIdentifier + | AllowEmptyUnionOrIntersection | AllowEmptyTuple | AllowEmptyIndexInfoType | AllowNodeModulesRelativePaths, // State InObjectTypeLiteral = 1 << 22, @@ -5310,10 +5612,12 @@ export const enum TypeFormatFlags { InFirstTypeArgument = 1 << 22, // Writing first type argument of the instantiated type InTypeAlias = 1 << 23, // Writing type in type alias declaration - NodeBuilderFlagsMask = NoTruncation | WriteArrayAsGenericType | UseStructuralFallback | WriteTypeArgumentsOfSignature | - UseFullyQualifiedType | SuppressAnyReturnType | MultilineObjectLiterals | WriteClassExpressionAsTypeLiteral | - UseTypeOfFunction | OmitParameterModifiers | UseAliasDefinedOutsideCurrentScope | AllowUniqueESSymbolType | InTypeAlias | - UseSingleQuotesForStringLiteralType | NoTypeReduction | OmitThisParameter, + NodeBuilderFlagsMask = NoTruncation | WriteArrayAsGenericType | UseStructuralFallback + | WriteTypeArgumentsOfSignature + | UseFullyQualifiedType | SuppressAnyReturnType | MultilineObjectLiterals | WriteClassExpressionAsTypeLiteral + | UseTypeOfFunction | OmitParameterModifiers | UseAliasDefinedOutsideCurrentScope | AllowUniqueESSymbolType + | InTypeAlias + | UseSingleQuotesForStringLiteralType | NoTypeReduction | OmitThisParameter, } export const enum SymbolFormatFlags { @@ -5421,7 +5725,11 @@ export interface AssertsIdentifierTypePredicate extends TypePredicateBase { type: Type | undefined; } -export type TypePredicate = ThisTypePredicate | IdentifierTypePredicate | AssertsThisTypePredicate | AssertsIdentifierTypePredicate; +export type TypePredicate = + | ThisTypePredicate + | IdentifierTypePredicate + | AssertsThisTypePredicate + | AssertsIdentifierTypePredicate; /** @internal */ export type AnyImportSyntax = ImportDeclaration | ImportEqualsDeclaration; @@ -5430,7 +5738,9 @@ export type AnyImportSyntax = ImportDeclaration | ImportEqualsDeclaration; export type AnyImportOrRequire = AnyImportSyntax | VariableDeclarationInitializedTo; /** @internal */ -export type AnyImportOrBareOrAccessedRequire = AnyImportSyntax | VariableDeclarationInitializedTo; +export type AnyImportOrBareOrAccessedRequire = + | AnyImportSyntax + | VariableDeclarationInitializedTo; /** @internal */ export type AliasDeclarationNode = @@ -5447,7 +5757,9 @@ export type AliasDeclarationNode = | BindingElementOfBareOrAccessedRequire; /** @internal */ -export type BindingElementOfBareOrAccessedRequire = BindingElement & { parent: { parent: VariableDeclarationInitializedTo; }; }; +export type BindingElementOfBareOrAccessedRequire = BindingElement & { + parent: { parent: VariableDeclarationInitializedTo; }; +}; /** @internal */ export type AnyImportOrRequireStatement = AnyImportSyntax | RequireVariableStatement; @@ -5575,7 +5887,10 @@ export enum TypeReferenceSerializationKind { /** @internal */ export interface EmitResolver { hasGlobalName(name: string): boolean; - getReferencedExportContainer(node: Identifier, prefixLocals?: boolean): SourceFile | ModuleDeclaration | EnumDeclaration | undefined; + getReferencedExportContainer( + node: Identifier, + prefixLocals?: boolean, + ): SourceFile | ModuleDeclaration | EnumDeclaration | undefined; getReferencedImportDeclaration(node: Identifier): Declaration | undefined; getReferencedDeclarationWithCollidingName(node: Identifier): Declaration | undefined; isDeclarationWithCollidingName(node: Declaration): boolean; @@ -5591,30 +5906,84 @@ export interface EmitResolver { isOptionalUninitializedParameterProperty(node: ParameterDeclaration): boolean; isExpandoFunctionDeclaration(node: FunctionDeclaration): boolean; getPropertiesOfContainerFunction(node: Declaration): Symbol[]; - createTypeOfDeclaration(declaration: AccessorDeclaration | VariableLikeDeclaration | PropertyAccessExpression | ElementAccessExpression | BinaryExpression, enclosingDeclaration: Node, flags: NodeBuilderFlags, tracker: SymbolTracker, addUndefined?: boolean): TypeNode | undefined; - createReturnTypeOfSignatureDeclaration(signatureDeclaration: SignatureDeclaration, enclosingDeclaration: Node, flags: NodeBuilderFlags, tracker: SymbolTracker): TypeNode | undefined; - createTypeOfExpression(expr: Expression, enclosingDeclaration: Node, flags: NodeBuilderFlags, tracker: SymbolTracker): TypeNode | undefined; - createLiteralConstValue(node: VariableDeclaration | PropertyDeclaration | PropertySignature | ParameterDeclaration, tracker: SymbolTracker): Expression; - isSymbolAccessible(symbol: Symbol, enclosingDeclaration: Node | undefined, meaning: SymbolFlags | undefined, shouldComputeAliasToMarkVisible: boolean): SymbolAccessibilityResult; - isEntityNameVisible(entityName: EntityNameOrEntityNameExpression, enclosingDeclaration: Node): SymbolVisibilityResult; + createTypeOfDeclaration( + declaration: + | AccessorDeclaration + | VariableLikeDeclaration + | PropertyAccessExpression + | ElementAccessExpression + | BinaryExpression, + enclosingDeclaration: Node, + flags: NodeBuilderFlags, + tracker: SymbolTracker, + addUndefined?: boolean, + ): TypeNode | undefined; + createReturnTypeOfSignatureDeclaration( + signatureDeclaration: SignatureDeclaration, + enclosingDeclaration: Node, + flags: NodeBuilderFlags, + tracker: SymbolTracker, + ): TypeNode | undefined; + createTypeOfExpression( + expr: Expression, + enclosingDeclaration: Node, + flags: NodeBuilderFlags, + tracker: SymbolTracker, + ): TypeNode | undefined; + createLiteralConstValue( + node: VariableDeclaration | PropertyDeclaration | PropertySignature | ParameterDeclaration, + tracker: SymbolTracker, + ): Expression; + isSymbolAccessible( + symbol: Symbol, + enclosingDeclaration: Node | undefined, + meaning: SymbolFlags | undefined, + shouldComputeAliasToMarkVisible: boolean, + ): SymbolAccessibilityResult; + isEntityNameVisible( + entityName: EntityNameOrEntityNameExpression, + enclosingDeclaration: Node, + ): SymbolVisibilityResult; // Returns the constant value this property access resolves to, or 'undefined' for a non-constant - getConstantValue(node: EnumMember | PropertyAccessExpression | ElementAccessExpression): string | number | undefined; + getConstantValue( + node: EnumMember | PropertyAccessExpression | ElementAccessExpression, + ): string | number | undefined; getReferencedValueDeclaration(reference: Identifier): Declaration | undefined; getReferencedValueDeclarations(reference: Identifier): Declaration[] | undefined; getTypeReferenceSerializationKind(typeName: EntityName, location?: Node): TypeReferenceSerializationKind; isOptionalParameter(node: ParameterDeclaration): boolean; moduleExportsSomeValue(moduleReferenceExpression: Expression): boolean; isArgumentsLocalBinding(node: Identifier): boolean; - getExternalModuleFileFromDeclaration(declaration: ImportEqualsDeclaration | ImportDeclaration | ExportDeclaration | ModuleDeclaration | ImportTypeNode | ImportCall): SourceFile | undefined; - getTypeReferenceDirectivesForEntityName(name: EntityNameOrEntityNameExpression): [specifier: string, mode: ResolutionMode][] | undefined; - getTypeReferenceDirectivesForSymbol(symbol: Symbol, meaning?: SymbolFlags): [specifier: string, mode: ResolutionMode][] | undefined; - isLiteralConstDeclaration(node: VariableDeclaration | PropertyDeclaration | PropertySignature | ParameterDeclaration): boolean; + getExternalModuleFileFromDeclaration( + declaration: + | ImportEqualsDeclaration + | ImportDeclaration + | ExportDeclaration + | ModuleDeclaration + | ImportTypeNode + | ImportCall, + ): SourceFile | undefined; + getTypeReferenceDirectivesForEntityName( + name: EntityNameOrEntityNameExpression, + ): [specifier: string, mode: ResolutionMode][] | undefined; + getTypeReferenceDirectivesForSymbol( + symbol: Symbol, + meaning?: SymbolFlags, + ): [specifier: string, mode: ResolutionMode][] | undefined; + isLiteralConstDeclaration( + node: VariableDeclaration | PropertyDeclaration | PropertySignature | ParameterDeclaration, + ): boolean; getJsxFactoryEntity(location?: Node): EntityName | undefined; getJsxFragmentFactoryEntity(location?: Node): EntityName | undefined; getAllAccessorDeclarations(declaration: AccessorDeclaration): AllAccessorDeclarations; getSymbolOfExternalModuleSpecifier(node: StringLiteralLike): Symbol | undefined; isBindingCapturedByNode(node: Node, decl: VariableDeclaration | BindingElement): boolean; - getDeclarationStatementsForSourceFile(node: SourceFile, flags: NodeBuilderFlags, tracker: SymbolTracker, bundled?: boolean): Statement[] | undefined; + getDeclarationStatementsForSourceFile( + node: SourceFile, + flags: NodeBuilderFlags, + tracker: SymbolTracker, + bundled?: boolean, + ): Statement[] | undefined; isImportRequiredByAugmentation(decl: ImportDeclaration): boolean; } @@ -5649,12 +6018,15 @@ export const enum SymbolFlags { Assignment = 1 << 26, // Assignment treated as declaration (eg `this.prop = 1`) ModuleExports = 1 << 27, // Symbol for CommonJS `module` of `module.exports` /** @internal */ - All = FunctionScopedVariable | BlockScopedVariable | Property | EnumMember | Function | Class | Interface | ConstEnum | RegularEnum | ValueModule | NamespaceModule | TypeLiteral - | ObjectLiteral | Method | Constructor | GetAccessor | SetAccessor | Signature | TypeParameter | TypeAlias | ExportValue | Alias | Prototype | ExportStar | Optional | Transient, + All = FunctionScopedVariable | BlockScopedVariable | Property | EnumMember | Function | Class | Interface + | ConstEnum | RegularEnum | ValueModule | NamespaceModule | TypeLiteral + | ObjectLiteral | Method | Constructor | GetAccessor | SetAccessor | Signature | TypeParameter | TypeAlias + | ExportValue | Alias | Prototype | ExportStar | Optional | Transient, Enum = RegularEnum | ConstEnum, Variable = FunctionScopedVariable | BlockScopedVariable, - Value = Variable | Property | EnumMember | ObjectLiteral | Function | Class | Enum | ValueModule | Method | GetAccessor | SetAccessor, + Value = Variable | Property | EnumMember | ObjectLiteral | Function | Class | Enum | ValueModule | Method + | GetAccessor | SetAccessor, Type = Class | Interface | Enum | EnumMember | TypeLiteral | TypeParameter | TypeAlias, Namespace = ValueModule | NamespaceModule | Enum, Module = ValueModule | NamespaceModule, @@ -5777,7 +6149,10 @@ export interface SymbolLinks { deferralParent?: Type; // Source union/intersection of a deferred type cjsExportMerged?: Symbol; // Version of the symbol with all non export= exports merged with the export= target typeOnlyDeclaration?: TypeOnlyAliasDeclaration | false; // First resolved alias declaration that makes the symbol only usable in type constructs - typeOnlyExportStarMap?: Map<__String, ExportDeclaration & { readonly isTypeOnly: true; readonly moduleSpecifier: Expression; }>; // Set on a module symbol when some of its exports were resolved through a 'export type * from "mod"' declaration + typeOnlyExportStarMap?: Map< + __String, + ExportDeclaration & { readonly isTypeOnly: true; readonly moduleSpecifier: Expression; } + >; // Set on a module symbol when some of its exports were resolved through a 'export type * from "mod"' declaration typeOnlyExportStarName?: __String; // Set to the name of the symbol re-exported by an 'export type *' declaration, when different from the symbol name isConstructorDeclaredProperty?: boolean; // Property declared through 'this.x = ...' assignment in constructor tupleLabelDeclaration?: NamedTupleMember | ParameterDeclaration; // Declaration associated with the tuple's label @@ -5881,7 +6256,10 @@ export const enum InternalSymbolName { * with a normal string (which is good, it cannot be misused on assignment or on usage), * while still being comparable with a normal string via === (also good) and castable from a string. */ -export type __String = (string & { __escapedIdentifier: void; }) | (void & { __escapedIdentifier: void; }) | InternalSymbolName; +export type __String = + | (string & { __escapedIdentifier: void; }) + | (void & { __escapedIdentifier: void; }) + | InternalSymbolName; /** @deprecated Use ReadonlyMap<__String, T> instead. */ export type ReadonlyUnderscoreEscapedMap = ReadonlyMap<__String, T>; @@ -6017,7 +6395,8 @@ export const enum TypeFlags { DefinitelyFalsy = StringLiteral | NumberLiteral | BigIntLiteral | BooleanLiteral | Void | Undefined | Null, PossiblyFalsy = DefinitelyFalsy | String | Number | BigInt | Boolean, /** @internal */ - Intrinsic = Any | Unknown | String | Number | BigInt | Boolean | BooleanLiteral | ESSymbol | Void | Undefined | Null | Never | NonPrimitive, + Intrinsic = Any | Unknown | String | Number | BigInt | Boolean | BooleanLiteral | ESSymbol | Void | Undefined | Null + | Never | NonPrimitive, StringLike = String | StringLiteral | TemplateLiteral | StringMapping, NumberLike = Number | NumberLiteral | Enum, BigIntLike = BigInt | BigIntLiteral, @@ -6028,9 +6407,11 @@ export const enum TypeFlags { /** @internal */ Primitive = StringLike | NumberLike | BigIntLike | BooleanLike | EnumLike | ESSymbolLike | VoidLike | Null, /** @internal */ - DefinitelyNonNullable = StringLike | NumberLike | BigIntLike | BooleanLike | EnumLike | ESSymbolLike | Object | NonPrimitive, + DefinitelyNonNullable = StringLike | NumberLike | BigIntLike | BooleanLike | EnumLike | ESSymbolLike | Object + | NonPrimitive, /** @internal */ - DisjointDomains = NonPrimitive | StringLike | NumberLike | BigIntLike | BooleanLike | ESSymbolLike | VoidLike | Null, + DisjointDomains = NonPrimitive | StringLike | NumberLike | BigIntLike | BooleanLike | ESSymbolLike | VoidLike + | Null, UnionOrIntersection = Union | Intersection, StructuredType = Object | Union | Intersection, TypeVariable = TypeParameter | IndexedAccess, @@ -6043,10 +6424,12 @@ export const enum TypeFlags { /** @internal */ Simplifiable = IndexedAccess | Conditional, /** @internal */ - Singleton = Any | Unknown | String | Number | Boolean | BigInt | ESSymbol | Void | Undefined | Null | Never | NonPrimitive, + Singleton = Any | Unknown | String | Number | Boolean | BigInt | ESSymbol | Void | Undefined | Null | Never + | NonPrimitive, // 'Narrowable' types are types where narrowing actually narrows. // This *should* be every type other than null, undefined, void, and never - Narrowable = Any | Unknown | StructuredOrInstantiable | StringLike | NumberLike | BigIntLike | BooleanLike | ESSymbol | UniqueESSymbol | NonPrimitive, + Narrowable = Any | Unknown | StructuredOrInstantiable | StringLike | NumberLike | BigIntLike | BooleanLike + | ESSymbol | UniqueESSymbol | NonPrimitive, // The following flags are aggregated during union and intersection type construction /** @internal */ IncludesMask = Any | Unknown | Primitive | Never | Object | Union | Intersection | NonPrimitive | TemplateLiteral, @@ -6626,7 +7009,8 @@ export const enum SignatureFlags { // We do not propagate `IsInnerCallChain` or `IsOuterCallChain` to instantiated signatures, as that would result in us // attempting to add `| undefined` on each recursive call to `getReturnTypeOfSignature` when // instantiating the return type. - PropagatingFlags = HasRestParameter | HasLiteralTypes | Abstract | IsUntypedSignatureInJSFile | IsSignatureCandidateForOverloadFailure, + PropagatingFlags = HasRestParameter | HasLiteralTypes | Abstract | IsUntypedSignatureInJSFile + | IsSignatureCandidateForOverloadFailure, CallChainFlags = IsInnerCallChain | IsOuterCallChain, } @@ -6981,7 +7365,17 @@ export enum PollingWatchKind { FixedChunkSize, } -export type CompilerOptionsValue = string | number | boolean | (string | number)[] | string[] | MapLike | PluginImport[] | ProjectReference[] | null | undefined; +export type CompilerOptionsValue = + | string + | number + | boolean + | (string | number)[] + | string[] + | MapLike + | PluginImport[] + | ProjectReference[] + | null + | undefined; export interface CompilerOptions { /** @internal */ all?: boolean; @@ -7364,12 +7758,23 @@ export interface TsConfigOnlyOption extends CommandLineOptionBase { /** @internal */ export interface CommandLineOptionOfListType extends CommandLineOptionBase { type: "list" | "listOrElement"; - element: CommandLineOptionOfCustomType | CommandLineOptionOfStringType | CommandLineOptionOfNumberType | CommandLineOptionOfBooleanType | TsConfigOnlyOption; + element: + | CommandLineOptionOfCustomType + | CommandLineOptionOfStringType + | CommandLineOptionOfNumberType + | CommandLineOptionOfBooleanType + | TsConfigOnlyOption; listPreserveFalsyValues?: boolean; } /** @internal */ -export type CommandLineOption = CommandLineOptionOfCustomType | CommandLineOptionOfStringType | CommandLineOptionOfNumberType | CommandLineOptionOfBooleanType | TsConfigOnlyOption | CommandLineOptionOfListType; +export type CommandLineOption = + | CommandLineOptionOfCustomType + | CommandLineOptionOfStringType + | CommandLineOptionOfNumberType + | CommandLineOptionOfBooleanType + | TsConfigOnlyOption + | CommandLineOptionOfListType; /** @internal */ export const enum CharacterCodes { @@ -7659,8 +8064,19 @@ export type HasInvalidatedLibResolutions = (libFileName: string) => boolean; export type HasChangedAutomaticTypeDirectiveNames = () => boolean; export interface CompilerHost extends ModuleResolutionHost { - getSourceFile(fileName: string, languageVersionOrOptions: ScriptTarget | CreateSourceFileOptions, onError?: (message: string) => void, shouldCreateNewSourceFile?: boolean): SourceFile | undefined; - getSourceFileByPath?(fileName: string, path: Path, languageVersionOrOptions: ScriptTarget | CreateSourceFileOptions, onError?: (message: string) => void, shouldCreateNewSourceFile?: boolean): SourceFile | undefined; + getSourceFile( + fileName: string, + languageVersionOrOptions: ScriptTarget | CreateSourceFileOptions, + onError?: (message: string) => void, + shouldCreateNewSourceFile?: boolean, + ): SourceFile | undefined; + getSourceFileByPath?( + fileName: string, + path: Path, + languageVersionOrOptions: ScriptTarget | CreateSourceFileOptions, + onError?: (message: string) => void, + shouldCreateNewSourceFile?: boolean, + ): SourceFile | undefined; getCancellationToken?(): CancellationToken; getDefaultLibFileName(options: CompilerOptions): string; getDefaultLibLocation?(): string; @@ -7669,7 +8085,13 @@ export interface CompilerHost extends ModuleResolutionHost { getCanonicalFileName(fileName: string): string; useCaseSensitiveFileNames(): boolean; getNewLine(): string; - readDirectory?(rootDir: string, extensions: readonly string[], excludes: readonly string[] | undefined, includes: readonly string[], depth?: number): string[]; + readDirectory?( + rootDir: string, + extensions: readonly string[], + excludes: readonly string[] | undefined, + includes: readonly string[], + depth?: number, + ): string[]; /* * CompilerHost must either implement resolveModuleNames (in case if it wants to be completely in charge of @@ -7679,7 +8101,14 @@ export interface CompilerHost extends ModuleResolutionHost { * 'throw new Error("NotImplemented")' */ /** @deprecated supply resolveModuleNameLiterals instead for resolution that can handle newer resolution modes like nodenext */ - resolveModuleNames?(moduleNames: string[], containingFile: string, reusedNames: string[] | undefined, redirectedReference: ResolvedProjectReference | undefined, options: CompilerOptions, containingSourceFile?: SourceFile): (ResolvedModule | undefined)[]; + resolveModuleNames?( + moduleNames: string[], + containingFile: string, + reusedNames: string[] | undefined, + redirectedReference: ResolvedProjectReference | undefined, + options: CompilerOptions, + containingSourceFile?: SourceFile, + ): (ResolvedModule | undefined)[]; /** * Returns the module resolution cache used by a provided `resolveModuleNames` implementation so that any non-name module resolution operations (eg, package.json lookup) can reuse it */ @@ -7689,7 +8118,13 @@ export interface CompilerHost extends ModuleResolutionHost { * * This method is a companion for 'resolveModuleNames' and is used to resolve 'types' references to actual type declaration files */ - resolveTypeReferenceDirectives?(typeReferenceDirectiveNames: string[] | readonly FileReference[], containingFile: string, redirectedReference: ResolvedProjectReference | undefined, options: CompilerOptions, containingFileMode?: ResolutionMode): (ResolvedTypeReferenceDirective | undefined)[]; + resolveTypeReferenceDirectives?( + typeReferenceDirectiveNames: string[] | readonly FileReference[], + containingFile: string, + redirectedReference: ResolvedProjectReference | undefined, + options: CompilerOptions, + containingFileMode?: ResolutionMode, + ): (ResolvedTypeReferenceDirective | undefined)[]; resolveModuleNameLiterals?( moduleLiterals: readonly StringLiteralLike[], containingFile: string, @@ -7719,8 +8154,16 @@ export interface CompilerHost extends ModuleResolutionHost { */ hasInvalidatedLibResolutions?(libFileName: string): boolean; getEnvironmentVariable?(name: string): string | undefined; - /** @internal */ onReleaseOldSourceFile?(oldSourceFile: SourceFile, oldOptions: CompilerOptions, hasSourceFileByPath: boolean): void; - /** @internal */ onReleaseParsedCommandLine?(configFileName: string, oldResolvedRef: ResolvedProjectReference | undefined, optionOptions: CompilerOptions): void; + /** @internal */ onReleaseOldSourceFile?( + oldSourceFile: SourceFile, + oldOptions: CompilerOptions, + hasSourceFileByPath: boolean, + ): void; + /** @internal */ onReleaseParsedCommandLine?( + configFileName: string, + oldResolvedRef: ResolvedProjectReference | undefined, + optionOptions: CompilerOptions, + ): void; /** If provided along with custom resolveModuleNames or resolveTypeReferenceDirectives, used to determine if unchanged file path needs to re-resolve modules/type reference directives */ hasInvalidatedResolutions?(filePath: Path): boolean; /** @internal */ hasChangedAutomaticTypeDirectiveNames?: HasChangedAutomaticTypeDirectiveNames; @@ -7745,7 +8188,9 @@ export type SourceOfProjectReferenceRedirect = string | true; /** @internal */ export interface ResolvedProjectReferenceCallbacks { getSourceOfProjectReferenceRedirect(fileName: string): SourceOfProjectReferenceRedirect | undefined; - forEachResolvedProjectReference(cb: (resolvedProjectReference: ResolvedProjectReference) => T | undefined): T | undefined; + forEachResolvedProjectReference( + cb: (resolvedProjectReference: ResolvedProjectReference) => T | undefined, + ): T | undefined; } /** @internal */ @@ -7812,15 +8257,25 @@ export const enum TransformFlags { OuterExpressionExcludes = HasComputedFlags, PropertyAccessExcludes = OuterExpressionExcludes, NodeExcludes = PropertyAccessExcludes, - ArrowFunctionExcludes = NodeExcludes | ContainsTypeScriptClassSyntax | ContainsBlockScopedBinding | ContainsYield | ContainsAwait | ContainsHoistedDeclarationOrCompletion | ContainsBindingPattern | ContainsObjectRestOrSpread | ContainsPossibleTopLevelAwait, - FunctionExcludes = NodeExcludes | ContainsTypeScriptClassSyntax | ContainsLexicalThis | ContainsLexicalSuper | ContainsBlockScopedBinding | ContainsYield | ContainsAwait | ContainsHoistedDeclarationOrCompletion | ContainsBindingPattern | ContainsObjectRestOrSpread | ContainsPossibleTopLevelAwait, - ConstructorExcludes = NodeExcludes | ContainsLexicalThis | ContainsLexicalSuper | ContainsBlockScopedBinding | ContainsYield | ContainsAwait | ContainsHoistedDeclarationOrCompletion | ContainsBindingPattern | ContainsObjectRestOrSpread | ContainsPossibleTopLevelAwait, - MethodOrAccessorExcludes = NodeExcludes | ContainsLexicalThis | ContainsLexicalSuper | ContainsBlockScopedBinding | ContainsYield | ContainsAwait | ContainsHoistedDeclarationOrCompletion | ContainsBindingPattern | ContainsObjectRestOrSpread, + ArrowFunctionExcludes = NodeExcludes | ContainsTypeScriptClassSyntax | ContainsBlockScopedBinding | ContainsYield + | ContainsAwait | ContainsHoistedDeclarationOrCompletion | ContainsBindingPattern | ContainsObjectRestOrSpread + | ContainsPossibleTopLevelAwait, + FunctionExcludes = NodeExcludes | ContainsTypeScriptClassSyntax | ContainsLexicalThis | ContainsLexicalSuper + | ContainsBlockScopedBinding | ContainsYield | ContainsAwait | ContainsHoistedDeclarationOrCompletion + | ContainsBindingPattern | ContainsObjectRestOrSpread | ContainsPossibleTopLevelAwait, + ConstructorExcludes = NodeExcludes | ContainsLexicalThis | ContainsLexicalSuper | ContainsBlockScopedBinding + | ContainsYield | ContainsAwait | ContainsHoistedDeclarationOrCompletion | ContainsBindingPattern + | ContainsObjectRestOrSpread | ContainsPossibleTopLevelAwait, + MethodOrAccessorExcludes = NodeExcludes | ContainsLexicalThis | ContainsLexicalSuper | ContainsBlockScopedBinding + | ContainsYield | ContainsAwait | ContainsHoistedDeclarationOrCompletion | ContainsBindingPattern + | ContainsObjectRestOrSpread, PropertyExcludes = NodeExcludes | ContainsLexicalThis | ContainsLexicalSuper, ClassExcludes = NodeExcludes | ContainsTypeScriptClassSyntax | ContainsComputedPropertyName, - ModuleExcludes = NodeExcludes | ContainsTypeScriptClassSyntax | ContainsLexicalThis | ContainsLexicalSuper | ContainsBlockScopedBinding | ContainsHoistedDeclarationOrCompletion | ContainsPossibleTopLevelAwait, + ModuleExcludes = NodeExcludes | ContainsTypeScriptClassSyntax | ContainsLexicalThis | ContainsLexicalSuper + | ContainsBlockScopedBinding | ContainsHoistedDeclarationOrCompletion | ContainsPossibleTopLevelAwait, TypeExcludes = ~ContainsTypeScript, - ObjectLiteralExcludes = NodeExcludes | ContainsTypeScriptClassSyntax | ContainsComputedPropertyName | ContainsObjectRestOrSpread, + ObjectLiteralExcludes = NodeExcludes | ContainsTypeScriptClassSyntax | ContainsComputedPropertyName + | ContainsObjectRestOrSpread, ArrayLiteralOrCallOrNewExcludes = NodeExcludes | ContainsRestOrSpread, VariableDeclarationListExcludes = NodeExcludes | ContainsBindingPattern | ContainsObjectRestOrSpread, ParameterExcludes = NodeExcludes, @@ -8095,7 +8550,16 @@ export type WrappedExpression = | T; /** @internal */ -export type TypeOfTag = "null" | "undefined" | "number" | "bigint" | "boolean" | "string" | "symbol" | "object" | "function"; +export type TypeOfTag = + | "null" + | "undefined" + | "number" + | "bigint" + | "boolean" + | "string" + | "symbol" + | "object" + | "function"; /** @internal */ export interface CallBinding { @@ -8108,7 +8572,11 @@ export interface ParenthesizerRules { getParenthesizeLeftSideOfBinaryForOperator(binaryOperator: SyntaxKind): (leftSide: Expression) => Expression; getParenthesizeRightSideOfBinaryForOperator(binaryOperator: SyntaxKind): (rightSide: Expression) => Expression; parenthesizeLeftSideOfBinary(binaryOperator: SyntaxKind, leftSide: Expression): Expression; - parenthesizeRightSideOfBinary(binaryOperator: SyntaxKind, leftSide: Expression | undefined, rightSide: Expression): Expression; + parenthesizeRightSideOfBinary( + binaryOperator: SyntaxKind, + leftSide: Expression | undefined, + rightSide: Expression, + ): Expression; parenthesizeExpressionOfComputedPropertyName(expression: Expression): Expression; parenthesizeConditionOfConditionalExpression(condition: Expression): Expression; parenthesizeBranchOfConditionalExpression(branch: Expression): Expression; @@ -8161,7 +8629,9 @@ export interface GeneratedNamePart { } export type ImmediatelyInvokedFunctionExpression = CallExpression & { readonly expression: FunctionExpression; }; -export type ImmediatelyInvokedArrowFunction = CallExpression & { readonly expression: ParenthesizedExpression & { readonly expression: ArrowFunction; }; }; +export type ImmediatelyInvokedArrowFunction = CallExpression & { + readonly expression: ParenthesizedExpression & { readonly expression: ArrowFunction; }; +}; export interface NodeFactory { /** @internal */ readonly parenthesizer: ParenthesizerRules; @@ -8178,8 +8648,15 @@ export interface NodeFactory { createNumericLiteral(value: string | number, numericLiteralFlags?: TokenFlags): NumericLiteral; createBigIntLiteral(value: string | PseudoBigInt): BigIntLiteral; createStringLiteral(text: string, isSingleQuote?: boolean): StringLiteral; - /** @internal */ createStringLiteral(text: string, isSingleQuote?: boolean, hasExtendedUnicodeEscape?: boolean): StringLiteral; // eslint-disable-line @typescript-eslint/unified-signatures - createStringLiteralFromNode(sourceNode: PropertyNameLiteral | PrivateIdentifier, isSingleQuote?: boolean): StringLiteral; + /** @internal */ createStringLiteral( + text: string, + isSingleQuote?: boolean, + hasExtendedUnicodeEscape?: boolean, + ): StringLiteral; // eslint-disable-line @typescript-eslint/unified-signatures + createStringLiteralFromNode( + sourceNode: PropertyNameLiteral | PrivateIdentifier, + isSingleQuote?: boolean, + ): StringLiteral; createRegularExpressionLiteral(text: string): RegularExpressionLiteral; // @@ -8187,7 +8664,11 @@ export interface NodeFactory { // createIdentifier(text: string): Identifier; - /** @internal */ createIdentifier(text: string, originalKeywordKind?: SyntaxKind, hasExtendedUnicodeEscape?: boolean): Identifier; // eslint-disable-line @typescript-eslint/unified-signatures + /** @internal */ createIdentifier( + text: string, + originalKeywordKind?: SyntaxKind, + hasExtendedUnicodeEscape?: boolean, + ): Identifier; // eslint-disable-line @typescript-eslint/unified-signatures /** * Create a unique temporary variable. @@ -8198,8 +8679,16 @@ export interface NodeFactory { * during emit so that the variable can be referenced in a nested function body. This is an alternative to * setting `EmitFlags.ReuseTempVariableScope` on the nested function itself. */ - createTempVariable(recordTempVariable: ((node: Identifier) => void) | undefined, reservedInNestedScopes?: boolean): Identifier; - /** @internal */ createTempVariable(recordTempVariable: ((node: Identifier) => void) | undefined, reservedInNestedScopes?: boolean, prefix?: string | GeneratedNamePart, suffix?: string): Identifier; // eslint-disable-line @typescript-eslint/unified-signatures + createTempVariable( + recordTempVariable: ((node: Identifier) => void) | undefined, + reservedInNestedScopes?: boolean, + ): Identifier; + /** @internal */ createTempVariable( + recordTempVariable: ((node: Identifier) => void) | undefined, + reservedInNestedScopes?: boolean, + prefix?: string | GeneratedNamePart, + suffix?: string, + ): Identifier; // eslint-disable-line @typescript-eslint/unified-signatures /** * Create a unique temporary variable for use in a loop. @@ -8211,17 +8700,35 @@ export interface NodeFactory { /** Create a unique name based on the supplied text. */ createUniqueName(text: string, flags?: GeneratedIdentifierFlags): Identifier; - /** @internal */ createUniqueName(text: string, flags?: GeneratedIdentifierFlags, prefix?: string | GeneratedNamePart, suffix?: string): Identifier; // eslint-disable-line @typescript-eslint/unified-signatures + /** @internal */ createUniqueName( + text: string, + flags?: GeneratedIdentifierFlags, + prefix?: string | GeneratedNamePart, + suffix?: string, + ): Identifier; // eslint-disable-line @typescript-eslint/unified-signatures /** Create a unique name generated for a node. */ getGeneratedNameForNode(node: Node | undefined, flags?: GeneratedIdentifierFlags): Identifier; - /** @internal */ getGeneratedNameForNode(node: Node | undefined, flags?: GeneratedIdentifierFlags, prefix?: string | GeneratedNamePart, suffix?: string): Identifier; // eslint-disable-line @typescript-eslint/unified-signatures + /** @internal */ getGeneratedNameForNode( + node: Node | undefined, + flags?: GeneratedIdentifierFlags, + prefix?: string | GeneratedNamePart, + suffix?: string, + ): Identifier; // eslint-disable-line @typescript-eslint/unified-signatures createPrivateIdentifier(text: string): PrivateIdentifier; createUniquePrivateName(text?: string): PrivateIdentifier; - /** @internal */ createUniquePrivateName(text?: string, prefix?: string | GeneratedNamePart, suffix?: string): PrivateIdentifier; // eslint-disable-line @typescript-eslint/unified-signatures + /** @internal */ createUniquePrivateName( + text?: string, + prefix?: string | GeneratedNamePart, + suffix?: string, + ): PrivateIdentifier; // eslint-disable-line @typescript-eslint/unified-signatures getGeneratedPrivateNameForNode(node: Node): PrivateIdentifier; - /** @internal */ getGeneratedPrivateNameForNode(node: Node, prefix?: string | GeneratedNamePart, suffix?: string): PrivateIdentifier; // eslint-disable-line @typescript-eslint/unified-signatures + /** @internal */ getGeneratedPrivateNameForNode( + node: Node, + prefix?: string | GeneratedNamePart, + suffix?: string, + ): PrivateIdentifier; // eslint-disable-line @typescript-eslint/unified-signatures // // Punctuation @@ -8270,10 +8777,36 @@ export interface NodeFactory { // Signature elements // - createTypeParameterDeclaration(modifiers: readonly Modifier[] | undefined, name: string | Identifier, constraint?: TypeNode, defaultType?: TypeNode): TypeParameterDeclaration; - updateTypeParameterDeclaration(node: TypeParameterDeclaration, modifiers: readonly Modifier[] | undefined, name: Identifier, constraint: TypeNode | undefined, defaultType: TypeNode | undefined): TypeParameterDeclaration; - createParameterDeclaration(modifiers: readonly ModifierLike[] | undefined, dotDotDotToken: DotDotDotToken | undefined, name: string | BindingName, questionToken?: QuestionToken, type?: TypeNode, initializer?: Expression): ParameterDeclaration; - updateParameterDeclaration(node: ParameterDeclaration, modifiers: readonly ModifierLike[] | undefined, dotDotDotToken: DotDotDotToken | undefined, name: string | BindingName, questionToken: QuestionToken | undefined, type: TypeNode | undefined, initializer: Expression | undefined): ParameterDeclaration; + createTypeParameterDeclaration( + modifiers: readonly Modifier[] | undefined, + name: string | Identifier, + constraint?: TypeNode, + defaultType?: TypeNode, + ): TypeParameterDeclaration; + updateTypeParameterDeclaration( + node: TypeParameterDeclaration, + modifiers: readonly Modifier[] | undefined, + name: Identifier, + constraint: TypeNode | undefined, + defaultType: TypeNode | undefined, + ): TypeParameterDeclaration; + createParameterDeclaration( + modifiers: readonly ModifierLike[] | undefined, + dotDotDotToken: DotDotDotToken | undefined, + name: string | BindingName, + questionToken?: QuestionToken, + type?: TypeNode, + initializer?: Expression, + ): ParameterDeclaration; + updateParameterDeclaration( + node: ParameterDeclaration, + modifiers: readonly ModifierLike[] | undefined, + dotDotDotToken: DotDotDotToken | undefined, + name: string | BindingName, + questionToken: QuestionToken | undefined, + type: TypeNode | undefined, + initializer: Expression | undefined, + ): ParameterDeclaration; createDecorator(expression: Expression): Decorator; updateDecorator(node: Decorator, expression: Expression): Decorator; @@ -8281,29 +8814,155 @@ export interface NodeFactory { // Type Elements // - createPropertySignature(modifiers: readonly Modifier[] | undefined, name: PropertyName | string, questionToken: QuestionToken | undefined, type: TypeNode | undefined): PropertySignature; - updatePropertySignature(node: PropertySignature, modifiers: readonly Modifier[] | undefined, name: PropertyName, questionToken: QuestionToken | undefined, type: TypeNode | undefined): PropertySignature; - createPropertyDeclaration(modifiers: readonly ModifierLike[] | undefined, name: string | PropertyName, questionOrExclamationToken: QuestionToken | ExclamationToken | undefined, type: TypeNode | undefined, initializer: Expression | undefined): PropertyDeclaration; - updatePropertyDeclaration(node: PropertyDeclaration, modifiers: readonly ModifierLike[] | undefined, name: string | PropertyName, questionOrExclamationToken: QuestionToken | ExclamationToken | undefined, type: TypeNode | undefined, initializer: Expression | undefined): PropertyDeclaration; - createMethodSignature(modifiers: readonly Modifier[] | undefined, name: string | PropertyName, questionToken: QuestionToken | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined): MethodSignature; - updateMethodSignature(node: MethodSignature, modifiers: readonly Modifier[] | undefined, name: PropertyName, questionToken: QuestionToken | undefined, typeParameters: NodeArray | undefined, parameters: NodeArray, type: TypeNode | undefined): MethodSignature; - createMethodDeclaration(modifiers: readonly ModifierLike[] | undefined, asteriskToken: AsteriskToken | undefined, name: string | PropertyName, questionToken: QuestionToken | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined): MethodDeclaration; - updateMethodDeclaration(node: MethodDeclaration, modifiers: readonly ModifierLike[] | undefined, asteriskToken: AsteriskToken | undefined, name: PropertyName, questionToken: QuestionToken | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined): MethodDeclaration; - createConstructorDeclaration(modifiers: readonly ModifierLike[] | undefined, parameters: readonly ParameterDeclaration[], body: Block | undefined): ConstructorDeclaration; - updateConstructorDeclaration(node: ConstructorDeclaration, modifiers: readonly ModifierLike[] | undefined, parameters: readonly ParameterDeclaration[], body: Block | undefined): ConstructorDeclaration; - createGetAccessorDeclaration(modifiers: readonly ModifierLike[] | undefined, name: string | PropertyName, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined): GetAccessorDeclaration; - updateGetAccessorDeclaration(node: GetAccessorDeclaration, modifiers: readonly ModifierLike[] | undefined, name: PropertyName, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined): GetAccessorDeclaration; - createSetAccessorDeclaration(modifiers: readonly ModifierLike[] | undefined, name: string | PropertyName, parameters: readonly ParameterDeclaration[], body: Block | undefined): SetAccessorDeclaration; - updateSetAccessorDeclaration(node: SetAccessorDeclaration, modifiers: readonly ModifierLike[] | undefined, name: PropertyName, parameters: readonly ParameterDeclaration[], body: Block | undefined): SetAccessorDeclaration; - createCallSignature(typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined): CallSignatureDeclaration; - updateCallSignature(node: CallSignatureDeclaration, typeParameters: NodeArray | undefined, parameters: NodeArray, type: TypeNode | undefined): CallSignatureDeclaration; - createConstructSignature(typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined): ConstructSignatureDeclaration; - updateConstructSignature(node: ConstructSignatureDeclaration, typeParameters: NodeArray | undefined, parameters: NodeArray, type: TypeNode | undefined): ConstructSignatureDeclaration; - createIndexSignature(modifiers: readonly ModifierLike[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode): IndexSignatureDeclaration; - /** @internal */ createIndexSignature(modifiers: readonly ModifierLike[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined): IndexSignatureDeclaration; // eslint-disable-line @typescript-eslint/unified-signatures - updateIndexSignature(node: IndexSignatureDeclaration, modifiers: readonly ModifierLike[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode): IndexSignatureDeclaration; + createPropertySignature( + modifiers: readonly Modifier[] | undefined, + name: PropertyName | string, + questionToken: QuestionToken | undefined, + type: TypeNode | undefined, + ): PropertySignature; + updatePropertySignature( + node: PropertySignature, + modifiers: readonly Modifier[] | undefined, + name: PropertyName, + questionToken: QuestionToken | undefined, + type: TypeNode | undefined, + ): PropertySignature; + createPropertyDeclaration( + modifiers: readonly ModifierLike[] | undefined, + name: string | PropertyName, + questionOrExclamationToken: QuestionToken | ExclamationToken | undefined, + type: TypeNode | undefined, + initializer: Expression | undefined, + ): PropertyDeclaration; + updatePropertyDeclaration( + node: PropertyDeclaration, + modifiers: readonly ModifierLike[] | undefined, + name: string | PropertyName, + questionOrExclamationToken: QuestionToken | ExclamationToken | undefined, + type: TypeNode | undefined, + initializer: Expression | undefined, + ): PropertyDeclaration; + createMethodSignature( + modifiers: readonly Modifier[] | undefined, + name: string | PropertyName, + questionToken: QuestionToken | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + parameters: readonly ParameterDeclaration[], + type: TypeNode | undefined, + ): MethodSignature; + updateMethodSignature( + node: MethodSignature, + modifiers: readonly Modifier[] | undefined, + name: PropertyName, + questionToken: QuestionToken | undefined, + typeParameters: NodeArray | undefined, + parameters: NodeArray, + type: TypeNode | undefined, + ): MethodSignature; + createMethodDeclaration( + modifiers: readonly ModifierLike[] | undefined, + asteriskToken: AsteriskToken | undefined, + name: string | PropertyName, + questionToken: QuestionToken | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + parameters: readonly ParameterDeclaration[], + type: TypeNode | undefined, + body: Block | undefined, + ): MethodDeclaration; + updateMethodDeclaration( + node: MethodDeclaration, + modifiers: readonly ModifierLike[] | undefined, + asteriskToken: AsteriskToken | undefined, + name: PropertyName, + questionToken: QuestionToken | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + parameters: readonly ParameterDeclaration[], + type: TypeNode | undefined, + body: Block | undefined, + ): MethodDeclaration; + createConstructorDeclaration( + modifiers: readonly ModifierLike[] | undefined, + parameters: readonly ParameterDeclaration[], + body: Block | undefined, + ): ConstructorDeclaration; + updateConstructorDeclaration( + node: ConstructorDeclaration, + modifiers: readonly ModifierLike[] | undefined, + parameters: readonly ParameterDeclaration[], + body: Block | undefined, + ): ConstructorDeclaration; + createGetAccessorDeclaration( + modifiers: readonly ModifierLike[] | undefined, + name: string | PropertyName, + parameters: readonly ParameterDeclaration[], + type: TypeNode | undefined, + body: Block | undefined, + ): GetAccessorDeclaration; + updateGetAccessorDeclaration( + node: GetAccessorDeclaration, + modifiers: readonly ModifierLike[] | undefined, + name: PropertyName, + parameters: readonly ParameterDeclaration[], + type: TypeNode | undefined, + body: Block | undefined, + ): GetAccessorDeclaration; + createSetAccessorDeclaration( + modifiers: readonly ModifierLike[] | undefined, + name: string | PropertyName, + parameters: readonly ParameterDeclaration[], + body: Block | undefined, + ): SetAccessorDeclaration; + updateSetAccessorDeclaration( + node: SetAccessorDeclaration, + modifiers: readonly ModifierLike[] | undefined, + name: PropertyName, + parameters: readonly ParameterDeclaration[], + body: Block | undefined, + ): SetAccessorDeclaration; + createCallSignature( + typeParameters: readonly TypeParameterDeclaration[] | undefined, + parameters: readonly ParameterDeclaration[], + type: TypeNode | undefined, + ): CallSignatureDeclaration; + updateCallSignature( + node: CallSignatureDeclaration, + typeParameters: NodeArray | undefined, + parameters: NodeArray, + type: TypeNode | undefined, + ): CallSignatureDeclaration; + createConstructSignature( + typeParameters: readonly TypeParameterDeclaration[] | undefined, + parameters: readonly ParameterDeclaration[], + type: TypeNode | undefined, + ): ConstructSignatureDeclaration; + updateConstructSignature( + node: ConstructSignatureDeclaration, + typeParameters: NodeArray | undefined, + parameters: NodeArray, + type: TypeNode | undefined, + ): ConstructSignatureDeclaration; + createIndexSignature( + modifiers: readonly ModifierLike[] | undefined, + parameters: readonly ParameterDeclaration[], + type: TypeNode, + ): IndexSignatureDeclaration; + /** @internal */ createIndexSignature( + modifiers: readonly ModifierLike[] | undefined, + parameters: readonly ParameterDeclaration[], + type: TypeNode | undefined, + ): IndexSignatureDeclaration; // eslint-disable-line @typescript-eslint/unified-signatures + updateIndexSignature( + node: IndexSignatureDeclaration, + modifiers: readonly ModifierLike[] | undefined, + parameters: readonly ParameterDeclaration[], + type: TypeNode, + ): IndexSignatureDeclaration; createTemplateLiteralTypeSpan(type: TypeNode, literal: TemplateMiddle | TemplateTail): TemplateLiteralTypeSpan; - updateTemplateLiteralTypeSpan(node: TemplateLiteralTypeSpan, type: TypeNode, literal: TemplateMiddle | TemplateTail): TemplateLiteralTypeSpan; + updateTemplateLiteralTypeSpan( + node: TemplateLiteralTypeSpan, + type: TypeNode, + literal: TemplateMiddle | TemplateTail, + ): TemplateLiteralTypeSpan; createClassStaticBlockDeclaration(body: Block): ClassStaticBlockDeclaration; updateClassStaticBlockDeclaration(node: ClassStaticBlockDeclaration, body: Block): ClassStaticBlockDeclaration; @@ -8312,14 +8971,47 @@ export interface NodeFactory { // createKeywordTypeNode(kind: TKind): KeywordTypeNode; - createTypePredicateNode(assertsModifier: AssertsKeyword | undefined, parameterName: Identifier | ThisTypeNode | string, type: TypeNode | undefined): TypePredicateNode; - updateTypePredicateNode(node: TypePredicateNode, assertsModifier: AssertsKeyword | undefined, parameterName: Identifier | ThisTypeNode, type: TypeNode | undefined): TypePredicateNode; + createTypePredicateNode( + assertsModifier: AssertsKeyword | undefined, + parameterName: Identifier | ThisTypeNode | string, + type: TypeNode | undefined, + ): TypePredicateNode; + updateTypePredicateNode( + node: TypePredicateNode, + assertsModifier: AssertsKeyword | undefined, + parameterName: Identifier | ThisTypeNode, + type: TypeNode | undefined, + ): TypePredicateNode; createTypeReferenceNode(typeName: string | EntityName, typeArguments?: readonly TypeNode[]): TypeReferenceNode; - updateTypeReferenceNode(node: TypeReferenceNode, typeName: EntityName, typeArguments: NodeArray | undefined): TypeReferenceNode; - createFunctionTypeNode(typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode): FunctionTypeNode; - updateFunctionTypeNode(node: FunctionTypeNode, typeParameters: NodeArray | undefined, parameters: NodeArray, type: TypeNode): FunctionTypeNode; - createConstructorTypeNode(modifiers: readonly Modifier[] | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode): ConstructorTypeNode; - updateConstructorTypeNode(node: ConstructorTypeNode, modifiers: readonly Modifier[] | undefined, typeParameters: NodeArray | undefined, parameters: NodeArray, type: TypeNode): ConstructorTypeNode; + updateTypeReferenceNode( + node: TypeReferenceNode, + typeName: EntityName, + typeArguments: NodeArray | undefined, + ): TypeReferenceNode; + createFunctionTypeNode( + typeParameters: readonly TypeParameterDeclaration[] | undefined, + parameters: readonly ParameterDeclaration[], + type: TypeNode, + ): FunctionTypeNode; + updateFunctionTypeNode( + node: FunctionTypeNode, + typeParameters: NodeArray | undefined, + parameters: NodeArray, + type: TypeNode, + ): FunctionTypeNode; + createConstructorTypeNode( + modifiers: readonly Modifier[] | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + parameters: readonly ParameterDeclaration[], + type: TypeNode, + ): ConstructorTypeNode; + updateConstructorTypeNode( + node: ConstructorTypeNode, + modifiers: readonly Modifier[] | undefined, + typeParameters: NodeArray | undefined, + parameters: NodeArray, + type: TypeNode, + ): ConstructorTypeNode; createTypeQueryNode(exprName: EntityName, typeArguments?: readonly TypeNode[]): TypeQueryNode; updateTypeQueryNode(node: TypeQueryNode, exprName: EntityName, typeArguments?: readonly TypeNode[]): TypeQueryNode; createTypeLiteralNode(members: readonly TypeElement[] | undefined): TypeLiteralNode; @@ -8328,8 +9020,19 @@ export interface NodeFactory { updateArrayTypeNode(node: ArrayTypeNode, elementType: TypeNode): ArrayTypeNode; createTupleTypeNode(elements: readonly (TypeNode | NamedTupleMember)[]): TupleTypeNode; updateTupleTypeNode(node: TupleTypeNode, elements: readonly (TypeNode | NamedTupleMember)[]): TupleTypeNode; - createNamedTupleMember(dotDotDotToken: DotDotDotToken | undefined, name: Identifier, questionToken: QuestionToken | undefined, type: TypeNode): NamedTupleMember; - updateNamedTupleMember(node: NamedTupleMember, dotDotDotToken: DotDotDotToken | undefined, name: Identifier, questionToken: QuestionToken | undefined, type: TypeNode): NamedTupleMember; + createNamedTupleMember( + dotDotDotToken: DotDotDotToken | undefined, + name: Identifier, + questionToken: QuestionToken | undefined, + type: TypeNode, + ): NamedTupleMember; + updateNamedTupleMember( + node: NamedTupleMember, + dotDotDotToken: DotDotDotToken | undefined, + name: Identifier, + questionToken: QuestionToken | undefined, + type: TypeNode, + ): NamedTupleMember; createOptionalTypeNode(type: TypeNode): OptionalTypeNode; updateOptionalTypeNode(node: OptionalTypeNode, type: TypeNode): OptionalTypeNode; createRestTypeNode(type: TypeNode): RestTypeNode; @@ -8338,25 +9041,78 @@ export interface NodeFactory { updateUnionTypeNode(node: UnionTypeNode, types: NodeArray): UnionTypeNode; createIntersectionTypeNode(types: readonly TypeNode[]): IntersectionTypeNode; updateIntersectionTypeNode(node: IntersectionTypeNode, types: NodeArray): IntersectionTypeNode; - createConditionalTypeNode(checkType: TypeNode, extendsType: TypeNode, trueType: TypeNode, falseType: TypeNode): ConditionalTypeNode; - updateConditionalTypeNode(node: ConditionalTypeNode, checkType: TypeNode, extendsType: TypeNode, trueType: TypeNode, falseType: TypeNode): ConditionalTypeNode; + createConditionalTypeNode( + checkType: TypeNode, + extendsType: TypeNode, + trueType: TypeNode, + falseType: TypeNode, + ): ConditionalTypeNode; + updateConditionalTypeNode( + node: ConditionalTypeNode, + checkType: TypeNode, + extendsType: TypeNode, + trueType: TypeNode, + falseType: TypeNode, + ): ConditionalTypeNode; createInferTypeNode(typeParameter: TypeParameterDeclaration): InferTypeNode; updateInferTypeNode(node: InferTypeNode, typeParameter: TypeParameterDeclaration): InferTypeNode; - createImportTypeNode(argument: TypeNode, assertions?: ImportTypeAssertionContainer, qualifier?: EntityName, typeArguments?: readonly TypeNode[], isTypeOf?: boolean): ImportTypeNode; - updateImportTypeNode(node: ImportTypeNode, argument: TypeNode, assertions: ImportTypeAssertionContainer | undefined, qualifier: EntityName | undefined, typeArguments: readonly TypeNode[] | undefined, isTypeOf?: boolean): ImportTypeNode; + createImportTypeNode( + argument: TypeNode, + assertions?: ImportTypeAssertionContainer, + qualifier?: EntityName, + typeArguments?: readonly TypeNode[], + isTypeOf?: boolean, + ): ImportTypeNode; + updateImportTypeNode( + node: ImportTypeNode, + argument: TypeNode, + assertions: ImportTypeAssertionContainer | undefined, + qualifier: EntityName | undefined, + typeArguments: readonly TypeNode[] | undefined, + isTypeOf?: boolean, + ): ImportTypeNode; createParenthesizedType(type: TypeNode): ParenthesizedTypeNode; updateParenthesizedType(node: ParenthesizedTypeNode, type: TypeNode): ParenthesizedTypeNode; createThisTypeNode(): ThisTypeNode; - createTypeOperatorNode(operator: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.ReadonlyKeyword, type: TypeNode): TypeOperatorNode; + createTypeOperatorNode( + operator: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.ReadonlyKeyword, + type: TypeNode, + ): TypeOperatorNode; updateTypeOperatorNode(node: TypeOperatorNode, type: TypeNode): TypeOperatorNode; createIndexedAccessTypeNode(objectType: TypeNode, indexType: TypeNode): IndexedAccessTypeNode; - updateIndexedAccessTypeNode(node: IndexedAccessTypeNode, objectType: TypeNode, indexType: TypeNode): IndexedAccessTypeNode; - createMappedTypeNode(readonlyToken: ReadonlyKeyword | PlusToken | MinusToken | undefined, typeParameter: TypeParameterDeclaration, nameType: TypeNode | undefined, questionToken: QuestionToken | PlusToken | MinusToken | undefined, type: TypeNode | undefined, members: NodeArray | undefined): MappedTypeNode; - updateMappedTypeNode(node: MappedTypeNode, readonlyToken: ReadonlyKeyword | PlusToken | MinusToken | undefined, typeParameter: TypeParameterDeclaration, nameType: TypeNode | undefined, questionToken: QuestionToken | PlusToken | MinusToken | undefined, type: TypeNode | undefined, members: NodeArray | undefined): MappedTypeNode; + updateIndexedAccessTypeNode( + node: IndexedAccessTypeNode, + objectType: TypeNode, + indexType: TypeNode, + ): IndexedAccessTypeNode; + createMappedTypeNode( + readonlyToken: ReadonlyKeyword | PlusToken | MinusToken | undefined, + typeParameter: TypeParameterDeclaration, + nameType: TypeNode | undefined, + questionToken: QuestionToken | PlusToken | MinusToken | undefined, + type: TypeNode | undefined, + members: NodeArray | undefined, + ): MappedTypeNode; + updateMappedTypeNode( + node: MappedTypeNode, + readonlyToken: ReadonlyKeyword | PlusToken | MinusToken | undefined, + typeParameter: TypeParameterDeclaration, + nameType: TypeNode | undefined, + questionToken: QuestionToken | PlusToken | MinusToken | undefined, + type: TypeNode | undefined, + members: NodeArray | undefined, + ): MappedTypeNode; createLiteralTypeNode(literal: LiteralTypeNode["literal"]): LiteralTypeNode; updateLiteralTypeNode(node: LiteralTypeNode, literal: LiteralTypeNode["literal"]): LiteralTypeNode; - createTemplateLiteralType(head: TemplateHead, templateSpans: readonly TemplateLiteralTypeSpan[]): TemplateLiteralTypeNode; - updateTemplateLiteralType(node: TemplateLiteralTypeNode, head: TemplateHead, templateSpans: readonly TemplateLiteralTypeSpan[]): TemplateLiteralTypeNode; + createTemplateLiteralType( + head: TemplateHead, + templateSpans: readonly TemplateLiteralTypeSpan[], + ): TemplateLiteralTypeNode; + updateTemplateLiteralType( + node: TemplateLiteralTypeNode, + head: TemplateHead, + templateSpans: readonly TemplateLiteralTypeSpan[], + ): TemplateLiteralTypeNode; // // Binding Patterns @@ -8366,8 +9122,19 @@ export interface NodeFactory { updateObjectBindingPattern(node: ObjectBindingPattern, elements: readonly BindingElement[]): ObjectBindingPattern; createArrayBindingPattern(elements: readonly ArrayBindingElement[]): ArrayBindingPattern; updateArrayBindingPattern(node: ArrayBindingPattern, elements: readonly ArrayBindingElement[]): ArrayBindingPattern; - createBindingElement(dotDotDotToken: DotDotDotToken | undefined, propertyName: string | PropertyName | undefined, name: string | BindingName, initializer?: Expression): BindingElement; - updateBindingElement(node: BindingElement, dotDotDotToken: DotDotDotToken | undefined, propertyName: PropertyName | undefined, name: BindingName, initializer: Expression | undefined): BindingElement; + createBindingElement( + dotDotDotToken: DotDotDotToken | undefined, + propertyName: string | PropertyName | undefined, + name: string | BindingName, + initializer?: Expression, + ): BindingElement; + updateBindingElement( + node: BindingElement, + dotDotDotToken: DotDotDotToken | undefined, + propertyName: PropertyName | undefined, + name: BindingName, + initializer: Expression | undefined, + ): BindingElement; // // Expression @@ -8375,32 +9142,134 @@ export interface NodeFactory { createArrayLiteralExpression(elements?: readonly Expression[], multiLine?: boolean): ArrayLiteralExpression; updateArrayLiteralExpression(node: ArrayLiteralExpression, elements: readonly Expression[]): ArrayLiteralExpression; - createObjectLiteralExpression(properties?: readonly ObjectLiteralElementLike[], multiLine?: boolean): ObjectLiteralExpression; - updateObjectLiteralExpression(node: ObjectLiteralExpression, properties: readonly ObjectLiteralElementLike[]): ObjectLiteralExpression; + createObjectLiteralExpression( + properties?: readonly ObjectLiteralElementLike[], + multiLine?: boolean, + ): ObjectLiteralExpression; + updateObjectLiteralExpression( + node: ObjectLiteralExpression, + properties: readonly ObjectLiteralElementLike[], + ): ObjectLiteralExpression; createPropertyAccessExpression(expression: Expression, name: string | MemberName): PropertyAccessExpression; - updatePropertyAccessExpression(node: PropertyAccessExpression, expression: Expression, name: MemberName): PropertyAccessExpression; - createPropertyAccessChain(expression: Expression, questionDotToken: QuestionDotToken | undefined, name: string | MemberName): PropertyAccessChain; - updatePropertyAccessChain(node: PropertyAccessChain, expression: Expression, questionDotToken: QuestionDotToken | undefined, name: MemberName): PropertyAccessChain; + updatePropertyAccessExpression( + node: PropertyAccessExpression, + expression: Expression, + name: MemberName, + ): PropertyAccessExpression; + createPropertyAccessChain( + expression: Expression, + questionDotToken: QuestionDotToken | undefined, + name: string | MemberName, + ): PropertyAccessChain; + updatePropertyAccessChain( + node: PropertyAccessChain, + expression: Expression, + questionDotToken: QuestionDotToken | undefined, + name: MemberName, + ): PropertyAccessChain; createElementAccessExpression(expression: Expression, index: number | Expression): ElementAccessExpression; - updateElementAccessExpression(node: ElementAccessExpression, expression: Expression, argumentExpression: Expression): ElementAccessExpression; - createElementAccessChain(expression: Expression, questionDotToken: QuestionDotToken | undefined, index: number | Expression): ElementAccessChain; - updateElementAccessChain(node: ElementAccessChain, expression: Expression, questionDotToken: QuestionDotToken | undefined, argumentExpression: Expression): ElementAccessChain; - createCallExpression(expression: Expression, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[] | undefined): CallExpression; - updateCallExpression(node: CallExpression, expression: Expression, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[]): CallExpression; - createCallChain(expression: Expression, questionDotToken: QuestionDotToken | undefined, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[] | undefined): CallChain; - updateCallChain(node: CallChain, expression: Expression, questionDotToken: QuestionDotToken | undefined, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[]): CallChain; - createNewExpression(expression: Expression, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[] | undefined): NewExpression; - updateNewExpression(node: NewExpression, expression: Expression, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[] | undefined): NewExpression; - createTaggedTemplateExpression(tag: Expression, typeArguments: readonly TypeNode[] | undefined, template: TemplateLiteral): TaggedTemplateExpression; - updateTaggedTemplateExpression(node: TaggedTemplateExpression, tag: Expression, typeArguments: readonly TypeNode[] | undefined, template: TemplateLiteral): TaggedTemplateExpression; + updateElementAccessExpression( + node: ElementAccessExpression, + expression: Expression, + argumentExpression: Expression, + ): ElementAccessExpression; + createElementAccessChain( + expression: Expression, + questionDotToken: QuestionDotToken | undefined, + index: number | Expression, + ): ElementAccessChain; + updateElementAccessChain( + node: ElementAccessChain, + expression: Expression, + questionDotToken: QuestionDotToken | undefined, + argumentExpression: Expression, + ): ElementAccessChain; + createCallExpression( + expression: Expression, + typeArguments: readonly TypeNode[] | undefined, + argumentsArray: readonly Expression[] | undefined, + ): CallExpression; + updateCallExpression( + node: CallExpression, + expression: Expression, + typeArguments: readonly TypeNode[] | undefined, + argumentsArray: readonly Expression[], + ): CallExpression; + createCallChain( + expression: Expression, + questionDotToken: QuestionDotToken | undefined, + typeArguments: readonly TypeNode[] | undefined, + argumentsArray: readonly Expression[] | undefined, + ): CallChain; + updateCallChain( + node: CallChain, + expression: Expression, + questionDotToken: QuestionDotToken | undefined, + typeArguments: readonly TypeNode[] | undefined, + argumentsArray: readonly Expression[], + ): CallChain; + createNewExpression( + expression: Expression, + typeArguments: readonly TypeNode[] | undefined, + argumentsArray: readonly Expression[] | undefined, + ): NewExpression; + updateNewExpression( + node: NewExpression, + expression: Expression, + typeArguments: readonly TypeNode[] | undefined, + argumentsArray: readonly Expression[] | undefined, + ): NewExpression; + createTaggedTemplateExpression( + tag: Expression, + typeArguments: readonly TypeNode[] | undefined, + template: TemplateLiteral, + ): TaggedTemplateExpression; + updateTaggedTemplateExpression( + node: TaggedTemplateExpression, + tag: Expression, + typeArguments: readonly TypeNode[] | undefined, + template: TemplateLiteral, + ): TaggedTemplateExpression; createTypeAssertion(type: TypeNode, expression: Expression): TypeAssertion; updateTypeAssertion(node: TypeAssertion, type: TypeNode, expression: Expression): TypeAssertion; createParenthesizedExpression(expression: Expression): ParenthesizedExpression; updateParenthesizedExpression(node: ParenthesizedExpression, expression: Expression): ParenthesizedExpression; - createFunctionExpression(modifiers: readonly Modifier[] | undefined, asteriskToken: AsteriskToken | undefined, name: string | Identifier | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[] | undefined, type: TypeNode | undefined, body: Block): FunctionExpression; - updateFunctionExpression(node: FunctionExpression, modifiers: readonly Modifier[] | undefined, asteriskToken: AsteriskToken | undefined, name: Identifier | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: Block): FunctionExpression; - createArrowFunction(modifiers: readonly Modifier[] | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, equalsGreaterThanToken: EqualsGreaterThanToken | undefined, body: ConciseBody): ArrowFunction; - updateArrowFunction(node: ArrowFunction, modifiers: readonly Modifier[] | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, equalsGreaterThanToken: EqualsGreaterThanToken, body: ConciseBody): ArrowFunction; + createFunctionExpression( + modifiers: readonly Modifier[] | undefined, + asteriskToken: AsteriskToken | undefined, + name: string | Identifier | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + parameters: readonly ParameterDeclaration[] | undefined, + type: TypeNode | undefined, + body: Block, + ): FunctionExpression; + updateFunctionExpression( + node: FunctionExpression, + modifiers: readonly Modifier[] | undefined, + asteriskToken: AsteriskToken | undefined, + name: Identifier | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + parameters: readonly ParameterDeclaration[], + type: TypeNode | undefined, + body: Block, + ): FunctionExpression; + createArrowFunction( + modifiers: readonly Modifier[] | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + parameters: readonly ParameterDeclaration[], + type: TypeNode | undefined, + equalsGreaterThanToken: EqualsGreaterThanToken | undefined, + body: ConciseBody, + ): ArrowFunction; + updateArrowFunction( + node: ArrowFunction, + modifiers: readonly Modifier[] | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + parameters: readonly ParameterDeclaration[], + type: TypeNode | undefined, + equalsGreaterThanToken: EqualsGreaterThanToken, + body: ConciseBody, + ): ArrowFunction; createDeleteExpression(expression: Expression): DeleteExpression; updateDeleteExpression(node: DeleteExpression, expression: Expression): DeleteExpression; createTypeOfExpression(expression: Expression): TypeOfExpression; @@ -8413,12 +9282,38 @@ export interface NodeFactory { updatePrefixUnaryExpression(node: PrefixUnaryExpression, operand: Expression): PrefixUnaryExpression; createPostfixUnaryExpression(operand: Expression, operator: PostfixUnaryOperator): PostfixUnaryExpression; updatePostfixUnaryExpression(node: PostfixUnaryExpression, operand: Expression): PostfixUnaryExpression; - createBinaryExpression(left: Expression, operator: BinaryOperator | BinaryOperatorToken, right: Expression): BinaryExpression; - updateBinaryExpression(node: BinaryExpression, left: Expression, operator: BinaryOperator | BinaryOperatorToken, right: Expression): BinaryExpression; - createConditionalExpression(condition: Expression, questionToken: QuestionToken | undefined, whenTrue: Expression, colonToken: ColonToken | undefined, whenFalse: Expression): ConditionalExpression; - updateConditionalExpression(node: ConditionalExpression, condition: Expression, questionToken: QuestionToken, whenTrue: Expression, colonToken: ColonToken, whenFalse: Expression): ConditionalExpression; + createBinaryExpression( + left: Expression, + operator: BinaryOperator | BinaryOperatorToken, + right: Expression, + ): BinaryExpression; + updateBinaryExpression( + node: BinaryExpression, + left: Expression, + operator: BinaryOperator | BinaryOperatorToken, + right: Expression, + ): BinaryExpression; + createConditionalExpression( + condition: Expression, + questionToken: QuestionToken | undefined, + whenTrue: Expression, + colonToken: ColonToken | undefined, + whenFalse: Expression, + ): ConditionalExpression; + updateConditionalExpression( + node: ConditionalExpression, + condition: Expression, + questionToken: QuestionToken, + whenTrue: Expression, + colonToken: ColonToken, + whenFalse: Expression, + ): ConditionalExpression; createTemplateExpression(head: TemplateHead, templateSpans: readonly TemplateSpan[]): TemplateExpression; - updateTemplateExpression(node: TemplateExpression, head: TemplateHead, templateSpans: readonly TemplateSpan[]): TemplateExpression; + updateTemplateExpression( + node: TemplateExpression, + head: TemplateHead, + templateSpans: readonly TemplateSpan[], + ): TemplateExpression; createTemplateHead(text: string, rawText?: string, templateFlags?: TokenFlags): TemplateHead; createTemplateHead(text: string | undefined, rawText: string, templateFlags?: TokenFlags): TemplateHead; createTemplateMiddle(text: string, rawText?: string, templateFlags?: TokenFlags): TemplateMiddle; @@ -8427,19 +9322,54 @@ export interface NodeFactory { createTemplateTail(text: string | undefined, rawText: string, templateFlags?: TokenFlags): TemplateTail; createNoSubstitutionTemplateLiteral(text: string, rawText?: string): NoSubstitutionTemplateLiteral; createNoSubstitutionTemplateLiteral(text: string | undefined, rawText: string): NoSubstitutionTemplateLiteral; - /** @internal */ createLiteralLikeNode(kind: LiteralToken["kind"] | SyntaxKind.JsxTextAllWhiteSpaces, text: string): LiteralToken; - /** @internal */ createTemplateLiteralLikeNode(kind: TemplateLiteralToken["kind"], text: string, rawText: string, templateFlags: TokenFlags | undefined): TemplateLiteralLikeNode; + /** @internal */ createLiteralLikeNode( + kind: LiteralToken["kind"] | SyntaxKind.JsxTextAllWhiteSpaces, + text: string, + ): LiteralToken; + /** @internal */ createTemplateLiteralLikeNode( + kind: TemplateLiteralToken["kind"], + text: string, + rawText: string, + templateFlags: TokenFlags | undefined, + ): TemplateLiteralLikeNode; createYieldExpression(asteriskToken: AsteriskToken, expression: Expression): YieldExpression; createYieldExpression(asteriskToken: undefined, expression: Expression | undefined): YieldExpression; - /** @internal */ createYieldExpression(asteriskToken: AsteriskToken | undefined, expression: Expression | undefined): YieldExpression; // eslint-disable-line @typescript-eslint/unified-signatures - updateYieldExpression(node: YieldExpression, asteriskToken: AsteriskToken | undefined, expression: Expression | undefined): YieldExpression; + /** @internal */ createYieldExpression( + asteriskToken: AsteriskToken | undefined, + expression: Expression | undefined, + ): YieldExpression; // eslint-disable-line @typescript-eslint/unified-signatures + updateYieldExpression( + node: YieldExpression, + asteriskToken: AsteriskToken | undefined, + expression: Expression | undefined, + ): YieldExpression; createSpreadElement(expression: Expression): SpreadElement; updateSpreadElement(node: SpreadElement, expression: Expression): SpreadElement; - createClassExpression(modifiers: readonly ModifierLike[] | undefined, name: string | Identifier | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, heritageClauses: readonly HeritageClause[] | undefined, members: readonly ClassElement[]): ClassExpression; - updateClassExpression(node: ClassExpression, modifiers: readonly ModifierLike[] | undefined, name: Identifier | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, heritageClauses: readonly HeritageClause[] | undefined, members: readonly ClassElement[]): ClassExpression; + createClassExpression( + modifiers: readonly ModifierLike[] | undefined, + name: string | Identifier | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + heritageClauses: readonly HeritageClause[] | undefined, + members: readonly ClassElement[], + ): ClassExpression; + updateClassExpression( + node: ClassExpression, + modifiers: readonly ModifierLike[] | undefined, + name: Identifier | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + heritageClauses: readonly HeritageClause[] | undefined, + members: readonly ClassElement[], + ): ClassExpression; createOmittedExpression(): OmittedExpression; - createExpressionWithTypeArguments(expression: Expression, typeArguments: readonly TypeNode[] | undefined): ExpressionWithTypeArguments; - updateExpressionWithTypeArguments(node: ExpressionWithTypeArguments, expression: Expression, typeArguments: readonly TypeNode[] | undefined): ExpressionWithTypeArguments; + createExpressionWithTypeArguments( + expression: Expression, + typeArguments: readonly TypeNode[] | undefined, + ): ExpressionWithTypeArguments; + updateExpressionWithTypeArguments( + node: ExpressionWithTypeArguments, + expression: Expression, + typeArguments: readonly TypeNode[] | undefined, + ): ExpressionWithTypeArguments; createAsExpression(expression: Expression, type: TypeNode): AsExpression; updateAsExpression(node: AsExpression, expression: Expression, type: TypeNode): AsExpression; createNonNullExpression(expression: Expression): NonNullExpression; @@ -8456,7 +9386,11 @@ export interface NodeFactory { // createTemplateSpan(expression: Expression, literal: TemplateMiddle | TemplateTail): TemplateSpan; - updateTemplateSpan(node: TemplateSpan, expression: Expression, literal: TemplateMiddle | TemplateTail): TemplateSpan; + updateTemplateSpan( + node: TemplateSpan, + expression: Expression, + literal: TemplateMiddle | TemplateTail, + ): TemplateSpan; createSemicolonClassElement(): SemicolonClassElement; // @@ -8465,23 +9399,62 @@ export interface NodeFactory { createBlock(statements: readonly Statement[], multiLine?: boolean): Block; updateBlock(node: Block, statements: readonly Statement[]): Block; - createVariableStatement(modifiers: readonly ModifierLike[] | undefined, declarationList: VariableDeclarationList | readonly VariableDeclaration[]): VariableStatement; - updateVariableStatement(node: VariableStatement, modifiers: readonly ModifierLike[] | undefined, declarationList: VariableDeclarationList): VariableStatement; + createVariableStatement( + modifiers: readonly ModifierLike[] | undefined, + declarationList: VariableDeclarationList | readonly VariableDeclaration[], + ): VariableStatement; + updateVariableStatement( + node: VariableStatement, + modifiers: readonly ModifierLike[] | undefined, + declarationList: VariableDeclarationList, + ): VariableStatement; createEmptyStatement(): EmptyStatement; createExpressionStatement(expression: Expression): ExpressionStatement; updateExpressionStatement(node: ExpressionStatement, expression: Expression): ExpressionStatement; createIfStatement(expression: Expression, thenStatement: Statement, elseStatement?: Statement): IfStatement; - updateIfStatement(node: IfStatement, expression: Expression, thenStatement: Statement, elseStatement: Statement | undefined): IfStatement; + updateIfStatement( + node: IfStatement, + expression: Expression, + thenStatement: Statement, + elseStatement: Statement | undefined, + ): IfStatement; createDoStatement(statement: Statement, expression: Expression): DoStatement; updateDoStatement(node: DoStatement, statement: Statement, expression: Expression): DoStatement; createWhileStatement(expression: Expression, statement: Statement): WhileStatement; updateWhileStatement(node: WhileStatement, expression: Expression, statement: Statement): WhileStatement; - createForStatement(initializer: ForInitializer | undefined, condition: Expression | undefined, incrementor: Expression | undefined, statement: Statement): ForStatement; - updateForStatement(node: ForStatement, initializer: ForInitializer | undefined, condition: Expression | undefined, incrementor: Expression | undefined, statement: Statement): ForStatement; + createForStatement( + initializer: ForInitializer | undefined, + condition: Expression | undefined, + incrementor: Expression | undefined, + statement: Statement, + ): ForStatement; + updateForStatement( + node: ForStatement, + initializer: ForInitializer | undefined, + condition: Expression | undefined, + incrementor: Expression | undefined, + statement: Statement, + ): ForStatement; createForInStatement(initializer: ForInitializer, expression: Expression, statement: Statement): ForInStatement; - updateForInStatement(node: ForInStatement, initializer: ForInitializer, expression: Expression, statement: Statement): ForInStatement; - createForOfStatement(awaitModifier: AwaitKeyword | undefined, initializer: ForInitializer, expression: Expression, statement: Statement): ForOfStatement; - updateForOfStatement(node: ForOfStatement, awaitModifier: AwaitKeyword | undefined, initializer: ForInitializer, expression: Expression, statement: Statement): ForOfStatement; + updateForInStatement( + node: ForInStatement, + initializer: ForInitializer, + expression: Expression, + statement: Statement, + ): ForInStatement; + createForOfStatement( + awaitModifier: AwaitKeyword | undefined, + initializer: ForInitializer, + expression: Expression, + statement: Statement, + ): ForOfStatement; + updateForOfStatement( + node: ForOfStatement, + awaitModifier: AwaitKeyword | undefined, + initializer: ForInitializer, + expression: Expression, + statement: Statement, + ): ForOfStatement; createContinueStatement(label?: string | Identifier): ContinueStatement; updateContinueStatement(node: ContinueStatement, label: Identifier | undefined): ContinueStatement; createBreakStatement(label?: string | Identifier): BreakStatement; @@ -8496,43 +9469,177 @@ export interface NodeFactory { updateLabeledStatement(node: LabeledStatement, label: Identifier, statement: Statement): LabeledStatement; createThrowStatement(expression: Expression): ThrowStatement; updateThrowStatement(node: ThrowStatement, expression: Expression): ThrowStatement; - createTryStatement(tryBlock: Block, catchClause: CatchClause | undefined, finallyBlock: Block | undefined): TryStatement; - updateTryStatement(node: TryStatement, tryBlock: Block, catchClause: CatchClause | undefined, finallyBlock: Block | undefined): TryStatement; + createTryStatement( + tryBlock: Block, + catchClause: CatchClause | undefined, + finallyBlock: Block | undefined, + ): TryStatement; + updateTryStatement( + node: TryStatement, + tryBlock: Block, + catchClause: CatchClause | undefined, + finallyBlock: Block | undefined, + ): TryStatement; createDebuggerStatement(): DebuggerStatement; - createVariableDeclaration(name: string | BindingName, exclamationToken?: ExclamationToken, type?: TypeNode, initializer?: Expression): VariableDeclaration; - updateVariableDeclaration(node: VariableDeclaration, name: BindingName, exclamationToken: ExclamationToken | undefined, type: TypeNode | undefined, initializer: Expression | undefined): VariableDeclaration; - createVariableDeclarationList(declarations: readonly VariableDeclaration[], flags?: NodeFlags): VariableDeclarationList; - updateVariableDeclarationList(node: VariableDeclarationList, declarations: readonly VariableDeclaration[]): VariableDeclarationList; - createFunctionDeclaration(modifiers: readonly ModifierLike[] | undefined, asteriskToken: AsteriskToken | undefined, name: string | Identifier | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined): FunctionDeclaration; - updateFunctionDeclaration(node: FunctionDeclaration, modifiers: readonly ModifierLike[] | undefined, asteriskToken: AsteriskToken | undefined, name: Identifier | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined): FunctionDeclaration; - createClassDeclaration(modifiers: readonly ModifierLike[] | undefined, name: string | Identifier | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, heritageClauses: readonly HeritageClause[] | undefined, members: readonly ClassElement[]): ClassDeclaration; - updateClassDeclaration(node: ClassDeclaration, modifiers: readonly ModifierLike[] | undefined, name: Identifier | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, heritageClauses: readonly HeritageClause[] | undefined, members: readonly ClassElement[]): ClassDeclaration; - createInterfaceDeclaration(modifiers: readonly ModifierLike[] | undefined, name: string | Identifier, typeParameters: readonly TypeParameterDeclaration[] | undefined, heritageClauses: readonly HeritageClause[] | undefined, members: readonly TypeElement[]): InterfaceDeclaration; - updateInterfaceDeclaration(node: InterfaceDeclaration, modifiers: readonly ModifierLike[] | undefined, name: Identifier, typeParameters: readonly TypeParameterDeclaration[] | undefined, heritageClauses: readonly HeritageClause[] | undefined, members: readonly TypeElement[]): InterfaceDeclaration; - createTypeAliasDeclaration(modifiers: readonly ModifierLike[] | undefined, name: string | Identifier, typeParameters: readonly TypeParameterDeclaration[] | undefined, type: TypeNode): TypeAliasDeclaration; - updateTypeAliasDeclaration(node: TypeAliasDeclaration, modifiers: readonly ModifierLike[] | undefined, name: Identifier, typeParameters: readonly TypeParameterDeclaration[] | undefined, type: TypeNode): TypeAliasDeclaration; - createEnumDeclaration(modifiers: readonly ModifierLike[] | undefined, name: string | Identifier, members: readonly EnumMember[]): EnumDeclaration; - updateEnumDeclaration(node: EnumDeclaration, modifiers: readonly ModifierLike[] | undefined, name: Identifier, members: readonly EnumMember[]): EnumDeclaration; - createModuleDeclaration(modifiers: readonly ModifierLike[] | undefined, name: ModuleName, body: ModuleBody | undefined, flags?: NodeFlags): ModuleDeclaration; - updateModuleDeclaration(node: ModuleDeclaration, modifiers: readonly ModifierLike[] | undefined, name: ModuleName, body: ModuleBody | undefined): ModuleDeclaration; + createVariableDeclaration( + name: string | BindingName, + exclamationToken?: ExclamationToken, + type?: TypeNode, + initializer?: Expression, + ): VariableDeclaration; + updateVariableDeclaration( + node: VariableDeclaration, + name: BindingName, + exclamationToken: ExclamationToken | undefined, + type: TypeNode | undefined, + initializer: Expression | undefined, + ): VariableDeclaration; + createVariableDeclarationList( + declarations: readonly VariableDeclaration[], + flags?: NodeFlags, + ): VariableDeclarationList; + updateVariableDeclarationList( + node: VariableDeclarationList, + declarations: readonly VariableDeclaration[], + ): VariableDeclarationList; + createFunctionDeclaration( + modifiers: readonly ModifierLike[] | undefined, + asteriskToken: AsteriskToken | undefined, + name: string | Identifier | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + parameters: readonly ParameterDeclaration[], + type: TypeNode | undefined, + body: Block | undefined, + ): FunctionDeclaration; + updateFunctionDeclaration( + node: FunctionDeclaration, + modifiers: readonly ModifierLike[] | undefined, + asteriskToken: AsteriskToken | undefined, + name: Identifier | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + parameters: readonly ParameterDeclaration[], + type: TypeNode | undefined, + body: Block | undefined, + ): FunctionDeclaration; + createClassDeclaration( + modifiers: readonly ModifierLike[] | undefined, + name: string | Identifier | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + heritageClauses: readonly HeritageClause[] | undefined, + members: readonly ClassElement[], + ): ClassDeclaration; + updateClassDeclaration( + node: ClassDeclaration, + modifiers: readonly ModifierLike[] | undefined, + name: Identifier | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + heritageClauses: readonly HeritageClause[] | undefined, + members: readonly ClassElement[], + ): ClassDeclaration; + createInterfaceDeclaration( + modifiers: readonly ModifierLike[] | undefined, + name: string | Identifier, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + heritageClauses: readonly HeritageClause[] | undefined, + members: readonly TypeElement[], + ): InterfaceDeclaration; + updateInterfaceDeclaration( + node: InterfaceDeclaration, + modifiers: readonly ModifierLike[] | undefined, + name: Identifier, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + heritageClauses: readonly HeritageClause[] | undefined, + members: readonly TypeElement[], + ): InterfaceDeclaration; + createTypeAliasDeclaration( + modifiers: readonly ModifierLike[] | undefined, + name: string | Identifier, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + type: TypeNode, + ): TypeAliasDeclaration; + updateTypeAliasDeclaration( + node: TypeAliasDeclaration, + modifiers: readonly ModifierLike[] | undefined, + name: Identifier, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + type: TypeNode, + ): TypeAliasDeclaration; + createEnumDeclaration( + modifiers: readonly ModifierLike[] | undefined, + name: string | Identifier, + members: readonly EnumMember[], + ): EnumDeclaration; + updateEnumDeclaration( + node: EnumDeclaration, + modifiers: readonly ModifierLike[] | undefined, + name: Identifier, + members: readonly EnumMember[], + ): EnumDeclaration; + createModuleDeclaration( + modifiers: readonly ModifierLike[] | undefined, + name: ModuleName, + body: ModuleBody | undefined, + flags?: NodeFlags, + ): ModuleDeclaration; + updateModuleDeclaration( + node: ModuleDeclaration, + modifiers: readonly ModifierLike[] | undefined, + name: ModuleName, + body: ModuleBody | undefined, + ): ModuleDeclaration; createModuleBlock(statements: readonly Statement[]): ModuleBlock; updateModuleBlock(node: ModuleBlock, statements: readonly Statement[]): ModuleBlock; createCaseBlock(clauses: readonly CaseOrDefaultClause[]): CaseBlock; updateCaseBlock(node: CaseBlock, clauses: readonly CaseOrDefaultClause[]): CaseBlock; createNamespaceExportDeclaration(name: string | Identifier): NamespaceExportDeclaration; updateNamespaceExportDeclaration(node: NamespaceExportDeclaration, name: Identifier): NamespaceExportDeclaration; - createImportEqualsDeclaration(modifiers: readonly ModifierLike[] | undefined, isTypeOnly: boolean, name: string | Identifier, moduleReference: ModuleReference): ImportEqualsDeclaration; - updateImportEqualsDeclaration(node: ImportEqualsDeclaration, modifiers: readonly ModifierLike[] | undefined, isTypeOnly: boolean, name: Identifier, moduleReference: ModuleReference): ImportEqualsDeclaration; - createImportDeclaration(modifiers: readonly ModifierLike[] | undefined, importClause: ImportClause | undefined, moduleSpecifier: Expression, assertClause?: AssertClause): ImportDeclaration; - updateImportDeclaration(node: ImportDeclaration, modifiers: readonly ModifierLike[] | undefined, importClause: ImportClause | undefined, moduleSpecifier: Expression, assertClause: AssertClause | undefined): ImportDeclaration; - createImportClause(isTypeOnly: boolean, name: Identifier | undefined, namedBindings: NamedImportBindings | undefined): ImportClause; - updateImportClause(node: ImportClause, isTypeOnly: boolean, name: Identifier | undefined, namedBindings: NamedImportBindings | undefined): ImportClause; + createImportEqualsDeclaration( + modifiers: readonly ModifierLike[] | undefined, + isTypeOnly: boolean, + name: string | Identifier, + moduleReference: ModuleReference, + ): ImportEqualsDeclaration; + updateImportEqualsDeclaration( + node: ImportEqualsDeclaration, + modifiers: readonly ModifierLike[] | undefined, + isTypeOnly: boolean, + name: Identifier, + moduleReference: ModuleReference, + ): ImportEqualsDeclaration; + createImportDeclaration( + modifiers: readonly ModifierLike[] | undefined, + importClause: ImportClause | undefined, + moduleSpecifier: Expression, + assertClause?: AssertClause, + ): ImportDeclaration; + updateImportDeclaration( + node: ImportDeclaration, + modifiers: readonly ModifierLike[] | undefined, + importClause: ImportClause | undefined, + moduleSpecifier: Expression, + assertClause: AssertClause | undefined, + ): ImportDeclaration; + createImportClause( + isTypeOnly: boolean, + name: Identifier | undefined, + namedBindings: NamedImportBindings | undefined, + ): ImportClause; + updateImportClause( + node: ImportClause, + isTypeOnly: boolean, + name: Identifier | undefined, + namedBindings: NamedImportBindings | undefined, + ): ImportClause; createAssertClause(elements: NodeArray, multiLine?: boolean): AssertClause; updateAssertClause(node: AssertClause, elements: NodeArray, multiLine?: boolean): AssertClause; createAssertEntry(name: AssertionKey, value: Expression): AssertEntry; updateAssertEntry(node: AssertEntry, name: AssertionKey, value: Expression): AssertEntry; createImportTypeAssertionContainer(clause: AssertClause, multiLine?: boolean): ImportTypeAssertionContainer; - updateImportTypeAssertionContainer(node: ImportTypeAssertionContainer, clause: AssertClause, multiLine?: boolean): ImportTypeAssertionContainer; + updateImportTypeAssertionContainer( + node: ImportTypeAssertionContainer, + clause: AssertClause, + multiLine?: boolean, + ): ImportTypeAssertionContainer; createNamespaceImport(name: Identifier): NamespaceImport; updateNamespaceImport(node: NamespaceImport, name: Identifier): NamespaceImport; createNamespaceExport(name: Identifier): NamespaceExport; @@ -8540,15 +9647,50 @@ export interface NodeFactory { createNamedImports(elements: readonly ImportSpecifier[]): NamedImports; updateNamedImports(node: NamedImports, elements: readonly ImportSpecifier[]): NamedImports; createImportSpecifier(isTypeOnly: boolean, propertyName: Identifier | undefined, name: Identifier): ImportSpecifier; - updateImportSpecifier(node: ImportSpecifier, isTypeOnly: boolean, propertyName: Identifier | undefined, name: Identifier): ImportSpecifier; - createExportAssignment(modifiers: readonly ModifierLike[] | undefined, isExportEquals: boolean | undefined, expression: Expression): ExportAssignment; - updateExportAssignment(node: ExportAssignment, modifiers: readonly ModifierLike[] | undefined, expression: Expression): ExportAssignment; - createExportDeclaration(modifiers: readonly ModifierLike[] | undefined, isTypeOnly: boolean, exportClause: NamedExportBindings | undefined, moduleSpecifier?: Expression, assertClause?: AssertClause): ExportDeclaration; - updateExportDeclaration(node: ExportDeclaration, modifiers: readonly ModifierLike[] | undefined, isTypeOnly: boolean, exportClause: NamedExportBindings | undefined, moduleSpecifier: Expression | undefined, assertClause: AssertClause | undefined): ExportDeclaration; + updateImportSpecifier( + node: ImportSpecifier, + isTypeOnly: boolean, + propertyName: Identifier | undefined, + name: Identifier, + ): ImportSpecifier; + createExportAssignment( + modifiers: readonly ModifierLike[] | undefined, + isExportEquals: boolean | undefined, + expression: Expression, + ): ExportAssignment; + updateExportAssignment( + node: ExportAssignment, + modifiers: readonly ModifierLike[] | undefined, + expression: Expression, + ): ExportAssignment; + createExportDeclaration( + modifiers: readonly ModifierLike[] | undefined, + isTypeOnly: boolean, + exportClause: NamedExportBindings | undefined, + moduleSpecifier?: Expression, + assertClause?: AssertClause, + ): ExportDeclaration; + updateExportDeclaration( + node: ExportDeclaration, + modifiers: readonly ModifierLike[] | undefined, + isTypeOnly: boolean, + exportClause: NamedExportBindings | undefined, + moduleSpecifier: Expression | undefined, + assertClause: AssertClause | undefined, + ): ExportDeclaration; createNamedExports(elements: readonly ExportSpecifier[]): NamedExports; updateNamedExports(node: NamedExports, elements: readonly ExportSpecifier[]): NamedExports; - createExportSpecifier(isTypeOnly: boolean, propertyName: string | Identifier | undefined, name: string | Identifier): ExportSpecifier; - updateExportSpecifier(node: ExportSpecifier, isTypeOnly: boolean, propertyName: Identifier | undefined, name: Identifier): ExportSpecifier; + createExportSpecifier( + isTypeOnly: boolean, + propertyName: string | Identifier | undefined, + name: string | Identifier, + ): ExportSpecifier; + updateExportSpecifier( + node: ExportSpecifier, + isTypeOnly: boolean, + propertyName: Identifier | undefined, + name: Identifier, + ): ExportSpecifier; /** @internal */ createMissingDeclaration(): MissingDeclaration; // @@ -8571,7 +9713,11 @@ export interface NodeFactory { createJSDocOptionalType(type: TypeNode): JSDocOptionalType; updateJSDocOptionalType(node: JSDocOptionalType, type: TypeNode): JSDocOptionalType; createJSDocFunctionType(parameters: readonly ParameterDeclaration[], type: TypeNode | undefined): JSDocFunctionType; - updateJSDocFunctionType(node: JSDocFunctionType, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined): JSDocFunctionType; + updateJSDocFunctionType( + node: JSDocFunctionType, + parameters: readonly ParameterDeclaration[], + type: TypeNode | undefined, + ): JSDocFunctionType; createJSDocVariadicType(type: TypeNode): JSDocVariadicType; updateJSDocVariadicType(node: JSDocVariadicType, type: TypeNode): JSDocVariadicType; createJSDocNamepathType(type: TypeNode): JSDocNamepathType; @@ -8581,90 +9727,366 @@ export interface NodeFactory { createJSDocNameReference(name: EntityName | JSDocMemberName): JSDocNameReference; updateJSDocNameReference(node: JSDocNameReference, name: EntityName | JSDocMemberName): JSDocNameReference; createJSDocMemberName(left: EntityName | JSDocMemberName, right: Identifier): JSDocMemberName; - updateJSDocMemberName(node: JSDocMemberName, left: EntityName | JSDocMemberName, right: Identifier): JSDocMemberName; + updateJSDocMemberName( + node: JSDocMemberName, + left: EntityName | JSDocMemberName, + right: Identifier, + ): JSDocMemberName; createJSDocLink(name: EntityName | JSDocMemberName | undefined, text: string): JSDocLink; updateJSDocLink(node: JSDocLink, name: EntityName | JSDocMemberName | undefined, text: string): JSDocLink; createJSDocLinkCode(name: EntityName | JSDocMemberName | undefined, text: string): JSDocLinkCode; - updateJSDocLinkCode(node: JSDocLinkCode, name: EntityName | JSDocMemberName | undefined, text: string): JSDocLinkCode; + updateJSDocLinkCode( + node: JSDocLinkCode, + name: EntityName | JSDocMemberName | undefined, + text: string, + ): JSDocLinkCode; createJSDocLinkPlain(name: EntityName | JSDocMemberName | undefined, text: string): JSDocLinkPlain; - updateJSDocLinkPlain(node: JSDocLinkPlain, name: EntityName | JSDocMemberName | undefined, text: string): JSDocLinkPlain; - createJSDocTypeLiteral(jsDocPropertyTags?: readonly JSDocPropertyLikeTag[], isArrayType?: boolean): JSDocTypeLiteral; - updateJSDocTypeLiteral(node: JSDocTypeLiteral, jsDocPropertyTags: readonly JSDocPropertyLikeTag[] | undefined, isArrayType: boolean | undefined): JSDocTypeLiteral; - createJSDocSignature(typeParameters: readonly JSDocTemplateTag[] | undefined, parameters: readonly JSDocParameterTag[], type?: JSDocReturnTag): JSDocSignature; - updateJSDocSignature(node: JSDocSignature, typeParameters: readonly JSDocTemplateTag[] | undefined, parameters: readonly JSDocParameterTag[], type: JSDocReturnTag | undefined): JSDocSignature; - createJSDocTemplateTag(tagName: Identifier | undefined, constraint: JSDocTypeExpression | undefined, typeParameters: readonly TypeParameterDeclaration[], comment?: string | NodeArray): JSDocTemplateTag; - updateJSDocTemplateTag(node: JSDocTemplateTag, tagName: Identifier | undefined, constraint: JSDocTypeExpression | undefined, typeParameters: readonly TypeParameterDeclaration[], comment: string | NodeArray | undefined): JSDocTemplateTag; - createJSDocTypedefTag(tagName: Identifier | undefined, typeExpression?: JSDocTypeExpression | JSDocTypeLiteral, fullName?: Identifier | JSDocNamespaceDeclaration, comment?: string | NodeArray): JSDocTypedefTag; - updateJSDocTypedefTag(node: JSDocTypedefTag, tagName: Identifier | undefined, typeExpression: JSDocTypeExpression | JSDocTypeLiteral | undefined, fullName: Identifier | JSDocNamespaceDeclaration | undefined, comment: string | NodeArray | undefined): JSDocTypedefTag; - createJSDocParameterTag(tagName: Identifier | undefined, name: EntityName, isBracketed: boolean, typeExpression?: JSDocTypeExpression, isNameFirst?: boolean, comment?: string | NodeArray): JSDocParameterTag; - updateJSDocParameterTag(node: JSDocParameterTag, tagName: Identifier | undefined, name: EntityName, isBracketed: boolean, typeExpression: JSDocTypeExpression | undefined, isNameFirst: boolean, comment: string | NodeArray | undefined): JSDocParameterTag; - createJSDocPropertyTag(tagName: Identifier | undefined, name: EntityName, isBracketed: boolean, typeExpression?: JSDocTypeExpression, isNameFirst?: boolean, comment?: string | NodeArray): JSDocPropertyTag; - updateJSDocPropertyTag(node: JSDocPropertyTag, tagName: Identifier | undefined, name: EntityName, isBracketed: boolean, typeExpression: JSDocTypeExpression | undefined, isNameFirst: boolean, comment: string | NodeArray | undefined): JSDocPropertyTag; - createJSDocTypeTag(tagName: Identifier | undefined, typeExpression: JSDocTypeExpression, comment?: string | NodeArray): JSDocTypeTag; - updateJSDocTypeTag(node: JSDocTypeTag, tagName: Identifier | undefined, typeExpression: JSDocTypeExpression, comment: string | NodeArray | undefined): JSDocTypeTag; - createJSDocSeeTag(tagName: Identifier | undefined, nameExpression: JSDocNameReference | undefined, comment?: string | NodeArray): JSDocSeeTag; - updateJSDocSeeTag(node: JSDocSeeTag, tagName: Identifier | undefined, nameExpression: JSDocNameReference | undefined, comment?: string | NodeArray): JSDocSeeTag; - createJSDocReturnTag(tagName: Identifier | undefined, typeExpression?: JSDocTypeExpression, comment?: string | NodeArray): JSDocReturnTag; - updateJSDocReturnTag(node: JSDocReturnTag, tagName: Identifier | undefined, typeExpression: JSDocTypeExpression | undefined, comment: string | NodeArray | undefined): JSDocReturnTag; - createJSDocThisTag(tagName: Identifier | undefined, typeExpression: JSDocTypeExpression, comment?: string | NodeArray): JSDocThisTag; - updateJSDocThisTag(node: JSDocThisTag, tagName: Identifier | undefined, typeExpression: JSDocTypeExpression | undefined, comment: string | NodeArray | undefined): JSDocThisTag; - createJSDocEnumTag(tagName: Identifier | undefined, typeExpression: JSDocTypeExpression, comment?: string | NodeArray): JSDocEnumTag; - updateJSDocEnumTag(node: JSDocEnumTag, tagName: Identifier | undefined, typeExpression: JSDocTypeExpression, comment: string | NodeArray | undefined): JSDocEnumTag; - createJSDocCallbackTag(tagName: Identifier | undefined, typeExpression: JSDocSignature, fullName?: Identifier | JSDocNamespaceDeclaration, comment?: string | NodeArray): JSDocCallbackTag; - updateJSDocCallbackTag(node: JSDocCallbackTag, tagName: Identifier | undefined, typeExpression: JSDocSignature, fullName: Identifier | JSDocNamespaceDeclaration | undefined, comment: string | NodeArray | undefined): JSDocCallbackTag; - createJSDocOverloadTag(tagName: Identifier | undefined, typeExpression: JSDocSignature, comment?: string | NodeArray): JSDocOverloadTag; - updateJSDocOverloadTag(node: JSDocOverloadTag, tagName: Identifier | undefined, typeExpression: JSDocSignature, comment: string | NodeArray | undefined): JSDocOverloadTag; - createJSDocAugmentsTag(tagName: Identifier | undefined, className: JSDocAugmentsTag["class"], comment?: string | NodeArray): JSDocAugmentsTag; - updateJSDocAugmentsTag(node: JSDocAugmentsTag, tagName: Identifier | undefined, className: JSDocAugmentsTag["class"], comment: string | NodeArray | undefined): JSDocAugmentsTag; - createJSDocImplementsTag(tagName: Identifier | undefined, className: JSDocImplementsTag["class"], comment?: string | NodeArray): JSDocImplementsTag; - updateJSDocImplementsTag(node: JSDocImplementsTag, tagName: Identifier | undefined, className: JSDocImplementsTag["class"], comment: string | NodeArray | undefined): JSDocImplementsTag; + updateJSDocLinkPlain( + node: JSDocLinkPlain, + name: EntityName | JSDocMemberName | undefined, + text: string, + ): JSDocLinkPlain; + createJSDocTypeLiteral( + jsDocPropertyTags?: readonly JSDocPropertyLikeTag[], + isArrayType?: boolean, + ): JSDocTypeLiteral; + updateJSDocTypeLiteral( + node: JSDocTypeLiteral, + jsDocPropertyTags: readonly JSDocPropertyLikeTag[] | undefined, + isArrayType: boolean | undefined, + ): JSDocTypeLiteral; + createJSDocSignature( + typeParameters: readonly JSDocTemplateTag[] | undefined, + parameters: readonly JSDocParameterTag[], + type?: JSDocReturnTag, + ): JSDocSignature; + updateJSDocSignature( + node: JSDocSignature, + typeParameters: readonly JSDocTemplateTag[] | undefined, + parameters: readonly JSDocParameterTag[], + type: JSDocReturnTag | undefined, + ): JSDocSignature; + createJSDocTemplateTag( + tagName: Identifier | undefined, + constraint: JSDocTypeExpression | undefined, + typeParameters: readonly TypeParameterDeclaration[], + comment?: string | NodeArray, + ): JSDocTemplateTag; + updateJSDocTemplateTag( + node: JSDocTemplateTag, + tagName: Identifier | undefined, + constraint: JSDocTypeExpression | undefined, + typeParameters: readonly TypeParameterDeclaration[], + comment: string | NodeArray | undefined, + ): JSDocTemplateTag; + createJSDocTypedefTag( + tagName: Identifier | undefined, + typeExpression?: JSDocTypeExpression | JSDocTypeLiteral, + fullName?: Identifier | JSDocNamespaceDeclaration, + comment?: string | NodeArray, + ): JSDocTypedefTag; + updateJSDocTypedefTag( + node: JSDocTypedefTag, + tagName: Identifier | undefined, + typeExpression: JSDocTypeExpression | JSDocTypeLiteral | undefined, + fullName: Identifier | JSDocNamespaceDeclaration | undefined, + comment: string | NodeArray | undefined, + ): JSDocTypedefTag; + createJSDocParameterTag( + tagName: Identifier | undefined, + name: EntityName, + isBracketed: boolean, + typeExpression?: JSDocTypeExpression, + isNameFirst?: boolean, + comment?: string | NodeArray, + ): JSDocParameterTag; + updateJSDocParameterTag( + node: JSDocParameterTag, + tagName: Identifier | undefined, + name: EntityName, + isBracketed: boolean, + typeExpression: JSDocTypeExpression | undefined, + isNameFirst: boolean, + comment: string | NodeArray | undefined, + ): JSDocParameterTag; + createJSDocPropertyTag( + tagName: Identifier | undefined, + name: EntityName, + isBracketed: boolean, + typeExpression?: JSDocTypeExpression, + isNameFirst?: boolean, + comment?: string | NodeArray, + ): JSDocPropertyTag; + updateJSDocPropertyTag( + node: JSDocPropertyTag, + tagName: Identifier | undefined, + name: EntityName, + isBracketed: boolean, + typeExpression: JSDocTypeExpression | undefined, + isNameFirst: boolean, + comment: string | NodeArray | undefined, + ): JSDocPropertyTag; + createJSDocTypeTag( + tagName: Identifier | undefined, + typeExpression: JSDocTypeExpression, + comment?: string | NodeArray, + ): JSDocTypeTag; + updateJSDocTypeTag( + node: JSDocTypeTag, + tagName: Identifier | undefined, + typeExpression: JSDocTypeExpression, + comment: string | NodeArray | undefined, + ): JSDocTypeTag; + createJSDocSeeTag( + tagName: Identifier | undefined, + nameExpression: JSDocNameReference | undefined, + comment?: string | NodeArray, + ): JSDocSeeTag; + updateJSDocSeeTag( + node: JSDocSeeTag, + tagName: Identifier | undefined, + nameExpression: JSDocNameReference | undefined, + comment?: string | NodeArray, + ): JSDocSeeTag; + createJSDocReturnTag( + tagName: Identifier | undefined, + typeExpression?: JSDocTypeExpression, + comment?: string | NodeArray, + ): JSDocReturnTag; + updateJSDocReturnTag( + node: JSDocReturnTag, + tagName: Identifier | undefined, + typeExpression: JSDocTypeExpression | undefined, + comment: string | NodeArray | undefined, + ): JSDocReturnTag; + createJSDocThisTag( + tagName: Identifier | undefined, + typeExpression: JSDocTypeExpression, + comment?: string | NodeArray, + ): JSDocThisTag; + updateJSDocThisTag( + node: JSDocThisTag, + tagName: Identifier | undefined, + typeExpression: JSDocTypeExpression | undefined, + comment: string | NodeArray | undefined, + ): JSDocThisTag; + createJSDocEnumTag( + tagName: Identifier | undefined, + typeExpression: JSDocTypeExpression, + comment?: string | NodeArray, + ): JSDocEnumTag; + updateJSDocEnumTag( + node: JSDocEnumTag, + tagName: Identifier | undefined, + typeExpression: JSDocTypeExpression, + comment: string | NodeArray | undefined, + ): JSDocEnumTag; + createJSDocCallbackTag( + tagName: Identifier | undefined, + typeExpression: JSDocSignature, + fullName?: Identifier | JSDocNamespaceDeclaration, + comment?: string | NodeArray, + ): JSDocCallbackTag; + updateJSDocCallbackTag( + node: JSDocCallbackTag, + tagName: Identifier | undefined, + typeExpression: JSDocSignature, + fullName: Identifier | JSDocNamespaceDeclaration | undefined, + comment: string | NodeArray | undefined, + ): JSDocCallbackTag; + createJSDocOverloadTag( + tagName: Identifier | undefined, + typeExpression: JSDocSignature, + comment?: string | NodeArray, + ): JSDocOverloadTag; + updateJSDocOverloadTag( + node: JSDocOverloadTag, + tagName: Identifier | undefined, + typeExpression: JSDocSignature, + comment: string | NodeArray | undefined, + ): JSDocOverloadTag; + createJSDocAugmentsTag( + tagName: Identifier | undefined, + className: JSDocAugmentsTag["class"], + comment?: string | NodeArray, + ): JSDocAugmentsTag; + updateJSDocAugmentsTag( + node: JSDocAugmentsTag, + tagName: Identifier | undefined, + className: JSDocAugmentsTag["class"], + comment: string | NodeArray | undefined, + ): JSDocAugmentsTag; + createJSDocImplementsTag( + tagName: Identifier | undefined, + className: JSDocImplementsTag["class"], + comment?: string | NodeArray, + ): JSDocImplementsTag; + updateJSDocImplementsTag( + node: JSDocImplementsTag, + tagName: Identifier | undefined, + className: JSDocImplementsTag["class"], + comment: string | NodeArray | undefined, + ): JSDocImplementsTag; createJSDocAuthorTag(tagName: Identifier | undefined, comment?: string | NodeArray): JSDocAuthorTag; - updateJSDocAuthorTag(node: JSDocAuthorTag, tagName: Identifier | undefined, comment: string | NodeArray | undefined): JSDocAuthorTag; + updateJSDocAuthorTag( + node: JSDocAuthorTag, + tagName: Identifier | undefined, + comment: string | NodeArray | undefined, + ): JSDocAuthorTag; createJSDocClassTag(tagName: Identifier | undefined, comment?: string | NodeArray): JSDocClassTag; - updateJSDocClassTag(node: JSDocClassTag, tagName: Identifier | undefined, comment: string | NodeArray | undefined): JSDocClassTag; + updateJSDocClassTag( + node: JSDocClassTag, + tagName: Identifier | undefined, + comment: string | NodeArray | undefined, + ): JSDocClassTag; createJSDocPublicTag(tagName: Identifier | undefined, comment?: string | NodeArray): JSDocPublicTag; - updateJSDocPublicTag(node: JSDocPublicTag, tagName: Identifier | undefined, comment: string | NodeArray | undefined): JSDocPublicTag; + updateJSDocPublicTag( + node: JSDocPublicTag, + tagName: Identifier | undefined, + comment: string | NodeArray | undefined, + ): JSDocPublicTag; createJSDocPrivateTag(tagName: Identifier | undefined, comment?: string | NodeArray): JSDocPrivateTag; - updateJSDocPrivateTag(node: JSDocPrivateTag, tagName: Identifier | undefined, comment: string | NodeArray | undefined): JSDocPrivateTag; - createJSDocProtectedTag(tagName: Identifier | undefined, comment?: string | NodeArray): JSDocProtectedTag; - updateJSDocProtectedTag(node: JSDocProtectedTag, tagName: Identifier | undefined, comment: string | NodeArray | undefined): JSDocProtectedTag; - createJSDocReadonlyTag(tagName: Identifier | undefined, comment?: string | NodeArray): JSDocReadonlyTag; - updateJSDocReadonlyTag(node: JSDocReadonlyTag, tagName: Identifier | undefined, comment: string | NodeArray | undefined): JSDocReadonlyTag; + updateJSDocPrivateTag( + node: JSDocPrivateTag, + tagName: Identifier | undefined, + comment: string | NodeArray | undefined, + ): JSDocPrivateTag; + createJSDocProtectedTag( + tagName: Identifier | undefined, + comment?: string | NodeArray, + ): JSDocProtectedTag; + updateJSDocProtectedTag( + node: JSDocProtectedTag, + tagName: Identifier | undefined, + comment: string | NodeArray | undefined, + ): JSDocProtectedTag; + createJSDocReadonlyTag( + tagName: Identifier | undefined, + comment?: string | NodeArray, + ): JSDocReadonlyTag; + updateJSDocReadonlyTag( + node: JSDocReadonlyTag, + tagName: Identifier | undefined, + comment: string | NodeArray | undefined, + ): JSDocReadonlyTag; createJSDocUnknownTag(tagName: Identifier, comment?: string | NodeArray): JSDocUnknownTag; - updateJSDocUnknownTag(node: JSDocUnknownTag, tagName: Identifier, comment: string | NodeArray | undefined): JSDocUnknownTag; - createJSDocDeprecatedTag(tagName: Identifier | undefined, comment?: string | NodeArray): JSDocDeprecatedTag; - updateJSDocDeprecatedTag(node: JSDocDeprecatedTag, tagName: Identifier | undefined, comment?: string | NodeArray): JSDocDeprecatedTag; - createJSDocOverrideTag(tagName: Identifier | undefined, comment?: string | NodeArray): JSDocOverrideTag; - updateJSDocOverrideTag(node: JSDocOverrideTag, tagName: Identifier | undefined, comment?: string | NodeArray): JSDocOverrideTag; - createJSDocThrowsTag(tagName: Identifier, typeExpression: JSDocTypeExpression | undefined, comment?: string | NodeArray): JSDocThrowsTag; - updateJSDocThrowsTag(node: JSDocThrowsTag, tagName: Identifier | undefined, typeExpression: JSDocTypeExpression | undefined, comment?: string | NodeArray | undefined): JSDocThrowsTag; - createJSDocSatisfiesTag(tagName: Identifier | undefined, typeExpression: JSDocTypeExpression, comment?: string | NodeArray): JSDocSatisfiesTag; - updateJSDocSatisfiesTag(node: JSDocSatisfiesTag, tagName: Identifier | undefined, typeExpression: JSDocTypeExpression, comment: string | NodeArray | undefined): JSDocSatisfiesTag; + updateJSDocUnknownTag( + node: JSDocUnknownTag, + tagName: Identifier, + comment: string | NodeArray | undefined, + ): JSDocUnknownTag; + createJSDocDeprecatedTag( + tagName: Identifier | undefined, + comment?: string | NodeArray, + ): JSDocDeprecatedTag; + updateJSDocDeprecatedTag( + node: JSDocDeprecatedTag, + tagName: Identifier | undefined, + comment?: string | NodeArray, + ): JSDocDeprecatedTag; + createJSDocOverrideTag( + tagName: Identifier | undefined, + comment?: string | NodeArray, + ): JSDocOverrideTag; + updateJSDocOverrideTag( + node: JSDocOverrideTag, + tagName: Identifier | undefined, + comment?: string | NodeArray, + ): JSDocOverrideTag; + createJSDocThrowsTag( + tagName: Identifier, + typeExpression: JSDocTypeExpression | undefined, + comment?: string | NodeArray, + ): JSDocThrowsTag; + updateJSDocThrowsTag( + node: JSDocThrowsTag, + tagName: Identifier | undefined, + typeExpression: JSDocTypeExpression | undefined, + comment?: string | NodeArray | undefined, + ): JSDocThrowsTag; + createJSDocSatisfiesTag( + tagName: Identifier | undefined, + typeExpression: JSDocTypeExpression, + comment?: string | NodeArray, + ): JSDocSatisfiesTag; + updateJSDocSatisfiesTag( + node: JSDocSatisfiesTag, + tagName: Identifier | undefined, + typeExpression: JSDocTypeExpression, + comment: string | NodeArray | undefined, + ): JSDocSatisfiesTag; createJSDocText(text: string): JSDocText; updateJSDocText(node: JSDocText, text: string): JSDocText; - createJSDocComment(comment?: string | NodeArray | undefined, tags?: readonly JSDocTag[] | undefined): JSDoc; - updateJSDocComment(node: JSDoc, comment: string | NodeArray | undefined, tags: readonly JSDocTag[] | undefined): JSDoc; + createJSDocComment( + comment?: string | NodeArray | undefined, + tags?: readonly JSDocTag[] | undefined, + ): JSDoc; + updateJSDocComment( + node: JSDoc, + comment: string | NodeArray | undefined, + tags: readonly JSDocTag[] | undefined, + ): JSDoc; // // JSX // - createJsxElement(openingElement: JsxOpeningElement, children: readonly JsxChild[], closingElement: JsxClosingElement): JsxElement; - updateJsxElement(node: JsxElement, openingElement: JsxOpeningElement, children: readonly JsxChild[], closingElement: JsxClosingElement): JsxElement; - createJsxSelfClosingElement(tagName: JsxTagNameExpression, typeArguments: readonly TypeNode[] | undefined, attributes: JsxAttributes): JsxSelfClosingElement; - updateJsxSelfClosingElement(node: JsxSelfClosingElement, tagName: JsxTagNameExpression, typeArguments: readonly TypeNode[] | undefined, attributes: JsxAttributes): JsxSelfClosingElement; - createJsxOpeningElement(tagName: JsxTagNameExpression, typeArguments: readonly TypeNode[] | undefined, attributes: JsxAttributes): JsxOpeningElement; - updateJsxOpeningElement(node: JsxOpeningElement, tagName: JsxTagNameExpression, typeArguments: readonly TypeNode[] | undefined, attributes: JsxAttributes): JsxOpeningElement; + createJsxElement( + openingElement: JsxOpeningElement, + children: readonly JsxChild[], + closingElement: JsxClosingElement, + ): JsxElement; + updateJsxElement( + node: JsxElement, + openingElement: JsxOpeningElement, + children: readonly JsxChild[], + closingElement: JsxClosingElement, + ): JsxElement; + createJsxSelfClosingElement( + tagName: JsxTagNameExpression, + typeArguments: readonly TypeNode[] | undefined, + attributes: JsxAttributes, + ): JsxSelfClosingElement; + updateJsxSelfClosingElement( + node: JsxSelfClosingElement, + tagName: JsxTagNameExpression, + typeArguments: readonly TypeNode[] | undefined, + attributes: JsxAttributes, + ): JsxSelfClosingElement; + createJsxOpeningElement( + tagName: JsxTagNameExpression, + typeArguments: readonly TypeNode[] | undefined, + attributes: JsxAttributes, + ): JsxOpeningElement; + updateJsxOpeningElement( + node: JsxOpeningElement, + tagName: JsxTagNameExpression, + typeArguments: readonly TypeNode[] | undefined, + attributes: JsxAttributes, + ): JsxOpeningElement; createJsxClosingElement(tagName: JsxTagNameExpression): JsxClosingElement; updateJsxClosingElement(node: JsxClosingElement, tagName: JsxTagNameExpression): JsxClosingElement; - createJsxFragment(openingFragment: JsxOpeningFragment, children: readonly JsxChild[], closingFragment: JsxClosingFragment): JsxFragment; + createJsxFragment( + openingFragment: JsxOpeningFragment, + children: readonly JsxChild[], + closingFragment: JsxClosingFragment, + ): JsxFragment; createJsxText(text: string, containsOnlyTriviaWhiteSpaces?: boolean): JsxText; updateJsxText(node: JsxText, text: string, containsOnlyTriviaWhiteSpaces?: boolean): JsxText; createJsxOpeningFragment(): JsxOpeningFragment; createJsxJsxClosingFragment(): JsxClosingFragment; - updateJsxFragment(node: JsxFragment, openingFragment: JsxOpeningFragment, children: readonly JsxChild[], closingFragment: JsxClosingFragment): JsxFragment; + updateJsxFragment( + node: JsxFragment, + openingFragment: JsxOpeningFragment, + children: readonly JsxChild[], + closingFragment: JsxClosingFragment, + ): JsxFragment; createJsxAttribute(name: JsxAttributeName, initializer: JsxAttributeValue | undefined): JsxAttribute; - updateJsxAttribute(node: JsxAttribute, name: JsxAttributeName, initializer: JsxAttributeValue | undefined): JsxAttribute; + updateJsxAttribute( + node: JsxAttribute, + name: JsxAttributeName, + initializer: JsxAttributeValue | undefined, + ): JsxAttribute; createJsxAttributes(properties: readonly JsxAttributeLike[]): JsxAttributes; updateJsxAttributes(node: JsxAttributes, properties: readonly JsxAttributeLike[]): JsxAttributes; createJsxSpreadAttribute(expression: Expression): JsxSpreadAttribute; @@ -8684,8 +10106,15 @@ export interface NodeFactory { updateDefaultClause(node: DefaultClause, statements: readonly Statement[]): DefaultClause; createHeritageClause(token: HeritageClause["token"], types: readonly ExpressionWithTypeArguments[]): HeritageClause; updateHeritageClause(node: HeritageClause, types: readonly ExpressionWithTypeArguments[]): HeritageClause; - createCatchClause(variableDeclaration: string | BindingName | VariableDeclaration | undefined, block: Block): CatchClause; - updateCatchClause(node: CatchClause, variableDeclaration: VariableDeclaration | undefined, block: Block): CatchClause; + createCatchClause( + variableDeclaration: string | BindingName | VariableDeclaration | undefined, + block: Block, + ): CatchClause; + updateCatchClause( + node: CatchClause, + variableDeclaration: VariableDeclaration | undefined, + block: Block, + ): CatchClause; // // Property assignments @@ -8693,8 +10122,15 @@ export interface NodeFactory { createPropertyAssignment(name: string | PropertyName, initializer: Expression): PropertyAssignment; updatePropertyAssignment(node: PropertyAssignment, name: PropertyName, initializer: Expression): PropertyAssignment; - createShorthandPropertyAssignment(name: string | Identifier, objectAssignmentInitializer?: Expression): ShorthandPropertyAssignment; - updateShorthandPropertyAssignment(node: ShorthandPropertyAssignment, name: Identifier, objectAssignmentInitializer: Expression | undefined): ShorthandPropertyAssignment; + createShorthandPropertyAssignment( + name: string | Identifier, + objectAssignmentInitializer?: Expression, + ): ShorthandPropertyAssignment; + updateShorthandPropertyAssignment( + node: ShorthandPropertyAssignment, + name: Identifier, + objectAssignmentInitializer: Expression | undefined, + ): ShorthandPropertyAssignment; createSpreadAssignment(expression: Expression): SpreadAssignment; updateSpreadAssignment(node: SpreadAssignment, expression: Expression): SpreadAssignment; @@ -8710,21 +10146,42 @@ export interface NodeFactory { // createSourceFile(statements: readonly Statement[], endOfFileToken: EndOfFileToken, flags: NodeFlags): SourceFile; - updateSourceFile(node: SourceFile, statements: readonly Statement[], isDeclarationFile?: boolean, referencedFiles?: readonly FileReference[], typeReferences?: readonly FileReference[], hasNoDefaultLib?: boolean, libReferences?: readonly FileReference[]): SourceFile; + updateSourceFile( + node: SourceFile, + statements: readonly Statement[], + isDeclarationFile?: boolean, + referencedFiles?: readonly FileReference[], + typeReferences?: readonly FileReference[], + hasNoDefaultLib?: boolean, + libReferences?: readonly FileReference[], + ): SourceFile; /** @internal */ createRedirectedSourceFile(redirectInfo: RedirectInfo): SourceFile; - /** @deprecated @internal */ createUnparsedSource(prologues: readonly UnparsedPrologue[], syntheticReferences: readonly UnparsedSyntheticReference[] | undefined, texts: readonly UnparsedSourceText[]): UnparsedSource; + /** @deprecated @internal */ createUnparsedSource( + prologues: readonly UnparsedPrologue[], + syntheticReferences: readonly UnparsedSyntheticReference[] | undefined, + texts: readonly UnparsedSourceText[], + ): UnparsedSource; /** @deprecated @internal */ createUnparsedPrologue(data?: string): UnparsedPrologue; - /** @deprecated @internal */ createUnparsedPrepend(data: string | undefined, texts: readonly UnparsedSourceText[]): UnparsedPrepend; + /** @deprecated @internal */ createUnparsedPrepend( + data: string | undefined, + texts: readonly UnparsedSourceText[], + ): UnparsedPrepend; /** @deprecated @internal */ createUnparsedTextLike(data: string | undefined, internal: boolean): UnparsedTextLike; - /** @deprecated @internal */ createUnparsedSyntheticReference(section: BundleFileHasNoDefaultLib | BundleFileReference): UnparsedSyntheticReference; + /** @deprecated @internal */ createUnparsedSyntheticReference( + section: BundleFileHasNoDefaultLib | BundleFileReference, + ): UnparsedSyntheticReference; /** @deprecated @internal */ createInputFiles(): InputFiles; // // Synthetic Nodes // - /** @internal */ createSyntheticExpression(type: Type, isSpread?: boolean, tupleNameSource?: ParameterDeclaration | NamedTupleMember): SyntheticExpression; + /** @internal */ createSyntheticExpression( + type: Type, + isSpread?: boolean, + tupleNameSource?: ParameterDeclaration | NamedTupleMember, + ): SyntheticExpression; /** @internal */ createSyntaxList(children: Node[]): SyntaxList; // @@ -8733,22 +10190,42 @@ export interface NodeFactory { createNotEmittedStatement(original: Node): NotEmittedStatement; createPartiallyEmittedExpression(expression: Expression, original?: Node): PartiallyEmittedExpression; - updatePartiallyEmittedExpression(node: PartiallyEmittedExpression, expression: Expression): PartiallyEmittedExpression; - /** @internal */ createSyntheticReferenceExpression(expression: Expression, thisArg: Expression): SyntheticReferenceExpression; - /** @internal */ updateSyntheticReferenceExpression(node: SyntheticReferenceExpression, expression: Expression, thisArg: Expression): SyntheticReferenceExpression; + updatePartiallyEmittedExpression( + node: PartiallyEmittedExpression, + expression: Expression, + ): PartiallyEmittedExpression; + /** @internal */ createSyntheticReferenceExpression( + expression: Expression, + thisArg: Expression, + ): SyntheticReferenceExpression; + /** @internal */ updateSyntheticReferenceExpression( + node: SyntheticReferenceExpression, + expression: Expression, + thisArg: Expression, + ): SyntheticReferenceExpression; createCommaListExpression(elements: readonly Expression[]): CommaListExpression; updateCommaListExpression(node: CommaListExpression, elements: readonly Expression[]): CommaListExpression; createBundle(sourceFiles: readonly SourceFile[]): Bundle; - /** @deprecated*/ createBundle(sourceFiles: readonly SourceFile[], prepends?: readonly (UnparsedSource | InputFiles)[]): Bundle; // eslint-disable-line @typescript-eslint/unified-signatures + /** @deprecated*/ createBundle( + sourceFiles: readonly SourceFile[], + prepends?: readonly (UnparsedSource | InputFiles)[], + ): Bundle; // eslint-disable-line @typescript-eslint/unified-signatures updateBundle(node: Bundle, sourceFiles: readonly SourceFile[]): Bundle; - /** @deprecated*/ updateBundle(node: Bundle, sourceFiles: readonly SourceFile[], prepends?: readonly (UnparsedSource | InputFiles)[]): Bundle; // eslint-disable-line @typescript-eslint/unified-signatures + /** @deprecated*/ updateBundle( + node: Bundle, + sourceFiles: readonly SourceFile[], + prepends?: readonly (UnparsedSource | InputFiles)[], + ): Bundle; // eslint-disable-line @typescript-eslint/unified-signatures // // Common operators // createComma(left: Expression, right: Expression): BinaryExpression; - createAssignment(left: ObjectLiteralExpression | ArrayLiteralExpression, right: Expression): DestructuringAssignment; + createAssignment( + left: ObjectLiteralExpression | ArrayLiteralExpression, + right: Expression, + ): DestructuringAssignment; createAssignment(left: Expression, right: Expression): AssignmentExpression; createLogicalOr(left: Expression, right: Expression): BinaryExpression; createLogicalAnd(left: Expression, right: Expression): BinaryExpression; @@ -8786,9 +10263,17 @@ export interface NodeFactory { // createImmediatelyInvokedFunctionExpression(statements: readonly Statement[]): CallExpression; - createImmediatelyInvokedFunctionExpression(statements: readonly Statement[], param: ParameterDeclaration, paramValue: Expression): CallExpression; + createImmediatelyInvokedFunctionExpression( + statements: readonly Statement[], + param: ParameterDeclaration, + paramValue: Expression, + ): CallExpression; createImmediatelyInvokedArrowFunction(statements: readonly Statement[]): ImmediatelyInvokedArrowFunction; - createImmediatelyInvokedArrowFunction(statements: readonly Statement[], param: ParameterDeclaration, paramValue: Expression): ImmediatelyInvokedArrowFunction; + createImmediatelyInvokedArrowFunction( + statements: readonly Statement[], + param: ParameterDeclaration, + paramValue: Expression, + ): ImmediatelyInvokedArrowFunction; createVoidZero(): VoidExpression; createExportDefault(expression: Expression): ExportAssignment; @@ -8796,19 +10281,63 @@ export interface NodeFactory { /** @internal */ createTypeCheck(value: Expression, tag: TypeOfTag): Expression; /** @internal */ createIsNotTypeCheck(value: Expression, tag: TypeOfTag): Expression; - /** @internal */ createMethodCall(object: Expression, methodName: string | Identifier, argumentsList: readonly Expression[]): CallExpression; - /** @internal */ createGlobalMethodCall(globalObjectName: string, globalMethodName: string, argumentsList: readonly Expression[]): CallExpression; - /** @internal */ createFunctionBindCall(target: Expression, thisArg: Expression, argumentsList: readonly Expression[]): CallExpression; - /** @internal */ createFunctionCallCall(target: Expression, thisArg: Expression, argumentsList: readonly Expression[]): CallExpression; - /** @internal */ createFunctionApplyCall(target: Expression, thisArg: Expression, argumentsExpression: Expression): CallExpression; - /** @internal */ createObjectDefinePropertyCall(target: Expression, propertyName: string | Expression, attributes: Expression): CallExpression; - /** @internal */ createObjectGetOwnPropertyDescriptorCall(target: Expression, propertyName: string | Expression): CallExpression; - /** @internal */ createReflectGetCall(target: Expression, propertyKey: Expression, receiver?: Expression): CallExpression; - /** @internal */ createReflectSetCall(target: Expression, propertyKey: Expression, value: Expression, receiver?: Expression): CallExpression; - /** @internal */ createPropertyDescriptor(attributes: PropertyDescriptorAttributes, singleLine?: boolean): ObjectLiteralExpression; + /** @internal */ createMethodCall( + object: Expression, + methodName: string | Identifier, + argumentsList: readonly Expression[], + ): CallExpression; + /** @internal */ createGlobalMethodCall( + globalObjectName: string, + globalMethodName: string, + argumentsList: readonly Expression[], + ): CallExpression; + /** @internal */ createFunctionBindCall( + target: Expression, + thisArg: Expression, + argumentsList: readonly Expression[], + ): CallExpression; + /** @internal */ createFunctionCallCall( + target: Expression, + thisArg: Expression, + argumentsList: readonly Expression[], + ): CallExpression; + /** @internal */ createFunctionApplyCall( + target: Expression, + thisArg: Expression, + argumentsExpression: Expression, + ): CallExpression; + /** @internal */ createObjectDefinePropertyCall( + target: Expression, + propertyName: string | Expression, + attributes: Expression, + ): CallExpression; + /** @internal */ createObjectGetOwnPropertyDescriptorCall( + target: Expression, + propertyName: string | Expression, + ): CallExpression; + /** @internal */ createReflectGetCall( + target: Expression, + propertyKey: Expression, + receiver?: Expression, + ): CallExpression; + /** @internal */ createReflectSetCall( + target: Expression, + propertyKey: Expression, + value: Expression, + receiver?: Expression, + ): CallExpression; + /** @internal */ createPropertyDescriptor( + attributes: PropertyDescriptorAttributes, + singleLine?: boolean, + ): ObjectLiteralExpression; /** @internal */ createArraySliceCall(array: Expression, start?: number | Expression): CallExpression; /** @internal */ createArrayConcatCall(array: Expression, values: readonly Expression[]): CallExpression; - /** @internal */ createCallBinding(expression: Expression, recordTempVariable: (temp: Identifier) => void, languageVersion?: ScriptTarget, cacheIdentifiers?: boolean): CallBinding; + /** @internal */ createCallBinding( + expression: Expression, + recordTempVariable: (temp: Identifier) => void, + languageVersion?: ScriptTarget, + cacheIdentifiers?: boolean, + ): CallBinding; /** * Wraps an expression that cannot be an assignment target in an expression that can be. * @@ -8855,7 +10384,12 @@ export interface NodeFactory { * * @internal */ - getLocalName(node: Declaration, allowComments?: boolean, allowSourceMaps?: boolean, ignoreAssignedName?: boolean): Identifier; + getLocalName( + node: Declaration, + allowComments?: boolean, + allowSourceMaps?: boolean, + ignoreAssignedName?: boolean, + ): Identifier; /** * Gets the export name of a declaration. This is primarily used for declarations that can be * referred to by name in the declaration's immediate scope (classes, enums, namespaces). An @@ -8889,7 +10423,12 @@ export interface NodeFactory { * * @internal */ - getNamespaceMemberName(ns: Identifier, name: Identifier, allowComments?: boolean, allowSourceMaps?: boolean): PropertyAccessExpression; + getNamespaceMemberName( + ns: Identifier, + name: Identifier, + allowComments?: boolean, + allowSourceMaps?: boolean, + ): PropertyAccessExpression; /** * Gets the exported name of a declaration for use in expressions. * @@ -8903,14 +10442,27 @@ export interface NodeFactory { * * @internal */ - getExternalModuleOrNamespaceExportName(ns: Identifier | undefined, node: Declaration, allowComments?: boolean, allowSourceMaps?: boolean): Identifier | PropertyAccessExpression; + getExternalModuleOrNamespaceExportName( + ns: Identifier | undefined, + node: Declaration, + allowComments?: boolean, + allowSourceMaps?: boolean, + ): Identifier | PropertyAccessExpression; // // Utilities // - restoreOuterExpressions(outerExpression: Expression | undefined, innerExpression: Expression, kinds?: OuterExpressionKinds): Expression; - /** @internal */ restoreEnclosingLabel(node: Statement, outermostLabeledStatement: LabeledStatement | undefined, afterRestoreLabelCallback?: (node: LabeledStatement) => void): Statement; + restoreOuterExpressions( + outerExpression: Expression | undefined, + innerExpression: Expression, + kinds?: OuterExpressionKinds, + ): Expression; + /** @internal */ restoreEnclosingLabel( + node: Statement, + outermostLabeledStatement: LabeledStatement | undefined, + afterRestoreLabelCallback?: (node: LabeledStatement) => void, + ): Statement; /** @internal */ createUseStrictPrologue(): PrologueDirective; /** * Copies any necessary standard and custom prologue-directives into target array. @@ -8921,7 +10473,12 @@ export interface NodeFactory { * * @internal */ - copyPrologue(source: readonly Statement[], target: Statement[], ensureUseStrict?: boolean, visitor?: (node: Node) => VisitResult): number; + copyPrologue( + source: readonly Statement[], + target: Statement[], + ensureUseStrict?: boolean, + visitor?: (node: Node) => VisitResult, + ): number; /** * Copies only the standard (string-expression) prologue-directives into the target statement-array. * @param source origin statements array @@ -8931,7 +10488,12 @@ export interface NodeFactory { * * @internal */ - copyStandardPrologue(source: readonly Statement[], target: Statement[], statementOffset: number | undefined, ensureUseStrict?: boolean): number; + copyStandardPrologue( + source: readonly Statement[], + target: Statement[], + statementOffset: number | undefined, + ensureUseStrict?: boolean, + ): number; /** * Copies only the custom prologue-directives into target statement-array. * @param source origin statements array @@ -8941,8 +10503,20 @@ export interface NodeFactory { * * @internal */ - copyCustomPrologue(source: readonly Statement[], target: Statement[], statementOffset: number, visitor?: (node: Node) => VisitResult, filter?: (node: Statement) => boolean): number; - /** @internal */ copyCustomPrologue(source: readonly Statement[], target: Statement[], statementOffset: number | undefined, visitor?: (node: Node) => VisitResult, filter?: (node: Statement) => boolean): number | undefined; + copyCustomPrologue( + source: readonly Statement[], + target: Statement[], + statementOffset: number, + visitor?: (node: Node) => VisitResult, + filter?: (node: Statement) => boolean, + ): number; + /** @internal */ copyCustomPrologue( + source: readonly Statement[], + target: Statement[], + statementOffset: number | undefined, + visitor?: (node: Node) => VisitResult, + filter?: (node: Statement) => boolean, + ): number | undefined; /** @internal */ ensureUseStrict(statements: NodeArray): NodeArray; /** @internal */ liftToBlock(nodes: readonly Node[]): Statement; /** @@ -8950,7 +10524,10 @@ export interface NodeFactory { * * @internal */ - mergeLexicalEnvironment(statements: NodeArray, declarations: readonly Statement[] | undefined): NodeArray; + mergeLexicalEnvironment( + statements: NodeArray, + declarations: readonly Statement[] | undefined, + ): NodeArray; /** * Appends generated lexical declarations to an array of statements. * @@ -8966,8 +10543,14 @@ export interface NodeFactory { * @internal */ cloneNode(node: T): T; - /** @internal */ updateModifiers(node: T, modifiers: readonly Modifier[] | ModifierFlags | undefined): T; - /** @internal */ updateModifierLike(node: T, modifierLike: readonly ModifierLike[] | undefined): T; + /** @internal */ updateModifiers( + node: T, + modifiers: readonly Modifier[] | ModifierFlags | undefined, + ): T; + /** @internal */ updateModifierLike( + node: T, + modifierLike: readonly ModifierLike[] | undefined, + ): T; } /** @internal */ @@ -9119,7 +10702,9 @@ export type Transformer = (node: T) => T; /** * A function that accepts and possibly transforms a node. */ -export type Visitor = (node: TIn) => VisitResult; +export type Visitor = ( + node: TIn, +) => VisitResult; /** * A function that walks a node using the given visitor, lifting node arrays into single nodes, @@ -9205,10 +10790,28 @@ export interface Printer { * Prints a bundle of source files as-is, without any emit transformations. */ printBundle(bundle: Bundle): string; - /** @internal */ writeNode(hint: EmitHint, node: Node, sourceFile: SourceFile | undefined, writer: EmitTextWriter): void; - /** @internal */ writeList(format: ListFormat, list: NodeArray | undefined, sourceFile: SourceFile | undefined, writer: EmitTextWriter): void; - /** @internal */ writeFile(sourceFile: SourceFile, writer: EmitTextWriter, sourceMapGenerator: SourceMapGenerator | undefined): void; - /** @internal */ writeBundle(bundle: Bundle, writer: EmitTextWriter, sourceMapGenerator: SourceMapGenerator | undefined): void; + /** @internal */ writeNode( + hint: EmitHint, + node: Node, + sourceFile: SourceFile | undefined, + writer: EmitTextWriter, + ): void; + /** @internal */ writeList( + format: ListFormat, + list: NodeArray | undefined, + sourceFile: SourceFile | undefined, + writer: EmitTextWriter, + ): void; + /** @internal */ writeFile( + sourceFile: SourceFile, + writer: EmitTextWriter, + sourceMapGenerator: SourceMapGenerator | undefined, + ): void; + /** @internal */ writeBundle( + bundle: Bundle, + writer: EmitTextWriter, + sourceMapGenerator: SourceMapGenerator | undefined, + ): void; /** @deprecated @internal */ bundleFileInfo?: BundleFileInfo; } @@ -9253,7 +10856,12 @@ export interface BundleFileHasNoDefaultLib extends BundleFileSectionBase { /** @deprecated @internal */ export interface BundleFileReference extends BundleFileSectionBase { - kind: BundleFileSectionKind.Reference | BundleFileSectionKind.Type | BundleFileSectionKind.Lib | BundleFileSectionKind.TypeResolutionModeImport | BundleFileSectionKind.TypeResolutionModeRequire; + kind: + | BundleFileSectionKind.Reference + | BundleFileSectionKind.Type + | BundleFileSectionKind.Lib + | BundleFileSectionKind.TypeResolutionModeImport + | BundleFileSectionKind.TypeResolutionModeRequire; data: string; } @@ -9377,8 +10985,18 @@ export interface PrintHandlers { * ``` */ substituteNode?(hint: EmitHint, node: Node): Node; - /** @internal */ onEmitSourceMapOfNode?: (hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void) => void; - /** @internal */ onEmitSourceMapOfToken?: (node: Node | undefined, token: SyntaxKind, writer: (s: string) => void, pos: number, emitCallback: (token: SyntaxKind, writer: (s: string) => void, pos: number) => number) => number; + /** @internal */ onEmitSourceMapOfNode?: ( + hint: EmitHint, + node: Node, + emitCallback: (hint: EmitHint, node: Node) => void, + ) => void; + /** @internal */ onEmitSourceMapOfToken?: ( + node: Node | undefined, + token: SyntaxKind, + writer: (s: string) => void, + pos: number, + emitCallback: (token: SyntaxKind, writer: (s: string) => void, pos: number) => number, + ) => number; /** @internal */ onEmitSourceMapOfPosition?: (pos: number) => void; /** @internal */ onSetSourceFile?: (node: SourceFile) => void; /** @internal */ onBeforeEmitNode?: (node: Node | undefined) => void; @@ -9447,11 +11065,25 @@ export interface SourceMapGenerator { /** * Adds a mapping with source information. */ - addMapping(generatedLine: number, generatedCharacter: number, sourceIndex: number, sourceLine: number, sourceCharacter: number, nameIndex?: number): void; + addMapping( + generatedLine: number, + generatedCharacter: number, + sourceIndex: number, + sourceLine: number, + sourceCharacter: number, + nameIndex?: number, + ): void; /** * Appends a source map. */ - appendSourceMap(generatedLine: number, generatedCharacter: number, sourceMap: RawSourceMap, sourceMapPath: string, start?: LineAndCharacter, end?: LineAndCharacter): void; + appendSourceMap( + generatedLine: number, + generatedCharacter: number, + sourceMap: RawSourceMap, + sourceMapPath: string, + start?: LineAndCharacter, + end?: LineAndCharacter, + ): void; /** * Gets the source map as a `RawSourceMap` object. */ @@ -9554,10 +11186,34 @@ export interface ModuleSpecifierOptions { /** @internal */ export interface ModuleSpecifierCache { - get(fromFileName: Path, toFileName: Path, preferences: UserPreferences, options: ModuleSpecifierOptions): Readonly | undefined; - set(fromFileName: Path, toFileName: Path, preferences: UserPreferences, options: ModuleSpecifierOptions, modulePaths: readonly ModulePath[], moduleSpecifiers: readonly string[]): void; - setBlockedByPackageJsonDependencies(fromFileName: Path, toFileName: Path, preferences: UserPreferences, options: ModuleSpecifierOptions, isBlockedByPackageJsonDependencies: boolean): void; - setModulePaths(fromFileName: Path, toFileName: Path, preferences: UserPreferences, options: ModuleSpecifierOptions, modulePaths: readonly ModulePath[]): void; + get( + fromFileName: Path, + toFileName: Path, + preferences: UserPreferences, + options: ModuleSpecifierOptions, + ): Readonly | undefined; + set( + fromFileName: Path, + toFileName: Path, + preferences: UserPreferences, + options: ModuleSpecifierOptions, + modulePaths: readonly ModulePath[], + moduleSpecifiers: readonly string[], + ): void; + setBlockedByPackageJsonDependencies( + fromFileName: Path, + toFileName: Path, + preferences: UserPreferences, + options: ModuleSpecifierOptions, + isBlockedByPackageJsonDependencies: boolean, + ): void; + setModulePaths( + fromFileName: Path, + toFileName: Path, + preferences: UserPreferences, + options: ModuleSpecifierOptions, + modulePaths: readonly ModulePath[], + ): void; clear(): void; count(): number; } @@ -9669,11 +11325,16 @@ export const enum ListFormat { MultiLineTupleTypeElements = CommaDelimited | Indented | SpaceBetweenSiblings | MultiLine, UnionTypeConstituents = BarDelimited | SpaceBetweenSiblings | SingleLine, IntersectionTypeConstituents = AmpersandDelimited | SpaceBetweenSiblings | SingleLine, - ObjectBindingPatternElements = SingleLine | AllowTrailingComma | SpaceBetweenBraces | CommaDelimited | SpaceBetweenSiblings | NoSpaceIfEmpty, - ArrayBindingPatternElements = SingleLine | AllowTrailingComma | CommaDelimited | SpaceBetweenSiblings | NoSpaceIfEmpty, - ObjectLiteralExpressionProperties = PreserveLines | CommaDelimited | SpaceBetweenSiblings | SpaceBetweenBraces | Indented | Braces | NoSpaceIfEmpty, - ImportClauseEntries = PreserveLines | CommaDelimited | SpaceBetweenSiblings | SpaceBetweenBraces | Indented | Braces | NoSpaceIfEmpty, - ArrayLiteralExpressionElements = PreserveLines | CommaDelimited | SpaceBetweenSiblings | AllowTrailingComma | Indented | SquareBrackets, + ObjectBindingPatternElements = SingleLine | AllowTrailingComma | SpaceBetweenBraces | CommaDelimited + | SpaceBetweenSiblings | NoSpaceIfEmpty, + ArrayBindingPatternElements = SingleLine | AllowTrailingComma | CommaDelimited | SpaceBetweenSiblings + | NoSpaceIfEmpty, + ObjectLiteralExpressionProperties = PreserveLines | CommaDelimited | SpaceBetweenSiblings | SpaceBetweenBraces + | Indented | Braces | NoSpaceIfEmpty, + ImportClauseEntries = PreserveLines | CommaDelimited | SpaceBetweenSiblings | SpaceBetweenBraces | Indented | Braces + | NoSpaceIfEmpty, + ArrayLiteralExpressionElements = PreserveLines | CommaDelimited | SpaceBetweenSiblings | AllowTrailingComma + | Indented | SquareBrackets, CommaListElements = CommaDelimited | SpaceBetweenSiblings | SingleLine, CallExpressionArguments = CommaDelimited | SpaceBetweenSiblings | SingleLine | Parenthesis, NewExpressionArguments = CommaDelimited | SpaceBetweenSiblings | SingleLine | Parenthesis | OptionalIfUndefined, @@ -9688,7 +11349,8 @@ export const enum ListFormat { InterfaceMembers = Indented | MultiLine, EnumMembers = CommaDelimited | Indented | MultiLine, CaseBlockClauses = Indented | MultiLine, - NamedImportsOrExportsElements = CommaDelimited | SpaceBetweenSiblings | AllowTrailingComma | SingleLine | SpaceBetweenBraces | NoSpaceIfEmpty, + NamedImportsOrExportsElements = CommaDelimited | SpaceBetweenSiblings | AllowTrailingComma | SingleLine + | SpaceBetweenBraces | NoSpaceIfEmpty, JsxElementOrFragmentChildren = SingleLine | NoInterveningComments, JsxElementAttributes = SingleLine | SpaceBetweenSiblings | NoInterveningComments, CaseOrDefaultClauseStatements = Indented | MultiLine | NoTrailingNewLine | OptionalIfEmpty, @@ -9734,12 +11396,22 @@ export interface PragmaArgumentSpecification { } /** @internal */ -export interface PragmaDefinition { +export interface PragmaDefinition< + T1 extends string = string, + T2 extends string = string, + T3 extends string = string, + T4 extends string = string, +> { args?: | readonly [PragmaArgumentSpecification] | readonly [PragmaArgumentSpecification, PragmaArgumentSpecification] | readonly [PragmaArgumentSpecification, PragmaArgumentSpecification, PragmaArgumentSpecification] - | readonly [PragmaArgumentSpecification, PragmaArgumentSpecification, PragmaArgumentSpecification, PragmaArgumentSpecification]; + | readonly [ + PragmaArgumentSpecification, + PragmaArgumentSpecification, + PragmaArgumentSpecification, + PragmaArgumentSpecification, + ]; // If not present, defaults to PragmaKindFlags.Default kind?: PragmaKindFlags; } @@ -9791,18 +11463,25 @@ export const commentPragmas = { } as const; /** @internal */ -export type PragmaArgTypeMaybeCapture = TDesc extends { captureSpan: true; } ? { value: string; pos: number; end: number; } : string; +export type PragmaArgTypeMaybeCapture = TDesc extends { captureSpan: true; } + ? { value: string; pos: number; end: number; } + : string; /** @internal */ -export type PragmaArgTypeOptional = TDesc extends { optional: true; } ? { [K in TName]?: PragmaArgTypeMaybeCapture; } +export type PragmaArgTypeOptional = TDesc extends { optional: true; } + ? { [K in TName]?: PragmaArgTypeMaybeCapture; } : { [K in TName]: PragmaArgTypeMaybeCapture; }; /** @internal */ -export type UnionToIntersection = (U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never; +export type UnionToIntersection = (U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I + : never; /** @internal */ export type ArgumentDefinitionToFieldUnion[]> = { - [K in keyof T]: PragmaArgTypeOptional; + [K in keyof T]: PragmaArgTypeOptional< + T[K], + T[K] extends { name: infer TName; } ? TName extends string ? TName : never : never + >; }[Extract]; // The mapped type maps over only the tuple members, but this reindex gets _all_ members - by extracting only `number` keys, we get only the tuple members /** @@ -9810,22 +11489,36 @@ export type ArgumentDefinitionToFieldUnion = ConcretePragmaSpecs[KPrag] extends { args: readonly PragmaArgumentSpecification[]; } ? UnionToIntersection> +export type PragmaArgumentType = ConcretePragmaSpecs[KPrag] extends + { args: readonly PragmaArgumentSpecification[]; } + ? UnionToIntersection> : never; /** @internal */ export type ConcretePragmaSpecs = typeof commentPragmas; /** @internal */ -export type PragmaPseudoMap = { [K in keyof ConcretePragmaSpecs]: { arguments: PragmaArgumentType; range: CommentRange; }; }; +export type PragmaPseudoMap = { + [K in keyof ConcretePragmaSpecs]: { arguments: PragmaArgumentType; range: CommentRange; }; +}; /** @internal */ -export type PragmaPseudoMapEntry = { [K in keyof PragmaPseudoMap]: { name: K; args: PragmaPseudoMap[K]; }; }[keyof PragmaPseudoMap]; +export type PragmaPseudoMapEntry = { + [K in keyof PragmaPseudoMap]: { name: K; args: PragmaPseudoMap[K]; }; +}[keyof PragmaPseudoMap]; /** @internal */ -export interface ReadonlyPragmaMap extends ReadonlyMap { +export interface ReadonlyPragmaMap + extends ReadonlyMap +{ get(key: TKey): PragmaPseudoMap[TKey] | PragmaPseudoMap[TKey][]; - forEach(action: (value: PragmaPseudoMap[TKey] | PragmaPseudoMap[TKey][], key: TKey, map: ReadonlyPragmaMap) => void): void; + forEach( + action: ( + value: PragmaPseudoMap[TKey] | PragmaPseudoMap[TKey][], + key: TKey, + map: ReadonlyPragmaMap, + ) => void, + ): void; } /** @@ -9835,10 +11528,20 @@ export interface ReadonlyPragmaMap extends ReadonlyMap, ReadonlyPragmaMap { +export interface PragmaMap + extends + Map, + ReadonlyPragmaMap +{ set(key: TKey, value: PragmaPseudoMap[TKey] | PragmaPseudoMap[TKey][]): this; get(key: TKey): PragmaPseudoMap[TKey] | PragmaPseudoMap[TKey][]; - forEach(action: (value: PragmaPseudoMap[TKey] | PragmaPseudoMap[TKey][], key: TKey, map: PragmaMap) => void): void; + forEach( + action: ( + value: PragmaPseudoMap[TKey] | PragmaPseudoMap[TKey][], + key: TKey, + map: PragmaMap, + ) => void, + ): void; } /** @internal */ diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 06812b8fe0b6e..a7aef13658f57 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -652,8 +652,8 @@ function createSingleLineStringWriter(): EmitTextWriter { /** @internal */ export function changesAffectModuleResolution(oldOptions: CompilerOptions, newOptions: CompilerOptions): boolean { - return oldOptions.configFilePath !== newOptions.configFilePath || - optionsHaveModuleResolutionChanges(oldOptions, newOptions); + return oldOptions.configFilePath !== newOptions.configFilePath + || optionsHaveModuleResolutionChanges(oldOptions, newOptions); } /** @internal */ @@ -667,8 +667,15 @@ export function changesAffectingProgramStructure(oldOptions: CompilerOptions, ne } /** @internal */ -export function optionsHaveChanges(oldOptions: CompilerOptions, newOptions: CompilerOptions, optionDeclarations: readonly CommandLineOption[]) { - return oldOptions !== newOptions && optionDeclarations.some(o => !isJsonEqual(getCompilerOptionValue(oldOptions, o), getCompilerOptionValue(newOptions, o))); +export function optionsHaveChanges( + oldOptions: CompilerOptions, + newOptions: CompilerOptions, + optionDeclarations: readonly CommandLineOption[], +) { + return oldOptions !== newOptions + && optionDeclarations.some(o => + !isJsonEqual(getCompilerOptionValue(oldOptions, o), getCompilerOptionValue(newOptions, o)) + ); } /** @internal */ @@ -688,7 +695,10 @@ export function forEachAncestor(node: Node, callback: (n: Node) => T | undefi * * @internal */ -export function forEachEntry(map: ReadonlyMap, callback: (value: V, key: K) => U | undefined): U | undefined { +export function forEachEntry( + map: ReadonlyMap, + callback: (value: V, key: K) => U | undefined, +): U | undefined { const iterator = map.entries(); for (const [key, value] of iterator) { const result = callback(value, key); @@ -745,12 +755,21 @@ export function getFullWidth(node: Node) { } /** @internal */ -export function getResolvedModule(sourceFile: SourceFile | undefined, moduleNameText: string, mode: ResolutionMode): ResolvedModuleFull | undefined { +export function getResolvedModule( + sourceFile: SourceFile | undefined, + moduleNameText: string, + mode: ResolutionMode, +): ResolvedModuleFull | undefined { return sourceFile?.resolvedModules?.get(moduleNameText, mode)?.resolvedModule; } /** @internal */ -export function setResolvedModule(sourceFile: SourceFile, moduleNameText: string, resolvedModule: ResolvedModuleWithFailedLookupLocations, mode: ResolutionMode): void { +export function setResolvedModule( + sourceFile: SourceFile, + moduleNameText: string, + resolvedModule: ResolvedModuleWithFailedLookupLocations, + mode: ResolutionMode, +): void { if (!sourceFile.resolvedModules) { sourceFile.resolvedModules = createModeAwareCache(); } @@ -759,71 +778,106 @@ export function setResolvedModule(sourceFile: SourceFile, moduleNameText: string } /** @internal */ -export function setResolvedTypeReferenceDirective(sourceFile: SourceFile, typeReferenceDirectiveName: string, resolvedTypeReferenceDirective: ResolvedTypeReferenceDirectiveWithFailedLookupLocations, mode: ResolutionMode): void { +export function setResolvedTypeReferenceDirective( + sourceFile: SourceFile, + typeReferenceDirectiveName: string, + resolvedTypeReferenceDirective: ResolvedTypeReferenceDirectiveWithFailedLookupLocations, + mode: ResolutionMode, +): void { if (!sourceFile.resolvedTypeReferenceDirectiveNames) { sourceFile.resolvedTypeReferenceDirectiveNames = createModeAwareCache(); } - sourceFile.resolvedTypeReferenceDirectiveNames.set(typeReferenceDirectiveName, mode, resolvedTypeReferenceDirective); + sourceFile.resolvedTypeReferenceDirectiveNames.set( + typeReferenceDirectiveName, + mode, + resolvedTypeReferenceDirective, + ); } /** @internal */ -export function getResolvedTypeReferenceDirective(sourceFile: SourceFile | undefined, typeReferenceDirectiveName: string, mode: ResolutionMode): ResolvedTypeReferenceDirective | undefined { - return sourceFile?.resolvedTypeReferenceDirectiveNames?.get(typeReferenceDirectiveName, mode)?.resolvedTypeReferenceDirective; +export function getResolvedTypeReferenceDirective( + sourceFile: SourceFile | undefined, + typeReferenceDirectiveName: string, + mode: ResolutionMode, +): ResolvedTypeReferenceDirective | undefined { + return sourceFile?.resolvedTypeReferenceDirectiveNames?.get(typeReferenceDirectiveName, mode) + ?.resolvedTypeReferenceDirective; } /** @internal */ export function projectReferenceIsEqualTo(oldRef: ProjectReference, newRef: ProjectReference) { - return oldRef.path === newRef.path && - !oldRef.prepend === !newRef.prepend && - !oldRef.circular === !newRef.circular; + return oldRef.path === newRef.path + && !oldRef.prepend === !newRef.prepend + && !oldRef.circular === !newRef.circular; } /** @internal */ -export function moduleResolutionIsEqualTo(oldResolution: ResolvedModuleWithFailedLookupLocations, newResolution: ResolvedModuleWithFailedLookupLocations): boolean { - return oldResolution === newResolution || - oldResolution.resolvedModule === newResolution.resolvedModule || - !!oldResolution.resolvedModule && - !!newResolution.resolvedModule && - oldResolution.resolvedModule.isExternalLibraryImport === newResolution.resolvedModule.isExternalLibraryImport && - oldResolution.resolvedModule.extension === newResolution.resolvedModule.extension && - oldResolution.resolvedModule.resolvedFileName === newResolution.resolvedModule.resolvedFileName && - oldResolution.resolvedModule.originalPath === newResolution.resolvedModule.originalPath && - packageIdIsEqual(oldResolution.resolvedModule.packageId, newResolution.resolvedModule.packageId) && - oldResolution.node10Result === newResolution.node10Result; -} - -/** @internal */ -export function createModuleNotFoundChain(sourceFile: SourceFile, host: TypeCheckerHost, moduleReference: string, mode: ResolutionMode, packageName: string) { +export function moduleResolutionIsEqualTo( + oldResolution: ResolvedModuleWithFailedLookupLocations, + newResolution: ResolvedModuleWithFailedLookupLocations, +): boolean { + return oldResolution === newResolution + || oldResolution.resolvedModule === newResolution.resolvedModule + || !!oldResolution.resolvedModule + && !!newResolution.resolvedModule + && oldResolution.resolvedModule.isExternalLibraryImport + === newResolution.resolvedModule.isExternalLibraryImport + && oldResolution.resolvedModule.extension === newResolution.resolvedModule.extension + && oldResolution.resolvedModule.resolvedFileName === newResolution.resolvedModule.resolvedFileName + && oldResolution.resolvedModule.originalPath === newResolution.resolvedModule.originalPath + && packageIdIsEqual(oldResolution.resolvedModule.packageId, newResolution.resolvedModule.packageId) + && oldResolution.node10Result === newResolution.node10Result; +} + +/** @internal */ +export function createModuleNotFoundChain( + sourceFile: SourceFile, + host: TypeCheckerHost, + moduleReference: string, + mode: ResolutionMode, + packageName: string, +) { const node10Result = sourceFile.resolvedModules?.get(moduleReference, mode)?.node10Result; const result = node10Result ? chainDiagnosticMessages( /*details*/ undefined, - Diagnostics.There_are_types_at_0_but_this_result_could_not_be_resolved_when_respecting_package_json_exports_The_1_library_may_need_to_update_its_package_json_or_typings, + Diagnostics + .There_are_types_at_0_but_this_result_could_not_be_resolved_when_respecting_package_json_exports_The_1_library_may_need_to_update_its_package_json_or_typings, node10Result, - node10Result.indexOf(nodeModulesPathPart + "@types/") > -1 ? `@types/${mangleScopedPackageName(packageName)}` : packageName, + node10Result.indexOf(nodeModulesPathPart + "@types/") > -1 + ? `@types/${mangleScopedPackageName(packageName)}` : packageName, ) : host.typesPackageExists(packageName) ? chainDiagnosticMessages( /*details*/ undefined, - Diagnostics.If_the_0_package_actually_exposes_this_module_consider_sending_a_pull_request_to_amend_https_Colon_Slash_Slashgithub_com_SlashDefinitelyTyped_SlashDefinitelyTyped_Slashtree_Slashmaster_Slashtypes_Slash_1, + Diagnostics + .If_the_0_package_actually_exposes_this_module_consider_sending_a_pull_request_to_amend_https_Colon_Slash_Slashgithub_com_SlashDefinitelyTyped_SlashDefinitelyTyped_Slashtree_Slashmaster_Slashtypes_Slash_1, packageName, mangleScopedPackageName(packageName), ) : host.packageBundlesTypes(packageName) ? chainDiagnosticMessages( /*details*/ undefined, - Diagnostics.If_the_0_package_actually_exposes_this_module_try_adding_a_new_declaration_d_ts_file_containing_declare_module_1, + Diagnostics + .If_the_0_package_actually_exposes_this_module_try_adding_a_new_declaration_d_ts_file_containing_declare_module_1, packageName, moduleReference, ) : chainDiagnosticMessages( /*details*/ undefined, - Diagnostics.Try_npm_i_save_dev_types_Slash_1_if_it_exists_or_add_a_new_declaration_d_ts_file_containing_declare_module_0, + Diagnostics + .Try_npm_i_save_dev_types_Slash_1_if_it_exists_or_add_a_new_declaration_d_ts_file_containing_declare_module_0, moduleReference, mangleScopedPackageName(packageName), ); - if (result) result.repopulateInfo = () => ({ moduleReference, mode, packageName: packageName === moduleReference ? undefined : packageName }); + if (result) { + result.repopulateInfo = () => ({ + moduleReference, + mode, + packageName: packageName === moduleReference ? undefined : packageName, + }); + } return result; } @@ -842,14 +896,20 @@ export function packageIdToString(packageId: PackageId): string { } /** @internal */ -export function typeDirectiveIsEqualTo(oldResolution: ResolvedTypeReferenceDirectiveWithFailedLookupLocations, newResolution: ResolvedTypeReferenceDirectiveWithFailedLookupLocations): boolean { - return oldResolution === newResolution || - oldResolution.resolvedTypeReferenceDirective === newResolution.resolvedTypeReferenceDirective || - !!oldResolution.resolvedTypeReferenceDirective && - !!newResolution.resolvedTypeReferenceDirective && - oldResolution.resolvedTypeReferenceDirective.resolvedFileName === newResolution.resolvedTypeReferenceDirective.resolvedFileName && - !!oldResolution.resolvedTypeReferenceDirective.primary === !!newResolution.resolvedTypeReferenceDirective.primary && - oldResolution.resolvedTypeReferenceDirective.originalPath === newResolution.resolvedTypeReferenceDirective.originalPath; +export function typeDirectiveIsEqualTo( + oldResolution: ResolvedTypeReferenceDirectiveWithFailedLookupLocations, + newResolution: ResolvedTypeReferenceDirectiveWithFailedLookupLocations, +): boolean { + return oldResolution === newResolution + || oldResolution.resolvedTypeReferenceDirective === newResolution.resolvedTypeReferenceDirective + || !!oldResolution.resolvedTypeReferenceDirective + && !!newResolution.resolvedTypeReferenceDirective + && oldResolution.resolvedTypeReferenceDirective.resolvedFileName + === newResolution.resolvedTypeReferenceDirective.resolvedFileName + && !!oldResolution.resolvedTypeReferenceDirective.primary + === !!newResolution.resolvedTypeReferenceDirective.primary + && oldResolution.resolvedTypeReferenceDirective.originalPath + === newResolution.resolvedTypeReferenceDirective.originalPath; } /** @internal */ @@ -891,8 +951,8 @@ function aggregateChildData(node: Node): void { // A node is considered to contain a parse error if: // a) the parser explicitly marked that it had an error // b) any of it's children reported that it had an error. - const thisNodeOrAnySubNodesHasError = ((node.flags & NodeFlags.ThisNodeHasError) !== 0) || - forEachChild(node, containsParseError); + const thisNodeOrAnySubNodesHasError = ((node.flags & NodeFlags.ThisNodeHasError) !== 0) + || forEachChild(node, containsParseError); // If so, mark ourselves accordingly. if (thisNodeOrAnySubNodesHasError) { @@ -925,7 +985,8 @@ export function getSourceFileOfModule(module: Symbol) { /** @internal */ export function isPlainJsFile(file: SourceFile | undefined, checkJs: boolean | undefined): boolean { - return !!file && (file.scriptKind === ScriptKind.JS || file.scriptKind === ScriptKind.JSX) && !file.checkJsDirective && checkJs === undefined; + return !!file && (file.scriptKind === ScriptKind.JS || file.scriptKind === ScriptKind.JSX) && !file.checkJsDirective + && checkJs === undefined; } /** @internal */ @@ -989,7 +1050,11 @@ export function getEndLinePosition(line: number, sourceFile: SourceFileLike): nu * * @internal */ -export function isFileLevelUniqueName(sourceFile: SourceFile, name: string, hasGlobalName?: PrintHandlers["hasGlobalName"]): boolean { +export function isFileLevelUniqueName( + sourceFile: SourceFile, + name: string, + hasGlobalName?: PrintHandlers["hasGlobalName"], +): boolean { return !(hasGlobalName && hasGlobalName(name)) && !sourceFile.identifiers.has(name); } @@ -1027,23 +1092,50 @@ export function isGrammarError(parent: Node, child: Node | NodeArray) { if (isTypeParameterDeclaration(parent)) return child === parent.expression; if (isClassStaticBlockDeclaration(parent)) return child === parent.modifiers; if (isPropertySignature(parent)) return child === parent.initializer; - if (isPropertyDeclaration(parent)) return child === parent.questionToken && isAutoAccessorPropertyDeclaration(parent); - if (isPropertyAssignment(parent)) return child === parent.modifiers || child === parent.questionToken || child === parent.exclamationToken || isGrammarErrorElement(parent.modifiers, child, isModifierLike); - if (isShorthandPropertyAssignment(parent)) return child === parent.equalsToken || child === parent.modifiers || child === parent.questionToken || child === parent.exclamationToken || isGrammarErrorElement(parent.modifiers, child, isModifierLike); + if (isPropertyDeclaration(parent)) { + return child === parent.questionToken && isAutoAccessorPropertyDeclaration(parent); + } + if (isPropertyAssignment(parent)) { + return child === parent.modifiers || child === parent.questionToken || child === parent.exclamationToken + || isGrammarErrorElement(parent.modifiers, child, isModifierLike); + } + if (isShorthandPropertyAssignment(parent)) { + return child === parent.equalsToken || child === parent.modifiers || child === parent.questionToken + || child === parent.exclamationToken || isGrammarErrorElement(parent.modifiers, child, isModifierLike); + } if (isMethodDeclaration(parent)) return child === parent.exclamationToken; - if (isConstructorDeclaration(parent)) return child === parent.typeParameters || child === parent.type || isGrammarErrorElement(parent.typeParameters, child, isTypeParameterDeclaration); - if (isGetAccessorDeclaration(parent)) return child === parent.typeParameters || isGrammarErrorElement(parent.typeParameters, child, isTypeParameterDeclaration); - if (isSetAccessorDeclaration(parent)) return child === parent.typeParameters || child === parent.type || isGrammarErrorElement(parent.typeParameters, child, isTypeParameterDeclaration); - if (isNamespaceExportDeclaration(parent)) return child === parent.modifiers || isGrammarErrorElement(parent.modifiers, child, isModifierLike); + if (isConstructorDeclaration(parent)) { + return child === parent.typeParameters || child === parent.type + || isGrammarErrorElement(parent.typeParameters, child, isTypeParameterDeclaration); + } + if (isGetAccessorDeclaration(parent)) { + return child === parent.typeParameters + || isGrammarErrorElement(parent.typeParameters, child, isTypeParameterDeclaration); + } + if (isSetAccessorDeclaration(parent)) { + return child === parent.typeParameters || child === parent.type + || isGrammarErrorElement(parent.typeParameters, child, isTypeParameterDeclaration); + } + if (isNamespaceExportDeclaration(parent)) { + return child === parent.modifiers || isGrammarErrorElement(parent.modifiers, child, isModifierLike); + } return false; } -function isGrammarErrorElement(nodeArray: NodeArray | undefined, child: Node | NodeArray, isElement: (node: Node) => node is T) { +function isGrammarErrorElement( + nodeArray: NodeArray | undefined, + child: Node | NodeArray, + isElement: (node: Node) => node is T, +) { if (!nodeArray || isArray(child) || !isElement(child)) return false; return contains(nodeArray, child); } -function insertStatementsAfterPrologue(to: T[], from: readonly T[] | undefined, isPrologueDirective: (node: Node) => boolean): T[] { +function insertStatementsAfterPrologue( + to: T[], + from: readonly T[] | undefined, + isPrologueDirective: (node: Node) => boolean, +): T[] { if (from === undefined || from.length === 0) return to; let statementIndex = 0; // skip all prologue directives to insert at the correct position @@ -1056,7 +1148,11 @@ function insertStatementsAfterPrologue(to: T[], from: reado return to; } -function insertStatementAfterPrologue(to: T[], statement: T | undefined, isPrologueDirective: (node: Node) => boolean): T[] { +function insertStatementAfterPrologue( + to: T[], + statement: T | undefined, + isPrologueDirective: (node: Node) => boolean, +): T[] { if (statement === undefined) return to; let statementIndex = 0; // skip all prologue directives to insert at the correct position @@ -1078,7 +1174,10 @@ function isAnyPrologueDirective(node: Node) { * * @internal */ -export function insertStatementsAfterStandardPrologue(to: T[], from: readonly T[] | undefined): T[] { +export function insertStatementsAfterStandardPrologue( + to: T[], + from: readonly T[] | undefined, +): T[] { return insertStatementsAfterPrologue(to, from, isPrologueDirective); } @@ -1112,30 +1211,33 @@ export function isRecognizedTripleSlashComment(text: string, commentPos: number, // Verify this is /// comment, but do the regexp match only when we first can find /// in the comment text // so that we don't end up computing comment string and doing match for all // comments if ( - text.charCodeAt(commentPos + 1) === CharacterCodes.slash && - commentPos + 2 < commentEnd && - text.charCodeAt(commentPos + 2) === CharacterCodes.slash + text.charCodeAt(commentPos + 1) === CharacterCodes.slash + && commentPos + 2 < commentEnd + && text.charCodeAt(commentPos + 2) === CharacterCodes.slash ) { const textSubStr = text.substring(commentPos, commentEnd); - return fullTripleSlashReferencePathRegEx.test(textSubStr) || - fullTripleSlashAMDReferencePathRegEx.test(textSubStr) || - fullTripleSlashAMDModuleRegEx.test(textSubStr) || - fullTripleSlashReferenceTypeReferenceDirectiveRegEx.test(textSubStr) || - fullTripleSlashLibReferenceRegEx.test(textSubStr) || - defaultLibReferenceRegEx.test(textSubStr) ? - true : false; + return fullTripleSlashReferencePathRegEx.test(textSubStr) + || fullTripleSlashAMDReferencePathRegEx.test(textSubStr) + || fullTripleSlashAMDModuleRegEx.test(textSubStr) + || fullTripleSlashReferenceTypeReferenceDirectiveRegEx.test(textSubStr) + || fullTripleSlashLibReferenceRegEx.test(textSubStr) + || defaultLibReferenceRegEx.test(textSubStr) + ? true : false; } return false; } /** @internal */ export function isPinnedComment(text: string, start: number) { - return text.charCodeAt(start + 1) === CharacterCodes.asterisk && - text.charCodeAt(start + 2) === CharacterCodes.exclamation; + return text.charCodeAt(start + 1) === CharacterCodes.asterisk + && text.charCodeAt(start + 2) === CharacterCodes.exclamation; } /** @internal */ -export function createCommentDirectivesMap(sourceFile: SourceFile, commentDirectives: CommentDirective[]): CommentDirectivesMap { +export function createCommentDirectivesMap( + sourceFile: SourceFile, + commentDirectives: CommentDirective[], +): CommentDirectivesMap { const directivesByLine = new Map( commentDirectives.map(commentDirective => [ `${getLineAndCharacterOfPosition(sourceFile, commentDirective.range.end).line}`, @@ -1173,7 +1275,12 @@ export function getTokenPosOfNode(node: Node, sourceFile?: SourceFileLike, inclu if (isJSDocNode(node) || node.kind === SyntaxKind.JsxText) { // JsxText cannot actually contain comments, even though the scanner will think it sees comments - return skipTrivia((sourceFile || getSourceFileOfNode(node)).text, node.pos, /*stopAfterLineBreak*/ false, /*stopAtComments*/ true); + return skipTrivia( + (sourceFile || getSourceFileOfNode(node)).text, + node.pos, + /*stopAfterLineBreak*/ false, + /*stopAtComments*/ true, + ); } if (includeJsDoc && hasJSDocNodes(node)) { @@ -1199,7 +1306,8 @@ export function getTokenPosOfNode(node: Node, sourceFile?: SourceFileLike, inclu /** @internal */ export function getNonDecoratorTokenPosOfNode(node: Node, sourceFile?: SourceFileLike): number { - const lastDecorator = !nodeIsMissing(node) && canHaveModifiers(node) ? findLast(node.modifiers, isDecorator) : undefined; + const lastDecorator = !nodeIsMissing(node) && canHaveModifiers(node) ? findLast(node.modifiers, isDecorator) + : undefined; if (!lastDecorator) { return getTokenPosOfNode(node, sourceFile); } @@ -1218,7 +1326,8 @@ function isJSDocTypeExpressionOrChild(node: Node): boolean { /** @internal */ export function isExportNamespaceAsDefaultDeclaration(node: Node): boolean { - return !!(isExportDeclaration(node) && node.exportClause && isNamespaceExport(node.exportClause) && node.exportClause.name.escapedText === "default"); + return !!(isExportDeclaration(node) && node.exportClause && isNamespaceExport(node.exportClause) + && node.exportClause.name.escapedText === "default"); } /** @internal */ @@ -1699,9 +1808,10 @@ export function getLiteralText(node: LiteralLikeNode, sourceFile: SourceFile | u // or a (possibly escaped) quoted form of the original text if it's string-like. switch (node.kind) { case SyntaxKind.StringLiteral: { - const escapeText = flags & GetLiteralTextFlags.JsxAttributeEscape ? escapeJsxAttributeString : - flags & GetLiteralTextFlags.NeverAsciiEscape || (getEmitFlags(node) & EmitFlags.NoAsciiEscaping) ? escapeString : - escapeNonAsciiString; + const escapeText = flags & GetLiteralTextFlags.JsxAttributeEscape ? escapeJsxAttributeString + : flags & GetLiteralTextFlags.NeverAsciiEscape || (getEmitFlags(node) & EmitFlags.NoAsciiEscaping) + ? escapeString + : escapeNonAsciiString; if ((node as StringLiteral).singleQuote) { return "'" + escapeText(node.text, CharacterCodes.singleQuote) + "'"; } @@ -1715,10 +1825,13 @@ export function getLiteralText(node: LiteralLikeNode, sourceFile: SourceFile | u case SyntaxKind.TemplateTail: { // If a NoSubstitutionTemplateLiteral appears to have a substitution in it, the original text // had to include a backslash: `not \${a} substitution`. - const escapeText = flags & GetLiteralTextFlags.NeverAsciiEscape || (getEmitFlags(node) & EmitFlags.NoAsciiEscaping) ? escapeString : - escapeNonAsciiString; + const escapeText = + flags & GetLiteralTextFlags.NeverAsciiEscape || (getEmitFlags(node) & EmitFlags.NoAsciiEscaping) + ? escapeString + : escapeNonAsciiString; - const rawText = (node as TemplateLiteralLikeNode).rawText ?? escapeTemplateSubstitution(escapeText(node.text, CharacterCodes.backtick)); + const rawText = (node as TemplateLiteralLikeNode).rawText + ?? escapeTemplateSubstitution(escapeText(node.text, CharacterCodes.backtick)); switch (node.kind) { case SyntaxKind.NoSubstitutionTemplateLiteral: return "`" + rawText + "`"; @@ -1736,7 +1849,8 @@ export function getLiteralText(node: LiteralLikeNode, sourceFile: SourceFile | u return node.text; case SyntaxKind.RegularExpressionLiteral: if (flags & GetLiteralTextFlags.TerminateUnterminatedLiterals && node.isUnterminated) { - return node.text + (node.text.charCodeAt(node.text.length - 1) === CharacterCodes.backslash ? " /" : "/"); + return node.text + + (node.text.charCodeAt(node.text.length - 1) === CharacterCodes.backslash ? " /" : "/"); } return node.text; } @@ -1745,7 +1859,10 @@ export function getLiteralText(node: LiteralLikeNode, sourceFile: SourceFile | u } function canUseOriginalText(node: LiteralLikeNode, flags: GetLiteralTextFlags): boolean { - if (nodeIsSynthesized(node) || !node.parent || (flags & GetLiteralTextFlags.TerminateUnterminatedLiterals && node.isUnterminated)) { + if ( + nodeIsSynthesized(node) || !node.parent + || (flags & GetLiteralTextFlags.TerminateUnterminatedLiterals && node.isUnterminated) + ) { return false; } @@ -1775,8 +1892,8 @@ export function makeIdentifierFromModuleName(moduleName: string): string { /** @internal */ export function isBlockOrCatchScoped(declaration: Declaration) { - return (getCombinedNodeFlags(declaration) & NodeFlags.BlockScoped) !== 0 || - isCatchClauseVariableDeclarationOrBindingElement(declaration); + return (getCombinedNodeFlags(declaration) & NodeFlags.BlockScoped) !== 0 + || isCatchClauseVariableDeclarationOrBindingElement(declaration); } /** @internal */ @@ -1787,7 +1904,8 @@ export function isCatchClauseVariableDeclarationOrBindingElement(declaration: De /** @internal */ export function isAmbientModule(node: Node): node is AmbientModuleDeclaration { - return isModuleDeclaration(node) && (node.name.kind === SyntaxKind.StringLiteral || isGlobalScopeAugmentation(node)); + return isModuleDeclaration(node) + && (node.name.kind === SyntaxKind.StringLiteral || isGlobalScopeAugmentation(node)); } /** @internal */ @@ -1828,9 +1946,9 @@ function isShorthandAmbientModule(node: Node | undefined): boolean { /** @internal */ export function isBlockScopedContainerTopLevel(node: Node): boolean { - return node.kind === SyntaxKind.SourceFile || - node.kind === SyntaxKind.ModuleDeclaration || - isFunctionLikeOrClassStaticBlockDeclaration(node); + return node.kind === SyntaxKind.SourceFile + || node.kind === SyntaxKind.ModuleDeclaration + || isFunctionLikeOrClassStaticBlockDeclaration(node); } /** @internal */ @@ -1852,14 +1970,17 @@ export function isModuleAugmentationExternal(node: AmbientModuleDeclaration) { case SyntaxKind.SourceFile: return isExternalModule(node.parent); case SyntaxKind.ModuleBlock: - return isAmbientModule(node.parent.parent) && isSourceFile(node.parent.parent.parent) && !isExternalModule(node.parent.parent.parent); + return isAmbientModule(node.parent.parent) && isSourceFile(node.parent.parent.parent) + && !isExternalModule(node.parent.parent.parent); } return false; } /** @internal */ export function getNonAugmentationDeclaration(symbol: Symbol) { - return symbol.declarations?.find(d => !isExternalModuleAugmentation(d) && !(isModuleDeclaration(d) && isGlobalScopeAugmentation(d))); + return symbol.declarations?.find(d => + !isExternalModuleAugmentation(d) && !(isModuleDeclaration(d) && isGlobalScopeAugmentation(d)) + ); } function isCommonJSContainingModuleKind(kind: ModuleKind) { @@ -1868,7 +1989,8 @@ function isCommonJSContainingModuleKind(kind: ModuleKind) { /** @internal */ export function isEffectiveExternalModule(node: SourceFile, compilerOptions: CompilerOptions) { - return isExternalModule(node) || (isCommonJSContainingModuleKind(getEmitModuleKind(compilerOptions)) && !!node.commonJsModuleIndicator); + return isExternalModule(node) + || (isCommonJSContainingModuleKind(getEmitModuleKind(compilerOptions)) && !!node.commonJsModuleIndicator); } /** @@ -2024,7 +2146,9 @@ export function isLateVisibilityPaintedStatement(node: Node): node is LateVisibi } /** @internal */ -export function hasPossibleExternalModuleReference(node: Node): node is AnyImportOrReExport | ModuleDeclaration | ImportTypeNode | ImportCall { +export function hasPossibleExternalModuleReference( + node: Node, +): node is AnyImportOrReExport | ModuleDeclaration | ImportTypeNode | ImportCall { return isAnyImportOrReExport(node) || isModuleDeclaration(node) || isImportTypeNode(node) || isImportCall(node); } @@ -2073,7 +2197,9 @@ export function isComputedNonLiteralName(name: PropertyName): boolean { } /** @internal */ -export function tryGetTextOfPropertyName(name: PropertyName | NoSubstitutionTemplateLiteral | JsxAttributeName): __String | undefined { +export function tryGetTextOfPropertyName( + name: PropertyName | NoSubstitutionTemplateLiteral | JsxAttributeName, +): __String | undefined { switch (name.kind) { case SyntaxKind.Identifier: case SyntaxKind.PrivateIdentifier: @@ -2098,7 +2224,9 @@ export function getTextOfPropertyName(name: PropertyName | NoSubstitutionTemplat } /** @internal */ -export function entityNameToString(name: EntityNameOrEntityNameExpression | JSDocMemberName | JsxTagNameExpression | PrivateIdentifier): string { +export function entityNameToString( + name: EntityNameOrEntityNameExpression | JSDocMemberName | JsxTagNameExpression | PrivateIdentifier, +): string { switch (name.kind) { case SyntaxKind.ThisKeyword: return "this"; @@ -2124,31 +2252,55 @@ export function entityNameToString(name: EntityNameOrEntityNameExpression | JSDo } /** @internal */ -export function createDiagnosticForNode(node: Node, message: DiagnosticMessage, ...args: DiagnosticArguments): DiagnosticWithLocation { +export function createDiagnosticForNode( + node: Node, + message: DiagnosticMessage, + ...args: DiagnosticArguments +): DiagnosticWithLocation { const sourceFile = getSourceFileOfNode(node); return createDiagnosticForNodeInSourceFile(sourceFile, node, message, ...args); } /** @internal */ -export function createDiagnosticForNodeArray(sourceFile: SourceFile, nodes: NodeArray, message: DiagnosticMessage, ...args: DiagnosticArguments): DiagnosticWithLocation { +export function createDiagnosticForNodeArray( + sourceFile: SourceFile, + nodes: NodeArray, + message: DiagnosticMessage, + ...args: DiagnosticArguments +): DiagnosticWithLocation { const start = skipTrivia(sourceFile.text, nodes.pos); return createFileDiagnostic(sourceFile, start, nodes.end - start, message, ...args); } /** @internal */ -export function createDiagnosticForNodeInSourceFile(sourceFile: SourceFile, node: Node, message: DiagnosticMessage, ...args: DiagnosticArguments): DiagnosticWithLocation { +export function createDiagnosticForNodeInSourceFile( + sourceFile: SourceFile, + node: Node, + message: DiagnosticMessage, + ...args: DiagnosticArguments +): DiagnosticWithLocation { const span = getErrorSpanForNode(sourceFile, node); return createFileDiagnostic(sourceFile, span.start, span.length, message, ...args); } /** @internal */ -export function createDiagnosticForNodeFromMessageChain(sourceFile: SourceFile, node: Node, messageChain: DiagnosticMessageChain, relatedInformation?: DiagnosticRelatedInformation[]): DiagnosticWithLocation { +export function createDiagnosticForNodeFromMessageChain( + sourceFile: SourceFile, + node: Node, + messageChain: DiagnosticMessageChain, + relatedInformation?: DiagnosticRelatedInformation[], +): DiagnosticWithLocation { const span = getErrorSpanForNode(sourceFile, node); return createFileDiagnosticFromMessageChain(sourceFile, span.start, span.length, messageChain, relatedInformation); } /** @internal */ -export function createDiagnosticForNodeArrayFromMessageChain(sourceFile: SourceFile, nodes: NodeArray, messageChain: DiagnosticMessageChain, relatedInformation?: DiagnosticRelatedInformation[]): DiagnosticWithLocation { +export function createDiagnosticForNodeArrayFromMessageChain( + sourceFile: SourceFile, + nodes: NodeArray, + messageChain: DiagnosticMessageChain, + relatedInformation?: DiagnosticRelatedInformation[], +): DiagnosticWithLocation { const start = skipTrivia(sourceFile.text, nodes.pos); return createFileDiagnosticFromMessageChain(sourceFile, start, nodes.end - start, messageChain, relatedInformation); } @@ -2164,7 +2316,13 @@ function assertDiagnosticLocation(file: SourceFile | undefined, start: number, l } /** @internal */ -export function createFileDiagnosticFromMessageChain(file: SourceFile, start: number, length: number, messageChain: DiagnosticMessageChain, relatedInformation?: DiagnosticRelatedInformation[]): DiagnosticWithLocation { +export function createFileDiagnosticFromMessageChain( + file: SourceFile, + start: number, + length: number, + messageChain: DiagnosticMessageChain, + relatedInformation?: DiagnosticRelatedInformation[], +): DiagnosticWithLocation { assertDiagnosticLocation(file, start, length); return { file, @@ -2178,7 +2336,11 @@ export function createFileDiagnosticFromMessageChain(file: SourceFile, start: nu } /** @internal */ -export function createDiagnosticForFileFromMessageChain(sourceFile: SourceFile, messageChain: DiagnosticMessageChain, relatedInformation?: DiagnosticRelatedInformation[]): DiagnosticWithLocation { +export function createDiagnosticForFileFromMessageChain( + sourceFile: SourceFile, + messageChain: DiagnosticMessageChain, + relatedInformation?: DiagnosticRelatedInformation[], +): DiagnosticWithLocation { return { file: sourceFile, start: 0, @@ -2191,7 +2353,9 @@ export function createDiagnosticForFileFromMessageChain(sourceFile: SourceFile, } /** @internal */ -export function createDiagnosticMessageChainFromDiagnostic(diagnostic: DiagnosticRelatedInformation): DiagnosticMessageChain { +export function createDiagnosticMessageChainFromDiagnostic( + diagnostic: DiagnosticRelatedInformation, +): DiagnosticMessageChain { return typeof diagnostic.messageText === "string" ? { code: diagnostic.code, category: diagnostic.category, @@ -2201,7 +2365,11 @@ export function createDiagnosticMessageChainFromDiagnostic(diagnostic: Diagnosti } /** @internal */ -export function createDiagnosticForRange(sourceFile: SourceFile, range: TextRange, message: DiagnosticMessage): DiagnosticWithLocation { +export function createDiagnosticForRange( + sourceFile: SourceFile, + range: TextRange, + message: DiagnosticMessage, +): DiagnosticWithLocation { return { file: sourceFile, start: range.pos, @@ -2214,7 +2382,14 @@ export function createDiagnosticForRange(sourceFile: SourceFile, range: TextRang /** @internal */ export function getSpanOfTokenAtPosition(sourceFile: SourceFile, pos: number): TextSpan { - const scanner = createScanner(sourceFile.languageVersion, /*skipTrivia*/ true, sourceFile.languageVariant, sourceFile.text, /*onError*/ undefined, pos); + const scanner = createScanner( + sourceFile.languageVersion, + /*skipTrivia*/ true, + sourceFile.languageVariant, + sourceFile.text, + /*onError*/ undefined, + pos, + ); scanner.scan(); const start = scanner.getTokenStart(); return createTextSpanFromBounds(start, scanner.getTokenEnd()); @@ -2222,7 +2397,14 @@ export function getSpanOfTokenAtPosition(sourceFile: SourceFile, pos: number): T /** @internal */ export function scanTokenAtPosition(sourceFile: SourceFile, pos: number) { - const scanner = createScanner(sourceFile.languageVersion, /*skipTrivia*/ true, sourceFile.languageVariant, sourceFile.text, /*onError*/ undefined, pos); + const scanner = createScanner( + sourceFile.languageVersion, + /*skipTrivia*/ true, + sourceFile.languageVariant, + sourceFile.text, + /*onError*/ undefined, + pos, + ); scanner.scan(); return scanner.getToken(); } @@ -2279,7 +2461,8 @@ export function getErrorSpanForNode(sourceFile: SourceFile, node: Node): TextSpa case SyntaxKind.CaseClause: case SyntaxKind.DefaultClause: { const start = skipTrivia(sourceFile.text, (node as CaseOrDefaultClause).pos); - const end = (node as CaseOrDefaultClause).statements.length > 0 ? (node as CaseOrDefaultClause).statements[0].pos : (node as CaseOrDefaultClause).end; + const end = (node as CaseOrDefaultClause).statements.length > 0 + ? (node as CaseOrDefaultClause).statements[0].pos : (node as CaseOrDefaultClause).end; return createTextSpanFromBounds(start, end); } case SyntaxKind.ReturnStatement: @@ -2312,12 +2495,24 @@ export function getErrorSpanForNode(sourceFile: SourceFile, node: Node): TextSpa // These asserts should all be satisfied for a properly constructed `errorNode`. if (isMissing) { - Debug.assert(pos === errorNode.pos, "This failure could trigger https://github.com/Microsoft/TypeScript/issues/20809"); - Debug.assert(pos === errorNode.end, "This failure could trigger https://github.com/Microsoft/TypeScript/issues/20809"); + Debug.assert( + pos === errorNode.pos, + "This failure could trigger https://github.com/Microsoft/TypeScript/issues/20809", + ); + Debug.assert( + pos === errorNode.end, + "This failure could trigger https://github.com/Microsoft/TypeScript/issues/20809", + ); } else { - Debug.assert(pos >= errorNode.pos, "This failure could trigger https://github.com/Microsoft/TypeScript/issues/20809"); - Debug.assert(pos <= errorNode.end, "This failure could trigger https://github.com/Microsoft/TypeScript/issues/20809"); + Debug.assert( + pos >= errorNode.pos, + "This failure could trigger https://github.com/Microsoft/TypeScript/issues/20809", + ); + Debug.assert( + pos <= errorNode.end, + "This failure could trigger https://github.com/Microsoft/TypeScript/issues/20809", + ); } return createTextSpanFromBounds(pos, errorNode.end); @@ -2340,7 +2535,8 @@ export function isEnumConst(node: EnumDeclaration): boolean { /** @internal */ export function isDeclarationReadonly(declaration: Declaration): boolean { - return !!(getCombinedModifierFlags(declaration) & ModifierFlags.Readonly && !isParameterPropertyDeclaration(declaration, declaration.parent)); + return !!(getCombinedModifierFlags(declaration) & ModifierFlags.Readonly + && !isParameterPropertyDeclaration(declaration, declaration.parent)); } /** @@ -2433,28 +2629,30 @@ export function getLeadingCommentRangesOfNode(node: Node, sourceFileOfNode: Sour /** @internal */ export function getJSDocCommentRanges(node: Node, text: string) { - const commentRanges = (node.kind === SyntaxKind.Parameter || - node.kind === SyntaxKind.TypeParameter || - node.kind === SyntaxKind.FunctionExpression || - node.kind === SyntaxKind.ArrowFunction || - node.kind === SyntaxKind.ParenthesizedExpression || - node.kind === SyntaxKind.VariableDeclaration || - node.kind === SyntaxKind.ExportSpecifier) ? - concatenate(getTrailingCommentRanges(text, node.pos), getLeadingCommentRanges(text, node.pos)) : - getLeadingCommentRanges(text, node.pos); + const commentRanges = (node.kind === SyntaxKind.Parameter + || node.kind === SyntaxKind.TypeParameter + || node.kind === SyntaxKind.FunctionExpression + || node.kind === SyntaxKind.ArrowFunction + || node.kind === SyntaxKind.ParenthesizedExpression + || node.kind === SyntaxKind.VariableDeclaration + || node.kind === SyntaxKind.ExportSpecifier) + ? concatenate(getTrailingCommentRanges(text, node.pos), getLeadingCommentRanges(text, node.pos)) + : getLeadingCommentRanges(text, node.pos); // True if the comment starts with '/**' but not if it is '/**/' return filter(commentRanges, comment => - text.charCodeAt(comment.pos + 1) === CharacterCodes.asterisk && - text.charCodeAt(comment.pos + 2) === CharacterCodes.asterisk && - text.charCodeAt(comment.pos + 3) !== CharacterCodes.slash); + text.charCodeAt(comment.pos + 1) === CharacterCodes.asterisk + && text.charCodeAt(comment.pos + 2) === CharacterCodes.asterisk + && text.charCodeAt(comment.pos + 3) !== CharacterCodes.slash); } /** @internal */ export const fullTripleSlashReferencePathRegEx = /^(\/\/\/\s*/; -const fullTripleSlashReferenceTypeReferenceDirectiveRegEx = /^(\/\/\/\s*/; +const fullTripleSlashReferenceTypeReferenceDirectiveRegEx = + /^(\/\/\/\s*/; const fullTripleSlashLibReferenceRegEx = /^(\/\/\/\s*/; /** @internal */ -export const fullTripleSlashAMDReferencePathRegEx = /^(\/\/\/\s*/; +export const fullTripleSlashAMDReferencePathRegEx = + /^(\/\/\/\s*/; const fullTripleSlashAMDModuleRegEx = /^\/\/\/\s*/; const defaultLibReferenceRegEx = /^(\/\/\/\s*/; @@ -2491,11 +2689,18 @@ export function isPartOfTypeNode(node: Node): boolean { if (node.parent.kind === SyntaxKind.QualifiedName && (node.parent as QualifiedName).right === node) { node = node.parent; } - else if (node.parent.kind === SyntaxKind.PropertyAccessExpression && (node.parent as PropertyAccessExpression).name === node) { + else if ( + node.parent.kind === SyntaxKind.PropertyAccessExpression + && (node.parent as PropertyAccessExpression).name === node + ) { node = node.parent; } // At this point, node is either a qualified name or an identifier - Debug.assert(node.kind === SyntaxKind.Identifier || node.kind === SyntaxKind.QualifiedName || node.kind === SyntaxKind.PropertyAccessExpression, "'node' was expected to be a qualified name, identifier or property access in 'isPartOfTypeNode'."); + Debug.assert( + node.kind === SyntaxKind.Identifier || node.kind === SyntaxKind.QualifiedName + || node.kind === SyntaxKind.PropertyAccessExpression, + "'node' was expected to be a qualified name, identifier or property access in 'isPartOfTypeNode'.", + ); // falls through case SyntaxKind.QualifiedName: @@ -2519,7 +2724,8 @@ export function isPartOfTypeNode(node: Node): boolean { } switch (parent.kind) { case SyntaxKind.ExpressionWithTypeArguments: - return isHeritageClause(parent.parent) && !isExpressionWithTypeArgumentsInClassExtendsClause(parent); + return isHeritageClause(parent.parent) + && !isExpressionWithTypeArgumentsInClassExtendsClause(parent); case SyntaxKind.TypeParameter: return node === (parent as TypeParameterDeclaration).constraint; case SyntaxKind.JSDocTemplateTag: @@ -2569,7 +2775,10 @@ export function isChildOfNodeWithKind(node: Node, kind: SyntaxKind): boolean { // Warning: This has the same semantics as the forEach family of functions, // in that traversal terminates in the event that 'visitor' supplies a truthy value. /** @internal */ -export function forEachReturnStatement(body: Block | Statement, visitor: (stmt: ReturnStatement) => T): T | undefined { +export function forEachReturnStatement( + body: Block | Statement, + visitor: (stmt: ReturnStatement) => T, +): T | undefined { return traverse(body); function traverse(node: Node): T | undefined { @@ -2655,7 +2864,9 @@ export function getRestParameterElementType(node: TypeNode | undefined) { } /** @internal */ -export function getMembersOfDeclaration(node: Declaration): NodeArray | undefined { +export function getMembersOfDeclaration( + node: Declaration, +): NodeArray | undefined { switch (node.kind) { case SyntaxKind.InterfaceDeclaration: case SyntaxKind.ClassDeclaration: @@ -2699,21 +2910,24 @@ export function isVariableDeclarationInVariableStatement(node: VariableDeclarati /** @internal */ export function isCommonJsExportedExpression(node: Node) { if (!isInJSFile(node)) return false; - return (isObjectLiteralExpression(node.parent) && isBinaryExpression(node.parent.parent) && getAssignmentDeclarationKind(node.parent.parent) === AssignmentDeclarationKind.ModuleExports) || - isCommonJsExportPropertyAssignment(node.parent); + return (isObjectLiteralExpression(node.parent) && isBinaryExpression(node.parent.parent) + && getAssignmentDeclarationKind(node.parent.parent) === AssignmentDeclarationKind.ModuleExports) + || isCommonJsExportPropertyAssignment(node.parent); } /** @internal */ export function isCommonJsExportPropertyAssignment(node: Node) { if (!isInJSFile(node)) return false; - return (isBinaryExpression(node) && getAssignmentDeclarationKind(node) === AssignmentDeclarationKind.ExportsProperty); + return (isBinaryExpression(node) + && getAssignmentDeclarationKind(node) === AssignmentDeclarationKind.ExportsProperty); } /** @internal */ export function isValidESSymbolDeclaration(node: Node): boolean { - return (isVariableDeclaration(node) ? isVarConst(node) && isIdentifier(node.name) && isVariableDeclarationInVariableStatement(node) : - isPropertyDeclaration(node) ? hasEffectiveReadonlyModifier(node) && hasStaticModifier(node) : - isPropertySignature(node) && hasEffectiveReadonlyModifier(node)) || isCommonJsExportPropertyAssignment(node); + return (isVariableDeclaration(node) + ? isVarConst(node) && isIdentifier(node.name) && isVariableDeclarationInVariableStatement(node) + : isPropertyDeclaration(node) ? hasEffectiveReadonlyModifier(node) && hasStaticModifier(node) + : isPropertySignature(node) && hasEffectiveReadonlyModifier(node)) || isCommonJsExportPropertyAssignment(node); } /** @internal */ @@ -2732,7 +2946,10 @@ export function introducesArgumentsExoticObject(node: Node) { } /** @internal */ -export function unwrapInnermostStatementOfLabel(node: LabeledStatement, beforeUnwrapLabelCallback?: (node: LabeledStatement) => void): Statement { +export function unwrapInnermostStatementOfLabel( + node: LabeledStatement, + beforeUnwrapLabelCallback?: (node: LabeledStatement) => void, +): Statement { while (true) { if (beforeUnwrapLabelCallback) { beforeUnwrapLabelCallback(node); @@ -2751,14 +2968,18 @@ export function isFunctionBlock(node: Node): boolean { /** @internal */ export function isObjectLiteralMethod(node: Node): node is MethodDeclaration { - return node && node.kind === SyntaxKind.MethodDeclaration && node.parent.kind === SyntaxKind.ObjectLiteralExpression; + return node && node.kind === SyntaxKind.MethodDeclaration + && node.parent.kind === SyntaxKind.ObjectLiteralExpression; } /** @internal */ -export function isObjectLiteralOrClassExpressionMethodOrAccessor(node: Node): node is MethodDeclaration | AccessorDeclaration { - return (node.kind === SyntaxKind.MethodDeclaration || node.kind === SyntaxKind.GetAccessor || node.kind === SyntaxKind.SetAccessor) && - (node.parent.kind === SyntaxKind.ObjectLiteralExpression || - node.parent.kind === SyntaxKind.ClassExpression); +export function isObjectLiteralOrClassExpressionMethodOrAccessor( + node: Node, +): node is MethodDeclaration | AccessorDeclaration { + return (node.kind === SyntaxKind.MethodDeclaration || node.kind === SyntaxKind.GetAccessor + || node.kind === SyntaxKind.SetAccessor) + && (node.parent.kind === SyntaxKind.ObjectLiteralExpression + || node.parent.kind === SyntaxKind.ClassExpression); } /** @internal */ @@ -2772,26 +2993,38 @@ export function isThisTypePredicate(predicate: TypePredicate): predicate is This } /** @internal */ -export function forEachPropertyAssignment(objectLiteral: ObjectLiteralExpression | undefined, key: string, callback: (property: PropertyAssignment) => T | undefined, key2?: string) { +export function forEachPropertyAssignment( + objectLiteral: ObjectLiteralExpression | undefined, + key: string, + callback: (property: PropertyAssignment) => T | undefined, + key2?: string, +) { return forEach(objectLiteral?.properties, property => { if (!isPropertyAssignment(property)) return undefined; const propName = tryGetTextOfPropertyName(property.name); - return key === propName || (key2 && key2 === propName) ? - callback(property) : - undefined; + return key === propName || (key2 && key2 === propName) + ? callback(property) + : undefined; }); } /** @internal */ -export function getPropertyArrayElementValue(objectLiteral: ObjectLiteralExpression, propKey: string, elementValue: string): StringLiteral | undefined { +export function getPropertyArrayElementValue( + objectLiteral: ObjectLiteralExpression, + propKey: string, + elementValue: string, +): StringLiteral | undefined { return forEachPropertyAssignment(objectLiteral, propKey, property => - isArrayLiteralExpression(property.initializer) ? - find(property.initializer.elements, (element): element is StringLiteral => isStringLiteral(element) && element.text === elementValue) : - undefined); + isArrayLiteralExpression(property.initializer) + ? find(property.initializer.elements, (element): element is StringLiteral => + isStringLiteral(element) && element.text === elementValue) + : undefined); } /** @internal */ -export function getTsConfigObjectLiteralExpression(tsConfigSourceFile: TsConfigSourceFile | undefined): ObjectLiteralExpression | undefined { +export function getTsConfigObjectLiteralExpression( + tsConfigSourceFile: TsConfigSourceFile | undefined, +): ObjectLiteralExpression | undefined { if (tsConfigSourceFile && tsConfigSourceFile.statements.length) { const expression = tsConfigSourceFile.statements[0].expression; return tryCast(expression, isObjectLiteralExpression); @@ -2799,15 +3032,30 @@ export function getTsConfigObjectLiteralExpression(tsConfigSourceFile: TsConfigS } /** @internal */ -export function getTsConfigPropArrayElementValue(tsConfigSourceFile: TsConfigSourceFile | undefined, propKey: string, elementValue: string): StringLiteral | undefined { - return forEachTsConfigPropArray(tsConfigSourceFile, propKey, property => - isArrayLiteralExpression(property.initializer) ? - find(property.initializer.elements, (element): element is StringLiteral => isStringLiteral(element) && element.text === elementValue) : - undefined); +export function getTsConfigPropArrayElementValue( + tsConfigSourceFile: TsConfigSourceFile | undefined, + propKey: string, + elementValue: string, +): StringLiteral | undefined { + return forEachTsConfigPropArray( + tsConfigSourceFile, + propKey, + property => + isArrayLiteralExpression(property.initializer) + ? find( + property.initializer.elements, + (element): element is StringLiteral => isStringLiteral(element) && element.text === elementValue, + ) + : undefined, + ); } /** @internal */ -export function forEachTsConfigPropArray(tsConfigSourceFile: TsConfigSourceFile | undefined, propKey: string, callback: (property: PropertyAssignment) => T | undefined) { +export function forEachTsConfigPropArray( + tsConfigSourceFile: TsConfigSourceFile | undefined, + propKey: string, + callback: (property: PropertyAssignment) => T | undefined, +) { return forEachPropertyAssignment(getTsConfigObjectLiteralExpression(tsConfigSourceFile), propKey, callback); } @@ -2837,14 +3085,17 @@ export function getContainingClassStaticBlock(node: Node): Node | undefined { } /** @internal */ -export function getContainingFunctionOrClassStaticBlock(node: Node): SignatureDeclaration | ClassStaticBlockDeclaration | undefined { +export function getContainingFunctionOrClassStaticBlock( + node: Node, +): SignatureDeclaration | ClassStaticBlockDeclaration | undefined { return findAncestor(node.parent, isFunctionLikeOrClassStaticBlockDeclaration); } /** @internal */ export function getContainingClassExcludingClassDecorators(node: Node): ClassLikeDeclaration | undefined { const decorator = findAncestor(node.parent, n => isClassLike(n) ? "quit" : isDecorator(n)); - return decorator && isClassLike(decorator.parent) ? getContainingClass(decorator.parent) : getContainingClass(decorator ?? node); + return decorator && isClassLike(decorator.parent) ? getContainingClass(decorator.parent) + : getContainingClass(decorator ?? node); } /** @internal */ @@ -2867,14 +3118,34 @@ export type ThisContainer = | SourceFile; /** @internal */ -export function getThisContainer(node: Node, includeArrowFunctions: false, includeClassComputedPropertyName: false): ThisContainer; -/** @internal */ -export function getThisContainer(node: Node, includeArrowFunctions: false, includeClassComputedPropertyName: boolean): ThisContainer | ComputedPropertyName; -/** @internal */ -export function getThisContainer(node: Node, includeArrowFunctions: boolean, includeClassComputedPropertyName: false): ThisContainer | ArrowFunction; -/** @internal */ -export function getThisContainer(node: Node, includeArrowFunctions: boolean, includeClassComputedPropertyName: boolean): ThisContainer | ArrowFunction | ComputedPropertyName; -export function getThisContainer(node: Node, includeArrowFunctions: boolean, includeClassComputedPropertyName: boolean) { +export function getThisContainer( + node: Node, + includeArrowFunctions: false, + includeClassComputedPropertyName: false, +): ThisContainer; +/** @internal */ +export function getThisContainer( + node: Node, + includeArrowFunctions: false, + includeClassComputedPropertyName: boolean, +): ThisContainer | ComputedPropertyName; +/** @internal */ +export function getThisContainer( + node: Node, + includeArrowFunctions: boolean, + includeClassComputedPropertyName: false, +): ThisContainer | ArrowFunction; +/** @internal */ +export function getThisContainer( + node: Node, + includeArrowFunctions: boolean, + includeClassComputedPropertyName: boolean, +): ThisContainer | ArrowFunction | ComputedPropertyName; +export function getThisContainer( + node: Node, + includeArrowFunctions: boolean, + includeClassComputedPropertyName: boolean, +) { Debug.assert(node.kind !== SyntaxKind.SourceFile); while (true) { node = node.parent; @@ -2970,16 +3241,27 @@ export function isThisContainerOrFunctionBlock(node: Node): boolean { /** @internal */ export function isInTopLevelContext(node: Node) { // The name of a class or function declaration is a BindingIdentifier in its surrounding scope. - if (isIdentifier(node) && (isClassDeclaration(node.parent) || isFunctionDeclaration(node.parent)) && node.parent.name === node) { + if ( + isIdentifier(node) && (isClassDeclaration(node.parent) || isFunctionDeclaration(node.parent)) + && node.parent.name === node + ) { node = node.parent; } - const container = getThisContainer(node, /*includeArrowFunctions*/ true, /*includeClassComputedPropertyName*/ false); + const container = getThisContainer( + node, + /*includeArrowFunctions*/ true, + /*includeClassComputedPropertyName*/ false, + ); return isSourceFile(container); } /** @internal */ export function getNewTargetContainer(node: Node) { - const container = getThisContainer(node, /*includeArrowFunctions*/ false, /*includeClassComputedPropertyName*/ false); + const container = getThisContainer( + node, + /*includeArrowFunctions*/ false, + /*includeClassComputedPropertyName*/ false, + ); if (container) { switch (container.kind) { case SyntaxKind.Constructor: @@ -3166,7 +3448,12 @@ export function nodeCanBeDecorated(useLegacyDecorators: boolean, node: ClassElem /** @internal */ export function nodeCanBeDecorated(useLegacyDecorators: boolean, node: Node, parent: Node, grandparent: Node): boolean; /** @internal */ -export function nodeCanBeDecorated(useLegacyDecorators: boolean, node: Node, parent?: Node, grandparent?: Node): boolean { +export function nodeCanBeDecorated( + useLegacyDecorators: boolean, + node: Node, + parent?: Node, + grandparent?: Node, +): boolean { // private names cannot be used with decorators yet if (useLegacyDecorators && isNamedDeclaration(node) && isPrivateIdentifier(node.name)) { return false; @@ -3184,7 +3471,8 @@ export function nodeCanBeDecorated(useLegacyDecorators: boolean, node: Node, par case SyntaxKind.PropertyDeclaration: // property declarations are valid if their parent is a class declaration. return parent !== undefined - && (useLegacyDecorators ? isClassDeclaration(parent) : isClassLike(parent) && !hasAbstractModifier(node) && !hasAmbientModifier(node)); + && (useLegacyDecorators ? isClassDeclaration(parent) + : isClassLike(parent) && !hasAbstractModifier(node) && !hasAmbientModifier(node)); case SyntaxKind.GetAccessor: case SyntaxKind.SetAccessor: @@ -3228,9 +3516,19 @@ export function nodeOrChildIsDecorated(useLegacyDecorators: boolean, node: Class /** @internal */ export function nodeOrChildIsDecorated(useLegacyDecorators: boolean, node: ClassElement, parent: Node): boolean; /** @internal */ -export function nodeOrChildIsDecorated(useLegacyDecorators: boolean, node: Node, parent: Node, grandparent: Node): boolean; -/** @internal */ -export function nodeOrChildIsDecorated(useLegacyDecorators: boolean, node: Node, parent?: Node, grandparent?: Node): boolean { +export function nodeOrChildIsDecorated( + useLegacyDecorators: boolean, + node: Node, + parent: Node, + grandparent: Node, +): boolean; +/** @internal */ +export function nodeOrChildIsDecorated( + useLegacyDecorators: boolean, + node: Node, + parent?: Node, + grandparent?: Node, +): boolean { return nodeIsDecorated(useLegacyDecorators, node, parent!, grandparent!) || childIsDecorated(useLegacyDecorators, node, parent!); } @@ -3243,33 +3541,50 @@ export function childIsDecorated(useLegacyDecorators: boolean, node: Node, paren export function childIsDecorated(useLegacyDecorators: boolean, node: Node, parent?: Node): boolean { switch (node.kind) { case SyntaxKind.ClassDeclaration: - return some((node as ClassDeclaration).members, m => nodeOrChildIsDecorated(useLegacyDecorators, m, node, parent!)); + return some( + (node as ClassDeclaration).members, + m => nodeOrChildIsDecorated(useLegacyDecorators, m, node, parent!), + ); case SyntaxKind.ClassExpression: - return !useLegacyDecorators && some((node as ClassExpression).members, m => nodeOrChildIsDecorated(useLegacyDecorators, m, node, parent!)); + return !useLegacyDecorators + && some( + (node as ClassExpression).members, + m => nodeOrChildIsDecorated(useLegacyDecorators, m, node, parent!), + ); case SyntaxKind.MethodDeclaration: case SyntaxKind.SetAccessor: case SyntaxKind.Constructor: - return some((node as FunctionLikeDeclaration).parameters, p => nodeIsDecorated(useLegacyDecorators, p, node, parent!)); + return some( + (node as FunctionLikeDeclaration).parameters, + p => nodeIsDecorated(useLegacyDecorators, p, node, parent!), + ); default: return false; } } /** @internal */ -export function classOrConstructorParameterIsDecorated(useLegacyDecorators: boolean, node: ClassDeclaration | ClassExpression): boolean { +export function classOrConstructorParameterIsDecorated( + useLegacyDecorators: boolean, + node: ClassDeclaration | ClassExpression, +): boolean { if (nodeIsDecorated(useLegacyDecorators, node)) return true; const constructor = getFirstConstructorWithBody(node); return !!constructor && childIsDecorated(useLegacyDecorators, constructor, node); } /** @internal */ -export function classElementOrClassElementParameterIsDecorated(useLegacyDecorators: boolean, node: ClassElement, parent: ClassDeclaration | ClassExpression): boolean { +export function classElementOrClassElementParameterIsDecorated( + useLegacyDecorators: boolean, + node: ClassElement, + parent: ClassDeclaration | ClassExpression, +): boolean { let parameters: NodeArray | undefined; if (isAccessor(node)) { const { firstAccessor, secondAccessor, setAccessor } = getAllAccessorDeclarations(parent.members, node); - const firstAccessorWithDecorators = hasDecorators(firstAccessor) ? firstAccessor : - secondAccessor && hasDecorators(secondAccessor) ? secondAccessor : - undefined; + const firstAccessorWithDecorators = hasDecorators(firstAccessor) ? firstAccessor + : secondAccessor && hasDecorators(secondAccessor) ? secondAccessor + : undefined; if (!firstAccessorWithDecorators || node !== firstAccessorWithDecorators) { return false; } @@ -3308,9 +3623,9 @@ export function isEmptyStringLiteral(node: StringLiteral): boolean { export function isJSXTagName(node: Node) { const { parent } = node; if ( - parent.kind === SyntaxKind.JsxOpeningElement || - parent.kind === SyntaxKind.JsxSelfClosingElement || - parent.kind === SyntaxKind.JsxClosingElement + parent.kind === SyntaxKind.JsxOpeningElement + || parent.kind === SyntaxKind.JsxSelfClosingElement + || parent.kind === SyntaxKind.JsxClosingElement ) { return (parent as JsxOpeningLikeElement).tagName === node; } @@ -3363,16 +3678,22 @@ export function isExpressionNode(node: Node): boolean { while (node.parent.kind === SyntaxKind.QualifiedName) { node = node.parent; } - return node.parent.kind === SyntaxKind.TypeQuery || isJSDocLinkLike(node.parent) || isJSDocNameReference(node.parent) || isJSDocMemberName(node.parent) || isJSXTagName(node); + return node.parent.kind === SyntaxKind.TypeQuery || isJSDocLinkLike(node.parent) + || isJSDocNameReference(node.parent) || isJSDocMemberName(node.parent) || isJSXTagName(node); case SyntaxKind.JSDocMemberName: while (isJSDocMemberName(node.parent)) { node = node.parent; } - return node.parent.kind === SyntaxKind.TypeQuery || isJSDocLinkLike(node.parent) || isJSDocNameReference(node.parent) || isJSDocMemberName(node.parent) || isJSXTagName(node); + return node.parent.kind === SyntaxKind.TypeQuery || isJSDocLinkLike(node.parent) + || isJSDocNameReference(node.parent) || isJSDocMemberName(node.parent) || isJSXTagName(node); case SyntaxKind.PrivateIdentifier: - return isBinaryExpression(node.parent) && node.parent.left === node && node.parent.operatorToken.kind === SyntaxKind.InKeyword; + return isBinaryExpression(node.parent) && node.parent.left === node + && node.parent.operatorToken.kind === SyntaxKind.InKeyword; case SyntaxKind.Identifier: - if (node.parent.kind === SyntaxKind.TypeQuery || isJSDocLinkLike(node.parent) || isJSDocNameReference(node.parent) || isJSDocMemberName(node.parent) || isJSXTagName(node)) { + if ( + node.parent.kind === SyntaxKind.TypeQuery || isJSDocLinkLike(node.parent) + || isJSDocNameReference(node.parent) || isJSDocMemberName(node.parent) || isJSXTagName(node) + ) { return true; } // falls through @@ -3412,14 +3733,16 @@ export function isInExpressionContext(node: Node): boolean { return (parent as ExpressionStatement).expression === node; case SyntaxKind.ForStatement: const forStatement = parent as ForStatement; - return (forStatement.initializer === node && forStatement.initializer.kind !== SyntaxKind.VariableDeclarationList) || - forStatement.condition === node || - forStatement.incrementor === node; + return (forStatement.initializer === node + && forStatement.initializer.kind !== SyntaxKind.VariableDeclarationList) + || forStatement.condition === node + || forStatement.incrementor === node; case SyntaxKind.ForInStatement: case SyntaxKind.ForOfStatement: const forInStatement = parent as ForInStatement | ForOfStatement; - return (forInStatement.initializer === node && forInStatement.initializer.kind !== SyntaxKind.VariableDeclarationList) || - forInStatement.expression === node; + return (forInStatement.initializer === node + && forInStatement.initializer.kind !== SyntaxKind.VariableDeclarationList) + || forInStatement.expression === node; case SyntaxKind.TypeAssertionExpression: case SyntaxKind.AsExpression: return node === (parent as AssertionExpression).expression; @@ -3457,8 +3780,11 @@ export function isNamespaceReexportDeclaration(node: Node): boolean { } /** @internal */ -export function isExternalModuleImportEqualsDeclaration(node: Node): node is ImportEqualsDeclaration & { moduleReference: ExternalModuleReference; } { - return node.kind === SyntaxKind.ImportEqualsDeclaration && (node as ImportEqualsDeclaration).moduleReference.kind === SyntaxKind.ExternalModuleReference; +export function isExternalModuleImportEqualsDeclaration( + node: Node, +): node is ImportEqualsDeclaration & { moduleReference: ExternalModuleReference; } { + return node.kind === SyntaxKind.ImportEqualsDeclaration + && (node as ImportEqualsDeclaration).moduleReference.kind === SyntaxKind.ExternalModuleReference; } /** @internal */ @@ -3469,12 +3795,14 @@ export function getExternalModuleImportEqualsDeclarationExpression(node: Node) { /** @internal */ export function getExternalModuleRequireArgument(node: Node) { - return isVariableDeclarationInitializedToBareOrAccessedRequire(node) && (getLeftmostAccessExpression(node.initializer) as CallExpression).arguments[0] as StringLiteral; + return isVariableDeclarationInitializedToBareOrAccessedRequire(node) + && (getLeftmostAccessExpression(node.initializer) as CallExpression).arguments[0] as StringLiteral; } /** @internal */ export function isInternalModuleImportEqualsDeclaration(node: Node): node is ImportEqualsDeclaration { - return node.kind === SyntaxKind.ImportEqualsDeclaration && (node as ImportEqualsDeclaration).moduleReference.kind !== SyntaxKind.ExternalModuleReference; + return node.kind === SyntaxKind.ImportEqualsDeclaration + && (node as ImportEqualsDeclaration).moduleReference.kind !== SyntaxKind.ExternalModuleReference; } /** @internal */ @@ -3509,11 +3837,12 @@ export function isInJSDoc(node: Node | undefined): boolean { /** @internal */ export function isJSDocIndexSignature(node: TypeReferenceNode | ExpressionWithTypeArguments) { - return isTypeReferenceNode(node) && - isIdentifier(node.typeName) && - node.typeName.escapedText === "Object" && - node.typeArguments && node.typeArguments.length === 2 && - (node.typeArguments[0].kind === SyntaxKind.StringKeyword || node.typeArguments[0].kind === SyntaxKind.NumberKeyword); + return isTypeReferenceNode(node) + && isIdentifier(node.typeName) + && node.typeName.escapedText === "Object" + && node.typeArguments && node.typeArguments.length === 2 + && (node.typeArguments[0].kind === SyntaxKind.StringKeyword + || node.typeArguments[0].kind === SyntaxKind.NumberKeyword); } /** @@ -3523,11 +3852,20 @@ export function isJSDocIndexSignature(node: TypeReferenceNode | ExpressionWithTy * * @internal */ -export function isRequireCall(callExpression: Node, requireStringLiteralLikeArgument: true): callExpression is RequireOrImportCall & { expression: Identifier; arguments: [StringLiteralLike]; }; -/** @internal */ -export function isRequireCall(callExpression: Node, requireStringLiteralLikeArgument: boolean): callExpression is CallExpression; -/** @internal */ -export function isRequireCall(callExpression: Node, requireStringLiteralLikeArgument: boolean): callExpression is CallExpression { +export function isRequireCall( + callExpression: Node, + requireStringLiteralLikeArgument: true, +): callExpression is RequireOrImportCall & { expression: Identifier; arguments: [StringLiteralLike]; }; +/** @internal */ +export function isRequireCall( + callExpression: Node, + requireStringLiteralLikeArgument: boolean, +): callExpression is CallExpression; +/** @internal */ +export function isRequireCall( + callExpression: Node, + requireStringLiteralLikeArgument: boolean, +): callExpression is CallExpression { if (callExpression.kind !== SyntaxKind.CallExpression) { return false; } @@ -3550,7 +3888,9 @@ export function isRequireCall(callExpression: Node, requireStringLiteralLikeArgu * * @internal */ -export function isVariableDeclarationInitializedToRequire(node: Node): node is VariableDeclarationInitializedTo { +export function isVariableDeclarationInitializedToRequire( + node: Node, +): node is VariableDeclarationInitializedTo { return isVariableDeclarationInitializedWithRequireHelper(node, /*allowAccessedRequire*/ false); } @@ -3559,7 +3899,9 @@ export function isVariableDeclarationInitializedToRequire(node: Node): node is V * * @internal */ -export function isVariableDeclarationInitializedToBareOrAccessedRequire(node: Node): node is VariableDeclarationInitializedTo { +export function isVariableDeclarationInitializedToBareOrAccessedRequire( + node: Node, +): node is VariableDeclarationInitializedTo { return isVariableDeclarationInitializedWithRequireHelper(node, /*allowAccessedRequire*/ true); } @@ -3569,9 +3911,12 @@ export function isBindingElementOfBareOrAccessedRequire(node: Node): node is Bin } function isVariableDeclarationInitializedWithRequireHelper(node: Node, allowAccessedRequire: boolean) { - return isVariableDeclaration(node) && - !!node.initializer && - isRequireCall(allowAccessedRequire ? getLeftmostAccessExpression(node.initializer) : node.initializer, /*requireStringLiteralLikeArgument*/ true); + return isVariableDeclaration(node) + && !!node.initializer + && isRequireCall( + allowAccessedRequire ? getLeftmostAccessExpression(node.initializer) : node.initializer, + /*requireStringLiteralLikeArgument*/ true, + ); } /** @internal */ @@ -3603,10 +3948,11 @@ export function isAssignmentDeclaration(decl: Declaration) { */ export function getEffectiveInitializer(node: HasExpressionInitializer) { if ( - isInJSFile(node) && node.initializer && - isBinaryExpression(node.initializer) && - (node.initializer.operatorToken.kind === SyntaxKind.BarBarToken || node.initializer.operatorToken.kind === SyntaxKind.QuestionQuestionToken) && - node.name && isEntityNameExpression(node.name) && isSameEntityName(node.name, node.initializer.left) + isInJSFile(node) && node.initializer + && isBinaryExpression(node.initializer) + && (node.initializer.operatorToken.kind === SyntaxKind.BarBarToken + || node.initializer.operatorToken.kind === SyntaxKind.QuestionQuestionToken) + && node.name && isEntityNameExpression(node.name) && isSameEntityName(node.name, node.initializer.left) ) { return node.initializer.right; } @@ -3625,11 +3971,11 @@ export function getDeclaredExpandoInitializer(node: HasExpressionInitializer) { function hasExpandoValueProperty(node: ObjectLiteralExpression, isPrototypeAssignment: boolean) { return forEach(node.properties, p => - isPropertyAssignment(p) && - isIdentifier(p.name) && - p.name.escapedText === "value" && - p.initializer && - getExpandoInitializer(p.initializer, isPrototypeAssignment)); + isPropertyAssignment(p) + && isIdentifier(p.name) + && p.name.escapedText === "value" + && p.initializer + && getExpandoInitializer(p.initializer, isPrototypeAssignment)); } /** @@ -3639,10 +3985,13 @@ function hasExpandoValueProperty(node: ObjectLiteralExpression, isPrototypeAssig * @internal */ export function getAssignedExpandoInitializer(node: Node | undefined): Expression | undefined { - if (node && node.parent && isBinaryExpression(node.parent) && node.parent.operatorToken.kind === SyntaxKind.EqualsToken) { + if ( + node && node.parent && isBinaryExpression(node.parent) + && node.parent.operatorToken.kind === SyntaxKind.EqualsToken + ) { const isPrototypeAssignment = isPrototypeAccess(node.parent.left); - return getExpandoInitializer(node.parent.right, isPrototypeAssignment) || - getDefaultedExpandoInitializer(node.parent.left, node.parent.right, isPrototypeAssignment); + return getExpandoInitializer(node.parent.right, isPrototypeAssignment) + || getDefaultedExpandoInitializer(node.parent.left, node.parent.right, isPrototypeAssignment); } if (node && isCallExpression(node) && isBindableObjectDefinePropertyCall(node)) { const result = hasExpandoValueProperty(node.arguments[2], node.arguments[1].text === "prototype"); @@ -3667,12 +4016,13 @@ export function getAssignedExpandoInitializer(node: Node | undefined): Expressio export function getExpandoInitializer(initializer: Node, isPrototypeAssignment: boolean): Expression | undefined { if (isCallExpression(initializer)) { const e = skipParentheses(initializer.expression); - return e.kind === SyntaxKind.FunctionExpression || e.kind === SyntaxKind.ArrowFunction ? initializer : undefined; + return e.kind === SyntaxKind.FunctionExpression || e.kind === SyntaxKind.ArrowFunction ? initializer + : undefined; } if ( - initializer.kind === SyntaxKind.FunctionExpression || - initializer.kind === SyntaxKind.ClassExpression || - initializer.kind === SyntaxKind.ArrowFunction + initializer.kind === SyntaxKind.FunctionExpression + || initializer.kind === SyntaxKind.ClassExpression + || initializer.kind === SyntaxKind.ArrowFunction ) { return initializer as Expression; } @@ -3691,7 +4041,8 @@ export function getExpandoInitializer(initializer: Node, isPrototypeAssignment: */ function getDefaultedExpandoInitializer(name: Expression, initializer: Expression, isPrototypeAssignment: boolean) { const e = isBinaryExpression(initializer) - && (initializer.operatorToken.kind === SyntaxKind.BarBarToken || initializer.operatorToken.kind === SyntaxKind.QuestionQuestionToken) + && (initializer.operatorToken.kind === SyntaxKind.BarBarToken + || initializer.operatorToken.kind === SyntaxKind.QuestionQuestionToken) && getExpandoInitializer(initializer.right, isPrototypeAssignment); if (e && isSameEntityName(name, initializer.left)) { return e; @@ -3700,10 +4051,12 @@ function getDefaultedExpandoInitializer(name: Expression, initializer: Expressio /** @internal */ export function isDefaultedExpandoInitializer(node: BinaryExpression) { - const name = isVariableDeclaration(node.parent) ? node.parent.name : - isBinaryExpression(node.parent) && node.parent.operatorToken.kind === SyntaxKind.EqualsToken ? node.parent.left : - undefined; - return name && getExpandoInitializer(node.right, isPrototypeAccess(name)) && isEntityNameExpression(name) && isSameEntityName(name, node.left); + const name = isVariableDeclaration(node.parent) ? node.parent.name + : isBinaryExpression(node.parent) && node.parent.operatorToken.kind === SyntaxKind.EqualsToken + ? node.parent.left + : undefined; + return name && getExpandoInitializer(node.right, isPrototypeAccess(name)) && isEntityNameExpression(name) + && isSameEntityName(name, node.left); } /** @@ -3713,7 +4066,9 @@ export function isDefaultedExpandoInitializer(node: BinaryExpression) { */ export function getNameOfExpando(node: Declaration): DeclarationName | undefined { if (isBinaryExpression(node.parent)) { - const parent = ((node.parent.operatorToken.kind === SyntaxKind.BarBarToken || node.parent.operatorToken.kind === SyntaxKind.QuestionQuestionToken) && isBinaryExpression(node.parent.parent)) ? node.parent.parent : node.parent; + const parent = ((node.parent.operatorToken.kind === SyntaxKind.BarBarToken + || node.parent.operatorToken.kind === SyntaxKind.QuestionQuestionToken) + && isBinaryExpression(node.parent.parent)) ? node.parent.parent : node.parent; if (parent.operatorToken.kind === SyntaxKind.EqualsToken && isIdentifier(parent.left)) { return parent.left; } @@ -3739,12 +4094,12 @@ export function isSameEntityName(name: Expression, initializer: Expression): boo return getTextOfIdentifierOrLiteral(name) === getTextOfIdentifierOrLiteral(initializer); } if ( - isMemberName(name) && isLiteralLikeAccess(initializer) && - (initializer.expression.kind === SyntaxKind.ThisKeyword || - isIdentifier(initializer.expression) && - (initializer.expression.escapedText === "window" || - initializer.expression.escapedText === "self" || - initializer.expression.escapedText === "global")) + isMemberName(name) && isLiteralLikeAccess(initializer) + && (initializer.expression.kind === SyntaxKind.ThisKeyword + || isIdentifier(initializer.expression) + && (initializer.expression.escapedText === "window" + || initializer.expression.escapedText === "self" + || initializer.expression.escapedText === "global")) ) { return isSameEntityName(name, getNameOrArgument(initializer)); } @@ -3774,7 +4129,9 @@ export function isModuleIdentifier(node: Node) { } /** @internal */ -export function isModuleExportsAccessExpression(node: Node): node is LiteralLikeElementAccessExpression & { expression: Identifier; } { +export function isModuleExportsAccessExpression( + node: Node, +): node is LiteralLikeElementAccessExpression & { expression: Identifier; } { return (isPropertyAccessExpression(node) || isLiteralLikeElementAccess(node)) && isModuleIdentifier(node.expression) && getElementOrPropertyAccessName(node) === "exports"; @@ -3785,18 +4142,19 @@ export function isModuleExportsAccessExpression(node: Node): node is LiteralLike /** @internal */ export function getAssignmentDeclarationKind(expr: BinaryExpression | CallExpression): AssignmentDeclarationKind { const special = getAssignmentDeclarationKindWorker(expr); - return special === AssignmentDeclarationKind.Property || isInJSFile(expr) ? special : AssignmentDeclarationKind.None; + return special === AssignmentDeclarationKind.Property || isInJSFile(expr) ? special + : AssignmentDeclarationKind.None; } /** @internal */ export function isBindableObjectDefinePropertyCall(expr: CallExpression): expr is BindableObjectDefinePropertyCall { - return length(expr.arguments) === 3 && - isPropertyAccessExpression(expr.expression) && - isIdentifier(expr.expression.expression) && - idText(expr.expression.expression) === "Object" && - idText(expr.expression.name) === "defineProperty" && - isStringOrNumericLiteralLike(expr.arguments[1]) && - isBindableStaticNameExpression(expr.arguments[0], /*excludeThisKeyword*/ true); + return length(expr.arguments) === 3 + && isPropertyAccessExpression(expr.expression) + && isIdentifier(expr.expression.expression) + && idText(expr.expression.expression) === "Object" + && idText(expr.expression.name) === "defineProperty" + && isStringOrNumericLiteralLike(expr.arguments[1]) + && isBindableStaticNameExpression(expr.arguments[0], /*excludeThisKeyword*/ true); } /** @@ -3822,8 +4180,14 @@ export function isLiteralLikeElementAccess(node: Node): node is LiteralLikeEleme * * @internal */ -export function isBindableStaticAccessExpression(node: Node, excludeThisKeyword?: boolean): node is BindableStaticAccessExpression { - return isPropertyAccessExpression(node) && (!excludeThisKeyword && node.expression.kind === SyntaxKind.ThisKeyword || isIdentifier(node.name) && isBindableStaticNameExpression(node.expression, /*excludeThisKeyword*/ true)) +export function isBindableStaticAccessExpression( + node: Node, + excludeThisKeyword?: boolean, +): node is BindableStaticAccessExpression { + return isPropertyAccessExpression(node) + && (!excludeThisKeyword && node.expression.kind === SyntaxKind.ThisKeyword + || isIdentifier(node.name) + && isBindableStaticNameExpression(node.expression, /*excludeThisKeyword*/ true)) || isBindableStaticElementAccessExpression(node, excludeThisKeyword); } @@ -3832,15 +4196,21 @@ export function isBindableStaticAccessExpression(node: Node, excludeThisKeyword? * * @internal */ -export function isBindableStaticElementAccessExpression(node: Node, excludeThisKeyword?: boolean): node is BindableStaticElementAccessExpression { +export function isBindableStaticElementAccessExpression( + node: Node, + excludeThisKeyword?: boolean, +): node is BindableStaticElementAccessExpression { return isLiteralLikeElementAccess(node) - && ((!excludeThisKeyword && node.expression.kind === SyntaxKind.ThisKeyword) || - isEntityNameExpression(node.expression) || - isBindableStaticAccessExpression(node.expression, /*excludeThisKeyword*/ true)); + && ((!excludeThisKeyword && node.expression.kind === SyntaxKind.ThisKeyword) + || isEntityNameExpression(node.expression) + || isBindableStaticAccessExpression(node.expression, /*excludeThisKeyword*/ true)); } /** @internal */ -export function isBindableStaticNameExpression(node: Node, excludeThisKeyword?: boolean): node is BindableStaticNameExpression { +export function isBindableStaticNameExpression( + node: Node, + excludeThisKeyword?: boolean, +): node is BindableStaticNameExpression { return isEntityNameExpression(node) || isBindableStaticAccessExpression(node, excludeThisKeyword); } @@ -3861,15 +4231,24 @@ function getAssignmentDeclarationKindWorker(expr: BinaryExpression | CallExpress if (isExportsIdentifier(entityName) || isModuleExportsAccessExpression(entityName)) { return AssignmentDeclarationKind.ObjectDefinePropertyExports; } - if (isBindableStaticAccessExpression(entityName) && getElementOrPropertyAccessName(entityName) === "prototype") { + if ( + isBindableStaticAccessExpression(entityName) && getElementOrPropertyAccessName(entityName) === "prototype" + ) { return AssignmentDeclarationKind.ObjectDefinePrototypeProperty; } return AssignmentDeclarationKind.ObjectDefinePropertyValue; } - if (expr.operatorToken.kind !== SyntaxKind.EqualsToken || !isAccessExpression(expr.left) || isVoidZero(getRightMostAssignedExpression(expr))) { + if ( + expr.operatorToken.kind !== SyntaxKind.EqualsToken || !isAccessExpression(expr.left) + || isVoidZero(getRightMostAssignedExpression(expr)) + ) { return AssignmentDeclarationKind.None; } - if (isBindableStaticNameExpression(expr.left.expression, /*excludeThisKeyword*/ true) && getElementOrPropertyAccessName(expr.left) === "prototype" && isObjectLiteralExpression(getInitializerOfBinaryExpression(expr))) { + if ( + isBindableStaticNameExpression(expr.left.expression, /*excludeThisKeyword*/ true) + && getElementOrPropertyAccessName(expr.left) === "prototype" + && isObjectLiteralExpression(getInitializerOfBinaryExpression(expr)) + ) { // F.prototype = { ... } return AssignmentDeclarationKind.Prototype; } @@ -3886,7 +4265,9 @@ function isVoidZero(node: Node) { * * @internal */ -export function getElementOrPropertyAccessArgumentExpressionOrName(node: AccessExpression): Identifier | PrivateIdentifier | StringLiteralLike | NumericLiteral | ElementAccessExpression | undefined { +export function getElementOrPropertyAccessArgumentExpressionOrName( + node: AccessExpression, +): Identifier | PrivateIdentifier | StringLiteralLike | NumericLiteral | ElementAccessExpression | undefined { if (isPropertyAccessExpression(node)) { return node.name; } @@ -3898,7 +4279,9 @@ export function getElementOrPropertyAccessArgumentExpressionOrName(node: AccessE } /** @internal */ -export function getElementOrPropertyAccessName(node: LiteralLikeElementAccessExpression | PropertyAccessExpression): __String; +export function getElementOrPropertyAccessName( + node: LiteralLikeElementAccessExpression | PropertyAccessExpression, +): __String; /** @internal */ export function getElementOrPropertyAccessName(node: AccessExpression): __String | undefined; /** @internal */ @@ -3936,15 +4319,18 @@ export function getAssignmentDeclarationPropertyAccessKind(lhs: AccessExpression } const id = nextToLast.expression; if ( - (id.escapedText === "exports" || - id.escapedText === "module" && getElementOrPropertyAccessName(nextToLast) === "exports") && + (id.escapedText === "exports" + || id.escapedText === "module" && getElementOrPropertyAccessName(nextToLast) === "exports") // ExportsProperty does not support binding with computed names - isBindableStaticAccessExpression(lhs) + && isBindableStaticAccessExpression(lhs) ) { // exports.name = expr OR module.exports.name = expr OR exports["name"] = expr ... return AssignmentDeclarationKind.ExportsProperty; } - if (isBindableStaticNameExpression(lhs, /*excludeThisKeyword*/ true) || (isElementAccessExpression(lhs) && isDynamicName(lhs))) { + if ( + isBindableStaticNameExpression(lhs, /*excludeThisKeyword*/ true) + || (isElementAccessExpression(lhs) && isDynamicName(lhs)) + ) { // F.G...x = expr return AssignmentDeclarationKind.Property; } @@ -3969,25 +4355,28 @@ export interface PrototypePropertyAssignment extends AssignmentExpression isRequireCall(node, /*requireStringLiteralLikeArgument*/ true))?.arguments[0]; + return findAncestor( + node.initializer, + (node): node is RequireOrImportCall => isRequireCall(node, /*requireStringLiteralLikeArgument*/ true), + )?.arguments[0]; case SyntaxKind.ImportDeclaration: return tryCast(node.moduleSpecifier, isStringLiteralLike); case SyntaxKind.ImportEqualsDeclaration: @@ -4040,7 +4435,8 @@ export function tryGetImportFromModuleSpecifier(node: StringLiteralLike): AnyVal case SyntaxKind.ExternalModuleReference: return (node.parent as ExternalModuleReference).parent as AnyValidImportOrReExport; case SyntaxKind.CallExpression: - return isImportCall(node.parent) || isRequireCall(node.parent, /*requireStringLiteralLikeArgument*/ false) ? node.parent as RequireOrImportCall : undefined; + return isImportCall(node.parent) || isRequireCall(node.parent, /*requireStringLiteralLikeArgument*/ false) + ? node.parent as RequireOrImportCall : undefined; case SyntaxKind.LiteralType: Debug.assert(isStringLiteral(node)); return tryCast(node.parent.parent, isImportTypeNode) as ValidImportTypeNode | undefined; @@ -4050,13 +4446,16 @@ export function tryGetImportFromModuleSpecifier(node: StringLiteralLike): AnyVal } /** @internal */ -export function getExternalModuleName(node: AnyImportOrReExport | ImportTypeNode | ImportCall | ModuleDeclaration): Expression | undefined { +export function getExternalModuleName( + node: AnyImportOrReExport | ImportTypeNode | ImportCall | ModuleDeclaration, +): Expression | undefined { switch (node.kind) { case SyntaxKind.ImportDeclaration: case SyntaxKind.ExportDeclaration: return node.moduleSpecifier; case SyntaxKind.ImportEqualsDeclaration: - return node.moduleReference.kind === SyntaxKind.ExternalModuleReference ? node.moduleReference.expression : undefined; + return node.moduleReference.kind === SyntaxKind.ExternalModuleReference ? node.moduleReference.expression + : undefined; case SyntaxKind.ImportType: return isLiteralImportTypeNode(node) ? node.argument.literal : undefined; case SyntaxKind.CallExpression: @@ -4069,7 +4468,9 @@ export function getExternalModuleName(node: AnyImportOrReExport | ImportTypeNode } /** @internal */ -export function getNamespaceDeclarationNode(node: ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration): ImportEqualsDeclaration | NamespaceImport | NamespaceExport | undefined { +export function getNamespaceDeclarationNode( + node: ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration, +): ImportEqualsDeclaration | NamespaceImport | NamespaceExport | undefined { switch (node.kind) { case SyntaxKind.ImportDeclaration: return node.importClause && tryCast(node.importClause.namedBindings, isNamespaceImport); @@ -4088,7 +4489,10 @@ export function isDefaultImport(node: ImportDeclaration | ImportEqualsDeclaratio } /** @internal */ -export function forEachImportClauseDeclaration(node: ImportClause, action: (declaration: ImportClause | NamespaceImport | ImportSpecifier) => T | undefined): T | undefined { +export function forEachImportClauseDeclaration( + node: ImportClause, + action: (declaration: ImportClause | NamespaceImport | ImportSpecifier) => T | undefined, +): T | undefined { if (node.name) { const result = action(node); if (result) return result; @@ -4112,7 +4516,8 @@ export function hasQuestionToken(node: Node) { case SyntaxKind.PropertyAssignment: case SyntaxKind.PropertyDeclaration: case SyntaxKind.PropertySignature: - return (node as ParameterDeclaration | MethodDeclaration | PropertyDeclaration).questionToken !== undefined; + return (node as ParameterDeclaration | MethodDeclaration | PropertyDeclaration).questionToken + !== undefined; } } @@ -4128,28 +4533,32 @@ export function isJSDocConstructSignature(node: Node) { /** @internal */ export function isJSDocTypeAlias(node: Node): node is JSDocTypedefTag | JSDocCallbackTag | JSDocEnumTag { - return node.kind === SyntaxKind.JSDocTypedefTag || node.kind === SyntaxKind.JSDocCallbackTag || node.kind === SyntaxKind.JSDocEnumTag; + return node.kind === SyntaxKind.JSDocTypedefTag || node.kind === SyntaxKind.JSDocCallbackTag + || node.kind === SyntaxKind.JSDocEnumTag; } /** @internal */ -export function isTypeAlias(node: Node): node is JSDocTypedefTag | JSDocCallbackTag | JSDocEnumTag | TypeAliasDeclaration { +export function isTypeAlias( + node: Node, +): node is JSDocTypedefTag | JSDocCallbackTag | JSDocEnumTag | TypeAliasDeclaration { return isJSDocTypeAlias(node) || isTypeAliasDeclaration(node); } function getSourceOfAssignment(node: Node): Node | undefined { - return isExpressionStatement(node) && - isBinaryExpression(node.expression) && - node.expression.operatorToken.kind === SyntaxKind.EqualsToken + return isExpressionStatement(node) + && isBinaryExpression(node.expression) + && node.expression.operatorToken.kind === SyntaxKind.EqualsToken ? getRightMostAssignedExpression(node.expression) : undefined; } function getSourceOfDefaultedAssignment(node: Node): Node | undefined { - return isExpressionStatement(node) && - isBinaryExpression(node.expression) && - getAssignmentDeclarationKind(node.expression) !== AssignmentDeclarationKind.None && - isBinaryExpression(node.expression.right) && - (node.expression.right.operatorToken.kind === SyntaxKind.BarBarToken || node.expression.right.operatorToken.kind === SyntaxKind.QuestionQuestionToken) + return isExpressionStatement(node) + && isBinaryExpression(node.expression) + && getAssignmentDeclarationKind(node.expression) !== AssignmentDeclarationKind.None + && isBinaryExpression(node.expression.right) + && (node.expression.right.operatorToken.kind === SyntaxKind.BarBarToken + || node.expression.right.operatorToken.kind === SyntaxKind.QuestionQuestionToken) ? node.expression.right.right : undefined; } @@ -4173,9 +4582,9 @@ export function getSingleVariableOfVariableStatement(node: Node): VariableDeclar } function getNestedModuleDeclaration(node: Node): Node | undefined { - return isModuleDeclaration(node) && - node.body && - node.body.kind === SyntaxKind.ModuleDeclaration + return isModuleDeclaration(node) + && node.body + && node.body.kind === SyntaxKind.ModuleDeclaration ? node.body : undefined; } @@ -4318,11 +4727,19 @@ export function getJSDocCommentsAndTags(hostNode: Node, noCache?: boolean): read } if (node.kind === SyntaxKind.Parameter) { - result = addRange(result, (noCache ? getJSDocParameterTagsNoCache : getJSDocParameterTags)(node as ParameterDeclaration)); + result = addRange( + result, + (noCache ? getJSDocParameterTagsNoCache : getJSDocParameterTags)(node as ParameterDeclaration), + ); break; } if (node.kind === SyntaxKind.TypeParameter) { - result = addRange(result, (noCache ? getJSDocTypeParameterTagsNoCache : getJSDocTypeParameterTags)(node as TypeParameterDeclaration)); + result = addRange( + result, + (noCache ? getJSDocTypeParameterTagsNoCache : getJSDocTypeParameterTags)( + node as TypeParameterDeclaration, + ), + ); break; } node = getNextJSDocCommentLocation(node); @@ -4354,13 +4771,13 @@ function ownsJSDocTag(hostNode: Node, tag: JSDocTag) { export function getNextJSDocCommentLocation(node: Node) { const parent = node.parent; if ( - parent.kind === SyntaxKind.PropertyAssignment || - parent.kind === SyntaxKind.ExportAssignment || - parent.kind === SyntaxKind.PropertyDeclaration || - parent.kind === SyntaxKind.ExpressionStatement && node.kind === SyntaxKind.PropertyAccessExpression || - parent.kind === SyntaxKind.ReturnStatement || - getNestedModuleDeclaration(parent) || - isBinaryExpression(node) && node.operatorToken.kind === SyntaxKind.EqualsToken + parent.kind === SyntaxKind.PropertyAssignment + || parent.kind === SyntaxKind.ExportAssignment + || parent.kind === SyntaxKind.PropertyDeclaration + || parent.kind === SyntaxKind.ExpressionStatement && node.kind === SyntaxKind.PropertyAccessExpression + || parent.kind === SyntaxKind.ReturnStatement + || getNestedModuleDeclaration(parent) + || isBinaryExpression(node) && node.operatorToken.kind === SyntaxKind.EqualsToken ) { return parent; } @@ -4371,17 +4788,17 @@ export function getNextJSDocCommentLocation(node: Node) { // */ // var x = function(name) { return name.length; } else if ( - parent.parent && - (getSingleVariableOfVariableStatement(parent.parent) === node || - isBinaryExpression(parent) && parent.operatorToken.kind === SyntaxKind.EqualsToken) + parent.parent + && (getSingleVariableOfVariableStatement(parent.parent) === node + || isBinaryExpression(parent) && parent.operatorToken.kind === SyntaxKind.EqualsToken) ) { return parent.parent; } else if ( - parent.parent && parent.parent.parent && - (getSingleVariableOfVariableStatement(parent.parent.parent) || - getSingleInitializerOfVariableStatementOrPropertyDeclaration(parent.parent.parent) === node || - getSourceOfDefaultedAssignment(parent.parent.parent)) + parent.parent && parent.parent.parent + && (getSingleVariableOfVariableStatement(parent.parent.parent) + || getSingleInitializerOfVariableStatementOrPropertyDeclaration(parent.parent.parent) === node + || getSourceOfDefaultedAssignment(parent.parent.parent)) ) { return parent.parent.parent; } @@ -4425,8 +4842,8 @@ export function getEffectiveContainerForJSDocTemplateTag(node: JSDocTemplateTag) export function getHostSignatureFromJSDoc(node: Node): SignatureDeclaration | undefined { const host = getEffectiveJSDocHost(node); if (host) { - return isPropertySignature(host) && host.type && isFunctionLike(host.type) ? host.type : - isFunctionLike(host) ? host : undefined; + return isPropertySignature(host) && host.type && isFunctionLike(host.type) ? host.type + : isFunctionLike(host) ? host : undefined; } return undefined; } @@ -4467,9 +4884,14 @@ export function getJSDocRoot(node: Node): JSDoc | undefined { } /** @internal */ -export function getTypeParameterFromJsDoc(node: TypeParameterDeclaration & { parent: JSDocTemplateTag; }): TypeParameterDeclaration | undefined { +export function getTypeParameterFromJsDoc( + node: TypeParameterDeclaration & { parent: JSDocTemplateTag; }, +): TypeParameterDeclaration | undefined { const name = node.name.escapedText; - const { typeParameters } = node.parent.parent.parent as SignatureDeclaration | InterfaceDeclaration | ClassDeclaration; + const { typeParameters } = node.parent.parent.parent as + | SignatureDeclaration + | InterfaceDeclaration + | ClassDeclaration; return typeParameters && find(typeParameters, p => p.name.escapedText === name); } @@ -4492,16 +4914,20 @@ export function getAssignmentTargetKind(node: Node): AssignmentKind { switch (parent.kind) { case SyntaxKind.BinaryExpression: const binaryOperator = (parent as BinaryExpression).operatorToken.kind; - return isAssignmentOperator(binaryOperator) && (parent as BinaryExpression).left === node ? - binaryOperator === SyntaxKind.EqualsToken || isLogicalOrCoalescingAssignmentOperator(binaryOperator) ? AssignmentKind.Definite : AssignmentKind.Compound : - AssignmentKind.None; + return isAssignmentOperator(binaryOperator) && (parent as BinaryExpression).left === node + ? binaryOperator === SyntaxKind.EqualsToken + || isLogicalOrCoalescingAssignmentOperator(binaryOperator) ? AssignmentKind.Definite + : AssignmentKind.Compound + : AssignmentKind.None; case SyntaxKind.PrefixUnaryExpression: case SyntaxKind.PostfixUnaryExpression: const unaryOperator = (parent as PrefixUnaryExpression | PostfixUnaryExpression).operator; - return unaryOperator === SyntaxKind.PlusPlusToken || unaryOperator === SyntaxKind.MinusMinusToken ? AssignmentKind.Compound : AssignmentKind.None; + return unaryOperator === SyntaxKind.PlusPlusToken || unaryOperator === SyntaxKind.MinusMinusToken + ? AssignmentKind.Compound : AssignmentKind.None; case SyntaxKind.ForInStatement: case SyntaxKind.ForOfStatement: - return (parent as ForInOrOfStatement).initializer === node ? AssignmentKind.Definite : AssignmentKind.None; + return (parent as ForInOrOfStatement).initializer === node ? AssignmentKind.Definite + : AssignmentKind.None; case SyntaxKind.ParenthesizedExpression: case SyntaxKind.ArrayLiteralExpression: case SyntaxKind.SpreadElement: @@ -4598,7 +5024,8 @@ export type ValueSignatureDeclaration = /** @internal */ export function isValueSignatureDeclaration(node: Node): node is ValueSignatureDeclaration { - return isFunctionExpression(node) || isArrowFunction(node) || isMethodOrAccessor(node) || isFunctionDeclaration(node) || isConstructorDeclaration(node); + return isFunctionExpression(node) || isArrowFunction(node) || isMethodOrAccessor(node) + || isFunctionDeclaration(node) || isConstructorDeclaration(node); } function walkUp(node: Node, kind: SyntaxKind) { @@ -4646,9 +5073,9 @@ export function skipParentheses(node: Expression, excludeJSDocTypeAssertions?: b export function skipParentheses(node: Node, excludeJSDocTypeAssertions?: boolean): Node; /** @internal */ export function skipParentheses(node: Node, excludeJSDocTypeAssertions?: boolean): Node { - const flags = excludeJSDocTypeAssertions ? - OuterExpressionKinds.Parentheses | OuterExpressionKinds.ExcludeJSDocTypeAssertion : - OuterExpressionKinds.Parentheses; + const flags = excludeJSDocTypeAssertions + ? OuterExpressionKinds.Parentheses | OuterExpressionKinds.ExcludeJSDocTypeAssertion + : OuterExpressionKinds.Parentheses; return skipOuterExpressions(node, flags); } @@ -4697,10 +5124,10 @@ export function getDeclarationFromName(name: Node): Declaration | undefined { } else { const binExp = parent.parent; - return isBinaryExpression(binExp) && - getAssignmentDeclarationKind(binExp) !== AssignmentDeclarationKind.None && - ((binExp.left as BindableStaticNameExpression).symbol || binExp.symbol) && - getNameOfDeclaration(binExp) === name + return isBinaryExpression(binExp) + && getAssignmentDeclarationKind(binExp) !== AssignmentDeclarationKind.None + && ((binExp.left as BindableStaticNameExpression).symbol || binExp.symbol) + && getNameOfDeclaration(binExp) === name ? binExp : undefined; } @@ -4713,9 +5140,9 @@ export function getDeclarationFromName(name: Node): Declaration | undefined { /** @internal */ export function isLiteralComputedPropertyDeclarationName(node: Node) { - return isStringOrNumericLiteralLike(node) && - node.parent.kind === SyntaxKind.ComputedPropertyName && - isDeclaration(node.parent.parent); + return isStringOrNumericLiteralLike(node) + && node.parent.kind === SyntaxKind.ComputedPropertyName + && isDeclaration(node.parent.parent); } // Return true if the given identifier is classified as an IdentifierName @@ -4770,21 +5197,22 @@ export function isIdentifierName(node: Identifier): boolean { /** @internal */ export function isAliasSymbolDeclaration(node: Node): boolean { if ( - node.kind === SyntaxKind.ImportEqualsDeclaration || - node.kind === SyntaxKind.NamespaceExportDeclaration || - node.kind === SyntaxKind.ImportClause && !!(node as ImportClause).name || - node.kind === SyntaxKind.NamespaceImport || - node.kind === SyntaxKind.NamespaceExport || - node.kind === SyntaxKind.ImportSpecifier || - node.kind === SyntaxKind.ExportSpecifier || - node.kind === SyntaxKind.ExportAssignment && exportAssignmentIsAlias(node as ExportAssignment) + node.kind === SyntaxKind.ImportEqualsDeclaration + || node.kind === SyntaxKind.NamespaceExportDeclaration + || node.kind === SyntaxKind.ImportClause && !!(node as ImportClause).name + || node.kind === SyntaxKind.NamespaceImport + || node.kind === SyntaxKind.NamespaceExport + || node.kind === SyntaxKind.ImportSpecifier + || node.kind === SyntaxKind.ExportSpecifier + || node.kind === SyntaxKind.ExportAssignment && exportAssignmentIsAlias(node as ExportAssignment) ) { return true; } return isInJSFile(node) && ( - isBinaryExpression(node) && getAssignmentDeclarationKind(node) === AssignmentDeclarationKind.ModuleExports && exportAssignmentIsAlias(node) || - isPropertyAccessExpression(node) + isBinaryExpression(node) && getAssignmentDeclarationKind(node) === AssignmentDeclarationKind.ModuleExports + && exportAssignmentIsAlias(node) + || isPropertyAccessExpression(node) && isBinaryExpression(node.parent) && node.parent.left === node && node.parent.operatorToken.kind === SyntaxKind.EqualsToken @@ -4829,9 +5257,12 @@ export function getExportAssignmentExpression(node: ExportAssignment | BinaryExp } /** @internal */ -export function getPropertyAssignmentAliasLikeExpression(node: PropertyAssignment | ShorthandPropertyAssignment | PropertyAccessExpression): Expression { - return node.kind === SyntaxKind.ShorthandPropertyAssignment ? node.name : node.kind === SyntaxKind.PropertyAssignment ? node.initializer : - (node.parent as BinaryExpression).right; +export function getPropertyAssignmentAliasLikeExpression( + node: PropertyAssignment | ShorthandPropertyAssignment | PropertyAccessExpression, +): Expression { + return node.kind === SyntaxKind.ShorthandPropertyAssignment ? node.name + : node.kind === SyntaxKind.PropertyAssignment ? node.initializer + : (node.parent as BinaryExpression).right; } /** @internal */ @@ -4854,7 +5285,9 @@ export function getClassExtendsHeritageElement(node: ClassLikeDeclaration | Inte } /** @internal */ -export function getEffectiveImplementsTypeNodes(node: ClassLikeDeclaration): undefined | readonly ExpressionWithTypeArguments[] { +export function getEffectiveImplementsTypeNodes( + node: ClassLikeDeclaration, +): undefined | readonly ExpressionWithTypeArguments[] { if (isInJSFile(node)) { return getJSDocImplementsTags(node).map(n => n.class); } @@ -4870,9 +5303,11 @@ export function getEffectiveImplementsTypeNodes(node: ClassLikeDeclaration): und * @internal */ export function getAllSuperTypeNodes(node: Node): readonly TypeNode[] { - return isInterfaceDeclaration(node) ? getInterfaceBaseTypeNodes(node) || emptyArray : - isClassLike(node) ? concatenate(singleElementArray(getEffectiveBaseTypeNode(node)), getEffectiveImplementsTypeNodes(node)) || emptyArray : - emptyArray; + return isInterfaceDeclaration(node) ? getInterfaceBaseTypeNodes(node) || emptyArray + : isClassLike(node) + ? concatenate(singleElementArray(getEffectiveBaseTypeNode(node)), getEffectiveImplementsTypeNodes(node)) + || emptyArray + : emptyArray; } /** @internal */ @@ -5018,7 +5453,9 @@ export function isStringOrNumericLiteralLike(node: Node): node is StringLiteralL /** @internal */ export function isSignedNumericLiteral(node: Node): node is PrefixUnaryExpression & { operand: NumericLiteral; } { - return isPrefixUnaryExpression(node) && (node.operator === SyntaxKind.PlusToken || node.operator === SyntaxKind.MinusToken) && isNumericLiteral(node.operand); + return isPrefixUnaryExpression(node) + && (node.operator === SyntaxKind.PlusToken || node.operator === SyntaxKind.MinusToken) + && isNumericLiteral(node.operand); } /** @@ -5031,7 +5468,9 @@ export function isSignedNumericLiteral(node: Node): node is PrefixUnaryExpressio * * @internal */ -export function hasDynamicName(declaration: Declaration): declaration is DynamicNamedDeclaration | DynamicNamedBinaryExpression { +export function hasDynamicName( + declaration: Declaration, +): declaration is DynamicNamedDeclaration | DynamicNamedBinaryExpression { const name = getNameOfDeclaration(declaration); return !!name && isDynamicName(name); } @@ -5042,8 +5481,8 @@ export function isDynamicName(name: DeclarationName): boolean { return false; } const expr = isElementAccessExpression(name) ? skipParentheses(name.argumentExpression) : name.expression; - return !isStringOrNumericLiteralLike(expr) && - !isSignedNumericLiteral(expr); + return !isStringOrNumericLiteralLike(expr) + && !isSignedNumericLiteral(expr); } /** @internal */ @@ -5093,7 +5532,8 @@ export function getTextOfIdentifierOrLiteral(node: PropertyNameLiteral | Private /** @internal */ export function getEscapedTextOfIdentifierOrLiteral(node: PropertyNameLiteral): __String { - return isMemberName(node) ? node.escapedText : isJsxNamespacedName(node) ? getEscapedTextOfJsxNamespacedName(node) : escapeLeadingUnderscores(node.text); + return isMemberName(node) ? node.escapedText + : isJsxNamespacedName(node) ? getEscapedTextOfJsxNamespacedName(node) : escapeLeadingUnderscores(node.text); } /** @internal */ @@ -5134,8 +5574,8 @@ export function isESSymbolIdentifier(node: Node): boolean { * @internal */ export function isProtoSetter(node: PropertyName) { - return isIdentifier(node) ? idText(node) === "__proto__" : - isStringLiteral(node) && node.text === "__proto__"; + return isIdentifier(node) ? idText(node) === "__proto__" + : isStringLiteral(node) && node.text === "__proto__"; } /** @internal */ @@ -5150,7 +5590,10 @@ export type AnonymousFunctionDefinition = * @see https://tc39.es/ecma262/#sec-isanonymousfunctiondefinition * @internal */ -export function isAnonymousFunctionDefinition(node: Expression, cb?: (node: AnonymousFunctionDefinition) => boolean): node is WrappedExpression { +export function isAnonymousFunctionDefinition( + node: Expression, + cb?: (node: AnonymousFunctionDefinition) => boolean, +): node is WrappedExpression { node = skipOuterExpressions(node); switch (node.kind) { case SyntaxKind.ClassExpression: @@ -5176,10 +5619,21 @@ export type NamedEvaluationSource = | PropertyAssignment & { readonly name: Identifier; } | ShorthandPropertyAssignment & { readonly objectAssignmentInitializer: Expression; } | VariableDeclaration & { readonly name: Identifier; readonly initializer: Expression; } - | ParameterDeclaration & { readonly name: Identifier; readonly initializer: Expression; readonly dotDotDotToken: undefined; } - | BindingElement & { readonly name: Identifier; readonly initializer: Expression; readonly dotDotDotToken: undefined; } + | ParameterDeclaration & { + readonly name: Identifier; + readonly initializer: Expression; + readonly dotDotDotToken: undefined; + } + | BindingElement & { + readonly name: Identifier; + readonly initializer: Expression; + readonly dotDotDotToken: undefined; + } | PropertyDeclaration & { readonly initializer: Expression; } - | AssignmentExpression & { readonly left: Identifier; } + | AssignmentExpression< + EqualsToken | AmpersandAmpersandEqualsToken | BarBarEqualsToken | QuestionQuestionEqualsToken + > + & { readonly left: Identifier; } | ExportAssignment; /** @@ -5196,9 +5650,11 @@ export function isNamedEvaluationSource(node: Node): node is NamedEvaluationSour case SyntaxKind.VariableDeclaration: return isIdentifier((node as VariableDeclaration).name) && !!(node as VariableDeclaration).initializer; case SyntaxKind.Parameter: - return isIdentifier((node as ParameterDeclaration).name) && !!(node as VariableDeclaration).initializer && !(node as BindingElement).dotDotDotToken; + return isIdentifier((node as ParameterDeclaration).name) && !!(node as VariableDeclaration).initializer + && !(node as BindingElement).dotDotDotToken; case SyntaxKind.BindingElement: - return isIdentifier((node as BindingElement).name) && !!(node as VariableDeclaration).initializer && !(node as BindingElement).dotDotDotToken; + return isIdentifier((node as BindingElement).name) && !!(node as VariableDeclaration).initializer + && !(node as BindingElement).dotDotDotToken; case SyntaxKind.PropertyDeclaration: return !!(node as PropertyDeclaration).initializer; case SyntaxKind.BinaryExpression: @@ -5218,18 +5674,43 @@ export function isNamedEvaluationSource(node: Node): node is NamedEvaluationSour /** @internal */ export type NamedEvaluation = - | PropertyAssignment & { readonly name: Identifier; readonly initializer: WrappedExpression; } - | ShorthandPropertyAssignment & { readonly objectAssignmentInitializer: WrappedExpression; } - | VariableDeclaration & { readonly name: Identifier; readonly initializer: WrappedExpression; } - | ParameterDeclaration & { readonly name: Identifier; readonly dotDotDotToken: undefined; readonly initializer: WrappedExpression; } - | BindingElement & { readonly name: Identifier; readonly dotDotDotToken: undefined; readonly initializer: WrappedExpression; } + | PropertyAssignment & { + readonly name: Identifier; + readonly initializer: WrappedExpression; + } + | ShorthandPropertyAssignment & { + readonly objectAssignmentInitializer: WrappedExpression; + } + | VariableDeclaration & { + readonly name: Identifier; + readonly initializer: WrappedExpression; + } + | ParameterDeclaration & { + readonly name: Identifier; + readonly dotDotDotToken: undefined; + readonly initializer: WrappedExpression; + } + | BindingElement & { + readonly name: Identifier; + readonly dotDotDotToken: undefined; + readonly initializer: WrappedExpression; + } | PropertyDeclaration & { readonly initializer: WrappedExpression; } - | AssignmentExpression & { readonly left: Identifier; readonly right: WrappedExpression; } - | AssignmentExpression & { readonly left: Identifier; readonly right: WrappedExpression; } + | AssignmentExpression & { + readonly left: Identifier; + readonly right: WrappedExpression; + } + | AssignmentExpression & { + readonly left: Identifier; + readonly right: WrappedExpression; + } | ExportAssignment & { readonly expression: WrappedExpression; }; /** @internal */ -export function isNamedEvaluation(node: Node, cb?: (node: AnonymousFunctionDefinition) => boolean): node is NamedEvaluation { +export function isNamedEvaluation( + node: Node, + cb?: (node: AnonymousFunctionDefinition) => boolean, +): node is NamedEvaluation { if (!isNamedEvaluationSource(node)) return false; switch (node.kind) { case SyntaxKind.PropertyAssignment: @@ -5313,7 +5794,8 @@ export const enum Associativity { /** @internal */ export function getExpressionAssociativity(expression: Expression) { const operator = getOperator(expression); - const hasArguments = expression.kind === SyntaxKind.NewExpression && (expression as NewExpression).arguments !== undefined; + const hasArguments = expression.kind === SyntaxKind.NewExpression + && (expression as NewExpression).arguments !== undefined; return getOperatorAssociativity(expression.kind, operator, hasArguments); } @@ -5360,7 +5842,8 @@ export function getOperatorAssociativity(kind: SyntaxKind, operator: SyntaxKind, /** @internal */ export function getExpressionPrecedence(expression: Expression) { const operator = getOperator(expression); - const hasArguments = expression.kind === SyntaxKind.NewExpression && (expression as NewExpression).arguments !== undefined; + const hasArguments = expression.kind === SyntaxKind.NewExpression + && (expression as NewExpression).arguments !== undefined; return getOperatorPrecedence(expression.kind, operator, hasArguments); } @@ -5369,7 +5852,9 @@ export function getOperator(expression: Expression): SyntaxKind { if (expression.kind === SyntaxKind.BinaryExpression) { return (expression as BinaryExpression).operatorToken.kind; } - else if (expression.kind === SyntaxKind.PrefixUnaryExpression || expression.kind === SyntaxKind.PostfixUnaryExpression) { + else if ( + expression.kind === SyntaxKind.PrefixUnaryExpression || expression.kind === SyntaxKind.PostfixUnaryExpression + ) { return (expression as PrefixUnaryExpression | PostfixUnaryExpression).operator; } else { @@ -5874,22 +6359,28 @@ function getReplacement(c: string, offset: number, input: string) { * * @internal */ -export function escapeString(s: string, quoteChar?: CharacterCodes.doubleQuote | CharacterCodes.singleQuote | CharacterCodes.backtick): string { - const escapedCharsRegExp = quoteChar === CharacterCodes.backtick ? backtickQuoteEscapedCharsRegExp : - quoteChar === CharacterCodes.singleQuote ? singleQuoteEscapedCharsRegExp : - doubleQuoteEscapedCharsRegExp; +export function escapeString( + s: string, + quoteChar?: CharacterCodes.doubleQuote | CharacterCodes.singleQuote | CharacterCodes.backtick, +): string { + const escapedCharsRegExp = quoteChar === CharacterCodes.backtick ? backtickQuoteEscapedCharsRegExp + : quoteChar === CharacterCodes.singleQuote ? singleQuoteEscapedCharsRegExp + : doubleQuoteEscapedCharsRegExp; return s.replace(escapedCharsRegExp, getReplacement); } const nonAsciiCharacters = /[^\u0000-\u007F]/g; /** @internal */ -export function escapeNonAsciiString(s: string, quoteChar?: CharacterCodes.doubleQuote | CharacterCodes.singleQuote | CharacterCodes.backtick): string { +export function escapeNonAsciiString( + s: string, + quoteChar?: CharacterCodes.doubleQuote | CharacterCodes.singleQuote | CharacterCodes.backtick, +): string { s = escapeString(s, quoteChar); // Replace non-ASCII characters with '\uNNNN' escapes if any exist. // Otherwise just return the original string. - return nonAsciiCharacters.test(s) ? - s.replace(nonAsciiCharacters, c => encodeUtf16EscapeSequence(c.charCodeAt(0))) : - s; + return nonAsciiCharacters.test(s) + ? s.replace(nonAsciiCharacters, c => encodeUtf16EscapeSequence(c.charCodeAt(0))) + : s; } // This consists of the first 19 unprintable ASCII characters, JSX canonical escapes, lineSeparator, @@ -5916,9 +6407,12 @@ function getJsxAttributeStringReplacement(c: string) { } /** @internal */ -export function escapeJsxAttributeString(s: string, quoteChar?: CharacterCodes.doubleQuote | CharacterCodes.singleQuote) { - const escapedCharsRegExp = quoteChar === CharacterCodes.singleQuote ? jsxSingleQuoteEscapedCharsRegExp : - jsxDoubleQuoteEscapedCharsRegExp; +export function escapeJsxAttributeString( + s: string, + quoteChar?: CharacterCodes.doubleQuote | CharacterCodes.singleQuote, +) { + const escapedCharsRegExp = quoteChar === CharacterCodes.singleQuote ? jsxSingleQuoteEscapedCharsRegExp + : jsxDoubleQuoteEscapedCharsRegExp; return s.replace(escapedCharsRegExp, getJsxAttributeStringReplacement); } @@ -5938,9 +6432,9 @@ export function stripQuotes(name: string) { } function isQuoteOrBacktick(charCode: number) { - return charCode === CharacterCodes.singleQuote || - charCode === CharacterCodes.doubleQuote || - charCode === CharacterCodes.backtick; + return charCode === CharacterCodes.singleQuote + || charCode === CharacterCodes.doubleQuote + || charCode === CharacterCodes.backtick; } /** @internal */ @@ -6178,8 +6672,13 @@ export interface ResolveModuleNameResolutionHost { } /** @internal */ -export function getResolvedExternalModuleName(host: ResolveModuleNameResolutionHost, file: SourceFile, referenceFile?: SourceFile): string { - return file.moduleName || getExternalModuleNameFromPath(host, file.fileName, referenceFile && referenceFile.fileName); +export function getResolvedExternalModuleName( + host: ResolveModuleNameResolutionHost, + file: SourceFile, + referenceFile?: SourceFile, +): string { + return file.moduleName + || getExternalModuleNameFromPath(host, file.fileName, referenceFile && referenceFile.fileName); } function getCanonicalAbsolutePath(host: ResolveModuleNameResolutionHost, path: string) { @@ -6187,7 +6686,11 @@ function getCanonicalAbsolutePath(host: ResolveModuleNameResolutionHost, path: s } /** @internal */ -export function getExternalModuleNameFromDeclaration(host: ResolveModuleNameResolutionHost, resolver: EmitResolver, declaration: ImportEqualsDeclaration | ImportDeclaration | ExportDeclaration | ModuleDeclaration | ImportTypeNode): string | undefined { +export function getExternalModuleNameFromDeclaration( + host: ResolveModuleNameResolutionHost, + resolver: EmitResolver, + declaration: ImportEqualsDeclaration | ImportDeclaration | ExportDeclaration | ModuleDeclaration | ImportTypeNode, +): string | undefined { const file = resolver.getExternalModuleFileFromDeclaration(declaration); if (!file || file.isDeclarationFile) { return undefined; @@ -6195,8 +6698,10 @@ export function getExternalModuleNameFromDeclaration(host: ResolveModuleNameReso // If the declaration already uses a non-relative name, and is outside the common source directory, continue to use it const specifier = getExternalModuleName(declaration); if ( - specifier && isStringLiteralLike(specifier) && !pathIsRelative(specifier.text) && - getCanonicalAbsolutePath(host, file.path).indexOf(getCanonicalAbsolutePath(host, ensureTrailingDirectorySeparator(host.getCommonSourceDirectory()))) === -1 + specifier && isStringLiteralLike(specifier) && !pathIsRelative(specifier.text) + && getCanonicalAbsolutePath(host, file.path).indexOf( + getCanonicalAbsolutePath(host, ensureTrailingDirectorySeparator(host.getCommonSourceDirectory())), + ) === -1 ) { return undefined; } @@ -6208,11 +6713,25 @@ export function getExternalModuleNameFromDeclaration(host: ResolveModuleNameReso * * @internal */ -export function getExternalModuleNameFromPath(host: ResolveModuleNameResolutionHost, fileName: string, referencePath?: string): string { +export function getExternalModuleNameFromPath( + host: ResolveModuleNameResolutionHost, + fileName: string, + referencePath?: string, +): string { const getCanonicalFileName = (f: string) => host.getCanonicalFileName(f); - const dir = toPath(referencePath ? getDirectoryPath(referencePath) : host.getCommonSourceDirectory(), host.getCurrentDirectory(), getCanonicalFileName); + const dir = toPath( + referencePath ? getDirectoryPath(referencePath) : host.getCommonSourceDirectory(), + host.getCurrentDirectory(), + getCanonicalFileName, + ); const filePath = getNormalizedAbsolutePath(fileName, host.getCurrentDirectory()); - const relativePath = getRelativePathToDirectoryOrUrl(dir, filePath, dir, getCanonicalFileName, /*isAbsolutePathAnUrl*/ false); + const relativePath = getRelativePathToDirectoryOrUrl( + dir, + filePath, + dir, + getCanonicalFileName, + /*isAbsolutePathAnUrl*/ false, + ); const extensionless = removeFileExtension(relativePath); return referencePath ? ensurePathIsNonModuleName(extensionless) : extensionless; } @@ -6222,7 +6741,9 @@ export function getOwnEmitOutputFilePath(fileName: string, host: EmitHost, exten const compilerOptions = host.getCompilerOptions(); let emitOutputFilePathWithoutExtension: string; if (compilerOptions.outDir) { - emitOutputFilePathWithoutExtension = removeFileExtension(getSourceFilePathInNewDir(fileName, host, compilerOptions.outDir)); + emitOutputFilePathWithoutExtension = removeFileExtension( + getSourceFilePathInNewDir(fileName, host, compilerOptions.outDir), + ); } else { emitOutputFilePathWithoutExtension = removeFileExtension(fileName); @@ -6233,15 +6754,33 @@ export function getOwnEmitOutputFilePath(fileName: string, host: EmitHost, exten /** @internal */ export function getDeclarationEmitOutputFilePath(fileName: string, host: EmitHost) { - return getDeclarationEmitOutputFilePathWorker(fileName, host.getCompilerOptions(), host.getCurrentDirectory(), host.getCommonSourceDirectory(), f => host.getCanonicalFileName(f)); + return getDeclarationEmitOutputFilePathWorker( + fileName, + host.getCompilerOptions(), + host.getCurrentDirectory(), + host.getCommonSourceDirectory(), + f => host.getCanonicalFileName(f), + ); } /** @internal */ -export function getDeclarationEmitOutputFilePathWorker(fileName: string, options: CompilerOptions, currentDirectory: string, commonSourceDirectory: string, getCanonicalFileName: GetCanonicalFileName): string { +export function getDeclarationEmitOutputFilePathWorker( + fileName: string, + options: CompilerOptions, + currentDirectory: string, + commonSourceDirectory: string, + getCanonicalFileName: GetCanonicalFileName, +): string { const outputDir = options.declarationDir || options.outDir; // Prefer declaration folder if specified const path = outputDir - ? getSourceFilePathInNewDirWorker(fileName, outputDir, currentDirectory, commonSourceDirectory, getCanonicalFileName) + ? getSourceFilePathInNewDirWorker( + fileName, + outputDir, + currentDirectory, + commonSourceDirectory, + getCanonicalFileName, + ) : fileName; const declarationExtension = getDeclarationEmitExtensionForPath(path); return removeFileExtension(path) + declarationExtension; @@ -6249,10 +6788,10 @@ export function getDeclarationEmitOutputFilePathWorker(fileName: string, options /** @internal */ export function getDeclarationEmitExtensionForPath(path: string) { - return fileExtensionIsOneOf(path, [Extension.Mjs, Extension.Mts]) ? Extension.Dmts : - fileExtensionIsOneOf(path, [Extension.Cjs, Extension.Cts]) ? Extension.Dcts : - fileExtensionIsOneOf(path, [Extension.Json]) ? `.d.json.ts` : // Drive-by redefinition of json declaration file output name so if it's ever enabled, it behaves well - Extension.Dts; + return fileExtensionIsOneOf(path, [Extension.Mjs, Extension.Mts]) ? Extension.Dmts + : fileExtensionIsOneOf(path, [Extension.Cjs, Extension.Cts]) ? Extension.Dcts + : fileExtensionIsOneOf(path, [Extension.Json]) ? `.d.json.ts` // Drive-by redefinition of json declaration file output name so if it's ever enabled, it behaves well + : Extension.Dts; } /** @@ -6261,10 +6800,10 @@ export function getDeclarationEmitExtensionForPath(path: string) { * @internal */ export function getPossibleOriginalInputExtensionForExtension(path: string) { - return fileExtensionIsOneOf(path, [Extension.Dmts, Extension.Mjs, Extension.Mts]) ? [Extension.Mts, Extension.Mjs] : - fileExtensionIsOneOf(path, [Extension.Dcts, Extension.Cjs, Extension.Cts]) ? [Extension.Cts, Extension.Cjs] : - fileExtensionIsOneOf(path, [`.d.json.ts`]) ? [Extension.Json] : - [Extension.Tsx, Extension.Ts, Extension.Jsx, Extension.Js]; + return fileExtensionIsOneOf(path, [Extension.Dmts, Extension.Mjs, Extension.Mts]) ? [Extension.Mts, Extension.Mjs] + : fileExtensionIsOneOf(path, [Extension.Dcts, Extension.Cjs, Extension.Cts]) ? [Extension.Cts, Extension.Cjs] + : fileExtensionIsOneOf(path, [`.d.json.ts`]) ? [Extension.Json] + : [Extension.Tsx, Extension.Ts, Extension.Jsx, Extension.Js]; } /** @internal */ @@ -6279,7 +6818,11 @@ export function outFile(options: CompilerOptions) { */ export function getPathsBasePath(options: CompilerOptions, host: { getCurrentDirectory?(): string; }) { if (!options.paths) return undefined; - return options.baseUrl ?? Debug.checkDefined(options.pathsBasePath || host.getCurrentDirectory?.(), "Encountered 'paths' without a 'baseUrl', config file, or host 'getCurrentDirectory'."); + return options.baseUrl + ?? Debug.checkDefined( + options.pathsBasePath || host.getCurrentDirectory?.(), + "Encountered 'paths' without a 'baseUrl', config file, or host 'getCurrentDirectory'.", + ); } /** @internal */ @@ -6302,17 +6845,22 @@ export interface EmitFileNames { * * @internal */ -export function getSourceFilesToEmit(host: EmitHost, targetSourceFile?: SourceFile, forceDtsEmit?: boolean): readonly SourceFile[] { +export function getSourceFilesToEmit( + host: EmitHost, + targetSourceFile?: SourceFile, + forceDtsEmit?: boolean, +): readonly SourceFile[] { const options = host.getCompilerOptions(); if (outFile(options)) { const moduleKind = getEmitModuleKind(options); - const moduleEmitEnabled = options.emitDeclarationOnly || moduleKind === ModuleKind.AMD || moduleKind === ModuleKind.System; + const moduleEmitEnabled = options.emitDeclarationOnly || moduleKind === ModuleKind.AMD + || moduleKind === ModuleKind.System; // Can emit only sources that are not declaration file and are either non module code or module with --module or --target es6 specified return filter( host.getSourceFiles(), sourceFile => - (moduleEmitEnabled || !isExternalModule(sourceFile)) && - sourceFileMayBeEmitted(sourceFile, host, forceDtsEmit), + (moduleEmitEnabled || !isExternalModule(sourceFile)) + && sourceFileMayBeEmitted(sourceFile, host, forceDtsEmit), ); } else { @@ -6329,38 +6877,66 @@ export function getSourceFilesToEmit(host: EmitHost, targetSourceFile?: SourceFi * * @internal */ -export function sourceFileMayBeEmitted(sourceFile: SourceFile, host: SourceFileMayBeEmittedHost, forceDtsEmit?: boolean) { +export function sourceFileMayBeEmitted( + sourceFile: SourceFile, + host: SourceFileMayBeEmittedHost, + forceDtsEmit?: boolean, +) { const options = host.getCompilerOptions(); - return !(options.noEmitForJsFiles && isSourceFileJS(sourceFile)) && - !sourceFile.isDeclarationFile && - !host.isSourceFileFromExternalLibrary(sourceFile) && - (forceDtsEmit || ( - !(isJsonSourceFile(sourceFile) && host.getResolvedProjectReferenceToRedirect(sourceFile.fileName)) && - !host.isSourceOfProjectReferenceRedirect(sourceFile.fileName) + return !(options.noEmitForJsFiles && isSourceFileJS(sourceFile)) + && !sourceFile.isDeclarationFile + && !host.isSourceFileFromExternalLibrary(sourceFile) + && (forceDtsEmit || ( + !(isJsonSourceFile(sourceFile) && host.getResolvedProjectReferenceToRedirect(sourceFile.fileName)) + && !host.isSourceOfProjectReferenceRedirect(sourceFile.fileName) )); } /** @internal */ export function getSourceFilePathInNewDir(fileName: string, host: EmitHost, newDirPath: string): string { - return getSourceFilePathInNewDirWorker(fileName, newDirPath, host.getCurrentDirectory(), host.getCommonSourceDirectory(), f => host.getCanonicalFileName(f)); + return getSourceFilePathInNewDirWorker( + fileName, + newDirPath, + host.getCurrentDirectory(), + host.getCommonSourceDirectory(), + f => host.getCanonicalFileName(f), + ); } /** @internal */ -export function getSourceFilePathInNewDirWorker(fileName: string, newDirPath: string, currentDirectory: string, commonSourceDirectory: string, getCanonicalFileName: GetCanonicalFileName): string { +export function getSourceFilePathInNewDirWorker( + fileName: string, + newDirPath: string, + currentDirectory: string, + commonSourceDirectory: string, + getCanonicalFileName: GetCanonicalFileName, +): string { let sourceFilePath = getNormalizedAbsolutePath(fileName, currentDirectory); - const isSourceFileInCommonSourceDirectory = getCanonicalFileName(sourceFilePath).indexOf(getCanonicalFileName(commonSourceDirectory)) === 0; - sourceFilePath = isSourceFileInCommonSourceDirectory ? sourceFilePath.substring(commonSourceDirectory.length) : sourceFilePath; + const isSourceFileInCommonSourceDirectory = + getCanonicalFileName(sourceFilePath).indexOf(getCanonicalFileName(commonSourceDirectory)) === 0; + sourceFilePath = isSourceFileInCommonSourceDirectory ? sourceFilePath.substring(commonSourceDirectory.length) + : sourceFilePath; return combinePaths(newDirPath, sourceFilePath); } /** @internal */ -export function writeFile(host: { writeFile: WriteFileCallback; }, diagnostics: DiagnosticCollection, fileName: string, text: string, writeByteOrderMark: boolean, sourceFiles?: readonly SourceFile[], data?: WriteFileCallbackData) { +export function writeFile( + host: { writeFile: WriteFileCallback; }, + diagnostics: DiagnosticCollection, + fileName: string, + text: string, + writeByteOrderMark: boolean, + sourceFiles?: readonly SourceFile[], + data?: WriteFileCallbackData, +) { host.writeFile( fileName, text, writeByteOrderMark, hostErrorMessage => { - diagnostics.add(createCompilerDiagnostic(Diagnostics.Could_not_write_file_0_Colon_1, fileName, hostErrorMessage)); + diagnostics.add( + createCompilerDiagnostic(Diagnostics.Could_not_write_file_0_Colon_1, fileName, hostErrorMessage), + ); }, sourceFiles, data, @@ -6411,8 +6987,14 @@ export function getLineOfLocalPositionFromLineMap(lineMap: readonly number[], po } /** @internal */ -export function getFirstConstructorWithBody(node: ClassLikeDeclaration): ConstructorDeclaration & { body: FunctionBody; } | undefined { - return find(node.members, (member): member is ConstructorDeclaration & { body: FunctionBody; } => isConstructorDeclaration(member) && nodeIsPresent(member.body)); +export function getFirstConstructorWithBody( + node: ClassLikeDeclaration, +): ConstructorDeclaration & { body: FunctionBody; } | undefined { + return find( + node.members, + (member): member is ConstructorDeclaration & { body: FunctionBody; } => + isConstructorDeclaration(member) && nodeIsPresent(member.body), + ); } /** @internal */ @@ -6461,7 +7043,8 @@ export function isInTypeQuery(node: Node): boolean { // The expression is restricted to a single identifier or a sequence of identifiers separated by periods return !!findAncestor( node, - n => n.kind === SyntaxKind.TypeQuery ? true : n.kind === SyntaxKind.Identifier || n.kind === SyntaxKind.QualifiedName ? false : "quit", + n => n.kind === SyntaxKind.TypeQuery ? true + : n.kind === SyntaxKind.Identifier || n.kind === SyntaxKind.QualifiedName ? false : "quit", ); } @@ -6484,7 +7067,10 @@ export function identifierIsThisKeyword(id: Identifier): boolean { } /** @internal */ -export function getAllAccessorDeclarations(declarations: readonly Declaration[], accessor: AccessorDeclaration): AllAccessorDeclarations { +export function getAllAccessorDeclarations( + declarations: readonly Declaration[], + accessor: AccessorDeclaration, +): AllAccessorDeclarations { // TODO: GH#18217 let firstAccessor!: AccessorDeclaration; let secondAccessor!: AccessorDeclaration; @@ -6563,19 +7149,23 @@ export function getTypeAnnotationNode(node: Node): TypeNode | undefined { * @internal */ export function getEffectiveReturnTypeNode(node: SignatureDeclaration | JSDocSignature): TypeNode | undefined { - return isJSDocSignature(node) ? - node.type && node.type.typeExpression && node.type.typeExpression.type : - node.type || (isInJSFile(node) ? getJSDocReturnType(node) : undefined); + return isJSDocSignature(node) + ? node.type && node.type.typeExpression && node.type.typeExpression.type + : node.type || (isInJSFile(node) ? getJSDocReturnType(node) : undefined); } /** @internal */ -export function getJSDocTypeParameterDeclarations(node: DeclarationWithTypeParameters): readonly TypeParameterDeclaration[] { +export function getJSDocTypeParameterDeclarations( + node: DeclarationWithTypeParameters, +): readonly TypeParameterDeclaration[] { return flatMap(getJSDocTags(node), tag => isNonTypeAliasTemplate(tag) ? tag.typeParameters : undefined); } /** template tags are only available when a typedef isn't already using them */ function isNonTypeAliasTemplate(tag: JSDocTag): tag is JSDocTemplateTag { - return isJSDocTemplateTag(tag) && !(tag.parent.kind === SyntaxKind.JSDoc && (tag.parent.tags!.some(isJSDocTypeAlias) || tag.parent.tags!.some(isJSDocOverloadTag))); + return isJSDocTemplateTag(tag) + && !(tag.parent.kind === SyntaxKind.JSDoc + && (tag.parent.tags!.some(isJSDocTypeAlias) || tag.parent.tags!.some(isJSDocOverloadTag))); } /** @@ -6590,27 +7180,43 @@ export function getEffectiveSetAccessorTypeAnnotationNode(node: SetAccessorDecla } /** @internal */ -export function emitNewLineBeforeLeadingComments(lineMap: readonly number[], writer: EmitTextWriter, node: TextRange, leadingComments: readonly CommentRange[] | undefined) { +export function emitNewLineBeforeLeadingComments( + lineMap: readonly number[], + writer: EmitTextWriter, + node: TextRange, + leadingComments: readonly CommentRange[] | undefined, +) { emitNewLineBeforeLeadingCommentsOfPosition(lineMap, writer, node.pos, leadingComments); } /** @internal */ -export function emitNewLineBeforeLeadingCommentsOfPosition(lineMap: readonly number[], writer: EmitTextWriter, pos: number, leadingComments: readonly CommentRange[] | undefined) { +export function emitNewLineBeforeLeadingCommentsOfPosition( + lineMap: readonly number[], + writer: EmitTextWriter, + pos: number, + leadingComments: readonly CommentRange[] | undefined, +) { // If the leading comments start on different line than the start of node, write new line if ( - leadingComments && leadingComments.length && pos !== leadingComments[0].pos && - getLineOfLocalPositionFromLineMap(lineMap, pos) !== getLineOfLocalPositionFromLineMap(lineMap, leadingComments[0].pos) + leadingComments && leadingComments.length && pos !== leadingComments[0].pos + && getLineOfLocalPositionFromLineMap(lineMap, pos) + !== getLineOfLocalPositionFromLineMap(lineMap, leadingComments[0].pos) ) { writer.writeLine(); } } /** @internal */ -export function emitNewLineBeforeLeadingCommentOfPosition(lineMap: readonly number[], writer: EmitTextWriter, pos: number, commentPos: number) { +export function emitNewLineBeforeLeadingCommentOfPosition( + lineMap: readonly number[], + writer: EmitTextWriter, + pos: number, + commentPos: number, +) { // If the leading comments start on different line than the start of node, write new line if ( - pos !== commentPos && - getLineOfLocalPositionFromLineMap(lineMap, pos) !== getLineOfLocalPositionFromLineMap(lineMap, commentPos) + pos !== commentPos + && getLineOfLocalPositionFromLineMap(lineMap, pos) !== getLineOfLocalPositionFromLineMap(lineMap, commentPos) ) { writer.writeLine(); } @@ -6625,7 +7231,14 @@ export function emitComments( leadingSeparator: boolean, trailingSeparator: boolean, newLine: string, - writeComment: (text: string, lineMap: readonly number[], writer: EmitTextWriter, commentPos: number, commentEnd: number, newLine: string) => void, + writeComment: ( + text: string, + lineMap: readonly number[], + writer: EmitTextWriter, + commentPos: number, + commentEnd: number, + newLine: string, + ) => void, ) { if (comments && comments.length > 0) { if (leadingSeparator) { @@ -6660,7 +7273,22 @@ export function emitComments( * * @internal */ -export function emitDetachedComments(text: string, lineMap: readonly number[], writer: EmitTextWriter, writeComment: (text: string, lineMap: readonly number[], writer: EmitTextWriter, commentPos: number, commentEnd: number, newLine: string) => void, node: TextRange, newLine: string, removeComments: boolean) { +export function emitDetachedComments( + text: string, + lineMap: readonly number[], + writer: EmitTextWriter, + writeComment: ( + text: string, + lineMap: readonly number[], + writer: EmitTextWriter, + commentPos: number, + commentEnd: number, + newLine: string, + ) => void, + node: TextRange, + newLine: string, + removeComments: boolean, +) { let leadingComments: CommentRange[] | undefined; let currentDetachedCommentInfo: { nodePos: number; detachedCommentEndPos: number; } | undefined; if (removeComments) { @@ -6708,7 +7336,16 @@ export function emitDetachedComments(text: string, lineMap: readonly number[], w if (nodeLine >= lastCommentLine + 2) { // Valid detachedComments emitNewLineBeforeLeadingComments(lineMap, writer, node, leadingComments); - emitComments(text, lineMap, writer, detachedComments, /*leadingSeparator*/ false, /*trailingSeparator*/ true, newLine, writeComment); + emitComments( + text, + lineMap, + writer, + detachedComments, + /*leadingSeparator*/ false, + /*trailingSeparator*/ true, + newLine, + writeComment, + ); currentDetachedCommentInfo = { nodePos: node.pos, detachedCommentEndPos: last(detachedComments).end }; } } @@ -6722,7 +7359,14 @@ export function emitDetachedComments(text: string, lineMap: readonly number[], w } /** @internal */ -export function writeCommentRange(text: string, lineMap: readonly number[], writer: EmitTextWriter, commentPos: number, commentEnd: number, newLine: string) { +export function writeCommentRange( + text: string, + lineMap: readonly number[], + writer: EmitTextWriter, + commentPos: number, + commentEnd: number, + newLine: string, +) { if (text.charCodeAt(commentPos + 1) === CharacterCodes.asterisk) { const firstCommentLineAndCharacter = computeLineAndCharacterOfPosition(lineMap, commentPos); const lineCount = lineMap.length; @@ -6735,7 +7379,11 @@ export function writeCommentRange(text: string, lineMap: readonly number[], writ if (pos !== commentPos) { // If we are not emitting first line, we need to write the spaces to adjust the alignment if (firstCommentLineIndent === undefined) { - firstCommentLineIndent = calculateIndent(text, lineMap[firstCommentLineAndCharacter.line], commentPos); + firstCommentLineIndent = calculateIndent( + text, + lineMap[firstCommentLineAndCharacter.line], + commentPos, + ); } // These are number of spaces writer is going to write at current indent @@ -6755,10 +7403,13 @@ export function writeCommentRange(text: string, lineMap: readonly number[], writ // More right indented comment */ --4 = 8 - 4 + 11 // class c { } // } - const spacesToEmit = currentWriterIndentSpacing - firstCommentLineIndent + calculateIndent(text, pos, nextLineStart); + const spacesToEmit = currentWriterIndentSpacing - firstCommentLineIndent + + calculateIndent(text, pos, nextLineStart); if (spacesToEmit > 0) { let numberOfSingleSpacesToEmit = spacesToEmit % getIndentSize(); - const indentSizeSpaceString = getIndentString((spacesToEmit - numberOfSingleSpacesToEmit) / getIndentSize()); + const indentSizeSpaceString = getIndentString( + (spacesToEmit - numberOfSingleSpacesToEmit) / getIndentSize(), + ); // Write indent size string ( in eg 1: = "", 2: "" , 3: string with 8 spaces 4: string with 12 spaces writer.rawWrite(indentSizeSpaceString); @@ -6787,7 +7438,14 @@ export function writeCommentRange(text: string, lineMap: readonly number[], writ } } -function writeTrimmedCurrentLine(text: string, commentEnd: number, writer: EmitTextWriter, newLine: string, pos: number, nextLineStart: number) { +function writeTrimmedCurrentLine( + text: string, + commentEnd: number, + writer: EmitTextWriter, + newLine: string, + pos: number, + nextLineStart: number, +) { const end = Math.min(commentEnd, nextLineStart - 1); const currentLineText = trimString(text.substring(pos, end)); if (currentLineText) { @@ -6899,7 +7557,10 @@ function getModifierFlagsWorker(node: Node, includeJSDoc: boolean, alwaysInclude node.modifierFlagsCache = getSyntacticModifierFlagsNoCache(node) | ModifierFlags.HasComputedFlags; } - if (includeJSDoc && !(node.modifierFlagsCache & ModifierFlags.HasComputedJSDocModifiers) && (alwaysIncludeJSDoc || isInJSFile(node)) && node.parent) { + if ( + includeJSDoc && !(node.modifierFlagsCache & ModifierFlags.HasComputedJSDocModifiers) + && (alwaysIncludeJSDoc || isInJSFile(node)) && node.parent + ) { node.modifierFlagsCache |= getJSDocModifierFlagsNoCache(node) | ModifierFlags.HasComputedJSDocModifiers; } @@ -6969,7 +7630,10 @@ export function getEffectiveModifierFlagsNoCache(node: Node): ModifierFlags { */ export function getSyntacticModifierFlagsNoCache(node: Node): ModifierFlags { let flags = canHaveModifiers(node) ? modifiersToFlags(node.modifiers) : ModifierFlags.None; - if (node.flags & NodeFlags.NestedNamespace || node.kind === SyntaxKind.Identifier && node.flags & NodeFlags.IdentifierIsInJSDocNamespace) { + if ( + node.flags & NodeFlags.NestedNamespace + || node.kind === SyntaxKind.Identifier && node.flags & NodeFlags.IdentifierIsInJSDocNamespace + ) { flags |= ModifierFlags.Export; } return flags; @@ -7035,19 +7699,25 @@ export function isLogicalOperator(token: SyntaxKind): boolean { } /** @internal */ -export function isLogicalOrCoalescingAssignmentOperator(token: SyntaxKind): token is LogicalOrCoalescingAssignmentOperator { +export function isLogicalOrCoalescingAssignmentOperator( + token: SyntaxKind, +): token is LogicalOrCoalescingAssignmentOperator { return token === SyntaxKind.BarBarEqualsToken || token === SyntaxKind.AmpersandAmpersandEqualsToken || token === SyntaxKind.QuestionQuestionEqualsToken; } /** @internal */ -export function isLogicalOrCoalescingAssignmentExpression(expr: Node): expr is AssignmentExpression> { +export function isLogicalOrCoalescingAssignmentExpression( + expr: Node, +): expr is AssignmentExpression> { return isBinaryExpression(expr) && isLogicalOrCoalescingAssignmentOperator(expr.operatorToken.kind); } /** @internal */ -export function isLogicalOrCoalescingBinaryOperator(token: SyntaxKind): token is LogicalOperator | SyntaxKind.QuestionQuestionToken { +export function isLogicalOrCoalescingBinaryOperator( + token: SyntaxKind, +): token is LogicalOperator | SyntaxKind.QuestionQuestionToken { return isBinaryLogicalOperator(token) || token === SyntaxKind.QuestionQuestionToken; } @@ -7077,7 +7747,9 @@ export interface ClassImplementingOrExtendingExpressionWithTypeArguments { readonly isImplements: boolean; } /** @internal */ -export function tryGetClassImplementingOrExtendingExpressionWithTypeArguments(node: Node): ClassImplementingOrExtendingExpressionWithTypeArguments | undefined { +export function tryGetClassImplementingOrExtendingExpressionWithTypeArguments( + node: Node, +): ClassImplementingOrExtendingExpressionWithTypeArguments | undefined { if (isExpressionWithTypeArguments(node)) { if (isHeritageClause(node.parent) && isClassLike(node.parent.parent)) { return { class: node.parent.parent, isImplements: node.parent.token === SyntaxKind.ImplementsKeyword }; @@ -7093,11 +7765,20 @@ export function tryGetClassImplementingOrExtendingExpressionWithTypeArguments(no } /** @internal */ -export function isAssignmentExpression(node: Node, excludeCompoundAssignment: true): node is AssignmentExpression; +export function isAssignmentExpression( + node: Node, + excludeCompoundAssignment: true, +): node is AssignmentExpression; /** @internal */ -export function isAssignmentExpression(node: Node, excludeCompoundAssignment?: false): node is AssignmentExpression; +export function isAssignmentExpression( + node: Node, + excludeCompoundAssignment?: false, +): node is AssignmentExpression; /** @internal */ -export function isAssignmentExpression(node: Node, excludeCompoundAssignment?: boolean): node is AssignmentExpression { +export function isAssignmentExpression( + node: Node, + excludeCompoundAssignment?: boolean, +): node is AssignmentExpression { return isBinaryExpression(node) && (excludeCompoundAssignment ? node.operatorToken.kind === SyntaxKind.EqualsToken @@ -7156,8 +7837,10 @@ export function isDottedName(node: Expression): boolean { || node.kind === SyntaxKind.ThisKeyword || node.kind === SyntaxKind.SuperKeyword || node.kind === SyntaxKind.MetaProperty - || node.kind === SyntaxKind.PropertyAccessExpression && isDottedName((node as PropertyAccessExpression).expression) - || node.kind === SyntaxKind.ParenthesizedExpression && isDottedName((node as ParenthesizedExpression).expression); + || node.kind === SyntaxKind.PropertyAccessExpression + && isDottedName((node as PropertyAccessExpression).expression) + || node.kind === SyntaxKind.ParenthesizedExpression + && isDottedName((node as ParenthesizedExpression).expression); } /** @internal */ @@ -7195,9 +7878,10 @@ export function isPrototypeAccess(node: Node): node is BindableStaticAccessExpre /** @internal */ export function isRightSideOfQualifiedNameOrPropertyAccess(node: Node) { - return (node.parent.kind === SyntaxKind.QualifiedName && (node.parent as QualifiedName).right === node) || - (node.parent.kind === SyntaxKind.PropertyAccessExpression && (node.parent as PropertyAccessExpression).name === node) || - (node.parent.kind === SyntaxKind.MetaProperty && (node.parent as MetaProperty).name === node); + return (node.parent.kind === SyntaxKind.QualifiedName && (node.parent as QualifiedName).right === node) + || (node.parent.kind === SyntaxKind.PropertyAccessExpression + && (node.parent as PropertyAccessExpression).name === node) + || (node.parent.kind === SyntaxKind.MetaProperty && (node.parent as MetaProperty).name === node); } /** @internal */ @@ -7215,14 +7899,14 @@ export function isRightSideOfQualifiedNameOrPropertyAccessOrJSDocMemberName(node /** @internal */ export function isEmptyObjectLiteral(expression: Node): boolean { - return expression.kind === SyntaxKind.ObjectLiteralExpression && - (expression as ObjectLiteralExpression).properties.length === 0; + return expression.kind === SyntaxKind.ObjectLiteralExpression + && (expression as ObjectLiteralExpression).properties.length === 0; } /** @internal */ export function isEmptyArrayLiteral(expression: Node): boolean { - return expression.kind === SyntaxKind.ArrayLiteralExpression && - (expression as ArrayLiteralExpression).elements.length === 0; + return expression.kind === SyntaxKind.ArrayLiteralExpression + && (expression as ArrayLiteralExpression).elements.length === 0; } /** @internal */ @@ -7235,7 +7919,8 @@ export function getLocalSymbolForExportDefault(symbol: Symbol) { } function isExportDefaultSymbol(symbol: Symbol): boolean { - return symbol && length(symbol.declarations) > 0 && hasSyntacticModifier(symbol.declarations![0], ModifierFlags.Default); + return symbol && length(symbol.declarations) > 0 + && hasSyntacticModifier(symbol.declarations![0], ModifierFlags.Default); } /** @@ -7316,7 +8001,8 @@ export function convertToBase64(input: string): string { } // Write to the output - result += base64Digits.charAt(byte1) + base64Digits.charAt(byte2) + base64Digits.charAt(byte3) + base64Digits.charAt(byte4); + result += base64Digits.charAt(byte1) + base64Digits.charAt(byte2) + base64Digits.charAt(byte3) + + base64Digits.charAt(byte4); i += 3; } @@ -7403,7 +8089,10 @@ export function base64decode(host: { base64decode?(input: string): string; } | u } /** @internal */ -export function readJsonOrUndefined(path: string, hostOrText: { readFile(fileName: string): string | undefined; } | string): object | undefined { +export function readJsonOrUndefined( + path: string, + hostOrText: { readFile(fileName: string): string | undefined; } | string, +): object | undefined { const jsonText = isString(hostOrText) ? hostOrText : hostOrText.readFile(path); if (!jsonText) return undefined; // gracefully handle if readFile fails or returns not JSON @@ -7417,7 +8106,10 @@ export function readJson(path: string, host: { readFile(fileName: string): strin } /** @internal */ -export function directoryProbablyExists(directoryName: string, host: { directoryExists?: (directoryName: string) => boolean; }): boolean { +export function directoryProbablyExists( + directoryName: string, + host: { directoryExists?: (directoryName: string) => boolean; }, +): boolean { // if host does not support 'directoryExists' assume that directory will exist return !host.directoryExists || host.directoryExists(directoryName); } @@ -7544,16 +8236,29 @@ export function rangeEndPositionsAreOnSameLine(range1: TextRange, range2: TextRa /** @internal */ export function rangeStartIsOnSameLineAsRangeEnd(range1: TextRange, range2: TextRange, sourceFile: SourceFile) { - return positionsAreOnSameLine(getStartPositionOfRange(range1, sourceFile, /*includeComments*/ false), range2.end, sourceFile); + return positionsAreOnSameLine( + getStartPositionOfRange(range1, sourceFile, /*includeComments*/ false), + range2.end, + sourceFile, + ); } /** @internal */ export function rangeEndIsOnSameLineAsRangeStart(range1: TextRange, range2: TextRange, sourceFile: SourceFile) { - return positionsAreOnSameLine(range1.end, getStartPositionOfRange(range2, sourceFile, /*includeComments*/ false), sourceFile); + return positionsAreOnSameLine( + range1.end, + getStartPositionOfRange(range2, sourceFile, /*includeComments*/ false), + sourceFile, + ); } /** @internal */ -export function getLinesBetweenRangeEndAndRangeStart(range1: TextRange, range2: TextRange, sourceFile: SourceFile, includeSecondRangeComments: boolean) { +export function getLinesBetweenRangeEndAndRangeStart( + range1: TextRange, + range2: TextRange, + sourceFile: SourceFile, + includeSecondRangeComments: boolean, +) { const range2Start = getStartPositionOfRange(range2, sourceFile, includeSecondRangeComments); return getLinesBetweenPositions(sourceFile, range1.end, range2Start); } @@ -7575,18 +8280,29 @@ export function positionsAreOnSameLine(pos1: number, pos2: number, sourceFile: S /** @internal */ export function getStartPositionOfRange(range: TextRange, sourceFile: SourceFile, includeComments: boolean) { - return positionIsSynthesized(range.pos) ? -1 : skipTrivia(sourceFile.text, range.pos, /*stopAfterLineBreak*/ false, includeComments); + return positionIsSynthesized(range.pos) ? -1 + : skipTrivia(sourceFile.text, range.pos, /*stopAfterLineBreak*/ false, includeComments); } /** @internal */ -export function getLinesBetweenPositionAndPrecedingNonWhitespaceCharacter(pos: number, stopPos: number, sourceFile: SourceFile, includeComments?: boolean) { +export function getLinesBetweenPositionAndPrecedingNonWhitespaceCharacter( + pos: number, + stopPos: number, + sourceFile: SourceFile, + includeComments?: boolean, +) { const startPos = skipTrivia(sourceFile.text, pos, /*stopAfterLineBreak*/ false, includeComments); const prevPos = getPreviousNonWhitespacePosition(startPos, stopPos, sourceFile); return getLinesBetweenPositions(sourceFile, prevPos ?? stopPos, startPos); } /** @internal */ -export function getLinesBetweenPositionAndNextNonWhitespaceCharacter(pos: number, stopPos: number, sourceFile: SourceFile, includeComments?: boolean) { +export function getLinesBetweenPositionAndNextNonWhitespaceCharacter( + pos: number, + stopPos: number, + sourceFile: SourceFile, + includeComments?: boolean, +) { const nextPos = skipTrivia(sourceFile.text, pos, /*stopAfterLineBreak*/ false, includeComments); return getLinesBetweenPositions(sourceFile, pos, Math.min(stopPos, nextPos)); } @@ -7647,16 +8363,17 @@ export function getCheckFlags(symbol: Symbol): CheckFlags { export function getDeclarationModifierFlagsFromSymbol(s: Symbol, isWrite = false): ModifierFlags { if (s.valueDeclaration) { const declaration = (isWrite && s.declarations && find(s.declarations, isSetAccessorDeclaration)) - || (s.flags & SymbolFlags.GetAccessor && find(s.declarations, isGetAccessorDeclaration)) || s.valueDeclaration; + || (s.flags & SymbolFlags.GetAccessor && find(s.declarations, isGetAccessorDeclaration)) + || s.valueDeclaration; const flags = getCombinedModifierFlags(declaration); return s.parent && s.parent.flags & SymbolFlags.Class ? flags : flags & ~ModifierFlags.AccessibilityModifier; } if (getCheckFlags(s) & CheckFlags.Synthetic) { // NOTE: potentially unchecked cast to TransientSymbol const checkFlags = (s as TransientSymbol).links.checkFlags; - const accessModifier = checkFlags & CheckFlags.ContainsPrivate ? ModifierFlags.Private : - checkFlags & CheckFlags.ContainsPublic ? ModifierFlags.Public : - ModifierFlags.Protected; + const accessModifier = checkFlags & CheckFlags.ContainsPrivate ? ModifierFlags.Private + : checkFlags & CheckFlags.ContainsPublic ? ModifierFlags.Public + : ModifierFlags.Protected; const staticModifier = checkFlags & CheckFlags.ContainsStatic ? ModifierFlags.Static : 0; return accessModifier | staticModifier; } @@ -7707,11 +8424,12 @@ function accessKind(node: Node): AccessKind { case SyntaxKind.PostfixUnaryExpression: case SyntaxKind.PrefixUnaryExpression: const { operator } = parent as PrefixUnaryExpression | PostfixUnaryExpression; - return operator === SyntaxKind.PlusPlusToken || operator === SyntaxKind.MinusMinusToken ? AccessKind.ReadWrite : AccessKind.Read; + return operator === SyntaxKind.PlusPlusToken || operator === SyntaxKind.MinusMinusToken + ? AccessKind.ReadWrite : AccessKind.Read; case SyntaxKind.BinaryExpression: const { left, operatorToken } = parent as BinaryExpression; - return left === node && isAssignmentOperator(operatorToken.kind) ? - operatorToken.kind === SyntaxKind.EqualsToken ? AccessKind.Write : AccessKind.ReadWrite + return left === node && isAssignmentOperator(operatorToken.kind) + ? operatorToken.kind === SyntaxKind.EqualsToken ? AccessKind.Write : AccessKind.ReadWrite : AccessKind.Read; case SyntaxKind.PropertyAccessExpression: return (parent as PropertyAccessExpression).name !== node ? AccessKind.Read : accessKind(parent); @@ -7722,7 +8440,8 @@ function accessKind(node: Node): AccessKind { } case SyntaxKind.ShorthandPropertyAssignment: // Assume it's the local variable being accessed, since we don't check public properties for --noUnusedLocals. - return node === (parent as ShorthandPropertyAssignment).objectAssignmentInitializer ? AccessKind.Read : accessKind(parent.parent); + return node === (parent as ShorthandPropertyAssignment).objectAssignmentInitializer ? AccessKind.Read + : accessKind(parent.parent); case SyntaxKind.ArrayLiteralExpression: return accessKind(parent); default: @@ -7768,7 +8487,10 @@ export function compareDataObjects(dst: any, src: any): boolean { * * @internal */ -export function clearMap(map: { forEach: Map["forEach"]; clear: Map["clear"]; }, onDeleteValue: (valueInMap: T, key: K) => void) { +export function clearMap( + map: { forEach: Map["forEach"]; clear: Map["clear"]; }, + onDeleteValue: (valueInMap: T, key: K) => void, +) { // Remove all map.forEach(onDeleteValue); map.clear(); @@ -7863,7 +8585,8 @@ export function forSomeAncestorDirectory(directory: string, callback: (directory /** @internal */ export function isUMDExportSymbol(symbol: Symbol | undefined): boolean { - return !!symbol && !!symbol.declarations && !!symbol.declarations[0] && isNamespaceExportDeclaration(symbol.declarations[0]); + return !!symbol && !!symbol.declarations && !!symbol.declarations[0] + && isNamespaceExportDeclaration(symbol.declarations[0]); } /** @internal */ @@ -7974,7 +8697,10 @@ export function getLeftmostAccessExpression(expr: Expression): Expression { } /** @internal */ -export function forEachNameInAccessChainWalkingLeft(name: MemberName | StringLiteralLike, action: (name: MemberName | StringLiteralLike) => T | undefined): T | undefined { +export function forEachNameInAccessChainWalkingLeft( + name: MemberName | StringLiteralLike, + action: (name: MemberName | StringLiteralLike) => T | undefined, +): T | undefined { if (isAccessExpression(name.parent) && isRightSideOfAccessExpression(name)) { return walkAccessExpression(name.parent); } @@ -8042,7 +8768,14 @@ export function getLeftmostExpression(node: Expression, stopAtCallExpressions: b case SyntaxKind.NonNullExpression: case SyntaxKind.PartiallyEmittedExpression: case SyntaxKind.SatisfiesExpression: - node = (node as CallExpression | PropertyAccessExpression | ElementAccessExpression | AsExpression | NonNullExpression | PartiallyEmittedExpression | SatisfiesExpression).expression; + node = (node as + | CallExpression + | PropertyAccessExpression + | ElementAccessExpression + | AsExpression + | NonNullExpression + | PartiallyEmittedExpression + | SatisfiesExpression).expression; continue; } @@ -8055,12 +8788,20 @@ export interface ObjectAllocator { getNodeConstructor(): new (kind: SyntaxKind, pos: number, end: number) => Node; getTokenConstructor(): new (kind: TKind, pos: number, end: number) => Token; getIdentifierConstructor(): new (kind: SyntaxKind.Identifier, pos: number, end: number) => Identifier; - getPrivateIdentifierConstructor(): new (kind: SyntaxKind.PrivateIdentifier, pos: number, end: number) => PrivateIdentifier; + getPrivateIdentifierConstructor(): new ( + kind: SyntaxKind.PrivateIdentifier, + pos: number, + end: number, + ) => PrivateIdentifier; getSourceFileConstructor(): new (kind: SyntaxKind.SourceFile, pos: number, end: number) => SourceFile; getSymbolConstructor(): new (flags: SymbolFlags, name: __String) => Symbol; getTypeConstructor(): new (checker: TypeChecker, flags: TypeFlags) => Type; getSignatureConstructor(): new (checker: TypeChecker, flags: SignatureFlags) => Signature; - getSourceMapSourceConstructor(): new (fileName: string, text: string, skipTrivia?: (pos: number) => number) => SourceMapSource; + getSourceMapSourceConstructor(): new ( + fileName: string, + text: string, + skipTrivia?: (pos: number) => number, + ) => SourceMapSource; } function Symbol(this: Symbol, flags: SymbolFlags, name: __String) { @@ -8193,9 +8934,20 @@ export function getLocaleSpecificMessage(message: DiagnosticMessage) { } /** @internal */ -export function createDetachedDiagnostic(fileName: string, start: number, length: number, message: DiagnosticMessage, ...args: DiagnosticArguments): DiagnosticWithDetachedLocation; +export function createDetachedDiagnostic( + fileName: string, + start: number, + length: number, + message: DiagnosticMessage, + ...args: DiagnosticArguments +): DiagnosticWithDetachedLocation; /** @internal */ -export function createDetachedDiagnostic(fileName: string, start: number, length: number, message: DiagnosticMessage): DiagnosticWithDetachedLocation { +export function createDetachedDiagnostic( + fileName: string, + start: number, + length: number, + message: DiagnosticMessage, +): DiagnosticWithDetachedLocation { assertDiagnosticLocation(/*file*/ undefined, start, length); let text = getLocaleSpecificMessage(message); @@ -8216,7 +8968,9 @@ export function createDetachedDiagnostic(fileName: string, start: number, length }; } -function isDiagnosticWithDetachedLocation(diagnostic: DiagnosticRelatedInformation | DiagnosticWithDetachedLocation): diagnostic is DiagnosticWithDetachedLocation { +function isDiagnosticWithDetachedLocation( + diagnostic: DiagnosticRelatedInformation | DiagnosticWithDetachedLocation, +): diagnostic is DiagnosticWithDetachedLocation { return diagnostic.file === undefined && diagnostic.start !== undefined && diagnostic.length !== undefined @@ -8255,7 +9009,10 @@ function attachFileToDiagnostic(diagnostic: DiagnosticWithDetachedLocation, file } /** @internal */ -export function attachFileToDiagnostics(diagnostics: DiagnosticWithDetachedLocation[], file: SourceFile): DiagnosticWithLocation[] { +export function attachFileToDiagnostics( + diagnostics: DiagnosticWithDetachedLocation[], + file: SourceFile, +): DiagnosticWithLocation[] { const diagnosticsWithLocation: DiagnosticWithLocation[] = []; for (const diagnostic of diagnostics) { diagnosticsWithLocation.push(attachFileToDiagnostic(diagnostic, file)); @@ -8264,9 +9021,20 @@ export function attachFileToDiagnostics(diagnostics: DiagnosticWithDetachedLocat } /** @internal */ -export function createFileDiagnostic(file: SourceFile, start: number, length: number, message: DiagnosticMessage, ...args: DiagnosticArguments): DiagnosticWithLocation; +export function createFileDiagnostic( + file: SourceFile, + start: number, + length: number, + message: DiagnosticMessage, + ...args: DiagnosticArguments +): DiagnosticWithLocation; /** @internal */ -export function createFileDiagnostic(file: SourceFile, start: number, length: number, message: DiagnosticMessage): DiagnosticWithLocation { +export function createFileDiagnostic( + file: SourceFile, + start: number, + length: number, + message: DiagnosticMessage, +): DiagnosticWithLocation { assertDiagnosticLocation(file, start, length); let text = getLocaleSpecificMessage(message); @@ -8325,7 +9093,10 @@ export function createCompilerDiagnostic(message: DiagnosticMessage): Diagnostic } /** @internal */ -export function createCompilerDiagnosticFromMessageChain(chain: DiagnosticMessageChain, relatedInformation?: DiagnosticRelatedInformation[]): Diagnostic { +export function createCompilerDiagnosticFromMessageChain( + chain: DiagnosticMessageChain, + relatedInformation?: DiagnosticRelatedInformation[], +): Diagnostic { return { file: undefined, start: undefined, @@ -8339,9 +9110,16 @@ export function createCompilerDiagnosticFromMessageChain(chain: DiagnosticMessag } /** @internal */ -export function chainDiagnosticMessages(details: DiagnosticMessageChain | DiagnosticMessageChain[] | undefined, message: DiagnosticMessage, ...args: DiagnosticArguments): DiagnosticMessageChain; +export function chainDiagnosticMessages( + details: DiagnosticMessageChain | DiagnosticMessageChain[] | undefined, + message: DiagnosticMessage, + ...args: DiagnosticArguments +): DiagnosticMessageChain; /** @internal */ -export function chainDiagnosticMessages(details: DiagnosticMessageChain | DiagnosticMessageChain[] | undefined, message: DiagnosticMessage): DiagnosticMessageChain { +export function chainDiagnosticMessages( + details: DiagnosticMessageChain | DiagnosticMessageChain[] | undefined, + message: DiagnosticMessage, +): DiagnosticMessageChain { let text = getLocaleSpecificMessage(message); if (arguments.length > 2) { @@ -8357,7 +9135,10 @@ export function chainDiagnosticMessages(details: DiagnosticMessageChain | Diagno } /** @internal */ -export function concatenateDiagnosticMessageChains(headChain: DiagnosticMessageChain, tailChain: DiagnosticMessageChain): void { +export function concatenateDiagnosticMessageChains( + headChain: DiagnosticMessageChain, + tailChain: DiagnosticMessageChain, +): void { let lastChain = headChain; while (lastChain.next) { lastChain = lastChain.next[0]; @@ -8372,19 +9153,19 @@ function getDiagnosticFilePath(diagnostic: Diagnostic): string | undefined { /** @internal */ export function compareDiagnostics(d1: Diagnostic, d2: Diagnostic): Comparison { - return compareDiagnosticsSkipRelatedInformation(d1, d2) || - compareRelatedInformation(d1, d2) || - Comparison.EqualTo; + return compareDiagnosticsSkipRelatedInformation(d1, d2) + || compareRelatedInformation(d1, d2) + || Comparison.EqualTo; } /** @internal */ export function compareDiagnosticsSkipRelatedInformation(d1: Diagnostic, d2: Diagnostic): Comparison { - return compareStringsCaseSensitive(getDiagnosticFilePath(d1), getDiagnosticFilePath(d2)) || - compareValues(d1.start, d2.start) || - compareValues(d1.length, d2.length) || - compareValues(d1.code, d2.code) || - compareMessageText(d1.messageText, d2.messageText) || - Comparison.EqualTo; + return compareStringsCaseSensitive(getDiagnosticFilePath(d1), getDiagnosticFilePath(d2)) + || compareValues(d1.start, d2.start) + || compareValues(d1.length, d2.length) + || compareValues(d1.code, d2.code) + || compareMessageText(d1.messageText, d2.messageText) + || Comparison.EqualTo; } function compareRelatedInformation(d1: Diagnostic, d2: Diagnostic): Comparison { @@ -8392,10 +9173,11 @@ function compareRelatedInformation(d1: Diagnostic, d2: Diagnostic): Comparison { return Comparison.EqualTo; } if (d1.relatedInformation && d2.relatedInformation) { - return compareValues(d1.relatedInformation.length, d2.relatedInformation.length) || forEach(d1.relatedInformation, (d1i, index) => { - const d2i = d2.relatedInformation![index]; - return compareDiagnostics(d1i, d2i); // EqualTo is 0, so falsy, and will cause the next item to be compared - }) || Comparison.EqualTo; + return compareValues(d1.relatedInformation.length, d2.relatedInformation.length) + || forEach(d1.relatedInformation, (d1i, index) => { + const d2i = d2.relatedInformation![index]; + return compareDiagnostics(d1i, d2i); // EqualTo is 0, so falsy, and will cause the next item to be compared + }) || Comparison.EqualTo; } return d1.relatedInformation ? Comparison.LessThan : Comparison.GreaterThan; } @@ -8442,7 +9224,8 @@ function compareMessageText(t1: string | DiagnosticMessageChain, t2: string | Di /** @internal */ export function getLanguageVariant(scriptKind: ScriptKind) { // .tsx and .jsx files are treated as jsx language variant. - return scriptKind === ScriptKind.TSX || scriptKind === ScriptKind.JSX || scriptKind === ScriptKind.JS || scriptKind === ScriptKind.JSON ? LanguageVariant.JSX : LanguageVariant.Standard; + return scriptKind === ScriptKind.TSX || scriptKind === ScriptKind.JSX || scriptKind === ScriptKind.JS + || scriptKind === ScriptKind.JSON ? LanguageVariant.JSX : LanguageVariant.Standard; } /** @@ -8469,7 +9252,9 @@ function isFileForcedToBeModuleByFormat(file: SourceFile): true | undefined { // Excludes declaration files - they still require an explicit `export {}` or the like // for back compat purposes. The only non-declaration files _not_ forced to be a module are `.js` files // that aren't esm-mode (meaning not in a `type: module` scope). - return (file.impliedNodeFormat === ModuleKind.ESNext || (fileExtensionIsOneOf(file.fileName, [Extension.Cjs, Extension.Cts, Extension.Mjs, Extension.Mts]))) && !file.isDeclarationFile ? true : undefined; + return (file.impliedNodeFormat === ModuleKind.ESNext + || (fileExtensionIsOneOf(file.fileName, [Extension.Cjs, Extension.Cts, Extension.Mjs, Extension.Mts]))) + && !file.isDeclarationFile ? true : undefined; } /** @internal */ @@ -8479,7 +9264,8 @@ export function getSetExternalModuleIndicator(options: CompilerOptions): (file: case ModuleDetectionKind.Force: // All non-declaration files are modules, declaration files still do the usual isFileProbablyExternalModule return (file: SourceFile) => { - file.externalModuleIndicator = isFileProbablyExternalModule(file) || !file.isDeclarationFile || undefined; + file.externalModuleIndicator = isFileProbablyExternalModule(file) || !file.isDeclarationFile + || undefined; }; case ModuleDetectionKind.Legacy: // Files are modules if they have imports, exports, or import.meta @@ -8502,18 +9288,22 @@ export function getSetExternalModuleIndicator(options: CompilerOptions): (file: } /** @internal */ -export function getEmitScriptTarget(compilerOptions: { module?: CompilerOptions["module"]; target?: CompilerOptions["target"]; }): ScriptTarget { - return compilerOptions.target ?? - ((compilerOptions.module === ModuleKind.Node16 && ScriptTarget.ES2022) || - (compilerOptions.module === ModuleKind.NodeNext && ScriptTarget.ESNext) || - ScriptTarget.ES5); +export function getEmitScriptTarget( + compilerOptions: { module?: CompilerOptions["module"]; target?: CompilerOptions["target"]; }, +): ScriptTarget { + return compilerOptions.target + ?? ((compilerOptions.module === ModuleKind.Node16 && ScriptTarget.ES2022) + || (compilerOptions.module === ModuleKind.NodeNext && ScriptTarget.ESNext) + || ScriptTarget.ES5); } /** @internal */ -export function getEmitModuleKind(compilerOptions: { module?: CompilerOptions["module"]; target?: CompilerOptions["target"]; }) { - return typeof compilerOptions.module === "number" ? - compilerOptions.module : - getEmitScriptTarget(compilerOptions) >= ScriptTarget.ES2015 ? ModuleKind.ES2015 : ModuleKind.CommonJS; +export function getEmitModuleKind( + compilerOptions: { module?: CompilerOptions["module"]; target?: CompilerOptions["target"]; }, +) { + return typeof compilerOptions.module === "number" + ? compilerOptions.module + : getEmitScriptTarget(compilerOptions) >= ScriptTarget.ES2015 ? ModuleKind.ES2015 : ModuleKind.CommonJS; } /** @internal */ @@ -8545,8 +9335,9 @@ export function getEmitModuleResolutionKind(compilerOptions: CompilerOptions) { /** @internal */ export function getEmitModuleDetectionKind(options: CompilerOptions) { - return options.moduleDetection || - (getEmitModuleKind(options) === ModuleKind.Node16 || getEmitModuleKind(options) === ModuleKind.NodeNext ? ModuleDetectionKind.Force : ModuleDetectionKind.Auto); + return options.moduleDetection + || (getEmitModuleKind(options) === ModuleKind.Node16 || getEmitModuleKind(options) === ModuleKind.NodeNext + ? ModuleDetectionKind.Force : ModuleDetectionKind.Auto); } /** @internal */ @@ -8623,7 +9414,8 @@ export function moduleResolutionSupportsPackageJsonExportsAndImports(moduleResol /** @internal */ export function shouldResolveJsRequire(compilerOptions: CompilerOptions): boolean { // `bundler` doesn't support resolving `require`, but needs to in `noDtsResolution` to support Find Source Definition - return !!compilerOptions.noDtsResolution || getEmitModuleResolutionKind(compilerOptions) !== ModuleResolutionKind.Bundler; + return !!compilerOptions.noDtsResolution + || getEmitModuleResolutionKind(compilerOptions) !== ModuleResolutionKind.Bundler; } /** @internal */ @@ -8708,16 +9500,21 @@ export function getAllowJSCompilerOption(compilerOptions: CompilerOptions): bool /** @internal */ export function getUseDefineForClassFields(compilerOptions: CompilerOptions): boolean { - return compilerOptions.useDefineForClassFields === undefined ? getEmitScriptTarget(compilerOptions) >= ScriptTarget.ES2022 : compilerOptions.useDefineForClassFields; + return compilerOptions.useDefineForClassFields === undefined + ? getEmitScriptTarget(compilerOptions) >= ScriptTarget.ES2022 : compilerOptions.useDefineForClassFields; } /** @internal */ export function getEmitStandardClassFields(compilerOptions: CompilerOptions) { - return compilerOptions.useDefineForClassFields !== false && getEmitScriptTarget(compilerOptions) >= ScriptTarget.ES2022; + return compilerOptions.useDefineForClassFields !== false + && getEmitScriptTarget(compilerOptions) >= ScriptTarget.ES2022; } /** @internal */ -export function compilerOptionsAffectSemanticDiagnostics(newOptions: CompilerOptions, oldOptions: CompilerOptions): boolean { +export function compilerOptionsAffectSemanticDiagnostics( + newOptions: CompilerOptions, + oldOptions: CompilerOptions, +): boolean { return optionsHaveChanges(oldOptions, newOptions, semanticDiagnosticsOptionDeclarations); } @@ -8727,7 +9524,10 @@ export function compilerOptionsAffectEmit(newOptions: CompilerOptions, oldOption } /** @internal */ -export function compilerOptionsAffectDeclarationPath(newOptions: CompilerOptions, oldOptions: CompilerOptions): boolean { +export function compilerOptionsAffectDeclarationPath( + newOptions: CompilerOptions, + oldOptions: CompilerOptions, +): boolean { return optionsHaveChanges(oldOptions, newOptions, affectsDeclarationPathOptionDeclarations); } @@ -8745,13 +9545,14 @@ export function getJSXTransformEnabled(options: CompilerOptions): boolean { /** @internal */ export function getJSXImplicitImportBase(compilerOptions: CompilerOptions, file?: SourceFile): string | undefined { const jsxImportSourcePragmas = file?.pragmas.get("jsximportsource"); - const jsxImportSourcePragma = isArray(jsxImportSourcePragmas) ? jsxImportSourcePragmas[jsxImportSourcePragmas.length - 1] : jsxImportSourcePragmas; - return compilerOptions.jsx === JsxEmit.ReactJSX || - compilerOptions.jsx === JsxEmit.ReactJSXDev || - compilerOptions.jsxImportSource || - jsxImportSourcePragma ? - jsxImportSourcePragma?.arguments.factory || compilerOptions.jsxImportSource || "react" : - undefined; + const jsxImportSourcePragma = isArray(jsxImportSourcePragmas) + ? jsxImportSourcePragmas[jsxImportSourcePragmas.length - 1] : jsxImportSourcePragmas; + return compilerOptions.jsx === JsxEmit.ReactJSX + || compilerOptions.jsx === JsxEmit.ReactJSXDev + || compilerOptions.jsxImportSource + || jsxImportSourcePragma + ? jsxImportSourcePragma?.arguments.factory || compilerOptions.jsxImportSource || "react" + : undefined; } /** @internal */ @@ -8800,7 +9601,10 @@ export interface SymlinkCache { * don't include automatic type reference directives. Must be called only when * `hasProcessedResolutions` returns false (once per cache instance). */ - setSymlinksFromResolutions(files: readonly SourceFile[], typeReferenceDirectives: ModeAwareCache): void; + setSymlinksFromResolutions( + files: readonly SourceFile[], + typeReferenceDirectives: ModeAwareCache, + ): void; /** * @internal * Whether `setSymlinksFromResolutions` has already been called. @@ -8827,7 +9631,10 @@ export function createSymlinkCache(cwd: string, getCanonicalFileName: GetCanonic if (!containsIgnoredPath(symlinkPath)) { symlinkPath = ensureTrailingDirectorySeparator(symlinkPath); if (real !== false && !symlinkedDirectories?.has(symlinkPath)) { - (symlinkedDirectoriesByRealpath ||= createMultiMap()).add(ensureTrailingDirectorySeparator(real.realPath), symlink); + (symlinkedDirectoriesByRealpath ||= createMultiMap()).add( + ensureTrailingDirectorySeparator(real.realPath), + symlink, + ); } (symlinkedDirectories || (symlinkedDirectories = new Map())).set(symlinkPath, real); } @@ -8837,18 +9644,26 @@ export function createSymlinkCache(cwd: string, getCanonicalFileName: GetCanonic hasProcessedResolutions = true; for (const file of files) { file.resolvedModules?.forEach(resolution => processResolution(this, resolution.resolvedModule)); - file.resolvedTypeReferenceDirectiveNames?.forEach(resolution => processResolution(this, resolution.resolvedTypeReferenceDirective)); + file.resolvedTypeReferenceDirectiveNames?.forEach(resolution => + processResolution(this, resolution.resolvedTypeReferenceDirective) + ); } - typeReferenceDirectives.forEach(resolution => processResolution(this, resolution.resolvedTypeReferenceDirective)); + typeReferenceDirectives.forEach(resolution => + processResolution(this, resolution.resolvedTypeReferenceDirective) + ); }, hasProcessedResolutions: () => hasProcessedResolutions, }; - function processResolution(cache: SymlinkCache, resolution: ResolvedModuleFull | ResolvedTypeReferenceDirective | undefined) { + function processResolution( + cache: SymlinkCache, + resolution: ResolvedModuleFull | ResolvedTypeReferenceDirective | undefined, + ) { if (!resolution || !resolution.originalPath || !resolution.resolvedFileName) return; const { resolvedFileName, originalPath } = resolution; cache.setSymlinkedFile(toPath(originalPath, cwd, getCanonicalFileName), resolvedFileName); - const [commonResolved, commonOriginal] = guessDirectorySymlink(resolvedFileName, originalPath, cwd, getCanonicalFileName) || emptyArray; + const [commonResolved, commonOriginal] = + guessDirectorySymlink(resolvedFileName, originalPath, cwd, getCanonicalFileName) || emptyArray; if (commonResolved && commonOriginal) { cache.setSymlinkedDirectory( commonOriginal, @@ -8858,15 +9673,20 @@ export function createSymlinkCache(cwd: string, getCanonicalFileName: GetCanonic } } -function guessDirectorySymlink(a: string, b: string, cwd: string, getCanonicalFileName: GetCanonicalFileName): [string, string] | undefined { +function guessDirectorySymlink( + a: string, + b: string, + cwd: string, + getCanonicalFileName: GetCanonicalFileName, +): [string, string] | undefined { const aParts = getPathComponents(getNormalizedAbsolutePath(a, cwd)); const bParts = getPathComponents(getNormalizedAbsolutePath(b, cwd)); let isDirectory = false; while ( - aParts.length >= 2 && bParts.length >= 2 && - !isNodeModulesOrScopedPackageDirectory(aParts[aParts.length - 2], getCanonicalFileName) && - !isNodeModulesOrScopedPackageDirectory(bParts[bParts.length - 2], getCanonicalFileName) && - getCanonicalFileName(aParts[aParts.length - 1]) === getCanonicalFileName(bParts[bParts.length - 1]) + aParts.length >= 2 && bParts.length >= 2 + && !isNodeModulesOrScopedPackageDirectory(aParts[aParts.length - 2], getCanonicalFileName) + && !isNodeModulesOrScopedPackageDirectory(bParts[bParts.length - 2], getCanonicalFileName) + && getCanonicalFileName(aParts[aParts.length - 1]) === getCanonicalFileName(bParts[bParts.length - 1]) ) { aParts.pop(); bParts.pop(); @@ -8877,7 +9697,10 @@ function guessDirectorySymlink(a: string, b: string, cwd: string, getCanonicalFi // KLUDGE: Don't assume one 'node_modules' links to another. More likely a single directory inside the node_modules is the symlink. // ALso, don't assume that an `@foo` directory is linked. More likely the contents of that are linked. -function isNodeModulesOrScopedPackageDirectory(s: string | undefined, getCanonicalFileName: GetCanonicalFileName): boolean { +function isNodeModulesOrScopedPackageDirectory( + s: string | undefined, + getCanonicalFileName: GetCanonicalFileName, +): boolean { return s !== undefined && (getCanonicalFileName(s) === "node_modules" || startsWith(s, "@")); } @@ -8886,7 +9709,11 @@ function stripLeadingDirectorySeparator(s: string): string | undefined { } /** @internal */ -export function tryRemoveDirectoryPrefix(path: string, dirPath: string, getCanonicalFileName: GetCanonicalFileName): string | undefined { +export function tryRemoveDirectoryPrefix( + path: string, + dirPath: string, + getCanonicalFileName: GetCanonicalFileName, +): string | undefined { const withoutPrefix = tryRemovePrefix(path, dirPath, getCanonicalFileName); return withoutPrefix === undefined ? undefined : stripLeadingDirectorySeparator(withoutPrefix); } @@ -8957,7 +9784,11 @@ const wildcardMatchers = { }; /** @internal */ -export function getRegularExpressionForWildcard(specs: readonly string[] | undefined, basePath: string, usage: "files" | "directories" | "exclude"): string | undefined { +export function getRegularExpressionForWildcard( + specs: readonly string[] | undefined, + basePath: string, + usage: "files" | "directories" | "exclude", +): string | undefined { const patterns = getRegularExpressionsForWildcards(specs, basePath, usage); if (!patterns || !patterns.length) { return undefined; @@ -8970,7 +9801,11 @@ export function getRegularExpressionForWildcard(specs: readonly string[] | undef } /** @internal */ -export function getRegularExpressionsForWildcards(specs: readonly string[] | undefined, basePath: string, usage: "files" | "directories" | "exclude"): readonly string[] | undefined { +export function getRegularExpressionsForWildcards( + specs: readonly string[] | undefined, + basePath: string, + usage: "files" | "directories" | "exclude", +): readonly string[] | undefined { if (specs === undefined || specs.length === 0) { return undefined; } @@ -8994,7 +9829,12 @@ export function getPatternFromSpec(spec: string, basePath: string, usage: "files return pattern && `^(${pattern})${usage === "exclude" ? "($|/)" : "$"}`; } -function getSubPatternFromSpec(spec: string, basePath: string, usage: "files" | "directories" | "exclude", { singleAsteriskRegexFragment, doubleAsteriskRegexFragment, replaceWildcardCharacter }: WildcardMatcher): string | undefined { +function getSubPatternFromSpec( + spec: string, + basePath: string, + usage: "files" | "directories" | "exclude", + { singleAsteriskRegexFragment, doubleAsteriskRegexFragment, replaceWildcardCharacter }: WildcardMatcher, +): string | undefined { let subpattern = ""; let hasWrittenComponent = false; const components = getNormalizedPathComponents(spec, basePath); @@ -9096,13 +9936,22 @@ export interface FileMatcherPatterns { * * @internal */ -export function getFileMatcherPatterns(path: string, excludes: readonly string[] | undefined, includes: readonly string[] | undefined, useCaseSensitiveFileNames: boolean, currentDirectory: string): FileMatcherPatterns { +export function getFileMatcherPatterns( + path: string, + excludes: readonly string[] | undefined, + includes: readonly string[] | undefined, + useCaseSensitiveFileNames: boolean, + currentDirectory: string, +): FileMatcherPatterns { path = normalizePath(path); currentDirectory = normalizePath(currentDirectory); const absolutePath = combinePaths(currentDirectory, path); return { - includeFilePatterns: map(getRegularExpressionsForWildcards(includes, absolutePath, "files"), pattern => `^${pattern}$`), + includeFilePatterns: map( + getRegularExpressionsForWildcards(includes, absolutePath, "files"), + pattern => `^${pattern}$`, + ), includeFilePattern: getRegularExpressionForWildcard(includes, absolutePath, "files"), includeDirectoryPattern: getRegularExpressionForWildcard(includes, absolutePath, "directories"), excludePattern: getRegularExpressionForWildcard(excludes, absolutePath, "exclude"), @@ -9120,15 +9969,28 @@ export function getRegexFromPattern(pattern: string, useCaseSensitiveFileNames: * * @internal */ -export function matchFiles(path: string, extensions: readonly string[] | undefined, excludes: readonly string[] | undefined, includes: readonly string[] | undefined, useCaseSensitiveFileNames: boolean, currentDirectory: string, depth: number | undefined, getFileSystemEntries: (path: string) => FileSystemEntries, realpath: (path: string) => string): string[] { +export function matchFiles( + path: string, + extensions: readonly string[] | undefined, + excludes: readonly string[] | undefined, + includes: readonly string[] | undefined, + useCaseSensitiveFileNames: boolean, + currentDirectory: string, + depth: number | undefined, + getFileSystemEntries: (path: string) => FileSystemEntries, + realpath: (path: string) => string, +): string[] { path = normalizePath(path); currentDirectory = normalizePath(currentDirectory); const patterns = getFileMatcherPatterns(path, excludes, includes, useCaseSensitiveFileNames, currentDirectory); - const includeFileRegexes = patterns.includeFilePatterns && patterns.includeFilePatterns.map(pattern => getRegexFromPattern(pattern, useCaseSensitiveFileNames)); - const includeDirectoryRegex = patterns.includeDirectoryPattern && getRegexFromPattern(patterns.includeDirectoryPattern, useCaseSensitiveFileNames); - const excludeRegex = patterns.excludePattern && getRegexFromPattern(patterns.excludePattern, useCaseSensitiveFileNames); + const includeFileRegexes = patterns.includeFilePatterns + && patterns.includeFilePatterns.map(pattern => getRegexFromPattern(pattern, useCaseSensitiveFileNames)); + const includeDirectoryRegex = patterns.includeDirectoryPattern + && getRegexFromPattern(patterns.includeDirectoryPattern, useCaseSensitiveFileNames); + const excludeRegex = patterns.excludePattern + && getRegexFromPattern(patterns.excludePattern, useCaseSensitiveFileNames); // Associate an array of results with each include regex. This keeps results in order of the "include" order. // If there are no "includes", then just put everything in results[0]. @@ -9174,8 +10036,8 @@ export function matchFiles(path: string, extensions: readonly string[] | undefin const name = combinePaths(path, current); const absoluteName = combinePaths(absolutePath, current); if ( - (!includeDirectoryRegex || includeDirectoryRegex.test(absoluteName)) && - (!excludeRegex || !excludeRegex.test(absoluteName)) + (!includeDirectoryRegex || includeDirectoryRegex.test(absoluteName)) + && (!excludeRegex || !excludeRegex.test(absoluteName)) ) { visitDirectory(name, absoluteName, depth); } @@ -9186,7 +10048,11 @@ export function matchFiles(path: string, extensions: readonly string[] | undefin /** * Computes the unique non-wildcard base paths amongst the provided include patterns. */ -function getBasePaths(path: string, includes: readonly string[] | undefined, useCaseSensitiveFileNames: boolean): string[] { +function getBasePaths( + path: string, + includes: readonly string[] | undefined, + useCaseSensitiveFileNames: boolean, +): string[] { // Storage for our results in the form of literal paths (e.g. the paths as written by the user). const basePaths: string[] = [path]; @@ -9207,7 +10073,9 @@ function getBasePaths(path: string, includes: readonly string[] | undefined, use // Iterate over each include base path and include unique base paths that are not a // subpath of an existing base path for (const includeBasePath of includeBasePaths) { - if (every(basePaths, basePath => !containsPath(basePath, includeBasePath, path, !useCaseSensitiveFileNames))) { + if ( + every(basePaths, basePath => !containsPath(basePath, includeBasePath, path, !useCaseSensitiveFileNames)) + ) { basePaths.push(includeBasePath); } } @@ -9266,31 +10134,66 @@ export function getScriptKindFromFileName(fileName: string): ScriptKind { * * @internal */ -export const supportedTSExtensions: readonly Extension[][] = [[Extension.Ts, Extension.Tsx, Extension.Dts], [Extension.Cts, Extension.Dcts], [Extension.Mts, Extension.Dmts]]; +export const supportedTSExtensions: readonly Extension[][] = [[Extension.Ts, Extension.Tsx, Extension.Dts], [ + Extension.Cts, + Extension.Dcts, +], [Extension.Mts, Extension.Dmts]]; /** @internal */ export const supportedTSExtensionsFlat: readonly Extension[] = flatten(supportedTSExtensions); const supportedTSExtensionsWithJson: readonly Extension[][] = [...supportedTSExtensions, [Extension.Json]]; /** Must have ".d.ts" first because if ".ts" goes first, that will be detected as the extension instead of ".d.ts". */ -const supportedTSExtensionsForExtractExtension: readonly Extension[] = [Extension.Dts, Extension.Dcts, Extension.Dmts, Extension.Cts, Extension.Mts, Extension.Ts, Extension.Tsx]; -/** @internal */ -export const supportedJSExtensions: readonly Extension[][] = [[Extension.Js, Extension.Jsx], [Extension.Mjs], [Extension.Cjs]]; +const supportedTSExtensionsForExtractExtension: readonly Extension[] = [ + Extension.Dts, + Extension.Dcts, + Extension.Dmts, + Extension.Cts, + Extension.Mts, + Extension.Ts, + Extension.Tsx, +]; +/** @internal */ +export const supportedJSExtensions: readonly Extension[][] = [[Extension.Js, Extension.Jsx], [Extension.Mjs], [ + Extension.Cjs, +]]; /** @internal */ export const supportedJSExtensionsFlat: readonly Extension[] = flatten(supportedJSExtensions); -const allSupportedExtensions: readonly Extension[][] = [[Extension.Ts, Extension.Tsx, Extension.Dts, Extension.Js, Extension.Jsx], [Extension.Cts, Extension.Dcts, Extension.Cjs], [Extension.Mts, Extension.Dmts, Extension.Mjs]]; +const allSupportedExtensions: readonly Extension[][] = [ + [Extension.Ts, Extension.Tsx, Extension.Dts, Extension.Js, Extension.Jsx], + [Extension.Cts, Extension.Dcts, Extension.Cjs], + [Extension.Mts, Extension.Dmts, Extension.Mjs], +]; const allSupportedExtensionsWithJson: readonly Extension[][] = [...allSupportedExtensions, [Extension.Json]]; /** @internal */ export const supportedDeclarationExtensions: readonly Extension[] = [Extension.Dts, Extension.Dcts, Extension.Dmts]; /** @internal */ -export const supportedTSImplementationExtensions: readonly Extension[] = [Extension.Ts, Extension.Cts, Extension.Mts, Extension.Tsx]; +export const supportedTSImplementationExtensions: readonly Extension[] = [ + Extension.Ts, + Extension.Cts, + Extension.Mts, + Extension.Tsx, +]; /** @internal */ -export const extensionsNotSupportingExtensionlessResolution: readonly Extension[] = [Extension.Mts, Extension.Dmts, Extension.Mjs, Extension.Cts, Extension.Dcts, Extension.Cjs]; +export const extensionsNotSupportingExtensionlessResolution: readonly Extension[] = [ + Extension.Mts, + Extension.Dmts, + Extension.Mjs, + Extension.Cts, + Extension.Dcts, + Extension.Cjs, +]; /** @internal */ export function getSupportedExtensions(options?: CompilerOptions): readonly Extension[][]; /** @internal */ -export function getSupportedExtensions(options?: CompilerOptions, extraFileExtensions?: readonly FileExtensionInfo[]): readonly string[][]; +export function getSupportedExtensions( + options?: CompilerOptions, + extraFileExtensions?: readonly FileExtensionInfo[], +): readonly string[][]; /** @internal */ -export function getSupportedExtensions(options?: CompilerOptions, extraFileExtensions?: readonly FileExtensionInfo[]): readonly string[][] { +export function getSupportedExtensions( + options?: CompilerOptions, + extraFileExtensions?: readonly FileExtensionInfo[], +): readonly string[][] { const needJsExtensions = options && getAllowJSCompilerOption(options); if (!extraFileExtensions || extraFileExtensions.length === 0) { @@ -9301,18 +10204,32 @@ export function getSupportedExtensions(options?: CompilerOptions, extraFileExten const flatBuiltins = flatten(builtins); const extensions = [ ...builtins, - ...mapDefined(extraFileExtensions, x => x.scriptKind === ScriptKind.Deferred || needJsExtensions && isJSLike(x.scriptKind) && flatBuiltins.indexOf(x.extension as Extension) === -1 ? [x.extension] : undefined), + ...mapDefined( + extraFileExtensions, + x => x.scriptKind === ScriptKind.Deferred + || needJsExtensions && isJSLike(x.scriptKind) + && flatBuiltins.indexOf(x.extension as Extension) === -1 ? [x.extension] : undefined, + ), ]; return extensions; } /** @internal */ -export function getSupportedExtensionsWithJsonIfResolveJsonModule(options: CompilerOptions | undefined, supportedExtensions: readonly Extension[][]): readonly Extension[][]; +export function getSupportedExtensionsWithJsonIfResolveJsonModule( + options: CompilerOptions | undefined, + supportedExtensions: readonly Extension[][], +): readonly Extension[][]; /** @internal */ -export function getSupportedExtensionsWithJsonIfResolveJsonModule(options: CompilerOptions | undefined, supportedExtensions: readonly string[][]): readonly string[][]; +export function getSupportedExtensionsWithJsonIfResolveJsonModule( + options: CompilerOptions | undefined, + supportedExtensions: readonly string[][], +): readonly string[][]; /** @internal */ -export function getSupportedExtensionsWithJsonIfResolveJsonModule(options: CompilerOptions | undefined, supportedExtensions: readonly string[][]): readonly string[][] { +export function getSupportedExtensionsWithJsonIfResolveJsonModule( + options: CompilerOptions | undefined, + supportedExtensions: readonly string[][], +): readonly string[][] { if (!options || !getResolveJsonModule(options)) return supportedExtensions; if (supportedExtensions === allSupportedExtensions) return allSupportedExtensionsWithJson; if (supportedExtensions === supportedTSExtensions) return supportedTSExtensionsWithJson; @@ -9345,15 +10262,26 @@ export const enum ModuleSpecifierEnding { } /** @internal */ -export function usesExtensionsOnImports({ imports }: SourceFile, hasExtension: (text: string) => boolean = or(hasJSFileExtension, hasTSFileExtension)): boolean { - return firstDefined(imports, ({ text }) => - pathIsRelative(text) && !fileExtensionIsOneOf(text, extensionsNotSupportingExtensionlessResolution) - ? hasExtension(text) - : undefined) || false; -} - -/** @internal */ -export function getModuleSpecifierEndingPreference(preference: UserPreferences["importModuleSpecifierEnding"], resolutionMode: ResolutionMode, compilerOptions: CompilerOptions, sourceFile: SourceFile): ModuleSpecifierEnding { +export function usesExtensionsOnImports( + { imports }: SourceFile, + hasExtension: (text: string) => boolean = or(hasJSFileExtension, hasTSFileExtension), +): boolean { + return firstDefined( + imports, + ({ text }) => + pathIsRelative(text) && !fileExtensionIsOneOf(text, extensionsNotSupportingExtensionlessResolution) + ? hasExtension(text) + : undefined, + ) || false; +} + +/** @internal */ +export function getModuleSpecifierEndingPreference( + preference: UserPreferences["importModuleSpecifierEnding"], + resolutionMode: ResolutionMode, + compilerOptions: CompilerOptions, + sourceFile: SourceFile, +): ModuleSpecifierEnding { if (preference === "js" || resolutionMode === ModuleKind.ESNext) { // Extensions are explicitly requested or required. Now choose between .js and .ts. if (!shouldAllowImportingTsExtension(compilerOptions)) { @@ -9385,9 +10313,9 @@ export function getModuleSpecifierEndingPreference(preference: UserPreferences[" function inferPreference() { let usesJsExtensions = false; - const specifiers = sourceFile.imports.length ? sourceFile.imports.map(i => i.text) : - isSourceFileJS(sourceFile) ? getRequiresAtTopOfFile(sourceFile).map(r => r.arguments[0].text) : - emptyArray; + const specifiers = sourceFile.imports.length ? sourceFile.imports.map(i => i.text) + : isSourceFileJS(sourceFile) ? getRequiresAtTopOfFile(sourceFile).map(r => r.arguments[0].text) + : emptyArray; for (const specifier of specifiers) { if (pathIsRelative(specifier)) { if (fileExtensionIsOneOf(specifier, extensionsNotSupportingExtensionlessResolution)) { @@ -9416,7 +10344,10 @@ function getRequiresAtTopOfFile(sourceFile: SourceFile): readonly RequireOrImpor if (isRequireVariableStatement(statement)) { requires = concatenate(requires, statement.declarationList.declarations.map(d => d.initializer)); } - else if (isExpressionStatement(statement) && isRequireCall(statement.expression, /*requireStringLiteralLikeArgument*/ true)) { + else if ( + isExpressionStatement(statement) + && isRequireCall(statement.expression, /*requireStringLiteralLikeArgument*/ true) + ) { requires = append(requires, statement.expression); } else { @@ -9427,11 +10358,19 @@ function getRequiresAtTopOfFile(sourceFile: SourceFile): readonly RequireOrImpor } /** @internal */ -export function isSupportedSourceFileName(fileName: string, compilerOptions?: CompilerOptions, extraFileExtensions?: readonly FileExtensionInfo[]) { +export function isSupportedSourceFileName( + fileName: string, + compilerOptions?: CompilerOptions, + extraFileExtensions?: readonly FileExtensionInfo[], +) { if (!fileName) return false; const supportedExtensions = getSupportedExtensions(compilerOptions, extraFileExtensions); - for (const extension of flatten(getSupportedExtensionsWithJsonIfResolveJsonModule(compilerOptions, supportedExtensions))) { + for ( + const extension of flatten( + getSupportedExtensionsWithJsonIfResolveJsonModule(compilerOptions, supportedExtensions), + ) + ) { if (fileExtensionIs(fileName, extension)) { return true; } @@ -9452,7 +10391,20 @@ export function compareNumberOfDirectorySeparators(path1: string, path2: string) ); } -const extensionsToRemove = [Extension.Dts, Extension.Dmts, Extension.Dcts, Extension.Mjs, Extension.Mts, Extension.Cjs, Extension.Cts, Extension.Ts, Extension.Js, Extension.Tsx, Extension.Jsx, Extension.Json]; +const extensionsToRemove = [ + Extension.Dts, + Extension.Dmts, + Extension.Dcts, + Extension.Mjs, + Extension.Mts, + Extension.Cjs, + Extension.Cts, + Extension.Ts, + Extension.Js, + Extension.Tsx, + Extension.Jsx, + Extension.Json, +]; /** @internal */ export function removeFileExtension(path: string): string { for (const ext of extensionsToRemove) { @@ -9516,7 +10468,9 @@ export function positionIsSynthesized(pos: number): boolean { * @internal */ export function extensionIsTS(ext: string): boolean { - return ext === Extension.Ts || ext === Extension.Tsx || ext === Extension.Dts || ext === Extension.Cts || ext === Extension.Mts || ext === Extension.Dmts || ext === Extension.Dcts || (startsWith(ext, ".d.") && endsWith(ext, ".ts")); + return ext === Extension.Ts || ext === Extension.Tsx || ext === Extension.Dts || ext === Extension.Cts + || ext === Extension.Mts || ext === Extension.Dmts || ext === Extension.Dcts + || (startsWith(ext, ".d.") && endsWith(ext, ".ts")); } /** @internal */ @@ -9563,7 +10517,10 @@ export const emptyFileSystemEntries: FileSystemEntries = { * * @internal */ -export function matchPatternOrExact(patternOrStrings: readonly (string | Pattern)[], candidate: string): string | Pattern | undefined { +export function matchPatternOrExact( + patternOrStrings: readonly (string | Pattern)[], + candidate: string, +): string | Pattern | undefined { const patterns: Pattern[] = []; for (const patternOrString of patternOrStrings) { if (patternOrString === candidate) { @@ -9589,20 +10546,29 @@ export function sliceAfter(arr: readonly T[], value: T): readonly T[] { } /** @internal */ -export function addRelatedInfo(diagnostic: T, ...relatedInformation: DiagnosticRelatedInformation[]): T { +export function addRelatedInfo( + diagnostic: T, + ...relatedInformation: DiagnosticRelatedInformation[] +): T { if (!relatedInformation.length) { return diagnostic; } if (!diagnostic.relatedInformation) { diagnostic.relatedInformation = []; } - Debug.assert(diagnostic.relatedInformation !== emptyArray, "Diagnostic had empty array singleton for related info, but is still being constructed!"); + Debug.assert( + diagnostic.relatedInformation !== emptyArray, + "Diagnostic had empty array singleton for related info, but is still being constructed!", + ); diagnostic.relatedInformation.push(...relatedInformation); return diagnostic; } /** @internal */ -export function minAndMax(arr: readonly T[], getValue: (value: T) => number): { readonly min: number; readonly max: number; } { +export function minAndMax( + arr: readonly T[], + getValue: (value: T) => number, +): { readonly min: number; readonly max: number; } { Debug.assert(arr.length !== 0); let min = getValue(arr[0]); let max = min; @@ -9624,7 +10590,10 @@ export function rangeOfNode(node: Node): TextRange { } /** @internal */ -export function rangeOfTypeParameters(sourceFile: SourceFile, typeParameters: NodeArray): TextRange { +export function rangeOfTypeParameters( + sourceFile: SourceFile, + typeParameters: NodeArray, +): TextRange { // Include the `<>` const pos = typeParameters.pos - 1; const end = Math.min(sourceFile.text.length, skipTrivia(sourceFile.text, typeParameters.end) + 1); @@ -9636,19 +10605,25 @@ export interface HostWithIsSourceOfProjectReferenceRedirect { isSourceOfProjectReferenceRedirect(fileName: string): boolean; } /** @internal */ -export function skipTypeChecking(sourceFile: SourceFile, options: CompilerOptions, host: HostWithIsSourceOfProjectReferenceRedirect) { +export function skipTypeChecking( + sourceFile: SourceFile, + options: CompilerOptions, + host: HostWithIsSourceOfProjectReferenceRedirect, +) { // If skipLibCheck is enabled, skip reporting errors if file is a declaration file. // If skipDefaultLibCheck is enabled, skip reporting errors if file contains a // '/// ' directive. - return (options.skipLibCheck && sourceFile.isDeclarationFile || - options.skipDefaultLibCheck && sourceFile.hasNoDefaultLib) || - host.isSourceOfProjectReferenceRedirect(sourceFile.fileName); + return (options.skipLibCheck && sourceFile.isDeclarationFile + || options.skipDefaultLibCheck && sourceFile.hasNoDefaultLib) + || host.isSourceOfProjectReferenceRedirect(sourceFile.fileName); } /** @internal */ export function isJsonEqual(a: unknown, b: unknown): boolean { // eslint-disable-next-line no-null/no-null - return a === b || typeof a === "object" && a !== null && typeof b === "object" && b !== null && equalOwnProperties(a as MapLike, b as MapLike, isJsonEqual); + return a === b + || typeof a === "object" && a !== null && typeof b === "object" && b !== null + && equalOwnProperties(a as MapLike, b as MapLike, isJsonEqual); } /** @@ -9695,8 +10670,8 @@ export function parsePseudoBigInt(stringValue: string): string { // Find character range: 0-9 < A-F < a-f const digit = digitChar <= CharacterCodes._9 ? digitChar - CharacterCodes._0 - : 10 + digitChar - - (digitChar <= CharacterCodes.F ? CharacterCodes.A : CharacterCodes.a); + : 10 + digitChar + - (digitChar <= CharacterCodes.F ? CharacterCodes.A : CharacterCodes.a); const shiftedDigit = digit << (bitOffset & 15); segments[segment] |= shiftedDigit; const residual = shiftedDigit >>> 16; @@ -9770,8 +10745,10 @@ export function isValidBigIntString(s: string, roundTripOnly: boolean): boolean // * a bigint can be scanned, and that when it is scanned, it is // * the full length of the input string (so the scanner is one character beyond the augmented input length) // * it does not contain a numeric seperator (the `BigInt` constructor does not accept a numeric seperator in its input) - return success && result === SyntaxKind.BigIntLiteral && scanner.getTokenEnd() === (s.length + 1) && !(flags & TokenFlags.ContainsSeparator) - && (!roundTripOnly || s === pseudoBigIntToString({ negative, base10Value: parsePseudoBigInt(scanner.getTokenValue()) })); + return success && result === SyntaxKind.BigIntLiteral && scanner.getTokenEnd() === (s.length + 1) + && !(flags & TokenFlags.ContainsSeparator) + && (!roundTripOnly + || s === pseudoBigIntToString({ negative, base10Value: parsePseudoBigInt(scanner.getTokenValue()) })); } /** @internal */ @@ -9815,7 +10792,8 @@ function isIdentifierInNonEmittingHeritageClause(node: Node): boolean { return "quit"; } }) as HeritageClause | undefined; - return heritageClause?.token === SyntaxKind.ImplementsKeyword || heritageClause?.parent.kind === SyntaxKind.InterfaceDeclaration; + return heritageClause?.token === SyntaxKind.ImplementsKeyword + || heritageClause?.parent.kind === SyntaxKind.InterfaceDeclaration; } /** @internal */ @@ -9912,9 +10890,15 @@ export function setParent(child: T | undefined, parent: T["paren */ export function setEachParent(children: T, parent: T[number]["parent"]): T; /** @internal */ -export function setEachParent(children: T | undefined, parent: T[number]["parent"]): T | undefined; +export function setEachParent( + children: T | undefined, + parent: T[number]["parent"], +): T | undefined; /** @internal */ -export function setEachParent(children: T | undefined, parent: T[number]["parent"]): T | undefined { +export function setEachParent( + children: T | undefined, + parent: T[number]["parent"], +): T | undefined { if (children) { for (const child of children) { setParent(child, parent); @@ -9992,9 +10976,9 @@ export function expressionResultIsUnused(node: Expression): boolean { } // result is unused in an expression statement, `void` expression, or the initializer or incrementer of a `for` loop if ( - isExpressionStatement(parent) || - isVoidExpression(parent) || - isForStatement(parent) && (parent.initializer === node || parent.incrementor === node) + isExpressionStatement(parent) + || isVoidExpression(parent) + || isForStatement(parent) && (parent.initializer === node || parent.incrementor === node) ) { return true; } @@ -10036,8 +11020,8 @@ export function getContainingNodeArray(node: Node): NodeArray | undefined return (node as TemplateSpan).parent.templateSpans; case SyntaxKind.Decorator: { const { parent } = node as Decorator; - return canHaveDecorators(parent) ? parent.modifiers : - undefined; + return canHaveDecorators(parent) ? parent.modifiers + : undefined; } case SyntaxKind.HeritageClause: return (node as HeritageClause).parent.heritageClauses; @@ -10060,15 +11044,20 @@ export function getContainingNodeArray(node: Node): NodeArray | undefined case SyntaxKind.CommaListExpression: case SyntaxKind.NamedImports: case SyntaxKind.NamedExports: - return (parent as TupleTypeNode | ArrayLiteralExpression | CommaListExpression | NamedImports | NamedExports).elements; + return (parent as + | TupleTypeNode + | ArrayLiteralExpression + | CommaListExpression + | NamedImports + | NamedExports).elements; case SyntaxKind.ObjectLiteralExpression: case SyntaxKind.JsxAttributes: return (parent as ObjectLiteralExpressionBase).properties; case SyntaxKind.CallExpression: case SyntaxKind.NewExpression: - return isTypeNode(node) ? (parent as CallExpression | NewExpression).typeArguments : - (parent as CallExpression | NewExpression).expression === node ? undefined : - (parent as CallExpression | NewExpression).arguments; + return isTypeNode(node) ? (parent as CallExpression | NewExpression).typeArguments + : (parent as CallExpression | NewExpression).expression === node ? undefined + : (parent as CallExpression | NewExpression).arguments; case SyntaxKind.JsxElement: case SyntaxKind.JsxFragment: return isJsxChild(node) ? (parent as JsxElement | JsxFragment).children : undefined; @@ -10165,10 +11154,15 @@ export function isNumericLiteralName(name: string | __String) { } /** @internal */ -export function createPropertyNameNodeForIdentifierOrLiteral(name: string, target: ScriptTarget, singleQuote?: boolean, stringNamed?: boolean) { - return isIdentifierText(name, target) ? factory.createIdentifier(name) : - !stringNamed && isNumericLiteralName(name) && +name >= 0 ? factory.createNumericLiteral(+name) : - factory.createStringLiteral(name, !!singleQuote); +export function createPropertyNameNodeForIdentifierOrLiteral( + name: string, + target: ScriptTarget, + singleQuote?: boolean, + stringNamed?: boolean, +) { + return isIdentifierText(name, target) ? factory.createIdentifier(name) + : !stringNamed && isNumericLiteralName(name) && +name >= 0 ? factory.createNumericLiteral(+name) + : factory.createStringLiteral(name, !!singleQuote); } /** @internal */ @@ -10239,7 +11233,8 @@ export function getNodeModulePathParts(fullPath: string): NodeModulePathParts | fileNameIndex = partStart; - return state > States.NodeModules ? { topLevelNodeModulesIndex, topLevelPackageNameIndex, packageRootIndex, fileNameIndex } : undefined; + return state > States.NodeModules + ? { topLevelNodeModulesIndex, topLevelPackageNameIndex, packageRootIndex, fileNameIndex } : undefined; } /** @internal */ @@ -10248,7 +11243,21 @@ export function getParameterTypeNode(parameter: ParameterDeclaration | JSDocPara } /** @internal */ -export function isTypeDeclaration(node: Node): node is TypeParameterDeclaration | ClassDeclaration | InterfaceDeclaration | TypeAliasDeclaration | JSDocTypedefTag | JSDocCallbackTag | JSDocEnumTag | EnumDeclaration | ImportClause | ImportSpecifier | ExportSpecifier { +export function isTypeDeclaration( + node: Node, +): node is + | TypeParameterDeclaration + | ClassDeclaration + | InterfaceDeclaration + | TypeAliasDeclaration + | JSDocTypedefTag + | JSDocCallbackTag + | JSDocEnumTag + | EnumDeclaration + | ImportClause + | ImportSpecifier + | ExportSpecifier +{ switch (node.kind) { case SyntaxKind.TypeParameter: case SyntaxKind.ClassDeclaration: @@ -10271,8 +11280,10 @@ export function isTypeDeclaration(node: Node): node is TypeParameterDeclaration /** @internal */ export function canHaveExportModifier(node: Node): node is Extract { - return isEnumDeclaration(node) || isVariableStatement(node) || isFunctionDeclaration(node) || isClassDeclaration(node) - || isInterfaceDeclaration(node) || isTypeDeclaration(node) || (isModuleDeclaration(node) && !isExternalModuleAugmentation(node) && !isGlobalScopeAugmentation(node)); + return isEnumDeclaration(node) || isVariableStatement(node) || isFunctionDeclaration(node) + || isClassDeclaration(node) + || isInterfaceDeclaration(node) || isTypeDeclaration(node) + || (isModuleDeclaration(node) && !isExternalModuleAugmentation(node) && !isGlobalScopeAugmentation(node)); } /** @internal */ @@ -10290,9 +11301,9 @@ export function canUsePropertyAccess(name: string, languageVersion: ScriptTarget return false; } const firstChar = name.charCodeAt(0); - return firstChar === CharacterCodes.hash ? - name.length > 1 && isIdentifierStart(name.charCodeAt(1), languageVersion) : - isIdentifierStart(firstChar, languageVersion); + return firstChar === CharacterCodes.hash + ? name.length > 1 && isIdentifierStart(name.charCodeAt(1), languageVersion) + : isIdentifierStart(firstChar, languageVersion); } /** @internal */ @@ -10305,7 +11316,9 @@ export function isJSDocOptionalParameter(node: ParameterDeclaration) { return isInJSFile(node) && ( // node.type should only be a JSDocOptionalType when node is a parameter of a JSDocFunctionType node.type && node.type.kind === SyntaxKind.JSDocOptionalType - || getJSDocParameterTags(node).some(({ isBracketed, typeExpression }) => isBracketed || !!typeExpression && typeExpression.type.kind === SyntaxKind.JSDocOptionalType) + || getJSDocParameterTags(node).some(({ isBracketed, typeExpression }) => + isBracketed || !!typeExpression && typeExpression.type.kind === SyntaxKind.JSDocOptionalType + ) ); } @@ -10316,7 +11329,8 @@ export function isOptionalDeclaration(declaration: Declaration): boolean { case SyntaxKind.PropertySignature: return !!(declaration as PropertyDeclaration | PropertySignature).questionToken; case SyntaxKind.Parameter: - return !!(declaration as ParameterDeclaration).questionToken || isJSDocOptionalParameter(declaration as ParameterDeclaration); + return !!(declaration as ParameterDeclaration).questionToken + || isJSDocOptionalParameter(declaration as ParameterDeclaration); case SyntaxKind.JSDocPropertyTag: case SyntaxKind.JSDocParameterTag: return isOptionalJSDocPropertyLikeTag(declaration); @@ -10384,7 +11398,9 @@ export function intrinsicTagNameToString(node: Identifier | JsxNamespacedName) { * Indicates whether a type can be used as a property name. * @internal */ -export function isTypeUsableAsPropertyName(type: Type): type is StringLiteralType | NumberLiteralType | UniqueESSymbolType { +export function isTypeUsableAsPropertyName( + type: Type, +): type is StringLiteralType | NumberLiteralType | UniqueESSymbolType { return !!(type.flags & TypeFlags.StringOrNumberLiteralOrUnique); } diff --git a/src/compiler/utilitiesPublic.ts b/src/compiler/utilitiesPublic.ts index 56ee00f89a04c..a5caf41e70e57 100644 --- a/src/compiler/utilitiesPublic.ts +++ b/src/compiler/utilitiesPublic.ts @@ -542,7 +542,8 @@ export function getTypeParameterOwner(d: Declaration): Declaration | undefined { export type ParameterPropertyDeclaration = ParameterDeclaration & { parent: ConstructorDeclaration; name: Identifier; }; export function isParameterPropertyDeclaration(node: Node, parent: Node): node is ParameterPropertyDeclaration { - return isParameter(node) && hasSyntacticModifier(node, ModifierFlags.ParameterPropertyModifier) && parent.kind === SyntaxKind.Constructor; + return isParameter(node) && hasSyntacticModifier(node, ModifierFlags.ParameterPropertyModifier) + && parent.kind === SyntaxKind.Constructor; } export function isEmptyBindingPattern(node: BindingName): node is BindingPattern { @@ -613,7 +614,21 @@ function getNodeFlags(node: Node) { } /** @internal */ -export const supportedLocaleDirectories = ["cs", "de", "es", "fr", "it", "ja", "ko", "pl", "pt-br", "ru", "tr", "zh-cn", "zh-tw"]; +export const supportedLocaleDirectories = [ + "cs", + "de", + "es", + "fr", + "it", + "ja", + "ko", + "pl", + "pt-br", + "ru", + "tr", + "zh-cn", + "zh-tw", +]; /** * Checks to see if the locale is in the appropriate format, @@ -621,7 +636,12 @@ export const supportedLocaleDirectories = ["cs", "de", "es", "fr", "it", "ja", " */ export function validateLocaleAndSetLanguage( locale: string, - sys: { getExecutingFilePath(): string; resolvePath(path: string): string; fileExists(fileName: string): boolean; readFile(fileName: string): string | undefined; }, + sys: { + getExecutingFilePath(): string; + resolvePath(path: string): string; + fileExists(fileName: string): boolean; + readFile(fileName: string): string | undefined; + }, errors?: Diagnostic[], ) { const lowerCaseLocale = locale.toLowerCase(); @@ -629,7 +649,13 @@ export function validateLocaleAndSetLanguage( if (!matchResult) { if (errors) { - errors.push(createCompilerDiagnostic(Diagnostics.Locale_must_be_of_the_form_language_or_language_territory_For_example_0_or_1, "en", "ja-jp")); + errors.push( + createCompilerDiagnostic( + Diagnostics.Locale_must_be_of_the_form_language_or_language_territory_For_example_0_or_1, + "en", + "ja-jp", + ), + ); } return; } @@ -639,14 +665,21 @@ export function validateLocaleAndSetLanguage( // First try the entire locale, then fall back to just language if that's all we have. // Either ways do not fail, and fallback to the English diagnostic strings. - if (contains(supportedLocaleDirectories, lowerCaseLocale) && !trySetLanguageAndTerritory(language, territory, errors)) { + if ( + contains(supportedLocaleDirectories, lowerCaseLocale) + && !trySetLanguageAndTerritory(language, territory, errors) + ) { trySetLanguageAndTerritory(language, /*territory*/ undefined, errors); } // Set the UI locale for string collation setUILocale(locale); - function trySetLanguageAndTerritory(language: string, territory: string | undefined, errors?: Diagnostic[]): boolean { + function trySetLanguageAndTerritory( + language: string, + territory: string | undefined, + errors?: Diagnostic[], + ): boolean { const compilerFilePath = normalizePath(sys.getExecutingFilePath()); const containingDirectoryPath = getDirectoryPath(compilerFilePath); @@ -691,8 +724,14 @@ export function validateLocaleAndSetLanguage( export function getOriginalNode(node: Node): Node; export function getOriginalNode(node: Node, nodeTest: (node: Node) => node is T): T; export function getOriginalNode(node: Node | undefined): Node | undefined; -export function getOriginalNode(node: Node | undefined, nodeTest: (node: Node) => node is T): T | undefined; -export function getOriginalNode(node: Node | undefined, nodeTest?: (node: Node) => node is T): T | undefined { +export function getOriginalNode( + node: Node | undefined, + nodeTest: (node: Node) => node is T, +): T | undefined; +export function getOriginalNode( + node: Node | undefined, + nodeTest?: (node: Node) => node is T, +): T | undefined { if (node) { while (node.original !== undefined) { node = node.original; @@ -712,7 +751,10 @@ export function getOriginalNode(node: Node | undefined, nodeTest * If no such value is found, it applies the callback until the parent pointer is undefined or the callback returns "quit" * At that point findAncestor returns undefined. */ -export function findAncestor(node: Node | undefined, callback: (element: Node) => element is T): T | undefined; +export function findAncestor( + node: Node | undefined, + callback: (element: Node) => element is T, +): T | undefined; export function findAncestor(node: Node | undefined, callback: (element: Node) => boolean | "quit"): Node | undefined; export function findAncestor(node: Node | undefined, callback: (element: Node) => boolean | "quit"): Node | undefined { while (node) { @@ -752,7 +794,10 @@ export function getParseTreeNode(node: Node | undefined): Node | undefined; * @param nodeTest A callback used to ensure the correct type of parse tree node is returned. * @returns The original parse tree node if found; otherwise, undefined. */ -export function getParseTreeNode(node: T | undefined, nodeTest?: (node: Node) => node is T): T | undefined; +export function getParseTreeNode( + node: T | undefined, + nodeTest?: (node: Node) => node is T, +): T | undefined; export function getParseTreeNode(node: Node | undefined, nodeTest?: (node: Node) => boolean): Node | undefined { if (node === undefined || isParseTreeNode(node)) { return node; @@ -769,7 +814,8 @@ export function getParseTreeNode(node: Node | undefined, nodeTest?: (node: Node) /** Add an extra underscore to identifiers that start with two underscores to avoid issues with magic names like '__proto__' */ export function escapeLeadingUnderscores(identifier: string): __String { - return (identifier.length >= 2 && identifier.charCodeAt(0) === CharacterCodes._ && identifier.charCodeAt(1) === CharacterCodes._ ? "_" + identifier : identifier) as __String; + return (identifier.length >= 2 && identifier.charCodeAt(0) === CharacterCodes._ + && identifier.charCodeAt(1) === CharacterCodes._ ? "_" + identifier : identifier) as __String; } /** @@ -780,7 +826,8 @@ export function escapeLeadingUnderscores(identifier: string): __String { */ export function unescapeLeadingUnderscores(identifier: __String): string { const id = identifier as string; - return id.length >= 3 && id.charCodeAt(0) === CharacterCodes._ && id.charCodeAt(1) === CharacterCodes._ && id.charCodeAt(2) === CharacterCodes._ ? id.substr(1) : id; + return id.length >= 3 && id.charCodeAt(0) === CharacterCodes._ && id.charCodeAt(1) === CharacterCodes._ + && id.charCodeAt(2) === CharacterCodes._ ? id.substr(1) : id; } export function idText(identifierOrPrivateName: Identifier | PrivateIdentifier): string { @@ -808,7 +855,9 @@ export function symbolName(symbol: Symbol): string { * attempt to draw the name from the node the declaration is on (as that declaration is what its' symbol * will be merged with) */ -function nameForNamelessJSDocTypedef(declaration: JSDocTypedefTag | JSDocEnumTag): Identifier | PrivateIdentifier | undefined { +function nameForNamelessJSDocTypedef( + declaration: JSDocTypedefTag | JSDocEnumTag, +): Identifier | PrivateIdentifier | undefined { const hostNode = declaration.parent.parent; if (!hostNode) { return undefined; @@ -826,7 +875,10 @@ function nameForNamelessJSDocTypedef(declaration: JSDocTypedefTag | JSDocEnumTag break; case SyntaxKind.ExpressionStatement: let expr = hostNode.expression; - if (expr.kind === SyntaxKind.BinaryExpression && (expr as BinaryExpression).operatorToken.kind === SyntaxKind.EqualsToken) { + if ( + expr.kind === SyntaxKind.BinaryExpression + && (expr as BinaryExpression).operatorToken.kind === SyntaxKind.EqualsToken + ) { expr = (expr as BinaryExpression).left; } switch (expr.kind) { @@ -858,7 +910,10 @@ function getDeclarationIdentifier(node: Declaration | Expression): Identifier | /** @internal */ export function nodeHasName(statement: Node, name: Identifier) { - if (isNamedDeclaration(statement) && isIdentifier(statement.name) && idText(statement.name as Identifier) === idText(name)) { + if ( + isNamedDeclaration(statement) && isIdentifier(statement.name) + && idText(statement.name as Identifier) === idText(name) + ) { return true; } if (isVariableStatement(statement) && some(statement.declarationList.declarations, d => nodeHasName(d, name))) { @@ -897,7 +952,9 @@ export function getNonAssignedNameOfDeclaration(declaration: Declaration | Expre case AssignmentDeclarationKind.ThisProperty: case AssignmentDeclarationKind.Property: case AssignmentDeclarationKind.PrototypeProperty: - return getElementOrPropertyAccessArgumentExpressionOrName((expr as BinaryExpression).left as AccessExpression); + return getElementOrPropertyAccessArgumentExpressionOrName( + (expr as BinaryExpression).left as AccessExpression, + ); case AssignmentDeclarationKind.ObjectDefinePropertyValue: case AssignmentDeclarationKind.ObjectDefinePropertyExports: case AssignmentDeclarationKind.ObjectDefinePrototypeProperty: @@ -925,8 +982,9 @@ export function getNonAssignedNameOfDeclaration(declaration: Declaration | Expre export function getNameOfDeclaration(declaration: Declaration | Expression | undefined): DeclarationName | undefined { if (declaration === undefined) return undefined; - return getNonAssignedNameOfDeclaration(declaration) || - (isFunctionExpression(declaration) || isArrowFunction(declaration) || isClassExpression(declaration) ? getAssignedName(declaration) : undefined); + return getNonAssignedNameOfDeclaration(declaration) + || (isFunctionExpression(declaration) || isArrowFunction(declaration) || isClassExpression(declaration) + ? getAssignedName(declaration) : undefined); } /** @internal */ @@ -966,7 +1024,9 @@ function getJSDocParameterTagsWorker(param: ParameterDeclaration, noCache?: bool if (param.name) { if (isIdentifier(param.name)) { const name = param.name.escapedText; - return getJSDocTagsWorker(param.parent, noCache).filter((tag): tag is JSDocParameterTag => isJSDocParameterTag(tag) && isIdentifier(tag.name) && tag.name.escapedText === name); + return getJSDocTagsWorker(param.parent, noCache).filter((tag): tag is JSDocParameterTag => + isJSDocParameterTag(tag) && isIdentifier(tag.name) && tag.name.escapedText === name + ); } else { const i = param.parent.parameters.indexOf(param); @@ -1002,9 +1062,14 @@ export function getJSDocParameterTagsNoCache(param: ParameterDeclaration): reado return getJSDocParameterTagsWorker(param, /*noCache*/ true); } -function getJSDocTypeParameterTagsWorker(param: TypeParameterDeclaration, noCache?: boolean): readonly JSDocTemplateTag[] { +function getJSDocTypeParameterTagsWorker( + param: TypeParameterDeclaration, + noCache?: boolean, +): readonly JSDocTemplateTag[] { const name = param.name.escapedText; - return getJSDocTagsWorker(param.parent, noCache).filter((tag): tag is JSDocTemplateTag => isJSDocTemplateTag(tag) && tag.typeParameters.some(tp => tp.name.escapedText === name)); + return getJSDocTagsWorker(param.parent, noCache).filter((tag): tag is JSDocTemplateTag => + isJSDocTemplateTag(tag) && tag.typeParameters.some(tp => tp.name.escapedText === name) + ); } /** @@ -1210,7 +1275,11 @@ export function getJSDocTagsNoCache(node: Node): readonly JSDocTag[] { } /** Get the first JSDoc tag of a specified kind, or undefined if not present. */ -function getFirstJSDocTag(node: Node, predicate: (tag: JSDocTag) => tag is T, noCache?: boolean): T | undefined { +function getFirstJSDocTag( + node: Node, + predicate: (tag: JSDocTag) => tag is T, + noCache?: boolean, +): T | undefined { return find(getJSDocTagsWorker(node, noCache), predicate); } @@ -1249,7 +1318,9 @@ function formatJSDocLink(link: JSDocLink | JSDocLinkCode | JSDocLinkPlain) { * /** @type {Id} / * function id(x) { return x } */ -export function getEffectiveTypeParameterDeclarations(node: DeclarationWithTypeParameters): readonly TypeParameterDeclaration[] { +export function getEffectiveTypeParameterDeclarations( + node: DeclarationWithTypeParameters, +): readonly TypeParameterDeclaration[] { if (isJSDocSignature(node)) { if (isJSDocOverloadTag(node.parent)) { const jsDoc = getJSDocRoot(node.parent); @@ -1283,9 +1354,9 @@ export function getEffectiveTypeParameterDeclarations(node: DeclarationWithTypeP } export function getEffectiveConstraintOfTypeParameter(node: TypeParameterDeclaration): TypeNode | undefined { - return node.constraint ? node.constraint : - isJSDocTemplateTag(node.parent) && node === node.parent.typeParameters[0] ? node.parent.constraint : - undefined; + return node.constraint ? node.constraint + : isJSDocTemplateTag(node.parent) && node === node.parent.typeParameters[0] ? node.parent.constraint + : undefined; } // #region @@ -1311,10 +1382,12 @@ export function isCallChain(node: Node): node is CallChain { return isCallExpression(node) && !!(node.flags & NodeFlags.OptionalChain); } -export function isOptionalChain(node: Node): node is PropertyAccessChain | ElementAccessChain | CallChain | NonNullChain { +export function isOptionalChain( + node: Node, +): node is PropertyAccessChain | ElementAccessChain | CallChain | NonNullChain { const kind = node.kind; - return !!(node.flags & NodeFlags.OptionalChain) && - (kind === SyntaxKind.PropertyAccessExpression + return !!(node.flags & NodeFlags.OptionalChain) + && (kind === SyntaxKind.PropertyAccessExpression || kind === SyntaxKind.ElementAccessExpression || kind === SyntaxKind.CallExpression || kind === SyntaxKind.NonNullExpression); @@ -1354,12 +1427,13 @@ export function isOutermostOptionalChain(node: OptionalChain) { } export function isNullishCoalesce(node: Node) { - return node.kind === SyntaxKind.BinaryExpression && (node as BinaryExpression).operatorToken.kind === SyntaxKind.QuestionQuestionToken; + return node.kind === SyntaxKind.BinaryExpression + && (node as BinaryExpression).operatorToken.kind === SyntaxKind.QuestionQuestionToken; } export function isConstTypeReference(node: Node) { - return isTypeReferenceNode(node) && isIdentifier(node.typeName) && - node.typeName.escapedText === "const" && !node.typeArguments; + return isTypeReferenceNode(node) && isIdentifier(node.typeName) + && node.typeName.escapedText === "const" && !node.typeArguments; } export function skipPartiallyEmittedExpressions(node: Expression): Expression; @@ -1393,9 +1467,9 @@ export function isUnparsedTextLike(node: Node): node is UnparsedTextLike { /** @deprecated */ export function isUnparsedNode(node: Node): node is UnparsedNode { - return isUnparsedTextLike(node) || - node.kind === SyntaxKind.UnparsedPrologue || - node.kind === SyntaxKind.UnparsedSyntheticReference; + return isUnparsedTextLike(node) + || node.kind === SyntaxKind.UnparsedPrologue + || node.kind === SyntaxKind.UnparsedSyntheticReference; } export function isJSDocPropertyLikeTag(node: Node): node is JSDocPropertyLikeTag { @@ -1507,7 +1581,8 @@ export function isTypeOnlyExportDeclaration(node: Node): node is TypeOnlyExportD case SyntaxKind.ExportSpecifier: return (node as ExportSpecifier).isTypeOnly || (node as ExportSpecifier).parent.parent.isTypeOnly; case SyntaxKind.ExportDeclaration: - return (node as ExportDeclaration).isTypeOnly && !!(node as ExportDeclaration).moduleSpecifier && !(node as ExportDeclaration).exportClause; + return (node as ExportDeclaration).isTypeOnly && !!(node as ExportDeclaration).moduleSpecifier + && !(node as ExportDeclaration).exportClause; case SyntaxKind.NamespaceExport: return (node as NamespaceExport).parent.isTypeOnly; } @@ -1553,7 +1628,9 @@ export function isPrivateIdentifierClassElementDeclaration(node: Node): node is } /** @internal */ -export function isPrivateIdentifierPropertyAccessExpression(node: Node): node is PrivateIdentifierPropertyAccessExpression { +export function isPrivateIdentifierPropertyAccessExpression( + node: Node, +): node is PrivateIdentifierPropertyAccessExpression { return isPropertyAccessExpression(node) && isPrivateIdentifier(node.name); } @@ -1589,10 +1666,10 @@ export function isParameterPropertyModifier(kind: SyntaxKind): boolean { /** @internal */ export function isClassMemberModifier(idToken: SyntaxKind): boolean { - return isParameterPropertyModifier(idToken) || - idToken === SyntaxKind.StaticKeyword || - idToken === SyntaxKind.OverrideKeyword || - idToken === SyntaxKind.AccessorKeyword; + return isParameterPropertyModifier(idToken) + || idToken === SyntaxKind.StaticKeyword + || idToken === SyntaxKind.OverrideKeyword + || idToken === SyntaxKind.AccessorKeyword; } export function isModifier(node: Node): node is Modifier { @@ -1628,7 +1705,9 @@ export function isFunctionLike(node: Node | undefined): node is SignatureDeclara } /** @internal */ -export function isFunctionLikeOrClassStaticBlockDeclaration(node: Node | undefined): node is SignatureDeclaration | ClassStaticBlockDeclaration { +export function isFunctionLikeOrClassStaticBlockDeclaration( + node: Node | undefined, +): node is SignatureDeclaration | ClassStaticBlockDeclaration { return !!node && (isFunctionLikeKind(node.kind) || isClassStaticBlockDeclaration(node)); } @@ -1812,7 +1891,9 @@ export function isArrayBindingElement(node: Node): node is ArrayBindingElement { * * @internal */ -export function isDeclarationBindingElement(bindingElement: BindingOrAssignmentElement): bindingElement is VariableDeclaration | ParameterDeclaration | BindingElement { +export function isDeclarationBindingElement( + bindingElement: BindingOrAssignmentElement, +): bindingElement is VariableDeclaration | ParameterDeclaration | BindingElement { switch (bindingElement.kind) { case SyntaxKind.VariableDeclaration: case SyntaxKind.Parameter: @@ -1836,7 +1917,9 @@ export function isBindingOrAssignmentElement(node: Node): node is BindingOrAssig * * @internal */ -export function isBindingOrAssignmentPattern(node: BindingOrAssignmentElementTarget): node is BindingOrAssignmentPattern { +export function isBindingOrAssignmentPattern( + node: BindingOrAssignmentElementTarget, +): node is BindingOrAssignmentPattern { return isObjectBindingOrAssignmentPattern(node) || isArrayBindingOrAssignmentPattern(node); } @@ -1846,7 +1929,9 @@ export function isBindingOrAssignmentPattern(node: BindingOrAssignmentElementTar * * @internal */ -export function isObjectBindingOrAssignmentPattern(node: BindingOrAssignmentElementTarget): node is ObjectBindingOrAssignmentPattern { +export function isObjectBindingOrAssignmentPattern( + node: BindingOrAssignmentElementTarget, +): node is ObjectBindingOrAssignmentPattern { switch (node.kind) { case SyntaxKind.ObjectBindingPattern: case SyntaxKind.ObjectLiteralExpression: @@ -1873,7 +1958,9 @@ export function isObjectBindingOrAssignmentElement(node: Node): node is ObjectBi * * @internal */ -export function isArrayBindingOrAssignmentPattern(node: BindingOrAssignmentElementTarget): node is ArrayBindingOrAssignmentPattern { +export function isArrayBindingOrAssignmentPattern( + node: BindingOrAssignmentElementTarget, +): node is ArrayBindingOrAssignmentPattern { switch (node.kind) { case SyntaxKind.ArrayBindingPattern: case SyntaxKind.ArrayLiteralExpression: @@ -1900,7 +1987,9 @@ export function isArrayBindingOrAssignmentElement(node: Node): node is ArrayBind } /** @internal */ -export function isPropertyAccessOrQualifiedNameOrImportTypeNode(node: Node): node is PropertyAccessExpression | QualifiedName | ImportTypeNode { +export function isPropertyAccessOrQualifiedNameOrImportTypeNode( + node: Node, +): node is PropertyAccessExpression | QualifiedName | ImportTypeNode { const kind = node.kind; return kind === SyntaxKind.PropertyAccessExpression || kind === SyntaxKind.QualifiedName @@ -2008,14 +2097,16 @@ export function isUnaryExpressionWithWrite(expr: Node): expr is PrefixUnaryExpre case SyntaxKind.PostfixUnaryExpression: return true; case SyntaxKind.PrefixUnaryExpression: - return (expr as PrefixUnaryExpression).operator === SyntaxKind.PlusPlusToken || - (expr as PrefixUnaryExpression).operator === SyntaxKind.MinusMinusToken; + return (expr as PrefixUnaryExpression).operator === SyntaxKind.PlusPlusToken + || (expr as PrefixUnaryExpression).operator === SyntaxKind.MinusMinusToken; default: return false; } } -export function isLiteralTypeLiteral(node: Node): node is NullLiteral | BooleanLiteral | LiteralExpression | PrefixUnaryExpression { +export function isLiteralTypeLiteral( + node: Node, +): node is NullLiteral | BooleanLiteral | LiteralExpression | PrefixUnaryExpression { switch (node.kind) { case SyntaxKind.NullKeyword: case SyntaxKind.TrueKeyword: @@ -2059,7 +2150,9 @@ export function isAssertionExpression(node: Node): node is AssertionExpression { } /** @internal */ -export function isNotEmittedOrPartiallyEmittedNode(node: Node): node is NotEmittedStatement | PartiallyEmittedExpression { +export function isNotEmittedOrPartiallyEmittedNode( + node: Node, +): node is NotEmittedStatement | PartiallyEmittedExpression { return isNotEmittedStatement(node) || isPartiallyEmittedExpression(node); } @@ -2067,7 +2160,10 @@ export function isNotEmittedOrPartiallyEmittedNode(node: Node): node is NotEmitt // Statement export function isIterationStatement(node: Node, lookInLabeledStatements: false): node is IterationStatement; -export function isIterationStatement(node: Node, lookInLabeledStatements: boolean): node is IterationStatement | LabeledStatement; +export function isIterationStatement( + node: Node, + lookInLabeledStatements: boolean, +): node is IterationStatement | LabeledStatement; export function isIterationStatement(node: Node, lookInLabeledStatements: boolean): node is IterationStatement { switch (node.kind) { case SyntaxKind.ForStatement: @@ -2077,7 +2173,8 @@ export function isIterationStatement(node: Node, lookInLabeledStatements: boolea case SyntaxKind.WhileStatement: return true; case SyntaxKind.LabeledStatement: - return lookInLabeledStatements && isIterationStatement((node as LabeledStatement).statement, lookInLabeledStatements); + return lookInLabeledStatements + && isIterationStatement((node as LabeledStatement).statement, lookInLabeledStatements); } return false; @@ -2095,13 +2192,15 @@ export function hasScopeMarker(statements: readonly Statement[]) { /** @internal */ export function needsScopeMarker(result: Statement) { - return !isAnyImportOrReExport(result) && !isExportAssignment(result) && !hasSyntacticModifier(result, ModifierFlags.Export) && !isAmbientModule(result); + return !isAnyImportOrReExport(result) && !isExportAssignment(result) + && !hasSyntacticModifier(result, ModifierFlags.Export) && !isAmbientModule(result); } /** @internal */ export function isExternalModuleIndicator(result: Statement) { // Exported top-level member indicates moduleness - return isAnyImportOrReExport(result) || isExportAssignment(result) || hasSyntacticModifier(result, ModifierFlags.Export); + return isAnyImportOrReExport(result) || isExportAssignment(result) + || hasSyntacticModifier(result, ModifierFlags.Export); } /** @internal */ @@ -2537,7 +2636,8 @@ export function hasOnlyExpressionInitializer(node: Node): node is HasExpressionI } export function isObjectLiteralElement(node: Node): node is ObjectLiteralElement { - return node.kind === SyntaxKind.JsxAttribute || node.kind === SyntaxKind.JsxSpreadAttribute || isObjectLiteralElementLike(node); + return node.kind === SyntaxKind.JsxAttribute || node.kind === SyntaxKind.JsxSpreadAttribute + || isObjectLiteralElementLike(node); } /** @internal */ @@ -2570,11 +2670,13 @@ export function guessIndentation(lines: string[]) { } export function isStringLiteralLike(node: Node | FileReference): node is StringLiteralLike { - return (node as Node).kind === SyntaxKind.StringLiteral || (node as Node).kind === SyntaxKind.NoSubstitutionTemplateLiteral; + return (node as Node).kind === SyntaxKind.StringLiteral + || (node as Node).kind === SyntaxKind.NoSubstitutionTemplateLiteral; } export function isJSDocLinkLike(node: Node): node is JSDocLink | JSDocLinkCode | JSDocLinkPlain { - return node.kind === SyntaxKind.JSDocLink || node.kind === SyntaxKind.JSDocLinkCode || node.kind === SyntaxKind.JSDocLinkPlain; + return node.kind === SyntaxKind.JSDocLink || node.kind === SyntaxKind.JSDocLinkCode + || node.kind === SyntaxKind.JSDocLinkPlain; } export function hasRestParameter(s: SignatureDeclaration | JSDocSignature): boolean { @@ -2584,5 +2686,6 @@ export function hasRestParameter(s: SignatureDeclaration | JSDocSignature): bool export function isRestParameter(node: ParameterDeclaration | JSDocParameterTag): boolean { const type = isJSDocParameterTag(node) ? (node.typeExpression && node.typeExpression.type) : node.type; - return (node as ParameterDeclaration).dotDotDotToken !== undefined || !!type && type.kind === SyntaxKind.JSDocVariadicType; + return (node as ParameterDeclaration).dotDotDotToken !== undefined + || !!type && type.kind === SyntaxKind.JSDocVariadicType; } diff --git a/src/compiler/visitorPublic.ts b/src/compiler/visitorPublic.ts index 065c0eade9cfd..8e8a9e0086d83 100644 --- a/src/compiler/visitorPublic.ts +++ b/src/compiler/visitorPublic.ts @@ -377,7 +377,14 @@ function visitArrayWorker( * Starts a new lexical environment and visits a statement list, ending the lexical environment * and merging hoisted declarations upon completion. */ -export function visitLexicalEnvironment(statements: NodeArray, visitor: Visitor, context: TransformationContext, start?: number, ensureUseStrict?: boolean, nodesVisitor: NodesVisitor = visitNodes) { +export function visitLexicalEnvironment( + statements: NodeArray, + visitor: Visitor, + context: TransformationContext, + start?: number, + ensureUseStrict?: boolean, + nodesVisitor: NodesVisitor = visitNodes, +) { context.startLexicalEnvironment(); statements = nodesVisitor(statements, visitor, isStatement, start); if (ensureUseStrict) statements = context.factory.ensureUseStrict(statements); @@ -388,9 +395,24 @@ export function visitLexicalEnvironment(statements: NodeArray, visito * Starts a new lexical environment and visits a parameter list, suspending the lexical * environment upon completion. */ -export function visitParameterList(nodes: NodeArray, visitor: Visitor, context: TransformationContext, nodesVisitor?: NodesVisitor): NodeArray; -export function visitParameterList(nodes: NodeArray | undefined, visitor: Visitor, context: TransformationContext, nodesVisitor?: NodesVisitor): NodeArray | undefined; -export function visitParameterList(nodes: NodeArray | undefined, visitor: Visitor, context: TransformationContext, nodesVisitor = visitNodes) { +export function visitParameterList( + nodes: NodeArray, + visitor: Visitor, + context: TransformationContext, + nodesVisitor?: NodesVisitor, +): NodeArray; +export function visitParameterList( + nodes: NodeArray | undefined, + visitor: Visitor, + context: TransformationContext, + nodesVisitor?: NodesVisitor, +): NodeArray | undefined; +export function visitParameterList( + nodes: NodeArray | undefined, + visitor: Visitor, + context: TransformationContext, + nodesVisitor = visitNodes, +) { let updated: NodeArray | undefined; context.startLexicalEnvironment(); if (nodes) { @@ -404,8 +426,8 @@ export function visitParameterList(nodes: NodeArray | unde // in a parameter list to the body if we detect a variable being hoisted while visiting a parameter list // when the emit target is greater than ES2015. if ( - context.getLexicalEnvironmentFlags() & LexicalEnvironmentFlags.VariablesHoistedInParameters && - getEmitScriptTarget(context.getCompilerOptions()) >= ScriptTarget.ES2015 + context.getLexicalEnvironmentFlags() & LexicalEnvironmentFlags.VariablesHoistedInParameters + && getEmitScriptTarget(context.getCompilerOptions()) >= ScriptTarget.ES2015 ) { updated = addDefaultValueAssignmentsIfNeeded(updated, context); } @@ -415,7 +437,10 @@ export function visitParameterList(nodes: NodeArray | unde return updated; } -function addDefaultValueAssignmentsIfNeeded(parameters: NodeArray, context: TransformationContext) { +function addDefaultValueAssignmentsIfNeeded( + parameters: NodeArray, + context: TransformationContext, +) { let result: ParameterDeclaration[] | undefined; for (let i = 0; i < parameters.length; i++) { const parameter = parameters[i]; @@ -434,10 +459,11 @@ function addDefaultValueAssignmentsIfNeeded(parameters: NodeArray, visitor: Visitor, discardVisitor = visitor): NodeArray { +export function visitCommaListElements( + elements: NodeArray, + visitor: Visitor, + discardVisitor = visitor, +): NodeArray { if (discardVisitor === visitor || elements.length <= 1) { return visitNodes(elements, visitor, isExpression); } @@ -582,7 +671,14 @@ export function visitCommaListElements(elements: NodeArray, visitor: */ export function visitEachChild(node: T, visitor: Visitor, context: TransformationContext): T; /** @internal */ -export function visitEachChild(node: T, visitor: Visitor, context: TransformationContext, nodesVisitor?: NodesVisitor, tokenVisitor?: Visitor, nodeVisitor?: NodeVisitor): T; // eslint-disable-line @typescript-eslint/unified-signatures +export function visitEachChild( + node: T, + visitor: Visitor, + context: TransformationContext, + nodesVisitor?: NodesVisitor, + tokenVisitor?: Visitor, + nodeVisitor?: NodeVisitor, +): T; // eslint-disable-line @typescript-eslint/unified-signatures /** * Visits each child of a Node using the supplied visitor, possibly returning a new Node of the same kind in its place. * @@ -590,10 +686,30 @@ export function visitEachChild(node: T, visitor: Visitor, contex * @param visitor The callback used to visit each child. * @param context A lexical environment context for the visitor. */ -export function visitEachChild(node: T | undefined, visitor: Visitor, context: TransformationContext, nodesVisitor?: typeof visitNodes, tokenVisitor?: Visitor): T | undefined; +export function visitEachChild( + node: T | undefined, + visitor: Visitor, + context: TransformationContext, + nodesVisitor?: typeof visitNodes, + tokenVisitor?: Visitor, +): T | undefined; /** @internal */ -export function visitEachChild(node: T | undefined, visitor: Visitor, context: TransformationContext, nodesVisitor?: NodesVisitor, tokenVisitor?: Visitor, nodeVisitor?: NodeVisitor): T | undefined; -export function visitEachChild(node: T | undefined, visitor: Visitor, context: TransformationContext, nodesVisitor = visitNodes, tokenVisitor?: Visitor, nodeVisitor: NodeVisitor = visitNode): T | undefined { +export function visitEachChild( + node: T | undefined, + visitor: Visitor, + context: TransformationContext, + nodesVisitor?: NodesVisitor, + tokenVisitor?: Visitor, + nodeVisitor?: NodeVisitor, +): T | undefined; +export function visitEachChild( + node: T | undefined, + visitor: Visitor, + context: TransformationContext, + nodesVisitor = visitNodes, + tokenVisitor?: Visitor, + nodeVisitor: NodeVisitor = visitNode, +): T | undefined { if (node === undefined) { return undefined; } @@ -602,7 +718,14 @@ export function visitEachChild(node: T | undefined, visitor: Vis return fn === undefined ? node : fn(node, visitor, context, nodesVisitor, nodeVisitor, tokenVisitor); } -type VisitEachChildFunction = (node: T, visitor: Visitor, context: TransformationContext, nodesVisitor: NodesVisitor, nodeVisitor: NodeVisitor, tokenVisitor: Visitor | undefined) => T; +type VisitEachChildFunction = ( + node: T, + visitor: Visitor, + context: TransformationContext, + nodesVisitor: NodesVisitor, + nodeVisitor: NodeVisitor, + tokenVisitor: Visitor | undefined, +) => T; // A type that correlates a `SyntaxKind` to a `VisitEachChildFunction`, for nodes in the `HasChildren` union. // This looks something like: @@ -619,575 +742,2078 @@ type VisitEachChildTable = { [TNode in HasChildren as TNode["kind"]]: VisitEachC // NOTE: Before you can add a new method to `visitEachChildTable`, you must first ensure the `Node` subtype you // wish to add is defined in the `HasChildren` union in types.ts. const visitEachChildTable: VisitEachChildTable = { - [SyntaxKind.QualifiedName]: function visitEachChildOfQualifiedName(node, visitor, context, _nodesVisitor, nodeVisitor, _tokenVisitor) { - return context.factory.updateQualifiedName(node, Debug.checkDefined(nodeVisitor(node.left, visitor, isEntityName)), Debug.checkDefined(nodeVisitor(node.right, visitor, isIdentifier))); + [SyntaxKind.QualifiedName]: function visitEachChildOfQualifiedName( + node, + visitor, + context, + _nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updateQualifiedName( + node, + Debug.checkDefined(nodeVisitor(node.left, visitor, isEntityName)), + Debug.checkDefined(nodeVisitor(node.right, visitor, isIdentifier)), + ); }, - [SyntaxKind.ComputedPropertyName]: function visitEachChildOfComputedPropertyName(node, visitor, context, _nodesVisitor, nodeVisitor, _tokenVisitor) { - return context.factory.updateComputedPropertyName(node, Debug.checkDefined(nodeVisitor(node.expression, visitor, isExpression))); + [SyntaxKind.ComputedPropertyName]: function visitEachChildOfComputedPropertyName( + node, + visitor, + context, + _nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updateComputedPropertyName( + node, + Debug.checkDefined(nodeVisitor(node.expression, visitor, isExpression)), + ); }, // Signature elements - [SyntaxKind.TypeParameter]: function visitEachChildOfTypeParameterDeclaration(node, visitor, context, nodesVisitor, nodeVisitor, _tokenVisitor) { - return context.factory.updateTypeParameterDeclaration(node, nodesVisitor(node.modifiers, visitor, isModifier), Debug.checkDefined(nodeVisitor(node.name, visitor, isIdentifier)), nodeVisitor(node.constraint, visitor, isTypeNode), nodeVisitor(node.default, visitor, isTypeNode)); + [SyntaxKind.TypeParameter]: function visitEachChildOfTypeParameterDeclaration( + node, + visitor, + context, + nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updateTypeParameterDeclaration( + node, + nodesVisitor(node.modifiers, visitor, isModifier), + Debug.checkDefined(nodeVisitor(node.name, visitor, isIdentifier)), + nodeVisitor(node.constraint, visitor, isTypeNode), + nodeVisitor(node.default, visitor, isTypeNode), + ); }, - [SyntaxKind.Parameter]: function visitEachChildOfParameterDeclaration(node, visitor, context, nodesVisitor, nodeVisitor, tokenVisitor) { - return context.factory.updateParameterDeclaration(node, nodesVisitor(node.modifiers, visitor, isModifierLike), tokenVisitor ? nodeVisitor(node.dotDotDotToken, tokenVisitor, isDotDotDotToken) : node.dotDotDotToken, Debug.checkDefined(nodeVisitor(node.name, visitor, isBindingName)), tokenVisitor ? nodeVisitor(node.questionToken, tokenVisitor, isQuestionToken) : node.questionToken, nodeVisitor(node.type, visitor, isTypeNode), nodeVisitor(node.initializer, visitor, isExpression)); + [SyntaxKind.Parameter]: function visitEachChildOfParameterDeclaration( + node, + visitor, + context, + nodesVisitor, + nodeVisitor, + tokenVisitor, + ) { + return context.factory.updateParameterDeclaration( + node, + nodesVisitor(node.modifiers, visitor, isModifierLike), + tokenVisitor ? nodeVisitor(node.dotDotDotToken, tokenVisitor, isDotDotDotToken) : node.dotDotDotToken, + Debug.checkDefined(nodeVisitor(node.name, visitor, isBindingName)), + tokenVisitor ? nodeVisitor(node.questionToken, tokenVisitor, isQuestionToken) : node.questionToken, + nodeVisitor(node.type, visitor, isTypeNode), + nodeVisitor(node.initializer, visitor, isExpression), + ); }, - [SyntaxKind.Decorator]: function visitEachChildOfDecorator(node, visitor, context, _nodesVisitor, nodeVisitor, _tokenVisitor) { - return context.factory.updateDecorator(node, Debug.checkDefined(nodeVisitor(node.expression, visitor, isExpression))); + [SyntaxKind.Decorator]: function visitEachChildOfDecorator( + node, + visitor, + context, + _nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updateDecorator( + node, + Debug.checkDefined(nodeVisitor(node.expression, visitor, isExpression)), + ); }, // Type elements - [SyntaxKind.PropertySignature]: function visitEachChildOfPropertySignature(node, visitor, context, nodesVisitor, nodeVisitor, tokenVisitor) { - return context.factory.updatePropertySignature(node, nodesVisitor(node.modifiers, visitor, isModifier), Debug.checkDefined(nodeVisitor(node.name, visitor, isPropertyName)), tokenVisitor ? nodeVisitor(node.questionToken, tokenVisitor, isQuestionToken) : node.questionToken, nodeVisitor(node.type, visitor, isTypeNode)); + [SyntaxKind.PropertySignature]: function visitEachChildOfPropertySignature( + node, + visitor, + context, + nodesVisitor, + nodeVisitor, + tokenVisitor, + ) { + return context.factory.updatePropertySignature( + node, + nodesVisitor(node.modifiers, visitor, isModifier), + Debug.checkDefined(nodeVisitor(node.name, visitor, isPropertyName)), + tokenVisitor ? nodeVisitor(node.questionToken, tokenVisitor, isQuestionToken) : node.questionToken, + nodeVisitor(node.type, visitor, isTypeNode), + ); }, - [SyntaxKind.PropertyDeclaration]: function visitEachChildOfPropertyDeclaration(node, visitor, context, nodesVisitor, nodeVisitor, tokenVisitor) { + [SyntaxKind.PropertyDeclaration]: function visitEachChildOfPropertyDeclaration( + node, + visitor, + context, + nodesVisitor, + nodeVisitor, + tokenVisitor, + ) { return context.factory.updatePropertyDeclaration( node, nodesVisitor(node.modifiers, visitor, isModifierLike), Debug.checkDefined(nodeVisitor(node.name, visitor, isPropertyName)), // QuestionToken and ExclamationToken are mutually exclusive in PropertyDeclaration - tokenVisitor ? nodeVisitor(node.questionToken ?? node.exclamationToken, tokenVisitor, isQuestionOrExclamationToken) : node.questionToken ?? node.exclamationToken, + tokenVisitor + ? nodeVisitor(node.questionToken ?? node.exclamationToken, tokenVisitor, isQuestionOrExclamationToken) + : node.questionToken ?? node.exclamationToken, nodeVisitor(node.type, visitor, isTypeNode), nodeVisitor(node.initializer, visitor, isExpression), ); }, - [SyntaxKind.MethodSignature]: function visitEachChildOfMethodSignature(node, visitor, context, nodesVisitor, nodeVisitor, tokenVisitor) { - return context.factory.updateMethodSignature(node, nodesVisitor(node.modifiers, visitor, isModifier), Debug.checkDefined(nodeVisitor(node.name, visitor, isPropertyName)), tokenVisitor ? nodeVisitor(node.questionToken, tokenVisitor, isQuestionToken) : node.questionToken, nodesVisitor(node.typeParameters, visitor, isTypeParameterDeclaration), nodesVisitor(node.parameters, visitor, isParameter), nodeVisitor(node.type, visitor, isTypeNode)); + [SyntaxKind.MethodSignature]: function visitEachChildOfMethodSignature( + node, + visitor, + context, + nodesVisitor, + nodeVisitor, + tokenVisitor, + ) { + return context.factory.updateMethodSignature( + node, + nodesVisitor(node.modifiers, visitor, isModifier), + Debug.checkDefined(nodeVisitor(node.name, visitor, isPropertyName)), + tokenVisitor ? nodeVisitor(node.questionToken, tokenVisitor, isQuestionToken) : node.questionToken, + nodesVisitor(node.typeParameters, visitor, isTypeParameterDeclaration), + nodesVisitor(node.parameters, visitor, isParameter), + nodeVisitor(node.type, visitor, isTypeNode), + ); }, - [SyntaxKind.MethodDeclaration]: function visitEachChildOfMethodDeclaration(node, visitor, context, nodesVisitor, nodeVisitor, tokenVisitor) { - return context.factory.updateMethodDeclaration(node, nodesVisitor(node.modifiers, visitor, isModifierLike), tokenVisitor ? nodeVisitor(node.asteriskToken, tokenVisitor, isAsteriskToken) : node.asteriskToken, Debug.checkDefined(nodeVisitor(node.name, visitor, isPropertyName)), tokenVisitor ? nodeVisitor(node.questionToken, tokenVisitor, isQuestionToken) : node.questionToken, nodesVisitor(node.typeParameters, visitor, isTypeParameterDeclaration), visitParameterList(node.parameters, visitor, context, nodesVisitor), nodeVisitor(node.type, visitor, isTypeNode), visitFunctionBody(node.body!, visitor, context, nodeVisitor)); + [SyntaxKind.MethodDeclaration]: function visitEachChildOfMethodDeclaration( + node, + visitor, + context, + nodesVisitor, + nodeVisitor, + tokenVisitor, + ) { + return context.factory.updateMethodDeclaration( + node, + nodesVisitor(node.modifiers, visitor, isModifierLike), + tokenVisitor ? nodeVisitor(node.asteriskToken, tokenVisitor, isAsteriskToken) : node.asteriskToken, + Debug.checkDefined(nodeVisitor(node.name, visitor, isPropertyName)), + tokenVisitor ? nodeVisitor(node.questionToken, tokenVisitor, isQuestionToken) : node.questionToken, + nodesVisitor(node.typeParameters, visitor, isTypeParameterDeclaration), + visitParameterList(node.parameters, visitor, context, nodesVisitor), + nodeVisitor(node.type, visitor, isTypeNode), + visitFunctionBody(node.body!, visitor, context, nodeVisitor), + ); }, - [SyntaxKind.Constructor]: function visitEachChildOfConstructorDeclaration(node, visitor, context, nodesVisitor, nodeVisitor, _tokenVisitor) { - return context.factory.updateConstructorDeclaration(node, nodesVisitor(node.modifiers, visitor, isModifierLike), visitParameterList(node.parameters, visitor, context, nodesVisitor), visitFunctionBody(node.body!, visitor, context, nodeVisitor)); + [SyntaxKind.Constructor]: function visitEachChildOfConstructorDeclaration( + node, + visitor, + context, + nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updateConstructorDeclaration( + node, + nodesVisitor(node.modifiers, visitor, isModifierLike), + visitParameterList(node.parameters, visitor, context, nodesVisitor), + visitFunctionBody(node.body!, visitor, context, nodeVisitor), + ); }, - [SyntaxKind.GetAccessor]: function visitEachChildOfGetAccessorDeclaration(node, visitor, context, nodesVisitor, nodeVisitor, _tokenVisitor) { - return context.factory.updateGetAccessorDeclaration(node, nodesVisitor(node.modifiers, visitor, isModifierLike), Debug.checkDefined(nodeVisitor(node.name, visitor, isPropertyName)), visitParameterList(node.parameters, visitor, context, nodesVisitor), nodeVisitor(node.type, visitor, isTypeNode), visitFunctionBody(node.body!, visitor, context, nodeVisitor)); + [SyntaxKind.GetAccessor]: function visitEachChildOfGetAccessorDeclaration( + node, + visitor, + context, + nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updateGetAccessorDeclaration( + node, + nodesVisitor(node.modifiers, visitor, isModifierLike), + Debug.checkDefined(nodeVisitor(node.name, visitor, isPropertyName)), + visitParameterList(node.parameters, visitor, context, nodesVisitor), + nodeVisitor(node.type, visitor, isTypeNode), + visitFunctionBody(node.body!, visitor, context, nodeVisitor), + ); }, - [SyntaxKind.SetAccessor]: function visitEachChildOfSetAccessorDeclaration(node, visitor, context, nodesVisitor, nodeVisitor, _tokenVisitor) { - return context.factory.updateSetAccessorDeclaration(node, nodesVisitor(node.modifiers, visitor, isModifierLike), Debug.checkDefined(nodeVisitor(node.name, visitor, isPropertyName)), visitParameterList(node.parameters, visitor, context, nodesVisitor), visitFunctionBody(node.body!, visitor, context, nodeVisitor)); + [SyntaxKind.SetAccessor]: function visitEachChildOfSetAccessorDeclaration( + node, + visitor, + context, + nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updateSetAccessorDeclaration( + node, + nodesVisitor(node.modifiers, visitor, isModifierLike), + Debug.checkDefined(nodeVisitor(node.name, visitor, isPropertyName)), + visitParameterList(node.parameters, visitor, context, nodesVisitor), + visitFunctionBody(node.body!, visitor, context, nodeVisitor), + ); }, - [SyntaxKind.ClassStaticBlockDeclaration]: function visitEachChildOfClassStaticBlockDeclaration(node, visitor, context, _nodesVisitor, nodeVisitor, _tokenVisitor) { + [SyntaxKind.ClassStaticBlockDeclaration]: function visitEachChildOfClassStaticBlockDeclaration( + node, + visitor, + context, + _nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { context.startLexicalEnvironment(); context.suspendLexicalEnvironment(); - return context.factory.updateClassStaticBlockDeclaration(node, visitFunctionBody(node.body, visitor, context, nodeVisitor)); + return context.factory.updateClassStaticBlockDeclaration( + node, + visitFunctionBody(node.body, visitor, context, nodeVisitor), + ); }, - [SyntaxKind.CallSignature]: function visitEachChildOfCallSignatureDeclaration(node, visitor, context, nodesVisitor, nodeVisitor, _tokenVisitor) { - return context.factory.updateCallSignature(node, nodesVisitor(node.typeParameters, visitor, isTypeParameterDeclaration), nodesVisitor(node.parameters, visitor, isParameter), nodeVisitor(node.type, visitor, isTypeNode)); + [SyntaxKind.CallSignature]: function visitEachChildOfCallSignatureDeclaration( + node, + visitor, + context, + nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updateCallSignature( + node, + nodesVisitor(node.typeParameters, visitor, isTypeParameterDeclaration), + nodesVisitor(node.parameters, visitor, isParameter), + nodeVisitor(node.type, visitor, isTypeNode), + ); }, - [SyntaxKind.ConstructSignature]: function visitEachChildOfConstructSignatureDeclaration(node, visitor, context, nodesVisitor, nodeVisitor, _tokenVisitor) { - return context.factory.updateConstructSignature(node, nodesVisitor(node.typeParameters, visitor, isTypeParameterDeclaration), nodesVisitor(node.parameters, visitor, isParameter), nodeVisitor(node.type, visitor, isTypeNode)); + [SyntaxKind.ConstructSignature]: function visitEachChildOfConstructSignatureDeclaration( + node, + visitor, + context, + nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updateConstructSignature( + node, + nodesVisitor(node.typeParameters, visitor, isTypeParameterDeclaration), + nodesVisitor(node.parameters, visitor, isParameter), + nodeVisitor(node.type, visitor, isTypeNode), + ); }, - [SyntaxKind.IndexSignature]: function visitEachChildOfIndexSignatureDeclaration(node, visitor, context, nodesVisitor, nodeVisitor, _tokenVisitor) { - return context.factory.updateIndexSignature(node, nodesVisitor(node.modifiers, visitor, isModifierLike), nodesVisitor(node.parameters, visitor, isParameter), Debug.checkDefined(nodeVisitor(node.type, visitor, isTypeNode))); + [SyntaxKind.IndexSignature]: function visitEachChildOfIndexSignatureDeclaration( + node, + visitor, + context, + nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updateIndexSignature( + node, + nodesVisitor(node.modifiers, visitor, isModifierLike), + nodesVisitor(node.parameters, visitor, isParameter), + Debug.checkDefined(nodeVisitor(node.type, visitor, isTypeNode)), + ); }, // Types - [SyntaxKind.TypePredicate]: function visitEachChildOfTypePredicateNode(node, visitor, context, _nodesVisitor, nodeVisitor, _tokenVisitor) { - return context.factory.updateTypePredicateNode(node, nodeVisitor(node.assertsModifier, visitor, isAssertsKeyword), Debug.checkDefined(nodeVisitor(node.parameterName, visitor, isIdentifierOrThisTypeNode)), nodeVisitor(node.type, visitor, isTypeNode)); + [SyntaxKind.TypePredicate]: function visitEachChildOfTypePredicateNode( + node, + visitor, + context, + _nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updateTypePredicateNode( + node, + nodeVisitor(node.assertsModifier, visitor, isAssertsKeyword), + Debug.checkDefined(nodeVisitor(node.parameterName, visitor, isIdentifierOrThisTypeNode)), + nodeVisitor(node.type, visitor, isTypeNode), + ); }, - [SyntaxKind.TypeReference]: function visitEachChildOfTypeReferenceNode(node, visitor, context, nodesVisitor, nodeVisitor, _tokenVisitor) { - return context.factory.updateTypeReferenceNode(node, Debug.checkDefined(nodeVisitor(node.typeName, visitor, isEntityName)), nodesVisitor(node.typeArguments, visitor, isTypeNode)); + [SyntaxKind.TypeReference]: function visitEachChildOfTypeReferenceNode( + node, + visitor, + context, + nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updateTypeReferenceNode( + node, + Debug.checkDefined(nodeVisitor(node.typeName, visitor, isEntityName)), + nodesVisitor(node.typeArguments, visitor, isTypeNode), + ); }, - [SyntaxKind.FunctionType]: function visitEachChildOfFunctionTypeNode(node, visitor, context, nodesVisitor, nodeVisitor, _tokenVisitor) { - return context.factory.updateFunctionTypeNode(node, nodesVisitor(node.typeParameters, visitor, isTypeParameterDeclaration), nodesVisitor(node.parameters, visitor, isParameter), Debug.checkDefined(nodeVisitor(node.type, visitor, isTypeNode))); + [SyntaxKind.FunctionType]: function visitEachChildOfFunctionTypeNode( + node, + visitor, + context, + nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updateFunctionTypeNode( + node, + nodesVisitor(node.typeParameters, visitor, isTypeParameterDeclaration), + nodesVisitor(node.parameters, visitor, isParameter), + Debug.checkDefined(nodeVisitor(node.type, visitor, isTypeNode)), + ); }, - [SyntaxKind.ConstructorType]: function visitEachChildOfConstructorTypeNode(node, visitor, context, nodesVisitor, nodeVisitor, _tokenVisitor) { - return context.factory.updateConstructorTypeNode(node, nodesVisitor(node.modifiers, visitor, isModifier), nodesVisitor(node.typeParameters, visitor, isTypeParameterDeclaration), nodesVisitor(node.parameters, visitor, isParameter), Debug.checkDefined(nodeVisitor(node.type, visitor, isTypeNode))); + [SyntaxKind.ConstructorType]: function visitEachChildOfConstructorTypeNode( + node, + visitor, + context, + nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updateConstructorTypeNode( + node, + nodesVisitor(node.modifiers, visitor, isModifier), + nodesVisitor(node.typeParameters, visitor, isTypeParameterDeclaration), + nodesVisitor(node.parameters, visitor, isParameter), + Debug.checkDefined(nodeVisitor(node.type, visitor, isTypeNode)), + ); }, - [SyntaxKind.TypeQuery]: function visitEachChildOfTypeQueryNode(node, visitor, context, nodesVisitor, nodeVisitor, _tokenVisitor) { - return context.factory.updateTypeQueryNode(node, Debug.checkDefined(nodeVisitor(node.exprName, visitor, isEntityName)), nodesVisitor(node.typeArguments, visitor, isTypeNode)); + [SyntaxKind.TypeQuery]: function visitEachChildOfTypeQueryNode( + node, + visitor, + context, + nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updateTypeQueryNode( + node, + Debug.checkDefined(nodeVisitor(node.exprName, visitor, isEntityName)), + nodesVisitor(node.typeArguments, visitor, isTypeNode), + ); }, - [SyntaxKind.TypeLiteral]: function visitEachChildOfTypeLiteralNode(node, visitor, context, nodesVisitor, _nodeVisitor, _tokenVisitor) { + [SyntaxKind.TypeLiteral]: function visitEachChildOfTypeLiteralNode( + node, + visitor, + context, + nodesVisitor, + _nodeVisitor, + _tokenVisitor, + ) { return context.factory.updateTypeLiteralNode(node, nodesVisitor(node.members, visitor, isTypeElement)); }, - [SyntaxKind.ArrayType]: function visitEachChildOfArrayTypeNode(node, visitor, context, _nodesVisitor, nodeVisitor, _tokenVisitor) { - return context.factory.updateArrayTypeNode(node, Debug.checkDefined(nodeVisitor(node.elementType, visitor, isTypeNode))); + [SyntaxKind.ArrayType]: function visitEachChildOfArrayTypeNode( + node, + visitor, + context, + _nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updateArrayTypeNode( + node, + Debug.checkDefined(nodeVisitor(node.elementType, visitor, isTypeNode)), + ); }, - [SyntaxKind.TupleType]: function visitEachChildOfTupleTypeNode(node, visitor, context, nodesVisitor, _nodeVisitor, _tokenVisitor) { + [SyntaxKind.TupleType]: function visitEachChildOfTupleTypeNode( + node, + visitor, + context, + nodesVisitor, + _nodeVisitor, + _tokenVisitor, + ) { return context.factory.updateTupleTypeNode(node, nodesVisitor(node.elements, visitor, isTypeNode)); }, - [SyntaxKind.OptionalType]: function visitEachChildOfOptionalTypeNode(node, visitor, context, _nodesVisitor, nodeVisitor, _tokenVisitor) { - return context.factory.updateOptionalTypeNode(node, Debug.checkDefined(nodeVisitor(node.type, visitor, isTypeNode))); + [SyntaxKind.OptionalType]: function visitEachChildOfOptionalTypeNode( + node, + visitor, + context, + _nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updateOptionalTypeNode( + node, + Debug.checkDefined(nodeVisitor(node.type, visitor, isTypeNode)), + ); }, - [SyntaxKind.RestType]: function visitEachChildOfRestTypeNode(node, visitor, context, _nodesVisitor, nodeVisitor, _tokenVisitor) { - return context.factory.updateRestTypeNode(node, Debug.checkDefined(nodeVisitor(node.type, visitor, isTypeNode))); + [SyntaxKind.RestType]: function visitEachChildOfRestTypeNode( + node, + visitor, + context, + _nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updateRestTypeNode( + node, + Debug.checkDefined(nodeVisitor(node.type, visitor, isTypeNode)), + ); }, - [SyntaxKind.UnionType]: function visitEachChildOfUnionTypeNode(node, visitor, context, nodesVisitor, _nodeVisitor, _tokenVisitor) { + [SyntaxKind.UnionType]: function visitEachChildOfUnionTypeNode( + node, + visitor, + context, + nodesVisitor, + _nodeVisitor, + _tokenVisitor, + ) { return context.factory.updateUnionTypeNode(node, nodesVisitor(node.types, visitor, isTypeNode)); }, - [SyntaxKind.IntersectionType]: function visitEachChildOfIntersectionTypeNode(node, visitor, context, nodesVisitor, _nodeVisitor, _tokenVisitor) { + [SyntaxKind.IntersectionType]: function visitEachChildOfIntersectionTypeNode( + node, + visitor, + context, + nodesVisitor, + _nodeVisitor, + _tokenVisitor, + ) { return context.factory.updateIntersectionTypeNode(node, nodesVisitor(node.types, visitor, isTypeNode)); }, - [SyntaxKind.ConditionalType]: function visitEachChildOfConditionalTypeNode(node, visitor, context, _nodesVisitor, nodeVisitor, _tokenVisitor) { - return context.factory.updateConditionalTypeNode(node, Debug.checkDefined(nodeVisitor(node.checkType, visitor, isTypeNode)), Debug.checkDefined(nodeVisitor(node.extendsType, visitor, isTypeNode)), Debug.checkDefined(nodeVisitor(node.trueType, visitor, isTypeNode)), Debug.checkDefined(nodeVisitor(node.falseType, visitor, isTypeNode))); + [SyntaxKind.ConditionalType]: function visitEachChildOfConditionalTypeNode( + node, + visitor, + context, + _nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updateConditionalTypeNode( + node, + Debug.checkDefined(nodeVisitor(node.checkType, visitor, isTypeNode)), + Debug.checkDefined(nodeVisitor(node.extendsType, visitor, isTypeNode)), + Debug.checkDefined(nodeVisitor(node.trueType, visitor, isTypeNode)), + Debug.checkDefined(nodeVisitor(node.falseType, visitor, isTypeNode)), + ); }, - [SyntaxKind.InferType]: function visitEachChildOfInferTypeNode(node, visitor, context, _nodesVisitor, nodeVisitor, _tokenVisitor) { - return context.factory.updateInferTypeNode(node, Debug.checkDefined(nodeVisitor(node.typeParameter, visitor, isTypeParameterDeclaration))); + [SyntaxKind.InferType]: function visitEachChildOfInferTypeNode( + node, + visitor, + context, + _nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updateInferTypeNode( + node, + Debug.checkDefined(nodeVisitor(node.typeParameter, visitor, isTypeParameterDeclaration)), + ); }, - [SyntaxKind.ImportType]: function visitEachChildOfImportTypeNode(node, visitor, context, nodesVisitor, nodeVisitor, _tokenVisitor) { - return context.factory.updateImportTypeNode(node, Debug.checkDefined(nodeVisitor(node.argument, visitor, isTypeNode)), nodeVisitor(node.assertions, visitor, isImportTypeAssertionContainer), nodeVisitor(node.qualifier, visitor, isEntityName), nodesVisitor(node.typeArguments, visitor, isTypeNode), node.isTypeOf); + [SyntaxKind.ImportType]: function visitEachChildOfImportTypeNode( + node, + visitor, + context, + nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updateImportTypeNode( + node, + Debug.checkDefined(nodeVisitor(node.argument, visitor, isTypeNode)), + nodeVisitor(node.assertions, visitor, isImportTypeAssertionContainer), + nodeVisitor(node.qualifier, visitor, isEntityName), + nodesVisitor(node.typeArguments, visitor, isTypeNode), + node.isTypeOf, + ); }, - [SyntaxKind.ImportTypeAssertionContainer]: function visitEachChildOfImportTypeAssertionContainer(node, visitor, context, _nodesVisitor, nodeVisitor, _tokenVisitor) { - return context.factory.updateImportTypeAssertionContainer(node, Debug.checkDefined(nodeVisitor(node.assertClause, visitor, isAssertClause)), node.multiLine); + [SyntaxKind.ImportTypeAssertionContainer]: function visitEachChildOfImportTypeAssertionContainer( + node, + visitor, + context, + _nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updateImportTypeAssertionContainer( + node, + Debug.checkDefined(nodeVisitor(node.assertClause, visitor, isAssertClause)), + node.multiLine, + ); }, - [SyntaxKind.NamedTupleMember]: function visitEachChildOfNamedTupleMember(node, visitor, context, _nodesVisitor, nodeVisitor, tokenVisitor) { - return context.factory.updateNamedTupleMember(node, tokenVisitor ? nodeVisitor(node.dotDotDotToken, tokenVisitor, isDotDotDotToken) : node.dotDotDotToken, Debug.checkDefined(nodeVisitor(node.name, visitor, isIdentifier)), tokenVisitor ? nodeVisitor(node.questionToken, tokenVisitor, isQuestionToken) : node.questionToken, Debug.checkDefined(nodeVisitor(node.type, visitor, isTypeNode))); + [SyntaxKind.NamedTupleMember]: function visitEachChildOfNamedTupleMember( + node, + visitor, + context, + _nodesVisitor, + nodeVisitor, + tokenVisitor, + ) { + return context.factory.updateNamedTupleMember( + node, + tokenVisitor ? nodeVisitor(node.dotDotDotToken, tokenVisitor, isDotDotDotToken) : node.dotDotDotToken, + Debug.checkDefined(nodeVisitor(node.name, visitor, isIdentifier)), + tokenVisitor ? nodeVisitor(node.questionToken, tokenVisitor, isQuestionToken) : node.questionToken, + Debug.checkDefined(nodeVisitor(node.type, visitor, isTypeNode)), + ); }, - [SyntaxKind.ParenthesizedType]: function visitEachChildOfParenthesizedType(node, visitor, context, _nodesVisitor, nodeVisitor, _tokenVisitor) { - return context.factory.updateParenthesizedType(node, Debug.checkDefined(nodeVisitor(node.type, visitor, isTypeNode))); + [SyntaxKind.ParenthesizedType]: function visitEachChildOfParenthesizedType( + node, + visitor, + context, + _nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updateParenthesizedType( + node, + Debug.checkDefined(nodeVisitor(node.type, visitor, isTypeNode)), + ); }, - [SyntaxKind.TypeOperator]: function visitEachChildOfTypeOperatorNode(node, visitor, context, _nodesVisitor, nodeVisitor, _tokenVisitor) { - return context.factory.updateTypeOperatorNode(node, Debug.checkDefined(nodeVisitor(node.type, visitor, isTypeNode))); + [SyntaxKind.TypeOperator]: function visitEachChildOfTypeOperatorNode( + node, + visitor, + context, + _nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updateTypeOperatorNode( + node, + Debug.checkDefined(nodeVisitor(node.type, visitor, isTypeNode)), + ); }, - [SyntaxKind.IndexedAccessType]: function visitEachChildOfIndexedAccessType(node, visitor, context, _nodesVisitor, nodeVisitor, _tokenVisitor) { - return context.factory.updateIndexedAccessTypeNode(node, Debug.checkDefined(nodeVisitor(node.objectType, visitor, isTypeNode)), Debug.checkDefined(nodeVisitor(node.indexType, visitor, isTypeNode))); + [SyntaxKind.IndexedAccessType]: function visitEachChildOfIndexedAccessType( + node, + visitor, + context, + _nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updateIndexedAccessTypeNode( + node, + Debug.checkDefined(nodeVisitor(node.objectType, visitor, isTypeNode)), + Debug.checkDefined(nodeVisitor(node.indexType, visitor, isTypeNode)), + ); }, - [SyntaxKind.MappedType]: function visitEachChildOfMappedType(node, visitor, context, nodesVisitor, nodeVisitor, tokenVisitor) { - return context.factory.updateMappedTypeNode(node, tokenVisitor ? nodeVisitor(node.readonlyToken, tokenVisitor, isReadonlyKeywordOrPlusOrMinusToken) : node.readonlyToken, Debug.checkDefined(nodeVisitor(node.typeParameter, visitor, isTypeParameterDeclaration)), nodeVisitor(node.nameType, visitor, isTypeNode), tokenVisitor ? nodeVisitor(node.questionToken, tokenVisitor, isQuestionOrPlusOrMinusToken) : node.questionToken, nodeVisitor(node.type, visitor, isTypeNode), nodesVisitor(node.members, visitor, isTypeElement)); + [SyntaxKind.MappedType]: function visitEachChildOfMappedType( + node, + visitor, + context, + nodesVisitor, + nodeVisitor, + tokenVisitor, + ) { + return context.factory.updateMappedTypeNode( + node, + tokenVisitor ? nodeVisitor(node.readonlyToken, tokenVisitor, isReadonlyKeywordOrPlusOrMinusToken) + : node.readonlyToken, + Debug.checkDefined(nodeVisitor(node.typeParameter, visitor, isTypeParameterDeclaration)), + nodeVisitor(node.nameType, visitor, isTypeNode), + tokenVisitor ? nodeVisitor(node.questionToken, tokenVisitor, isQuestionOrPlusOrMinusToken) + : node.questionToken, + nodeVisitor(node.type, visitor, isTypeNode), + nodesVisitor(node.members, visitor, isTypeElement), + ); }, - [SyntaxKind.LiteralType]: function visitEachChildOfLiteralTypeNode(node, visitor, context, _nodesVisitor, nodeVisitor, _tokenVisitor) { - return context.factory.updateLiteralTypeNode(node, Debug.checkDefined(nodeVisitor(node.literal, visitor, isLiteralTypeLiteral))); + [SyntaxKind.LiteralType]: function visitEachChildOfLiteralTypeNode( + node, + visitor, + context, + _nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updateLiteralTypeNode( + node, + Debug.checkDefined(nodeVisitor(node.literal, visitor, isLiteralTypeLiteral)), + ); }, - [SyntaxKind.TemplateLiteralType]: function visitEachChildOfTemplateLiteralType(node, visitor, context, nodesVisitor, nodeVisitor, _tokenVisitor) { - return context.factory.updateTemplateLiteralType(node, Debug.checkDefined(nodeVisitor(node.head, visitor, isTemplateHead)), nodesVisitor(node.templateSpans, visitor, isTemplateLiteralTypeSpan)); + [SyntaxKind.TemplateLiteralType]: function visitEachChildOfTemplateLiteralType( + node, + visitor, + context, + nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updateTemplateLiteralType( + node, + Debug.checkDefined(nodeVisitor(node.head, visitor, isTemplateHead)), + nodesVisitor(node.templateSpans, visitor, isTemplateLiteralTypeSpan), + ); }, - [SyntaxKind.TemplateLiteralTypeSpan]: function visitEachChildOfTemplateLiteralTypeSpan(node, visitor, context, _nodesVisitor, nodeVisitor, _tokenVisitor) { - return context.factory.updateTemplateLiteralTypeSpan(node, Debug.checkDefined(nodeVisitor(node.type, visitor, isTypeNode)), Debug.checkDefined(nodeVisitor(node.literal, visitor, isTemplateMiddleOrTemplateTail))); + [SyntaxKind.TemplateLiteralTypeSpan]: function visitEachChildOfTemplateLiteralTypeSpan( + node, + visitor, + context, + _nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updateTemplateLiteralTypeSpan( + node, + Debug.checkDefined(nodeVisitor(node.type, visitor, isTypeNode)), + Debug.checkDefined(nodeVisitor(node.literal, visitor, isTemplateMiddleOrTemplateTail)), + ); }, // Binding patterns - [SyntaxKind.ObjectBindingPattern]: function visitEachChildOfObjectBindingPattern(node, visitor, context, nodesVisitor, _nodeVisitor, _tokenVisitor) { + [SyntaxKind.ObjectBindingPattern]: function visitEachChildOfObjectBindingPattern( + node, + visitor, + context, + nodesVisitor, + _nodeVisitor, + _tokenVisitor, + ) { return context.factory.updateObjectBindingPattern(node, nodesVisitor(node.elements, visitor, isBindingElement)); }, - [SyntaxKind.ArrayBindingPattern]: function visitEachChildOfArrayBindingPattern(node, visitor, context, nodesVisitor, _nodeVisitor, _tokenVisitor) { - return context.factory.updateArrayBindingPattern(node, nodesVisitor(node.elements, visitor, isArrayBindingElement)); + [SyntaxKind.ArrayBindingPattern]: function visitEachChildOfArrayBindingPattern( + node, + visitor, + context, + nodesVisitor, + _nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updateArrayBindingPattern( + node, + nodesVisitor(node.elements, visitor, isArrayBindingElement), + ); }, - [SyntaxKind.BindingElement]: function visitEachChildOfBindingElement(node, visitor, context, _nodesVisitor, nodeVisitor, tokenVisitor) { - return context.factory.updateBindingElement(node, tokenVisitor ? nodeVisitor(node.dotDotDotToken, tokenVisitor, isDotDotDotToken) : node.dotDotDotToken, nodeVisitor(node.propertyName, visitor, isPropertyName), Debug.checkDefined(nodeVisitor(node.name, visitor, isBindingName)), nodeVisitor(node.initializer, visitor, isExpression)); + [SyntaxKind.BindingElement]: function visitEachChildOfBindingElement( + node, + visitor, + context, + _nodesVisitor, + nodeVisitor, + tokenVisitor, + ) { + return context.factory.updateBindingElement( + node, + tokenVisitor ? nodeVisitor(node.dotDotDotToken, tokenVisitor, isDotDotDotToken) : node.dotDotDotToken, + nodeVisitor(node.propertyName, visitor, isPropertyName), + Debug.checkDefined(nodeVisitor(node.name, visitor, isBindingName)), + nodeVisitor(node.initializer, visitor, isExpression), + ); }, // Expression - [SyntaxKind.ArrayLiteralExpression]: function visitEachChildOfArrayLiteralExpression(node, visitor, context, nodesVisitor, _nodeVisitor, _tokenVisitor) { + [SyntaxKind.ArrayLiteralExpression]: function visitEachChildOfArrayLiteralExpression( + node, + visitor, + context, + nodesVisitor, + _nodeVisitor, + _tokenVisitor, + ) { return context.factory.updateArrayLiteralExpression(node, nodesVisitor(node.elements, visitor, isExpression)); }, - [SyntaxKind.ObjectLiteralExpression]: function visitEachChildOfObjectLiteralExpression(node, visitor, context, nodesVisitor, _nodeVisitor, _tokenVisitor) { - return context.factory.updateObjectLiteralExpression(node, nodesVisitor(node.properties, visitor, isObjectLiteralElementLike)); - }, - - [SyntaxKind.PropertyAccessExpression]: function visitEachChildOfPropertyAccessExpression(node, visitor, context, _nodesVisitor, nodeVisitor, tokenVisitor) { - return isPropertyAccessChain(node) ? - context.factory.updatePropertyAccessChain(node, Debug.checkDefined(nodeVisitor(node.expression, visitor, isExpression)), tokenVisitor ? nodeVisitor(node.questionDotToken, tokenVisitor, isQuestionDotToken) : node.questionDotToken, Debug.checkDefined(nodeVisitor(node.name, visitor, isMemberName))) : - context.factory.updatePropertyAccessExpression(node, Debug.checkDefined(nodeVisitor(node.expression, visitor, isExpression)), Debug.checkDefined(nodeVisitor(node.name, visitor, isMemberName))); - }, - - [SyntaxKind.ElementAccessExpression]: function visitEachChildOfElementAccessExpression(node, visitor, context, _nodesVisitor, nodeVisitor, tokenVisitor) { - return isElementAccessChain(node) ? - context.factory.updateElementAccessChain(node, Debug.checkDefined(nodeVisitor(node.expression, visitor, isExpression)), tokenVisitor ? nodeVisitor(node.questionDotToken, tokenVisitor, isQuestionDotToken) : node.questionDotToken, Debug.checkDefined(nodeVisitor(node.argumentExpression, visitor, isExpression))) : - context.factory.updateElementAccessExpression(node, Debug.checkDefined(nodeVisitor(node.expression, visitor, isExpression)), Debug.checkDefined(nodeVisitor(node.argumentExpression, visitor, isExpression))); - }, - - [SyntaxKind.CallExpression]: function visitEachChildOfCallExpression(node, visitor, context, nodesVisitor, nodeVisitor, tokenVisitor) { - return isCallChain(node) ? - context.factory.updateCallChain(node, Debug.checkDefined(nodeVisitor(node.expression, visitor, isExpression)), tokenVisitor ? nodeVisitor(node.questionDotToken, tokenVisitor, isQuestionDotToken) : node.questionDotToken, nodesVisitor(node.typeArguments, visitor, isTypeNode), nodesVisitor(node.arguments, visitor, isExpression)) : - context.factory.updateCallExpression(node, Debug.checkDefined(nodeVisitor(node.expression, visitor, isExpression)), nodesVisitor(node.typeArguments, visitor, isTypeNode), nodesVisitor(node.arguments, visitor, isExpression)); - }, - - [SyntaxKind.NewExpression]: function visitEachChildOfNewExpression(node, visitor, context, nodesVisitor, nodeVisitor, _tokenVisitor) { - return context.factory.updateNewExpression(node, Debug.checkDefined(nodeVisitor(node.expression, visitor, isExpression)), nodesVisitor(node.typeArguments, visitor, isTypeNode), nodesVisitor(node.arguments, visitor, isExpression)); + [SyntaxKind.ObjectLiteralExpression]: function visitEachChildOfObjectLiteralExpression( + node, + visitor, + context, + nodesVisitor, + _nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updateObjectLiteralExpression( + node, + nodesVisitor(node.properties, visitor, isObjectLiteralElementLike), + ); }, - [SyntaxKind.TaggedTemplateExpression]: function visitEachChildOfTaggedTemplateExpression(node, visitor, context, nodesVisitor, nodeVisitor, _tokenVisitor) { - return context.factory.updateTaggedTemplateExpression(node, Debug.checkDefined(nodeVisitor(node.tag, visitor, isExpression)), nodesVisitor(node.typeArguments, visitor, isTypeNode), Debug.checkDefined(nodeVisitor(node.template, visitor, isTemplateLiteral))); + [SyntaxKind.PropertyAccessExpression]: function visitEachChildOfPropertyAccessExpression( + node, + visitor, + context, + _nodesVisitor, + nodeVisitor, + tokenVisitor, + ) { + return isPropertyAccessChain(node) + ? context.factory.updatePropertyAccessChain( + node, + Debug.checkDefined(nodeVisitor(node.expression, visitor, isExpression)), + tokenVisitor ? nodeVisitor(node.questionDotToken, tokenVisitor, isQuestionDotToken) + : node.questionDotToken, + Debug.checkDefined(nodeVisitor(node.name, visitor, isMemberName)), + ) + : context.factory.updatePropertyAccessExpression( + node, + Debug.checkDefined(nodeVisitor(node.expression, visitor, isExpression)), + Debug.checkDefined(nodeVisitor(node.name, visitor, isMemberName)), + ); + }, + + [SyntaxKind.ElementAccessExpression]: function visitEachChildOfElementAccessExpression( + node, + visitor, + context, + _nodesVisitor, + nodeVisitor, + tokenVisitor, + ) { + return isElementAccessChain(node) + ? context.factory.updateElementAccessChain( + node, + Debug.checkDefined(nodeVisitor(node.expression, visitor, isExpression)), + tokenVisitor ? nodeVisitor(node.questionDotToken, tokenVisitor, isQuestionDotToken) + : node.questionDotToken, + Debug.checkDefined(nodeVisitor(node.argumentExpression, visitor, isExpression)), + ) + : context.factory.updateElementAccessExpression( + node, + Debug.checkDefined(nodeVisitor(node.expression, visitor, isExpression)), + Debug.checkDefined(nodeVisitor(node.argumentExpression, visitor, isExpression)), + ); + }, + + [SyntaxKind.CallExpression]: function visitEachChildOfCallExpression( + node, + visitor, + context, + nodesVisitor, + nodeVisitor, + tokenVisitor, + ) { + return isCallChain(node) + ? context.factory.updateCallChain( + node, + Debug.checkDefined(nodeVisitor(node.expression, visitor, isExpression)), + tokenVisitor ? nodeVisitor(node.questionDotToken, tokenVisitor, isQuestionDotToken) + : node.questionDotToken, + nodesVisitor(node.typeArguments, visitor, isTypeNode), + nodesVisitor(node.arguments, visitor, isExpression), + ) + : context.factory.updateCallExpression( + node, + Debug.checkDefined(nodeVisitor(node.expression, visitor, isExpression)), + nodesVisitor(node.typeArguments, visitor, isTypeNode), + nodesVisitor(node.arguments, visitor, isExpression), + ); + }, + + [SyntaxKind.NewExpression]: function visitEachChildOfNewExpression( + node, + visitor, + context, + nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updateNewExpression( + node, + Debug.checkDefined(nodeVisitor(node.expression, visitor, isExpression)), + nodesVisitor(node.typeArguments, visitor, isTypeNode), + nodesVisitor(node.arguments, visitor, isExpression), + ); }, - [SyntaxKind.TypeAssertionExpression]: function visitEachChildOfTypeAssertionExpression(node, visitor, context, _nodesVisitor, nodeVisitor, _tokenVisitor) { - return context.factory.updateTypeAssertion(node, Debug.checkDefined(nodeVisitor(node.type, visitor, isTypeNode)), Debug.checkDefined(nodeVisitor(node.expression, visitor, isExpression))); + [SyntaxKind.TaggedTemplateExpression]: function visitEachChildOfTaggedTemplateExpression( + node, + visitor, + context, + nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updateTaggedTemplateExpression( + node, + Debug.checkDefined(nodeVisitor(node.tag, visitor, isExpression)), + nodesVisitor(node.typeArguments, visitor, isTypeNode), + Debug.checkDefined(nodeVisitor(node.template, visitor, isTemplateLiteral)), + ); }, - [SyntaxKind.ParenthesizedExpression]: function visitEachChildOfParenthesizedExpression(node, visitor, context, _nodesVisitor, nodeVisitor, _tokenVisitor) { - return context.factory.updateParenthesizedExpression(node, Debug.checkDefined(nodeVisitor(node.expression, visitor, isExpression))); + [SyntaxKind.TypeAssertionExpression]: function visitEachChildOfTypeAssertionExpression( + node, + visitor, + context, + _nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updateTypeAssertion( + node, + Debug.checkDefined(nodeVisitor(node.type, visitor, isTypeNode)), + Debug.checkDefined(nodeVisitor(node.expression, visitor, isExpression)), + ); }, - [SyntaxKind.FunctionExpression]: function visitEachChildOfFunctionExpression(node, visitor, context, nodesVisitor, nodeVisitor, tokenVisitor) { - return context.factory.updateFunctionExpression(node, nodesVisitor(node.modifiers, visitor, isModifier), tokenVisitor ? nodeVisitor(node.asteriskToken, tokenVisitor, isAsteriskToken) : node.asteriskToken, nodeVisitor(node.name, visitor, isIdentifier), nodesVisitor(node.typeParameters, visitor, isTypeParameterDeclaration), visitParameterList(node.parameters, visitor, context, nodesVisitor), nodeVisitor(node.type, visitor, isTypeNode), visitFunctionBody(node.body, visitor, context, nodeVisitor)); + [SyntaxKind.ParenthesizedExpression]: function visitEachChildOfParenthesizedExpression( + node, + visitor, + context, + _nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updateParenthesizedExpression( + node, + Debug.checkDefined(nodeVisitor(node.expression, visitor, isExpression)), + ); }, - [SyntaxKind.ArrowFunction]: function visitEachChildOfArrowFunction(node, visitor, context, nodesVisitor, nodeVisitor, tokenVisitor) { - return context.factory.updateArrowFunction(node, nodesVisitor(node.modifiers, visitor, isModifier), nodesVisitor(node.typeParameters, visitor, isTypeParameterDeclaration), visitParameterList(node.parameters, visitor, context, nodesVisitor), nodeVisitor(node.type, visitor, isTypeNode), tokenVisitor ? Debug.checkDefined(nodeVisitor(node.equalsGreaterThanToken, tokenVisitor, isEqualsGreaterThanToken)) : node.equalsGreaterThanToken, visitFunctionBody(node.body, visitor, context, nodeVisitor)); + [SyntaxKind.FunctionExpression]: function visitEachChildOfFunctionExpression( + node, + visitor, + context, + nodesVisitor, + nodeVisitor, + tokenVisitor, + ) { + return context.factory.updateFunctionExpression( + node, + nodesVisitor(node.modifiers, visitor, isModifier), + tokenVisitor ? nodeVisitor(node.asteriskToken, tokenVisitor, isAsteriskToken) : node.asteriskToken, + nodeVisitor(node.name, visitor, isIdentifier), + nodesVisitor(node.typeParameters, visitor, isTypeParameterDeclaration), + visitParameterList(node.parameters, visitor, context, nodesVisitor), + nodeVisitor(node.type, visitor, isTypeNode), + visitFunctionBody(node.body, visitor, context, nodeVisitor), + ); }, - [SyntaxKind.DeleteExpression]: function visitEachChildOfDeleteExpression(node, visitor, context, _nodesVisitor, nodeVisitor, _tokenVisitor) { - return context.factory.updateDeleteExpression(node, Debug.checkDefined(nodeVisitor(node.expression, visitor, isExpression))); + [SyntaxKind.ArrowFunction]: function visitEachChildOfArrowFunction( + node, + visitor, + context, + nodesVisitor, + nodeVisitor, + tokenVisitor, + ) { + return context.factory.updateArrowFunction( + node, + nodesVisitor(node.modifiers, visitor, isModifier), + nodesVisitor(node.typeParameters, visitor, isTypeParameterDeclaration), + visitParameterList(node.parameters, visitor, context, nodesVisitor), + nodeVisitor(node.type, visitor, isTypeNode), + tokenVisitor + ? Debug.checkDefined(nodeVisitor(node.equalsGreaterThanToken, tokenVisitor, isEqualsGreaterThanToken)) + : node.equalsGreaterThanToken, + visitFunctionBody(node.body, visitor, context, nodeVisitor), + ); }, - [SyntaxKind.TypeOfExpression]: function visitEachChildOfTypeOfExpression(node, visitor, context, _nodesVisitor, nodeVisitor, _tokenVisitor) { - return context.factory.updateTypeOfExpression(node, Debug.checkDefined(nodeVisitor(node.expression, visitor, isExpression))); + [SyntaxKind.DeleteExpression]: function visitEachChildOfDeleteExpression( + node, + visitor, + context, + _nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updateDeleteExpression( + node, + Debug.checkDefined(nodeVisitor(node.expression, visitor, isExpression)), + ); }, - [SyntaxKind.VoidExpression]: function visitEachChildOfVoidExpression(node, visitor, context, _nodesVisitor, nodeVisitor, _tokenVisitor) { - return context.factory.updateVoidExpression(node, Debug.checkDefined(nodeVisitor(node.expression, visitor, isExpression))); + [SyntaxKind.TypeOfExpression]: function visitEachChildOfTypeOfExpression( + node, + visitor, + context, + _nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updateTypeOfExpression( + node, + Debug.checkDefined(nodeVisitor(node.expression, visitor, isExpression)), + ); }, - [SyntaxKind.AwaitExpression]: function visitEachChildOfAwaitExpression(node, visitor, context, _nodesVisitor, nodeVisitor, _tokenVisitor) { - return context.factory.updateAwaitExpression(node, Debug.checkDefined(nodeVisitor(node.expression, visitor, isExpression))); + [SyntaxKind.VoidExpression]: function visitEachChildOfVoidExpression( + node, + visitor, + context, + _nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updateVoidExpression( + node, + Debug.checkDefined(nodeVisitor(node.expression, visitor, isExpression)), + ); }, - [SyntaxKind.PrefixUnaryExpression]: function visitEachChildOfPrefixUnaryExpression(node, visitor, context, _nodesVisitor, nodeVisitor, _tokenVisitor) { - return context.factory.updatePrefixUnaryExpression(node, Debug.checkDefined(nodeVisitor(node.operand, visitor, isExpression))); + [SyntaxKind.AwaitExpression]: function visitEachChildOfAwaitExpression( + node, + visitor, + context, + _nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updateAwaitExpression( + node, + Debug.checkDefined(nodeVisitor(node.expression, visitor, isExpression)), + ); }, - [SyntaxKind.PostfixUnaryExpression]: function visitEachChildOfPostfixUnaryExpression(node, visitor, context, _nodesVisitor, nodeVisitor, _tokenVisitor) { - return context.factory.updatePostfixUnaryExpression(node, Debug.checkDefined(nodeVisitor(node.operand, visitor, isExpression))); + [SyntaxKind.PrefixUnaryExpression]: function visitEachChildOfPrefixUnaryExpression( + node, + visitor, + context, + _nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updatePrefixUnaryExpression( + node, + Debug.checkDefined(nodeVisitor(node.operand, visitor, isExpression)), + ); }, - [SyntaxKind.BinaryExpression]: function visitEachChildOfBinaryExpression(node, visitor, context, _nodesVisitor, nodeVisitor, tokenVisitor) { - return context.factory.updateBinaryExpression(node, Debug.checkDefined(nodeVisitor(node.left, visitor, isExpression)), tokenVisitor ? Debug.checkDefined(nodeVisitor(node.operatorToken, tokenVisitor, isBinaryOperatorToken)) : node.operatorToken, Debug.checkDefined(nodeVisitor(node.right, visitor, isExpression))); + [SyntaxKind.PostfixUnaryExpression]: function visitEachChildOfPostfixUnaryExpression( + node, + visitor, + context, + _nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updatePostfixUnaryExpression( + node, + Debug.checkDefined(nodeVisitor(node.operand, visitor, isExpression)), + ); }, - [SyntaxKind.ConditionalExpression]: function visitEachChildOfConditionalExpression(node, visitor, context, _nodesVisitor, nodeVisitor, tokenVisitor) { - return context.factory.updateConditionalExpression(node, Debug.checkDefined(nodeVisitor(node.condition, visitor, isExpression)), tokenVisitor ? Debug.checkDefined(nodeVisitor(node.questionToken, tokenVisitor, isQuestionToken)) : node.questionToken, Debug.checkDefined(nodeVisitor(node.whenTrue, visitor, isExpression)), tokenVisitor ? Debug.checkDefined(nodeVisitor(node.colonToken, tokenVisitor, isColonToken)) : node.colonToken, Debug.checkDefined(nodeVisitor(node.whenFalse, visitor, isExpression))); + [SyntaxKind.BinaryExpression]: function visitEachChildOfBinaryExpression( + node, + visitor, + context, + _nodesVisitor, + nodeVisitor, + tokenVisitor, + ) { + return context.factory.updateBinaryExpression( + node, + Debug.checkDefined(nodeVisitor(node.left, visitor, isExpression)), + tokenVisitor ? Debug.checkDefined(nodeVisitor(node.operatorToken, tokenVisitor, isBinaryOperatorToken)) + : node.operatorToken, + Debug.checkDefined(nodeVisitor(node.right, visitor, isExpression)), + ); }, - [SyntaxKind.TemplateExpression]: function visitEachChildOfTemplateExpression(node, visitor, context, nodesVisitor, nodeVisitor, _tokenVisitor) { - return context.factory.updateTemplateExpression(node, Debug.checkDefined(nodeVisitor(node.head, visitor, isTemplateHead)), nodesVisitor(node.templateSpans, visitor, isTemplateSpan)); + [SyntaxKind.ConditionalExpression]: function visitEachChildOfConditionalExpression( + node, + visitor, + context, + _nodesVisitor, + nodeVisitor, + tokenVisitor, + ) { + return context.factory.updateConditionalExpression( + node, + Debug.checkDefined(nodeVisitor(node.condition, visitor, isExpression)), + tokenVisitor ? Debug.checkDefined(nodeVisitor(node.questionToken, tokenVisitor, isQuestionToken)) + : node.questionToken, + Debug.checkDefined(nodeVisitor(node.whenTrue, visitor, isExpression)), + tokenVisitor ? Debug.checkDefined(nodeVisitor(node.colonToken, tokenVisitor, isColonToken)) + : node.colonToken, + Debug.checkDefined(nodeVisitor(node.whenFalse, visitor, isExpression)), + ); }, - [SyntaxKind.YieldExpression]: function visitEachChildOfYieldExpression(node, visitor, context, _nodesVisitor, nodeVisitor, tokenVisitor) { - return context.factory.updateYieldExpression(node, tokenVisitor ? nodeVisitor(node.asteriskToken, tokenVisitor, isAsteriskToken) : node.asteriskToken, nodeVisitor(node.expression, visitor, isExpression)); + [SyntaxKind.TemplateExpression]: function visitEachChildOfTemplateExpression( + node, + visitor, + context, + nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updateTemplateExpression( + node, + Debug.checkDefined(nodeVisitor(node.head, visitor, isTemplateHead)), + nodesVisitor(node.templateSpans, visitor, isTemplateSpan), + ); }, - [SyntaxKind.SpreadElement]: function visitEachChildOfSpreadElement(node, visitor, context, _nodesVisitor, nodeVisitor, _tokenVisitor) { - return context.factory.updateSpreadElement(node, Debug.checkDefined(nodeVisitor(node.expression, visitor, isExpression))); + [SyntaxKind.YieldExpression]: function visitEachChildOfYieldExpression( + node, + visitor, + context, + _nodesVisitor, + nodeVisitor, + tokenVisitor, + ) { + return context.factory.updateYieldExpression( + node, + tokenVisitor ? nodeVisitor(node.asteriskToken, tokenVisitor, isAsteriskToken) : node.asteriskToken, + nodeVisitor(node.expression, visitor, isExpression), + ); }, - [SyntaxKind.ClassExpression]: function visitEachChildOfClassExpression(node, visitor, context, nodesVisitor, nodeVisitor, _tokenVisitor) { - return context.factory.updateClassExpression(node, nodesVisitor(node.modifiers, visitor, isModifierLike), nodeVisitor(node.name, visitor, isIdentifier), nodesVisitor(node.typeParameters, visitor, isTypeParameterDeclaration), nodesVisitor(node.heritageClauses, visitor, isHeritageClause), nodesVisitor(node.members, visitor, isClassElement)); + [SyntaxKind.SpreadElement]: function visitEachChildOfSpreadElement( + node, + visitor, + context, + _nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updateSpreadElement( + node, + Debug.checkDefined(nodeVisitor(node.expression, visitor, isExpression)), + ); }, - [SyntaxKind.ExpressionWithTypeArguments]: function visitEachChildOfExpressionWithTypeArguments(node, visitor, context, nodesVisitor, nodeVisitor, _tokenVisitor) { - return context.factory.updateExpressionWithTypeArguments(node, Debug.checkDefined(nodeVisitor(node.expression, visitor, isExpression)), nodesVisitor(node.typeArguments, visitor, isTypeNode)); + [SyntaxKind.ClassExpression]: function visitEachChildOfClassExpression( + node, + visitor, + context, + nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updateClassExpression( + node, + nodesVisitor(node.modifiers, visitor, isModifierLike), + nodeVisitor(node.name, visitor, isIdentifier), + nodesVisitor(node.typeParameters, visitor, isTypeParameterDeclaration), + nodesVisitor(node.heritageClauses, visitor, isHeritageClause), + nodesVisitor(node.members, visitor, isClassElement), + ); }, - [SyntaxKind.AsExpression]: function visitEachChildOfAsExpression(node, visitor, context, _nodesVisitor, nodeVisitor, _tokenVisitor) { - return context.factory.updateAsExpression(node, Debug.checkDefined(nodeVisitor(node.expression, visitor, isExpression)), Debug.checkDefined(nodeVisitor(node.type, visitor, isTypeNode))); + [SyntaxKind.ExpressionWithTypeArguments]: function visitEachChildOfExpressionWithTypeArguments( + node, + visitor, + context, + nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updateExpressionWithTypeArguments( + node, + Debug.checkDefined(nodeVisitor(node.expression, visitor, isExpression)), + nodesVisitor(node.typeArguments, visitor, isTypeNode), + ); }, - [SyntaxKind.SatisfiesExpression]: function visitEachChildOfSatisfiesExpression(node, visitor, context, _nodesVisitor, nodeVisitor, _tokenVisitor) { - return context.factory.updateSatisfiesExpression(node, Debug.checkDefined(nodeVisitor(node.expression, visitor, isExpression)), Debug.checkDefined(nodeVisitor(node.type, visitor, isTypeNode))); + [SyntaxKind.AsExpression]: function visitEachChildOfAsExpression( + node, + visitor, + context, + _nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updateAsExpression( + node, + Debug.checkDefined(nodeVisitor(node.expression, visitor, isExpression)), + Debug.checkDefined(nodeVisitor(node.type, visitor, isTypeNode)), + ); }, - [SyntaxKind.NonNullExpression]: function visitEachChildOfNonNullExpression(node, visitor, context, _nodesVisitor, nodeVisitor, _tokenVisitor) { - return isOptionalChain(node) ? - context.factory.updateNonNullChain(node, Debug.checkDefined(nodeVisitor(node.expression, visitor, isExpression))) : - context.factory.updateNonNullExpression(node, Debug.checkDefined(nodeVisitor(node.expression, visitor, isExpression))); + [SyntaxKind.SatisfiesExpression]: function visitEachChildOfSatisfiesExpression( + node, + visitor, + context, + _nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updateSatisfiesExpression( + node, + Debug.checkDefined(nodeVisitor(node.expression, visitor, isExpression)), + Debug.checkDefined(nodeVisitor(node.type, visitor, isTypeNode)), + ); }, - [SyntaxKind.MetaProperty]: function visitEachChildOfMetaProperty(node, visitor, context, _nodesVisitor, nodeVisitor, _tokenVisitor) { - return context.factory.updateMetaProperty(node, Debug.checkDefined(nodeVisitor(node.name, visitor, isIdentifier))); + [SyntaxKind.NonNullExpression]: function visitEachChildOfNonNullExpression( + node, + visitor, + context, + _nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { + return isOptionalChain(node) + ? context.factory.updateNonNullChain( + node, + Debug.checkDefined(nodeVisitor(node.expression, visitor, isExpression)), + ) + : context.factory.updateNonNullExpression( + node, + Debug.checkDefined(nodeVisitor(node.expression, visitor, isExpression)), + ); + }, + + [SyntaxKind.MetaProperty]: function visitEachChildOfMetaProperty( + node, + visitor, + context, + _nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updateMetaProperty( + node, + Debug.checkDefined(nodeVisitor(node.name, visitor, isIdentifier)), + ); }, // Misc - [SyntaxKind.TemplateSpan]: function visitEachChildOfTemplateSpan(node, visitor, context, _nodesVisitor, nodeVisitor, _tokenVisitor) { - return context.factory.updateTemplateSpan(node, Debug.checkDefined(nodeVisitor(node.expression, visitor, isExpression)), Debug.checkDefined(nodeVisitor(node.literal, visitor, isTemplateMiddleOrTemplateTail))); + [SyntaxKind.TemplateSpan]: function visitEachChildOfTemplateSpan( + node, + visitor, + context, + _nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updateTemplateSpan( + node, + Debug.checkDefined(nodeVisitor(node.expression, visitor, isExpression)), + Debug.checkDefined(nodeVisitor(node.literal, visitor, isTemplateMiddleOrTemplateTail)), + ); }, // Element - [SyntaxKind.Block]: function visitEachChildOfBlock(node, visitor, context, nodesVisitor, _nodeVisitor, _tokenVisitor) { + [SyntaxKind.Block]: function visitEachChildOfBlock( + node, + visitor, + context, + nodesVisitor, + _nodeVisitor, + _tokenVisitor, + ) { return context.factory.updateBlock(node, nodesVisitor(node.statements, visitor, isStatement)); }, - [SyntaxKind.VariableStatement]: function visitEachChildOfVariableStatement(node, visitor, context, nodesVisitor, nodeVisitor, _tokenVisitor) { - return context.factory.updateVariableStatement(node, nodesVisitor(node.modifiers, visitor, isModifierLike), Debug.checkDefined(nodeVisitor(node.declarationList, visitor, isVariableDeclarationList))); + [SyntaxKind.VariableStatement]: function visitEachChildOfVariableStatement( + node, + visitor, + context, + nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updateVariableStatement( + node, + nodesVisitor(node.modifiers, visitor, isModifierLike), + Debug.checkDefined(nodeVisitor(node.declarationList, visitor, isVariableDeclarationList)), + ); }, - [SyntaxKind.ExpressionStatement]: function visitEachChildOfExpressionStatement(node, visitor, context, _nodesVisitor, nodeVisitor, _tokenVisitor) { - return context.factory.updateExpressionStatement(node, Debug.checkDefined(nodeVisitor(node.expression, visitor, isExpression))); + [SyntaxKind.ExpressionStatement]: function visitEachChildOfExpressionStatement( + node, + visitor, + context, + _nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updateExpressionStatement( + node, + Debug.checkDefined(nodeVisitor(node.expression, visitor, isExpression)), + ); }, - [SyntaxKind.IfStatement]: function visitEachChildOfIfStatement(node, visitor, context, _nodesVisitor, nodeVisitor, _tokenVisitor) { - return context.factory.updateIfStatement(node, Debug.checkDefined(nodeVisitor(node.expression, visitor, isExpression)), Debug.checkDefined(nodeVisitor(node.thenStatement, visitor, isStatement, context.factory.liftToBlock)), nodeVisitor(node.elseStatement, visitor, isStatement, context.factory.liftToBlock)); + [SyntaxKind.IfStatement]: function visitEachChildOfIfStatement( + node, + visitor, + context, + _nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updateIfStatement( + node, + Debug.checkDefined(nodeVisitor(node.expression, visitor, isExpression)), + Debug.checkDefined(nodeVisitor(node.thenStatement, visitor, isStatement, context.factory.liftToBlock)), + nodeVisitor(node.elseStatement, visitor, isStatement, context.factory.liftToBlock), + ); }, - [SyntaxKind.DoStatement]: function visitEachChildOfDoStatement(node, visitor, context, _nodesVisitor, nodeVisitor, _tokenVisitor) { - return context.factory.updateDoStatement(node, visitIterationBody(node.statement, visitor, context, nodeVisitor), Debug.checkDefined(nodeVisitor(node.expression, visitor, isExpression))); + [SyntaxKind.DoStatement]: function visitEachChildOfDoStatement( + node, + visitor, + context, + _nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updateDoStatement( + node, + visitIterationBody(node.statement, visitor, context, nodeVisitor), + Debug.checkDefined(nodeVisitor(node.expression, visitor, isExpression)), + ); }, - [SyntaxKind.WhileStatement]: function visitEachChildOfWhileStatement(node, visitor, context, _nodesVisitor, nodeVisitor, _tokenVisitor) { - return context.factory.updateWhileStatement(node, Debug.checkDefined(nodeVisitor(node.expression, visitor, isExpression)), visitIterationBody(node.statement, visitor, context, nodeVisitor)); + [SyntaxKind.WhileStatement]: function visitEachChildOfWhileStatement( + node, + visitor, + context, + _nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updateWhileStatement( + node, + Debug.checkDefined(nodeVisitor(node.expression, visitor, isExpression)), + visitIterationBody(node.statement, visitor, context, nodeVisitor), + ); }, - [SyntaxKind.ForStatement]: function visitEachChildOfForStatement(node, visitor, context, _nodesVisitor, nodeVisitor, _tokenVisitor) { - return context.factory.updateForStatement(node, nodeVisitor(node.initializer, visitor, isForInitializer), nodeVisitor(node.condition, visitor, isExpression), nodeVisitor(node.incrementor, visitor, isExpression), visitIterationBody(node.statement, visitor, context, nodeVisitor)); + [SyntaxKind.ForStatement]: function visitEachChildOfForStatement( + node, + visitor, + context, + _nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updateForStatement( + node, + nodeVisitor(node.initializer, visitor, isForInitializer), + nodeVisitor(node.condition, visitor, isExpression), + nodeVisitor(node.incrementor, visitor, isExpression), + visitIterationBody(node.statement, visitor, context, nodeVisitor), + ); }, - [SyntaxKind.ForInStatement]: function visitEachChildOfForInStatement(node, visitor, context, _nodesVisitor, nodeVisitor, _tokenVisitor) { - return context.factory.updateForInStatement(node, Debug.checkDefined(nodeVisitor(node.initializer, visitor, isForInitializer)), Debug.checkDefined(nodeVisitor(node.expression, visitor, isExpression)), visitIterationBody(node.statement, visitor, context, nodeVisitor)); + [SyntaxKind.ForInStatement]: function visitEachChildOfForInStatement( + node, + visitor, + context, + _nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updateForInStatement( + node, + Debug.checkDefined(nodeVisitor(node.initializer, visitor, isForInitializer)), + Debug.checkDefined(nodeVisitor(node.expression, visitor, isExpression)), + visitIterationBody(node.statement, visitor, context, nodeVisitor), + ); }, - [SyntaxKind.ForOfStatement]: function visitEachChildOfForOfStatement(node, visitor, context, _nodesVisitor, nodeVisitor, tokenVisitor) { - return context.factory.updateForOfStatement(node, tokenVisitor ? nodeVisitor(node.awaitModifier, tokenVisitor, isAwaitKeyword) : node.awaitModifier, Debug.checkDefined(nodeVisitor(node.initializer, visitor, isForInitializer)), Debug.checkDefined(nodeVisitor(node.expression, visitor, isExpression)), visitIterationBody(node.statement, visitor, context, nodeVisitor)); + [SyntaxKind.ForOfStatement]: function visitEachChildOfForOfStatement( + node, + visitor, + context, + _nodesVisitor, + nodeVisitor, + tokenVisitor, + ) { + return context.factory.updateForOfStatement( + node, + tokenVisitor ? nodeVisitor(node.awaitModifier, tokenVisitor, isAwaitKeyword) : node.awaitModifier, + Debug.checkDefined(nodeVisitor(node.initializer, visitor, isForInitializer)), + Debug.checkDefined(nodeVisitor(node.expression, visitor, isExpression)), + visitIterationBody(node.statement, visitor, context, nodeVisitor), + ); }, - [SyntaxKind.ContinueStatement]: function visitEachChildOfContinueStatement(node, visitor, context, _nodesVisitor, nodeVisitor, _tokenVisitor) { + [SyntaxKind.ContinueStatement]: function visitEachChildOfContinueStatement( + node, + visitor, + context, + _nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { return context.factory.updateContinueStatement(node, nodeVisitor(node.label, visitor, isIdentifier)); }, - [SyntaxKind.BreakStatement]: function visitEachChildOfBreakStatement(node, visitor, context, _nodesVisitor, nodeVisitor, _tokenVisitor) { + [SyntaxKind.BreakStatement]: function visitEachChildOfBreakStatement( + node, + visitor, + context, + _nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { return context.factory.updateBreakStatement(node, nodeVisitor(node.label, visitor, isIdentifier)); }, - [SyntaxKind.ReturnStatement]: function visitEachChildOfReturnStatement(node, visitor, context, _nodesVisitor, nodeVisitor, _tokenVisitor) { + [SyntaxKind.ReturnStatement]: function visitEachChildOfReturnStatement( + node, + visitor, + context, + _nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { return context.factory.updateReturnStatement(node, nodeVisitor(node.expression, visitor, isExpression)); }, - [SyntaxKind.WithStatement]: function visitEachChildOfWithStatement(node, visitor, context, _nodesVisitor, nodeVisitor, _tokenVisitor) { - return context.factory.updateWithStatement(node, Debug.checkDefined(nodeVisitor(node.expression, visitor, isExpression)), Debug.checkDefined(nodeVisitor(node.statement, visitor, isStatement, context.factory.liftToBlock))); + [SyntaxKind.WithStatement]: function visitEachChildOfWithStatement( + node, + visitor, + context, + _nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updateWithStatement( + node, + Debug.checkDefined(nodeVisitor(node.expression, visitor, isExpression)), + Debug.checkDefined(nodeVisitor(node.statement, visitor, isStatement, context.factory.liftToBlock)), + ); }, - [SyntaxKind.SwitchStatement]: function visitEachChildOfSwitchStatement(node, visitor, context, _nodesVisitor, nodeVisitor, _tokenVisitor) { - return context.factory.updateSwitchStatement(node, Debug.checkDefined(nodeVisitor(node.expression, visitor, isExpression)), Debug.checkDefined(nodeVisitor(node.caseBlock, visitor, isCaseBlock))); + [SyntaxKind.SwitchStatement]: function visitEachChildOfSwitchStatement( + node, + visitor, + context, + _nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updateSwitchStatement( + node, + Debug.checkDefined(nodeVisitor(node.expression, visitor, isExpression)), + Debug.checkDefined(nodeVisitor(node.caseBlock, visitor, isCaseBlock)), + ); }, - [SyntaxKind.LabeledStatement]: function visitEachChildOfLabeledStatement(node, visitor, context, _nodesVisitor, nodeVisitor, _tokenVisitor) { - return context.factory.updateLabeledStatement(node, Debug.checkDefined(nodeVisitor(node.label, visitor, isIdentifier)), Debug.checkDefined(nodeVisitor(node.statement, visitor, isStatement, context.factory.liftToBlock))); + [SyntaxKind.LabeledStatement]: function visitEachChildOfLabeledStatement( + node, + visitor, + context, + _nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updateLabeledStatement( + node, + Debug.checkDefined(nodeVisitor(node.label, visitor, isIdentifier)), + Debug.checkDefined(nodeVisitor(node.statement, visitor, isStatement, context.factory.liftToBlock)), + ); }, - [SyntaxKind.ThrowStatement]: function visitEachChildOfThrowStatement(node, visitor, context, _nodesVisitor, nodeVisitor, _tokenVisitor) { - return context.factory.updateThrowStatement(node, Debug.checkDefined(nodeVisitor(node.expression, visitor, isExpression))); + [SyntaxKind.ThrowStatement]: function visitEachChildOfThrowStatement( + node, + visitor, + context, + _nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updateThrowStatement( + node, + Debug.checkDefined(nodeVisitor(node.expression, visitor, isExpression)), + ); }, - [SyntaxKind.TryStatement]: function visitEachChildOfTryStatement(node, visitor, context, _nodesVisitor, nodeVisitor, _tokenVisitor) { - return context.factory.updateTryStatement(node, Debug.checkDefined(nodeVisitor(node.tryBlock, visitor, isBlock)), nodeVisitor(node.catchClause, visitor, isCatchClause), nodeVisitor(node.finallyBlock, visitor, isBlock)); + [SyntaxKind.TryStatement]: function visitEachChildOfTryStatement( + node, + visitor, + context, + _nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updateTryStatement( + node, + Debug.checkDefined(nodeVisitor(node.tryBlock, visitor, isBlock)), + nodeVisitor(node.catchClause, visitor, isCatchClause), + nodeVisitor(node.finallyBlock, visitor, isBlock), + ); }, - [SyntaxKind.VariableDeclaration]: function visitEachChildOfVariableDeclaration(node, visitor, context, _nodesVisitor, nodeVisitor, tokenVisitor) { - return context.factory.updateVariableDeclaration(node, Debug.checkDefined(nodeVisitor(node.name, visitor, isBindingName)), tokenVisitor ? nodeVisitor(node.exclamationToken, tokenVisitor, isExclamationToken) : node.exclamationToken, nodeVisitor(node.type, visitor, isTypeNode), nodeVisitor(node.initializer, visitor, isExpression)); + [SyntaxKind.VariableDeclaration]: function visitEachChildOfVariableDeclaration( + node, + visitor, + context, + _nodesVisitor, + nodeVisitor, + tokenVisitor, + ) { + return context.factory.updateVariableDeclaration( + node, + Debug.checkDefined(nodeVisitor(node.name, visitor, isBindingName)), + tokenVisitor ? nodeVisitor(node.exclamationToken, tokenVisitor, isExclamationToken) : node.exclamationToken, + nodeVisitor(node.type, visitor, isTypeNode), + nodeVisitor(node.initializer, visitor, isExpression), + ); }, - [SyntaxKind.VariableDeclarationList]: function visitEachChildOfVariableDeclarationList(node, visitor, context, nodesVisitor, _nodeVisitor, _tokenVisitor) { - return context.factory.updateVariableDeclarationList(node, nodesVisitor(node.declarations, visitor, isVariableDeclaration)); + [SyntaxKind.VariableDeclarationList]: function visitEachChildOfVariableDeclarationList( + node, + visitor, + context, + nodesVisitor, + _nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updateVariableDeclarationList( + node, + nodesVisitor(node.declarations, visitor, isVariableDeclaration), + ); }, - [SyntaxKind.FunctionDeclaration]: function visitEachChildOfFunctionDeclaration(node, visitor, context, nodesVisitor, nodeVisitor, tokenVisitor) { - return context.factory.updateFunctionDeclaration(node, nodesVisitor(node.modifiers, visitor, isModifier), tokenVisitor ? nodeVisitor(node.asteriskToken, tokenVisitor, isAsteriskToken) : node.asteriskToken, nodeVisitor(node.name, visitor, isIdentifier), nodesVisitor(node.typeParameters, visitor, isTypeParameterDeclaration), visitParameterList(node.parameters, visitor, context, nodesVisitor), nodeVisitor(node.type, visitor, isTypeNode), visitFunctionBody(node.body, visitor, context, nodeVisitor)); + [SyntaxKind.FunctionDeclaration]: function visitEachChildOfFunctionDeclaration( + node, + visitor, + context, + nodesVisitor, + nodeVisitor, + tokenVisitor, + ) { + return context.factory.updateFunctionDeclaration( + node, + nodesVisitor(node.modifiers, visitor, isModifier), + tokenVisitor ? nodeVisitor(node.asteriskToken, tokenVisitor, isAsteriskToken) : node.asteriskToken, + nodeVisitor(node.name, visitor, isIdentifier), + nodesVisitor(node.typeParameters, visitor, isTypeParameterDeclaration), + visitParameterList(node.parameters, visitor, context, nodesVisitor), + nodeVisitor(node.type, visitor, isTypeNode), + visitFunctionBody(node.body, visitor, context, nodeVisitor), + ); }, - [SyntaxKind.ClassDeclaration]: function visitEachChildOfClassDeclaration(node, visitor, context, nodesVisitor, nodeVisitor, _tokenVisitor) { - return context.factory.updateClassDeclaration(node, nodesVisitor(node.modifiers, visitor, isModifierLike), nodeVisitor(node.name, visitor, isIdentifier), nodesVisitor(node.typeParameters, visitor, isTypeParameterDeclaration), nodesVisitor(node.heritageClauses, visitor, isHeritageClause), nodesVisitor(node.members, visitor, isClassElement)); + [SyntaxKind.ClassDeclaration]: function visitEachChildOfClassDeclaration( + node, + visitor, + context, + nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updateClassDeclaration( + node, + nodesVisitor(node.modifiers, visitor, isModifierLike), + nodeVisitor(node.name, visitor, isIdentifier), + nodesVisitor(node.typeParameters, visitor, isTypeParameterDeclaration), + nodesVisitor(node.heritageClauses, visitor, isHeritageClause), + nodesVisitor(node.members, visitor, isClassElement), + ); }, - [SyntaxKind.InterfaceDeclaration]: function visitEachChildOfInterfaceDeclaration(node, visitor, context, nodesVisitor, nodeVisitor, _tokenVisitor) { - return context.factory.updateInterfaceDeclaration(node, nodesVisitor(node.modifiers, visitor, isModifierLike), Debug.checkDefined(nodeVisitor(node.name, visitor, isIdentifier)), nodesVisitor(node.typeParameters, visitor, isTypeParameterDeclaration), nodesVisitor(node.heritageClauses, visitor, isHeritageClause), nodesVisitor(node.members, visitor, isTypeElement)); + [SyntaxKind.InterfaceDeclaration]: function visitEachChildOfInterfaceDeclaration( + node, + visitor, + context, + nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updateInterfaceDeclaration( + node, + nodesVisitor(node.modifiers, visitor, isModifierLike), + Debug.checkDefined(nodeVisitor(node.name, visitor, isIdentifier)), + nodesVisitor(node.typeParameters, visitor, isTypeParameterDeclaration), + nodesVisitor(node.heritageClauses, visitor, isHeritageClause), + nodesVisitor(node.members, visitor, isTypeElement), + ); }, - [SyntaxKind.TypeAliasDeclaration]: function visitEachChildOfTypeAliasDeclaration(node, visitor, context, nodesVisitor, nodeVisitor, _tokenVisitor) { - return context.factory.updateTypeAliasDeclaration(node, nodesVisitor(node.modifiers, visitor, isModifierLike), Debug.checkDefined(nodeVisitor(node.name, visitor, isIdentifier)), nodesVisitor(node.typeParameters, visitor, isTypeParameterDeclaration), Debug.checkDefined(nodeVisitor(node.type, visitor, isTypeNode))); + [SyntaxKind.TypeAliasDeclaration]: function visitEachChildOfTypeAliasDeclaration( + node, + visitor, + context, + nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updateTypeAliasDeclaration( + node, + nodesVisitor(node.modifiers, visitor, isModifierLike), + Debug.checkDefined(nodeVisitor(node.name, visitor, isIdentifier)), + nodesVisitor(node.typeParameters, visitor, isTypeParameterDeclaration), + Debug.checkDefined(nodeVisitor(node.type, visitor, isTypeNode)), + ); }, - [SyntaxKind.EnumDeclaration]: function visitEachChildOfEnumDeclaration(node, visitor, context, nodesVisitor, nodeVisitor, _tokenVisitor) { - return context.factory.updateEnumDeclaration(node, nodesVisitor(node.modifiers, visitor, isModifierLike), Debug.checkDefined(nodeVisitor(node.name, visitor, isIdentifier)), nodesVisitor(node.members, visitor, isEnumMember)); + [SyntaxKind.EnumDeclaration]: function visitEachChildOfEnumDeclaration( + node, + visitor, + context, + nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updateEnumDeclaration( + node, + nodesVisitor(node.modifiers, visitor, isModifierLike), + Debug.checkDefined(nodeVisitor(node.name, visitor, isIdentifier)), + nodesVisitor(node.members, visitor, isEnumMember), + ); }, - [SyntaxKind.ModuleDeclaration]: function visitEachChildOfModuleDeclaration(node, visitor, context, nodesVisitor, nodeVisitor, _tokenVisitor) { - return context.factory.updateModuleDeclaration(node, nodesVisitor(node.modifiers, visitor, isModifierLike), Debug.checkDefined(nodeVisitor(node.name, visitor, isModuleName)), nodeVisitor(node.body, visitor, isModuleBody)); + [SyntaxKind.ModuleDeclaration]: function visitEachChildOfModuleDeclaration( + node, + visitor, + context, + nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updateModuleDeclaration( + node, + nodesVisitor(node.modifiers, visitor, isModifierLike), + Debug.checkDefined(nodeVisitor(node.name, visitor, isModuleName)), + nodeVisitor(node.body, visitor, isModuleBody), + ); }, - [SyntaxKind.ModuleBlock]: function visitEachChildOfModuleBlock(node, visitor, context, nodesVisitor, _nodeVisitor, _tokenVisitor) { + [SyntaxKind.ModuleBlock]: function visitEachChildOfModuleBlock( + node, + visitor, + context, + nodesVisitor, + _nodeVisitor, + _tokenVisitor, + ) { return context.factory.updateModuleBlock(node, nodesVisitor(node.statements, visitor, isStatement)); }, - [SyntaxKind.CaseBlock]: function visitEachChildOfCaseBlock(node, visitor, context, nodesVisitor, _nodeVisitor, _tokenVisitor) { + [SyntaxKind.CaseBlock]: function visitEachChildOfCaseBlock( + node, + visitor, + context, + nodesVisitor, + _nodeVisitor, + _tokenVisitor, + ) { return context.factory.updateCaseBlock(node, nodesVisitor(node.clauses, visitor, isCaseOrDefaultClause)); }, - [SyntaxKind.NamespaceExportDeclaration]: function visitEachChildOfNamespaceExportDeclaration(node, visitor, context, _nodesVisitor, nodeVisitor, _tokenVisitor) { - return context.factory.updateNamespaceExportDeclaration(node, Debug.checkDefined(nodeVisitor(node.name, visitor, isIdentifier))); + [SyntaxKind.NamespaceExportDeclaration]: function visitEachChildOfNamespaceExportDeclaration( + node, + visitor, + context, + _nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updateNamespaceExportDeclaration( + node, + Debug.checkDefined(nodeVisitor(node.name, visitor, isIdentifier)), + ); }, - [SyntaxKind.ImportEqualsDeclaration]: function visitEachChildOfImportEqualsDeclaration(node, visitor, context, nodesVisitor, nodeVisitor, _tokenVisitor) { - return context.factory.updateImportEqualsDeclaration(node, nodesVisitor(node.modifiers, visitor, isModifierLike), node.isTypeOnly, Debug.checkDefined(nodeVisitor(node.name, visitor, isIdentifier)), Debug.checkDefined(nodeVisitor(node.moduleReference, visitor, isModuleReference))); + [SyntaxKind.ImportEqualsDeclaration]: function visitEachChildOfImportEqualsDeclaration( + node, + visitor, + context, + nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updateImportEqualsDeclaration( + node, + nodesVisitor(node.modifiers, visitor, isModifierLike), + node.isTypeOnly, + Debug.checkDefined(nodeVisitor(node.name, visitor, isIdentifier)), + Debug.checkDefined(nodeVisitor(node.moduleReference, visitor, isModuleReference)), + ); }, - [SyntaxKind.ImportDeclaration]: function visitEachChildOfImportDeclaration(node, visitor, context, nodesVisitor, nodeVisitor, _tokenVisitor) { - return context.factory.updateImportDeclaration(node, nodesVisitor(node.modifiers, visitor, isModifierLike), nodeVisitor(node.importClause, visitor, isImportClause), Debug.checkDefined(nodeVisitor(node.moduleSpecifier, visitor, isExpression)), nodeVisitor(node.assertClause, visitor, isAssertClause)); + [SyntaxKind.ImportDeclaration]: function visitEachChildOfImportDeclaration( + node, + visitor, + context, + nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updateImportDeclaration( + node, + nodesVisitor(node.modifiers, visitor, isModifierLike), + nodeVisitor(node.importClause, visitor, isImportClause), + Debug.checkDefined(nodeVisitor(node.moduleSpecifier, visitor, isExpression)), + nodeVisitor(node.assertClause, visitor, isAssertClause), + ); }, - [SyntaxKind.AssertClause]: function visitEachChildOfAssertClause(node, visitor, context, nodesVisitor, _nodeVisitor, _tokenVisitor) { - return context.factory.updateAssertClause(node, nodesVisitor(node.elements, visitor, isAssertEntry), node.multiLine); + [SyntaxKind.AssertClause]: function visitEachChildOfAssertClause( + node, + visitor, + context, + nodesVisitor, + _nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updateAssertClause( + node, + nodesVisitor(node.elements, visitor, isAssertEntry), + node.multiLine, + ); }, - [SyntaxKind.AssertEntry]: function visitEachChildOfAssertEntry(node, visitor, context, _nodesVisitor, nodeVisitor, _tokenVisitor) { - return context.factory.updateAssertEntry(node, Debug.checkDefined(nodeVisitor(node.name, visitor, isAssertionKey)), Debug.checkDefined(nodeVisitor(node.value, visitor, isExpression))); + [SyntaxKind.AssertEntry]: function visitEachChildOfAssertEntry( + node, + visitor, + context, + _nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updateAssertEntry( + node, + Debug.checkDefined(nodeVisitor(node.name, visitor, isAssertionKey)), + Debug.checkDefined(nodeVisitor(node.value, visitor, isExpression)), + ); }, - [SyntaxKind.ImportClause]: function visitEachChildOfImportClause(node, visitor, context, _nodesVisitor, nodeVisitor, _tokenVisitor) { - return context.factory.updateImportClause(node, node.isTypeOnly, nodeVisitor(node.name, visitor, isIdentifier), nodeVisitor(node.namedBindings, visitor, isNamedImportBindings)); + [SyntaxKind.ImportClause]: function visitEachChildOfImportClause( + node, + visitor, + context, + _nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updateImportClause( + node, + node.isTypeOnly, + nodeVisitor(node.name, visitor, isIdentifier), + nodeVisitor(node.namedBindings, visitor, isNamedImportBindings), + ); }, - [SyntaxKind.NamespaceImport]: function visitEachChildOfNamespaceImport(node, visitor, context, _nodesVisitor, nodeVisitor, _tokenVisitor) { - return context.factory.updateNamespaceImport(node, Debug.checkDefined(nodeVisitor(node.name, visitor, isIdentifier))); + [SyntaxKind.NamespaceImport]: function visitEachChildOfNamespaceImport( + node, + visitor, + context, + _nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updateNamespaceImport( + node, + Debug.checkDefined(nodeVisitor(node.name, visitor, isIdentifier)), + ); }, - [SyntaxKind.NamespaceExport]: function visitEachChildOfNamespaceExport(node, visitor, context, _nodesVisitor, nodeVisitor, _tokenVisitor) { - return context.factory.updateNamespaceExport(node, Debug.checkDefined(nodeVisitor(node.name, visitor, isIdentifier))); + [SyntaxKind.NamespaceExport]: function visitEachChildOfNamespaceExport( + node, + visitor, + context, + _nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updateNamespaceExport( + node, + Debug.checkDefined(nodeVisitor(node.name, visitor, isIdentifier)), + ); }, - [SyntaxKind.NamedImports]: function visitEachChildOfNamedImports(node, visitor, context, nodesVisitor, _nodeVisitor, _tokenVisitor) { + [SyntaxKind.NamedImports]: function visitEachChildOfNamedImports( + node, + visitor, + context, + nodesVisitor, + _nodeVisitor, + _tokenVisitor, + ) { return context.factory.updateNamedImports(node, nodesVisitor(node.elements, visitor, isImportSpecifier)); }, - [SyntaxKind.ImportSpecifier]: function visitEachChildOfImportSpecifier(node, visitor, context, _nodesVisitor, nodeVisitor, _tokenVisitor) { - return context.factory.updateImportSpecifier(node, node.isTypeOnly, nodeVisitor(node.propertyName, visitor, isIdentifier), Debug.checkDefined(nodeVisitor(node.name, visitor, isIdentifier))); + [SyntaxKind.ImportSpecifier]: function visitEachChildOfImportSpecifier( + node, + visitor, + context, + _nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updateImportSpecifier( + node, + node.isTypeOnly, + nodeVisitor(node.propertyName, visitor, isIdentifier), + Debug.checkDefined(nodeVisitor(node.name, visitor, isIdentifier)), + ); }, - [SyntaxKind.ExportAssignment]: function visitEachChildOfExportAssignment(node, visitor, context, nodesVisitor, nodeVisitor, _tokenVisitor) { - return context.factory.updateExportAssignment(node, nodesVisitor(node.modifiers, visitor, isModifierLike), Debug.checkDefined(nodeVisitor(node.expression, visitor, isExpression))); + [SyntaxKind.ExportAssignment]: function visitEachChildOfExportAssignment( + node, + visitor, + context, + nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updateExportAssignment( + node, + nodesVisitor(node.modifiers, visitor, isModifierLike), + Debug.checkDefined(nodeVisitor(node.expression, visitor, isExpression)), + ); }, - [SyntaxKind.ExportDeclaration]: function visitEachChildOfExportDeclaration(node, visitor, context, nodesVisitor, nodeVisitor, _tokenVisitor) { - return context.factory.updateExportDeclaration(node, nodesVisitor(node.modifiers, visitor, isModifierLike), node.isTypeOnly, nodeVisitor(node.exportClause, visitor, isNamedExportBindings), nodeVisitor(node.moduleSpecifier, visitor, isExpression), nodeVisitor(node.assertClause, visitor, isAssertClause)); + [SyntaxKind.ExportDeclaration]: function visitEachChildOfExportDeclaration( + node, + visitor, + context, + nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updateExportDeclaration( + node, + nodesVisitor(node.modifiers, visitor, isModifierLike), + node.isTypeOnly, + nodeVisitor(node.exportClause, visitor, isNamedExportBindings), + nodeVisitor(node.moduleSpecifier, visitor, isExpression), + nodeVisitor(node.assertClause, visitor, isAssertClause), + ); }, - [SyntaxKind.NamedExports]: function visitEachChildOfNamedExports(node, visitor, context, nodesVisitor, _nodeVisitor, _tokenVisitor) { + [SyntaxKind.NamedExports]: function visitEachChildOfNamedExports( + node, + visitor, + context, + nodesVisitor, + _nodeVisitor, + _tokenVisitor, + ) { return context.factory.updateNamedExports(node, nodesVisitor(node.elements, visitor, isExportSpecifier)); }, - [SyntaxKind.ExportSpecifier]: function visitEachChildOfExportSpecifier(node, visitor, context, _nodesVisitor, nodeVisitor, _tokenVisitor) { - return context.factory.updateExportSpecifier(node, node.isTypeOnly, nodeVisitor(node.propertyName, visitor, isIdentifier), Debug.checkDefined(nodeVisitor(node.name, visitor, isIdentifier))); + [SyntaxKind.ExportSpecifier]: function visitEachChildOfExportSpecifier( + node, + visitor, + context, + _nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updateExportSpecifier( + node, + node.isTypeOnly, + nodeVisitor(node.propertyName, visitor, isIdentifier), + Debug.checkDefined(nodeVisitor(node.name, visitor, isIdentifier)), + ); }, // Module references - [SyntaxKind.ExternalModuleReference]: function visitEachChildOfExternalModuleReference(node, visitor, context, _nodesVisitor, nodeVisitor, _tokenVisitor) { - return context.factory.updateExternalModuleReference(node, Debug.checkDefined(nodeVisitor(node.expression, visitor, isExpression))); + [SyntaxKind.ExternalModuleReference]: function visitEachChildOfExternalModuleReference( + node, + visitor, + context, + _nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updateExternalModuleReference( + node, + Debug.checkDefined(nodeVisitor(node.expression, visitor, isExpression)), + ); }, // JSX - [SyntaxKind.JsxElement]: function visitEachChildOfJsxElement(node, visitor, context, nodesVisitor, nodeVisitor, _tokenVisitor) { - return context.factory.updateJsxElement(node, Debug.checkDefined(nodeVisitor(node.openingElement, visitor, isJsxOpeningElement)), nodesVisitor(node.children, visitor, isJsxChild), Debug.checkDefined(nodeVisitor(node.closingElement, visitor, isJsxClosingElement))); + [SyntaxKind.JsxElement]: function visitEachChildOfJsxElement( + node, + visitor, + context, + nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updateJsxElement( + node, + Debug.checkDefined(nodeVisitor(node.openingElement, visitor, isJsxOpeningElement)), + nodesVisitor(node.children, visitor, isJsxChild), + Debug.checkDefined(nodeVisitor(node.closingElement, visitor, isJsxClosingElement)), + ); }, - [SyntaxKind.JsxSelfClosingElement]: function visitEachChildOfJsxSelfClosingElement(node, visitor, context, nodesVisitor, nodeVisitor, _tokenVisitor) { - return context.factory.updateJsxSelfClosingElement(node, Debug.checkDefined(nodeVisitor(node.tagName, visitor, isJsxTagNameExpression)), nodesVisitor(node.typeArguments, visitor, isTypeNode), Debug.checkDefined(nodeVisitor(node.attributes, visitor, isJsxAttributes))); + [SyntaxKind.JsxSelfClosingElement]: function visitEachChildOfJsxSelfClosingElement( + node, + visitor, + context, + nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updateJsxSelfClosingElement( + node, + Debug.checkDefined(nodeVisitor(node.tagName, visitor, isJsxTagNameExpression)), + nodesVisitor(node.typeArguments, visitor, isTypeNode), + Debug.checkDefined(nodeVisitor(node.attributes, visitor, isJsxAttributes)), + ); }, - [SyntaxKind.JsxOpeningElement]: function visitEachChildOfJsxOpeningElement(node, visitor, context, nodesVisitor, nodeVisitor, _tokenVisitor) { - return context.factory.updateJsxOpeningElement(node, Debug.checkDefined(nodeVisitor(node.tagName, visitor, isJsxTagNameExpression)), nodesVisitor(node.typeArguments, visitor, isTypeNode), Debug.checkDefined(nodeVisitor(node.attributes, visitor, isJsxAttributes))); + [SyntaxKind.JsxOpeningElement]: function visitEachChildOfJsxOpeningElement( + node, + visitor, + context, + nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updateJsxOpeningElement( + node, + Debug.checkDefined(nodeVisitor(node.tagName, visitor, isJsxTagNameExpression)), + nodesVisitor(node.typeArguments, visitor, isTypeNode), + Debug.checkDefined(nodeVisitor(node.attributes, visitor, isJsxAttributes)), + ); }, - [SyntaxKind.JsxClosingElement]: function visitEachChildOfJsxClosingElement(node, visitor, context, _nodesVisitor, nodeVisitor, _tokenVisitor) { - return context.factory.updateJsxClosingElement(node, Debug.checkDefined(nodeVisitor(node.tagName, visitor, isJsxTagNameExpression))); + [SyntaxKind.JsxClosingElement]: function visitEachChildOfJsxClosingElement( + node, + visitor, + context, + _nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updateJsxClosingElement( + node, + Debug.checkDefined(nodeVisitor(node.tagName, visitor, isJsxTagNameExpression)), + ); }, - [SyntaxKind.JsxNamespacedName]: function forEachChildInJsxNamespacedName(node, visitor, context, _nodesVisitor, nodeVisitor, _tokenVisitor) { - return context.factory.updateJsxNamespacedName(node, Debug.checkDefined(nodeVisitor(node.namespace, visitor, isIdentifier)), Debug.checkDefined(nodeVisitor(node.name, visitor, isIdentifier))); + [SyntaxKind.JsxNamespacedName]: function forEachChildInJsxNamespacedName( + node, + visitor, + context, + _nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updateJsxNamespacedName( + node, + Debug.checkDefined(nodeVisitor(node.namespace, visitor, isIdentifier)), + Debug.checkDefined(nodeVisitor(node.name, visitor, isIdentifier)), + ); }, - [SyntaxKind.JsxFragment]: function visitEachChildOfJsxFragment(node, visitor, context, nodesVisitor, nodeVisitor, _tokenVisitor) { - return context.factory.updateJsxFragment(node, Debug.checkDefined(nodeVisitor(node.openingFragment, visitor, isJsxOpeningFragment)), nodesVisitor(node.children, visitor, isJsxChild), Debug.checkDefined(nodeVisitor(node.closingFragment, visitor, isJsxClosingFragment))); + [SyntaxKind.JsxFragment]: function visitEachChildOfJsxFragment( + node, + visitor, + context, + nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updateJsxFragment( + node, + Debug.checkDefined(nodeVisitor(node.openingFragment, visitor, isJsxOpeningFragment)), + nodesVisitor(node.children, visitor, isJsxChild), + Debug.checkDefined(nodeVisitor(node.closingFragment, visitor, isJsxClosingFragment)), + ); }, - [SyntaxKind.JsxAttribute]: function visitEachChildOfJsxAttribute(node, visitor, context, _nodesVisitor, nodeVisitor, _tokenVisitor) { - return context.factory.updateJsxAttribute(node, Debug.checkDefined(nodeVisitor(node.name, visitor, isJsxAttributeName)), nodeVisitor(node.initializer, visitor, isStringLiteralOrJsxExpression)); + [SyntaxKind.JsxAttribute]: function visitEachChildOfJsxAttribute( + node, + visitor, + context, + _nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updateJsxAttribute( + node, + Debug.checkDefined(nodeVisitor(node.name, visitor, isJsxAttributeName)), + nodeVisitor(node.initializer, visitor, isStringLiteralOrJsxExpression), + ); }, - [SyntaxKind.JsxAttributes]: function visitEachChildOfJsxAttributes(node, visitor, context, nodesVisitor, _nodeVisitor, _tokenVisitor) { + [SyntaxKind.JsxAttributes]: function visitEachChildOfJsxAttributes( + node, + visitor, + context, + nodesVisitor, + _nodeVisitor, + _tokenVisitor, + ) { return context.factory.updateJsxAttributes(node, nodesVisitor(node.properties, visitor, isJsxAttributeLike)); }, - [SyntaxKind.JsxSpreadAttribute]: function visitEachChildOfJsxSpreadAttribute(node, visitor, context, _nodesVisitor, nodeVisitor, _tokenVisitor) { - return context.factory.updateJsxSpreadAttribute(node, Debug.checkDefined(nodeVisitor(node.expression, visitor, isExpression))); + [SyntaxKind.JsxSpreadAttribute]: function visitEachChildOfJsxSpreadAttribute( + node, + visitor, + context, + _nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updateJsxSpreadAttribute( + node, + Debug.checkDefined(nodeVisitor(node.expression, visitor, isExpression)), + ); }, - [SyntaxKind.JsxExpression]: function visitEachChildOfJsxExpression(node, visitor, context, _nodesVisitor, nodeVisitor, _tokenVisitor) { + [SyntaxKind.JsxExpression]: function visitEachChildOfJsxExpression( + node, + visitor, + context, + _nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { return context.factory.updateJsxExpression(node, nodeVisitor(node.expression, visitor, isExpression)); }, // Clauses - [SyntaxKind.CaseClause]: function visitEachChildOfCaseClause(node, visitor, context, nodesVisitor, nodeVisitor, _tokenVisitor) { - return context.factory.updateCaseClause(node, Debug.checkDefined(nodeVisitor(node.expression, visitor, isExpression)), nodesVisitor(node.statements, visitor, isStatement)); + [SyntaxKind.CaseClause]: function visitEachChildOfCaseClause( + node, + visitor, + context, + nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updateCaseClause( + node, + Debug.checkDefined(nodeVisitor(node.expression, visitor, isExpression)), + nodesVisitor(node.statements, visitor, isStatement), + ); }, - [SyntaxKind.DefaultClause]: function visitEachChildOfDefaultClause(node, visitor, context, nodesVisitor, _nodeVisitor, _tokenVisitor) { + [SyntaxKind.DefaultClause]: function visitEachChildOfDefaultClause( + node, + visitor, + context, + nodesVisitor, + _nodeVisitor, + _tokenVisitor, + ) { return context.factory.updateDefaultClause(node, nodesVisitor(node.statements, visitor, isStatement)); }, - [SyntaxKind.HeritageClause]: function visitEachChildOfHeritageClause(node, visitor, context, nodesVisitor, _nodeVisitor, _tokenVisitor) { - return context.factory.updateHeritageClause(node, nodesVisitor(node.types, visitor, isExpressionWithTypeArguments)); + [SyntaxKind.HeritageClause]: function visitEachChildOfHeritageClause( + node, + visitor, + context, + nodesVisitor, + _nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updateHeritageClause( + node, + nodesVisitor(node.types, visitor, isExpressionWithTypeArguments), + ); }, - [SyntaxKind.CatchClause]: function visitEachChildOfCatchClause(node, visitor, context, _nodesVisitor, nodeVisitor, _tokenVisitor) { - return context.factory.updateCatchClause(node, nodeVisitor(node.variableDeclaration, visitor, isVariableDeclaration), Debug.checkDefined(nodeVisitor(node.block, visitor, isBlock))); + [SyntaxKind.CatchClause]: function visitEachChildOfCatchClause( + node, + visitor, + context, + _nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updateCatchClause( + node, + nodeVisitor(node.variableDeclaration, visitor, isVariableDeclaration), + Debug.checkDefined(nodeVisitor(node.block, visitor, isBlock)), + ); }, // Property assignments - [SyntaxKind.PropertyAssignment]: function visitEachChildOfPropertyAssignment(node, visitor, context, _nodesVisitor, nodeVisitor, _tokenVisitor) { - return context.factory.updatePropertyAssignment(node, Debug.checkDefined(nodeVisitor(node.name, visitor, isPropertyName)), Debug.checkDefined(nodeVisitor(node.initializer, visitor, isExpression))); + [SyntaxKind.PropertyAssignment]: function visitEachChildOfPropertyAssignment( + node, + visitor, + context, + _nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updatePropertyAssignment( + node, + Debug.checkDefined(nodeVisitor(node.name, visitor, isPropertyName)), + Debug.checkDefined(nodeVisitor(node.initializer, visitor, isExpression)), + ); }, - [SyntaxKind.ShorthandPropertyAssignment]: function visitEachChildOfShorthandPropertyAssignment(node, visitor, context, _nodesVisitor, nodeVisitor, _tokenVisitor) { - return context.factory.updateShorthandPropertyAssignment(node, Debug.checkDefined(nodeVisitor(node.name, visitor, isIdentifier)), nodeVisitor(node.objectAssignmentInitializer, visitor, isExpression)); + [SyntaxKind.ShorthandPropertyAssignment]: function visitEachChildOfShorthandPropertyAssignment( + node, + visitor, + context, + _nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updateShorthandPropertyAssignment( + node, + Debug.checkDefined(nodeVisitor(node.name, visitor, isIdentifier)), + nodeVisitor(node.objectAssignmentInitializer, visitor, isExpression), + ); }, - [SyntaxKind.SpreadAssignment]: function visitEachChildOfSpreadAssignment(node, visitor, context, _nodesVisitor, nodeVisitor, _tokenVisitor) { - return context.factory.updateSpreadAssignment(node, Debug.checkDefined(nodeVisitor(node.expression, visitor, isExpression))); + [SyntaxKind.SpreadAssignment]: function visitEachChildOfSpreadAssignment( + node, + visitor, + context, + _nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updateSpreadAssignment( + node, + Debug.checkDefined(nodeVisitor(node.expression, visitor, isExpression)), + ); }, // Enum - [SyntaxKind.EnumMember]: function visitEachChildOfEnumMember(node, visitor, context, _nodesVisitor, nodeVisitor, _tokenVisitor) { - return context.factory.updateEnumMember(node, Debug.checkDefined(nodeVisitor(node.name, visitor, isPropertyName)), nodeVisitor(node.initializer, visitor, isExpression)); + [SyntaxKind.EnumMember]: function visitEachChildOfEnumMember( + node, + visitor, + context, + _nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updateEnumMember( + node, + Debug.checkDefined(nodeVisitor(node.name, visitor, isPropertyName)), + nodeVisitor(node.initializer, visitor, isExpression), + ); }, // Top-level nodes - [SyntaxKind.SourceFile]: function visitEachChildOfSourceFile(node, visitor, context, _nodesVisitor, _nodeVisitor, _tokenVisitor) { + [SyntaxKind.SourceFile]: function visitEachChildOfSourceFile( + node, + visitor, + context, + _nodesVisitor, + _nodeVisitor, + _tokenVisitor, + ) { return context.factory.updateSourceFile(node, visitLexicalEnvironment(node.statements, visitor, context)); }, // Transformation nodes - [SyntaxKind.PartiallyEmittedExpression]: function visitEachChildOfPartiallyEmittedExpression(node, visitor, context, _nodesVisitor, nodeVisitor, _tokenVisitor) { - return context.factory.updatePartiallyEmittedExpression(node, Debug.checkDefined(nodeVisitor(node.expression, visitor, isExpression))); + [SyntaxKind.PartiallyEmittedExpression]: function visitEachChildOfPartiallyEmittedExpression( + node, + visitor, + context, + _nodesVisitor, + nodeVisitor, + _tokenVisitor, + ) { + return context.factory.updatePartiallyEmittedExpression( + node, + Debug.checkDefined(nodeVisitor(node.expression, visitor, isExpression)), + ); }, - [SyntaxKind.CommaListExpression]: function visitEachChildOfCommaListExpression(node, visitor, context, nodesVisitor, _nodeVisitor, _tokenVisitor) { + [SyntaxKind.CommaListExpression]: function visitEachChildOfCommaListExpression( + node, + visitor, + context, + nodesVisitor, + _nodeVisitor, + _tokenVisitor, + ) { return context.factory.updateCommaListExpression(node, nodesVisitor(node.elements, visitor, isExpression)); }, }; diff --git a/src/compiler/watch.ts b/src/compiler/watch.ts index fd4d4a8b6ca28..ffef55ce3b9e7 100644 --- a/src/compiler/watch.ts +++ b/src/compiler/watch.ts @@ -140,13 +140,17 @@ export function createDiagnosticReporter(system: System, pretty?: boolean): Diag /** * @returns Whether the screen was cleared. */ -function clearScreenIfNotWatchingForFileChanges(system: System, diagnostic: Diagnostic, options: CompilerOptions): boolean { +function clearScreenIfNotWatchingForFileChanges( + system: System, + diagnostic: Diagnostic, + options: CompilerOptions, +): boolean { if ( - system.clearScreen && - !options.preserveWatchOutput && - !options.extendedDiagnostics && - !options.diagnostics && - contains(screenStartingMessageCodes, diagnostic.code) + system.clearScreen + && !options.preserveWatchOutput + && !options.extendedDiagnostics + && !options.diagnostics + && contains(screenStartingMessageCodes, diagnostic.code) ) { system.clearScreen(); return true; @@ -173,14 +177,14 @@ function getPlainDiagnosticFollowingNewLines(diagnostic: Diagnostic, newLine: st * @internal */ export function getLocaleTimeString(system: System) { - return !system.now ? - new Date().toLocaleTimeString() : + return !system.now + ? new Date().toLocaleTimeString() // On some systems / builds of Node, there's a non-breaking space between the time and AM/PM. // This branch is solely for testing, so just switch it to a normal space for baseline stability. // See: // - https://github.com/nodejs/node/issues/45171 // - https://github.com/nodejs/node/issues/45753 - system.now().toLocaleTimeString("en-US", { timeZone: "UTC" }).replace("\u202f", " "); + : system.now().toLocaleTimeString("en-US", { timeZone: "UTC" }).replace("\u202f", " "); } /** @@ -189,14 +193,14 @@ export function getLocaleTimeString(system: System) { * @internal */ export function createWatchStatusReporter(system: System, pretty?: boolean): WatchStatusReporter { - return pretty ? - (diagnostic, newLine, options) => { + return pretty + ? (diagnostic, newLine, options) => { clearScreenIfNotWatchingForFileChanges(system, diagnostic, options); let output = `[${formatColorAndReset(getLocaleTimeString(system), ForegroundColorEscapeSequences.Grey)}] `; output += `${flattenDiagnosticMessageText(diagnostic.messageText, system.newLine)}${newLine + newLine}`; system.write(output); - } : - (diagnostic, newLine, options) => { + } + : (diagnostic, newLine, options) => { let output = ""; if (!clearScreenIfNotWatchingForFileChanges(system, diagnostic, options)) { @@ -204,7 +208,9 @@ export function createWatchStatusReporter(system: System, pretty?: boolean): Wat } output += `${getLocaleTimeString(system)} - `; - output += `${flattenDiagnosticMessageText(diagnostic.messageText, system.newLine)}${getPlainDiagnosticFollowingNewLines(diagnostic, newLine)}`; + output += `${flattenDiagnosticMessageText(diagnostic.messageText, system.newLine)}${ + getPlainDiagnosticFollowingNewLines(diagnostic, newLine) + }`; system.write(output); }; @@ -215,10 +221,24 @@ export function createWatchStatusReporter(system: System, pretty?: boolean): Wat * * @internal */ -export function parseConfigFileWithSystem(configFileName: string, optionsToExtend: CompilerOptions, extendedConfigCache: Map | undefined, watchOptionsToExtend: WatchOptions | undefined, system: System, reportDiagnostic: DiagnosticReporter): ParsedCommandLine | undefined { +export function parseConfigFileWithSystem( + configFileName: string, + optionsToExtend: CompilerOptions, + extendedConfigCache: Map | undefined, + watchOptionsToExtend: WatchOptions | undefined, + system: System, + reportDiagnostic: DiagnosticReporter, +): ParsedCommandLine | undefined { const host: ParseConfigFileHost = system as any; - host.onUnRecoverableConfigFileDiagnostic = diagnostic => reportUnrecoverableDiagnostic(system, reportDiagnostic, diagnostic); - const result = getParsedCommandLineOfConfigFile(configFileName, optionsToExtend, host, extendedConfigCache, watchOptionsToExtend); + host.onUnRecoverableConfigFileDiagnostic = diagnostic => + reportUnrecoverableDiagnostic(system, reportDiagnostic, diagnostic); + const result = getParsedCommandLineOfConfigFile( + configFileName, + optionsToExtend, + host, + extendedConfigCache, + watchOptionsToExtend, + ); host.onUnRecoverableConfigFileDiagnostic = undefined!; // TODO: GH#18217 return result; } @@ -242,7 +262,10 @@ export function getFilesInErrorForSummary(diagnostics: readonly Diagnostic[]): ( return undefined; } - const diagnosticForFileName = find(diagnostics, diagnostic => diagnostic.file !== undefined && diagnostic.file.fileName === fileName); + const diagnosticForFileName = find( + diagnostics, + diagnostic => diagnostic.file !== undefined && diagnostic.file.fileName === fileName, + ); if (diagnosticForFileName !== undefined) { const { line } = getLineAndCharacterOfPosition(diagnosticForFileName.file!, diagnosticForFileName.start!); @@ -256,9 +279,9 @@ export function getFilesInErrorForSummary(diagnostics: readonly Diagnostic[]): ( /** @internal */ export function getWatchErrorSummaryDiagnosticMessage(errorCount: number) { - return errorCount === 1 ? - Diagnostics.Found_1_error_Watching_for_file_changes : - Diagnostics.Found_0_errors_Watching_for_file_changes; + return errorCount === 1 + ? Diagnostics.Found_1_error_Watching_for_file_changes + : Diagnostics.Found_0_errors_Watching_for_file_changes; } function prettyPathForFileError(error: ReportFileInError, cwd: string) { @@ -286,12 +309,14 @@ export function getErrorSummaryText( let messageAndArgs: DiagnosticAndArguments; if (errorCount === 1) { - messageAndArgs = filesInError[0] !== undefined ? [Diagnostics.Found_1_error_in_0, firstFileReference!] : [Diagnostics.Found_1_error]; + messageAndArgs = filesInError[0] !== undefined ? [Diagnostics.Found_1_error_in_0, firstFileReference!] + : [Diagnostics.Found_1_error]; } else { - messageAndArgs = distinctFileNamesWithLines.length === 0 ? [Diagnostics.Found_0_errors, errorCount] : - distinctFileNamesWithLines.length === 1 ? [Diagnostics.Found_0_errors_in_the_same_file_starting_at_Colon_1, errorCount, firstFileReference!] : - [Diagnostics.Found_0_errors_in_1_files, errorCount, distinctFileNamesWithLines.length]; + messageAndArgs = distinctFileNamesWithLines.length === 0 ? [Diagnostics.Found_0_errors, errorCount] + : distinctFileNamesWithLines.length === 1 + ? [Diagnostics.Found_0_errors_in_the_same_file_starting_at_Colon_1, errorCount, firstFileReference!] + : [Diagnostics.Found_0_errors_in_1_files, errorCount, distinctFileNamesWithLines.length]; } const d = createCompilerDiagnostic(...messageAndArgs); @@ -300,11 +325,15 @@ export function getErrorSummaryText( } function createTabularErrorsDisplay(filesInError: (ReportFileInError | undefined)[], host: HasCurrentDirectory) { - const distinctFiles = filesInError.filter((value, index, self) => index === self.findIndex(file => file?.fileName === value?.fileName)); + const distinctFiles = filesInError.filter((value, index, self) => + index === self.findIndex(file => file?.fileName === value?.fileName) + ); if (distinctFiles.length === 0) return ""; const numberLength = (num: number) => Math.log(num) * Math.LOG10E + 1; - const fileToErrorCount = distinctFiles.map(file => ([file, countWhere(filesInError, fileInError => fileInError!.fileName === file!.fileName)] as const)); + const fileToErrorCount = distinctFiles.map( + file => ([file, countWhere(filesInError, fileInError => fileInError!.fileName === file!.fileName)] as const), + ); const maxErrors = fileToErrorCount.reduce((acc, value) => Math.max(acc, value[1] || 0), 0); const headerRow = Diagnostics.Errors_Files.message; @@ -317,8 +346,8 @@ function createTabularErrorsDisplay(filesInError: (ReportFileInError | undefined fileToErrorCount.forEach(row => { const [file, errorCount] = row; const errorCountDigitsLength = Math.log(errorCount) * Math.LOG10E + 1 | 0; - const leftPadding = errorCountDigitsLength < leftPaddingGoal ? - " ".repeat(leftPaddingGoal - errorCountDigitsLength) + const leftPadding = errorCountDigitsLength < leftPaddingGoal + ? " ".repeat(leftPaddingGoal - errorCountDigitsLength) : ""; const fileRef = prettyPathForFileError(file!, host.getCurrentDirectory()); @@ -349,10 +378,13 @@ export function listFiles(program: Program | T, write: /** @internal */ export function explainFiles(program: Program, write: (s: string) => void) { const reasons = program.getFileIncludeReasons(); - const relativeFileName = (fileName: string) => convertToRelativePath(fileName, program.getCurrentDirectory(), program.getCanonicalFileName); + const relativeFileName = (fileName: string) => + convertToRelativePath(fileName, program.getCurrentDirectory(), program.getCanonicalFileName); for (const file of program.getSourceFiles()) { write(`${toFileName(file, relativeFileName)}`); - reasons.get(file.path)?.forEach(reason => write(` ${fileIncludeReasonToDiagnostics(program, reason, relativeFileName).messageText}`)); + reasons.get(file.path)?.forEach(reason => + write(` ${fileIncludeReasonToDiagnostics(program, reason, relativeFileName).messageText}`) + ); explainIfFileIsRedirectAndImpliedFormat(file, relativeFileName)?.forEach(d => write(` ${d.messageText}`)); } } @@ -392,9 +424,9 @@ export function explainIfFileIsRedirectAndImpliedFormat( if (file.packageJsonScope) { (result ??= []).push(chainDiagnosticMessages( /*details*/ undefined, - file.packageJsonScope.contents.packageJsonContent.type ? - Diagnostics.File_is_CommonJS_module_because_0_has_field_type_whose_value_is_not_module : - Diagnostics.File_is_CommonJS_module_because_0_does_not_have_field_type, + file.packageJsonScope.contents.packageJsonContent.type + ? Diagnostics.File_is_CommonJS_module_because_0_has_field_type_whose_value_is_not_module + : Diagnostics.File_is_CommonJS_module_because_0_does_not_have_field_type, toFileName(last(file.packageJsonLocations!), fileNameConvertor), )); } @@ -417,7 +449,10 @@ export function getMatchedFileSpec(program: Program, fileName: string) { const filePath = program.getCanonicalFileName(fileName); const basePath = getDirectoryPath(getNormalizedAbsolutePath(configFile.fileName, program.getCurrentDirectory())); - return find(configFile.configFileSpecs.validatedFilesSpec, fileSpec => program.getCanonicalFileName(getNormalizedAbsolutePath(fileSpec, basePath)) === filePath); + return find( + configFile.configFileSpecs.validatedFilesSpec, + fileSpec => program.getCanonicalFileName(getNormalizedAbsolutePath(fileSpec, basePath)) === filePath, + ); } /** @internal */ @@ -439,29 +474,41 @@ export function getMatchedIncludeSpec(program: Program, fileName: string) { } /** @internal */ -export function fileIncludeReasonToDiagnostics(program: Program, reason: FileIncludeReason, fileNameConvertor?: (fileName: string) => string): DiagnosticMessageChain { +export function fileIncludeReasonToDiagnostics( + program: Program, + reason: FileIncludeReason, + fileNameConvertor?: (fileName: string) => string, +): DiagnosticMessageChain { const options = program.getCompilerOptions(); if (isReferencedFile(reason)) { const referenceLocation = getReferencedFileLocation(path => program.getSourceFileByPath(path), reason); - const referenceText = isReferenceFileLocation(referenceLocation) ? referenceLocation.file.text.substring(referenceLocation.pos, referenceLocation.end) : `"${referenceLocation.text}"`; + const referenceText = isReferenceFileLocation(referenceLocation) + ? referenceLocation.file.text.substring(referenceLocation.pos, referenceLocation.end) + : `"${referenceLocation.text}"`; let message: DiagnosticMessage; - Debug.assert(isReferenceFileLocation(referenceLocation) || reason.kind === FileIncludeKind.Import, "Only synthetic references are imports"); + Debug.assert( + isReferenceFileLocation(referenceLocation) || reason.kind === FileIncludeKind.Import, + "Only synthetic references are imports", + ); switch (reason.kind) { case FileIncludeKind.Import: if (isReferenceFileLocation(referenceLocation)) { - message = referenceLocation.packageId ? - Diagnostics.Imported_via_0_from_file_1_with_packageId_2 : - Diagnostics.Imported_via_0_from_file_1; + message = referenceLocation.packageId + ? Diagnostics.Imported_via_0_from_file_1_with_packageId_2 + : Diagnostics.Imported_via_0_from_file_1; } else if (referenceLocation.text === externalHelpersModuleNameText) { - message = referenceLocation.packageId ? - Diagnostics.Imported_via_0_from_file_1_with_packageId_2_to_import_importHelpers_as_specified_in_compilerOptions : - Diagnostics.Imported_via_0_from_file_1_to_import_importHelpers_as_specified_in_compilerOptions; + message = referenceLocation.packageId + ? Diagnostics + .Imported_via_0_from_file_1_with_packageId_2_to_import_importHelpers_as_specified_in_compilerOptions + : Diagnostics + .Imported_via_0_from_file_1_to_import_importHelpers_as_specified_in_compilerOptions; } else { - message = referenceLocation.packageId ? - Diagnostics.Imported_via_0_from_file_1_with_packageId_2_to_import_jsx_and_jsxs_factory_functions : - Diagnostics.Imported_via_0_from_file_1_to_import_jsx_and_jsxs_factory_functions; + message = referenceLocation.packageId + ? Diagnostics + .Imported_via_0_from_file_1_with_packageId_2_to_import_jsx_and_jsxs_factory_functions + : Diagnostics.Imported_via_0_from_file_1_to_import_jsx_and_jsxs_factory_functions; } break; case FileIncludeKind.ReferenceFile: @@ -469,9 +516,9 @@ export function fileIncludeReasonToDiagnostics(program: Program, reason: FileInc message = Diagnostics.Referenced_via_0_from_file_1; break; case FileIncludeKind.TypeReferenceDirective: - message = referenceLocation.packageId ? - Diagnostics.Type_library_referenced_via_0_from_file_1_with_packageId_2 : - Diagnostics.Type_library_referenced_via_0_from_file_1; + message = referenceLocation.packageId + ? Diagnostics.Type_library_referenced_via_0_from_file_1_with_packageId_2 + : Diagnostics.Type_library_referenced_via_0_from_file_1; break; case FileIncludeKind.LibReferenceDirective: Debug.assert(!referenceLocation.packageId); @@ -490,24 +537,31 @@ export function fileIncludeReasonToDiagnostics(program: Program, reason: FileInc } switch (reason.kind) { case FileIncludeKind.RootFile: - if (!options.configFile?.configFileSpecs) return chainDiagnosticMessages(/*details*/ undefined, Diagnostics.Root_file_specified_for_compilation); - const fileName = getNormalizedAbsolutePath(program.getRootFileNames()[reason.index], program.getCurrentDirectory()); + if (!options.configFile?.configFileSpecs) { + return chainDiagnosticMessages(/*details*/ undefined, Diagnostics.Root_file_specified_for_compilation); + } + const fileName = getNormalizedAbsolutePath( + program.getRootFileNames()[reason.index], + program.getCurrentDirectory(), + ); const matchedByFiles = getMatchedFileSpec(program, fileName); - if (matchedByFiles) return chainDiagnosticMessages(/*details*/ undefined, Diagnostics.Part_of_files_list_in_tsconfig_json); + if (matchedByFiles) { + return chainDiagnosticMessages(/*details*/ undefined, Diagnostics.Part_of_files_list_in_tsconfig_json); + } const matchedByInclude = getMatchedIncludeSpec(program, fileName); - return isString(matchedByInclude) ? - chainDiagnosticMessages( + return isString(matchedByInclude) + ? chainDiagnosticMessages( /*details*/ undefined, Diagnostics.Matched_by_include_pattern_0_in_1, matchedByInclude, toFileName(options.configFile, fileNameConvertor), - ) : + ) // Could be additional files specified as roots or matched by default include - chainDiagnosticMessages( + : chainDiagnosticMessages( /*details*/ undefined, - matchedByInclude ? - Diagnostics.Matched_by_default_include_pattern_Asterisk_Asterisk_Slash_Asterisk : - Diagnostics.Root_file_specified_for_compilation, + matchedByInclude + ? Diagnostics.Matched_by_default_include_pattern_Asterisk_Asterisk_Slash_Asterisk + : Diagnostics.Root_file_specified_for_compilation, ); case FileIncludeKind.SourceFromProjectReference: case FileIncludeKind.OutputFromProjectReference: @@ -515,31 +569,49 @@ export function fileIncludeReasonToDiagnostics(program: Program, reason: FileInc const referencedResolvedRef = Debug.checkDefined(program.getResolvedProjectReferences()?.[reason.index]); return chainDiagnosticMessages( /*details*/ undefined, - outFile(options) ? - isOutput ? - Diagnostics.Output_from_referenced_project_0_included_because_1_specified : - Diagnostics.Source_from_referenced_project_0_included_because_1_specified : - isOutput ? - Diagnostics.Output_from_referenced_project_0_included_because_module_is_specified_as_none : - Diagnostics.Source_from_referenced_project_0_included_because_module_is_specified_as_none, + outFile(options) + ? isOutput + ? Diagnostics.Output_from_referenced_project_0_included_because_1_specified + : Diagnostics.Source_from_referenced_project_0_included_because_1_specified + : isOutput + ? Diagnostics.Output_from_referenced_project_0_included_because_module_is_specified_as_none + : Diagnostics.Source_from_referenced_project_0_included_because_module_is_specified_as_none, toFileName(referencedResolvedRef.sourceFile.fileName, fileNameConvertor), options.outFile ? "--outFile" : "--out", ); case FileIncludeKind.AutomaticTypeDirectiveFile: { - const messageAndArgs: DiagnosticAndArguments = options.types ? - reason.packageId ? - [Diagnostics.Entry_point_of_type_library_0_specified_in_compilerOptions_with_packageId_1, reason.typeReference, packageIdToString(reason.packageId)] : - [Diagnostics.Entry_point_of_type_library_0_specified_in_compilerOptions, reason.typeReference] : - reason.packageId ? - [Diagnostics.Entry_point_for_implicit_type_library_0_with_packageId_1, reason.typeReference, packageIdToString(reason.packageId)] : - [Diagnostics.Entry_point_for_implicit_type_library_0, reason.typeReference]; + const messageAndArgs: DiagnosticAndArguments = options.types + ? reason.packageId + ? [ + Diagnostics.Entry_point_of_type_library_0_specified_in_compilerOptions_with_packageId_1, + reason.typeReference, + packageIdToString(reason.packageId), + ] + : [Diagnostics.Entry_point_of_type_library_0_specified_in_compilerOptions, reason.typeReference] + : reason.packageId + ? [ + Diagnostics.Entry_point_for_implicit_type_library_0_with_packageId_1, + reason.typeReference, + packageIdToString(reason.packageId), + ] + : [Diagnostics.Entry_point_for_implicit_type_library_0, reason.typeReference]; return chainDiagnosticMessages(/*details*/ undefined, ...messageAndArgs); } case FileIncludeKind.LibFile: { - if (reason.index !== undefined) return chainDiagnosticMessages(/*details*/ undefined, Diagnostics.Library_0_specified_in_compilerOptions, options.lib![reason.index]); - const target = forEachEntry(targetOptionDeclaration.type, (value, key) => value === getEmitScriptTarget(options) ? key : undefined); - const messageAndArgs: DiagnosticAndArguments = target ? [Diagnostics.Default_library_for_target_0, target] : [Diagnostics.Default_library]; + if (reason.index !== undefined) { + return chainDiagnosticMessages( + /*details*/ undefined, + Diagnostics.Library_0_specified_in_compilerOptions, + options.lib![reason.index], + ); + } + const target = forEachEntry( + targetOptionDeclaration.type, + (value, key) => value === getEmitScriptTarget(options) ? key : undefined, + ); + const messageAndArgs: DiagnosticAndArguments = target ? [Diagnostics.Default_library_for_target_0, target] + : [Diagnostics.Default_library]; return chainDiagnosticMessages(/*details*/ undefined, ...messageAndArgs); } default: @@ -594,7 +666,13 @@ export function emitFilesAndReportErrors( // Emit and report any errors we ran into. const emitResult = isListFilesOnly ? { emitSkipped: true, diagnostics: emptyArray } - : program.emit(/*targetSourceFile*/ undefined, writeFile, cancellationToken, emitOnlyDtsFiles, customTransformers); + : program.emit( + /*targetSourceFile*/ undefined, + writeFile, + cancellationToken, + emitOnlyDtsFiles, + customTransformers, + ); const { emittedFiles, diagnostics: emitDiagnostics } = emitResult; addRange(allDiagnostics, emitDiagnostics); @@ -730,8 +808,13 @@ export interface WatchFactoryWithLog extends WatchFactory(host: WatchFactoryHost & { trace?(s: string): void; }, options: { extendedDiagnostics?: boolean; diagnostics?: boolean; }) { - const watchLogLevel = host.trace ? options.extendedDiagnostics ? WatchLogLevel.Verbose : options.diagnostics ? WatchLogLevel.TriggerOnly : WatchLogLevel.None : WatchLogLevel.None; +export function createWatchFactory( + host: WatchFactoryHost & { trace?(s: string): void; }, + options: { extendedDiagnostics?: boolean; diagnostics?: boolean; }, +) { + const watchLogLevel = host.trace + ? options.extendedDiagnostics ? WatchLogLevel.Verbose + : options.diagnostics ? WatchLogLevel.TriggerOnly : WatchLogLevel.None : WatchLogLevel.None; const writeLog: (s: string) => void = watchLogLevel !== WatchLogLevel.None ? (s => host.trace!(s)) : noop; const result = getWatchFactory(host, watchLogLevel, writeLog) as WatchFactoryWithLog; result.writeLog = writeLog; @@ -739,7 +822,11 @@ export function createWatchFactory(host: WatchFactoryHost & { tra } /** @internal */ -export function createCompilerHostFromProgramHost(host: ProgramHost, getCompilerOptions: () => CompilerOptions, directoryStructureHost: DirectoryStructureHost = host): CompilerHost { +export function createCompilerHostFromProgramHost( + host: ProgramHost, + getCompilerOptions: () => CompilerOptions, + directoryStructureHost: DirectoryStructureHost = host, +): CompilerHost { const useCaseSensitiveFileNames = host.useCaseSensitiveFileNames(); const compilerHost: CompilerHost = { getSourceFile: createGetSourceFile( @@ -828,7 +915,10 @@ export function setGetSourceFileAsHashVersioned(compilerHost: CompilerHost) { * * @internal */ -export function createProgramHost(system: System, createProgram: CreateProgram | undefined): ProgramHost { +export function createProgramHost( + system: System, + createProgram: CreateProgram | undefined, +): ProgramHost { const getDefaultLibLocation = memoize(() => getDirectoryPath(normalizePath(system.getExecutingFilePath()))); return { useCaseSensitiveFileNames: () => system.useCaseSensitiveFileNames, @@ -840,7 +930,8 @@ export function createProgramHost system.readFile(path, encoding), directoryExists: path => system.directoryExists(path), getDirectories: path => system.getDirectories(path), - readDirectory: (path, extensions, exclude, include, depth) => system.readDirectory(path, extensions, exclude, include, depth), + readDirectory: (path, extensions, exclude, include, depth) => + system.readDirectory(path, extensions, exclude, include, depth), realpath: maybeBind(system, system.realpath), getEnvironmentVariable: maybeBind(system, system.getEnvironmentVariable), trace: s => system.write(s + system.newLine), @@ -856,7 +947,12 @@ export function createProgramHost(system = sys, createProgram: CreateProgram | undefined, reportDiagnostic: DiagnosticReporter, reportWatchStatus?: WatchStatusReporter): WatchCompilerHost { +function createWatchCompilerHost( + system = sys, + createProgram: CreateProgram | undefined, + reportDiagnostic: DiagnosticReporter, + reportWatchStatus?: WatchStatusReporter, +): WatchCompilerHost { const write = (s: string) => system.write(s + system.newLine); const result = createProgramHost(system, createProgram) as WatchCompilerHost; copyProperties(result, createWatchHost(system, reportWatchStatus)); @@ -897,7 +993,9 @@ export interface CreateWatchCompilerHostInput { } /** @internal */ -export interface CreateWatchCompilerHostOfConfigFileInput extends CreateWatchCompilerHostInput { +export interface CreateWatchCompilerHostOfConfigFileInput + extends CreateWatchCompilerHostInput +{ configFileName: string; optionsToExtend?: CompilerOptions; watchOptionsToExtend?: WatchOptions; @@ -908,7 +1006,9 @@ export interface CreateWatchCompilerHostOfConfigFileInput({ +export function createWatchCompilerHostOfConfigFile< + T extends BuilderProgram = EmitAndSemanticDiagnosticsBuilderProgram, +>({ configFileName, optionsToExtend, watchOptionsToExtend, @@ -919,8 +1019,14 @@ export function createWatchCompilerHostOfConfigFile): WatchCompilerHostOfConfigFile { const diagnosticReporter = reportDiagnostic || createDiagnosticReporter(system); - const host = createWatchCompilerHost(system, createProgram, diagnosticReporter, reportWatchStatus) as WatchCompilerHostOfConfigFile; - host.onUnRecoverableConfigFileDiagnostic = diagnostic => reportUnrecoverableDiagnostic(system, diagnosticReporter, diagnostic); + const host = createWatchCompilerHost( + system, + createProgram, + diagnosticReporter, + reportWatchStatus, + ) as WatchCompilerHostOfConfigFile; + host.onUnRecoverableConfigFileDiagnostic = diagnostic => + reportUnrecoverableDiagnostic(system, diagnosticReporter, diagnostic); host.configFileName = configFileName; host.optionsToExtend = optionsToExtend; host.watchOptionsToExtend = watchOptionsToExtend; @@ -929,7 +1035,9 @@ export function createWatchCompilerHostOfConfigFile extends CreateWatchCompilerHostInput { +export interface CreateWatchCompilerHostOfFilesAndCompilerOptionsInput + extends CreateWatchCompilerHostInput +{ rootFiles: string[]; options: CompilerOptions; watchOptions: WatchOptions | undefined; @@ -940,7 +1048,9 @@ export interface CreateWatchCompilerHostOfFilesAndCompilerOptionsInput({ +export function createWatchCompilerHostOfFilesAndCompilerOptions< + T extends BuilderProgram = EmitAndSemanticDiagnosticsBuilderProgram, +>({ rootFiles, options, watchOptions, @@ -950,7 +1060,12 @@ export function createWatchCompilerHostOfFilesAndCompilerOptions): WatchCompilerHostOfFilesAndCompilerOptions { - const host = createWatchCompilerHost(system, createProgram, reportDiagnostic || createDiagnosticReporter(system), reportWatchStatus) as WatchCompilerHostOfFilesAndCompilerOptions; + const host = createWatchCompilerHost( + system, + createProgram, + reportDiagnostic || createDiagnosticReporter(system), + reportWatchStatus, + ) as WatchCompilerHostOfFilesAndCompilerOptions; host.rootFiles = rootFiles; host.options = options; host.watchOptions = watchOptions; @@ -979,7 +1094,9 @@ export function performIncrementalCompilation(input: IncrementalCompilationOptio builderProgram, input.reportDiagnostic || createDiagnosticReporter(system), s => host.trace && host.trace(s), - input.reportErrorSummary || input.options.pretty ? (errorCount, filesInError) => system.write(getErrorSummaryText(errorCount, filesInError, system.newLine, host)) : undefined, + input.reportErrorSummary || input.options.pretty + ? (errorCount, filesInError) => + system.write(getErrorSummaryText(errorCount, filesInError, system.newLine, host)) : undefined, ); if (input.afterProgramEmitAndDiagnostics) input.afterProgramEmitAndDiagnostics(builderProgram); return exitStatus; diff --git a/src/compiler/watchPublic.ts b/src/compiler/watchPublic.ts index e963067868d66..f64373dfd863e 100644 --- a/src/compiler/watchPublic.ts +++ b/src/compiler/watchPublic.ts @@ -123,7 +123,10 @@ export function createIncrementalCompilerHost(options: CompilerOptions, system = host.createHash = maybeBind(system, system.createHash); host.storeFilesChangingSignatureDuringEmit = system.storeFilesChangingSignatureDuringEmit; setGetSourceFileAsHashVersioned(host); - changeCompilerHostLikeToUseCache(host, fileName => toPath(fileName, host.getCurrentDirectory(), host.getCanonicalFileName)); + changeCompilerHostLikeToUseCache( + host, + fileName => toPath(fileName, host.getCurrentDirectory(), host.getCanonicalFileName), + ); return host; } @@ -150,9 +153,21 @@ export function createIncrementalProgram void; +export type WatchStatusReporter = ( + diagnostic: Diagnostic, + newLine: string, + options: CompilerOptions, + errorCount?: number, +) => void; /** Create the program with rootNames and options, if they are undefined, oldProgram and new configFile diagnostics create new program */ -export type CreateProgram = (rootNames: readonly string[] | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: T, configFileParsingDiagnostics?: readonly Diagnostic[], projectReferences?: readonly ProjectReference[] | undefined) => T; +export type CreateProgram = ( + rootNames: readonly string[] | undefined, + options: CompilerOptions | undefined, + host?: CompilerHost, + oldProgram?: T, + configFileParsingDiagnostics?: readonly Diagnostic[], + projectReferences?: readonly ProjectReference[] | undefined, +) => T; /** Host that has watch functionality used in --watch mode */ export interface WatchHost { @@ -160,9 +175,19 @@ export interface WatchHost { onWatchStatusChange?(diagnostic: Diagnostic, newLine: string, options: CompilerOptions, errorCount?: number): void; /** Used to watch changes in source files, missing files needed to update the program or config file */ - watchFile(path: string, callback: FileWatcherCallback, pollingInterval?: number, options?: WatchOptions): FileWatcher; + watchFile( + path: string, + callback: FileWatcherCallback, + pollingInterval?: number, + options?: WatchOptions, + ): FileWatcher; /** Used to watch resolved module's failed lookup locations, config file specs, type roots where auto type reference directives are added */ - watchDirectory(path: string, callback: DirectoryWatcherCallback, recursive?: boolean, options?: WatchOptions): FileWatcher; + watchDirectory( + path: string, + callback: DirectoryWatcherCallback, + recursive?: boolean, + options?: WatchOptions, + ): FileWatcher; /** If provided, will be used to set delayed compilation, so that multiple changes in short span are compiled together */ setTimeout?(callback: (...args: any[]) => void, ms: number, ...args: any[]): any; /** If provided, will be used to reset existing delayed compilation */ @@ -198,7 +223,13 @@ export interface ProgramHost { /** If provided, used in resolutions as well as handling directory structure */ getDirectories?(path: string): string[]; /** If provided, used to cache and handle directory structure modifications */ - readDirectory?(path: string, extensions?: readonly string[], exclude?: readonly string[], include?: readonly string[], depth?: number): string[]; + readDirectory?( + path: string, + extensions?: readonly string[], + exclude?: readonly string[], + include?: readonly string[], + depth?: number, + ): string[]; /** Symbol links resolution */ realpath?(path: string): string; @@ -212,13 +243,26 @@ export interface ProgramHost { * * If provided, used to resolve the module names, otherwise typescript's default module resolution */ - resolveModuleNames?(moduleNames: string[], containingFile: string, reusedNames: string[] | undefined, redirectedReference: ResolvedProjectReference | undefined, options: CompilerOptions, containingSourceFile?: SourceFile): (ResolvedModule | undefined)[]; + resolveModuleNames?( + moduleNames: string[], + containingFile: string, + reusedNames: string[] | undefined, + redirectedReference: ResolvedProjectReference | undefined, + options: CompilerOptions, + containingSourceFile?: SourceFile, + ): (ResolvedModule | undefined)[]; /** * @deprecated supply resolveTypeReferenceDirectiveReferences instead for resolution that can handle newer resolution modes like nodenext * * If provided, used to resolve type reference directives, otherwise typescript's default resolution */ - resolveTypeReferenceDirectives?(typeReferenceDirectiveNames: string[] | readonly FileReference[], containingFile: string, redirectedReference: ResolvedProjectReference | undefined, options: CompilerOptions, containingFileMode?: ResolutionMode): (ResolvedTypeReferenceDirective | undefined)[]; + resolveTypeReferenceDirectives?( + typeReferenceDirectiveNames: string[] | readonly FileReference[], + containingFile: string, + redirectedReference: ResolvedProjectReference | undefined, + options: CompilerOptions, + containingFileMode?: ResolutionMode, + ): (ResolvedTypeReferenceDirective | undefined)[]; resolveModuleNameLiterals?( moduleLiterals: readonly StringLiteralLike[], containingFile: string, @@ -299,7 +343,9 @@ export interface WatchCompilerHostOfFilesAndCompilerOptions extends WatchCompilerHost, ConfigFileDiagnosticsReporter { +export interface WatchCompilerHostOfConfigFile + extends WatchCompilerHost, ConfigFileDiagnosticsReporter +{ /** Name of the config file to compile */ configFileName: string; @@ -314,7 +360,13 @@ export interface WatchCompilerHostOfConfigFile extends * Used to generate source file names from the config file and its include, exclude, files rules * and also to cache the directory stucture */ - readDirectory(path: string, extensions?: readonly string[], exclude?: readonly string[], include?: readonly string[], depth?: number): string[]; + readDirectory( + path: string, + extensions?: readonly string[], + exclude?: readonly string[], + include?: readonly string[], + depth?: number, + ): string[]; } /** @@ -357,9 +409,36 @@ export interface WatchOfFilesAndCompilerOptions extends Watch { /** * Create the watch compiler host for either configFile or fileNames and its options */ -export function createWatchCompilerHost(configFileName: string, optionsToExtend: CompilerOptions | undefined, system: System, createProgram?: CreateProgram, reportDiagnostic?: DiagnosticReporter, reportWatchStatus?: WatchStatusReporter, watchOptionsToExtend?: WatchOptions, extraFileExtensions?: readonly FileExtensionInfo[]): WatchCompilerHostOfConfigFile; -export function createWatchCompilerHost(rootFiles: string[], options: CompilerOptions, system: System, createProgram?: CreateProgram, reportDiagnostic?: DiagnosticReporter, reportWatchStatus?: WatchStatusReporter, projectReferences?: readonly ProjectReference[], watchOptions?: WatchOptions): WatchCompilerHostOfFilesAndCompilerOptions; -export function createWatchCompilerHost(rootFilesOrConfigFileName: string | string[], options: CompilerOptions | undefined, system: System, createProgram?: CreateProgram, reportDiagnostic?: DiagnosticReporter, reportWatchStatus?: WatchStatusReporter, projectReferencesOrWatchOptionsToExtend?: readonly ProjectReference[] | WatchOptions, watchOptionsOrExtraFileExtensions?: WatchOptions | readonly FileExtensionInfo[]): WatchCompilerHostOfFilesAndCompilerOptions | WatchCompilerHostOfConfigFile { +export function createWatchCompilerHost( + configFileName: string, + optionsToExtend: CompilerOptions | undefined, + system: System, + createProgram?: CreateProgram, + reportDiagnostic?: DiagnosticReporter, + reportWatchStatus?: WatchStatusReporter, + watchOptionsToExtend?: WatchOptions, + extraFileExtensions?: readonly FileExtensionInfo[], +): WatchCompilerHostOfConfigFile; +export function createWatchCompilerHost( + rootFiles: string[], + options: CompilerOptions, + system: System, + createProgram?: CreateProgram, + reportDiagnostic?: DiagnosticReporter, + reportWatchStatus?: WatchStatusReporter, + projectReferences?: readonly ProjectReference[], + watchOptions?: WatchOptions, +): WatchCompilerHostOfFilesAndCompilerOptions; +export function createWatchCompilerHost( + rootFilesOrConfigFileName: string | string[], + options: CompilerOptions | undefined, + system: System, + createProgram?: CreateProgram, + reportDiagnostic?: DiagnosticReporter, + reportWatchStatus?: WatchStatusReporter, + projectReferencesOrWatchOptionsToExtend?: readonly ProjectReference[] | WatchOptions, + watchOptionsOrExtraFileExtensions?: WatchOptions | readonly FileExtensionInfo[], +): WatchCompilerHostOfFilesAndCompilerOptions | WatchCompilerHostOfConfigFile { if (isArray(rootFilesOrConfigFileName)) { return createWatchCompilerHostOfFilesAndCompilerOptions({ rootFiles: rootFilesOrConfigFileName, @@ -405,12 +484,18 @@ type WatchCompilerHostOfFilesAndCompilerOptionsOrConfigFile(host: WatchCompilerHostOfFilesAndCompilerOptions): WatchOfFilesAndCompilerOptions; +export function createWatchProgram( + host: WatchCompilerHostOfFilesAndCompilerOptions, +): WatchOfFilesAndCompilerOptions; /** * Creates the watch from the host for config file */ -export function createWatchProgram(host: WatchCompilerHostOfConfigFile): WatchOfConfigFile; -export function createWatchProgram(host: WatchCompilerHostOfFilesAndCompilerOptionsOrConfigFile): WatchOfFilesAndCompilerOptions | WatchOfConfigFile { +export function createWatchProgram( + host: WatchCompilerHostOfConfigFile, +): WatchOfConfigFile; +export function createWatchProgram( + host: WatchCompilerHostOfFilesAndCompilerOptionsOrConfigFile, +): WatchOfFilesAndCompilerOptions | WatchOfConfigFile { interface FilePresentOnHost { version: string; sourceFile: SourceFile; @@ -441,14 +526,21 @@ export function createWatchProgram(host: WatchCompiler const useCaseSensitiveFileNames = host.useCaseSensitiveFileNames(); const currentDirectory = host.getCurrentDirectory(); - const { configFileName, optionsToExtend: optionsToExtendForConfigFile = {}, watchOptionsToExtend, extraFileExtensions, createProgram } = host; + const { + configFileName, + optionsToExtend: optionsToExtendForConfigFile = {}, + watchOptionsToExtend, + extraFileExtensions, + createProgram, + } = host; let { rootFiles: rootFileNames, options: compilerOptions, watchOptions, projectReferences } = host; let wildcardDirectories: MapLike | undefined; let configFileParsingDiagnostics: Diagnostic[] | undefined; let canConfigFileJsonReportNoInputFiles = false; let hasChangedConfigFileParsingErrors = false; - const cachedDirectoryStructureHost = configFileName === undefined ? undefined : createCachedDirectoryStructureHost(host, currentDirectory, useCaseSensitiveFileNames); + const cachedDirectoryStructureHost = configFileName === undefined ? undefined + : createCachedDirectoryStructureHost(host, currentDirectory, useCaseSensitiveFileNames); const directoryStructureHost: DirectoryStructureHost = cachedDirectoryStructureHost || host; const parseConfigFileHost = parseConfigHostFromCompilerHostLike(host, directoryStructureHost); @@ -475,14 +567,23 @@ export function createWatchProgram(host: WatchCompiler writeLog(`Current directory: ${currentDirectory} CaseSensitiveFileNames: ${useCaseSensitiveFileNames}`); let configFileWatcher: FileWatcher | undefined; if (configFileName) { - configFileWatcher = watchFile(configFileName, scheduleProgramReload, PollingInterval.High, watchOptions, WatchType.ConfigFile); + configFileWatcher = watchFile( + configFileName, + scheduleProgramReload, + PollingInterval.High, + watchOptions, + WatchType.ConfigFile, + ); } - const compilerHost = createCompilerHostFromProgramHost(host, () => compilerOptions!, directoryStructureHost) as CompilerHost & ResolutionCacheHost; + const compilerHost = createCompilerHostFromProgramHost(host, () => compilerOptions!, directoryStructureHost) as + & CompilerHost + & ResolutionCacheHost; setGetSourceFileAsHashVersioned(compilerHost); // Members for CompilerHost const getNewSourceFile = compilerHost.getSourceFile; - compilerHost.getSourceFile = (fileName, ...args) => getVersionedSourceFileByPath(fileName, toPath(fileName), ...args); + compilerHost.getSourceFile = (fileName, ...args) => + getVersionedSourceFileByPath(fileName, toPath(fileName), ...args); compilerHost.getSourceFileByPath = getVersionedSourceFileByPath; compilerHost.getNewLine = () => newLine; compilerHost.fileExists = fileExists; @@ -492,11 +593,15 @@ export function createWatchProgram(host: WatchCompiler compilerHost.toPath = toPath; compilerHost.getCompilationSettings = () => compilerOptions!; compilerHost.useSourceOfProjectReferenceRedirect = maybeBind(host, host.useSourceOfProjectReferenceRedirect); - compilerHost.watchDirectoryOfFailedLookupLocation = (dir, cb, flags) => watchDirectory(dir, cb, flags, watchOptions, WatchType.FailedLookupLocations); - compilerHost.watchAffectingFileLocation = (file, cb) => watchFile(file, cb, PollingInterval.High, watchOptions, WatchType.AffectingFileLocation); - compilerHost.watchTypeRootsDirectory = (dir, cb, flags) => watchDirectory(dir, cb, flags, watchOptions, WatchType.TypeRoots); + compilerHost.watchDirectoryOfFailedLookupLocation = (dir, cb, flags) => + watchDirectory(dir, cb, flags, watchOptions, WatchType.FailedLookupLocations); + compilerHost.watchAffectingFileLocation = (file, cb) => + watchFile(file, cb, PollingInterval.High, watchOptions, WatchType.AffectingFileLocation); + compilerHost.watchTypeRootsDirectory = (dir, cb, flags) => + watchDirectory(dir, cb, flags, watchOptions, WatchType.TypeRoots); compilerHost.getCachedDirectoryStructureHost = () => cachedDirectoryStructureHost; - compilerHost.scheduleInvalidateResolutionsOfFailedLookupLocations = scheduleInvalidateResolutionsOfFailedLookupLocations; + compilerHost.scheduleInvalidateResolutionsOfFailedLookupLocations = + scheduleInvalidateResolutionsOfFailedLookupLocations; compilerHost.onInvalidatedResolution = scheduleProgramUpdate; compilerHost.onChangedAutomaticTypeDirectiveNames = scheduleProgramUpdate; compilerHost.fileIsOpen = returnFalse; @@ -507,9 +612,9 @@ export function createWatchProgram(host: WatchCompiler // Cache for the module resolution const resolutionCache = createResolutionCache( compilerHost, - configFileName ? - getDirectoryPath(getNormalizedAbsolutePath(configFileName, currentDirectory)) : - currentDirectory, + configFileName + ? getDirectoryPath(getNormalizedAbsolutePath(configFileName, currentDirectory)) + : currentDirectory, /*logChangesWhenResolvingModule*/ false, ); // Resolve module using host module resolution strategy if provided otherwise use resolution cache to resolve module names @@ -518,26 +623,30 @@ export function createWatchProgram(host: WatchCompiler if (!compilerHost.resolveModuleNameLiterals && !compilerHost.resolveModuleNames) { compilerHost.resolveModuleNameLiterals = resolutionCache.resolveModuleNameLiterals.bind(resolutionCache); } - compilerHost.resolveTypeReferenceDirectiveReferences = maybeBind(host, host.resolveTypeReferenceDirectiveReferences); + compilerHost.resolveTypeReferenceDirectiveReferences = maybeBind( + host, + host.resolveTypeReferenceDirectiveReferences, + ); compilerHost.resolveTypeReferenceDirectives = maybeBind(host, host.resolveTypeReferenceDirectives); if (!compilerHost.resolveTypeReferenceDirectiveReferences && !compilerHost.resolveTypeReferenceDirectives) { - compilerHost.resolveTypeReferenceDirectiveReferences = resolutionCache.resolveTypeReferenceDirectiveReferences.bind(resolutionCache); + compilerHost.resolveTypeReferenceDirectiveReferences = resolutionCache.resolveTypeReferenceDirectiveReferences + .bind(resolutionCache); } - compilerHost.resolveLibrary = !host.resolveLibrary ? - resolutionCache.resolveLibrary.bind(resolutionCache) : - host.resolveLibrary.bind(host); - compilerHost.getModuleResolutionCache = host.resolveModuleNameLiterals || host.resolveModuleNames ? - maybeBind(host, host.getModuleResolutionCache) : - (() => resolutionCache.getModuleResolutionCache()); - const userProvidedResolution = !!host.resolveModuleNameLiterals || !!host.resolveTypeReferenceDirectiveReferences || - !!host.resolveModuleNames || !!host.resolveTypeReferenceDirectives; + compilerHost.resolveLibrary = !host.resolveLibrary + ? resolutionCache.resolveLibrary.bind(resolutionCache) + : host.resolveLibrary.bind(host); + compilerHost.getModuleResolutionCache = host.resolveModuleNameLiterals || host.resolveModuleNames + ? maybeBind(host, host.getModuleResolutionCache) + : (() => resolutionCache.getModuleResolutionCache()); + const userProvidedResolution = !!host.resolveModuleNameLiterals || !!host.resolveTypeReferenceDirectiveReferences + || !!host.resolveModuleNames || !!host.resolveTypeReferenceDirectives; // All resolutions are invalid if user provided resolutions and didnt supply hasInvalidatedResolutions - const customHasInvalidatedResolutions = userProvidedResolution ? - maybeBind(host, host.hasInvalidatedResolutions) || returnTrue : - returnFalse; - const customHasInvalidLibResolutions = host.resolveLibrary ? - maybeBind(host, host.hasInvalidatedLibResolutions) || returnTrue : - returnFalse; + const customHasInvalidatedResolutions = userProvidedResolution + ? maybeBind(host, host.hasInvalidatedResolutions) || returnTrue + : returnFalse; + const customHasInvalidLibResolutions = host.resolveLibrary + ? maybeBind(host, host.hasInvalidatedLibResolutions) || returnTrue + : returnFalse; builderProgram = readBuilderProgram(compilerOptions, compilerHost) as any as T; synchronizeProgram(); @@ -546,11 +655,18 @@ export function createWatchProgram(host: WatchCompiler watchConfigFileWildCardDirectories(); // Update extended config file watch - if (configFileName) updateExtendedConfigFilesWatches(toPath(configFileName), compilerOptions, watchOptions, WatchType.ExtendedConfigFile); + if (configFileName) { + updateExtendedConfigFilesWatches( + toPath(configFileName), + compilerOptions, + watchOptions, + WatchType.ExtendedConfigFile, + ); + } - return configFileName ? - { getCurrentProgram: getCurrentBuilderProgram, getProgram: updateProgram, close } : - { getCurrentProgram: getCurrentBuilderProgram, getProgram: updateProgram, updateRootFileNames, close }; + return configFileName + ? { getCurrentProgram: getCurrentBuilderProgram, getProgram: updateProgram, close } + : { getCurrentProgram: getCurrentBuilderProgram, getProgram: updateProgram, updateRootFileNames, close }; function close() { clearInvalidateResolutionsOfFailedLookupLocations(); @@ -614,7 +730,8 @@ export function createWatchProgram(host: WatchCompiler } } - const { hasInvalidatedResolutions, hasInvalidatedLibResolutions } = resolutionCache.createHasInvalidatedResolutions(customHasInvalidatedResolutions, customHasInvalidLibResolutions); + const { hasInvalidatedResolutions, hasInvalidatedLibResolutions } = resolutionCache + .createHasInvalidatedResolutions(customHasInvalidatedResolutions, customHasInvalidLibResolutions); const { originalReadFile, originalFileExists, @@ -623,12 +740,32 @@ export function createWatchProgram(host: WatchCompiler originalWriteFile, readFileWithCache, } = changeCompilerHostLikeToUseCache(compilerHost, toPath); - if (isProgramUptoDate(getCurrentProgram(), rootFileNames, compilerOptions, path => getSourceVersion(path, readFileWithCache), fileName => compilerHost.fileExists(fileName), hasInvalidatedResolutions, hasInvalidatedLibResolutions, hasChangedAutomaticTypeDirectiveNames, getParsedCommandLine, projectReferences)) { + if ( + isProgramUptoDate( + getCurrentProgram(), + rootFileNames, + compilerOptions, + path => getSourceVersion(path, readFileWithCache), + fileName => compilerHost.fileExists(fileName), + hasInvalidatedResolutions, + hasInvalidatedLibResolutions, + hasChangedAutomaticTypeDirectiveNames, + getParsedCommandLine, + projectReferences, + ) + ) { if (hasChangedConfigFileParsingErrors) { if (reportFileChangeDetectedOnCreateProgram) { reportWatchDiagnostic(Diagnostics.File_change_detected_Starting_incremental_compilation); } - builderProgram = createProgram(/*rootNames*/ undefined, /*options*/ undefined, compilerHost, builderProgram, configFileParsingDiagnostics, projectReferences); + builderProgram = createProgram( + /*rootNames*/ undefined, + /*options*/ undefined, + compilerHost, + builderProgram, + configFileParsingDiagnostics, + projectReferences, + ); hasChangedConfigFileParsingErrors = false; } } @@ -653,7 +790,10 @@ export function createWatchProgram(host: WatchCompiler return builderProgram; } - function createNewProgram(hasInvalidatedResolutions: HasInvalidatedResolutions, hasInvalidatedLibResolutions: HasInvalidatedLibResolutions) { + function createNewProgram( + hasInvalidatedResolutions: HasInvalidatedResolutions, + hasInvalidatedLibResolutions: HasInvalidatedLibResolutions, + ) { // Compile the program writeLog("CreatingProgramWith::"); writeLog(` roots: ${JSON.stringify(rootFileNames)}`); @@ -668,11 +808,22 @@ export function createWatchProgram(host: WatchCompiler compilerHost.hasInvalidatedLibResolutions = hasInvalidatedLibResolutions; compilerHost.hasChangedAutomaticTypeDirectiveNames = hasChangedAutomaticTypeDirectiveNames; const oldProgram = getCurrentProgram(); - builderProgram = createProgram(rootFileNames, compilerOptions, compilerHost, builderProgram, configFileParsingDiagnostics, projectReferences); + builderProgram = createProgram( + rootFileNames, + compilerOptions, + compilerHost, + builderProgram, + configFileParsingDiagnostics, + projectReferences, + ); resolutionCache.finishCachingPerDirectoryResolution(builderProgram.getProgram(), oldProgram); // Update watches - updateMissingFilePathsWatch(builderProgram.getProgram(), missingFilesMap || (missingFilesMap = new Map()), watchMissingFilePath); + updateMissingFilePathsWatch( + builderProgram.getProgram(), + missingFilesMap || (missingFilesMap = new Map()), + watchMissingFilePath, + ); if (needsUpdateInTypeRootWatch) { resolutionCache.updateTypeRootsWatch(); } @@ -710,7 +861,9 @@ export function createWatchProgram(host: WatchCompiler return typeof hostSourceFile === "boolean"; } - function isFilePresenceUnknownOnHost(hostSourceFile: FileMayBePresentOnHost): hostSourceFile is FilePresenceUnknownOnHost { + function isFilePresenceUnknownOnHost( + hostSourceFile: FileMayBePresentOnHost, + ): hostSourceFile is FilePresenceUnknownOnHost { return typeof (hostSourceFile as FilePresenceUnknownOnHost).version === "boolean"; } @@ -725,7 +878,13 @@ export function createWatchProgram(host: WatchCompiler return directoryStructureHost.fileExists(fileName); } - function getVersionedSourceFileByPath(fileName: string, path: Path, languageVersionOrOptions: ScriptTarget | CreateSourceFileOptions, onError?: (message: string) => void, shouldCreateNewSourceFile?: boolean): SourceFile | undefined { + function getVersionedSourceFileByPath( + fileName: string, + path: Path, + languageVersionOrOptions: ScriptTarget | CreateSourceFileOptions, + onError?: (message: string) => void, + shouldCreateNewSourceFile?: boolean, + ): SourceFile | undefined { const hostSourceFile = sourceFilesCache.get(path); // No source file on the host if (isFileMissingOnHost(hostSourceFile)) { @@ -733,8 +892,12 @@ export function createWatchProgram(host: WatchCompiler } // Create new source file if requested or the versions dont match - const impliedNodeFormat = typeof languageVersionOrOptions === "object" ? languageVersionOrOptions.impliedNodeFormat : undefined; - if (hostSourceFile === undefined || shouldCreateNewSourceFile || isFilePresenceUnknownOnHost(hostSourceFile) || hostSourceFile.sourceFile.impliedNodeFormat !== impliedNodeFormat) { + const impliedNodeFormat = typeof languageVersionOrOptions === "object" + ? languageVersionOrOptions.impliedNodeFormat : undefined; + if ( + hostSourceFile === undefined || shouldCreateNewSourceFile || isFilePresenceUnknownOnHost(hostSourceFile) + || hostSourceFile.sourceFile.impliedNodeFormat !== impliedNodeFormat + ) { const sourceFile = getNewSourceFile(fileName, languageVersionOrOptions, onError); if (hostSourceFile) { if (sourceFile) { @@ -742,7 +905,14 @@ export function createWatchProgram(host: WatchCompiler (hostSourceFile as FilePresentOnHost).sourceFile = sourceFile; hostSourceFile.version = sourceFile.version; if (!hostSourceFile.fileWatcher) { - hostSourceFile.fileWatcher = watchFilePath(path, fileName, onSourceFileChange, PollingInterval.Low, watchOptions, WatchType.SourceFile); + hostSourceFile.fileWatcher = watchFilePath( + path, + fileName, + onSourceFileChange, + PollingInterval.Low, + watchOptions, + WatchType.SourceFile, + ); } } else { @@ -755,7 +925,14 @@ export function createWatchProgram(host: WatchCompiler } else { if (sourceFile) { - const fileWatcher = watchFilePath(path, fileName, onSourceFileChange, PollingInterval.Low, watchOptions, WatchType.SourceFile); + const fileWatcher = watchFilePath( + path, + fileName, + onSourceFileChange, + PollingInterval.Low, + watchOptions, + WatchType.SourceFile, + ); sourceFilesCache.set(path, { sourceFile, version: sourceFile.version, fileWatcher }); } else { @@ -789,7 +966,11 @@ export function createWatchProgram(host: WatchCompiler return text !== undefined ? getSourceFileVersionAsHashFromText(compilerHost, text) : undefined; } - function onReleaseOldSourceFile(oldSourceFile: SourceFile, _oldOptions: CompilerOptions, hasSourceFileByPath: boolean) { + function onReleaseOldSourceFile( + oldSourceFile: SourceFile, + _oldOptions: CompilerOptions, + hasSourceFileByPath: boolean, + ) { const hostSourceFileInfo = sourceFilesCache.get(oldSourceFile.resolvedPath); // If this is the source file thats in the cache and new program doesnt need it, // remove the cached entry. @@ -798,7 +979,9 @@ export function createWatchProgram(host: WatchCompiler if (hostSourceFileInfo !== undefined) { // record the missing file paths so they can be removed later if watchers arent tracking them if (isFileMissingOnHost(hostSourceFileInfo)) { - (missingFilePathsRequestedForRelease || (missingFilePathsRequestedForRelease = [])).push(oldSourceFile.path); + (missingFilePathsRequestedForRelease || (missingFilePathsRequestedForRelease = [])).push( + oldSourceFile.path, + ); } else if ((hostSourceFileInfo as FilePresentOnHost).sourceFile === oldSourceFile) { if (hostSourceFileInfo.fileWatcher) { @@ -814,7 +997,11 @@ export function createWatchProgram(host: WatchCompiler function reportWatchDiagnostic(message: DiagnosticMessage) { if (host.onWatchStatusChange) { - host.onWatchStatusChange(createCompilerDiagnostic(message), newLine, compilerOptions || optionsToExtendForConfigFile); + host.onWatchStatusChange( + createCompilerDiagnostic(message), + newLine, + compilerOptions || optionsToExtendForConfigFile, + ); } } @@ -835,7 +1022,11 @@ export function createWatchProgram(host: WatchCompiler } const pending = clearInvalidateResolutionsOfFailedLookupLocations(); writeLog(`Scheduling invalidateFailedLookup${pending ? ", Cancelled earlier one" : ""}`); - timerToInvalidateFailedLookupResolutions = host.setTimeout(invalidateResolutionsOfFailedLookup, 250, "timerToInvalidateFailedLookupResolutions"); + timerToInvalidateFailedLookupResolutions = host.setTimeout( + invalidateResolutionsOfFailedLookup, + 250, + "timerToInvalidateFailedLookupResolutions", + ); } function invalidateResolutionsOfFailedLookup() { @@ -898,8 +1089,22 @@ export function createWatchProgram(host: WatchCompiler Debug.assert(configFileName); reloadLevel = ConfigFileProgramReloadLevel.None; - rootFileNames = getFileNamesFromConfigSpecs(compilerOptions.configFile!.configFileSpecs!, getNormalizedAbsolutePath(getDirectoryPath(configFileName), currentDirectory), compilerOptions, parseConfigFileHost, extraFileExtensions); - if (updateErrorForNoInputFiles(rootFileNames, getNormalizedAbsolutePath(configFileName, currentDirectory), compilerOptions.configFile!.configFileSpecs!, configFileParsingDiagnostics!, canConfigFileJsonReportNoInputFiles)) { + rootFileNames = getFileNamesFromConfigSpecs( + compilerOptions.configFile!.configFileSpecs!, + getNormalizedAbsolutePath(getDirectoryPath(configFileName), currentDirectory), + compilerOptions, + parseConfigFileHost, + extraFileExtensions, + ); + if ( + updateErrorForNoInputFiles( + rootFileNames, + getNormalizedAbsolutePath(configFileName, currentDirectory), + compilerOptions.configFile!.configFileSpecs!, + configFileParsingDiagnostics!, + canConfigFileJsonReportNoInputFiles, + ) + ) { hasChangedConfigFileParsingErrors = true; } @@ -923,7 +1128,12 @@ export function createWatchProgram(host: WatchCompiler watchConfigFileWildCardDirectories(); // Update extended config file watch - updateExtendedConfigFilesWatches(toPath(configFileName), compilerOptions, watchOptions, WatchType.ExtendedConfigFile); + updateExtendedConfigFilesWatches( + toPath(configFileName), + compilerOptions, + watchOptions, + WatchType.ExtendedConfigFile, + ); } function parseConfigFile() { @@ -957,7 +1167,10 @@ export function createWatchProgram(host: WatchCompiler if (config) { if (!config.reloadLevel) return config.parsedCommandLine; // With host implementing getParsedCommandLine we cant just update file names - if (config.parsedCommandLine && config.reloadLevel === ConfigFileProgramReloadLevel.Partial && !host.getParsedCommandLine) { + if ( + config.parsedCommandLine && config.reloadLevel === ConfigFileProgramReloadLevel.Partial + && !host.getParsedCommandLine + ) { writeLog("Reloading new file names and options"); Debug.assert(compilerOptions); const fileNames = getFileNamesFromConfigSpecs( @@ -973,9 +1186,9 @@ export function createWatchProgram(host: WatchCompiler } writeLog(`Loading config file: ${configFileName}`); - const parsedCommandLine = host.getParsedCommandLine ? - host.getParsedCommandLine(configFileName) : - getParsedCommandLineFromConfigFileHost(configFileName); + const parsedCommandLine = host.getParsedCommandLine + ? host.getParsedCommandLine(configFileName) + : getParsedCommandLineFromConfigFileHost(configFileName); if (config) { config.parsedCommandLine = parsedCommandLine; config.reloadLevel = undefined; @@ -1021,7 +1234,13 @@ export function createWatchProgram(host: WatchCompiler options: WatchOptions | undefined, watchType: WatchType, ): FileWatcher { - return watchFile(file, (fileName, eventKind) => callback(fileName, eventKind, path), pollingInterval, options, watchType); + return watchFile( + file, + (fileName, eventKind) => callback(fileName, eventKind, path), + pollingInterval, + options, + watchType, + ); } function onSourceFileChange(fileName: string, eventKind: FileWatcherEventKind, path: Path) { @@ -1045,9 +1264,16 @@ export function createWatchProgram(host: WatchCompiler function watchMissingFilePath(missingFilePath: Path) { // If watching missing referenced config file, we are already watching it so no need for separate watcher - return parsedConfigs?.has(missingFilePath) ? - noopFileWatcher : - watchFilePath(missingFilePath, missingFilePath, onMissingFileChange, PollingInterval.Medium, watchOptions, WatchType.MissingFile); + return parsedConfigs?.has(missingFilePath) + ? noopFileWatcher + : watchFilePath( + missingFilePath, + missingFilePath, + onMissingFileChange, + PollingInterval.Medium, + watchOptions, + WatchType.MissingFile, + ); } function onMissingFileChange(fileName: string, eventKind: FileWatcherEventKind, missingFilePath: Path) { @@ -1123,7 +1349,12 @@ export function createWatchProgram(host: WatchCompiler ); } - function updateExtendedConfigFilesWatches(forProjectPath: Path, options: CompilerOptions | undefined, watchOptions: WatchOptions | undefined, watchType: WatchTypeRegistry["ExtendedConfigFile"] | WatchTypeRegistry["ExtendedConfigOfReferencedProject"]) { + function updateExtendedConfigFilesWatches( + forProjectPath: Path, + options: CompilerOptions | undefined, + watchOptions: WatchOptions | undefined, + watchType: WatchTypeRegistry["ExtendedConfigFile"] | WatchTypeRegistry["ExtendedConfigOfReferencedProject"], + ) { updateSharedExtendedConfigFileWatcher( forProjectPath, options, @@ -1134,7 +1365,13 @@ export function createWatchProgram(host: WatchCompiler (_fileName, eventKind) => { updateCachedSystemWithFile(extendedConfigFileName, extendedConfigFilePath, eventKind); // Update extended config cache - if (extendedConfigCache) cleanExtendedConfigCache(extendedConfigCache, extendedConfigFilePath, toPath); + if (extendedConfigCache) { + cleanExtendedConfigCache( + extendedConfigCache, + extendedConfigFilePath, + toPath, + ); + } // Update projects const projects = sharedExtendedConfigFileWatchers.get(extendedConfigFilePath)?.projects; // If there are no referenced projects this extended config file watcher depend on ignore @@ -1188,7 +1425,10 @@ export function createWatchProgram(host: WatchCompiler const fileOrDirectoryPath = toPath(fileOrDirectory); // Since the file existence changed, update the sourceFiles cache if (cachedDirectoryStructureHost) { - cachedDirectoryStructureHost.addOrDeleteFileOrDirectory(fileOrDirectory, fileOrDirectoryPath); + cachedDirectoryStructureHost.addOrDeleteFileOrDirectory( + fileOrDirectory, + fileOrDirectoryPath, + ); } nextSourceFileVersion(fileOrDirectoryPath); diff --git a/src/compiler/watchUtilities.ts b/src/compiler/watchUtilities.ts index 7073986dd5951..30b291379db84 100644 --- a/src/compiler/watchUtilities.ts +++ b/src/compiler/watchUtilities.ts @@ -67,7 +67,13 @@ export interface DirectoryStructureHost { // TODO: GH#18217 Optional methods are frequently used as non-optional directoryExists?(path: string): boolean; getDirectories?(path: string): string[]; - readDirectory?(path: string, extensions?: readonly string[], exclude?: readonly string[], include?: readonly string[], depth?: number): string[]; + readDirectory?( + path: string, + extensions?: readonly string[], + exclude?: readonly string[], + include?: readonly string[], + depth?: number, + ): string[]; realpath?(path: string): string; createDirectory?(path: string): void; @@ -85,10 +91,19 @@ export interface CachedDirectoryStructureHost extends DirectoryStructureHost { useCaseSensitiveFileNames: boolean; getDirectories(path: string): string[]; - readDirectory(path: string, extensions?: readonly string[], exclude?: readonly string[], include?: readonly string[], depth?: number): string[]; + readDirectory( + path: string, + extensions?: readonly string[], + exclude?: readonly string[], + include?: readonly string[], + depth?: number, + ): string[]; /** Returns the queried result for the file exists and directory exists if at all it was done */ - addOrDeleteFileOrDirectory(fileOrDirectory: string, fileOrDirectoryPath: Path): FileAndDirectoryExistence | undefined; + addOrDeleteFileOrDirectory( + fileOrDirectory: string, + fileOrDirectoryPath: Path, + ): FileAndDirectoryExistence | undefined; addOrDeleteFile(fileName: string, filePath: Path, eventKind: FileWatcherEventKind): void; clearCache(): void; } @@ -110,13 +125,19 @@ interface SortedAndCanonicalizedMutableFileSystemEntries { } /** @internal */ -export function createCachedDirectoryStructureHost(host: DirectoryStructureHost, currentDirectory: string, useCaseSensitiveFileNames: boolean): CachedDirectoryStructureHost | undefined { +export function createCachedDirectoryStructureHost( + host: DirectoryStructureHost, + currentDirectory: string, + useCaseSensitiveFileNames: boolean, +): CachedDirectoryStructureHost | undefined { if (!host.getDirectories || !host.readDirectory) { return undefined; } const cachedReadDirectoryResult = new Map(); - const getCanonicalFileName = createGetCanonicalFileName(useCaseSensitiveFileNames) as ((name: string) => Canonicalized); + const getCanonicalFileName = createGetCanonicalFileName( + useCaseSensitiveFileNames, + ) as ((name: string) => Canonicalized); return { useCaseSensitiveFileNames, fileExists, @@ -148,8 +169,11 @@ export function createCachedDirectoryStructureHost(host: DirectoryStructureHost, // If we're looking for the base directory, we're definitely going to search the entries if (!entries.sortedAndCanonicalizedFiles) { - entries.sortedAndCanonicalizedFiles = entries.files.map(getCanonicalFileName).sort() as SortedArray; - entries.sortedAndCanonicalizedDirectories = entries.directories.map(getCanonicalFileName).sort() as SortedArray; + entries.sortedAndCanonicalizedFiles = entries.files.map(getCanonicalFileName).sort() as SortedArray< + Canonicalized + >; + entries.sortedAndCanonicalizedDirectories = entries.directories.map(getCanonicalFileName) + .sort() as SortedArray; } return entries as SortedAndCanonicalizedMutableFileSystemEntries; } @@ -161,7 +185,12 @@ export function createCachedDirectoryStructureHost(host: DirectoryStructureHost, function createCachedFileSystemEntries(rootDir: string, rootDirPath: Path) { if (!host.realpath || ensureTrailingDirectorySeparator(toPath(host.realpath(rootDir))) === rootDirPath) { const resultFromHost: MutableFileSystemEntries = { - files: map(host.readDirectory!(rootDir, /*extensions*/ undefined, /*exclude*/ undefined, /*include*/ ["*.*"]), getBaseNameOfFileName) || [], + files: map( + host.readDirectory!(rootDir, /*extensions*/ undefined, /*exclude*/ undefined, /*include*/ [ + "*.*", + ]), + getBaseNameOfFileName, + ) || [], directories: host.getDirectories!(rootDir) || [], }; @@ -219,8 +248,9 @@ export function createCachedDirectoryStructureHost(host: DirectoryStructureHost, function fileExists(fileName: string): boolean { const path = toPath(fileName); const result = getCachedFileSystemEntriesForBaseDir(path); - return result && hasEntry(result.sortedAndCanonicalizedFiles, getCanonicalFileName(getBaseNameOfFileName(fileName))) || - host.fileExists(fileName); + return result + && hasEntry(result.sortedAndCanonicalizedFiles, getCanonicalFileName(getBaseNameOfFileName(fileName))) + || host.fileExists(fileName); } function directoryExists(dirPath: string): boolean { @@ -252,12 +282,28 @@ export function createCachedDirectoryStructureHost(host: DirectoryStructureHost, return host.getDirectories!(rootDir); } - function readDirectory(rootDir: string, extensions?: readonly string[], excludes?: readonly string[], includes?: readonly string[], depth?: number): string[] { + function readDirectory( + rootDir: string, + extensions?: readonly string[], + excludes?: readonly string[], + includes?: readonly string[], + depth?: number, + ): string[] { const rootDirPath = toPath(rootDir); const rootResult = tryReadDirectory(rootDir, rootDirPath); let rootSymLinkResult: FileSystemEntries | undefined; if (rootResult !== undefined) { - return matchFiles(rootDir, extensions, excludes, includes, useCaseSensitiveFileNames, currentDirectory, depth, getFileSystemEntries, realpath); + return matchFiles( + rootDir, + extensions, + excludes, + includes, + useCaseSensitiveFileNames, + currentDirectory, + depth, + getFileSystemEntries, + realpath, + ); } return host.readDirectory!(rootDir, extensions, excludes, includes, depth); @@ -267,15 +313,18 @@ export function createCachedDirectoryStructureHost(host: DirectoryStructureHost, return rootResult || getFileSystemEntriesFromHost(dir, path); } const result = tryReadDirectory(dir, path); - return result !== undefined ? - result || getFileSystemEntriesFromHost(dir, path) : - emptyFileSystemEntries; + return result !== undefined + ? result || getFileSystemEntriesFromHost(dir, path) + : emptyFileSystemEntries; } function getFileSystemEntriesFromHost(dir: string, path: Path): FileSystemEntries { if (rootSymLinkResult && path === rootDirPath) return rootSymLinkResult; const result: FileSystemEntries = { - files: map(host.readDirectory!(dir, /*extensions*/ undefined, /*exclude*/ undefined, /*include*/ ["*.*"]), getBaseNameOfFileName) || emptyArray, + files: map( + host.readDirectory!(dir, /*extensions*/ undefined, /*exclude*/ undefined, /*include*/ ["*.*"]), + getBaseNameOfFileName, + ) || emptyArray, directories: host.getDirectories!(dir) || emptyArray, }; if (path === rootDirPath) rootSymLinkResult = result; @@ -315,7 +364,10 @@ export function createCachedDirectoryStructureHost(host: DirectoryStructureHost, fileExists: host.fileExists(fileOrDirectoryPath), directoryExists: host.directoryExists(fileOrDirectoryPath), }; - if (fsQueryResult.directoryExists || hasEntry(parentResult.sortedAndCanonicalizedDirectories, getCanonicalFileName(baseName))) { + if ( + fsQueryResult.directoryExists + || hasEntry(parentResult.sortedAndCanonicalizedDirectories, getCanonicalFileName(baseName)) + ) { // Folder added or removed, clear the cache instead of updating the folder and its structure clearCache(); } @@ -333,11 +385,19 @@ export function createCachedDirectoryStructureHost(host: DirectoryStructureHost, const parentResult = getCachedFileSystemEntriesForBaseDir(filePath); if (parentResult) { - updateFilesOfFileSystemEntry(parentResult, getBaseNameOfFileName(fileName), eventKind === FileWatcherEventKind.Created); + updateFilesOfFileSystemEntry( + parentResult, + getBaseNameOfFileName(fileName), + eventKind === FileWatcherEventKind.Created, + ); } } - function updateFilesOfFileSystemEntry(parentResult: SortedAndCanonicalizedMutableFileSystemEntries, baseName: string, fileExists: boolean): void { + function updateFilesOfFileSystemEntry( + parentResult: SortedAndCanonicalizedMutableFileSystemEntries, + baseName: string, + fileExists: boolean, + ): void { const canonicalizedFiles = parentResult.sortedAndCanonicalizedFiles; const canonicalizedBaseName = getCanonicalFileName(baseName); if (fileExists) { @@ -348,10 +408,17 @@ export function createCachedDirectoryStructureHost(host: DirectoryStructureHost, } else { // Case-sensitive comparison since already canonicalized - const sortedIndex = binarySearch(canonicalizedFiles, canonicalizedBaseName, identity, compareStringsCaseSensitive); + const sortedIndex = binarySearch( + canonicalizedFiles, + canonicalizedBaseName, + identity, + compareStringsCaseSensitive, + ); if (sortedIndex >= 0) { canonicalizedFiles.splice(sortedIndex, 1); - const unsortedIndex = parentResult.files.findIndex(entry => getCanonicalFileName(entry) === canonicalizedBaseName); + const unsortedIndex = parentResult.files.findIndex(entry => + getCanonicalFileName(entry) === canonicalizedBaseName + ); parentResult.files.splice(unsortedIndex, 1); } } @@ -539,7 +606,11 @@ export function updateWatchingWildcardDirectories( }; } - function updateWildcardDirectoryWatcher(existingWatcher: WildcardDirectoryWatcher, flags: WatchDirectoryFlags, directory: string) { + function updateWildcardDirectoryWatcher( + existingWatcher: WildcardDirectoryWatcher, + flags: WatchDirectoryFlags, + directory: string, + ) { // Watcher needs to be updated if the recursive flags dont match if (existingWatcher.flags === flags) { return; @@ -589,12 +660,22 @@ export function isIgnoredFileFromWildCardWatching({ // If the the added or created file or directory is not supported file name, ignore the file // But when watched directory is added/removed, we need to reload the file list - if (hasExtension(fileOrDirectoryPath) && !isSupportedSourceFileName(fileOrDirectory, options, extraFileExtensions)) { + if ( + hasExtension(fileOrDirectoryPath) && !isSupportedSourceFileName(fileOrDirectory, options, extraFileExtensions) + ) { writeLog(`Project: ${configFileName} Detected file add/remove of non supported extension: ${fileOrDirectory}`); return true; } - if (isExcludedFile(fileOrDirectory, options.configFile!.configFileSpecs!, getNormalizedAbsolutePath(getDirectoryPath(configFileName), currentDirectory), useCaseSensitiveFileNames, currentDirectory)) { + if ( + isExcludedFile( + fileOrDirectory, + options.configFile!.configFileSpecs!, + getNormalizedAbsolutePath(getDirectoryPath(configFileName), currentDirectory), + useCaseSensitiveFileNames, + currentDirectory, + ) + ) { writeLog(`Project: ${configFileName} Detected excluded file: ${fileOrDirectory}`); return true; } @@ -616,11 +697,12 @@ export function isIgnoredFileFromWildCardWatching({ // just check if sourceFile with the name exists const filePathWithoutExtension = removeFileExtension(fileOrDirectoryPath); - const realProgram = isArray(program) ? undefined : isBuilderProgram(program) ? program.getProgramOrUndefined() : program; + const realProgram = isArray(program) ? undefined + : isBuilderProgram(program) ? program.getProgramOrUndefined() : program; const builderProgram = !realProgram && !isArray(program) ? program as BuilderProgram : undefined; if ( - hasSourceFile((filePathWithoutExtension + Extension.Ts) as Path) || - hasSourceFile((filePathWithoutExtension + Extension.Tsx) as Path) + hasSourceFile((filePathWithoutExtension + Extension.Ts) as Path) + || hasSourceFile((filePathWithoutExtension + Extension.Tsx) as Path) ) { writeLog(`Project: ${configFileName} Detected output file: ${fileOrDirectory}`); return true; @@ -628,11 +710,11 @@ export function isIgnoredFileFromWildCardWatching({ return false; function hasSourceFile(file: Path): boolean { - return realProgram ? - !!realProgram.getSourceFileByPath(file) : - builderProgram ? - builderProgram.getState().fileInfos.has(file) : - !!find(program as readonly string[], rootFile => toPath(rootFile) === file); + return realProgram + ? !!realProgram.getSourceFileByPath(file) + : builderProgram + ? builderProgram.getState().fileInfos.has(file) + : !!find(program as readonly string[], rootFile => toPath(rootFile) === file); } } @@ -658,42 +740,73 @@ export enum WatchLogLevel { /** @internal */ export interface WatchFactoryHost { - watchFile(path: string, callback: FileWatcherCallback, pollingInterval?: number, options?: WatchOptions): FileWatcher; - watchDirectory(path: string, callback: DirectoryWatcherCallback, recursive?: boolean, options?: WatchOptions): FileWatcher; + watchFile( + path: string, + callback: FileWatcherCallback, + pollingInterval?: number, + options?: WatchOptions, + ): FileWatcher; + watchDirectory( + path: string, + callback: DirectoryWatcherCallback, + recursive?: boolean, + options?: WatchOptions, + ): FileWatcher; getCurrentDirectory?(): string; useCaseSensitiveFileNames: boolean | (() => boolean); } /** @internal */ export interface WatchFactory { - watchFile: (file: string, callback: FileWatcherCallback, pollingInterval: PollingInterval, options: WatchOptions | undefined, detailInfo1: X, detailInfo2?: Y) => FileWatcher; - watchDirectory: (directory: string, callback: DirectoryWatcherCallback, flags: WatchDirectoryFlags, options: WatchOptions | undefined, detailInfo1: X, detailInfo2?: Y) => FileWatcher; + watchFile: ( + file: string, + callback: FileWatcherCallback, + pollingInterval: PollingInterval, + options: WatchOptions | undefined, + detailInfo1: X, + detailInfo2?: Y, + ) => FileWatcher; + watchDirectory: ( + directory: string, + callback: DirectoryWatcherCallback, + flags: WatchDirectoryFlags, + options: WatchOptions | undefined, + detailInfo1: X, + detailInfo2?: Y, + ) => FileWatcher; } /** @internal */ export type GetDetailWatchInfo = (detailInfo1: X, detailInfo2: Y | undefined) => string; /** @internal */ -export function getWatchFactory(host: WatchFactoryHost, watchLogLevel: WatchLogLevel, log: (s: string) => void, getDetailWatchInfo?: GetDetailWatchInfo): WatchFactory { +export function getWatchFactory( + host: WatchFactoryHost, + watchLogLevel: WatchLogLevel, + log: (s: string) => void, + getDetailWatchInfo?: GetDetailWatchInfo, +): WatchFactory { setSysLog(watchLogLevel === WatchLogLevel.Verbose ? log : noop); const plainInvokeFactory: WatchFactory = { - watchFile: (file, callback, pollingInterval, options) => host.watchFile(file, callback, pollingInterval, options), - watchDirectory: (directory, callback, flags, options) => host.watchDirectory(directory, callback, (flags & WatchDirectoryFlags.Recursive) !== 0, options), + watchFile: (file, callback, pollingInterval, options) => + host.watchFile(file, callback, pollingInterval, options), + watchDirectory: (directory, callback, flags, options) => + host.watchDirectory(directory, callback, (flags & WatchDirectoryFlags.Recursive) !== 0, options), }; - const triggerInvokingFactory: WatchFactory | undefined = watchLogLevel !== WatchLogLevel.None ? - { + const triggerInvokingFactory: WatchFactory | undefined = watchLogLevel !== WatchLogLevel.None + ? { watchFile: createTriggerLoggingAddWatch("watchFile"), watchDirectory: createTriggerLoggingAddWatch("watchDirectory"), - } : - undefined; - const factory = watchLogLevel === WatchLogLevel.Verbose ? - { + } + : undefined; + const factory = watchLogLevel === WatchLogLevel.Verbose + ? { watchFile: createFileWatcherWithLogging, watchDirectory: createDirectoryWatcherWithLogging, - } : - triggerInvokingFactory || plainInvokeFactory; - const excludeWatcherFactory = watchLogLevel === WatchLogLevel.Verbose ? - createExcludeWatcherWithLogging : - returnNoopFileWatcher; + } + : triggerInvokingFactory || plainInvokeFactory; + const excludeWatcherFactory = watchLogLevel === WatchLogLevel.Verbose + ? createExcludeWatcherWithLogging + : returnNoopFileWatcher; return { watchFile: createExcludeHandlingAddWatch("watchFile"), @@ -708,15 +821,20 @@ export function getWatchFactory(host: WatchFactoryHost, watchL options: WatchOptions | undefined, detailInfo1: X, detailInfo2?: Y, - ) => !matchesExclude(file, key === "watchFile" ? options?.excludeFiles : options?.excludeDirectories, useCaseSensitiveFileNames(), host.getCurrentDirectory?.() || "") ? - factory[key].call(/*thisArgs*/ undefined, file, cb, flags, options, detailInfo1, detailInfo2) : - excludeWatcherFactory(file, flags, options, detailInfo1, detailInfo2); + ) => !matchesExclude( + file, + key === "watchFile" ? options?.excludeFiles : options?.excludeDirectories, + useCaseSensitiveFileNames(), + host.getCurrentDirectory?.() || "", + ) + ? factory[key].call(/*thisArgs*/ undefined, file, cb, flags, options, detailInfo1, detailInfo2) + : excludeWatcherFactory(file, flags, options, detailInfo1, detailInfo2); } function useCaseSensitiveFileNames() { - return typeof host.useCaseSensitiveFileNames === "boolean" ? - host.useCaseSensitiveFileNames : - host.useCaseSensitiveFileNames(); + return typeof host.useCaseSensitiveFileNames === "boolean" + ? host.useCaseSensitiveFileNames + : host.useCaseSensitiveFileNames(); } function createExcludeWatcherWithLogging( @@ -726,9 +844,14 @@ export function getWatchFactory(host: WatchFactoryHost, watchL detailInfo1: X, detailInfo2?: Y, ) { - log(`ExcludeWatcher:: Added:: ${getWatchInfo(file, flags, options, detailInfo1, detailInfo2, getDetailWatchInfo)}`); + log(`ExcludeWatcher:: Added:: ${ + getWatchInfo(file, flags, options, detailInfo1, detailInfo2, getDetailWatchInfo) + }`); return { - close: () => log(`ExcludeWatcher:: Close:: ${getWatchInfo(file, flags, options, detailInfo1, detailInfo2, getDetailWatchInfo)}`), + close: () => + log(`ExcludeWatcher:: Close:: ${ + getWatchInfo(file, flags, options, detailInfo1, detailInfo2, getDetailWatchInfo) + }`), }; } @@ -740,11 +863,15 @@ export function getWatchFactory(host: WatchFactoryHost, watchL detailInfo1: X, detailInfo2?: Y, ): FileWatcher { - log(`FileWatcher:: Added:: ${getWatchInfo(file, flags, options, detailInfo1, detailInfo2, getDetailWatchInfo)}`); + log(`FileWatcher:: Added:: ${ + getWatchInfo(file, flags, options, detailInfo1, detailInfo2, getDetailWatchInfo) + }`); const watcher = triggerInvokingFactory!.watchFile(file, cb, flags, options, detailInfo1, detailInfo2); return { close: () => { - log(`FileWatcher:: Close:: ${getWatchInfo(file, flags, options, detailInfo1, detailInfo2, getDetailWatchInfo)}`); + log(`FileWatcher:: Close:: ${ + getWatchInfo(file, flags, options, detailInfo1, detailInfo2, getDetailWatchInfo) + }`); watcher.close(); }, }; @@ -758,7 +885,9 @@ export function getWatchFactory(host: WatchFactoryHost, watchL detailInfo1: X, detailInfo2?: Y, ): FileWatcher { - const watchInfo = `DirectoryWatcher:: Added:: ${getWatchInfo(file, flags, options, detailInfo1, detailInfo2, getDetailWatchInfo)}`; + const watchInfo = `DirectoryWatcher:: Added:: ${ + getWatchInfo(file, flags, options, detailInfo1, detailInfo2, getDetailWatchInfo) + }`; log(watchInfo); const start = timestamp(); const watcher = triggerInvokingFactory!.watchDirectory(file, cb, flags, options, detailInfo1, detailInfo2); @@ -766,7 +895,9 @@ export function getWatchFactory(host: WatchFactoryHost, watchL log(`Elapsed:: ${elapsed}ms ${watchInfo}`); return { close: () => { - const watchInfo = `DirectoryWatcher:: Close:: ${getWatchInfo(file, flags, options, detailInfo1, detailInfo2, getDetailWatchInfo)}`; + const watchInfo = `DirectoryWatcher:: Close:: ${ + getWatchInfo(file, flags, options, detailInfo1, detailInfo2, getDetailWatchInfo) + }`; log(watchInfo); const start = timestamp(); watcher.close(); @@ -788,7 +919,11 @@ export function getWatchFactory(host: WatchFactoryHost, watchL /*thisArgs*/ undefined, file, (...args: any[]) => { - const triggerredInfo = `${key === "watchFile" ? "FileWatcher" : "DirectoryWatcher"}:: Triggered with ${args[0]} ${args[1] !== undefined ? args[1] : ""}:: ${getWatchInfo(file, flags, options, detailInfo1, detailInfo2, getDetailWatchInfo)}`; + const triggerredInfo = `${key === "watchFile" ? "FileWatcher" : "DirectoryWatcher"}:: Triggered with ${ + args[0] + } ${args[1] !== undefined ? args[1] : ""}:: ${ + getWatchInfo(file, flags, options, detailInfo1, detailInfo2, getDetailWatchInfo) + }`; log(triggerredInfo); const start = timestamp(); cb.call(/*thisArg*/ undefined, ...args); @@ -802,8 +937,18 @@ export function getWatchFactory(host: WatchFactoryHost, watchL ); } - function getWatchInfo(file: string, flags: T, options: WatchOptions | undefined, detailInfo1: X, detailInfo2: Y | undefined, getDetailWatchInfo: GetDetailWatchInfo | undefined) { - return `WatchInfo: ${file} ${flags} ${JSON.stringify(options)} ${getDetailWatchInfo ? getDetailWatchInfo(detailInfo1, detailInfo2) : detailInfo2 === undefined ? detailInfo1 : `${detailInfo1} ${detailInfo2}`}`; + function getWatchInfo( + file: string, + flags: T, + options: WatchOptions | undefined, + detailInfo1: X, + detailInfo2: Y | undefined, + getDetailWatchInfo: GetDetailWatchInfo | undefined, + ) { + return `WatchInfo: ${file} ${flags} ${JSON.stringify(options)} ${ + getDetailWatchInfo ? getDetailWatchInfo(detailInfo1, detailInfo2) + : detailInfo2 === undefined ? detailInfo1 : `${detailInfo1} ${detailInfo2}` + }`; } } @@ -811,9 +956,9 @@ export function getWatchFactory(host: WatchFactoryHost, watchL export function getFallbackOptions(options: WatchOptions | undefined): WatchOptions { const fallbackPolling = options?.fallbackPolling; return { - watchFile: fallbackPolling !== undefined ? - fallbackPolling as unknown as WatchFileKind : - WatchFileKind.PriorityPollingInterval, + watchFile: fallbackPolling !== undefined + ? fallbackPolling as unknown as WatchFileKind + : WatchFileKind.PriorityPollingInterval, }; } diff --git a/src/deprecatedCompat/deprecate.ts b/src/deprecatedCompat/deprecate.ts index 3b5fa9d2d286f..53b54329a3cf5 100644 --- a/src/deprecatedCompat/deprecate.ts +++ b/src/deprecatedCompat/deprecate.ts @@ -19,23 +19,40 @@ function getTypeScriptVersion() { return typeScriptVersion ?? (typeScriptVersion = new Version(version)); } -function formatDeprecationMessage(name: string, error: boolean | undefined, errorAfter: Version | undefined, since: Version | undefined, message: string | undefined) { +function formatDeprecationMessage( + name: string, + error: boolean | undefined, + errorAfter: Version | undefined, + since: Version | undefined, + message: string | undefined, +) { let deprecationMessage = error ? "DeprecationError: " : "DeprecationWarning: "; deprecationMessage += `'${name}' `; deprecationMessage += since ? `has been deprecated since v${since}` : "is deprecated"; - deprecationMessage += error ? " and can no longer be used." : errorAfter ? ` and will no longer be usable after v${errorAfter}.` : "."; + deprecationMessage += error ? " and can no longer be used." + : errorAfter ? ` and will no longer be usable after v${errorAfter}.` : "."; deprecationMessage += message ? ` ${formatStringFromArgs(message, [name], 0)}` : ""; return deprecationMessage; } -function createErrorDeprecation(name: string, errorAfter: Version | undefined, since: Version | undefined, message: string | undefined) { +function createErrorDeprecation( + name: string, + errorAfter: Version | undefined, + since: Version | undefined, + message: string | undefined, +) { const deprecationMessage = formatDeprecationMessage(name, /*error*/ true, errorAfter, since, message); return () => { throw new TypeError(deprecationMessage); }; } -function createWarningDeprecation(name: string, errorAfter: Version | undefined, since: Version | undefined, message: string | undefined) { +function createWarningDeprecation( + name: string, + errorAfter: Version | undefined, + since: Version | undefined, + message: string | undefined, +) { let hasWrittenDeprecation = false; return () => { if (enableDeprecationWarnings && !hasWrittenDeprecation) { @@ -48,15 +65,16 @@ function createWarningDeprecation(name: string, errorAfter: Version | undefined, export function createDeprecation(name: string, options: DeprecationOptions & { error: true; }): () => never; export function createDeprecation(name: string, options?: DeprecationOptions): () => void; export function createDeprecation(name: string, options: DeprecationOptions = {}) { - const version = typeof options.typeScriptVersion === "string" ? new Version(options.typeScriptVersion) : options.typeScriptVersion ?? getTypeScriptVersion(); + const version = typeof options.typeScriptVersion === "string" ? new Version(options.typeScriptVersion) + : options.typeScriptVersion ?? getTypeScriptVersion(); const errorAfter = typeof options.errorAfter === "string" ? new Version(options.errorAfter) : options.errorAfter; const warnAfter = typeof options.warnAfter === "string" ? new Version(options.warnAfter) : options.warnAfter; const since = typeof options.since === "string" ? new Version(options.since) : options.since ?? warnAfter; const error = options.error || errorAfter && version.compareTo(errorAfter) >= 0; const warn = !warnAfter || version.compareTo(warnAfter) >= 0; - return error ? createErrorDeprecation(name, errorAfter, since, options.message) : - warn ? createWarningDeprecation(name, errorAfter, since, options.message) : - noop; + return error ? createErrorDeprecation(name, errorAfter, since, options.message) + : warn ? createWarningDeprecation(name, errorAfter, since, options.message) + : noop; } function wrapFunction any>(deprecation: () => void, func: F): F { diff --git a/src/deprecatedCompat/deprecations.ts b/src/deprecatedCompat/deprecations.ts index 84310b22a55c2..5fae14cb7af1c 100644 --- a/src/deprecatedCompat/deprecations.ts +++ b/src/deprecatedCompat/deprecations.ts @@ -52,7 +52,9 @@ export type OverloadKeys = Extract = Parameters<{ [P in OverloadKeys]: T[P]; }[OverloadKeys]>; +export type OverloadParameters = Parameters< + { [P in OverloadKeys]: T[P]; }[OverloadKeys] +>; // NOTE: the following doesn't work in TS 4.4 (the current LKG in main), so we have to use UnionToIntersection for now // type OverloadFunction any)[] = [], O = unknown> = @@ -70,7 +72,9 @@ export type OverloadFunction = UnionToIntersectio * * @internal */ -export type OverloadBinders = { [P in OverloadKeys]: (args: OverloadParameters) => boolean | undefined; }; +export type OverloadBinders = { + [P in OverloadKeys]: (args: OverloadParameters) => boolean | undefined; +}; /** * Defines deprecations for specific overloads by ordinal. @@ -80,7 +84,12 @@ export type OverloadBinders = { [P in OverloadKey export type OverloadDeprecations = { [P in OverloadKeys]?: DeprecationOptions; }; /** @internal */ -export function createOverload(name: string, overloads: T, binder: OverloadBinders, deprecations?: OverloadDeprecations) { +export function createOverload( + name: string, + overloads: T, + binder: OverloadBinders, + deprecations?: OverloadDeprecations, +) { Object.defineProperty(call, "name", { ...Object.getOwnPropertyDescriptor(call, "name"), value: name }); if (deprecations) { diff --git a/src/executeCommandLine/executeCommandLine.ts b/src/executeCommandLine/executeCommandLine.ts index 6ea14de092e1a..1b07efa5a7c7e 100644 --- a/src/executeCommandLine/executeCommandLine.ts +++ b/src/executeCommandLine/executeCommandLine.ts @@ -151,9 +151,9 @@ function updateReportDiagnostic( existing: DiagnosticReporter, options: CompilerOptions | BuildOptions, ): DiagnosticReporter { - return shouldBePretty(sys, options) ? - createDiagnosticReporter(sys, /*pretty*/ true) : - existing; + return shouldBePretty(sys, options) + ? createDiagnosticReporter(sys, /*pretty*/ true) + : existing; } function defaultIsPretty(sys: System) { @@ -169,9 +169,9 @@ function shouldBePretty(sys: System, options: CompilerOptions | BuildOptions) { function getOptionsForHelp(commandLine: ParsedCommandLine) { // Sort our options by their names, (e.g. "--noImplicitAny" comes before "--watch") - return !!commandLine.options.all ? - sort(optionDeclarations, (a, b) => compareStringsCaseInsensitive(a.name, b.name)) : - filter(optionDeclarations.slice(), v => !!v.showInSimplifiedHelpView); + return !!commandLine.options.all + ? sort(optionDeclarations, (a, b) => compareStringsCaseInsensitive(a.name, b.name)) + : filter(optionDeclarations.slice(), v => !!v.showInSimplifiedHelpView); } function printVersion(sys: System) { @@ -193,9 +193,11 @@ function createColors(sys: System) { return `\x1b[1m${str}\x1b[22m`; } - const isWindows = sys.getEnvironmentVariable("OS") && stringContains(sys.getEnvironmentVariable("OS").toLowerCase(), "windows"); + const isWindows = sys.getEnvironmentVariable("OS") + && stringContains(sys.getEnvironmentVariable("OS").toLowerCase(), "windows"); const isWindowsTerminal = sys.getEnvironmentVariable("WT_SESSION"); - const isVSCode = sys.getEnvironmentVariable("TERM_PROGRAM") && sys.getEnvironmentVariable("TERM_PROGRAM") === "vscode"; + const isVSCode = sys.getEnvironmentVariable("TERM_PROGRAM") + && sys.getEnvironmentVariable("TERM_PROGRAM") === "vscode"; function blue(str: string) { // Effectively Powershell and Command prompt users use cyan instead @@ -210,7 +212,8 @@ function createColors(sys: System) { // There are ~3 types of terminal color support: 16 colors, 256 and 16m colors // If there is richer color support, e.g. 256+ we can use extended ANSI codes which are not just generic 'blue' // but a 'lighter blue' which is closer to the blue in the TS logo. - const supportsRicherColors = sys.getEnvironmentVariable("COLORTERM") === "truecolor" || sys.getEnvironmentVariable("TERM") === "xterm-256color"; + const supportsRicherColors = sys.getEnvironmentVariable("COLORTERM") === "truecolor" + || sys.getEnvironmentVariable("TERM") === "xterm-256color"; function blueBackground(str: string) { if (supportsRicherColors) { return `\x1B[48;5;68m${str}\x1B[39;49m`; @@ -234,7 +237,12 @@ function getDisplayNameTextOfOption(option: CommandLineOption) { return `--${option.name}${option.shortName ? `, -${option.shortName}` : ""}`; } -function generateOptionOutput(sys: System, option: CommandLineOption, rightAlignOfLeft: number, leftAlignOfRight: number) { +function generateOptionOutput( + sys: System, + option: CommandLineOption, + rightAlignOfLeft: number, + leftAlignOfRight: number, +) { interface ValueCandidate { // "one or more" or "any of" valueType: string; @@ -263,13 +271,43 @@ function generateOptionOutput(sys: System, option: CommandLineOption, rightAlign if (option.description) { description = getDiagnosticText(option.description); } - text.push(...getPrettyOutput(name, description, rightAlignOfLeft, leftAlignOfRight, terminalWidth, /*colorLeft*/ true), sys.newLine); + text.push( + ...getPrettyOutput( + name, + description, + rightAlignOfLeft, + leftAlignOfRight, + terminalWidth, + /*colorLeft*/ true, + ), + sys.newLine, + ); if (showAdditionalInfoOutput(valueCandidates, option)) { if (valueCandidates) { - text.push(...getPrettyOutput(valueCandidates.valueType, valueCandidates.possibleValues, rightAlignOfLeft, leftAlignOfRight, terminalWidth, /*colorLeft*/ false), sys.newLine); + text.push( + ...getPrettyOutput( + valueCandidates.valueType, + valueCandidates.possibleValues, + rightAlignOfLeft, + leftAlignOfRight, + terminalWidth, + /*colorLeft*/ false, + ), + sys.newLine, + ); } if (defaultValueDescription) { - text.push(...getPrettyOutput(getDiagnosticText(Diagnostics.default_Colon), defaultValueDescription, rightAlignOfLeft, leftAlignOfRight, terminalWidth, /*colorLeft*/ false), sys.newLine); + text.push( + ...getPrettyOutput( + getDiagnosticText(Diagnostics.default_Colon), + defaultValueDescription, + rightAlignOfLeft, + leftAlignOfRight, + terminalWidth, + /*colorLeft*/ false, + ), + sys.newLine, + ); } } text.push(sys.newLine); @@ -316,13 +354,23 @@ function generateOptionOutput(sys: System, option: CommandLineOption, rightAlign const defaultValueDescription = option.defaultValueDescription; if (option.category === Diagnostics.Command_line_Options) return false; - if (contains(ignoreValues, valueCandidates?.possibleValues) && contains(ignoredDescriptions, defaultValueDescription)) { + if ( + contains(ignoreValues, valueCandidates?.possibleValues) + && contains(ignoredDescriptions, defaultValueDescription) + ) { return false; } return true; } - function getPrettyOutput(left: string, right: string, rightAlignOfLeft: number, leftAlignOfRight: number, terminalWidth: number, colorLeft: boolean) { + function getPrettyOutput( + left: string, + right: string, + rightAlignOfLeft: number, + leftAlignOfRight: number, + terminalWidth: number, + colorLeft: boolean, + ) { const res = []; let isFirstLine = true; let remainRight = right; @@ -433,7 +481,14 @@ function generateGroupOptionOutput(sys: System, optionsList: readonly CommandLin return lines; } -function generateSectionOptionsOutput(sys: System, sectionName: string, options: readonly CommandLineOption[], subCategory: boolean, beforeOptionsDescription?: string, afterOptionsDescription?: string) { +function generateSectionOptionsOutput( + sys: System, + sectionName: string, + options: readonly CommandLineOption[], + subCategory: boolean, + beforeOptionsDescription?: string, + afterOptionsDescription?: string, +) { let res: string[] = []; res.push(createColors(sys).bold(sectionName) + sys.newLine + sys.newLine); if (beforeOptionsDescription) { @@ -468,24 +523,60 @@ function generateSectionOptionsOutput(sys: System, sectionName: string, options: function printEasyHelp(sys: System, simpleOptions: readonly CommandLineOption[]) { const colors = createColors(sys); - let output: string[] = [...getHeader(sys, `${getDiagnosticText(Diagnostics.tsc_Colon_The_TypeScript_Compiler)} - ${getDiagnosticText(Diagnostics.Version_0, version)}`)]; + let output: string[] = [ + ...getHeader( + sys, + `${getDiagnosticText(Diagnostics.tsc_Colon_The_TypeScript_Compiler)} - ${ + getDiagnosticText(Diagnostics.Version_0, version) + }`, + ), + ]; output.push(colors.bold(getDiagnosticText(Diagnostics.COMMON_COMMANDS)) + sys.newLine + sys.newLine); example("tsc", Diagnostics.Compiles_the_current_project_tsconfig_json_in_the_working_directory); - example("tsc app.ts util.ts", Diagnostics.Ignoring_tsconfig_json_compiles_the_specified_files_with_default_compiler_options); + example( + "tsc app.ts util.ts", + Diagnostics.Ignoring_tsconfig_json_compiles_the_specified_files_with_default_compiler_options, + ); example("tsc -b", Diagnostics.Build_a_composite_project_in_the_working_directory); example("tsc --init", Diagnostics.Creates_a_tsconfig_json_with_the_recommended_settings_in_the_working_directory); - example("tsc -p ./path/to/tsconfig.json", Diagnostics.Compiles_the_TypeScript_project_located_at_the_specified_path); - example("tsc --help --all", Diagnostics.An_expanded_version_of_this_information_showing_all_possible_compiler_options); + example( + "tsc -p ./path/to/tsconfig.json", + Diagnostics.Compiles_the_TypeScript_project_located_at_the_specified_path, + ); + example( + "tsc --help --all", + Diagnostics.An_expanded_version_of_this_information_showing_all_possible_compiler_options, + ); example(["tsc --noEmit", "tsc --target esnext"], Diagnostics.Compiles_the_current_project_with_additional_settings); - const cliCommands = simpleOptions.filter(opt => opt.isCommandLineOnly || opt.category === Diagnostics.Command_line_Options); + const cliCommands = simpleOptions.filter(opt => + opt.isCommandLineOnly || opt.category === Diagnostics.Command_line_Options + ); const configOpts = simpleOptions.filter(opt => !contains(cliCommands, opt)); output = [ ...output, - ...generateSectionOptionsOutput(sys, getDiagnosticText(Diagnostics.COMMAND_LINE_FLAGS), cliCommands, /*subCategory*/ false, /*beforeOptionsDescription*/ undefined, /*afterOptionsDescription*/ undefined), - ...generateSectionOptionsOutput(sys, getDiagnosticText(Diagnostics.COMMON_COMPILER_OPTIONS), configOpts, /*subCategory*/ false, /*beforeOptionsDescription*/ undefined, formatMessage(/*dummy*/ undefined, Diagnostics.You_can_learn_about_all_of_the_compiler_options_at_0, "https://aka.ms/tsc")), + ...generateSectionOptionsOutput( + sys, + getDiagnosticText(Diagnostics.COMMAND_LINE_FLAGS), + cliCommands, + /*subCategory*/ false, + /*beforeOptionsDescription*/ undefined, + /*afterOptionsDescription*/ undefined, + ), + ...generateSectionOptionsOutput( + sys, + getDiagnosticText(Diagnostics.COMMON_COMPILER_OPTIONS), + configOpts, + /*subCategory*/ false, + /*beforeOptionsDescription*/ undefined, + formatMessage( + /*dummy*/ undefined, + Diagnostics.You_can_learn_about_all_of_the_compiler_options_at_0, + "https://aka.ms/tsc", + ), + ), ]; for (const line of output) { @@ -501,19 +592,92 @@ function printEasyHelp(sys: System, simpleOptions: readonly CommandLineOption[]) } } -function printAllHelp(sys: System, compilerOptions: readonly CommandLineOption[], buildOptions: readonly CommandLineOption[], watchOptions: readonly CommandLineOption[]) { - let output: string[] = [...getHeader(sys, `${getDiagnosticText(Diagnostics.tsc_Colon_The_TypeScript_Compiler)} - ${getDiagnosticText(Diagnostics.Version_0, version)}`)]; - output = [...output, ...generateSectionOptionsOutput(sys, getDiagnosticText(Diagnostics.ALL_COMPILER_OPTIONS), compilerOptions, /*subCategory*/ true, /*beforeOptionsDescription*/ undefined, formatMessage(/*dummy*/ undefined, Diagnostics.You_can_learn_about_all_of_the_compiler_options_at_0, "https://aka.ms/tsc"))]; - output = [...output, ...generateSectionOptionsOutput(sys, getDiagnosticText(Diagnostics.WATCH_OPTIONS), watchOptions, /*subCategory*/ false, getDiagnosticText(Diagnostics.Including_watch_w_will_start_watching_the_current_project_for_the_file_changes_Once_set_you_can_config_watch_mode_with_Colon))]; - output = [...output, ...generateSectionOptionsOutput(sys, getDiagnosticText(Diagnostics.BUILD_OPTIONS), buildOptions, /*subCategory*/ false, formatMessage(/*dummy*/ undefined, Diagnostics.Using_build_b_will_make_tsc_behave_more_like_a_build_orchestrator_than_a_compiler_This_is_used_to_trigger_building_composite_projects_which_you_can_learn_more_about_at_0, "https://aka.ms/tsc-composite-builds"))]; +function printAllHelp( + sys: System, + compilerOptions: readonly CommandLineOption[], + buildOptions: readonly CommandLineOption[], + watchOptions: readonly CommandLineOption[], +) { + let output: string[] = [ + ...getHeader( + sys, + `${getDiagnosticText(Diagnostics.tsc_Colon_The_TypeScript_Compiler)} - ${ + getDiagnosticText(Diagnostics.Version_0, version) + }`, + ), + ]; + output = [ + ...output, + ...generateSectionOptionsOutput( + sys, + getDiagnosticText(Diagnostics.ALL_COMPILER_OPTIONS), + compilerOptions, + /*subCategory*/ true, + /*beforeOptionsDescription*/ undefined, + formatMessage( + /*dummy*/ undefined, + Diagnostics.You_can_learn_about_all_of_the_compiler_options_at_0, + "https://aka.ms/tsc", + ), + ), + ]; + output = [ + ...output, + ...generateSectionOptionsOutput( + sys, + getDiagnosticText(Diagnostics.WATCH_OPTIONS), + watchOptions, + /*subCategory*/ false, + getDiagnosticText( + Diagnostics + .Including_watch_w_will_start_watching_the_current_project_for_the_file_changes_Once_set_you_can_config_watch_mode_with_Colon, + ), + ), + ]; + output = [ + ...output, + ...generateSectionOptionsOutput( + sys, + getDiagnosticText(Diagnostics.BUILD_OPTIONS), + buildOptions, + /*subCategory*/ false, + formatMessage( + /*dummy*/ undefined, + Diagnostics + .Using_build_b_will_make_tsc_behave_more_like_a_build_orchestrator_than_a_compiler_This_is_used_to_trigger_building_composite_projects_which_you_can_learn_more_about_at_0, + "https://aka.ms/tsc-composite-builds", + ), + ), + ]; for (const line of output) { sys.write(line); } } function printBuildHelp(sys: System, buildOptions: readonly CommandLineOption[]) { - let output: string[] = [...getHeader(sys, `${getDiagnosticText(Diagnostics.tsc_Colon_The_TypeScript_Compiler)} - ${getDiagnosticText(Diagnostics.Version_0, version)}`)]; - output = [...output, ...generateSectionOptionsOutput(sys, getDiagnosticText(Diagnostics.BUILD_OPTIONS), buildOptions, /*subCategory*/ false, formatMessage(/*dummy*/ undefined, Diagnostics.Using_build_b_will_make_tsc_behave_more_like_a_build_orchestrator_than_a_compiler_This_is_used_to_trigger_building_composite_projects_which_you_can_learn_more_about_at_0, "https://aka.ms/tsc-composite-builds"))]; + let output: string[] = [ + ...getHeader( + sys, + `${getDiagnosticText(Diagnostics.tsc_Colon_The_TypeScript_Compiler)} - ${ + getDiagnosticText(Diagnostics.Version_0, version) + }`, + ), + ]; + output = [ + ...output, + ...generateSectionOptionsOutput( + sys, + getDiagnosticText(Diagnostics.BUILD_OPTIONS), + buildOptions, + /*subCategory*/ false, + formatMessage( + /*dummy*/ undefined, + Diagnostics + .Using_build_b_will_make_tsc_behave_more_like_a_build_orchestrator_than_a_compiler_This_is_used_to_trigger_building_composite_projects_which_you_can_learn_more_about_at_0, + "https://aka.ms/tsc-composite-builds", + ), + ), + ]; for (const line of output) { sys.write(line); } @@ -591,13 +755,19 @@ function executeCommandLineWorker( } if (commandLine.options.watch && commandLine.options.listFilesOnly) { - reportDiagnostic(createCompilerDiagnostic(Diagnostics.Options_0_and_1_cannot_be_combined, "watch", "listFilesOnly")); + reportDiagnostic( + createCompilerDiagnostic(Diagnostics.Options_0_and_1_cannot_be_combined, "watch", "listFilesOnly"), + ); return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped); } if (commandLine.options.project) { if (commandLine.fileNames.length !== 0) { - reportDiagnostic(createCompilerDiagnostic(Diagnostics.Option_project_cannot_be_mixed_with_source_files_on_a_command_line)); + reportDiagnostic( + createCompilerDiagnostic( + Diagnostics.Option_project_cannot_be_mixed_with_source_files_on_a_command_line, + ), + ); return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped); } @@ -605,14 +775,24 @@ function executeCommandLineWorker( if (!fileOrDirectory /* current directory "." */ || sys.directoryExists(fileOrDirectory)) { configFileName = combinePaths(fileOrDirectory, "tsconfig.json"); if (!sys.fileExists(configFileName)) { - reportDiagnostic(createCompilerDiagnostic(Diagnostics.Cannot_find_a_tsconfig_json_file_at_the_specified_directory_Colon_0, commandLine.options.project)); + reportDiagnostic( + createCompilerDiagnostic( + Diagnostics.Cannot_find_a_tsconfig_json_file_at_the_specified_directory_Colon_0, + commandLine.options.project, + ), + ); return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped); } } else { configFileName = fileOrDirectory; if (!sys.fileExists(configFileName)) { - reportDiagnostic(createCompilerDiagnostic(Diagnostics.The_specified_path_does_not_exist_Colon_0, commandLine.options.project)); + reportDiagnostic( + createCompilerDiagnostic( + Diagnostics.The_specified_path_does_not_exist_Colon_0, + commandLine.options.project, + ), + ); return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped); } } @@ -624,7 +804,12 @@ function executeCommandLineWorker( if (commandLine.fileNames.length === 0 && !configFileName) { if (commandLine.options.showConfig) { - reportDiagnostic(createCompilerDiagnostic(Diagnostics.Cannot_find_a_tsconfig_json_file_at_the_current_directory_Colon_0, normalizePath(sys.getCurrentDirectory()))); + reportDiagnostic( + createCompilerDiagnostic( + Diagnostics.Cannot_find_a_tsconfig_json_file_at_the_current_directory_Colon_0, + normalizePath(sys.getCurrentDirectory()), + ), + ); } else { printVersion(sys); @@ -640,7 +825,14 @@ function executeCommandLineWorker( ); if (configFileName) { const extendedConfigCache = new Map(); - const configParseResult = parseConfigFileWithSystem(configFileName, commandLineOptions, extendedConfigCache, commandLine.watchOptions, sys, reportDiagnostic)!; // TODO: GH#18217 + const configParseResult = parseConfigFileWithSystem( + configFileName, + commandLineOptions, + extendedConfigCache, + commandLine.watchOptions, + sys, + reportDiagnostic, + )!; // TODO: GH#18217 if (commandLineOptions.showConfig) { if (configParseResult.errors.length !== 0) { reportDiagnostic = updateReportDiagnostic( @@ -692,7 +884,13 @@ function executeCommandLineWorker( else { if (commandLineOptions.showConfig) { // eslint-disable-next-line no-null/no-null - sys.write(JSON.stringify(convertToTSConfig(commandLine, combinePaths(currentDirectory, "tsconfig.json"), sys), null, 4) + sys.newLine); + sys.write( + JSON.stringify( + convertToTSConfig(commandLine, combinePaths(currentDirectory, "tsconfig.json"), sys), + null, + 4, + ) + sys.newLine, + ); return sys.exit(ExitStatus.Success); } reportDiagnostic = updateReportDiagnostic( @@ -732,7 +930,8 @@ function executeCommandLineWorker( export function isBuild(commandLineArgs: readonly string[]) { if (commandLineArgs.length > 0 && commandLineArgs[0].charCodeAt(0) === CharacterCodes.minus) { - const firstOption = commandLineArgs[0].slice(commandLineArgs[0].charCodeAt(1) === CharacterCodes.minus ? 2 : 1).toLowerCase(); + const firstOption = commandLineArgs[0].slice(commandLineArgs[0].charCodeAt(1) === CharacterCodes.minus ? 2 : 1) + .toLowerCase(); return firstOption === "build" || firstOption === "b"; } return false; @@ -785,7 +984,9 @@ export function executeCommandLine( function reportWatchModeWithoutSysSupport(sys: System, reportDiagnostic: DiagnosticReporter) { if (!sys.watchFile || !sys.watchDirectory) { - reportDiagnostic(createCompilerDiagnostic(Diagnostics.The_current_host_does_not_support_the_0_option, "--watch")); + reportDiagnostic( + createCompilerDiagnostic(Diagnostics.The_current_host_does_not_support_the_0_option, "--watch"), + ); sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped); return true; } @@ -829,7 +1030,9 @@ function performBuild( } if (!sys.getModifiedTime || !sys.setModifiedTime || (buildOptions.clean && !sys.deleteFile)) { - reportDiagnostic(createCompilerDiagnostic(Diagnostics.The_current_host_does_not_support_the_0_option, "--build")); + reportDiagnostic( + createCompilerDiagnostic(Diagnostics.The_current_host_does_not_support_the_0_option, "--build"), + ); return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped); } @@ -850,8 +1053,8 @@ function performBuild( onWatchStatusChange?.(d, newLine, options, errorCount); if ( reportBuildStatistics && ( - d.code === Diagnostics.Found_0_errors_Watching_for_file_changes.code || - d.code === Diagnostics.Found_1_error_Watching_for_file_changes.code + d.code === Diagnostics.Found_0_errors_Watching_for_file_changes.code + || d.code === Diagnostics.Found_1_error_Watching_for_file_changes.code ) ) { reportSolutionBuilderTimes(builder, solutionPerformance); @@ -880,10 +1083,13 @@ function performBuild( return sys.exit(exitStatus); } -function createReportErrorSummary(sys: System, options: CompilerOptions | BuildOptions): ReportEmitErrorSummary | undefined { - return shouldBePretty(sys, options) ? - (errorCount, filesInError) => sys.write(getErrorSummaryText(errorCount, filesInError, sys.newLine, sys)) : - undefined; +function createReportErrorSummary( + sys: System, + options: CompilerOptions | BuildOptions, +): ReportEmitErrorSummary | undefined { + return shouldBePretty(sys, options) + ? (errorCount, filesInError) => sys.write(getErrorSummaryText(errorCount, filesInError, sys.newLine, sys)) + : undefined; } function performCompilation( @@ -962,14 +1168,25 @@ function updateSolutionBuilderHost( }; } -function updateCreateProgram(sys: System, host: { createProgram: CreateProgram; }, isBuildMode: boolean) { +function updateCreateProgram( + sys: System, + host: { createProgram: CreateProgram; }, + isBuildMode: boolean, +) { const compileUsingBuilder = host.createProgram; host.createProgram = (rootNames, options, host, oldProgram, configFileParsingDiagnostics, projectReferences) => { Debug.assert(rootNames !== undefined || (options === undefined && !!oldProgram)); if (options !== undefined) { enableStatisticsAndTracing(sys, options, isBuildMode); } - return compileUsingBuilder(rootNames, options, host, oldProgram, configFileParsingDiagnostics, projectReferences); + return compileUsingBuilder( + rootNames, + options, + host, + oldProgram, + configFileParsingDiagnostics, + projectReferences, + ); }; } @@ -1082,13 +1299,21 @@ function reportSolutionBuilderTimes( if (!solutionPerformance) return; if (!performance.isEnabled()) { - sys.write(Diagnostics.Performance_timings_for_diagnostics_or_extendedDiagnostics_are_not_available_in_this_session_A_native_implementation_of_the_Web_Performance_API_could_not_be_found.message + "\n"); + sys.write( + Diagnostics + .Performance_timings_for_diagnostics_or_extendedDiagnostics_are_not_available_in_this_session_A_native_implementation_of_the_Web_Performance_API_could_not_be_found + .message + "\n", + ); return; } const statistics: Statistic[] = []; statistics.push( - { name: "Projects in scope", value: getBuildOrderFromAnyBuildOrder(builder.getBuildOrder()).length, type: StatisticType.count }, + { + name: "Projects in scope", + value: getBuildOrderFromAnyBuildOrder(builder.getBuildOrder()).length, + type: StatisticType.count, + }, ); reportSolutionBuilderCountStatistic("SolutionBuilder::Projects built"); reportSolutionBuilderCountStatistic("SolutionBuilder::Timestamps only updates"); @@ -1098,7 +1323,13 @@ function reportSolutionBuilderTimes( statistics.push(s); }); performance.forEachMeasure((name, duration) => { - if (isSolutionMarkOrMeasure(name)) statistics.push({ name: `${getNameFromSolutionBuilderMarkOrMeasure(name)} time`, value: duration, type: StatisticType.time }); + if (isSolutionMarkOrMeasure(name)) { + statistics.push({ + name: `${getNameFromSolutionBuilderMarkOrMeasure(name)} time`, + value: duration, + type: StatisticType.time, + }); + } }); performance.disable(); performance.enable(); @@ -1144,7 +1375,11 @@ function isProgram(programOrConfig: Program | ParsedCommandLine): programOrConfi return !(programOrConfig as ParsedCommandLine).options; } -function reportStatistics(sys: System, programOrConfig: Program | ParsedCommandLine, solutionPerformance: SolutionPerformance | undefined) { +function reportStatistics( + sys: System, + programOrConfig: Program | ParsedCommandLine, + solutionPerformance: SolutionPerformance | undefined, +) { const program = isProgram(programOrConfig) ? programOrConfig : undefined; const config = isProgram(programOrConfig) ? undefined : programOrConfig; const compilerOptions = program ? program.getCompilerOptions() : config!.options; @@ -1176,7 +1411,10 @@ function reportStatistics(sys: System, programOrConfig: Program | ParsedCommandL reportCountStatistic("Instantiations", program.getInstantiationCount()); } if (memoryUsed >= 0) { - reportStatisticalValue({ name: "Memory used", value: memoryUsed, type: StatisticType.memory }, /*aggregate*/ true); + reportStatisticalValue( + { name: "Memory used", value: memoryUsed, type: StatisticType.memory }, + /*aggregate*/ true, + ); } const isPerformanceEnabled = performance.isEnabled(); @@ -1194,7 +1432,9 @@ function reportStatistics(sys: System, programOrConfig: Program | ParsedCommandL } if (isPerformanceEnabled) { performance.forEachMeasure((name, duration) => { - if (!isSolutionMarkOrMeasure(name)) reportTimeStatistic(`${name} time`, duration, /*aggregate*/ true); + if (!isSolutionMarkOrMeasure(name)) { + reportTimeStatistic(`${name} time`, duration, /*aggregate*/ true); + } }); } } @@ -1215,7 +1455,11 @@ function reportStatistics(sys: System, programOrConfig: Program | ParsedCommandL } reportAllStatistics(sys, statistics); if (!isPerformanceEnabled) { - sys.write(Diagnostics.Performance_timings_for_diagnostics_or_extendedDiagnostics_are_not_available_in_this_session_A_native_implementation_of_the_Web_Performance_API_could_not_be_found.message + "\n"); + sys.write( + Diagnostics + .Performance_timings_for_diagnostics_or_extendedDiagnostics_are_not_available_in_this_session_A_native_implementation_of_the_Web_Performance_API_could_not_be_found + .message + "\n", + ); } else { if (solutionPerformance) { @@ -1262,7 +1506,9 @@ function reportAllStatistics(sys: System, statistics: Statistic[]) { } for (const s of statistics) { - sys.write(padRight(s.name + ":", nameSize + 2) + padLeft(statisticValue(s).toString(), valueSize) + sys.newLine); + sys.write( + padRight(s.name + ":", nameSize + 2) + padLeft(statisticValue(s).toString(), valueSize) + sys.newLine, + ); } } @@ -1288,7 +1534,9 @@ function writeConfigFile( const currentDirectory = sys.getCurrentDirectory(); const file = normalizePath(combinePaths(currentDirectory, "tsconfig.json")); if (sys.fileExists(file)) { - reportDiagnostic(createCompilerDiagnostic(Diagnostics.A_tsconfig_json_file_is_already_defined_at_Colon_0, file)); + reportDiagnostic( + createCompilerDiagnostic(Diagnostics.A_tsconfig_json_file_is_already_defined_at_Colon_0, file), + ); } else { sys.writeFile(file, generateTSConfig(options, fileNames, sys.newLine)); diff --git a/src/harness/client.ts b/src/harness/client.ts index 6f3a3cf9bbac5..a46df3e248272 100644 --- a/src/harness/client.ts +++ b/src/harness/client.ts @@ -102,14 +102,20 @@ export function extractMessage(message: string): string { Debug.assert(lines.length >= 2, "Malformed response: Expected 3 lines in the response."); const contentLengthText = lines[0]; - Debug.assert(contentLengthText.indexOf(contentLengthPrefix) === 0, "Malformed response: Response text did not contain content-length header."); + Debug.assert( + contentLengthText.indexOf(contentLengthPrefix) === 0, + "Malformed response: Response text did not contain content-length header.", + ); const contentLength = parseInt(contentLengthText.substring(contentLengthPrefix.length)); // Read the body const responseBody = lines[2]; // Verify content length - Debug.assert(responseBody.length + 1 === contentLength, "Malformed response: Content length did not match the response's body length."); + Debug.assert( + responseBody.length + 1 === contentLength, + "Malformed response: Content length did not match the response's body length.", + ); return responseBody; } @@ -187,7 +193,10 @@ export class SessionClient implements LanguageService { } } catch (e) { - throw new Error("Malformed response: Failed to parse server response: " + lastMessage + ". \r\n Error details: " + e.message); + throw new Error( + "Malformed response: Failed to parse server response: " + lastMessage + ". \r\n Error details: " + + e.message, + ); } } @@ -196,7 +205,10 @@ export class SessionClient implements LanguageService { throw new Error("Error " + response.message); } - Debug.assert(response.request_seq === request.seq, "Malformed response: response sequence number did not match request sequence number."); + Debug.assert( + response.request_seq === request.seq, + "Malformed response: response sequence number did not match request sequence number.", + ); Debug.assert(expectEmptyBody || !!response.body, "Malformed response: Unexpected empty response body."); Debug.assert(!expectEmptyBody || !response.body, "Malformed response: Unexpected non-empty response body."); @@ -235,7 +247,12 @@ export class SessionClient implements LanguageService { this.processRequest(protocol.CommandTypes.Close, args); } - createChangeFileRequestArgs(fileName: string, start: number, end: number, insertString: string): protocol.ChangeRequestArgs { + createChangeFileRequestArgs( + fileName: string, + start: number, + end: number, + insertString: string, + ): protocol.ChangeRequestArgs { return { ...this.createFileLocationRequestArgsWithEndLineAndOffset(fileName, start, end), insertString }; } @@ -262,7 +279,8 @@ export class SessionClient implements LanguageService { kindModifiers: body.kindModifiers, textSpan: this.decodeSpan(body, fileName), displayParts: [{ kind: "text", text: body.displayString }], - documentation: typeof body.documentation === "string" ? [{ kind: "text", text: body.documentation }] : body.documentation, + documentation: typeof body.documentation === "string" ? [{ kind: "text", text: body.documentation }] + : body.documentation, tags: this.decodeLinkDisplayParts(body.tags), }; } @@ -279,7 +297,11 @@ export class SessionClient implements LanguageService { }; } - getCompletionsAtPosition(fileName: string, position: number, _preferences: UserPreferences | undefined): CompletionInfo { + getCompletionsAtPosition( + fileName: string, + position: number, + _preferences: UserPreferences | undefined, + ): CompletionInfo { // Not passing along 'preferences' because server should already have those from the 'configure' command const args: protocol.CompletionsRequestArgs = this.createFileLocationRequestArgs(fileName, position); @@ -292,7 +314,11 @@ export class SessionClient implements LanguageService { isNewIdentifierLocation: response.body!.isNewIdentifierLocation, entries: response.body!.entries.map(entry => { // TODO: GH#18217 if (entry.replacementSpan !== undefined) { - const res: CompletionEntry = { ...entry, data: entry.data as any, replacementSpan: this.decodeSpan(entry.replacementSpan, fileName) }; + const res: CompletionEntry = { + ...entry, + data: entry.data as any, + replacementSpan: this.decodeSpan(entry.replacementSpan, fileName), + }; return res; } @@ -301,10 +327,24 @@ export class SessionClient implements LanguageService { }; } - getCompletionEntryDetails(fileName: string, position: number, entryName: string, _options: FormatCodeOptions | FormatCodeSettings | undefined, source: string | undefined, _preferences: UserPreferences | undefined, data: unknown): CompletionEntryDetails { - const args: protocol.CompletionDetailsRequestArgs = { ...this.createFileLocationRequestArgs(fileName, position), entryNames: [{ name: entryName, source, data }] }; + getCompletionEntryDetails( + fileName: string, + position: number, + entryName: string, + _options: FormatCodeOptions | FormatCodeSettings | undefined, + source: string | undefined, + _preferences: UserPreferences | undefined, + data: unknown, + ): CompletionEntryDetails { + const args: protocol.CompletionDetailsRequestArgs = { + ...this.createFileLocationRequestArgs(fileName, position), + entryNames: [{ name: entryName, source, data }], + }; - const request = this.processRequest(protocol.CommandTypes.CompletionDetailsFull, args); + const request = this.processRequest( + protocol.CommandTypes.CompletionDetailsFull, + args, + ); const response = this.processResponse(request); Debug.assert(response.body.length === 1, "Unexpected length of completion details response body."); return response.body[0]; @@ -337,7 +377,11 @@ export class SessionClient implements LanguageService { } getFormattingEditsForRange(file: string, start: number, end: number, _options: FormatCodeOptions): TextChange[] { - const args: protocol.FormatRequestArgs = this.createFileLocationRequestArgsWithEndLineAndOffset(file, start, end); + const args: protocol.FormatRequestArgs = this.createFileLocationRequestArgsWithEndLineAndOffset( + file, + start, + end, + ); // TODO: handle FormatCodeOptions const request = this.processRequest(protocol.CommandTypes.Format, args); @@ -347,11 +391,24 @@ export class SessionClient implements LanguageService { } getFormattingEditsForDocument(fileName: string, options: FormatCodeOptions): TextChange[] { - return this.getFormattingEditsForRange(fileName, 0, this.host.getScriptSnapshot(fileName)!.getLength(), options); + return this.getFormattingEditsForRange( + fileName, + 0, + this.host.getScriptSnapshot(fileName)!.getLength(), + options, + ); } - getFormattingEditsAfterKeystroke(fileName: string, position: number, key: string, _options: FormatCodeOptions): TextChange[] { - const args: protocol.FormatOnKeyRequestArgs = { ...this.createFileLocationRequestArgs(fileName, position), key }; + getFormattingEditsAfterKeystroke( + fileName: string, + position: number, + key: string, + _options: FormatCodeOptions, + ): TextChange[] { + const args: protocol.FormatOnKeyRequestArgs = { + ...this.createFileLocationRequestArgs(fileName, position), + key, + }; // TODO: handle FormatCodeOptions const request = this.processRequest(protocol.CommandTypes.Formatonkey, args); @@ -379,7 +436,10 @@ export class SessionClient implements LanguageService { getDefinitionAndBoundSpan(fileName: string, position: number): DefinitionInfoAndBoundSpan { const args: protocol.FileLocationRequestArgs = this.createFileLocationRequestArgs(fileName, position); - const request = this.processRequest(protocol.CommandTypes.DefinitionAndBoundSpan, args); + const request = this.processRequest( + protocol.CommandTypes.DefinitionAndBoundSpan, + args, + ); const response = this.processResponse(request); const body = Debug.checkDefined(response.body); // TODO: GH#18217 @@ -415,7 +475,10 @@ export class SessionClient implements LanguageService { getSourceDefinitionAndBoundSpan(fileName: string, position: number): DefinitionInfo[] { const args: protocol.FileLocationRequestArgs = this.createFileLocationRequestArgs(fileName, position); - const request = this.processRequest(protocol.CommandTypes.FindSourceDefinition, args); + const request = this.processRequest( + protocol.CommandTypes.FindSourceDefinition, + args, + ); const response = this.processResponse(request); const body = Debug.checkDefined(response.body); // TODO: GH#18217 @@ -466,7 +529,9 @@ export class SessionClient implements LanguageService { } getFileReferences(fileName: string): ReferenceEntry[] { - const request = this.processRequest(protocol.CommandTypes.FileReferences, { file: fileName }); + const request = this.processRequest(protocol.CommandTypes.FileReferences, { + file: fileName, + }); const response = this.processResponse(request); return response.body!.refs.map(entry => ({ // TODO: GH#18217 @@ -494,13 +559,24 @@ export class SessionClient implements LanguageService { } private getDiagnostics(file: string, command: protocol.CommandTypes): DiagnosticWithLocation[] { - const request = this.processRequest(command, { file, includeLinePosition: true }); - const response = this.processResponse(request); + const request = this.processRequest< + | protocol.SyntacticDiagnosticsSyncRequest + | protocol.SemanticDiagnosticsSyncRequest + | protocol.SuggestionDiagnosticsSyncRequest + >(command, { file, includeLinePosition: true }); + const response = this.processResponse< + | protocol.SyntacticDiagnosticsSyncResponse + | protocol.SemanticDiagnosticsSyncResponse + | protocol.SuggestionDiagnosticsSyncResponse + >(request); const sourceText = getSnapshotText(this.host.getScriptSnapshot(file)!); const fakeSourceFile = { fileName: file, text: sourceText } as SourceFile; // Warning! This is a huge lie! return (response.body as protocol.DiagnosticWithLinePosition[]).map((entry): DiagnosticWithLocation => { - const category = firstDefined(Object.keys(DiagnosticCategory), id => isString(id) && entry.category === id.toLowerCase() ? (DiagnosticCategory as any)[id] : undefined); + const category = firstDefined( + Object.keys(DiagnosticCategory), + id => isString(id) && entry.category === id.toLowerCase() ? (DiagnosticCategory as any)[id] : undefined, + ); return { file: fakeSourceFile, start: entry.start, @@ -518,9 +594,19 @@ export class SessionClient implements LanguageService { return notImplemented(); } - getRenameInfo(fileName: string, position: number, _preferences: UserPreferences, findInStrings?: boolean, findInComments?: boolean): RenameInfo { + getRenameInfo( + fileName: string, + position: number, + _preferences: UserPreferences, + findInStrings?: boolean, + findInComments?: boolean, + ): RenameInfo { // Not passing along 'options' because server should already have those from the 'configure' command - const args: protocol.RenameRequestArgs = { ...this.createFileLocationRequestArgs(fileName, position), findInStrings, findInComments }; + const args: protocol.RenameRequestArgs = { + ...this.createFileLocationRequestArgs(fileName, position), + findInStrings, + findInComments, + }; const request = this.processRequest(protocol.CommandTypes.Rename, args); const response = this.processResponse(request); @@ -532,9 +618,9 @@ export class SessionClient implements LanguageService { locations.push({ textSpan: this.decodeSpan({ start, end }, fileName), fileName, - ...(contextStart !== undefined ? - { contextSpan: this.decodeSpan({ start: contextStart, end: contextEnd! }, fileName) } : - undefined), + ...(contextStart !== undefined + ? { contextSpan: this.decodeSpan({ start: contextStart, end: contextEnd! }, fileName) } + : undefined), ...prefixSuffixText, }); } @@ -568,15 +654,22 @@ export class SessionClient implements LanguageService { return notImplemented(); } - findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean, preferences: UserPreferences | boolean | undefined): RenameLocation[] { + findRenameLocations( + fileName: string, + position: number, + findInStrings: boolean, + findInComments: boolean, + preferences: UserPreferences | boolean | undefined, + ): RenameLocation[] { if ( - !this.lastRenameEntry || - this.lastRenameEntry.inputs.fileName !== fileName || - this.lastRenameEntry.inputs.position !== position || - this.lastRenameEntry.inputs.findInStrings !== findInStrings || - this.lastRenameEntry.inputs.findInComments !== findInComments + !this.lastRenameEntry + || this.lastRenameEntry.inputs.fileName !== fileName + || this.lastRenameEntry.inputs.position !== position + || this.lastRenameEntry.inputs.findInStrings !== findInStrings + || this.lastRenameEntry.inputs.findInComments !== findInComments ) { - const providePrefixAndSuffixTextForRename = typeof preferences === "boolean" ? preferences : preferences?.providePrefixAndSuffixTextForRename; + const providePrefixAndSuffixTextForRename = typeof preferences === "boolean" ? preferences + : preferences?.providePrefixAndSuffixTextForRename; const quotePreference = typeof preferences === "boolean" ? undefined : preferences?.quotePreference; if (providePrefixAndSuffixTextForRename !== undefined || quotePreference !== undefined) { // User preferences have to be set through the `Configure` command @@ -596,7 +689,11 @@ export class SessionClient implements LanguageService { return this.lastRenameEntry!.locations; } - private decodeNavigationBarItems(items: protocol.NavigationBarItem[] | undefined, fileName: string, lineMap: number[]): NavigationBarItem[] { + private decodeNavigationBarItems( + items: protocol.NavigationBarItem[] | undefined, + fileName: string, + lineMap: number[], + ): NavigationBarItem[] { if (!items) { return []; } @@ -681,18 +778,33 @@ export class SessionClient implements LanguageService { return undefined; } - const { items: encodedItems, applicableSpan: encodedApplicableSpan, selectedItemIndex, argumentIndex, argumentCount } = response.body; + const { + items: encodedItems, + applicableSpan: encodedApplicableSpan, + selectedItemIndex, + argumentIndex, + argumentCount, + } = response.body; const applicableSpan = encodedApplicableSpan as unknown as TextSpan; - const items = (encodedItems as (SignatureHelpItem | protocol.SignatureHelpItem)[]).map(item => ({ ...item, tags: this.decodeLinkDisplayParts(item.tags) })); + const items = (encodedItems as (SignatureHelpItem | protocol.SignatureHelpItem)[]).map(item => ({ + ...item, + tags: this.decodeLinkDisplayParts(item.tags), + })); return { items, applicableSpan, selectedItemIndex, argumentIndex, argumentCount }; } getDocumentHighlights(fileName: string, position: number, filesToSearch: string[]): DocumentHighlights[] { - const args: protocol.DocumentHighlightsRequestArgs = { ...this.createFileLocationRequestArgs(fileName, position), filesToSearch }; + const args: protocol.DocumentHighlightsRequestArgs = { + ...this.createFileLocationRequestArgs(fileName, position), + filesToSearch, + }; - const request = this.processRequest(protocol.CommandTypes.DocumentHighlights, args); + const request = this.processRequest( + protocol.CommandTypes.DocumentHighlights, + args, + ); const response = this.processResponse(request); return response.body!.map(item => ({ // TODO: GH#18217 @@ -705,7 +817,9 @@ export class SessionClient implements LanguageService { } getOutliningSpans(file: string): OutliningSpan[] { - const request = this.processRequest(protocol.CommandTypes.GetOutliningSpans, { file }); + const request = this.processRequest(protocol.CommandTypes.GetOutliningSpans, { + file, + }); const response = this.processResponse(request); return response.body!.map(item => ({ @@ -721,7 +835,12 @@ export class SessionClient implements LanguageService { return notImplemented(); } - getDocCommentTemplateAtPosition(_fileName: string, _position: number, _options?: DocCommentTemplateOptions, _formatOptions?: FormatCodeSettings): TextInsertion { + getDocCommentTemplateAtPosition( + _fileName: string, + _position: number, + _options?: DocCommentTemplateOptions, + _formatOptions?: FormatCodeSettings, + ): TextInsertion { return notImplemented(); } @@ -741,14 +860,28 @@ export class SessionClient implements LanguageService { return notImplemented(); } - getCodeFixesAtPosition(file: string, start: number, end: number, errorCodes: readonly number[]): readonly CodeFixAction[] { + getCodeFixesAtPosition( + file: string, + start: number, + end: number, + errorCodes: readonly number[], + ): readonly CodeFixAction[] { const args: protocol.CodeFixRequestArgs = { ...this.createFileRangeRequestArgs(file, start, end), errorCodes }; const request = this.processRequest(protocol.CommandTypes.GetCodeFixes, args); const response = this.processResponse(request); - return response.body!.map(({ fixName, description, changes, commands, fixId, fixAllDescription }) => // TODO: GH#18217 - ({ fixName, description, changes: this.convertChanges(changes, file), commands: commands as CodeActionCommand[], fixId, fixAllDescription })); + return response.body!.map(( + { fixName, description, changes, commands, fixId, fixAllDescription }, + ) => // TODO: GH#18217 + ({ + fixName, + description, + changes: this.convertChanges(changes, file), + commands: commands as CodeActionCommand[], + fixId, + fixAllDescription, + })); } getCombinedCodeFix = notImplemented; @@ -773,7 +906,8 @@ export class SessionClient implements LanguageService { text, span: span && { start: this.lineOffsetToPosition(span.file, span.start), - length: this.lineOffsetToPosition(span.file, span.end) - this.lineOffsetToPosition(span.file, span.start), + length: this.lineOffsetToPosition(span.file, span.end) + - this.lineOffsetToPosition(span.file, span.start), }, file: span && span.file, })), @@ -781,7 +915,10 @@ export class SessionClient implements LanguageService { }); } - private createFileLocationOrRangeRequestArgs(positionOrRange: number | TextRange, fileName: string): protocol.FileLocationOrRangeRequestArgs { + private createFileLocationOrRangeRequestArgs( + positionOrRange: number | TextRange, + fileName: string, + ): protocol.FileLocationOrRangeRequestArgs { return typeof positionOrRange === "number" ? this.createFileLocationRequestArgs(fileName, positionOrRange) : this.createFileRangeRequestArgs(fileName, positionOrRange.pos, positionOrRange.end); @@ -798,7 +935,11 @@ export class SessionClient implements LanguageService { return { file, startLine, startOffset, endLine, endOffset }; } - private createFileLocationRequestArgsWithEndLineAndOffset(file: string, start: number, end: number): protocol.FileLocationRequestArgs & { endLine: number; endOffset: number; } { + private createFileLocationRequestArgsWithEndLineAndOffset( + file: string, + start: number, + end: number, + ): protocol.FileLocationRequestArgs & { endLine: number; endOffset: number; } { const { line, offset } = this.positionToOneBasedLineOffset(file, start); const { line: endLine, offset: endOffset } = this.positionToOneBasedLineOffset(file, end); return { file, line, offset, endLine, endOffset }; @@ -815,11 +956,17 @@ export class SessionClient implements LanguageService { if (preferences) { // Temporarily set preferences this.configure(preferences); } - const args: protocol.GetApplicableRefactorsRequestArgs = this.createFileLocationOrRangeRequestArgs(positionOrRange, fileName); + const args: protocol.GetApplicableRefactorsRequestArgs = this.createFileLocationOrRangeRequestArgs( + positionOrRange, + fileName, + ); args.triggerReason = triggerReason; args.kind = kind; args.includeInteractiveActions = includeInteractiveActions; - const request = this.processRequest(protocol.CommandTypes.GetApplicableRefactors, args); + const request = this.processRequest( + protocol.CommandTypes.GetApplicableRefactors, + args, + ); const response = this.processResponse(request); if (preferences) { // Restore preferences this.configure(this.preferences || {}); @@ -827,10 +974,16 @@ export class SessionClient implements LanguageService { return response.body!; // TODO: GH#18217 } - getMoveToRefactoringFileSuggestions(fileName: string, positionOrRange: number | TextRange): { newFileName: string; files: string[]; } { + getMoveToRefactoringFileSuggestions( + fileName: string, + positionOrRange: number | TextRange, + ): { newFileName: string; files: string[]; } { const args = this.createFileLocationOrRangeRequestArgs(positionOrRange, fileName); - const request = this.processRequest(protocol.CommandTypes.GetMoveToRefactoringFileSuggestions, args); + const request = this.processRequest( + protocol.CommandTypes.GetMoveToRefactoringFileSuggestions, + args, + ); const response = this.processResponse(request); return { newFileName: response.body?.newFileName, files: response.body?.files }!; } @@ -847,12 +1000,18 @@ export class SessionClient implements LanguageService { if (preferences) { // Temporarily set preferences this.configure(preferences); } - const args = this.createFileLocationOrRangeRequestArgs(positionOrRange, fileName) as protocol.GetEditsForRefactorRequestArgs; + const args = this.createFileLocationOrRangeRequestArgs( + positionOrRange, + fileName, + ) as protocol.GetEditsForRefactorRequestArgs; args.refactor = refactorName; args.action = actionName; args.interactiveRefactorArguments = interactiveRefactorArguments; - const request = this.processRequest(protocol.CommandTypes.GetEditsForRefactor, args); + const request = this.processRequest( + protocol.CommandTypes.GetEditsForRefactor, + args, + ); const response = this.processResponse(request); if (!response.body) { @@ -921,7 +1080,10 @@ export class SessionClient implements LanguageService { } configurePlugin(pluginName: string, configuration: any): void { - const request = this.processRequest("configurePlugin", { pluginName, configuration }); + const request = this.processRequest("configurePlugin", { + pluginName, + configuration, + }); this.processResponse(request, /*expectEmptyBody*/ true); } @@ -941,8 +1103,15 @@ export class SessionClient implements LanguageService { return notImplemented(); } - getEncodedSemanticClassifications(file: string, span: TextSpan, format?: SemanticClassificationFormat): Classifications { - const request = this.processRequest(protocol.CommandTypes.EncodedSemanticClassificationsFull, { file, start: span.start, length: span.length, format }); + getEncodedSemanticClassifications( + file: string, + span: TextSpan, + format?: SemanticClassificationFormat, + ): Classifications { + const request = this.processRequest( + protocol.CommandTypes.EncodedSemanticClassificationsFull, + { file, start: span.start, length: span.length, format }, + ); const r = this.processResponse(request); return r.body!; } @@ -961,7 +1130,10 @@ export class SessionClient implements LanguageService { prepareCallHierarchy(fileName: string, position: number): CallHierarchyItem | CallHierarchyItem[] | undefined { const args = this.createFileLocationRequestArgs(fileName, position); - const request = this.processRequest(protocol.CommandTypes.PrepareCallHierarchy, args); + const request = this.processRequest( + protocol.CommandTypes.PrepareCallHierarchy, + args, + ); const response = this.processResponse(request); return response.body && mapOneOrMany(response.body, item => this.convertCallHierarchyItem(item)); } @@ -975,12 +1147,18 @@ export class SessionClient implements LanguageService { provideCallHierarchyIncomingCalls(fileName: string, position: number) { const args = this.createFileLocationRequestArgs(fileName, position); - const request = this.processRequest(protocol.CommandTypes.ProvideCallHierarchyIncomingCalls, args); + const request = this.processRequest( + protocol.CommandTypes.ProvideCallHierarchyIncomingCalls, + args, + ); const response = this.processResponse(request); return response.body.map(item => this.convertCallHierarchyIncomingCall(item)); } - private convertCallHierarchyOutgoingCall(file: string, item: protocol.CallHierarchyOutgoingCall): CallHierarchyOutgoingCall { + private convertCallHierarchyOutgoingCall( + file: string, + item: protocol.CallHierarchyOutgoingCall, + ): CallHierarchyOutgoingCall { return { to: this.convertCallHierarchyItem(item.to), fromSpans: item.fromSpans.map(span => this.decodeSpan(span, file)), @@ -989,7 +1167,10 @@ export class SessionClient implements LanguageService { provideCallHierarchyOutgoingCalls(fileName: string, position: number) { const args = this.createFileLocationRequestArgs(fileName, position); - const request = this.processRequest(protocol.CommandTypes.ProvideCallHierarchyOutgoingCalls, args); + const request = this.processRequest( + protocol.CommandTypes.ProvideCallHierarchyOutgoingCalls, + args, + ); const response = this.processResponse(request); return response.body.map(item => this.convertCallHierarchyOutgoingCall(fileName, item)); } @@ -1010,7 +1191,10 @@ export class SessionClient implements LanguageService { throw new Error("Program objects are not serializable through the server protocol."); } - updateIsDefinitionOfReferencedSymbols(_referencedSymbols: readonly ReferencedSymbol[], _knownSymbolSpans: Set): boolean { + updateIsDefinitionOfReferencedSymbols( + _referencedSymbols: readonly ReferencedSymbol[], + _knownSymbolSpans: Set, + ): boolean { return notImplemented(); } diff --git a/src/harness/collectionsImpl.ts b/src/harness/collectionsImpl.ts index 9f3b88cfb13ac..9c86d021546c3 100644 --- a/src/harness/collectionsImpl.ts +++ b/src/harness/collectionsImpl.ts @@ -300,6 +300,7 @@ export class Metadata { } private static _unescapeKey(text: string) { - return (text.length >= 3 && text.charAt(0) === "_" && text.charAt(1) === "_" && text.charAt(2) === "_" ? text.slice(1) : text); + return (text.length >= 3 && text.charAt(0) === "_" && text.charAt(1) === "_" && text.charAt(2) === "_" + ? text.slice(1) : text); } } diff --git a/src/harness/compilerImpl.ts b/src/harness/compilerImpl.ts index 1a37603da1e41..67c442dbe04d0 100644 --- a/src/harness/compilerImpl.ts +++ b/src/harness/compilerImpl.ts @@ -16,13 +16,18 @@ export interface Project { errors?: ts.Diagnostic[]; } -export function readProject(host: fakes.ParseConfigHost, project: string | undefined, existingOptions?: ts.CompilerOptions): Project | undefined { +export function readProject( + host: fakes.ParseConfigHost, + project: string | undefined, + existingOptions?: ts.CompilerOptions, +): Project | undefined { if (project) { project = vpath.isTsConfigFile(project) ? project : vpath.combine(project, "tsconfig.json"); } else { [project] = host.vfs.scanSync(".", "ancestors-or-self", { - accept: (path, stats) => stats.isFile() && host.vfs.stringComparer(vpath.basename(path), "tsconfig.json") === 0, + accept: (path, stats) => + stats.isFile() && host.vfs.stringComparer(vpath.basename(path), "tsconfig.json") === 0, }); } @@ -66,7 +71,13 @@ export class CompilationResult { private _inputs: documents.TextDocument[] = []; private _inputsAndOutputs: collections.SortedMap; - constructor(host: fakes.CompilerHost, options: ts.CompilerOptions, program: ts.Program | undefined, result: ts.EmitResult | undefined, diagnostics: readonly ts.Diagnostic[]) { + constructor( + host: fakes.CompilerHost, + options: ts.CompilerOptions, + program: ts.Program | undefined, + result: ts.EmitResult | undefined, + diagnostics: readonly ts.Diagnostic[], + ) { this.host = host; this.program = program; this.result = result; @@ -74,9 +85,18 @@ export class CompilationResult { this.options = program ? program.getCompilerOptions() : options; // collect outputs - const js = this.js = new collections.SortedMap({ comparer: this.vfs.stringComparer, sort: "insertion" }); - const dts = this.dts = new collections.SortedMap({ comparer: this.vfs.stringComparer, sort: "insertion" }); - const maps = this.maps = new collections.SortedMap({ comparer: this.vfs.stringComparer, sort: "insertion" }); + const js = this.js = new collections.SortedMap({ + comparer: this.vfs.stringComparer, + sort: "insertion", + }); + const dts = this.dts = new collections.SortedMap({ + comparer: this.vfs.stringComparer, + sort: "insertion", + }); + const maps = this.maps = new collections.SortedMap({ + comparer: this.vfs.stringComparer, + sort: "insertion", + }); for (const document of this.host.outputs) { if (vpath.isJavaScript(document.file) || ts.fileExtensionIs(document.file, ts.Extension.Json)) { js.set(document.file, document); @@ -90,7 +110,10 @@ export class CompilationResult { } // correlate inputs and outputs - this._inputsAndOutputs = new collections.SortedMap({ comparer: this.vfs.stringComparer, sort: "insertion" }); + this._inputsAndOutputs = new collections.SortedMap({ + comparer: this.vfs.stringComparer, + sort: "insertion", + }); if (program) { if (this.options.out || this.options.outFile) { const outFile = vpath.resolve(this.vfs.cwd(), this.options.outFile || this.options.out); @@ -130,7 +153,12 @@ export class CompilationResult { const outputs: CompilationOutput = { inputs: [input], js: js.get(this.getOutputPath(sourceFile.fileName, extname)), - dts: dts.get(this.getOutputPath(sourceFile.fileName, ts.getDeclarationEmitExtensionForPath(sourceFile.fileName))), + dts: dts.get( + this.getOutputPath( + sourceFile.fileName, + ts.getDeclarationEmitExtensionForPath(sourceFile.fileName), + ), + ), map: maps.get(this.getOutputPath(sourceFile.fileName, extname + ".map")), }; @@ -191,7 +219,12 @@ export class CompilationResult { public getSourceMapRecord(): string | undefined { const maps = this.result!.sourceMaps; if (maps && maps.length > 0) { - return Harness.SourceMapRecorder.getSourceMapRecord(maps, this.program!, ts.arrayFrom(this.js.values()).filter(d => !ts.fileExtensionIs(d.file, ts.Extension.Json)), ts.arrayFrom(this.dts.values())); + return Harness.SourceMapRecorder.getSourceMapRecord( + maps, + this.program!, + ts.arrayFrom(this.js.values()).filter(d => !ts.fileExtensionIs(d.file, ts.Extension.Json)), + ts.arrayFrom(this.dts.values()), + ); } } @@ -213,7 +246,9 @@ export class CompilationResult { } else { path = vpath.resolve(this.vfs.cwd(), path); - const outDir = ext === ".d.ts" || ext === ".d.mts" || ext === ".d.cts" || (ext.endsWith(".ts") || ts.stringContains(ext, ".d.")) ? this.options.declarationDir || this.options.outDir : this.options.outDir; + const outDir = ext === ".d.ts" || ext === ".d.mts" || ext === ".d.cts" + || (ext.endsWith(".ts") || ts.stringContains(ext, ".d.")) + ? this.options.declarationDir || this.options.outDir : this.options.outDir; if (outDir) { const common = this.commonSourceDirectory; if (common) { @@ -241,12 +276,23 @@ export class CompilationResult { } } -export function compileFiles(host: fakes.CompilerHost, rootFiles: string[] | undefined, compilerOptions: ts.CompilerOptions, typeScriptVersion?: string): CompilationResult { +export function compileFiles( + host: fakes.CompilerHost, + rootFiles: string[] | undefined, + compilerOptions: ts.CompilerOptions, + typeScriptVersion?: string, +): CompilationResult { if (compilerOptions.project || !rootFiles || rootFiles.length === 0) { const project = readProject(host.parseConfigHost, compilerOptions.project, compilerOptions); if (project) { if (project.errors && project.errors.length > 0) { - return new CompilationResult(host, compilerOptions, /*program*/ undefined, /*result*/ undefined, project.errors); + return new CompilationResult( + host, + compilerOptions, + /*program*/ undefined, + /*result*/ undefined, + project.errors, + ); } if (project.config) { rootFiles = project.config.fileNames; @@ -257,15 +303,25 @@ export function compileFiles(host: fakes.CompilerHost, rootFiles: string[] | und } // establish defaults (aligns with old harness) - if (compilerOptions.target === undefined && compilerOptions.module !== ts.ModuleKind.Node16 && compilerOptions.module !== ts.ModuleKind.NodeNext) compilerOptions.target = ts.ScriptTarget.ES3; + if ( + compilerOptions.target === undefined && compilerOptions.module !== ts.ModuleKind.Node16 + && compilerOptions.module !== ts.ModuleKind.NodeNext + ) compilerOptions.target = ts.ScriptTarget.ES3; if (compilerOptions.newLine === undefined) compilerOptions.newLine = ts.NewLineKind.CarriageReturnLineFeed; if (compilerOptions.skipDefaultLibCheck === undefined) compilerOptions.skipDefaultLibCheck = true; if (compilerOptions.noErrorTruncation === undefined) compilerOptions.noErrorTruncation = true; // pre-emit/post-emit error comparison requires declaration emit twice, which can be slow. If it's unlikely to flag any error consistency issues // and if the test is running `skipLibCheck` - an indicator that we want the tets to run quickly - skip the before/after error comparison, too - const skipErrorComparison = ts.length(rootFiles) >= 100 || (!!compilerOptions.skipLibCheck && !!compilerOptions.declaration); - const preProgram = !skipErrorComparison ? ts.createProgram({ rootNames: rootFiles || [], options: { ...compilerOptions, configFile: compilerOptions.configFile, traceResolution: false }, host, typeScriptVersion }) : undefined; + const skipErrorComparison = ts.length(rootFiles) >= 100 + || (!!compilerOptions.skipLibCheck && !!compilerOptions.declaration); + const preProgram = !skipErrorComparison + ? ts.createProgram({ + rootNames: rootFiles || [], + options: { ...compilerOptions, configFile: compilerOptions.configFile, traceResolution: false }, + host, + typeScriptVersion, + }) : undefined; const preErrors = preProgram && ts.getPreEmitDiagnostics(preProgram); const program = ts.createProgram({ rootNames: rootFiles || [], options: compilerOptions, host, typeScriptVersion }); @@ -280,7 +336,8 @@ export function compileFiles(host: fakes.CompilerHost, rootFiles: string[] | und category: ts.DiagnosticCategory.Error, code: -1, key: "-1", - message: `Pre-emit (${preErrors.length}) and post-emit (${postErrors.length}) diagnostic counts do not match! This can indicate that a semantic _error_ was added by the emit resolver - such an error may not be reflected on the command line or in the editor, but may be captured in a baseline here!`, + message: + `Pre-emit (${preErrors.length}) and post-emit (${postErrors.length}) diagnostic counts do not match! This can indicate that a semantic _error_ was added by the emit resolver - such an error may not be reflected on the command line or in the editor, but may be captured in a baseline here!`, }), ts.createCompilerDiagnostic({ category: ts.DiagnosticCategory.Error, @@ -288,7 +345,10 @@ export function compileFiles(host: fakes.CompilerHost, rootFiles: string[] | und key: "-1", message: `The excess diagnostics are:`, }), - ...ts.filter(longerErrors!, p => !ts.some(shorterErrors, p2 => ts.compareDiagnostics(p, p2) === ts.Comparison.EqualTo)), + ...ts.filter( + longerErrors!, + p => !ts.some(shorterErrors, p2 => ts.compareDiagnostics(p, p2) === ts.Comparison.EqualTo), + ), ), ] : postErrors; return new CompilationResult(host, compilerOptions, program, emitResult, errors); diff --git a/src/harness/documentsUtil.ts b/src/harness/documentsUtil.ts index c538ae3931ec9..4a23ac5818069 100644 --- a/src/harness/documentsUtil.ts +++ b/src/harness/documentsUtil.ts @@ -113,7 +113,14 @@ export class SourceMap { sourceColumn += segment[3]; } - const mapping: Mapping = { mappingIndex: mappings.length, emittedLine, emittedColumn, sourceIndex, sourceLine, sourceColumn }; + const mapping: Mapping = { + mappingIndex: mappings.length, + emittedLine, + emittedColumn, + sourceIndex, + sourceLine, + sourceColumn, + }; if (segment.length === 5) { nameIndex += segment[4]; mapping.nameIndex = nameIndex; @@ -121,11 +128,14 @@ export class SourceMap { mappings.push(mapping); - const mappingsForEmittedLine = this._emittedLineMappings[mapping.emittedLine] || (this._emittedLineMappings[mapping.emittedLine] = []); + const mappingsForEmittedLine = this._emittedLineMappings[mapping.emittedLine] + || (this._emittedLineMappings[mapping.emittedLine] = []); mappingsForEmittedLine.push(mapping); - const mappingsForSource = this._sourceLineMappings[mapping.sourceIndex] || (this._sourceLineMappings[mapping.sourceIndex] = []); - const mappingsForSourceLine = mappingsForSource[mapping.sourceLine] || (mappingsForSource[mapping.sourceLine] = []); + const mappingsForSource = this._sourceLineMappings[mapping.sourceIndex] + || (this._sourceLineMappings[mapping.sourceIndex] = []); + const mappingsForSourceLine = mappingsForSource[mapping.sourceLine] + || (mappingsForSource[mapping.sourceLine] = []); mappingsForSourceLine.push(mapping); } else if (match[2]) { diff --git a/src/harness/evaluatorImpl.ts b/src/harness/evaluatorImpl.ts index c6edef27fb07c..257550766b094 100644 --- a/src/harness/evaluatorImpl.ts +++ b/src/harness/evaluatorImpl.ts @@ -33,8 +33,14 @@ for (const symbolName of symbolNames) { } } -export function evaluateTypeScript(source: string | { files: vfs.FileSet; rootFiles: string[]; main: string; }, options?: ts.CompilerOptions, globals?: Record) { - if (typeof source === "string") source = { files: { [sourceFile]: source }, rootFiles: [sourceFile], main: sourceFile }; +export function evaluateTypeScript( + source: string | { files: vfs.FileSet; rootFiles: string[]; main: string; }, + options?: ts.CompilerOptions, + globals?: Record, +) { + if (typeof source === "string") { + source = { files: { [sourceFile]: source }, rootFiles: [sourceFile], main: sourceFile }; + } const fs = vfs.createFromFileSystem(Harness.IO, /*ignoreCase*/ false, { files: source.files }); const compilerOptions: ts.CompilerOptions = { target: ts.ScriptTarget.ES5, @@ -68,7 +74,11 @@ export function evaluateJavaScript(sourceText: string, globals?: Record): Loader { +function getLoader( + compilerOptions: ts.CompilerOptions, + fs: vfs.FileSystem, + globals: Record, +): Loader { const moduleKind = ts.getEmitModuleKind(compilerOptions); switch (moduleKind) { case ts.ModuleKind.UMD: @@ -189,10 +199,27 @@ class CommonJsLoader extends Loader { } const base = vpath.dirname(file); const localRequire = (id: string) => this.import(id, base); - const evaluateText = `(function (module, exports, require, __dirname, __filename, ${globalNames.join(", ")}) { ${text}\n})`; + const evaluateText = `(function (module, exports, require, __dirname, __filename, ${ + globalNames.join(", ") + }) { ${text}\n})`; // eslint-disable-next-line no-eval - const evaluateThunk = (void 0, eval)(evaluateText) as (module: any, exports: any, require: (id: string) => any, dirname: string, filename: string, ...globalArgs: any[]) => void; - evaluateThunk.call(this.globals, module, module.exports, localRequire, vpath.dirname(file), file, ...globalArgs); + const evaluateThunk = (void 0, eval)(evaluateText) as ( + module: any, + exports: any, + require: (id: string) => any, + dirname: string, + filename: string, + ...globalArgs: any[] + ) => void; + evaluateThunk.call( + this.globals, + module, + module.exports, + localRequire, + vpath.dirname(file), + file, + ...globalArgs, + ); } } @@ -237,7 +264,10 @@ interface SystemModuleContext { meta: any; } -type SystemModuleRegisterCallback = (exporter: SystemModuleExporter, context: SystemModuleContext) => SystemModuleDeclaration; +type SystemModuleRegisterCallback = ( + exporter: SystemModuleExporter, + context: SystemModuleContext, +) => SystemModuleDeclaration; type SystemModuleDependencySetter = (dependency: any) => void; interface SystemModuleDeclaration { @@ -311,7 +341,11 @@ class SystemLoader extends Loader { } } - private instantiateModule(module: SystemModule, dependencies: string[], registration?: SystemModuleRegisterCallback) { + private instantiateModule( + module: SystemModule, + dependencies: string[], + registration?: SystemModuleRegisterCallback, + ) { function exporter(name: string, value: T): T; function exporter(value: T): T; function exporter(...args: [string, T] | [T]) { @@ -337,7 +371,10 @@ class SystemLoader extends Loader { throw new Error("Dynamic import not implemented."); }, meta: { - url: ts.isUrl(module.file) ? module.file : `file:///${ts.normalizeSlashes(module.file).replace(/^\//, "").split("/").map(encodeURIComponent).join("/")}`, + url: ts.isUrl(module.file) ? module.file + : `file:///${ + ts.normalizeSlashes(module.file).replace(/^\//, "").split("/").map(encodeURIComponent).join("/") + }`, }, }; @@ -517,9 +554,15 @@ type AmdDefineArgsUnnamedModuleNoDependencies = [declare: AmdModuleDeclaration]; type AmdDefineArgsUnnamedModule = [dependencies: string[], declare: AmdModuleDeclaration]; type AmdDefineArgsNamedModuleNoDependencies = [id: string, declare: AmdModuleDeclaration]; type AmdDefineArgsNamedModule = [id: string, dependencies: string[], declare: AmdModuleDeclaration]; -type AmdDefineArgs = AmdDefineArgsUnnamedModuleNoDependencies | AmdDefineArgsUnnamedModule | AmdDefineArgsNamedModuleNoDependencies | AmdDefineArgsNamedModule; - -function isAmdDefineArgsUnnamedModuleNoDependencies(args: AmdDefineArgs): args is AmdDefineArgsUnnamedModuleNoDependencies { +type AmdDefineArgs = + | AmdDefineArgsUnnamedModuleNoDependencies + | AmdDefineArgsUnnamedModule + | AmdDefineArgsNamedModuleNoDependencies + | AmdDefineArgsNamedModule; + +function isAmdDefineArgsUnnamedModuleNoDependencies( + args: AmdDefineArgs, +): args is AmdDefineArgsUnnamedModuleNoDependencies { return args.length === 1; } diff --git a/src/harness/fakesHosts.ts b/src/harness/fakesHosts.ts index 390d69d93ce67..bd14ef2d89f89 100644 --- a/src/harness/fakesHosts.ts +++ b/src/harness/fakesHosts.ts @@ -103,8 +103,24 @@ export class System implements ts.System { return result; } - public readDirectory(path: string, extensions?: readonly string[], exclude?: readonly string[], include?: readonly string[], depth?: number): string[] { - return ts.matchFiles(path, extensions, exclude, include, this.useCaseSensitiveFileNames, this.getCurrentDirectory(), depth, path => this.getAccessibleFileSystemEntries(path), path => this.realpath(path)); + public readDirectory( + path: string, + extensions?: readonly string[], + exclude?: readonly string[], + include?: readonly string[], + depth?: number, + ): string[] { + return ts.matchFiles( + path, + extensions, + exclude, + include, + this.useCaseSensitiveFileNames, + this.getCurrentDirectory(), + depth, + path => this.getAccessibleFileSystemEntries(path), + path => this.realpath(path), + ); } public getAccessibleFileSystemEntries(path: string): ts.FileSystemEntries { @@ -218,7 +234,13 @@ export class ParseConfigHost implements ts.ParseConfigHost { return this.sys.readFile(path); } - public readDirectory(path: string, extensions: string[], excludes: string[], includes: string[], depth: number): string[] { + public readDirectory( + path: string, + extensions: string[], + excludes: string[], + includes: string[], + depth: number, + ): string[] { return this.sys.readDirectory(path, extensions, excludes, includes, depth); } @@ -256,7 +278,10 @@ export class CompilerHost implements ts.CompilerHost { this.sys = sys; this.defaultLibLocation = sys.vfs.meta.get("defaultLibLocation") || ""; this._newLine = ts.getNewLineCharacter(options); - this._sourceFiles = new collections.SortedMap({ comparer: sys.vfs.stringComparer, sort: "insertion" }); + this._sourceFiles = new collections.SortedMap({ + comparer: sys.vfs.stringComparer, + sort: "insertion", + }); this._setParentNodes = setParentNodes; this._outputsMap = new collections.SortedMap(this.vfs.stringComparer); } @@ -309,7 +334,13 @@ export class CompilerHost implements ts.CompilerHost { return this.sys.getDirectories(path); } - public readDirectory(path: string, extensions?: readonly string[], exclude?: readonly string[], include?: readonly string[], depth?: number): string[] { + public readDirectory( + path: string, + extensions?: readonly string[], + exclude?: readonly string[], + include?: readonly string[], + depth?: number, + ): string[] { return this.sys.readDirectory(path, extensions, exclude, include, depth); } @@ -361,7 +392,8 @@ export class CompilerHost implements ts.CompilerHost { // reused across multiple tests. In that case, we cache the SourceFile we parse // so that it can be reused across multiple tests to avoid the cost of // repeatedly parsing the same file over and over (such as lib.d.ts). - const cacheKey = this.vfs.shadowRoot && `SourceFile[languageVersion=${languageVersion},setParentNodes=${this._setParentNodes}]`; + const cacheKey = this.vfs.shadowRoot + && `SourceFile[languageVersion=${languageVersion},setParentNodes=${this._setParentNodes}]`; if (cacheKey) { const meta = this.vfs.filemeta(canonicalFileName); const sourceFileFromMetadata = meta.get(cacheKey) as ts.SourceFile | undefined; @@ -371,7 +403,12 @@ export class CompilerHost implements ts.CompilerHost { } } - const parsed = ts.createSourceFile(fileName, content, languageVersion, this._setParentNodes || this.shouldAssertInvariants); + const parsed = ts.createSourceFile( + fileName, + content, + languageVersion, + this._setParentNodes || this.shouldAssertInvariants, + ); if (this.shouldAssertInvariants) { Utils.assertInvariants(parsed, /*parent*/ undefined); } @@ -385,11 +422,12 @@ export class CompilerHost implements ts.CompilerHost { let fs = this.vfs; while (fs.shadowRoot) { try { - const shadowRootStats = fs.shadowRoot.existsSync(canonicalFileName) ? fs.shadowRoot.statSync(canonicalFileName) : undefined!; // TODO: GH#18217 + const shadowRootStats = fs.shadowRoot.existsSync(canonicalFileName) + ? fs.shadowRoot.statSync(canonicalFileName) : undefined!; // TODO: GH#18217 if ( - shadowRootStats.dev !== stats.dev || - shadowRootStats.ino !== stats.ino || - shadowRootStats.mtimeMs !== stats.mtimeMs + shadowRootStats.dev !== stats.dev + || shadowRootStats.ino !== stats.ino + || shadowRootStats.mtimeMs !== stats.mtimeMs ) { break; } @@ -467,7 +505,9 @@ function expectedDiagnosticMessageChainToText({ message, next }: ExpectedDiagnos return text; } -function expectedDiagnosticRelatedInformationToText({ location, ...diagnosticMessage }: ExpectedDiagnosticRelatedInformation) { +function expectedDiagnosticRelatedInformationToText( + { location, ...diagnosticMessage }: ExpectedDiagnosticRelatedInformation, +) { const text = expectedDiagnosticMessageChainToText(diagnosticMessage); if (location) { const { file, start, length } = location; @@ -476,7 +516,9 @@ function expectedDiagnosticRelatedInformationToText({ location, ...diagnosticMes return text; } -function expectedErrorDiagnosticToText({ relatedInformation, ...diagnosticRelatedInformation }: ExpectedErrorDiagnostic) { +function expectedErrorDiagnosticToText( + { relatedInformation, ...diagnosticRelatedInformation }: ExpectedErrorDiagnostic, +) { let text = `${DiagnosticKind.Error}!: ${expectedDiagnosticRelatedInformationToText(diagnosticRelatedInformation)}`; if (relatedInformation) { for (const kid of relatedInformation) { @@ -488,9 +530,9 @@ function expectedErrorDiagnosticToText({ relatedInformation, ...diagnosticRelate } function expectedDiagnosticToText(errorOrStatus: ExpectedDiagnostic) { - return ts.isArray(errorOrStatus) ? - `${DiagnosticKind.Status}!: ${expectedDiagnosticMessageToText(errorOrStatus)}` : - expectedErrorDiagnosticToText(errorOrStatus); + return ts.isArray(errorOrStatus) + ? `${DiagnosticKind.Status}!: ${expectedDiagnosticMessageToText(errorOrStatus)}` + : expectedErrorDiagnosticToText(errorOrStatus); } function diagnosticMessageChainToText({ messageText, next }: ts.DiagnosticMessageChain, indent = 0) { @@ -503,15 +545,17 @@ function diagnosticMessageChainToText({ messageText, next }: ts.DiagnosticMessag } function diagnosticRelatedInformationToText({ file, start, length, messageText }: ts.DiagnosticRelatedInformation) { - const text = typeof messageText === "string" ? - messageText : - diagnosticMessageChainToText(messageText); - return file ? - `${file.fileName}(${start}:${length}):: ${text}` : - text; + const text = typeof messageText === "string" + ? messageText + : diagnosticMessageChainToText(messageText); + return file + ? `${file.fileName}(${start}:${length}):: ${text}` + : text; } -function diagnosticToText({ kind, diagnostic: { relatedInformation, ...diagnosticRelatedInformation } }: SolutionBuilderDiagnostic) { +function diagnosticToText( + { kind, diagnostic: { relatedInformation, ...diagnosticRelatedInformation } }: SolutionBuilderDiagnostic, +) { let text = `${kind}!: ${diagnosticRelatedInformationToText(diagnosticRelatedInformation)}`; if (relatedInformation) { for (const kid of relatedInformation) { @@ -558,12 +602,23 @@ export function patchHostForBuildInfoWrite(sys: T, version: export class SolutionBuilderHost extends CompilerHost implements ts.SolutionBuilderHost { createProgram: ts.CreateProgram; - private constructor(sys: System | vfs.FileSystem, options?: ts.CompilerOptions, setParentNodes?: boolean, createProgram?: ts.CreateProgram) { + private constructor( + sys: System | vfs.FileSystem, + options?: ts.CompilerOptions, + setParentNodes?: boolean, + createProgram?: ts.CreateProgram, + ) { super(sys, options, setParentNodes); - this.createProgram = createProgram || ts.createEmitAndSemanticDiagnosticsBuilderProgram as unknown as ts.CreateProgram; + this.createProgram = createProgram + || ts.createEmitAndSemanticDiagnosticsBuilderProgram as unknown as ts.CreateProgram; } - static create(sys: System | vfs.FileSystem, options?: ts.CompilerOptions, setParentNodes?: boolean, createProgram?: ts.CreateProgram) { + static create( + sys: System | vfs.FileSystem, + options?: ts.CompilerOptions, + setParentNodes?: boolean, + createProgram?: ts.CreateProgram, + ) { const host = new SolutionBuilderHost(sys, options, setParentNodes, createProgram); patchHostForBuildInfoReadWrite(host.sys); return host; diff --git a/src/harness/findUpDir.ts b/src/harness/findUpDir.ts index 4cbd0f8638827..bee3c14cce20e 100644 --- a/src/harness/findUpDir.ts +++ b/src/harness/findUpDir.ts @@ -21,4 +21,5 @@ export function findUpFile(name: string): string { } } -export const findUpRoot: { (): string; cached?: string; } = () => findUpRoot.cached ||= dirname(findUpFile("Herebyfile.mjs")); +export const findUpRoot: { (): string; cached?: string; } = () => + findUpRoot.cached ||= dirname(findUpFile("Herebyfile.mjs")); diff --git a/src/harness/fourslashImpl.ts b/src/harness/fourslashImpl.ts index 9191eb90aa858..7e974d5ec48fb 100644 --- a/src/harness/fourslashImpl.ts +++ b/src/harness/fourslashImpl.ts @@ -93,10 +93,20 @@ const enum MetadataOptionNames { } // List of allowed metadata names -const fileMetadataNames = [MetadataOptionNames.fileName, MetadataOptionNames.emitThisFile, MetadataOptionNames.resolveReference, MetadataOptionNames.symlink]; - -function convertGlobalOptionsToCompilerOptions(globalOptions: Harness.TestCaseParser.CompilerSettings): ts.CompilerOptions { - const settings: ts.CompilerOptions = { target: ts.ScriptTarget.ES5, newLine: ts.NewLineKind.CarriageReturnLineFeed }; +const fileMetadataNames = [ + MetadataOptionNames.fileName, + MetadataOptionNames.emitThisFile, + MetadataOptionNames.resolveReference, + MetadataOptionNames.symlink, +]; + +function convertGlobalOptionsToCompilerOptions( + globalOptions: Harness.TestCaseParser.CompilerSettings, +): ts.CompilerOptions { + const settings: ts.CompilerOptions = { + target: ts.ScriptTarget.ES5, + newLine: ts.NewLineKind.CarriageReturnLineFeed, + }; Harness.Compiler.setCompilerOptionsFromHarnessSetting(globalOptions, settings); return settings; } @@ -105,7 +115,11 @@ function isMarker(x: Marker | Range): x is Marker { return (x as Marker).position !== undefined; } -function convertDocumentSpanToString(span: T, prefix?: string, ignoredProperties?: readonly string[]) { +function convertDocumentSpanToString( + span: T, + prefix?: string, + ignoredProperties?: readonly string[], +) { let text = prefix || ""; for (const p in span) { if (p === "textSpan" || p === "fileName" || p === "contextSpan") continue; @@ -186,7 +200,9 @@ export function verifyOperationIsCancelled(f: () => void) { throw new Error("Operation should be cancelled"); } -export function ignoreInterpolations(diagnostic: string | ts.DiagnosticMessage): FourSlashInterface.DiagnosticIgnoredInterpolations { +export function ignoreInterpolations( + diagnostic: string | ts.DiagnosticMessage, +): FourSlashInterface.DiagnosticIgnoredInterpolations { return { template: typeof diagnostic === "string" ? diagnostic : diagnostic.message }; } @@ -263,14 +279,26 @@ export class TestState { } } - private getLanguageServiceAdapter(testType: FourSlashTestType, cancellationToken: TestCancellationToken, compilationOptions: ts.CompilerOptions): Harness.LanguageService.LanguageServiceAdapter { + private getLanguageServiceAdapter( + testType: FourSlashTestType, + cancellationToken: TestCancellationToken, + compilationOptions: ts.CompilerOptions, + ): Harness.LanguageService.LanguageServiceAdapter { switch (testType) { case FourSlashTestType.Native: return new Harness.LanguageService.NativeLanguageServiceAdapter(cancellationToken, compilationOptions); case FourSlashTestType.Shims: - return new Harness.LanguageService.ShimLanguageServiceAdapter(/*preprocessToResolve*/ false, cancellationToken, compilationOptions); + return new Harness.LanguageService.ShimLanguageServiceAdapter( + /*preprocessToResolve*/ false, + cancellationToken, + compilationOptions, + ); case FourSlashTestType.ShimsWithPreprocess: - return new Harness.LanguageService.ShimLanguageServiceAdapter(/*preprocessToResolve*/ true, cancellationToken, compilationOptions); + return new Harness.LanguageService.ShimLanguageServiceAdapter( + /*preprocessToResolve*/ true, + cancellationToken, + compilationOptions, + ); case FourSlashTestType.Server: return new Harness.LanguageService.ServerLanguageServiceAdapter(cancellationToken, compilationOptions); default: @@ -278,7 +306,12 @@ export class TestState { } } - constructor(private originalInputFileName: string, private basePath: string, private testType: FourSlashTestType, public testData: FourSlashData) { + constructor( + private originalInputFileName: string, + private basePath: string, + private testType: FourSlashTestType, + public testData: FourSlashData, + ) { // Create a new Services Adapter this.cancellationToken = new TestCancellationToken(); let compilationOptions = convertGlobalOptionsToCompilerOptions(this.testData.globalOptions); @@ -300,7 +333,11 @@ export class TestState { // Extend our existing compiler options so that we can also support tsconfig only options if (configJson.config.compilerOptions) { const baseDirectory = ts.normalizePath(ts.getDirectoryPath(file.fileName)); - const tsConfig = ts.convertCompilerOptionsFromJson(configJson.config.compilerOptions, baseDirectory, file.fileName); + const tsConfig = ts.convertCompilerOptionsFromJson( + configJson.config.compilerOptions, + baseDirectory, + file.fileName, + ); if (!tsConfig.errors || !tsConfig.errors.length) { compilationOptions = ts.extend(tsConfig.options, compilationOptions); @@ -314,7 +351,9 @@ export class TestState { } else if (startResolveFileRef) { // If entry point for resolving file references is already specified, report duplication error - throw new Error("There exists a Fourslash file which has resolveReference flag specified; remove duplicated resolveReference flag"); + throw new Error( + "There exists a Fourslash file which has resolveReference flag specified; remove duplicated resolveReference flag", + ); } } @@ -329,26 +368,48 @@ export class TestState { const fs = new vfs.FileSystem(/*ignoreCase*/ true, { cwd: baseDir, files }); const host = new fakes.ParseConfigHost(fs); const jsonSourceFile = ts.parseJsonText(configFileName, this.inputFiles.get(configFileName)!); - configParseResult = ts.parseJsonSourceFileConfigFileContent(jsonSourceFile, host, baseDir, compilationOptions, configFileName); + configParseResult = ts.parseJsonSourceFileConfigFileContent( + jsonSourceFile, + host, + baseDir, + compilationOptions, + configFileName, + ); compilationOptions = configParseResult.options; } if (compilationOptions.typeRoots) { - compilationOptions.typeRoots = compilationOptions.typeRoots.map(p => ts.getNormalizedAbsolutePath(p, this.basePath)); + compilationOptions.typeRoots = compilationOptions.typeRoots.map(p => + ts.getNormalizedAbsolutePath(p, this.basePath) + ); } - const languageServiceAdapter = this.getLanguageServiceAdapter(testType, this.cancellationToken, compilationOptions); + const languageServiceAdapter = this.getLanguageServiceAdapter( + testType, + this.cancellationToken, + compilationOptions, + ); this.languageServiceAdapterHost = languageServiceAdapter.getHost(); this.languageService = memoWrap(languageServiceAdapter.getLanguageService(), this); // Wrap the LS to cache some expensive operations certain tests call repeatedly if (this.testType === FourSlashTestType.Server) { - this.assertTextConsistent = fileName => (languageServiceAdapter as Harness.LanguageService.ServerLanguageServiceAdapter).assertTextConsistent(fileName); + this.assertTextConsistent = fileName => + (languageServiceAdapter as Harness.LanguageService.ServerLanguageServiceAdapter).assertTextConsistent( + fileName, + ); } if (startResolveFileRef) { // Add the entry-point file itself into the languageServiceShimHost - this.languageServiceAdapterHost.addScript(startResolveFileRef.fileName, startResolveFileRef.content, /*isRootFile*/ true); + this.languageServiceAdapterHost.addScript( + startResolveFileRef.fileName, + startResolveFileRef.content, + /*isRootFile*/ true, + ); - const resolvedResult = languageServiceAdapter.getPreProcessedFileInfo(startResolveFileRef.fileName, startResolveFileRef.content); + const resolvedResult = languageServiceAdapter.getPreProcessedFileInfo( + startResolveFileRef.fileName, + startResolveFileRef.content, + ); const referencedFiles: ts.FileReference[] = resolvedResult.referencedFiles; const importedFiles: ts.FileReference[] = resolvedResult.importedFiles; @@ -370,7 +431,11 @@ export class TestState { // Check if no-default-lib flag is false and if so add default library if (!resolvedResult.isLibFile) { - this.languageServiceAdapterHost.addScript(Harness.Compiler.defaultLibFileName, Harness.Compiler.getDefaultLibrarySourceFile()!.text, /*isRootFile*/ false); + this.languageServiceAdapterHost.addScript( + Harness.Compiler.defaultLibFileName, + Harness.Compiler.getDefaultLibrarySourceFile()!.text, + /*isRootFile*/ false, + ); compilationOptions.lib?.forEach(fileName => { const libFile = Harness.Compiler.getDefaultLibrarySourceFile(fileName); @@ -386,9 +451,10 @@ export class TestState { this.inputFiles.forEach((file, fileName) => { if (!Harness.isDefaultLibraryFile(fileName)) { // all files if config file not specified, otherwise root files from the config and typings cache files are root files - const isRootFile = !configParseResult || - ts.contains(configParseResult.fileNames, fileName) || - (ts.isDeclarationFileName(fileName) && ts.containsPath("/Library/Caches/typescript", fileName)); + const isRootFile = !configParseResult + || ts.contains(configParseResult.fileNames, fileName) + || (ts.isDeclarationFileName(fileName) + && ts.containsPath("/Library/Caches/typescript", fileName)); this.languageServiceAdapterHost.addScript(fileName, file, isRootFile); } }); @@ -445,7 +511,14 @@ export class TestState { continue; } const memo = Utils.memoize( - (_version: number, _active: string, _caret: number, _selectEnd: number, _marker: string | undefined, ...args: any[]) => (ls[key] as (...args: any[]) => any)(...args), + ( + _version: number, + _active: string, + _caret: number, + _selectEnd: number, + _marker: string | undefined, + ...args: any[] + ) => (ls[key] as (...args: any[]) => any)(...args), (...args) => args.map(a => a && typeof a === "object" ? JSON.stringify(a) : a).join("|,|"), ); proxy[key] = (...args: any[]) => @@ -487,9 +560,9 @@ export class TestState { } private goToMarkerOrNameOrRange(markerOrRange: MarkerOrNameOrRange) { - return ts.isString(markerOrRange) || isMarker(markerOrRange) ? - this.goToMarker(markerOrRange) : - this.goToRangeStart(markerOrRange); + return ts.isString(markerOrRange) || isMarker(markerOrRange) + ? this.goToMarker(markerOrRange) + : this.goToRangeStart(markerOrRange); } public goToEachMarker(markers: readonly Marker[], action: (marker: Marker, index: number) => void) { @@ -520,7 +593,10 @@ export class TestState { public goToPosition(positionOrLineAndCharacter: number | ts.LineAndCharacter) { const pos = typeof positionOrLineAndCharacter === "number" ? positionOrLineAndCharacter - : this.languageServiceAdapterHost.lineAndCharacterToPosition(this.activeFile.fileName, positionOrLineAndCharacter); + : this.languageServiceAdapterHost.lineAndCharacterToPosition( + this.activeFile.fileName, + positionOrLineAndCharacter, + ); this.currentCaretPosition = pos; this.selectionEnd = -1; } @@ -547,14 +623,20 @@ export class TestState { } public selectLine(index: number) { - const lineStart = this.languageServiceAdapterHost.lineAndCharacterToPosition(this.activeFile.fileName, { line: index, character: 0 }); + const lineStart = this.languageServiceAdapterHost.lineAndCharacterToPosition(this.activeFile.fileName, { + line: index, + character: 0, + }); const lineEnd = lineStart + this.getLineContent(index).length; this.selectRange({ fileName: this.activeFile.fileName, pos: lineStart, end: lineEnd }); } public moveCaretRight(count = 1) { this.currentCaretPosition += count; - this.currentCaretPosition = Math.min(this.currentCaretPosition, this.getFileContent(this.activeFile.fileName).length); + this.currentCaretPosition = Math.min( + this.currentCaretPosition, + this.getFileContent(this.activeFile.fileName).length, + ); this.selectionEnd = -1; } @@ -570,18 +652,27 @@ export class TestState { public verifyErrorExistsBetweenMarkers(startMarkerName: string, endMarkerName: string, shouldExist: boolean) { const startMarker = this.getMarkerByName(startMarkerName); const endMarker = this.getMarkerByName(endMarkerName); - const predicate = (errorMinChar: number, errorLimChar: number, startPos: number, endPos: number | undefined) => ((errorMinChar === startPos) && (errorLimChar === endPos)) ? true : false; + const predicate = (errorMinChar: number, errorLimChar: number, startPos: number, endPos: number | undefined) => + ((errorMinChar === startPos) && (errorLimChar === endPos)) ? true : false; const exists = this.anyErrorInRange(predicate, startMarker, endMarker); if (exists !== shouldExist) { this.printErrorLog(shouldExist, this.getAllDiagnostics()); - throw new Error(`${shouldExist ? "Expected" : "Did not expect"} failure between markers: '${startMarkerName}', '${endMarkerName}'`); + throw new Error( + `${ + shouldExist ? "Expected" : "Did not expect" + } failure between markers: '${startMarkerName}', '${endMarkerName}'`, + ); } } public verifyOrganizeImports(newContent: string, mode?: ts.OrganizeImportsMode, preferences?: ts.UserPreferences) { - const changes = this.languageService.organizeImports({ fileName: this.activeFile.fileName, type: "file", mode }, this.formatCodeSettings, preferences); + const changes = this.languageService.organizeImports( + { fileName: this.activeFile.fileName, type: "file", mode }, + this.formatCodeSettings, + preferences, + ); this.applyChanges(changes); this.verifyFileContent(this.activeFile.fileName, newContent); } @@ -591,7 +682,8 @@ export class TestState { } private messageAtLastKnownMarker(message: string) { - const locationDescription = this.lastKnownMarker !== undefined ? this.lastKnownMarker : this.getLineColStringAtPosition(this.currentCaretPosition); + const locationDescription = this.lastKnownMarker !== undefined ? this.lastKnownMarker + : this.getLineColStringAtPosition(this.currentCaretPosition); return `At marker '${locationDescription}': ${message}`; } @@ -623,13 +715,20 @@ export class TestState { public verifyErrorExistsAfterMarker(markerName: string, shouldExist: boolean, after: boolean) { const marker: Marker = this.getMarkerByName(markerName); - let predicate: (errorMinChar: number, errorLimChar: number, startPos: number, endPos: number | undefined) => boolean; + let predicate: ( + errorMinChar: number, + errorLimChar: number, + startPos: number, + endPos: number | undefined, + ) => boolean; if (after) { - predicate = (errorMinChar: number, errorLimChar: number, startPos: number) => ((errorMinChar >= startPos) && (errorLimChar >= startPos)) ? true : false; + predicate = (errorMinChar: number, errorLimChar: number, startPos: number) => + ((errorMinChar >= startPos) && (errorLimChar >= startPos)) ? true : false; } else { - predicate = (errorMinChar: number, errorLimChar: number, startPos: number) => ((errorMinChar <= startPos) && (errorLimChar <= startPos)) ? true : false; + predicate = (errorMinChar: number, errorLimChar: number, startPos: number) => + ((errorMinChar <= startPos) && (errorLimChar <= startPos)) ? true : false; } const exists = this.anyErrorInRange(predicate, marker); @@ -641,8 +740,24 @@ export class TestState { } } - private anyErrorInRange(predicate: (errorMinChar: number, errorLimChar: number, startPos: number, endPos: number | undefined) => boolean, startMarker: Marker, endMarker?: Marker): boolean { - return this.getDiagnostics(startMarker.fileName).some(({ start, length }) => predicate(start!, start! + length!, startMarker.position, endMarker === undefined ? undefined : endMarker.position)); // TODO: GH#18217 + private anyErrorInRange( + predicate: ( + errorMinChar: number, + errorLimChar: number, + startPos: number, + endPos: number | undefined, + ) => boolean, + startMarker: Marker, + endMarker?: Marker, + ): boolean { + return this.getDiagnostics(startMarker.fileName).some(({ start, length }) => + predicate( + start!, + start! + length!, + startMarker.position, + endMarker === undefined ? undefined : endMarker.position, + ) + ); // TODO: GH#18217 } private printErrorLog(expectErrors: boolean, errors: readonly ts.Diagnostic[]): void { @@ -655,15 +770,17 @@ export class TestState { for (const { start, length, messageText, file } of errors) { Harness.IO.log( - " " + this.formatRange(file, start!, length!) + // TODO: GH#18217 - ", message: " + ts.flattenDiagnosticMessageText(messageText, Harness.IO.newLine()) + "\n", + " " + this.formatRange(file, start!, length!) // TODO: GH#18217 + + ", message: " + ts.flattenDiagnosticMessageText(messageText, Harness.IO.newLine()) + "\n", ); } } private formatRange(file: ts.SourceFile | undefined, start: number, length: number) { if (file) { - return `from: ${this.formatLineAndCharacterOfPosition(file, start)}, to: ${this.formatLineAndCharacterOfPosition(file, start + length)}`; + return `from: ${this.formatLineAndCharacterOfPosition(file, start)}, to: ${ + this.formatLineAndCharacterOfPosition(file, start + length) + }`; } return "global"; } @@ -689,14 +806,17 @@ export class TestState { !ts.isAnySupportedFileExtension(fileName) || Harness.getConfigNameFromFileName(fileName) // Can't get a Program in Server tests - || this.testType !== FourSlashTestType.Server && !ts.getAllowJSCompilerOption(this.getProgram().getCompilerOptions()) && !ts.resolutionExtensionIsTSOrJson(ts.extensionFromPath(fileName)) + || this.testType !== FourSlashTestType.Server + && !ts.getAllowJSCompilerOption(this.getProgram().getCompilerOptions()) + && !ts.resolutionExtensionIsTSOrJson(ts.extensionFromPath(fileName)) || ts.getBaseFileName(fileName) === "package.json" ) return; const errors = this.getDiagnostics(fileName).filter(e => e.category !== ts.DiagnosticCategory.Suggestion); if (errors.length) { this.printErrorLog(/*expectErrors*/ false, errors); const error = errors[0]; - const message = typeof error.messageText === "string" ? error.messageText : error.messageText.messageText; + const message = typeof error.messageText === "string" ? error.messageText + : error.messageText.messageText; this.raiseError(`Found an error: ${this.formatPosition(error.file!, error.start!)}: ${message}`); } }); @@ -707,10 +827,10 @@ export class TestState { const hasMatchingError = ts.some( this.getDiagnostics(range.fileName), ({ code, messageText, start, length }) => - code === code && - (!expectedMessage || expectedMessage === messageText) && - ts.isNumber(start) && ts.isNumber(length) && - ts.textSpansEqual(span, { start, length }), + code === code + && (!expectedMessage || expectedMessage === messageText) + && ts.isNumber(start) && ts.isNumber(length) + && ts.textSpansEqual(span, { start, length }), ); if (!hasMatchingError) { @@ -724,7 +844,8 @@ export class TestState { if (actual !== expected) { this.printErrorLog(/*expectErrors*/ false, errors); - const errorMsg = "Actual number of errors (" + actual + ") does not match expected number (" + expected + ")"; + const errorMsg = "Actual number of errors (" + actual + ") does not match expected number (" + expected + + ")"; Harness.IO.log(errorMsg); this.raiseError(errorMsg); } @@ -750,13 +871,19 @@ export class TestState { return this.languageService.getDefinitionAndBoundSpan(this.activeFile.fileName, this.currentCaretPosition)!; } - private renderMarkers(markers: { text: string; fileName: string; position: number; }[], useTerminalBoldSequence = true) { + private renderMarkers( + markers: { text: string; fileName: string; position: number; }[], + useTerminalBoldSequence = true, + ) { const filesToDisplay = ts.deduplicate(markers.map(m => m.fileName), ts.equateValues); return filesToDisplay.map(fileName => { - const markersToRender = markers.filter(m => m.fileName === fileName).sort((a, b) => b.position - a.position); + const markersToRender = markers.filter(m => m.fileName === fileName).sort((a, b) => + b.position - a.position + ); let fileContent = this.tryGetFileContent(fileName) || ""; for (const marker of markersToRender) { - fileContent = fileContent.slice(0, marker.position) + bold(`/*${marker.text}*/`) + fileContent.slice(marker.position); + fileContent = fileContent.slice(0, marker.position) + bold(`/*${marker.text}*/`) + + fileContent.slice(marker.position); } return `// @Filename: ${fileName}\n${fileContent}`; }).join("\n\n"); @@ -769,7 +896,11 @@ export class TestState { private baselineGoToDefs( markerName: string, markerOrRange: MarkerOrNameOrRange, - getDefs: () => readonly ts.DefinitionInfo[] | readonly ts.ImplementationLocation[] | ts.DefinitionInfoAndBoundSpan | undefined, + getDefs: () => + | readonly ts.DefinitionInfo[] + | readonly ts.ImplementationLocation[] + | ts.DefinitionInfoAndBoundSpan + | undefined, ) { this.goToMarkerOrNameOrRange(markerOrRange); const defs = getDefs(); @@ -784,14 +915,15 @@ export class TestState { markerInfo: { markerOrRange, markerName }, documentSpanId: defIdMap.size ? def => `defId: ${defIdMap.get(def)}` : undefined, skipDocumentSpanDetails: true, - additionalSpan: defs && !ts.isArray(defs) ? { fileName: this.activeFile.fileName, textSpan: defs.textSpan } : undefined, + additionalSpan: defs && !ts.isArray(defs) + ? { fileName: this.activeFile.fileName, textSpan: defs.textSpan } : undefined, }, ); if (definitions?.length) { baseline += "\n\n"; baseline += indentJsonBaseline( - "// === Details ===\n" + - JSON.stringify( + "// === Details ===\n" + + JSON.stringify( definitions.map(def => ({ defId: defIdMap.get(def), ...def, @@ -827,7 +959,10 @@ export class TestState { }); } - public baselineInlayHints(span: ts.TextSpan = { start: 0, length: this.activeFile.content.length }, preferences?: ts.UserPreferences): void { + public baselineInlayHints( + span: ts.TextSpan = { start: 0, length: this.activeFile.content.length }, + preferences?: ts.UserPreferences, + ): void { interface HasPosition { position: number; } @@ -840,7 +975,10 @@ export class TestState { const hints = this.languageService.provideInlayHints(fileName, span, preferences); const annotations = ts.map(hints.sort(sortHints), hint => { const span = { start: hint.position, length: hint.text.length }; - const { character, line } = this.languageServiceAdapterHost.positionToLineAndCharacter(fileName, span.start); + const { character, line } = this.languageServiceAdapterHost.positionToLineAndCharacter( + fileName, + span.start, + ); const underline = " ".repeat(character) + "^"; let annotation = this.getFileContent(fileName).split(/\r?\n/)[line]; annotation += "\n" + underline + "\n" + JSON.stringify(hint, undefined, " "); @@ -877,20 +1015,35 @@ export class TestState { private verifyCompletionsWorker(options: FourSlashInterface.VerifyCompletionsOptions) { const preferences = options.preferences; - const actualCompletions = this.getCompletionListAtCaret({ ...preferences, triggerCharacter: options.triggerCharacter })!; + const actualCompletions = this.getCompletionListAtCaret({ + ...preferences, + triggerCharacter: options.triggerCharacter, + })!; if (!actualCompletions) { - if (ts.hasProperty(options, "exact") && (options.exact === undefined || ts.isArray(options.exact) && !options.exact.length)) { + if ( + ts.hasProperty(options, "exact") + && (options.exact === undefined || ts.isArray(options.exact) && !options.exact.length) + ) { return; } this.raiseError(`No completions at position '${this.currentCaretPosition}'.`); } if (actualCompletions.isNewIdentifierLocation !== (options.isNewIdentifierLocation || false)) { - this.raiseError(`Expected 'isNewIdentifierLocation' to be ${options.isNewIdentifierLocation || false}, got ${actualCompletions.isNewIdentifierLocation}`); + this.raiseError( + `Expected 'isNewIdentifierLocation' to be ${ + options.isNewIdentifierLocation || false + }, got ${actualCompletions.isNewIdentifierLocation}`, + ); } - if (ts.hasProperty(options, "isGlobalCompletion") && actualCompletions.isGlobalCompletion !== options.isGlobalCompletion) { - this.raiseError(`Expected 'isGlobalCompletion to be ${options.isGlobalCompletion}, got ${actualCompletions.isGlobalCompletion}`); + if ( + ts.hasProperty(options, "isGlobalCompletion") + && actualCompletions.isGlobalCompletion !== options.isGlobalCompletion + ) { + this.raiseError( + `Expected 'isGlobalCompletion to be ${options.isGlobalCompletion}, got ${actualCompletions.isGlobalCompletion}`, + ); } if (ts.hasProperty(options, "optionalReplacementSpan")) { @@ -911,11 +1064,11 @@ export class TestState { else { if ( entries.some(e => - e.source === entry.source && - e.data?.exportName === entry.data?.exportName && - e.data?.fileName === entry.data?.fileName && - e.data?.moduleSpecifier === entry.data?.moduleSpecifier && - e.data?.ambientModuleName === entry.data?.ambientModuleName + e.source === entry.source + && e.data?.exportName === entry.data?.exportName + && e.data?.fileName === entry.data?.fileName + && e.data?.moduleSpecifier === entry.data?.moduleSpecifier + && e.data?.ambientModuleName === entry.data?.ambientModuleName ) ) { this.raiseError(`Duplicate completions for ${entry.name}`); @@ -934,7 +1087,10 @@ export class TestState { } if (ts.hasProperty(options, "exact")) { - ts.Debug.assert(!ts.hasProperty(options, "includes") && !ts.hasProperty(options, "excludes") && !ts.hasProperty(options, "unsorted")); + ts.Debug.assert( + !ts.hasProperty(options, "includes") && !ts.hasProperty(options, "excludes") + && !ts.hasProperty(options, "unsorted"), + ); if (options.exact === undefined) throw this.raiseError("Expected no completions"); this.verifyCompletionsAreExactly(actualCompletions.entries, options.exact, options.marker); } @@ -944,7 +1100,9 @@ export class TestState { const name = typeof expectedEntry === "string" ? expectedEntry : expectedEntry.name; const found = nameToEntries.get(name); if (!found) throw this.raiseError(`Unsorted: completion '${name}' not found.`); - if (!found.length) throw this.raiseError(`Unsorted: no completions with name '${name}' remain unmatched.`); + if (!found.length) { + throw this.raiseError(`Unsorted: no completions with name '${name}' remain unmatched.`); + } this.verifyCompletionEntry(found.shift()!, expectedEntry); } if (actualCompletions.entries.length !== options.unsorted.length) { @@ -961,7 +1119,9 @@ export class TestState { const name = typeof include === "string" ? include : include.name; const found = nameToEntries.get(name); if (!found) throw this.raiseError(`Includes: completion '${name}' not found.`); - if (!found.length) throw this.raiseError(`Includes: no completions with name '${name}' remain unmatched.`); + if (!found.length) { + throw this.raiseError(`Includes: no completions with name '${name}' remain unmatched.`); + } this.verifyCompletionEntry(found.shift()!, include); } } @@ -986,12 +1146,22 @@ export class TestState { const { name, source, description, newFileContent, newRangeContent } = options; const data = nameAndSourceToData.get(`${options.name}|${options.source}`); if (data === false) { - this.raiseError(`Multiple completion entries found for '${options.name}' from '${options.source}'. This API cannot be used. Use 'verify.applyCodeActionFromCompletion' instead.`); + this.raiseError( + `Multiple completion entries found for '${options.name}' from '${options.source}'. This API cannot be used. Use 'verify.applyCodeActionFromCompletion' instead.`, + ); } if (data === undefined) { this.raiseError(`No completion entry found for '${options.name}' from '${options.source}'`); } - this.applyCodeActionFromCompletion(/*markerName*/ undefined, { name, source, data, description, newFileContent, newRangeContent, preferences }); + this.applyCodeActionFromCompletion(/*markerName*/ undefined, { + name, + source, + data, + description, + newFileContent, + newRangeContent, + preferences, + }); }, }; } @@ -1000,87 +1170,182 @@ export class TestState { expected = typeof expected === "string" ? { name: expected } : expected; if (actual.insertText !== expected.insertText) { - this.raiseError(`At entry ${actual.name}: Completion insert text did not match: ${showTextDiff(expected.insertText || "", actual.insertText || "")}`); + this.raiseError( + `At entry ${actual.name}: Completion insert text did not match: ${ + showTextDiff(expected.insertText || "", actual.insertText || "") + }`, + ); } - const convertedReplacementSpan = expected.replacementSpan && ts.createTextSpanFromRange(expected.replacementSpan); + const convertedReplacementSpan = expected.replacementSpan + && ts.createTextSpanFromRange(expected.replacementSpan); if (convertedReplacementSpan) { try { assert.deepEqual(actual.replacementSpan, convertedReplacementSpan); } catch { - this.raiseError(`At entry ${actual.name}: Expected completion replacementSpan to be ${stringify(convertedReplacementSpan)}, got ${stringify(actual.replacementSpan)}`); + this.raiseError( + `At entry ${actual.name}: Expected completion replacementSpan to be ${ + stringify(convertedReplacementSpan) + }, got ${stringify(actual.replacementSpan)}`, + ); } } else if (ts.hasProperty(expected, "replacementSpan")) { // Expected `replacementSpan` is explicitly set as `undefined`. - assert.equal(actual.replacementSpan, undefined, `At entry ${actual.name}: Expected 'replacementSpan' properties to match`); + assert.equal( + actual.replacementSpan, + undefined, + `At entry ${actual.name}: Expected 'replacementSpan' properties to match`, + ); } if (expected.kind !== undefined || expected.kindModifiers !== undefined) { - assert.equal(actual.kind, expected.kind, `At entry ${actual.name}: Expected 'kind' for ${actual.name} to match`); - assert.equal(actual.kindModifiers, expected.kindModifiers || "", `At entry ${actual.name}: Expected 'kindModifiers' for ${actual.name} to match`); + assert.equal( + actual.kind, + expected.kind, + `At entry ${actual.name}: Expected 'kind' for ${actual.name} to match`, + ); + assert.equal( + actual.kindModifiers, + expected.kindModifiers || "", + `At entry ${actual.name}: Expected 'kindModifiers' for ${actual.name} to match`, + ); } if (expected.isFromUncheckedFile !== undefined) { - assert.equal(actual.isFromUncheckedFile, expected.isFromUncheckedFile, `At entry ${actual.name}: Expected 'isFromUncheckedFile' properties to match`); + assert.equal( + actual.isFromUncheckedFile, + expected.isFromUncheckedFile, + `At entry ${actual.name}: Expected 'isFromUncheckedFile' properties to match`, + ); } if (expected.isPackageJsonImport !== undefined) { - assert.equal(actual.isPackageJsonImport, expected.isPackageJsonImport, `At entry ${actual.name}: Expected 'isPackageJsonImport' properties to match`); + assert.equal( + actual.isPackageJsonImport, + expected.isPackageJsonImport, + `At entry ${actual.name}: Expected 'isPackageJsonImport' properties to match`, + ); } assert.equal( actual.filterText, expected.filterText, - `At entry ${actual.name}: Completion 'filterText' not match: ${showTextDiff(expected.filterText || "", actual.filterText || "")}`, + `At entry ${actual.name}: Completion 'filterText' not match: ${ + showTextDiff(expected.filterText || "", actual.filterText || "") + }`, ); assert.equal( actual.labelDetails?.description, expected.labelDetails?.description, - `At entry ${actual.name}: Completion 'labelDetails.description' did not match: ${showTextDiff(expected.labelDetails?.description || "", actual.labelDetails?.description || "")}`, + `At entry ${actual.name}: Completion 'labelDetails.description' did not match: ${ + showTextDiff(expected.labelDetails?.description || "", actual.labelDetails?.description || "") + }`, ); assert.equal( actual.labelDetails?.detail, expected.labelDetails?.detail, - `At entry ${actual.name}: Completion 'labelDetails.detail' did not match: ${showTextDiff(expected.labelDetails?.detail || "", actual.labelDetails?.detail || "")}`, + `At entry ${actual.name}: Completion 'labelDetails.detail' did not match: ${ + showTextDiff(expected.labelDetails?.detail || "", actual.labelDetails?.detail || "") + }`, + ); + assert.equal( + actual.hasAction, + expected.hasAction, + `At entry ${actual.name}: Expected 'hasAction' properties to match`, + ); + assert.equal( + actual.isRecommended, + expected.isRecommended, + `At entry ${actual.name}: Expected 'isRecommended' properties to match'`, + ); + assert.equal( + actual.isSnippet, + expected.isSnippet, + `At entry ${actual.name}: Expected 'isSnippet' properties to match`, ); - assert.equal(actual.hasAction, expected.hasAction, `At entry ${actual.name}: Expected 'hasAction' properties to match`); - assert.equal(actual.isRecommended, expected.isRecommended, `At entry ${actual.name}: Expected 'isRecommended' properties to match'`); - assert.equal(actual.isSnippet, expected.isSnippet, `At entry ${actual.name}: Expected 'isSnippet' properties to match`); assert.equal(actual.source, expected.source, `At entry ${actual.name}: Expected 'source' values to match`); - assert.equal(actual.sortText, expected.sortText || ts.Completions.SortText.LocationPriority, `At entry ${actual.name}: Expected 'sortText' properties to match`); + assert.equal( + actual.sortText, + expected.sortText || ts.Completions.SortText.LocationPriority, + `At entry ${actual.name}: Expected 'sortText' properties to match`, + ); if (expected.sourceDisplay && actual.sourceDisplay) { - assert.equal(ts.displayPartsToString(actual.sourceDisplay), expected.sourceDisplay, `At entry ${actual.name}: Expected 'sourceDisplay' properties to match`); + assert.equal( + ts.displayPartsToString(actual.sourceDisplay), + expected.sourceDisplay, + `At entry ${actual.name}: Expected 'sourceDisplay' properties to match`, + ); } if (expected.text !== undefined) { - const actualDetails = ts.Debug.checkDefined(this.getCompletionEntryDetails(actual.name, actual.source, actual.data), `No completion details available for name '${actual.name}' and source '${actual.source}'`); - assert.equal(ts.displayPartsToString(actualDetails.displayParts), expected.text, "Expected 'text' property to match 'displayParts' string"); - assert.equal(ts.displayPartsToString(actualDetails.documentation), expected.documentation || "", "Expected 'documentation' property to match 'documentation' display parts string"); + const actualDetails = ts.Debug.checkDefined( + this.getCompletionEntryDetails(actual.name, actual.source, actual.data), + `No completion details available for name '${actual.name}' and source '${actual.source}'`, + ); + assert.equal( + ts.displayPartsToString(actualDetails.displayParts), + expected.text, + "Expected 'text' property to match 'displayParts' string", + ); + assert.equal( + ts.displayPartsToString(actualDetails.documentation), + expected.documentation || "", + "Expected 'documentation' property to match 'documentation' display parts string", + ); // TODO: GH#23587 // assert.equal(actualDetails.kind, actual.kind); - assert.equal(actualDetails.kindModifiers, actual.kindModifiers, "Expected 'kindModifiers' properties to match"); - assert.equal(actualDetails.source && ts.displayPartsToString(actualDetails.source), expected.sourceDisplay, "Expected 'sourceDisplay' property to match 'source' display parts string"); + assert.equal( + actualDetails.kindModifiers, + actual.kindModifiers, + "Expected 'kindModifiers' properties to match", + ); + assert.equal( + actualDetails.source && ts.displayPartsToString(actualDetails.source), + expected.sourceDisplay, + "Expected 'sourceDisplay' property to match 'source' display parts string", + ); if (!actual.sourceDisplay) { - assert.equal(actualDetails.sourceDisplay && ts.displayPartsToString(actualDetails.sourceDisplay), expected.sourceDisplay, "Expected 'sourceDisplay' property to match 'sourceDisplay' display parts string"); + assert.equal( + actualDetails.sourceDisplay && ts.displayPartsToString(actualDetails.sourceDisplay), + expected.sourceDisplay, + "Expected 'sourceDisplay' property to match 'sourceDisplay' display parts string", + ); } assert.deepEqual(actualDetails.tags, expected.tags); } else { - assert(expected.documentation === undefined && expected.tags === undefined, "If specifying completion details, should specify 'text'"); + assert( + expected.documentation === undefined && expected.tags === undefined, + "If specifying completion details, should specify 'text'", + ); } } - private verifyCompletionsAreExactly(actual: readonly ts.CompletionEntry[], expected: ArrayOrSingle | FourSlashInterface.ExpectedExactCompletionsPlus, marker?: ArrayOrSingle) { + private verifyCompletionsAreExactly( + actual: readonly ts.CompletionEntry[], + expected: + | ArrayOrSingle + | FourSlashInterface.ExpectedExactCompletionsPlus, + marker?: ArrayOrSingle, + ) { if (!ts.isArray(expected)) { expected = [expected]; } // First pass: test that names are right. Then we'll test details. - assert.deepEqual(actual.map(a => a.name), expected.map(e => typeof e === "string" ? e : e.name), marker ? "At marker " + JSON.stringify(marker) : undefined); + assert.deepEqual( + actual.map(a => a.name), + expected.map(e => typeof e === "string" ? e : e.name), + marker ? "At marker " + JSON.stringify(marker) : undefined, + ); ts.zipWith(actual, expected, (completion, expectedCompletion, index) => { const name = typeof expectedCompletion === "string" ? expectedCompletion : expectedCompletion.name; if (completion.name !== name) { - this.raiseError(`${marker ? JSON.stringify(marker) : ""} Expected completion at index ${index} to be ${name}, got ${completion.name}`); + this.raiseError( + `${ + marker ? JSON.stringify(marker) : "" + } Expected completion at index ${index} to be ${name}, got ${completion.name}`, + ); } this.verifyCompletionEntry(completion, expectedCompletion); }); @@ -1162,7 +1427,10 @@ export class TestState { public symbolsInScope(range: Range): ts.Symbol[] { const node = this.goToAndGetNode(range); - return this.getChecker().getSymbolsInScope(node, ts.SymbolFlags.Value | ts.SymbolFlags.Type | ts.SymbolFlags.Namespace); + return this.getChecker().getSymbolsInScope( + node, + ts.SymbolFlags.Value | ts.SymbolFlags.Type | ts.SymbolFlags.Namespace, + ); } public setTypesRegistry(map: ts.MapLike): void { @@ -1202,7 +1470,9 @@ export class TestState { done = baselineArrayOrSingle(command, command.markerOrRange, worker); } if (command.rangeText !== undefined) { - toArray(command.rangeText).forEach(text => done = baselineArrayOrSingle(command, this.rangesByText().get(text)!, worker) || done); + toArray(command.rangeText).forEach(text => + done = baselineArrayOrSingle(command, this.rangesByText().get(text)!, worker) || done + ); } if (!done) { baselineArrayOrSingle(command, this.getRanges(), worker); @@ -1258,7 +1528,10 @@ export class TestState { markerOrRange, () => (this.languageService as ts.server.SessionClient) - .getSourceDefinitionAndBoundSpan(this.activeFile.fileName, this.currentCaretPosition), + .getSourceDefinitionAndBoundSpan( + this.activeFile.fileName, + this.currentCaretPosition, + ), ), ); case "goToType": @@ -1268,7 +1541,11 @@ export class TestState { this.baselineGoToDefs( "/*GOTO TYPE*/", markerOrRange, - () => this.languageService.getTypeDefinitionAtPosition(this.activeFile.fileName, this.currentCaretPosition), + () => + this.languageService.getTypeDefinitionAtPosition( + this.activeFile.fileName, + this.currentCaretPosition, + ), ), ); case "goToImplementation": @@ -1278,7 +1555,11 @@ export class TestState { this.baselineGoToDefs( "/*GOTO IMPL*/", markerOrRange, - () => this.languageService.getImplementationAtPosition(this.activeFile.fileName, this.currentCaretPosition), + () => + this.languageService.getImplementationAtPosition( + this.activeFile.fileName, + this.currentCaretPosition, + ), ), ); case "documentHighlights": @@ -1336,8 +1617,8 @@ export class TestState { if (references?.length) { baseline += "\n\n"; baseline += indentJsonBaseline( - "// === Definitions ===\n" + - this.getBaselineForDocumentSpansWithFileContents( + "// === Definitions ===\n" + + this.getBaselineForDocumentSpansWithFileContents( references.map(r => r.definition), { markerInfo, @@ -1345,9 +1626,9 @@ export class TestState { skipDocumentSpanDetails: true, skipDocumentContainingOnlyMarker: true, }, - ) + - "\n\n// === Details ===\n" + - JSON.stringify( + ) + + "\n\n// === Details ===\n" + + JSON.stringify( references.map(r => ({ defId: defIdMap.get(r.definition), ...r.definition, @@ -1393,13 +1674,13 @@ export class TestState { skipDocumentContainingOnlyMarker, additionalSpan, } = options; - const marker: Marker | undefined = markerInfo !== undefined ? - ts.isString(markerInfo.markerOrRange) ? - this.getMarkerByName(markerInfo.markerOrRange) : - isMarker(markerInfo.markerOrRange) ? - markerInfo.markerOrRange : - { fileName: markerInfo.markerOrRange.fileName, position: markerInfo.markerOrRange.pos } : - undefined; + const marker: Marker | undefined = markerInfo !== undefined + ? ts.isString(markerInfo.markerOrRange) + ? this.getMarkerByName(markerInfo.markerOrRange) + : isMarker(markerInfo.markerOrRange) + ? markerInfo.markerOrRange + : { fileName: markerInfo.markerOrRange.fileName, position: markerInfo.markerOrRange.pos } + : undefined; const fileBaselines: string[] = []; let foundMarker = false; let foundAdditionalSpan = false; @@ -1422,10 +1703,12 @@ export class TestState { else { let baseline = `// === ${group[0].fileName} ===\n// Unavailable file content:\n`; for (const span of group) { - baseline += `// textSpan: ${JSON.stringify(span.textSpan)}${span.contextSpan ? `, contextSpan: ${JSON.stringify(span.contextSpan)}` : ""}`; - const text = !skipDocumentSpanDetails ? - convertDocumentSpanToString(span, documentSpanId?.(span)) : - documentSpanId?.(span); + baseline += `// textSpan: ${JSON.stringify(span.textSpan)}${ + span.contextSpan ? `, contextSpan: ${JSON.stringify(span.contextSpan)}` : "" + }`; + const text = !skipDocumentSpanDetails + ? convertDocumentSpanToString(span, documentSpanId?.(span)) + : documentSpanId?.(span); if (text) baseline += ` ${text}`; baseline += "\n"; } @@ -1489,7 +1772,9 @@ export class TestState { const detailSuffixes = new Map(); const details: Detail[] = []; let groupedSpanForAdditionalSpan: T | undefined; - if (fileName === marker?.fileName) details.push({ location: marker.position, locationMarker: markerInfo!.markerName }); + if (fileName === marker?.fileName) { + details.push({ location: marker.position, locationMarker: markerInfo!.markerName }); + } let canDetermineContextIdInline = true; for (const span of group) { const contextSpanIndex = details.length; @@ -1572,11 +1857,15 @@ export class TestState { const { location, locationMarker, span, type } = detail; if (!span && deferredMarkerIndex === undefined) { // If this is marker position and its same as textEnd and/or contextEnd we want to write marker after those - for (let matchingEndPosIndex = index + 1; matchingEndPosIndex < sortedDetails.length; matchingEndPosIndex++) { + for ( + let matchingEndPosIndex = index + 1; + matchingEndPosIndex < sortedDetails.length; + matchingEndPosIndex++ + ) { // Defer after the location if its same as rangeEnd if ( - sortedDetails[matchingEndPosIndex].location === location && - sortedDetails[matchingEndPosIndex].type!.endsWith("End") + sortedDetails[matchingEndPosIndex].location === location + && sortedDetails[matchingEndPosIndex].type!.endsWith("End") ) { deferredMarkerIndex = matchingEndPosIndex; } @@ -1595,9 +1884,9 @@ export class TestState { if (span) { switch (type) { case "textStart": - let text = !skipDocumentSpanDetails ? - convertDocumentSpanToString(span, documentSpanId?.(span), ignoredDocumentSpanProperties) : - documentSpanId?.(span); + let text = !skipDocumentSpanDetails + ? convertDocumentSpanToString(span, documentSpanId?.(span), ignoredDocumentSpanProperties) + : documentSpanId?.(span); if (span === groupedSpanForAdditionalSpan) { text = `textSpan: true` + (text ? `, ${text}` : ""); } @@ -1643,8 +1932,10 @@ export class TestState { if (!newContent && location === undefined) ts.Debug.fail("Unsupported"); if (type !== "textEnd" && type !== "contextEnd") { // Calculate pos to location number of lines - const posLine = posLineInfo?.pos === pos ? posLineInfo.line : ts.computeLineOfPosition(lineStarts, pos, posLineInfo?.line); - const locationLine = location !== undefined ? ts.computeLineOfPosition(lineStarts, location, posLine) : lineStarts.length - 1; + const posLine = posLineInfo?.pos === pos ? posLineInfo.line + : ts.computeLineOfPosition(lineStarts, pos, posLineInfo?.line); + const locationLine = location !== undefined ? ts.computeLineOfPosition(lineStarts, location, posLine) + : lineStarts.length - 1; if (location !== undefined) posLineInfo = { pos: location, line: locationLine }; let nLines = 0; if (newContent) nLines += TestState.nLinesContext + 1; @@ -1653,15 +1944,16 @@ export class TestState { if (locationLine - posLine > nLines) { if (newContent) { readableContents = readableContents + "\n" + readableJsoncBaseline( - newContent + content.slice(pos, lineStarts[posLine + TestState.nLinesContext]) + - `--- (line: ${isLibFile ? "--" : posLine + TestState.nLinesContext + 1}) skipped ---`, + newContent + content.slice(pos, lineStarts[posLine + TestState.nLinesContext]) + + `--- (line: ${isLibFile ? "--" : posLine + TestState.nLinesContext + 1}) skipped ---`, ); if (location !== undefined) readableContents += "\n"; newContent = ""; } if (location !== undefined) { - newContent += `--- (line: ${isLibFile ? "--" : locationLine - TestState.nLinesContext + 1}) skipped ---\n` + - content.slice(lineStarts[locationLine - TestState.nLinesContext + 1], location); + newContent += + `--- (line: ${isLibFile ? "--" : locationLine - TestState.nLinesContext + 1}) skipped ---\n` + + content.slice(lineStarts[locationLine - TestState.nLinesContext + 1], location); } return; } @@ -1673,7 +1965,11 @@ export class TestState { private assertObjectsEqual(fullActual: T, fullExpected: T, msgPrefix = ""): void { const recur = (actual: U, expected: U, path: string) => { const fail = (msg: string) => { - this.raiseError(`${msgPrefix} At ${path}: ${msg} ${displayExpectedAndActualString(stringify(fullExpected), stringify(fullActual))}`); + this.raiseError( + `${msgPrefix} At ${path}: ${msg} ${ + displayExpectedAndActualString(stringify(fullExpected), stringify(fullActual)) + }`, + ); }; if ((actual === undefined) !== (expected === undefined)) { @@ -1705,7 +2001,9 @@ export class TestState { if (fullActual === fullExpected) { return; } - this.raiseError(`${msgPrefix} ${displayExpectedAndActualString(stringify(fullExpected), stringify(fullActual))}`); + this.raiseError( + `${msgPrefix} ${displayExpectedAndActualString(stringify(fullExpected), stringify(fullActual))}`, + ); } recur(fullActual, fullExpected, ""); } @@ -1728,11 +2026,24 @@ export class TestState { ); } - private getCompletionEntryDetails(entryName: string, source: string | undefined, data: ts.CompletionEntryData | undefined, preferences?: ts.UserPreferences): ts.CompletionEntryDetails | undefined { + private getCompletionEntryDetails( + entryName: string, + source: string | undefined, + data: ts.CompletionEntryData | undefined, + preferences?: ts.UserPreferences, + ): ts.CompletionEntryDetails | undefined { if (preferences) { this.configure(preferences); } - return this.languageService.getCompletionEntryDetails(this.activeFile.fileName, this.currentCaretPosition, entryName, this.formatCodeSettings, source, preferences, data); + return this.languageService.getCompletionEntryDetails( + this.activeFile.fileName, + this.currentCaretPosition, + entryName, + this.formatCodeSettings, + source, + preferences, + data, + ); } private findReferencesAtCaret() { @@ -1750,16 +2061,26 @@ export class TestState { } public getSuggestionDiagnostics(expected: readonly FourSlashInterface.Diagnostic[]): void { - this.testDiagnostics(expected, this.languageService.getSuggestionDiagnostics(this.activeFile.fileName), "suggestion"); + this.testDiagnostics( + expected, + this.languageService.getSuggestionDiagnostics(this.activeFile.fileName), + "suggestion", + ); } - private testDiagnostics(expected: readonly FourSlashInterface.Diagnostic[], diagnostics: readonly ts.Diagnostic[], category: string) { + private testDiagnostics( + expected: readonly FourSlashInterface.Diagnostic[], + diagnostics: readonly ts.Diagnostic[], + category: string, + ) { assert.deepEqual( ts.realizeDiagnostics(diagnostics, "\n"), expected.map((e): ts.RealizedDiagnostic => { const range = e.range || this.getRangesInFile()[0]; if (!range) { - this.raiseError("Must provide a range for each expected diagnostic, or have one range in the fourslash source."); + this.raiseError( + "Must provide a range for each expected diagnostic, or have one range in the fourslash source.", + ); } return { message: e.message, @@ -1773,7 +2094,12 @@ export class TestState { ); } - public verifyQuickInfoAt(markerName: string | Range, expectedText: string, expectedDocumentation?: string, expectedTags?: { name: string; text: string; }[]) { + public verifyQuickInfoAt( + markerName: string | Range, + expectedText: string, + expectedDocumentation?: string, + expectedTags?: { name: string; text: string; }[], + ) { if (typeof markerName === "string") this.goToMarker(markerName); else this.goToRangeStart(markerName); @@ -1796,17 +2122,31 @@ export class TestState { } } - public verifyQuickInfoString(expectedText: string, expectedDocumentation?: string, expectedTags?: { name: string; text: string; }[]) { + public verifyQuickInfoString( + expectedText: string, + expectedDocumentation?: string, + expectedTags?: { name: string; text: string; }[], + ) { if (expectedDocumentation === "") { throw new Error("Use 'undefined' instead of empty string for `expectedDocumentation`"); } - const actualQuickInfo = this.languageService.getQuickInfoAtPosition(this.activeFile.fileName, this.currentCaretPosition); + const actualQuickInfo = this.languageService.getQuickInfoAtPosition( + this.activeFile.fileName, + this.currentCaretPosition, + ); const actualQuickInfoText = ts.displayPartsToString(actualQuickInfo?.displayParts); const actualQuickInfoDocumentation = ts.displayPartsToString(actualQuickInfo?.documentation); - const actualQuickInfoTags = actualQuickInfo?.tags?.map(tag => ({ name: tag.name, text: ts.displayPartsToString(tag.text) })); + const actualQuickInfoTags = actualQuickInfo?.tags?.map(tag => ({ + name: tag.name, + text: ts.displayPartsToString(tag.text), + })); assert.equal(actualQuickInfoText, expectedText, this.messageAtLastKnownMarker("quick info text")); - assert.equal(actualQuickInfoDocumentation, expectedDocumentation || "", this.assertionMessageAtLastKnownMarker("quick info doc")); + assert.equal( + actualQuickInfoDocumentation, + expectedDocumentation || "", + this.assertionMessageAtLastKnownMarker("quick info doc"), + ); if (!expectedTags) { // Skip if `expectedTags` is not given } @@ -1816,18 +2156,48 @@ export class TestState { else { ts.zipWith(expectedTags, actualQuickInfoTags, (expectedTag, actualTag) => { assert.equal(expectedTag.name, actualTag.name); - assert.equal(expectedTag.text, actualTag.text, this.messageAtLastKnownMarker("QuickInfo tag " + actualTag.name)); + assert.equal( + expectedTag.text, + actualTag.text, + this.messageAtLastKnownMarker("QuickInfo tag " + actualTag.name), + ); }); } } - public verifyQuickInfoDisplayParts(kind: string, kindModifiers: string, textSpan: TextSpan, displayParts: ts.SymbolDisplayPart[], documentation: ts.SymbolDisplayPart[], tags: ts.JSDocTagInfo[] | undefined) { - const actualQuickInfo = this.languageService.getQuickInfoAtPosition(this.activeFile.fileName, this.currentCaretPosition)!; + public verifyQuickInfoDisplayParts( + kind: string, + kindModifiers: string, + textSpan: TextSpan, + displayParts: ts.SymbolDisplayPart[], + documentation: ts.SymbolDisplayPart[], + tags: ts.JSDocTagInfo[] | undefined, + ) { + const actualQuickInfo = this.languageService.getQuickInfoAtPosition( + this.activeFile.fileName, + this.currentCaretPosition, + )!; assert.equal(actualQuickInfo.kind, kind, this.messageAtLastKnownMarker("QuickInfo kind")); - assert.equal(actualQuickInfo.kindModifiers, kindModifiers, this.messageAtLastKnownMarker("QuickInfo kindModifiers")); - assert.equal(JSON.stringify(actualQuickInfo.textSpan), JSON.stringify(textSpan), this.messageAtLastKnownMarker("QuickInfo textSpan")); - assert.equal(TestState.getDisplayPartsJson(actualQuickInfo.displayParts), TestState.getDisplayPartsJson(displayParts), this.messageAtLastKnownMarker("QuickInfo displayParts")); - assert.equal(TestState.getDisplayPartsJson(actualQuickInfo.documentation), TestState.getDisplayPartsJson(documentation), this.messageAtLastKnownMarker("QuickInfo documentation")); + assert.equal( + actualQuickInfo.kindModifiers, + kindModifiers, + this.messageAtLastKnownMarker("QuickInfo kindModifiers"), + ); + assert.equal( + JSON.stringify(actualQuickInfo.textSpan), + JSON.stringify(textSpan), + this.messageAtLastKnownMarker("QuickInfo textSpan"), + ); + assert.equal( + TestState.getDisplayPartsJson(actualQuickInfo.displayParts), + TestState.getDisplayPartsJson(displayParts), + this.messageAtLastKnownMarker("QuickInfo displayParts"), + ); + assert.equal( + TestState.getDisplayPartsJson(actualQuickInfo.documentation), + TestState.getDisplayPartsJson(documentation), + this.messageAtLastKnownMarker("QuickInfo documentation"), + ); if (!actualQuickInfo.tags || !tags) { assert.equal(actualQuickInfo.tags, tags, this.messageAtLastKnownMarker("QuickInfo tags")); } @@ -1835,17 +2205,21 @@ export class TestState { assert.equal(actualQuickInfo.tags.length, tags.length, this.messageAtLastKnownMarker("QuickInfo tags")); ts.zipWith(tags, actualQuickInfo.tags, (expectedTag, actualTag) => { assert.equal(expectedTag.name, actualTag.name); - assert.equal(expectedTag.text, actualTag.text, this.messageAtLastKnownMarker("QuickInfo tag " + actualTag.name)); + assert.equal( + expectedTag.text, + actualTag.text, + this.messageAtLastKnownMarker("QuickInfo tag " + actualTag.name), + ); }); } } private baselineRenameWorker(markerOrRange: MarkerOrNameOrRange, options?: FourSlashInterface.RenameOptions) { - const { fileName, position } = ts.isString(markerOrRange) ? - this.getMarkerByName(markerOrRange) : - isMarker(markerOrRange) ? - markerOrRange : - { fileName: markerOrRange.fileName, position: markerOrRange.pos }; + const { fileName, position } = ts.isString(markerOrRange) + ? this.getMarkerByName(markerOrRange) + : isMarker(markerOrRange) + ? markerOrRange + : { fileName: markerOrRange.fileName, position: markerOrRange.pos }; const { findInStrings = false, findInComments = false, @@ -1864,12 +2238,13 @@ export class TestState { this.raiseError(`baselineRename failed. Could not rename at the provided position.`); } - const renameOptions = options ? - (options.findInStrings !== undefined ? `// @findInStrings: ${findInStrings}\n` : "") + - (options.findInComments !== undefined ? `// @findInComments: ${findInComments}\n` : "") + - (options.providePrefixAndSuffixTextForRename !== undefined ? `// @providePrefixAndSuffixTextForRename: ${providePrefixAndSuffixTextForRename}\n` : "") + - (options.quotePreference !== undefined ? `// @quotePreference: ${quotePreference}\n` : "") : - ""; + const renameOptions = options + ? (options.findInStrings !== undefined ? `// @findInStrings: ${findInStrings}\n` : "") + + (options.findInComments !== undefined ? `// @findInComments: ${findInComments}\n` : "") + + (options.providePrefixAndSuffixTextForRename !== undefined + ? `// @providePrefixAndSuffixTextForRename: ${providePrefixAndSuffixTextForRename}\n` : "") + + (options.quotePreference !== undefined ? `// @quotePreference: ${quotePreference}\n` : "") + : ""; return renameOptions + (renameOptions ? "\n" : "") + this.getBaselineForDocumentSpansWithFileContents( locations, @@ -1884,7 +2259,10 @@ export class TestState { } public verifyQuickInfoExists(negative: boolean) { - const actualQuickInfo = this.languageService.getQuickInfoAtPosition(this.activeFile.fileName, this.currentCaretPosition); + const actualQuickInfo = this.languageService.getQuickInfoAtPosition( + this.activeFile.fileName, + this.currentCaretPosition, + ); if (negative) { if (actualQuickInfo) { this.raiseError("verifyQuickInfoExists failed. Expected quick info NOT to exist"); @@ -1897,7 +2275,11 @@ export class TestState { } } - public verifySignatureHelpPresence(expectPresent: boolean, triggerReason: ts.SignatureHelpTriggerReason | undefined, markers: readonly (string | Marker)[]) { + public verifySignatureHelpPresence( + expectPresent: boolean, + triggerReason: ts.SignatureHelpTriggerReason | undefined, + markers: readonly (string | Marker)[], + ) { if (markers.length) { for (const marker of markers) { this.goToMarker(marker); @@ -1940,15 +2322,25 @@ export class TestState { // Argument index may exceed number of parameters const currentParameter = selectedItem.parameters[help.argumentIndex] as ts.SignatureHelpParameter | undefined; - assert.equal(help.items.length, options.overloadsCount || 1, this.assertionMessageAtLastKnownMarker("signature help overloads count")); + assert.equal( + help.items.length, + options.overloadsCount || 1, + this.assertionMessageAtLastKnownMarker("signature help overloads count"), + ); - assert.equal(ts.displayPartsToString(selectedItem.documentation), options.docComment || "", this.assertionMessageAtLastKnownMarker("current signature help doc comment")); + assert.equal( + ts.displayPartsToString(selectedItem.documentation), + options.docComment || "", + this.assertionMessageAtLastKnownMarker("current signature help doc comment"), + ); if (options.text !== undefined) { assert.equal( - ts.displayPartsToString(selectedItem.prefixDisplayParts) + - selectedItem.parameters.map(p => ts.displayPartsToString(p.displayParts)).join(ts.displayPartsToString(selectedItem.separatorDisplayParts)) + - ts.displayPartsToString(selectedItem.suffixDisplayParts), + ts.displayPartsToString(selectedItem.prefixDisplayParts) + + selectedItem.parameters.map(p => ts.displayPartsToString(p.displayParts)).join( + ts.displayPartsToString(selectedItem.separatorDisplayParts), + ) + + ts.displayPartsToString(selectedItem.suffixDisplayParts), options.text, ); } @@ -1959,7 +2351,11 @@ export class TestState { assert.equal(ts.displayPartsToString(currentParameter!.displayParts), options.parameterSpan); } if (currentParameter) { - assert.equal(ts.displayPartsToString(currentParameter.documentation), options.parameterDocComment || "", this.assertionMessageAtLastKnownMarker("current parameter Help DocComment")); + assert.equal( + ts.displayPartsToString(currentParameter.documentation), + options.parameterDocComment || "", + this.assertionMessageAtLastKnownMarker("current parameter Help DocComment"), + ); } if (options.parameterCount !== undefined) { assert.equal(selectedItem.parameters.length, options.parameterCount); @@ -1971,10 +2367,18 @@ export class TestState { assert.equal(selectedItem.isVariadic, !!options.isVariadic); const actualTags = selectedItem.tags; - assert.equal(actualTags.length, (options.tags || ts.emptyArray).length, this.assertionMessageAtLastKnownMarker("signature help tags")); + assert.equal( + actualTags.length, + (options.tags || ts.emptyArray).length, + this.assertionMessageAtLastKnownMarker("signature help tags"), + ); ts.zipWith(options.tags || ts.emptyArray, actualTags, (expectedTag, actualTag) => { assert.equal(actualTag.name, expectedTag.name); - assert.deepEqual(actualTag.text, expectedTag.text, this.assertionMessageAtLastKnownMarker("signature help tag " + actualTag.name)); + assert.deepEqual( + actualTag.text, + expectedTag.text, + this.assertionMessageAtLastKnownMarker("signature help tag " + actualTag.name), + ); }); const allKeys: readonly (keyof FourSlashInterface.VerifySignatureHelpOptions)[] = [ @@ -2014,7 +2418,11 @@ export class TestState { expectedRange: Range | undefined, preferences: ts.UserPreferences | undefined, ): void { - const renameInfo = this.languageService.getRenameInfo(this.activeFile.fileName, this.currentCaretPosition, preferences || { allowRenameOfImportPath: true }); + const renameInfo = this.languageService.getRenameInfo( + this.activeFile.fileName, + this.currentCaretPosition, + preferences || { allowRenameOfImportPath: true }, + ); if (!renameInfo.canRename) { throw this.raiseError("Rename did not succeed"); } @@ -2033,19 +2441,23 @@ export class TestState { } if ( - renameInfo.triggerSpan.start !== expectedRange.pos || - ts.textSpanEnd(renameInfo.triggerSpan) !== expectedRange.end + renameInfo.triggerSpan.start !== expectedRange.pos + || ts.textSpanEnd(renameInfo.triggerSpan) !== expectedRange.end ) { this.raiseError( - "Expected triggerSpan [" + expectedRange.pos + "," + expectedRange.end + "). Got [" + - renameInfo.triggerSpan.start + "," + ts.textSpanEnd(renameInfo.triggerSpan) + ") instead.", + "Expected triggerSpan [" + expectedRange.pos + "," + expectedRange.end + "). Got [" + + renameInfo.triggerSpan.start + "," + ts.textSpanEnd(renameInfo.triggerSpan) + ") instead.", ); } } public verifyRenameInfoFailed(message?: string, preferences?: ts.UserPreferences) { - const allowRenameOfImportPath = preferences?.allowRenameOfImportPath === undefined ? true : preferences.allowRenameOfImportPath; - const renameInfo = this.languageService.getRenameInfo(this.activeFile.fileName, this.currentCaretPosition, { ...preferences, allowRenameOfImportPath }); + const allowRenameOfImportPath = preferences?.allowRenameOfImportPath === undefined ? true + : preferences.allowRenameOfImportPath; + const renameInfo = this.languageService.getRenameInfo(this.activeFile.fileName, this.currentCaretPosition, { + ...preferences, + allowRenameOfImportPath, + }); if (renameInfo.canRename) { throw this.raiseError("Rename was expected to fail"); } @@ -2054,7 +2466,11 @@ export class TestState { private alignmentForExtraInfo = 50; - private spanLines(file: FourSlashFile, spanInfo: ts.TextSpan, { selection = false, fullLines = false, lineNumbers = false } = {}) { + private spanLines( + file: FourSlashFile, + spanInfo: ts.TextSpan, + { selection = false, fullLines = false, lineNumbers = false } = {}, + ) { if (selection) { fullLines = true; } @@ -2103,24 +2519,35 @@ export class TestState { contextLineMap = ts.computeLineStarts(contextString); contextStart = { line: 0, character: 0 }; contextEnd = { line: contextLineMap.length - 1, character: 0 }; - selectionStart = selection ? ts.computeLineAndCharacterOfPosition(contextLineMap, spanInfo.start - contextStartPos) : contextStart; - selectionEnd = selection ? ts.computeLineAndCharacterOfPosition(contextLineMap, ts.textSpanEnd(spanInfo) - contextStartPos) : contextEnd; + selectionStart = selection + ? ts.computeLineAndCharacterOfPosition(contextLineMap, spanInfo.start - contextStartPos) : contextStart; + selectionEnd = selection + ? ts.computeLineAndCharacterOfPosition(contextLineMap, ts.textSpanEnd(spanInfo) - contextStartPos) + : contextEnd; lineNumberPrefixLength = 0; } const output: string[] = []; for (let lineNumber = contextStart.line; lineNumber <= contextEnd.line; lineNumber++) { const spanLine = contextString.substring(contextLineMap[lineNumber], contextLineMap[lineNumber + 1]); - output.push(lineNumbers ? `${ts.padLeft(`${lineNumber + 1}: `, lineNumberPrefixLength)}${spanLine}` : spanLine); + output.push( + lineNumbers ? `${ts.padLeft(`${lineNumber + 1}: `, lineNumberPrefixLength)}${spanLine}` : spanLine, + ); if (selection) { if (lineNumber < selectionStart.line || lineNumber > selectionEnd.line) { continue; } - const isEmpty = selectionStart.line === selectionEnd.line && selectionStart.character === selectionEnd.character; + const isEmpty = selectionStart.line === selectionEnd.line + && selectionStart.character === selectionEnd.character; const selectionPadLength = lineNumber === selectionStart.line ? selectionStart.character : 0; const selectionPad = " ".repeat(selectionPadLength + lineNumberPrefixLength); - const selectionLength = isEmpty ? 0 : Math.max(lineNumber < selectionEnd.line ? spanLine.trimRight().length - selectionPadLength : selectionEnd.character - selectionPadLength, 1); + const selectionLength = isEmpty ? 0 + : Math.max( + lineNumber < selectionEnd.line ? spanLine.trimRight().length - selectionPadLength + : selectionEnd.character - selectionPadLength, + 1, + ); const selectionLine = isEmpty ? "<" : "^".repeat(selectionLength); output.push(`${selectionPad}${selectionLine}`); } @@ -2138,7 +2565,8 @@ export class TestState { } resultString += prefixString + spanLines[i]; } - resultString += "\n" + prefixString + ":=> (" + this.getLineColStringAtPosition(spanInfo.start, file) + ") to (" + this.getLineColStringAtPosition(ts.textSpanEnd(spanInfo), file) + ")"; + resultString += "\n" + prefixString + ":=> (" + this.getLineColStringAtPosition(spanInfo.start, file) + + ") to (" + this.getLineColStringAtPosition(ts.textSpanEnd(spanInfo), file) + ")"; } return resultString; @@ -2159,7 +2587,10 @@ export class TestState { if (previousSpanInfo) { resultString += currentLine; let thisLineMarker = ts.repeatString(" ", startColumn!) + ts.repeatString("~", length!); - thisLineMarker += ts.repeatString(" ", this.alignmentForExtraInfo - thisLineMarker.length - prefixString.length + 1); + thisLineMarker += ts.repeatString( + " ", + this.alignmentForExtraInfo - thisLineMarker.length - prefixString.length + 1, + ); resultString += thisLineMarker; resultString += "=> Pos: (" + (pos - length!) + " to " + (pos - 1) + ") "; resultString += " " + previousSpanInfo; @@ -2174,7 +2605,8 @@ export class TestState { if (resultString.length) { resultString += "\n--------------------------------"; } - currentLine = "\n" + nextLine.toString() + ts.repeatString(" ", 3 - nextLine.toString().length) + ">" + this.activeFile.content.substring(pos, fileLineMap[nextLine]) + "\n "; + currentLine = "\n" + nextLine.toString() + ts.repeatString(" ", 3 - nextLine.toString().length) + ">" + + this.activeFile.content.substring(pos, fileLineMap[nextLine]) + "\n "; startColumn = 0; length = 0; } @@ -2199,8 +2631,14 @@ export class TestState { } public baselineCurrentFileBreakpointLocations() { - const baselineFile = this.getBaselineFileNameForInternalFourslashFile().replace("breakpointValidation", "bpSpan"); - Harness.Baseline.runBaseline(baselineFile, this.baselineCurrentFileLocations(pos => this.getBreakpointStatementLocation(pos)!)); + const baselineFile = this.getBaselineFileNameForInternalFourslashFile().replace( + "breakpointValidation", + "bpSpan", + ); + Harness.Baseline.runBaseline( + baselineFile, + this.baselineCurrentFileLocations(pos => this.getBreakpointStatementLocation(pos)!), + ); } private getEmitFiles(): readonly FourSlashFile[] { @@ -2224,7 +2662,10 @@ export class TestState { } public verifyGetEmitOutput(expectedOutputFiles: readonly string[]): void { - const outputFiles = ts.flatMap(this.getEmitFiles(), e => this.languageService.getEmitOutput(e.fileName).outputFiles); + const outputFiles = ts.flatMap( + this.getEmitFiles(), + e => this.languageService.getEmitOutput(e.fileName).outputFiles, + ); assert.deepEqual(outputFiles.map(f => f.name), expectedOutputFiles); @@ -2264,7 +2705,10 @@ export class TestState { resultString += Harness.IO.newLine(); } - Harness.Baseline.runBaseline(ts.Debug.checkDefined(this.testData.globalOptions[MetadataOptionNames.baselineFile]), resultString); + Harness.Baseline.runBaseline( + ts.Debug.checkDefined(this.testData.globalOptions[MetadataOptionNames.baselineFile]), + resultString, + ); } private flattenChainedMessage(diag: ts.DiagnosticMessageChain, indent = " ") { @@ -2329,7 +2773,9 @@ export class TestState { ({ displayParts, documentation, tags }) => [ ...(displayParts ? displayParts.map(p => p.text).join("").split("\n") : []), ...(documentation?.length ? documentation.map(p => p.text).join("").split("\n") : []), - ...(tags?.length ? tags.map(p => `@${p.name} ${p.text?.map(dp => dp.text).join("") ?? ""}`).join("\n").split("\n") : []), + ...(tags?.length + ? tags.map(p => `@${p.name} ${p.text?.map(dp => dp.text).join("") ?? ""}`).join("\n").split("\n") + : []), ], ); Harness.Baseline.runBaseline(baselineFile, annotations + "\n\n" + stringify(result)); @@ -2346,7 +2792,14 @@ export class TestState { "signature help", () => undefined, // use default: marker.position (item, previous) => { - const { documentation, tags, prefixDisplayParts, suffixDisplayParts, separatorDisplayParts, parameters } = item.items[item.selectedItemIndex]; + const { + documentation, + tags, + prefixDisplayParts, + suffixDisplayParts, + separatorDisplayParts, + parameters, + } = item.items[item.selectedItemIndex]; const tooltip = []; let signature = ""; if (prefixDisplayParts.length) signature += prefixDisplayParts.map(p => p.text).join(""); @@ -2361,7 +2814,10 @@ export class TestState { if (previous?.applicableSpan.start !== item.applicableSpan.start) { if (documentation?.length) tooltip.push(...documentation.map(p => p.text).join("").split("\n")); if (tags?.length) { - tooltip.push(...tags.map(p => `@${p.name} ${p.text?.map(dp => dp.text).join("") ?? ""}`).join("\n").split("\n")); + tooltip.push( + ...tags.map(p => `@${p.name} ${p.text?.map(dp => dp.text).join("") ?? ""}`).join("\n") + .split("\n"), + ); } } return tooltip; @@ -2468,7 +2924,10 @@ export class TestState { files.set(marker.fileName, lines); previous = item; } - return Array.from(files.entries(), ([fileName, lines]) => `=== ${fileName} ===\n` + lines.map(l => "// " + l).join("\n")) + return Array.from( + files.entries(), + ([fileName, lines]) => `=== ${fileName} ===\n` + lines.map(l => "// " + l).join("\n"), + ) .join("\n\n"); } @@ -2478,8 +2937,13 @@ export class TestState { const markers = this.getMarkers(); const fileContent = this.activeFile.content; const text = markers.map(marker => { - const baselineContent = [fileContent.slice(0, marker.position) + "/**/" + fileContent.slice(marker.position) + n]; - let selectionRange: ts.SelectionRange | undefined = this.languageService.getSmartSelectionRange(this.activeFile.fileName, marker.position); + const baselineContent = [ + fileContent.slice(0, marker.position) + "/**/" + fileContent.slice(marker.position) + n, + ]; + let selectionRange: ts.SelectionRange | undefined = this.languageService.getSmartSelectionRange( + this.activeFile.fileName, + marker.position, + ); while (selectionRange) { const { textSpan } = selectionRange; let masked = ts.arrayFrom(fileContent).map((char, index) => { @@ -2490,7 +2954,8 @@ export class TestState { return ts.isLineBreak(charCode) ? char : " "; }).join(""); masked = masked.replace(/^\s*$\r?\n?/gm, ""); // Remove blank lines - const isRealCharacter = (char: string) => char !== "•" && char !== "↲" && !ts.isWhiteSpaceLike(char.charCodeAt(0)); + const isRealCharacter = (char: string) => + char !== "•" && char !== "↲" && !ts.isWhiteSpaceLike(char.charCodeAt(0)); const leadingWidth = ts.arrayFrom(masked).findIndex(isRealCharacter); const trailingWidth = ts.findLastIndex(ts.arrayFrom(masked), isRealCharacter); masked = masked.slice(0, leadingWidth) @@ -2506,7 +2971,9 @@ export class TestState { } public printBreakpointLocation(pos: number) { - Harness.IO.log("\n**Pos: " + pos + " " + this.spanInfoToString(this.getBreakpointStatementLocation(pos)!, " ")); + Harness.IO.log( + "\n**Pos: " + pos + " " + this.spanInfoToString(this.getBreakpointStatementLocation(pos)!, " "), + ); } public printBreakpointAtCurrentLocation() { @@ -2514,12 +2981,19 @@ export class TestState { } public printCurrentParameterHelp() { - const help = this.languageService.getSignatureHelpItems(this.activeFile.fileName, this.currentCaretPosition, /*options*/ undefined); + const help = this.languageService.getSignatureHelpItems( + this.activeFile.fileName, + this.currentCaretPosition, + /*options*/ undefined, + ); Harness.IO.log(stringify(help)); } public printCurrentQuickInfo() { - const quickInfo = this.languageService.getQuickInfoAtPosition(this.activeFile.fileName, this.currentCaretPosition)!; + const quickInfo = this.languageService.getQuickInfoAtPosition( + this.activeFile.fileName, + this.currentCaretPosition, + )!; Harness.IO.log("Quick Info: " + quickInfo.displayParts!.map(part => part.text).join("")); } @@ -2532,9 +3006,9 @@ export class TestState { if (errorList.length) { errorList.forEach(err => { Harness.IO.log( - "start: " + err.start + - ", length: " + err.length + - ", message: " + ts.flattenDiagnosticMessageText(err.messageText, Harness.IO.newLine()), + "start: " + err.start + + ", length: " + err.length + + ", message: " + ts.flattenDiagnosticMessageText(err.messageText, Harness.IO.newLine()), ); }); } @@ -2546,7 +3020,8 @@ export class TestState { Harness.IO.log(`=== Script (${file.fileName}) ${(active ? "(active, cursor at |)" : "")} ===`); let content = this.getFileContent(file.fileName); if (active) { - content = content.substr(0, this.currentCaretPosition) + (makeCaretVisible ? "|" : "") + content.substr(this.currentCaretPosition); + content = content.substr(0, this.currentCaretPosition) + (makeCaretVisible ? "|" : "") + + content.substr(this.currentCaretPosition); } if (showWhitespace) { content = makeWhitespaceVisible(content); @@ -2561,16 +3036,18 @@ export class TestState { } private getBaselineFileNameForInternalFourslashFile(ext = ".baseline") { - return this.testData.globalOptions[MetadataOptionNames.baselineFile] || - ts.getBaseFileName(this.activeFile.fileName).replace(ts.Extension.Ts, ext); + return this.testData.globalOptions[MetadataOptionNames.baselineFile] + || ts.getBaseFileName(this.activeFile.fileName).replace(ts.Extension.Ts, ext); } private getBaselineFileNameForContainingTestFile(ext = ".baseline") { - return this.testData.globalOptions[MetadataOptionNames.baselineFile] || - ts.getBaseFileName(this.originalInputFileName).replace(ts.Extension.Ts, ext); + return this.testData.globalOptions[MetadataOptionNames.baselineFile] + || ts.getBaseFileName(this.originalInputFileName).replace(ts.Extension.Ts, ext); } - private getSignatureHelp({ triggerReason }: FourSlashInterface.VerifySignatureHelpOptions): ts.SignatureHelpItems | undefined { + private getSignatureHelp( + { triggerReason }: FourSlashInterface.VerifySignatureHelpOptions, + ): ts.SignatureHelpItems | undefined { return this.languageService.getSignatureHelpItems(this.activeFile.fileName, this.currentCaretPosition, { triggerReason, }); @@ -2593,8 +3070,14 @@ export class TestState { } const longestNameLength = max(entries, m => m.name.length); const longestKindLength = max(entries, m => m.kind.length); - entries.sort((m, n) => m.sortText > n.sortText ? 1 : m.sortText < n.sortText ? -1 : m.name > n.name ? 1 : m.name < n.name ? -1 : 0); - const membersString = entries.map(m => `${pad(m.name, longestNameLength)} ${pad(m.kind, longestKindLength)} ${m.kindModifiers} ${m.isRecommended ? "recommended " : ""}${m.source === undefined ? "" : m.source}`).join("\n"); + entries.sort((m, n) => + m.sortText > n.sortText ? 1 : m.sortText < n.sortText ? -1 : m.name > n.name ? 1 : m.name < n.name ? -1 : 0 + ); + const membersString = entries.map(m => + `${pad(m.name, longestNameLength)} ${pad(m.kind, longestKindLength)} ${m.kindModifiers} ${ + m.isRecommended ? "recommended " : "" + }${m.source === undefined ? "" : m.source}` + ).join("\n"); Harness.IO.log(membersString); } @@ -2617,7 +3100,12 @@ export class TestState { // Handle post-keystroke formatting if (this.enableFormatting) { - const edits = this.languageService.getFormattingEditsAfterKeystroke(this.activeFile.fileName, offset, ch, this.formatCodeSettings); + const edits = this.languageService.getFormattingEditsAfterKeystroke( + this.activeFile.fileName, + offset, + ch, + this.formatCodeSettings, + ); if (edits.length) { offset += this.applyEdits(this.activeFile.fileName, edits); } @@ -2633,8 +3121,14 @@ export class TestState { } public deleteLineRange(startIndex: number, endIndexInclusive: number) { - const startPos = this.languageServiceAdapterHost.lineAndCharacterToPosition(this.activeFile.fileName, { line: startIndex, character: 0 }); - const endPos = this.languageServiceAdapterHost.lineAndCharacterToPosition(this.activeFile.fileName, { line: endIndexInclusive + 1, character: 0 }); + const startPos = this.languageServiceAdapterHost.lineAndCharacterToPosition(this.activeFile.fileName, { + line: startIndex, + character: 0, + }); + const endPos = this.languageServiceAdapterHost.lineAndCharacterToPosition(this.activeFile.fileName, { + line: endIndexInclusive + 1, + character: 0, + }); this.replace(startPos, endPos - startPos, ""); } @@ -2702,7 +3196,12 @@ export class TestState { // Handle post-keystroke formatting if (this.enableFormatting) { - const edits = this.languageService.getFormattingEditsAfterKeystroke(this.activeFile.fileName, offset, ch, this.formatCodeSettings); + const edits = this.languageService.getFormattingEditsAfterKeystroke( + this.activeFile.fileName, + offset, + ch, + this.formatCodeSettings, + ); if (edits.length) { offset += this.applyEdits(this.activeFile.fileName, edits); } @@ -2715,13 +3214,23 @@ export class TestState { // Enters text as if the user had pasted it public paste(text: string) { const start = this.currentCaretPosition; - this.editScriptAndUpdateMarkers(this.activeFile.fileName, this.currentCaretPosition, this.currentCaretPosition, text); + this.editScriptAndUpdateMarkers( + this.activeFile.fileName, + this.currentCaretPosition, + this.currentCaretPosition, + text, + ); this.checkPostEditInvariants(); const offset = this.currentCaretPosition += text.length; // Handle formatting if (this.enableFormatting) { - const edits = this.languageService.getFormattingEditsForRange(this.activeFile.fileName, start, offset, this.formatCodeSettings); + const edits = this.languageService.getFormattingEditsForRange( + this.activeFile.fileName, + start, + offset, + this.formatCodeSettings, + ); if (edits.length) { this.applyEdits(this.activeFile.fileName, edits); } @@ -2748,12 +3257,18 @@ export class TestState { const options: ts.CreateSourceFileOptions = { languageVersion: ts.ScriptTarget.Latest, impliedNodeFormat: ts.getImpliedNodeFormatForFile( - ts.toPath(this.activeFile.fileName, this.languageServiceAdapterHost.sys.getCurrentDirectory(), ts.hostGetCanonicalFileName(this.languageServiceAdapterHost)), + ts.toPath( + this.activeFile.fileName, + this.languageServiceAdapterHost.sys.getCurrentDirectory(), + ts.hostGetCanonicalFileName(this.languageServiceAdapterHost), + ), /*packageJsonInfoCache*/ undefined, this.languageServiceAdapterHost, this.languageService.getProgram()?.getCompilerOptions() || {}, ), - setExternalModuleIndicator: ts.getSetExternalModuleIndicator(this.languageService.getProgram()?.getCompilerOptions() || {}), + setExternalModuleIndicator: ts.getSetExternalModuleIndicator( + this.languageService.getProgram()?.getCompilerOptions() || {}, + ), }; const referenceSourceFile = ts.createLanguageServiceSourceFile( this.activeFile.fileName, @@ -2810,17 +3325,30 @@ export class TestState { } public formatDocument() { - const edits = this.languageService.getFormattingEditsForDocument(this.activeFile.fileName, this.formatCodeSettings); + const edits = this.languageService.getFormattingEditsForDocument( + this.activeFile.fileName, + this.formatCodeSettings, + ); this.applyEdits(this.activeFile.fileName, edits); } public formatSelection(start: number, end: number) { - const edits = this.languageService.getFormattingEditsForRange(this.activeFile.fileName, start, end, this.formatCodeSettings); + const edits = this.languageService.getFormattingEditsForRange( + this.activeFile.fileName, + start, + end, + this.formatCodeSettings, + ); this.applyEdits(this.activeFile.fileName, edits); } public formatOnType(pos: number, key: string) { - const edits = this.languageService.getFormattingEditsAfterKeystroke(this.activeFile.fileName, pos, key, this.formatCodeSettings); + const edits = this.languageService.getFormattingEditsAfterKeystroke( + this.activeFile.fileName, + pos, + key, + this.formatCodeSettings, + ); this.applyEdits(this.activeFile.fileName, edits); } @@ -2897,40 +3425,72 @@ export class TestState { public verifyCaretAtMarker(markerName = "") { const pos = this.getMarkerByName(markerName); if (pos.fileName !== this.activeFile.fileName) { - throw new Error(`verifyCaretAtMarker failed - expected to be in file "${pos.fileName}", but was in file "${this.activeFile.fileName}"`); + throw new Error( + `verifyCaretAtMarker failed - expected to be in file "${pos.fileName}", but was in file "${this.activeFile.fileName}"`, + ); } if (pos.position !== this.currentCaretPosition) { - throw new Error(`verifyCaretAtMarker failed - expected to be at marker "/*${markerName}*/, but was at position ${this.currentCaretPosition}(${this.getLineColStringAtPosition(this.currentCaretPosition)})`); + throw new Error( + `verifyCaretAtMarker failed - expected to be at marker "/*${markerName}*/, but was at position ${this.currentCaretPosition}(${ + this.getLineColStringAtPosition(this.currentCaretPosition) + })`, + ); } } - private getIndentation(fileName: string, position: number, indentStyle: ts.IndentStyle, baseIndentSize: number): number { + private getIndentation( + fileName: string, + position: number, + indentStyle: ts.IndentStyle, + baseIndentSize: number, + ): number { const formatOptions = ts.clone(this.formatCodeSettings); formatOptions.indentStyle = indentStyle; formatOptions.baseIndentSize = baseIndentSize; return this.languageService.getIndentationAtPosition(fileName, position, formatOptions); } - public verifyIndentationAtCurrentPosition(numberOfSpaces: number, indentStyle: ts.IndentStyle = ts.IndentStyle.Smart, baseIndentSize = 0) { - const actual = this.getIndentation(this.activeFile.fileName, this.currentCaretPosition, indentStyle, baseIndentSize); + public verifyIndentationAtCurrentPosition( + numberOfSpaces: number, + indentStyle: ts.IndentStyle = ts.IndentStyle.Smart, + baseIndentSize = 0, + ) { + const actual = this.getIndentation( + this.activeFile.fileName, + this.currentCaretPosition, + indentStyle, + baseIndentSize, + ); const lineCol = this.getLineColStringAtPosition(this.currentCaretPosition); if (actual !== numberOfSpaces) { - this.raiseError(`verifyIndentationAtCurrentPosition failed at ${lineCol} - expected: ${numberOfSpaces}, actual: ${actual}`); + this.raiseError( + `verifyIndentationAtCurrentPosition failed at ${lineCol} - expected: ${numberOfSpaces}, actual: ${actual}`, + ); } } - public verifyIndentationAtPosition(fileName: string, position: number, numberOfSpaces: number, indentStyle: ts.IndentStyle = ts.IndentStyle.Smart, baseIndentSize = 0) { + public verifyIndentationAtPosition( + fileName: string, + position: number, + numberOfSpaces: number, + indentStyle: ts.IndentStyle = ts.IndentStyle.Smart, + baseIndentSize = 0, + ) { const actual = this.getIndentation(fileName, position, indentStyle, baseIndentSize); const lineCol = this.getLineColStringAtPosition(position); if (actual !== numberOfSpaces) { - this.raiseError(`verifyIndentationAtPosition failed at ${lineCol} - expected: ${numberOfSpaces}, actual: ${actual}`); + this.raiseError( + `verifyIndentationAtPosition failed at ${lineCol} - expected: ${numberOfSpaces}, actual: ${actual}`, + ); } } public verifyCurrentLineContent(text: string) { const actual = this.getCurrentLineContent(); if (actual !== text) { - throw new Error("verifyCurrentLineContent\n" + displayExpectedAndActualString(text, actual, /*quoted*/ true)); + throw new Error( + "verifyCurrentLineContent\n" + displayExpectedAndActualString(text, actual, /*quoted*/ true), + ); } } @@ -2953,21 +3513,34 @@ export class TestState { } public verifyTextAtCaretIs(text: string) { - const actual = this.getFileContent(this.activeFile.fileName).substring(this.currentCaretPosition, this.currentCaretPosition + text.length); + const actual = this.getFileContent(this.activeFile.fileName).substring( + this.currentCaretPosition, + this.currentCaretPosition + text.length, + ); if (actual !== text) { throw new Error("verifyTextAtCaretIs\n" + displayExpectedAndActualString(text, actual, /*quoted*/ true)); } } public verifyCurrentNameOrDottedNameSpanText(text: string) { - const span = this.languageService.getNameOrDottedNameSpan(this.activeFile.fileName, this.currentCaretPosition, this.currentCaretPosition); + const span = this.languageService.getNameOrDottedNameSpan( + this.activeFile.fileName, + this.currentCaretPosition, + this.currentCaretPosition, + ); if (!span) { - return this.raiseError("verifyCurrentNameOrDottedNameSpanText\n" + displayExpectedAndActualString('"' + text + '"', "undefined")); + return this.raiseError( + "verifyCurrentNameOrDottedNameSpanText\n" + + displayExpectedAndActualString('"' + text + '"', "undefined"), + ); } const actual = this.getFileContent(this.activeFile.fileName).substring(span.start, ts.textSpanEnd(span)); if (actual !== text) { - this.raiseError("verifyCurrentNameOrDottedNameSpanText\n" + displayExpectedAndActualString(text, actual, /*quoted*/ true)); + this.raiseError( + "verifyCurrentNameOrDottedNameSpanText\n" + + displayExpectedAndActualString(text, actual, /*quoted*/ true), + ); } } @@ -3026,25 +3599,31 @@ export class TestState { return [tokenTypes[typeIdx], ...tokenModifiers.filter((_, i) => modSet & 1 << i)].join("."); } - private verifyClassifications(expected: { classificationType: string | number; text?: string; textSpan?: TextSpan; }[], actual: (ts.ClassifiedSpan | ts.ClassifiedSpan2020)[], sourceFileText: string) { + private verifyClassifications( + expected: { classificationType: string | number; text?: string; textSpan?: TextSpan; }[], + actual: (ts.ClassifiedSpan | ts.ClassifiedSpan2020)[], + sourceFileText: string, + ) { if (actual.length !== expected.length) { this.raiseError( - "verifyClassifications failed - expected total classifications to be " + expected.length + - ", but was " + actual.length + - jsonMismatchString(), + "verifyClassifications failed - expected total classifications to be " + expected.length + + ", but was " + actual.length + + jsonMismatchString(), ); } ts.zipWith(expected, actual, (expectedClassification, actualClassification) => { const expectedType = expectedClassification.classificationType; - const actualType = typeof actualClassification.classificationType === "number" ? this.classificationToIdentifier(actualClassification.classificationType) : actualClassification.classificationType; + const actualType = typeof actualClassification.classificationType === "number" + ? this.classificationToIdentifier(actualClassification.classificationType) + : actualClassification.classificationType; if (expectedType !== actualType) { this.raiseError( - "verifyClassifications failed - expected classifications type to be " + - expectedType + ", but was " + - actualType + - jsonMismatchString(), + "verifyClassifications failed - expected classifications type to be " + + expectedType + ", but was " + + actualType + + jsonMismatchString(), ); } @@ -3056,10 +3635,10 @@ export class TestState { if (expectedSpan.start !== actualSpan.start || expectedLength !== actualSpan.length) { this.raiseError( - "verifyClassifications failed - expected span of text to be " + - "{start=" + expectedSpan.start + ", length=" + expectedLength + "}, but was " + - "{start=" + actualSpan.start + ", length=" + actualSpan.length + "}" + - jsonMismatchString(), + "verifyClassifications failed - expected span of text to be " + + "{start=" + expectedSpan.start + ", length=" + expectedLength + "}, but was " + + "{start=" + actualSpan.start + ", length=" + actualSpan.length + "}" + + jsonMismatchString(), ); } } @@ -3067,19 +3646,22 @@ export class TestState { const actualText = this.activeFile.content.substr(actualSpan.start, actualSpan.length); if (expectedClassification.text !== actualText) { this.raiseError( - "verifyClassifications failed - expected classified text to be " + - expectedClassification.text + ", but was " + - actualText + - jsonMismatchString(), + "verifyClassifications failed - expected classified text to be " + + expectedClassification.text + ", but was " + + actualText + + jsonMismatchString(), ); } }); function jsonMismatchString() { - const showActual = actual.map(({ classificationType, textSpan }) => ({ classificationType, text: sourceFileText.slice(textSpan.start, textSpan.start + textSpan.length) })); - return Harness.IO.newLine() + - "expected: '" + Harness.IO.newLine() + stringify(expected) + "'" + Harness.IO.newLine() + - "actual: '" + Harness.IO.newLine() + stringify(showActual) + "'"; + const showActual = actual.map(({ classificationType, textSpan }) => ({ + classificationType, + text: sourceFileText.slice(textSpan.start, textSpan.start + textSpan.length), + })); + return Harness.IO.newLine() + + "expected: '" + Harness.IO.newLine() + stringify(expected) + "'" + Harness.IO.newLine() + + "actual: '" + Harness.IO.newLine() + stringify(showActual) + "'"; } } @@ -3099,7 +3681,11 @@ export class TestState { } public replaceWithSemanticClassifications(format: ts.SemanticClassificationFormat.TwentyTwenty) { - const actual = this.languageService.getSemanticClassifications(this.activeFile.fileName, ts.createTextSpan(0, this.activeFile.content.length), format); + const actual = this.languageService.getSemanticClassifications( + this.activeFile.fileName, + ts.createTextSpan(0, this.activeFile.content.length), + format, + ); const replacement = [`const c2 = classification("2020");`, `verify.semanticClassificationsAre("2020",`]; for (const a of actual) { const identifier = this.classificationToIdentifier(a.classificationType as number); @@ -3108,7 +3694,9 @@ export class TestState { } replacement.push(");"); - throw new Error("You need to change the source code of fourslash test to use replaceWithSemanticClassifications"); + throw new Error( + "You need to change the source code of fourslash test to use replaceWithSemanticClassifications", + ); // const fs = require("fs"); // const testfilePath = this.originalInputFileName.slice(1); @@ -3118,26 +3706,47 @@ export class TestState { } public verifyEncodedSyntacticClassificationsLength(expected: number) { - const actual = this.languageService.getEncodedSyntacticClassifications(this.activeFile.fileName, ts.createTextSpan(0, this.activeFile.content.length)); + const actual = this.languageService.getEncodedSyntacticClassifications( + this.activeFile.fileName, + ts.createTextSpan(0, this.activeFile.content.length), + ); if (actual.spans.length !== expected) { - this.raiseError(`encodedSyntacticClassificationsLength failed - expected total spans to be ${expected} got ${actual.spans.length}`); + this.raiseError( + `encodedSyntacticClassificationsLength failed - expected total spans to be ${expected} got ${actual.spans.length}`, + ); } } public verifyEncodedSemanticClassificationsLength(format: ts.SemanticClassificationFormat, expected: number) { - const actual = this.languageService.getEncodedSemanticClassifications(this.activeFile.fileName, ts.createTextSpan(0, this.activeFile.content.length), format); + const actual = this.languageService.getEncodedSemanticClassifications( + this.activeFile.fileName, + ts.createTextSpan(0, this.activeFile.content.length), + format, + ); if (actual.spans.length !== expected) { - this.raiseError(`encodedSemanticClassificationsLength failed - expected total spans to be ${expected} got ${actual.spans.length}`); + this.raiseError( + `encodedSemanticClassificationsLength failed - expected total spans to be ${expected} got ${actual.spans.length}`, + ); } } - public verifySemanticClassifications(format: ts.SemanticClassificationFormat, expected: { classificationType: string | number; text?: string; }[]) { - const actual = this.languageService.getSemanticClassifications(this.activeFile.fileName, ts.createTextSpan(0, this.activeFile.content.length), format); + public verifySemanticClassifications( + format: ts.SemanticClassificationFormat, + expected: { classificationType: string | number; text?: string; }[], + ) { + const actual = this.languageService.getSemanticClassifications( + this.activeFile.fileName, + ts.createTextSpan(0, this.activeFile.content.length), + format, + ); this.verifyClassifications(expected, actual, this.activeFile.content); } public verifySyntacticClassifications(expected: { classificationType: string; text: string; }[]) { - const actual = this.languageService.getSyntacticClassifications(this.activeFile.fileName, ts.createTextSpan(0, this.activeFile.content.length)); + const actual = this.languageService.getSyntacticClassifications( + this.activeFile.fileName, + ts.createTextSpan(0, this.activeFile.content.length), + ); this.verifyClassifications(expected, actual, this.activeFile.content); } @@ -3169,15 +3778,30 @@ export class TestState { const filterActual = ts.filter(actual, f => kind === undefined ? true : f.kind === kind); if (filterActual.length !== spans.length) { - this.raiseError(`verifyOutliningSpans failed - expected total spans to be ${spans.length}, but was ${actual.length}\n\nFound Spans:\n\n${this.printOutliningSpansInline(actual)}`); + this.raiseError( + `verifyOutliningSpans failed - expected total spans to be ${spans.length}, but was ${actual.length}\n\nFound Spans:\n\n${ + this.printOutliningSpansInline(actual) + }`, + ); } ts.zipWith(spans, filterActual, (expectedSpan, actualSpan, i) => { - if (expectedSpan.pos !== actualSpan.textSpan.start || expectedSpan.end !== ts.textSpanEnd(actualSpan.textSpan)) { - return this.raiseError(`verifyOutliningSpans failed - span ${(i + 1)} expected: (${expectedSpan.pos},${expectedSpan.end}), actual: (${actualSpan.textSpan.start},${ts.textSpanEnd(actualSpan.textSpan)})`); + if ( + expectedSpan.pos !== actualSpan.textSpan.start + || expectedSpan.end !== ts.textSpanEnd(actualSpan.textSpan) + ) { + return this.raiseError( + `verifyOutliningSpans failed - span ${(i + + 1)} expected: (${expectedSpan.pos},${expectedSpan.end}), actual: (${actualSpan.textSpan.start},${ + ts.textSpanEnd(actualSpan.textSpan) + })`, + ); } if (kind !== undefined && actualSpan.kind !== kind) { - return this.raiseError(`verifyOutliningSpans failed - span ${(i + 1)} expected kind: ('${kind}'), actual: ('${actualSpan.kind}')`); + return this.raiseError( + `verifyOutliningSpans failed - span ${(i + + 1)} expected kind: ('${kind}'), actual: ('${actualSpan.kind}')`, + ); } }); } @@ -3186,28 +3810,50 @@ export class TestState { const actual = this.languageService.getOutliningSpans(this.activeFile.fileName); if (actual.length !== spans.length) { - this.raiseError(`verifyOutliningHintSpans failed - expected total spans to be ${spans.length}, but was ${actual.length}`); + this.raiseError( + `verifyOutliningHintSpans failed - expected total spans to be ${spans.length}, but was ${actual.length}`, + ); } ts.zipWith(spans, actual, (expectedSpan, actualSpan, i) => { - if (expectedSpan.pos !== actualSpan.hintSpan.start || expectedSpan.end !== ts.textSpanEnd(actualSpan.hintSpan)) { - return this.raiseError(`verifyOutliningSpans failed - span ${(i + 1)} expected: (${expectedSpan.pos},${expectedSpan.end}), actual: (${actualSpan.hintSpan.start},${ts.textSpanEnd(actualSpan.hintSpan)})`); + if ( + expectedSpan.pos !== actualSpan.hintSpan.start + || expectedSpan.end !== ts.textSpanEnd(actualSpan.hintSpan) + ) { + return this.raiseError( + `verifyOutliningSpans failed - span ${(i + + 1)} expected: (${expectedSpan.pos},${expectedSpan.end}), actual: (${actualSpan.hintSpan.start},${ + ts.textSpanEnd(actualSpan.hintSpan) + })`, + ); } }); } public verifyTodoComments(descriptors: string[], spans: Range[]) { - const actual = this.languageService.getTodoComments(this.activeFile.fileName, descriptors.map(d => ({ text: d, priority: 0 }))); + const actual = this.languageService.getTodoComments( + this.activeFile.fileName, + descriptors.map(d => ({ text: d, priority: 0 })), + ); if (actual.length !== spans.length) { - this.raiseError(`verifyTodoComments failed - expected total spans to be ${spans.length}, but was ${actual.length}`); + this.raiseError( + `verifyTodoComments failed - expected total spans to be ${spans.length}, but was ${actual.length}`, + ); } ts.zipWith(spans, actual, (expectedSpan, actualComment, i) => { const actualCommentSpan = ts.createTextSpan(actualComment.position, actualComment.message.length); - if (expectedSpan.pos !== actualCommentSpan.start || expectedSpan.end !== ts.textSpanEnd(actualCommentSpan)) { - this.raiseError(`verifyOutliningSpans failed - span ${(i + 1)} expected: (${expectedSpan.pos},${expectedSpan.end}), actual: (${actualCommentSpan.start},${ts.textSpanEnd(actualCommentSpan)})`); + if ( + expectedSpan.pos !== actualCommentSpan.start || expectedSpan.end !== ts.textSpanEnd(actualCommentSpan) + ) { + this.raiseError( + `verifyOutliningSpans failed - span ${(i + + 1)} expected: (${expectedSpan.pos},${expectedSpan.end}), actual: (${actualCommentSpan.start},${ + ts.textSpanEnd(actualCommentSpan) + })`, + ); } }); } @@ -3223,20 +3869,29 @@ export class TestState { const fixes = this.getCodeFixes(fileName, errorCode); if (index === undefined) { if (!(fixes && fixes.length === 1)) { - this.raiseError(`Should find exactly one codefix, but ${fixes ? fixes.length : "none"} found. ${fixes ? fixes.map(a => `${Harness.IO.newLine()} "${a.description}"`) : ""}`); + this.raiseError( + `Should find exactly one codefix, but ${fixes ? fixes.length : "none"} found. ${ + fixes ? fixes.map(a => `${Harness.IO.newLine()} "${a.description}"`) : "" + }`, + ); } index = 0; } else { if (!(fixes && fixes.length >= index + 1)) { - this.raiseError(`Should find at least ${index + 1} codefix(es), but ${fixes ? fixes.length : "none"} found.`); + this.raiseError( + `Should find at least ${index + 1} codefix(es), but ${fixes ? fixes.length : "none"} found.`, + ); } } this.applyChanges(fixes[index].changes); } - public applyCodeActionFromCompletion(markerName: string | undefined, options: FourSlashInterface.VerifyCompletionActionOptions) { + public applyCodeActionFromCompletion( + markerName: string | undefined, + options: FourSlashInterface.VerifyCompletionActionOptions, + ) { if (markerName !== undefined) { this.goToMarker(markerName); } @@ -3246,9 +3901,13 @@ export class TestState { const completions = this.getCompletionListAtCaret(options.preferences)?.entries; const matchingName = completions?.filter(e => e.name === options.name); const detailMessage = matchingName?.length - ? `\n Found ${matchingName.length} with name '${options.name}' from source(s) ${matchingName.map(e => `'${e.source}'`).join(", ")}.` + ? `\n Found ${matchingName.length} with name '${options.name}' from source(s) ${ + matchingName.map(e => `'${e.source}'`).join(", ") + }.` : ` (In fact, there were no completions with name '${options.name}' at all.)`; - return this.raiseError(`No completions were found for the given name, source/data, and preferences.` + detailMessage); + return this.raiseError( + `No completions were found for the given name, source/data, and preferences.` + detailMessage, + ); } const codeActions = details.codeActions; if (codeActions?.length !== 1) { @@ -3279,7 +3938,9 @@ export class TestState { private verifyTextMatches(actualText: string, includeWhitespace: boolean, expectedText: string) { const removeWhitespace = (s: string): string => includeWhitespace ? s : this.removeWhitespace(s); if (removeWhitespace(actualText) !== removeWhitespace(expectedText)) { - this.raiseError(`Actual range text doesn't match expected text.\n${showTextDiff(expectedText, actualText)}`); + this.raiseError( + `Actual range text doesn't match expected text.\n${showTextDiff(expectedText, actualText)}`, + ); } } @@ -3288,17 +3949,40 @@ export class TestState { * (ie: [|...|]) in the file after applying the codefix sole codefix * in the source file. */ - public verifyRangeAfterCodeFix(expectedText: string, includeWhiteSpace?: boolean, errorCode?: number, index?: number) { + public verifyRangeAfterCodeFix( + expectedText: string, + includeWhiteSpace?: boolean, + errorCode?: number, + index?: number, + ) { this.getAndApplyCodeActions(errorCode, index); this.verifyRangeIs(expectedText, includeWhiteSpace); } - public verifyCodeFixAll({ fixId, fixAllDescription, newFileContent, commands: expectedCommands }: FourSlashInterface.VerifyCodeFixAllOptions): void { + public verifyCodeFixAll( + { fixId, fixAllDescription, newFileContent, commands: expectedCommands }: + FourSlashInterface.VerifyCodeFixAllOptions, + ): void { const fixWithId = ts.find(this.getCodeFixes(this.activeFile.fileName), a => a.fixId === fixId); - ts.Debug.assert(fixWithId !== undefined, "No available code fix has the expected id. Fix All is not available if there is only one potentially fixable diagnostic present.", () => `Expected '${fixId}'. Available actions:\n${ts.mapDefined(this.getCodeFixes(this.activeFile.fileName), a => `${a.fixName} (${a.fixId || "no fix id"})`).join("\n")}`); + ts.Debug.assert( + fixWithId !== undefined, + "No available code fix has the expected id. Fix All is not available if there is only one potentially fixable diagnostic present.", + () => + `Expected '${fixId}'. Available actions:\n${ + ts.mapDefined( + this.getCodeFixes(this.activeFile.fileName), + a => `${a.fixName} (${a.fixId || "no fix id"})`, + ).join("\n") + }`, + ); ts.Debug.assertEqual(fixWithId.fixAllDescription, fixAllDescription); - const { changes, commands } = this.languageService.getCombinedCodeFix({ type: "file", fileName: this.activeFile.fileName }, fixId, this.formatCodeSettings, ts.emptyOptions); + const { changes, commands } = this.languageService.getCombinedCodeFix( + { type: "file", fileName: this.activeFile.fileName }, + fixId, + this.formatCodeSettings, + ts.emptyOptions, + ); assert.deepEqual(commands, expectedCommands); this.verifyNewContent({ newFileContent }, changes); } @@ -3309,13 +3993,19 @@ export class TestState { let index = options.index; if (index === undefined) { if (!(actions && actions.length === 1)) { - this.raiseError(`Should find exactly one codefix, but ${actions ? actions.length : "none"} found. ${actions ? actions.map(a => `${Harness.IO.newLine()} "${a.description}"`) : ""}`); + this.raiseError( + `Should find exactly one codefix, but ${actions ? actions.length : "none"} found. ${ + actions ? actions.map(a => `${Harness.IO.newLine()} "${a.description}"`) : "" + }`, + ); } index = 0; } else { if (!(actions && actions.length >= index + 1)) { - this.raiseError(`Should find at least ${index + 1} codefix(es), but ${actions ? actions.length : "none"} found.`); + this.raiseError( + `Should find at least ${index + 1} codefix(es), but ${actions ? actions.length : "none"} found.`, + ); } } @@ -3344,13 +4034,22 @@ export class TestState { } } - private verifyNewContent({ newFileContent, newRangeContent }: FourSlashInterface.NewContentOptions, changes: readonly ts.FileTextChanges[]): void { + private verifyNewContent( + { newFileContent, newRangeContent }: FourSlashInterface.NewContentOptions, + changes: readonly ts.FileTextChanges[], + ): void { if (newRangeContent !== undefined) { assert(newFileContent === undefined); - assert(changes.length === 1, "Affected 0 or more than 1 file, must use 'newFileContent' instead of 'newRangeContent'"); + assert( + changes.length === 1, + "Affected 0 or more than 1 file, must use 'newFileContent' instead of 'newRangeContent'", + ); const change = ts.first(changes); assert(change.fileName = this.activeFile.fileName); - const newText = ts.textChanges.applyChanges(this.getFileContent(this.activeFile.fileName), change.textChanges); + const newText = ts.textChanges.applyChanges( + this.getFileContent(this.activeFile.fileName), + change.textChanges, + ); const newRange = updateTextRangeForTextChanges(this.getOnlyRange(), change.textChanges); const actualText = newText.slice(newRange.pos, newRange.end); this.verifyTextMatches(actualText, /*includeWhitespace*/ true, newRangeContent); @@ -3364,7 +4063,8 @@ export class TestState { ts.Debug.fail(`Did not expect a change in ${change.fileName}`); } const oldText = this.tryGetFileContent(change.fileName); - const newContent = change.isNewFile ? ts.first(change.textChanges).newText : ts.textChanges.applyChanges(oldText!, change.textChanges); + const newContent = change.isNewFile ? ts.first(change.textChanges).newText + : ts.textChanges.applyChanges(oldText!, change.textChanges); this.verifyTextMatches(newContent, /*includeWhitespace*/ true, expectedNewContent); } for (const newFileName in newFileContent) { @@ -3373,7 +4073,10 @@ export class TestState { } } - private verifyNewContentAfterChange({ newFileContent, newRangeContent }: FourSlashInterface.NewContentOptions, changedFiles: readonly string[]) { + private verifyNewContentAfterChange( + { newFileContent, newRangeContent }: FourSlashInterface.NewContentOptions, + changedFiles: readonly string[], + ) { const assertedChangedFiles = !newFileContent || typeof newFileContent === "string" ? [this.activeFile.fileName] : ts.getOwnKeys(newFileContent); @@ -3399,7 +4102,12 @@ export class TestState { * Rerieves a codefix satisfying the parameters, or undefined if no such codefix is found. * @param fileName Path to file where error should be retrieved from. */ - private getCodeFixes(fileName: string, errorCode?: number, preferences: ts.UserPreferences = ts.emptyOptions, position?: number): readonly ts.CodeFixAction[] { + private getCodeFixes( + fileName: string, + errorCode?: number, + preferences: ts.UserPreferences = ts.emptyOptions, + position?: number, + ): readonly ts.CodeFixAction[] { if (this.testType === FourSlashTestType.Server) { this.configure(preferences); } @@ -3420,7 +4128,14 @@ export class TestState { return; } } - return this.languageService.getCodeFixesAtPosition(fileName, diagnostic.start!, diagnostic.start! + diagnostic.length!, [diagnostic.code], this.formatCodeSettings, preferences); + return this.languageService.getCodeFixesAtPosition( + fileName, + diagnostic.start!, + diagnostic.start! + diagnostic.length!, + [diagnostic.code], + this.formatCodeSettings, + preferences, + ); }); } @@ -3430,7 +4145,11 @@ export class TestState { } } - public verifyImportFixAtPosition(expectedTextArray: string[], errorCode: number | undefined, preferences: ts.UserPreferences | undefined) { + public verifyImportFixAtPosition( + expectedTextArray: string[], + errorCode: number | undefined, + preferences: ts.UserPreferences | undefined, + ) { const { fileName } = this.activeFile; const ranges = this.getRanges().filter(r => r.fileName === fileName); if (ranges.length > 1) { @@ -3442,7 +4161,9 @@ export class TestState { this.configure(preferences); } - const codeFixes = this.getCodeFixes(fileName, errorCode, preferences).filter(f => f.fixName === ts.codefix.importFixName); + const codeFixes = this.getCodeFixes(fileName, errorCode, preferences).filter(f => + f.fixName === ts.codefix.importFixName + ); if (codeFixes.length === 0) { if (expectedTextArray.length !== 0) { @@ -3469,7 +4190,11 @@ export class TestState { this.editScriptAndUpdateMarkers(fileName, span.start, span.start + insertedText.length, deletedText); } if (expectedTextArray.length !== actualTextArray.length) { - this.raiseError(`Expected ${expectedTextArray.length} import fixes, got ${actualTextArray.length}:\n\n${actualTextArray.join("\n\n" + "-".repeat(20) + "\n\n")}`); + this.raiseError( + `Expected ${expectedTextArray.length} import fixes, got ${actualTextArray.length}:\n\n${ + actualTextArray.join("\n\n" + "-".repeat(20) + "\n\n") + }`, + ); } ts.zipWith(expectedTextArray, actualTextArray, (expected, actual, index) => { if (expected !== actual) { @@ -3478,7 +4203,11 @@ export class TestState { }); } - public verifyImportFixModuleSpecifiers(markerName: string, moduleSpecifiers: string[], preferences?: ts.UserPreferences) { + public verifyImportFixModuleSpecifiers( + markerName: string, + moduleSpecifiers: string[], + preferences?: ts.UserPreferences, + ) { const marker = this.getMarkerByName(markerName); const codeFixes = this.getCodeFixes(marker.fileName, ts.Diagnostics.Cannot_find_name_0.code, { includeCompletionsForModuleExports: true, @@ -3498,26 +4227,39 @@ export class TestState { public verifyDocCommentTemplate(expected: ts.TextInsertion | undefined, options?: ts.DocCommentTemplateOptions) { const name = "verifyDocCommentTemplate"; - const actual = this.languageService.getDocCommentTemplateAtPosition(this.activeFile.fileName, this.currentCaretPosition, options || { generateReturnInDocTemplate: true }, this.formatCodeSettings)!; + const actual = this.languageService.getDocCommentTemplateAtPosition( + this.activeFile.fileName, + this.currentCaretPosition, + options || { generateReturnInDocTemplate: true }, + this.formatCodeSettings, + )!; if (expected === undefined) { if (actual) { - this.raiseError(`${name} failed - expected no template but got {newText: "${actual.newText}", caretOffset: ${actual.caretOffset}}`); + this.raiseError( + `${name} failed - expected no template but got {newText: "${actual.newText}", caretOffset: ${actual.caretOffset}}`, + ); } return; } else { if (actual === undefined) { - this.raiseError(`${name} failed - expected the template {newText: "${expected.newText}", caretOffset: "${expected.caretOffset}"} but got nothing instead`); + this.raiseError( + `${name} failed - expected the template {newText: "${expected.newText}", caretOffset: "${expected.caretOffset}"} but got nothing instead`, + ); } if (actual.newText !== expected.newText) { - this.raiseError(`${name} failed for expected insertion.\n${showTextDiff(expected.newText, actual.newText)}`); + this.raiseError( + `${name} failed for expected insertion.\n${showTextDiff(expected.newText, actual.newText)}`, + ); } if (actual.caretOffset !== expected.caretOffset) { - this.raiseError(`${name} failed - expected caretOffset: ${expected.caretOffset}\nactual caretOffset:${actual.caretOffset}`); + this.raiseError( + `${name} failed - expected caretOffset: ${expected.caretOffset}\nactual caretOffset:${actual.caretOffset}`, + ); } } } @@ -3541,7 +4283,11 @@ export class TestState { const position = this.currentCaretPosition; - const validBraceCompletion = this.languageService.isValidBraceCompletionAtPosition(this.activeFile.fileName, position, charCode); + const validBraceCompletion = this.languageService.isValidBraceCompletionAtPosition( + this.activeFile.fileName, + position, + charCode, + ); if (!negative && !validBraceCompletion) { this.raiseError(`${position} is not a valid brace completion position for ${openingBrace}`); @@ -3567,25 +4313,52 @@ export class TestState { const fileName = this.activeFile.fileName; const ext = ts.getAnyExtensionFromPath(fileName).slice(1); const lang = ["mts", "cts"].includes(ext) ? "ts" : ext; - let baselineText = codeFence(this.renderMarkers([{ text: "|", fileName: marker.fileName, position: marker.position }], /*useTerminalBoldSequence*/ false), lang) + "\n\n"; + let baselineText = codeFence( + this.renderMarkers( + [{ text: "|", fileName: marker.fileName, position: marker.position }], + /*useTerminalBoldSequence*/ false, + ), + lang, + ) + "\n\n"; const completions = this.getCompletionListAtCaret(completionPreferences)!; - const autoImportCompletions = completions.entries.filter(c => c.hasAction && c.source && c.sortText === ts.Completions.SortText.AutoImportSuggestions); + const autoImportCompletions = completions.entries.filter(c => + c.hasAction && c.source && c.sortText === ts.Completions.SortText.AutoImportSuggestions + ); if (autoImportCompletions.length) { - baselineText += `## From completions\n\n${autoImportCompletions.map(c => `- \`${c.name}\` from \`"${c.source}"\``).join("\n")}\n\n`; + baselineText += `## From completions\n\n${ + autoImportCompletions.map(c => `- \`${c.name}\` from \`"${c.source}"\``).join("\n") + }\n\n`; autoImportCompletions.forEach(c => { const details = this.getCompletionEntryDetails(c.name, c.source, c.data, completionPreferences); - assert(details?.codeActions, `Entry '${c.name}' from "${c.source}" returned no code actions from completion details request`); - assert(details.codeActions.length === 1, `Entry '${c.name}' from "${c.source}" returned more than one code action`); - assert(details.codeActions[0].changes.length === 1, `Entry '${c.name}' from "${c.source}" returned a code action changing more than one file`); - assert(details.codeActions[0].changes[0].fileName === this.activeFile.fileName, `Entry '${c.name}' from "${c.source}" returned a code action changing a different file`); + assert( + details?.codeActions, + `Entry '${c.name}' from "${c.source}" returned no code actions from completion details request`, + ); + assert( + details.codeActions.length === 1, + `Entry '${c.name}' from "${c.source}" returned more than one code action`, + ); + assert( + details.codeActions[0].changes.length === 1, + `Entry '${c.name}' from "${c.source}" returned a code action changing more than one file`, + ); + assert( + details.codeActions[0].changes[0].fileName === this.activeFile.fileName, + `Entry '${c.name}' from "${c.source}" returned a code action changing a different file`, + ); const changes = details.codeActions[0].changes[0].textChanges; - const completionChange: ts.TextChange = { newText: c.insertText || c.name, span: c.replacementSpan || completions.optionalReplacementSpan || { start: marker.position, length: 0 } }; + const completionChange: ts.TextChange = { + newText: c.insertText || c.name, + span: c.replacementSpan || completions.optionalReplacementSpan + || { start: marker.position, length: 0 }, + }; const sortedChanges = [...changes, completionChange].sort((a, b) => a.span.start - b.span.start); let newFileContent = this.activeFile.content; for (let i = sortedChanges.length - 1; i >= 0; i--) { - newFileContent = newFileContent.substring(0, sortedChanges[i].span.start) + sortedChanges[i].newText + newFileContent.substring(sortedChanges[i].span.start + sortedChanges[i].span.length); + newFileContent = newFileContent.substring(0, sortedChanges[i].span.start) + sortedChanges[i].newText + + newFileContent.substring(sortedChanges[i].span.start + sortedChanges[i].span.length); } baselineText += codeFence(newFileContent, lang) + "\n\n"; }); @@ -3600,7 +4373,10 @@ export class TestState { baselineText += `## From codefixes\n\n`; for (const fullNameForCodeFix of fullNamesForCodeFix) { - this.applyEdits(fileName, [{ span: { start: 0, length: this.getFileContent(fileName).length }, newText: originalContent }]); + this.applyEdits(fileName, [{ + span: { start: 0, length: this.getFileContent(fileName).length }, + newText: originalContent, + }]); this.applyEdits(fileName, [{ span: ts.createTextSpanFromRange(range), newText: fullNameForCodeFix }]); baselineText += `### When marker text is \`${fullNameForCodeFix}\`\n\n`; @@ -3627,7 +4403,10 @@ export class TestState { public verifyJsxClosingTag(map: { [markerName: string]: ts.JsxClosingTagInfo | undefined; }): void { for (const markerName in map) { this.goToMarker(markerName); - const actual = this.languageService.getJsxClosingTagAtPosition(this.activeFile.fileName, this.currentCaretPosition); + const actual = this.languageService.getJsxClosingTagAtPosition( + this.activeFile.fileName, + this.currentCaretPosition, + ); assert.deepEqual(actual, map[markerName], markerName); } } @@ -3635,7 +4414,10 @@ export class TestState { public verifyLinkedEditingRange(map: { [markerName: string]: ts.LinkedEditingInfo | undefined; }): void { for (const markerName in map) { this.goToMarker(markerName); - const actual = this.languageService.getLinkedEditingRangeAtPosition(this.activeFile.fileName, this.currentCaretPosition); + const actual = this.languageService.getLinkedEditingRangeAtPosition( + this.activeFile.fileName, + this.currentCaretPosition, + ); assert.deepEqual(actual, map[markerName], markerName); } } @@ -3654,7 +4436,11 @@ export class TestState { Harness.Baseline.runBaseline(baselineFile, baselineContent); - function getLinkedEditingBaselineWorker(activeFile: FourSlashFile, offset: number, languageService: ts.LanguageService) { + function getLinkedEditingBaselineWorker( + activeFile: FourSlashFile, + offset: number, + languageService: ts.LanguageService, + ) { const fileName = activeFile.fileName; let baselineContent = `=== ${fileName} ===\n`; @@ -3671,7 +4457,10 @@ export class TestState { const linkedEditsByRange = [...linkedEditsInFile.entries()].sort((a, b) => a[1][0] - b[1][0]); if (linkedEditsByRange.length === 0) { - return { baselineContent: baselineContent + activeFile.content + `\n\n--No linked edits found--`, offset }; + return { + baselineContent: baselineContent + activeFile.content + `\n\n--No linked edits found--`, + offset, + }; } let inlineLinkedEditBaselines: { start: number; end: number; index: number; }[] = []; @@ -3682,11 +4471,19 @@ export class TestState { for (let j = 0; j < positions.length - 1; j++) { // for each distinct range in the list of positions, add an entry to the list of places that need to be annotated in the baseline if (positions[j] + 1 !== positions[j + 1]) { - inlineLinkedEditBaselines.push({ start: positions[rangeStart], end: positions[j], index: offset }); + inlineLinkedEditBaselines.push({ + start: positions[rangeStart], + end: positions[j], + index: offset, + }); rangeStart = j + 1; } } - inlineLinkedEditBaselines.push({ start: positions[rangeStart], end: positions[positions.length - 1], index: offset }); + inlineLinkedEditBaselines.push({ + start: positions[rangeStart], + end: positions[positions.length - 1], + index: offset, + }); // add the LinkedEditInfo with its index to the baseline linkedEditInfoBaseline += `\n\n=== ${offset} ===\n` + linkedEdit; @@ -3699,7 +4496,8 @@ export class TestState { for (let i = 0; i < inlineLinkedEditBaselines.length; i++) { const e = inlineLinkedEditBaselines[i]; const sliceEnd = inlineLinkedEditBaselines[i + 1]?.start; - baselineContent += `[|/*${e.index}*/` + fileText.slice(e.start, e.end) + `|]` + fileText.slice(e.end, sliceEnd); + baselineContent += `[|/*${e.index}*/` + fileText.slice(e.start, e.end) + `|]` + + fileText.slice(e.end, sliceEnd); } baselineContent += linkedEditInfoBaseline; @@ -3711,7 +4509,9 @@ export class TestState { const actual = this.languageService.getBraceMatchingAtPosition(this.activeFile.fileName, bracePosition); if (actual.length !== 2) { - this.raiseError(`verifyMatchingBracePosition failed - expected result to contain 2 spans, but it had ${actual.length}`); + this.raiseError( + `verifyMatchingBracePosition failed - expected result to contain 2 spans, but it had ${actual.length}`, + ); } let actualMatchPosition = -1; @@ -3722,11 +4522,17 @@ export class TestState { actualMatchPosition = actual[0].start; } else { - this.raiseError(`verifyMatchingBracePosition failed - could not find the brace position: ${bracePosition} in the returned list: (${actual[0].start},${ts.textSpanEnd(actual[0])}) and (${actual[1].start},${ts.textSpanEnd(actual[1])})`); + this.raiseError( + `verifyMatchingBracePosition failed - could not find the brace position: ${bracePosition} in the returned list: (${ + actual[0].start + },${ts.textSpanEnd(actual[0])}) and (${actual[1].start},${ts.textSpanEnd(actual[1])})`, + ); } if (actualMatchPosition !== expectedMatchPosition) { - this.raiseError(`verifyMatchingBracePosition failed - expected: ${actualMatchPosition}, actual: ${expectedMatchPosition}`); + this.raiseError( + `verifyMatchingBracePosition failed - expected: ${actualMatchPosition}, actual: ${expectedMatchPosition}`, + ); } } @@ -3743,7 +4549,11 @@ export class TestState { const position = this.currentCaretPosition; const fileName = this.activeFile.fileName; const actual = !!this.languageService.getSpanOfEnclosingComment(fileName, position, /*onlyMultiLine*/ false); - const actualOnlyMultiLine = !!this.languageService.getSpanOfEnclosingComment(fileName, position, /*onlyMultiLine*/ true); + const actualOnlyMultiLine = !!this.languageService.getSpanOfEnclosingComment( + fileName, + position, + /*onlyMultiLine*/ true, + ); if (expected !== actual || onlyMultiLineDiverges === (actual === actualOnlyMultiLine)) { this.raiseError(`verifySpanOfEnclosingComment failed: position: '${position}' @@ -3776,16 +4586,33 @@ export class TestState { } public verifyNavigationBar(json: any, options: { checkSpans?: boolean; } | undefined) { - this.verifyNavigationTreeOrBar(json, this.languageService.getNavigationBarItems(this.activeFile.fileName), "Bar", options); + this.verifyNavigationTreeOrBar( + json, + this.languageService.getNavigationBarItems(this.activeFile.fileName), + "Bar", + options, + ); } public verifyNavigationTree(json: any, options: { checkSpans?: boolean; } | undefined) { - this.verifyNavigationTreeOrBar(json, this.languageService.getNavigationTree(this.activeFile.fileName), "Tree", options); + this.verifyNavigationTreeOrBar( + json, + this.languageService.getNavigationTree(this.activeFile.fileName), + "Tree", + options, + ); } - private verifyNavigationTreeOrBar(json: any, tree: any, name: "Tree" | "Bar", options: { checkSpans?: boolean; } | undefined) { + private verifyNavigationTreeOrBar( + json: any, + tree: any, + name: "Tree" | "Bar", + options: { checkSpans?: boolean; } | undefined, + ) { if (JSON.stringify(tree, replacer) !== JSON.stringify(json)) { - this.raiseError(`verifyNavigation${name} failed - \n${showTextDiff(stringify(json), stringify(tree, replacer))}`); + this.raiseError( + `verifyNavigation${name} failed - \n${showTextDiff(stringify(json), stringify(tree, replacer))}`, + ); } function replacer(key: string, value: any) { @@ -3810,7 +4637,9 @@ export class TestState { const items = this.languageService.getNavigateToItems(searchValue); Harness.IO.log(`NavigationItems list (${items.length} items)`); for (const item of items) { - Harness.IO.log(`name: ${item.name}, kind: ${item.kind}, parentName: ${item.containerName}, fileName: ${item.fileName}`); + Harness.IO.log( + `name: ${item.name}, kind: ${item.kind}, parentName: ${item.containerName}, fileName: ${item.fileName}`, + ); } } @@ -3818,31 +4647,49 @@ export class TestState { const items = this.languageService.getNavigationBarItems(this.activeFile.fileName); Harness.IO.log(`Navigation bar (${items.length} items)`); for (const item of items) { - Harness.IO.log(`${ts.repeatString(" ", item.indent)}name: ${item.text}, kind: ${item.kind}, childItems: ${item.childItems.map(child => child.text)}`); + Harness.IO.log( + `${ts.repeatString(" ", item.indent)}name: ${item.text}, kind: ${item.kind}, childItems: ${ + item.childItems.map(child => child.text) + }`, + ); } } private getDocumentHighlightsAtCurrentPosition(fileNamesToSearch: readonly string[]) { const filesToSearch = fileNamesToSearch.map(name => ts.combinePaths(this.basePath, name)); - return this.languageService.getDocumentHighlights(this.activeFile.fileName, this.currentCaretPosition, filesToSearch); + return this.languageService.getDocumentHighlights( + this.activeFile.fileName, + this.currentCaretPosition, + filesToSearch, + ); } - private baselineGetDocumentHighlights(markerOrRange: MarkerOrNameOrRange, options: FourSlashInterface.VerifyDocumentHighlightsOptions | undefined) { + private baselineGetDocumentHighlights( + markerOrRange: MarkerOrNameOrRange, + options: FourSlashInterface.VerifyDocumentHighlightsOptions | undefined, + ) { this.goToMarkerOrNameOrRange(markerOrRange); - const highlights = this.getDocumentHighlightsAtCurrentPosition(ts.map(options?.filesToSearch, ts.normalizePath) || [this.activeFile.fileName]); + const highlights = this.getDocumentHighlightsAtCurrentPosition( + ts.map(options?.filesToSearch, ts.normalizePath) || [this.activeFile.fileName], + ); // Write input files - const filesToSearch = options ? "// filesToSearch:\n" + - options.filesToSearch.map(f => "// " + f).join("\n") + "\n\n" : - ""; + const filesToSearch = options ? "// filesToSearch:\n" + + options.filesToSearch.map(f => "// " + f).join("\n") + "\n\n" + : ""; const baselineContent = this.getBaselineForGroupedDocumentSpansWithFileContents( - highlights?.map(h => h.highlightSpans.map(s => s.fileName ? s as ts.DocumentSpan : { ...s, fileName: h.fileName })) || ts.emptyArray, + highlights?.map(h => + h.highlightSpans.map(s => s.fileName ? s as ts.DocumentSpan : { ...s, fileName: h.fileName }) + ) || ts.emptyArray, { markerInfo: { markerOrRange, markerName: "/*HIGHLIGHTS*/" } }, ); return filesToSearch + baselineContent; } - public verifyCodeFixAvailable(negative: boolean, expected: FourSlashInterface.VerifyCodeFixAvailableOptions[] | string | undefined): void { + public verifyCodeFixAvailable( + negative: boolean, + expected: FourSlashInterface.VerifyCodeFixAvailableOptions[] | string | undefined, + ): void { const codeFixes = this.getCodeFixes(this.activeFile.fileName); if (negative) { if (typeof expected === "undefined") { @@ -3854,14 +4701,20 @@ export class TestState { } } else { - assert(typeof expected === "undefined" || typeof expected === "string", "With a negated assertion, 'expected' must be undefined or a string value of a codefix name."); + assert( + typeof expected === "undefined" || typeof expected === "string", + "With a negated assertion, 'expected' must be undefined or a string value of a codefix name.", + ); } } else if (typeof expected === "string") { this.assertObjectsEqual(codeFixes.map(fix => fix.fixName), [expected]); } else { - const actuals = codeFixes.map((fix): FourSlashInterface.VerifyCodeFixAvailableOptions => ({ description: fix.description, commands: fix.commands })); + const actuals = codeFixes.map((fix): FourSlashInterface.VerifyCodeFixAvailableOptions => ({ + description: fix.description, + commands: fix.commands, + })); this.assertObjectsEqual(actuals, negative ? ts.emptyArray : expected); } } @@ -3878,9 +4731,13 @@ export class TestState { } this.raiseError( - `Expected to find a fix with the name '${fixName}', but none exists.` + - availableFixes.length - ? ` Available fixes: ${availableFixes.map(fix => `${fix.fixName} (${fix.fixId ? "with" : "without"} fix-all)`).join(", ")}` + `Expected to find a fix with the name '${fixName}', but none exists.` + + availableFixes.length + ? ` Available fixes: ${ + availableFixes.map(fix => `${fix.fixName} (${fix.fixId ? "with" : "without"} fix-all)`).join( + ", ", + ) + }` : "", ); } @@ -3889,10 +4746,14 @@ export class TestState { public verifyApplicableRefactorAvailableAtMarker(negative: boolean, markerName: string) { const isAvailable = this.getApplicableRefactors(this.getMarkerByName(markerName)).length > 0; if (negative && isAvailable) { - this.raiseError(`verifyApplicableRefactorAvailableAtMarker failed - expected no refactor at marker ${markerName} but found some.`); + this.raiseError( + `verifyApplicableRefactorAvailableAtMarker failed - expected no refactor at marker ${markerName} but found some.`, + ); } if (!negative && !isAvailable) { - this.raiseError(`verifyApplicableRefactorAvailableAtMarker failed - expected a refactor at marker ${markerName} but found none.`); + this.raiseError( + `verifyApplicableRefactorAvailableAtMarker failed - expected a refactor at marker ${markerName} but found none.`, + ); } } @@ -3903,7 +4764,13 @@ export class TestState { }; } - public verifyRefactorAvailable(negative: boolean, triggerReason: ts.RefactorTriggerReason, name: string, actionName?: string, actionDescription?: string) { + public verifyRefactorAvailable( + negative: boolean, + triggerReason: ts.RefactorTriggerReason, + name: string, + actionName?: string, + actionDescription?: string, + ) { let refactors = this.getApplicableRefactorsAtSelection(triggerReason); refactors = refactors.filter(r => r.name === name); @@ -3921,15 +4788,23 @@ export class TestState { if (negative) { if (isAvailable) { - this.raiseError(`verifyApplicableRefactorAvailableForRange failed - expected no refactor but found: ${refactors.map(r => r.name).join(", ")}`); + this.raiseError( + `verifyApplicableRefactorAvailableForRange failed - expected no refactor but found: ${ + refactors.map(r => r.name).join(", ") + }`, + ); } } else { if (!isAvailable) { - this.raiseError(`verifyApplicableRefactorAvailableForRange failed - expected a refactor but found none.`); + this.raiseError( + `verifyApplicableRefactorAvailableForRange failed - expected a refactor but found none.`, + ); } if (refactors.length > 1) { - this.raiseError(`${refactors.length} available refactors both have name ${name} and action ${actionName}`); + this.raiseError( + `${refactors.length} available refactors both have name ${name} and action ${actionName}`, + ); } } } @@ -3959,23 +4834,48 @@ export class TestState { } } - public applyRefactor({ refactorName, actionName, actionDescription, newContent: newContentWithRenameMarker, triggerReason }: FourSlashInterface.ApplyRefactorOptions) { + public applyRefactor( + { refactorName, actionName, actionDescription, newContent: newContentWithRenameMarker, triggerReason }: + FourSlashInterface.ApplyRefactorOptions, + ) { const range = this.getSelection(); const refactors = this.getApplicableRefactorsAtSelection(triggerReason); const refactorsWithName = refactors.filter(r => r.name === refactorName); if (refactorsWithName.length === 0) { - this.raiseError(`The expected refactor: ${refactorName} is not available at the marker location.\nAvailable refactors: ${refactors.map(r => r.name)}`); + this.raiseError( + `The expected refactor: ${refactorName} is not available at the marker location.\nAvailable refactors: ${ + refactors.map(r => r.name) + }`, + ); } - const action = ts.firstDefined(refactorsWithName, refactor => refactor.actions.find(a => a.name === actionName)); + const action = ts.firstDefined( + refactorsWithName, + refactor => refactor.actions.find(a => a.name === actionName), + ); if (!action) { - throw this.raiseError(`The expected action: ${actionName} is not included in: ${ts.flatMap(refactorsWithName, r => r.actions.map(a => a.name))}`); + throw this.raiseError( + `The expected action: ${actionName} is not included in: ${ + ts.flatMap(refactorsWithName, r => r.actions.map(a => a.name)) + }`, + ); } if (action.description !== actionDescription) { - this.raiseError(`Expected action description to be ${JSON.stringify(actionDescription)}, got: ${JSON.stringify(action.description)}`); + this.raiseError( + `Expected action description to be ${JSON.stringify(actionDescription)}, got: ${ + JSON.stringify(action.description) + }`, + ); } - const editInfo = this.languageService.getEditsForRefactor(this.activeFile.fileName, this.formatCodeSettings, range, refactorName, actionName, ts.emptyOptions)!; + const editInfo = this.languageService.getEditsForRefactor( + this.activeFile.fileName, + this.formatCodeSettings, + range, + refactorName, + actionName, + ts.emptyOptions, + )!; for (const edit of editInfo.edits) { this.applyEdits(edit.fileName, edit.textChanges); } @@ -3983,7 +4883,8 @@ export class TestState { let renameFilename: string | undefined; let renamePosition: number | undefined; - const newFileContents = typeof newContentWithRenameMarker === "string" ? { [this.activeFile.fileName]: newContentWithRenameMarker } : newContentWithRenameMarker; + const newFileContents = typeof newContentWithRenameMarker === "string" + ? { [this.activeFile.fileName]: newContentWithRenameMarker } : newContentWithRenameMarker; for (const fileName in newFileContents) { const { renamePosition: rp, newContent } = TestState.parseNewContent(newFileContents[fileName]); if (renamePosition === undefined) { @@ -4009,13 +4910,16 @@ export class TestState { } } - private static parseNewContent(newContentWithRenameMarker: string): { readonly renamePosition: number | undefined; readonly newContent: string; } { + private static parseNewContent( + newContentWithRenameMarker: string, + ): { readonly renamePosition: number | undefined; readonly newContent: string; } { const renamePosition = newContentWithRenameMarker.indexOf("/*RENAME*/"); if (renamePosition === -1) { return { renamePosition: undefined, newContent: newContentWithRenameMarker }; } else { - const newContent = newContentWithRenameMarker.slice(0, renamePosition) + newContentWithRenameMarker.slice(renamePosition + "/*RENAME*/".length); + const newContent = newContentWithRenameMarker.slice(0, renamePosition) + + newContentWithRenameMarker.slice(renamePosition + "/*RENAME*/".length); return { renamePosition, newContent }; } } @@ -4033,30 +4937,67 @@ export class TestState { } public moveToNewFile(options: FourSlashInterface.MoveToNewFileOptions): void { - assert(this.getRanges().length === 1, "Must have exactly one fourslash range (source enclosed between '[|' and '|]' delimiters) in the source file"); + assert( + this.getRanges().length === 1, + "Must have exactly one fourslash range (source enclosed between '[|' and '|]' delimiters) in the source file", + ); const range = this.getRanges()[0]; - const refactor = ts.find(this.getApplicableRefactors(range, { allowTextChangesInNewFiles: true }), r => r.name === "Move to a new file")!; + const refactor = ts.find( + this.getApplicableRefactors(range, { allowTextChangesInNewFiles: true }), + r => r.name === "Move to a new file", + )!; assert(refactor.actions.length === 1); const action = ts.first(refactor.actions); assert(action.name === "Move to a new file" && action.description === "Move to a new file"); - const editInfo = this.languageService.getEditsForRefactor(range.fileName, this.formatCodeSettings, range, refactor.name, action.name, options.preferences || ts.emptyOptions)!; + const editInfo = this.languageService.getEditsForRefactor( + range.fileName, + this.formatCodeSettings, + range, + refactor.name, + action.name, + options.preferences || ts.emptyOptions, + )!; this.verifyNewContent({ newFileContent: options.newFileContents }, editInfo.edits); } public moveToFile(options: FourSlashInterface.MoveToFileOptions): void { - assert(this.getRanges().length === 1, "Must have exactly one fourslash range (source enclosed between '[|' and '|]' delimiters) in the source file"); + assert( + this.getRanges().length === 1, + "Must have exactly one fourslash range (source enclosed between '[|' and '|]' delimiters) in the source file", + ); const range = this.getRanges()[0]; - const refactor = ts.find(this.getApplicableRefactors(range, { allowTextChangesInNewFiles: true }, /*triggerReason*/ undefined, /*kind*/ undefined, /*includeInteractiveActions*/ true), r => r.name === "Move to file")!; + const refactor = ts.find( + this.getApplicableRefactors( + range, + { allowTextChangesInNewFiles: true }, + /*triggerReason*/ undefined, + /*kind*/ undefined, + /*includeInteractiveActions*/ true, + ), + r => r.name === "Move to file", + )!; assert(refactor.actions.length === 1); const action = ts.first(refactor.actions); assert(action.name === "Move to file" && action.description === "Move to file"); - const editInfo = this.languageService.getEditsForRefactor(range.fileName, this.formatCodeSettings, range, refactor.name, action.name, options.preferences || ts.emptyOptions, options.interactiveRefactorArguments)!; + const editInfo = this.languageService.getEditsForRefactor( + range.fileName, + this.formatCodeSettings, + range, + refactor.name, + action.name, + options.preferences || ts.emptyOptions, + options.interactiveRefactorArguments, + )!; this.verifyNewContent({ newFileContent: options.newFileContents }, editInfo.edits); } - private testNewFileContents(edits: readonly ts.FileTextChanges[], newFileContents: { [fileName: string]: string; }, description: string): void { + private testNewFileContents( + edits: readonly ts.FileTextChanges[], + newFileContents: { [fileName: string]: string; }, + description: string, + ): void { for (const { fileName, textChanges } of edits) { const newContent = newFileContents[fileName]; if (newContent === undefined) { @@ -4094,14 +5035,28 @@ export class TestState { formattingOptions = formattingOptions || this.formatCodeSettings; const marker = this.getMarkerByName(markerName); - const applicableRefactors = this.languageService.getApplicableRefactors(this.activeFile.fileName, marker.position, ts.emptyOptions); - const applicableRefactorToApply = ts.find(applicableRefactors, refactor => refactor.name === refactorNameToApply); + const applicableRefactors = this.languageService.getApplicableRefactors( + this.activeFile.fileName, + marker.position, + ts.emptyOptions, + ); + const applicableRefactorToApply = ts.find( + applicableRefactors, + refactor => refactor.name === refactorNameToApply, + ); if (!applicableRefactorToApply) { this.raiseError(`The expected refactor: ${refactorNameToApply} is not available at the marker location.`); } - const editInfo = this.languageService.getEditsForRefactor(marker.fileName, formattingOptions, marker.position, refactorNameToApply, actionName, ts.emptyOptions)!; + const editInfo = this.languageService.getEditsForRefactor( + marker.fileName, + formattingOptions, + marker.position, + refactorNameToApply, + actionName, + ts.emptyOptions, + )!; for (const edit of editInfo.edits) { this.applyEdits(edit.fileName, edit.textChanges); @@ -4109,7 +5064,9 @@ export class TestState { const actualContent = this.getFileContent(marker.fileName); if (actualContent !== expectedContent) { - this.raiseError(`verifyFileAfterApplyingRefactors failed:\n${showTextDiff(expectedContent, actualContent)}`); + this.raiseError( + `verifyFileAfterApplyingRefactors failed:\n${showTextDiff(expectedContent, actualContent)}`, + ); } } @@ -4118,12 +5075,19 @@ export class TestState { Harness.IO.log(stringify(codeFixes)); } - private formatCallHierarchyItemSpan(file: FourSlashFile, span: ts.TextSpan, prefix: string, trailingPrefix = prefix) { + private formatCallHierarchyItemSpan( + file: FourSlashFile, + span: ts.TextSpan, + prefix: string, + trailingPrefix = prefix, + ) { const startLc = this.languageServiceAdapterHost.positionToLineAndCharacter(file.fileName, span.start); const endLc = this.languageServiceAdapterHost.positionToLineAndCharacter(file.fileName, ts.textSpanEnd(span)); const lines = this.spanLines(file, span, { fullLines: true, lineNumbers: true, selection: true }); let text = ""; - text += `${prefix}╭ ${file.fileName}:${startLc.line + 1}:${startLc.character + 1}-${endLc.line + 1}:${endLc.character + 1}\n`; + text += `${prefix}╭ ${file.fileName}:${startLc.line + 1}:${startLc.character + 1}-${endLc.line + 1}:${ + endLc.character + 1 + }\n`; for (const line of lines) { text += `${prefix}│ ${line.trimRight()}\n`; } @@ -4131,26 +5095,55 @@ export class TestState { return text; } - private formatCallHierarchyItemSpans(file: FourSlashFile, spans: ts.TextSpan[], prefix: string, trailingPrefix = prefix) { + private formatCallHierarchyItemSpans( + file: FourSlashFile, + spans: ts.TextSpan[], + prefix: string, + trailingPrefix = prefix, + ) { let text = ""; for (let i = 0; i < spans.length; i++) { - text += this.formatCallHierarchyItemSpan(file, spans[i], prefix, i < spans.length - 1 ? prefix : trailingPrefix); + text += this.formatCallHierarchyItemSpan( + file, + spans[i], + prefix, + i < spans.length - 1 ? prefix : trailingPrefix, + ); } return text; } - private formatCallHierarchyItem(file: FourSlashFile, callHierarchyItem: ts.CallHierarchyItem, direction: CallHierarchyItemDirection, seen: Map, prefix: string, trailingPrefix: string = prefix) { + private formatCallHierarchyItem( + file: FourSlashFile, + callHierarchyItem: ts.CallHierarchyItem, + direction: CallHierarchyItemDirection, + seen: Map, + prefix: string, + trailingPrefix: string = prefix, + ) { const key = `${callHierarchyItem.file}|${JSON.stringify(callHierarchyItem.span)}|${direction}`; const alreadySeen = seen.has(key); seen.set(key, true); - const incomingCalls = direction === CallHierarchyItemDirection.Outgoing ? { result: "skip" } as const : - alreadySeen ? { result: "seen" } as const : - { result: "show", values: this.languageService.provideCallHierarchyIncomingCalls(callHierarchyItem.file, callHierarchyItem.selectionSpan.start) } as const; - - const outgoingCalls = direction === CallHierarchyItemDirection.Incoming ? { result: "skip" } as const : - alreadySeen ? { result: "seen" } as const : - { result: "show", values: this.languageService.provideCallHierarchyOutgoingCalls(callHierarchyItem.file, callHierarchyItem.selectionSpan.start) } as const; + const incomingCalls = direction === CallHierarchyItemDirection.Outgoing ? { result: "skip" } as const + : alreadySeen ? { result: "seen" } as const + : { + result: "show", + values: this.languageService.provideCallHierarchyIncomingCalls( + callHierarchyItem.file, + callHierarchyItem.selectionSpan.start, + ), + } as const; + + const outgoingCalls = direction === CallHierarchyItemDirection.Incoming ? { result: "skip" } as const + : alreadySeen ? { result: "seen" } as const + : { + result: "show", + values: this.languageService.provideCallHierarchyOutgoingCalls( + callHierarchyItem.file, + callHierarchyItem.selectionSpan.start, + ), + } as const; let text = ""; text += `${prefix}╭ name: ${callHierarchyItem.name}\n`; @@ -4166,8 +5159,8 @@ export class TestState { file, callHierarchyItem.selectionSpan, `${prefix}│ `, - incomingCalls.result !== "skip" || outgoingCalls.result !== "skip" ? `${prefix}│ ` : - `${trailingPrefix}╰ `, + incomingCalls.result !== "skip" || outgoingCalls.result !== "skip" ? `${prefix}│ ` + : `${trailingPrefix}╰ `, ); if (incomingCalls.result === "seen") { @@ -4193,15 +5186,21 @@ export class TestState { const incomingCall = incomingCalls.values[i]; const file = this.findFile(incomingCall.from.file); text += `${prefix}│ ╭ from:\n`; - text += this.formatCallHierarchyItem(file, incomingCall.from, CallHierarchyItemDirection.Incoming, seen, `${prefix}│ │ `); + text += this.formatCallHierarchyItem( + file, + incomingCall.from, + CallHierarchyItemDirection.Incoming, + seen, + `${prefix}│ │ `, + ); text += `${prefix}│ ├ fromSpans:\n`; text += this.formatCallHierarchyItemSpans( file, incomingCall.fromSpans, `${prefix}│ │ `, - i < incomingCalls.values.length - 1 ? `${prefix}│ ╰ ` : - outgoingCalls.result !== "skip" ? `${prefix}│ ╰ ` : - `${trailingPrefix}╰ ╰ `, + i < incomingCalls.values.length - 1 ? `${prefix}│ ╰ ` + : outgoingCalls.result !== "skip" ? `${prefix}│ ╰ ` + : `${trailingPrefix}╰ ╰ `, ); } } @@ -4219,14 +5218,20 @@ export class TestState { for (let i = 0; i < outgoingCalls.values.length; i++) { const outgoingCall = outgoingCalls.values[i]; text += `${prefix}│ ╭ to:\n`; - text += this.formatCallHierarchyItem(this.findFile(outgoingCall.to.file), outgoingCall.to, CallHierarchyItemDirection.Outgoing, seen, `${prefix}│ │ `); + text += this.formatCallHierarchyItem( + this.findFile(outgoingCall.to.file), + outgoingCall.to, + CallHierarchyItemDirection.Outgoing, + seen, + `${prefix}│ │ `, + ); text += `${prefix}│ ├ fromSpans:\n`; text += this.formatCallHierarchyItemSpans( file, outgoingCall.fromSpans, `${prefix}│ │ `, - i < outgoingCalls.values.length - 1 ? `${prefix}│ ╰ ` : - `${trailingPrefix}╰ ╰ `, + i < outgoingCalls.values.length - 1 ? `${prefix}│ ╰ ` + : `${trailingPrefix}╰ ╰ `, ); } } @@ -4238,21 +5243,35 @@ export class TestState { let text = ""; if (callHierarchyItem) { const file = this.findFile(callHierarchyItem.file); - text += this.formatCallHierarchyItem(file, callHierarchyItem, CallHierarchyItemDirection.Root, new Map(), ""); + text += this.formatCallHierarchyItem( + file, + callHierarchyItem, + CallHierarchyItemDirection.Root, + new Map(), + "", + ); } return text; } public baselineCallHierarchy() { const baselineFile = this.getBaselineFileNameForContainingTestFile(".callHierarchy.txt"); - const callHierarchyItem = this.languageService.prepareCallHierarchy(this.activeFile.fileName, this.currentCaretPosition); - const text = callHierarchyItem ? ts.mapOneOrMany(callHierarchyItem, item => this.formatCallHierarchy(item), result => result.join("")) : "none"; + const callHierarchyItem = this.languageService.prepareCallHierarchy( + this.activeFile.fileName, + this.currentCaretPosition, + ); + const text = callHierarchyItem + ? ts.mapOneOrMany(callHierarchyItem, item => this.formatCallHierarchy(item), result => result.join("")) + : "none"; Harness.Baseline.runBaseline(baselineFile, text); } private getLineContent(index: number) { const text = this.getFileContent(this.activeFile.fileName); - const pos = this.languageServiceAdapterHost.lineAndCharacterToPosition(this.activeFile.fileName, { line: index, character: 0 }); + const pos = this.languageServiceAdapterHost.lineAndCharacterToPosition(this.activeFile.fileName, { + line: index, + character: 0, + }); let startPos = pos, endPos = pos; while (startPos > 0) { @@ -4291,7 +5310,9 @@ export class TestState { if (typeof indexOrName === "number") { const index = indexOrName; if (index >= this.testData.files.length) { - throw new Error(`File index (${index}) in openFile was out of range. There are only ${this.testData.files.length} files in this test.`); + throw new Error( + `File index (${index}) in openFile was out of range. There are only ${this.testData.files.length} files in this test.`, + ); } else { return this.testData.files[index]; @@ -4300,7 +5321,11 @@ export class TestState { else if (ts.isString(indexOrName)) { const { file, availableNames } = this.tryFindFileWorker(indexOrName); if (!file) { - throw new Error(`No test file named "${indexOrName}" exists. Available file names are: ${availableNames.join(", ")}`); + throw new Error( + `No test file named "${indexOrName}" exists. Available file names are: ${ + availableNames.join(", ") + }`, + ); } return file; } @@ -4309,7 +5334,9 @@ export class TestState { } } - private tryFindFileWorker(name: string): { readonly file: FourSlashFile | undefined; readonly availableNames: readonly string[]; } { + private tryFindFileWorker( + name: string, + ): { readonly file: FourSlashFile | undefined; readonly availableNames: readonly string[]; } { name = ts.normalizePath(name); // names are stored in the compiler with this relative path, this allows people to use goTo.file on just the fileName name = name.indexOf("/") === -1 ? (this.basePath + "/" + name) : name; @@ -4339,7 +5366,11 @@ export class TestState { public getMarkerByName(markerName: string) { const markerPos = this.testData.markerPositions.get(markerName); if (markerPos === undefined) { - throw new Error(`Unknown marker "${markerName}" Available markers: ${this.getMarkerNames().map(m => '"' + m + '"').join(", ")}`); + throw new Error( + `Unknown marker "${markerName}" Available markers: ${ + this.getMarkerNames().map(m => '"' + m + '"').join(", ") + }`, + ); } else { return markerPos; @@ -4354,9 +5385,16 @@ export class TestState { this.cancellationToken.resetCancelled(); } - public getEditsForFileRename({ oldPath, newPath, newFileContents, preferences }: FourSlashInterface.GetEditsForFileRenameOptions): void { + public getEditsForFileRename( + { oldPath, newPath, newFileContents, preferences }: FourSlashInterface.GetEditsForFileRenameOptions, + ): void { const test = (fileContents: { readonly [fileName: string]: string; }, description: string): void => { - const changes = this.languageService.getEditsForFileRename(oldPath, newPath, this.formatCodeSettings, preferences); + const changes = this.languageService.getEditsForFileRename( + oldPath, + newPath, + this.formatCodeSettings, + preferences, + ); this.testNewFileContents(changes, fileContents, description); }; @@ -4366,18 +5404,60 @@ export class TestState { this.languageServiceAdapterHost.renameFileOrDirectory(oldPath, newPath); this.languageService.cleanupSemanticCache(); - const pathUpdater = ts.getPathUpdater(oldPath, newPath, ts.createGetCanonicalFileName(/*useCaseSensitiveFileNames*/ false), /*sourceMapper*/ undefined); + const pathUpdater = ts.getPathUpdater( + oldPath, + newPath, + ts.createGetCanonicalFileName(/*useCaseSensitiveFileNames*/ false), + /*sourceMapper*/ undefined, + ); test(renameKeys(newFileContents, key => pathUpdater(key) || key), "with file moved"); } - private getApplicableRefactorsAtSelection(triggerReason: ts.RefactorTriggerReason = "implicit", kind?: string, preferences = ts.emptyOptions) { - return this.getApplicableRefactorsWorker(this.getSelection(), this.activeFile.fileName, preferences, triggerReason, kind); + private getApplicableRefactorsAtSelection( + triggerReason: ts.RefactorTriggerReason = "implicit", + kind?: string, + preferences = ts.emptyOptions, + ) { + return this.getApplicableRefactorsWorker( + this.getSelection(), + this.activeFile.fileName, + preferences, + triggerReason, + kind, + ); } - private getApplicableRefactors(rangeOrMarker: Range | Marker, preferences = ts.emptyOptions, triggerReason: ts.RefactorTriggerReason = "implicit", kind?: string, includeInteractiveActions?: boolean): readonly ts.ApplicableRefactorInfo[] { - return this.getApplicableRefactorsWorker("position" in rangeOrMarker ? rangeOrMarker.position : rangeOrMarker, rangeOrMarker.fileName, preferences, triggerReason, kind, includeInteractiveActions); // eslint-disable-line local/no-in-operator + private getApplicableRefactors( + rangeOrMarker: Range | Marker, + preferences = ts.emptyOptions, + triggerReason: ts.RefactorTriggerReason = "implicit", + kind?: string, + includeInteractiveActions?: boolean, + ): readonly ts.ApplicableRefactorInfo[] { + return this.getApplicableRefactorsWorker( + "position" in rangeOrMarker ? rangeOrMarker.position : rangeOrMarker, + rangeOrMarker.fileName, + preferences, + triggerReason, + kind, + includeInteractiveActions, + ); // eslint-disable-line local/no-in-operator } - private getApplicableRefactorsWorker(positionOrRange: number | ts.TextRange, fileName: string, preferences = ts.emptyOptions, triggerReason: ts.RefactorTriggerReason, kind?: string, includeInteractiveActions?: boolean): readonly ts.ApplicableRefactorInfo[] { - return this.languageService.getApplicableRefactors(fileName, positionOrRange, preferences, triggerReason, kind, includeInteractiveActions) || ts.emptyArray; + private getApplicableRefactorsWorker( + positionOrRange: number | ts.TextRange, + fileName: string, + preferences = ts.emptyOptions, + triggerReason: ts.RefactorTriggerReason, + kind?: string, + includeInteractiveActions?: boolean, + ): readonly ts.ApplicableRefactorInfo[] { + return this.languageService.getApplicableRefactors( + fileName, + positionOrRange, + preferences, + triggerReason, + kind, + includeInteractiveActions, + ) || ts.emptyArray; } public configurePlugin(pluginName: string, configuration: any): void { @@ -4434,9 +5514,13 @@ export class TestState { } } -function updateTextRangeForTextChanges({ pos, end }: ts.TextRange, textChanges: readonly ts.TextChange[]): ts.TextRange { +function updateTextRangeForTextChanges( + { pos, end }: ts.TextRange, + textChanges: readonly ts.TextChange[], +): ts.TextRange { forEachTextChange(textChanges, change => { - const update = (p: number): number => updatePosition(p, change.span.start, ts.textSpanEnd(change.span), change.newText); + const update = (p: number): number => + updatePosition(p, change.span.start, ts.textSpanEnd(change.span), change.newText); pos = update(pos); end = update(end); }); @@ -4464,7 +5548,10 @@ function updatePosition(position: number, editStart: number, editEnd: number, { return position <= editStart ? position : position < editEnd ? -1 : position + length - +(editEnd - editStart); } -function renameKeys(obj: { readonly [key: string]: T; }, renameKey: (key: string) => string): { readonly [key: string]: T; } { +function renameKeys( + obj: { readonly [key: string]: T; }, + renameKey: (key: string) => string, +): { readonly [key: string]: T; } { const res: { [key: string]: T; } = {}; for (const key in obj) { res[renameKey(key)] = obj[key]; @@ -4477,7 +5564,12 @@ export function runFourSlashTest(basePath: string, testType: FourSlashTestType, runFourSlashTestContent(basePath, testType, content, fileName); } -export function runFourSlashTestContent(basePath: string, testType: FourSlashTestType, content: string, fileName: string): void { +export function runFourSlashTestContent( + basePath: string, + testType: FourSlashTestType, + content: string, + fileName: string, +): void { // Give file paths an absolute path for the virtual file system const absoluteBasePath = ts.combinePaths(Harness.virtualFileSystemRoot, basePath); const absoluteFileName = ts.combinePaths(Harness.virtualFileSystemRoot, fileName); @@ -4486,7 +5578,11 @@ export function runFourSlashTestContent(basePath: string, testType: FourSlashTes const testData = parseTestData(absoluteBasePath, content, absoluteFileName); const state = new TestState(absoluteFileName, absoluteBasePath, testType, testData); const actualFileName = Harness.IO.resolvePath(fileName) || absoluteFileName; - const output = ts.transpileModule(content, { reportDiagnostics: true, fileName: actualFileName, compilerOptions: { target: ts.ScriptTarget.ES2015, inlineSourceMap: true, inlineSources: true } }); + const output = ts.transpileModule(content, { + reportDiagnostics: true, + fileName: actualFileName, + compilerOptions: { target: ts.ScriptTarget.ES2015, inlineSourceMap: true, inlineSources: true }, + }); if (output.diagnostics!.length > 0) { throw new Error(`Syntax error in ${absoluteBasePath}: ${output.diagnostics![0].messageText}`); } @@ -4496,7 +5592,10 @@ export function runFourSlashTestContent(basePath: string, testType: FourSlashTes function runCode(code: string, state: TestState, fileName: string): void { // Compile and execute the test const generatedFile = ts.changeExtension(fileName, ".js"); - const wrappedCode = `(function(ts, test, goTo, config, verify, edit, debug, format, cancellation, classification, completion, verifyOperationIsCancelled, ignoreInterpolations) {${code}\n//# sourceURL=${ts.getBaseFileName(generatedFile)}\n})`; + const wrappedCode = + `(function(ts, test, goTo, config, verify, edit, debug, format, cancellation, classification, completion, verifyOperationIsCancelled, ignoreInterpolations) {${code}\n//# sourceURL=${ + ts.getBaseFileName(generatedFile) + }\n})`; type SourceMapSupportModule = typeof import("source-map-support") & { // TODO(rbuckton): This is missing from the DT definitions and needs to be added. @@ -4515,8 +5614,8 @@ function runCode(code: string, state: TestState, fileName: string): void { sourceMapSupportModule?.install({ retrieveFile: path => { - return path === generatedFile ? wrappedCode : - undefined!; + return path === generatedFile ? wrappedCode + : undefined!; }, }); @@ -4531,7 +5630,21 @@ function runCode(code: string, state: TestState, fileName: string): void { const cancellation = new FourSlashInterface.Cancellation(state); // eslint-disable-next-line no-eval const f = (0, eval)(wrappedCode); - f(ts, test, goTo, config, verify, edit, debug, format, cancellation, FourSlashInterface.classification, FourSlashInterface.Completion, verifyOperationIsCancelled, ignoreInterpolations); + f( + ts, + test, + goTo, + config, + verify, + edit, + debug, + format, + cancellation, + FourSlashInterface.classification, + FourSlashInterface.Completion, + verifyOperationIsCancelled, + ignoreInterpolations, + ); } catch (err) { // ensure 'source-map-support' is triggered while we still have the handler attached by accessing `error.stack`. @@ -4710,7 +5823,13 @@ function reportError(fileName: string, line: number, col: number, message: strin throw new Error(errorMessage); } -function recordObjectMarker(fileName: string, location: LocationInformation, text: string, markerMap: Map, markers: Marker[]): Marker | undefined { +function recordObjectMarker( + fileName: string, + location: LocationInformation, + text: string, + markerMap: Map, + markers: Marker[], +): Marker | undefined { let markerValue; try { // Attempt to parse the marker value as JSON @@ -4740,7 +5859,13 @@ function recordObjectMarker(fileName: string, location: LocationInformation, tex return marker; } -function recordMarker(fileName: string, location: LocationInformation, name: string, markerMap: Map, markers: Marker[]): Marker | undefined { +function recordMarker( + fileName: string, + location: LocationInformation, + name: string, + markerMap: Map, + markers: Marker[], +): Marker | undefined { const marker: Marker = { fileName, position: location.position, @@ -4758,7 +5883,13 @@ function recordMarker(fileName: string, location: LocationInformation, name: str } } -function parseFileContent(content: string, fileName: string, markerMap: Map, markers: Marker[], ranges: Range[]): FourSlashFile { +function parseFileContent( + content: string, + fileName: string, + markerMap: Map, + markers: Marker[], + ranges: Range[], +): FourSlashFile { content = chompLeadingSpace(content); // Any slash-star comment with a character not in this string is not a marker. @@ -4790,7 +5921,11 @@ function parseFileContent(content: string, fileName: string, markerMap: Map { - output = output + content.substr(lastNormalCharPosition, lastSafeCharIndex === undefined ? undefined : lastSafeCharIndex - lastNormalCharPosition); + output = output + + content.substr( + lastNormalCharPosition, + lastSafeCharIndex === undefined ? undefined : lastSafeCharIndex - lastNormalCharPosition, + ); }; if (content.length > 0) { @@ -4860,7 +5995,13 @@ function parseFileContent(content: string, fileName: string, markerMap: Map 0) { openRanges[openRanges.length - 1].marker = marker; @@ -4996,7 +6137,9 @@ function displayExpectedAndActualString(expected: string, actual: string, quoted const actualMsg = "\x1b[1mActual\x1b[0m\x1b[31m"; const expectedString = quoted ? '"' + expected + '"' : expected; const actualString = quoted ? '"' + actual + '"' : actual; - return `\n${expectMsg}:\n${expectedString}\n\n${actualMsg}:\n${highlightDifferenceBetweenStrings(expected, actualString)}`; + return `\n${expectMsg}:\n${expectedString}\n\n${actualMsg}:\n${ + highlightDifferenceBetweenStrings(expected, actualString) + }`; } function templateToRegExp(template: string) { @@ -5058,7 +6201,10 @@ function getRangeOfIdentifierTouchingPosition(content: string, position: number) const scanner = ts.createScanner(ts.ScriptTarget.Latest, /*skipTrivia*/ true, ts.LanguageVariant.Standard, content); while (scanner.scan() !== ts.SyntaxKind.EndOfFileToken) { const tokenFullStart = scanner.getTokenFullStart(); - if (scanner.getToken() === ts.SyntaxKind.Identifier && tokenFullStart <= position && scanner.getTokenEnd() >= position) { + if ( + scanner.getToken() === ts.SyntaxKind.Identifier && tokenFullStart <= position + && scanner.getTokenEnd() >= position + ) { return { pos: tokenFullStart, end: scanner.getTokenEnd() }; } if (tokenFullStart > position) { diff --git a/src/harness/fourslashInterfaceImpl.ts b/src/harness/fourslashInterfaceImpl.ts index 6a15ca0a3ff09..81ac862dccb19 100644 --- a/src/harness/fourslashInterfaceImpl.ts +++ b/src/harness/fourslashInterfaceImpl.ts @@ -75,7 +75,10 @@ export class GoTo { public eachMarker(markers: readonly string[], action: (marker: FourSlash.Marker, index: number) => void): void; public eachMarker(action: (marker: FourSlash.Marker, index: number) => void): void; - public eachMarker(a: readonly string[] | ((marker: FourSlash.Marker, index: number) => void), b?: (marker: FourSlash.Marker, index: number) => void): void { + public eachMarker( + a: readonly string[] | ((marker: FourSlash.Marker, index: number) => void), + b?: (marker: FourSlash.Marker, index: number) => void, + ): void { const markers = typeof a === "function" ? this.state.getMarkers() : a.map(m => this.state.getMarkerByName(m)); this.state.goToEachMarker(markers, typeof a === "function" ? a : b!); } @@ -140,11 +143,17 @@ export class VerifyNegatable { this.state.verifySignatureHelpPresence(/*expectPresent*/ false, /*triggerReason*/ undefined, markers); } - public noSignatureHelpForTriggerReason(reason: ts.SignatureHelpTriggerReason, ...markers: (string | FourSlash.Marker)[]): void { + public noSignatureHelpForTriggerReason( + reason: ts.SignatureHelpTriggerReason, + ...markers: (string | FourSlash.Marker)[] + ): void { this.state.verifySignatureHelpPresence(/*expectPresent*/ false, reason, markers); } - public signatureHelpPresentForTriggerReason(reason: ts.SignatureHelpTriggerReason, ...markers: (string | FourSlash.Marker)[]): void { + public signatureHelpPresentForTriggerReason( + reason: ts.SignatureHelpTriggerReason, + ...markers: (string | FourSlash.Marker)[] + ): void { this.state.verifySignatureHelpPresence(/*expectPresent*/ true, reason, markers); } @@ -216,7 +225,11 @@ export class VerifyNegatable { this.state.verifyRefactorAvailable(this.negative, "implicit", name, actionName, actionDescription); } - public refactorAvailableForTriggerReason(triggerReason: ts.RefactorTriggerReason, name: string, actionName?: string) { + public refactorAvailableForTriggerReason( + triggerReason: ts.RefactorTriggerReason, + name: string, + actionName?: string, + ) { this.state.verifyRefactorAvailable(this.negative, triggerReason, name, actionName); } @@ -264,11 +277,20 @@ export class Verify extends VerifyNegatable { this.state.baselineInlayHints(span, preference); } - public quickInfoIs(expectedText: string, expectedDocumentation?: string, expectedTags?: { name: string; text: string; }[]) { + public quickInfoIs( + expectedText: string, + expectedDocumentation?: string, + expectedTags?: { name: string; text: string; }[], + ) { this.state.verifyQuickInfoString(expectedText, expectedDocumentation, expectedTags); } - public quickInfoAt(markerName: string | FourSlash.Range, expectedText: string, expectedDocumentation?: string, expectedTags?: { name: string; text: string; }[]) { + public quickInfoAt( + markerName: string | FourSlash.Range, + expectedText: string, + expectedDocumentation?: string, + expectedTags?: { name: string; text: string; }[], + ) { this.state.verifyQuickInfoAt(markerName, expectedText, expectedDocumentation, expectedTags); } @@ -284,7 +306,13 @@ export class Verify extends VerifyNegatable { this.state.verifyIndentationAtCurrentPosition(numberOfSpaces); } - public indentationAtPositionIs(fileName: string, position: number, numberOfSpaces: number, indentStyle = ts.IndentStyle.Smart, baseIndentSize = 0) { + public indentationAtPositionIs( + fileName: string, + position: number, + numberOfSpaces: number, + indentStyle = ts.IndentStyle.Smart, + baseIndentSize = 0, + ) { this.state.verifyIndentationAtPosition(fileName, position, numberOfSpaces, indentStyle, baseIndentSize); } @@ -389,11 +417,17 @@ export class Verify extends VerifyNegatable { this.state.verifyBaselineCommands({ type: "goToImplementation", rangeText }); } - public baselineDocumentHighlights(markerOrRange?: ArrayOrSingle, options?: VerifyDocumentHighlightsOptions) { + public baselineDocumentHighlights( + markerOrRange?: ArrayOrSingle, + options?: VerifyDocumentHighlightsOptions, + ) { this.state.verifyBaselineCommands({ type: "documentHighlights", markerOrRange, options }); } - public baselineDocumentHighlightsAtRangesWithText(rangeText?: ArrayOrSingle, options?: VerifyDocumentHighlightsOptions) { + public baselineDocumentHighlightsAtRangesWithText( + rangeText?: ArrayOrSingle, + options?: VerifyDocumentHighlightsOptions, + ) { this.state.verifyBaselineCommands({ type: "documentHighlights", rangeText, options }); } @@ -473,9 +507,17 @@ export class Verify extends VerifyNegatable { this.state.verifyNoMatchingBracePosition(bracePosition); } - public docCommentTemplateAt(marker: string | FourSlash.Marker, expectedOffset: number, expectedText: string, options?: ts.DocCommentTemplateOptions) { + public docCommentTemplateAt( + marker: string | FourSlash.Marker, + expectedOffset: number, + expectedText: string, + options?: ts.DocCommentTemplateOptions, + ) { this.state.goToMarker(marker); - this.state.verifyDocCommentTemplate({ newText: expectedText.replace(/\r?\n/g, ts.testFormatSettings.newLineCharacter!), caretOffset: expectedOffset }, options); + this.state.verifyDocCommentTemplate({ + newText: expectedText.replace(/\r?\n/g, ts.testFormatSettings.newLineCharacter!), + caretOffset: expectedOffset, + }, options); } public noDocCommentTemplateAt(marker: string | FourSlash.Marker) { @@ -483,7 +525,12 @@ export class Verify extends VerifyNegatable { this.state.verifyDocCommentTemplate(/*expected*/ undefined); } - public rangeAfterCodeFix(expectedText: string, includeWhiteSpace?: boolean, errorCode?: number, index?: number): void { + public rangeAfterCodeFix( + expectedText: string, + includeWhiteSpace?: boolean, + errorCode?: number, + index?: number, + ): void { this.state.verifyRangeAfterCodeFix(expectedText, includeWhiteSpace, errorCode, index); } @@ -491,8 +538,20 @@ export class Verify extends VerifyNegatable { this.state.verifyCodeFixAll(options); } - public fileAfterApplyingRefactorAtMarker(markerName: string, expectedContent: string, refactorNameToApply: string, actionName: string, formattingOptions?: ts.FormatCodeSettings): void { - this.state.verifyFileAfterApplyingRefactorAtMarker(markerName, expectedContent, refactorNameToApply, actionName, formattingOptions); + public fileAfterApplyingRefactorAtMarker( + markerName: string, + expectedContent: string, + refactorNameToApply: string, + actionName: string, + formattingOptions?: ts.FormatCodeSettings, + ): void { + this.state.verifyFileAfterApplyingRefactorAtMarker( + markerName, + expectedContent, + refactorNameToApply, + actionName, + formattingOptions, + ); } public rangeIs(expectedText: string, includeWhiteSpace?: boolean): void { @@ -507,7 +566,11 @@ export class Verify extends VerifyNegatable { this.state.applyCodeActionFromCompletion(markerName, options); } - public importFixAtPosition(expectedTextArray: string[], errorCode?: number, preferences?: ts.UserPreferences): void { + public importFixAtPosition( + expectedTextArray: string[], + errorCode?: number, + preferences?: ts.UserPreferences, + ): void { this.state.verifyImportFixAtPosition(expectedTextArray, errorCode, preferences); } @@ -566,7 +629,15 @@ export class Verify extends VerifyNegatable { expectedRange?: FourSlash.Range, preferences?: ts.UserPreferences, ) { - this.state.verifyRenameInfoSucceeded(displayName, fullDisplayName, kind, kindModifiers, fileToRename, expectedRange, preferences); + this.state.verifyRenameInfoSucceeded( + displayName, + fullDisplayName, + kind, + kindModifiers, + fileToRename, + expectedRange, + preferences, + ); } public renameInfoFailed(message?: string, preferences?: ts.UserPreferences) { @@ -581,7 +652,14 @@ export class Verify extends VerifyNegatable { this.state.verifyBaselineCommands({ type: "findRenameLocations", rangeText, options }); } - public verifyQuickInfoDisplayParts(kind: string, kindModifiers: string, textSpan: FourSlash.TextSpan, displayParts: ts.SymbolDisplayPart[], documentation: ts.SymbolDisplayPart[], tags: ts.JSDocTagInfo[]) { + public verifyQuickInfoDisplayParts( + kind: string, + kindModifiers: string, + textSpan: FourSlash.TextSpan, + displayParts: ts.SymbolDisplayPart[], + documentation: ts.SymbolDisplayPart[], + tags: ts.JSDocTagInfo[], + ) { this.state.verifyQuickInfoDisplayParts(kind, kindModifiers, textSpan, displayParts, documentation, tags); } @@ -782,7 +860,10 @@ export class Format { } public selection(startMarker: string, endMarker: string) { - this.state.formatSelection(this.state.getMarkerByName(startMarker).position, this.state.getMarkerByName(endMarker).position); + this.state.formatSelection( + this.state.getMarkerByName(startMarker).position, + this.state.getMarkerByName(endMarker).position, + ); } public onType(posMarker: string, key: string) { @@ -930,7 +1011,11 @@ export function classification(format: ts.SemanticClassificationFormat) { return getClassification(ts.ClassificationTypeNames.jsxAttributeStringLiteralValue, text, position); } - function getClassification(classificationType: ts.ClassificationTypeNames, text: string, position?: number): Classification { + function getClassification( + classificationType: ts.ClassificationTypeNames, + text: string, + position?: number, + ): Classification { const textSpan = position === undefined ? undefined : { start: position, end: position + text.length }; return { classificationType, text, textSpan }; } @@ -1063,7 +1148,9 @@ export namespace Completion { }); } export const keywordsWithUndefined: readonly ExpectedCompletionEntryObject[] = res; - export const keywords: readonly ExpectedCompletionEntryObject[] = keywordsWithUndefined.filter(k => k.name !== "undefined"); + export const keywords: readonly ExpectedCompletionEntryObject[] = keywordsWithUndefined.filter(k => + k.name !== "undefined" + ); export const typeKeywords: readonly ExpectedCompletionEntryObject[] = [ "any", @@ -1102,7 +1189,10 @@ export namespace Completion { providedByHarness: readonly ExpectedCompletionEntry[], providedByTest: readonly ExpectedCompletionEntry[], ): ExpectedExactCompletionsPlus { - return Object.assign(sorted([...providedByHarness, ...providedByTest]), { plusFunctionName: functionName, plusArgument: providedByTest }); + return Object.assign(sorted([...providedByHarness, ...providedByTest]), { + plusFunctionName: functionName, + plusArgument: providedByTest, + }); } export function typeKeywordsPlus(plus: readonly ExpectedCompletionEntry[]) { @@ -1245,7 +1335,9 @@ export namespace Completion { export const typeAssertionKeywords: readonly ExpectedCompletionEntry[] = globalTypesPlus([keywordEntry("const")]); - function getInJsKeywords(keywords: readonly ExpectedCompletionEntryObject[]): readonly ExpectedCompletionEntryObject[] { + function getInJsKeywords( + keywords: readonly ExpectedCompletionEntryObject[], + ): readonly ExpectedCompletionEntryObject[] { return keywords.filter(keyword => { switch (keyword.name) { case "enum": @@ -1300,7 +1392,13 @@ export namespace Completion { export const classElementInJsKeywords = getInJsKeywords(classElementKeywords); - export const constructorParameterKeywords: readonly ExpectedCompletionEntryObject[] = ["override", "private", "protected", "public", "readonly"].map((name): ExpectedCompletionEntryObject => ({ + export const constructorParameterKeywords: readonly ExpectedCompletionEntryObject[] = [ + "override", + "private", + "protected", + "public", + "readonly", + ].map((name): ExpectedCompletionEntryObject => ({ name, kind: "keyword", sortText: SortText.GlobalsOrKeywords, @@ -1547,7 +1645,10 @@ export namespace Completion { sortText: SortText.GlobalsOrKeywords, }; // TODO: many of these are inappropriate to always provide - export const globalsInsideFunction = (plus: readonly ExpectedCompletionEntry[], options?: { noLib?: boolean; }): readonly ExpectedCompletionEntry[] => + export const globalsInsideFunction = ( + plus: readonly ExpectedCompletionEntry[], + options?: { noLib?: boolean; }, + ): readonly ExpectedCompletionEntry[] => [ { name: "arguments", kind: "local var" }, ...plus, @@ -1560,7 +1661,10 @@ export namespace Completion { const globalInJsKeywordsInsideFunction = getInJsKeywords(globalKeywordsInsideFunction); // TODO: many of these are inappropriate to always provide - export const globalsInJsInsideFunction = (plus: readonly ExpectedCompletionEntry[], options?: { noLib?: boolean; }): readonly ExpectedCompletionEntry[] => + export const globalsInJsInsideFunction = ( + plus: readonly ExpectedCompletionEntry[], + options?: { noLib?: boolean; }, + ): readonly ExpectedCompletionEntry[] => [ { name: "arguments", kind: "local var" }, globalThisEntry, @@ -1922,7 +2026,11 @@ export type RenameLocationsOptions = readonly RenameLocationOptions[] | { export interface DiagnosticIgnoredInterpolations { template: string; } -export type RenameLocationOptions = FourSlash.Range | { readonly range: FourSlash.Range; readonly prefixText?: string; readonly suffixText?: string; }; +export type RenameLocationOptions = FourSlash.Range | { + readonly range: FourSlash.Range; + readonly prefixText?: string; + readonly suffixText?: string; +}; export interface RenameOptions { readonly findInStrings?: boolean; readonly findInComments?: boolean; @@ -1930,7 +2038,13 @@ export interface RenameOptions { readonly quotePreference?: "auto" | "double" | "single"; } export type BaselineCommandWithMarkerOrRange = { - type: "findAllReferences" | "goToDefinition" | "getDefinitionAtPosition" | "goToSourceDefinition" | "goToType" | "goToImplementation"; + type: + | "findAllReferences" + | "goToDefinition" + | "getDefinitionAtPosition" + | "goToSourceDefinition" + | "goToType" + | "goToImplementation"; markerOrRange?: ArrayOrSingle; rangeText?: ArrayOrSingle; } | { diff --git a/src/harness/harnessIO.ts b/src/harness/harnessIO.ts index 880a591fb2780..4543212092780 100644 --- a/src/harness/harnessIO.ts +++ b/src/harness/harnessIO.ts @@ -32,7 +32,13 @@ export interface IO { getExecutingFilePath(): string; getWorkspaceRoot(): string; exit(exitCode?: number): void; - readDirectory(path: string, extension?: readonly string[], exclude?: readonly string[], include?: readonly string[], depth?: number): readonly string[]; + readDirectory( + path: string, + extension?: readonly string[], + exclude?: readonly string[], + include?: readonly string[], + depth?: number, + ): readonly string[]; getAccessibleFileSystemEntries(dirname: string): ts.FileSystemEntries; tryEnableSourceMapsForHost?(): void; getEnvironmentVariable?(name: string): string; @@ -108,7 +114,9 @@ function createNodeIO(): IO { function getAccessibleFileSystemEntries(dirname: string): ts.FileSystemEntries { try { - const entries: string[] = fs.readdirSync(dirname || ".").sort(ts.sys.useCaseSensitiveFileNames ? ts.compareStringsCaseSensitive : ts.compareStringsCaseInsensitive); + const entries: string[] = fs.readdirSync(dirname || ".").sort( + ts.sys.useCaseSensitiveFileNames ? ts.compareStringsCaseSensitive : ts.compareStringsCaseInsensitive, + ); const files: string[] = []; const directories: string[] = []; for (const entry of entries) { @@ -169,7 +177,8 @@ function createNodeIO(): IO { getExecutingFilePath: () => ts.sys.getExecutingFilePath(), getWorkspaceRoot: () => workspaceRoot, exit: exitCode => ts.sys.exit(exitCode), - readDirectory: (path, extension, exclude, include, depth) => ts.sys.readDirectory(path, extension, exclude, include, depth), + readDirectory: (path, extension, exclude, include, depth) => + ts.sys.readDirectory(path, extension, exclude, include, depth), getAccessibleFileSystemEntries, tryEnableSourceMapsForHost: () => ts.sys.tryEnableSourceMapsForHost && ts.sys.tryEnableSourceMapsForHost(), getMemoryUsage: () => ts.sys.getMemoryUsage && ts.sys.getMemoryUsage(), @@ -249,7 +258,12 @@ export namespace Compiler { const shouldAssertInvariants = !lightMode; // Only set the parent nodes if we're asserting invariants. We don't need them otherwise. - const result = ts.createSourceFile(fileName, sourceText, languageVersion, /*setParentNodes:*/ shouldAssertInvariants); + const result = ts.createSourceFile( + fileName, + sourceText, + languageVersion, + /*setParentNodes:*/ shouldAssertInvariants, + ); if (shouldAssertInvariants) { Utils.assertInvariants(result, /*parent:*/ undefined); @@ -271,13 +285,24 @@ export namespace Compiler { if (!libFileNameSourceFileMap) { libFileNameSourceFileMap = new Map(Object.entries({ - [defaultLibFileName]: createSourceFileAndAssertInvariants(defaultLibFileName, IO.readFile(libFolder + "lib.es5.d.ts")!, /*languageVersion*/ ts.ScriptTarget.Latest), + [defaultLibFileName]: createSourceFileAndAssertInvariants( + defaultLibFileName, + IO.readFile(libFolder + "lib.es5.d.ts")!, + /*languageVersion*/ ts.ScriptTarget.Latest, + ), })); } let sourceFile = libFileNameSourceFileMap.get(fileName); if (!sourceFile) { - libFileNameSourceFileMap.set(fileName, sourceFile = createSourceFileAndAssertInvariants(fileName, IO.readFile(libFolder + fileName)!, ts.ScriptTarget.Latest)); + libFileNameSourceFileMap.set( + fileName, + sourceFile = createSourceFileAndAssertInvariants( + fileName, + IO.readFile(libFolder + fileName)!, + ts.ScriptTarget.Latest, + ), + ); } return sourceFile; } @@ -344,7 +369,10 @@ export namespace Compiler { return optionsIndex.get(name.toLowerCase()); } - export function setCompilerOptionsFromHarnessSetting(settings: TestCaseParser.CompilerSettings, options: ts.CompilerOptions & HarnessOptions): void { + export function setCompilerOptionsFromHarnessSetting( + settings: TestCaseParser.CompilerSettings, + options: ts.CompilerOptions & HarnessOptions, + ): void { for (const name in settings) { if (ts.hasProperty(settings, name)) { const value = settings[name]; @@ -406,11 +434,13 @@ export namespace Compiler { currentDirectory: string | undefined, symlinks?: vfs.FileSet, ): compiler.CompilationResult { - const options: ts.CompilerOptions & HarnessOptions = compilerOptions ? ts.cloneCompilerOptions(compilerOptions) : { noResolve: false }; + const options: ts.CompilerOptions & HarnessOptions = compilerOptions ? ts.cloneCompilerOptions(compilerOptions) + : { noResolve: false }; options.target = ts.getEmitScriptTarget(options); options.newLine = options.newLine || ts.NewLineKind.CarriageReturnLineFeed; options.noErrorTruncation = true; - options.skipDefaultLibCheck = typeof options.skipDefaultLibCheck === "undefined" ? true : options.skipDefaultLibCheck; + options.skipDefaultLibCheck = typeof options.skipDefaultLibCheck === "undefined" ? true + : options.skipDefaultLibCheck; if (typeof currentDirectory === "undefined") { currentDirectory = vfs.srcFolder; @@ -426,10 +456,13 @@ export namespace Compiler { } } - const useCaseSensitiveFileNames = options.useCaseSensitiveFileNames !== undefined ? options.useCaseSensitiveFileNames : true; + const useCaseSensitiveFileNames = options.useCaseSensitiveFileNames !== undefined + ? options.useCaseSensitiveFileNames : true; // When a tsconfig is present, root names passed to createProgram should already be absolute const programFileNames = inputFiles - .map(file => options.configFile ? ts.getNormalizedAbsolutePath(file.unitName, currentDirectory) : file.unitName) + .map(file => + options.configFile ? ts.getNormalizedAbsolutePath(file.unitName, currentDirectory) : file.unitName + ) .filter(fileName => !ts.fileExtensionIs(fileName, ts.Extension.Json)); // Files from built\local that are requested by test "@includeBuiltFiles" to be in the context. @@ -451,7 +484,10 @@ export namespace Compiler { fs.apply(symlinks); } - ts.assign(options, ts.convertToOptionsWithAbsolutePaths(options, path => ts.getNormalizedAbsolutePath(path, currentDirectory))); + ts.assign( + options, + ts.convertToOptionsWithAbsolutePaths(options, path => ts.getNormalizedAbsolutePath(path, currentDirectory)), + ); const host = new fakes.CompilerHost(fs, options); const result = compiler.compileFiles(host, programFileNames, options, typeScriptVersion); result.symlinks = symlinks; @@ -482,7 +518,9 @@ export namespace Compiler { } } else if (result.dts.size !== result.getNumberOfJsFiles(/*includeJson*/ false)) { - throw new Error("There were no errors and declFiles generated did not match number of js files generated"); + throw new Error( + "There were no errors and declFiles generated did not match number of js files generated", + ); } } @@ -493,14 +531,23 @@ export namespace Compiler { if (options.declaration && result.diagnostics.length === 0 && result.dts.size > 0) { ts.forEach(inputFiles, file => addDtsFile(file, declInputFiles)); ts.forEach(otherFiles, file => addDtsFile(file, declOtherFiles)); - return { declInputFiles, declOtherFiles, harnessSettings, options, currentDirectory: currentDirectory || harnessSettings.currentDirectory }; + return { + declInputFiles, + declOtherFiles, + harnessSettings, + options, + currentDirectory: currentDirectory || harnessSettings.currentDirectory, + }; } function addDtsFile(file: TestFile, dtsFiles: TestFile[]) { if (vpath.isDeclaration(file.unitName) || vpath.isJson(file.unitName)) { dtsFiles.push(file); } - else if (vpath.isTypeScript(file.unitName) || (vpath.isJavaScript(file.unitName) && ts.getAllowJSCompilerOption(options))) { + else if ( + vpath.isTypeScript(file.unitName) + || (vpath.isJavaScript(file.unitName) && ts.getAllowJSCompilerOption(options)) + ) { const declFile = findResultCodeFile(file.unitName); if (declFile && !findUnit(declFile.file, declInputFiles) && !findUnit(declFile.file, declOtherFiles)) { dtsFiles.push({ @@ -532,7 +579,8 @@ export namespace Compiler { sourceFileName = outFile; } - const dTsFileName = ts.removeFileExtension(sourceFileName) + ts.getDeclarationEmitExtensionForPath(sourceFileName); + const dTsFileName = ts.removeFileExtension(sourceFileName) + + ts.getDeclarationEmitExtensionForPath(sourceFileName); return result.dts.get(dTsFileName); } @@ -541,12 +589,22 @@ export namespace Compiler { } } - export function compileDeclarationFiles(context: DeclarationCompilationContext | undefined, symlinks: vfs.FileSet | undefined) { + export function compileDeclarationFiles( + context: DeclarationCompilationContext | undefined, + symlinks: vfs.FileSet | undefined, + ) { if (!context) { return; } const { declInputFiles, declOtherFiles, harnessSettings, options, currentDirectory } = context; - const output = compileFiles(declInputFiles, declOtherFiles, harnessSettings, options, currentDirectory, symlinks); + const output = compileFiles( + declInputFiles, + declOtherFiles, + harnessSettings, + options, + currentDirectory, + symlinks, + ); return { declInputFiles, declOtherFiles, declResult: output }; } @@ -555,7 +613,11 @@ export namespace Compiler { return (pretty ? ts.formatDiagnosticsWithColorAndContext : ts.formatDiagnostics)(diagnostics, host); } - export function getErrorBaseline(inputFiles: readonly TestFile[], diagnostics: readonly ts.Diagnostic[], pretty?: boolean) { + export function getErrorBaseline( + inputFiles: readonly TestFile[], + diagnostics: readonly ts.Diagnostic[], + pretty?: boolean, + ) { let outputLines = ""; const gen = iterateErrorBaseline(inputFiles, diagnostics, { pretty }); for (const value of gen) { @@ -563,14 +625,25 @@ export namespace Compiler { outputLines += content; } if (pretty) { - outputLines += Utils.removeTestPathPrefixes(ts.getErrorSummaryText(ts.getErrorCountForSummary(diagnostics), ts.getFilesInErrorForSummary(diagnostics), IO.newLine(), { getCurrentDirectory: () => "" })); + outputLines += Utils.removeTestPathPrefixes( + ts.getErrorSummaryText( + ts.getErrorCountForSummary(diagnostics), + ts.getFilesInErrorForSummary(diagnostics), + IO.newLine(), + { getCurrentDirectory: () => "" }, + ), + ); } return outputLines; } export const diagnosticSummaryMarker = "__diagnosticSummary"; export const globalErrorsMarker = "__globalErrors"; - export function* iterateErrorBaseline(inputFiles: readonly TestFile[], diagnostics: readonly ts.Diagnostic[], options?: { pretty?: boolean; caseSensitive?: boolean; currentDirectory?: string; }): IterableIterator<[string, string, number]> { + export function* iterateErrorBaseline( + inputFiles: readonly TestFile[], + diagnostics: readonly ts.Diagnostic[], + options?: { pretty?: boolean; caseSensitive?: boolean; currentDirectory?: string; }, + ): IterableIterator<[string, string, number]> { diagnostics = ts.sort(diagnostics, ts.compareDiagnostics); let outputLines = ""; // Count up all errors that were found in files other than lib.d.ts so we don't miss any @@ -590,7 +663,9 @@ export namespace Compiler { const formatDiagnsoticHost = { getCurrentDirectory: () => options && options.currentDirectory ? options.currentDirectory : "", getNewLine: () => IO.newLine(), - getCanonicalFileName: ts.createGetCanonicalFileName(options && options.caseSensitive !== undefined ? options.caseSensitive : true), + getCanonicalFileName: ts.createGetCanonicalFileName( + options && options.caseSensitive !== undefined ? options.caseSensitive : true, + ), }; function outputErrorText(error: ts.Diagnostic) { @@ -603,12 +678,17 @@ export namespace Compiler { .map(s => "!!! " + ts.diagnosticCategoryName(error) + " TS" + error.code + ": " + s); if (error.relatedInformation) { for (const info of error.relatedInformation) { - let location = info.file ? " " + ts.formatLocation(info.file, info.start!, formatDiagnsoticHost, ts.identity) : ""; + let location = info.file + ? " " + ts.formatLocation(info.file, info.start!, formatDiagnsoticHost, ts.identity) : ""; location = Utils.removeTestPathPrefixes(location); if (location && isDefaultLibraryFile(info.file!.fileName)) { location = location.replace(/(lib(?:.*)\.d\.ts):\d+:\d+/i, "$1:--:--"); } - errLines.push(`!!! related TS${info.code}${location}: ${ts.flattenDiagnosticMessageText(info.messageText, IO.newLine())}`); + errLines.push( + `!!! related TS${info.code}${location}: ${ + ts.flattenDiagnosticMessageText(info.messageText, IO.newLine()) + }`, + ); } } errLines.forEach(e => outputLines += newLine() + e); @@ -620,7 +700,9 @@ export namespace Compiler { // Similarly for tsconfig, which may be in the input files and contain errors. // 'totalErrorsReportedInNonLibraryNonTsconfigFiles + numLibraryDiagnostics + numTsconfigDiagnostics, diagnostics.length - if (!error.file || !isDefaultLibraryFile(error.file.fileName) && !vpath.isTsConfigFile(error.file.fileName)) { + if ( + !error.file || !isDefaultLibraryFile(error.file.fileName) && !vpath.isTsConfigFile(error.file.fileName) + ) { totalErrorsReportedInNonLibraryNonTsconfigFiles++; } } @@ -644,11 +726,18 @@ export namespace Compiler { // Filter down to the errors in the file const fileErrors = diagnostics.filter((e): e is ts.DiagnosticWithLocation => { const errFn = e.file; - return !!errFn && ts.comparePaths(Utils.removeTestPathPrefixes(errFn.fileName), Utils.removeTestPathPrefixes(inputFile.unitName), options && options.currentDirectory || "", !(options && options.caseSensitive)) === ts.Comparison.EqualTo; + return !!errFn + && ts.comparePaths( + Utils.removeTestPathPrefixes(errFn.fileName), + Utils.removeTestPathPrefixes(inputFile.unitName), + options && options.currentDirectory || "", + !(options && options.caseSensitive), + ) === ts.Comparison.EqualTo; }); // Header - outputLines += newLine() + "==== " + Utils.removeTestPathPrefixes(inputFile.unitName) + " (" + fileErrors.length + " errors) ===="; + outputLines += newLine() + "==== " + Utils.removeTestPathPrefixes(inputFile.unitName) + " (" + + fileErrors.length + " errors) ===="; // Make sure we emit something for every error let markedErrorCount = 0; @@ -690,7 +779,8 @@ export namespace Compiler { // Calculate the start of the squiggle const squiggleStart = Math.max(0, relativeOffset); // TODO/REVIEW: this doesn't work quite right in the browser if a multi file test has files whose names are just the right length relative to one another - outputLines += newLine() + " " + line.substr(0, squiggleStart).replace(/[^\s]/g, " ") + new Array(Math.min(length, line.length - squiggleStart) + 1).join("~"); + outputLines += newLine() + " " + line.substr(0, squiggleStart).replace(/[^\s]/g, " ") + + new Array(Math.min(length, line.length - squiggleStart) + 1).join("~"); // If the error ended here, or we're at the end of the file, emit its message if ((lineIndex === lines.length - 1) || nextLineStart > end) { @@ -719,7 +809,8 @@ export namespace Compiler { } const numLibraryDiagnostics = ts.countWhere(diagnostics, diagnostic => { - return !!diagnostic.file && (isDefaultLibraryFile(diagnostic.file.fileName) || isBuiltFile(diagnostic.file.fileName)); + return !!diagnostic.file + && (isDefaultLibraryFile(diagnostic.file.fileName) || isBuiltFile(diagnostic.file.fileName)); }); const numTsconfigDiagnostics = ts.countWhere(diagnostics, diagnostic => { @@ -727,14 +818,36 @@ export namespace Compiler { }); // Verify we didn't miss any errors in total - assert.equal(totalErrorsReportedInNonLibraryNonTsconfigFiles + numLibraryDiagnostics + numTsconfigDiagnostics, diagnostics.length, "total number of errors"); + assert.equal( + totalErrorsReportedInNonLibraryNonTsconfigFiles + numLibraryDiagnostics + numTsconfigDiagnostics, + diagnostics.length, + "total number of errors", + ); } - export function doErrorBaseline(baselinePath: string, inputFiles: readonly TestFile[], errors: readonly ts.Diagnostic[], pretty?: boolean) { - Baseline.runBaseline(baselinePath.replace(/\.tsx?$/, ".errors.txt"), !errors || (errors.length === 0) ? null : getErrorBaseline(inputFiles, errors, pretty)); // eslint-disable-line no-null/no-null + export function doErrorBaseline( + baselinePath: string, + inputFiles: readonly TestFile[], + errors: readonly ts.Diagnostic[], + pretty?: boolean, + ) { + Baseline.runBaseline( + baselinePath.replace(/\.tsx?$/, ".errors.txt"), + !errors || (errors.length === 0) ? null : getErrorBaseline(inputFiles, errors, pretty), + ); // eslint-disable-line no-null/no-null } - export function doTypeAndSymbolBaseline(baselinePath: string, header: string, program: ts.Program, allFiles: { unitName: string; content: string; }[], opts?: Baseline.BaselineOptions, multifile?: boolean, skipTypeBaselines?: boolean, skipSymbolBaselines?: boolean, hasErrorBaseline?: boolean) { + export function doTypeAndSymbolBaseline( + baselinePath: string, + header: string, + program: ts.Program, + allFiles: { unitName: string; content: string; }[], + opts?: Baseline.BaselineOptions, + multifile?: boolean, + skipTypeBaselines?: boolean, + skipSymbolBaselines?: boolean, + hasErrorBaseline?: boolean, + ) { // The full walker simulates the types that you would get from doing a full // compile. The pull walker simulates the types you get when you just do // a type query for a random node (like how the LS would do it). Most of the @@ -788,16 +901,23 @@ export namespace Compiler { // When calling this function from rwc-runner, the baselinePath will have no extension. // As rwc test- file is stored in json which ".json" will get stripped off. // When calling this function from compiler-runner, the baselinePath will then has either ".ts" or ".tsx" extension - const outputFileName = ts.endsWith(baselinePath, ts.Extension.Ts) || ts.endsWith(baselinePath, ts.Extension.Tsx) ? - baselinePath.replace(/\.tsx?/, "") : baselinePath; + const outputFileName = + ts.endsWith(baselinePath, ts.Extension.Ts) || ts.endsWith(baselinePath, ts.Extension.Tsx) + ? baselinePath.replace(/\.tsx?/, "") : baselinePath; if (!multifile) { - const fullBaseLine = generateBaseLine(isSymbolBaseLine, isSymbolBaseLine ? skipSymbolBaselines : skipTypeBaselines); + const fullBaseLine = generateBaseLine( + isSymbolBaseLine, + isSymbolBaseLine ? skipSymbolBaselines : skipTypeBaselines, + ); Baseline.runBaseline(outputFileName + fullExtension, fullBaseLine, opts); } else { Baseline.runMultifileBaseline(outputFileName, fullExtension, () => { - return iterateBaseLine(isSymbolBaseLine, isSymbolBaseLine ? skipSymbolBaselines : skipTypeBaselines); + return iterateBaseLine( + isSymbolBaseLine, + isSymbolBaseLine ? skipSymbolBaselines : skipTypeBaselines, + ); }, opts); } } @@ -812,7 +932,10 @@ export namespace Compiler { return result ? (`//// [${header}] ////\r\n\r\n` + result) : null; // eslint-disable-line no-null/no-null } - function* iterateBaseLine(isSymbolBaseline: boolean, skipBaseline?: boolean): IterableIterator<[string, string]> { + function* iterateBaseLine( + isSymbolBaseline: boolean, + skipBaseline?: boolean, + ): IterableIterator<[string, string]> { if (skipBaseline) { return; } @@ -822,7 +945,8 @@ export namespace Compiler { const { unitName } = file; let typeLines = "=== " + unitName + " ===\r\n"; const codeLines = ts.flatMap(file.content.split(/\r?\n/g), e => e.split(/[\r\u2028\u2029]/g)); - const gen: IterableIterator = isSymbolBaseline ? fullWalker.getSymbols(unitName) : fullWalker.getTypes(unitName); + const gen: IterableIterator = isSymbolBaseline ? fullWalker.getSymbols(unitName) + : fullWalker.getTypes(unitName); let lastIndexWritten: number | undefined; for (const result of gen) { if (isSymbolBaseline && !result.symbol) { @@ -832,7 +956,11 @@ export namespace Compiler { typeLines += codeLines.slice(0, result.line + 1).join("\r\n") + "\r\n"; } else if (result.line !== lastIndexWritten) { - if (!((lastIndexWritten + 1 < codeLines.length) && (codeLines[lastIndexWritten + 1].match(/^\s*[{|}]\s*$/) || codeLines[lastIndexWritten + 1].trim() === ""))) { + if ( + !((lastIndexWritten + 1 < codeLines.length) + && (codeLines[lastIndexWritten + 1].match(/^\s*[{|}]\s*$/) + || codeLines[lastIndexWritten + 1].trim() === "")) + ) { typeLines += "\r\n"; } typeLines += codeLines.slice(lastIndexWritten + 1, result.line + 1).join("\r\n") + "\r\n"; @@ -845,7 +973,11 @@ export namespace Compiler { lastIndexWritten ??= -1; if (lastIndexWritten + 1 < codeLines.length) { - if (!((lastIndexWritten + 1 < codeLines.length) && (codeLines[lastIndexWritten + 1].match(/^\s*[{|}]\s*$/) || codeLines[lastIndexWritten + 1].trim() === ""))) { + if ( + !((lastIndexWritten + 1 < codeLines.length) + && (codeLines[lastIndexWritten + 1].match(/^\s*[{|}]\s*$/) + || codeLines[lastIndexWritten + 1].trim() === "")) + ) { typeLines += "\r\n"; } typeLines += codeLines.slice(lastIndexWritten + 1).join("\r\n"); @@ -856,7 +988,12 @@ export namespace Compiler { } } - export function doSourcemapBaseline(baselinePath: string, options: ts.CompilerOptions, result: compiler.CompilationResult, harnessSettings: TestCaseParser.CompilerSettings) { + export function doSourcemapBaseline( + baselinePath: string, + options: ts.CompilerOptions, + result: compiler.CompilationResult, + harnessSettings: TestCaseParser.CompilerSettings, + ) { const declMaps = ts.getAreDeclarationMapsEnabled(options); if (options.inlineSourceMap) { if (result.maps.size > 0 && !declMaps) { @@ -865,7 +1002,11 @@ export namespace Compiler { return; } else if (options.sourceMap || declMaps) { - if (result.maps.size !== ((options.sourceMap ? result.getNumberOfJsFiles(/*includeJson*/ false) : 0) + (declMaps ? result.getNumberOfJsFiles(/*includeJson*/ true) : 0))) { + if ( + result.maps.size + !== ((options.sourceMap ? result.getNumberOfJsFiles(/*includeJson*/ false) : 0) + + (declMaps ? result.getNumberOfJsFiles(/*includeJson*/ true) : 0)) + ) { throw new Error("Number of sourcemap files should be same as js files."); } @@ -898,12 +1039,27 @@ export namespace Compiler { const anyUnfoundSources = ts.contains(sourceTDs, /*value*/ undefined); if (anyUnfoundSources) return ""; - const hash = "#base64," + ts.map([outputJSFile.text, sourcemap].concat(sourceTDs.map(td => td!.text)), s => ts.convertToBase64(decodeURIComponent(encodeURIComponent(s)))).join(","); + const hash = "#base64," + + ts.map( + [outputJSFile.text, sourcemap].concat(sourceTDs.map(td => td!.text)), + s => ts.convertToBase64(decodeURIComponent(encodeURIComponent(s))), + ).join(","); return "\n//// https://sokra.github.io/source-map-visualization" + hash + "\n"; } - export function doJsEmitBaseline(baselinePath: string, header: string, options: ts.CompilerOptions, result: compiler.CompilationResult, tsConfigFiles: readonly TestFile[], toBeCompiled: readonly TestFile[], otherFiles: readonly TestFile[], harnessSettings: TestCaseParser.CompilerSettings) { - if (!options.noEmit && !options.emitDeclarationOnly && result.js.size === 0 && result.diagnostics.length === 0) { + export function doJsEmitBaseline( + baselinePath: string, + header: string, + options: ts.CompilerOptions, + result: compiler.CompilationResult, + tsConfigFiles: readonly TestFile[], + toBeCompiled: readonly TestFile[], + otherFiles: readonly TestFile[], + harnessSettings: TestCaseParser.CompilerSettings, + ) { + if ( + !options.noEmit && !options.emitDeclarationOnly && result.js.size === 0 && result.diagnostics.length === 0 + ) { throw new Error("Expected at least one js file to be emitted or at least one error to be created."); } @@ -923,7 +1079,13 @@ export namespace Compiler { jsCode += "\r\n"; } if (!result.diagnostics.length && !ts.endsWith(file.file, ts.Extension.Json)) { - const fileParseResult = ts.createSourceFile(file.file, file.text, ts.getEmitScriptTarget(options), /*setParentNodes*/ false, ts.endsWith(file.file, "x") ? ts.ScriptKind.JSX : ts.ScriptKind.JS); + const fileParseResult = ts.createSourceFile( + file.file, + file.text, + ts.getEmitScriptTarget(options), + /*setParentNodes*/ false, + ts.endsWith(file.file, "x") ? ts.ScriptKind.JSX : ts.ScriptKind.JS, + ); if (ts.length(fileParseResult.parseDiagnostics)) { jsCode += getErrorBaseline([file.asTestFile()], fileParseResult.parseDiagnostics); return; @@ -952,15 +1114,25 @@ export namespace Compiler { if (declFileCompilationResult && declFileCompilationResult.declResult.diagnostics.length) { jsCode += "\r\n\r\n//// [DtsFileErrors]\r\n"; jsCode += "\r\n\r\n"; - jsCode += getErrorBaseline(tsConfigFiles.concat(declFileCompilationResult.declInputFiles, declFileCompilationResult.declOtherFiles), declFileCompilationResult.declResult.diagnostics); + jsCode += getErrorBaseline( + tsConfigFiles.concat( + declFileCompilationResult.declInputFiles, + declFileCompilationResult.declOtherFiles, + ), + declFileCompilationResult.declResult.diagnostics, + ); } // eslint-disable-next-line no-null/no-null - Baseline.runBaseline(baselinePath.replace(/\.tsx?/, ts.Extension.Js), jsCode.length > 0 ? tsCode + "\r\n\r\n" + jsCode : null); + Baseline.runBaseline( + baselinePath.replace(/\.tsx?/, ts.Extension.Js), + jsCode.length > 0 ? tsCode + "\r\n\r\n" + jsCode : null, + ); } function fileOutput(file: documents.TextDocument, harnessSettings: TestCaseParser.CompilerSettings): string { - const fileName = harnessSettings.fullEmitPaths ? Utils.removeTestPathPrefixes(file.file) : ts.getBaseFileName(file.file); + const fileName = harnessSettings.fullEmitPaths ? Utils.removeTestPathPrefixes(file.file) + : ts.getBaseFileName(file.file); return "//// [" + fileName + "]\r\n" + Utils.removeTestPathPrefixes(file.text); } @@ -987,7 +1159,10 @@ export namespace Compiler { const dupeCase = new Map(); // Yield them for (const outputFile of files) { - yield [checkDuplicatedFileName(outputFile.file, dupeCase), "/*====== " + outputFile.file + " ======*/\r\n" + Utils.removeByteOrderMark(outputFile.text)]; + yield [ + checkDuplicatedFileName(outputFile.file, dupeCase), + "/*====== " + outputFile.file + " ======*/\r\n" + Utils.removeByteOrderMark(outputFile.text), + ]; } function cleanName(fn: string) { @@ -1011,7 +1186,11 @@ export namespace Compiler { } export function sanitizeTestFilePath(name: string) { - const path = ts.toPath(ts.normalizeSlashes(name.replace(/[\^<>:"|?*%]/g, "_")).replace(/\.\.\//g, "__dotdot/"), "", Utils.canonicalizeForHarness); + const path = ts.toPath( + ts.normalizeSlashes(name.replace(/[\^<>:"|?*%]/g, "_")).replace(/\.\.\//g, "__dotdot/"), + "", + Utils.canonicalizeForHarness, + ); if (ts.startsWith(path, "/")) { return path.substring(1); } @@ -1077,7 +1256,9 @@ function splitVaryBySettingValue(text: string, varyBy: string): string[] | undef for (const exclude of excludes) { const value = values?.get(exclude); let index: number; - while ((index = ts.findIndex(variations, v => v.key === exclude || value !== undefined && v.value === value)) >= 0) { + while ( + (index = ts.findIndex(variations, v => v.key === exclude || value !== undefined && v.value === value)) >= 0 + ) { ts.orderedRemoveItemAt(variations, index); } } @@ -1089,7 +1270,12 @@ function splitVaryBySettingValue(text: string, varyBy: string): string[] | undef return ts.map(variations, v => v.key); } -function computeFileBasedTestConfigurationVariations(configurations: FileBasedTestConfiguration[], variationState: FileBasedTestConfiguration, varyByEntries: [string, string[]][], offset: number) { +function computeFileBasedTestConfigurationVariations( + configurations: FileBasedTestConfiguration[], + variationState: FileBasedTestConfiguration, + varyByEntries: [string, string[]][], + offset: number, +) { if (offset >= varyByEntries.length) { // make a copy of the current variation state configurations.push({ ...variationState }); @@ -1107,7 +1293,10 @@ function computeFileBasedTestConfigurationVariations(configurations: FileBasedTe let booleanVaryByStarSettingValues: Map | undefined; function getVaryByStarSettingValues(varyBy: string): ReadonlyMap | undefined { - const option = ts.forEach(ts.optionDeclarations, decl => ts.equateStringsCaseInsensitive(decl.name, varyBy) ? decl : undefined); + const option = ts.forEach( + ts.optionDeclarations, + decl => ts.equateStringsCaseInsensitive(decl.name, varyBy) ? decl : undefined, + ); if (option) { if (typeof option.type === "object") { return option.type; @@ -1124,7 +1313,10 @@ function getVaryByStarSettingValues(varyBy: string): ReadonlyMap 25) throw new Error(`Provided test options exceeded the maximum number of variations: ${varyBy.map(v => `'@${v}'`).join(", ")}`); + if (variationCount > 25) { + throw new Error( + `Provided test options exceeded the maximum number of variations: ${ + varyBy.map(v => `'@${v}'`).join(", ") + }`, + ); + } varyByEntries.push([varyByKey, entries]); } } @@ -1187,7 +1385,9 @@ export namespace TestCaseParser { if (!linkMetaData) return undefined; if (!symlinks) symlinks = {}; - symlinks[ts.getNormalizedAbsolutePath(linkMetaData[2].trim(), absoluteRootDir)] = new vfs.Symlink(ts.getNormalizedAbsolutePath(linkMetaData[1].trim(), absoluteRootDir)); + symlinks[ts.getNormalizedAbsolutePath(linkMetaData[2].trim(), absoluteRootDir)] = new vfs.Symlink( + ts.getNormalizedAbsolutePath(linkMetaData[1].trim(), absoluteRootDir), + ); return symlinks; } @@ -1211,7 +1411,11 @@ export namespace TestCaseParser { } /** Given a test file containing // @FileName directives, return an array of named units of code to be added to an existing compiler instance */ - export function makeUnitsFromTest(code: string, fileName: string, settings = extractCompilerSettings(code)): TestCaseContent { + export function makeUnitsFromTest( + code: string, + fileName: string, + settings = extractCompilerSettings(code), + ): TestCaseContent { // List of all the subfiles we've parsed out const testUnitData: TestUnitData[] = []; @@ -1293,30 +1497,44 @@ export namespace TestCaseParser { const parseConfigHost: ts.ParseConfigHost = { useCaseSensitiveFileNames: false, readDirectory: (directory, extensions, excludes, includes, depth) => { - return ts.matchFiles(directory, extensions, excludes, includes, /*useCaseSensitiveFileNames*/ false, "", depth, dir => { - const files: string[] = []; - const directories = new Set(); - for (const unit of testUnitData) { - const fileName = ts.getNormalizedAbsolutePath(unit.name, vfs.srcFolder); - if (fileName.toLowerCase().startsWith(dir.toLowerCase())) { - let path = fileName.substring(dir.length); - if (path.startsWith("/")) { - path = path.substring(1); - } - if (path.includes("/")) { - const directoryName = path.substring(0, path.indexOf("/")); - directories.add(directoryName); - } - else { - files.push(path); + return ts.matchFiles( + directory, + extensions, + excludes, + includes, + /*useCaseSensitiveFileNames*/ false, + "", + depth, + dir => { + const files: string[] = []; + const directories = new Set(); + for (const unit of testUnitData) { + const fileName = ts.getNormalizedAbsolutePath(unit.name, vfs.srcFolder); + if (fileName.toLowerCase().startsWith(dir.toLowerCase())) { + let path = fileName.substring(dir.length); + if (path.startsWith("/")) { + path = path.substring(1); + } + if (path.includes("/")) { + const directoryName = path.substring(0, path.indexOf("/")); + directories.add(directoryName); + } + else { + files.push(path); + } } } - } - return { files, directories: ts.arrayFrom(directories) }; - }, ts.identity); + return { files, directories: ts.arrayFrom(directories) }; + }, + ts.identity, + ); }, fileExists: fileName => testUnitData.some(data => data.name.toLowerCase() === fileName.toLowerCase()), - readFile: name => ts.forEach(testUnitData, data => data.name.toLowerCase() === name.toLowerCase() ? data.content : undefined), + readFile: name => + ts.forEach( + testUnitData, + data => data.name.toLowerCase() === name.toLowerCase() ? data.content : undefined, + ), }; // check if project has tsconfig.json in the list of files @@ -1329,7 +1547,13 @@ export namespace TestCaseParser { assert.isTrue(configJson.endOfFileToken !== undefined); const configFileName = ts.getNormalizedAbsolutePath(data.name, vfs.srcFolder); const configDir = ts.getDirectoryPath(configFileName); - tsConfig = ts.parseJsonSourceFileConfigFileContent(configJson, parseConfigHost, configDir, /*existingOptions*/ undefined, configFileName); + tsConfig = ts.parseJsonSourceFileConfigFileContent( + configJson, + parseConfigHost, + configDir, + /*existingOptions*/ undefined, + configFileName, + ); tsConfigFileUnitData = data; // delete entry from the list @@ -1404,7 +1628,13 @@ export namespace Baseline { return { expected, actual }; } - function writeComparison(expected: string, actual: string, relativeFileName: string, actualFileName: string, opts?: BaselineOptions) { + function writeComparison( + expected: string, + actual: string, + relativeFileName: string, + actualFileName: string, + opts?: BaselineOptions, + ) { // For now this is written using TypeScript, because sys is not available when running old test cases. // But we need to move to sys once we have // Creates the directory including its parent if not already present @@ -1441,12 +1671,21 @@ export namespace Baseline { const errorMessage = getBaselineFileChangedErrorMessage(relativeFileName); if (!!require && opts && opts.PrintDiff) { const Diff = require("diff"); - const patch = Diff.createTwoFilesPatch("Expected", "Actual", expected, actual, "The current baseline", "The new version"); + const patch = Diff.createTwoFilesPatch( + "Expected", + "Actual", + expected, + actual, + "The current baseline", + "The new version", + ); throw new Error(`${errorMessage}${ts.ForegroundColorEscapeSequences.Grey}\n\n${patch}`); } else { if (!IO.fileExists(expected)) { - throw new Error(`New baseline created at ${IO.joinPath("tests", "baselines", "local", relativeFileName)}`); + throw new Error( + `New baseline created at ${IO.joinPath("tests", "baselines", "local", relativeFileName)}`, + ); } else { throw new Error(errorMessage); @@ -1468,7 +1707,13 @@ export namespace Baseline { writeComparison(comparison.expected, comparison.actual, relativeFileName, actualFileName, opts); } - export function runMultifileBaseline(relativeFileBase: string, extension: string, generateContent: () => IterableIterator<[string, string, number]> | IterableIterator<[string, string]> | null, opts?: BaselineOptions, referencedExtensions?: string[]): void { + export function runMultifileBaseline( + relativeFileBase: string, + extension: string, + generateContent: () => IterableIterator<[string, string, number]> | IterableIterator<[string, string]> | null, + opts?: BaselineOptions, + referencedExtensions?: string[], + ): void { const gen = generateContent(); const writtenFiles = new Map(); const errors: Error[] = []; @@ -1493,7 +1738,11 @@ export namespace Baseline { const referenceDir = referencePath(relativeFileBase, opts && opts.Baselinefolder, opts && opts.Subfolder); let existing = IO.readDirectory(referenceDir, referencedExtensions || [extension]); - if (extension === ".ts" || referencedExtensions && referencedExtensions.indexOf(".ts") > -1 && referencedExtensions.indexOf(".d.ts") === -1) { + if ( + extension === ".ts" + || referencedExtensions && referencedExtensions.indexOf(".ts") > -1 + && referencedExtensions.indexOf(".d.ts") === -1 + ) { // special-case and filter .d.ts out of .ts results existing = existing.filter(f => !ts.endsWith(f, ".d.ts")); } @@ -1513,14 +1762,23 @@ export namespace Baseline { if (errors.length || missing.length) { let errorMsg = ""; if (errors.length) { - errorMsg += `The baseline for ${relativeFileBase} in ${errors.length} files has changed:${"\n " + errors.slice(0, 5).map(e => e.message).join("\n ") + (errors.length > 5 ? "\n" + ` and ${errors.length - 5} more` : "")}`; + errorMsg += `The baseline for ${relativeFileBase} in ${errors.length} files has changed:${ + "\n " + errors.slice(0, 5).map(e => e.message).join("\n ") + + (errors.length > 5 ? "\n" + ` and ${errors.length - 5} more` : "") + }`; } if (errors.length && missing.length) { errorMsg += "\n"; } if (missing.length) { const writtenFilesArray = ts.arrayFrom(writtenFiles.keys()); - errorMsg += `Baseline missing ${missing.length} files:${"\n " + missing.slice(0, 5).join("\n ") + (missing.length > 5 ? "\n" + ` and ${missing.length - 5} more` : "") + "\n"}Written ${writtenFiles.size} files:${"\n " + writtenFilesArray.slice(0, 5).join("\n ") + (writtenFilesArray.length > 5 ? "\n" + ` and ${writtenFilesArray.length - 5} more` : "")}`; + errorMsg += `Baseline missing ${missing.length} files:${ + "\n " + missing.slice(0, 5).join("\n ") + + (missing.length > 5 ? "\n" + ` and ${missing.length - 5} more` : "") + "\n" + }Written ${writtenFiles.size} files:${ + "\n " + writtenFilesArray.slice(0, 5).join("\n ") + + (writtenFilesArray.length > 5 ? "\n" + ` and ${writtenFilesArray.length - 5} more` : "") + }`; } throw new Error(errorMsg); } @@ -1534,8 +1792,8 @@ export function isDefaultLibraryFile(filePath: string): boolean { } export function isBuiltFile(filePath: string): boolean { - return filePath.indexOf(libFolder) === 0 || - filePath.indexOf(vpath.addTrailingSeparator(vfs.builtFolder)) === 0; + return filePath.indexOf(libFolder) === 0 + || filePath.indexOf(vpath.addTrailingSeparator(vfs.builtFolder)) === 0; } export function getDefaultLibraryFile(filePath: string, io: IO): Compiler.TestFile { diff --git a/src/harness/harnessLanguageService.ts b/src/harness/harnessLanguageService.ts index 369f98ad3c806..e1847e8123c1b 100644 --- a/src/harness/harnessLanguageService.ts +++ b/src/harness/harnessLanguageService.ts @@ -146,7 +146,10 @@ export abstract class LanguageServiceAdapterHost { public typesRegistry: Map | undefined; private scriptInfos: collections.SortedMap; - constructor(protected cancellationToken = DefaultHostCancellationToken.instance, protected settings = ts.getDefaultCompilerOptions()) { + constructor( + protected cancellationToken = DefaultHostCancellationToken.instance, + protected settings = ts.getDefaultCompilerOptions(), + ) { this.scriptInfos = new collections.SortedMap({ comparer: this.vfs.stringComparer, sort: "insertion" }); } @@ -215,7 +218,12 @@ export abstract class LanguageServiceAdapterHost { this.vfs.mkdirpSync(ts.getDirectoryPath(newPath)); this.vfs.renameSync(oldPath, newPath); - const updater = ts.getPathUpdater(oldPath, newPath, ts.createGetCanonicalFileName(this.useCaseSensitiveFileNames()), /*sourceMapper*/ undefined); + const updater = ts.getPathUpdater( + oldPath, + newPath, + ts.createGetCanonicalFileName(this.useCaseSensitiveFileNames()), + /*sourceMapper*/ undefined, + ); this.scriptInfos.forEach((scriptInfo, key) => { const newFileName = updater(key); if (newFileName !== undefined) { @@ -253,7 +261,11 @@ export abstract class LanguageServiceAdapterHost { public lineAndCharacterToPosition(fileName: string, lineAndCharacter: ts.LineAndCharacter): number { const script: ScriptInfo = this.getScriptInfo(fileName)!; assert.isOk(script); - return ts.computePositionOfLineAndCharacter(script.getLineMap(), lineAndCharacter.line, lineAndCharacter.character); + return ts.computePositionOfLineAndCharacter( + script.getLineMap(), + lineAndCharacter.line, + lineAndCharacter.character, + ); } useCaseSensitiveFileNames() { @@ -262,7 +274,9 @@ export abstract class LanguageServiceAdapterHost { } /// Native adapter -class NativeLanguageServiceHost extends LanguageServiceAdapterHost implements ts.LanguageServiceHost, LanguageServiceAdapterHost { +class NativeLanguageServiceHost extends LanguageServiceAdapterHost + implements ts.LanguageServiceHost, LanguageServiceAdapterHost +{ isKnownTypesPackageName(name: string): boolean { return !!this.typesRegistry && this.typesRegistry.has(name); } @@ -319,7 +333,13 @@ class NativeLanguageServiceHost extends LanguageServiceAdapterHost implements ts return this.sys.fileExists(fileName); } - readDirectory(path: string, extensions?: readonly string[], exclude?: readonly string[], include?: readonly string[], depth?: number): string[] { + readDirectory( + path: string, + extensions?: readonly string[], + exclude?: readonly string[], + include?: readonly string[], + depth?: number, + ): string[] { return this.sys.readDirectory(path, extensions, exclude, include, depth); } @@ -360,13 +380,19 @@ export class NativeLanguageServiceAdapter implements LanguageServiceAdapter { } /// Shim adapter -class ShimLanguageServiceHost extends LanguageServiceAdapterHost implements ts.LanguageServiceShimHost, ts.CoreServicesShimHost { +class ShimLanguageServiceHost extends LanguageServiceAdapterHost + implements ts.LanguageServiceShimHost, ts.CoreServicesShimHost +{ private nativeHost: NativeLanguageServiceHost; public getModuleResolutionsForFile: ((fileName: string) => string) | undefined; public getTypeReferenceDirectiveResolutionsForFile: ((fileName: string) => string) | undefined; - constructor(preprocessToResolve: boolean, cancellationToken?: ts.HostCancellationToken, options?: ts.CompilerOptions) { + constructor( + preprocessToResolve: boolean, + cancellationToken?: ts.HostCancellationToken, + options?: ts.CompilerOptions, + ) { super(cancellationToken, options); this.nativeHost = new NativeLanguageServiceHost(cancellationToken, options); @@ -385,7 +411,12 @@ class ShimLanguageServiceHost extends LanguageServiceAdapterHost implements ts.L const preprocessInfo = ts.preProcessFile(scriptInfo.content, /*readImportFiles*/ true); const imports: ts.MapLike = {}; for (const module of preprocessInfo.importedFiles) { - const resolutionInfo = ts.resolveModuleName(module.fileName, fileName, compilerOptions, moduleResolutionHost); + const resolutionInfo = ts.resolveModuleName( + module.fileName, + fileName, + compilerOptions, + moduleResolutionHost, + ); if (resolutionInfo.resolvedModule) { imports[module.fileName] = resolutionInfo.resolvedModule.resolvedFileName; } @@ -399,9 +430,15 @@ class ShimLanguageServiceHost extends LanguageServiceAdapterHost implements ts.L const resolutions: ts.MapLike = {}; const settings = this.nativeHost.getCompilationSettings(); for (const typeReferenceDirective of preprocessInfo.typeReferenceDirectives) { - const resolutionInfo = ts.resolveTypeReferenceDirective(typeReferenceDirective.fileName, fileName, settings, moduleResolutionHost); + const resolutionInfo = ts.resolveTypeReferenceDirective( + typeReferenceDirective.fileName, + fileName, + settings, + moduleResolutionHost, + ); if (resolutionInfo.resolvedTypeReferenceDirective!.resolvedFileName) { - resolutions[typeReferenceDirective.fileName] = resolutionInfo.resolvedTypeReferenceDirective!; + resolutions[typeReferenceDirective.fileName] = resolutionInfo + .resolvedTypeReferenceDirective!; } } return JSON.stringify(resolutions); @@ -489,10 +526,18 @@ class ShimLanguageServiceHost extends LanguageServiceAdapterHost implements ts.L class ClassifierShimProxy implements ts.Classifier { constructor(private shim: ts.ClassifierShim) { } - getEncodedLexicalClassifications(_text: string, _lexState: ts.EndOfLineState, _classifyKeywordsInGenerics?: boolean): ts.Classifications { + getEncodedLexicalClassifications( + _text: string, + _lexState: ts.EndOfLineState, + _classifyKeywordsInGenerics?: boolean, + ): ts.Classifications { return ts.notImplemented(); } - getClassificationsForLine(text: string, lexState: ts.EndOfLineState, classifyKeywordsInGenerics?: boolean): ts.ClassificationResult { + getClassificationsForLine( + text: string, + lexState: ts.EndOfLineState, + classifyKeywordsInGenerics?: boolean, + ): ts.ClassificationResult { const result = this.shim.getClassificationsForLine(text, lexState, classifyKeywordsInGenerics).split("\n"); const entries: ts.ClassificationInfo[] = []; let i = 0; @@ -509,7 +554,12 @@ class ClassifierShimProxy implements ts.Classifier { } const finalLexState = parseInt(result[result.length - 1]); - assert.equal(position, text.length, "Expected cumulative length of all entries to match the length of the source. expected: " + text.length + ", but got: " + position); + assert.equal( + position, + text.length, + "Expected cumulative length of all entries to match the length of the source. expected: " + text.length + + ", but got: " + position, + ); return { finalLexState, @@ -550,21 +600,56 @@ class LanguageServiceShimProxy implements ts.LanguageService { getSyntacticClassifications(fileName: string, span: ts.TextSpan): ts.ClassifiedSpan[] { return unwrapJSONCallResult(this.shim.getSyntacticClassifications(fileName, span.start, span.length)); } - getSemanticClassifications(fileName: string, span: ts.TextSpan, format?: ts.SemanticClassificationFormat): ts.ClassifiedSpan[] { + getSemanticClassifications( + fileName: string, + span: ts.TextSpan, + format?: ts.SemanticClassificationFormat, + ): ts.ClassifiedSpan[] { return unwrapJSONCallResult(this.shim.getSemanticClassifications(fileName, span.start, span.length, format)); } getEncodedSyntacticClassifications(fileName: string, span: ts.TextSpan): ts.Classifications { return unwrapJSONCallResult(this.shim.getEncodedSyntacticClassifications(fileName, span.start, span.length)); } - getEncodedSemanticClassifications(fileName: string, span: ts.TextSpan, format?: ts.SemanticClassificationFormat): ts.Classifications { + getEncodedSemanticClassifications( + fileName: string, + span: ts.TextSpan, + format?: ts.SemanticClassificationFormat, + ): ts.Classifications { const responseFormat = format || ts.SemanticClassificationFormat.Original; - return unwrapJSONCallResult(this.shim.getEncodedSemanticClassifications(fileName, span.start, span.length, responseFormat)); + return unwrapJSONCallResult( + this.shim.getEncodedSemanticClassifications(fileName, span.start, span.length, responseFormat), + ); } - getCompletionsAtPosition(fileName: string, position: number, preferences: ts.UserPreferences | undefined, formattingSettings: ts.FormatCodeSettings | undefined): ts.CompletionInfo { - return unwrapJSONCallResult(this.shim.getCompletionsAtPosition(fileName, position, preferences, formattingSettings)); + getCompletionsAtPosition( + fileName: string, + position: number, + preferences: ts.UserPreferences | undefined, + formattingSettings: ts.FormatCodeSettings | undefined, + ): ts.CompletionInfo { + return unwrapJSONCallResult( + this.shim.getCompletionsAtPosition(fileName, position, preferences, formattingSettings), + ); } - getCompletionEntryDetails(fileName: string, position: number, entryName: string, formatOptions: ts.FormatCodeOptions | undefined, source: string | undefined, preferences: ts.UserPreferences | undefined, data: ts.CompletionEntryData | undefined): ts.CompletionEntryDetails { - return unwrapJSONCallResult(this.shim.getCompletionEntryDetails(fileName, position, entryName, JSON.stringify(formatOptions), source, preferences, data)); + getCompletionEntryDetails( + fileName: string, + position: number, + entryName: string, + formatOptions: ts.FormatCodeOptions | undefined, + source: string | undefined, + preferences: ts.UserPreferences | undefined, + data: ts.CompletionEntryData | undefined, + ): ts.CompletionEntryDetails { + return unwrapJSONCallResult( + this.shim.getCompletionEntryDetails( + fileName, + position, + entryName, + JSON.stringify(formatOptions), + source, + preferences, + data, + ), + ); } getCompletionEntrySymbol(): ts.Symbol { throw new Error("getCompletionEntrySymbol not implemented across the shim layer."); @@ -578,7 +663,11 @@ class LanguageServiceShimProxy implements ts.LanguageService { getBreakpointStatementAtPosition(fileName: string, position: number): ts.TextSpan { return unwrapJSONCallResult(this.shim.getBreakpointStatementAtPosition(fileName, position)); } - getSignatureHelpItems(fileName: string, position: number, options: ts.SignatureHelpItemsOptions | undefined): ts.SignatureHelpItems { + getSignatureHelpItems( + fileName: string, + position: number, + options: ts.SignatureHelpItemsOptions | undefined, + ): ts.SignatureHelpItems { return unwrapJSONCallResult(this.shim.getSignatureHelpItems(fileName, position, options)); } getRenameInfo(fileName: string, position: number, preferences: ts.UserPreferences): ts.RenameInfo { @@ -587,8 +676,16 @@ class LanguageServiceShimProxy implements ts.LanguageService { getSmartSelectionRange(fileName: string, position: number): ts.SelectionRange { return unwrapJSONCallResult(this.shim.getSmartSelectionRange(fileName, position)); } - findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean, preferences?: ts.UserPreferences | boolean): ts.RenameLocation[] { - return unwrapJSONCallResult(this.shim.findRenameLocations(fileName, position, findInStrings, findInComments, preferences)); + findRenameLocations( + fileName: string, + position: number, + findInStrings: boolean, + findInComments: boolean, + preferences?: ts.UserPreferences | boolean, + ): ts.RenameLocation[] { + return unwrapJSONCallResult( + this.shim.findRenameLocations(fileName, position, findInStrings, findInComments, preferences), + ); } getDefinitionAtPosition(fileName: string, position: number): ts.DefinitionInfo[] { return unwrapJSONCallResult(this.shim.getDefinitionAtPosition(fileName, position)); @@ -635,17 +732,38 @@ class LanguageServiceShimProxy implements ts.LanguageService { getIndentationAtPosition(fileName: string, position: number, options: ts.EditorOptions): number { return unwrapJSONCallResult(this.shim.getIndentationAtPosition(fileName, position, JSON.stringify(options))); } - getFormattingEditsForRange(fileName: string, start: number, end: number, options: ts.FormatCodeOptions): ts.TextChange[] { - return unwrapJSONCallResult(this.shim.getFormattingEditsForRange(fileName, start, end, JSON.stringify(options))); + getFormattingEditsForRange( + fileName: string, + start: number, + end: number, + options: ts.FormatCodeOptions, + ): ts.TextChange[] { + return unwrapJSONCallResult( + this.shim.getFormattingEditsForRange(fileName, start, end, JSON.stringify(options)), + ); } getFormattingEditsForDocument(fileName: string, options: ts.FormatCodeOptions): ts.TextChange[] { return unwrapJSONCallResult(this.shim.getFormattingEditsForDocument(fileName, JSON.stringify(options))); } - getFormattingEditsAfterKeystroke(fileName: string, position: number, key: string, options: ts.FormatCodeOptions): ts.TextChange[] { - return unwrapJSONCallResult(this.shim.getFormattingEditsAfterKeystroke(fileName, position, key, JSON.stringify(options))); + getFormattingEditsAfterKeystroke( + fileName: string, + position: number, + key: string, + options: ts.FormatCodeOptions, + ): ts.TextChange[] { + return unwrapJSONCallResult( + this.shim.getFormattingEditsAfterKeystroke(fileName, position, key, JSON.stringify(options)), + ); } - getDocCommentTemplateAtPosition(fileName: string, position: number, options?: ts.DocCommentTemplateOptions, formatOptions?: ts.FormatCodeSettings): ts.TextInsertion { - return unwrapJSONCallResult(this.shim.getDocCommentTemplateAtPosition(fileName, position, options, formatOptions)); + getDocCommentTemplateAtPosition( + fileName: string, + position: number, + options?: ts.DocCommentTemplateOptions, + formatOptions?: ts.FormatCodeSettings, + ): ts.TextInsertion { + return unwrapJSONCallResult( + this.shim.getDocCommentTemplateAtPosition(fileName, position, options, formatOptions), + ); } isValidBraceCompletionAtPosition(fileName: string, position: number, openingBrace: number): boolean { return unwrapJSONCallResult(this.shim.isValidBraceCompletionAtPosition(fileName, position, openingBrace)); @@ -679,7 +797,10 @@ class LanguageServiceShimProxy implements ts.LanguageService { getMoveToRefactoringFileSuggestions(): { newFileName: string; files: string[]; } { throw new Error("Not supported on the shim."); } - organizeImports(_args: ts.OrganizeImportsArgs, _formatOptions: ts.FormatCodeSettings): readonly ts.FileTextChanges[] { + organizeImports( + _args: ts.OrganizeImportsArgs, + _formatOptions: ts.FormatCodeSettings, + ): readonly ts.FileTextChanges[] { throw new Error("Not supported on the shim."); } getEditsForFileRename(): readonly ts.FileTextChanges[] { @@ -709,7 +830,10 @@ class LanguageServiceShimProxy implements ts.LanguageService { getAutoImportProvider(): ts.Program | undefined { throw new Error("Program can not be marshaled across the shim layer."); } - updateIsDefinitionOfReferencedSymbols(_referencedSymbols: readonly ts.ReferencedSymbol[], _knownSymbolSpans: Set): boolean { + updateIsDefinitionOfReferencedSymbols( + _referencedSymbols: readonly ts.ReferencedSymbol[], + _knownSymbolSpans: Set, + ): boolean { return ts.notImplemented(); } getNonBoundSourceFile(): ts.SourceFile { @@ -744,7 +868,11 @@ class LanguageServiceShimProxy implements ts.LanguageService { export class ShimLanguageServiceAdapter implements LanguageServiceAdapter { private host: ShimLanguageServiceHost; private factory: ts.TypeScriptServicesFactory; - constructor(preprocessToResolve: boolean, cancellationToken?: ts.HostCancellationToken, options?: ts.CompilerOptions) { + constructor( + preprocessToResolve: boolean, + cancellationToken?: ts.HostCancellationToken, + options?: ts.CompilerOptions, + ) { this.host = new ShimLanguageServiceHost(preprocessToResolve, cancellationToken, options); this.factory = new ts.TypeScriptServicesFactory(); } @@ -764,7 +892,9 @@ export class ShimLanguageServiceAdapter implements LanguageServiceAdapter { typeReferenceDirectives: ts.ShimsFileReference[]; importedFiles: ts.ShimsFileReference[]; isLibFile: boolean; - } = unwrapJSONCallResult(coreServicesShim.getPreProcessedFileInfo(fileName, ts.ScriptSnapshot.fromString(fileContents))); + } = unwrapJSONCallResult( + coreServicesShim.getPreProcessedFileInfo(fileName, ts.ScriptSnapshot.fromString(fileContents)), + ); const convertResult: ts.PreProcessedFileInfo = { referencedFiles: [], @@ -895,7 +1025,13 @@ class SessionServerHost implements ts.server.ServerHost, ts.server.Logger { return ts.sys.getEnvironmentVariable(name); } - readDirectory(path: string, extensions?: readonly string[], exclude?: readonly string[], include?: readonly string[], depth?: number): string[] { + readDirectory( + path: string, + extensions?: readonly string[], + exclude?: readonly string[], + include?: readonly string[], + depth?: number, + ): string[] { return this.host.readDirectory(path, extensions, exclude, include, depth); } @@ -1005,7 +1141,13 @@ class SessionServerHost implements ts.server.ServerHost, ts.server.Logger { const proxy = makeDefaultProxy(info); proxy.getSemanticDiagnostics = filename => { const prev = info.languageService.getSemanticDiagnostics(filename); - const sourceFile: ts.SourceFile = info.project.getSourceFile(ts.toPath(filename, /*basePath*/ undefined, ts.createGetCanonicalFileName(info.serverHost.useCaseSensitiveFileNames)))!; + const sourceFile: ts.SourceFile = info.project.getSourceFile( + ts.toPath( + filename, + /*basePath*/ undefined, + ts.createGetCanonicalFileName(info.serverHost.useCaseSensitiveFileNames), + ), + )!; prev.push({ category: ts.DiagnosticCategory.Warning, file: sourceFile, @@ -1032,7 +1174,13 @@ class SessionServerHost implements ts.server.ServerHost, ts.server.Logger { const proxy = makeDefaultProxy(info); proxy.getSemanticDiagnostics = filename => { const prev = info.languageService.getSemanticDiagnostics(filename); - const sourceFile: ts.SourceFile = info.project.getSourceFile(ts.toPath(filename, /*basePath*/ undefined, ts.createGetCanonicalFileName(info.serverHost.useCaseSensitiveFileNames)))!; + const sourceFile: ts.SourceFile = info.project.getSourceFile( + ts.toPath( + filename, + /*basePath*/ undefined, + ts.createGetCanonicalFileName(info.serverHost.useCaseSensitiveFileNames), + ), + )!; prev.push({ category: ts.DiagnosticCategory.Error, file: sourceFile, @@ -1063,7 +1211,10 @@ class SessionServerHost implements ts.server.ServerHost, ts.server.Logger { class FourslashSession extends ts.server.Session { getText(fileName: string) { - return ts.getSnapshotText(this.projectService.getDefaultProjectForFile(ts.server.toNormalizedPath(fileName), /*ensureProject*/ true)!.getScriptSnapshot(fileName)!); + return ts.getSnapshotText( + this.projectService.getDefaultProjectForFile(ts.server.toNormalizedPath(fileName), /*ensureProject*/ true)! + .getScriptSnapshot(fileName)!, + ); } } @@ -1084,7 +1235,10 @@ export class ServerLanguageServiceAdapter implements LanguageServiceAdapter { cancellationToken: ts.server.nullCancellationToken, useSingleInferredProject: false, useInferredProjectPerProjectRoot: false, - typingsInstaller: { ...ts.server.nullTypingsInstaller, globalTypingsCacheLocation: "/Library/Caches/typescript" }, + typingsInstaller: { + ...ts.server.nullTypingsInstaller, + globalTypingsCacheLocation: "/Library/Caches/typescript", + }, byteLength: Buffer.byteLength, hrtime: process.hrtime, logger: serverHost, diff --git a/src/harness/harnessUtils.ts b/src/harness/harnessUtils.ts index 95c6068ab0702..b51e608380bed 100644 --- a/src/harness/harnessUtils.ts +++ b/src/harness/harnessUtils.ts @@ -116,29 +116,33 @@ export function assertInvariants(node: ts.Node | undefined, parent: ts.Node | un for (const childName in node) { if ( - childName === "parent" || - childName === "nextContainer" || - childName === "modifiers" || - childName === "externalModuleIndicator" || - childName === "original" || + childName === "parent" + || childName === "nextContainer" + || childName === "modifiers" + || childName === "externalModuleIndicator" + || childName === "original" // for now ignore jsdoc comments - childName === "jsDocComment" || - childName === "checkJsDirective" || - childName === "commonJsModuleIndicator" || + || childName === "jsDocComment" + || childName === "checkJsDirective" + || childName === "commonJsModuleIndicator" // ignore nodes added only to report grammar errors - childName === "illegalInitializer" || - childName === "illegalDecorators" || - childName === "illegalModifiers" || - childName === "illegalQuestionToken" || - childName === "illegalExclamationToken" || - childName === "illegalTypeParameters" || - childName === "illegalType" + || childName === "illegalInitializer" + || childName === "illegalDecorators" + || childName === "illegalModifiers" + || childName === "illegalQuestionToken" + || childName === "illegalExclamationToken" + || childName === "illegalTypeParameters" + || childName === "illegalType" ) { continue; } const child = (node as any)[childName]; if (isNodeOrArray(child)) { - assert.isFalse(childNodesAndArrays.indexOf(child) < 0, "Missing child when forEach'ing over node: " + ts.Debug.formatSyntaxKind(node.kind) + "-" + childName); + assert.isFalse( + childNodesAndArrays.indexOf(child) < 0, + "Missing child when forEach'ing over node: " + ts.Debug.formatSyntaxKind(node.kind) + "-" + + childName, + ); } } } @@ -183,7 +187,11 @@ export function sourceFileToJSON(file: ts.Node): string { o.containsParseError = true; } - for (const propertyName of Object.getOwnPropertyNames(n) as readonly (keyof ts.SourceFile | keyof ts.Identifier | keyof ts.StringLiteral)[]) { + for ( + const propertyName of Object.getOwnPropertyNames( + n, + ) as readonly (keyof ts.SourceFile | keyof ts.Identifier | keyof ts.StringLiteral)[] + ) { switch (propertyName) { case "parent": case "symbol": @@ -231,7 +239,11 @@ export function sourceFileToJSON(file: ts.Node): string { case "nextContainer": if ((n as ts.HasLocals).nextContainer) { - o[propertyName] = { kind: (n as ts.HasLocals).nextContainer!.kind, pos: (n as ts.HasLocals).nextContainer!.pos, end: (n as ts.HasLocals).nextContainer!.end }; + o[propertyName] = { + kind: (n as ts.HasLocals).nextContainer!.kind, + pos: (n as ts.HasLocals).nextContainer!.pos, + end: (n as ts.HasLocals).nextContainer!.end, + }; } break; @@ -291,7 +303,11 @@ export function assertStructuralEquals(node1: ts.Node, node2: ts.Node) { // call this on both nodes to ensure all propagated flags have been set (and thus can be // compared). assert.equal(ts.containsParseError(node1), ts.containsParseError(node2)); - assert.equal(node1.flags & ~ts.NodeFlags.ReachabilityAndEmitFlags, node2.flags & ~ts.NodeFlags.ReachabilityAndEmitFlags, "node1.flags !== node2.flags"); + assert.equal( + node1.flags & ~ts.NodeFlags.ReachabilityAndEmitFlags, + node2.flags & ~ts.NodeFlags.ReachabilityAndEmitFlags, + "node1.flags !== node2.flags", + ); ts.forEachChild(node1, child1 => { const childName = findChildName(node1, child1); diff --git a/src/harness/incrementalUtils.ts b/src/harness/incrementalUtils.ts index 5aa4c16b927aa..17acbcbf0da3a 100644 --- a/src/harness/incrementalUtils.ts +++ b/src/harness/incrementalUtils.ts @@ -6,17 +6,26 @@ export function reportDocumentRegistryStats(documentRegistry: ts.DocumentRegistr str.push(` Key:: ${key}`); bucketEntries.forEach((entry, path) => { if (ts.isDocumentRegistryEntry(entry)) { - str.push(` ${path}: ${ts.Debug.formatScriptKind(entry.sourceFile.scriptKind)} ${entry.languageServiceRefCount}`); + str.push( + ` ${path}: ${ + ts.Debug.formatScriptKind(entry.sourceFile.scriptKind) + } ${entry.languageServiceRefCount}`, + ); } else { - entry.forEach((real, kind) => str.push(` ${path}: ${ts.Debug.formatScriptKind(kind)} ${real.languageServiceRefCount}`)); + entry.forEach((real, kind) => + str.push(` ${path}: ${ts.Debug.formatScriptKind(kind)} ${real.languageServiceRefCount}`) + ); } }); }); return str; } -type DocumentRegistryExpectedStats = Map>>; +type DocumentRegistryExpectedStats = Map< + ts.DocumentRegistryBucketKeyWithMode, + Map> +>; function verifyDocumentRegistryStats( documentRegistry: ts.DocumentRegistry, stats: DocumentRegistryExpectedStats, @@ -27,8 +36,11 @@ function verifyDocumentRegistryStats( const expected = statsByPath?.get(path); if (ts.isDocumentRegistryEntry(entry)) { ts.Debug.assert( - expected?.size === 1 && expected.has(entry.sourceFile.scriptKind) && expected.get(entry.sourceFile.scriptKind) === entry.languageServiceRefCount, - `Document registry has unexpected language service ref count for ${key} ${path} ${ts.Debug.formatScriptKind(entry.sourceFile.scriptKind)} ${entry.languageServiceRefCount}`, + expected?.size === 1 && expected.has(entry.sourceFile.scriptKind) + && expected.get(entry.sourceFile.scriptKind) === entry.languageServiceRefCount, + `Document registry has unexpected language service ref count for ${key} ${path} ${ + ts.Debug.formatScriptKind(entry.sourceFile.scriptKind) + } ${entry.languageServiceRefCount}`, reportStats, ); } @@ -36,14 +48,18 @@ function verifyDocumentRegistryStats( entry.forEach((real, kind) => ts.Debug.assert( real.languageServiceRefCount === expected?.get(kind), - `Document registry has unexpected language service ref count for ${key} ${path} ${ts.Debug.formatScriptKind(kind)} ${real.languageServiceRefCount}`, + `Document registry has unexpected language service ref count for ${key} ${path} ${ + ts.Debug.formatScriptKind(kind) + } ${real.languageServiceRefCount}`, reportStats, ) ); expected?.forEach((value, kind) => ts.Debug.assert( entry.has(kind), - `Document registry expected language service ref count for ${key} ${path} ${ts.Debug.formatScriptKind(kind)} ${value}`, + `Document registry expected language service ref count for ${key} ${path} ${ + ts.Debug.formatScriptKind(kind) + } ${value}`, reportStats, ) ); @@ -70,7 +86,11 @@ function verifyDocumentRegistryStats( str.push("Expected::"); stats?.forEach((statsByPath, key) => { str.push(` Key:: ${key}`); - statsByPath.forEach((entry, path) => entry.forEach((refCount, kind) => str.push(` ${path}: ${ts.Debug.formatScriptKind(kind)} ${refCount}`))); + statsByPath.forEach((entry, path) => + entry.forEach((refCount, kind) => + str.push(` ${path}: ${ts.Debug.formatScriptKind(kind)} ${refCount}`) + ) + ); }); return str.join("\n"); } diff --git a/src/harness/runnerbase.ts b/src/harness/runnerbase.ts index 3401301a08ca5..a8053bc6cb911 100644 --- a/src/harness/runnerbase.ts +++ b/src/harness/runnerbase.ts @@ -30,7 +30,10 @@ export abstract class RunnerBase { } public enumerateFiles(folder: string, regex?: RegExp, options?: { recursive: boolean; }): string[] { - return ts.map(IO.listFiles(userSpecifiedRoot + folder, regex, { recursive: (options ? options.recursive : false) }), ts.normalizeSlashes); + return ts.map( + IO.listFiles(userSpecifiedRoot + folder, regex, { recursive: (options ? options.recursive : false) }), + ts.normalizeSlashes, + ); } abstract kind(): TestRunnerKind; diff --git a/src/harness/sourceMapRecorder.ts b/src/harness/sourceMapRecorder.ts index 9f0a906ed3218..8c9d61d70e4ae 100644 --- a/src/harness/sourceMapRecorder.ts +++ b/src/harness/sourceMapRecorder.ts @@ -58,7 +58,11 @@ namespace SourceMapSpanWriter { let nextJsLineToWrite: number; let spanMarkerContinues: boolean; - export function initializeSourceMapSpanWriter(sourceMapRecordWriter: Compiler.WriterAggregator, sourceMap: ts.RawSourceMap, currentJsFile: documents.TextDocument) { + export function initializeSourceMapSpanWriter( + sourceMapRecordWriter: Compiler.WriterAggregator, + sourceMap: ts.RawSourceMap, + currentJsFile: documents.TextDocument, + ) { sourceMapRecorder = sourceMapRecordWriter; sourceMapSources = sourceMap.sources; sourceMapNames = sourceMap.names; @@ -86,7 +90,8 @@ namespace SourceMapSpanWriter { function getSourceMapSpanString(mapEntry: ts.Mapping, getAbsentNameIndex?: boolean) { let mapString = "Emitted(" + (mapEntry.generatedLine + 1) + ", " + (mapEntry.generatedCharacter + 1) + ")"; if (ts.isSourceMapping(mapEntry)) { - mapString += " Source(" + (mapEntry.sourceLine + 1) + ", " + (mapEntry.sourceCharacter + 1) + ") + SourceIndex(" + mapEntry.sourceIndex + ")"; + mapString += " Source(" + (mapEntry.sourceLine + 1) + ", " + (mapEntry.sourceCharacter + 1) + + ") + SourceIndex(" + mapEntry.sourceIndex + ")"; if (mapEntry.nameIndex! >= 0 && mapEntry.nameIndex! < sourceMapNames!.length) { mapString += " name (" + sourceMapNames![mapEntry.nameIndex!] + ")"; } @@ -106,15 +111,26 @@ namespace SourceMapSpanWriter { let decodeErrors: string[] | undefined; if (typeof decodeResult.error === "string" || !ts.sameMapping(decodeResult.sourceMapSpan, sourceMapSpan)) { if (decodeResult.error) { - decodeErrors = ["!!^^ !!^^ There was decoding error in the sourcemap at this location: " + decodeResult.error]; + decodeErrors = [ + "!!^^ !!^^ There was decoding error in the sourcemap at this location: " + decodeResult.error, + ]; } else { - decodeErrors = ["!!^^ !!^^ The decoded span from sourcemap's mapping entry does not match what was encoded for this span:"]; + decodeErrors = [ + "!!^^ !!^^ The decoded span from sourcemap's mapping entry does not match what was encoded for this span:", + ]; } - decodeErrors.push("!!^^ !!^^ Decoded span from sourcemap's mappings entry: " + getSourceMapSpanString(decodeResult.sourceMapSpan, /*getAbsentNameIndex*/ true) + " Span encoded by the emitter:" + getSourceMapSpanString(sourceMapSpan, /*getAbsentNameIndex*/ true)); + decodeErrors.push( + "!!^^ !!^^ Decoded span from sourcemap's mappings entry: " + + getSourceMapSpanString(decodeResult.sourceMapSpan, /*getAbsentNameIndex*/ true) + + " Span encoded by the emitter:" + + getSourceMapSpanString(sourceMapSpan, /*getAbsentNameIndex*/ true), + ); } - if (spansOnSingleLine.length && spansOnSingleLine[0].sourceMapSpan.generatedLine !== sourceMapSpan.generatedLine) { + if ( + spansOnSingleLine.length && spansOnSingleLine[0].sourceMapSpan.generatedLine !== sourceMapSpan.generatedLine + ) { // On different line from the one that we have been recording till now, writeRecordedSpans(); spansOnSingleLine = []; @@ -124,7 +140,10 @@ namespace SourceMapSpanWriter { export function recordNewSourceFileSpan(sourceMapSpan: ts.Mapping, newSourceFileCode: string) { let continuesLine = false; - if (spansOnSingleLine.length > 0 && spansOnSingleLine[0].sourceMapSpan.generatedCharacter === sourceMapSpan.generatedLine) { + if ( + spansOnSingleLine.length > 0 + && spansOnSingleLine[0].sourceMapSpan.generatedCharacter === sourceMapSpan.generatedLine + ) { writeRecordedSpans(); spansOnSingleLine = []; nextJsLineToWrite--; // walk back one line to reprint the line @@ -135,7 +154,11 @@ namespace SourceMapSpanWriter { assert.isTrue(spansOnSingleLine.length === 1); sourceMapRecorder.WriteLine("-------------------------------------------------------------------"); - sourceMapRecorder.WriteLine("emittedFile:" + jsFile.file + (continuesLine ? ` (${sourceMapSpan.generatedLine + 1}, ${sourceMapSpan.generatedCharacter + 1})` : "")); + sourceMapRecorder.WriteLine( + "emittedFile:" + jsFile.file + + (continuesLine ? ` (${sourceMapSpan.generatedLine + 1}, ${sourceMapSpan.generatedCharacter + 1})` + : ""), + ); sourceMapRecorder.WriteLine("sourceFile:" + sourceMapSources[spansOnSingleLine[0].sourceMapSpan.sourceIndex!]); sourceMapRecorder.WriteLine("-------------------------------------------------------------------"); @@ -149,8 +172,12 @@ namespace SourceMapSpanWriter { writeRecordedSpans(); if (!SourceMapDecoder.hasCompletedDecoding()) { - sourceMapRecorder.WriteLine("!!!! **** There are more source map entries in the sourceMap's mapping than what was encoded"); - sourceMapRecorder.WriteLine("!!!! **** Remaining decoded string: " + SourceMapDecoder.getRemainingDecodeString()); + sourceMapRecorder.WriteLine( + "!!!! **** There are more source map entries in the sourceMap's mapping than what was encoded", + ); + sourceMapRecorder.WriteLine( + "!!!! **** Remaining decoded string: " + SourceMapDecoder.getRemainingDecodeString(), + ); } // write remaining js lines @@ -205,7 +232,12 @@ namespace SourceMapSpanWriter { } } - function writeSourceMapMarker(currentSpan: SourceMapSpanWithDecodeErrors, index: number, endColumn = currentSpan.sourceMapSpan.generatedCharacter, endContinues = false) { + function writeSourceMapMarker( + currentSpan: SourceMapSpanWithDecodeErrors, + index: number, + endColumn = currentSpan.sourceMapSpan.generatedCharacter, + endContinues = false, + ) { const markerId = getMarkerId(index); markerIds.push(markerId); @@ -222,7 +254,8 @@ namespace SourceMapSpanWriter { } function writeSourceMapSourceText(currentSpan: SourceMapSpanWithDecodeErrors, index: number) { - const sourcePos = tsLineMap[currentSpan.sourceMapSpan.sourceLine!] + (currentSpan.sourceMapSpan.sourceCharacter!); + const sourcePos = tsLineMap[currentSpan.sourceMapSpan.sourceLine!] + + (currentSpan.sourceMapSpan.sourceCharacter!); let sourceText = ""; if (prevWrittenSourcePos < sourcePos) { // Position that goes forward, get text @@ -265,7 +298,12 @@ namespace SourceMapSpanWriter { const jsFileText = getTextOfLine(currentJsLine + 1, jsLineMap, jsFile.text); if (prevEmittedCol < jsFileText.length - 1) { // There is remaining text on this line that will be part of next source span so write marker that continues - writeSourceMapMarker(/*currentSpan*/ undefined!, spansOnSingleLine.length, /*endColumn*/ jsFileText.length - 1, /*endContinues*/ true); // TODO: GH#18217 + writeSourceMapMarker( + /*currentSpan*/ undefined!, + spansOnSingleLine.length, + /*endColumn*/ jsFileText.length - 1, + /*endContinues*/ true, + ); // TODO: GH#18217 } // Emit Source text @@ -279,7 +317,12 @@ namespace SourceMapSpanWriter { } } -export function getSourceMapRecord(sourceMapDataList: readonly ts.SourceMapEmitResult[], program: ts.Program, jsFiles: readonly documents.TextDocument[], declarationFiles: readonly documents.TextDocument[]) { +export function getSourceMapRecord( + sourceMapDataList: readonly ts.SourceMapEmitResult[], + program: ts.Program, + jsFiles: readonly documents.TextDocument[], + declarationFiles: readonly documents.TextDocument[], +) { const sourceMapRecorder = new Compiler.WriterAggregator(); for (let i = 0; i < sourceMapDataList.length; i++) { @@ -333,9 +376,12 @@ export function getSourceMapRecordWithSystem(sys: ts.System, sourceMapFile: stri const sourceMap = ts.tryParseRawSourceMap(sys.readFile(sourceMapFile, "utf8")!); if (sourceMap) { const mapDirectory = ts.getDirectoryPath(sourceMapFile); - const sourceRoot = sourceMap.sourceRoot ? ts.getNormalizedAbsolutePath(sourceMap.sourceRoot, mapDirectory) : mapDirectory; + const sourceRoot = sourceMap.sourceRoot ? ts.getNormalizedAbsolutePath(sourceMap.sourceRoot, mapDirectory) + : mapDirectory; const generatedAbsoluteFilePath = ts.getNormalizedAbsolutePath(sourceMap.file, mapDirectory); - const sourceFileAbsolutePaths = sourceMap.sources.map(source => ts.getNormalizedAbsolutePath(source, sourceRoot)); + const sourceFileAbsolutePaths = sourceMap.sources.map(source => + ts.getNormalizedAbsolutePath(source, sourceRoot) + ); const currentFile = getFile(generatedAbsoluteFilePath); SourceMapSpanWriter.initializeSourceMapSpanWriter(sourceMapRecorder, sourceMap, currentFile); diff --git a/src/harness/typeWriter.ts b/src/harness/typeWriter.ts index 5cb9e7149da87..40ee7b7406fb8 100644 --- a/src/harness/typeWriter.ts +++ b/src/harness/typeWriter.ts @@ -75,7 +75,9 @@ export class TypeWriterWalker { } private isImportStatementName(node: ts.Node) { - if (ts.isImportSpecifier(node.parent) && (node.parent.name === node || node.parent.propertyName === node)) return true; + if (ts.isImportSpecifier(node.parent) && (node.parent.name === node || node.parent.propertyName === node)) { + return true; + } if (ts.isImportClause(node.parent) && node.parent.name === node) return true; if (ts.isImportEqualsDeclaration(node.parent) && node.parent.name === node) return true; return false; @@ -83,7 +85,9 @@ export class TypeWriterWalker { private isExportStatementName(node: ts.Node) { if (ts.isExportAssignment(node.parent) && node.parent.expression === node) return true; - if (ts.isExportSpecifier(node.parent) && (node.parent.name === node || node.parent.propertyName === node)) return true; + if (ts.isExportSpecifier(node.parent) && (node.parent.name === node || node.parent.propertyName === node)) { + return true; + } return false; } @@ -102,13 +106,18 @@ export class TypeWriterWalker { if (!isSymbolWalk) { // Don't try to get the type of something that's already a type. // Exception for `T` in `type T = something` because that may evaluate to some interesting type. - if (ts.isPartOfTypeNode(node) || ts.isIdentifier(node) && !(ts.getMeaningFromDeclaration(node.parent) & ts.SemanticMeaning.Value) && !(ts.isTypeAliasDeclaration(node.parent) && node.parent.name === node)) { + if ( + ts.isPartOfTypeNode(node) + || ts.isIdentifier(node) && !(ts.getMeaningFromDeclaration(node.parent) & ts.SemanticMeaning.Value) + && !(ts.isTypeAliasDeclaration(node.parent) && node.parent.name === node) + ) { return undefined; } // Workaround to ensure we output 'C' instead of 'typeof C' for base class expressions // let type = this.checker.getTypeAtLocation(node); - let type = ts.isExpressionWithTypeArgumentsInClassExtendsClause(node.parent) ? this.checker.getTypeAtLocation(node.parent) : undefined; + let type = ts.isExpressionWithTypeArgumentsInClassExtendsClause(node.parent) + ? this.checker.getTypeAtLocation(node.parent) : undefined; if (!type || type.flags & ts.TypeFlags.Any) type = this.checker.getTypeAtLocation(node); // Distinguish `errorType`s from `any`s; but only if the file has no errors. // Additionally, @@ -124,25 +133,37 @@ export class TypeWriterWalker { // But this is generally expected, so we don't call those out, either let typeString: string; if ( - !this.hadErrorBaseline && - type.flags & ts.TypeFlags.Any && - !ts.isBindingElement(node.parent) && - !ts.isPropertyAccessOrQualifiedName(node.parent) && - !ts.isLabelName(node) && - !(ts.isModuleDeclaration(node.parent) && ts.isGlobalScopeAugmentation(node.parent)) && - !ts.isMetaProperty(node.parent) && - !this.isImportStatementName(node) && - !this.isExportStatementName(node) && - !this.isIntrinsicJsxTag(node) + !this.hadErrorBaseline + && type.flags & ts.TypeFlags.Any + && !ts.isBindingElement(node.parent) + && !ts.isPropertyAccessOrQualifiedName(node.parent) + && !ts.isLabelName(node) + && !(ts.isModuleDeclaration(node.parent) && ts.isGlobalScopeAugmentation(node.parent)) + && !ts.isMetaProperty(node.parent) + && !this.isImportStatementName(node) + && !this.isExportStatementName(node) + && !this.isIntrinsicJsxTag(node) ) { typeString = (type as ts.IntrinsicType).intrinsicName; } else { - typeString = this.checker.typeToString(type, node.parent, ts.TypeFormatFlags.NoTruncation | ts.TypeFormatFlags.AllowUniqueESSymbolType); - if (ts.isIdentifier(node) && ts.isTypeAliasDeclaration(node.parent) && node.parent.name === node && typeString === ts.idText(node)) { + typeString = this.checker.typeToString( + type, + node.parent, + ts.TypeFormatFlags.NoTruncation | ts.TypeFormatFlags.AllowUniqueESSymbolType, + ); + if ( + ts.isIdentifier(node) && ts.isTypeAliasDeclaration(node.parent) && node.parent.name === node + && typeString === ts.idText(node) + ) { // for a complex type alias `type T = ...`, showing "T : T" isn't very helpful for type tests. When the type produced is the same as // the name of the type alias, recreate the type string without reusing the alias name - typeString = this.checker.typeToString(type, node.parent, ts.TypeFormatFlags.NoTruncation | ts.TypeFormatFlags.AllowUniqueESSymbolType | ts.TypeFormatFlags.InTypeAlias); + typeString = this.checker.typeToString( + type, + node.parent, + ts.TypeFormatFlags.NoTruncation | ts.TypeFormatFlags.AllowUniqueESSymbolType + | ts.TypeFormatFlags.InTypeAlias, + ); } } return { @@ -174,7 +195,9 @@ export class TypeWriterWalker { const declLineAndCharacter = declSourceFile.getLineAndCharacterOfPosition(declaration.pos); const fileName = ts.getBaseFileName(declSourceFile.fileName); const isLibFile = /lib(.*)\.d\.ts/i.test(fileName); - const declText = `Decl(${fileName}, ${isLibFile ? "--" : declLineAndCharacter.line}, ${isLibFile ? "--" : declLineAndCharacter.character})`; + const declText = `Decl(${fileName}, ${isLibFile ? "--" : declLineAndCharacter.line}, ${ + isLibFile ? "--" : declLineAndCharacter.character + })`; symbolString += declText; (declaration as any).__symbolTestOutputCache = declText; } diff --git a/src/harness/util.ts b/src/harness/util.ts index 3a4a78f724009..81c250e2789d1 100644 --- a/src/harness/util.ts +++ b/src/harness/util.ts @@ -6,18 +6,28 @@ import * as ts from "./_namespaces/ts"; const testPathPrefixRegExp = /(?:(file:\/{3})|\/)\.(ts|lib|src)\//g; export function removeTestPathPrefixes(text: string, retainTrailingDirectorySeparator?: boolean): string { - return text !== undefined ? text.replace(testPathPrefixRegExp, (_, scheme) => scheme || (retainTrailingDirectorySeparator ? "/" : "")) : undefined!; // TODO: GH#18217 + return text !== undefined + ? text.replace(testPathPrefixRegExp, (_, scheme) => scheme || (retainTrailingDirectorySeparator ? "/" : "")) + : undefined!; // TODO: GH#18217 } -function createDiagnosticMessageReplacer string[]>(diagnosticMessage: ts.DiagnosticMessage, replacer: R) { +function createDiagnosticMessageReplacer string[]>( + diagnosticMessage: ts.DiagnosticMessage, + replacer: R, +) { const messageParts = diagnosticMessage.message.split(/{\d+}/g); const regExp = new RegExp(`^(?:${messageParts.map(ts.regExpEscape).join("(.*?)")})$`); type Args = R extends (messageArgs: string[], ...args: infer A) => string[] ? A : []; - return (text: string, ...args: Args) => text.replace(regExp, (_, ...fixedArgs) => ts.formatStringFromArgs(diagnosticMessage.message, replacer(fixedArgs, ...args))); + return (text: string, ...args: Args) => + text.replace( + regExp, + (_, ...fixedArgs) => ts.formatStringFromArgs(diagnosticMessage.message, replacer(fixedArgs, ...args)), + ); } const replaceTypesVersionsMessage = createDiagnosticMessageReplacer( - ts.Diagnostics.package_json_has_a_typesVersions_entry_0_that_matches_compiler_version_1_looking_for_a_pattern_to_match_module_name_2, + ts.Diagnostics + .package_json_has_a_typesVersions_entry_0_that_matches_compiler_version_1_looking_for_a_pattern_to_match_module_name_2, ([entry, , moduleName], compilerVersion) => [entry, compilerVersion, moduleName], ); @@ -108,9 +118,9 @@ export function theory(name: string, cb: (...args: T) => void, } function formatTheoryDatum(value: any) { - return typeof value === "function" ? value.name || "" : - value === undefined ? "undefined" : - JSON.stringify(value); + return typeof value === "function" ? value.name || "" + : value === undefined ? "undefined" + : JSON.stringify(value); } export interface Deferred { diff --git a/src/harness/vfsUtil.ts b/src/harness/vfsUtil.ts index 5d34d0bf15fb5..91a4c83d74be6 100644 --- a/src/harness/vfsUtil.ts +++ b/src/harness/vfsUtil.ts @@ -155,7 +155,9 @@ export class FileSystem { */ public shadow(ignoreCase = this.ignoreCase) { if (!this.isReadonly) throw new Error("Cannot shadow a mutable file system."); - if (ignoreCase && !this.ignoreCase) throw new Error("Cannot create a case-insensitive file system from a case-sensitive one."); + if (ignoreCase && !this.ignoreCase) { + throw new Error("Cannot create a case-insensitive file system from a case-sensitive one."); + } const fs = new FileSystem(ignoreCase, { time: this._time }); fs._shadowRoot = this; fs._cwd = this._cwd; @@ -576,11 +578,17 @@ export class FileSystem { public renameSync(oldpath: string, newpath: string) { if (this.isReadonly) throw createIOError("EROFS"); - const { parent: oldParent, links: oldParentLinks, node, basename: oldBasename } = this._walk(this._resolve(oldpath), /*noFollow*/ true); + const { parent: oldParent, links: oldParentLinks, node, basename: oldBasename } = this._walk( + this._resolve(oldpath), + /*noFollow*/ true, + ); if (!oldParent) throw createIOError("EPERM"); if (!node) throw createIOError("ENOENT"); - const { parent: newParent, links: newParentLinks, node: existingNode, basename: newBasename } = this._walk(this._resolve(newpath), /*noFollow*/ true); + const { parent: newParent, links: newParentLinks, node: existingNode, basename: newBasename } = this._walk( + this._resolve(newpath), + /*noFollow*/ true, + ); if (!newParent) throw createIOError("EPERM"); const time = this.time(); @@ -589,7 +597,9 @@ export class FileSystem { if (!isDirectory(existingNode)) throw createIOError("ENOTDIR"); // if both old and new arguments point to the same directory, just pass. So we could rename /src/a/1 to /src/A/1 in Win. // if not and the directory pointed by the new path is not empty, throw an error. - if (this.stringComparer(oldpath, newpath) !== 0 && this._getLinks(existingNode).size > 0) throw createIOError("ENOTEMPTY"); + if (this.stringComparer(oldpath, newpath) !== 0 && this._getLinks(existingNode).size > 0) { + throw createIOError("ENOTEMPTY"); + } } else { if (isDirectory(existingNode)) throw createIOError("EISDIR"); @@ -681,7 +691,8 @@ export class FileSystem { if (isDirectory(node)) throw createIOError("EISDIR"); if (!isFile(node)) throw createIOError("EBADF"); - node.buffer = Buffer.isBuffer(data) ? data.slice() : ts.sys.bufferFrom!("" + data, encoding || "utf8") as Buffer; + node.buffer = Buffer.isBuffer(data) ? data.slice() + : ts.sys.bufferFrom!("" + data, encoding || "utf8") as Buffer; node.size = node.buffer.byteLength; node.mtimeMs = time; node.ctimeMs = time; @@ -694,9 +705,9 @@ export class FileSystem { public diff(base?: FileSystem | undefined, options: DiffOptions = {}) { if (!base && !options.baseIsNotShadowRoot) base = this.shadowRoot; const differences: FileSet = {}; - const hasDifferences = base ? - FileSystem.rootDiff(differences, this, base, options) : - FileSystem.trackCreatedInodes(differences, this, this._getRootLinks()); + const hasDifferences = base + ? FileSystem.rootDiff(differences, this, base, options) + : FileSystem.trackCreatedInodes(differences, this, this._getRootLinks()); return hasDifferences ? differences : undefined; } @@ -705,12 +716,19 @@ export class FileSystem { */ public static diff(changed: FileSystem, base: FileSystem, options: DiffOptions = {}) { const differences: FileSet = {}; - return FileSystem.rootDiff(differences, changed, base, options) ? - differences : - undefined; - } - - private static diffWorker(container: FileSet, changed: FileSystem, changedLinks: ReadonlyMap | undefined, base: FileSystem, baseLinks: ReadonlyMap | undefined, options: DiffOptions) { + return FileSystem.rootDiff(differences, changed, base, options) + ? differences + : undefined; + } + + private static diffWorker( + container: FileSet, + changed: FileSystem, + changedLinks: ReadonlyMap | undefined, + base: FileSystem, + baseLinks: ReadonlyMap | undefined, + options: DiffOptions, + ) { if (changedLinks && !baseLinks) return FileSystem.trackCreatedInodes(container, changed, changedLinks); if (baseLinks && !changedLinks) return FileSystem.trackDeletedInodes(container, baseLinks); if (changedLinks && baseLinks) { @@ -727,16 +745,22 @@ export class FileSystem { const baseNode = baseLinks.get(basename); if (baseNode) { if (isDirectory(changedNode) && isDirectory(baseNode)) { - return hasChanges = FileSystem.directoryDiff(container, basename, changed, changedNode, base, baseNode, options) || hasChanges; + return hasChanges = + FileSystem.directoryDiff(container, basename, changed, changedNode, base, baseNode, options) + || hasChanges; } if (isFile(changedNode) && isFile(baseNode)) { - return hasChanges = FileSystem.fileDiff(container, basename, changed, changedNode, base, baseNode, options) || hasChanges; + return hasChanges = + FileSystem.fileDiff(container, basename, changed, changedNode, base, baseNode, options) + || hasChanges; } if (isSymlink(changedNode) && isSymlink(baseNode)) { - return hasChanges = FileSystem.symlinkDiff(container, basename, changedNode, baseNode) || hasChanges; + return hasChanges = FileSystem.symlinkDiff(container, basename, changedNode, baseNode) + || hasChanges; } } - return hasChanges = FileSystem.trackCreatedInode(container, basename, changed, changedNode) || hasChanges; + return hasChanges = FileSystem.trackCreatedInode(container, basename, changed, changedNode) + || hasChanges; }); return hasChanges; } @@ -756,7 +780,15 @@ export class FileSystem { return FileSystem.diffWorker(container, changed, changed._getRootLinks(), base, base._getRootLinks(), options); } - private static directoryDiff(container: FileSet, basename: string, changed: FileSystem, changedNode: DirectoryInode, base: FileSystem, baseNode: DirectoryInode, options: DiffOptions) { + private static directoryDiff( + container: FileSet, + basename: string, + changed: FileSystem, + changedNode: DirectoryInode, + base: FileSystem, + baseNode: DirectoryInode, + options: DiffOptions, + ) { while (!changedNode.links && changedNode.shadowRoot) changedNode = changedNode.shadowRoot; while (!baseNode.links && baseNode.shadowRoot) baseNode = baseNode.shadowRoot; @@ -768,14 +800,23 @@ export class FileSystem { // no difference if both nodes are unpopulated and point to the same mounted file system if ( - !changedNode.links && !baseNode.links && - changedNode.resolver && changedNode.source !== undefined && - baseNode.resolver === changedNode.resolver && baseNode.source === changedNode.source + !changedNode.links && !baseNode.links + && changedNode.resolver && changedNode.source !== undefined + && baseNode.resolver === changedNode.resolver && baseNode.source === changedNode.source ) return false; // no difference if both nodes have identical children const children: FileSet = {}; - if (!FileSystem.diffWorker(children, changed, changed._getLinks(changedNode), base, base._getLinks(baseNode), options)) { + if ( + !FileSystem.diffWorker( + children, + changed, + changed._getLinks(changedNode), + base, + base._getLinks(baseNode), + options, + ) + ) { return false; } @@ -783,7 +824,15 @@ export class FileSystem { return true; } - private static fileDiff(container: FileSet, basename: string, changed: FileSystem, changedNode: FileInode, base: FileSystem, baseNode: FileInode, options: DiffOptions) { + private static fileDiff( + container: FileSet, + basename: string, + changed: FileSystem, + changedNode: FileInode, + base: FileSystem, + baseNode: FileInode, + options: DiffOptions, + ) { while (!changedNode.buffer && changedNode.shadowRoot) changedNode = changedNode.shadowRoot; while (!baseNode.buffer && baseNode.shadowRoot) baseNode = baseNode.shadowRoot; @@ -795,9 +844,9 @@ export class FileSystem { // no difference if both nodes are unpopulated and point to the same mounted file system if ( - !changedNode.buffer && !baseNode.buffer && - changedNode.resolver && changedNode.source !== undefined && - baseNode.resolver === changedNode.resolver && baseNode.source === changedNode.source + !changedNode.buffer && !baseNode.buffer + && changedNode.resolver && changedNode.source !== undefined + && baseNode.resolver === changedNode.resolver && baseNode.source === changedNode.source ) return false; const changedBuffer = changed._getBuffer(changedNode); @@ -821,7 +870,12 @@ export class FileSystem { return true; } - private static symlinkDiff(container: FileSet, basename: string, changedNode: SymlinkInode, baseNode: SymlinkInode) { + private static symlinkDiff( + container: FileSet, + basename: string, + changedNode: SymlinkInode, + baseNode: SymlinkInode, + ) { // no difference if the nodes are the same reference if (changedNode.symlink === baseNode.symlink) return false; container[basename] = new Symlink(changedNode.symlink); @@ -843,7 +897,11 @@ export class FileSystem { return true; } - private static trackCreatedInodes(container: FileSet, changed: FileSystem, changedLinks: ReadonlyMap) { + private static trackCreatedInodes( + container: FileSet, + changed: FileSystem, + changedLinks: ReadonlyMap, + ) { // no difference if links are empty if (!changedLinks.size) return false; @@ -878,7 +936,13 @@ export class FileSystem { }; } - private _addLink(parent: DirectoryInode | undefined, links: collections.SortedMap, name: string, node: Inode, time = this.time()) { + private _addLink( + parent: DirectoryInode | undefined, + links: collections.SortedMap, + name: string, + node: Inode, + time = this.time(), + ) { links.set(name, node); node.nlink++; node.ctimeMs = time; @@ -886,14 +950,29 @@ export class FileSystem { if (!parent && !this._cwd) this._cwd = name; } - private _removeLink(parent: DirectoryInode | undefined, links: collections.SortedMap, name: string, node: Inode, time = this.time()) { + private _removeLink( + parent: DirectoryInode | undefined, + links: collections.SortedMap, + name: string, + node: Inode, + time = this.time(), + ) { links.delete(name); node.nlink--; node.ctimeMs = time; if (parent) parent.mtimeMs = time; } - private _replaceLink(oldParent: DirectoryInode, oldLinks: collections.SortedMap, oldName: string, newParent: DirectoryInode, newLinks: collections.SortedMap, newName: string, node: Inode, time: number) { + private _replaceLink( + oldParent: DirectoryInode, + oldLinks: collections.SortedMap, + oldName: string, + newParent: DirectoryInode, + newLinks: collections.SortedMap, + newName: string, + node: Inode, + time: number, + ) { if (oldParent !== newParent) { this._removeLink(oldParent, oldLinks, oldName, node, time); this._addLink(newParent, newLinks, newName, node, time); @@ -1019,9 +1098,21 @@ export class FileSystem { * * @link http://man7.org/linux/man-pages/man7/path_resolution.7.html */ - private _walk(path: string, noFollow?: boolean, onError?: (error: NodeJS.ErrnoException, fragment: WalkResult) => "retry" | "throw"): WalkResult; - private _walk(path: string, noFollow?: boolean, onError?: (error: NodeJS.ErrnoException, fragment: WalkResult) => "stop" | "retry" | "throw"): WalkResult | undefined; - private _walk(path: string, noFollow?: boolean, onError?: (error: NodeJS.ErrnoException, fragment: WalkResult) => "stop" | "retry" | "throw"): WalkResult | undefined { + private _walk( + path: string, + noFollow?: boolean, + onError?: (error: NodeJS.ErrnoException, fragment: WalkResult) => "retry" | "throw", + ): WalkResult; + private _walk( + path: string, + noFollow?: boolean, + onError?: (error: NodeJS.ErrnoException, fragment: WalkResult) => "stop" | "retry" | "throw", + ): WalkResult | undefined; + private _walk( + path: string, + noFollow?: boolean, + onError?: (error: NodeJS.ErrnoException, fragment: WalkResult) => "stop" | "retry" | "throw", + ): WalkResult | undefined { let links = this._getRootLinks(); let parent: DirectoryInode | undefined; let components = vpath.parse(path); @@ -1084,7 +1175,10 @@ export class FileSystem { */ private _resolve(path: string) { return this._cwd - ? vpath.resolve(this._cwd, vpath.validate(path, vpath.ValidationFlags.RelativeOrAbsolute | vpath.ValidationFlags.AllowWildcard)) + ? vpath.resolve( + this._cwd, + vpath.validate(path, vpath.ValidationFlags.RelativeOrAbsolute | vpath.ValidationFlags.AllowWildcard), + ) : vpath.validate(path, vpath.ValidationFlags.Absolute | vpath.ValidationFlags.AllowWildcard); } @@ -1234,7 +1328,11 @@ export function createResolver(host: FileSystemResolverHost): FileSystemResolver * * Unless overridden, `/.src` will be the current working directory for the virtual file system. */ -export function createFromFileSystem(host: FileSystemResolverHost, ignoreCase: boolean, { documents, files, cwd, time, meta }: FileSystemCreateOptions = {}) { +export function createFromFileSystem( + host: FileSystemResolverHost, + ignoreCase: boolean, + { documents, files, cwd, time, meta }: FileSystemCreateOptions = {}, +) { const fs = getBuiltLocal(host, ignoreCase).shadow(); if (meta) { for (const key of Object.keys(meta)) { @@ -1290,8 +1388,34 @@ export class Stats { public birthtime: Date; constructor(); - constructor(dev: number, ino: number, mode: number, nlink: number, rdev: number, size: number, blksize: number, blocks: number, atimeMs: number, mtimeMs: number, ctimeMs: number, birthtimeMs: number); - constructor(dev = 0, ino = 0, mode = 0, nlink = 0, rdev = 0, size = 0, blksize = 0, blocks = 0, atimeMs = 0, mtimeMs = 0, ctimeMs = 0, birthtimeMs = 0) { + constructor( + dev: number, + ino: number, + mode: number, + nlink: number, + rdev: number, + size: number, + blksize: number, + blocks: number, + atimeMs: number, + mtimeMs: number, + ctimeMs: number, + birthtimeMs: number, + ); + constructor( + dev = 0, + ino = 0, + mode = 0, + nlink = 0, + rdev = 0, + size = 0, + blksize = 0, + blocks = 0, + atimeMs = 0, + mtimeMs = 0, + ctimeMs = 0, + birthtimeMs = 0, + ) { this.dev = dev; this.ino = ino; this.mode = mode; @@ -1554,15 +1678,15 @@ function getBuiltLocal(host: FileSystemResolverHost, ignoreCase: boolean): FileS /* eslint-disable no-null/no-null */ function normalizeFileSetEntry(value: FileSet[string]) { if ( - value === undefined || - value === null || - value instanceof Directory || - value instanceof File || - value instanceof Link || - value instanceof Symlink || - value instanceof Mount || - value instanceof Rmdir || - value instanceof Unlink + value === undefined + || value === null + || value instanceof Directory + || value instanceof File + || value instanceof Link + || value instanceof Symlink + || value instanceof Mount + || value instanceof Rmdir + || value instanceof Unlink ) { return value; } diff --git a/src/harness/vpathUtil.ts b/src/harness/vpathUtil.ts index 0e84144cf0958..aff65f8967adc 100644 --- a/src/harness/vpathUtil.ts +++ b/src/harness/vpathUtil.ts @@ -54,10 +54,12 @@ export const enum ValidationFlags { Root = RequireRoot | AllowRoot | AllowTrailingSeparator, /** Path must be a absolute */ - Absolute = RequireRoot | AllowRoot | AllowDirname | AllowBasename | AllowExtname | AllowTrailingSeparator | AllowNavigation, + Absolute = RequireRoot | AllowRoot | AllowDirname | AllowBasename | AllowExtname | AllowTrailingSeparator + | AllowNavigation, /** Path may be relative or absolute */ - RelativeOrAbsolute = AllowRoot | AllowDirname | AllowBasename | AllowExtname | AllowTrailingSeparator | AllowNavigation, + RelativeOrAbsolute = AllowRoot | AllowDirname | AllowBasename | AllowExtname | AllowTrailingSeparator + | AllowNavigation, /** Path may only be a filename */ Basename = RequireBasename | AllowExtname, @@ -69,8 +71,10 @@ function validateComponents(components: string[], flags: ValidationFlags, hasTra const hasBasename = components.length > 1; const hasExtname = hasBasename && extRegExp.test(components[components.length - 1]); const invalidComponentRegExp = flags & ValidationFlags.AllowNavigation - ? flags & ValidationFlags.AllowWildcard ? invalidNavigableComponentWithWildcardsRegExp : invalidNavigableComponentRegExp - : flags & ValidationFlags.AllowWildcard ? invalidNonNavigableComponentWithWildcardsRegExp : invalidNonNavigableComponentRegExp; + ? flags & ValidationFlags.AllowWildcard ? invalidNavigableComponentWithWildcardsRegExp + : invalidNavigableComponentRegExp + : flags & ValidationFlags.AllowWildcard ? invalidNonNavigableComponentWithWildcardsRegExp + : invalidNonNavigableComponentRegExp; // Validate required components if (flags & ValidationFlags.RequireRoot && !hasRoot) return false; diff --git a/src/jsTyping/jsTyping.ts b/src/jsTyping/jsTyping.ts index b2c186d6ede10..d1692fce33cb1 100644 --- a/src/jsTyping/jsTyping.ts +++ b/src/jsTyping/jsTyping.ts @@ -35,7 +35,13 @@ export interface TypingResolutionHost { directoryExists(path: string): boolean; fileExists(fileName: string): boolean; readFile(path: string, encoding?: string): string | undefined; - readDirectory(rootDir: string, extensions: readonly string[], excludes: readonly string[] | undefined, includes: readonly string[] | undefined, depth?: number): string[]; + readDirectory( + rootDir: string, + extensions: readonly string[], + excludes: readonly string[] | undefined, + includes: readonly string[] | undefined, + depth?: number, + ): string[]; } interface PackageJson { @@ -56,7 +62,10 @@ export interface CachedTyping { /** @internal */ export function isTypingUpToDate(cachedTyping: CachedTyping, availableTypingVersions: MapLike) { - const availableVersion = new Version(getProperty(availableTypingVersions, `ts${versionMajorMinor}`) || getProperty(availableTypingVersions, "latest")!); + const availableVersion = new Version( + getProperty(availableTypingVersions, `ts${versionMajorMinor}`) + || getProperty(availableTypingVersions, "latest")!, + ); return availableVersion.compareTo(cachedTyping.version) <= 0; } @@ -214,7 +223,10 @@ export function discoverTypings( // Add the cached typing locations for inferred typings that are already installed packageNameToTypingLocation.forEach((typing, name) => { const registryEntry = typesRegistry.get(name); - if (inferredTypings.has(name) && inferredTypings.get(name) === undefined && registryEntry !== undefined && isTypingUpToDate(typing, registryEntry)) { + if ( + inferredTypings.has(name) && inferredTypings.get(name) === undefined && registryEntry !== undefined + && isTypingUpToDate(typing, registryEntry) + ) { inferredTypings.set(name, typing.typingLocation); } }); @@ -257,7 +269,12 @@ export function discoverTypings( * @param modulesDirName is the directory name for modules (node_modules or bower_components). Should be lowercase! * @param filesToWatch are the files to watch for changes. We will push things into this array. */ - function getTypingNames(projectRootPath: string, manifestName: string, modulesDirName: string, filesToWatch: string[]): void { + function getTypingNames( + projectRootPath: string, + manifestName: string, + modulesDirName: string, + filesToWatch: string[], + ): void { // First, we check the manifests themselves. They're not // _required_, but they allow us to do some filtering when dealing // with big flat dep directories. @@ -267,7 +284,12 @@ export function discoverTypings( if (host.fileExists(manifestPath)) { filesToWatch.push(manifestPath); manifest = readConfigFile(manifestPath, path => host.readFile(path)).config; - manifestTypingNames = flatMap([manifest.dependencies, manifest.devDependencies, manifest.optionalDependencies, manifest.peerDependencies], getOwnKeys); + manifestTypingNames = flatMap([ + manifest.dependencies, + manifest.devDependencies, + manifest.optionalDependencies, + manifest.peerDependencies, + ], getOwnKeys); addInferredTypings(manifestTypingNames, `Typing names in '${manifestPath}' dependencies`); } @@ -300,7 +322,13 @@ export function discoverTypings( // This is #1 described above. ? manifestTypingNames.map(typingName => combinePaths(packagesFolderPath, typingName, manifestName)) // And #2. Depth = 3 because scoped packages look like `node_modules/@foo/bar/package.json` - : host.readDirectory(packagesFolderPath, [Extension.Json], /*excludes*/ undefined, /*includes*/ undefined, /*depth*/ 3) + : host.readDirectory( + packagesFolderPath, + [Extension.Json], + /*excludes*/ undefined, + /*includes*/ undefined, + /*depth*/ 3, + ) .filter(manifestPath => { if (getBaseFileName(manifestPath) !== manifestName) { return false; @@ -312,11 +340,17 @@ export function discoverTypings( // packages. So that needs this dance here. const pathComponents = getPathComponents(normalizePath(manifestPath)); const isScoped = pathComponents[pathComponents.length - 3][0] === "@"; - return isScoped && toFileNameLowerCase(pathComponents[pathComponents.length - 4]) === modulesDirName || // `node_modules/@foo/bar` - !isScoped && toFileNameLowerCase(pathComponents[pathComponents.length - 3]) === modulesDirName; // `node_modules/foo` + return isScoped + && toFileNameLowerCase(pathComponents[pathComponents.length - 4]) === modulesDirName // `node_modules/@foo/bar` + || !isScoped + && toFileNameLowerCase(pathComponents[pathComponents.length - 3]) === modulesDirName; // `node_modules/foo` }); - if (log) log(`Searching for typing names in ${packagesFolderPath}; all files: ${JSON.stringify(dependencyManifestNames)}`); + if (log) { + log(`Searching for typing names in ${packagesFolderPath}; all files: ${ + JSON.stringify(dependencyManifestNames) + }`); + } // Once we have the names of things to look up, we iterate over // and either collect their included typings, or add them to the @@ -445,12 +479,17 @@ function validatePackageNameWorker(packageName: string, supportScopedPackage: bo /** @internal */ export function renderPackageNameValidationFailure(result: PackageNameValidationResult, typing: string): string { - return typeof result === "object" ? - renderPackageNameValidationFailureWorker(typing, result.result, result.name, result.isScopeName) : - renderPackageNameValidationFailureWorker(typing, result, typing, /*isScopeName*/ false); + return typeof result === "object" + ? renderPackageNameValidationFailureWorker(typing, result.result, result.name, result.isScopeName) + : renderPackageNameValidationFailureWorker(typing, result, typing, /*isScopeName*/ false); } -function renderPackageNameValidationFailureWorker(typing: string, result: NameValidationResult, name: string, isScopeName: boolean): string { +function renderPackageNameValidationFailureWorker( + typing: string, + result: NameValidationResult, + name: string, + isScopeName: boolean, +): string { const kind = isScopeName ? "Scope" : "Package"; switch (result) { case NameValidationResult.EmptyName: diff --git a/src/jsTyping/shared.ts b/src/jsTyping/shared.ts index 5ae0e09354c75..c0c4c0c1f5145 100644 --- a/src/jsTyping/shared.ts +++ b/src/jsTyping/shared.ts @@ -64,5 +64,7 @@ export function findArgument(argumentName: string): string | undefined { export function nowString() { // E.g. "12:34:56.789" const d = new Date(); - return `${padLeft(d.getHours().toString(), 2, "0")}:${padLeft(d.getMinutes().toString(), 2, "0")}:${padLeft(d.getSeconds().toString(), 2, "0")}.${padLeft(d.getMilliseconds().toString(), 3, "0")}`; + return `${padLeft(d.getHours().toString(), 2, "0")}:${padLeft(d.getMinutes().toString(), 2, "0")}:${ + padLeft(d.getSeconds().toString(), 2, "0") + }.${padLeft(d.getMilliseconds().toString(), 3, "0")}`; } diff --git a/src/jsTyping/types.ts b/src/jsTyping/types.ts index a9991a2f086c7..b428ba1f9f408 100644 --- a/src/jsTyping/types.ts +++ b/src/jsTyping/types.ts @@ -18,7 +18,15 @@ import { } from "./_namespaces/ts.server"; export interface TypingInstallerResponse { - readonly kind: ActionSet | ActionInvalidate | EventTypesRegistry | ActionPackageInstalled | EventBeginInstallTypes | EventEndInstallTypes | EventInitializationFailed | ActionWatchTypingLocations; + readonly kind: + | ActionSet + | ActionInvalidate + | EventTypesRegistry + | ActionPackageInstalled + | EventBeginInstallTypes + | EventEndInstallTypes + | EventInitializationFailed + | ActionWatchTypingLocations; } export interface TypingInstallerRequestWithProjectName { @@ -117,4 +125,11 @@ export interface WatchTypingLocations extends ProjectResponse { } /** @internal */ -export type TypingInstallerResponseUnion = SetTypings | InvalidateCachedTypings | TypesRegistryResponse | PackageInstalledResponse | InstallTypes | InitializationFailedResponse | WatchTypingLocations; +export type TypingInstallerResponseUnion = + | SetTypings + | InvalidateCachedTypings + | TypesRegistryResponse + | PackageInstalledResponse + | InstallTypes + | InitializationFailedResponse + | WatchTypingLocations; diff --git a/src/lib/decorators.d.ts b/src/lib/decorators.d.ts index 69b2d9ec3d970..e0815367dfbe8 100644 --- a/src/lib/decorators.d.ts +++ b/src/lib/decorators.d.ts @@ -17,7 +17,8 @@ type DecoratorContext = type DecoratorMetadataObject = Record & object; -type DecoratorMetadata = typeof globalThis extends { Symbol: { readonly metadata: symbol; }; } ? DecoratorMetadataObject : DecoratorMetadataObject | undefined; +type DecoratorMetadata = typeof globalThis extends { Symbol: { readonly metadata: symbol; }; } ? DecoratorMetadataObject + : DecoratorMetadataObject | undefined; /** * Context provided to a class decorator. diff --git a/src/lib/decorators.legacy.d.ts b/src/lib/decorators.legacy.d.ts index 2207e50bbda2d..79d794d0f3970 100644 --- a/src/lib/decorators.legacy.d.ts +++ b/src/lib/decorators.legacy.d.ts @@ -1,4 +1,12 @@ declare type ClassDecorator = (target: TFunction) => TFunction | void; declare type PropertyDecorator = (target: Object, propertyKey: string | symbol) => void; -declare type MethodDecorator = (target: Object, propertyKey: string | symbol, descriptor: TypedPropertyDescriptor) => TypedPropertyDescriptor | void; -declare type ParameterDecorator = (target: Object, propertyKey: string | symbol | undefined, parameterIndex: number) => void; +declare type MethodDecorator = ( + target: Object, + propertyKey: string | symbol, + descriptor: TypedPropertyDescriptor, +) => TypedPropertyDescriptor | void; +declare type ParameterDecorator = ( + target: Object, + propertyKey: string | symbol | undefined, + parameterIndex: number, +) => void; diff --git a/src/lib/es2015.core.d.ts b/src/lib/es2015.core.d.ts index 397e19639a3d9..0195237d95a41 100644 --- a/src/lib/es2015.core.d.ts +++ b/src/lib/es2015.core.d.ts @@ -329,7 +329,10 @@ interface ReadonlyArray { * @param thisArg If provided, it will be used as the this value for each invocation of * predicate. If it is not provided, undefined is used instead. */ - find(predicate: (value: T, index: number, obj: readonly T[]) => value is S, thisArg?: any): S | undefined; + find( + predicate: (value: T, index: number, obj: readonly T[]) => value is S, + thisArg?: any, + ): S | undefined; find(predicate: (value: T, index: number, obj: readonly T[]) => unknown, thisArg?: any): T | undefined; /** diff --git a/src/lib/es2015.promise.d.ts b/src/lib/es2015.promise.d.ts index e4925d8b14962..3636347d1f1f8 100644 --- a/src/lib/es2015.promise.d.ts +++ b/src/lib/es2015.promise.d.ts @@ -10,7 +10,9 @@ interface PromiseConstructor { * a resolve callback used to resolve the promise with a value or the result of another promise, * and a reject callback used to reject the promise with a provided reason or error. */ - new (executor: (resolve: (value: T | PromiseLike) => void, reject: (reason?: any) => void) => void): Promise; + new ( + executor: (resolve: (value: T | PromiseLike) => void, reject: (reason?: any) => void) => void, + ): Promise; /** * Creates a Promise that is resolved with an array of results when all of the provided Promises diff --git a/src/lib/es2015.reflect.d.ts b/src/lib/es2015.reflect.d.ts index 4f4ddc404f02f..a3f74bbfeeb64 100644 --- a/src/lib/es2015.reflect.d.ts +++ b/src/lib/es2015.reflect.d.ts @@ -34,7 +34,11 @@ declare namespace Reflect { * @param propertyKey The property name. * @param attributes Descriptor for the property. It can be for a data property or an accessor property. */ - function defineProperty(target: object, propertyKey: PropertyKey, attributes: PropertyDescriptor & ThisType): boolean; + function defineProperty( + target: object, + propertyKey: PropertyKey, + attributes: PropertyDescriptor & ThisType, + ): boolean; /** * Removes a property from an object, equivalent to `delete target[propertyKey]`, diff --git a/src/lib/es2015.symbol.wellknown.d.ts b/src/lib/es2015.symbol.wellknown.d.ts index cf6ccef52b89f..ab18c1f5ddf45 100644 --- a/src/lib/es2015.symbol.wellknown.d.ts +++ b/src/lib/es2015.symbol.wellknown.d.ts @@ -227,14 +227,22 @@ interface String { * @param searchValue An object that supports searching for and replacing matches within a string. * @param replaceValue The replacement text. */ - replace(searchValue: { [Symbol.replace](string: string, replaceValue: string): string; }, replaceValue: string): string; + replace( + searchValue: { [Symbol.replace](string: string, replaceValue: string): string; }, + replaceValue: string, + ): string; /** * Replaces text in a string, using an object that supports replacement within a string. * @param searchValue A object can search for and replace matches within a string. * @param replacer A function that returns the replacement text. */ - replace(searchValue: { [Symbol.replace](string: string, replacer: (substring: string, ...args: any[]) => string): string; }, replacer: (substring: string, ...args: any[]) => string): string; + replace( + searchValue: { + [Symbol.replace](string: string, replacer: (substring: string, ...args: any[]) => string): string; + }, + replacer: (substring: string, ...args: any[]) => string, + ): string; /** * Finds the first substring match in a regular expression search. diff --git a/src/lib/es2017.date.d.ts b/src/lib/es2017.date.d.ts index 0d3434964b64c..ebd08ea50fb2c 100644 --- a/src/lib/es2017.date.d.ts +++ b/src/lib/es2017.date.d.ts @@ -9,5 +9,13 @@ interface DateConstructor { * @param seconds Must be supplied if milliseconds is supplied. A number from 0 to 59 that specifies the seconds. * @param ms A number from 0 to 999 that specifies the milliseconds. */ - UTC(year: number, monthIndex?: number, date?: number, hours?: number, minutes?: number, seconds?: number, ms?: number): number; + UTC( + year: number, + monthIndex?: number, + date?: number, + hours?: number, + minutes?: number, + seconds?: number, + ms?: number, + ): number; } diff --git a/src/lib/es2017.object.d.ts b/src/lib/es2017.object.d.ts index 139cc5b81ba39..43e234a3c4dd2 100644 --- a/src/lib/es2017.object.d.ts +++ b/src/lib/es2017.object.d.ts @@ -27,5 +27,7 @@ interface ObjectConstructor { * Returns an object containing all own property descriptors of an object * @param o Object that contains the properties and methods. This can be an object that you created or an existing Document Object Model (DOM) object. */ - getOwnPropertyDescriptors(o: T): { [P in keyof T]: TypedPropertyDescriptor; } & { [x: string]: PropertyDescriptor; }; + getOwnPropertyDescriptors( + o: T, + ): { [P in keyof T]: TypedPropertyDescriptor; } & { [x: string]: PropertyDescriptor; }; } diff --git a/src/lib/es2017.sharedmemory.d.ts b/src/lib/es2017.sharedmemory.d.ts index 0d93ba914e09e..77b88af98a408 100644 --- a/src/lib/es2017.sharedmemory.d.ts +++ b/src/lib/es2017.sharedmemory.d.ts @@ -31,28 +31,45 @@ interface Atomics { * Until this atomic operation completes, any other read or write operation against the array * will block. */ - add(typedArray: Int8Array | Uint8Array | Int16Array | Uint16Array | Int32Array | Uint32Array, index: number, value: number): number; + add( + typedArray: Int8Array | Uint8Array | Int16Array | Uint16Array | Int32Array | Uint32Array, + index: number, + value: number, + ): number; /** * Stores the bitwise AND of a value with the value at the given position in the array, * returning the original value. Until this atomic operation completes, any other read or * write operation against the array will block. */ - and(typedArray: Int8Array | Uint8Array | Int16Array | Uint16Array | Int32Array | Uint32Array, index: number, value: number): number; + and( + typedArray: Int8Array | Uint8Array | Int16Array | Uint16Array | Int32Array | Uint32Array, + index: number, + value: number, + ): number; /** * Replaces the value at the given position in the array if the original value equals the given * expected value, returning the original value. Until this atomic operation completes, any * other read or write operation against the array will block. */ - compareExchange(typedArray: Int8Array | Uint8Array | Int16Array | Uint16Array | Int32Array | Uint32Array, index: number, expectedValue: number, replacementValue: number): number; + compareExchange( + typedArray: Int8Array | Uint8Array | Int16Array | Uint16Array | Int32Array | Uint32Array, + index: number, + expectedValue: number, + replacementValue: number, + ): number; /** * Replaces the value at the given position in the array, returning the original value. Until * this atomic operation completes, any other read or write operation against the array will * block. */ - exchange(typedArray: Int8Array | Uint8Array | Int16Array | Uint16Array | Int32Array | Uint32Array, index: number, value: number): number; + exchange( + typedArray: Int8Array | Uint8Array | Int16Array | Uint16Array | Int32Array | Uint32Array, + index: number, + value: number, + ): number; /** * Returns a value indicating whether high-performance algorithms can use atomic operations @@ -65,27 +82,42 @@ interface Atomics { * Returns the value at the given position in the array. Until this atomic operation completes, * any other read or write operation against the array will block. */ - load(typedArray: Int8Array | Uint8Array | Int16Array | Uint16Array | Int32Array | Uint32Array, index: number): number; + load( + typedArray: Int8Array | Uint8Array | Int16Array | Uint16Array | Int32Array | Uint32Array, + index: number, + ): number; /** * Stores the bitwise OR of a value with the value at the given position in the array, * returning the original value. Until this atomic operation completes, any other read or write * operation against the array will block. */ - or(typedArray: Int8Array | Uint8Array | Int16Array | Uint16Array | Int32Array | Uint32Array, index: number, value: number): number; + or( + typedArray: Int8Array | Uint8Array | Int16Array | Uint16Array | Int32Array | Uint32Array, + index: number, + value: number, + ): number; /** * Stores a value at the given position in the array, returning the new value. Until this * atomic operation completes, any other read or write operation against the array will block. */ - store(typedArray: Int8Array | Uint8Array | Int16Array | Uint16Array | Int32Array | Uint32Array, index: number, value: number): number; + store( + typedArray: Int8Array | Uint8Array | Int16Array | Uint16Array | Int32Array | Uint32Array, + index: number, + value: number, + ): number; /** * Subtracts a value from the value at the given position in the array, returning the original * value. Until this atomic operation completes, any other read or write operation against the * array will block. */ - sub(typedArray: Int8Array | Uint8Array | Int16Array | Uint16Array | Int32Array | Uint32Array, index: number, value: number): number; + sub( + typedArray: Int8Array | Uint8Array | Int16Array | Uint16Array | Int32Array | Uint32Array, + index: number, + value: number, + ): number; /** * If the value at the given position in the array is equal to the provided value, the current @@ -109,7 +141,11 @@ interface Atomics { * returning the original value. Until this atomic operation completes, any other read or write * operation against the array will block. */ - xor(typedArray: Int8Array | Uint8Array | Int16Array | Uint16Array | Int32Array | Uint32Array, index: number, value: number): number; + xor( + typedArray: Int8Array | Uint8Array | Int16Array | Uint16Array | Int32Array | Uint32Array, + index: number, + value: number, + ): number; readonly [Symbol.toStringTag]: "Atomics"; } diff --git a/src/lib/es2018.intl.d.ts b/src/lib/es2018.intl.d.ts index 9dfc84ed364de..345fef902dc23 100644 --- a/src/lib/es2018.intl.d.ts +++ b/src/lib/es2018.intl.d.ts @@ -37,8 +37,29 @@ declare namespace Intl { }; // We can only have one definition for 'type' in TypeScript, and so you can learn where the keys come from here: - type ES2018NumberFormatPartType = "literal" | "nan" | "infinity" | "percent" | "integer" | "group" | "decimal" | "fraction" | "plusSign" | "minusSign" | "percentSign" | "currency" | "code" | "symbol" | "name"; - type ES2020NumberFormatPartType = "compact" | "exponentInteger" | "exponentMinusSign" | "exponentSeparator" | "unit" | "unknown"; + type ES2018NumberFormatPartType = + | "literal" + | "nan" + | "infinity" + | "percent" + | "integer" + | "group" + | "decimal" + | "fraction" + | "plusSign" + | "minusSign" + | "percentSign" + | "currency" + | "code" + | "symbol" + | "name"; + type ES2020NumberFormatPartType = + | "compact" + | "exponentInteger" + | "exponentMinusSign" + | "exponentSeparator" + | "unit" + | "unknown"; type NumberFormatPartTypes = ES2018NumberFormatPartType | ES2020NumberFormatPartType; interface NumberFormatPart { diff --git a/src/lib/es2019.array.d.ts b/src/lib/es2019.array.d.ts index bd3c5cec27712..b8479a36bad67 100644 --- a/src/lib/es2019.array.d.ts +++ b/src/lib/es2019.array.d.ts @@ -1,6 +1,7 @@ type FlatArray = { "done": Arr; - "recur": Arr extends ReadonlyArray ? FlatArray + "recur": Arr extends ReadonlyArray + ? FlatArray : Arr; }[Depth extends -1 ? "done" : "recur"]; diff --git a/src/lib/es2020.bigint.d.ts b/src/lib/es2020.bigint.d.ts index 597b3822792eb..2851cb7994329 100644 --- a/src/lib/es2020.bigint.d.ts +++ b/src/lib/es2020.bigint.d.ts @@ -45,27 +45,132 @@ interface BigIntToLocaleStringOptions { /** * The minimum number of integer digits to use. Possible values are from 1 to 21; the default is 1. */ - minimumIntegerDigits?: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21; + minimumIntegerDigits?: + | 1 + | 2 + | 3 + | 4 + | 5 + | 6 + | 7 + | 8 + | 9 + | 10 + | 11 + | 12 + | 13 + | 14 + | 15 + | 16 + | 17 + | 18 + | 19 + | 20 + | 21; /** * The minimum number of fraction digits to use. Possible values are from 0 to 20; the default for plain number and percent formatting is 0; the default for currency formatting is the number of minor unit digits provided by the {@link http://www.currency-iso.org/en/home/tables/table-a1.html ISO 4217 currency codes list} (2 if the list doesn't provide that information). */ - minimumFractionDigits?: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20; + minimumFractionDigits?: + | 0 + | 1 + | 2 + | 3 + | 4 + | 5 + | 6 + | 7 + | 8 + | 9 + | 10 + | 11 + | 12 + | 13 + | 14 + | 15 + | 16 + | 17 + | 18 + | 19 + | 20; /** * The maximum number of fraction digits to use. Possible values are from 0 to 20; the default for plain number formatting is the larger of minimumFractionDigits and 3; the default for currency formatting is the larger of minimumFractionDigits and the number of minor unit digits provided by the {@link http://www.currency-iso.org/en/home/tables/table-a1.html ISO 4217 currency codes list} (2 if the list doesn't provide that information); the default for percent formatting is the larger of minimumFractionDigits and 0. */ - maximumFractionDigits?: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20; + maximumFractionDigits?: + | 0 + | 1 + | 2 + | 3 + | 4 + | 5 + | 6 + | 7 + | 8 + | 9 + | 10 + | 11 + | 12 + | 13 + | 14 + | 15 + | 16 + | 17 + | 18 + | 19 + | 20; /** * The minimum number of significant digits to use. Possible values are from 1 to 21; the default is 1. */ - minimumSignificantDigits?: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21; + minimumSignificantDigits?: + | 1 + | 2 + | 3 + | 4 + | 5 + | 6 + | 7 + | 8 + | 9 + | 10 + | 11 + | 12 + | 13 + | 14 + | 15 + | 16 + | 17 + | 18 + | 19 + | 20 + | 21; /** * The maximum number of significant digits to use. Possible values are from 1 to 21; the default is 21. */ - maximumSignificantDigits?: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21; + maximumSignificantDigits?: + | 1 + | 2 + | 3 + | 4 + | 5 + | 6 + | 7 + | 8 + | 9 + | 10 + | 11 + | 12 + | 13 + | 14 + | 15 + | 16 + | 17 + | 18 + | 19 + | 20 + | 21; /** * The formatting that should be displayed for the number, the defaults is "standard" @@ -271,7 +376,9 @@ interface BigInt64Array { * the accumulation. The first call to the callbackfn function provides this value as an argument * instead of an array value. */ - reduce(callbackfn: (previousValue: bigint, currentValue: bigint, currentIndex: number, array: BigInt64Array) => bigint): bigint; + reduce( + callbackfn: (previousValue: bigint, currentValue: bigint, currentIndex: number, array: BigInt64Array) => bigint, + ): bigint; /** * Calls the specified callback function for all the elements in an array. The return value of @@ -283,7 +390,10 @@ interface BigInt64Array { * the accumulation. The first call to the callbackfn function provides this value as an argument * instead of an array value. */ - reduce(callbackfn: (previousValue: U, currentValue: bigint, currentIndex: number, array: BigInt64Array) => U, initialValue: U): U; + reduce( + callbackfn: (previousValue: U, currentValue: bigint, currentIndex: number, array: BigInt64Array) => U, + initialValue: U, + ): U; /** * Calls the specified callback function for all the elements in an array, in descending order. @@ -295,7 +405,9 @@ interface BigInt64Array { * the accumulation. The first call to the callbackfn function provides this value as an * argument instead of an array value. */ - reduceRight(callbackfn: (previousValue: bigint, currentValue: bigint, currentIndex: number, array: BigInt64Array) => bigint): bigint; + reduceRight( + callbackfn: (previousValue: bigint, currentValue: bigint, currentIndex: number, array: BigInt64Array) => bigint, + ): bigint; /** * Calls the specified callback function for all the elements in an array, in descending order. @@ -307,7 +419,10 @@ interface BigInt64Array { * the accumulation. The first call to the callbackfn function provides this value as an argument * instead of an array value. */ - reduceRight(callbackfn: (previousValue: U, currentValue: bigint, currentIndex: number, array: BigInt64Array) => U, initialValue: U): U; + reduceRight( + callbackfn: (previousValue: U, currentValue: bigint, currentIndex: number, array: BigInt64Array) => U, + initialValue: U, + ): U; /** Reverses the elements in the array. */ reverse(): this; @@ -465,7 +580,10 @@ interface BigUint64Array { * @param thisArg If provided, it will be used as the this value for each invocation of * predicate. If it is not provided, undefined is used instead. */ - find(predicate: (value: bigint, index: number, array: BigUint64Array) => boolean, thisArg?: any): bigint | undefined; + find( + predicate: (value: bigint, index: number, array: BigUint64Array) => boolean, + thisArg?: any, + ): bigint | undefined; /** * Returns the index of the first element in the array where predicate is true, and -1 @@ -543,7 +661,14 @@ interface BigUint64Array { * the accumulation. The first call to the callbackfn function provides this value as an argument * instead of an array value. */ - reduce(callbackfn: (previousValue: bigint, currentValue: bigint, currentIndex: number, array: BigUint64Array) => bigint): bigint; + reduce( + callbackfn: ( + previousValue: bigint, + currentValue: bigint, + currentIndex: number, + array: BigUint64Array, + ) => bigint, + ): bigint; /** * Calls the specified callback function for all the elements in an array. The return value of @@ -555,7 +680,10 @@ interface BigUint64Array { * the accumulation. The first call to the callbackfn function provides this value as an argument * instead of an array value. */ - reduce(callbackfn: (previousValue: U, currentValue: bigint, currentIndex: number, array: BigUint64Array) => U, initialValue: U): U; + reduce( + callbackfn: (previousValue: U, currentValue: bigint, currentIndex: number, array: BigUint64Array) => U, + initialValue: U, + ): U; /** * Calls the specified callback function for all the elements in an array, in descending order. @@ -567,7 +695,14 @@ interface BigUint64Array { * the accumulation. The first call to the callbackfn function provides this value as an * argument instead of an array value. */ - reduceRight(callbackfn: (previousValue: bigint, currentValue: bigint, currentIndex: number, array: BigUint64Array) => bigint): bigint; + reduceRight( + callbackfn: ( + previousValue: bigint, + currentValue: bigint, + currentIndex: number, + array: BigUint64Array, + ) => bigint, + ): bigint; /** * Calls the specified callback function for all the elements in an array, in descending order. @@ -579,7 +714,10 @@ interface BigUint64Array { * the accumulation. The first call to the callbackfn function provides this value as an argument * instead of an array value. */ - reduceRight(callbackfn: (previousValue: U, currentValue: bigint, currentIndex: number, array: BigUint64Array) => U, initialValue: U): U; + reduceRight( + callbackfn: (previousValue: U, currentValue: bigint, currentIndex: number, array: BigUint64Array) => U, + initialValue: U, + ): U; /** Reverses the elements in the array. */ reverse(): this; diff --git a/src/lib/es2020.intl.d.ts b/src/lib/es2020.intl.d.ts index 550edaaa6c848..a82f062b61781 100644 --- a/src/lib/es2020.intl.d.ts +++ b/src/lib/es2020.intl.d.ts @@ -82,7 +82,11 @@ declare namespace Intl { * * [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl#locales_argument). */ - type LocalesArgument = UnicodeBCP47LocaleIdentifier | Locale | readonly (UnicodeBCP47LocaleIdentifier | Locale)[] | undefined; + type LocalesArgument = + | UnicodeBCP47LocaleIdentifier + | Locale + | readonly (UnicodeBCP47LocaleIdentifier | Locale)[] + | undefined; /** * An object with some or all of properties of `options` parameter @@ -406,6 +410,9 @@ declare namespace Intl { * * [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DisplayNames/supportedLocalesOf). */ - supportedLocalesOf(locales?: LocalesArgument, options?: { localeMatcher?: RelativeTimeFormatLocaleMatcher; }): BCP47LanguageTag[]; + supportedLocalesOf( + locales?: LocalesArgument, + options?: { localeMatcher?: RelativeTimeFormatLocaleMatcher; }, + ): BCP47LanguageTag[]; }; } diff --git a/src/lib/es2020.promise.d.ts b/src/lib/es2020.promise.d.ts index a4ebc79a8df28..47018b45db8e1 100644 --- a/src/lib/es2020.promise.d.ts +++ b/src/lib/es2020.promise.d.ts @@ -17,7 +17,9 @@ interface PromiseConstructor { * @param values An array of Promises. * @returns A new Promise. */ - allSettled(values: T): Promise<{ -readonly [P in keyof T]: PromiseSettledResult>; }>; + allSettled( + values: T, + ): Promise<{ -readonly [P in keyof T]: PromiseSettledResult>; }>; /** * Creates a Promise that is resolved with an array of results when all diff --git a/src/lib/es2020.sharedmemory.d.ts b/src/lib/es2020.sharedmemory.d.ts index e8403c18ba82b..5c0680f41f492 100644 --- a/src/lib/es2020.sharedmemory.d.ts +++ b/src/lib/es2020.sharedmemory.d.ts @@ -18,7 +18,12 @@ interface Atomics { * expected value, returning the original value. Until this atomic operation completes, any * other read or write operation against the array will block. */ - compareExchange(typedArray: BigInt64Array | BigUint64Array, index: number, expectedValue: bigint, replacementValue: bigint): bigint; + compareExchange( + typedArray: BigInt64Array | BigUint64Array, + index: number, + expectedValue: bigint, + replacementValue: bigint, + ): bigint; /** * Replaces the value at the given position in the array, returning the original value. Until diff --git a/src/lib/es2021.intl.d.ts b/src/lib/es2021.intl.d.ts index b3835b8b1ff04..f0c4b96797862 100644 --- a/src/lib/es2021.intl.d.ts +++ b/src/lib/es2021.intl.d.ts @@ -17,7 +17,10 @@ declare namespace Intl { interface DateTimeFormat { formatRange(startDate: Date | number | bigint, endDate: Date | number | bigint): string; - formatRangeToParts(startDate: Date | number | bigint, endDate: Date | number | bigint): DateTimeRangeFormatPart[]; + formatRangeToParts( + startDate: Date | number | bigint, + endDate: Date | number | bigint, + ): DateTimeRangeFormatPart[]; } interface ResolvedDateTimeFormatOptions { @@ -143,6 +146,9 @@ declare namespace Intl { * * [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/ListFormat/supportedLocalesOf). */ - supportedLocalesOf(locales: BCP47LanguageTag | BCP47LanguageTag[], options?: Pick): BCP47LanguageTag[]; + supportedLocalesOf( + locales: BCP47LanguageTag | BCP47LanguageTag[], + options?: Pick, + ): BCP47LanguageTag[]; }; } diff --git a/src/lib/es2022.intl.d.ts b/src/lib/es2022.intl.d.ts index 7ed03b05e07ca..57af89a100803 100644 --- a/src/lib/es2022.intl.d.ts +++ b/src/lib/es2022.intl.d.ts @@ -85,7 +85,10 @@ declare namespace Intl { * * [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/Segmenter/supportedLocalesOf) */ - supportedLocalesOf(locales: BCP47LanguageTag | BCP47LanguageTag[], options?: Pick): BCP47LanguageTag[]; + supportedLocalesOf( + locales: BCP47LanguageTag | BCP47LanguageTag[], + options?: Pick, + ): BCP47LanguageTag[]; }; /** @@ -95,5 +98,7 @@ declare namespace Intl { * @param key A string indicating the category of values to return. * @returns A sorted array of the supported values. */ - function supportedValuesOf(key: "calendar" | "collation" | "currency" | "numberingSystem" | "timeZone" | "unit"): string[]; + function supportedValuesOf( + key: "calendar" | "collation" | "currency" | "numberingSystem" | "timeZone" | "unit", + ): string[]; } diff --git a/src/lib/es2022.sharedmemory.d.ts b/src/lib/es2022.sharedmemory.d.ts index e6803febf07fc..9944ce2a97598 100644 --- a/src/lib/es2022.sharedmemory.d.ts +++ b/src/lib/es2022.sharedmemory.d.ts @@ -7,7 +7,12 @@ interface Atomics { * @param value The expected value to test. * @param [timeout] The expected value to test. */ - waitAsync(typedArray: Int32Array, index: number, value: number, timeout?: number): { async: false; value: "not-equal" | "timed-out"; } | { async: true; value: Promise<"ok" | "timed-out">; }; + waitAsync( + typedArray: Int32Array, + index: number, + value: number, + timeout?: number, + ): { async: false; value: "not-equal" | "timed-out"; } | { async: true; value: Promise<"ok" | "timed-out">; }; /** * A non-blocking, asynchronous version of wait which is usable on the main thread. @@ -17,5 +22,10 @@ interface Atomics { * @param value The expected value to test. * @param [timeout] The expected value to test. */ - waitAsync(typedArray: BigInt64Array, index: number, value: bigint, timeout?: number): { async: false; value: "not-equal" | "timed-out"; } | { async: true; value: Promise<"ok" | "timed-out">; }; + waitAsync( + typedArray: BigInt64Array, + index: number, + value: bigint, + timeout?: number, + ): { async: false; value: "not-equal" | "timed-out"; } | { async: true; value: Promise<"ok" | "timed-out">; }; } diff --git a/src/lib/es5.d.ts b/src/lib/es5.d.ts index 17c33e776903f..5ec4faf01362c 100644 --- a/src/lib/es5.d.ts +++ b/src/lib/es5.d.ts @@ -207,7 +207,10 @@ interface ObjectConstructor { * Prevents the modification of existing property attributes and values, and prevents the addition of new properties. * @param o Object on which to lock the attributes. */ - freeze(o: T): Readonly; + freeze< + T extends { [idx: string]: U | null | undefined | object; }, + U extends string | bigint | number | boolean | symbol, + >(o: T): Readonly; /** * Prevents the modification of existing property attributes and values, and prevents the addition of new properties. @@ -308,7 +311,9 @@ type ThisParameterType = T extends (this: infer U, ...args: never) => any ? U /** * Removes the 'this' parameter from a function type. */ -type OmitThisParameter = unknown extends ThisParameterType ? T : T extends (...args: infer A) => infer R ? (...args: A) => R : T; +type OmitThisParameter = unknown extends ThisParameterType ? T + : T extends (...args: infer A) => infer R ? (...args: A) => R + : T; interface CallableFunction extends Function { /** @@ -344,7 +349,11 @@ interface CallableFunction extends Function { * @param thisArg The object to be used as the this object. * @param args Arguments to bind to the parameters of the function. */ - bind(this: (this: T, ...args: [...A, ...B]) => R, thisArg: T, ...args: A): (...args: B) => R; + bind( + this: (this: T, ...args: [...A, ...B]) => R, + thisArg: T, + ...args: A + ): (...args: B) => R; } interface NewableFunction extends Function { @@ -380,7 +389,11 @@ interface NewableFunction extends Function { * @param thisArg The object to be used as the this object. * @param args Arguments to bind to the parameters of the function. */ - bind(this: new (...args: [...A, ...B]) => R, thisArg: any, ...args: A): new (...args: B) => R; + bind( + this: new (...args: [...A, ...B]) => R, + thisArg: any, + ...args: A + ): new (...args: B) => R; } interface IArguments { @@ -908,7 +921,15 @@ interface DateConstructor { * @param seconds Must be supplied if milliseconds is supplied. A number from 0 to 59 that specifies the seconds. * @param ms A number from 0 to 999 that specifies the milliseconds. */ - new (year: number, monthIndex: number, date?: number, hours?: number, minutes?: number, seconds?: number, ms?: number): Date; + new ( + year: number, + monthIndex: number, + date?: number, + hours?: number, + minutes?: number, + seconds?: number, + ms?: number, + ): Date; (): string; readonly prototype: Date; /** @@ -926,7 +947,15 @@ interface DateConstructor { * @param seconds Must be supplied if milliseconds is supplied. A number from 0 to 59 that specifies the seconds. * @param ms A number from 0 to 999 that specifies the milliseconds. */ - UTC(year: number, monthIndex: number, date?: number, hours?: number, minutes?: number, seconds?: number, ms?: number): number; + UTC( + year: number, + monthIndex: number, + date?: number, + hours?: number, + minutes?: number, + seconds?: number, + ms?: number, + ): number; /** Returns the number of milliseconds elapsed since midnight, January 1, 1970 Universal Coordinated Time (UTC). */ now(): number; } @@ -1212,7 +1241,10 @@ interface ReadonlyArray { * @param thisArg An object to which the this keyword can refer in the predicate function. * If thisArg is omitted, undefined is used as the this value. */ - every(predicate: (value: T, index: number, array: readonly T[]) => value is S, thisArg?: any): this is readonly S[]; + every( + predicate: (value: T, index: number, array: readonly T[]) => value is S, + thisArg?: any, + ): this is readonly S[]; /** * Determines whether all the members of an array satisfy the specified test. * @param predicate A function that accepts up to three arguments. The every method calls @@ -1261,26 +1293,38 @@ interface ReadonlyArray { * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value. */ reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: readonly T[]) => T): T; - reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: readonly T[]) => T, initialValue: T): T; + reduce( + callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: readonly T[]) => T, + initialValue: T, + ): T; /** * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function. * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array. * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value. */ - reduce(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: readonly T[]) => U, initialValue: U): U; + reduce( + callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: readonly T[]) => U, + initialValue: U, + ): U; /** * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function. * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array. * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value. */ reduceRight(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: readonly T[]) => T): T; - reduceRight(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: readonly T[]) => T, initialValue: T): T; + reduceRight( + callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: readonly T[]) => T, + initialValue: T, + ): T; /** * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function. * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array. * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value. */ - reduceRight(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: readonly T[]) => U, initialValue: U): U; + reduceRight( + callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: readonly T[]) => U, + initialValue: U, + ): U; readonly [n: number]: T; } @@ -1458,20 +1502,29 @@ interface Array { * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array. * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value. */ - reduce(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U; + reduce( + callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, + initialValue: U, + ): U; /** * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function. * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array. * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value. */ reduceRight(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T): T; - reduceRight(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue: T): T; + reduceRight( + callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, + initialValue: T, + ): T; /** * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function. * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array. * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value. */ - reduceRight(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U; + reduceRight( + callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, + initialValue: U, + ): U; [n: number]: T; } @@ -1498,7 +1551,9 @@ interface TypedPropertyDescriptor { set?: (value: T) => void; } -declare type PromiseConstructorLike = new (executor: (resolve: (value: T | PromiseLike) => void, reject: (reason?: any) => void) => void) => PromiseLike; +declare type PromiseConstructorLike = new ( + executor: (resolve: (value: T | PromiseLike) => void, reject: (reason?: any) => void) => void, +) => PromiseLike; interface PromiseLike { /** @@ -1507,7 +1562,10 @@ interface PromiseLike { * @param onrejected The callback to execute when the Promise is rejected. * @returns A Promise for the completion of which ever callback is executed. */ - then(onfulfilled?: ((value: T) => TResult1 | PromiseLike) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike) | undefined | null): PromiseLike; + then( + onfulfilled?: ((value: T) => TResult1 | PromiseLike) | undefined | null, + onrejected?: ((reason: any) => TResult2 | PromiseLike) | undefined | null, + ): PromiseLike; } /** @@ -1520,25 +1578,30 @@ interface Promise { * @param onrejected The callback to execute when the Promise is rejected. * @returns A Promise for the completion of which ever callback is executed. */ - then(onfulfilled?: ((value: T) => TResult1 | PromiseLike) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike) | undefined | null): Promise; + then( + onfulfilled?: ((value: T) => TResult1 | PromiseLike) | undefined | null, + onrejected?: ((reason: any) => TResult2 | PromiseLike) | undefined | null, + ): Promise; /** * Attaches a callback for only the rejection of the Promise. * @param onrejected The callback to execute when the Promise is rejected. * @returns A Promise for the completion of the callback. */ - catch(onrejected?: ((reason: any) => TResult | PromiseLike) | undefined | null): Promise; + catch( + onrejected?: ((reason: any) => TResult | PromiseLike) | undefined | null, + ): Promise; } /** * Recursively unwraps the "awaited type" of a type. Non-promise "thenables" should resolve to `never`. This emulates the behavior of `await`. */ -type Awaited = T extends null | undefined ? T : // special case for `null | undefined` when not in `--strictNullChecks` mode - T extends object & { then(onfulfilled: infer F, ...args: infer _): any; } ? // `await` only unwraps object types with a callable `then`. Non-object types are not unwrapped - F extends ((value: infer V, ...args: infer _) => any) ? // if the argument to `then` is callable, extracts the first argument - Awaited : // recursively unwrap the value - never : // the argument to `then` was not callable - T; // non-object or non-thenable +type Awaited = T extends null | undefined ? T // special case for `null | undefined` when not in `--strictNullChecks` mode + : T extends object & { then(onfulfilled: infer F, ...args: infer _): any; } // `await` only unwraps object types with a callable `then`. Non-object types are not unwrapped + ? F extends ((value: infer V, ...args: infer _) => any) // if the argument to `then` is callable, extracts the first argument + ? Awaited // recursively unwrap the value + : never // the argument to `then` was not callable + : T; // non-object or non-thenable interface ArrayLike { readonly length: number; @@ -1608,7 +1671,8 @@ type Parameters any> = T extends (...args: infer P) /** * Obtain the parameters of a constructor function type in a tuple */ -type ConstructorParameters any> = T extends abstract new (...args: infer P) => any ? P : never; +type ConstructorParameters any> = T extends + abstract new (...args: infer P) => any ? P : never; /** * Obtain the return type of a function type @@ -1618,7 +1682,8 @@ type ReturnType any> = T extends (...args: any) => i /** * Obtain the return type of a constructor function type */ -type InstanceType any> = T extends abstract new (...args: any) => infer R ? R : any; +type InstanceType any> = T extends abstract new (...args: any) => infer R ? R + : any; /** * Convert string literal type to uppercase @@ -1982,8 +2047,13 @@ interface Int8Array { * the accumulation. The first call to the callbackfn function provides this value as an argument * instead of an array value. */ - reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Int8Array) => number): number; - reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Int8Array) => number, initialValue: number): number; + reduce( + callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Int8Array) => number, + ): number; + reduce( + callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Int8Array) => number, + initialValue: number, + ): number; /** * Calls the specified callback function for all the elements in an array. The return value of @@ -1995,7 +2065,10 @@ interface Int8Array { * the accumulation. The first call to the callbackfn function provides this value as an argument * instead of an array value. */ - reduce(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Int8Array) => U, initialValue: U): U; + reduce( + callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Int8Array) => U, + initialValue: U, + ): U; /** * Calls the specified callback function for all the elements in an array, in descending order. @@ -2007,8 +2080,13 @@ interface Int8Array { * the accumulation. The first call to the callbackfn function provides this value as an * argument instead of an array value. */ - reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Int8Array) => number): number; - reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Int8Array) => number, initialValue: number): number; + reduceRight( + callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Int8Array) => number, + ): number; + reduceRight( + callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Int8Array) => number, + initialValue: number, + ): number; /** * Calls the specified callback function for all the elements in an array, in descending order. @@ -2020,7 +2098,10 @@ interface Int8Array { * the accumulation. The first call to the callbackfn function provides this value as an argument * instead of an array value. */ - reduceRight(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Int8Array) => U, initialValue: U): U; + reduceRight( + callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Int8Array) => U, + initialValue: U, + ): U; /** * Reverses the elements in an Array. @@ -2262,8 +2343,13 @@ interface Uint8Array { * the accumulation. The first call to the callbackfn function provides this value as an argument * instead of an array value. */ - reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint8Array) => number): number; - reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint8Array) => number, initialValue: number): number; + reduce( + callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint8Array) => number, + ): number; + reduce( + callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint8Array) => number, + initialValue: number, + ): number; /** * Calls the specified callback function for all the elements in an array. The return value of @@ -2275,7 +2361,10 @@ interface Uint8Array { * the accumulation. The first call to the callbackfn function provides this value as an argument * instead of an array value. */ - reduce(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Uint8Array) => U, initialValue: U): U; + reduce( + callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Uint8Array) => U, + initialValue: U, + ): U; /** * Calls the specified callback function for all the elements in an array, in descending order. @@ -2287,8 +2376,13 @@ interface Uint8Array { * the accumulation. The first call to the callbackfn function provides this value as an * argument instead of an array value. */ - reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint8Array) => number): number; - reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint8Array) => number, initialValue: number): number; + reduceRight( + callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint8Array) => number, + ): number; + reduceRight( + callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint8Array) => number, + initialValue: number, + ): number; /** * Calls the specified callback function for all the elements in an array, in descending order. @@ -2300,7 +2394,10 @@ interface Uint8Array { * the accumulation. The first call to the callbackfn function provides this value as an argument * instead of an array value. */ - reduceRight(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Uint8Array) => U, initialValue: U): U; + reduceRight( + callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Uint8Array) => U, + initialValue: U, + ): U; /** * Reverses the elements in an Array. @@ -2462,7 +2559,10 @@ interface Uint8ClampedArray { * @param thisArg An object to which the this keyword can refer in the predicate function. * If thisArg is omitted, undefined is used as the this value. */ - filter(predicate: (value: number, index: number, array: Uint8ClampedArray) => any, thisArg?: any): Uint8ClampedArray; + filter( + predicate: (value: number, index: number, array: Uint8ClampedArray) => any, + thisArg?: any, + ): Uint8ClampedArray; /** * Returns the value of the first element in the array where predicate is true, and undefined @@ -2473,7 +2573,10 @@ interface Uint8ClampedArray { * @param thisArg If provided, it will be used as the this value for each invocation of * predicate. If it is not provided, undefined is used instead. */ - find(predicate: (value: number, index: number, obj: Uint8ClampedArray) => boolean, thisArg?: any): number | undefined; + find( + predicate: (value: number, index: number, obj: Uint8ClampedArray) => boolean, + thisArg?: any, + ): number | undefined; /** * Returns the index of the first element in the array where predicate is true, and -1 @@ -2531,7 +2634,10 @@ interface Uint8ClampedArray { * @param thisArg An object to which the this keyword can refer in the callbackfn function. * If thisArg is omitted, undefined is used as the this value. */ - map(callbackfn: (value: number, index: number, array: Uint8ClampedArray) => number, thisArg?: any): Uint8ClampedArray; + map( + callbackfn: (value: number, index: number, array: Uint8ClampedArray) => number, + thisArg?: any, + ): Uint8ClampedArray; /** * Calls the specified callback function for all the elements in an array. The return value of @@ -2543,8 +2649,23 @@ interface Uint8ClampedArray { * the accumulation. The first call to the callbackfn function provides this value as an argument * instead of an array value. */ - reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint8ClampedArray) => number): number; - reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint8ClampedArray) => number, initialValue: number): number; + reduce( + callbackfn: ( + previousValue: number, + currentValue: number, + currentIndex: number, + array: Uint8ClampedArray, + ) => number, + ): number; + reduce( + callbackfn: ( + previousValue: number, + currentValue: number, + currentIndex: number, + array: Uint8ClampedArray, + ) => number, + initialValue: number, + ): number; /** * Calls the specified callback function for all the elements in an array. The return value of @@ -2556,7 +2677,10 @@ interface Uint8ClampedArray { * the accumulation. The first call to the callbackfn function provides this value as an argument * instead of an array value. */ - reduce(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Uint8ClampedArray) => U, initialValue: U): U; + reduce( + callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Uint8ClampedArray) => U, + initialValue: U, + ): U; /** * Calls the specified callback function for all the elements in an array, in descending order. @@ -2568,8 +2692,23 @@ interface Uint8ClampedArray { * the accumulation. The first call to the callbackfn function provides this value as an * argument instead of an array value. */ - reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint8ClampedArray) => number): number; - reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint8ClampedArray) => number, initialValue: number): number; + reduceRight( + callbackfn: ( + previousValue: number, + currentValue: number, + currentIndex: number, + array: Uint8ClampedArray, + ) => number, + ): number; + reduceRight( + callbackfn: ( + previousValue: number, + currentValue: number, + currentIndex: number, + array: Uint8ClampedArray, + ) => number, + initialValue: number, + ): number; /** * Calls the specified callback function for all the elements in an array, in descending order. @@ -2581,7 +2720,10 @@ interface Uint8ClampedArray { * the accumulation. The first call to the callbackfn function provides this value as an argument * instead of an array value. */ - reduceRight(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Uint8ClampedArray) => U, initialValue: U): U; + reduceRight( + callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Uint8ClampedArray) => U, + initialValue: U, + ): U; /** * Reverses the elements in an Array. @@ -2823,8 +2965,13 @@ interface Int16Array { * the accumulation. The first call to the callbackfn function provides this value as an argument * instead of an array value. */ - reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Int16Array) => number): number; - reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Int16Array) => number, initialValue: number): number; + reduce( + callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Int16Array) => number, + ): number; + reduce( + callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Int16Array) => number, + initialValue: number, + ): number; /** * Calls the specified callback function for all the elements in an array. The return value of @@ -2836,7 +2983,10 @@ interface Int16Array { * the accumulation. The first call to the callbackfn function provides this value as an argument * instead of an array value. */ - reduce(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Int16Array) => U, initialValue: U): U; + reduce( + callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Int16Array) => U, + initialValue: U, + ): U; /** * Calls the specified callback function for all the elements in an array, in descending order. @@ -2848,8 +2998,13 @@ interface Int16Array { * the accumulation. The first call to the callbackfn function provides this value as an * argument instead of an array value. */ - reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Int16Array) => number): number; - reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Int16Array) => number, initialValue: number): number; + reduceRight( + callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Int16Array) => number, + ): number; + reduceRight( + callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Int16Array) => number, + initialValue: number, + ): number; /** * Calls the specified callback function for all the elements in an array, in descending order. @@ -2861,7 +3016,10 @@ interface Int16Array { * the accumulation. The first call to the callbackfn function provides this value as an argument * instead of an array value. */ - reduceRight(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Int16Array) => U, initialValue: U): U; + reduceRight( + callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Int16Array) => U, + initialValue: U, + ): U; /** * Reverses the elements in an Array. @@ -3104,8 +3262,13 @@ interface Uint16Array { * the accumulation. The first call to the callbackfn function provides this value as an argument * instead of an array value. */ - reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint16Array) => number): number; - reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint16Array) => number, initialValue: number): number; + reduce( + callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint16Array) => number, + ): number; + reduce( + callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint16Array) => number, + initialValue: number, + ): number; /** * Calls the specified callback function for all the elements in an array. The return value of @@ -3117,7 +3280,10 @@ interface Uint16Array { * the accumulation. The first call to the callbackfn function provides this value as an argument * instead of an array value. */ - reduce(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Uint16Array) => U, initialValue: U): U; + reduce( + callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Uint16Array) => U, + initialValue: U, + ): U; /** * Calls the specified callback function for all the elements in an array, in descending order. @@ -3129,8 +3295,13 @@ interface Uint16Array { * the accumulation. The first call to the callbackfn function provides this value as an * argument instead of an array value. */ - reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint16Array) => number): number; - reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint16Array) => number, initialValue: number): number; + reduceRight( + callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint16Array) => number, + ): number; + reduceRight( + callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint16Array) => number, + initialValue: number, + ): number; /** * Calls the specified callback function for all the elements in an array, in descending order. @@ -3142,7 +3313,10 @@ interface Uint16Array { * the accumulation. The first call to the callbackfn function provides this value as an argument * instead of an array value. */ - reduceRight(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Uint16Array) => U, initialValue: U): U; + reduceRight( + callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Uint16Array) => U, + initialValue: U, + ): U; /** * Reverses the elements in an Array. @@ -3384,8 +3558,13 @@ interface Int32Array { * the accumulation. The first call to the callbackfn function provides this value as an argument * instead of an array value. */ - reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Int32Array) => number): number; - reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Int32Array) => number, initialValue: number): number; + reduce( + callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Int32Array) => number, + ): number; + reduce( + callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Int32Array) => number, + initialValue: number, + ): number; /** * Calls the specified callback function for all the elements in an array. The return value of @@ -3397,7 +3576,10 @@ interface Int32Array { * the accumulation. The first call to the callbackfn function provides this value as an argument * instead of an array value. */ - reduce(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Int32Array) => U, initialValue: U): U; + reduce( + callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Int32Array) => U, + initialValue: U, + ): U; /** * Calls the specified callback function for all the elements in an array, in descending order. @@ -3409,8 +3591,13 @@ interface Int32Array { * the accumulation. The first call to the callbackfn function provides this value as an * argument instead of an array value. */ - reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Int32Array) => number): number; - reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Int32Array) => number, initialValue: number): number; + reduceRight( + callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Int32Array) => number, + ): number; + reduceRight( + callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Int32Array) => number, + initialValue: number, + ): number; /** * Calls the specified callback function for all the elements in an array, in descending order. @@ -3422,7 +3609,10 @@ interface Int32Array { * the accumulation. The first call to the callbackfn function provides this value as an argument * instead of an array value. */ - reduceRight(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Int32Array) => U, initialValue: U): U; + reduceRight( + callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Int32Array) => U, + initialValue: U, + ): U; /** * Reverses the elements in an Array. @@ -3664,8 +3854,13 @@ interface Uint32Array { * the accumulation. The first call to the callbackfn function provides this value as an argument * instead of an array value. */ - reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint32Array) => number): number; - reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint32Array) => number, initialValue: number): number; + reduce( + callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint32Array) => number, + ): number; + reduce( + callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint32Array) => number, + initialValue: number, + ): number; /** * Calls the specified callback function for all the elements in an array. The return value of @@ -3677,7 +3872,10 @@ interface Uint32Array { * the accumulation. The first call to the callbackfn function provides this value as an argument * instead of an array value. */ - reduce(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Uint32Array) => U, initialValue: U): U; + reduce( + callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Uint32Array) => U, + initialValue: U, + ): U; /** * Calls the specified callback function for all the elements in an array, in descending order. @@ -3689,8 +3887,13 @@ interface Uint32Array { * the accumulation. The first call to the callbackfn function provides this value as an * argument instead of an array value. */ - reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint32Array) => number): number; - reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint32Array) => number, initialValue: number): number; + reduceRight( + callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint32Array) => number, + ): number; + reduceRight( + callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint32Array) => number, + initialValue: number, + ): number; /** * Calls the specified callback function for all the elements in an array, in descending order. @@ -3702,7 +3905,10 @@ interface Uint32Array { * the accumulation. The first call to the callbackfn function provides this value as an argument * instead of an array value. */ - reduceRight(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Uint32Array) => U, initialValue: U): U; + reduceRight( + callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Uint32Array) => U, + initialValue: U, + ): U; /** * Reverses the elements in an Array. @@ -3945,8 +4151,13 @@ interface Float32Array { * the accumulation. The first call to the callbackfn function provides this value as an argument * instead of an array value. */ - reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Float32Array) => number): number; - reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Float32Array) => number, initialValue: number): number; + reduce( + callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Float32Array) => number, + ): number; + reduce( + callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Float32Array) => number, + initialValue: number, + ): number; /** * Calls the specified callback function for all the elements in an array. The return value of @@ -3958,7 +4169,10 @@ interface Float32Array { * the accumulation. The first call to the callbackfn function provides this value as an argument * instead of an array value. */ - reduce(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Float32Array) => U, initialValue: U): U; + reduce( + callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Float32Array) => U, + initialValue: U, + ): U; /** * Calls the specified callback function for all the elements in an array, in descending order. @@ -3970,8 +4184,13 @@ interface Float32Array { * the accumulation. The first call to the callbackfn function provides this value as an * argument instead of an array value. */ - reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Float32Array) => number): number; - reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Float32Array) => number, initialValue: number): number; + reduceRight( + callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Float32Array) => number, + ): number; + reduceRight( + callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Float32Array) => number, + initialValue: number, + ): number; /** * Calls the specified callback function for all the elements in an array, in descending order. @@ -3983,7 +4202,10 @@ interface Float32Array { * the accumulation. The first call to the callbackfn function provides this value as an argument * instead of an array value. */ - reduceRight(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Float32Array) => U, initialValue: U): U; + reduceRight( + callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Float32Array) => U, + initialValue: U, + ): U; /** * Reverses the elements in an Array. @@ -4226,8 +4448,13 @@ interface Float64Array { * the accumulation. The first call to the callbackfn function provides this value as an argument * instead of an array value. */ - reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Float64Array) => number): number; - reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Float64Array) => number, initialValue: number): number; + reduce( + callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Float64Array) => number, + ): number; + reduce( + callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Float64Array) => number, + initialValue: number, + ): number; /** * Calls the specified callback function for all the elements in an array. The return value of @@ -4239,7 +4466,10 @@ interface Float64Array { * the accumulation. The first call to the callbackfn function provides this value as an argument * instead of an array value. */ - reduce(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Float64Array) => U, initialValue: U): U; + reduce( + callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Float64Array) => U, + initialValue: U, + ): U; /** * Calls the specified callback function for all the elements in an array, in descending order. @@ -4251,8 +4481,13 @@ interface Float64Array { * the accumulation. The first call to the callbackfn function provides this value as an * argument instead of an array value. */ - reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Float64Array) => number): number; - reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Float64Array) => number, initialValue: number): number; + reduceRight( + callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Float64Array) => number, + ): number; + reduceRight( + callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Float64Array) => number, + initialValue: number, + ): number; /** * Calls the specified callback function for all the elements in an array, in descending order. @@ -4264,7 +4499,10 @@ interface Float64Array { * the accumulation. The first call to the callbackfn function provides this value as an argument * instead of an array value. */ - reduceRight(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Float64Array) => U, initialValue: U): U; + reduceRight( + callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Float64Array) => U, + initialValue: U, + ): U; /** * Reverses the elements in an Array. @@ -4374,7 +4612,25 @@ declare namespace Intl { numeric?: boolean | undefined; caseFirst?: "upper" | "lower" | "false" | undefined; sensitivity?: "base" | "accent" | "case" | "variant" | undefined; - collation?: "big5han" | "compat" | "dict" | "direct" | "ducet" | "emoji" | "eor" | "gb2312" | "phonebk" | "phonetic" | "pinyin" | "reformed" | "searchjl" | "stroke" | "trad" | "unihan" | "zhuyin" | undefined; + collation?: + | "big5han" + | "compat" + | "dict" + | "direct" + | "ducet" + | "emoji" + | "eor" + | "gb2312" + | "phonebk" + | "phonetic" + | "pinyin" + | "reformed" + | "searchjl" + | "stroke" + | "trad" + | "unihan" + | "zhuyin" + | undefined; ignorePunctuation?: boolean | undefined; } diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index 158e08f25d30e..92f5aa396a569 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -338,7 +338,9 @@ export interface SafeList { [name: string]: { match: RegExp; exclude?: (string | number)[][]; types?: string[]; }; } -function prepareConvertersForEnumLikeCompilerOptions(commandLineOptions: CommandLineOption[]): Map> { +function prepareConvertersForEnumLikeCompilerOptions( + commandLineOptions: CommandLineOption[], +): Map> { const map = new Map>(); for (const option of commandLineOptions) { if (typeof option.type === "object") { @@ -422,7 +424,9 @@ export function convertFormatOptions(protocolOptions: protocol.FormatCodeSetting return protocolOptions as any; } -export function convertCompilerOptions(protocolOptions: protocol.ExternalProjectCompilerOptions): CompilerOptions & protocol.CompileOnSaveMixin { +export function convertCompilerOptions( + protocolOptions: protocol.ExternalProjectCompilerOptions, +): CompilerOptions & protocol.CompileOnSaveMixin { compilerOptionConverters.forEach((mappedValues, id) => { const propertyValue = protocolOptions[id]; if (isString(propertyValue)) { @@ -432,21 +436,26 @@ export function convertCompilerOptions(protocolOptions: protocol.ExternalProject return protocolOptions as any; } -export function convertWatchOptions(protocolOptions: protocol.ExternalProjectCompilerOptions, currentDirectory?: string): WatchOptionsAndErrors | undefined { +export function convertWatchOptions( + protocolOptions: protocol.ExternalProjectCompilerOptions, + currentDirectory?: string, +): WatchOptionsAndErrors | undefined { let watchOptions: WatchOptions | undefined; let errors: Diagnostic[] | undefined; optionsForWatch.forEach(option => { const propertyValue = protocolOptions[option.name]; if (propertyValue === undefined) return; const mappedValues = watchOptionsConverters.get(option.name); - (watchOptions || (watchOptions = {}))[option.name] = mappedValues ? - isString(propertyValue) ? mappedValues.get(propertyValue.toLowerCase()) : propertyValue : - convertJsonOption(option, propertyValue, currentDirectory || "", errors || (errors = [])); + (watchOptions || (watchOptions = {}))[option.name] = mappedValues + ? isString(propertyValue) ? mappedValues.get(propertyValue.toLowerCase()) : propertyValue + : convertJsonOption(option, propertyValue, currentDirectory || "", errors || (errors = [])); }); return watchOptions && { watchOptions, errors }; } -export function convertTypeAcquisition(protocolOptions: protocol.InferredProjectCompilerOptions): TypeAcquisition | undefined { +export function convertTypeAcquisition( + protocolOptions: protocol.InferredProjectCompilerOptions, +): TypeAcquisition | undefined { let result: TypeAcquisition | undefined; typeAcquisitionDeclarations.forEach(option => { const propertyValue = protocolOptions[option.name]; @@ -522,7 +531,8 @@ const fileNamePropertyReader: FilePropertyReader = { } return result!; // TODO: GH#18217 }, - hasMixedContent: (fileName, extraFileExtensions) => some(extraFileExtensions, ext => ext.isMixedContent && fileExtensionIs(fileName, ext.extension)), + hasMixedContent: (fileName, extraFileExtensions) => + some(extraFileExtensions, ext => ext.isMixedContent && fileExtensionIs(fileName, ext.extension)), }; const externalFilePropertyReader: FilePropertyReader = { @@ -607,11 +617,15 @@ interface AncestorConfigFileInfo { type OpenScriptInfoOrClosedFileInfo = ScriptInfo | OriginalFileInfo; type OpenScriptInfoOrClosedOrConfigFileInfo = OpenScriptInfoOrClosedFileInfo | AncestorConfigFileInfo; -function isOpenScriptInfo(infoOrFileNameOrConfig: OpenScriptInfoOrClosedOrConfigFileInfo): infoOrFileNameOrConfig is ScriptInfo { +function isOpenScriptInfo( + infoOrFileNameOrConfig: OpenScriptInfoOrClosedOrConfigFileInfo, +): infoOrFileNameOrConfig is ScriptInfo { return !!(infoOrFileNameOrConfig as ScriptInfo).containingProjects; } -function isAncestorConfigFileInfo(infoOrFileNameOrConfig: OpenScriptInfoOrClosedOrConfigFileInfo): infoOrFileNameOrConfig is AncestorConfigFileInfo { +function isAncestorConfigFileInfo( + infoOrFileNameOrConfig: OpenScriptInfoOrClosedOrConfigFileInfo, +): infoOrFileNameOrConfig is AncestorConfigFileInfo { return !!(infoOrFileNameOrConfig as AncestorConfigFileInfo).configFileInfo; } @@ -692,13 +706,13 @@ export function forEachResolvedProjectReferenceProject( function callback(ref: ResolvedProjectReference, loadKind: ProjectReferenceProjectLoadKind) { const configFileName = toNormalizedPath(ref.sourceFile.fileName); const child = project.projectService.findConfiguredProjectByProjectName(configFileName) || ( - loadKind === ProjectReferenceProjectLoadKind.Find ? - undefined : - loadKind === ProjectReferenceProjectLoadKind.FindCreate ? - project.projectService.createConfiguredProject(configFileName) : - loadKind === ProjectReferenceProjectLoadKind.FindCreateLoad ? - project.projectService.createAndLoadConfiguredProject(configFileName, reason!) : - Debug.assertNever(loadKind) + loadKind === ProjectReferenceProjectLoadKind.Find + ? undefined + : loadKind === ProjectReferenceProjectLoadKind.FindCreate + ? project.projectService.createConfiguredProject(configFileName) + : loadKind === ProjectReferenceProjectLoadKind.FindCreateLoad + ? project.projectService.createAndLoadConfiguredProject(configFileName, reason!) + : Debug.assertNever(loadKind) ); return child && cb(child); @@ -713,7 +727,8 @@ function forEachResolvedProjectReferenceProjectWorker( projectService: ProjectService, seenResolvedRefs: Map | undefined, ): T | undefined { - const loadKind = parentOptions.disableReferencedProjectLoad ? ProjectReferenceProjectLoadKind.Find : projectReferenceProjectLoadKind; + const loadKind = parentOptions.disableReferencedProjectLoad ? ProjectReferenceProjectLoadKind.Find + : projectReferenceProjectLoadKind; return forEach(resolvedProjectReferences, ref => { if (!ref) return undefined; @@ -729,7 +744,15 @@ function forEachResolvedProjectReferenceProjectWorker( } (seenResolvedRefs || (seenResolvedRefs = new Map())).set(canonicalPath, loadKind); - return ref.references && forEachResolvedProjectReferenceProjectWorker(ref.references, ref.commandLine.options, cb, loadKind, projectService, seenResolvedRefs); + return ref.references + && forEachResolvedProjectReferenceProjectWorker( + ref.references, + ref.commandLine.options, + cb, + loadKind, + projectService, + seenResolvedRefs, + ); }); } @@ -737,8 +760,8 @@ function forEachPotentialProjectReference( project: ConfiguredProject, cb: (potentialProjectReference: NormalizedPath) => T | undefined, ): T | undefined { - return project.potentialProjectReferences && - forEachKey(project.potentialProjectReferences, cb); + return project.potentialProjectReferences + && forEachKey(project.potentialProjectReferences, cb); } function forEachAnyProjectReferenceKind( @@ -747,11 +770,11 @@ function forEachAnyProjectReferenceKind( cbProjectRef: (projectReference: ProjectReference) => T | undefined, cbPotentialProjectRef: (potentialProjectReference: NormalizedPath) => T | undefined, ): T | undefined { - return project.getCurrentProgram() ? - project.forEachResolvedProjectReference(cb) : - project.isInitialLoadPending() ? - forEachPotentialProjectReference(project, cbPotentialProjectRef) : - forEach(project.getProjectReferences(), cbProjectRef); + return project.getCurrentProgram() + ? project.forEachResolvedProjectReference(cb) + : project.isInitialLoadPending() + ? forEachPotentialProjectReference(project, cbPotentialProjectRef) + : forEach(project.getProjectReferences(), cbProjectRef); } function callbackRefProject( @@ -783,7 +806,9 @@ interface NodeModulesWatcher extends FileWatcher { } function getDetailWatchInfo(watchType: WatchType, project: Project | NormalizedPath | undefined) { - return `${isString(project) ? `Config: ${project} ` : project ? `Project: ${project.getProjectName()} ` : ""}WatchType: ${watchType}`; + return `${ + isString(project) ? `Config: ${project} ` : project ? `Project: ${project.getProjectName()} ` : "" + }WatchType: ${watchType}`; } function isScriptInfoWatchedFromNodeModules(info: ScriptInfo) { @@ -796,8 +821,8 @@ function isScriptInfoWatchedFromNodeModules(info: ScriptInfo) { * @internal */ export function projectContainsInfoDirectly(project: Project, info: ScriptInfo) { - return project.containsScriptInfo(info) && - !project.isSourceOfProjectReferenceRedirect(info.path); + return project.containsScriptInfo(info) + && !project.isSourceOfProjectReferenceRedirect(info.path); } /** @internal */ @@ -978,7 +1003,10 @@ export class ProjectService { readonly watchFactory: WatchFactory; /** @internal */ - private readonly sharedExtendedConfigFileWatchers = new Map>(); + private readonly sharedExtendedConfigFileWatchers = new Map< + Path, + SharedExtendedConfigFileWatcher + >(); /** @internal */ private readonly extendedConfigCache = new Map(); @@ -1011,7 +1039,8 @@ export class ProjectService { this.globalPlugins = opts.globalPlugins || emptyArray; this.pluginProbeLocations = opts.pluginProbeLocations || emptyArray; this.allowLocalPluginLoads = !!opts.allowLocalPluginLoads; - this.typesMapLocation = (opts.typesMapLocation === undefined) ? combinePaths(getDirectoryPath(this.getExecutingFilePath()), "typesMap.json") : opts.typesMapLocation; + this.typesMapLocation = (opts.typesMapLocation === undefined) + ? combinePaths(getDirectoryPath(this.getExecutingFilePath()), "typesMap.json") : opts.typesMapLocation; this.session = opts.session; if (opts.serverMode !== undefined) { @@ -1049,17 +1078,21 @@ export class ProjectService { extraFileExtensions: [], }; - this.documentRegistry = createDocumentRegistryInternal(this.host.useCaseSensitiveFileNames, this.currentDirectory, this); - const watchLogLevel = this.logger.hasLevel(LogLevel.verbose) ? WatchLogLevel.Verbose : - this.logger.loggingEnabled() ? WatchLogLevel.TriggerOnly : WatchLogLevel.None; + this.documentRegistry = createDocumentRegistryInternal( + this.host.useCaseSensitiveFileNames, + this.currentDirectory, + this, + ); + const watchLogLevel = this.logger.hasLevel(LogLevel.verbose) ? WatchLogLevel.Verbose + : this.logger.loggingEnabled() ? WatchLogLevel.TriggerOnly : WatchLogLevel.None; const log: (s: string) => void = watchLogLevel !== WatchLogLevel.None ? (s => this.logger.info(s)) : noop; this.packageJsonCache = createPackageJsonCache(this); - this.watchFactory = this.serverMode !== LanguageServiceMode.Semantic ? - { + this.watchFactory = this.serverMode !== LanguageServiceMode.Semantic + ? { watchFile: returnNoopFileWatcher, watchDirectory: returnNoopFileWatcher, - } : - getWatchFactory(this.host, watchLogLevel, log, getDetailWatchInfo); + } + : getWatchFactory(this.host, watchLogLevel, log, getDetailWatchInfo); opts.incrementalVerifier?.(this); } @@ -1086,7 +1119,8 @@ export class ProjectService { /** @internal */ getDocument(key: DocumentRegistryBucketKeyWithMode, path: Path): SourceFile | undefined { const info = this.getScriptInfoForPath(path); - return info && info.cacheSourceFile && info.cacheSourceFile.key === key ? info.cacheSourceFile.sourceFile : undefined; + return info && info.cacheSourceFile && info.cacheSourceFile.key === key ? info.cacheSourceFile.sourceFile + : undefined; } /** @internal */ @@ -1140,8 +1174,12 @@ export class ProjectService { updateTypingsForProject(response: SetTypings | InvalidateCachedTypings | PackageInstalledResponse): void; /** @internal */ - updateTypingsForProject(response: SetTypings | InvalidateCachedTypings | PackageInstalledResponse | BeginInstallTypes | EndInstallTypes): void; // eslint-disable-line @typescript-eslint/unified-signatures - updateTypingsForProject(response: SetTypings | InvalidateCachedTypings | PackageInstalledResponse | BeginInstallTypes | EndInstallTypes): void { + updateTypingsForProject( + response: SetTypings | InvalidateCachedTypings | PackageInstalledResponse | BeginInstallTypes | EndInstallTypes, + ): void; // eslint-disable-line @typescript-eslint/unified-signatures + updateTypingsForProject( + response: SetTypings | InvalidateCachedTypings | PackageInstalledResponse | BeginInstallTypes | EndInstallTypes, + ): void { const project = this.findProject(response.projectName); if (!project) { return; @@ -1149,11 +1187,23 @@ export class ProjectService { switch (response.kind) { case ActionSet: // Update the typing files and update the project - project.updateTypingFiles(this.typingsCache.updateTypingsForProject(response.projectName, response.compilerOptions, response.typeAcquisition, response.unresolvedImports, response.typings)); + project.updateTypingFiles( + this.typingsCache.updateTypingsForProject( + response.projectName, + response.compilerOptions, + response.typeAcquisition, + response.unresolvedImports, + response.typings, + ), + ); return; case ActionInvalidate: // Do not clear resolution cache, there was changes detected in typings, so enque typing request and let it get us correct results - this.typingsCache.enqueueInstallTypingsForProject(project, project.lastCachedUnresolvedImportsList, /*forceRefresh*/ true); + this.typingsCache.enqueueInstallTypingsForProject( + project, + project.lastCachedUnresolvedImportsList, + /*forceRefresh*/ true, + ); return; } } @@ -1280,8 +1330,14 @@ export class ProjectService { } } - setCompilerOptionsForInferredProjects(projectCompilerOptions: protocol.InferredProjectCompilerOptions, projectRootPath?: string): void { - Debug.assert(projectRootPath === undefined || this.useInferredProjectPerProjectRoot, "Setting compiler options per project root path is only supported when useInferredProjectPerProjectRoot is enabled"); + setCompilerOptionsForInferredProjects( + projectCompilerOptions: protocol.InferredProjectCompilerOptions, + projectRootPath?: string, + ): void { + Debug.assert( + projectRootPath === undefined || this.useInferredProjectPerProjectRoot, + "Setting compiler options per project root path is only supported when useInferredProjectPerProjectRoot is enabled", + ); const compilerOptions = convertCompilerOptions(projectCompilerOptions); const watchOptions = convertWatchOptions(projectCompilerOptions, projectRootPath); @@ -1312,9 +1368,10 @@ export class ProjectService { // - Inferred projects with a projectRootPath, if the new options apply to that // project root path. if ( - canonicalProjectRootPath ? - project.projectRootPath === canonicalProjectRootPath : - !project.projectRootPath || !this.compilerOptionsForInferredProjectsPerProjectRoot.has(project.projectRootPath) + canonicalProjectRootPath + ? project.projectRootPath === canonicalProjectRootPath + : !project.projectRootPath + || !this.compilerOptionsForInferredProjectsPerProjectRoot.has(project.projectRootPath) ) { project.setCompilerOptions(compilerOptions); project.setTypeAcquisition(typeAcquisition); @@ -1336,7 +1393,8 @@ export class ProjectService { if (isInferredProjectName(projectName)) { return findProjectByName(projectName, this.inferredProjects); } - return this.findExternalProjectByProjectName(projectName) || this.findConfiguredProjectByProjectName(toNormalizedPath(projectName)); + return this.findExternalProjectByProjectName(projectName) + || this.findConfiguredProjectByProjectName(toNormalizedPath(projectName)); } /** @internal */ @@ -1361,21 +1419,27 @@ export class ProjectService { /** @internal */ tryGetDefaultProjectForFile(fileNameOrScriptInfo: NormalizedPath | ScriptInfo): Project | undefined { - const scriptInfo = isString(fileNameOrScriptInfo) ? this.getScriptInfoForNormalizedPath(fileNameOrScriptInfo) : fileNameOrScriptInfo; + const scriptInfo = isString(fileNameOrScriptInfo) ? this.getScriptInfoForNormalizedPath(fileNameOrScriptInfo) + : fileNameOrScriptInfo; return scriptInfo && !scriptInfo.isOrphan() ? scriptInfo.getDefaultProject() : undefined; } /** @internal */ ensureDefaultProjectForFile(fileNameOrScriptInfo: NormalizedPath | ScriptInfo): Project { - return this.tryGetDefaultProjectForFile(fileNameOrScriptInfo) || this.doEnsureDefaultProjectForFile(fileNameOrScriptInfo); + return this.tryGetDefaultProjectForFile(fileNameOrScriptInfo) + || this.doEnsureDefaultProjectForFile(fileNameOrScriptInfo); } private doEnsureDefaultProjectForFile(fileNameOrScriptInfo: NormalizedPath | ScriptInfo): Project { this.ensureProjectStructuresUptoDate(); - const scriptInfo = isString(fileNameOrScriptInfo) ? this.getScriptInfoForNormalizedPath(fileNameOrScriptInfo) : fileNameOrScriptInfo; - return scriptInfo ? - scriptInfo.getDefaultProject() : - (this.logErrorForScriptInfoNotFound(isString(fileNameOrScriptInfo) ? fileNameOrScriptInfo : fileNameOrScriptInfo.fileName), Errors.ThrowNoProject()); + const scriptInfo = isString(fileNameOrScriptInfo) ? this.getScriptInfoForNormalizedPath(fileNameOrScriptInfo) + : fileNameOrScriptInfo; + return scriptInfo + ? scriptInfo.getDefaultProject() + : (this.logErrorForScriptInfoNotFound( + isString(fileNameOrScriptInfo) ? fileNameOrScriptInfo : fileNameOrScriptInfo.fileName, + ), + Errors.ThrowNoProject()); } getScriptInfoEnsuringProjectsUptoDate(uncheckedFileName: string) { @@ -1498,15 +1562,23 @@ export class ProjectService { * * @internal */ - private watchWildcardDirectory(directory: Path, flags: WatchDirectoryFlags, configFileName: NormalizedPath, config: ParsedConfig) { + private watchWildcardDirectory( + directory: Path, + flags: WatchDirectoryFlags, + configFileName: NormalizedPath, + config: ParsedConfig, + ) { return this.watchFactory.watchDirectory( directory, fileOrDirectory => { const fileOrDirectoryPath = this.toPath(fileOrDirectory); - const fsResult = config.cachedDirectoryStructureHost.addOrDeleteFileOrDirectory(fileOrDirectory, fileOrDirectoryPath); + const fsResult = config.cachedDirectoryStructureHost.addOrDeleteFileOrDirectory( + fileOrDirectory, + fileOrDirectoryPath, + ); if ( - getBaseFileName(fileOrDirectoryPath) === "package.json" && !isInsideNodeModules(fileOrDirectoryPath) && - (fsResult && fsResult.fileExists || !fsResult && this.host.fileExists(fileOrDirectoryPath)) + getBaseFileName(fileOrDirectoryPath) === "package.json" && !isInsideNodeModules(fileOrDirectoryPath) + && (fsResult && fsResult.fileExists || !fsResult && this.host.fileExists(fileOrDirectoryPath)) ) { this.logger.info(`Config: ${configFileName} Detected new package.json: ${fileOrDirectory}`); this.onAddPackageJson(fileOrDirectoryPath); @@ -1530,7 +1602,9 @@ export class ProjectService { ) return; // Reload is pending, do the reload - if (config.reloadLevel !== ConfigFileProgramReloadLevel.Full) config.reloadLevel = ConfigFileProgramReloadLevel.Partial; + if (config.reloadLevel !== ConfigFileProgramReloadLevel.Full) { + config.reloadLevel = ConfigFileProgramReloadLevel.Partial; + } config.projects.forEach((watchWildcardDirectories, projectCanonicalPath) => { if (!watchWildcardDirectories) return; const project = this.getConfiguredProjectByCanonicalConfigFilePath(projectCanonicalPath); @@ -1538,14 +1612,19 @@ export class ProjectService { // Load root file names for configured project with the config file name // But only schedule update if project references this config file - const reloadLevel = configuredProjectForConfig === project ? ConfigFileProgramReloadLevel.Partial : ConfigFileProgramReloadLevel.None; + const reloadLevel = configuredProjectForConfig === project ? ConfigFileProgramReloadLevel.Partial + : ConfigFileProgramReloadLevel.None; if (project.pendingReload !== undefined && project.pendingReload > reloadLevel) return; // don't trigger callback on open, existing files if (this.openFiles.has(fileOrDirectoryPath)) { const info = Debug.checkDefined(this.getScriptInfoForPath(fileOrDirectoryPath)); if (info.isAttached(project)) { - const loadLevelToSet = Math.max(reloadLevel, project.openFileWatchTriggered.get(fileOrDirectoryPath) || ConfigFileProgramReloadLevel.None) as ConfigFileProgramReloadLevel; + const loadLevelToSet = Math.max( + reloadLevel, + project.openFileWatchTriggered.get(fileOrDirectoryPath) + || ConfigFileProgramReloadLevel.None, + ) as ConfigFileProgramReloadLevel; project.openFileWatchTriggered.set(fileOrDirectoryPath, loadLevelToSet); } else { @@ -1567,7 +1646,10 @@ export class ProjectService { } /** @internal */ - private delayUpdateProjectsFromParsedConfigOnConfigFileChange(canonicalConfigFilePath: NormalizedPath, reloadReason: string) { + private delayUpdateProjectsFromParsedConfigOnConfigFileChange( + canonicalConfigFilePath: NormalizedPath, + reloadReason: string, + ) { const configFileExistenceInfo = this.configFileExistenceInfoCache.get(canonicalConfigFilePath); if (!configFileExistenceInfo?.config) return false; let scheduledAnyProjectUpdate = false; @@ -1588,7 +1670,9 @@ export class ProjectService { } else { // Change in referenced project config file - project.resolutionCache.removeResolutionsFromProjectReferenceRedirects(this.toPath(canonicalConfigFilePath)); + project.resolutionCache.removeResolutionsFromProjectReferenceRedirects( + this.toPath(canonicalConfigFilePath), + ); this.delayUpdateProjectGraph(project); } }); @@ -1605,9 +1689,9 @@ export class ProjectService { configFileExistenceInfo.exists = false; // Remove the configured project for this config file - const project = configFileExistenceInfo.config?.projects.has(canonicalConfigFilePath) ? - this.getConfiguredProjectByCanonicalConfigFilePath(canonicalConfigFilePath) : - undefined; + const project = configFileExistenceInfo.config?.projects.has(canonicalConfigFilePath) + ? this.getConfiguredProjectByCanonicalConfigFilePath(canonicalConfigFilePath) + : undefined; if (project) this.removeProject(project); } else { @@ -1616,7 +1700,10 @@ export class ProjectService { } // Update projects watching config - this.delayUpdateProjectsFromParsedConfigOnConfigFileChange(canonicalConfigFilePath, "Change in config file detected"); + this.delayUpdateProjectsFromParsedConfigOnConfigFileChange( + canonicalConfigFilePath, + "Change in config file detected", + ); // Reload the configured projects for the open files in the map as they are affected by this config file // If the configured project was deleted, we want to reload projects for all the open files including files @@ -1628,9 +1715,9 @@ export class ProjectService { configFileExistenceInfo.openFilesImpactedByConfigFile, /*clearSemanticCache*/ false, /*delayReload*/ true, - eventKind !== FileWatcherEventKind.Deleted ? - identity : // Reload open files if they are root of inferred project - returnTrue, // Reload all the open files impacted by config file + eventKind !== FileWatcherEventKind.Deleted + ? identity // Reload open files if they are root of inferred project + : returnTrue, // Reload all the open files impacted by config file "Change in config file detected", ); this.delayEnsureProjectForOpenFiles(); @@ -1638,7 +1725,11 @@ export class ProjectService { private removeProject(project: Project) { this.logger.info("`remove Project::"); - project.print(/*writeProjectFileNames*/ true, /*writeFileExplaination*/ true, /*writeFileVersionAndText*/ false); + project.print( + /*writeProjectFileNames*/ true, + /*writeFileExplaination*/ true, + /*writeFileVersionAndText*/ false, + ); project.close(); if (Debug.shouldAssert(AssertionLevel.Normal)) { @@ -1653,8 +1744,8 @@ export class ProjectService { mapDefinedIterator( this.filenameToScriptInfo.values(), info => - info.isAttached(project) ? - { + info.isAttached(project) + ? { fileName: info.fileName, projects: info.containingProjects.map(p => p.projectName), hasMixedContent: info.hasMixedContent, @@ -1690,19 +1781,19 @@ export class ProjectService { assignOrphanScriptInfoToInferredProject(info: ScriptInfo, projectRootPath: NormalizedPath | undefined) { Debug.assert(info.isOrphan()); - const project = this.getOrCreateInferredProjectForProjectRootPathIfEnabled(info, projectRootPath) || - this.getOrCreateSingleInferredProjectIfEnabled() || - this.getOrCreateSingleInferredWithoutProjectRoot( - info.isDynamic ? - projectRootPath || this.currentDirectory : - getDirectoryPath( - isRootedDiskPath(info.fileName) ? - info.fileName : - getNormalizedAbsolutePath( + const project = this.getOrCreateInferredProjectForProjectRootPathIfEnabled(info, projectRootPath) + || this.getOrCreateSingleInferredProjectIfEnabled() + || this.getOrCreateSingleInferredWithoutProjectRoot( + info.isDynamic + ? projectRootPath || this.currentDirectory + : getDirectoryPath( + isRootedDiskPath(info.fileName) + ? info.fileName + : getNormalizedAbsolutePath( info.fileName, - projectRootPath ? - this.getNormalizedAbsolutePath(projectRootPath) : - this.currentDirectory, + projectRootPath + ? this.getNormalizedAbsolutePath(projectRootPath) + : this.currentDirectory, ), ), ); @@ -1732,7 +1823,10 @@ export class ProjectService { // instead of scanning all open files const roots = inferredProject.getRootScriptInfos(); Debug.assert(roots.length === 1 || !!inferredProject.projectRootPath); - if (roots.length === 1 && forEach(roots[0].containingProjects, p => p !== roots[0].containingProjects[0] && !p.isOrphan())) { + if ( + roots.length === 1 + && forEach(roots[0].containingProjects, p => p !== roots[0].containingProjects[0] && !p.isOrphan()) + ) { inferredProject.removeFile(roots[0], /*fileExists*/ true, /*detachFromProject*/ true); } } @@ -1841,7 +1935,11 @@ export class ProjectService { } } - private configFileExists(configFileName: NormalizedPath, canonicalConfigFilePath: NormalizedPath, info: OpenScriptInfoOrClosedOrConfigFileInfo) { + private configFileExists( + configFileName: NormalizedPath, + canonicalConfigFilePath: NormalizedPath, + info: OpenScriptInfoOrClosedOrConfigFileInfo, + ) { let configFileExistenceInfo = this.configFileExistenceInfoCache.get(canonicalConfigFilePath); if (configFileExistenceInfo) { // By default the info would get impacted by presence of config file since its in the detection path @@ -1873,7 +1971,11 @@ export class ProjectService { } /** @internal */ - private createConfigFileWatcherForParsedConfig(configFileName: NormalizedPath, canonicalConfigFilePath: NormalizedPath, forProject: ConfiguredProject) { + private createConfigFileWatcherForParsedConfig( + configFileName: NormalizedPath, + canonicalConfigFilePath: NormalizedPath, + forProject: ConfiguredProject, + ) { const configFileExistenceInfo = this.configFileExistenceInfoCache.get(canonicalConfigFilePath)!; // When watching config file for parsed config, remove the noopFileWatcher that can be created for open files impacted by config file and watch for real if (!configFileExistenceInfo.watcher || configFileExistenceInfo.watcher === noopConfigFileWatcher) { @@ -1881,7 +1983,9 @@ export class ProjectService { configFileName, (_fileName, eventKind) => this.onConfigFileChanged(canonicalConfigFilePath, eventKind), PollingInterval.High, - this.getWatchOptionsFromProjectWatchOptions(configFileExistenceInfo?.config?.parsedCommandLine?.watchOptions), + this.getWatchOptionsFromProjectWatchOptions( + configFileExistenceInfo?.config?.parsedCommandLine?.watchOptions, + ), WatchType.ConfigFile, forProject, ); @@ -1895,8 +1999,8 @@ export class ProjectService { * Returns true if the configFileExistenceInfo is needed/impacted by open files that are root of inferred project */ private configFileExistenceImpactsRootOfInferredProject(configFileExistenceInfo: ConfigFileExistenceInfo) { - return configFileExistenceInfo.openFilesImpactedByConfigFile && - forEachEntry(configFileExistenceInfo.openFilesImpactedByConfigFile, identity); + return configFileExistenceInfo.openFilesImpactedByConfigFile + && forEachEntry(configFileExistenceInfo.openFilesImpactedByConfigFile, identity); } /** @internal */ @@ -1943,9 +2047,9 @@ export class ProjectService { // Close the config file watcher if there are no more open files that are root of inferred project // or if there are no projects that need to watch this config file existence info if ( - configFileExistenceInfo.watcher && - !configFileExistenceInfo.config && - !this.configFileExistenceImpactsRootOfInferredProject(configFileExistenceInfo) + configFileExistenceInfo.watcher + && !configFileExistenceInfo.config + && !this.configFileExistenceImpactsRootOfInferredProject(configFileExistenceInfo) ) { configFileExistenceInfo.watcher.close(); configFileExistenceInfo.watcher = undefined; @@ -1960,7 +2064,9 @@ export class ProjectService { this.forEachConfigFileLocation(info, canonicalConfigFilePath => { const configFileExistenceInfo = this.configFileExistenceInfoCache.get(canonicalConfigFilePath); if (configFileExistenceInfo) { - const infoIsRootOfInferredProject = configFileExistenceInfo.openFilesImpactedByConfigFile?.get(info.path); + const infoIsRootOfInferredProject = configFileExistenceInfo.openFilesImpactedByConfigFile?.get( + info.path, + ); // Delete the info from map, since this file is no more open configFileExistenceInfo.openFilesImpactedByConfigFile?.delete(info.path); @@ -1977,8 +2083,8 @@ export class ProjectService { // and there is are no projects that need the config file existence or parsed config, // remove the cached existence info if ( - !configFileExistenceInfo.openFilesImpactedByConfigFile?.size && - !configFileExistenceInfo.config + !configFileExistenceInfo.openFilesImpactedByConfigFile?.size + && !configFileExistenceInfo.config ) { Debug.assert(!configFileExistenceInfo.watcher); this.configFileExistenceInfoCache.delete(canonicalConfigFilePath); @@ -2006,15 +2112,16 @@ export class ProjectService { (configFileExistenceInfo.openFilesImpactedByConfigFile ||= new Map()).set(info.path, true); // If there is no configured project for this config file, add the file watcher - configFileExistenceInfo.watcher ||= canWatchDirectoryOrFile(getPathComponents(getDirectoryPath(canonicalConfigFilePath) as Path)) ? - this.watchFactory.watchFile( - configFileName, - (_filename, eventKind) => this.onConfigFileChanged(canonicalConfigFilePath, eventKind), - PollingInterval.High, - this.hostConfiguration.watchOptions, - WatchType.ConfigFileForInferredRoot, - ) : - noopConfigFileWatcher; + configFileExistenceInfo.watcher ||= + canWatchDirectoryOrFile(getPathComponents(getDirectoryPath(canonicalConfigFilePath) as Path)) + ? this.watchFactory.watchFile( + configFileName, + (_filename, eventKind) => this.onConfigFileChanged(canonicalConfigFilePath, eventKind), + PollingInterval.High, + this.hostConfiguration.watchOptions, + WatchType.ConfigFileForInferredRoot, + ) + : noopConfigFileWatcher; }); } @@ -2046,7 +2153,10 @@ export class ProjectService { * The server must start searching from the directory containing * the newly opened file. */ - private forEachConfigFileLocation(info: OpenScriptInfoOrClosedOrConfigFileInfo, action: (canonicalConfigFilePath: NormalizedPath, configFileName: NormalizedPath) => boolean | void) { + private forEachConfigFileLocation( + info: OpenScriptInfoOrClosedOrConfigFileInfo, + action: (canonicalConfigFilePath: NormalizedPath, configFileName: NormalizedPath) => boolean | void, + ) { if (this.serverMode !== LanguageServiceMode.Semantic) { return undefined; } @@ -2057,7 +2167,8 @@ export class ProjectService { if (scriptInfo.isDynamic) return undefined; let searchPath = asNormalizedPath(getDirectoryPath(info.fileName)); - const isSearchPathInProjectRoot = () => containsPath(projectRootPath!, searchPath, this.currentDirectory, !this.host.useCaseSensitiveFileNames); + const isSearchPathInProjectRoot = () => + containsPath(projectRootPath!, searchPath, this.currentDirectory, !this.host.useCaseSensitiveFileNames); // If projectRootPath doesn't contain info.path, then do normal search for config file const anySearchPathOk = !projectRootPath || !isSearchPathInProjectRoot(); @@ -2065,9 +2176,16 @@ export class ProjectService { let searchInDirectory = !isAncestorConfigFileInfo(info); do { if (searchInDirectory) { - const canonicalSearchPath = normalizedPathToPath(searchPath, this.currentDirectory, this.toCanonicalFileName); + const canonicalSearchPath = normalizedPathToPath( + searchPath, + this.currentDirectory, + this.toCanonicalFileName, + ); const tsconfigFileName = asNormalizedPath(combinePaths(searchPath, "tsconfig.json")); - let result = action(combinePaths(canonicalSearchPath, "tsconfig.json") as NormalizedPath, tsconfigFileName); + let result = action( + combinePaths(canonicalSearchPath, "tsconfig.json") as NormalizedPath, + tsconfigFileName, + ); if (result) return tsconfigFileName; const jsconfigFileName = asNormalizedPath(combinePaths(searchPath, "jsconfig.json")); @@ -2096,12 +2214,12 @@ export class ProjectService { findDefaultConfiguredProject(info: ScriptInfo) { if (!info.isScriptOpen()) return undefined; const configFileName = this.getConfigFileNameForFile(info); - const project = configFileName && - this.findConfiguredProjectByProjectName(configFileName); + const project = configFileName + && this.findConfiguredProjectByProjectName(configFileName); - return project && projectContainsInfoDirectly(project, info) ? - project : - project?.getDefaultChildProjectFromProjectWithReferences(info); + return project && projectContainsInfoDirectly(project, info) + ? project + : project?.getDefaultChildProjectFromProjectWithReferences(info); } /** @@ -2121,7 +2239,11 @@ export class ProjectService { if (result !== undefined) return result || undefined; } this.logger.info(`Search path: ${getDirectoryPath(info.fileName)}`); - const configFileName = this.forEachConfigFileLocation(info, (canonicalConfigFilePath, configFileName) => this.configFileExists(configFileName, canonicalConfigFilePath, info)); + const configFileName = this.forEachConfigFileLocation( + info, + (canonicalConfigFilePath, configFileName) => + this.configFileExists(configFileName, canonicalConfigFilePath, info), + ); if (configFileName) { this.logger.info(`For info: ${info.fileName} :: Config file name: ${configFileName}`); } @@ -2162,7 +2284,9 @@ export class ProjectService { return this.getConfiguredProjectByCanonicalConfigFilePath(canonicalConfigFilePath); } - private getConfiguredProjectByCanonicalConfigFilePath(canonicalConfigFilePath: string): ConfiguredProject | undefined { + private getConfiguredProjectByCanonicalConfigFilePath( + canonicalConfigFilePath: string, + ): ConfiguredProject | undefined { return this.configuredProjects.get(canonicalConfigFilePath); } @@ -2171,7 +2295,12 @@ export class ProjectService { } /** Get a filename if the language service exceeds the maximum allowed program size; otherwise returns undefined. */ - private getFilenameForExceededTotalSizeLimitForNonTsFiles(name: string, options: CompilerOptions | undefined, fileNames: T[], propertyReader: FilePropertyReader): string | undefined { + private getFilenameForExceededTotalSizeLimitForNonTsFiles( + name: string, + options: CompilerOptions | undefined, + fileNames: T[], + propertyReader: FilePropertyReader, + ): string | undefined { if (options && options.disableSizeLimit || !this.host.getFileSize) { return; } @@ -2196,7 +2325,11 @@ export class ProjectService { .map(name => ({ name, size: this.host.getFileSize!(name) })) .sort((a, b) => b.size - a.size) .slice(0, 5); - this.logger.info(`Non TS file size exceeded limit (${totalNonTsFileSize}). Largest files: ${top5LargestFiles.map(file => `${file.name}:${file.size}`).join(", ")}`); + this.logger.info( + `Non TS file size exceeded limit (${totalNonTsFileSize}). Largest files: ${ + top5LargestFiles.map(file => `${file.name}:${file.size}`).join(", ") + }`, + ); // Keep the size as zero since it's disabled return fileName; } @@ -2204,7 +2337,13 @@ export class ProjectService { this.projectToSizeMap.set(name, totalNonTsFileSize); } - private createExternalProject(projectFileName: string, files: protocol.ExternalFile[], options: protocol.ExternalProjectCompilerOptions, typeAcquisition: TypeAcquisition, excludedFiles: NormalizedPath[]) { + private createExternalProject( + projectFileName: string, + files: protocol.ExternalFile[], + options: protocol.ExternalProjectCompilerOptions, + typeAcquisition: TypeAcquisition, + excludedFiles: NormalizedPath[], + ) { const compilerOptions = convertCompilerOptions(options); const watchOptionsAndErrors = convertWatchOptions(options, getDirectoryPath(normalizeSlashes(projectFileName))); const project = new ExternalProject( @@ -2212,7 +2351,12 @@ export class ProjectService { this, this.documentRegistry, compilerOptions, - /*lastFileExceededProgramSize*/ this.getFilenameForExceededTotalSizeLimitForNonTsFiles(projectFileName, compilerOptions, files, externalFilePropertyReader), + /*lastFileExceededProgramSize*/ this.getFilenameForExceededTotalSizeLimitForNonTsFiles( + projectFileName, + compilerOptions, + files, + externalFilePropertyReader, + ), options.compileOnSave === undefined ? true : options.compileOnSave, /*projectFilePath*/ undefined, watchOptionsAndErrors?.watchOptions, @@ -2274,7 +2418,12 @@ export class ProjectService { } } - private addFilesToNonInferredProject(project: ConfiguredProject | ExternalProject, files: T[], propertyReader: FilePropertyReader, typeAcquisition: TypeAcquisition): void { + private addFilesToNonInferredProject( + project: ConfiguredProject | ExternalProject, + files: T[], + propertyReader: FilePropertyReader, + typeAcquisition: TypeAcquisition, + ): void { this.updateNonInferredProjectFiles(project, files, propertyReader); project.setTypeAcquisition(typeAcquisition); } @@ -2295,7 +2444,11 @@ export class ProjectService { } if (!configFileExistenceInfo.config) { configFileExistenceInfo.config = { - cachedDirectoryStructureHost: createCachedDirectoryStructureHost(this.host, this.host.getCurrentDirectory(), this.host.useCaseSensitiveFileNames)!, + cachedDirectoryStructureHost: createCachedDirectoryStructureHost( + this.host, + this.host.getCurrentDirectory(), + this.host.useCaseSensitiveFileNames, + )!, projects: new Map(), reloadLevel: ConfigFileProgramReloadLevel.Full, }; @@ -2341,7 +2494,9 @@ export class ProjectService { * @internal */ private loadConfiguredProject(project: ConfiguredProject, reason: string) { - tracing?.push(tracing.Phase.Session, "loadConfiguredProject", { configFilePath: project.canonicalConfigFilePath }); + tracing?.push(tracing.Phase.Session, "loadConfiguredProject", { + configFilePath: project.canonicalConfigFilePath, + }); this.sendProjectLoadingStartEvent(project, reason); // Read updated contents from disk @@ -2368,10 +2523,17 @@ export class ProjectService { project.canConfigFileJsonReportNoInputFiles = canJsonReportNoInputFiles(parsedCommandLine.raw); project.setProjectErrors(parsedCommandLine.options.configFile!.parseDiagnostics); project.updateReferences(parsedCommandLine.projectReferences); - const lastFileExceededProgramSize = this.getFilenameForExceededTotalSizeLimitForNonTsFiles(project.canonicalConfigFilePath, compilerOptions, parsedCommandLine.fileNames, fileNamePropertyReader); + const lastFileExceededProgramSize = this.getFilenameForExceededTotalSizeLimitForNonTsFiles( + project.canonicalConfigFilePath, + compilerOptions, + parsedCommandLine.fileNames, + fileNamePropertyReader, + ); if (lastFileExceededProgramSize) { project.disableLanguageService(lastFileExceededProgramSize); - this.configFileExistenceInfoCache.forEach((_configFileExistenceInfo, canonicalConfigFilePath) => this.stopWatchingWildCards(canonicalConfigFilePath, project)); + this.configFileExistenceInfoCache.forEach((_configFileExistenceInfo, canonicalConfigFilePath) => + this.stopWatchingWildCards(canonicalConfigFilePath, project) + ); } else { project.setCompilerOptions(compilerOptions); @@ -2381,12 +2543,25 @@ export class ProjectService { } project.enablePluginsWithOptions(compilerOptions); const filesToAdd = parsedCommandLine.fileNames.concat(project.getExternalFiles()); - this.updateRootAndOptionsOfNonInferredProject(project, filesToAdd, fileNamePropertyReader, compilerOptions, parsedCommandLine.typeAcquisition!, parsedCommandLine.compileOnSave, parsedCommandLine.watchOptions); + this.updateRootAndOptionsOfNonInferredProject( + project, + filesToAdd, + fileNamePropertyReader, + compilerOptions, + parsedCommandLine.typeAcquisition!, + parsedCommandLine.compileOnSave, + parsedCommandLine.watchOptions, + ); tracing?.pop(); } /** @internal */ - ensureParsedConfigUptoDate(configFilename: NormalizedPath, canonicalConfigFilePath: NormalizedPath, configFileExistenceInfo: ConfigFileExistenceInfo, forProject: ConfiguredProject): ConfigFileExistenceInfo { + ensureParsedConfigUptoDate( + configFilename: NormalizedPath, + canonicalConfigFilePath: NormalizedPath, + configFileExistenceInfo: ConfigFileExistenceInfo, + forProject: ConfiguredProject, + ): ConfigFileExistenceInfo { if (configFileExistenceInfo.config) { if (!configFileExistenceInfo.config.reloadLevel) return configFileExistenceInfo; if (configFileExistenceInfo.config.reloadLevel === ConfigFileProgramReloadLevel.Partial) { @@ -2396,12 +2571,19 @@ export class ProjectService { } // Parse the config file and ensure its cached - const cachedDirectoryStructureHost = configFileExistenceInfo.config?.cachedDirectoryStructureHost || - createCachedDirectoryStructureHost(this.host, this.host.getCurrentDirectory(), this.host.useCaseSensitiveFileNames)!; + const cachedDirectoryStructureHost = configFileExistenceInfo.config?.cachedDirectoryStructureHost + || createCachedDirectoryStructureHost( + this.host, + this.host.getCurrentDirectory(), + this.host.useCaseSensitiveFileNames, + )!; // Read updated contents from disk const configFileContent = tryReadFile(configFilename, fileName => this.host.readFile(fileName)); - const configFile = parseJsonText(configFilename, isString(configFileContent) ? configFileContent : "") as TsConfigSourceFile; + const configFile = parseJsonText( + configFilename, + isString(configFileContent) ? configFileContent : "", + ) as TsConfigSourceFile; const configFileErrors = configFile.parseDiagnostics as Diagnostic[]; if (!isString(configFileContent)) configFileErrors.push(configFileContent); const parsedCommandLine = parseJsonSourceFileConfigFileContent( @@ -2468,13 +2650,21 @@ export class ProjectService { extendedConfigFileName, () => { // Update extended config cache - cleanExtendedConfigCache(this.extendedConfigCache, extendedConfigFilePath, fileName => this.toPath(fileName)); + cleanExtendedConfigCache(this.extendedConfigCache, extendedConfigFilePath, fileName => + this.toPath(fileName)); // Update projects let ensureProjectsForOpenFiles = false; - this.sharedExtendedConfigFileWatchers.get(extendedConfigFilePath)?.projects.forEach(canonicalPath => { - ensureProjectsForOpenFiles = this.delayUpdateProjectsFromParsedConfigOnConfigFileChange(canonicalPath, `Change in extended config file ${extendedConfigFileName} detected`) || ensureProjectsForOpenFiles; - }); - if (ensureProjectsForOpenFiles) this.delayEnsureProjectForOpenFiles(); + this.sharedExtendedConfigFileWatchers.get(extendedConfigFilePath)?.projects.forEach( + canonicalPath => { + ensureProjectsForOpenFiles = this.delayUpdateProjectsFromParsedConfigOnConfigFileChange( + canonicalPath, + `Change in extended config file ${extendedConfigFileName} detected`, + ) || ensureProjectsForOpenFiles; + }, + ); + if (ensureProjectsForOpenFiles) { + this.delayEnsureProjectForOpenFiles(); + } }, PollingInterval.High, this.hostConfiguration.watchOptions, @@ -2487,7 +2677,11 @@ export class ProjectService { } /** @internal */ - watchWildcards(configFileName: NormalizedPath, { exists, config }: ConfigFileExistenceInfo, forProject: ConfiguredProject) { + watchWildcards( + configFileName: NormalizedPath, + { exists, config }: ConfigFileExistenceInfo, + forProject: ConfiguredProject, + ) { config!.projects.set(forProject.canonicalConfigFilePath, true); if (exists) { if (config!.watchedDirectories && !config!.watchedDirectoriesStale) return; @@ -2511,8 +2705,8 @@ export class ProjectService { stopWatchingWildCards(canonicalConfigFilePath: NormalizedPath, forProject: ConfiguredProject) { const configFileExistenceInfo = this.configFileExistenceInfoCache.get(canonicalConfigFilePath)!; if ( - !configFileExistenceInfo.config || - !configFileExistenceInfo.config.projects.get(forProject.canonicalConfigFilePath) + !configFileExistenceInfo.config + || !configFileExistenceInfo.config.projects.get(forProject.canonicalConfigFilePath) ) { return; } @@ -2601,7 +2795,15 @@ export class ProjectService { project.markAsDirty(); } - private updateRootAndOptionsOfNonInferredProject(project: ExternalProject | ConfiguredProject, newUncheckedFiles: T[], propertyReader: FilePropertyReader, newOptions: CompilerOptions, newTypeAcquisition: TypeAcquisition, compileOnSave: boolean | undefined, watchOptions: WatchOptions | undefined) { + private updateRootAndOptionsOfNonInferredProject( + project: ExternalProject | ConfiguredProject, + newUncheckedFiles: T[], + propertyReader: FilePropertyReader, + newOptions: CompilerOptions, + newTypeAcquisition: TypeAcquisition, + compileOnSave: boolean | undefined, + watchOptions: WatchOptions | undefined, + ) { project.setCompilerOptions(newOptions); project.setWatchOptions(watchOptions); // VS only set the CompileOnSaveEnabled option in the request if the option was changed recently @@ -2618,9 +2820,16 @@ export class ProjectService { * @internal */ reloadFileNamesOfConfiguredProject(project: ConfiguredProject) { - const fileNames = this.reloadFileNamesOfParsedConfig(project.getConfigFilePath(), this.configFileExistenceInfoCache.get(project.canonicalConfigFilePath)!.config!); + const fileNames = this.reloadFileNamesOfParsedConfig( + project.getConfigFilePath(), + this.configFileExistenceInfoCache.get(project.canonicalConfigFilePath)!.config!, + ); project.updateErrorOnNoInputFiles(fileNames); - this.updateNonInferredProjectFiles(project, fileNames.concat(project.getExternalFiles()), fileNamePropertyReader); + this.updateNonInferredProjectFiles( + project, + fileNames.concat(project.getExternalFiles()), + fileNamePropertyReader, + ); return project.updateGraph(); } @@ -2650,7 +2859,12 @@ export class ProjectService { * * @internal */ - reloadConfiguredProject(project: ConfiguredProject, reason: string, isInitialLoad: boolean, clearSemanticCache: boolean) { + reloadConfiguredProject( + project: ConfiguredProject, + reason: string, + isInitialLoad: boolean, + clearSemanticCache: boolean, + ) { // At this point, there is no reason to not have configFile in the host const host = project.getCachedDirectoryStructureHost(); if (clearSemanticCache) this.clearSemanticCache(project); @@ -2690,11 +2904,14 @@ export class ProjectService { ); } - private getOrCreateInferredProjectForProjectRootPathIfEnabled(info: ScriptInfo, projectRootPath: NormalizedPath | undefined): InferredProject | undefined { + private getOrCreateInferredProjectForProjectRootPathIfEnabled( + info: ScriptInfo, + projectRootPath: NormalizedPath | undefined, + ): InferredProject | undefined { if ( - !this.useInferredProjectPerProjectRoot || + !this.useInferredProjectPerProjectRoot // Its a dynamic info opened without project root - (info.isDynamic && projectRootPath === undefined) + || (info.isDynamic && projectRootPath === undefined) ) { return undefined; } @@ -2717,7 +2934,14 @@ export class ProjectService { // ignore single inferred projects (handled elsewhere) if (!project.projectRootPath) continue; // ignore inferred projects that don't contain the root's path - if (!containsPath(project.projectRootPath, info.path, this.host.getCurrentDirectory(), !this.host.useCaseSensitiveFileNames)) continue; + if ( + !containsPath( + project.projectRootPath, + info.path, + this.host.getCurrentDirectory(), + !this.host.useCaseSensitiveFileNames, + ) + ) continue; // ignore inferred projects that are higher up in the project root. // TODO(rbuckton): Should we add the file as a root to these as well? if (bestMatch && bestMatch.projectRootPath!.length > project.projectRootPath.length) continue; @@ -2754,9 +2978,9 @@ export class ProjectService { // Reuse the project with same current directory but no roots for (const inferredProject of this.inferredProjects) { if ( - !inferredProject.projectRootPath && - inferredProject.isOrphan() && - inferredProject.canonicalCurrentDirectory === expectedCurrentDirectory + !inferredProject.projectRootPath + && inferredProject.isOrphan() + && inferredProject.canonicalCurrentDirectory === expectedCurrentDirectory ) { return inferredProject; } @@ -2765,8 +2989,14 @@ export class ProjectService { return this.createInferredProject(currentDirectory); } - private createInferredProject(currentDirectory: string, isSingleInferredProject?: boolean, projectRootPath?: NormalizedPath): InferredProject { - const compilerOptions = projectRootPath && this.compilerOptionsForInferredProjectsPerProjectRoot.get(projectRootPath) || this.compilerOptionsForInferredProjects!; // TODO: GH#18217 + private createInferredProject( + currentDirectory: string, + isSingleInferredProject?: boolean, + projectRootPath?: NormalizedPath, + ): InferredProject { + const compilerOptions = + projectRootPath && this.compilerOptionsForInferredProjectsPerProjectRoot.get(projectRootPath) + || this.compilerOptionsForInferredProjects!; // TODO: GH#18217 let watchOptionsAndErrors: WatchOptionsAndErrors | false | undefined; let typeAcquisition: TypeAcquisition | undefined; if (projectRootPath) { @@ -2780,7 +3010,15 @@ export class ProjectService { typeAcquisition = this.typeAcquisitionForInferredProjects; } watchOptionsAndErrors = watchOptionsAndErrors || undefined; - const project = new InferredProject(this, this.documentRegistry, compilerOptions, watchOptionsAndErrors?.watchOptions, projectRootPath, currentDirectory, typeAcquisition); + const project = new InferredProject( + this, + this.documentRegistry, + compilerOptions, + watchOptionsAndErrors?.watchOptions, + projectRootPath, + currentDirectory, + typeAcquisition, + ); project.setProjectErrors(watchOptionsAndErrors?.errors); if (isSingleInferredProject) { this.inferredProjects.unshift(project); @@ -2792,7 +3030,11 @@ export class ProjectService { } /** @internal */ - getOrCreateScriptInfoNotOpenedByClient(uncheckedFileName: string, currentDirectory: string, hostToQueryFileExistsOn: DirectoryStructureHost) { + getOrCreateScriptInfoNotOpenedByClient( + uncheckedFileName: string, + currentDirectory: string, + hostToQueryFileExistsOn: DirectoryStructureHost, + ) { return this.getOrCreateScriptInfoNotOpenedByClientForNormalizedPath( toNormalizedPath(uncheckedFileName), currentDirectory, @@ -2817,8 +3059,14 @@ export class ProjectService { /** @internal */ logErrorForScriptInfoNotFound(fileName: string): void { - const names = arrayFrom(this.filenameToScriptInfo.entries(), ([path, scriptInfo]) => ({ path, fileName: scriptInfo.fileName })); - this.logger.msg(`Could not find file ${JSON.stringify(fileName)}.\nAll files are: ${JSON.stringify(names)}`, Msg.Err); + const names = arrayFrom( + this.filenameToScriptInfo.entries(), + ([path, scriptInfo]) => ({ path, fileName: scriptInfo.fileName }), + ); + this.logger.msg( + `Could not find file ${JSON.stringify(fileName)}.\nAll files are: ${JSON.stringify(names)}`, + Msg.Err, + ); } /** @@ -2844,16 +3092,21 @@ export class ProjectService { for (const project of toAddInfo.containingProjects) { // Add the projects only if they can use symLink targets and not already in the list if ( - project.languageServiceEnabled && - !project.isOrphan() && - !project.getCompilerOptions().preserveSymlinks && - !info.isAttached(project) + project.languageServiceEnabled + && !project.isOrphan() + && !project.getCompilerOptions().preserveSymlinks + && !info.isAttached(project) ) { if (!projects) { projects = createMultiMap(); projects.add(toAddInfo.path, project); } - else if (!forEachEntry(projects, (projs, path) => path === toAddInfo.path ? false : contains(projs, project))) { + else if ( + !forEachEntry( + projects, + (projs, path) => path === toAddInfo.path ? false : contains(projs, project), + ) + ) { projects.add(toAddInfo.path, project); } } @@ -2867,9 +3120,9 @@ export class ProjectService { // do not watch files with mixed content - server doesn't know how to interpret it // do not watch files in the global cache location if ( - !info.isDynamicOrHasMixedContent() && - (!this.globalCacheLocationDirectoryPath || - !startsWith(info.path, this.globalCacheLocationDirectoryPath)) + !info.isDynamicOrHasMixedContent() + && (!this.globalCacheLocationDirectoryPath + || !startsWith(info.path, this.globalCacheLocationDirectoryPath)) ) { const indexOfNodeModules = info.path.indexOf("/node_modules/"); if (!this.host.getModifiedTime || indexOfNodeModules === -1) { @@ -2883,7 +3136,9 @@ export class ProjectService { } else { info.mTime = this.getModifiedTime(info); - info.fileWatcher = this.watchClosedScriptInfoInNodeModules(info.path.substr(0, indexOfNodeModules) as Path); + info.fileWatcher = this.watchClosedScriptInfoInNodeModules( + info.path.substr(0, indexOfNodeModules) as Path, + ); } } } @@ -3000,9 +3255,23 @@ export class ProjectService { } } - private getOrCreateScriptInfoNotOpenedByClientForNormalizedPath(fileName: NormalizedPath, currentDirectory: string, scriptKind: ScriptKind | undefined, hasMixedContent: boolean | undefined, hostToQueryFileExistsOn: DirectoryStructureHost | undefined) { + private getOrCreateScriptInfoNotOpenedByClientForNormalizedPath( + fileName: NormalizedPath, + currentDirectory: string, + scriptKind: ScriptKind | undefined, + hasMixedContent: boolean | undefined, + hostToQueryFileExistsOn: DirectoryStructureHost | undefined, + ) { if (isRootedDiskPath(fileName) || isDynamicFileName(fileName)) { - return this.getOrCreateScriptInfoWorker(fileName, currentDirectory, /*openedByClient*/ false, /*fileContent*/ undefined, scriptKind, hasMixedContent, hostToQueryFileExistsOn); + return this.getOrCreateScriptInfoWorker( + fileName, + currentDirectory, + /*openedByClient*/ false, + /*fileContent*/ undefined, + scriptKind, + hasMixedContent, + hostToQueryFileExistsOn, + ); } // This is non rooted path with different current directory than project service current directory @@ -3017,28 +3286,111 @@ export class ProjectService { return undefined; } - private getOrCreateScriptInfoOpenedByClientForNormalizedPath(fileName: NormalizedPath, currentDirectory: string, fileContent: string | undefined, scriptKind: ScriptKind | undefined, hasMixedContent: boolean | undefined) { - return this.getOrCreateScriptInfoWorker(fileName, currentDirectory, /*openedByClient*/ true, fileContent, scriptKind, hasMixedContent); + private getOrCreateScriptInfoOpenedByClientForNormalizedPath( + fileName: NormalizedPath, + currentDirectory: string, + fileContent: string | undefined, + scriptKind: ScriptKind | undefined, + hasMixedContent: boolean | undefined, + ) { + return this.getOrCreateScriptInfoWorker( + fileName, + currentDirectory, + /*openedByClient*/ true, + fileContent, + scriptKind, + hasMixedContent, + ); } - getOrCreateScriptInfoForNormalizedPath(fileName: NormalizedPath, openedByClient: boolean, fileContent?: string, scriptKind?: ScriptKind, hasMixedContent?: boolean, hostToQueryFileExistsOn?: { fileExists(path: string): boolean; }) { - return this.getOrCreateScriptInfoWorker(fileName, this.currentDirectory, openedByClient, fileContent, scriptKind, hasMixedContent, hostToQueryFileExistsOn); + getOrCreateScriptInfoForNormalizedPath( + fileName: NormalizedPath, + openedByClient: boolean, + fileContent?: string, + scriptKind?: ScriptKind, + hasMixedContent?: boolean, + hostToQueryFileExistsOn?: { fileExists(path: string): boolean; }, + ) { + return this.getOrCreateScriptInfoWorker( + fileName, + this.currentDirectory, + openedByClient, + fileContent, + scriptKind, + hasMixedContent, + hostToQueryFileExistsOn, + ); } - private getOrCreateScriptInfoWorker(fileName: NormalizedPath, currentDirectory: string, openedByClient: boolean, fileContent?: string, scriptKind?: ScriptKind, hasMixedContent?: boolean, hostToQueryFileExistsOn?: { fileExists(path: string): boolean; }) { - Debug.assert(fileContent === undefined || openedByClient, "ScriptInfo needs to be opened by client to be able to set its user defined content"); + private getOrCreateScriptInfoWorker( + fileName: NormalizedPath, + currentDirectory: string, + openedByClient: boolean, + fileContent?: string, + scriptKind?: ScriptKind, + hasMixedContent?: boolean, + hostToQueryFileExistsOn?: { fileExists(path: string): boolean; }, + ) { + Debug.assert( + fileContent === undefined || openedByClient, + "ScriptInfo needs to be opened by client to be able to set its user defined content", + ); const path = normalizedPathToPath(fileName, currentDirectory, this.toCanonicalFileName); let info = this.getScriptInfoForPath(path); if (!info) { const isDynamic = isDynamicFileName(fileName); - Debug.assert(isRootedDiskPath(fileName) || isDynamic || openedByClient, "", () => `${JSON.stringify({ fileName, currentDirectory, hostCurrentDirectory: this.currentDirectory, openKeys: arrayFrom(this.openFilesWithNonRootedDiskPath.keys()) })}\nScript info with non-dynamic relative file name can only be open script info or in context of host currentDirectory`); - Debug.assert(!isRootedDiskPath(fileName) || this.currentDirectory === currentDirectory || !this.openFilesWithNonRootedDiskPath.has(this.toCanonicalFileName(fileName)), "", () => `${JSON.stringify({ fileName, currentDirectory, hostCurrentDirectory: this.currentDirectory, openKeys: arrayFrom(this.openFilesWithNonRootedDiskPath.keys()) })}\nOpen script files with non rooted disk path opened with current directory context cannot have same canonical names`); - Debug.assert(!isDynamic || this.currentDirectory === currentDirectory || this.useInferredProjectPerProjectRoot, "", () => `${JSON.stringify({ fileName, currentDirectory, hostCurrentDirectory: this.currentDirectory, openKeys: arrayFrom(this.openFilesWithNonRootedDiskPath.keys()) })}\nDynamic files must always be opened with service's current directory or service should support inferred project per projectRootPath.`); + Debug.assert( + isRootedDiskPath(fileName) || isDynamic || openedByClient, + "", + () => + `${ + JSON.stringify({ + fileName, + currentDirectory, + hostCurrentDirectory: this.currentDirectory, + openKeys: arrayFrom(this.openFilesWithNonRootedDiskPath.keys()), + }) + }\nScript info with non-dynamic relative file name can only be open script info or in context of host currentDirectory`, + ); + Debug.assert( + !isRootedDiskPath(fileName) || this.currentDirectory === currentDirectory + || !this.openFilesWithNonRootedDiskPath.has(this.toCanonicalFileName(fileName)), + "", + () => + `${ + JSON.stringify({ + fileName, + currentDirectory, + hostCurrentDirectory: this.currentDirectory, + openKeys: arrayFrom(this.openFilesWithNonRootedDiskPath.keys()), + }) + }\nOpen script files with non rooted disk path opened with current directory context cannot have same canonical names`, + ); + Debug.assert( + !isDynamic || this.currentDirectory === currentDirectory || this.useInferredProjectPerProjectRoot, + "", + () => + `${ + JSON.stringify({ + fileName, + currentDirectory, + hostCurrentDirectory: this.currentDirectory, + openKeys: arrayFrom(this.openFilesWithNonRootedDiskPath.keys()), + }) + }\nDynamic files must always be opened with service's current directory or service should support inferred project per projectRootPath.`, + ); // If the file is not opened by client and the file doesnot exist on the disk, return if (!openedByClient && !isDynamic && !(hostToQueryFileExistsOn || this.host).fileExists(fileName)) { return; } - info = new ScriptInfo(this.host, fileName, scriptKind!, !!hasMixedContent, path, this.filenameToScriptInfoVersion.get(path)); // TODO: GH#18217 + info = new ScriptInfo( + this.host, + fileName, + scriptKind!, + !!hasMixedContent, + path, + this.filenameToScriptInfoVersion.get(path), + ); // TODO: GH#18217 this.filenameToScriptInfo.set(info.path, info); this.filenameToScriptInfoVersion.delete(info.path); if (!openedByClient) { @@ -3065,8 +3417,11 @@ export class ProjectService { * This gets the script info for the normalized path. If the path is not rooted disk path then the open script info with project root context is preferred */ getScriptInfoForNormalizedPath(fileName: NormalizedPath) { - return !isRootedDiskPath(fileName) && this.openFilesWithNonRootedDiskPath.get(this.toCanonicalFileName(fileName)) || - this.getScriptInfoForPath(normalizedPathToPath(fileName, this.currentDirectory, this.toCanonicalFileName)); + return !isRootedDiskPath(fileName) + && this.openFilesWithNonRootedDiskPath.get(this.toCanonicalFileName(fileName)) + || this.getScriptInfoForPath( + normalizedPathToPath(fileName, this.currentDirectory, this.toCanonicalFileName), + ); } getScriptInfoForPath(fileName: Path) { @@ -3074,9 +3429,17 @@ export class ProjectService { } /** @internal */ - getDocumentPositionMapper(project: Project, generatedFileName: string, sourceFileName?: string): DocumentPositionMapper | undefined { + getDocumentPositionMapper( + project: Project, + generatedFileName: string, + sourceFileName?: string, + ): DocumentPositionMapper | undefined { // Since declaration info and map file watches arent updating project's directory structure host (which can cache file structure) use host - const declarationInfo = this.getOrCreateScriptInfoNotOpenedByClient(generatedFileName, project.currentDirectory, this.host); + const declarationInfo = this.getOrCreateScriptInfoNotOpenedByClient( + generatedFileName, + project.currentDirectory, + this.host, + ); if (!declarationInfo) { if (sourceFileName) { // Project contains source file and it generates the generated file name @@ -3093,14 +3456,23 @@ export class ProjectService { if (sourceMapFileInfo) { sourceMapFileInfo.getSnapshot(); if (sourceMapFileInfo.documentPositionMapper !== undefined) { - sourceMapFileInfo.sourceInfos = this.addSourceInfoToSourceMap(sourceFileName, project, sourceMapFileInfo.sourceInfos); - return sourceMapFileInfo.documentPositionMapper ? sourceMapFileInfo.documentPositionMapper : undefined; + sourceMapFileInfo.sourceInfos = this.addSourceInfoToSourceMap( + sourceFileName, + project, + sourceMapFileInfo.sourceInfos, + ); + return sourceMapFileInfo.documentPositionMapper ? sourceMapFileInfo.documentPositionMapper + : undefined; } } declarationInfo.sourceMapFilePath = undefined; } else if (declarationInfo.sourceMapFilePath) { - declarationInfo.sourceMapFilePath.sourceInfos = this.addSourceInfoToSourceMap(sourceFileName, project, declarationInfo.sourceMapFilePath.sourceInfos); + declarationInfo.sourceMapFilePath.sourceInfos = this.addSourceInfoToSourceMap( + sourceFileName, + project, + declarationInfo.sourceMapFilePath.sourceInfos, + ); return undefined; } else if (declarationInfo.sourceMapFilePath !== undefined) { @@ -3113,7 +3485,11 @@ export class ProjectService { let mapFileNameFromDeclarationInfo: string | undefined; let readMapFile: ReadMapFile | undefined = (mapFileName, mapFileNameFromDts) => { - const mapInfo = this.getOrCreateScriptInfoNotOpenedByClient(mapFileName, project.currentDirectory, this.host); + const mapInfo = this.getOrCreateScriptInfoNotOpenedByClient( + mapFileName, + project.currentDirectory, + this.host, + ); if (!mapInfo) { mapFileNameFromDeclarationInfo = mapFileNameFromDts; return undefined; @@ -3125,7 +3501,11 @@ export class ProjectService { }; const projectName = project.projectName; const documentPositionMapper = getDocumentPositionMapper( - { getCanonicalFileName: this.toCanonicalFileName, log: s => this.logger.info(s), getSourceFileLike: f => this.getSourceFileLike(f, projectName, declarationInfo) }, + { + getCanonicalFileName: this.toCanonicalFileName, + log: s => this.logger.info(s), + getSourceFileLike: f => this.getSourceFileLike(f, projectName, declarationInfo), + }, declarationInfo.fileName, declarationInfo.textStorage.getLineInfo(), readMapFile, @@ -3135,14 +3515,18 @@ export class ProjectService { declarationInfo.sourceMapFilePath = sourceMapFileInfo.path; sourceMapFileInfo.declarationInfoPath = declarationInfo.path; sourceMapFileInfo.documentPositionMapper = documentPositionMapper || false; - sourceMapFileInfo.sourceInfos = this.addSourceInfoToSourceMap(sourceFileName, project, sourceMapFileInfo.sourceInfos); + sourceMapFileInfo.sourceInfos = this.addSourceInfoToSourceMap( + sourceFileName, + project, + sourceMapFileInfo.sourceInfos, + ); } else if (mapFileNameFromDeclarationInfo) { declarationInfo.sourceMapFilePath = { watcher: this.addMissingSourceMapFile( - project.currentDirectory === this.currentDirectory ? - mapFileNameFromDeclarationInfo : - getNormalizedAbsolutePath(mapFileNameFromDeclarationInfo, project.currentDirectory), + project.currentDirectory === this.currentDirectory + ? mapFileNameFromDeclarationInfo + : getNormalizedAbsolutePath(mapFileNameFromDeclarationInfo, project.currentDirectory), declarationInfo.path, ), sourceInfos: this.addSourceInfoToSourceMap(sourceFileName, project), @@ -3157,7 +3541,11 @@ export class ProjectService { private addSourceInfoToSourceMap(sourceFileName: string | undefined, project: Project, sourceInfos?: Set) { if (sourceFileName) { // Attach as source - const sourceInfo = this.getOrCreateScriptInfoNotOpenedByClient(sourceFileName, project.currentDirectory, project.directoryStructureHost)!; + const sourceInfo = this.getOrCreateScriptInfoNotOpenedByClient( + sourceFileName, + project.currentDirectory, + project.directoryStructureHost, + )!; (sourceInfos || (sourceInfos = new Set())).add(sourceInfo.path); } return sourceInfos; @@ -3168,7 +3556,9 @@ export class ProjectService { mapFileName, () => { const declarationInfo = this.getScriptInfoForPath(declarationInfoPath); - if (declarationInfo && declarationInfo.sourceMapFilePath && !isString(declarationInfo.sourceMapFilePath)) { + if ( + declarationInfo && declarationInfo.sourceMapFilePath && !isString(declarationInfo.sourceMapFilePath) + ) { // Update declaration and source projects this.delayUpdateProjectGraphs(declarationInfo.containingProjects, /*clearSourceMapperCache*/ true); this.delayUpdateSourceInfoProjects(declarationInfo.sourceMapFilePath.sourceInfos); @@ -3183,8 +3573,13 @@ export class ProjectService { } /** @internal */ - getSourceFileLike(fileName: string, projectNameOrProject: string | Project, declarationInfo?: ScriptInfo): SourceFileLike | undefined { - const project = (projectNameOrProject as Project).projectName ? projectNameOrProject as Project : this.findProject(projectNameOrProject as string); + getSourceFileLike( + fileName: string, + projectNameOrProject: string | Project, + declarationInfo?: ScriptInfo, + ): SourceFileLike | undefined { + const project = (projectNameOrProject as Project).projectName ? projectNameOrProject as Project + : this.findProject(projectNameOrProject as string); if (project) { const path = project.toPath(fileName); const sourceFile = project.getSourceFile(path); @@ -3192,7 +3587,11 @@ export class ProjectService { } // Need to look for other files. - const info = this.getOrCreateScriptInfoNotOpenedByClient(fileName, (project || this).currentDirectory, project ? project.directoryStructureHost : this.host); + const info = this.getOrCreateScriptInfoNotOpenedByClient( + fileName, + (project || this).currentDirectory, + project ? project.directoryStructureHost : this.host, + ); if (!info) return undefined; // Attach as source @@ -3217,7 +3616,8 @@ export class ProjectService { const lineOffset = info.positionToLineOffset(pos); return { line: lineOffset.line - 1, character: lineOffset.offset - 1 }; }, - getPositionOfLineAndCharacter: (line, character, allowEdits) => info.lineOffsetToPosition(line + 1, character + 1, allowEdits), + getPositionOfLineAndCharacter: (line, character, allowEdits) => + info.lineOffsetToPosition(line + 1, character + 1, allowEdits), }; } return info.sourceFileLike; @@ -3242,7 +3642,10 @@ export class ProjectService { this.logger.info(`Host information ${args.hostInfo}`); } if (args.formatOptions) { - this.hostConfiguration.formatCodeOptions = { ...this.hostConfiguration.formatCodeOptions, ...convertFormatOptions(args.formatOptions) }; + this.hostConfiguration.formatCodeOptions = { + ...this.hostConfiguration.formatCodeOptions, + ...convertFormatOptions(args.formatOptions), + }; this.logger.info("Format host information updated"); } if (args.preferences) { @@ -3252,13 +3655,16 @@ export class ProjectService { } = this.hostConfiguration.preferences; this.hostConfiguration.preferences = { ...this.hostConfiguration.preferences, ...args.preferences }; - if (lazyConfiguredProjectsFromExternalProject && !this.hostConfiguration.preferences.lazyConfiguredProjectsFromExternalProject) { + if ( + lazyConfiguredProjectsFromExternalProject + && !this.hostConfiguration.preferences.lazyConfiguredProjectsFromExternalProject + ) { // Load configured projects for external projects that are pending reload this.configuredProjects.forEach(project => { if ( - project.hasExternalProjectRef() && - project.pendingReload === ConfigFileProgramReloadLevel.Full && - !this.pendingProjectUpdates.has(project.getProjectName()) + project.hasExternalProjectRef() + && project.pendingReload === ConfigFileProgramReloadLevel.Full + && !this.pendingProjectUpdates.has(project.getProjectName()) ) { project.updateGraph(); } @@ -3278,7 +3684,11 @@ export class ProjectService { if (args.watchOptions) { this.hostConfiguration.watchOptions = convertWatchOptions(args.watchOptions)?.watchOptions; - this.logger.info(`Host watch options changed to ${JSON.stringify(this.hostConfiguration.watchOptions)}, it will be take effect for next watches.`); + this.logger.info( + `Host watch options changed to ${ + JSON.stringify(this.hostConfiguration.watchOptions) + }, it will be take effect for next watches.`, + ); } } } @@ -3290,9 +3700,9 @@ export class ProjectService { /** @internal */ private getWatchOptionsFromProjectWatchOptions(projectOptions: WatchOptions | undefined) { - return projectOptions && this.hostConfiguration.watchOptions ? - { ...this.hostConfiguration.watchOptions, ...projectOptions } : - projectOptions || this.hostConfiguration.watchOptions; + return projectOptions && this.hostConfiguration.watchOptions + ? { ...this.hostConfiguration.watchOptions, ...projectOptions } + : projectOptions || this.hostConfiguration.watchOptions; } closeLog() { @@ -3315,7 +3725,10 @@ export class ProjectService { if (this.openFiles.has(info.path)) return; // Skip open files if (!info.fileWatcher) return; // not watched file // Handle as if file is changed or deleted - this.onSourceFileChanged(info, this.host.fileExists(info.fileName) ? FileWatcherEventKind.Changed : FileWatcherEventKind.Deleted); + this.onSourceFileChanged( + info, + this.host.fileExists(info.fileName) ? FileWatcherEventKind.Changed : FileWatcherEventKind.Deleted, + ); }); // Cancel all project updates since we will be updating them now this.pendingProjectUpdates.forEach((_project, projectName) => { @@ -3331,7 +3744,13 @@ export class ProjectService { }); // Reload Projects - this.reloadConfiguredProjectForFiles(this.openFiles as Map, /*clearSemanticCache*/ true, /*delayReload*/ false, returnTrue, "User requested reload projects"); + this.reloadConfiguredProjectForFiles( + this.openFiles as Map, + /*clearSemanticCache*/ true, + /*delayReload*/ false, + returnTrue, + "User requested reload projects", + ); this.externalProjects.forEach(project => { this.clearSemanticCache(project); project.updateGraph(); @@ -3347,7 +3766,13 @@ export class ProjectService { * If there is no existing project it just opens the configured project for the config file * reloadForInfo provides a way to filter out files to reload configured project for */ - private reloadConfiguredProjectForFiles(openFiles: Map | undefined, clearSemanticCache: boolean, delayReload: boolean, shouldReloadProjectFor: (openFileValue: T) => boolean, reason: string) { + private reloadConfiguredProjectForFiles( + openFiles: Map | undefined, + clearSemanticCache: boolean, + delayReload: boolean, + shouldReloadProjectFor: (openFileValue: T) => boolean, + reason: string, + ) { const updatedProjects = new Map(); const reloadChildProject = (child: ConfiguredProject) => { if (!updatedProjects.has(child.canonicalConfigFilePath)) { @@ -3372,7 +3797,8 @@ export class ProjectService { // otherwise we create a new one. const configFileName = this.getConfigFileNameForFile(info); if (configFileName) { - const project = this.findConfiguredProjectByProjectName(configFileName) || this.createConfiguredProject(configFileName); + const project = this.findConfiguredProjectByProjectName(configFileName) + || this.createConfiguredProject(configFileName); if (!updatedProjects.has(project.canonicalConfigFilePath)) { updatedProjects.set(project.canonicalConfigFilePath, true); if (delayReload) { @@ -3433,10 +3859,10 @@ export class ProjectService { const firstProject = info.containingProjects[0]; if ( - !firstProject.isOrphan() && - isInferredProject(firstProject) && - firstProject.isRoot(info) && - forEach(info.containingProjects, p => p !== firstProject && !p.isOrphan()) + !firstProject.isOrphan() + && isInferredProject(firstProject) + && firstProject.isRoot(info) + && forEach(info.containingProjects, p => p !== firstProject && !p.isOrphan()) ) { firstProject.removeFile(info, /*fileExists*/ true, /*detachFromProject*/ true); } @@ -3476,23 +3902,40 @@ export class ProjectService { * @param filename is absolute pathname * @param fileContent is a known version of the file content that is more up to date than the one on disk */ - openClientFile(fileName: string, fileContent?: string, scriptKind?: ScriptKind, projectRootPath?: string): OpenConfiguredProjectResult { - return this.openClientFileWithNormalizedPath(toNormalizedPath(fileName), fileContent, scriptKind, /*hasMixedContent*/ false, projectRootPath ? toNormalizedPath(projectRootPath) : undefined); + openClientFile( + fileName: string, + fileContent?: string, + scriptKind?: ScriptKind, + projectRootPath?: string, + ): OpenConfiguredProjectResult { + return this.openClientFileWithNormalizedPath( + toNormalizedPath(fileName), + fileContent, + scriptKind, + /*hasMixedContent*/ false, + projectRootPath ? toNormalizedPath(projectRootPath) : undefined, + ); } /** @internal */ - getOriginalLocationEnsuringConfiguredProject(project: Project, location: DocumentPosition): DocumentPosition | undefined { + getOriginalLocationEnsuringConfiguredProject( + project: Project, + location: DocumentPosition, + ): DocumentPosition | undefined { const isSourceOfProjectReferenceRedirect = project.isSourceOfProjectReferenceRedirect(location.fileName); - const originalLocation = isSourceOfProjectReferenceRedirect ? - location : - project.getSourceMapper().tryGetSourcePosition(location); + const originalLocation = isSourceOfProjectReferenceRedirect + ? location + : project.getSourceMapper().tryGetSourcePosition(location); if (!originalLocation) return undefined; const { fileName } = originalLocation; const scriptInfo = this.getScriptInfo(fileName); if (!scriptInfo && !this.host.fileExists(fileName)) return undefined; - const originalFileInfo: OriginalFileInfo = { fileName: toNormalizedPath(fileName), path: this.toPath(fileName) }; + const originalFileInfo: OriginalFileInfo = { + fileName: toNormalizedPath(fileName), + path: this.toPath(fileName), + }; const configFileName = this.getConfigFileNameForFile(originalFileInfo); if (!configFileName) return undefined; @@ -3513,7 +3956,12 @@ export class ProjectService { : location; } - configuredProject = this.createAndLoadConfiguredProject(configFileName, `Creating project for original file: ${originalFileInfo.fileName}${location !== originalLocation ? " for location: " + location.fileName : ""}`); + configuredProject = this.createAndLoadConfiguredProject( + configFileName, + `Creating project for original file: ${originalFileInfo.fileName}${ + location !== originalLocation ? " for location: " + location.fileName : "" + }`, + ); } updateProjectIfDirty(configuredProject); @@ -3532,7 +3980,9 @@ export class ProjectService { return projectContainsOriginalInfo(child) ? child : undefined; }, ProjectReferenceProjectLoadKind.FindCreateLoad, - `Creating project referenced in solution ${configuredProject.projectName} to find possible configured project for original file: ${originalFileInfo.fileName}${location !== originalLocation ? " for location: " + location.fileName : ""}`, + `Creating project referenced in solution ${configuredProject.projectName} to find possible configured project for original file: ${originalFileInfo.fileName}${ + location !== originalLocation ? " for location: " + location.fileName : "" + }`, ); if (!configuredProject) return undefined; if (configuredProject === project) return originalLocation; @@ -3573,8 +4023,20 @@ export class ProjectService { }); } - private getOrCreateOpenScriptInfo(fileName: NormalizedPath, fileContent: string | undefined, scriptKind: ScriptKind | undefined, hasMixedContent: boolean | undefined, projectRootPath: NormalizedPath | undefined) { - const info = this.getOrCreateScriptInfoOpenedByClientForNormalizedPath(fileName, projectRootPath ? this.getNormalizedAbsolutePath(projectRootPath) : this.currentDirectory, fileContent, scriptKind, hasMixedContent)!; // TODO: GH#18217 + private getOrCreateOpenScriptInfo( + fileName: NormalizedPath, + fileContent: string | undefined, + scriptKind: ScriptKind | undefined, + hasMixedContent: boolean | undefined, + projectRootPath: NormalizedPath | undefined, + ) { + const info = this.getOrCreateScriptInfoOpenedByClientForNormalizedPath( + fileName, + projectRootPath ? this.getNormalizedAbsolutePath(projectRootPath) : this.currentDirectory, + fileContent, + scriptKind, + hasMixedContent, + )!; // TODO: GH#18217 this.openFiles.set(info.path, projectRootPath); return info; } @@ -3582,7 +4044,9 @@ export class ProjectService { private assignProjectToOpenedScriptInfo(info: ScriptInfo): AssignProjectResult { let configFileName: NormalizedPath | undefined; let configFileErrors: readonly Diagnostic[] | undefined; - let project: ConfiguredProject | ExternalProject | undefined = this.findExternalProjectContainingOpenScriptInfo(info); + let project: ConfiguredProject | ExternalProject | undefined = this.findExternalProjectContainingOpenScriptInfo( + info, + ); let retainProjects: ConfiguredProject[] | ConfiguredProject | undefined; let projectForConfigFileDiag: ConfiguredProject | undefined; let defaultConfigProjectIsCreated = false; @@ -3591,7 +4055,10 @@ export class ProjectService { if (configFileName) { project = this.findConfiguredProjectByProjectName(configFileName); if (!project) { - project = this.createLoadAndUpdateConfiguredProject(configFileName, `Creating possible configured project for ${info.fileName} to open`); + project = this.createLoadAndUpdateConfiguredProject( + configFileName, + `Creating possible configured project for ${info.fileName} to open`, + ); defaultConfigProjectIsCreated = true; } else { @@ -3686,10 +4153,10 @@ export class ProjectService { while (true) { // Skip if project is not composite if ( - !project.isInitialLoadPending() && - ( - !project.getCompilerOptions().composite || - project.getCompilerOptions().disableSolutionSearching + !project.isInitialLoadPending() + && ( + !project.getCompilerOptions().composite + || project.getCompilerOptions().disableSolutionSearching ) ) return; @@ -3702,8 +4169,11 @@ export class ProjectService { if (!configFileName) return; // find or delay load the project - const ancestor = this.findConfiguredProjectByProjectName(configFileName) || - this.createConfiguredProjectWithDelayLoad(configFileName, `Creating project possibly referencing default composite project ${project.getProjectName()} of open file ${info.fileName}`); + const ancestor = this.findConfiguredProjectByProjectName(configFileName) + || this.createConfiguredProjectWithDelayLoad( + configFileName, + `Creating project possibly referencing default composite project ${project.getProjectName()} of open file ${info.fileName}`, + ); if (ancestor.isInitialLoadPending()) { // Set a potential project reference ancestor.setPotentialProjectReference(project.canonicalConfigFilePath); @@ -3731,7 +4201,11 @@ export class ProjectService { } } - private ensureProjectChildren(project: ConfiguredProject, forProjects: ReadonlyCollection, seenProjects: Set) { + private ensureProjectChildren( + project: ConfiguredProject, + forProjects: ReadonlyCollection, + seenProjects: Set, + ) { if (!tryAddToSet(seenProjects, project.canonicalConfigFilePath)) return; // If this project disables child load ignore it @@ -3742,13 +4216,19 @@ export class ProjectService { for (const child of children) { if (!child) continue; - const referencedProject = forEachResolvedProjectReference(child.references, ref => forProjects.has(ref.sourceFile.path) ? ref : undefined); + const referencedProject = forEachResolvedProjectReference( + child.references, + ref => forProjects.has(ref.sourceFile.path) ? ref : undefined, + ); if (!referencedProject) continue; // Load this project, const configFileName = toNormalizedPath(child.sourceFile.fileName); - const childProject = project.projectService.findConfiguredProjectByProjectName(configFileName) || - project.projectService.createAndLoadConfiguredProject(configFileName, `Creating project referenced by : ${project.projectName} as it references project ${referencedProject.sourceFile.fileName}`); + const childProject = project.projectService.findConfiguredProjectByProjectName(configFileName) + || project.projectService.createAndLoadConfiguredProject( + configFileName, + `Creating project referenced by : ${project.projectName} as it references project ${referencedProject.sourceFile.fileName}`, + ); updateProjectIfDirty(childProject); // Ensure children for this project @@ -3756,7 +4236,9 @@ export class ProjectService { } } - private cleanupAfterOpeningFile(toRetainConfigProjects: readonly ConfiguredProject[] | ConfiguredProject | undefined) { + private cleanupAfterOpeningFile( + toRetainConfigProjects: readonly ConfiguredProject[] | ConfiguredProject | undefined, + ) { // This was postponed from closeOpenFile to after opening next file, // so that we can reuse the project if we need to right away this.removeOrphanConfiguredProjects(toRetainConfigProjects); @@ -3776,8 +4258,20 @@ export class ProjectService { this.removeOrphanScriptInfos(); } - openClientFileWithNormalizedPath(fileName: NormalizedPath, fileContent?: string, scriptKind?: ScriptKind, hasMixedContent?: boolean, projectRootPath?: NormalizedPath): OpenConfiguredProjectResult { - const info = this.getOrCreateOpenScriptInfo(fileName, fileContent, scriptKind, hasMixedContent, projectRootPath); + openClientFileWithNormalizedPath( + fileName: NormalizedPath, + fileContent?: string, + scriptKind?: ScriptKind, + hasMixedContent?: boolean, + projectRootPath?: NormalizedPath, + ): OpenConfiguredProjectResult { + const info = this.getOrCreateOpenScriptInfo( + fileName, + fileContent, + scriptKind, + hasMixedContent, + projectRootPath, + ); const { retainProjects, ...result } = this.assignProjectToOpenedScriptInfo(info); this.cleanupAfterOpeningFile(retainProjects); this.telemetryOnOpenFile(info); @@ -3785,7 +4279,9 @@ export class ProjectService { return result; } - private removeOrphanConfiguredProjects(toRetainConfiguredProjects: readonly ConfiguredProject[] | ConfiguredProject | undefined) { + private removeOrphanConfiguredProjects( + toRetainConfiguredProjects: readonly ConfiguredProject[] | ConfiguredProject | undefined, + ) { const toRemoveConfiguredProjects = new Map(this.configuredProjects); const markOriginalProjectsAsUsed = (project: Project) => { if (!project.isOrphan() && project.originalConfiguredProjects) { @@ -3894,7 +4390,10 @@ export class ProjectService { } private telemetryOnOpenFile(scriptInfo: ScriptInfo): void { - if (this.serverMode !== LanguageServiceMode.Semantic || !this.eventHandler || !scriptInfo.isJavaScript() || !addToSeen(this.allJsFilesForOpenFileTelemetry, scriptInfo.path)) { + if ( + this.serverMode !== LanguageServiceMode.Semantic || !this.eventHandler || !scriptInfo.isJavaScript() + || !addToSeen(this.allJsFilesForOpenFileTelemetry, scriptInfo.path) + ) { return; } @@ -3932,21 +4431,35 @@ export class ProjectService { ): void { for (const proj of currentProjects) { const knownProject = find(lastKnownProjectVersions, p => p.projectName === proj.getProjectName()); - result.push(proj.getChangesSinceVersion(knownProject && knownProject.version, includeProjectReferenceRedirectInfo)); + result.push( + proj.getChangesSinceVersion(knownProject && knownProject.version, includeProjectReferenceRedirectInfo), + ); } } /** @internal */ - synchronizeProjectList(knownProjects: protocol.ProjectVersionInfo[], includeProjectReferenceRedirectInfo?: boolean): ProjectFilesWithTSDiagnostics[] { + synchronizeProjectList( + knownProjects: protocol.ProjectVersionInfo[], + includeProjectReferenceRedirectInfo?: boolean, + ): ProjectFilesWithTSDiagnostics[] { const files: ProjectFilesWithTSDiagnostics[] = []; this.collectChanges(knownProjects, this.externalProjects, includeProjectReferenceRedirectInfo, files); - this.collectChanges(knownProjects, this.configuredProjects.values(), includeProjectReferenceRedirectInfo, files); + this.collectChanges( + knownProjects, + this.configuredProjects.values(), + includeProjectReferenceRedirectInfo, + files, + ); this.collectChanges(knownProjects, this.inferredProjects, includeProjectReferenceRedirectInfo, files); return files; } /** @internal */ - applyChangesInOpenFiles(openFiles: Iterable | undefined, changedFiles?: Iterable, closedFiles?: string[]): void { + applyChangesInOpenFiles( + openFiles: Iterable | undefined, + changedFiles?: Iterable, + closedFiles?: string[], + ): void { let openScriptInfos: ScriptInfo[] | undefined; let assignOrphanScriptInfosToInferredProject = false; if (openFiles) { @@ -3975,14 +4488,19 @@ export class ProjectService { if (closedFiles) { for (const file of closedFiles) { // Close files, but dont assign projects to orphan open script infos, that part comes later - assignOrphanScriptInfosToInferredProject = this.closeClientFile(file, /*skipAssignOrphanScriptInfosToInferredProject*/ true) || assignOrphanScriptInfosToInferredProject; + assignOrphanScriptInfosToInferredProject = + this.closeClientFile(file, /*skipAssignOrphanScriptInfosToInferredProject*/ true) + || assignOrphanScriptInfosToInferredProject; } } // All the script infos now exist, so ok to go update projects for open files let retainProjects: readonly ConfiguredProject[] | undefined; if (openScriptInfos) { - retainProjects = flatMap(openScriptInfos, info => this.assignProjectToOpenedScriptInfo(info).retainProjects); + retainProjects = flatMap( + openScriptInfos, + info => this.assignProjectToOpenedScriptInfo(info).retainProjects, + ); } // While closing files there could be open files that needed assigning new inferred projects, do it now @@ -4108,7 +4626,9 @@ export class ProjectService { if (typeof groupNumberOrString === "number") { if (!isString(groups[groupNumberOrString])) { // Specification was wrong - exclude nothing! - this.logger.info(`Incorrect RegExp specification in safelist rule ${name} - not enough groups`); + this.logger.info( + `Incorrect RegExp specification in safelist rule ${name} - not enough groups`, + ); // * can't appear in a filename; escape it because it's feeding into a RegExp return "\\*"; } @@ -4149,7 +4669,11 @@ export class ProjectService { const cleanedTypingName = removeMinAndVersionNumbers(inferredTypingName); const typeName = this.legacySafelist.get(cleanedTypingName); if (typeName !== undefined) { - this.logger.info(`Excluded '${normalizedNames[i]}' because it matched ${cleanedTypingName} from the legacy safelist`); + this.logger.info( + `Excluded '${ + normalizedNames[i] + }' because it matched ${cleanedTypingName} from the legacy safelist`, + ); excludedFiles.push(normalizedNames[i]); // *exclude* it from the project... exclude = true; @@ -4212,7 +4736,12 @@ export class ProjectService { if (!tsConfigFiles) { const compilerOptions = convertCompilerOptions(proj.options); const watchOptionsAndErrors = convertWatchOptions(proj.options, externalProject.getCurrentDirectory()); - const lastFileExceededProgramSize = this.getFilenameForExceededTotalSizeLimitForNonTsFiles(proj.projectFileName, compilerOptions, proj.rootFiles, externalFilePropertyReader); + const lastFileExceededProgramSize = this.getFilenameForExceededTotalSizeLimitForNonTsFiles( + proj.projectFileName, + compilerOptions, + proj.rootFiles, + externalFilePropertyReader, + ); if (lastFileExceededProgramSize) { externalProject.disableLanguageService(lastFileExceededProgramSize); } @@ -4222,7 +4751,15 @@ export class ProjectService { externalProject.setProjectErrors(watchOptionsAndErrors?.errors); // external project already exists and not config files were added - update the project and return; // The graph update here isnt postponed since any file open operation needs all updated external projects - this.updateRootAndOptionsOfNonInferredProject(externalProject, proj.rootFiles, externalFilePropertyReader, compilerOptions, proj.typeAcquisition, proj.options.compileOnSave, watchOptionsAndErrors?.watchOptions); + this.updateRootAndOptionsOfNonInferredProject( + externalProject, + proj.rootFiles, + externalFilePropertyReader, + compilerOptions, + proj.typeAcquisition, + proj.options.compileOnSave, + watchOptionsAndErrors?.watchOptions, + ); externalProject.updateGraph(); return; } @@ -4271,9 +4808,15 @@ export class ProjectService { let project = this.findConfiguredProjectByProjectName(tsconfigFile); if (!project) { // errors are stored in the project, do not need to update the graph - project = this.getHostPreferences().lazyConfiguredProjectsFromExternalProject ? - this.createConfiguredProjectWithDelayLoad(tsconfigFile, `Creating configured project in external project: ${proj.projectFileName}`) : - this.createLoadAndUpdateConfiguredProject(tsconfigFile, `Creating configured project in external project: ${proj.projectFileName}`); + project = this.getHostPreferences().lazyConfiguredProjectsFromExternalProject + ? this.createConfiguredProjectWithDelayLoad( + tsconfigFile, + `Creating configured project in external project: ${proj.projectFileName}`, + ) + : this.createLoadAndUpdateConfiguredProject( + tsconfigFile, + `Creating configured project in external project: ${proj.projectFileName}`, + ); } if (project && !contains(exisingConfigFiles, tsconfigFile)) { // keep project alive even if no documents are opened - its lifetime is bound to the lifetime of containing external project @@ -4286,7 +4829,13 @@ export class ProjectService { // Create external project and update its graph, do not delay update since // any file open operation needs all updated external projects this.externalProjectToConfiguredProjectMap.delete(proj.projectFileName); - const project = this.createExternalProject(proj.projectFileName, rootFiles, proj.options, proj.typeAcquisition, excludedFiles); + const project = this.createExternalProject( + proj.projectFileName, + rootFiles, + proj.options, + proj.typeAcquisition, + excludedFiles, + ); project.updateGraph(); } } @@ -4307,13 +4856,19 @@ export class ProjectService { */ requestEnablePlugin(project: Project, pluginConfigEntry: PluginImport, searchPaths: string[]) { if (!this.host.importPlugin && !this.host.require) { - this.logger.info("Plugins were requested but not running in environment that supports 'require'. Nothing will be loaded"); + this.logger.info( + "Plugins were requested but not running in environment that supports 'require'. Nothing will be loaded", + ); return; } this.logger.info(`Enabling plugin ${pluginConfigEntry.name} from candidate paths: ${searchPaths.join(",")}`); if (!pluginConfigEntry.name || parsePackageName(pluginConfigEntry.name).rest) { - this.logger.info(`Skipped loading plugin ${pluginConfigEntry.name || JSON.stringify(pluginConfigEntry)} because only package name is allowed plugin name`); + this.logger.info( + `Skipped loading plugin ${ + pluginConfigEntry.name || JSON.stringify(pluginConfigEntry) + } because only package name is allowed plugin name`, + ); return; } @@ -4348,7 +4903,10 @@ export class ProjectService { * Performs the remaining steps of enabling a plugin after its module has been instantiated. * @internal */ - private endEnablePlugin(project: Project, { pluginConfigEntry, resolvedModule, errorLogs }: BeginEnablePluginResult) { + private endEnablePlugin( + project: Project, + { pluginConfigEntry, resolvedModule, errorLogs }: BeginEnablePluginResult, + ) { if (resolvedModule) { const configurationOverride = this.currentPluginConfigOverrides?.get(pluginConfigEntry.name); if (configurationOverride) { @@ -4424,14 +4982,19 @@ export class ProjectService { // Process all pending plugins, partitioned by project. This way a project with few plugins doesn't need to wait // on a project with many plugins. - await Promise.all(map(pendingPlugins, ([project, promises]) => this.enableRequestedPluginsForProjectAsync(project, promises))); + await Promise.all( + map(pendingPlugins, ([project, promises]) => this.enableRequestedPluginsForProjectAsync(project, promises)), + ); // Clear the pending operation and notify the client that projects have been updated. this.currentPluginEnablementPromise = undefined; this.sendProjectsUpdatedInBackgroundEvent(); } - private async enableRequestedPluginsForProjectAsync(project: Project, promises: Promise[]) { + private async enableRequestedPluginsForProjectAsync( + project: Project, + promises: Promise[], + ) { // Await all pending plugin imports. This ensures all requested plugin modules are fully loaded // prior to patching the language service, and that any promise rejections are observed. const results = await Promise.all(promises); @@ -4450,7 +5013,9 @@ export class ProjectService { configurePlugin(args: protocol.ConfigurePluginRequestArguments) { // For any projects that already have the plugin loaded, configure the plugin - this.forEachEnabledProject(project => project.onPluginConfigurationChanged(args.pluginName, args.configuration)); + this.forEachEnabledProject(project => + project.onPluginConfigurationChanged(args.pluginName, args.configuration) + ); // Also save the current configuration to pass on to any projects that are yet to be loaded. // If a plugin is configured twice, only the latest configuration will be remembered. diff --git a/src/server/moduleSpecifierCache.ts b/src/server/moduleSpecifierCache.ts index 7a4499c434874..cdec3252de15e 100644 --- a/src/server/moduleSpecifierCache.ts +++ b/src/server/moduleSpecifierCache.ts @@ -26,7 +26,10 @@ export function createModuleSpecifierCache(host: ModuleSpecifierResolutionCacheH return cache.get(toFileName); }, set(fromFileName, toFileName, preferences, options, modulePaths, moduleSpecifiers) { - ensureCache(fromFileName, preferences, options).set(toFileName, createInfo(modulePaths, moduleSpecifiers, /*isBlockedByPackageJsonDependencies*/ false)); + ensureCache(fromFileName, preferences, options).set( + toFileName, + createInfo(modulePaths, moduleSpecifiers, /*isBlockedByPackageJsonDependencies*/ false), + ); // If any module specifiers were generated based off paths in node_modules, // a package.json file in that package was read and is an input to the cached. @@ -37,7 +40,10 @@ export function createModuleSpecifierCache(host: ModuleSpecifierResolutionCacheH for (const p of modulePaths) { if (p.isInNodeModules) { // No trailing slash - const nodeModulesPath = p.path.substring(0, p.path.indexOf(nodeModulesPathPart) + nodeModulesPathPart.length - 1); + const nodeModulesPath = p.path.substring( + 0, + p.path.indexOf(nodeModulesPathPart) + nodeModulesPathPart.length - 1, + ); if (!containedNodeModulesWatchers?.has(nodeModulesPath)) { (containedNodeModulesWatchers ||= new Map()).set( nodeModulesPath, @@ -55,17 +61,37 @@ export function createModuleSpecifierCache(host: ModuleSpecifierResolutionCacheH info.modulePaths = modulePaths; } else { - cache.set(toFileName, createInfo(modulePaths, /*moduleSpecifiers*/ undefined, /*isBlockedByPackageJsonDependencies*/ undefined)); + cache.set( + toFileName, + createInfo( + modulePaths, + /*moduleSpecifiers*/ undefined, + /*isBlockedByPackageJsonDependencies*/ undefined, + ), + ); } }, - setBlockedByPackageJsonDependencies(fromFileName, toFileName, preferences, options, isBlockedByPackageJsonDependencies) { + setBlockedByPackageJsonDependencies( + fromFileName, + toFileName, + preferences, + options, + isBlockedByPackageJsonDependencies, + ) { const cache = ensureCache(fromFileName, preferences, options); const info = cache.get(toFileName); if (info) { info.isBlockedByPackageJsonDependencies = isBlockedByPackageJsonDependencies; } else { - cache.set(toFileName, createInfo(/*modulePaths*/ undefined, /*moduleSpecifiers*/ undefined, isBlockedByPackageJsonDependencies)); + cache.set( + toFileName, + createInfo( + /*modulePaths*/ undefined, + /*moduleSpecifiers*/ undefined, + isBlockedByPackageJsonDependencies, + ), + ); } }, clear() { diff --git a/src/server/packageJsonCache.ts b/src/server/packageJsonCache.ts index dc62d64f69334..b1d7251695cd1 100644 --- a/src/server/packageJsonCache.ts +++ b/src/server/packageJsonCache.ts @@ -63,8 +63,8 @@ export function createPackageJsonCache(host: ProjectService): PackageJsonCache { } function directoryHasPackageJson(directory: Path) { - return packageJsons.has(combinePaths(directory, "package.json")) ? Ternary.True : - directoriesWithoutPackageJson.has(directory) ? Ternary.False : - Ternary.Maybe; + return packageJsons.has(combinePaths(directory, "package.json")) ? Ternary.True + : directoriesWithoutPackageJson.has(directory) ? Ternary.False + : Ternary.Maybe; } } diff --git a/src/server/project.ts b/src/server/project.ts index 97451f224c7f7..e8ddd4c01b187 100644 --- a/src/server/project.ts +++ b/src/server/project.ts @@ -233,7 +233,10 @@ export function allFilesAreJsOrDts(project: Project): boolean { /** @internal */ export function hasNoTypeScriptSource(fileNames: string[]): boolean { - return !fileNames.some(fileName => (fileExtensionIs(fileName, Extension.Ts) && !isDeclarationFileName(fileName)) || fileExtensionIs(fileName, Extension.Tsx)); + return !fileNames.some(fileName => + (fileExtensionIs(fileName, Extension.Ts) && !isDeclarationFileName(fileName)) + || fileExtensionIs(fileName, Extension.Tsx) + ); } /** @internal */ @@ -421,7 +424,12 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo return hasOneOrMoreJsAndNoTsFiles(this); } - public static resolveModule(moduleName: string, initialDir: string, host: ServerHost, log: (message: string) => void): {} | undefined { + public static resolveModule( + moduleName: string, + initialDir: string, + host: ServerHost, + log: (message: string) => void, + ): {} | undefined { return Project.importServicePluginSync({ name: moduleName }, [initialDir], host, log).resolvedModule; } @@ -474,7 +482,9 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo break; } const err = result.error.stack || result.error.message || JSON.stringify(result.error); - (errorLogs ??= []).push(`Failed to dynamically import module '${pluginConfigEntry.name}' from ${resolvedPath}: ${err}`); + (errorLogs ??= []).push( + `Failed to dynamically import module '${pluginConfigEntry.name}' from ${resolvedPath}: ${err}`, + ); } return { pluginConfigEntry, resolvedModule, errorLogs }; } @@ -525,13 +535,19 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo this.currentDirectory = this.projectService.getNormalizedAbsolutePath(currentDirectory); this.getCanonicalFileName = this.projectService.toCanonicalFileName; - this.cancellationToken = new ThrottledCancellationToken(this.projectService.cancellationToken, this.projectService.throttleWaitMilliseconds); + this.cancellationToken = new ThrottledCancellationToken( + this.projectService.cancellationToken, + this.projectService.throttleWaitMilliseconds, + ); if (!this.compilerOptions) { this.compilerOptions = getDefaultCompilerOptions(); this.compilerOptions.allowNonTsExtensions = true; this.compilerOptions.allowJs = true; } - else if (hasExplicitListOfFiles || getAllowJSCompilerOption(this.compilerOptions) || this.projectService.hasDeferredExtension()) { + else if ( + hasExplicitListOfFiles || getAllowJSCompilerOption(this.compilerOptions) + || this.projectService.hasDeferredExtension() + ) { // If files are listed explicitly or allowJs is specified, allow all extensions this.compilerOptions.allowNonTsExtensions = true; } @@ -584,7 +600,11 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo return this.typingsCache.isKnownTypesPackageName(name); } installPackage(options: InstallPackageOptions): Promise { - return this.typingsCache.installPackage({ ...options, projectName: this.projectName, projectRootPath: this.toPath(this.currentDirectory) }); + return this.typingsCache.installPackage({ + ...options, + projectName: this.projectName, + projectRootPath: this.toPath(this.currentDirectory), + }); } /** @internal */ @@ -649,7 +669,11 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo } private getOrCreateScriptInfoAndAttachToProject(fileName: string) { - const scriptInfo = this.projectService.getOrCreateScriptInfoNotOpenedByClient(fileName, this.currentDirectory, this.directoryStructureHost); + const scriptInfo = this.projectService.getOrCreateScriptInfoNotOpenedByClient( + fileName, + this.currentDirectory, + this.directoryStructureHost, + ); if (scriptInfo) { const existingValue = this.rootFilesMap.get(scriptInfo.path); if (existingValue && existingValue.info !== scriptInfo) { @@ -670,7 +694,11 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo getScriptVersion(filename: string) { // Don't attach to the project if version is asked - const info = this.projectService.getOrCreateScriptInfoNotOpenedByClient(filename, this.currentDirectory, this.directoryStructureHost); + const info = this.projectService.getOrCreateScriptInfoNotOpenedByClient( + filename, + this.currentDirectory, + this.directoryStructureHost, + ); return (info && info.getLatestVersion())!; // TODO: GH#18217 } @@ -698,7 +726,13 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo return this.projectService.host.useCaseSensitiveFileNames; } - readDirectory(path: string, extensions?: readonly string[], exclude?: readonly string[], include?: readonly string[], depth?: number): string[] { + readDirectory( + path: string, + extensions?: readonly string[], + exclude?: readonly string[], + include?: readonly string[], + depth?: number, + ): string[] { return this.directoryStructureHost.readDirectory!(path, extensions, exclude, include, depth); } @@ -718,8 +752,22 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo } /** @internal */ - resolveModuleNameLiterals(moduleLiterals: readonly StringLiteralLike[], containingFile: string, redirectedReference: ResolvedProjectReference | undefined, options: CompilerOptions, containingSourceFile: SourceFile, reusedNames: readonly StringLiteralLike[] | undefined): readonly ResolvedModuleWithFailedLookupLocations[] { - return this.resolutionCache.resolveModuleNameLiterals(moduleLiterals, containingFile, redirectedReference, options, containingSourceFile, reusedNames); + resolveModuleNameLiterals( + moduleLiterals: readonly StringLiteralLike[], + containingFile: string, + redirectedReference: ResolvedProjectReference | undefined, + options: CompilerOptions, + containingSourceFile: SourceFile, + reusedNames: readonly StringLiteralLike[] | undefined, + ): readonly ResolvedModuleWithFailedLookupLocations[] { + return this.resolutionCache.resolveModuleNameLiterals( + moduleLiterals, + containingFile, + redirectedReference, + options, + containingSourceFile, + reusedNames, + ); } getModuleResolutionCache(): ModuleResolutionCache | undefined { @@ -727,7 +775,14 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo } /** @internal */ - resolveTypeReferenceDirectiveReferences(typeDirectiveReferences: readonly T[], containingFile: string, redirectedReference: ResolvedProjectReference | undefined, options: CompilerOptions, containingSourceFile: SourceFile | undefined, reusedNames: readonly T[] | undefined): readonly ResolvedTypeReferenceDirectiveWithFailedLookupLocations[] { + resolveTypeReferenceDirectiveReferences( + typeDirectiveReferences: readonly T[], + containingFile: string, + redirectedReference: ResolvedProjectReference | undefined, + options: CompilerOptions, + containingSourceFile: SourceFile | undefined, + reusedNames: readonly T[] | undefined, + ): readonly ResolvedTypeReferenceDirectiveWithFailedLookupLocations[] { return this.resolutionCache.resolveTypeReferenceDirectiveReferences( typeDirectiveReferences, containingFile, @@ -739,7 +794,12 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo } /** @internal */ - resolveLibrary(libraryName: string, resolveFrom: string, options: CompilerOptions, libFileName: string): ResolvedModuleWithFailedLookupLocations { + resolveLibrary( + libraryName: string, + resolveFrom: string, + options: CompilerOptions, + libFileName: string, + ): ResolvedModuleWithFailedLookupLocations { return this.resolutionCache.resolveLibrary(libraryName, resolveFrom, options, libFileName); } @@ -792,18 +852,22 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo /** @internal */ scheduleInvalidateResolutionsOfFailedLookupLocations() { - this.projectService.throttledOperations.schedule(`${this.getProjectName()}FailedLookupInvalidation`, /*delay*/ 1000, () => { - if (this.resolutionCache.invalidateResolutionsOfFailedLookupLocations()) { - this.projectService.delayUpdateProjectGraphAndEnsureProjectStructureForOpenFiles(this); - } - }); + this.projectService.throttledOperations.schedule( + `${this.getProjectName()}FailedLookupInvalidation`, + /*delay*/ 1000, + () => { + if (this.resolutionCache.invalidateResolutionsOfFailedLookupLocations()) { + this.projectService.delayUpdateProjectGraphAndEnsureProjectStructureForOpenFiles(this); + } + }, + ); } /** @internal */ invalidateResolutionsOfFailedLookupLocations() { if ( - this.clearInvalidateResolutionOfFailedLookupTimer() && - this.resolutionCache.invalidateResolutionsOfFailedLookupLocations() + this.clearInvalidateResolutionOfFailedLookupTimer() + && this.resolutionCache.invalidateResolutionsOfFailedLookupLocations() ) { this.markAsDirty(); this.projectService.delayEnsureProjectForOpenFiles(); @@ -839,7 +903,8 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo /** @internal */ getGlobalCache() { - return this.getTypeAcquisition().enable ? this.projectService.typingsInstaller.globalTypingsCacheLocation : undefined; + return this.getTypeAcquisition().enable ? this.projectService.typingsInstaller.globalTypingsCacheLocation + : undefined; } /** @internal */ @@ -916,9 +981,9 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo /** @internal */ shouldEmitFile(scriptInfo: ScriptInfo | undefined) { - return scriptInfo && - !scriptInfo.isDynamicOrHasMixedContent() && - !this.program!.isSourceOfProjectReferenceRedirect(scriptInfo.path); + return scriptInfo + && !scriptInfo.isDynamicOrHasMixedContent() + && !this.program!.isSourceOfProjectReferenceRedirect(scriptInfo.path); } getCompileOnSaveAffectedFileList(scriptInfo: ScriptInfo): string[] { @@ -926,7 +991,11 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo return []; } updateProjectIfDirty(this); - this.builderState = BuilderState.create(this.program!, this.builderState, /*disableUseFileVersionAsSignature*/ true); + this.builderState = BuilderState.create( + this.program!, + this.builderState, + /*disableUseFileVersionAsSignature*/ true, + ); return mapDefined( BuilderState.getFilesAffectedBy( this.builderState, @@ -935,14 +1004,19 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo this.cancellationToken, this.projectService.host, ), - sourceFile => this.shouldEmitFile(this.projectService.getScriptInfoForPath(sourceFile.path)) ? sourceFile.fileName : undefined, + sourceFile => + this.shouldEmitFile(this.projectService.getScriptInfoForPath(sourceFile.path)) ? sourceFile.fileName + : undefined, ); } /** * Returns true if emit was conducted */ - emitFile(scriptInfo: ScriptInfo, writeFile: (path: string, data: string, writeByteOrderMark?: boolean) => void): EmitResult { + emitFile( + scriptInfo: ScriptInfo, + writeFile: (path: string, data: string, writeByteOrderMark?: boolean) => void, + ): EmitResult { if (!this.languageServiceEnabled || !this.shouldEmitFile(scriptInfo)) { return { emitSkipped: true, diagnostics: emptyArray }; } @@ -958,9 +1032,9 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo const dtsFiles = outputFiles.filter(f => isDeclarationFileName(f.name)); if (dtsFiles.length === 1) { const sourceFile = this.program!.getSourceFile(scriptInfo.fileName)!; - const signature = this.projectService.host.createHash ? - this.projectService.host.createHash(dtsFiles[0].text) : - generateDjb2Hash(dtsFiles[0].text); + const signature = this.projectService.host.createHash + ? this.projectService.host.createHash(dtsFiles[0].text) + : generateDjb2Hash(dtsFiles[0].text); BuilderState.updateSignatureOfFile(this.builderState, signature, sourceFile.resolvedPath); } } @@ -985,7 +1059,9 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo for (const f of this.program.getSourceFiles()) { this.detachScriptInfoIfNotRoot(f.fileName); } - this.program.forEachResolvedProjectReference(ref => this.detachScriptInfoFromProject(ref.sourceFile.fileName)); + this.program.forEachResolvedProjectReference(ref => + this.detachScriptInfoFromProject(ref.sourceFile.fileName) + ); this.program = undefined; } } @@ -1142,7 +1218,12 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo } return map(this.program!.getSourceFiles(), sourceFile => { const scriptInfo = this.projectService.getScriptInfoForPath(sourceFile.resolvedPath); - Debug.assert(!!scriptInfo, "getScriptInfo", () => `scriptInfo for a file '${sourceFile.fileName}' Path: '${sourceFile.path}' / '${sourceFile.resolvedPath}' is missing.`); + Debug.assert( + !!scriptInfo, + "getScriptInfo", + () => + `scriptInfo for a file '${sourceFile.fileName}' Path: '${sourceFile.path}' / '${sourceFile.resolvedPath}' is missing.`, + ); return scriptInfo; }); } @@ -1192,7 +1273,8 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo getFileNamesWithRedirectInfo(includeProjectReferenceRedirectInfo: boolean) { return this.getFileNames().map((fileName): protocol.FileWithProjectReferenceRedirectInfo => ({ fileName, - isSourceOfProjectReferenceRedirect: includeProjectReferenceRedirectInfo && this.isSourceOfProjectReferenceRedirect(fileName), + isSourceOfProjectReferenceRedirect: includeProjectReferenceRedirectInfo + && this.isSourceOfProjectReferenceRedirect(fileName), })); } @@ -1328,7 +1410,10 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo * @returns: true if set of files in the project stays the same and false - otherwise. */ updateGraph(): boolean { - tracing?.push(tracing.Phase.Session, "updateGraph", { name: this.projectName, kind: ProjectKind[this.projectKind] }); + tracing?.push(tracing.Phase.Session, "updateGraph", { + name: this.projectName, + kind: ProjectKind[this.projectKind], + }); perfLogger?.logStartUpdateGraph(); this.resolutionCache.startRecordingFilesWithChangedResolutions(); @@ -1337,7 +1422,8 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo this.hasAddedorRemovedFiles = false; this.hasAddedOrRemovedSymlinks = false; - const changedFiles: readonly Path[] = this.resolutionCache.finishRecordingFilesWithChangedResolutions() || emptyArray; + const changedFiles: readonly Path[] = this.resolutionCache.finishRecordingFilesWithChangedResolutions() + || emptyArray; for (const file of changedFiles) { // delete cached information for changed files @@ -1354,10 +1440,17 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo // (can reuse cached imports for files that were not changed) // 4. compilation settings were changed in the way that might affect module resolution - drop all caches and collect all data from the scratch if (hasNewProgram || changedFiles.length) { - this.lastCachedUnresolvedImportsList = getUnresolvedImports(this.program!, this.cachedUnresolvedImportsPerFile); + this.lastCachedUnresolvedImportsList = getUnresolvedImports( + this.program!, + this.cachedUnresolvedImportsPerFile, + ); } - this.projectService.typingsCache.enqueueInstallTypingsForProject(this, this.lastCachedUnresolvedImportsList, hasAddedorRemovedFiles); + this.projectService.typingsCache.enqueueInstallTypingsForProject( + this, + this.lastCachedUnresolvedImportsList, + hasAddedorRemovedFiles, + ); } else { this.lastCachedUnresolvedImportsList = undefined; @@ -1382,11 +1475,21 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo /** @internal */ updateTypingFiles(typingFiles: SortedReadonlyArray) { - if (enumerateInsertsAndDeletes(typingFiles, this.typingFiles, getStringComparer(!this.useCaseSensitiveFileNames()), /*inserted*/ noop, removed => this.detachScriptInfoFromProject(removed))) { + if ( + enumerateInsertsAndDeletes( + typingFiles, + this.typingFiles, + getStringComparer(!this.useCaseSensitiveFileNames()), + /*inserted*/ noop, + removed => this.detachScriptInfoFromProject(removed), + ) + ) { // If typing files changed, then only schedule project update this.typingFiles = typingFiles; // Invalidate files with unresolved imports - this.resolutionCache.setFilesWithInvalidatedNonRelativeUnresolvedImports(this.cachedUnresolvedImportsPerFile); + this.resolutionCache.setFilesWithInvalidatedNonRelativeUnresolvedImports( + this.cachedUnresolvedImportsPerFile, + ); this.projectService.delayUpdateProjectGraphAndEnsureProjectStructureForOpenFiles(this); } } @@ -1427,24 +1530,37 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo if (!this.typingWatchers!.has(canonicalPath)) { this.typingWatchers!.set( canonicalPath, - typingsWatcherType === TypingWatcherType.FileWatcher ? - this.projectService.watchFactory.watchFile( + typingsWatcherType === TypingWatcherType.FileWatcher + ? this.projectService.watchFactory.watchFile( path, () => - !this.typingWatchers!.isInvoked ? - this.onTypingInstallerWatchInvoke() : - this.writeLog(`TypingWatchers already invoked`), + !this.typingWatchers!.isInvoked + ? this.onTypingInstallerWatchInvoke() + : this.writeLog(`TypingWatchers already invoked`), PollingInterval.High, this.projectService.getWatchOptions(this), WatchType.TypingInstallerLocationFile, this, - ) : - this.projectService.watchFactory.watchDirectory( + ) + : this.projectService.watchFactory.watchDirectory( path, f => { - if (this.typingWatchers!.isInvoked) return this.writeLog(`TypingWatchers already invoked`); - if (!fileExtensionIs(f, Extension.Json)) return this.writeLog(`Ignoring files that are not *.json`); - if (comparePaths(f, combinePaths(this.projectService.typingsInstaller.globalTypingsCacheLocation!, "package.json"), !this.useCaseSensitiveFileNames())) return this.writeLog(`Ignoring package.json change at global typings location`); + if (this.typingWatchers!.isInvoked) { + return this.writeLog(`TypingWatchers already invoked`); + } + if (!fileExtensionIs(f, Extension.Json)) { + return this.writeLog(`Ignoring files that are not *.json`); + } + if ( + comparePaths( + f, + combinePaths( + this.projectService.typingsInstaller.globalTypingsCacheLocation!, + "package.json", + ), + !this.useCaseSensitiveFileNames(), + ) + ) return this.writeLog(`Ignoring package.json change at global typings location`); this.onTypingInstallerWatchInvoke(); }, WatchDirectoryFlags.Recursive, @@ -1480,8 +1596,18 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo } // path in global cache, watch global cache - if (containsPath(this.projectService.typingsInstaller.globalTypingsCacheLocation!, file, this.currentDirectory, !this.useCaseSensitiveFileNames())) { - createProjectWatcher(this.projectService.typingsInstaller.globalTypingsCacheLocation!, TypingWatcherType.DirectoryWatcher); + if ( + containsPath( + this.projectService.typingsInstaller.globalTypingsCacheLocation!, + file, + this.currentDirectory, + !this.useCaseSensitiveFileNames(), + ) + ) { + createProjectWatcher( + this.projectService.typingsInstaller.globalTypingsCacheLocation!, + TypingWatcherType.DirectoryWatcher, + ); continue; } @@ -1512,7 +1638,8 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo Debug.assert(!this.isClosed(), "Called update graph worker of closed project"); this.writeLog(`Starting updateGraphWorker: Project: ${this.getProjectName()}`); const start = timestamp(); - const { hasInvalidatedResolutions, hasInvalidatedLibResolutions } = this.resolutionCache.createHasInvalidatedResolutions(returnFalse, returnFalse); + const { hasInvalidatedResolutions, hasInvalidatedLibResolutions } = this.resolutionCache + .createHasInvalidatedResolutions(returnFalse, returnFalse); this.hasInvalidatedResolutions = hasInvalidatedResolutions; this.hasInvalidatedLibResolutions = hasInvalidatedLibResolutions; this.resolutionCache.startCachingPerDirectoryResolution(); @@ -1528,7 +1655,11 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo // - oldProgram is not set - this is a first time updateGraph is called // - newProgram is different from the old program and structure of the old program was not reused. let hasNewProgram = false; - if (this.program && (!oldProgram || (this.program !== oldProgram && this.program.structureIsReused !== StructureIsReused.Completely))) { + if ( + this.program + && (!oldProgram + || (this.program !== oldProgram && this.program.structureIsReused !== StructureIsReused.Completely)) + ) { hasNewProgram = true; if (oldProgram) { for (const f of oldProgram.getSourceFiles()) { @@ -1577,10 +1708,16 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo this.generatedFilesMap.forEach((watcher, source) => { const sourceFile = this.program!.getSourceFileByPath(source); if ( - !sourceFile || - sourceFile.resolvedPath !== source || - !this.isValidGeneratedFileWatcher( - getDeclarationEmitOutputFilePathWorker(sourceFile.fileName, this.compilerOptions, this.currentDirectory, this.program!.getCommonSourceDirectory(), this.getCanonicalFileName), + !sourceFile + || sourceFile.resolvedPath !== source + || !this.isValidGeneratedFileWatcher( + getDeclarationEmitOutputFilePathWorker( + sourceFile.fileName, + this.compilerOptions, + this.currentDirectory, + this.program!.getCommonSourceDirectory(), + this.getCanonicalFileName, + ), watcher, ) ) { @@ -1611,7 +1748,11 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo this.exportMapCache!.clear(); return true; } - return this.exportMapCache!.onFileChanged(oldSourceFile, sourceFile, !!this.getTypeAcquisition().enable); + return this.exportMapCache!.onFileChanged( + oldSourceFile, + sourceFile, + !!this.getTypeAcquisition().enable, + ); }); } } @@ -1619,7 +1760,10 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo this.changedFilesForExportMapCache.clear(); } - if (this.hasAddedOrRemovedSymlinks || this.program && !this.program.structureIsReused && this.getCompilerOptions().preserveSymlinks) { + if ( + this.hasAddedOrRemovedSymlinks + || this.program && !this.program.structureIsReused && this.getCompilerOptions().preserveSymlinks + ) { // With --preserveSymlinks, we may not determine that a file is a symlink, so we never set `hasAddedOrRemovedSymlinks` this.symlinks = undefined; this.moduleSpecifierCache.clear(); @@ -1634,24 +1778,41 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo // by the host for files in the program when the program is retrieved above but // the program doesn't contain external files so this must be done explicitly. inserted => { - const scriptInfo = this.projectService.getOrCreateScriptInfoNotOpenedByClient(inserted, this.currentDirectory, this.directoryStructureHost); + const scriptInfo = this.projectService.getOrCreateScriptInfoNotOpenedByClient( + inserted, + this.currentDirectory, + this.directoryStructureHost, + ); scriptInfo?.attachToProject(this); }, removed => this.detachScriptInfoFromProject(removed), ); const elapsed = timestamp() - start; this.sendPerformanceEvent("UpdateGraph", elapsed); - this.writeLog(`Finishing updateGraphWorker: Project: ${this.getProjectName()} Version: ${this.getProjectVersion()} structureChanged: ${hasNewProgram}${this.program ? ` structureIsReused:: ${(ts as any).StructureIsReused[this.program.structureIsReused]}` : ""} Elapsed: ${elapsed}ms`); + this.writeLog( + `Finishing updateGraphWorker: Project: ${this.getProjectName()} Version: ${this.getProjectVersion()} structureChanged: ${hasNewProgram}${ + this.program ? ` structureIsReused:: ${(ts as any).StructureIsReused[this.program.structureIsReused]}` + : "" + } Elapsed: ${elapsed}ms`, + ); if (this.projectService.logger.isTestLogger) { if (this.program !== oldProgram) { - this.print(/*writeProjectFileNames*/ true, this.hasAddedorRemovedFiles, /*writeFileVersionAndText*/ true); + this.print( + /*writeProjectFileNames*/ true, + this.hasAddedorRemovedFiles, + /*writeFileVersionAndText*/ true, + ); } else { this.writeLog(`Same program as before`); } } else if (this.hasAddedorRemovedFiles) { - this.print(/*writeProjectFileNames*/ true, /*writeFileExplaination*/ true, /*writeFileVersionAndText*/ false); + this.print( + /*writeProjectFileNames*/ true, + /*writeFileExplaination*/ true, + /*writeFileVersionAndText*/ false, + ); } else if (this.program !== oldProgram) { this.writeLog(`Different program with same set of files`); @@ -1679,7 +1840,9 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo private addMissingFileWatcher(missingFilePath: Path): FileWatcher { if (isConfiguredProject(this)) { // If this file is referenced config file, we are already watching it, no need to watch again - const configFileExistenceInfo = this.projectService.configFileExistenceInfoCache.get(missingFilePath as string as NormalizedPath); + const configFileExistenceInfo = this.projectService.configFileExistenceInfoCache.get( + missingFilePath as string as NormalizedPath, + ); if (configFileExistenceInfo?.config?.projects.has(this.canonicalConfigFilePath)) return noopFileWatcher; } const fileWatcher = this.projectService.watchFactory.watchFile( @@ -1722,7 +1885,11 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo const path = this.toPath(sourceFile); if (this.generatedFilesMap) { if (isGeneratedFileWatcher(this.generatedFilesMap)) { - Debug.fail(`${this.projectName} Expected to not have --out watcher for generated file with options: ${JSON.stringify(this.compilerOptions)}`); + Debug.fail( + `${this.projectName} Expected to not have --out watcher for generated file with options: ${ + JSON.stringify(this.compilerOptions) + }`, + ); return; } if (this.generatedFilesMap.has(path)) return; @@ -1780,18 +1947,28 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo } filesToString(writeProjectFileNames: boolean) { - return this.filesToStringWorker(writeProjectFileNames, /*writeFileExplaination*/ true, /*writeFileVersionAndText*/ false); + return this.filesToStringWorker( + writeProjectFileNames, + /*writeFileExplaination*/ true, + /*writeFileVersionAndText*/ false, + ); } /** @internal */ - private filesToStringWorker(writeProjectFileNames: boolean, writeFileExplaination: boolean, writeFileVersionAndText: boolean) { + private filesToStringWorker( + writeProjectFileNames: boolean, + writeFileExplaination: boolean, + writeFileVersionAndText: boolean, + ) { if (this.isInitialLoadPending()) return "\tFiles (0) InitialLoadPending\n"; if (!this.program) return "\tFiles (0) NoProgram\n"; const sourceFiles = this.program.getSourceFiles(); let strBuilder = `\tFiles (${sourceFiles.length})\n`; if (writeProjectFileNames) { for (const file of sourceFiles) { - strBuilder += `\t${file.fileName}${writeFileVersionAndText ? ` ${file.version} ${JSON.stringify(file.text)}` : ""}\n`; + strBuilder += `\t${file.fileName}${ + writeFileVersionAndText ? ` ${file.version} ${JSON.stringify(file.text)}` : "" + }\n`; } if (writeFileExplaination) { strBuilder += "\n\n"; @@ -1811,7 +1988,11 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo )); this.writeLog("-----------------------------------------------"); if (this.autoImportProviderHost) { - this.autoImportProviderHost.print(/*writeProjectFileNames*/ false, /*writeFileExplaination*/ false, /*writeFileVersionAndText*/ false); + this.autoImportProviderHost.print( + /*writeProjectFileNames*/ false, + /*writeFileExplaination*/ false, + /*writeFileVersionAndText*/ false, + ); } } @@ -1854,13 +2035,21 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo } /** @internal */ - getChangesSinceVersion(lastKnownVersion?: number, includeProjectReferenceRedirectInfo?: boolean): ProjectFilesWithTSDiagnostics { + getChangesSinceVersion( + lastKnownVersion?: number, + includeProjectReferenceRedirectInfo?: boolean, + ): ProjectFilesWithTSDiagnostics { const includeProjectReferenceRedirectInfoIfRequested = includeProjectReferenceRedirectInfo ? (files: Map) => - arrayFrom(files.entries(), ([fileName, isSourceOfProjectReferenceRedirect]): protocol.FileWithProjectReferenceRedirectInfo => ({ - fileName, - isSourceOfProjectReferenceRedirect, - })) + arrayFrom( + files.entries(), + ( + [fileName, isSourceOfProjectReferenceRedirect], + ): protocol.FileWithProjectReferenceRedirectInfo => ({ + fileName, + isSourceOfProjectReferenceRedirect, + }), + ) : (files: Map) => arrayFrom(files.keys()); // Update the graph only if initial configured project load is not pending @@ -1906,7 +2095,10 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo if (!lastReportedFileNames.has(fileName)) { added.set(fileName, isSourceOfProjectReferenceRedirect); } - else if (includeProjectReferenceRedirectInfo && isSourceOfProjectReferenceRedirect !== lastReportedFileNames.get(fileName)) { + else if ( + includeProjectReferenceRedirectInfo + && isSourceOfProjectReferenceRedirect !== lastReportedFileNames.get(fileName) + ) { updatedRedirects.push({ fileName, isSourceOfProjectReferenceRedirect, @@ -1984,7 +2176,9 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo const host = this.projectService.host; if (!host.require && !host.importPlugin) { - this.projectService.logger.info("Plugins were requested but not running in environment that supports 'require'. Nothing will be loaded"); + this.projectService.logger.info( + "Plugins were requested but not running in environment that supports 'require'. Nothing will be loaded", + ); return; } @@ -2012,7 +2206,9 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo enableProxy(pluginModuleFactory: PluginModuleFactory, configEntry: PluginImport) { try { if (typeof pluginModuleFactory !== "function") { - this.projectService.logger.info(`Skipped loading plugin ${configEntry.name} because it did not expose a proper factory function`); + this.projectService.logger.info( + `Skipped loading plugin ${configEntry.name} because it did not expose a proper factory function`, + ); return; } @@ -2030,7 +2226,9 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo for (const k of Object.keys(this.languageService)) { // eslint-disable-next-line local/no-in-operator if (!(k in newLS)) { - this.projectService.logger.info(`Plugin activation warning: Missing proxied method ${k} in created LS. Patching.`); + this.projectService.logger.info( + `Plugin activation warning: Missing proxied method ${k} in created LS. Patching.`, + ); (newLS as any)[k] = (this.languageService as any)[k]; } } @@ -2070,7 +2268,10 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo /** @internal */ getPackageJsonsForAutoImport(rootDir?: string): readonly ProjectPackageJsonInfo[] { - const packageJsons = this.getPackageJsonsVisibleToFile(combinePaths(this.currentDirectory, inferredTypesContainingFile), rootDir); + const packageJsons = this.getPackageJsonsVisibleToFile( + combinePaths(this.currentDirectory, inferredTypesContainingFile), + rootDir, + ); this.packageJsonsForAutoImport = new Set(packageJsons.map(p => p.fileName)); return packageJsons; } @@ -2098,10 +2299,10 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo /** @internal */ includePackageJsonAutoImports(): PackageJsonAutoImportPreference { if ( - this.projectService.includePackageJsonAutoImports() === PackageJsonAutoImportPreference.Off || - !this.languageServiceEnabled || - isInsideNodeModules(this.currentDirectory) || - !this.isDefaultProjectForOpenFiles() + this.projectService.includePackageJsonAutoImports() === PackageJsonAutoImportPreference.Off + || !this.languageServiceEnabled + || isInsideNodeModules(this.currentDirectory) + || !this.isDefaultProjectForOpenFiles() ) { return PackageJsonAutoImportPreference.Off; } @@ -2149,7 +2350,12 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo if (dependencySelection) { tracing?.push(tracing.Phase.Session, "getPackageJsonAutoImportProvider"); const start = timestamp(); - this.autoImportProviderHost = AutoImportProviderProject.create(dependencySelection, this, this.getHostForAutoImportProvider(), this.documentRegistry); + this.autoImportProviderHost = AutoImportProviderProject.create( + dependencySelection, + this, + this.getHostForAutoImportProvider(), + this.documentRegistry, + ); if (this.autoImportProviderHost) { updateProjectIfDirty(this.autoImportProviderHost); this.sendPerformanceEvent("CreatePackageJsonAutoImportProvider", timestamp() - start); @@ -2182,7 +2388,12 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo getNoDtsResolutionProject(rootFileNames: readonly string[]): Project { Debug.assert(this.projectService.serverMode === LanguageServiceMode.Semantic); if (!this.noDtsResolutionProject) { - this.noDtsResolutionProject = new AuxiliaryProject(this.projectService, this.documentRegistry, this.getCompilerOptionsForNoDtsResolutionProject(), this.currentDirectory); + this.noDtsResolutionProject = new AuxiliaryProject( + this.projectService, + this.documentRegistry, + this.getCompilerOptionsForNoDtsResolutionProject(), + this.currentDirectory, + ); } enumerateInsertsAndDeletes( @@ -2228,24 +2439,37 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo } } -function getUnresolvedImports(program: Program, cachedUnresolvedImportsPerFile: Map): SortedReadonlyArray { +function getUnresolvedImports( + program: Program, + cachedUnresolvedImportsPerFile: Map, +): SortedReadonlyArray { const sourceFiles = program.getSourceFiles(); tracing?.push(tracing.Phase.Session, "getUnresolvedImports", { count: sourceFiles.length }); const ambientModules = program.getTypeChecker().getAmbientModules().map(mod => stripQuotes(mod.getName())); - const result = sortAndDeduplicate(flatMap(sourceFiles, sourceFile => extractUnresolvedImportsFromSourceFile(sourceFile, ambientModules, cachedUnresolvedImportsPerFile))); + const result = sortAndDeduplicate( + flatMap( + sourceFiles, + sourceFile => + extractUnresolvedImportsFromSourceFile(sourceFile, ambientModules, cachedUnresolvedImportsPerFile), + ), + ); tracing?.pop(); return result; } -function extractUnresolvedImportsFromSourceFile(file: SourceFile, ambientModules: readonly string[], cachedUnresolvedImportsPerFile: Map): readonly string[] { +function extractUnresolvedImportsFromSourceFile( + file: SourceFile, + ambientModules: readonly string[], + cachedUnresolvedImportsPerFile: Map, +): readonly string[] { return getOrUpdate(cachedUnresolvedImportsPerFile, file.path, () => { if (!file.resolvedModules) return emptyArray; let unresolvedImports: string[] | undefined; file.resolvedModules.forEach(({ resolvedModule }, name) => { // pick unresolved non-relative names if ( - (!resolvedModule || !resolutionExtensionIsTSOrJson(resolvedModule.extension)) && - !isExternalModuleNameRelative(name) && - !ambientModules.some(m => m === name) + (!resolvedModule || !resolutionExtensionIsTSOrJson(resolvedModule.extension)) + && !isExternalModuleNameRelative(name) + && !ambientModules.some(m => m === name) ) { unresolvedImports = append(unresolvedImports, parsePackageName(name).packageName); } @@ -2358,12 +2582,15 @@ export class InferredProject extends Project { // - when useSingleInferredProject is not set and projectRootPath is not set, // we can guarantee that this will be the only root // - other wise it has single root if it has single root script info - return (!this.projectRootPath && !this.projectService.useSingleInferredProject) || - this.getRootScriptInfos().length === 1; + return (!this.projectRootPath && !this.projectService.useSingleInferredProject) + || this.getRootScriptInfos().length === 1; } override close() { - forEach(this.getRootScriptInfos(), info => this.projectService.stopWatchingConfigFilesForInferredProjectRoot(info)); + forEach( + this.getRootScriptInfos(), + info => this.projectService.stopWatchingConfigFilesForInferredProjectRoot(info), + ); super.close(); } @@ -2378,8 +2605,25 @@ export class InferredProject extends Project { /** @internal */ export class AuxiliaryProject extends Project { - constructor(projectService: ProjectService, documentRegistry: DocumentRegistry, compilerOptions: CompilerOptions, currentDirectory: string) { - super(projectService.newAuxiliaryProjectName(), ProjectKind.Auxiliary, projectService, documentRegistry, /*hasExplicitListOfFiles*/ false, /*lastFileExceededProgramSize*/ undefined, compilerOptions, /*compileOnSaveEnabled*/ false, /*watchOptions*/ undefined, projectService.host, currentDirectory); + constructor( + projectService: ProjectService, + documentRegistry: DocumentRegistry, + compilerOptions: CompilerOptions, + currentDirectory: string, + ) { + super( + projectService.newAuxiliaryProjectName(), + ProjectKind.Auxiliary, + projectService, + documentRegistry, + /*hasExplicitListOfFiles*/ false, + /*lastFileExceededProgramSize*/ undefined, + compilerOptions, + /*compileOnSaveEnabled*/ false, + /*watchOptions*/ undefined, + projectService.host, + currentDirectory, + ); } override isOrphan(): boolean { @@ -2397,7 +2641,12 @@ export class AutoImportProviderProject extends Project { private static readonly maxDependencies = 10; /** @internal */ - static getRootFileNames(dependencySelection: PackageJsonAutoImportPreference, hostProject: Project, host: GetPackageJsonEntrypointsHost, compilerOptions: CompilerOptions): string[] { + static getRootFileNames( + dependencySelection: PackageJsonAutoImportPreference, + hostProject: Project, + host: GetPackageJsonEntrypointsHost, + compilerOptions: CompilerOptions, + ): string[] { if (!dependencySelection) { return ts.emptyArray; } @@ -2411,7 +2660,9 @@ export class AutoImportProviderProject extends Project { let dependencyNames: Set | undefined; let rootNames: string[] | undefined; const rootFileName = combinePaths(hostProject.currentDirectory, inferredTypesContainingFile); - const packageJsons = hostProject.getPackageJsonsForAutoImport(combinePaths(hostProject.currentDirectory, rootFileName)); + const packageJsons = hostProject.getPackageJsonsForAutoImport( + combinePaths(hostProject.currentDirectory, rootFileName), + ); for (const packageJson of packageJsons) { packageJson.dependencies?.forEach((_, dependenyName) => addDependency(dependenyName)); packageJson.peerDependencies?.forEach((_, dependencyName) => addDependency(dependencyName)); @@ -2422,8 +2673,13 @@ export class AutoImportProviderProject extends Project { const symlinkCache = hostProject.getSymlinkCache(); for (const name of arrayFrom(dependencyNames.keys())) { // Avoid creating a large project that would significantly slow down time to editor interactivity - if (dependencySelection === PackageJsonAutoImportPreference.Auto && dependenciesAdded > this.maxDependencies) { - hostProject.log(`AutoImportProviderProject: attempted to add more than ${this.maxDependencies} dependencies. Aborting.`); + if ( + dependencySelection === PackageJsonAutoImportPreference.Auto + && dependenciesAdded > this.maxDependencies + ) { + hostProject.log( + `AutoImportProviderProject: attempted to add more than ${this.maxDependencies} dependencies. Aborting.`, + ); return ts.emptyArray; } @@ -2449,23 +2705,30 @@ export class AutoImportProviderProject extends Project { // 2. Try to load from the @types package in the tree and in the global // typings cache location, if enabled. - const done = forEach([hostProject.currentDirectory, hostProject.getGlobalTypingsCacheLocation()], directory => { - if (directory) { - const typesPackageJson = resolvePackageNameToPackageJson( - `@types/${name}`, - directory, - compilerOptions, - host, - program.getModuleResolutionCache(), - ); - if (typesPackageJson) { - const entrypoints = getRootNamesFromPackageJson(typesPackageJson, program, symlinkCache); - rootNames = concatenate(rootNames, entrypoints); - dependenciesAdded += entrypoints?.length ? 1 : 0; - return true; + const done = forEach( + [hostProject.currentDirectory, hostProject.getGlobalTypingsCacheLocation()], + directory => { + if (directory) { + const typesPackageJson = resolvePackageNameToPackageJson( + `@types/${name}`, + directory, + compilerOptions, + host, + program.getModuleResolutionCache(), + ); + if (typesPackageJson) { + const entrypoints = getRootNamesFromPackageJson( + typesPackageJson, + program, + symlinkCache, + ); + rootNames = concatenate(rootNames, entrypoints); + dependenciesAdded += entrypoints?.length ? 1 : 0; + return true; + } } - } - }); + }, + ); if (done) continue; @@ -2473,7 +2736,12 @@ export class AutoImportProviderProject extends Project { // allow processing JS from node_modules, go back to the implementation // package and load the JS. if (packageJson && compilerOptions.allowJs && compilerOptions.maxNodeModuleJsDepth) { - const entrypoints = getRootNamesFromPackageJson(packageJson, program, symlinkCache, /*resolveJs*/ true); + const entrypoints = getRootNamesFromPackageJson( + packageJson, + program, + symlinkCache, + /*resolveJs*/ true, + ); rootNames = concatenate(rootNames, entrypoints); dependenciesAdded += entrypoints?.length ? 1 : 0; } @@ -2481,7 +2749,11 @@ export class AutoImportProviderProject extends Project { } if (rootNames?.length) { - hostProject.log(`AutoImportProviderProject: found ${rootNames.length} root files in ${dependenciesAdded} dependencies in ${timestamp() - start} ms`); + hostProject.log( + `AutoImportProviderProject: found ${rootNames.length} root files in ${dependenciesAdded} dependencies in ${ + timestamp() - start + } ms`, + ); } return rootNames || ts.emptyArray; @@ -2491,7 +2763,12 @@ export class AutoImportProviderProject extends Project { } } - function getRootNamesFromPackageJson(packageJson: PackageJsonInfo, program: Program, symlinkCache: SymlinkCache, resolveJs?: boolean) { + function getRootNamesFromPackageJson( + packageJson: PackageJsonInfo, + program: Program, + symlinkCache: SymlinkCache, + resolveJs?: boolean, + ) { const entrypoints = getEntrypointsFromPackageJsonInfo( packageJson, compilerOptions, @@ -2510,7 +2787,8 @@ export class AutoImportProviderProject extends Project { } return mapDefined(entrypoints, entrypoint => { - const resolvedFileName = isSymlink ? entrypoint.replace(packageJson.packageDirectory, real) : entrypoint; + const resolvedFileName = isSymlink ? entrypoint.replace(packageJson.packageDirectory, real) + : entrypoint; if (!program.getSourceFile(resolvedFileName) && !(isSymlink && program.getSourceFile(entrypoint))) { return resolvedFileName; } @@ -2530,7 +2808,12 @@ export class AutoImportProviderProject extends Project { }; /** @internal */ - static create(dependencySelection: PackageJsonAutoImportPreference, hostProject: Project, host: GetPackageJsonEntrypointsHost, documentRegistry: DocumentRegistry): AutoImportProviderProject | undefined { + static create( + dependencySelection: PackageJsonAutoImportPreference, + hostProject: Project, + host: GetPackageJsonEntrypointsHost, + documentRegistry: DocumentRegistry, + ): AutoImportProviderProject | undefined { if (dependencySelection === PackageJsonAutoImportPreference.Off) { return undefined; } @@ -2557,10 +2840,25 @@ export class AutoImportProviderProject extends Project { documentRegistry: DocumentRegistry, compilerOptions: CompilerOptions, ) { - super(hostProject.projectService.newAutoImportProviderProjectName(), ProjectKind.AutoImportProvider, hostProject.projectService, documentRegistry, /*hasExplicitListOfFiles*/ false, /*lastFileExceededProgramSize*/ undefined, compilerOptions, /*compileOnSaveEnabled*/ false, hostProject.getWatchOptions(), hostProject.projectService.host, hostProject.currentDirectory); + super( + hostProject.projectService.newAutoImportProviderProjectName(), + ProjectKind.AutoImportProvider, + hostProject.projectService, + documentRegistry, + /*hasExplicitListOfFiles*/ false, + /*lastFileExceededProgramSize*/ undefined, + compilerOptions, + /*compileOnSaveEnabled*/ false, + hostProject.getWatchOptions(), + hostProject.projectService.host, + hostProject.currentDirectory, + ); this.rootFileNames = initialRootNames; - this.useSourceOfProjectReferenceRedirect = maybeBind(this.hostProject, this.hostProject.useSourceOfProjectReferenceRedirect); + this.useSourceOfProjectReferenceRedirect = maybeBind( + this.hostProject, + this.hostProject.useSourceOfProjectReferenceRedirect, + ); this.getParsedCommandLine = maybeBind(this.hostProject, this.hostProject.getParsedCommandLine); } @@ -2614,7 +2912,9 @@ export class AutoImportProviderProject extends Project { } override getLanguageService(): never { - throw new Error("AutoImportProviderProject language service should never be used. To get the program, use `project.getCurrentProgram()`."); + throw new Error( + "AutoImportProviderProject language service should never be used. To get the program, use `project.getCurrentProgram()`.", + ); } /** @internal */ @@ -2628,7 +2928,9 @@ export class AutoImportProviderProject extends Project { } override getHostForAutoImportProvider(): never { - throw new Error("AutoImportProviderProject cannot provide its own host; use `hostProject.getModuleResolutionHostForAutomImportProvider()` instead."); + throw new Error( + "AutoImportProviderProject cannot provide its own host; use `hostProject.getModuleResolutionHostForAutomImportProvider()` instead.", + ); } override getProjectReferences() { @@ -2697,8 +2999,26 @@ export class ConfiguredProject extends Project { private compilerHost?: CompilerHost; /** @internal */ - constructor(configFileName: NormalizedPath, readonly canonicalConfigFilePath: NormalizedPath, projectService: ProjectService, documentRegistry: DocumentRegistry, cachedDirectoryStructureHost: CachedDirectoryStructureHost) { - super(configFileName, ProjectKind.Configured, projectService, documentRegistry, /*hasExplicitListOfFiles*/ false, /*lastFileExceededProgramSize*/ undefined, /*compilerOptions*/ {}, /*compileOnSaveEnabled*/ false, /*watchOptions*/ undefined, cachedDirectoryStructureHost, getDirectoryPath(configFileName)); + constructor( + configFileName: NormalizedPath, + readonly canonicalConfigFilePath: NormalizedPath, + projectService: ProjectService, + documentRegistry: DocumentRegistry, + cachedDirectoryStructureHost: CachedDirectoryStructureHost, + ) { + super( + configFileName, + ProjectKind.Configured, + projectService, + documentRegistry, + /*hasExplicitListOfFiles*/ false, + /*lastFileExceededProgramSize*/ undefined, + /*compilerOptions*/ {}, + /*compileOnSaveEnabled*/ false, + /*watchOptions*/ undefined, + cachedDirectoryStructureHost, + getDirectoryPath(configFileName), + ); } /** @internal */ @@ -2723,10 +3043,18 @@ export class ConfiguredProject extends Project { // Ensure the config file existience info is cached let configFileExistenceInfo = this.projectService.configFileExistenceInfoCache.get(canonicalConfigFilePath); if (!configFileExistenceInfo) { - this.projectService.configFileExistenceInfoCache.set(canonicalConfigFilePath, configFileExistenceInfo = { exists: this.projectService.host.fileExists(configFileName) }); + this.projectService.configFileExistenceInfoCache.set( + canonicalConfigFilePath, + configFileExistenceInfo = { exists: this.projectService.host.fileExists(configFileName) }, + ); } // Ensure we have upto date parsed command line - this.projectService.ensureParsedConfigUptoDate(configFileName, canonicalConfigFilePath, configFileExistenceInfo, this); + this.projectService.ensureParsedConfigUptoDate( + configFileName, + canonicalConfigFilePath, + configFileExistenceInfo, + this, + ); // Watch wild cards if LS is enabled if (this.languageServiceEnabled && this.projectService.serverMode === LanguageServiceMode.Semantic) { this.projectService.watchWildcards(configFileName, configFileExistenceInfo, this); @@ -2736,7 +3064,9 @@ export class ConfiguredProject extends Project { /** @internal */ onReleaseParsedCommandLine(fileName: string) { - this.releaseParsedConfig(asNormalizedPath(this.projectService.toCanonicalFileName(asNormalizedPath(normalizePath(fileName))))); + this.releaseParsedConfig( + asNormalizedPath(this.projectService.toCanonicalFileName(asNormalizedPath(normalizePath(fileName)))), + ); } /** @internal */ @@ -2819,7 +3149,9 @@ export class ConfiguredProject extends Project { if (!options.plugins?.length && !this.projectService.globalPlugins.length) return; const host = this.projectService.host; if (!host.require && !host.importPlugin) { - this.projectService.logger.info("Plugins were requested but not running in environment that supports 'require'. Nothing will be loaded"); + this.projectService.logger.info( + "Plugins were requested but not running in environment that supports 'require'. Nothing will be loaded", + ); return; } @@ -2859,7 +3191,9 @@ export class ConfiguredProject extends Project { } override close() { - this.projectService.configFileExistenceInfoCache.forEach((_configFileExistenceInfo, canonicalConfigFilePath) => this.releaseParsedConfig(canonicalConfigFilePath)); + this.projectService.configFileExistenceInfoCache.forEach((_configFileExistenceInfo, canonicalConfigFilePath) => + this.releaseParsedConfig(canonicalConfigFilePath) + ); this.projectErrors = undefined; this.openFileWatchTriggered.clear(); this.compilerHost = undefined; @@ -2878,8 +3212,8 @@ export class ConfiguredProject extends Project { /** @internal */ isSolution() { - return this.getRootFilesMap().size === 0 && - !this.canConfigFileJsonReportNoInputFiles; + return this.getRootFilesMap().size === 0 + && !this.canConfigFileJsonReportNoInputFiles; } /** @@ -2892,9 +3226,9 @@ export class ConfiguredProject extends Project { this, info.path, child => - projectContainsInfoDirectly(child, info) ? - child : - undefined, + projectContainsInfoDirectly(child, info) + ? child + : undefined, ProjectReferenceProjectLoadKind.Find, ); } @@ -2914,7 +3248,9 @@ export class ConfiguredProject extends Project { return false; } - const configFileExistenceInfo = this.projectService.configFileExistenceInfoCache.get(this.canonicalConfigFilePath)!; + const configFileExistenceInfo = this.projectService.configFileExistenceInfoCache.get( + this.canonicalConfigFilePath, + )!; if (this.projectService.hasPendingProjectUpdate(this)) { // If there is pending update for this project, // we dont know if this project would be needed by any of the open files impacted by this config file @@ -2929,8 +3265,8 @@ export class ConfiguredProject extends Project { configFileExistenceInfo.openFilesImpactedByConfigFile, (_value, infoPath) => { const info = this.projectService.getScriptInfoForPath(infoPath)!; - return this.containsScriptInfo(info) || - !!forEachResolvedProjectReferenceProject( + return this.containsScriptInfo(info) + || !!forEachResolvedProjectReferenceProject( this, info.path, child => child.containsScriptInfo(info), @@ -2951,7 +3287,13 @@ export class ConfiguredProject extends Project { /** @internal */ updateErrorOnNoInputFiles(fileNames: string[]) { - updateErrorForNoInputFiles(fileNames, this.getConfigFilePath(), this.getCompilerOptions().configFile!.configFileSpecs!, this.projectErrors!, this.canConfigFileJsonReportNoInputFiles); + updateErrorForNoInputFiles( + fileNames, + this.getConfigFilePath(), + this.getCompilerOptions().configFile!.configFileSpecs!, + this.projectErrors!, + this.canConfigFileJsonReportNoInputFiles, + ); } } @@ -2962,8 +3304,29 @@ export class ConfiguredProject extends Project { export class ExternalProject extends Project { excludedFiles: readonly NormalizedPath[] = []; /** @internal */ - constructor(public externalProjectName: string, projectService: ProjectService, documentRegistry: DocumentRegistry, compilerOptions: CompilerOptions, lastFileExceededProgramSize: string | undefined, public override compileOnSaveEnabled: boolean, projectFilePath?: string, watchOptions?: WatchOptions) { - super(externalProjectName, ProjectKind.External, projectService, documentRegistry, /*hasExplicitListOfFiles*/ true, lastFileExceededProgramSize, compilerOptions, compileOnSaveEnabled, watchOptions, projectService.host, getDirectoryPath(projectFilePath || normalizeSlashes(externalProjectName))); + constructor( + public externalProjectName: string, + projectService: ProjectService, + documentRegistry: DocumentRegistry, + compilerOptions: CompilerOptions, + lastFileExceededProgramSize: string | undefined, + public override compileOnSaveEnabled: boolean, + projectFilePath?: string, + watchOptions?: WatchOptions, + ) { + super( + externalProjectName, + ProjectKind.External, + projectService, + documentRegistry, + /*hasExplicitListOfFiles*/ true, + lastFileExceededProgramSize, + compilerOptions, + compileOnSaveEnabled, + watchOptions, + projectService.host, + getDirectoryPath(projectFilePath || normalizeSlashes(externalProjectName)), + ); this.enableGlobalPlugins(this.getCompilerOptions()); } diff --git a/src/server/scriptInfo.ts b/src/server/scriptInfo.ts index 57a9d06c911fb..ff7736776b1a7 100644 --- a/src/server/scriptInfo.ts +++ b/src/server/scriptInfo.ts @@ -175,9 +175,9 @@ export class TextStorage { * returns true if text changed */ public reloadWithFileText(tempFileName?: string) { - const { text: newText, fileSize } = tempFileName || !this.info.isDynamicOrHasMixedContent() ? - this.getFileTextAndSize(tempFileName) : - { text: "", fileSize: undefined }; + const { text: newText, fileSize } = tempFileName || !this.info.isDynamicOrHasMixedContent() + ? this.getFileTextAndSize(tempFileName) + : { text: "", fileSize: undefined }; const reloaded = this.reload(newText); this.fileSize = fileSize; // NB: after reload since reload clears it this.ownFileText = !tempFileName || tempFileName === this.info.fileName; @@ -189,9 +189,9 @@ export class TextStorage { * returns true when scheduling reload */ public scheduleReloadIfNeeded() { - return !this.pendingReloadFromDisk && !this.ownFileText ? - this.pendingReloadFromDisk = true : - false; + return !this.pendingReloadFromDisk && !this.ownFileText + ? this.pendingReloadFromDisk = true + : false; } public delayReloadFromFileIntoText() { @@ -216,20 +216,20 @@ export class TextStorage { } public getSnapshot(): IScriptSnapshot { - return this.tryUseScriptVersionCache()?.getSnapshot() || - (this.textSnapshot ??= ScriptSnapshot.fromString(Debug.checkDefined(this.text))); + return this.tryUseScriptVersionCache()?.getSnapshot() + || (this.textSnapshot ??= ScriptSnapshot.fromString(Debug.checkDefined(this.text))); } public getAbsolutePositionAndLineText(oneBasedLine: number): AbsolutePositionAndLineText { const svc = this.tryUseScriptVersionCache(); if (svc) return svc.getAbsolutePositionAndLineText(oneBasedLine); const lineMap = this.getLineMap(); - return oneBasedLine <= lineMap.length ? - { + return oneBasedLine <= lineMap.length + ? { absolutePosition: lineMap[oneBasedLine - 1], lineText: this.text!.substring(lineMap[oneBasedLine - 1], lineMap[oneBasedLine]), - } : - { + } + : { absolutePosition: this.text!.length, lineText: undefined, }; @@ -252,9 +252,9 @@ export class TextStorage { */ lineOffsetToPosition(line: number, offset: number, allowEdits?: true): number { const svc = this.tryUseScriptVersionCache(); - return svc ? - svc.lineOffsetToPosition(line, offset) : - computePositionOfLineAndCharacter(this.getLineMap(), line - 1, offset - 1, this.text, allowEdits); + return svc + ? svc.lineOffsetToPosition(line, offset) + : computePositionOfLineAndCharacter(this.getLineMap(), line - 1, offset - 1, this.text, allowEdits); } positionToLineOffset(position: number): protocol.Location { @@ -274,7 +274,9 @@ export class TextStorage { if (fileSize > maxFileSize) { Debug.assert(!!this.info.containingProjects.length); const service = this.info.containingProjects[0].projectService; - service.logger.info(`Skipped loading contents of large file ${fileName} for info ${this.info.fileName}: fileSize: ${fileSize}`); + service.logger.info( + `Skipped loading contents of large file ${fileName} for info ${this.info.fileName}: fileSize: ${fileSize}`, + ); this.info.containingProjects[0].projectService.sendLargeFileReferencedEvent(fileName, fileSize); return { text: "", fileSize }; } @@ -313,7 +315,10 @@ export class TextStorage { private getOrLoadText() { if (this.text === undefined || this.pendingReloadFromDisk) { - Debug.assert(!this.svc || this.pendingReloadFromDisk, "ScriptVersionCache should not be set when reloading from disk"); + Debug.assert( + !this.svc || this.pendingReloadFromDisk, + "ScriptVersionCache should not be set when reloading from disk", + ); this.reloadWithFileText(); } return this.text!; @@ -338,10 +343,10 @@ export class TextStorage { } export function isDynamicFileName(fileName: NormalizedPath) { - return fileName[0] === "^" || - ((stringContains(fileName, "walkThroughSnippet:/") || stringContains(fileName, "untitled:/")) && - getBaseFileName(fileName)[0] === "^") || - (stringContains(fileName, ":^") && !stringContains(fileName, directorySeparator)); + return fileName[0] === "^" + || ((stringContains(fileName, "walkThroughSnippet:/") || stringContains(fileName, "untitled:/")) + && getBaseFileName(fileName)[0] === "^") + || (stringContains(fileName, ":^") && !stringContains(fileName, directorySeparator)); } /** @internal */ @@ -430,8 +435,8 @@ export class ScriptInfo { public open(newText: string | undefined) { this.textStorage.isOpen = true; if ( - newText !== undefined && - this.textStorage.reload(newText) + newText !== undefined + && this.textStorage.reload(newText) ) { // reload new contents only if the existing contents changed this.markContainingProjectsAsDirty(); @@ -547,7 +552,11 @@ export class ScriptInfo { detachAllProjects() { for (const p of this.containingProjects) { if (isConfiguredProject(p)) { - p.getCachedDirectoryStructureHost().addOrDeleteFile(this.fileName, this.path, FileWatcherEventKind.Deleted); + p.getCachedDirectoryStructureHost().addOrDeleteFile( + this.fileName, + this.path, + FileWatcherEventKind.Deleted, + ); } const existingRoot = p.getRootFilesMap().get(this.path); // detach is unnecessary since we'll clean the list of containing projects anyways @@ -587,13 +596,16 @@ export class ScriptInfo { // If we havent found default configuredProject and // its not the last one, find it and use that one if there if ( - defaultConfiguredProject === undefined && - index !== this.containingProjects.length - 1 + defaultConfiguredProject === undefined + && index !== this.containingProjects.length - 1 ) { - defaultConfiguredProject = project.projectService.findDefaultConfiguredProject(this) || false; + defaultConfiguredProject = project.projectService.findDefaultConfiguredProject(this) + || false; } if (defaultConfiguredProject === project) return project; - if (!firstNonSourceOfProjectReferenceRedirect) firstNonSourceOfProjectReferenceRedirect = project; + if (!firstNonSourceOfProjectReferenceRedirect) { + firstNonSourceOfProjectReferenceRedirect = project; + } } if (!firstConfiguredProject) firstConfiguredProject = project; } @@ -605,11 +617,11 @@ export class ScriptInfo { } } return ensurePrimaryProjectKind( - defaultConfiguredProject || - firstNonSourceOfProjectReferenceRedirect || - firstConfiguredProject || - firstExternalProject || - firstInferredProject, + defaultConfiguredProject + || firstNonSourceOfProjectReferenceRedirect + || firstConfiguredProject + || firstExternalProject + || firstInferredProject, ); } } @@ -731,7 +743,10 @@ export class ScriptInfo { * reported as the default project for a ScriptInfo. */ function ensurePrimaryProjectKind(project: Project | undefined) { - if (!project || project.projectKind === ProjectKind.AutoImportProvider || project.projectKind === ProjectKind.Auxiliary) { + if ( + !project || project.projectKind === ProjectKind.AutoImportProvider + || project.projectKind === ProjectKind.Auxiliary + ) { return Errors.ThrowNoProject(); } return project; diff --git a/src/server/scriptVersionCache.ts b/src/server/scriptVersionCache.ts index 28449179243cf..111f3f3c1148e 100644 --- a/src/server/scriptVersionCache.ts +++ b/src/server/scriptVersionCache.ts @@ -45,8 +45,20 @@ export interface LineIndexWalker { goSubtree: boolean; done: boolean; leaf(relativeStart: number, relativeLength: number, lineCollection: LineLeaf): void; - pre?(relativeStart: number, relativeLength: number, lineCollection: LineCollection, parent: LineNode, nodeType: CharRangeSection): void; - post?(relativeStart: number, relativeLength: number, lineCollection: LineCollection, parent: LineNode, nodeType: CharRangeSection): void; + pre?( + relativeStart: number, + relativeLength: number, + lineCollection: LineCollection, + parent: LineNode, + nodeType: CharRangeSection, + ): void; + post?( + relativeStart: number, + relativeLength: number, + lineCollection: LineCollection, + parent: LineNode, + nodeType: CharRangeSection, + ): void; } class EditWalker implements LineIndexWalker { @@ -164,7 +176,13 @@ class EditWalker implements LineIndexWalker { this.stack.pop(); } - pre(_relativeStart: number, _relativeLength: number, lineCollection: LineCollection, _parent: LineCollection, nodeType: CharRangeSection): void { + pre( + _relativeStart: number, + _relativeLength: number, + lineCollection: LineCollection, + _parent: LineCollection, + nodeType: CharRangeSection, + ): void { // currentNode corresponds to parent, but in the new tree const currentNode = this.stack[this.stack.length - 1]; @@ -261,7 +279,10 @@ class TextChange { } getTextChangeRange() { - return createTextChangeRange(createTextSpan(this.pos, this.deleteLen), this.insertedText ? this.insertedText.length : 0); + return createTextChangeRange( + createTextSpan(this.pos, this.deleteLen), + this.insertedText ? this.insertedText.length : 0, + ); } } @@ -292,9 +313,9 @@ export class ScriptVersionCache { edit(pos: number, deleteLen: number, insertedText?: string) { this.changes.push(new TextChange(pos, deleteLen, insertedText)); if ( - this.changes.length > ScriptVersionCache.changeNumberThreshold || - deleteLen > ScriptVersionCache.changeLengthThreshold || - insertedText && insertedText.length > ScriptVersionCache.changeLengthThreshold + this.changes.length > ScriptVersionCache.changeNumberThreshold + || deleteLen > ScriptVersionCache.changeLengthThreshold + || insertedText && insertedText.length > ScriptVersionCache.changeLengthThreshold ) { this.getSnapshot(); } @@ -343,7 +364,8 @@ export class ScriptVersionCache { lineToTextSpan(line: number): TextSpan { const index = this._getSnapshot().index; const { lineText, absolutePosition } = index.lineNumberToInfo(line + 1); - const len = lineText !== undefined ? lineText.length : index.absolutePositionOfStartOfLine(line + 2) - absolutePosition; + const len = lineText !== undefined ? lineText.length + : index.absolutePositionOfStartOfLine(line + 2) - absolutePosition; return createTextSpan(absolutePosition, len); } @@ -383,7 +405,12 @@ export class ScriptVersionCache { } class LineIndexSnapshot implements IScriptSnapshot { - constructor(readonly version: number, readonly cache: ScriptVersionCache, readonly index: LineIndex, readonly changesSincePreviousVersion: readonly TextChange[] = emptyArray) { + constructor( + readonly version: number, + readonly cache: ScriptVersionCache, + readonly index: LineIndex, + readonly changesSincePreviousVersion: readonly TextChange[] = emptyArray, + ) { } getText(rangeStart: number, rangeEnd: number) { @@ -606,7 +633,13 @@ export class LineNode implements LineCollection { } } - private execWalk(rangeStart: number, rangeLength: number, walkFns: LineIndexWalker, childIndex: number, nodeType: CharRangeSection) { + private execWalk( + rangeStart: number, + rangeLength: number, + walkFns: LineIndexWalker, + childIndex: number, + nodeType: CharRangeSection, + ) { if (walkFns.pre) { walkFns.pre(rangeStart, rangeLength, this.children[childIndex], this, nodeType); } @@ -622,7 +655,13 @@ export class LineNode implements LineCollection { return walkFns.done; } - private skipChild(relativeStart: number, relativeLength: number, childIndex: number, walkFns: LineIndexWalker, nodeType: CharRangeSection) { + private skipChild( + relativeStart: number, + relativeLength: number, + childIndex: number, + walkFns: LineIndexWalker, + nodeType: CharRangeSection, + ) { if (walkFns.pre && (!walkFns.done)) { walkFns.pre(relativeStart, relativeLength, this.children[childIndex], this, nodeType); walkFns.goSubtree = true; @@ -649,7 +688,15 @@ export class LineNode implements LineCollection { } else { // Case II: start and end of range in different subtrees (possibly with subtrees in the middle) - if (this.execWalk(adjustedStart, childCharCount - adjustedStart, walkFns, childIndex, CharRangeSection.Start)) { + if ( + this.execWalk( + adjustedStart, + childCharCount - adjustedStart, + walkFns, + childIndex, + CharRangeSection.Start, + ) + ) { return; } let adjustedLength = rangeLength - (childCharCount - adjustedStart); @@ -683,7 +730,10 @@ export class LineNode implements LineCollection { // Input position is relative to the start of this node. // Output line number is absolute. - charOffsetToLineInfo(lineNumberAccumulator: number, relativePosition: number): { oneBasedLine: number; zeroBasedColumn: number; lineText: string | undefined; } { + charOffsetToLineInfo( + lineNumberAccumulator: number, + relativePosition: number, + ): { oneBasedLine: number; zeroBasedColumn: number; lineText: string | undefined; } { if (this.children.length === 0) { // Root node might have no children if this is an empty document. return { oneBasedLine: lineNumberAccumulator, zeroBasedColumn: relativePosition, lineText: undefined }; @@ -692,7 +742,11 @@ export class LineNode implements LineCollection { for (const child of this.children) { if (child.charCount() > relativePosition) { if (child.isLeaf()) { - return { oneBasedLine: lineNumberAccumulator, zeroBasedColumn: relativePosition, lineText: child.text }; + return { + oneBasedLine: lineNumberAccumulator, + zeroBasedColumn: relativePosition, + lineText: child.text, + }; } else { return (child as LineNode).charOffsetToLineInfo(lineNumberAccumulator, relativePosition); @@ -718,11 +772,15 @@ export class LineNode implements LineCollection { * Output line number is relative to the child. * positionAccumulator will be an absolute position once relativeLineNumber reaches 0. */ - lineNumberToInfo(relativeOneBasedLine: number, positionAccumulator: number): { position: number; leaf: LineLeaf | undefined; } { + lineNumberToInfo( + relativeOneBasedLine: number, + positionAccumulator: number, + ): { position: number; leaf: LineLeaf | undefined; } { for (const child of this.children) { const childLineCount = child.lineCount(); if (childLineCount >= relativeOneBasedLine) { - return child.isLeaf() ? { position: positionAccumulator, leaf: child } : (child as LineNode).lineNumberToInfo(relativeOneBasedLine, positionAccumulator); + return child.isLeaf() ? { position: positionAccumulator, leaf: child } + : (child as LineNode).lineNumberToInfo(relativeOneBasedLine, positionAccumulator); } else { relativeOneBasedLine -= childLineCount; diff --git a/src/server/session.ts b/src/server/session.ts index 0cf89ad746a23..96f2e42069cd0 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -217,8 +217,8 @@ function isDeclarationFileInJSOnlyNonConfiguredProject(project: Project, file: N // file has '// @ts-check'). if ( - (isInferredProject(project) || isExternalProject(project)) && - project.isJsOnlyProject() + (isInferredProject(project) || isExternalProject(project)) + && project.isJsOnlyProject() ) { const scriptInfo = project.getScriptInfoForNormalizedPath(file); return scriptInfo && !scriptInfo.isJavaScript(); @@ -274,7 +274,10 @@ export function formatDiagnosticToProtocol(diag: Diagnostic, includeFileName: tr /** @internal */ export function formatDiagnosticToProtocol(diag: Diagnostic, includeFileName: false): protocol.Diagnostic; /** @internal */ -export function formatDiagnosticToProtocol(diag: Diagnostic, includeFileName: boolean): protocol.Diagnostic | protocol.DiagnosticWithFileName { +export function formatDiagnosticToProtocol( + diag: Diagnostic, + includeFileName: boolean, +): protocol.Diagnostic | protocol.DiagnosticWithFileName { const start = (diag.file && convertToLocation(getLineAndCharacterOfPosition(diag.file, diag.start!)))!; // TODO: GH#18217 const end = (diag.file && convertToLocation(getLineAndCharacterOfPosition(diag.file, diag.start! + diag.length!)))!; // TODO: GH#18217 const text = flattenDiagnosticMessageText(diag.messageText, "\n"); @@ -315,7 +318,12 @@ export type CommandNames = protocol.CommandTypes; /** @deprecated use ts.server.protocol.CommandTypes */ export const CommandNames = (protocol as any).CommandTypes; -export function formatMessage(msg: T, logger: Logger, byteLength: (s: string, encoding: BufferEncoding) => number, newLine: string): string { +export function formatMessage( + msg: T, + logger: Logger, + byteLength: (s: string, encoding: BufferEncoding) => number, + newLine: string, +): string { const verboseLogging = logger.hasLevel(LogLevel.verbose); const json = JSON.stringify(msg); @@ -422,7 +430,10 @@ class MultistepOperation implements NextStep { tracing?.instant(tracing.Phase.Session, "stepCanceled", { seq: this.requestId }); } else { - tracing?.instant(tracing.Phase.Session, "stepError", { seq: this.requestId, message: (e as Error).message }); + tracing?.instant(tracing.Phase.Session, "stepError", { + seq: this.requestId, + message: (e as Error).message, + }); this.operationHost.logError(e, `delayed processing of request ${this.requestId}`); } } @@ -480,7 +491,10 @@ function combineProjectOutput( projects: Projects, action: (project: Project, value: T) => readonly U[] | U | undefined, ): U[] { - const outputs = flatMapToMutable(isArray(projects) ? projects : projects.projects, project => action(project, defaultValue)); + const outputs = flatMapToMutable( + isArray(projects) ? projects : projects.projects, + project => action(project, defaultValue), + ); if (!isArray(projects) && projects.symLinkedProjects) { projects.symLinkedProjects.forEach((projects, path) => { const value = getValue(path); @@ -512,7 +526,14 @@ function getRenameLocationsWorker( defaultProject, initialLocation, /*isForRename*/ true, - (project, position) => project.getLanguageService().findRenameLocations(position.fileName, position.pos, findInStrings, findInComments, preferences), + (project, position) => + project.getLanguageService().findRenameLocations( + position.fileName, + position.pos, + findInStrings, + findInComments, + preferences, + ), (renameLocation, cb) => cb(documentSpanLocation(renameLocation)), ); @@ -537,8 +558,17 @@ function getRenameLocationsWorker( return results; } -function getDefinitionLocation(defaultProject: Project, initialLocation: DocumentPosition, isForRename: boolean): DocumentPosition | undefined { - const infos = defaultProject.getLanguageService().getDefinitionAtPosition(initialLocation.fileName, initialLocation.pos, /*searchOtherFilesOnly*/ false, /*stopAtAlias*/ isForRename); +function getDefinitionLocation( + defaultProject: Project, + initialLocation: DocumentPosition, + isForRename: boolean, +): DocumentPosition | undefined { + const infos = defaultProject.getLanguageService().getDefinitionAtPosition( + initialLocation.fileName, + initialLocation.pos, + /*searchOtherFilesOnly*/ false, + /*stopAtAlias*/ isForRename, + ); const info = infos && firstOrUndefined(infos); // Note that the value of `isLocal` may depend on whether or not the checker has run on the containing file // (implying that FAR cascading behavior may depend on request order) @@ -557,7 +587,9 @@ function getReferencesWorker( initialLocation, /*isForRename*/ false, (project, position) => { - logger.info(`Finding references to ${position.fileName} position ${position.pos} in project ${project.getProjectName()}`); + logger.info( + `Finding references to ${position.fileName} position ${position.pos} in project ${project.getProjectName()}`, + ); return project.getLanguageService().findReferences(position.fileName, position.pos); }, (referencedSymbol, cb) => { @@ -606,7 +638,10 @@ function getReferencesWorker( let progress = false; perProjectResults.forEach((referencedSymbols, project) => { if (updatedProjects.has(project)) return; - const updated = project.getLanguageService().updateIsDefinitionOfReferencedSymbols(referencedSymbols, knownSymbolSpans); + const updated = project.getLanguageService().updateIsDefinitionOfReferencedSymbols( + referencedSymbols, + knownSymbolSpans, + ); if (updated) { updatedProjects.add(project); progress = true; @@ -636,10 +671,13 @@ function getReferencesWorker( // dropped later when we check for defs with ref-count 0. perProjectResults.forEach((projectResults, project) => { for (const referencedSymbol of projectResults) { - const mappedDefinitionFile = getMappedLocationForProject(documentSpanLocation(referencedSymbol.definition), project); - const definition: ReferencedSymbolDefinitionInfo = mappedDefinitionFile === undefined ? - referencedSymbol.definition : - { + const mappedDefinitionFile = getMappedLocationForProject( + documentSpanLocation(referencedSymbol.definition), + project, + ); + const definition: ReferencedSymbolDefinitionInfo = mappedDefinitionFile === undefined + ? referencedSymbol.definition + : { ...referencedSymbol.definition, textSpan: createTextSpan(mappedDefinitionFile.pos, referencedSymbol.definition.textSpan.length), // Why would the length be the same in the original? fileName: mappedDefinitionFile.fileName, @@ -669,7 +707,11 @@ interface ProjectAndLocation { readonly location: DocumentPosition; } -function forEachProjectInProjects(projects: Projects, path: string | undefined, cb: (project: Project, path: string | undefined) => void): void { +function forEachProjectInProjects( + projects: Projects, + path: string | undefined, + cb: (project: Project, path: string | undefined) => void, +): void { for (const project of isArray(projects) ? projects : projects.projects) { cb(project, path); } @@ -723,14 +765,14 @@ function getPerProjectReferences( // Don't call these unless !!defaultDefinition const getGeneratedDefinition = memoize(() => - defaultProject.isSourceOfProjectReferenceRedirect(defaultDefinition!.fileName) ? - defaultDefinition : - defaultProject.getLanguageService().getSourceMapper().tryGetGeneratedPosition(defaultDefinition!) + defaultProject.isSourceOfProjectReferenceRedirect(defaultDefinition!.fileName) + ? defaultDefinition + : defaultProject.getLanguageService().getSourceMapper().tryGetGeneratedPosition(defaultDefinition!) ); const getSourceDefinition = memoize(() => - defaultProject.isSourceOfProjectReferenceRedirect(defaultDefinition!.fileName) ? - defaultDefinition : - defaultProject.getLanguageService().getSourceMapper().tryGetSourcePosition(defaultDefinition!) + defaultProject.isSourceOfProjectReferenceRedirect(defaultDefinition!.fileName) + ? defaultDefinition + : defaultProject.getLanguageService().getSourceMapper().tryGetSourcePosition(defaultDefinition!) ); // The keys of resultsMap allow us to check which projects have already been searched, but we also @@ -768,7 +810,12 @@ function getPerProjectReferences( projectService.forEachEnabledProject(project => { if (cancellationToken.isCancellationRequested()) return; // There's no mechanism for skipping the remaining projects if (resultsMap.has(project)) return; // Can loop forever without this (enqueue here, dequeue above, repeat) - const location = mapDefinitionInProject(defaultDefinition, project, getGeneratedDefinition, getSourceDefinition); + const location = mapDefinitionInProject( + defaultDefinition, + project, + getGeneratedDefinition, + getSourceDefinition, + ); if (location) { queue.enqueue({ project, location }); } @@ -807,7 +854,10 @@ function getPerProjectReferences( symlinkedProjectsMap.forEach((symlinkedProjects, symlinkedPath) => { for (const symlinkedProject of symlinkedProjects) { if (!symlinkedProject.isOrphan() && !resultsMap.has(symlinkedProject)) { // Optimization: don't enqueue if will be discarded - queue.enqueue({ project: symlinkedProject, location: { fileName: symlinkedPath as string, pos: originalLocation.pos } }); + queue.enqueue({ + project: symlinkedProject, + location: { fileName: symlinkedPath as string, pos: originalLocation.pos }, + }); } } }); @@ -827,15 +877,18 @@ function mapDefinitionInProject( ): DocumentPosition | undefined { // If the definition is actually from the project, definition is correct as is if ( - project.containsFile(toNormalizedPath(definition.fileName)) && - !isLocationProjectReferenceRedirect(project, definition) + project.containsFile(toNormalizedPath(definition.fileName)) + && !isLocationProjectReferenceRedirect(project, definition) ) { return definition; } const generatedDefinition = getGeneratedDefinition(); - if (generatedDefinition && project.containsFile(toNormalizedPath(generatedDefinition.fileName))) return generatedDefinition; + if (generatedDefinition && project.containsFile(toNormalizedPath(generatedDefinition.fileName))) { + return generatedDefinition; + } const sourceDefinition = getSourceDefinition(); - return sourceDefinition && project.containsFile(toNormalizedPath(sourceDefinition.fileName)) ? sourceDefinition : undefined; + return sourceDefinition && project.containsFile(toNormalizedPath(sourceDefinition.fileName)) ? sourceDefinition + : undefined; } function isLocationProjectReferenceRedirect(project: Project, location: DocumentPosition | undefined) { @@ -849,9 +902,9 @@ function isLocationProjectReferenceRedirect(project: Project, location: Document // This happens when rootFile in project is one of the file from referenced project // Thus root is attached but program doesnt have the actual .ts file but .d.ts // If this is not the file we were actually looking, return rest of the toDo - return !!sourceFile && - sourceFile.resolvedPath !== sourceFile.path && - sourceFile.resolvedPath !== project.toPath(location.fileName); + return !!sourceFile + && sourceFile.resolvedPath !== sourceFile.path + && sourceFile.resolvedPath !== project.toPath(location.fileName); } function getProjectKey(project: Project) { @@ -863,15 +916,27 @@ function documentSpanLocation({ fileName, textSpan }: DocumentSpan): DocumentPos } function getMappedLocationForProject(location: DocumentPosition, project: Project): DocumentPosition | undefined { - return getMappedLocation(location, project.getSourceMapper(), p => project.projectService.fileExists(p as NormalizedPath)); + return getMappedLocation( + location, + project.getSourceMapper(), + p => project.projectService.fileExists(p as NormalizedPath), + ); } function getMappedDocumentSpanForProject(documentSpan: DocumentSpan, project: Project): DocumentSpan | undefined { - return getMappedDocumentSpan(documentSpan, project.getSourceMapper(), p => project.projectService.fileExists(p as NormalizedPath)); + return getMappedDocumentSpan( + documentSpan, + project.getSourceMapper(), + p => project.projectService.fileExists(p as NormalizedPath), + ); } function getMappedContextSpanForProject(documentSpan: DocumentSpan, project: Project): TextSpan | undefined { - return getMappedContextSpan(documentSpan, project.getSourceMapper(), p => project.projectService.fileExists(p as NormalizedPath)); + return getMappedContextSpan( + documentSpan, + project.getSourceMapper(), + p => project.projectService.fileExists(p as NormalizedPath), + ); } const invalidPartialSemanticModeCommands: readonly protocol.CommandTypes[] = [ @@ -1040,7 +1105,9 @@ export class Session implements EventSender { case LanguageServiceMode.PartialSemantic: invalidPartialSemanticModeCommands.forEach(commandName => this.handlers.set(commandName, request => { - throw new Error(`Request: ${request.command} not allowed in LanguageServiceMode.PartialSemantic`); + throw new Error( + `Request: ${request.command} not allowed in LanguageServiceMode.PartialSemantic`, + ); }) ); break; @@ -1093,15 +1160,24 @@ export class Session implements EventSender { break; case ProjectLoadingFinishEvent: const { project: finishProject } = event.data; - this.event({ projectName: finishProject.getProjectName() }, ProjectLoadingFinishEvent); + this.event( + { projectName: finishProject.getProjectName() }, + ProjectLoadingFinishEvent, + ); break; case LargeFileReferencedEvent: const { file, fileSize, maxFileSize } = event.data; - this.event({ file, fileSize, maxFileSize }, LargeFileReferencedEvent); + this.event( + { file, fileSize, maxFileSize }, + LargeFileReferencedEvent, + ); break; case ConfigFileDiagEvent: const { triggerFile, configFileName: configFile, diagnostics } = event.data; - const bakedDiags = map(diagnostics, diagnostic => formatDiagnosticToProtocol(diagnostic, /*includeFileName*/ true)); + const bakedDiags = map( + diagnostics, + diagnostic => formatDiagnosticToProtocol(diagnostic, /*includeFileName*/ true), + ); this.event({ triggerFile, configFile, @@ -1146,7 +1222,11 @@ export class Session implements EventSender { this.logErrorWorker(err, cmd); } - private logErrorWorker(err: Error & PossibleProgramFileInfo, cmd: string, fileRequest?: protocol.FileRequestArgs): void { + private logErrorWorker( + err: Error & PossibleProgramFileInfo, + cmd: string, + fileRequest?: protocol.FileRequestArgs, + ): void { let msg = "Exception on executing command " + cmd; if (err.message) { msg += ":\n" + indent(err.message); @@ -1250,7 +1330,10 @@ export class Session implements EventSender { } private semanticCheck(file: NormalizedPath, project: Project) { - tracing?.push(tracing.Phase.Session, "semanticCheck", { file, configFilePath: (project as ConfiguredProject).canonicalConfigFilePath }); // undefined is fine if the cast fails + tracing?.push(tracing.Phase.Session, "semanticCheck", { + file, + configFilePath: (project as ConfiguredProject).canonicalConfigFilePath, + }); // undefined is fine if the cast fails const diags = isDeclarationFileInJSOnlyNonConfiguredProject(project, file) ? emptyArray : project.getLanguageService().getSemanticDiagnostics(file).filter(d => !!d.file); @@ -1259,20 +1342,44 @@ export class Session implements EventSender { } private syntacticCheck(file: NormalizedPath, project: Project) { - tracing?.push(tracing.Phase.Session, "syntacticCheck", { file, configFilePath: (project as ConfiguredProject).canonicalConfigFilePath }); // undefined is fine if the cast fails - this.sendDiagnosticsEvent(file, project, project.getLanguageService().getSyntacticDiagnostics(file), "syntaxDiag"); + tracing?.push(tracing.Phase.Session, "syntacticCheck", { + file, + configFilePath: (project as ConfiguredProject).canonicalConfigFilePath, + }); // undefined is fine if the cast fails + this.sendDiagnosticsEvent( + file, + project, + project.getLanguageService().getSyntacticDiagnostics(file), + "syntaxDiag", + ); tracing?.pop(); } private suggestionCheck(file: NormalizedPath, project: Project) { - tracing?.push(tracing.Phase.Session, "suggestionCheck", { file, configFilePath: (project as ConfiguredProject).canonicalConfigFilePath }); // undefined is fine if the cast fails - this.sendDiagnosticsEvent(file, project, project.getLanguageService().getSuggestionDiagnostics(file), "suggestionDiag"); + tracing?.push(tracing.Phase.Session, "suggestionCheck", { + file, + configFilePath: (project as ConfiguredProject).canonicalConfigFilePath, + }); // undefined is fine if the cast fails + this.sendDiagnosticsEvent( + file, + project, + project.getLanguageService().getSuggestionDiagnostics(file), + "suggestionDiag", + ); tracing?.pop(); } - private sendDiagnosticsEvent(file: NormalizedPath, project: Project, diagnostics: readonly Diagnostic[], kind: protocol.DiagnosticEventKind): void { + private sendDiagnosticsEvent( + file: NormalizedPath, + project: Project, + diagnostics: readonly Diagnostic[], + kind: protocol.DiagnosticEventKind, + ): void { try { - this.event({ file, diagnostics: diagnostics.map(diag => formatDiag(file, project, diag)) }, kind); + this.event({ + file, + diagnostics: diagnostics.map(diag => formatDiag(file, project, diag)), + }, kind); } catch (err) { this.logError(err, kind); @@ -1280,7 +1387,12 @@ export class Session implements EventSender { } /** It is the caller's responsibility to verify that `!this.suppressDiagnosticEvents`. */ - private updateErrorCheck(next: NextStep, checkList: readonly string[] | readonly PendingErrorCheck[], ms: number, requireOpen = true) { + private updateErrorCheck( + next: NextStep, + checkList: readonly string[] | readonly PendingErrorCheck[], + ms: number, + requireOpen = true, + ) { Debug.assert(!this.suppressDiagnosticEvents); // Caller's responsibility const seq = this.changeSeq; @@ -1377,7 +1489,8 @@ export class Session implements EventSender { private getEncodedSemanticClassifications(args: protocol.EncodedSemanticClassificationsRequestArgs) { const { file, project } = this.getFileAndProject(args); - const format = args.format === "2020" ? SemanticClassificationFormat.TwentyTwenty : SemanticClassificationFormat.Original; + const format = args.format === "2020" ? SemanticClassificationFormat.TwentyTwenty + : SemanticClassificationFormat.Original; return project.getLanguageService().getEncodedSemanticClassifications(file, args, format); } @@ -1385,7 +1498,9 @@ export class Session implements EventSender { return projectFileName === undefined ? undefined : this.projectService.findProject(projectFileName); } - private getConfigFileAndProject(args: protocol.FileRequestArgs): { configFile: NormalizedPath | undefined; project: Project | undefined; } { + private getConfigFileAndProject( + args: protocol.FileRequestArgs, + ): { configFile: NormalizedPath | undefined; project: Project | undefined; } { const project = this.getProject(args.projectFileName); const file = toNormalizedPath(args.file); @@ -1402,15 +1517,17 @@ export class Session implements EventSender { concatenate(projectErrors, optionsErrors), diagnostic => !!diagnostic.file && diagnostic.file.fileName === configFile, ); - return includeLinePosition ? - this.convertToDiagnosticsWithLinePositionFromDiagnosticFile(diagnosticsForConfigFile) : - map( + return includeLinePosition + ? this.convertToDiagnosticsWithLinePositionFromDiagnosticFile(diagnosticsForConfigFile) + : map( diagnosticsForConfigFile, diagnostic => formatDiagnosticToProtocol(diagnostic, /*includeFileName*/ false), ); } - private convertToDiagnosticsWithLinePositionFromDiagnosticFile(diagnostics: readonly Diagnostic[]): protocol.DiagnosticWithLinePosition[] { + private convertToDiagnosticsWithLinePositionFromDiagnosticFile( + diagnostics: readonly Diagnostic[], + ): protocol.DiagnosticWithLinePosition[] { return diagnostics.map(d => ({ message: flattenDiagnosticMessageText(d.messageText, this.host.newLine), start: d.start!, // TODO: GH#18217 @@ -1440,7 +1557,10 @@ export class Session implements EventSender { ); } - private convertToDiagnosticsWithLinePosition(diagnostics: readonly Diagnostic[], scriptInfo: ScriptInfo | undefined): protocol.DiagnosticWithLinePosition[] { + private convertToDiagnosticsWithLinePosition( + diagnostics: readonly Diagnostic[], + scriptInfo: ScriptInfo | undefined, + ): protocol.DiagnosticWithLinePosition[] { return diagnostics.map(d => ({ message: flattenDiagnosticMessageText(d.messageText, this.host.newLine), @@ -1475,14 +1595,24 @@ export class Session implements EventSender { : diagnostics.map(d => formatDiag(file, project, d)); } - private getDefinition(args: protocol.FileLocationRequestArgs, simplifiedResult: boolean): readonly protocol.FileSpanWithContext[] | readonly DefinitionInfo[] { + private getDefinition( + args: protocol.FileLocationRequestArgs, + simplifiedResult: boolean, + ): readonly protocol.FileSpanWithContext[] | readonly DefinitionInfo[] { const { file, project } = this.getFileAndProject(args); const position = this.getPositionInFile(args, file); - const definitions = this.mapDefinitionInfoLocations(project.getLanguageService().getDefinitionAtPosition(file, position) || emptyArray, project); - return simplifiedResult ? this.mapDefinitionInfo(definitions, project) : definitions.map(Session.mapToOriginalLocation); + const definitions = this.mapDefinitionInfoLocations( + project.getLanguageService().getDefinitionAtPosition(file, position) || emptyArray, + project, + ); + return simplifiedResult ? this.mapDefinitionInfo(definitions, project) + : definitions.map(Session.mapToOriginalLocation); } - private mapDefinitionInfoLocations(definitions: readonly DefinitionInfo[], project: Project): readonly DefinitionInfo[] { + private mapDefinitionInfoLocations( + definitions: readonly DefinitionInfo[], + project: Project, + ): readonly DefinitionInfo[] { return definitions.map((info): DefinitionInfo => { const newDocumentSpan = getMappedDocumentSpanForProject(info, project); return !newDocumentSpan ? info : { @@ -1497,7 +1627,10 @@ export class Session implements EventSender { }); } - private getDefinitionAndBoundSpan(args: protocol.FileLocationRequestArgs, simplifiedResult: boolean): protocol.DefinitionInfoAndBoundSpan | DefinitionInfoAndBoundSpan { + private getDefinitionAndBoundSpan( + args: protocol.FileLocationRequestArgs, + simplifiedResult: boolean, + ): protocol.DefinitionInfoAndBoundSpan | DefinitionInfoAndBoundSpan { const { file, project } = this.getFileAndProject(args); const position = this.getPositionInFile(args, file); const scriptInfo = Debug.checkDefined(project.getScriptInfo(file)); @@ -1531,10 +1664,13 @@ export class Session implements EventSender { const { file, project } = this.getFileAndProject(args); const position = this.getPositionInFile(args, file); const unmappedDefinitions = project.getLanguageService().getDefinitionAtPosition(file, position); - let definitions: readonly DefinitionInfo[] = this.mapDefinitionInfoLocations(unmappedDefinitions || emptyArray, project).slice(); + let definitions: readonly DefinitionInfo[] = this.mapDefinitionInfoLocations( + unmappedDefinitions || emptyArray, + project, + ).slice(); const needsJsResolution = this.projectService.serverMode === LanguageServiceMode.Semantic && ( - !some(definitions, d => toNormalizedPath(d.fileName) !== file && !d.isAmbient) || - some(definitions, d => !!d.failedAliasResolution) + !some(definitions, d => toNormalizedPath(d.fileName) !== file && !d.isAmbient) + || some(definitions, d => !!d.failedAliasResolution) ); if (needsJsResolution) { @@ -1542,12 +1678,21 @@ export class Session implements EventSender { definitions?.forEach(d => definitionSet.add(d)); const noDtsProject = project.getNoDtsResolutionProject([file]); const ls = noDtsProject.getLanguageService(); - const jsDefinitions = ls.getDefinitionAtPosition(file, position, /*searchOtherFilesOnly*/ true, /*stopAtAlias*/ false) + const jsDefinitions = ls.getDefinitionAtPosition( + file, + position, + /*searchOtherFilesOnly*/ true, + /*stopAtAlias*/ false, + ) ?.filter(d => toNormalizedPath(d.fileName) !== file); if (some(jsDefinitions)) { for (const jsDefinition of jsDefinitions) { if (jsDefinition.unverified) { - const refined = tryRefineDefinition(jsDefinition, project.getLanguageService().getProgram()!, ls.getProgram()!); + const refined = tryRefineDefinition( + jsDefinition, + project.getLanguageService().getProgram()!, + ls.getProgram()!, + ); if (some(refined)) { for (const def of refined) { definitionSet.add(def); @@ -1560,8 +1705,15 @@ export class Session implements EventSender { } else { const ambientCandidates = definitions.filter(d => toNormalizedPath(d.fileName) !== file && d.isAmbient); - for (const candidate of some(ambientCandidates) ? ambientCandidates : getAmbientCandidatesByClimbingAccessChain()) { - const fileNameToSearch = findImplementationFileFromDtsFileName(candidate.fileName, file, noDtsProject); + for ( + const candidate of some(ambientCandidates) ? ambientCandidates + : getAmbientCandidatesByClimbingAccessChain() + ) { + const fileNameToSearch = findImplementationFileFromDtsFileName( + candidate.fileName, + file, + noDtsProject, + ); if (!fileNameToSearch || !ensureRoot(noDtsProject, fileNameToSearch)) { continue; } @@ -1578,14 +1730,24 @@ export class Session implements EventSender { definitions = definitions.filter(d => !d.isAmbient && !d.failedAliasResolution); return this.mapDefinitionInfo(definitions, project); - function findImplementationFileFromDtsFileName(fileName: string, resolveFromFile: string, auxiliaryProject: Project) { + function findImplementationFileFromDtsFileName( + fileName: string, + resolveFromFile: string, + auxiliaryProject: Project, + ) { const nodeModulesPathParts = getNodeModulePathParts(fileName); - if (nodeModulesPathParts && fileName.lastIndexOf(nodeModulesPathPart) === nodeModulesPathParts.topLevelNodeModulesIndex) { + if ( + nodeModulesPathParts + && fileName.lastIndexOf(nodeModulesPathPart) === nodeModulesPathParts.topLevelNodeModulesIndex + ) { // Second check ensures the fileName only contains one `/node_modules/`. If there's more than one I give up. const packageDirectory = fileName.substring(0, nodeModulesPathParts.packageRootIndex); const packageJsonCache = project.getModuleResolutionCache()?.getPackageJsonInfoCache(); const compilerOptions = project.getCompilationSettings(); - const packageJson = getPackageScopeForPath(getNormalizedAbsolutePath(packageDirectory + "/package.json", project.getCurrentDirectory()), getTemporaryModuleResolutionState(packageJsonCache, project, compilerOptions)); + const packageJson = getPackageScopeForPath( + getNormalizedAbsolutePath(packageDirectory + "/package.json", project.getCurrentDirectory()), + getTemporaryModuleResolutionState(packageJsonCache, project, compilerOptions), + ); if (!packageJson) return undefined; // Use fake options instead of actual compiler options to avoid following export map if the project uses node16 or nodenext - // Mapping from an export map entry across packages is out of scope for now. Returned entrypoints will only be what can be @@ -1606,13 +1768,19 @@ export class Session implements EventSender { if (entrypoints && some(entrypoints, e => project.toPath(e) === path)) { // This file was the main entrypoint of a package. Try to resolve that same package name with // the auxiliary project that only resolves to implementation files. - return auxiliaryProject.resolutionCache.resolveSingleModuleNameWithoutWatching(packageName, resolveFromFile).resolvedModule?.resolvedFileName; + return auxiliaryProject.resolutionCache.resolveSingleModuleNameWithoutWatching( + packageName, + resolveFromFile, + ).resolvedModule?.resolvedFileName; } else { // It wasn't the main entrypoint but we are in node_modules. Try a subpath into the package. const pathToFileInPackage = fileName.substring(nodeModulesPathParts.packageRootIndex + 1); const specifier = `${packageName}/${removeFileExtension(pathToFileInPackage)}`; - return auxiliaryProject.resolutionCache.resolveSingleModuleNameWithoutWatching(specifier, resolveFromFile).resolvedModule?.resolvedFileName; + return auxiliaryProject.resolutionCache.resolveSingleModuleNameWithoutWatching( + specifier, + resolveFromFile, + ).resolvedModule?.resolvedFileName; } } // We're not in node_modules, and we only get to this function if non-dts module resolution failed. @@ -1626,10 +1794,18 @@ export class Session implements EventSender { const ls = project.getLanguageService(); const program = ls.getProgram()!; const initialNode = getTouchingPropertyName(program.getSourceFile(file)!, position); - if ((isStringLiteralLike(initialNode) || isIdentifier(initialNode)) && isAccessExpression(initialNode.parent)) { + if ( + (isStringLiteralLike(initialNode) || isIdentifier(initialNode)) + && isAccessExpression(initialNode.parent) + ) { return forEachNameInAccessChainWalkingLeft(initialNode, nameInChain => { if (nameInChain === initialNode) return undefined; - const candidates = ls.getDefinitionAtPosition(file, nameInChain.getStart(), /*searchOtherFilesOnly*/ true, /*stopAtAlias*/ false) + const candidates = ls.getDefinitionAtPosition( + file, + nameInChain.getStart(), + /*searchOtherFilesOnly*/ true, + /*stopAtAlias*/ false, + ) ?.filter(d => toNormalizedPath(d.fileName) !== file && d.isAmbient) .map(d => ({ fileName: d.fileName, @@ -1665,7 +1841,13 @@ export class Session implements EventSender { if (symbol && decl) { // I think the last argument to this is supposed to be the start node, but it doesn't seem important. // Callers internal to GoToDefinition already get confused about this. - return GoToDefinition.createDefinitionInfo(decl, noDtsProgram.getTypeChecker(), symbol, decl, /*unverified*/ true); + return GoToDefinition.createDefinitionInfo( + decl, + noDtsProgram.getTypeChecker(), + symbol, + decl, + /*unverified*/ true, + ); } }); } @@ -1687,17 +1869,21 @@ export class Session implements EventSender { return { emitSkipped: true, outputFiles: [], diagnostics: [] }; } const result = project.getLanguageService().getEmitOutput(file); - return args.richResponse ? - { + return args.richResponse + ? { ...result, - diagnostics: args.includeLinePosition ? - this.convertToDiagnosticsWithLinePositionFromDiagnosticFile(result.diagnostics) : - result.diagnostics.map(d => formatDiagnosticToProtocol(d, /*includeFileName*/ true)), - } : - result; + diagnostics: args.includeLinePosition + ? this.convertToDiagnosticsWithLinePositionFromDiagnosticFile(result.diagnostics) + : result.diagnostics.map(d => formatDiagnosticToProtocol(d, /*includeFileName*/ true)), + } + : result; } - private mapJSDocTagInfo(tags: JSDocTagInfo[] | undefined, project: Project, richResponse: boolean): protocol.JSDocTagInfo[] { + private mapJSDocTagInfo( + tags: JSDocTagInfo[] | undefined, + project: Project, + richResponse: boolean, + ): protocol.JSDocTagInfo[] { return tags ? tags.map(tag => ({ ...tag, text: richResponse ? this.mapDisplayParts(tag.text, project) : tag.text?.map(part => part.text).join(""), @@ -1711,22 +1897,39 @@ export class Session implements EventSender { return parts.map(part => part.kind !== "linkName" ? part : { ...part, - target: this.toFileSpan((part as JSDocLinkDisplayPart).target.fileName, (part as JSDocLinkDisplayPart).target.textSpan, project), + target: this.toFileSpan( + (part as JSDocLinkDisplayPart).target.fileName, + (part as JSDocLinkDisplayPart).target.textSpan, + project, + ), } ); } - private mapSignatureHelpItems(items: SignatureHelpItem[], project: Project, richResponse: boolean): protocol.SignatureHelpItem[] { + private mapSignatureHelpItems( + items: SignatureHelpItem[], + project: Project, + richResponse: boolean, + ): protocol.SignatureHelpItem[] { return items.map(item => ({ ...item, documentation: this.mapDisplayParts(item.documentation, project), - parameters: item.parameters.map(p => ({ ...p, documentation: this.mapDisplayParts(p.documentation, project) })), + parameters: item.parameters.map(p => ({ + ...p, + documentation: this.mapDisplayParts(p.documentation, project), + })), tags: this.mapJSDocTagInfo(item.tags, project, richResponse), })); } - private mapDefinitionInfo(definitions: readonly DefinitionInfo[], project: Project): readonly protocol.DefinitionInfo[] { - return definitions.map(def => ({ ...this.toFileSpanWithContext(def.fileName, def.textSpan, def.contextSpan, project), ...def.unverified && { unverified: def.unverified } })); + private mapDefinitionInfo( + definitions: readonly DefinitionInfo[], + project: Project, + ): readonly protocol.DefinitionInfo[] { + return definitions.map(def => ({ + ...this.toFileSpanWithContext(def.fileName, def.textSpan, def.contextSpan, project), + ...def.unverified && { unverified: def.unverified }, + })); } /* @@ -1738,7 +1941,10 @@ export class Session implements EventSender { */ private static mapToOriginalLocation(def: T): T { if (def.originalFileName) { - Debug.assert(def.originalTextSpan !== undefined, "originalTextSpan should be present if originalFileName is"); + Debug.assert( + def.originalTextSpan !== undefined, + "originalTextSpan should be present if originalFileName is", + ); return { ...def as any, fileName: def.originalFileName, @@ -1764,23 +1970,34 @@ export class Session implements EventSender { }; } - private toFileSpanWithContext(fileName: string, textSpan: TextSpan, contextSpan: TextSpan | undefined, project: Project): protocol.FileSpanWithContext { + private toFileSpanWithContext( + fileName: string, + textSpan: TextSpan, + contextSpan: TextSpan | undefined, + project: Project, + ): protocol.FileSpanWithContext { const fileSpan = this.toFileSpan(fileName, textSpan, project); const context = contextSpan && this.toFileSpan(fileName, contextSpan, project); - return context ? - { ...fileSpan, contextStart: context.start, contextEnd: context.end } : - fileSpan; + return context + ? { ...fileSpan, contextStart: context.start, contextEnd: context.end } + : fileSpan; } private getTypeDefinition(args: protocol.FileLocationRequestArgs): readonly protocol.FileSpanWithContext[] { const { file, project } = this.getFileAndProject(args); const position = this.getPositionInFile(args, file); - const definitions = this.mapDefinitionInfoLocations(project.getLanguageService().getTypeDefinitionAtPosition(file, position) || emptyArray, project); + const definitions = this.mapDefinitionInfoLocations( + project.getLanguageService().getTypeDefinitionAtPosition(file, position) || emptyArray, + project, + ); return this.mapDefinitionInfo(definitions, project); } - private mapImplementationLocations(implementations: readonly ImplementationLocation[], project: Project): readonly ImplementationLocation[] { + private mapImplementationLocations( + implementations: readonly ImplementationLocation[], + project: Project, + ): readonly ImplementationLocation[] { return implementations.map((info): ImplementationLocation => { const newDocumentSpan = getMappedDocumentSpanForProject(info, project); return !newDocumentSpan ? info : { @@ -1791,13 +2008,21 @@ export class Session implements EventSender { }); } - private getImplementation(args: protocol.FileLocationRequestArgs, simplifiedResult: boolean): readonly protocol.FileSpanWithContext[] | readonly ImplementationLocation[] { + private getImplementation( + args: protocol.FileLocationRequestArgs, + simplifiedResult: boolean, + ): readonly protocol.FileSpanWithContext[] | readonly ImplementationLocation[] { const { file, project } = this.getFileAndProject(args); const position = this.getPositionInFile(args, file); - const implementations = this.mapImplementationLocations(project.getLanguageService().getImplementationAtPosition(file, position) || emptyArray, project); - return simplifiedResult ? - implementations.map(({ fileName, textSpan, contextSpan }) => this.toFileSpanWithContext(fileName, textSpan, contextSpan, project)) : - implementations.map(Session.mapToOriginalLocation); + const implementations = this.mapImplementationLocations( + project.getLanguageService().getImplementationAtPosition(file, position) || emptyArray, + project, + ); + return simplifiedResult + ? implementations.map(({ fileName, textSpan, contextSpan }) => + this.toFileSpanWithContext(fileName, textSpan, contextSpan, project) + ) + : implementations.map(Session.mapToOriginalLocation); } private getSyntacticDiagnosticsSync(args: protocol.SyntacticDiagnosticsSyncRequestArgs) { @@ -1807,7 +2032,12 @@ export class Session implements EventSender { return emptyArray; } - return this.getDiagnosticsWorker(args, /*isSemantic*/ false, (project, file) => project.getLanguageService().getSyntacticDiagnostics(file), !!args.includeLinePosition); + return this.getDiagnosticsWorker( + args, + /*isSemantic*/ false, + (project, file) => project.getLanguageService().getSyntacticDiagnostics(file), + !!args.includeLinePosition, + ); } private getSemanticDiagnosticsSync(args: protocol.SemanticDiagnosticsSyncRequestArgs) { @@ -1815,7 +2045,12 @@ export class Session implements EventSender { if (configFile) { return this.getConfigFileDiagnostics(configFile, project!, !!args.includeLinePosition); // TODO: GH#18217 } - return this.getDiagnosticsWorker(args, /*isSemantic*/ true, (project, file) => project.getLanguageService().getSemanticDiagnostics(file).filter(d => !!d.file), !!args.includeLinePosition); + return this.getDiagnosticsWorker( + args, + /*isSemantic*/ true, + (project, file) => project.getLanguageService().getSemanticDiagnostics(file).filter(d => !!d.file), + !!args.includeLinePosition, + ); } private getSuggestionDiagnosticsSync(args: protocol.SuggestionDiagnosticsSyncRequestArgs) { @@ -1825,7 +2060,12 @@ export class Session implements EventSender { return emptyArray; } // isSemantic because we don't want to info diagnostics in declaration files for JS-only users - return this.getDiagnosticsWorker(args, /*isSemantic*/ true, (project, file) => project.getLanguageService().getSuggestionDiagnostics(file), !!args.includeLinePosition); + return this.getDiagnosticsWorker( + args, + /*isSemantic*/ true, + (project, file) => project.getLanguageService().getSuggestionDiagnostics(file), + !!args.includeLinePosition, + ); } private getJsxClosingTag(args: protocol.JsxClosingTagRequestArgs): TextInsertion | undefined { @@ -1835,7 +2075,9 @@ export class Session implements EventSender { return tag === undefined ? undefined : { newText: tag.newText, caretOffset: 0 }; } - private getLinkedEditingRange(args: protocol.FileLocationRequestArgs): protocol.LinkedEditingRangesBody | undefined { + private getLinkedEditingRange( + args: protocol.FileLocationRequestArgs, + ): protocol.LinkedEditingRangesBody | undefined { const { file, languageService } = this.getFileAndLanguageServiceForSyntacticOperation(args); const position = this.getPositionInFile(args, file); const linkedEditInfo = languageService.getLinkedEditingRangeAtPosition(file, position); @@ -1844,10 +2086,17 @@ export class Session implements EventSender { return convertLinkedEditInfoToRanges(linkedEditInfo, scriptInfo); } - private getDocumentHighlights(args: protocol.DocumentHighlightsRequestArgs, simplifiedResult: boolean): readonly protocol.DocumentHighlightsItem[] | readonly DocumentHighlights[] { + private getDocumentHighlights( + args: protocol.DocumentHighlightsRequestArgs, + simplifiedResult: boolean, + ): readonly protocol.DocumentHighlightsItem[] | readonly DocumentHighlights[] { const { file, project } = this.getFileAndProject(args); const position = this.getPositionInFile(args, file); - const documentHighlights = project.getLanguageService().getDocumentHighlights(file, position, args.filesToSearch); + const documentHighlights = project.getLanguageService().getDocumentHighlights( + file, + position, + args.filesToSearch, + ); if (!documentHighlights) return emptyArray; if (!simplifiedResult) return documentHighlights; @@ -1892,16 +2141,27 @@ export class Session implements EventSender { } private getProjectInfo(args: protocol.ProjectInfoRequestArgs): protocol.ProjectInfo { - return this.getProjectInfoWorker(args.file, args.projectFileName, args.needFileNameList, /*excludeConfigFiles*/ false); + return this.getProjectInfoWorker( + args.file, + args.projectFileName, + args.needFileNameList, + /*excludeConfigFiles*/ false, + ); } - private getProjectInfoWorker(uncheckedFileName: string, projectFileName: string | undefined, needFileNameList: boolean, excludeConfigFiles: boolean) { + private getProjectInfoWorker( + uncheckedFileName: string, + projectFileName: string | undefined, + needFileNameList: boolean, + excludeConfigFiles: boolean, + ) { const { project } = this.getFileAndProjectWorker(uncheckedFileName, projectFileName); updateProjectIfDirty(project); const projectInfo = { configFileName: project.getProjectName(), languageServiceDisabled: !project.languageServiceEnabled, - fileNames: needFileNameList ? project.getFileNames(/*excludeFilesFromExternalLibraries*/ false, excludeConfigFiles) : undefined, + fileNames: needFileNameList + ? project.getFileNames(/*excludeFilesFromExternalLibraries*/ false, excludeConfigFiles) : undefined, }; return projectInfo; } @@ -1913,7 +2173,11 @@ export class Session implements EventSender { return project.getLanguageService().getRenameInfo(file, position, preferences); } - private getProjects(args: protocol.FileRequestArgs, getScriptInfoEnsuringProjectsUptoDate?: boolean, ignoreNoProjectError?: boolean): Projects { + private getProjects( + args: protocol.FileRequestArgs, + getScriptInfoEnsuringProjectsUptoDate?: boolean, + ignoreNoProjectError?: boolean, + ): Projects { let projects: readonly Project[] | undefined; let symLinkedProjects: MultiMap | undefined; if (args.projectFileName) { @@ -1923,9 +2187,9 @@ export class Session implements EventSender { } } else { - const scriptInfo = getScriptInfoEnsuringProjectsUptoDate ? - this.projectService.getScriptInfoEnsuringProjectsUptoDate(args.file) : - this.projectService.getScriptInfo(args.file); + const scriptInfo = getScriptInfoEnsuringProjectsUptoDate + ? this.projectService.getScriptInfoEnsuringProjectsUptoDate(args.file) + : this.projectService.getScriptInfo(args.file); if (!scriptInfo) { if (ignoreNoProjectError) return emptyArray; this.projectService.logErrorForScriptInfoNotFound(args.file); @@ -1961,7 +2225,10 @@ export class Session implements EventSender { return info.getDefaultProject(); } - private getRenameLocations(args: protocol.RenameRequestArgs, simplifiedResult: boolean): protocol.RenameResponseBody | readonly RenameLocation[] { + private getRenameLocations( + args: protocol.RenameRequestArgs, + simplifiedResult: boolean, + ): protocol.RenameResponseBody | readonly RenameLocation[] { const file = toNormalizedPath(args.file); const position = this.getPositionInFile(args, file); const projects = this.getProjects(args); @@ -1990,7 +2257,15 @@ export class Session implements EventSender { if (info.canRename) { const { canRename, fileToRename, displayName, fullDisplayName, kind, kindModifiers, triggerSpan } = info; return identity( - { canRename, fileToRename, displayName, fullDisplayName, kind, kindModifiers, triggerSpan: toProtocolTextSpan(triggerSpan, scriptInfo) }, + { + canRename, + fileToRename, + displayName, + fullDisplayName, + kind, + kindModifiers, + triggerSpan: toProtocolTextSpan(triggerSpan, scriptInfo), + }, ); } else { @@ -2000,16 +2275,32 @@ export class Session implements EventSender { private toSpanGroups(locations: readonly RenameLocation[]): readonly protocol.SpanGroup[] { const map = new Map(); - for (const { fileName, textSpan, contextSpan, originalContextSpan: _2, originalTextSpan: _, originalFileName: _1, ...prefixSuffixText } of locations) { + for ( + const { + fileName, + textSpan, + contextSpan, + originalContextSpan: _2, + originalTextSpan: _, + originalFileName: _1, + ...prefixSuffixText + } of locations + ) { let group = map.get(fileName); if (!group) map.set(fileName, group = { file: fileName, locs: [] }); const scriptInfo = Debug.checkDefined(this.projectService.getScriptInfo(fileName)); - group.locs.push({ ...toProtocolTextSpanWithContext(textSpan, contextSpan, scriptInfo), ...prefixSuffixText }); + group.locs.push({ + ...toProtocolTextSpanWithContext(textSpan, contextSpan, scriptInfo), + ...prefixSuffixText, + }); } return arrayFrom(map.values()); } - private getReferences(args: protocol.FileLocationRequestArgs, simplifiedResult: boolean): protocol.ReferencesResponseBody | readonly ReferencedSymbol[] { + private getReferences( + args: protocol.FileLocationRequestArgs, + simplifiedResult: boolean, + ): protocol.ReferencesResponseBody | readonly ReferencedSymbol[] { const file = toNormalizedPath(args.file); const projects = this.getProjects(args); const position = this.getPositionInFile(args, file); @@ -2031,12 +2322,17 @@ export class Session implements EventSender { const symbolStartOffset = nameSpan ? scriptInfo.positionToLineOffset(nameSpan.start).offset : 0; const symbolName = nameSpan ? scriptInfo.getSnapshot().getText(nameSpan.start, textSpanEnd(nameSpan)) : ""; const refs: readonly protocol.ReferencesResponseItem[] = flatMap(references, referencedSymbol => { - return referencedSymbol.references.map(entry => referenceEntryToReferencesResponseItem(this.projectService, entry, preferences)); + return referencedSymbol.references.map(entry => + referenceEntryToReferencesResponseItem(this.projectService, entry, preferences) + ); }); return { refs, symbolName, symbolStartOffset, symbolDisplayString }; } - private getFileReferences(args: protocol.FileRequestArgs, simplifiedResult: boolean): protocol.FileReferencesResponseBody | readonly ReferenceEntry[] { + private getFileReferences( + args: protocol.FileRequestArgs, + simplifiedResult: boolean, + ): protocol.FileReferencesResponseBody | readonly ReferenceEntry[] { const projects = this.getProjects(args); const fileName = args.file; const preferences = this.getPreferences(toNormalizedPath(fileName)); @@ -2059,7 +2355,9 @@ export class Session implements EventSender { }); if (!simplifiedResult) return references; - const refs = references.map(entry => referenceEntryToReferencesResponseItem(this.projectService, entry, preferences)); + const refs = references.map(entry => + referenceEntryToReferencesResponseItem(this.projectService, entry, preferences) + ); return { refs, symbolName: `"${args.file}"`, @@ -2070,8 +2368,19 @@ export class Session implements EventSender { * @param fileName is the name of the file to be opened * @param fileContent is a version of the file content that is known to be more up to date than the one on disk */ - private openClientFile(fileName: NormalizedPath, fileContent?: string, scriptKind?: ScriptKind, projectRootPath?: NormalizedPath) { - this.projectService.openClientFileWithNormalizedPath(fileName, fileContent, scriptKind, /*hasMixedContent*/ false, projectRootPath); + private openClientFile( + fileName: NormalizedPath, + fileContent?: string, + scriptKind?: ScriptKind, + projectRootPath?: NormalizedPath, + ) { + this.projectService.openClientFileWithNormalizedPath( + fileName, + fileContent, + scriptKind, + /*hasMixedContent*/ false, + projectRootPath, + ); } private getPosition(args: protocol.Location & { position?: number; }, scriptInfo: ScriptInfo): number { @@ -2095,13 +2404,19 @@ export class Session implements EventSender { }; } - private getFileAndProjectWorker(uncheckedFileName: string, projectFileName: string | undefined): { file: NormalizedPath; project: Project; } { + private getFileAndProjectWorker( + uncheckedFileName: string, + projectFileName: string | undefined, + ): { file: NormalizedPath; project: Project; } { const file = toNormalizedPath(uncheckedFileName); const project = this.getProject(projectFileName) || this.projectService.ensureDefaultProjectForFile(file); return { file, project }; } - private getOutliningSpans(args: protocol.FileRequestArgs, simplifiedResult: boolean): protocol.OutliningSpan[] | OutliningSpan[] { + private getOutliningSpans( + args: protocol.FileRequestArgs, + simplifiedResult: boolean, + ): protocol.OutliningSpan[] | OutliningSpan[] { const { file, languageService } = this.getFileAndLanguageServiceForSyntacticOperation(args); const spans = languageService.getOutliningSpans(file); if (simplifiedResult) { @@ -2127,7 +2442,12 @@ export class Session implements EventSender { private getDocCommentTemplate(args: protocol.FileLocationRequestArgs) { const { file, languageService } = this.getFileAndLanguageServiceForSyntacticOperation(args); const position = this.getPositionInFile(args, file); - return languageService.getDocCommentTemplateAtPosition(file, position, this.getPreferences(file), this.getFormatOptions(file)); + return languageService.getDocCommentTemplateAtPosition( + file, + position, + this.getPreferences(file), + this.getFormatOptions(file), + ); } private getSpanOfEnclosingComment(args: protocol.SpanOfEnclosingCommentRequestArgs) { @@ -2163,7 +2483,10 @@ export class Session implements EventSender { return languageService.isValidBraceCompletionAtPosition(file, position, args.openingBrace.charCodeAt(0)); } - private getQuickInfoWorker(args: protocol.FileLocationRequestArgs, simplifiedResult: boolean): protocol.QuickInfoResponseBody | QuickInfo | undefined { + private getQuickInfoWorker( + args: protocol.FileLocationRequestArgs, + simplifiedResult: boolean, + ): protocol.QuickInfoResponseBody | QuickInfo | undefined { const { file, project } = this.getFileAndProject(args); const scriptInfo = this.projectService.getScriptInfoForNormalizedPath(file)!; const quickInfo = project.getLanguageService().getQuickInfoAtPosition(file, this.getPosition(args, scriptInfo)); @@ -2180,7 +2503,8 @@ export class Session implements EventSender { start: scriptInfo.positionToLineOffset(quickInfo.textSpan.start), end: scriptInfo.positionToLineOffset(textSpanEnd(quickInfo.textSpan)), displayString, - documentation: useDisplayParts ? this.mapDisplayParts(quickInfo.documentation, project) : displayPartsToString(quickInfo.documentation), + documentation: useDisplayParts ? this.mapDisplayParts(quickInfo.documentation, project) + : displayPartsToString(quickInfo.documentation), tags: this.mapJSDocTagInfo(quickInfo.tags, project, useDisplayParts), }; } @@ -2200,7 +2524,12 @@ export class Session implements EventSender { const endPosition = scriptInfo.lineOffsetToPosition(args.endLine, args.endOffset); // TODO: avoid duplicate code (with formatonkey) - const edits = languageService.getFormattingEditsForRange(file, startPosition, endPosition, this.getFormatOptions(file)); + const edits = languageService.getFormattingEditsForRange( + file, + startPosition, + endPosition, + this.getFormatOptions(file), + ); if (!edits) { return undefined; } @@ -2279,7 +2608,13 @@ export class Session implements EventSender { }); } - private getCompletions(args: protocol.CompletionsRequestArgs, kind: protocol.CommandTypes.CompletionInfo | protocol.CommandTypes.Completions | protocol.CommandTypes.CompletionsFull): WithMetadata | protocol.CompletionInfo | CompletionInfo | undefined { + private getCompletions( + args: protocol.CompletionsRequestArgs, + kind: + | protocol.CommandTypes.CompletionInfo + | protocol.CommandTypes.Completions + | protocol.CommandTypes.CompletionsFull, + ): WithMetadata | protocol.CompletionInfo | CompletionInfo | undefined { const { file, project } = this.getFileAndProject(args); const scriptInfo = this.projectService.getScriptInfoForNormalizedPath(file)!; const position = this.getPosition(args, scriptInfo); @@ -2345,19 +2680,25 @@ export class Session implements EventSender { }); if (kind === protocol.CommandTypes.Completions) { - if (completions.metadata) (entries as WithMetadata).metadata = completions.metadata; + if (completions.metadata) { + (entries as WithMetadata).metadata = completions.metadata; + } return entries; } const res: protocol.CompletionInfo = { ...completions, - optionalReplacementSpan: completions.optionalReplacementSpan && toProtocolTextSpan(completions.optionalReplacementSpan, scriptInfo), + optionalReplacementSpan: completions.optionalReplacementSpan + && toProtocolTextSpan(completions.optionalReplacementSpan, scriptInfo), entries, }; return res; } - private getCompletionEntryDetails(args: protocol.CompletionDetailsRequestArgs, fullResult: boolean): readonly protocol.CompletionEntryDetails[] | readonly CompletionEntryDetails[] { + private getCompletionEntryDetails( + args: protocol.CompletionDetailsRequestArgs, + fullResult: boolean, + ): readonly protocol.CompletionEntryDetails[] | readonly CompletionEntryDetails[] { const { file, project } = this.getFileAndProject(args); const scriptInfo = this.projectService.getScriptInfoForNormalizedPath(file)!; const position = this.getPosition(args, scriptInfo); @@ -2365,11 +2706,24 @@ export class Session implements EventSender { const useDisplayParts = !!this.getPreferences(file).displayPartsForJSDoc; const result = mapDefined(args.entryNames, entryName => { - const { name, source, data } = typeof entryName === "string" ? { name: entryName, source: undefined, data: undefined } : entryName; - return project.getLanguageService().getCompletionEntryDetails(file, position, name, formattingOptions, source, this.getPreferences(file), data ? cast(data, isCompletionEntryData) : undefined); + const { name, source, data } = typeof entryName === "string" + ? { name: entryName, source: undefined, data: undefined } : entryName; + return project.getLanguageService().getCompletionEntryDetails( + file, + position, + name, + formattingOptions, + source, + this.getPreferences(file), + data ? cast(data, isCompletionEntryData) : undefined, + ); }); return fullResult - ? (useDisplayParts ? result : result.map(details => ({ ...details, tags: this.mapJSDocTagInfo(details.tags, project, /*richResponse*/ false) as JSDocTagInfo[] }))) + ? (useDisplayParts ? result + : result.map(details => ({ + ...details, + tags: this.mapJSDocTagInfo(details.tags, project, /*richResponse*/ false) as JSDocTagInfo[], + }))) : result.map(details => ({ ...details, codeActions: map(details.codeActions, action => this.mapCodeAction(action)), @@ -2378,8 +2732,14 @@ export class Session implements EventSender { })); } - private getCompileOnSaveAffectedFileList(args: protocol.FileRequestArgs): readonly protocol.CompileOnSaveAffectedFileListSingleProject[] { - const projects = this.getProjects(args, /*getScriptInfoEnsuringProjectsUptoDate*/ true, /*ignoreNoProjectError*/ true); + private getCompileOnSaveAffectedFileList( + args: protocol.FileRequestArgs, + ): readonly protocol.CompileOnSaveAffectedFileListSingleProject[] { + const projects = this.getProjects( + args, + /*getScriptInfoEnsuringProjectsUptoDate*/ true, + /*ignoreNoProjectError*/ true, + ); const info = this.projectService.getScriptInfo(args.file); if (!info) { return emptyArray; @@ -2396,7 +2756,10 @@ export class Session implements EventSender { const compilationSettings = project.getCompilationSettings(); - if (!!compilationSettings.noEmit || isDeclarationFileName(info.fileName) && !dtsChangeCanAffectEmit(compilationSettings)) { + if ( + !!compilationSettings.noEmit + || isDeclarationFileName(info.fileName) && !dtsChangeCanAffectEmit(compilationSettings) + ) { // avoid triggering emit when a change is made in a .d.ts when declaration emit and decorator metadata emit are disabled return undefined; } @@ -2419,18 +2782,24 @@ export class Session implements EventSender { return args.richResponse ? { emitSkipped: true, diagnostics: [] } : false; } const scriptInfo = project.getScriptInfo(file)!; - const { emitSkipped, diagnostics } = project.emitFile(scriptInfo, (path, data, writeByteOrderMark) => this.host.writeFile(path, data, writeByteOrderMark)); - return args.richResponse ? - { + const { emitSkipped, diagnostics } = project.emitFile( + scriptInfo, + (path, data, writeByteOrderMark) => this.host.writeFile(path, data, writeByteOrderMark), + ); + return args.richResponse + ? { emitSkipped, - diagnostics: args.includeLinePosition ? - this.convertToDiagnosticsWithLinePositionFromDiagnosticFile(diagnostics) : - diagnostics.map(d => formatDiagnosticToProtocol(d, /*includeFileName*/ true)), - } : - !emitSkipped; + diagnostics: args.includeLinePosition + ? this.convertToDiagnosticsWithLinePositionFromDiagnosticFile(diagnostics) + : diagnostics.map(d => formatDiagnosticToProtocol(d, /*includeFileName*/ true)), + } + : !emitSkipped; } - private getSignatureHelpItems(args: protocol.SignatureHelpRequestArgs, simplifiedResult: boolean): protocol.SignatureHelpItems | SignatureHelpItems | undefined { + private getSignatureHelpItems( + args: protocol.SignatureHelpRequestArgs, + simplifiedResult: boolean, + ): protocol.SignatureHelpItems | SignatureHelpItems | undefined { const { file, project } = this.getFileAndProject(args); const scriptInfo = this.projectService.getScriptInfoForNormalizedPath(file)!; const position = this.getPosition(args, scriptInfo); @@ -2453,7 +2822,10 @@ export class Session implements EventSender { else { return { ...helpItems, - items: helpItems.items.map(item => ({ ...item, tags: this.mapJSDocTagInfo(item.tags, project, /*richResponse*/ false) as JSDocTagInfo[] })), + items: helpItems.items.map(item => ({ + ...item, + tags: this.mapJSDocTagInfo(item.tags, project, /*richResponse*/ false) as JSDocTagInfo[], + })), }; } } @@ -2521,7 +2893,10 @@ export class Session implements EventSender { this.projectService.closeClientFile(file); } - private mapLocationNavigationBarItems(items: NavigationBarItem[], scriptInfo: ScriptInfo): protocol.NavigationBarItem[] { + private mapLocationNavigationBarItems( + items: NavigationBarItem[], + scriptInfo: ScriptInfo, + ): protocol.NavigationBarItem[] { return map(items, item => ({ text: item.text, kind: item.kind, @@ -2532,7 +2907,10 @@ export class Session implements EventSender { })); } - private getNavigationBarItems(args: protocol.FileRequestArgs, simplifiedResult: boolean): protocol.NavigationBarItem[] | NavigationBarItem[] | undefined { + private getNavigationBarItems( + args: protocol.FileRequestArgs, + simplifiedResult: boolean, + ): protocol.NavigationBarItem[] | NavigationBarItem[] | undefined { const { file, languageService } = this.getFileAndLanguageServiceForSyntacticOperation(args); const items = languageService.getNavigationBarItems(file); return !items @@ -2553,7 +2931,10 @@ export class Session implements EventSender { }; } - private getNavigationTree(args: protocol.FileRequestArgs, simplifiedResult: boolean): protocol.NavigationTree | NavigationTree | undefined { + private getNavigationTree( + args: protocol.FileRequestArgs, + simplifiedResult: boolean, + ): protocol.NavigationTree | NavigationTree | undefined { const { file, languageService } = this.getFileAndLanguageServiceForSyntacticOperation(args); const tree = languageService.getNavigationTree(file); return !tree @@ -2563,11 +2944,14 @@ export class Session implements EventSender { : tree; } - private getNavigateToItems(args: protocol.NavtoRequestArgs, simplifiedResult: boolean): readonly protocol.NavtoItem[] | readonly NavigateToItem[] { + private getNavigateToItems( + args: protocol.NavtoRequestArgs, + simplifiedResult: boolean, + ): readonly protocol.NavtoItem[] | readonly NavigateToItem[] { const full = this.getFullNavigateToItems(args); - return !simplifiedResult ? - flatMap(full, ({ navigateToItems }) => navigateToItems) : - flatMap( + return !simplifiedResult + ? flatMap(full, ({ navigateToItems }) => navigateToItems) + : flatMap( full, ({ project, navigateToItems }) => navigateToItems.map(navItem => { @@ -2602,7 +2986,10 @@ export class Session implements EventSender { if (currentFileOnly) { Debug.assertIsDefined(args.file); const { file, project } = this.getFileAndProject(args as protocol.FileRequestArgs); - return [{ project, navigateToItems: project.getLanguageService().getNavigateToItems(searchValue, maxResultCount, file) }]; + return [{ + project, + navigateToItems: project.getLanguageService().getNavigateToItems(searchValue, maxResultCount, file), + }]; } const outputs: ProjectNavigateToItems[] = []; @@ -2637,8 +3024,16 @@ export class Session implements EventSender { // Mutates `outputs` function addItemsForProject(project: Project) { - const projectItems = project.getLanguageService().getNavigateToItems(searchValue, maxResultCount, /*fileName*/ undefined, /*excludeDts*/ project.isNonTsProject()); - const unseenItems = filter(projectItems, item => tryAddSeenItem(item) && !getMappedLocationForProject(documentSpanLocation(item), project)); + const projectItems = project.getLanguageService().getNavigateToItems( + searchValue, + maxResultCount, + /*fileName*/ undefined, + /*excludeDts*/ project.isNonTsProject(), + ); + const unseenItems = filter( + projectItems, + item => tryAddSeenItem(item) && !getMappedLocationForProject(documentSpanLocation(item), project), + ); if (unseenItems.length) { outputs.push({ project, navigateToItems: unseenItems }); } @@ -2671,16 +3066,16 @@ export class Session implements EventSender { if (!a || !b) { return false; } - return a.containerKind === b.containerKind && - a.containerName === b.containerName && - a.fileName === b.fileName && - a.isCaseSensitive === b.isCaseSensitive && - a.kind === b.kind && - a.kindModifiers === b.kindModifiers && - a.matchKind === b.matchKind && - a.name === b.name && - a.textSpan.start === b.textSpan.start && - a.textSpan.length === b.textSpan.length; + return a.containerKind === b.containerKind + && a.containerName === b.containerName + && a.fileName === b.fileName + && a.isCaseSensitive === b.isCaseSensitive + && a.kind === b.kind + && a.kindModifiers === b.kindModifiers + && a.matchKind === b.matchKind + && a.name === b.name + && a.textSpan.start === b.textSpan.start + && a.textSpan.length === b.textSpan.length; } } @@ -2695,11 +3090,16 @@ export class Session implements EventSender { return project.getLanguageService().getSupportedCodeFixes(); } - private isLocation(locationOrSpan: protocol.FileLocationOrRangeRequestArgs): locationOrSpan is protocol.FileLocationRequestArgs { + private isLocation( + locationOrSpan: protocol.FileLocationOrRangeRequestArgs, + ): locationOrSpan is protocol.FileLocationRequestArgs { return (locationOrSpan as protocol.FileLocationRequestArgs).line !== undefined; } - private extractPositionOrRange(args: protocol.FileLocationOrRangeRequestArgs, scriptInfo: ScriptInfo): number | TextRange { + private extractPositionOrRange( + args: protocol.FileLocationOrRangeRequestArgs, + scriptInfo: ScriptInfo, + ): number | TextRange { let position: number | undefined; let textRange: TextRange | undefined; if (this.isLocation(args)) { @@ -2721,13 +3121,25 @@ export class Session implements EventSender { return { pos: startPosition, end: endPosition }; } - private getApplicableRefactors(args: protocol.GetApplicableRefactorsRequestArgs): protocol.ApplicableRefactorInfo[] { + private getApplicableRefactors( + args: protocol.GetApplicableRefactorsRequestArgs, + ): protocol.ApplicableRefactorInfo[] { const { file, project } = this.getFileAndProject(args); const scriptInfo = project.getScriptInfoForNormalizedPath(file)!; - return project.getLanguageService().getApplicableRefactors(file, this.extractPositionOrRange(args, scriptInfo), this.getPreferences(file), args.triggerReason, args.kind, args.includeInteractiveActions); + return project.getLanguageService().getApplicableRefactors( + file, + this.extractPositionOrRange(args, scriptInfo), + this.getPreferences(file), + args.triggerReason, + args.kind, + args.includeInteractiveActions, + ); } - private getEditsForRefactor(args: protocol.GetEditsForRefactorRequestArgs, simplifiedResult: boolean): RefactorEditInfo | protocol.RefactorEditInfo { + private getEditsForRefactor( + args: protocol.GetEditsForRefactorRequestArgs, + simplifiedResult: boolean, + ): RefactorEditInfo | protocol.RefactorEditInfo { const { file, project } = this.getFileAndProject(args); const scriptInfo = project.getScriptInfoForNormalizedPath(file)!; const result = project.getLanguageService().getEditsForRefactor( @@ -2751,7 +3163,12 @@ export class Session implements EventSender { let mappedRenameLocation: protocol.Location | undefined; if (renameFilename !== undefined && renameLocation !== undefined) { const renameScriptInfo = project.getScriptInfoForNormalizedPath(toNormalizedPath(renameFilename))!; - mappedRenameLocation = getLocationInNewDocument(getSnapshotText(renameScriptInfo.getSnapshot()), renameFilename, renameLocation, edits); + mappedRenameLocation = getLocationInNewDocument( + getSnapshotText(renameScriptInfo.getSnapshot()), + renameFilename, + renameLocation, + edits, + ); } return { renameLocation: mappedRenameLocation, @@ -2763,19 +3180,29 @@ export class Session implements EventSender { return result; } - private getMoveToRefactoringFileSuggestions(args: protocol.GetMoveToRefactoringFileSuggestionsRequestArgs): { newFileName: string; files: string[]; } { + private getMoveToRefactoringFileSuggestions( + args: protocol.GetMoveToRefactoringFileSuggestionsRequestArgs, + ): { newFileName: string; files: string[]; } { const { file, project } = this.getFileAndProject(args); const scriptInfo = project.getScriptInfoForNormalizedPath(file)!; - return project.getLanguageService().getMoveToRefactoringFileSuggestions(file, this.extractPositionOrRange(args, scriptInfo), this.getPreferences(file)); + return project.getLanguageService().getMoveToRefactoringFileSuggestions( + file, + this.extractPositionOrRange(args, scriptInfo), + this.getPreferences(file), + ); } - private organizeImports(args: protocol.OrganizeImportsRequestArgs, simplifiedResult: boolean): readonly protocol.FileCodeEdits[] | readonly FileTextChanges[] { + private organizeImports( + args: protocol.OrganizeImportsRequestArgs, + simplifiedResult: boolean, + ): readonly protocol.FileCodeEdits[] | readonly FileTextChanges[] { Debug.assert(args.scope.type === "file"); const { file, project } = this.getFileAndProject(args.scope.args); const changes = project.getLanguageService().organizeImports( { fileName: file, - mode: args.mode as OrganizeImportsMode | undefined ?? (args.skipDestructiveCodeActions ? OrganizeImportsMode.SortAndCombine : undefined), + mode: args.mode as OrganizeImportsMode | undefined + ?? (args.skipDestructiveCodeActions ? OrganizeImportsMode.SortAndCombine : undefined), type: "file", }, this.getFormatOptions(file), @@ -2789,7 +3216,10 @@ export class Session implements EventSender { } } - private getEditsForFileRename(args: protocol.GetEditsForFileRenameRequestArgs, simplifiedResult: boolean): readonly protocol.FileCodeEdits[] | readonly FileTextChanges[] { + private getEditsForFileRename( + args: protocol.GetEditsForFileRenameRequestArgs, + simplifiedResult: boolean, + ): readonly protocol.FileCodeEdits[] | readonly FileTextChanges[] { const oldPath = toNormalizedPath(args.oldFilePath); const newPath = toNormalizedPath(args.newFilePath); const formatOptions = this.getHostFormatOptions(); @@ -2802,7 +3232,12 @@ export class Session implements EventSender { // those that are downstream from already-loaded projects. this.projectService.loadAncestorProjectTree(); this.projectService.forEachEnabledProject(project => { - const projectTextChanges = project.getLanguageService().getEditsForFileRename(oldPath, newPath, formatOptions, preferences); + const projectTextChanges = project.getLanguageService().getEditsForFileRename( + oldPath, + newPath, + formatOptions, + preferences, + ); const projectFiles: string[] = []; for (const textChange of projectTextChanges) { if (!seenFiles.has(textChange.fileName)) { @@ -2818,7 +3253,10 @@ export class Session implements EventSender { return simplifiedResult ? textChanges.map(c => this.mapTextChangeToCodeEdit(c)) : textChanges; } - private getCodeFixes(args: protocol.CodeFixRequestArgs, simplifiedResult: boolean): readonly protocol.CodeFixAction[] | readonly CodeFixAction[] | undefined { + private getCodeFixes( + args: protocol.CodeFixRequestArgs, + simplifiedResult: boolean, + ): readonly protocol.CodeFixAction[] | readonly CodeFixAction[] | undefined { const { file, project } = this.getFileAndProject(args); const scriptInfo = project.getScriptInfoForNormalizedPath(file)!; @@ -2826,7 +3264,14 @@ export class Session implements EventSender { let codeActions: readonly CodeFixAction[]; try { - codeActions = project.getLanguageService().getCodeFixesAtPosition(file, startPosition, endPosition, args.errorCodes, this.getFormatOptions(file), this.getPreferences(file)); + codeActions = project.getLanguageService().getCodeFixesAtPosition( + file, + startPosition, + endPosition, + args.errorCodes, + this.getFormatOptions(file), + this.getPreferences(file), + ); } catch (e) { const ls = project.getLanguageService(); @@ -2840,17 +3285,28 @@ export class Session implements EventSender { ); const badCode = args.errorCodes.find(c => !existingDiagCodes.includes(c)); if (badCode !== undefined) { - e.message = `BADCLIENT: Bad error code, ${badCode} not found in range ${startPosition}..${endPosition} (found: ${existingDiagCodes.join(", ")}); could have caused this error:\n${e.message}`; + e.message = + `BADCLIENT: Bad error code, ${badCode} not found in range ${startPosition}..${endPosition} (found: ${ + existingDiagCodes.join(", ") + }); could have caused this error:\n${e.message}`; } throw e; } return simplifiedResult ? codeActions.map(codeAction => this.mapCodeFixAction(codeAction)) : codeActions; } - private getCombinedCodeFix({ scope, fixId }: protocol.GetCombinedCodeFixRequestArgs, simplifiedResult: boolean): protocol.CombinedCodeActions | CombinedCodeActions { + private getCombinedCodeFix( + { scope, fixId }: protocol.GetCombinedCodeFixRequestArgs, + simplifiedResult: boolean, + ): protocol.CombinedCodeActions | CombinedCodeActions { Debug.assert(scope.type === "file"); const { file, project } = this.getFileAndProject(scope.args); - const res = project.getLanguageService().getCombinedCodeFix({ type: "file", fileName: file }, fixId, this.getFormatOptions(file), this.getPreferences(file)); + const res = project.getLanguageService().getCombinedCodeFix( + { type: "file", fileName: file }, + fixId, + this.getFormatOptions(file), + this.getPreferences(file), + ); if (simplifiedResult) { return { changes: this.mapTextChangesToCodeEdits(res.changes), commands: res.commands }; } @@ -2897,8 +3353,17 @@ export class Session implements EventSender { return { description, changes: this.mapTextChangesToCodeEdits(changes), commands }; } - private mapCodeFixAction({ fixName, description, changes, commands, fixId, fixAllDescription }: CodeFixAction): protocol.CodeFixAction { - return { fixName, description, changes: this.mapTextChangesToCodeEdits(changes), commands, fixId, fixAllDescription }; + private mapCodeFixAction( + { fixName, description, changes, commands, fixId, fixAllDescription }: CodeFixAction, + ): protocol.CodeFixAction { + return { + fixName, + description, + changes: this.mapTextChangesToCodeEdits(changes), + commands, + fixId, + fixAllDescription, + }; } private mapTextChangesToCodeEdits(textChanges: readonly FileTextChanges[]): protocol.FileCodeEdits[] { @@ -2911,10 +3376,18 @@ export class Session implements EventSender { if (!scriptInfo) { // and !isNewFile this.projectService.logErrorForScriptInfoNotFound(textChanges.fileName); } - Debug.fail("Expected isNewFile for (only) new files. " + JSON.stringify({ isNewFile: !!textChanges.isNewFile, hasScriptInfo: !!scriptInfo })); + Debug.fail( + "Expected isNewFile for (only) new files. " + + JSON.stringify({ isNewFile: !!textChanges.isNewFile, hasScriptInfo: !!scriptInfo }), + ); } return scriptInfo - ? { fileName: textChanges.fileName, textChanges: textChanges.textChanges.map(textChange => convertTextChangeToCodeEdit(textChange, scriptInfo)) } + ? { + fileName: textChanges.fileName, + textChanges: textChanges.textChanges.map(textChange => + convertTextChangeToCodeEdit(textChange, scriptInfo) + ), + } : convertNewFileTextChangeToCodeEdit(textChanges); } @@ -2926,7 +3399,10 @@ export class Session implements EventSender { }; } - private getBraceMatching(args: protocol.FileLocationRequestArgs, simplifiedResult: boolean): protocol.TextSpan[] | TextSpan[] | undefined { + private getBraceMatching( + args: protocol.FileLocationRequestArgs, + simplifiedResult: boolean, + ): protocol.TextSpan[] | TextSpan[] | undefined { const { file, languageService } = this.getFileAndLanguageServiceForSyntacticOperation(args); const scriptInfo = this.projectService.getScriptInfoForNormalizedPath(file)!; const position = this.getPosition(args, scriptInfo); @@ -2944,7 +3420,12 @@ export class Session implements EventSender { return; } - const { fileNames, languageServiceDisabled } = this.getProjectInfoWorker(fileName, /*projectFileName*/ undefined, /*needFileNameList*/ true, /*excludeConfigFiles*/ true); + const { fileNames, languageServiceDisabled } = this.getProjectInfoWorker( + fileName, + /*projectFileName*/ undefined, + /*needFileNameList*/ true, + /*excludeConfigFiles*/ true, + ); if (languageServiceDisabled) { return; } @@ -2982,7 +3463,12 @@ export class Session implements EventSender { } } - const sortedFiles = [...highPriorityFiles, ...mediumPriorityFiles, ...lowPriorityFiles, ...veryLowPriorityFiles]; + const sortedFiles = [ + ...highPriorityFiles, + ...mediumPriorityFiles, + ...lowPriorityFiles, + ...veryLowPriorityFiles, + ]; const checkList = sortedFiles.map(fileName => ({ fileName, project })); // Project level error analysis runs on background files too, therefore // doesn't require the file to be opened @@ -3005,7 +3491,10 @@ export class Session implements EventSender { }); } - private toggleLineComment(args: protocol.FileRangeRequestArgs, simplifiedResult: boolean): TextChange[] | protocol.CodeEdit[] { + private toggleLineComment( + args: protocol.FileRangeRequestArgs, + simplifiedResult: boolean, + ): TextChange[] | protocol.CodeEdit[] { const { file, languageService } = this.getFileAndLanguageServiceForSyntacticOperation(args); const scriptInfo = this.projectService.getScriptInfo(file)!; const textRange = this.getRange(args, scriptInfo); @@ -3021,7 +3510,10 @@ export class Session implements EventSender { return textChanges; } - private toggleMultilineComment(args: protocol.FileRangeRequestArgs, simplifiedResult: boolean): TextChange[] | protocol.CodeEdit[] { + private toggleMultilineComment( + args: protocol.FileRangeRequestArgs, + simplifiedResult: boolean, + ): TextChange[] | protocol.CodeEdit[] { const { file, languageService } = this.getFileAndLanguageServiceForSyntacticOperation(args); const scriptInfo = this.projectService.getScriptInfoForNormalizedPath(file)!; const textRange = this.getRange(args, scriptInfo); @@ -3037,7 +3529,10 @@ export class Session implements EventSender { return textChanges; } - private commentSelection(args: protocol.FileRangeRequestArgs, simplifiedResult: boolean): TextChange[] | protocol.CodeEdit[] { + private commentSelection( + args: protocol.FileRangeRequestArgs, + simplifiedResult: boolean, + ): TextChange[] | protocol.CodeEdit[] { const { file, languageService } = this.getFileAndLanguageServiceForSyntacticOperation(args); const scriptInfo = this.projectService.getScriptInfoForNormalizedPath(file)!; const textRange = this.getRange(args, scriptInfo); @@ -3053,7 +3548,10 @@ export class Session implements EventSender { return textChanges; } - private uncommentSelection(args: protocol.FileRangeRequestArgs, simplifiedResult: boolean): TextChange[] | protocol.CodeEdit[] { + private uncommentSelection( + args: protocol.FileRangeRequestArgs, + simplifiedResult: boolean, + ): TextChange[] | protocol.CodeEdit[] { const { file, languageService } = this.getFileAndLanguageServiceForSyntacticOperation(args); const scriptInfo = this.projectService.getScriptInfoForNormalizedPath(file)!; const textRange = this.getRange(args, scriptInfo); @@ -3102,7 +3600,9 @@ export class Session implements EventSender { }; } - private toProtocolCallHierarchyIncomingCall(incomingCall: CallHierarchyIncomingCall): protocol.CallHierarchyIncomingCall { + private toProtocolCallHierarchyIncomingCall( + incomingCall: CallHierarchyIncomingCall, + ): protocol.CallHierarchyIncomingCall { const scriptInfo = this.getScriptInfoFromProjectService(incomingCall.from.file); return { from: this.toProtocolCallHierarchyItem(incomingCall.from), @@ -3110,14 +3610,19 @@ export class Session implements EventSender { }; } - private toProtocolCallHierarchyOutgoingCall(outgoingCall: CallHierarchyOutgoingCall, scriptInfo: ScriptInfo): protocol.CallHierarchyOutgoingCall { + private toProtocolCallHierarchyOutgoingCall( + outgoingCall: CallHierarchyOutgoingCall, + scriptInfo: ScriptInfo, + ): protocol.CallHierarchyOutgoingCall { return { to: this.toProtocolCallHierarchyItem(outgoingCall.to), fromSpans: outgoingCall.fromSpans.map(fromSpan => toProtocolTextSpan(fromSpan, scriptInfo)), }; } - private prepareCallHierarchy(args: protocol.FileLocationRequestArgs): protocol.CallHierarchyItem | protocol.CallHierarchyItem[] | undefined { + private prepareCallHierarchy( + args: protocol.FileLocationRequestArgs, + ): protocol.CallHierarchyItem | protocol.CallHierarchyItem[] | undefined { const { file, project } = this.getFileAndProject(args); const scriptInfo = this.projectService.getScriptInfoForNormalizedPath(file); if (scriptInfo) { @@ -3128,17 +3633,27 @@ export class Session implements EventSender { return undefined; } - private provideCallHierarchyIncomingCalls(args: protocol.FileLocationRequestArgs): protocol.CallHierarchyIncomingCall[] { + private provideCallHierarchyIncomingCalls( + args: protocol.FileLocationRequestArgs, + ): protocol.CallHierarchyIncomingCall[] { const { file, project } = this.getFileAndProject(args); const scriptInfo = this.getScriptInfoFromProjectService(file); - const incomingCalls = project.getLanguageService().provideCallHierarchyIncomingCalls(file, this.getPosition(args, scriptInfo)); + const incomingCalls = project.getLanguageService().provideCallHierarchyIncomingCalls( + file, + this.getPosition(args, scriptInfo), + ); return incomingCalls.map(call => this.toProtocolCallHierarchyIncomingCall(call)); } - private provideCallHierarchyOutgoingCalls(args: protocol.FileLocationRequestArgs): protocol.CallHierarchyOutgoingCall[] { + private provideCallHierarchyOutgoingCalls( + args: protocol.FileLocationRequestArgs, + ): protocol.CallHierarchyOutgoingCall[] { const { file, project } = this.getFileAndProject(args); const scriptInfo = this.getScriptInfoFromProjectService(file); - const outgoingCalls = project.getLanguageService().provideCallHierarchyOutgoingCalls(file, this.getPosition(args, scriptInfo)); + const outgoingCalls = project.getLanguageService().provideCallHierarchyOutgoingCalls( + file, + this.getPosition(args, scriptInfo), + ); return outgoingCalls.map(call => this.toProtocolCallHierarchyOutgoingCall(call, scriptInfo)); } @@ -3178,7 +3693,10 @@ export class Session implements EventSender { return this.requiredResponse(/*response*/ true); }, [protocol.CommandTypes.SynchronizeProjectList]: (request: protocol.SynchronizeProjectListRequest) => { - const result = this.projectService.synchronizeProjectList(request.arguments.knownProjects, request.arguments.includeProjectReferenceRedirectInfo); + const result = this.projectService.synchronizeProjectList( + request.arguments.knownProjects, + request.arguments.includeProjectReferenceRedirectInfo, + ); if (!result.some(p => p.projectErrors && p.projectErrors.length !== 0)) { return this.requiredResponse(result); } @@ -3210,7 +3728,8 @@ export class Session implements EventSender { const scriptInfo = Debug.checkDefined(this.projectService.getScriptInfo(file.fileName)); const start = scriptInfo.lineOffsetToPosition(change.start.line, change.start.offset); const end = scriptInfo.lineOffsetToPosition(change.end.line, change.end.offset); - return start >= 0 ? { span: { start, length: end - start }, newText: change.newText } : undefined; + return start >= 0 ? { span: { start, length: end - start }, newText: change.newText } + : undefined; }), })), request.arguments.closedFiles, @@ -3355,7 +3874,9 @@ export class Session implements EventSender { [protocol.CommandTypes.CompletionDetailsFull]: (request: protocol.CompletionDetailsRequest) => { return this.requiredResponse(this.getCompletionEntryDetails(request.arguments, /*fullResult*/ true)); }, - [protocol.CommandTypes.CompileOnSaveAffectedFileList]: (request: protocol.CompileOnSaveAffectedFileListRequest) => { + [protocol.CommandTypes.CompileOnSaveAffectedFileList]: ( + request: protocol.CompileOnSaveAffectedFileListRequest, + ) => { return this.requiredResponse(this.getCompileOnSaveAffectedFileList(request.arguments)); }, [protocol.CommandTypes.CompileOnSaveEmitFile]: (request: protocol.CompileOnSaveEmitFileRequest) => { @@ -3367,13 +3888,19 @@ export class Session implements EventSender { [protocol.CommandTypes.SignatureHelpFull]: (request: protocol.SignatureHelpRequest) => { return this.requiredResponse(this.getSignatureHelpItems(request.arguments, /*simplifiedResult*/ false)); }, - [protocol.CommandTypes.CompilerOptionsDiagnosticsFull]: (request: protocol.CompilerOptionsDiagnosticsRequest) => { + [protocol.CommandTypes.CompilerOptionsDiagnosticsFull]: ( + request: protocol.CompilerOptionsDiagnosticsRequest, + ) => { return this.requiredResponse(this.getCompilerOptionsDiagnostics(request.arguments)); }, - [protocol.CommandTypes.EncodedSyntacticClassificationsFull]: (request: protocol.EncodedSyntacticClassificationsRequest) => { + [protocol.CommandTypes.EncodedSyntacticClassificationsFull]: ( + request: protocol.EncodedSyntacticClassificationsRequest, + ) => { return this.requiredResponse(this.getEncodedSyntacticClassifications(request.arguments)); }, - [protocol.CommandTypes.EncodedSemanticClassificationsFull]: (request: protocol.EncodedSemanticClassificationsRequest) => { + [protocol.CommandTypes.EncodedSemanticClassificationsFull]: ( + request: protocol.EncodedSemanticClassificationsRequest, + ) => { return this.requiredResponse(this.getEncodedSemanticClassifications(request.arguments)); }, [protocol.CommandTypes.Cleanup]: () => { @@ -3390,11 +3917,15 @@ export class Session implements EventSender { return this.requiredResponse(this.getSuggestionDiagnosticsSync(request.arguments)); }, [protocol.CommandTypes.Geterr]: (request: protocol.GeterrRequest) => { - this.errorCheck.startNew(next => this.getDiagnostics(next, request.arguments.delay, request.arguments.files)); + this.errorCheck.startNew(next => + this.getDiagnostics(next, request.arguments.delay, request.arguments.files) + ); return this.notRequired(); }, [protocol.CommandTypes.GeterrForProject]: (request: protocol.GeterrForProjectRequest) => { - this.errorCheck.startNew(next => this.getDiagnosticsForProject(next, request.arguments.delay, request.arguments.file)); + this.errorCheck.startNew(next => + this.getDiagnosticsForProject(next, request.arguments.delay, request.arguments.file) + ); return this.notRequired(); }, [protocol.CommandTypes.Change]: (request: protocol.ChangeRequest) => { @@ -3450,7 +3981,9 @@ export class Session implements EventSender { [protocol.CommandTypes.DocumentHighlightsFull]: (request: protocol.DocumentHighlightsRequest) => { return this.requiredResponse(this.getDocumentHighlights(request.arguments, /*simplifiedResult*/ false)); }, - [protocol.CommandTypes.CompilerOptionsForInferredProjects]: (request: protocol.SetCompilerOptionsForInferredProjectsRequest) => { + [protocol.CommandTypes.CompilerOptionsForInferredProjects]: ( + request: protocol.SetCompilerOptionsForInferredProjectsRequest, + ) => { this.setCompilerOptionsForInferredProjects(request.arguments); return this.requiredResponse(/*response*/ true); }, @@ -3491,7 +4024,9 @@ export class Session implements EventSender { [protocol.CommandTypes.GetEditsForRefactor]: (request: protocol.GetEditsForRefactorRequest) => { return this.requiredResponse(this.getEditsForRefactor(request.arguments, /*simplifiedResult*/ true)); }, - [protocol.CommandTypes.GetMoveToRefactoringFileSuggestions]: (request: protocol.GetMoveToRefactoringFileSuggestionsRequest) => { + [protocol.CommandTypes.GetMoveToRefactoringFileSuggestions]: ( + request: protocol.GetMoveToRefactoringFileSuggestionsRequest, + ) => { return this.requiredResponse(this.getMoveToRefactoringFileSuggestions(request.arguments)); }, [protocol.CommandTypes.GetEditsForRefactorFull]: (request: protocol.GetEditsForRefactorRequest) => { @@ -3523,10 +4058,14 @@ export class Session implements EventSender { [protocol.CommandTypes.PrepareCallHierarchy]: (request: protocol.PrepareCallHierarchyRequest) => { return this.requiredResponse(this.prepareCallHierarchy(request.arguments)); }, - [protocol.CommandTypes.ProvideCallHierarchyIncomingCalls]: (request: protocol.ProvideCallHierarchyIncomingCallsRequest) => { + [protocol.CommandTypes.ProvideCallHierarchyIncomingCalls]: ( + request: protocol.ProvideCallHierarchyIncomingCallsRequest, + ) => { return this.requiredResponse(this.provideCallHierarchyIncomingCalls(request.arguments)); }, - [protocol.CommandTypes.ProvideCallHierarchyOutgoingCalls]: (request: protocol.ProvideCallHierarchyOutgoingCallsRequest) => { + [protocol.CommandTypes.ProvideCallHierarchyOutgoingCalls]: ( + request: protocol.ProvideCallHierarchyOutgoingCallsRequest, + ) => { return this.requiredResponse(this.provideCallHierarchyOutgoingCalls(request.arguments)); }, [protocol.CommandTypes.ToggleLineComment]: (request: protocol.ToggleLineCommentRequest) => { @@ -3596,7 +4135,13 @@ export class Session implements EventSender { } else { this.logger.msg(`Unrecognized JSON command:${stringifyIndented(request)}`, Msg.Err); - this.doOutput(/*info*/ undefined, protocol.CommandTypes.Unknown, request.seq, /*success*/ false, `Unrecognized JSON command: ${request.command}`); + this.doOutput( + /*info*/ undefined, + protocol.CommandTypes.Unknown, + request.seq, + /*success*/ false, + `Unrecognized JSON command: ${request.command}`, + ); return { responseRequired: false }; } } @@ -3618,33 +4163,53 @@ export class Session implements EventSender { let relevantFile: protocol.FileRequestArgs | undefined; try { request = this.parseMessage(message); - relevantFile = request.arguments && (request as protocol.FileRequest).arguments.file ? (request as protocol.FileRequest).arguments : undefined; + relevantFile = request.arguments && (request as protocol.FileRequest).arguments.file + ? (request as protocol.FileRequest).arguments : undefined; tracing?.instant(tracing.Phase.Session, "request", { seq: request.seq, command: request.command }); perfLogger?.logStartCommand("" + request.command, this.toStringMessage(message).substring(0, 100)); - tracing?.push(tracing.Phase.Session, "executeCommand", { seq: request.seq, command: request.command }, /*separateBeginAndEnd*/ true); + tracing?.push( + tracing.Phase.Session, + "executeCommand", + { seq: request.seq, command: request.command }, + /*separateBeginAndEnd*/ true, + ); const { response, responseRequired } = this.executeCommand(request); tracing?.pop(); if (this.logger.hasLevel(LogLevel.requestTime)) { const elapsedTime = hrTimeToMilliseconds(this.hrtime(start)).toFixed(4); if (responseRequired) { - this.logger.perftrc(`${request.seq}::${request.command}: elapsed time (in milliseconds) ${elapsedTime}`); + this.logger.perftrc( + `${request.seq}::${request.command}: elapsed time (in milliseconds) ${elapsedTime}`, + ); } else { - this.logger.perftrc(`${request.seq}::${request.command}: async elapsed time (in milliseconds) ${elapsedTime}`); + this.logger.perftrc( + `${request.seq}::${request.command}: async elapsed time (in milliseconds) ${elapsedTime}`, + ); } } // Note: Log before writing the response, else the editor can complete its activity before the server does perfLogger?.logStopCommand("" + request.command, "Success"); - tracing?.instant(tracing.Phase.Session, "response", { seq: request.seq, command: request.command, success: !!response }); + tracing?.instant(tracing.Phase.Session, "response", { + seq: request.seq, + command: request.command, + success: !!response, + }); if (response) { this.doOutput(response, request.command, request.seq, /*success*/ true); } else if (responseRequired) { - this.doOutput(/*info*/ undefined, request.command, request.seq, /*success*/ false, "No content available."); + this.doOutput( + /*info*/ undefined, + request.command, + request.seq, + /*success*/ false, + "No content available.", + ); } } catch (err) { @@ -3654,14 +4219,21 @@ export class Session implements EventSender { if (err instanceof OperationCanceledException) { // Handle cancellation exceptions perfLogger?.logStopCommand("" + (request && request.command), "Canceled: " + err); - tracing?.instant(tracing.Phase.Session, "commandCanceled", { seq: request?.seq, command: request?.command }); + tracing?.instant(tracing.Phase.Session, "commandCanceled", { + seq: request?.seq, + command: request?.command, + }); this.doOutput({ canceled: true }, request!.command, request!.seq, /*success*/ true); return; } this.logErrorWorker(err, this.toStringMessage(message), relevantFile); perfLogger?.logStopCommand("" + (request && request.command), "Error: " + err); - tracing?.instant(tracing.Phase.Session, "commandError", { seq: request?.seq, command: request?.command, message: (err as Error).message }); + tracing?.instant(tracing.Phase.Session, "commandError", { + seq: request?.seq, + command: request?.command, + message: (err as Error).message, + }); this.doOutput( /*info*/ undefined, @@ -3710,23 +4282,35 @@ function toProtocolTextSpan(textSpan: TextSpan, scriptInfo: ScriptInfo): protoco }; } -function toProtocolTextSpanWithContext(span: TextSpan, contextSpan: TextSpan | undefined, scriptInfo: ScriptInfo): protocol.TextSpanWithContext { +function toProtocolTextSpanWithContext( + span: TextSpan, + contextSpan: TextSpan | undefined, + scriptInfo: ScriptInfo, +): protocol.TextSpanWithContext { const textSpan = toProtocolTextSpan(span, scriptInfo); const contextTextSpan = contextSpan && toProtocolTextSpan(contextSpan, scriptInfo); - return contextTextSpan ? - { ...textSpan, contextStart: contextTextSpan.start, contextEnd: contextTextSpan.end } : - textSpan; + return contextTextSpan + ? { ...textSpan, contextStart: contextTextSpan.start, contextEnd: contextTextSpan.end } + : textSpan; } function convertTextChangeToCodeEdit(change: TextChange, scriptInfo: ScriptInfoOrConfig): protocol.CodeEdit { - return { start: positionToLineOffset(scriptInfo, change.span.start), end: positionToLineOffset(scriptInfo, textSpanEnd(change.span)), newText: change.newText }; + return { + start: positionToLineOffset(scriptInfo, change.span.start), + end: positionToLineOffset(scriptInfo, textSpanEnd(change.span)), + newText: change.newText, + }; } function positionToLineOffset(info: ScriptInfoOrConfig, position: number): protocol.Location { - return isConfigFile(info) ? locationFromLineAndCharacter(info.getLineAndCharacterOfPosition(position)) : info.positionToLineOffset(position); + return isConfigFile(info) ? locationFromLineAndCharacter(info.getLineAndCharacterOfPosition(position)) + : info.positionToLineOffset(position); } -function convertLinkedEditInfoToRanges(linkedEdit: LinkedEditingInfo, scriptInfo: ScriptInfo): protocol.LinkedEditingRangesBody { +function convertLinkedEditInfoToRanges( + linkedEdit: LinkedEditingInfo, + scriptInfo: ScriptInfo, +): protocol.LinkedEditingRangesBody { const ranges = linkedEdit.ranges.map( r => { return { @@ -3747,7 +4331,10 @@ function convertNewFileTextChangeToCodeEdit(textChanges: FileTextChanges): proto Debug.assert(textChanges.textChanges.length === 1); const change = first(textChanges.textChanges); Debug.assert(change.span.start === 0 && change.span.length === 0); - return { fileName: textChanges.fileName, textChanges: [{ start: { line: 0, offset: 0 }, end: { line: 0, offset: 0 }, newText: change.newText }] }; + return { + fileName: textChanges.fileName, + textChanges: [{ start: { line: 0, offset: 0 }, end: { line: 0, offset: 0 }, newText: change.newText }], + }; } export interface HandlerResponse { @@ -3757,7 +4344,12 @@ export interface HandlerResponse { /** @internal */ // Exported only for tests -export function getLocationInNewDocument(oldText: string, renameFilename: string, renameLocation: number, edits: readonly FileTextChanges[]): protocol.Location { +export function getLocationInNewDocument( + oldText: string, + renameFilename: string, + renameLocation: number, + edits: readonly FileTextChanges[], +): protocol.Location { const newText = applyEdits(oldText, renameFilename, edits); const { line, character } = computeLineAndCharacterOfPosition(computeLineStarts(newText), renameLocation); return { line: line + 1, offset: character + 1 }; @@ -3778,7 +4370,11 @@ function applyEdits(text: string, textFilename: string, edits: readonly FileText return text; } -function referenceEntryToReferencesResponseItem(projectService: ProjectService, { fileName, textSpan, contextSpan, isWriteAccess, isDefinition }: ReferencedSymbolEntry, { disableLineTextInReferences }: protocol.UserPreferences): protocol.ReferencesResponseItem { +function referenceEntryToReferencesResponseItem( + projectService: ProjectService, + { fileName, textSpan, contextSpan, isWriteAccess, isDefinition }: ReferencedSymbolEntry, + { disableLineTextInReferences }: protocol.UserPreferences, +): protocol.ReferencesResponseItem { const scriptInfo = Debug.checkDefined(projectService.getScriptInfo(fileName)); const span = toProtocolTextSpanWithContext(textSpan, contextSpan, scriptInfo); const lineText = disableLineTextInReferences ? undefined : getLineText(scriptInfo, span); diff --git a/src/server/types.ts b/src/server/types.ts index 4a6aa56f7fb46..72b6ef4ada2c6 100644 --- a/src/server/types.ts +++ b/src/server/types.ts @@ -12,14 +12,27 @@ export interface CompressedData { data: any; } -export type ModuleImportResult = { module: {}; error: undefined; } | { module: undefined; error: { stack?: string; message?: string; }; }; +export type ModuleImportResult = { module: {}; error: undefined; } | { + module: undefined; + error: { stack?: string; message?: string; }; +}; /** @deprecated Use {@link ModuleImportResult} instead. */ export type RequireResult = ModuleImportResult; export interface ServerHost extends System { - watchFile(path: string, callback: FileWatcherCallback, pollingInterval?: number, options?: WatchOptions): FileWatcher; - watchDirectory(path: string, callback: DirectoryWatcherCallback, recursive?: boolean, options?: WatchOptions): FileWatcher; + watchFile( + path: string, + callback: FileWatcherCallback, + pollingInterval?: number, + options?: WatchOptions, + ): FileWatcher; + watchDirectory( + path: string, + callback: DirectoryWatcherCallback, + recursive?: boolean, + options?: WatchOptions, + ): FileWatcher; setTimeout(callback: (...args: any[]) => void, ms: number, ...args: any[]): any; clearTimeout(timeoutId: any): void; setImmediate(callback: (...args: any[]) => void, ...args: any[]): any; diff --git a/src/server/typingsCache.ts b/src/server/typingsCache.ts index 6f905fce17bbf..a5df9426dae63 100644 --- a/src/server/typingsCache.ts +++ b/src/server/typingsCache.ts @@ -28,7 +28,11 @@ export interface InstallPackageOptionsWithProject extends InstallPackageOptions export interface ITypingsInstaller { isKnownTypesPackageName(name: string): boolean; installPackage(options: InstallPackageOptionsWithProject): Promise; - enqueueInstallTypingsRequest(p: Project, typeAcquisition: TypeAcquisition, unresolvedImports: SortedReadonlyArray | undefined): void; + enqueueInstallTypingsRequest( + p: Project, + typeAcquisition: TypeAcquisition, + unresolvedImports: SortedReadonlyArray | undefined, + ): void; attach(projectService: ProjectService): void; onProjectClosed(p: Project): void; readonly globalTypingsCacheLocation: string | undefined; @@ -83,9 +87,9 @@ function setIsEqualTo(arr1: string[] | undefined, arr2: string[] | undefined): b } function typeAcquisitionChanged(opt1: TypeAcquisition, opt2: TypeAcquisition): boolean { - return opt1.enable !== opt2.enable || - !setIsEqualTo(opt1.include, opt2.include) || - !setIsEqualTo(opt1.exclude, opt2.exclude); + return opt1.enable !== opt2.enable + || !setIsEqualTo(opt1.include, opt2.include) + || !setIsEqualTo(opt1.exclude, opt2.exclude); } function compilerOptionsChanged(opt1: CompilerOptions, opt2: CompilerOptions): boolean { @@ -93,7 +97,10 @@ function compilerOptionsChanged(opt1: CompilerOptions, opt2: CompilerOptions): b return getAllowJSCompilerOption(opt1) !== getAllowJSCompilerOption(opt2); } -function unresolvedImportsChanged(imports1: SortedReadonlyArray | undefined, imports2: SortedReadonlyArray | undefined): boolean { +function unresolvedImportsChanged( + imports1: SortedReadonlyArray | undefined, + imports2: SortedReadonlyArray | undefined, +): boolean { if (imports1 === imports2) { return false; } @@ -115,7 +122,11 @@ export class TypingsCache { return this.installer.installPackage(options); } - enqueueInstallTypingsForProject(project: Project, unresolvedImports: SortedReadonlyArray | undefined, forceRefresh: boolean) { + enqueueInstallTypingsForProject( + project: Project, + unresolvedImports: SortedReadonlyArray | undefined, + forceRefresh: boolean, + ) { const typeAcquisition = project.getTypeAcquisition(); if (!typeAcquisition || !typeAcquisition.enable) { @@ -124,11 +135,11 @@ export class TypingsCache { const entry = this.perProjectCache.get(project.getProjectName()); if ( - forceRefresh || - !entry || - typeAcquisitionChanged(typeAcquisition, entry.typeAcquisition) || - compilerOptionsChanged(project.getCompilationSettings(), entry.compilerOptions) || - unresolvedImportsChanged(unresolvedImports, entry.unresolvedImports) + forceRefresh + || !entry + || typeAcquisitionChanged(typeAcquisition, entry.typeAcquisition) + || compilerOptionsChanged(project.getCompilationSettings(), entry.compilerOptions) + || unresolvedImportsChanged(unresolvedImports, entry.unresolvedImports) ) { // Note: entry is now poisoned since it does not really contain typings for a given combination of compiler options\typings options. // instead it acts as a placeholder to prevent issuing multiple requests @@ -144,7 +155,13 @@ export class TypingsCache { } } - updateTypingsForProject(projectName: string, compilerOptions: CompilerOptions, typeAcquisition: TypeAcquisition, unresolvedImports: SortedReadonlyArray, newTypings: string[]) { + updateTypingsForProject( + projectName: string, + compilerOptions: CompilerOptions, + typeAcquisition: TypeAcquisition, + unresolvedImports: SortedReadonlyArray, + newTypings: string[], + ) { const typings = sort(newTypings); this.perProjectCache.set(projectName, { compilerOptions, diff --git a/src/server/utilities.ts b/src/server/utilities.ts index c9bd0ea1c6700..def0cbf5e5621 100644 --- a/src/server/utilities.ts +++ b/src/server/utilities.ts @@ -34,7 +34,10 @@ export class ThrottledOperations { this.host.clearTimeout(pendingTimeout); } // schedule new operation, pass arguments - this.pendingTimeouts.set(operationId, this.host.setTimeout(ThrottledOperations.run, delay, operationId, this, cb)); + this.pendingTimeouts.set( + operationId, + this.host.setTimeout(ThrottledOperations.run, delay, operationId, this, cb), + ); if (this.logger) { this.logger.info(`Scheduled: ${operationId}${pendingTimeout ? ", Cancelled earlier one" : ""}`); } diff --git a/src/server/utilitiesPublic.ts b/src/server/utilitiesPublic.ts index ac8e0f3c131c3..c762eb6277b95 100644 --- a/src/server/utilitiesPublic.ts +++ b/src/server/utilitiesPublic.ts @@ -41,10 +41,17 @@ export enum Msg { Perf = "Perf", } -export function createInstallTypingsRequest(project: Project, typeAcquisition: TypeAcquisition, unresolvedImports: SortedReadonlyArray, cachePath?: string): DiscoverTypings { +export function createInstallTypingsRequest( + project: Project, + typeAcquisition: TypeAcquisition, + unresolvedImports: SortedReadonlyArray, + cachePath?: string, +): DiscoverTypings { return { projectName: project.getProjectName(), - fileNames: project.getFileNames(/*excludeFilesFromExternalLibraries*/ true, /*excludeConfigFiles*/ true).concat(project.getExcludedFiles() as NormalizedPath[]), + fileNames: project.getFileNames(/*excludeFilesFromExternalLibraries*/ true, /*excludeConfigFiles*/ true).concat( + project.getExcludedFiles() as NormalizedPath[], + ), compilerOptions: project.getCompilationSettings(), typeAcquisition, unresolvedImports, @@ -72,8 +79,13 @@ export function toNormalizedPath(fileName: string): NormalizedPath { return normalizePath(fileName) as NormalizedPath; } -export function normalizedPathToPath(normalizedPath: NormalizedPath, currentDirectory: string, getCanonicalFileName: (f: string) => string): Path { - const f = isRootedDiskPath(normalizedPath) ? normalizedPath : getNormalizedAbsolutePath(normalizedPath, currentDirectory); +export function normalizedPathToPath( + normalizedPath: NormalizedPath, + currentDirectory: string, + getCanonicalFileName: (f: string) => string, +): Path { + const f = isRootedDiskPath(normalizedPath) ? normalizedPath + : getNormalizedAbsolutePath(normalizedPath, currentDirectory); return getCanonicalFileName(f) as Path; } diff --git a/src/services/breakpoints.ts b/src/services/breakpoints.ts index 8963a5dcf0d73..f36ade5661b95 100644 --- a/src/services/breakpoints.ts +++ b/src/services/breakpoints.ts @@ -110,14 +110,17 @@ export function spanInSourceFileAtLocation(sourceFile: SourceFile, position: num function textSpan(startNode: Node, endNode?: Node) { const lastDecorator = canHaveDecorators(startNode) ? findLast(startNode.modifiers, isDecorator) : undefined; - const start = lastDecorator ? - skipTrivia(sourceFile.text, lastDecorator.end) : - startNode.getStart(sourceFile); + const start = lastDecorator + ? skipTrivia(sourceFile.text, lastDecorator.end) + : startNode.getStart(sourceFile); return createTextSpanFromBounds(start, (endNode || startNode).getEnd()); } function textSpanEndingAtNextToken(startNode: Node, previousTokenToFindNextEndToken: Node): TextSpan { - return textSpan(startNode, findNextToken(previousTokenToFindNextEndToken, previousTokenToFindNextEndToken.parent, sourceFile)); + return textSpan( + startNode, + findNextToken(previousTokenToFindNextEndToken, previousTokenToFindNextEndToken.parent, sourceFile), + ); } function spanInNodeIfStartsOnSameLine(node: Node | undefined, otherwiseOnNode?: Node): TextSpan | undefined { @@ -127,7 +130,11 @@ export function spanInSourceFileAtLocation(sourceFile: SourceFile, position: num return spanInNode(otherwiseOnNode); } - function spanInNodeArray(nodeArray: NodeArray | undefined, node: T, match: (value: Node) => boolean) { + function spanInNodeArray( + nodeArray: NodeArray | undefined, + node: T, + match: (value: Node) => boolean, + ) { if (nodeArray) { const index = nodeArray.indexOf(node); if (index >= 0) { @@ -135,7 +142,10 @@ export function spanInSourceFileAtLocation(sourceFile: SourceFile, position: num let end = index + 1; while (start > 0 && match(nodeArray[start - 1])) start--; while (end < nodeArray.length && match(nodeArray[end])) end++; - return createTextSpanFromBounds(skipTrivia(sourceFile.text, nodeArray[start].pos), nodeArray[end - 1].end); + return createTextSpanFromBounds( + skipTrivia(sourceFile.text, nodeArray[start].pos), + nodeArray[end - 1].end, + ); } } return textSpan(node); @@ -160,7 +170,9 @@ export function spanInSourceFileAtLocation(sourceFile: SourceFile, position: num case SyntaxKind.VariableDeclaration: case SyntaxKind.PropertyDeclaration: case SyntaxKind.PropertySignature: - return spanInVariableDeclaration(node as VariableDeclaration | PropertyDeclaration | PropertySignature); + return spanInVariableDeclaration( + node as VariableDeclaration | PropertyDeclaration | PropertySignature, + ); case SyntaxKind.Parameter: return spanInParameterDeclaration(node as ParameterDeclaration); @@ -347,11 +359,11 @@ export function spanInSourceFileAtLocation(sourceFile: SourceFile, position: num // `a` or `...c` or `d: x` from // `[a, b, ...c]` or `{ a, b }` or `{ d: x }` from destructuring pattern if ( - (node.kind === SyntaxKind.Identifier || - node.kind === SyntaxKind.SpreadElement || - node.kind === SyntaxKind.PropertyAssignment || - node.kind === SyntaxKind.ShorthandPropertyAssignment) && - isArrayLiteralOrObjectLiteralDestructuringPattern(parent) + (node.kind === SyntaxKind.Identifier + || node.kind === SyntaxKind.SpreadElement + || node.kind === SyntaxKind.PropertyAssignment + || node.kind === SyntaxKind.ShorthandPropertyAssignment) + && isArrayLiteralOrObjectLiteralDestructuringPattern(parent) ) { return textSpan(node); } @@ -368,7 +380,10 @@ export function spanInSourceFileAtLocation(sourceFile: SourceFile, position: num ); } - if (operatorToken.kind === SyntaxKind.EqualsToken && isArrayLiteralOrObjectLiteralDestructuringPattern(node.parent)) { + if ( + operatorToken.kind === SyntaxKind.EqualsToken + && isArrayLiteralOrObjectLiteralDestructuringPattern(node.parent) + ) { // Set breakpoint on assignment expression element of destructuring pattern // a = expression of // [a = expression, b, c] = someExpression or @@ -415,8 +430,8 @@ export function spanInSourceFileAtLocation(sourceFile: SourceFile, position: num case SyntaxKind.PropertyAssignment: // If this is name of property assignment, set breakpoint in the initializer if ( - (node.parent as PropertyAssignment).name === node && - !isArrayLiteralOrObjectLiteralDestructuringPattern(node.parent.parent) + (node.parent as PropertyAssignment).name === node + && !isArrayLiteralOrObjectLiteralDestructuringPattern(node.parent.parent) ) { return spanInNode((node.parent as PropertyAssignment).initializer); } @@ -456,10 +471,18 @@ export function spanInSourceFileAtLocation(sourceFile: SourceFile, position: num } } - function textSpanFromVariableDeclaration(variableDeclaration: VariableDeclaration | PropertyDeclaration | PropertySignature): TextSpan { - if (isVariableDeclarationList(variableDeclaration.parent) && variableDeclaration.parent.declarations[0] === variableDeclaration) { + function textSpanFromVariableDeclaration( + variableDeclaration: VariableDeclaration | PropertyDeclaration | PropertySignature, + ): TextSpan { + if ( + isVariableDeclarationList(variableDeclaration.parent) + && variableDeclaration.parent.declarations[0] === variableDeclaration + ) { // First declaration - include let keyword - return textSpan(findPrecedingToken(variableDeclaration.pos, sourceFile, variableDeclaration.parent)!, variableDeclaration); + return textSpan( + findPrecedingToken(variableDeclaration.pos, sourceFile, variableDeclaration.parent)!, + variableDeclaration, + ); } else { // Span only on this declaration @@ -467,7 +490,9 @@ export function spanInSourceFileAtLocation(sourceFile: SourceFile, position: num } } - function spanInVariableDeclaration(variableDeclaration: VariableDeclaration | PropertyDeclaration | PropertySignature): TextSpan | undefined { + function spanInVariableDeclaration( + variableDeclaration: VariableDeclaration | PropertyDeclaration | PropertySignature, + ): TextSpan | undefined { // If declaration of for in statement, just set the span in parent if (variableDeclaration.parent.parent.kind === SyntaxKind.ForInStatement) { return spanInNode(variableDeclaration.parent.parent); @@ -482,16 +507,16 @@ export function spanInSourceFileAtLocation(sourceFile: SourceFile, position: num // Breakpoint is possible in variableDeclaration only if there is initialization // or its declaration from 'for of' if ( - (hasOnlyExpressionInitializer(variableDeclaration) && variableDeclaration.initializer) || - hasSyntacticModifier(variableDeclaration, ModifierFlags.Export) || - parent.parent.kind === SyntaxKind.ForOfStatement + (hasOnlyExpressionInitializer(variableDeclaration) && variableDeclaration.initializer) + || hasSyntacticModifier(variableDeclaration, ModifierFlags.Export) + || parent.parent.kind === SyntaxKind.ForOfStatement ) { return textSpanFromVariableDeclaration(variableDeclaration); } if ( - isVariableDeclarationList(variableDeclaration.parent) && - variableDeclaration.parent.declarations[0] !== variableDeclaration + isVariableDeclarationList(variableDeclaration.parent) + && variableDeclaration.parent.declarations[0] !== variableDeclaration ) { // If we cannot set breakpoint on this declaration, set it on previous one // Because the variable declaration may be binding pattern and @@ -503,8 +528,8 @@ export function spanInSourceFileAtLocation(sourceFile: SourceFile, position: num function canHaveSpanInParameterDeclaration(parameter: ParameterDeclaration): boolean { // Breakpoint is possible on parameter only if it has initializer, is a rest parameter, or has public or private modifier - return !!parameter.initializer || parameter.dotDotDotToken !== undefined || - hasSyntacticModifier(parameter, ModifierFlags.Public | ModifierFlags.Private); + return !!parameter.initializer || parameter.dotDotDotToken !== undefined + || hasSyntacticModifier(parameter, ModifierFlags.Public | ModifierFlags.Private); } function spanInParameterDeclaration(parameter: ParameterDeclaration): TextSpan | undefined { @@ -531,8 +556,9 @@ export function spanInSourceFileAtLocation(sourceFile: SourceFile, position: num } function canFunctionHaveSpanInWholeDeclaration(functionDeclaration: FunctionLikeDeclaration) { - return hasSyntacticModifier(functionDeclaration, ModifierFlags.Export) || - (functionDeclaration.parent.kind === SyntaxKind.ClassDeclaration && functionDeclaration.kind !== SyntaxKind.Constructor); + return hasSyntacticModifier(functionDeclaration, ModifierFlags.Export) + || (functionDeclaration.parent.kind === SyntaxKind.ClassDeclaration + && functionDeclaration.kind !== SyntaxKind.Constructor); } function spanInFunctionDeclaration(functionDeclaration: FunctionLikeDeclaration): TextSpan | undefined { @@ -562,7 +588,9 @@ export function spanInSourceFileAtLocation(sourceFile: SourceFile, position: num function spanInBlock(block: Block): TextSpan | undefined { switch (block.parent.kind) { case SyntaxKind.ModuleDeclaration: - if (getModuleInstanceState(block.parent as ModuleDeclaration) !== ModuleInstanceState.Instantiated) { + if ( + getModuleInstanceState(block.parent as ModuleDeclaration) !== ModuleInstanceState.Instantiated + ) { return undefined; } @@ -576,14 +604,19 @@ export function spanInSourceFileAtLocation(sourceFile: SourceFile, position: num // Set span on previous token if it starts on same line otherwise on the first statement of the block case SyntaxKind.ForStatement: case SyntaxKind.ForOfStatement: - return spanInNodeIfStartsOnSameLine(findPrecedingToken(block.pos, sourceFile, block.parent), block.statements[0]); + return spanInNodeIfStartsOnSameLine( + findPrecedingToken(block.pos, sourceFile, block.parent), + block.statements[0], + ); } // Default action is to set on first statement return spanInNode(block.statements[0]); } - function spanInInitializerOfForLike(forLikeStatement: ForStatement | ForOfStatement | ForInStatement): TextSpan | undefined { + function spanInInitializerOfForLike( + forLikeStatement: ForStatement | ForOfStatement | ForInStatement, + ): TextSpan | undefined { if (forLikeStatement.initializer!.kind === SyntaxKind.VariableDeclarationList) { // Declaration list - set breakpoint in first declaration const variableDeclarationList = forLikeStatement.initializer as VariableDeclarationList; @@ -612,7 +645,10 @@ export function spanInSourceFileAtLocation(sourceFile: SourceFile, position: num function spanInBindingPattern(bindingPattern: BindingPattern): TextSpan | undefined { // Set breakpoint in first binding element - const firstBindingElement = forEach(bindingPattern.elements, element => element.kind !== SyntaxKind.OmittedExpression ? element : undefined); + const firstBindingElement = forEach( + bindingPattern.elements, + element => element.kind !== SyntaxKind.OmittedExpression ? element : undefined, + ); if (firstBindingElement) { return spanInNode(firstBindingElement); @@ -627,11 +663,17 @@ export function spanInSourceFileAtLocation(sourceFile: SourceFile, position: num return textSpanFromVariableDeclaration(bindingPattern.parent as VariableDeclaration); } - function spanInArrayLiteralOrObjectLiteralDestructuringPattern(node: DestructuringPattern): TextSpan | undefined { + function spanInArrayLiteralOrObjectLiteralDestructuringPattern( + node: DestructuringPattern, + ): TextSpan | undefined { Debug.assert(node.kind !== SyntaxKind.ArrayBindingPattern && node.kind !== SyntaxKind.ObjectBindingPattern); - const elements: NodeArray = node.kind === SyntaxKind.ArrayLiteralExpression ? node.elements : node.properties; + const elements: NodeArray = + node.kind === SyntaxKind.ArrayLiteralExpression ? node.elements : node.properties; - const firstBindingElement = forEach(elements, element => element.kind !== SyntaxKind.OmittedExpression ? element : undefined); + const firstBindingElement = forEach( + elements, + element => element.kind !== SyntaxKind.OmittedExpression ? element : undefined, + ); if (firstBindingElement) { return spanInNode(firstBindingElement); @@ -649,11 +691,19 @@ export function spanInSourceFileAtLocation(sourceFile: SourceFile, position: num switch (node.parent.kind) { case SyntaxKind.EnumDeclaration: const enumDeclaration = node.parent as EnumDeclaration; - return spanInNodeIfStartsOnSameLine(findPrecedingToken(node.pos, sourceFile, node.parent), enumDeclaration.members.length ? enumDeclaration.members[0] : enumDeclaration.getLastToken(sourceFile)); + return spanInNodeIfStartsOnSameLine( + findPrecedingToken(node.pos, sourceFile, node.parent), + enumDeclaration.members.length ? enumDeclaration.members[0] + : enumDeclaration.getLastToken(sourceFile), + ); case SyntaxKind.ClassDeclaration: const classDeclaration = node.parent as ClassDeclaration; - return spanInNodeIfStartsOnSameLine(findPrecedingToken(node.pos, sourceFile, node.parent), classDeclaration.members.length ? classDeclaration.members[0] : classDeclaration.getLastToken(sourceFile)); + return spanInNodeIfStartsOnSameLine( + findPrecedingToken(node.pos, sourceFile, node.parent), + classDeclaration.members.length ? classDeclaration.members[0] + : classDeclaration.getLastToken(sourceFile), + ); case SyntaxKind.CaseBlock: return spanInNodeIfStartsOnSameLine(node.parent.parent, (node.parent as CaseBlock).clauses[0]); @@ -667,7 +717,10 @@ export function spanInSourceFileAtLocation(sourceFile: SourceFile, position: num switch (node.parent.kind) { case SyntaxKind.ModuleBlock: // If this is not an instantiated module block, no bp span - if (getModuleInstanceState(node.parent.parent as ModuleDeclaration) !== ModuleInstanceState.Instantiated) { + if ( + getModuleInstanceState(node.parent.parent as ModuleDeclaration) + !== ModuleInstanceState.Instantiated + ) { return undefined; } // falls through @@ -733,9 +786,9 @@ export function spanInSourceFileAtLocation(sourceFile: SourceFile, position: num function spanInOpenParenToken(node: Node): TextSpan | undefined { if ( - node.parent.kind === SyntaxKind.DoStatement || // Go to while keyword and do action instead - node.parent.kind === SyntaxKind.CallExpression || - node.parent.kind === SyntaxKind.NewExpression + node.parent.kind === SyntaxKind.DoStatement // Go to while keyword and do action instead + || node.parent.kind === SyntaxKind.CallExpression + || node.parent.kind === SyntaxKind.NewExpression ) { return spanInPreviousNode(node); } @@ -777,9 +830,9 @@ export function spanInSourceFileAtLocation(sourceFile: SourceFile, position: num function spanInColonToken(node: Node): TextSpan | undefined { // Is this : specifying return annotation of the function declaration if ( - isFunctionLike(node.parent) || - node.parent.kind === SyntaxKind.PropertyAssignment || - node.parent.kind === SyntaxKind.Parameter + isFunctionLike(node.parent) + || node.parent.kind === SyntaxKind.PropertyAssignment + || node.parent.kind === SyntaxKind.Parameter ) { return spanInPreviousNode(node); } diff --git a/src/services/callHierarchy.ts b/src/services/callHierarchy.ts index aa8373081f984..ea702adb678fd 100644 --- a/src/services/callHierarchy.ts +++ b/src/services/callHierarchy.ts @@ -183,7 +183,9 @@ function isValidCallHierarchyDeclaration(node: Node): node is CallHierarchyDecla } /** Gets the node that can be used as a reference to a call hierarchy declaration. */ -function getCallHierarchyDeclarationReferenceNode(node: Exclude) { +function getCallHierarchyDeclarationReferenceNode( + node: Exclude, +) { if (isSourceFile(node)) return node; if (isNamedDeclaration(node)) return node.name; if (isConstNamedExpression(node)) return node.parent.name; @@ -195,13 +197,19 @@ function isDefaultModifier(node: Node) { } /** Gets the symbol for a call hierarchy declaration. */ -function getSymbolOfCallHierarchyDeclaration(typeChecker: TypeChecker, node: Exclude) { +function getSymbolOfCallHierarchyDeclaration( + typeChecker: TypeChecker, + node: Exclude, +) { const location = getCallHierarchyDeclarationReferenceNode(node); return location && typeChecker.getSymbolAtLocation(location); } /** Gets the text and range for the name of a call hierarchy declaration. */ -function getCallHierarchyItemName(program: Program, node: CallHierarchyDeclaration): { text: string; pos: number; end: number; } { +function getCallHierarchyItemName( + program: Program, + node: CallHierarchyDeclaration, +): { text: string; pos: number; end: number; } { if (isSourceFile(node)) { return { text: node.fileName, pos: 0, end: 0 }; } @@ -223,15 +231,15 @@ function getCallHierarchyItemName(program: Program, node: CallHierarchyDeclarati return { text: `${prefix}static {}`, pos, end }; } - const declName = isConstNamedExpression(node) ? node.parent.name : - Debug.checkDefined(getNameOfDeclaration(node), "Expected call hierarchy item to have a name"); + const declName = isConstNamedExpression(node) ? node.parent.name + : Debug.checkDefined(getNameOfDeclaration(node), "Expected call hierarchy item to have a name"); - let text = isIdentifier(declName) ? idText(declName) : - isStringOrNumericLiteralLike(declName) ? declName.text : - isComputedPropertyName(declName) ? - isStringOrNumericLiteralLike(declName.expression) ? declName.expression.text : - undefined : - undefined; + let text = isIdentifier(declName) ? idText(declName) + : isStringOrNumericLiteralLike(declName) ? declName.text + : isComputedPropertyName(declName) + ? isStringOrNumericLiteralLike(declName.expression) ? declName.expression.text + : undefined + : undefined; if (text === undefined) { const typeChecker = program.getTypeChecker(); const symbol = typeChecker.getSymbolAtLocation(declName); @@ -242,14 +250,19 @@ function getCallHierarchyItemName(program: Program, node: CallHierarchyDeclarati if (text === undefined) { // get the text from printing the node on a single line without comments... const printer = createPrinterWithRemoveCommentsOmitTrailingSemicolon(); - text = usingSingleLineStringWriter(writer => printer.writeNode(EmitHint.Unspecified, node, node.getSourceFile(), writer)); + text = usingSingleLineStringWriter(writer => + printer.writeNode(EmitHint.Unspecified, node, node.getSourceFile(), writer) + ); } return { text, pos: declName.getStart(), end: declName.getEnd() }; } function getCallHierarchItemContainerName(node: CallHierarchyDeclaration): string | undefined { if (isConstNamedExpression(node)) { - if (isModuleBlock(node.parent.parent.parent.parent) && isIdentifier(node.parent.parent.parent.parent.parent.name)) { + if ( + isModuleBlock(node.parent.parent.parent.parent) + && isIdentifier(node.parent.parent.parent.parent.parent.name) + ) { return node.parent.parent.parent.parent.parent.name.getText(); } return; @@ -273,9 +286,18 @@ function getCallHierarchItemContainerName(node: CallHierarchyDeclaration): strin } /** Finds the implementation of a function-like declaration, if one exists. */ -function findImplementation(typeChecker: TypeChecker, node: Extract): Extract | undefined; -function findImplementation(typeChecker: TypeChecker, node: FunctionLikeDeclaration): FunctionLikeDeclaration | undefined; -function findImplementation(typeChecker: TypeChecker, node: FunctionLikeDeclaration): FunctionLikeDeclaration | undefined { +function findImplementation( + typeChecker: TypeChecker, + node: Extract, +): Extract | undefined; +function findImplementation( + typeChecker: TypeChecker, + node: FunctionLikeDeclaration, +): FunctionLikeDeclaration | undefined; +function findImplementation( + typeChecker: TypeChecker, + node: FunctionLikeDeclaration, +): FunctionLikeDeclaration | undefined { if (node.body) { return node; } @@ -284,7 +306,10 @@ function findImplementation(typeChecker: TypeChecker, node: FunctionLikeDeclarat } if (isFunctionDeclaration(node) || isMethodDeclaration(node)) { const symbol = getSymbolOfCallHierarchyDeclaration(typeChecker, node); - if (symbol && symbol.valueDeclaration && isFunctionLikeDeclaration(symbol.valueDeclaration) && symbol.valueDeclaration.body) { + if ( + symbol && symbol.valueDeclaration && isFunctionLikeDeclaration(symbol.valueDeclaration) + && symbol.valueDeclaration.body + ) { return symbol.valueDeclaration; } return undefined; @@ -292,7 +317,10 @@ function findImplementation(typeChecker: TypeChecker, node: FunctionLikeDeclarat return node; } -function findAllInitialDeclarations(typeChecker: TypeChecker, node: Exclude) { +function findAllInitialDeclarations( + typeChecker: TypeChecker, + node: Exclude, +) { const symbol = getSymbolOfCallHierarchyDeclaration(typeChecker, node); let declarations: CallHierarchyDeclaration[] | undefined; if (symbol && symbol.declarations) { @@ -314,14 +342,17 @@ function findAllInitialDeclarations(typeChecker: TypeChecker, node: Exclude createTextSpanFromRange(entry.range))); + return createCallHierarchyIncomingCall( + createCallHierarchyItem(program, entries[0].declaration), + map(entries, entry => createTextSpanFromRange(entry.range)), + ); } /** @@ -460,23 +503,49 @@ function convertCallSiteGroupToIncomingCall(program: Program, entries: readonly * * @internal */ -export function getIncomingCalls(program: Program, declaration: CallHierarchyDeclaration, cancellationToken: CancellationToken): CallHierarchyIncomingCall[] { +export function getIncomingCalls( + program: Program, + declaration: CallHierarchyDeclaration, + cancellationToken: CancellationToken, +): CallHierarchyIncomingCall[] { // Source files and modules have no incoming calls. if (isSourceFile(declaration) || isModuleDeclaration(declaration) || isClassStaticBlockDeclaration(declaration)) { return []; } const location = getCallHierarchyDeclarationReferenceNode(declaration); - const calls = filter(FindAllReferences.findReferenceOrRenameEntries(program, cancellationToken, program.getSourceFiles(), location, /*position*/ 0, { use: FindAllReferences.FindReferencesUse.References }, convertEntryToCallSite), isDefined); - return calls ? group(calls, getCallSiteGroupKey, entries => convertCallSiteGroupToIncomingCall(program, entries)) : []; + const calls = filter( + FindAllReferences.findReferenceOrRenameEntries( + program, + cancellationToken, + program.getSourceFiles(), + location, + /*position*/ 0, + { use: FindAllReferences.FindReferencesUse.References }, + convertEntryToCallSite, + ), + isDefined, + ); + return calls ? group(calls, getCallSiteGroupKey, entries => convertCallSiteGroupToIncomingCall(program, entries)) + : []; } function createCallSiteCollector(program: Program, callSites: CallSite[]): (node: Node | undefined) => void { - function recordCallSite(node: CallExpression | NewExpression | TaggedTemplateExpression | PropertyAccessExpression | ElementAccessExpression | Decorator | JsxOpeningLikeElement | ClassStaticBlockDeclaration) { - const target = isTaggedTemplateExpression(node) ? node.tag : - isJsxOpeningLikeElement(node) ? node.tagName : - isAccessExpression(node) ? node : - isClassStaticBlockDeclaration(node) ? node : - node.expression; + function recordCallSite( + node: + | CallExpression + | NewExpression + | TaggedTemplateExpression + | PropertyAccessExpression + | ElementAccessExpression + | Decorator + | JsxOpeningLikeElement + | ClassStaticBlockDeclaration, + ) { + const target = isTaggedTemplateExpression(node) ? node.tag + : isJsxOpeningLikeElement(node) ? node.tagName + : isAccessExpression(node) ? node + : isClassStaticBlockDeclaration(node) ? node + : node.expression; const declaration = resolveCallHierarchyDeclaration(program, target); if (declaration) { const range = createTextRangeFromNode(target, node.getSourceFile()); @@ -593,7 +662,11 @@ function collectCallSitesOfModuleDeclaration(node: ModuleDeclaration, collect: ( } } -function collectCallSitesOfFunctionLikeDeclaration(typeChecker: TypeChecker, node: FunctionLikeDeclaration, collect: (node: Node | undefined) => void) { +function collectCallSitesOfFunctionLikeDeclaration( + typeChecker: TypeChecker, + node: FunctionLikeDeclaration, + collect: (node: Node | undefined) => void, +) { const implementation = findImplementation(typeChecker, node); if (implementation) { forEach(implementation.parameters, collect); @@ -601,7 +674,10 @@ function collectCallSitesOfFunctionLikeDeclaration(typeChecker: TypeChecker, nod } } -function collectCallSitesOfClassStaticBlockDeclaration(node: ClassStaticBlockDeclaration, collect: (node: Node | undefined) => void) { +function collectCallSitesOfClassStaticBlockDeclaration( + node: ClassStaticBlockDeclaration, + collect: (node: Node | undefined) => void, +) { collect(node.body); } @@ -664,7 +740,10 @@ function createCallHierarchyOutgoingCall(to: CallHierarchyItem, fromSpans: TextS } function convertCallSiteGroupToOutgoingCall(program: Program, entries: readonly CallSite[]) { - return createCallHierarchyOutgoingCall(createCallHierarchyItem(program, entries[0].declaration), map(entries, entry => createTextSpanFromRange(entry.range))); + return createCallHierarchyOutgoingCall( + createCallHierarchyItem(program, entries[0].declaration), + map(entries, entry => createTextSpanFromRange(entry.range)), + ); } /** @@ -676,5 +755,9 @@ export function getOutgoingCalls(program: Program, declaration: CallHierarchyDec if (declaration.flags & NodeFlags.Ambient || isMethodSignature(declaration)) { return []; } - return group(collectCallSites(program, declaration), getCallSiteGroupKey, entries => convertCallSiteGroupToOutgoingCall(program, entries)); + return group( + collectCallSites(program, declaration), + getCallSiteGroupKey, + entries => convertCallSiteGroupToOutgoingCall(program, entries), + ); } diff --git a/src/services/classifier.ts b/src/services/classifier.ts index df9b7d3e14880..da95cf9c8e7c3 100644 --- a/src/services/classifier.ts +++ b/src/services/classifier.ts @@ -81,13 +81,24 @@ import { export function createClassifier(): Classifier { const scanner = createScanner(ScriptTarget.Latest, /*skipTrivia*/ false); - function getClassificationsForLine(text: string, lexState: EndOfLineState, syntacticClassifierAbsent: boolean): ClassificationResult { - return convertClassificationsToResult(getEncodedLexicalClassifications(text, lexState, syntacticClassifierAbsent), text); + function getClassificationsForLine( + text: string, + lexState: EndOfLineState, + syntacticClassifierAbsent: boolean, + ): ClassificationResult { + return convertClassificationsToResult( + getEncodedLexicalClassifications(text, lexState, syntacticClassifierAbsent), + text, + ); } // If there is a syntactic classifier ('syntacticClassifierAbsent' is false), // we will be more conservative in order to avoid conflicting with the syntactic classifier. - function getEncodedLexicalClassifications(text: string, lexState: EndOfLineState, syntacticClassifierAbsent: boolean): Classifications { + function getEncodedLexicalClassifications( + text: string, + lexState: EndOfLineState, + syntacticClassifierAbsent: boolean, + ): Classifications { let token = SyntaxKind.Unknown; let lastNonTriviaToken = SyntaxKind.Unknown; @@ -167,7 +178,10 @@ export function createClassifier(): Classifier { switch (token) { case SyntaxKind.SlashToken: case SyntaxKind.SlashEqualsToken: - if (!noRegexTable[lastNonTriviaToken] && scanner.reScanSlashToken() === SyntaxKind.RegularExpressionLiteral) { + if ( + !noRegexTable[lastNonTriviaToken] + && scanner.reScanSlashToken() === SyntaxKind.RegularExpressionLiteral + ) { token = SyntaxKind.RegularExpressionLiteral; } break; @@ -221,11 +235,19 @@ export function createClassifier(): Classifier { templateStack.pop(); } else { - Debug.assertEqual(token, SyntaxKind.TemplateMiddle, "Should have been a template middle."); + Debug.assertEqual( + token, + SyntaxKind.TemplateMiddle, + "Should have been a template middle.", + ); } } else { - Debug.assertEqual(lastTemplateStackToken, SyntaxKind.OpenBraceToken, "Should have been an open brace"); + Debug.assertEqual( + lastTemplateStackToken, + SyntaxKind.OpenBraceToken, + "Should have been an open brace", + ); templateStack.pop(); } } @@ -238,7 +260,9 @@ export function createClassifier(): Classifier { if (lastNonTriviaToken === SyntaxKind.DotToken) { token = SyntaxKind.Identifier; } - else if (isKeyword(lastNonTriviaToken) && isKeyword(token) && !canFollow(lastNonTriviaToken, token)) { + else if ( + isKeyword(lastNonTriviaToken) && isKeyword(token) && !canFollow(lastNonTriviaToken, token) + ) { // We have two keywords in a row. Only treat the second as a keyword if // it's a sequence that could legally occur in the language. Otherwise // treat it as an identifier. This way, if someone writes "private var" @@ -278,7 +302,11 @@ const noRegexTable: true[] = arrayToNumericMap( () => true, ); -function getNewEndOfLineState(scanner: Scanner, token: SyntaxKind, lastOnTemplateStack: SyntaxKind | undefined): EndOfLineState | undefined { +function getNewEndOfLineState( + scanner: Scanner, + token: SyntaxKind, + lastOnTemplateStack: SyntaxKind | undefined, +): EndOfLineState | undefined { switch (token) { case SyntaxKind.StringLiteral: { // Check to see if we finished up on a multiline string literal. @@ -293,7 +321,8 @@ function getNewEndOfLineState(scanner: Scanner, token: SyntaxKind, lastOnTemplat // If we have an odd number of backslashes, then the multiline string is unclosed if ((numBackslashes & 1) === 0) return undefined; - return tokenText.charCodeAt(0) === CharacterCodes.doubleQuote ? EndOfLineState.InDoubleQuoteStringLiteral : EndOfLineState.InSingleQuoteStringLiteral; + return tokenText.charCodeAt(0) === CharacterCodes.doubleQuote ? EndOfLineState.InDoubleQuoteStringLiteral + : EndOfLineState.InSingleQuoteStringLiteral; } case SyntaxKind.MultiLineCommentTrivia: // Check to see if the multiline comment was unclosed. @@ -309,14 +338,24 @@ function getNewEndOfLineState(scanner: Scanner, token: SyntaxKind, lastOnTemplat case SyntaxKind.NoSubstitutionTemplateLiteral: return EndOfLineState.InTemplateHeadOrNoSubstitutionTemplate; default: - return Debug.fail("Only 'NoSubstitutionTemplateLiteral's and 'TemplateTail's can be unterminated; got SyntaxKind #" + token); + return Debug.fail( + "Only 'NoSubstitutionTemplateLiteral's and 'TemplateTail's can be unterminated; got SyntaxKind #" + + token, + ); } } - return lastOnTemplateStack === SyntaxKind.TemplateHead ? EndOfLineState.InTemplateSubstitutionPosition : undefined; + return lastOnTemplateStack === SyntaxKind.TemplateHead ? EndOfLineState.InTemplateSubstitutionPosition + : undefined; } } -function pushEncodedClassification(start: number, end: number, offset: number, classification: ClassificationType, result: number[]): void { +function pushEncodedClassification( + start: number, + end: number, + offset: number, + classification: ClassificationType, + result: number[], +): void { if (classification === ClassificationType.whiteSpace) { // Don't bother with whitespace classifications. They're not needed. return; @@ -545,8 +584,16 @@ function classFromKind(token: SyntaxKind): ClassificationType { } /** @internal */ -export function getSemanticClassifications(typeChecker: TypeChecker, cancellationToken: CancellationToken, sourceFile: SourceFile, classifiableNames: ReadonlySet<__String>, span: TextSpan): ClassifiedSpan[] { - return convertClassificationsToSpans(getEncodedSemanticClassifications(typeChecker, cancellationToken, sourceFile, classifiableNames, span)); +export function getSemanticClassifications( + typeChecker: TypeChecker, + cancellationToken: CancellationToken, + sourceFile: SourceFile, + classifiableNames: ReadonlySet<__String>, + span: TextSpan, +): ClassifiedSpan[] { + return convertClassificationsToSpans( + getEncodedSemanticClassifications(typeChecker, cancellationToken, sourceFile, classifiableNames, span), + ); } function checkForClassificationCancellation(cancellationToken: CancellationToken, kind: SyntaxKind) { @@ -573,7 +620,13 @@ function checkForClassificationCancellation(cancellationToken: CancellationToken } /** @internal */ -export function getEncodedSemanticClassifications(typeChecker: TypeChecker, cancellationToken: CancellationToken, sourceFile: SourceFile, classifiableNames: ReadonlySet<__String>, span: TextSpan): Classifications { +export function getEncodedSemanticClassifications( + typeChecker: TypeChecker, + cancellationToken: CancellationToken, + sourceFile: SourceFile, + classifiableNames: ReadonlySet<__String>, + span: TextSpan, +): Classifications { const spans: number[] = []; sourceFile.forEachChild(function cb(node: Node): void { // Only walk into nodes that intersect the requested span. @@ -606,7 +659,11 @@ export function getEncodedSemanticClassifications(typeChecker: TypeChecker, canc } } -function classifySymbol(symbol: Symbol, meaningAtPosition: SemanticMeaning, checker: TypeChecker): ClassificationType | undefined { +function classifySymbol( + symbol: Symbol, + meaningAtPosition: SemanticMeaning, + checker: TypeChecker, +): ClassificationType | undefined { const flags = symbol.getFlags(); if ((flags & SymbolFlags.Classifiable) === SymbolFlags.None) { return undefined; @@ -624,13 +681,16 @@ function classifySymbol(symbol: Symbol, meaningAtPosition: SemanticMeaning, chec // Only classify a module as such if // - It appears in a namespace context. // - There exists a module declaration which actually impacts the value side. - return meaningAtPosition & SemanticMeaning.Namespace || meaningAtPosition & SemanticMeaning.Value && hasValueSideModule(symbol) ? ClassificationType.moduleName : undefined; + return meaningAtPosition & SemanticMeaning.Namespace + || meaningAtPosition & SemanticMeaning.Value && hasValueSideModule(symbol) + ? ClassificationType.moduleName : undefined; } else if (flags & SymbolFlags.Alias) { return classifySymbol(checker.getAliasedSymbol(symbol), meaningAtPosition, checker); } else if (meaningAtPosition & SemanticMeaning.Type) { - return flags & SymbolFlags.Interface ? ClassificationType.interfaceName : flags & SymbolFlags.TypeParameter ? ClassificationType.typeParameterName : undefined; + return flags & SymbolFlags.Interface ? ClassificationType.interfaceName + : flags & SymbolFlags.TypeParameter ? ClassificationType.typeParameterName : undefined; } else { return undefined; @@ -639,7 +699,12 @@ function classifySymbol(symbol: Symbol, meaningAtPosition: SemanticMeaning, chec /** Returns true if there exists a module that introduces entities on the value side. */ function hasValueSideModule(symbol: Symbol): boolean { - return some(symbol.declarations, declaration => isModuleDeclaration(declaration) && getModuleInstanceState(declaration) === ModuleInstanceState.Instantiated); + return some( + symbol.declarations, + declaration => + isModuleDeclaration(declaration) + && getModuleInstanceState(declaration) === ModuleInstanceState.Instantiated, + ); } function getClassificationTypeName(type: ClassificationType): ClassificationTypeNames { @@ -712,18 +777,36 @@ function convertClassificationsToSpans(classifications: Classifications): Classi } /** @internal */ -export function getSyntacticClassifications(cancellationToken: CancellationToken, sourceFile: SourceFile, span: TextSpan): ClassifiedSpan[] { +export function getSyntacticClassifications( + cancellationToken: CancellationToken, + sourceFile: SourceFile, + span: TextSpan, +): ClassifiedSpan[] { return convertClassificationsToSpans(getEncodedSyntacticClassifications(cancellationToken, sourceFile, span)); } /** @internal */ -export function getEncodedSyntacticClassifications(cancellationToken: CancellationToken, sourceFile: SourceFile, span: TextSpan): Classifications { +export function getEncodedSyntacticClassifications( + cancellationToken: CancellationToken, + sourceFile: SourceFile, + span: TextSpan, +): Classifications { const spanStart = span.start; const spanLength = span.length; // Make a scanner we can get trivia from. - const triviaScanner = createScanner(ScriptTarget.Latest, /*skipTrivia*/ false, sourceFile.languageVariant, sourceFile.text); - const mergeConflictScanner = createScanner(ScriptTarget.Latest, /*skipTrivia*/ false, sourceFile.languageVariant, sourceFile.text); + const triviaScanner = createScanner( + ScriptTarget.Latest, + /*skipTrivia*/ false, + sourceFile.languageVariant, + sourceFile.text, + ); + const mergeConflictScanner = createScanner( + ScriptTarget.Latest, + /*skipTrivia*/ false, + sourceFile.languageVariant, + sourceFile.text, + ); const result: number[] = []; processElement(sourceFile); @@ -836,7 +919,11 @@ export function getEncodedSyntacticClassifications(cancellationToken: Cancellati } pushClassification(tag.pos, 1, ClassificationType.punctuation); // "@" - pushClassification(tag.tagName.pos, tag.tagName.end - tag.tagName.pos, ClassificationType.docCommentTagName); // e.g. "param" + pushClassification( + tag.tagName.pos, + tag.tagName.end - tag.tagName.pos, + ClassificationType.docCommentTagName, + ); // e.g. "param" pos = tag.tagName.end; let commentStart = tag.tagName.end; @@ -858,7 +945,9 @@ export function getEncodedSyntacticClassifications(cancellationToken: Cancellati break; case SyntaxKind.JSDocTypedefTag: const type = tag as JSDocTypedefTag; - commentStart = type.typeExpression?.kind === SyntaxKind.JSDocTypeExpression && type.fullName?.end || type.typeExpression?.end || commentStart; + commentStart = + type.typeExpression?.kind === SyntaxKind.JSDocTypeExpression && type.fullName?.end + || type.typeExpression?.end || commentStart; break; case SyntaxKind.JSDocCallbackTag: commentStart = (tag as JSDocCallbackTag).typeExpression.end; @@ -1126,20 +1215,20 @@ export function getEncodedSyntacticClassifications(cancellationToken: Cancellati if (tokenKind === SyntaxKind.EqualsToken) { // the '=' in a variable declaration is special cased here. if ( - parent.kind === SyntaxKind.VariableDeclaration || - parent.kind === SyntaxKind.PropertyDeclaration || - parent.kind === SyntaxKind.Parameter || - parent.kind === SyntaxKind.JsxAttribute + parent.kind === SyntaxKind.VariableDeclaration + || parent.kind === SyntaxKind.PropertyDeclaration + || parent.kind === SyntaxKind.Parameter + || parent.kind === SyntaxKind.JsxAttribute ) { return ClassificationType.operator; } } if ( - parent.kind === SyntaxKind.BinaryExpression || - parent.kind === SyntaxKind.PrefixUnaryExpression || - parent.kind === SyntaxKind.PostfixUnaryExpression || - parent.kind === SyntaxKind.ConditionalExpression + parent.kind === SyntaxKind.BinaryExpression + || parent.kind === SyntaxKind.PrefixUnaryExpression + || parent.kind === SyntaxKind.PostfixUnaryExpression + || parent.kind === SyntaxKind.ConditionalExpression ) { return ClassificationType.operator; } @@ -1154,7 +1243,8 @@ export function getEncodedSyntacticClassifications(cancellationToken: Cancellati return ClassificationType.bigintLiteral; } else if (tokenKind === SyntaxKind.StringLiteral) { - return token && token.parent.kind === SyntaxKind.JsxAttribute ? ClassificationType.jsxAttributeStringLiteralValue : ClassificationType.stringLiteral; + return token && token.parent.kind === SyntaxKind.JsxAttribute + ? ClassificationType.jsxAttributeStringLiteralValue : ClassificationType.stringLiteral; } else if (tokenKind === SyntaxKind.RegularExpressionLiteral) { // TODO: we should get another classification type for these literals. @@ -1197,7 +1287,8 @@ export function getEncodedSyntacticClassifications(cancellationToken: Cancellati return; case SyntaxKind.Parameter: if ((token.parent as ParameterDeclaration).name === token) { - return isThisIdentifier(token) ? ClassificationType.keyword : ClassificationType.parameterName; + return isThisIdentifier(token) ? ClassificationType.keyword + : ClassificationType.parameterName; } return; } diff --git a/src/services/classifier2020.ts b/src/services/classifier2020.ts index 1fa90584974f5..56e97cc0278de 100644 --- a/src/services/classifier2020.ts +++ b/src/services/classifier2020.ts @@ -82,7 +82,12 @@ export const enum TokenModifier { * * @internal */ -export function getSemanticClassifications(program: Program, cancellationToken: CancellationToken, sourceFile: SourceFile, span: TextSpan): ClassifiedSpan2020[] { +export function getSemanticClassifications( + program: Program, + cancellationToken: CancellationToken, + sourceFile: SourceFile, + span: TextSpan, +): ClassifiedSpan2020[] { const classifications = getEncodedSemanticClassifications(program, cancellationToken, sourceFile, span); Debug.assert(classifications.spans.length % 3 === 0); @@ -99,18 +104,32 @@ export function getSemanticClassifications(program: Program, cancellationToken: } /** @internal */ -export function getEncodedSemanticClassifications(program: Program, cancellationToken: CancellationToken, sourceFile: SourceFile, span: TextSpan): Classifications { +export function getEncodedSemanticClassifications( + program: Program, + cancellationToken: CancellationToken, + sourceFile: SourceFile, + span: TextSpan, +): Classifications { return { spans: getSemanticTokens(program, sourceFile, span, cancellationToken), endOfLineState: EndOfLineState.None, }; } -function getSemanticTokens(program: Program, sourceFile: SourceFile, span: TextSpan, cancellationToken: CancellationToken): number[] { +function getSemanticTokens( + program: Program, + sourceFile: SourceFile, + span: TextSpan, + cancellationToken: CancellationToken, +): number[] { const resultTokens: number[] = []; const collector = (node: Node, typeIdx: number, modifierSet: number) => { - resultTokens.push(node.getStart(sourceFile), node.getWidth(sourceFile), ((typeIdx + 1) << TokenEncodingConsts.typeOffset) + modifierSet); + resultTokens.push( + node.getStart(sourceFile), + node.getWidth(sourceFile), + ((typeIdx + 1) << TokenEncodingConsts.typeOffset) + modifierSet, + ); }; if (program && sourceFile) { @@ -119,7 +138,13 @@ function getSemanticTokens(program: Program, sourceFile: SourceFile, span: TextS return resultTokens; } -function collectTokens(program: Program, sourceFile: SourceFile, span: TextSpan, collector: (node: Node, tokenType: number, tokenModifier: number) => void, cancellationToken: CancellationToken) { +function collectTokens( + program: Program, + sourceFile: SourceFile, + span: TextSpan, + collector: (node: Node, tokenType: number, tokenModifier: number) => void, + cancellationToken: CancellationToken, +) { const typeChecker = program.getTypeChecker(); let inJSXElement = false; @@ -157,7 +182,8 @@ function collectTokens(program: Program, sourceFile: SourceFile, span: TextSpan, if (typeIdx !== undefined) { let modifierSet = 0; if (node.parent) { - const parentIsDeclaration = isBindingElement(node.parent) || tokenFromDeclarationMapping.get(node.parent.kind) === typeIdx; + const parentIsDeclaration = isBindingElement(node.parent) + || tokenFromDeclarationMapping.get(node.parent.kind) === typeIdx; if (parentIsDeclaration && (node.parent as NamedDeclaration).name === node) { modifierSet = 1 << TokenModifier.declaration; } @@ -181,18 +207,27 @@ function collectTokens(program: Program, sourceFile: SourceFile, span: TextSpan, modifierSet |= 1 << TokenModifier.async; } if (typeIdx !== TokenType.class && typeIdx !== TokenType.interface) { - if ((modifiers & ModifierFlags.Readonly) || (nodeFlags & NodeFlags.Const) || (symbol.getFlags() & SymbolFlags.EnumMember)) { + if ( + (modifiers & ModifierFlags.Readonly) || (nodeFlags & NodeFlags.Const) + || (symbol.getFlags() & SymbolFlags.EnumMember) + ) { modifierSet |= 1 << TokenModifier.readonly; } } - if ((typeIdx === TokenType.variable || typeIdx === TokenType.function) && isLocalDeclaration(decl, sourceFile)) { + if ( + (typeIdx === TokenType.variable || typeIdx === TokenType.function) + && isLocalDeclaration(decl, sourceFile) + ) { modifierSet |= 1 << TokenModifier.local; } if (program.isSourceFileDefaultLibrary(decl.getSourceFile())) { modifierSet |= 1 << TokenModifier.defaultLibrary; } } - else if (symbol.declarations && symbol.declarations.some(d => program.isSourceFileDefaultLibrary(d.getSourceFile()))) { + else if ( + symbol.declarations + && symbol.declarations.some(d => program.isSourceFileDefaultLibrary(d.getSourceFile())) + ) { modifierSet |= 1 << TokenModifier.defaultLibrary; } @@ -244,7 +279,10 @@ function reclassifyByType(typeChecker: TypeChecker, node: Node, typeIdx: TokenTy if (typeIdx !== TokenType.parameter && test(t => t.getConstructSignatures().length > 0)) { return TokenType.class; } - if (test(t => t.getCallSignatures().length > 0) && !test(t => t.getProperties().length > 0) || isExpressionInCallExpression(node)) { + if ( + test(t => t.getCallSignatures().length > 0) && !test(t => t.getProperties().length > 0) + || isExpressionInCallExpression(node) + ) { return typeIdx === TokenType.property ? TokenType.member : TokenType.function; } } @@ -257,7 +295,8 @@ function isLocalDeclaration(decl: Declaration, sourceFile: SourceFile): boolean decl = getDeclarationForBindingElement(decl); } if (isVariableDeclaration(decl)) { - return (!isSourceFile(decl.parent.parent.parent) || isCatchClause(decl.parent)) && decl.getSourceFile() === sourceFile; + return (!isSourceFile(decl.parent.parent.parent) || isCatchClause(decl.parent)) + && decl.getSourceFile() === sourceFile; } else if (isFunctionDeclaration(decl)) { return !isSourceFile(decl.parent) && decl.getSourceFile() === sourceFile; @@ -289,7 +328,8 @@ function isExpressionInCallExpression(node: Node): boolean { } function isRightSideOfQualifiedNameOrPropertyAccess(node: Node): boolean { - return (isQualifiedName(node.parent) && node.parent.right === node) || (isPropertyAccessExpression(node.parent) && node.parent.name === node); + return (isQualifiedName(node.parent) && node.parent.right === node) + || (isPropertyAccessExpression(node.parent) && node.parent.name === node); } const tokenFromDeclarationMapping = new Map([ diff --git a/src/services/codeFixProvider.ts b/src/services/codeFixProvider.ts index 7ca63871fb2de..2ae0f7d8745ec 100644 --- a/src/services/codeFixProvider.ts +++ b/src/services/codeFixProvider.ts @@ -28,21 +28,66 @@ const errorCodeToFixes = createMultiMap(); const fixIdToRegistration = new Map(); /** @internal */ -export function createCodeFixActionWithoutFixAll(fixName: string, changes: FileTextChanges[], description: DiagnosticOrDiagnosticAndArguments) { - return createCodeFixActionWorker(fixName, diagnosticToString(description), changes, /*fixId*/ undefined, /*fixAllDescription*/ undefined); +export function createCodeFixActionWithoutFixAll( + fixName: string, + changes: FileTextChanges[], + description: DiagnosticOrDiagnosticAndArguments, +) { + return createCodeFixActionWorker( + fixName, + diagnosticToString(description), + changes, + /*fixId*/ undefined, + /*fixAllDescription*/ undefined, + ); } /** @internal */ -export function createCodeFixAction(fixName: string, changes: FileTextChanges[], description: DiagnosticOrDiagnosticAndArguments, fixId: {}, fixAllDescription: DiagnosticOrDiagnosticAndArguments, command?: CodeActionCommand): CodeFixAction { - return createCodeFixActionWorker(fixName, diagnosticToString(description), changes, fixId, diagnosticToString(fixAllDescription), command); +export function createCodeFixAction( + fixName: string, + changes: FileTextChanges[], + description: DiagnosticOrDiagnosticAndArguments, + fixId: {}, + fixAllDescription: DiagnosticOrDiagnosticAndArguments, + command?: CodeActionCommand, +): CodeFixAction { + return createCodeFixActionWorker( + fixName, + diagnosticToString(description), + changes, + fixId, + diagnosticToString(fixAllDescription), + command, + ); } /** @internal */ -export function createCodeFixActionMaybeFixAll(fixName: string, changes: FileTextChanges[], description: DiagnosticOrDiagnosticAndArguments, fixId?: {}, fixAllDescription?: DiagnosticOrDiagnosticAndArguments, command?: CodeActionCommand) { - return createCodeFixActionWorker(fixName, diagnosticToString(description), changes, fixId, fixAllDescription && diagnosticToString(fixAllDescription), command); +export function createCodeFixActionMaybeFixAll( + fixName: string, + changes: FileTextChanges[], + description: DiagnosticOrDiagnosticAndArguments, + fixId?: {}, + fixAllDescription?: DiagnosticOrDiagnosticAndArguments, + command?: CodeActionCommand, +) { + return createCodeFixActionWorker( + fixName, + diagnosticToString(description), + changes, + fixId, + fixAllDescription && diagnosticToString(fixAllDescription), + command, + ); } -function createCodeFixActionWorker(fixName: string, description: string, changes: FileTextChanges[], fixId?: {}, fixAllDescription?: string, command?: CodeActionCommand): CodeFixAction { +function createCodeFixActionWorker( + fixName: string, + description: string, + changes: FileTextChanges[], + fixId?: {}, + fixAllDescription?: string, + command?: CodeActionCommand, +): CodeFixAction { return { fixName, description, changes, fixId, fixAllDescription, commands: command ? [command] : undefined }; } @@ -94,7 +139,10 @@ export function getAllFixes(context: CodeFixAllContext): CombinedCodeActions { } /** @internal */ -export function createCombinedCodeActions(changes: FileTextChanges[], commands?: CodeActionCommand[]): CombinedCodeActions { +export function createCombinedCodeActions( + changes: FileTextChanges[], + commands?: CodeActionCommand[], +): CombinedCodeActions { return { changes, commands }; } @@ -110,12 +158,19 @@ export function codeFixAll( use: (changes: textChanges.ChangeTracker, error: DiagnosticWithLocation, commands: CodeActionCommand[]) => void, ): CombinedCodeActions { const commands: CodeActionCommand[] = []; - const changes = textChanges.ChangeTracker.with(context, t => eachDiagnostic(context, errorCodes, diag => use(t, diag, commands))); + const changes = textChanges.ChangeTracker.with( + context, + t => eachDiagnostic(context, errorCodes, diag => use(t, diag, commands)), + ); return createCombinedCodeActions(changes, commands.length === 0 ? undefined : commands); } /** @internal */ -export function eachDiagnostic(context: CodeFixAllContext, errorCodes: readonly number[], cb: (diag: DiagnosticWithLocation) => void): void { +export function eachDiagnostic( + context: CodeFixAllContext, + errorCodes: readonly number[], + cb: (diag: DiagnosticWithLocation) => void, +): void { for (const diag of getDiagnostics(context)) { if (contains(errorCodes, diag.code)) { cb(diag as DiagnosticWithLocation); diff --git a/src/services/codefixes/addConvertToUnknownForNonOverlappingTypes.ts b/src/services/codefixes/addConvertToUnknownForNonOverlappingTypes.ts index 4b27aee72c953..d12d054c24aec 100644 --- a/src/services/codefixes/addConvertToUnknownForNonOverlappingTypes.ts +++ b/src/services/codefixes/addConvertToUnknownForNonOverlappingTypes.ts @@ -19,14 +19,26 @@ import { } from "../_namespaces/ts.codefix"; const fixId = "addConvertToUnknownForNonOverlappingTypes"; -const errorCodes = [Diagnostics.Conversion_of_type_0_to_type_1_may_be_a_mistake_because_neither_type_sufficiently_overlaps_with_the_other_If_this_was_intentional_convert_the_expression_to_unknown_first.code]; +const errorCodes = [ + Diagnostics + .Conversion_of_type_0_to_type_1_may_be_a_mistake_because_neither_type_sufficiently_overlaps_with_the_other_If_this_was_intentional_convert_the_expression_to_unknown_first + .code, +]; registerCodeFix({ errorCodes, getCodeActions: function getCodeActionsToAddConvertToUnknownForNonOverlappingTypes(context) { const assertion = getAssertion(context.sourceFile, context.span.start); if (assertion === undefined) return undefined; const changes = textChanges.ChangeTracker.with(context, t => makeChange(t, context.sourceFile, assertion)); - return [createCodeFixAction(fixId, changes, Diagnostics.Add_unknown_conversion_for_non_overlapping_types, fixId, Diagnostics.Add_unknown_to_all_conversions_of_non_overlapping_types)]; + return [ + createCodeFixAction( + fixId, + changes, + Diagnostics.Add_unknown_conversion_for_non_overlapping_types, + fixId, + Diagnostics.Add_unknown_to_all_conversions_of_non_overlapping_types, + ), + ]; }, fixIds: [fixId], getAllCodeActions: context => @@ -38,7 +50,11 @@ registerCodeFix({ }), }); -function makeChange(changeTracker: textChanges.ChangeTracker, sourceFile: SourceFile, assertion: AsExpression | TypeAssertion) { +function makeChange( + changeTracker: textChanges.ChangeTracker, + sourceFile: SourceFile, + assertion: AsExpression | TypeAssertion, +) { const replacement = isAsExpression(assertion) ? factory.createAsExpression(assertion.expression, factory.createKeywordTypeNode(SyntaxKind.UnknownKeyword)) : factory.createTypeAssertion(factory.createKeywordTypeNode(SyntaxKind.UnknownKeyword), assertion.expression); @@ -47,5 +63,8 @@ function makeChange(changeTracker: textChanges.ChangeTracker, sourceFile: Source function getAssertion(sourceFile: SourceFile, pos: number): AsExpression | TypeAssertion | undefined { if (isInJSFile(sourceFile)) return undefined; - return findAncestor(getTokenAtPosition(sourceFile, pos), (n): n is AsExpression | TypeAssertion => isAsExpression(n) || isTypeAssertionExpression(n)); + return findAncestor( + getTokenAtPosition(sourceFile, pos), + (n): n is AsExpression | TypeAssertion => isAsExpression(n) || isTypeAssertionExpression(n), + ); } diff --git a/src/services/codefixes/addEmptyExportDeclaration.ts b/src/services/codefixes/addEmptyExportDeclaration.ts index d1c9bbf9a6e54..eb707e8aa2486 100644 --- a/src/services/codefixes/addEmptyExportDeclaration.ts +++ b/src/services/codefixes/addEmptyExportDeclaration.ts @@ -10,9 +10,15 @@ import { registerCodeFix({ errorCodes: [ - Diagnostics.await_expressions_are_only_allowed_at_the_top_level_of_a_file_when_that_file_is_a_module_but_this_file_has_no_imports_or_exports_Consider_adding_an_empty_export_to_make_this_file_a_module.code, - Diagnostics.await_using_statements_are_only_allowed_at_the_top_level_of_a_file_when_that_file_is_a_module_but_this_file_has_no_imports_or_exports_Consider_adding_an_empty_export_to_make_this_file_a_module.code, - Diagnostics.for_await_loops_are_only_allowed_at_the_top_level_of_a_file_when_that_file_is_a_module_but_this_file_has_no_imports_or_exports_Consider_adding_an_empty_export_to_make_this_file_a_module.code, + Diagnostics + .await_expressions_are_only_allowed_at_the_top_level_of_a_file_when_that_file_is_a_module_but_this_file_has_no_imports_or_exports_Consider_adding_an_empty_export_to_make_this_file_a_module + .code, + Diagnostics + .await_using_statements_are_only_allowed_at_the_top_level_of_a_file_when_that_file_is_a_module_but_this_file_has_no_imports_or_exports_Consider_adding_an_empty_export_to_make_this_file_a_module + .code, + Diagnostics + .for_await_loops_are_only_allowed_at_the_top_level_of_a_file_when_that_file_is_a_module_but_this_file_has_no_imports_or_exports_Consider_adding_an_empty_export_to_make_this_file_a_module + .code, ], getCodeActions: function getCodeActionsToAddEmptyExportDeclaration(context) { const { sourceFile } = context; @@ -25,6 +31,12 @@ registerCodeFix({ ); changes.insertNodeAtEndOfScope(sourceFile, sourceFile, exportDeclaration); }); - return [createCodeFixActionWithoutFixAll("addEmptyExportDeclaration", changes, Diagnostics.Add_export_to_make_this_file_into_a_module)]; + return [ + createCodeFixActionWithoutFixAll( + "addEmptyExportDeclaration", + changes, + Diagnostics.Add_export_to_make_this_file_into_a_module, + ), + ]; }, }); diff --git a/src/services/codefixes/addMissingAsync.ts b/src/services/codefixes/addMissingAsync.ts index ef1087ad0ba11..31b3ed7fdc40a 100644 --- a/src/services/codefixes/addMissingAsync.ts +++ b/src/services/codefixes/addMissingAsync.ts @@ -48,8 +48,15 @@ registerCodeFix({ errorCodes, getCodeActions: function getCodeActionsToAddMissingAsync(context) { const { sourceFile, errorCode, cancellationToken, program, span } = context; - const diagnostic = find(program.getTypeChecker().getDiagnostics(sourceFile, cancellationToken), getIsMatchingAsyncError(span, errorCode)); - const directSpan = diagnostic && diagnostic.relatedInformation && find(diagnostic.relatedInformation, r => r.code === Diagnostics.Did_you_mean_to_mark_this_function_as_async.code) as TextSpan | undefined; + const diagnostic = find( + program.getTypeChecker().getDiagnostics(sourceFile, cancellationToken), + getIsMatchingAsyncError(span, errorCode), + ); + const directSpan = diagnostic && diagnostic.relatedInformation + && find( + diagnostic.relatedInformation, + r => r.code === Diagnostics.Did_you_mean_to_mark_this_function_as_async.code, + ) as TextSpan | undefined; const decl = getFixableErrorSpanDeclaration(sourceFile, directSpan); if (!decl) { @@ -63,7 +70,11 @@ registerCodeFix({ const { sourceFile } = context; const fixedDeclarations = new Set(); return codeFixAll(context, errorCodes, (t, diagnostic) => { - const span = diagnostic.relatedInformation && find(diagnostic.relatedInformation, r => r.code === Diagnostics.Did_you_mean_to_mark_this_function_as_async.code) as TextSpan | undefined; + const span = diagnostic.relatedInformation + && find( + diagnostic.relatedInformation, + r => r.code === Diagnostics.Did_you_mean_to_mark_this_function_as_async.code, + ) as TextSpan | undefined; const decl = getFixableErrorSpanDeclaration(sourceFile, span); if (!decl) { return; @@ -75,12 +86,28 @@ registerCodeFix({ }); type FixableDeclaration = ArrowFunction | FunctionDeclaration | FunctionExpression | MethodDeclaration; -function getFix(context: CodeFixContext | CodeFixAllContext, decl: FixableDeclaration, trackChanges: ContextualTrackChangesFunction, fixedDeclarations?: Set) { +function getFix( + context: CodeFixContext | CodeFixAllContext, + decl: FixableDeclaration, + trackChanges: ContextualTrackChangesFunction, + fixedDeclarations?: Set, +) { const changes = trackChanges(t => makeChange(t, context.sourceFile, decl, fixedDeclarations)); - return createCodeFixAction(fixId, changes, Diagnostics.Add_async_modifier_to_containing_function, fixId, Diagnostics.Add_all_missing_async_modifiers); + return createCodeFixAction( + fixId, + changes, + Diagnostics.Add_async_modifier_to_containing_function, + fixId, + Diagnostics.Add_all_missing_async_modifiers, + ); } -function makeChange(changeTracker: textChanges.ChangeTracker, sourceFile: SourceFile, insertionSite: FixableDeclaration, fixedDeclarations?: Set) { +function makeChange( + changeTracker: textChanges.ChangeTracker, + sourceFile: SourceFile, + insertionSite: FixableDeclaration, + fixedDeclarations?: Set, +) { if (fixedDeclarations) { if (fixedDeclarations.has(getNodeId(insertionSite))) { return; @@ -89,7 +116,9 @@ function makeChange(changeTracker: textChanges.ChangeTracker, sourceFile: Source fixedDeclarations?.add(getNodeId(insertionSite)); const cloneWithModifier = factory.updateModifiers( getSynthesizedDeepClone(insertionSite, /*includeTrivia*/ true), - factory.createNodeArray(factory.createModifiersFromModifierFlags(getSyntacticModifierFlags(insertionSite) | ModifierFlags.Async)), + factory.createNodeArray( + factory.createModifiersFromModifierFlags(getSyntacticModifierFlags(insertionSite) | ModifierFlags.Async), + ), ); changeTracker.replaceNode( sourceFile, @@ -98,7 +127,10 @@ function makeChange(changeTracker: textChanges.ChangeTracker, sourceFile: Source ); } -function getFixableErrorSpanDeclaration(sourceFile: SourceFile, span: TextSpan | undefined): FixableDeclaration | undefined { +function getFixableErrorSpanDeclaration( + sourceFile: SourceFile, + span: TextSpan | undefined, +): FixableDeclaration | undefined { if (!span) return undefined; const token = getTokenAtPosition(sourceFile, span.start); // Checker has already done work to determine that async might be possible, and has attached @@ -108,7 +140,8 @@ function getFixableErrorSpanDeclaration(sourceFile: SourceFile, span: TextSpan | if (node.getStart(sourceFile) < span.start || node.getEnd() > textSpanEnd(span)) { return "quit"; } - return (isArrowFunction(node) || isMethodDeclaration(node) || isFunctionExpression(node) || isFunctionDeclaration(node)) && textSpansEqual(span, createTextSpanFromNode(node, sourceFile)); + return (isArrowFunction(node) || isMethodDeclaration(node) || isFunctionExpression(node) + || isFunctionDeclaration(node)) && textSpansEqual(span, createTextSpanFromNode(node, sourceFile)); }) as FixableDeclaration | undefined; return decl; @@ -116,8 +149,11 @@ function getFixableErrorSpanDeclaration(sourceFile: SourceFile, span: TextSpan | function getIsMatchingAsyncError(span: TextSpan, errorCode: number) { return ({ start, length, relatedInformation, code }: Diagnostic) => - isNumber(start) && isNumber(length) && textSpansEqual({ start, length }, span) && - code === errorCode && - !!relatedInformation && - some(relatedInformation, related => related.code === Diagnostics.Did_you_mean_to_mark_this_function_as_async.code); + isNumber(start) && isNumber(length) && textSpansEqual({ start, length }, span) + && code === errorCode + && !!relatedInformation + && some( + relatedInformation, + related => related.code === Diagnostics.Did_you_mean_to_mark_this_function_as_async.code, + ); } diff --git a/src/services/codefixes/addMissingAwait.ts b/src/services/codefixes/addMissingAwait.ts index 61c2692b3a8b5..5ff2eb308e948 100644 --- a/src/services/codefixes/addMissingAwait.ts +++ b/src/services/codefixes/addMissingAwait.ts @@ -69,8 +69,12 @@ const errorCodes = [ Diagnostics.This_condition_will_always_return_true_since_this_0_is_always_defined.code, Diagnostics.Type_0_is_not_an_array_type.code, Diagnostics.Type_0_is_not_an_array_type_or_a_string_type.code, - Diagnostics.Type_0_can_only_be_iterated_through_when_using_the_downlevelIteration_flag_or_with_a_target_of_es2015_or_higher.code, - Diagnostics.Type_0_is_not_an_array_type_or_a_string_type_or_does_not_have_a_Symbol_iterator_method_that_returns_an_iterator.code, + Diagnostics + .Type_0_can_only_be_iterated_through_when_using_the_downlevelIteration_flag_or_with_a_target_of_es2015_or_higher + .code, + Diagnostics + .Type_0_is_not_an_array_type_or_a_string_type_or_does_not_have_a_Symbol_iterator_method_that_returns_an_iterator + .code, Diagnostics.Type_0_is_not_an_array_type_or_does_not_have_a_Symbol_iterator_method_that_returns_an_iterator.code, Diagnostics.Type_0_must_have_a_Symbol_iterator_method_that_returns_an_iterator.code, Diagnostics.Type_0_must_have_a_Symbol_asyncIterator_method_that_returns_an_async_iterator.code, @@ -101,7 +105,13 @@ registerCodeFix({ const checker = context.program.getTypeChecker(); const fixedDeclarations = new Set(); return codeFixAll(context, errorCodes, (t, diagnostic) => { - const expression = getAwaitErrorSpanExpression(sourceFile, diagnostic.code, diagnostic, cancellationToken, program); + const expression = getAwaitErrorSpanExpression( + sourceFile, + diagnostic.code, + diagnostic, + cancellationToken, + program, + ); if (!expression) { return; } @@ -112,19 +122,41 @@ registerCodeFix({ }, }); -function getAwaitErrorSpanExpression(sourceFile: SourceFile, errorCode: number, span: TextSpan, cancellationToken: CancellationToken, program: Program) { +function getAwaitErrorSpanExpression( + sourceFile: SourceFile, + errorCode: number, + span: TextSpan, + cancellationToken: CancellationToken, + program: Program, +) { const expression = getFixableErrorSpanExpression(sourceFile, span); return expression && isMissingAwaitError(sourceFile, errorCode, span, cancellationToken, program) && isInsideAwaitableBody(expression) ? expression : undefined; } -function getDeclarationSiteFix(context: CodeFixContext | CodeFixAllContext, expression: Expression, errorCode: number, checker: TypeChecker, trackChanges: ContextualTrackChangesFunction, fixedDeclarations?: Set) { +function getDeclarationSiteFix( + context: CodeFixContext | CodeFixAllContext, + expression: Expression, + errorCode: number, + checker: TypeChecker, + trackChanges: ContextualTrackChangesFunction, + fixedDeclarations?: Set, +) { const { sourceFile, program, cancellationToken } = context; - const awaitableInitializers = findAwaitableInitializers(expression, sourceFile, cancellationToken, program, checker); + const awaitableInitializers = findAwaitableInitializers( + expression, + sourceFile, + cancellationToken, + program, + checker, + ); if (awaitableInitializers) { const initializerChanges = trackChanges(t => { - forEach(awaitableInitializers.initializers, ({ expression }) => makeChange(t, errorCode, sourceFile, checker, expression, fixedDeclarations)); + forEach( + awaitableInitializers.initializers, + ({ expression }) => makeChange(t, errorCode, sourceFile, checker, expression, fixedDeclarations), + ); if (fixedDeclarations && awaitableInitializers.needsSecondPassForFixAll) { makeChange(t, errorCode, sourceFile, checker, expression, fixedDeclarations); } @@ -135,25 +167,52 @@ function getDeclarationSiteFix(context: CodeFixContext | CodeFixAllContext, expr "addMissingAwaitToInitializer", initializerChanges, awaitableInitializers.initializers.length === 1 - ? [Diagnostics.Add_await_to_initializer_for_0, awaitableInitializers.initializers[0].declarationSymbol.name] + ? [ + Diagnostics.Add_await_to_initializer_for_0, + awaitableInitializers.initializers[0].declarationSymbol.name, + ] : Diagnostics.Add_await_to_initializers, ); } } -function getUseSiteFix(context: CodeFixContext | CodeFixAllContext, expression: Expression, errorCode: number, checker: TypeChecker, trackChanges: ContextualTrackChangesFunction, fixedDeclarations?: Set) { - const changes = trackChanges(t => makeChange(t, errorCode, context.sourceFile, checker, expression, fixedDeclarations)); - return createCodeFixAction(fixId, changes, Diagnostics.Add_await, fixId, Diagnostics.Fix_all_expressions_possibly_missing_await); +function getUseSiteFix( + context: CodeFixContext | CodeFixAllContext, + expression: Expression, + errorCode: number, + checker: TypeChecker, + trackChanges: ContextualTrackChangesFunction, + fixedDeclarations?: Set, +) { + const changes = trackChanges(t => + makeChange(t, errorCode, context.sourceFile, checker, expression, fixedDeclarations) + ); + return createCodeFixAction( + fixId, + changes, + Diagnostics.Add_await, + fixId, + Diagnostics.Fix_all_expressions_possibly_missing_await, + ); } -function isMissingAwaitError(sourceFile: SourceFile, errorCode: number, span: TextSpan, cancellationToken: CancellationToken, program: Program) { +function isMissingAwaitError( + sourceFile: SourceFile, + errorCode: number, + span: TextSpan, + cancellationToken: CancellationToken, + program: Program, +) { const checker = program.getTypeChecker(); const diagnostics = checker.getDiagnostics(sourceFile, cancellationToken); - return some(diagnostics, ({ start, length, relatedInformation, code }) => - isNumber(start) && isNumber(length) && textSpansEqual({ start, length }, span) && - code === errorCode && - !!relatedInformation && - some(relatedInformation, related => related.code === Diagnostics.Did_you_forget_to_use_await.code)); + return some( + diagnostics, + ({ start, length, relatedInformation, code }) => + isNumber(start) && isNumber(length) && textSpansEqual({ start, length }, span) + && code === errorCode + && !!relatedInformation + && some(relatedInformation, related => related.code === Diagnostics.Did_you_forget_to_use_await.code), + ); } interface AwaitableInitializer { @@ -190,22 +249,28 @@ function findAwaitableInitializers( const variableName = declaration && tryCast(declaration.name, isIdentifier); const variableStatement = getAncestor(declaration, SyntaxKind.VariableStatement); if ( - !declaration || !variableStatement || - declaration.type || - !declaration.initializer || - variableStatement.getSourceFile() !== sourceFile || - hasSyntacticModifier(variableStatement, ModifierFlags.Export) || - !variableName || - !isInsideAwaitableBody(declaration.initializer) + !declaration || !variableStatement + || declaration.type + || !declaration.initializer + || variableStatement.getSourceFile() !== sourceFile + || hasSyntacticModifier(variableStatement, ModifierFlags.Export) + || !variableName + || !isInsideAwaitableBody(declaration.initializer) ) { isCompleteFix = false; continue; } const diagnostics = program.getSemanticDiagnostics(sourceFile, cancellationToken); - const isUsedElsewhere = FindAllReferences.Core.eachSymbolReferenceInFile(variableName, checker, sourceFile, reference => { - return identifier !== reference && !symbolReferenceIsAlsoMissingAwait(reference, diagnostics, sourceFile, checker); - }); + const isUsedElsewhere = FindAllReferences.Core.eachSymbolReferenceInFile( + variableName, + checker, + sourceFile, + reference => { + return identifier !== reference + && !symbolReferenceIsAlsoMissingAwait(reference, diagnostics, sourceFile, checker); + }, + ); if (isUsedElsewhere) { isCompleteFix = false; @@ -252,15 +317,20 @@ function getIdentifiersFromErrorSpanExpression(expression: Node, checker: TypeCh } } -function symbolReferenceIsAlsoMissingAwait(reference: Identifier, diagnostics: readonly Diagnostic[], sourceFile: SourceFile, checker: TypeChecker) { - const errorNode = isPropertyAccessExpression(reference.parent) ? reference.parent.name : - isBinaryExpression(reference.parent) ? reference.parent : - reference; +function symbolReferenceIsAlsoMissingAwait( + reference: Identifier, + diagnostics: readonly Diagnostic[], + sourceFile: SourceFile, + checker: TypeChecker, +) { + const errorNode = isPropertyAccessExpression(reference.parent) ? reference.parent.name + : isBinaryExpression(reference.parent) ? reference.parent + : reference; const diagnostic = find(diagnostics, diagnostic => - diagnostic.start === errorNode.getStart(sourceFile) && - (diagnostic.start + diagnostic.length!) === errorNode.getEnd()); + diagnostic.start === errorNode.getStart(sourceFile) + && (diagnostic.start + diagnostic.length!) === errorNode.getEnd()); - return diagnostic && contains(errorCodes, diagnostic.code) || + return diagnostic && contains(errorCodes, diagnostic.code) // A Promise is usually not correct in a binary expression (it's not valid // in an arithmetic expression and an equality comparison seems unusual), // but if the other side of the binary expression has an error, the side @@ -268,27 +338,48 @@ function symbolReferenceIsAlsoMissingAwait(reference: Identifier, diagnostics: r // Promise as an invalid operand. So if the whole binary expression is // typed `any` as a result, there is a strong likelihood that this Promise // is accidentally missing `await`. - checker.getTypeAtLocation(errorNode).flags & TypeFlags.Any; + || checker.getTypeAtLocation(errorNode).flags & TypeFlags.Any; } function isInsideAwaitableBody(node: Node) { - return node.flags & NodeFlags.AwaitContext || !!findAncestor(node, ancestor => - ancestor.parent && isArrowFunction(ancestor.parent) && ancestor.parent.body === ancestor || - isBlock(ancestor) && ( - ancestor.parent.kind === SyntaxKind.FunctionDeclaration || - ancestor.parent.kind === SyntaxKind.FunctionExpression || - ancestor.parent.kind === SyntaxKind.ArrowFunction || - ancestor.parent.kind === SyntaxKind.MethodDeclaration - )); + return node.flags & NodeFlags.AwaitContext + || !!findAncestor( + node, + ancestor => + ancestor.parent && isArrowFunction(ancestor.parent) && ancestor.parent.body === ancestor + || isBlock(ancestor) && ( + ancestor.parent.kind === SyntaxKind.FunctionDeclaration + || ancestor.parent.kind === SyntaxKind.FunctionExpression + || ancestor.parent.kind === SyntaxKind.ArrowFunction + || ancestor.parent.kind === SyntaxKind.MethodDeclaration + ), + ); } -function makeChange(changeTracker: textChanges.ChangeTracker, errorCode: number, sourceFile: SourceFile, checker: TypeChecker, insertionSite: Expression, fixedDeclarations?: Set) { +function makeChange( + changeTracker: textChanges.ChangeTracker, + errorCode: number, + sourceFile: SourceFile, + checker: TypeChecker, + insertionSite: Expression, + fixedDeclarations?: Set, +) { if (isForOfStatement(insertionSite.parent) && !insertionSite.parent.awaitModifier) { const exprType = checker.getTypeAtLocation(insertionSite); const asyncIter = checker.getAsyncIterableType(); if (asyncIter && checker.isTypeAssignableTo(exprType, asyncIter)) { const forOf = insertionSite.parent; - changeTracker.replaceNode(sourceFile, forOf, factory.updateForOfStatement(forOf, factory.createToken(SyntaxKind.AwaitKeyword), forOf.initializer, forOf.expression, forOf.statement)); + changeTracker.replaceNode( + sourceFile, + forOf, + factory.updateForOfStatement( + forOf, + factory.createToken(SyntaxKind.AwaitKeyword), + forOf.initializer, + forOf.expression, + forOf.statement, + ), + ); return; } } @@ -326,11 +417,17 @@ function makeChange(changeTracker: textChanges.ChangeTracker, errorCode: number, return; } } - changeTracker.replaceNode(sourceFile, insertionSite, factory.createParenthesizedExpression(factory.createAwaitExpression(insertionSite))); + changeTracker.replaceNode( + sourceFile, + insertionSite, + factory.createParenthesizedExpression(factory.createAwaitExpression(insertionSite)), + ); insertLeadingSemicolonIfNeeded(changeTracker, insertionSite, sourceFile); } else { - if (fixedDeclarations && isVariableDeclaration(insertionSite.parent) && isIdentifier(insertionSite.parent.name)) { + if ( + fixedDeclarations && isVariableDeclaration(insertionSite.parent) && isIdentifier(insertionSite.parent.name) + ) { const symbol = checker.getSymbolAtLocation(insertionSite.parent.name); if (symbol && !tryAddToSet(fixedDeclarations, getSymbolId(symbol))) { return; @@ -340,7 +437,11 @@ function makeChange(changeTracker: textChanges.ChangeTracker, errorCode: number, } } -function insertLeadingSemicolonIfNeeded(changeTracker: textChanges.ChangeTracker, beforeNode: Node, sourceFile: SourceFile) { +function insertLeadingSemicolonIfNeeded( + changeTracker: textChanges.ChangeTracker, + beforeNode: Node, + sourceFile: SourceFile, +) { const precedingToken = findPrecedingToken(beforeNode.pos, sourceFile); if (precedingToken && positionIsASICandidate(precedingToken.end, precedingToken.parent, sourceFile)) { changeTracker.insertText(sourceFile, beforeNode.getStart(sourceFile), ";"); diff --git a/src/services/codefixes/addMissingConst.ts b/src/services/codefixes/addMissingConst.ts index 87adb892cd9f6..952bfc16117ce 100644 --- a/src/services/codefixes/addMissingConst.ts +++ b/src/services/codefixes/addMissingConst.ts @@ -33,27 +33,54 @@ const errorCodes = [ registerCodeFix({ errorCodes, getCodeActions: function getCodeActionsToAddMissingConst(context) { - const changes = textChanges.ChangeTracker.with(context, t => makeChange(t, context.sourceFile, context.span.start, context.program)); + const changes = textChanges.ChangeTracker.with( + context, + t => makeChange(t, context.sourceFile, context.span.start, context.program), + ); if (changes.length > 0) { - return [createCodeFixAction(fixId, changes, Diagnostics.Add_const_to_unresolved_variable, fixId, Diagnostics.Add_const_to_all_unresolved_variables)]; + return [ + createCodeFixAction( + fixId, + changes, + Diagnostics.Add_const_to_unresolved_variable, + fixId, + Diagnostics.Add_const_to_all_unresolved_variables, + ), + ]; } }, fixIds: [fixId], getAllCodeActions: context => { const fixedNodes = new Set(); - return codeFixAll(context, errorCodes, (changes, diag) => makeChange(changes, diag.file, diag.start, context.program, fixedNodes)); + return codeFixAll( + context, + errorCodes, + (changes, diag) => makeChange(changes, diag.file, diag.start, context.program, fixedNodes), + ); }, }); -function makeChange(changeTracker: textChanges.ChangeTracker, sourceFile: SourceFile, pos: number, program: Program, fixedNodes?: Set) { +function makeChange( + changeTracker: textChanges.ChangeTracker, + sourceFile: SourceFile, + pos: number, + program: Program, + fixedNodes?: Set, +) { const token = getTokenAtPosition(sourceFile, pos); - const forInitializer = findAncestor(token, node => - isForInOrOfStatement(node.parent) ? node.parent.initializer === node : - isPossiblyPartOfDestructuring(node) ? false : "quit"); + const forInitializer = findAncestor( + token, + node => + isForInOrOfStatement(node.parent) ? node.parent.initializer === node + : isPossiblyPartOfDestructuring(node) ? false : "quit", + ); if (forInitializer) return applyChange(changeTracker, forInitializer, sourceFile, fixedNodes); const parent = token.parent; - if (isBinaryExpression(parent) && parent.operatorToken.kind === SyntaxKind.EqualsToken && isExpressionStatement(parent.parent)) { + if ( + isBinaryExpression(parent) && parent.operatorToken.kind === SyntaxKind.EqualsToken + && isExpressionStatement(parent.parent) + ) { return applyChange(changeTracker, token, sourceFile, fixedNodes); } @@ -67,8 +94,8 @@ function makeChange(changeTracker: textChanges.ChangeTracker, sourceFile: Source } const commaExpression = findAncestor(token, node => - isExpressionStatement(node.parent) ? true : - isPossiblyPartOfCommaSeperatedInitializer(node) ? false : "quit"); + isExpressionStatement(node.parent) ? true + : isPossiblyPartOfCommaSeperatedInitializer(node) ? false : "quit"); if (commaExpression) { const checker = program.getTypeChecker(); if (!expressionCouldBeVariableDeclaration(commaExpression, checker)) { @@ -79,7 +106,12 @@ function makeChange(changeTracker: textChanges.ChangeTracker, sourceFile: Source } } -function applyChange(changeTracker: textChanges.ChangeTracker, initializer: Node, sourceFile: SourceFile, fixedNodes?: Set) { +function applyChange( + changeTracker: textChanges.ChangeTracker, + initializer: Node, + sourceFile: SourceFile, + fixedNodes?: Set, +) { if (!fixedNodes || tryAddToSet(fixedNodes, initializer)) { changeTracker.insertModifierBefore(sourceFile, SyntaxKind.ConstKeyword, initializer); } @@ -99,9 +131,10 @@ function isPossiblyPartOfDestructuring(node: Node): boolean { } function arrayElementCouldBeVariableDeclaration(expression: Expression, checker: TypeChecker): boolean { - const identifier = isIdentifier(expression) ? expression : - isAssignmentExpression(expression, /*excludeCompoundAssignment*/ true) && isIdentifier(expression.left) ? expression.left : - undefined; + const identifier = isIdentifier(expression) ? expression + : isAssignmentExpression(expression, /*excludeCompoundAssignment*/ true) && isIdentifier(expression.left) + ? expression.left + : undefined; return !!identifier && !checker.getSymbolAtLocation(identifier); } @@ -122,7 +155,10 @@ function expressionCouldBeVariableDeclaration(expression: Node, checker: TypeChe } if (expression.operatorToken.kind === SyntaxKind.CommaToken) { - return every([expression.left, expression.right], expression => expressionCouldBeVariableDeclaration(expression, checker)); + return every( + [expression.left, expression.right], + expression => expressionCouldBeVariableDeclaration(expression, checker), + ); } return expression.operatorToken.kind === SyntaxKind.EqualsToken diff --git a/src/services/codefixes/addMissingDeclareProperty.ts b/src/services/codefixes/addMissingDeclareProperty.ts index e78a76e25e96d..bc2adab63d02d 100644 --- a/src/services/codefixes/addMissingDeclareProperty.ts +++ b/src/services/codefixes/addMissingDeclareProperty.ts @@ -16,33 +16,55 @@ import { const fixId = "addMissingDeclareProperty"; const errorCodes = [ - Diagnostics.Property_0_will_overwrite_the_base_property_in_1_If_this_is_intentional_add_an_initializer_Otherwise_add_a_declare_modifier_or_remove_the_redundant_declaration.code, + Diagnostics + .Property_0_will_overwrite_the_base_property_in_1_If_this_is_intentional_add_an_initializer_Otherwise_add_a_declare_modifier_or_remove_the_redundant_declaration + .code, ]; registerCodeFix({ errorCodes, getCodeActions: function getCodeActionsToAddMissingDeclareOnProperty(context) { - const changes = textChanges.ChangeTracker.with(context, t => makeChange(t, context.sourceFile, context.span.start)); + const changes = textChanges.ChangeTracker.with( + context, + t => makeChange(t, context.sourceFile, context.span.start), + ); if (changes.length > 0) { - return [createCodeFixAction(fixId, changes, Diagnostics.Prefix_with_declare, fixId, Diagnostics.Prefix_all_incorrect_property_declarations_with_declare)]; + return [ + createCodeFixAction( + fixId, + changes, + Diagnostics.Prefix_with_declare, + fixId, + Diagnostics.Prefix_all_incorrect_property_declarations_with_declare, + ), + ]; } }, fixIds: [fixId], getAllCodeActions: context => { const fixedNodes = new Set(); - return codeFixAll(context, errorCodes, (changes, diag) => makeChange(changes, diag.file, diag.start, fixedNodes)); + return codeFixAll( + context, + errorCodes, + (changes, diag) => makeChange(changes, diag.file, diag.start, fixedNodes), + ); }, }); -function makeChange(changeTracker: textChanges.ChangeTracker, sourceFile: SourceFile, pos: number, fixedNodes?: Set) { +function makeChange( + changeTracker: textChanges.ChangeTracker, + sourceFile: SourceFile, + pos: number, + fixedNodes?: Set, +) { const token = getTokenAtPosition(sourceFile, pos); if (!isIdentifier(token)) { return; } const declaration = token.parent; if ( - declaration.kind === SyntaxKind.PropertyDeclaration && - (!fixedNodes || tryAddToSet(fixedNodes, declaration)) + declaration.kind === SyntaxKind.PropertyDeclaration + && (!fixedNodes || tryAddToSet(fixedNodes, declaration)) ) { changeTracker.insertModifierBefore(sourceFile, SyntaxKind.DeclareKeyword, declaration); } diff --git a/src/services/codefixes/addMissingInvocationForDecorator.ts b/src/services/codefixes/addMissingInvocationForDecorator.ts index 330757c9fa76f..9f5ca45a6e15f 100644 --- a/src/services/codefixes/addMissingInvocationForDecorator.ts +++ b/src/services/codefixes/addMissingInvocationForDecorator.ts @@ -15,21 +15,40 @@ import { } from "../_namespaces/ts.codefix"; const fixId = "addMissingInvocationForDecorator"; -const errorCodes = [Diagnostics._0_accepts_too_few_arguments_to_be_used_as_a_decorator_here_Did_you_mean_to_call_it_first_and_write_0.code]; +const errorCodes = [ + Diagnostics._0_accepts_too_few_arguments_to_be_used_as_a_decorator_here_Did_you_mean_to_call_it_first_and_write_0 + .code, +]; registerCodeFix({ errorCodes, getCodeActions: function getCodeActionsToAddMissingInvocationForDecorator(context) { - const changes = textChanges.ChangeTracker.with(context, t => makeChange(t, context.sourceFile, context.span.start)); - return [createCodeFixAction(fixId, changes, Diagnostics.Call_decorator_expression, fixId, Diagnostics.Add_to_all_uncalled_decorators)]; + const changes = textChanges.ChangeTracker.with( + context, + t => makeChange(t, context.sourceFile, context.span.start), + ); + return [ + createCodeFixAction( + fixId, + changes, + Diagnostics.Call_decorator_expression, + fixId, + Diagnostics.Add_to_all_uncalled_decorators, + ), + ]; }, fixIds: [fixId], - getAllCodeActions: context => codeFixAll(context, errorCodes, (changes, diag) => makeChange(changes, diag.file, diag.start)), + getAllCodeActions: context => + codeFixAll(context, errorCodes, (changes, diag) => makeChange(changes, diag.file, diag.start)), }); function makeChange(changeTracker: textChanges.ChangeTracker, sourceFile: SourceFile, pos: number) { const token = getTokenAtPosition(sourceFile, pos); const decorator = findAncestor(token, isDecorator)!; Debug.assert(!!decorator, "Expected position to be owned by a decorator."); - const replacement = factory.createCallExpression(decorator.expression, /*typeArguments*/ undefined, /*argumentsArray*/ undefined); + const replacement = factory.createCallExpression( + decorator.expression, + /*typeArguments*/ undefined, + /*argumentsArray*/ undefined, + ); changeTracker.replaceNode(sourceFile, decorator.expression, replacement); } diff --git a/src/services/codefixes/addNameToNamelessParameter.ts b/src/services/codefixes/addNameToNamelessParameter.ts index a4d662fa913b9..f61b887458e09 100644 --- a/src/services/codefixes/addNameToNamelessParameter.ts +++ b/src/services/codefixes/addNameToNamelessParameter.ts @@ -19,11 +19,23 @@ const errorCodes = [Diagnostics.Parameter_has_a_name_but_no_type_Did_you_mean_0_ registerCodeFix({ errorCodes, getCodeActions: function getCodeActionsToAddNameToNamelessParameter(context) { - const changes = textChanges.ChangeTracker.with(context, t => makeChange(t, context.sourceFile, context.span.start)); - return [createCodeFixAction(fixId, changes, Diagnostics.Add_parameter_name, fixId, Diagnostics.Add_names_to_all_parameters_without_names)]; + const changes = textChanges.ChangeTracker.with( + context, + t => makeChange(t, context.sourceFile, context.span.start), + ); + return [ + createCodeFixAction( + fixId, + changes, + Diagnostics.Add_parameter_name, + fixId, + Diagnostics.Add_names_to_all_parameters_without_names, + ), + ]; }, fixIds: [fixId], - getAllCodeActions: context => codeFixAll(context, errorCodes, (changes, diag) => makeChange(changes, diag.file, diag.start)), + getAllCodeActions: context => + codeFixAll(context, errorCodes, (changes, diag) => makeChange(changes, diag.file, diag.start)), }); function makeChange(changeTracker: textChanges.ChangeTracker, sourceFile: SourceFile, pos: number) { diff --git a/src/services/codefixes/addOptionalPropertyUndefined.ts b/src/services/codefixes/addOptionalPropertyUndefined.ts index 4b584c3f617ca..cb453e7f651b4 100644 --- a/src/services/codefixes/addOptionalPropertyUndefined.ts +++ b/src/services/codefixes/addOptionalPropertyUndefined.ts @@ -35,9 +35,15 @@ import { const addOptionalPropertyUndefined = "addOptionalPropertyUndefined"; const errorCodes = [ - Diagnostics.Type_0_is_not_assignable_to_type_1_with_exactOptionalPropertyTypes_Colon_true_Consider_adding_undefined_to_the_type_of_the_target.code, - Diagnostics.Type_0_is_not_assignable_to_type_1_with_exactOptionalPropertyTypes_Colon_true_Consider_adding_undefined_to_the_types_of_the_target_s_properties.code, - Diagnostics.Argument_of_type_0_is_not_assignable_to_parameter_of_type_1_with_exactOptionalPropertyTypes_Colon_true_Consider_adding_undefined_to_the_types_of_the_target_s_properties.code, + Diagnostics + .Type_0_is_not_assignable_to_type_1_with_exactOptionalPropertyTypes_Colon_true_Consider_adding_undefined_to_the_type_of_the_target + .code, + Diagnostics + .Type_0_is_not_assignable_to_type_1_with_exactOptionalPropertyTypes_Colon_true_Consider_adding_undefined_to_the_types_of_the_target_s_properties + .code, + Diagnostics + .Argument_of_type_0_is_not_assignable_to_parameter_of_type_1_with_exactOptionalPropertyTypes_Colon_true_Consider_adding_undefined_to_the_types_of_the_target_s_properties + .code, ]; registerCodeFix({ @@ -49,7 +55,13 @@ registerCodeFix({ return undefined; } const changes = textChanges.ChangeTracker.with(context, t => addUndefinedToOptionalProperty(t, toAdd)); - return [createCodeFixActionWithoutFixAll(addOptionalPropertyUndefined, changes, Diagnostics.Add_undefined_to_optional_property_type)]; + return [ + createCodeFixActionWithoutFixAll( + addOptionalPropertyUndefined, + changes, + Diagnostics.Add_undefined_to_optional_property_type, + ), + ]; }, fixIds: [addOptionalPropertyUndefined], }); @@ -69,7 +81,11 @@ function getPropertiesToAdd(file: SourceFile, span: TextSpan, checker: TypeCheck return checker.getExactOptionalProperties(target); } -function shouldUseParentTypeOfProperty(sourceNode: Node, targetNode: Node, checker: TypeChecker): targetNode is PropertyAccessExpression { +function shouldUseParentTypeOfProperty( + sourceNode: Node, + targetNode: Node, + checker: TypeChecker, +): targetNode is PropertyAccessExpression { return isPropertyAccessExpression(targetNode) && !!checker.getExactOptionalProperties(checker.getTypeAtLocation(targetNode.expression)).length && checker.getTypeAtLocation(sourceNode) === checker.getUndefinedType(); @@ -79,7 +95,10 @@ function shouldUseParentTypeOfProperty(sourceNode: Node, targetNode: Node, check * Find the source and target of the incorrect assignment. * The call is recursive for property assignments. */ -function getSourceTarget(errorNode: Node | undefined, checker: TypeChecker): { source: Node; target: Node; } | undefined { +function getSourceTarget( + errorNode: Node | undefined, + checker: TypeChecker, +): { source: Node; target: Node; } | undefined { if (!errorNode) { return undefined; } @@ -99,12 +118,15 @@ function getSourceTarget(errorNode: Node | undefined, checker: TypeChecker): { s if (isIdentifier(name)) return { source: errorNode, target: name }; } else if ( - isPropertyAssignment(errorNode.parent) && isIdentifier(errorNode.parent.name) || - isShorthandPropertyAssignment(errorNode.parent) + isPropertyAssignment(errorNode.parent) && isIdentifier(errorNode.parent.name) + || isShorthandPropertyAssignment(errorNode.parent) ) { const parentTarget = getSourceTarget(errorNode.parent.parent, checker); if (!parentTarget) return undefined; - const prop = checker.getPropertyOfType(checker.getTypeAtLocation(parentTarget.target), (errorNode.parent.name as Identifier).text); + const prop = checker.getPropertyOfType( + checker.getTypeAtLocation(parentTarget.target), + (errorNode.parent.name as Identifier).text, + ); const declaration = prop?.declarations?.[0]; if (!declaration) return undefined; return { diff --git a/src/services/codefixes/annotateWithTypeFromJSDoc.ts b/src/services/codefixes/annotateWithTypeFromJSDoc.ts index f989025b5cc4c..de0a8748c4537 100644 --- a/src/services/codefixes/annotateWithTypeFromJSDoc.ts +++ b/src/services/codefixes/annotateWithTypeFromJSDoc.ts @@ -56,7 +56,15 @@ registerCodeFix({ const decl = getDeclaration(context.sourceFile, context.span.start); if (!decl) return; const changes = textChanges.ChangeTracker.with(context, t => doChange(t, context.sourceFile, decl)); - return [createCodeFixAction(fixId, changes, Diagnostics.Annotate_with_type_from_JSDoc, fixId, Diagnostics.Annotate_everything_with_types_from_JSDoc)]; + return [ + createCodeFixAction( + fixId, + changes, + Diagnostics.Annotate_with_type_from_JSDoc, + fixId, + Diagnostics.Annotate_everything_with_types_from_JSDoc, + ), + ]; }, fixIds: [fixId], getAllCodeActions: context => @@ -97,17 +105,37 @@ function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, de if (typeParameters.length) changes.insertTypeParameters(sourceFile, decl, typeParameters); } const needParens = isArrowFunction(decl) && !findChildOfKind(decl, SyntaxKind.OpenParenToken, sourceFile); - if (needParens) changes.insertNodeBefore(sourceFile, first(decl.parameters), factory.createToken(SyntaxKind.OpenParenToken)); + if (needParens) { + changes.insertNodeBefore( + sourceFile, + first(decl.parameters), + factory.createToken(SyntaxKind.OpenParenToken), + ); + } for (const param of decl.parameters) { if (!param.type) { const paramType = getJSDocType(param); - if (paramType) changes.tryInsertTypeAnnotation(sourceFile, param, visitNode(paramType, transformJSDocType, isTypeNode)); + if (paramType) { + changes.tryInsertTypeAnnotation( + sourceFile, + param, + visitNode(paramType, transformJSDocType, isTypeNode), + ); + } } } - if (needParens) changes.insertNodeAfter(sourceFile, last(decl.parameters), factory.createToken(SyntaxKind.CloseParenToken)); + if (needParens) { + changes.insertNodeAfter(sourceFile, last(decl.parameters), factory.createToken(SyntaxKind.CloseParenToken)); + } if (!decl.type) { const returnType = getJSDocReturnType(decl); - if (returnType) changes.tryInsertTypeAnnotation(sourceFile, decl, visitNode(returnType, transformJSDocType, isTypeNode)); + if (returnType) { + changes.tryInsertTypeAnnotation( + sourceFile, + decl, + visitNode(returnType, transformJSDocType, isTypeNode), + ); + } } } else { @@ -118,10 +146,10 @@ function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, de } function isDeclarationWithType(node: Node): node is DeclarationWithType { - return isFunctionLikeDeclaration(node) || - node.kind === SyntaxKind.VariableDeclaration || - node.kind === SyntaxKind.PropertySignature || - node.kind === SyntaxKind.PropertyDeclaration; + return isFunctionLikeDeclaration(node) + || node.kind === SyntaxKind.VariableDeclaration + || node.kind === SyntaxKind.PropertySignature + || node.kind === SyntaxKind.PropertyDeclaration; } function transformJSDocType(node: Node): Node { @@ -156,18 +184,25 @@ function transformJSDocTypeLiteral(node: JSDocTypeLiteral) { /*modifiers*/ undefined, isIdentifier(tag.name) ? tag.name : tag.name.right, isOptionalJSDocPropertyLikeTag(tag) ? factory.createToken(SyntaxKind.QuestionToken) : undefined, - tag.typeExpression && visitNode(tag.typeExpression.type, transformJSDocType, isTypeNode) || factory.createKeywordTypeNode(SyntaxKind.AnyKeyword), + tag.typeExpression && visitNode(tag.typeExpression.type, transformJSDocType, isTypeNode) + || factory.createKeywordTypeNode(SyntaxKind.AnyKeyword), ))); setEmitFlags(typeNode, EmitFlags.SingleLine); return typeNode; } function transformJSDocOptionalType(node: JSDocOptionalType) { - return factory.createUnionTypeNode([visitNode(node.type, transformJSDocType, isTypeNode), factory.createTypeReferenceNode("undefined", emptyArray)]); + return factory.createUnionTypeNode([ + visitNode(node.type, transformJSDocType, isTypeNode), + factory.createTypeReferenceNode("undefined", emptyArray), + ]); } function transformJSDocNullableType(node: JSDocNullableType) { - return factory.createUnionTypeNode([visitNode(node.type, transformJSDocType, isTypeNode), factory.createTypeReferenceNode("null", emptyArray)]); + return factory.createUnionTypeNode([ + visitNode(node.type, transformJSDocType, isTypeNode), + factory.createTypeReferenceNode("null", emptyArray), + ]); } function transformJSDocVariadicType(node: JSDocVariadicType) { @@ -177,7 +212,11 @@ function transformJSDocVariadicType(node: JSDocVariadicType) { function transformJSDocFunctionType(node: JSDocFunctionType) { // TODO: This does not properly handle `function(new:C, string)` per https://github.com/google/closure-compiler/wiki/Types-in-the-Closure-Type-System#the-javascript-type-language // however we do handle it correctly in `serializeTypeForDeclaration` in checker.ts - return factory.createFunctionTypeNode(emptyArray, node.parameters.map(transformJSDocParameter), node.type ?? factory.createKeywordTypeNode(SyntaxKind.AnyKeyword)); + return factory.createFunctionTypeNode( + emptyArray, + node.parameters.map(transformJSDocParameter), + node.type ?? factory.createKeywordTypeNode(SyntaxKind.AnyKeyword), + ); } function transformJSDocParameter(node: ParameterDeclaration) { @@ -185,7 +224,14 @@ function transformJSDocParameter(node: ParameterDeclaration) { const isRest = node.type!.kind === SyntaxKind.JSDocVariadicType && index === node.parent.parameters.length - 1; // TODO: GH#18217 const name = node.name || (isRest ? "rest" : "arg" + index); const dotdotdot = isRest ? factory.createToken(SyntaxKind.DotDotDotToken) : node.dotDotDotToken; - return factory.createParameterDeclaration(node.modifiers, dotdotdot, name, node.questionToken, visitNode(node.type, transformJSDocType, isTypeNode), node.initializer); + return factory.createParameterDeclaration( + node.modifiers, + dotdotdot, + name, + node.questionToken, + visitNode(node.type, transformJSDocType, isTypeNode), + node.initializer, + ); } function transformJSDocTypeReference(node: TypeReferenceNode) { @@ -226,10 +272,15 @@ function transformJSDocIndexSignature(node: TypeReferenceNode) { /*dotDotDotToken*/ undefined, node.typeArguments![0].kind === SyntaxKind.NumberKeyword ? "n" : "s", /*questionToken*/ undefined, - factory.createTypeReferenceNode(node.typeArguments![0].kind === SyntaxKind.NumberKeyword ? "number" : "string", []), + factory.createTypeReferenceNode( + node.typeArguments![0].kind === SyntaxKind.NumberKeyword ? "number" : "string", + [], + ), /*initializer*/ undefined, ); - const indexSignature = factory.createTypeLiteralNode([factory.createIndexSignature(/*modifiers*/ undefined, [index], node.typeArguments![1])]); + const indexSignature = factory.createTypeLiteralNode([ + factory.createIndexSignature(/*modifiers*/ undefined, [index], node.typeArguments![1]), + ]); setEmitFlags(indexSignature, EmitFlags.SingleLine); return indexSignature; } diff --git a/src/services/codefixes/convertConstToLet.ts b/src/services/codefixes/convertConstToLet.ts index fb1cefbc859b3..de69362391c1c 100644 --- a/src/services/codefixes/convertConstToLet.ts +++ b/src/services/codefixes/convertConstToLet.ts @@ -32,7 +32,15 @@ registerCodeFix({ if (info === undefined) return; const changes = textChanges.ChangeTracker.with(context, t => doChange(t, sourceFile, info.token)); - return [createCodeFixActionMaybeFixAll(fixId, changes, Diagnostics.Convert_const_to_let, fixId, Diagnostics.Convert_all_const_to_let)]; + return [ + createCodeFixActionMaybeFixAll( + fixId, + changes, + Diagnostics.Convert_const_to_let, + fixId, + Diagnostics.Convert_all_const_to_let, + ), + ]; }, getAllCodeActions: context => { const { program } = context; @@ -66,7 +74,11 @@ function getInfo(sourceFile: SourceFile, pos: number, program: Program): Info | const declaration = tryCast(symbol?.valueDeclaration?.parent, isVariableDeclarationList); if (declaration === undefined) return; - const constToken = findChildOfKind>(declaration, SyntaxKind.ConstKeyword, sourceFile); + const constToken = findChildOfKind>( + declaration, + SyntaxKind.ConstKeyword, + sourceFile, + ); if (constToken === undefined) return; return { symbol, token: constToken }; diff --git a/src/services/codefixes/convertFunctionToEs6Class.ts b/src/services/codefixes/convertFunctionToEs6Class.ts index 92d1c85f269f6..f0e73c44e9b7b 100644 --- a/src/services/codefixes/convertFunctionToEs6Class.ts +++ b/src/services/codefixes/convertFunctionToEs6Class.ts @@ -72,16 +72,57 @@ const errorCodes = [Diagnostics.This_constructor_function_may_be_converted_to_a_ registerCodeFix({ errorCodes, getCodeActions(context: CodeFixContext) { - const changes = textChanges.ChangeTracker.with(context, t => doChange(t, context.sourceFile, context.span.start, context.program.getTypeChecker(), context.preferences, context.program.getCompilerOptions())); - return [createCodeFixAction(fixId, changes, Diagnostics.Convert_function_to_an_ES2015_class, fixId, Diagnostics.Convert_all_constructor_functions_to_classes)]; + const changes = textChanges.ChangeTracker.with( + context, + t => doChange( + t, + context.sourceFile, + context.span.start, + context.program.getTypeChecker(), + context.preferences, + context.program.getCompilerOptions(), + ), + ); + return [ + createCodeFixAction( + fixId, + changes, + Diagnostics.Convert_function_to_an_ES2015_class, + fixId, + Diagnostics.Convert_all_constructor_functions_to_classes, + ), + ]; }, fixIds: [fixId], - getAllCodeActions: context => codeFixAll(context, errorCodes, (changes, err) => doChange(changes, err.file, err.start, context.program.getTypeChecker(), context.preferences, context.program.getCompilerOptions())), + getAllCodeActions: context => + codeFixAll( + context, + errorCodes, + (changes, err) => + doChange( + changes, + err.file, + err.start, + context.program.getTypeChecker(), + context.preferences, + context.program.getCompilerOptions(), + ), + ), }); -function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, position: number, checker: TypeChecker, preferences: UserPreferences, compilerOptions: CompilerOptions): void { +function doChange( + changes: textChanges.ChangeTracker, + sourceFile: SourceFile, + position: number, + checker: TypeChecker, + preferences: UserPreferences, + compilerOptions: CompilerOptions, +): void { const ctorSymbol = checker.getSymbolAtLocation(getTokenAtPosition(sourceFile, position))!; - if (!ctorSymbol || !ctorSymbol.valueDeclaration || !(ctorSymbol.flags & (SymbolFlags.Function | SymbolFlags.Variable))) { + if ( + !ctorSymbol || !ctorSymbol.valueDeclaration + || !(ctorSymbol.flags & (SymbolFlags.Function | SymbolFlags.Variable)) + ) { // Bad input return undefined; } @@ -115,11 +156,11 @@ function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, po const firstDeclaration = member.declarations[0]; // only one "x.prototype = { ... }" will pass if ( - member.declarations.length === 1 && - isPropertyAccessExpression(firstDeclaration) && - isBinaryExpression(firstDeclaration.parent) && - firstDeclaration.parent.operatorToken.kind === SyntaxKind.EqualsToken && - isObjectLiteralExpression(firstDeclaration.parent.right) + member.declarations.length === 1 + && isPropertyAccessExpression(firstDeclaration) + && isBinaryExpression(firstDeclaration.parent) + && firstDeclaration.parent.operatorToken.kind === SyntaxKind.EqualsToken + && isObjectLiteralExpression(firstDeclaration.parent.right) ) { const prototypes = firstDeclaration.parent.right; createClassElement(prototypes.symbol, /*modifiers*/ undefined, memberElements); @@ -136,7 +177,11 @@ function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, po symbol.members.forEach((member, key) => { if (key === "constructor" && member.valueDeclaration) { const prototypeAssignment = symbol.exports?.get("prototype" as __String)?.declarations?.[0]?.parent; - if (prototypeAssignment && isBinaryExpression(prototypeAssignment) && isObjectLiteralExpression(prototypeAssignment.right) && some(prototypeAssignment.right.properties, isConstructorAssignment)) { + if ( + prototypeAssignment && isBinaryExpression(prototypeAssignment) + && isObjectLiteralExpression(prototypeAssignment.right) + && some(prototypeAssignment.right.properties, isConstructorAssignment) + ) { // fn.prototype = { constructor: fn } // Already deleted in `createClassElement` in first pass } @@ -165,7 +210,9 @@ function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, po // a() {} if (isMethodDeclaration(property) || isGetOrSetAccessorDeclaration(property)) return true; // a: function() {} - if (isPropertyAssignment(property) && isFunctionExpression(property.initializer) && !!property.name) return true; + if ( + isPropertyAssignment(property) && isFunctionExpression(property.initializer) && !!property.name + ) return true; // x.prototype.constructor = fn if (isConstructorAssignment(property)) return true; return false; @@ -200,17 +247,29 @@ function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, po } // delete the entire statement if this expression is the sole expression to take care of the semicolon at the end - const nodeToDelete = assignmentBinaryExpression.parent && assignmentBinaryExpression.parent.kind === SyntaxKind.ExpressionStatement + const nodeToDelete = assignmentBinaryExpression.parent + && assignmentBinaryExpression.parent.kind === SyntaxKind.ExpressionStatement ? assignmentBinaryExpression.parent : assignmentBinaryExpression; changes.delete(sourceFile, nodeToDelete); if (!assignmentExpr) { - members.push(factory.createPropertyDeclaration(modifiers, symbol.name, /*questionOrExclamationToken*/ undefined, /*type*/ undefined, /*initializer*/ undefined)); + members.push( + factory.createPropertyDeclaration( + modifiers, + symbol.name, + /*questionOrExclamationToken*/ undefined, + /*type*/ undefined, + /*initializer*/ undefined, + ), + ); return; } // f.x = expr - if (isAccessExpression(memberDeclaration) && (isFunctionExpression(assignmentExpr) || isArrowFunction(assignmentExpr))) { + if ( + isAccessExpression(memberDeclaration) + && (isFunctionExpression(assignmentExpr) || isArrowFunction(assignmentExpr)) + ) { const quotePreference = getQuotePreference(sourceFile, preferences); const name = tryGetPropertyName(memberDeclaration, compilerOptions, quotePreference); if (name) { @@ -241,26 +300,56 @@ function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, po // Don't try to declare members in JavaScript files if (isSourceFileJS(sourceFile)) return; if (!isPropertyAccessExpression(memberDeclaration)) return; - const prop = factory.createPropertyDeclaration(modifiers, memberDeclaration.name, /*questionOrExclamationToken*/ undefined, /*type*/ undefined, assignmentExpr); + const prop = factory.createPropertyDeclaration( + modifiers, + memberDeclaration.name, + /*questionOrExclamationToken*/ undefined, + /*type*/ undefined, + assignmentExpr, + ); copyLeadingComments(assignmentBinaryExpression.parent, prop, sourceFile); members.push(prop); return; } - function createFunctionLikeExpressionMember(members: ClassElement[], expression: FunctionExpression | ArrowFunction, name: PropertyName) { + function createFunctionLikeExpressionMember( + members: ClassElement[], + expression: FunctionExpression | ArrowFunction, + name: PropertyName, + ) { if (isFunctionExpression(expression)) return createFunctionExpressionMember(members, expression, name); else return createArrowFunctionExpressionMember(members, expression, name); } - function createFunctionExpressionMember(members: ClassElement[], functionExpression: FunctionExpression, name: PropertyName) { - const fullModifiers = concatenate(modifiers, getModifierKindFromSource(functionExpression, SyntaxKind.AsyncKeyword)); - const method = factory.createMethodDeclaration(fullModifiers, /*asteriskToken*/ undefined, name, /*questionToken*/ undefined, /*typeParameters*/ undefined, functionExpression.parameters, /*type*/ undefined, functionExpression.body); + function createFunctionExpressionMember( + members: ClassElement[], + functionExpression: FunctionExpression, + name: PropertyName, + ) { + const fullModifiers = concatenate( + modifiers, + getModifierKindFromSource(functionExpression, SyntaxKind.AsyncKeyword), + ); + const method = factory.createMethodDeclaration( + fullModifiers, + /*asteriskToken*/ undefined, + name, + /*questionToken*/ undefined, + /*typeParameters*/ undefined, + functionExpression.parameters, + /*type*/ undefined, + functionExpression.body, + ); copyLeadingComments(assignmentBinaryExpression, method, sourceFile); members.push(method); return; } - function createArrowFunctionExpressionMember(members: ClassElement[], arrowFunction: ArrowFunction, name: PropertyName) { + function createArrowFunctionExpressionMember( + members: ClassElement[], + arrowFunction: ArrowFunction, + name: PropertyName, + ) { const arrowFunctionBody = arrowFunction.body; let bodyBlock: Block; @@ -272,8 +361,20 @@ function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, po else { bodyBlock = factory.createBlock([factory.createReturnStatement(arrowFunctionBody)]); } - const fullModifiers = concatenate(modifiers, getModifierKindFromSource(arrowFunction, SyntaxKind.AsyncKeyword)); - const method = factory.createMethodDeclaration(fullModifiers, /*asteriskToken*/ undefined, name, /*questionToken*/ undefined, /*typeParameters*/ undefined, arrowFunction.parameters, /*type*/ undefined, bodyBlock); + const fullModifiers = concatenate( + modifiers, + getModifierKindFromSource(arrowFunction, SyntaxKind.AsyncKeyword), + ); + const method = factory.createMethodDeclaration( + fullModifiers, + /*asteriskToken*/ undefined, + name, + /*questionToken*/ undefined, + /*typeParameters*/ undefined, + arrowFunction.parameters, + /*type*/ undefined, + bodyBlock, + ); copyLeadingComments(assignmentBinaryExpression, method, sourceFile); members.push(method); } @@ -288,11 +389,19 @@ function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, po const memberElements = createClassElementsFromSymbol(node.symbol); if (initializer.body) { - memberElements.unshift(factory.createConstructorDeclaration(/*modifiers*/ undefined, initializer.parameters, initializer.body)); + memberElements.unshift( + factory.createConstructorDeclaration(/*modifiers*/ undefined, initializer.parameters, initializer.body), + ); } const modifiers = getModifierKindFromSource(node.parent.parent, SyntaxKind.ExportKeyword); - const cls = factory.createClassDeclaration(modifiers, node.name, /*typeParameters*/ undefined, /*heritageClauses*/ undefined, memberElements); + const cls = factory.createClassDeclaration( + modifiers, + node.name, + /*typeParameters*/ undefined, + /*heritageClauses*/ undefined, + memberElements, + ); // Don't call copyComments here because we'll already leave them in place return cls; } @@ -300,18 +409,27 @@ function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, po function createClassFromFunction(node: FunctionDeclaration | FunctionExpression): ClassDeclaration { const memberElements = createClassElementsFromSymbol(ctorSymbol); if (node.body) { - memberElements.unshift(factory.createConstructorDeclaration(/*modifiers*/ undefined, node.parameters, node.body)); + memberElements.unshift( + factory.createConstructorDeclaration(/*modifiers*/ undefined, node.parameters, node.body), + ); } const modifiers = getModifierKindFromSource(node, SyntaxKind.ExportKeyword); - const cls = factory.createClassDeclaration(modifiers, node.name, /*typeParameters*/ undefined, /*heritageClauses*/ undefined, memberElements); + const cls = factory.createClassDeclaration( + modifiers, + node.name, + /*typeParameters*/ undefined, + /*heritageClauses*/ undefined, + memberElements, + ); // Don't call copyComments here because we'll already leave them in place return cls; } } function getModifierKindFromSource(source: Node, kind: Modifier["kind"]): readonly Modifier[] | undefined { - return canHaveModifiers(source) ? filter(source.modifiers, (modifier): modifier is Modifier => modifier.kind === kind) : undefined; + return canHaveModifiers(source) + ? filter(source.modifiers, (modifier): modifier is Modifier => modifier.kind === kind) : undefined; } function isConstructorAssignment(x: ObjectLiteralElementLike | PropertyAccessExpression) { @@ -320,7 +438,11 @@ function isConstructorAssignment(x: ObjectLiteralElementLike | PropertyAccessExp return false; } -function tryGetPropertyName(node: AccessExpression, compilerOptions: CompilerOptions, quotePreference: QuotePreference): PropertyName | undefined { +function tryGetPropertyName( + node: AccessExpression, + compilerOptions: CompilerOptions, + quotePreference: QuotePreference, +): PropertyName | undefined { if (isPropertyAccessExpression(node)) { return node.name; } @@ -331,8 +453,10 @@ function tryGetPropertyName(node: AccessExpression, compilerOptions: CompilerOpt } if (isStringLiteralLike(propName)) { - return isIdentifierText(propName.text, getEmitScriptTarget(compilerOptions)) ? factory.createIdentifier(propName.text) - : isNoSubstitutionTemplateLiteral(propName) ? factory.createStringLiteral(propName.text, quotePreference === QuotePreference.Single) + return isIdentifierText(propName.text, getEmitScriptTarget(compilerOptions)) + ? factory.createIdentifier(propName.text) + : isNoSubstitutionTemplateLiteral(propName) + ? factory.createStringLiteral(propName.text, quotePreference === QuotePreference.Single) : propName; } diff --git a/src/services/codefixes/convertLiteralTypeToMappedType.ts b/src/services/codefixes/convertLiteralTypeToMappedType.ts index bde76824b8ce6..a8807dc206c8a 100644 --- a/src/services/codefixes/convertLiteralTypeToMappedType.ts +++ b/src/services/codefixes/convertLiteralTypeToMappedType.ts @@ -18,7 +18,9 @@ import { } from "../_namespaces/ts.codefix"; const fixId = "convertLiteralTypeToMappedType"; -const errorCodes = [Diagnostics._0_only_refers_to_a_type_but_is_being_used_as_a_value_here_Did_you_mean_to_use_1_in_0.code]; +const errorCodes = [ + Diagnostics._0_only_refers_to_a_type_but_is_being_used_as_a_value_here_Did_you_mean_to_use_1_in_0.code, +]; registerCodeFix({ errorCodes, @@ -30,7 +32,15 @@ registerCodeFix({ } const { name, constraint } = info; const changes = textChanges.ChangeTracker.with(context, t => doChange(t, sourceFile, info)); - return [createCodeFixAction(fixId, changes, [Diagnostics.Convert_0_to_1_in_0, constraint, name], fixId, Diagnostics.Convert_all_type_literals_to_mapped_type)]; + return [ + createCodeFixAction( + fixId, + changes, + [Diagnostics.Convert_0_to_1_in_0, constraint, name], + fixId, + Diagnostics.Convert_all_type_literals_to_mapped_type, + ), + ]; }, fixIds: [fixId], getAllCodeActions: context => @@ -64,13 +74,21 @@ function getInfo(sourceFile: SourceFile, pos: number): Info | undefined { return undefined; } -function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, { container, typeNode, constraint, name }: Info): void { +function doChange( + changes: textChanges.ChangeTracker, + sourceFile: SourceFile, + { container, typeNode, constraint, name }: Info, +): void { changes.replaceNode( sourceFile, container, factory.createMappedTypeNode( /*readonlyToken*/ undefined, - factory.createTypeParameterDeclaration(/*modifiers*/ undefined, name, factory.createTypeReferenceNode(constraint)), + factory.createTypeParameterDeclaration( + /*modifiers*/ undefined, + name, + factory.createTypeReferenceNode(constraint), + ), /*nameType*/ undefined, /*questionToken*/ undefined, typeNode, diff --git a/src/services/codefixes/convertToAsyncFunction.ts b/src/services/codefixes/convertToAsyncFunction.ts index cb122865c66ac..d77dc005b5463 100644 --- a/src/services/codefixes/convertToAsyncFunction.ts +++ b/src/services/codefixes/convertToAsyncFunction.ts @@ -91,11 +91,26 @@ registerCodeFix({ errorCodes, getCodeActions(context: CodeFixContext) { codeActionSucceeded = true; - const changes = textChanges.ChangeTracker.with(context, t => convertToAsyncFunction(t, context.sourceFile, context.span.start, context.program.getTypeChecker())); - return codeActionSucceeded ? [createCodeFixAction(fixId, changes, Diagnostics.Convert_to_async_function, fixId, Diagnostics.Convert_all_to_async_functions)] : []; + const changes = textChanges.ChangeTracker.with( + context, + t => convertToAsyncFunction(t, context.sourceFile, context.span.start, context.program.getTypeChecker()), + ); + return codeActionSucceeded + ? [createCodeFixAction( + fixId, + changes, + Diagnostics.Convert_to_async_function, + fixId, + Diagnostics.Convert_all_to_async_functions, + )] : []; }, fixIds: [fixId], - getAllCodeActions: context => codeFixAll(context, errorCodes, (changes, err) => convertToAsyncFunction(changes, err.file, err.start, context.program.getTypeChecker())), + getAllCodeActions: context => + codeFixAll( + context, + errorCodes, + (changes, err) => convertToAsyncFunction(changes, err.file, err.start, context.program.getTypeChecker()), + ), }); const enum SynthBindingNameKind { @@ -134,20 +149,28 @@ interface PromiseReturningCallExpression extends CallExpres }; } -function convertToAsyncFunction(changes: textChanges.ChangeTracker, sourceFile: SourceFile, position: number, checker: TypeChecker): void { +function convertToAsyncFunction( + changes: textChanges.ChangeTracker, + sourceFile: SourceFile, + position: number, + checker: TypeChecker, +): void { // get the function declaration - returns a promise const tokenAtPosition = getTokenAtPosition(sourceFile, position); let functionToConvert: FunctionLikeDeclaration | undefined; // if the parent of a FunctionLikeDeclaration is a variable declaration, the convertToAsync diagnostic will be reported on the variable name if ( - isIdentifier(tokenAtPosition) && isVariableDeclaration(tokenAtPosition.parent) && - tokenAtPosition.parent.initializer && isFunctionLikeDeclaration(tokenAtPosition.parent.initializer) + isIdentifier(tokenAtPosition) && isVariableDeclaration(tokenAtPosition.parent) + && tokenAtPosition.parent.initializer && isFunctionLikeDeclaration(tokenAtPosition.parent.initializer) ) { functionToConvert = tokenAtPosition.parent.initializer; } else { - functionToConvert = tryCast(getContainingFunction(getTokenAtPosition(sourceFile, position)), canBeConvertedToAsync); + functionToConvert = tryCast( + getContainingFunction(getTokenAtPosition(sourceFile, position)), + canBeConvertedToAsync, + ); } if (!functionToConvert) { @@ -162,7 +185,8 @@ function convertToAsyncFunction(changes: textChanges.ChangeTracker, sourceFile: return; } - const returnStatements = functionToConvertRenamed.body && isBlock(functionToConvertRenamed.body) ? getReturnStatementsWithPromiseHandlers(functionToConvertRenamed.body, checker) : emptyArray; + const returnStatements = functionToConvertRenamed.body && isBlock(functionToConvertRenamed.body) + ? getReturnStatementsWithPromiseHandlers(functionToConvertRenamed.body, checker) : emptyArray; const transformer: Transformer = { checker, synthNamesMap, setOfExpressionsToReturn, isInJSFile: isInJavascript }; if (!returnStatements.length) { return; @@ -216,8 +240,8 @@ function getAllPromiseExpressionsToReturn(func: FunctionLikeDeclaration, checker forEach(node.arguments, visit); } else if ( - isPromiseReturningCallExpression(node, checker, "catch") || - isPromiseReturningCallExpression(node, checker, "finally") + isPromiseReturningCallExpression(node, checker, "catch") + || isPromiseReturningCallExpression(node, checker, "finally") ) { setOfExpressionsToReturn.add(getNodeId(node)); // if .catch() or .finally() is the last call in the chain, move leftward in the chain until we hit something else that should be returned @@ -235,7 +259,11 @@ function getAllPromiseExpressionsToReturn(func: FunctionLikeDeclaration, checker return setOfExpressionsToReturn; } -function isPromiseReturningCallExpression(node: Node, checker: TypeChecker, name: Name): node is PromiseReturningCallExpression { +function isPromiseReturningCallExpression( + node: Node, + checker: TypeChecker, + name: Name, +): node is PromiseReturningCallExpression { if (!isCallExpression(node)) return false; const isExpressionOfName = hasPropertyAccessExpressionWithName(node, name); const nodeType = isExpressionOfName && checker.getTypeAtLocation(node); @@ -249,7 +277,11 @@ function isReferenceToType(type: Type, target: Type) { && (type as TypeReference).target === target; } -function getExplicitPromisedTypeOfPromiseReturningCallExpression(node: PromiseReturningCallExpression<"then" | "catch" | "finally">, callback: Expression, checker: TypeChecker) { +function getExplicitPromisedTypeOfPromiseReturningCallExpression( + node: PromiseReturningCallExpression<"then" | "catch" | "finally">, + callback: Expression, + checker: TypeChecker, +) { if (node.expression.name.escapedText === "finally") { // for a `finally`, there's no type argument return undefined; @@ -260,8 +292,8 @@ function getExplicitPromisedTypeOfPromiseReturningCallExpression(node: PromiseRe // which type argument is safe to use as an annotation. const promiseType = checker.getTypeAtLocation(node.expression.expression); if ( - isReferenceToType(promiseType, checker.getPromiseType()) || - isReferenceToType(promiseType, checker.getPromiseLikeType()) + isReferenceToType(promiseType, checker.getPromiseType()) + || isReferenceToType(promiseType, checker.getPromiseLikeType()) ) { if (node.expression.name.escapedText === "then") { if (callback === elementAt(node.arguments, 0)) { @@ -289,7 +321,11 @@ function isPromiseTypedExpression(node: Node, checker: TypeChecker): node is Exp This function collects all existing identifier names and names of identifiers that will be created in the refactor. It then checks for any collisions and renames them through getSynthesizedDeepClone */ -function renameCollidingVarNames(nodeToRename: FunctionLikeDeclaration, checker: TypeChecker, synthNamesMap: Map): FunctionLikeDeclaration { +function renameCollidingVarNames( + nodeToRename: FunctionLikeDeclaration, + checker: TypeChecker, + synthNamesMap: Map, +): FunctionLikeDeclaration { const identsToRenameMap = new Map(); // key is the symbol id const collidingSymbolMap = createMultiMap(); forEachChild(nodeToRename, function visit(node: Node) { @@ -309,7 +345,10 @@ function renameCollidingVarNames(nodeToRename: FunctionLikeDeclaration, checker: // will eventually become // const response = await fetch('...') // so we push an entry for 'response'. - if (lastCallSignature && !isParameter(node.parent) && !isFunctionLikeDeclaration(node.parent) && !synthNamesMap.has(symbolIdString)) { + if ( + lastCallSignature && !isParameter(node.parent) && !isFunctionLikeDeclaration(node.parent) + && !synthNamesMap.has(symbolIdString) + ) { const firstParameter = firstOrUndefined(lastCallSignature.parameters); const ident = firstParameter?.valueDeclaration && isParameter(firstParameter.valueDeclaration) @@ -320,7 +359,10 @@ function renameCollidingVarNames(nodeToRename: FunctionLikeDeclaration, checker: collidingSymbolMap.add(ident.text, symbol); } // We only care about identifiers that are parameters, variable declarations, or binding elements - else if (node.parent && (isParameter(node.parent) || isVariableDeclaration(node.parent) || isBindingElement(node.parent))) { + else if ( + node.parent + && (isParameter(node.parent) || isVariableDeclaration(node.parent) || isBindingElement(node.parent)) + ) { const originalName = node.text; const collidingSymbols = collidingSymbolMap.get(originalName); @@ -384,9 +426,22 @@ function silentFail() { * @param hasContinuation Whether another `then`, `catch`, or `finally` continuation follows the continuation to which this expression belongs. * @param continuationArgName The argument name for the continuation that follows this call. */ -function transformExpression(returnContextNode: Expression, node: Expression, transformer: Transformer, hasContinuation: boolean, continuationArgName?: SynthBindingName): readonly Statement[] { +function transformExpression( + returnContextNode: Expression, + node: Expression, + transformer: Transformer, + hasContinuation: boolean, + continuationArgName?: SynthBindingName, +): readonly Statement[] { if (isPromiseReturningCallExpression(node, transformer.checker, "then")) { - return transformThen(node, elementAt(node.arguments, 0), elementAt(node.arguments, 1), transformer, hasContinuation, continuationArgName); + return transformThen( + node, + elementAt(node.arguments, 0), + elementAt(node.arguments, 1), + transformer, + hasContinuation, + continuationArgName, + ); } if (isPromiseReturningCallExpression(node, transformer.checker, "catch")) { return transformCatch(node, elementAt(node.arguments, 0), transformer, hasContinuation, continuationArgName); @@ -395,13 +450,25 @@ function transformExpression(returnContextNode: Expression, node: Expression, tr return transformFinally(node, elementAt(node.arguments, 0), transformer, hasContinuation, continuationArgName); } if (isPropertyAccessExpression(node)) { - return transformExpression(returnContextNode, node.expression, transformer, hasContinuation, continuationArgName); + return transformExpression( + returnContextNode, + node.expression, + transformer, + hasContinuation, + continuationArgName, + ); } const nodeType = transformer.checker.getTypeAtLocation(node); if (nodeType && transformer.checker.getPromisedTypeOfPromise(nodeType)) { Debug.assertNode(getOriginalNode(node).parent, isPropertyAccessExpression); - return transformPromiseExpressionOfPropertyAccess(returnContextNode, node, transformer, hasContinuation, continuationArgName); + return transformPromiseExpressionOfPropertyAccess( + returnContextNode, + node, + transformer, + hasContinuation, + continuationArgName, + ); } return silentFail(); @@ -421,7 +488,11 @@ function createUniqueSynthName(prevArgName: SynthIdentifier): SynthIdentifier { return createSynthIdentifier(renamedPrevArg); } -function getPossibleNameForVarDecl(node: PromiseReturningCallExpression<"then" | "catch" | "finally">, transformer: Transformer, continuationArgName?: SynthBindingName) { +function getPossibleNameForVarDecl( + node: PromiseReturningCallExpression<"then" | "catch" | "finally">, + transformer: Transformer, + continuationArgName?: SynthBindingName, +) { let possibleNameForVarDecl: SynthIdentifier | undefined; // If there is another call in the chain after the .catch() or .finally() we are transforming, we will need to save the result of both paths @@ -440,7 +511,10 @@ function getPossibleNameForVarDecl(node: PromiseReturningCallExpression<"then" | }); } else { - possibleNameForVarDecl = createSynthIdentifier(factory.createUniqueName("result", GeneratedIdentifierFlags.Optimistic), continuationArgName.types); + possibleNameForVarDecl = createSynthIdentifier( + factory.createUniqueName("result", GeneratedIdentifierFlags.Optimistic), + continuationArgName.types, + ); } // We are about to write a 'let' variable declaration, but `transformExpression` for both @@ -452,7 +526,13 @@ function getPossibleNameForVarDecl(node: PromiseReturningCallExpression<"then" | return possibleNameForVarDecl; } -function finishCatchOrFinallyTransform(node: PromiseReturningCallExpression<"then" | "catch" | "finally">, transformer: Transformer, tryStatement: TryStatement, possibleNameForVarDecl: SynthIdentifier | undefined, continuationArgName?: SynthBindingName) { +function finishCatchOrFinallyTransform( + node: PromiseReturningCallExpression<"then" | "catch" | "finally">, + transformer: Transformer, + tryStatement: TryStatement, + possibleNameForVarDecl: SynthIdentifier | undefined, + continuationArgName?: SynthBindingName, +) { const statements: Statement[] = []; // In order to avoid an implicit any, we will synthesize a type for the declaration using the unions of the types of both paths (try block and catch block) @@ -462,9 +542,15 @@ function finishCatchOrFinallyTransform(node: PromiseReturningCallExpression<"the varDeclIdentifier = getSynthesizedDeepClone(declareSynthIdentifier(possibleNameForVarDecl)); const typeArray: Type[] = possibleNameForVarDecl.types; const unionType = transformer.checker.getUnionType(typeArray, UnionReduction.Subtype); - const unionTypeNode = transformer.isInJSFile ? undefined : transformer.checker.typeToTypeNode(unionType, /*enclosingDeclaration*/ undefined, /*flags*/ undefined); - const varDecl = [factory.createVariableDeclaration(varDeclIdentifier, /*exclamationToken*/ undefined, unionTypeNode)]; - const varDeclList = factory.createVariableStatement(/*modifiers*/ undefined, factory.createVariableDeclarationList(varDecl, NodeFlags.Let)); + const unionTypeNode = transformer.isInJSFile ? undefined + : transformer.checker.typeToTypeNode(unionType, /*enclosingDeclaration*/ undefined, /*flags*/ undefined); + const varDecl = [ + factory.createVariableDeclaration(varDeclIdentifier, /*exclamationToken*/ undefined, unionTypeNode), + ]; + const varDeclList = factory.createVariableStatement( + /*modifiers*/ undefined, + factory.createVariableDeclarationList(varDecl, NodeFlags.Let), + ); statements.push(varDeclList); } @@ -491,21 +577,46 @@ function finishCatchOrFinallyTransform(node: PromiseReturningCallExpression<"the * @param hasContinuation Whether another `then`, `catch`, or `finally` continuation follows this continuation. * @param continuationArgName The argument name for the continuation that follows this call. */ -function transformFinally(node: PromiseReturningCallExpression<"finally">, onFinally: Expression | undefined, transformer: Transformer, hasContinuation: boolean, continuationArgName?: SynthBindingName): readonly Statement[] { +function transformFinally( + node: PromiseReturningCallExpression<"finally">, + onFinally: Expression | undefined, + transformer: Transformer, + hasContinuation: boolean, + continuationArgName?: SynthBindingName, +): readonly Statement[] { if (!onFinally || isNullOrUndefined(transformer, onFinally)) { // Ignore this call as it has no effect on the result - return transformExpression(/* returnContextNode */ node, node.expression.expression, transformer, hasContinuation, continuationArgName); + return transformExpression( + /* returnContextNode */ node, + node.expression.expression, + transformer, + hasContinuation, + continuationArgName, + ); } const possibleNameForVarDecl = getPossibleNameForVarDecl(node, transformer, continuationArgName); // Transform the left-hand-side of `.finally` into an array of inlined statements. We pass `true` for hasContinuation as `node` is the outer continuation. - const inlinedLeftHandSide = transformExpression(/*returnContextNode*/ node, node.expression.expression, transformer, /*hasContinuation*/ true, possibleNameForVarDecl); + const inlinedLeftHandSide = transformExpression( + /*returnContextNode*/ node, + node.expression.expression, + transformer, + /*hasContinuation*/ true, + possibleNameForVarDecl, + ); if (hasFailed()) return silentFail(); // shortcut out of more work // Transform the callback argument into an array of inlined statements. We pass whether we have an outer continuation here // as that indicates whether `return` is valid. - const inlinedCallback = transformCallbackArgument(onFinally, hasContinuation, /*continuationArgName*/ undefined, /*inputArgName*/ undefined, node, transformer); + const inlinedCallback = transformCallbackArgument( + onFinally, + hasContinuation, + /*continuationArgName*/ undefined, + /*inputArgName*/ undefined, + node, + transformer, + ); if (hasFailed()) return silentFail(); // shortcut out of more work const tryBlock = factory.createBlock(inlinedLeftHandSide); @@ -518,26 +629,54 @@ function transformFinally(node: PromiseReturningCallExpression<"finally">, onFin * @param hasContinuation Whether another `then`, `catch`, or `finally` continuation follows this continuation. * @param continuationArgName The argument name for the continuation that follows this call. */ -function transformCatch(node: PromiseReturningCallExpression<"then" | "catch">, onRejected: Expression | undefined, transformer: Transformer, hasContinuation: boolean, continuationArgName?: SynthBindingName): readonly Statement[] { +function transformCatch( + node: PromiseReturningCallExpression<"then" | "catch">, + onRejected: Expression | undefined, + transformer: Transformer, + hasContinuation: boolean, + continuationArgName?: SynthBindingName, +): readonly Statement[] { if (!onRejected || isNullOrUndefined(transformer, onRejected)) { // Ignore this call as it has no effect on the result - return transformExpression(/* returnContextNode */ node, node.expression.expression, transformer, hasContinuation, continuationArgName); + return transformExpression( + /* returnContextNode */ node, + node.expression.expression, + transformer, + hasContinuation, + continuationArgName, + ); } const inputArgName = getArgBindingName(onRejected, transformer); const possibleNameForVarDecl = getPossibleNameForVarDecl(node, transformer, continuationArgName); // Transform the left-hand-side of `.then`/`.catch` into an array of inlined statements. We pass `true` for hasContinuation as `node` is the outer continuation. - const inlinedLeftHandSide = transformExpression(/*returnContextNode*/ node, node.expression.expression, transformer, /*hasContinuation*/ true, possibleNameForVarDecl); + const inlinedLeftHandSide = transformExpression( + /*returnContextNode*/ node, + node.expression.expression, + transformer, + /*hasContinuation*/ true, + possibleNameForVarDecl, + ); if (hasFailed()) return silentFail(); // shortcut out of more work // Transform the callback argument into an array of inlined statements. We pass whether we have an outer continuation here // as that indicates whether `return` is valid. - const inlinedCallback = transformCallbackArgument(onRejected, hasContinuation, possibleNameForVarDecl, inputArgName, node, transformer); + const inlinedCallback = transformCallbackArgument( + onRejected, + hasContinuation, + possibleNameForVarDecl, + inputArgName, + node, + transformer, + ); if (hasFailed()) return silentFail(); // shortcut out of more work const tryBlock = factory.createBlock(inlinedLeftHandSide); - const catchClause = factory.createCatchClause(inputArgName && getSynthesizedDeepClone(declareSynthBindingName(inputArgName)), factory.createBlock(inlinedCallback)); + const catchClause = factory.createCatchClause( + inputArgName && getSynthesizedDeepClone(declareSynthBindingName(inputArgName)), + factory.createBlock(inlinedCallback), + ); const tryStatement = factory.createTryStatement(tryBlock, catchClause, /*finallyBlock*/ undefined); return finishCatchOrFinallyTransform(node, transformer, tryStatement, possibleNameForVarDecl, continuationArgName); } @@ -546,7 +685,14 @@ function transformCatch(node: PromiseReturningCallExpression<"then" | "catch">, * @param hasContinuation Whether another `then`, `catch`, or `finally` continuation follows this continuation. * @param continuationArgName The argument name for the continuation that follows this call. */ -function transformThen(node: PromiseReturningCallExpression<"then">, onFulfilled: Expression | undefined, onRejected: Expression | undefined, transformer: Transformer, hasContinuation: boolean, continuationArgName?: SynthBindingName): readonly Statement[] { +function transformThen( + node: PromiseReturningCallExpression<"then">, + onFulfilled: Expression | undefined, + onRejected: Expression | undefined, + transformer: Transformer, + hasContinuation: boolean, + continuationArgName?: SynthBindingName, +): readonly Statement[] { if (!onFulfilled || isNullOrUndefined(transformer, onFulfilled)) { // If we don't have an `onfulfilled` callback, try treating this as a `.catch`. return transformCatch(node, onRejected, transformer, hasContinuation, continuationArgName); @@ -560,12 +706,25 @@ function transformThen(node: PromiseReturningCallExpression<"then">, onFulfilled const inputArgName = getArgBindingName(onFulfilled, transformer); // Transform the left-hand-side of `.then` into an array of inlined statements. We pass `true` for hasContinuation as `node` is the outer continuation. - const inlinedLeftHandSide = transformExpression(node.expression.expression, node.expression.expression, transformer, /*hasContinuation*/ true, inputArgName); + const inlinedLeftHandSide = transformExpression( + node.expression.expression, + node.expression.expression, + transformer, + /*hasContinuation*/ true, + inputArgName, + ); if (hasFailed()) return silentFail(); // shortcut out of more work // Transform the callback argument into an array of inlined statements. We pass whether we have an outer continuation here // as that indicates whether `return` is valid. - const inlinedCallback = transformCallbackArgument(onFulfilled, hasContinuation, continuationArgName, inputArgName, node, transformer); + const inlinedCallback = transformCallbackArgument( + onFulfilled, + hasContinuation, + continuationArgName, + inputArgName, + node, + transformer, + ); if (hasFailed()) return silentFail(); // shortcut out of more work return concatenate(inlinedLeftHandSide, inlinedCallback); @@ -574,7 +733,13 @@ function transformThen(node: PromiseReturningCallExpression<"then">, onFulfilled /** * Transforms the 'x' part of `x.then(...)`, or the 'y()' part of `y().catch(...)`, where 'x' and 'y()' are Promises. */ -function transformPromiseExpressionOfPropertyAccess(returnContextNode: Expression, node: Expression, transformer: Transformer, hasContinuation: boolean, continuationArgName?: SynthBindingName): readonly Statement[] { +function transformPromiseExpressionOfPropertyAccess( + returnContextNode: Expression, + node: Expression, + transformer: Transformer, + hasContinuation: boolean, + continuationArgName?: SynthBindingName, +): readonly Statement[] { if (shouldReturn(returnContextNode, transformer)) { let returnValue = getSynthesizedDeepClone(node); if (hasContinuation) { @@ -583,10 +748,18 @@ function transformPromiseExpressionOfPropertyAccess(returnContextNode: Expressio return [factory.createReturnStatement(returnValue)]; } - return createVariableOrAssignmentOrExpressionStatement(continuationArgName, factory.createAwaitExpression(node), /*typeAnnotation*/ undefined); + return createVariableOrAssignmentOrExpressionStatement( + continuationArgName, + factory.createAwaitExpression(node), + /*typeAnnotation*/ undefined, + ); } -function createVariableOrAssignmentOrExpressionStatement(variableName: SynthBindingName | undefined, rightHandSide: Expression, typeAnnotation: TypeNode | undefined): readonly Statement[] { +function createVariableOrAssignmentOrExpressionStatement( + variableName: SynthBindingName | undefined, + rightHandSide: Expression, + typeAnnotation: TypeNode | undefined, +): readonly Statement[] { if (!variableName || isEmptyBindingName(variableName)) { // if there's no argName to assign to, there still might be side effects return [factory.createExpressionStatement(rightHandSide)]; @@ -594,7 +767,14 @@ function createVariableOrAssignmentOrExpressionStatement(variableName: SynthBind if (isSynthIdentifier(variableName) && variableName.hasBeenDeclared) { // if the variable has already been declared, we don't need "let" or "const" - return [factory.createExpressionStatement(factory.createAssignment(getSynthesizedDeepClone(referenceSynthIdentifier(variableName)), rightHandSide))]; + return [ + factory.createExpressionStatement( + factory.createAssignment( + getSynthesizedDeepClone(referenceSynthIdentifier(variableName)), + rightHandSide, + ), + ), + ]; } return [ @@ -612,11 +792,18 @@ function createVariableOrAssignmentOrExpressionStatement(variableName: SynthBind ]; } -function maybeAnnotateAndReturn(expressionToReturn: Expression | undefined, typeAnnotation: TypeNode | undefined): Statement[] { +function maybeAnnotateAndReturn( + expressionToReturn: Expression | undefined, + typeAnnotation: TypeNode | undefined, +): Statement[] { if (typeAnnotation && expressionToReturn) { const name = factory.createUniqueName("result", GeneratedIdentifierFlags.Optimistic); return [ - ...createVariableOrAssignmentOrExpressionStatement(createSynthIdentifier(name), expressionToReturn, typeAnnotation), + ...createVariableOrAssignmentOrExpressionStatement( + createSynthIdentifier(name), + expressionToReturn, + typeAnnotation, + ), factory.createReturnStatement(name), ]; } @@ -629,7 +816,14 @@ function maybeAnnotateAndReturn(expressionToReturn: Expression | undefined, type * @param continuationArgName The argument name for the continuation that follows this call. * @param inputArgName The argument name provided to this call */ -function transformCallbackArgument(func: Expression, hasContinuation: boolean, continuationArgName: SynthBindingName | undefined, inputArgName: SynthBindingName | undefined, parent: PromiseReturningCallExpression<"then" | "catch" | "finally">, transformer: Transformer): readonly Statement[] { +function transformCallbackArgument( + func: Expression, + hasContinuation: boolean, + continuationArgName: SynthBindingName | undefined, + inputArgName: SynthBindingName | undefined, + parent: PromiseReturningCallExpression<"then" | "catch" | "finally">, + transformer: Transformer, +): readonly Statement[] { switch (func.kind) { case SyntaxKind.NullKeyword: // do not produce a transformed statement for a null argument @@ -641,10 +835,17 @@ function transformCallbackArgument(func: Expression, hasContinuation: boolean, c break; } - const synthCall = factory.createCallExpression(getSynthesizedDeepClone(func as Identifier | PropertyAccessExpression), /*typeArguments*/ undefined, isSynthIdentifier(inputArgName) ? [referenceSynthIdentifier(inputArgName)] : []); + const synthCall = factory.createCallExpression( + getSynthesizedDeepClone(func as Identifier | PropertyAccessExpression), + /*typeArguments*/ undefined, + isSynthIdentifier(inputArgName) ? [referenceSynthIdentifier(inputArgName)] : [], + ); if (shouldReturn(parent, transformer)) { - return maybeAnnotateAndReturn(synthCall, getExplicitPromisedTypeOfPromiseReturningCallExpression(parent, func, transformer.checker)); + return maybeAnnotateAndReturn( + synthCall, + getExplicitPromisedTypeOfPromiseReturningCallExpression(parent, func, transformer.checker), + ); } const type = transformer.checker.getTypeAtLocation(func); @@ -654,7 +855,11 @@ function transformCallbackArgument(func: Expression, hasContinuation: boolean, c return silentFail(); } const returnType = callSignatures[0].getReturnType(); - const varDeclOrAssignment = createVariableOrAssignmentOrExpressionStatement(continuationArgName, factory.createAwaitExpression(synthCall), getExplicitPromisedTypeOfPromiseReturningCallExpression(parent, func, transformer.checker)); + const varDeclOrAssignment = createVariableOrAssignmentOrExpressionStatement( + continuationArgName, + factory.createAwaitExpression(synthCall), + getExplicitPromisedTypeOfPromiseReturningCallExpression(parent, func, transformer.checker), + ); if (continuationArgName) { continuationArgName.types.push(transformer.checker.getAwaitedType(returnType) || returnType); } @@ -663,7 +868,8 @@ function transformCallbackArgument(func: Expression, hasContinuation: boolean, c case SyntaxKind.FunctionExpression: case SyntaxKind.ArrowFunction: { const funcBody = (func as FunctionExpression | ArrowFunction).body; - const returnType = getLastCallSignature(transformer.checker.getTypeAtLocation(func), transformer.checker)?.getReturnType(); + const returnType = getLastCallSignature(transformer.checker.getTypeAtLocation(func), transformer.checker) + ?.getReturnType(); // Arrow functions with block bodies { } will enter this control flow if (isBlock(funcBody)) { @@ -673,11 +879,29 @@ function transformCallbackArgument(func: Expression, hasContinuation: boolean, c if (isReturnStatement(statement)) { seenReturnStatement = true; if (isReturnStatementWithFixablePromiseHandler(statement, transformer.checker)) { - refactoredStmts = refactoredStmts.concat(transformReturnStatementWithFixablePromiseHandler(transformer, statement, hasContinuation, continuationArgName)); + refactoredStmts = refactoredStmts.concat( + transformReturnStatementWithFixablePromiseHandler( + transformer, + statement, + hasContinuation, + continuationArgName, + ), + ); } else { - const possiblyAwaitedRightHandSide = returnType && statement.expression ? getPossiblyAwaitedRightHandSide(transformer.checker, returnType, statement.expression) : statement.expression; - refactoredStmts.push(...maybeAnnotateAndReturn(possiblyAwaitedRightHandSide, getExplicitPromisedTypeOfPromiseReturningCallExpression(parent, func, transformer.checker))); + const possiblyAwaitedRightHandSide = returnType && statement.expression + ? getPossiblyAwaitedRightHandSide(transformer.checker, returnType, statement.expression) + : statement.expression; + refactoredStmts.push( + ...maybeAnnotateAndReturn( + possiblyAwaitedRightHandSide, + getExplicitPromisedTypeOfPromiseReturningCallExpression( + parent, + func, + transformer.checker, + ), + ), + ); } } else if (hasContinuation && forEachReturnStatement(statement, returnTrue)) { @@ -735,26 +959,44 @@ function transformCallbackArgument(func: Expression, hasContinuation: boolean, c ); } else { - const inlinedStatements = isFixablePromiseHandler(funcBody, transformer.checker) ? - transformReturnStatementWithFixablePromiseHandler(transformer, factory.createReturnStatement(funcBody), hasContinuation, continuationArgName) : - emptyArray; + const inlinedStatements = isFixablePromiseHandler(funcBody, transformer.checker) + ? transformReturnStatementWithFixablePromiseHandler( + transformer, + factory.createReturnStatement(funcBody), + hasContinuation, + continuationArgName, + ) + : emptyArray; if (inlinedStatements.length > 0) { return inlinedStatements; } if (returnType) { - const possiblyAwaitedRightHandSide = getPossiblyAwaitedRightHandSide(transformer.checker, returnType, funcBody); + const possiblyAwaitedRightHandSide = getPossiblyAwaitedRightHandSide( + transformer.checker, + returnType, + funcBody, + ); if (!shouldReturn(parent, transformer)) { - const transformedStatement = createVariableOrAssignmentOrExpressionStatement(continuationArgName, possiblyAwaitedRightHandSide, /*typeAnnotation*/ undefined); + const transformedStatement = createVariableOrAssignmentOrExpressionStatement( + continuationArgName, + possiblyAwaitedRightHandSide, + /*typeAnnotation*/ undefined, + ); if (continuationArgName) { - continuationArgName.types.push(transformer.checker.getAwaitedType(returnType) || returnType); + continuationArgName.types.push( + transformer.checker.getAwaitedType(returnType) || returnType, + ); } return transformedStatement; } else { - return maybeAnnotateAndReturn(possiblyAwaitedRightHandSide, getExplicitPromisedTypeOfPromiseReturningCallExpression(parent, func, transformer.checker)); + return maybeAnnotateAndReturn( + possiblyAwaitedRightHandSide, + getExplicitPromisedTypeOfPromiseReturningCallExpression(parent, func, transformer.checker), + ); } } else { @@ -769,7 +1011,11 @@ function transformCallbackArgument(func: Expression, hasContinuation: boolean, c return emptyArray; } -function getPossiblyAwaitedRightHandSide(checker: TypeChecker, type: Type, expr: Expression): AwaitExpression | Expression { +function getPossiblyAwaitedRightHandSide( + checker: TypeChecker, + type: Type, + expr: Expression, +): AwaitExpression | Expression { const rightHandSide = getSynthesizedDeepClone(expr); return !!checker.getPromisedTypeOfPromise(type) ? factory.createAwaitExpression(rightHandSide) : rightHandSide; } @@ -779,20 +1025,42 @@ function getLastCallSignature(type: Type, checker: TypeChecker): Signature | und return lastOrUndefined(callSignatures); } -function removeReturns(stmts: readonly Statement[], prevArgName: SynthBindingName | undefined, transformer: Transformer, seenReturnStatement: boolean): readonly Statement[] { +function removeReturns( + stmts: readonly Statement[], + prevArgName: SynthBindingName | undefined, + transformer: Transformer, + seenReturnStatement: boolean, +): readonly Statement[] { const ret: Statement[] = []; for (const stmt of stmts) { if (isReturnStatement(stmt)) { if (stmt.expression) { - const possiblyAwaitedExpression = isPromiseTypedExpression(stmt.expression, transformer.checker) ? factory.createAwaitExpression(stmt.expression) : stmt.expression; + const possiblyAwaitedExpression = isPromiseTypedExpression(stmt.expression, transformer.checker) + ? factory.createAwaitExpression(stmt.expression) : stmt.expression; if (prevArgName === undefined) { ret.push(factory.createExpressionStatement(possiblyAwaitedExpression)); } else if (isSynthIdentifier(prevArgName) && prevArgName.hasBeenDeclared) { - ret.push(factory.createExpressionStatement(factory.createAssignment(referenceSynthIdentifier(prevArgName), possiblyAwaitedExpression))); + ret.push( + factory.createExpressionStatement( + factory.createAssignment(referenceSynthIdentifier(prevArgName), possiblyAwaitedExpression), + ), + ); } else { - ret.push(factory.createVariableStatement(/*modifiers*/ undefined, factory.createVariableDeclarationList([factory.createVariableDeclaration(declareSynthBindingName(prevArgName), /*exclamationToken*/ undefined, /*type*/ undefined, possiblyAwaitedExpression)], NodeFlags.Const))); + ret.push( + factory.createVariableStatement( + /*modifiers*/ undefined, + factory.createVariableDeclarationList([ + factory.createVariableDeclaration( + declareSynthBindingName(prevArgName), + /*exclamationToken*/ undefined, + /*type*/ undefined, + possiblyAwaitedExpression, + ), + ], NodeFlags.Const), + ), + ); } } } @@ -803,7 +1071,19 @@ function removeReturns(stmts: readonly Statement[], prevArgName: SynthBindingNam // if block has no return statement, need to define prevArgName as undefined to prevent undeclared variables if (!seenReturnStatement && prevArgName !== undefined) { - ret.push(factory.createVariableStatement(/*modifiers*/ undefined, factory.createVariableDeclarationList([factory.createVariableDeclaration(declareSynthBindingName(prevArgName), /*exclamationToken*/ undefined, /*type*/ undefined, factory.createIdentifier("undefined"))], NodeFlags.Const))); + ret.push( + factory.createVariableStatement( + /*modifiers*/ undefined, + factory.createVariableDeclarationList([ + factory.createVariableDeclaration( + declareSynthBindingName(prevArgName), + /*exclamationToken*/ undefined, + /*type*/ undefined, + factory.createIdentifier("undefined"), + ), + ], NodeFlags.Const), + ), + ); } return ret; @@ -813,7 +1093,12 @@ function removeReturns(stmts: readonly Statement[], prevArgName: SynthBindingNam * @param hasContinuation Whether another `then`, `catch`, or `finally` continuation follows the continuation to which this statement belongs. * @param continuationArgName The argument name for the continuation that follows this call. */ -function transformReturnStatementWithFixablePromiseHandler(transformer: Transformer, innerRetStmt: ReturnStatement, hasContinuation: boolean, continuationArgName?: SynthBindingName) { +function transformReturnStatementWithFixablePromiseHandler( + transformer: Transformer, + innerRetStmt: ReturnStatement, + hasContinuation: boolean, + continuationArgName?: SynthBindingName, +) { let innerCbBody: Statement[] = []; forEachChild(innerRetStmt, function visit(node) { if (isCallExpression(node)) { @@ -897,10 +1182,20 @@ function isEmptyBindingName(bindingName: SynthBindingName | undefined): boolean } function createSynthIdentifier(identifier: Identifier, types: Type[] = []): SynthIdentifier { - return { kind: SynthBindingNameKind.Identifier, identifier, types, hasBeenDeclared: false, hasBeenReferenced: false }; + return { + kind: SynthBindingNameKind.Identifier, + identifier, + types, + hasBeenDeclared: false, + hasBeenReferenced: false, + }; } -function createSynthBindingPattern(bindingPattern: BindingPattern, elements: readonly SynthBindingName[] = emptyArray, types: Type[] = []): SynthBindingPattern { +function createSynthBindingPattern( + bindingPattern: BindingPattern, + elements: readonly SynthBindingName[] = emptyArray, + types: Type[] = [], +): SynthBindingPattern { return { kind: SynthBindingNameKind.BindingPattern, bindingPattern, elements, types }; } diff --git a/src/services/codefixes/convertToEsModule.ts b/src/services/codefixes/convertToEsModule.ts index 1a5d2ad8ad2c8..1de471e11884b 100644 --- a/src/services/codefixes/convertToEsModule.ts +++ b/src/services/codefixes/convertToEsModule.ts @@ -87,10 +87,21 @@ registerCodeFix({ getCodeActions(context) { const { sourceFile, program, preferences } = context; const changes = textChanges.ChangeTracker.with(context, changes => { - const moduleExportsChangedToDefault = convertFileToEsModule(sourceFile, program.getTypeChecker(), changes, getEmitScriptTarget(program.getCompilerOptions()), getQuotePreference(sourceFile, preferences)); + const moduleExportsChangedToDefault = convertFileToEsModule( + sourceFile, + program.getTypeChecker(), + changes, + getEmitScriptTarget(program.getCompilerOptions()), + getQuotePreference(sourceFile, preferences), + ); if (moduleExportsChangedToDefault) { for (const importingFile of program.getSourceFiles()) { - fixImportOfModuleExports(importingFile, sourceFile, changes, getQuotePreference(importingFile, preferences)); + fixImportOfModuleExports( + importingFile, + sourceFile, + changes, + getQuotePreference(importingFile, preferences), + ); } } }); @@ -99,9 +110,18 @@ registerCodeFix({ }, }); -function fixImportOfModuleExports(importingFile: SourceFile, exportingFile: SourceFile, changes: textChanges.ChangeTracker, quotePreference: QuotePreference) { +function fixImportOfModuleExports( + importingFile: SourceFile, + exportingFile: SourceFile, + changes: textChanges.ChangeTracker, + quotePreference: QuotePreference, +) { for (const moduleSpecifier of importingFile.imports) { - const imported = getResolvedModule(importingFile, moduleSpecifier.text, getModeForUsageLocation(importingFile, moduleSpecifier)); + const imported = getResolvedModule( + importingFile, + moduleSpecifier.text, + getModeForUsageLocation(importingFile, moduleSpecifier), + ); if (!imported || imported.resolvedFileName !== exportingFile.fileName) { continue; } @@ -109,11 +129,19 @@ function fixImportOfModuleExports(importingFile: SourceFile, exportingFile: Sour const importNode = importFromModuleSpecifier(moduleSpecifier); switch (importNode.kind) { case SyntaxKind.ImportEqualsDeclaration: - changes.replaceNode(importingFile, importNode, makeImport(importNode.name, /*namedImports*/ undefined, moduleSpecifier, quotePreference)); + changes.replaceNode( + importingFile, + importNode, + makeImport(importNode.name, /*namedImports*/ undefined, moduleSpecifier, quotePreference), + ); break; case SyntaxKind.CallExpression: if (isRequireCall(importNode, /*requireStringLiteralLikeArgument*/ false)) { - changes.replaceNode(importingFile, importNode, factory.createPropertyAccessExpression(getSynthesizedDeepClone(importNode), "default")); + changes.replaceNode( + importingFile, + importNode, + factory.createPropertyAccessExpression(getSynthesizedDeepClone(importNode), "default"), + ); } break; } @@ -121,7 +149,13 @@ function fixImportOfModuleExports(importingFile: SourceFile, exportingFile: Sour } /** @returns Whether we converted a `module.exports =` to a default export. */ -function convertFileToEsModule(sourceFile: SourceFile, checker: TypeChecker, changes: textChanges.ChangeTracker, target: ScriptTarget, quotePreference: QuotePreference): ModuleExportsChanged { +function convertFileToEsModule( + sourceFile: SourceFile, + checker: TypeChecker, + changes: textChanges.ChangeTracker, + target: ScriptTarget, + quotePreference: QuotePreference, +): ModuleExportsChanged { const identifiers: Identifiers = { original: collectFreeIdentifiers(sourceFile), additional: new Set() }; const exports = collectExportRenames(sourceFile, checker, identifiers); convertExportsAccesses(sourceFile, exports, changes); @@ -129,14 +163,32 @@ function convertFileToEsModule(sourceFile: SourceFile, checker: TypeChecker, cha let useSitesToUnqualify: Map | undefined; // Process variable statements first to collect use sites that need to be updated inside other transformations for (const statement of filter(sourceFile.statements, isVariableStatement)) { - const newUseSites = convertVariableStatement(sourceFile, statement, changes, checker, identifiers, target, quotePreference); + const newUseSites = convertVariableStatement( + sourceFile, + statement, + changes, + checker, + identifiers, + target, + quotePreference, + ); if (newUseSites) { copyEntries(newUseSites, useSitesToUnqualify ??= new Map()); } } // `convertStatement` will delete entries from `useSitesToUnqualify` when containing statements are replaced for (const statement of filter(sourceFile.statements, s => !isVariableStatement(s))) { - const moduleExportsChanged = convertStatement(sourceFile, statement, checker, changes, identifiers, target, exports, useSitesToUnqualify, quotePreference); + const moduleExportsChanged = convertStatement( + sourceFile, + statement, + checker, + changes, + identifiers, + target, + exports, + useSitesToUnqualify, + quotePreference, + ); moduleExportsChangedToDefault = moduleExportsChangedToDefault || moduleExportsChanged; } // Remaining use sites can be changed directly @@ -173,7 +225,11 @@ function collectExportRenames(sourceFile: SourceFile, checker: TypeChecker, iden return res; } -function convertExportsAccesses(sourceFile: SourceFile, exports: ExportRenames, changes: textChanges.ChangeTracker): void { +function convertExportsAccesses( + sourceFile: SourceFile, + exports: ExportRenames, + changes: textChanges.ChangeTracker, +): void { forEachExportReference(sourceFile, (node, isAssignmentLhs) => { if (isAssignmentLhs) { return; @@ -183,11 +239,21 @@ function convertExportsAccesses(sourceFile: SourceFile, exports: ExportRenames, }); } -function forEachExportReference(sourceFile: SourceFile, cb: (node: PropertyAccessExpression & { name: Identifier; }, isAssignmentLhs: boolean) => void): void { +function forEachExportReference( + sourceFile: SourceFile, + cb: (node: PropertyAccessExpression & { name: Identifier; }, isAssignmentLhs: boolean) => void, +): void { sourceFile.forEachChild(function recur(node) { - if (isPropertyAccessExpression(node) && isExportsOrModuleExportsOrAlias(sourceFile, node.expression) && isIdentifier(node.name)) { + if ( + isPropertyAccessExpression(node) && isExportsOrModuleExportsOrAlias(sourceFile, node.expression) + && isIdentifier(node.name) + ) { const { parent } = node; - cb(node as typeof node & { name: Identifier; }, isBinaryExpression(parent) && parent.left === node && parent.operatorToken.kind === SyntaxKind.EqualsToken); + cb( + node as typeof node & { name: Identifier; }, + isBinaryExpression(parent) && parent.left === node + && parent.operatorToken.kind === SyntaxKind.EqualsToken, + ); } node.forEachChild(recur); }); @@ -209,7 +275,15 @@ function convertStatement( ): ModuleExportsChanged { switch (statement.kind) { case SyntaxKind.VariableStatement: - convertVariableStatement(sourceFile, statement as VariableStatement, changes, checker, identifiers, target, quotePreference); + convertVariableStatement( + sourceFile, + statement as VariableStatement, + changes, + checker, + identifiers, + target, + quotePreference, + ); return false; case SyntaxKind.ExpressionStatement: { const { expression } = statement as ExpressionStatement; @@ -217,13 +291,30 @@ function convertStatement( case SyntaxKind.CallExpression: { if (isRequireCall(expression, /*requireStringLiteralLikeArgument*/ true)) { // For side-effecting require() call, just make a side-effecting import. - changes.replaceNode(sourceFile, statement, makeImport(/*defaultImport*/ undefined, /*namedImports*/ undefined, expression.arguments[0], quotePreference)); + changes.replaceNode( + sourceFile, + statement, + makeImport( + /*defaultImport*/ undefined, + /*namedImports*/ undefined, + expression.arguments[0], + quotePreference, + ), + ); } return false; } case SyntaxKind.BinaryExpression: { const { operatorToken } = expression as BinaryExpression; - return operatorToken.kind === SyntaxKind.EqualsToken && convertAssignment(sourceFile, checker, expression as BinaryExpression, changes, exports, useSitesToUnqualify); + return operatorToken.kind === SyntaxKind.EqualsToken + && convertAssignment( + sourceFile, + checker, + expression as BinaryExpression, + changes, + exports, + useSitesToUnqualify, + ); } } } @@ -254,15 +345,36 @@ function convertVariableStatement( } else if (isRequireCall(initializer, /*requireStringLiteralLikeArgument*/ true)) { foundImport = true; - return convertSingleImport(name, initializer.arguments[0], checker, identifiers, target, quotePreference); + return convertSingleImport( + name, + initializer.arguments[0], + checker, + identifiers, + target, + quotePreference, + ); } - else if (isPropertyAccessExpression(initializer) && isRequireCall(initializer.expression, /*requireStringLiteralLikeArgument*/ true)) { + else if ( + isPropertyAccessExpression(initializer) + && isRequireCall(initializer.expression, /*requireStringLiteralLikeArgument*/ true) + ) { foundImport = true; - return convertPropertyAccessImport(name, initializer.name.text, initializer.expression.arguments[0], identifiers, quotePreference); + return convertPropertyAccessImport( + name, + initializer.name.text, + initializer.expression.arguments[0], + identifiers, + quotePreference, + ); } } // Move it out to its own variable statement. (This will not be used if `!foundImport`) - return convertedImports([factory.createVariableStatement(/*modifiers*/ undefined, factory.createVariableDeclarationList([decl], declarationList.flags))]); + return convertedImports([ + factory.createVariableStatement( + /*modifiers*/ undefined, + factory.createVariableDeclarationList([decl], declarationList.flags), + ), + ]); }); if (foundImport) { // useNonAdjustedEndPosition to ensure we don't eat the newline after the statement. @@ -279,7 +391,13 @@ function convertVariableStatement( } /** Converts `const name = require("moduleSpecifier").propertyName` */ -function convertPropertyAccessImport(name: BindingName, propertyName: string, moduleSpecifier: StringLiteralLike, identifiers: Identifiers, quotePreference: QuotePreference): ConvertedImports { +function convertPropertyAccessImport( + name: BindingName, + propertyName: string, + moduleSpecifier: StringLiteralLike, + identifiers: Identifiers, + quotePreference: QuotePreference, +): ConvertedImports { switch (name.kind) { case SyntaxKind.ObjectBindingPattern: case SyntaxKind.ArrayBindingPattern: { @@ -294,7 +412,10 @@ function convertPropertyAccessImport(name: BindingName, propertyName: string, mo // `const a = require("b").c` --> `import { c as a } from "./b"; return convertedImports([makeSingleImport(name.text, propertyName, moduleSpecifier, quotePreference)]); default: - return Debug.assertNever(name, `Convert to ES module got invalid syntax form ${(name as BindingName).kind}`); + return Debug.assertNever( + name, + `Convert to ES module got invalid syntax form ${(name as BindingName).kind}`, + ); } } @@ -317,21 +438,32 @@ function convertAssignment( changes.delete(sourceFile, assignment.parent); } else { - const replacement = isObjectLiteralExpression(right) ? tryChangeModuleExportsObject(right, useSitesToUnqualify) - : isRequireCall(right, /*requireStringLiteralLikeArgument*/ true) ? convertReExportAll(right.arguments[0], checker) + const replacement = isObjectLiteralExpression(right) + ? tryChangeModuleExportsObject(right, useSitesToUnqualify) + : isRequireCall(right, /*requireStringLiteralLikeArgument*/ true) + ? convertReExportAll(right.arguments[0], checker) : undefined; if (replacement) { changes.replaceNodeWithNodes(sourceFile, assignment.parent, replacement[0]); return replacement[1]; } else { - changes.replaceRangeWithText(sourceFile, createRange(left.getStart(sourceFile), right.pos), "export default"); + changes.replaceRangeWithText( + sourceFile, + createRange(left.getStart(sourceFile), right.pos), + "export default", + ); return true; } } } else if (isExportsOrModuleExportsOrAlias(sourceFile, left.expression)) { - convertNamedExport(sourceFile, assignment as BinaryExpression & { left: PropertyAccessExpression; }, changes, exports); + convertNamedExport( + sourceFile, + assignment as BinaryExpression & { left: PropertyAccessExpression; }, + changes, + exports, + ); } return false; @@ -341,7 +473,10 @@ function convertAssignment( * Convert `module.exports = { ... }` to individual exports.. * We can't always do this if the module has interesting members -- then it will be a default export instead. */ -function tryChangeModuleExportsObject(object: ObjectLiteralExpression, useSitesToUnqualify: Map | undefined): [readonly Statement[], ModuleExportsChanged] | undefined { +function tryChangeModuleExportsObject( + object: ObjectLiteralExpression, + useSitesToUnqualify: Map | undefined, +): [readonly Statement[], ModuleExportsChanged] | undefined { const statements = mapAllOrFail(object.properties, prop => { switch (prop.kind) { case SyntaxKind.GetAccessor: @@ -352,11 +487,21 @@ function tryChangeModuleExportsObject(object: ObjectLiteralExpression, useSitesT case SyntaxKind.SpreadAssignment: return undefined; case SyntaxKind.PropertyAssignment: - return !isIdentifier(prop.name) ? undefined : convertExportsDotXEquals_replaceNode(prop.name.text, prop.initializer, useSitesToUnqualify); + return !isIdentifier(prop.name) ? undefined + : convertExportsDotXEquals_replaceNode(prop.name.text, prop.initializer, useSitesToUnqualify); case SyntaxKind.MethodDeclaration: - return !isIdentifier(prop.name) ? undefined : functionExpressionToDeclaration(prop.name.text, [factory.createToken(SyntaxKind.ExportKeyword)], prop, useSitesToUnqualify); + return !isIdentifier(prop.name) ? undefined + : functionExpressionToDeclaration( + prop.name.text, + [factory.createToken(SyntaxKind.ExportKeyword)], + prop, + useSitesToUnqualify, + ); default: - Debug.assertNever(prop, `Convert to ES6 got invalid prop kind ${(prop as ObjectLiteralElementLike).kind}`); + Debug.assertNever( + prop, + `Convert to ES6 got invalid prop kind ${(prop as ObjectLiteralElementLike).kind}`, + ); } }); return statements && [statements, false]; @@ -387,28 +532,46 @@ function convertNamedExport( } } -function convertReExportAll(reExported: StringLiteralLike, checker: TypeChecker): [readonly Statement[], ModuleExportsChanged] { +function convertReExportAll( + reExported: StringLiteralLike, + checker: TypeChecker, +): [readonly Statement[], ModuleExportsChanged] { // `module.exports = require("x");` ==> `export * from "x"; export { default } from "x";` const moduleSpecifier = reExported.text; const moduleSymbol = checker.getSymbolAtLocation(reExported); const exports = moduleSymbol ? moduleSymbol.exports! : emptyMap as ReadonlyCollection<__String>; - return exports.has(InternalSymbolName.ExportEquals) ? [[reExportDefault(moduleSpecifier)], true] : - !exports.has(InternalSymbolName.Default) ? [[reExportStar(moduleSpecifier)], false] : + return exports.has(InternalSymbolName.ExportEquals) ? [[reExportDefault(moduleSpecifier)], true] + : !exports.has(InternalSymbolName.Default) ? [[reExportStar(moduleSpecifier)], false] // If there's some non-default export, must include both `export *` and `export default`. - exports.size > 1 ? [[reExportStar(moduleSpecifier), reExportDefault(moduleSpecifier)], true] : [[reExportDefault(moduleSpecifier)], true]; + : exports.size > 1 ? [[reExportStar(moduleSpecifier), reExportDefault(moduleSpecifier)], true] + : [[reExportDefault(moduleSpecifier)], true]; } function reExportStar(moduleSpecifier: string): ExportDeclaration { return makeExportDeclaration(/*exportSpecifiers*/ undefined, moduleSpecifier); } function reExportDefault(moduleSpecifier: string): ExportDeclaration { - return makeExportDeclaration([factory.createExportSpecifier(/*isTypeOnly*/ false, /*propertyName*/ undefined, "default")], moduleSpecifier); + return makeExportDeclaration([ + factory.createExportSpecifier(/*isTypeOnly*/ false, /*propertyName*/ undefined, "default"), + ], moduleSpecifier); } -function convertExportsPropertyAssignment({ left, right, parent }: BinaryExpression & { left: PropertyAccessExpression; }, sourceFile: SourceFile, changes: textChanges.ChangeTracker): void { +function convertExportsPropertyAssignment( + { left, right, parent }: BinaryExpression & { left: PropertyAccessExpression; }, + sourceFile: SourceFile, + changes: textChanges.ChangeTracker, +): void { const name = left.name.text; - if ((isFunctionExpression(right) || isArrowFunction(right) || isClassExpression(right)) && (!right.name || right.name.text === name)) { + if ( + (isFunctionExpression(right) || isArrowFunction(right) || isClassExpression(right)) + && (!right.name || right.name.text === name) + ) { // `exports.f = function() {}` -> `export function f() {}` -- Replace `exports.f = ` with `export `, and insert the name after `function`. - changes.replaceRange(sourceFile, { pos: left.getStart(sourceFile), end: right.getStart(sourceFile) }, factory.createToken(SyntaxKind.ExportKeyword), { suffix: " " }); + changes.replaceRange( + sourceFile, + { pos: left.getStart(sourceFile), end: right.getStart(sourceFile) }, + factory.createToken(SyntaxKind.ExportKeyword), + { suffix: " " }, + ); if (!right.name) changes.insertName(sourceFile, right, name); @@ -417,12 +580,22 @@ function convertExportsPropertyAssignment({ left, right, parent }: BinaryExpress } else { // `exports.f = function g() {}` -> `export const f = function g() {}` -- just replace `exports.` with `export const ` - changes.replaceNodeRangeWithNodes(sourceFile, left.expression, findChildOfKind(left, SyntaxKind.DotToken, sourceFile)!, [factory.createToken(SyntaxKind.ExportKeyword), factory.createToken(SyntaxKind.ConstKeyword)], { joiner: " ", suffix: " " }); + changes.replaceNodeRangeWithNodes( + sourceFile, + left.expression, + findChildOfKind(left, SyntaxKind.DotToken, sourceFile)!, + [factory.createToken(SyntaxKind.ExportKeyword), factory.createToken(SyntaxKind.ConstKeyword)], + { joiner: " ", suffix: " " }, + ); } } // TODO: GH#22492 this will cause an error if a change has been made inside the body of the node. -function convertExportsDotXEquals_replaceNode(name: string | undefined, exported: Expression, useSitesToUnqualify: Map | undefined): Statement { +function convertExportsDotXEquals_replaceNode( + name: string | undefined, + exported: Expression, + useSitesToUnqualify: Map | undefined, +): Statement { const modifiers = [factory.createToken(SyntaxKind.ExportKeyword)]; switch (exported.kind) { case SyntaxKind.FunctionExpression: { @@ -436,7 +609,12 @@ function convertExportsDotXEquals_replaceNode(name: string | undefined, exported // falls through case SyntaxKind.ArrowFunction: // `exports.f = function() {}` --> `export function f() {}` - return functionExpressionToDeclaration(name, modifiers, exported as FunctionExpression | ArrowFunction, useSitesToUnqualify); + return functionExpressionToDeclaration( + name, + modifiers, + exported as FunctionExpression | ArrowFunction, + useSitesToUnqualify, + ); case SyntaxKind.ClassExpression: // `exports.C = class {}` --> `export class C {}` return classExpressionToDeclaration(name, modifiers, exported as ClassExpression, useSitesToUnqualify); @@ -446,14 +624,27 @@ function convertExportsDotXEquals_replaceNode(name: string | undefined, exported function exportConst() { // `exports.x = 0;` --> `export const x = 0;` - return makeConst(modifiers, factory.createIdentifier(name!), replaceImportUseSites(exported, useSitesToUnqualify)); // TODO: GH#18217 + return makeConst( + modifiers, + factory.createIdentifier(name!), + replaceImportUseSites(exported, useSitesToUnqualify), + ); // TODO: GH#18217 } } function replaceImportUseSites(node: T, useSitesToUnqualify: Map | undefined): T; -function replaceImportUseSites(nodes: NodeArray, useSitesToUnqualify: Map | undefined): NodeArray; -function replaceImportUseSites(nodeOrNodes: T | NodeArray, useSitesToUnqualify: Map | undefined) { - if (!useSitesToUnqualify || !some(arrayFrom(useSitesToUnqualify.keys()), original => rangeContainsRange(nodeOrNodes, original))) { +function replaceImportUseSites( + nodes: NodeArray, + useSitesToUnqualify: Map | undefined, +): NodeArray; +function replaceImportUseSites( + nodeOrNodes: T | NodeArray, + useSitesToUnqualify: Map | undefined, +) { + if ( + !useSitesToUnqualify + || !some(arrayFrom(useSitesToUnqualify.keys()), original => rangeContainsRange(nodeOrNodes, original)) + ) { return nodeOrNodes; } @@ -487,12 +678,17 @@ function convertSingleImport( ): ConvertedImports { switch (name.kind) { case SyntaxKind.ObjectBindingPattern: { - const importSpecifiers = mapAllOrFail(name.elements, e => - e.dotDotDotToken || e.initializer || e.propertyName && !isIdentifier(e.propertyName) || !isIdentifier(e.name) + const importSpecifiers = mapAllOrFail( + name.elements, + e => e.dotDotDotToken || e.initializer || e.propertyName && !isIdentifier(e.propertyName) + || !isIdentifier(e.name) ? undefined - : makeImportSpecifier(e.propertyName && e.propertyName.text, e.name.text)); + : makeImportSpecifier(e.propertyName && e.propertyName.text, e.name.text), + ); if (importSpecifiers) { - return convertedImports([makeImport(/*defaultImport*/ undefined, importSpecifiers, moduleSpecifier, quotePreference)]); + return convertedImports([ + makeImport(/*defaultImport*/ undefined, importSpecifiers, moduleSpecifier, quotePreference), + ]); } } // falls through -- object destructuring has an interesting pattern and must be a variable declaration @@ -520,7 +716,13 @@ function convertSingleImport( * - Convert `x.default()` to `x()` to handle ES6 default export * - Converts uses like `x.y()` to `y()` and uses a named import. */ -function convertSingleIdentifierImport(name: Identifier, moduleSpecifier: StringLiteralLike, checker: TypeChecker, identifiers: Identifiers, quotePreference: QuotePreference): ConvertedImports { +function convertSingleIdentifierImport( + name: Identifier, + moduleSpecifier: StringLiteralLike, + checker: TypeChecker, + identifiers: Identifiers, + quotePreference: QuotePreference, +): ConvertedImports { const nameSymbol = checker.getSymbolAtLocation(name); // Maps from module property name to name actually used. (The same if there isn't shadowing.) const namedBindingsNames = new Map(); @@ -559,13 +761,26 @@ function convertSingleIdentifierImport(name: Identifier, moduleSpecifier: String } } - const namedBindings = namedBindingsNames.size === 0 ? undefined : arrayFrom(mapIterator(namedBindingsNames.entries(), ([propertyName, idName]) => factory.createImportSpecifier(/*isTypeOnly*/ false, propertyName === idName ? undefined : factory.createIdentifier(propertyName), factory.createIdentifier(idName)))); + const namedBindings = namedBindingsNames.size === 0 ? undefined + : arrayFrom( + mapIterator(namedBindingsNames.entries(), ([propertyName, idName]) => + factory.createImportSpecifier( + /*isTypeOnly*/ false, + propertyName === idName ? undefined : factory.createIdentifier(propertyName), + factory.createIdentifier(idName), + )), + ); if (!namedBindings) { // If it was unused, ensure that we at least import *something*. needDefaultImport = true; } return convertedImports( - [makeImport(needDefaultImport ? getSynthesizedDeepClone(name) : undefined, namedBindings, moduleSpecifier, quotePreference)], + [makeImport( + needDefaultImport ? getSynthesizedDeepClone(name) : undefined, + namedBindings, + moduleSpecifier, + quotePreference, + )], useSitesToUnqualify, ); } @@ -623,7 +838,12 @@ function isFreeIdentifier(node: Identifier): boolean { // Node helpers -function functionExpressionToDeclaration(name: string | undefined, additionalModifiers: readonly Modifier[], fn: FunctionExpression | ArrowFunction | MethodDeclaration, useSitesToUnqualify: Map | undefined): FunctionDeclaration { +function functionExpressionToDeclaration( + name: string | undefined, + additionalModifiers: readonly Modifier[], + fn: FunctionExpression | ArrowFunction | MethodDeclaration, + useSitesToUnqualify: Map | undefined, +): FunctionDeclaration { return factory.createFunctionDeclaration( concatenate(additionalModifiers, getSynthesizedDeepClones(fn.modifiers)), getSynthesizedDeepClone(fn.asteriskToken), @@ -635,7 +855,12 @@ function functionExpressionToDeclaration(name: string | undefined, additionalMod ); } -function classExpressionToDeclaration(name: string | undefined, additionalModifiers: readonly Modifier[], cls: ClassExpression, useSitesToUnqualify: Map | undefined): ClassDeclaration { +function classExpressionToDeclaration( + name: string | undefined, + additionalModifiers: readonly Modifier[], + cls: ClassExpression, + useSitesToUnqualify: Map | undefined, +): ClassDeclaration { return factory.createClassDeclaration( concatenate(additionalModifiers, getSynthesizedDeepClones(cls.modifiers)), name, @@ -645,17 +870,35 @@ function classExpressionToDeclaration(name: string | undefined, additionalModifi ); } -function makeSingleImport(localName: string, propertyName: string, moduleSpecifier: StringLiteralLike, quotePreference: QuotePreference): ImportDeclaration { +function makeSingleImport( + localName: string, + propertyName: string, + moduleSpecifier: StringLiteralLike, + quotePreference: QuotePreference, +): ImportDeclaration { return propertyName === "default" ? makeImport(factory.createIdentifier(localName), /*namedImports*/ undefined, moduleSpecifier, quotePreference) - : makeImport(/*defaultImport*/ undefined, [makeImportSpecifier(propertyName, localName)], moduleSpecifier, quotePreference); + : makeImport( + /*defaultImport*/ undefined, + [makeImportSpecifier(propertyName, localName)], + moduleSpecifier, + quotePreference, + ); } function makeImportSpecifier(propertyName: string | undefined, name: string): ImportSpecifier { - return factory.createImportSpecifier(/*isTypeOnly*/ false, propertyName !== undefined && propertyName !== name ? factory.createIdentifier(propertyName) : undefined, factory.createIdentifier(name)); + return factory.createImportSpecifier( + /*isTypeOnly*/ false, + propertyName !== undefined && propertyName !== name ? factory.createIdentifier(propertyName) : undefined, + factory.createIdentifier(name), + ); } -function makeConst(modifiers: readonly Modifier[] | undefined, name: string | BindingName, init: Expression): VariableStatement { +function makeConst( + modifiers: readonly Modifier[] | undefined, + name: string | BindingName, + init: Expression, +): VariableStatement { return factory.createVariableStatement( modifiers, factory.createVariableDeclarationList( @@ -665,7 +908,10 @@ function makeConst(modifiers: readonly Modifier[] | undefined, name: string | Bi ); } -function makeExportDeclaration(exportSpecifiers: ExportSpecifier[] | undefined, moduleSpecifier?: string): ExportDeclaration { +function makeExportDeclaration( + exportSpecifiers: ExportSpecifier[] | undefined, + moduleSpecifier?: string, +): ExportDeclaration { return factory.createExportDeclaration( /*modifiers*/ undefined, /*isTypeOnly*/ false, diff --git a/src/services/codefixes/convertToMappedObjectType.ts b/src/services/codefixes/convertToMappedObjectType.ts index f07987f258c6b..b1f4bc29b36de 100644 --- a/src/services/codefixes/convertToMappedObjectType.ts +++ b/src/services/codefixes/convertToMappedObjectType.ts @@ -29,7 +29,11 @@ import { } from "../_namespaces/ts.codefix"; const fixId = "fixConvertToMappedObjectType"; -const errorCodes = [Diagnostics.An_index_signature_parameter_type_cannot_be_a_literal_type_or_generic_type_Consider_using_a_mapped_object_type_instead.code]; +const errorCodes = [ + Diagnostics + .An_index_signature_parameter_type_cannot_be_a_literal_type_or_generic_type_Consider_using_a_mapped_object_type_instead + .code, +]; type FixableDeclaration = InterfaceDeclaration | TypeAliasDeclaration; @@ -41,7 +45,12 @@ registerCodeFix({ if (!info) return undefined; const changes = textChanges.ChangeTracker.with(context, t => doChange(t, sourceFile, info)); const name = idText(info.container.name); - return [createCodeFixAction(fixId, changes, [Diagnostics.Convert_0_to_mapped_object_type, name], fixId, [Diagnostics.Convert_0_to_mapped_object_type, name])]; + return [ + createCodeFixAction(fixId, changes, [Diagnostics.Convert_0_to_mapped_object_type, name], fixId, [ + Diagnostics.Convert_0_to_mapped_object_type, + name, + ]), + ]; }, fixIds: [fixId], getAllCodeActions: context => @@ -60,21 +69,35 @@ function getInfo(sourceFile: SourceFile, pos: number): Info | undefined { const indexSignature = tryCast(token.parent.parent, isIndexSignatureDeclaration); if (!indexSignature) return undefined; - const container = isInterfaceDeclaration(indexSignature.parent) ? indexSignature.parent : tryCast(indexSignature.parent.parent, isTypeAliasDeclaration); + const container = isInterfaceDeclaration(indexSignature.parent) ? indexSignature.parent + : tryCast(indexSignature.parent.parent, isTypeAliasDeclaration); if (!container) return undefined; return { indexSignature, container }; } function createTypeAliasFromInterface(declaration: FixableDeclaration, type: TypeNode): TypeAliasDeclaration { - return factory.createTypeAliasDeclaration(declaration.modifiers, declaration.name, declaration.typeParameters, type); + return factory.createTypeAliasDeclaration( + declaration.modifiers, + declaration.name, + declaration.typeParameters, + type, + ); } -function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, { indexSignature, container }: Info): void { +function doChange( + changes: textChanges.ChangeTracker, + sourceFile: SourceFile, + { indexSignature, container }: Info, +): void { const members = isInterfaceDeclaration(container) ? container.members : (container.type as TypeLiteralNode).members; const otherMembers = members.filter(member => !isIndexSignatureDeclaration(member)); const parameter = first(indexSignature.parameters); - const mappedTypeParameter = factory.createTypeParameterDeclaration(/*modifiers*/ undefined, cast(parameter.name, isIdentifier), parameter.type); + const mappedTypeParameter = factory.createTypeParameterDeclaration( + /*modifiers*/ undefined, + cast(parameter.name, isIdentifier), + parameter.type, + ); const mappedIntersectionType = factory.createMappedTypeNode( hasEffectiveReadonlyModifier(indexSignature) ? factory.createModifier(SyntaxKind.ReadonlyKeyword) : undefined, mappedTypeParameter, diff --git a/src/services/codefixes/convertToTypeOnlyExport.ts b/src/services/codefixes/convertToTypeOnlyExport.ts index 36a75c5ddefaa..2aa0e4451b162 100644 --- a/src/services/codefixes/convertToTypeOnlyExport.ts +++ b/src/services/codefixes/convertToTypeOnlyExport.ts @@ -29,9 +29,24 @@ const fixId = "convertToTypeOnlyExport"; registerCodeFix({ errorCodes, getCodeActions: function getCodeActionsToConvertToTypeOnlyExport(context) { - const changes = textChanges.ChangeTracker.with(context, t => fixSingleExportDeclaration(t, getExportSpecifierForDiagnosticSpan(context.span, context.sourceFile), context)); + const changes = textChanges.ChangeTracker.with( + context, + t => fixSingleExportDeclaration( + t, + getExportSpecifierForDiagnosticSpan(context.span, context.sourceFile), + context, + ), + ); if (changes.length) { - return [createCodeFixAction(fixId, changes, Diagnostics.Convert_to_type_only_export, fixId, Diagnostics.Convert_all_re_exported_types_to_type_only_exports)]; + return [ + createCodeFixAction( + fixId, + changes, + Diagnostics.Convert_to_type_only_export, + fixId, + Diagnostics.Convert_all_re_exported_types_to_type_only_exports, + ), + ]; } }, fixIds: [fixId], @@ -50,7 +65,11 @@ function getExportSpecifierForDiagnosticSpan(span: TextSpan, sourceFile: SourceF return tryCast(getTokenAtPosition(sourceFile, span.start).parent, isExportSpecifier); } -function fixSingleExportDeclaration(changes: textChanges.ChangeTracker, exportSpecifier: ExportSpecifier | undefined, context: CodeFixContextBase) { +function fixSingleExportDeclaration( + changes: textChanges.ChangeTracker, + exportSpecifier: ExportSpecifier | undefined, + context: CodeFixContextBase, +) { if (!exportSpecifier) { return; } @@ -66,7 +85,10 @@ function fixSingleExportDeclaration(changes: textChanges.ChangeTracker, exportSp exportDeclaration, exportDeclaration.modifiers, /*isTypeOnly*/ false, - factory.updateNamedExports(exportClause, filter(exportClause.elements, e => !contains(typeExportSpecifiers, e))), + factory.updateNamedExports( + exportClause, + filter(exportClause.elements, e => !contains(typeExportSpecifiers, e)), + ), exportDeclaration.moduleSpecifier, /*assertClause*/ undefined, ); @@ -86,7 +108,10 @@ function fixSingleExportDeclaration(changes: textChanges.ChangeTracker, exportSp } } -function getTypeExportSpecifiers(originExportSpecifier: ExportSpecifier, context: CodeFixContextBase): readonly ExportSpecifier[] { +function getTypeExportSpecifiers( + originExportSpecifier: ExportSpecifier, + context: CodeFixContextBase, +): readonly ExportSpecifier[] { const exportClause = originExportSpecifier.parent; if (exportClause.elements.length === 1) { return exportClause.elements; diff --git a/src/services/codefixes/convertToTypeOnlyImport.ts b/src/services/codefixes/convertToTypeOnlyImport.ts index 5578ddc5d6902..8ab21a1eb9114 100644 --- a/src/services/codefixes/convertToTypeOnlyImport.ts +++ b/src/services/codefixes/convertToTypeOnlyImport.ts @@ -26,7 +26,9 @@ import { } from "../_namespaces/ts.codefix"; const errorCodes = [ - Diagnostics.This_import_is_never_used_as_a_value_and_must_use_import_type_because_importsNotUsedAsValues_is_set_to_error.code, + Diagnostics + .This_import_is_never_used_as_a_value_and_must_use_import_type_because_importsNotUsedAsValues_is_set_to_error + .code, Diagnostics._0_is_a_type_and_must_be_imported_using_a_type_only_import_when_verbatimModuleSyntax_is_enabled.code, ]; const fixId = "convertToTypeOnlyImport"; @@ -37,8 +39,12 @@ registerCodeFix({ const declaration = getDeclaration(context.sourceFile, context.span.start); if (declaration) { const changes = textChanges.ChangeTracker.with(context, t => doChange(t, context.sourceFile, declaration)); - const importDeclarationChanges = declaration.kind === SyntaxKind.ImportSpecifier && canConvertImportDeclarationForSpecifier(declaration, context.sourceFile, context.program) - ? textChanges.ChangeTracker.with(context, t => doChange(t, context.sourceFile, declaration.parent.parent.parent)) + const importDeclarationChanges = declaration.kind === SyntaxKind.ImportSpecifier + && canConvertImportDeclarationForSpecifier(declaration, context.sourceFile, context.program) + ? textChanges.ChangeTracker.with( + context, + t => doChange(t, context.sourceFile, declaration.parent.parent.parent), + ) : undefined; const mainAction = createCodeFixAction( fixId, @@ -65,7 +71,10 @@ registerCodeFix({ const fixedImportDeclarations = new Set(); return codeFixAll(context, errorCodes, (changes, diag) => { const errorDeclaration = getDeclaration(diag.file, diag.start); - if (errorDeclaration?.kind === SyntaxKind.ImportDeclaration && !fixedImportDeclarations.has(errorDeclaration)) { + if ( + errorDeclaration?.kind === SyntaxKind.ImportDeclaration + && !fixedImportDeclarations.has(errorDeclaration) + ) { doChange(changes, diag.file, errorDeclaration); fixedImportDeclarations.add(errorDeclaration); } @@ -89,7 +98,11 @@ function getDeclaration(sourceFile: SourceFile, pos: number) { return isImportSpecifier(parent) || isImportDeclaration(parent) && parent.importClause ? parent : undefined; } -function canConvertImportDeclarationForSpecifier(specifier: ImportSpecifier, sourceFile: SourceFile, program: Program): boolean { +function canConvertImportDeclarationForSpecifier( + specifier: ImportSpecifier, + sourceFile: SourceFile, + program: Program, +): boolean { if (specifier.parent.parent.name) { // An import declaration with a default import and named bindings can't be type-only return false; @@ -102,9 +115,14 @@ function canConvertImportDeclarationForSpecifier(specifier: ImportSpecifier, sou // Otherwise, we need to check the usage of the other specifiers const checker = program.getTypeChecker(); for (const specifier of nonTypeOnlySpecifiers) { - const isUsedAsValue = FindAllReferences.Core.eachSymbolReferenceInFile(specifier.name, checker, sourceFile, usage => { - return !isValidTypeOnlyAliasUseSite(usage); - }); + const isUsedAsValue = FindAllReferences.Core.eachSymbolReferenceInFile( + specifier.name, + checker, + sourceFile, + usage => { + return !isValidTypeOnlyAliasUseSite(usage); + }, + ); if (isUsedAsValue) { return false; } @@ -113,9 +131,17 @@ function canConvertImportDeclarationForSpecifier(specifier: ImportSpecifier, sou return true; } -function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, declaration: ImportDeclaration | ImportSpecifier) { +function doChange( + changes: textChanges.ChangeTracker, + sourceFile: SourceFile, + declaration: ImportDeclaration | ImportSpecifier, +) { if (isImportSpecifier(declaration)) { - changes.replaceNode(sourceFile, declaration, factory.updateImportSpecifier(declaration, /*isTypeOnly*/ true, declaration.propertyName, declaration.name)); + changes.replaceNode( + sourceFile, + declaration, + factory.updateImportSpecifier(declaration, /*isTypeOnly*/ true, declaration.propertyName, declaration.name), + ); } else { const importClause = declaration.importClause as ImportClause; @@ -123,13 +149,21 @@ function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, de changes.replaceNodeWithNodes(sourceFile, declaration, [ factory.createImportDeclaration( getSynthesizedDeepClones(declaration.modifiers, /*includeTrivia*/ true), - factory.createImportClause(/*isTypeOnly*/ true, getSynthesizedDeepClone(importClause.name, /*includeTrivia*/ true), /*namedBindings*/ undefined), + factory.createImportClause( + /*isTypeOnly*/ true, + getSynthesizedDeepClone(importClause.name, /*includeTrivia*/ true), + /*namedBindings*/ undefined, + ), getSynthesizedDeepClone(declaration.moduleSpecifier, /*includeTrivia*/ true), getSynthesizedDeepClone(declaration.assertClause, /*includeTrivia*/ true), ), factory.createImportDeclaration( getSynthesizedDeepClones(declaration.modifiers, /*includeTrivia*/ true), - factory.createImportClause(/*isTypeOnly*/ true, /*name*/ undefined, getSynthesizedDeepClone(importClause.namedBindings, /*includeTrivia*/ true)), + factory.createImportClause( + /*isTypeOnly*/ true, + /*name*/ undefined, + getSynthesizedDeepClone(importClause.namedBindings, /*includeTrivia*/ true), + ), getSynthesizedDeepClone(declaration.moduleSpecifier, /*includeTrivia*/ true), getSynthesizedDeepClone(declaration.assertClause, /*includeTrivia*/ true), ), @@ -139,10 +173,19 @@ function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, de const newNamedBindings = importClause.namedBindings?.kind === SyntaxKind.NamedImports ? factory.updateNamedImports( importClause.namedBindings, - sameMap(importClause.namedBindings.elements, e => factory.updateImportSpecifier(e, /*isTypeOnly*/ false, e.propertyName, e.name)), + sameMap( + importClause.namedBindings.elements, + e => factory.updateImportSpecifier(e, /*isTypeOnly*/ false, e.propertyName, e.name), + ), ) : importClause.namedBindings; - const importDeclaration = factory.updateImportDeclaration(declaration, declaration.modifiers, factory.updateImportClause(importClause, /*isTypeOnly*/ true, importClause.name, newNamedBindings), declaration.moduleSpecifier, declaration.assertClause); + const importDeclaration = factory.updateImportDeclaration( + declaration, + declaration.modifiers, + factory.updateImportClause(importClause, /*isTypeOnly*/ true, importClause.name, newNamedBindings), + declaration.moduleSpecifier, + declaration.assertClause, + ); changes.replaceNode(sourceFile, declaration, importDeclaration); } } diff --git a/src/services/codefixes/convertTypedefToType.ts b/src/services/codefixes/convertTypedefToType.ts index 395ee58f1378f..8d0afaffe2ae6 100644 --- a/src/services/codefixes/convertTypedefToType.ts +++ b/src/services/codefixes/convertTypedefToType.ts @@ -43,7 +43,10 @@ registerCodeFix({ ); if (!node) return; - const changes = textChanges.ChangeTracker.with(context, t => doChange(t, node, context.sourceFile, newLineCharacter)); + const changes = textChanges.ChangeTracker.with( + context, + t => doChange(t, node, context.sourceFile, newLineCharacter), + ); if (changes.length > 0) { return [ diff --git a/src/services/codefixes/correctQualifiedNameToIndexedAccessType.ts b/src/services/codefixes/correctQualifiedNameToIndexedAccessType.ts index 3dbcb5e8f2180..f3dbb49a91e93 100644 --- a/src/services/codefixes/correctQualifiedNameToIndexedAccessType.ts +++ b/src/services/codefixes/correctQualifiedNameToIndexedAccessType.ts @@ -18,7 +18,11 @@ import { } from "../_namespaces/ts.codefix"; const fixId = "correctQualifiedNameToIndexedAccessType"; -const errorCodes = [Diagnostics.Cannot_access_0_1_because_0_is_a_type_but_not_a_namespace_Did_you_mean_to_retrieve_the_type_of_the_property_1_in_0_with_0_1.code]; +const errorCodes = [ + Diagnostics + .Cannot_access_0_1_because_0_is_a_type_but_not_a_namespace_Did_you_mean_to_retrieve_the_type_of_the_property_1_in_0_with_0_1 + .code, +]; registerCodeFix({ errorCodes, getCodeActions(context) { @@ -26,7 +30,15 @@ registerCodeFix({ if (!qualifiedName) return undefined; const changes = textChanges.ChangeTracker.with(context, t => doChange(t, context.sourceFile, qualifiedName)); const newText = `${qualifiedName.left.text}["${qualifiedName.right.text}"]`; - return [createCodeFixAction(fixId, changes, [Diagnostics.Rewrite_as_the_indexed_access_type_0, newText], fixId, Diagnostics.Rewrite_all_as_indexed_access_types)]; + return [ + createCodeFixAction( + fixId, + changes, + [Diagnostics.Rewrite_as_the_indexed_access_type_0, newText], + fixId, + Diagnostics.Rewrite_all_as_indexed_access_types, + ), + ]; }, fixIds: [fixId], getAllCodeActions: context => @@ -44,7 +56,11 @@ function getQualifiedName(sourceFile: SourceFile, pos: number): QualifiedName & return isIdentifier(qualifiedName.left) ? qualifiedName as QualifiedName & { left: Identifier; } : undefined; } -function doChange(changeTracker: textChanges.ChangeTracker, sourceFile: SourceFile, qualifiedName: QualifiedName): void { +function doChange( + changeTracker: textChanges.ChangeTracker, + sourceFile: SourceFile, + qualifiedName: QualifiedName, +): void { const rightText = qualifiedName.right.text; const replacement = factory.createIndexedAccessTypeNode( factory.createTypeReferenceNode(qualifiedName.left, /*typeArguments*/ undefined), diff --git a/src/services/codefixes/disableJsDiagnostics.ts b/src/services/codefixes/disableJsDiagnostics.ts index 09d7a00d0c6c5..f89dbfe7b0184 100644 --- a/src/services/codefixes/disableJsDiagnostics.ts +++ b/src/services/codefixes/disableJsDiagnostics.ts @@ -38,7 +38,8 @@ registerCodeFix({ return undefined; } - const newLineCharacter = sourceFile.checkJsDirective ? "" : getNewLineOrDefaultFromHost(host, formatContext.options); + const newLineCharacter = sourceFile.checkJsDirective ? "" + : getNewLineOrDefaultFromHost(host, formatContext.options); const fixes: CodeFixAction[] = [ // fixId unnecessary because adding `// @ts-nocheck` even once will ignore every error in the file. createCodeFixActionWithoutFixAll( @@ -56,7 +57,15 @@ registerCodeFix({ ]; if (textChanges.isValidLocationToAddComment(sourceFile, span.start)) { - fixes.unshift(createCodeFixAction(fixName, textChanges.ChangeTracker.with(context, t => makeChange(t, sourceFile, span.start)), Diagnostics.Ignore_this_error_message, fixId, Diagnostics.Add_ts_ignore_to_all_error_messages)); + fixes.unshift( + createCodeFixAction( + fixName, + textChanges.ChangeTracker.with(context, t => makeChange(t, sourceFile, span.start)), + Diagnostics.Ignore_this_error_message, + fixId, + Diagnostics.Add_ts_ignore_to_all_error_messages, + ), + ); } return fixes; @@ -72,7 +81,12 @@ registerCodeFix({ }, }); -function makeChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, position: number, seenLines?: Set) { +function makeChange( + changes: textChanges.ChangeTracker, + sourceFile: SourceFile, + position: number, + seenLines?: Set, +) { const { line: lineNumber } = getLineAndCharacterOfPosition(sourceFile, position); // Only need to add `// @ts-ignore` for a line once. if (!seenLines || tryAddToSet(seenLines, lineNumber)) { diff --git a/src/services/codefixes/fixAddMissingConstraint.ts b/src/services/codefixes/fixAddMissingConstraint.ts index df99139e709c7..7752f7a354f8b 100644 --- a/src/services/codefixes/fixAddMissingConstraint.ts +++ b/src/services/codefixes/fixAddMissingConstraint.ts @@ -43,9 +43,13 @@ const errorCodes = [ // Diagnostics.This_type_parameter_probably_needs_an_extends_0_constraint Diagnostics.Type_0_is_not_comparable_to_type_1.code, Diagnostics.Type_0_is_not_assignable_to_type_1_Two_different_types_with_this_name_exist_but_they_are_unrelated.code, - Diagnostics.Type_0_is_not_assignable_to_type_1_with_exactOptionalPropertyTypes_Colon_true_Consider_adding_undefined_to_the_types_of_the_target_s_properties.code, + Diagnostics + .Type_0_is_not_assignable_to_type_1_with_exactOptionalPropertyTypes_Colon_true_Consider_adding_undefined_to_the_types_of_the_target_s_properties + .code, Diagnostics.Type_0_is_not_assignable_to_type_1.code, - Diagnostics.Argument_of_type_0_is_not_assignable_to_parameter_of_type_1_with_exactOptionalPropertyTypes_Colon_true_Consider_adding_undefined_to_the_types_of_the_target_s_properties.code, + Diagnostics + .Argument_of_type_0_is_not_assignable_to_parameter_of_type_1_with_exactOptionalPropertyTypes_Colon_true_Consider_adding_undefined_to_the_types_of_the_target_s_properties + .code, Diagnostics.Property_0_is_incompatible_with_index_signature.code, Diagnostics.Property_0_in_type_1_is_not_assignable_to_type_2.code, Diagnostics.Type_0_does_not_satisfy_the_constraint_1.code, @@ -57,8 +61,19 @@ registerCodeFix({ const info = getInfo(program, sourceFile, span); if (info === undefined) return; - const changes = textChanges.ChangeTracker.with(context, t => addMissingConstraint(t, program, preferences, host, sourceFile, info)); - return [createCodeFixAction(fixId, changes, Diagnostics.Add_extends_constraint, fixId, Diagnostics.Add_extends_constraint_to_all_type_parameters)]; + const changes = textChanges.ChangeTracker.with( + context, + t => addMissingConstraint(t, program, preferences, host, sourceFile, info), + ); + return [ + createCodeFixAction( + fixId, + changes, + Diagnostics.Add_extends_constraint, + fixId, + Diagnostics.Add_extends_constraint_to_all_type_parameters, + ), + ]; }, fixIds: [fixId], getAllCodeActions: context => { @@ -86,11 +101,20 @@ interface Info { } function getInfo(program: Program, sourceFile: SourceFile, span: TextSpan): Info | undefined { - const diag = find(program.getSemanticDiagnostics(sourceFile), diag => diag.start === span.start && diag.length === span.length); + const diag = find( + program.getSemanticDiagnostics(sourceFile), + diag => diag.start === span.start && diag.length === span.length, + ); if (diag === undefined || diag.relatedInformation === undefined) return; - const related = find(diag.relatedInformation, related => related.code === Diagnostics.This_type_parameter_might_need_an_extends_0_constraint.code); - if (related === undefined || related.file === undefined || related.start === undefined || related.length === undefined) return; + const related = find( + diag.relatedInformation, + related => related.code === Diagnostics.This_type_parameter_might_need_an_extends_0_constraint.code, + ); + if ( + related === undefined || related.file === undefined || related.start === undefined + || related.length === undefined + ) return; let declaration = findAncestorMatchingSpan(related.file, createTextSpan(related.start, related.length)); if (declaration === undefined) return; @@ -105,14 +129,22 @@ function getInfo(program: Program, sourceFile: SourceFile, span: TextSpan): Info const token = getTokenAtPosition(sourceFile, span.start); const checker = program.getTypeChecker(); - const constraint = tryGetConstraintType(checker, token) || tryGetConstraintFromDiagnosticMessage(related.messageText); + const constraint = tryGetConstraintType(checker, token) + || tryGetConstraintFromDiagnosticMessage(related.messageText); return { constraint, declaration, token }; } return undefined; } -function addMissingConstraint(changes: textChanges.ChangeTracker, program: Program, preferences: UserPreferences, host: LanguageServiceHost, sourceFile: SourceFile, info: Info): void { +function addMissingConstraint( + changes: textChanges.ChangeTracker, + program: Program, + preferences: UserPreferences, + host: LanguageServiceHost, + sourceFile: SourceFile, + info: Info, +): void { const { declaration, constraint } = info; const checker = program.getTypeChecker(); @@ -123,9 +155,27 @@ function addMissingConstraint(changes: textChanges.ChangeTracker, program: Progr const scriptTarget = getEmitScriptTarget(program.getCompilerOptions()); const tracker = getNoopSymbolTrackerWithResolver({ program, host }); const importAdder = createImportAdder(sourceFile, program, preferences, host); - const typeNode = typeToAutoImportableTypeNode(checker, importAdder, constraint, /*contextNode*/ undefined, scriptTarget, /*flags*/ undefined, tracker); + const typeNode = typeToAutoImportableTypeNode( + checker, + importAdder, + constraint, + /*contextNode*/ undefined, + scriptTarget, + /*flags*/ undefined, + tracker, + ); if (typeNode) { - changes.replaceNode(sourceFile, declaration, factory.updateTypeParameterDeclaration(declaration, /*modifiers*/ undefined, declaration.name, typeNode, declaration.default)); + changes.replaceNode( + sourceFile, + declaration, + factory.updateTypeParameterDeclaration( + declaration, + /*modifiers*/ undefined, + declaration.name, + typeNode, + declaration.default, + ), + ); importAdder.writeFixes(changes); } } diff --git a/src/services/codefixes/fixAddMissingMember.ts b/src/services/codefixes/fixAddMissingMember.ts index 90b718fe8437d..8671f0a5c1fe3 100644 --- a/src/services/codefixes/fixAddMissingMember.ts +++ b/src/services/codefixes/fixAddMissingMember.ts @@ -160,28 +160,69 @@ registerCodeFix({ } if (info.kind === InfoKind.ObjectLiteral) { const changes = textChanges.ChangeTracker.with(context, t => addObjectLiteralProperties(t, context, info)); - return [createCodeFixAction(fixMissingProperties, changes, Diagnostics.Add_missing_properties, fixMissingProperties, Diagnostics.Add_all_missing_properties)]; + return [ + createCodeFixAction( + fixMissingProperties, + changes, + Diagnostics.Add_missing_properties, + fixMissingProperties, + Diagnostics.Add_all_missing_properties, + ), + ]; } if (info.kind === InfoKind.JsxAttributes) { const changes = textChanges.ChangeTracker.with(context, t => addJsxAttributes(t, context, info)); - return [createCodeFixAction(fixMissingAttributes, changes, Diagnostics.Add_missing_attributes, fixMissingAttributes, Diagnostics.Add_all_missing_attributes)]; + return [ + createCodeFixAction( + fixMissingAttributes, + changes, + Diagnostics.Add_missing_attributes, + fixMissingAttributes, + Diagnostics.Add_all_missing_attributes, + ), + ]; } if (info.kind === InfoKind.Function || info.kind === InfoKind.Signature) { const changes = textChanges.ChangeTracker.with(context, t => addFunctionDeclaration(t, context, info)); - return [createCodeFixAction(fixMissingFunctionDeclaration, changes, [Diagnostics.Add_missing_function_declaration_0, info.token.text], fixMissingFunctionDeclaration, Diagnostics.Add_all_missing_function_declarations)]; + return [ + createCodeFixAction( + fixMissingFunctionDeclaration, + changes, + [Diagnostics.Add_missing_function_declaration_0, info.token.text], + fixMissingFunctionDeclaration, + Diagnostics.Add_all_missing_function_declarations, + ), + ]; } if (info.kind === InfoKind.Enum) { - const changes = textChanges.ChangeTracker.with(context, t => addEnumMemberDeclaration(t, context.program.getTypeChecker(), info)); - return [createCodeFixAction(fixMissingMember, changes, [Diagnostics.Add_missing_enum_member_0, info.token.text], fixMissingMember, Diagnostics.Add_all_missing_members)]; + const changes = textChanges.ChangeTracker.with( + context, + t => addEnumMemberDeclaration(t, context.program.getTypeChecker(), info), + ); + return [ + createCodeFixAction( + fixMissingMember, + changes, + [Diagnostics.Add_missing_enum_member_0, info.token.text], + fixMissingMember, + Diagnostics.Add_all_missing_members, + ), + ]; } - return concatenate(getActionsForMissingMethodDeclaration(context, info), getActionsForMissingMemberDeclaration(context, info)); + return concatenate( + getActionsForMissingMethodDeclaration(context, info), + getActionsForMissingMemberDeclaration(context, info), + ); }, fixIds: [fixMissingMember, fixMissingFunctionDeclaration, fixMissingProperties, fixMissingAttributes], getAllCodeActions: context => { const { program, fixId } = context; const checker = program.getTypeChecker(); const seen = new Map(); - const typeDeclToMembers = new Map(); + const typeDeclToMembers = new Map< + ClassLikeDeclaration | InterfaceDeclaration | TypeLiteralNode, + TypeLikeDeclarationInfo[] + >(); return createCombinedCodeActions(textChanges.ChangeTracker.with(context, changes => { eachDiagnostic(context, errorCodes, diag => { @@ -189,7 +230,10 @@ registerCodeFix({ if (!info || !addToSeen(seen, getNodeId(info.parentDeclaration) + "#" + info.token.text)) { return; } - if (fixId === fixMissingFunctionDeclaration && (info.kind === InfoKind.Function || info.kind === InfoKind.Signature)) { + if ( + fixId === fixMissingFunctionDeclaration + && (info.kind === InfoKind.Function || info.kind === InfoKind.Signature) + ) { addFunctionDeclaration(changes, context, info); } else if (fixId === fixMissingProperties && info.kind === InfoKind.ObjectLiteral) { @@ -226,15 +270,39 @@ registerCodeFix({ const { parentDeclaration, declSourceFile, modifierFlags, token, call, isJSFile } = info; // Always prefer to add a method declaration if possible. if (call && !isPrivateIdentifier(token)) { - addMethodDeclaration(context, changes, call, token, modifierFlags & ModifierFlags.Static, parentDeclaration, declSourceFile); + addMethodDeclaration( + context, + changes, + call, + token, + modifierFlags & ModifierFlags.Static, + parentDeclaration, + declSourceFile, + ); } else { - if (isJSFile && !isInterfaceDeclaration(parentDeclaration) && !isTypeLiteralNode(parentDeclaration)) { - addMissingMemberInJs(changes, declSourceFile, parentDeclaration, token, !!(modifierFlags & ModifierFlags.Static)); + if ( + isJSFile && !isInterfaceDeclaration(parentDeclaration) + && !isTypeLiteralNode(parentDeclaration) + ) { + addMissingMemberInJs( + changes, + declSourceFile, + parentDeclaration, + token, + !!(modifierFlags & ModifierFlags.Static), + ); } else { const typeNode = getTypeNode(checker, parentDeclaration, token); - addPropertyDeclaration(changes, declSourceFile, parentDeclaration, token.text, typeNode, modifierFlags & ModifierFlags.Static); + addPropertyDeclaration( + changes, + declSourceFile, + parentDeclaration, + token.text, + typeNode, + modifierFlags & ModifierFlags.Static, + ); } } } @@ -293,7 +361,13 @@ interface SignatureInfo { readonly parentDeclaration: Node; } -function getInfo(sourceFile: SourceFile, tokenPos: number, errorCode: number, checker: TypeChecker, program: Program): Info | undefined { +function getInfo( + sourceFile: SourceFile, + tokenPos: number, + errorCode: number, + checker: TypeChecker, + program: Program, +): Info | undefined { // The identifier of the missing property. eg: // this.missing = 1; // ^^^^^^^ @@ -301,7 +375,10 @@ function getInfo(sourceFile: SourceFile, tokenPos: number, errorCode: number, ch const parent = token.parent; if (errorCode === Diagnostics.Argument_of_type_0_is_not_assignable_to_parameter_of_type_1.code) { - if (!(token.kind === SyntaxKind.OpenBraceToken && isObjectLiteralExpression(parent) && isCallExpression(parent.parent))) return undefined; + if ( + !(token.kind === SyntaxKind.OpenBraceToken && isObjectLiteralExpression(parent) + && isCallExpression(parent.parent)) + ) return undefined; const argIndex = findIndex(parent.parent.arguments, arg => arg === parent); if (argIndex < 0) return undefined; @@ -312,16 +389,33 @@ function getInfo(sourceFile: SourceFile, tokenPos: number, errorCode: number, ch const param = signature.parameters[argIndex].valueDeclaration; if (!(param && isParameter(param) && isIdentifier(param.name))) return undefined; - const properties = arrayFrom(checker.getUnmatchedProperties(checker.getTypeAtLocation(parent), checker.getParameterType(signature, argIndex), /*requireOptionalProperties*/ false, /*matchDiscriminantProperties*/ false)); + const properties = arrayFrom( + checker.getUnmatchedProperties( + checker.getTypeAtLocation(parent), + checker.getParameterType(signature, argIndex), + /*requireOptionalProperties*/ false, + /*matchDiscriminantProperties*/ false, + ), + ); if (!length(properties)) return undefined; return { kind: InfoKind.ObjectLiteral, token: param.name, properties, parentDeclaration: parent }; } if (!isMemberName(token)) return undefined; - if (isIdentifier(token) && hasInitializer(parent) && parent.initializer && isObjectLiteralExpression(parent.initializer)) { + if ( + isIdentifier(token) && hasInitializer(parent) && parent.initializer + && isObjectLiteralExpression(parent.initializer) + ) { const targetType = checker.getContextualType(token) || checker.getTypeAtLocation(token); - const properties = arrayFrom(checker.getUnmatchedProperties(checker.getTypeAtLocation(parent.initializer), targetType, /*requireOptionalProperties*/ false, /*matchDiscriminantProperties*/ false)); + const properties = arrayFrom( + checker.getUnmatchedProperties( + checker.getTypeAtLocation(parent.initializer), + targetType, + /*requireOptionalProperties*/ false, + /*matchDiscriminantProperties*/ false, + ), + ); if (!length(properties)) return undefined; return { kind: InfoKind.ObjectLiteral, token, properties, parentDeclaration: parent.initializer }; @@ -342,7 +436,14 @@ function getInfo(sourceFile: SourceFile, tokenPos: number, errorCode: number, ch return { kind: InfoKind.Signature, token, signature, sourceFile, parentDeclaration: findScope(token) }; } if (isCallExpression(parent) && parent.expression === token) { - return { kind: InfoKind.Function, token, call: parent, sourceFile, modifierFlags: ModifierFlags.None, parentDeclaration: findScope(token) }; + return { + kind: InfoKind.Function, + token, + call: parent, + sourceFile, + modifierFlags: ModifierFlags.None, + parentDeclaration: findScope(token), + }; } } @@ -355,15 +456,32 @@ function getInfo(sourceFile: SourceFile, tokenPos: number, errorCode: number, ch if (isIdentifier(token) && isCallExpression(parent.parent)) { const moduleDeclaration = find(symbol.declarations, isModuleDeclaration); const moduleDeclarationSourceFile = moduleDeclaration?.getSourceFile(); - if (moduleDeclaration && moduleDeclarationSourceFile && !isSourceFileFromLibrary(program, moduleDeclarationSourceFile)) { - return { kind: InfoKind.Function, token, call: parent.parent, sourceFile, modifierFlags: ModifierFlags.Export, parentDeclaration: moduleDeclaration }; + if ( + moduleDeclaration && moduleDeclarationSourceFile + && !isSourceFileFromLibrary(program, moduleDeclarationSourceFile) + ) { + return { + kind: InfoKind.Function, + token, + call: parent.parent, + sourceFile, + modifierFlags: ModifierFlags.Export, + parentDeclaration: moduleDeclaration, + }; } const moduleSourceFile = find(symbol.declarations, isSourceFile); if (sourceFile.commonJsModuleIndicator) return undefined; if (moduleSourceFile && !isSourceFileFromLibrary(program, moduleSourceFile)) { - return { kind: InfoKind.Function, token, call: parent.parent, sourceFile: moduleSourceFile, modifierFlags: ModifierFlags.Export, parentDeclaration: moduleSourceFile }; + return { + kind: InfoKind.Function, + token, + call: parent.parent, + sourceFile: moduleSourceFile, + modifierFlags: ModifierFlags.Export, + parentDeclaration: moduleSourceFile, + }; } } @@ -372,49 +490,95 @@ function getInfo(sourceFile: SourceFile, tokenPos: number, errorCode: number, ch if (!classDeclaration && isPrivateIdentifier(token)) return undefined; // Prefer to change the class instead of the interface if they are merged - const declaration = classDeclaration || find(symbol.declarations, d => isInterfaceDeclaration(d) || isTypeLiteralNode(d)) as InterfaceDeclaration | TypeLiteralNode | undefined; + const declaration = classDeclaration + || find(symbol.declarations, d => isInterfaceDeclaration(d) || isTypeLiteralNode(d)) as + | InterfaceDeclaration + | TypeLiteralNode + | undefined; if (declaration && !isSourceFileFromLibrary(program, declaration.getSourceFile())) { - const makeStatic = !isTypeLiteralNode(declaration) && ((leftExpressionType as TypeReference).target || leftExpressionType) !== checker.getDeclaredTypeOfSymbol(symbol); + const makeStatic = !isTypeLiteralNode(declaration) + && ((leftExpressionType as TypeReference).target || leftExpressionType) + !== checker.getDeclaredTypeOfSymbol(symbol); if (makeStatic && (isPrivateIdentifier(token) || isInterfaceDeclaration(declaration))) return undefined; const declSourceFile = declaration.getSourceFile(); - const modifierFlags = isTypeLiteralNode(declaration) ? ModifierFlags.None : - (makeStatic ? ModifierFlags.Static : ModifierFlags.None) | (startsWithUnderscore(token.text) ? ModifierFlags.Private : ModifierFlags.None); + const modifierFlags = isTypeLiteralNode(declaration) ? ModifierFlags.None + : (makeStatic ? ModifierFlags.Static : ModifierFlags.None) + | (startsWithUnderscore(token.text) ? ModifierFlags.Private : ModifierFlags.None); const isJSFile = isSourceFileJS(declSourceFile); const call = tryCast(parent.parent, isCallExpression); - return { kind: InfoKind.TypeLikeDeclaration, token, call, modifierFlags, parentDeclaration: declaration, declSourceFile, isJSFile }; + return { + kind: InfoKind.TypeLikeDeclaration, + token, + call, + modifierFlags, + parentDeclaration: declaration, + declSourceFile, + isJSFile, + }; } const enumDeclaration = find(symbol.declarations, isEnumDeclaration); - if (enumDeclaration && !(leftExpressionType.flags & TypeFlags.EnumLike) && !isPrivateIdentifier(token) && !isSourceFileFromLibrary(program, enumDeclaration.getSourceFile())) { + if ( + enumDeclaration && !(leftExpressionType.flags & TypeFlags.EnumLike) && !isPrivateIdentifier(token) + && !isSourceFileFromLibrary(program, enumDeclaration.getSourceFile()) + ) { return { kind: InfoKind.Enum, token, parentDeclaration: enumDeclaration }; } return undefined; } -function getActionsForMissingMemberDeclaration(context: CodeFixContext, info: TypeLikeDeclarationInfo): CodeFixAction[] | undefined { - return info.isJSFile ? singleElementArray(createActionForAddMissingMemberInJavascriptFile(context, info)) : - createActionsForAddMissingMemberInTypeScriptFile(context, info); +function getActionsForMissingMemberDeclaration( + context: CodeFixContext, + info: TypeLikeDeclarationInfo, +): CodeFixAction[] | undefined { + return info.isJSFile ? singleElementArray(createActionForAddMissingMemberInJavascriptFile(context, info)) + : createActionsForAddMissingMemberInTypeScriptFile(context, info); } -function createActionForAddMissingMemberInJavascriptFile(context: CodeFixContext, { parentDeclaration, declSourceFile, modifierFlags, token }: TypeLikeDeclarationInfo): CodeFixAction | undefined { +function createActionForAddMissingMemberInJavascriptFile( + context: CodeFixContext, + { parentDeclaration, declSourceFile, modifierFlags, token }: TypeLikeDeclarationInfo, +): CodeFixAction | undefined { if (isInterfaceDeclaration(parentDeclaration) || isTypeLiteralNode(parentDeclaration)) { return undefined; } - const changes = textChanges.ChangeTracker.with(context, t => addMissingMemberInJs(t, declSourceFile, parentDeclaration, token, !!(modifierFlags & ModifierFlags.Static))); + const changes = textChanges.ChangeTracker.with( + context, + t => addMissingMemberInJs( + t, + declSourceFile, + parentDeclaration, + token, + !!(modifierFlags & ModifierFlags.Static), + ), + ); if (changes.length === 0) { return undefined; } - const diagnostic = modifierFlags & ModifierFlags.Static ? Diagnostics.Initialize_static_property_0 : - isPrivateIdentifier(token) ? Diagnostics.Declare_a_private_field_named_0 : Diagnostics.Initialize_property_0_in_the_constructor; + const diagnostic = modifierFlags & ModifierFlags.Static ? Diagnostics.Initialize_static_property_0 + : isPrivateIdentifier(token) ? Diagnostics.Declare_a_private_field_named_0 + : Diagnostics.Initialize_property_0_in_the_constructor; - return createCodeFixAction(fixMissingMember, changes, [diagnostic, token.text], fixMissingMember, Diagnostics.Add_all_missing_members); + return createCodeFixAction( + fixMissingMember, + changes, + [diagnostic, token.text], + fixMissingMember, + Diagnostics.Add_all_missing_members, + ); } -function addMissingMemberInJs(changeTracker: textChanges.ChangeTracker, sourceFile: SourceFile, classDeclaration: ClassLikeDeclaration, token: Identifier | PrivateIdentifier, makeStatic: boolean): void { +function addMissingMemberInJs( + changeTracker: textChanges.ChangeTracker, + sourceFile: SourceFile, + classDeclaration: ClassLikeDeclaration, + token: Identifier | PrivateIdentifier, + makeStatic: boolean, +): void { const tokenName = token.text; if (makeStatic) { if (classDeclaration.kind === SyntaxKind.ClassExpression) { @@ -452,48 +616,92 @@ function addMissingMemberInJs(changeTracker: textChanges.ChangeTracker, sourceFi } function initializePropertyToUndefined(obj: Expression, propertyName: string) { - return factory.createExpressionStatement(factory.createAssignment(factory.createPropertyAccessExpression(obj, propertyName), createUndefined())); + return factory.createExpressionStatement( + factory.createAssignment(factory.createPropertyAccessExpression(obj, propertyName), createUndefined()), + ); } -function createActionsForAddMissingMemberInTypeScriptFile(context: CodeFixContext, { parentDeclaration, declSourceFile, modifierFlags, token }: TypeLikeDeclarationInfo): CodeFixAction[] | undefined { +function createActionsForAddMissingMemberInTypeScriptFile( + context: CodeFixContext, + { parentDeclaration, declSourceFile, modifierFlags, token }: TypeLikeDeclarationInfo, +): CodeFixAction[] | undefined { const memberName = token.text; const isStatic = modifierFlags & ModifierFlags.Static; const typeNode = getTypeNode(context.program.getTypeChecker(), parentDeclaration, token); - const addPropertyDeclarationChanges = (modifierFlags: ModifierFlags) => textChanges.ChangeTracker.with(context, t => addPropertyDeclaration(t, declSourceFile, parentDeclaration, memberName, typeNode, modifierFlags)); + const addPropertyDeclarationChanges = (modifierFlags: ModifierFlags) => + textChanges.ChangeTracker.with( + context, + t => addPropertyDeclaration(t, declSourceFile, parentDeclaration, memberName, typeNode, modifierFlags), + ); - const actions = [createCodeFixAction(fixMissingMember, addPropertyDeclarationChanges(modifierFlags & ModifierFlags.Static), [isStatic ? Diagnostics.Declare_static_property_0 : Diagnostics.Declare_property_0, memberName], fixMissingMember, Diagnostics.Add_all_missing_members)]; + const actions = [ + createCodeFixAction( + fixMissingMember, + addPropertyDeclarationChanges(modifierFlags & ModifierFlags.Static), + [isStatic ? Diagnostics.Declare_static_property_0 : Diagnostics.Declare_property_0, memberName], + fixMissingMember, + Diagnostics.Add_all_missing_members, + ), + ]; if (isStatic || isPrivateIdentifier(token)) { return actions; } if (modifierFlags & ModifierFlags.Private) { - actions.unshift(createCodeFixActionWithoutFixAll(fixMissingMember, addPropertyDeclarationChanges(ModifierFlags.Private), [Diagnostics.Declare_private_property_0, memberName])); + actions.unshift( + createCodeFixActionWithoutFixAll(fixMissingMember, addPropertyDeclarationChanges(ModifierFlags.Private), [ + Diagnostics.Declare_private_property_0, + memberName, + ]), + ); } actions.push(createAddIndexSignatureAction(context, declSourceFile, parentDeclaration, token.text, typeNode)); return actions; } -function getTypeNode(checker: TypeChecker, node: ClassLikeDeclaration | InterfaceDeclaration | TypeLiteralNode, token: Node) { +function getTypeNode( + checker: TypeChecker, + node: ClassLikeDeclaration | InterfaceDeclaration | TypeLiteralNode, + token: Node, +) { let typeNode: TypeNode | undefined; if (token.parent.parent.kind === SyntaxKind.BinaryExpression) { const binaryExpression = token.parent.parent as BinaryExpression; const otherExpression = token.parent === binaryExpression.left ? binaryExpression.right : binaryExpression.left; - const widenedType = checker.getWidenedType(checker.getBaseTypeOfLiteralType(checker.getTypeAtLocation(otherExpression))); + const widenedType = checker.getWidenedType( + checker.getBaseTypeOfLiteralType(checker.getTypeAtLocation(otherExpression)), + ); typeNode = checker.typeToTypeNode(widenedType, node, NodeBuilderFlags.NoTruncation); } else { const contextualType = checker.getContextualType(token.parent as Expression); - typeNode = contextualType ? checker.typeToTypeNode(contextualType, /*enclosingDeclaration*/ undefined, NodeBuilderFlags.NoTruncation) : undefined; + typeNode = contextualType + ? checker.typeToTypeNode(contextualType, /*enclosingDeclaration*/ undefined, NodeBuilderFlags.NoTruncation) + : undefined; } return typeNode || factory.createKeywordTypeNode(SyntaxKind.AnyKeyword); } -function addPropertyDeclaration(changeTracker: textChanges.ChangeTracker, sourceFile: SourceFile, node: ClassLikeDeclaration | InterfaceDeclaration | TypeLiteralNode, tokenName: string, typeNode: TypeNode, modifierFlags: ModifierFlags): void { - const modifiers = modifierFlags ? factory.createNodeArray(factory.createModifiersFromModifierFlags(modifierFlags)) : undefined; +function addPropertyDeclaration( + changeTracker: textChanges.ChangeTracker, + sourceFile: SourceFile, + node: ClassLikeDeclaration | InterfaceDeclaration | TypeLiteralNode, + tokenName: string, + typeNode: TypeNode, + modifierFlags: ModifierFlags, +): void { + const modifiers = modifierFlags ? factory.createNodeArray(factory.createModifiersFromModifierFlags(modifierFlags)) + : undefined; const property = isClassLike(node) - ? factory.createPropertyDeclaration(modifiers, tokenName, /*questionOrExclamationToken*/ undefined, typeNode, /*initializer*/ undefined) + ? factory.createPropertyDeclaration( + modifiers, + tokenName, + /*questionOrExclamationToken*/ undefined, + typeNode, + /*initializer*/ undefined, + ) : factory.createPropertySignature(/*modifiers*/ undefined, tokenName, /*questionToken*/ undefined, typeNode); const lastProp = getNodeToInsertPropertyAfter(node); @@ -506,7 +714,9 @@ function addPropertyDeclaration(changeTracker: textChanges.ChangeTracker, source } // Gets the last of the first run of PropertyDeclarations, or undefined if the class does not start with a PropertyDeclaration. -function getNodeToInsertPropertyAfter(node: ClassLikeDeclaration | InterfaceDeclaration | TypeLiteralNode): PropertyDeclaration | undefined { +function getNodeToInsertPropertyAfter( + node: ClassLikeDeclaration | InterfaceDeclaration | TypeLiteralNode, +): PropertyDeclaration | undefined { let res: PropertyDeclaration | undefined; for (const member of node.members) { if (!isPropertyDeclaration(member)) break; @@ -515,7 +725,13 @@ function getNodeToInsertPropertyAfter(node: ClassLikeDeclaration | InterfaceDecl return res; } -function createAddIndexSignatureAction(context: CodeFixContext, sourceFile: SourceFile, node: ClassLikeDeclaration | InterfaceDeclaration | TypeLiteralNode, tokenName: string, typeNode: TypeNode): CodeFixAction { +function createAddIndexSignatureAction( + context: CodeFixContext, + sourceFile: SourceFile, + node: ClassLikeDeclaration | InterfaceDeclaration | TypeLiteralNode, + tokenName: string, + typeNode: TypeNode, +): CodeFixAction { // Index signatures cannot have the static modifier. const stringTypeNode = factory.createKeywordTypeNode(SyntaxKind.StringKeyword); const indexingParameter = factory.createParameterDeclaration( @@ -532,22 +748,52 @@ function createAddIndexSignatureAction(context: CodeFixContext, sourceFile: Sour typeNode, ); - const changes = textChanges.ChangeTracker.with(context, t => t.insertMemberAtStart(sourceFile, node, indexSignature)); + const changes = textChanges.ChangeTracker.with( + context, + t => t.insertMemberAtStart(sourceFile, node, indexSignature), + ); // No fixId here because code-fix-all currently only works on adding individual named properties. - return createCodeFixActionWithoutFixAll(fixMissingMember, changes, [Diagnostics.Add_index_signature_for_property_0, tokenName]); + return createCodeFixActionWithoutFixAll(fixMissingMember, changes, [ + Diagnostics.Add_index_signature_for_property_0, + tokenName, + ]); } -function getActionsForMissingMethodDeclaration(context: CodeFixContext, info: TypeLikeDeclarationInfo): CodeFixAction[] | undefined { +function getActionsForMissingMethodDeclaration( + context: CodeFixContext, + info: TypeLikeDeclarationInfo, +): CodeFixAction[] | undefined { const { parentDeclaration, declSourceFile, modifierFlags, token, call } = info; if (call === undefined) { return undefined; } const methodName = token.text; - const addMethodDeclarationChanges = (modifierFlags: ModifierFlags) => textChanges.ChangeTracker.with(context, t => addMethodDeclaration(context, t, call, token, modifierFlags, parentDeclaration, declSourceFile)); - const actions = [createCodeFixAction(fixMissingMember, addMethodDeclarationChanges(modifierFlags & ModifierFlags.Static), [modifierFlags & ModifierFlags.Static ? Diagnostics.Declare_static_method_0 : Diagnostics.Declare_method_0, methodName], fixMissingMember, Diagnostics.Add_all_missing_members)]; + const addMethodDeclarationChanges = (modifierFlags: ModifierFlags) => + textChanges.ChangeTracker.with( + context, + t => addMethodDeclaration(context, t, call, token, modifierFlags, parentDeclaration, declSourceFile), + ); + const actions = [ + createCodeFixAction( + fixMissingMember, + addMethodDeclarationChanges(modifierFlags & ModifierFlags.Static), + [ + modifierFlags & ModifierFlags.Static ? Diagnostics.Declare_static_method_0 + : Diagnostics.Declare_method_0, + methodName, + ], + fixMissingMember, + Diagnostics.Add_all_missing_members, + ), + ]; if (modifierFlags & ModifierFlags.Private) { - actions.unshift(createCodeFixActionWithoutFixAll(fixMissingMember, addMethodDeclarationChanges(ModifierFlags.Private), [Diagnostics.Declare_private_method_0, methodName])); + actions.unshift( + createCodeFixActionWithoutFixAll(fixMissingMember, addMethodDeclarationChanges(ModifierFlags.Private), [ + Diagnostics.Declare_private_method_0, + methodName, + ]), + ); } return actions; } @@ -563,7 +809,15 @@ function addMethodDeclaration( ): void { const importAdder = createImportAdder(sourceFile, context.program, context.preferences, context.host); const kind = isClassLike(parentDeclaration) ? SyntaxKind.MethodDeclaration : SyntaxKind.MethodSignature; - const signatureDeclaration = createSignatureDeclarationFromCallExpression(kind, context, importAdder, callExpression, name, modifierFlags, parentDeclaration) as MethodDeclaration; + const signatureDeclaration = createSignatureDeclarationFromCallExpression( + kind, + context, + importAdder, + callExpression, + name, + modifierFlags, + parentDeclaration, + ) as MethodDeclaration; const containingMethodDeclaration = tryGetContainingMethodDeclaration(parentDeclaration, callExpression); if (containingMethodDeclaration) { changes.insertNodeAfter(sourceFile, containingMethodDeclaration, signatureDeclaration); @@ -574,7 +828,11 @@ function addMethodDeclaration( importAdder.writeFixes(changes); } -function addEnumMemberDeclaration(changes: textChanges.ChangeTracker, checker: TypeChecker, { token, parentDeclaration }: EnumInfo) { +function addEnumMemberDeclaration( + changes: textChanges.ChangeTracker, + checker: TypeChecker, + { token, parentDeclaration }: EnumInfo, +) { /** * create initializer only literal enum that has string initializer. * value of initializer is a string literal that equal to name of enum member. @@ -585,7 +843,10 @@ function addEnumMemberDeclaration(changes: textChanges.ChangeTracker, checker: T return !!(type && type.flags & TypeFlags.StringLike); }); - const enumMember = factory.createEnumMember(token, hasStringInitializer ? factory.createStringLiteral(token.text) : undefined); + const enumMember = factory.createEnumMember( + token, + hasStringInitializer ? factory.createStringLiteral(token.text) : undefined, + ); changes.replaceNode( parentDeclaration.getSourceFile(), parentDeclaration, @@ -602,18 +863,46 @@ function addEnumMemberDeclaration(changes: textChanges.ChangeTracker, checker: T ); } -function addFunctionDeclaration(changes: textChanges.ChangeTracker, context: CodeFixContextBase, info: FunctionInfo | SignatureInfo) { +function addFunctionDeclaration( + changes: textChanges.ChangeTracker, + context: CodeFixContextBase, + info: FunctionInfo | SignatureInfo, +) { const quotePreference = getQuotePreference(context.sourceFile, context.preferences); const importAdder = createImportAdder(context.sourceFile, context.program, context.preferences, context.host); const functionDeclaration = info.kind === InfoKind.Function - ? createSignatureDeclarationFromCallExpression(SyntaxKind.FunctionDeclaration, context, importAdder, info.call, idText(info.token), info.modifierFlags, info.parentDeclaration) - : createSignatureDeclarationFromSignature(SyntaxKind.FunctionDeclaration, context, quotePreference, info.signature, createStubbedBody(Diagnostics.Function_not_implemented.message, quotePreference), info.token, /*modifiers*/ undefined, /*optional*/ undefined, /*enclosingDeclaration*/ undefined, importAdder); + ? createSignatureDeclarationFromCallExpression( + SyntaxKind.FunctionDeclaration, + context, + importAdder, + info.call, + idText(info.token), + info.modifierFlags, + info.parentDeclaration, + ) + : createSignatureDeclarationFromSignature( + SyntaxKind.FunctionDeclaration, + context, + quotePreference, + info.signature, + createStubbedBody(Diagnostics.Function_not_implemented.message, quotePreference), + info.token, + /*modifiers*/ undefined, + /*optional*/ undefined, + /*enclosingDeclaration*/ undefined, + importAdder, + ); if (functionDeclaration === undefined) { Debug.fail("fixMissingFunctionDeclaration codefix got unexpected error."); } isReturnStatement(info.parentDeclaration) - ? changes.insertNodeBefore(info.sourceFile, info.parentDeclaration, functionDeclaration, /*blankLineBetween*/ true) + ? changes.insertNodeBefore( + info.sourceFile, + info.parentDeclaration, + functionDeclaration, + /*blankLineBetween*/ true, + ) : changes.insertNodeAtEndOfScope(info.sourceFile, info.parentDeclaration, functionDeclaration); importAdder.writeFixes(changes); } @@ -625,38 +914,76 @@ function addJsxAttributes(changes: textChanges.ChangeTracker, context: CodeFixCo const jsxAttributesNode = info.parentDeclaration.attributes; const hasSpreadAttribute = some(jsxAttributesNode.properties, isJsxSpreadAttribute); const attrs = map(info.attributes, attr => { - const value = tryGetValueFromType(context, checker, importAdder, quotePreference, checker.getTypeOfSymbol(attr), info.parentDeclaration); + const value = tryGetValueFromType( + context, + checker, + importAdder, + quotePreference, + checker.getTypeOfSymbol(attr), + info.parentDeclaration, + ); const name = factory.createIdentifier(attr.name); - const jsxAttribute = factory.createJsxAttribute(name, factory.createJsxExpression(/*dotDotDotToken*/ undefined, value)); + const jsxAttribute = factory.createJsxAttribute( + name, + factory.createJsxExpression(/*dotDotDotToken*/ undefined, value), + ); // formattingScanner requires the Identifier to have a context for scanning attributes with "-" (data-foo). setParent(name, jsxAttribute); return jsxAttribute; }); - const jsxAttributes = factory.createJsxAttributes(hasSpreadAttribute ? [...attrs, ...jsxAttributesNode.properties] : [...jsxAttributesNode.properties, ...attrs]); + const jsxAttributes = factory.createJsxAttributes( + hasSpreadAttribute ? [...attrs, ...jsxAttributesNode.properties] : [...jsxAttributesNode.properties, ...attrs], + ); const options = { prefix: jsxAttributesNode.pos === jsxAttributesNode.end ? " " : undefined }; changes.replaceNode(context.sourceFile, jsxAttributesNode, jsxAttributes, options); importAdder.writeFixes(changes); } -function addObjectLiteralProperties(changes: textChanges.ChangeTracker, context: CodeFixContextBase, info: ObjectLiteralInfo) { +function addObjectLiteralProperties( + changes: textChanges.ChangeTracker, + context: CodeFixContextBase, + info: ObjectLiteralInfo, +) { const importAdder = createImportAdder(context.sourceFile, context.program, context.preferences, context.host); const quotePreference = getQuotePreference(context.sourceFile, context.preferences); const target = getEmitScriptTarget(context.program.getCompilerOptions()); const checker = context.program.getTypeChecker(); const props = map(info.properties, prop => { - const initializer = tryGetValueFromType(context, checker, importAdder, quotePreference, checker.getTypeOfSymbol(prop), info.parentDeclaration); - return factory.createPropertyAssignment(createPropertyNameFromSymbol(prop, target, quotePreference, checker), initializer); + const initializer = tryGetValueFromType( + context, + checker, + importAdder, + quotePreference, + checker.getTypeOfSymbol(prop), + info.parentDeclaration, + ); + return factory.createPropertyAssignment( + createPropertyNameFromSymbol(prop, target, quotePreference, checker), + initializer, + ); }); const options = { leadingTriviaOption: textChanges.LeadingTriviaOption.Exclude, trailingTriviaOption: textChanges.TrailingTriviaOption.Exclude, indentation: info.indentation, }; - changes.replaceNode(context.sourceFile, info.parentDeclaration, factory.createObjectLiteralExpression([...info.parentDeclaration.properties, ...props], /*multiLine*/ true), options); + changes.replaceNode( + context.sourceFile, + info.parentDeclaration, + factory.createObjectLiteralExpression([...info.parentDeclaration.properties, ...props], /*multiLine*/ true), + options, + ); importAdder.writeFixes(changes); } -function tryGetValueFromType(context: CodeFixContextBase, checker: TypeChecker, importAdder: ImportAdder, quotePreference: QuotePreference, type: Type, enclosingDeclaration: Node | undefined): Expression { +function tryGetValueFromType( + context: CodeFixContextBase, + checker: TypeChecker, + importAdder: ImportAdder, + quotePreference: QuotePreference, + type: Type, + enclosingDeclaration: Node | undefined, +): Expression { if (type.flags & TypeFlags.AnyOrUnknown) { return createUndefined(); } @@ -674,8 +1001,14 @@ function tryGetValueFromType(context: CodeFixContextBase, checker: TypeChecker, } if (type.flags & TypeFlags.EnumLike) { const enumMember = type.symbol.exports ? firstOrUndefinedIterator(type.symbol.exports.values()) : type.symbol; - const name = checker.symbolToExpression(type.symbol.parent ? type.symbol.parent : type.symbol, SymbolFlags.Value, /*enclosingDeclaration*/ undefined, /*flags*/ undefined); - return enumMember === undefined || name === undefined ? factory.createNumericLiteral(0) : factory.createPropertyAccessExpression(name, checker.symbolToString(enumMember)); + const name = checker.symbolToExpression( + type.symbol.parent ? type.symbol.parent : type.symbol, + SymbolFlags.Value, + /*enclosingDeclaration*/ undefined, + /*flags*/ undefined, + ); + return enumMember === undefined || name === undefined ? factory.createNumericLiteral(0) + : factory.createPropertyAccessExpression(name, checker.symbolToString(enumMember)); } if (type.flags & TypeFlags.NumberLiteral) { return factory.createNumericLiteral((type as NumberLiteralType).value); @@ -684,16 +1017,23 @@ function tryGetValueFromType(context: CodeFixContextBase, checker: TypeChecker, return factory.createBigIntLiteral((type as BigIntLiteralType).value); } if (type.flags & TypeFlags.StringLiteral) { - return factory.createStringLiteral((type as StringLiteralType).value, /* isSingleQuote */ quotePreference === QuotePreference.Single); + return factory.createStringLiteral( + (type as StringLiteralType).value, + /* isSingleQuote */ quotePreference === QuotePreference.Single, + ); } if (type.flags & TypeFlags.BooleanLiteral) { - return (type === checker.getFalseType() || type === checker.getFalseType(/*fresh*/ true)) ? factory.createFalse() : factory.createTrue(); + return (type === checker.getFalseType() || type === checker.getFalseType(/*fresh*/ true)) + ? factory.createFalse() : factory.createTrue(); } if (type.flags & TypeFlags.Null) { return factory.createNull(); } if (type.flags & TypeFlags.Union) { - const expression = firstDefined((type as UnionType).types, t => tryGetValueFromType(context, checker, importAdder, quotePreference, t, enclosingDeclaration)); + const expression = firstDefined( + (type as UnionType).types, + t => tryGetValueFromType(context, checker, importAdder, quotePreference, t, enclosingDeclaration), + ); return expression ?? createUndefined(); } if (checker.isArrayLikeType(type)) { @@ -701,19 +1041,40 @@ function tryGetValueFromType(context: CodeFixContextBase, checker: TypeChecker, } if (isObjectLiteralType(type)) { const props = map(checker.getPropertiesOfType(type), prop => { - const initializer = tryGetValueFromType(context, checker, importAdder, quotePreference, checker.getTypeOfSymbol(prop), enclosingDeclaration); + const initializer = tryGetValueFromType( + context, + checker, + importAdder, + quotePreference, + checker.getTypeOfSymbol(prop), + enclosingDeclaration, + ); return factory.createPropertyAssignment(prop.name, initializer); }); return factory.createObjectLiteralExpression(props, /*multiLine*/ true); } if (getObjectFlags(type) & ObjectFlags.Anonymous) { - const decl = find(type.symbol.declarations || emptyArray, or(isFunctionTypeNode, isMethodSignature, isMethodDeclaration)); + const decl = find( + type.symbol.declarations || emptyArray, + or(isFunctionTypeNode, isMethodSignature, isMethodDeclaration), + ); if (decl === undefined) return createUndefined(); const signature = checker.getSignaturesOfType(type, SignatureKind.Call); if (signature === undefined) return createUndefined(); - const func = createSignatureDeclarationFromSignature(SyntaxKind.FunctionExpression, context, quotePreference, signature[0], createStubbedBody(Diagnostics.Function_not_implemented.message, quotePreference), /*name*/ undefined, /*modifiers*/ undefined, /*optional*/ undefined, /*enclosingDeclaration*/ enclosingDeclaration, importAdder) as FunctionExpression | undefined; + const func = createSignatureDeclarationFromSignature( + SyntaxKind.FunctionExpression, + context, + quotePreference, + signature[0], + createStubbedBody(Diagnostics.Function_not_implemented.message, quotePreference), + /*name*/ undefined, + /*modifiers*/ undefined, + /*optional*/ undefined, + /*enclosingDeclaration*/ enclosingDeclaration, + importAdder, + ) as FunctionExpression | undefined; return func ?? createUndefined(); } if (getObjectFlags(type) & ObjectFlags.Class) { @@ -723,7 +1084,11 @@ function tryGetValueFromType(context: CodeFixContextBase, checker: TypeChecker, const constructorDeclaration = getFirstConstructorWithBody(classDeclaration); if (constructorDeclaration && length(constructorDeclaration.parameters)) return createUndefined(); - return factory.createNewExpression(factory.createIdentifier(type.symbol.name), /*typeArguments*/ undefined, /*argumentsArray*/ undefined); + return factory.createNewExpression( + factory.createIdentifier(type.symbol.name), + /*typeArguments*/ undefined, + /*argumentsArray*/ undefined, + ); } return createUndefined(); } @@ -733,8 +1098,9 @@ function createUndefined() { } function isObjectLiteralType(type: Type) { - return (type.flags & TypeFlags.Object) && - ((getObjectFlags(type) & ObjectFlags.ObjectLiteral) || (type.symbol && tryCast(singleOrUndefined(type.symbol.declarations), isTypeLiteralNode))); + return (type.flags & TypeFlags.Object) + && ((getObjectFlags(type) & ObjectFlags.ObjectLiteral) + || (type.symbol && tryCast(singleOrUndefined(type.symbol.declarations), isTypeLiteralNode))); } function getUnmatchedAttributes(checker: TypeChecker, target: ScriptTarget, source: JsxOpeningLikeElement) { @@ -756,10 +1122,19 @@ function getUnmatchedAttributes(checker: TypeChecker, target: ScriptTarget, sour } } } - return filter(targetProps, targetProp => isIdentifierText(targetProp.name, target, LanguageVariant.JSX) && !((targetProp.flags & SymbolFlags.Optional || getCheckFlags(targetProp) & CheckFlags.Partial) || seenNames.has(targetProp.escapedName))); + return filter( + targetProps, + targetProp => + isIdentifierText(targetProp.name, target, LanguageVariant.JSX) + && !((targetProp.flags & SymbolFlags.Optional || getCheckFlags(targetProp) & CheckFlags.Partial) + || seenNames.has(targetProp.escapedName)), + ); } -function tryGetContainingMethodDeclaration(node: ClassLikeDeclaration | InterfaceDeclaration | TypeLiteralNode, callExpression: CallExpression) { +function tryGetContainingMethodDeclaration( + node: ClassLikeDeclaration | InterfaceDeclaration | TypeLiteralNode, + callExpression: CallExpression, +) { if (isTypeLiteralNode(node)) { return undefined; } @@ -767,12 +1142,26 @@ function tryGetContainingMethodDeclaration(node: ClassLikeDeclaration | Interfac return declaration && declaration.parent === node ? declaration : undefined; } -function createPropertyNameFromSymbol(symbol: Symbol, target: ScriptTarget, quotePreference: QuotePreference, checker: TypeChecker) { +function createPropertyNameFromSymbol( + symbol: Symbol, + target: ScriptTarget, + quotePreference: QuotePreference, + checker: TypeChecker, +) { if (isTransientSymbol(symbol)) { - const prop = checker.symbolToNode(symbol, SymbolFlags.Value, /*enclosingDeclaration*/ undefined, NodeBuilderFlags.WriteComputedProps); + const prop = checker.symbolToNode( + symbol, + SymbolFlags.Value, + /*enclosingDeclaration*/ undefined, + NodeBuilderFlags.WriteComputedProps, + ); if (prop && isComputedPropertyName(prop)) return prop; } - return createPropertyNameNodeForIdentifierOrLiteral(symbol.name, target, quotePreference === QuotePreference.Single); + return createPropertyNameNodeForIdentifierOrLiteral( + symbol.name, + target, + quotePreference === QuotePreference.Single, + ); } function findScope(node: Node) { diff --git a/src/services/codefixes/fixAddMissingNewOperator.ts b/src/services/codefixes/fixAddMissingNewOperator.ts index 8a44e267fb5f7..3bd1762741811 100644 --- a/src/services/codefixes/fixAddMissingNewOperator.ts +++ b/src/services/codefixes/fixAddMissingNewOperator.ts @@ -23,10 +23,19 @@ registerCodeFix({ getCodeActions(context) { const { sourceFile, span } = context; const changes = textChanges.ChangeTracker.with(context, t => addMissingNewOperator(t, sourceFile, span)); - return [createCodeFixAction(fixId, changes, Diagnostics.Add_missing_new_operator_to_call, fixId, Diagnostics.Add_missing_new_operator_to_all_calls)]; + return [ + createCodeFixAction( + fixId, + changes, + Diagnostics.Add_missing_new_operator_to_call, + fixId, + Diagnostics.Add_missing_new_operator_to_all_calls, + ), + ]; }, fixIds: [fixId], - getAllCodeActions: context => codeFixAll(context, errorCodes, (changes, diag) => addMissingNewOperator(changes, context.sourceFile, diag)), + getAllCodeActions: context => + codeFixAll(context, errorCodes, (changes, diag) => addMissingNewOperator(changes, context.sourceFile, diag)), }); function addMissingNewOperator(changes: textChanges.ChangeTracker, sourceFile: SourceFile, span: TextSpan): void { diff --git a/src/services/codefixes/fixAddModuleReferTypeMissingTypeof.ts b/src/services/codefixes/fixAddModuleReferTypeMissingTypeof.ts index 830e76d60f9c8..12e6eb02a576c 100644 --- a/src/services/codefixes/fixAddModuleReferTypeMissingTypeof.ts +++ b/src/services/codefixes/fixAddModuleReferTypeMissingTypeof.ts @@ -16,7 +16,9 @@ import { const fixIdAddMissingTypeof = "fixAddModuleReferTypeMissingTypeof"; const fixId = fixIdAddMissingTypeof; -const errorCodes = [Diagnostics.Module_0_does_not_refer_to_a_type_but_is_used_as_a_type_here_Did_you_mean_typeof_import_0.code]; +const errorCodes = [ + Diagnostics.Module_0_does_not_refer_to_a_type_but_is_used_as_a_type_here_Did_you_mean_typeof_import_0.code, +]; registerCodeFix({ errorCodes, @@ -24,10 +26,17 @@ registerCodeFix({ const { sourceFile, span } = context; const importType = getImportTypeNode(sourceFile, span.start); const changes = textChanges.ChangeTracker.with(context, t => doChange(t, sourceFile, importType)); - return [createCodeFixAction(fixId, changes, Diagnostics.Add_missing_typeof, fixId, Diagnostics.Add_missing_typeof)]; + return [ + createCodeFixAction(fixId, changes, Diagnostics.Add_missing_typeof, fixId, Diagnostics.Add_missing_typeof), + ]; }, fixIds: [fixId], - getAllCodeActions: context => codeFixAll(context, errorCodes, (changes, diag) => doChange(changes, context.sourceFile, getImportTypeNode(diag.file, diag.start))), + getAllCodeActions: context => + codeFixAll( + context, + errorCodes, + (changes, diag) => doChange(changes, context.sourceFile, getImportTypeNode(diag.file, diag.start)), + ), }); function getImportTypeNode(sourceFile: SourceFile, pos: number): ImportTypeNode { @@ -38,6 +47,13 @@ function getImportTypeNode(sourceFile: SourceFile, pos: number): ImportTypeNode } function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, importType: ImportTypeNode) { - const newTypeNode = factory.updateImportTypeNode(importType, importType.argument, importType.assertions, importType.qualifier, importType.typeArguments, /*isTypeOf*/ true); + const newTypeNode = factory.updateImportTypeNode( + importType, + importType.argument, + importType.assertions, + importType.qualifier, + importType.typeArguments, + /*isTypeOf*/ true, + ); changes.replaceNode(sourceFile, importType, newTypeNode); } diff --git a/src/services/codefixes/fixAddVoidToPromise.ts b/src/services/codefixes/fixAddVoidToPromise.ts index 82114594c92fb..10230e22d8cae 100644 --- a/src/services/codefixes/fixAddVoidToPromise.ts +++ b/src/services/codefixes/fixAddVoidToPromise.ts @@ -34,26 +34,52 @@ import { const fixName = "addVoidToPromise"; const fixId = "addVoidToPromise"; const errorCodes = [ - Diagnostics.Expected_1_argument_but_got_0_new_Promise_needs_a_JSDoc_hint_to_produce_a_resolve_that_can_be_called_without_arguments.code, + Diagnostics + .Expected_1_argument_but_got_0_new_Promise_needs_a_JSDoc_hint_to_produce_a_resolve_that_can_be_called_without_arguments + .code, Diagnostics.Expected_0_arguments_but_got_1_Did_you_forget_to_include_void_in_your_type_argument_to_Promise.code, ]; registerCodeFix({ errorCodes, fixIds: [fixId], getCodeActions(context) { - const changes = textChanges.ChangeTracker.with(context, t => makeChange(t, context.sourceFile, context.span, context.program)); + const changes = textChanges.ChangeTracker.with( + context, + t => makeChange(t, context.sourceFile, context.span, context.program), + ); if (changes.length > 0) { - return [createCodeFixAction(fixName, changes, Diagnostics.Add_void_to_Promise_resolved_without_a_value, fixId, Diagnostics.Add_void_to_all_Promises_resolved_without_a_value)]; + return [ + createCodeFixAction( + fixName, + changes, + Diagnostics.Add_void_to_Promise_resolved_without_a_value, + fixId, + Diagnostics.Add_void_to_all_Promises_resolved_without_a_value, + ), + ]; } }, getAllCodeActions(context: CodeFixAllContext) { - return codeFixAll(context, errorCodes, (changes, diag) => makeChange(changes, diag.file, diag, context.program, new Set())); + return codeFixAll( + context, + errorCodes, + (changes, diag) => makeChange(changes, diag.file, diag, context.program, new Set()), + ); }, }); -function makeChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, span: TextSpan, program: Program, seen?: Set) { +function makeChange( + changes: textChanges.ChangeTracker, + sourceFile: SourceFile, + span: TextSpan, + program: Program, + seen?: Set, +) { const node = getTokenAtPosition(sourceFile, span.start); - if (!isIdentifier(node) || !isCallExpression(node.parent) || node.parent.expression !== node || node.parent.arguments.length !== 0) return; + if ( + !isIdentifier(node) || !isCallExpression(node.parent) || node.parent.expression !== node + || node.parent.arguments.length !== 0 + ) return; const checker = program.getTypeChecker(); const symbol = checker.getSymbolAtLocation(node); @@ -70,8 +96,11 @@ function makeChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, if (some(typeArguments)) { // append ` | void` to type argument const typeArgument = typeArguments[0]; - const needsParens = !isUnionTypeNode(typeArgument) && !isParenthesizedTypeNode(typeArgument) && - isParenthesizedTypeNode(factory.createUnionTypeNode([typeArgument, factory.createKeywordTypeNode(SyntaxKind.VoidKeyword)]).types[0]); + const needsParens = !isUnionTypeNode(typeArgument) && !isParenthesizedTypeNode(typeArgument) + && isParenthesizedTypeNode( + factory.createUnionTypeNode([typeArgument, factory.createKeywordTypeNode(SyntaxKind.VoidKeyword)]) + .types[0], + ); if (needsParens) { changes.insertText(sourceFile, typeArgument.pos, "("); } @@ -86,7 +115,11 @@ function makeChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, if (!parameterType || parameterType.flags & TypeFlags.AnyOrUnknown) { // give the expression a type changes.insertText(sourceFile, decl.parent.parent.end, `)`); - changes.insertText(sourceFile, skipTrivia(sourceFile.text, decl.parent.parent.pos), `/** @type {Promise} */(`); + changes.insertText( + sourceFile, + skipTrivia(sourceFile.text, decl.parent.parent.pos), + `/** @type {Promise} */(`, + ); } } else { @@ -102,7 +135,10 @@ function getEffectiveTypeArguments(node: NewExpression) { if (isInJSFile(node)) { if (isParenthesizedExpression(node.parent)) { const jsDocType = getJSDocTypeTag(node.parent)?.typeExpression.type; - if (jsDocType && isTypeReferenceNode(jsDocType) && isIdentifier(jsDocType.typeName) && idText(jsDocType.typeName) === "Promise") { + if ( + jsDocType && isTypeReferenceNode(jsDocType) && isIdentifier(jsDocType.typeName) + && idText(jsDocType.typeName) === "Promise" + ) { return jsDocType.typeArguments; } } diff --git a/src/services/codefixes/fixAwaitInSyncFunction.ts b/src/services/codefixes/fixAwaitInSyncFunction.ts index e1f78e928cd00..79ed7d04ceaca 100644 --- a/src/services/codefixes/fixAwaitInSyncFunction.ts +++ b/src/services/codefixes/fixAwaitInSyncFunction.ts @@ -40,7 +40,15 @@ registerCodeFix({ const nodes = getNodes(sourceFile, span.start); if (!nodes) return undefined; const changes = textChanges.ChangeTracker.with(context, t => doChange(t, sourceFile, nodes)); - return [createCodeFixAction(fixId, changes, Diagnostics.Add_async_modifier_to_containing_function, fixId, Diagnostics.Add_all_missing_async_modifiers)]; + return [ + createCodeFixAction( + fixId, + changes, + Diagnostics.Add_async_modifier_to_containing_function, + fixId, + Diagnostics.Add_all_missing_async_modifiers, + ), + ]; }, fixIds: [fixId], getAllCodeActions: function getAllCodeActionsToFixAwaitInSyncFunction(context) { @@ -58,15 +66,18 @@ function getReturnType(expr: FunctionDeclaration | MethodDeclaration | FunctionE return expr.type; } if ( - isVariableDeclaration(expr.parent) && - expr.parent.type && - isFunctionTypeNode(expr.parent.type) + isVariableDeclaration(expr.parent) + && expr.parent.type + && isFunctionTypeNode(expr.parent.type) ) { return expr.parent.type.type; } } -function getNodes(sourceFile: SourceFile, start: number): { insertBefore: Node; returnType: TypeNode | undefined; } | undefined { +function getNodes( + sourceFile: SourceFile, + start: number, +): { insertBefore: Node; returnType: TypeNode | undefined; } | undefined { const token = getTokenAtPosition(sourceFile, start); const containingFunction = getContainingFunction(token); if (!containingFunction) { @@ -84,7 +95,8 @@ function getNodes(sourceFile: SourceFile, start: number): { insertBefore: Node; break; case SyntaxKind.ArrowFunction: const kind = containingFunction.typeParameters ? SyntaxKind.LessThanToken : SyntaxKind.OpenParenToken; - insertBefore = findChildOfKind(containingFunction, kind, sourceFile) || first(containingFunction.parameters); + insertBefore = findChildOfKind(containingFunction, kind, sourceFile) + || first(containingFunction.parameters); break; default: return; @@ -104,7 +116,11 @@ function doChange( if (returnType) { const entityName = getEntityNameFromTypeNode(returnType); if (!entityName || entityName.kind !== SyntaxKind.Identifier || entityName.text !== "Promise") { - changes.replaceNode(sourceFile, returnType, factory.createTypeReferenceNode("Promise", factory.createNodeArray([returnType]))); + changes.replaceNode( + sourceFile, + returnType, + factory.createTypeReferenceNode("Promise", factory.createNodeArray([returnType])), + ); } } changes.insertModifierBefore(sourceFile, SyntaxKind.AsyncKeyword, insertBefore); diff --git a/src/services/codefixes/fixCannotFindModule.ts b/src/services/codefixes/fixCannotFindModule.ts index d128045f7f075..66970931e89de 100644 --- a/src/services/codefixes/fixCannotFindModule.ts +++ b/src/services/codefixes/fixCannotFindModule.ts @@ -35,7 +35,14 @@ registerCodeFix({ const typesPackageName = getTypesPackageNameToInstall(packageName, host, context.errorCode); return typesPackageName === undefined ? [] - : [createCodeFixAction(fixName, /*changes*/ [], [Diagnostics.Install_0, typesPackageName], fixIdInstallTypesPackage, Diagnostics.Install_all_missing_types_packages, getInstallCommand(sourceFile.fileName, typesPackageName))]; + : [createCodeFixAction( + fixName, + /*changes*/ [], + [Diagnostics.Install_0, typesPackageName], + fixIdInstallTypesPackage, + Diagnostics.Install_all_missing_types_packages, + getInstallCommand(sourceFile.fileName, typesPackageName), + )]; }, fixIds: [fixIdInstallTypesPackage], getAllCodeActions: context => { @@ -69,7 +76,11 @@ function tryGetImportedPackageName(sourceFile: SourceFile, pos: number): string return isExternalModuleNameRelative(packageName) ? undefined : packageName; } -function getTypesPackageNameToInstall(packageName: string, host: LanguageServiceHost, diagCode: number): string | undefined { +function getTypesPackageNameToInstall( + packageName: string, + host: LanguageServiceHost, + diagCode: number, +): string | undefined { return diagCode === errorCodeCannotFindModule ? (JsTyping.nodeCoreModules.has(packageName) ? "@types/node" : undefined) : (host.isKnownTypesPackageName?.(packageName) ? getTypesPackageName(packageName) : undefined); diff --git a/src/services/codefixes/fixClassDoesntImplementInheritedAbstractMember.ts b/src/services/codefixes/fixClassDoesntImplementInheritedAbstractMember.ts index 44c14f724c126..1d5bbe3d2c929 100644 --- a/src/services/codefixes/fixClassDoesntImplementInheritedAbstractMember.ts +++ b/src/services/codefixes/fixClassDoesntImplementInheritedAbstractMember.ts @@ -33,8 +33,18 @@ registerCodeFix({ errorCodes, getCodeActions: function getCodeActionsToFixClassNotImplementingInheritedMembers(context) { const { sourceFile, span } = context; - const changes = textChanges.ChangeTracker.with(context, t => addMissingMembers(getClass(sourceFile, span.start), sourceFile, context, t, context.preferences)); - return changes.length === 0 ? undefined : [createCodeFixAction(fixId, changes, Diagnostics.Implement_inherited_abstract_class, fixId, Diagnostics.Implement_all_inherited_abstract_classes)]; + const changes = textChanges.ChangeTracker.with( + context, + t => addMissingMembers(getClass(sourceFile, span.start), sourceFile, context, t, context.preferences), + ); + return changes.length === 0 ? undefined + : [createCodeFixAction( + fixId, + changes, + Diagnostics.Implement_inherited_abstract_class, + fixId, + Diagnostics.Implement_all_inherited_abstract_classes, + )]; }, fixIds: [fixId], getAllCodeActions: function getAllCodeActionsToFixClassDoesntImplementInheritedAbstractMember(context) { @@ -55,17 +65,33 @@ function getClass(sourceFile: SourceFile, pos: number): ClassLikeDeclaration { return cast(token.parent, isClassLike); } -function addMissingMembers(classDeclaration: ClassLikeDeclaration, sourceFile: SourceFile, context: TypeConstructionContext, changeTracker: textChanges.ChangeTracker, preferences: UserPreferences): void { +function addMissingMembers( + classDeclaration: ClassLikeDeclaration, + sourceFile: SourceFile, + context: TypeConstructionContext, + changeTracker: textChanges.ChangeTracker, + preferences: UserPreferences, +): void { const extendsNode = getEffectiveBaseTypeNode(classDeclaration)!; const checker = context.program.getTypeChecker(); const instantiatedExtendsType = checker.getTypeAtLocation(extendsNode); // Note that this is ultimately derived from a map indexed by symbol names, // so duplicates cannot occur. - const abstractAndNonPrivateExtendsSymbols = checker.getPropertiesOfType(instantiatedExtendsType).filter(symbolPointsToNonPrivateAndAbstractMember); + const abstractAndNonPrivateExtendsSymbols = checker.getPropertiesOfType(instantiatedExtendsType).filter( + symbolPointsToNonPrivateAndAbstractMember, + ); const importAdder = createImportAdder(sourceFile, context.program, preferences, context.host); - createMissingMemberNodes(classDeclaration, abstractAndNonPrivateExtendsSymbols, sourceFile, context, preferences, importAdder, member => changeTracker.insertMemberAtStart(sourceFile, classDeclaration, member as ClassElement)); + createMissingMemberNodes( + classDeclaration, + abstractAndNonPrivateExtendsSymbols, + sourceFile, + context, + preferences, + importAdder, + member => changeTracker.insertMemberAtStart(sourceFile, classDeclaration, member as ClassElement), + ); importAdder.writeFixes(changeTracker); } diff --git a/src/services/codefixes/fixClassIncorrectlyImplementsInterface.ts b/src/services/codefixes/fixClassIncorrectlyImplementsInterface.ts index 7c5e3652af32a..ed7c2083f657d 100644 --- a/src/services/codefixes/fixClassIncorrectlyImplementsInterface.ts +++ b/src/services/codefixes/fixClassIncorrectlyImplementsInterface.ts @@ -40,7 +40,8 @@ import { const errorCodes = [ Diagnostics.Class_0_incorrectly_implements_interface_1.code, - Diagnostics.Class_0_incorrectly_implements_class_1_Did_you_mean_to_extend_1_and_inherit_its_members_as_a_subclass.code, + Diagnostics.Class_0_incorrectly_implements_class_1_Did_you_mean_to_extend_1_and_inherit_its_members_as_a_subclass + .code, ]; const fixId = "fixClassIncorrectlyImplementsInterface"; // TODO: share a group with fixClassDoesntImplementInheritedAbstractMember? registerCodeFix({ @@ -48,10 +49,28 @@ registerCodeFix({ getCodeActions(context) { const { sourceFile, span } = context; const classDeclaration = getClass(sourceFile, span.start); - return mapDefined(getEffectiveImplementsTypeNodes(classDeclaration), implementedTypeNode => { - const changes = textChanges.ChangeTracker.with(context, t => addMissingDeclarations(context, implementedTypeNode, sourceFile, classDeclaration, t, context.preferences)); - return changes.length === 0 ? undefined : createCodeFixAction(fixId, changes, [Diagnostics.Implement_interface_0, implementedTypeNode.getText(sourceFile)], fixId, Diagnostics.Implement_all_unimplemented_interfaces); - }); + return mapDefined( + getEffectiveImplementsTypeNodes(classDeclaration), + implementedTypeNode => { + const changes = textChanges.ChangeTracker.with(context, t => + addMissingDeclarations( + context, + implementedTypeNode, + sourceFile, + classDeclaration, + t, + context.preferences, + )); + return changes.length === 0 ? undefined + : createCodeFixAction( + fixId, + changes, + [Diagnostics.Implement_interface_0, implementedTypeNode.getText(sourceFile)], + fixId, + Diagnostics.Implement_all_unimplemented_interfaces, + ); + }, + ); }, fixIds: [fixId], getAllCodeActions(context) { @@ -60,7 +79,14 @@ registerCodeFix({ const classDeclaration = getClass(diag.file, diag.start); if (addToSeen(seenClassDeclarations, getNodeId(classDeclaration))) { for (const implementedTypeNode of getEffectiveImplementsTypeNodes(classDeclaration)!) { - addMissingDeclarations(context, implementedTypeNode, diag.file, classDeclaration, changes, context.preferences); + addMissingDeclarations( + context, + implementedTypeNode, + diag.file, + classDeclaration, + changes, + context.preferences, + ); } } }); @@ -68,7 +94,10 @@ registerCodeFix({ }); function getClass(sourceFile: SourceFile, pos: number): ClassLikeDeclaration { - return Debug.checkDefined(getContainingClass(getTokenAtPosition(sourceFile, pos)), "There should be a containing class"); + return Debug.checkDefined( + getContainingClass(getTokenAtPosition(sourceFile, pos)), + "There should be a containing class", + ); } function symbolPointsToNonPrivateMember(symbol: Symbol) { @@ -89,7 +118,9 @@ function addMissingDeclarations( // so duplicates cannot occur. const implementedType = checker.getTypeAtLocation(implementedTypeNode) as InterfaceType; const implementedTypeSymbols = checker.getPropertiesOfType(implementedType); - const nonPrivateAndNotExistedInHeritageClauseMembers = implementedTypeSymbols.filter(and(symbolPointsToNonPrivateMember, symbol => !maybeHeritageClauseSymbol.has(symbol.escapedName))); + const nonPrivateAndNotExistedInHeritageClauseMembers = implementedTypeSymbols.filter( + and(symbolPointsToNonPrivateMember, symbol => !maybeHeritageClauseSymbol.has(symbol.escapedName)), + ); const classType = checker.getTypeAtLocation(classDeclaration); const constructor = find(classDeclaration.members, m => isConstructorDeclaration(m)); @@ -102,18 +133,39 @@ function addMissingDeclarations( } const importAdder = createImportAdder(sourceFile, context.program, preferences, context.host); - createMissingMemberNodes(classDeclaration, nonPrivateAndNotExistedInHeritageClauseMembers, sourceFile, context, preferences, importAdder, member => insertInterfaceMemberNode(sourceFile, classDeclaration, member as ClassElement)); + createMissingMemberNodes( + classDeclaration, + nonPrivateAndNotExistedInHeritageClauseMembers, + sourceFile, + context, + preferences, + importAdder, + member => insertInterfaceMemberNode(sourceFile, classDeclaration, member as ClassElement), + ); importAdder.writeFixes(changeTracker); function createMissingIndexSignatureDeclaration(type: InterfaceType, kind: IndexKind): void { const indexInfoOfKind = checker.getIndexInfoOfType(type, kind); if (indexInfoOfKind) { - insertInterfaceMemberNode(sourceFile, classDeclaration, checker.indexInfoToIndexSignatureDeclaration(indexInfoOfKind, classDeclaration, /*flags*/ undefined, getNoopSymbolTrackerWithResolver(context))!); + insertInterfaceMemberNode( + sourceFile, + classDeclaration, + checker.indexInfoToIndexSignatureDeclaration( + indexInfoOfKind, + classDeclaration, + /*flags*/ undefined, + getNoopSymbolTrackerWithResolver(context), + )!, + ); } } // Either adds the node at the top of the class, or if there's a constructor right after that - function insertInterfaceMemberNode(sourceFile: SourceFile, cls: ClassLikeDeclaration | InterfaceDeclaration, newElement: ClassElement): void { + function insertInterfaceMemberNode( + sourceFile: SourceFile, + cls: ClassLikeDeclaration | InterfaceDeclaration, + newElement: ClassElement, + ): void { if (constructor) { changeTracker.insertNodeAfter(sourceFile, constructor, newElement); } diff --git a/src/services/codefixes/fixClassSuperMustPrecedeThisAccess.ts b/src/services/codefixes/fixClassSuperMustPrecedeThisAccess.ts index 66032b9f315ee..cf2d21b4c9012 100644 --- a/src/services/codefixes/fixClassSuperMustPrecedeThisAccess.ts +++ b/src/services/codefixes/fixClassSuperMustPrecedeThisAccess.ts @@ -33,7 +33,15 @@ registerCodeFix({ if (!nodes) return undefined; const { constructor, superCall } = nodes; const changes = textChanges.ChangeTracker.with(context, t => doChange(t, sourceFile, constructor, superCall)); - return [createCodeFixAction(fixId, changes, Diagnostics.Make_super_call_the_first_statement_in_the_constructor, fixId, Diagnostics.Make_all_super_calls_the_first_statement_in_their_constructor)]; + return [ + createCodeFixAction( + fixId, + changes, + Diagnostics.Make_super_call_the_first_statement_in_the_constructor, + fixId, + Diagnostics.Make_all_super_calls_the_first_statement_in_their_constructor, + ), + ]; }, fixIds: [fixId], getAllCodeActions(context) { @@ -50,19 +58,29 @@ registerCodeFix({ }, }); -function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, constructor: ConstructorDeclaration, superCall: ExpressionStatement): void { +function doChange( + changes: textChanges.ChangeTracker, + sourceFile: SourceFile, + constructor: ConstructorDeclaration, + superCall: ExpressionStatement, +): void { changes.insertNodeAtConstructorStart(sourceFile, constructor, superCall); changes.delete(sourceFile, superCall); } -function getNodes(sourceFile: SourceFile, pos: number): { readonly constructor: ConstructorDeclaration; readonly superCall: ExpressionStatement; } | undefined { +function getNodes( + sourceFile: SourceFile, + pos: number, +): { readonly constructor: ConstructorDeclaration; readonly superCall: ExpressionStatement; } | undefined { const token = getTokenAtPosition(sourceFile, pos); if (token.kind !== SyntaxKind.ThisKeyword) return undefined; const constructor = getContainingFunction(token) as ConstructorDeclaration; const superCall = findSuperCall(constructor.body!); // figure out if the `this` access is actually inside the supercall // i.e. super(this.a), since in that case we won't suggest a fix - return superCall && !superCall.expression.arguments.some(arg => isPropertyAccessExpression(arg) && arg.expression === token) ? { constructor, superCall } : undefined; + return superCall + && !superCall.expression.arguments.some(arg => isPropertyAccessExpression(arg) && arg.expression === token) + ? { constructor, superCall } : undefined; } function findSuperCall(n: Node): ExpressionStatement & { expression: CallExpression; } | undefined { diff --git a/src/services/codefixes/fixConstructorForDerivedNeedSuperCall.ts b/src/services/codefixes/fixConstructorForDerivedNeedSuperCall.ts index 20e0cb3b35d9a..e4455024b3af8 100644 --- a/src/services/codefixes/fixConstructorForDerivedNeedSuperCall.ts +++ b/src/services/codefixes/fixConstructorForDerivedNeedSuperCall.ts @@ -23,10 +23,23 @@ registerCodeFix({ const { sourceFile, span } = context; const ctr = getNode(sourceFile, span.start); const changes = textChanges.ChangeTracker.with(context, t => doChange(t, sourceFile, ctr)); - return [createCodeFixAction(fixId, changes, Diagnostics.Add_missing_super_call, fixId, Diagnostics.Add_all_missing_super_calls)]; + return [ + createCodeFixAction( + fixId, + changes, + Diagnostics.Add_missing_super_call, + fixId, + Diagnostics.Add_all_missing_super_calls, + ), + ]; }, fixIds: [fixId], - getAllCodeActions: context => codeFixAll(context, errorCodes, (changes, diag) => doChange(changes, context.sourceFile, getNode(diag.file, diag.start))), + getAllCodeActions: context => + codeFixAll( + context, + errorCodes, + (changes, diag) => doChange(changes, context.sourceFile, getNode(diag.file, diag.start)), + ), }); function getNode(sourceFile: SourceFile, pos: number): ConstructorDeclaration { @@ -36,6 +49,8 @@ function getNode(sourceFile: SourceFile, pos: number): ConstructorDeclaration { } function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, ctr: ConstructorDeclaration) { - const superCall = factory.createExpressionStatement(factory.createCallExpression(factory.createSuper(), /*typeArguments*/ undefined, /*argumentsArray*/ emptyArray)); + const superCall = factory.createExpressionStatement( + factory.createCallExpression(factory.createSuper(), /*typeArguments*/ undefined, /*argumentsArray*/ emptyArray), + ); changes.insertNodeAtConstructorStart(sourceFile, ctr, superCall); } diff --git a/src/services/codefixes/fixEnableJsxFlag.ts b/src/services/codefixes/fixEnableJsxFlag.ts index 6d00ac88e072b..daeae293dbf7c 100644 --- a/src/services/codefixes/fixEnableJsxFlag.ts +++ b/src/services/codefixes/fixEnableJsxFlag.ts @@ -23,7 +23,11 @@ registerCodeFix({ const changes = textChanges.ChangeTracker.with(context, changeTracker => doChange(changeTracker, configFile)); return [ - createCodeFixActionWithoutFixAll(fixID, changes, Diagnostics.Enable_the_jsx_flag_in_your_configuration_file), + createCodeFixActionWithoutFixAll( + fixID, + changes, + Diagnostics.Enable_the_jsx_flag_in_your_configuration_file, + ), ]; }, fixIds: [fixID], diff --git a/src/services/codefixes/fixExpectedComma.ts b/src/services/codefixes/fixExpectedComma.ts index 352760d482a28..c2cdca8f82288 100644 --- a/src/services/codefixes/fixExpectedComma.ts +++ b/src/services/codefixes/fixExpectedComma.ts @@ -51,10 +51,10 @@ interface Info { function getInfo(sourceFile: SourceFile, pos: number, _: number): Info | undefined { const node = getTokenAtPosition(sourceFile, pos); - return (node.kind === SyntaxKind.SemicolonToken && - node.parent && - (isObjectLiteralExpression(node.parent) || - isArrayLiteralExpression(node.parent))) ? { node } : undefined; + return (node.kind === SyntaxKind.SemicolonToken + && node.parent + && (isObjectLiteralExpression(node.parent) + || isArrayLiteralExpression(node.parent))) ? { node } : undefined; } function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, { node }: Info): void { diff --git a/src/services/codefixes/fixExtendsInterfaceBecomesImplements.ts b/src/services/codefixes/fixExtendsInterfaceBecomesImplements.ts index 65595a78b8b6a..3e32a9ac6c21e 100644 --- a/src/services/codefixes/fixExtendsInterfaceBecomesImplements.ts +++ b/src/services/codefixes/fixExtendsInterfaceBecomesImplements.ts @@ -25,8 +25,19 @@ registerCodeFix({ const nodes = getNodes(sourceFile, context.span.start); if (!nodes) return undefined; const { extendsToken, heritageClauses } = nodes; - const changes = textChanges.ChangeTracker.with(context, t => doChanges(t, sourceFile, extendsToken, heritageClauses)); - return [createCodeFixAction(fixId, changes, Diagnostics.Change_extends_to_implements, fixId, Diagnostics.Change_all_extended_interfaces_to_implements)]; + const changes = textChanges.ChangeTracker.with( + context, + t => doChanges(t, sourceFile, extendsToken, heritageClauses), + ); + return [ + createCodeFixAction( + fixId, + changes, + Diagnostics.Change_extends_to_implements, + fixId, + Diagnostics.Change_all_extended_interfaces_to_implements, + ), + ]; }, fixIds: [fixId], getAllCodeActions: context => @@ -43,18 +54,27 @@ function getNodes(sourceFile: SourceFile, pos: number) { return extendsToken.kind === SyntaxKind.ExtendsKeyword ? { extendsToken, heritageClauses } : undefined; } -function doChanges(changes: textChanges.ChangeTracker, sourceFile: SourceFile, extendsToken: Node, heritageClauses: readonly HeritageClause[]): void { +function doChanges( + changes: textChanges.ChangeTracker, + sourceFile: SourceFile, + extendsToken: Node, + heritageClauses: readonly HeritageClause[], +): void { changes.replaceNode(sourceFile, extendsToken, factory.createToken(SyntaxKind.ImplementsKeyword)); // If there is already an implements clause, replace the implements keyword with a comma. if ( - heritageClauses.length === 2 && - heritageClauses[0].token === SyntaxKind.ExtendsKeyword && - heritageClauses[1].token === SyntaxKind.ImplementsKeyword + heritageClauses.length === 2 + && heritageClauses[0].token === SyntaxKind.ExtendsKeyword + && heritageClauses[1].token === SyntaxKind.ImplementsKeyword ) { const implementsToken = heritageClauses[1].getFirstToken()!; const implementsFullStart = implementsToken.getFullStart(); - changes.replaceRange(sourceFile, { pos: implementsFullStart, end: implementsFullStart }, factory.createToken(SyntaxKind.CommaToken)); + changes.replaceRange( + sourceFile, + { pos: implementsFullStart, end: implementsFullStart }, + factory.createToken(SyntaxKind.CommaToken), + ); // Rough heuristic: delete trailing whitespace after keyword so that it's not excessive. // (Trailing because leading might be indentation, which is more sensitive.) diff --git a/src/services/codefixes/fixForgottenThisPropertyAccess.ts b/src/services/codefixes/fixForgottenThisPropertyAccess.ts index 1bd0de54296ee..a26bf23f3c0fb 100644 --- a/src/services/codefixes/fixForgottenThisPropertyAccess.ts +++ b/src/services/codefixes/fixForgottenThisPropertyAccess.ts @@ -21,7 +21,9 @@ const fixId = "forgottenThisPropertyAccess"; const didYouMeanStaticMemberCode = Diagnostics.Cannot_find_name_0_Did_you_mean_the_static_member_1_0.code; const errorCodes = [ Diagnostics.Cannot_find_name_0_Did_you_mean_the_instance_member_this_0.code, - Diagnostics.Private_identifiers_are_only_allowed_in_class_bodies_and_may_only_be_used_as_part_of_a_class_member_declaration_property_access_or_on_the_left_hand_side_of_an_in_expression.code, + Diagnostics + .Private_identifiers_are_only_allowed_in_class_bodies_and_may_only_be_used_as_part_of_a_class_member_declaration_property_access_or_on_the_left_hand_side_of_an_in_expression + .code, didYouMeanStaticMemberCode, ]; registerCodeFix({ @@ -33,7 +35,15 @@ registerCodeFix({ return undefined; } const changes = textChanges.ChangeTracker.with(context, t => doChange(t, sourceFile, info)); - return [createCodeFixAction(fixId, changes, [Diagnostics.Add_0_to_unresolved_variable, info.className || "this"], fixId, Diagnostics.Add_qualifier_to_all_unresolved_variables_matching_a_member_name)]; + return [ + createCodeFixAction( + fixId, + changes, + [Diagnostics.Add_0_to_unresolved_variable, info.className || "this"], + fixId, + Diagnostics.Add_qualifier_to_all_unresolved_variables_matching_a_member_name, + ), + ]; }, fixIds: [fixId], getAllCodeActions: context => @@ -51,12 +61,22 @@ interface Info { function getInfo(sourceFile: SourceFile, pos: number, diagCode: number): Info | undefined { const node = getTokenAtPosition(sourceFile, pos); if (isIdentifier(node) || isPrivateIdentifier(node)) { - return { node, className: diagCode === didYouMeanStaticMemberCode ? getContainingClass(node)!.name!.text : undefined }; + return { + node, + className: diagCode === didYouMeanStaticMemberCode ? getContainingClass(node)!.name!.text : undefined, + }; } } function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, { node, className }: Info): void { // TODO (https://github.com/Microsoft/TypeScript/issues/21246): use shared helper suppressLeadingAndTrailingTrivia(node); - changes.replaceNode(sourceFile, node, factory.createPropertyAccessExpression(className ? factory.createIdentifier(className) : factory.createThis(), node)); + changes.replaceNode( + sourceFile, + node, + factory.createPropertyAccessExpression( + className ? factory.createIdentifier(className) : factory.createThis(), + node, + ), + ); } diff --git a/src/services/codefixes/fixImplicitThis.ts b/src/services/codefixes/fixImplicitThis.ts index 9a867574cac10..074d492b1c6e2 100644 --- a/src/services/codefixes/fixImplicitThis.ts +++ b/src/services/codefixes/fixImplicitThis.ts @@ -34,7 +34,9 @@ registerCodeFix({ const changes = textChanges.ChangeTracker.with(context, t => { diagnostic = doChange(t, sourceFile, span.start, program.getTypeChecker()); }); - return diagnostic ? [createCodeFixAction(fixId, changes, diagnostic, fixId, Diagnostics.Fix_all_implicit_this_errors)] : emptyArray; + return diagnostic + ? [createCodeFixAction(fixId, changes, diagnostic, fixId, Diagnostics.Fix_all_implicit_this_errors)] + : emptyArray; }, fixIds: [fixId], getAllCodeActions: context => @@ -43,14 +45,21 @@ registerCodeFix({ }), }); -function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, pos: number, checker: TypeChecker): DiagnosticOrDiagnosticAndArguments | undefined { +function doChange( + changes: textChanges.ChangeTracker, + sourceFile: SourceFile, + pos: number, + checker: TypeChecker, +): DiagnosticOrDiagnosticAndArguments | undefined { const token = getTokenAtPosition(sourceFile, pos); if (!isThis(token)) return undefined; const fn = getThisContainer(token, /*includeArrowFunctions*/ false, /*includeClassComputedPropertyName*/ false); if (!isFunctionDeclaration(fn) && !isFunctionExpression(fn)) return undefined; - if (!isSourceFile(getThisContainer(fn, /*includeArrowFunctions*/ false, /*includeClassComputedPropertyName*/ false))) { // 'this' is defined outside, convert to arrow function + if ( + !isSourceFile(getThisContainer(fn, /*includeArrowFunctions*/ false, /*includeClassComputedPropertyName*/ false)) + ) { // 'this' is defined outside, convert to arrow function const fnKeyword = Debug.checkDefined(findChildOfKind(fn, SyntaxKind.FunctionKeyword, sourceFile)); const { name } = fn; const body = Debug.checkDefined(fn.body); // Should be defined because the function contained a 'this' expression diff --git a/src/services/codefixes/fixImportNonExportedMember.ts b/src/services/codefixes/fixImportNonExportedMember.ts index 51202cc8c32e2..60f7a6a2c8576 100644 --- a/src/services/codefixes/fixImportNonExportedMember.ts +++ b/src/services/codefixes/fixImportNonExportedMember.ts @@ -53,7 +53,15 @@ registerCodeFix({ if (info === undefined) return undefined; const changes = textChanges.ChangeTracker.with(context, t => doChange(t, program, info)); - return [createCodeFixAction(fixId, changes, [Diagnostics.Export_0_from_module_1, info.exportName.node.text, info.moduleSpecifier], fixId, Diagnostics.Export_all_referenced_locals)]; + return [ + createCodeFixAction( + fixId, + changes, + [Diagnostics.Export_0_from_module_1, info.exportName.node.text, info.moduleSpecifier], + fixId, + Diagnostics.Export_all_referenced_locals, + ), + ]; }, getAllCodeActions(context) { const { program } = context; @@ -65,7 +73,10 @@ registerCodeFix({ if (info === undefined) return undefined; const { exportName, node, moduleSourceFile } = info; - if (tryGetExportDeclaration(moduleSourceFile, exportName.isTypeOnly) === undefined && canHaveExportModifier(node)) { + if ( + tryGetExportDeclaration(moduleSourceFile, exportName.isTypeOnly) === undefined + && canHaveExportModifier(node) + ) { changes.insertExportModifier(moduleSourceFile, node); } else { @@ -84,10 +95,19 @@ registerCodeFix({ const exportDeclaration = tryGetExportDeclaration(moduleSourceFile, /*isTypeOnly*/ true); if (exportDeclaration && exportDeclaration.isTypeOnly) { doChanges(changes, program, moduleSourceFile, moduleExports.typeOnlyExports, exportDeclaration); - doChanges(changes, program, moduleSourceFile, moduleExports.exports, tryGetExportDeclaration(moduleSourceFile, /*isTypeOnly*/ false)); + doChanges( + changes, + program, + moduleSourceFile, + moduleExports.exports, + tryGetExportDeclaration(moduleSourceFile, /*isTypeOnly*/ false), + ); } else { - doChanges(changes, program, moduleSourceFile, [...moduleExports.exports, ...moduleExports.typeOnlyExports], exportDeclaration); + doChanges(changes, program, moduleSourceFile, [ + ...moduleExports.exports, + ...moduleExports.typeOnlyExports, + ], exportDeclaration); } }); })); @@ -117,7 +137,8 @@ function getInfo(sourceFile: SourceFile, pos: number, program: Program): Info | const importDeclaration = findAncestor(token, isImportDeclaration); if (importDeclaration === undefined) return undefined; - const moduleSpecifier = isStringLiteral(importDeclaration.moduleSpecifier) ? importDeclaration.moduleSpecifier.text : undefined; + const moduleSpecifier = isStringLiteral(importDeclaration.moduleSpecifier) + ? importDeclaration.moduleSpecifier.text : undefined; if (moduleSpecifier === undefined) return undefined; const resolvedModule = getResolvedModule(sourceFile, moduleSpecifier, /*mode*/ undefined); @@ -155,7 +176,13 @@ function doChange(changes: textChanges.ChangeTracker, program: Program, { export } } -function doChanges(changes: textChanges.ChangeTracker, program: Program, sourceFile: SourceFile, moduleExports: ExportName[], node: ExportDeclaration | undefined) { +function doChanges( + changes: textChanges.ChangeTracker, + program: Program, + sourceFile: SourceFile, + moduleExports: ExportName[], + node: ExportDeclaration | undefined, +) { if (length(moduleExports)) { if (node) { updateExport(changes, program, sourceFile, node, moduleExports); @@ -167,13 +194,22 @@ function doChanges(changes: textChanges.ChangeTracker, program: Program, sourceF } function tryGetExportDeclaration(sourceFile: SourceFile, isTypeOnly: boolean) { - const predicate = (node: Node): node is ExportDeclaration => isExportDeclaration(node) && (isTypeOnly && node.isTypeOnly || !node.isTypeOnly); + const predicate = (node: Node): node is ExportDeclaration => + isExportDeclaration(node) && (isTypeOnly && node.isTypeOnly || !node.isTypeOnly); return findLast(sourceFile.statements, predicate); } -function updateExport(changes: textChanges.ChangeTracker, program: Program, sourceFile: SourceFile, node: ExportDeclaration, names: ExportName[]) { - const namedExports = node.exportClause && isNamedExports(node.exportClause) ? node.exportClause.elements : factory.createNodeArray([]); - const allowTypeModifier = !node.isTypeOnly && !!(getIsolatedModules(program.getCompilerOptions()) || find(namedExports, e => e.isTypeOnly)); +function updateExport( + changes: textChanges.ChangeTracker, + program: Program, + sourceFile: SourceFile, + node: ExportDeclaration, + names: ExportName[], +) { + const namedExports = node.exportClause && isNamedExports(node.exportClause) ? node.exportClause.elements + : factory.createNodeArray([]); + const allowTypeModifier = !node.isTypeOnly + && !!(getIsolatedModules(program.getCompilerOptions()) || find(namedExports, e => e.isTypeOnly)); changes.replaceNode( sourceFile, node, @@ -182,7 +218,10 @@ function updateExport(changes: textChanges.ChangeTracker, program: Program, sour node.modifiers, node.isTypeOnly, factory.createNamedExports( - factory.createNodeArray([...namedExports, ...createExportSpecifiers(names, allowTypeModifier)], /*hasTrailingComma*/ namedExports.hasTrailingComma), + factory.createNodeArray( + [...namedExports, ...createExportSpecifiers(names, allowTypeModifier)], + /*hasTrailingComma*/ namedExports.hasTrailingComma, + ), ), node.moduleSpecifier, node.assertClause, @@ -190,12 +229,34 @@ function updateExport(changes: textChanges.ChangeTracker, program: Program, sour ); } -function createExport(changes: textChanges.ChangeTracker, program: Program, sourceFile: SourceFile, names: ExportName[]) { - changes.insertNodeAtEndOfScope(sourceFile, sourceFile, factory.createExportDeclaration(/*modifiers*/ undefined, /*isTypeOnly*/ false, factory.createNamedExports(createExportSpecifiers(names, /*allowTypeModifier*/ getIsolatedModules(program.getCompilerOptions()))), /*moduleSpecifier*/ undefined, /*assertClause*/ undefined)); +function createExport( + changes: textChanges.ChangeTracker, + program: Program, + sourceFile: SourceFile, + names: ExportName[], +) { + changes.insertNodeAtEndOfScope( + sourceFile, + sourceFile, + factory.createExportDeclaration( + /*modifiers*/ undefined, + /*isTypeOnly*/ false, + factory.createNamedExports( + createExportSpecifiers(names, /*allowTypeModifier*/ getIsolatedModules(program.getCompilerOptions())), + ), + /*moduleSpecifier*/ undefined, + /*assertClause*/ undefined, + ), + ); } function createExportSpecifiers(names: ExportName[], allowTypeModifier: boolean) { - return factory.createNodeArray(map(names, n => factory.createExportSpecifier(allowTypeModifier && n.isTypeOnly, /*propertyName*/ undefined, n.node))); + return factory.createNodeArray( + map( + names, + n => factory.createExportSpecifier(allowTypeModifier && n.isTypeOnly, /*propertyName*/ undefined, n.node), + ), + ); } function getNodeOfSymbol(symbol: Symbol) { @@ -203,6 +264,8 @@ function getNodeOfSymbol(symbol: Symbol) { return firstOrUndefined(symbol.declarations); } const declaration = symbol.valueDeclaration; - const variableStatement = isVariableDeclaration(declaration) ? tryCast(declaration.parent.parent, isVariableStatement) : undefined; - return variableStatement && length(variableStatement.declarationList.declarations) === 1 ? variableStatement : declaration; + const variableStatement = isVariableDeclaration(declaration) + ? tryCast(declaration.parent.parent, isVariableStatement) : undefined; + return variableStatement && length(variableStatement.declarationList.declarations) === 1 ? variableStatement + : declaration; } diff --git a/src/services/codefixes/fixIncorrectNamedTupleSyntax.ts b/src/services/codefixes/fixIncorrectNamedTupleSyntax.ts index 4c831bac51529..756764758d724 100644 --- a/src/services/codefixes/fixIncorrectNamedTupleSyntax.ts +++ b/src/services/codefixes/fixIncorrectNamedTupleSyntax.ts @@ -18,7 +18,9 @@ import { const fixId = "fixIncorrectNamedTupleSyntax"; const errorCodes = [ - Diagnostics.A_labeled_tuple_element_is_declared_as_optional_with_a_question_mark_after_the_name_and_before_the_colon_rather_than_after_the_type.code, + Diagnostics + .A_labeled_tuple_element_is_declared_as_optional_with_a_question_mark_after_the_name_and_before_the_colon_rather_than_after_the_type + .code, Diagnostics.A_labeled_tuple_element_is_declared_as_rest_with_a_before_the_name_rather_than_before_the_type.code, ]; @@ -28,7 +30,15 @@ registerCodeFix({ const { sourceFile, span } = context; const namedTupleMember = getNamedTupleMember(sourceFile, span.start); const changes = textChanges.ChangeTracker.with(context, t => doChange(t, sourceFile, namedTupleMember)); - return [createCodeFixAction(fixId, changes, Diagnostics.Move_labeled_tuple_element_modifiers_to_labels, fixId, Diagnostics.Move_labeled_tuple_element_modifiers_to_labels)]; + return [ + createCodeFixAction( + fixId, + changes, + Diagnostics.Move_labeled_tuple_element_modifiers_to_labels, + fixId, + Diagnostics.Move_labeled_tuple_element_modifiers_to_labels, + ), + ]; }, fixIds: [fixId], }); @@ -44,7 +54,10 @@ function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, na let unwrappedType = namedTupleMember.type; let sawOptional = false; let sawRest = false; - while (unwrappedType.kind === SyntaxKind.OptionalType || unwrappedType.kind === SyntaxKind.RestType || unwrappedType.kind === SyntaxKind.ParenthesizedType) { + while ( + unwrappedType.kind === SyntaxKind.OptionalType || unwrappedType.kind === SyntaxKind.RestType + || unwrappedType.kind === SyntaxKind.ParenthesizedType + ) { if (unwrappedType.kind === SyntaxKind.OptionalType) { sawOptional = true; } diff --git a/src/services/codefixes/fixInvalidImportSyntax.ts b/src/services/codefixes/fixInvalidImportSyntax.ts index 6301bf0ba6e16..b594cf19ac48d 100644 --- a/src/services/codefixes/fixInvalidImportSyntax.ts +++ b/src/services/codefixes/fixInvalidImportSyntax.ts @@ -39,7 +39,19 @@ function getCodeFixesForImportDeclaration(context: CodeFixContext, node: ImportD const variations: CodeFixAction[] = []; // import Bluebird from "bluebird"; - variations.push(createAction(context, sourceFile, node, makeImport(namespace.name, /*namedImports*/ undefined, node.moduleSpecifier, getQuotePreference(sourceFile, context.preferences)))); + variations.push( + createAction( + context, + sourceFile, + node, + makeImport( + namespace.name, + /*namedImports*/ undefined, + node.moduleSpecifier, + getQuotePreference(sourceFile, context.preferences), + ), + ), + ); if (getEmitModuleKind(opts) === ModuleKind.CommonJS) { // import Bluebird = require("bluebird"); @@ -61,7 +73,10 @@ function getCodeFixesForImportDeclaration(context: CodeFixContext, node: ImportD function createAction(context: CodeFixContext, sourceFile: SourceFile, node: Node, replacement: Node): CodeFixAction { const changes = textChanges.ChangeTracker.with(context, t => t.replaceNode(sourceFile, node, replacement)); - return createCodeFixActionWithoutFixAll(fixName, changes, [Diagnostics.Replace_import_with_0, changes[0].textChanges[0].newText]); + return createCodeFixActionWithoutFixAll(fixName, changes, [ + Diagnostics.Replace_import_with_0, + changes[0].textChanges[0].newText, + ]); } registerCodeFix({ @@ -74,8 +89,11 @@ registerCodeFix({ function getActionsForUsageOfInvalidImport(context: CodeFixContext): CodeFixAction[] | undefined { const sourceFile = context.sourceFile; - const targetKind = Diagnostics.This_expression_is_not_callable.code === context.errorCode ? SyntaxKind.CallExpression : SyntaxKind.NewExpression; - const node = findAncestor(getTokenAtPosition(sourceFile, context.span.start), a => a.kind === targetKind) as CallExpression | NewExpression; + const targetKind = Diagnostics.This_expression_is_not_callable.code === context.errorCode + ? SyntaxKind.CallExpression : SyntaxKind.NewExpression; + const node = findAncestor(getTokenAtPosition(sourceFile, context.span.start), a => a.kind === targetKind) as + | CallExpression + | NewExpression; if (!node) { return []; } @@ -89,7 +107,8 @@ registerCodeFix({ Diagnostics.Argument_of_type_0_is_not_assignable_to_parameter_of_type_1.code, Diagnostics.Type_0_does_not_satisfy_the_constraint_1.code, Diagnostics.Type_0_is_not_assignable_to_type_1.code, - Diagnostics.Type_0_is_not_assignable_to_type_1_Two_different_types_with_this_name_exist_but_they_are_unrelated.code, + Diagnostics.Type_0_is_not_assignable_to_type_1_Two_different_types_with_this_name_exist_but_they_are_unrelated + .code, Diagnostics.Type_predicate_0_is_not_assignable_to_1.code, Diagnostics.Property_0_of_type_1_is_not_assignable_to_2_index_type_3.code, Diagnostics._0_index_type_1_is_not_assignable_to_2_index_type_3.code, @@ -103,7 +122,10 @@ registerCodeFix({ function getActionsForInvalidImportLocation(context: CodeFixContext): CodeFixAction[] | undefined { const sourceFile = context.sourceFile; - const node = findAncestor(getTokenAtPosition(sourceFile, context.span.start), a => a.getStart() === context.span.start && a.getEnd() === (context.span.start + context.span.length)); + const node = findAncestor( + getTokenAtPosition(sourceFile, context.span.start), + a => a.getStart() === context.span.start && a.getEnd() === (context.span.start + context.span.length), + ); if (!node) { return []; } @@ -122,7 +144,10 @@ function getImportCodeFixesForExpression(context: CodeFixContext, expr: Node): C } if (isExpression(expr) && !(isNamedDeclaration(expr.parent) && expr.parent.name === expr)) { const sourceFile = context.sourceFile; - const changes = textChanges.ChangeTracker.with(context, t => t.replaceNode(sourceFile, expr, factory.createPropertyAccessExpression(expr, "default"), {})); + const changes = textChanges.ChangeTracker.with( + context, + t => t.replaceNode(sourceFile, expr, factory.createPropertyAccessExpression(expr, "default"), {}), + ); fixes.push(createCodeFixActionWithoutFixAll(fixName, changes, Diagnostics.Use_synthetic_default_member)); } return fixes; diff --git a/src/services/codefixes/fixInvalidJsxCharacters.ts b/src/services/codefixes/fixInvalidJsxCharacters.ts index 744354c7fb87b..23e069ddb571a 100644 --- a/src/services/codefixes/fixInvalidJsxCharacters.ts +++ b/src/services/codefixes/fixInvalidJsxCharacters.ts @@ -25,16 +25,45 @@ registerCodeFix({ fixIds: [fixIdExpression, fixIdHtmlEntity], getCodeActions(context) { const { sourceFile, preferences, span } = context; - const changeToExpression = textChanges.ChangeTracker.with(context, t => doChange(t, preferences, sourceFile, span.start, /*useHtmlEntity*/ false)); - const changeToHtmlEntity = textChanges.ChangeTracker.with(context, t => doChange(t, preferences, sourceFile, span.start, /*useHtmlEntity*/ true)); + const changeToExpression = textChanges.ChangeTracker.with( + context, + t => doChange(t, preferences, sourceFile, span.start, /*useHtmlEntity*/ false), + ); + const changeToHtmlEntity = textChanges.ChangeTracker.with( + context, + t => doChange(t, preferences, sourceFile, span.start, /*useHtmlEntity*/ true), + ); return [ - createCodeFixAction(fixIdExpression, changeToExpression, Diagnostics.Wrap_invalid_character_in_an_expression_container, fixIdExpression, Diagnostics.Wrap_all_invalid_characters_in_an_expression_container), - createCodeFixAction(fixIdHtmlEntity, changeToHtmlEntity, Diagnostics.Convert_invalid_character_to_its_html_entity_code, fixIdHtmlEntity, Diagnostics.Convert_all_invalid_characters_to_HTML_entity_code), + createCodeFixAction( + fixIdExpression, + changeToExpression, + Diagnostics.Wrap_invalid_character_in_an_expression_container, + fixIdExpression, + Diagnostics.Wrap_all_invalid_characters_in_an_expression_container, + ), + createCodeFixAction( + fixIdHtmlEntity, + changeToHtmlEntity, + Diagnostics.Convert_invalid_character_to_its_html_entity_code, + fixIdHtmlEntity, + Diagnostics.Convert_all_invalid_characters_to_HTML_entity_code, + ), ]; }, getAllCodeActions(context) { - return codeFixAll(context, errorCodes, (changes, diagnostic) => doChange(changes, context.preferences, diagnostic.file, diagnostic.start, context.fixId === fixIdHtmlEntity)); + return codeFixAll( + context, + errorCodes, + (changes, diagnostic) => + doChange( + changes, + context.preferences, + diagnostic.file, + diagnostic.start, + context.fixId === fixIdHtmlEntity, + ), + ); }, }); @@ -47,7 +76,13 @@ function isValidCharacter(character: string): character is keyof typeof htmlEnti return hasProperty(htmlEntity, character); } -function doChange(changes: textChanges.ChangeTracker, preferences: UserPreferences, sourceFile: SourceFile, start: number, useHtmlEntity: boolean) { +function doChange( + changes: textChanges.ChangeTracker, + preferences: UserPreferences, + sourceFile: SourceFile, + start: number, + useHtmlEntity: boolean, +) { const character = sourceFile.getText()[start]; // sanity check if (!isValidCharacter(character)) { diff --git a/src/services/codefixes/fixJSDocTypes.ts b/src/services/codefixes/fixJSDocTypes.ts index 2a35ba3fdb3a9..bcce48826074a 100644 --- a/src/services/codefixes/fixJSDocTypes.ts +++ b/src/services/codefixes/fixJSDocTypes.ts @@ -58,13 +58,28 @@ registerCodeFix({ if (typeNode.kind === SyntaxKind.JSDocNullableType) { // for nullable types, suggest the flow-compatible `T | null | undefined` // in addition to the jsdoc/closure-compatible `T | null` - actions.push(fix(type, fixIdNullable, Diagnostics.Change_all_jsdoc_style_types_to_TypeScript_and_add_undefined_to_nullable_types)); + actions.push( + fix( + type, + fixIdNullable, + Diagnostics.Change_all_jsdoc_style_types_to_TypeScript_and_add_undefined_to_nullable_types, + ), + ); } return actions; function fix(type: Type, fixId: string, fixAllDescription: DiagnosticMessage): CodeFixAction { - const changes = textChanges.ChangeTracker.with(context, t => doChange(t, sourceFile, typeNode, type, checker)); - return createCodeFixAction("jdocTypes", changes, [Diagnostics.Change_0_to_1, original, checker.typeToString(type)], fixId, fixAllDescription); + const changes = textChanges.ChangeTracker.with( + context, + t => doChange(t, sourceFile, typeNode, type, checker), + ); + return createCodeFixAction( + "jdocTypes", + changes, + [Diagnostics.Change_0_to_1, original, checker.typeToString(type)], + fixId, + fixAllDescription, + ); } }, fixIds: [fixIdPlain, fixIdNullable], @@ -75,24 +90,55 @@ registerCodeFix({ const info = getInfo(err.file, err.start, checker); if (!info) return; const { typeNode, type } = info; - const fixedType = typeNode.kind === SyntaxKind.JSDocNullableType && fixId === fixIdNullable ? checker.getNullableType(type, TypeFlags.Undefined) : type; + const fixedType = typeNode.kind === SyntaxKind.JSDocNullableType && fixId === fixIdNullable + ? checker.getNullableType(type, TypeFlags.Undefined) : type; doChange(changes, sourceFile, typeNode, fixedType, checker); }); }, }); -function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, oldTypeNode: TypeNode, newType: Type, checker: TypeChecker): void { - changes.replaceNode(sourceFile, oldTypeNode, checker.typeToTypeNode(newType, /*enclosingDeclaration*/ oldTypeNode, /*flags*/ undefined)!); // TODO: GH#18217 +function doChange( + changes: textChanges.ChangeTracker, + sourceFile: SourceFile, + oldTypeNode: TypeNode, + newType: Type, + checker: TypeChecker, +): void { + changes.replaceNode( + sourceFile, + oldTypeNode, + checker.typeToTypeNode(newType, /*enclosingDeclaration*/ oldTypeNode, /*flags*/ undefined)!, + ); // TODO: GH#18217 } -function getInfo(sourceFile: SourceFile, pos: number, checker: TypeChecker): { readonly typeNode: TypeNode; readonly type: Type; } | undefined { +function getInfo( + sourceFile: SourceFile, + pos: number, + checker: TypeChecker, +): { readonly typeNode: TypeNode; readonly type: Type; } | undefined { const decl = findAncestor(getTokenAtPosition(sourceFile, pos), isTypeContainer); const typeNode = decl && decl.type; return typeNode && { typeNode, type: getType(checker, typeNode) }; } // TODO: GH#19856 Node & { type: TypeNode } -type TypeContainer = AsExpression | CallSignatureDeclaration | ConstructSignatureDeclaration | FunctionDeclaration | GetAccessorDeclaration | IndexSignatureDeclaration | MappedTypeNode | MethodDeclaration | MethodSignature | ParameterDeclaration | PropertyDeclaration | PropertySignature | SetAccessorDeclaration | TypeAliasDeclaration | TypeAssertion | VariableDeclaration; +type TypeContainer = + | AsExpression + | CallSignatureDeclaration + | ConstructSignatureDeclaration + | FunctionDeclaration + | GetAccessorDeclaration + | IndexSignatureDeclaration + | MappedTypeNode + | MethodDeclaration + | MethodSignature + | ParameterDeclaration + | PropertyDeclaration + | PropertySignature + | SetAccessorDeclaration + | TypeAliasDeclaration + | TypeAssertion + | VariableDeclaration; function isTypeContainer(node: Node): node is TypeContainer { // NOTE: Some locations are not handled yet: // MappedTypeNode.typeParameters and SignatureDeclaration.typeParameters, as well as CallExpression.typeArguments diff --git a/src/services/codefixes/fixMissingCallParentheses.ts b/src/services/codefixes/fixMissingCallParentheses.ts index 5a254bc1392dc..3cb9a2f0246fb 100644 --- a/src/services/codefixes/fixMissingCallParentheses.ts +++ b/src/services/codefixes/fixMissingCallParentheses.ts @@ -17,7 +17,9 @@ import { const fixId = "fixMissingCallParentheses"; const errorCodes = [ - Diagnostics.This_condition_will_always_return_true_since_this_function_is_always_defined_Did_you_mean_to_call_it_instead.code, + Diagnostics + .This_condition_will_always_return_true_since_this_function_is_always_defined_Did_you_mean_to_call_it_instead + .code, ]; registerCodeFix({ @@ -29,7 +31,15 @@ registerCodeFix({ if (!callName) return; const changes = textChanges.ChangeTracker.with(context, t => doChange(t, context.sourceFile, callName)); - return [createCodeFixAction(fixId, changes, Diagnostics.Add_missing_call_parentheses, fixId, Diagnostics.Add_all_missing_call_parentheses)]; + return [ + createCodeFixAction( + fixId, + changes, + Diagnostics.Add_missing_call_parentheses, + fixId, + Diagnostics.Add_all_missing_call_parentheses, + ), + ]; }, getAllCodeActions: context => codeFixAll(context, errorCodes, (changes, diag) => { @@ -38,7 +48,11 @@ registerCodeFix({ }), }); -function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, name: Identifier | PrivateIdentifier): void { +function doChange( + changes: textChanges.ChangeTracker, + sourceFile: SourceFile, + name: Identifier | PrivateIdentifier, +): void { changes.replaceNodeWithText(sourceFile, name, `${name.text}()`); } diff --git a/src/services/codefixes/fixModuleAndTargetOptions.ts b/src/services/codefixes/fixModuleAndTargetOptions.ts index 7446e4babe1d2..a6028ae07ae9d 100644 --- a/src/services/codefixes/fixModuleAndTargetOptions.ts +++ b/src/services/codefixes/fixModuleAndTargetOptions.ts @@ -19,9 +19,15 @@ import { registerCodeFix({ errorCodes: [ - Diagnostics.Top_level_await_expressions_are_only_allowed_when_the_module_option_is_set_to_es2022_esnext_system_node16_or_nodenext_and_the_target_option_is_set_to_es2017_or_higher.code, - Diagnostics.Top_level_await_using_statements_are_only_allowed_when_the_module_option_is_set_to_es2022_esnext_system_node16_or_nodenext_and_the_target_option_is_set_to_es2017_or_higher.code, - Diagnostics.Top_level_for_await_loops_are_only_allowed_when_the_module_option_is_set_to_es2022_esnext_system_node16_or_nodenext_and_the_target_option_is_set_to_es2017_or_higher.code, + Diagnostics + .Top_level_await_expressions_are_only_allowed_when_the_module_option_is_set_to_es2022_esnext_system_node16_or_nodenext_and_the_target_option_is_set_to_es2017_or_higher + .code, + Diagnostics + .Top_level_await_using_statements_are_only_allowed_when_the_module_option_is_set_to_es2022_esnext_system_node16_or_nodenext_and_the_target_option_is_set_to_es2017_or_higher + .code, + Diagnostics + .Top_level_for_await_loops_are_only_allowed_when_the_module_option_is_set_to_es2022_esnext_system_node16_or_nodenext_and_the_target_option_is_set_to_es2017_or_higher + .code, ], getCodeActions: function getCodeActionsToFixModuleAndTarget(context) { const compilerOptions = context.program.getCompilerOptions(); @@ -37,7 +43,12 @@ registerCodeFix({ const changes = textChanges.ChangeTracker.with(context, changes => { setJsonCompilerOptionValue(changes, configFile, "module", factory.createStringLiteral("esnext")); }); - codeFixes.push(createCodeFixActionWithoutFixAll("fixModuleOption", changes, [Diagnostics.Set_the_module_option_in_your_configuration_file_to_0, "esnext"])); + codeFixes.push( + createCodeFixActionWithoutFixAll("fixModuleOption", changes, [ + Diagnostics.Set_the_module_option_in_your_configuration_file_to_0, + "esnext", + ]), + ); } const target = getEmitScriptTarget(compilerOptions); @@ -56,7 +67,12 @@ registerCodeFix({ setJsonCompilerOptionValues(tracker, configFile, options); }); - codeFixes.push(createCodeFixActionWithoutFixAll("fixTargetOption", changes, [Diagnostics.Set_the_target_option_in_your_configuration_file_to_0, "es2017"])); + codeFixes.push( + createCodeFixActionWithoutFixAll("fixTargetOption", changes, [ + Diagnostics.Set_the_target_option_in_your_configuration_file_to_0, + "es2017", + ]), + ); } return codeFixes.length ? codeFixes : undefined; diff --git a/src/services/codefixes/fixNaNEquality.ts b/src/services/codefixes/fixNaNEquality.ts index 53db6b1b8b8d6..5ace1965a2ebc 100644 --- a/src/services/codefixes/fixNaNEquality.ts +++ b/src/services/codefixes/fixNaNEquality.ts @@ -36,7 +36,15 @@ registerCodeFix({ const { suggestion, expression, arg } = info; const changes = textChanges.ChangeTracker.with(context, t => doChange(t, sourceFile, arg, expression)); - return [createCodeFixAction(fixId, changes, [Diagnostics.Use_0, suggestion], fixId, Diagnostics.Use_Number_isNaN_in_all_conditions)]; + return [ + createCodeFixAction( + fixId, + changes, + [Diagnostics.Use_0, suggestion], + fixId, + Diagnostics.Use_Number_isNaN_in_all_conditions, + ), + ]; }, fixIds: [fixId], getAllCodeActions: context => { @@ -56,11 +64,17 @@ interface Info { } function getInfo(program: Program, sourceFile: SourceFile, span: TextSpan): Info | undefined { - const diag = find(program.getSemanticDiagnostics(sourceFile), diag => diag.start === span.start && diag.length === span.length); + const diag = find( + program.getSemanticDiagnostics(sourceFile), + diag => diag.start === span.start && diag.length === span.length, + ); if (diag === undefined || diag.relatedInformation === undefined) return; const related = find(diag.relatedInformation, related => related.code === Diagnostics.Did_you_mean_0.code); - if (related === undefined || related.file === undefined || related.start === undefined || related.length === undefined) return; + if ( + related === undefined || related.file === undefined || related.start === undefined + || related.length === undefined + ) return; const token = findAncestorMatchingSpan(related.file, createTextSpan(related.start, related.length)); if (token === undefined) return; @@ -71,7 +85,12 @@ function getInfo(program: Program, sourceFile: SourceFile, span: TextSpan): Info return undefined; } -function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, arg: Expression, expression: BinaryExpression) { +function doChange( + changes: textChanges.ChangeTracker, + sourceFile: SourceFile, + arg: Expression, + expression: BinaryExpression, +) { const callExpression = factory.createCallExpression( factory.createPropertyAccessExpression(factory.createIdentifier("Number"), factory.createIdentifier("isNaN")), /*typeArguments*/ undefined, diff --git a/src/services/codefixes/fixNoPropertyAccessFromIndexSignature.ts b/src/services/codefixes/fixNoPropertyAccessFromIndexSignature.ts index 3ae9b9045e223..9abe666cd2d63 100644 --- a/src/services/codefixes/fixNoPropertyAccessFromIndexSignature.ts +++ b/src/services/codefixes/fixNoPropertyAccessFromIndexSignature.ts @@ -29,21 +29,43 @@ registerCodeFix({ getCodeActions(context) { const { sourceFile, span, preferences } = context; const property = getPropertyAccessExpression(sourceFile, span.start); - const changes = textChanges.ChangeTracker.with(context, t => doChange(t, context.sourceFile, property, preferences)); - return [createCodeFixAction(fixId, changes, [Diagnostics.Use_element_access_for_0, property.name.text], fixId, Diagnostics.Use_element_access_for_all_undeclared_properties)]; + const changes = textChanges.ChangeTracker.with( + context, + t => doChange(t, context.sourceFile, property, preferences), + ); + return [ + createCodeFixAction( + fixId, + changes, + [Diagnostics.Use_element_access_for_0, property.name.text], + fixId, + Diagnostics.Use_element_access_for_all_undeclared_properties, + ), + ]; }, - getAllCodeActions: context => codeFixAll(context, errorCodes, (changes, diag) => doChange(changes, diag.file, getPropertyAccessExpression(diag.file, diag.start), context.preferences)), + getAllCodeActions: context => + codeFixAll( + context, + errorCodes, + (changes, diag) => + doChange(changes, diag.file, getPropertyAccessExpression(diag.file, diag.start), context.preferences), + ), }); -function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, node: PropertyAccessExpression, preferences: UserPreferences): void { +function doChange( + changes: textChanges.ChangeTracker, + sourceFile: SourceFile, + node: PropertyAccessExpression, + preferences: UserPreferences, +): void { const quotePreference = getQuotePreference(sourceFile, preferences); const argumentsExpression = factory.createStringLiteral(node.name.text, quotePreference === QuotePreference.Single); changes.replaceNode( sourceFile, node, - isPropertyAccessChain(node) ? - factory.createElementAccessChain(node.expression, node.questionDotToken, argumentsExpression) : - factory.createElementAccessExpression(node.expression, argumentsExpression), + isPropertyAccessChain(node) + ? factory.createElementAccessChain(node.expression, node.questionDotToken, argumentsExpression) + : factory.createElementAccessExpression(node.expression, argumentsExpression), ); } diff --git a/src/services/codefixes/fixOverrideModifier.ts b/src/services/codefixes/fixOverrideModifier.ts index 2c3f8242a7ff5..879f50ab1f4fb 100644 --- a/src/services/codefixes/fixOverrideModifier.ts +++ b/src/services/codefixes/fixOverrideModifier.ts @@ -52,14 +52,26 @@ type ClassElementLikeHasJSDoc = const errorCodes = [ Diagnostics.This_member_cannot_have_an_override_modifier_because_it_is_not_declared_in_the_base_class_0.code, - Diagnostics.This_member_cannot_have_an_override_modifier_because_its_containing_class_0_does_not_extend_another_class.code, - Diagnostics.This_member_must_have_an_override_modifier_because_it_overrides_an_abstract_method_that_is_declared_in_the_base_class_0.code, + Diagnostics + .This_member_cannot_have_an_override_modifier_because_its_containing_class_0_does_not_extend_another_class.code, + Diagnostics + .This_member_must_have_an_override_modifier_because_it_overrides_an_abstract_method_that_is_declared_in_the_base_class_0 + .code, Diagnostics.This_member_must_have_an_override_modifier_because_it_overrides_a_member_in_the_base_class_0.code, - Diagnostics.This_parameter_property_must_have_an_override_modifier_because_it_overrides_a_member_in_base_class_0.code, - Diagnostics.This_member_must_have_a_JSDoc_comment_with_an_override_tag_because_it_overrides_a_member_in_the_base_class_0.code, - Diagnostics.This_member_cannot_have_a_JSDoc_comment_with_an_override_tag_because_its_containing_class_0_does_not_extend_another_class.code, - Diagnostics.This_parameter_property_must_have_a_JSDoc_comment_with_an_override_tag_because_it_overrides_a_member_in_the_base_class_0.code, - Diagnostics.This_member_cannot_have_a_JSDoc_comment_with_an_override_tag_because_it_is_not_declared_in_the_base_class_0.code, + Diagnostics.This_parameter_property_must_have_an_override_modifier_because_it_overrides_a_member_in_base_class_0 + .code, + Diagnostics + .This_member_must_have_a_JSDoc_comment_with_an_override_tag_because_it_overrides_a_member_in_the_base_class_0 + .code, + Diagnostics + .This_member_cannot_have_a_JSDoc_comment_with_an_override_tag_because_its_containing_class_0_does_not_extend_another_class + .code, + Diagnostics + .This_parameter_property_must_have_a_JSDoc_comment_with_an_override_tag_because_it_overrides_a_member_in_the_base_class_0 + .code, + Diagnostics + .This_member_cannot_have_a_JSDoc_comment_with_an_override_tag_because_it_is_not_declared_in_the_base_class_0 + .code, ]; interface ErrorCodeFixInfo { @@ -75,35 +87,58 @@ const errorCodeFixIdMap: Record = { fixId: fixAddOverrideId, fixAllDescriptions: Diagnostics.Add_all_missing_override_modifiers, }, - [Diagnostics.This_member_must_have_a_JSDoc_comment_with_an_override_tag_because_it_overrides_a_member_in_the_base_class_0.code]: { + [ + Diagnostics + .This_member_must_have_a_JSDoc_comment_with_an_override_tag_because_it_overrides_a_member_in_the_base_class_0 + .code + ]: { descriptions: Diagnostics.Add_override_modifier, fixId: fixAddOverrideId, fixAllDescriptions: Diagnostics.Add_all_missing_override_modifiers, }, // case #2: - [Diagnostics.This_member_cannot_have_an_override_modifier_because_its_containing_class_0_does_not_extend_another_class.code]: { + [ + Diagnostics + .This_member_cannot_have_an_override_modifier_because_its_containing_class_0_does_not_extend_another_class + .code + ]: { descriptions: Diagnostics.Remove_override_modifier, fixId: fixRemoveOverrideId, fixAllDescriptions: Diagnostics.Remove_all_unnecessary_override_modifiers, }, - [Diagnostics.This_member_cannot_have_a_JSDoc_comment_with_an_override_tag_because_its_containing_class_0_does_not_extend_another_class.code]: { + [ + Diagnostics + .This_member_cannot_have_a_JSDoc_comment_with_an_override_tag_because_its_containing_class_0_does_not_extend_another_class + .code + ]: { descriptions: Diagnostics.Remove_override_modifier, fixId: fixRemoveOverrideId, fixAllDescriptions: Diagnostics.Remove_override_modifier, }, // case #3: - [Diagnostics.This_parameter_property_must_have_an_override_modifier_because_it_overrides_a_member_in_base_class_0.code]: { + [ + Diagnostics.This_parameter_property_must_have_an_override_modifier_because_it_overrides_a_member_in_base_class_0 + .code + ]: { descriptions: Diagnostics.Add_override_modifier, fixId: fixAddOverrideId, fixAllDescriptions: Diagnostics.Add_all_missing_override_modifiers, }, - [Diagnostics.This_parameter_property_must_have_a_JSDoc_comment_with_an_override_tag_because_it_overrides_a_member_in_the_base_class_0.code]: { + [ + Diagnostics + .This_parameter_property_must_have_a_JSDoc_comment_with_an_override_tag_because_it_overrides_a_member_in_the_base_class_0 + .code + ]: { descriptions: Diagnostics.Add_override_modifier, fixId: fixAddOverrideId, fixAllDescriptions: Diagnostics.Add_all_missing_override_modifiers, }, // case #4: - [Diagnostics.This_member_must_have_an_override_modifier_because_it_overrides_an_abstract_method_that_is_declared_in_the_base_class_0.code]: { + [ + Diagnostics + .This_member_must_have_an_override_modifier_because_it_overrides_an_abstract_method_that_is_declared_in_the_base_class_0 + .code + ]: { descriptions: Diagnostics.Add_override_modifier, fixId: fixAddOverrideId, fixAllDescriptions: Diagnostics.Remove_all_unnecessary_override_modifiers, @@ -114,7 +149,11 @@ const errorCodeFixIdMap: Record = { fixId: fixRemoveOverrideId, fixAllDescriptions: Diagnostics.Remove_all_unnecessary_override_modifiers, }, - [Diagnostics.This_member_cannot_have_a_JSDoc_comment_with_an_override_tag_because_it_is_not_declared_in_the_base_class_0.code]: { + [ + Diagnostics + .This_member_cannot_have_a_JSDoc_comment_with_an_override_tag_because_it_is_not_declared_in_the_base_class_0 + .code + ]: { descriptions: Diagnostics.Remove_override_modifier, fixId: fixRemoveOverrideId, fixAllDescriptions: Diagnostics.Remove_all_unnecessary_override_modifiers, @@ -130,7 +169,10 @@ registerCodeFix({ if (!info) return emptyArray; const { descriptions, fixId, fixAllDescriptions } = info; - const changes = textChanges.ChangeTracker.with(context, changes => dispatchChanges(changes, context, errorCode, span.start)); + const changes = textChanges.ChangeTracker.with( + context, + changes => dispatchChanges(changes, context, errorCode, span.start), + ); return [ createCodeFixActionMaybeFixAll(fixName, changes, descriptions, fixId, fixAllDescriptions), @@ -156,16 +198,31 @@ function dispatchChanges( pos: number, ) { switch (errorCode) { - case Diagnostics.This_member_must_have_an_override_modifier_because_it_overrides_a_member_in_the_base_class_0.code: - case Diagnostics.This_member_must_have_a_JSDoc_comment_with_an_override_tag_because_it_overrides_a_member_in_the_base_class_0.code: - case Diagnostics.This_member_must_have_an_override_modifier_because_it_overrides_an_abstract_method_that_is_declared_in_the_base_class_0.code: - case Diagnostics.This_parameter_property_must_have_an_override_modifier_because_it_overrides_a_member_in_base_class_0.code: - case Diagnostics.This_parameter_property_must_have_a_JSDoc_comment_with_an_override_tag_because_it_overrides_a_member_in_the_base_class_0.code: + case Diagnostics.This_member_must_have_an_override_modifier_because_it_overrides_a_member_in_the_base_class_0 + .code: + case Diagnostics + .This_member_must_have_a_JSDoc_comment_with_an_override_tag_because_it_overrides_a_member_in_the_base_class_0 + .code: + case Diagnostics + .This_member_must_have_an_override_modifier_because_it_overrides_an_abstract_method_that_is_declared_in_the_base_class_0 + .code: + case Diagnostics + .This_parameter_property_must_have_an_override_modifier_because_it_overrides_a_member_in_base_class_0.code: + case Diagnostics + .This_parameter_property_must_have_a_JSDoc_comment_with_an_override_tag_because_it_overrides_a_member_in_the_base_class_0 + .code: return doAddOverrideModifierChange(changeTracker, context.sourceFile, pos); - case Diagnostics.This_member_cannot_have_an_override_modifier_because_it_is_not_declared_in_the_base_class_0.code: - case Diagnostics.This_member_cannot_have_a_JSDoc_comment_with_an_override_tag_because_it_is_not_declared_in_the_base_class_0.code: - case Diagnostics.This_member_cannot_have_an_override_modifier_because_its_containing_class_0_does_not_extend_another_class.code: - case Diagnostics.This_member_cannot_have_a_JSDoc_comment_with_an_override_tag_because_its_containing_class_0_does_not_extend_another_class.code: + case Diagnostics.This_member_cannot_have_an_override_modifier_because_it_is_not_declared_in_the_base_class_0 + .code: + case Diagnostics + .This_member_cannot_have_a_JSDoc_comment_with_an_override_tag_because_it_is_not_declared_in_the_base_class_0 + .code: + case Diagnostics + .This_member_cannot_have_an_override_modifier_because_its_containing_class_0_does_not_extend_another_class + .code: + case Diagnostics + .This_member_cannot_have_a_JSDoc_comment_with_an_override_tag_because_its_containing_class_0_does_not_extend_another_class + .code: return doRemoveOverrideModifierChange(changeTracker, context.sourceFile, pos); default: Debug.fail("Unexpected error code: " + errorCode); @@ -175,7 +232,9 @@ function dispatchChanges( function doAddOverrideModifierChange(changeTracker: textChanges.ChangeTracker, sourceFile: SourceFile, pos: number) { const classElement = findContainerClassElementLike(sourceFile, pos); if (isSourceFileJS(sourceFile)) { - changeTracker.addJSDocTags(sourceFile, classElement, [factory.createJSDocOverrideTag(factory.createIdentifier("override"))]); + changeTracker.addJSDocTags(sourceFile, classElement, [ + factory.createJSDocOverrideTag(factory.createIdentifier("override")), + ]); return; } const modifiers = classElement.modifiers || emptyArray; @@ -183,10 +242,10 @@ function doAddOverrideModifierChange(changeTracker: textChanges.ChangeTracker, s const abstractModifier = find(modifiers, isAbstractModifier); const accessibilityModifier = find(modifiers, m => isAccessibilityModifier(m.kind)); const lastDecorator = findLast(modifiers, isDecorator); - const modifierPos = abstractModifier ? abstractModifier.end : - staticModifier ? staticModifier.end : - accessibilityModifier ? accessibilityModifier.end : - lastDecorator ? skipTrivia(sourceFile.text, lastDecorator.end) : classElement.getStart(sourceFile); + const modifierPos = abstractModifier ? abstractModifier.end + : staticModifier ? staticModifier.end + : accessibilityModifier ? accessibilityModifier.end + : lastDecorator ? skipTrivia(sourceFile.text, lastDecorator.end) : classElement.getStart(sourceFile); const options = accessibilityModifier || staticModifier || abstractModifier ? { prefix: " " } : { suffix: " " }; changeTracker.insertModifierAt(sourceFile, modifierPos, SyntaxKind.OverrideKeyword, options); } diff --git a/src/services/codefixes/fixPropertyAssignment.ts b/src/services/codefixes/fixPropertyAssignment.ts index d75fb8b365ac3..2a328759f7a8f 100644 --- a/src/services/codefixes/fixPropertyAssignment.ts +++ b/src/services/codefixes/fixPropertyAssignment.ts @@ -17,7 +17,9 @@ import { const fixId = "fixPropertyAssignment"; const errorCodes = [ - Diagnostics.Did_you_mean_to_use_a_Colon_An_can_only_follow_a_property_name_when_the_containing_object_literal_is_part_of_a_destructuring_pattern.code, + Diagnostics + .Did_you_mean_to_use_a_Colon_An_can_only_follow_a_property_name_when_the_containing_object_literal_is_part_of_a_destructuring_pattern + .code, ]; registerCodeFix({ @@ -27,13 +29,28 @@ registerCodeFix({ const { sourceFile, span } = context; const property = getProperty(sourceFile, span.start); const changes = textChanges.ChangeTracker.with(context, t => doChange(t, context.sourceFile, property)); - return [createCodeFixAction(fixId, changes, [Diagnostics.Change_0_to_1, "=", ":"], fixId, [Diagnostics.Switch_each_misused_0_to_1, "=", ":"])]; + return [ + createCodeFixAction(fixId, changes, [Diagnostics.Change_0_to_1, "=", ":"], fixId, [ + Diagnostics.Switch_each_misused_0_to_1, + "=", + ":", + ]), + ]; }, - getAllCodeActions: context => codeFixAll(context, errorCodes, (changes, diag) => doChange(changes, diag.file, getProperty(diag.file, diag.start))), + getAllCodeActions: context => + codeFixAll( + context, + errorCodes, + (changes, diag) => doChange(changes, diag.file, getProperty(diag.file, diag.start)), + ), }); function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, node: ShorthandPropertyAssignment): void { - changes.replaceNode(sourceFile, node, factory.createPropertyAssignment(node.name, node.objectAssignmentInitializer as Expression)); + changes.replaceNode( + sourceFile, + node, + factory.createPropertyAssignment(node.name, node.objectAssignmentInitializer as Expression), + ); } function getProperty(sourceFile: SourceFile, pos: number): ShorthandPropertyAssignment { diff --git a/src/services/codefixes/fixPropertyOverrideAccessor.ts b/src/services/codefixes/fixPropertyOverrideAccessor.ts index 4ee42dbbeee1e..632aaf842ca41 100644 --- a/src/services/codefixes/fixPropertyOverrideAccessor.ts +++ b/src/services/codefixes/fixPropertyOverrideAccessor.ts @@ -30,7 +30,15 @@ registerCodeFix({ getCodeActions(context) { const edits = doChange(context.sourceFile, context.span.start, context.span.length, context.errorCode, context); if (edits) { - return [createCodeFixAction(fixId, edits, Diagnostics.Generate_get_and_set_accessors, fixId, Diagnostics.Generate_get_and_set_accessors_for_all_overriding_properties)]; + return [ + createCodeFixAction( + fixId, + edits, + Diagnostics.Generate_get_and_set_accessors, + fixId, + Diagnostics.Generate_get_and_set_accessors_for_all_overriding_properties, + ), + ]; } }, fixIds: [fixId], @@ -46,14 +54,26 @@ registerCodeFix({ }), }); -function doChange(file: SourceFile, start: number, length: number, code: number, context: CodeFixContext | CodeFixAllContext) { +function doChange( + file: SourceFile, + start: number, + length: number, + code: number, + context: CodeFixContext | CodeFixAllContext, +) { let startPosition: number; let endPosition: number; - if (code === Diagnostics._0_is_defined_as_an_accessor_in_class_1_but_is_overridden_here_in_2_as_an_instance_property.code) { + if ( + code + === Diagnostics._0_is_defined_as_an_accessor_in_class_1_but_is_overridden_here_in_2_as_an_instance_property + .code + ) { startPosition = start; endPosition = start + length; } - else if (code === Diagnostics._0_is_defined_as_a_property_in_class_1_but_is_overridden_here_in_2_as_an_accessor.code) { + else if ( + code === Diagnostics._0_is_defined_as_a_property_in_class_1_but_is_overridden_here_in_2_as_an_accessor.code + ) { const checker = context.program.getTypeChecker(); const node = getTokenAtPosition(file, start).parent; Debug.assert(isAccessor(node), "error span of fixPropertyOverrideAccessor should only be on an accessor"); @@ -73,5 +93,12 @@ function doChange(file: SourceFile, start: number, length: number, code: number, else { Debug.fail("fixPropertyOverrideAccessor codefix got unexpected error code " + code); } - return generateAccessorFromProperty(file, context.program, startPosition, endPosition, context, Diagnostics.Generate_get_and_set_accessors.message); + return generateAccessorFromProperty( + file, + context.program, + startPosition, + endPosition, + context, + Diagnostics.Generate_get_and_set_accessors.message, + ); } diff --git a/src/services/codefixes/fixReturnTypeInAsyncFunction.ts b/src/services/codefixes/fixReturnTypeInAsyncFunction.ts index 8b33ec0c8cede..0464810e56634 100644 --- a/src/services/codefixes/fixReturnTypeInAsyncFunction.ts +++ b/src/services/codefixes/fixReturnTypeInAsyncFunction.ts @@ -19,7 +19,9 @@ import { const fixId = "fixReturnTypeInAsyncFunction"; const errorCodes = [ - Diagnostics.The_return_type_of_an_async_function_or_method_must_be_the_global_Promise_T_type_Did_you_mean_to_write_Promise_0.code, + Diagnostics + .The_return_type_of_an_async_function_or_method_must_be_the_global_Promise_T_type_Did_you_mean_to_write_Promise_0 + .code, ]; interface Info { @@ -40,11 +42,18 @@ registerCodeFix({ return undefined; } const { returnTypeNode, returnType, promisedTypeNode, promisedType } = info; - const changes = textChanges.ChangeTracker.with(context, t => doChange(t, sourceFile, returnTypeNode, promisedTypeNode)); + const changes = textChanges.ChangeTracker.with( + context, + t => doChange(t, sourceFile, returnTypeNode, promisedTypeNode), + ); return [createCodeFixAction( fixId, changes, - [Diagnostics.Replace_0_with_Promise_1, checker.typeToString(returnType), checker.typeToString(promisedType)], + [ + Diagnostics.Replace_0_with_Promise_1, + checker.typeToString(returnType), + checker.typeToString(promisedType), + ], fixId, Diagnostics.Fix_all_incorrect_return_type_of_an_async_functions, )]; @@ -72,12 +81,21 @@ function getInfo(sourceFile: SourceFile, checker: TypeChecker, pos: number): Inf const returnType = checker.getTypeFromTypeNode(returnTypeNode); const promisedType = checker.getAwaitedType(returnType) || checker.getVoidType(); - const promisedTypeNode = checker.typeToTypeNode(promisedType, /*enclosingDeclaration*/ returnTypeNode, /*flags*/ undefined); + const promisedTypeNode = checker.typeToTypeNode( + promisedType, + /*enclosingDeclaration*/ returnTypeNode, + /*flags*/ undefined, + ); if (promisedTypeNode) { return { returnTypeNode, returnType, promisedTypeNode, promisedType }; } } -function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, returnTypeNode: TypeNode, promisedTypeNode: TypeNode): void { +function doChange( + changes: textChanges.ChangeTracker, + sourceFile: SourceFile, + returnTypeNode: TypeNode, + promisedTypeNode: TypeNode, +): void { changes.replaceNode(sourceFile, returnTypeNode, factory.createTypeReferenceNode("Promise", [promisedTypeNode])); } diff --git a/src/services/codefixes/fixSpelling.ts b/src/services/codefixes/fixSpelling.ts index 222851cb99f96..a5b533eefccce 100644 --- a/src/services/codefixes/fixSpelling.ts +++ b/src/services/codefixes/fixSpelling.ts @@ -56,8 +56,12 @@ const errorCodes = [ Diagnostics.Cannot_find_name_0_Did_you_mean_the_instance_member_this_0.code, Diagnostics.Cannot_find_name_0_Did_you_mean_the_static_member_1_0.code, Diagnostics._0_has_no_exported_member_named_1_Did_you_mean_2.code, - Diagnostics.This_member_cannot_have_an_override_modifier_because_it_is_not_declared_in_the_base_class_0_Did_you_mean_1.code, - Diagnostics.This_member_cannot_have_a_JSDoc_comment_with_an_override_tag_because_it_is_not_declared_in_the_base_class_0_Did_you_mean_1.code, + Diagnostics + .This_member_cannot_have_an_override_modifier_because_it_is_not_declared_in_the_base_class_0_Did_you_mean_1 + .code, + Diagnostics + .This_member_cannot_have_a_JSDoc_comment_with_an_override_tag_because_it_is_not_declared_in_the_base_class_0_Did_you_mean_1 + .code, // for JSX class components Diagnostics.No_overload_matches_this_call.code, // for JSX FC @@ -71,8 +75,19 @@ registerCodeFix({ if (!info) return undefined; const { node, suggestedSymbol } = info; const target = getEmitScriptTarget(context.host.getCompilationSettings()); - const changes = textChanges.ChangeTracker.with(context, t => doChange(t, sourceFile, node, suggestedSymbol, target)); - return [createCodeFixAction("spelling", changes, [Diagnostics.Change_spelling_to_0, symbolName(suggestedSymbol)], fixId, Diagnostics.Fix_all_detected_spelling_errors)]; + const changes = textChanges.ChangeTracker.with( + context, + t => doChange(t, sourceFile, node, suggestedSymbol, target), + ); + return [ + createCodeFixAction( + "spelling", + changes, + [Diagnostics.Change_spelling_to_0, symbolName(suggestedSymbol)], + fixId, + Diagnostics.Fix_all_detected_spelling_errors, + ), + ]; }, fixIds: [fixId], getAllCodeActions: context => @@ -83,7 +98,12 @@ registerCodeFix({ }), }); -function getInfo(sourceFile: SourceFile, pos: number, context: CodeFixContextBase, errorCode: number): { node: Node; suggestedSymbol: Symbol; } | undefined { +function getInfo( + sourceFile: SourceFile, + pos: number, + context: CodeFixContextBase, + errorCode: number, +): { node: Node; suggestedSymbol: Symbol; } | undefined { // This is the identifier of the misspelled word. eg: // this.speling = 1; // ^^^^^^^ @@ -92,10 +112,10 @@ function getInfo(sourceFile: SourceFile, pos: number, context: CodeFixContextBas // Only fix spelling for No_overload_matches_this_call emitted on the React class component if ( ( - errorCode === Diagnostics.No_overload_matches_this_call.code || - errorCode === Diagnostics.Type_0_is_not_assignable_to_type_1.code - ) && - !isJsxAttribute(parent) + errorCode === Diagnostics.No_overload_matches_this_call.code + || errorCode === Diagnostics.Type_0_is_not_assignable_to_type_1.code + ) + && !isJsxAttribute(parent) ) return undefined; const checker = context.program.getTypeChecker(); @@ -108,7 +128,10 @@ function getInfo(sourceFile: SourceFile, pos: number, context: CodeFixContextBas } suggestedSymbol = checker.getSuggestedSymbolForNonexistentProperty(node, containingType); } - else if (isBinaryExpression(parent) && parent.operatorToken.kind === SyntaxKind.InKeyword && parent.left === node && isPrivateIdentifier(node)) { + else if ( + isBinaryExpression(parent) && parent.operatorToken.kind === SyntaxKind.InKeyword && parent.left === node + && isPrivateIdentifier(node) + ) { const receiverType = checker.getTypeAtLocation(parent.right); suggestedSymbol = checker.getSuggestedSymbolForNonexistentProperty(node, receiverType); } @@ -144,13 +167,23 @@ function getInfo(sourceFile: SourceFile, pos: number, context: CodeFixContextBas const meaning = getMeaningFromLocation(node); const name = getTextOfNode(node); Debug.assert(name !== undefined, "name should be defined"); - suggestedSymbol = checker.getSuggestedSymbolForNonexistentSymbol(node, name, convertSemanticMeaningToSymbolFlags(meaning)); + suggestedSymbol = checker.getSuggestedSymbolForNonexistentSymbol( + node, + name, + convertSemanticMeaningToSymbolFlags(meaning), + ); } return suggestedSymbol === undefined ? undefined : { node, suggestedSymbol }; } -function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, node: Node, suggestedSymbol: Symbol, target: ScriptTarget) { +function doChange( + changes: textChanges.ChangeTracker, + sourceFile: SourceFile, + node: Node, + suggestedSymbol: Symbol, + target: ScriptTarget, +) { const suggestion = symbolName(suggestedSymbol); if (!isIdentifierText(suggestion, target) && isPropertyAccessExpression(node.parent)) { const valDecl = suggestedSymbol.valueDeclaration; @@ -158,7 +191,11 @@ function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, no changes.replaceNode(sourceFile, node, factory.createIdentifier(suggestion)); } else { - changes.replaceNode(sourceFile, node.parent, factory.createElementAccessExpression(node.parent.expression, factory.createStringLiteral(suggestion))); + changes.replaceNode( + sourceFile, + node.parent, + factory.createElementAccessExpression(node.parent.expression, factory.createStringLiteral(suggestion)), + ); } } else { @@ -180,10 +217,18 @@ function convertSemanticMeaningToSymbolFlags(meaning: SemanticMeaning): SymbolFl return flags; } -function getResolvedSourceFileFromImportDeclaration(sourceFile: SourceFile, context: CodeFixContextBase, importDeclaration: ImportDeclaration): SourceFile | undefined { +function getResolvedSourceFileFromImportDeclaration( + sourceFile: SourceFile, + context: CodeFixContextBase, + importDeclaration: ImportDeclaration, +): SourceFile | undefined { if (!importDeclaration || !isStringLiteralLike(importDeclaration.moduleSpecifier)) return undefined; - const resolvedModule = getResolvedModule(sourceFile, importDeclaration.moduleSpecifier.text, getModeForUsageLocation(sourceFile, importDeclaration.moduleSpecifier)); + const resolvedModule = getResolvedModule( + sourceFile, + importDeclaration.moduleSpecifier.text, + getModeForUsageLocation(sourceFile, importDeclaration.moduleSpecifier), + ); if (!resolvedModule) return undefined; return context.program.getSourceFile(resolvedModule.resolvedFileName); diff --git a/src/services/codefixes/fixStrictClassInitialization.ts b/src/services/codefixes/fixStrictClassInitialization.ts index d42e858964a1b..695a7ab9b61b0 100644 --- a/src/services/codefixes/fixStrictClassInitialization.ts +++ b/src/services/codefixes/fixStrictClassInitialization.ts @@ -94,13 +94,29 @@ function getInfo(sourceFile: SourceFile, pos: number): Info | undefined { return undefined; } -function getActionForAddMissingDefiniteAssignmentAssertion(context: CodeFixContext, info: Info): CodeFixAction | undefined { +function getActionForAddMissingDefiniteAssignmentAssertion( + context: CodeFixContext, + info: Info, +): CodeFixAction | undefined { if (info.isJs) return undefined; - const changes = textChanges.ChangeTracker.with(context, t => addDefiniteAssignmentAssertion(t, context.sourceFile, info.prop)); - return createCodeFixAction(fixName, changes, [Diagnostics.Add_definite_assignment_assertion_to_property_0, info.prop.getText()], fixIdAddDefiniteAssignmentAssertions, Diagnostics.Add_definite_assignment_assertions_to_all_uninitialized_properties); + const changes = textChanges.ChangeTracker.with( + context, + t => addDefiniteAssignmentAssertion(t, context.sourceFile, info.prop), + ); + return createCodeFixAction( + fixName, + changes, + [Diagnostics.Add_definite_assignment_assertion_to_property_0, info.prop.getText()], + fixIdAddDefiniteAssignmentAssertions, + Diagnostics.Add_definite_assignment_assertions_to_all_uninitialized_properties, + ); } -function addDefiniteAssignmentAssertion(changeTracker: textChanges.ChangeTracker, propertyDeclarationSourceFile: SourceFile, propertyDeclaration: PropertyDeclaration): void { +function addDefiniteAssignmentAssertion( + changeTracker: textChanges.ChangeTracker, + propertyDeclarationSourceFile: SourceFile, + propertyDeclaration: PropertyDeclaration, +): void { suppressLeadingAndTrailingTrivia(propertyDeclaration); const property = factory.updatePropertyDeclaration( propertyDeclaration, @@ -115,15 +131,24 @@ function addDefiniteAssignmentAssertion(changeTracker: textChanges.ChangeTracker function getActionForAddMissingUndefinedType(context: CodeFixContext, info: Info): CodeFixAction { const changes = textChanges.ChangeTracker.with(context, t => addUndefinedType(t, context.sourceFile, info)); - return createCodeFixAction(fixName, changes, [Diagnostics.Add_undefined_type_to_property_0, info.prop.name.getText()], fixIdAddUndefinedType, Diagnostics.Add_undefined_type_to_all_uninitialized_properties); + return createCodeFixAction( + fixName, + changes, + [Diagnostics.Add_undefined_type_to_property_0, info.prop.name.getText()], + fixIdAddUndefinedType, + Diagnostics.Add_undefined_type_to_all_uninitialized_properties, + ); } function addUndefinedType(changeTracker: textChanges.ChangeTracker, sourceFile: SourceFile, info: Info): void { const undefinedTypeNode = factory.createKeywordTypeNode(SyntaxKind.UndefinedKeyword); - const types = isUnionTypeNode(info.type) ? info.type.types.concat(undefinedTypeNode) : [info.type, undefinedTypeNode]; + const types = isUnionTypeNode(info.type) ? info.type.types.concat(undefinedTypeNode) + : [info.type, undefinedTypeNode]; const unionTypeNode = factory.createUnionTypeNode(types); if (info.isJs) { - changeTracker.addJSDocTags(sourceFile, info.prop, [factory.createJSDocTypeTag(/*tagName*/ undefined, factory.createJSDocTypeExpression(unionTypeNode))]); + changeTracker.addJSDocTags(sourceFile, info.prop, [ + factory.createJSDocTypeTag(/*tagName*/ undefined, factory.createJSDocTypeExpression(unionTypeNode)), + ]); } else { changeTracker.replaceNode(sourceFile, info.type, unionTypeNode); @@ -137,11 +162,25 @@ function getActionForAddMissingInitializer(context: CodeFixContext, info: Info): const initializer = getInitializer(checker, info.prop); if (!initializer) return undefined; - const changes = textChanges.ChangeTracker.with(context, t => addInitializer(t, context.sourceFile, info.prop, initializer)); - return createCodeFixAction(fixName, changes, [Diagnostics.Add_initializer_to_property_0, info.prop.name.getText()], fixIdAddInitializer, Diagnostics.Add_initializers_to_all_uninitialized_properties); + const changes = textChanges.ChangeTracker.with( + context, + t => addInitializer(t, context.sourceFile, info.prop, initializer), + ); + return createCodeFixAction( + fixName, + changes, + [Diagnostics.Add_initializer_to_property_0, info.prop.name.getText()], + fixIdAddInitializer, + Diagnostics.Add_initializers_to_all_uninitialized_properties, + ); } -function addInitializer(changeTracker: textChanges.ChangeTracker, propertyDeclarationSourceFile: SourceFile, propertyDeclaration: PropertyDeclaration, initializer: Expression): void { +function addInitializer( + changeTracker: textChanges.ChangeTracker, + propertyDeclarationSourceFile: SourceFile, + propertyDeclaration: PropertyDeclaration, + initializer: Expression, +): void { suppressLeadingAndTrailingTrivia(propertyDeclaration); const property = factory.updatePropertyDeclaration( propertyDeclaration, @@ -160,7 +199,8 @@ function getInitializer(checker: TypeChecker, propertyDeclaration: PropertyDecla function getDefaultValueFromType(checker: TypeChecker, type: Type): Expression | undefined { if (type.flags & TypeFlags.BooleanLiteral) { - return (type === checker.getFalseType() || type === checker.getFalseType(/*fresh*/ true)) ? factory.createFalse() : factory.createTrue(); + return (type === checker.getFalseType() || type === checker.getFalseType(/*fresh*/ true)) + ? factory.createFalse() : factory.createTrue(); } else if (type.isStringLiteral()) { return factory.createStringLiteral(type.value); @@ -181,7 +221,11 @@ function getDefaultValueFromType(checker: TypeChecker, type: Type): Expression | const constructorDeclaration = getFirstConstructorWithBody(classDeclaration); if (constructorDeclaration && constructorDeclaration.parameters.length) return undefined; - return factory.createNewExpression(factory.createIdentifier(type.symbol.name), /*typeArguments*/ undefined, /*argumentsArray*/ undefined); + return factory.createNewExpression( + factory.createIdentifier(type.symbol.name), + /*typeArguments*/ undefined, + /*argumentsArray*/ undefined, + ); } else if (checker.isArrayLikeType(type)) { return factory.createArrayLiteralExpression(); diff --git a/src/services/codefixes/fixUnmatchedParameter.ts b/src/services/codefixes/fixUnmatchedParameter.ts index bba50c32e589f..aa1cf5cea0730 100644 --- a/src/services/codefixes/fixUnmatchedParameter.ts +++ b/src/services/codefixes/fixUnmatchedParameter.ts @@ -57,7 +57,10 @@ registerCodeFix({ eachDiagnostic(context, errorCodes, ({ file, start }) => { const info = getInfo(file, start); if (info) { - tagsToSignature.set(info.signature, append(tagsToSignature.get(info.signature), info.jsDocParameterTag)); + tagsToSignature.set( + info.signature, + append(tagsToSignature.get(info.signature), info.jsDocParameterTag), + ); } }); @@ -72,7 +75,10 @@ registerCodeFix({ }); function getDeleteAction(context: CodeFixContext, { name, jsDocHost, jsDocParameterTag }: Info) { - const changes = textChanges.ChangeTracker.with(context, changeTracker => changeTracker.filterJSDocTags(context.sourceFile, jsDocHost, t => t !== jsDocParameterTag)); + const changes = textChanges.ChangeTracker.with( + context, + changeTracker => changeTracker.filterJSDocTags(context.sourceFile, jsDocHost, t => t !== jsDocParameterTag), + ); return createCodeFixAction( deleteUnmatchedParameter, changes, @@ -95,7 +101,10 @@ function getRenameAction(context: CodeFixContext, { name, jsDocHost, signature, } // @todo - match to all available names instead to the first parameter name // @see /codeFixRenameUnmatchedParameter3.ts - const parameterName = firstDefined(signature.parameters, p => isIdentifier(p.name) && !names.has(p.name.escapedText) ? p.name.getText(sourceFile) : undefined); + const parameterName = firstDefined( + signature.parameters, + p => isIdentifier(p.name) && !names.has(p.name.escapedText) ? p.name.getText(sourceFile) : undefined, + ); if (parameterName === undefined) return undefined; const newJSDocParameterTag = factory.updateJSDocParameterTag( @@ -107,8 +116,20 @@ function getRenameAction(context: CodeFixContext, { name, jsDocHost, signature, jsDocParameterTag.isNameFirst, jsDocParameterTag.comment, ); - const changes = textChanges.ChangeTracker.with(context, changeTracker => changeTracker.replaceJSDocComment(sourceFile, jsDocHost, map(tags, t => t === jsDocParameterTag ? newJSDocParameterTag : t))); - return createCodeFixActionWithoutFixAll(renameUnmatchedParameter, changes, [Diagnostics.Rename_param_tag_name_0_to_1, name.getText(sourceFile), parameterName]); + const changes = textChanges.ChangeTracker.with( + context, + changeTracker => + changeTracker.replaceJSDocComment( + sourceFile, + jsDocHost, + map(tags, t => t === jsDocParameterTag ? newJSDocParameterTag : t), + ), + ); + return createCodeFixActionWithoutFixAll(renameUnmatchedParameter, changes, [ + Diagnostics.Rename_param_tag_name_0_to_1, + name.getText(sourceFile), + parameterName, + ]); } interface Info { diff --git a/src/services/codefixes/fixUnreachableCode.ts b/src/services/codefixes/fixUnreachableCode.ts index 61c363c3fc868..cf4a359fd1ff2 100644 --- a/src/services/codefixes/fixUnreachableCode.ts +++ b/src/services/codefixes/fixUnreachableCode.ts @@ -25,16 +25,41 @@ const errorCodes = [Diagnostics.Unreachable_code_detected.code]; registerCodeFix({ errorCodes, getCodeActions(context) { - const syntacticDiagnostics = context.program.getSyntacticDiagnostics(context.sourceFile, context.cancellationToken); + const syntacticDiagnostics = context.program.getSyntacticDiagnostics( + context.sourceFile, + context.cancellationToken, + ); if (syntacticDiagnostics.length) return; - const changes = textChanges.ChangeTracker.with(context, t => doChange(t, context.sourceFile, context.span.start, context.span.length, context.errorCode)); - return [createCodeFixAction(fixId, changes, Diagnostics.Remove_unreachable_code, fixId, Diagnostics.Remove_all_unreachable_code)]; + const changes = textChanges.ChangeTracker.with( + context, + t => doChange(t, context.sourceFile, context.span.start, context.span.length, context.errorCode), + ); + return [ + createCodeFixAction( + fixId, + changes, + Diagnostics.Remove_unreachable_code, + fixId, + Diagnostics.Remove_all_unreachable_code, + ), + ]; }, fixIds: [fixId], - getAllCodeActions: context => codeFixAll(context, errorCodes, (changes, diag) => doChange(changes, diag.file, diag.start, diag.length, diag.code)), + getAllCodeActions: context => + codeFixAll( + context, + errorCodes, + (changes, diag) => doChange(changes, diag.file, diag.start, diag.length, diag.code), + ), }); -function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, start: number, length: number, errorCode: number): void { +function doChange( + changes: textChanges.ChangeTracker, + sourceFile: SourceFile, + start: number, + length: number, + errorCode: number, +): void { const token = getTokenAtPosition(sourceFile, start); const statement = findAncestor(token, isStatement)!; if (statement.getStart(sourceFile) !== token.getStart(sourceFile)) { @@ -71,7 +96,10 @@ function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, st if (isBlock(statement.parent)) { const end = start + length; - const lastStatement = Debug.checkDefined(lastWhere(sliceAfter(statement.parent.statements, statement), s => s.pos < end), "Some statement should be last"); + const lastStatement = Debug.checkDefined( + lastWhere(sliceAfter(statement.parent.statements, statement), s => s.pos < end), + "Some statement should be last", + ); changes.deleteNodeRange(sourceFile, statement, lastStatement); } else { diff --git a/src/services/codefixes/fixUnreferenceableDecoratorMetadata.ts b/src/services/codefixes/fixUnreferenceableDecoratorMetadata.ts index 4c35ee6b9629a..d76e3bfddb1e4 100644 --- a/src/services/codefixes/fixUnreferenceableDecoratorMetadata.ts +++ b/src/services/codefixes/fixUnreferenceableDecoratorMetadata.ts @@ -30,34 +30,64 @@ import { } from "../_namespaces/ts.codefix"; const fixId = "fixUnreferenceableDecoratorMetadata"; -const errorCodes = [Diagnostics.A_type_referenced_in_a_decorated_signature_must_be_imported_with_import_type_or_a_namespace_import_when_isolatedModules_and_emitDecoratorMetadata_are_enabled.code]; +const errorCodes = [ + Diagnostics + .A_type_referenced_in_a_decorated_signature_must_be_imported_with_import_type_or_a_namespace_import_when_isolatedModules_and_emitDecoratorMetadata_are_enabled + .code, +]; registerCodeFix({ errorCodes, getCodeActions: context => { const importDeclaration = getImportDeclaration(context.sourceFile, context.program, context.span.start); if (!importDeclaration) return; - const namespaceChanges = textChanges.ChangeTracker.with(context, t => importDeclaration.kind === SyntaxKind.ImportSpecifier && doNamespaceImportChange(t, context.sourceFile, importDeclaration, context.program)); - const typeOnlyChanges = textChanges.ChangeTracker.with(context, t => doTypeOnlyImportChange(t, context.sourceFile, importDeclaration, context.program)); + const namespaceChanges = textChanges.ChangeTracker.with( + context, + t => importDeclaration.kind === SyntaxKind.ImportSpecifier + && doNamespaceImportChange(t, context.sourceFile, importDeclaration, context.program), + ); + const typeOnlyChanges = textChanges.ChangeTracker.with( + context, + t => doTypeOnlyImportChange(t, context.sourceFile, importDeclaration, context.program), + ); let actions: CodeFixAction[] | undefined; if (namespaceChanges.length) { - actions = append(actions, createCodeFixActionWithoutFixAll(fixId, namespaceChanges, Diagnostics.Convert_named_imports_to_namespace_import)); + actions = append( + actions, + createCodeFixActionWithoutFixAll( + fixId, + namespaceChanges, + Diagnostics.Convert_named_imports_to_namespace_import, + ), + ); } if (typeOnlyChanges.length) { - actions = append(actions, createCodeFixActionWithoutFixAll(fixId, typeOnlyChanges, Diagnostics.Use_import_type)); + actions = append( + actions, + createCodeFixActionWithoutFixAll(fixId, typeOnlyChanges, Diagnostics.Use_import_type), + ); } return actions; }, fixIds: [fixId], }); -function getImportDeclaration(sourceFile: SourceFile, program: Program, start: number): ImportClause | ImportSpecifier | ImportEqualsDeclaration | undefined { +function getImportDeclaration( + sourceFile: SourceFile, + program: Program, + start: number, +): ImportClause | ImportSpecifier | ImportEqualsDeclaration | undefined { const identifier = tryCast(getTokenAtPosition(sourceFile, start), isIdentifier); if (!identifier || identifier.parent.kind !== SyntaxKind.TypeReference) return; const checker = program.getTypeChecker(); const symbol = checker.getSymbolAtLocation(identifier); - return find(symbol?.declarations || emptyArray, or(isImportClause, isImportSpecifier, isImportEqualsDeclaration) as (n: Node) => n is ImportClause | ImportSpecifier | ImportEqualsDeclaration); + return find( + symbol?.declarations || emptyArray, + or(isImportClause, isImportSpecifier, isImportEqualsDeclaration) as ( + n: Node, + ) => n is ImportClause | ImportSpecifier | ImportEqualsDeclaration, + ); } // Converts the import declaration of the offending import to a type-only import, @@ -65,13 +95,19 @@ function getImportDeclaration(sourceFile: SourceFile, program: Program, start: n // cannot be done cleanly, we could offer to *extract* the offending import to a // new type-only import declaration, but honestly I doubt anyone will ever use this // codefix at all, so it's probably not worth the lines of code. -function doTypeOnlyImportChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, importDeclaration: ImportClause | ImportSpecifier | ImportEqualsDeclaration, program: Program) { +function doTypeOnlyImportChange( + changes: textChanges.ChangeTracker, + sourceFile: SourceFile, + importDeclaration: ImportClause | ImportSpecifier | ImportEqualsDeclaration, + program: Program, +) { if (importDeclaration.kind === SyntaxKind.ImportEqualsDeclaration) { changes.insertModifierBefore(sourceFile, SyntaxKind.TypeKeyword, importDeclaration.name); return; } - const importClause = importDeclaration.kind === SyntaxKind.ImportClause ? importDeclaration : importDeclaration.parent.parent; + const importClause = importDeclaration.kind === SyntaxKind.ImportClause ? importDeclaration + : importDeclaration.parent.parent; if (importClause.name && importClause.namedBindings) { // Cannot convert an import with a default import and named bindings to type-only // (it's a grammar error). @@ -93,6 +129,11 @@ function doTypeOnlyImportChange(changes: textChanges.ChangeTracker, sourceFile: changes.insertModifierBefore(sourceFile, SyntaxKind.TypeKeyword, importClause); } -function doNamespaceImportChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, importDeclaration: ImportSpecifier, program: Program) { +function doNamespaceImportChange( + changes: textChanges.ChangeTracker, + sourceFile: SourceFile, + importDeclaration: ImportSpecifier, + program: Program, +) { refactor.doChangeNamedToNamespaceOrDefault(sourceFile, program, changes, importDeclaration.parent); } diff --git a/src/services/codefixes/fixUnusedIdentifier.ts b/src/services/codefixes/fixUnusedIdentifier.ts index 494721afb5ce5..39ba73b735470 100644 --- a/src/services/codefixes/fixUnusedIdentifier.ts +++ b/src/services/codefixes/fixUnusedIdentifier.ts @@ -89,7 +89,12 @@ registerCodeFix({ const token = getTokenAtPosition(sourceFile, context.span.start); if (isJSDocTemplateTag(token)) { - return [createDeleteFix(textChanges.ChangeTracker.with(context, t => t.delete(sourceFile, token)), Diagnostics.Remove_template_tag)]; + return [ + createDeleteFix( + textChanges.ChangeTracker.with(context, t => t.delete(sourceFile, token)), + Diagnostics.Remove_template_tag, + ), + ]; } if (token.kind === SyntaxKind.LessThanToken) { const changes = textChanges.ChangeTracker.with(context, t => deleteTypeParameters(t, sourceFile, token)); @@ -98,12 +103,40 @@ registerCodeFix({ const importDecl = tryGetFullImport(token); if (importDecl) { const changes = textChanges.ChangeTracker.with(context, t => t.delete(sourceFile, importDecl)); - return [createCodeFixAction(fixName, changes, [Diagnostics.Remove_import_from_0, showModuleSpecifier(importDecl)], fixIdDeleteImports, Diagnostics.Delete_all_unused_imports)]; + return [ + createCodeFixAction( + fixName, + changes, + [Diagnostics.Remove_import_from_0, showModuleSpecifier(importDecl)], + fixIdDeleteImports, + Diagnostics.Delete_all_unused_imports, + ), + ]; } else if (isImport(token)) { - const deletion = textChanges.ChangeTracker.with(context, t => tryDeleteDeclaration(sourceFile, token, t, checker, sourceFiles, program, cancellationToken, /*isFixAll*/ false)); + const deletion = textChanges.ChangeTracker.with( + context, + t => tryDeleteDeclaration( + sourceFile, + token, + t, + checker, + sourceFiles, + program, + cancellationToken, + /*isFixAll*/ false, + ), + ); if (deletion.length) { - return [createCodeFixAction(fixName, deletion, [Diagnostics.Remove_unused_declaration_for_Colon_0, token.getText(sourceFile)], fixIdDeleteImports, Diagnostics.Delete_all_unused_imports)]; + return [ + createCodeFixAction( + fixName, + deletion, + [Diagnostics.Remove_unused_declaration_for_Colon_0, token.getText(sourceFile)], + fixIdDeleteImports, + Diagnostics.Delete_all_unused_imports, + ), + ]; } } @@ -111,21 +144,45 @@ registerCodeFix({ if (isParameter(token.parent.parent)) { const elements = token.parent.elements; const diagnostic: [DiagnosticMessage, string] = [ - elements.length > 1 ? Diagnostics.Remove_unused_declarations_for_Colon_0 : Diagnostics.Remove_unused_declaration_for_Colon_0, + elements.length > 1 ? Diagnostics.Remove_unused_declarations_for_Colon_0 + : Diagnostics.Remove_unused_declaration_for_Colon_0, map(elements, e => e.getText(sourceFile)).join(", "), ]; return [ - createDeleteFix(textChanges.ChangeTracker.with(context, t => deleteDestructuringElements(t, sourceFile, token.parent as ObjectBindingPattern | ArrayBindingPattern)), diagnostic), + createDeleteFix( + textChanges.ChangeTracker.with(context, t => + deleteDestructuringElements( + t, + sourceFile, + token.parent as ObjectBindingPattern | ArrayBindingPattern, + )), + diagnostic, + ), ]; } return [ - createDeleteFix(textChanges.ChangeTracker.with(context, t => deleteDestructuring(context, t, sourceFile, token.parent as ObjectBindingPattern | ArrayBindingPattern)), Diagnostics.Remove_unused_destructuring_declaration), + createDeleteFix( + textChanges.ChangeTracker.with(context, t => + deleteDestructuring( + context, + t, + sourceFile, + token.parent as ObjectBindingPattern | ArrayBindingPattern, + )), + Diagnostics.Remove_unused_destructuring_declaration, + ), ]; } if (canDeleteEntireVariableStatement(sourceFile, token)) { return [ - createDeleteFix(textChanges.ChangeTracker.with(context, t => deleteEntireVariableStatement(t, sourceFile, token.parent as VariableDeclarationList)), Diagnostics.Remove_variable_statement), + createDeleteFix( + textChanges.ChangeTracker.with( + context, + t => deleteEntireVariableStatement(t, sourceFile, token.parent as VariableDeclarationList), + ), + Diagnostics.Remove_variable_statement, + ), ]; } @@ -133,19 +190,55 @@ registerCodeFix({ if (token.kind === SyntaxKind.InferKeyword) { const changes = textChanges.ChangeTracker.with(context, t => changeInferToUnknown(t, sourceFile, token)); const name = cast(token.parent, isInferTypeNode).typeParameter.name.text; - result.push(createCodeFixAction(fixName, changes, [Diagnostics.Replace_infer_0_with_unknown, name], fixIdInfer, Diagnostics.Replace_all_unused_infer_with_unknown)); + result.push( + createCodeFixAction( + fixName, + changes, + [Diagnostics.Replace_infer_0_with_unknown, name], + fixIdInfer, + Diagnostics.Replace_all_unused_infer_with_unknown, + ), + ); } else { - const deletion = textChanges.ChangeTracker.with(context, t => tryDeleteDeclaration(sourceFile, token, t, checker, sourceFiles, program, cancellationToken, /*isFixAll*/ false)); + const deletion = textChanges.ChangeTracker.with( + context, + t => tryDeleteDeclaration( + sourceFile, + token, + t, + checker, + sourceFiles, + program, + cancellationToken, + /*isFixAll*/ false, + ), + ); if (deletion.length) { const name = isComputedPropertyName(token.parent) ? token.parent : token; - result.push(createDeleteFix(deletion, [Diagnostics.Remove_unused_declaration_for_Colon_0, name.getText(sourceFile)])); + result.push( + createDeleteFix(deletion, [ + Diagnostics.Remove_unused_declaration_for_Colon_0, + name.getText(sourceFile), + ]), + ); } } - const prefix = textChanges.ChangeTracker.with(context, t => tryPrefixDeclaration(t, errorCode, sourceFile, token)); + const prefix = textChanges.ChangeTracker.with( + context, + t => tryPrefixDeclaration(t, errorCode, sourceFile, token), + ); if (prefix.length) { - result.push(createCodeFixAction(fixName, prefix, [Diagnostics.Prefix_0_with_an_underscore, token.getText(sourceFile)], fixIdPrefix, Diagnostics.Prefix_all_unused_declarations_with_where_possible)); + result.push( + createCodeFixAction( + fixName, + prefix, + [Diagnostics.Prefix_0_with_an_underscore, token.getText(sourceFile)], + fixIdPrefix, + Diagnostics.Prefix_all_unused_declarations_with_where_possible, + ), + ); } return result; @@ -167,7 +260,16 @@ registerCodeFix({ changes.delete(sourceFile, importDecl); } else if (isImport(token)) { - tryDeleteDeclaration(sourceFile, token, changes, checker, sourceFiles, program, cancellationToken, /*isFixAll*/ true); + tryDeleteDeclaration( + sourceFile, + token, + changes, + checker, + sourceFiles, + program, + cancellationToken, + /*isFixAll*/ true, + ); } break; } @@ -185,7 +287,10 @@ registerCodeFix({ if (token.parent.parent.initializer) { break; } - else if (!isParameter(token.parent.parent) || isNotProvidedArguments(token.parent.parent, checker, sourceFiles)) { + else if ( + !isParameter(token.parent.parent) + || isNotProvidedArguments(token.parent.parent, checker, sourceFiles) + ) { changes.delete(sourceFile, token.parent.parent); } } @@ -196,7 +301,16 @@ registerCodeFix({ deleteEntireVariableStatement(changes, sourceFile, token.parent as VariableDeclarationList); } else { - tryDeleteDeclaration(sourceFile, token, changes, checker, sourceFiles, program, cancellationToken, /*isFixAll*/ true); + tryDeleteDeclaration( + sourceFile, + token, + changes, + checker, + sourceFiles, + program, + cancellationToken, + /*isFixAll*/ true, + ); } break; } @@ -221,12 +335,19 @@ function createDeleteFix(changes: FileTextChanges[], diag: DiagnosticOrDiagnosti } function deleteTypeParameters(changes: textChanges.ChangeTracker, sourceFile: SourceFile, token: Node): void { - changes.delete(sourceFile, Debug.checkDefined(cast(token.parent, isDeclarationWithTypeParameterChildren).typeParameters, "The type parameter to delete should exist")); + changes.delete( + sourceFile, + Debug.checkDefined( + cast(token.parent, isDeclarationWithTypeParameterChildren).typeParameters, + "The type parameter to delete should exist", + ), + ); } function isImport(token: Node) { return token.kind === SyntaxKind.ImportKeyword - || token.kind === SyntaxKind.Identifier && (token.parent.kind === SyntaxKind.ImportSpecifier || token.parent.kind === SyntaxKind.ImportClause); + || token.kind === SyntaxKind.Identifier + && (token.parent.kind === SyntaxKind.ImportSpecifier || token.parent.kind === SyntaxKind.ImportClause); } /** Sometimes the diagnostic span is an entire ImportDeclaration, so we should remove the whole thing. */ @@ -238,15 +359,28 @@ function canDeleteEntireVariableStatement(sourceFile: SourceFile, token: Node): return isVariableDeclarationList(token.parent) && first(token.parent.getChildren(sourceFile)) === token; } -function deleteEntireVariableStatement(changes: textChanges.ChangeTracker, sourceFile: SourceFile, node: VariableDeclarationList) { +function deleteEntireVariableStatement( + changes: textChanges.ChangeTracker, + sourceFile: SourceFile, + node: VariableDeclarationList, +) { changes.delete(sourceFile, node.parent.kind === SyntaxKind.VariableStatement ? node.parent : node); } -function deleteDestructuringElements(changes: textChanges.ChangeTracker, sourceFile: SourceFile, node: ObjectBindingPattern | ArrayBindingPattern) { +function deleteDestructuringElements( + changes: textChanges.ChangeTracker, + sourceFile: SourceFile, + node: ObjectBindingPattern | ArrayBindingPattern, +) { forEach(node.elements, n => changes.delete(sourceFile, n)); } -function deleteDestructuring(context: CodeFixContext, changes: textChanges.ChangeTracker, sourceFile: SourceFile, { parent }: ObjectBindingPattern | ArrayBindingPattern) { +function deleteDestructuring( + context: CodeFixContext, + changes: textChanges.ChangeTracker, + sourceFile: SourceFile, + { parent }: ObjectBindingPattern | ArrayBindingPattern, +) { if (isVariableDeclaration(parent) && parent.initializer && isCallLikeExpression(parent.initializer)) { if (isVariableDeclarationList(parent.parent) && length(parent.parent.declarations) > 1) { const varStatement = parent.parent.parent; @@ -254,7 +388,8 @@ function deleteDestructuring(context: CodeFixContext, changes: textChanges.Chang const end = varStatement.end; changes.delete(sourceFile, parent); changes.insertNodeAt(sourceFile, end, parent.initializer, { - prefix: getNewLineOrDefaultFromHost(context.host, context.formatContext.options) + sourceFile.text.slice(getPrecedingNonSpaceCharacterPosition(sourceFile.text, pos - 1), pos), + prefix: getNewLineOrDefaultFromHost(context.host, context.formatContext.options) + + sourceFile.text.slice(getPrecedingNonSpaceCharacterPosition(sourceFile.text, pos - 1), pos), suffix: probablyUsesSemicolons(sourceFile) ? ";" : "", }); } @@ -267,7 +402,12 @@ function deleteDestructuring(context: CodeFixContext, changes: textChanges.Chang } } -function tryPrefixDeclaration(changes: textChanges.ChangeTracker, errorCode: number, sourceFile: SourceFile, token: Node): void { +function tryPrefixDeclaration( + changes: textChanges.ChangeTracker, + errorCode: number, + sourceFile: SourceFile, + token: Node, +): void { // Don't offer to prefix a property. if (errorCode === Diagnostics.Property_0_is_declared_but_its_value_is_never_read.code) return; if (token.kind === SyntaxKind.InferKeyword) { @@ -302,7 +442,16 @@ function canPrefix(token: Identifier): boolean { return false; } -function tryDeleteDeclaration(sourceFile: SourceFile, token: Node, changes: textChanges.ChangeTracker, checker: TypeChecker, sourceFiles: readonly SourceFile[], program: Program, cancellationToken: CancellationToken, isFixAll: boolean) { +function tryDeleteDeclaration( + sourceFile: SourceFile, + token: Node, + changes: textChanges.ChangeTracker, + checker: TypeChecker, + sourceFiles: readonly SourceFile[], + program: Program, + cancellationToken: CancellationToken, + isFixAll: boolean, +) { tryDeleteDeclarationWorker(token, changes, sourceFile, checker, sourceFiles, program, cancellationToken, isFixAll); if (isIdentifier(token)) { FindAllReferences.Core.eachSymbolReferenceInFile(token, checker, sourceFile, (ref: Node) => { @@ -314,12 +463,24 @@ function tryDeleteDeclaration(sourceFile: SourceFile, token: Node, changes: text } } -function tryDeleteDeclarationWorker(token: Node, changes: textChanges.ChangeTracker, sourceFile: SourceFile, checker: TypeChecker, sourceFiles: readonly SourceFile[], program: Program, cancellationToken: CancellationToken, isFixAll: boolean): void { +function tryDeleteDeclarationWorker( + token: Node, + changes: textChanges.ChangeTracker, + sourceFile: SourceFile, + checker: TypeChecker, + sourceFiles: readonly SourceFile[], + program: Program, + cancellationToken: CancellationToken, + isFixAll: boolean, +): void { const { parent } = token; if (isParameter(parent)) { tryDeleteParameter(changes, sourceFile, parent, checker, sourceFiles, program, cancellationToken, isFixAll); } - else if (!(isFixAll && isIdentifier(token) && FindAllReferences.Core.isSymbolReferencedInFile(token, checker, sourceFile))) { + else if ( + !(isFixAll && isIdentifier(token) + && FindAllReferences.Core.isSymbolReferencedInFile(token, checker, sourceFile)) + ) { const node = isImportClause(parent) ? token : isComputedPropertyName(parent) ? parent.parent : parent; Debug.assert(node !== sourceFile, "should not delete whole source file"); changes.delete(sourceFile, node); @@ -338,8 +499,9 @@ function tryDeleteParameter( ): void { if (mayDeleteParameter(checker, sourceFile, parameter, sourceFiles, program, cancellationToken, isFixAll)) { if ( - parameter.modifiers && parameter.modifiers.length > 0 && - (!isIdentifier(parameter.name) || FindAllReferences.Core.isSymbolReferencedInFile(parameter.name, checker, sourceFile)) + parameter.modifiers && parameter.modifiers.length > 0 + && (!isIdentifier(parameter.name) + || FindAllReferences.Core.isSymbolReferencedInFile(parameter.name, checker, sourceFile)) ) { for (const modifier of parameter.modifiers) { if (isModifier(modifier)) { @@ -353,20 +515,43 @@ function tryDeleteParameter( } } -function isNotProvidedArguments(parameter: ParameterDeclaration, checker: TypeChecker, sourceFiles: readonly SourceFile[]) { +function isNotProvidedArguments( + parameter: ParameterDeclaration, + checker: TypeChecker, + sourceFiles: readonly SourceFile[], +) { const index = parameter.parent.parameters.indexOf(parameter); // Just in case the call didn't provide enough arguments. - return !FindAllReferences.Core.someSignatureUsage(parameter.parent, sourceFiles, checker, (_, call) => !call || call.arguments.length > index); + return !FindAllReferences.Core.someSignatureUsage( + parameter.parent, + sourceFiles, + checker, + (_, call) => !call || call.arguments.length > index, + ); } -function mayDeleteParameter(checker: TypeChecker, sourceFile: SourceFile, parameter: ParameterDeclaration, sourceFiles: readonly SourceFile[], program: Program, cancellationToken: CancellationToken, isFixAll: boolean): boolean { +function mayDeleteParameter( + checker: TypeChecker, + sourceFile: SourceFile, + parameter: ParameterDeclaration, + sourceFiles: readonly SourceFile[], + program: Program, + cancellationToken: CancellationToken, + isFixAll: boolean, +): boolean { const { parent } = parameter; switch (parent.kind) { case SyntaxKind.MethodDeclaration: case SyntaxKind.Constructor: const index = parent.parameters.indexOf(parameter); const referent = isMethodDeclaration(parent) ? parent.name : parent; - const entries = FindAllReferences.Core.getReferencedSymbolsForNode(parent.pos, referent, program, sourceFiles, cancellationToken); + const entries = FindAllReferences.Core.getReferencedSymbolsForNode( + parent.pos, + referent, + program, + sourceFiles, + cancellationToken, + ); if (entries) { for (const entry of entries) { for (const reference of entry.references) { @@ -381,7 +566,8 @@ function mayDeleteParameter(checker: TypeChecker, sourceFile: SourceFile, parame && isCallExpression(reference.node.parent.parent) && reference.node.parent.parent.arguments.length > index; // parameter in overridden or overriding method - const isOverriddenMethod = (isMethodDeclaration(reference.node.parent) || isMethodSignature(reference.node.parent)) + const isOverriddenMethod = + (isMethodDeclaration(reference.node.parent) || isMethodSignature(reference.node.parent)) && reference.node.parent !== parameter.parent && reference.node.parent.parameters.length > index; if (isSuperCall || isSuperMethodCall || isOverriddenMethod) return false; @@ -415,19 +601,27 @@ function mayDeleteParameter(checker: TypeChecker, sourceFile: SourceFile, parame } function isCallbackLike(checker: TypeChecker, sourceFile: SourceFile, name: Identifier): boolean { - return !!FindAllReferences.Core.eachSymbolReferenceInFile(name, checker, sourceFile, reference => isIdentifier(reference) && isCallExpression(reference.parent) && reference.parent.arguments.indexOf(reference) >= 0); + return !!FindAllReferences.Core.eachSymbolReferenceInFile( + name, + checker, + sourceFile, + reference => + isIdentifier(reference) && isCallExpression(reference.parent) + && reference.parent.arguments.indexOf(reference) >= 0, + ); } function isLastParameter(func: FunctionLikeDeclaration, parameter: ParameterDeclaration, isFixAll: boolean): boolean { const parameters = func.parameters; const index = parameters.indexOf(parameter); Debug.assert(index !== -1, "The parameter should already be in the list"); - return isFixAll ? - parameters.slice(index + 1).every(p => isIdentifier(p.name) && !p.symbol.isReferenced) : - index === parameters.length - 1; + return isFixAll + ? parameters.slice(index + 1).every(p => isIdentifier(p.name) && !p.symbol.isReferenced) + : index === parameters.length - 1; } function mayDeleteExpression(node: Node) { - return ((isBinaryExpression(node.parent) && node.parent.left === node) || - ((isPostfixUnaryExpression(node.parent) || isPrefixUnaryExpression(node.parent)) && node.parent.operand === node)) && isExpressionStatement(node.parent.parent); + return ((isBinaryExpression(node.parent) && node.parent.left === node) + || ((isPostfixUnaryExpression(node.parent) || isPrefixUnaryExpression(node.parent)) + && node.parent.operand === node)) && isExpressionStatement(node.parent.parent); } diff --git a/src/services/codefixes/fixUnusedLabel.ts b/src/services/codefixes/fixUnusedLabel.ts index 88e6aed5d41a6..c30b26f5a405a 100644 --- a/src/services/codefixes/fixUnusedLabel.ts +++ b/src/services/codefixes/fixUnusedLabel.ts @@ -21,11 +21,23 @@ const errorCodes = [Diagnostics.Unused_label.code]; registerCodeFix({ errorCodes, getCodeActions(context) { - const changes = textChanges.ChangeTracker.with(context, t => doChange(t, context.sourceFile, context.span.start)); - return [createCodeFixAction(fixId, changes, Diagnostics.Remove_unused_label, fixId, Diagnostics.Remove_all_unused_labels)]; + const changes = textChanges.ChangeTracker.with( + context, + t => doChange(t, context.sourceFile, context.span.start), + ); + return [ + createCodeFixAction( + fixId, + changes, + Diagnostics.Remove_unused_label, + fixId, + Diagnostics.Remove_all_unused_labels, + ), + ]; }, fixIds: [fixId], - getAllCodeActions: context => codeFixAll(context, errorCodes, (changes, diag) => doChange(changes, diag.file, diag.start)), + getAllCodeActions: context => + codeFixAll(context, errorCodes, (changes, diag) => doChange(changes, diag.file, diag.start)), }); function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, start: number): void { @@ -35,6 +47,10 @@ function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, st const statementPos = labeledStatement.statement.getStart(sourceFile); // If label is on a separate line, just delete the rest of that line, but not the indentation of the labeled statement. const end = positionsAreOnSameLine(pos, statementPos, sourceFile) ? statementPos - : skipTrivia(sourceFile.text, findChildOfKind(labeledStatement, SyntaxKind.ColonToken, sourceFile)!.end, /*stopAfterLineBreak*/ true); + : skipTrivia( + sourceFile.text, + findChildOfKind(labeledStatement, SyntaxKind.ColonToken, sourceFile)!.end, + /*stopAfterLineBreak*/ true, + ); changes.deleteRange(sourceFile, { pos, end }); } diff --git a/src/services/codefixes/generateAccessors.ts b/src/services/codefixes/generateAccessors.ts index fe4af3faca1c1..dc1f226d06c57 100644 --- a/src/services/codefixes/generateAccessors.ts +++ b/src/services/codefixes/generateAccessors.ts @@ -80,7 +80,14 @@ export interface AccessorInfo { } /** @internal */ -export function generateAccessorFromProperty(file: SourceFile, program: Program, start: number, end: number, context: textChanges.TextChangesContext, _actionName: string): FileTextChanges[] | undefined { +export function generateAccessorFromProperty( + file: SourceFile, + program: Program, + start: number, + end: number, + context: textChanges.TextChangesContext, + _actionName: string, +): FileTextChanges[] | undefined { const fieldInfo = getAccessorConvertiblePropertyAtPosition(file, program, start, end); if (!fieldInfo || refactor.isRefactorErrorInfo(fieldInfo)) return undefined; @@ -102,7 +109,9 @@ export function generateAccessorFromProperty(file: SourceFile, program: Program, fieldModifiers = modifiers; } else { - accessorModifiers = factory.createModifiersFromModifierFlags(prepareModifierFlagsForAccessor(modifierFlags)); + accessorModifiers = factory.createModifiersFromModifierFlags( + prepareModifierFlagsForAccessor(modifierFlags), + ); fieldModifiers = factory.createModifiersFromModifierFlags(prepareModifierFlagsForField(modifierFlags)); } if (canHaveDecorators(declaration)) { @@ -120,7 +129,13 @@ export function generateAccessorFromProperty(file: SourceFile, program: Program, // readonly modifier only existed in classLikeDeclaration const constructor = getFirstConstructorWithBody(container as ClassLikeDeclaration); if (constructor) { - updateReadonlyPropertyInitializerStatementConstructor(changeTracker, file, constructor, fieldName.text, originalName); + updateReadonlyPropertyInitializerStatementConstructor( + changeTracker, + file, + constructor, + fieldName.text, + originalName, + ); } } else { @@ -137,16 +152,22 @@ function isConvertibleName(name: DeclarationName): name is AcceptedNameType { } function isAcceptedDeclaration(node: Node): node is AcceptedDeclaration { - return isParameterPropertyDeclaration(node, node.parent) || isPropertyDeclaration(node) || isPropertyAssignment(node); + return isParameterPropertyDeclaration(node, node.parent) || isPropertyDeclaration(node) + || isPropertyAssignment(node); } function createPropertyName(name: string, originalName: AcceptedNameType) { return isIdentifier(originalName) ? factory.createIdentifier(name) : factory.createStringLiteral(name); } -function createAccessorAccessExpression(fieldName: AcceptedNameType, isStatic: boolean, container: ContainerDeclaration) { +function createAccessorAccessExpression( + fieldName: AcceptedNameType, + isStatic: boolean, + container: ContainerDeclaration, +) { const leftHead = isStatic ? (container as ClassLikeDeclaration).name! : factory.createThis(); // TODO: GH#18217 - return isIdentifier(fieldName) ? factory.createPropertyAccessExpression(leftHead, fieldName) : factory.createElementAccessExpression(leftHead, factory.createStringLiteralFromNode(fieldName)); + return isIdentifier(fieldName) ? factory.createPropertyAccessExpression(leftHead, fieldName) + : factory.createElementAccessExpression(leftHead, factory.createStringLiteralFromNode(fieldName)); } function prepareModifierFlagsForAccessor(modifierFlags: ModifierFlags): ModifierFlags { @@ -168,7 +189,13 @@ function prepareModifierFlagsForField(modifierFlags: ModifierFlags): ModifierFla } /** @internal */ -export function getAccessorConvertiblePropertyAtPosition(file: SourceFile, program: Program, start: number, end: number, considerEmptySpans = true): AccessorOrRefactorErrorInfo | undefined { +export function getAccessorConvertiblePropertyAtPosition( + file: SourceFile, + program: Program, + start: number, + end: number, + considerEmptySpans = true, +): AccessorOrRefactorErrorInfo | undefined { const node = getTokenAtPosition(file, start); const cursorRequest = start === end && considerEmptySpans; const declaration = findAncestor(node.parent, isAcceptedDeclaration); @@ -195,8 +222,14 @@ export function getAccessorConvertiblePropertyAtPosition(file: SourceFile, progr const name = declaration.name.text; const startWithUnderscore = startsWithUnderscore(name); - const fieldName = createPropertyName(startWithUnderscore ? name : getUniqueName(`_${name}`, file), declaration.name); - const accessorName = createPropertyName(startWithUnderscore ? getUniqueName(name.substring(1), file) : name, declaration.name); + const fieldName = createPropertyName( + startWithUnderscore ? name : getUniqueName(`_${name}`, file), + declaration.name, + ); + const accessorName = createPropertyName( + startWithUnderscore ? getUniqueName(name.substring(1), file) : name, + declaration.name, + ); return { isStatic: hasStaticModifier(declaration), isReadonly: hasEffectiveReadonlyModifier(declaration), @@ -210,7 +243,14 @@ export function getAccessorConvertiblePropertyAtPosition(file: SourceFile, progr }; } -function generateGetAccessor(fieldName: AcceptedNameType, accessorName: AcceptedNameType, type: TypeNode | undefined, modifiers: readonly ModifierLike[] | undefined, isStatic: boolean, container: ContainerDeclaration) { +function generateGetAccessor( + fieldName: AcceptedNameType, + accessorName: AcceptedNameType, + type: TypeNode | undefined, + modifiers: readonly ModifierLike[] | undefined, + isStatic: boolean, + container: ContainerDeclaration, +) { return factory.createGetAccessorDeclaration( modifiers, accessorName, @@ -224,7 +264,14 @@ function generateGetAccessor(fieldName: AcceptedNameType, accessorName: Accepted ); } -function generateSetAccessor(fieldName: AcceptedNameType, accessorName: AcceptedNameType, type: TypeNode | undefined, modifiers: readonly ModifierLike[] | undefined, isStatic: boolean, container: ContainerDeclaration) { +function generateSetAccessor( + fieldName: AcceptedNameType, + accessorName: AcceptedNameType, + type: TypeNode | undefined, + modifiers: readonly ModifierLike[] | undefined, + isStatic: boolean, + container: ContainerDeclaration, +) { return factory.createSetAccessorDeclaration( modifiers, accessorName, @@ -246,7 +293,14 @@ function generateSetAccessor(fieldName: AcceptedNameType, accessorName: Accepted ); } -function updatePropertyDeclaration(changeTracker: textChanges.ChangeTracker, file: SourceFile, declaration: PropertyDeclaration, type: TypeNode | undefined, fieldName: AcceptedNameType, modifiers: readonly ModifierLike[] | undefined) { +function updatePropertyDeclaration( + changeTracker: textChanges.ChangeTracker, + file: SourceFile, + declaration: PropertyDeclaration, + type: TypeNode | undefined, + fieldName: AcceptedNameType, + modifiers: readonly ModifierLike[] | undefined, +) { const property = factory.updatePropertyDeclaration( declaration, modifiers, @@ -258,7 +312,12 @@ function updatePropertyDeclaration(changeTracker: textChanges.ChangeTracker, fil changeTracker.replaceNode(file, declaration, property); } -function updatePropertyAssignmentDeclaration(changeTracker: textChanges.ChangeTracker, file: SourceFile, declaration: PropertyAssignment, fieldName: AcceptedNameType) { +function updatePropertyAssignmentDeclaration( + changeTracker: textChanges.ChangeTracker, + file: SourceFile, + declaration: PropertyAssignment, + fieldName: AcceptedNameType, +) { let assignment = factory.updatePropertyAssignment(declaration, fieldName, declaration.initializer); // Remove grammar errors from assignment if (assignment.modifiers || assignment.questionToken || assignment.exclamationToken) { @@ -270,7 +329,14 @@ function updatePropertyAssignmentDeclaration(changeTracker: textChanges.ChangeTr changeTracker.replacePropertyAssignment(file, declaration, assignment); } -function updateFieldDeclaration(changeTracker: textChanges.ChangeTracker, file: SourceFile, declaration: AcceptedDeclaration, type: TypeNode | undefined, fieldName: AcceptedNameType, modifiers: readonly ModifierLike[] | undefined) { +function updateFieldDeclaration( + changeTracker: textChanges.ChangeTracker, + file: SourceFile, + declaration: AcceptedDeclaration, + type: TypeNode | undefined, + fieldName: AcceptedNameType, + modifiers: readonly ModifierLike[] | undefined, +) { if (isPropertyDeclaration(declaration)) { updatePropertyDeclaration(changeTracker, file, declaration, type, fieldName, modifiers); } @@ -278,29 +344,57 @@ function updateFieldDeclaration(changeTracker: textChanges.ChangeTracker, file: updatePropertyAssignmentDeclaration(changeTracker, file, declaration, fieldName); } else { - changeTracker.replaceNode(file, declaration, factory.updateParameterDeclaration(declaration, modifiers, declaration.dotDotDotToken, cast(fieldName, isIdentifier), declaration.questionToken, declaration.type, declaration.initializer)); + changeTracker.replaceNode( + file, + declaration, + factory.updateParameterDeclaration( + declaration, + modifiers, + declaration.dotDotDotToken, + cast(fieldName, isIdentifier), + declaration.questionToken, + declaration.type, + declaration.initializer, + ), + ); } } -function insertAccessor(changeTracker: textChanges.ChangeTracker, file: SourceFile, accessor: AccessorDeclaration, declaration: AcceptedDeclaration, container: ContainerDeclaration) { - isParameterPropertyDeclaration(declaration, declaration.parent) ? changeTracker.insertMemberAtStart(file, container as ClassLikeDeclaration, accessor) : - isPropertyAssignment(declaration) ? changeTracker.insertNodeAfterComma(file, declaration, accessor) : - changeTracker.insertNodeAfter(file, declaration, accessor); +function insertAccessor( + changeTracker: textChanges.ChangeTracker, + file: SourceFile, + accessor: AccessorDeclaration, + declaration: AcceptedDeclaration, + container: ContainerDeclaration, +) { + isParameterPropertyDeclaration(declaration, declaration.parent) + ? changeTracker.insertMemberAtStart(file, container as ClassLikeDeclaration, accessor) + : isPropertyAssignment(declaration) ? changeTracker.insertNodeAfterComma(file, declaration, accessor) + : changeTracker.insertNodeAfter(file, declaration, accessor); } -function updateReadonlyPropertyInitializerStatementConstructor(changeTracker: textChanges.ChangeTracker, file: SourceFile, constructor: ConstructorDeclaration, fieldName: string, originalName: string) { +function updateReadonlyPropertyInitializerStatementConstructor( + changeTracker: textChanges.ChangeTracker, + file: SourceFile, + constructor: ConstructorDeclaration, + fieldName: string, + originalName: string, +) { if (!constructor.body) return; constructor.body.forEachChild(function recur(node) { if ( - isElementAccessExpression(node) && - node.expression.kind === SyntaxKind.ThisKeyword && - isStringLiteral(node.argumentExpression) && - node.argumentExpression.text === originalName && - isWriteAccess(node) + isElementAccessExpression(node) + && node.expression.kind === SyntaxKind.ThisKeyword + && isStringLiteral(node.argumentExpression) + && node.argumentExpression.text === originalName + && isWriteAccess(node) ) { changeTracker.replaceNode(file, node.argumentExpression, factory.createStringLiteral(fieldName)); } - if (isPropertyAccessExpression(node) && node.expression.kind === SyntaxKind.ThisKeyword && node.name.text === originalName && isWriteAccess(node)) { + if ( + isPropertyAccessExpression(node) && node.expression.kind === SyntaxKind.ThisKeyword + && node.name.text === originalName && isWriteAccess(node) + ) { changeTracker.replaceNode(file, node.name, factory.createIdentifier(fieldName)); } if (!isFunctionLike(node) && !isClassLike(node)) { diff --git a/src/services/codefixes/helpers.ts b/src/services/codefixes/helpers.ts index 804e87040f48b..659a2ce917999 100644 --- a/src/services/codefixes/helpers.ts +++ b/src/services/codefixes/helpers.ts @@ -137,7 +137,16 @@ export function createMissingMemberNodes( const classMembers = classDeclaration.symbol.members!; for (const symbol of possiblyMissingSymbols) { if (!classMembers.has(symbol.escapedName)) { - addNewNodeForMemberSymbol(symbol, classDeclaration, sourceFile, context, preferences, importAdder, addClassElement, /*body*/ undefined); + addNewNodeForMemberSymbol( + symbol, + classDeclaration, + sourceFile, + context, + preferences, + importAdder, + addClassElement, + /*body*/ undefined, + ); } } } @@ -157,7 +166,13 @@ export interface TypeConstructionContext { } /** @internal */ -export type AddNode = PropertyDeclaration | GetAccessorDeclaration | SetAccessorDeclaration | MethodDeclaration | FunctionExpression | ArrowFunction; +export type AddNode = + | PropertyDeclaration + | GetAccessorDeclaration + | SetAccessorDeclaration + | MethodDeclaration + | FunctionExpression + | ArrowFunction; /** @internal */ export const enum PreserveOptionalFlags { @@ -207,9 +222,9 @@ export function addNewNodeForMemberSymbol( const declarationName = createDeclarationName(symbol, declaration); const effectiveModifierFlags = declaration ? getEffectiveModifierFlags(declaration) : ModifierFlags.None; let modifierFlags = effectiveModifierFlags & ModifierFlags.Static; - modifierFlags |= effectiveModifierFlags & ModifierFlags.Public ? ModifierFlags.Public : - effectiveModifierFlags & ModifierFlags.Protected ? ModifierFlags.Protected : - ModifierFlags.None; + modifierFlags |= effectiveModifierFlags & ModifierFlags.Public ? ModifierFlags.Public + : effectiveModifierFlags & ModifierFlags.Protected ? ModifierFlags.Protected + : ModifierFlags.None; if (declaration && isAutoAccessorPropertyDeclaration(declaration)) { modifierFlags |= ModifierFlags.Accessor; } @@ -222,8 +237,14 @@ export function addNewNodeForMemberSymbol( switch (kind) { case SyntaxKind.PropertySignature: case SyntaxKind.PropertyDeclaration: - const flags = quotePreference === QuotePreference.Single ? NodeBuilderFlags.UseSingleQuotesForStringLiteralType : undefined; - let typeNode = checker.typeToTypeNode(type, enclosingDeclaration, flags, getNoopSymbolTrackerWithResolver(context)); + const flags = quotePreference === QuotePreference.Single + ? NodeBuilderFlags.UseSingleQuotesForStringLiteralType : undefined; + let typeNode = checker.typeToTypeNode( + type, + enclosingDeclaration, + flags, + getNoopSymbolTrackerWithResolver(context), + ); if (importAdder) { const importableReference = tryGetAutoImportableReferenceFromTypeNode(typeNode, scriptTarget); if (importableReference) { @@ -234,7 +255,8 @@ export function addNewNodeForMemberSymbol( addClassElement(factory.createPropertyDeclaration( modifiers, declaration ? createName(declarationName) : symbol.getName(), - optional && (preserveOptional & PreserveOptionalFlags.Property) ? factory.createToken(SyntaxKind.QuestionToken) : undefined, + optional && (preserveOptional & PreserveOptionalFlags.Property) + ? factory.createToken(SyntaxKind.QuestionToken) : undefined, typeNode, /*initializer*/ undefined, )); @@ -242,7 +264,12 @@ export function addNewNodeForMemberSymbol( case SyntaxKind.GetAccessor: case SyntaxKind.SetAccessor: { Debug.assertIsDefined(declarations); - let typeNode = checker.typeToTypeNode(type, enclosingDeclaration, /*flags*/ undefined, getNoopSymbolTrackerWithResolver(context)); + let typeNode = checker.typeToTypeNode( + type, + enclosingDeclaration, + /*flags*/ undefined, + getNoopSymbolTrackerWithResolver(context), + ); const allAccessors = getAllAccessorDeclarations(declarations, declaration as AccessorDeclaration); const orderedAccessors = allAccessors.secondAccessor ? [allAccessors.firstAccessor, allAccessors.secondAccessor] @@ -265,9 +292,14 @@ export function addNewNodeForMemberSymbol( )); } else { - Debug.assertNode(accessor, isSetAccessorDeclaration, "The counterpart to a getter should be a setter"); + Debug.assertNode( + accessor, + isSetAccessorDeclaration, + "The counterpart to a getter should be a setter", + ); const parameter = getSetAccessorValueParameter(accessor); - const parameterName = parameter && isIdentifier(parameter.name) ? idText(parameter.name) : undefined; + const parameterName = parameter && isIdentifier(parameter.name) ? idText(parameter.name) + : undefined; addClassElement(factory.createSetAccessorDeclaration( modifiers, createName(declarationName), @@ -288,7 +320,8 @@ export function addNewNodeForMemberSymbol( // (eg: an abstract method or interface declaration), there is a 1-1 // correspondence of declarations and signatures. Debug.assertIsDefined(declarations); - const signatures = type.isUnion() ? flatMap(type.types, t => t.getCallSignatures()) : type.getCallSignatures(); + const signatures = type.isUnion() ? flatMap(type.types, t => t.getCallSignatures()) + : type.getCallSignatures(); if (!some(signatures)) { break; } @@ -296,7 +329,13 @@ export function addNewNodeForMemberSymbol( if (declarations.length === 1) { Debug.assert(signatures.length === 1, "One declaration implies one signature"); const signature = signatures[0]; - outputMethod(quotePreference, signature, modifiers, createName(declarationName), createBody(body, quotePreference, ambient)); + outputMethod( + quotePreference, + signature, + modifiers, + createName(declarationName), + createBody(body, quotePreference, ambient), + ); break; } @@ -307,19 +346,59 @@ export function addNewNodeForMemberSymbol( if (!ambient) { if (declarations.length > signatures.length) { - const signature = checker.getSignatureFromDeclaration(declarations[declarations.length - 1] as SignatureDeclaration)!; - outputMethod(quotePreference, signature, modifiers, createName(declarationName), createBody(body, quotePreference)); + const signature = checker.getSignatureFromDeclaration( + declarations[declarations.length - 1] as SignatureDeclaration, + )!; + outputMethod( + quotePreference, + signature, + modifiers, + createName(declarationName), + createBody(body, quotePreference), + ); } else { - Debug.assert(declarations.length === signatures.length, "Declarations and signatures should match count"); - addClassElement(createMethodImplementingSignatures(checker, context, enclosingDeclaration, signatures, createName(declarationName), optional && !!(preserveOptional & PreserveOptionalFlags.Method), modifiers, quotePreference, body)); + Debug.assert( + declarations.length === signatures.length, + "Declarations and signatures should match count", + ); + addClassElement( + createMethodImplementingSignatures( + checker, + context, + enclosingDeclaration, + signatures, + createName(declarationName), + optional && !!(preserveOptional & PreserveOptionalFlags.Method), + modifiers, + quotePreference, + body, + ), + ); } } break; } - function outputMethod(quotePreference: QuotePreference, signature: Signature, modifiers: NodeArray | undefined, name: PropertyName, body?: Block): void { - const method = createSignatureDeclarationFromSignature(SyntaxKind.MethodDeclaration, context, quotePreference, signature, body, name, modifiers, optional && !!(preserveOptional & PreserveOptionalFlags.Method), enclosingDeclaration, importAdder) as MethodDeclaration; + function outputMethod( + quotePreference: QuotePreference, + signature: Signature, + modifiers: NodeArray | undefined, + name: PropertyName, + body?: Block, + ): void { + const method = createSignatureDeclarationFromSignature( + SyntaxKind.MethodDeclaration, + context, + quotePreference, + signature, + body, + name, + modifiers, + optional && !!(preserveOptional & PreserveOptionalFlags.Method), + enclosingDeclaration, + importAdder, + ) as MethodDeclaration; if (method) addClassElement(method); } @@ -338,19 +417,22 @@ export function addNewNodeForMemberSymbol( } function shouldAddOverrideKeyword(): boolean { - return !!(context.program.getCompilerOptions().noImplicitOverride && declaration && hasAbstractModifier(declaration)); + return !!(context.program.getCompilerOptions().noImplicitOverride && declaration + && hasAbstractModifier(declaration)); } function createName(node: PropertyName) { if (isIdentifier(node) && node.escapedText === "constructor") { - return factory.createComputedPropertyName(factory.createStringLiteral(idText(node), quotePreference === QuotePreference.Single)); + return factory.createComputedPropertyName( + factory.createStringLiteral(idText(node), quotePreference === QuotePreference.Single), + ); } return getSynthesizedDeepClone(node, /*includeTrivia*/ false); } function createBody(block: Block | undefined, quotePreference: QuotePreference, ambient?: boolean) { - return ambient ? undefined : - getSynthesizedDeepClone(block, /*includeTrivia*/ false) || createStubbedMethodBody(quotePreference); + return ambient ? undefined + : getSynthesizedDeepClone(block, /*includeTrivia*/ false) || createStubbedMethodBody(quotePreference); } function createTypeNode(typeNode: TypeNode | undefined) { @@ -392,8 +474,15 @@ export function createSignatureDeclarationFromSignature( const flags = NodeBuilderFlags.NoTruncation | NodeBuilderFlags.SuppressAnyReturnType | NodeBuilderFlags.AllowEmptyTuple - | (quotePreference === QuotePreference.Single ? NodeBuilderFlags.UseSingleQuotesForStringLiteralType : NodeBuilderFlags.None); - const signatureDeclaration = checker.signatureToSignatureDeclaration(signature, kind, enclosingDeclaration, flags, getNoopSymbolTrackerWithResolver(context)) as ArrowFunction | FunctionExpression | MethodDeclaration | FunctionDeclaration; + | (quotePreference === QuotePreference.Single ? NodeBuilderFlags.UseSingleQuotesForStringLiteralType + : NodeBuilderFlags.None); + const signatureDeclaration = checker.signatureToSignatureDeclaration( + signature, + kind, + enclosingDeclaration, + flags, + getNoopSymbolTrackerWithResolver(context), + ) as ArrowFunction | FunctionExpression | MethodDeclaration | FunctionDeclaration; if (!signatureDeclaration) { return undefined; } @@ -429,7 +518,10 @@ export function createSignatureDeclarationFromSignature( ); }); if (typeParameters !== newTypeParameters) { - typeParameters = setTextRange(factory.createNodeArray(newTypeParameters, typeParameters.hasTrailingComma), typeParameters); + typeParameters = setTextRange( + factory.createNodeArray(newTypeParameters, typeParameters.hasTrailingComma), + typeParameters, + ); } } const newParameters = sameMap(parameters, parameterDecl => { @@ -466,16 +558,52 @@ export function createSignatureDeclarationFromSignature( const questionToken = optional ? factory.createToken(SyntaxKind.QuestionToken) : undefined; const asteriskToken = signatureDeclaration.asteriskToken; if (isFunctionExpression(signatureDeclaration)) { - return factory.updateFunctionExpression(signatureDeclaration, modifiers, signatureDeclaration.asteriskToken, tryCast(name, isIdentifier), typeParameters, parameters, type, body ?? signatureDeclaration.body); + return factory.updateFunctionExpression( + signatureDeclaration, + modifiers, + signatureDeclaration.asteriskToken, + tryCast(name, isIdentifier), + typeParameters, + parameters, + type, + body ?? signatureDeclaration.body, + ); } if (isArrowFunction(signatureDeclaration)) { - return factory.updateArrowFunction(signatureDeclaration, modifiers, typeParameters, parameters, type, signatureDeclaration.equalsGreaterThanToken, body ?? signatureDeclaration.body); + return factory.updateArrowFunction( + signatureDeclaration, + modifiers, + typeParameters, + parameters, + type, + signatureDeclaration.equalsGreaterThanToken, + body ?? signatureDeclaration.body, + ); } if (isMethodDeclaration(signatureDeclaration)) { - return factory.updateMethodDeclaration(signatureDeclaration, modifiers, asteriskToken, name ?? factory.createIdentifier(""), questionToken, typeParameters, parameters, type, body); + return factory.updateMethodDeclaration( + signatureDeclaration, + modifiers, + asteriskToken, + name ?? factory.createIdentifier(""), + questionToken, + typeParameters, + parameters, + type, + body, + ); } if (isFunctionDeclaration(signatureDeclaration)) { - return factory.updateFunctionDeclaration(signatureDeclaration, modifiers, signatureDeclaration.asteriskToken, tryCast(name, isIdentifier), typeParameters, parameters, type, body ?? signatureDeclaration.body); + return factory.updateFunctionDeclaration( + signatureDeclaration, + modifiers, + signatureDeclaration.asteriskToken, + tryCast(name, isIdentifier), + typeParameters, + parameters, + type, + body ?? signatureDeclaration.body, + ); } return undefined; } @@ -498,7 +626,12 @@ export function createSignatureDeclarationFromCallExpression( const { typeArguments, arguments: args, parent } = call; const contextualType = isJs ? undefined : checker.getContextualType(call); - const names = map(args, arg => isIdentifier(arg) ? arg.text : isPropertyAccessExpression(arg) && isIdentifier(arg.name) ? arg.name.text : undefined); + const names = map( + args, + arg => + isIdentifier(arg) ? arg.text + : isPropertyAccessExpression(arg) && isIdentifier(arg.name) ? arg.name.text : undefined, + ); const instanceTypes = isJs ? [] : map(args, arg => checker.getTypeAtLocation(arg)); const { argumentTypeNodes, argumentTypeParameters } = getArgumentTypesAndTypeParameters( checker, @@ -516,8 +649,15 @@ export function createSignatureDeclarationFromCallExpression( const asteriskToken = isYieldExpression(parent) ? factory.createToken(SyntaxKind.AsteriskToken) : undefined; - const typeParameters = isJs ? undefined : createTypeParametersForArguments(checker, argumentTypeParameters, typeArguments); - const parameters = createDummyParameters(args.length, names, argumentTypeNodes, /*minArgumentCount*/ undefined, isJs); + const typeParameters = isJs ? undefined + : createTypeParametersForArguments(checker, argumentTypeParameters, typeArguments); + const parameters = createDummyParameters( + args.length, + names, + argumentTypeNodes, + /*minArgumentCount*/ undefined, + isJs, + ); const type = isJs || contextualType === undefined ? undefined : checker.typeToTypeNode(contextualType, contextNode, /*flags*/ undefined, tracker); @@ -565,12 +705,18 @@ export interface ArgumentTypeParameterAndConstraint { constraint?: TypeNode; } -function createTypeParametersForArguments(checker: TypeChecker, argumentTypeParameters: [string, ArgumentTypeParameterAndConstraint | undefined][], typeArguments: NodeArray | undefined) { +function createTypeParametersForArguments( + checker: TypeChecker, + argumentTypeParameters: [string, ArgumentTypeParameterAndConstraint | undefined][], + typeArguments: NodeArray | undefined, +) { const usedNames = new Set(argumentTypeParameters.map(pair => pair[0])); const constraintsByName = new Map(argumentTypeParameters); if (typeArguments) { - const typeArgumentsWithNewTypes = typeArguments.filter(typeArgument => !argumentTypeParameters.some(pair => checker.getTypeAtLocation(typeArgument) === pair[1]?.argumentType)); + const typeArgumentsWithNewTypes = typeArguments.filter(typeArgument => + !argumentTypeParameters.some(pair => checker.getTypeAtLocation(typeArgument) === pair[1]?.argumentType) + ); const targetSize = usedNames.size + typeArgumentsWithNewTypes.length; for (let i = 0; usedNames.size < targetSize; i += 1) { usedNames.add(createTypeParameterName(i)); @@ -579,7 +725,12 @@ function createTypeParametersForArguments(checker: TypeChecker, argumentTypePara return arrayFrom( usedNames.values(), - usedName => factory.createTypeParameterDeclaration(/*modifiers*/ undefined, usedName, constraintsByName.get(usedName)?.constraint), + usedName => + factory.createTypeParameterDeclaration( + /*modifiers*/ undefined, + usedName, + constraintsByName.get(usedName)?.constraint, + ), ); } @@ -590,7 +741,15 @@ function createTypeParameterName(index: number) { } /** @internal */ -export function typeToAutoImportableTypeNode(checker: TypeChecker, importAdder: ImportAdder, type: Type, contextNode: Node | undefined, scriptTarget: ScriptTarget, flags?: NodeBuilderFlags, tracker?: SymbolTracker): TypeNode | undefined { +export function typeToAutoImportableTypeNode( + checker: TypeChecker, + importAdder: ImportAdder, + type: Type, + contextNode: Node | undefined, + scriptTarget: ScriptTarget, + flags?: NodeBuilderFlags, + tracker?: SymbolTracker, +): TypeNode | undefined { let typeNode = checker.typeToTypeNode(type, contextNode, flags, tracker); if (typeNode && isImportTypeNode(typeNode)) { const importableReference = tryGetAutoImportableReferenceFromTypeNode(typeNode, scriptTarget); @@ -613,7 +772,15 @@ function typeContainsTypeParameter(type: Type) { } /** @internal */ -export function getArgumentTypesAndTypeParameters(checker: TypeChecker, importAdder: ImportAdder, instanceTypes: Type[], contextNode: Node | undefined, scriptTarget: ScriptTarget, flags?: NodeBuilderFlags, tracker?: SymbolTracker) { +export function getArgumentTypesAndTypeParameters( + checker: TypeChecker, + importAdder: ImportAdder, + instanceTypes: Type[], + contextNode: Node | undefined, + scriptTarget: ScriptTarget, + flags?: NodeBuilderFlags, + tracker?: SymbolTracker, +) { // Types to be used as the types of the parameters in the new function // E.g. from this source: // added("", 0) @@ -656,7 +823,15 @@ export function getArgumentTypesAndTypeParameters(checker: TypeChecker, importAd // Widen the type so we don't emit nonsense annotations like "function fn(x: 3) {" const widenedInstanceType = checker.getBaseTypeOfLiteralType(instanceType); - const argumentTypeNode = typeToAutoImportableTypeNode(checker, importAdder, widenedInstanceType, contextNode, scriptTarget, flags, tracker); + const argumentTypeNode = typeToAutoImportableTypeNode( + checker, + importAdder, + widenedInstanceType, + contextNode, + scriptTarget, + flags, + tracker, + ); if (!argumentTypeNode) { continue; } @@ -673,12 +848,24 @@ export function getArgumentTypesAndTypeParameters(checker: TypeChecker, importAd // function added(value: T) { ... } // We instead want to output: // function added(value: T) { ... } - const instanceTypeConstraint = instanceType.isTypeParameter() && instanceType.constraint && !isAnonymousObjectConstraintType(instanceType.constraint) - ? typeToAutoImportableTypeNode(checker, importAdder, instanceType.constraint, contextNode, scriptTarget, flags, tracker) + const instanceTypeConstraint = instanceType.isTypeParameter() && instanceType.constraint + && !isAnonymousObjectConstraintType(instanceType.constraint) + ? typeToAutoImportableTypeNode( + checker, + importAdder, + instanceType.constraint, + contextNode, + scriptTarget, + flags, + tracker, + ) : undefined; if (argumentTypeParameter) { - argumentTypeParameters.set(argumentTypeParameter, { argumentType: instanceType, constraint: instanceTypeConstraint }); + argumentTypeParameters.set(argumentTypeParameter, { + argumentType: instanceType, + constraint: instanceTypeConstraint, + }); } } @@ -704,7 +891,13 @@ function getFirstTypeParameterName(type: Type): string | undefined { : undefined; } -function createDummyParameters(argCount: number, names: (string | undefined)[] | undefined, types: (TypeNode | undefined)[] | undefined, minArgumentCount: number | undefined, inJs: boolean): ParameterDeclaration[] { +function createDummyParameters( + argCount: number, + names: (string | undefined)[] | undefined, + types: (TypeNode | undefined)[] | undefined, + minArgumentCount: number | undefined, + inJs: boolean, +): ParameterDeclaration[] { const parameters: ParameterDeclaration[] = []; const parameterNameCounts = new Map(); for (let i = 0; i < argCount; i++) { @@ -716,7 +909,8 @@ function createDummyParameters(argCount: number, names: (string | undefined)[] | /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, /*name*/ parameterName + (parameterNameCount || ""), - /*questionToken*/ minArgumentCount !== undefined && i >= minArgumentCount ? factory.createToken(SyntaxKind.QuestionToken) : undefined, + /*questionToken*/ minArgumentCount !== undefined && i >= minArgumentCount + ? factory.createToken(SyntaxKind.QuestionToken) : undefined, /*type*/ inJs ? undefined : types?.[i] || factory.createKeywordTypeNode(SyntaxKind.UnknownKeyword), /*initializer*/ undefined, ); @@ -748,20 +942,30 @@ function createMethodImplementingSignatures( if (signatureHasRestParameter(sig)) { someSigHasRestParameter = true; } - if (sig.parameters.length >= maxArgsSignature.parameters.length && (!signatureHasRestParameter(sig) || signatureHasRestParameter(maxArgsSignature))) { + if ( + sig.parameters.length >= maxArgsSignature.parameters.length + && (!signatureHasRestParameter(sig) || signatureHasRestParameter(maxArgsSignature)) + ) { maxArgsSignature = sig; } } const maxNonRestArgs = maxArgsSignature.parameters.length - (signatureHasRestParameter(maxArgsSignature) ? 1 : 0); const maxArgsParameterSymbolNames = maxArgsSignature.parameters.map(symbol => symbol.name); - const parameters = createDummyParameters(maxNonRestArgs, maxArgsParameterSymbolNames, /*types*/ undefined, minArgumentCount, /*inJs*/ false); + const parameters = createDummyParameters( + maxNonRestArgs, + maxArgsParameterSymbolNames, + /*types*/ undefined, + minArgumentCount, + /*inJs*/ false, + ); if (someSigHasRestParameter) { const restParameter = factory.createParameterDeclaration( /*modifiers*/ undefined, factory.createToken(SyntaxKind.DotDotDotToken), maxArgsParameterSymbolNames[maxNonRestArgs] || "rest", - /*questionToken*/ maxNonRestArgs >= minArgumentCount ? factory.createToken(SyntaxKind.QuestionToken) : undefined, + /*questionToken*/ maxNonRestArgs >= minArgumentCount ? factory.createToken(SyntaxKind.QuestionToken) + : undefined, factory.createArrayTypeNode(factory.createKeywordTypeNode(SyntaxKind.UnknownKeyword)), /*initializer*/ undefined, ); @@ -780,10 +984,20 @@ function createMethodImplementingSignatures( ); } -function getReturnTypeFromSignatures(signatures: readonly Signature[], checker: TypeChecker, context: TypeConstructionContext, enclosingDeclaration: ClassLikeDeclaration): TypeNode | undefined { +function getReturnTypeFromSignatures( + signatures: readonly Signature[], + checker: TypeChecker, + context: TypeConstructionContext, + enclosingDeclaration: ClassLikeDeclaration, +): TypeNode | undefined { if (length(signatures)) { const type = checker.getUnionType(map(signatures, checker.getReturnTypeOfSignature)); - return checker.typeToTypeNode(type, enclosingDeclaration, NodeBuilderFlags.NoTruncation, getNoopSymbolTrackerWithResolver(context)); + return checker.typeToTypeNode( + type, + enclosingDeclaration, + NodeBuilderFlags.NoTruncation, + getNoopSymbolTrackerWithResolver(context), + ); } } @@ -844,7 +1058,10 @@ export function setJsonCompilerOptionValues( tsconfigObjectLiteral, createJsonPropertyAssignment( "compilerOptions", - factory.createObjectLiteralExpression(options.map(([optionName, optionValue]) => createJsonPropertyAssignment(optionName, optionValue)), /*multiLine*/ true), + factory.createObjectLiteralExpression( + options.map(([optionName, optionValue]) => createJsonPropertyAssignment(optionName, optionValue)), + /*multiLine*/ true, + ), ), ); return; @@ -858,7 +1075,11 @@ export function setJsonCompilerOptionValues( for (const [optionName, optionValue] of options) { const optionProperty = findJsonProperty(compilerOptions, optionName); if (optionProperty === undefined) { - changeTracker.insertNodeAtObjectStart(configFile, compilerOptions, createJsonPropertyAssignment(optionName, optionValue)); + changeTracker.insertNodeAtObjectStart( + configFile, + compilerOptions, + createJsonPropertyAssignment(optionName, optionValue), + ); } else { changeTracker.replaceNode(configFile, optionProperty.initializer, optionValue); @@ -883,7 +1104,11 @@ export function createJsonPropertyAssignment(name: string, initializer: Expressi /** @internal */ export function findJsonProperty(obj: ObjectLiteralExpression, name: string): PropertyAssignment | undefined { - return find(obj.properties, (p): p is PropertyAssignment => isPropertyAssignment(p) && !!p.name && isStringLiteral(p.name) && p.name.text === name); + return find( + obj.properties, + (p): p is PropertyAssignment => + isPropertyAssignment(p) && !!p.name && isStringLiteral(p.name) && p.name.text === name, + ); } /** @@ -893,7 +1118,10 @@ export function findJsonProperty(obj: ObjectLiteralExpression, name: string): Pr * * @internal */ -export function tryGetAutoImportableReferenceFromTypeNode(importTypeNode: TypeNode | undefined, scriptTarget: ScriptTarget) { +export function tryGetAutoImportableReferenceFromTypeNode( + importTypeNode: TypeNode | undefined, + scriptTarget: ScriptTarget, +) { let symbols: Symbol[] | undefined; const typeNode = visitNode(importTypeNode, visit, isTypeNode); if (symbols && typeNode) { diff --git a/src/services/codefixes/importFixes.ts b/src/services/codefixes/importFixes.ts index 1b0bcd9145d65..3deb4c6232961 100644 --- a/src/services/codefixes/importFixes.ts +++ b/src/services/codefixes/importFixes.ts @@ -186,7 +186,14 @@ registerCodeFix({ fixIds: [importFixId], getAllCodeActions: context => { const { sourceFile, program, preferences, host, cancellationToken } = context; - const importAdder = createImportAdderWorker(sourceFile, program, /*useAutoImportProvider*/ true, preferences, host, cancellationToken); + const importAdder = createImportAdderWorker( + sourceFile, + program, + /*useAutoImportProvider*/ true, + preferences, + host, + cancellationToken, + ); eachDiagnostic(context, errorCodes, diag => importAdder.addImportFromDiagnostic(diag, context)); return createCombinedCodeActions(textChanges.ChangeTracker.with(context, importAdder.writeFixes)); }, @@ -205,8 +212,21 @@ export interface ImportAdder { } /** @internal */ -export function createImportAdder(sourceFile: SourceFile, program: Program, preferences: UserPreferences, host: LanguageServiceHost, cancellationToken?: CancellationToken): ImportAdder { - return createImportAdderWorker(sourceFile, program, /*useAutoImportProvider*/ false, preferences, host, cancellationToken); +export function createImportAdder( + sourceFile: SourceFile, + program: Program, + preferences: UserPreferences, + host: LanguageServiceHost, + cancellationToken?: CancellationToken, +): ImportAdder { + return createImportAdderWorker( + sourceFile, + program, + /*useAutoImportProvider*/ false, + preferences, + host, + cancellationToken, + ); } interface AddToExistingState { @@ -215,7 +235,14 @@ interface AddToExistingState { readonly namedImports: Map; } -function createImportAdderWorker(sourceFile: SourceFile, program: Program, useAutoImportProvider: boolean, preferences: UserPreferences, host: LanguageServiceHost, cancellationToken: CancellationToken | undefined): ImportAdder { +function createImportAdderWorker( + sourceFile: SourceFile, + program: Program, + useAutoImportProvider: boolean, + preferences: UserPreferences, + host: LanguageServiceHost, + cancellationToken: CancellationToken | undefined, +): ImportAdder { const compilerOptions = program.getCompilerOptions(); // Namespace fixes don't conflict, so just build a list. const addToNamespace: FixUseNamespaceImport[] = []; @@ -239,9 +266,28 @@ function createImportAdderWorker(sourceFile: SourceFile, program: Program, useAu const symbolName = getNameForExportedSymbol(exportedSymbol, getEmitScriptTarget(compilerOptions)); const checker = program.getTypeChecker(); const symbol = checker.getMergedSymbol(skipAlias(exportedSymbol, checker)); - const exportInfo = getAllExportInfoForSymbol(sourceFile, symbol, symbolName, moduleSymbol, /*preferCapitalized*/ false, program, host, preferences, cancellationToken); + const exportInfo = getAllExportInfoForSymbol( + sourceFile, + symbol, + symbolName, + moduleSymbol, + /*preferCapitalized*/ false, + program, + host, + preferences, + cancellationToken, + ); const useRequire = shouldUseRequire(sourceFile, program); - const fix = getImportFixForSymbol(sourceFile, Debug.checkDefined(exportInfo), program, /*position*/ undefined, !!isValidTypeOnlyUseSite, useRequire, host, preferences); + const fix = getImportFixForSymbol( + sourceFile, + Debug.checkDefined(exportInfo), + program, + /*position*/ undefined, + !!isValidTypeOnlyUseSite, + useRequire, + host, + preferences, + ); if (fix) { addImport({ fix, symbolName, errorIdentifierText: undefined }); } @@ -261,14 +307,20 @@ function createImportAdderWorker(sourceFile: SourceFile, program: Program, useAu const key = String(getNodeId(importClauseOrBindingPattern)); let entry = addToExisting.get(key); if (!entry) { - addToExisting.set(key, entry = { importClauseOrBindingPattern, defaultImport: undefined, namedImports: new Map() }); + addToExisting.set( + key, + entry = { importClauseOrBindingPattern, defaultImport: undefined, namedImports: new Map() }, + ); } if (importKind === ImportKind.Named) { const prevValue = entry?.namedImports.get(symbolName); entry.namedImports.set(symbolName, reduceAddAsTypeOnlyValues(prevValue, addAsTypeOnly)); } else { - Debug.assert(entry.defaultImport === undefined || entry.defaultImport.name === symbolName, "(Add to Existing) Default import should be missing or match symbolName"); + Debug.assert( + entry.defaultImport === undefined || entry.defaultImport.name === symbolName, + "(Add to Existing) Default import should be missing or match symbolName", + ); entry.defaultImport = { name: symbolName, addAsTypeOnly: reduceAddAsTypeOnlyValues(entry.defaultImport?.addAsTypeOnly, addAsTypeOnly), @@ -279,12 +331,21 @@ function createImportAdderWorker(sourceFile: SourceFile, program: Program, useAu case ImportFixKind.AddNew: { const { moduleSpecifier, importKind, useRequire, addAsTypeOnly } = fix; const entry = getNewImportEntry(moduleSpecifier, importKind, useRequire, addAsTypeOnly); - Debug.assert(entry.useRequire === useRequire, "(Add new) Tried to add an `import` and a `require` for the same module"); + Debug.assert( + entry.useRequire === useRequire, + "(Add new) Tried to add an `import` and a `require` for the same module", + ); switch (importKind) { case ImportKind.Default: - Debug.assert(entry.defaultImport === undefined || entry.defaultImport.name === symbolName, "(Add new) Default import should be missing or match symbolName"); - entry.defaultImport = { name: symbolName, addAsTypeOnly: reduceAddAsTypeOnlyValues(entry.defaultImport?.addAsTypeOnly, addAsTypeOnly) }; + Debug.assert( + entry.defaultImport === undefined || entry.defaultImport.name === symbolName, + "(Add new) Default import should be missing or match symbolName", + ); + entry.defaultImport = { + name: symbolName, + addAsTypeOnly: reduceAddAsTypeOnlyValues(entry.defaultImport?.addAsTypeOnly, addAsTypeOnly), + }; break; case ImportKind.Named: const prevValue = (entry.namedImports ||= new Map()).get(symbolName); @@ -292,7 +353,10 @@ function createImportAdderWorker(sourceFile: SourceFile, program: Program, useAu break; case ImportKind.CommonJS: case ImportKind.Namespace: - Debug.assert(entry.namespaceLikeImport === undefined || entry.namespaceLikeImport.name === symbolName, "Namespacelike import shoudl be missing or match symbolName"); + Debug.assert( + entry.namespaceLikeImport === undefined || entry.namespaceLikeImport.name === symbolName, + "Namespacelike import shoudl be missing or match symbolName", + ); entry.namespaceLikeImport = { importKind, name: symbolName, addAsTypeOnly }; break; } @@ -305,7 +369,10 @@ function createImportAdderWorker(sourceFile: SourceFile, program: Program, useAu Debug.assertNever(fix, `fix wasn't never - got kind ${(fix as ImportFix).kind}`); } - function reduceAddAsTypeOnlyValues(prevValue: AddAsTypeOnly | undefined, newValue: AddAsTypeOnly): AddAsTypeOnly { + function reduceAddAsTypeOnlyValues( + prevValue: AddAsTypeOnly | undefined, + newValue: AddAsTypeOnly, + ): AddAsTypeOnly { // `NotAllowed` overrides `Required` because one addition of a new import might be required to be type-only // because of `--importsNotUsedAsValues=error`, but if a second addition of the same import is `NotAllowed` // to be type-only, the reason the first one was `Required` - the unused runtime dependency - is now moot. @@ -315,7 +382,12 @@ function createImportAdderWorker(sourceFile: SourceFile, program: Program, useAu return Math.max(prevValue ?? 0, newValue); } - function getNewImportEntry(moduleSpecifier: string, importKind: ImportKind, useRequire: boolean, addAsTypeOnly: AddAsTypeOnly): Mutable { + function getNewImportEntry( + moduleSpecifier: string, + importKind: ImportKind, + useRequire: boolean, + addAsTypeOnly: AddAsTypeOnly, + ): Mutable { // A default import that requires type-only makes the whole import type-only. // (We could add `default` as a named import, but that style seems undesirable.) // Under `--preserveValueImports` and `--importsNotUsedAsValues=error`, if a @@ -417,7 +489,12 @@ export interface ImportSpecifierResolver { } /** @internal */ -export function createImportSpecifierResolver(importingFile: SourceFile, program: Program, host: LanguageServiceHost, preferences: UserPreferences): ImportSpecifierResolver { +export function createImportSpecifierResolver( + importingFile: SourceFile, + program: Program, + host: LanguageServiceHost, + preferences: UserPreferences, +): ImportSpecifierResolver { const packageJsonImportFilter = createPackageJsonImportFilter(importingFile, preferences, host); const importMap = createExistingImportMap(program.getTypeChecker(), importingFile, program.getCompilerOptions()); return { getModuleSpecifierForBestExportInfo }; @@ -462,8 +539,17 @@ const enum AddAsTypeOnly { Required = 1 << 1, NotAllowed = 1 << 2, } -type ImportFix = FixUseNamespaceImport | FixAddJsdocTypeImport | FixAddToExistingImport | FixAddNewImport | FixPromoteTypeOnlyImport; -type ImportFixWithModuleSpecifier = FixUseNamespaceImport | FixAddJsdocTypeImport | FixAddToExistingImport | FixAddNewImport; +type ImportFix = + | FixUseNamespaceImport + | FixAddJsdocTypeImport + | FixAddToExistingImport + | FixAddNewImport + | FixPromoteTypeOnlyImport; +type ImportFixWithModuleSpecifier = + | FixUseNamespaceImport + | FixAddJsdocTypeImport + | FixAddToExistingImport + | FixAddNewImport; // Properties are be undefined if fix is derived from an existing import interface ImportFixBase { @@ -531,20 +617,44 @@ export function getImportCompletionAction( if (exportMapKey) { // The new way: `exportMapKey` should be in the `data` of each auto-import completion entry and // sent back when asking for details. - exportInfos = getExportInfoMap(sourceFile, host, program, preferences, cancellationToken).get(sourceFile.path, exportMapKey); + exportInfos = getExportInfoMap(sourceFile, host, program, preferences, cancellationToken).get( + sourceFile.path, + exportMapKey, + ); Debug.assertIsDefined(exportInfos, "Some exportInfo should match the specified exportMapKey"); } else { // The old way, kept alive for super old editors that don't give us `data` back. exportInfos = pathIsBareSpecifier(stripQuotes(moduleSymbol.name)) ? [getSingleExportInfoForSymbol(targetSymbol, symbolName, moduleSymbol, program, host)] - : getAllExportInfoForSymbol(sourceFile, targetSymbol, symbolName, moduleSymbol, isJsxTagName, program, host, preferences, cancellationToken); + : getAllExportInfoForSymbol( + sourceFile, + targetSymbol, + symbolName, + moduleSymbol, + isJsxTagName, + program, + host, + preferences, + cancellationToken, + ); Debug.assertIsDefined(exportInfos, "Some exportInfo should match the specified symbol / moduleSymbol"); } const useRequire = shouldUseRequire(sourceFile, program); const isValidTypeOnlyUseSite = isValidTypeOnlyAliasUseSite(getTokenAtPosition(sourceFile, position)); - const fix = Debug.checkDefined(getImportFixForSymbol(sourceFile, exportInfos, program, position, isValidTypeOnlyUseSite, useRequire, host, preferences)); + const fix = Debug.checkDefined( + getImportFixForSymbol( + sourceFile, + exportInfos, + program, + position, + isValidTypeOnlyUseSite, + useRequire, + host, + preferences, + ), + ); return { moduleSpecifier: fix.moduleSpecifier, codeAction: codeFixActionToCodeAction(codeActionForFix( @@ -560,50 +670,130 @@ export function getImportCompletionAction( } /** @internal */ -export function getPromoteTypeOnlyCompletionAction(sourceFile: SourceFile, symbolToken: Identifier, program: Program, host: LanguageServiceHost, formatContext: formatting.FormatContext, preferences: UserPreferences) { +export function getPromoteTypeOnlyCompletionAction( + sourceFile: SourceFile, + symbolToken: Identifier, + program: Program, + host: LanguageServiceHost, + formatContext: formatting.FormatContext, + preferences: UserPreferences, +) { const compilerOptions = program.getCompilerOptions(); - const symbolName = single(getSymbolNamesToImport(sourceFile, program.getTypeChecker(), symbolToken, compilerOptions)); + const symbolName = single( + getSymbolNamesToImport(sourceFile, program.getTypeChecker(), symbolToken, compilerOptions), + ); const fix = getTypeOnlyPromotionFix(sourceFile, symbolToken, symbolName, program); const includeSymbolNameInDescription = symbolName !== symbolToken.text; - return fix && codeFixActionToCodeAction(codeActionForFix({ host, formatContext, preferences }, sourceFile, symbolName, fix, includeSymbolNameInDescription, compilerOptions, preferences)); + return fix + && codeFixActionToCodeAction( + codeActionForFix( + { host, formatContext, preferences }, + sourceFile, + symbolName, + fix, + includeSymbolNameInDescription, + compilerOptions, + preferences, + ), + ); } -function getImportFixForSymbol(sourceFile: SourceFile, exportInfos: readonly SymbolExportInfo[], program: Program, position: number | undefined, isValidTypeOnlyUseSite: boolean, useRequire: boolean, host: LanguageServiceHost, preferences: UserPreferences) { +function getImportFixForSymbol( + sourceFile: SourceFile, + exportInfos: readonly SymbolExportInfo[], + program: Program, + position: number | undefined, + isValidTypeOnlyUseSite: boolean, + useRequire: boolean, + host: LanguageServiceHost, + preferences: UserPreferences, +) { const packageJsonImportFilter = createPackageJsonImportFilter(sourceFile, preferences, host); - return getBestFix(getImportFixes(exportInfos, position, isValidTypeOnlyUseSite, useRequire, program, sourceFile, host, preferences).fixes, sourceFile, program, packageJsonImportFilter, host); + return getBestFix( + getImportFixes( + exportInfos, + position, + isValidTypeOnlyUseSite, + useRequire, + program, + sourceFile, + host, + preferences, + ).fixes, + sourceFile, + program, + packageJsonImportFilter, + host, + ); } function codeFixActionToCodeAction({ description, changes, commands }: CodeFixAction): CodeAction { return { description, changes, commands }; } -function getAllExportInfoForSymbol(importingFile: SourceFile, symbol: Symbol, symbolName: string, moduleSymbol: Symbol, preferCapitalized: boolean, program: Program, host: LanguageServiceHost, preferences: UserPreferences, cancellationToken: CancellationToken | undefined): readonly SymbolExportInfo[] | undefined { +function getAllExportInfoForSymbol( + importingFile: SourceFile, + symbol: Symbol, + symbolName: string, + moduleSymbol: Symbol, + preferCapitalized: boolean, + program: Program, + host: LanguageServiceHost, + preferences: UserPreferences, + cancellationToken: CancellationToken | undefined, +): readonly SymbolExportInfo[] | undefined { const getChecker = createGetChecker(program, host); return getExportInfoMap(importingFile, host, program, preferences, cancellationToken) .search(importingFile.path, preferCapitalized, name => name === symbolName, info => { - if (skipAlias(info[0].symbol, getChecker(info[0].isFromPackageJson)) === symbol && info.some(i => i.moduleSymbol === moduleSymbol || i.symbol.parent === moduleSymbol)) { + if ( + skipAlias(info[0].symbol, getChecker(info[0].isFromPackageJson)) === symbol + && info.some(i => i.moduleSymbol === moduleSymbol || i.symbol.parent === moduleSymbol) + ) { return info; } }); } -function getSingleExportInfoForSymbol(symbol: Symbol, symbolName: string, moduleSymbol: Symbol, program: Program, host: LanguageServiceHost): SymbolExportInfo { +function getSingleExportInfoForSymbol( + symbol: Symbol, + symbolName: string, + moduleSymbol: Symbol, + program: Program, + host: LanguageServiceHost, +): SymbolExportInfo { const compilerOptions = program.getCompilerOptions(); const mainProgramInfo = getInfoWithChecker(program.getTypeChecker(), /*isFromPackageJson*/ false); if (mainProgramInfo) { return mainProgramInfo; } const autoImportProvider = host.getPackageJsonAutoImportProvider?.()?.getTypeChecker(); - return Debug.checkDefined(autoImportProvider && getInfoWithChecker(autoImportProvider, /*isFromPackageJson*/ true), `Could not find symbol in specified module for code actions`); + return Debug.checkDefined( + autoImportProvider && getInfoWithChecker(autoImportProvider, /*isFromPackageJson*/ true), + `Could not find symbol in specified module for code actions`, + ); function getInfoWithChecker(checker: TypeChecker, isFromPackageJson: boolean): SymbolExportInfo | undefined { const defaultInfo = getDefaultLikeExportInfo(moduleSymbol, checker, compilerOptions); if (defaultInfo && skipAlias(defaultInfo.symbol, checker) === symbol) { - return { symbol: defaultInfo.symbol, moduleSymbol, moduleFileName: undefined, exportKind: defaultInfo.exportKind, targetFlags: skipAlias(symbol, checker).flags, isFromPackageJson }; + return { + symbol: defaultInfo.symbol, + moduleSymbol, + moduleFileName: undefined, + exportKind: defaultInfo.exportKind, + targetFlags: skipAlias(symbol, checker).flags, + isFromPackageJson, + }; } const named = checker.tryGetMemberInModuleExportsAndProperties(symbolName, moduleSymbol); if (named && skipAlias(named, checker) === symbol) { - return { symbol: named, moduleSymbol, moduleFileName: undefined, exportKind: ExportKind.Named, targetFlags: skipAlias(symbol, checker).flags, isFromPackageJson }; + return { + symbol: named, + moduleSymbol, + moduleFileName: undefined, + exportKind: ExportKind.Named, + targetFlags: skipAlias(symbol, checker).flags, + isFromPackageJson, + }; } } } @@ -623,7 +813,12 @@ function getImportFixes( const checker = program.getTypeChecker(); const existingImports = flatMap(exportInfos, importMap.getImportsForExportInfo); const useNamespace = usagePosition !== undefined && tryUseExistingNamespaceImport(existingImports, usagePosition); - const addToExisting = tryAddToExistingImport(existingImports, isValidTypeOnlyUseSite, checker, program.getCompilerOptions()); + const addToExisting = tryAddToExistingImport( + existingImports, + isValidTypeOnlyUseSite, + checker, + program.getCompilerOptions(), + ); if (addToExisting) { // Don't bother providing an action to add a new import if we can add to an existing one. return { @@ -650,7 +845,10 @@ function getImportFixes( }; } -function tryUseExistingNamespaceImport(existingImports: readonly FixAddToExistingImportInfo[], position: number): FixUseNamespaceImport | undefined { +function tryUseExistingNamespaceImport( + existingImports: readonly FixAddToExistingImportInfo[], + position: number, +): FixUseNamespaceImport | undefined { // It is possible that multiple import statements with the same specifier exist in the file. // e.g. // @@ -703,8 +901,8 @@ function getAddAsTypeOnly( return AddAsTypeOnly.Required; } if ( - importNameElisionDisabled(compilerOptions) && - (!(targetFlags & SymbolFlags.Value) || !!checker.getTypeOnlyAliasDeclaration(symbol)) + importNameElisionDisabled(compilerOptions) + && (!(targetFlags & SymbolFlags.Value) || !!checker.getTypeOnlyAliasDeclaration(symbol)) ) { // A type-only import is required for this symbol if under these settings if the symbol will // be erased, which will happen if the target symbol is purely a type or if it was exported/imported @@ -714,15 +912,20 @@ function getAddAsTypeOnly( return AddAsTypeOnly.Allowed; } -function tryAddToExistingImport(existingImports: readonly FixAddToExistingImportInfo[], isValidTypeOnlyUseSite: boolean, checker: TypeChecker, compilerOptions: CompilerOptions): FixAddToExistingImport | undefined { +function tryAddToExistingImport( + existingImports: readonly FixAddToExistingImportInfo[], + isValidTypeOnlyUseSite: boolean, + checker: TypeChecker, + compilerOptions: CompilerOptions, +): FixAddToExistingImport | undefined { let best: FixAddToExistingImport | undefined; for (const existingImport of existingImports) { const fix = getAddToExistingImportFix(existingImport); if (!fix) continue; const isTypeOnly = isTypeOnlyImportDeclaration(fix.importClauseOrBindingPattern); if ( - fix.addAsTypeOnly !== AddAsTypeOnly.NotAllowed && isTypeOnly || - fix.addAsTypeOnly === AddAsTypeOnly.NotAllowed && !isTypeOnly + fix.addAsTypeOnly !== AddAsTypeOnly.NotAllowed && isTypeOnly + || fix.addAsTypeOnly === AddAsTypeOnly.NotAllowed && !isTypeOnly ) { // Give preference to putting types in existing type-only imports and avoiding conversions // of import statements to/from type-only. @@ -732,15 +935,27 @@ function tryAddToExistingImport(existingImports: readonly FixAddToExistingImport } return best; - function getAddToExistingImportFix({ declaration, importKind, symbol, targetFlags }: FixAddToExistingImportInfo): FixAddToExistingImport | undefined { - if (importKind === ImportKind.CommonJS || importKind === ImportKind.Namespace || declaration.kind === SyntaxKind.ImportEqualsDeclaration) { + function getAddToExistingImportFix( + { declaration, importKind, symbol, targetFlags }: FixAddToExistingImportInfo, + ): FixAddToExistingImport | undefined { + if ( + importKind === ImportKind.CommonJS || importKind === ImportKind.Namespace + || declaration.kind === SyntaxKind.ImportEqualsDeclaration + ) { // These kinds of imports are not combinable with anything return undefined; } if (declaration.kind === SyntaxKind.VariableDeclaration) { - return (importKind === ImportKind.Named || importKind === ImportKind.Default) && declaration.name.kind === SyntaxKind.ObjectBindingPattern - ? { kind: ImportFixKind.AddToExisting, importClauseOrBindingPattern: declaration.name, importKind, moduleSpecifier: declaration.initializer.arguments[0].text, addAsTypeOnly: AddAsTypeOnly.NotAllowed } + return (importKind === ImportKind.Named || importKind === ImportKind.Default) + && declaration.name.kind === SyntaxKind.ObjectBindingPattern + ? { + kind: ImportFixKind.AddToExisting, + importClauseOrBindingPattern: declaration.name, + importKind, + moduleSpecifier: declaration.initializer.arguments[0].text, + addAsTypeOnly: AddAsTypeOnly.NotAllowed, + } : undefined; } @@ -758,19 +973,26 @@ function tryAddToExistingImport(existingImports: readonly FixAddToExistingImport // N.B. we don't have to figure out whether to use the main program checker // or the AutoImportProvider checker because we're adding to an existing import; the existence of // the import guarantees the symbol came from the main program. - const addAsTypeOnly = getAddAsTypeOnly(isValidTypeOnlyUseSite, /*isForNewImportDeclaration*/ false, symbol, targetFlags, checker, compilerOptions); + const addAsTypeOnly = getAddAsTypeOnly( + isValidTypeOnlyUseSite, + /*isForNewImportDeclaration*/ false, + symbol, + targetFlags, + checker, + compilerOptions, + ); if ( importKind === ImportKind.Default && ( - name || // Cannot add a default import to a declaration that already has one - addAsTypeOnly === AddAsTypeOnly.Required && namedBindings // Cannot add a default import as type-only if the import already has named bindings + name // Cannot add a default import to a declaration that already has one + || addAsTypeOnly === AddAsTypeOnly.Required && namedBindings // Cannot add a default import as type-only if the import already has named bindings ) ) { return undefined; } if ( - importKind === ImportKind.Named && - namedBindings?.kind === SyntaxKind.NamespaceImport // Cannot add a named import to a declaration that has a namespace import + importKind === ImportKind.Named + && namedBindings?.kind === SyntaxKind.NamespaceImport // Cannot add a named import to a declaration that has a namespace import ) { return undefined; } @@ -804,7 +1026,9 @@ function createExistingImportMap(checker: TypeChecker, importingFile: SourceFile } return { - getImportsForExportInfo: ({ moduleSymbol, exportKind, targetFlags, symbol }: SymbolExportInfo): readonly FixAddToExistingImportInfo[] => { + getImportsForExportInfo: ( + { moduleSymbol, exportKind, targetFlags, symbol }: SymbolExportInfo, + ): readonly FixAddToExistingImportInfo[] => { // Can't use an es6 import for a type in JS. if (!(targetFlags & SymbolFlags.Value) && isSourceFileJS(importingFile)) return emptyArray; const matchingDeclarations = importMap?.get(getSymbolId(moduleSymbol)); @@ -838,7 +1062,9 @@ function shouldUseRequire(sourceFile: SourceFile, program: Program): boolean { // 5. Match the first other JS file in the program that's unambiguously CJS or ESM for (const otherFile of program.getSourceFiles()) { - if (otherFile === sourceFile || !isSourceFileJS(otherFile) || program.isSourceFileFromExternalLibrary(otherFile)) continue; + if ( + otherFile === sourceFile || !isSourceFileJS(otherFile) || program.isSourceFileFromExternalLibrary(otherFile) + ) continue; if (otherFile.commonJsModuleIndicator && !otherFile.externalModuleIndicator) return true; if (otherFile.externalModuleIndicator && !otherFile.commonJsModuleIndicator) return false; } @@ -848,7 +1074,9 @@ function shouldUseRequire(sourceFile: SourceFile, program: Program): boolean { } function createGetChecker(program: Program, host: LanguageServiceHost) { - return memoizeOne((isFromPackageJson: boolean) => isFromPackageJson ? host.getPackageJsonAutoImportProvider!()!.getTypeChecker() : program.getTypeChecker()); + return memoizeOne((isFromPackageJson: boolean) => + isFromPackageJson ? host.getPackageJsonAutoImportProvider!()!.getTypeChecker() : program.getTypeChecker() + ); } function getNewImportFixes( @@ -869,15 +1097,38 @@ function getNewImportFixes( const moduleResolution = getEmitModuleResolutionKind(compilerOptions); const rejectNodeModulesRelativePaths = moduleResolutionUsesNodeModules(moduleResolution); const getModuleSpecifiers = fromCacheOnly - ? (moduleSymbol: Symbol) => ({ moduleSpecifiers: moduleSpecifiers.tryGetModuleSpecifiersFromCache(moduleSymbol, sourceFile, moduleSpecifierResolutionHost, preferences), computedWithoutCache: false }) - : (moduleSymbol: Symbol, checker: TypeChecker) => moduleSpecifiers.getModuleSpecifiersWithCacheInfo(moduleSymbol, checker, compilerOptions, sourceFile, moduleSpecifierResolutionHost, preferences); + ? (moduleSymbol: Symbol) => ({ + moduleSpecifiers: moduleSpecifiers.tryGetModuleSpecifiersFromCache( + moduleSymbol, + sourceFile, + moduleSpecifierResolutionHost, + preferences, + ), + computedWithoutCache: false, + }) + : (moduleSymbol: Symbol, checker: TypeChecker) => + moduleSpecifiers.getModuleSpecifiersWithCacheInfo( + moduleSymbol, + checker, + compilerOptions, + sourceFile, + moduleSpecifierResolutionHost, + preferences, + ); let computedWithoutCacheCount = 0; const fixes = flatMap(exportInfo, (exportInfo, i) => { const checker = getChecker(exportInfo.isFromPackageJson); const { computedWithoutCache, moduleSpecifiers } = getModuleSpecifiers(exportInfo.moduleSymbol, checker); const importedSymbolHasValueMeaning = !!(exportInfo.targetFlags & SymbolFlags.Value); - const addAsTypeOnly = getAddAsTypeOnly(isValidTypeOnlyUseSite, /*isForNewImportDeclaration*/ true, exportInfo.symbol, exportInfo.targetFlags, checker, compilerOptions); + const addAsTypeOnly = getAddAsTypeOnly( + isValidTypeOnlyUseSite, + /*isForNewImportDeclaration*/ true, + exportInfo.symbol, + exportInfo.targetFlags, + checker, + compilerOptions, + ); computedWithoutCacheCount += computedWithoutCache ? 1 : 0; return mapDefined(moduleSpecifiers, (moduleSpecifier): FixAddNewImport | FixAddJsdocTypeImport | undefined => { if (rejectNodeModulesRelativePaths && pathContainsNodeModules(moduleSpecifier)) { @@ -885,11 +1136,20 @@ function getNewImportFixes( } if (!importedSymbolHasValueMeaning && isJs && usagePosition !== undefined) { // `position` should only be undefined at a missing jsx namespace, in which case we shouldn't be looking for pure types. - return { kind: ImportFixKind.JsdocTypeImport, moduleSpecifier, usagePosition, exportInfo, isReExport: i > 0 }; + return { + kind: ImportFixKind.JsdocTypeImport, + moduleSpecifier, + usagePosition, + exportInfo, + isReExport: i > 0, + }; } const importKind = getImportKind(sourceFile, exportInfo.exportKind, compilerOptions); let qualification: Qualification | undefined; - if (usagePosition !== undefined && importKind === ImportKind.CommonJS && exportInfo.exportKind === ExportKind.Named) { + if ( + usagePosition !== undefined && importKind === ImportKind.CommonJS + && exportInfo.exportKind === ExportKind.Named + ) { // Compiler options are restricting our import options to a require, but we need to access // a named export or property of the exporting module. We need to import the entire module // and insert a property access, e.g. `writeFile` becomes @@ -936,8 +1196,29 @@ function getFixesForAddImport( preferences: UserPreferences, fromCacheOnly?: boolean, ): { computedWithoutCacheCount?: number; fixes: readonly (FixAddNewImport | FixAddJsdocTypeImport)[]; } { - const existingDeclaration = firstDefined(existingImports, info => newImportInfoFromExistingSpecifier(info, isValidTypeOnlyUseSite, useRequire, program.getTypeChecker(), program.getCompilerOptions())); - return existingDeclaration ? { fixes: [existingDeclaration] } : getNewImportFixes(program, sourceFile, usagePosition, isValidTypeOnlyUseSite, useRequire, exportInfos, host, preferences, fromCacheOnly); + const existingDeclaration = firstDefined( + existingImports, + info => + newImportInfoFromExistingSpecifier( + info, + isValidTypeOnlyUseSite, + useRequire, + program.getTypeChecker(), + program.getCompilerOptions(), + ), + ); + return existingDeclaration ? { fixes: [existingDeclaration] } + : getNewImportFixes( + program, + sourceFile, + usagePosition, + isValidTypeOnlyUseSite, + useRequire, + exportInfos, + host, + preferences, + fromCacheOnly, + ); } function newImportInfoFromExistingSpecifier( @@ -951,7 +1232,14 @@ function newImportInfoFromExistingSpecifier( if (moduleSpecifier) { const addAsTypeOnly = useRequire ? AddAsTypeOnly.NotAllowed - : getAddAsTypeOnly(isValidTypeOnlyUseSite, /*isForNewImportDeclaration*/ true, symbol, targetFlags, checker, compilerOptions); + : getAddAsTypeOnly( + isValidTypeOnlyUseSite, + /*isForNewImportDeclaration*/ true, + symbol, + targetFlags, + checker, + compilerOptions, + ); return { kind: ImportFixKind.AddNew, moduleSpecifier, importKind, addAsTypeOnly, useRequire }; } } @@ -962,17 +1250,33 @@ interface FixInfo { readonly errorIdentifierText: string | undefined; readonly isJsxNamespaceFix?: boolean; } -function getFixInfos(context: CodeFixContextBase, errorCode: number, pos: number, useAutoImportProvider: boolean): readonly FixInfo[] | undefined { +function getFixInfos( + context: CodeFixContextBase, + errorCode: number, + pos: number, + useAutoImportProvider: boolean, +): readonly FixInfo[] | undefined { const symbolToken = getTokenAtPosition(context.sourceFile, pos); let info; - if (errorCode === Diagnostics._0_refers_to_a_UMD_global_but_the_current_file_is_a_module_Consider_adding_an_import_instead.code) { + if ( + errorCode + === Diagnostics._0_refers_to_a_UMD_global_but_the_current_file_is_a_module_Consider_adding_an_import_instead + .code + ) { info = getFixesInfoForUMDImport(context, symbolToken); } else if (!isIdentifier(symbolToken)) { return undefined; } else if (errorCode === Diagnostics._0_cannot_be_used_as_a_value_because_it_was_imported_using_import_type.code) { - const symbolName = single(getSymbolNamesToImport(context.sourceFile, context.program.getTypeChecker(), symbolToken, context.program.getCompilerOptions())); + const symbolName = single( + getSymbolNamesToImport( + context.sourceFile, + context.program.getTypeChecker(), + symbolToken, + context.program.getCompilerOptions(), + ), + ); const fix = getTypeOnlyPromotionFix(context.sourceFile, symbolToken, symbolName, context.program); return fix && [{ fix, symbolName, errorIdentifierText: symbolToken.text }]; } @@ -980,19 +1284,42 @@ function getFixInfos(context: CodeFixContextBase, errorCode: number, pos: number info = getFixesInfoForNonUMDImport(context, symbolToken, useAutoImportProvider); } - const packageJsonImportFilter = createPackageJsonImportFilter(context.sourceFile, context.preferences, context.host); + const packageJsonImportFilter = createPackageJsonImportFilter( + context.sourceFile, + context.preferences, + context.host, + ); return info && sortFixInfo(info, context.sourceFile, context.program, packageJsonImportFilter, context.host); } -function sortFixInfo(fixes: readonly (FixInfo & { fix: ImportFixWithModuleSpecifier; })[], sourceFile: SourceFile, program: Program, packageJsonImportFilter: PackageJsonImportFilter, host: LanguageServiceHost): readonly (FixInfo & { fix: ImportFixWithModuleSpecifier; })[] { +function sortFixInfo( + fixes: readonly (FixInfo & { fix: ImportFixWithModuleSpecifier; })[], + sourceFile: SourceFile, + program: Program, + packageJsonImportFilter: PackageJsonImportFilter, + host: LanguageServiceHost, +): readonly (FixInfo & { fix: ImportFixWithModuleSpecifier; })[] { const _toPath = (fileName: string) => toPath(fileName, host.getCurrentDirectory(), hostGetCanonicalFileName(host)); return sort(fixes, (a, b) => - compareBooleans(!!a.isJsxNamespaceFix, !!b.isJsxNamespaceFix) || - compareValues(a.fix.kind, b.fix.kind) || - compareModuleSpecifiers(a.fix, b.fix, sourceFile, program, packageJsonImportFilter.allowsImportingSpecifier, _toPath)); + compareBooleans(!!a.isJsxNamespaceFix, !!b.isJsxNamespaceFix) + || compareValues(a.fix.kind, b.fix.kind) + || compareModuleSpecifiers( + a.fix, + b.fix, + sourceFile, + program, + packageJsonImportFilter.allowsImportingSpecifier, + _toPath, + )); } -function getBestFix(fixes: readonly ImportFixWithModuleSpecifier[], sourceFile: SourceFile, program: Program, packageJsonImportFilter: PackageJsonImportFilter, host: LanguageServiceHost): ImportFixWithModuleSpecifier | undefined { +function getBestFix( + fixes: readonly ImportFixWithModuleSpecifier[], + sourceFile: SourceFile, + program: Program, + packageJsonImportFilter: PackageJsonImportFilter, + host: LanguageServiceHost, +): ImportFixWithModuleSpecifier | undefined { if (!some(fixes)) return; // These will always be placed first if available, and are better than other kinds if (fixes[0].kind === ImportFixKind.UseNamespace || fixes[0].kind === ImportFixKind.AddToExisting) { @@ -1038,12 +1365,17 @@ function compareModuleSpecifiers( // This can produce false positives or negatives if re-exports cross into sibling directories // (e.g. `export * from "../whatever"`) or are not named "index" (we don't even try to consider // this if we're in a resolution mode where you can't drop trailing "/index" from paths). -function isFixPossiblyReExportingImportingFile(fix: ImportFixWithModuleSpecifier, importingFile: SourceFile, compilerOptions: CompilerOptions, toPath: (fileName: string) => Path): boolean { +function isFixPossiblyReExportingImportingFile( + fix: ImportFixWithModuleSpecifier, + importingFile: SourceFile, + compilerOptions: CompilerOptions, + toPath: (fileName: string) => Path, +): boolean { if ( - fix.isReExport && - fix.exportInfo?.moduleFileName && - getEmitModuleResolutionKind(compilerOptions) === ModuleResolutionKind.Node10 && - isIndexFileName(fix.exportInfo.moduleFileName) + fix.isReExport + && fix.exportInfo?.moduleFileName + && getEmitModuleResolutionKind(compilerOptions) === ModuleResolutionKind.Node10 + && isIndexFileName(fix.exportInfo.moduleFileName) ) { const reExportDir = toPath(getDirectoryPath(fix.exportInfo.moduleFileName)); return startsWith(importingFile.path, reExportDir); @@ -1055,19 +1387,38 @@ function isIndexFileName(fileName: string) { return getBaseFileName(fileName, [".js", ".jsx", ".d.ts", ".ts", ".tsx"], /*ignoreCase*/ true) === "index"; } -function compareNodeCoreModuleSpecifiers(a: string, b: string, importingFile: SourceFile, program: Program): Comparison { - if (startsWith(a, "node:") && !startsWith(b, "node:")) return shouldUseUriStyleNodeCoreModules(importingFile, program) ? Comparison.LessThan : Comparison.GreaterThan; - if (startsWith(b, "node:") && !startsWith(a, "node:")) return shouldUseUriStyleNodeCoreModules(importingFile, program) ? Comparison.GreaterThan : Comparison.LessThan; +function compareNodeCoreModuleSpecifiers( + a: string, + b: string, + importingFile: SourceFile, + program: Program, +): Comparison { + if (startsWith(a, "node:") && !startsWith(b, "node:")) { + return shouldUseUriStyleNodeCoreModules(importingFile, program) ? Comparison.LessThan : Comparison.GreaterThan; + } + if (startsWith(b, "node:") && !startsWith(a, "node:")) { + return shouldUseUriStyleNodeCoreModules(importingFile, program) ? Comparison.GreaterThan : Comparison.LessThan; + } return Comparison.EqualTo; } -function getFixesInfoForUMDImport({ sourceFile, program, host, preferences }: CodeFixContextBase, token: Node): (FixInfo & { fix: ImportFixWithModuleSpecifier; })[] | undefined { +function getFixesInfoForUMDImport( + { sourceFile, program, host, preferences }: CodeFixContextBase, + token: Node, +): (FixInfo & { fix: ImportFixWithModuleSpecifier; })[] | undefined { const checker = program.getTypeChecker(); const umdSymbol = getUmdSymbol(token, checker); if (!umdSymbol) return undefined; const symbol = checker.getAliasedSymbol(umdSymbol); const symbolName = umdSymbol.name; - const exportInfo: readonly SymbolExportInfo[] = [{ symbol: umdSymbol, moduleSymbol: symbol, moduleFileName: undefined, exportKind: ExportKind.UMD, targetFlags: symbol.flags, isFromPackageJson: false }]; + const exportInfo: readonly SymbolExportInfo[] = [{ + symbol: umdSymbol, + moduleSymbol: symbol, + moduleFileName: undefined, + exportKind: ExportKind.UMD, + targetFlags: symbol.flags, + isFromPackageJson: false, + }]; const useRequire = shouldUseRequire(sourceFile, program); // `usagePosition` is undefined because `token` may not actually be a usage of the symbol we're importing. // For example, we might need to import `React` in order to use an arbitrary JSX tag. We could send a position @@ -1075,7 +1426,16 @@ function getFixesInfoForUMDImport({ sourceFile, program, host, preferences }: Co // before a named import, like converting `writeFile` to `fs.writeFile` (whether `fs` is already imported or // not), and this function will only be called for UMD symbols, which are necessarily an `export =`, not a // named export. - const fixes = getImportFixes(exportInfo, /*usagePosition*/ undefined, /*isValidTypeOnlyUseSite*/ false, useRequire, program, sourceFile, host, preferences).fixes; + const fixes = getImportFixes( + exportInfo, + /*usagePosition*/ undefined, + /*isValidTypeOnlyUseSite*/ false, + useRequire, + program, + sourceFile, + host, + preferences, + ).fixes; return fixes.map(fix => ({ fix, symbolName, errorIdentifierText: tryCast(token, isIdentifier)?.text })); } function getUmdSymbol(token: Node, checker: TypeChecker): Symbol | undefined { @@ -1086,7 +1446,12 @@ function getUmdSymbol(token: Node, checker: TypeChecker): Symbol | undefined { // The error wasn't for the symbolAtLocation, it was for the JSX tag itself, which needs access to e.g. `React`. const { parent } = token; if ((isJsxOpeningLikeElement(parent) && parent.tagName === token) || isJsxOpeningFragment(parent)) { - const parentSymbol = checker.resolveName(checker.getJsxNamespace(parent), isJsxOpeningLikeElement(parent) ? token : parent, SymbolFlags.Value, /*excludeGlobals*/ false); + const parentSymbol = checker.resolveName( + checker.getJsxNamespace(parent), + isJsxOpeningLikeElement(parent) ? token : parent, + SymbolFlags.Value, + /*excludeGlobals*/ false, + ); if (isUMDExportSymbol(parentSymbol)) { return parentSymbol; } @@ -1100,8 +1465,17 @@ function getUmdSymbol(token: Node, checker: TypeChecker): Symbol | undefined { * * @internal */ -export function getImportKind(importingFile: SourceFile, exportKind: ExportKind, compilerOptions: CompilerOptions, forceImportKeyword?: boolean): ImportKind { - if (compilerOptions.verbatimModuleSyntax && (getEmitModuleKind(compilerOptions) === ModuleKind.CommonJS || importingFile.impliedNodeFormat === ModuleKind.CommonJS)) { +export function getImportKind( + importingFile: SourceFile, + exportKind: ExportKind, + compilerOptions: CompilerOptions, + forceImportKeyword?: boolean, +): ImportKind { + if ( + compilerOptions.verbatimModuleSyntax + && (getEmitModuleKind(compilerOptions) === ModuleKind.CommonJS + || importingFile.impliedNodeFormat === ModuleKind.CommonJS) + ) { // TODO: if the exporting file is ESM under nodenext, or `forceImport` is given in a JS file, this is impossible return ImportKind.CommonJS; } @@ -1119,7 +1493,11 @@ export function getImportKind(importingFile: SourceFile, exportKind: ExportKind, } } -function getUmdImportKind(importingFile: SourceFile, compilerOptions: CompilerOptions, forceImportKeyword: boolean): ImportKind { +function getUmdImportKind( + importingFile: SourceFile, + compilerOptions: CompilerOptions, + forceImportKeyword: boolean, +): ImportKind { // Import a synthetic `default` if enabled. if (getAllowSyntheticDefaultImports(compilerOptions)) { return ImportKind.Default; @@ -1132,7 +1510,8 @@ function getUmdImportKind(importingFile: SourceFile, compilerOptions: CompilerOp case ModuleKind.CommonJS: case ModuleKind.UMD: if (isInJSFile(importingFile)) { - return isExternalModule(importingFile) || forceImportKeyword ? ImportKind.Namespace : ImportKind.CommonJS; + return isExternalModule(importingFile) || forceImportKeyword ? ImportKind.Namespace + : ImportKind.CommonJS; } return ImportKind.CommonJS; case ModuleKind.System: @@ -1151,7 +1530,11 @@ function getUmdImportKind(importingFile: SourceFile, compilerOptions: CompilerOp } } -function getFixesInfoForNonUMDImport({ sourceFile, program, cancellationToken, host, preferences }: CodeFixContextBase, symbolToken: Identifier, useAutoImportProvider: boolean): readonly (FixInfo & { fix: ImportFixWithModuleSpecifier; })[] | undefined { +function getFixesInfoForNonUMDImport( + { sourceFile, program, cancellationToken, host, preferences }: CodeFixContextBase, + symbolToken: Identifier, + useAutoImportProvider: boolean, +): readonly (FixInfo & { fix: ImportFixWithModuleSpecifier; })[] | undefined { const checker = program.getTypeChecker(); const compilerOptions = program.getCompilerOptions(); return flatMap(getSymbolNamesToImport(sourceFile, checker, symbolToken, compilerOptions), symbolName => { @@ -1161,15 +1544,48 @@ function getFixesInfoForNonUMDImport({ sourceFile, program, cancellationToken, h } const isValidTypeOnlyUseSite = isValidTypeOnlyAliasUseSite(symbolToken); const useRequire = shouldUseRequire(sourceFile, program); - const exportInfo = getExportInfos(symbolName, isJSXTagName(symbolToken), getMeaningFromLocation(symbolToken), cancellationToken, sourceFile, program, useAutoImportProvider, host, preferences); + const exportInfo = getExportInfos( + symbolName, + isJSXTagName(symbolToken), + getMeaningFromLocation(symbolToken), + cancellationToken, + sourceFile, + program, + useAutoImportProvider, + host, + preferences, + ); return arrayFrom( - flatMapIterator(exportInfo.values(), exportInfos => getImportFixes(exportInfos, symbolToken.getStart(sourceFile), isValidTypeOnlyUseSite, useRequire, program, sourceFile, host, preferences).fixes), - fix => ({ fix, symbolName, errorIdentifierText: symbolToken.text, isJsxNamespaceFix: symbolName !== symbolToken.text }), + flatMapIterator( + exportInfo.values(), + exportInfos => + getImportFixes( + exportInfos, + symbolToken.getStart(sourceFile), + isValidTypeOnlyUseSite, + useRequire, + program, + sourceFile, + host, + preferences, + ).fixes, + ), + fix => ({ + fix, + symbolName, + errorIdentifierText: symbolToken.text, + isJsxNamespaceFix: symbolName !== symbolToken.text, + }), ); }); } -function getTypeOnlyPromotionFix(sourceFile: SourceFile, symbolToken: Identifier, symbolName: string, program: Program): FixPromoteTypeOnlyImport | undefined { +function getTypeOnlyPromotionFix( + sourceFile: SourceFile, + symbolToken: Identifier, + symbolName: string, + program: Program, +): FixPromoteTypeOnlyImport | undefined { const checker = program.getTypeChecker(); const symbol = checker.resolveName(symbolName, symbolToken, SymbolFlags.Value, /*excludeGlobals*/ true); if (!symbol) return undefined; @@ -1180,12 +1596,21 @@ function getTypeOnlyPromotionFix(sourceFile: SourceFile, symbolToken: Identifier return { kind: ImportFixKind.PromoteTypeOnly, typeOnlyAliasDeclaration }; } -function getSymbolNamesToImport(sourceFile: SourceFile, checker: TypeChecker, symbolToken: Identifier, compilerOptions: CompilerOptions): string[] { +function getSymbolNamesToImport( + sourceFile: SourceFile, + checker: TypeChecker, + symbolToken: Identifier, + compilerOptions: CompilerOptions, +): string[] { const parent = symbolToken.parent; - if ((isJsxOpeningLikeElement(parent) || isJsxClosingElement(parent)) && parent.tagName === symbolToken && jsxModeNeedsExplicitImport(compilerOptions.jsx)) { + if ( + (isJsxOpeningLikeElement(parent) || isJsxClosingElement(parent)) && parent.tagName === symbolToken + && jsxModeNeedsExplicitImport(compilerOptions.jsx) + ) { const jsxNamespace = checker.getJsxNamespace(sourceFile); if (needsJsxNamespaceFix(jsxNamespace, symbolToken, checker)) { - const needsComponentNameFix = !isIntrinsicJsxName(symbolToken.text) && !checker.resolveName(symbolToken.text, symbolToken, SymbolFlags.Value, /*excludeGlobals*/ false); + const needsComponentNameFix = !isIntrinsicJsxName(symbolToken.text) + && !checker.resolveName(symbolToken.text, symbolToken, SymbolFlags.Value, /*excludeGlobals*/ false); return needsComponentNameFix ? [symbolToken.text, jsxNamespace] : [jsxNamespace]; } } @@ -1195,7 +1620,9 @@ function getSymbolNamesToImport(sourceFile: SourceFile, checker: TypeChecker, sy function needsJsxNamespaceFix(jsxNamespace: string, symbolToken: Identifier, checker: TypeChecker) { if (isIntrinsicJsxName(symbolToken.text)) return true; // If we were triggered by a matching error code on an intrinsic, the error must have been about missing the JSX factory const namespaceSymbol = checker.resolveName(jsxNamespace, symbolToken, SymbolFlags.Value, /*excludeGlobals*/ true); - return !namespaceSymbol || some(namespaceSymbol.declarations, isTypeOnlyImportOrExportDeclaration) && !(namespaceSymbol.flags & SymbolFlags.Value); + return !namespaceSymbol + || some(namespaceSymbol.declarations, isTypeOnlyImportOrExportDeclaration) + && !(namespaceSymbol.flags & SymbolFlags.Value); } // Returns a map from an exported symbol's ID to a list of every way it's (re-)exported. @@ -1216,38 +1643,97 @@ function getExportInfos( const packageJsonFilter = createPackageJsonImportFilter(fromFile, preferences, host); const moduleSpecifierCache = host.getModuleSpecifierCache?.(); const getModuleSpecifierResolutionHost = memoizeOne((isFromPackageJson: boolean) => { - return createModuleSpecifierResolutionHost(isFromPackageJson ? host.getPackageJsonAutoImportProvider!()! : program, host); + return createModuleSpecifierResolutionHost( + isFromPackageJson ? host.getPackageJsonAutoImportProvider!()! : program, + host, + ); }); - function addSymbol(moduleSymbol: Symbol, toFile: SourceFile | undefined, exportedSymbol: Symbol, exportKind: ExportKind, program: Program, isFromPackageJson: boolean): void { + function addSymbol( + moduleSymbol: Symbol, + toFile: SourceFile | undefined, + exportedSymbol: Symbol, + exportKind: ExportKind, + program: Program, + isFromPackageJson: boolean, + ): void { const moduleSpecifierResolutionHost = getModuleSpecifierResolutionHost(isFromPackageJson); if ( - toFile && isImportableFile(program, fromFile, toFile, preferences, packageJsonFilter, moduleSpecifierResolutionHost, moduleSpecifierCache) || - !toFile && packageJsonFilter.allowsImportingAmbientModule(moduleSymbol, moduleSpecifierResolutionHost) + toFile + && isImportableFile( + program, + fromFile, + toFile, + preferences, + packageJsonFilter, + moduleSpecifierResolutionHost, + moduleSpecifierCache, + ) + || !toFile && packageJsonFilter.allowsImportingAmbientModule(moduleSymbol, moduleSpecifierResolutionHost) ) { const checker = program.getTypeChecker(); - originalSymbolToExportInfos.add(getUniqueSymbolId(exportedSymbol, checker).toString(), { symbol: exportedSymbol, moduleSymbol, moduleFileName: toFile?.fileName, exportKind, targetFlags: skipAlias(exportedSymbol, checker).flags, isFromPackageJson }); + originalSymbolToExportInfos.add(getUniqueSymbolId(exportedSymbol, checker).toString(), { + symbol: exportedSymbol, + moduleSymbol, + moduleFileName: toFile?.fileName, + exportKind, + targetFlags: skipAlias(exportedSymbol, checker).flags, + isFromPackageJson, + }); } } - forEachExternalModuleToImportFrom(program, host, preferences, useAutoImportProvider, (moduleSymbol, sourceFile, program, isFromPackageJson) => { - const checker = program.getTypeChecker(); - cancellationToken.throwIfCancellationRequested(); - - const compilerOptions = program.getCompilerOptions(); - const defaultInfo = getDefaultLikeExportInfo(moduleSymbol, checker, compilerOptions); - if (defaultInfo && (defaultInfo.name === symbolName || moduleSymbolToValidIdentifier(moduleSymbol, getEmitScriptTarget(compilerOptions), isJsxTagName) === symbolName) && symbolHasMeaning(defaultInfo.resolvedSymbol, currentTokenMeaning)) { - addSymbol(moduleSymbol, sourceFile, defaultInfo.symbol, defaultInfo.exportKind, program, isFromPackageJson); - } + forEachExternalModuleToImportFrom( + program, + host, + preferences, + useAutoImportProvider, + (moduleSymbol, sourceFile, program, isFromPackageJson) => { + const checker = program.getTypeChecker(); + cancellationToken.throwIfCancellationRequested(); + + const compilerOptions = program.getCompilerOptions(); + const defaultInfo = getDefaultLikeExportInfo(moduleSymbol, checker, compilerOptions); + if ( + defaultInfo + && (defaultInfo.name === symbolName + || moduleSymbolToValidIdentifier(moduleSymbol, getEmitScriptTarget(compilerOptions), isJsxTagName) + === symbolName) + && symbolHasMeaning(defaultInfo.resolvedSymbol, currentTokenMeaning) + ) { + addSymbol( + moduleSymbol, + sourceFile, + defaultInfo.symbol, + defaultInfo.exportKind, + program, + isFromPackageJson, + ); + } - // check exports with the same name - const exportSymbolWithIdenticalName = checker.tryGetMemberInModuleExportsAndProperties(symbolName, moduleSymbol); - if (exportSymbolWithIdenticalName && symbolHasMeaning(exportSymbolWithIdenticalName, currentTokenMeaning)) { - addSymbol(moduleSymbol, sourceFile, exportSymbolWithIdenticalName, ExportKind.Named, program, isFromPackageJson); - } - }); + // check exports with the same name + const exportSymbolWithIdenticalName = checker.tryGetMemberInModuleExportsAndProperties( + symbolName, + moduleSymbol, + ); + if (exportSymbolWithIdenticalName && symbolHasMeaning(exportSymbolWithIdenticalName, currentTokenMeaning)) { + addSymbol( + moduleSymbol, + sourceFile, + exportSymbolWithIdenticalName, + ExportKind.Named, + program, + isFromPackageJson, + ); + } + }, + ); return originalSymbolToExportInfos; } -function getExportEqualsImportKind(importingFile: SourceFile, compilerOptions: CompilerOptions, forceImportKeyword: boolean): ImportKind { +function getExportEqualsImportKind( + importingFile: SourceFile, + compilerOptions: CompilerOptions, + forceImportKeyword: boolean, +): ImportKind { const allowSyntheticDefaults = getAllowSyntheticDefaultImports(compilerOptions); const isJS = isInJSFile(importingFile); // 1. 'import =' will not work in es2015+ TS files, so the decision is between a default @@ -1276,14 +1762,38 @@ function getExportEqualsImportKind(importingFile: SourceFile, compilerOptions: C return allowSyntheticDefaults ? ImportKind.Default : ImportKind.CommonJS; } -function codeActionForFix(context: textChanges.TextChangesContext, sourceFile: SourceFile, symbolName: string, fix: ImportFix, includeSymbolNameInDescription: boolean, compilerOptions: CompilerOptions, preferences: UserPreferences): CodeFixAction { +function codeActionForFix( + context: textChanges.TextChangesContext, + sourceFile: SourceFile, + symbolName: string, + fix: ImportFix, + includeSymbolNameInDescription: boolean, + compilerOptions: CompilerOptions, + preferences: UserPreferences, +): CodeFixAction { let diag!: DiagnosticOrDiagnosticAndArguments; const changes = textChanges.ChangeTracker.with(context, tracker => { - diag = codeActionForFixWorker(tracker, sourceFile, symbolName, fix, includeSymbolNameInDescription, compilerOptions, preferences); + diag = codeActionForFixWorker( + tracker, + sourceFile, + symbolName, + fix, + includeSymbolNameInDescription, + compilerOptions, + preferences, + ); }); return createCodeFixAction(importFixName, changes, diag, importFixId, Diagnostics.Add_all_missing_imports); } -function codeActionForFixWorker(changes: textChanges.ChangeTracker, sourceFile: SourceFile, symbolName: string, fix: ImportFix, includeSymbolNameInDescription: boolean, compilerOptions: CompilerOptions, preferences: UserPreferences): DiagnosticOrDiagnosticAndArguments { +function codeActionForFixWorker( + changes: textChanges.ChangeTracker, + sourceFile: SourceFile, + symbolName: string, + fix: ImportFix, + includeSymbolNameInDescription: boolean, + compilerOptions: CompilerOptions, + preferences: UserPreferences, +): DiagnosticOrDiagnosticAndArguments { const quotePreference = getQuotePreference(sourceFile, preferences); switch (fix.kind) { case ImportFixKind.UseNamespace: @@ -1291,7 +1801,11 @@ function codeActionForFixWorker(changes: textChanges.ChangeTracker, sourceFile: return [Diagnostics.Change_0_to_1, symbolName, `${fix.namespacePrefix}.${symbolName}`]; case ImportFixKind.JsdocTypeImport: addImportType(changes, sourceFile, fix, quotePreference); - return [Diagnostics.Change_0_to_1, symbolName, getImportTypePrefix(fix.moduleSpecifier, quotePreference) + symbolName]; + return [ + Diagnostics.Change_0_to_1, + symbolName, + getImportTypePrefix(fix.moduleSpecifier, quotePreference) + symbolName, + ]; case ImportFixKind.AddToExisting: { const { importClauseOrBindingPattern, importKind, addAsTypeOnly, moduleSpecifier } = fix; doAddExistingFix( @@ -1310,8 +1824,10 @@ function codeActionForFixWorker(changes: textChanges.ChangeTracker, sourceFile: case ImportFixKind.AddNew: { const { importKind, moduleSpecifier, addAsTypeOnly, useRequire, qualification } = fix; const getDeclarations = useRequire ? getNewRequires : getNewImports; - const defaultImport: Import | undefined = importKind === ImportKind.Default ? { name: symbolName, addAsTypeOnly } : undefined; - const namedImports: Import[] | undefined = importKind === ImportKind.Named ? [{ name: symbolName, addAsTypeOnly }] : undefined; + const defaultImport: Import | undefined = importKind === ImportKind.Default + ? { name: symbolName, addAsTypeOnly } : undefined; + const namedImports: Import[] | undefined = importKind === ImportKind.Named + ? [{ name: symbolName, addAsTypeOnly }] : undefined; const namespaceLikeImport = importKind === ImportKind.Namespace || importKind === ImportKind.CommonJS ? { importKind, name: qualification?.namespacePrefix || symbolName, addAsTypeOnly } : undefined; @@ -1338,9 +1854,19 @@ function codeActionForFixWorker(changes: textChanges.ChangeTracker, sourceFile: } case ImportFixKind.PromoteTypeOnly: { const { typeOnlyAliasDeclaration } = fix; - const promotedDeclaration = promoteFromTypeOnly(changes, typeOnlyAliasDeclaration, compilerOptions, sourceFile, preferences); + const promotedDeclaration = promoteFromTypeOnly( + changes, + typeOnlyAliasDeclaration, + compilerOptions, + sourceFile, + preferences, + ); return promotedDeclaration.kind === SyntaxKind.ImportSpecifier - ? [Diagnostics.Remove_type_from_import_of_0_from_1, symbolName, getModuleSpecifierText(promotedDeclaration.parent.parent)] + ? [ + Diagnostics.Remove_type_from_import_of_0_from_1, + symbolName, + getModuleSpecifierText(promotedDeclaration.parent.parent), + ] : [Diagnostics.Remove_type_from_import_declaration_from_0, getModuleSpecifierText(promotedDeclaration)]; } default: @@ -1350,23 +1876,52 @@ function codeActionForFixWorker(changes: textChanges.ChangeTracker, sourceFile: function getModuleSpecifierText(promotedDeclaration: ImportClause | ImportEqualsDeclaration): string { return promotedDeclaration.kind === SyntaxKind.ImportEqualsDeclaration - ? tryCast(tryCast(promotedDeclaration.moduleReference, isExternalModuleReference)?.expression, isStringLiteralLike)?.text || promotedDeclaration.moduleReference.getText() + ? tryCast( + tryCast(promotedDeclaration.moduleReference, isExternalModuleReference)?.expression, + isStringLiteralLike, + )?.text || promotedDeclaration.moduleReference.getText() : cast(promotedDeclaration.parent.moduleSpecifier, isStringLiteral).text; } -function promoteFromTypeOnly(changes: textChanges.ChangeTracker, aliasDeclaration: TypeOnlyAliasDeclaration, compilerOptions: CompilerOptions, sourceFile: SourceFile, preferences: UserPreferences) { +function promoteFromTypeOnly( + changes: textChanges.ChangeTracker, + aliasDeclaration: TypeOnlyAliasDeclaration, + compilerOptions: CompilerOptions, + sourceFile: SourceFile, + preferences: UserPreferences, +) { // See comment in `doAddExistingFix` on constant with the same name. const convertExistingToTypeOnly = importNameElisionDisabled(compilerOptions); switch (aliasDeclaration.kind) { case SyntaxKind.ImportSpecifier: if (aliasDeclaration.isTypeOnly) { - const sortKind = OrganizeImports.detectImportSpecifierSorting(aliasDeclaration.parent.elements, preferences); + const sortKind = OrganizeImports.detectImportSpecifierSorting( + aliasDeclaration.parent.elements, + preferences, + ); if (aliasDeclaration.parent.elements.length > 1 && sortKind) { changes.delete(sourceFile, aliasDeclaration); - const newSpecifier = factory.updateImportSpecifier(aliasDeclaration, /*isTypeOnly*/ false, aliasDeclaration.propertyName, aliasDeclaration.name); - const comparer = OrganizeImports.getOrganizeImportsComparer(preferences, sortKind === SortKind.CaseInsensitive); - const insertionIndex = OrganizeImports.getImportSpecifierInsertionIndex(aliasDeclaration.parent.elements, newSpecifier, comparer); - changes.insertImportSpecifierAtIndex(sourceFile, newSpecifier, aliasDeclaration.parent, insertionIndex); + const newSpecifier = factory.updateImportSpecifier( + aliasDeclaration, + /*isTypeOnly*/ false, + aliasDeclaration.propertyName, + aliasDeclaration.name, + ); + const comparer = OrganizeImports.getOrganizeImportsComparer( + preferences, + sortKind === SortKind.CaseInsensitive, + ); + const insertionIndex = OrganizeImports.getImportSpecifierInsertionIndex( + aliasDeclaration.parent.elements, + newSpecifier, + comparer, + ); + changes.insertImportSpecifierAtIndex( + sourceFile, + newSpecifier, + aliasDeclaration.parent, + insertionIndex, + ); } else { changes.deleteRange(sourceFile, aliasDeclaration.getFirstToken()!); @@ -1396,9 +1951,17 @@ function promoteFromTypeOnly(changes: textChanges.ChangeTracker, aliasDeclaratio // Change .ts extension to .js if necessary if (!compilerOptions.allowImportingTsExtensions) { const moduleSpecifier = tryGetModuleSpecifierFromDeclaration(importClause.parent); - const resolvedModule = moduleSpecifier && getResolvedModule(sourceFile, moduleSpecifier.text, getModeForUsageLocation(sourceFile, moduleSpecifier)); + const resolvedModule = moduleSpecifier + && getResolvedModule( + sourceFile, + moduleSpecifier.text, + getModeForUsageLocation(sourceFile, moduleSpecifier), + ); if (resolvedModule?.resolvedUsingTsExtension) { - const changedExtension = changeAnyExtension(moduleSpecifier!.text, getOutputExtension(moduleSpecifier!.text, compilerOptions)); + const changedExtension = changeAnyExtension( + moduleSpecifier!.text, + getOutputExtension(moduleSpecifier!.text, compilerOptions), + ); changes.replaceNode(sourceFile, moduleSpecifier!, factory.createStringLiteral(changedExtension)); } } @@ -1406,9 +1969,9 @@ function promoteFromTypeOnly(changes: textChanges.ChangeTracker, aliasDeclaratio const namedImports = tryCast(importClause.namedBindings, isNamedImports); if (namedImports && namedImports.elements.length > 1) { if ( - OrganizeImports.detectImportSpecifierSorting(namedImports.elements, preferences) && - aliasDeclaration.kind === SyntaxKind.ImportSpecifier && - namedImports.elements.indexOf(aliasDeclaration) !== 0 + OrganizeImports.detectImportSpecifierSorting(namedImports.elements, preferences) + && aliasDeclaration.kind === SyntaxKind.ImportSpecifier + && namedImports.elements.indexOf(aliasDeclaration) !== 0 ) { // The import specifier being promoted will be the only non-type-only, // import in the NamedImports, so it should be moved to the front. @@ -1443,12 +2006,15 @@ function doAddExistingFix( return; } - const promoteFromTypeOnly = clause.isTypeOnly && some([defaultImport, ...namedImports], i => i?.addAsTypeOnly === AddAsTypeOnly.NotAllowed); + const promoteFromTypeOnly = clause.isTypeOnly + && some([defaultImport, ...namedImports], i => i?.addAsTypeOnly === AddAsTypeOnly.NotAllowed); const existingSpecifiers = clause.namedBindings && tryCast(clause.namedBindings, isNamedImports)?.elements; if (defaultImport) { Debug.assert(!clause.name, "Cannot add a default import to an import clause that already has one"); - changes.insertNodeAt(sourceFile, clause.getStart(sourceFile), factory.createIdentifier(defaultImport.name), { suffix: ", " }); + changes.insertNodeAt(sourceFile, clause.getStart(sourceFile), factory.createIdentifier(defaultImport.name), { + suffix: ", ", + }); } if (namedImports.length) { @@ -1487,7 +2053,8 @@ function doAddExistingFix( // nonsense. So if there are existing specifiers, even if we know the sorting preference, we // need to ensure that the existing specifiers are sorted according to the preference in order // to do a sorted insertion. - const specifierSort = existingSpecifiers?.length && OrganizeImports.detectImportSpecifierSorting(existingSpecifiers, preferences); + const specifierSort = existingSpecifiers?.length + && OrganizeImports.detectImportSpecifierSorting(existingSpecifiers, preferences); if (specifierSort && !(ignoreCaseForSorting && specifierSort === SortKind.CaseSensitive)) { for (const spec of newSpecifiers) { // Organize imports puts type-only import specifiers last, so if we're @@ -1496,7 +2063,12 @@ function doAddExistingFix( const insertionIndex = promoteFromTypeOnly && !spec.isTypeOnly ? 0 : OrganizeImports.getImportSpecifierInsertionIndex(existingSpecifiers, spec, comparer); - changes.insertImportSpecifierAtIndex(sourceFile, spec, clause.namedBindings as NamedImports, insertionIndex); + changes.insertImportSpecifierAtIndex( + sourceFile, + spec, + clause.namedBindings as NamedImports, + insertionIndex, + ); } } else if (existingSpecifiers?.length) { @@ -1511,7 +2083,14 @@ function doAddExistingFix( changes.replaceNode(sourceFile, clause.namedBindings, namedImports); } else { - changes.insertNodeAfter(sourceFile, Debug.checkDefined(clause.name, "Import clause must have either named imports or a default import"), namedImports); + changes.insertNodeAfter( + sourceFile, + Debug.checkDefined( + clause.name, + "Import clause must have either named imports or a default import", + ), + namedImports, + ); } } } @@ -1530,7 +2109,11 @@ function doAddExistingFix( } } - function addElementToBindingPattern(bindingPattern: ObjectBindingPattern, name: string, propertyName: string | undefined) { + function addElementToBindingPattern( + bindingPattern: ObjectBindingPattern, + name: string, + propertyName: string | undefined, + ) { const element = factory.createBindingElement(/*dotDotDotToken*/ undefined, propertyName, name); if (bindingPattern.elements.length) { changes.insertNodeInListAfter(sourceFile, last(bindingPattern.elements), element); @@ -1541,11 +2124,20 @@ function doAddExistingFix( } } -function addNamespaceQualifier(changes: textChanges.ChangeTracker, sourceFile: SourceFile, { namespacePrefix, usagePosition }: Qualification): void { +function addNamespaceQualifier( + changes: textChanges.ChangeTracker, + sourceFile: SourceFile, + { namespacePrefix, usagePosition }: Qualification, +): void { changes.insertText(sourceFile, usagePosition, namespacePrefix + "."); } -function addImportType(changes: textChanges.ChangeTracker, sourceFile: SourceFile, { moduleSpecifier, usagePosition: position }: FixAddJsdocTypeImport, quotePreference: QuotePreference): void { +function addImportType( + changes: textChanges.ChangeTracker, + sourceFile: SourceFile, + { moduleSpecifier, usagePosition: position }: FixAddJsdocTypeImport, + quotePreference: QuotePreference, +): void { changes.insertText(sourceFile, position, getImportTypePrefix(moduleSpecifier, quotePreference)); } @@ -1586,10 +2178,10 @@ function getNewImports( if (defaultImport !== undefined || namedImports?.length) { // `verbatimModuleSyntax` should prefer top-level `import type` - // even though it's not an error, it would add unnecessary runtime emit. - const topLevelTypeOnly = (!defaultImport || needsTypeOnly(defaultImport)) && every(namedImports, needsTypeOnly) || - compilerOptions.verbatimModuleSyntax && - defaultImport?.addAsTypeOnly !== AddAsTypeOnly.NotAllowed && - !some(namedImports, i => i.addAsTypeOnly === AddAsTypeOnly.NotAllowed); + const topLevelTypeOnly = (!defaultImport || needsTypeOnly(defaultImport)) && every(namedImports, needsTypeOnly) + || compilerOptions.verbatimModuleSyntax + && defaultImport?.addAsTypeOnly !== AddAsTypeOnly.NotAllowed + && !some(namedImports, i => i.addAsTypeOnly === AddAsTypeOnly.NotAllowed); statements = combine( statements, makeImport( @@ -1631,16 +2223,29 @@ function getNewImports( return Debug.checkDefined(statements); } -function getNewRequires(moduleSpecifier: string, quotePreference: QuotePreference, defaultImport: Import | undefined, namedImports: readonly Import[] | undefined, namespaceLikeImport: Import | undefined): RequireVariableStatement | readonly RequireVariableStatement[] { +function getNewRequires( + moduleSpecifier: string, + quotePreference: QuotePreference, + defaultImport: Import | undefined, + namedImports: readonly Import[] | undefined, + namespaceLikeImport: Import | undefined, +): RequireVariableStatement | readonly RequireVariableStatement[] { const quotedModuleSpecifier = makeStringLiteral(moduleSpecifier, quotePreference); let statements: RequireVariableStatement | readonly RequireVariableStatement[] | undefined; // const { default: foo, bar, etc } = require('./mod'); if (defaultImport || namedImports?.length) { - const bindingElements = namedImports?.map(({ name }) => factory.createBindingElement(/*dotDotDotToken*/ undefined, /*propertyName*/ undefined, name)) || []; + const bindingElements = namedImports?.map(({ name }) => + factory.createBindingElement(/*dotDotDotToken*/ undefined, /*propertyName*/ undefined, name) + ) || []; if (defaultImport) { - bindingElements.unshift(factory.createBindingElement(/*dotDotDotToken*/ undefined, "default", defaultImport.name)); + bindingElements.unshift( + factory.createBindingElement(/*dotDotDotToken*/ undefined, "default", defaultImport.name), + ); } - const declaration = createConstEqualsRequireDeclaration(factory.createObjectBindingPattern(bindingElements), quotedModuleSpecifier); + const declaration = createConstEqualsRequireDeclaration( + factory.createObjectBindingPattern(bindingElements), + quotedModuleSpecifier, + ); statements = combine(statements, declaration); } // const foo = require('./mod'); @@ -1651,7 +2256,10 @@ function getNewRequires(moduleSpecifier: string, quotePreference: QuotePreferenc return Debug.checkDefined(statements); } -function createConstEqualsRequireDeclaration(name: string | ObjectBindingPattern, quotedModuleSpecifier: StringLiteral): RequireVariableStatement { +function createConstEqualsRequireDeclaration( + name: string | ObjectBindingPattern, + quotedModuleSpecifier: StringLiteral, +): RequireVariableStatement { return factory.createVariableStatement( /*modifiers*/ undefined, factory.createVariableDeclarationList([ @@ -1659,7 +2267,9 @@ function createConstEqualsRequireDeclaration(name: string | ObjectBindingPattern typeof name === "string" ? factory.createIdentifier(name) : name, /*exclamationToken*/ undefined, /*type*/ undefined, - factory.createCallExpression(factory.createIdentifier("require"), /*typeArguments*/ undefined, [quotedModuleSpecifier]), + factory.createCallExpression(factory.createIdentifier("require"), /*typeArguments*/ undefined, [ + quotedModuleSpecifier, + ]), ), ], NodeFlags.Const), ) as RequireVariableStatement; @@ -1670,12 +2280,24 @@ function symbolHasMeaning({ declarations }: Symbol, meaning: SemanticMeaning): b } /** @internal */ -export function moduleSymbolToValidIdentifier(moduleSymbol: Symbol, target: ScriptTarget | undefined, forceCapitalize: boolean): string { - return moduleSpecifierToValidIdentifier(removeFileExtension(stripQuotes(moduleSymbol.name)), target, forceCapitalize); +export function moduleSymbolToValidIdentifier( + moduleSymbol: Symbol, + target: ScriptTarget | undefined, + forceCapitalize: boolean, +): string { + return moduleSpecifierToValidIdentifier( + removeFileExtension(stripQuotes(moduleSymbol.name)), + target, + forceCapitalize, + ); } /** @internal */ -export function moduleSpecifierToValidIdentifier(moduleSpecifier: string, target: ScriptTarget | undefined, forceCapitalize?: boolean): string { +export function moduleSpecifierToValidIdentifier( + moduleSpecifier: string, + target: ScriptTarget | undefined, + forceCapitalize?: boolean, +): string { const baseName = getBaseFileName(removeSuffix(moduleSpecifier, "/index")); let res = ""; let lastCharWasValid = true; diff --git a/src/services/codefixes/inferFromUsage.ts b/src/services/codefixes/inferFromUsage.ts index 95a19e1d39638..41e335a2e532f 100644 --- a/src/services/codefixes/inferFromUsage.ts +++ b/src/services/codefixes/inferFromUsage.ts @@ -145,11 +145,13 @@ const errorCodes = [ Diagnostics.Rest_parameter_0_implicitly_has_an_any_type_but_a_better_type_may_be_inferred_from_usage.code, // Get Accessor declarations - Diagnostics.Property_0_implicitly_has_type_any_but_a_better_type_for_its_get_accessor_may_be_inferred_from_usage.code, + Diagnostics.Property_0_implicitly_has_type_any_but_a_better_type_for_its_get_accessor_may_be_inferred_from_usage + .code, Diagnostics._0_implicitly_has_an_1_return_type_but_a_better_type_may_be_inferred_from_usage.code, // Set Accessor declarations - Diagnostics.Property_0_implicitly_has_type_any_but_a_better_type_for_its_set_accessor_may_be_inferred_from_usage.code, + Diagnostics.Property_0_implicitly_has_type_any_but_a_better_type_for_its_set_accessor_may_be_inferred_from_usage + .code, // Property declarations Diagnostics.Member_0_implicitly_has_an_1_type_but_a_better_type_may_be_inferred_from_usage.code, @@ -165,18 +167,44 @@ registerCodeFix({ const token = getTokenAtPosition(sourceFile, start); let declaration: Declaration | undefined; const changes = textChanges.ChangeTracker.with(context, changes => { - declaration = doChange(changes, sourceFile, token, errorCode, program, cancellationToken, /*markSeen*/ returnTrue, host, preferences); + declaration = doChange( + changes, + sourceFile, + token, + errorCode, + program, + cancellationToken, + /*markSeen*/ returnTrue, + host, + preferences, + ); }); const name = declaration && getNameOfDeclaration(declaration); return !name || changes.length === 0 ? undefined - : [createCodeFixAction(fixId, changes, [getDiagnostic(errorCode, token), getTextOfNode(name)], fixId, Diagnostics.Infer_all_types_from_usage)]; + : [createCodeFixAction( + fixId, + changes, + [getDiagnostic(errorCode, token), getTextOfNode(name)], + fixId, + Diagnostics.Infer_all_types_from_usage, + )]; }, fixIds: [fixId], getAllCodeActions(context) { const { sourceFile, program, cancellationToken, host, preferences } = context; const markSeen = nodeSeenTracker(); return codeFixAll(context, errorCodes, (changes, err) => { - doChange(changes, sourceFile, getTokenAtPosition(err.file, err.start), err.code, program, cancellationToken, markSeen, host, preferences); + doChange( + changes, + sourceFile, + getTokenAtPosition(err.file, err.start), + err.code, + program, + cancellationToken, + markSeen, + host, + preferences, + ); }); }, }); @@ -185,7 +213,8 @@ function getDiagnostic(errorCode: number, token: Node): DiagnosticMessage { switch (errorCode) { case Diagnostics.Parameter_0_implicitly_has_an_1_type.code: case Diagnostics.Parameter_0_implicitly_has_an_1_type_but_a_better_type_may_be_inferred_from_usage.code: - return isSetAccessorDeclaration(getContainingFunction(token)!) ? Diagnostics.Infer_type_of_0_from_usage : Diagnostics.Infer_parameter_types_from_usage; // TODO: GH#18217 + return isSetAccessorDeclaration(getContainingFunction(token)!) ? Diagnostics.Infer_type_of_0_from_usage + : Diagnostics.Infer_parameter_types_from_usage; // TODO: GH#18217 case Diagnostics.Rest_parameter_0_implicitly_has_an_any_type.code: case Diagnostics.Rest_parameter_0_implicitly_has_an_any_type_but_a_better_type_may_be_inferred_from_usage.code: return Diagnostics.Infer_parameter_types_from_usage; @@ -199,28 +228,47 @@ function getDiagnostic(errorCode: number, token: Node): DiagnosticMessage { /** Map suggestion code to error code */ function mapSuggestionDiagnostic(errorCode: number) { switch (errorCode) { - case Diagnostics.Variable_0_implicitly_has_type_1_in_some_locations_but_a_better_type_may_be_inferred_from_usage.code: - return Diagnostics.Variable_0_implicitly_has_type_1_in_some_locations_where_its_type_cannot_be_determined.code; + case Diagnostics.Variable_0_implicitly_has_type_1_in_some_locations_but_a_better_type_may_be_inferred_from_usage + .code: + return Diagnostics.Variable_0_implicitly_has_type_1_in_some_locations_where_its_type_cannot_be_determined + .code; case Diagnostics.Variable_0_implicitly_has_an_1_type_but_a_better_type_may_be_inferred_from_usage.code: return Diagnostics.Variable_0_implicitly_has_an_1_type.code; case Diagnostics.Parameter_0_implicitly_has_an_1_type_but_a_better_type_may_be_inferred_from_usage.code: return Diagnostics.Parameter_0_implicitly_has_an_1_type.code; case Diagnostics.Rest_parameter_0_implicitly_has_an_any_type_but_a_better_type_may_be_inferred_from_usage.code: return Diagnostics.Rest_parameter_0_implicitly_has_an_any_type.code; - case Diagnostics.Property_0_implicitly_has_type_any_but_a_better_type_for_its_get_accessor_may_be_inferred_from_usage.code: - return Diagnostics.Property_0_implicitly_has_type_any_because_its_get_accessor_lacks_a_return_type_annotation.code; + case Diagnostics + .Property_0_implicitly_has_type_any_but_a_better_type_for_its_get_accessor_may_be_inferred_from_usage.code: + return Diagnostics + .Property_0_implicitly_has_type_any_because_its_get_accessor_lacks_a_return_type_annotation.code; case Diagnostics._0_implicitly_has_an_1_return_type_but_a_better_type_may_be_inferred_from_usage.code: return Diagnostics._0_which_lacks_return_type_annotation_implicitly_has_an_1_return_type.code; - case Diagnostics.Property_0_implicitly_has_type_any_but_a_better_type_for_its_set_accessor_may_be_inferred_from_usage.code: - return Diagnostics.Property_0_implicitly_has_type_any_because_its_set_accessor_lacks_a_parameter_type_annotation.code; + case Diagnostics + .Property_0_implicitly_has_type_any_but_a_better_type_for_its_set_accessor_may_be_inferred_from_usage.code: + return Diagnostics + .Property_0_implicitly_has_type_any_because_its_set_accessor_lacks_a_parameter_type_annotation.code; case Diagnostics.Member_0_implicitly_has_an_1_type_but_a_better_type_may_be_inferred_from_usage.code: return Diagnostics.Member_0_implicitly_has_an_1_type.code; } return errorCode; } -function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, token: Node, errorCode: number, program: Program, cancellationToken: CancellationToken, markSeen: NodeSeenTracker, host: LanguageServiceHost, preferences: UserPreferences): Declaration | undefined { - if (!isParameterPropertyModifier(token.kind) && token.kind !== SyntaxKind.Identifier && token.kind !== SyntaxKind.DotDotDotToken && token.kind !== SyntaxKind.ThisKeyword) { +function doChange( + changes: textChanges.ChangeTracker, + sourceFile: SourceFile, + token: Node, + errorCode: number, + program: Program, + cancellationToken: CancellationToken, + markSeen: NodeSeenTracker, + host: LanguageServiceHost, + preferences: UserPreferences, +): Declaration | undefined { + if ( + !isParameterPropertyModifier(token.kind) && token.kind !== SyntaxKind.Identifier + && token.kind !== SyntaxKind.DotDotDotToken && token.kind !== SyntaxKind.ThisKeyword + ) { return undefined; } @@ -231,7 +279,10 @@ function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, to // Variable and Property declarations case Diagnostics.Member_0_implicitly_has_an_1_type.code: case Diagnostics.Variable_0_implicitly_has_type_1_in_some_locations_where_its_type_cannot_be_determined.code: - if ((isVariableDeclaration(parent) && markSeen(parent)) || isPropertyDeclaration(parent) || isPropertySignature(parent)) { // handle bad location + if ( + (isVariableDeclaration(parent) && markSeen(parent)) || isPropertyDeclaration(parent) + || isPropertySignature(parent) + ) { // handle bad location annotateVariableDeclaration(changes, importAdder, sourceFile, parent, program, host, cancellationToken); importAdder.writeFixes(changes); return parent; @@ -241,7 +292,11 @@ function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, to const typeNode = getTypeNodeIfAccessible(type, parent, program, host); if (typeNode) { // Note that the codefix will never fire with an existing `@type` tag, so there is no need to merge tags - const typeTag = factory.createJSDocTypeTag(/*tagName*/ undefined, factory.createJSDocTypeExpression(typeNode), /*comment*/ undefined); + const typeTag = factory.createJSDocTypeTag( + /*tagName*/ undefined, + factory.createJSDocTypeExpression(typeNode), + /*comment*/ undefined, + ); changes.addJSDocTags(sourceFile, cast(parent.parent.parent, isExpressionStatement), [typeTag]); } importAdder.writeFixes(changes); @@ -251,8 +306,19 @@ function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, to case Diagnostics.Variable_0_implicitly_has_an_1_type.code: { const symbol = program.getTypeChecker().getSymbolAtLocation(token); - if (symbol && symbol.valueDeclaration && isVariableDeclaration(symbol.valueDeclaration) && markSeen(symbol.valueDeclaration)) { - annotateVariableDeclaration(changes, importAdder, getSourceFileOfNode(symbol.valueDeclaration), symbol.valueDeclaration, program, host, cancellationToken); + if ( + symbol && symbol.valueDeclaration && isVariableDeclaration(symbol.valueDeclaration) + && markSeen(symbol.valueDeclaration) + ) { + annotateVariableDeclaration( + changes, + importAdder, + getSourceFileOfNode(symbol.valueDeclaration), + symbol.valueDeclaration, + program, + host, + cancellationToken, + ); importAdder.writeFixes(changes); return symbol.valueDeclaration; } @@ -270,7 +336,15 @@ function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, to // Parameter declarations case Diagnostics.Parameter_0_implicitly_has_an_1_type.code: if (isSetAccessorDeclaration(containingFunction)) { - annotateSetAccessor(changes, importAdder, sourceFile, containingFunction, program, host, cancellationToken); + annotateSetAccessor( + changes, + importAdder, + sourceFile, + containingFunction, + program, + host, + cancellationToken, + ); declaration = containingFunction; break; } @@ -278,24 +352,51 @@ function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, to case Diagnostics.Rest_parameter_0_implicitly_has_an_any_type.code: if (markSeen(containingFunction)) { const param = cast(parent, isParameter); - annotateParameters(changes, importAdder, sourceFile, param, containingFunction, program, host, cancellationToken); + annotateParameters( + changes, + importAdder, + sourceFile, + param, + containingFunction, + program, + host, + cancellationToken, + ); declaration = param; } break; // Get Accessor declarations - case Diagnostics.Property_0_implicitly_has_type_any_because_its_get_accessor_lacks_a_return_type_annotation.code: + case Diagnostics.Property_0_implicitly_has_type_any_because_its_get_accessor_lacks_a_return_type_annotation + .code: case Diagnostics._0_which_lacks_return_type_annotation_implicitly_has_an_1_return_type.code: if (isGetAccessorDeclaration(containingFunction) && isIdentifier(containingFunction.name)) { - annotate(changes, importAdder, sourceFile, containingFunction, inferTypeForVariableFromUsage(containingFunction.name, program, cancellationToken), program, host); + annotate( + changes, + importAdder, + sourceFile, + containingFunction, + inferTypeForVariableFromUsage(containingFunction.name, program, cancellationToken), + program, + host, + ); declaration = containingFunction; } break; // Set Accessor declarations - case Diagnostics.Property_0_implicitly_has_type_any_because_its_set_accessor_lacks_a_parameter_type_annotation.code: + case Diagnostics.Property_0_implicitly_has_type_any_because_its_set_accessor_lacks_a_parameter_type_annotation + .code: if (isSetAccessorDeclaration(containingFunction)) { - annotateSetAccessor(changes, importAdder, sourceFile, containingFunction, program, host, cancellationToken); + annotateSetAccessor( + changes, + importAdder, + sourceFile, + containingFunction, + program, + host, + cancellationToken, + ); declaration = containingFunction; } break; @@ -326,7 +427,15 @@ function annotateVariableDeclaration( cancellationToken: CancellationToken, ): void { if (isIdentifier(declaration.name)) { - annotate(changes, importAdder, sourceFile, declaration, inferTypeForVariableFromUsage(declaration.name, program, cancellationToken), program, host); + annotate( + changes, + importAdder, + sourceFile, + declaration, + inferTypeForVariableFromUsage(declaration.name, program, cancellationToken), + program, + host, + ); } } @@ -344,25 +453,53 @@ function annotateParameters( return; } - const parameterInferences = inferTypeForParametersFromUsage(containingFunction, sourceFile, program, cancellationToken); - Debug.assert(containingFunction.parameters.length === parameterInferences.length, "Parameter count and inference count should match"); + const parameterInferences = inferTypeForParametersFromUsage( + containingFunction, + sourceFile, + program, + cancellationToken, + ); + Debug.assert( + containingFunction.parameters.length === parameterInferences.length, + "Parameter count and inference count should match", + ); if (isInJSFile(containingFunction)) { annotateJSDocParameters(changes, sourceFile, parameterInferences, program, host); } else { - const needParens = isArrowFunction(containingFunction) && !findChildOfKind(containingFunction, SyntaxKind.OpenParenToken, sourceFile); - if (needParens) changes.insertNodeBefore(sourceFile, first(containingFunction.parameters), factory.createToken(SyntaxKind.OpenParenToken)); + const needParens = isArrowFunction(containingFunction) + && !findChildOfKind(containingFunction, SyntaxKind.OpenParenToken, sourceFile); + if (needParens) { + changes.insertNodeBefore( + sourceFile, + first(containingFunction.parameters), + factory.createToken(SyntaxKind.OpenParenToken), + ); + } for (const { declaration, type } of parameterInferences) { if (declaration && !declaration.type && !declaration.initializer) { annotate(changes, importAdder, sourceFile, declaration, type, program, host); } } - if (needParens) changes.insertNodeAfter(sourceFile, last(containingFunction.parameters), factory.createToken(SyntaxKind.CloseParenToken)); + if (needParens) { + changes.insertNodeAfter( + sourceFile, + last(containingFunction.parameters), + factory.createToken(SyntaxKind.CloseParenToken), + ); + } } } -function annotateThis(changes: textChanges.ChangeTracker, sourceFile: SourceFile, containingFunction: textChanges.ThisTypeAnnotatable, program: Program, host: LanguageServiceHost, cancellationToken: CancellationToken) { +function annotateThis( + changes: textChanges.ChangeTracker, + sourceFile: SourceFile, + containingFunction: textChanges.ThisTypeAnnotatable, + program: Program, + host: LanguageServiceHost, + cancellationToken: CancellationToken, +) { const references = getFunctionReferences(containingFunction, sourceFile, program, cancellationToken); if (!references || !references.length) { return; @@ -381,7 +518,12 @@ function annotateThis(changes: textChanges.ChangeTracker, sourceFile: SourceFile } } -function annotateJSDocThis(changes: textChanges.ChangeTracker, sourceFile: SourceFile, containingFunction: SignatureDeclaration, typeNode: TypeNode) { +function annotateJSDocThis( + changes: textChanges.ChangeTracker, + sourceFile: SourceFile, + containingFunction: SignatureDeclaration, + typeNode: TypeNode, +) { changes.addJSDocTags(sourceFile, containingFunction, [ factory.createJSDocThisTag(/*tagName*/ undefined, factory.createJSDocTypeExpression(typeNode)), ]); @@ -411,19 +553,39 @@ function annotateSetAccessor( } } -function annotate(changes: textChanges.ChangeTracker, importAdder: ImportAdder, sourceFile: SourceFile, declaration: textChanges.TypeAnnotatable, type: Type, program: Program, host: LanguageServiceHost): void { +function annotate( + changes: textChanges.ChangeTracker, + importAdder: ImportAdder, + sourceFile: SourceFile, + declaration: textChanges.TypeAnnotatable, + type: Type, + program: Program, + host: LanguageServiceHost, +): void { const typeNode = getTypeNodeIfAccessible(type, declaration, program, host); if (typeNode) { if (isInJSFile(sourceFile) && declaration.kind !== SyntaxKind.PropertySignature) { - const parent = isVariableDeclaration(declaration) ? tryCast(declaration.parent.parent, isVariableStatement) : declaration; + const parent = isVariableDeclaration(declaration) ? tryCast(declaration.parent.parent, isVariableStatement) + : declaration; if (!parent) { return; } const typeExpression = factory.createJSDocTypeExpression(typeNode); - const typeTag = isGetAccessorDeclaration(declaration) ? factory.createJSDocReturnTag(/*tagName*/ undefined, typeExpression, /*comment*/ undefined) : factory.createJSDocTypeTag(/*tagName*/ undefined, typeExpression, /*comment*/ undefined); + const typeTag = isGetAccessorDeclaration(declaration) + ? factory.createJSDocReturnTag(/*tagName*/ undefined, typeExpression, /*comment*/ undefined) + : factory.createJSDocTypeTag(/*tagName*/ undefined, typeExpression, /*comment*/ undefined); changes.addJSDocTags(sourceFile, parent, [typeTag]); } - else if (!tryReplaceImportTypeNodeWithAutoImport(typeNode, declaration, sourceFile, changes, importAdder, getEmitScriptTarget(program.getCompilerOptions()))) { + else if ( + !tryReplaceImportTypeNodeWithAutoImport( + typeNode, + declaration, + sourceFile, + changes, + importAdder, + getEmitScriptTarget(program.getCompilerOptions()), + ) + ) { changes.tryInsertTypeAnnotation(sourceFile, declaration, typeNode); } } @@ -439,13 +601,22 @@ function tryReplaceImportTypeNodeWithAutoImport( ): boolean { const importableReference = tryGetAutoImportableReferenceFromTypeNode(typeNode, scriptTarget); if (importableReference && changes.tryInsertTypeAnnotation(sourceFile, declaration, importableReference.typeNode)) { - forEach(importableReference.symbols, s => importAdder.addImportFromExportedSymbol(s, /*isValidTypeOnlyUseSite*/ true)); + forEach( + importableReference.symbols, + s => importAdder.addImportFromExportedSymbol(s, /*isValidTypeOnlyUseSite*/ true), + ); return true; } return false; } -function annotateJSDocParameters(changes: textChanges.ChangeTracker, sourceFile: SourceFile, parameterInferences: readonly ParameterInference[], program: Program, host: LanguageServiceHost): void { +function annotateJSDocParameters( + changes: textChanges.ChangeTracker, + sourceFile: SourceFile, + parameterInferences: readonly ParameterInference[], + program: Program, + host: LanguageServiceHost, +): void { const signature = parameterInferences.length && parameterInferences[0].declaration.parent; if (!signature) { return; @@ -470,58 +641,107 @@ function annotateJSDocParameters(changes: textChanges.ChangeTracker, sourceFile: } if (isArrowFunction(signature) || isFunctionExpression(signature)) { - const needParens = isArrowFunction(signature) && !findChildOfKind(signature, SyntaxKind.OpenParenToken, sourceFile); + const needParens = isArrowFunction(signature) + && !findChildOfKind(signature, SyntaxKind.OpenParenToken, sourceFile); if (needParens) { - changes.insertNodeBefore(sourceFile, first(signature.parameters), factory.createToken(SyntaxKind.OpenParenToken)); + changes.insertNodeBefore( + sourceFile, + first(signature.parameters), + factory.createToken(SyntaxKind.OpenParenToken), + ); } forEach(inferences, ({ typeNode, param }) => { - const typeTag = factory.createJSDocTypeTag(/*tagName*/ undefined, factory.createJSDocTypeExpression(typeNode)); + const typeTag = factory.createJSDocTypeTag( + /*tagName*/ undefined, + factory.createJSDocTypeExpression(typeNode), + ); const jsDoc = factory.createJSDocComment(/*comment*/ undefined, [typeTag]); changes.insertNodeAt(sourceFile, param.getStart(sourceFile), jsDoc, { suffix: " " }); }); if (needParens) { - changes.insertNodeAfter(sourceFile, last(signature.parameters), factory.createToken(SyntaxKind.CloseParenToken)); + changes.insertNodeAfter( + sourceFile, + last(signature.parameters), + factory.createToken(SyntaxKind.CloseParenToken), + ); } } else { - const paramTags = map(inferences, ({ name, typeNode, isOptional }) => factory.createJSDocParameterTag(/*tagName*/ undefined, name, /*isBracketed*/ !!isOptional, factory.createJSDocTypeExpression(typeNode), /*isNameFirst*/ false, /*comment*/ undefined)); + const paramTags = map( + inferences, + ({ name, typeNode, isOptional }) => + factory.createJSDocParameterTag( + /*tagName*/ undefined, + name, + /*isBracketed*/ !!isOptional, + factory.createJSDocTypeExpression(typeNode), + /*isNameFirst*/ false, + /*comment*/ undefined, + ), + ); changes.addJSDocTags(sourceFile, signature, paramTags); } } -function getReferences(token: PropertyName | Token, program: Program, cancellationToken: CancellationToken): readonly Identifier[] { +function getReferences( + token: PropertyName | Token, + program: Program, + cancellationToken: CancellationToken, +): readonly Identifier[] { // Position shouldn't matter since token is not a SourceFile. - return mapDefined(FindAllReferences.getReferenceEntriesForNode(-1, token, program, program.getSourceFiles(), cancellationToken), entry => entry.kind !== FindAllReferences.EntryKind.Span ? tryCast(entry.node, isIdentifier) : undefined); + return mapDefined( + FindAllReferences.getReferenceEntriesForNode(-1, token, program, program.getSourceFiles(), cancellationToken), + entry => entry.kind !== FindAllReferences.EntryKind.Span ? tryCast(entry.node, isIdentifier) : undefined, + ); } -function inferTypeForVariableFromUsage(token: Identifier | PrivateIdentifier, program: Program, cancellationToken: CancellationToken): Type { +function inferTypeForVariableFromUsage( + token: Identifier | PrivateIdentifier, + program: Program, + cancellationToken: CancellationToken, +): Type { const references = getReferences(token, program, cancellationToken); return inferTypeFromReferences(program, references, cancellationToken).single(); } -function inferTypeForParametersFromUsage(func: SignatureDeclaration, sourceFile: SourceFile, program: Program, cancellationToken: CancellationToken) { +function inferTypeForParametersFromUsage( + func: SignatureDeclaration, + sourceFile: SourceFile, + program: Program, + cancellationToken: CancellationToken, +) { const references = getFunctionReferences(func, sourceFile, program, cancellationToken); - return references && inferTypeFromReferences(program, references, cancellationToken).parameters(func) || - func.parameters.map(p => ({ + return references && inferTypeFromReferences(program, references, cancellationToken).parameters(func) + || func.parameters.map(p => ({ declaration: p, - type: isIdentifier(p.name) ? inferTypeForVariableFromUsage(p.name, program, cancellationToken) : program.getTypeChecker().getAnyType(), + type: isIdentifier(p.name) ? inferTypeForVariableFromUsage(p.name, program, cancellationToken) + : program.getTypeChecker().getAnyType(), })); } -function getFunctionReferences(containingFunction: SignatureDeclaration, sourceFile: SourceFile, program: Program, cancellationToken: CancellationToken): readonly Identifier[] | undefined { +function getFunctionReferences( + containingFunction: SignatureDeclaration, + sourceFile: SourceFile, + program: Program, + cancellationToken: CancellationToken, +): readonly Identifier[] | undefined { let searchToken; switch (containingFunction.kind) { case SyntaxKind.Constructor: - searchToken = findChildOfKind>(containingFunction, SyntaxKind.ConstructorKeyword, sourceFile); + searchToken = findChildOfKind>( + containingFunction, + SyntaxKind.ConstructorKeyword, + sourceFile, + ); break; case SyntaxKind.ArrowFunction: case SyntaxKind.FunctionExpression: const parent = containingFunction.parent; - searchToken = (isVariableDeclaration(parent) || isPropertyDeclaration(parent)) && isIdentifier(parent.name) ? - parent.name : - containingFunction.name; + searchToken = (isVariableDeclaration(parent) || isPropertyDeclaration(parent)) && isIdentifier(parent.name) + ? parent.name + : containingFunction.name; break; case SyntaxKind.FunctionDeclaration: case SyntaxKind.MethodDeclaration: @@ -543,7 +763,11 @@ interface ParameterInference { readonly isOptional?: boolean; } -function inferTypeFromReferences(program: Program, references: readonly Identifier[], cancellationToken: CancellationToken) { +function inferTypeFromReferences( + program: Program, + references: readonly Identifier[], + cancellationToken: CancellationToken, +) { const checker = program.getTypeChecker(); const builtinConstructors: { [s: string]: (t: Type) => Type; } = { string: () => checker.getStringType(), @@ -666,7 +890,9 @@ function inferTypeFromReferences(program: Program, references: readonly Identifi } } if (isIdentifier(parameter.name)) { - const inferred = inferTypesFromReferencesSingle(getReferences(parameter.name, program, cancellationToken)); + const inferred = inferTypesFromReferencesSingle( + getReferences(parameter.name, program, cancellationToken), + ); types.push(...(isRest ? mapDefined(inferred, checker.getElementTypeOfArrayType) : inferred)); } const type = combineTypes(types); @@ -882,8 +1108,9 @@ function inferTypeFromReferences(program: Program, references: readonly Identifi case SyntaxKind.BarBarToken: case SyntaxKind.QuestionQuestionToken: if ( - node === parent.left && - (node.parent.parent.kind === SyntaxKind.VariableDeclaration || isAssignmentExpression(node.parent.parent, /*excludeCompoundAssignment*/ true)) + node === parent.left + && (node.parent.parent.kind === SyntaxKind.VariableDeclaration + || isAssignmentExpression(node.parent.parent, /*excludeCompoundAssignment*/ true)) ) { // var x = x || {}; // TODO: use getFalsyflagsOfType @@ -934,7 +1161,11 @@ function inferTypeFromReferences(program: Program, references: readonly Identifi usage.properties.set(name, propertyUsage); } - function inferTypeFromPropertyElementExpression(parent: ElementAccessExpression, node: Expression, usage: Usage): void { + function inferTypeFromPropertyElementExpression( + parent: ElementAccessExpression, + node: Expression, + usage: Usage, + ): void { if (node === parent.argumentExpression) { usage.isNumberOrString = true; return; @@ -952,10 +1183,13 @@ function inferTypeFromReferences(program: Program, references: readonly Identifi } } - function inferTypeFromPropertyAssignment(assignment: PropertyAssignment | ShorthandPropertyAssignment, usage: Usage) { - const nodeWithRealType = isVariableDeclaration(assignment.parent.parent) ? - assignment.parent.parent : - assignment.parent; + function inferTypeFromPropertyAssignment( + assignment: PropertyAssignment | ShorthandPropertyAssignment, + usage: Usage, + ) { + const nodeWithRealType = isVariableDeclaration(assignment.parent.parent) + ? assignment.parent.parent + : assignment.parent; addCandidateThisType(usage, checker.getTypeAtLocation(nodeWithRealType)); } @@ -1002,7 +1236,9 @@ function inferTypeFromReferences(program: Program, references: readonly Identifi low: t => !!(t.flags & (TypeFlags.Any | TypeFlags.Void)), }, { - high: t => !(t.flags & (TypeFlags.Nullable | TypeFlags.Any | TypeFlags.Void)) && !(getObjectFlags(t) & ObjectFlags.Anonymous), + high: t => + !(t.flags & (TypeFlags.Nullable | TypeFlags.Any | TypeFlags.Void)) + && !(getObjectFlags(t) & ObjectFlags.Anonymous), low: t => !!(getObjectFlags(t) & ObjectFlags.Anonymous), }, ]; @@ -1012,7 +1248,9 @@ function inferTypeFromReferences(program: Program, references: readonly Identifi good = good.filter(i => !(getObjectFlags(i) & ObjectFlags.Anonymous)); good.push(combineAnonymousTypes(anons)); } - return checker.getWidenedType(checker.getUnionType(good.map(checker.getBaseTypeOfLiteralType), UnionReduction.Subtype)); + return checker.getWidenedType( + checker.getUnionType(good.map(checker.getBaseTypeOfLiteralType), UnionReduction.Subtype), + ); } function combineAnonymousTypes(anons: AnonymousType[]) { @@ -1028,7 +1266,11 @@ function inferTypeFromReferences(program: Program, references: readonly Identifi const props = createMultiMap<__String, Type>(); for (const anon of anons) { for (const p of checker.getPropertiesOfType(anon)) { - props.add(p.escapedName, p.valueDeclaration ? checker.getTypeOfSymbolAtLocation(p, p.valueDeclaration) : checker.getAnyType()); + props.add( + p.escapedName, + p.valueDeclaration ? checker.getTypeOfSymbolAtLocation(p, p.valueDeclaration) + : checker.getAnyType(), + ); } calls.push(...checker.getSignaturesOfType(anon, SignatureKind.Call)); constructs.push(...checker.getSignaturesOfType(anon, SignatureKind.Construct)); @@ -1050,8 +1292,24 @@ function inferTypeFromReferences(program: Program, references: readonly Identifi return [name, s]; }); const indexInfos = []; - if (stringIndices.length) indexInfos.push(checker.createIndexInfo(checker.getStringType(), checker.getUnionType(stringIndices), stringIndexReadonly)); - if (numberIndices.length) indexInfos.push(checker.createIndexInfo(checker.getNumberType(), checker.getUnionType(numberIndices), numberIndexReadonly)); + if (stringIndices.length) { + indexInfos.push( + checker.createIndexInfo( + checker.getStringType(), + checker.getUnionType(stringIndices), + stringIndexReadonly, + ), + ); + } + if (numberIndices.length) { + indexInfos.push( + checker.createIndexInfo( + checker.getNumberType(), + checker.getUnionType(numberIndices), + numberIndexReadonly, + ), + ); + } return checker.createAnonymousType( anons[0].symbol, members, @@ -1109,8 +1367,19 @@ function inferTypeFromReferences(program: Program, references: readonly Identifi } const callSignatures: Signature[] = usage.calls ? [getSignatureFromCalls(usage.calls)] : []; const constructSignatures: Signature[] = usage.constructs ? [getSignatureFromCalls(usage.constructs)] : []; - const indexInfos = usage.stringIndex ? [checker.createIndexInfo(checker.getStringType(), combineFromUsage(usage.stringIndex), /*isReadonly*/ false)] : []; - return checker.createAnonymousType(/*symbol*/ undefined, members, callSignatures, constructSignatures, indexInfos); + const indexInfos = usage.stringIndex + ? [checker.createIndexInfo( + checker.getStringType(), + combineFromUsage(usage.stringIndex), + /*isReadonly*/ false, + )] : []; + return checker.createAnonymousType( + /*symbol*/ undefined, + members, + callSignatures, + constructSignatures, + indexInfos, + ); } function inferNamedTypesFromProperties(usage: Usage): Type[] { @@ -1166,9 +1435,14 @@ function inferTypeFromReferences(program: Program, references: readonly Identifi return [usageType]; } else if (genericType.flags & TypeFlags.UnionOrIntersection) { - return flatMap((genericType as UnionOrIntersectionType).types, t => inferTypeParameters(t, usageType, typeParameter)); + return flatMap( + (genericType as UnionOrIntersectionType).types, + t => inferTypeParameters(t, usageType, typeParameter), + ); } - else if (getObjectFlags(genericType) & ObjectFlags.Reference && getObjectFlags(usageType) & ObjectFlags.Reference) { + else if ( + getObjectFlags(genericType) & ObjectFlags.Reference && getObjectFlags(usageType) & ObjectFlags.Reference + ) { // this is wrong because we need a reference to the targetType to, so we can check that it's also a reference const genericArgs = checker.getTypeArguments(genericType as TypeReference); const usageArgs = checker.getTypeArguments(usageType as TypeReference); @@ -1199,13 +1473,16 @@ function inferTypeFromReferences(program: Program, references: readonly Identifi if (!usageParam) { break; } - let genericParamType = genericParam.valueDeclaration ? checker.getTypeOfSymbolAtLocation(genericParam, genericParam.valueDeclaration) : checker.getAnyType(); + let genericParamType = genericParam.valueDeclaration + ? checker.getTypeOfSymbolAtLocation(genericParam, genericParam.valueDeclaration) : checker.getAnyType(); const elementType = isRest && checker.getElementTypeOfArrayType(genericParamType); if (elementType) { genericParamType = elementType; } const targetType = tryCast(usageParam, isTransientSymbol)?.links.type - || (usageParam.valueDeclaration ? checker.getTypeOfSymbolAtLocation(usageParam, usageParam.valueDeclaration) : checker.getAnyType()); + || (usageParam.valueDeclaration + ? checker.getTypeOfSymbolAtLocation(usageParam, usageParam.valueDeclaration) + : checker.getAnyType()); types.push(...inferTypeParameters(genericParamType, targetType, typeParameter)); } const genericReturn = checker.getReturnTypeOfSignature(genericSig); @@ -1215,14 +1492,23 @@ function inferTypeFromReferences(program: Program, references: readonly Identifi } function getFunctionFromCalls(calls: CallUsage[]) { - return checker.createAnonymousType(/*symbol*/ undefined, createSymbolTable(), [getSignatureFromCalls(calls)], emptyArray, emptyArray); + return checker.createAnonymousType( + /*symbol*/ undefined, + createSymbolTable(), + [getSignatureFromCalls(calls)], + emptyArray, + emptyArray, + ); } function getSignatureFromCalls(calls: CallUsage[]): Signature { const parameters: Symbol[] = []; const length = Math.max(...calls.map(c => c.argumentTypes.length)); for (let i = 0; i < length; i++) { - const symbol = checker.createSymbol(SymbolFlags.FunctionScopedVariable, escapeLeadingUnderscores(`arg${i}`)); + const symbol = checker.createSymbol( + SymbolFlags.FunctionScopedVariable, + escapeLeadingUnderscores(`arg${i}`), + ); symbol.links.type = combineTypes(calls.map(call => call.argumentTypes[i] || checker.getUndefinedType())); if (calls.some(call => call.argumentTypes[i] === undefined)) { symbol.flags |= SymbolFlags.Optional; @@ -1230,7 +1516,16 @@ function inferTypeFromReferences(program: Program, references: readonly Identifi parameters.push(symbol); } const returnType = combineFromUsage(combineUsages(calls.map(call => call.return_))); - return checker.createSignature(/*declaration*/ undefined, /*typeParameters*/ undefined, /*thisParameter*/ undefined, parameters, returnType, /*typePredicate*/ undefined, length, SignatureFlags.None); + return checker.createSignature( + /*declaration*/ undefined, + /*typeParameters*/ undefined, + /*thisParameter*/ undefined, + parameters, + returnType, + /*typePredicate*/ undefined, + length, + SignatureFlags.None, + ); } function addCandidateType(usage: Usage, type: Type | undefined) { diff --git a/src/services/codefixes/removeAccidentalCallParentheses.ts b/src/services/codefixes/removeAccidentalCallParentheses.ts index c4ad5c9ea3721..d639ed2485f4b 100644 --- a/src/services/codefixes/removeAccidentalCallParentheses.ts +++ b/src/services/codefixes/removeAccidentalCallParentheses.ts @@ -17,7 +17,10 @@ const errorCodes = [ registerCodeFix({ errorCodes, getCodeActions(context) { - const callExpression = findAncestor(getTokenAtPosition(context.sourceFile, context.span.start), isCallExpression); + const callExpression = findAncestor( + getTokenAtPosition(context.sourceFile, context.span.start), + isCallExpression, + ); if (!callExpression) { return undefined; } diff --git a/src/services/codefixes/removeUnnecessaryAwait.ts b/src/services/codefixes/removeUnnecessaryAwait.ts index 45e6dcdef0dcd..f54fe82547b16 100644 --- a/src/services/codefixes/removeUnnecessaryAwait.ts +++ b/src/services/codefixes/removeUnnecessaryAwait.ts @@ -30,7 +30,15 @@ registerCodeFix({ getCodeActions: function getCodeActionsToRemoveUnnecessaryAwait(context) { const changes = textChanges.ChangeTracker.with(context, t => makeChange(t, context.sourceFile, context.span)); if (changes.length > 0) { - return [createCodeFixAction(fixId, changes, Diagnostics.Remove_unnecessary_await, fixId, Diagnostics.Remove_all_unnecessary_uses_of_await)]; + return [ + createCodeFixAction( + fixId, + changes, + Diagnostics.Remove_unnecessary_await, + fixId, + Diagnostics.Remove_all_unnecessary_uses_of_await, + ), + ]; } }, fixIds: [fixId], @@ -40,7 +48,10 @@ registerCodeFix({ }); function makeChange(changeTracker: textChanges.ChangeTracker, sourceFile: SourceFile, span: TextSpan) { - const awaitKeyword = tryCast(getTokenAtPosition(sourceFile, span.start), (node): node is AwaitKeyword => node.kind === SyntaxKind.AwaitKeyword); + const awaitKeyword = tryCast( + getTokenAtPosition(sourceFile, span.start), + (node): node is AwaitKeyword => node.kind === SyntaxKind.AwaitKeyword, + ); const awaitExpression = awaitKeyword && tryCast(awaitKeyword.parent, isAwaitExpression); if (!awaitExpression) { return; diff --git a/src/services/codefixes/requireInTs.ts b/src/services/codefixes/requireInTs.ts index cc22d5e9f0078..a33b9b9563546 100644 --- a/src/services/codefixes/requireInTs.ts +++ b/src/services/codefixes/requireInTs.ts @@ -38,7 +38,15 @@ registerCodeFix({ return undefined; } const changes = textChanges.ChangeTracker.with(context, t => doChange(t, context.sourceFile, info)); - return [createCodeFixAction(fixId, changes, Diagnostics.Convert_require_to_import, fixId, Diagnostics.Convert_all_require_to_import)]; + return [ + createCodeFixAction( + fixId, + changes, + Diagnostics.Convert_require_to_import, + fixId, + Diagnostics.Convert_all_require_to_import, + ), + ]; }, fixIds: [fixId], getAllCodeActions: context => @@ -56,8 +64,18 @@ function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, in sourceFile, statement, defaultImportName && !allowSyntheticDefaults - ? factory.createImportEqualsDeclaration(/*modifiers*/ undefined, /*isTypeOnly*/ false, defaultImportName, factory.createExternalModuleReference(required)) - : factory.createImportDeclaration(/*modifiers*/ undefined, factory.createImportClause(/*isTypeOnly*/ false, defaultImportName, namedImports), required, /*assertClause*/ undefined), + ? factory.createImportEqualsDeclaration( + /*modifiers*/ undefined, + /*isTypeOnly*/ false, + defaultImportName, + factory.createExternalModuleReference(required), + ) + : factory.createImportDeclaration( + /*modifiers*/ undefined, + factory.createImportClause(/*isTypeOnly*/ false, defaultImportName, namedImports), + required, + /*assertClause*/ undefined, + ), ); } @@ -77,7 +95,8 @@ function getInfo(sourceFile: SourceFile, program: Program, pos: number): Info | const decl = cast(parent.parent, isVariableDeclaration); const defaultImportName = tryCast(decl.name, isIdentifier); - const namedImports = isObjectBindingPattern(decl.name) ? tryCreateNamedImportsFromObjectBindingPattern(decl.name) : undefined; + const namedImports = isObjectBindingPattern(decl.name) ? tryCreateNamedImportsFromObjectBindingPattern(decl.name) + : undefined; if (defaultImportName || namedImports) { return { allowSyntheticDefaults: getAllowSyntheticDefaultImports(program.getCompilerOptions()), @@ -95,7 +114,13 @@ function tryCreateNamedImportsFromObjectBindingPattern(node: ObjectBindingPatter if (!isIdentifier(element.name) || element.initializer) { return undefined; } - importSpecifiers.push(factory.createImportSpecifier(/*isTypeOnly*/ false, tryCast(element.propertyName, isIdentifier), element.name)); + importSpecifiers.push( + factory.createImportSpecifier( + /*isTypeOnly*/ false, + tryCast(element.propertyName, isIdentifier), + element.name, + ), + ); } if (importSpecifiers.length) { diff --git a/src/services/codefixes/returnValueCorrect.ts b/src/services/codefixes/returnValueCorrect.ts index 3aba6c183d29a..11222c85e28a6 100644 --- a/src/services/codefixes/returnValueCorrect.ts +++ b/src/services/codefixes/returnValueCorrect.ts @@ -90,7 +90,13 @@ registerCodeFix({ if (info.kind === ProblemKind.MissingReturnStatement) { return append( [getActionForfixAddReturnStatement(context, info.expression, info.statement)], - isArrowFunction(info.declaration) ? getActionForFixRemoveBracesFromArrowFunctionBody(context, info.declaration, info.expression, info.commentSource) : undefined, + isArrowFunction(info.declaration) + ? getActionForFixRemoveBracesFromArrowFunctionBody( + context, + info.declaration, + info.expression, + info.commentSource, + ) : undefined, ); } else { @@ -108,7 +114,14 @@ registerCodeFix({ break; case fixRemoveBracesFromArrowFunctionBody: if (!isArrowFunction(info.declaration)) return undefined; - removeBlockBodyBrace(changes, diag.file, info.declaration, info.expression, info.commentSource, /*withParen*/ false); + removeBlockBodyBrace( + changes, + diag.file, + info.declaration, + info.expression, + info.commentSource, + /*withParen*/ false, + ); break; case fixIdWrapTheBlockWithParen: if (!isArrowFunction(info.declaration)) return undefined; @@ -127,11 +140,25 @@ function createObjectTypeFromLabeledExpression(checker: TypeChecker, label: Iden return checker.createAnonymousType(/*symbol*/ undefined, members, [], [], []); } -function getFixInfo(checker: TypeChecker, declaration: FunctionLikeDeclaration, expectType: Type, isFunctionType: boolean): Info | undefined { +function getFixInfo( + checker: TypeChecker, + declaration: FunctionLikeDeclaration, + expectType: Type, + isFunctionType: boolean, +): Info | undefined { if (!declaration.body || !isBlock(declaration.body) || length(declaration.body.statements) !== 1) return undefined; const firstStatement = first(declaration.body.statements); - if (isExpressionStatement(firstStatement) && checkFixedAssignableTo(checker, declaration, checker.getTypeAtLocation(firstStatement.expression), expectType, isFunctionType)) { + if ( + isExpressionStatement(firstStatement) + && checkFixedAssignableTo( + checker, + declaration, + checker.getTypeAtLocation(firstStatement.expression), + expectType, + isFunctionType, + ) + ) { return { declaration, kind: ProblemKind.MissingReturnStatement, @@ -141,8 +168,14 @@ function getFixInfo(checker: TypeChecker, declaration: FunctionLikeDeclaration, }; } else if (isLabeledStatement(firstStatement) && isExpressionStatement(firstStatement.statement)) { - const node = factory.createObjectLiteralExpression([factory.createPropertyAssignment(firstStatement.label, firstStatement.statement.expression)]); - const nodeType = createObjectTypeFromLabeledExpression(checker, firstStatement.label, firstStatement.statement.expression); + const node = factory.createObjectLiteralExpression([ + factory.createPropertyAssignment(firstStatement.label, firstStatement.statement.expression), + ]); + const nodeType = createObjectTypeFromLabeledExpression( + checker, + firstStatement.label, + firstStatement.statement.expression, + ); if (checkFixedAssignableTo(checker, declaration, nodeType, expectType, isFunctionType)) { return isArrowFunction(declaration) ? { declaration, @@ -162,8 +195,14 @@ function getFixInfo(checker: TypeChecker, declaration: FunctionLikeDeclaration, else if (isBlock(firstStatement) && length(firstStatement.statements) === 1) { const firstBlockStatement = first(firstStatement.statements); if (isLabeledStatement(firstBlockStatement) && isExpressionStatement(firstBlockStatement.statement)) { - const node = factory.createObjectLiteralExpression([factory.createPropertyAssignment(firstBlockStatement.label, firstBlockStatement.statement.expression)]); - const nodeType = createObjectTypeFromLabeledExpression(checker, firstBlockStatement.label, firstBlockStatement.statement.expression); + const node = factory.createObjectLiteralExpression([ + factory.createPropertyAssignment(firstBlockStatement.label, firstBlockStatement.statement.expression), + ]); + const nodeType = createObjectTypeFromLabeledExpression( + checker, + firstBlockStatement.label, + firstBlockStatement.statement.expression, + ); if (checkFixedAssignableTo(checker, declaration, nodeType, expectType, isFunctionType)) { return { declaration, @@ -179,7 +218,13 @@ function getFixInfo(checker: TypeChecker, declaration: FunctionLikeDeclaration, return undefined; } -function checkFixedAssignableTo(checker: TypeChecker, declaration: FunctionLikeDeclaration, exprType: Type, type: Type, isFunctionType: boolean) { +function checkFixedAssignableTo( + checker: TypeChecker, + declaration: FunctionLikeDeclaration, + exprType: Type, + type: Type, + isFunctionType: boolean, +) { if (isFunctionType) { const sig = checker.getSignatureFromDeclaration(declaration); if (sig) { @@ -218,8 +263,15 @@ function getInfo(checker: TypeChecker, sourceFile: SourceFile, position: number, const declaration = findAncestor(node.parent, isFunctionLikeDeclaration); switch (errorCode) { case Diagnostics.A_function_whose_declared_type_is_neither_undefined_void_nor_any_must_return_a_value.code: - if (!declaration || !declaration.body || !declaration.type || !rangeContainsRange(declaration.type, node)) return undefined; - return getFixInfo(checker, declaration, checker.getTypeFromTypeNode(declaration.type), /*isFunctionType*/ false); + if (!declaration || !declaration.body || !declaration.type || !rangeContainsRange(declaration.type, node)) { + return undefined; + } + return getFixInfo( + checker, + declaration, + checker.getTypeFromTypeNode(declaration.type), + /*isFunctionType*/ false, + ); case Diagnostics.Argument_of_type_0_is_not_assignable_to_parameter_of_type_1.code: if (!declaration || !isCallExpression(declaration.parent) || !declaration.body) return undefined; const pos = declaration.parent.arguments.indexOf(declaration as Expression); @@ -228,7 +280,9 @@ function getInfo(checker: TypeChecker, sourceFile: SourceFile, position: number, if (!type) return undefined; return getFixInfo(checker, declaration, type, /*isFunctionType*/ true); case Diagnostics.Type_0_is_not_assignable_to_type_1.code: - if (!isDeclarationName(node) || !isVariableLike(node.parent) && !isJsxAttribute(node.parent)) return undefined; + if (!isDeclarationName(node) || !isVariableLike(node.parent) && !isJsxAttribute(node.parent)) { + return undefined; + } const initializer = getVariableLikeInitializer(node.parent); if (!initializer || !isFunctionLikeDeclaration(initializer) || !initializer.body) return undefined; return getFixInfo(checker, initializer, checker.getTypeAtLocation(node.parent), /*isFunctionType*/ true); @@ -245,7 +299,8 @@ function getVariableLikeInitializer(declaration: VariableLikeDeclaration): Expre case SyntaxKind.PropertyAssignment: return declaration.initializer; case SyntaxKind.JsxAttribute: - return declaration.initializer && (isJsxExpression(declaration.initializer) ? declaration.initializer.expression : undefined); + return declaration.initializer + && (isJsxExpression(declaration.initializer) ? declaration.initializer.expression : undefined); case SyntaxKind.ShorthandPropertyAssignment: case SyntaxKind.PropertySignature: case SyntaxKind.EnumMember: @@ -255,7 +310,12 @@ function getVariableLikeInitializer(declaration: VariableLikeDeclaration): Expre } } -function addReturnStatement(changes: textChanges.ChangeTracker, sourceFile: SourceFile, expression: Expression, statement: Statement) { +function addReturnStatement( + changes: textChanges.ChangeTracker, + sourceFile: SourceFile, + expression: Expression, + statement: Statement, +) { suppressLeadingAndTrailingTrivia(expression); const probablyNeedSemi = probablyUsesSemicolons(sourceFile); changes.replaceNode(sourceFile, statement, factory.createReturnStatement(expression), { @@ -265,29 +325,78 @@ function addReturnStatement(changes: textChanges.ChangeTracker, sourceFile: Sour }); } -function removeBlockBodyBrace(changes: textChanges.ChangeTracker, sourceFile: SourceFile, declaration: ArrowFunction, expression: Expression, commentSource: Node, withParen: boolean) { - const newBody = (withParen || needsParentheses(expression)) ? factory.createParenthesizedExpression(expression) : expression; +function removeBlockBodyBrace( + changes: textChanges.ChangeTracker, + sourceFile: SourceFile, + declaration: ArrowFunction, + expression: Expression, + commentSource: Node, + withParen: boolean, +) { + const newBody = (withParen || needsParentheses(expression)) ? factory.createParenthesizedExpression(expression) + : expression; suppressLeadingAndTrailingTrivia(commentSource); copyComments(commentSource, newBody); changes.replaceNode(sourceFile, declaration.body, newBody); } -function wrapBlockWithParen(changes: textChanges.ChangeTracker, sourceFile: SourceFile, declaration: ArrowFunction, expression: Expression) { +function wrapBlockWithParen( + changes: textChanges.ChangeTracker, + sourceFile: SourceFile, + declaration: ArrowFunction, + expression: Expression, +) { changes.replaceNode(sourceFile, declaration.body, factory.createParenthesizedExpression(expression)); } function getActionForfixAddReturnStatement(context: CodeFixContext, expression: Expression, statement: Statement) { - const changes = textChanges.ChangeTracker.with(context, t => addReturnStatement(t, context.sourceFile, expression, statement)); - return createCodeFixAction(fixId, changes, Diagnostics.Add_a_return_statement, fixIdAddReturnStatement, Diagnostics.Add_all_missing_return_statement); + const changes = textChanges.ChangeTracker.with( + context, + t => addReturnStatement(t, context.sourceFile, expression, statement), + ); + return createCodeFixAction( + fixId, + changes, + Diagnostics.Add_a_return_statement, + fixIdAddReturnStatement, + Diagnostics.Add_all_missing_return_statement, + ); } -function getActionForFixRemoveBracesFromArrowFunctionBody(context: CodeFixContext, declaration: ArrowFunction, expression: Expression, commentSource: Node) { - const changes = textChanges.ChangeTracker.with(context, t => removeBlockBodyBrace(t, context.sourceFile, declaration, expression, commentSource, /*withParen*/ false)); - return createCodeFixAction(fixId, changes, Diagnostics.Remove_braces_from_arrow_function_body, fixRemoveBracesFromArrowFunctionBody, Diagnostics.Remove_braces_from_all_arrow_function_bodies_with_relevant_issues); +function getActionForFixRemoveBracesFromArrowFunctionBody( + context: CodeFixContext, + declaration: ArrowFunction, + expression: Expression, + commentSource: Node, +) { + const changes = textChanges.ChangeTracker.with( + context, + t => removeBlockBodyBrace(t, context.sourceFile, declaration, expression, commentSource, /*withParen*/ false), + ); + return createCodeFixAction( + fixId, + changes, + Diagnostics.Remove_braces_from_arrow_function_body, + fixRemoveBracesFromArrowFunctionBody, + Diagnostics.Remove_braces_from_all_arrow_function_bodies_with_relevant_issues, + ); } -function getActionForfixWrapTheBlockWithParen(context: CodeFixContext, declaration: ArrowFunction, expression: Expression) { - const changes = textChanges.ChangeTracker.with(context, t => wrapBlockWithParen(t, context.sourceFile, declaration, expression)); - return createCodeFixAction(fixId, changes, Diagnostics.Wrap_the_following_body_with_parentheses_which_should_be_an_object_literal, fixIdWrapTheBlockWithParen, Diagnostics.Wrap_all_object_literal_with_parentheses); +function getActionForfixWrapTheBlockWithParen( + context: CodeFixContext, + declaration: ArrowFunction, + expression: Expression, +) { + const changes = textChanges.ChangeTracker.with( + context, + t => wrapBlockWithParen(t, context.sourceFile, declaration, expression), + ); + return createCodeFixAction( + fixId, + changes, + Diagnostics.Wrap_the_following_body_with_parentheses_which_should_be_an_object_literal, + fixIdWrapTheBlockWithParen, + Diagnostics.Wrap_all_object_literal_with_parentheses, + ); } diff --git a/src/services/codefixes/splitTypeOnlyImport.ts b/src/services/codefixes/splitTypeOnlyImport.ts index 0b1e2e48e577e..dbd0c75756efe 100644 --- a/src/services/codefixes/splitTypeOnlyImport.ts +++ b/src/services/codefixes/splitTypeOnlyImport.ts @@ -27,7 +27,15 @@ registerCodeFix({ return splitTypeOnlyImport(t, getImportDeclaration(context.sourceFile, context.span), context); }); if (changes.length) { - return [createCodeFixAction(fixId, changes, Diagnostics.Split_into_two_separate_import_declarations, fixId, Diagnostics.Split_all_invalid_type_only_imports)]; + return [ + createCodeFixAction( + fixId, + changes, + Diagnostics.Split_into_two_separate_import_declarations, + fixId, + Diagnostics.Split_all_invalid_type_only_imports, + ), + ]; } }, getAllCodeActions: context => @@ -40,7 +48,11 @@ function getImportDeclaration(sourceFile: SourceFile, span: TextSpan) { return findAncestor(getTokenAtPosition(sourceFile, span.start), isImportDeclaration); } -function splitTypeOnlyImport(changes: textChanges.ChangeTracker, importDeclaration: ImportDeclaration | undefined, context: CodeFixContextBase) { +function splitTypeOnlyImport( + changes: textChanges.ChangeTracker, + importDeclaration: ImportDeclaration | undefined, + context: CodeFixContextBase, +) { if (!importDeclaration) { return; } @@ -51,7 +63,12 @@ function splitTypeOnlyImport(changes: textChanges.ChangeTracker, importDeclarati factory.updateImportDeclaration( importDeclaration, importDeclaration.modifiers, - factory.updateImportClause(importClause, importClause.isTypeOnly, importClause.name, /*namedBindings*/ undefined), + factory.updateImportClause( + importClause, + importClause.isTypeOnly, + importClause.name, + /*namedBindings*/ undefined, + ), importDeclaration.moduleSpecifier, importDeclaration.assertClause, ), @@ -62,7 +79,12 @@ function splitTypeOnlyImport(changes: textChanges.ChangeTracker, importDeclarati importDeclaration, factory.createImportDeclaration( /*modifiers*/ undefined, - factory.updateImportClause(importClause, importClause.isTypeOnly, /*name*/ undefined, importClause.namedBindings), + factory.updateImportClause( + importClause, + importClause.isTypeOnly, + /*name*/ undefined, + importClause.namedBindings, + ), importDeclaration.moduleSpecifier, importDeclaration.assertClause, ), diff --git a/src/services/codefixes/useBigintLiteral.ts b/src/services/codefixes/useBigintLiteral.ts index 4492e176b5c57..c9f372048dd12 100644 --- a/src/services/codefixes/useBigintLiteral.ts +++ b/src/services/codefixes/useBigintLiteral.ts @@ -16,7 +16,9 @@ import { const fixId = "useBigintLiteral"; const errorCodes = [ - Diagnostics.Numeric_literals_with_absolute_values_equal_to_2_53_or_greater_are_too_large_to_be_represented_accurately_as_integers.code, + Diagnostics + .Numeric_literals_with_absolute_values_equal_to_2_53_or_greater_are_too_large_to_be_represented_accurately_as_integers + .code, ]; registerCodeFix({ @@ -24,7 +26,15 @@ registerCodeFix({ getCodeActions: function getCodeActionsToUseBigintLiteral(context) { const changes = textChanges.ChangeTracker.with(context, t => makeChange(t, context.sourceFile, context.span)); if (changes.length > 0) { - return [createCodeFixAction(fixId, changes, Diagnostics.Convert_to_a_bigint_numeric_literal, fixId, Diagnostics.Convert_all_to_bigint_numeric_literals)]; + return [ + createCodeFixAction( + fixId, + changes, + Diagnostics.Convert_to_a_bigint_numeric_literal, + fixId, + Diagnostics.Convert_all_to_bigint_numeric_literals, + ), + ]; } }, fixIds: [fixId], diff --git a/src/services/codefixes/useDefaultImport.ts b/src/services/codefixes/useDefaultImport.ts index 92ef84495a7bb..893652ca2419d 100644 --- a/src/services/codefixes/useDefaultImport.ts +++ b/src/services/codefixes/useDefaultImport.ts @@ -28,8 +28,19 @@ registerCodeFix({ const { sourceFile, span: { start } } = context; const info = getInfo(sourceFile, start); if (!info) return undefined; - const changes = textChanges.ChangeTracker.with(context, t => doChange(t, sourceFile, info, context.preferences)); - return [createCodeFixAction(fixId, changes, Diagnostics.Convert_to_default_import, fixId, Diagnostics.Convert_all_to_default_imports)]; + const changes = textChanges.ChangeTracker.with( + context, + t => doChange(t, sourceFile, info, context.preferences), + ); + return [ + createCodeFixAction( + fixId, + changes, + Diagnostics.Convert_to_default_import, + fixId, + Diagnostics.Convert_all_to_default_imports, + ), + ]; }, fixIds: [fixId], getAllCodeActions: context => @@ -57,6 +68,20 @@ function getInfo(sourceFile: SourceFile, pos: number): Info | undefined { } } -function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, info: Info, preferences: UserPreferences): void { - changes.replaceNode(sourceFile, info.importNode, makeImport(info.name, /*namedImports*/ undefined, info.moduleSpecifier, getQuotePreference(sourceFile, preferences))); +function doChange( + changes: textChanges.ChangeTracker, + sourceFile: SourceFile, + info: Info, + preferences: UserPreferences, +): void { + changes.replaceNode( + sourceFile, + info.importNode, + makeImport( + info.name, + /*namedImports*/ undefined, + info.moduleSpecifier, + getQuotePreference(sourceFile, preferences), + ), + ); } diff --git a/src/services/codefixes/wrapJsxInFragment.ts b/src/services/codefixes/wrapJsxInFragment.ts index 11693d88a4c43..89140c85854ca 100644 --- a/src/services/codefixes/wrapJsxInFragment.ts +++ b/src/services/codefixes/wrapJsxInFragment.ts @@ -27,7 +27,15 @@ registerCodeFix({ const node = findNodeToFix(sourceFile, span.start); if (!node) return undefined; const changes = textChanges.ChangeTracker.with(context, t => doChange(t, sourceFile, node)); - return [createCodeFixAction(fixID, changes, Diagnostics.Wrap_in_JSX_fragment, fixID, Diagnostics.Wrap_all_unparented_JSX_in_JSX_fragment)]; + return [ + createCodeFixAction( + fixID, + changes, + Diagnostics.Wrap_in_JSX_fragment, + fixID, + Diagnostics.Wrap_all_unparented_JSX_in_JSX_fragment, + ), + ]; }, fixIds: [fixID], getAllCodeActions: context => @@ -55,7 +63,13 @@ function findNodeToFix(sourceFile: SourceFile, pos: number): BinaryExpression | function doChange(changeTracker: textChanges.ChangeTracker, sf: SourceFile, node: Node) { const jsx = flattenInvalidBinaryExpr(node); - if (jsx) changeTracker.replaceNode(sf, node, factory.createJsxFragment(factory.createJsxOpeningFragment(), jsx, factory.createJsxJsxClosingFragment())); + if (jsx) { + changeTracker.replaceNode( + sf, + node, + factory.createJsxFragment(factory.createJsxOpeningFragment(), jsx, factory.createJsxJsxClosingFragment()), + ); + } } // The invalid syntax is constructed as // InvalidJsxTree :: One of @@ -65,7 +79,10 @@ function flattenInvalidBinaryExpr(node: Node): JsxChild[] | undefined { const children: JsxChild[] = []; let current = node; while (true) { - if (isBinaryExpression(current) && nodeIsMissing(current.operatorToken) && current.operatorToken.kind === SyntaxKind.CommaToken) { + if ( + isBinaryExpression(current) && nodeIsMissing(current.operatorToken) + && current.operatorToken.kind === SyntaxKind.CommaToken + ) { children.push(current.left as JsxChild); if (isJsxChild(current.right)) { children.push(current.right); diff --git a/src/services/completions.ts b/src/services/completions.ts index 23458ee7eeec4..e36dd26936d58 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -525,7 +525,9 @@ function originIsResolvedExport(origin: SymbolOriginInfo | undefined): origin is return !!(origin && origin.kind === SymbolOriginInfoKind.ResolvedExport); } -function originIncludesSymbolName(origin: SymbolOriginInfo | undefined): origin is SymbolOriginInfoExport | SymbolOriginInfoResolvedExport | SymbolOriginInfoComputedPropertyName { +function originIncludesSymbolName( + origin: SymbolOriginInfo | undefined, +): origin is SymbolOriginInfoExport | SymbolOriginInfoResolvedExport | SymbolOriginInfoComputedPropertyName { return originIsExport(origin) || originIsResolvedExport(origin) || originIsComputedPropertyName(origin); } @@ -545,7 +547,9 @@ function originIsTypeOnlyAlias(origin: SymbolOriginInfo | undefined): origin is return !!(origin && origin.kind & SymbolOriginInfoKind.TypeOnlyAlias); } -function originIsObjectLiteralMethod(origin: SymbolOriginInfo | undefined): origin is SymbolOriginInfoObjectLiteralMethod { +function originIsObjectLiteralMethod( + origin: SymbolOriginInfo | undefined, +): origin is SymbolOriginInfoObjectLiteralMethod { return !!(origin && origin.kind & SymbolOriginInfoKind.ObjectLiteralMethod); } @@ -553,7 +557,9 @@ function originIsIgnore(origin: SymbolOriginInfo | undefined): boolean { return !!(origin && origin.kind & SymbolOriginInfoKind.Ignore); } -function originIsComputedPropertyName(origin: SymbolOriginInfo | undefined): origin is SymbolOriginInfoComputedPropertyName { +function originIsComputedPropertyName( + origin: SymbolOriginInfo | undefined, +): origin is SymbolOriginInfoComputedPropertyName { return !!(origin && origin.kind & SymbolOriginInfoKind.ComputedPropertyName); } @@ -597,7 +603,10 @@ const enum GlobalsSearch { } interface ModuleSpecifierResolutionContext { - tryResolve: (exportInfo: readonly SymbolExportInfo[], isFromAmbientModule: boolean) => ModuleSpecifierResolutionResult; + tryResolve: ( + exportInfo: readonly SymbolExportInfo[], + isFromAmbientModule: boolean, + ) => ModuleSpecifierResolutionResult; resolvedAny: () => boolean; skippedAny: () => boolean; resolvedBeyondLimit: () => boolean; @@ -625,7 +634,10 @@ function resolvingModuleSpecifiers( // relative path into node_modules), and we want to filter those completions out entirely. // Import statement completions always need specifier resolution because the module specifier is // part of their `insertText`, not the `codeActions` creating edits away from the cursor. - const needsFullResolution = isForImportStatementCompletion || moduleResolutionSupportsPackageJsonExportsAndImports(getEmitModuleResolutionKind(program.getCompilerOptions())); + const needsFullResolution = isForImportStatementCompletion + || moduleResolutionSupportsPackageJsonExportsAndImports( + getEmitModuleResolutionKind(program.getCompilerOptions()), + ); let skippedAny = false; let ambientCount = 0; let resolvedCount = 0; @@ -639,13 +651,19 @@ function resolvingModuleSpecifiers( resolvedBeyondLimit: () => resolvedCount > moduleSpecifierResolutionLimit, }); - const hitRateMessage = cacheAttemptCount ? ` (${(resolvedFromCacheCount / cacheAttemptCount * 100).toFixed(1)}% hit rate)` : ""; - host.log?.(`${logPrefix}: resolved ${resolvedCount} module specifiers, plus ${ambientCount} ambient and ${resolvedFromCacheCount} from cache${hitRateMessage}`); + const hitRateMessage = cacheAttemptCount + ? ` (${(resolvedFromCacheCount / cacheAttemptCount * 100).toFixed(1)}% hit rate)` : ""; + host.log?.( + `${logPrefix}: resolved ${resolvedCount} module specifiers, plus ${ambientCount} ambient and ${resolvedFromCacheCount} from cache${hitRateMessage}`, + ); host.log?.(`${logPrefix}: response is ${skippedAny ? "incomplete" : "complete"}`); host.log?.(`${logPrefix}: ${timestamp() - start}`); return result; - function tryResolve(exportInfo: readonly SymbolExportInfo[], isFromAmbientModule: boolean): ModuleSpecifierResolutionResult { + function tryResolve( + exportInfo: readonly SymbolExportInfo[], + isFromAmbientModule: boolean, + ): ModuleSpecifierResolutionResult { if (isFromAmbientModule) { const result = resolver.getModuleSpecifierForBestExportInfo(exportInfo, position, isValidTypeOnlyUseSite); if (result) { @@ -653,13 +671,23 @@ function resolvingModuleSpecifiers( } return result || "failed"; } - const shouldResolveModuleSpecifier = needsFullResolution || preferences.allowIncompleteCompletions && resolvedCount < moduleSpecifierResolutionLimit; - const shouldGetModuleSpecifierFromCache = !shouldResolveModuleSpecifier && preferences.allowIncompleteCompletions && cacheAttemptCount < moduleSpecifierResolutionCacheAttemptLimit; + const shouldResolveModuleSpecifier = needsFullResolution + || preferences.allowIncompleteCompletions && resolvedCount < moduleSpecifierResolutionLimit; + const shouldGetModuleSpecifierFromCache = !shouldResolveModuleSpecifier + && preferences.allowIncompleteCompletions && cacheAttemptCount < moduleSpecifierResolutionCacheAttemptLimit; const result = (shouldResolveModuleSpecifier || shouldGetModuleSpecifierFromCache) - ? resolver.getModuleSpecifierForBestExportInfo(exportInfo, position, isValidTypeOnlyUseSite, shouldGetModuleSpecifierFromCache) + ? resolver.getModuleSpecifierForBestExportInfo( + exportInfo, + position, + isValidTypeOnlyUseSite, + shouldGetModuleSpecifierFromCache, + ) : undefined; - if (!shouldResolveModuleSpecifier && !shouldGetModuleSpecifierFromCache || shouldGetModuleSpecifierFromCache && !result) { + if ( + !shouldResolveModuleSpecifier && !shouldGetModuleSpecifierFromCache + || shouldGetModuleSpecifierFromCache && !result + ) { skippedAny = true; } @@ -688,14 +716,23 @@ export function getCompletionsAtPosition( includeSymbol = false, ): CompletionInfo | undefined { const { previousToken } = getRelevantTokens(position, sourceFile); - if (triggerCharacter && !isInString(sourceFile, position, previousToken) && !isValidTrigger(sourceFile, triggerCharacter, previousToken, position)) { + if ( + triggerCharacter && !isInString(sourceFile, position, previousToken) + && !isValidTrigger(sourceFile, triggerCharacter, previousToken, position) + ) { return undefined; } if (triggerCharacter === " ") { // `isValidTrigger` ensures we are at `import |` if (preferences.includeCompletionsForImportStatements && preferences.includeCompletionsWithInsertText) { - return { isGlobalCompletion: true, isMemberCompletion: false, isNewIdentifierLocation: true, isIncomplete: true, entries: [] }; + return { + isGlobalCompletion: true, + isMemberCompletion: false, + isNewIdentifierLocation: true, + isIncomplete: true, + entries: [], + }; } return undefined; } @@ -704,9 +741,22 @@ export function getCompletionsAtPosition( const checker = program.getTypeChecker(); // If the request is a continuation of an earlier `isIncomplete` response, // we can continue it from the cached previous response. - const incompleteCompletionsCache = preferences.allowIncompleteCompletions ? host.getIncompleteCompletionsCache?.() : undefined; - if (incompleteCompletionsCache && completionKind === CompletionTriggerKind.TriggerForIncompleteCompletions && previousToken && isIdentifier(previousToken)) { - const incompleteContinuation = continuePreviousIncompleteResponse(incompleteCompletionsCache, sourceFile, previousToken, program, host, preferences, cancellationToken, position); + const incompleteCompletionsCache = preferences.allowIncompleteCompletions ? host.getIncompleteCompletionsCache?.() + : undefined; + if ( + incompleteCompletionsCache && completionKind === CompletionTriggerKind.TriggerForIncompleteCompletions + && previousToken && isIdentifier(previousToken) + ) { + const incompleteContinuation = continuePreviousIncompleteResponse( + incompleteCompletionsCache, + sourceFile, + previousToken, + program, + host, + preferences, + cancellationToken, + position, + ); if (incompleteContinuation) { return incompleteContinuation; } @@ -715,26 +765,59 @@ export function getCompletionsAtPosition( incompleteCompletionsCache?.clear(); } - const stringCompletions = StringCompletions.getStringLiteralCompletions(sourceFile, position, previousToken, compilerOptions, host, program, log, preferences, includeSymbol); + const stringCompletions = StringCompletions.getStringLiteralCompletions( + sourceFile, + position, + previousToken, + compilerOptions, + host, + program, + log, + preferences, + includeSymbol, + ); if (stringCompletions) { return stringCompletions; } if ( previousToken && isBreakOrContinueStatement(previousToken.parent) - && (previousToken.kind === SyntaxKind.BreakKeyword || previousToken.kind === SyntaxKind.ContinueKeyword || previousToken.kind === SyntaxKind.Identifier) + && (previousToken.kind === SyntaxKind.BreakKeyword || previousToken.kind === SyntaxKind.ContinueKeyword + || previousToken.kind === SyntaxKind.Identifier) ) { return getLabelCompletionAtPosition(previousToken.parent); } - const completionData = getCompletionData(program, log, sourceFile, compilerOptions, position, preferences, /*detailsEntryId*/ undefined, host, formatContext, cancellationToken); + const completionData = getCompletionData( + program, + log, + sourceFile, + compilerOptions, + position, + preferences, + /*detailsEntryId*/ undefined, + host, + formatContext, + cancellationToken, + ); if (!completionData) { return undefined; } switch (completionData.kind) { case CompletionDataKind.Data: - const response = completionInfoFromData(sourceFile, host, program, compilerOptions, log, completionData, preferences, formatContext, position, includeSymbol); + const response = completionInfoFromData( + sourceFile, + host, + program, + compilerOptions, + log, + completionData, + preferences, + formatContext, + position, + includeSymbol, + ); if (response?.isIncomplete) { incompleteCompletionsCache?.set(response); } @@ -768,7 +851,10 @@ export function getCompletionsAtPosition( case CompletionDataKind.JsDocParameterName: return jsdocCompletionInfo(JsDoc.getJSDocParameterNameCompletions(completionData.tag)); case CompletionDataKind.Keywords: - return specificKeywordCompletionInfo(completionData.keywordCompletions, completionData.isNewIdentifierLocation); + return specificKeywordCompletionInfo( + completionData.keywordCompletions, + completionData.isNewIdentifierLocation, + ); default: return Debug.assertNever(completionData); } @@ -800,7 +886,9 @@ function compareCompletionEntries(entryInArray: CompletionEntry, entryToInsert: return result; } -function completionEntryDataIsResolved(data: CompletionEntryDataAutoImport | undefined): data is CompletionEntryDataResolved { +function completionEntryDataIsResolved( + data: CompletionEntryDataAutoImport | undefined, +): data is CompletionEntryDataResolved { return !!data?.moduleSpecifier; } @@ -840,10 +928,13 @@ function continuePreviousIncompleteResponse( return undefined; } - const { origin } = Debug.checkDefined(getAutoImportSymbolFromCompletionEntryData(entry.name, entry.data, program, host)); + const { origin } = Debug.checkDefined( + getAutoImportSymbolFromCompletionEntryData(entry.name, entry.data, program, host), + ); const info = exportMap.get(file.path, entry.data.exportMapKey); - const result = info && context.tryResolve(info, !isExternalModuleNameRelative(stripQuotes(origin.moduleSymbol.name))); + const result = info + && context.tryResolve(info, !isExternalModuleNameRelative(stripQuotes(origin.moduleSymbol.name))); if (result === "skipped") return entry; if (!result || result === "failed") { host.log?.(`Unexpected failure resolving auto import for '${entry.name}' from '${entry.source}'`); @@ -1079,7 +1170,8 @@ function generateJSDocParamTagsForDestructuring( // We can't really deeply annotate an array binding pattern. function elementWorker(path: string, element: BindingElement, counter: TabStopCounter): string[] | undefined { if ((!element.propertyName && isIdentifier(element.name)) || isIdentifier(element.name)) { // `{ b }` or `{ b: newB }` - const propertyName = element.propertyName ? tryGetTextOfPropertyName(element.propertyName) : element.name.text; + const propertyName = element.propertyName ? tryGetTextOfPropertyName(element.propertyName) + : element.name.text; if (!propertyName) { return undefined; } @@ -1102,7 +1194,13 @@ function generateJSDocParamTagsForDestructuring( else if (element.propertyName) { // `{ b: {...} }` or `{ b: [...] }` const propertyName = tryGetTextOfPropertyName(element.propertyName); return propertyName - && patternWorker(`${path}.${propertyName}`, element.name, element.initializer, element.dotDotDotToken, counter); + && patternWorker( + `${path}.${propertyName}`, + element.name, + element.initializer, + element.dotDotDotToken, + counter, + ); } return undefined; } @@ -1145,8 +1243,13 @@ function getJSDocParamAnnotation( if (!(inferredType.flags & (TypeFlags.Any | TypeFlags.Void))) { const sourceFile = initializer.getSourceFile(); const quotePreference = getQuotePreference(sourceFile, preferences); - const builderFlags = quotePreference === QuotePreference.Single ? NodeBuilderFlags.UseSingleQuotesForStringLiteralType : NodeBuilderFlags.None; - const typeNode = checker.typeToTypeNode(inferredType, findAncestor(initializer, isFunctionLike), builderFlags); + const builderFlags = quotePreference === QuotePreference.Single + ? NodeBuilderFlags.UseSingleQuotesForStringLiteralType : NodeBuilderFlags.None; + const typeNode = checker.typeToTypeNode( + inferredType, + findAncestor(initializer, isFunctionLike), + builderFlags, + ); if (typeNode) { const printer = isSnippet ? createSnippetPrinter({ @@ -1195,7 +1298,10 @@ function keywordToCompletionEntry(keyword: TokenSyntaxKind) { }; } -function specificKeywordCompletionInfo(entries: readonly CompletionEntry[], isNewIdentifierLocation: boolean): CompletionInfo { +function specificKeywordCompletionInfo( + entries: readonly CompletionEntry[], + isNewIdentifierLocation: boolean, +): CompletionInfo { return { isGlobalCompletion: false, isMemberCompletion: false, @@ -1204,7 +1310,11 @@ function specificKeywordCompletionInfo(entries: readonly CompletionEntry[], isNe }; } -function keywordCompletionData(keywordFilters: KeywordCompletionFilters, filterOutTsOnlyKeywords: boolean, isNewIdentifierLocation: boolean): Request { +function keywordCompletionData( + keywordFilters: KeywordCompletionFilters, + filterOutTsOnlyKeywords: boolean, + isNewIdentifierLocation: boolean, +): Request { return { kind: CompletionDataKind.Keywords, keywordCompletions: getKeywordCompletions(keywordFilters, filterOutTsOnlyKeywords), @@ -1292,7 +1402,10 @@ function completionInfoFromData( const entries = createSortedArray(); const isChecked = isCheckedFile(sourceFile, compilerOptions); - if (isChecked && !isNewIdentifierLocation && (!symbols || symbols.length === 0) && keywordFilters === KeywordCompletionFilters.None) { + if ( + isChecked && !isNewIdentifierLocation && (!symbols || symbols.length === 0) + && keywordFilters === KeywordCompletionFilters.None + ) { return undefined; } const uniqueNames = getCompletionEntriesFromSymbols( @@ -1325,8 +1438,16 @@ function completionInfoFromData( ); if (keywordFilters !== KeywordCompletionFilters.None) { - for (const keywordEntry of getKeywordCompletions(keywordFilters, !insideJsDocTagTypeExpression && isSourceFileJS(sourceFile))) { - if (isTypeOnlyLocation && isTypeKeyword(stringToToken(keywordEntry.name)!) || !uniqueNames.has(keywordEntry.name)) { + for ( + const keywordEntry of getKeywordCompletions( + keywordFilters, + !insideJsDocTagTypeExpression && isSourceFileJS(sourceFile), + ) + ) { + if ( + isTypeOnlyLocation && isTypeKeyword(stringToToken(keywordEntry.name)!) + || !uniqueNames.has(keywordEntry.name) + ) { uniqueNames.add(keywordEntry.name); insertSorted(entries, keywordEntry, compareCompletionEntries, /*allowDuplicates*/ true); } @@ -1358,7 +1479,15 @@ function completionInfoFromData( && !isRightOfDotOrQuestionDot && (caseBlock = findAncestor(contextToken, isCaseBlock)) ) { - const cases = getExhaustiveCaseSnippets(caseBlock, sourceFile, preferences, compilerOptions, host, program, formatContext); + const cases = getExhaustiveCaseSnippets( + caseBlock, + sourceFile, + preferences, + compilerOptions, + host, + program, + formatContext, + ); if (cases) { entries.push(cases.entry); } @@ -1405,7 +1534,8 @@ function getExhaustiveCaseSnippets( Debug.assert(type.symbol, "An enum member type should have a symbol"); Debug.assert(type.symbol.parent, "An enum member type should have a parent symbol (the enum symbol)"); // Filter existing enums by their values - const enumValue = type.symbol.valueDeclaration && checker.getConstantValue(type.symbol.valueDeclaration as EnumMember); + const enumValue = type.symbol.valueDeclaration + && checker.getConstantValue(type.symbol.valueDeclaration as EnumMember); if (enumValue !== undefined) { if (tracker.hasValue(enumValue)) { continue; @@ -1426,13 +1556,30 @@ function getExhaustiveCaseSnippets( else if (!tracker.hasValue(type.value)) { switch (typeof type.value) { case "object": - elements.push(type.value.negative ? factory.createPrefixUnaryExpression(SyntaxKind.MinusToken, factory.createBigIntLiteral({ negative: false, base10Value: type.value.base10Value })) : factory.createBigIntLiteral(type.value)); + elements.push( + type.value.negative + ? factory.createPrefixUnaryExpression( + SyntaxKind.MinusToken, + factory.createBigIntLiteral({ + negative: false, + base10Value: type.value.base10Value, + }), + ) : factory.createBigIntLiteral(type.value), + ); break; case "number": - elements.push(type.value < 0 ? factory.createPrefixUnaryExpression(SyntaxKind.MinusToken, factory.createNumericLiteral(-type.value)) : factory.createNumericLiteral(type.value)); + elements.push( + type.value < 0 + ? factory.createPrefixUnaryExpression( + SyntaxKind.MinusToken, + factory.createNumericLiteral(-type.value), + ) : factory.createNumericLiteral(type.value), + ); break; case "string": - elements.push(factory.createStringLiteral(type.value, quotePreference === QuotePreference.Single)); + elements.push( + factory.createStringLiteral(type.value, quotePreference === QuotePreference.Single), + ); break; } } @@ -1477,14 +1624,26 @@ function getExhaustiveCaseSnippets( return undefined; } -function typeNodeToExpression(typeNode: TypeNode, languageVersion: ScriptTarget, quotePreference: QuotePreference): Expression | undefined { +function typeNodeToExpression( + typeNode: TypeNode, + languageVersion: ScriptTarget, + quotePreference: QuotePreference, +): Expression | undefined { switch (typeNode.kind) { case SyntaxKind.TypeReference: const typeName = (typeNode as TypeReferenceNode).typeName; return entityNameToExpression(typeName, languageVersion, quotePreference); case SyntaxKind.IndexedAccessType: - const objectExpression = typeNodeToExpression((typeNode as IndexedAccessTypeNode).objectType, languageVersion, quotePreference); - const indexExpression = typeNodeToExpression((typeNode as IndexedAccessTypeNode).indexType, languageVersion, quotePreference); + const objectExpression = typeNodeToExpression( + (typeNode as IndexedAccessTypeNode).objectType, + languageVersion, + quotePreference, + ); + const indexExpression = typeNodeToExpression( + (typeNode as IndexedAccessTypeNode).indexType, + languageVersion, + quotePreference, + ); return objectExpression && indexExpression && factory.createElementAccessExpression(objectExpression, indexExpression); @@ -1498,7 +1657,11 @@ function typeNodeToExpression(typeNode: TypeNode, languageVersion: ScriptTarget, } return undefined; case SyntaxKind.ParenthesizedType: - const exp = typeNodeToExpression((typeNode as ParenthesizedTypeNode).type, languageVersion, quotePreference); + const exp = typeNodeToExpression( + (typeNode as ParenthesizedTypeNode).type, + languageVersion, + quotePreference, + ); return exp && (isIdentifier(exp) ? exp : factory.createParenthesizedExpression(exp)); case SyntaxKind.TypeQuery: return entityNameToExpression((typeNode as TypeQueryNode).exprName, languageVersion, quotePreference); @@ -1509,7 +1672,11 @@ function typeNodeToExpression(typeNode: TypeNode, languageVersion: ScriptTarget, return undefined; } -function entityNameToExpression(entityName: EntityName, languageVersion: ScriptTarget, quotePreference: QuotePreference): Expression { +function entityNameToExpression( + entityName: EntityName, + languageVersion: ScriptTarget, + quotePreference: QuotePreference, +): Expression { if (isIdentifier(entityName)) { return entityName; } @@ -1580,7 +1747,13 @@ function getJsxClosingTagCompletion(location: Node | undefined, sourceFile: Sour kindModifiers: undefined, sortText: SortText.LocationPriority, }; - return { isGlobalCompletion: false, isMemberCompletion: true, isNewIdentifierLocation: false, optionalReplacementSpan: replacementSpan, entries: [entry] }; + return { + isGlobalCompletion: false, + isMemberCompletion: true, + isNewIdentifierLocation: false, + optionalReplacementSpan: replacementSpan, + entries: [entry], + }; } return; } @@ -1611,13 +1784,26 @@ function getJSCompletionEntries( }); } -function completionNameForLiteral(sourceFile: SourceFile, preferences: UserPreferences, literal: string | number | PseudoBigInt): string { - return typeof literal === "object" ? pseudoBigIntToString(literal) + "n" : - isString(literal) ? quote(sourceFile, preferences, literal) : JSON.stringify(literal); +function completionNameForLiteral( + sourceFile: SourceFile, + preferences: UserPreferences, + literal: string | number | PseudoBigInt, +): string { + return typeof literal === "object" ? pseudoBigIntToString(literal) + "n" + : isString(literal) ? quote(sourceFile, preferences, literal) : JSON.stringify(literal); } -function createCompletionEntryForLiteral(sourceFile: SourceFile, preferences: UserPreferences, literal: string | number | PseudoBigInt): CompletionEntry { - return { name: completionNameForLiteral(sourceFile, preferences, literal), kind: ScriptElementKind.string, kindModifiers: ScriptElementKindModifier.none, sortText: SortText.LocationPriority }; +function createCompletionEntryForLiteral( + sourceFile: SourceFile, + preferences: UserPreferences, + literal: string | number | PseudoBigInt, +): CompletionEntry { + return { + name: completionNameForLiteral(sourceFile, preferences, literal), + kind: ScriptElementKind.string, + kindModifiers: ScriptElementKindModifier.none, + sortText: SortText.LocationPriority, + }; } function createCompletionEntry( @@ -1667,13 +1853,14 @@ function createCompletionEntry( // We should only have needsConvertPropertyAccess if there's a property access to convert. But see #21790. // Somehow there was a global with a non-identifier name. Hopefully someone will complain about getting a "foo bar" global completion and provide a repro. else if ((useBraces || insertQuestionDot) && propertyAccessToConvert) { - insertText = useBraces ? needsConvertPropertyAccess ? `[${quotePropertyName(sourceFile, preferences, name)}]` : `[${name}]` : name; + insertText = useBraces + ? needsConvertPropertyAccess ? `[${quotePropertyName(sourceFile, preferences, name)}]` : `[${name}]` : name; if (insertQuestionDot || propertyAccessToConvert.questionDotToken) { insertText = `?.${insertText}`; } - const dot = findChildOfKind(propertyAccessToConvert, SyntaxKind.DotToken, sourceFile) || - findChildOfKind(propertyAccessToConvert, SyntaxKind.QuestionDotToken, sourceFile); + const dot = findChildOfKind(propertyAccessToConvert, SyntaxKind.DotToken, sourceFile) + || findChildOfKind(propertyAccessToConvert, SyntaxKind.QuestionDotToken, sourceFile); if (!dot) { return undefined; } @@ -1698,7 +1885,8 @@ function createCompletionEntry( } awaitText += `(await ${propertyAccessToConvert.expression.getText()})`; - insertText = needsConvertPropertyAccess ? `${awaitText}${insertText}` : `${awaitText}${insertQuestionDot ? "?." : "."}${insertText}`; + insertText = needsConvertPropertyAccess ? `${awaitText}${insertText}` + : `${awaitText}${insertQuestionDot ? "?." : "."}${insertText}`; const isInAwaitExpression = tryCast(propertyAccessToConvert.parent, isAwaitExpression); const wrapNode = isInAwaitExpression ? propertyAccessToConvert.parent : propertyAccessToConvert.expression; replacementSpan = createTextSpanFromBounds(wrapNode.getStart(sourceFile), propertyAccessToConvert.end); @@ -1707,7 +1895,15 @@ function createCompletionEntry( if (originIsResolvedExport(origin)) { sourceDisplay = [textPart(origin.moduleSpecifier)]; if (importStatementCompletion) { - ({ insertText, replacementSpan } = getInsertTextAndReplacementSpanForImportCompletion(name, importStatementCompletion, origin, useSemicolons, sourceFile, options, preferences)); + ({ insertText, replacementSpan } = getInsertTextAndReplacementSpanForImportCompletion( + name, + importStatementCompletion, + origin, + useSemicolons, + sourceFile, + options, + preferences, + )); isSnippet = preferences.includeCompletionsWithSnippetText ? true : undefined; } } @@ -1727,14 +1923,19 @@ function createCompletionEntry( // const cc: I = { a: "red" | } // // Completion should add a comma after "red" and provide completions for b - if (completionKind === CompletionKind.ObjectPropertyDeclaration && contextToken && findPrecedingToken(contextToken.pos, sourceFile, contextToken)?.kind !== SyntaxKind.CommaToken) { + if ( + completionKind === CompletionKind.ObjectPropertyDeclaration && contextToken + && findPrecedingToken(contextToken.pos, sourceFile, contextToken)?.kind !== SyntaxKind.CommaToken + ) { if ( - isMethodDeclaration(contextToken.parent.parent) || - isGetAccessorDeclaration(contextToken.parent.parent) || - isSetAccessorDeclaration(contextToken.parent.parent) || - isSpreadAssignment(contextToken.parent) || - findAncestor(contextToken.parent, isPropertyAssignment)?.getLastToken(sourceFile) === contextToken || - isShorthandPropertyAssignment(contextToken.parent) && getLineAndCharacterOfPosition(sourceFile, contextToken.getEnd()).line !== getLineAndCharacterOfPosition(sourceFile, position).line + isMethodDeclaration(contextToken.parent.parent) + || isGetAccessorDeclaration(contextToken.parent.parent) + || isSetAccessorDeclaration(contextToken.parent.parent) + || isSpreadAssignment(contextToken.parent) + || findAncestor(contextToken.parent, isPropertyAssignment)?.getLastToken(sourceFile) === contextToken + || isShorthandPropertyAssignment(contextToken.parent) + && getLineAndCharacterOfPosition(sourceFile, contextToken.getEnd()).line + !== getLineAndCharacterOfPosition(sourceFile, position).line ) { source = CompletionSource.ObjectLiteralMemberWithComma; hasAction = true; @@ -1742,13 +1943,24 @@ function createCompletionEntry( } if ( - preferences.includeCompletionsWithClassMemberSnippets && - preferences.includeCompletionsWithInsertText && - completionKind === CompletionKind.MemberLike && - isClassLikeMemberCompletion(symbol, location, sourceFile) + preferences.includeCompletionsWithClassMemberSnippets + && preferences.includeCompletionsWithInsertText + && completionKind === CompletionKind.MemberLike + && isClassLikeMemberCompletion(symbol, location, sourceFile) ) { let importAdder; - const memberCompletionEntry = getEntryForMemberCompletion(host, program, options, preferences, name, symbol, location, position, contextToken, formatContext); + const memberCompletionEntry = getEntryForMemberCompletion( + host, + program, + options, + preferences, + name, + symbol, + location, + position, + contextToken, + formatContext, + ); if (memberCompletionEntry) { ({ insertText, filterText, isSnippet, importAdder } = memberCompletionEntry); if (importAdder?.hasFixes()) { @@ -1774,7 +1986,8 @@ function createCompletionEntry( if ( isJsxIdentifierExpected && !isRightOfOpenTag && preferences.includeCompletionsWithSnippetText && preferences.jsxAttributeCompletionStyle - && preferences.jsxAttributeCompletionStyle !== "none" && !(isJsxAttribute(location.parent) && location.parent.initializer) + && preferences.jsxAttributeCompletionStyle !== "none" + && !(isJsxAttribute(location.parent) && location.parent.initializer) ) { let useBraces = preferences.jsxAttributeCompletionStyle === "braces"; const type = typeChecker.getTypeOfSymbolAtLocation(symbol, location); @@ -1783,9 +1996,19 @@ function createCompletionEntry( if ( preferences.jsxAttributeCompletionStyle === "auto" && !(type.flags & TypeFlags.BooleanLike) - && !(type.flags & TypeFlags.Union && find((type as UnionType).types, type => !!(type.flags & TypeFlags.BooleanLike))) + && !(type.flags & TypeFlags.Union + && find((type as UnionType).types, type => !!(type.flags & TypeFlags.BooleanLike))) ) { - if (type.flags & TypeFlags.StringLike || (type.flags & TypeFlags.Union && every((type as UnionType).types, type => !!(type.flags & (TypeFlags.StringLike | TypeFlags.Undefined) || isStringAndEmptyAnonymousObjectIntersection(type))))) { + if ( + type.flags & TypeFlags.StringLike + || (type.flags & TypeFlags.Union + && every( + (type as UnionType).types, + type => + !!(type.flags & (TypeFlags.StringLike | TypeFlags.Undefined) + || isStringAndEmptyAnonymousObjectIntersection(type)), + )) + ) { // If is string like or undefined use quotes insertText = `${escapeSnippetText(name)}=${quote(sourceFile, preferences, "$1")}`; isSnippet = true; @@ -1814,7 +2037,10 @@ function createCompletionEntry( const parentNamedImportOrExport = findAncestor(location, isNamedImportsOrExports); if (parentNamedImportOrExport?.kind === SyntaxKind.NamedImports) { const possibleToken = stringToToken(name); - if (parentNamedImportOrExport && possibleToken && (possibleToken === SyntaxKind.AwaitKeyword || isNonContextualKeyword(possibleToken))) { + if ( + parentNamedImportOrExport && possibleToken + && (possibleToken === SyntaxKind.AwaitKeyword || isNonContextualKeyword(possibleToken)) + ) { insertText = `${name} as ${name}_`; } } @@ -1877,21 +2103,21 @@ function isClassLikeMemberCompletion(symbol: Symbol, location: Node, sourceFile: `location` is a syntax list (with modifiers as children), and `location.parent` is a class-like declaration. */ - return !!(symbol.flags & memberFlags) && - ( - isClassLike(location) || - ( - location.parent && - location.parent.parent && - isClassElement(location.parent) && - location === location.parent.name && - location.parent.getLastToken(sourceFile) === location.parent.name && - isClassLike(location.parent.parent) - ) || - ( - location.parent && - isSyntaxList(location) && - isClassLike(location.parent) + return !!(symbol.flags & memberFlags) + && ( + isClassLike(location) + || ( + location.parent + && location.parent.parent + && isClassElement(location.parent) + && location === location.parent.name + && location.parent.getLastToken(sourceFile) === location.parent.name + && isClassLike(location.parent.parent) + ) + || ( + location.parent + && isSyntaxList(location) + && isClassLike(location.parent) ) ); } @@ -1907,7 +2133,13 @@ function getEntryForMemberCompletion( position: number, contextToken: Node | undefined, formatContext: formatting.FormatContext | undefined, -): { insertText: string; filterText?: string; isSnippet?: true; importAdder?: codefix.ImportAdder; eraseRange?: TextRange; } | undefined { +): { + insertText: string; + filterText?: string; + isSnippet?: true; + importAdder?: codefix.ImportAdder; + eraseRange?: TextRange; +} | undefined { const classLikeDeclaration = findAncestor(location, isClassLike); if (!classLikeDeclaration) { return undefined; // This should never happen. @@ -1944,10 +2176,15 @@ function getEntryForMemberCompletion( } let modifiers = ModifierFlags.None; - const { modifiers: presentModifiers, range: eraseRange, decorators: presentDecorators } = getPresentModifiers(contextToken, sourceFile, position); + const { modifiers: presentModifiers, range: eraseRange, decorators: presentDecorators } = getPresentModifiers( + contextToken, + sourceFile, + position, + ); // Whether the suggested member should be abstract. // e.g. in `abstract class C { abstract | }`, we should offer abstract method signatures at position `|`. - const isAbstract = presentModifiers & ModifierFlags.Abstract && classLikeDeclaration.modifierFlagsCache & ModifierFlags.Abstract; + const isAbstract = presentModifiers & ModifierFlags.Abstract + && classLikeDeclaration.modifierFlagsCache & ModifierFlags.Abstract; let completionNodes: codefix.AddNode[] = []; codefix.addNewNodeForMemberSymbol( symbol, @@ -1970,7 +2207,8 @@ function getEntryForMemberCompletion( } if ( isClassElement(node) - && checker.getMemberOverrideModifierStatus(classLikeDeclaration, node, symbol) === MemberOverrideStatus.NeedsOverride + && checker.getMemberOverrideModifierStatus(classLikeDeclaration, node, symbol) + === MemberOverrideStatus.NeedsOverride ) { requiredModifiers |= ModifierFlags.Override; } @@ -2016,7 +2254,10 @@ function getEntryForMemberCompletion( if (presentDecorators?.length) { const lastNode = completionNodes[completionNodes.length - 1]; if (canHaveDecorators(lastNode)) { - completionNodes[completionNodes.length - 1] = factory.updateModifierLike(lastNode, (presentDecorators as ModifierLike[]).concat(getModifiers(lastNode) || [])); + completionNodes[completionNodes.length - 1] = factory.updateModifierLike( + lastNode, + (presentDecorators as ModifierLike[]).concat(getModifiers(lastNode) || []), + ); } } @@ -2049,8 +2290,8 @@ function getPresentModifiers( position: number, ): { modifiers: ModifierFlags; decorators?: Decorator[]; range?: TextRange; } { if ( - !contextToken || - getLineAndCharacterOfPosition(sourceFile, position).line + !contextToken + || getLineAndCharacterOfPosition(sourceFile, position).line > getLineAndCharacterOfPosition(sourceFile, contextToken.getEnd()).line ) { return { modifiers: ModifierFlags.None }; @@ -2134,10 +2375,19 @@ function getEntryForObjectLiteralMethodCompletion( newLine: getNewLineKind(getNewLineOrDefaultFromHost(host, formatContext?.options)), }); if (formatContext) { - insertText = printer.printAndFormatSnippetList(ListFormat.CommaDelimited | ListFormat.AllowTrailingComma, factory.createNodeArray([method], /*hasTrailingComma*/ true), sourceFile, formatContext); + insertText = printer.printAndFormatSnippetList( + ListFormat.CommaDelimited | ListFormat.AllowTrailingComma, + factory.createNodeArray([method], /*hasTrailingComma*/ true), + sourceFile, + formatContext, + ); } else { - insertText = printer.printSnippetList(ListFormat.CommaDelimited | ListFormat.AllowTrailingComma, factory.createNodeArray([method], /*hasTrailingComma*/ true), sourceFile); + insertText = printer.printSnippetList( + ListFormat.CommaDelimited | ListFormat.AllowTrailingComma, + factory.createNodeArray([method], /*hasTrailingComma*/ true), + sourceFile, + ); } const signaturePrinter = createPrinter({ @@ -2178,7 +2428,9 @@ function createObjectLiteralMethod( const name = getSynthesizedDeepClone(getNameOfDeclaration(declaration), /*includeTrivia*/ false) as PropertyName; const type = checker.getWidenedType(checker.getTypeOfSymbolAtLocation(symbol, enclosingDeclaration)); const quotePreference = getQuotePreference(sourceFile, preferences); - const builderFlags = NodeBuilderFlags.OmitThisParameter | (quotePreference === QuotePreference.Single ? NodeBuilderFlags.UseSingleQuotesForStringLiteralType : NodeBuilderFlags.None); + const builderFlags = NodeBuilderFlags.OmitThisParameter + | (quotePreference === QuotePreference.Single ? NodeBuilderFlags.UseSingleQuotesForStringLiteralType + : NodeBuilderFlags.None); switch (declaration.kind) { case SyntaxKind.PropertySignature: @@ -2190,7 +2442,10 @@ function createObjectLiteralMethod( : type; if (effectiveType.flags & TypeFlags.Union) { // Only offer the completion if there's a single function type component. - const functionTypes = filter((effectiveType as UnionType).types, type => checker.getSignaturesOfType(type, SignatureKind.Call).length > 0); + const functionTypes = filter( + (effectiveType as UnionType).types, + type => checker.getSignaturesOfType(type, SignatureKind.Call).length > 0, + ); if (functionTypes.length === 1) { effectiveType = functionTypes[0]; } @@ -2203,7 +2458,12 @@ function createObjectLiteralMethod( // We don't support overloads in object literals. return undefined; } - const typeNode = checker.typeToTypeNode(effectiveType, enclosingDeclaration, builderFlags, codefix.getNoopSymbolTrackerWithResolver({ program, host })); + const typeNode = checker.typeToTypeNode( + effectiveType, + enclosingDeclaration, + builderFlags, + codefix.getNoopSymbolTrackerWithResolver({ program, host }), + ); if (!typeNode || !isFunctionTypeNode(typeNode)) { return undefined; } @@ -2391,7 +2651,9 @@ function createSnippetPrinter( } } -function originToCompletionEntryData(origin: SymbolOriginInfoExport | SymbolOriginInfoResolvedExport): CompletionEntryData | undefined { +function originToCompletionEntryData( + origin: SymbolOriginInfoExport | SymbolOriginInfoResolvedExport, +): CompletionEntryData | undefined { const ambientModuleName = origin.fileName ? undefined : stripQuotes(origin.moduleSymbol.name); const isPackageJsonImport = origin.isFromPackageJson ? true : undefined; if (originIsResolvedExport(origin)) { @@ -2415,7 +2677,11 @@ function originToCompletionEntryData(origin: SymbolOriginInfoExport | SymbolOrig return unresolvedData; } -function completionEntryDataToSymbolOriginInfo(data: CompletionEntryData, completionName: string, moduleSymbol: Symbol): SymbolOriginInfoExport | SymbolOriginInfoResolvedExport { +function completionEntryDataToSymbolOriginInfo( + data: CompletionEntryData, + completionName: string, + moduleSymbol: Symbol, +): SymbolOriginInfoExport | SymbolOriginInfoResolvedExport { const isDefaultExport = data.exportName === InternalSymbolName.Default; const isFromPackageJson = !!data.isPackageJsonImport; if (completionEntryDataIsResolved(data)) { @@ -2445,27 +2711,56 @@ function completionEntryDataToSymbolOriginInfo(data: CompletionEntryData, comple return unresolvedOrigin; } -function getInsertTextAndReplacementSpanForImportCompletion(name: string, importStatementCompletion: ImportStatementCompletionInfo, origin: SymbolOriginInfoResolvedExport, useSemicolons: boolean, sourceFile: SourceFile, options: CompilerOptions, preferences: UserPreferences) { +function getInsertTextAndReplacementSpanForImportCompletion( + name: string, + importStatementCompletion: ImportStatementCompletionInfo, + origin: SymbolOriginInfoResolvedExport, + useSemicolons: boolean, + sourceFile: SourceFile, + options: CompilerOptions, + preferences: UserPreferences, +) { const replacementSpan = importStatementCompletion.replacementSpan; const quotedModuleSpecifier = escapeSnippetText(quote(sourceFile, preferences, origin.moduleSpecifier)); - const exportKind = origin.isDefaultExport ? ExportKind.Default : - origin.exportName === InternalSymbolName.ExportEquals ? ExportKind.ExportEquals : - ExportKind.Named; + const exportKind = origin.isDefaultExport ? ExportKind.Default + : origin.exportName === InternalSymbolName.ExportEquals ? ExportKind.ExportEquals + : ExportKind.Named; const tabStop = preferences.includeCompletionsWithSnippetText ? "$1" : ""; const importKind = codefix.getImportKind(sourceFile, exportKind, options, /*forceImportKeyword*/ true); const isImportSpecifierTypeOnly = importStatementCompletion.couldBeTypeOnlyImportSpecifier; - const topLevelTypeOnlyText = importStatementCompletion.isTopLevelTypeOnly ? ` ${tokenToString(SyntaxKind.TypeKeyword)} ` : " "; + const topLevelTypeOnlyText = importStatementCompletion.isTopLevelTypeOnly + ? ` ${tokenToString(SyntaxKind.TypeKeyword)} ` : " "; const importSpecifierTypeOnlyText = isImportSpecifierTypeOnly ? `${tokenToString(SyntaxKind.TypeKeyword)} ` : ""; const suffix = useSemicolons ? ";" : ""; switch (importKind) { case ImportKind.CommonJS: - return { replacementSpan, insertText: `import${topLevelTypeOnlyText}${escapeSnippetText(name)}${tabStop} = require(${quotedModuleSpecifier})${suffix}` }; + return { + replacementSpan, + insertText: `import${topLevelTypeOnlyText}${ + escapeSnippetText(name) + }${tabStop} = require(${quotedModuleSpecifier})${suffix}`, + }; case ImportKind.Default: - return { replacementSpan, insertText: `import${topLevelTypeOnlyText}${escapeSnippetText(name)}${tabStop} from ${quotedModuleSpecifier}${suffix}` }; + return { + replacementSpan, + insertText: `import${topLevelTypeOnlyText}${ + escapeSnippetText(name) + }${tabStop} from ${quotedModuleSpecifier}${suffix}`, + }; case ImportKind.Namespace: - return { replacementSpan, insertText: `import${topLevelTypeOnlyText}* as ${escapeSnippetText(name)} from ${quotedModuleSpecifier}${suffix}` }; + return { + replacementSpan, + insertText: `import${topLevelTypeOnlyText}* as ${ + escapeSnippetText(name) + } from ${quotedModuleSpecifier}${suffix}`, + }; case ImportKind.Named: - return { replacementSpan, insertText: `import${topLevelTypeOnlyText}{ ${importSpecifierTypeOnlyText}${escapeSnippetText(name)}${tabStop} } from ${quotedModuleSpecifier}${suffix}` }; + return { + replacementSpan, + insertText: `import${topLevelTypeOnlyText}{ ${importSpecifierTypeOnlyText}${ + escapeSnippetText(name) + }${tabStop} } from ${quotedModuleSpecifier}${suffix}`, + }; } } @@ -2477,9 +2772,14 @@ function quotePropertyName(sourceFile: SourceFile, preferences: UserPreferences, return quote(sourceFile, preferences, name); } -function isRecommendedCompletionMatch(localSymbol: Symbol, recommendedCompletion: Symbol | undefined, checker: TypeChecker): boolean { - return localSymbol === recommendedCompletion || - !!(localSymbol.flags & SymbolFlags.ExportValue) && checker.getExportSymbolOfSymbol(localSymbol) === recommendedCompletion; +function isRecommendedCompletionMatch( + localSymbol: Symbol, + recommendedCompletion: Symbol | undefined, + checker: TypeChecker, +): boolean { + return localSymbol === recommendedCompletion + || !!(localSymbol.flags & SymbolFlags.ExportValue) + && checker.getExportSymbolOfSymbol(localSymbol) === recommendedCompletion; } function getSourceFromOrigin(origin: SymbolOriginInfo | undefined): string | undefined { @@ -2539,7 +2839,11 @@ export function getCompletionEntriesFromSymbols( const symbol = symbols[i]; const origin = symbolToOriginInfoMap?.[i]; const info = getCompletionEntryDisplayNameForSymbol(symbol, target, origin, kind, !!jsxIdentifierExpected); - if (!info || (uniques.get(info.name) && (!origin || !originIsObjectLiteralMethod(origin))) || kind === CompletionKind.Global && symbolToSortTextMap && !shouldIncludeSymbol(symbol, symbolToSortTextMap)) { + if ( + !info || (uniques.get(info.name) && (!origin || !originIsObjectLiteralMethod(origin))) + || kind === CompletionKind.Global && symbolToSortTextMap + && !shouldIncludeSymbol(symbol, symbolToSortTextMap) + ) { continue; } @@ -2577,7 +2881,9 @@ export function getCompletionEntriesFromSymbols( } /** True for locals; false for globals, module exports from other files, `this.` completions. */ - const shouldShadowLaterSymbols = (!origin || originIsTypeOnlyAlias(origin)) && !(symbol.parent === undefined && !some(symbol.declarations, d => d.getSourceFile() === location.getSourceFile())); + const shouldShadowLaterSymbols = (!origin || originIsTypeOnlyAlias(origin)) + && !(symbol.parent === undefined + && !some(symbol.declarations, d => d.getSourceFile() === location.getSourceFile())); uniques.set(name, shouldShadowLaterSymbols); insertSorted(entries, entry, compareCompletionEntries, /*allowDuplicates*/ true); } @@ -2601,7 +2907,10 @@ export function getCompletionEntriesFromSymbols( } // Filter out variables from their own initializers // `const a = /* no 'a' here */` - if (tryCast(variableOrParameterDeclaration, isVariableDeclaration) && symbol.valueDeclaration === variableOrParameterDeclaration) { + if ( + tryCast(variableOrParameterDeclaration, isVariableDeclaration) + && symbol.valueDeclaration === variableOrParameterDeclaration + ) { return false; } @@ -2611,15 +2920,20 @@ export function getCompletionEntriesFromSymbols( const symbolDeclaration = symbol.valueDeclaration ?? symbol.declarations?.[0]; if ( variableOrParameterDeclaration && symbolDeclaration && ( - (isTypeParameterDeclaration(variableOrParameterDeclaration) && isTypeParameterDeclaration(symbolDeclaration)) || - (isParameter(variableOrParameterDeclaration) && isParameter(symbolDeclaration)) + (isTypeParameterDeclaration(variableOrParameterDeclaration) + && isTypeParameterDeclaration(symbolDeclaration)) + || (isParameter(variableOrParameterDeclaration) && isParameter(symbolDeclaration)) ) ) { const symbolDeclarationPos = symbolDeclaration.pos; - const parameters = isParameter(variableOrParameterDeclaration) ? variableOrParameterDeclaration.parent.parameters : - isInferTypeNode(variableOrParameterDeclaration.parent) ? undefined : - variableOrParameterDeclaration.parent.typeParameters; - if (symbolDeclarationPos >= variableOrParameterDeclaration.pos && parameters && symbolDeclarationPos < parameters.end) { + const parameters = isParameter(variableOrParameterDeclaration) + ? variableOrParameterDeclaration.parent.parameters + : isInferTypeNode(variableOrParameterDeclaration.parent) ? undefined + : variableOrParameterDeclaration.parent.typeParameters; + if ( + symbolDeclarationPos >= variableOrParameterDeclaration.pos && parameters + && symbolDeclarationPos < parameters.end + ) { return false; } } @@ -2711,7 +3025,13 @@ function getSymbolCompletionFromEntryId( entryId: CompletionEntryIdentifier, host: LanguageServiceHost, preferences: UserPreferences, -): SymbolCompletion | { type: "request"; request: Request; } | { type: "literal"; literal: string | number | PseudoBigInt; } | { type: "cases"; } | { type: "none"; } { +): + | SymbolCompletion + | { type: "request"; request: Request; } + | { type: "literal"; literal: string | number | PseudoBigInt; } + | { type: "cases"; } + | { type: "none"; } +{ if (entryId.source === CompletionSource.SwitchCases) { return { type: "cases" }; } @@ -2733,7 +3053,17 @@ function getSymbolCompletionFromEntryId( } const compilerOptions = program.getCompilerOptions(); - const completionData = getCompletionData(program, log, sourceFile, compilerOptions, position, { includeCompletionsForModuleExports: true, includeCompletionsWithInsertText: true }, entryId, host, /*formatContext*/ undefined); + const completionData = getCompletionData( + program, + log, + sourceFile, + compilerOptions, + position, + { includeCompletionsForModuleExports: true, includeCompletionsWithInsertText: true }, + entryId, + host, + /*formatContext*/ undefined, + ); if (!completionData) { return { type: "none" }; } @@ -2741,7 +3071,17 @@ function getSymbolCompletionFromEntryId( return { type: "request", request: completionData }; } - const { symbols, literals, location, completionKind, symbolToOriginInfoMap, contextToken, previousToken, isJsxInitializer, isTypeOnlyLocation } = completionData; + const { + symbols, + literals, + location, + completionKind, + symbolToOriginInfoMap, + contextToken, + previousToken, + isJsxInitializer, + isTypeOnlyLocation, + } = completionData; const literal = find(literals, l => completionNameForLiteral(sourceFile, preferences, l) === entryId.name); if (literal !== undefined) return { type: "literal", literal }; @@ -2752,14 +3092,30 @@ function getSymbolCompletionFromEntryId( // completion entry. return firstDefined(symbols, (symbol, index): SymbolCompletion | undefined => { const origin = symbolToOriginInfoMap[index]; - const info = getCompletionEntryDisplayNameForSymbol(symbol, getEmitScriptTarget(compilerOptions), origin, completionKind, completionData.isJsxIdentifierExpected); + const info = getCompletionEntryDisplayNameForSymbol( + symbol, + getEmitScriptTarget(compilerOptions), + origin, + completionKind, + completionData.isJsxIdentifierExpected, + ); return info && info.name === entryId.name && ( entryId.source === CompletionSource.ClassMemberSnippet && symbol.flags & SymbolFlags.ClassMember - || entryId.source === CompletionSource.ObjectLiteralMethodSnippet && symbol.flags & (SymbolFlags.Property | SymbolFlags.Method) + || entryId.source === CompletionSource.ObjectLiteralMethodSnippet + && symbol.flags & (SymbolFlags.Property | SymbolFlags.Method) || getSourceFromOrigin(origin) === entryId.source || entryId.source === CompletionSource.ObjectLiteralMemberWithComma ) - ? { type: "symbol" as const, symbol, location, origin, contextToken, previousToken, isJsxInitializer, isTypeOnlyLocation } + ? { + type: "symbol" as const, + symbol, + location, + origin, + contextToken, + previousToken, + isJsxInitializer, + isTypeOnlyLocation, + } : undefined; }) || { type: "none" }; } @@ -2789,11 +3145,29 @@ export function getCompletionEntryDetails( const { previousToken, contextToken } = getRelevantTokens(position, sourceFile); if (isInString(sourceFile, position, previousToken)) { - return StringCompletions.getStringLiteralCompletionDetails(name, sourceFile, position, previousToken, typeChecker, compilerOptions, host, cancellationToken, preferences); + return StringCompletions.getStringLiteralCompletionDetails( + name, + sourceFile, + position, + previousToken, + typeChecker, + compilerOptions, + host, + cancellationToken, + preferences, + ); } // Compute all the completion symbols again. - const symbolCompletion = getSymbolCompletionFromEntryId(program, log, sourceFile, position, entryId, host, preferences); + const symbolCompletion = getSymbolCompletionFromEntryId( + program, + log, + sourceFile, + position, + entryId, + host, + preferences, + ); switch (symbolCompletion.type) { case "request": { const { request } = symbolCompletion; @@ -2805,20 +3179,53 @@ export function getCompletionEntryDetails( case CompletionDataKind.JsDocParameterName: return JsDoc.getJSDocParameterNameCompletionDetails(name); case CompletionDataKind.Keywords: - return some(request.keywordCompletions, c => c.name === name) ? createSimpleDetails(name, ScriptElementKind.keyword, SymbolDisplayPartKind.keyword) : undefined; + return some(request.keywordCompletions, c => c.name === name) + ? createSimpleDetails(name, ScriptElementKind.keyword, SymbolDisplayPartKind.keyword) + : undefined; default: return Debug.assertNever(request); } } case "symbol": { const { symbol, location, contextToken, origin, previousToken } = symbolCompletion; - const { codeActions, sourceDisplay } = getCompletionEntryCodeActionsAndSourceDisplay(name, location, contextToken, origin, symbol, program, host, compilerOptions, sourceFile, position, previousToken, formatContext, preferences, data, source, cancellationToken); + const { codeActions, sourceDisplay } = getCompletionEntryCodeActionsAndSourceDisplay( + name, + location, + contextToken, + origin, + symbol, + program, + host, + compilerOptions, + sourceFile, + position, + previousToken, + formatContext, + preferences, + data, + source, + cancellationToken, + ); const symbolName = originIsComputedPropertyName(origin) ? origin.symbolName : symbol.name; - return createCompletionDetailsForSymbol(symbol, symbolName, typeChecker, sourceFile, location, cancellationToken, codeActions, sourceDisplay); // TODO: GH#18217 + return createCompletionDetailsForSymbol( + symbol, + symbolName, + typeChecker, + sourceFile, + location, + cancellationToken, + codeActions, + sourceDisplay, + ); // TODO: GH#18217 } case "literal": { const { literal } = symbolCompletion; - return createSimpleDetails(completionNameForLiteral(sourceFile, preferences, literal), ScriptElementKind.string, typeof literal === "string" ? SymbolDisplayPartKind.stringLiteral : SymbolDisplayPartKind.numericLiteral); + return createSimpleDetails( + completionNameForLiteral(sourceFile, preferences, literal), + ScriptElementKind.string, + typeof literal === "string" ? SymbolDisplayPartKind.stringLiteral + : SymbolDisplayPartKind.numericLiteral, + ); } case "cases": { const { entry, importAdder } = getExhaustiveCaseSnippets( @@ -2857,24 +3264,67 @@ export function getCompletionEntryDetails( } case "none": // Didn't find a symbol with this name. See if we can find a keyword instead. - return allKeywordsCompletions().some(c => c.name === name) ? createSimpleDetails(name, ScriptElementKind.keyword, SymbolDisplayPartKind.keyword) : undefined; + return allKeywordsCompletions().some(c => c.name === name) + ? createSimpleDetails(name, ScriptElementKind.keyword, SymbolDisplayPartKind.keyword) : undefined; default: Debug.assertNever(symbolCompletion); } } -function createSimpleDetails(name: string, kind: ScriptElementKind, kind2: SymbolDisplayPartKind): CompletionEntryDetails { +function createSimpleDetails( + name: string, + kind: ScriptElementKind, + kind2: SymbolDisplayPartKind, +): CompletionEntryDetails { return createCompletionDetails(name, ScriptElementKindModifier.none, kind, [displayPart(name, kind2)]); } /** @internal */ -export function createCompletionDetailsForSymbol(symbol: Symbol, name: string, checker: TypeChecker, sourceFile: SourceFile, location: Node, cancellationToken: CancellationToken, codeActions?: CodeAction[], sourceDisplay?: SymbolDisplayPart[]): CompletionEntryDetails { - const { displayParts, documentation, symbolKind, tags } = checker.runWithCancellationToken(cancellationToken, checker => SymbolDisplay.getSymbolDisplayPartsDocumentationAndSymbolKind(checker, symbol, sourceFile, location, location, SemanticMeaning.All)); - return createCompletionDetails(name, SymbolDisplay.getSymbolModifiers(checker, symbol), symbolKind, displayParts, documentation, tags, codeActions, sourceDisplay); +export function createCompletionDetailsForSymbol( + symbol: Symbol, + name: string, + checker: TypeChecker, + sourceFile: SourceFile, + location: Node, + cancellationToken: CancellationToken, + codeActions?: CodeAction[], + sourceDisplay?: SymbolDisplayPart[], +): CompletionEntryDetails { + const { displayParts, documentation, symbolKind, tags } = checker.runWithCancellationToken( + cancellationToken, + checker => + SymbolDisplay.getSymbolDisplayPartsDocumentationAndSymbolKind( + checker, + symbol, + sourceFile, + location, + location, + SemanticMeaning.All, + ), + ); + return createCompletionDetails( + name, + SymbolDisplay.getSymbolModifiers(checker, symbol), + symbolKind, + displayParts, + documentation, + tags, + codeActions, + sourceDisplay, + ); } /** @internal */ -export function createCompletionDetails(name: string, kindModifiers: string, kind: ScriptElementKind, displayParts: SymbolDisplayPart[], documentation?: SymbolDisplayPart[], tags?: JSDocTagInfo[], codeActions?: CodeAction[], source?: SymbolDisplayPart[]): CompletionEntryDetails { +export function createCompletionDetails( + name: string, + kindModifiers: string, + kind: ScriptElementKind, + displayParts: SymbolDisplayPart[], + documentation?: SymbolDisplayPart[], + tags?: JSDocTagInfo[], + codeActions?: CodeAction[], + source?: SymbolDisplayPart[], +): CompletionEntryDetails { return { name, kindModifiers, kind, displayParts, documentation, tags, codeActions, source, sourceDisplay: source }; } @@ -2901,7 +3351,9 @@ function getCompletionEntryCodeActionsAndSourceDisplay( cancellationToken: CancellationToken, ): CodeActionsAndSourceDisplay { if (data?.moduleSpecifier) { - if (previousToken && getImportStatementCompletionInfo(contextToken || previousToken, sourceFile).replacementSpan) { + if ( + previousToken && getImportStatementCompletionInfo(contextToken || previousToken, sourceFile).replacementSpan + ) { // Import statement completion: 'import c|' return { codeActions: undefined, sourceDisplay: [textPart(data.moduleSpecifier)] }; } @@ -2967,7 +3419,10 @@ function getCompletionEntryCodeActionsAndSourceDisplay( sourceDisplay: undefined, codeActions: [{ changes, - description: diagnosticToString([Diagnostics.Add_missing_comma_for_object_member_completion_0, name]), + description: diagnosticToString([ + Diagnostics.Add_missing_comma_for_object_member_completion_0, + name, + ]), }], }; } @@ -2977,10 +3432,12 @@ function getCompletionEntryCodeActionsAndSourceDisplay( return { codeActions: undefined, sourceDisplay: undefined }; } - const checker = origin.isFromPackageJson ? host.getPackageJsonAutoImportProvider!()!.getTypeChecker() : program.getTypeChecker(); + const checker = origin.isFromPackageJson ? host.getPackageJsonAutoImportProvider!()!.getTypeChecker() + : program.getTypeChecker(); const { moduleSymbol } = origin; const targetSymbol = checker.getMergedSymbol(skipAlias(symbol.exportSymbol || symbol, checker)); - const isJsxOpeningTagName = contextToken?.kind === SyntaxKind.LessThanToken && isJsxOpeningLikeElement(contextToken.parent); + const isJsxOpeningTagName = contextToken?.kind === SyntaxKind.LessThanToken + && isJsxOpeningLikeElement(contextToken.parent); const { moduleSpecifier, codeAction } = codefix.getImportCompletionAction( targetSymbol, moduleSymbol, @@ -3056,7 +3513,11 @@ interface CompletionData { type Request = | { readonly kind: CompletionDataKind.JsDocTagName | CompletionDataKind.JsDocTag; } | { readonly kind: CompletionDataKind.JsDocParameterName; tag: JSDocParameterTag; } - | { readonly kind: CompletionDataKind.Keywords; keywordCompletions: readonly CompletionEntry[]; isNewIdentifierLocation: boolean; }; + | { + readonly kind: CompletionDataKind.Keywords; + keywordCompletions: readonly CompletionEntry[]; + isNewIdentifierLocation: boolean; + }; /** @internal */ export const enum CompletionKind { @@ -3070,16 +3531,26 @@ export const enum CompletionKind { function getRecommendedCompletion(previousToken: Node, contextualType: Type, checker: TypeChecker): Symbol | undefined { // For a union, return the first one with a recommended completion. - return firstDefined(contextualType && (contextualType.isUnion() ? contextualType.types : [contextualType]), type => { - const symbol = type && type.symbol; - // Don't include make a recommended completion for an abstract class - return symbol && (symbol.flags & (SymbolFlags.EnumMember | SymbolFlags.Enum | SymbolFlags.Class) && !isAbstractConstructorSymbol(symbol)) - ? getFirstSymbolInChain(symbol, previousToken, checker) - : undefined; - }); + return firstDefined( + contextualType && (contextualType.isUnion() ? contextualType.types : [contextualType]), + type => { + const symbol = type && type.symbol; + // Don't include make a recommended completion for an abstract class + return symbol + && (symbol.flags & (SymbolFlags.EnumMember | SymbolFlags.Enum | SymbolFlags.Class) + && !isAbstractConstructorSymbol(symbol)) + ? getFirstSymbolInChain(symbol, previousToken, checker) + : undefined; + }, + ); } -function getContextualType(previousToken: Node, position: number, sourceFile: SourceFile, checker: TypeChecker): Type | undefined { +function getContextualType( + previousToken: Node, + position: number, + sourceFile: SourceFile, + checker: TypeChecker, +): Type | undefined { const { parent } = previousToken; switch (previousToken.kind) { case SyntaxKind.Identifier: @@ -3101,23 +3572,36 @@ function getContextualType(previousToken: Node, position: number, sourceFile: So const caseClause = tryCast(parent, isCaseClause); return caseClause ? getSwitchedType(caseClause, checker) : undefined; case SyntaxKind.OpenBraceToken: - return isJsxExpression(parent) && !isJsxElement(parent.parent) && !isJsxFragment(parent.parent) ? checker.getContextualTypeForJsxAttribute(parent.parent) : undefined; + return isJsxExpression(parent) && !isJsxElement(parent.parent) && !isJsxFragment(parent.parent) + ? checker.getContextualTypeForJsxAttribute(parent.parent) : undefined; default: const argInfo = SignatureHelp.getArgumentInfoForCompletions(previousToken, position, sourceFile); - return argInfo ? + return argInfo // At `,`, treat this as the next argument after the comma. - checker.getContextualTypeForArgumentAtIndex(argInfo.invocation, argInfo.argumentIndex + (previousToken.kind === SyntaxKind.CommaToken ? 1 : 0)) : - isEqualityOperatorKind(previousToken.kind) && isBinaryExpression(parent) && isEqualityOperatorKind(parent.operatorToken.kind) ? + ? checker.getContextualTypeForArgumentAtIndex( + argInfo.invocation, + argInfo.argumentIndex + (previousToken.kind === SyntaxKind.CommaToken ? 1 : 0), + ) + : isEqualityOperatorKind(previousToken.kind) && isBinaryExpression(parent) + && isEqualityOperatorKind(parent.operatorToken.kind) // completion at `x ===/**/` should be for the right side - checker.getTypeAtLocation(parent.left) : - checker.getContextualType(previousToken as Expression, ContextFlags.Completions) || checker.getContextualType(previousToken as Expression); + ? checker.getTypeAtLocation(parent.left) + : checker.getContextualType(previousToken as Expression, ContextFlags.Completions) + || checker.getContextualType(previousToken as Expression); } } function getFirstSymbolInChain(symbol: Symbol, enclosingDeclaration: Node, checker: TypeChecker): Symbol | undefined { - const chain = checker.getAccessibleSymbolChain(symbol, enclosingDeclaration, /*meaning*/ SymbolFlags.All, /*useOnlyExternalAliasing*/ false); + const chain = checker.getAccessibleSymbolChain( + symbol, + enclosingDeclaration, + /*meaning*/ SymbolFlags.All, + /*useOnlyExternalAliasing*/ false, + ); if (chain) return first(chain); - return symbol.parent && (isModuleSymbol(symbol.parent) ? symbol : getFirstSymbolInChain(symbol.parent, enclosingDeclaration, checker)); + return symbol.parent + && (isModuleSymbol(symbol.parent) ? symbol + : getFirstSymbolInChain(symbol.parent, enclosingDeclaration, checker)); } function isModuleSymbol(symbol: Symbol): boolean { @@ -3193,16 +3677,19 @@ function getCompletionData( if (typeExpression) { currentToken = getTokenAtPosition(sourceFile, position); if ( - !currentToken || - (!isDeclarationName(currentToken) && - (currentToken.parent.kind !== SyntaxKind.JSDocPropertyTag || - (currentToken.parent as JSDocPropertyTag).name !== currentToken)) + !currentToken + || (!isDeclarationName(currentToken) + && (currentToken.parent.kind !== SyntaxKind.JSDocPropertyTag + || (currentToken.parent as JSDocPropertyTag).name !== currentToken)) ) { // Use as type location if inside tag's type expression insideJsDocTagTypeExpression = isCurrentlyEditingNode(typeExpression); } } - if (!insideJsDocTagTypeExpression && isJSDocParameterTag(tag) && (nodeIsMissing(tag.name) || tag.name.pos <= position && position <= tag.name.end)) { + if ( + !insideJsDocTagTypeExpression && isJSDocParameterTag(tag) + && (nodeIsMissing(tag.name) || tag.name.pos <= position && position <= tag.name.end) + ) { return { kind: CompletionDataKind.JsDocParameterName, tag }; } } @@ -3253,7 +3740,10 @@ function getCompletionData( } keywordFilters = keywordFiltersFromSyntaxKind(importStatementCompletionInfo.keywordCompletion); } - if (importStatementCompletionInfo.replacementSpan && preferences.includeCompletionsForImportStatements && preferences.includeCompletionsWithInsertText) { + if ( + importStatementCompletionInfo.replacementSpan && preferences.includeCompletionsForImportStatements + && preferences.includeCompletionsWithInsertText + ) { // Import statement completions use `insertText`, and also require the `data` property of `CompletionEntryIdentifier` // added in TypeScript 4.3 to be sent back from the client during `getCompletionEntryDetails`. Since this feature // is not backward compatible with older clients, the language service defaults to disabling it, allowing newer clients @@ -3280,11 +3770,11 @@ function getCompletionData( node = propertyAccessToConvert.expression; const leftmostAccessExpression = getLeftmostAccessExpression(propertyAccessToConvert); if ( - nodeIsMissing(leftmostAccessExpression) || - ((isCallExpression(node) || isFunctionLike(node)) && - node.end === contextToken.pos && - node.getChildCount(sourceFile) && - last(node.getChildren(sourceFile)).kind !== SyntaxKind.CloseParenToken) + nodeIsMissing(leftmostAccessExpression) + || ((isCallExpression(node) || isFunctionLike(node)) + && node.end === contextToken.pos + && node.getChildCount(sourceFile) + && last(node.getChildren(sourceFile)).kind !== SyntaxKind.CloseParenToken) ) { // This is likely dot from incorrectly parsed expression and user is starting to write spread // eg: Math.min(./**/) @@ -3325,7 +3815,10 @@ function getCompletionData( if (currentToken.parent === location) { switch (currentToken.kind) { case SyntaxKind.GreaterThanToken: - if (currentToken.parent.kind === SyntaxKind.JsxElement || currentToken.parent.kind === SyntaxKind.JsxOpeningElement) { + if ( + currentToken.parent.kind === SyntaxKind.JsxElement + || currentToken.parent.kind === SyntaxKind.JsxOpeningElement + ) { location = currentToken; } break; @@ -3368,7 +3861,11 @@ function getCompletionData( // `parent` will be `{true}` and `previousToken` will be `}` // Second case is for `
` // Second case must not match for `
` - if (previousToken.kind === SyntaxKind.CloseBraceToken || (previousToken.kind === SyntaxKind.Identifier && previousToken.parent.kind === SyntaxKind.JsxAttribute)) { + if ( + previousToken.kind === SyntaxKind.CloseBraceToken + || (previousToken.kind === SyntaxKind.Identifier + && previousToken.parent.kind === SyntaxKind.JsxAttribute) + ) { isJsxIdentifierExpected = true; } break; @@ -3376,8 +3873,8 @@ function getCompletionData( case SyntaxKind.JsxAttribute: // For `
`, `parent` will be JsxAttribute and `previousToken` will be its initializer if ( - (parent as JsxAttribute).initializer === previousToken && - previousToken.end < position + (parent as JsxAttribute).initializer === previousToken + && previousToken.end < position ) { isJsxIdentifierExpected = true; break; @@ -3391,9 +3888,9 @@ function getCompletionData( // For `
` we don't want to treat this as a jsx inializer, instead it's the attribute name. if ( - parent !== previousToken.parent && - !(parent as JsxAttribute).initializer && - findChildOfKind(parent, SyntaxKind.EqualsToken, sourceFile) + parent !== previousToken.parent + && !(parent as JsxAttribute).initializer + && findChildOfKind(parent, SyntaxKind.EqualsToken, sourceFile) ) { isJsxInitializer = previousToken as Identifier; } @@ -3415,7 +3912,10 @@ function getCompletionData( const seenPropertySymbols = new Map(); const isTypeOnlyLocation = isTypeOnlyCompletion(); const getModuleSpecifierResolutionHost = memoizeOne((isFromPackageJson: boolean) => { - return createModuleSpecifierResolutionHost(isFromPackageJson ? host.getPackageJsonAutoImportProvider!()! : program, host); + return createModuleSpecifierResolutionHost( + isFromPackageJson ? host.getPackageJsonAutoImportProvider!()! : program, + host, + ); }); if (isRightOfDot || isRightOfQuestionDot) { @@ -3459,7 +3959,8 @@ function getCompletionData( t => t.isLiteral() && !(t.flags & TypeFlags.EnumLiteral) ? t.value : undefined, ); - const recommendedCompletion = previousToken && contextualType && getRecommendedCompletion(previousToken, contextualType, typeChecker); + const recommendedCompletion = previousToken && contextualType + && getRecommendedCompletion(previousToken, contextualType, typeChecker); return { kind: CompletionDataKind.Data, symbols, @@ -3516,7 +4017,8 @@ function getCompletionData( function tryGetTypeExpressionFromTag(tag: JSDocTag): JSDocTypeExpression | ExpressionWithTypeArguments | undefined { if (isTagWithTypeExpression(tag)) { const typeExpression = isJSDocTemplateTag(tag) ? tag.constraint : tag.typeExpression; - return typeExpression && typeExpression.kind === SyntaxKind.JSDocTypeExpression ? typeExpression : undefined; + return typeExpression && typeExpression.kind === SyntaxKind.JSDocTypeExpression ? typeExpression + : undefined; } if (isJSDocAugmentsTag(tag) || isJSDocImplementsTag(tag)) { return tag.class; @@ -3544,15 +4046,22 @@ function getCompletionData( // Extract module or enum members const exportedSymbols = typeChecker.getExportsOfModule(symbol); Debug.assertEachIsDefined(exportedSymbols, "getExportsOfModule() should all be defined"); - const isValidValueAccess = (symbol: Symbol) => typeChecker.isValidPropertyAccess(isImportType ? node as ImportTypeNode : (node.parent as PropertyAccessExpression), symbol.name); - const isValidTypeAccess = (symbol: Symbol) => symbolCanBeReferencedAtTypeLocation(symbol, typeChecker); + const isValidValueAccess = (symbol: Symbol) => + typeChecker.isValidPropertyAccess( + isImportType ? node as ImportTypeNode : (node.parent as PropertyAccessExpression), + symbol.name, + ); + const isValidTypeAccess = (symbol: Symbol) => + symbolCanBeReferencedAtTypeLocation(symbol, typeChecker); const isValidAccess: (symbol: Symbol) => boolean = isNamespaceName // At `namespace N.M/**/`, if this is the only declaration of `M`, don't include `M` as a completion. - ? symbol => !!(symbol.flags & SymbolFlags.Namespace) && !symbol.declarations?.every(d => d.parent === node.parent) - : isRhsOfImportDeclaration ? + ? symbol => + !!(symbol.flags & SymbolFlags.Namespace) + && !symbol.declarations?.every(d => d.parent === node.parent) + : isRhsOfImportDeclaration // Any kind is allowed when dotting off namespace in internal import equals declaration - symbol => isValidTypeAccess(symbol) || isValidValueAccess(symbol) : - isTypeLocation || insideJsDocTagTypeExpression ? isValidTypeAccess : isValidValueAccess; + ? symbol => isValidTypeAccess(symbol) || isValidValueAccess(symbol) + : isTypeLocation || insideJsDocTagTypeExpression ? isValidTypeAccess : isValidValueAccess; for (const exportedSymbol of exportedSymbols) { if (isValidAccess(exportedSymbol)) { symbols.push(exportedSymbol); @@ -3561,17 +4070,20 @@ function getCompletionData( // If the module is merged with a value, we must get the type of the class and add its propertes (for inherited static methods). if ( - !isTypeLocation && - !insideJsDocTagTypeExpression && - symbol.declarations && - symbol.declarations.some(d => d.kind !== SyntaxKind.SourceFile && d.kind !== SyntaxKind.ModuleDeclaration && d.kind !== SyntaxKind.EnumDeclaration) + !isTypeLocation + && !insideJsDocTagTypeExpression + && symbol.declarations + && symbol.declarations.some(d => + d.kind !== SyntaxKind.SourceFile && d.kind !== SyntaxKind.ModuleDeclaration + && d.kind !== SyntaxKind.EnumDeclaration + ) ) { let type = typeChecker.getTypeOfSymbolAtLocation(symbol, node).getNonOptionalType(); let insertQuestionDot = false; if (type.isNullableType()) { - const canCorrectToQuestionDot = isRightOfDot && - !isRightOfQuestionDot && - preferences.includeAutomaticOptionalChainCompletions !== false; + const canCorrectToQuestionDot = isRightOfDot + && !isRightOfQuestionDot + && preferences.includeAutomaticOptionalChainCompletions !== false; if (canCorrectToQuestionDot || isRightOfQuestionDot) { type = type.getNonNullableType(); @@ -3598,9 +4110,9 @@ function getCompletionData( if (!isTypeLocation) { let insertQuestionDot = false; if (type.isNullableType()) { - const canCorrectToQuestionDot = isRightOfDot && - !isRightOfQuestionDot && - preferences.includeAutomaticOptionalChainCompletions !== false; + const canCorrectToQuestionDot = isRightOfDot + && !isRightOfQuestionDot + && preferences.includeAutomaticOptionalChainCompletions !== false; if (canCorrectToQuestionDot || isRightOfQuestionDot) { type = type.getNonNullableType(); @@ -3623,7 +4135,8 @@ function getCompletionData( isNewIdentifierLocation = true; } - const propertyAccess = node.kind === SyntaxKind.ImportType ? node as ImportTypeNode : node.parent as PropertyAccessExpression | QualifiedName; + const propertyAccess = node.kind === SyntaxKind.ImportType ? node as ImportTypeNode + : node.parent as PropertyAccessExpression | QualifiedName; if (inCheckedFile) { for (const symbol of type.getApparentProperties()) { if (typeChecker.isValidPropertyAccessForCompletions(propertyAccess, type, symbol)) { @@ -3637,7 +4150,12 @@ function getCompletionData( // each individual type has. This is because we're going to add all identifiers // anyways. So we might as well elevate the members that were at least part // of the individual types to a higher status since we know what they are. - symbols.push(...filter(getPropertiesForCompletion(type, typeChecker), s => typeChecker.isValidPropertyAccessForCompletions(propertyAccess, type, s))); + symbols.push( + ...filter( + getPropertiesForCompletion(type, typeChecker), + s => typeChecker.isValidPropertyAccessForCompletions(propertyAccess, type, s), + ), + ); } if (insertAwait && preferences.includeCompletionsWithInsertText) { @@ -3656,7 +4174,10 @@ function getCompletionData( // For a computed property with an accessible name like `Symbol.iterator`, // we'll add a completion for the *name* `Symbol` instead of for the property. // If this is e.g. [Symbol.iterator], add a completion for `Symbol`. - const computedPropertyName = firstDefined(symbol.declarations, decl => tryCast(getNameOfDeclaration(decl), isComputedPropertyName)); + const computedPropertyName = firstDefined( + symbol.declarations, + decl => tryCast(getNameOfDeclaration(decl), isComputedPropertyName), + ); if (computedPropertyName) { const leftMostName = getLeftMostName(computedPropertyName.expression); // The completion is for `Symbol`, not `iterator`. const nameSymbol = leftMostName && typeChecker.getSymbolAtLocation(leftMostName); @@ -3668,15 +4189,24 @@ function getCompletionData( symbols.push(firstAccessibleSymbol); const moduleSymbol = firstAccessibleSymbol.parent; if ( - !moduleSymbol || - !isExternalModuleSymbol(moduleSymbol) || - typeChecker.tryGetMemberInModuleExportsAndProperties(firstAccessibleSymbol.name, moduleSymbol) !== firstAccessibleSymbol + !moduleSymbol + || !isExternalModuleSymbol(moduleSymbol) + || typeChecker.tryGetMemberInModuleExportsAndProperties(firstAccessibleSymbol.name, moduleSymbol) + !== firstAccessibleSymbol ) { - symbolToOriginInfoMap[index] = { kind: getNullableSymbolOriginInfoKind(SymbolOriginInfoKind.SymbolMemberNoExport) }; + symbolToOriginInfoMap[index] = { + kind: getNullableSymbolOriginInfoKind(SymbolOriginInfoKind.SymbolMemberNoExport), + }; } else { - const fileName = isExternalModuleNameRelative(stripQuotes(moduleSymbol.name)) ? getSourceFileOfModule(moduleSymbol)?.fileName : undefined; - const { moduleSpecifier } = (importSpecifierResolver ||= codefix.createImportSpecifierResolver(sourceFile, program, host, preferences)).getModuleSpecifierForBestExportInfo( + const fileName = isExternalModuleNameRelative(stripQuotes(moduleSymbol.name)) + ? getSourceFileOfModule(moduleSymbol)?.fileName : undefined; + const { moduleSpecifier } = (importSpecifierResolver ||= codefix.createImportSpecifierResolver( + sourceFile, + program, + host, + preferences, + )).getModuleSpecifierForBestExportInfo( [{ exportKind: ExportKind.Named, moduleFileName: fileName, @@ -3727,7 +4257,9 @@ function getCompletionData( function addSymbolOriginInfo(symbol: Symbol) { if (preferences.includeCompletionsWithInsertText) { if (insertAwait && addToSeen(seenPropertySymbols, getSymbolId(symbol))) { - symbolToOriginInfoMap[symbols.length] = { kind: getNullableSymbolOriginInfoKind(SymbolOriginInfoKind.Promise) }; + symbolToOriginInfoMap[symbols.length] = { + kind: getNullableSymbolOriginInfoKind(SymbolOriginInfoKind.Promise), + }; } else if (insertQuestionDot) { symbolToOriginInfoMap[symbols.length] = { kind: SymbolOriginInfoKind.Nullable }; @@ -3774,8 +4306,15 @@ function getCompletionData( // Cursor is inside a JSX self-closing element or opening element const attrsType = jsxContainer && typeChecker.getContextualType(jsxContainer.attributes); if (!attrsType) return GlobalsSearch.Continue; - const completionsType = jsxContainer && typeChecker.getContextualType(jsxContainer.attributes, ContextFlags.Completions); - symbols = concatenate(symbols, filterJsxAttributes(getPropertiesForObjectExpression(attrsType, completionsType, jsxContainer.attributes, typeChecker), jsxContainer.attributes.properties)); + const completionsType = jsxContainer + && typeChecker.getContextualType(jsxContainer.attributes, ContextFlags.Completions); + symbols = concatenate( + symbols, + filterJsxAttributes( + getPropertiesForObjectExpression(attrsType, completionsType, jsxContainer.attributes, typeChecker), + jsxContainer.attributes.properties, + ), + ); setSortTextToOptionalMember(); completionKind = CompletionKind.MemberLike; isNewIdentifierLocation = false; @@ -3790,7 +4329,8 @@ function getCompletionData( } function getGlobalCompletions(): void { - keywordFilters = tryGetFunctionLikeBodyCompletionContainer(contextToken) ? KeywordCompletionFilters.FunctionLikeBodyKeywords : KeywordCompletionFilters.All; + keywordFilters = tryGetFunctionLikeBodyCompletionContainer(contextToken) + ? KeywordCompletionFilters.FunctionLikeBodyKeywords : KeywordCompletionFilters.All; // Get all entities in the current scope. completionKind = CompletionKind.Global; @@ -3824,14 +4364,15 @@ function getCompletionData( // - 'contextToken' was adjusted to the token prior to 'previousToken' // because we were at the end of an identifier. // - 'previousToken' is defined. - const adjustedPosition = previousToken !== contextToken ? - previousToken.getStart() : - position; + const adjustedPosition = previousToken !== contextToken + ? previousToken.getStart() + : position; const scopeNode = getScopeNode(contextToken, adjustedPosition, sourceFile) || sourceFile; isInSnippetScope = isSnippetScope(scopeNode); - const symbolMeanings = (isTypeOnlyLocation ? SymbolFlags.None : SymbolFlags.Value) | SymbolFlags.Type | SymbolFlags.Namespace | SymbolFlags.Alias; + const symbolMeanings = (isTypeOnlyLocation ? SymbolFlags.None : SymbolFlags.Value) | SymbolFlags.Type + | SymbolFlags.Namespace | SymbolFlags.Alias; const typeOnlyAliasNeedsPromotion = previousToken && !isValidTypeOnlyAliasUseSite(previousToken); symbols = concatenate(symbols, typeChecker.getSymbolsInScope(scopeNode, symbolMeanings)); @@ -3839,15 +4380,19 @@ function getCompletionData( for (let i = 0; i < symbols.length; i++) { const symbol = symbols[i]; if ( - !typeChecker.isArgumentsSymbol(symbol) && - !some(symbol.declarations, d => d.getSourceFile() === sourceFile) + !typeChecker.isArgumentsSymbol(symbol) + && !some(symbol.declarations, d => d.getSourceFile() === sourceFile) ) { symbolToSortTextMap[getSymbolId(symbol)] = SortText.GlobalsOrKeywords; } if (typeOnlyAliasNeedsPromotion && !(symbol.flags & SymbolFlags.Value)) { - const typeOnlyAliasDeclaration = symbol.declarations && find(symbol.declarations, isTypeOnlyImportDeclaration); + const typeOnlyAliasDeclaration = symbol.declarations + && find(symbol.declarations, isTypeOnlyImportDeclaration); if (typeOnlyAliasDeclaration) { - const origin: SymbolOriginInfoTypeOnlyImport = { kind: SymbolOriginInfoKind.TypeOnlyAlias, declaration: typeOnlyAliasDeclaration }; + const origin: SymbolOriginInfoTypeOnlyImport = { + kind: SymbolOriginInfoKind.TypeOnlyAlias, + declaration: typeOnlyAliasDeclaration, + }; symbolToOriginInfoMap[i] = origin; } } @@ -3855,7 +4400,11 @@ function getCompletionData( // Need to insert 'this.' before properties of `this` type, so only do that if `includeInsertTextCompletions` if (preferences.includeCompletionsWithInsertText && scopeNode.kind !== SyntaxKind.SourceFile) { - const thisType = typeChecker.tryGetThisTypeAt(scopeNode, /*includeGlobalThis*/ false, isClassLike(scopeNode.parent) ? scopeNode as ThisContainer : undefined); + const thisType = typeChecker.tryGetThisTypeAt( + scopeNode, + /*includeGlobalThis*/ false, + isClassLike(scopeNode.parent) ? scopeNode as ThisContainer : undefined, + ); if (thisType && !isProbablyGlobalType(thisType, sourceFile, typeChecker)) { for (const symbol of getPropertiesForCompletion(thisType, typeChecker)) { symbolToOriginInfoMap[symbols.length] = { kind: SymbolOriginInfoKind.ThisType }; @@ -3902,17 +4451,18 @@ function getCompletionData( function isTypeOnlyCompletion(): boolean { return insideJsDocTagTypeExpression || !!importStatementCompletion && isTypeOnlyImportOrExportDeclaration(location.parent) - || !isContextTokenValueLocation(contextToken) && - (isPossiblyTypeArgumentPosition(contextToken, sourceFile, typeChecker) + || !isContextTokenValueLocation(contextToken) + && (isPossiblyTypeArgumentPosition(contextToken, sourceFile, typeChecker) || isPartOfTypeNode(location) || isContextTokenTypeLocation(contextToken)); } function isContextTokenValueLocation(contextToken: Node) { - return contextToken && - ((contextToken.kind === SyntaxKind.TypeOfKeyword && - (contextToken.parent.kind === SyntaxKind.TypeQuery || isTypeOfExpression(contextToken.parent))) || - (contextToken.kind === SyntaxKind.AssertsKeyword && contextToken.parent.kind === SyntaxKind.TypePredicate)); + return contextToken + && ((contextToken.kind === SyntaxKind.TypeOfKeyword + && (contextToken.parent.kind === SyntaxKind.TypeQuery || isTypeOfExpression(contextToken.parent))) + || (contextToken.kind === SyntaxKind.AssertsKeyword + && contextToken.parent.kind === SyntaxKind.TypePredicate)); } function isContextTokenTypeLocation(contextToken: Node): boolean { @@ -3920,11 +4470,11 @@ function getCompletionData( const parentKind = contextToken.parent.kind; switch (contextToken.kind) { case SyntaxKind.ColonToken: - return parentKind === SyntaxKind.PropertyDeclaration || - parentKind === SyntaxKind.PropertySignature || - parentKind === SyntaxKind.Parameter || - parentKind === SyntaxKind.VariableDeclaration || - isFunctionLikeKind(parentKind); + return parentKind === SyntaxKind.PropertyDeclaration + || parentKind === SyntaxKind.PropertySignature + || parentKind === SyntaxKind.Parameter + || parentKind === SyntaxKind.VariableDeclaration + || isFunctionLikeKind(parentKind); case SyntaxKind.EqualsToken: return parentKind === SyntaxKind.TypeAliasDeclaration; @@ -3933,8 +4483,8 @@ function getCompletionData( return parentKind === SyntaxKind.AsExpression; case SyntaxKind.LessThanToken: - return parentKind === SyntaxKind.TypeReference || - parentKind === SyntaxKind.TypeAssertionExpression; + return parentKind === SyntaxKind.TypeReference + || parentKind === SyntaxKind.TypeAssertionExpression; case SyntaxKind.ExtendsKeyword: return parentKind === SyntaxKind.TypeParameter; @@ -3949,7 +4499,10 @@ function getCompletionData( /** Mutates `symbols`, `symbolToOriginInfoMap`, and `symbolToSortTextMap` */ function collectAutoImports() { if (!shouldOfferImportCompletions()) return; - Debug.assert(!detailsEntryId?.data, "Should not run 'collectAutoImports' when faster path is available via `data`"); + Debug.assert( + !detailsEntryId?.data, + "Should not run 'collectAutoImports' when faster path is available via `data`", + ); if (detailsEntryId && !detailsEntryId.source) { // Asking for completion details for an item that is not an auto-import return; @@ -3960,14 +4513,15 @@ function getCompletionData( const isAfterTypeOnlyImportSpecifierModifier = previousToken === contextToken && importStatementCompletion; - const lowerCaseTokenText = isAfterTypeOnlyImportSpecifierModifier ? "" : - previousToken && isIdentifier(previousToken) ? previousToken.text.toLowerCase() : - ""; + const lowerCaseTokenText = isAfterTypeOnlyImportSpecifierModifier ? "" + : previousToken && isIdentifier(previousToken) ? previousToken.text.toLowerCase() + : ""; const moduleSpecifierCache = host.getModuleSpecifierCache?.(); const exportInfo = getExportInfoMap(sourceFile, host, program, preferences, cancellationToken); const packageJsonAutoImportProvider = host.getPackageJsonAutoImportProvider?.(); - const packageJsonFilter = detailsEntryId ? undefined : createPackageJsonImportFilter(sourceFile, preferences, host); + const packageJsonFilter = detailsEntryId ? undefined + : createPackageJsonImportFilter(sourceFile, preferences, host); resolvingModuleSpecifiers( "collectAutoImports", host, @@ -3982,19 +4536,30 @@ function getCompletionData( sourceFile.path, /*preferCapitalized*/ isRightOfOpenTag, (symbolName, targetFlags) => { - if (!isIdentifierText(symbolName, getEmitScriptTarget(host.getCompilationSettings()))) return false; + if (!isIdentifierText(symbolName, getEmitScriptTarget(host.getCompilationSettings()))) { + return false; + } if (!detailsEntryId && isStringANonContextualKeyword(symbolName)) return false; - if (!isTypeOnlyLocation && !importStatementCompletion && !(targetFlags & SymbolFlags.Value)) return false; - if (isTypeOnlyLocation && !(targetFlags & (SymbolFlags.Module | SymbolFlags.Type))) return false; + if (!isTypeOnlyLocation && !importStatementCompletion && !(targetFlags & SymbolFlags.Value)) { + return false; + } + if (isTypeOnlyLocation && !(targetFlags & (SymbolFlags.Module | SymbolFlags.Type))) { + return false; + } // Do not try to auto-import something with a lowercase first letter for a JSX tag const firstChar = symbolName.charCodeAt(0); - if (isRightOfOpenTag && (firstChar < CharacterCodes.A || firstChar > CharacterCodes.Z)) return false; + if (isRightOfOpenTag && (firstChar < CharacterCodes.A || firstChar > CharacterCodes.Z)) { + return false; + } if (detailsEntryId) return true; return charactersFuzzyMatchInString(symbolName, lowerCaseTokenText); }, (info, symbolName, isFromAmbientModule, exportMapKey) => { - if (detailsEntryId && !some(info, i => detailsEntryId.source === stripQuotes(i.moduleSymbol.name))) { + if ( + detailsEntryId + && !some(info, i => detailsEntryId.source === stripQuotes(i.moduleSymbol.name)) + ) { return; } @@ -4027,14 +4592,16 @@ function getCompletionData( } const isDefaultExport = exportInfo.exportKind === ExportKind.Default; - const symbol = isDefaultExport && getLocalSymbolForExportDefault(exportInfo.symbol) || exportInfo.symbol; + const symbol = isDefaultExport && getLocalSymbolForExportDefault(exportInfo.symbol) + || exportInfo.symbol; pushAutoImportSymbol(symbol, { kind: moduleSpecifier ? SymbolOriginInfoKind.ResolvedExport : SymbolOriginInfoKind.Export, moduleSpecifier, symbolName, exportMapKey, - exportName: exportInfo.exportKind === ExportKind.ExportEquals ? InternalSymbolName.ExportEquals : exportInfo.symbol.name, + exportName: exportInfo.exportKind === ExportKind.ExportEquals + ? InternalSymbolName.ExportEquals : exportInfo.symbol.name, fileName: exportInfo.moduleFileName, isDefaultExport, moduleSymbol: exportInfo.moduleSymbol, @@ -4053,11 +4620,17 @@ function getCompletionData( const moduleFile = tryCast(info.moduleSymbol.valueDeclaration, isSourceFile); if (!moduleFile) { const moduleName = stripQuotes(info.moduleSymbol.name); - if (JsTyping.nodeCoreModules.has(moduleName) && startsWith(moduleName, "node:") !== shouldUseUriStyleNodeCoreModules(sourceFile, program)) { + if ( + JsTyping.nodeCoreModules.has(moduleName) + && startsWith(moduleName, "node:") !== shouldUseUriStyleNodeCoreModules(sourceFile, program) + ) { return false; } return packageJsonFilter - ? packageJsonFilter.allowsImportingAmbientModule(info.moduleSymbol, getModuleSpecifierResolutionHost(info.isFromPackageJson)) + ? packageJsonFilter.allowsImportingAmbientModule( + info.moduleSymbol, + getModuleSpecifierResolutionHost(info.isFromPackageJson), + ) : true; } return isImportableFile( @@ -4079,7 +4652,8 @@ function getCompletionData( return; } symbolToOriginInfoMap[symbols.length] = origin; - symbolToSortTextMap[symbolId] = importStatementCompletion ? SortText.LocationPriority : SortText.AutoImportSuggestions; + symbolToSortTextMap[symbolId] = importStatementCompletion ? SortText.LocationPriority + : SortText.AutoImportSuggestions; symbols.push(symbol); } @@ -4117,7 +4691,10 @@ function getCompletionData( if (!entryProps) { return; } - const origin: SymbolOriginInfoObjectLiteralMethod = { kind: SymbolOriginInfoKind.ObjectLiteralMethod, ...entryProps }; + const origin: SymbolOriginInfoObjectLiteralMethod = { + kind: SymbolOriginInfoKind.ObjectLiteralMethod, + ...entryProps, + }; flags |= CompletionInfoFlags.MayIncludeMethodSnippets; symbolToOriginInfoMap[symbols.length] = origin; symbols.push(member); @@ -4154,11 +4731,11 @@ function getCompletionData( function isCompletionListBlocker(contextToken: Node): boolean { const start = timestamp(); - const result = isInStringOrRegularExpressionOrTemplateLiteral(contextToken) || - isSolelyIdentifierDefinitionLocation(contextToken) || - isDotOfNumericLiteral(contextToken) || - isInJsxText(contextToken) || - isBigIntLiteral(contextToken); + const result = isInStringOrRegularExpressionOrTemplateLiteral(contextToken) + || isSolelyIdentifierDefinitionLocation(contextToken) + || isDotOfNumericLiteral(contextToken) + || isInJsxText(contextToken) + || isBigIntLiteral(contextToken); log("getCompletionsAtPosition: isCompletionListBlocker: " + (timestamp() - start)); return result; } @@ -4174,7 +4751,11 @@ function getCompletionData( // - contextToken: GreaterThanToken (before cursor) // - location: JsxSelfClosingElement or JsxOpeningElement // - contextToken.parent === location - if (location === contextToken.parent && (location.kind === SyntaxKind.JsxOpeningElement || location.kind === SyntaxKind.JsxSelfClosingElement)) { + if ( + location === contextToken.parent + && (location.kind === SyntaxKind.JsxOpeningElement + || location.kind === SyntaxKind.JsxSelfClosingElement) + ) { return false; } @@ -4186,7 +4767,10 @@ function getCompletionData( return location.parent.kind !== SyntaxKind.JsxOpeningElement; } - if (contextToken.parent.kind === SyntaxKind.JsxClosingElement || contextToken.parent.kind === SyntaxKind.JsxSelfClosingElement) { + if ( + contextToken.parent.kind === SyntaxKind.JsxClosingElement + || contextToken.parent.kind === SyntaxKind.JsxSelfClosingElement + ) { return !!contextToken.parent.parent && contextToken.parent.parent.kind === SyntaxKind.JsxElement; } } @@ -4264,8 +4848,9 @@ function getCompletionData( // 2. at the end position of an unterminated token. // 3. at the end of a regular expression (due to trailing flags like '/foo/g'). return (isRegularExpressionLiteral(contextToken) || isStringTextContainingNode(contextToken)) && ( - rangeContainsPositionExclusive(contextToken, position) || - position === contextToken.end && (!!contextToken.isUnterminated || isRegularExpressionLiteral(contextToken)) + rangeContainsPositionExclusive(contextToken, position) + || position === contextToken.end + && (!!contextToken.isUnterminated || isRegularExpressionLiteral(contextToken)) ); } @@ -4273,7 +4858,8 @@ function getCompletionData( const typeLiteralNode = tryGetTypeLiteralNode(contextToken); if (!typeLiteralNode) return GlobalsSearch.Continue; - const intersectionTypeNode = isIntersectionTypeNode(typeLiteralNode.parent) ? typeLiteralNode.parent : undefined; + const intersectionTypeNode = isIntersectionTypeNode(typeLiteralNode.parent) ? typeLiteralNode.parent + : undefined; const containerTypeNode = intersectionTypeNode || typeLiteralNode; const containerExpectedType = getConstraintOfTypeArgumentProperty(containerTypeNode, typeChecker); @@ -4327,7 +4913,12 @@ function getCompletionData( const hasStringIndexType = (completionsType || instantiatedType).getStringIndexType(); const hasNumberIndextype = (completionsType || instantiatedType).getNumberIndexType(); isNewIdentifierLocation = !!hasStringIndexType || !!hasNumberIndextype; - typeMembers = getPropertiesForObjectExpression(instantiatedType, completionsType, objectLikeContainer, typeChecker); + typeMembers = getPropertiesForObjectExpression( + instantiatedType, + completionsType, + objectLikeContainer, + typeChecker, + ); existingMembers = objectLikeContainer.properties; if (typeMembers.length === 0) { @@ -4351,20 +4942,31 @@ function getCompletionData( // through type declaration or inference. // Also proceed if rootDeclaration is a parameter and if its containing function expression/arrow function is contextually typed - // type of parameter will flow in from the contextual type of the function - let canGetType = hasInitializer(rootDeclaration) || !!getEffectiveTypeAnnotationNode(rootDeclaration) || rootDeclaration.parent.parent.kind === SyntaxKind.ForOfStatement; + let canGetType = hasInitializer(rootDeclaration) || !!getEffectiveTypeAnnotationNode(rootDeclaration) + || rootDeclaration.parent.parent.kind === SyntaxKind.ForOfStatement; if (!canGetType && rootDeclaration.kind === SyntaxKind.Parameter) { if (isExpression(rootDeclaration.parent)) { canGetType = !!typeChecker.getContextualType(rootDeclaration.parent as Expression); } - else if (rootDeclaration.parent.kind === SyntaxKind.MethodDeclaration || rootDeclaration.parent.kind === SyntaxKind.SetAccessor) { - canGetType = isExpression(rootDeclaration.parent.parent) && !!typeChecker.getContextualType(rootDeclaration.parent.parent as Expression); + else if ( + rootDeclaration.parent.kind === SyntaxKind.MethodDeclaration + || rootDeclaration.parent.kind === SyntaxKind.SetAccessor + ) { + canGetType = isExpression(rootDeclaration.parent.parent) + && !!typeChecker.getContextualType(rootDeclaration.parent.parent as Expression); } } if (canGetType) { const typeForObject = typeChecker.getTypeAtLocation(objectLikeContainer); if (!typeForObject) return GlobalsSearch.Fail; typeMembers = typeChecker.getPropertiesOfType(typeForObject).filter(propertySymbol => { - return typeChecker.isPropertyAccessible(objectLikeContainer, /*isSuper*/ false, /*isWrite*/ false, typeForObject, propertySymbol); + return typeChecker.isPropertyAccessible( + objectLikeContainer, + /*isSuper*/ false, + /*isWrite*/ false, + typeForObject, + propertySymbol, + ); }); existingMembers = objectLikeContainer.elements; } @@ -4405,8 +5007,11 @@ function getCompletionData( if (!contextToken) return GlobalsSearch.Continue; // `import { |` or `import { a as 0, | }` or `import { type | }` - const namedImportsOrExports = contextToken.kind === SyntaxKind.OpenBraceToken || contextToken.kind === SyntaxKind.CommaToken ? tryCast(contextToken.parent, isNamedImportsOrExports) : - isTypeKeywordTokenOrIdentifier(contextToken) ? tryCast(contextToken.parent.parent, isNamedImportsOrExports) : undefined; + const namedImportsOrExports = + contextToken.kind === SyntaxKind.OpenBraceToken || contextToken.kind === SyntaxKind.CommaToken + ? tryCast(contextToken.parent, isNamedImportsOrExports) + : isTypeKeywordTokenOrIdentifier(contextToken) + ? tryCast(contextToken.parent.parent, isNamedImportsOrExports) : undefined; if (!namedImportsOrExports) return GlobalsSearch.Continue; @@ -4416,7 +5021,8 @@ function getCompletionData( } // try to show exported member for imported/re-exported module - const { moduleSpecifier } = namedImportsOrExports.kind === SyntaxKind.NamedImports ? namedImportsOrExports.parent.parent : namedImportsOrExports.parent; + const { moduleSpecifier } = namedImportsOrExports.kind === SyntaxKind.NamedImports + ? namedImportsOrExports.parent.parent : namedImportsOrExports.parent; if (!moduleSpecifier) { isNewIdentifierLocation = true; return namedImportsOrExports.kind === SyntaxKind.NamedImports ? GlobalsSearch.Fail : GlobalsSearch.Continue; @@ -4430,8 +5036,14 @@ function getCompletionData( completionKind = CompletionKind.MemberLike; isNewIdentifierLocation = false; const exports = typeChecker.getExportsAndPropertiesOfModule(moduleSpecifierSymbol); - const existing = new Set((namedImportsOrExports.elements as NodeArray).filter(n => !isCurrentlyEditingNode(n)).map(n => (n.propertyName || n.name).escapedText)); - const uniques = exports.filter(e => e.escapedName !== InternalSymbolName.Default && !existing.has(e.escapedName)); + const existing = new Set( + (namedImportsOrExports.elements as NodeArray).filter(n => + !isCurrentlyEditingNode(n) + ).map(n => (n.propertyName || n.name).escapedText), + ); + const uniques = exports.filter(e => + e.escapedName !== InternalSymbolName.Default && !existing.has(e.escapedName) + ); symbols = concatenate(symbols, uniques); if (!uniques.length) { // If there's nothing else to import, don't offer `type` either @@ -4450,7 +5062,8 @@ function getCompletionData( * preventing this function from running. */ function tryGetLocalNamedExportCompletionSymbols(): GlobalsSearch { - const namedExports = contextToken && (contextToken.kind === SyntaxKind.OpenBraceToken || contextToken.kind === SyntaxKind.CommaToken) + const namedExports = contextToken + && (contextToken.kind === SyntaxKind.OpenBraceToken || contextToken.kind === SyntaxKind.CommaToken) ? tryCast(contextToken.parent, isNamedExports) : undefined; @@ -4482,14 +5095,17 @@ function getCompletionData( completionKind = CompletionKind.MemberLike; // Declaring new property/method/accessor isNewIdentifierLocation = true; - keywordFilters = contextToken.kind === SyntaxKind.AsteriskToken ? KeywordCompletionFilters.None : - isClassLike(decl) ? KeywordCompletionFilters.ClassElementKeywords : KeywordCompletionFilters.InterfaceElementKeywords; + keywordFilters = contextToken.kind === SyntaxKind.AsteriskToken ? KeywordCompletionFilters.None + : isClassLike(decl) ? KeywordCompletionFilters.ClassElementKeywords + : KeywordCompletionFilters.InterfaceElementKeywords; // If you're in an interface you don't want to repeat things from super-interface. So just stop here. if (!isClassLike(decl)) return GlobalsSearch.Success; - const classElement = contextToken.kind === SyntaxKind.SemicolonToken ? contextToken.parent.parent : contextToken.parent; - let classElementModifierFlags = isClassElement(classElement) ? getEffectiveModifierFlags(classElement) : ModifierFlags.None; + const classElement = contextToken.kind === SyntaxKind.SemicolonToken ? contextToken.parent.parent + : contextToken.parent; + let classElementModifierFlags = isClassElement(classElement) ? getEffectiveModifierFlags(classElement) + : ModifierFlags.None; // If this is context token is not something we are editing now, consider if this would lead to be modifier if (contextToken.kind === SyntaxKind.Identifier && !isCurrentlyEditingNode(contextToken)) { switch (contextToken.getText()) { @@ -4511,17 +5127,25 @@ function getCompletionData( // No member list for private methods if (!(classElementModifierFlags & ModifierFlags.Private)) { // List of property symbols of base type that are not private and already implemented - const baseTypeNodes = isClassLike(decl) && classElementModifierFlags & ModifierFlags.Override ? singleElementArray(getEffectiveBaseTypeNode(decl)) : getAllSuperTypeNodes(decl); + const baseTypeNodes = isClassLike(decl) && classElementModifierFlags & ModifierFlags.Override + ? singleElementArray(getEffectiveBaseTypeNode(decl)) : getAllSuperTypeNodes(decl); const baseSymbols = flatMap(baseTypeNodes, baseTypeNode => { const type = typeChecker.getTypeAtLocation(baseTypeNode); - return classElementModifierFlags & ModifierFlags.Static ? - type?.symbol && typeChecker.getPropertiesOfType(typeChecker.getTypeOfSymbolAtLocation(type.symbol, decl)) : - type && typeChecker.getPropertiesOfType(type); + return classElementModifierFlags & ModifierFlags.Static + ? type?.symbol + && typeChecker.getPropertiesOfType(typeChecker.getTypeOfSymbolAtLocation(type.symbol, decl)) + : type && typeChecker.getPropertiesOfType(type); }); - symbols = concatenate(symbols, filterClassMembersList(baseSymbols, decl.members, classElementModifierFlags)); + symbols = concatenate( + symbols, + filterClassMembersList(baseSymbols, decl.members, classElementModifierFlags), + ); forEach(symbols, (symbol, index) => { const declaration = symbol?.valueDeclaration; - if (declaration && isClassElement(declaration) && declaration.name && isComputedPropertyName(declaration.name)) { + if ( + declaration && isClassElement(declaration) && declaration.name + && isComputedPropertyName(declaration.name) + ) { const origin: SymbolOriginInfoComputedPropertyName = { kind: SymbolOriginInfoKind.ComputedPropertyName, symbolName: typeChecker.symbolToString(symbol), @@ -4588,10 +5212,21 @@ function getCompletionData( case SyntaxKind.JsxAttributes: case SyntaxKind.JsxAttribute: case SyntaxKind.JsxSpreadAttribute: - if (parent && (parent.kind === SyntaxKind.JsxSelfClosingElement || parent.kind === SyntaxKind.JsxOpeningElement)) { + if ( + parent + && (parent.kind === SyntaxKind.JsxSelfClosingElement + || parent.kind === SyntaxKind.JsxOpeningElement) + ) { if (contextToken.kind === SyntaxKind.GreaterThanToken) { - const precedingToken = findPrecedingToken(contextToken.pos, sourceFile, /*startNode*/ undefined); - if (!(parent as JsxOpeningLikeElement).typeArguments || (precedingToken && precedingToken.kind === SyntaxKind.SlashToken)) break; + const precedingToken = findPrecedingToken( + contextToken.pos, + sourceFile, + /*startNode*/ undefined, + ); + if ( + !(parent as JsxOpeningLikeElement).typeArguments + || (precedingToken && precedingToken.kind === SyntaxKind.SlashToken) + ) break; } return parent as JsxOpeningLikeElement; } @@ -4608,7 +5243,11 @@ function getCompletionData( // its parent is a JsxExpression, whose parent is a JsxAttribute, // whose parent is a JsxOpeningLikeElement case SyntaxKind.StringLiteral: - if (parent && ((parent.kind === SyntaxKind.JsxAttribute) || (parent.kind === SyntaxKind.JsxSpreadAttribute))) { + if ( + parent + && ((parent.kind === SyntaxKind.JsxAttribute) + || (parent.kind === SyntaxKind.JsxSpreadAttribute)) + ) { // Currently we parse JsxOpeningLikeElement as: // JsxOpeningLikeElement // attributes: JsxAttributes @@ -4620,9 +5259,9 @@ function getCompletionData( case SyntaxKind.CloseBraceToken: if ( - parent && - parent.kind === SyntaxKind.JsxExpression && - parent.parent && parent.parent.kind === SyntaxKind.JsxAttribute + parent + && parent.kind === SyntaxKind.JsxExpression + && parent.parent && parent.parent.kind === SyntaxKind.JsxAttribute ) { // Currently we parse JsxOpeningLikeElement as: // JsxOpeningLikeElement @@ -4654,19 +5293,19 @@ function getCompletionData( const containingNodeKind = parent.kind; switch (contextToken.kind) { case SyntaxKind.CommaToken: - return containingNodeKind === SyntaxKind.VariableDeclaration || - isVariableDeclarationListButNotTypeArgument(contextToken) || - containingNodeKind === SyntaxKind.VariableStatement || - containingNodeKind === SyntaxKind.EnumDeclaration || // enum a { foo, | - isFunctionLikeButNotConstructor(containingNodeKind) || - containingNodeKind === SyntaxKind.InterfaceDeclaration || // interface A= contextToken.pos); + || (isClassLike(parent) + && !!parent.typeParameters + && parent.typeParameters.end >= contextToken.pos); case SyntaxKind.DotToken: return containingNodeKind === SyntaxKind.ArrayBindingPattern; // var [.| @@ -4678,25 +5317,25 @@ function getCompletionData( return containingNodeKind === SyntaxKind.ArrayBindingPattern; // var [x| case SyntaxKind.OpenParenToken: - return containingNodeKind === SyntaxKind.CatchClause || - isFunctionLikeButNotConstructor(containingNodeKind); + return containingNodeKind === SyntaxKind.CatchClause + || isFunctionLikeButNotConstructor(containingNodeKind); case SyntaxKind.OpenBraceToken: return containingNodeKind === SyntaxKind.EnumDeclaration; // enum a { | case SyntaxKind.LessThanToken: - return containingNodeKind === SyntaxKind.ClassDeclaration || // class A< | - containingNodeKind === SyntaxKind.ClassExpression || // var C = class D< | - containingNodeKind === SyntaxKind.InterfaceDeclaration || // interface A< | - containingNodeKind === SyntaxKind.TypeAliasDeclaration || // type List< | - isFunctionLikeKind(containingNodeKind); + return containingNodeKind === SyntaxKind.ClassDeclaration // class A< | + || containingNodeKind === SyntaxKind.ClassExpression // var C = class D< | + || containingNodeKind === SyntaxKind.InterfaceDeclaration // interface A< | + || containingNodeKind === SyntaxKind.TypeAliasDeclaration // type List< | + || isFunctionLikeKind(containingNodeKind); case SyntaxKind.StaticKeyword: return containingNodeKind === SyntaxKind.PropertyDeclaration && !isClassLike(parent.parent); case SyntaxKind.DotDotDotToken: - return containingNodeKind === SyntaxKind.Parameter || - (!!parent.parent && parent.parent.kind === SyntaxKind.ArrayBindingPattern); // var [...z| + return containingNodeKind === SyntaxKind.Parameter + || (!!parent.parent && parent.parent.kind === SyntaxKind.ArrayBindingPattern); // var [...z| case SyntaxKind.PublicKeyword: case SyntaxKind.PrivateKeyword: @@ -4704,9 +5343,9 @@ function getCompletionData( return containingNodeKind === SyntaxKind.Parameter && !isConstructorDeclaration(parent.parent); case SyntaxKind.AsKeyword: - return containingNodeKind === SyntaxKind.ImportSpecifier || - containingNodeKind === SyntaxKind.ExportSpecifier || - containingNodeKind === SyntaxKind.NamespaceImport; + return containingNodeKind === SyntaxKind.ImportSpecifier + || containingNodeKind === SyntaxKind.ExportSpecifier + || containingNodeKind === SyntaxKind.NamespaceImport; case SyntaxKind.GetKeyword: case SyntaxKind.SetKeyword: @@ -4714,9 +5353,9 @@ function getCompletionData( case SyntaxKind.Identifier: if ( - containingNodeKind === SyntaxKind.ImportSpecifier && - contextToken === (parent as ImportSpecifier).name && - (contextToken as Identifier).text === "type" + containingNodeKind === SyntaxKind.ImportSpecifier + && contextToken === (parent as ImportSpecifier).name + && (contextToken as Identifier).text === "type" ) { // import { type | } return false; @@ -4754,9 +5393,9 @@ function getCompletionData( // - its name of the parameter and not being edited // eg. constructor(a |<- this shouldnt show completion if ( - !isIdentifier(contextToken) || - isParameterPropertyModifier(keywordForNode(contextToken)) || - isCurrentlyEditingNode(contextToken) + !isIdentifier(contextToken) + || isParameterPropertyModifier(keywordForNode(contextToken)) + || isCurrentlyEditingNode(contextToken) ) { return false; } @@ -4785,7 +5424,10 @@ function getCompletionData( // If we are inside a class declaration, and `constructor` is totally not present, // but we request a completion manually at a whitespace... const ancestorClassLike = findAncestor(contextToken.parent, isClassLike); - if (ancestorClassLike && contextToken === previousToken && isPreviousPropertyDeclarationTerminated(contextToken, position)) { + if ( + ancestorClassLike && contextToken === previousToken + && isPreviousPropertyDeclarationTerminated(contextToken, position) + ) { return false; // Don't block completions. } @@ -4818,12 +5460,14 @@ function getCompletionData( && !isJsxAttribute(contextToken.parent) // Don't block completions if we're in `class C /**/`, `interface I /**/` or `` , because we're *past* the end of the identifier and might want to complete `extends`. // If `contextToken !== previousToken`, this is `class C ex/**/`, `interface I ex/**/` or ``. - && !((isClassLike(contextToken.parent) || isInterfaceDeclaration(contextToken.parent) || isTypeParameterDeclaration(contextToken.parent)) && (contextToken !== previousToken || position > previousToken.end)); + && !((isClassLike(contextToken.parent) || isInterfaceDeclaration(contextToken.parent) + || isTypeParameterDeclaration(contextToken.parent)) + && (contextToken !== previousToken || position > previousToken.end)); } function isPreviousPropertyDeclarationTerminated(contextToken: Node, position: number) { - return contextToken.kind !== SyntaxKind.EqualsToken && - (contextToken.kind === SyntaxKind.SemicolonToken + return contextToken.kind !== SyntaxKind.EqualsToken + && (contextToken.kind === SyntaxKind.SemicolonToken || !positionsAreOnSameLine(contextToken.end, position, sourceFile)); } @@ -4851,7 +5495,10 @@ function getCompletionData( * @returns Symbols to be suggested in an object binding pattern or object literal expression, barring those whose declarations * do not occur at the current position and have not otherwise been typed. */ - function filterObjectMembersList(contextualMemberSymbols: Symbol[], existingMembers: readonly Declaration[]): Symbol[] { + function filterObjectMembersList( + contextualMemberSymbols: Symbol[], + existingMembers: readonly Declaration[], + ): Symbol[] { if (existingMembers.length === 0) { return contextualMemberSymbols; } @@ -4861,13 +5508,13 @@ function getCompletionData( for (const m of existingMembers) { // Ignore omitted expressions for missing members if ( - m.kind !== SyntaxKind.PropertyAssignment && - m.kind !== SyntaxKind.ShorthandPropertyAssignment && - m.kind !== SyntaxKind.BindingElement && - m.kind !== SyntaxKind.MethodDeclaration && - m.kind !== SyntaxKind.GetAccessor && - m.kind !== SyntaxKind.SetAccessor && - m.kind !== SyntaxKind.SpreadAssignment + m.kind !== SyntaxKind.PropertyAssignment + && m.kind !== SyntaxKind.ShorthandPropertyAssignment + && m.kind !== SyntaxKind.BindingElement + && m.kind !== SyntaxKind.MethodDeclaration + && m.kind !== SyntaxKind.GetAccessor + && m.kind !== SyntaxKind.SetAccessor + && m.kind !== SyntaxKind.SpreadAssignment ) { continue; } @@ -4893,7 +5540,8 @@ function getCompletionData( // NOTE: if one only performs this step when m.name is an identifier, // things like '__proto__' are not filtered out. const name = getNameOfDeclaration(m); - existingName = name && isPropertyNameLiteral(name) ? getEscapedTextOfIdentifierOrLiteral(name) : undefined; + existingName = name && isPropertyNameLiteral(name) ? getEscapedTextOfIdentifierOrLiteral(name) + : undefined; } if (existingName !== undefined) { @@ -4907,7 +5555,10 @@ function getCompletionData( return filteredSymbols; } - function setMembersDeclaredBySpreadAssignment(declaration: SpreadAssignment | JsxSpreadAttribute, membersDeclaredBySpreadAssignment: Set) { + function setMembersDeclaredBySpreadAssignment( + declaration: SpreadAssignment | JsxSpreadAttribute, + membersDeclaredBySpreadAssignment: Set, + ) { const expression = declaration.expression; const symbol = typeChecker.getSymbolAtLocation(expression); const type = symbol && typeChecker.getTypeOfSymbolAtLocation(symbol, expression); @@ -4930,7 +5581,10 @@ function getCompletionData( } // Set SortText to MemberDeclaredBySpreadAssignment if it is fulfilled by spread assignment - function setSortTextToMemberDeclaredBySpreadAssignment(membersDeclaredBySpreadAssignment: Set, contextualMemberSymbols: Symbol[]): void { + function setSortTextToMemberDeclaredBySpreadAssignment( + membersDeclaredBySpreadAssignment: Set, + contextualMemberSymbols: Symbol[], + ): void { if (membersDeclaredBySpreadAssignment.size === 0) { return; } @@ -4967,15 +5621,19 @@ function getCompletionData( * * @returns Symbols to be suggested in an class element depending on existing memebers and symbol flags */ - function filterClassMembersList(baseSymbols: readonly Symbol[], existingMembers: readonly ClassElement[], currentClassElementModifierFlags: ModifierFlags): Symbol[] { + function filterClassMembersList( + baseSymbols: readonly Symbol[], + existingMembers: readonly ClassElement[], + currentClassElementModifierFlags: ModifierFlags, + ): Symbol[] { const existingMemberNames = new Set<__String>(); for (const m of existingMembers) { // Ignore omitted expressions for missing members if ( - m.kind !== SyntaxKind.PropertyDeclaration && - m.kind !== SyntaxKind.MethodDeclaration && - m.kind !== SyntaxKind.GetAccessor && - m.kind !== SyntaxKind.SetAccessor + m.kind !== SyntaxKind.PropertyDeclaration + && m.kind !== SyntaxKind.MethodDeclaration + && m.kind !== SyntaxKind.GetAccessor + && m.kind !== SyntaxKind.SetAccessor ) { continue; } @@ -5002,10 +5660,11 @@ function getCompletionData( } return baseSymbols.filter(propertySymbol => - !existingMemberNames.has(propertySymbol.escapedName) && - !!propertySymbol.declarations && - !(getDeclarationModifierFlagsFromSymbol(propertySymbol) & ModifierFlags.Private) && - !(propertySymbol.valueDeclaration && isPrivateIdentifierClassElementDeclaration(propertySymbol.valueDeclaration)) + !existingMemberNames.has(propertySymbol.escapedName) + && !!propertySymbol.declarations + && !(getDeclarationModifierFlagsFromSymbol(propertySymbol) & ModifierFlags.Private) + && !(propertySymbol.valueDeclaration + && isPrivateIdentifierClassElementDeclaration(propertySymbol.valueDeclaration)) ); } @@ -5015,7 +5674,10 @@ function getCompletionData( * @returns Symbols to be suggested in a JSX element, barring those whose attributes * do not occur at the current position and have not otherwise been typed. */ - function filterJsxAttributes(symbols: Symbol[], attributes: NodeArray): Symbol[] { + function filterJsxAttributes( + symbols: Symbol[], + attributes: NodeArray, + ): Symbol[] { const seenNames = new Set<__String>(); const membersDeclaredBySpreadAssignment = new Set(); for (const attr of attributes) { @@ -5047,7 +5709,11 @@ function getCompletionData( * Returns the immediate owning object literal or binding pattern of a context token, * on the condition that one exists and that the context implies completion should be given. */ -function tryGetObjectLikeCompletionContainer(contextToken: Node | undefined, position: number, sourceFile: SourceFile): ObjectLiteralExpression | ObjectBindingPattern | undefined { +function tryGetObjectLikeCompletionContainer( + contextToken: Node | undefined, + position: number, + sourceFile: SourceFile, +): ObjectLiteralExpression | ObjectBindingPattern | undefined { if (contextToken) { const { parent } = contextToken; switch (contextToken.kind) { @@ -5062,25 +5728,37 @@ function tryGetObjectLikeCompletionContainer(contextToken: Node | undefined, pos case SyntaxKind.AsyncKeyword: return tryCast(parent.parent, isObjectLiteralExpression); case SyntaxKind.Identifier: - if ((contextToken as Identifier).text === "async" && isShorthandPropertyAssignment(contextToken.parent)) { + if ( + (contextToken as Identifier).text === "async" && isShorthandPropertyAssignment(contextToken.parent) + ) { return contextToken.parent.parent; } else { if ( - isObjectLiteralExpression(contextToken.parent.parent) && - (isSpreadAssignment(contextToken.parent) || isShorthandPropertyAssignment(contextToken.parent) && - (getLineAndCharacterOfPosition(sourceFile, contextToken.getEnd()).line !== getLineAndCharacterOfPosition(sourceFile, position).line)) + isObjectLiteralExpression(contextToken.parent.parent) + && (isSpreadAssignment(contextToken.parent) + || isShorthandPropertyAssignment(contextToken.parent) + && (getLineAndCharacterOfPosition(sourceFile, contextToken.getEnd()).line + !== getLineAndCharacterOfPosition(sourceFile, position).line)) ) { return contextToken.parent.parent; } const ancestorNode = findAncestor(parent, isPropertyAssignment); - if (ancestorNode?.getLastToken(sourceFile) === contextToken && isObjectLiteralExpression(ancestorNode.parent)) { + if ( + ancestorNode?.getLastToken(sourceFile) === contextToken + && isObjectLiteralExpression(ancestorNode.parent) + ) { return ancestorNode.parent; } } break; default: - if (parent.parent?.parent && (isMethodDeclaration(parent.parent) || isGetAccessorDeclaration(parent.parent) || isSetAccessorDeclaration(parent.parent)) && isObjectLiteralExpression(parent.parent.parent)) { + if ( + parent.parent?.parent + && (isMethodDeclaration(parent.parent) || isGetAccessorDeclaration(parent.parent) + || isSetAccessorDeclaration(parent.parent)) + && isObjectLiteralExpression(parent.parent.parent) + ) { return parent.parent.parent; } if (isSpreadAssignment(parent) && isObjectLiteralExpression(parent.parent)) { @@ -5088,8 +5766,9 @@ function tryGetObjectLikeCompletionContainer(contextToken: Node | undefined, pos } const ancestorNode = findAncestor(parent, isPropertyAssignment); if ( - contextToken.kind !== SyntaxKind.ColonToken && ancestorNode?.getLastToken(sourceFile) === contextToken && - isObjectLiteralExpression(ancestorNode.parent) + contextToken.kind !== SyntaxKind.ColonToken + && ancestorNode?.getLastToken(sourceFile) === contextToken + && isObjectLiteralExpression(ancestorNode.parent) ) { return ancestorNode.parent; } @@ -5099,21 +5778,32 @@ function tryGetObjectLikeCompletionContainer(contextToken: Node | undefined, pos return undefined; } -function getRelevantTokens(position: number, sourceFile: SourceFile): { contextToken: Node; previousToken: Node; } | { contextToken: undefined; previousToken: undefined; } { +function getRelevantTokens( + position: number, + sourceFile: SourceFile, +): { contextToken: Node; previousToken: Node; } | { contextToken: undefined; previousToken: undefined; } { const previousToken = findPrecedingToken(position, sourceFile); - if (previousToken && position <= previousToken.end && (isMemberName(previousToken) || isKeyword(previousToken.kind))) { + if ( + previousToken && position <= previousToken.end && (isMemberName(previousToken) || isKeyword(previousToken.kind)) + ) { const contextToken = findPrecedingToken(previousToken.getFullStart(), sourceFile, /*startNode*/ undefined)!; // TODO: GH#18217 return { contextToken, previousToken }; } return { contextToken: previousToken as Node, previousToken: previousToken as Node }; } -function getAutoImportSymbolFromCompletionEntryData(name: string, data: CompletionEntryData, program: Program, host: LanguageServiceHost): { symbol: Symbol; origin: SymbolOriginInfoExport | SymbolOriginInfoResolvedExport; } | undefined { +function getAutoImportSymbolFromCompletionEntryData( + name: string, + data: CompletionEntryData, + program: Program, + host: LanguageServiceHost, +): { symbol: Symbol; origin: SymbolOriginInfoExport | SymbolOriginInfoResolvedExport; } | undefined { const containingProgram = data.isPackageJsonImport ? host.getPackageJsonAutoImportProvider!()! : program; const checker = containingProgram.getTypeChecker(); - const moduleSymbol = data.ambientModuleName ? checker.tryFindAmbientModule(data.ambientModuleName) : - data.fileName ? checker.getMergedSymbol(Debug.checkDefined(containingProgram.getSourceFile(data.fileName)).symbol) : - undefined; + const moduleSymbol = data.ambientModuleName ? checker.tryFindAmbientModule(data.ambientModuleName) + : data.fileName + ? checker.getMergedSymbol(Debug.checkDefined(containingProgram.getSourceFile(data.fileName)).symbol) + : undefined; if (!moduleSymbol) return undefined; let symbol = data.exportName === InternalSymbolName.ExportEquals @@ -5152,12 +5842,16 @@ function getCompletionEntryDisplayNameForSymbol( } const validNameResult: CompletionEntryDisplayNameForSymbol = { name, needsConvertPropertyAccess: false }; - if (isIdentifierText(name, target, jsxIdentifierExpected ? LanguageVariant.JSX : LanguageVariant.Standard) || symbol.valueDeclaration && isPrivateIdentifierClassElementDeclaration(symbol.valueDeclaration)) { + if ( + isIdentifierText(name, target, jsxIdentifierExpected ? LanguageVariant.JSX : LanguageVariant.Standard) + || symbol.valueDeclaration && isPrivateIdentifierClassElementDeclaration(symbol.valueDeclaration) + ) { return validNameResult; } switch (kind) { case CompletionKind.MemberLike: - return originIsComputedPropertyName(origin) ? { name: origin.symbolName, needsConvertPropertyAccess: false } : undefined; + return originIsComputedPropertyName(origin) ? { name: origin.symbolName, needsConvertPropertyAccess: false } + : undefined; case CompletionKind.ObjectPropertyDeclaration: // TODO: GH#18169 return { name: JSON.stringify(name), needsConvertPropertyAccess: false }; @@ -5188,47 +5882,51 @@ const allKeywordsCompletions: () => readonly CompletionEntry[] = memoize(() => { return res; }); -function getKeywordCompletions(keywordFilter: KeywordCompletionFilters, filterOutTsOnlyKeywords: boolean): readonly CompletionEntry[] { +function getKeywordCompletions( + keywordFilter: KeywordCompletionFilters, + filterOutTsOnlyKeywords: boolean, +): readonly CompletionEntry[] { if (!filterOutTsOnlyKeywords) return getTypescriptKeywordCompletions(keywordFilter); const index = keywordFilter + KeywordCompletionFilters.Last + 1; - return _keywordCompletions[index] || - (_keywordCompletions[index] = getTypescriptKeywordCompletions(keywordFilter) + return _keywordCompletions[index] + || (_keywordCompletions[index] = getTypescriptKeywordCompletions(keywordFilter) .filter(entry => !isTypeScriptOnlyKeyword(stringToToken(entry.name)!))); } function getTypescriptKeywordCompletions(keywordFilter: KeywordCompletionFilters): readonly CompletionEntry[] { - return _keywordCompletions[keywordFilter] || (_keywordCompletions[keywordFilter] = allKeywordsCompletions().filter(entry => { - const kind = stringToToken(entry.name)!; - switch (keywordFilter) { - case KeywordCompletionFilters.None: - return false; - case KeywordCompletionFilters.All: - return isFunctionLikeBodyKeyword(kind) - || kind === SyntaxKind.DeclareKeyword - || kind === SyntaxKind.ModuleKeyword - || kind === SyntaxKind.TypeKeyword - || kind === SyntaxKind.NamespaceKeyword - || kind === SyntaxKind.AbstractKeyword - || isTypeKeyword(kind) && kind !== SyntaxKind.UndefinedKeyword; - case KeywordCompletionFilters.FunctionLikeBodyKeywords: - return isFunctionLikeBodyKeyword(kind); - case KeywordCompletionFilters.ClassElementKeywords: - return isClassMemberCompletionKeyword(kind); - case KeywordCompletionFilters.InterfaceElementKeywords: - return isInterfaceOrTypeLiteralCompletionKeyword(kind); - case KeywordCompletionFilters.ConstructorParameterKeywords: - return isParameterPropertyModifier(kind); - case KeywordCompletionFilters.TypeAssertionKeywords: - return isTypeKeyword(kind) || kind === SyntaxKind.ConstKeyword; - case KeywordCompletionFilters.TypeKeywords: - return isTypeKeyword(kind); - case KeywordCompletionFilters.TypeKeyword: - return kind === SyntaxKind.TypeKeyword; - default: - return Debug.assertNever(keywordFilter); - } - })); + return _keywordCompletions[keywordFilter] + || (_keywordCompletions[keywordFilter] = allKeywordsCompletions().filter(entry => { + const kind = stringToToken(entry.name)!; + switch (keywordFilter) { + case KeywordCompletionFilters.None: + return false; + case KeywordCompletionFilters.All: + return isFunctionLikeBodyKeyword(kind) + || kind === SyntaxKind.DeclareKeyword + || kind === SyntaxKind.ModuleKeyword + || kind === SyntaxKind.TypeKeyword + || kind === SyntaxKind.NamespaceKeyword + || kind === SyntaxKind.AbstractKeyword + || isTypeKeyword(kind) && kind !== SyntaxKind.UndefinedKeyword; + case KeywordCompletionFilters.FunctionLikeBodyKeywords: + return isFunctionLikeBodyKeyword(kind); + case KeywordCompletionFilters.ClassElementKeywords: + return isClassMemberCompletionKeyword(kind); + case KeywordCompletionFilters.InterfaceElementKeywords: + return isInterfaceOrTypeLiteralCompletionKeyword(kind); + case KeywordCompletionFilters.ConstructorParameterKeywords: + return isParameterPropertyModifier(kind); + case KeywordCompletionFilters.TypeAssertionKeywords: + return isTypeKeyword(kind) || kind === SyntaxKind.ConstKeyword; + case KeywordCompletionFilters.TypeKeywords: + return isTypeKeyword(kind); + case KeywordCompletionFilters.TypeKeyword: + return kind === SyntaxKind.TypeKeyword; + default: + return Debug.assertNever(keywordFilter); + } + })); } function isTypeScriptOnlyKeyword(kind: SyntaxKind) { @@ -5336,20 +6034,25 @@ function getContextualKeywords( /** Get the corresponding JSDocTag node if the position is in a jsDoc comment */ function getJsDocTagAtPosition(node: Node, position: number): JSDocTag | undefined { return findAncestor(node, n => - isJSDocTag(n) && rangeContainsPosition(n, position) ? true : - isJSDoc(n) ? "quit" : false) as JSDocTag | undefined; + isJSDocTag(n) && rangeContainsPosition(n, position) ? true + : isJSDoc(n) ? "quit" : false) as JSDocTag | undefined; } /** @internal */ -export function getPropertiesForObjectExpression(contextualType: Type, completionsType: Type | undefined, obj: ObjectLiteralExpression | JsxAttributes, checker: TypeChecker): Symbol[] { +export function getPropertiesForObjectExpression( + contextualType: Type, + completionsType: Type | undefined, + obj: ObjectLiteralExpression | JsxAttributes, + checker: TypeChecker, +): Symbol[] { const hasCompletionsType = completionsType && completionsType !== contextualType; const type = hasCompletionsType && !(completionsType.flags & TypeFlags.AnyOrUnknown) ? checker.getUnionType([contextualType, completionsType]) : contextualType; const properties = getApparentProperties(type, obj, checker); - return type.isClass() && containsNonPublicProperties(properties) ? [] : - hasCompletionsType ? filter(properties, hasDeclarationOtherThanSelf) : properties; + return type.isClass() && containsNonPublicProperties(properties) ? [] + : hasCompletionsType ? filter(properties, hasDeclarationOtherThanSelf) : properties; // Filter out members whose only declaration is the object literal itself to avoid // self-fulfilling completions like: @@ -5364,16 +6067,21 @@ export function getPropertiesForObjectExpression(contextualType: Type, completio function getApparentProperties(type: Type, node: ObjectLiteralExpression | JsxAttributes, checker: TypeChecker) { if (!type.isUnion()) return type.getApparentProperties(); - return checker.getAllPossiblePropertiesOfTypes(filter(type.types, memberType => - !(memberType.flags & TypeFlags.Primitive - || checker.isArrayLikeType(memberType) - || checker.isTypeInvalidDueToUnionDiscriminant(memberType, node) - || checker.typeHasCallOrConstructSignatures(memberType) - || memberType.isClass() && containsNonPublicProperties(memberType.getApparentProperties())))); + return checker.getAllPossiblePropertiesOfTypes( + filter(type.types, memberType => + !(memberType.flags & TypeFlags.Primitive + || checker.isArrayLikeType(memberType) + || checker.isTypeInvalidDueToUnionDiscriminant(memberType, node) + || checker.typeHasCallOrConstructSignatures(memberType) + || memberType.isClass() && containsNonPublicProperties(memberType.getApparentProperties()))), + ); } function containsNonPublicProperties(props: Symbol[]) { - return some(props, p => !!(getDeclarationModifierFlagsFromSymbol(p) & ModifierFlags.NonPublicAccessibilityModifier)); + return some( + props, + p => !!(getDeclarationModifierFlagsFromSymbol(p) & ModifierFlags.NonPublicAccessibilityModifier), + ); } /** @@ -5382,7 +6090,10 @@ function containsNonPublicProperties(props: Symbol[]) { */ function getPropertiesForCompletion(type: Type, checker: TypeChecker): Symbol[] { return type.isUnion() - ? Debug.checkEachDefined(checker.getAllPossiblePropertiesOfTypes(type.types), "getAllPossiblePropertiesOfTypes() should all be defined") + ? Debug.checkEachDefined( + checker.getAllPossiblePropertiesOfTypes(type.types), + "getAllPossiblePropertiesOfTypes() should all be defined", + ) : Debug.checkEachDefined(type.getApparentProperties(), "getApparentProperties() should all be defined"); } @@ -5390,13 +6101,21 @@ function getPropertiesForCompletion(type: Type, checker: TypeChecker): Symbol[] * Returns the immediate owning class declaration of a context token, * on the condition that one exists and that the context implies completion should be given. */ -function tryGetObjectTypeDeclarationCompletionContainer(sourceFile: SourceFile, contextToken: Node | undefined, location: Node, position: number): ObjectTypeDeclaration | undefined { +function tryGetObjectTypeDeclarationCompletionContainer( + sourceFile: SourceFile, + contextToken: Node | undefined, + location: Node, + position: number, +): ObjectTypeDeclaration | undefined { // class c { method() { } | method2() { } } switch (location.kind) { case SyntaxKind.SyntaxList: return tryCast(location.parent, isObjectTypeDeclaration); case SyntaxKind.EndOfFileToken: - const cls = tryCast(lastOrUndefined(cast(location.parent, isSourceFile).statements), isObjectTypeDeclaration); + const cls = tryCast( + lastOrUndefined(cast(location.parent, isSourceFile).statements), + isObjectTypeDeclaration, + ); if (cls && !findChildOfKind(cls, SyntaxKind.CloseBraceToken, sourceFile)) { return cls; } @@ -5440,7 +6159,8 @@ function tryGetObjectTypeDeclarationCompletionContainer(sourceFile: SourceFile, case SyntaxKind.SemicolonToken: // class c {getValue(): number; | } case SyntaxKind.CloseBraceToken: // class c { method() { } | } // class c { method() { } b| } - return isFromObjectTypeDeclaration(location) && (location.parent as ClassElement | TypeElement).name === location + return isFromObjectTypeDeclaration(location) + && (location.parent as ClassElement | TypeElement).name === location ? location.parent.parent as ObjectTypeDeclaration : tryCast(location, isObjectTypeDeclaration); case SyntaxKind.OpenBraceToken: // class c { | @@ -5450,11 +6170,17 @@ function tryGetObjectTypeDeclarationCompletionContainer(sourceFile: SourceFile, if (isObjectTypeDeclaration(location)) { // class C extends React.Component { a: () => 1\n| } // class C { prop = ""\n | } - if (getLineAndCharacterOfPosition(sourceFile, contextToken.getEnd()).line !== getLineAndCharacterOfPosition(sourceFile, position).line) { + if ( + getLineAndCharacterOfPosition(sourceFile, contextToken.getEnd()).line + !== getLineAndCharacterOfPosition(sourceFile, position).line + ) { return location; } - const isValidKeyword = isClassLike(contextToken.parent.parent) ? isClassMemberCompletionKeyword : isInterfaceOrTypeLiteralCompletionKeyword; - return (isValidKeyword(contextToken.kind) || contextToken.kind === SyntaxKind.AsteriskToken || isIdentifier(contextToken) && isValidKeyword(identifierToKeywordKind(contextToken) ?? SyntaxKind.Unknown)) + const isValidKeyword = isClassLike(contextToken.parent.parent) ? isClassMemberCompletionKeyword + : isInterfaceOrTypeLiteralCompletionKeyword; + return (isValidKeyword(contextToken.kind) || contextToken.kind === SyntaxKind.AsteriskToken + || isIdentifier(contextToken) + && isValidKeyword(identifierToKeywordKind(contextToken) ?? SyntaxKind.Unknown)) ? contextToken.parent.parent as ObjectTypeDeclaration : undefined; } return undefined; @@ -5509,7 +6235,12 @@ function isFromObjectTypeDeclaration(node: Node): boolean { return node.parent && isClassOrTypeElement(node.parent) && isObjectTypeDeclaration(node.parent.parent); } -function isValidTrigger(sourceFile: SourceFile, triggerCharacter: CompletionsTriggerCharacter, contextToken: Node | undefined, position: number): boolean { +function isValidTrigger( + sourceFile: SourceFile, + triggerCharacter: CompletionsTriggerCharacter, + contextToken: Node | undefined, + position: number, +): boolean { switch (triggerCharacter) { case ".": case "@": @@ -5518,18 +6249,21 @@ function isValidTrigger(sourceFile: SourceFile, triggerCharacter: CompletionsTri case "'": case "`": // Only automatically bring up completions if this is an opening quote. - return !!contextToken && isStringLiteralOrTemplate(contextToken) && position === contextToken.getStart(sourceFile) + 1; + return !!contextToken && isStringLiteralOrTemplate(contextToken) + && position === contextToken.getStart(sourceFile) + 1; case "#": return !!contextToken && isPrivateIdentifier(contextToken) && !!getContainingClass(contextToken); case "<": // Opening JSX tag - return !!contextToken && contextToken.kind === SyntaxKind.LessThanToken && (!isBinaryExpression(contextToken.parent) || binaryExpressionMayBeOpenTag(contextToken.parent)); + return !!contextToken && contextToken.kind === SyntaxKind.LessThanToken + && (!isBinaryExpression(contextToken.parent) || binaryExpressionMayBeOpenTag(contextToken.parent)); case "/": return !!contextToken && (isStringLiteralLike(contextToken) ? !!tryGetImportFromModuleSpecifier(contextToken) : contextToken.kind === SyntaxKind.SlashToken && isJsxClosingElement(contextToken.parent)); case " ": - return !!contextToken && isImportKeyword(contextToken) && contextToken.parent.kind === SyntaxKind.SourceFile; + return !!contextToken && isImportKeyword(contextToken) + && contextToken.parent.kind === SyntaxKind.SourceFile; default: return Debug.assertNever(triggerCharacter); } @@ -5547,11 +6281,21 @@ function isProbablyGlobalType(type: Type, sourceFile: SourceFile, checker: TypeC if (selfSymbol && checker.getTypeOfSymbolAtLocation(selfSymbol, sourceFile) === type) { return true; } - const globalSymbol = checker.resolveName("global", /*location*/ undefined, SymbolFlags.Value, /*excludeGlobals*/ false); + const globalSymbol = checker.resolveName( + "global", + /*location*/ undefined, + SymbolFlags.Value, + /*excludeGlobals*/ false, + ); if (globalSymbol && checker.getTypeOfSymbolAtLocation(globalSymbol, sourceFile) === type) { return true; } - const globalThisSymbol = checker.resolveName("globalThis", /*location*/ undefined, SymbolFlags.Value, /*excludeGlobals*/ false); + const globalThisSymbol = checker.resolveName( + "globalThis", + /*location*/ undefined, + SymbolFlags.Value, + /*excludeGlobals*/ false, + ); if (globalThisSymbol && checker.getTypeOfSymbolAtLocation(globalThisSymbol, sourceFile) === type) { return true; } @@ -5559,7 +6303,8 @@ function isProbablyGlobalType(type: Type, sourceFile: SourceFile, checker: TypeC } function isStaticProperty(symbol: Symbol) { - return !!(symbol.valueDeclaration && getEffectiveModifierFlags(symbol.valueDeclaration) & ModifierFlags.Static && isClassLike(symbol.valueDeclaration.parent)); + return !!(symbol.valueDeclaration && getEffectiveModifierFlags(symbol.valueDeclaration) & ModifierFlags.Static + && isClassLike(symbol.valueDeclaration.parent)); } function tryGetObjectLiteralContextualType(node: ObjectLiteralExpression, typeChecker: TypeChecker) { @@ -5597,7 +6342,8 @@ function getImportStatementCompletionInfo(contextToken: Node, sourceFile: Source isKeywordOnlyCompletion, keywordCompletion, isNewIdentifierLocation: !!(candidate || keywordCompletion === SyntaxKind.TypeKeyword), - isTopLevelTypeOnly: !!tryCast(candidate, isImportDeclaration)?.importClause?.isTypeOnly || !!tryCast(candidate, isImportEqualsDeclaration)?.isTypeOnly, + isTopLevelTypeOnly: !!tryCast(candidate, isImportDeclaration)?.importClause?.isTypeOnly + || !!tryCast(candidate, isImportEqualsDeclaration)?.isTypeOnly, couldBeTypeOnlyImportSpecifier: !!candidate && couldBeTypeOnlyImportSpecifier(candidate, contextToken), replacementSpan: getSingleLineReplacementSpanForImportCompletionNode(candidate), }; @@ -5623,9 +6369,9 @@ function getImportStatementCompletionInfo(contextToken: Node, sourceFile: Source if (isNamedImports(parent) || isNamespaceImport(parent)) { if ( !parent.parent.isTypeOnly && ( - contextToken.kind === SyntaxKind.OpenBraceToken || - contextToken.kind === SyntaxKind.ImportKeyword || - contextToken.kind === SyntaxKind.CommaToken + contextToken.kind === SyntaxKind.OpenBraceToken + || contextToken.kind === SyntaxKind.ImportKeyword + || contextToken.kind === SyntaxKind.CommaToken ) ) { keywordCompletion = SyntaxKind.TypeKeyword; @@ -5657,7 +6403,9 @@ function getImportStatementCompletionInfo(contextToken: Node, sourceFile: Source } } -function getSingleLineReplacementSpanForImportCompletionNode(node: ImportDeclaration | ImportEqualsDeclaration | ImportSpecifier | Token | undefined) { +function getSingleLineReplacementSpanForImportCompletionNode( + node: ImportDeclaration | ImportEqualsDeclaration | ImportSpecifier | Token | undefined, +) { if (!node) return undefined; const top = findAncestor(node, or(isImportDeclaration, isImportEqualsDeclaration)) ?? node; const sourceFile = top.getSourceFile(); @@ -5698,15 +6446,20 @@ function getSingleLineReplacementSpanForImportCompletionNode(node: ImportDeclara function getPotentiallyInvalidImportSpecifier(namedBindings: NamedImportBindings | undefined) { return find( tryCast(namedBindings, isNamedImports)?.elements, - e => !e.propertyName && - isStringANonContextualKeyword(e.name.text) && - findPrecedingToken(e.name.pos, namedBindings!.getSourceFile(), namedBindings)?.kind !== SyntaxKind.CommaToken, + e => !e.propertyName + && isStringANonContextualKeyword(e.name.text) + && findPrecedingToken(e.name.pos, namedBindings!.getSourceFile(), namedBindings)?.kind + !== SyntaxKind.CommaToken, ); } -function couldBeTypeOnlyImportSpecifier(importSpecifier: Node, contextToken: Node | undefined): importSpecifier is ImportSpecifier { +function couldBeTypeOnlyImportSpecifier( + importSpecifier: Node, + contextToken: Node | undefined, +): importSpecifier is ImportSpecifier { return isImportSpecifier(importSpecifier) - && (importSpecifier.isTypeOnly || contextToken === importSpecifier.name && isTypeKeywordTokenOrIdentifier(contextToken)); + && (importSpecifier.isTypeOnly + || contextToken === importSpecifier.name && isTypeKeywordTokenOrIdentifier(contextToken)); } function canCompleteFromNamedBindings(namedBindings: NamedImportBindings) { @@ -5718,7 +6471,8 @@ function canCompleteFromNamedBindings(namedBindings: NamedImportBindings) { // but parser recovery sometimes puts later statements in the named imports list, so // we try to only consider the probably-valid ones. const invalidNamedImport = getPotentiallyInvalidImportSpecifier(namedBindings); - const validImports = invalidNamedImport ? namedBindings.elements.indexOf(invalidNamedImport) : namedBindings.elements.length; + const validImports = invalidNamedImport ? namedBindings.elements.indexOf(invalidNamedImport) + : namedBindings.elements.length; return validImports < 2; } return true; @@ -5732,36 +6486,54 @@ function isModuleSpecifierMissingOrEmpty(specifier: ModuleReference | Expression function getVariableOrParameterDeclaration(contextToken: Node | undefined, location: Node) { if (!contextToken) return; - const possiblyParameterDeclaration = findAncestor(contextToken, node => - isFunctionBlock(node) || isArrowFunctionBody(node) || isBindingPattern(node) - ? "quit" - : ((isParameter(node) || isTypeParameterDeclaration(node)) && !isIndexSignatureDeclaration(node.parent))); + const possiblyParameterDeclaration = findAncestor( + contextToken, + node => + isFunctionBlock(node) || isArrowFunctionBody(node) || isBindingPattern(node) + ? "quit" + : ((isParameter(node) || isTypeParameterDeclaration(node)) + && !isIndexSignatureDeclaration(node.parent)), + ); - const possiblyVariableDeclaration = findAncestor(location, node => - isFunctionBlock(node) || isArrowFunctionBody(node) || isBindingPattern(node) - ? "quit" - : isVariableDeclaration(node)); + const possiblyVariableDeclaration = findAncestor( + location, + node => + isFunctionBlock(node) || isArrowFunctionBody(node) || isBindingPattern(node) + ? "quit" + : isVariableDeclaration(node), + ); - return (possiblyParameterDeclaration || possiblyVariableDeclaration) as ParameterDeclaration | TypeParameterDeclaration | VariableDeclaration | undefined; + return (possiblyParameterDeclaration || possiblyVariableDeclaration) as + | ParameterDeclaration + | TypeParameterDeclaration + | VariableDeclaration + | undefined; } function isArrowFunctionBody(node: Node) { - return node.parent && isArrowFunction(node.parent) && - (node.parent.body === node || + return node.parent && isArrowFunction(node.parent) + && (node.parent.body === node // const a = () => /**/; - node.kind === SyntaxKind.EqualsGreaterThanToken); + || node.kind === SyntaxKind.EqualsGreaterThanToken); } /** True if symbol is a type or a module containing at least one type. */ -function symbolCanBeReferencedAtTypeLocation(symbol: Symbol, checker: TypeChecker, seenModules = new Map()): boolean { +function symbolCanBeReferencedAtTypeLocation( + symbol: Symbol, + checker: TypeChecker, + seenModules = new Map(), +): boolean { // Since an alias can be merged with a local declaration, we need to test both the alias and its target. // This code used to just test the result of `skipAlias`, but that would ignore any locally introduced meanings. - return nonAliasCanBeReferencedAtTypeLocation(symbol) || nonAliasCanBeReferencedAtTypeLocation(skipAlias(symbol.exportSymbol || symbol, checker)); + return nonAliasCanBeReferencedAtTypeLocation(symbol) + || nonAliasCanBeReferencedAtTypeLocation(skipAlias(symbol.exportSymbol || symbol, checker)); function nonAliasCanBeReferencedAtTypeLocation(symbol: Symbol): boolean { - return !!(symbol.flags & SymbolFlags.Type) || checker.isUnknownSymbol(symbol) || - !!(symbol.flags & SymbolFlags.Module) && addToSeen(seenModules, getSymbolId(symbol)) && - checker.getExportsOfModule(symbol).some(e => symbolCanBeReferencedAtTypeLocation(e, checker, seenModules)); + return !!(symbol.flags & SymbolFlags.Type) || checker.isUnknownSymbol(symbol) + || !!(symbol.flags & SymbolFlags.Module) && addToSeen(seenModules, getSymbolId(symbol)) + && checker.getExportsOfModule(symbol).some(e => + symbolCanBeReferencedAtTypeLocation(e, checker, seenModules) + ); } } @@ -5799,9 +6571,10 @@ function charactersFuzzyMatchInString(identifierString: string, lowercaseCharact const strChar = identifierString.charCodeAt(strIndex); const testChar = lowercaseCharacters.charCodeAt(characterIndex); if (strChar === testChar || strChar === toUpperCharCode(testChar)) { - matchedFirstCharacter ||= prevChar === undefined || // Beginning of word - CharacterCodes.a <= prevChar && prevChar <= CharacterCodes.z && CharacterCodes.A <= strChar && strChar <= CharacterCodes.Z || // camelCase transition - prevChar === CharacterCodes._ && strChar !== CharacterCodes._; // snake_case transition + matchedFirstCharacter ||= prevChar === undefined // Beginning of word + || CharacterCodes.a <= prevChar && prevChar <= CharacterCodes.z && CharacterCodes.A <= strChar + && strChar <= CharacterCodes.Z // camelCase transition + || prevChar === CharacterCodes._ && strChar !== CharacterCodes._; // snake_case transition if (matchedFirstCharacter) { characterIndex++; } diff --git a/src/services/documentHighlights.ts b/src/services/documentHighlights.ts index b5c92cc1b3f17..ce5b0fd1afa39 100644 --- a/src/services/documentHighlights.ts +++ b/src/services/documentHighlights.ts @@ -90,17 +90,29 @@ export interface DocumentHighlights { /** @internal */ export namespace DocumentHighlights { - export function getDocumentHighlights(program: Program, cancellationToken: CancellationToken, sourceFile: SourceFile, position: number, sourceFilesToSearch: readonly SourceFile[]): DocumentHighlights[] | undefined { + export function getDocumentHighlights( + program: Program, + cancellationToken: CancellationToken, + sourceFile: SourceFile, + position: number, + sourceFilesToSearch: readonly SourceFile[], + ): DocumentHighlights[] | undefined { const node = getTouchingPropertyName(sourceFile, position); - if (node.parent && (isJsxOpeningElement(node.parent) && node.parent.tagName === node || isJsxClosingElement(node.parent))) { + if ( + node.parent + && (isJsxOpeningElement(node.parent) && node.parent.tagName === node || isJsxClosingElement(node.parent)) + ) { // For a JSX element, just highlight the matching tag, not all references. const { openingElement, closingElement } = node.parent.parent; - const highlightSpans = [openingElement, closingElement].map(({ tagName }) => getHighlightSpanForNode(tagName, sourceFile)); + const highlightSpans = [openingElement, closingElement].map(({ tagName }) => + getHighlightSpanForNode(tagName, sourceFile) + ); return [{ fileName: sourceFile.fileName, highlightSpans }]; } - return getSemanticDocumentHighlights(position, node, program, cancellationToken, sourceFilesToSearch) || getSyntacticDocumentHighlights(node, sourceFile); + return getSemanticDocumentHighlights(position, node, program, cancellationToken, sourceFilesToSearch) + || getSyntacticDocumentHighlights(node, sourceFile); } function getHighlightSpanForNode(node: Node, sourceFile: SourceFile): HighlightSpan { @@ -111,19 +123,44 @@ export namespace DocumentHighlights { }; } - function getSemanticDocumentHighlights(position: number, node: Node, program: Program, cancellationToken: CancellationToken, sourceFilesToSearch: readonly SourceFile[]): DocumentHighlights[] | undefined { + function getSemanticDocumentHighlights( + position: number, + node: Node, + program: Program, + cancellationToken: CancellationToken, + sourceFilesToSearch: readonly SourceFile[], + ): DocumentHighlights[] | undefined { const sourceFilesSet = new Set(sourceFilesToSearch.map(f => f.fileName)); - const referenceEntries = FindAllReferences.getReferenceEntriesForNode(position, node, program, sourceFilesToSearch, cancellationToken, /*options*/ undefined, sourceFilesSet); + const referenceEntries = FindAllReferences.getReferenceEntriesForNode( + position, + node, + program, + sourceFilesToSearch, + cancellationToken, + /*options*/ undefined, + sourceFilesSet, + ); if (!referenceEntries) return undefined; - const map = arrayToMultiMap(referenceEntries.map(FindAllReferences.toHighlightSpan), e => e.fileName, e => e.span); + const map = arrayToMultiMap( + referenceEntries.map(FindAllReferences.toHighlightSpan), + e => e.fileName, + e => e.span, + ); const getCanonicalFileName = createGetCanonicalFileName(program.useCaseSensitiveFileNames()); return arrayFrom(mapDefinedIterator(map.entries(), ([fileName, highlightSpans]) => { if (!sourceFilesSet.has(fileName)) { - if (!program.redirectTargetsMap.has(toPath(fileName, program.getCurrentDirectory(), getCanonicalFileName))) { + if ( + !program.redirectTargetsMap.has( + toPath(fileName, program.getCurrentDirectory(), getCanonicalFileName), + ) + ) { return undefined; } const redirectTarget = program.getSourceFile(fileName); - const redirect = find(sourceFilesToSearch, f => !!f.redirectInfo && f.redirectInfo.redirectTarget === redirectTarget)!; + const redirect = find( + sourceFilesToSearch, + f => !!f.redirectInfo && f.redirectInfo.redirectTarget === redirectTarget, + )!; fileName = redirect.fileName; Debug.assert(sourceFilesSet.has(fileName)); } @@ -165,7 +202,11 @@ export namespace DocumentHighlights { case SyntaxKind.ForKeyword: case SyntaxKind.WhileKeyword: case SyntaxKind.DoKeyword: - return useParent(node.parent, (n): n is IterationStatement => isIterationStatement(n, /*lookInLabeledStatements*/ true), getLoopBreakContinueOccurrences); + return useParent( + node.parent, + (n): n is IterationStatement => isIterationStatement(n, /*lookInLabeledStatements*/ true), + getLoopBreakContinueOccurrences, + ); case SyntaxKind.ConstructorKeyword: return getFromAllDeclarations(isConstructorDeclaration, [SyntaxKind.ConstructorKeyword]); case SyntaxKind.GetKeyword: @@ -185,11 +226,26 @@ export namespace DocumentHighlights { : undefined; } - function getFromAllDeclarations(nodeTest: (node: Node) => node is T, keywords: readonly SyntaxKind[]): HighlightSpan[] | undefined { - return useParent(node.parent, nodeTest, decl => mapDefined(tryCast(decl, canHaveSymbol)?.symbol.declarations, d => nodeTest(d) ? find(d.getChildren(sourceFile), c => contains(keywords, c.kind)) : undefined)); + function getFromAllDeclarations( + nodeTest: (node: Node) => node is T, + keywords: readonly SyntaxKind[], + ): HighlightSpan[] | undefined { + return useParent( + node.parent, + nodeTest, + decl => + mapDefined( + tryCast(decl, canHaveSymbol)?.symbol.declarations, + d => nodeTest(d) ? find(d.getChildren(sourceFile), c => contains(keywords, c.kind)) : undefined, + ), + ); } - function useParent(node: Node, nodeTest: (node: Node) => node is T, getNodes: (node: T, sourceFile: SourceFile) => readonly Node[] | undefined): HighlightSpan[] | undefined { + function useParent( + node: Node, + nodeTest: (node: Node) => node is T, + getNodes: (node: T, sourceFile: SourceFile) => readonly Node[] | undefined, + ): HighlightSpan[] | undefined { return nodeTest(node) ? highlightSpans(getNodes(node, sourceFile)) : undefined; } @@ -209,7 +265,8 @@ export namespace DocumentHighlights { else if (isTryStatement(node)) { // Exceptions thrown within a try block lacking a catch clause are "owned" in the current context. return concatenate( - node.catchClause ? aggregateOwnedThrowStatements(node.catchClause) : node.tryBlock && aggregateOwnedThrowStatements(node.tryBlock), + node.catchClause ? aggregateOwnedThrowStatements(node.catchClause) + : node.tryBlock && aggregateOwnedThrowStatements(node.tryBlock), node.finallyBlock && aggregateOwnedThrowStatements(node.finallyBlock), ); } @@ -245,7 +302,8 @@ export namespace DocumentHighlights { } function aggregateAllBreakAndContinueStatements(node: Node): readonly BreakOrContinueStatement[] | undefined { - return isBreakOrContinueStatement(node) ? [node] : isFunctionLike(node) ? undefined : flatMapChildren(node, aggregateAllBreakAndContinueStatements); + return isBreakOrContinueStatement(node) ? [node] + : isFunctionLike(node) ? undefined : flatMapChildren(node, aggregateAllBreakAndContinueStatements); } function flatMapChildren(node: Node, cb: (child: Node) => readonly T[] | T | undefined): readonly T[] { @@ -288,12 +346,25 @@ export namespace DocumentHighlights { } function getModifierOccurrences(modifier: Modifier["kind"], declaration: Node): Node[] { - return mapDefined(getNodesToSearchForModifier(declaration, modifierToFlag(modifier)), node => findModifier(node, modifier)); + return mapDefined( + getNodesToSearchForModifier(declaration, modifierToFlag(modifier)), + node => findModifier(node, modifier), + ); } function getNodesToSearchForModifier(declaration: Node, modifierFlag: ModifierFlags): readonly Node[] | undefined { // Types of node whose children might have modifiers. - const container = declaration.parent as ModuleBlock | SourceFile | Block | CaseClause | DefaultClause | ConstructorDeclaration | MethodDeclaration | FunctionDeclaration | ObjectTypeDeclaration | ObjectLiteralExpression; + const container = declaration.parent as + | ModuleBlock + | SourceFile + | Block + | CaseClause + | DefaultClause + | ConstructorDeclaration + | MethodDeclaration + | FunctionDeclaration + | ObjectTypeDeclaration + | ObjectLiteralExpression; switch (container.kind) { case SyntaxKind.ModuleBlock: case SyntaxKind.SourceFile: @@ -351,7 +422,15 @@ export namespace DocumentHighlights { function getLoopBreakContinueOccurrences(loopNode: IterationStatement): Node[] { const keywords: Node[] = []; - if (pushKeywordIf(keywords, loopNode.getFirstToken(), SyntaxKind.ForKeyword, SyntaxKind.WhileKeyword, SyntaxKind.DoKeyword)) { + if ( + pushKeywordIf( + keywords, + loopNode.getFirstToken(), + SyntaxKind.ForKeyword, + SyntaxKind.WhileKeyword, + SyntaxKind.DoKeyword, + ) + ) { // If we succeeded and got a do-while loop, then start looking for a 'while' keyword. if (loopNode.kind === SyntaxKind.DoStatement) { const loopTokens = loopNode.getChildren(); @@ -373,7 +452,9 @@ export namespace DocumentHighlights { return keywords; } - function getBreakOrContinueStatementOccurrences(breakOrContinueStatement: BreakOrContinueStatement): Node[] | undefined { + function getBreakOrContinueStatementOccurrences( + breakOrContinueStatement: BreakOrContinueStatement, + ): Node[] | undefined { const owner = getBreakOrContinueOwner(breakOrContinueStatement); if (owner) { @@ -518,7 +599,10 @@ export namespace DocumentHighlights { // Do not cross function/class/interface/module/type boundaries. function traverseWithoutCrossingFunction(node: Node, cb: (node: Node) => void) { cb(node); - if (!isFunctionLike(node) && !isClassLike(node) && !isInterfaceDeclaration(node) && !isModuleDeclaration(node) && !isTypeAliasDeclaration(node) && !isTypeNode(node)) { + if ( + !isFunctionLike(node) && !isClassLike(node) && !isInterfaceDeclaration(node) && !isModuleDeclaration(node) + && !isTypeAliasDeclaration(node) && !isTypeNode(node) + ) { forEachChild(node, child => traverseWithoutCrossingFunction(child, cb)); } } @@ -597,6 +681,9 @@ export namespace DocumentHighlights { * Note: 'node' cannot be a SourceFile. */ function isLabeledBy(node: Node, labelName: __String): boolean { - return !!findAncestor(node.parent, owner => !isLabeledStatement(owner) ? "quit" : owner.label.escapedText === labelName); + return !!findAncestor( + node.parent, + owner => !isLabeledStatement(owner) ? "quit" : owner.label.escapedText === labelName, + ); } } diff --git a/src/services/documentRegistry.ts b/src/services/documentRegistry.ts index 9fc06295100cd..b4f473d2d5dfa 100644 --- a/src/services/documentRegistry.ts +++ b/src/services/documentRegistry.ts @@ -118,7 +118,10 @@ export interface DocumentRegistry { getKeyForCompilationSettings(settings: CompilerOptions): DocumentRegistryBucketKey; /** @internal */ - getDocumentRegistryBucketKeyWithMode(key: DocumentRegistryBucketKey, mode: ResolutionMode): DocumentRegistryBucketKeyWithMode; + getDocumentRegistryBucketKeyWithMode( + key: DocumentRegistryBucketKey, + mode: ResolutionMode, + ): DocumentRegistryBucketKeyWithMode; /** * Informs the DocumentRegistry that a file is not needed any longer. * @@ -143,11 +146,21 @@ export interface DocumentRegistry { * @param scriptKind The script kind of the file to be released * @param impliedNodeFormat The implied source file format of the file to be released */ - releaseDocument(fileName: string, compilationSettings: CompilerOptions, scriptKind: ScriptKind, impliedNodeFormat: ResolutionMode): void; // eslint-disable-line @typescript-eslint/unified-signatures + releaseDocument( + fileName: string, + compilationSettings: CompilerOptions, + scriptKind: ScriptKind, + impliedNodeFormat: ResolutionMode, + ): void; // eslint-disable-line @typescript-eslint/unified-signatures /** * @deprecated pass scriptKind for and impliedNodeFormat correctness */ releaseDocumentWithKey(path: Path, key: DocumentRegistryBucketKey, scriptKind?: ScriptKind): void; - releaseDocumentWithKey(path: Path, key: DocumentRegistryBucketKey, scriptKind: ScriptKind, impliedNodeFormat: ResolutionMode): void; // eslint-disable-line @typescript-eslint/unified-signatures + releaseDocumentWithKey( + path: Path, + key: DocumentRegistryBucketKey, + scriptKind: ScriptKind, + impliedNodeFormat: ResolutionMode, + ): void; // eslint-disable-line @typescript-eslint/unified-signatures reportStats(): string; /** @internal */ getBuckets(): Map>; @@ -178,14 +191,21 @@ export function isDocumentRegistryEntry(entry: BucketEntry): entry is DocumentRe return !!(entry as DocumentRegistryEntry).sourceFile; } -export function createDocumentRegistry(useCaseSensitiveFileNames?: boolean, currentDirectory?: string): DocumentRegistry { +export function createDocumentRegistry( + useCaseSensitiveFileNames?: boolean, + currentDirectory?: string, +): DocumentRegistry { return createDocumentRegistryInternal(useCaseSensitiveFileNames, currentDirectory); } /** @internal */ export type DocumentRegistryBucketKeyWithMode = string & { __documentRegistryBucketKeyWithMode: any; }; /** @internal */ -export function createDocumentRegistryInternal(useCaseSensitiveFileNames?: boolean, currentDirectory = "", externalCache?: ExternalDocumentCache): DocumentRegistry { +export function createDocumentRegistryInternal( + useCaseSensitiveFileNames?: boolean, + currentDirectory = "", + externalCache?: ExternalDocumentCache, +): DocumentRegistry { // Maps from compiler setting target (ES3, ES5, etc.) to all the cached documents we have // for those settings. const buckets = new Map>(); @@ -204,7 +224,9 @@ export function createDocumentRegistryInternal(useCaseSensitiveFileNames?: boole }); } else { - entry.forEach((value, scriptKind) => sourceFiles.push({ name, scriptKind, refCount: value.languageServiceRefCount })); + entry.forEach((value, scriptKind) => + sourceFiles.push({ name, scriptKind, refCount: value.languageServiceRefCount }) + ); } }); sourceFiles.sort((x, y) => y.refCount - x.refCount); @@ -223,29 +245,108 @@ export function createDocumentRegistryInternal(useCaseSensitiveFileNames?: boole return settingsOrHost as CompilerOptions; } - function acquireDocument(fileName: string, compilationSettings: CompilerOptions | MinimalResolutionCacheHost, scriptSnapshot: IScriptSnapshot, version: string, scriptKind?: ScriptKind, languageVersionOrOptions?: CreateSourceFileOptions | ScriptTarget): SourceFile { + function acquireDocument( + fileName: string, + compilationSettings: CompilerOptions | MinimalResolutionCacheHost, + scriptSnapshot: IScriptSnapshot, + version: string, + scriptKind?: ScriptKind, + languageVersionOrOptions?: CreateSourceFileOptions | ScriptTarget, + ): SourceFile { const path = toPath(fileName, currentDirectory, getCanonicalFileName); const key = getKeyForCompilationSettings(getCompilationSettings(compilationSettings)); - return acquireDocumentWithKey(fileName, path, compilationSettings, key, scriptSnapshot, version, scriptKind, languageVersionOrOptions); + return acquireDocumentWithKey( + fileName, + path, + compilationSettings, + key, + scriptSnapshot, + version, + scriptKind, + languageVersionOrOptions, + ); } - function acquireDocumentWithKey(fileName: string, path: Path, compilationSettings: CompilerOptions | MinimalResolutionCacheHost, key: DocumentRegistryBucketKey, scriptSnapshot: IScriptSnapshot, version: string, scriptKind?: ScriptKind, languageVersionOrOptions?: CreateSourceFileOptions | ScriptTarget): SourceFile { - return acquireOrUpdateDocument(fileName, path, compilationSettings, key, scriptSnapshot, version, /*acquiring*/ true, scriptKind, languageVersionOrOptions); + function acquireDocumentWithKey( + fileName: string, + path: Path, + compilationSettings: CompilerOptions | MinimalResolutionCacheHost, + key: DocumentRegistryBucketKey, + scriptSnapshot: IScriptSnapshot, + version: string, + scriptKind?: ScriptKind, + languageVersionOrOptions?: CreateSourceFileOptions | ScriptTarget, + ): SourceFile { + return acquireOrUpdateDocument( + fileName, + path, + compilationSettings, + key, + scriptSnapshot, + version, + /*acquiring*/ true, + scriptKind, + languageVersionOrOptions, + ); } - function updateDocument(fileName: string, compilationSettings: CompilerOptions | MinimalResolutionCacheHost, scriptSnapshot: IScriptSnapshot, version: string, scriptKind?: ScriptKind, languageVersionOrOptions?: CreateSourceFileOptions | ScriptTarget): SourceFile { + function updateDocument( + fileName: string, + compilationSettings: CompilerOptions | MinimalResolutionCacheHost, + scriptSnapshot: IScriptSnapshot, + version: string, + scriptKind?: ScriptKind, + languageVersionOrOptions?: CreateSourceFileOptions | ScriptTarget, + ): SourceFile { const path = toPath(fileName, currentDirectory, getCanonicalFileName); const key = getKeyForCompilationSettings(getCompilationSettings(compilationSettings)); - return updateDocumentWithKey(fileName, path, compilationSettings, key, scriptSnapshot, version, scriptKind, languageVersionOrOptions); + return updateDocumentWithKey( + fileName, + path, + compilationSettings, + key, + scriptSnapshot, + version, + scriptKind, + languageVersionOrOptions, + ); } - function updateDocumentWithKey(fileName: string, path: Path, compilationSettings: CompilerOptions | MinimalResolutionCacheHost, key: DocumentRegistryBucketKey, scriptSnapshot: IScriptSnapshot, version: string, scriptKind?: ScriptKind, languageVersionOrOptions?: CreateSourceFileOptions | ScriptTarget): SourceFile { - return acquireOrUpdateDocument(fileName, path, getCompilationSettings(compilationSettings), key, scriptSnapshot, version, /*acquiring*/ false, scriptKind, languageVersionOrOptions); + function updateDocumentWithKey( + fileName: string, + path: Path, + compilationSettings: CompilerOptions | MinimalResolutionCacheHost, + key: DocumentRegistryBucketKey, + scriptSnapshot: IScriptSnapshot, + version: string, + scriptKind?: ScriptKind, + languageVersionOrOptions?: CreateSourceFileOptions | ScriptTarget, + ): SourceFile { + return acquireOrUpdateDocument( + fileName, + path, + getCompilationSettings(compilationSettings), + key, + scriptSnapshot, + version, + /*acquiring*/ false, + scriptKind, + languageVersionOrOptions, + ); } function getDocumentRegistryEntry(bucketEntry: BucketEntry, scriptKind: ScriptKind | undefined) { - const entry = isDocumentRegistryEntry(bucketEntry) ? bucketEntry : bucketEntry.get(Debug.checkDefined(scriptKind, "If there are more than one scriptKind's for same document the scriptKind should be provided")); - Debug.assert(scriptKind === undefined || !entry || entry.sourceFile.scriptKind === scriptKind, `Script kind should match provided ScriptKind:${scriptKind} and sourceFile.scriptKind: ${entry?.sourceFile.scriptKind}, !entry: ${!entry}`); + const entry = isDocumentRegistryEntry(bucketEntry) ? bucketEntry + : bucketEntry.get( + Debug.checkDefined( + scriptKind, + "If there are more than one scriptKind's for same document the scriptKind should be provided", + ), + ); + Debug.assert( + scriptKind === undefined || !entry || entry.sourceFile.scriptKind === scriptKind, + `Script kind should match provided ScriptKind:${scriptKind} and sourceFile.scriptKind: ${entry?.sourceFile.scriptKind}, !entry: ${!entry}`, + ); return entry; } @@ -262,13 +363,21 @@ export function createDocumentRegistryInternal(useCaseSensitiveFileNames?: boole ): SourceFile { scriptKind = ensureScriptKind(fileName, scriptKind); const compilationSettings = getCompilationSettings(compilationSettingsOrHost); - const host: MinimalResolutionCacheHost | undefined = compilationSettingsOrHost === compilationSettings ? undefined : compilationSettingsOrHost as MinimalResolutionCacheHost; - const scriptTarget = scriptKind === ScriptKind.JSON ? ScriptTarget.JSON : getEmitScriptTarget(compilationSettings); - const sourceFileOptions: CreateSourceFileOptions = typeof languageVersionOrOptions === "object" ? - languageVersionOrOptions : - { + const host: MinimalResolutionCacheHost | undefined = compilationSettingsOrHost === compilationSettings + ? undefined : compilationSettingsOrHost as MinimalResolutionCacheHost; + const scriptTarget = scriptKind === ScriptKind.JSON ? ScriptTarget.JSON + : getEmitScriptTarget(compilationSettings); + const sourceFileOptions: CreateSourceFileOptions = typeof languageVersionOrOptions === "object" + ? languageVersionOrOptions + : { languageVersion: scriptTarget, - impliedNodeFormat: host && getImpliedNodeFormatForFile(path, host.getCompilerHost?.()?.getModuleResolutionCache?.()?.getPackageJsonInfoCache(), host, compilationSettings), + impliedNodeFormat: host + && getImpliedNodeFormatForFile( + path, + host.getCompilerHost?.()?.getModuleResolutionCache?.()?.getPackageJsonInfoCache(), + host, + compilationSettings, + ), setExternalModuleIndicator: getSetExternalModuleIndicator(compilationSettings), }; sourceFileOptions.languageVersion = scriptTarget; @@ -280,16 +389,26 @@ export function createDocumentRegistryInternal(useCaseSensitiveFileNames?: boole // It is interesting, but not definitively problematic if a build requires multiple document registry buckets - // perhaps they are for two projects that don't have any overlap. // Bonus: these events can help us interpret the more interesting event below. - tracing.instant(tracing.Phase.Session, "createdDocumentRegistryBucket", { configFilePath: compilationSettings.configFilePath, key: keyWithMode }); + tracing.instant(tracing.Phase.Session, "createdDocumentRegistryBucket", { + configFilePath: compilationSettings.configFilePath, + key: keyWithMode, + }); } // It is fairly suspicious to have one path in two buckets - you'd expect dependencies to have similar configurations. // If this occurs unexpectedly, the fix is likely to synchronize the project settings. // Skip .d.ts files to reduce noise (should also cover most of node_modules). - const otherBucketKey = !isDeclarationFileName(path) && - forEachEntry(buckets, (bucket, bucketKey) => bucketKey !== keyWithMode && bucket.has(path) && bucketKey); + const otherBucketKey = !isDeclarationFileName(path) + && forEachEntry( + buckets, + (bucket, bucketKey) => bucketKey !== keyWithMode && bucket.has(path) && bucketKey, + ); if (otherBucketKey) { - tracing.instant(tracing.Phase.Session, "documentRegistryBucketOverlap", { path, key1: otherBucketKey, key2: keyWithMode }); + tracing.instant(tracing.Phase.Session, "documentRegistryBucketOverlap", { + path, + key1: otherBucketKey, + key2: keyWithMode, + }); } } @@ -309,7 +428,14 @@ export function createDocumentRegistryInternal(useCaseSensitiveFileNames?: boole if (!entry) { // Have never seen this file with these settings. Create a new source file for it. - const sourceFile = createLanguageServiceSourceFile(fileName, scriptSnapshot, sourceFileOptions, version, /*setNodeParents*/ false, scriptKind); + const sourceFile = createLanguageServiceSourceFile( + fileName, + scriptSnapshot, + sourceFileOptions, + version, + /*setNodeParents*/ false, + scriptKind, + ); if (externalCache) { externalCache.setDocument(keyWithMode, path, sourceFile); } @@ -324,7 +450,12 @@ export function createDocumentRegistryInternal(useCaseSensitiveFileNames?: boole // the script snapshot. If so, update it appropriately. Otherwise, we can just // return it as is. if (entry.sourceFile.version !== version) { - entry.sourceFile = updateLanguageServiceSourceFile(entry.sourceFile, scriptSnapshot, version, scriptSnapshot.getChangeRange(entry.sourceFile.scriptSnapshot!)); // TODO: GH#18217 + entry.sourceFile = updateLanguageServiceSourceFile( + entry.sourceFile, + scriptSnapshot, + version, + scriptSnapshot.getChangeRange(entry.sourceFile.scriptSnapshot!), + ); // TODO: GH#18217 if (externalCache) { externalCache.setDocument(keyWithMode, path, entry.sourceFile); } @@ -359,13 +490,23 @@ export function createDocumentRegistryInternal(useCaseSensitiveFileNames?: boole } } - function releaseDocument(fileName: string, compilationSettings: CompilerOptions, scriptKind?: ScriptKind, impliedNodeFormat?: ResolutionMode): void { + function releaseDocument( + fileName: string, + compilationSettings: CompilerOptions, + scriptKind?: ScriptKind, + impliedNodeFormat?: ResolutionMode, + ): void { const path = toPath(fileName, currentDirectory, getCanonicalFileName); const key = getKeyForCompilationSettings(compilationSettings); return releaseDocumentWithKey(path, key, scriptKind, impliedNodeFormat); } - function releaseDocumentWithKey(path: Path, key: DocumentRegistryBucketKey, scriptKind?: ScriptKind, impliedNodeFormat?: ResolutionMode): void { + function releaseDocumentWithKey( + path: Path, + key: DocumentRegistryBucketKey, + scriptKind?: ScriptKind, + impliedNodeFormat?: ResolutionMode, + ): void { const bucket = Debug.checkDefined(buckets.get(getDocumentRegistryBucketKeyWithMode(key, impliedNodeFormat))); const bucketEntry = bucket.get(path)!; const entry = getDocumentRegistryEntry(bucketEntry, scriptKind)!; diff --git a/src/services/exportInfoMap.ts b/src/services/exportInfoMap.ts index 9a4d9cf1d2b7c..b9205a402615e 100644 --- a/src/services/exportInfoMap.ts +++ b/src/services/exportInfoMap.ts @@ -112,9 +112,28 @@ interface CachedSymbolExportInfo { export interface ExportInfoMap { isUsableByFile(importingFile: Path): boolean; clear(): void; - add(importingFile: Path, symbol: Symbol, key: __String, moduleSymbol: Symbol, moduleFile: SourceFile | undefined, exportKind: ExportKind, isFromPackageJson: boolean, checker: TypeChecker): void; + add( + importingFile: Path, + symbol: Symbol, + key: __String, + moduleSymbol: Symbol, + moduleFile: SourceFile | undefined, + exportKind: ExportKind, + isFromPackageJson: boolean, + checker: TypeChecker, + ): void; get(importingFile: Path, key: string): readonly SymbolExportInfo[] | undefined; - search(importingFile: Path, preferCapitalized: boolean, matches: (name: string, targetFlags: SymbolFlags) => boolean, action: (info: readonly SymbolExportInfo[], symbolName: string, isFromAmbientModule: boolean, key: string) => T | undefined): T | undefined; + search( + importingFile: Path, + preferCapitalized: boolean, + matches: (name: string, targetFlags: SymbolFlags) => boolean, + action: ( + info: readonly SymbolExportInfo[], + symbolName: string, + isFromAmbientModule: boolean, + key: string, + ) => T | undefined, + ): T | undefined; releaseSymbols(): void; isEmpty(): boolean; /** @returns Whether the change resulted in the cache being cleared */ @@ -153,7 +172,16 @@ export function createCacheableExportInfoMap(host: CacheableExportInfoMapHost): symbols.clear(); usableByFileName = undefined; }, - add: (importingFile, symbol, symbolTableKey, moduleSymbol, moduleFile, exportKind, isFromPackageJson, checker) => { + add: ( + importingFile, + symbol, + symbolTableKey, + moduleSymbol, + moduleFile, + exportKind, + isFromPackageJson, + checker, + ) => { if (importingFile !== usableByFileName) { cache.clear(); usableByFileName = importingFile; @@ -163,8 +191,13 @@ export function createCacheableExportInfoMap(host: CacheableExportInfoMapHost): if (moduleFile) { const nodeModulesPathParts = getNodeModulePathParts(moduleFile.fileName); if (nodeModulesPathParts) { - const { topLevelNodeModulesIndex, topLevelPackageNameIndex, packageRootIndex } = nodeModulesPathParts; - packageName = unmangleScopedPackageName(getPackageNameFromTypesPackageName(moduleFile.fileName.substring(topLevelPackageNameIndex + 1, packageRootIndex))); + const { topLevelNodeModulesIndex, topLevelPackageNameIndex, packageRootIndex } = + nodeModulesPathParts; + packageName = unmangleScopedPackageName( + getPackageNameFromTypesPackageName( + moduleFile.fileName.substring(topLevelPackageNameIndex + 1, packageRootIndex), + ), + ); if (startsWith(importingFile, moduleFile.path.substring(0, topLevelNodeModulesIndex))) { const prevDeepestNodeModulesPath = packages.get(packageName); const nodeModulesPath = moduleFile.fileName.substring(0, topLevelPackageNameIndex + 1); @@ -204,21 +237,24 @@ export function createCacheableExportInfoMap(host: CacheableExportInfoMapHost): const storedModuleSymbol = moduleSymbol.flags & SymbolFlags.Transient ? undefined : moduleSymbol; if (!storedSymbol || !storedModuleSymbol) symbols.set(id, [symbol, moduleSymbol]); - exportInfo.add(key(symbolName, symbol, isExternalModuleNameRelative(moduleName) ? undefined : moduleName, checker), { - id, - symbolTableKey, - symbolName, - capitalizedSymbolName, - moduleName, - moduleFile, - moduleFileName: moduleFile?.fileName, - packageName, - exportKind, - targetFlags: target.flags, - isFromPackageJson, - symbol: storedSymbol, - moduleSymbol: storedModuleSymbol, - }); + exportInfo.add( + key(symbolName, symbol, isExternalModuleNameRelative(moduleName) ? undefined : moduleName, checker), + { + id, + symbolTableKey, + symbolName, + capitalizedSymbolName, + moduleName, + moduleFile, + moduleFileName: moduleFile?.fileName, + packageName, + exportKind, + targetFlags: target.flags, + isFromPackageJson, + symbol: storedSymbol, + moduleSymbol: storedModuleSymbol, + }, + ); }, get: (importingFile, key) => { if (importingFile !== usableByFileName) return; @@ -232,7 +268,9 @@ export function createCacheableExportInfoMap(host: CacheableExportInfoMapHost): const name = preferCapitalized && info[0].capitalizedSymbolName || symbolName; if (matches(name, info[0].targetFlags)) { const rehydrated = info.map(rehydrateCachedInfo); - const filtered = rehydrated.filter((r, i) => isNotShadowedByDeeperNodeModulesPackage(r, info[i].packageName)); + const filtered = rehydrated.filter((r, i) => + isNotShadowedByDeeperNodeModulesPackage(r, info[i].packageName) + ); if (filtered.length) { const res = action(filtered, name, !!ambientModuleName, key); if (res !== undefined) return res; @@ -249,15 +287,16 @@ export function createCacheableExportInfoMap(host: CacheableExportInfoMapHost): return false; } if ( - usableByFileName && usableByFileName !== newSourceFile.path || + usableByFileName && usableByFileName !== newSourceFile.path // If ATA is enabled, auto-imports uses existing imports to guess whether you want auto-imports from node. // Adding or removing imports from node could change the outcome of that guess, so could change the suggestions list. - typeAcquisitionEnabled && consumesNodeCoreModules(oldSourceFile) !== consumesNodeCoreModules(newSourceFile) || + || typeAcquisitionEnabled + && consumesNodeCoreModules(oldSourceFile) !== consumesNodeCoreModules(newSourceFile) // Module agumentation and ambient module changes can add or remove exports available to be auto-imported. // Changes elsewhere in the file can change the *type* of an export in a module augmentation, // but type info is gathered in getCompletionEntryDetails, which doesn't use the cache. - !arrayIsEqualTo(oldSourceFile.moduleAugmentations, newSourceFile.moduleAugmentations) || - !ambientModuleDeclarationsAreEqual(oldSourceFile, newSourceFile) + || !arrayIsEqualTo(oldSourceFile.moduleAugmentations, newSourceFile.moduleAugmentations) + || !ambientModuleDeclarationsAreEqual(oldSourceFile, newSourceFile) ) { cache.clear(); return true; @@ -296,7 +335,10 @@ export function createCacheableExportInfoMap(host: CacheableExportInfoMapHost): const symbol = info.symbol || cachedSymbol || Debug.checkDefined( exportKind === ExportKind.ExportEquals ? checker.resolveExternalModuleSymbol(moduleSymbol) - : checker.tryGetMemberInModuleExportsAndProperties(unescapeLeadingUnderscores(info.symbolTableKey), moduleSymbol), + : checker.tryGetMemberInModuleExportsAndProperties( + unescapeLeadingUnderscores(info.symbolTableKey), + moduleSymbol, + ), `Could not find symbol '${info.symbolName}' by key '${info.symbolTableKey}' in module ${moduleSymbol.name}`, ); symbols.set(id, [symbol, moduleSymbol]); @@ -310,7 +352,12 @@ export function createCacheableExportInfoMap(host: CacheableExportInfoMapHost): }; } - function key(importedName: string, symbol: Symbol, ambientModuleName: string | undefined, checker: TypeChecker): string { + function key( + importedName: string, + symbol: Symbol, + ambientModuleName: string | undefined, + checker: TypeChecker, + ): string { const moduleKey = ambientModuleName || ""; return `${importedName}|${getSymbolId(skipAlias(symbol, checker))}|${moduleKey}`; } @@ -323,7 +370,8 @@ export function createCacheableExportInfoMap(host: CacheableExportInfoMapHost): } function fileIsGlobalOnly(file: SourceFile) { - return !file.commonJsModuleIndicator && !file.externalModuleIndicator && !file.moduleAugmentations && !file.ambientModuleNames; + return !file.commonJsModuleIndicator && !file.externalModuleIndicator && !file.moduleAugmentations + && !file.ambientModuleNames; } function ambientModuleDeclarationsAreEqual(oldSourceFile: SourceFile, newSourceFile: SourceFile) { @@ -333,9 +381,18 @@ export function createCacheableExportInfoMap(host: CacheableExportInfoMapHost): let oldFileStatementIndex = -1; let newFileStatementIndex = -1; for (const ambientModuleName of newSourceFile.ambientModuleNames) { - const isMatchingModuleDeclaration = (node: Statement) => isNonGlobalAmbientModule(node) && node.name.text === ambientModuleName; - oldFileStatementIndex = findIndex(oldSourceFile.statements, isMatchingModuleDeclaration, oldFileStatementIndex + 1); - newFileStatementIndex = findIndex(newSourceFile.statements, isMatchingModuleDeclaration, newFileStatementIndex + 1); + const isMatchingModuleDeclaration = (node: Statement) => + isNonGlobalAmbientModule(node) && node.name.text === ambientModuleName; + oldFileStatementIndex = findIndex( + oldSourceFile.statements, + isMatchingModuleDeclaration, + oldFileStatementIndex + 1, + ); + newFileStatementIndex = findIndex( + newSourceFile.statements, + isMatchingModuleDeclaration, + newFileStatementIndex + 1, + ); if (oldSourceFile.statements[oldFileStatementIndex] !== newSourceFile.statements[newFileStatementIndex]) { return false; } @@ -379,14 +436,21 @@ export function isImportableFile( const toFile = program.getSourceFile(toPath); // Determine to import using toPath only if toPath is what we were looking at // or there doesnt exist the file in the program by the symlink - return (toFile === to || !toFile) && - isImportablePath(from.fileName, toPath, getCanonicalFileName, globalTypingsCache); + return (toFile === to || !toFile) + && isImportablePath(from.fileName, toPath, getCanonicalFileName, globalTypingsCache); }, ); if (packageJsonFilter) { - const isAutoImportable = hasImportablePath && packageJsonFilter.allowsImportingSourceFile(to, moduleSpecifierResolutionHost); - moduleSpecifierCache?.setBlockedByPackageJsonDependencies(from.path, to.path, preferences, {}, !isAutoImportable); + const isAutoImportable = hasImportablePath + && packageJsonFilter.allowsImportingSourceFile(to, moduleSpecifierResolutionHost); + moduleSpecifierCache?.setBlockedByPackageJsonDependencies( + from.path, + to.path, + preferences, + {}, + !isAutoImportable, + ); return isAutoImportable; } @@ -397,9 +461,17 @@ export function isImportableFile( * Don't include something from a `node_modules` that isn't actually reachable by a global import. * A relative import to node_modules is usually a bad idea. */ -function isImportablePath(fromPath: string, toPath: string, getCanonicalFileName: GetCanonicalFileName, globalCachePath?: string): boolean { +function isImportablePath( + fromPath: string, + toPath: string, + getCanonicalFileName: GetCanonicalFileName, + globalCachePath?: string, +): boolean { // If it's in a `node_modules` but is not reachable from here via a global import, don't bother. - const toNodeModules = forEachAncestorDirectory(toPath, ancestor => getBaseFileName(ancestor) === "node_modules" ? ancestor : undefined); + const toNodeModules = forEachAncestorDirectory( + toPath, + ancestor => getBaseFileName(ancestor) === "node_modules" ? ancestor : undefined, + ); const toNodeModulesParent = toNodeModules && getDirectoryPath(getCanonicalFileName(toNodeModules)); return toNodeModulesParent === undefined || startsWith(getCanonicalFileName(fromPath), toNodeModulesParent) @@ -415,35 +487,63 @@ export function forEachExternalModuleToImportFrom( cb: (module: Symbol, moduleFile: SourceFile | undefined, program: Program, isFromPackageJson: boolean) => void, ) { const useCaseSensitiveFileNames = hostUsesCaseSensitiveFileNames(host); - const excludePatterns = preferences.autoImportFileExcludePatterns && mapDefined(preferences.autoImportFileExcludePatterns, spec => { - // The client is expected to send rooted path specs since we don't know - // what directory a relative path is relative to. - const pattern = getPatternFromSpec(spec, "", "exclude"); - return pattern ? getRegexFromPattern(pattern, useCaseSensitiveFileNames) : undefined; - }); + const excludePatterns = preferences.autoImportFileExcludePatterns + && mapDefined(preferences.autoImportFileExcludePatterns, spec => { + // The client is expected to send rooted path specs since we don't know + // what directory a relative path is relative to. + const pattern = getPatternFromSpec(spec, "", "exclude"); + return pattern ? getRegexFromPattern(pattern, useCaseSensitiveFileNames) : undefined; + }); - forEachExternalModule(program.getTypeChecker(), program.getSourceFiles(), excludePatterns, (module, file) => cb(module, file, program, /*isFromPackageJson*/ false)); + forEachExternalModule( + program.getTypeChecker(), + program.getSourceFiles(), + excludePatterns, + (module, file) => cb(module, file, program, /*isFromPackageJson*/ false), + ); const autoImportProvider = useAutoImportProvider && host.getPackageJsonAutoImportProvider?.(); if (autoImportProvider) { const start = timestamp(); const checker = program.getTypeChecker(); - forEachExternalModule(autoImportProvider.getTypeChecker(), autoImportProvider.getSourceFiles(), excludePatterns, (module, file) => { - if (file && !program.getSourceFile(file.fileName) || !file && !checker.resolveName(module.name, /*location*/ undefined, SymbolFlags.Module, /*excludeGlobals*/ false)) { - // The AutoImportProvider filters files already in the main program out of its *root* files, - // but non-root files can still be present in both programs, and already in the export info map - // at this point. This doesn't create any incorrect behavior, but is a waste of time and memory, - // so we filter them out here. - cb(module, file, autoImportProvider, /*isFromPackageJson*/ true); - } - }); + forEachExternalModule( + autoImportProvider.getTypeChecker(), + autoImportProvider.getSourceFiles(), + excludePatterns, + (module, file) => { + if ( + file && !program.getSourceFile(file.fileName) + || !file + && !checker.resolveName( + module.name, + /*location*/ undefined, + SymbolFlags.Module, + /*excludeGlobals*/ false, + ) + ) { + // The AutoImportProvider filters files already in the main program out of its *root* files, + // but non-root files can still be present in both programs, and already in the export info map + // at this point. This doesn't create any incorrect behavior, but is a waste of time and memory, + // so we filter them out here. + cb(module, file, autoImportProvider, /*isFromPackageJson*/ true); + } + }, + ); host.log?.(`forEachExternalModuleToImportFrom autoImportProvider: ${timestamp() - start}`); } } -function forEachExternalModule(checker: TypeChecker, allSourceFiles: readonly SourceFile[], excludePatterns: readonly RegExp[] | undefined, cb: (module: Symbol, sourceFile: SourceFile | undefined) => void) { +function forEachExternalModule( + checker: TypeChecker, + allSourceFiles: readonly SourceFile[], + excludePatterns: readonly RegExp[] | undefined, + cb: (module: Symbol, sourceFile: SourceFile | undefined) => void, +) { const isExcluded = excludePatterns && ((fileName: string) => excludePatterns.some(p => p.test(fileName))); for (const ambient of checker.getAmbientModules()) { - if (!stringContains(ambient.name, "*") && !(excludePatterns && ambient.declarations?.every(d => isExcluded!(d.getSourceFile().fileName)))) { + if ( + !stringContains(ambient.name, "*") + && !(excludePatterns && ambient.declarations?.every(d => isExcluded!(d.getSourceFile().fileName))) + ) { cb(ambient, /*sourceFile*/ undefined); } } @@ -455,7 +555,13 @@ function forEachExternalModule(checker: TypeChecker, allSourceFiles: readonly So } /** @internal */ -export function getExportInfoMap(importingFile: SourceFile, host: LanguageServiceHost, program: Program, preferences: UserPreferences, cancellationToken: CancellationToken | undefined): ExportInfoMap { +export function getExportInfoMap( + importingFile: SourceFile, + host: LanguageServiceHost, + program: Program, + preferences: UserPreferences, + cancellationToken: CancellationToken | undefined, +): ExportInfoMap { const start = timestamp(); // Pulling the AutoImportProvider project will trigger its updateGraph if pending, // which will invalidate the export map cache if things change, so pull it before @@ -476,40 +582,50 @@ export function getExportInfoMap(importingFile: SourceFile, host: LanguageServic const compilerOptions = program.getCompilerOptions(); let moduleCount = 0; try { - forEachExternalModuleToImportFrom(program, host, preferences, /*useAutoImportProvider*/ true, (moduleSymbol, moduleFile, program, isFromPackageJson) => { - if (++moduleCount % 100 === 0) cancellationToken?.throwIfCancellationRequested(); - const seenExports = new Map<__String, true>(); - const checker = program.getTypeChecker(); - const defaultInfo = getDefaultLikeExportInfo(moduleSymbol, checker, compilerOptions); - // Note: I think we shouldn't actually see resolved module symbols here, but weird merges - // can cause it to happen: see 'completionsImport_mergedReExport.ts' - if (defaultInfo && isImportableSymbol(defaultInfo.symbol, checker)) { - cache.add( - importingFile.path, - defaultInfo.symbol, - defaultInfo.exportKind === ExportKind.Default ? InternalSymbolName.Default : InternalSymbolName.ExportEquals, - moduleSymbol, - moduleFile, - defaultInfo.exportKind, - isFromPackageJson, - checker, - ); - } - checker.forEachExportAndPropertyOfModule(moduleSymbol, (exported, key) => { - if (exported !== defaultInfo?.symbol && isImportableSymbol(exported, checker) && addToSeen(seenExports, key)) { + forEachExternalModuleToImportFrom( + program, + host, + preferences, + /*useAutoImportProvider*/ true, + (moduleSymbol, moduleFile, program, isFromPackageJson) => { + if (++moduleCount % 100 === 0) cancellationToken?.throwIfCancellationRequested(); + const seenExports = new Map<__String, true>(); + const checker = program.getTypeChecker(); + const defaultInfo = getDefaultLikeExportInfo(moduleSymbol, checker, compilerOptions); + // Note: I think we shouldn't actually see resolved module symbols here, but weird merges + // can cause it to happen: see 'completionsImport_mergedReExport.ts' + if (defaultInfo && isImportableSymbol(defaultInfo.symbol, checker)) { cache.add( importingFile.path, - exported, - key, + defaultInfo.symbol, + defaultInfo.exportKind === ExportKind.Default ? InternalSymbolName.Default + : InternalSymbolName.ExportEquals, moduleSymbol, moduleFile, - ExportKind.Named, + defaultInfo.exportKind, isFromPackageJson, checker, ); } - }); - }); + checker.forEachExportAndPropertyOfModule(moduleSymbol, (exported, key) => { + if ( + exported !== defaultInfo?.symbol && isImportableSymbol(exported, checker) + && addToSeen(seenExports, key) + ) { + cache.add( + importingFile.path, + exported, + key, + moduleSymbol, + moduleFile, + ExportKind.Named, + isFromPackageJson, + checker, + ); + } + }); + }, + ); } catch (err) { // Ensure cache is reset if operation is cancelled @@ -531,10 +647,14 @@ export function getDefaultLikeExportInfo(moduleSymbol: Symbol, checker: TypeChec } function isImportableSymbol(symbol: Symbol, checker: TypeChecker) { - return !checker.isUndefinedSymbol(symbol) && !checker.isUnknownSymbol(symbol) && !isKnownSymbol(symbol) && !isPrivateIdentifierSymbol(symbol); + return !checker.isUndefinedSymbol(symbol) && !checker.isUnknownSymbol(symbol) && !isKnownSymbol(symbol) + && !isPrivateIdentifierSymbol(symbol); } -function getDefaultLikeExportWorker(moduleSymbol: Symbol, checker: TypeChecker): { readonly symbol: Symbol; readonly exportKind: ExportKind; } | undefined { +function getDefaultLikeExportWorker( + moduleSymbol: Symbol, + checker: TypeChecker, +): { readonly symbol: Symbol; readonly exportKind: ExportKind; } | undefined { const exportEquals = checker.resolveExternalModuleSymbol(moduleSymbol); if (exportEquals !== moduleSymbol) return { symbol: exportEquals, exportKind: ExportKind.ExportEquals }; const defaultExport = checker.tryGetMemberInModuleExports(InternalSymbolName.Default, moduleSymbol); @@ -542,7 +662,11 @@ function getDefaultLikeExportWorker(moduleSymbol: Symbol, checker: TypeChecker): } /** @internal */ -export function getDefaultExportInfoWorker(defaultExport: Symbol, checker: TypeChecker, compilerOptions: CompilerOptions): { readonly resolvedSymbol: Symbol; readonly name: string; } | undefined { +export function getDefaultExportInfoWorker( + defaultExport: Symbol, + checker: TypeChecker, + compilerOptions: CompilerOptions, +): { readonly resolvedSymbol: Symbol; readonly name: string; } | undefined { const localSymbol = getLocalSymbolForExportDefault(defaultExport); if (localSymbol) return { resolvedSymbol: localSymbol, name: localSymbol.name }; @@ -561,8 +685,8 @@ export function getDefaultExportInfoWorker(defaultExport: Symbol, checker: TypeC } if ( - defaultExport.escapedName !== InternalSymbolName.Default && - defaultExport.escapedName !== InternalSymbolName.ExportEquals + defaultExport.escapedName !== InternalSymbolName.Default + && defaultExport.escapedName !== InternalSymbolName.ExportEquals ) { return { resolvedSymbol: defaultExport, name: defaultExport.getName() }; } @@ -575,7 +699,10 @@ function getNameForExportDefault(symbol: Symbol): string | undefined { return tryCast(skipOuterExpressions(declaration.expression), isIdentifier)?.text; } else if (isExportSpecifier(declaration)) { - Debug.assert(declaration.name.text === InternalSymbolName.Default, "Expected the specifier to be a default export"); + Debug.assert( + declaration.name.text === InternalSymbolName.Default, + "Expected the specifier to be a default export", + ); return declaration.propertyName && declaration.propertyName.text; } }); diff --git a/src/services/findAllReferences.ts b/src/services/findAllReferences.ts index 11a00e51954da..a5e9867e6e655 100644 --- a/src/services/findAllReferences.ts +++ b/src/services/findAllReferences.ts @@ -283,7 +283,11 @@ export type Definition = | { readonly type: DefinitionKind.Keyword; readonly node: Node; } | { readonly type: DefinitionKind.This; readonly node: Node; } | { readonly type: DefinitionKind.String; readonly node: StringLiteralLike; } - | { readonly type: DefinitionKind.TripleSlashReference; readonly reference: FileReference; readonly file: SourceFile; }; + | { + readonly type: DefinitionKind.TripleSlashReference; + readonly reference: FileReference; + readonly file: SourceFile; + }; /** @internal */ export const enum EntryKind { @@ -294,7 +298,11 @@ export const enum EntryKind { SearchedPropertyFoundLocal, } /** @internal */ -export type NodeEntryKind = EntryKind.Node | EntryKind.StringLiteral | EntryKind.SearchedLocalFoundProperty | EntryKind.SearchedPropertyFoundLocal; +export type NodeEntryKind = + | EntryKind.Node + | EntryKind.StringLiteral + | EntryKind.SearchedLocalFoundProperty + | EntryKind.SearchedPropertyFoundLocal; /** @internal */ export type Entry = NodeEntry | SpanEntry; /** @internal */ @@ -340,13 +348,13 @@ function getContextNodeForNodeEntry(node: Node): ContextNode | undefined { if (!isDeclaration(node.parent) && !isExportAssignment(node.parent)) { // Special property assignment in javascript if (isInJSFile(node)) { - const binaryExpression = isBinaryExpression(node.parent) ? - node.parent : - isAccessExpression(node.parent) && - isBinaryExpression(node.parent.parent) && - node.parent.parent.left === node.parent ? - node.parent.parent : - undefined; + const binaryExpression = isBinaryExpression(node.parent) + ? node.parent + : isAccessExpression(node.parent) + && isBinaryExpression(node.parent.parent) + && node.parent.parent.left === node.parent + ? node.parent.parent + : undefined; if (binaryExpression && getAssignmentDeclarationKind(binaryExpression) !== AssignmentDeclarationKind.None) { return getContextNode(binaryExpression); } @@ -357,9 +365,9 @@ function getContextNodeForNodeEntry(node: Node): ContextNode | undefined { return node.parent.parent; } else if ( - isJsxSelfClosingElement(node.parent) || - isLabeledStatement(node.parent) || - isBreakOrContinueStatement(node.parent) + isJsxSelfClosingElement(node.parent) + || isLabeledStatement(node.parent) + || isBreakOrContinueStatement(node.parent) ) { return node.parent; } @@ -367,31 +375,31 @@ function getContextNodeForNodeEntry(node: Node): ContextNode | undefined { const validImport = tryGetImportFromModuleSpecifier(node); if (validImport) { const declOrStatement = findAncestor(validImport, node => - isDeclaration(node) || - isStatement(node) || - isJSDocTag(node))! as NamedDeclaration | Statement | JSDocTag; - return isDeclaration(declOrStatement) ? - getContextNode(declOrStatement) : - declOrStatement; + isDeclaration(node) + || isStatement(node) + || isJSDocTag(node))! as NamedDeclaration | Statement | JSDocTag; + return isDeclaration(declOrStatement) + ? getContextNode(declOrStatement) + : declOrStatement; } } // Handle computed property name const propertyName = findAncestor(node, isComputedPropertyName); - return propertyName ? - getContextNode(propertyName.parent) : - undefined; + return propertyName + ? getContextNode(propertyName.parent) + : undefined; } if ( - node.parent.name === node || // node is name of declaration, use parent - isConstructorDeclaration(node.parent) || - isExportAssignment(node.parent) || + node.parent.name === node // node is name of declaration, use parent + || isConstructorDeclaration(node.parent) + || isExportAssignment(node.parent) // Property name of the import export specifier or binding pattern, use parent - ((isImportOrExportSpecifier(node.parent) || isBindingElement(node.parent)) - && node.parent.propertyName === node) || + || ((isImportOrExportSpecifier(node.parent) || isBindingElement(node.parent)) + && node.parent.propertyName === node) // Is default export - (node.kind === SyntaxKind.DefaultKeyword && hasSyntacticModifier(node.parent, ModifierFlags.ExportDefault)) + || (node.kind === SyntaxKind.DefaultKeyword && hasSyntacticModifier(node.parent, ModifierFlags.ExportDefault)) ) { return getContextNode(node.parent); } @@ -400,17 +408,19 @@ function getContextNodeForNodeEntry(node: Node): ContextNode | undefined { } /** @internal */ -export function getContextNode(node: NamedDeclaration | BinaryExpression | ForInOrOfStatement | undefined): ContextNode | undefined { +export function getContextNode( + node: NamedDeclaration | BinaryExpression | ForInOrOfStatement | undefined, +): ContextNode | undefined { if (!node) return undefined; switch (node.kind) { case SyntaxKind.VariableDeclaration: - return !isVariableDeclarationList(node.parent) || node.parent.declarations.length !== 1 ? - node : - isVariableStatement(node.parent.parent) ? - node.parent.parent : - isForInOrOfStatement(node.parent.parent) ? - getContextNode(node.parent.parent) : - node.parent; + return !isVariableDeclarationList(node.parent) || node.parent.declarations.length !== 1 + ? node + : isVariableStatement(node.parent.parent) + ? node.parent.parent + : isForInOrOfStatement(node.parent.parent) + ? getContextNode(node.parent.parent) + : node.parent; case SyntaxKind.BindingElement: return getContextNode(node.parent.parent as NamedDeclaration); @@ -427,9 +437,9 @@ export function getContextNode(node: NamedDeclaration | BinaryExpression | ForIn return node.parent; case SyntaxKind.BinaryExpression: - return isExpressionStatement(node.parent) ? - node.parent : - node; + return isExpressionStatement(node.parent) + ? node.parent + : node; case SyntaxKind.ForOfStatement: case SyntaxKind.ForInStatement: @@ -440,11 +450,13 @@ export function getContextNode(node: NamedDeclaration | BinaryExpression | ForIn case SyntaxKind.PropertyAssignment: case SyntaxKind.ShorthandPropertyAssignment: - return isArrayLiteralOrObjectLiteralDestructuringPattern(node.parent) ? - getContextNode( - findAncestor(node.parent, node => isBinaryExpression(node) || isForInOrOfStatement(node)) as BinaryExpression | ForInOrOfStatement, - ) : - node; + return isArrayLiteralOrObjectLiteralDestructuringPattern(node.parent) + ? getContextNode( + findAncestor(node.parent, node => isBinaryExpression(node) || isForInOrOfStatement(node)) as + | BinaryExpression + | ForInOrOfStatement, + ) + : node; default: return node; @@ -452,14 +464,18 @@ export function getContextNode(node: NamedDeclaration | BinaryExpression | ForIn } /** @internal */ -export function toContextSpan(textSpan: TextSpan, sourceFile: SourceFile, context?: ContextNode): { contextSpan: TextSpan; } | undefined { +export function toContextSpan( + textSpan: TextSpan, + sourceFile: SourceFile, + context?: ContextNode, +): { contextSpan: TextSpan; } | undefined { if (!context) return undefined; - const contextSpan = isContextWithStartAndEndNode(context) ? - getTextSpan(context.start, sourceFile, context.end) : - getTextSpan(context, sourceFile); - return contextSpan.start !== textSpan.start || contextSpan.length !== textSpan.length ? - { contextSpan } : - undefined; + const contextSpan = isContextWithStartAndEndNode(context) + ? getTextSpan(context.start, sourceFile, context.end) + : getTextSpan(context, sourceFile); + return contextSpan.start !== textSpan.start || contextSpan.length !== textSpan.length + ? { contextSpan } + : undefined; } /** @internal */ @@ -496,20 +512,37 @@ export interface Options { } /** @internal */ -export function findReferencedSymbols(program: Program, cancellationToken: CancellationToken, sourceFiles: readonly SourceFile[], sourceFile: SourceFile, position: number): ReferencedSymbol[] | undefined { +export function findReferencedSymbols( + program: Program, + cancellationToken: CancellationToken, + sourceFiles: readonly SourceFile[], + sourceFile: SourceFile, + position: number, +): ReferencedSymbol[] | undefined { const node = getTouchingPropertyName(sourceFile, position); const options = { use: FindReferencesUse.References }; - const referencedSymbols = Core.getReferencedSymbolsForNode(position, node, program, sourceFiles, cancellationToken, options); + const referencedSymbols = Core.getReferencedSymbolsForNode( + position, + node, + program, + sourceFiles, + cancellationToken, + options, + ); const checker = program.getTypeChecker(); // Unless the starting node is a declaration (vs e.g. JSDoc), don't attempt to compute isDefinition const adjustedNode = Core.getAdjustedNode(node, options); const symbol = isDefinitionForReference(adjustedNode) ? checker.getSymbolAtLocation(adjustedNode) : undefined; - return !referencedSymbols || !referencedSymbols.length ? undefined : mapDefined(referencedSymbols, ({ definition, references }) => - // Only include referenced symbols that have a valid definition. - definition && { - definition: checker.runWithCancellationToken(cancellationToken, checker => definitionToReferencedSymbolDefinitionInfo(definition, checker, node)), - references: references.map(r => toReferencedSymbolEntry(r, symbol)), - }); + return !referencedSymbols || !referencedSymbols.length ? undefined + : mapDefined(referencedSymbols, ({ definition, references }) => + // Only include referenced symbols that have a valid definition. + definition && { + definition: checker.runWithCancellationToken(cancellationToken, checker => + definitionToReferencedSymbolDefinitionInfo(definition, checker, node)), + references: references.map(r => + toReferencedSymbolEntry(r, symbol) + ), + }); } function isDefinitionForReference(node: Node): boolean { @@ -520,7 +553,13 @@ function isDefinitionForReference(node: Node): boolean { } /** @internal */ -export function getImplementationsAtPosition(program: Program, cancellationToken: CancellationToken, sourceFiles: readonly SourceFile[], sourceFile: SourceFile, position: number): ImplementationLocation[] | undefined { +export function getImplementationsAtPosition( + program: Program, + cancellationToken: CancellationToken, + sourceFiles: readonly SourceFile[], + sourceFile: SourceFile, + position: number, +): ImplementationLocation[] | undefined { const node = getTouchingPropertyName(sourceFile, position); let referenceEntries: Entry[] | undefined; const entries = getImplementationReferenceEntries(program, cancellationToken, sourceFiles, node, position); @@ -542,7 +581,13 @@ export function getImplementationsAtPosition(program: Program, cancellationToken continue; } referenceEntries = append(referenceEntries, entry); - const entries = getImplementationReferenceEntries(program, cancellationToken, sourceFiles, entry.node, entry.node.pos); + const entries = getImplementationReferenceEntries( + program, + cancellationToken, + sourceFiles, + entry.node, + entry.node.pos, + ); if (entries) { queue.enqueue(...entries); } @@ -552,7 +597,13 @@ export function getImplementationsAtPosition(program: Program, cancellationToken return map(referenceEntries, entry => toImplementationLocation(entry, checker)); } -function getImplementationReferenceEntries(program: Program, cancellationToken: CancellationToken, sourceFiles: readonly SourceFile[], node: Node, position: number): readonly Entry[] | undefined { +function getImplementationReferenceEntries( + program: Program, + cancellationToken: CancellationToken, + sourceFiles: readonly SourceFile[], + node: Node, + position: number, +): readonly Entry[] | undefined { if (node.kind === SyntaxKind.SourceFile) { return undefined; } @@ -573,7 +624,10 @@ function getImplementationReferenceEntries(program: Program, cancellationToken: } else { // Perform "Find all References" and retrieve only those that are implementations - return getReferenceEntriesForNode(position, node, program, sourceFiles, cancellationToken, { implementations: true, use: FindReferencesUse.References }); + return getReferenceEntriesForNode(position, node, program, sourceFiles, cancellationToken, { + implementations: true, + use: FindReferencesUse.References, + }); } } @@ -587,7 +641,12 @@ export function findReferenceOrRenameEntries( options: Options | undefined, convertEntry: ToReferenceOrRenameEntry, ): T[] | undefined { - return map(flattenEntries(Core.getReferencedSymbolsForNode(position, node, program, sourceFiles, cancellationToken, options)), entry => convertEntry(entry, node, program.getTypeChecker())); + return map( + flattenEntries( + Core.getReferencedSymbolsForNode(position, node, program, sourceFiles, cancellationToken, options), + ), + entry => convertEntry(entry, node, program.getTypeChecker()), + ); } /** @internal */ @@ -603,15 +662,36 @@ export function getReferenceEntriesForNode( options: Options = {}, sourceFilesSet: ReadonlySet = new Set(sourceFiles.map(f => f.fileName)), ): readonly Entry[] | undefined { - return flattenEntries(Core.getReferencedSymbolsForNode(position, node, program, sourceFiles, cancellationToken, options, sourceFilesSet)); + return flattenEntries( + Core.getReferencedSymbolsForNode( + position, + node, + program, + sourceFiles, + cancellationToken, + options, + sourceFilesSet, + ), + ); } function flattenEntries(referenceSymbols: readonly SymbolAndEntries[] | undefined): readonly Entry[] | undefined { return referenceSymbols && flatMap(referenceSymbols, r => r.references); } -function definitionToReferencedSymbolDefinitionInfo(def: Definition, checker: TypeChecker, originalNode: Node): ReferencedSymbolDefinitionInfo { - const info = ((): { sourceFile: SourceFile; textSpan: TextSpan; name: string; kind: ScriptElementKind; displayParts: SymbolDisplayPart[]; context?: Node | ContextWithStartAndEndNode; } => { +function definitionToReferencedSymbolDefinitionInfo( + def: Definition, + checker: TypeChecker, + originalNode: Node, +): ReferencedSymbolDefinitionInfo { + const info = ((): { + sourceFile: SourceFile; + textSpan: TextSpan; + name: string; + kind: ScriptElementKind; + displayParts: SymbolDisplayPart[]; + context?: Node | ContextWithStartAndEndNode; + } => { switch (def.type) { case DefinitionKind.Symbol: { const { symbol } = def; @@ -629,12 +709,22 @@ function definitionToReferencedSymbolDefinitionInfo(def: Definition, checker: Ty } case DefinitionKind.Label: { const { node } = def; - return { ...getFileAndTextSpanFromNode(node), name: node.text, kind: ScriptElementKind.label, displayParts: [displayPart(node.text, SymbolDisplayPartKind.text)] }; + return { + ...getFileAndTextSpanFromNode(node), + name: node.text, + kind: ScriptElementKind.label, + displayParts: [displayPart(node.text, SymbolDisplayPartKind.text)], + }; } case DefinitionKind.Keyword: { const { node } = def; const name = tokenToString(node.kind)!; - return { ...getFileAndTextSpanFromNode(node), name, kind: ScriptElementKind.keyword, displayParts: [{ text: name, kind: ScriptElementKind.keyword }] }; + return { + ...getFileAndTextSpanFromNode(node), + name, + kind: ScriptElementKind.keyword, + displayParts: [{ text: name, kind: ScriptElementKind.keyword }], + }; } case DefinitionKind.This: { const { node } = def; @@ -646,7 +736,12 @@ function definitionToReferencedSymbolDefinitionInfo(def: Definition, checker: Ty getContainerNode(node), node, ).displayParts || [textPart("this")]; - return { ...getFileAndTextSpanFromNode(node), name: "this", kind: ScriptElementKind.variableElement, displayParts }; + return { + ...getFileAndTextSpanFromNode(node), + name: "this", + kind: ScriptElementKind.variableElement, + displayParts, + }; } case DefinitionKind.String: { const { node } = def; @@ -692,16 +787,36 @@ function getFileAndTextSpanFromNode(node: Node) { }; } -function getDefinitionKindAndDisplayParts(symbol: Symbol, checker: TypeChecker, node: Node): { displayParts: SymbolDisplayPart[]; kind: ScriptElementKind; } { +function getDefinitionKindAndDisplayParts( + symbol: Symbol, + checker: TypeChecker, + node: Node, +): { displayParts: SymbolDisplayPart[]; kind: ScriptElementKind; } { const meaning = Core.getIntersectingMeaningFromDeclarations(node, symbol); const enclosingDeclaration = symbol.declarations && firstOrUndefined(symbol.declarations) || node; - const { displayParts, symbolKind } = SymbolDisplay.getSymbolDisplayPartsDocumentationAndSymbolKind(checker, symbol, enclosingDeclaration.getSourceFile(), enclosingDeclaration, enclosingDeclaration, meaning); + const { displayParts, symbolKind } = SymbolDisplay.getSymbolDisplayPartsDocumentationAndSymbolKind( + checker, + symbol, + enclosingDeclaration.getSourceFile(), + enclosingDeclaration, + enclosingDeclaration, + meaning, + ); return { displayParts, kind: symbolKind }; } /** @internal */ -export function toRenameLocation(entry: Entry, originalNode: Node, checker: TypeChecker, providePrefixAndSuffixText: boolean, quotePreference: QuotePreference): RenameLocation { - return { ...entryToDocumentSpan(entry), ...(providePrefixAndSuffixText && getPrefixAndSuffixText(entry, originalNode, checker, quotePreference)) }; +export function toRenameLocation( + entry: Entry, + originalNode: Node, + checker: TypeChecker, + providePrefixAndSuffixText: boolean, + quotePreference: QuotePreference, +): RenameLocation { + return { + ...entryToDocumentSpan(entry), + ...(providePrefixAndSuffixText && getPrefixAndSuffixText(entry, originalNode, checker, quotePreference)), + }; } function toReferencedSymbolEntry(entry: Entry, symbol: Symbol | undefined): ReferencedSymbolEntry { @@ -746,13 +861,22 @@ interface PrefixAndSuffix { readonly prefixText?: string; readonly suffixText?: string; } -function getPrefixAndSuffixText(entry: Entry, originalNode: Node, checker: TypeChecker, quotePreference: QuotePreference): PrefixAndSuffix { +function getPrefixAndSuffixText( + entry: Entry, + originalNode: Node, + checker: TypeChecker, + quotePreference: QuotePreference, +): PrefixAndSuffix { if (entry.kind !== EntryKind.Span && isIdentifier(originalNode)) { const { node, kind } = entry; const parent = node.parent; const name = originalNode.text; const isShorthandAssignment = isShorthandPropertyAssignment(parent); - if (isShorthandAssignment || (isObjectBindingElementWithoutPropertyName(parent) && parent.name === node && parent.dotDotDotToken === undefined)) { + if ( + isShorthandAssignment + || (isObjectBindingElementWithoutPropertyName(parent) && parent.name === node + && parent.dotDotDotToken === undefined) + ) { const prefixColon: PrefixAndSuffix = { prefixText: name + ": " }; const suffixColon: PrefixAndSuffix = { suffixText: ": " + name }; if (kind === EntryKind.SearchedLocalFoundProperty) { @@ -767,9 +891,9 @@ function getPrefixAndSuffixText(entry: Entry, originalNode: Node, checker: TypeC if (isShorthandAssignment) { const grandParent = parent.parent; if ( - isObjectLiteralExpression(grandParent) && - isBinaryExpression(grandParent.parent) && - isModuleExportsAccessExpression(grandParent.parent.left) + isObjectLiteralExpression(grandParent) + && isBinaryExpression(grandParent.parent) + && isModuleExportsAccessExpression(grandParent.parent.left) ) { return prefixColon; } @@ -781,14 +905,17 @@ function getPrefixAndSuffixText(entry: Entry, originalNode: Node, checker: TypeC } else if (isImportSpecifier(parent) && !parent.propertyName) { // If the original symbol was using this alias, just rename the alias. - const originalSymbol = isExportSpecifier(originalNode.parent) ? checker.getExportSpecifierLocalTargetSymbol(originalNode.parent) : checker.getSymbolAtLocation(originalNode); + const originalSymbol = isExportSpecifier(originalNode.parent) + ? checker.getExportSpecifierLocalTargetSymbol(originalNode.parent) + : checker.getSymbolAtLocation(originalNode); return contains(originalSymbol!.declarations, parent) ? { prefixText: name + " as " } : emptyOptions; } else if (isExportSpecifier(parent) && !parent.propertyName) { // If the symbol for the node is same as declared node symbol use prefix text - return originalNode === entry.node || checker.getSymbolAtLocation(originalNode) === checker.getSymbolAtLocation(entry.node) ? - { prefixText: name + " as " } : - { suffixText: " as " + name }; + return originalNode === entry.node + || checker.getSymbolAtLocation(originalNode) === checker.getSymbolAtLocation(entry.node) + ? { prefixText: name + " as " } + : { suffixText: " as " + name }; } } @@ -815,7 +942,10 @@ function toImplementationLocation(entry: Entry, checker: TypeChecker): Implement } } -function implementationKindDisplayParts(node: Node, checker: TypeChecker): { kind: ScriptElementKind; displayParts: SymbolDisplayPart[]; } { +function implementationKindDisplayParts( + node: Node, + checker: TypeChecker, +): { kind: ScriptElementKind; displayParts: SymbolDisplayPart[]; } { const symbol = checker.getSymbolAtLocation(isDeclaration(node) && node.name ? node.name : node); if (symbol) { return getDefinitionKindAndDisplayParts(symbol, checker, node); @@ -823,13 +953,21 @@ function implementationKindDisplayParts(node: Node, checker: TypeChecker): { kin else if (node.kind === SyntaxKind.ObjectLiteralExpression) { return { kind: ScriptElementKind.interfaceElement, - displayParts: [punctuationPart(SyntaxKind.OpenParenToken), textPart("object literal"), punctuationPart(SyntaxKind.CloseParenToken)], + displayParts: [ + punctuationPart(SyntaxKind.OpenParenToken), + textPart("object literal"), + punctuationPart(SyntaxKind.CloseParenToken), + ], }; } else if (node.kind === SyntaxKind.ClassExpression) { return { kind: ScriptElementKind.localClassElement, - displayParts: [punctuationPart(SyntaxKind.OpenParenToken), textPart("anonymous local class"), punctuationPart(SyntaxKind.CloseParenToken)], + displayParts: [ + punctuationPart(SyntaxKind.OpenParenToken), + textPart("anonymous local class"), + punctuationPart(SyntaxKind.CloseParenToken), + ], }; } else { @@ -873,8 +1011,8 @@ function getTextSpan(node: Node, sourceFile: SourceFile, endNode?: Node): TextSp /** @internal */ export function getTextSpanOfEntry(entry: Entry) { - return entry.kind === EntryKind.Span ? entry.textSpan : - getTextSpan(entry.node, entry.node.getSourceFile()); + return entry.kind === EntryKind.Span ? entry.textSpan + : getTextSpan(entry.node, entry.node.getSourceFile()); } /** @@ -894,8 +1032,8 @@ export function isWriteAccessForReference(node: Node): boolean { */ export function isDeclarationOfSymbol(node: Node, target: Symbol | undefined): boolean { if (!target) return false; - const source = getDeclarationFromName(node) || - (node.kind === SyntaxKind.DefaultKeyword ? node.parent + const source = getDeclarationFromName(node) + || (node.kind === SyntaxKind.DefaultKeyword ? node.parent : isLiteralComputedPropertyDeclarationName(node) ? node.parent.parent : node.kind === SyntaxKind.ConstructorKeyword && isConstructorDeclaration(node.parent) ? node.parent.parent : undefined); @@ -947,7 +1085,13 @@ function declarationIsWriteAccess(decl: Declaration): boolean { case SyntaxKind.MethodDeclaration: case SyntaxKind.GetAccessor: case SyntaxKind.SetAccessor: - return !!(decl as FunctionDeclaration | FunctionExpression | ConstructorDeclaration | MethodDeclaration | GetAccessorDeclaration | SetAccessorDeclaration).body; + return !!(decl as + | FunctionDeclaration + | FunctionExpression + | ConstructorDeclaration + | MethodDeclaration + | GetAccessorDeclaration + | SetAccessorDeclaration).body; case SyntaxKind.VariableDeclaration: case SyntaxKind.PropertyDeclaration: @@ -971,7 +1115,15 @@ function declarationIsWriteAccess(decl: Declaration): boolean { */ export namespace Core { /** Core find-all-references algorithm. Handles special cases before delegating to `getReferencedSymbolsForSymbol`. */ - export function getReferencedSymbolsForNode(position: number, node: Node, program: Program, sourceFiles: readonly SourceFile[], cancellationToken: CancellationToken, options: Options = {}, sourceFilesSet: ReadonlySet = new Set(sourceFiles.map(f => f.fileName))): readonly SymbolAndEntries[] | undefined { + export function getReferencedSymbolsForNode( + position: number, + node: Node, + program: Program, + sourceFiles: readonly SourceFile[], + cancellationToken: CancellationToken, + options: Options = {}, + sourceFilesSet: ReadonlySet = new Set(sourceFiles.map(f => f.fileName)), + ): readonly SymbolAndEntries[] | undefined { node = getAdjustedNode(node, options); if (isSourceFile(node)) { const resolvedRef = GoToDefinition.getReferenceAtPosition(node, position, program); @@ -980,7 +1132,13 @@ export namespace Core { } const moduleSymbol = program.getTypeChecker().getMergedSymbol(resolvedRef.file.symbol); if (moduleSymbol) { - return getReferencedSymbolsForModule(program, moduleSymbol, /*excludeImportTypeOfExportEquals*/ false, sourceFiles, sourceFilesSet); + return getReferencedSymbolsForModule( + program, + moduleSymbol, + /*excludeImportTypeOfExportEquals*/ false, + sourceFiles, + sourceFilesSet, + ); } const fileIncludeReasons = program.getFileIncludeReasons(); if (!fileIncludeReasons) { @@ -1009,10 +1167,17 @@ export namespace Core { if (!options.implementations && isStringLiteralLike(node)) { if (isModuleSpecifierLike(node)) { const fileIncludeReasons = program.getFileIncludeReasons(); - const referencedFileName = node.getSourceFile().resolvedModules?.get(node.text, getModeForUsageLocation(node.getSourceFile(), node))?.resolvedModule?.resolvedFileName; + const referencedFileName = node.getSourceFile().resolvedModules?.get( + node.text, + getModeForUsageLocation(node.getSourceFile(), node), + )?.resolvedModule?.resolvedFileName; const referencedFile = referencedFileName ? program.getSourceFile(referencedFileName) : undefined; if (referencedFile) { - return [{ definition: { type: DefinitionKind.String, node }, references: getReferencesForNonModule(referencedFile, fileIncludeReasons, program) || emptyArray }]; + return [{ + definition: { type: DefinitionKind.String, node }, + references: getReferencesForNonModule(referencedFile, fileIncludeReasons, program) + || emptyArray, + }]; } // Fall through to string literal references. This is not very likely to return // anything useful, but I guess it's better than nothing, and there's an existing @@ -1024,19 +1189,47 @@ export namespace Core { } if (symbol.escapedName === InternalSymbolName.ExportEquals) { - return getReferencedSymbolsForModule(program, symbol.parent!, /*excludeImportTypeOfExportEquals*/ false, sourceFiles, sourceFilesSet); + return getReferencedSymbolsForModule( + program, + symbol.parent!, + /*excludeImportTypeOfExportEquals*/ false, + sourceFiles, + sourceFilesSet, + ); } - const moduleReferences = getReferencedSymbolsForModuleIfDeclaredBySourceFile(symbol, program, sourceFiles, cancellationToken, options, sourceFilesSet); + const moduleReferences = getReferencedSymbolsForModuleIfDeclaredBySourceFile( + symbol, + program, + sourceFiles, + cancellationToken, + options, + sourceFilesSet, + ); if (moduleReferences && !(symbol.flags & SymbolFlags.Transient)) { return moduleReferences; } const aliasedSymbol = getMergedAliasedSymbolOfNamespaceExportDeclaration(node, symbol, checker); - const moduleReferencesOfExportTarget = aliasedSymbol && - getReferencedSymbolsForModuleIfDeclaredBySourceFile(aliasedSymbol, program, sourceFiles, cancellationToken, options, sourceFilesSet); + const moduleReferencesOfExportTarget = aliasedSymbol + && getReferencedSymbolsForModuleIfDeclaredBySourceFile( + aliasedSymbol, + program, + sourceFiles, + cancellationToken, + options, + sourceFilesSet, + ); - const references = getReferencedSymbolsForSymbol(symbol, node, sourceFiles, sourceFilesSet, checker, cancellationToken, options); + const references = getReferencedSymbolsForSymbol( + symbol, + node, + sourceFiles, + sourceFilesSet, + checker, + cancellationToken, + options, + ); return mergeReferences(program, moduleReferences, references, moduleReferencesOfExportTarget); } @@ -1050,17 +1243,33 @@ export namespace Core { return node; } - export function getReferencesForFileName(fileName: string, program: Program, sourceFiles: readonly SourceFile[], sourceFilesSet: ReadonlySet = new Set(sourceFiles.map(f => f.fileName))): readonly Entry[] { + export function getReferencesForFileName( + fileName: string, + program: Program, + sourceFiles: readonly SourceFile[], + sourceFilesSet: ReadonlySet = new Set(sourceFiles.map(f => f.fileName)), + ): readonly Entry[] { const moduleSymbol = program.getSourceFile(fileName)?.symbol; if (moduleSymbol) { - return getReferencedSymbolsForModule(program, moduleSymbol, /*excludeImportTypeOfExportEquals*/ false, sourceFiles, sourceFilesSet)[0]?.references || emptyArray; + return getReferencedSymbolsForModule( + program, + moduleSymbol, + /*excludeImportTypeOfExportEquals*/ false, + sourceFiles, + sourceFilesSet, + )[0]?.references || emptyArray; } const fileIncludeReasons = program.getFileIncludeReasons(); const referencedFile = program.getSourceFile(fileName); - return referencedFile && fileIncludeReasons && getReferencesForNonModule(referencedFile, fileIncludeReasons, program) || emptyArray; + return referencedFile && fileIncludeReasons + && getReferencesForNonModule(referencedFile, fileIncludeReasons, program) || emptyArray; } - function getReferencesForNonModule(referencedFile: SourceFile, refFileMap: MultiMap, program: Program): readonly SpanEntry[] | undefined { + function getReferencesForNonModule( + referencedFile: SourceFile, + refFileMap: MultiMap, + program: Program, + ): readonly SpanEntry[] | undefined { let entries: SpanEntry[] | undefined; const references = refFileMap.get(referencedFile.path) || emptyArray; for (const ref of references) { @@ -1090,23 +1299,52 @@ export namespace Core { return undefined; } - function getReferencedSymbolsForModuleIfDeclaredBySourceFile(symbol: Symbol, program: Program, sourceFiles: readonly SourceFile[], cancellationToken: CancellationToken, options: Options, sourceFilesSet: ReadonlySet) { - const moduleSourceFile = (symbol.flags & SymbolFlags.Module) && symbol.declarations && find(symbol.declarations, isSourceFile); + function getReferencedSymbolsForModuleIfDeclaredBySourceFile( + symbol: Symbol, + program: Program, + sourceFiles: readonly SourceFile[], + cancellationToken: CancellationToken, + options: Options, + sourceFilesSet: ReadonlySet, + ) { + const moduleSourceFile = (symbol.flags & SymbolFlags.Module) && symbol.declarations + && find(symbol.declarations, isSourceFile); if (!moduleSourceFile) return undefined; const exportEquals = symbol.exports!.get(InternalSymbolName.ExportEquals); // If !!exportEquals, we're about to add references to `import("mod")` anyway, so don't double-count them. - const moduleReferences = getReferencedSymbolsForModule(program, symbol, !!exportEquals, sourceFiles, sourceFilesSet); + const moduleReferences = getReferencedSymbolsForModule( + program, + symbol, + !!exportEquals, + sourceFiles, + sourceFilesSet, + ); if (!exportEquals || !sourceFilesSet.has(moduleSourceFile.fileName)) return moduleReferences; // Continue to get references to 'export ='. const checker = program.getTypeChecker(); symbol = skipAlias(exportEquals, checker); - return mergeReferences(program, moduleReferences, getReferencedSymbolsForSymbol(symbol, /*node*/ undefined, sourceFiles, sourceFilesSet, checker, cancellationToken, options)); + return mergeReferences( + program, + moduleReferences, + getReferencedSymbolsForSymbol( + symbol, + /*node*/ undefined, + sourceFiles, + sourceFilesSet, + checker, + cancellationToken, + options, + ), + ); } /** * Merges the references by sorting them (by file index in sourceFiles and their location in it) that point to same definition symbol */ - function mergeReferences(program: Program, ...referencesToMerge: (SymbolAndEntries[] | undefined)[]): SymbolAndEntries[] | undefined { + function mergeReferences( + program: Program, + ...referencesToMerge: (SymbolAndEntries[] | undefined)[] + ): SymbolAndEntries[] | undefined { let result: SymbolAndEntries[] | undefined; for (const references of referencesToMerge) { if (!references || !references.length) continue; @@ -1121,9 +1359,9 @@ export namespace Core { } const symbol = entry.definition.symbol; const refIndex = findIndex(result, ref => - !!ref.definition && - ref.definition.type === DefinitionKind.Symbol && - ref.definition.symbol === symbol); + !!ref.definition + && ref.definition.type === DefinitionKind.Symbol + && ref.definition.symbol === symbol); if (refIndex === -1) { result.push(entry); continue; @@ -1141,9 +1379,9 @@ export namespace Core { const entry1Span = getTextSpanOfEntry(entry1); const entry2Span = getTextSpanOfEntry(entry2); - return entry1Span.start !== entry2Span.start ? - compareValues(entry1Span.start, entry2Span.start) : - compareValues(entry1Span.length, entry2Span.length); + return entry1Span.start !== entry2Span.start + ? compareValues(entry1Span.start, entry2Span.start) + : compareValues(entry1Span.length, entry2Span.length); }), }; } @@ -1152,43 +1390,53 @@ export namespace Core { } function getSourceFileIndexOfEntry(program: Program, entry: Entry) { - const sourceFile = entry.kind === EntryKind.Span ? - program.getSourceFile(entry.fileName)! : - entry.node.getSourceFile(); + const sourceFile = entry.kind === EntryKind.Span + ? program.getSourceFile(entry.fileName)! + : entry.node.getSourceFile(); return program.getSourceFiles().indexOf(sourceFile); } - function getReferencedSymbolsForModule(program: Program, symbol: Symbol, excludeImportTypeOfExportEquals: boolean, sourceFiles: readonly SourceFile[], sourceFilesSet: ReadonlySet): SymbolAndEntries[] { + function getReferencedSymbolsForModule( + program: Program, + symbol: Symbol, + excludeImportTypeOfExportEquals: boolean, + sourceFiles: readonly SourceFile[], + sourceFilesSet: ReadonlySet, + ): SymbolAndEntries[] { Debug.assert(!!symbol.valueDeclaration); - const references = mapDefined(findModuleReferences(program, sourceFiles, symbol), reference => { - if (reference.kind === "import") { - const parent = reference.literal.parent; - if (isLiteralTypeNode(parent)) { - const importType = cast(parent.parent, isImportTypeNode); - if (excludeImportTypeOfExportEquals && !importType.qualifier) { - return undefined; + const references = mapDefined( + findModuleReferences(program, sourceFiles, symbol), + reference => { + if (reference.kind === "import") { + const parent = reference.literal.parent; + if (isLiteralTypeNode(parent)) { + const importType = cast(parent.parent, isImportTypeNode); + if (excludeImportTypeOfExportEquals && !importType.qualifier) { + return undefined; + } } + // import("foo") with no qualifier will reference the `export =` of the module, which may be referenced anyway. + return nodeEntry(reference.literal); } - // import("foo") with no qualifier will reference the `export =` of the module, which may be referenced anyway. - return nodeEntry(reference.literal); - } - else if (reference.kind === "implicit") { - // Return either: The first JSX node in the (if not a tslib import), the first statement of the file, or the whole file if neither of those exist - const range = reference.literal.text !== externalHelpersModuleNameText && forEachChildRecursively( - reference.referencingFile, - n => !(n.transformFlags & TransformFlags.ContainsJsx) ? "skip" : isJsxElement(n) || isJsxSelfClosingElement(n) || isJsxFragment(n) ? n : undefined, - ) || reference.referencingFile.statements[0] || reference.referencingFile; - return nodeEntry(range); - } - else { - return { - kind: EntryKind.Span, - fileName: reference.referencingFile.fileName, - textSpan: createTextSpanFromRange(reference.ref), - }; - } - }); + else if (reference.kind === "implicit") { + // Return either: The first JSX node in the (if not a tslib import), the first statement of the file, or the whole file if neither of those exist + const range = reference.literal.text !== externalHelpersModuleNameText && forEachChildRecursively( + reference.referencingFile, + n => !(n.transformFlags & TransformFlags.ContainsJsx) ? "skip" + : isJsxElement(n) || isJsxSelfClosingElement(n) || isJsxFragment(n) ? n : undefined, + ) || reference.referencingFile.statements[0] || reference.referencingFile; + return nodeEntry(range); + } + else { + return { + kind: EntryKind.Span, + fileName: reference.referencingFile.fileName, + textSpan: createTextSpanFromRange(reference.ref), + }; + } + }, + ); if (symbol.declarations) { for (const decl of symbol.declarations) { @@ -1203,7 +1451,10 @@ export namespace Core { break; default: // This may be merged with something. - Debug.assert(!!(symbol.flags & SymbolFlags.Transient), "Expected a module symbol to be declared by a SourceFile or ModuleDeclaration."); + Debug.assert( + !!(symbol.flags & SymbolFlags.Transient), + "Expected a module symbol to be declared by a SourceFile or ModuleDeclaration.", + ); } } } @@ -1214,9 +1465,11 @@ export namespace Core { const sourceFile = decl.getSourceFile(); if (sourceFilesSet.has(sourceFile.fileName)) { // At `module.exports = ...`, reference node is `module` - const node = isBinaryExpression(decl) && isPropertyAccessExpression(decl.left) ? decl.left.expression : - isExportAssignment(decl) ? Debug.checkDefined(findChildOfKind(decl, SyntaxKind.ExportKeyword, sourceFile)) : - getNameOfDeclaration(decl) || decl; + const node = isBinaryExpression(decl) && isPropertyAccessExpression(decl.left) + ? decl.left.expression + : isExportAssignment(decl) + ? Debug.checkDefined(findChildOfKind(decl, SyntaxKind.ExportKeyword, sourceFile)) + : getNameOfDeclaration(decl) || decl; references.push(nodeEntry(node)); } } @@ -1233,7 +1486,11 @@ export namespace Core { } /** getReferencedSymbols for special node kinds. */ - function getReferencedSymbolsSpecial(node: Node, sourceFiles: readonly SourceFile[], cancellationToken: CancellationToken): SymbolAndEntries[] | undefined { + function getReferencedSymbolsSpecial( + node: Node, + sourceFiles: readonly SourceFile[], + cancellationToken: CancellationToken, + ): SymbolAndEntries[] | undefined { if (isTypeKeyword(node.kind)) { // A void expression (i.e., `void foo()`) is not special, but the `void` type is. if (node.kind === SyntaxKind.VoidKeyword && isVoidExpression(node.parent)) { @@ -1287,25 +1544,73 @@ export namespace Core { } /** Core find-all-references algorithm for a normal symbol. */ - function getReferencedSymbolsForSymbol(originalSymbol: Symbol, node: Node | undefined, sourceFiles: readonly SourceFile[], sourceFilesSet: ReadonlySet, checker: TypeChecker, cancellationToken: CancellationToken, options: Options): SymbolAndEntries[] { - const symbol = node && skipPastExportOrImportSpecifierOrUnion(originalSymbol, node, checker, /*useLocalSymbolForExportSpecifier*/ !isForRenameWithPrefixAndSuffixText(options)) || originalSymbol; + function getReferencedSymbolsForSymbol( + originalSymbol: Symbol, + node: Node | undefined, + sourceFiles: readonly SourceFile[], + sourceFilesSet: ReadonlySet, + checker: TypeChecker, + cancellationToken: CancellationToken, + options: Options, + ): SymbolAndEntries[] { + const symbol = node + && skipPastExportOrImportSpecifierOrUnion( + originalSymbol, + node, + checker, + /*useLocalSymbolForExportSpecifier*/ !isForRenameWithPrefixAndSuffixText(options), + ) || originalSymbol; // Compute the meaning from the location and the symbol it references const searchMeaning = node ? getIntersectingMeaningFromDeclarations(node, symbol) : SemanticMeaning.All; const result: SymbolAndEntries[] = []; - const state = new State(sourceFiles, sourceFilesSet, node ? getSpecialSearchKind(node) : SpecialSearchKind.None, checker, cancellationToken, searchMeaning, options, result); + const state = new State( + sourceFiles, + sourceFilesSet, + node ? getSpecialSearchKind(node) : SpecialSearchKind.None, + checker, + cancellationToken, + searchMeaning, + options, + result, + ); - const exportSpecifier = !isForRenameWithPrefixAndSuffixText(options) || !symbol.declarations ? undefined : find(symbol.declarations, isExportSpecifier); + const exportSpecifier = !isForRenameWithPrefixAndSuffixText(options) || !symbol.declarations ? undefined + : find(symbol.declarations, isExportSpecifier); if (exportSpecifier) { // When renaming at an export specifier, rename the export and not the thing being exported. - getReferencesAtExportSpecifier(exportSpecifier.name, symbol, exportSpecifier, state.createSearch(node, originalSymbol, /*comingFrom*/ undefined), state, /*addReferencesHere*/ true, /*alwaysGetReferences*/ true); + getReferencesAtExportSpecifier( + exportSpecifier.name, + symbol, + exportSpecifier, + state.createSearch(node, originalSymbol, /*comingFrom*/ undefined), + state, + /*addReferencesHere*/ true, + /*alwaysGetReferences*/ true, + ); } - else if (node && node.kind === SyntaxKind.DefaultKeyword && symbol.escapedName === InternalSymbolName.Default && symbol.parent) { + else if ( + node && node.kind === SyntaxKind.DefaultKeyword && symbol.escapedName === InternalSymbolName.Default + && symbol.parent + ) { addReference(node, symbol, state); - searchForImportsOfExport(node, symbol, { exportingModuleSymbol: symbol.parent, exportKind: ExportKind.Default }, state); + searchForImportsOfExport(node, symbol, { + exportingModuleSymbol: symbol.parent, + exportKind: ExportKind.Default, + }, state); } else { - const search = state.createSearch(node, symbol, /*comingFrom*/ undefined, { allSearchSymbols: node ? populateSearchSymbolSet(symbol, node, checker, options.use === FindReferencesUse.Rename, !!options.providePrefixAndSuffixTextForRename, !!options.implementations) : [symbol] }); + const search = state.createSearch(node, symbol, /*comingFrom*/ undefined, { + allSearchSymbols: node + ? populateSearchSymbolSet( + symbol, + node, + checker, + options.use === FindReferencesUse.Rename, + !!options.providePrefixAndSuffixTextForRename, + !!options.implementations, + ) : [symbol], + }); getReferencesInContainerOrFiles(symbol, state, search); } @@ -1317,7 +1622,13 @@ export namespace Core { // otherwise we'll need to search globally (i.e. include each file). const scope = getSymbolScope(symbol); if (scope) { - getReferencesInContainer(scope, scope.getSourceFile(), search, state, /*addReferencesHere*/ !(isSourceFile(scope) && !contains(state.sourceFiles, scope))); + getReferencesInContainer( + scope, + scope.getSourceFile(), + search, + state, + /*addReferencesHere*/ !(isSourceFile(scope) && !contains(state.sourceFiles, scope)), + ); } else { // Global search @@ -1345,7 +1656,12 @@ export namespace Core { } /** Handle a few special cases relating to export/import specifiers. */ - function skipPastExportOrImportSpecifierOrUnion(symbol: Symbol, node: Node, checker: TypeChecker, useLocalSymbolForExportSpecifier: boolean): Symbol | undefined { + function skipPastExportOrImportSpecifierOrUnion( + symbol: Symbol, + node: Node, + checker: TypeChecker, + useLocalSymbolForExportSpecifier: boolean, + ): Symbol | undefined { const { parent } = node; if (isExportSpecifier(parent) && useLocalSymbolForExportSpecifier) { return getLocalSymbolForExportSpecifier(node as Identifier, symbol, parent, checker); @@ -1447,23 +1763,49 @@ export namespace Core { private importTracker: ImportTracker | undefined; /** Gets every place to look for references of an exported symbols. See `ImportsResult` in `importTracker.ts` for more documentation. */ getImportSearches(exportSymbol: Symbol, exportInfo: ExportInfo): ImportsResult { - if (!this.importTracker) this.importTracker = createImportTracker(this.sourceFiles, this.sourceFilesSet, this.checker, this.cancellationToken); + if (!this.importTracker) { + this.importTracker = createImportTracker( + this.sourceFiles, + this.sourceFilesSet, + this.checker, + this.cancellationToken, + ); + } return this.importTracker(exportSymbol, exportInfo, this.options.use === FindReferencesUse.Rename); } /** @param allSearchSymbols set of additional symbols for use by `includes`. */ - createSearch(location: Node | undefined, symbol: Symbol, comingFrom: ImportExport | undefined, searchOptions: { text?: string; allSearchSymbols?: Symbol[]; } = {}): Search { + createSearch( + location: Node | undefined, + symbol: Symbol, + comingFrom: ImportExport | undefined, + searchOptions: { text?: string; allSearchSymbols?: Symbol[]; } = {}, + ): Search { // Note: if this is an external module symbol, the name doesn't include quotes. // Note: getLocalSymbolForExportDefault handles `export default class C {}`, but not `export default C` or `export { C as default }`. // The other two forms seem to be handled downstream (e.g. in `skipPastExportOrImportSpecifier`), so special-casing the first form // here appears to be intentional). const { - text = stripQuotes(symbolName(getLocalSymbolForExportDefault(symbol) || getNonModuleSymbolOfMergedModuleSymbol(symbol) || symbol)), + text = stripQuotes( + symbolName( + getLocalSymbolForExportDefault(symbol) || getNonModuleSymbolOfMergedModuleSymbol(symbol) + || symbol, + ), + ), allSearchSymbols = [symbol], } = searchOptions; const escapedText = escapeLeadingUnderscores(text); - const parents = this.options.implementations && location ? getParentSymbolsOfPropertyAccess(location, symbol, this.checker) : undefined; - return { symbol, comingFrom, text, escapedText, parents, allSearchSymbols, includes: sym => contains(allSearchSymbols, sym) }; + const parents = this.options.implementations && location + ? getParentSymbolsOfPropertyAccess(location, symbol, this.checker) : undefined; + return { + symbol, + comingFrom, + text, + escapedText, + parents, + allSearchSymbols, + includes: sym => contains(allSearchSymbols, sym), + }; } private readonly symbolIdToReferences: Entry[][] = []; @@ -1494,7 +1836,8 @@ export namespace Core { /** Returns `true` the first time we search for a symbol in a file and `false` afterwards. */ markSearchedSymbols(sourceFile: SourceFile, symbols: readonly Symbol[]): boolean { const sourceId = getNodeId(sourceFile); - const seenSymbols = this.sourceFileToSeenSymbols[sourceId] || (this.sourceFileToSeenSymbols[sourceId] = new Set()); + const seenSymbols = this.sourceFileToSeenSymbols[sourceId] + || (this.sourceFileToSeenSymbols[sourceId] = new Set()); let anyNewSymbols = false; for (const sym of symbols) { @@ -1505,7 +1848,12 @@ export namespace Core { } /** Search for all imports of a given exported symbol using `State.getImportSearches`. */ - function searchForImportsOfExport(exportLocation: Node, exportSymbol: Symbol, exportInfo: ExportInfo, state: State): void { + function searchForImportsOfExport( + exportLocation: Node, + exportSymbol: Symbol, + exportInfo: ExportInfo, + state: State, + ): void { const { importSearches, singleReferences, indirectUsers } = state.getImportSearches(exportSymbol, exportInfo); // For `import { foo as bar }` just add the reference to `foo`, and don't otherwise search in the file. @@ -1518,7 +1866,11 @@ export namespace Core { // For each import, find all references to that import in its source file. for (const [importLocation, importSymbol] of importSearches) { - getReferencesInSourceFile(importLocation.getSourceFile(), state.createSearch(importLocation, importSymbol, ImportExport.Export), state); + getReferencesInSourceFile( + importLocation.getSourceFile(), + state.createSearch(importLocation, importSymbol, ImportExport.Export), + state, + ); } if (indirectUsers.length) { @@ -1529,7 +1881,8 @@ export namespace Core { break; case ExportKind.Default: // Search for a property access to '.default'. This can't be renamed. - indirectSearch = state.options.use === FindReferencesUse.Rename ? undefined : state.createSearch(exportLocation, exportSymbol, ImportExport.Export, { text: "default" }); + indirectSearch = state.options.use === FindReferencesUse.Rename ? undefined + : state.createSearch(exportLocation, exportSymbol, ImportExport.Export, { text: "default" }); break; case ExportKind.ExportEquals: break; @@ -1552,8 +1905,16 @@ export namespace Core { isDefaultExport: boolean, cb: (ref: Identifier) => void, ): void { - const importTracker = createImportTracker(sourceFiles, new Set(sourceFiles.map(f => f.fileName)), checker, cancellationToken); - const { importSearches, indirectUsers, singleReferences } = importTracker(exportSymbol, { exportKind: isDefaultExport ? ExportKind.Default : ExportKind.Named, exportingModuleSymbol }, /*isForRename*/ false); + const importTracker = createImportTracker( + sourceFiles, + new Set(sourceFiles.map(f => f.fileName)), + checker, + cancellationToken, + ); + const { importSearches, indirectUsers, singleReferences } = importTracker(exportSymbol, { + exportKind: isDefaultExport ? ExportKind.Default : ExportKind.Named, + exportingModuleSymbol, + }, /*isForRename*/ false); for (const [importLocation] of importSearches) { cb(importLocation); } @@ -1563,11 +1924,19 @@ export namespace Core { } } for (const indirectUser of indirectUsers) { - for (const node of getPossibleSymbolReferenceNodes(indirectUser, isDefaultExport ? "default" : exportName)) { + for ( + const node of getPossibleSymbolReferenceNodes(indirectUser, isDefaultExport ? "default" : exportName) + ) { // Import specifiers should be handled by importSearches const symbol = checker.getSymbolAtLocation(node); - const hasExportAssignmentDeclaration = some(symbol?.declarations, d => tryCast(d, isExportAssignment) ? true : false); - if (isIdentifier(node) && !isImportOrExportSpecifier(node.parent) && (symbol === exportSymbol || hasExportAssignmentDeclaration)) { + const hasExportAssignmentDeclaration = some( + symbol?.declarations, + d => tryCast(d, isExportAssignment) ? true : false, + ); + if ( + isIdentifier(node) && !isImportOrExportSpecifier(node.parent) + && (symbol === exportSymbol || hasExportAssignmentDeclaration) + ) { cb(node); } } @@ -1590,7 +1959,12 @@ export namespace Core { for (const declaration of symbol.declarations) { const exportingFile = declaration.getSourceFile(); // Need to search in the file even if it's not in the search-file set, because it might export the symbol. - getReferencesInSourceFile(exportingFile, state.createSearch(declaration, symbol, ImportExport.Import), state, state.includesSourceFile(exportingFile)); + getReferencesInSourceFile( + exportingFile, + state.createSearch(declaration, symbol, ImportExport.Import), + state, + state.includesSourceFile(exportingFile), + ); } } @@ -1619,7 +1993,11 @@ export namespace Core { // If this is the symbol of a named function expression or named class expression, // then named references are limited to its own scope. const { declarations, flags, parent, valueDeclaration } = symbol; - if (valueDeclaration && (valueDeclaration.kind === SyntaxKind.FunctionExpression || valueDeclaration.kind === SyntaxKind.ClassExpression)) { + if ( + valueDeclaration + && (valueDeclaration.kind === SyntaxKind.FunctionExpression + || valueDeclaration.kind === SyntaxKind.ClassExpression) + ) { return valueDeclaration; } @@ -1629,7 +2007,10 @@ export namespace Core { // If this is private property or method, the scope is the containing class if (flags & (SymbolFlags.Property | SymbolFlags.Method)) { - const privateDeclaration = find(declarations, d => hasEffectiveModifier(d, ModifierFlags.Private) || isPrivateIdentifierClassElementDeclaration(d)); + const privateDeclaration = find( + declarations, + d => hasEffectiveModifier(d, ModifierFlags.Private) || isPrivateIdentifierClassElementDeclaration(d), + ); if (privateDeclaration) { return getAncestor(privateDeclaration, SyntaxKind.ClassDeclaration); } @@ -1663,7 +2044,10 @@ export namespace Core { return undefined; } - if (!container || container.kind === SyntaxKind.SourceFile && !isExternalOrCommonJsModule(container as SourceFile)) { + if ( + !container + || container.kind === SyntaxKind.SourceFile && !isExternalOrCommonJsModule(container as SourceFile) + ) { // This is a global variable and not an external module, any declaration defined // within this scope is visible outside the file return undefined; @@ -1687,11 +2071,22 @@ export namespace Core { } /** Used as a quick check for whether a symbol is used at all in a file (besides its definition). */ - export function isSymbolReferencedInFile(definition: Identifier, checker: TypeChecker, sourceFile: SourceFile, searchContainer: Node = sourceFile): boolean { + export function isSymbolReferencedInFile( + definition: Identifier, + checker: TypeChecker, + sourceFile: SourceFile, + searchContainer: Node = sourceFile, + ): boolean { return eachSymbolReferenceInFile(definition, checker, sourceFile, () => true, searchContainer) || false; } - export function eachSymbolReferenceInFile(definition: Identifier, checker: TypeChecker, sourceFile: SourceFile, cb: (token: Identifier) => T, searchContainer: Node = sourceFile): T | undefined { + export function eachSymbolReferenceInFile( + definition: Identifier, + checker: TypeChecker, + sourceFile: SourceFile, + cb: (token: Identifier) => T, + searchContainer: Node = sourceFile, + ): T | undefined { const symbol = isParameterPropertyDeclaration(definition.parent, definition.parent.parent) ? first(checker.getSymbolsOfParameterPropertyDeclaration(definition.parent, definition.text)) : checker.getSymbolAtLocation(definition); @@ -1702,7 +2097,8 @@ export namespace Core { if ( referenceSymbol === symbol || checker.getShorthandAssignmentValueSymbol(token.parent) === symbol - || isExportSpecifier(token.parent) && getLocalSymbolForExportSpecifier(token, referenceSymbol, token.parent, checker) === symbol + || isExportSpecifier(token.parent) + && getLocalSymbolForExportSpecifier(token, referenceSymbol, token.parent, checker) === symbol ) { const res = cb(token); if (res) return res; @@ -1711,7 +2107,10 @@ export namespace Core { } export function getTopMostDeclarationNamesInFile(declarationName: string, sourceFile: SourceFile): readonly Node[] { - const candidates = filter(getPossibleSymbolReferenceNodes(sourceFile, declarationName), name => !!getDeclarationFromName(name)); + const candidates = filter( + getPossibleSymbolReferenceNodes(sourceFile, declarationName), + name => !!getDeclarationFromName(name), + ); return candidates.reduce((topMost, decl) => { const depth = getDepth(decl); if (!some(topMost.declarationNames) || depth === topMost.depth) { @@ -1747,9 +2146,12 @@ export namespace Core { for (const sourceFile of sourceFiles) { for (const name of getPossibleSymbolReferenceNodes(sourceFile, symbol.name)) { - if (!isIdentifier(name) || name === signature.name || name.escapedText !== signature.name.escapedText) continue; + if (!isIdentifier(name) || name === signature.name || name.escapedText !== signature.name.escapedText) { + continue; + } const called = climbPastPropertyAccess(name); - const call = isCallExpression(called.parent) && called.parent.expression === called ? called.parent : undefined; + const call = isCallExpression(called.parent) && called.parent.expression === called ? called.parent + : undefined; const referenceSymbol = checker.getSymbolAtLocation(name); if (referenceSymbol && checker.getRootSymbols(referenceSymbol).some(s => s === symbol)) { if (cb(name, call)) { @@ -1761,14 +2163,22 @@ export namespace Core { return false; } - function getPossibleSymbolReferenceNodes(sourceFile: SourceFile, symbolName: string, container: Node = sourceFile): readonly Node[] { + function getPossibleSymbolReferenceNodes( + sourceFile: SourceFile, + symbolName: string, + container: Node = sourceFile, + ): readonly Node[] { return mapDefined(getPossibleSymbolReferencePositions(sourceFile, symbolName, container), pos => { const referenceLocation = getTouchingPropertyName(sourceFile, pos); return referenceLocation === sourceFile ? undefined : referenceLocation; }); } - function getPossibleSymbolReferencePositions(sourceFile: SourceFile, symbolName: string, container: Node = sourceFile): readonly number[] { + function getPossibleSymbolReferencePositions( + sourceFile: SourceFile, + symbolName: string, + container: Node = sourceFile, + ): readonly number[] { const positions: number[] = []; /// TODO: Cache symbol existence for files to save text search @@ -1793,8 +2203,9 @@ export namespace Core { const endPosition = position + symbolNameLength; if ( - (position === 0 || !isIdentifierPart(text.charCodeAt(position - 1), ScriptTarget.Latest)) && - (endPosition === sourceLength || !isIdentifierPart(text.charCodeAt(endPosition), ScriptTarget.Latest)) + (position === 0 || !isIdentifierPart(text.charCodeAt(position - 1), ScriptTarget.Latest)) + && (endPosition === sourceLength + || !isIdentifierPart(text.charCodeAt(endPosition), ScriptTarget.Latest)) ) { // Found a real match. Keep searching. positions.push(position); @@ -1810,7 +2221,8 @@ export namespace Core { const labelName = targetLabel.text; const references = mapDefined(getPossibleSymbolReferenceNodes(sourceFile, labelName, container), node => // Only pick labels that are either the target label, or have a target that is the target label - node === targetLabel || (isJumpStatementTarget(node) && getTargetLabel(node, labelName) === targetLabel) ? nodeEntry(node) : undefined); + node === targetLabel || (isJumpStatementTarget(node) && getTargetLabel(node, labelName) === targetLabel) + ? nodeEntry(node) : undefined); return [{ definition: { type: DefinitionKind.Label, node: targetLabel }, references }]; } @@ -1827,12 +2239,16 @@ export namespace Core { case SyntaxKind.NoSubstitutionTemplateLiteral: case SyntaxKind.StringLiteral: { const str = node as StringLiteralLike; - return (isLiteralNameOfPropertyDeclarationOrIndexAccess(str) || isNameOfModuleDeclaration(node) || isExpressionOfExternalModuleImportEqualsDeclaration(node) || (isCallExpression(node.parent) && isBindableObjectDefinePropertyCall(node.parent) && node.parent.arguments[1] === node)) && - str.text.length === searchSymbolName.length; + return (isLiteralNameOfPropertyDeclarationOrIndexAccess(str) || isNameOfModuleDeclaration(node) + || isExpressionOfExternalModuleImportEqualsDeclaration(node) + || (isCallExpression(node.parent) && isBindableObjectDefinePropertyCall(node.parent) + && node.parent.arguments[1] === node)) + && str.text.length === searchSymbolName.length; } case SyntaxKind.NumericLiteral: - return isLiteralNameOfPropertyDeclarationOrIndexAccess(node as NumericLiteral) && (node as NumericLiteral).text.length === searchSymbolName.length; + return isLiteralNameOfPropertyDeclarationOrIndexAccess(node as NumericLiteral) + && (node as NumericLiteral).text.length === searchSymbolName.length; case SyntaxKind.DefaultKeyword: return "default".length === searchSymbolName.length; @@ -1842,7 +2258,10 @@ export namespace Core { } } - function getAllReferencesForImportMeta(sourceFiles: readonly SourceFile[], cancellationToken: CancellationToken): SymbolAndEntries[] | undefined { + function getAllReferencesForImportMeta( + sourceFiles: readonly SourceFile[], + cancellationToken: CancellationToken, + ): SymbolAndEntries[] | undefined { const references = flatMap(sourceFiles, sourceFile => { cancellationToken.throwIfCancellationRequested(); return mapDefined(getPossibleSymbolReferenceNodes(sourceFile, "meta", sourceFile), node => { @@ -1852,22 +2271,37 @@ export namespace Core { } }); }); - return references.length ? [{ definition: { type: DefinitionKind.Keyword, node: references[0].node }, references }] : undefined; + return references.length + ? [{ definition: { type: DefinitionKind.Keyword, node: references[0].node }, references }] : undefined; } - function getAllReferencesForKeyword(sourceFiles: readonly SourceFile[], keywordKind: SyntaxKind, cancellationToken: CancellationToken, filter?: (node: Node) => boolean): SymbolAndEntries[] | undefined { + function getAllReferencesForKeyword( + sourceFiles: readonly SourceFile[], + keywordKind: SyntaxKind, + cancellationToken: CancellationToken, + filter?: (node: Node) => boolean, + ): SymbolAndEntries[] | undefined { const references = flatMap(sourceFiles, sourceFile => { cancellationToken.throwIfCancellationRequested(); - return mapDefined(getPossibleSymbolReferenceNodes(sourceFile, tokenToString(keywordKind)!, sourceFile), referenceLocation => { - if (referenceLocation.kind === keywordKind && (!filter || filter(referenceLocation))) { - return nodeEntry(referenceLocation); - } - }); + return mapDefined( + getPossibleSymbolReferenceNodes(sourceFile, tokenToString(keywordKind)!, sourceFile), + referenceLocation => { + if (referenceLocation.kind === keywordKind && (!filter || filter(referenceLocation))) { + return nodeEntry(referenceLocation); + } + }, + ); }); - return references.length ? [{ definition: { type: DefinitionKind.Keyword, node: references[0].node }, references }] : undefined; + return references.length + ? [{ definition: { type: DefinitionKind.Keyword, node: references[0].node }, references }] : undefined; } - function getReferencesInSourceFile(sourceFile: SourceFile, search: Search, state: State, addReferencesHere = true): void { + function getReferencesInSourceFile( + sourceFile: SourceFile, + search: Search, + state: State, + addReferencesHere = true, + ): void { state.cancellationToken.throwIfCancellationRequested(); return getReferencesInContainer(sourceFile, sourceFile, search, state, addReferencesHere); } @@ -1877,7 +2311,13 @@ export namespace Core { * tuple of(searchSymbol, searchText, searchLocation, and searchMeaning). * searchLocation: a node where the search value */ - function getReferencesInContainer(container: Node, sourceFile: SourceFile, search: Search, state: State, addReferencesHere: boolean): void { + function getReferencesInContainer( + container: Node, + sourceFile: SourceFile, + search: Search, + state: State, + addReferencesHere: boolean, + ): void { if (!state.markSearchedSymbols(sourceFile, search.allSearchSymbols)) { return; } @@ -1891,14 +2331,24 @@ export namespace Core { return !!(getMeaningFromLocation(referenceLocation) & state.searchMeaning); } - function getReferencesAtLocation(sourceFile: SourceFile, position: number, search: Search, state: State, addReferencesHere: boolean): void { + function getReferencesAtLocation( + sourceFile: SourceFile, + position: number, + search: Search, + state: State, + addReferencesHere: boolean, + ): void { const referenceLocation = getTouchingPropertyName(sourceFile, position); if (!isValidReferencePosition(referenceLocation, search.text)) { // This wasn't the start of a token. Check to see if it might be a // match in a comment or string if that's what the caller is asking // for. - if (!state.options.implementations && (state.options.findInStrings && isInString(sourceFile, position) || state.options.findInComments && isInNonReferenceComment(sourceFile, position))) { + if ( + !state.options.implementations + && (state.options.findInStrings && isInString(sourceFile, position) + || state.options.findInComments && isInNonReferenceComment(sourceFile, position)) + ) { // In the case where we're looking inside comments/strings, we don't have // an actual definition. So just use 'undefined' here. Features like // 'Rename' won't care (as they ignore the definitions), and features like @@ -1924,7 +2374,14 @@ export namespace Core { if (isExportSpecifier(parent)) { Debug.assert(referenceLocation.kind === SyntaxKind.Identifier); - getReferencesAtExportSpecifier(referenceLocation as Identifier, referenceSymbol, parent, search, state, addReferencesHere); + getReferencesAtExportSpecifier( + referenceLocation as Identifier, + referenceSymbol, + parent, + search, + state, + addReferencesHere, + ); return; } @@ -1972,18 +2429,28 @@ export namespace Core { addReferencesHere: boolean, alwaysGetReferences?: boolean, ): void { - Debug.assert(!alwaysGetReferences || !!state.options.providePrefixAndSuffixTextForRename, "If alwaysGetReferences is true, then prefix/suffix text must be enabled"); + Debug.assert( + !alwaysGetReferences || !!state.options.providePrefixAndSuffixTextForRename, + "If alwaysGetReferences is true, then prefix/suffix text must be enabled", + ); const { parent, propertyName, name } = exportSpecifier; const exportDeclaration = parent.parent; - const localSymbol = getLocalSymbolForExportSpecifier(referenceLocation, referenceSymbol, exportSpecifier, state.checker); + const localSymbol = getLocalSymbolForExportSpecifier( + referenceLocation, + referenceSymbol, + exportSpecifier, + state.checker, + ); if (!alwaysGetReferences && !search.includes(localSymbol)) { return; } if (!propertyName) { // Don't rename at `export { default } from "m";`. (but do continue to search for imports of the re-export) - if (!(state.options.use === FindReferencesUse.Rename && (name.escapedText === InternalSymbolName.Default))) { + if ( + !(state.options.use === FindReferencesUse.Rename && (name.escapedText === InternalSymbolName.Default)) + ) { addRef(); } } @@ -1994,7 +2461,9 @@ export namespace Core { addRef(); } - if (addReferencesHere && state.options.use !== FindReferencesUse.Rename && state.markSeenReExportRHS(name)) { + if ( + addReferencesHere && state.options.use !== FindReferencesUse.Rename && state.markSeenReExportRHS(name) + ) { addReference(name, Debug.checkDefined(exportSpecifier.symbol), state); } } @@ -2017,7 +2486,10 @@ export namespace Core { } // At `export { x } from "foo"`, also search for the imported symbol `"foo".x`. - if (search.comingFrom !== ImportExport.Export && exportDeclaration.moduleSpecifier && !propertyName && !isForRenameWithPrefixAndSuffixText(state.options)) { + if ( + search.comingFrom !== ImportExport.Export && exportDeclaration.moduleSpecifier && !propertyName + && !isForRenameWithPrefixAndSuffixText(state.options) + ) { const imported = state.checker.getExportSpecifierLocalTargetSymbol(exportSpecifier); if (imported) searchForImportedSymbol(imported, state); } @@ -2027,8 +2499,14 @@ export namespace Core { } } - function getLocalSymbolForExportSpecifier(referenceLocation: Identifier, referenceSymbol: Symbol, exportSpecifier: ExportSpecifier, checker: TypeChecker): Symbol { - return isExportSpecifierAlias(referenceLocation, exportSpecifier) && checker.getExportSpecifierLocalTargetSymbol(exportSpecifier) || referenceSymbol; + function getLocalSymbolForExportSpecifier( + referenceLocation: Identifier, + referenceSymbol: Symbol, + exportSpecifier: ExportSpecifier, + checker: TypeChecker, + ): Symbol { + return isExportSpecifierAlias(referenceLocation, exportSpecifier) + && checker.getExportSpecifierLocalTargetSymbol(exportSpecifier) || referenceSymbol; } function isExportSpecifierAlias(referenceLocation: Identifier, exportSpecifier: ExportSpecifier): boolean { @@ -2045,8 +2523,18 @@ export namespace Core { } } - function getImportOrExportReferences(referenceLocation: Node, referenceSymbol: Symbol, search: Search, state: State): void { - const importOrExport = getImportOrExportSymbol(referenceLocation, referenceSymbol, state.checker, search.comingFrom === ImportExport.Export); + function getImportOrExportReferences( + referenceLocation: Node, + referenceSymbol: Symbol, + search: Search, + state: State, + ): void { + const importOrExport = getImportOrExportSymbol( + referenceLocation, + referenceSymbol, + state.checker, + search.comingFrom === ImportExport.Export, + ); if (!importOrExport) return; const { symbol } = importOrExport; @@ -2094,7 +2582,12 @@ export namespace Core { } /** Adds references when a constructor is used with `new this()` in its own class and `super()` calls in subclasses. */ - function addConstructorReferences(referenceLocation: Node, sourceFile: SourceFile, search: Search, state: State): void { + function addConstructorReferences( + referenceLocation: Node, + sourceFile: SourceFile, + search: Search, + state: State, + ): void { if (isNewExpressionTarget(referenceLocation)) { addReference(referenceLocation, search.symbol, state); } @@ -2102,7 +2595,10 @@ export namespace Core { const pusher = () => state.referenceAdder(search.symbol); if (isClassLike(referenceLocation.parent)) { - Debug.assert(referenceLocation.kind === SyntaxKind.DefaultKeyword || referenceLocation.parent.name === referenceLocation); + Debug.assert( + referenceLocation.kind === SyntaxKind.DefaultKeyword + || referenceLocation.parent.name === referenceLocation, + ); // This is the class declaration containing the constructor. findOwnConstructorReferences(search.symbol, sourceFile, pusher()); } @@ -2143,7 +2639,11 @@ export namespace Core { * `classSymbol` is the class where the constructor was defined. * Reference the constructor and all calls to `new this()`. */ - function findOwnConstructorReferences(classSymbol: Symbol, sourceFile: SourceFile, addNode: (node: Node) => void): void { + function findOwnConstructorReferences( + classSymbol: Symbol, + sourceFile: SourceFile, + addNode: (node: Node) => void, + ): void { const constructorSymbol = getClassConstructorSymbol(classSymbol); if (constructorSymbol && constructorSymbol.declarations) { for (const decl of constructorSymbol.declarations) { @@ -2230,9 +2730,15 @@ export namespace Core { // If we got a type reference, try and see if the reference applies to any expressions that can implement an interface // Find the first node whose parent isn't a type node -- i.e., the highest type node. - const typeNode = findAncestor(refNode, a => !isQualifiedName(a.parent) && !isTypeNode(a.parent) && !isTypeElement(a.parent))!; + const typeNode = findAncestor( + refNode, + a => !isQualifiedName(a.parent) && !isTypeNode(a.parent) && !isTypeElement(a.parent), + )!; const typeHavingNode = typeNode.parent; - if (hasType(typeHavingNode) && typeHavingNode.type === typeNode && state.markSeenContainingTypeReference(typeHavingNode)) { + if ( + hasType(typeHavingNode) && typeHavingNode.type === typeNode + && state.markSeenContainingTypeReference(typeHavingNode) + ) { if (hasInitializer(typeHavingNode)) { addIfImplementation(typeHavingNode.initializer!); } @@ -2259,7 +2765,8 @@ export namespace Core { function getContainingNodeIfInHeritageClause(node: Node): ClassLikeDeclaration | InterfaceDeclaration | undefined { return isIdentifier(node) || isPropertyAccessExpression(node) ? getContainingNodeIfInHeritageClause(node.parent) - : isExpressionWithTypeArguments(node) ? tryCast(node.parent.parent, or(isClassLike, isInterfaceDeclaration)) : undefined; + : isExpressionWithTypeArguments(node) ? tryCast(node.parent.parent, or(isClassLike, isInterfaceDeclaration)) + : undefined; } /** @@ -2299,7 +2806,12 @@ export namespace Core { * @param parent Another class or interface Symbol * @param cachedResults A map of symbol id pairs (i.e. "child,parent") to booleans indicating previous results */ - function explicitlyInheritsFrom(symbol: Symbol, parent: Symbol, cachedResults: Map, checker: TypeChecker): boolean { + function explicitlyInheritsFrom( + symbol: Symbol, + parent: Symbol, + cachedResults: Map, + checker: TypeChecker, + ): boolean { if (symbol === parent) { return true; } @@ -2313,18 +2825,26 @@ export namespace Core { // Set the key so that we don't infinitely recurse cachedResults.set(key, false); - const inherits = !!symbol.declarations && symbol.declarations.some(declaration => - getAllSuperTypeNodes(declaration).some(typeReference => { - const type = checker.getTypeAtLocation(typeReference); - return !!type && !!type.symbol && explicitlyInheritsFrom(type.symbol, parent, cachedResults, checker); - }) - ); + const inherits = !!symbol.declarations + && symbol.declarations.some(declaration => + getAllSuperTypeNodes(declaration).some(typeReference => { + const type = checker.getTypeAtLocation(typeReference); + return !!type && !!type.symbol + && explicitlyInheritsFrom(type.symbol, parent, cachedResults, checker); + }) + ); cachedResults.set(key, inherits); return inherits; } function getReferencesForSuperKeyword(superKeyword: Node): SymbolAndEntries[] | undefined { - let searchSpaceNode: SuperContainer | ClassLikeDeclaration | TypeLiteralNode | InterfaceDeclaration | ObjectLiteralExpression | undefined = getSuperContainer(superKeyword, /*stopOnFunctions*/ false); + let searchSpaceNode: + | SuperContainer + | ClassLikeDeclaration + | TypeLiteralNode + | InterfaceDeclaration + | ObjectLiteralExpression + | undefined = getSuperContainer(superKeyword, /*stopOnFunctions*/ false); if (!searchSpaceNode) { return undefined; } @@ -2357,18 +2877,28 @@ export namespace Core { // If we have a 'super' container, we must have an enclosing class. // Now make sure the owning class is the same as the search-space // and has the same static qualifier as the original 'super's owner. - return container && isStatic(container) === !!staticFlag && container.parent.symbol === searchSpaceNode!.symbol ? nodeEntry(node) : undefined; + return container && isStatic(container) === !!staticFlag + && container.parent.symbol === searchSpaceNode!.symbol ? nodeEntry(node) : undefined; }); return [{ definition: { type: DefinitionKind.Symbol, symbol: searchSpaceNode.symbol }, references }]; } function isParameterName(node: Node) { - return node.kind === SyntaxKind.Identifier && node.parent.kind === SyntaxKind.Parameter && (node.parent as ParameterDeclaration).name === node; + return node.kind === SyntaxKind.Identifier && node.parent.kind === SyntaxKind.Parameter + && (node.parent as ParameterDeclaration).name === node; } - function getReferencesForThisKeyword(thisOrSuperKeyword: Node, sourceFiles: readonly SourceFile[], cancellationToken: CancellationToken): SymbolAndEntries[] | undefined { - let searchSpaceNode: Node = getThisContainer(thisOrSuperKeyword, /*includeArrowFunctions*/ false, /*includeClassComputedPropertyName*/ false); + function getReferencesForThisKeyword( + thisOrSuperKeyword: Node, + sourceFiles: readonly SourceFile[], + cancellationToken: CancellationToken, + ): SymbolAndEntries[] | undefined { + let searchSpaceNode: Node = getThisContainer( + thisOrSuperKeyword, + /*includeArrowFunctions*/ false, + /*includeClassComputedPropertyName*/ false, + ); // Whether 'this' occurs in a static context within a class. let staticFlag = ModifierFlags.Static; @@ -2404,32 +2934,49 @@ export namespace Core { return undefined; } - const references = flatMap(searchSpaceNode.kind === SyntaxKind.SourceFile ? sourceFiles : [searchSpaceNode.getSourceFile()], sourceFile => { - cancellationToken.throwIfCancellationRequested(); - return getPossibleSymbolReferenceNodes(sourceFile, "this", isSourceFile(searchSpaceNode) ? sourceFile : searchSpaceNode).filter(node => { - if (!isThis(node)) { - return false; - } - const container = getThisContainer(node, /*includeArrowFunctions*/ false, /*includeClassComputedPropertyName*/ false); - if (!canHaveSymbol(container)) return false; - switch (searchSpaceNode.kind) { - case SyntaxKind.FunctionExpression: - case SyntaxKind.FunctionDeclaration: - return (searchSpaceNode as FunctionExpression | FunctionDeclaration).symbol === container.symbol; - case SyntaxKind.MethodDeclaration: - case SyntaxKind.MethodSignature: - return isObjectLiteralMethod(searchSpaceNode) && searchSpaceNode.symbol === container.symbol; - case SyntaxKind.ClassExpression: - case SyntaxKind.ClassDeclaration: - case SyntaxKind.ObjectLiteralExpression: - // Make sure the container belongs to the same class/object literals - // and has the appropriate static modifier from the original container. - return container.parent && canHaveSymbol(container.parent) && (searchSpaceNode as ClassLikeDeclaration | ObjectLiteralExpression).symbol === container.parent.symbol && isStatic(container) === !!staticFlag; - case SyntaxKind.SourceFile: - return container.kind === SyntaxKind.SourceFile && !isExternalModule(container) && !isParameterName(node); - } - }); - }).map(n => nodeEntry(n)); + const references = flatMap( + searchSpaceNode.kind === SyntaxKind.SourceFile ? sourceFiles : [searchSpaceNode.getSourceFile()], + sourceFile => { + cancellationToken.throwIfCancellationRequested(); + return getPossibleSymbolReferenceNodes( + sourceFile, + "this", + isSourceFile(searchSpaceNode) ? sourceFile : searchSpaceNode, + ).filter(node => { + if (!isThis(node)) { + return false; + } + const container = getThisContainer( + node, + /*includeArrowFunctions*/ false, + /*includeClassComputedPropertyName*/ false, + ); + if (!canHaveSymbol(container)) return false; + switch (searchSpaceNode.kind) { + case SyntaxKind.FunctionExpression: + case SyntaxKind.FunctionDeclaration: + return (searchSpaceNode as FunctionExpression | FunctionDeclaration).symbol + === container.symbol; + case SyntaxKind.MethodDeclaration: + case SyntaxKind.MethodSignature: + return isObjectLiteralMethod(searchSpaceNode) + && searchSpaceNode.symbol === container.symbol; + case SyntaxKind.ClassExpression: + case SyntaxKind.ClassDeclaration: + case SyntaxKind.ObjectLiteralExpression: + // Make sure the container belongs to the same class/object literals + // and has the appropriate static modifier from the original container. + return container.parent && canHaveSymbol(container.parent) + && (searchSpaceNode as ClassLikeDeclaration | ObjectLiteralExpression).symbol + === container.parent.symbol + && isStatic(container) === !!staticFlag; + case SyntaxKind.SourceFile: + return container.kind === SyntaxKind.SourceFile && !isExternalModule(container) + && !isParameterName(node); + } + }); + }, + ).map(n => nodeEntry(n)); const thisParameter = firstDefined(references, r => isParameter(r.node.parent) ? r.node : undefined); return [{ @@ -2438,7 +2985,12 @@ export namespace Core { }]; } - function getReferencesForStringLiteral(node: StringLiteralLike, sourceFiles: readonly SourceFile[], checker: TypeChecker, cancellationToken: CancellationToken): SymbolAndEntries[] { + function getReferencesForStringLiteral( + node: StringLiteralLike, + sourceFiles: readonly SourceFile[], + checker: TypeChecker, + cancellationToken: CancellationToken, + ): SymbolAndEntries[] { const type = getContextualTypeFromParentOrAncestorTypeNode(node, checker); const references = flatMap(sourceFiles, sourceFile => { cancellationToken.throwIfCancellationRequested(); @@ -2451,8 +3003,8 @@ export namespace Core { } } else { - return isNoSubstitutionTemplateLiteral(ref) && !rangeIsOnSingleLine(ref, sourceFile) ? undefined : - nodeEntry(ref, EntryKind.StringLiteral); + return isNoSubstitutionTemplateLiteral(ref) && !rangeIsOnSingleLine(ref, sourceFile) ? undefined + : nodeEntry(ref, EntryKind.StringLiteral); } } }); @@ -2466,7 +3018,14 @@ export namespace Core { // For certain symbol kinds, we need to include other symbols in the search set. // This is not needed when searching for re-exports. - function populateSearchSymbolSet(symbol: Symbol, location: Node, checker: TypeChecker, isForRename: boolean, providePrefixAndSuffixText: boolean, implementations: boolean): Symbol[] { + function populateSearchSymbolSet( + symbol: Symbol, + location: Node, + checker: TypeChecker, + isForRename: boolean, + providePrefixAndSuffixText: boolean, + implementations: boolean, + ): Symbol[] { const result: Symbol[] = []; forEachRelatedSymbol( symbol, @@ -2519,7 +3078,12 @@ export namespace Core { const shorthandValueSymbol = checker.getShorthandAssignmentValueSymbol(location.parent); // gets the local symbol if (shorthandValueSymbol && isForRenamePopulateSearchSymbolSet) { // When renaming 'x' in `const o = { x }`, just rename the local variable, not the property. - return cbSymbol(shorthandValueSymbol, /*rootSymbol*/ undefined, /*baseSymbol*/ undefined, EntryKind.SearchedLocalFoundProperty); + return cbSymbol( + shorthandValueSymbol, + /*rootSymbol*/ undefined, + /*baseSymbol*/ undefined, + EntryKind.SearchedLocalFoundProperty, + ); } // If the location is in a context sensitive location (i.e. in an object literal) try @@ -2527,7 +3091,12 @@ export namespace Core { // type to the search set const contextualType = checker.getContextualType(containingObjectLiteralElement.parent); const res = contextualType && firstDefined( - getPropertySymbolsFromContextualType(containingObjectLiteralElement, checker, contextualType, /*unionSymbolOk*/ true), + getPropertySymbolsFromContextualType( + containingObjectLiteralElement, + checker, + contextualType, + /*unionSymbolOk*/ true, + ), sym => fromRoot(sym, EntryKind.SearchedPropertyFoundLocal), ); if (res) return res; @@ -2536,10 +3105,22 @@ export namespace Core { // Search the property symbol // for ( { property: p2 } of elems) { } const propertySymbol = getPropertySymbolOfDestructuringAssignment(location, checker); - const res1 = propertySymbol && cbSymbol(propertySymbol, /*rootSymbol*/ undefined, /*baseSymbol*/ undefined, EntryKind.SearchedPropertyFoundLocal); + const res1 = propertySymbol + && cbSymbol( + propertySymbol, + /*rootSymbol*/ undefined, + /*baseSymbol*/ undefined, + EntryKind.SearchedPropertyFoundLocal, + ); if (res1) return res1; - const res2 = shorthandValueSymbol && cbSymbol(shorthandValueSymbol, /*rootSymbol*/ undefined, /*baseSymbol*/ undefined, EntryKind.SearchedLocalFoundProperty); + const res2 = shorthandValueSymbol + && cbSymbol( + shorthandValueSymbol, + /*rootSymbol*/ undefined, + /*baseSymbol*/ undefined, + EntryKind.SearchedLocalFoundProperty, + ); if (res2) return res2; } @@ -2553,10 +3134,19 @@ export namespace Core { const res = fromRoot(symbol); if (res) return res; - if (symbol.valueDeclaration && isParameterPropertyDeclaration(symbol.valueDeclaration, symbol.valueDeclaration.parent)) { + if ( + symbol.valueDeclaration + && isParameterPropertyDeclaration(symbol.valueDeclaration, symbol.valueDeclaration.parent) + ) { // For a parameter property, now try on the other symbol (property if this was a parameter, parameter if this was a property). - const paramProps = checker.getSymbolsOfParameterPropertyDeclaration(cast(symbol.valueDeclaration, isParameter), symbol.name); - Debug.assert(paramProps.length === 2 && !!(paramProps[0].flags & SymbolFlags.FunctionScopedVariable) && !!(paramProps[1].flags & SymbolFlags.Property)); // is [parameter, property] + const paramProps = checker.getSymbolsOfParameterPropertyDeclaration( + cast(symbol.valueDeclaration, isParameter), + symbol.name, + ); + Debug.assert( + paramProps.length === 2 && !!(paramProps[0].flags & SymbolFlags.FunctionScopedVariable) + && !!(paramProps[1].flags & SymbolFlags.Property), + ); // is [parameter, property] return fromRoot(symbol.flags & SymbolFlags.FunctionScopedVariable ? paramProps[1] : paramProps[0]); } @@ -2574,12 +3164,17 @@ export namespace Core { if (!isForRenamePopulateSearchSymbolSet) { let bindingElementPropertySymbol: Symbol | undefined; if (onlyIncludeBindingElementAtReferenceLocation) { - bindingElementPropertySymbol = isObjectBindingElementWithoutPropertyName(location.parent) ? getPropertySymbolFromBindingElement(checker, location.parent) : undefined; + bindingElementPropertySymbol = isObjectBindingElementWithoutPropertyName(location.parent) + ? getPropertySymbolFromBindingElement(checker, location.parent) : undefined; } else { - bindingElementPropertySymbol = getPropertySymbolOfObjectBindingPatternWithoutPropertyName(symbol, checker); + bindingElementPropertySymbol = getPropertySymbolOfObjectBindingPatternWithoutPropertyName( + symbol, + checker, + ); } - return bindingElementPropertySymbol && fromRoot(bindingElementPropertySymbol, EntryKind.SearchedPropertyFoundLocal); + return bindingElementPropertySymbol + && fromRoot(bindingElementPropertySymbol, EntryKind.SearchedPropertyFoundLocal); } Debug.assert(isForRenamePopulateSearchSymbolSet); @@ -2588,8 +3183,12 @@ export namespace Core { const includeOriginalSymbolOfBindingElement = onlyIncludeBindingElementAtReferenceLocation; if (includeOriginalSymbolOfBindingElement) { - const bindingElementPropertySymbol = getPropertySymbolOfObjectBindingPatternWithoutPropertyName(symbol, checker); - return bindingElementPropertySymbol && fromRoot(bindingElementPropertySymbol, EntryKind.SearchedPropertyFoundLocal); + const bindingElementPropertySymbol = getPropertySymbolOfObjectBindingPatternWithoutPropertyName( + symbol, + checker, + ); + return bindingElementPropertySymbol + && fromRoot(bindingElementPropertySymbol, EntryKind.SearchedPropertyFoundLocal); } function fromRoot(sym: Symbol, kind?: NodeEntryKind): T | undefined { @@ -2599,15 +3198,27 @@ export namespace Core { // If the symbol is an instantiation from a another symbol (e.g. widened symbol): // - In populateSearchSymbolsSet, add the root the list // - In findRelatedSymbol, return the source symbol if that is in the search. (Do not return the instantiation symbol.) - return firstDefined(checker.getRootSymbols(sym), rootSymbol => - cbSymbol(sym, rootSymbol, /*baseSymbol*/ undefined, kind) - // Add symbol of properties/methods of the same name in base classes and implemented interfaces definitions - || (rootSymbol.parent && rootSymbol.parent.flags & (SymbolFlags.Class | SymbolFlags.Interface) && allowBaseTypes(rootSymbol) - ? getPropertySymbolsFromBaseTypes(rootSymbol.parent, rootSymbol.name, checker, base => cbSymbol(sym, rootSymbol, base, kind)) - : undefined)); + return firstDefined( + checker.getRootSymbols(sym), + rootSymbol => + cbSymbol(sym, rootSymbol, /*baseSymbol*/ undefined, kind) + // Add symbol of properties/methods of the same name in base classes and implemented interfaces definitions + || (rootSymbol.parent && rootSymbol.parent.flags & (SymbolFlags.Class | SymbolFlags.Interface) + && allowBaseTypes(rootSymbol) + ? getPropertySymbolsFromBaseTypes( + rootSymbol.parent, + rootSymbol.name, + checker, + base => cbSymbol(sym, rootSymbol, base, kind), + ) + : undefined), + ); } - function getPropertySymbolOfObjectBindingPatternWithoutPropertyName(symbol: Symbol, checker: TypeChecker): Symbol | undefined { + function getPropertySymbolOfObjectBindingPatternWithoutPropertyName( + symbol: Symbol, + checker: TypeChecker, + ): Symbol | undefined { const bindingElement = getDeclarationOfKind(symbol, SyntaxKind.BindingElement); if (bindingElement && isObjectBindingElementWithoutPropertyName(bindingElement)) { return getPropertySymbolFromBindingElement(checker, bindingElement); @@ -2623,7 +3234,12 @@ export namespace Core { * @param previousIterationSymbolsCache a cache of symbol from previous iterations of calling this function to prevent infinite revisiting of the same symbol. * The value of previousIterationSymbol is undefined when the function is first called. */ - function getPropertySymbolsFromBaseTypes(symbol: Symbol, propertyName: string, checker: TypeChecker, cb: (symbol: Symbol) => T | undefined): T | undefined { + function getPropertySymbolsFromBaseTypes( + symbol: Symbol, + propertyName: string, + checker: TypeChecker, + cb: (symbol: Symbol) => T | undefined, + ): T | undefined { const seen = new Map(); return recur(symbol); @@ -2632,15 +3248,21 @@ export namespace Core { // interface C extends C { // /*findRef*/propName: string; // } - if (!(symbol.flags & (SymbolFlags.Class | SymbolFlags.Interface)) || !addToSeen(seen, getSymbolId(symbol))) return; - - return firstDefined(symbol.declarations, declaration => - firstDefined(getAllSuperTypeNodes(declaration), typeReference => { - const type = checker.getTypeAtLocation(typeReference); - const propertySymbol = type && type.symbol && checker.getPropertyOfType(type, propertyName); - // Visit the typeReference as well to see if it directly or indirectly uses that property - return type && propertySymbol && (firstDefined(checker.getRootSymbols(propertySymbol), cb) || recur(type.symbol)); - })); + if ( + !(symbol.flags & (SymbolFlags.Class | SymbolFlags.Interface)) || !addToSeen(seen, getSymbolId(symbol)) + ) return; + + return firstDefined( + symbol.declarations, + declaration => + firstDefined(getAllSuperTypeNodes(declaration), typeReference => { + const type = checker.getTypeAtLocation(typeReference); + const propertySymbol = type && type.symbol && checker.getPropertyOfType(type, propertyName); + // Visit the typeReference as well to see if it directly or indirectly uses that property + return type && propertySymbol + && (firstDefined(checker.getRootSymbols(propertySymbol), cb) || recur(type.symbol)); + }), + ); } } @@ -2655,21 +3277,39 @@ export namespace Core { return !!(modifierFlags & ModifierFlags.Static); } - function getRelatedSymbol(search: Search, referenceSymbol: Symbol, referenceLocation: Node, state: State): RelatedSymbol | undefined { + function getRelatedSymbol( + search: Search, + referenceSymbol: Symbol, + referenceLocation: Node, + state: State, + ): RelatedSymbol | undefined { const { checker } = state; - return forEachRelatedSymbol(referenceSymbol, referenceLocation, checker, /*isForRenamePopulateSearchSymbolSet*/ false, /*onlyIncludeBindingElementAtReferenceLocation*/ state.options.use !== FindReferencesUse.Rename || !!state.options.providePrefixAndSuffixTextForRename, (sym, rootSymbol, baseSymbol, kind): RelatedSymbol | undefined => { - // check whether the symbol used to search itself is just the searched one. - if (baseSymbol) { - // static method/property and instance method/property might have the same name. Only check static or only check instance. - if (isStaticSymbol(referenceSymbol) !== isStaticSymbol(baseSymbol)) { - baseSymbol = undefined; + return forEachRelatedSymbol( + referenceSymbol, + referenceLocation, + checker, + /*isForRenamePopulateSearchSymbolSet*/ false, + /*onlyIncludeBindingElementAtReferenceLocation*/ state.options.use !== FindReferencesUse.Rename + || !!state.options.providePrefixAndSuffixTextForRename, + (sym, rootSymbol, baseSymbol, kind): RelatedSymbol | undefined => { + // check whether the symbol used to search itself is just the searched one. + if (baseSymbol) { + // static method/property and instance method/property might have the same name. Only check static or only check instance. + if (isStaticSymbol(referenceSymbol) !== isStaticSymbol(baseSymbol)) { + baseSymbol = undefined; + } } - } - return search.includes(baseSymbol || rootSymbol || sym) - // For a base type, use the symbol for the derived type. For a synthetic (e.g. union) property, use the union symbol. - ? { symbol: rootSymbol && !(getCheckFlags(sym) & CheckFlags.Synthetic) ? rootSymbol : sym, kind } - : undefined; - }, /*allowBaseTypes*/ rootSymbol => !(search.parents && !search.parents.some(parent => explicitlyInheritsFrom(rootSymbol.parent!, parent, state.inheritsFromCache, checker)))); + return search.includes(baseSymbol || rootSymbol || sym) + // For a base type, use the symbol for the derived type. For a synthetic (e.g. union) property, use the union symbol. + ? { symbol: rootSymbol && !(getCheckFlags(sym) & CheckFlags.Synthetic) ? rootSymbol : sym, kind } + : undefined; + }, + /*allowBaseTypes*/ rootSymbol => + !(search.parents + && !search.parents.some(parent => + explicitlyInheritsFrom(rootSymbol.parent!, parent, state.inheritsFromCache, checker) + )), + ); } /** @@ -2708,13 +3348,17 @@ export namespace Core { } function isImplementation(node: Node): boolean { - return !!(node.flags & NodeFlags.Ambient) ? !(isInterfaceDeclaration(node) || isTypeAliasDeclaration(node)) : - (isVariableLike(node) ? hasInitializer(node) : - isFunctionLikeDeclaration(node) ? !!node.body : - isClassLike(node) || isModuleOrEnumDeclaration(node)); + return !!(node.flags & NodeFlags.Ambient) ? !(isInterfaceDeclaration(node) || isTypeAliasDeclaration(node)) + : (isVariableLike(node) ? hasInitializer(node) + : isFunctionLikeDeclaration(node) ? !!node.body + : isClassLike(node) || isModuleOrEnumDeclaration(node)); } - export function getReferenceEntriesForShorthandPropertyAssignment(node: Node, checker: TypeChecker, addReference: (node: Node) => void): void { + export function getReferenceEntriesForShorthandPropertyAssignment( + node: Node, + checker: TypeChecker, + addReference: (node: Node) => void, + ): void { const refSymbol = checker.getSymbolAtLocation(node)!; const shorthandSymbol = checker.getShorthandAssignmentValueSymbol(refSymbol.valueDeclaration); @@ -2747,10 +3391,20 @@ export namespace Core { * symbol may have a different parent symbol if the local type's symbol does not declare the property * being accessed (i.e. it is declared in some parent class or interface) */ - function getParentSymbolsOfPropertyAccess(location: Node, symbol: Symbol, checker: TypeChecker): readonly Symbol[] | undefined { - const propertyAccessExpression = isRightSideOfPropertyAccess(location) ? location.parent as PropertyAccessExpression : undefined; + function getParentSymbolsOfPropertyAccess( + location: Node, + symbol: Symbol, + checker: TypeChecker, + ): readonly Symbol[] | undefined { + const propertyAccessExpression = isRightSideOfPropertyAccess(location) + ? location.parent as PropertyAccessExpression : undefined; const lhsType = propertyAccessExpression && checker.getTypeAtLocation(propertyAccessExpression.expression); - const res = mapDefined(lhsType && (lhsType.isUnionOrIntersection() ? lhsType.types : lhsType.symbol === symbol.parent ? undefined : [lhsType]), t => t.symbol && t.symbol.flags & (SymbolFlags.Class | SymbolFlags.Interface) ? t.symbol : undefined); + const res = mapDefined( + lhsType + && (lhsType.isUnionOrIntersection() ? lhsType.types + : lhsType.symbol === symbol.parent ? undefined : [lhsType]), + t => t.symbol && t.symbol.flags & (SymbolFlags.Class | SymbolFlags.Interface) ? t.symbol : undefined, + ); return res.length === 0 ? undefined : res; } diff --git a/src/services/formatting/formatting.ts b/src/services/formatting/formatting.ts index 474af54946f32..846cc4be16fc6 100644 --- a/src/services/formatting/formatting.ts +++ b/src/services/formatting/formatting.ts @@ -187,13 +187,26 @@ export function formatOnEnter(position: number, sourceFile: SourceFile, formatCo } /** @internal */ -export function formatOnSemicolon(position: number, sourceFile: SourceFile, formatContext: FormatContext): TextChange[] { +export function formatOnSemicolon( + position: number, + sourceFile: SourceFile, + formatContext: FormatContext, +): TextChange[] { const semicolon = findImmediatelyPrecedingTokenOfKind(position, SyntaxKind.SemicolonToken, sourceFile); - return formatNodeLines(findOutermostNodeWithinListLevel(semicolon), sourceFile, formatContext, FormattingRequestKind.FormatOnSemicolon); + return formatNodeLines( + findOutermostNodeWithinListLevel(semicolon), + sourceFile, + formatContext, + FormattingRequestKind.FormatOnSemicolon, + ); } /** @internal */ -export function formatOnOpeningCurly(position: number, sourceFile: SourceFile, formatContext: FormatContext): TextChange[] { +export function formatOnOpeningCurly( + position: number, + sourceFile: SourceFile, + formatContext: FormatContext, +): TextChange[] { const openingCurly = findImmediatelyPrecedingTokenOfKind(position, SyntaxKind.OpenBraceToken, sourceFile); if (!openingCurly) { return []; @@ -222,9 +235,18 @@ export function formatOnOpeningCurly(position: number, sourceFile: SourceFile, f } /** @internal */ -export function formatOnClosingCurly(position: number, sourceFile: SourceFile, formatContext: FormatContext): TextChange[] { +export function formatOnClosingCurly( + position: number, + sourceFile: SourceFile, + formatContext: FormatContext, +): TextChange[] { const precedingToken = findImmediatelyPrecedingTokenOfKind(position, SyntaxKind.CloseBraceToken, sourceFile); - return formatNodeLines(findOutermostNodeWithinListLevel(precedingToken), sourceFile, formatContext, FormattingRequestKind.FormatOnClosingCurlyBrace); + return formatNodeLines( + findOutermostNodeWithinListLevel(precedingToken), + sourceFile, + formatContext, + FormattingRequestKind.FormatOnClosingCurlyBrace, + ); } /** @internal */ @@ -237,7 +259,12 @@ export function formatDocument(sourceFile: SourceFile, formatContext: FormatCont } /** @internal */ -export function formatSelection(start: number, end: number, sourceFile: SourceFile, formatContext: FormatContext): TextChange[] { +export function formatSelection( + start: number, + end: number, + sourceFile: SourceFile, + formatContext: FormatContext, +): TextChange[] { // format from the beginning of the line const span = { pos: getLineStartPositionForPosition(start, sourceFile), @@ -250,12 +277,16 @@ export function formatSelection(start: number, end: number, sourceFile: SourceFi * Validating `expectedTokenKind` ensures the token was typed in the context we expect (eg: not a comment). * @param expectedTokenKind The kind of the last token constituting the desired parent node. */ -function findImmediatelyPrecedingTokenOfKind(end: number, expectedTokenKind: SyntaxKind, sourceFile: SourceFile): Node | undefined { +function findImmediatelyPrecedingTokenOfKind( + end: number, + expectedTokenKind: SyntaxKind, + sourceFile: SourceFile, +): Node | undefined { const precedingToken = findPrecedingToken(end, sourceFile); - return precedingToken && precedingToken.kind === expectedTokenKind && end === precedingToken.getEnd() ? - precedingToken : - undefined; + return precedingToken && precedingToken.kind === expectedTokenKind && end === precedingToken.getEnd() + ? precedingToken + : undefined; } /** @@ -274,10 +305,10 @@ function findImmediatelyPrecedingTokenOfKind(end: number, expectedTokenKind: Syn function findOutermostNodeWithinListLevel(node: Node | undefined) { let current = node; while ( - current && - current.parent && - current.parent.end === node!.end && - !isListElement(current.parent, current) + current + && current.parent + && current.parent.end === node!.end + && !isListElement(current.parent, current) ) { current = current.parent; } @@ -327,7 +358,10 @@ function findEnclosingNode(range: TextRange, sourceFile: SourceFile): Node { * This function will return a predicate that for a given text range will tell * if there are any parse errors that overlap with the range. */ -function prepareRangeContainsErrorFunction(errors: readonly Diagnostic[], originalRange: TextRange): (r: TextRange) => boolean { +function prepareRangeContainsErrorFunction( + errors: readonly Diagnostic[], + originalRange: TextRange, +): (r: TextRange) => boolean { if (!errors.length) { return rangeHasNoErrors; } @@ -434,7 +468,14 @@ function getOwnOrInheritedDelta(n: Node, options: FormatCodeSettings, sourceFile } /** @internal */ -export function formatNodeGivenIndentation(node: Node, sourceFileLike: SourceFileLike, languageVariant: LanguageVariant, initialIndentation: number, delta: number, formatContext: FormatContext): TextChange[] { +export function formatNodeGivenIndentation( + node: Node, + sourceFileLike: SourceFileLike, + languageVariant: LanguageVariant, + initialIndentation: number, + delta: number, + formatContext: FormatContext, +): TextChange[] { const range = { pos: node.pos, end: node.end }; return getFormattingScanner(sourceFileLike.text, languageVariant, range.pos, range.end, scanner => formatSpanWorker( @@ -450,7 +491,12 @@ export function formatNodeGivenIndentation(node: Node, sourceFileLike: SourceFil )); } -function formatNodeLines(node: Node | undefined, sourceFile: SourceFile, formatContext: FormatContext, requestKind: FormattingRequestKind): TextChange[] { +function formatNodeLines( + node: Node | undefined, + sourceFile: SourceFile, + formatContext: FormatContext, + requestKind: FormattingRequestKind, +): TextChange[] { if (!node) { return []; } @@ -463,7 +509,12 @@ function formatNodeLines(node: Node | undefined, sourceFile: SourceFile, formatC return formatSpan(span, sourceFile, formatContext, requestKind); } -function formatSpan(originalRange: TextRange, sourceFile: SourceFile, formatContext: FormatContext, requestKind: FormattingRequestKind): TextChange[] { +function formatSpan( + originalRange: TextRange, + sourceFile: SourceFile, + formatContext: FormatContext, + requestKind: FormattingRequestKind, +): TextChange[] { // find the smallest node that fully wraps the range and compute the initial indentation for the node const enclosingNode = findEnclosingNode(originalRange, sourceFile); return getFormattingScanner( @@ -515,7 +566,8 @@ function formatSpanWorker( const startLine = sourceFile.getLineAndCharacterOfPosition(enclosingNode.getStart(sourceFile)).line; let undecoratedStartLine = startLine; if (hasDecorators(enclosingNode)) { - undecoratedStartLine = sourceFile.getLineAndCharacterOfPosition(getNonDecoratorTokenPosOfNode(enclosingNode, sourceFile)).line; + undecoratedStartLine = + sourceFile.getLineAndCharacterOfPosition(getNonDecoratorTokenPosOfNode(enclosingNode, sourceFile)).line; } processNode(enclosingNode, enclosingNode, startLine, undecoratedStartLine, initialIndentation, delta); @@ -526,11 +578,23 @@ function formatSpanWorker( // range and thus won't get processed. So we process those remaining trivia items here. const remainingTrivia = formattingScanner.getCurrentLeadingTrivia(); if (remainingTrivia) { - const indentation = SmartIndenter.nodeWillIndentChild(options, enclosingNode, /*child*/ undefined, sourceFile, /*indentByDefault*/ false) + const indentation = SmartIndenter.nodeWillIndentChild( + options, + enclosingNode, + /*child*/ undefined, + sourceFile, + /*indentByDefault*/ false, + ) ? initialIndentation + options.indentSize! : initialIndentation; indentTriviaItems(remainingTrivia, indentation, /*indentNextTokenOrTrivia*/ true, item => { - processRange(item, sourceFile.getLineAndCharacterOfPosition(item.pos), enclosingNode, enclosingNode, /*dynamicIndentation*/ undefined!); + processRange( + item, + sourceFile.getLineAndCharacterOfPosition(item.pos), + enclosingNode, + enclosingNode, + /*dynamicIndentation*/ undefined!, + ); insertIndentation(item.pos, indentation, /*lineAdded*/ false); }); if (options.trimTrailingWhitespace !== false) { @@ -549,9 +613,9 @@ function formatSpanWorker( // inclusive. We would expect a format-selection would delete the space (if rules apply), // but in order to do that, we need to process the pair ["{", "}"], but we stopped processing // just before getting there. This block handles this trailing edit. - const tokenInfo = formattingScanner.isOnEOF() ? formattingScanner.readEOFTokenRange() : - formattingScanner.isOnToken() ? formattingScanner.readTokenInfo(enclosingNode).token : - undefined; + const tokenInfo = formattingScanner.isOnEOF() ? formattingScanner.readEOFTokenRange() + : formattingScanner.isOnToken() ? formattingScanner.readTokenInfo(enclosingNode).token + : undefined; if (tokenInfo && tokenInfo.pos === previousRangeTriviaEnd!) { // We need to check that tokenInfo and previousRange are contiguous: the `originalRange` @@ -589,10 +653,16 @@ function formatSpanWorker( * If list element is in the range - its indentation will be equal * to inherited indentation from its predecessors. */ - function tryComputeIndentationForListItem(startPos: number, endPos: number, parentStartLine: number, range: TextRange, inheritedIndentation: number): number { + function tryComputeIndentationForListItem( + startPos: number, + endPos: number, + parentStartLine: number, + range: TextRange, + inheritedIndentation: number, + ): number { if ( - rangeOverlapsWithStartEnd(range, startPos, endPos) || - rangeContainsStartEnd(range, startPos, endPos) /* Not to miss zero-range nodes e.g. JsxText */ + rangeOverlapsWithStartEnd(range, startPos, endPos) + || rangeContainsStartEnd(range, startPos, endPos) /* Not to miss zero-range nodes e.g. JsxText */ ) { if (inheritedIndentation !== Constants.Unknown) { return inheritedIndentation; @@ -628,7 +698,8 @@ function formatSpanWorker( // - inherit indentation from the parent // - push children if either parent of node itself has non-zero delta return { - indentation: startLine === lastIndentedLine ? indentationOnLastIndentedLine : parentDynamicIndentation.getIndentation(), + indentation: startLine === lastIndentedLine ? indentationOnLastIndentedLine + : parentDynamicIndentation.getIndentation(), delta: Math.min(options.indentSize!, parentDynamicIndentation.getDelta(node) + delta), }; } @@ -639,14 +710,17 @@ function formatSpanWorker( return { indentation: indentationOnLastIndentedLine, delta: parentDynamicIndentation.getDelta(node) }; } else if ( - SmartIndenter.childStartsOnTheSameLineWithElseInIfStatement(parent, node, startLine, sourceFile) || - SmartIndenter.childIsUnindentedBranchOfConditionalExpression(parent, node, startLine, sourceFile) || - SmartIndenter.argumentStartsOnSameLineAsPreviousArgument(parent, node, startLine, sourceFile) + SmartIndenter.childStartsOnTheSameLineWithElseInIfStatement(parent, node, startLine, sourceFile) + || SmartIndenter.childIsUnindentedBranchOfConditionalExpression(parent, node, startLine, sourceFile) + || SmartIndenter.argumentStartsOnSameLineAsPreviousArgument(parent, node, startLine, sourceFile) ) { return { indentation: parentDynamicIndentation.getIndentation(), delta }; } else { - return { indentation: parentDynamicIndentation.getIndentation() + parentDynamicIndentation.getDelta(node), delta }; + return { + indentation: parentDynamicIndentation.getIndentation() + parentDynamicIndentation.getDelta(node), + delta, + }; } } else { @@ -688,7 +762,12 @@ function formatSpanWorker( } } - function getDynamicIndentation(node: Node, nodeStartLine: number, indentation: number, delta: number): DynamicIndentation { + function getDynamicIndentation( + node: Node, + nodeStartLine: number, + indentation: number, + delta: number, + ): DynamicIndentation { return { getIndentationForComment: (kind, tokenIndentation, container) => { switch (kind) { @@ -713,7 +792,9 @@ function formatSpanWorker( // vs // var a = xValue // > yValue; - getIndentationForToken: (line, kind, container, suppressDelta) => !suppressDelta && shouldAddDelta(line, kind, container) ? indentation + getDelta(container) : indentation, + getIndentationForToken: (line, kind, container, suppressDelta) => + !suppressDelta && shouldAddDelta(line, kind, container) ? indentation + getDelta(container) + : indentation, getIndentation: () => indentation, getDelta, recomputeIndentation: (lineAdded, parent) => { @@ -758,11 +839,19 @@ function formatSpanWorker( function getDelta(child: TextRangeWithKind) { // Delta value should be zero when the node explicitly prevents indentation of the child node - return SmartIndenter.nodeWillIndentChild(options, node, child, sourceFile, /*indentByDefault*/ true) ? delta : 0; + return SmartIndenter.nodeWillIndentChild(options, node, child, sourceFile, /*indentByDefault*/ true) ? delta + : 0; } } - function processNode(node: Node, contextNode: Node, nodeStartLine: number, undecoratedNodeStartLine: number, indentation: number, delta: number) { + function processNode( + node: Node, + contextNode: Node, + nodeStartLine: number, + undecoratedNodeStartLine: number, + indentation: number, + delta: number, + ) { if (!rangeOverlapsWithStartEnd(originalRange, node.getStart(sourceFile), node.getEnd())) { return; } @@ -788,7 +877,15 @@ function formatSpanWorker( forEachChild( node, child => { - processChildNode(child, /*inheritedIndentation*/ Constants.Unknown, node, nodeDynamicIndentation, nodeStartLine, undecoratedNodeStartLine, /*isListItem*/ false); + processChildNode( + child, + /*inheritedIndentation*/ Constants.Unknown, + node, + nodeDynamicIndentation, + nodeStartLine, + undecoratedNodeStartLine, + /*isListItem*/ false, + ); }, nodes => { processChildNodes(nodes, node, nodeStartLine, nodeDynamicIndentation); @@ -826,14 +923,21 @@ function formatSpanWorker( let undecoratedChildStartLine = childStartLine; if (hasDecorators(child)) { - undecoratedChildStartLine = sourceFile.getLineAndCharacterOfPosition(getNonDecoratorTokenPosOfNode(child, sourceFile)).line; + undecoratedChildStartLine = + sourceFile.getLineAndCharacterOfPosition(getNonDecoratorTokenPosOfNode(child, sourceFile)).line; } // if child is a list item - try to get its indentation, only if parent is within the original range. let childIndentationAmount = Constants.Unknown; if (isListItem && rangeContainsRange(originalRange, parent)) { - childIndentationAmount = tryComputeIndentationForListItem(childStartPos, child.end, parentStartLine, originalRange, inheritedIndentation); + childIndentationAmount = tryComputeIndentationForListItem( + childStartPos, + child.end, + parentStartLine, + originalRange, + inheritedIndentation, + ); if (childIndentationAmount !== Constants.Unknown) { inheritedIndentation = childIndentationAmount; } @@ -883,21 +987,44 @@ function formatSpanWorker( } } - const effectiveParentStartLine = child.kind === SyntaxKind.Decorator ? childStartLine : undecoratedParentStartLine; - const childIndentation = computeIndentation(child, childStartLine, childIndentationAmount, node, parentDynamicIndentation, effectiveParentStartLine); + const effectiveParentStartLine = child.kind === SyntaxKind.Decorator ? childStartLine + : undecoratedParentStartLine; + const childIndentation = computeIndentation( + child, + childStartLine, + childIndentationAmount, + node, + parentDynamicIndentation, + effectiveParentStartLine, + ); - processNode(child, childContextNode, childStartLine, undecoratedChildStartLine, childIndentation.indentation, childIndentation.delta); + processNode( + child, + childContextNode, + childStartLine, + undecoratedChildStartLine, + childIndentation.indentation, + childIndentation.delta, + ); childContextNode = node; - if (isFirstListItem && parent.kind === SyntaxKind.ArrayLiteralExpression && inheritedIndentation === Constants.Unknown) { + if ( + isFirstListItem && parent.kind === SyntaxKind.ArrayLiteralExpression + && inheritedIndentation === Constants.Unknown + ) { inheritedIndentation = childIndentation.indentation; } return inheritedIndentation; } - function processChildNodes(nodes: NodeArray, parent: Node, parentStartLine: number, parentDynamicIndentation: DynamicIndentation): void { + function processChildNodes( + nodes: NodeArray, + parent: Node, + parentStartLine: number, + parentDynamicIndentation: DynamicIndentation, + ): void { Debug.assert(isNodeArray(nodes)); Debug.assert(!nodeIsSynthesized(nodes)); @@ -937,10 +1064,20 @@ function formatSpanWorker( } else { const startLinePosition = getLineStartPositionForPosition(tokenInfo.token.pos, sourceFile); - indentationOnListStartToken = SmartIndenter.findFirstNonWhitespaceColumn(startLinePosition, tokenInfo.token.pos, sourceFile, options); + indentationOnListStartToken = SmartIndenter.findFirstNonWhitespaceColumn( + startLinePosition, + tokenInfo.token.pos, + sourceFile, + options, + ); } - listDynamicIndentation = getDynamicIndentation(parent, parentStartLine, indentationOnListStartToken, options.indentSize!); // TODO: GH#18217 + listDynamicIndentation = getDynamicIndentation( + parent, + parentStartLine, + indentationOnListStartToken, + options.indentSize!, + ); // TODO: GH#18217 } else { // consume any tokens that precede the list as child elements of 'node' using its indentation scope @@ -952,11 +1089,23 @@ function formatSpanWorker( let inheritedIndentation = Constants.Unknown; for (let i = 0; i < nodes.length; i++) { const child = nodes[i]; - inheritedIndentation = processChildNode(child, inheritedIndentation, node, listDynamicIndentation, startLine, startLine, /*isListItem*/ true, /*isFirstListItem*/ i === 0); + inheritedIndentation = processChildNode( + child, + inheritedIndentation, + node, + listDynamicIndentation, + startLine, + startLine, + /*isListItem*/ true, + /*isFirstListItem*/ i === 0, + ); } const listEndToken = getCloseTokenForOpenToken(listStartToken); - if (listEndToken !== SyntaxKind.Unknown && formattingScanner.isOnToken() && formattingScanner.getTokenFullStart() < originalRange.end) { + if ( + listEndToken !== SyntaxKind.Unknown && formattingScanner.isOnToken() + && formattingScanner.getTokenFullStart() < originalRange.end + ) { let tokenInfo: TokenInfo | undefined = formattingScanner.readTokenInfo(parent); if (tokenInfo.token.kind === SyntaxKind.CommaToken) { // consume the comma @@ -970,12 +1119,24 @@ function formatSpanWorker( // without this check close paren will be interpreted as list end token for function expression which is wrong if (tokenInfo && tokenInfo.token.kind === listEndToken && rangeContainsRange(parent, tokenInfo.token)) { // consume list end token - consumeTokenAndAdvanceScanner(tokenInfo, parent, listDynamicIndentation, parent, /*isListEndToken*/ true); + consumeTokenAndAdvanceScanner( + tokenInfo, + parent, + listDynamicIndentation, + parent, + /*isListEndToken*/ true, + ); } } } - function consumeTokenAndAdvanceScanner(currentTokenInfo: TokenInfo, parent: Node, dynamicIndentation: DynamicIndentation, container: Node, isListEndToken?: boolean): void { + function consumeTokenAndAdvanceScanner( + currentTokenInfo: TokenInfo, + parent: Node, + dynamicIndentation: DynamicIndentation, + container: Node, + isListEndToken?: boolean, + ): void { Debug.assert(rangeContainsRange(parent, currentTokenInfo.token)); const lastTriviaWasNewLine = formattingScanner.lastTrailingTriviaWasNewLine(); @@ -993,12 +1154,19 @@ function formatSpanWorker( const rangeHasError = rangeContainsError(currentTokenInfo.token); // save previousRange since processRange will overwrite this value with current one const savePreviousRange = previousRange; - lineAction = processRange(currentTokenInfo.token, tokenStart, parent, childContextNode, dynamicIndentation); + lineAction = processRange( + currentTokenInfo.token, + tokenStart, + parent, + childContextNode, + dynamicIndentation, + ); // do not indent comments\token if token range overlaps with some error if (!rangeHasError) { if (lineAction === LineAction.None) { // indent token only if end line of previous range does not match start line of the token - const prevEndLine = savePreviousRange && sourceFile.getLineAndCharacterOfPosition(savePreviousRange.end).line; + const prevEndLine = savePreviousRange + && sourceFile.getLineAndCharacterOfPosition(savePreviousRange.end).line; indentToken = lastTriviaWasNewLine && tokenStart.line !== prevEndLine; } else { @@ -1013,19 +1181,37 @@ function formatSpanWorker( } if (indentToken) { - const tokenIndentation = (isTokenInRange && !rangeContainsError(currentTokenInfo.token)) ? - dynamicIndentation.getIndentationForToken(tokenStart.line, currentTokenInfo.token.kind, container, !!isListEndToken) : - Constants.Unknown; + const tokenIndentation = (isTokenInRange && !rangeContainsError(currentTokenInfo.token)) + ? dynamicIndentation.getIndentationForToken( + tokenStart.line, + currentTokenInfo.token.kind, + container, + !!isListEndToken, + ) + : Constants.Unknown; let indentNextTokenOrTrivia = true; if (currentTokenInfo.leadingTrivia) { - const commentIndentation = dynamicIndentation.getIndentationForComment(currentTokenInfo.token.kind, tokenIndentation, container); - indentNextTokenOrTrivia = indentTriviaItems(currentTokenInfo.leadingTrivia, commentIndentation, indentNextTokenOrTrivia, item => insertIndentation(item.pos, commentIndentation, /*lineAdded*/ false)); + const commentIndentation = dynamicIndentation.getIndentationForComment( + currentTokenInfo.token.kind, + tokenIndentation, + container, + ); + indentNextTokenOrTrivia = indentTriviaItems( + currentTokenInfo.leadingTrivia, + commentIndentation, + indentNextTokenOrTrivia, + item => insertIndentation(item.pos, commentIndentation, /*lineAdded*/ false), + ); } // indent token only if is it is in target range and does not overlap with any error ranges if (tokenIndentation !== Constants.Unknown && indentNextTokenOrTrivia) { - insertIndentation(currentTokenInfo.token.pos, tokenIndentation, lineAction === LineAction.LineAdded); + insertIndentation( + currentTokenInfo.token.pos, + tokenIndentation, + lineAction === LineAction.LineAdded, + ); lastIndentedLine = tokenStart.line; indentationOnLastIndentedLine = tokenIndentation; @@ -1049,7 +1235,11 @@ function formatSpanWorker( switch (triviaItem.kind) { case SyntaxKind.MultiLineCommentTrivia: if (triviaInRange) { - indentMultilineComment(triviaItem, commentIndentation, /*firstLineIsIndented*/ !indentNextTokenOrTrivia); + indentMultilineComment( + triviaItem, + commentIndentation, + /*firstLineIsIndented*/ !indentNextTokenOrTrivia, + ); } indentNextTokenOrTrivia = false; break; @@ -1067,7 +1257,12 @@ function formatSpanWorker( return indentNextTokenOrTrivia; } - function processTrivia(trivia: TextRangeWithKind[], parent: Node, contextNode: Node, dynamicIndentation: DynamicIndentation): void { + function processTrivia( + trivia: TextRangeWithKind[], + parent: Node, + contextNode: Node, + dynamicIndentation: DynamicIndentation, + ): void { for (const triviaItem of trivia) { if (isComment(triviaItem.kind) && rangeContainsRange(originalRange, triviaItem)) { const triviaItemStart = sourceFile.getLineAndCharacterOfPosition(triviaItem.pos); @@ -1076,7 +1271,13 @@ function formatSpanWorker( } } - function processRange(range: TextRangeWithKind, rangeStart: LineAndCharacter, parent: Node, contextNode: Node, dynamicIndentation: DynamicIndentation): LineAction { + function processRange( + range: TextRangeWithKind, + rangeStart: LineAndCharacter, + parent: Node, + contextNode: Node, + dynamicIndentation: DynamicIndentation, + ): LineAction { const rangeHasError = rangeContainsError(range); let lineAction = LineAction.None; if (!rangeHasError) { @@ -1086,7 +1287,16 @@ function formatSpanWorker( trimTrailingWhitespacesForLines(originalStart.line, rangeStart.line); } else { - lineAction = processPair(range, rangeStart.line, parent, previousRange, previousRangeStartLine, previousParent, contextNode, dynamicIndentation); + lineAction = processPair( + range, + rangeStart.line, + parent, + previousRange, + previousRangeStartLine, + previousParent, + contextNode, + dynamicIndentation, + ); } } @@ -1098,7 +1308,16 @@ function formatSpanWorker( return lineAction; } - function processPair(currentItem: TextRangeWithKind, currentStartLine: number, currentParent: Node, previousItem: TextRangeWithKind, previousStartLine: number, previousParent: Node, contextNode: Node, dynamicIndentation: DynamicIndentation | undefined): LineAction { + function processPair( + currentItem: TextRangeWithKind, + currentStartLine: number, + currentParent: Node, + previousItem: TextRangeWithKind, + previousStartLine: number, + previousParent: Node, + contextNode: Node, + dynamicIndentation: DynamicIndentation | undefined, + ): LineAction { formattingContext.updateContext(previousItem, previousParent, currentItem, currentParent, contextNode); const rules = getRules(formattingContext); @@ -1133,7 +1352,8 @@ function formatSpanWorker( } // We need to trim trailing whitespace between the tokens if they were on different lines, and no rule was applied to put them on the same line - trimTrailingWhitespaces = trimTrailingWhitespaces && !(rule.action & RuleAction.DeleteSpace) && rule.flags !== RuleFlags.CanDeleteNewLines; + trimTrailingWhitespaces = trimTrailingWhitespaces && !(rule.action & RuleAction.DeleteSpace) + && rule.flags !== RuleFlags.CanDeleteNewLines; }); } else { @@ -1158,7 +1378,10 @@ function formatSpanWorker( else { const tokenStart = sourceFile.getLineAndCharacterOfPosition(pos); const startLinePosition = getStartPositionOfLine(tokenStart.line, sourceFile); - if (indentation !== characterToColumn(startLinePosition, tokenStart.character) || indentationIsDifferent(indentationString, startLinePosition)) { + if ( + indentation !== characterToColumn(startLinePosition, tokenStart.character) + || indentationIsDifferent(indentationString, startLinePosition) + ) { recordReplace(startLinePosition, tokenStart.character, indentationString); } } @@ -1181,7 +1404,12 @@ function formatSpanWorker( return indentationString !== sourceFile.text.substr(startLinePosition, indentationString.length); } - function indentMultilineComment(commentRange: TextRange, indentation: number, firstLineIsIndented: boolean, indentFinalLine = true) { + function indentMultilineComment( + commentRange: TextRange, + indentation: number, + firstLineIsIndented: boolean, + indentFinalLine = true, + ) { // split comment in lines let startLine = sourceFile.getLineAndCharacterOfPosition(commentRange.pos).line; const endLine = sourceFile.getLineAndCharacterOfPosition(commentRange.end).line; @@ -1209,7 +1437,12 @@ function formatSpanWorker( const startLinePos = getStartPositionOfLine(startLine, sourceFile); - const nonWhitespaceColumnInFirstPart = SmartIndenter.findFirstNonWhitespaceCharacterAndColumn(startLinePos, parts[0].pos, sourceFile, options); + const nonWhitespaceColumnInFirstPart = SmartIndenter.findFirstNonWhitespaceCharacterAndColumn( + startLinePos, + parts[0].pos, + sourceFile, + options, + ); let startIndex = 0; if (firstLineIsIndented) { @@ -1223,7 +1456,12 @@ function formatSpanWorker( const startLinePos = getStartPositionOfLine(startLine, sourceFile); const nonWhitespaceCharacterAndColumn = i === 0 ? nonWhitespaceColumnInFirstPart - : SmartIndenter.findFirstNonWhitespaceCharacterAndColumn(parts[i].pos, parts[i].end, sourceFile, options); + : SmartIndenter.findFirstNonWhitespaceCharacterAndColumn( + parts[i].pos, + parts[i].end, + sourceFile, + options, + ); const newIndentation = nonWhitespaceCharacterAndColumn.column + delta; if (newIndentation > 0) { const indentationString = getIndentationString(newIndentation, options); @@ -1241,13 +1479,19 @@ function formatSpanWorker( const lineEndPosition = getEndLinePosition(line, sourceFile); // do not trim whitespaces in comments or template expression - if (range && (isComment(range.kind) || isStringOrRegularExpressionOrTemplateLiteral(range.kind)) && range.pos <= lineEndPosition && range.end > lineEndPosition) { + if ( + range && (isComment(range.kind) || isStringOrRegularExpressionOrTemplateLiteral(range.kind)) + && range.pos <= lineEndPosition && range.end > lineEndPosition + ) { continue; } const whitespaceStart = getTrailingWhitespaceStartPosition(lineStartPosition, lineEndPosition); if (whitespaceStart !== -1) { - Debug.assert(whitespaceStart === lineStartPosition || !isWhiteSpaceSingleLine(sourceFile.text.charCodeAt(whitespaceStart - 1))); + Debug.assert( + whitespaceStart === lineStartPosition + || !isWhiteSpaceSingleLine(sourceFile.text.charCodeAt(whitespaceStart - 1)), + ); recordDelete(whitespaceStart, lineEndPosition + 1 - whitespaceStart); } } @@ -1314,7 +1558,13 @@ function formatSpanWorker( } } - function applyRuleEdits(rule: Rule, previousRange: TextRangeWithKind, previousStartLine: number, currentRange: TextRangeWithKind, currentStartLine: number): LineAction { + function applyRuleEdits( + rule: Rule, + previousRange: TextRangeWithKind, + previousStartLine: number, + currentRange: TextRangeWithKind, + currentStartLine: number, + ): LineAction { const onLaterLine = currentStartLine !== previousStartLine; switch (rule.action) { case RuleAction.StopProcessingSpaceActions: @@ -1341,7 +1591,11 @@ function formatSpanWorker( // edit should not be applied if we have one line feed between elements const lineDelta = currentStartLine - previousStartLine; if (lineDelta !== 1) { - recordReplace(previousRange.end, currentRange.pos - previousRange.end, getNewLineOrDefaultFromHost(host, options)); + recordReplace( + previousRange.end, + currentRange.pos - previousRange.end, + getNewLineOrDefaultFromHost(host, options), + ); return onLaterLine ? LineAction.None : LineAction.LineAdded; } break; @@ -1387,15 +1641,17 @@ export function getRangeOfEnclosingComment( } // eslint-disable-next-line no-null/no-null - precedingToken = precedingToken === null ? undefined : precedingToken === undefined ? findPrecedingToken(position, sourceFile) : precedingToken; + precedingToken = precedingToken === null ? undefined + : precedingToken === undefined ? findPrecedingToken(position, sourceFile) : precedingToken; // Between two consecutive tokens, all comments are either trailing on the former // or leading on the latter (and none are in both lists). - const trailingRangesOfPreviousToken = precedingToken && getTrailingCommentRanges(sourceFile.text, precedingToken.end); + const trailingRangesOfPreviousToken = precedingToken + && getTrailingCommentRanges(sourceFile.text, precedingToken.end); const leadingCommentRangesOfNextToken = getLeadingCommentRangesOfNode(tokenAtPosition, sourceFile); const commentRanges = concatenate(trailingRangesOfPreviousToken, leadingCommentRangesOfNextToken); return commentRanges && find(commentRanges, range => - rangeContainsPositionExclusive(range, position) || + rangeContainsPositionExclusive(range, position) // The end marker of a single-line comment does not include the newline character. // With caret at `^`, in the following case, we are inside a comment (^ denotes the cursor position): // @@ -1409,7 +1665,8 @@ export function getRangeOfEnclosingComment( // // Internally, we represent the end of the comment at the newline and closing '/', respectively. // - position === range.end && (range.kind === SyntaxKind.SingleLineCommentTrivia || position === sourceFile.getFullWidth())); + || position === range.end + && (range.kind === SyntaxKind.SingleLineCommentTrivia || position === sourceFile.getFullWidth())); } function getOpenTokenForList(node: Node, list: readonly Node[]) { @@ -1486,7 +1743,8 @@ let internedSpacesIndentation: string[] | undefined; /** @internal */ export function getIndentationString(indentation: number, options: EditorSettings): string { // reset interned strings if FormatCodeOptions were changed - const resetInternedStrings = !internedSizes || (internedSizes.tabSize !== options.tabSize || internedSizes.indentSize !== options.indentSize); + const resetInternedStrings = !internedSizes + || (internedSizes.tabSize !== options.tabSize || internedSizes.indentSize !== options.indentSize); if (resetInternedStrings) { internedSizes = { tabSize: options.tabSize!, indentSize: options.indentSize! }; diff --git a/src/services/formatting/formattingContext.ts b/src/services/formatting/formattingContext.ts index 660f7199ba9eb..22d62f8d9aff8 100644 --- a/src/services/formatting/formattingContext.ts +++ b/src/services/formatting/formattingContext.ts @@ -34,10 +34,20 @@ export class FormattingContext { private contextNodeBlockIsOnOneLine: boolean | undefined; private nextNodeBlockIsOnOneLine: boolean | undefined; - constructor(public readonly sourceFile: SourceFileLike, public formattingRequestKind: FormattingRequestKind, public options: FormatCodeSettings) { + constructor( + public readonly sourceFile: SourceFileLike, + public formattingRequestKind: FormattingRequestKind, + public options: FormatCodeSettings, + ) { } - public updateContext(currentRange: TextRangeWithKind, currentTokenParent: Node, nextRange: TextRangeWithKind, nextTokenParent: Node, commonParent: Node) { + public updateContext( + currentRange: TextRangeWithKind, + currentTokenParent: Node, + nextRange: TextRangeWithKind, + nextTokenParent: Node, + commonParent: Node, + ) { this.currentTokenSpan = Debug.checkDefined(currentRange); this.currentTokenParent = Debug.checkDefined(currentTokenParent); this.nextTokenSpan = Debug.checkDefined(nextRange); diff --git a/src/services/formatting/formattingScanner.ts b/src/services/formatting/formattingScanner.ts index 78890ad3a29b3..b4000c6690081 100644 --- a/src/services/formatting/formattingScanner.ts +++ b/src/services/formatting/formattingScanner.ts @@ -52,7 +52,13 @@ const enum ScanAction { } /** @internal */ -export function getFormattingScanner(text: string, languageVariant: LanguageVariant, startPos: number, endPos: number, cb: (scanner: FormattingScanner) => T): T { +export function getFormattingScanner( + text: string, + languageVariant: LanguageVariant, + startPos: number, + endPos: number, + cb: (scanner: FormattingScanner) => T, +): T { const scanner = languageVariant === LanguageVariant.JSX ? jsxScanner : standardScanner; scanner.setText(text); @@ -161,8 +167,8 @@ export function getFormattingScanner(text: string, languageVariant: LanguageV } function shouldRescanTemplateToken(container: Node): boolean { - return container.kind === SyntaxKind.TemplateMiddle || - container.kind === SyntaxKind.TemplateTail; + return container.kind === SyntaxKind.TemplateMiddle + || container.kind === SyntaxKind.TemplateTail; } function shouldRescanJsxAttributeValue(node: Node): boolean { @@ -178,13 +184,13 @@ export function getFormattingScanner(text: string, languageVariant: LanguageV // normally scanner returns the smallest available token // check the kind of context node to determine if scanner should have more greedy behavior and consume more text. - const expectedScanAction = shouldRescanGreaterThanToken(n) ? ScanAction.RescanGreaterThanToken : - shouldRescanSlashToken(n) ? ScanAction.RescanSlashToken : - shouldRescanTemplateToken(n) ? ScanAction.RescanTemplateToken : - shouldRescanJsxIdentifier(n) ? ScanAction.RescanJsxIdentifier : - shouldRescanJsxText(n) ? ScanAction.RescanJsxText : - shouldRescanJsxAttributeValue(n) ? ScanAction.RescanJsxAttributeValue : - ScanAction.Scan; + const expectedScanAction = shouldRescanGreaterThanToken(n) ? ScanAction.RescanGreaterThanToken + : shouldRescanSlashToken(n) ? ScanAction.RescanSlashToken + : shouldRescanTemplateToken(n) ? ScanAction.RescanTemplateToken + : shouldRescanJsxIdentifier(n) ? ScanAction.RescanJsxIdentifier + : shouldRescanJsxText(n) ? ScanAction.RescanJsxText + : shouldRescanJsxAttributeValue(n) ? ScanAction.RescanJsxAttributeValue + : ScanAction.Scan; if (lastTokenInfo && expectedScanAction === lastScanAction) { // readTokenInfo was called before with the same expected scan action. diff --git a/src/services/formatting/rules.ts b/src/services/formatting/rules.ts index f57de9336d92e..e66d76a92e928 100644 --- a/src/services/formatting/rules.ts +++ b/src/services/formatting/rules.ts @@ -65,7 +65,12 @@ export function getAllRules(): RuleSpec[] { SyntaxKind.IsKeyword, SyntaxKind.SatisfiesKeyword, ]; - const unaryPrefixOperators = [SyntaxKind.PlusPlusToken, SyntaxKind.MinusMinusToken, SyntaxKind.TildeToken, SyntaxKind.ExclamationToken]; + const unaryPrefixOperators = [ + SyntaxKind.PlusPlusToken, + SyntaxKind.MinusMinusToken, + SyntaxKind.TildeToken, + SyntaxKind.ExclamationToken, + ]; const unaryPrefixExpressions = [ SyntaxKind.NumericLiteral, SyntaxKind.BigIntLiteral, @@ -76,10 +81,30 @@ export function getAllRules(): RuleSpec[] { SyntaxKind.ThisKeyword, SyntaxKind.NewKeyword, ]; - const unaryPreincrementExpressions = [SyntaxKind.Identifier, SyntaxKind.OpenParenToken, SyntaxKind.ThisKeyword, SyntaxKind.NewKeyword]; - const unaryPostincrementExpressions = [SyntaxKind.Identifier, SyntaxKind.CloseParenToken, SyntaxKind.CloseBracketToken, SyntaxKind.NewKeyword]; - const unaryPredecrementExpressions = [SyntaxKind.Identifier, SyntaxKind.OpenParenToken, SyntaxKind.ThisKeyword, SyntaxKind.NewKeyword]; - const unaryPostdecrementExpressions = [SyntaxKind.Identifier, SyntaxKind.CloseParenToken, SyntaxKind.CloseBracketToken, SyntaxKind.NewKeyword]; + const unaryPreincrementExpressions = [ + SyntaxKind.Identifier, + SyntaxKind.OpenParenToken, + SyntaxKind.ThisKeyword, + SyntaxKind.NewKeyword, + ]; + const unaryPostincrementExpressions = [ + SyntaxKind.Identifier, + SyntaxKind.CloseParenToken, + SyntaxKind.CloseBracketToken, + SyntaxKind.NewKeyword, + ]; + const unaryPredecrementExpressions = [ + SyntaxKind.Identifier, + SyntaxKind.OpenParenToken, + SyntaxKind.ThisKeyword, + SyntaxKind.NewKeyword, + ]; + const unaryPostdecrementExpressions = [ + SyntaxKind.Identifier, + SyntaxKind.CloseParenToken, + SyntaxKind.CloseBracketToken, + SyntaxKind.NewKeyword, + ]; const comments = [SyntaxKind.SingleLineCommentTrivia, SyntaxKind.MultiLineCommentTrivia]; const typeNames = [SyntaxKind.Identifier, ...typeKeywords]; @@ -88,113 +113,304 @@ export function getAllRules(): RuleSpec[] { const functionOpenBraceLeftTokenRange = anyTokenIncludingMultilineComments; // Place a space before open brace in a TypeScript declaration that has braces as children (class, module, enum, etc) - const typeScriptOpenBraceLeftTokenRange = tokenRangeFrom([SyntaxKind.Identifier, SyntaxKind.MultiLineCommentTrivia, SyntaxKind.ClassKeyword, SyntaxKind.ExportKeyword, SyntaxKind.ImportKeyword]); + const typeScriptOpenBraceLeftTokenRange = tokenRangeFrom([ + SyntaxKind.Identifier, + SyntaxKind.MultiLineCommentTrivia, + SyntaxKind.ClassKeyword, + SyntaxKind.ExportKeyword, + SyntaxKind.ImportKeyword, + ]); // Place a space before open brace in a control flow construct - const controlOpenBraceLeftTokenRange = tokenRangeFrom([SyntaxKind.CloseParenToken, SyntaxKind.MultiLineCommentTrivia, SyntaxKind.DoKeyword, SyntaxKind.TryKeyword, SyntaxKind.FinallyKeyword, SyntaxKind.ElseKeyword]); + const controlOpenBraceLeftTokenRange = tokenRangeFrom([ + SyntaxKind.CloseParenToken, + SyntaxKind.MultiLineCommentTrivia, + SyntaxKind.DoKeyword, + SyntaxKind.TryKeyword, + SyntaxKind.FinallyKeyword, + SyntaxKind.ElseKeyword, + ]); // These rules are higher in priority than user-configurable const highPriorityCommonRules = [ // Leave comments alone rule("IgnoreBeforeComment", anyToken, comments, anyContext, RuleAction.StopProcessingSpaceActions), - rule("IgnoreAfterLineComment", SyntaxKind.SingleLineCommentTrivia, anyToken, anyContext, RuleAction.StopProcessingSpaceActions), + rule( + "IgnoreAfterLineComment", + SyntaxKind.SingleLineCommentTrivia, + anyToken, + anyContext, + RuleAction.StopProcessingSpaceActions, + ), - rule("NotSpaceBeforeColon", anyToken, SyntaxKind.ColonToken, [isNonJsxSameLineTokenContext, isNotBinaryOpContext, isNotTypeAnnotationContext], RuleAction.DeleteSpace), - rule("SpaceAfterColon", SyntaxKind.ColonToken, anyToken, [isNonJsxSameLineTokenContext, isNotBinaryOpContext, isNextTokenParentNotJsxNamespacedName], RuleAction.InsertSpace), - rule("NoSpaceBeforeQuestionMark", anyToken, SyntaxKind.QuestionToken, [isNonJsxSameLineTokenContext, isNotBinaryOpContext, isNotTypeAnnotationContext], RuleAction.DeleteSpace), + rule("NotSpaceBeforeColon", anyToken, SyntaxKind.ColonToken, [ + isNonJsxSameLineTokenContext, + isNotBinaryOpContext, + isNotTypeAnnotationContext, + ], RuleAction.DeleteSpace), + rule("SpaceAfterColon", SyntaxKind.ColonToken, anyToken, [ + isNonJsxSameLineTokenContext, + isNotBinaryOpContext, + isNextTokenParentNotJsxNamespacedName, + ], RuleAction.InsertSpace), + rule("NoSpaceBeforeQuestionMark", anyToken, SyntaxKind.QuestionToken, [ + isNonJsxSameLineTokenContext, + isNotBinaryOpContext, + isNotTypeAnnotationContext, + ], RuleAction.DeleteSpace), // insert space after '?' only when it is used in conditional operator - rule("SpaceAfterQuestionMarkInConditionalOperator", SyntaxKind.QuestionToken, anyToken, [isNonJsxSameLineTokenContext, isConditionalOperatorContext], RuleAction.InsertSpace), + rule("SpaceAfterQuestionMarkInConditionalOperator", SyntaxKind.QuestionToken, anyToken, [ + isNonJsxSameLineTokenContext, + isConditionalOperatorContext, + ], RuleAction.InsertSpace), // in other cases there should be no space between '?' and next token - rule("NoSpaceAfterQuestionMark", SyntaxKind.QuestionToken, anyToken, [isNonJsxSameLineTokenContext], RuleAction.DeleteSpace), + rule( + "NoSpaceAfterQuestionMark", + SyntaxKind.QuestionToken, + anyToken, + [isNonJsxSameLineTokenContext], + RuleAction.DeleteSpace, + ), - rule("NoSpaceBeforeDot", anyToken, [SyntaxKind.DotToken, SyntaxKind.QuestionDotToken], [isNonJsxSameLineTokenContext, isNotPropertyAccessOnIntegerLiteral], RuleAction.DeleteSpace), - rule("NoSpaceAfterDot", [SyntaxKind.DotToken, SyntaxKind.QuestionDotToken], anyToken, [isNonJsxSameLineTokenContext], RuleAction.DeleteSpace), + rule("NoSpaceBeforeDot", anyToken, [SyntaxKind.DotToken, SyntaxKind.QuestionDotToken], [ + isNonJsxSameLineTokenContext, + isNotPropertyAccessOnIntegerLiteral, + ], RuleAction.DeleteSpace), + rule("NoSpaceAfterDot", [SyntaxKind.DotToken, SyntaxKind.QuestionDotToken], anyToken, [ + isNonJsxSameLineTokenContext, + ], RuleAction.DeleteSpace), - rule("NoSpaceBetweenImportParenInImportType", SyntaxKind.ImportKeyword, SyntaxKind.OpenParenToken, [isNonJsxSameLineTokenContext, isImportTypeContext], RuleAction.DeleteSpace), + rule("NoSpaceBetweenImportParenInImportType", SyntaxKind.ImportKeyword, SyntaxKind.OpenParenToken, [ + isNonJsxSameLineTokenContext, + isImportTypeContext, + ], RuleAction.DeleteSpace), // Special handling of unary operators. // Prefix operators generally shouldn't have a space between // them and their target unary expression. - rule("NoSpaceAfterUnaryPrefixOperator", unaryPrefixOperators, unaryPrefixExpressions, [isNonJsxSameLineTokenContext, isNotBinaryOpContext], RuleAction.DeleteSpace), - rule("NoSpaceAfterUnaryPreincrementOperator", SyntaxKind.PlusPlusToken, unaryPreincrementExpressions, [isNonJsxSameLineTokenContext], RuleAction.DeleteSpace), - rule("NoSpaceAfterUnaryPredecrementOperator", SyntaxKind.MinusMinusToken, unaryPredecrementExpressions, [isNonJsxSameLineTokenContext], RuleAction.DeleteSpace), - rule("NoSpaceBeforeUnaryPostincrementOperator", unaryPostincrementExpressions, SyntaxKind.PlusPlusToken, [isNonJsxSameLineTokenContext, isNotStatementConditionContext], RuleAction.DeleteSpace), - rule("NoSpaceBeforeUnaryPostdecrementOperator", unaryPostdecrementExpressions, SyntaxKind.MinusMinusToken, [isNonJsxSameLineTokenContext, isNotStatementConditionContext], RuleAction.DeleteSpace), + rule("NoSpaceAfterUnaryPrefixOperator", unaryPrefixOperators, unaryPrefixExpressions, [ + isNonJsxSameLineTokenContext, + isNotBinaryOpContext, + ], RuleAction.DeleteSpace), + rule("NoSpaceAfterUnaryPreincrementOperator", SyntaxKind.PlusPlusToken, unaryPreincrementExpressions, [ + isNonJsxSameLineTokenContext, + ], RuleAction.DeleteSpace), + rule("NoSpaceAfterUnaryPredecrementOperator", SyntaxKind.MinusMinusToken, unaryPredecrementExpressions, [ + isNonJsxSameLineTokenContext, + ], RuleAction.DeleteSpace), + rule("NoSpaceBeforeUnaryPostincrementOperator", unaryPostincrementExpressions, SyntaxKind.PlusPlusToken, [ + isNonJsxSameLineTokenContext, + isNotStatementConditionContext, + ], RuleAction.DeleteSpace), + rule("NoSpaceBeforeUnaryPostdecrementOperator", unaryPostdecrementExpressions, SyntaxKind.MinusMinusToken, [ + isNonJsxSameLineTokenContext, + isNotStatementConditionContext, + ], RuleAction.DeleteSpace), // More unary operator special-casing. // DevDiv 181814: Be careful when removing leading whitespace // around unary operators. Examples: // 1 - -2 --X--> 1--2 // a + ++b --X--> a+++b - rule("SpaceAfterPostincrementWhenFollowedByAdd", SyntaxKind.PlusPlusToken, SyntaxKind.PlusToken, [isNonJsxSameLineTokenContext, isBinaryOpContext], RuleAction.InsertSpace), - rule("SpaceAfterAddWhenFollowedByUnaryPlus", SyntaxKind.PlusToken, SyntaxKind.PlusToken, [isNonJsxSameLineTokenContext, isBinaryOpContext], RuleAction.InsertSpace), - rule("SpaceAfterAddWhenFollowedByPreincrement", SyntaxKind.PlusToken, SyntaxKind.PlusPlusToken, [isNonJsxSameLineTokenContext, isBinaryOpContext], RuleAction.InsertSpace), - rule("SpaceAfterPostdecrementWhenFollowedBySubtract", SyntaxKind.MinusMinusToken, SyntaxKind.MinusToken, [isNonJsxSameLineTokenContext, isBinaryOpContext], RuleAction.InsertSpace), - rule("SpaceAfterSubtractWhenFollowedByUnaryMinus", SyntaxKind.MinusToken, SyntaxKind.MinusToken, [isNonJsxSameLineTokenContext, isBinaryOpContext], RuleAction.InsertSpace), - rule("SpaceAfterSubtractWhenFollowedByPredecrement", SyntaxKind.MinusToken, SyntaxKind.MinusMinusToken, [isNonJsxSameLineTokenContext, isBinaryOpContext], RuleAction.InsertSpace), - - rule("NoSpaceAfterCloseBrace", SyntaxKind.CloseBraceToken, [SyntaxKind.CommaToken, SyntaxKind.SemicolonToken], [isNonJsxSameLineTokenContext], RuleAction.DeleteSpace), + rule("SpaceAfterPostincrementWhenFollowedByAdd", SyntaxKind.PlusPlusToken, SyntaxKind.PlusToken, [ + isNonJsxSameLineTokenContext, + isBinaryOpContext, + ], RuleAction.InsertSpace), + rule("SpaceAfterAddWhenFollowedByUnaryPlus", SyntaxKind.PlusToken, SyntaxKind.PlusToken, [ + isNonJsxSameLineTokenContext, + isBinaryOpContext, + ], RuleAction.InsertSpace), + rule("SpaceAfterAddWhenFollowedByPreincrement", SyntaxKind.PlusToken, SyntaxKind.PlusPlusToken, [ + isNonJsxSameLineTokenContext, + isBinaryOpContext, + ], RuleAction.InsertSpace), + rule("SpaceAfterPostdecrementWhenFollowedBySubtract", SyntaxKind.MinusMinusToken, SyntaxKind.MinusToken, [ + isNonJsxSameLineTokenContext, + isBinaryOpContext, + ], RuleAction.InsertSpace), + rule("SpaceAfterSubtractWhenFollowedByUnaryMinus", SyntaxKind.MinusToken, SyntaxKind.MinusToken, [ + isNonJsxSameLineTokenContext, + isBinaryOpContext, + ], RuleAction.InsertSpace), + rule("SpaceAfterSubtractWhenFollowedByPredecrement", SyntaxKind.MinusToken, SyntaxKind.MinusMinusToken, [ + isNonJsxSameLineTokenContext, + isBinaryOpContext, + ], RuleAction.InsertSpace), + + rule("NoSpaceAfterCloseBrace", SyntaxKind.CloseBraceToken, [SyntaxKind.CommaToken, SyntaxKind.SemicolonToken], [ + isNonJsxSameLineTokenContext, + ], RuleAction.DeleteSpace), // For functions and control block place } on a new line [multi-line rule] - rule("NewLineBeforeCloseBraceInBlockContext", anyTokenIncludingMultilineComments, SyntaxKind.CloseBraceToken, [isMultilineBlockContext], RuleAction.InsertNewLine), + rule("NewLineBeforeCloseBraceInBlockContext", anyTokenIncludingMultilineComments, SyntaxKind.CloseBraceToken, [ + isMultilineBlockContext, + ], RuleAction.InsertNewLine), // Space/new line after }. - rule("SpaceAfterCloseBrace", SyntaxKind.CloseBraceToken, anyTokenExcept(SyntaxKind.CloseParenToken), [isNonJsxSameLineTokenContext, isAfterCodeBlockContext], RuleAction.InsertSpace), + rule("SpaceAfterCloseBrace", SyntaxKind.CloseBraceToken, anyTokenExcept(SyntaxKind.CloseParenToken), [ + isNonJsxSameLineTokenContext, + isAfterCodeBlockContext, + ], RuleAction.InsertSpace), // Special case for (}, else) and (}, while) since else & while tokens are not part of the tree which makes SpaceAfterCloseBrace rule not applied // Also should not apply to }) - rule("SpaceBetweenCloseBraceAndElse", SyntaxKind.CloseBraceToken, SyntaxKind.ElseKeyword, [isNonJsxSameLineTokenContext], RuleAction.InsertSpace), - rule("SpaceBetweenCloseBraceAndWhile", SyntaxKind.CloseBraceToken, SyntaxKind.WhileKeyword, [isNonJsxSameLineTokenContext], RuleAction.InsertSpace), - rule("NoSpaceBetweenEmptyBraceBrackets", SyntaxKind.OpenBraceToken, SyntaxKind.CloseBraceToken, [isNonJsxSameLineTokenContext, isObjectContext], RuleAction.DeleteSpace), + rule("SpaceBetweenCloseBraceAndElse", SyntaxKind.CloseBraceToken, SyntaxKind.ElseKeyword, [ + isNonJsxSameLineTokenContext, + ], RuleAction.InsertSpace), + rule("SpaceBetweenCloseBraceAndWhile", SyntaxKind.CloseBraceToken, SyntaxKind.WhileKeyword, [ + isNonJsxSameLineTokenContext, + ], RuleAction.InsertSpace), + rule("NoSpaceBetweenEmptyBraceBrackets", SyntaxKind.OpenBraceToken, SyntaxKind.CloseBraceToken, [ + isNonJsxSameLineTokenContext, + isObjectContext, + ], RuleAction.DeleteSpace), // Add a space after control dec context if the next character is an open bracket ex: 'if (false)[a, b] = [1, 2];' -> 'if (false) [a, b] = [1, 2];' - rule("SpaceAfterConditionalClosingParen", SyntaxKind.CloseParenToken, SyntaxKind.OpenBracketToken, [isControlDeclContext], RuleAction.InsertSpace), + rule("SpaceAfterConditionalClosingParen", SyntaxKind.CloseParenToken, SyntaxKind.OpenBracketToken, [ + isControlDeclContext, + ], RuleAction.InsertSpace), - rule("NoSpaceBetweenFunctionKeywordAndStar", SyntaxKind.FunctionKeyword, SyntaxKind.AsteriskToken, [isFunctionDeclarationOrFunctionExpressionContext], RuleAction.DeleteSpace), - rule("SpaceAfterStarInGeneratorDeclaration", SyntaxKind.AsteriskToken, SyntaxKind.Identifier, [isFunctionDeclarationOrFunctionExpressionContext], RuleAction.InsertSpace), + rule("NoSpaceBetweenFunctionKeywordAndStar", SyntaxKind.FunctionKeyword, SyntaxKind.AsteriskToken, [ + isFunctionDeclarationOrFunctionExpressionContext, + ], RuleAction.DeleteSpace), + rule("SpaceAfterStarInGeneratorDeclaration", SyntaxKind.AsteriskToken, SyntaxKind.Identifier, [ + isFunctionDeclarationOrFunctionExpressionContext, + ], RuleAction.InsertSpace), - rule("SpaceAfterFunctionInFuncDecl", SyntaxKind.FunctionKeyword, anyToken, [isFunctionDeclContext], RuleAction.InsertSpace), + rule( + "SpaceAfterFunctionInFuncDecl", + SyntaxKind.FunctionKeyword, + anyToken, + [isFunctionDeclContext], + RuleAction.InsertSpace, + ), // Insert new line after { and before } in multi-line contexts. - rule("NewLineAfterOpenBraceInBlockContext", SyntaxKind.OpenBraceToken, anyToken, [isMultilineBlockContext], RuleAction.InsertNewLine), + rule( + "NewLineAfterOpenBraceInBlockContext", + SyntaxKind.OpenBraceToken, + anyToken, + [isMultilineBlockContext], + RuleAction.InsertNewLine, + ), // For get/set members, we check for (identifier,identifier) since get/set don't have tokens and they are represented as just an identifier token. // Though, we do extra check on the context to make sure we are dealing with get/set node. Example: // get x() {} // set x(val) {} - rule("SpaceAfterGetSetInMember", [SyntaxKind.GetKeyword, SyntaxKind.SetKeyword], SyntaxKind.Identifier, [isFunctionDeclContext], RuleAction.InsertSpace), + rule("SpaceAfterGetSetInMember", [SyntaxKind.GetKeyword, SyntaxKind.SetKeyword], SyntaxKind.Identifier, [ + isFunctionDeclContext, + ], RuleAction.InsertSpace), - rule("NoSpaceBetweenYieldKeywordAndStar", SyntaxKind.YieldKeyword, SyntaxKind.AsteriskToken, [isNonJsxSameLineTokenContext, isYieldOrYieldStarWithOperand], RuleAction.DeleteSpace), - rule("SpaceBetweenYieldOrYieldStarAndOperand", [SyntaxKind.YieldKeyword, SyntaxKind.AsteriskToken], anyToken, [isNonJsxSameLineTokenContext, isYieldOrYieldStarWithOperand], RuleAction.InsertSpace), + rule("NoSpaceBetweenYieldKeywordAndStar", SyntaxKind.YieldKeyword, SyntaxKind.AsteriskToken, [ + isNonJsxSameLineTokenContext, + isYieldOrYieldStarWithOperand, + ], RuleAction.DeleteSpace), + rule("SpaceBetweenYieldOrYieldStarAndOperand", [SyntaxKind.YieldKeyword, SyntaxKind.AsteriskToken], anyToken, [ + isNonJsxSameLineTokenContext, + isYieldOrYieldStarWithOperand, + ], RuleAction.InsertSpace), - rule("NoSpaceBetweenReturnAndSemicolon", SyntaxKind.ReturnKeyword, SyntaxKind.SemicolonToken, [isNonJsxSameLineTokenContext], RuleAction.DeleteSpace), - rule("SpaceAfterCertainKeywords", [SyntaxKind.VarKeyword, SyntaxKind.ThrowKeyword, SyntaxKind.NewKeyword, SyntaxKind.DeleteKeyword, SyntaxKind.ReturnKeyword, SyntaxKind.TypeOfKeyword, SyntaxKind.AwaitKeyword], anyToken, [isNonJsxSameLineTokenContext], RuleAction.InsertSpace), - rule("SpaceAfterLetConstInVariableDeclaration", [SyntaxKind.LetKeyword, SyntaxKind.ConstKeyword], anyToken, [isNonJsxSameLineTokenContext, isStartOfVariableDeclarationList], RuleAction.InsertSpace), - rule("NoSpaceBeforeOpenParenInFuncCall", anyToken, SyntaxKind.OpenParenToken, [isNonJsxSameLineTokenContext, isFunctionCallOrNewContext, isPreviousTokenNotComma], RuleAction.DeleteSpace), + rule("NoSpaceBetweenReturnAndSemicolon", SyntaxKind.ReturnKeyword, SyntaxKind.SemicolonToken, [ + isNonJsxSameLineTokenContext, + ], RuleAction.DeleteSpace), + rule( + "SpaceAfterCertainKeywords", + [ + SyntaxKind.VarKeyword, + SyntaxKind.ThrowKeyword, + SyntaxKind.NewKeyword, + SyntaxKind.DeleteKeyword, + SyntaxKind.ReturnKeyword, + SyntaxKind.TypeOfKeyword, + SyntaxKind.AwaitKeyword, + ], + anyToken, + [isNonJsxSameLineTokenContext], + RuleAction.InsertSpace, + ), + rule("SpaceAfterLetConstInVariableDeclaration", [SyntaxKind.LetKeyword, SyntaxKind.ConstKeyword], anyToken, [ + isNonJsxSameLineTokenContext, + isStartOfVariableDeclarationList, + ], RuleAction.InsertSpace), + rule("NoSpaceBeforeOpenParenInFuncCall", anyToken, SyntaxKind.OpenParenToken, [ + isNonJsxSameLineTokenContext, + isFunctionCallOrNewContext, + isPreviousTokenNotComma, + ], RuleAction.DeleteSpace), // Special case for binary operators (that are keywords). For these we have to add a space and shouldn't follow any user options. - rule("SpaceBeforeBinaryKeywordOperator", anyToken, binaryKeywordOperators, [isNonJsxSameLineTokenContext, isBinaryOpContext], RuleAction.InsertSpace), - rule("SpaceAfterBinaryKeywordOperator", binaryKeywordOperators, anyToken, [isNonJsxSameLineTokenContext, isBinaryOpContext], RuleAction.InsertSpace), + rule("SpaceBeforeBinaryKeywordOperator", anyToken, binaryKeywordOperators, [ + isNonJsxSameLineTokenContext, + isBinaryOpContext, + ], RuleAction.InsertSpace), + rule("SpaceAfterBinaryKeywordOperator", binaryKeywordOperators, anyToken, [ + isNonJsxSameLineTokenContext, + isBinaryOpContext, + ], RuleAction.InsertSpace), - rule("SpaceAfterVoidOperator", SyntaxKind.VoidKeyword, anyToken, [isNonJsxSameLineTokenContext, isVoidOpContext], RuleAction.InsertSpace), + rule("SpaceAfterVoidOperator", SyntaxKind.VoidKeyword, anyToken, [ + isNonJsxSameLineTokenContext, + isVoidOpContext, + ], RuleAction.InsertSpace), // Async-await - rule("SpaceBetweenAsyncAndOpenParen", SyntaxKind.AsyncKeyword, SyntaxKind.OpenParenToken, [isArrowFunctionContext, isNonJsxSameLineTokenContext], RuleAction.InsertSpace), - rule("SpaceBetweenAsyncAndFunctionKeyword", SyntaxKind.AsyncKeyword, [SyntaxKind.FunctionKeyword, SyntaxKind.Identifier], [isNonJsxSameLineTokenContext], RuleAction.InsertSpace), + rule("SpaceBetweenAsyncAndOpenParen", SyntaxKind.AsyncKeyword, SyntaxKind.OpenParenToken, [ + isArrowFunctionContext, + isNonJsxSameLineTokenContext, + ], RuleAction.InsertSpace), + rule( + "SpaceBetweenAsyncAndFunctionKeyword", + SyntaxKind.AsyncKeyword, + [SyntaxKind.FunctionKeyword, SyntaxKind.Identifier], + [isNonJsxSameLineTokenContext], + RuleAction.InsertSpace, + ), // Template string - rule("NoSpaceBetweenTagAndTemplateString", [SyntaxKind.Identifier, SyntaxKind.CloseParenToken], [SyntaxKind.NoSubstitutionTemplateLiteral, SyntaxKind.TemplateHead], [isNonJsxSameLineTokenContext], RuleAction.DeleteSpace), + rule( + "NoSpaceBetweenTagAndTemplateString", + [SyntaxKind.Identifier, SyntaxKind.CloseParenToken], + [SyntaxKind.NoSubstitutionTemplateLiteral, SyntaxKind.TemplateHead], + [isNonJsxSameLineTokenContext], + RuleAction.DeleteSpace, + ), // JSX opening elements - rule("SpaceBeforeJsxAttribute", anyToken, SyntaxKind.Identifier, [isNextTokenParentJsxAttribute, isNonJsxSameLineTokenContext], RuleAction.InsertSpace), - rule("SpaceBeforeSlashInJsxOpeningElement", anyToken, SyntaxKind.SlashToken, [isJsxSelfClosingElementContext, isNonJsxSameLineTokenContext], RuleAction.InsertSpace), - rule("NoSpaceBeforeGreaterThanTokenInJsxOpeningElement", SyntaxKind.SlashToken, SyntaxKind.GreaterThanToken, [isJsxSelfClosingElementContext, isNonJsxSameLineTokenContext], RuleAction.DeleteSpace), - rule("NoSpaceBeforeEqualInJsxAttribute", anyToken, SyntaxKind.EqualsToken, [isJsxAttributeContext, isNonJsxSameLineTokenContext], RuleAction.DeleteSpace), - rule("NoSpaceAfterEqualInJsxAttribute", SyntaxKind.EqualsToken, anyToken, [isJsxAttributeContext, isNonJsxSameLineTokenContext], RuleAction.DeleteSpace), - rule("NoSpaceBeforeJsxNamespaceColon", SyntaxKind.Identifier, SyntaxKind.ColonToken, [isNextTokenParentJsxNamespacedName], RuleAction.DeleteSpace), - rule("NoSpaceAfterJsxNamespaceColon", SyntaxKind.ColonToken, SyntaxKind.Identifier, [isNextTokenParentJsxNamespacedName], RuleAction.DeleteSpace), + rule("SpaceBeforeJsxAttribute", anyToken, SyntaxKind.Identifier, [ + isNextTokenParentJsxAttribute, + isNonJsxSameLineTokenContext, + ], RuleAction.InsertSpace), + rule("SpaceBeforeSlashInJsxOpeningElement", anyToken, SyntaxKind.SlashToken, [ + isJsxSelfClosingElementContext, + isNonJsxSameLineTokenContext, + ], RuleAction.InsertSpace), + rule("NoSpaceBeforeGreaterThanTokenInJsxOpeningElement", SyntaxKind.SlashToken, SyntaxKind.GreaterThanToken, [ + isJsxSelfClosingElementContext, + isNonJsxSameLineTokenContext, + ], RuleAction.DeleteSpace), + rule("NoSpaceBeforeEqualInJsxAttribute", anyToken, SyntaxKind.EqualsToken, [ + isJsxAttributeContext, + isNonJsxSameLineTokenContext, + ], RuleAction.DeleteSpace), + rule("NoSpaceAfterEqualInJsxAttribute", SyntaxKind.EqualsToken, anyToken, [ + isJsxAttributeContext, + isNonJsxSameLineTokenContext, + ], RuleAction.DeleteSpace), + rule("NoSpaceBeforeJsxNamespaceColon", SyntaxKind.Identifier, SyntaxKind.ColonToken, [ + isNextTokenParentJsxNamespacedName, + ], RuleAction.DeleteSpace), + rule("NoSpaceAfterJsxNamespaceColon", SyntaxKind.ColonToken, SyntaxKind.Identifier, [ + isNextTokenParentJsxNamespacedName, + ], RuleAction.DeleteSpace), // TypeScript-specific rules // Use of module as a function call. e.g.: import m2 = module("m2"); - rule("NoSpaceAfterModuleImport", [SyntaxKind.ModuleKeyword, SyntaxKind.RequireKeyword], SyntaxKind.OpenParenToken, [isNonJsxSameLineTokenContext], RuleAction.DeleteSpace), + rule( + "NoSpaceAfterModuleImport", + [SyntaxKind.ModuleKeyword, SyntaxKind.RequireKeyword], + SyntaxKind.OpenParenToken, + [isNonJsxSameLineTokenContext], + RuleAction.DeleteSpace, + ), // Add a space around certain TypeScript keywords rule( "SpaceAfterCertainTypeScriptKeywords", @@ -236,25 +452,75 @@ export function getAllRules(): RuleSpec[] { RuleAction.InsertSpace, ), // Treat string literals in module names as identifiers, and add a space between the literal and the opening Brace braces, e.g.: module "m2" { - rule("SpaceAfterModuleName", SyntaxKind.StringLiteral, SyntaxKind.OpenBraceToken, [isModuleDeclContext], RuleAction.InsertSpace), + rule( + "SpaceAfterModuleName", + SyntaxKind.StringLiteral, + SyntaxKind.OpenBraceToken, + [isModuleDeclContext], + RuleAction.InsertSpace, + ), // Lambda expressions - rule("SpaceBeforeArrow", anyToken, SyntaxKind.EqualsGreaterThanToken, [isNonJsxSameLineTokenContext], RuleAction.InsertSpace), - rule("SpaceAfterArrow", SyntaxKind.EqualsGreaterThanToken, anyToken, [isNonJsxSameLineTokenContext], RuleAction.InsertSpace), + rule( + "SpaceBeforeArrow", + anyToken, + SyntaxKind.EqualsGreaterThanToken, + [isNonJsxSameLineTokenContext], + RuleAction.InsertSpace, + ), + rule( + "SpaceAfterArrow", + SyntaxKind.EqualsGreaterThanToken, + anyToken, + [isNonJsxSameLineTokenContext], + RuleAction.InsertSpace, + ), // Optional parameters and let args - rule("NoSpaceAfterEllipsis", SyntaxKind.DotDotDotToken, SyntaxKind.Identifier, [isNonJsxSameLineTokenContext], RuleAction.DeleteSpace), - rule("NoSpaceAfterOptionalParameters", SyntaxKind.QuestionToken, [SyntaxKind.CloseParenToken, SyntaxKind.CommaToken], [isNonJsxSameLineTokenContext, isNotBinaryOpContext], RuleAction.DeleteSpace), + rule( + "NoSpaceAfterEllipsis", + SyntaxKind.DotDotDotToken, + SyntaxKind.Identifier, + [isNonJsxSameLineTokenContext], + RuleAction.DeleteSpace, + ), + rule( + "NoSpaceAfterOptionalParameters", + SyntaxKind.QuestionToken, + [SyntaxKind.CloseParenToken, SyntaxKind.CommaToken], + [isNonJsxSameLineTokenContext, isNotBinaryOpContext], + RuleAction.DeleteSpace, + ), // Remove spaces in empty interface literals. e.g.: x: {} - rule("NoSpaceBetweenEmptyInterfaceBraceBrackets", SyntaxKind.OpenBraceToken, SyntaxKind.CloseBraceToken, [isNonJsxSameLineTokenContext, isObjectTypeContext], RuleAction.DeleteSpace), + rule("NoSpaceBetweenEmptyInterfaceBraceBrackets", SyntaxKind.OpenBraceToken, SyntaxKind.CloseBraceToken, [ + isNonJsxSameLineTokenContext, + isObjectTypeContext, + ], RuleAction.DeleteSpace), // generics and type assertions - rule("NoSpaceBeforeOpenAngularBracket", typeNames, SyntaxKind.LessThanToken, [isNonJsxSameLineTokenContext, isTypeArgumentOrParameterOrAssertionContext], RuleAction.DeleteSpace), - rule("NoSpaceBetweenCloseParenAndAngularBracket", SyntaxKind.CloseParenToken, SyntaxKind.LessThanToken, [isNonJsxSameLineTokenContext, isTypeArgumentOrParameterOrAssertionContext], RuleAction.DeleteSpace), - rule("NoSpaceAfterOpenAngularBracket", SyntaxKind.LessThanToken, anyToken, [isNonJsxSameLineTokenContext, isTypeArgumentOrParameterOrAssertionContext], RuleAction.DeleteSpace), - rule("NoSpaceBeforeCloseAngularBracket", anyToken, SyntaxKind.GreaterThanToken, [isNonJsxSameLineTokenContext, isTypeArgumentOrParameterOrAssertionContext], RuleAction.DeleteSpace), - rule("NoSpaceAfterCloseAngularBracket", SyntaxKind.GreaterThanToken, [SyntaxKind.OpenParenToken, SyntaxKind.OpenBracketToken, SyntaxKind.GreaterThanToken, SyntaxKind.CommaToken], [ + rule("NoSpaceBeforeOpenAngularBracket", typeNames, SyntaxKind.LessThanToken, [ + isNonJsxSameLineTokenContext, + isTypeArgumentOrParameterOrAssertionContext, + ], RuleAction.DeleteSpace), + rule("NoSpaceBetweenCloseParenAndAngularBracket", SyntaxKind.CloseParenToken, SyntaxKind.LessThanToken, [ + isNonJsxSameLineTokenContext, + isTypeArgumentOrParameterOrAssertionContext, + ], RuleAction.DeleteSpace), + rule("NoSpaceAfterOpenAngularBracket", SyntaxKind.LessThanToken, anyToken, [ + isNonJsxSameLineTokenContext, + isTypeArgumentOrParameterOrAssertionContext, + ], RuleAction.DeleteSpace), + rule("NoSpaceBeforeCloseAngularBracket", anyToken, SyntaxKind.GreaterThanToken, [ + isNonJsxSameLineTokenContext, + isTypeArgumentOrParameterOrAssertionContext, + ], RuleAction.DeleteSpace), + rule("NoSpaceAfterCloseAngularBracket", SyntaxKind.GreaterThanToken, [ + SyntaxKind.OpenParenToken, + SyntaxKind.OpenBracketToken, + SyntaxKind.GreaterThanToken, + SyntaxKind.CommaToken, + ], [ isNonJsxSameLineTokenContext, isTypeArgumentOrParameterOrAssertionContext, isNotFunctionDeclContext, /*To prevent an interference with the SpaceBeforeOpenParenInFuncDecl rule*/ @@ -262,7 +528,9 @@ export function getAllRules(): RuleSpec[] { ], RuleAction.DeleteSpace), // decorators - rule("SpaceBeforeAt", [SyntaxKind.CloseParenToken, SyntaxKind.Identifier], SyntaxKind.AtToken, [isNonJsxSameLineTokenContext], RuleAction.InsertSpace), + rule("SpaceBeforeAt", [SyntaxKind.CloseParenToken, SyntaxKind.Identifier], SyntaxKind.AtToken, [ + isNonJsxSameLineTokenContext, + ], RuleAction.InsertSpace), rule("NoSpaceAfterAt", SyntaxKind.AtToken, anyToken, [isNonJsxSameLineTokenContext], RuleAction.DeleteSpace), // Insert space after @ in decorator rule( @@ -287,116 +555,404 @@ export function getAllRules(): RuleSpec[] { RuleAction.InsertSpace, ), - rule("NoSpaceBeforeNonNullAssertionOperator", anyToken, SyntaxKind.ExclamationToken, [isNonJsxSameLineTokenContext, isNonNullAssertionContext], RuleAction.DeleteSpace), - rule("NoSpaceAfterNewKeywordOnConstructorSignature", SyntaxKind.NewKeyword, SyntaxKind.OpenParenToken, [isNonJsxSameLineTokenContext, isConstructorSignatureContext], RuleAction.DeleteSpace), - rule("SpaceLessThanAndNonJSXTypeAnnotation", SyntaxKind.LessThanToken, SyntaxKind.LessThanToken, [isNonJsxSameLineTokenContext], RuleAction.InsertSpace), + rule("NoSpaceBeforeNonNullAssertionOperator", anyToken, SyntaxKind.ExclamationToken, [ + isNonJsxSameLineTokenContext, + isNonNullAssertionContext, + ], RuleAction.DeleteSpace), + rule("NoSpaceAfterNewKeywordOnConstructorSignature", SyntaxKind.NewKeyword, SyntaxKind.OpenParenToken, [ + isNonJsxSameLineTokenContext, + isConstructorSignatureContext, + ], RuleAction.DeleteSpace), + rule("SpaceLessThanAndNonJSXTypeAnnotation", SyntaxKind.LessThanToken, SyntaxKind.LessThanToken, [ + isNonJsxSameLineTokenContext, + ], RuleAction.InsertSpace), ]; // These rules are applied after high priority const userConfigurableRules = [ // Treat constructor as an identifier in a function declaration, and remove spaces between constructor and following left parentheses - rule("SpaceAfterConstructor", SyntaxKind.ConstructorKeyword, SyntaxKind.OpenParenToken, [isOptionEnabled("insertSpaceAfterConstructor"), isNonJsxSameLineTokenContext], RuleAction.InsertSpace), - rule("NoSpaceAfterConstructor", SyntaxKind.ConstructorKeyword, SyntaxKind.OpenParenToken, [isOptionDisabledOrUndefined("insertSpaceAfterConstructor"), isNonJsxSameLineTokenContext], RuleAction.DeleteSpace), + rule("SpaceAfterConstructor", SyntaxKind.ConstructorKeyword, SyntaxKind.OpenParenToken, [ + isOptionEnabled("insertSpaceAfterConstructor"), + isNonJsxSameLineTokenContext, + ], RuleAction.InsertSpace), + rule("NoSpaceAfterConstructor", SyntaxKind.ConstructorKeyword, SyntaxKind.OpenParenToken, [ + isOptionDisabledOrUndefined("insertSpaceAfterConstructor"), + isNonJsxSameLineTokenContext, + ], RuleAction.DeleteSpace), - rule("SpaceAfterComma", SyntaxKind.CommaToken, anyToken, [isOptionEnabled("insertSpaceAfterCommaDelimiter"), isNonJsxSameLineTokenContext, isNonJsxElementOrFragmentContext, isNextTokenNotCloseBracket, isNextTokenNotCloseParen], RuleAction.InsertSpace), - rule("NoSpaceAfterComma", SyntaxKind.CommaToken, anyToken, [isOptionDisabledOrUndefined("insertSpaceAfterCommaDelimiter"), isNonJsxSameLineTokenContext, isNonJsxElementOrFragmentContext], RuleAction.DeleteSpace), + rule("SpaceAfterComma", SyntaxKind.CommaToken, anyToken, [ + isOptionEnabled("insertSpaceAfterCommaDelimiter"), + isNonJsxSameLineTokenContext, + isNonJsxElementOrFragmentContext, + isNextTokenNotCloseBracket, + isNextTokenNotCloseParen, + ], RuleAction.InsertSpace), + rule("NoSpaceAfterComma", SyntaxKind.CommaToken, anyToken, [ + isOptionDisabledOrUndefined("insertSpaceAfterCommaDelimiter"), + isNonJsxSameLineTokenContext, + isNonJsxElementOrFragmentContext, + ], RuleAction.DeleteSpace), // Insert space after function keyword for anonymous functions - rule("SpaceAfterAnonymousFunctionKeyword", [SyntaxKind.FunctionKeyword, SyntaxKind.AsteriskToken], SyntaxKind.OpenParenToken, [isOptionEnabled("insertSpaceAfterFunctionKeywordForAnonymousFunctions"), isFunctionDeclContext], RuleAction.InsertSpace), - rule("NoSpaceAfterAnonymousFunctionKeyword", [SyntaxKind.FunctionKeyword, SyntaxKind.AsteriskToken], SyntaxKind.OpenParenToken, [isOptionDisabledOrUndefined("insertSpaceAfterFunctionKeywordForAnonymousFunctions"), isFunctionDeclContext], RuleAction.DeleteSpace), + rule( + "SpaceAfterAnonymousFunctionKeyword", + [SyntaxKind.FunctionKeyword, SyntaxKind.AsteriskToken], + SyntaxKind.OpenParenToken, + [isOptionEnabled("insertSpaceAfterFunctionKeywordForAnonymousFunctions"), isFunctionDeclContext], + RuleAction.InsertSpace, + ), + rule( + "NoSpaceAfterAnonymousFunctionKeyword", + [SyntaxKind.FunctionKeyword, SyntaxKind.AsteriskToken], + SyntaxKind.OpenParenToken, + [ + isOptionDisabledOrUndefined("insertSpaceAfterFunctionKeywordForAnonymousFunctions"), + isFunctionDeclContext, + ], + RuleAction.DeleteSpace, + ), // Insert space after keywords in control flow statements - rule("SpaceAfterKeywordInControl", keywords, SyntaxKind.OpenParenToken, [isOptionEnabled("insertSpaceAfterKeywordsInControlFlowStatements"), isControlDeclContext], RuleAction.InsertSpace), - rule("NoSpaceAfterKeywordInControl", keywords, SyntaxKind.OpenParenToken, [isOptionDisabledOrUndefined("insertSpaceAfterKeywordsInControlFlowStatements"), isControlDeclContext], RuleAction.DeleteSpace), + rule("SpaceAfterKeywordInControl", keywords, SyntaxKind.OpenParenToken, [ + isOptionEnabled("insertSpaceAfterKeywordsInControlFlowStatements"), + isControlDeclContext, + ], RuleAction.InsertSpace), + rule("NoSpaceAfterKeywordInControl", keywords, SyntaxKind.OpenParenToken, [ + isOptionDisabledOrUndefined("insertSpaceAfterKeywordsInControlFlowStatements"), + isControlDeclContext, + ], RuleAction.DeleteSpace), // Insert space after opening and before closing nonempty parenthesis - rule("SpaceAfterOpenParen", SyntaxKind.OpenParenToken, anyToken, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis"), isNonJsxSameLineTokenContext], RuleAction.InsertSpace), - rule("SpaceBeforeCloseParen", anyToken, SyntaxKind.CloseParenToken, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis"), isNonJsxSameLineTokenContext], RuleAction.InsertSpace), - rule("SpaceBetweenOpenParens", SyntaxKind.OpenParenToken, SyntaxKind.OpenParenToken, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis"), isNonJsxSameLineTokenContext], RuleAction.InsertSpace), - rule("NoSpaceBetweenParens", SyntaxKind.OpenParenToken, SyntaxKind.CloseParenToken, [isNonJsxSameLineTokenContext], RuleAction.DeleteSpace), - rule("NoSpaceAfterOpenParen", SyntaxKind.OpenParenToken, anyToken, [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis"), isNonJsxSameLineTokenContext], RuleAction.DeleteSpace), - rule("NoSpaceBeforeCloseParen", anyToken, SyntaxKind.CloseParenToken, [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis"), isNonJsxSameLineTokenContext], RuleAction.DeleteSpace), + rule("SpaceAfterOpenParen", SyntaxKind.OpenParenToken, anyToken, [ + isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis"), + isNonJsxSameLineTokenContext, + ], RuleAction.InsertSpace), + rule("SpaceBeforeCloseParen", anyToken, SyntaxKind.CloseParenToken, [ + isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis"), + isNonJsxSameLineTokenContext, + ], RuleAction.InsertSpace), + rule("SpaceBetweenOpenParens", SyntaxKind.OpenParenToken, SyntaxKind.OpenParenToken, [ + isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis"), + isNonJsxSameLineTokenContext, + ], RuleAction.InsertSpace), + rule("NoSpaceBetweenParens", SyntaxKind.OpenParenToken, SyntaxKind.CloseParenToken, [ + isNonJsxSameLineTokenContext, + ], RuleAction.DeleteSpace), + rule("NoSpaceAfterOpenParen", SyntaxKind.OpenParenToken, anyToken, [ + isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis"), + isNonJsxSameLineTokenContext, + ], RuleAction.DeleteSpace), + rule("NoSpaceBeforeCloseParen", anyToken, SyntaxKind.CloseParenToken, [ + isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis"), + isNonJsxSameLineTokenContext, + ], RuleAction.DeleteSpace), // Insert space after opening and before closing nonempty brackets - rule("SpaceAfterOpenBracket", SyntaxKind.OpenBracketToken, anyToken, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets"), isNonJsxSameLineTokenContext], RuleAction.InsertSpace), - rule("SpaceBeforeCloseBracket", anyToken, SyntaxKind.CloseBracketToken, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets"), isNonJsxSameLineTokenContext], RuleAction.InsertSpace), - rule("NoSpaceBetweenBrackets", SyntaxKind.OpenBracketToken, SyntaxKind.CloseBracketToken, [isNonJsxSameLineTokenContext], RuleAction.DeleteSpace), - rule("NoSpaceAfterOpenBracket", SyntaxKind.OpenBracketToken, anyToken, [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets"), isNonJsxSameLineTokenContext], RuleAction.DeleteSpace), - rule("NoSpaceBeforeCloseBracket", anyToken, SyntaxKind.CloseBracketToken, [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets"), isNonJsxSameLineTokenContext], RuleAction.DeleteSpace), + rule("SpaceAfterOpenBracket", SyntaxKind.OpenBracketToken, anyToken, [ + isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets"), + isNonJsxSameLineTokenContext, + ], RuleAction.InsertSpace), + rule("SpaceBeforeCloseBracket", anyToken, SyntaxKind.CloseBracketToken, [ + isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets"), + isNonJsxSameLineTokenContext, + ], RuleAction.InsertSpace), + rule("NoSpaceBetweenBrackets", SyntaxKind.OpenBracketToken, SyntaxKind.CloseBracketToken, [ + isNonJsxSameLineTokenContext, + ], RuleAction.DeleteSpace), + rule("NoSpaceAfterOpenBracket", SyntaxKind.OpenBracketToken, anyToken, [ + isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets"), + isNonJsxSameLineTokenContext, + ], RuleAction.DeleteSpace), + rule("NoSpaceBeforeCloseBracket", anyToken, SyntaxKind.CloseBracketToken, [ + isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets"), + isNonJsxSameLineTokenContext, + ], RuleAction.DeleteSpace), // Insert a space after { and before } in single-line contexts, but remove space from empty object literals {}. - rule("SpaceAfterOpenBrace", SyntaxKind.OpenBraceToken, anyToken, [isOptionEnabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces"), isBraceWrappedContext], RuleAction.InsertSpace), - rule("SpaceBeforeCloseBrace", anyToken, SyntaxKind.CloseBraceToken, [isOptionEnabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces"), isBraceWrappedContext], RuleAction.InsertSpace), - rule("NoSpaceBetweenEmptyBraceBrackets", SyntaxKind.OpenBraceToken, SyntaxKind.CloseBraceToken, [isNonJsxSameLineTokenContext, isObjectContext], RuleAction.DeleteSpace), - rule("NoSpaceAfterOpenBrace", SyntaxKind.OpenBraceToken, anyToken, [isOptionDisabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces"), isNonJsxSameLineTokenContext], RuleAction.DeleteSpace), - rule("NoSpaceBeforeCloseBrace", anyToken, SyntaxKind.CloseBraceToken, [isOptionDisabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces"), isNonJsxSameLineTokenContext], RuleAction.DeleteSpace), + rule("SpaceAfterOpenBrace", SyntaxKind.OpenBraceToken, anyToken, [ + isOptionEnabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces"), + isBraceWrappedContext, + ], RuleAction.InsertSpace), + rule("SpaceBeforeCloseBrace", anyToken, SyntaxKind.CloseBraceToken, [ + isOptionEnabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces"), + isBraceWrappedContext, + ], RuleAction.InsertSpace), + rule("NoSpaceBetweenEmptyBraceBrackets", SyntaxKind.OpenBraceToken, SyntaxKind.CloseBraceToken, [ + isNonJsxSameLineTokenContext, + isObjectContext, + ], RuleAction.DeleteSpace), + rule("NoSpaceAfterOpenBrace", SyntaxKind.OpenBraceToken, anyToken, [ + isOptionDisabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces"), + isNonJsxSameLineTokenContext, + ], RuleAction.DeleteSpace), + rule("NoSpaceBeforeCloseBrace", anyToken, SyntaxKind.CloseBraceToken, [ + isOptionDisabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces"), + isNonJsxSameLineTokenContext, + ], RuleAction.DeleteSpace), // Insert a space after opening and before closing empty brace brackets - rule("SpaceBetweenEmptyBraceBrackets", SyntaxKind.OpenBraceToken, SyntaxKind.CloseBraceToken, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingEmptyBraces")], RuleAction.InsertSpace), - rule("NoSpaceBetweenEmptyBraceBrackets", SyntaxKind.OpenBraceToken, SyntaxKind.CloseBraceToken, [isOptionDisabled("insertSpaceAfterOpeningAndBeforeClosingEmptyBraces"), isNonJsxSameLineTokenContext], RuleAction.DeleteSpace), + rule("SpaceBetweenEmptyBraceBrackets", SyntaxKind.OpenBraceToken, SyntaxKind.CloseBraceToken, [ + isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingEmptyBraces"), + ], RuleAction.InsertSpace), + rule("NoSpaceBetweenEmptyBraceBrackets", SyntaxKind.OpenBraceToken, SyntaxKind.CloseBraceToken, [ + isOptionDisabled("insertSpaceAfterOpeningAndBeforeClosingEmptyBraces"), + isNonJsxSameLineTokenContext, + ], RuleAction.DeleteSpace), // Insert space after opening and before closing template string braces - rule("SpaceAfterTemplateHeadAndMiddle", [SyntaxKind.TemplateHead, SyntaxKind.TemplateMiddle], anyToken, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces"), isNonJsxTextContext], RuleAction.InsertSpace, RuleFlags.CanDeleteNewLines), - rule("SpaceBeforeTemplateMiddleAndTail", anyToken, [SyntaxKind.TemplateMiddle, SyntaxKind.TemplateTail], [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces"), isNonJsxSameLineTokenContext], RuleAction.InsertSpace), - rule("NoSpaceAfterTemplateHeadAndMiddle", [SyntaxKind.TemplateHead, SyntaxKind.TemplateMiddle], anyToken, [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces"), isNonJsxTextContext], RuleAction.DeleteSpace, RuleFlags.CanDeleteNewLines), - rule("NoSpaceBeforeTemplateMiddleAndTail", anyToken, [SyntaxKind.TemplateMiddle, SyntaxKind.TemplateTail], [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces"), isNonJsxSameLineTokenContext], RuleAction.DeleteSpace), + rule( + "SpaceAfterTemplateHeadAndMiddle", + [SyntaxKind.TemplateHead, SyntaxKind.TemplateMiddle], + anyToken, + [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces"), isNonJsxTextContext], + RuleAction.InsertSpace, + RuleFlags.CanDeleteNewLines, + ), + rule("SpaceBeforeTemplateMiddleAndTail", anyToken, [SyntaxKind.TemplateMiddle, SyntaxKind.TemplateTail], [ + isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces"), + isNonJsxSameLineTokenContext, + ], RuleAction.InsertSpace), + rule( + "NoSpaceAfterTemplateHeadAndMiddle", + [SyntaxKind.TemplateHead, SyntaxKind.TemplateMiddle], + anyToken, + [ + isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces"), + isNonJsxTextContext, + ], + RuleAction.DeleteSpace, + RuleFlags.CanDeleteNewLines, + ), + rule("NoSpaceBeforeTemplateMiddleAndTail", anyToken, [SyntaxKind.TemplateMiddle, SyntaxKind.TemplateTail], [ + isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces"), + isNonJsxSameLineTokenContext, + ], RuleAction.DeleteSpace), // No space after { and before } in JSX expression - rule("SpaceAfterOpenBraceInJsxExpression", SyntaxKind.OpenBraceToken, anyToken, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces"), isNonJsxSameLineTokenContext, isJsxExpressionContext], RuleAction.InsertSpace), - rule("SpaceBeforeCloseBraceInJsxExpression", anyToken, SyntaxKind.CloseBraceToken, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces"), isNonJsxSameLineTokenContext, isJsxExpressionContext], RuleAction.InsertSpace), - rule("NoSpaceAfterOpenBraceInJsxExpression", SyntaxKind.OpenBraceToken, anyToken, [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces"), isNonJsxSameLineTokenContext, isJsxExpressionContext], RuleAction.DeleteSpace), - rule("NoSpaceBeforeCloseBraceInJsxExpression", anyToken, SyntaxKind.CloseBraceToken, [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces"), isNonJsxSameLineTokenContext, isJsxExpressionContext], RuleAction.DeleteSpace), + rule("SpaceAfterOpenBraceInJsxExpression", SyntaxKind.OpenBraceToken, anyToken, [ + isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces"), + isNonJsxSameLineTokenContext, + isJsxExpressionContext, + ], RuleAction.InsertSpace), + rule("SpaceBeforeCloseBraceInJsxExpression", anyToken, SyntaxKind.CloseBraceToken, [ + isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces"), + isNonJsxSameLineTokenContext, + isJsxExpressionContext, + ], RuleAction.InsertSpace), + rule("NoSpaceAfterOpenBraceInJsxExpression", SyntaxKind.OpenBraceToken, anyToken, [ + isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces"), + isNonJsxSameLineTokenContext, + isJsxExpressionContext, + ], RuleAction.DeleteSpace), + rule("NoSpaceBeforeCloseBraceInJsxExpression", anyToken, SyntaxKind.CloseBraceToken, [ + isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces"), + isNonJsxSameLineTokenContext, + isJsxExpressionContext, + ], RuleAction.DeleteSpace), // Insert space after semicolon in for statement - rule("SpaceAfterSemicolonInFor", SyntaxKind.SemicolonToken, anyToken, [isOptionEnabled("insertSpaceAfterSemicolonInForStatements"), isNonJsxSameLineTokenContext, isForContext], RuleAction.InsertSpace), - rule("NoSpaceAfterSemicolonInFor", SyntaxKind.SemicolonToken, anyToken, [isOptionDisabledOrUndefined("insertSpaceAfterSemicolonInForStatements"), isNonJsxSameLineTokenContext, isForContext], RuleAction.DeleteSpace), + rule("SpaceAfterSemicolonInFor", SyntaxKind.SemicolonToken, anyToken, [ + isOptionEnabled("insertSpaceAfterSemicolonInForStatements"), + isNonJsxSameLineTokenContext, + isForContext, + ], RuleAction.InsertSpace), + rule("NoSpaceAfterSemicolonInFor", SyntaxKind.SemicolonToken, anyToken, [ + isOptionDisabledOrUndefined("insertSpaceAfterSemicolonInForStatements"), + isNonJsxSameLineTokenContext, + isForContext, + ], RuleAction.DeleteSpace), // Insert space before and after binary operators - rule("SpaceBeforeBinaryOperator", anyToken, binaryOperators, [isOptionEnabled("insertSpaceBeforeAndAfterBinaryOperators"), isNonJsxSameLineTokenContext, isBinaryOpContext], RuleAction.InsertSpace), - rule("SpaceAfterBinaryOperator", binaryOperators, anyToken, [isOptionEnabled("insertSpaceBeforeAndAfterBinaryOperators"), isNonJsxSameLineTokenContext, isBinaryOpContext], RuleAction.InsertSpace), - rule("NoSpaceBeforeBinaryOperator", anyToken, binaryOperators, [isOptionDisabledOrUndefined("insertSpaceBeforeAndAfterBinaryOperators"), isNonJsxSameLineTokenContext, isBinaryOpContext], RuleAction.DeleteSpace), - rule("NoSpaceAfterBinaryOperator", binaryOperators, anyToken, [isOptionDisabledOrUndefined("insertSpaceBeforeAndAfterBinaryOperators"), isNonJsxSameLineTokenContext, isBinaryOpContext], RuleAction.DeleteSpace), + rule("SpaceBeforeBinaryOperator", anyToken, binaryOperators, [ + isOptionEnabled("insertSpaceBeforeAndAfterBinaryOperators"), + isNonJsxSameLineTokenContext, + isBinaryOpContext, + ], RuleAction.InsertSpace), + rule("SpaceAfterBinaryOperator", binaryOperators, anyToken, [ + isOptionEnabled("insertSpaceBeforeAndAfterBinaryOperators"), + isNonJsxSameLineTokenContext, + isBinaryOpContext, + ], RuleAction.InsertSpace), + rule("NoSpaceBeforeBinaryOperator", anyToken, binaryOperators, [ + isOptionDisabledOrUndefined("insertSpaceBeforeAndAfterBinaryOperators"), + isNonJsxSameLineTokenContext, + isBinaryOpContext, + ], RuleAction.DeleteSpace), + rule("NoSpaceAfterBinaryOperator", binaryOperators, anyToken, [ + isOptionDisabledOrUndefined("insertSpaceBeforeAndAfterBinaryOperators"), + isNonJsxSameLineTokenContext, + isBinaryOpContext, + ], RuleAction.DeleteSpace), - rule("SpaceBeforeOpenParenInFuncDecl", anyToken, SyntaxKind.OpenParenToken, [isOptionEnabled("insertSpaceBeforeFunctionParenthesis"), isNonJsxSameLineTokenContext, isFunctionDeclContext], RuleAction.InsertSpace), - rule("NoSpaceBeforeOpenParenInFuncDecl", anyToken, SyntaxKind.OpenParenToken, [isOptionDisabledOrUndefined("insertSpaceBeforeFunctionParenthesis"), isNonJsxSameLineTokenContext, isFunctionDeclContext], RuleAction.DeleteSpace), + rule("SpaceBeforeOpenParenInFuncDecl", anyToken, SyntaxKind.OpenParenToken, [ + isOptionEnabled("insertSpaceBeforeFunctionParenthesis"), + isNonJsxSameLineTokenContext, + isFunctionDeclContext, + ], RuleAction.InsertSpace), + rule("NoSpaceBeforeOpenParenInFuncDecl", anyToken, SyntaxKind.OpenParenToken, [ + isOptionDisabledOrUndefined("insertSpaceBeforeFunctionParenthesis"), + isNonJsxSameLineTokenContext, + isFunctionDeclContext, + ], RuleAction.DeleteSpace), // Open Brace braces after control block - rule("NewLineBeforeOpenBraceInControl", controlOpenBraceLeftTokenRange, SyntaxKind.OpenBraceToken, [isOptionEnabled("placeOpenBraceOnNewLineForControlBlocks"), isControlDeclContext, isBeforeMultilineBlockContext], RuleAction.InsertNewLine, RuleFlags.CanDeleteNewLines), + rule( + "NewLineBeforeOpenBraceInControl", + controlOpenBraceLeftTokenRange, + SyntaxKind.OpenBraceToken, + [ + isOptionEnabled("placeOpenBraceOnNewLineForControlBlocks"), + isControlDeclContext, + isBeforeMultilineBlockContext, + ], + RuleAction.InsertNewLine, + RuleFlags.CanDeleteNewLines, + ), // Open Brace braces after function // TypeScript: Function can have return types, which can be made of tons of different token kinds - rule("NewLineBeforeOpenBraceInFunction", functionOpenBraceLeftTokenRange, SyntaxKind.OpenBraceToken, [isOptionEnabled("placeOpenBraceOnNewLineForFunctions"), isFunctionDeclContext, isBeforeMultilineBlockContext], RuleAction.InsertNewLine, RuleFlags.CanDeleteNewLines), + rule( + "NewLineBeforeOpenBraceInFunction", + functionOpenBraceLeftTokenRange, + SyntaxKind.OpenBraceToken, + [ + isOptionEnabled("placeOpenBraceOnNewLineForFunctions"), + isFunctionDeclContext, + isBeforeMultilineBlockContext, + ], + RuleAction.InsertNewLine, + RuleFlags.CanDeleteNewLines, + ), // Open Brace braces after TypeScript module/class/interface - rule("NewLineBeforeOpenBraceInTypeScriptDeclWithBlock", typeScriptOpenBraceLeftTokenRange, SyntaxKind.OpenBraceToken, [isOptionEnabled("placeOpenBraceOnNewLineForFunctions"), isTypeScriptDeclWithBlockContext, isBeforeMultilineBlockContext], RuleAction.InsertNewLine, RuleFlags.CanDeleteNewLines), + rule( + "NewLineBeforeOpenBraceInTypeScriptDeclWithBlock", + typeScriptOpenBraceLeftTokenRange, + SyntaxKind.OpenBraceToken, + [ + isOptionEnabled("placeOpenBraceOnNewLineForFunctions"), + isTypeScriptDeclWithBlockContext, + isBeforeMultilineBlockContext, + ], + RuleAction.InsertNewLine, + RuleFlags.CanDeleteNewLines, + ), - rule("SpaceAfterTypeAssertion", SyntaxKind.GreaterThanToken, anyToken, [isOptionEnabled("insertSpaceAfterTypeAssertion"), isNonJsxSameLineTokenContext, isTypeAssertionContext], RuleAction.InsertSpace), - rule("NoSpaceAfterTypeAssertion", SyntaxKind.GreaterThanToken, anyToken, [isOptionDisabledOrUndefined("insertSpaceAfterTypeAssertion"), isNonJsxSameLineTokenContext, isTypeAssertionContext], RuleAction.DeleteSpace), + rule("SpaceAfterTypeAssertion", SyntaxKind.GreaterThanToken, anyToken, [ + isOptionEnabled("insertSpaceAfterTypeAssertion"), + isNonJsxSameLineTokenContext, + isTypeAssertionContext, + ], RuleAction.InsertSpace), + rule("NoSpaceAfterTypeAssertion", SyntaxKind.GreaterThanToken, anyToken, [ + isOptionDisabledOrUndefined("insertSpaceAfterTypeAssertion"), + isNonJsxSameLineTokenContext, + isTypeAssertionContext, + ], RuleAction.DeleteSpace), - rule("SpaceBeforeTypeAnnotation", anyToken, [SyntaxKind.QuestionToken, SyntaxKind.ColonToken], [isOptionEnabled("insertSpaceBeforeTypeAnnotation"), isNonJsxSameLineTokenContext, isTypeAnnotationContext], RuleAction.InsertSpace), - rule("NoSpaceBeforeTypeAnnotation", anyToken, [SyntaxKind.QuestionToken, SyntaxKind.ColonToken], [isOptionDisabledOrUndefined("insertSpaceBeforeTypeAnnotation"), isNonJsxSameLineTokenContext, isTypeAnnotationContext], RuleAction.DeleteSpace), + rule("SpaceBeforeTypeAnnotation", anyToken, [SyntaxKind.QuestionToken, SyntaxKind.ColonToken], [ + isOptionEnabled("insertSpaceBeforeTypeAnnotation"), + isNonJsxSameLineTokenContext, + isTypeAnnotationContext, + ], RuleAction.InsertSpace), + rule("NoSpaceBeforeTypeAnnotation", anyToken, [SyntaxKind.QuestionToken, SyntaxKind.ColonToken], [ + isOptionDisabledOrUndefined("insertSpaceBeforeTypeAnnotation"), + isNonJsxSameLineTokenContext, + isTypeAnnotationContext, + ], RuleAction.DeleteSpace), - rule("NoOptionalSemicolon", SyntaxKind.SemicolonToken, anyTokenIncludingEOF, [optionEquals("semicolons", SemicolonPreference.Remove), isSemicolonDeletionContext], RuleAction.DeleteToken), - rule("OptionalSemicolon", anyToken, anyTokenIncludingEOF, [optionEquals("semicolons", SemicolonPreference.Insert), isSemicolonInsertionContext], RuleAction.InsertTrailingSemicolon), + rule("NoOptionalSemicolon", SyntaxKind.SemicolonToken, anyTokenIncludingEOF, [ + optionEquals("semicolons", SemicolonPreference.Remove), + isSemicolonDeletionContext, + ], RuleAction.DeleteToken), + rule("OptionalSemicolon", anyToken, anyTokenIncludingEOF, [ + optionEquals("semicolons", SemicolonPreference.Insert), + isSemicolonInsertionContext, + ], RuleAction.InsertTrailingSemicolon), ]; // These rules are lower in priority than user-configurable. Rules earlier in this list have priority over rules later in the list. const lowPriorityCommonRules = [ // Space after keyword but not before ; or : or ? - rule("NoSpaceBeforeSemicolon", anyToken, SyntaxKind.SemicolonToken, [isNonJsxSameLineTokenContext], RuleAction.DeleteSpace), + rule( + "NoSpaceBeforeSemicolon", + anyToken, + SyntaxKind.SemicolonToken, + [isNonJsxSameLineTokenContext], + RuleAction.DeleteSpace, + ), - rule("SpaceBeforeOpenBraceInControl", controlOpenBraceLeftTokenRange, SyntaxKind.OpenBraceToken, [isOptionDisabledOrUndefinedOrTokensOnSameLine("placeOpenBraceOnNewLineForControlBlocks"), isControlDeclContext, isNotFormatOnEnter, isSameLineTokenOrBeforeBlockContext], RuleAction.InsertSpace, RuleFlags.CanDeleteNewLines), - rule("SpaceBeforeOpenBraceInFunction", functionOpenBraceLeftTokenRange, SyntaxKind.OpenBraceToken, [isOptionDisabledOrUndefinedOrTokensOnSameLine("placeOpenBraceOnNewLineForFunctions"), isFunctionDeclContext, isBeforeBlockContext, isNotFormatOnEnter, isSameLineTokenOrBeforeBlockContext], RuleAction.InsertSpace, RuleFlags.CanDeleteNewLines), - rule("SpaceBeforeOpenBraceInTypeScriptDeclWithBlock", typeScriptOpenBraceLeftTokenRange, SyntaxKind.OpenBraceToken, [isOptionDisabledOrUndefinedOrTokensOnSameLine("placeOpenBraceOnNewLineForFunctions"), isTypeScriptDeclWithBlockContext, isNotFormatOnEnter, isSameLineTokenOrBeforeBlockContext], RuleAction.InsertSpace, RuleFlags.CanDeleteNewLines), + rule( + "SpaceBeforeOpenBraceInControl", + controlOpenBraceLeftTokenRange, + SyntaxKind.OpenBraceToken, + [ + isOptionDisabledOrUndefinedOrTokensOnSameLine("placeOpenBraceOnNewLineForControlBlocks"), + isControlDeclContext, + isNotFormatOnEnter, + isSameLineTokenOrBeforeBlockContext, + ], + RuleAction.InsertSpace, + RuleFlags.CanDeleteNewLines, + ), + rule( + "SpaceBeforeOpenBraceInFunction", + functionOpenBraceLeftTokenRange, + SyntaxKind.OpenBraceToken, + [ + isOptionDisabledOrUndefinedOrTokensOnSameLine("placeOpenBraceOnNewLineForFunctions"), + isFunctionDeclContext, + isBeforeBlockContext, + isNotFormatOnEnter, + isSameLineTokenOrBeforeBlockContext, + ], + RuleAction.InsertSpace, + RuleFlags.CanDeleteNewLines, + ), + rule( + "SpaceBeforeOpenBraceInTypeScriptDeclWithBlock", + typeScriptOpenBraceLeftTokenRange, + SyntaxKind.OpenBraceToken, + [ + isOptionDisabledOrUndefinedOrTokensOnSameLine("placeOpenBraceOnNewLineForFunctions"), + isTypeScriptDeclWithBlockContext, + isNotFormatOnEnter, + isSameLineTokenOrBeforeBlockContext, + ], + RuleAction.InsertSpace, + RuleFlags.CanDeleteNewLines, + ), - rule("NoSpaceBeforeComma", anyToken, SyntaxKind.CommaToken, [isNonJsxSameLineTokenContext], RuleAction.DeleteSpace), + rule( + "NoSpaceBeforeComma", + anyToken, + SyntaxKind.CommaToken, + [isNonJsxSameLineTokenContext], + RuleAction.DeleteSpace, + ), // No space before and after indexer `x[]` - rule("NoSpaceBeforeOpenBracket", anyTokenExcept(SyntaxKind.AsyncKeyword, SyntaxKind.CaseKeyword), SyntaxKind.OpenBracketToken, [isNonJsxSameLineTokenContext], RuleAction.DeleteSpace), - rule("NoSpaceAfterCloseBracket", SyntaxKind.CloseBracketToken, anyToken, [isNonJsxSameLineTokenContext, isNotBeforeBlockInFunctionDeclarationContext], RuleAction.DeleteSpace), - rule("SpaceAfterSemicolon", SyntaxKind.SemicolonToken, anyToken, [isNonJsxSameLineTokenContext], RuleAction.InsertSpace), + rule( + "NoSpaceBeforeOpenBracket", + anyTokenExcept(SyntaxKind.AsyncKeyword, SyntaxKind.CaseKeyword), + SyntaxKind.OpenBracketToken, + [isNonJsxSameLineTokenContext], + RuleAction.DeleteSpace, + ), + rule("NoSpaceAfterCloseBracket", SyntaxKind.CloseBracketToken, anyToken, [ + isNonJsxSameLineTokenContext, + isNotBeforeBlockInFunctionDeclarationContext, + ], RuleAction.DeleteSpace), + rule( + "SpaceAfterSemicolon", + SyntaxKind.SemicolonToken, + anyToken, + [isNonJsxSameLineTokenContext], + RuleAction.InsertSpace, + ), // Remove extra space between for and await - rule("SpaceBetweenForAndAwaitKeyword", SyntaxKind.ForKeyword, SyntaxKind.AwaitKeyword, [isNonJsxSameLineTokenContext], RuleAction.InsertSpace), + rule("SpaceBetweenForAndAwaitKeyword", SyntaxKind.ForKeyword, SyntaxKind.AwaitKeyword, [ + isNonJsxSameLineTokenContext, + ], RuleAction.InsertSpace), // Add a space between statements. All keywords except (do,else,case) has open/close parens after them. // So, we have a rule to add a space for [),Any], [do,Any], [else,Any], and [case,Any] @@ -408,7 +964,13 @@ export function getAllRules(): RuleSpec[] { RuleAction.InsertSpace, ), // This low-pri rule takes care of "try {", "catch {" and "finally {" in case the rule SpaceBeforeOpenBraceInControl didn't execute on FormatOnEnter. - rule("SpaceAfterTryCatchFinally", [SyntaxKind.TryKeyword, SyntaxKind.CatchKeyword, SyntaxKind.FinallyKeyword], SyntaxKind.OpenBraceToken, [isNonJsxSameLineTokenContext], RuleAction.InsertSpace), + rule( + "SpaceAfterTryCatchFinally", + [SyntaxKind.TryKeyword, SyntaxKind.CatchKeyword, SyntaxKind.FinallyKeyword], + SyntaxKind.OpenBraceToken, + [isNonJsxSameLineTokenContext], + RuleAction.InsertSpace, + ), ]; return [ @@ -438,7 +1000,11 @@ function rule( action: RuleAction, flags: RuleFlags = RuleFlags.None, ): RuleSpec { - return { leftTokenRange: toTokenRange(left), rightTokenRange: toTokenRange(right), rule: { debugName, context, action, flags } }; + return { + leftTokenRange: toTokenRange(left), + rightTokenRange: toTokenRange(right), + rule: { debugName, context, action, flags }, + }; } function tokenRangeFrom(tokens: readonly SyntaxKind[]): TokenRange { @@ -463,7 +1029,10 @@ function tokenRangeFromRange(from: SyntaxKind, to: SyntaxKind, except: readonly /// Contexts /// -function optionEquals(optionName: K, optionValue: FormatCodeSettings[K]): (context: FormattingContext) => boolean { +function optionEquals( + optionName: K, + optionValue: FormatCodeSettings[K], +): (context: FormattingContext) => boolean { return context => context.options && context.options[optionName] === optionValue; } @@ -479,8 +1048,12 @@ function isOptionDisabledOrUndefined(optionName: keyof FormatCodeSettings): (con return context => !context.options || !hasProperty(context.options, optionName) || !context.options[optionName]; } -function isOptionDisabledOrUndefinedOrTokensOnSameLine(optionName: keyof FormatCodeSettings): (context: FormattingContext) => boolean { - return context => !context.options || !hasProperty(context.options, optionName) || !context.options[optionName] || context.TokensAreOnSameLine(); +function isOptionDisabledOrUndefinedOrTokensOnSameLine( + optionName: keyof FormatCodeSettings, +): (context: FormattingContext) => boolean { + return context => + !context.options || !hasProperty(context.options, optionName) || !context.options[optionName] + || context.TokensAreOnSameLine(); } function isOptionEnabledOrUndefined(optionName: keyof FormatCodeSettings): (context: FormattingContext) => boolean { @@ -530,16 +1103,21 @@ function isBinaryOpContext(context: FormattingContext): boolean { case SyntaxKind.EnumMember: case SyntaxKind.PropertyDeclaration: case SyntaxKind.PropertySignature: - return context.currentTokenSpan.kind === SyntaxKind.EqualsToken || context.nextTokenSpan.kind === SyntaxKind.EqualsToken; + return context.currentTokenSpan.kind === SyntaxKind.EqualsToken + || context.nextTokenSpan.kind === SyntaxKind.EqualsToken; // "in" keyword in for (let x in []) { } case SyntaxKind.ForInStatement: // "in" keyword in [P in keyof T]: T[P] // falls through case SyntaxKind.TypeParameter: - return context.currentTokenSpan.kind === SyntaxKind.InKeyword || context.nextTokenSpan.kind === SyntaxKind.InKeyword || context.currentTokenSpan.kind === SyntaxKind.EqualsToken || context.nextTokenSpan.kind === SyntaxKind.EqualsToken; + return context.currentTokenSpan.kind === SyntaxKind.InKeyword + || context.nextTokenSpan.kind === SyntaxKind.InKeyword + || context.currentTokenSpan.kind === SyntaxKind.EqualsToken + || context.nextTokenSpan.kind === SyntaxKind.EqualsToken; // Technically, "of" is not a binary operator, but format it the same way as "in" case SyntaxKind.ForOfStatement: - return context.currentTokenSpan.kind === SyntaxKind.OfKeyword || context.nextTokenSpan.kind === SyntaxKind.OfKeyword; + return context.currentTokenSpan.kind === SyntaxKind.OfKeyword + || context.nextTokenSpan.kind === SyntaxKind.OfKeyword; } return false; } @@ -554,16 +1132,16 @@ function isNotTypeAnnotationContext(context: FormattingContext): boolean { function isTypeAnnotationContext(context: FormattingContext): boolean { const contextKind = context.contextNode.kind; - return contextKind === SyntaxKind.PropertyDeclaration || - contextKind === SyntaxKind.PropertySignature || - contextKind === SyntaxKind.Parameter || - contextKind === SyntaxKind.VariableDeclaration || - isFunctionLikeKind(contextKind); + return contextKind === SyntaxKind.PropertyDeclaration + || contextKind === SyntaxKind.PropertySignature + || contextKind === SyntaxKind.Parameter + || contextKind === SyntaxKind.VariableDeclaration + || isFunctionLikeKind(contextKind); } function isConditionalOperatorContext(context: FormattingContext): boolean { - return context.contextNode.kind === SyntaxKind.ConditionalExpression || - context.contextNode.kind === SyntaxKind.ConditionalType; + return context.contextNode.kind === SyntaxKind.ConditionalExpression + || context.contextNode.kind === SyntaxKind.ConditionalType; } function isSameLineTokenOrBeforeBlockContext(context: FormattingContext): boolean { @@ -571,9 +1149,9 @@ function isSameLineTokenOrBeforeBlockContext(context: FormattingContext): boolea } function isBraceWrappedContext(context: FormattingContext): boolean { - return context.contextNode.kind === SyntaxKind.ObjectBindingPattern || - context.contextNode.kind === SyntaxKind.MappedType || - isSingleLineBlockContext(context); + return context.contextNode.kind === SyntaxKind.ObjectBindingPattern + || context.contextNode.kind === SyntaxKind.MappedType + || isSingleLineBlockContext(context); } // This check is done before an open brace in a control construct, a function, or a typescript block declaration @@ -646,7 +1224,8 @@ function isNotFunctionDeclContext(context: FormattingContext): boolean { } function isFunctionDeclarationOrFunctionExpressionContext(context: FormattingContext): boolean { - return context.contextNode.kind === SyntaxKind.FunctionDeclaration || context.contextNode.kind === SyntaxKind.FunctionExpression; + return context.contextNode.kind === SyntaxKind.FunctionDeclaration + || context.contextNode.kind === SyntaxKind.FunctionExpression; } function isTypeScriptDeclWithBlockContext(context: FormattingContext): boolean { @@ -683,7 +1262,10 @@ function isAfterCodeBlockContext(context: FormattingContext): boolean { case SyntaxKind.Block: { const blockParent = context.currentTokenParent.parent; // In a codefix scenario, we can't rely on parents being set. So just always return true. - if (!blockParent || blockParent.kind !== SyntaxKind.ArrowFunction && blockParent.kind !== SyntaxKind.FunctionExpression) { + if ( + !blockParent + || blockParent.kind !== SyntaxKind.ArrowFunction && blockParent.kind !== SyntaxKind.FunctionExpression + ) { return true; } } @@ -762,12 +1344,14 @@ function isNonJsxElementOrFragmentContext(context: FormattingContext): boolean { } function isJsxExpressionContext(context: FormattingContext): boolean { - return context.contextNode.kind === SyntaxKind.JsxExpression || context.contextNode.kind === SyntaxKind.JsxSpreadAttribute; + return context.contextNode.kind === SyntaxKind.JsxExpression + || context.contextNode.kind === SyntaxKind.JsxSpreadAttribute; } function isNextTokenParentJsxAttribute(context: FormattingContext): boolean { return context.nextTokenParent.kind === SyntaxKind.JsxAttribute || ( - context.nextTokenParent.kind === SyntaxKind.JsxNamespacedName && context.nextTokenParent.parent.kind === SyntaxKind.JsxAttribute + context.nextTokenParent.kind === SyntaxKind.JsxNamespacedName + && context.nextTokenParent.parent.kind === SyntaxKind.JsxAttribute ); } @@ -792,10 +1376,10 @@ function isNotBeforeBlockInFunctionDeclarationContext(context: FormattingContext } function isEndOfDecoratorContextOnSameLine(context: FormattingContext): boolean { - return context.TokensAreOnSameLine() && - hasDecorators(context.contextNode) && - nodeIsInDecoratorContext(context.currentTokenParent) && - !nodeIsInDecoratorContext(context.nextTokenParent); + return context.TokensAreOnSameLine() + && hasDecorators(context.contextNode) + && nodeIsInDecoratorContext(context.currentTokenParent) + && !nodeIsInDecoratorContext(context.nextTokenParent); } function nodeIsInDecoratorContext(node: Node): boolean { @@ -806,8 +1390,8 @@ function nodeIsInDecoratorContext(node: Node): boolean { } function isStartOfVariableDeclarationList(context: FormattingContext): boolean { - return context.currentTokenParent.kind === SyntaxKind.VariableDeclarationList && - context.currentTokenParent.getStart(context.sourceFile) === context.currentTokenSpan.pos; + return context.currentTokenParent.kind === SyntaxKind.VariableDeclarationList + && context.currentTokenParent.getStart(context.sourceFile) === context.currentTokenSpan.pos; } function isNotFormatOnEnter(context: FormattingContext): boolean { @@ -854,8 +1438,8 @@ function isTypeArgumentOrParameterOrAssertion(token: TextRangeWithKind, parent: } function isTypeArgumentOrParameterOrAssertionContext(context: FormattingContext): boolean { - return isTypeArgumentOrParameterOrAssertion(context.currentTokenSpan, context.currentTokenParent) || - isTypeArgumentOrParameterOrAssertion(context.nextTokenSpan, context.nextTokenParent); + return isTypeArgumentOrParameterOrAssertion(context.currentTokenSpan, context.currentTokenParent) + || isTypeArgumentOrParameterOrAssertion(context.nextTokenSpan, context.nextTokenParent); } function isTypeAssertionContext(context: FormattingContext): boolean { @@ -867,11 +1451,13 @@ function isNonTypeAssertionContext(context: FormattingContext): boolean { } function isVoidOpContext(context: FormattingContext): boolean { - return context.currentTokenSpan.kind === SyntaxKind.VoidKeyword && context.currentTokenParent.kind === SyntaxKind.VoidExpression; + return context.currentTokenSpan.kind === SyntaxKind.VoidKeyword + && context.currentTokenParent.kind === SyntaxKind.VoidExpression; } function isYieldOrYieldStarWithOperand(context: FormattingContext): boolean { - return context.contextNode.kind === SyntaxKind.YieldExpression && (context.contextNode as YieldExpression).expression !== undefined; + return context.contextNode.kind === SyntaxKind.YieldExpression + && (context.contextNode as YieldExpression).expression !== undefined; } function isNonNullAssertionContext(context: FormattingContext): boolean { @@ -923,15 +1509,15 @@ function isSemicolonDeletionContext(context: FormattingContext): boolean { } if ( - nextTokenKind === SyntaxKind.SemicolonClassElement || - nextTokenKind === SyntaxKind.SemicolonToken + nextTokenKind === SyntaxKind.SemicolonClassElement + || nextTokenKind === SyntaxKind.SemicolonToken ) { return false; } if ( - context.contextNode.kind === SyntaxKind.InterfaceDeclaration || - context.contextNode.kind === SyntaxKind.TypeAliasDeclaration + context.contextNode.kind === SyntaxKind.InterfaceDeclaration + || context.contextNode.kind === SyntaxKind.TypeAliasDeclaration ) { // Can't remove semicolon after `foo`; it would parse as a method declaration: // diff --git a/src/services/formatting/rulesMap.ts b/src/services/formatting/rulesMap.ts index 15ee6fa629043..9f13381cdbbdc 100644 --- a/src/services/formatting/rulesMap.ts +++ b/src/services/formatting/rulesMap.ts @@ -96,7 +96,10 @@ function buildMap(rules: readonly RuleSpec[]): readonly (readonly Rule[])[] { } function getRuleBucketIndex(row: number, column: number): number { - Debug.assert(row <= SyntaxKind.LastKeyword && column <= SyntaxKind.LastKeyword, "Must compute formatting context from tokens"); + Debug.assert( + row <= SyntaxKind.LastKeyword && column <= SyntaxKind.LastKeyword, + "Must compute formatting context from tokens", + ); return (row * mapRowLength) + column; } @@ -128,12 +131,18 @@ enum RulesPosition { // Example: // In order to insert a rule to the end of sub-bucket (3), we get the index by adding // the values in the bitmap segments 3rd, 2nd, and 1st. -function addRule(rules: Rule[], rule: Rule, specificTokens: boolean, constructionState: number[], rulesBucketIndex: number): void { - const position = rule.action & RuleAction.StopAction ? - specificTokens ? RulesPosition.StopRulesSpecific : RulesPosition.StopRulesAny : - rule.context !== anyContext ? - specificTokens ? RulesPosition.ContextRulesSpecific : RulesPosition.ContextRulesAny : - specificTokens ? RulesPosition.NoContextRulesSpecific : RulesPosition.NoContextRulesAny; +function addRule( + rules: Rule[], + rule: Rule, + specificTokens: boolean, + constructionState: number[], + rulesBucketIndex: number, +): void { + const position = rule.action & RuleAction.StopAction + ? specificTokens ? RulesPosition.StopRulesSpecific : RulesPosition.StopRulesAny + : rule.context !== anyContext + ? specificTokens ? RulesPosition.ContextRulesSpecific : RulesPosition.ContextRulesAny + : specificTokens ? RulesPosition.NoContextRulesSpecific : RulesPosition.NoContextRulesAny; const state = constructionState[rulesBucketIndex] || 0; rules.splice(getInsertionIndex(state, position), 0, rule); @@ -151,6 +160,9 @@ function getInsertionIndex(indexBitmap: number, maskPosition: RulesPosition) { function increaseInsertionIndex(indexBitmap: number, maskPosition: RulesPosition): number { const value = ((indexBitmap >> maskPosition) & mask) + 1; - Debug.assert((value & mask) === value, "Adding more rules into the sub-bucket than allowed. Maximum allowed is 32 rules."); + Debug.assert( + (value & mask) === value, + "Adding more rules into the sub-bucket than allowed. Maximum allowed is 32 rules.", + ); return (indexBitmap & ~(mask << maskPosition)) | (value << maskPosition); } diff --git a/src/services/formatting/smartIndenter.ts b/src/services/formatting/smartIndenter.ts index d2468b1b2e10b..a7a747cba48b3 100644 --- a/src/services/formatting/smartIndenter.ts +++ b/src/services/formatting/smartIndenter.ts @@ -79,7 +79,12 @@ export namespace SmartIndenter { * When inserting some text after an open brace, we would like to get indentation as if a newline was already there. * By default indentation at `position` will be 0 so 'assumeNewLineBeforeCloseBrace' overrides this behavior. */ - export function getIndentation(position: number, sourceFile: SourceFile, options: EditorSettings, assumeNewLineBeforeCloseBrace = false): number { + export function getIndentation( + position: number, + sourceFile: SourceFile, + options: EditorSettings, + assumeNewLineBeforeCloseBrace = false, + ): number { if (position > sourceFile.text.length) { return getBaseIndentation(options); // past EOF } @@ -104,7 +109,9 @@ export namespace SmartIndenter { // no indentation in string \regex\template literals const precedingTokenIsLiteral = isStringOrRegularExpressionOrTemplateLiteral(precedingToken.kind); - if (precedingTokenIsLiteral && precedingToken.getStart(sourceFile) <= position && position < precedingToken.end) { + if ( + precedingTokenIsLiteral && precedingToken.getStart(sourceFile) <= position && position < precedingToken.end + ) { return 0; } @@ -134,12 +141,15 @@ export namespace SmartIndenter { // y: undefined, // } // ``` - const isObjectLiteral = currentToken.kind === SyntaxKind.OpenBraceToken && currentToken.parent.kind === SyntaxKind.ObjectLiteralExpression; + const isObjectLiteral = currentToken.kind === SyntaxKind.OpenBraceToken + && currentToken.parent.kind === SyntaxKind.ObjectLiteralExpression; if (options.indentStyle === IndentStyle.Block || isObjectLiteral) { return getBlockIndent(sourceFile, position, options); } - if (precedingToken.kind === SyntaxKind.CommaToken && precedingToken.parent.kind !== SyntaxKind.BinaryExpression) { + if ( + precedingToken.kind === SyntaxKind.CommaToken && precedingToken.parent.kind !== SyntaxKind.BinaryExpression + ) { // previous token is comma that separates items in list - find the previous item and try to derive indentation from it const actualIndentation = getActualIndentationForListItemBeforeComma(precedingToken, sourceFile, options); if (actualIndentation !== Value.Unknown) { @@ -150,26 +160,49 @@ export namespace SmartIndenter { const containerList = getListByPosition(position, precedingToken.parent, sourceFile); // use list position if the preceding token is before any list items if (containerList && !rangeContainsRange(containerList, precedingToken)) { - const useTheSameBaseIndentation = [SyntaxKind.FunctionExpression, SyntaxKind.ArrowFunction].indexOf(currentToken.parent.kind) !== -1; + const useTheSameBaseIndentation = + [SyntaxKind.FunctionExpression, SyntaxKind.ArrowFunction].indexOf(currentToken.parent.kind) !== -1; const indentSize = useTheSameBaseIndentation ? 0 : options.indentSize!; return getActualIndentationForListStartLine(containerList, sourceFile, options) + indentSize; // TODO: GH#18217 } - return getSmartIndent(sourceFile, position, precedingToken, lineAtPosition, assumeNewLineBeforeCloseBrace, options); + return getSmartIndent( + sourceFile, + position, + precedingToken, + lineAtPosition, + assumeNewLineBeforeCloseBrace, + options, + ); } - function getCommentIndent(sourceFile: SourceFile, position: number, options: EditorSettings, enclosingCommentRange: CommentRange): number { + function getCommentIndent( + sourceFile: SourceFile, + position: number, + options: EditorSettings, + enclosingCommentRange: CommentRange, + ): number { const previousLine = getLineAndCharacterOfPosition(sourceFile, position).line - 1; const commentStartLine = getLineAndCharacterOfPosition(sourceFile, enclosingCommentRange.pos).line; Debug.assert(commentStartLine >= 0); if (previousLine <= commentStartLine) { - return findFirstNonWhitespaceColumn(getStartPositionOfLine(commentStartLine, sourceFile), position, sourceFile, options); + return findFirstNonWhitespaceColumn( + getStartPositionOfLine(commentStartLine, sourceFile), + position, + sourceFile, + options, + ); } const startPositionOfLine = getStartPositionOfLine(previousLine, sourceFile); - const { column, character } = findFirstNonWhitespaceCharacterAndColumn(startPositionOfLine, position, sourceFile, options); + const { column, character } = findFirstNonWhitespaceCharacterAndColumn( + startPositionOfLine, + position, + sourceFile, + options, + ); if (column === 0) { return column; @@ -195,28 +228,57 @@ export namespace SmartIndenter { return findFirstNonWhitespaceColumn(lineStart, current, sourceFile, options); } - function getSmartIndent(sourceFile: SourceFile, position: number, precedingToken: Node, lineAtPosition: number, assumeNewLineBeforeCloseBrace: boolean, options: EditorSettings): number { + function getSmartIndent( + sourceFile: SourceFile, + position: number, + precedingToken: Node, + lineAtPosition: number, + assumeNewLineBeforeCloseBrace: boolean, + options: EditorSettings, + ): number { // try to find node that can contribute to indentation and includes 'position' starting from 'precedingToken' // if such node is found - compute initial indentation for 'position' inside this node let previous: Node | undefined; let current = precedingToken; while (current) { - if (positionBelongsToNode(current, position, sourceFile) && shouldIndentChildNode(options, current, previous, sourceFile, /*isNextChild*/ true)) { + if ( + positionBelongsToNode(current, position, sourceFile) + && shouldIndentChildNode(options, current, previous, sourceFile, /*isNextChild*/ true) + ) { const currentStart = getStartLineAndCharacterForNode(current, sourceFile); - const nextTokenKind = nextTokenIsCurlyBraceOnSameLineAsCursor(precedingToken, current, lineAtPosition, sourceFile); + const nextTokenKind = nextTokenIsCurlyBraceOnSameLineAsCursor( + precedingToken, + current, + lineAtPosition, + sourceFile, + ); const indentationDelta = nextTokenKind !== NextTokenKind.Unknown // handle cases when codefix is about to be inserted before the close brace - ? assumeNewLineBeforeCloseBrace && nextTokenKind === NextTokenKind.CloseBrace ? options.indentSize : 0 + ? assumeNewLineBeforeCloseBrace && nextTokenKind === NextTokenKind.CloseBrace ? options.indentSize + : 0 : lineAtPosition !== currentStart.line ? options.indentSize : 0; - return getIndentationForNodeWorker(current, currentStart, /*ignoreActualIndentationRange*/ undefined, indentationDelta!, sourceFile, /*isNextChild*/ true, options); // TODO: GH#18217 + return getIndentationForNodeWorker( + current, + currentStart, + /*ignoreActualIndentationRange*/ undefined, + indentationDelta!, + sourceFile, + /*isNextChild*/ true, + options, + ); // TODO: GH#18217 } // check if current node is a list item - if yes, take indentation from it // do not consider parent-child line sharing yet: // function foo(a // | preceding node 'a' does share line with its parent but indentation is expected - const actualIndentation = getActualIndentationForListItem(current, sourceFile, options, /*listIndentsChild*/ true); + const actualIndentation = getActualIndentationForListItem( + current, + sourceFile, + options, + /*listIndentsChild*/ true, + ); if (actualIndentation !== Value.Unknown) { return actualIndentation; } @@ -228,9 +290,22 @@ export namespace SmartIndenter { return getBaseIndentation(options); } - export function getIndentationForNode(n: Node, ignoreActualIndentationRange: TextRange, sourceFile: SourceFile, options: EditorSettings): number { + export function getIndentationForNode( + n: Node, + ignoreActualIndentationRange: TextRange, + sourceFile: SourceFile, + options: EditorSettings, + ): number { const start = sourceFile.getLineAndCharacterOfPosition(n.getStart(sourceFile)); - return getIndentationForNodeWorker(n, start, ignoreActualIndentationRange, /*indentationDelta*/ 0, sourceFile, /*isNextChild*/ false, options); + return getIndentationForNodeWorker( + n, + start, + ignoreActualIndentationRange, + /*indentationDelta*/ 0, + sourceFile, + /*isNextChild*/ false, + options, + ); } export function getBaseIndentation(options: EditorSettings) { @@ -255,12 +330,13 @@ export namespace SmartIndenter { let useActualIndentation = true; if (ignoreActualIndentationRange) { const start = current.getStart(sourceFile); - useActualIndentation = start < ignoreActualIndentationRange.pos || start > ignoreActualIndentationRange.end; + useActualIndentation = start < ignoreActualIndentationRange.pos + || start > ignoreActualIndentationRange.end; } const containingListOrParentStart = getContainingListOrParentStart(parent, current, sourceFile); - const parentAndChildShareLine = containingListOrParentStart.line === currentStart.line || - childStartsOnTheSameLineWithElseInIfStatement(parent, current, currentStart.line, sourceFile); + const parentAndChildShareLine = containingListOrParentStart.line === currentStart.line + || childStartsOnTheSameLineWithElseInIfStatement(parent, current, currentStart.line, sourceFile); if (useActualIndentation) { // check if current node is a list item - if yes, take indentation from it @@ -281,14 +357,23 @@ export namespace SmartIndenter { // }, { itself contributes nothing. // prop: 1 L3 - The indentation of the second object literal is best understood by // }) looking at the relationship between the list and *first* list item. - const listIndentsChild = !!firstListChild && getStartLineAndCharacterForNode(firstListChild, sourceFile).line > containingListOrParentStart.line; + const listIndentsChild = !!firstListChild + && getStartLineAndCharacterForNode(firstListChild, sourceFile).line + > containingListOrParentStart.line; let actualIndentation = getActualIndentationForListItem(current, sourceFile, options, listIndentsChild); if (actualIndentation !== Value.Unknown) { return actualIndentation + indentationDelta; } // try to fetch actual indentation for current node from source text - actualIndentation = getActualIndentationForNode(current, parent, currentStart, parentAndChildShareLine, sourceFile, options); + actualIndentation = getActualIndentationForNode( + current, + parent, + currentStart, + parentAndChildShareLine, + sourceFile, + options, + ); if (actualIndentation !== Value.Unknown) { return actualIndentation + indentationDelta; } @@ -308,11 +393,17 @@ export namespace SmartIndenter { // Instead, when at an argument, we unspoof the starting position of the enclosing call expression // *after* applying indentation for the argument. - const useTrueStart = isArgumentAndStartLineOverlapsExpressionBeingCalled(parent, current, currentStart.line, sourceFile); + const useTrueStart = isArgumentAndStartLineOverlapsExpressionBeingCalled( + parent, + current, + currentStart.line, + sourceFile, + ); current = parent; parent = current.parent; - currentStart = useTrueStart ? sourceFile.getLineAndCharacterOfPosition(current.getStart(sourceFile)) : containingListOrParentStart; + currentStart = useTrueStart ? sourceFile.getLineAndCharacterOfPosition(current.getStart(sourceFile)) + : containingListOrParentStart; } return indentationDelta + getBaseIndentation(options); @@ -327,11 +418,20 @@ export namespace SmartIndenter { /* * Function returns Value.Unknown if indentation cannot be determined */ - function getActualIndentationForListItemBeforeComma(commaToken: Node, sourceFile: SourceFile, options: EditorSettings): number { + function getActualIndentationForListItemBeforeComma( + commaToken: Node, + sourceFile: SourceFile, + options: EditorSettings, + ): number { // previous token is comma that separates items in list - find the previous item and try to derive indentation from it const commaItemInfo = findListItemInfo(commaToken); if (commaItemInfo && commaItemInfo.listItemIndex > 0) { - return deriveActualIndentationFromList(commaItemInfo.list.getChildren(), commaItemInfo.listItemIndex - 1, sourceFile, options); + return deriveActualIndentationFromList( + commaItemInfo.list.getChildren(), + commaItemInfo.listItemIndex - 1, + sourceFile, + options, + ); } else { // handle broken code gracefully @@ -342,12 +442,19 @@ export namespace SmartIndenter { /* * Function returns Value.Unknown if actual indentation for node should not be used (i.e because node is nested expression) */ - function getActualIndentationForNode(current: Node, parent: Node, currentLineAndChar: LineAndCharacter, parentAndChildShareLine: boolean, sourceFile: SourceFile, options: EditorSettings): number { + function getActualIndentationForNode( + current: Node, + parent: Node, + currentLineAndChar: LineAndCharacter, + parentAndChildShareLine: boolean, + sourceFile: SourceFile, + options: EditorSettings, + ): number { // actual indentation is used for statements\declarations if one of cases below is true: // - parent is SourceFile - by default immediate children of SourceFile are not indented except when user indents them manually // - parent and child are not on the same line - const useActualIndentation = (isDeclaration(current) || isStatementButNotDeclaration(current)) && - (parent.kind === SyntaxKind.SourceFile || !parentAndChildShareLine); + const useActualIndentation = (isDeclaration(current) || isStatementButNotDeclaration(current)) + && (parent.kind === SyntaxKind.SourceFile || !parentAndChildShareLine); if (!useActualIndentation) { return Value.Unknown; @@ -362,7 +469,12 @@ export namespace SmartIndenter { CloseBrace, } - function nextTokenIsCurlyBraceOnSameLineAsCursor(precedingToken: Node, current: Node, lineAtPosition: number, sourceFile: SourceFile): NextTokenKind { + function nextTokenIsCurlyBraceOnSameLineAsCursor( + precedingToken: Node, + current: Node, + lineAtPosition: number, + sourceFile: SourceFile, + ): NextTokenKind { const nextToken = findNextToken(precedingToken, current, sourceFile); if (!nextToken) { return NextTokenKind.Unknown; @@ -393,17 +505,28 @@ export namespace SmartIndenter { return sourceFile.getLineAndCharacterOfPosition(n.getStart(sourceFile)); } - export function isArgumentAndStartLineOverlapsExpressionBeingCalled(parent: Node, child: Node, childStartLine: number, sourceFile: SourceFileLike): boolean { + export function isArgumentAndStartLineOverlapsExpressionBeingCalled( + parent: Node, + child: Node, + childStartLine: number, + sourceFile: SourceFileLike, + ): boolean { if (!(isCallExpression(parent) && contains(parent.arguments, child))) { return false; } const expressionOfCallExpressionEnd = parent.expression.getEnd(); - const expressionOfCallExpressionEndLine = getLineAndCharacterOfPosition(sourceFile, expressionOfCallExpressionEnd).line; + const expressionOfCallExpressionEndLine = + getLineAndCharacterOfPosition(sourceFile, expressionOfCallExpressionEnd).line; return expressionOfCallExpressionEndLine === childStartLine; } - export function childStartsOnTheSameLineWithElseInIfStatement(parent: Node, child: TextRangeWithKind, childStartLine: number, sourceFile: SourceFileLike): boolean { + export function childStartsOnTheSameLineWithElseInIfStatement( + parent: Node, + child: TextRangeWithKind, + childStartLine: number, + sourceFile: SourceFileLike, + ): boolean { if (parent.kind === SyntaxKind.IfStatement && (parent as IfStatement).elseStatement === child) { const elseKeyword = findChildOfKind(parent, SyntaxKind.ElseKeyword, sourceFile)!; Debug.assert(elseKeyword !== undefined); @@ -436,7 +559,12 @@ export namespace SmartIndenter { // whenTrue and whenFalse children to avoid double-indenting their contents. To identify this scenario, // we check for the whenTrue branch beginning on the line that the condition ends, and the whenFalse // branch beginning on the line that the whenTrue branch ends. - export function childIsUnindentedBranchOfConditionalExpression(parent: Node, child: TextRangeWithKind, childStartLine: number, sourceFile: SourceFileLike): boolean { + export function childIsUnindentedBranchOfConditionalExpression( + parent: Node, + child: TextRangeWithKind, + childStartLine: number, + sourceFile: SourceFileLike, + ): boolean { if (isConditionalExpression(parent) && (child === parent.whenTrue || child === parent.whenFalse)) { const conditionEndLine = getLineAndCharacterOfPosition(sourceFile, parent.condition.end).line; if (child === parent.whenTrue) { @@ -458,7 +586,12 @@ export namespace SmartIndenter { return false; } - export function argumentStartsOnSameLineAsPreviousArgument(parent: Node, child: TextRangeWithKind, childStartLine: number, sourceFile: SourceFileLike): boolean { + export function argumentStartsOnSameLineAsPreviousArgument( + parent: Node, + child: TextRangeWithKind, + childStartLine: number, + sourceFile: SourceFileLike, + ): boolean { if (isCallOrNewExpression(parent)) { if (!parent.arguments) return false; const currentNode = find(parent.arguments, arg => arg.pos === child.pos); @@ -486,7 +619,12 @@ export namespace SmartIndenter { return node && getListByRange(pos, pos, node, sourceFile); } - function getListByRange(start: number, end: number, node: Node, sourceFile: SourceFile): NodeArray | undefined { + function getListByRange( + start: number, + end: number, + node: Node, + sourceFile: SourceFile, + ): NodeArray | undefined { switch (node.kind) { case SyntaxKind.TypeReference: return getList((node as TypeReferenceNode).typeArguments); @@ -505,7 +643,8 @@ export namespace SmartIndenter { case SyntaxKind.Constructor: case SyntaxKind.ConstructorType: case SyntaxKind.ConstructSignature: - return getList((node as SignatureDeclaration).typeParameters) || getList((node as SignatureDeclaration).parameters); + return getList((node as SignatureDeclaration).typeParameters) + || getList((node as SignatureDeclaration).parameters); case SyntaxKind.GetAccessor: return getList((node as GetAccessorDeclaration).parameters); case SyntaxKind.ClassDeclaration: @@ -513,7 +652,14 @@ export namespace SmartIndenter { case SyntaxKind.InterfaceDeclaration: case SyntaxKind.TypeAliasDeclaration: case SyntaxKind.JSDocTemplateTag: - return getList((node as ClassDeclaration | ClassExpression | InterfaceDeclaration | TypeAliasDeclaration | JSDocTemplateTag).typeParameters); + return getList( + (node as + | ClassDeclaration + | ClassExpression + | InterfaceDeclaration + | TypeAliasDeclaration + | JSDocTemplateTag).typeParameters, + ); case SyntaxKind.NewExpression: case SyntaxKind.CallExpression: return getList((node as CallExpression).typeArguments) || getList((node as CallExpression).arguments); @@ -528,7 +674,8 @@ export namespace SmartIndenter { } function getList(list: NodeArray | undefined): NodeArray | undefined { - return list && rangeContainsStartEnd(getVisualListRange(node, list, sourceFile), start, end) ? list : undefined; + return list && rangeContainsStartEnd(getVisualListRange(node, list, sourceFile), start, end) ? list + : undefined; } } @@ -542,14 +689,27 @@ export namespace SmartIndenter { return list; } - function getActualIndentationForListStartLine(list: NodeArray, sourceFile: SourceFile, options: EditorSettings): number { + function getActualIndentationForListStartLine( + list: NodeArray, + sourceFile: SourceFile, + options: EditorSettings, + ): number { if (!list) { return Value.Unknown; } - return findColumnForFirstNonWhitespaceCharacterInLine(sourceFile.getLineAndCharacterOfPosition(list.pos), sourceFile, options); + return findColumnForFirstNonWhitespaceCharacterInLine( + sourceFile.getLineAndCharacterOfPosition(list.pos), + sourceFile, + options, + ); } - function getActualIndentationForListItem(node: Node, sourceFile: SourceFile, options: EditorSettings, listIndentsChild: boolean): number { + function getActualIndentationForListItem( + node: Node, + sourceFile: SourceFile, + options: EditorSettings, + listIndentsChild: boolean, + ): number { if (node.parent && node.parent.kind === SyntaxKind.VariableDeclarationList) { // VariableDeclarationList has no wrapping tokens return Value.Unknown; @@ -563,12 +723,18 @@ export namespace SmartIndenter { return result; } } - return getActualIndentationForListStartLine(containingList, sourceFile, options) + (listIndentsChild ? options.indentSize! : 0); // TODO: GH#18217 + return getActualIndentationForListStartLine(containingList, sourceFile, options) + + (listIndentsChild ? options.indentSize! : 0); // TODO: GH#18217 } return Value.Unknown; } - function deriveActualIndentationFromList(list: readonly Node[], index: number, sourceFile: SourceFile, options: EditorSettings): number { + function deriveActualIndentationFromList( + list: readonly Node[], + index: number, + sourceFile: SourceFile, + options: EditorSettings, + ): number { Debug.assert(index >= 0 && index < list.length); const node = list[index]; @@ -590,7 +756,11 @@ export namespace SmartIndenter { return Value.Unknown; } - function findColumnForFirstNonWhitespaceCharacterInLine(lineAndCharacter: LineAndCharacter, sourceFile: SourceFile, options: EditorSettings): number { + function findColumnForFirstNonWhitespaceCharacterInLine( + lineAndCharacter: LineAndCharacter, + sourceFile: SourceFile, + options: EditorSettings, + ): number { const lineStart = sourceFile.getPositionOfLineAndCharacter(lineAndCharacter.line, 0); return findFirstNonWhitespaceColumn(lineStart, lineStart + lineAndCharacter.character, sourceFile, options); } @@ -602,7 +772,12 @@ export namespace SmartIndenter { * value of 'character' for '$' is 3 * value of 'column' for '$' is 6 (assuming that tab size is 4) */ - export function findFirstNonWhitespaceCharacterAndColumn(startPos: number, endPos: number, sourceFile: SourceFileLike, options: EditorSettings) { + export function findFirstNonWhitespaceCharacterAndColumn( + startPos: number, + endPos: number, + sourceFile: SourceFileLike, + options: EditorSettings, + ) { let character = 0; let column = 0; for (let pos = startPos; pos < endPos; pos++) { @@ -623,11 +798,22 @@ export namespace SmartIndenter { return { column, character }; } - export function findFirstNonWhitespaceColumn(startPos: number, endPos: number, sourceFile: SourceFileLike, options: EditorSettings): number { + export function findFirstNonWhitespaceColumn( + startPos: number, + endPos: number, + sourceFile: SourceFileLike, + options: EditorSettings, + ): number { return findFirstNonWhitespaceCharacterAndColumn(startPos, endPos, sourceFile, options).column; } - export function nodeWillIndentChild(settings: FormatCodeSettings, parent: TextRangeWithKind, child: TextRangeWithKind | undefined, sourceFile: SourceFileLike | undefined, indentByDefault: boolean): boolean { + export function nodeWillIndentChild( + settings: FormatCodeSettings, + parent: TextRangeWithKind, + child: TextRangeWithKind | undefined, + sourceFile: SourceFileLike | undefined, + indentByDefault: boolean, + ): boolean { const childKind = child ? child.kind : SyntaxKind.Unknown; switch (parent.kind) { @@ -680,12 +866,20 @@ export namespace SmartIndenter { case SyntaxKind.VariableDeclaration: case SyntaxKind.PropertyAssignment: case SyntaxKind.BinaryExpression: - if (!settings.indentMultiLineObjectLiteralBeginningOnBlankLine && sourceFile && childKind === SyntaxKind.ObjectLiteralExpression) { // TODO: GH#18217 + if ( + !settings.indentMultiLineObjectLiteralBeginningOnBlankLine && sourceFile + && childKind === SyntaxKind.ObjectLiteralExpression + ) { // TODO: GH#18217 return rangeIsOnOneLine(sourceFile, child!); } - if (parent.kind === SyntaxKind.BinaryExpression && sourceFile && child && childKind === SyntaxKind.JsxElement) { - const parentStartLine = sourceFile.getLineAndCharacterOfPosition(skipTrivia(sourceFile.text, parent.pos)).line; - const childStartLine = sourceFile.getLineAndCharacterOfPosition(skipTrivia(sourceFile.text, child.pos)).line; + if ( + parent.kind === SyntaxKind.BinaryExpression && sourceFile && child + && childKind === SyntaxKind.JsxElement + ) { + const parentStartLine = + sourceFile.getLineAndCharacterOfPosition(skipTrivia(sourceFile.text, parent.pos)).line; + const childStartLine = + sourceFile.getLineAndCharacterOfPosition(skipTrivia(sourceFile.text, child.pos)).line; return parentStartLine !== childStartLine; } if (parent.kind !== SyntaxKind.BinaryExpression) { @@ -713,8 +907,9 @@ export namespace SmartIndenter { case SyntaxKind.ExportDeclaration: return childKind !== SyntaxKind.NamedExports; case SyntaxKind.ImportDeclaration: - return childKind !== SyntaxKind.ImportClause || - (!!(child as ImportClause).namedBindings && (child as ImportClause).namedBindings!.kind !== SyntaxKind.NamedImports); + return childKind !== SyntaxKind.ImportClause + || (!!(child as ImportClause).namedBindings + && (child as ImportClause).namedBindings!.kind !== SyntaxKind.NamedImports); case SyntaxKind.JsxElement: return childKind !== SyntaxKind.JsxClosingElement; case SyntaxKind.JsxFragment: @@ -746,7 +941,13 @@ export namespace SmartIndenter { * True when the parent node should indent the given child by an explicit rule. * @param isNextChild If true, we are judging indent of a hypothetical child *after* this one, not the current child. */ - export function shouldIndentChildNode(settings: FormatCodeSettings, parent: TextRangeWithKind, child?: Node, sourceFile?: SourceFileLike, isNextChild = false): boolean { + export function shouldIndentChildNode( + settings: FormatCodeSettings, + parent: TextRangeWithKind, + child?: Node, + sourceFile?: SourceFileLike, + isNextChild = false, + ): boolean { return nodeWillIndentChild(settings, parent, child, sourceFile, /*indentByDefault*/ false) && !(isNextChild && child && isControlFlowEndingStatement(child.kind, parent)); } diff --git a/src/services/getEditsForFileRename.ts b/src/services/getEditsForFileRename.ts index fdc4c1e412534..791541fd3f009 100644 --- a/src/services/getEditsForFileRename.ts +++ b/src/services/getEditsForFileRename.ts @@ -67,7 +67,15 @@ export function getEditsForFileRename( const oldToNew = getPathUpdater(oldFileOrDirPath, newFileOrDirPath, getCanonicalFileName, sourceMapper); const newToOld = getPathUpdater(newFileOrDirPath, oldFileOrDirPath, getCanonicalFileName, sourceMapper); return textChanges.ChangeTracker.with({ host, formatContext, preferences }, changeTracker => { - updateTsconfigFiles(program, changeTracker, oldToNew, oldFileOrDirPath, newFileOrDirPath, host.getCurrentDirectory(), useCaseSensitiveFileNames); + updateTsconfigFiles( + program, + changeTracker, + oldToNew, + oldFileOrDirPath, + newFileOrDirPath, + host.getCurrentDirectory(), + useCaseSensitiveFileNames, + ); updateImports(program, changeTracker, oldToNew, newToOld, host, getCanonicalFileName); }); } @@ -80,13 +88,19 @@ export function getEditsForFileRename( export type PathUpdater = (path: string) => string | undefined; // exported for tests /** @internal */ -export function getPathUpdater(oldFileOrDirPath: string, newFileOrDirPath: string, getCanonicalFileName: GetCanonicalFileName, sourceMapper: SourceMapper | undefined): PathUpdater { +export function getPathUpdater( + oldFileOrDirPath: string, + newFileOrDirPath: string, + getCanonicalFileName: GetCanonicalFileName, + sourceMapper: SourceMapper | undefined, +): PathUpdater { const canonicalOldPath = getCanonicalFileName(oldFileOrDirPath); return path => { const originalPath = sourceMapper && sourceMapper.tryGetSourcePosition({ fileName: path, pos: 0 }); const updatedPath = getUpdatedPath(originalPath ? originalPath.fileName : path); return originalPath - ? updatedPath === undefined ? undefined : makeCorrespondingRelativeChange(originalPath.fileName, updatedPath, path, getCanonicalFileName) + ? updatedPath === undefined ? undefined + : makeCorrespondingRelativeChange(originalPath.fileName, updatedPath, path, getCanonicalFileName) : updatedPath; }; @@ -98,12 +112,25 @@ export function getPathUpdater(oldFileOrDirPath: string, newFileOrDirPath: strin } // Relative path from a0 to b0 should be same as relative path from a1 to b1. Returns b1. -function makeCorrespondingRelativeChange(a0: string, b0: string, a1: string, getCanonicalFileName: GetCanonicalFileName): string { +function makeCorrespondingRelativeChange( + a0: string, + b0: string, + a1: string, + getCanonicalFileName: GetCanonicalFileName, +): string { const rel = getRelativePathFromFile(a0, b0, getCanonicalFileName); return combinePathsSafe(getDirectoryPath(a1), rel); } -function updateTsconfigFiles(program: Program, changeTracker: textChanges.ChangeTracker, oldToNew: PathUpdater, oldFileOrDirPath: string, newFileOrDirPath: string, currentDirectory: string, useCaseSensitiveFileNames: boolean): void { +function updateTsconfigFiles( + program: Program, + changeTracker: textChanges.ChangeTracker, + oldToNew: PathUpdater, + oldFileOrDirPath: string, + newFileOrDirPath: string, + currentDirectory: string, + useCaseSensitiveFileNames: boolean, +): void { const { configFile } = program.getCompilerOptions(); if (!configFile) return; const configDir = getDirectoryPath(configFile.fileName); @@ -117,16 +144,33 @@ function updateTsconfigFiles(program: Program, changeTracker: textChanges.Change case "include": case "exclude": { const foundExactMatch = updatePaths(property); - if (foundExactMatch || propertyName !== "include" || !isArrayLiteralExpression(property.initializer)) return; - const includes = mapDefined(property.initializer.elements, e => isStringLiteral(e) ? e.text : undefined); + if (foundExactMatch || propertyName !== "include" || !isArrayLiteralExpression(property.initializer)) { + return; + } + const includes = mapDefined( + property.initializer.elements, + e => isStringLiteral(e) ? e.text : undefined, + ); if (includes.length === 0) return; - const matchers = getFileMatcherPatterns(configDir, /*excludes*/ [], includes, useCaseSensitiveFileNames, currentDirectory); + const matchers = getFileMatcherPatterns( + configDir, + /*excludes*/ [], + includes, + useCaseSensitiveFileNames, + currentDirectory, + ); // If there isn't some include for this, add a new one. if ( - getRegexFromPattern(Debug.checkDefined(matchers.includeFilePattern), useCaseSensitiveFileNames).test(oldFileOrDirPath) && - !getRegexFromPattern(Debug.checkDefined(matchers.includeFilePattern), useCaseSensitiveFileNames).test(newFileOrDirPath) + getRegexFromPattern(Debug.checkDefined(matchers.includeFilePattern), useCaseSensitiveFileNames) + .test(oldFileOrDirPath) + && !getRegexFromPattern(Debug.checkDefined(matchers.includeFilePattern), useCaseSensitiveFileNames) + .test(newFileOrDirPath) ) { - changeTracker.insertNodeAfter(configFile, last(property.initializer.elements), factory.createStringLiteral(relativePath(newFileOrDirPath))); + changeTracker.insertNodeAfter( + configFile, + last(property.initializer.elements), + factory.createStringLiteral(relativePath(newFileOrDirPath)), + ); } return; } @@ -151,7 +195,8 @@ function updateTsconfigFiles(program: Program, changeTracker: textChanges.Change }); function updatePaths(property: PropertyAssignment): boolean { - const elements = isArrayLiteralExpression(property.initializer) ? property.initializer.elements : [property.initializer]; + const elements = isArrayLiteralExpression(property.initializer) ? property.initializer.elements + : [property.initializer]; let foundExactMatch = false; for (const element of elements) { foundExactMatch = tryUpdateString(element) || foundExactMatch; @@ -165,7 +210,11 @@ function updateTsconfigFiles(program: Program, changeTracker: textChanges.Change const updated = oldToNew(elementFileName); if (updated !== undefined) { - changeTracker.replaceRangeWithText(configFile!, createStringRange(element, configFile!), relativePath(updated)); + changeTracker.replaceRangeWithText( + configFile!, + createStringRange(element, configFile!), + relativePath(updated), + ); return true; } return false; @@ -200,21 +249,44 @@ function updateImports( if (!pathIsRelative(referenceText)) return undefined; const oldAbsolute = combinePathsSafe(oldImportFromDirectory, referenceText); const newAbsolute = oldToNew(oldAbsolute); - return newAbsolute === undefined ? undefined : ensurePathIsNonModuleName(getRelativePathFromDirectory(newImportFromDirectory, newAbsolute, getCanonicalFileName)); + return newAbsolute === undefined ? undefined + : ensurePathIsNonModuleName( + getRelativePathFromDirectory(newImportFromDirectory, newAbsolute, getCanonicalFileName), + ); }, importLiteral => { const importedModuleSymbol = program.getTypeChecker().getSymbolAtLocation(importLiteral); // No need to update if it's an ambient module^M - if (importedModuleSymbol?.declarations && importedModuleSymbol.declarations.some(d => isAmbientModule(d))) return undefined; + if (importedModuleSymbol?.declarations && importedModuleSymbol.declarations.some(d => isAmbientModule(d))) { + return undefined; + } const toImport = oldFromNew !== undefined // If we're at the new location (file was already renamed), need to redo module resolution starting from the old location. // TODO:GH#18217 - ? getSourceFileToImportFromResolved(importLiteral, resolveModuleName(importLiteral.text, oldImportFromPath, program.getCompilerOptions(), host as ModuleResolutionHost), oldToNew, allFiles) + ? getSourceFileToImportFromResolved( + importLiteral, + resolveModuleName( + importLiteral.text, + oldImportFromPath, + program.getCompilerOptions(), + host as ModuleResolutionHost, + ), + oldToNew, + allFiles, + ) : getSourceFileToImport(importedModuleSymbol, importLiteral, sourceFile, program, host, oldToNew); // Need an update if the imported file moved, or the importing file moved and was using a relative path. - return toImport !== undefined && (toImport.updated || (importingSourceFileMoved && pathIsRelative(importLiteral.text))) - ? moduleSpecifiers.updateModuleSpecifier(program.getCompilerOptions(), sourceFile, getCanonicalFileName(newImportFromPath) as Path, toImport.newFileName, createModuleSpecifierResolutionHost(program, host), importLiteral.text) + return toImport !== undefined + && (toImport.updated || (importingSourceFileMoved && pathIsRelative(importLiteral.text))) + ? moduleSpecifiers.updateModuleSpecifier( + program.getCompilerOptions(), + sourceFile, + getCanonicalFileName(newImportFromPath) as Path, + toImport.newFileName, + createModuleSpecifierResolutionHost(program, host), + importLiteral.text, + ) : undefined; }); } @@ -244,18 +316,29 @@ function getSourceFileToImport( // `find` should succeed because we checked for ambient modules before calling this function. const oldFileName = find(importedModuleSymbol.declarations, isSourceFile)!.fileName; const newFileName = oldToNew(oldFileName); - return newFileName === undefined ? { newFileName: oldFileName, updated: false } : { newFileName, updated: true }; + return newFileName === undefined ? { newFileName: oldFileName, updated: false } + : { newFileName, updated: true }; } else { const mode = getModeForUsageLocation(importingSourceFile, importLiteral); - const resolved = host.resolveModuleNameLiterals || !host.resolveModuleNames ? - importingSourceFile.resolvedModules?.get(importLiteral.text, mode) : - host.getResolvedModuleWithFailedLookupLocationsFromCache && host.getResolvedModuleWithFailedLookupLocationsFromCache(importLiteral.text, importingSourceFile.fileName, mode); + const resolved = host.resolveModuleNameLiterals || !host.resolveModuleNames + ? importingSourceFile.resolvedModules?.get(importLiteral.text, mode) + : host.getResolvedModuleWithFailedLookupLocationsFromCache + && host.getResolvedModuleWithFailedLookupLocationsFromCache( + importLiteral.text, + importingSourceFile.fileName, + mode, + ); return getSourceFileToImportFromResolved(importLiteral, resolved, oldToNew, program.getSourceFiles()); } } -function getSourceFileToImportFromResolved(importLiteral: StringLiteralLike, resolved: ResolvedModuleWithFailedLookupLocations | undefined, oldToNew: PathUpdater, sourceFiles: readonly SourceFile[]): ToImport | undefined { +function getSourceFileToImportFromResolved( + importLiteral: StringLiteralLike, + resolved: ResolvedModuleWithFailedLookupLocations | undefined, + oldToNew: PathUpdater, + sourceFiles: readonly SourceFile[], +): ToImport | undefined { // Search through all locations looking for a moved file, and only then test already existing files. // This is because if `a.ts` is compiled to `a.js` and `a.ts` is moved, we don't want to resolve anything to `a.js`, but to `a.ts`'s new location. if (!resolved) return undefined; @@ -270,7 +353,8 @@ function getSourceFileToImportFromResolved(importLiteral: StringLiteralLike, res const result = forEach(resolved.failedLookupLocations, tryChangeWithIgnoringPackageJsonExisting) // Then failed lookups except package.json since we dont want to touch them (only included ts/js files). // At this point, the confidence level of this fix being correct is too low to change bare specifiers or absolute paths. - || pathIsRelative(importLiteral.text) && forEach(resolved.failedLookupLocations, tryChangeWithIgnoringPackageJson); + || pathIsRelative(importLiteral.text) + && forEach(resolved.failedLookupLocations, tryChangeWithIgnoringPackageJson); if (result) return result; // If nothing changed, then result is resolved module file thats not updated @@ -292,15 +376,24 @@ function getSourceFileToImportFromResolved(importLiteral: StringLiteralLike, res } } -function updateImportsWorker(sourceFile: SourceFile, changeTracker: textChanges.ChangeTracker, updateRef: (refText: string) => string | undefined, updateImport: (importLiteral: StringLiteralLike) => string | undefined) { +function updateImportsWorker( + sourceFile: SourceFile, + changeTracker: textChanges.ChangeTracker, + updateRef: (refText: string) => string | undefined, + updateImport: (importLiteral: StringLiteralLike) => string | undefined, +) { for (const ref of sourceFile.referencedFiles || emptyArray) { // TODO: GH#26162 const updated = updateRef(ref.fileName); - if (updated !== undefined && updated !== sourceFile.text.slice(ref.pos, ref.end)) changeTracker.replaceRangeWithText(sourceFile, ref, updated); + if (updated !== undefined && updated !== sourceFile.text.slice(ref.pos, ref.end)) { + changeTracker.replaceRangeWithText(sourceFile, ref, updated); + } } for (const importStringLiteral of sourceFile.imports) { const updated = updateImport(importStringLiteral); - if (updated !== undefined && updated !== importStringLiteral.text) changeTracker.replaceRangeWithText(sourceFile, createStringRange(importStringLiteral, sourceFile), updated); + if (updated !== undefined && updated !== importStringLiteral.text) { + changeTracker.replaceRangeWithText(sourceFile, createStringRange(importStringLiteral, sourceFile), updated); + } } } diff --git a/src/services/goToDefinition.ts b/src/services/goToDefinition.ts index e622ed105d443..8e715092fc23d 100644 --- a/src/services/goToDefinition.ts +++ b/src/services/goToDefinition.ts @@ -106,9 +106,20 @@ import { } from "./_namespaces/ts"; /** @internal */ -export function getDefinitionAtPosition(program: Program, sourceFile: SourceFile, position: number, searchOtherFilesOnly?: boolean, stopAtAlias?: boolean): readonly DefinitionInfo[] | undefined { +export function getDefinitionAtPosition( + program: Program, + sourceFile: SourceFile, + position: number, + searchOtherFilesOnly?: boolean, + stopAtAlias?: boolean, +): readonly DefinitionInfo[] | undefined { const resolvedRef = getReferenceAtPosition(sourceFile, position, program); - const fileReferenceDefinition = resolvedRef && [getDefinitionInfoForFileReference(resolvedRef.reference.fileName, resolvedRef.fileName, resolvedRef.unverified)] || emptyArray; + const fileReferenceDefinition = resolvedRef + && [getDefinitionInfoForFileReference( + resolvedRef.reference.fileName, + resolvedRef.fileName, + resolvedRef.unverified, + )] || emptyArray; if (resolvedRef?.file) { // If `file` is missing, do a symbol-based lookup as well return fileReferenceDefinition; @@ -122,31 +133,52 @@ export function getDefinitionAtPosition(program: Program, sourceFile: SourceFile const { parent } = node; const typeChecker = program.getTypeChecker(); - if (node.kind === SyntaxKind.OverrideKeyword || (isIdentifier(node) && isJSDocOverrideTag(parent) && parent.tagName === node)) { + if ( + node.kind === SyntaxKind.OverrideKeyword + || (isIdentifier(node) && isJSDocOverrideTag(parent) && parent.tagName === node) + ) { return getDefinitionFromOverriddenMember(typeChecker, node) || emptyArray; } // Labels if (isJumpStatementTarget(node)) { const label = getTargetLabel(node.parent, node.text); - return label ? [createDefinitionInfoFromName(typeChecker, label, ScriptElementKind.label, node.text, /*containerName*/ undefined!)] : undefined; // TODO: GH#18217 + return label + ? [createDefinitionInfoFromName( + typeChecker, + label, + ScriptElementKind.label, + node.text, + /*containerName*/ undefined!, + )] : undefined; // TODO: GH#18217 } if (node.kind === SyntaxKind.ReturnKeyword) { - const functionDeclaration = findAncestor(node.parent, n => isClassStaticBlockDeclaration(n) ? "quit" : isFunctionLikeDeclaration(n)) as FunctionLikeDeclaration | undefined; - return functionDeclaration ? [createDefinitionFromSignatureDeclaration(typeChecker, functionDeclaration)] : undefined; + const functionDeclaration = findAncestor( + node.parent, + n => isClassStaticBlockDeclaration(n) ? "quit" : isFunctionLikeDeclaration(n), + ) as FunctionLikeDeclaration | undefined; + return functionDeclaration ? [createDefinitionFromSignatureDeclaration(typeChecker, functionDeclaration)] + : undefined; } if (node.kind === SyntaxKind.AwaitKeyword) { - const functionDeclaration = findAncestor(node, n => isFunctionLikeDeclaration(n)) as FunctionLikeDeclaration | undefined; - const isAsyncFunction = functionDeclaration && some(functionDeclaration.modifiers, node => node.kind === SyntaxKind.AsyncKeyword); - return isAsyncFunction ? [createDefinitionFromSignatureDeclaration(typeChecker, functionDeclaration)] : undefined; + const functionDeclaration = findAncestor(node, n => isFunctionLikeDeclaration(n)) as + | FunctionLikeDeclaration + | undefined; + const isAsyncFunction = functionDeclaration + && some(functionDeclaration.modifiers, node => node.kind === SyntaxKind.AsyncKeyword); + return isAsyncFunction ? [createDefinitionFromSignatureDeclaration(typeChecker, functionDeclaration)] + : undefined; } if (node.kind === SyntaxKind.YieldKeyword) { - const functionDeclaration = findAncestor(node, n => isFunctionLikeDeclaration(n)) as FunctionLikeDeclaration | undefined; + const functionDeclaration = findAncestor(node, n => isFunctionLikeDeclaration(n)) as + | FunctionLikeDeclaration + | undefined; const isGeneratorFunction = functionDeclaration && functionDeclaration.asteriskToken; - return isGeneratorFunction ? [createDefinitionFromSignatureDeclaration(typeChecker, functionDeclaration)] : undefined; + return isGeneratorFunction ? [createDefinitionFromSignatureDeclaration(typeChecker, functionDeclaration)] + : undefined; } if (isStaticModifier(node) && isClassStaticBlockDeclaration(node.parent)) { @@ -159,7 +191,16 @@ export function getDefinitionAtPosition(program: Program, sourceFile: SourceFile return map(staticBlocks, staticBlock => { let { pos } = moveRangePastModifiers(staticBlock); pos = skipTrivia(sourceFile.text, pos); - return createDefinitionInfoFromName(typeChecker, staticBlock, ScriptElementKind.constructorImplementationElement, "static {}", containerName, /*unverified*/ false, failedAliasResolution, { start: pos, length: "static".length }); + return createDefinitionInfoFromName( + typeChecker, + staticBlock, + ScriptElementKind.constructorImplementationElement, + "static {}", + containerName, + /*unverified*/ false, + failedAliasResolution, + { start: pos, length: "static".length }, + ); }); } @@ -168,7 +209,10 @@ export function getDefinitionAtPosition(program: Program, sourceFile: SourceFile if (searchOtherFilesOnly && failedAliasResolution) { // We couldn't resolve the specific import, try on the module specifier. - const importDeclaration = forEach([node, ...symbol?.declarations || emptyArray], n => findAncestor(n, isAnyImportOrBareOrAccessedRequire)); + const importDeclaration = forEach( + [node, ...symbol?.declarations || emptyArray], + n => findAncestor(n, isAnyImportOrBareOrAccessedRequire), + ); const moduleSpecifier = importDeclaration && tryGetModuleSpecifierFromDeclaration(importDeclaration); if (moduleSpecifier) { ({ symbol, failedAliasResolution } = getSymbol(moduleSpecifier, typeChecker, stopAtAlias)); @@ -179,7 +223,10 @@ export function getDefinitionAtPosition(program: Program, sourceFile: SourceFile if (!symbol && isModuleSpecifierLike(fallbackNode)) { // We couldn't resolve the module specifier as an external module, but it could // be that module resolution succeeded but the target was not a module. - const ref = sourceFile.resolvedModules?.get(fallbackNode.text, getModeForUsageLocation(sourceFile, fallbackNode))?.resolvedModule; + const ref = sourceFile.resolvedModules?.get( + fallbackNode.text, + getModeForUsageLocation(sourceFile, fallbackNode), + )?.resolvedModule; if (ref) { return [{ name: fallbackNode.text, @@ -201,7 +248,9 @@ export function getDefinitionAtPosition(program: Program, sourceFile: SourceFile return concatenate(fileReferenceDefinition, getDefinitionInfoForIndexSignatures(node, typeChecker)); } - if (searchOtherFilesOnly && every(symbol.declarations, d => d.getSourceFile().fileName === sourceFile.fileName)) return undefined; + if (searchOtherFilesOnly && every(symbol.declarations, d => d.getSourceFile().fileName === sourceFile.fileName)) { + return undefined; + } const calledDeclaration = tryGetSignatureDeclaration(typeChecker, node); // Don't go to the component constructor definition for a JSX element, just go to the component definition. @@ -213,7 +262,8 @@ export function getDefinitionAtPosition(program: Program, sourceFile: SourceFile return [sigInfo]; } else { - const defs = getDefinitionFromSymbol(typeChecker, symbol, node, failedAliasResolution, calledDeclaration) || emptyArray; + const defs = getDefinitionFromSymbol(typeChecker, symbol, node, failedAliasResolution, calledDeclaration) + || emptyArray; // For a 'super()' call, put the signature first, else put the variable first. return node.kind === SyntaxKind.SuperKeyword ? [sigInfo, ...defs] : [...defs, sigInfo]; } @@ -226,7 +276,9 @@ export function getDefinitionAtPosition(program: Program, sourceFile: SourceFile // assignment. This case and others are handled by the following code. if (node.parent.kind === SyntaxKind.ShorthandPropertyAssignment) { const shorthandSymbol = typeChecker.getShorthandAssignmentValueSymbol(symbol.valueDeclaration); - const definitions = shorthandSymbol?.declarations ? shorthandSymbol.declarations.map(decl => createDefinitionInfo(decl, typeChecker, shorthandSymbol, node, /*unverified*/ false, failedAliasResolution)) : emptyArray; + const definitions = shorthandSymbol?.declarations ? shorthandSymbol.declarations.map(decl => + createDefinitionInfo(decl, typeChecker, shorthandSymbol, node, /*unverified*/ false, failedAliasResolution) + ) : emptyArray; return concatenate(definitions, getDefinitionFromObjectLiteralElement(typeChecker, node)); } @@ -242,8 +294,8 @@ export function getDefinitionAtPosition(program: Program, sourceFile: SourceFile // } // bar(({pr/*goto*/op1})=>{}); if ( - isPropertyName(node) && isBindingElement(parent) && isObjectBindingPattern(parent.parent) && - (node === (parent.propertyName || parent.name)) + isPropertyName(node) && isBindingElement(parent) && isObjectBindingPattern(parent.parent) + && (node === (parent.propertyName || parent.name)) ) { const name = getNameFromPropertyName(node); const type = typeChecker.getTypeAtLocation(parent.parent); @@ -254,7 +306,11 @@ export function getDefinitionAtPosition(program: Program, sourceFile: SourceFile } const objectLiteralElementDefinition = getDefinitionFromObjectLiteralElement(typeChecker, node); - return concatenate(fileReferenceDefinition, objectLiteralElementDefinition.length ? objectLiteralElementDefinition : getDefinitionFromSymbol(typeChecker, symbol, node, failedAliasResolution)); + return concatenate( + fileReferenceDefinition, + objectLiteralElementDefinition.length ? objectLiteralElementDefinition + : getDefinitionFromSymbol(typeChecker, symbol, node, failedAliasResolution), + ); } /** @@ -266,7 +322,8 @@ function symbolMatchesSignature(s: Symbol, calledDeclaration: SignatureDeclarati return s === calledDeclaration.symbol || s === calledDeclaration.symbol.parent || isAssignmentExpression(calledDeclaration.parent) - || (!isCallLikeExpression(calledDeclaration.parent) && s === tryCast(calledDeclaration.parent, canHaveSymbol)?.symbol); + || (!isCallLikeExpression(calledDeclaration.parent) + && s === tryCast(calledDeclaration.parent, canHaveSymbol)?.symbol); } // If the current location we want to find its definition is in an object literal, try to get the contextual type for the @@ -283,7 +340,10 @@ function getDefinitionFromObjectLiteralElement(typeChecker: TypeChecker, node: N if (element) { const contextualType = element && typeChecker.getContextualType(element.parent); if (contextualType) { - return flatMap(getPropertySymbolsFromContextualType(element, typeChecker, contextualType, /*unionSymbolOk*/ false), propertySymbol => getDefinitionFromSymbol(typeChecker, propertySymbol, node)); + return flatMap( + getPropertySymbolsFromContextualType(element, typeChecker, contextualType, /*unionSymbolOk*/ false), + propertySymbol => getDefinitionFromSymbol(typeChecker, propertySymbol, node), + ); } } return emptyArray; @@ -312,7 +372,11 @@ function getDefinitionFromOverriddenMember(typeChecker: TypeChecker, node: Node) } /** @internal */ -export function getReferenceAtPosition(sourceFile: SourceFile, position: number, program: Program): { reference: FileReference; fileName: string; unverified: boolean; file?: SourceFile; } | undefined { +export function getReferenceAtPosition( + sourceFile: SourceFile, + position: number, + program: Program, +): { reference: FileReference; fileName: string; unverified: boolean; file?: SourceFile; } | undefined { const referencePath = findReferenceInPosition(sourceFile.referencedFiles, position); if (referencePath) { const file = program.getSourceFileFromReference(sourceFile, referencePath); @@ -321,7 +385,10 @@ export function getReferenceAtPosition(sourceFile: SourceFile, position: number, const typeReferenceDirective = findReferenceInPosition(sourceFile.typeReferenceDirectives, position); if (typeReferenceDirective) { - const reference = program.getResolvedTypeReferenceDirectives().get(typeReferenceDirective.fileName, typeReferenceDirective.resolutionMode || sourceFile.impliedNodeFormat)?.resolvedTypeReferenceDirective; + const reference = program.getResolvedTypeReferenceDirectives().get( + typeReferenceDirective.fileName, + typeReferenceDirective.resolutionMode || sourceFile.impliedNodeFormat, + )?.resolvedTypeReferenceDirective; const file = reference && program.getSourceFile(reference.resolvedFileName!); // TODO:GH#18217 return file && { reference: typeReferenceDirective, fileName: file.fileName, file, unverified: false }; } @@ -334,8 +401,14 @@ export function getReferenceAtPosition(sourceFile: SourceFile, position: number, if (sourceFile.resolvedModules?.size()) { const node = getTouchingToken(sourceFile, position); - if (isModuleSpecifierLike(node) && isExternalModuleNameRelative(node.text) && sourceFile.resolvedModules.has(node.text, getModeForUsageLocation(sourceFile, node))) { - const verifiedFileName = sourceFile.resolvedModules.get(node.text, getModeForUsageLocation(sourceFile, node))?.resolvedModule?.resolvedFileName; + if ( + isModuleSpecifierLike(node) && isExternalModuleNameRelative(node.text) + && sourceFile.resolvedModules.has(node.text, getModeForUsageLocation(sourceFile, node)) + ) { + const verifiedFileName = sourceFile.resolvedModules.get( + node.text, + getModeForUsageLocation(sourceFile, node), + )?.resolvedModule?.resolvedFileName; const fileName = verifiedFileName || resolvePath(getDirectoryPath(sourceFile.fileName), node.text); return { file: program.getSourceFile(fileName), @@ -375,12 +448,20 @@ const typesWithUnwrappedTypeArguments = new Set([ "Omit", ]); -function shouldUnwrapFirstTypeArgumentTypeDefinitionFromTypeReference(typeChecker: TypeChecker, type: TypeReference): boolean { +function shouldUnwrapFirstTypeArgumentTypeDefinitionFromTypeReference( + typeChecker: TypeChecker, + type: TypeReference, +): boolean { const referenceName = type.symbol.name; if (!typesWithUnwrappedTypeArguments.has(referenceName)) { return false; } - const globalType = typeChecker.resolveName(referenceName, /*location*/ undefined, SymbolFlags.Type, /*excludeGlobals*/ false); + const globalType = typeChecker.resolveName( + referenceName, + /*location*/ undefined, + SymbolFlags.Type, + /*excludeGlobals*/ false, + ); return !!globalType && globalType === type.target.symbol; } @@ -392,27 +473,53 @@ function shouldUnwrapFirstTypeArgumentTypeDefinitionFromAlias(typeChecker: TypeC if (!typesWithUnwrappedTypeArguments.has(referenceName)) { return false; } - const globalType = typeChecker.resolveName(referenceName, /*location*/ undefined, SymbolFlags.Type, /*excludeGlobals*/ false); + const globalType = typeChecker.resolveName( + referenceName, + /*location*/ undefined, + SymbolFlags.Type, + /*excludeGlobals*/ false, + ); return !!globalType && globalType === type.aliasSymbol; } -function getFirstTypeArgumentDefinitions(typeChecker: TypeChecker, type: Type, node: Node, failedAliasResolution: boolean | undefined): readonly DefinitionInfo[] { - if (!!(getObjectFlags(type) & ObjectFlags.Reference) && shouldUnwrapFirstTypeArgumentTypeDefinitionFromTypeReference(typeChecker, type as TypeReference)) { - return definitionFromType(typeChecker.getTypeArguments(type as TypeReference)[0], typeChecker, node, failedAliasResolution); +function getFirstTypeArgumentDefinitions( + typeChecker: TypeChecker, + type: Type, + node: Node, + failedAliasResolution: boolean | undefined, +): readonly DefinitionInfo[] { + if ( + !!(getObjectFlags(type) & ObjectFlags.Reference) + && shouldUnwrapFirstTypeArgumentTypeDefinitionFromTypeReference(typeChecker, type as TypeReference) + ) { + return definitionFromType( + typeChecker.getTypeArguments(type as TypeReference)[0], + typeChecker, + node, + failedAliasResolution, + ); } if (shouldUnwrapFirstTypeArgumentTypeDefinitionFromAlias(typeChecker, type) && type.aliasTypeArguments) { return definitionFromType(type.aliasTypeArguments[0], typeChecker, node, failedAliasResolution); } if ( - (getObjectFlags(type) & ObjectFlags.Mapped) && - (type as MappedType).target && - shouldUnwrapFirstTypeArgumentTypeDefinitionFromAlias(typeChecker, (type as MappedType).target!) + (getObjectFlags(type) & ObjectFlags.Mapped) + && (type as MappedType).target + && shouldUnwrapFirstTypeArgumentTypeDefinitionFromAlias(typeChecker, (type as MappedType).target!) ) { const declaration = type.aliasSymbol?.declarations?.[0]; - if (declaration && isTypeAliasDeclaration(declaration) && isTypeReferenceNode(declaration.type) && declaration.type.typeArguments) { - return definitionFromType(typeChecker.getTypeAtLocation(declaration.type.typeArguments[0]), typeChecker, node, failedAliasResolution); + if ( + declaration && isTypeAliasDeclaration(declaration) && isTypeReferenceNode(declaration.type) + && declaration.type.typeArguments + ) { + return definitionFromType( + typeChecker.getTypeAtLocation(declaration.type.typeArguments[0]), + typeChecker, + node, + failedAliasResolution, + ); } } @@ -421,14 +528,23 @@ function getFirstTypeArgumentDefinitions(typeChecker: TypeChecker, type: Type, n /// Goto type /** @internal */ -export function getTypeDefinitionAtPosition(typeChecker: TypeChecker, sourceFile: SourceFile, position: number): readonly DefinitionInfo[] | undefined { +export function getTypeDefinitionAtPosition( + typeChecker: TypeChecker, + sourceFile: SourceFile, + position: number, +): readonly DefinitionInfo[] | undefined { const node = getTouchingPropertyName(sourceFile, position); if (node === sourceFile) { return undefined; } if (isImportMeta(node.parent) && node.parent.name === node) { - return definitionFromType(typeChecker.getTypeAtLocation(node.parent), typeChecker, node.parent, /*failedAliasResolution*/ false); + return definitionFromType( + typeChecker.getTypeAtLocation(node.parent), + typeChecker, + node.parent, + /*failedAliasResolution*/ false, + ); } const { symbol, failedAliasResolution } = getSymbol(node, typeChecker, /*stopAtAlias*/ false); if (!symbol) return undefined; @@ -438,26 +554,40 @@ export function getTypeDefinitionAtPosition(typeChecker: TypeChecker, sourceFile const fromReturnType = returnType && definitionFromType(returnType, typeChecker, node, failedAliasResolution); // If a function returns 'void' or some other type with no definition, just return the function definition. - const [resolvedType, typeDefinitions] = fromReturnType && fromReturnType.length !== 0 ? - [returnType, fromReturnType] : - [typeAtLocation, definitionFromType(typeAtLocation, typeChecker, node, failedAliasResolution)]; - - return typeDefinitions.length ? [...getFirstTypeArgumentDefinitions(typeChecker, resolvedType, node, failedAliasResolution), ...typeDefinitions] - : !(symbol.flags & SymbolFlags.Value) && symbol.flags & SymbolFlags.Type ? getDefinitionFromSymbol(typeChecker, skipAlias(symbol, typeChecker), node, failedAliasResolution) + const [resolvedType, typeDefinitions] = fromReturnType && fromReturnType.length !== 0 + ? [returnType, fromReturnType] + : [typeAtLocation, definitionFromType(typeAtLocation, typeChecker, node, failedAliasResolution)]; + + return typeDefinitions.length + ? [ + ...getFirstTypeArgumentDefinitions(typeChecker, resolvedType, node, failedAliasResolution), + ...typeDefinitions, + ] + : !(symbol.flags & SymbolFlags.Value) && symbol.flags & SymbolFlags.Type + ? getDefinitionFromSymbol(typeChecker, skipAlias(symbol, typeChecker), node, failedAliasResolution) : undefined; } -function definitionFromType(type: Type, checker: TypeChecker, node: Node, failedAliasResolution: boolean | undefined): readonly DefinitionInfo[] { - return flatMap(type.isUnion() && !(type.flags & TypeFlags.Enum) ? type.types : [type], t => t.symbol && getDefinitionFromSymbol(checker, t.symbol, node, failedAliasResolution)); +function definitionFromType( + type: Type, + checker: TypeChecker, + node: Node, + failedAliasResolution: boolean | undefined, +): readonly DefinitionInfo[] { + return flatMap( + type.isUnion() && !(type.flags & TypeFlags.Enum) ? type.types : [type], + t => t.symbol && getDefinitionFromSymbol(checker, t.symbol, node, failedAliasResolution), + ); } function tryGetReturnTypeOfFunction(symbol: Symbol, type: Type, checker: TypeChecker): Type | undefined { // If the type is just a function's inferred type, // go-to-type should go to the return type instead, since go-to-definition takes you to the function anyway. if ( - type.symbol === symbol || + type.symbol === symbol // At `const f = () => {}`, the symbol is `f` and the type symbol is at `() => {}` - symbol.valueDeclaration && type.symbol && isVariableDeclaration(symbol.valueDeclaration) && symbol.valueDeclaration.initializer === type.symbol.valueDeclaration as Node + || symbol.valueDeclaration && type.symbol && isVariableDeclaration(symbol.valueDeclaration) + && symbol.valueDeclaration.initializer === type.symbol.valueDeclaration as Node ) { const sigs = type.getCallSignatures(); if (sigs.length === 1) return checker.getReturnTypeOfSignature(first(sigs)); @@ -466,7 +596,11 @@ function tryGetReturnTypeOfFunction(symbol: Symbol, type: Type, checker: TypeChe } /** @internal */ -export function getDefinitionAndBoundSpan(program: Program, sourceFile: SourceFile, position: number): DefinitionInfoAndBoundSpan | undefined { +export function getDefinitionAndBoundSpan( + program: Program, + sourceFile: SourceFile, + position: number, +): DefinitionInfoAndBoundSpan | undefined { const definitions = getDefinitionAtPosition(program, sourceFile, position); if (!definitions || definitions.length === 0) { @@ -474,9 +608,9 @@ export function getDefinitionAndBoundSpan(program: Program, sourceFile: SourceFi } // Check if position is on triple slash reference. - const comment = findReferenceInPosition(sourceFile.referencedFiles, position) || - findReferenceInPosition(sourceFile.typeReferenceDirectives, position) || - findReferenceInPosition(sourceFile.libReferenceDirectives, position); + const comment = findReferenceInPosition(sourceFile.referencedFiles, position) + || findReferenceInPosition(sourceFile.typeReferenceDirectives, position) + || findReferenceInPosition(sourceFile.libReferenceDirectives, position); if (comment) { return { definitions, textSpan: createTextSpanFromRange(comment) }; @@ -490,7 +624,10 @@ export function getDefinitionAndBoundSpan(program: Program, sourceFile: SourceFi // At 'x.foo', see if the type of 'x' has an index signature, and if so find its declarations. function getDefinitionInfoForIndexSignatures(node: Node, checker: TypeChecker): DefinitionInfo[] | undefined { - return mapDefined(checker.getIndexInfosAtLocation(node), info => info.declaration && createDefinitionFromSignatureDeclaration(checker, info.declaration)); + return mapDefined( + checker.getIndexInfosAtLocation(node), + info => info.declaration && createDefinitionFromSignatureDeclaration(checker, info.declaration), + ); } function getSymbol(node: Node, checker: TypeChecker, stopAtAlias: boolean | undefined) { @@ -500,7 +637,10 @@ function getSymbol(node: Node, checker: TypeChecker, stopAtAlias: boolean | unde // import {A, B} from "mod"; // to jump to the implementation directly. let failedAliasResolution = false; - if (symbol?.declarations && symbol.flags & SymbolFlags.Alias && !stopAtAlias && shouldSkipAlias(node, symbol.declarations[0])) { + if ( + symbol?.declarations && symbol.flags & SymbolFlags.Alias && !stopAtAlias + && shouldSkipAlias(node, symbol.declarations[0]) + ) { const aliased = checker.getAliasedSymbol(symbol); if (aliased.declarations) { return { symbol: aliased }; @@ -554,20 +694,43 @@ function isExpandoDeclaration(node: Declaration): boolean { if (!isAssignmentDeclaration(p as Declaration)) return "quit"; return false; }) as AssignmentExpression | undefined; - return !!containingAssignment && getAssignmentDeclarationKind(containingAssignment) === AssignmentDeclarationKind.Property; + return !!containingAssignment + && getAssignmentDeclarationKind(containingAssignment) === AssignmentDeclarationKind.Property; } -function getDefinitionFromSymbol(typeChecker: TypeChecker, symbol: Symbol, node: Node, failedAliasResolution?: boolean, excludeDeclaration?: Node): DefinitionInfo[] | undefined { +function getDefinitionFromSymbol( + typeChecker: TypeChecker, + symbol: Symbol, + node: Node, + failedAliasResolution?: boolean, + excludeDeclaration?: Node, +): DefinitionInfo[] | undefined { const filteredDeclarations = filter(symbol.declarations, d => d !== excludeDeclaration); const withoutExpandos = filter(filteredDeclarations, d => !isExpandoDeclaration(d)); const results = some(withoutExpandos) ? withoutExpandos : filteredDeclarations; - return getConstructSignatureDefinition() || getCallSignatureDefinition() || map(results, declaration => createDefinitionInfo(declaration, typeChecker, symbol, node, /*unverified*/ false, failedAliasResolution)); + return getConstructSignatureDefinition() || getCallSignatureDefinition() + || map( + results, + declaration => + createDefinitionInfo( + declaration, + typeChecker, + symbol, + node, + /*unverified*/ false, + failedAliasResolution, + ), + ); function getConstructSignatureDefinition(): DefinitionInfo[] | undefined { // Applicable only if we are in a new expression, or we are on a constructor declaration // and in either case the symbol has a construct signature definition, i.e. class - if (symbol.flags & SymbolFlags.Class && !(symbol.flags & (SymbolFlags.Function | SymbolFlags.Variable)) && (isNewExpressionTarget(node) || node.kind === SyntaxKind.ConstructorKeyword)) { - const cls = find(filteredDeclarations, isClassLike) || Debug.fail("Expected declaration to have at least one class-like declaration"); + if ( + symbol.flags & SymbolFlags.Class && !(symbol.flags & (SymbolFlags.Function | SymbolFlags.Variable)) + && (isNewExpressionTarget(node) || node.kind === SyntaxKind.ConstructorKeyword) + ) { + const cls = find(filteredDeclarations, isClassLike) + || Debug.fail("Expected declaration to have at least one class-like declaration"); return getSignatureDefinition(cls.members, /*selectConstructors*/ true); } } @@ -578,18 +741,30 @@ function getDefinitionFromSymbol(typeChecker: TypeChecker, symbol: Symbol, node: : undefined; } - function getSignatureDefinition(signatureDeclarations: readonly Declaration[] | undefined, selectConstructors: boolean): DefinitionInfo[] | undefined { + function getSignatureDefinition( + signatureDeclarations: readonly Declaration[] | undefined, + selectConstructors: boolean, + ): DefinitionInfo[] | undefined { if (!signatureDeclarations) { return undefined; } - const declarations = signatureDeclarations.filter(selectConstructors ? isConstructorDeclaration : isFunctionLike); + const declarations = signatureDeclarations.filter( + selectConstructors ? isConstructorDeclaration : isFunctionLike, + ); const declarationsWithBody = declarations.filter(d => !!(d as FunctionLikeDeclaration).body); // declarations defined on the global scope can be defined on multiple files. Get all of them. return declarations.length ? declarationsWithBody.length !== 0 ? declarationsWithBody.map(x => createDefinitionInfo(x, typeChecker, symbol, node)) - : [createDefinitionInfo(last(declarations), typeChecker, symbol, node, /*unverified*/ false, failedAliasResolution)] + : [createDefinitionInfo( + last(declarations), + typeChecker, + symbol, + node, + /*unverified*/ false, + failedAliasResolution, + )] : undefined; } } @@ -599,15 +774,39 @@ function getDefinitionFromSymbol(typeChecker: TypeChecker, symbol: Symbol, node: * * @internal */ -export function createDefinitionInfo(declaration: Declaration, checker: TypeChecker, symbol: Symbol, node: Node, unverified?: boolean, failedAliasResolution?: boolean): DefinitionInfo { +export function createDefinitionInfo( + declaration: Declaration, + checker: TypeChecker, + symbol: Symbol, + node: Node, + unverified?: boolean, + failedAliasResolution?: boolean, +): DefinitionInfo { const symbolName = checker.symbolToString(symbol); // Do not get scoped name, just the name of the symbol const symbolKind = SymbolDisplay.getSymbolKind(checker, symbol, node); const containerName = symbol.parent ? checker.symbolToString(symbol.parent, node) : ""; - return createDefinitionInfoFromName(checker, declaration, symbolKind, symbolName, containerName, unverified, failedAliasResolution); + return createDefinitionInfoFromName( + checker, + declaration, + symbolKind, + symbolName, + containerName, + unverified, + failedAliasResolution, + ); } /** Creates a DefinitionInfo directly from the name of a declaration. */ -function createDefinitionInfoFromName(checker: TypeChecker, declaration: Declaration, symbolKind: ScriptElementKind, symbolName: string, containerName: string, unverified?: boolean, failedAliasResolution?: boolean, textSpan?: TextSpan): DefinitionInfo { +function createDefinitionInfoFromName( + checker: TypeChecker, + declaration: Declaration, + symbolKind: ScriptElementKind, + symbolName: string, + containerName: string, + unverified?: boolean, + failedAliasResolution?: boolean, + textSpan?: TextSpan, +): DefinitionInfo { const sourceFile = declaration.getSourceFile(); if (!textSpan) { const name = getNameOfDeclaration(declaration) || declaration; @@ -637,7 +836,9 @@ function isDefinitionVisible(checker: TypeChecker, declaration: Declaration): bo if (!declaration.parent) return false; // Variable initializers are visible if variable is visible - if (hasInitializer(declaration.parent) && declaration.parent.initializer === declaration) return isDefinitionVisible(checker, declaration.parent as Declaration); + if (hasInitializer(declaration.parent) && declaration.parent.initializer === declaration) { + return isDefinitionVisible(checker, declaration.parent as Declaration); + } // Handle some exceptions here like arrow function, members of class and object literal expression which are technically not visible but we want the definition to be determined by its parent switch (declaration.kind) { @@ -663,7 +864,11 @@ function isDefinitionVisible(checker: TypeChecker, declaration: Declaration): bo } } -function createDefinitionFromSignatureDeclaration(typeChecker: TypeChecker, decl: SignatureDeclaration, failedAliasResolution?: boolean): DefinitionInfo { +function createDefinitionFromSignatureDeclaration( + typeChecker: TypeChecker, + decl: SignatureDeclaration, + failedAliasResolution?: boolean, +): DefinitionInfo { return createDefinitionInfo(decl, typeChecker, decl.symbol, decl, /*unverified*/ false, failedAliasResolution); } @@ -688,14 +893,18 @@ function getDefinitionInfoForFileReference(name: string, targetFileName: string, function getAncestorCallLikeExpression(node: Node): CallLikeExpression | undefined { const target = findAncestor(node, n => !isRightSideOfPropertyAccess(n)); const callLike = target?.parent; - return callLike && isCallLikeExpression(callLike) && getInvokedExpression(callLike) === target ? callLike : undefined; + return callLike && isCallLikeExpression(callLike) && getInvokedExpression(callLike) === target ? callLike + : undefined; } function tryGetSignatureDeclaration(typeChecker: TypeChecker, node: Node): SignatureDeclaration | undefined { const callLike = getAncestorCallLikeExpression(node); const signature = callLike && typeChecker.getResolvedSignature(callLike); // Don't go to a function type, go to the value having that type. - return tryCast(signature && signature.declaration, (d): d is SignatureDeclaration => isFunctionLike(d) && !isFunctionTypeNode(d)); + return tryCast( + signature && signature.declaration, + (d): d is SignatureDeclaration => isFunctionLike(d) && !isFunctionTypeNode(d), + ); } function isConstructorLike(node: Node): boolean { diff --git a/src/services/importTracker.ts b/src/services/importTracker.ts index b0e7215625e12..64ef963978d49 100644 --- a/src/services/importTracker.ts +++ b/src/services/importTracker.ts @@ -102,11 +102,26 @@ export type ImportTracker = (exportSymbol: Symbol, exportInfo: ExportInfo, isFor * * @internal */ -export function createImportTracker(sourceFiles: readonly SourceFile[], sourceFilesSet: ReadonlySet, checker: TypeChecker, cancellationToken: CancellationToken | undefined): ImportTracker { +export function createImportTracker( + sourceFiles: readonly SourceFile[], + sourceFilesSet: ReadonlySet, + checker: TypeChecker, + cancellationToken: CancellationToken | undefined, +): ImportTracker { const allDirectImports = getDirectImportsMap(sourceFiles, checker, cancellationToken); return (exportSymbol, exportInfo, isForRename) => { - const { directImports, indirectUsers } = getImportersForExport(sourceFiles, sourceFilesSet, allDirectImports, exportInfo, checker, cancellationToken); - return { indirectUsers, ...getSearchesFromDirectImports(directImports, exportSymbol, exportInfo.exportKind, checker, isForRename) }; + const { directImports, indirectUsers } = getImportersForExport( + sourceFiles, + sourceFilesSet, + allDirectImports, + exportInfo, + checker, + cancellationToken, + ); + return { + indirectUsers, + ...getSearchesFromDirectImports(directImports, exportSymbol, exportInfo.exportKind, checker, isForRename), + }; }; } @@ -197,7 +212,9 @@ function getImportersForExport( } if (!isAvailableThroughGlobal) { const parent = direct.parent; - if (exportKind === ExportKind.ExportEquals && parent.kind === SyntaxKind.VariableDeclaration) { + if ( + exportKind === ExportKind.ExportEquals && parent.kind === SyntaxKind.VariableDeclaration + ) { const { name } = parent as VariableDeclaration; if (name.kind === SyntaxKind.Identifier) { directImports.push(name); @@ -211,14 +228,24 @@ function getImportersForExport( break; // TODO: GH#23879 case SyntaxKind.ImportEqualsDeclaration: - handleNamespaceImport(direct, direct.name, hasSyntacticModifier(direct, ModifierFlags.Export), /*alreadyAddedDirect*/ false); + handleNamespaceImport( + direct, + direct.name, + hasSyntacticModifier(direct, ModifierFlags.Export), + /*alreadyAddedDirect*/ false, + ); break; case SyntaxKind.ImportDeclaration: directImports.push(direct); const namedBindings = direct.importClause && direct.importClause.namedBindings; if (namedBindings && namedBindings.kind === SyntaxKind.NamespaceImport) { - handleNamespaceImport(direct, namedBindings.name, /*isReExport*/ false, /*alreadyAddedDirect*/ true); + handleNamespaceImport( + direct, + namedBindings.name, + /*isReExport*/ false, + /*alreadyAddedDirect*/ true, + ); } else if (!isAvailableThroughGlobal && isDefaultImport(direct)) { addIndirectUser(getSourceFileLikeForImportDeclaration(direct)); // Add a check for indirect uses to handle synthetic default imports @@ -232,7 +259,10 @@ function getImportersForExport( } else if (direct.exportClause.kind === SyntaxKind.NamespaceExport) { // `export * as foo from "foo"` add to indirect uses - addIndirectUser(getSourceFileLikeForImportDeclaration(direct), /*addTransitiveDependencies*/ true); + addIndirectUser( + getSourceFileLikeForImportDeclaration(direct), + /*addTransitiveDependencies*/ true, + ); } else { // This is `export { foo } from "foo"` and creates an alias symbol, so recursive search will get handle re-exports. @@ -267,14 +297,21 @@ function getImportersForExport( }); } - function handleNamespaceImport(importDeclaration: ImportEqualsDeclaration | ImportDeclaration, name: Identifier, isReExport: boolean, alreadyAddedDirect: boolean): void { + function handleNamespaceImport( + importDeclaration: ImportEqualsDeclaration | ImportDeclaration, + name: Identifier, + isReExport: boolean, + alreadyAddedDirect: boolean, + ): void { if (exportKind === ExportKind.ExportEquals) { // This is a direct import, not import-as-namespace. if (!alreadyAddedDirect) directImports.push(importDeclaration); } else if (!isAvailableThroughGlobal) { const sourceFileLike = getSourceFileLikeForImportDeclaration(importDeclaration); - Debug.assert(sourceFileLike.kind === SyntaxKind.SourceFile || sourceFileLike.kind === SyntaxKind.ModuleDeclaration); + Debug.assert( + sourceFileLike.kind === SyntaxKind.SourceFile || sourceFileLike.kind === SyntaxKind.ModuleDeclaration, + ); if (isReExport || findNamespaceReExports(sourceFileLike, name, checker)) { addIndirectUser(sourceFileLike, /*addTransitiveDependencies*/ true); } @@ -299,7 +336,10 @@ function getImportersForExport( if (directImports) { for (const directImport of directImports) { if (!isImportTypeNode(directImport)) { - addIndirectUser(getSourceFileLikeForImportDeclaration(directImport), /*addTransitiveDependencies*/ true); + addIndirectUser( + getSourceFileLikeForImportDeclaration(directImport), + /*addTransitiveDependencies*/ true, + ); } } } @@ -315,7 +355,13 @@ function getImportersForExport( * The returned `importSearches` will result in the entire source file being searched. * But re-exports will be placed in 'singleReferences' since they cannot be locally referenced. */ -function getSearchesFromDirectImports(directImports: Importer[], exportSymbol: Symbol, exportKind: ExportKind, checker: TypeChecker, isForRename: boolean): Pick { +function getSearchesFromDirectImports( + directImports: Importer[], + exportSymbol: Symbol, + exportKind: ExportKind, + checker: TypeChecker, + isForRename: boolean, +): Pick { const importSearches: [Identifier, Symbol][] = []; const singleReferences: (Identifier | StringLiteral)[] = []; function addSearch(location: Identifier, symbol: Symbol): void { @@ -389,7 +435,10 @@ function getSearchesFromDirectImports(directImports: Importer[], exportSymbol: S // `export =` might be imported by a default import if `--allowSyntheticDefaultImports` is on, so this handles both ExportKind.Default and ExportKind.ExportEquals. // If a default import has the same name as the default export, allow to rename it. // Given `import f` and `export default function f`, we will rename both, but for `import g` we will rename just that. - if (name && (exportKind === ExportKind.Default || exportKind === ExportKind.ExportEquals) && (!isForRename || name.escapedText === symbolEscapedNameNoDefault(exportSymbol))) { + if ( + name && (exportKind === ExportKind.Default || exportKind === ExportKind.ExportEquals) + && (!isForRename || name.escapedText === symbolEscapedNameNoDefault(exportSymbol)) + ) { const defaultImportAlias = checker.getSymbolAtLocation(name)!; addSearch(name, defaultImportAlias); } @@ -439,7 +488,8 @@ function getSearchesFromDirectImports(directImports: Importer[], exportSymbol: S function isNameMatch(name: __String): boolean { // Use name of "default" even in `export =` case because we may have allowSyntheticDefaultImports - return name === exportSymbol.escapedName || exportKind !== ExportKind.Named && name === InternalSymbolName.Default; + return name === exportSymbol.escapedName + || exportKind !== ExportKind.Named && name === InternalSymbolName.Default; } } @@ -450,8 +500,10 @@ function findNamespaceReExports(sourceFileLike: SourceFileLike, name: Identifier return !!forEachPossibleImportOrExportStatement(sourceFileLike, statement => { if (!isExportDeclaration(statement)) return; const { exportClause, moduleSpecifier } = statement; - return !moduleSpecifier && exportClause && isNamedExports(exportClause) && - exportClause.elements.some(element => checker.getExportSpecifierLocalTargetSymbol(element) === namespaceImportSymbol); + return !moduleSpecifier && exportClause && isNamedExports(exportClause) + && exportClause.elements.some(element => + checker.getExportSpecifierLocalTargetSymbol(element) === namespaceImportSymbol + ); }); } @@ -465,7 +517,11 @@ export type ModuleReference = | { kind: "implicit"; literal: StringLiteralLike; referencingFile: SourceFile; }; /** @internal */ -export function findModuleReferences(program: Program, sourceFiles: readonly SourceFile[], searchModuleSymbol: Symbol): ModuleReference[] { +export function findModuleReferences( + program: Program, + sourceFiles: readonly SourceFile[], + searchModuleSymbol: Symbol, +): ModuleReference[] { const refs: ModuleReference[] = []; const checker = program.getTypeChecker(); for (const referencingFile of sourceFiles) { @@ -477,8 +533,14 @@ export function findModuleReferences(program: Program, sourceFiles: readonly Sou } } for (const ref of referencingFile.typeReferenceDirectives) { - const referenced = program.getResolvedTypeReferenceDirectives().get(ref.fileName, ref.resolutionMode || referencingFile.impliedNodeFormat)?.resolvedTypeReferenceDirective; - if (referenced !== undefined && referenced.resolvedFileName === (searchSourceFile as SourceFile).fileName) { + const referenced = program.getResolvedTypeReferenceDirectives().get( + ref.fileName, + ref.resolutionMode || referencingFile.impliedNodeFormat, + )?.resolvedTypeReferenceDirective; + if ( + referenced !== undefined + && referenced.resolvedFileName === (searchSourceFile as SourceFile).fileName + ) { refs.push({ kind: "reference", referencingFile, ref }); } } @@ -487,7 +549,10 @@ export function findModuleReferences(program: Program, sourceFiles: readonly Sou forEachImport(referencingFile, (importDecl, moduleSpecifier) => { const moduleSymbol = checker.getSymbolAtLocation(moduleSpecifier); if (moduleSymbol === searchModuleSymbol) { - refs.push(nodeIsSynthesized(importDecl) ? { kind: "implicit", literal: moduleSpecifier, referencingFile } : { kind: "import", literal: moduleSpecifier }); + refs.push( + nodeIsSynthesized(importDecl) ? { kind: "implicit", literal: moduleSpecifier, referencingFile } + : { kind: "import", literal: moduleSpecifier }, + ); } }); } @@ -495,7 +560,11 @@ export function findModuleReferences(program: Program, sourceFiles: readonly Sou } /** Returns a map from a module symbol Id to all import statements that directly reference the module. */ -function getDirectImportsMap(sourceFiles: readonly SourceFile[], checker: TypeChecker, cancellationToken: CancellationToken | undefined): Map { +function getDirectImportsMap( + sourceFiles: readonly SourceFile[], + checker: TypeChecker, + cancellationToken: CancellationToken | undefined, +): Map { const map = new Map(); for (const sourceFile of sourceFiles) { @@ -517,14 +586,24 @@ function getDirectImportsMap(sourceFiles: readonly SourceFile[], checker: TypeCh } /** Iterates over all statements at the top level or in module declarations. Returns the first truthy result. */ -function forEachPossibleImportOrExportStatement(sourceFileLike: SourceFileLike, action: (statement: Statement) => T) { - return forEach(sourceFileLike.kind === SyntaxKind.SourceFile ? sourceFileLike.statements : sourceFileLike.body!.statements, statement => - // TODO: GH#18217 - action(statement) || (isAmbientModuleDeclaration(statement) && forEach(statement.body && statement.body.statements, action))); +function forEachPossibleImportOrExportStatement( + sourceFileLike: SourceFileLike, + action: (statement: Statement) => T, +) { + return forEach( + sourceFileLike.kind === SyntaxKind.SourceFile ? sourceFileLike.statements : sourceFileLike.body!.statements, + statement => + // TODO: GH#18217 + action(statement) + || (isAmbientModuleDeclaration(statement) && forEach(statement.body && statement.body.statements, action)), + ); } /** Calls `action` for each import, re-export, or require() in a file. */ -function forEachImport(sourceFile: SourceFile, action: (importStatement: ImporterOrCallExpression, imported: StringLiteralLike) => void): void { +function forEachImport( + sourceFile: SourceFile, + action: (importStatement: ImporterOrCallExpression, imported: StringLiteralLike) => void, +): void { if (sourceFile.externalModuleIndicator || sourceFile.imports !== undefined) { for (const i of sourceFile.imports) { action(importFromModuleSpecifier(i), i); @@ -575,7 +654,12 @@ export interface ExportedSymbol { * * @internal */ -export function getImportOrExportSymbol(node: Node, symbol: Symbol, checker: TypeChecker, comingFromExport: boolean): ImportedSymbol | ExportedSymbol | undefined { +export function getImportOrExportSymbol( + node: Node, + symbol: Symbol, + checker: TypeChecker, + comingFromExport: boolean, +): ImportedSymbol | ExportedSymbol | undefined { return comingFromExport ? getExport() : getExport() || getImport(); function getExport(): ExportedSymbol | ImportedSymbol | undefined { @@ -636,7 +720,11 @@ export function getImportOrExportSymbol(node: Node, symbol: Symbol, checker: Typ // Get the symbol for the `export =` node; its parent is the module it's the export of. if (!ex.symbol.parent) return undefined; const exportKind = ex.isExportEquals ? ExportKind.ExportEquals : ExportKind.Default; - return { kind: ImportExport.Export, symbol, exportInfo: { exportingModuleSymbol: ex.symbol.parent, exportKind } }; + return { + kind: ImportExport.Export, + symbol, + exportInfo: { exportingModuleSymbol: ex.symbol.parent, exportKind }, + }; } function getSpecialPropertyExport(node: BinaryExpression, useLhsSymbol: boolean): ExportedSymbol | undefined { @@ -652,7 +740,8 @@ export function getImportOrExportSymbol(node: Node, symbol: Symbol, checker: Typ return undefined; } - const sym = useLhsSymbol ? checker.getSymbolAtLocation(getNameOfAccessExpression(cast(node.left, isAccessExpression))) : symbol; + const sym = useLhsSymbol + ? checker.getSymbolAtLocation(getNameOfAccessExpression(cast(node.left, isAccessExpression))) : symbol; return sym && exportInfo(sym, kind); } } @@ -678,7 +767,10 @@ export function getImportOrExportSymbol(node: Node, symbol: Symbol, checker: Typ // If `importedName` is undefined, do continue searching as the export is anonymous. // (All imports returned from this function will be ignored anyway if we are in rename and this is a not a named export.) const importedName = symbolEscapedNameNoDefault(importedSymbol); - if (importedName === undefined || importedName === InternalSymbolName.Default || importedName === symbol.escapedName) { + if ( + importedName === undefined || importedName === InternalSymbolName.Default + || importedName === symbol.escapedName + ) { return { kind: ImportExport.Import, symbol: importedSymbol }; } } @@ -715,10 +807,12 @@ function getExportEqualsLocalSymbol(importedSymbol: Symbol, checker: TypeChecker // If a reference is a class expression, the exported node would be its parent. // If a reference is a variable declaration, the exported node would be the variable statement. function getExportNode(parent: Node, node: Node): Node | undefined { - const declaration = isVariableDeclaration(parent) ? parent : isBindingElement(parent) ? walkUpBindingElementsAndPatterns(parent) : undefined; + const declaration = isVariableDeclaration(parent) ? parent + : isBindingElement(parent) ? walkUpBindingElementsAndPatterns(parent) : undefined; if (declaration) { - return (parent as VariableDeclaration | BindingElement).name !== node ? undefined : - isCatchClause(declaration.parent) ? undefined : isVariableStatement(declaration.parent.parent) ? declaration.parent.parent : undefined; + return (parent as VariableDeclaration | BindingElement).name !== node ? undefined + : isCatchClause(declaration.parent) ? undefined + : isVariableStatement(declaration.parent.parent) ? declaration.parent.parent : undefined; } else { return parent; @@ -729,7 +823,8 @@ function isNodeImport(node: Node): boolean { const { parent } = node; switch (parent.kind) { case SyntaxKind.ImportEqualsDeclaration: - return (parent as ImportEqualsDeclaration).name === node && isExternalModuleImportEquals(parent as ImportEqualsDeclaration); + return (parent as ImportEqualsDeclaration).name === node + && isExternalModuleImportEquals(parent as ImportEqualsDeclaration); case SyntaxKind.ImportSpecifier: // For a rename import `{ foo as bar }`, don't search for the imported symbol. Just find local uses of `bar`. return !(parent as ImportSpecifier).propertyName; @@ -745,7 +840,11 @@ function isNodeImport(node: Node): boolean { } /** @internal */ -export function getExportInfo(exportSymbol: Symbol, exportKind: ExportKind, checker: TypeChecker): ExportInfo | undefined { +export function getExportInfo( + exportSymbol: Symbol, + exportKind: ExportKind, + checker: TypeChecker, +): ExportInfo | undefined { const moduleSymbol = exportSymbol.parent; if (!moduleSymbol) return undefined; // This can happen if an `export` is not at the top-level (which is a compile error). const exportingModuleSymbol = checker.getMergedSymbol(moduleSymbol); // Need to get merged symbol in case there's an augmentation. @@ -758,10 +857,16 @@ function skipExportSpecifierSymbol(symbol: Symbol, checker: TypeChecker): Symbol // For `export { foo } from './bar", there's nothing to skip, because it does not create a new alias. But `export { foo } does. if (symbol.declarations) { for (const declaration of symbol.declarations) { - if (isExportSpecifier(declaration) && !declaration.propertyName && !declaration.parent.parent.moduleSpecifier) { + if ( + isExportSpecifier(declaration) && !declaration.propertyName + && !declaration.parent.parent.moduleSpecifier + ) { return checker.getExportSpecifierLocalTargetSymbol(declaration) || symbol; } - else if (isPropertyAccessExpression(declaration) && isModuleExportsAccessExpression(declaration.expression) && !isPrivateIdentifier(declaration.name)) { + else if ( + isPropertyAccessExpression(declaration) && isModuleExportsAccessExpression(declaration.expression) + && !isPrivateIdentifier(declaration.name) + ) { // Export of form 'module.exports.propName = expr'; return checker.getSymbolAtLocation(declaration)!; } @@ -795,9 +900,13 @@ function getSourceFileLikeForImportDeclaration(node: ImporterOrCallExpression): } function isAmbientModuleDeclaration(node: Node): node is AmbientModuleDeclaration { - return node.kind === SyntaxKind.ModuleDeclaration && (node as ModuleDeclaration).name.kind === SyntaxKind.StringLiteral; + return node.kind === SyntaxKind.ModuleDeclaration + && (node as ModuleDeclaration).name.kind === SyntaxKind.StringLiteral; } -function isExternalModuleImportEquals(eq: ImportEqualsDeclaration): eq is ImportEqualsDeclaration & { moduleReference: { expression: StringLiteral; }; } { - return eq.moduleReference.kind === SyntaxKind.ExternalModuleReference && eq.moduleReference.expression.kind === SyntaxKind.StringLiteral; +function isExternalModuleImportEquals( + eq: ImportEqualsDeclaration, +): eq is ImportEqualsDeclaration & { moduleReference: { expression: StringLiteral; }; } { + return eq.moduleReference.kind === SyntaxKind.ExternalModuleReference + && eq.moduleReference.expression.kind === SyntaxKind.StringLiteral; } diff --git a/src/services/inlayHints.ts b/src/services/inlayHints.ts index e31532acb000a..6160922c3d56c 100644 --- a/src/services/inlayHints.ts +++ b/src/services/inlayHints.ts @@ -82,7 +82,8 @@ const leadingParameterNameCommentRegexFactory = (name: string) => { }; function shouldShowParameterNameHints(preferences: UserPreferences) { - return preferences.includeInlayParameterNameHints === "literals" || preferences.includeInlayParameterNameHints === "all"; + return preferences.includeInlayParameterNameHints === "literals" + || preferences.includeInlayParameterNameHints === "all"; } function shouldShowLiteralParameterNameHintsOnly(preferences: UserPreferences) { @@ -143,7 +144,10 @@ export function provideInlayHints(context: InlayHintsContext): InlayHint[] { visitCallOrNewExpression(node); } else { - if (preferences.includeInlayFunctionParameterTypeHints && isFunctionLikeDeclaration(node) && hasContextSensitiveParameters(node)) { + if ( + preferences.includeInlayFunctionParameterTypeHints && isFunctionLikeDeclaration(node) + && hasContextSensitiveParameters(node) + ) { visitFunctionLikeForParameterType(node); } if (preferences.includeInlayFunctionLikeReturnTypeHints && isSignatureSupportingReturnAnnotation(node)) { @@ -153,11 +157,20 @@ export function provideInlayHints(context: InlayHintsContext): InlayHint[] { return forEachChild(node, visitor); } - function isSignatureSupportingReturnAnnotation(node: Node): node is FunctionDeclaration | ArrowFunction | FunctionExpression | MethodDeclaration | GetAccessorDeclaration { - return isArrowFunction(node) || isFunctionExpression(node) || isFunctionDeclaration(node) || isMethodDeclaration(node) || isGetAccessorDeclaration(node); + function isSignatureSupportingReturnAnnotation( + node: Node, + ): node is FunctionDeclaration | ArrowFunction | FunctionExpression | MethodDeclaration | GetAccessorDeclaration { + return isArrowFunction(node) || isFunctionExpression(node) || isFunctionDeclaration(node) + || isMethodDeclaration(node) || isGetAccessorDeclaration(node); } - function addParameterHints(text: string, parameter: Identifier, position: number, isFirstVariadicArgument: boolean, sourceFile: SourceFile | undefined) { + function addParameterHints( + text: string, + parameter: Identifier, + position: number, + isFirstVariadicArgument: boolean, + sourceFile: SourceFile | undefined, + ) { let hintText = `${isFirstVariadicArgument ? "..." : ""}${text}`; let displayParts: InlayHintDisplayPart[] | undefined; if (shouldUseInteractiveInlayHints(preferences)) { @@ -179,7 +192,9 @@ export function provideInlayHints(context: InlayHintsContext): InlayHint[] { function addTypeHints(text: string, position: number) { result.push({ - text: `: ${text.length > maxTypeHintLength ? text.substr(0, maxTypeHintLength - "...".length) + "..." : text}`, + text: `: ${ + text.length > maxTypeHintLength ? text.substr(0, maxTypeHintLength - "...".length) + "..." : text + }`, position, kind: InlayHintKind.Type, whitespaceBefore: true, @@ -211,7 +226,10 @@ export function provideInlayHints(context: InlayHintsContext): InlayHint[] { } function visitVariableLikeDeclaration(decl: VariableDeclaration | PropertyDeclaration) { - if (!decl.initializer || isBindingPattern(decl.name) || isVariableDeclaration(decl) && !isHintableDeclaration(decl)) { + if ( + !decl.initializer || isBindingPattern(decl.name) + || isVariableDeclaration(decl) && !isHintableDeclaration(decl) + ) { return; } @@ -227,7 +245,8 @@ export function provideInlayHints(context: InlayHintsContext): InlayHint[] { const typeDisplayString = printTypeInSingleLine(declarationType); if (typeDisplayString) { - const isVariableNameMatchesType = preferences.includeInlayVariableTypeHintsWhenTypeMatchesName === false && equateStringsCaseInsensitive(decl.name.getText(), typeDisplayString); + const isVariableNameMatchesType = preferences.includeInlayVariableTypeHintsWhenTypeMatchesName === false + && equateStringsCaseInsensitive(decl.name.getText(), typeDisplayString); if (isVariableNameMatchesType) { return; } @@ -275,7 +294,9 @@ export function provideInlayHints(context: InlayHintsContext): InlayHint[] { signatureParamPos = signatureParamPos + (spreadArgs || 1); if (identifierInfo) { const { parameter, parameterName, isRestParameter: isFirstVariadicArgument } = identifierInfo; - const isParameterNameNotSameAsArgument = preferences.includeInlayParameterNameHintsWhenArgumentMatchesName || !identifierOrAccessExpressionPostfixMatchesParameterName(arg, parameterName); + const isParameterNameNotSameAsArgument = + preferences.includeInlayParameterNameHintsWhenArgumentMatchesName + || !identifierOrAccessExpressionPostfixMatchesParameterName(arg, parameterName); if (!isParameterNameNotSameAsArgument && !isFirstVariadicArgument) { continue; } @@ -318,7 +339,8 @@ export function provideInlayHints(context: InlayHintsContext): InlayHint[] { switch (node.kind) { case SyntaxKind.PrefixUnaryExpression: { const operand = (node as PrefixUnaryExpression).operand; - return isLiteralExpression(operand) || isIdentifier(operand) && isInfinityOrNaNString(operand.escapedText); + return isLiteralExpression(operand) + || isIdentifier(operand) && isInfinityOrNaNString(operand.escapedText); } case SyntaxKind.TrueKeyword: case SyntaxKind.FalseKeyword: @@ -334,7 +356,9 @@ export function provideInlayHints(context: InlayHintsContext): InlayHint[] { return isLiteralExpression(node); } - function visitFunctionDeclarationLikeForReturnType(decl: FunctionDeclaration | ArrowFunction | FunctionExpression | MethodDeclaration | GetAccessorDeclaration) { + function visitFunctionDeclarationLikeForReturnType( + decl: FunctionDeclaration | ArrowFunction | FunctionExpression | MethodDeclaration | GetAccessorDeclaration, + ) { if (isArrowFunction(decl)) { if (!findChildOfKind(decl, SyntaxKind.OpenParenToken, file)) { return; @@ -364,7 +388,9 @@ export function provideInlayHints(context: InlayHintsContext): InlayHint[] { addTypeHints(typeDisplayString, getTypeAnnotationPosition(decl)); } - function getTypeAnnotationPosition(decl: FunctionDeclaration | ArrowFunction | FunctionExpression | MethodDeclaration | GetAccessorDeclaration) { + function getTypeAnnotationPosition( + decl: FunctionDeclaration | ArrowFunction | FunctionExpression | MethodDeclaration | GetAccessorDeclaration, + ) { const closeParenToken = findChildOfKind(decl, SyntaxKind.CloseParenToken, file); if (closeParenToken) { return closeParenToken.end; @@ -413,7 +439,8 @@ export function provideInlayHints(context: InlayHintsContext): InlayHint[] { } function printTypeInSingleLine(type: Type) { - const flags = NodeBuilderFlags.IgnoreErrors | NodeBuilderFlags.AllowUniqueESSymbolType | NodeBuilderFlags.UseAliasDefinedOutsideCurrentScope; + const flags = NodeBuilderFlags.IgnoreErrors | NodeBuilderFlags.AllowUniqueESSymbolType + | NodeBuilderFlags.UseAliasDefinedOutsideCurrentScope; const printer = createPrinterWithRemoveComments(); return usingSingleLineStringWriter(writer => { @@ -430,7 +457,8 @@ export function provideInlayHints(context: InlayHintsContext): InlayHint[] { function isHintableDeclaration(node: VariableDeclaration | ParameterDeclaration) { if ((isParameterDeclaration(node) || isVariableDeclaration(node) && isVarConst(node)) && node.initializer) { const initializer = skipParentheses(node.initializer); - return !(isHintableLiteral(initializer) || isNewExpression(initializer) || isObjectLiteralExpression(initializer) || isAssertionExpression(initializer)); + return !(isHintableLiteral(initializer) || isNewExpression(initializer) + || isObjectLiteralExpression(initializer) || isAssertionExpression(initializer)); } return true; } diff --git a/src/services/jsDoc.ts b/src/services/jsDoc.ts index a68fdfcbfbae6..a8eb30f8ea4ef 100644 --- a/src/services/jsDoc.ts +++ b/src/services/jsDoc.ts @@ -179,7 +179,10 @@ let jsDocTagNameCompletionEntries: CompletionEntry[]; let jsDocTagCompletionEntries: CompletionEntry[]; /** @internal */ -export function getJsDocCommentsFromDeclarations(declarations: readonly Declaration[], checker?: TypeChecker): SymbolDisplayPart[] { +export function getJsDocCommentsFromDeclarations( + declarations: readonly Declaration[], + checker?: TypeChecker, +): SymbolDisplayPart[] { // Only collect doc comments from duplicate declarations once: // In case of a union property there might be same declaration multiple times // which only varies in type parameter @@ -189,7 +192,12 @@ export function getJsDocCommentsFromDeclarations(declarations: readonly Declarat const parts: SymbolDisplayPart[][] = []; forEachUnique(declarations, declaration => { for (const jsdoc of getCommentHavingNodes(declaration)) { - const inheritDoc = isJSDoc(jsdoc) && jsdoc.tags && find(jsdoc.tags, t => t.kind === SyntaxKind.JSDocTag && (t.tagName.escapedText === "inheritDoc" || t.tagName.escapedText === "inheritdoc")); + const inheritDoc = isJSDoc(jsdoc) && jsdoc.tags + && find( + jsdoc.tags, + t => t.kind === SyntaxKind.JSDocTag + && (t.tagName.escapedText === "inheritDoc" || t.tagName.escapedText === "inheritdoc"), + ); // skip comments containing @typedefs since they're not associated with particular declarations // Exceptions: // - @typedefs are themselves declarations with associated comments @@ -197,10 +205,15 @@ export function getJsDocCommentsFromDeclarations(declarations: readonly Declarat if ( jsdoc.comment === undefined && !inheritDoc || isJSDoc(jsdoc) - && declaration.kind !== SyntaxKind.JSDocTypedefTag && declaration.kind !== SyntaxKind.JSDocCallbackTag + && declaration.kind !== SyntaxKind.JSDocTypedefTag + && declaration.kind !== SyntaxKind.JSDocCallbackTag && jsdoc.tags - && jsdoc.tags.some(t => t.kind === SyntaxKind.JSDocTypedefTag || t.kind === SyntaxKind.JSDocCallbackTag) - && !jsdoc.tags.some(t => t.kind === SyntaxKind.JSDocParameterTag || t.kind === SyntaxKind.JSDocReturnTag) + && jsdoc.tags.some(t => + t.kind === SyntaxKind.JSDocTypedefTag || t.kind === SyntaxKind.JSDocCallbackTag + ) + && !jsdoc.tags.some(t => + t.kind === SyntaxKind.JSDocParameterTag || t.kind === SyntaxKind.JSDocReturnTag + ) ) { continue; } @@ -255,7 +268,10 @@ export function getJsDocTagsFromDeclarations(declarations?: Declaration[], check return infos; } -function getDisplayPartsFromComment(comment: string | readonly JSDocComment[], checker: TypeChecker | undefined): SymbolDisplayPart[] { +function getDisplayPartsFromComment( + comment: string | readonly JSDocComment[], + checker: TypeChecker | undefined, +): SymbolDisplayPart[] { if (typeof comment === "string") { return [textPart(comment)]; } @@ -271,8 +287,8 @@ function getCommentDisplayParts(tag: JSDocTag, checker?: TypeChecker): SymbolDis switch (kind) { case SyntaxKind.JSDocThrowsTag: const typeExpression = (tag as JSDocThrowsTag).typeExpression; - return typeExpression ? withNode(typeExpression) : - comment === undefined ? undefined : getDisplayPartsFromComment(comment, checker); + return typeExpression ? withNode(typeExpression) + : comment === undefined ? undefined : getDisplayPartsFromComment(comment, checker); case SyntaxKind.JSDocImplementsTag: return withNode((tag as JSDocImplementsTag).class); case SyntaxKind.JSDocAugmentsTag: @@ -307,7 +323,12 @@ function getCommentDisplayParts(tag: JSDocTag, checker?: TypeChecker): SymbolDis case SyntaxKind.JSDocPropertyTag: case SyntaxKind.JSDocParameterTag: case SyntaxKind.JSDocSeeTag: - const { name } = tag as JSDocTypedefTag | JSDocCallbackTag | JSDocPropertyTag | JSDocParameterTag | JSDocSeeTag; + const { name } = tag as + | JSDocTypedefTag + | JSDocCallbackTag + | JSDocPropertyTag + | JSDocParameterTag + | JSDocSeeTag; return name ? withNode(name) : comment === undefined ? undefined : getDisplayPartsFromComment(comment, checker); @@ -405,13 +426,20 @@ export function getJSDocParameterNameCompletions(tag: JSDocParameterTag): Comple const name = param.name.text; if ( - jsdoc.tags!.some(t => t !== tag && isJSDocParameterTag(t) && isIdentifier(t.name) && t.name.escapedText === name) // TODO: GH#18217 + jsdoc.tags!.some(t => + t !== tag && isJSDocParameterTag(t) && isIdentifier(t.name) && t.name.escapedText === name + ) // TODO: GH#18217 || nameThusFar !== undefined && !startsWith(name, nameThusFar) ) { return undefined; } - return { name, kind: ScriptElementKind.parameterElement, kindModifiers: "", sortText: Completions.SortText.LocationPriority }; + return { + name, + kind: ScriptElementKind.parameterElement, + kindModifiers: "", + sortText: Completions.SortText.LocationPriority, + }; }); } @@ -453,7 +481,12 @@ export function getJSDocParameterNameCompletionDetails(name: string): Completion * * @internal */ -export function getDocCommentTemplateAtPosition(newLine: string, sourceFile: SourceFile, position: number, options?: DocCommentTemplateOptions): TextInsertion | undefined { +export function getDocCommentTemplateAtPosition( + newLine: string, + sourceFile: SourceFile, + position: number, + options?: DocCommentTemplateOptions, +): TextInsertion | undefined { const tokenAtPos = getTokenAtPosition(sourceFile, position); const existingDocComment = findAncestor(tokenAtPos, isJSDoc); if (existingDocComment && (existingDocComment.comment !== undefined || length(existingDocComment.tags))) { @@ -486,8 +519,8 @@ export function getDocCommentTemplateAtPosition(newLine: string, sourceFile: Sou const indentationStr = getIndentationStringAtPosition(sourceFile, position); const isJavaScriptFile = hasJSFileExtension(sourceFile.fileName); - const tags = (parameters ? parameterDocComments(parameters || [], isJavaScriptFile, indentationStr, newLine) : "") + - (hasReturn ? returnsDocComment(indentationStr, newLine) : ""); + const tags = (parameters ? parameterDocComments(parameters || [], isJavaScriptFile, indentationStr, newLine) : "") + + (hasReturn ? returnsDocComment(indentationStr, newLine) : ""); // A doc comment consists of the following // * The opening comment line @@ -518,7 +551,12 @@ function getIndentationStringAtPosition(sourceFile: SourceFile, position: number return text.slice(lineStart, pos); } -function parameterDocComments(parameters: readonly ParameterDeclaration[], isJavaScriptFile: boolean, indentationStr: string, newLine: string): string { +function parameterDocComments( + parameters: readonly ParameterDeclaration[], + isJavaScriptFile: boolean, + indentationStr: string, + newLine: string, +): string { return parameters.map(({ name, dotDotDotToken }, i) => { const paramName = name.kind === SyntaxKind.Identifier ? name.text : "param" + i; const type = isJavaScriptFile ? (dotDotDotToken ? "{...any} " : "{any} ") : ""; @@ -535,10 +573,16 @@ interface CommentOwnerInfo { readonly parameters?: readonly ParameterDeclaration[]; readonly hasReturn?: boolean; } -function getCommentOwnerInfo(tokenAtPos: Node, options: DocCommentTemplateOptions | undefined): CommentOwnerInfo | undefined { +function getCommentOwnerInfo( + tokenAtPos: Node, + options: DocCommentTemplateOptions | undefined, +): CommentOwnerInfo | undefined { return forEachAncestor(tokenAtPos, n => getCommentOwnerInfoWorker(n, options)); } -function getCommentOwnerInfoWorker(commentOwner: Node, options: DocCommentTemplateOptions | undefined): CommentOwnerInfo | undefined | "quit" { +function getCommentOwnerInfoWorker( + commentOwner: Node, + options: DocCommentTemplateOptions | undefined, +): CommentOwnerInfo | undefined | "quit" { switch (commentOwner.kind) { case SyntaxKind.FunctionDeclaration: case SyntaxKind.FunctionExpression: @@ -546,7 +590,12 @@ function getCommentOwnerInfoWorker(commentOwner: Node, options: DocCommentTempla case SyntaxKind.Constructor: case SyntaxKind.MethodSignature: case SyntaxKind.ArrowFunction: - const host = commentOwner as ArrowFunction | FunctionDeclaration | MethodDeclaration | ConstructorDeclaration | MethodSignature; + const host = commentOwner as + | ArrowFunction + | FunctionDeclaration + | MethodDeclaration + | ConstructorDeclaration + | MethodSignature; return { commentOwner, parameters: host.parameters, hasReturn: hasReturn(host, options) }; case SyntaxKind.PropertyAssignment: @@ -606,12 +655,15 @@ function getCommentOwnerInfoWorker(commentOwner: Node, options: DocCommentTempla } function hasReturn(node: Node, options: DocCommentTemplateOptions | undefined) { - return !!options?.generateReturnInDocTemplate && - (isFunctionTypeNode(node) || isArrowFunction(node) && isExpression(node.body) - || isFunctionLikeDeclaration(node) && node.body && isBlock(node.body) && !!forEachReturnStatement(node.body, n => n)); + return !!options?.generateReturnInDocTemplate + && (isFunctionTypeNode(node) || isArrowFunction(node) && isExpression(node.body) + || isFunctionLikeDeclaration(node) && node.body && isBlock(node.body) + && !!forEachReturnStatement(node.body, n => n)); } -function getRightHandSideOfAssignment(rightHandSide: Expression): FunctionExpression | ArrowFunction | ConstructorDeclaration | undefined { +function getRightHandSideOfAssignment( + rightHandSide: Expression, +): FunctionExpression | ArrowFunction | ConstructorDeclaration | undefined { while (rightHandSide.kind === SyntaxKind.ParenthesizedExpression) { rightHandSide = (rightHandSide as ParenthesizedExpression).expression; } diff --git a/src/services/navigateTo.ts b/src/services/navigateTo.ts index 873bba76e9278..a496ee5c24a33 100644 --- a/src/services/navigateTo.ts +++ b/src/services/navigateTo.ts @@ -37,7 +37,14 @@ interface RawNavigateToItem { } /** @internal */ -export function getNavigateToItems(sourceFiles: readonly SourceFile[], checker: TypeChecker, cancellationToken: CancellationToken, searchValue: string, maxResultCount: number | undefined, excludeDtsFiles: boolean): NavigateToItem[] { +export function getNavigateToItems( + sourceFiles: readonly SourceFile[], + checker: TypeChecker, + cancellationToken: CancellationToken, + searchValue: string, + maxResultCount: number | undefined, + excludeDtsFiles: boolean, +): NavigateToItem[] { const patternMatcher = createPatternMatcher(searchValue); if (!patternMatcher) return emptyArray; const rawItems: RawNavigateToItem[] = []; @@ -59,7 +66,14 @@ export function getNavigateToItems(sourceFiles: readonly SourceFile[], checker: return (maxResultCount === undefined ? rawItems : rawItems.slice(0, maxResultCount)).map(createNavigateToItem); } -function getItemsFromNamedDeclaration(patternMatcher: PatternMatcher, name: string, declarations: readonly Declaration[], checker: TypeChecker, fileName: string, rawItems: RawNavigateToItem[]): void { +function getItemsFromNamedDeclaration( + patternMatcher: PatternMatcher, + name: string, + declarations: readonly Declaration[], + checker: TypeChecker, + fileName: string, + rawItems: RawNavigateToItem[], +): void { // First do a quick check to see if the name of the declaration matches the // last portion of the (possibly) dotted name they're searching for. const match = patternMatcher.getMatchForLastSegmentOfPattern(name); @@ -74,11 +88,23 @@ function getItemsFromNamedDeclaration(patternMatcher: PatternMatcher, name: stri // If the pattern has dots in it, then also see if the declaration container matches as well. const fullMatch = patternMatcher.getFullMatch(getContainers(declaration), name); if (fullMatch) { - rawItems.push({ name, fileName, matchKind: fullMatch.kind, isCaseSensitive: fullMatch.isCaseSensitive, declaration }); + rawItems.push({ + name, + fileName, + matchKind: fullMatch.kind, + isCaseSensitive: fullMatch.isCaseSensitive, + declaration, + }); } } else { - rawItems.push({ name, fileName, matchKind: match.kind, isCaseSensitive: match.isCaseSensitive, declaration }); + rawItems.push({ + name, + fileName, + matchKind: match.kind, + isCaseSensitive: match.isCaseSensitive, + declaration, + }); } } } @@ -88,7 +114,9 @@ function shouldKeepItem(declaration: Declaration, checker: TypeChecker): boolean case SyntaxKind.ImportClause: case SyntaxKind.ImportSpecifier: case SyntaxKind.ImportEqualsDeclaration: - const importer = checker.getSymbolAtLocation((declaration as ImportClause | ImportSpecifier | ImportEqualsDeclaration).name!)!; // TODO: GH#18217 + const importer = checker.getSymbolAtLocation( + (declaration as ImportClause | ImportSpecifier | ImportEqualsDeclaration).name!, + )!; // TODO: GH#18217 const imported = checker.getAliasedSymbol(importer); return importer.escapedName !== imported.escapedName; default: @@ -98,7 +126,10 @@ function shouldKeepItem(declaration: Declaration, checker: TypeChecker): boolean function tryAddSingleDeclarationName(declaration: Declaration, containers: string[]): boolean { const name = getNameOfDeclaration(declaration); - return !!name && (pushLiteral(name, containers) || name.kind === SyntaxKind.ComputedPropertyName && tryAddComputedPropertyName(name.expression, containers)); + return !!name + && (pushLiteral(name, containers) + || name.kind === SyntaxKind.ComputedPropertyName + && tryAddComputedPropertyName(name.expression, containers)); } // Only added the names of computed properties if they're simple dotted expressions, like: @@ -106,7 +137,8 @@ function tryAddSingleDeclarationName(declaration: Declaration, containers: strin // [X.Y.Z]() { } function tryAddComputedPropertyName(expression: Expression, containers: string[]): boolean { return pushLiteral(expression, containers) - || isPropertyAccessExpression(expression) && (containers.push(expression.name.text), true) && tryAddComputedPropertyName(expression.expression, containers); + || isPropertyAccessExpression(expression) && (containers.push(expression.name.text), true) + && tryAddComputedPropertyName(expression.expression, containers); } function pushLiteral(node: Node, containers: string[]): boolean { @@ -119,7 +151,10 @@ function getContainers(declaration: Declaration): readonly string[] { // First, if we started with a computed property name, then add all but the last // portion into the container array. const name = getNameOfDeclaration(declaration); - if (name && name.kind === SyntaxKind.ComputedPropertyName && !tryAddComputedPropertyName(name.expression, containers)) { + if ( + name && name.kind === SyntaxKind.ComputedPropertyName + && !tryAddComputedPropertyName(name.expression, containers) + ) { return emptyArray; } // Don't include the last portion. diff --git a/src/services/navigationBar.ts b/src/services/navigationBar.ts index d4bb1f7358587..eed7f6278baa7 100644 --- a/src/services/navigationBar.ts +++ b/src/services/navigationBar.ts @@ -163,7 +163,10 @@ interface NavigationBarNode { } /** @internal */ -export function getNavigationBarItems(sourceFile: SourceFile, cancellationToken: CancellationToken): NavigationBarItem[] { +export function getNavigationBarItems( + sourceFile: SourceFile, + cancellationToken: CancellationToken, +): NavigationBarItem[] { curCancellationToken = cancellationToken; curSourceFile = sourceFile; try { @@ -213,7 +216,14 @@ function pushChild(parent: NavigationBarNode, child: NavigationBarNode): void { function rootNavigationBarNode(sourceFile: SourceFile): NavigationBarNode { Debug.assert(!parentsStack.length); - const root: NavigationBarNode = { node: sourceFile, name: undefined, additionalNodes: undefined, parent: undefined, children: undefined, indent: 0 }; + const root: NavigationBarNode = { + node: sourceFile, + name: undefined, + additionalNodes: undefined, + parent: undefined, + children: undefined, + indent: 0, + }; parent = root; for (const statement of sourceFile.statements) { addChildrenRecursively(statement); @@ -295,7 +305,9 @@ function addNodeWithRecursiveChild(node: Node, child: Node | undefined, name?: D endNode(); } -function addNodeWithRecursiveInitializer(node: VariableDeclaration | PropertyAssignment | BindingElement | PropertyDeclaration): void { +function addNodeWithRecursiveInitializer( + node: VariableDeclaration | PropertyAssignment | BindingElement | PropertyDeclaration, +): void { if (node.initializer && isFunctionOrClassExpression(node.initializer)) { startNode(node); forEachChild(node.initializer, addChildrenRecursively); @@ -312,12 +324,12 @@ function addNodeWithRecursiveInitializer(node: VariableDeclaration | PropertyAss * symbols from other unique symbols, we do the below to retain those members in the nav tree. */ function hasNavigationBarName(node: Declaration) { - return !hasDynamicName(node) || - ( - node.kind !== SyntaxKind.BinaryExpression && - isPropertyAccessExpression(node.name.expression) && - isIdentifier(node.name.expression.expression) && - idText(node.name.expression.expression) === "Symbol" + return !hasDynamicName(node) + || ( + node.kind !== SyntaxKind.BinaryExpression + && isPropertyAccessExpression(node.name.expression) + && isIdentifier(node.name.expression.expression) + && idText(node.name.expression.expression) === "Symbol" ); } @@ -446,8 +458,8 @@ function addChildrenRecursively(node: Node | undefined): void { case SyntaxKind.ExportAssignment: { const expression = (node as ExportAssignment).expression; - const child = isObjectLiteralExpression(expression) || isCallExpression(expression) ? expression : - isArrowFunction(expression) || isFunctionExpression(expression) ? expression.body : undefined; + const child = isObjectLiteralExpression(expression) || isCallExpression(expression) ? expression + : isArrowFunction(expression) || isFunctionExpression(expression) ? expression.body : undefined; if (child) { startNode(node); addChildrenRecursively(child); @@ -480,9 +492,9 @@ function addChildrenRecursively(node: Node | undefined): void { const binaryExpression = node as BinaryExpression; const assignmentTarget = binaryExpression.left as PropertyAccessExpression; - const prototypeAccess = special === AssignmentDeclarationKind.PrototypeProperty ? - assignmentTarget.expression as PropertyAccessExpression : - assignmentTarget; + const prototypeAccess = special === AssignmentDeclarationKind.PrototypeProperty + ? assignmentTarget.expression as PropertyAccessExpression + : assignmentTarget; let depth = 0; let className: PropertyNameLiteral; @@ -493,7 +505,10 @@ function addChildrenRecursively(node: Node | undefined): void { className = prototypeAccess.expression; } else { - [depth, className] = startNestedNodes(binaryExpression, prototypeAccess.expression as EntityNameExpression); + [depth, className] = startNestedNodes( + binaryExpression, + prototypeAccess.expression as EntityNameExpression, + ); } if (special === AssignmentDeclarationKind.Prototype) { if (isObjectLiteralExpression(binaryExpression.right)) { @@ -518,9 +533,9 @@ function addChildrenRecursively(node: Node | undefined): void { case AssignmentDeclarationKind.ObjectDefinePropertyValue: case AssignmentDeclarationKind.ObjectDefinePrototypeProperty: { const defineCall = node as BindableObjectDefinePropertyCall; - const className = special === AssignmentDeclarationKind.ObjectDefinePropertyValue ? - defineCall.arguments[0] : - (defineCall.arguments[0] as PropertyAccessExpression).expression as EntityNameExpression; + const className = special === AssignmentDeclarationKind.ObjectDefinePropertyValue + ? defineCall.arguments[0] + : (defineCall.arguments[0] as PropertyAccessExpression).expression as EntityNameExpression; const memberName = defineCall.arguments[1]; const [depth, classNameIdentifier] = startNestedNodes(node, className); @@ -534,18 +549,24 @@ function addChildrenRecursively(node: Node | undefined): void { } case AssignmentDeclarationKind.Property: { const binaryExpression = node as BinaryExpression; - const assignmentTarget = binaryExpression.left as PropertyAccessExpression | BindableElementAccessExpression; + const assignmentTarget = binaryExpression.left as + | PropertyAccessExpression + | BindableElementAccessExpression; const targetFunction = assignmentTarget.expression; if ( - isIdentifier(targetFunction) && getElementOrPropertyAccessName(assignmentTarget) !== "prototype" && - trackedEs5Classes && trackedEs5Classes.has(targetFunction.text) + isIdentifier(targetFunction) && getElementOrPropertyAccessName(assignmentTarget) !== "prototype" + && trackedEs5Classes && trackedEs5Classes.has(targetFunction.text) ) { if (isFunctionExpression(binaryExpression.right) || isArrowFunction(binaryExpression.right)) { addNodeWithRecursiveChild(node, binaryExpression.right, targetFunction); } else if (isBindableStaticAccessExpression(assignmentTarget)) { startNode(binaryExpression, targetFunction); - addNodeWithRecursiveChild(binaryExpression.left, binaryExpression.right, getNameOrArgument(assignmentTarget)); + addNodeWithRecursiveChild( + binaryExpression.left, + binaryExpression.right, + getNameOrArgument(assignmentTarget), + ); endNode(); } return; @@ -625,17 +646,22 @@ const isEs5ClassMember: Record = { [AssignmentDeclarationKind.Prototype]: true, [AssignmentDeclarationKind.ThisProperty]: false, }; -function tryMergeEs5Class(a: NavigationBarNode, b: NavigationBarNode, bIndex: number, parent: NavigationBarNode): boolean | undefined { +function tryMergeEs5Class( + a: NavigationBarNode, + b: NavigationBarNode, + bIndex: number, + parent: NavigationBarNode, +): boolean | undefined { function isPossibleConstructor(node: Node) { return isFunctionExpression(node) || isFunctionDeclaration(node) || isVariableDeclaration(node); } - const bAssignmentDeclarationKind = isBinaryExpression(b.node) || isCallExpression(b.node) ? - getAssignmentDeclarationKind(b.node) : - AssignmentDeclarationKind.None; + const bAssignmentDeclarationKind = isBinaryExpression(b.node) || isCallExpression(b.node) + ? getAssignmentDeclarationKind(b.node) + : AssignmentDeclarationKind.None; - const aAssignmentDeclarationKind = isBinaryExpression(a.node) || isCallExpression(a.node) ? - getAssignmentDeclarationKind(a.node) : - AssignmentDeclarationKind.None; + const aAssignmentDeclarationKind = isBinaryExpression(a.node) || isCallExpression(a.node) + ? getAssignmentDeclarationKind(a.node) + : AssignmentDeclarationKind.None; // We treat this as an es5 class and merge the nodes in in one of several cases if ( @@ -653,9 +679,9 @@ function tryMergeEs5Class(a: NavigationBarNode, b: NavigationBarNode, bIndex: nu (!isClassDeclaration(a.node) && !isClassDeclaration(b.node)) // If neither outline node is a class || isPossibleConstructor(a.node) || isPossibleConstructor(b.node) // If either function is a constructor function ) { - const ctorFunction = isPossibleConstructor(a.node) ? a.node : - isPossibleConstructor(b.node) ? b.node : - undefined; + const ctorFunction = isPossibleConstructor(a.node) ? a.node + : isPossibleConstructor(b.node) ? b.node + : undefined; if (ctorFunction !== undefined) { const ctorNode = setTextRange( @@ -665,7 +691,8 @@ function tryMergeEs5Class(a: NavigationBarNode, b: NavigationBarNode, bIndex: nu const ctor = emptyNavigationBarNode(ctorNode); ctor.indent = a.indent + 1; ctor.children = a.node === ctorFunction ? a.children : b.children; - a.children = a.node === ctorFunction ? concatenate([ctor], b.children || [b]) : concatenate(a.children || [{ ...a }], [ctor]); + a.children = a.node === ctorFunction ? concatenate([ctor], b.children || [b]) + : concatenate(a.children || [{ ...a }], [ctor]); } else { if (a.children || b.children) { @@ -748,7 +775,8 @@ function shouldReallyMerge(a: Node, b: Node, parent: NavigationBarNode): boolean return isStatic(a) === isStatic(b); case SyntaxKind.ModuleDeclaration: return areSameModule(a as ModuleDeclaration, b as ModuleDeclaration) - && getFullyQualifiedModuleName(a as ModuleDeclaration) === getFullyQualifiedModuleName(b as ModuleDeclaration); + && getFullyQualifiedModuleName(a as ModuleDeclaration) + === getFullyQualifiedModuleName(b as ModuleDeclaration); default: return true; } @@ -771,7 +799,9 @@ function areSameModule(a: ModuleDeclaration, b: ModuleDeclaration): boolean { if (!a.body || !b.body) { return a.body === b.body; } - return a.body.kind === b.body.kind && (a.body.kind !== SyntaxKind.ModuleDeclaration || areSameModule(a.body as ModuleDeclaration, b.body as ModuleDeclaration)); + return a.body.kind === b.body.kind + && (a.body.kind !== SyntaxKind.ModuleDeclaration + || areSameModule(a.body as ModuleDeclaration, b.body as ModuleDeclaration)); } /** Merge source into target. Source should be thrown away after this is called. */ @@ -845,7 +875,8 @@ function getItemName(node: Node, name: Node | undefined): string { ? `"${escapeString(getBaseFileName(removeFileExtension(normalizePath(sourceFile.fileName))))}"` : ""; case SyntaxKind.ExportAssignment: - return isExportAssignment(node) && node.isExportEquals ? InternalSymbolName.ExportEquals : InternalSymbolName.Default; + return isExportAssignment(node) && node.isExportEquals ? InternalSymbolName.ExportEquals + : InternalSymbolName.Default; case SyntaxKind.ArrowFunction: case SyntaxKind.FunctionDeclaration: @@ -1016,7 +1047,8 @@ function isComputedProperty(member: EnumMember): boolean { } function getNodeSpan(node: Node): TextSpan { - return node.kind === SyntaxKind.SourceFile ? createTextSpanFromRange(node) : createTextSpanFromNode(node, curSourceFile); + return node.kind === SyntaxKind.SourceFile ? createTextSpanFromRange(node) + : createTextSpanFromNode(node, curSourceFile); } function getModifiers(node: Node): string { @@ -1026,7 +1058,9 @@ function getModifiers(node: Node): string { return getNodeModifiers(node); } -function getFunctionOrClassName(node: FunctionExpression | FunctionDeclaration | ArrowFunction | ClassLikeDeclaration): string { +function getFunctionOrClassName( + node: FunctionExpression | FunctionDeclaration | ArrowFunction | ClassLikeDeclaration, +): string { const { parent } = node; if (node.name && getFullWidth(node.name) > 0) { return cleanText(declarationNameToString(node.name)); @@ -1059,7 +1093,11 @@ function getFunctionOrClassName(node: FunctionExpression | FunctionDeclaration | return `${name} callback`; } - const args = cleanText(mapDefined(parent.arguments, a => isStringLiteralLike(a) ? a.getText(curSourceFile) : undefined).join(", ")); + const args = cleanText( + mapDefined(parent.arguments, a => isStringLiteralLike(a) ? a.getText(curSourceFile) : undefined).join( + ", ", + ), + ); return `${name}(${args}) callback`; } } diff --git a/src/services/organizeImports.ts b/src/services/organizeImports.ts index 1a5fa964a9c63..b62b2ef752829 100644 --- a/src/services/organizeImports.ts +++ b/src/services/organizeImports.ts @@ -88,30 +88,48 @@ export function organizeImports( const shouldCombine = shouldSort; // These are currently inseparable, but I draw a distinction for clarity and in case we add modes in the future. const shouldRemove = mode === OrganizeImportsMode.RemoveUnused || mode === OrganizeImportsMode.All; // All of the old ImportDeclarations in the file, in syntactic order. - const topLevelImportGroupDecls = groupByNewlineContiguous(sourceFile, sourceFile.statements.filter(isImportDeclaration)); + const topLevelImportGroupDecls = groupByNewlineContiguous( + sourceFile, + sourceFile.statements.filter(isImportDeclaration), + ); - const comparer = getOrganizeImportsComparerWithDetection(preferences, shouldSort ? () => detectSortingWorker(topLevelImportGroupDecls, preferences) === SortKind.CaseInsensitive : undefined); + const comparer = getOrganizeImportsComparerWithDetection( + preferences, + shouldSort ? () => detectSortingWorker(topLevelImportGroupDecls, preferences) === SortKind.CaseInsensitive + : undefined, + ); const processImportsOfSameModuleSpecifier = (importGroup: readonly ImportDeclaration[]) => { if (shouldRemove) importGroup = removeUnusedImports(importGroup, sourceFile, program); if (shouldCombine) importGroup = coalesceImportsWorker(importGroup, comparer, sourceFile); - if (shouldSort) importGroup = stableSort(importGroup, (s1, s2) => compareImportsOrRequireStatements(s1, s2, comparer)); + if (shouldSort) { + importGroup = stableSort(importGroup, (s1, s2) => compareImportsOrRequireStatements(s1, s2, comparer)); + } return importGroup; }; - topLevelImportGroupDecls.forEach(importGroupDecl => organizeImportsWorker(importGroupDecl, processImportsOfSameModuleSpecifier)); + topLevelImportGroupDecls.forEach(importGroupDecl => + organizeImportsWorker(importGroupDecl, processImportsOfSameModuleSpecifier) + ); // Exports are always used if (mode !== OrganizeImportsMode.RemoveUnused) { // All of the old ExportDeclarations in the file, in syntactic order. - getTopLevelExportGroups(sourceFile).forEach(exportGroupDecl => organizeImportsWorker(exportGroupDecl, group => coalesceExportsWorker(group, comparer))); + getTopLevelExportGroups(sourceFile).forEach(exportGroupDecl => + organizeImportsWorker(exportGroupDecl, group => coalesceExportsWorker(group, comparer)) + ); } for (const ambientModule of sourceFile.statements.filter(isAmbientModule)) { if (!ambientModule.body) continue; - const ambientModuleImportGroupDecls = groupByNewlineContiguous(sourceFile, ambientModule.body.statements.filter(isImportDeclaration)); - ambientModuleImportGroupDecls.forEach(importGroupDecl => organizeImportsWorker(importGroupDecl, processImportsOfSameModuleSpecifier)); + const ambientModuleImportGroupDecls = groupByNewlineContiguous( + sourceFile, + ambientModule.body.statements.filter(isImportDeclaration), + ); + ambientModuleImportGroupDecls.forEach(importGroupDecl => + organizeImportsWorker(importGroupDecl, processImportsOfSameModuleSpecifier) + ); // Exports are always used if (mode !== OrganizeImportsMode.RemoveUnused) { @@ -141,12 +159,19 @@ export function organizeImports( ? group(oldImportDecls, importDecl => getExternalModuleName(importDecl.moduleSpecifier)!) : [oldImportDecls]; const sortedImportGroups = shouldSort - ? stableSort(oldImportGroups, (group1, group2) => compareModuleSpecifiersWorker(group1[0].moduleSpecifier, group2[0].moduleSpecifier, comparer)) + ? stableSort( + oldImportGroups, + (group1, group2) => + compareModuleSpecifiersWorker(group1[0].moduleSpecifier, group2[0].moduleSpecifier, comparer), + ) : oldImportGroups; - const newImportDecls = flatMap(sortedImportGroups, importGroup => - getExternalModuleName(importGroup[0].moduleSpecifier) || importGroup[0].moduleSpecifier === undefined - ? coalesce(importGroup) - : importGroup); + const newImportDecls = flatMap( + sortedImportGroups, + importGroup => + getExternalModuleName(importGroup[0].moduleSpecifier) || importGroup[0].moduleSpecifier === undefined + ? coalesce(importGroup) + : importGroup, + ); // Delete all nodes if there are no imports. if (newImportDecls.length === 0) { @@ -165,7 +190,11 @@ export function organizeImports( suffix: getNewLineOrDefaultFromHost(host, formatContext.options), }; changeTracker.replaceNodeWithNodes(sourceFile, oldImportDecls[0], newImportDecls, replaceOptions); - const hasTrailingComment = changeTracker.nodeHasTrailingComment(sourceFile, oldImportDecls[0], replaceOptions); + const hasTrailingComment = changeTracker.nodeHasTrailingComment( + sourceFile, + oldImportDecls[0], + replaceOptions, + ); changeTracker.deleteNodes(sourceFile, oldImportDecls.slice(1), { trailingTriviaOption: textChanges.TrailingTriviaOption.Include, }, hasTrailingComment); @@ -173,7 +202,10 @@ export function organizeImports( } } -function groupByNewlineContiguous(sourceFile: SourceFile, decls: T[]): T[][] { +function groupByNewlineContiguous( + sourceFile: SourceFile, + decls: T[], +): T[][] { const scanner = createScanner(sourceFile.languageVersion, /*skipTrivia*/ false, sourceFile.languageVariant); const group: T[][] = []; let groupIndex = 0; @@ -285,16 +317,19 @@ function removeUnusedImports(oldImports: readonly ImportDeclaration[], sourceFil function isDeclarationUsed(identifier: Identifier) { // The JSX factory symbol is always used if JSX elements are present - even if they are not allowed. - return jsxElementsPresent && (identifier.text === jsxNamespace || jsxFragmentFactory && identifier.text === jsxFragmentFactory) && jsxModeNeedsExplicitImport(compilerOptions.jsx) || - FindAllReferences.Core.isSymbolReferencedInFile(identifier, typeChecker, sourceFile); + return jsxElementsPresent + && (identifier.text === jsxNamespace || jsxFragmentFactory && identifier.text === jsxFragmentFactory) + && jsxModeNeedsExplicitImport(compilerOptions.jsx) + || FindAllReferences.Core.isSymbolReferencedInFile(identifier, typeChecker, sourceFile); } } function hasModuleDeclarationMatchingSpecifier(sourceFile: SourceFile, moduleSpecifier: Expression) { const moduleSpecifierText = isStringLiteral(moduleSpecifier) && moduleSpecifier.text; - return isString(moduleSpecifierText) && some(sourceFile.moduleAugmentations, moduleName => - isStringLiteral(moduleName) - && moduleName.text === moduleSpecifierText); + return isString(moduleSpecifierText) + && some(sourceFile.moduleAugmentations, moduleName => + isStringLiteral(moduleName) + && moduleName.text === moduleSpecifierText); } function getExternalModuleName(specifier: Expression | undefined) { @@ -310,12 +345,20 @@ function getExternalModuleName(specifier: Expression | undefined) { * @deprecated Only used for testing * @internal */ -export function coalesceImports(importGroup: readonly ImportDeclaration[], ignoreCase: boolean, sourceFile?: SourceFile): readonly ImportDeclaration[] { +export function coalesceImports( + importGroup: readonly ImportDeclaration[], + ignoreCase: boolean, + sourceFile?: SourceFile, +): readonly ImportDeclaration[] { const comparer = getOrganizeImportsOrdinalStringComparer(ignoreCase); return coalesceImportsWorker(importGroup, comparer, sourceFile); } -function coalesceImportsWorker(importGroup: readonly ImportDeclaration[], comparer: Comparer, sourceFile?: SourceFile): readonly ImportDeclaration[] { +function coalesceImportsWorker( + importGroup: readonly ImportDeclaration[], + comparer: Comparer, + sourceFile?: SourceFile, +): readonly ImportDeclaration[] { if (importGroup.length === 0) { return importGroup; } @@ -336,18 +379,29 @@ function coalesceImportsWorker(importGroup: readonly ImportDeclaration[], compar // Add the namespace import to the existing default ImportDeclaration. const defaultImport = defaultImports[0]; coalescedImports.push( - updateImportDeclarationAndClause(defaultImport, defaultImport.importClause.name, namespaceImports[0].importClause.namedBindings), + updateImportDeclarationAndClause( + defaultImport, + defaultImport.importClause.name, + namespaceImports[0].importClause.namedBindings, + ), ); continue; } - const sortedNamespaceImports = stableSort(namespaceImports, (i1, i2) => comparer(i1.importClause.namedBindings.name.text, i2.importClause.namedBindings.name.text)); + const sortedNamespaceImports = stableSort( + namespaceImports, + (i1, i2) => comparer(i1.importClause.namedBindings.name.text, i2.importClause.namedBindings.name.text), + ); for (const namespaceImport of sortedNamespaceImports) { // Drop the name, if any coalescedImports.push( - updateImportDeclarationAndClause(namespaceImport, /*name*/ undefined, namespaceImport.importClause.namedBindings), + updateImportDeclarationAndClause( + namespaceImport, + /*name*/ undefined, + namespaceImport.importClause.namedBindings, + ), ); } @@ -366,7 +420,11 @@ function coalesceImportsWorker(importGroup: readonly ImportDeclaration[], compar else { for (const defaultImport of defaultImports) { newImportSpecifiers.push( - factory.createImportSpecifier(/*isTypeOnly*/ false, factory.createIdentifier("default"), defaultImport.importClause.name), + factory.createImportSpecifier( + /*isTypeOnly*/ false, + factory.createIdentifier("default"), + defaultImport.importClause.name, + ), ); } } @@ -387,10 +445,10 @@ function coalesceImportsWorker(importGroup: readonly ImportDeclaration[], compar : factory.createNamedImports(sortedImportSpecifiers); if ( - sourceFile && - newNamedImports && - firstNamedImport?.importClause.namedBindings && - !rangeIsOnSingleLine(firstNamedImport.importClause.namedBindings, sourceFile) + sourceFile + && newNamedImports + && firstNamedImport?.importClause.namedBindings + && !rangeIsOnSingleLine(firstNamedImport.importClause.namedBindings, sourceFile) ) { setEmitFlags(newNamedImports, EmitFlags.MultiLine); } @@ -514,7 +572,12 @@ function coalesceExportsWorker(exportGroup: readonly ExportDeclaration[], compar continue; } const newExportSpecifiers: ExportSpecifier[] = []; - newExportSpecifiers.push(...flatMap(exportGroup, i => i.exportClause && isNamedExports(i.exportClause) ? i.exportClause.elements : emptyArray)); + newExportSpecifiers.push( + ...flatMap( + exportGroup, + i => i.exportClause && isNamedExports(i.exportClause) ? i.exportClause.elements : emptyArray, + ), + ); const sortedExportSpecifiers = sortSpecifiers(newExportSpecifiers, comparer); @@ -525,9 +588,9 @@ function coalesceExportsWorker(exportGroup: readonly ExportDeclaration[], compar exportDecl.modifiers, exportDecl.isTypeOnly, exportDecl.exportClause && ( - isNamedExports(exportDecl.exportClause) ? - factory.updateNamedExports(exportDecl.exportClause, sortedExportSpecifiers) : - factory.updateNamespaceExport(exportDecl.exportClause, exportDecl.exportClause.name) + isNamedExports(exportDecl.exportClause) + ? factory.updateNamedExports(exportDecl.exportClause, sortedExportSpecifiers) + : factory.updateNamespaceExport(exportDecl.exportClause, exportDecl.exportClause.name) ), exportDecl.moduleSpecifier, exportDecl.assertClause, @@ -577,7 +640,12 @@ function updateImportDeclarationAndClause( return factory.updateImportDeclaration( importDeclaration, importDeclaration.modifiers, - factory.updateImportClause(importDeclaration.importClause!, importDeclaration.importClause!.isTypeOnly, name, namedBindings), // TODO: GH#18217 + factory.updateImportClause( + importDeclaration.importClause!, + importDeclaration.importClause!.isTypeOnly, + name, + namedBindings, + ), // TODO: GH#18217 importDeclaration.moduleSpecifier, importDeclaration.assertClause, ); @@ -588,7 +656,11 @@ function sortSpecifiers(specifiers: readonly } /** @internal */ -export function compareImportOrExportSpecifiers(s1: T, s2: T, comparer: Comparer): Comparison { +export function compareImportOrExportSpecifiers( + s1: T, + s2: T, + comparer: Comparer, +): Comparison { return compareBooleans(s1.isTypeOnly, s2.isTypeOnly) || comparer(s1.name.text, s2.name.text); } @@ -603,12 +675,16 @@ export function compareModuleSpecifiers(m1: Expression | undefined, m2: Expressi return compareModuleSpecifiersWorker(m1, m2, comparer); } -function compareModuleSpecifiersWorker(m1: Expression | undefined, m2: Expression | undefined, comparer: Comparer) { +function compareModuleSpecifiersWorker( + m1: Expression | undefined, + m2: Expression | undefined, + comparer: Comparer, +) { const name1 = m1 === undefined ? undefined : getExternalModuleName(m1); const name2 = m2 === undefined ? undefined : getExternalModuleName(m2); - return compareBooleans(name1 === undefined, name2 === undefined) || - compareBooleans(isExternalModuleNameRelative(name1!), isExternalModuleNameRelative(name2!)) || - comparer(name1!, name2!); + return compareBooleans(name1 === undefined, name2 === undefined) + || compareBooleans(isExternalModuleNameRelative(name1!), isExternalModuleNameRelative(name2!)) + || comparer(name1!, name2!); } function getModuleSpecifierExpression(declaration: AnyImportOrRequireStatement): Expression | undefined { @@ -661,7 +737,10 @@ function detectSortingWorker(importGroups: ImportDeclaration[][], preferences: U i => tryCast(i.importClause?.namedBindings, isNamedImports)?.elements.length! > 1, ); if (declarationWithNamedImports) { - const namedImportSort = detectImportSpecifierSorting((declarationWithNamedImports.importClause!.namedBindings as NamedImports).elements, preferences); + const namedImportSort = detectImportSpecifierSorting( + (declarationWithNamedImports.importClause!.namedBindings as NamedImports).elements, + preferences, + ); if (namedImportSort) { // Don't let a single unsorted group of named imports make the whole algorithm detect unsorted. // If other things are sorted consistently, that's a stronger indicator than unsorted named imports. @@ -684,7 +763,10 @@ function detectSortingWorker(importGroups: ImportDeclaration[][], preferences: U } /** @internal */ -export function detectImportDeclarationSorting(imports: readonly AnyImportOrRequireStatement[], preferences: UserPreferences): SortKind { +export function detectImportDeclarationSorting( + imports: readonly AnyImportOrRequireStatement[], + preferences: UserPreferences, +): SortKind { const collateCaseSensitive = getOrganizeImportsComparer(preferences, /*ignoreCase*/ false); const collateCaseInsensitive = getOrganizeImportsComparer(preferences, /*ignoreCase*/ true); return detectSortCaseSensitivity( @@ -720,30 +802,61 @@ class ImportSpecifierSortingCache implements MemoizeCache<[readonly ImportSpecif } /** @internal */ -export const detectImportSpecifierSorting = memoizeCached((specifiers: readonly ImportSpecifier[], preferences: UserPreferences): SortKind => { - if (!arrayIsSorted(specifiers, (s1, s2) => compareBooleans(s1.isTypeOnly, s2.isTypeOnly))) { - return SortKind.None; - } - const collateCaseSensitive = getOrganizeImportsComparer(preferences, /*ignoreCase*/ false); - const collateCaseInsensitive = getOrganizeImportsComparer(preferences, /*ignoreCase*/ true); - return detectSortCaseSensitivity(specifiers, specifier => specifier.name.text, collateCaseSensitive, collateCaseInsensitive); -}, new ImportSpecifierSortingCache()); +export const detectImportSpecifierSorting = memoizeCached( + (specifiers: readonly ImportSpecifier[], preferences: UserPreferences): SortKind => { + if (!arrayIsSorted(specifiers, (s1, s2) => compareBooleans(s1.isTypeOnly, s2.isTypeOnly))) { + return SortKind.None; + } + const collateCaseSensitive = getOrganizeImportsComparer(preferences, /*ignoreCase*/ false); + const collateCaseInsensitive = getOrganizeImportsComparer(preferences, /*ignoreCase*/ true); + return detectSortCaseSensitivity( + specifiers, + specifier => specifier.name.text, + collateCaseSensitive, + collateCaseInsensitive, + ); + }, + new ImportSpecifierSortingCache(), +); /** @internal */ -export function getImportDeclarationInsertionIndex(sortedImports: readonly AnyImportOrRequireStatement[], newImport: AnyImportOrRequireStatement, comparer: Comparer) { - const index = binarySearch(sortedImports, newImport, identity, (a, b) => compareImportsOrRequireStatements(a, b, comparer)); +export function getImportDeclarationInsertionIndex( + sortedImports: readonly AnyImportOrRequireStatement[], + newImport: AnyImportOrRequireStatement, + comparer: Comparer, +) { + const index = binarySearch( + sortedImports, + newImport, + identity, + (a, b) => compareImportsOrRequireStatements(a, b, comparer), + ); return index < 0 ? ~index : index; } /** @internal */ -export function getImportSpecifierInsertionIndex(sortedImports: readonly ImportSpecifier[], newImport: ImportSpecifier, comparer: Comparer) { - const index = binarySearch(sortedImports, newImport, identity, (s1, s2) => compareImportOrExportSpecifiers(s1, s2, comparer)); +export function getImportSpecifierInsertionIndex( + sortedImports: readonly ImportSpecifier[], + newImport: ImportSpecifier, + comparer: Comparer, +) { + const index = binarySearch( + sortedImports, + newImport, + identity, + (s1, s2) => compareImportOrExportSpecifiers(s1, s2, comparer), + ); return index < 0 ? ~index : index; } /** @internal */ -export function compareImportsOrRequireStatements(s1: AnyImportOrRequireStatement, s2: AnyImportOrRequireStatement, comparer: Comparer) { - return compareModuleSpecifiersWorker(getModuleSpecifierExpression(s1), getModuleSpecifierExpression(s2), comparer) || compareImportKind(s1, s2); +export function compareImportsOrRequireStatements( + s1: AnyImportOrRequireStatement, + s2: AnyImportOrRequireStatement, + comparer: Comparer, +) { + return compareModuleSpecifiersWorker(getModuleSpecifierExpression(s1), getModuleSpecifierExpression(s2), comparer) + || compareImportKind(s1, s2); } function compareImportKind(s1: AnyImportOrRequireStatement, s2: AnyImportOrRequireStatement) { @@ -773,11 +886,23 @@ function getImportKindOrder(s1: AnyImportOrRequireStatement) { } function getNewImportSpecifiers(namedImports: ImportDeclaration[]) { - return flatMap(namedImports, namedImport => - map(tryGetNamedBindingElements(namedImport), importSpecifier => - importSpecifier.name && importSpecifier.propertyName && importSpecifier.name.escapedText === importSpecifier.propertyName.escapedText - ? factory.updateImportSpecifier(importSpecifier, importSpecifier.isTypeOnly, /*propertyName*/ undefined, importSpecifier.name) - : importSpecifier)); + return flatMap( + namedImports, + namedImport => + map( + tryGetNamedBindingElements(namedImport), + importSpecifier => + importSpecifier.name && importSpecifier.propertyName + && importSpecifier.name.escapedText === importSpecifier.propertyName.escapedText + ? factory.updateImportSpecifier( + importSpecifier, + importSpecifier.isTypeOnly, + /*propertyName*/ undefined, + importSpecifier.name, + ) + : importSpecifier, + ), + ); } function tryGetNamedBindingElements(namedImport: ImportDeclaration) { @@ -795,9 +920,9 @@ function getOrganizeImportsUnicodeStringComparer(ignoreCase: boolean, preference const caseFirst = preferences.organizeImportsCaseFirst ?? false; const numeric = preferences.organizeImportsNumericCollation ?? false; const accents = preferences.organizeImportsAccentCollation ?? true; - const sensitivity = ignoreCase ? - accents ? "accent" : "base" : - accents ? "variant" : "case"; + const sensitivity = ignoreCase + ? accents ? "accent" : "base" + : accents ? "variant" : "case"; const collator = new Intl.Collator(resolvedLocale, { usage: "sort", @@ -823,13 +948,17 @@ function getOrganizeImportsLocale(preferences: UserPreferences): string { /** @internal */ export function getOrganizeImportsComparer(preferences: UserPreferences, ignoreCase: boolean): Comparer { const collation = preferences.organizeImportsCollation ?? "ordinal"; - return collation === "unicode" ? - getOrganizeImportsUnicodeStringComparer(ignoreCase, preferences) : - getOrganizeImportsOrdinalStringComparer(ignoreCase); + return collation === "unicode" + ? getOrganizeImportsUnicodeStringComparer(ignoreCase, preferences) + : getOrganizeImportsOrdinalStringComparer(ignoreCase); } -function getOrganizeImportsComparerWithDetection(preferences: UserPreferences, detectIgnoreCase?: () => boolean): Comparer { - const ignoreCase = typeof preferences.organizeImportsIgnoreCase === "boolean" ? preferences.organizeImportsIgnoreCase : detectIgnoreCase?.() ?? false; +function getOrganizeImportsComparerWithDetection( + preferences: UserPreferences, + detectIgnoreCase?: () => boolean, +): Comparer { + const ignoreCase = typeof preferences.organizeImportsIgnoreCase === "boolean" + ? preferences.organizeImportsIgnoreCase : detectIgnoreCase?.() ?? false; return getOrganizeImportsComparer(preferences, ignoreCase); } diff --git a/src/services/outliningElementsCollector.ts b/src/services/outliningElementsCollector.ts index 91e0573993e08..eed1c39d3192f 100644 --- a/src/services/outliningElementsCollector.ts +++ b/src/services/outliningElementsCollector.ts @@ -65,7 +65,11 @@ export function collectElements(sourceFile: SourceFile, cancellationToken: Cance return res.sort((span1, span2) => span1.textSpan.start - span2.textSpan.start); } -function addNodeOutliningSpans(sourceFile: SourceFile, cancellationToken: CancellationToken, out: OutliningSpan[]): void { +function addNodeOutliningSpans( + sourceFile: SourceFile, + cancellationToken: CancellationToken, + out: OutliningSpan[], +): void { let depthRemaining = 40; let current = 0; // Includes the EOF Token so that comments which aren't attached to statements are included @@ -84,7 +88,15 @@ function addNodeOutliningSpans(sourceFile: SourceFile, cancellationToken: Cancel } const lastImport = current - 1; if (lastImport !== firstImport) { - out.push(createOutliningSpanFromBounds(findChildOfKind(statements[firstImport], SyntaxKind.ImportKeyword, sourceFile)!.getStart(sourceFile), statements[lastImport].getEnd(), OutliningSpanKind.Imports)); + out.push( + createOutliningSpanFromBounds( + findChildOfKind(statements[firstImport], SyntaxKind.ImportKeyword, sourceFile)!.getStart( + sourceFile, + ), + statements[lastImport].getEnd(), + OutliningSpanKind.Imports, + ), + ); } } @@ -92,7 +104,10 @@ function addNodeOutliningSpans(sourceFile: SourceFile, cancellationToken: Cancel if (depthRemaining === 0) return; cancellationToken.throwIfCancellationRequested(); - if (isDeclaration(n) || isVariableStatement(n) || isReturnStatement(n) || isCallOrNewExpression(n) || n.kind === SyntaxKind.EndOfFileToken) { + if ( + isDeclaration(n) || isVariableStatement(n) || isReturnStatement(n) || isCallOrNewExpression(n) + || n.kind === SyntaxKind.EndOfFileToken + ) { addOutliningForLeadingCommentsForNode(n, sourceFile, cancellationToken, out); } @@ -147,7 +162,15 @@ function addRegionOutliningSpans(sourceFile: SourceFile, out: OutliningSpan[]): if (!result[1]) { const span = createTextSpanFromBounds(sourceFile.text.indexOf("//", currentLineStart), lineEnd); - regions.push(createOutliningSpan(span, OutliningSpanKind.Region, span, /*autoCollapse*/ false, result[2] || "#region")); + regions.push( + createOutliningSpan( + span, + OutliningSpanKind.Region, + span, + /*autoCollapse*/ false, + result[2] || "#region", + ), + ); } else { const region = regions.pop(); @@ -172,7 +195,12 @@ function isRegionDelimiter(lineText: string) { return regionDelimiterRegExp.exec(lineText); } -function addOutliningForLeadingCommentsForPos(pos: number, sourceFile: SourceFile, cancellationToken: CancellationToken, out: OutliningSpan[]): void { +function addOutliningForLeadingCommentsForPos( + pos: number, + sourceFile: SourceFile, + cancellationToken: CancellationToken, + out: OutliningSpan[], +): void { const comments = getLeadingCommentRanges(sourceFile.text, pos); if (!comments) return; @@ -214,12 +242,23 @@ function addOutliningForLeadingCommentsForPos(pos: number, sourceFile: SourceFil function combineAndAddMultipleSingleLineComments(): void { // Only outline spans of two or more consecutive single line comments if (singleLineCommentCount > 1) { - out.push(createOutliningSpanFromBounds(firstSingleLineCommentStart, lastSingleLineCommentEnd, OutliningSpanKind.Comment)); + out.push( + createOutliningSpanFromBounds( + firstSingleLineCommentStart, + lastSingleLineCommentEnd, + OutliningSpanKind.Comment, + ), + ); } } } -function addOutliningForLeadingCommentsForNode(n: Node, sourceFile: SourceFile, cancellationToken: CancellationToken, out: OutliningSpan[]): void { +function addOutliningForLeadingCommentsForNode( + n: Node, + sourceFile: SourceFile, + cancellationToken: CancellationToken, + out: OutliningSpan[], +): void { if (isJsxText(n)) return; addOutliningForLeadingCommentsForPos(n.pos, sourceFile, cancellationToken, out); } @@ -274,7 +313,12 @@ function getOutliningSpanForNode(n: Node, sourceFile: SourceFile): OutliningSpan case SyntaxKind.ObjectBindingPattern: return spanForNode(n); case SyntaxKind.TupleType: - return spanForNode(n, /*autoCollapse*/ false, /*useFullStart*/ !isTupleTypeNode(n.parent), SyntaxKind.OpenBracketToken); + return spanForNode( + n, + /*autoCollapse*/ false, + /*useFullStart*/ !isTupleTypeNode(n.parent), + SyntaxKind.OpenBracketToken, + ); case SyntaxKind.CaseClause: case SyntaxKind.DefaultClause: return spanForNodeArray((n as CaseClause | DefaultClause).statements); @@ -293,7 +337,12 @@ function getOutliningSpanForNode(n: Node, sourceFile: SourceFile): OutliningSpan case SyntaxKind.NoSubstitutionTemplateLiteral: return spanForTemplateLiteral(n as TemplateExpression | NoSubstitutionTemplateLiteral); case SyntaxKind.ArrayBindingPattern: - return spanForNode(n, /*autoCollapse*/ false, /*useFullStart*/ !isBindingElement(n.parent), SyntaxKind.OpenBracketToken); + return spanForNode( + n, + /*autoCollapse*/ false, + /*useFullStart*/ !isBindingElement(n.parent), + SyntaxKind.OpenBracketToken, + ); case SyntaxKind.ArrowFunction: return spanForArrowFunction(n as ArrowFunction); case SyntaxKind.CallExpression: @@ -316,7 +365,14 @@ function getOutliningSpanForNode(n: Node, sourceFile: SourceFile): OutliningSpan return undefined; } - return spanBetweenTokens(openToken, closeToken, node, sourceFile, /*autoCollapse*/ false, /*useFullStart*/ false); + return spanBetweenTokens( + openToken, + closeToken, + node, + sourceFile, + /*autoCollapse*/ false, + /*useFullStart*/ false, + ); } function spanForCallExpression(node: CallExpression): OutliningSpan | undefined { @@ -329,11 +385,21 @@ function getOutliningSpanForNode(n: Node, sourceFile: SourceFile): OutliningSpan return undefined; } - return spanBetweenTokens(openToken, closeToken, node, sourceFile, /*autoCollapse*/ false, /*useFullStart*/ true); + return spanBetweenTokens( + openToken, + closeToken, + node, + sourceFile, + /*autoCollapse*/ false, + /*useFullStart*/ true, + ); } function spanForArrowFunction(node: ArrowFunction): OutliningSpan | undefined { - if (isBlock(node.body) || isParenthesizedExpression(node.body) || positionsAreOnSameLine(node.body.getFullStart(), node.body.getEnd(), sourceFile)) { + if ( + isBlock(node.body) || isParenthesizedExpression(node.body) + || positionsAreOnSameLine(node.body.getFullStart(), node.body.getEnd(), sourceFile) + ) { return undefined; } const textSpan = createTextSpanFromBounds(node.body.getFullStart(), node.body.getEnd()); @@ -341,14 +407,20 @@ function getOutliningSpanForNode(n: Node, sourceFile: SourceFile): OutliningSpan } function spanForJSXElement(node: JsxElement): OutliningSpan | undefined { - const textSpan = createTextSpanFromBounds(node.openingElement.getStart(sourceFile), node.closingElement.getEnd()); + const textSpan = createTextSpanFromBounds( + node.openingElement.getStart(sourceFile), + node.closingElement.getEnd(), + ); const tagName = node.openingElement.tagName.getText(sourceFile); const bannerText = "<" + tagName + ">..."; return createOutliningSpan(textSpan, OutliningSpanKind.Code, textSpan, /*autoCollapse*/ false, bannerText); } function spanForJSXFragment(node: JsxFragment): OutliningSpan | undefined { - const textSpan = createTextSpanFromBounds(node.openingFragment.getStart(sourceFile), node.closingFragment.getEnd()); + const textSpan = createTextSpanFromBounds( + node.openingFragment.getStart(sourceFile), + node.closingFragment.getEnd(), + ); const bannerText = "<>..."; return createOutliningSpan(textSpan, OutliningSpanKind.Code, textSpan, /*autoCollapse*/ false, bannerText); } @@ -368,21 +440,38 @@ function getOutliningSpanForNode(n: Node, sourceFile: SourceFile): OutliningSpan return createOutliningSpanFromBounds(node.getStart(sourceFile), node.getEnd(), OutliningSpanKind.Code); } - function spanForObjectOrArrayLiteral(node: Node, open: SyntaxKind.OpenBraceToken | SyntaxKind.OpenBracketToken = SyntaxKind.OpenBraceToken): OutliningSpan | undefined { + function spanForObjectOrArrayLiteral( + node: Node, + open: SyntaxKind.OpenBraceToken | SyntaxKind.OpenBracketToken = SyntaxKind.OpenBraceToken, + ): OutliningSpan | undefined { // If the block has no leading keywords and is inside an array literal or call expression, // we only want to collapse the span of the block. // Otherwise, the collapsed section will include the end of the previous line. - return spanForNode(node, /*autoCollapse*/ false, /*useFullStart*/ !isArrayLiteralExpression(node.parent) && !isCallExpression(node.parent), open); + return spanForNode( + node, + /*autoCollapse*/ false, + /*useFullStart*/ !isArrayLiteralExpression(node.parent) && !isCallExpression(node.parent), + open, + ); } - function spanForNode(hintSpanNode: Node, autoCollapse = false, useFullStart = true, open: SyntaxKind.OpenBraceToken | SyntaxKind.OpenBracketToken = SyntaxKind.OpenBraceToken, close: SyntaxKind = open === SyntaxKind.OpenBraceToken ? SyntaxKind.CloseBraceToken : SyntaxKind.CloseBracketToken): OutliningSpan | undefined { + function spanForNode( + hintSpanNode: Node, + autoCollapse = false, + useFullStart = true, + open: SyntaxKind.OpenBraceToken | SyntaxKind.OpenBracketToken = SyntaxKind.OpenBraceToken, + close: SyntaxKind = open === SyntaxKind.OpenBraceToken ? SyntaxKind.CloseBraceToken + : SyntaxKind.CloseBracketToken, + ): OutliningSpan | undefined { const openToken = findChildOfKind(n, open, sourceFile); const closeToken = findChildOfKind(n, close, sourceFile); - return openToken && closeToken && spanBetweenTokens(openToken, closeToken, hintSpanNode, sourceFile, autoCollapse, useFullStart); + return openToken && closeToken + && spanBetweenTokens(openToken, closeToken, hintSpanNode, sourceFile, autoCollapse, useFullStart); } function spanForNodeArray(nodeArray: NodeArray): OutliningSpan | undefined { - return nodeArray.length ? createOutliningSpan(createTextSpanFromRange(nodeArray), OutliningSpanKind.Code) : undefined; + return nodeArray.length ? createOutliningSpan(createTextSpanFromRange(nodeArray), OutliningSpanKind.Code) + : undefined; } function spanForParenthesizedExpression(node: ParenthesizedExpression): OutliningSpan | undefined { @@ -395,15 +484,43 @@ function getOutliningSpanForNode(n: Node, sourceFile: SourceFile): OutliningSpan function functionSpan(node: SignatureDeclaration, body: Block, sourceFile: SourceFile): OutliningSpan | undefined { const openToken = tryGetFunctionOpenToken(node, body, sourceFile); const closeToken = findChildOfKind(body, SyntaxKind.CloseBraceToken, sourceFile); - return openToken && closeToken && spanBetweenTokens(openToken, closeToken, node, sourceFile, /*autoCollapse*/ node.kind !== SyntaxKind.ArrowFunction); + return openToken && closeToken + && spanBetweenTokens( + openToken, + closeToken, + node, + sourceFile, + /*autoCollapse*/ node.kind !== SyntaxKind.ArrowFunction, + ); } -function spanBetweenTokens(openToken: Node, closeToken: Node, hintSpanNode: Node, sourceFile: SourceFile, autoCollapse = false, useFullStart = true): OutliningSpan { - const textSpan = createTextSpanFromBounds(useFullStart ? openToken.getFullStart() : openToken.getStart(sourceFile), closeToken.getEnd()); - return createOutliningSpan(textSpan, OutliningSpanKind.Code, createTextSpanFromNode(hintSpanNode, sourceFile), autoCollapse); +function spanBetweenTokens( + openToken: Node, + closeToken: Node, + hintSpanNode: Node, + sourceFile: SourceFile, + autoCollapse = false, + useFullStart = true, +): OutliningSpan { + const textSpan = createTextSpanFromBounds( + useFullStart ? openToken.getFullStart() : openToken.getStart(sourceFile), + closeToken.getEnd(), + ); + return createOutliningSpan( + textSpan, + OutliningSpanKind.Code, + createTextSpanFromNode(hintSpanNode, sourceFile), + autoCollapse, + ); } -function createOutliningSpan(textSpan: TextSpan, kind: OutliningSpanKind, hintSpan: TextSpan = textSpan, autoCollapse = false, bannerText = "..."): OutliningSpan { +function createOutliningSpan( + textSpan: TextSpan, + kind: OutliningSpanKind, + hintSpan: TextSpan = textSpan, + autoCollapse = false, + bannerText = "...", +): OutliningSpan { return { textSpan, kind, hintSpan, bannerText, autoCollapse }; } diff --git a/src/services/patternMatcher.ts b/src/services/patternMatcher.ts index 7409dc5f3c62d..6a197f0eeee26 100644 --- a/src/services/patternMatcher.ts +++ b/src/services/patternMatcher.ts @@ -125,13 +125,20 @@ export function createPatternMatcher(pattern: string): PatternMatcher | undefine if (dotSeparatedSegments.some(segment => !segment.subWordTextChunks.length)) return undefined; return { - getFullMatch: (containers, candidate) => getFullMatch(containers, candidate, dotSeparatedSegments, stringToWordSpans), - getMatchForLastSegmentOfPattern: candidate => matchSegment(candidate, last(dotSeparatedSegments), stringToWordSpans), + getFullMatch: (containers, candidate) => + getFullMatch(containers, candidate, dotSeparatedSegments, stringToWordSpans), + getMatchForLastSegmentOfPattern: candidate => + matchSegment(candidate, last(dotSeparatedSegments), stringToWordSpans), patternContainsDots: dotSeparatedSegments.length > 1, }; } -function getFullMatch(candidateContainers: readonly string[], candidate: string, dotSeparatedSegments: readonly Segment[], stringToWordSpans: Map): PatternMatch | undefined { +function getFullMatch( + candidateContainers: readonly string[], + candidate: string, + dotSeparatedSegments: readonly Segment[], + stringToWordSpans: Map, +): PatternMatch | undefined { // First, check that the last part of the dot separated pattern matches the name of the // candidate. If not, then there's no point in proceeding and doing the more // expensive work. @@ -150,7 +157,10 @@ function getFullMatch(candidateContainers: readonly string[], candidate: string, let bestMatch: PatternMatch | undefined; for (let i = dotSeparatedSegments.length - 2, j = candidateContainers.length - 1; i >= 0; i -= 1, j -= 1) { - bestMatch = betterMatch(bestMatch, matchSegment(candidateContainers[j], dotSeparatedSegments[i], stringToWordSpans)); + bestMatch = betterMatch( + bestMatch, + matchSegment(candidateContainers[j], dotSeparatedSegments[i], stringToWordSpans), + ); } return bestMatch; } @@ -163,12 +173,19 @@ function getWordSpans(word: string, stringToWordSpans: Map): return spans; } -function matchTextChunk(candidate: string, chunk: TextChunk, stringToWordSpans: Map): PatternMatch | undefined { +function matchTextChunk( + candidate: string, + chunk: TextChunk, + stringToWordSpans: Map, +): PatternMatch | undefined { const index = indexOfIgnoringCase(candidate, chunk.textLowerCase); if (index === 0) { // a) Check if the word is a prefix of the candidate, in a case insensitive or // sensitive manner. If it does, return that there was an exact match if the word and candidate are the same length, else a prefix match. - return createPatternMatch(chunk.text.length === candidate.length ? PatternMatchKind.exact : PatternMatchKind.prefix, /*isCaseSensitive:*/ startsWith(candidate, chunk.text)); + return createPatternMatch( + chunk.text.length === candidate.length ? PatternMatchKind.exact : PatternMatchKind.prefix, + /*isCaseSensitive:*/ startsWith(candidate, chunk.text), + ); } if (chunk.isLowerCase) { @@ -183,7 +200,10 @@ function matchTextChunk(candidate: string, chunk: TextChunk, stringToWordSpans: const wordSpans = getWordSpans(candidate, stringToWordSpans); for (const span of wordSpans) { if (partStartsWith(candidate, span, chunk.text, /*ignoreCase*/ true)) { - return createPatternMatch(PatternMatchKind.substring, /*isCaseSensitive:*/ partStartsWith(candidate, span, chunk.text, /*ignoreCase*/ false)); + return createPatternMatch( + PatternMatchKind.substring, + /*isCaseSensitive:*/ partStartsWith(candidate, span, chunk.text, /*ignoreCase*/ false), + ); } } // c) Is the pattern a substring of the candidate starting on one of the candidate's word boundaries? @@ -215,7 +235,11 @@ function matchTextChunk(candidate: string, chunk: TextChunk, stringToWordSpans: } } -function matchSegment(candidate: string, segment: Segment, stringToWordSpans: Map): PatternMatch | undefined { +function matchSegment( + candidate: string, + segment: Segment, + stringToWordSpans: Map, +): PatternMatch | undefined { // First check if the segment matches as is. This is also useful if the segment contains // characters we would normally strip when splitting into parts that we also may want to // match in the candidate. For example if the segment is "@int" and the candidate is @@ -280,16 +304,35 @@ function compareMatches(a: PatternMatch | undefined, b: PatternMatch | undefined : compareValues(a.kind, b.kind) || compareBooleans(!a.isCaseSensitive, !b.isCaseSensitive); } -function partStartsWith(candidate: string, candidateSpan: TextSpan, pattern: string, ignoreCase: boolean, patternSpan: TextSpan = { start: 0, length: pattern.length }): boolean { +function partStartsWith( + candidate: string, + candidateSpan: TextSpan, + pattern: string, + ignoreCase: boolean, + patternSpan: TextSpan = { start: 0, length: pattern.length }, +): boolean { return patternSpan.length <= candidateSpan.length // If pattern part is longer than the candidate part there can never be a match. - && everyInRange(0, patternSpan.length, i => equalChars(pattern.charCodeAt(patternSpan.start + i), candidate.charCodeAt(candidateSpan.start + i), ignoreCase)); + && everyInRange( + 0, + patternSpan.length, + i => equalChars( + pattern.charCodeAt(patternSpan.start + i), + candidate.charCodeAt(candidateSpan.start + i), + ignoreCase, + ), + ); } function equalChars(ch1: number, ch2: number, ignoreCase: boolean): boolean { return ignoreCase ? toLowerCase(ch1) === toLowerCase(ch2) : ch1 === ch2; } -function tryCamelCaseMatch(candidate: string, candidateParts: TextSpan[], chunk: TextChunk, ignoreCase: boolean): boolean { +function tryCamelCaseMatch( + candidate: string, + candidateParts: TextSpan[], + chunk: TextChunk, + ignoreCase: boolean, +): boolean { const chunkCharacterSpans = chunk.characterSpans; // Note: we may have more pattern parts than candidate parts. This is because multiple @@ -327,8 +370,8 @@ function tryCamelCaseMatch(candidate: string, candidateParts: TextSpan[], chunk: // only continue trying to consumer pattern parts if the last part and this // part are both upper case. if ( - !isUpperCaseLetter(chunk.text.charCodeAt(chunkCharacterSpans[currentChunkSpan - 1].start)) || - !isUpperCaseLetter(chunk.text.charCodeAt(chunkCharacterSpans[currentChunkSpan].start)) + !isUpperCaseLetter(chunk.text.charCodeAt(chunkCharacterSpans[currentChunkSpan - 1].start)) + || !isUpperCaseLetter(chunk.text.charCodeAt(chunkCharacterSpans[currentChunkSpan].start)) ) { break; } @@ -347,7 +390,10 @@ function tryCamelCaseMatch(candidate: string, candidateParts: TextSpan[], chunk: // obviously contiguous. contiguous = contiguous === undefined ? true : contiguous; - candidatePart = createTextSpan(candidatePart.start + chunkCharacterSpan.length, candidatePart.length - chunkCharacterSpan.length); + candidatePart = createTextSpan( + candidatePart.start + chunkCharacterSpan.length, + candidatePart.length - chunkCharacterSpan.length, + ); } // Check if we matched anything at all. If we didn't, then we need to unset the @@ -435,7 +481,8 @@ function isDigit(ch: number) { } function isWordChar(ch: number) { - return isUpperCaseLetter(ch) || isLowerCaseLetter(ch) || isDigit(ch) || ch === CharacterCodes._ || ch === CharacterCodes.$; + return isUpperCaseLetter(ch) || isLowerCaseLetter(ch) || isDigit(ch) || ch === CharacterCodes._ + || ch === CharacterCodes.$; } function breakPatternIntoTextChunks(pattern: string): TextChunk[] { @@ -498,11 +545,11 @@ function breakIntoSpans(identifier: string, word: boolean): TextSpan[] { const hasTransitionFromUpperToLower = word && transitionFromUpperToLower(identifier, i, wordStart); if ( - charIsPunctuation(identifier.charCodeAt(i - 1)) || - charIsPunctuation(identifier.charCodeAt(i)) || - lastIsDigit !== currentIsDigit || - hasTransitionFromLowerToUpper || - hasTransitionFromUpperToLower + charIsPunctuation(identifier.charCodeAt(i - 1)) + || charIsPunctuation(identifier.charCodeAt(i)) + || lastIsDigit !== currentIsDigit + || hasTransitionFromLowerToUpper + || hasTransitionFromUpperToLower ) { if (!isAllPunctuation(identifier, wordStart, i)) { result.push(createTextSpan(wordStart, i - wordStart)); diff --git a/src/services/preProcess.ts b/src/services/preProcess.ts index 2d98a63586c55..7293654da70cf 100644 --- a/src/services/preProcess.ts +++ b/src/services/preProcess.ts @@ -13,7 +13,11 @@ import { SyntaxKind, } from "./_namespaces/ts"; -export function preProcessFile(sourceText: string, readImportFiles = true, detectJavaScriptImports = false): PreProcessedFileInfo { +export function preProcessFile( + sourceText: string, + readImportFiles = true, + detectJavaScriptImports = false, +): PreProcessedFileInfo { const pragmaContext: PragmaContext = { languageVersion: ScriptTarget.ES5, // controls whether the token scanner considers unicode identifiers or not - shouldn't matter, since we're only using it for trivia pragmas: undefined, @@ -119,10 +123,10 @@ export function preProcessFile(sourceText: string, readImportFiles = true, detec const skipTypeKeyword = scanner.lookAhead(() => { const token = scanner.scan(); return token !== SyntaxKind.FromKeyword && ( - token === SyntaxKind.AsteriskToken || - token === SyntaxKind.OpenBraceToken || - token === SyntaxKind.Identifier || - isKeyword(token) + token === SyntaxKind.AsteriskToken + || token === SyntaxKind.OpenBraceToken + || token === SyntaxKind.Identifier + || isKeyword(token) ); }); if (skipTypeKeyword) { @@ -208,8 +212,8 @@ export function preProcessFile(sourceText: string, readImportFiles = true, detec if (token === SyntaxKind.TypeKeyword) { const skipTypeKeyword = scanner.lookAhead(() => { const token = scanner.scan(); - return token === SyntaxKind.AsteriskToken || - token === SyntaxKind.OpenBraceToken; + return token === SyntaxKind.AsteriskToken + || token === SyntaxKind.OpenBraceToken; }); if (skipTypeKeyword) { token = nextToken(); @@ -250,8 +254,8 @@ export function preProcessFile(sourceText: string, readImportFiles = true, detec if (token === SyntaxKind.TypeKeyword) { const skipTypeKeyword = scanner.lookAhead(() => { const token = scanner.scan(); - return token === SyntaxKind.Identifier || - isKeyword(token); + return token === SyntaxKind.Identifier + || isKeyword(token); }); if (skipTypeKeyword) { token = nextToken(); @@ -280,8 +284,8 @@ export function preProcessFile(sourceText: string, readImportFiles = true, detec if (token === SyntaxKind.OpenParenToken) { token = nextToken(); if ( - token === SyntaxKind.StringLiteral || - allowTemplateLiterals && token === SyntaxKind.NoSubstitutionTemplateLiteral + token === SyntaxKind.StringLiteral + || allowTemplateLiterals && token === SyntaxKind.NoSubstitutionTemplateLiteral ) { // require("mod"); recordModuleName(); @@ -382,7 +386,10 @@ export function preProcessFile(sourceText: string, readImportFiles = true, detec case SyntaxKind.CloseBraceToken: if (length(stack)) { if (lastOrUndefined(stack) === SyntaxKind.TemplateHead) { - if (scanner.reScanTemplateToken(/*isTaggedTemplate*/ false) === SyntaxKind.TemplateTail) { + if ( + scanner.reScanTemplateToken(/*isTaggedTemplate*/ false) + === SyntaxKind.TemplateTail + ) { stack.pop(); } } @@ -398,12 +405,12 @@ export function preProcessFile(sourceText: string, readImportFiles = true, detec // check if at least one of alternative have moved scanner forward if ( - tryConsumeDeclare() || - tryConsumeImport() || - tryConsumeExport() || - (detectJavaScriptImports && ( - tryConsumeRequireCall(/*skipCurrentToken*/ false, /*allowTemplateLiterals*/ true) || - tryConsumeDefine() + tryConsumeDeclare() + || tryConsumeImport() + || tryConsumeExport() + || (detectJavaScriptImports && ( + tryConsumeRequireCall(/*skipCurrentToken*/ false, /*allowTemplateLiterals*/ true) + || tryConsumeDefine() )) ) { continue; @@ -429,7 +436,14 @@ export function preProcessFile(sourceText: string, readImportFiles = true, detec importedFiles.push(decl.ref); } } - return { referencedFiles: pragmaContext.referencedFiles, typeReferenceDirectives: pragmaContext.typeReferenceDirectives, libReferenceDirectives: pragmaContext.libReferenceDirectives, importedFiles, isLibFile: !!pragmaContext.hasNoDefaultLib, ambientExternalModules: undefined }; + return { + referencedFiles: pragmaContext.referencedFiles, + typeReferenceDirectives: pragmaContext.typeReferenceDirectives, + libReferenceDirectives: pragmaContext.libReferenceDirectives, + importedFiles, + isLibFile: !!pragmaContext.hasNoDefaultLib, + ambientExternalModules: undefined, + }; } else { // for global scripts ambient modules still can have augmentations - look for ambient modules with depth > 0 @@ -447,6 +461,13 @@ export function preProcessFile(sourceText: string, readImportFiles = true, detec } } } - return { referencedFiles: pragmaContext.referencedFiles, typeReferenceDirectives: pragmaContext.typeReferenceDirectives, libReferenceDirectives: pragmaContext.libReferenceDirectives, importedFiles, isLibFile: !!pragmaContext.hasNoDefaultLib, ambientExternalModules: ambientModuleNames }; + return { + referencedFiles: pragmaContext.referencedFiles, + typeReferenceDirectives: pragmaContext.typeReferenceDirectives, + libReferenceDirectives: pragmaContext.libReferenceDirectives, + importedFiles, + isLibFile: !!pragmaContext.hasNoDefaultLib, + ambientExternalModules: ambientModuleNames, + }; } } diff --git a/src/services/refactorProvider.ts b/src/services/refactorProvider.ts index 71759672452b2..392c79c8618ca 100644 --- a/src/services/refactorProvider.ts +++ b/src/services/refactorProvider.ts @@ -25,15 +25,28 @@ export function registerRefactor(name: string, refactor: Refactor) { } /** @internal */ -export function getApplicableRefactors(context: RefactorContext, includeInteractiveActions?: boolean): ApplicableRefactorInfo[] { - return arrayFrom(flatMapIterator(refactors.values(), refactor => - context.cancellationToken && context.cancellationToken.isCancellationRequested() || - !refactor.kinds?.some(kind => refactorKindBeginsWith(kind, context.kind)) ? undefined : - refactor.getAvailableActions(context, includeInteractiveActions))); +export function getApplicableRefactors( + context: RefactorContext, + includeInteractiveActions?: boolean, +): ApplicableRefactorInfo[] { + return arrayFrom( + flatMapIterator( + refactors.values(), + refactor => + context.cancellationToken && context.cancellationToken.isCancellationRequested() + || !refactor.kinds?.some(kind => refactorKindBeginsWith(kind, context.kind)) ? undefined + : refactor.getAvailableActions(context, includeInteractiveActions), + ), + ); } /** @internal */ -export function getEditsForRefactor(context: RefactorContext, refactorName: string, actionName: string, interactiveRefactorArguments?: InteractiveRefactorArguments): RefactorEditInfo | undefined { +export function getEditsForRefactor( + context: RefactorContext, + refactorName: string, + actionName: string, + interactiveRefactorArguments?: InteractiveRefactorArguments, +): RefactorEditInfo | undefined { const refactor = refactors.get(refactorName); return refactor && refactor.getEditsForAction(context, actionName, interactiveRefactorArguments); } diff --git a/src/services/refactors/addOrRemoveBracesToArrowFunction.ts b/src/services/refactors/addOrRemoveBracesToArrowFunction.ts index 0d7489554cf8f..588fa065561c7 100644 --- a/src/services/refactors/addOrRemoveBracesToArrowFunction.ts +++ b/src/services/refactors/addOrRemoveBracesToArrowFunction.ts @@ -89,7 +89,10 @@ function getRefactorActionsToRemoveFunctionBraces(context: RefactorContext): rea return emptyArray; } -function getRefactorEditsToRemoveFunctionBraces(context: RefactorContext, actionName: string): RefactorEditInfo | undefined { +function getRefactorEditsToRemoveFunctionBraces( + context: RefactorContext, + actionName: string, +): RefactorEditInfo | undefined { const { file, startPosition } = context; const info = getConvertibleArrowFunctionAtPosition(file, startPosition); Debug.assert(info && !isRefactorErrorInfo(info), "Expected applicable refactor info"); @@ -101,14 +104,39 @@ function getRefactorEditsToRemoveFunctionBraces(context: RefactorContext, action if (actionName === addBracesAction.name) { const returnStatement = factory.createReturnStatement(expression); body = factory.createBlock([returnStatement], /*multiLine*/ true); - copyLeadingComments(expression!, returnStatement, file, SyntaxKind.MultiLineCommentTrivia, /*hasTrailingNewLine*/ true); + copyLeadingComments( + expression!, + returnStatement, + file, + SyntaxKind.MultiLineCommentTrivia, + /*hasTrailingNewLine*/ true, + ); } else if (actionName === removeBracesAction.name && returnStatement) { const actualExpression = expression || factory.createVoidZero(); - body = needsParentheses(actualExpression) ? factory.createParenthesizedExpression(actualExpression) : actualExpression; - copyTrailingAsLeadingComments(returnStatement, body, file, SyntaxKind.MultiLineCommentTrivia, /*hasTrailingNewLine*/ false); - copyLeadingComments(returnStatement, body, file, SyntaxKind.MultiLineCommentTrivia, /*hasTrailingNewLine*/ false); - copyTrailingComments(returnStatement, body, file, SyntaxKind.MultiLineCommentTrivia, /*hasTrailingNewLine*/ false); + body = needsParentheses(actualExpression) ? factory.createParenthesizedExpression(actualExpression) + : actualExpression; + copyTrailingAsLeadingComments( + returnStatement, + body, + file, + SyntaxKind.MultiLineCommentTrivia, + /*hasTrailingNewLine*/ false, + ); + copyLeadingComments( + returnStatement, + body, + file, + SyntaxKind.MultiLineCommentTrivia, + /*hasTrailingNewLine*/ false, + ); + copyTrailingComments( + returnStatement, + body, + file, + SyntaxKind.MultiLineCommentTrivia, + /*hasTrailingNewLine*/ false, + ); } else { Debug.fail("invalid action"); @@ -121,7 +149,12 @@ function getRefactorEditsToRemoveFunctionBraces(context: RefactorContext, action return { renameFilename: undefined, renameLocation: undefined, edits }; } -function getConvertibleArrowFunctionAtPosition(file: SourceFile, startPosition: number, considerFunctionBodies = true, kind?: string): FunctionBracesInfo | RefactorErrorInfo | undefined { +function getConvertibleArrowFunctionAtPosition( + file: SourceFile, + startPosition: number, + considerFunctionBodies = true, + kind?: string, +): FunctionBracesInfo | RefactorErrorInfo | undefined { const node = getTokenAtPosition(file, startPosition); const func = getContainingFunction(node); @@ -144,7 +177,9 @@ function getConvertibleArrowFunctionAtPosition(file: SourceFile, startPosition: if (refactorKindBeginsWith(addBracesAction.kind, kind) && isExpression(func.body)) { return { func, addBraces: true, expression: func.body }; } - else if (refactorKindBeginsWith(removeBracesAction.kind, kind) && isBlock(func.body) && func.body.statements.length === 1) { + else if ( + refactorKindBeginsWith(removeBracesAction.kind, kind) && isBlock(func.body) && func.body.statements.length === 1 + ) { const firstStatement = first(func.body.statements); if (isReturnStatement(firstStatement)) { return { func, addBraces: false, expression: firstStatement.expression, returnStatement: firstStatement }; diff --git a/src/services/refactors/convertArrowFunctionOrFunctionExpression.ts b/src/services/refactors/convertArrowFunctionOrFunctionExpression.ts index 05d13bdc8fd91..e15423f2ea44d 100644 --- a/src/services/refactors/convertArrowFunctionOrFunctionExpression.ts +++ b/src/services/refactors/convertArrowFunctionOrFunctionExpression.ts @@ -107,8 +107,8 @@ function getRefactorActionsToConvertFunctionExpressions(context: RefactorContext const possibleActions: RefactorActionInfo[] = []; const errors: RefactorActionInfo[] = []; if (refactorKindBeginsWith(toNamedFunctionAction.kind, kind)) { - const error = selectedVariableDeclaration || (isArrowFunction(func) && isVariableDeclaration(func.parent)) ? - undefined : getLocaleSpecificMessage(Diagnostics.Could_not_convert_to_named_function); + const error = selectedVariableDeclaration || (isArrowFunction(func) && isVariableDeclaration(func.parent)) + ? undefined : getLocaleSpecificMessage(Diagnostics.Could_not_convert_to_named_function); if (error) { errors.push({ ...toNamedFunctionAction, notApplicableReason: error }); } @@ -118,8 +118,8 @@ function getRefactorActionsToConvertFunctionExpressions(context: RefactorContext } if (refactorKindBeginsWith(toAnonymousFunctionAction.kind, kind)) { - const error = !selectedVariableDeclaration && isArrowFunction(func) ? - undefined : getLocaleSpecificMessage(Diagnostics.Could_not_convert_to_anonymous_function); + const error = !selectedVariableDeclaration && isArrowFunction(func) + ? undefined : getLocaleSpecificMessage(Diagnostics.Could_not_convert_to_anonymous_function); if (error) { errors.push({ ...toAnonymousFunctionAction, notApplicableReason: error }); } @@ -129,7 +129,8 @@ function getRefactorActionsToConvertFunctionExpressions(context: RefactorContext } if (refactorKindBeginsWith(toArrowFunctionAction.kind, kind)) { - const error = isFunctionExpression(func) ? undefined : getLocaleSpecificMessage(Diagnostics.Could_not_convert_to_arrow_function); + const error = isFunctionExpression(func) ? undefined + : getLocaleSpecificMessage(Diagnostics.Could_not_convert_to_arrow_function); if (error) { errors.push({ ...toArrowFunctionAction, notApplicableReason: error }); } @@ -141,12 +142,15 @@ function getRefactorActionsToConvertFunctionExpressions(context: RefactorContext return [{ name: refactorName, description: refactorDescription, - actions: possibleActions.length === 0 && context.preferences.provideRefactorNotApplicableReason ? - errors : possibleActions, + actions: possibleActions.length === 0 && context.preferences.provideRefactorNotApplicableReason + ? errors : possibleActions, }]; } -function getRefactorEditsToConvertFunctionExpressions(context: RefactorContext, actionName: string): RefactorEditInfo | undefined { +function getRefactorEditsToConvertFunctionExpressions( + context: RefactorContext, + actionName: string, +): RefactorEditInfo | undefined { const { file, startPosition, program } = context; const info = getFunctionInfo(file, startPosition, program); @@ -204,13 +208,15 @@ function getFunctionInfo(file: SourceFile, startPosition: number, program: Progr const maybeFunc = getContainingFunction(token); if ( - maybeFunc && - (isFunctionExpression(maybeFunc) || isArrowFunction(maybeFunc)) && - !rangeContainsRange(maybeFunc.body, token) && - !containingThis(maybeFunc.body) && - !typeChecker.containsArgumentsReference(maybeFunc) + maybeFunc + && (isFunctionExpression(maybeFunc) || isArrowFunction(maybeFunc)) + && !rangeContainsRange(maybeFunc.body, token) + && !containingThis(maybeFunc.body) + && !typeChecker.containsArgumentsReference(maybeFunc) ) { - if (isFunctionExpression(maybeFunc) && isFunctionReferencedInFile(file, typeChecker, maybeFunc)) return undefined; + if (isFunctionExpression(maybeFunc) && isFunctionReferencedInFile(file, typeChecker, maybeFunc)) { + return undefined; + } return { selectedVariableDeclaration: false, func: maybeFunc }; } @@ -221,13 +227,21 @@ function isSingleVariableDeclaration(parent: Node): parent is VariableDeclaratio return isVariableDeclaration(parent) || (isVariableDeclarationList(parent) && parent.declarations.length === 1); } -function tryGetFunctionFromVariableDeclaration(sourceFile: SourceFile, typeChecker: TypeChecker, parent: Node): ArrowFunction | FunctionExpression | undefined { +function tryGetFunctionFromVariableDeclaration( + sourceFile: SourceFile, + typeChecker: TypeChecker, + parent: Node, +): ArrowFunction | FunctionExpression | undefined { if (!isSingleVariableDeclaration(parent)) { return undefined; } const variableDeclaration = isVariableDeclaration(parent) ? parent : first(parent.declarations); const initializer = variableDeclaration.initializer; - if (initializer && (isArrowFunction(initializer) || isFunctionExpression(initializer) && !isFunctionReferencedInFile(sourceFile, typeChecker, initializer))) { + if ( + initializer + && (isArrowFunction(initializer) + || isFunctionExpression(initializer) && !isFunctionReferencedInFile(sourceFile, typeChecker, initializer)) + ) { return initializer; } return undefined; @@ -239,7 +253,13 @@ function convertToBlock(body: ConciseBody): Block { const file = body.getSourceFile(); setTextRange(returnStatement, body); suppressLeadingAndTrailingTrivia(returnStatement); - copyTrailingAsLeadingComments(body, returnStatement, file, /*commentKind*/ undefined, /*hasTrailingNewLine*/ true); + copyTrailingAsLeadingComments( + body, + returnStatement, + file, + /*commentKind*/ undefined, + /*hasTrailingNewLine*/ true, + ); return factory.createBlock([returnStatement], /*multiLine*/ true); } else { @@ -249,32 +269,61 @@ function convertToBlock(body: ConciseBody): Block { function getVariableInfo(func: FunctionExpression | ArrowFunction): VariableInfo | undefined { const variableDeclaration = func.parent; - if (!isVariableDeclaration(variableDeclaration) || !isVariableDeclarationInVariableStatement(variableDeclaration)) return undefined; + if (!isVariableDeclaration(variableDeclaration) || !isVariableDeclarationInVariableStatement(variableDeclaration)) { + return undefined; + } const variableDeclarationList = variableDeclaration.parent; const statement = variableDeclarationList.parent; - if (!isVariableDeclarationList(variableDeclarationList) || !isVariableStatement(statement) || !isIdentifier(variableDeclaration.name)) return undefined; + if ( + !isVariableDeclarationList(variableDeclarationList) || !isVariableStatement(statement) + || !isIdentifier(variableDeclaration.name) + ) return undefined; return { variableDeclaration, variableDeclarationList, statement, name: variableDeclaration.name }; } -function getEditInfoForConvertToAnonymousFunction(context: RefactorContext, func: FunctionExpression | ArrowFunction): FileTextChanges[] { +function getEditInfoForConvertToAnonymousFunction( + context: RefactorContext, + func: FunctionExpression | ArrowFunction, +): FileTextChanges[] { const { file } = context; const body = convertToBlock(func.body); - const newNode = factory.createFunctionExpression(func.modifiers, func.asteriskToken, /*name*/ undefined, func.typeParameters, func.parameters, func.type, body); + const newNode = factory.createFunctionExpression( + func.modifiers, + func.asteriskToken, + /*name*/ undefined, + func.typeParameters, + func.parameters, + func.type, + body, + ); return textChanges.ChangeTracker.with(context, t => t.replaceNode(file, func, newNode)); } -function getEditInfoForConvertToNamedFunction(context: RefactorContext, func: FunctionExpression | ArrowFunction, variableInfo: VariableInfo): FileTextChanges[] { +function getEditInfoForConvertToNamedFunction( + context: RefactorContext, + func: FunctionExpression | ArrowFunction, + variableInfo: VariableInfo, +): FileTextChanges[] { const { file } = context; const body = convertToBlock(func.body); const { variableDeclaration, variableDeclarationList, statement, name } = variableInfo; suppressLeadingTrivia(statement); - const modifiersFlags = (getCombinedModifierFlags(variableDeclaration) & ModifierFlags.Export) | getEffectiveModifierFlags(func); + const modifiersFlags = (getCombinedModifierFlags(variableDeclaration) & ModifierFlags.Export) + | getEffectiveModifierFlags(func); const modifiers = factory.createModifiersFromModifierFlags(modifiersFlags); - const newNode = factory.createFunctionDeclaration(length(modifiers) ? modifiers : undefined, func.asteriskToken, name, func.typeParameters, func.parameters, func.type, body); + const newNode = factory.createFunctionDeclaration( + length(modifiers) ? modifiers : undefined, + func.asteriskToken, + name, + func.typeParameters, + func.parameters, + func.type, + body, + ); if (variableDeclarationList.declarations.length === 1) { return textChanges.ChangeTracker.with(context, t => t.replaceNode(file, statement, newNode)); @@ -302,7 +351,14 @@ function getEditInfoForConvertToArrowFunction(context: RefactorContext, func: Fu body = func.body; } - const newNode = factory.createArrowFunction(func.modifiers, func.typeParameters, func.parameters, func.type, factory.createToken(SyntaxKind.EqualsGreaterThanToken), body); + const newNode = factory.createArrowFunction( + func.modifiers, + func.typeParameters, + func.parameters, + func.type, + factory.createToken(SyntaxKind.EqualsGreaterThanToken), + body, + ); return textChanges.ChangeTracker.with(context, t => t.replaceNode(file, func, newNode)); } @@ -310,6 +366,10 @@ function canBeConvertedToExpression(body: Block, head: Statement): head is Retur return body.statements.length === 1 && (isReturnStatement(head) && !!head.expression); } -function isFunctionReferencedInFile(sourceFile: SourceFile, typeChecker: TypeChecker, node: FunctionExpression): boolean { +function isFunctionReferencedInFile( + sourceFile: SourceFile, + typeChecker: TypeChecker, + node: FunctionExpression, +): boolean { return !!node.name && FindAllReferences.Core.isSymbolReferencedInFile(node.name, typeChecker, sourceFile); } diff --git a/src/services/refactors/convertExport.ts b/src/services/refactors/convertExport.ts index 342013cdac37b..0c94751233c05 100644 --- a/src/services/refactors/convertExport.ts +++ b/src/services/refactors/convertExport.ts @@ -75,7 +75,9 @@ registerRefactor(refactorName, { defaultToNamedAction.kind, namedToDefaultAction.kind, ], - getAvailableActions: function getRefactorActionsToConvertBetweenNamedAndDefaultExports(context): readonly ApplicableRefactorInfo[] { + getAvailableActions: function getRefactorActionsToConvertBetweenNamedAndDefaultExports( + context, + ): readonly ApplicableRefactorInfo[] { const info = getInfo(context, context.triggerReason === "invoked"); if (!info) return emptyArray; @@ -99,17 +101,34 @@ registerRefactor(refactorName, { return emptyArray; }, - getEditsForAction: function getRefactorEditsToConvertBetweenNamedAndDefaultExports(context, actionName): RefactorEditInfo { - Debug.assert(actionName === defaultToNamedAction.name || actionName === namedToDefaultAction.name, "Unexpected action name"); + getEditsForAction: function getRefactorEditsToConvertBetweenNamedAndDefaultExports( + context, + actionName, + ): RefactorEditInfo { + Debug.assert( + actionName === defaultToNamedAction.name || actionName === namedToDefaultAction.name, + "Unexpected action name", + ); const info = getInfo(context); Debug.assert(info && !isRefactorErrorInfo(info), "Expected applicable refactor info"); - const edits = textChanges.ChangeTracker.with(context, t => doChange(context.file, context.program, info, t, context.cancellationToken)); + const edits = textChanges.ChangeTracker.with( + context, + t => doChange(context.file, context.program, info, t, context.cancellationToken), + ); return { edits, renameFilename: undefined, renameLocation: undefined }; }, }); // If a VariableStatement, will have exactly one VariableDeclaration, with an Identifier for a name. -type ExportToConvert = FunctionDeclaration | ClassDeclaration | InterfaceDeclaration | EnumDeclaration | NamespaceDeclaration | TypeAliasDeclaration | VariableStatement | ExportAssignment; +type ExportToConvert = + | FunctionDeclaration + | ClassDeclaration + | InterfaceDeclaration + | EnumDeclaration + | NamespaceDeclaration + | TypeAliasDeclaration + | VariableStatement + | ExportAssignment; interface ExportInfo { readonly exportNode: ExportToConvert; readonly exportName: Identifier; // This is exportNode.name except for VariableStatement_s. @@ -121,18 +140,28 @@ function getInfo(context: RefactorContext, considerPartialSpans = true): ExportI const { file, program } = context; const span = getRefactorContextSpan(context); const token = getTokenAtPosition(file, span.start); - const exportNode = !!(token.parent && getSyntacticModifierFlags(token.parent) & ModifierFlags.Export) && considerPartialSpans ? token.parent : getParentNodeInSpan(token, file, span); - if (!exportNode || (!isSourceFile(exportNode.parent) && !(isModuleBlock(exportNode.parent) && isAmbientModule(exportNode.parent.parent)))) { + const exportNode = + !!(token.parent && getSyntacticModifierFlags(token.parent) & ModifierFlags.Export) && considerPartialSpans + ? token.parent : getParentNodeInSpan(token, file, span); + if ( + !exportNode + || (!isSourceFile(exportNode.parent) + && !(isModuleBlock(exportNode.parent) && isAmbientModule(exportNode.parent.parent))) + ) { return { error: getLocaleSpecificMessage(Diagnostics.Could_not_find_export_statement) }; } const checker = program.getTypeChecker(); const exportingModuleSymbol = getExportingModuleSymbol(exportNode.parent, checker); - const flags = getSyntacticModifierFlags(exportNode) || ((isExportAssignment(exportNode) && !exportNode.isExportEquals) ? ModifierFlags.ExportDefault : ModifierFlags.None); + const flags = getSyntacticModifierFlags(exportNode) + || ((isExportAssignment(exportNode) && !exportNode.isExportEquals) ? ModifierFlags.ExportDefault + : ModifierFlags.None); const wasDefault = !!(flags & ModifierFlags.Default); // If source file already has a default export, don't offer refactor. - if (!(flags & ModifierFlags.Export) || !wasDefault && exportingModuleSymbol.exports!.has(InternalSymbolName.Default)) { + if ( + !(flags & ModifierFlags.Export) || !wasDefault && exportingModuleSymbol.exports!.has(InternalSymbolName.Default) + ) { return { error: getLocaleSpecificMessage(Diagnostics.This_file_already_has_a_default_export) }; } @@ -147,7 +176,13 @@ function getInfo(context: RefactorContext, considerPartialSpans = true): ExportI case SyntaxKind.EnumDeclaration: case SyntaxKind.TypeAliasDeclaration: case SyntaxKind.ModuleDeclaration: { - const node = exportNode as FunctionDeclaration | ClassDeclaration | InterfaceDeclaration | EnumDeclaration | TypeAliasDeclaration | NamespaceDeclaration; + const node = exportNode as + | FunctionDeclaration + | ClassDeclaration + | InterfaceDeclaration + | EnumDeclaration + | TypeAliasDeclaration + | NamespaceDeclaration; if (!node.name) return undefined; return noSymbolError(node.name) || { exportNode: node, exportName: node.name, wasDefault, exportingModuleSymbol }; @@ -175,36 +210,77 @@ function getInfo(context: RefactorContext, considerPartialSpans = true): ExportI } } -function doChange(exportingSourceFile: SourceFile, program: Program, info: ExportInfo, changes: textChanges.ChangeTracker, cancellationToken: CancellationToken | undefined): void { +function doChange( + exportingSourceFile: SourceFile, + program: Program, + info: ExportInfo, + changes: textChanges.ChangeTracker, + cancellationToken: CancellationToken | undefined, +): void { changeExport(exportingSourceFile, info, changes, program.getTypeChecker()); changeImports(program, info, changes, cancellationToken); } -function changeExport(exportingSourceFile: SourceFile, { wasDefault, exportNode, exportName }: ExportInfo, changes: textChanges.ChangeTracker, checker: TypeChecker): void { +function changeExport( + exportingSourceFile: SourceFile, + { wasDefault, exportNode, exportName }: ExportInfo, + changes: textChanges.ChangeTracker, + checker: TypeChecker, +): void { if (wasDefault) { if (isExportAssignment(exportNode) && !exportNode.isExportEquals) { const exp = exportNode.expression as Identifier; const spec = makeExportSpecifier(exp.text, exp.text); - changes.replaceNode(exportingSourceFile, exportNode, factory.createExportDeclaration(/*modifiers*/ undefined, /*isTypeOnly*/ false, factory.createNamedExports([spec]))); + changes.replaceNode( + exportingSourceFile, + exportNode, + factory.createExportDeclaration( + /*modifiers*/ undefined, + /*isTypeOnly*/ false, + factory.createNamedExports([spec]), + ), + ); } else { - changes.delete(exportingSourceFile, Debug.checkDefined(findModifier(exportNode, SyntaxKind.DefaultKeyword), "Should find a default keyword in modifier list")); + changes.delete( + exportingSourceFile, + Debug.checkDefined( + findModifier(exportNode, SyntaxKind.DefaultKeyword), + "Should find a default keyword in modifier list", + ), + ); } } else { - const exportKeyword = Debug.checkDefined(findModifier(exportNode, SyntaxKind.ExportKeyword), "Should find an export keyword in modifier list"); + const exportKeyword = Debug.checkDefined( + findModifier(exportNode, SyntaxKind.ExportKeyword), + "Should find an export keyword in modifier list", + ); switch (exportNode.kind) { case SyntaxKind.FunctionDeclaration: case SyntaxKind.ClassDeclaration: case SyntaxKind.InterfaceDeclaration: - changes.insertNodeAfter(exportingSourceFile, exportKeyword, factory.createToken(SyntaxKind.DefaultKeyword)); + changes.insertNodeAfter( + exportingSourceFile, + exportKeyword, + factory.createToken(SyntaxKind.DefaultKeyword), + ); break; case SyntaxKind.VariableStatement: // If 'x' isn't used in this file and doesn't have type definition, `export const x = 0;` --> `export default 0;` const decl = first(exportNode.declarationList.declarations); - if (!FindAllReferences.Core.isSymbolReferencedInFile(exportName, checker, exportingSourceFile) && !decl.type) { + if ( + !FindAllReferences.Core.isSymbolReferencedInFile(exportName, checker, exportingSourceFile) + && !decl.type + ) { // We checked in `getInfo` that an initializer exists. - changes.replaceNode(exportingSourceFile, exportNode, factory.createExportDefault(Debug.checkDefined(decl.initializer, "Initializer was previously known to be present"))); + changes.replaceNode( + exportingSourceFile, + exportNode, + factory.createExportDefault( + Debug.checkDefined(decl.initializer, "Initializer was previously known to be present"), + ), + ); break; } // falls through @@ -213,7 +289,11 @@ function changeExport(exportingSourceFile: SourceFile, { wasDefault, exportNode, case SyntaxKind.ModuleDeclaration: // `export type T = number;` -> `type T = number; export default T;` changes.deleteModifier(exportingSourceFile, exportKeyword); - changes.insertNodeAfter(exportingSourceFile, exportNode, factory.createExportDefault(factory.createIdentifier(exportName.text))); + changes.insertNodeAfter( + exportingSourceFile, + exportNode, + factory.createExportDefault(factory.createIdentifier(exportName.text)), + ); break; default: Debug.fail(`Unexpected exportNode kind ${(exportNode as ExportToConvert).kind}`); @@ -221,22 +301,44 @@ function changeExport(exportingSourceFile: SourceFile, { wasDefault, exportNode, } } -function changeImports(program: Program, { wasDefault, exportName, exportingModuleSymbol }: ExportInfo, changes: textChanges.ChangeTracker, cancellationToken: CancellationToken | undefined): void { +function changeImports( + program: Program, + { wasDefault, exportName, exportingModuleSymbol }: ExportInfo, + changes: textChanges.ChangeTracker, + cancellationToken: CancellationToken | undefined, +): void { const checker = program.getTypeChecker(); - const exportSymbol = Debug.checkDefined(checker.getSymbolAtLocation(exportName), "Export name should resolve to a symbol"); - FindAllReferences.Core.eachExportReference(program.getSourceFiles(), checker, cancellationToken, exportSymbol, exportingModuleSymbol, exportName.text, wasDefault, ref => { - if (exportName === ref) return; - const importingSourceFile = ref.getSourceFile(); - if (wasDefault) { - changeDefaultToNamedImport(importingSourceFile, ref, changes, exportName.text); - } - else { - changeNamedToDefaultImport(importingSourceFile, ref, changes); - } - }); + const exportSymbol = Debug.checkDefined( + checker.getSymbolAtLocation(exportName), + "Export name should resolve to a symbol", + ); + FindAllReferences.Core.eachExportReference( + program.getSourceFiles(), + checker, + cancellationToken, + exportSymbol, + exportingModuleSymbol, + exportName.text, + wasDefault, + ref => { + if (exportName === ref) return; + const importingSourceFile = ref.getSourceFile(); + if (wasDefault) { + changeDefaultToNamedImport(importingSourceFile, ref, changes, exportName.text); + } + else { + changeNamedToDefaultImport(importingSourceFile, ref, changes); + } + }, + ); } -function changeDefaultToNamedImport(importingSourceFile: SourceFile, ref: Identifier, changes: textChanges.ChangeTracker, exportName: string): void { +function changeDefaultToNamedImport( + importingSourceFile: SourceFile, + ref: Identifier, + changes: textChanges.ChangeTracker, + exportName: string, +): void { const { parent } = ref; switch (parent.kind) { case SyntaxKind.PropertyAccessExpression: @@ -261,9 +363,19 @@ function changeDefaultToNamedImport(importingSourceFile: SourceFile, ref: Identi } else if (namedBindings.kind === SyntaxKind.NamespaceImport) { // `import foo, * as a from "./a";` --> `import * as a from ".a/"; import { foo } from "./a";` - changes.deleteRange(importingSourceFile, { pos: ref.getStart(importingSourceFile), end: namedBindings.getStart(importingSourceFile) }); - const quotePreference = isStringLiteral(clause.parent.moduleSpecifier) ? quotePreferenceFromString(clause.parent.moduleSpecifier, importingSourceFile) : QuotePreference.Double; - const newImport = makeImport(/*defaultImport*/ undefined, [makeImportSpecifier(exportName, ref.text)], clause.parent.moduleSpecifier, quotePreference); + changes.deleteRange(importingSourceFile, { + pos: ref.getStart(importingSourceFile), + end: namedBindings.getStart(importingSourceFile), + }); + const quotePreference = isStringLiteral(clause.parent.moduleSpecifier) + ? quotePreferenceFromString(clause.parent.moduleSpecifier, importingSourceFile) + : QuotePreference.Double; + const newImport = makeImport( + /*defaultImport*/ undefined, + [makeImportSpecifier(exportName, ref.text)], + clause.parent.moduleSpecifier, + quotePreference, + ); changes.insertNodeAfter(importingSourceFile, clause.parent, newImport); } else { @@ -275,14 +387,28 @@ function changeDefaultToNamedImport(importingSourceFile: SourceFile, ref: Identi } case SyntaxKind.ImportType: const importTypeNode = parent as ImportTypeNode; - changes.replaceNode(importingSourceFile, parent, factory.createImportTypeNode(importTypeNode.argument, importTypeNode.assertions, factory.createIdentifier(exportName), importTypeNode.typeArguments, importTypeNode.isTypeOf)); + changes.replaceNode( + importingSourceFile, + parent, + factory.createImportTypeNode( + importTypeNode.argument, + importTypeNode.assertions, + factory.createIdentifier(exportName), + importTypeNode.typeArguments, + importTypeNode.isTypeOf, + ), + ); break; default: Debug.failBadSyntaxKind(parent); } } -function changeNamedToDefaultImport(importingSourceFile: SourceFile, ref: Identifier, changes: textChanges.ChangeTracker): void { +function changeNamedToDefaultImport( + importingSourceFile: SourceFile, + ref: Identifier, + changes: textChanges.ChangeTracker, +): void { const parent = ref.parent as PropertyAccessExpression | ImportSpecifier | ExportSpecifier; switch (parent.kind) { case SyntaxKind.PropertyAccessExpression: @@ -316,11 +442,19 @@ function changeNamedToDefaultImport(importingSourceFile: SourceFile, ref: Identi } function makeImportSpecifier(propertyName: string, name: string): ImportSpecifier { - return factory.createImportSpecifier(/*isTypeOnly*/ false, propertyName === name ? undefined : factory.createIdentifier(propertyName), factory.createIdentifier(name)); + return factory.createImportSpecifier( + /*isTypeOnly*/ false, + propertyName === name ? undefined : factory.createIdentifier(propertyName), + factory.createIdentifier(name), + ); } function makeExportSpecifier(propertyName: string, name: string): ExportSpecifier { - return factory.createExportSpecifier(/*isTypeOnly*/ false, propertyName === name ? undefined : factory.createIdentifier(propertyName), factory.createIdentifier(name)); + return factory.createExportSpecifier( + /*isTypeOnly*/ false, + propertyName === name ? undefined : factory.createIdentifier(propertyName), + factory.createIdentifier(name), + ); } function getExportingModuleSymbol(parent: SourceFile | ModuleBlock, checker: TypeChecker) { diff --git a/src/services/refactors/convertImport.ts b/src/services/refactors/convertImport.ts index fdcaccff5773c..dfa5e7ff8c660 100644 --- a/src/services/refactors/convertImport.ts +++ b/src/services/refactors/convertImport.ts @@ -72,7 +72,9 @@ const actions = { registerRefactor(refactorName, { kinds: getOwnValues(actions).map(a => a.kind), - getAvailableActions: function getRefactorActionsToConvertBetweenNamedAndNamespacedImports(context): readonly ApplicableRefactorInfo[] { + getAvailableActions: function getRefactorActionsToConvertBetweenNamedAndNamespacedImports( + context, + ): readonly ApplicableRefactorInfo[] { const info = getImportConversionInfo(context, context.triggerReason === "invoked"); if (!info) return emptyArray; @@ -91,7 +93,10 @@ registerRefactor(refactorName, { return emptyArray; }, - getEditsForAction: function getRefactorEditsToConvertBetweenNamedAndNamespacedImports(context, actionName): RefactorEditInfo { + getEditsForAction: function getRefactorEditsToConvertBetweenNamedAndNamespacedImports( + context, + actionName, + ): RefactorEditInfo { Debug.assert(some(getOwnValues(actions), action => action.name === actionName), "Unexpected action name"); const info = getImportConversionInfo(context); Debug.assert(info && !isRefactorErrorInfo(info), "Expected applicable refactor info"); @@ -106,11 +111,15 @@ type ImportConversionInfo = | { convertTo: ImportKind.Namespace; import: NamedImports; } | { convertTo: ImportKind.Named; import: NamespaceImport; }; -function getImportConversionInfo(context: RefactorContext, considerPartialSpans = true): ImportConversionInfo | RefactorErrorInfo | undefined { +function getImportConversionInfo( + context: RefactorContext, + considerPartialSpans = true, +): ImportConversionInfo | RefactorErrorInfo | undefined { const { file } = context; const span = getRefactorContextSpan(context); const token = getTokenAtPosition(file, span.start); - const importDecl = considerPartialSpans ? findAncestor(token, isImportDeclaration) : getParentNodeInSpan(token, file, span); + const importDecl = considerPartialSpans ? findAncestor(token, isImportDeclaration) + : getParentNodeInSpan(token, file, span); if (!importDecl || !isImportDeclaration(importDecl)) return { error: "Selection is not an import declaration." }; const end = span.start + span.length; @@ -141,17 +150,40 @@ function getShouldUseDefault(program: Program, importClause: ImportClause) { && isExportEqualsModule(importClause.parent.moduleSpecifier, program.getTypeChecker()); } -function doChange(sourceFile: SourceFile, program: Program, changes: textChanges.ChangeTracker, info: ImportConversionInfo): void { +function doChange( + sourceFile: SourceFile, + program: Program, + changes: textChanges.ChangeTracker, + info: ImportConversionInfo, +): void { const checker = program.getTypeChecker(); if (info.convertTo === ImportKind.Named) { - doChangeNamespaceToNamed(sourceFile, checker, changes, info.import, getAllowSyntheticDefaultImports(program.getCompilerOptions())); + doChangeNamespaceToNamed( + sourceFile, + checker, + changes, + info.import, + getAllowSyntheticDefaultImports(program.getCompilerOptions()), + ); } else { - doChangeNamedToNamespaceOrDefault(sourceFile, program, changes, info.import, info.convertTo === ImportKind.Default); + doChangeNamedToNamespaceOrDefault( + sourceFile, + program, + changes, + info.import, + info.convertTo === ImportKind.Default, + ); } } -function doChangeNamespaceToNamed(sourceFile: SourceFile, checker: TypeChecker, changes: textChanges.ChangeTracker, toConvert: NamespaceImport, allowSyntheticDefaultImports: boolean): void { +function doChangeNamespaceToNamed( + sourceFile: SourceFile, + checker: TypeChecker, + changes: textChanges.ChangeTracker, + toConvert: NamespaceImport, + allowSyntheticDefaultImports: boolean, +): void { let usedAsNamespaceOrDefault = false; const nodesToReplace: (PropertyAccessExpression | QualifiedName)[] = []; @@ -178,36 +210,69 @@ function doChangeNamespaceToNamed(sourceFile: SourceFile, checker: TypeChecker, const exportName = getRightOfPropertyAccessOrQualifiedName(propertyAccessOrQualifiedName).text; let importName = exportNameToImportName.get(exportName); if (importName === undefined) { - exportNameToImportName.set(exportName, importName = conflictingNames.has(exportName) ? getUniqueName(exportName, sourceFile) : exportName); + exportNameToImportName.set( + exportName, + importName = conflictingNames.has(exportName) ? getUniqueName(exportName, sourceFile) : exportName, + ); } changes.replaceNode(sourceFile, propertyAccessOrQualifiedName, factory.createIdentifier(importName)); } const importSpecifiers: ImportSpecifier[] = []; exportNameToImportName.forEach((name, propertyName) => { - importSpecifiers.push(factory.createImportSpecifier(/*isTypeOnly*/ false, name === propertyName ? undefined : factory.createIdentifier(propertyName), factory.createIdentifier(name))); + importSpecifiers.push( + factory.createImportSpecifier( + /*isTypeOnly*/ false, + name === propertyName ? undefined : factory.createIdentifier(propertyName), + factory.createIdentifier(name), + ), + ); }); const importDecl = toConvert.parent.parent; if (usedAsNamespaceOrDefault && !allowSyntheticDefaultImports) { // Need to leave the namespace import alone - changes.insertNodeAfter(sourceFile, importDecl, updateImport(importDecl, /*defaultImportName*/ undefined, importSpecifiers)); + changes.insertNodeAfter( + sourceFile, + importDecl, + updateImport(importDecl, /*defaultImportName*/ undefined, importSpecifiers), + ); } else { - changes.replaceNode(sourceFile, importDecl, updateImport(importDecl, usedAsNamespaceOrDefault ? factory.createIdentifier(toConvert.name.text) : undefined, importSpecifiers)); + changes.replaceNode( + sourceFile, + importDecl, + updateImport( + importDecl, + usedAsNamespaceOrDefault ? factory.createIdentifier(toConvert.name.text) : undefined, + importSpecifiers, + ), + ); } } -function getRightOfPropertyAccessOrQualifiedName(propertyAccessOrQualifiedName: PropertyAccessExpression | QualifiedName) { - return isPropertyAccessExpression(propertyAccessOrQualifiedName) ? propertyAccessOrQualifiedName.name : propertyAccessOrQualifiedName.right; +function getRightOfPropertyAccessOrQualifiedName( + propertyAccessOrQualifiedName: PropertyAccessExpression | QualifiedName, +) { + return isPropertyAccessExpression(propertyAccessOrQualifiedName) ? propertyAccessOrQualifiedName.name + : propertyAccessOrQualifiedName.right; } -function getLeftOfPropertyAccessOrQualifiedName(propertyAccessOrQualifiedName: PropertyAccessExpression | QualifiedName) { - return isPropertyAccessExpression(propertyAccessOrQualifiedName) ? propertyAccessOrQualifiedName.expression : propertyAccessOrQualifiedName.left; +function getLeftOfPropertyAccessOrQualifiedName( + propertyAccessOrQualifiedName: PropertyAccessExpression | QualifiedName, +) { + return isPropertyAccessExpression(propertyAccessOrQualifiedName) ? propertyAccessOrQualifiedName.expression + : propertyAccessOrQualifiedName.left; } /** @internal */ -export function doChangeNamedToNamespaceOrDefault(sourceFile: SourceFile, program: Program, changes: textChanges.ChangeTracker, toConvert: NamedImports, shouldUseDefault = getShouldUseDefault(program, toConvert.parent)): void { +export function doChangeNamedToNamespaceOrDefault( + sourceFile: SourceFile, + program: Program, + changes: textChanges.ChangeTracker, + toConvert: NamedImports, + shouldUseDefault = getShouldUseDefault(program, toConvert.parent), +): void { const checker = program.getTypeChecker(); const importDecl = toConvert.parent.parent; const { moduleSpecifier } = importDecl; @@ -219,7 +284,8 @@ export function doChangeNamedToNamespaceOrDefault(sourceFile: SourceFile, progra toConvertSymbols.add(symbol); } }); - const preferredName = moduleSpecifier && isStringLiteral(moduleSpecifier) ? codefix.moduleSpecifierToValidIdentifier(moduleSpecifier.text, ScriptTarget.ESNext) : "module"; + const preferredName = moduleSpecifier && isStringLiteral(moduleSpecifier) + ? codefix.moduleSpecifierToValidIdentifier(moduleSpecifier.text, ScriptTarget.ESNext) : "module"; function hasNamespaceNameConflict(namedImport: ImportSpecifier): boolean { // We need to check if the preferred namespace name (`preferredName`) we'd like to use in the refactored code will present a name conflict. // A name conflict means that, in a scope where we would like to use the preferred namespace name, there already exists a symbol with that name in that scope. @@ -246,7 +312,10 @@ export function doChangeNamedToNamespaceOrDefault(sourceFile: SourceFile, progra for (const element of toConvert.elements) { const propertyName = (element.propertyName || element.name).text; FindAllReferences.Core.eachSymbolReferenceInFile(element.name, checker, sourceFile, id => { - const access = factory.createPropertyAccessExpression(factory.createIdentifier(namespaceImportName), propertyName); + const access = factory.createPropertyAccessExpression( + factory.createIdentifier(namespaceImportName), + propertyName, + ); if (isShorthandPropertyAssignment(id.parent)) { changes.replaceNode(sourceFile, id.parent, factory.createPropertyAssignment(id.text, access)); } @@ -267,8 +336,20 @@ export function doChangeNamedToNamespaceOrDefault(sourceFile: SourceFile, progra : factory.createNamespaceImport(factory.createIdentifier(namespaceImportName)), ); if (neededNamedImports.size) { - const newNamedImports: ImportSpecifier[] = arrayFrom(neededNamedImports.values(), element => factory.createImportSpecifier(element.isTypeOnly, element.propertyName && factory.createIdentifier(element.propertyName.text), factory.createIdentifier(element.name.text))); - changes.insertNodeAfter(sourceFile, toConvert.parent.parent, updateImport(importDecl, /*defaultImportName*/ undefined, newNamedImports)); + const newNamedImports: ImportSpecifier[] = arrayFrom( + neededNamedImports.values(), + element => + factory.createImportSpecifier( + element.isTypeOnly, + element.propertyName && factory.createIdentifier(element.propertyName.text), + factory.createIdentifier(element.name.text), + ), + ); + changes.insertNodeAfter( + sourceFile, + toConvert.parent.parent, + updateImport(importDecl, /*defaultImportName*/ undefined, newNamedImports), + ); } } @@ -279,6 +360,19 @@ function isExportEqualsModule(moduleSpecifier: Expression, checker: TypeChecker) return externalModule !== exportEquals; } -function updateImport(old: ImportDeclaration, defaultImportName: Identifier | undefined, elements: readonly ImportSpecifier[] | undefined): ImportDeclaration { - return factory.createImportDeclaration(/*modifiers*/ undefined, factory.createImportClause(/*isTypeOnly*/ false, defaultImportName, elements && elements.length ? factory.createNamedImports(elements) : undefined), old.moduleSpecifier, /*assertClause*/ undefined); +function updateImport( + old: ImportDeclaration, + defaultImportName: Identifier | undefined, + elements: readonly ImportSpecifier[] | undefined, +): ImportDeclaration { + return factory.createImportDeclaration( + /*modifiers*/ undefined, + factory.createImportClause( + /*isTypeOnly*/ false, + defaultImportName, + elements && elements.length ? factory.createNamedImports(elements) : undefined, + ), + old.moduleSpecifier, + /*assertClause*/ undefined, + ); } diff --git a/src/services/refactors/convertOverloadListToSingleSignature.ts b/src/services/refactors/convertOverloadListToSingleSignature.ts index 6eccdbb06af61..78b6cb6f29645 100644 --- a/src/services/refactors/convertOverloadListToSingleSignature.ts +++ b/src/services/refactors/convertOverloadListToSingleSignature.ts @@ -58,7 +58,9 @@ registerRefactor(refactorName, { getAvailableActions: getRefactorActionsToConvertOverloadsToOneSignature, }); -function getRefactorActionsToConvertOverloadsToOneSignature(context: RefactorContext): readonly ApplicableRefactorInfo[] { +function getRefactorActionsToConvertOverloadsToOneSignature( + context: RefactorContext, +): readonly ApplicableRefactorInfo[] { const { file, startPosition, program } = context; const info = getConvertableOverloadListAtPosition(file, startPosition, program); if (!info) return emptyArray; @@ -147,7 +149,10 @@ function getRefactorEditsToConvertOverloadsToOneSignature(context: RefactorConte break; } default: - return Debug.failBadSyntaxKind(lastDeclaration, "Unhandled signature kind in overload list conversion refactoring"); + return Debug.failBadSyntaxKind( + lastDeclaration, + "Unhandled signature kind in overload list conversion refactoring", + ); } if (updated === lastDeclaration) { @@ -160,7 +165,16 @@ function getRefactorEditsToConvertOverloadsToOneSignature(context: RefactorConte return { renameFilename: undefined, renameLocation: undefined, edits }; - function getNewParametersForCombinedSignature(signatureDeclarations: (MethodSignature | MethodDeclaration | CallSignatureDeclaration | ConstructorDeclaration | ConstructSignatureDeclaration | FunctionDeclaration)[]): NodeArray { + function getNewParametersForCombinedSignature( + signatureDeclarations: ( + | MethodSignature + | MethodDeclaration + | CallSignatureDeclaration + | ConstructorDeclaration + | ConstructSignatureDeclaration + | FunctionDeclaration + )[], + ): NodeArray { const lastSig = signatureDeclarations[signatureDeclarations.length - 1]; if (isFunctionLikeDeclaration(lastSig) && lastSig.body) { // Trim away implementation signature arguments (they should already be compatible with overloads, but are likely less precise to guarantee compatability with the overloads) @@ -177,9 +191,20 @@ function getRefactorEditsToConvertOverloadsToOneSignature(context: RefactorConte ]); } - function convertSignatureParametersToTuple(decl: MethodSignature | MethodDeclaration | CallSignatureDeclaration | ConstructorDeclaration | ConstructSignatureDeclaration | FunctionDeclaration): TupleTypeNode { + function convertSignatureParametersToTuple( + decl: + | MethodSignature + | MethodDeclaration + | CallSignatureDeclaration + | ConstructorDeclaration + | ConstructSignatureDeclaration + | FunctionDeclaration, + ): TupleTypeNode { const members = map(decl.parameters, convertParameterToNamedTupleMember); - return setEmitFlags(factory.createTupleTypeNode(members), some(members, m => !!length(getSyntheticLeadingComments(m))) ? EmitFlags.None : EmitFlags.SingleLine); + return setEmitFlags( + factory.createTupleTypeNode(members), + some(members, m => !!length(getSyntheticLeadingComments(m))) ? EmitFlags.None : EmitFlags.SingleLine, + ); } function convertParameterToNamedTupleMember(p: ParameterDeclaration): NamedTupleMember { @@ -213,7 +238,16 @@ ${newComment.split("\n").map(c => ` * ${c}`).join("\n")} } } -function isConvertableSignatureDeclaration(d: Node): d is MethodSignature | MethodDeclaration | CallSignatureDeclaration | ConstructorDeclaration | ConstructSignatureDeclaration | FunctionDeclaration { +function isConvertableSignatureDeclaration( + d: Node, +): d is + | MethodSignature + | MethodDeclaration + | CallSignatureDeclaration + | ConstructorDeclaration + | ConstructSignatureDeclaration + | FunctionDeclaration +{ switch (d.kind) { case SyntaxKind.MethodSignature: case SyntaxKind.MethodDeclaration: @@ -232,7 +266,10 @@ function getConvertableOverloadListAtPosition(file: SourceFile, startPosition: n if (!containingDecl) { return; } - if (isFunctionLikeDeclaration(containingDecl) && containingDecl.body && rangeContainsPosition(containingDecl.body, startPosition)) { + if ( + isFunctionLikeDeclaration(containingDecl) && containingDecl.body + && rangeContainsPosition(containingDecl.body, startPosition) + ) { return; } @@ -255,8 +292,17 @@ function getConvertableOverloadListAtPosition(file: SourceFile, startPosition: n if (!every(decls, d => d.kind === kindOne)) { return; } - const signatureDecls = decls as (MethodSignature | MethodDeclaration | CallSignatureDeclaration | ConstructorDeclaration | ConstructSignatureDeclaration | FunctionDeclaration)[]; - if (some(signatureDecls, d => !!d.typeParameters || some(d.parameters, p => !!p.modifiers || !isIdentifier(p.name)))) { + const signatureDecls = decls as ( + | MethodSignature + | MethodDeclaration + | CallSignatureDeclaration + | ConstructorDeclaration + | ConstructSignatureDeclaration + | FunctionDeclaration + )[]; + if ( + some(signatureDecls, d => !!d.typeParameters || some(d.parameters, p => !!p.modifiers || !isIdentifier(p.name))) + ) { return; } const signatures = mapDefined(signatureDecls, d => checker.getSignatureFromDeclaration(d)); diff --git a/src/services/refactors/convertParamsToDestructuredObject.ts b/src/services/refactors/convertParamsToDestructuredObject.ts index e0d32869e5877..597226c555203 100644 --- a/src/services/refactors/convertParamsToDestructuredObject.ts +++ b/src/services/refactors/convertParamsToDestructuredObject.ts @@ -123,7 +123,9 @@ registerRefactor(refactorName, { getAvailableActions: getRefactorActionsToConvertParametersToDestructuredObject, }); -function getRefactorActionsToConvertParametersToDestructuredObject(context: RefactorContext): readonly ApplicableRefactorInfo[] { +function getRefactorActionsToConvertParametersToDestructuredObject( + context: RefactorContext, +): readonly ApplicableRefactorInfo[] { const { file, startPosition } = context; const isJSFile = isSourceFileJS(file); if (isJSFile) return emptyArray; // TODO: GH#30113 @@ -137,7 +139,10 @@ function getRefactorActionsToConvertParametersToDestructuredObject(context: Refa }]; } -function getRefactorEditsToConvertParametersToDestructuredObject(context: RefactorContext, actionName: string): RefactorEditInfo | undefined { +function getRefactorEditsToConvertParametersToDestructuredObject( + context: RefactorContext, + actionName: string, +): RefactorEditInfo | undefined { Debug.assert(actionName === refactorName, "Unexpected action name"); const { file, startPosition, program, cancellationToken, host } = context; const functionDeclaration = getFunctionDeclarationAtPosition(file, startPosition, program.getTypeChecker()); @@ -145,7 +150,10 @@ function getRefactorEditsToConvertParametersToDestructuredObject(context: Refact const groupedReferences = getGroupedReferences(functionDeclaration, program, cancellationToken); if (groupedReferences.valid) { - const edits = textChanges.ChangeTracker.with(context, t => doChange(file, program, host, t, functionDeclaration, groupedReferences)); + const edits = textChanges.ChangeTracker.with( + context, + t => doChange(file, program, host, t, functionDeclaration, groupedReferences), + ); return { renameFilename: undefined, renameLocation: undefined, edits }; } @@ -161,29 +169,47 @@ function doChange( groupedReferences: GroupedReferences, ): void { const signature = groupedReferences.signature; - const newFunctionDeclarationParams = map(createNewParameters(functionDeclaration, program, host), param => getSynthesizedDeepClone(param)); + const newFunctionDeclarationParams = map( + createNewParameters(functionDeclaration, program, host), + param => getSynthesizedDeepClone(param), + ); if (signature) { - const newSignatureParams = map(createNewParameters(signature, program, host), param => getSynthesizedDeepClone(param)); + const newSignatureParams = map( + createNewParameters(signature, program, host), + param => getSynthesizedDeepClone(param), + ); replaceParameters(signature, newSignatureParams); } replaceParameters(functionDeclaration, newFunctionDeclarationParams); - const functionCalls = sortAndDeduplicate(groupedReferences.functionCalls, /*comparer*/ (a, b) => compareValues(a.pos, b.pos)); + const functionCalls = sortAndDeduplicate( + groupedReferences.functionCalls, + /*comparer*/ (a, b) => compareValues(a.pos, b.pos), + ); for (const call of functionCalls) { if (call.arguments && call.arguments.length) { - const newArgument = getSynthesizedDeepClone(createNewArgument(functionDeclaration, call.arguments), /*includeTrivia*/ true); + const newArgument = getSynthesizedDeepClone( + createNewArgument(functionDeclaration, call.arguments), + /*includeTrivia*/ true, + ); changes.replaceNodeRange( getSourceFileOfNode(call), first(call.arguments), last(call.arguments), newArgument, - { leadingTriviaOption: textChanges.LeadingTriviaOption.IncludeAll, trailingTriviaOption: textChanges.TrailingTriviaOption.Include }, + { + leadingTriviaOption: textChanges.LeadingTriviaOption.IncludeAll, + trailingTriviaOption: textChanges.TrailingTriviaOption.Include, + }, ); } } - function replaceParameters(declarationOrSignature: ValidFunctionDeclaration | ValidMethodSignature, parameterDeclarations: ParameterDeclaration[]) { + function replaceParameters( + declarationOrSignature: ValidFunctionDeclaration | ValidMethodSignature, + parameterDeclarations: ParameterDeclaration[], + ) { changes.replaceNodeRangeWithNodes( sourceFile, first(declarationOrSignature.parameters), @@ -200,13 +226,27 @@ function doChange( } } -function getGroupedReferences(functionDeclaration: ValidFunctionDeclaration, program: Program, cancellationToken: CancellationToken): GroupedReferences { +function getGroupedReferences( + functionDeclaration: ValidFunctionDeclaration, + program: Program, + cancellationToken: CancellationToken, +): GroupedReferences { const functionNames = getFunctionNames(functionDeclaration); const classNames = isConstructorDeclaration(functionDeclaration) ? getClassNames(functionDeclaration) : []; const names = deduplicate([...functionNames, ...classNames], equateValues); const checker = program.getTypeChecker(); - const references = flatMap(names, /*mapfn*/ name => FindAllReferences.getReferenceEntriesForNode(-1, name, program, program.getSourceFiles(), cancellationToken)); + const references = flatMap( + names, + /*mapfn*/ name => + FindAllReferences.getReferenceEntriesForNode( + -1, + name, + program, + program.getSourceFiles(), + cancellationToken, + ), + ); const groupedReferences = groupReferences(references); if (!every(groupedReferences.declarations, /*callback*/ decl => contains(names, decl))) { @@ -217,7 +257,12 @@ function getGroupedReferences(functionDeclaration: ValidFunctionDeclaration, pro function groupReferences(referenceEntries: readonly FindAllReferences.Entry[]): GroupedReferences { const classReferences: ClassReferences = { accessExpressions: [], typeUsages: [] }; - const groupedReferences: GroupedReferences = { functionCalls: [], declarations: [], classReferences, valid: true }; + const groupedReferences: GroupedReferences = { + functionCalls: [], + declarations: [], + classReferences, + valid: true, + }; const functionSymbols = map(functionNames, getSymbolTargetAtLocation); const classSymbols = map(classNames, getSymbolTargetAtLocation); const isConstructor = isConstructorDeclaration(functionDeclaration); @@ -380,7 +425,10 @@ function entryToFunctionCall(entry: FindAllReferences.NodeEntry): CallExpression // x.foo(...) case SyntaxKind.PropertyAccessExpression: const propertyAccessExpression = tryCast(parent, isPropertyAccessExpression); - if (propertyAccessExpression && propertyAccessExpression.parent && propertyAccessExpression.name === functionReference) { + if ( + propertyAccessExpression && propertyAccessExpression.parent + && propertyAccessExpression.name === functionReference + ) { const callOrNewExpression = tryCast(propertyAccessExpression.parent, isCallOrNewExpression); if (callOrNewExpression && callOrNewExpression.expression === propertyAccessExpression) { return callOrNewExpression; @@ -390,7 +438,10 @@ function entryToFunctionCall(entry: FindAllReferences.NodeEntry): CallExpression // x["foo"](...) case SyntaxKind.ElementAccessExpression: const elementAccessExpression = tryCast(parent, isElementAccessExpression); - if (elementAccessExpression && elementAccessExpression.parent && elementAccessExpression.argumentExpression === functionReference) { + if ( + elementAccessExpression && elementAccessExpression.parent + && elementAccessExpression.argumentExpression === functionReference + ) { const callOrNewExpression = tryCast(elementAccessExpression.parent, isCallOrNewExpression); if (callOrNewExpression && callOrNewExpression.expression === elementAccessExpression) { return callOrNewExpression; @@ -402,7 +453,9 @@ function entryToFunctionCall(entry: FindAllReferences.NodeEntry): CallExpression return undefined; } -function entryToAccessExpression(entry: FindAllReferences.NodeEntry): ElementAccessExpression | PropertyAccessExpression | undefined { +function entryToAccessExpression( + entry: FindAllReferences.NodeEntry, +): ElementAccessExpression | PropertyAccessExpression | undefined { if (entry.node.parent) { const reference = entry.node; const parent = reference.parent; @@ -428,13 +481,20 @@ function entryToAccessExpression(entry: FindAllReferences.NodeEntry): ElementAcc function entryToType(entry: FindAllReferences.NodeEntry): Node | undefined { const reference = entry.node; - if (getMeaningFromLocation(reference) === SemanticMeaning.Type || isExpressionWithTypeArgumentsInClassExtendsClause(reference.parent)) { + if ( + getMeaningFromLocation(reference) === SemanticMeaning.Type + || isExpressionWithTypeArgumentsInClassExtendsClause(reference.parent) + ) { return reference; } return undefined; } -function getFunctionDeclarationAtPosition(file: SourceFile, startPosition: number, checker: TypeChecker): ValidFunctionDeclaration | undefined { +function getFunctionDeclarationAtPosition( + file: SourceFile, + startPosition: number, + checker: TypeChecker, +): ValidFunctionDeclaration | undefined { const node = getTouchingToken(file, startPosition); const functionDeclaration = getContainingFunctionDeclaration(node); @@ -476,12 +536,14 @@ function isValidFunctionDeclaration( if (isObjectLiteralExpression(functionDeclaration.parent)) { const contextualSymbol = getSymbolForContextualType(functionDeclaration.name, checker); // don't offer the refactor when there are multiple signatures since we won't know which ones the user wants to change - return contextualSymbol?.declarations?.length === 1 && isSingleImplementation(functionDeclaration, checker); + return contextualSymbol?.declarations?.length === 1 + && isSingleImplementation(functionDeclaration, checker); } return isSingleImplementation(functionDeclaration, checker); case SyntaxKind.Constructor: if (isClassDeclaration(functionDeclaration.parent)) { - return hasNameOrDefault(functionDeclaration.parent) && isSingleImplementation(functionDeclaration, checker); + return hasNameOrDefault(functionDeclaration.parent) + && isSingleImplementation(functionDeclaration, checker); } else { return isValidVariableDeclaration(functionDeclaration.parent.parent) @@ -540,21 +602,29 @@ function getRefactorableParametersLength(parameters: NodeArray): NodeArray { +function getRefactorableParameters( + parameters: NodeArray, +): NodeArray { if (hasThisParameter(parameters)) { parameters = factory.createNodeArray(parameters.slice(1), parameters.hasTrailingComma); } return parameters; } -function createPropertyOrShorthandAssignment(name: string, initializer: Expression): PropertyAssignment | ShorthandPropertyAssignment { +function createPropertyOrShorthandAssignment( + name: string, + initializer: Expression, +): PropertyAssignment | ShorthandPropertyAssignment { if (isIdentifier(initializer) && getTextOfIdentifierOrLiteral(initializer) === name) { return factory.createShorthandPropertyAssignment(name); } return factory.createPropertyAssignment(name, initializer); } -function createNewArgument(functionDeclaration: ValidFunctionDeclaration, functionArguments: NodeArray): ObjectLiteralExpression { +function createNewArgument( + functionDeclaration: ValidFunctionDeclaration, + functionArguments: NodeArray, +): ObjectLiteralExpression { const parameters = getRefactorableParameters(functionDeclaration.parameters); const hasRestParameter = isRestParameter(last(parameters)); const nonRestArguments = hasRestParameter ? functionArguments.slice(0, parameters.length - 1) : functionArguments; @@ -570,7 +640,10 @@ function createNewArgument(functionDeclaration: ValidFunctionDeclaration, functi if (hasRestParameter && functionArguments.length >= parameters.length) { const restArguments = functionArguments.slice(parameters.length - 1); - const restProperty = factory.createPropertyAssignment(getParameterName(last(parameters)), factory.createArrayLiteralExpression(restArguments)); + const restProperty = factory.createPropertyAssignment( + getParameterName(last(parameters)), + factory.createArrayLiteralExpression(restArguments), + ); properties.push(restProperty); } @@ -578,7 +651,11 @@ function createNewArgument(functionDeclaration: ValidFunctionDeclaration, functi return objectLiteral; } -function createNewParameters(functionDeclaration: ValidFunctionDeclaration | ValidMethodSignature, program: Program, host: LanguageServiceHost): NodeArray { +function createNewParameters( + functionDeclaration: ValidFunctionDeclaration | ValidMethodSignature, + program: Program, + host: LanguageServiceHost, +): NodeArray { const checker = program.getTypeChecker(); const refactorableParameters = getRefactorableParameters(functionDeclaration.parameters); const bindingElements = map(refactorableParameters, createBindingElementFromParameterDeclaration); @@ -621,12 +698,15 @@ function createNewParameters(functionDeclaration: ValidFunctionDeclaration | Val } return factory.createNodeArray([objectParameter]); - function createBindingElementFromParameterDeclaration(parameterDeclaration: ValidParameterDeclaration): BindingElement { + function createBindingElementFromParameterDeclaration( + parameterDeclaration: ValidParameterDeclaration, + ): BindingElement { const element = factory.createBindingElement( /*dotDotDotToken*/ undefined, /*propertyName*/ undefined, getParameterName(parameterDeclaration), - isRestParameter(parameterDeclaration) && isOptionalParameter(parameterDeclaration) ? factory.createArrayLiteralExpression() : parameterDeclaration.initializer, + isRestParameter(parameterDeclaration) && isOptionalParameter(parameterDeclaration) + ? factory.createArrayLiteralExpression() : parameterDeclaration.initializer, ); suppressLeadingAndTrailingTrivia(element); @@ -642,7 +722,9 @@ function createNewParameters(functionDeclaration: ValidFunctionDeclaration | Val return typeNode; } - function createPropertySignatureFromParameterDeclaration(parameterDeclaration: ValidParameterDeclaration): PropertySignature { + function createPropertySignatureFromParameterDeclaration( + parameterDeclaration: ValidParameterDeclaration, + ): PropertySignature { let parameterType = parameterDeclaration.type; if (!parameterType && (parameterDeclaration.initializer || isRestParameter(parameterDeclaration))) { parameterType = getTypeNode(parameterDeclaration); @@ -651,7 +733,8 @@ function createNewParameters(functionDeclaration: ValidFunctionDeclaration | Val const propertySignature = factory.createPropertySignature( /*modifiers*/ undefined, getParameterName(parameterDeclaration), - isOptionalParameter(parameterDeclaration) ? factory.createToken(SyntaxKind.QuestionToken) : parameterDeclaration.questionToken, + isOptionalParameter(parameterDeclaration) ? factory.createToken(SyntaxKind.QuestionToken) + : parameterDeclaration.questionToken, parameterType, ); @@ -718,7 +801,11 @@ function getFunctionNames(functionDeclaration: ValidFunctionDeclaration): Node[] return [functionDeclaration.name]; case SyntaxKind.Constructor: const ctrKeyword = Debug.checkDefined( - findChildOfKind(functionDeclaration, SyntaxKind.ConstructorKeyword, functionDeclaration.getSourceFile()), + findChildOfKind( + functionDeclaration, + SyntaxKind.ConstructorKeyword, + functionDeclaration.getSourceFile(), + ), "Constructor declaration should have constructor keyword", ); if (functionDeclaration.parent.kind === SyntaxKind.ClassExpression) { @@ -732,7 +819,10 @@ function getFunctionNames(functionDeclaration: ValidFunctionDeclaration): Node[] if (functionDeclaration.name) return [functionDeclaration.name, functionDeclaration.parent.name]; return [functionDeclaration.parent.name]; default: - return Debug.assertNever(functionDeclaration, `Unexpected function declaration kind ${(functionDeclaration as ValidFunctionDeclaration).kind}`); + return Debug.assertNever( + functionDeclaration, + `Unexpected function declaration kind ${(functionDeclaration as ValidFunctionDeclaration).kind}`, + ); } } @@ -773,7 +863,12 @@ interface ValidMethodSignature extends MethodSignature { parameters: NodeArray; } -type ValidFunctionDeclaration = ValidConstructor | ValidFunction | ValidMethod | ValidArrowFunction | ValidFunctionExpression; +type ValidFunctionDeclaration = + | ValidConstructor + | ValidFunction + | ValidMethod + | ValidArrowFunction + | ValidFunctionExpression; interface ValidParameterDeclaration extends ParameterDeclaration { name: Identifier; diff --git a/src/services/refactors/convertStringOrTemplateLiteral.ts b/src/services/refactors/convertStringOrTemplateLiteral.ts index a13e4f6f6eb33..c2c9c978cd054 100644 --- a/src/services/refactors/convertStringOrTemplateLiteral.ts +++ b/src/services/refactors/convertStringOrTemplateLiteral.ts @@ -65,7 +65,10 @@ function getRefactorActionsToConvertToTemplateString(context: RefactorContext): return [refactorInfo]; } else if (context.preferences.provideRefactorNotApplicableReason) { - refactorInfo.actions.push({ ...convertStringAction, notApplicableReason: getLocaleSpecificMessage(Diagnostics.Can_only_convert_string_concatenation) }); + refactorInfo.actions.push({ + ...convertStringAction, + notApplicableReason: getLocaleSpecificMessage(Diagnostics.Can_only_convert_string_concatenation), + }); return [refactorInfo]; } return emptyArray; @@ -77,16 +80,19 @@ function getNodeOrParentOfParentheses(file: SourceFile, startPosition: number) { const isNonStringBinary = !treeToArray(nestedBinary).isValidConcatenation; if ( - isNonStringBinary && - isParenthesizedExpression(nestedBinary.parent) && - isBinaryExpression(nestedBinary.parent.parent) + isNonStringBinary + && isParenthesizedExpression(nestedBinary.parent) + && isBinaryExpression(nestedBinary.parent.parent) ) { return nestedBinary.parent.parent; } return node; } -function getRefactorEditsToConvertToTemplateString(context: RefactorContext, actionName: string): RefactorEditInfo | undefined { +function getRefactorEditsToConvertToTemplateString( + context: RefactorContext, + actionName: string, +): RefactorEditInfo | undefined { const { file, startPosition } = context; const node = getNodeOrParentOfParentheses(file, startPosition); @@ -122,7 +128,8 @@ function getEditsForToTemplateLiteral(context: RefactorContext, node: Node) { } function isNotEqualsOperator(node: BinaryExpression) { - return !(node.operatorToken.kind === SyntaxKind.EqualsToken || node.operatorToken.kind === SyntaxKind.PlusEqualsToken); + return !(node.operatorToken.kind === SyntaxKind.EqualsToken + || node.operatorToken.kind === SyntaxKind.PlusEqualsToken); } function getParentBinaryExpression(expr: Node) { @@ -143,9 +150,16 @@ function getParentBinaryExpression(expr: Node) { } function treeToArray(current: Expression) { - const loop = (current: Node): { nodes: Expression[]; operators: Token[]; hasString: boolean; validOperators: boolean; } => { + const loop = ( + current: Node, + ): { nodes: Expression[]; operators: Token[]; hasString: boolean; validOperators: boolean; } => { if (!isBinaryExpression(current)) { - return { nodes: [current as Expression], operators: [], validOperators: true, hasString: isStringLiteral(current) || isNoSubstitutionTemplateLiteral(current) }; + return { + nodes: [current as Expression], + operators: [], + validOperators: true, + hasString: isStringLiteral(current) || isNoSubstitutionTemplateLiteral(current), + }; } const { nodes, operators, hasString: leftHasString, validOperators: leftOperatorValid } = loop(current.left); @@ -167,21 +181,36 @@ function treeToArray(current: Expression) { // to copy comments following the operator // "foo" + /* comment */ "bar" -const copyTrailingOperatorComments = (operators: Token[], file: SourceFile) => (index: number, targetNode: Node) => { - if (index < operators.length) { - copyTrailingComments(operators[index], targetNode, file, SyntaxKind.MultiLineCommentTrivia, /*hasTrailingNewLine*/ false); - } -}; +const copyTrailingOperatorComments = + (operators: Token[], file: SourceFile) => (index: number, targetNode: Node) => { + if (index < operators.length) { + copyTrailingComments( + operators[index], + targetNode, + file, + SyntaxKind.MultiLineCommentTrivia, + /*hasTrailingNewLine*/ false, + ); + } + }; // to copy comments following the string // "foo" /* comment */ + "bar" /* comment */ + "bar2" -const copyCommentFromMultiNode = (nodes: readonly Expression[], file: SourceFile, copyOperatorComments: (index: number, targetNode: Node) => void) => (indexes: number[], targetNode: Node) => { - while (indexes.length > 0) { - const index = indexes.shift()!; - copyTrailingComments(nodes[index], targetNode, file, SyntaxKind.MultiLineCommentTrivia, /*hasTrailingNewLine*/ false); - copyOperatorComments(index, targetNode); - } -}; +const copyCommentFromMultiNode = + (nodes: readonly Expression[], file: SourceFile, copyOperatorComments: (index: number, targetNode: Node) => void) => + (indexes: number[], targetNode: Node) => { + while (indexes.length > 0) { + const index = indexes.shift()!; + copyTrailingComments( + nodes[index], + targetNode, + file, + SyntaxKind.MultiLineCommentTrivia, + /*hasTrailingNewLine*/ false, + ); + copyOperatorComments(index, targetNode); + } + }; function escapeRawStringForTemplate(s: string) { // Escaping for $s in strings that are to be used in template strings @@ -199,7 +228,10 @@ function getRawTextOfTemplate(node: TemplateHead | TemplateMiddle | TemplateTail return getTextOfNode(node).slice(1, rightShaving); } -function concatConsecutiveString(index: number, nodes: readonly Expression[]): [nextIndex: number, text: string, rawText: string, usedIndexes: number[]] { +function concatConsecutiveString( + index: number, + nodes: readonly Expression[], +): [nextIndex: number, text: string, rawText: string, usedIndexes: number[]] { const indexes = []; let text = "", rawText = ""; while (index < nodes.length) { @@ -222,7 +254,10 @@ function concatConsecutiveString(index: number, nodes: readonly Expression[]): [ return [index, text, rawText, indexes]; } -function nodesToTemplate({ nodes, operators }: { nodes: readonly Expression[]; operators: Token[]; }, file: SourceFile) { +function nodesToTemplate( + { nodes, operators }: { nodes: readonly Expression[]; operators: Token[]; }, + file: SourceFile, +) { const copyOperatorComments = copyTrailingOperatorComments(operators, file); const copyCommentFromStringLiterals = copyCommentFromMultiNode(nodes, file, copyOperatorComments); const [begin, headText, rawHeadText, headIndexes] = concatConsecutiveString(0, nodes); @@ -277,7 +312,13 @@ function nodesToTemplate({ nodes, operators }: { nodes: readonly Expression[]; o function copyExpressionComments(node: ParenthesizedExpression | TemplateSpan) { const file = node.getSourceFile(); copyTrailingComments(node, node.expression, file, SyntaxKind.MultiLineCommentTrivia, /*hasTrailingNewLine*/ false); - copyTrailingAsLeadingComments(node.expression, node.expression, file, SyntaxKind.MultiLineCommentTrivia, /*hasTrailingNewLine*/ false); + copyTrailingAsLeadingComments( + node.expression, + node.expression, + file, + SyntaxKind.MultiLineCommentTrivia, + /*hasTrailingNewLine*/ false, + ); } function getExpressionFromParenthesesOrExpression(node: Expression) { diff --git a/src/services/refactors/convertToOptionalChainExpression.ts b/src/services/refactors/convertToOptionalChainExpression.ts index ebacc0935a5c2..eb57af68ca8ec 100644 --- a/src/services/refactors/convertToOptionalChainExpression.ts +++ b/src/services/refactors/convertToOptionalChainExpression.ts @@ -48,7 +48,9 @@ import { } from "../_namespaces/ts.refactor"; const refactorName = "Convert to optional chain expression"; -const convertToOptionalChainExpressionMessage = getLocaleSpecificMessage(Diagnostics.Convert_to_optional_chain_expression); +const convertToOptionalChainExpressionMessage = getLocaleSpecificMessage( + Diagnostics.Convert_to_optional_chain_expression, +); const toOptionalChainAction = { name: refactorName, @@ -83,10 +85,16 @@ function getRefactorActionsToConvertToOptionalChain(context: RefactorContext): r return emptyArray; } -function getRefactorEditsToConvertToOptionalChain(context: RefactorContext, actionName: string): RefactorEditInfo | undefined { +function getRefactorEditsToConvertToOptionalChain( + context: RefactorContext, + actionName: string, +): RefactorEditInfo | undefined { const info = getInfo(context); Debug.assert(info && !isRefactorErrorInfo(info), "Expected applicable refactor info"); - const edits = textChanges.ChangeTracker.with(context, t => doChange(context.file, context.program.getTypeChecker(), t, info, actionName)); + const edits = textChanges.ChangeTracker.with( + context, + t => doChange(context.file, context.program.getTypeChecker(), t, info, actionName), + ); return { edits, renameFilename: undefined, renameLocation: undefined }; } @@ -122,7 +130,10 @@ function isValidExpressionOrStatement(node: Node): node is ValidExpressionOrStat return isValidExpression(node) || isValidStatement(node); } -function getInfo(context: RefactorContext, considerEmptySpans = true): OptionalChainInfo | RefactorErrorInfo | undefined { +function getInfo( + context: RefactorContext, + considerEmptySpans = true, +): OptionalChainInfo | RefactorErrorInfo | undefined { const { file, program } = context; const span = getRefactorContextSpan(context); @@ -132,17 +143,26 @@ function getInfo(context: RefactorContext, considerEmptySpans = true): OptionalC // selecting fo[|o && foo.ba|]r should be valid, so adjust span to fit start and end tokens const startToken = getTokenAtPosition(file, span.start); const endToken = findTokenOnLeftOfPosition(file, span.start + span.length); - const adjustedSpan = createTextSpanFromBounds(startToken.pos, endToken && endToken.end >= startToken.pos ? endToken.getEnd() : startToken.getEnd()); + const adjustedSpan = createTextSpanFromBounds( + startToken.pos, + endToken && endToken.end >= startToken.pos ? endToken.getEnd() : startToken.getEnd(), + ); - const parent = forEmptySpan ? getValidParentNodeOfEmptySpan(startToken) : getValidParentNodeContainingSpan(startToken, adjustedSpan); + const parent = forEmptySpan ? getValidParentNodeOfEmptySpan(startToken) + : getValidParentNodeContainingSpan(startToken, adjustedSpan); const expression = parent && isValidExpressionOrStatement(parent) ? getExpression(parent) : undefined; - if (!expression) return { error: getLocaleSpecificMessage(Diagnostics.Could_not_find_convertible_access_expression) }; + if (!expression) { + return { error: getLocaleSpecificMessage(Diagnostics.Could_not_find_convertible_access_expression) }; + } const checker = program.getTypeChecker(); return isConditionalExpression(expression) ? getConditionalInfo(expression, checker) : getBinaryInfo(expression); } -function getConditionalInfo(expression: ConditionalExpression, checker: TypeChecker): OptionalChainInfo | RefactorErrorInfo | undefined { +function getConditionalInfo( + expression: ConditionalExpression, + checker: TypeChecker, +): OptionalChainInfo | RefactorErrorInfo | undefined { const condition = expression.condition; const finalExpression = getFinalExpressionInChain(expression.whenTrue); @@ -158,8 +178,8 @@ function getConditionalInfo(expression: ConditionalExpression, checker: TypeChec } else if (isBinaryExpression(condition)) { const occurrences = getOccurrencesInExpression(finalExpression.expression, condition); - return occurrences ? { finalExpression, occurrences, expression } : - { error: getLocaleSpecificMessage(Diagnostics.Could_not_find_matching_access_expressions) }; + return occurrences ? { finalExpression, occurrences, expression } + : { error: getLocaleSpecificMessage(Diagnostics.Could_not_find_matching_access_expressions) }; } } @@ -169,11 +189,13 @@ function getBinaryInfo(expression: BinaryExpression): OptionalChainInfo | Refact } const finalExpression = getFinalExpressionInChain(expression.right); - if (!finalExpression) return { error: getLocaleSpecificMessage(Diagnostics.Could_not_find_convertible_access_expression) }; + if (!finalExpression) { + return { error: getLocaleSpecificMessage(Diagnostics.Could_not_find_convertible_access_expression) }; + } const occurrences = getOccurrencesInExpression(finalExpression.expression, expression.left); - return occurrences ? { finalExpression, occurrences, expression } : - { error: getLocaleSpecificMessage(Diagnostics.Could_not_find_matching_access_expressions) }; + return occurrences ? { finalExpression, occurrences, expression } + : { error: getLocaleSpecificMessage(Diagnostics.Could_not_find_matching_access_expressions) }; } /** @@ -200,7 +222,10 @@ function getOccurrencesInExpression(matchTo: Expression, expression: Expression) /** * Returns subchain if chain begins with subchain syntactically. */ -function getMatchingStart(chain: Expression, subchain: Expression): PropertyAccessExpression | ElementAccessExpression | Identifier | undefined { +function getMatchingStart( + chain: Expression, + subchain: Expression, +): PropertyAccessExpression | ElementAccessExpression | Identifier | undefined { if (!isIdentifier(subchain) && !isPropertyAccessExpression(subchain) && !isElementAccessExpression(subchain)) { return undefined; } @@ -218,8 +243,8 @@ function chainStartsWith(chain: Node, subchain: Node): boolean { } // check that the chains match at each access. Call chains in subchain are not valid. while ( - (isPropertyAccessExpression(chain) && isPropertyAccessExpression(subchain)) || - (isElementAccessExpression(chain) && isElementAccessExpression(subchain)) + (isPropertyAccessExpression(chain) && isPropertyAccessExpression(subchain)) + || (isElementAccessExpression(chain) && isElementAccessExpression(subchain)) ) { if (getTextOfChainNode(chain) !== getTextOfChainNode(subchain)) return false; chain = chain.expression; @@ -289,7 +314,9 @@ function getExpression(node: ValidExpressionOrStatement): ValidExpression | unde * it is followed by a different binary operator. * @param node the right child of a binary expression or a call expression. */ -function getFinalExpressionInChain(node: Expression): CallExpression | PropertyAccessExpression | ElementAccessExpression | undefined { +function getFinalExpressionInChain( + node: Expression, +): CallExpression | PropertyAccessExpression | ElementAccessExpression | undefined { // foo && |foo.bar === 1|; - here the right child of the && binary expression is another binary expression. // the rightmost member of the && chain should be the leftmost child of that expression. node = skipParentheses(node); @@ -297,7 +324,10 @@ function getFinalExpressionInChain(node: Expression): CallExpression | PropertyA return getFinalExpressionInChain(node.left); } // foo && |foo.bar()()| - nested calls are treated like further accesses. - else if ((isPropertyAccessExpression(node) || isElementAccessExpression(node) || isCallExpression(node)) && !isOptionalChain(node)) { + else if ( + (isPropertyAccessExpression(node) || isElementAccessExpression(node) || isCallExpression(node)) + && !isOptionalChain(node) + ) { return node; } return undefined; @@ -313,34 +343,70 @@ function convertOccurrences(checker: TypeChecker, toConvert: Expression, occurre const isOccurrence = lastOccurrence?.getText() === toConvert.expression.getText(); if (isOccurrence) occurrences.pop(); if (isCallExpression(toConvert)) { - return isOccurrence ? - factory.createCallChain(chain, factory.createToken(SyntaxKind.QuestionDotToken), toConvert.typeArguments, toConvert.arguments) : - factory.createCallChain(chain, toConvert.questionDotToken, toConvert.typeArguments, toConvert.arguments); + return isOccurrence + ? factory.createCallChain( + chain, + factory.createToken(SyntaxKind.QuestionDotToken), + toConvert.typeArguments, + toConvert.arguments, + ) + : factory.createCallChain( + chain, + toConvert.questionDotToken, + toConvert.typeArguments, + toConvert.arguments, + ); } else if (isPropertyAccessExpression(toConvert)) { - return isOccurrence ? - factory.createPropertyAccessChain(chain, factory.createToken(SyntaxKind.QuestionDotToken), toConvert.name) : - factory.createPropertyAccessChain(chain, toConvert.questionDotToken, toConvert.name); + return isOccurrence + ? factory.createPropertyAccessChain( + chain, + factory.createToken(SyntaxKind.QuestionDotToken), + toConvert.name, + ) + : factory.createPropertyAccessChain(chain, toConvert.questionDotToken, toConvert.name); } else if (isElementAccessExpression(toConvert)) { - return isOccurrence ? - factory.createElementAccessChain(chain, factory.createToken(SyntaxKind.QuestionDotToken), toConvert.argumentExpression) : - factory.createElementAccessChain(chain, toConvert.questionDotToken, toConvert.argumentExpression); + return isOccurrence + ? factory.createElementAccessChain( + chain, + factory.createToken(SyntaxKind.QuestionDotToken), + toConvert.argumentExpression, + ) + : factory.createElementAccessChain(chain, toConvert.questionDotToken, toConvert.argumentExpression); } } return toConvert; } -function doChange(sourceFile: SourceFile, checker: TypeChecker, changes: textChanges.ChangeTracker, info: OptionalChainInfo, _actionName: string): void { +function doChange( + sourceFile: SourceFile, + checker: TypeChecker, + changes: textChanges.ChangeTracker, + info: OptionalChainInfo, + _actionName: string, +): void { const { finalExpression, occurrences, expression } = info; const firstOccurrence = occurrences[occurrences.length - 1]; const convertedChain = convertOccurrences(checker, finalExpression, occurrences); - if (convertedChain && (isPropertyAccessExpression(convertedChain) || isElementAccessExpression(convertedChain) || isCallExpression(convertedChain))) { + if ( + convertedChain + && (isPropertyAccessExpression(convertedChain) || isElementAccessExpression(convertedChain) + || isCallExpression(convertedChain)) + ) { if (isBinaryExpression(expression)) { changes.replaceNodeRange(sourceFile, firstOccurrence, finalExpression, convertedChain); } else if (isConditionalExpression(expression)) { - changes.replaceNode(sourceFile, expression, factory.createBinaryExpression(convertedChain, factory.createToken(SyntaxKind.QuestionQuestionToken), expression.whenFalse)); + changes.replaceNode( + sourceFile, + expression, + factory.createBinaryExpression( + convertedChain, + factory.createToken(SyntaxKind.QuestionQuestionToken), + expression.whenFalse, + ), + ); } } } diff --git a/src/services/refactors/extractSymbol.ts b/src/services/refactors/extractSymbol.ts index 906ddefbcd1c7..553441cb031e9 100644 --- a/src/services/refactors/extractSymbol.ts +++ b/src/services/refactors/extractSymbol.ts @@ -194,11 +194,18 @@ registerRefactor(refactorName, { */ export function getRefactorActionsToExtractSymbol(context: RefactorContext): readonly ApplicableRefactorInfo[] { const requestedRefactor = context.kind; - const rangeToExtract = getRangeToExtract(context.file, getRefactorContextSpan(context), context.triggerReason === "invoked"); + const rangeToExtract = getRangeToExtract( + context.file, + getRefactorContextSpan(context), + context.triggerReason === "invoked", + ); const targetRange = rangeToExtract.targetRange; if (targetRange === undefined) { - if (!rangeToExtract.errors || rangeToExtract.errors.length === 0 || !context.preferences.provideRefactorNotApplicableReason) { + if ( + !rangeToExtract.errors || rangeToExtract.errors.length === 0 + || !context.preferences.provideRefactorNotApplicableReason + ) { return emptyArray; } @@ -339,7 +346,10 @@ export function getRefactorActionsToExtractSymbol(context: RefactorContext): rea * * @internal */ -export function getRefactorEditsToExtractSymbol(context: RefactorContext, actionName: string): RefactorEditInfo | undefined { +export function getRefactorEditsToExtractSymbol( + context: RefactorContext, + actionName: string, +): RefactorEditInfo | undefined { const rangeToExtract = getRangeToExtract(context.file, getRefactorContextSpan(context)); const targetRange = rangeToExtract.targetRange!; // TODO:GH#18217 @@ -375,21 +385,39 @@ export namespace Messages { export const expressionExpected: DiagnosticMessage = createMessage("expression expected."); export const uselessConstantType: DiagnosticMessage = createMessage("No reason to extract constant of type."); export const statementOrExpressionExpected: DiagnosticMessage = createMessage("Statement or expression expected."); - export const cannotExtractRangeContainingConditionalBreakOrContinueStatements: DiagnosticMessage = createMessage("Cannot extract range containing conditional break or continue statements."); - export const cannotExtractRangeContainingConditionalReturnStatement: DiagnosticMessage = createMessage("Cannot extract range containing conditional return statement."); - export const cannotExtractRangeContainingLabeledBreakOrContinueStatementWithTargetOutsideOfTheRange: DiagnosticMessage = createMessage("Cannot extract range containing labeled break or continue with target outside of the range."); - export const cannotExtractRangeThatContainsWritesToReferencesLocatedOutsideOfTheTargetRangeInGenerators: DiagnosticMessage = createMessage("Cannot extract range containing writes to references located outside of the target range in generators."); + export const cannotExtractRangeContainingConditionalBreakOrContinueStatements: DiagnosticMessage = createMessage( + "Cannot extract range containing conditional break or continue statements.", + ); + export const cannotExtractRangeContainingConditionalReturnStatement: DiagnosticMessage = createMessage( + "Cannot extract range containing conditional return statement.", + ); + export const cannotExtractRangeContainingLabeledBreakOrContinueStatementWithTargetOutsideOfTheRange: + DiagnosticMessage = createMessage( + "Cannot extract range containing labeled break or continue with target outside of the range.", + ); + export const cannotExtractRangeThatContainsWritesToReferencesLocatedOutsideOfTheTargetRangeInGenerators: + DiagnosticMessage = createMessage( + "Cannot extract range containing writes to references located outside of the target range in generators.", + ); export const typeWillNotBeVisibleInTheNewScope = createMessage("Type will not visible in the new scope."); export const functionWillNotBeVisibleInTheNewScope = createMessage("Function will not visible in the new scope."); export const cannotExtractIdentifier = createMessage("Select more than a single identifier."); export const cannotExtractExportedEntity = createMessage("Cannot extract exported declaration"); - export const cannotWriteInExpression = createMessage("Cannot write back side-effects when extracting an expression"); - export const cannotExtractReadonlyPropertyInitializerOutsideConstructor = createMessage("Cannot move initialization of read-only class property outside of the constructor"); + export const cannotWriteInExpression = createMessage( + "Cannot write back side-effects when extracting an expression", + ); + export const cannotExtractReadonlyPropertyInitializerOutsideConstructor = createMessage( + "Cannot move initialization of read-only class property outside of the constructor", + ); export const cannotExtractAmbientBlock = createMessage("Cannot extract code from ambient contexts"); export const cannotAccessVariablesFromNestedScopes = createMessage("Cannot access variables from nested scopes"); export const cannotExtractToJSClass = createMessage("Cannot extract constant to a class scope in JS"); - export const cannotExtractToExpressionArrowFunction = createMessage("Cannot extract constant to an arrow function without a block"); - export const cannotExtractFunctionsContainingThisToMethod = createMessage("Cannot extract functions containing this to method"); + export const cannotExtractToExpressionArrowFunction = createMessage( + "Cannot extract constant to an arrow function without a block", + ); + export const cannotExtractFunctionsContainingThisToMethod = createMessage( + "Cannot extract functions containing this to method", + ); } /** @internal */ @@ -459,11 +487,13 @@ export function getRangeToExtract(sourceFile: SourceFile, span: TextSpan, invoke /* If the refactoring command is invoked through a keyboard action it's safe to assume that the user is actively looking for refactoring actions at the span location. As they may not know the exact range that will trigger a refactoring, we expand the searched span to cover a real node range making it more likely that something useful will show up. */ - const adjustedSpan = startToken && endToken && invoked ? getAdjustedSpanFromNodes(startToken, endToken, sourceFile) : span; + const adjustedSpan = startToken && endToken && invoked ? getAdjustedSpanFromNodes(startToken, endToken, sourceFile) + : span; // Walk up starting from the the start position until we find a non-SourceFile node that subsumes the selected span. // This may fail (e.g. you select two statements in the root of a source file) - const start = cursorRequest ? getExtractableParent(startToken) : getParentNodeInSpan(startToken, sourceFile, adjustedSpan); + const start = cursorRequest ? getExtractableParent(startToken) + : getParentNodeInSpan(startToken, sourceFile, adjustedSpan); // Do the same for the ending position const end = cursorRequest ? start : getParentNodeInSpan(endToken, sourceFile, adjustedSpan); @@ -608,12 +638,21 @@ export function getRangeToExtract(sourceFile: SourceFile, span: TextSpan, invoke } // We believe it's true because the node is from the (unmodified) tree. - Debug.assert(nodeToCheck.pos <= nodeToCheck.end, "This failure could trigger https://github.com/Microsoft/TypeScript/issues/20809 (1)"); + Debug.assert( + nodeToCheck.pos <= nodeToCheck.end, + "This failure could trigger https://github.com/Microsoft/TypeScript/issues/20809 (1)", + ); // For understanding how skipTrivia functioned: - Debug.assert(!positionIsSynthesized(nodeToCheck.pos), "This failure could trigger https://github.com/Microsoft/TypeScript/issues/20809 (2)"); + Debug.assert( + !positionIsSynthesized(nodeToCheck.pos), + "This failure could trigger https://github.com/Microsoft/TypeScript/issues/20809 (2)", + ); - if (!isStatement(nodeToCheck) && !(isExpressionNode(nodeToCheck) && isExtractableExpression(nodeToCheck)) && !isStringLiteralJsxAttribute(nodeToCheck)) { + if ( + !isStatement(nodeToCheck) && !(isExpressionNode(nodeToCheck) && isExtractableExpression(nodeToCheck)) + && !isStringLiteralJsxAttribute(nodeToCheck) + ) { return [createDiagnosticForNode(nodeToCheck, Messages.statementOrExpressionExpected)]; } @@ -634,11 +673,16 @@ export function getRangeToExtract(sourceFile: SourceFile, span: TextSpan, invoke visit(nodeToCheck); if (rangeFacts & RangeFacts.UsesThis) { - const container = getThisContainer(nodeToCheck, /*includeArrowFunctions*/ false, /*includeClassComputedPropertyName*/ false); + const container = getThisContainer( + nodeToCheck, + /*includeArrowFunctions*/ false, + /*includeClassComputedPropertyName*/ false, + ); if ( - container.kind === SyntaxKind.FunctionDeclaration || - (container.kind === SyntaxKind.MethodDeclaration && container.parent.kind === SyntaxKind.ObjectLiteralExpression) || - container.kind === SyntaxKind.FunctionExpression + container.kind === SyntaxKind.FunctionDeclaration + || (container.kind === SyntaxKind.MethodDeclaration + && container.parent.kind === SyntaxKind.ObjectLiteralExpression) + || container.kind === SyntaxKind.FunctionExpression ) { rangeFacts |= RangeFacts.UsesThisInFunction; } @@ -677,7 +721,10 @@ export function getRangeToExtract(sourceFile: SourceFile, span: TextSpan, invoke if (node.parent.kind === SyntaxKind.CallExpression) { // Super constructor call const containingClass = getContainingClass(node); - if (containingClass === undefined || containingClass.pos < span.start || containingClass.end >= (span.start + span.length)) { + if ( + containingClass === undefined || containingClass.pos < span.start + || containingClass.end >= (span.start + span.length) + ) { (errors ||= []).push(createDiagnosticForNode(node, Messages.cannotExtractSuper)); return true; } @@ -706,7 +753,9 @@ export function getRangeToExtract(sourceFile: SourceFile, span: TextSpan, invoke case SyntaxKind.FunctionDeclaration: if (isSourceFile(node.parent) && node.parent.externalModuleIndicator === undefined) { // You cannot extract global declarations - (errors ||= []).push(createDiagnosticForNode(node, Messages.functionWillNotBeVisibleInTheNewScope)); + (errors ||= []).push( + createDiagnosticForNode(node, Messages.functionWillNotBeVisibleInTheNewScope), + ); } // falls through case SyntaxKind.ClassExpression: @@ -729,7 +778,10 @@ export function getRangeToExtract(sourceFile: SourceFile, span: TextSpan, invoke permittedJumps = PermittedJumps.None; break; case SyntaxKind.Block: - if (node.parent && node.parent.kind === SyntaxKind.TryStatement && (node.parent as TryStatement).finallyBlock === node) { + if ( + node.parent && node.parent.kind === SyntaxKind.TryStatement + && (node.parent as TryStatement).finallyBlock === node + ) { // allow unconditional returns from finally blocks permittedJumps = PermittedJumps.Return; } @@ -766,13 +818,28 @@ export function getRangeToExtract(sourceFile: SourceFile, span: TextSpan, invoke if (label) { if (!contains(seenLabels, label.escapedText)) { // attempts to jump to label that is not in range to be extracted - (errors ||= []).push(createDiagnosticForNode(node, Messages.cannotExtractRangeContainingLabeledBreakOrContinueStatementWithTargetOutsideOfTheRange)); + (errors ||= []).push( + createDiagnosticForNode( + node, + Messages + .cannotExtractRangeContainingLabeledBreakOrContinueStatementWithTargetOutsideOfTheRange, + ), + ); } } else { - if (!(permittedJumps & (node.kind === SyntaxKind.BreakStatement ? PermittedJumps.Break : PermittedJumps.Continue))) { + if ( + !(permittedJumps + & (node.kind === SyntaxKind.BreakStatement ? PermittedJumps.Break + : PermittedJumps.Continue)) + ) { // attempt to break or continue in a forbidden context - (errors ||= []).push(createDiagnosticForNode(node, Messages.cannotExtractRangeContainingConditionalBreakOrContinueStatements)); + (errors ||= []).push( + createDiagnosticForNode( + node, + Messages.cannotExtractRangeContainingConditionalBreakOrContinueStatements, + ), + ); } } break; @@ -788,7 +855,12 @@ export function getRangeToExtract(sourceFile: SourceFile, span: TextSpan, invoke rangeFacts |= RangeFacts.HasReturn; } else { - (errors ||= []).push(createDiagnosticForNode(node, Messages.cannotExtractRangeContainingConditionalReturnStatement)); + (errors ||= []).push( + createDiagnosticForNode( + node, + Messages.cannotExtractRangeContainingConditionalReturnStatement, + ), + ); } break; default: @@ -832,8 +904,8 @@ function getStatementOrExpressionRange(node: Node): Statement[] | Expression | u } function isScope(node: Node): node is Scope { - return isArrowFunction(node) ? isFunctionBody(node.body) : - isFunctionLikeDeclaration(node) || isSourceFile(node) || isModuleBlock(node) || isClassLike(node); + return isArrowFunction(node) ? isFunctionBody(node.body) + : isFunctionLikeDeclaration(node) || isSourceFile(node) || isModuleBlock(node) || isClassLike(node); } /** @@ -877,22 +949,48 @@ function collectEnclosingScopes(range: TargetRange): Scope[] { } } -function getFunctionExtractionAtIndex(targetRange: TargetRange, context: RefactorContext, requestedChangesIndex: number): RefactorEditInfo { - const { scopes, readsAndWrites: { target, usagesPerScope, functionErrorsPerScope, exposedVariableDeclarations } } = getPossibleExtractionsWorker(targetRange, context); +function getFunctionExtractionAtIndex( + targetRange: TargetRange, + context: RefactorContext, + requestedChangesIndex: number, +): RefactorEditInfo { + const { scopes, readsAndWrites: { target, usagesPerScope, functionErrorsPerScope, exposedVariableDeclarations } } = + getPossibleExtractionsWorker(targetRange, context); Debug.assert(!functionErrorsPerScope[requestedChangesIndex].length, "The extraction went missing? How?"); context.cancellationToken!.throwIfCancellationRequested(); // TODO: GH#18217 - return extractFunctionInScope(target, scopes[requestedChangesIndex], usagesPerScope[requestedChangesIndex], exposedVariableDeclarations, targetRange, context); + return extractFunctionInScope( + target, + scopes[requestedChangesIndex], + usagesPerScope[requestedChangesIndex], + exposedVariableDeclarations, + targetRange, + context, + ); } -function getConstantExtractionAtIndex(targetRange: TargetRange, context: RefactorContext, requestedChangesIndex: number): RefactorEditInfo { - const { scopes, readsAndWrites: { target, usagesPerScope, constantErrorsPerScope, exposedVariableDeclarations } } = getPossibleExtractionsWorker(targetRange, context); +function getConstantExtractionAtIndex( + targetRange: TargetRange, + context: RefactorContext, + requestedChangesIndex: number, +): RefactorEditInfo { + const { scopes, readsAndWrites: { target, usagesPerScope, constantErrorsPerScope, exposedVariableDeclarations } } = + getPossibleExtractionsWorker(targetRange, context); Debug.assert(!constantErrorsPerScope[requestedChangesIndex].length, "The extraction went missing? How?"); - Debug.assert(exposedVariableDeclarations.length === 0, "Extract constant accepted a range containing a variable declaration?"); + Debug.assert( + exposedVariableDeclarations.length === 0, + "Extract constant accepted a range containing a variable declaration?", + ); context.cancellationToken!.throwIfCancellationRequested(); const expression = isExpression(target) ? target : (target.statements[0] as ExpressionStatement).expression; - return extractConstantInScope(expression, scopes[requestedChangesIndex], usagesPerScope[requestedChangesIndex], targetRange.facts, context); + return extractConstantInScope( + expression, + scopes[requestedChangesIndex], + usagesPerScope[requestedChangesIndex], + targetRange.facts, + context, + ); } interface Extraction { @@ -910,8 +1008,14 @@ interface ScopeExtractions { * Each returned ExtractResultForScope corresponds to a possible target scope and is either a set of changes * or an error explaining why we can't extract into that scope. */ -function getPossibleExtractions(targetRange: TargetRange, context: RefactorContext): readonly ScopeExtractions[] | undefined { - const { scopes, readsAndWrites: { functionErrorsPerScope, constantErrorsPerScope } } = getPossibleExtractionsWorker(targetRange, context); +function getPossibleExtractions( + targetRange: TargetRange, + context: RefactorContext, +): readonly ScopeExtractions[] | undefined { + const { scopes, readsAndWrites: { functionErrorsPerScope, constantErrorsPerScope } } = getPossibleExtractionsWorker( + targetRange, + context, + ); // Need the inner type annotation to avoid https://github.com/Microsoft/TypeScript/issues/7547 const extractions = scopes.map((scope, i): ScopeExtractions => { const functionDescriptionPart = getDescriptionForFunctionInScope(scope); @@ -926,21 +1030,42 @@ function getPossibleExtractions(targetRange: TargetRange, context: RefactorConte let functionDescription: string; let constantDescription: string; if (scopeDescription === SpecialScope.Global) { - functionDescription = formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Extract_to_0_in_1_scope), [functionDescriptionPart, "global"]); - constantDescription = formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Extract_to_0_in_1_scope), [constantDescriptionPart, "global"]); + functionDescription = formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Extract_to_0_in_1_scope), [ + functionDescriptionPart, + "global", + ]); + constantDescription = formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Extract_to_0_in_1_scope), [ + constantDescriptionPart, + "global", + ]); } else if (scopeDescription === SpecialScope.Module) { - functionDescription = formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Extract_to_0_in_1_scope), [functionDescriptionPart, "module"]); - constantDescription = formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Extract_to_0_in_1_scope), [constantDescriptionPart, "module"]); + functionDescription = formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Extract_to_0_in_1_scope), [ + functionDescriptionPart, + "module", + ]); + constantDescription = formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Extract_to_0_in_1_scope), [ + constantDescriptionPart, + "module", + ]); } else { - functionDescription = formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Extract_to_0_in_1), [functionDescriptionPart, scopeDescription]); - constantDescription = formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Extract_to_0_in_1), [constantDescriptionPart, scopeDescription]); + functionDescription = formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Extract_to_0_in_1), [ + functionDescriptionPart, + scopeDescription, + ]); + constantDescription = formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Extract_to_0_in_1), [ + constantDescriptionPart, + scopeDescription, + ]); } // Customize the phrasing for the innermost scope to increase clarity. if (i === 0 && !isClassLike(scope)) { - constantDescription = formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Extract_to_0_in_enclosing_scope), [constantDescriptionPart]); + constantDescription = formatStringFromArgs( + getLocaleSpecificMessage(Diagnostics.Extract_to_0_in_enclosing_scope), + [constantDescriptionPart], + ); } return { @@ -957,7 +1082,10 @@ function getPossibleExtractions(targetRange: TargetRange, context: RefactorConte return extractions; } -function getPossibleExtractionsWorker(targetRange: TargetRange, context: RefactorContext): { readonly scopes: Scope[]; readonly readsAndWrites: ReadsAndWrites; } { +function getPossibleExtractionsWorker( + targetRange: TargetRange, + context: RefactorContext, +): { readonly scopes: Scope[]; readonly readsAndWrites: ReadsAndWrites; } { const { file: sourceFile } = context; const scopes = collectEnclosingScopes(targetRange); @@ -1055,7 +1183,14 @@ function extractFunctionInScope( let type = checker.getTypeOfSymbolAtLocation(usage.symbol, usage.node); // Widen the type so we don't emit nonsense annotations like "function fn(x: 3) {" type = checker.getBaseTypeOfLiteralType(type); - typeNode = codefix.typeToAutoImportableTypeNode(checker, importAdder, type, scope, scriptTarget, NodeBuilderFlags.NoTruncation); + typeNode = codefix.typeToAutoImportableTypeNode( + checker, + importAdder, + type, + scope, + scriptTarget, + NodeBuilderFlags.NoTruncation, + ); } const paramDecl = factory.createParameterDeclaration( @@ -1072,12 +1207,19 @@ function extractFunctionInScope( callArguments.push(factory.createIdentifier(name)); }); - const typeParametersAndDeclarations = arrayFrom(typeParameterUsages.values(), type => ({ type, declaration: getFirstDeclarationBeforePosition(type, context.startPosition) })); + const typeParametersAndDeclarations = arrayFrom( + typeParameterUsages.values(), + type => ({ type, declaration: getFirstDeclarationBeforePosition(type, context.startPosition) }), + ); const sortedTypeParametersAndDeclarations = typeParametersAndDeclarations.sort(compareTypesByDeclarationOrder); - const typeParameters: readonly TypeParameterDeclaration[] | undefined = sortedTypeParametersAndDeclarations.length === 0 - ? undefined - : mapDefined(sortedTypeParametersAndDeclarations, ({ declaration }) => declaration as TypeParameterDeclaration); + const typeParameters: readonly TypeParameterDeclaration[] | undefined = + sortedTypeParametersAndDeclarations.length === 0 + ? undefined + : mapDefined( + sortedTypeParametersAndDeclarations, + ({ declaration }) => declaration as TypeParameterDeclaration, + ); // Strictly speaking, we should check whether each name actually binds to the appropriate type // parameter. In cases of shadowing, they may not. @@ -1092,7 +1234,13 @@ function extractFunctionInScope( returnType = checker.typeToTypeNode(contextualType!, scope, NodeBuilderFlags.NoTruncation); // TODO: GH#18217 } - const { body, returnValueProperty } = transformFunctionBody(node, exposedVariableDeclarations, writes, substitutions, !!(range.facts & RangeFacts.HasReturn)); + const { body, returnValueProperty } = transformFunctionBody( + node, + exposedVariableDeclarations, + writes, + substitutions, + !!(range.facts & RangeFacts.HasReturn), + ); suppressLeadingAndTrailingTrivia(body); let newFunction: MethodDeclaration | FunctionDeclaration; @@ -1197,7 +1345,12 @@ function extractFunctionInScope( newNodes.push(factory.createVariableStatement( /*modifiers*/ undefined, factory.createVariableDeclarationList( - [factory.createVariableDeclaration(getSynthesizedDeepClone(variableDeclaration.name), /*exclamationToken*/ undefined, /*type*/ getSynthesizedDeepClone(variableDeclaration.type), /*initializer*/ call)], + [factory.createVariableDeclaration( + getSynthesizedDeepClone(variableDeclaration.name), + /*exclamationToken*/ undefined, + /*type*/ getSynthesizedDeepClone(variableDeclaration.type), + /*initializer*/ call, + )], variableDeclaration.parent.flags, ), )); @@ -1233,7 +1386,8 @@ function extractFunctionInScope( commonNodeFlags = commonNodeFlags & variableDeclaration.parent.flags; } - const typeLiteral: TypeLiteralNode | undefined = sawExplicitType ? factory.createTypeLiteralNode(typeElements) : undefined; + const typeLiteral: TypeLiteralNode | undefined = sawExplicitType + ? factory.createTypeLiteralNode(typeElements) : undefined; if (typeLiteral) { setEmitFlags(typeLiteral, EmitFlags.SingleLine); } @@ -1264,7 +1418,11 @@ function extractFunctionInScope( newNodes.push(factory.createVariableStatement( /*modifiers*/ undefined, factory.createVariableDeclarationList( - [factory.createVariableDeclaration(variableDeclaration.symbol.name, /*exclamationToken*/ undefined, getTypeDeepCloneUnionUndefined(variableDeclaration.type))], + [factory.createVariableDeclaration( + variableDeclaration.symbol.name, + /*exclamationToken*/ undefined, + getTypeDeepCloneUnionUndefined(variableDeclaration.type), + )], flags, ), )); @@ -1276,7 +1434,11 @@ function extractFunctionInScope( newNodes.push(factory.createVariableStatement( /*modifiers*/ undefined, factory.createVariableDeclarationList( - [factory.createVariableDeclaration(returnValueProperty, /*exclamationToken*/ undefined, getTypeDeepCloneUnionUndefined(returnType))], + [factory.createVariableDeclaration( + returnValueProperty, + /*exclamationToken*/ undefined, + getTypeDeepCloneUnionUndefined(returnType), + )], NodeFlags.Let, ), )); @@ -1303,7 +1465,11 @@ function extractFunctionInScope( // emit e.g. // { a, b, __return } = newFunction(a, b); // return __return; - newNodes.push(factory.createExpressionStatement(factory.createAssignment(factory.createObjectLiteralExpression(assignments), call))); + newNodes.push( + factory.createExpressionStatement( + factory.createAssignment(factory.createObjectLiteralExpression(assignments), call), + ), + ); if (returnValueProperty) { newNodes.push(factory.createReturnStatement(factory.createIdentifier(returnValueProperty))); } @@ -1366,7 +1532,9 @@ function extractConstantInScope( // Make a unique name for the extracted variable const file = scope.getSourceFile(); - const localNameText = isPropertyAccessExpression(node) && !isClassLike(scope) && !checker.resolveName(node.name.text, node, SymbolFlags.Value, /*excludeGlobals*/ false) && !isPrivateIdentifier(node.name) && !identifierToKeywordKind(node.name) + const localNameText = isPropertyAccessExpression(node) && !isClassLike(scope) + && !checker.resolveName(node.name.text, node, SymbolFlags.Value, /*excludeGlobals*/ false) + && !isPrivateIdentifier(node.name) && !identifierToKeywordKind(node.name) ? node.name.text : getUniqueName(isClassLike(scope) ? "newProperty" : "newLocal", file); const isJS = isInJSFile(scope); @@ -1420,7 +1588,12 @@ function extractConstantInScope( changeTracker.replaceNode(context.file, node, localReference); } else { - const newVariableDeclaration = factory.createVariableDeclaration(localNameText, /*exclamationToken*/ undefined, variableType, initializer); + const newVariableDeclaration = factory.createVariableDeclaration( + localNameText, + /*exclamationToken*/ undefined, + variableType, + initializer, + ); // If the node is part of an initializer in a list of variable declarations, insert a new // variable declaration into the list (in case it depends on earlier ones). @@ -1457,7 +1630,12 @@ function extractConstantInScope( changeTracker.insertNodeAtTopOfFile(context.file, newVariableStatement, /*blankLineBetween*/ false); } else { - changeTracker.insertNodeBefore(context.file, nodeToInsertBefore, newVariableStatement, /*blankLineBetween*/ false); + changeTracker.insertNodeBefore( + context.file, + nodeToInsertBefore, + newVariableStatement, + /*blankLineBetween*/ false, + ); } // Consume @@ -1483,11 +1661,16 @@ function extractConstantInScope( const renameLocation = getRenameLocation(edits, renameFilename, localNameText, /*preferLastLocation*/ true); return { renameFilename, renameLocation, edits }; - function transformFunctionInitializerAndType(variableType: TypeNode | undefined, initializer: Expression): { variableType: TypeNode | undefined; initializer: Expression; } { + function transformFunctionInitializerAndType( + variableType: TypeNode | undefined, + initializer: Expression, + ): { variableType: TypeNode | undefined; initializer: Expression; } { // If no contextual type exists there is nothing to transfer to the function signature if (variableType === undefined) return { variableType, initializer }; // Only do this for function expressions and arrow functions that are not generic - if (!isFunctionExpression(initializer) && !isArrowFunction(initializer) || !!initializer.typeParameters) return { variableType, initializer }; + if (!isFunctionExpression(initializer) && !isArrowFunction(initializer) || !!initializer.typeParameters) { + return { variableType, initializer }; + } const functionType = checker.getTypeAtLocation(node); const functionSignature = singleOrUndefined(checker.getSignaturesOfType(functionType, SignatureKind.Call)); @@ -1507,7 +1690,17 @@ function extractConstantInScope( const paramType = checker.getTypeAtLocation(p); if (paramType === checker.getAnyType()) hasAny = true; - parameters.push(factory.updateParameterDeclaration(p, p.modifiers, p.dotDotDotToken, p.name, p.questionToken, p.type || checker.typeToTypeNode(paramType, scope, NodeBuilderFlags.NoTruncation), p.initializer)); + parameters.push( + factory.updateParameterDeclaration( + p, + p.modifiers, + p.dotDotDotToken, + p.name, + p.questionToken, + p.type || checker.typeToTypeNode(paramType, scope, NodeBuilderFlags.NoTruncation), + p.initializer, + ), + ); } } // If a parameter was inferred as any we skip adding function parameters at all. @@ -1516,14 +1709,26 @@ function extractConstantInScope( if (hasAny) return { variableType, initializer }; variableType = undefined; if (isArrowFunction(initializer)) { - initializer = factory.updateArrowFunction(initializer, canHaveModifiers(node) ? getModifiers(node) : undefined, initializer.typeParameters, parameters, initializer.type || checker.typeToTypeNode(functionSignature.getReturnType(), scope, NodeBuilderFlags.NoTruncation), initializer.equalsGreaterThanToken, initializer.body); + initializer = factory.updateArrowFunction( + initializer, + canHaveModifiers(node) ? getModifiers(node) : undefined, + initializer.typeParameters, + parameters, + initializer.type + || checker.typeToTypeNode(functionSignature.getReturnType(), scope, NodeBuilderFlags.NoTruncation), + initializer.equalsGreaterThanToken, + initializer.body, + ); } else { if (functionSignature && !!functionSignature.thisParameter) { const firstParameter = firstOrUndefined(parameters); // If the function signature has a this parameter and if the first defined parameter is not the this parameter, we must add it // Note: If this parameter was already there, it would have been previously updated with the type if not type was present - if ((!firstParameter || (isIdentifier(firstParameter.name) && firstParameter.name.escapedText !== "this"))) { + if ( + (!firstParameter + || (isIdentifier(firstParameter.name) && firstParameter.name.escapedText !== "this")) + ) { const thisType = checker.getTypeOfSymbolAtLocation(functionSignature.thisParameter, node); parameters.splice( 0, @@ -1538,7 +1743,17 @@ function extractConstantInScope( ); } } - initializer = factory.updateFunctionExpression(initializer, canHaveModifiers(node) ? getModifiers(node) : undefined, initializer.asteriskToken, initializer.name, initializer.typeParameters, parameters, initializer.type || checker.typeToTypeNode(functionSignature.getReturnType(), scope, NodeBuilderFlags.NoTruncation), initializer.body); + initializer = factory.updateFunctionExpression( + initializer, + canHaveModifiers(node) ? getModifiers(node) : undefined, + initializer.asteriskToken, + initializer.name, + initializer.typeParameters, + parameters, + initializer.type + || checker.typeToTypeNode(functionSignature.getReturnType(), scope, NodeBuilderFlags.NoTruncation), + initializer.body, + ); } return { variableType, initializer }; } @@ -1548,10 +1763,10 @@ function getContainingVariableDeclarationIfInList(node: Node, scope: Scope) { let prevNode; while (node !== undefined && node !== scope) { if ( - isVariableDeclaration(node) && - node.initializer === prevNode && - isVariableDeclarationList(node.parent) && - node.parent.declarations.length > 1 + isVariableDeclaration(node) + && node.initializer === prevNode + && isVariableDeclarationList(node.parent) + && node.parent.declarations.length > 1 ) { return node; } @@ -1567,7 +1782,9 @@ function getFirstDeclarationBeforePosition(type: Type, position: number): Declar const symbol = type.symbol; if (symbol && symbol.declarations) { for (const declaration of symbol.declarations) { - if ((firstDeclaration === undefined || declaration.pos < firstDeclaration.pos) && declaration.pos < position) { + if ( + (firstDeclaration === undefined || declaration.pos < firstDeclaration.pos) && declaration.pos < position + ) { firstDeclaration = declaration; } } @@ -1591,7 +1808,8 @@ function compareTypesByDeclarationOrder( function getCalledExpression(scope: Node, range: TargetRange, functionNameText: string): Expression { const functionReference = factory.createIdentifier(functionNameText); if (isClassLike(scope)) { - const lhs = range.facts & RangeFacts.InStaticRegion ? factory.createIdentifier(scope.name!.text) : factory.createThis(); // TODO: GH#18217 + const lhs = range.facts & RangeFacts.InStaticRegion ? factory.createIdentifier(scope.name!.text) + : factory.createThis(); // TODO: GH#18217 return factory.createPropertyAccessExpression(lhs, functionReference); } else { @@ -1599,7 +1817,13 @@ function getCalledExpression(scope: Node, range: TargetRange, functionNameText: } } -function transformFunctionBody(body: Node, exposedVariableDeclarations: readonly VariableDeclaration[], writes: readonly UsageEntry[] | undefined, substitutions: ReadonlyMap, hasReturn: boolean): { body: Block; returnValueProperty: string | undefined; } { +function transformFunctionBody( + body: Node, + exposedVariableDeclarations: readonly VariableDeclaration[], + writes: readonly UsageEntry[] | undefined, + substitutions: ReadonlyMap, + hasReturn: boolean, +): { body: Block; returnValueProperty: string | undefined; } { const hasWritesOrVariableDeclarations = writes !== undefined || exposedVariableDeclarations.length > 0; if (isBlock(body) && !hasWritesOrVariableDeclarations && substitutions.size === 0) { // already block, no declarations or writes to propagate back, no substitutions - can use node as is @@ -1607,19 +1831,27 @@ function transformFunctionBody(body: Node, exposedVariableDeclarations: readonly } let returnValueProperty: string | undefined; let ignoreReturns = false; - const statements = factory.createNodeArray(isBlock(body) ? body.statements.slice(0) : [isStatement(body) ? body : factory.createReturnStatement(skipParentheses(body as Expression))]); + const statements = factory.createNodeArray( + isBlock(body) ? body.statements.slice(0) + : [isStatement(body) ? body : factory.createReturnStatement(skipParentheses(body as Expression))], + ); // rewrite body if either there are writes that should be propagated back via return statements or there are substitutions if (hasWritesOrVariableDeclarations || substitutions.size) { const rewrittenStatements = visitNodes(statements, visitor, isStatement).slice(); if (hasWritesOrVariableDeclarations && !hasReturn && isStatement(body)) { // add return at the end to propagate writes back in case if control flow falls out of the function body // it is ok to know that range has at least one return since it we only allow unconditional returns - const assignments = getPropertyAssignmentsForWritesAndVariableDeclarations(exposedVariableDeclarations, writes); + const assignments = getPropertyAssignmentsForWritesAndVariableDeclarations( + exposedVariableDeclarations, + writes, + ); if (assignments.length === 1) { rewrittenStatements.push(factory.createReturnStatement(assignments[0].name)); } else { - rewrittenStatements.push(factory.createReturnStatement(factory.createObjectLiteralExpression(assignments))); + rewrittenStatements.push( + factory.createReturnStatement(factory.createObjectLiteralExpression(assignments)), + ); } } return { body: factory.createBlock(rewrittenStatements, /*multiLine*/ true), returnValueProperty }; @@ -1630,12 +1862,20 @@ function transformFunctionBody(body: Node, exposedVariableDeclarations: readonly function visitor(node: Node): VisitResult { if (!ignoreReturns && isReturnStatement(node) && hasWritesOrVariableDeclarations) { - const assignments: ObjectLiteralElementLike[] = getPropertyAssignmentsForWritesAndVariableDeclarations(exposedVariableDeclarations, writes); + const assignments: ObjectLiteralElementLike[] = getPropertyAssignmentsForWritesAndVariableDeclarations( + exposedVariableDeclarations, + writes, + ); if (node.expression) { if (!returnValueProperty) { returnValueProperty = "__return"; } - assignments.unshift(factory.createPropertyAssignment(returnValueProperty, visitNode(node.expression, visitor, isExpression))); + assignments.unshift( + factory.createPropertyAssignment( + returnValueProperty, + visitNode(node.expression, visitor, isExpression), + ), + ); } if (assignments.length === 1) { return factory.createReturnStatement(assignments[0].name as Expression); @@ -1648,7 +1888,8 @@ function transformFunctionBody(body: Node, exposedVariableDeclarations: readonly const oldIgnoreReturns = ignoreReturns; ignoreReturns = ignoreReturns || isFunctionLikeDeclaration(node) || isClassLike(node); const substitution = substitutions.get(getNodeId(node).toString()); - const result = substitution ? getSynthesizedDeepClone(substitution) : visitEachChild(node, visitor, nullTransformationContext); + const result = substitution ? getSynthesizedDeepClone(substitution) + : visitEachChild(node, visitor, nullTransformationContext); ignoreReturns = oldIgnoreReturns; return result; } @@ -1662,7 +1903,8 @@ function transformConstantInitializer(initializer: Expression, substitutions: Re function visitor(node: Node): VisitResult { const substitution = substitutions.get(getNodeId(node).toString()); - return substitution ? getSynthesizedDeepClone(substitution) : visitEachChild(node, visitor, nullTransformationContext); + return substitution ? getSynthesizedDeepClone(substitution) + : visitEachChild(node, visitor, nullTransformationContext); } } @@ -1691,7 +1933,10 @@ function getStatementsOrClassElements(scope: Scope): readonly Statement[] | read * Otherwise, return `undefined`. */ function getNodeToInsertFunctionBefore(minPos: number, scope: Scope): Statement | ClassElement | undefined { - return find(getStatementsOrClassElements(scope), child => child.pos >= minPos && isFunctionLikeDeclaration(child) && !isConstructorDeclaration(child)); + return find( + getStatementsOrClassElements(scope), + child => child.pos >= minPos && isFunctionLikeDeclaration(child) && !isConstructorDeclaration(child), + ); } function getNodeToInsertPropertyBefore(maxPos: number, scope: ClassLikeDeclaration): ClassElement { @@ -1758,7 +2003,10 @@ function getPropertyAssignmentsForWritesAndVariableDeclarations( exposedVariableDeclarations: readonly VariableDeclaration[], writes: readonly UsageEntry[] | undefined, ): ShorthandPropertyAssignment[] { - const variableAssignments = map(exposedVariableDeclarations, v => factory.createShorthandPropertyAssignment(v.symbol.name)); + const variableAssignments = map( + exposedVariableDeclarations, + v => factory.createShorthandPropertyAssignment(v.symbol.name), + ); const writeAssignments = map(writes, w => factory.createShorthandPropertyAssignment(w.symbol.name)); // TODO: GH#18217 `variableAssignments` not possibly undefined! @@ -1851,7 +2099,11 @@ function collectReadsAndWrites( // initialize results for (const scope of scopes) { - usagesPerScope.push({ usages: new Map(), typeParameterUsages: new Map(), substitutions: new Map() }); + usagesPerScope.push({ + usages: new Map(), + typeParameterUsages: new Map(), + substitutions: new Map(), + }); substitutionsPerScope.push(new Map()); functionErrorsPerScope.push([]); @@ -1933,11 +2185,15 @@ function collectReadsAndWrites( // local will actually be declared at the same level as the extracted expression). if (i > 0 && (scopeUsages.usages.size > 0 || scopeUsages.typeParameterUsages.size > 0)) { const errorNode = isReadonlyArray(targetRange.range) ? targetRange.range[0] : targetRange.range; - constantErrorsPerScope[i].push(createDiagnosticForNode(errorNode, Messages.cannotAccessVariablesFromNestedScopes)); + constantErrorsPerScope[i].push( + createDiagnosticForNode(errorNode, Messages.cannotAccessVariablesFromNestedScopes), + ); } if (targetRange.facts & RangeFacts.UsesThisInFunction && isClassLike(scopes[i])) { - functionErrorsPerScope[i].push(createDiagnosticForNode(targetRange.thisNode!, Messages.cannotExtractFunctionsContainingThisToMethod)); + functionErrorsPerScope[i].push( + createDiagnosticForNode(targetRange.thisNode!, Messages.cannotExtractFunctionsContainingThisToMethod), + ); } let hasWrite = false; @@ -1946,9 +2202,9 @@ function collectReadsAndWrites( if (value.usage === Usage.Write) { hasWrite = true; if ( - value.symbol.flags & SymbolFlags.ClassMember && - value.symbol.valueDeclaration && - hasEffectiveModifier(value.symbol.valueDeclaration, ModifierFlags.Readonly) + value.symbol.flags & SymbolFlags.ClassMember + && value.symbol.valueDeclaration + && hasEffectiveModifier(value.symbol.valueDeclaration, ModifierFlags.Readonly) ) { readonlyClassPropertyWrite = value.symbol.valueDeclaration; } @@ -1956,7 +2212,10 @@ function collectReadsAndWrites( }); // If an expression was extracted, then there shouldn't have been any variable declarations. - Debug.assert(isReadonlyArray(targetRange.range) || exposedVariableDeclarations.length === 0, "No variable declarations expected if something was extracted"); + Debug.assert( + isReadonlyArray(targetRange.range) || exposedVariableDeclarations.length === 0, + "No variable declarations expected if something was extracted", + ); if (hasWrite && !isReadonlyArray(targetRange.range)) { const diag = createDiagnosticForNode(targetRange.range, Messages.cannotWriteInExpression); @@ -1964,12 +2223,18 @@ function collectReadsAndWrites( constantErrorsPerScope[i].push(diag); } else if (readonlyClassPropertyWrite && i > 0) { - const diag = createDiagnosticForNode(readonlyClassPropertyWrite, Messages.cannotExtractReadonlyPropertyInitializerOutsideConstructor); + const diag = createDiagnosticForNode( + readonlyClassPropertyWrite, + Messages.cannotExtractReadonlyPropertyInitializerOutsideConstructor, + ); functionErrorsPerScope[i].push(diag); constantErrorsPerScope[i].push(diag); } else if (firstExposedNonVariableDeclaration) { - const diag = createDiagnosticForNode(firstExposedNonVariableDeclaration, Messages.cannotExtractExportedEntity); + const diag = createDiagnosticForNode( + firstExposedNonVariableDeclaration, + Messages.cannotExtractExportedEntity, + ); functionErrorsPerScope[i].push(diag); constantErrorsPerScope[i].push(diag); } @@ -1978,7 +2243,10 @@ function collectReadsAndWrites( return { target, usagesPerScope, functionErrorsPerScope, constantErrorsPerScope, exposedVariableDeclarations }; function isInGenericContext(node: Node) { - return !!findAncestor(node, n => isDeclarationWithTypeParameters(n) && getEffectiveTypeParameterDeclarations(n).length !== 0); + return !!findAncestor( + node, + n => isDeclarationWithTypeParameters(n) && getEffectiveTypeParameterDeclarations(n).length !== 0, + ); } function recordTypeParameterUsages(type: Type) { @@ -2090,7 +2358,10 @@ function collectReadsAndWrites( if (targetRange.facts & RangeFacts.IsGenerator && usage === Usage.Write) { // this is write to a reference located outside of the target scope and range is extracted into generator // currently this is unsupported scenario - const diag = createDiagnosticForNode(identifier, Messages.cannotExtractRangeThatContainsWritesToReferencesLocatedOutsideOfTheTargetRangeInGenerators); + const diag = createDiagnosticForNode( + identifier, + Messages.cannotExtractRangeThatContainsWritesToReferencesLocatedOutsideOfTheTargetRangeInGenerators, + ); for (const errors of functionErrorsPerScope) { errors.push(diag); } @@ -2105,7 +2376,11 @@ function collectReadsAndWrites( continue; } if (!substitutionsPerScope[i].has(symbolId)) { - const substitution = tryReplaceWithQualifiedNameOrPropertyAccess(symbol.exportSymbol || symbol, scope, isTypeName); + const substitution = tryReplaceWithQualifiedNameOrPropertyAccess( + symbol.exportSymbol || symbol, + scope, + isTypeName, + ); if (substitution) { substitutionsPerScope[i].set(symbolId, substitution); } @@ -2128,7 +2403,10 @@ function collectReadsAndWrites( function checkForUsedDeclarations(node: Node) { // If this node is entirely within the original extraction range, we don't need to do anything. - if (node === targetRange.range || (isReadonlyArray(targetRange.range) && targetRange.range.indexOf(node as Statement) >= 0)) { + if ( + node === targetRange.range + || (isReadonlyArray(targetRange.range) && targetRange.range.indexOf(node as Statement) >= 0) + ) { return; } @@ -2163,12 +2441,17 @@ function collectReadsAndWrites( function getSymbolReferencedByIdentifier(identifier: Identifier) { // If the identifier is both a property name and its value, we're only interested in its value // (since the name is a declaration and will be included in the extracted range). - return identifier.parent && isShorthandPropertyAssignment(identifier.parent) && identifier.parent.name === identifier + return identifier.parent && isShorthandPropertyAssignment(identifier.parent) + && identifier.parent.name === identifier ? checker.getShorthandAssignmentValueSymbol(identifier.parent) : checker.getSymbolAtLocation(identifier); } - function tryReplaceWithQualifiedNameOrPropertyAccess(symbol: Symbol | undefined, scopeDecl: Node, isTypeNode: boolean): PropertyAccessExpression | EntityName | undefined { + function tryReplaceWithQualifiedNameOrPropertyAccess( + symbol: Symbol | undefined, + scopeDecl: Node, + isTypeNode: boolean, + ): PropertyAccessExpression | EntityName | undefined { if (!symbol) { return undefined; } @@ -2206,8 +2489,8 @@ function isExtractableExpression(node: Node): boolean { switch (node.kind) { case SyntaxKind.StringLiteral: - return parent.kind !== SyntaxKind.ImportDeclaration && - parent.kind !== SyntaxKind.ImportSpecifier; + return parent.kind !== SyntaxKind.ImportDeclaration + && parent.kind !== SyntaxKind.ImportSpecifier; case SyntaxKind.SpreadElement: case SyntaxKind.ObjectBindingPattern: @@ -2215,9 +2498,9 @@ function isExtractableExpression(node: Node): boolean { return false; case SyntaxKind.Identifier: - return parent.kind !== SyntaxKind.BindingElement && - parent.kind !== SyntaxKind.ImportSpecifier && - parent.kind !== SyntaxKind.ExportSpecifier; + return parent.kind !== SyntaxKind.BindingElement + && parent.kind !== SyntaxKind.ImportSpecifier + && parent.kind !== SyntaxKind.ExportSpecifier; } return true; } @@ -2235,8 +2518,9 @@ function isBlockLike(node: Node): node is BlockLike { } function isInJSXContent(node: Node) { - return isStringLiteralJsxAttribute(node) || - (isJsxElement(node) || isJsxSelfClosingElement(node) || isJsxFragment(node)) && (isJsxElement(node.parent) || isJsxFragment(node.parent)); + return isStringLiteralJsxAttribute(node) + || (isJsxElement(node) || isJsxSelfClosingElement(node) || isJsxFragment(node)) + && (isJsxElement(node.parent) || isJsxFragment(node.parent)); } function isStringLiteralJsxAttribute(node: Node): node is StringLiteral { diff --git a/src/services/refactors/extractType.ts b/src/services/refactors/extractType.ts index 205a23345930e..fcff952d12c05 100644 --- a/src/services/refactors/extractType.ts +++ b/src/services/refactors/extractType.ts @@ -102,8 +102,9 @@ registerRefactor(refactorName, { return [{ name: refactorName, description: getLocaleSpecificMessage(Diagnostics.Extract_type), - actions: info.isJS ? - [extractToTypeDefAction] : append([extractToTypeAliasAction], info.typeElements && extractToInterfaceAction), + actions: info.isJS + ? [extractToTypeDefAction] + : append([extractToTypeAliasAction], info.typeElements && extractToInterfaceAction), }]; } @@ -167,37 +168,57 @@ interface InterfaceInfo { type ExtractInfo = TypeAliasInfo | InterfaceInfo; -function getRangeToExtract(context: RefactorContext, considerEmptySpans = true): ExtractInfo | RefactorErrorInfo | undefined { +function getRangeToExtract( + context: RefactorContext, + considerEmptySpans = true, +): ExtractInfo | RefactorErrorInfo | undefined { const { file, startPosition } = context; const isJS = isSourceFileJS(file); const current = getTokenAtPosition(file, startPosition); const range = createTextRangeFromSpan(getRefactorContextSpan(context)); const cursorRequest = range.pos === range.end && considerEmptySpans; - const selection = findAncestor(current, node => - node.parent && isTypeNode(node) && !rangeContainsSkipTrivia(range, node.parent, file) && - (cursorRequest || nodeOverlapsWithStartEnd(current, file, range.pos, range.end))); - if (!selection || !isTypeNode(selection)) return { error: getLocaleSpecificMessage(Diagnostics.Selection_is_not_a_valid_type_node) }; + const selection = findAncestor( + current, + node => + node.parent && isTypeNode(node) && !rangeContainsSkipTrivia(range, node.parent, file) + && (cursorRequest || nodeOverlapsWithStartEnd(current, file, range.pos, range.end)), + ); + if (!selection || !isTypeNode(selection)) { + return { error: getLocaleSpecificMessage(Diagnostics.Selection_is_not_a_valid_type_node) }; + } const checker = context.program.getTypeChecker(); const enclosingNode = getEnclosingNode(selection, isJS); - if (enclosingNode === undefined) return { error: getLocaleSpecificMessage(Diagnostics.No_type_could_be_extracted_from_this_type_node) }; + if (enclosingNode === undefined) { + return { error: getLocaleSpecificMessage(Diagnostics.No_type_could_be_extracted_from_this_type_node) }; + } const typeParameters = collectTypeParameters(checker, selection, enclosingNode, file); - if (!typeParameters) return { error: getLocaleSpecificMessage(Diagnostics.No_type_could_be_extracted_from_this_type_node) }; + if (!typeParameters) { + return { error: getLocaleSpecificMessage(Diagnostics.No_type_could_be_extracted_from_this_type_node) }; + } const typeElements = flattenTypeLiteralNodeReference(checker, selection); return { isJS, selection, enclosingNode, typeParameters, typeElements }; } -function flattenTypeLiteralNodeReference(checker: TypeChecker, node: TypeNode | undefined): readonly TypeElement[] | undefined { +function flattenTypeLiteralNodeReference( + checker: TypeChecker, + node: TypeNode | undefined, +): readonly TypeElement[] | undefined { if (!node) return undefined; if (isIntersectionTypeNode(node)) { const result: TypeElement[] = []; const seen = new Map(); for (const type of node.types) { const flattenedTypeMembers = flattenTypeLiteralNodeReference(checker, type); - if (!flattenedTypeMembers || !flattenedTypeMembers.every(type => type.name && addToSeen(seen, getNameFromPropertyName(type.name) as string))) { + if ( + !flattenedTypeMembers + || !flattenedTypeMembers.every(type => + type.name && addToSeen(seen, getNameFromPropertyName(type.name) as string) + ) + ) { return undefined; } @@ -218,7 +239,12 @@ function rangeContainsSkipTrivia(r1: TextRange, node: Node, file: SourceFile): b return rangeContainsStartEnd(r1, skipTrivia(file.text, node.pos), node.end); } -function collectTypeParameters(checker: TypeChecker, selection: TypeNode, enclosingNode: Node, file: SourceFile): TypeParameterDeclaration[] | undefined { +function collectTypeParameters( + checker: TypeChecker, + selection: TypeNode, + enclosingNode: Node, + file: SourceFile, +): TypeParameterDeclaration[] | undefined { const result: TypeParameterDeclaration[] = []; return visitor(selection) ? undefined : result; @@ -226,16 +252,27 @@ function collectTypeParameters(checker: TypeChecker, selection: TypeNode, enclos if (isTypeReferenceNode(node)) { if (isIdentifier(node.typeName)) { const typeName = node.typeName; - const symbol = checker.resolveName(typeName.text, typeName, SymbolFlags.TypeParameter, /*excludeGlobals*/ true); + const symbol = checker.resolveName( + typeName.text, + typeName, + SymbolFlags.TypeParameter, + /*excludeGlobals*/ true, + ); for (const decl of symbol?.declarations || emptyArray) { if (isTypeParameterDeclaration(decl) && decl.getSourceFile() === file) { // skip extraction if the type node is in the range of the type parameter declaration. // function foo(): void; - if (decl.name.escapedText === typeName.escapedText && rangeContainsSkipTrivia(decl, selection, file)) { + if ( + decl.name.escapedText === typeName.escapedText + && rangeContainsSkipTrivia(decl, selection, file) + ) { return true; } - if (rangeContainsSkipTrivia(enclosingNode, decl, file) && !rangeContainsSkipTrivia(selection, decl, file)) { + if ( + rangeContainsSkipTrivia(enclosingNode, decl, file) + && !rangeContainsSkipTrivia(selection, decl, file) + ) { pushIfUnique(result, decl); break; } @@ -244,21 +281,35 @@ function collectTypeParameters(checker: TypeChecker, selection: TypeNode, enclos } } else if (isInferTypeNode(node)) { - const conditionalTypeNode = findAncestor(node, n => isConditionalTypeNode(n) && rangeContainsSkipTrivia(n.extendsType, node, file)); + const conditionalTypeNode = findAncestor( + node, + n => isConditionalTypeNode(n) && rangeContainsSkipTrivia(n.extendsType, node, file), + ); if (!conditionalTypeNode || !rangeContainsSkipTrivia(selection, conditionalTypeNode, file)) { return true; } } else if ((isTypePredicateNode(node) || isThisTypeNode(node))) { const functionLikeNode = findAncestor(node.parent, isFunctionLike); - if (functionLikeNode && functionLikeNode.type && rangeContainsSkipTrivia(functionLikeNode.type, node, file) && !rangeContainsSkipTrivia(selection, functionLikeNode, file)) { + if ( + functionLikeNode && functionLikeNode.type && rangeContainsSkipTrivia(functionLikeNode.type, node, file) + && !rangeContainsSkipTrivia(selection, functionLikeNode, file) + ) { return true; } } else if (isTypeQueryNode(node)) { if (isIdentifier(node.exprName)) { - const symbol = checker.resolveName(node.exprName.text, node.exprName, SymbolFlags.Value, /*excludeGlobals*/ false); - if (symbol?.valueDeclaration && rangeContainsSkipTrivia(enclosingNode, symbol.valueDeclaration, file) && !rangeContainsSkipTrivia(selection, symbol.valueDeclaration, file)) { + const symbol = checker.resolveName( + node.exprName.text, + node.exprName, + SymbolFlags.Value, + /*excludeGlobals*/ false, + ); + if ( + symbol?.valueDeclaration && rangeContainsSkipTrivia(enclosingNode, symbol.valueDeclaration, file) + && !rangeContainsSkipTrivia(selection, symbol.valueDeclaration, file) + ) { return true; } } @@ -269,7 +320,11 @@ function collectTypeParameters(checker: TypeChecker, selection: TypeNode, enclos } } - if (file && isTupleTypeNode(node) && (getLineAndCharacterOfPosition(file, node.pos).line === getLineAndCharacterOfPosition(file, node.end).line)) { + if ( + file && isTupleTypeNode(node) + && (getLineAndCharacterOfPosition(file, node.pos).line + === getLineAndCharacterOfPosition(file, node.end).line) + ) { setEmitFlags(node, EmitFlags.SingleLine); } @@ -283,11 +338,24 @@ function doTypeAliasChange(changes: textChanges.ChangeTracker, file: SourceFile, const newTypeNode = factory.createTypeAliasDeclaration( /*modifiers*/ undefined, name, - typeParameters.map(id => factory.updateTypeParameterDeclaration(id, id.modifiers, id.name, id.constraint, /*defaultType*/ undefined)), + typeParameters.map(id => + factory.updateTypeParameterDeclaration(id, id.modifiers, id.name, id.constraint, /*defaultType*/ undefined) + ), selection, ); changes.insertNodeBefore(file, enclosingNode, ignoreSourceNewlines(newTypeNode), /*blankLineBetween*/ true); - changes.replaceNode(file, selection, factory.createTypeReferenceNode(name, typeParameters.map(id => factory.createTypeReferenceNode(id.name, /*typeArguments*/ undefined))), { leadingTriviaOption: textChanges.LeadingTriviaOption.Exclude, trailingTriviaOption: textChanges.TrailingTriviaOption.ExcludeWhitespace }); + changes.replaceNode( + file, + selection, + factory.createTypeReferenceNode( + name, + typeParameters.map(id => factory.createTypeReferenceNode(id.name, /*typeArguments*/ undefined)), + ), + { + leadingTriviaOption: textChanges.LeadingTriviaOption.Exclude, + trailingTriviaOption: textChanges.TrailingTriviaOption.ExcludeWhitespace, + }, + ); } function doInterfaceChange(changes: textChanges.ChangeTracker, file: SourceFile, name: string, info: InterfaceInfo) { @@ -302,10 +370,27 @@ function doInterfaceChange(changes: textChanges.ChangeTracker, file: SourceFile, ); setTextRange(newTypeNode, typeElements[0]?.parent); changes.insertNodeBefore(file, enclosingNode, ignoreSourceNewlines(newTypeNode), /*blankLineBetween*/ true); - changes.replaceNode(file, selection, factory.createTypeReferenceNode(name, typeParameters.map(id => factory.createTypeReferenceNode(id.name, /*typeArguments*/ undefined))), { leadingTriviaOption: textChanges.LeadingTriviaOption.Exclude, trailingTriviaOption: textChanges.TrailingTriviaOption.ExcludeWhitespace }); + changes.replaceNode( + file, + selection, + factory.createTypeReferenceNode( + name, + typeParameters.map(id => factory.createTypeReferenceNode(id.name, /*typeArguments*/ undefined)), + ), + { + leadingTriviaOption: textChanges.LeadingTriviaOption.Exclude, + trailingTriviaOption: textChanges.TrailingTriviaOption.ExcludeWhitespace, + }, + ); } -function doTypedefChange(changes: textChanges.ChangeTracker, context: RefactorContext, file: SourceFile, name: string, info: ExtractInfo) { +function doTypedefChange( + changes: textChanges.ChangeTracker, + context: RefactorContext, + file: SourceFile, + name: string, + info: ExtractInfo, +) { const { enclosingNode, selection, typeParameters } = info; setEmitFlags(selection, EmitFlags.NoComments | EmitFlags.NoNestedComments); @@ -328,18 +413,29 @@ function doTypedefChange(changes: textChanges.ChangeTracker, context: RefactorCo templates.push(template); }); - const jsDoc = factory.createJSDocComment(/*comment*/ undefined, factory.createNodeArray(concatenate(templates, [node]))); + const jsDoc = factory.createJSDocComment( + /*comment*/ undefined, + factory.createNodeArray(concatenate(templates, [node])), + ); if (isJSDoc(enclosingNode)) { const pos = enclosingNode.getStart(file); const newLineCharacter = getNewLineOrDefaultFromHost(context.host, context.formatContext?.options); changes.insertNodeAt(file, enclosingNode.getStart(file), jsDoc, { - suffix: newLineCharacter + newLineCharacter + file.text.slice(getPrecedingNonSpaceCharacterPosition(file.text, pos - 1), pos), + suffix: newLineCharacter + newLineCharacter + + file.text.slice(getPrecedingNonSpaceCharacterPosition(file.text, pos - 1), pos), }); } else { changes.insertNodeBefore(file, enclosingNode, jsDoc, /*blankLineBetween*/ true); } - changes.replaceNode(file, selection, factory.createTypeReferenceNode(name, typeParameters.map(id => factory.createTypeReferenceNode(id.name, /*typeArguments*/ undefined)))); + changes.replaceNode( + file, + selection, + factory.createTypeReferenceNode( + name, + typeParameters.map(id => factory.createTypeReferenceNode(id.name, /*typeArguments*/ undefined)), + ), + ); } function getEnclosingNode(node: Node, isJS: boolean) { diff --git a/src/services/refactors/generateGetAccessorAndSetAccessor.ts b/src/services/refactors/generateGetAccessorAndSetAccessor.ts index 2756ae20471ed..efd9e74f0bc51 100644 --- a/src/services/refactors/generateGetAccessorAndSetAccessor.ts +++ b/src/services/refactors/generateGetAccessorAndSetAccessor.ts @@ -27,21 +27,45 @@ registerRefactor(actionName, { kinds: [generateGetSetAction.kind], getEditsForAction: function getRefactorActionsToGenerateGetAndSetAccessors(context, actionName) { if (!context.endPosition) return undefined; - const info = codefix.getAccessorConvertiblePropertyAtPosition(context.file, context.program, context.startPosition, context.endPosition); + const info = codefix.getAccessorConvertiblePropertyAtPosition( + context.file, + context.program, + context.startPosition, + context.endPosition, + ); Debug.assert(info && !isRefactorErrorInfo(info), "Expected applicable refactor info"); - const edits = codefix.generateAccessorFromProperty(context.file, context.program, context.startPosition, context.endPosition, context, actionName); + const edits = codefix.generateAccessorFromProperty( + context.file, + context.program, + context.startPosition, + context.endPosition, + context, + actionName, + ); if (!edits) return undefined; const renameFilename = context.file.fileName; const nameNeedRename = info.renameAccessor ? info.accessorName : info.fieldName; const renameLocationOffset = isIdentifier(nameNeedRename) ? 0 : -1; - const renameLocation = renameLocationOffset + getRenameLocation(edits, renameFilename, nameNeedRename.text, /*preferLastLocation*/ isParameter(info.declaration)); + const renameLocation = renameLocationOffset + + getRenameLocation( + edits, + renameFilename, + nameNeedRename.text, + /*preferLastLocation*/ isParameter(info.declaration), + ); return { renameFilename, renameLocation, edits }; }, getAvailableActions(context: RefactorContext): readonly ApplicableRefactorInfo[] { if (!context.endPosition) return emptyArray; - const info = codefix.getAccessorConvertiblePropertyAtPosition(context.file, context.program, context.startPosition, context.endPosition, context.triggerReason === "invoked"); + const info = codefix.getAccessorConvertiblePropertyAtPosition( + context.file, + context.program, + context.startPosition, + context.endPosition, + context.triggerReason === "invoked", + ); if (!info) return emptyArray; if (!isRefactorErrorInfo(info)) { diff --git a/src/services/refactors/inferFunctionReturnType.ts b/src/services/refactors/inferFunctionReturnType.ts index d4f4a5c871cfc..2cf7acdec57be 100644 --- a/src/services/refactors/inferFunctionReturnType.ts +++ b/src/services/refactors/inferFunctionReturnType.ts @@ -51,7 +51,10 @@ registerRefactor(refactorName, { function getRefactorEditsToInferReturnType(context: RefactorContext): RefactorEditInfo | undefined { const info = getInfo(context); if (info && !isRefactorErrorInfo(info)) { - const edits = textChanges.ChangeTracker.with(context, t => doChange(context.file, t, info.declaration, info.returnTypeNode)); + const edits = textChanges.ChangeTracker.with( + context, + t => doChange(context.file, t, info.declaration, info.returnTypeNode), + ); return { renameFilename: undefined, renameLocation: undefined, edits }; } return undefined; @@ -88,7 +91,12 @@ interface FunctionInfo { returnTypeNode: TypeNode; } -function doChange(sourceFile: SourceFile, changes: textChanges.ChangeTracker, declaration: ConvertibleDeclaration, typeNode: TypeNode) { +function doChange( + sourceFile: SourceFile, + changes: textChanges.ChangeTracker, + declaration: ConvertibleDeclaration, + typeNode: TypeNode, +) { const closeParen = findChildOfKind(declaration, SyntaxKind.CloseParenToken, sourceFile); const needParens = isArrowFunction(declaration) && closeParen === undefined; const endNode = needParens ? first(declaration.parameters) : closeParen; @@ -105,9 +113,13 @@ function getInfo(context: RefactorContext): FunctionInfo | RefactorErrorInfo | u if (isInJSFile(context.file) || !refactorKindBeginsWith(inferReturnTypeAction.kind, context.kind)) return; const token = getTokenAtPosition(context.file, context.startPosition); - const declaration = findAncestor(token, n => - isBlock(n) || n.parent && isArrowFunction(n.parent) && (n.kind === SyntaxKind.EqualsGreaterThanToken || n.parent.body === n) ? "quit" : - isConvertibleDeclaration(n)) as ConvertibleDeclaration | undefined; + const declaration = findAncestor( + token, + n => isBlock(n) + || n.parent && isArrowFunction(n.parent) + && (n.kind === SyntaxKind.EqualsGreaterThanToken || n.parent.body === n) ? "quit" + : isConvertibleDeclaration(n), + ) as ConvertibleDeclaration | undefined; if (!declaration || !declaration.body || declaration.type) { return { error: getLocaleSpecificMessage(Diagnostics.Return_type_must_be_inferred_from_a_function) }; } diff --git a/src/services/refactors/inlineVariable.ts b/src/services/refactors/inlineVariable.ts index 3b9b94c062424..71493ec08fc8d 100644 --- a/src/services/refactors/inlineVariable.ts +++ b/src/services/refactors/inlineVariable.ts @@ -124,7 +124,12 @@ registerRefactor(refactorName, { }, }); -function getInliningInfo(file: SourceFile, startPosition: number, tryWithReferenceToken: boolean, program: Program): InliningInfo | RefactorErrorInfo | undefined { +function getInliningInfo( + file: SourceFile, + startPosition: number, + tryWithReferenceToken: boolean, + program: Program, +): InliningInfo | RefactorErrorInfo | undefined { const checker = program.getTypeChecker(); const token = getTouchingPropertyName(file, startPosition); const parent = token.parent; @@ -135,10 +140,14 @@ function getInliningInfo(file: SourceFile, startPosition: number, tryWithReferen // If triggered in a variable declaration, make sure it's not in a catch clause or for-loop // and that it has a value. - if (isInitializedVariable(parent) && isVariableDeclarationInVariableStatement(parent) && isIdentifier(parent.name)) { + if ( + isInitializedVariable(parent) && isVariableDeclarationInVariableStatement(parent) && isIdentifier(parent.name) + ) { // Don't inline the variable if it has multiple declarations. if (checker.getMergedSymbol(parent.symbol).declarations?.length !== 1) { - return { error: getLocaleSpecificMessage(Diagnostics.Variables_with_multiple_declarations_cannot_be_inlined) }; + return { + error: getLocaleSpecificMessage(Diagnostics.Variables_with_multiple_declarations_cannot_be_inlined), + }; } // Do not inline if the variable is exported. @@ -158,12 +167,17 @@ function getInliningInfo(file: SourceFile, startPosition: number, tryWithReferen // Don't inline the variable if it has multiple declarations. if (definition?.declarations?.length !== 1) { - return { error: getLocaleSpecificMessage(Diagnostics.Variables_with_multiple_declarations_cannot_be_inlined) }; + return { + error: getLocaleSpecificMessage(Diagnostics.Variables_with_multiple_declarations_cannot_be_inlined), + }; } // Make sure we're not inlining something like "let foo;" or "for (let i = 0; i < 5; i++) {}". const declaration = definition.declarations[0]; - if (!isInitializedVariable(declaration) || !isVariableDeclarationInVariableStatement(declaration) || !isIdentifier(declaration.name)) { + if ( + !isInitializedVariable(declaration) || !isVariableDeclarationInVariableStatement(declaration) + || !isIdentifier(declaration.name) + ) { return undefined; } @@ -186,32 +200,41 @@ function isDeclarationExported(declaration: InitializedVariableDeclaration): boo return some(variableStatement.modifiers, isExportModifier); } -function getReferenceNodes(declaration: InitializedVariableDeclaration, checker: TypeChecker, file: SourceFile): Identifier[] | undefined { +function getReferenceNodes( + declaration: InitializedVariableDeclaration, + checker: TypeChecker, + file: SourceFile, +): Identifier[] | undefined { const references: Identifier[] = []; - const cannotInline = FindAllReferences.Core.eachSymbolReferenceInFile(declaration.name as Identifier, checker, file, ref => { - // Only inline if all references are reads. Else we might end up with an invalid scenario like: - // const y = x++ + 1 -> const y = 2++ + 1 - if (FindAllReferences.isWriteAccessForReference(ref)) { - return true; - } + const cannotInline = FindAllReferences.Core.eachSymbolReferenceInFile( + declaration.name as Identifier, + checker, + file, + ref => { + // Only inline if all references are reads. Else we might end up with an invalid scenario like: + // const y = x++ + 1 -> const y = 2++ + 1 + if (FindAllReferences.isWriteAccessForReference(ref)) { + return true; + } - // We cannot inline exported variables like "export { x as y }" or "export default foo". - if (isExportSpecifier(ref.parent) || isExportAssignment(ref.parent)) { - return true; - } + // We cannot inline exported variables like "export { x as y }" or "export default foo". + if (isExportSpecifier(ref.parent) || isExportAssignment(ref.parent)) { + return true; + } - // typeof needs an identifier, so we can't inline a value in there. - if (isTypeQueryNode(ref.parent)) { - return true; - } + // typeof needs an identifier, so we can't inline a value in there. + if (isTypeQueryNode(ref.parent)) { + return true; + } - // Cannot inline recursive declarations (e.g. const foo = () => foo();) - if (textRangeContainsPositionInclusive(declaration, ref.pos)) { - return true; - } + // Cannot inline recursive declarations (e.g. const foo = () => foo();) + if (textRangeContainsPositionInclusive(declaration, ref.pos)) { + return true; + } - references.push(ref); - }); + references.push(ref); + }, + ); return references.length === 0 || cannotInline ? undefined : references; } @@ -228,7 +251,10 @@ function getReplacementExpression(reference: Node, replacement: Expression): Exp // Note that binaryOperandNeedsParentheses has further logic when the precedences // are equal, but for the purposes of this refactor we keep things simple and // instead just check for special cases with needsParentheses. - if (isExpression(parent) && (getExpressionPrecedence(replacement) < getExpressionPrecedence(parent) || needsParentheses(parent))) { + if ( + isExpression(parent) + && (getExpressionPrecedence(replacement) < getExpressionPrecedence(parent) || needsParentheses(parent)) + ) { return factory.createParenthesizedExpression(replacement); } @@ -240,7 +266,9 @@ function getReplacementExpression(reference: Node, replacement: Expression): Exp // Property access of numeric literals and objects need parentheses. // E.g.: const x = 1; x.toString(); -> (1).toString(); - if (isPropertyAccessExpression(parent) && (isNumericLiteral(replacement) || isObjectLiteralExpression(replacement))) { + if ( + isPropertyAccessExpression(parent) && (isNumericLiteral(replacement) || isObjectLiteralExpression(replacement)) + ) { return factory.createParenthesizedExpression(replacement); } diff --git a/src/services/refactors/moveToFile.ts b/src/services/refactors/moveToFile.ts index 352c9043b40f4..bf0d6fff7f2be 100644 --- a/src/services/refactors/moveToFile.ts +++ b/src/services/refactors/moveToFile.ts @@ -158,7 +158,10 @@ const moveToFileAction = { }; registerRefactor(refactorNameForMoveToFile, { kinds: [moveToFileAction.kind], - getAvailableActions: function getRefactorActionsToMoveToFile(context, interactiveRefactorArguments): readonly ApplicableRefactorInfo[] { + getAvailableActions: function getRefactorActionsToMoveToFile( + context, + interactiveRefactorArguments, + ): readonly ApplicableRefactorInfo[] { const statements = getStatementsToMove(context); if (!interactiveRefactorArguments) { return emptyArray; @@ -167,11 +170,24 @@ registerRefactor(refactorNameForMoveToFile, { return [{ name: refactorNameForMoveToFile, description, actions: [moveToFileAction] }]; } if (context.preferences.provideRefactorNotApplicableReason) { - return [{ name: refactorNameForMoveToFile, description, actions: [{ ...moveToFileAction, notApplicableReason: getLocaleSpecificMessage(Diagnostics.Selection_is_not_a_valid_statement_or_statements) }] }]; + return [{ + name: refactorNameForMoveToFile, + description, + actions: [{ + ...moveToFileAction, + notApplicableReason: getLocaleSpecificMessage( + Diagnostics.Selection_is_not_a_valid_statement_or_statements, + ), + }], + }]; } return emptyArray; }, - getEditsForAction: function getRefactorEditsToMoveToFile(context, actionName, interactiveRefactorArguments): RefactorEditInfo | undefined { + getEditsForAction: function getRefactorEditsToMoveToFile( + context, + actionName, + interactiveRefactorArguments, + ): RefactorEditInfo | undefined { Debug.assert(actionName === refactorNameForMoveToFile, "Wrong refactor invoked"); const statements = Debug.checkDefined(getStatementsToMove(context)); const { host, program } = context; @@ -181,7 +197,19 @@ registerRefactor(refactorNameForMoveToFile, { if (host.fileExists(targetFile) && program.getSourceFile(targetFile) === undefined) { return error(getLocaleSpecificMessage(Diagnostics.Cannot_move_statements_to_the_selected_file)); } - const edits = textChanges.ChangeTracker.with(context, t => doChange(context, context.file, interactiveRefactorArguments.targetFile, context.program, statements, t, context.host, context.preferences)); + const edits = textChanges.ChangeTracker.with( + context, + t => doChange( + context, + context.file, + interactiveRefactorArguments.targetFile, + context.program, + statements, + t, + context.host, + context.preferences, + ), + ); return { edits, renameFilename: undefined, renameLocation: undefined }; } return error(getLocaleSpecificMessage(Diagnostics.Cannot_move_to_file_selected_file_is_invalid)); @@ -192,18 +220,55 @@ function error(notApplicableReason: string) { return { edits: [], renameFilename: undefined, renameLocation: undefined, notApplicableReason }; } -function doChange(context: RefactorContext, oldFile: SourceFile, targetFile: string, program: Program, toMove: ToMove, changes: textChanges.ChangeTracker, host: LanguageServiceHost, preferences: UserPreferences): void { +function doChange( + context: RefactorContext, + oldFile: SourceFile, + targetFile: string, + program: Program, + toMove: ToMove, + changes: textChanges.ChangeTracker, + host: LanguageServiceHost, + preferences: UserPreferences, +): void { const checker = program.getTypeChecker(); const usage = getUsageInfo(oldFile, toMove.all, checker); // For a new file if (!host.fileExists(targetFile)) { - changes.createNewFile(oldFile, targetFile, getNewStatementsAndRemoveFromOldFile(oldFile, targetFile, usage, changes, toMove, program, host, preferences)); + changes.createNewFile( + oldFile, + targetFile, + getNewStatementsAndRemoveFromOldFile( + oldFile, + targetFile, + usage, + changes, + toMove, + program, + host, + preferences, + ), + ); addNewFileToTsconfig(program, changes, oldFile.fileName, targetFile, hostGetCanonicalFileName(host)); } else { const targetSourceFile = Debug.checkDefined(program.getSourceFile(targetFile)); - const importAdder = codefix.createImportAdder(targetSourceFile, context.program, context.preferences, context.host); - getNewStatementsAndRemoveFromOldFile(oldFile, targetSourceFile, usage, changes, toMove, program, host, preferences, importAdder); + const importAdder = codefix.createImportAdder( + targetSourceFile, + context.program, + context.preferences, + context.host, + ); + getNewStatementsAndRemoveFromOldFile( + oldFile, + targetSourceFile, + usage, + changes, + toMove, + program, + host, + preferences, + importAdder, + ); } } @@ -220,7 +285,11 @@ function getNewStatementsAndRemoveFromOldFile( ) { const checker = program.getTypeChecker(); const prologueDirectives = takeWhile(oldFile.statements, isPrologueDirective); - if (oldFile.externalModuleIndicator === undefined && oldFile.commonJsModuleIndicator === undefined && usage.oldImportsNeededByTargetFile.size === 0 && usage.targetFileImportsFromOldFile.size === 0 && typeof targetFile === "string") { + if ( + oldFile.externalModuleIndicator === undefined && oldFile.commonJsModuleIndicator === undefined + && usage.oldImportsNeededByTargetFile.size === 0 && usage.targetFileImportsFromOldFile.size === 0 + && typeof targetFile === "string" + ) { deleteMovedStatements(oldFile, toMove.ranges, changes); return [...prologueDirectives, ...toMove.all]; } @@ -228,9 +297,22 @@ function getNewStatementsAndRemoveFromOldFile( // If the targetFile is a string, it’s the file name for a new file, if it’s a SourceFile, it’s the existing target file. const targetFileName = typeof targetFile === "string" ? targetFile : targetFile.fileName; - const useEsModuleSyntax = !fileShouldUseJavaScriptRequire(targetFileName, program, host, !!oldFile.commonJsModuleIndicator); + const useEsModuleSyntax = !fileShouldUseJavaScriptRequire( + targetFileName, + program, + host, + !!oldFile.commonJsModuleIndicator, + ); const quotePreference = getQuotePreference(oldFile, preferences); - const importsFromTargetFile = createOldFileImportsFromTargetFile(oldFile, usage.oldFileImportsFromTargetFile, targetFileName, program, host, useEsModuleSyntax, quotePreference); + const importsFromTargetFile = createOldFileImportsFromTargetFile( + oldFile, + usage.oldFileImportsFromTargetFile, + targetFileName, + program, + host, + useEsModuleSyntax, + quotePreference, + ); if (importsFromTargetFile) { insertImports(changes, oldFile, importsFromTargetFile, /*blankLineBetween*/ true, preferences); } @@ -239,7 +321,19 @@ function getNewStatementsAndRemoveFromOldFile( deleteMovedStatements(oldFile, toMove.ranges, changes); updateImportsInOtherFiles(changes, program, host, oldFile, usage.movedSymbols, targetFileName, quotePreference); - const imports = getTargetFileImportsAndAddExportInOldFile(oldFile, targetFileName, usage.oldImportsNeededByTargetFile, usage.targetFileImportsFromOldFile, changes, checker, program, host, useEsModuleSyntax, quotePreference, importAdder); + const imports = getTargetFileImportsAndAddExportInOldFile( + oldFile, + targetFileName, + usage.oldImportsNeededByTargetFile, + usage.targetFileImportsFromOldFile, + changes, + checker, + program, + host, + useEsModuleSyntax, + quotePreference, + importAdder, + ); const body = addExports(oldFile, toMove.all, usage.oldFileImportsFromTargetFile, useEsModuleSyntax); if (typeof targetFile !== "string") { if (targetFile.statements.length > 0) { @@ -298,7 +392,14 @@ function getTargetFileImportsAndAddExportInOldFile( catch { for (const oldStatement of oldFile.statements) { forEachImportInStatement(oldStatement, i => { - append(copiedOldImports, filterImport(i, factory.createStringLiteral(moduleSpecifierFromImport(i).text), name => importsToCopy.has(checker.getSymbolAtLocation(name)!))); + append( + copiedOldImports, + filterImport( + i, + factory.createStringLiteral(moduleSpecifierFromImport(i).text), + name => importsToCopy.has(checker.getSymbolAtLocation(name)!), + ), + ); }); } } @@ -310,14 +411,37 @@ function getTargetFileImportsAndAddExportInOldFile( forEachImportInStatement(oldStatement, i => { // Recomputing module specifier const moduleSpecifier = moduleSpecifierFromImport(i); - const resolved = oldFile.resolvedModules?.get(moduleSpecifier.text, getModeForUsageLocation(oldFile, moduleSpecifier)); + const resolved = oldFile.resolvedModules?.get( + moduleSpecifier.text, + getModeForUsageLocation(oldFile, moduleSpecifier), + ); const fileName = resolved?.resolvedModule?.resolvedFileName; if (fileName && targetSourceFile) { - const newModuleSpecifier = getModuleSpecifier(program.getCompilerOptions(), targetSourceFile, targetSourceFile.path, fileName, createModuleSpecifierResolutionHost(program, host)); - append(copiedOldImports, filterImport(i, makeStringLiteral(newModuleSpecifier, quotePreference), name => importsToCopy.has(checker.getSymbolAtLocation(name)!))); + const newModuleSpecifier = getModuleSpecifier( + program.getCompilerOptions(), + targetSourceFile, + targetSourceFile.path, + fileName, + createModuleSpecifierResolutionHost(program, host), + ); + append( + copiedOldImports, + filterImport( + i, + makeStringLiteral(newModuleSpecifier, quotePreference), + name => importsToCopy.has(checker.getSymbolAtLocation(name)!), + ), + ); } else { - append(copiedOldImports, filterImport(i, factory.createStringLiteral(moduleSpecifierFromImport(i).text), name => importsToCopy.has(checker.getSymbolAtLocation(name)!))); + append( + copiedOldImports, + filterImport( + i, + factory.createStringLiteral(moduleSpecifierFromImport(i).text), + name => importsToCopy.has(checker.getSymbolAtLocation(name)!), + ), + ); } }); } @@ -355,12 +479,42 @@ function getTargetFileImportsAndAddExportInOldFile( } }); return targetFileSourceFile - ? append(copiedOldImports, makeImportOrRequire(targetFileSourceFile, oldFileDefault, oldFileNamedImports, oldFile.fileName, program, host, useEsModuleSyntax, quotePreference)) - : append(copiedOldImports, makeImportOrRequire(oldFile, oldFileDefault, oldFileNamedImports, oldFile.fileName, program, host, useEsModuleSyntax, quotePreference)); + ? append( + copiedOldImports, + makeImportOrRequire( + targetFileSourceFile, + oldFileDefault, + oldFileNamedImports, + oldFile.fileName, + program, + host, + useEsModuleSyntax, + quotePreference, + ), + ) + : append( + copiedOldImports, + makeImportOrRequire( + oldFile, + oldFileDefault, + oldFileNamedImports, + oldFile.fileName, + program, + host, + useEsModuleSyntax, + quotePreference, + ), + ); } /** @internal */ -export function addNewFileToTsconfig(program: Program, changes: textChanges.ChangeTracker, oldFileName: string, newFileNameWithExtension: string, getCanonicalFileName: GetCanonicalFileName): void { +export function addNewFileToTsconfig( + program: Program, + changes: textChanges.ChangeTracker, + oldFileName: string, + newFileNameWithExtension: string, + getCanonicalFileName: GetCanonicalFileName, +): void { const cfg = program.getCompilerOptions().configFile; if (!cfg) return; @@ -368,24 +522,47 @@ export function addNewFileToTsconfig(program: Program, changes: textChanges.Chan const newFilePath = getRelativePathFromFile(cfg.fileName, newFileAbsolutePath, getCanonicalFileName); const cfgObject = cfg.statements[0] && tryCast(cfg.statements[0].expression, isObjectLiteralExpression); - const filesProp = cfgObject && find(cfgObject.properties, (prop): prop is PropertyAssignment => isPropertyAssignment(prop) && isStringLiteral(prop.name) && prop.name.text === "files"); + const filesProp = cfgObject + && find( + cfgObject.properties, + (prop): prop is PropertyAssignment => + isPropertyAssignment(prop) && isStringLiteral(prop.name) && prop.name.text === "files", + ); if (filesProp && isArrayLiteralExpression(filesProp.initializer)) { - changes.insertNodeInListAfter(cfg, last(filesProp.initializer.elements), factory.createStringLiteral(newFilePath), filesProp.initializer.elements); + changes.insertNodeInListAfter( + cfg, + last(filesProp.initializer.elements), + factory.createStringLiteral(newFilePath), + filesProp.initializer.elements, + ); } } /** @internal */ -export function deleteMovedStatements(sourceFile: SourceFile, moved: readonly StatementRange[], changes: textChanges.ChangeTracker) { +export function deleteMovedStatements( + sourceFile: SourceFile, + moved: readonly StatementRange[], + changes: textChanges.ChangeTracker, +) { for (const { first, afterLast } of moved) { changes.deleteNodeRangeExcludingEnd(sourceFile, first, afterLast); } } /** @internal */ -export function deleteUnusedOldImports(oldFile: SourceFile, toMove: readonly Statement[], changes: textChanges.ChangeTracker, toDelete: Set, checker: TypeChecker) { +export function deleteUnusedOldImports( + oldFile: SourceFile, + toMove: readonly Statement[], + changes: textChanges.ChangeTracker, + toDelete: Set, + checker: TypeChecker, +) { for (const statement of oldFile.statements) { if (contains(toMove, statement)) continue; - forEachImportInStatement(statement, i => deleteUnusedImports(oldFile, i, changes, name => toDelete.has(checker.getSymbolAtLocation(name)!))); + forEachImportInStatement( + statement, + i => deleteUnusedImports(oldFile, i, changes, name => toDelete.has(checker.getSymbolAtLocation(name)!)), + ); } } @@ -408,19 +585,43 @@ export function updateImportsInOtherFiles( const shouldMove = (name: Identifier): boolean => { const symbol = isBindingElement(name.parent) - ? getPropertySymbolFromBindingElement(checker, name.parent as ObjectBindingElementWithoutPropertyName) + ? getPropertySymbolFromBindingElement( + checker, + name.parent as ObjectBindingElementWithoutPropertyName, + ) : skipAlias(checker.getSymbolAtLocation(name)!, checker); return !!symbol && movedSymbols.has(symbol); }; deleteUnusedImports(sourceFile, importNode, changes, shouldMove); // These will be changed to imports from the new file const pathToTargetFileWithExtension = resolvePath(getDirectoryPath(oldFile.path), targetFileName); - const newModuleSpecifier = getModuleSpecifier(program.getCompilerOptions(), sourceFile, sourceFile.path, pathToTargetFileWithExtension, createModuleSpecifierResolutionHost(program, host)); - const newImportDeclaration = filterImport(importNode, makeStringLiteral(newModuleSpecifier, quotePreference), shouldMove); + const newModuleSpecifier = getModuleSpecifier( + program.getCompilerOptions(), + sourceFile, + sourceFile.path, + pathToTargetFileWithExtension, + createModuleSpecifierResolutionHost(program, host), + ); + const newImportDeclaration = filterImport( + importNode, + makeStringLiteral(newModuleSpecifier, quotePreference), + shouldMove, + ); if (newImportDeclaration) changes.insertNodeAfter(sourceFile, statement, newImportDeclaration); const ns = getNamespaceLikeImport(importNode); - if (ns) updateNamespaceLikeImport(changes, sourceFile, checker, movedSymbols, newModuleSpecifier, ns, importNode, quotePreference); + if (ns) { + updateNamespaceLikeImport( + changes, + sourceFile, + checker, + movedSymbols, + newModuleSpecifier, + ns, + importNode, + quotePreference, + ); + } }); } } @@ -429,8 +630,9 @@ export function updateImportsInOtherFiles( function getNamespaceLikeImport(node: SupportedImport): Identifier | undefined { switch (node.kind) { case SyntaxKind.ImportDeclaration: - return node.importClause && node.importClause.namedBindings && node.importClause.namedBindings.kind === SyntaxKind.NamespaceImport ? - node.importClause.namedBindings.name : undefined; + return node.importClause && node.importClause.namedBindings + && node.importClause.namedBindings.kind === SyntaxKind.NamespaceImport + ? node.importClause.namedBindings.name : undefined; case SyntaxKind.ImportEqualsDeclaration: return node.name; case SyntaxKind.VariableDeclaration: @@ -455,43 +657,75 @@ function updateNamespaceLikeImport( const toChange: Identifier[] = []; FindAllReferences.Core.eachSymbolReferenceInFile(oldImportId, checker, sourceFile, ref => { if (!isPropertyAccessExpression(ref.parent)) return; - needUniqueName = needUniqueName || !!checker.resolveName(preferredNewNamespaceName, ref, SymbolFlags.All, /*excludeGlobals*/ true); + needUniqueName = needUniqueName + || !!checker.resolveName(preferredNewNamespaceName, ref, SymbolFlags.All, /*excludeGlobals*/ true); if (movedSymbols.has(checker.getSymbolAtLocation(ref.parent.name)!)) { toChange.push(ref); } }); if (toChange.length) { - const newNamespaceName = needUniqueName ? getUniqueName(preferredNewNamespaceName, sourceFile) : preferredNewNamespaceName; + const newNamespaceName = needUniqueName ? getUniqueName(preferredNewNamespaceName, sourceFile) + : preferredNewNamespaceName; for (const ref of toChange) { changes.replaceNode(sourceFile, ref, factory.createIdentifier(newNamespaceName)); } - changes.insertNodeAfter(sourceFile, oldImportNode, updateNamespaceLikeImportNode(oldImportNode, preferredNewNamespaceName, newModuleSpecifier, quotePreference)); + changes.insertNodeAfter( + sourceFile, + oldImportNode, + updateNamespaceLikeImportNode( + oldImportNode, + preferredNewNamespaceName, + newModuleSpecifier, + quotePreference, + ), + ); } } -function updateNamespaceLikeImportNode(node: SupportedImport, newNamespaceName: string, newModuleSpecifier: string, quotePreference: QuotePreference): Node { +function updateNamespaceLikeImportNode( + node: SupportedImport, + newNamespaceName: string, + newModuleSpecifier: string, + quotePreference: QuotePreference, +): Node { const newNamespaceId = factory.createIdentifier(newNamespaceName); const newModuleString = makeStringLiteral(newModuleSpecifier, quotePreference); switch (node.kind) { case SyntaxKind.ImportDeclaration: return factory.createImportDeclaration( /*modifiers*/ undefined, - factory.createImportClause(/*isTypeOnly*/ false, /*name*/ undefined, factory.createNamespaceImport(newNamespaceId)), + factory.createImportClause( + /*isTypeOnly*/ false, + /*name*/ undefined, + factory.createNamespaceImport(newNamespaceId), + ), newModuleString, /*assertClause*/ undefined, ); case SyntaxKind.ImportEqualsDeclaration: - return factory.createImportEqualsDeclaration(/*modifiers*/ undefined, /*isTypeOnly*/ false, newNamespaceId, factory.createExternalModuleReference(newModuleString)); + return factory.createImportEqualsDeclaration( + /*modifiers*/ undefined, + /*isTypeOnly*/ false, + newNamespaceId, + factory.createExternalModuleReference(newModuleString), + ); case SyntaxKind.VariableDeclaration: - return factory.createVariableDeclaration(newNamespaceId, /*exclamationToken*/ undefined, /*type*/ undefined, createRequireCall(newModuleString)); + return factory.createVariableDeclaration( + newNamespaceId, + /*exclamationToken*/ undefined, + /*type*/ undefined, + createRequireCall(newModuleString), + ); default: return Debug.assertNever(node, `Unexpected node kind ${(node as SupportedImport).kind}`); } } function createRequireCall(moduleSpecifier: StringLiteralLike): CallExpression { - return factory.createCallExpression(factory.createIdentifier("require"), /*typeArguments*/ undefined, [moduleSpecifier]); + return factory.createCallExpression(factory.createIdentifier("require"), /*typeArguments*/ undefined, [ + moduleSpecifier, + ]); } /** @internal */ @@ -507,7 +741,10 @@ export function forEachImportInStatement(statement: Statement, cb: (importNode: if (isStringLiteral(statement.moduleSpecifier)) cb(statement as SupportedImport); } else if (isImportEqualsDeclaration(statement)) { - if (isExternalModuleReference(statement.moduleReference) && isStringLiteralLike(statement.moduleReference.expression)) { + if ( + isExternalModuleReference(statement.moduleReference) + && isStringLiteralLike(statement.moduleReference.expression) + ) { cb(statement as SupportedImport); } } @@ -552,7 +789,16 @@ export function createOldFileImportsFromTargetFile( imports.push(symbol.name); } }); - return makeImportOrRequire(sourceFile, defaultImport, imports, targetFileNameWithExtension, program, host, useEs6Imports, quotePreference); + return makeImportOrRequire( + sourceFile, + defaultImport, + imports, + targetFileNameWithExtension, + program, + host, + useEs6Imports, + quotePreference, + ); } /** @internal */ @@ -567,32 +813,64 @@ export function makeImportOrRequire( quotePreference: QuotePreference, ): AnyImportOrRequireStatement | undefined { const pathToTargetFile = resolvePath(getDirectoryPath(sourceFile.path), targetFileNameWithExtension); - const pathToTargetFileWithCorrectExtension = getModuleSpecifier(program.getCompilerOptions(), sourceFile, sourceFile.path, pathToTargetFile, createModuleSpecifierResolutionHost(program, host)); + const pathToTargetFileWithCorrectExtension = getModuleSpecifier( + program.getCompilerOptions(), + sourceFile, + sourceFile.path, + pathToTargetFile, + createModuleSpecifierResolutionHost(program, host), + ); if (useEs6Imports) { - const specifiers = imports.map(i => factory.createImportSpecifier(/*isTypeOnly*/ false, /*propertyName*/ undefined, factory.createIdentifier(i))); + const specifiers = imports.map(i => + factory.createImportSpecifier(/*isTypeOnly*/ false, /*propertyName*/ undefined, factory.createIdentifier(i)) + ); return makeImportIfNecessary(defaultImport, specifiers, pathToTargetFileWithCorrectExtension, quotePreference); } else { Debug.assert(!defaultImport, "No default import should exist"); // If there's a default export, it should have been an es6 module. - const bindingElements = imports.map(i => factory.createBindingElement(/*dotDotDotToken*/ undefined, /*propertyName*/ undefined, i)); + const bindingElements = imports.map(i => + factory.createBindingElement(/*dotDotDotToken*/ undefined, /*propertyName*/ undefined, i) + ); return bindingElements.length - ? makeVariableStatement(factory.createObjectBindingPattern(bindingElements), /*type*/ undefined, createRequireCall(makeStringLiteral(pathToTargetFileWithCorrectExtension, quotePreference))) as RequireVariableStatement + ? makeVariableStatement( + factory.createObjectBindingPattern(bindingElements), + /*type*/ undefined, + createRequireCall(makeStringLiteral(pathToTargetFileWithCorrectExtension, quotePreference)), + ) as RequireVariableStatement : undefined; } } -function makeVariableStatement(name: BindingName, type: TypeNode | undefined, initializer: Expression | undefined, flags: NodeFlags = NodeFlags.Const) { - return factory.createVariableStatement(/*modifiers*/ undefined, factory.createVariableDeclarationList([factory.createVariableDeclaration(name, /*exclamationToken*/ undefined, type, initializer)], flags)); +function makeVariableStatement( + name: BindingName, + type: TypeNode | undefined, + initializer: Expression | undefined, + flags: NodeFlags = NodeFlags.Const, +) { + return factory.createVariableStatement( + /*modifiers*/ undefined, + factory.createVariableDeclarationList([ + factory.createVariableDeclaration(name, /*exclamationToken*/ undefined, type, initializer), + ], flags), + ); } /** @internal */ -export function addExports(sourceFile: SourceFile, toMove: readonly Statement[], needExport: Set, useEs6Exports: boolean): readonly Statement[] { +export function addExports( + sourceFile: SourceFile, + toMove: readonly Statement[], + needExport: Set, + useEs6Exports: boolean, +): readonly Statement[] { return flatMap(toMove, statement => { if ( - isTopLevelDeclarationStatement(statement) && - !isExported(sourceFile, statement, useEs6Exports) && - forEachTopLevelDeclaration(statement, d => needExport.has(Debug.checkDefined(tryCast(d, canHaveSymbol)?.symbol))) + isTopLevelDeclarationStatement(statement) + && !isExported(sourceFile, statement, useEs6Exports) + && forEachTopLevelDeclaration( + statement, + d => needExport.has(Debug.checkDefined(tryCast(d, canHaveSymbol)?.symbol)), + ) ) { const exports = addExport(getSynthesizedDeepClone(statement), useEs6Exports); if (exports) return exports; @@ -601,16 +879,29 @@ export function addExports(sourceFile: SourceFile, toMove: readonly Statement[], }); } -function isExported(sourceFile: SourceFile, decl: TopLevelDeclarationStatement, useEs6Exports: boolean, name?: Identifier): boolean { +function isExported( + sourceFile: SourceFile, + decl: TopLevelDeclarationStatement, + useEs6Exports: boolean, + name?: Identifier, +): boolean { if (useEs6Exports) { - return !isExpressionStatement(decl) && hasSyntacticModifier(decl, ModifierFlags.Export) || !!(name && sourceFile.symbol && sourceFile.symbol.exports?.has(name.escapedText)); + return !isExpressionStatement(decl) && hasSyntacticModifier(decl, ModifierFlags.Export) + || !!(name && sourceFile.symbol && sourceFile.symbol.exports?.has(name.escapedText)); } - return !!sourceFile.symbol && !!sourceFile.symbol.exports && - getNamesToExportInCommonJS(decl).some(name => sourceFile.symbol.exports!.has(escapeLeadingUnderscores(name))); + return !!sourceFile.symbol && !!sourceFile.symbol.exports + && getNamesToExportInCommonJS(decl).some(name => + sourceFile.symbol.exports!.has(escapeLeadingUnderscores(name)) + ); } /** @internal */ -export function deleteUnusedImports(sourceFile: SourceFile, importDecl: SupportedImport, changes: textChanges.ChangeTracker, isUnused: (name: Identifier) => boolean): void { +export function deleteUnusedImports( + sourceFile: SourceFile, + importDecl: SupportedImport, + changes: textChanges.ChangeTracker, + isUnused: (name: Identifier) => boolean, +): void { switch (importDecl.kind) { case SyntaxKind.ImportDeclaration: deleteUnusedImportsInDeclaration(sourceFile, importDecl, changes, isUnused); @@ -628,12 +919,18 @@ export function deleteUnusedImports(sourceFile: SourceFile, importDecl: Supporte } } -function deleteUnusedImportsInDeclaration(sourceFile: SourceFile, importDecl: ImportDeclaration, changes: textChanges.ChangeTracker, isUnused: (name: Identifier) => boolean): void { +function deleteUnusedImportsInDeclaration( + sourceFile: SourceFile, + importDecl: ImportDeclaration, + changes: textChanges.ChangeTracker, + isUnused: (name: Identifier) => boolean, +): void { if (!importDecl.importClause) return; const { name, namedBindings } = importDecl.importClause; const defaultUnused = !name || isUnused(name); - const namedBindingsUnused = !namedBindings || - (namedBindings.kind === SyntaxKind.NamespaceImport ? isUnused(namedBindings.name) : namedBindings.elements.length !== 0 && namedBindings.elements.every(e => isUnused(e.name))); + const namedBindingsUnused = !namedBindings + || (namedBindings.kind === SyntaxKind.NamespaceImport ? isUnused(namedBindings.name) + : namedBindings.elements.length !== 0 && namedBindings.elements.every(e => isUnused(e.name))); if (defaultUnused && namedBindingsUnused) { changes.delete(sourceFile, importDecl); } @@ -646,7 +943,12 @@ function deleteUnusedImportsInDeclaration(sourceFile: SourceFile, importDecl: Im changes.replaceNode( sourceFile, importDecl.importClause, - factory.updateImportClause(importDecl.importClause, importDecl.importClause.isTypeOnly, name, /*namedBindings*/ undefined), + factory.updateImportClause( + importDecl.importClause, + importDecl.importClause.isTypeOnly, + name, + /*namedBindings*/ undefined, + ), ); } else if (namedBindings.kind === SyntaxKind.NamedImports) { @@ -658,13 +960,24 @@ function deleteUnusedImportsInDeclaration(sourceFile: SourceFile, importDecl: Im } } -function deleteUnusedImportsInVariableDeclaration(sourceFile: SourceFile, varDecl: VariableDeclaration, changes: textChanges.ChangeTracker, isUnused: (name: Identifier) => boolean) { +function deleteUnusedImportsInVariableDeclaration( + sourceFile: SourceFile, + varDecl: VariableDeclaration, + changes: textChanges.ChangeTracker, + isUnused: (name: Identifier) => boolean, +) { const { name } = varDecl; switch (name.kind) { case SyntaxKind.Identifier: if (isUnused(name)) { - if (varDecl.initializer && isRequireCall(varDecl.initializer, /*requireStringLiteralLikeArgument*/ true)) { - changes.delete(sourceFile, isVariableDeclarationList(varDecl.parent) && length(varDecl.parent.declarations) === 1 ? varDecl.parent.parent : varDecl); + if ( + varDecl.initializer && isRequireCall(varDecl.initializer, /*requireStringLiteralLikeArgument*/ true) + ) { + changes.delete( + sourceFile, + isVariableDeclarationList(varDecl.parent) && length(varDecl.parent.declarations) === 1 + ? varDecl.parent.parent : varDecl, + ); } else { changes.delete(sourceFile, name); @@ -675,7 +988,11 @@ function deleteUnusedImportsInVariableDeclaration(sourceFile: SourceFile, varDec break; case SyntaxKind.ObjectBindingPattern: if (name.elements.every(e => isIdentifier(e.name) && isUnused(e.name))) { - changes.delete(sourceFile, isVariableDeclarationList(varDecl.parent) && varDecl.parent.declarations.length === 1 ? varDecl.parent.parent : varDecl); + changes.delete( + sourceFile, + isVariableDeclarationList(varDecl.parent) && varDecl.parent.declarations.length === 1 + ? varDecl.parent.parent : varDecl, + ); } else { for (const element of name.elements) { @@ -701,13 +1018,30 @@ function addExport(decl: TopLevelDeclarationStatement, useEs6Exports: boolean): } function addEs6Export(d: TopLevelDeclarationStatement): TopLevelDeclarationStatement { - const modifiers = canHaveModifiers(d) ? concatenate([factory.createModifier(SyntaxKind.ExportKeyword)], getModifiers(d)) : undefined; + const modifiers = canHaveModifiers(d) + ? concatenate([factory.createModifier(SyntaxKind.ExportKeyword)], getModifiers(d)) : undefined; switch (d.kind) { case SyntaxKind.FunctionDeclaration: - return factory.updateFunctionDeclaration(d, modifiers, d.asteriskToken, d.name, d.typeParameters, d.parameters, d.type, d.body); + return factory.updateFunctionDeclaration( + d, + modifiers, + d.asteriskToken, + d.name, + d.typeParameters, + d.parameters, + d.type, + d.body, + ); case SyntaxKind.ClassDeclaration: const decorators = canHaveDecorators(d) ? getDecorators(d) : undefined; - return factory.updateClassDeclaration(d, concatenate(decorators, modifiers), d.name, d.typeParameters, d.heritageClauses, d.members); + return factory.updateClassDeclaration( + d, + concatenate(decorators, modifiers), + d.name, + d.typeParameters, + d.heritageClauses, + d.members, + ); case SyntaxKind.VariableStatement: return factory.updateVariableStatement(d, modifiers, d.declarationList); case SyntaxKind.ModuleDeclaration: @@ -717,7 +1051,14 @@ function addEs6Export(d: TopLevelDeclarationStatement): TopLevelDeclarationState case SyntaxKind.TypeAliasDeclaration: return factory.updateTypeAliasDeclaration(d, modifiers, d.name, d.typeParameters, d.type); case SyntaxKind.InterfaceDeclaration: - return factory.updateInterfaceDeclaration(d, modifiers, d.name, d.typeParameters, d.heritageClauses, d.members); + return factory.updateInterfaceDeclaration( + d, + modifiers, + d.name, + d.typeParameters, + d.heritageClauses, + d.members, + ); case SyntaxKind.ImportEqualsDeclaration: return factory.updateImportEqualsDeclaration(d, modifiers, d.isTypeOnly, d.name, d.moduleReference); case SyntaxKind.ExpressionStatement: @@ -764,7 +1105,11 @@ function getNamesToExportInCommonJS(decl: TopLevelDeclarationStatement): readonl } /** @internal */ -export function filterImport(i: SupportedImport, moduleSpecifier: StringLiteralLike, keep: (name: Identifier) => boolean): SupportedImportStatement | undefined { +export function filterImport( + i: SupportedImport, + moduleSpecifier: StringLiteralLike, + keep: (name: Identifier) => boolean, +): SupportedImportStatement | undefined { switch (i.kind) { case SyntaxKind.ImportDeclaration: { const clause = i.importClause; @@ -772,21 +1117,30 @@ export function filterImport(i: SupportedImport, moduleSpecifier: StringLiteralL const defaultImport = clause.name && keep(clause.name) ? clause.name : undefined; const namedBindings = clause.namedBindings && filterNamedBindings(clause.namedBindings, keep); return defaultImport || namedBindings - ? factory.createImportDeclaration(/*modifiers*/ undefined, factory.createImportClause(clause.isTypeOnly, defaultImport, namedBindings), getSynthesizedDeepClone(moduleSpecifier), /*assertClause*/ undefined) + ? factory.createImportDeclaration( + /*modifiers*/ undefined, + factory.createImportClause(clause.isTypeOnly, defaultImport, namedBindings), + getSynthesizedDeepClone(moduleSpecifier), + /*assertClause*/ undefined, + ) : undefined; } case SyntaxKind.ImportEqualsDeclaration: return keep(i.name) ? i : undefined; case SyntaxKind.VariableDeclaration: { const name = filterBindingName(i.name, keep); - return name ? makeVariableStatement(name, i.type, createRequireCall(moduleSpecifier), i.parent.flags) : undefined; + return name ? makeVariableStatement(name, i.type, createRequireCall(moduleSpecifier), i.parent.flags) + : undefined; } default: return Debug.assertNever(i, `Unexpected import kind ${(i as SupportedImport).kind}`); } } -function filterNamedBindings(namedBindings: NamedImportBindings, keep: (name: Identifier) => boolean): NamedImportBindings | undefined { +function filterNamedBindings( + namedBindings: NamedImportBindings, + keep: (name: Identifier) => boolean, +): NamedImportBindings | undefined { if (namedBindings.kind === SyntaxKind.NamespaceImport) { return keep(namedBindings.name) ? namedBindings : undefined; } @@ -804,7 +1158,9 @@ function filterBindingName(name: BindingName, keep: (name: Identifier) => boolea return name; case SyntaxKind.ObjectBindingPattern: { // We can't handle nested destructurings or property names well here, so just copy them all. - const newElements = name.elements.filter(prop => prop.propertyName || !isIdentifier(prop.name) || keep(prop.name)); + const newElements = name.elements.filter(prop => + prop.propertyName || !isIdentifier(prop.name) || keep(prop.name) + ); return newElements.length ? factory.createObjectBindingPattern(newElements) : undefined; } } @@ -822,7 +1178,11 @@ export function getTopLevelDeclarationStatement(d: TopLevelDeclaration): TopLeve return d.parent.parent; case SyntaxKind.BindingElement: return getTopLevelDeclarationStatement( - cast(d.parent.parent, (p): p is TopLevelVariableDeclaration | BindingElement => isVariableDeclaration(p) || isBindingElement(p)), + cast( + d.parent.parent, + (p): p is TopLevelVariableDeclaration | BindingElement => + isVariableDeclaration(p) || isBindingElement(p), + ), ); default: return d; @@ -830,7 +1190,13 @@ export function getTopLevelDeclarationStatement(d: TopLevelDeclaration): TopLeve } /** @internal */ -export function addExportToChanges(sourceFile: SourceFile, decl: TopLevelDeclarationStatement, name: Identifier, changes: textChanges.ChangeTracker, useEs6Exports: boolean): void { +export function addExportToChanges( + sourceFile: SourceFile, + decl: TopLevelDeclarationStatement, + name: Identifier, + changes: textChanges.ChangeTracker, + useEs6Exports: boolean, +): void { if (isExported(sourceFile, decl, useEs6Exports, name)) return; if (useEs6Exports) { if (!isExpressionStatement(decl)) changes.insertExportModifier(sourceFile, decl); @@ -869,7 +1235,9 @@ export interface UsageInfo { } /** @internal */ -export type TopLevelExpressionStatement = ExpressionStatement & { expression: BinaryExpression & { left: PropertyAccessExpression; }; }; // 'exports.x = ...' +export type TopLevelExpressionStatement = ExpressionStatement & { + expression: BinaryExpression & { left: PropertyAccessExpression; }; +}; // 'exports.x = ...' /** @internal */ export type NonVariableTopLevelDeclaration = @@ -891,7 +1259,12 @@ export interface TopLevelVariableDeclaration extends VariableDeclaration { export type TopLevelDeclaration = NonVariableTopLevelDeclaration | TopLevelVariableDeclaration | BindingElement; /** @internal */ -export function createNewFileName(oldFile: SourceFile, program: Program, context: RefactorContext, host: LanguageServiceHost): string { +export function createNewFileName( + oldFile: SourceFile, + program: Program, + context: RefactorContext, + host: LanguageServiceHost, +): string { const checker = program.getTypeChecker(); const toMove = getStatementsToMove(context); let usage; @@ -986,7 +1359,9 @@ function isPureImport(node: Node): boolean { case SyntaxKind.ImportEqualsDeclaration: return !hasSyntacticModifier(node, ModifierFlags.Export); case SyntaxKind.VariableStatement: - return (node as VariableStatement).declarationList.declarations.every(d => !!d.initializer && isRequireCall(d.initializer, /*requireStringLiteralLikeArgument*/ true)); + return (node as VariableStatement).declarationList.declarations.every(d => + !!d.initializer && isRequireCall(d.initializer, /*requireStringLiteralLikeArgument*/ true) + ); default: return false; } @@ -1007,7 +1382,12 @@ export function getUsageInfo(oldFile: SourceFile, toMove: readonly Statement[], for (const statement of toMove) { forEachTopLevelDeclaration(statement, decl => { - movedSymbols.add(Debug.checkDefined(isExpressionStatement(decl) ? checker.getSymbolAtLocation(decl.expression.left) : decl.symbol, "Need a symbol here")); + movedSymbols.add( + Debug.checkDefined( + isExpressionStatement(decl) ? checker.getSymbolAtLocation(decl.expression.left) : decl.symbol, + "Need a symbol here", + ), + ); }); } for (const statement of toMove) { @@ -1016,9 +1396,16 @@ export function getUsageInfo(oldFile: SourceFile, toMove: readonly Statement[], for (const decl of symbol.declarations) { if (isInImport(decl)) { const prevIsTypeOnly = oldImportsNeededByTargetFile.get(symbol); - oldImportsNeededByTargetFile.set(symbol, prevIsTypeOnly === undefined ? isValidTypeOnlyUseSite : prevIsTypeOnly && isValidTypeOnlyUseSite); + oldImportsNeededByTargetFile.set( + symbol, + prevIsTypeOnly === undefined ? isValidTypeOnlyUseSite + : prevIsTypeOnly && isValidTypeOnlyUseSite, + ); } - else if (isTopLevelDeclaration(decl) && sourceFileOfTopLevelDeclaration(decl) === oldFile && !movedSymbols.has(symbol)) { + else if ( + isTopLevelDeclaration(decl) && sourceFileOfTopLevelDeclaration(decl) === oldFile + && !movedSymbols.has(symbol) + ) { targetFileImportsFromOldFile.add(symbol); } } @@ -1041,7 +1428,13 @@ export function getUsageInfo(oldFile: SourceFile, toMove: readonly Statement[], }); } - return { movedSymbols, targetFileImportsFromOldFile, oldFileImportsFromTargetFile, oldImportsNeededByTargetFile, unusedImportsFromOldFile }; + return { + movedSymbols, + targetFileImportsFromOldFile, + oldFileImportsFromTargetFile, + oldImportsNeededByTargetFile, + unusedImportsFromOldFile, + }; function getJsxNamespaceSymbol(containsJsx: Node | undefined) { if (containsJsx === undefined) { @@ -1053,7 +1446,12 @@ export function getUsageInfo(oldFile: SourceFile, toMove: readonly Statement[], // Strictly speaking, this could resolve to a symbol other than the JSX namespace. // This will produce erroneous output (probably, an incorrectly copied import) but // is expected to be very rare and easily reversible. - const jsxNamespaceSymbol = checker.resolveName(jsxNamespace, containsJsx, SymbolFlags.Namespace, /*excludeGlobals*/ true); + const jsxNamespaceSymbol = checker.resolveName( + jsxNamespace, + containsJsx, + SymbolFlags.Namespace, + /*excludeGlobals*/ true, + ); return !!jsxNamespaceSymbol && some(jsxNamespaceSymbol.declarations, isInImport) ? jsxNamespaceSymbol @@ -1061,7 +1459,12 @@ export function getUsageInfo(oldFile: SourceFile, toMove: readonly Statement[], } } -function makeUniqueFilename(proposedFilename: string, extension: string, inDirectory: string, host: LanguageServiceHost): string { +function makeUniqueFilename( + proposedFilename: string, + extension: string, + inDirectory: string, + host: LanguageServiceHost, +): string { let newFilename = proposedFilename; for (let i = 1;; i++) { const name = combinePaths(inDirectory, newFilename + extension); @@ -1071,10 +1474,15 @@ function makeUniqueFilename(proposedFilename: string, extension: string, inDirec } function inferNewFileName(importsFromNewFile: Set, movedSymbols: Set): string { - return forEachKey(importsFromNewFile, symbolNameNoDefault) || forEachKey(movedSymbols, symbolNameNoDefault) || "newFile"; + return forEachKey(importsFromNewFile, symbolNameNoDefault) || forEachKey(movedSymbols, symbolNameNoDefault) + || "newFile"; } -function forEachReference(node: Node, checker: TypeChecker, onReference: (s: Symbol, isValidTypeOnlyUseSite: boolean) => void) { +function forEachReference( + node: Node, + checker: TypeChecker, + onReference: (s: Symbol, isValidTypeOnlyUseSite: boolean) => void, +) { node.forEachChild(function cb(node) { if (isIdentifier(node) && !isDeclarationName(node)) { const sym = checker.getSymbolAtLocation(node); @@ -1095,14 +1503,27 @@ function forEachTopLevelDeclaration(statement: Statement, cb: (node: TopLevel case SyntaxKind.TypeAliasDeclaration: case SyntaxKind.InterfaceDeclaration: case SyntaxKind.ImportEqualsDeclaration: - return cb(statement as FunctionDeclaration | ClassDeclaration | EnumDeclaration | ModuleDeclaration | TypeAliasDeclaration | InterfaceDeclaration | ImportEqualsDeclaration); + return cb( + statement as + | FunctionDeclaration + | ClassDeclaration + | EnumDeclaration + | ModuleDeclaration + | TypeAliasDeclaration + | InterfaceDeclaration + | ImportEqualsDeclaration, + ); case SyntaxKind.VariableStatement: - return firstDefined((statement as VariableStatement).declarationList.declarations, decl => forEachTopLevelDeclarationInBindingName(decl.name, cb)); + return firstDefined( + (statement as VariableStatement).declarationList.declarations, + decl => forEachTopLevelDeclarationInBindingName(decl.name, cb), + ); case SyntaxKind.ExpressionStatement: { const { expression } = statement as ExpressionStatement; - return isBinaryExpression(expression) && getAssignmentDeclarationKind(expression) === AssignmentDeclarationKind.ExportsProperty + return isBinaryExpression(expression) + && getAssignmentDeclarationKind(expression) === AssignmentDeclarationKind.ExportsProperty ? cb(statement as TopLevelExpressionStatement) : undefined; } @@ -1126,25 +1547,38 @@ function isInImport(decl: Declaration) { } function isVariableDeclarationInImport(decl: VariableDeclaration) { - return isSourceFile(decl.parent.parent.parent) && - !!decl.initializer && isRequireCall(decl.initializer, /*requireStringLiteralLikeArgument*/ true); + return isSourceFile(decl.parent.parent.parent) + && !!decl.initializer && isRequireCall(decl.initializer, /*requireStringLiteralLikeArgument*/ true); } /** @internal */ export function isTopLevelDeclaration(node: Node): node is TopLevelDeclaration { - return isNonVariableTopLevelDeclaration(node) && isSourceFile(node.parent) || isVariableDeclaration(node) && isSourceFile(node.parent.parent.parent); + return isNonVariableTopLevelDeclaration(node) && isSourceFile(node.parent) + || isVariableDeclaration(node) && isSourceFile(node.parent.parent.parent); } function sourceFileOfTopLevelDeclaration(node: TopLevelDeclaration): Node { return isVariableDeclaration(node) ? node.parent.parent.parent : node.parent; } -function forEachTopLevelDeclarationInBindingName(name: BindingName, cb: (node: TopLevelDeclaration) => T): T | undefined { +function forEachTopLevelDeclarationInBindingName( + name: BindingName, + cb: (node: TopLevelDeclaration) => T, +): T | undefined { switch (name.kind) { case SyntaxKind.Identifier: - return cb(cast(name.parent, (x): x is TopLevelVariableDeclaration | BindingElement => isVariableDeclaration(x) || isBindingElement(x))); + return cb( + cast( + name.parent, + (x): x is TopLevelVariableDeclaration | BindingElement => + isVariableDeclaration(x) || isBindingElement(x), + ), + ); case SyntaxKind.ArrayBindingPattern: case SyntaxKind.ObjectBindingPattern: - return firstDefined(name.elements, em => isOmittedExpression(em) ? undefined : forEachTopLevelDeclarationInBindingName(em.name, cb)); + return firstDefined( + name.elements, + em => isOmittedExpression(em) ? undefined : forEachTopLevelDeclarationInBindingName(em.name, cb), + ); default: return Debug.assertNever(name, `Unexpected name kind ${(name as BindingName).kind}`); } @@ -1165,7 +1599,13 @@ function isNonVariableTopLevelDeclaration(node: Node): node is NonVariableTopLev } } -function moveStatementsToTargetFile(changes: textChanges.ChangeTracker, program: Program, statements: readonly Statement[], targetFile: SourceFile, toMove: ToMove) { +function moveStatementsToTargetFile( + changes: textChanges.ChangeTracker, + program: Program, + statements: readonly Statement[], + targetFile: SourceFile, + toMove: ToMove, +) { const removedExports = new Set(); const targetExports = targetFile.symbol?.exports; if (targetExports) { @@ -1175,21 +1615,35 @@ function moveStatementsToTargetFile(changes: textChanges.ChangeTracker, program: for (const node of toMove.all) { if (isTopLevelDeclarationStatement(node) && hasSyntacticModifier(node, ModifierFlags.Export)) { forEachTopLevelDeclaration(node, declaration => { - const targetDeclarations = canHaveSymbol(declaration) ? targetExports.get(declaration.symbol.escapedName)?.declarations : undefined; + const targetDeclarations = canHaveSymbol(declaration) + ? targetExports.get(declaration.symbol.escapedName)?.declarations : undefined; const exportDeclaration = firstDefined(targetDeclarations, d => - isExportDeclaration(d) ? d : - isExportSpecifier(d) ? tryCast(d.parent.parent, isExportDeclaration) : undefined); + isExportDeclaration(d) ? d + : isExportSpecifier(d) ? tryCast(d.parent.parent, isExportDeclaration) : undefined); if (exportDeclaration && exportDeclaration.moduleSpecifier) { - targetToSourceExports.set(exportDeclaration, (targetToSourceExports.get(exportDeclaration) || new Set()).add(declaration)); + targetToSourceExports.set( + exportDeclaration, + (targetToSourceExports.get(exportDeclaration) || new Set()).add(declaration), + ); } }); } } for (const [exportDeclaration, topLevelDeclarations] of arrayFrom(targetToSourceExports)) { - if (exportDeclaration.exportClause && isNamedExports(exportDeclaration.exportClause) && length(exportDeclaration.exportClause.elements)) { + if ( + exportDeclaration.exportClause && isNamedExports(exportDeclaration.exportClause) + && length(exportDeclaration.exportClause.elements) + ) { const elements = exportDeclaration.exportClause.elements; - const updatedElements = filter(elements, elem => find(skipAlias(elem.symbol, checker).declarations, d => isTopLevelDeclaration(d) && topLevelDeclarations.has(d)) === undefined); + const updatedElements = filter( + elements, + elem => + find( + skipAlias(elem.symbol, checker).declarations, + d => isTopLevelDeclaration(d) && topLevelDeclarations.has(d), + ) === undefined, + ); if (length(updatedElements) === 0) { changes.deleteNode(targetFile, exportDeclaration); @@ -1198,13 +1652,30 @@ function moveStatementsToTargetFile(changes: textChanges.ChangeTracker, program: } if (length(updatedElements) < length(elements)) { - changes.replaceNode(targetFile, exportDeclaration, factory.updateExportDeclaration(exportDeclaration, exportDeclaration.modifiers, exportDeclaration.isTypeOnly, factory.updateNamedExports(exportDeclaration.exportClause, factory.createNodeArray(updatedElements, elements.hasTrailingComma)), exportDeclaration.moduleSpecifier, exportDeclaration.assertClause)); + changes.replaceNode( + targetFile, + exportDeclaration, + factory.updateExportDeclaration( + exportDeclaration, + exportDeclaration.modifiers, + exportDeclaration.isTypeOnly, + factory.updateNamedExports( + exportDeclaration.exportClause, + factory.createNodeArray(updatedElements, elements.hasTrailingComma), + ), + exportDeclaration.moduleSpecifier, + exportDeclaration.assertClause, + ), + ); } } } } - const lastReExport = findLast(targetFile.statements, n => isExportDeclaration(n) && !!n.moduleSpecifier && !removedExports.has(n)); + const lastReExport = findLast( + targetFile.statements, + n => isExportDeclaration(n) && !!n.moduleSpecifier && !removedExports.has(n), + ); if (lastReExport) { changes.insertNodesBefore(targetFile, lastReExport, statements, /*blankLineBetween*/ true); } @@ -1221,7 +1692,10 @@ function getOverloadRangeToMove(sourceFile: SourceFile, statement: Statement) { } const firstDecl = declarations[0]; const lastDecl = declarations[length(declarations) - 1]; - const statementsToMove = mapDefined(declarations, d => getSourceFileOfNode(d) === sourceFile && isStatement(d) ? d : undefined); + const statementsToMove = mapDefined( + declarations, + d => getSourceFileOfNode(d) === sourceFile && isStatement(d) ? d : undefined, + ); const end = findIndex(sourceFile.statements, s => s.end >= lastDecl.end); const start = findIndex(sourceFile.statements, s => s.end >= firstDecl.end); return { toMove: statementsToMove, start, end }; diff --git a/src/services/refactors/moveToNewFile.ts b/src/services/refactors/moveToNewFile.ts index 275ed16bd5a9d..2daa0e5ccbc9f 100644 --- a/src/services/refactors/moveToNewFile.ts +++ b/src/services/refactors/moveToNewFile.ts @@ -68,26 +68,50 @@ registerRefactor(refactorName, { return [{ name: refactorName, description, actions: [moveToNewFileAction] }]; } if (context.preferences.provideRefactorNotApplicableReason) { - return [{ name: refactorName, description, actions: [{ ...moveToNewFileAction, notApplicableReason: getLocaleSpecificMessage(Diagnostics.Selection_is_not_a_valid_statement_or_statements) }] }]; + return [{ + name: refactorName, + description, + actions: [{ + ...moveToNewFileAction, + notApplicableReason: getLocaleSpecificMessage( + Diagnostics.Selection_is_not_a_valid_statement_or_statements, + ), + }], + }]; } return emptyArray; }, getEditsForAction: function getRefactorEditsToMoveToNewFile(context, actionName): RefactorEditInfo { Debug.assert(actionName === refactorName, "Wrong refactor invoked"); const statements = Debug.checkDefined(getStatementsToMove(context)); - const edits = textChanges.ChangeTracker.with(context, t => doChange(context.file, context.program, statements, t, context.host, context.preferences, context)); + const edits = textChanges.ChangeTracker.with( + context, + t => doChange(context.file, context.program, statements, t, context.host, context.preferences, context), + ); return { edits, renameFilename: undefined, renameLocation: undefined }; }, }); -function doChange(oldFile: SourceFile, program: Program, toMove: ToMove, changes: textChanges.ChangeTracker, host: LanguageServiceHost, preferences: UserPreferences, context: RefactorContext): void { +function doChange( + oldFile: SourceFile, + program: Program, + toMove: ToMove, + changes: textChanges.ChangeTracker, + host: LanguageServiceHost, + preferences: UserPreferences, + context: RefactorContext, +): void { const checker = program.getTypeChecker(); const usage = getUsageInfo(oldFile, toMove.all, checker); const newFilename = createNewFileName(oldFile, program, context, host); // If previous file was global, this is easy. - changes.createNewFile(oldFile, newFilename, getNewStatementsAndRemoveFromOldFile(oldFile, usage, changes, toMove, program, host, newFilename, preferences)); + changes.createNewFile( + oldFile, + newFilename, + getNewStatementsAndRemoveFromOldFile(oldFile, usage, changes, toMove, program, host, newFilename, preferences), + ); addNewFileToTsconfig(program, changes, oldFile.fileName, newFilename, hostGetCanonicalFileName(host)); } @@ -104,14 +128,30 @@ function getNewStatementsAndRemoveFromOldFile( ) { const checker = program.getTypeChecker(); const prologueDirectives = takeWhile(oldFile.statements, isPrologueDirective); - if (oldFile.externalModuleIndicator === undefined && oldFile.commonJsModuleIndicator === undefined && usage.oldImportsNeededByTargetFile.size === 0) { + if ( + oldFile.externalModuleIndicator === undefined && oldFile.commonJsModuleIndicator === undefined + && usage.oldImportsNeededByTargetFile.size === 0 + ) { deleteMovedStatements(oldFile, toMove.ranges, changes); return [...prologueDirectives, ...toMove.all]; } - const useEsModuleSyntax = !fileShouldUseJavaScriptRequire(newFilename, program, host, !!oldFile.commonJsModuleIndicator); + const useEsModuleSyntax = !fileShouldUseJavaScriptRequire( + newFilename, + program, + host, + !!oldFile.commonJsModuleIndicator, + ); const quotePreference = getQuotePreference(oldFile, preferences); - const importsFromNewFile = createOldFileImportsFromTargetFile(oldFile, usage.oldFileImportsFromTargetFile, newFilename, program, host, useEsModuleSyntax, quotePreference); + const importsFromNewFile = createOldFileImportsFromTargetFile( + oldFile, + usage.oldFileImportsFromTargetFile, + newFilename, + program, + host, + useEsModuleSyntax, + quotePreference, + ); if (importsFromNewFile) { insertImports(changes, oldFile, importsFromNewFile, /*blankLineBetween*/ true, preferences); } @@ -120,7 +160,17 @@ function getNewStatementsAndRemoveFromOldFile( deleteMovedStatements(oldFile, toMove.ranges, changes); updateImportsInOtherFiles(changes, program, host, oldFile, usage.movedSymbols, newFilename, quotePreference); - const imports = getNewFileImportsAndAddExportInOldFile(oldFile, usage.oldImportsNeededByTargetFile, usage.targetFileImportsFromOldFile, changes, checker, program, host, useEsModuleSyntax, quotePreference); + const imports = getNewFileImportsAndAddExportInOldFile( + oldFile, + usage.oldImportsNeededByTargetFile, + usage.targetFileImportsFromOldFile, + changes, + checker, + program, + host, + useEsModuleSyntax, + quotePreference, + ); const body = addExports(oldFile, toMove.all, usage.oldFileImportsFromTargetFile, useEsModuleSyntax); if (imports.length && body.length) { return [ @@ -152,7 +202,14 @@ function getNewFileImportsAndAddExportInOldFile( const copiedOldImports: SupportedImportStatement[] = []; for (const oldStatement of oldFile.statements) { forEachImportInStatement(oldStatement, i => { - append(copiedOldImports, filterImport(i, moduleSpecifierFromImport(i), name => importsToCopy.has(checker.getSymbolAtLocation(name)!))); + append( + copiedOldImports, + filterImport( + i, + moduleSpecifierFromImport(i), + name => importsToCopy.has(checker.getSymbolAtLocation(name)!), + ), + ); }); } @@ -182,6 +239,18 @@ function getNewFileImportsAndAddExportInOldFile( } }); - append(copiedOldImports, makeImportOrRequire(oldFile, oldFileDefault, oldFileNamedImports, getBaseFileName(oldFile.fileName), program, host, useEsModuleSyntax, quotePreference)); + append( + copiedOldImports, + makeImportOrRequire( + oldFile, + oldFileDefault, + oldFileNamedImports, + getBaseFileName(oldFile.fileName), + program, + host, + useEsModuleSyntax, + quotePreference, + ), + ); return copiedOldImports; } diff --git a/src/services/rename.ts b/src/services/rename.ts index 4083612dae428..cfd7ff2dc820a 100644 --- a/src/services/rename.ts +++ b/src/services/rename.ts @@ -54,7 +54,12 @@ import { } from "./_namespaces/ts"; /** @internal */ -export function getRenameInfo(program: Program, sourceFile: SourceFile, position: number, preferences: UserPreferences): RenameInfo { +export function getRenameInfo( + program: Program, + sourceFile: SourceFile, + position: number, + preferences: UserPreferences, +): RenameInfo { const node = getAdjustedRenameLocation(getTouchingPropertyName(sourceFile, position)); if (nodeIsEligibleForRename(node)) { const renameInfo = getRenameInfoForNode(node, program.getTypeChecker(), sourceFile, program, preferences); @@ -78,7 +83,8 @@ function getRenameInfoForNode( const type = getContextualTypeFromParentOrAncestorTypeNode(node, typeChecker); if ( type && ((type.flags & TypeFlags.StringLiteral) || ( - (type.flags & TypeFlags.Union) && every((type as UnionType).types, type => !!(type.flags & TypeFlags.StringLiteral)) + (type.flags & TypeFlags.Union) + && every((type as UnionType).types, type => !!(type.flags & TypeFlags.StringLiteral)) )) ) { return getRenameInfoSuccess(node.text, node.text, ScriptElementKind.string, "", node, sourceFile); @@ -86,7 +92,14 @@ function getRenameInfoForNode( } else if (isLabelName(node)) { const name = getTextOfNode(node); - return getRenameInfoSuccess(name, name, ScriptElementKind.label, ScriptElementKindModifier.none, node, sourceFile); + return getRenameInfoSuccess( + name, + name, + ScriptElementKind.label, + ScriptElementKindModifier.none, + node, + sourceFile, + ); } return undefined; } @@ -96,11 +109,16 @@ function getRenameInfoForNode( // Disallow rename for elements that are defined in the standard TypeScript library. if (declarations.some(declaration => isDefinedInLibraryFile(program, declaration))) { - return getRenameInfoError(Diagnostics.You_cannot_rename_elements_that_are_defined_in_the_standard_TypeScript_library); + return getRenameInfoError( + Diagnostics.You_cannot_rename_elements_that_are_defined_in_the_standard_TypeScript_library, + ); } // Cannot rename `default` as in `import { default as foo } from "./someModule"; - if (isIdentifier(node) && node.escapedText === "default" && symbol.parent && symbol.parent.flags & SymbolFlags.Module) { + if ( + isIdentifier(node) && node.escapedText === "default" && symbol.parent + && symbol.parent.flags & SymbolFlags.Module + ) { return undefined; } @@ -115,12 +133,20 @@ function getRenameInfoForNode( } const kind = SymbolDisplay.getSymbolKind(typeChecker, symbol, node); - const specifierName = (isImportOrExportSpecifierName(node) || isStringOrNumericLiteralLike(node) && node.parent.kind === SyntaxKind.ComputedPropertyName) + const specifierName = (isImportOrExportSpecifierName(node) + || isStringOrNumericLiteralLike(node) && node.parent.kind === SyntaxKind.ComputedPropertyName) ? stripQuotes(getTextOfIdentifierOrLiteral(node)) : undefined; const displayName = specifierName || typeChecker.symbolToString(symbol); const fullDisplayName = specifierName || typeChecker.getFullyQualifiedName(symbol); - return getRenameInfoSuccess(displayName, fullDisplayName, kind, SymbolDisplay.getSymbolModifiers(typeChecker, symbol), node, sourceFile); + return getRenameInfoSuccess( + displayName, + fullDisplayName, + kind, + SymbolDisplay.getSymbolModifiers(typeChecker, symbol), + node, + sourceFile, + ); } function isDefinedInLibraryFile(program: Program, declaration: Node) { @@ -177,19 +203,27 @@ function getPackagePathComponents(filePath: Path): string[] | undefined { return components.slice(0, nodeModulesIdx + 2); } -function getRenameInfoForModule(node: StringLiteralLike, sourceFile: SourceFile, moduleSymbol: Symbol): RenameInfo | undefined { +function getRenameInfoForModule( + node: StringLiteralLike, + sourceFile: SourceFile, + moduleSymbol: Symbol, +): RenameInfo | undefined { if (!isExternalModuleNameRelative(node.text)) { return getRenameInfoError(Diagnostics.You_cannot_rename_a_module_via_a_global_import); } const moduleSourceFile = moduleSymbol.declarations && find(moduleSymbol.declarations, isSourceFile); if (!moduleSourceFile) return undefined; - const withoutIndex = endsWith(node.text, "/index") || endsWith(node.text, "/index.js") ? undefined : tryRemoveSuffix(removeFileExtension(moduleSourceFile.fileName), "/index"); + const withoutIndex = endsWith(node.text, "/index") || endsWith(node.text, "/index.js") ? undefined + : tryRemoveSuffix(removeFileExtension(moduleSourceFile.fileName), "/index"); const name = withoutIndex === undefined ? moduleSourceFile.fileName : withoutIndex; const kind = withoutIndex === undefined ? ScriptElementKind.moduleElement : ScriptElementKind.directory; const indexAfterLastSlash = node.text.lastIndexOf("/") + 1; // Span should only be the last component of the path. + 1 to account for the quote character. - const triggerSpan = createTextSpan(node.getStart(sourceFile) + 1 + indexAfterLastSlash, node.text.length - indexAfterLastSlash); + const triggerSpan = createTextSpan( + node.getStart(sourceFile) + 1 + indexAfterLastSlash, + node.text.length - indexAfterLastSlash, + ); return { canRename: true, fileToRename: name, @@ -201,7 +235,14 @@ function getRenameInfoForModule(node: StringLiteralLike, sourceFile: SourceFile, }; } -function getRenameInfoSuccess(displayName: string, fullDisplayName: string, kind: ScriptElementKind, kindModifiers: string, node: Node, sourceFile: SourceFile): RenameInfoSuccess { +function getRenameInfoSuccess( + displayName: string, + fullDisplayName: string, + kind: ScriptElementKind, + kindModifiers: string, + node: Node, + sourceFile: SourceFile, +): RenameInfoSuccess { return { canRename: true, fileToRename: undefined, diff --git a/src/services/services.ts b/src/services/services.ts index d4fbbc3407b64..ed0dbcb8c8b96 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -334,11 +334,16 @@ import * as classifier2020 from "./classifier2020"; /** The version of the language service API */ export const servicesVersion = "0.8"; -function createNode(kind: TKind, pos: number, end: number, parent: Node): NodeObject | TokenObject | IdentifierObject | PrivateIdentifierObject { - const node = isNodeKind(kind) ? new NodeObject(kind, pos, end) : - kind === SyntaxKind.Identifier ? new IdentifierObject(SyntaxKind.Identifier, pos, end) : - kind === SyntaxKind.PrivateIdentifier ? new PrivateIdentifierObject(SyntaxKind.PrivateIdentifier, pos, end) : - new TokenObject(kind, pos, end); +function createNode( + kind: TKind, + pos: number, + end: number, + parent: Node, +): NodeObject | TokenObject | IdentifierObject | PrivateIdentifierObject { + const node = isNodeKind(kind) ? new NodeObject(kind, pos, end) + : kind === SyntaxKind.Identifier ? new IdentifierObject(SyntaxKind.Identifier, pos, end) + : kind === SyntaxKind.PrivateIdentifier ? new PrivateIdentifierObject(SyntaxKind.PrivateIdentifier, pos, end) + : new TokenObject(kind, pos, end); node.parent = parent; node.flags = parent.flags & NodeFlags.ContextFlags; return node; @@ -369,7 +374,10 @@ class NodeObject implements Node { private assertHasRealPosition(message?: string) { // eslint-disable-next-line local/debug-assert - Debug.assert(!positionIsSynthesized(this.pos) && !positionIsSynthesized(this.end), message || "Node must have a real position for this operation"); + Debug.assert( + !positionIsSynthesized(this.pos) && !positionIsSynthesized(this.end), + message || "Node must have a real position for this operation", + ); } public getSourceFile(): SourceFile { @@ -428,7 +436,9 @@ class NodeObject implements Node { } public getChildren(sourceFile?: SourceFileLike): Node[] { - this.assertHasRealPosition("Node without a real position cannot be scanned and thus has no token nodes - use forEachChild and collect the result if that's fine"); + this.assertHasRealPosition( + "Node without a real position cannot be scanned and thus has no token nodes - use forEachChild and collect the result if that's fine", + ); return this._children || (this._children = createChildren(this, sourceFile)); } @@ -439,10 +449,13 @@ class NodeObject implements Node { return undefined; } - const child = find(children, kid => kid.kind < SyntaxKind.FirstJSDocNode || kid.kind > SyntaxKind.LastJSDocNode)!; - return child.kind < SyntaxKind.FirstNode ? - child : - child.getFirstToken(sourceFile); + const child = find( + children, + kid => kid.kind < SyntaxKind.FirstJSDocNode || kid.kind > SyntaxKind.LastJSDocNode, + )!; + return child.kind < SyntaxKind.FirstNode + ? child + : child.getFirstToken(sourceFile); } public getLastToken(sourceFile?: SourceFileLike): Node | undefined { @@ -604,7 +617,8 @@ class TokenOrIdentifierObject implements Node { } public getChildren(): Node[] { - return this.kind === SyntaxKind.EndOfFileToken ? (this as Node as EndOfFileToken).jsDoc || emptyArray : emptyArray; + return this.kind === SyntaxKind.EndOfFileToken ? (this as Node as EndOfFileToken).jsDoc || emptyArray + : emptyArray; } public getFirstToken(): Node | undefined { @@ -669,7 +683,10 @@ class SymbolObject implements Symbol { if (!this.documentationComment) { this.documentationComment = emptyArray; // Set temporarily to avoid an infinite loop finding inherited docs - if (!this.declarations && isTransientSymbol(this) && this.links.target && isTransientSymbol(this.links.target) && this.links.target.links.tupleLabelDeclaration) { + if ( + !this.declarations && isTransientSymbol(this) && this.links.target + && isTransientSymbol(this.links.target) && this.links.target.links.tupleLabelDeclaration + ) { const labelDecl = this.links.target.links.tupleLabelDeclaration; this.documentationComment = getDocumentationComment([labelDecl], checker); } @@ -680,11 +697,17 @@ class SymbolObject implements Symbol { return this.documentationComment; } - getContextualDocumentationComment(context: Node | undefined, checker: TypeChecker | undefined): SymbolDisplayPart[] { + getContextualDocumentationComment( + context: Node | undefined, + checker: TypeChecker | undefined, + ): SymbolDisplayPart[] { if (context) { if (isGetAccessor(context)) { if (!this.contextualGetAccessorDocumentationComment) { - this.contextualGetAccessorDocumentationComment = getDocumentationComment(filter(this.declarations, isGetAccessor), checker); + this.contextualGetAccessorDocumentationComment = getDocumentationComment( + filter(this.declarations, isGetAccessor), + checker, + ); } if (length(this.contextualGetAccessorDocumentationComment)) { return this.contextualGetAccessorDocumentationComment; @@ -692,7 +715,10 @@ class SymbolObject implements Symbol { } if (isSetAccessor(context)) { if (!this.contextualSetAccessorDocumentationComment) { - this.contextualSetAccessorDocumentationComment = getDocumentationComment(filter(this.declarations, isSetAccessor), checker); + this.contextualSetAccessorDocumentationComment = getDocumentationComment( + filter(this.declarations, isSetAccessor), + checker, + ); } if (length(this.contextualSetAccessorDocumentationComment)) { return this.contextualSetAccessorDocumentationComment; @@ -714,7 +740,10 @@ class SymbolObject implements Symbol { if (context) { if (isGetAccessor(context)) { if (!this.contextualGetAccessorTags) { - this.contextualGetAccessorTags = getJsDocTagsOfDeclarations(filter(this.declarations, isGetAccessor), checker); + this.contextualGetAccessorTags = getJsDocTagsOfDeclarations( + filter(this.declarations, isGetAccessor), + checker, + ); } if (length(this.contextualGetAccessorTags)) { return this.contextualGetAccessorTags; @@ -722,7 +751,10 @@ class SymbolObject implements Symbol { } if (isSetAccessor(context)) { if (!this.contextualSetAccessorTags) { - this.contextualSetAccessorTags = getJsDocTagsOfDeclarations(filter(this.declarations, isSetAccessor), checker); + this.contextualSetAccessorTags = getJsDocTagsOfDeclarations( + filter(this.declarations, isSetAccessor), + checker, + ); } if (length(this.contextualSetAccessorTags)) { return this.contextualSetAccessorTags; @@ -926,11 +958,16 @@ class SignatureObject implements Signature { } getDocumentationComment(): SymbolDisplayPart[] { - return this.documentationComment || (this.documentationComment = getDocumentationComment(singleElementArray(this.declaration), this.checker)); + return this.documentationComment + || (this.documentationComment = getDocumentationComment( + singleElementArray(this.declaration), + this.checker, + )); } getJsDocTags(): JSDocTagInfo[] { - return this.jsDocTags || (this.jsDocTags = getJsDocTagsOfDeclarations(singleElementArray(this.declaration), this.checker)); + return this.jsDocTags + || (this.jsDocTags = getJsDocTagsOfDeclarations(singleElementArray(this.declaration), this.checker)); } } @@ -943,7 +980,10 @@ function hasJSDocInheritDocTag(node: Node) { return getJSDocTags(node).some(tag => tag.tagName.text === "inheritDoc" || tag.tagName.text === "inheritdoc"); } -function getJsDocTagsOfDeclarations(declarations: Declaration[] | undefined, checker: TypeChecker | undefined): JSDocTagInfo[] { +function getJsDocTagsOfDeclarations( + declarations: Declaration[] | undefined, + checker: TypeChecker | undefined, +): JSDocTagInfo[] { if (!declarations) return emptyArray; let tags = JsDoc.getJsDocTagsFromDeclarations(declarations, checker); @@ -967,7 +1007,10 @@ function getJsDocTagsOfDeclarations(declarations: Declaration[] | undefined, che return tags; } -function getDocumentationComment(declarations: readonly Declaration[] | undefined, checker: TypeChecker | undefined): SymbolDisplayPart[] { +function getDocumentationComment( + declarations: readonly Declaration[] | undefined, + checker: TypeChecker | undefined, +): SymbolDisplayPart[] { if (!declarations) return emptyArray; let doc = JsDoc.getJsDocCommentsFromDeclarations(declarations, checker); @@ -984,14 +1027,21 @@ function getDocumentationComment(declarations: readonly Declaration[] | undefine } }); // TODO: GH#16312 Return a ReadonlyArray, avoid copying inheritedDocs - if (inheritedDocs) doc = doc.length === 0 ? inheritedDocs.slice() : inheritedDocs.concat(lineBreakPart(), doc); + if (inheritedDocs) { + doc = doc.length === 0 ? inheritedDocs.slice() : inheritedDocs.concat(lineBreakPart(), doc); + } } } return doc; } -function findBaseOfDeclaration(checker: TypeChecker, declaration: Declaration, cb: (symbol: Symbol) => T[] | undefined): T[] | undefined { - const classOrInterfaceDeclaration = declaration.parent?.kind === SyntaxKind.Constructor ? declaration.parent.parent : declaration.parent; +function findBaseOfDeclaration( + checker: TypeChecker, + declaration: Declaration, + cb: (symbol: Symbol) => T[] | undefined, +): T[] | undefined { + const classOrInterfaceDeclaration = declaration.parent?.kind === SyntaxKind.Constructor ? declaration.parent.parent + : declaration.parent; if (!classOrInterfaceDeclaration) return; const isStaticMember = hasStaticModifier(declaration); @@ -1044,7 +1094,9 @@ class SourceFileObject extends NodeObject implements SourceFile { public identifiers!: Map; public nameTable: Map<__String, number> | undefined; public resolvedModules: ModeAwareCache | undefined; - public resolvedTypeReferenceDirectiveNames!: ModeAwareCache; + public resolvedTypeReferenceDirectiveNames!: ModeAwareCache< + ResolvedTypeReferenceDirectiveWithFailedLookupLocations + >; public imports!: readonly StringLiteralLike[]; public moduleAugmentations!: StringLiteral[]; private namedDeclarations: Map | undefined; @@ -1125,8 +1177,10 @@ class SourceFileObject extends NodeObject implements SourceFile { function getDeclarationName(declaration: Declaration) { const name = getNonAssignedNameOfDeclaration(declaration); - return name && (isComputedPropertyName(name) && isPropertyAccessExpression(name.expression) ? name.expression.name.text - : isPropertyName(name) ? getNameFromPropertyName(name) : undefined); + return name + && (isComputedPropertyName(name) && isPropertyAccessExpression(name.expression) + ? name.expression.name.text + : isPropertyName(name) ? getNameFromPropertyName(name) : undefined); } function visit(node: Node): void { @@ -1143,7 +1197,10 @@ class SourceFileObject extends NodeObject implements SourceFile { const lastDeclaration = lastOrUndefined(declarations); // Check whether this declaration belongs to an "overload group". - if (lastDeclaration && functionDeclaration.parent === lastDeclaration.parent && functionDeclaration.symbol === lastDeclaration.symbol) { + if ( + lastDeclaration && functionDeclaration.parent === lastDeclaration.parent + && functionDeclaration.symbol === lastDeclaration.symbol + ) { // Overwrite the last declaration if it was an overload // and this one is an implementation. if (functionDeclaration.body && !(lastDeclaration as FunctionLikeDeclaration).body) { @@ -1356,14 +1413,25 @@ class SyntaxTreeCache { const options: CreateSourceFileOptions = { languageVersion: ScriptTarget.Latest, impliedNodeFormat: getImpliedNodeFormatForFile( - toPath(fileName, this.host.getCurrentDirectory(), this.host.getCompilerHost?.()?.getCanonicalFileName || hostGetCanonicalFileName(this.host)), + toPath( + fileName, + this.host.getCurrentDirectory(), + this.host.getCompilerHost?.()?.getCanonicalFileName || hostGetCanonicalFileName(this.host), + ), this.host.getCompilerHost?.()?.getModuleResolutionCache?.()?.getPackageJsonInfoCache(), this.host, this.host.getCompilationSettings(), ), setExternalModuleIndicator: getSetExternalModuleIndicator(this.host.getCompilationSettings()), }; - sourceFile = createLanguageServiceSourceFile(fileName, scriptSnapshot, options, version, /*setNodeParents*/ true, scriptKind); + sourceFile = createLanguageServiceSourceFile( + fileName, + scriptSnapshot, + options, + version, + /*setNodeParents*/ true, + scriptKind, + ); } else if (this.currentFileVersion !== version) { // This is the same file, just a newer version. Incrementally parse the file. @@ -1388,13 +1456,32 @@ function setSourceFileFields(sourceFile: SourceFile, scriptSnapshot: IScriptSnap sourceFile.scriptSnapshot = scriptSnapshot; } -export function createLanguageServiceSourceFile(fileName: string, scriptSnapshot: IScriptSnapshot, scriptTargetOrOptions: ScriptTarget | CreateSourceFileOptions, version: string, setNodeParents: boolean, scriptKind?: ScriptKind): SourceFile { - const sourceFile = createSourceFile(fileName, getSnapshotText(scriptSnapshot), scriptTargetOrOptions, setNodeParents, scriptKind); +export function createLanguageServiceSourceFile( + fileName: string, + scriptSnapshot: IScriptSnapshot, + scriptTargetOrOptions: ScriptTarget | CreateSourceFileOptions, + version: string, + setNodeParents: boolean, + scriptKind?: ScriptKind, +): SourceFile { + const sourceFile = createSourceFile( + fileName, + getSnapshotText(scriptSnapshot), + scriptTargetOrOptions, + setNodeParents, + scriptKind, + ); setSourceFileFields(sourceFile, scriptSnapshot, version); return sourceFile; } -export function updateLanguageServiceSourceFile(sourceFile: SourceFile, scriptSnapshot: IScriptSnapshot, version: string, textChangeRange: TextChangeRange | undefined, aggressiveChecks?: boolean): SourceFile { +export function updateLanguageServiceSourceFile( + sourceFile: SourceFile, + scriptSnapshot: IScriptSnapshot, + version: string, + textChangeRange: TextChangeRange | undefined, + aggressiveChecks?: boolean, +): SourceFile { // If we were given a text change range, and our version or open-ness changed, then // incrementally parse this file. if (textChangeRange) { @@ -1417,7 +1504,10 @@ export function updateLanguageServiceSourceFile(sourceFile: SourceFile, scriptSn } else { // it was actual edit, fetch the fragment of new text that correspond to new span - const changedText = scriptSnapshot.getText(textChangeRange.span.start, textChangeRange.span.start + textChangeRange.newLength); + const changedText = scriptSnapshot.getText( + textChangeRange.span.start, + textChangeRange.span.start + textChangeRange.newLength, + ); // combine prefix, changed text and suffix newText = prefix && suffix ? prefix + changedText + suffix @@ -1451,7 +1541,14 @@ export function updateLanguageServiceSourceFile(sourceFile: SourceFile, scriptSn setExternalModuleIndicator: sourceFile.setExternalModuleIndicator, }; // Otherwise, just create a new source file. - return createLanguageServiceSourceFile(sourceFile.fileName, scriptSnapshot, options, version, /*setNodeParents*/ true, sourceFile.scriptKind); + return createLanguageServiceSourceFile( + sourceFile.fileName, + scriptSnapshot, + options, + version, + /*setNodeParents*/ true, + sourceFile.scriptKind, + ); } const NoopCancellationToken: CancellationToken = { @@ -1551,7 +1648,10 @@ const invalidOperationsInSyntacticMode: readonly (keyof LanguageService)[] = [ ]; export function createLanguageService( host: LanguageServiceHost, - documentRegistry: DocumentRegistry = createDocumentRegistry(host.useCaseSensitiveFileNames && host.useCaseSensitiveFileNames(), host.getCurrentDirectory()), + documentRegistry: DocumentRegistry = createDocumentRegistry( + host.useCaseSensitiveFileNames && host.useCaseSensitiveFileNames(), + host.getCurrentDirectory(), + ), syntaxOnlyOrLanguageServiceMode?: boolean | LanguageServiceMode, ): LanguageService { let languageServiceMode: LanguageServiceMode; @@ -1560,7 +1660,8 @@ export function createLanguageService( } else if (typeof syntaxOnlyOrLanguageServiceMode === "boolean") { // languageServiceMode = SyntaxOnly - languageServiceMode = syntaxOnlyOrLanguageServiceMode ? LanguageServiceMode.Syntactic : LanguageServiceMode.Semantic; + languageServiceMode = syntaxOnlyOrLanguageServiceMode ? LanguageServiceMode.Syntactic + : LanguageServiceMode.Semantic; } else { languageServiceMode = syntaxOnlyOrLanguageServiceMode; @@ -1669,8 +1770,17 @@ export function createLanguageService( getDirectories: path => { return host.getDirectories ? host.getDirectories(path) : []; }, - readDirectory: (path: string, extensions?: readonly string[], exclude?: readonly string[], include?: readonly string[], depth?: number) => { - Debug.checkDefined(host.readDirectory, "'LanguageServiceHost.readDirectory' must be implemented to correctly process 'projectReferences'"); + readDirectory: ( + path: string, + extensions?: readonly string[], + exclude?: readonly string[], + include?: readonly string[], + depth?: number, + ) => { + Debug.checkDefined( + host.readDirectory, + "'LanguageServiceHost.readDirectory' must be implemented to correctly process 'projectReferences'", + ); return host.readDirectory!(path, extensions, exclude, include, depth); }, onReleaseOldSourceFile, @@ -1721,7 +1831,20 @@ export function createLanguageService( let releasedScriptKinds: Set | undefined = new Set(); // If the program is already up-to-date, we can reuse it - if (isProgramUptoDate(program, rootFileNames, newSettings, (_path, fileName) => host.getScriptVersion(fileName), fileName => compilerHost!.fileExists(fileName), hasInvalidatedResolutions, hasInvalidatedLibResolutions, hasChangedAutomaticTypeDirectiveNames, getParsedCommandLine, projectReferences)) { + if ( + isProgramUptoDate( + program, + rootFileNames, + newSettings, + (_path, fileName) => host.getScriptVersion(fileName), + fileName => compilerHost!.fileExists(fileName), + hasInvalidatedResolutions, + hasInvalidatedLibResolutions, + hasChangedAutomaticTypeDirectiveNames, + getParsedCommandLine, + projectReferences, + ) + ) { compilerHost = undefined; parsedCommandLines = undefined; releasedScriptKinds = undefined; @@ -1764,14 +1887,16 @@ export function createLanguageService( const existing = parsedCommandLines?.get(path); if (existing !== undefined) return existing || undefined; - const result = host.getParsedCommandLine ? - host.getParsedCommandLine(fileName) : - getParsedCommandLineOfConfigFileUsingSourceFile(fileName); + const result = host.getParsedCommandLine + ? host.getParsedCommandLine(fileName) + : getParsedCommandLineOfConfigFileUsingSourceFile(fileName); (parsedCommandLines ||= new Map()).set(path, result || false); return result; } - function getParsedCommandLineOfConfigFileUsingSourceFile(configFileName: string): ParsedCommandLine | undefined { + function getParsedCommandLineOfConfigFileUsingSourceFile( + configFileName: string, + ): ParsedCommandLine | undefined { const result = getOrCreateSourceFile(configFileName, ScriptTarget.JSON) as JsonSourceFile | undefined; if (!result) return undefined; result.path = toPath(configFileName, currentDirectory, getCanonicalFileName); @@ -1786,7 +1911,11 @@ export function createLanguageService( ); } - function onReleaseParsedCommandLine(configFileName: string, oldResolvedRef: ResolvedProjectReference | undefined, oldOptions: CompilerOptions) { + function onReleaseParsedCommandLine( + configFileName: string, + oldResolvedRef: ResolvedProjectReference | undefined, + oldOptions: CompilerOptions, + ) { if (host.getParsedCommandLine) { host.onReleaseParsedCommandLine?.(configFileName, oldResolvedRef, oldOptions); } @@ -1799,15 +1928,40 @@ export function createLanguageService( // not part of the new program. function onReleaseOldSourceFile(oldSourceFile: SourceFile, oldOptions: CompilerOptions) { const oldSettingsKey = documentRegistry.getKeyForCompilationSettings(oldOptions); - documentRegistry.releaseDocumentWithKey(oldSourceFile.resolvedPath, oldSettingsKey, oldSourceFile.scriptKind, oldSourceFile.impliedNodeFormat); + documentRegistry.releaseDocumentWithKey( + oldSourceFile.resolvedPath, + oldSettingsKey, + oldSourceFile.scriptKind, + oldSourceFile.impliedNodeFormat, + ); } - function getOrCreateSourceFile(fileName: string, languageVersionOrOptions: ScriptTarget | CreateSourceFileOptions, onError?: (message: string) => void, shouldCreateNewSourceFile?: boolean): SourceFile | undefined { - return getOrCreateSourceFileByPath(fileName, toPath(fileName, currentDirectory, getCanonicalFileName), languageVersionOrOptions, onError, shouldCreateNewSourceFile); + function getOrCreateSourceFile( + fileName: string, + languageVersionOrOptions: ScriptTarget | CreateSourceFileOptions, + onError?: (message: string) => void, + shouldCreateNewSourceFile?: boolean, + ): SourceFile | undefined { + return getOrCreateSourceFileByPath( + fileName, + toPath(fileName, currentDirectory, getCanonicalFileName), + languageVersionOrOptions, + onError, + shouldCreateNewSourceFile, + ); } - function getOrCreateSourceFileByPath(fileName: string, path: Path, languageVersionOrOptions: ScriptTarget | CreateSourceFileOptions, _onError?: (message: string) => void, shouldCreateNewSourceFile?: boolean): SourceFile | undefined { - Debug.assert(compilerHost, "getOrCreateSourceFileByPath called after typical CompilerHost lifetime, check the callstack something with a reference to an old host."); + function getOrCreateSourceFileByPath( + fileName: string, + path: Path, + languageVersionOrOptions: ScriptTarget | CreateSourceFileOptions, + _onError?: (message: string) => void, + shouldCreateNewSourceFile?: boolean, + ): SourceFile | undefined { + Debug.assert( + compilerHost, + "getOrCreateSourceFileByPath called after typical CompilerHost lifetime, check the callstack something with a reference to an old host.", + ); // The program is asking for this file, check first if the host can locate it. // If the host can not locate the file, then it does not exist. return undefined // to the program to allow reporting of errors for missing files. @@ -1851,12 +2005,28 @@ export function createLanguageService( // We do not support the scenario where a host can modify a registered // file's script kind, i.e. in one project some file is treated as ".ts" // and in another as ".js" - if (scriptKind === oldSourceFile.scriptKind || releasedScriptKinds!.has(oldSourceFile.resolvedPath)) { - return documentRegistry.updateDocumentWithKey(fileName, path, host, documentRegistryBucketKey, scriptSnapshot, scriptVersion, scriptKind, languageVersionOrOptions); + if ( + scriptKind === oldSourceFile.scriptKind || releasedScriptKinds!.has(oldSourceFile.resolvedPath) + ) { + return documentRegistry.updateDocumentWithKey( + fileName, + path, + host, + documentRegistryBucketKey, + scriptSnapshot, + scriptVersion, + scriptKind, + languageVersionOrOptions, + ); } else { // Release old source file and fall through to aquire new file with new script kind - documentRegistry.releaseDocumentWithKey(oldSourceFile.resolvedPath, documentRegistry.getKeyForCompilationSettings(program.getCompilerOptions()), oldSourceFile.scriptKind, oldSourceFile.impliedNodeFormat); + documentRegistry.releaseDocumentWithKey( + oldSourceFile.resolvedPath, + documentRegistry.getKeyForCompilationSettings(program.getCompilerOptions()), + oldSourceFile.scriptKind, + oldSourceFile.impliedNodeFormat, + ); releasedScriptKinds!.add(oldSourceFile.resolvedPath); } } @@ -1865,7 +2035,16 @@ export function createLanguageService( } // Could not find this file in the old program, create a new SourceFile for it. - return documentRegistry.acquireDocumentWithKey(fileName, path, host, documentRegistryBucketKey, scriptSnapshot, scriptVersion, scriptKind, languageVersionOrOptions); + return documentRegistry.acquireDocumentWithKey( + fileName, + path, + host, + documentRegistryBucketKey, + scriptSnapshot, + scriptVersion, + scriptKind, + languageVersionOrOptions, + ); } } @@ -1885,7 +2064,10 @@ export function createLanguageService( return host.getPackageJsonAutoImportProvider?.(); } - function updateIsDefinitionOfReferencedSymbols(referencedSymbols: readonly ReferencedSymbol[], knownSymbolSpans: Set): boolean { + function updateIsDefinitionOfReferencedSymbols( + referencedSymbols: readonly ReferencedSymbol[], + knownSymbolSpans: Set, + ): boolean { const checker = program.getTypeChecker(); const symbol = getSymbolForProgram(); @@ -1936,7 +2118,9 @@ export function createLanguageService( const sourceFile = program.getSourceFile(docSpan.fileName); if (!sourceFile) return undefined; const rawNode = getTouchingPropertyName(sourceFile, docSpan.textSpan.start); - const adjustedNode = FindAllReferences.Core.getAdjustedNode(rawNode, { use: FindAllReferences.FindReferencesUse.References }); + const adjustedNode = FindAllReferences.Core.getAdjustedNode(rawNode, { + use: FindAllReferences.FindReferencesUse.References, + }); return adjustedNode; } } @@ -1945,7 +2129,10 @@ export function createLanguageService( if (program) { // Use paths to ensure we are using correct key and paths as document registry could be created with different current directory than host const key = documentRegistry.getKeyForCompilationSettings(program.getCompilerOptions()); - forEach(program.getSourceFiles(), f => documentRegistry.releaseDocumentWithKey(f.resolvedPath, key, f.scriptKind, f.impliedNodeFormat)); + forEach( + program.getSourceFiles(), + f => documentRegistry.releaseDocumentWithKey(f.resolvedPath, key, f.scriptKind, f.impliedNodeFormat), + ); program = undefined!; // TODO: GH#18217 } } @@ -1991,15 +2178,25 @@ export function createLanguageService( function getCompilerOptionsDiagnostics() { synchronizeHostData(); - return [...program.getOptionsDiagnostics(cancellationToken), ...program.getGlobalDiagnostics(cancellationToken)]; + return [ + ...program.getOptionsDiagnostics(cancellationToken), + ...program.getGlobalDiagnostics(cancellationToken), + ]; } - function getCompletionsAtPosition(fileName: string, position: number, options: GetCompletionsAtPositionOptions = emptyOptions, formattingSettings?: FormatCodeSettings): CompletionInfo | undefined { + function getCompletionsAtPosition( + fileName: string, + position: number, + options: GetCompletionsAtPositionOptions = emptyOptions, + formattingSettings?: FormatCodeSettings, + ): CompletionInfo | undefined { // Convert from deprecated options names to new names const fullPreferences: UserPreferences = { ...identity(options), // avoid excess property check - includeCompletionsForModuleExports: options.includeCompletionsForModuleExports || options.includeExternalModuleExports, - includeCompletionsWithInsertText: options.includeCompletionsWithInsertText || options.includeInsertTextCompletions, + includeCompletionsForModuleExports: options.includeCompletionsForModuleExports + || options.includeExternalModuleExports, + includeCompletionsWithInsertText: options.includeCompletionsWithInsertText + || options.includeInsertTextCompletions, }; synchronizeHostData(); return Completions.getCompletionsAtPosition( @@ -2017,7 +2214,15 @@ export function createLanguageService( ); } - function getCompletionEntryDetails(fileName: string, position: number, name: string, formattingOptions: FormatCodeSettings | undefined, source: string | undefined, preferences: UserPreferences = emptyOptions, data?: CompletionEntryData): CompletionEntryDetails | undefined { + function getCompletionEntryDetails( + fileName: string, + position: number, + name: string, + formattingOptions: FormatCodeSettings | undefined, + source: string | undefined, + preferences: UserPreferences = emptyOptions, + data?: CompletionEntryData, + ): CompletionEntryDetails | undefined { synchronizeHostData(); return Completions.getCompletionEntryDetails( program, @@ -2032,9 +2237,23 @@ export function createLanguageService( ); } - function getCompletionEntrySymbol(fileName: string, position: number, name: string, source?: string, preferences: UserPreferences = emptyOptions): Symbol | undefined { + function getCompletionEntrySymbol( + fileName: string, + position: number, + name: string, + source?: string, + preferences: UserPreferences = emptyOptions, + ): Symbol | undefined { synchronizeHostData(); - return Completions.getCompletionEntrySymbol(program, log, getValidSourceFile(fileName), position, { name, source }, host, preferences); + return Completions.getCompletionEntrySymbol( + program, + log, + getValidSourceFile(fileName), + position, + { name, source }, + host, + preferences, + ); } function getQuickInfoAtPosition(fileName: string, position: number): QuickInfo | undefined { @@ -2052,18 +2271,32 @@ export function createLanguageService( const symbol = getSymbolAtLocationForQuickInfo(nodeForQuickInfo, typeChecker); if (!symbol || typeChecker.isUnknownSymbol(symbol)) { - const type = shouldGetType(sourceFile, nodeForQuickInfo, position) ? typeChecker.getTypeAtLocation(nodeForQuickInfo) : undefined; + const type = shouldGetType(sourceFile, nodeForQuickInfo, position) + ? typeChecker.getTypeAtLocation(nodeForQuickInfo) : undefined; return type && { kind: ScriptElementKind.unknown, kindModifiers: ScriptElementKindModifier.none, textSpan: createTextSpanFromNode(nodeForQuickInfo, sourceFile), - displayParts: typeChecker.runWithCancellationToken(cancellationToken, typeChecker => typeToDisplayParts(typeChecker, type, getContainerNode(nodeForQuickInfo))), + displayParts: typeChecker.runWithCancellationToken( + cancellationToken, + typeChecker => typeToDisplayParts(typeChecker, type, getContainerNode(nodeForQuickInfo)), + ), documentation: type.symbol ? type.symbol.getDocumentationComment(typeChecker) : undefined, tags: type.symbol ? type.symbol.getJsDocTags(typeChecker) : undefined, }; } - const { symbolKind, displayParts, documentation, tags } = typeChecker.runWithCancellationToken(cancellationToken, typeChecker => SymbolDisplay.getSymbolDisplayPartsDocumentationAndSymbolKind(typeChecker, symbol, sourceFile, getContainerNode(nodeForQuickInfo), nodeForQuickInfo)); + const { symbolKind, displayParts, documentation, tags } = typeChecker.runWithCancellationToken( + cancellationToken, + typeChecker => + SymbolDisplay.getSymbolDisplayPartsDocumentationAndSymbolKind( + typeChecker, + symbol, + sourceFile, + getContainerNode(nodeForQuickInfo), + nodeForQuickInfo, + ), + ); return { kind: symbolKind, kindModifiers: SymbolDisplay.getSymbolModifiers(typeChecker, symbol), @@ -2111,9 +2344,20 @@ export function createLanguageService( } /// Goto definition - function getDefinitionAtPosition(fileName: string, position: number, searchOtherFilesOnly?: boolean, stopAtAlias?: boolean): readonly DefinitionInfo[] | undefined { + function getDefinitionAtPosition( + fileName: string, + position: number, + searchOtherFilesOnly?: boolean, + stopAtAlias?: boolean, + ): readonly DefinitionInfo[] | undefined { synchronizeHostData(); - return GoToDefinition.getDefinitionAtPosition(program, getValidSourceFile(fileName), position, searchOtherFilesOnly, stopAtAlias); + return GoToDefinition.getDefinitionAtPosition( + program, + getValidSourceFile(fileName), + position, + searchOtherFilesOnly, + stopAtAlias, + ); } function getDefinitionAndBoundSpan(fileName: string, position: number): DefinitionInfoAndBoundSpan | undefined { @@ -2123,33 +2367,62 @@ export function createLanguageService( function getTypeDefinitionAtPosition(fileName: string, position: number): readonly DefinitionInfo[] | undefined { synchronizeHostData(); - return GoToDefinition.getTypeDefinitionAtPosition(program.getTypeChecker(), getValidSourceFile(fileName), position); + return GoToDefinition.getTypeDefinitionAtPosition( + program.getTypeChecker(), + getValidSourceFile(fileName), + position, + ); } /// Goto implementation function getImplementationAtPosition(fileName: string, position: number): ImplementationLocation[] | undefined { synchronizeHostData(); - return FindAllReferences.getImplementationsAtPosition(program, cancellationToken, program.getSourceFiles(), getValidSourceFile(fileName), position); + return FindAllReferences.getImplementationsAtPosition( + program, + cancellationToken, + program.getSourceFiles(), + getValidSourceFile(fileName), + position, + ); } /// References and Occurrences - function getDocumentHighlights(fileName: string, position: number, filesToSearch: readonly string[]): DocumentHighlights[] | undefined { + function getDocumentHighlights( + fileName: string, + position: number, + filesToSearch: readonly string[], + ): DocumentHighlights[] | undefined { const normalizedFileName = normalizePath(fileName); Debug.assert(filesToSearch.some(f => normalizePath(f) === normalizedFileName)); synchronizeHostData(); const sourceFilesToSearch = mapDefined(filesToSearch, fileName => program.getSourceFile(fileName)); const sourceFile = getValidSourceFile(fileName); - return DocumentHighlights.getDocumentHighlights(program, cancellationToken, sourceFile, position, sourceFilesToSearch); + return DocumentHighlights.getDocumentHighlights( + program, + cancellationToken, + sourceFile, + position, + sourceFilesToSearch, + ); } - function findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean, preferences?: UserPreferences | boolean): RenameLocation[] | undefined { + function findRenameLocations( + fileName: string, + position: number, + findInStrings: boolean, + findInComments: boolean, + preferences?: UserPreferences | boolean, + ): RenameLocation[] | undefined { synchronizeHostData(); const sourceFile = getValidSourceFile(fileName); const node = getAdjustedRenameLocation(getTouchingPropertyName(sourceFile, position)); if (!Rename.nodeIsEligibleForRename(node)) return undefined; - if (isIdentifier(node) && (isJsxOpeningElement(node.parent) || isJsxClosingElement(node.parent)) && isIntrinsicJsxName(node.escapedText)) { + if ( + isIdentifier(node) && (isJsxOpeningElement(node.parent) || isJsxClosingElement(node.parent)) + && isIntrinsicJsxName(node.escapedText) + ) { const { openingElement, closingElement } = node.parent.parent; return [openingElement, closingElement].map((node): RenameLocation => { const textSpan = createTextSpanFromNode(node.tagName, sourceFile); @@ -2162,17 +2435,42 @@ export function createLanguageService( } else { const quotePreference = getQuotePreference(sourceFile, preferences ?? emptyOptions); - const providePrefixAndSuffixTextForRename = typeof preferences === "boolean" ? preferences : preferences?.providePrefixAndSuffixTextForRename; - return getReferencesWorker(node, position, { findInStrings, findInComments, providePrefixAndSuffixTextForRename, use: FindAllReferences.FindReferencesUse.Rename }, (entry, originalNode, checker) => FindAllReferences.toRenameLocation(entry, originalNode, checker, providePrefixAndSuffixTextForRename || false, quotePreference)); + const providePrefixAndSuffixTextForRename = typeof preferences === "boolean" ? preferences + : preferences?.providePrefixAndSuffixTextForRename; + return getReferencesWorker( + node, + position, + { + findInStrings, + findInComments, + providePrefixAndSuffixTextForRename, + use: FindAllReferences.FindReferencesUse.Rename, + }, + (entry, originalNode, checker) => + FindAllReferences.toRenameLocation( + entry, + originalNode, + checker, + providePrefixAndSuffixTextForRename || false, + quotePreference, + ), + ); } } function getReferencesAtPosition(fileName: string, position: number): ReferenceEntry[] | undefined { synchronizeHostData(); - return getReferencesWorker(getTouchingPropertyName(getValidSourceFile(fileName), position), position, { use: FindAllReferences.FindReferencesUse.References }, FindAllReferences.toReferenceEntry); + return getReferencesWorker(getTouchingPropertyName(getValidSourceFile(fileName), position), position, { + use: FindAllReferences.FindReferencesUse.References, + }, FindAllReferences.toReferenceEntry); } - function getReferencesWorker(node: Node, position: number, options: FindAllReferences.Options, cb: FindAllReferences.ToReferenceOrRenameEntry): T[] | undefined { + function getReferencesWorker( + node: Node, + position: number, + options: FindAllReferences.Options, + cb: FindAllReferences.ToReferenceOrRenameEntry, + ): T[] | undefined { synchronizeHostData(); // Exclude default library when renaming as commonly user don't want to change that file. @@ -2180,23 +2478,51 @@ export function createLanguageService( ? program.getSourceFiles().filter(sourceFile => !program.isSourceFileDefaultLibrary(sourceFile)) : program.getSourceFiles(); - return FindAllReferences.findReferenceOrRenameEntries(program, cancellationToken, sourceFiles, node, position, options, cb); + return FindAllReferences.findReferenceOrRenameEntries( + program, + cancellationToken, + sourceFiles, + node, + position, + options, + cb, + ); } function findReferences(fileName: string, position: number): ReferencedSymbol[] | undefined { synchronizeHostData(); - return FindAllReferences.findReferencedSymbols(program, cancellationToken, program.getSourceFiles(), getValidSourceFile(fileName), position); + return FindAllReferences.findReferencedSymbols( + program, + cancellationToken, + program.getSourceFiles(), + getValidSourceFile(fileName), + position, + ); } function getFileReferences(fileName: string): ReferenceEntry[] { synchronizeHostData(); - return FindAllReferences.Core.getReferencesForFileName(fileName, program, program.getSourceFiles()).map(FindAllReferences.toReferenceEntry); + return FindAllReferences.Core.getReferencesForFileName(fileName, program, program.getSourceFiles()).map( + FindAllReferences.toReferenceEntry, + ); } - function getNavigateToItems(searchValue: string, maxResultCount?: number, fileName?: string, excludeDtsFiles = false): NavigateToItem[] { + function getNavigateToItems( + searchValue: string, + maxResultCount?: number, + fileName?: string, + excludeDtsFiles = false, + ): NavigateToItem[] { synchronizeHostData(); const sourceFiles = fileName ? [getValidSourceFile(fileName)] : program.getSourceFiles(); - return NavigateTo.getNavigateToItems(sourceFiles, program.getTypeChecker(), cancellationToken, searchValue, maxResultCount, excludeDtsFiles); + return NavigateTo.getNavigateToItems( + sourceFiles, + program.getTypeChecker(), + cancellationToken, + searchValue, + maxResultCount, + excludeDtsFiles, + ); } function getEmitOutput(fileName: string, emitOnlyDtsFiles?: boolean, forceDtsEmit?: boolean) { @@ -2204,14 +2530,25 @@ export function createLanguageService( const sourceFile = getValidSourceFile(fileName); const customTransformers = host.getCustomTransformers && host.getCustomTransformers(); - return getFileEmitOutput(program, sourceFile, !!emitOnlyDtsFiles, cancellationToken, customTransformers, forceDtsEmit); + return getFileEmitOutput( + program, + sourceFile, + !!emitOnlyDtsFiles, + cancellationToken, + customTransformers, + forceDtsEmit, + ); } // Signature help /** * This is a semantic operation. */ - function getSignatureHelpItems(fileName: string, position: number, { triggerReason }: SignatureHelpItemsOptions = emptyOptions): SignatureHelpItems | undefined { + function getSignatureHelpItems( + fileName: string, + position: number, + { triggerReason }: SignatureHelpItemsOptions = emptyOptions, + ): SignatureHelpItems | undefined { synchronizeHostData(); const sourceFile = getValidSourceFile(fileName); @@ -2263,8 +2600,8 @@ export function createLanguageService( // If parent of the module declaration which is parent of this node is module declaration and its body is the module declaration that this node is name of // Then this name is name from dotted module if ( - nodeForStartPos.parent.parent.kind === SyntaxKind.ModuleDeclaration && - (nodeForStartPos.parent.parent as ModuleDeclaration).body === nodeForStartPos.parent + nodeForStartPos.parent.parent.kind === SyntaxKind.ModuleDeclaration + && (nodeForStartPos.parent.parent as ModuleDeclaration).body === nodeForStartPos.parent ) { // Use parent module declarations name for start pos nodeForStartPos = (nodeForStartPos.parent.parent as ModuleDeclaration).name; @@ -2299,38 +2636,76 @@ export function createLanguageService( } function getSemanticClassifications(fileName: string, span: TextSpan): ClassifiedSpan[]; - function getSemanticClassifications(fileName: string, span: TextSpan, format?: SemanticClassificationFormat): ClassifiedSpan[] | ClassifiedSpan2020[] { + function getSemanticClassifications( + fileName: string, + span: TextSpan, + format?: SemanticClassificationFormat, + ): ClassifiedSpan[] | ClassifiedSpan2020[] { synchronizeHostData(); const responseFormat = format || SemanticClassificationFormat.Original; if (responseFormat === SemanticClassificationFormat.TwentyTwenty) { - return classifier2020.getSemanticClassifications(program, cancellationToken, getValidSourceFile(fileName), span); + return classifier2020.getSemanticClassifications( + program, + cancellationToken, + getValidSourceFile(fileName), + span, + ); } else { - return classifier.getSemanticClassifications(program.getTypeChecker(), cancellationToken, getValidSourceFile(fileName), program.getClassifiableNames(), span); + return classifier.getSemanticClassifications( + program.getTypeChecker(), + cancellationToken, + getValidSourceFile(fileName), + program.getClassifiableNames(), + span, + ); } } - function getEncodedSemanticClassifications(fileName: string, span: TextSpan, format?: SemanticClassificationFormat): Classifications { + function getEncodedSemanticClassifications( + fileName: string, + span: TextSpan, + format?: SemanticClassificationFormat, + ): Classifications { synchronizeHostData(); const responseFormat = format || SemanticClassificationFormat.Original; if (responseFormat === SemanticClassificationFormat.Original) { - return classifier.getEncodedSemanticClassifications(program.getTypeChecker(), cancellationToken, getValidSourceFile(fileName), program.getClassifiableNames(), span); + return classifier.getEncodedSemanticClassifications( + program.getTypeChecker(), + cancellationToken, + getValidSourceFile(fileName), + program.getClassifiableNames(), + span, + ); } else { - return classifier2020.getEncodedSemanticClassifications(program, cancellationToken, getValidSourceFile(fileName), span); + return classifier2020.getEncodedSemanticClassifications( + program, + cancellationToken, + getValidSourceFile(fileName), + span, + ); } } function getSyntacticClassifications(fileName: string, span: TextSpan): ClassifiedSpan[] { // doesn't use compiler - no need to synchronize with host - return classifier.getSyntacticClassifications(cancellationToken, syntaxTreeCache.getCurrentSourceFile(fileName), span); + return classifier.getSyntacticClassifications( + cancellationToken, + syntaxTreeCache.getCurrentSourceFile(fileName), + span, + ); } function getEncodedSyntacticClassifications(fileName: string, span: TextSpan): Classifications { // doesn't use compiler - no need to synchronize with host - return classifier.getEncodedSyntacticClassifications(cancellationToken, syntaxTreeCache.getCurrentSourceFile(fileName), span); + return classifier.getEncodedSyntacticClassifications( + cancellationToken, + syntaxTreeCache.getCurrentSourceFile(fileName), + span, + ); } function getOutliningSpans(fileName: string): OutliningSpan[] { @@ -2350,13 +2725,21 @@ export function createLanguageService( function getBraceMatchingAtPosition(fileName: string, position: number): TextSpan[] { const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); const token = getTouchingToken(sourceFile, position); - const matchKind = token.getStart(sourceFile) === position ? braceMatching.get(token.kind.toString()) : undefined; + const matchKind = token.getStart(sourceFile) === position ? braceMatching.get(token.kind.toString()) + : undefined; const match = matchKind && findChildOfKind(token.parent, matchKind, sourceFile); // We want to order the braces when we return the result. - return match ? [createTextSpanFromNode(token, sourceFile), createTextSpanFromNode(match, sourceFile)].sort((a, b) => a.start - b.start) : emptyArray; + return match + ? [createTextSpanFromNode(token, sourceFile), createTextSpanFromNode(match, sourceFile)].sort((a, b) => + a.start - b.start + ) : emptyArray; } - function getIndentationAtPosition(fileName: string, position: number, editorOptions: EditorOptions | EditorSettings) { + function getIndentationAtPosition( + fileName: string, + position: number, + editorOptions: EditorOptions | EditorSettings, + ) { let start = timestamp(); const settings = toEditorSettings(editorOptions); const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); @@ -2370,16 +2753,37 @@ export function createLanguageService( return result; } - function getFormattingEditsForRange(fileName: string, start: number, end: number, options: FormatCodeOptions | FormatCodeSettings): TextChange[] { + function getFormattingEditsForRange( + fileName: string, + start: number, + end: number, + options: FormatCodeOptions | FormatCodeSettings, + ): TextChange[] { const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); - return formatting.formatSelection(start, end, sourceFile, formatting.getFormatContext(toEditorSettings(options), host)); + return formatting.formatSelection( + start, + end, + sourceFile, + formatting.getFormatContext(toEditorSettings(options), host), + ); } - function getFormattingEditsForDocument(fileName: string, options: FormatCodeOptions | FormatCodeSettings): TextChange[] { - return formatting.formatDocument(syntaxTreeCache.getCurrentSourceFile(fileName), formatting.getFormatContext(toEditorSettings(options), host)); + function getFormattingEditsForDocument( + fileName: string, + options: FormatCodeOptions | FormatCodeSettings, + ): TextChange[] { + return formatting.formatDocument( + syntaxTreeCache.getCurrentSourceFile(fileName), + formatting.getFormatContext(toEditorSettings(options), host), + ); } - function getFormattingEditsAfterKeystroke(fileName: string, position: number, key: string, options: FormatCodeOptions | FormatCodeSettings): TextChange[] { + function getFormattingEditsAfterKeystroke( + fileName: string, + position: number, + key: string, + options: FormatCodeOptions | FormatCodeSettings, + ): TextChange[] { const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); const formatContext = formatting.getFormatContext(toEditorSettings(options), host); @@ -2399,7 +2803,14 @@ export function createLanguageService( return []; } - function getCodeFixesAtPosition(fileName: string, start: number, end: number, errorCodes: readonly number[], formatOptions: FormatCodeSettings, preferences: UserPreferences = emptyOptions): readonly CodeFixAction[] { + function getCodeFixesAtPosition( + fileName: string, + start: number, + end: number, + errorCodes: readonly number[], + formatOptions: FormatCodeSettings, + preferences: UserPreferences = emptyOptions, + ): readonly CodeFixAction[] { synchronizeHostData(); const sourceFile = getValidSourceFile(fileName); const span = createTextSpanFromBounds(start, end); @@ -2407,11 +2818,25 @@ export function createLanguageService( return flatMap(deduplicate(errorCodes, equateValues, compareValues), errorCode => { cancellationToken.throwIfCancellationRequested(); - return codefix.getFixes({ errorCode, sourceFile, span, program, host, cancellationToken, formatContext, preferences }); + return codefix.getFixes({ + errorCode, + sourceFile, + span, + program, + host, + cancellationToken, + formatContext, + preferences, + }); }); } - function getCombinedCodeFix(scope: CombinedCodeFixScope, fixId: {}, formatOptions: FormatCodeSettings, preferences: UserPreferences = emptyOptions): CombinedCodeActions { + function getCombinedCodeFix( + scope: CombinedCodeFixScope, + fixId: {}, + formatOptions: FormatCodeSettings, + preferences: UserPreferences = emptyOptions, + ): CombinedCodeActions { synchronizeHostData(); Debug.assert(scope.type === "file"); const sourceFile = getValidSourceFile(scope.fileName); @@ -2420,28 +2845,64 @@ export function createLanguageService( return codefix.getAllFixes({ fixId, sourceFile, program, host, cancellationToken, formatContext, preferences }); } - function organizeImports(args: OrganizeImportsArgs, formatOptions: FormatCodeSettings, preferences: UserPreferences = emptyOptions): readonly FileTextChanges[] { + function organizeImports( + args: OrganizeImportsArgs, + formatOptions: FormatCodeSettings, + preferences: UserPreferences = emptyOptions, + ): readonly FileTextChanges[] { synchronizeHostData(); Debug.assert(args.type === "file"); const sourceFile = getValidSourceFile(args.fileName); const formatContext = formatting.getFormatContext(formatOptions, host); - const mode = args.mode ?? (args.skipDestructiveCodeActions ? OrganizeImportsMode.SortAndCombine : OrganizeImportsMode.All); + const mode = args.mode + ?? (args.skipDestructiveCodeActions ? OrganizeImportsMode.SortAndCombine : OrganizeImportsMode.All); return OrganizeImports.organizeImports(sourceFile, formatContext, host, program, preferences, mode); } - function getEditsForFileRename(oldFilePath: string, newFilePath: string, formatOptions: FormatCodeSettings, preferences: UserPreferences = emptyOptions): readonly FileTextChanges[] { - return ts_getEditsForFileRename(getProgram()!, oldFilePath, newFilePath, host, formatting.getFormatContext(formatOptions, host), preferences, sourceMapper); + function getEditsForFileRename( + oldFilePath: string, + newFilePath: string, + formatOptions: FormatCodeSettings, + preferences: UserPreferences = emptyOptions, + ): readonly FileTextChanges[] { + return ts_getEditsForFileRename( + getProgram()!, + oldFilePath, + newFilePath, + host, + formatting.getFormatContext(formatOptions, host), + preferences, + sourceMapper, + ); } - function applyCodeActionCommand(action: CodeActionCommand, formatSettings?: FormatCodeSettings): Promise; - function applyCodeActionCommand(action: CodeActionCommand[], formatSettings?: FormatCodeSettings): Promise; - function applyCodeActionCommand(action: CodeActionCommand | CodeActionCommand[], formatSettings?: FormatCodeSettings): Promise; + function applyCodeActionCommand( + action: CodeActionCommand, + formatSettings?: FormatCodeSettings, + ): Promise; + function applyCodeActionCommand( + action: CodeActionCommand[], + formatSettings?: FormatCodeSettings, + ): Promise; + function applyCodeActionCommand( + action: CodeActionCommand | CodeActionCommand[], + formatSettings?: FormatCodeSettings, + ): Promise; function applyCodeActionCommand(fileName: Path, action: CodeActionCommand): Promise; - function applyCodeActionCommand(fileName: Path, action: CodeActionCommand[]): Promise; - function applyCodeActionCommand(fileName: Path | CodeActionCommand | CodeActionCommand[], actionOrFormatSettingsOrUndefined?: CodeActionCommand | CodeActionCommand[] | FormatCodeSettings): Promise { - const action = typeof fileName === "string" ? actionOrFormatSettingsOrUndefined as CodeActionCommand | CodeActionCommand[] : fileName as CodeActionCommand[]; - return isArray(action) ? Promise.all(action.map(a => applySingleCodeActionCommand(a))) : applySingleCodeActionCommand(action); + function applyCodeActionCommand( + fileName: Path, + action: CodeActionCommand[], + ): Promise; + function applyCodeActionCommand( + fileName: Path | CodeActionCommand | CodeActionCommand[], + actionOrFormatSettingsOrUndefined?: CodeActionCommand | CodeActionCommand[] | FormatCodeSettings, + ): Promise { + const action = typeof fileName === "string" + ? actionOrFormatSettingsOrUndefined as CodeActionCommand | CodeActionCommand[] + : fileName as CodeActionCommand[]; + return isArray(action) ? Promise.all(action.map(a => applySingleCodeActionCommand(a))) + : applySingleCodeActionCommand(action); } function applySingleCodeActionCommand(action: CodeActionCommand): Promise { @@ -2452,9 +2913,19 @@ export function createLanguageService( : Promise.reject("Host does not implement `installPackage`"); } - function getDocCommentTemplateAtPosition(fileName: string, position: number, options?: DocCommentTemplateOptions, formatOptions?: FormatCodeSettings): TextInsertion | undefined { + function getDocCommentTemplateAtPosition( + fileName: string, + position: number, + options?: DocCommentTemplateOptions, + formatOptions?: FormatCodeSettings, + ): TextInsertion | undefined { const formatSettings = formatOptions ? formatting.getFormatContext(formatOptions, host).options : undefined; - return JsDoc.getDocCommentTemplateAtPosition(getNewLineOrDefaultFromHost(host, formatSettings), syntaxTreeCache.getCurrentSourceFile(fileName), position, options); + return JsDoc.getDocCommentTemplateAtPosition( + getNewLineOrDefaultFromHost(host, formatSettings), + syntaxTreeCache.getCurrentSourceFile(fileName), + position, + options, + ); } function isValidBraceCompletionAtPosition(fileName: string, position: number, openingBrace: number): boolean { @@ -2497,12 +2968,14 @@ export function createLanguageService( const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); const token = findPrecedingToken(position, sourceFile); if (!token) return undefined; - const element = token.kind === SyntaxKind.GreaterThanToken && isJsxOpeningElement(token.parent) ? token.parent.parent + const element = token.kind === SyntaxKind.GreaterThanToken && isJsxOpeningElement(token.parent) + ? token.parent.parent : isJsxText(token) && isJsxElement(token.parent) ? token.parent : undefined; if (element && isUnclosedTag(element)) { return { newText: `` }; } - const fragment = token.kind === SyntaxKind.GreaterThanToken && isJsxOpeningFragment(token.parent) ? token.parent.parent + const fragment = token.kind === SyntaxKind.GreaterThanToken && isJsxOpeningFragment(token.parent) + ? token.parent.parent : isJsxText(token) && isJsxFragment(token.parent) ? token.parent : undefined; if (fragment && isUnclosedFragment(fragment)) { return { newText: "" }; @@ -2542,7 +3015,10 @@ export function createLanguageService( return false; }); if (!tag) return undefined; - Debug.assert(isJsxOpeningElement(tag) || isJsxClosingElement(tag), "tag should be opening or closing element"); + Debug.assert( + isJsxOpeningElement(tag) || isJsxClosingElement(tag), + "tag should be opening or closing element", + ); const openTag = tag.parent.openingElement; const closeTag = tag.parent.closingElement; @@ -2553,14 +3029,20 @@ export function createLanguageService( const closeTagEnd = closeTag.tagName.end; // only return linked cursors if the cursor is within a tag name - if (!(openTagStart <= position && position <= openTagEnd || closeTagStart <= position && position <= closeTagEnd)) return undefined; + if ( + !(openTagStart <= position && position <= openTagEnd + || closeTagStart <= position && position <= closeTagEnd) + ) return undefined; // only return linked cursors if text in both tags is identical const openingTagText = openTag.tagName.getText(sourceFile); if (openingTagText !== closeTag.tagName.getText(sourceFile)) return undefined; return { - ranges: [{ start: openTagStart, length: openTagEnd - openTagStart }, { start: closeTagStart, length: closeTagEnd - closeTagStart }], + ranges: [{ start: openTagStart, length: openTagEnd - openTagStart }, { + start: closeTagStart, + length: closeTagEnd - closeTagStart, + }], wordPattern: jsxTagWordPattern, }; } @@ -2614,7 +3096,18 @@ export function createLanguageService( // If the line is not an empty line; otherwise no-op. if (lineTextStart !== undefined) { if (isJsx) { - textChanges.push.apply(textChanges, toggleMultilineComment(fileName, { pos: lineStarts[i] + leftMostPosition, end: sourceFile.getLineEndOfPosition(lineStarts[i]) }, isCommenting, isJsx)); + textChanges.push.apply( + textChanges, + toggleMultilineComment( + fileName, + { + pos: lineStarts[i] + leftMostPosition, + end: sourceFile.getLineEndOfPosition(lineStarts[i]), + }, + isCommenting, + isJsx, + ), + ); } else if (isCommenting) { textChanges.push({ @@ -2640,7 +3133,12 @@ export function createLanguageService( return textChanges; } - function toggleMultilineComment(fileName: string, textRange: TextRange, insertComment?: boolean, isInsideJsx?: boolean): TextChange[] { + function toggleMultilineComment( + fileName: string, + textRange: TextRange, + insertComment?: boolean, + isInsideJsx?: boolean, + ): TextChange[] { const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); const textChanges: TextChange[] = []; const { text } = sourceFile; @@ -2680,7 +3178,9 @@ export function createLanguageService( pos = commentRange.end + 1; } else { // If it's not in a comment range, then we need to comment the uncommented portions. - const newPos = text.substring(pos, textRange.end).search(`(${openMultilineRegex})|(${closeMultilineRegex})`); + const newPos = text.substring(pos, textRange.end).search( + `(${openMultilineRegex})|(${closeMultilineRegex})`, + ); isCommenting = insertComment !== undefined ? insertComment @@ -2788,10 +3288,24 @@ export function createLanguageService( if (commentRange) { switch (commentRange.kind) { case SyntaxKind.SingleLineCommentTrivia: - textChanges.push.apply(textChanges, toggleLineComment(fileName, { end: commentRange.end, pos: commentRange.pos + 1 }, /*insertComment*/ false)); + textChanges.push.apply( + textChanges, + toggleLineComment( + fileName, + { end: commentRange.end, pos: commentRange.pos + 1 }, + /*insertComment*/ false, + ), + ); break; case SyntaxKind.MultiLineCommentTrivia: - textChanges.push.apply(textChanges, toggleMultilineComment(fileName, { end: commentRange.end, pos: commentRange.pos + 1 }, /*insertComment*/ false)); + textChanges.push.apply( + textChanges, + toggleMultilineComment( + fileName, + { end: commentRange.end, pos: commentRange.pos + 1 }, + /*insertComment*/ false, + ), + ); } i = commentRange.end + 1; @@ -2802,18 +3316,25 @@ export function createLanguageService( } function isUnclosedTag({ openingElement, closingElement, parent }: JsxElement): boolean { - return !tagNamesAreEquivalent(openingElement.tagName, closingElement.tagName) || - isJsxElement(parent) && tagNamesAreEquivalent(openingElement.tagName, parent.openingElement.tagName) && isUnclosedTag(parent); + return !tagNamesAreEquivalent(openingElement.tagName, closingElement.tagName) + || isJsxElement(parent) && tagNamesAreEquivalent(openingElement.tagName, parent.openingElement.tagName) + && isUnclosedTag(parent); } function isUnclosedFragment({ closingFragment, parent }: JsxFragment): boolean { - return !!(closingFragment.flags & NodeFlags.ThisNodeHasError) || (isJsxFragment(parent) && isUnclosedFragment(parent)); + return !!(closingFragment.flags & NodeFlags.ThisNodeHasError) + || (isJsxFragment(parent) && isUnclosedFragment(parent)); } - function getSpanOfEnclosingComment(fileName: string, position: number, onlyMultiLine: boolean): TextSpan | undefined { + function getSpanOfEnclosingComment( + fileName: string, + position: number, + onlyMultiLine: boolean, + ): TextSpan | undefined { const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); const range = formatting.getRangeOfEnclosingComment(sourceFile, position); - return range && (!onlyMultiLine || range.kind === SyntaxKind.MultiLineCommentTrivia) ? createTextSpanFromRange(range) : undefined; + return range && (!onlyMultiLine || range.kind === SyntaxKind.MultiLineCommentTrivia) + ? createTextSpanFromRange(range) : undefined; } function getTodoComments(fileName: string, descriptors: TodoCommentDescriptor[]): TodoComment[] { @@ -2917,7 +3438,8 @@ export function createLanguageService( // Match any of the above three TODO comment start regexps. // Note that the outermost group *is* a capture group. We want to capture the preamble // so that we can determine the starting position of the TODO comment match. - const preamble = "(" + anyNumberOfSpacesAndAsterisksAtStartOfLine + "|" + singleLineCommentStart + "|" + multiLineCommentStart + ")"; + const preamble = "(" + anyNumberOfSpacesAndAsterisksAtStartOfLine + "|" + singleLineCommentStart + "|" + + multiLineCommentStart + ")"; // Takes the descriptors and forms a regexp that matches them as if they were literals. // For example, if the descriptors are "TODO(jason)" and "HACK", then this will be: @@ -2953,9 +3475,9 @@ export function createLanguageService( } function isLetterOrDigit(char: number): boolean { - return (char >= CharacterCodes.a && char <= CharacterCodes.z) || - (char >= CharacterCodes.A && char <= CharacterCodes.Z) || - (char >= CharacterCodes._0 && char <= CharacterCodes._9); + return (char >= CharacterCodes.a && char <= CharacterCodes.z) + || (char >= CharacterCodes.A && char <= CharacterCodes.Z) + || (char >= CharacterCodes._0 && char <= CharacterCodes._9); } function isNodeModulesFile(path: string): boolean { @@ -2963,13 +3485,25 @@ export function createLanguageService( } } - function getRenameInfo(fileName: string, position: number, preferences: UserPreferences | RenameInfoOptions | undefined): RenameInfo { + function getRenameInfo( + fileName: string, + position: number, + preferences: UserPreferences | RenameInfoOptions | undefined, + ): RenameInfo { synchronizeHostData(); return Rename.getRenameInfo(program, getValidSourceFile(fileName), position, preferences || {}); } - function getRefactorContext(file: SourceFile, positionOrRange: number | TextRange, preferences: UserPreferences, formatOptions?: FormatCodeSettings, triggerReason?: RefactorTriggerReason, kind?: string): RefactorContext { - const [startPosition, endPosition] = typeof positionOrRange === "number" ? [positionOrRange, undefined] : [positionOrRange.pos, positionOrRange.end]; + function getRefactorContext( + file: SourceFile, + positionOrRange: number | TextRange, + preferences: UserPreferences, + formatOptions?: FormatCodeSettings, + triggerReason?: RefactorTriggerReason, + kind?: string, + ): RefactorContext { + const [startPosition, endPosition] = typeof positionOrRange === "number" ? [positionOrRange, undefined] + : [positionOrRange.pos, positionOrRange.end]; return { file, startPosition, @@ -2999,23 +3533,45 @@ export function createLanguageService( return SmartSelectionRange.getSmartSelectionRange(position, syntaxTreeCache.getCurrentSourceFile(fileName)); } - function getApplicableRefactors(fileName: string, positionOrRange: number | TextRange, preferences: UserPreferences = emptyOptions, triggerReason: RefactorTriggerReason, kind: string, includeInteractiveActions?: boolean): ApplicableRefactorInfo[] { + function getApplicableRefactors( + fileName: string, + positionOrRange: number | TextRange, + preferences: UserPreferences = emptyOptions, + triggerReason: RefactorTriggerReason, + kind: string, + includeInteractiveActions?: boolean, + ): ApplicableRefactorInfo[] { synchronizeHostData(); const file = getValidSourceFile(fileName); - return refactor.getApplicableRefactors(getRefactorContext(file, positionOrRange, preferences, emptyOptions, triggerReason, kind), includeInteractiveActions); + return refactor.getApplicableRefactors( + getRefactorContext(file, positionOrRange, preferences, emptyOptions, triggerReason, kind), + includeInteractiveActions, + ); } - function getMoveToRefactoringFileSuggestions(fileName: string, positionOrRange: number | TextRange, preferences: UserPreferences = emptyOptions): { newFileName: string; files: string[]; } { + function getMoveToRefactoringFileSuggestions( + fileName: string, + positionOrRange: number | TextRange, + preferences: UserPreferences = emptyOptions, + ): { newFileName: string; files: string[]; } { synchronizeHostData(); const sourceFile = getValidSourceFile(fileName); const allFiles = Debug.checkDefined(program.getSourceFiles()); const extension = extensionFromPath(fileName); const files = mapDefined(allFiles, file => - !program?.isSourceFileFromExternalLibrary(sourceFile) && - !(sourceFile === getValidSourceFile(file.fileName) || extension === Extension.Ts && extensionFromPath(file.fileName) === Extension.Dts || extension === Extension.Dts && startsWith(getBaseFileName(file.fileName), "lib.") && extensionFromPath(file.fileName) === Extension.Dts) + !program?.isSourceFileFromExternalLibrary(sourceFile) + && !(sourceFile === getValidSourceFile(file.fileName) + || extension === Extension.Ts && extensionFromPath(file.fileName) === Extension.Dts + || extension === Extension.Dts && startsWith(getBaseFileName(file.fileName), "lib.") + && extensionFromPath(file.fileName) === Extension.Dts) && extension === extensionFromPath(file.fileName) ? file.fileName : undefined); - const newFileName = createNewFileName(sourceFile, program, getRefactorContext(sourceFile, positionOrRange, preferences, emptyOptions), host); + const newFileName = createNewFileName( + sourceFile, + program, + getRefactorContext(sourceFile, positionOrRange, preferences, emptyOptions), + host, + ); return { newFileName, files }; } @@ -3030,7 +3586,12 @@ export function createLanguageService( ): RefactorEditInfo | undefined { synchronizeHostData(); const file = getValidSourceFile(fileName); - return refactor.getEditsForRefactor(getRefactorContext(file, positionOrRange, preferences, formatOptions), refactorName, actionName, interactiveRefactorArguments); + return refactor.getEditsForRefactor( + getRefactorContext(file, positionOrRange, preferences, formatOptions), + refactorName, + actionName, + interactiveRefactorArguments, + ); } function toLineColumnOffset(fileName: string, position: number): LineAndCharacter { @@ -3044,27 +3605,48 @@ export function createLanguageService( return sourceMapper.toLineColumnOffset(fileName, position); } - function prepareCallHierarchy(fileName: string, position: number): CallHierarchyItem | CallHierarchyItem[] | undefined { + function prepareCallHierarchy( + fileName: string, + position: number, + ): CallHierarchyItem | CallHierarchyItem[] | undefined { synchronizeHostData(); - const declarations = CallHierarchy.resolveCallHierarchyDeclaration(program, getTouchingPropertyName(getValidSourceFile(fileName), position)); - return declarations && mapOneOrMany(declarations, declaration => CallHierarchy.createCallHierarchyItem(program, declaration)); + const declarations = CallHierarchy.resolveCallHierarchyDeclaration( + program, + getTouchingPropertyName(getValidSourceFile(fileName), position), + ); + return declarations + && mapOneOrMany(declarations, declaration => CallHierarchy.createCallHierarchyItem(program, declaration)); } function provideCallHierarchyIncomingCalls(fileName: string, position: number): CallHierarchyIncomingCall[] { synchronizeHostData(); const sourceFile = getValidSourceFile(fileName); - const declaration = firstOrOnly(CallHierarchy.resolveCallHierarchyDeclaration(program, position === 0 ? sourceFile : getTouchingPropertyName(sourceFile, position))); + const declaration = firstOrOnly( + CallHierarchy.resolveCallHierarchyDeclaration( + program, + position === 0 ? sourceFile : getTouchingPropertyName(sourceFile, position), + ), + ); return declaration ? CallHierarchy.getIncomingCalls(program, declaration, cancellationToken) : []; } function provideCallHierarchyOutgoingCalls(fileName: string, position: number): CallHierarchyOutgoingCall[] { synchronizeHostData(); const sourceFile = getValidSourceFile(fileName); - const declaration = firstOrOnly(CallHierarchy.resolveCallHierarchyDeclaration(program, position === 0 ? sourceFile : getTouchingPropertyName(sourceFile, position))); + const declaration = firstOrOnly( + CallHierarchy.resolveCallHierarchyDeclaration( + program, + position === 0 ? sourceFile : getTouchingPropertyName(sourceFile, position), + ), + ); return declaration ? CallHierarchy.getOutgoingCalls(program, declaration) : []; } - function provideInlayHints(fileName: string, span: TextSpan, preferences: UserPreferences = emptyOptions): InlayHint[] { + function provideInlayHints( + fileName: string, + span: TextSpan, + preferences: UserPreferences = emptyOptions, + ): InlayHint[] { synchronizeHostData(); const sourceFile = getValidSourceFile(fileName); return InlayHints.provideInlayHints(getInlayHintsContext(sourceFile, span, preferences)); @@ -3148,7 +3730,9 @@ export function createLanguageService( case LanguageServiceMode.PartialSemantic: invalidOperationsInPartialSemanticMode.forEach(key => ls[key] = () => { - throw new Error(`LanguageService Operation: ${key} not allowed in LanguageServiceMode.PartialSemantic`); + throw new Error( + `LanguageService Operation: ${key} not allowed in LanguageServiceMode.PartialSemantic`, + ); } ); break; @@ -3181,7 +3765,10 @@ export function getNameTable(sourceFile: SourceFile): Map<__String, number> { function initializeNameTable(sourceFile: SourceFile): void { const nameTable = sourceFile.nameTable = new Map(); sourceFile.forEachChild(function walk(node) { - if (isIdentifier(node) && !isTagName(node) && node.escapedText || isStringOrNumericLiteralLike(node) && literalIsName(node)) { + if ( + isIdentifier(node) && !isTagName(node) && node.escapedText + || isStringOrNumericLiteralLike(node) && literalIsName(node) + ) { const text = getEscapedTextOfIdentifierOrLiteral(node); nameTable.set(text, nameTable.get(text) === undefined ? node.pos : -1); } @@ -3206,10 +3793,10 @@ function initializeNameTable(sourceFile: SourceFile): void { * "a['propname']" then we want to store "propname" in the name table. */ function literalIsName(node: StringLiteralLike | NumericLiteral): boolean { - return isDeclarationName(node) || - node.parent.kind === SyntaxKind.ExternalModuleReference || - isArgumentOfElementAccessExpression(node) || - isLiteralComputedPropertyDeclarationName(node); + return isDeclarationName(node) + || node.parent.kind === SyntaxKind.ExternalModuleReference + || isArgumentOfElementAccessExpression(node) + || isLiteralComputedPropertyDeclarationName(node); } /** @@ -3219,7 +3806,8 @@ function literalIsName(node: StringLiteralLike | NumericLiteral): boolean { */ export function getContainingObjectLiteralElement(node: Node): ObjectLiteralElementWithName | undefined { const element = getContainingObjectLiteralElementWorker(node); - return element && (isObjectLiteralExpression(element.parent) || isJsxAttributes(element.parent)) ? element as ObjectLiteralElementWithName : undefined; + return element && (isObjectLiteralExpression(element.parent) || isJsxAttributes(element.parent)) + ? element as ObjectLiteralElementWithName : undefined; } function getContainingObjectLiteralElementWorker(node: Node): ObjectLiteralElement | undefined { switch (node.kind) { @@ -3232,21 +3820,26 @@ function getContainingObjectLiteralElementWorker(node: Node): ObjectLiteralEleme // falls through case SyntaxKind.Identifier: - return isObjectLiteralElement(node.parent) && - (node.parent.parent.kind === SyntaxKind.ObjectLiteralExpression || node.parent.parent.kind === SyntaxKind.JsxAttributes) && - node.parent.name === node ? node.parent : undefined; + return isObjectLiteralElement(node.parent) + && (node.parent.parent.kind === SyntaxKind.ObjectLiteralExpression + || node.parent.parent.kind === SyntaxKind.JsxAttributes) + && node.parent.name === node ? node.parent : undefined; } return undefined; } /** @internal */ -export type ObjectLiteralElementWithName = ObjectLiteralElement & { name: PropertyName; parent: ObjectLiteralExpression | JsxAttributes; }; +export type ObjectLiteralElementWithName = ObjectLiteralElement & { + name: PropertyName; + parent: ObjectLiteralExpression | JsxAttributes; +}; function getSymbolAtLocationForQuickInfo(node: Node, checker: TypeChecker): Symbol | undefined { const object = getContainingObjectLiteralElement(node); if (object) { const contextualType = checker.getContextualType(object.parent); - const properties = contextualType && getPropertySymbolsFromContextualType(object, checker, contextualType, /*unionSymbolOk*/ false); + const properties = contextualType + && getPropertySymbolsFromContextualType(object, checker, contextualType, /*unionSymbolOk*/ false); if (properties && properties.length === 1) { return first(properties); } @@ -3259,7 +3852,12 @@ function getSymbolAtLocationForQuickInfo(node: Node, checker: TypeChecker): Symb * * @internal */ -export function getPropertySymbolsFromContextualType(node: ObjectLiteralElementWithName, checker: TypeChecker, contextualType: Type, unionSymbolOk: boolean): readonly Symbol[] { +export function getPropertySymbolsFromContextualType( + node: ObjectLiteralElementWithName, + checker: TypeChecker, + contextualType: Type, + unionSymbolOk: boolean, +): readonly Symbol[] { const name = getNameFromPropertyName(node.name); if (!name) return emptyArray; if (!contextualType.isUnion()) { @@ -3267,8 +3865,16 @@ export function getPropertySymbolsFromContextualType(node: ObjectLiteralElementW return symbol ? [symbol] : emptyArray; } - const discriminatedPropertySymbols = mapDefined(contextualType.types, t => (isObjectLiteralExpression(node.parent) || isJsxAttributes(node.parent)) && checker.isTypeInvalidDueToUnionDiscriminant(t, node.parent) ? undefined : t.getProperty(name)); - if (unionSymbolOk && (discriminatedPropertySymbols.length === 0 || discriminatedPropertySymbols.length === contextualType.types.length)) { + const discriminatedPropertySymbols = mapDefined( + contextualType.types, + t => (isObjectLiteralExpression(node.parent) || isJsxAttributes(node.parent)) + && checker.isTypeInvalidDueToUnionDiscriminant(t, node.parent) ? undefined : t.getProperty(name), + ); + if ( + unionSymbolOk + && (discriminatedPropertySymbols.length === 0 + || discriminatedPropertySymbols.length === contextualType.types.length) + ) { const symbol = contextualType.getProperty(name); if (symbol) return [symbol]; } @@ -3280,10 +3886,10 @@ export function getPropertySymbolsFromContextualType(node: ObjectLiteralElementW } function isArgumentOfElementAccessExpression(node: Node) { - return node && - node.parent && - node.parent.kind === SyntaxKind.ElementAccessExpression && - (node.parent as ElementAccessExpression).argumentExpression === node; + return node + && node.parent + && node.parent.kind === SyntaxKind.ElementAccessExpression + && (node.parent as ElementAccessExpression).argumentExpression === node; } /** @@ -3293,7 +3899,10 @@ function isArgumentOfElementAccessExpression(node: Node) { */ export function getDefaultLibFilePath(options: CompilerOptions): string { if (sys) { - return combinePaths(getDirectoryPath(normalizePath(sys.getExecutingFilePath())), getDefaultLibFileName(options)); + return combinePaths( + getDirectoryPath(normalizePath(sys.getExecutingFilePath())), + getDefaultLibFileName(options), + ); } throw new Error("getDefaultLibFilePath is only supported when consumed as a node module. "); diff --git a/src/services/shims.ts b/src/services/shims.ts index 10b6baaf7d02b..8e6b976d79489 100644 --- a/src/services/shims.ts +++ b/src/services/shims.ts @@ -151,7 +151,15 @@ export interface LanguageServiceShimHost extends Logger { useCaseSensitiveFileNames?(): boolean; getTypeRootsVersion?(): number; - readDirectory(rootDir: string, extension: string, basePaths?: string, excludeEx?: string, includeFileEx?: string, includeDirEx?: string, depth?: number): string; + readDirectory( + rootDir: string, + extension: string, + basePaths?: string, + excludeEx?: string, + includeFileEx?: string, + includeDirEx?: string, + depth?: number, + ): string; readFile(path: string, encoding?: string): string | undefined; fileExists(path: string): boolean; @@ -177,7 +185,15 @@ export interface CoreServicesShimHost extends Logger { * @param exclude A JSON encoded string[] containing the paths to exclude * when enumerating the directory. */ - readDirectory(rootDir: string, extension: string, basePaths?: string, excludeEx?: string, includeFileEx?: string, includeDirEx?: string, depth?: number): string; + readDirectory( + rootDir: string, + extension: string, + basePaths?: string, + excludeEx?: string, + includeFileEx?: string, + includeDirEx?: string, + depth?: number, + ): string; /** * Read arbitrary text files on disk, i.e. when resolution procedure needs the content of 'package.json' to determine location of bundled typings for node modules @@ -231,12 +247,35 @@ export interface LanguageServiceShim extends Shim { getCompilerOptionsDiagnostics(): string; getSyntacticClassifications(fileName: string, start: number, length: number): string; - getSemanticClassifications(fileName: string, start: number, length: number, format?: SemanticClassificationFormat): string; + getSemanticClassifications( + fileName: string, + start: number, + length: number, + format?: SemanticClassificationFormat, + ): string; getEncodedSyntacticClassifications(fileName: string, start: number, length: number): string; - getEncodedSemanticClassifications(fileName: string, start: number, length: number, format?: SemanticClassificationFormat): string; - - getCompletionsAtPosition(fileName: string, position: number, preferences: UserPreferences | undefined, formattingSettings: FormatCodeSettings | undefined): string; - getCompletionEntryDetails(fileName: string, position: number, entryName: string, formatOptions: string /*Services.FormatCodeOptions*/ | undefined, source: string | undefined, preferences: UserPreferences | undefined, data: CompletionEntryData | undefined): string; + getEncodedSemanticClassifications( + fileName: string, + start: number, + length: number, + format?: SemanticClassificationFormat, + ): string; + + getCompletionsAtPosition( + fileName: string, + position: number, + preferences: UserPreferences | undefined, + formattingSettings: FormatCodeSettings | undefined, + ): string; + getCompletionEntryDetails( + fileName: string, + position: number, + entryName: string, + formatOptions: string /*Services.FormatCodeOptions*/ | undefined, + source: string | undefined, + preferences: UserPreferences | undefined, + data: CompletionEntryData | undefined, + ): string; getQuickInfoAtPosition(fileName: string, position: number): string; @@ -256,7 +295,13 @@ export interface LanguageServiceShim extends Shim { * Returns a JSON-encoded value of the type: * { fileName: string, textSpan: { start: number, length: number } }[] */ - findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean, preferences?: UserPreferences | boolean): string; + findRenameLocations( + fileName: string, + position: number, + findInStrings: boolean, + findInComments: boolean, + preferences?: UserPreferences | boolean, + ): string; /** * Returns a JSON-encoded value of the type: @@ -335,14 +380,29 @@ export interface LanguageServiceShim extends Shim { getBraceMatchingAtPosition(fileName: string, position: number): string; getIndentationAtPosition(fileName: string, position: number, options: string /*Services.EditorOptions*/): string; - getFormattingEditsForRange(fileName: string, start: number, end: number, options: string /*Services.FormatCodeOptions*/): string; + getFormattingEditsForRange( + fileName: string, + start: number, + end: number, + options: string, /*Services.FormatCodeOptions*/ + ): string; getFormattingEditsForDocument(fileName: string, options: string /*Services.FormatCodeOptions*/): string; - getFormattingEditsAfterKeystroke(fileName: string, position: number, key: string, options: string /*Services.FormatCodeOptions*/): string; + getFormattingEditsAfterKeystroke( + fileName: string, + position: number, + key: string, + options: string, /*Services.FormatCodeOptions*/ + ): string; /** * Returns JSON-encoded value of the type TextInsertion. */ - getDocCommentTemplateAtPosition(fileName: string, position: number, options?: DocCommentTemplateOptions, formatOptions?: FormatCodeSettings): string; + getDocCommentTemplateAtPosition( + fileName: string, + position: number, + options?: DocCommentTemplateOptions, + formatOptions?: FormatCodeSettings, + ): string; /** * Returns JSON-encoded boolean to indicate whether we should support brace location @@ -371,7 +431,11 @@ export interface LanguageServiceShim extends Shim { /** @internal */ export interface ClassifierShim extends Shim { - getEncodedLexicalClassifications(text: string, lexState: EndOfLineState, syntacticClassifierAbsent?: boolean): string; + getEncodedLexicalClassifications( + text: string, + lexState: EndOfLineState, + syntacticClassifierAbsent?: boolean, + ): string; getClassificationsForLine(text: string, lexState: EndOfLineState, syntacticClassifierAbsent?: boolean): string; } @@ -432,8 +496,15 @@ export class LanguageServiceShimHostAdapter implements LanguageServiceHost { private loggingEnabled = false; private tracingEnabled = false; - public resolveModuleNames: ((moduleName: string[], containingFile: string) => (ResolvedModuleFull | undefined)[]) | undefined; - public resolveTypeReferenceDirectives: ((typeDirectiveNames: string[] | readonly FileReference[], containingFile: string) => (ResolvedTypeReferenceDirective | undefined)[]) | undefined; + public resolveModuleNames: + | ((moduleName: string[], containingFile: string) => (ResolvedModuleFull | undefined)[]) + | undefined; + public resolveTypeReferenceDirectives: + | (( + typeDirectiveNames: string[] | readonly FileReference[], + containingFile: string, + ) => (ResolvedTypeReferenceDirective | undefined)[]) + | undefined; public directoryExists: ((directoryName: string) => boolean) | undefined; constructor(private shimHost: LanguageServiceShimHost) { @@ -441,10 +512,17 @@ export class LanguageServiceShimHostAdapter implements LanguageServiceHost { // 'in' does not have this effect. if ("getModuleResolutionsForFile" in this.shimHost) { this.resolveModuleNames = (moduleNames, containingFile) => { - const resolutionsInFile = JSON.parse(this.shimHost.getModuleResolutionsForFile!(containingFile)) as MapLike; // TODO: GH#18217 + const resolutionsInFile = JSON.parse( + this.shimHost.getModuleResolutionsForFile!(containingFile), + ) as MapLike; // TODO: GH#18217 return map(moduleNames, name => { const result = getProperty(resolutionsInFile, name); - return result ? { resolvedFileName: result, extension: extensionFromPath(result), isExternalLibraryImport: false } : undefined; + return result + ? { + resolvedFileName: result, + extension: extensionFromPath(result), + isExternalLibraryImport: false, + } : undefined; }); }; } @@ -453,8 +531,14 @@ export class LanguageServiceShimHostAdapter implements LanguageServiceHost { } if ("getTypeReferenceDirectiveResolutionsForFile" in this.shimHost) { this.resolveTypeReferenceDirectives = (typeDirectiveNames, containingFile) => { - const typeDirectivesForFile = JSON.parse(this.shimHost.getTypeReferenceDirectiveResolutionsForFile!(containingFile)) as MapLike; // TODO: GH#18217 - return map(typeDirectiveNames as (string | FileReference)[], name => getProperty(typeDirectivesForFile, isString(name) ? name : toFileNameLowerCase(name.fileName))); + const typeDirectivesForFile = JSON.parse( + this.shimHost.getTypeReferenceDirectiveResolutionsForFile!(containingFile), + ) as MapLike; // TODO: GH#18217 + return map( + typeDirectiveNames as (string | FileReference)[], + name => + getProperty(typeDirectivesForFile, isString(name) ? name : toFileNameLowerCase(name.fileName)), + ); }; } } @@ -564,8 +648,20 @@ export class LanguageServiceShimHostAdapter implements LanguageServiceHost { return this.shimHost.getDefaultLibFileName(JSON.stringify(options)); } - public readDirectory(path: string, extensions?: readonly string[], exclude?: string[], include?: string[], depth?: number): string[] { - const pattern = getFileMatcherPatterns(path, exclude, include, this.shimHost.useCaseSensitiveFileNames!(), this.shimHost.getCurrentDirectory()); // TODO: GH#18217 + public readDirectory( + path: string, + extensions?: readonly string[], + exclude?: string[], + include?: string[], + depth?: number, + ): string[] { + const pattern = getFileMatcherPatterns( + path, + exclude, + include, + this.shimHost.useCaseSensitiveFileNames!(), + this.shimHost.getCurrentDirectory(), + ); // TODO: GH#18217 return JSON.parse(this.shimHost.readDirectory( path, JSON.stringify(extensions), @@ -587,13 +683,16 @@ export class LanguageServiceShimHostAdapter implements LanguageServiceHost { } /** @internal */ -export class CoreServicesShimHostAdapter implements ParseConfigHost, ModuleResolutionHost, JsTyping.TypingResolutionHost { +export class CoreServicesShimHostAdapter + implements ParseConfigHost, ModuleResolutionHost, JsTyping.TypingResolutionHost +{ public directoryExists: (directoryName: string) => boolean; public realpath: (path: string) => string; public useCaseSensitiveFileNames: boolean; constructor(private shimHost: CoreServicesShimHost) { - this.useCaseSensitiveFileNames = this.shimHost.useCaseSensitiveFileNames ? this.shimHost.useCaseSensitiveFileNames() : false; + this.useCaseSensitiveFileNames = this.shimHost.useCaseSensitiveFileNames + ? this.shimHost.useCaseSensitiveFileNames() : false; if ("directoryExists" in this.shimHost) { this.directoryExists = directoryName => this.shimHost.directoryExists(directoryName); } @@ -608,8 +707,20 @@ export class CoreServicesShimHostAdapter implements ParseConfigHost, ModuleResol } } - public readDirectory(rootDir: string, extensions: readonly string[], exclude: readonly string[], include: readonly string[], depth?: number): string[] { - const pattern = getFileMatcherPatterns(rootDir, exclude, include, this.shimHost.useCaseSensitiveFileNames!(), this.shimHost.getCurrentDirectory()); // TODO: GH#18217 + public readDirectory( + rootDir: string, + extensions: readonly string[], + exclude: readonly string[], + include: readonly string[], + depth?: number, + ): string[] { + const pattern = getFileMatcherPatterns( + rootDir, + exclude, + include, + this.shimHost.useCaseSensitiveFileNames!(), + this.shimHost.getCurrentDirectory(), + ); // TODO: GH#18217 return JSON.parse(this.shimHost.readDirectory( rootDir, JSON.stringify(extensions), @@ -634,7 +745,12 @@ export class CoreServicesShimHostAdapter implements ParseConfigHost, ModuleResol } } -function simpleForwardCall(logger: Logger, actionDescription: string, action: () => unknown, logPerformance: boolean): unknown { +function simpleForwardCall( + logger: Logger, + actionDescription: string, + action: () => unknown, + logPerformance: boolean, +): unknown { let start: number | undefined; if (logPerformance) { logger.log(actionDescription); @@ -658,11 +774,22 @@ function simpleForwardCall(logger: Logger, actionDescription: string, action: () return result; } -function forwardJSONCall(logger: Logger, actionDescription: string, action: () => {} | null | undefined, logPerformance: boolean): string { +function forwardJSONCall( + logger: Logger, + actionDescription: string, + action: () => {} | null | undefined, + logPerformance: boolean, +): string { return forwardCall(logger, actionDescription, /*returnJson*/ true, action, logPerformance) as string; } -function forwardCall(logger: Logger, actionDescription: string, returnJson: boolean, action: () => T, logPerformance: boolean): T | string { +function forwardCall( + logger: Logger, + actionDescription: string, + returnJson: boolean, + action: () => T, + logPerformance: boolean, +): T | string { try { const result = simpleForwardCall(logger, actionDescription, action, logPerformance); return returnJson ? JSON.stringify({ result }) : result as T; @@ -770,7 +897,9 @@ class LanguageServiceShimObject extends ShimBase implements LanguageServiceShim ); } - private realizeDiagnostics(diagnostics: readonly Diagnostic[]): { message: string; start: number; length: number; category: string; }[] { + private realizeDiagnostics( + diagnostics: readonly Diagnostic[], + ): { message: string; start: number; length: number; category: string; }[] { const newLine = getNewLineOrDefaultFromHost(this.host, /*formatSettings*/ undefined); return realizeDiagnostics(diagnostics, newLine); } @@ -794,7 +923,10 @@ class LanguageServiceShimObject extends ShimBase implements LanguageServiceShim `getEncodedSyntacticClassifications('${fileName}', ${start}, ${length})`, // directly serialize the spans out to a string. This is much faster to decode // on the managed side versus a full JSON array. - () => convertClassifications(this.languageService.getEncodedSyntacticClassifications(fileName, createTextSpan(start, length))), + () => + convertClassifications( + this.languageService.getEncodedSyntacticClassifications(fileName, createTextSpan(start, length)), + ), ); } @@ -803,7 +935,10 @@ class LanguageServiceShimObject extends ShimBase implements LanguageServiceShim `getEncodedSemanticClassifications('${fileName}', ${start}, ${length})`, // directly serialize the spans out to a string. This is much faster to decode // on the managed side versus a full JSON array. - () => convertClassifications(this.languageService.getEncodedSemanticClassifications(fileName, createTextSpan(start, length))), + () => + convertClassifications( + this.languageService.getEncodedSemanticClassifications(fileName, createTextSpan(start, length)), + ), ); } @@ -828,7 +963,10 @@ class LanguageServiceShimObject extends ShimBase implements LanguageServiceShim } public getSuggestionDiagnostics(fileName: string): string { - return this.forwardJSONCall(`getSuggestionDiagnostics('${fileName}')`, () => this.realizeDiagnostics(this.languageService.getSuggestionDiagnostics(fileName))); + return this.forwardJSONCall( + `getSuggestionDiagnostics('${fileName}')`, + () => this.realizeDiagnostics(this.languageService.getSuggestionDiagnostics(fileName)), + ); } public getCompilerOptionsDiagnostics(): string { @@ -880,7 +1018,11 @@ class LanguageServiceShimObject extends ShimBase implements LanguageServiceShim /// SIGNATUREHELP - public getSignatureHelpItems(fileName: string, position: number, options: SignatureHelpItemsOptions | undefined): string { + public getSignatureHelpItems( + fileName: string, + position: number, + options: SignatureHelpItemsOptions | undefined, + ): string { return this.forwardJSONCall( `getSignatureHelpItems('${fileName}', ${position})`, () => this.languageService.getSignatureHelpItems(fileName, position, options), @@ -951,10 +1093,23 @@ class LanguageServiceShimObject extends ShimBase implements LanguageServiceShim ); } - public findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean, preferences: UserPreferences): string { + public findRenameLocations( + fileName: string, + position: number, + findInStrings: boolean, + findInComments: boolean, + preferences: UserPreferences, + ): string { return this.forwardJSONCall( `findRenameLocations('${fileName}', ${position}, ${findInStrings}, ${findInComments})`, - () => this.languageService.findRenameLocations(fileName, position, findInStrings, findInComments, preferences), + () => + this.languageService.findRenameLocations( + fileName, + position, + findInStrings, + findInComments, + preferences, + ), ); } @@ -981,7 +1136,11 @@ class LanguageServiceShimObject extends ShimBase implements LanguageServiceShim } /// GET SMART INDENT - public getIndentationAtPosition(fileName: string, position: number, options: string /*Services.EditorOptions*/): string { + public getIndentationAtPosition( + fileName: string, + position: number, + options: string, /*Services.EditorOptions*/ + ): string { return this.forwardJSONCall( `getIndentationAtPosition('${fileName}', ${position})`, () => { @@ -1018,7 +1177,11 @@ class LanguageServiceShimObject extends ShimBase implements LanguageServiceShim return this.forwardJSONCall( `getDocumentHighlights('${fileName}', ${position})`, () => { - const results = this.languageService.getDocumentHighlights(fileName, position, JSON.parse(filesToSearch)); + const results = this.languageService.getDocumentHighlights( + fileName, + position, + JSON.parse(filesToSearch), + ); // workaround for VS document highlighting issue - keep only items from the initial file const normalizedName = toFileNameLowerCase(normalizeSlashes(fileName)); return filter(results, r => toFileNameLowerCase(normalizeSlashes(r.fileName)) === normalizedName); @@ -1033,7 +1196,12 @@ class LanguageServiceShimObject extends ShimBase implements LanguageServiceShim * to provide at the given source position and providing a member completion * list if requested. */ - public getCompletionsAtPosition(fileName: string, position: number, preferences: GetCompletionsAtPositionOptions | undefined, formattingSettings: FormatCodeSettings | undefined) { + public getCompletionsAtPosition( + fileName: string, + position: number, + preferences: GetCompletionsAtPositionOptions | undefined, + formattingSettings: FormatCodeSettings | undefined, + ) { return this.forwardJSONCall( `getCompletionsAtPosition('${fileName}', ${position}, ${preferences}, ${formattingSettings})`, () => this.languageService.getCompletionsAtPosition(fileName, position, preferences, formattingSettings), @@ -1041,17 +1209,39 @@ class LanguageServiceShimObject extends ShimBase implements LanguageServiceShim } /** Get a string based representation of a completion list entry details */ - public getCompletionEntryDetails(fileName: string, position: number, entryName: string, formatOptions: string /*Services.FormatCodeOptions*/ | undefined, source: string | undefined, preferences: UserPreferences | undefined, data: CompletionEntryData | undefined) { + public getCompletionEntryDetails( + fileName: string, + position: number, + entryName: string, + formatOptions: string /*Services.FormatCodeOptions*/ | undefined, + source: string | undefined, + preferences: UserPreferences | undefined, + data: CompletionEntryData | undefined, + ) { return this.forwardJSONCall( `getCompletionEntryDetails('${fileName}', ${position}, '${entryName}')`, () => { - const localOptions: FormatCodeOptions = formatOptions === undefined ? undefined : JSON.parse(formatOptions); - return this.languageService.getCompletionEntryDetails(fileName, position, entryName, localOptions, source, preferences, data); + const localOptions: FormatCodeOptions = formatOptions === undefined ? undefined + : JSON.parse(formatOptions); + return this.languageService.getCompletionEntryDetails( + fileName, + position, + entryName, + localOptions, + source, + preferences, + data, + ); }, ); } - public getFormattingEditsForRange(fileName: string, start: number, end: number, options: string /*Services.FormatCodeOptions*/): string { + public getFormattingEditsForRange( + fileName: string, + start: number, + end: number, + options: string, /*Services.FormatCodeOptions*/ + ): string { return this.forwardJSONCall( `getFormattingEditsForRange('${fileName}', ${start}, ${end})`, () => { @@ -1071,7 +1261,12 @@ class LanguageServiceShimObject extends ShimBase implements LanguageServiceShim ); } - public getFormattingEditsAfterKeystroke(fileName: string, position: number, key: string, options: string /*Services.FormatCodeOptions*/): string { + public getFormattingEditsAfterKeystroke( + fileName: string, + position: number, + key: string, + options: string, /*Services.FormatCodeOptions*/ + ): string { return this.forwardJSONCall( `getFormattingEditsAfterKeystroke('${fileName}', ${position}, '${key}')`, () => { @@ -1081,7 +1276,12 @@ class LanguageServiceShimObject extends ShimBase implements LanguageServiceShim ); } - public getDocCommentTemplateAtPosition(fileName: string, position: number, options?: DocCommentTemplateOptions, formatOptions?: FormatCodeSettings): string { + public getDocCommentTemplateAtPosition( + fileName: string, + position: number, + options?: DocCommentTemplateOptions, + formatOptions?: FormatCodeSettings, + ): string { return this.forwardJSONCall( `getDocCommentTemplateAtPosition('${fileName}', ${position})`, () => this.languageService.getDocCommentTemplateAtPosition(fileName, position, options, formatOptions), @@ -1219,12 +1419,28 @@ class ClassifierShimObject extends ShimBase implements ClassifierShim { this.classifier = createClassifier(); } - public getEncodedLexicalClassifications(text: string, lexState: EndOfLineState, syntacticClassifierAbsent = false): string { - return forwardJSONCall(this.logger, "getEncodedLexicalClassifications", () => convertClassifications(this.classifier.getEncodedLexicalClassifications(text, lexState, syntacticClassifierAbsent)), this.logPerformance); + public getEncodedLexicalClassifications( + text: string, + lexState: EndOfLineState, + syntacticClassifierAbsent = false, + ): string { + return forwardJSONCall( + this.logger, + "getEncodedLexicalClassifications", + () => + convertClassifications( + this.classifier.getEncodedLexicalClassifications(text, lexState, syntacticClassifierAbsent), + ), + this.logPerformance, + ); } /// COLORIZATION - public getClassificationsForLine(text: string, lexState: EndOfLineState, classifyKeywordsInGenerics = false): string { + public getClassificationsForLine( + text: string, + lexState: EndOfLineState, + classifyKeywordsInGenerics = false, + ): string { const classification = this.classifier.getClassificationsForLine(text, lexState, classifyKeywordsInGenerics); let result = ""; for (const item of classification.entries) { @@ -1240,7 +1456,11 @@ class CoreServicesShimObject extends ShimBase implements CoreServicesShim { private logPerformance = false; private safeList: JsTyping.SafeList | undefined; - constructor(factory: ShimFactory, public readonly logger: Logger, private readonly host: CoreServicesShimHostAdapter) { + constructor( + factory: ShimFactory, + public readonly logger: Logger, + private readonly host: CoreServicesShimHostAdapter, + ) { super(factory); } @@ -1253,7 +1473,11 @@ class CoreServicesShimObject extends ShimBase implements CoreServicesShim { const compilerOptions = JSON.parse(compilerOptionsJson) as CompilerOptions; const result = resolveModuleName(moduleName, normalizeSlashes(fileName), compilerOptions, this.host); let resolvedFileName = result.resolvedModule ? result.resolvedModule.resolvedFileName : undefined; - if (result.resolvedModule && result.resolvedModule.extension !== Extension.Ts && result.resolvedModule.extension !== Extension.Tsx && result.resolvedModule.extension !== Extension.Dts) { + if ( + result.resolvedModule && result.resolvedModule.extension !== Extension.Ts + && result.resolvedModule.extension !== Extension.Tsx + && result.resolvedModule.extension !== Extension.Dts + ) { resolvedFileName = undefined; } @@ -1265,12 +1489,22 @@ class CoreServicesShimObject extends ShimBase implements CoreServicesShim { }); } - public resolveTypeReferenceDirective(fileName: string, typeReferenceDirective: string, compilerOptionsJson: string): string { + public resolveTypeReferenceDirective( + fileName: string, + typeReferenceDirective: string, + compilerOptionsJson: string, + ): string { return this.forwardJSONCall(`resolveTypeReferenceDirective(${fileName})`, () => { const compilerOptions = JSON.parse(compilerOptionsJson) as CompilerOptions; - const result = resolveTypeReferenceDirective(typeReferenceDirective, normalizeSlashes(fileName), compilerOptions, this.host); + const result = resolveTypeReferenceDirective( + typeReferenceDirective, + normalizeSlashes(fileName), + compilerOptions, + this.host, + ); return { - resolvedFileName: result.resolvedTypeReferenceDirective ? result.resolvedTypeReferenceDirective.resolvedFileName : undefined, + resolvedFileName: result.resolvedTypeReferenceDirective + ? result.resolvedTypeReferenceDirective.resolvedFileName : undefined, primary: result.resolvedTypeReferenceDirective ? result.resolvedTypeReferenceDirective.primary : true, failedLookupLocations: result.failedLookupLocations, }; @@ -1282,7 +1516,11 @@ class CoreServicesShimObject extends ShimBase implements CoreServicesShim { `getPreProcessedFileInfo('${fileName}')`, () => { // for now treat files as JavaScript - const result = preProcessFile(getSnapshotText(sourceTextSnapshot), /*readImportFiles*/ true, /*detectJavaScriptImports*/ true); + const result = preProcessFile( + getSnapshotText(sourceTextSnapshot), + /*readImportFiles*/ true, + /*detectJavaScriptImports*/ true, + ); return { referencedFiles: this.convertFileReferences(result.referencedFiles), importedFiles: this.convertFileReferences(result.importedFiles), @@ -1326,7 +1564,13 @@ class CoreServicesShimObject extends ShimBase implements CoreServicesShim { () => { const result = parseJsonText(fileName, getSnapshotText(sourceTextSnapshot)); const normalizedFileName = normalizeSlashes(fileName); - const configFile = parseJsonSourceFileConfigFileContent(result, this.host, getDirectoryPath(normalizedFileName), /*existingOptions*/ {}, normalizedFileName); + const configFile = parseJsonSourceFileConfigFileContent( + result, + this.host, + getDirectoryPath(normalizedFileName), + /*existingOptions*/ {}, + normalizedFileName, + ); return { options: configFile.options, @@ -1351,7 +1595,10 @@ class CoreServicesShimObject extends ShimBase implements CoreServicesShim { return this.forwardJSONCall("discoverTypings()", () => { const info = JSON.parse(discoverTypingsJson) as DiscoverTypingsInfo; if (this.safeList === undefined) { - this.safeList = JsTyping.loadSafeList(this.host, toPath(info.safeListPath, info.safeListPath, getCanonicalFileName)); + this.safeList = JsTyping.loadSafeList( + this.host, + toPath(info.safeListPath, info.safeListPath, getCanonicalFileName), + ); } return JsTyping.discoverTypings( this.host, @@ -1384,10 +1631,17 @@ export class TypeScriptServicesFactory implements ShimFactory { public createLanguageServiceShim(host: LanguageServiceShimHost): LanguageServiceShim { try { if (this.documentRegistry === undefined) { - this.documentRegistry = createDocumentRegistry(host.useCaseSensitiveFileNames && host.useCaseSensitiveFileNames(), host.getCurrentDirectory()); + this.documentRegistry = createDocumentRegistry( + host.useCaseSensitiveFileNames && host.useCaseSensitiveFileNames(), + host.getCurrentDirectory(), + ); } const hostAdapter = new LanguageServiceShimHostAdapter(host); - const languageService = createLanguageService(hostAdapter, this.documentRegistry, /*syntaxOnlyOrLanguageServiceMode*/ false); + const languageService = createLanguageService( + hostAdapter, + this.documentRegistry, + /*syntaxOnlyOrLanguageServiceMode*/ false, + ); return new LanguageServiceShimObject(this, host, languageService); } catch (err) { diff --git a/src/services/signatureHelp.ts b/src/services/signatureHelp.ts index 7f8b86373d9f2..9a8ecb13d778c 100644 --- a/src/services/signatureHelp.ts +++ b/src/services/signatureHelp.ts @@ -121,7 +121,13 @@ interface ArgumentListInfo { } /** @internal */ -export function getSignatureHelpItems(program: Program, sourceFile: SourceFile, position: number, triggerReason: SignatureHelpTriggerReason | undefined, cancellationToken: CancellationToken): SignatureHelpItems | undefined { +export function getSignatureHelpItems( + program: Program, + sourceFile: SourceFile, + position: number, + triggerReason: SignatureHelpTriggerReason | undefined, + cancellationToken: CancellationToken, +): SignatureHelpItems | undefined { const typeChecker = program.getTypeChecker(); // Decide whether to show signature help @@ -135,7 +141,9 @@ export function getSignatureHelpItems(program: Program, sourceFile: SourceFile, const onlyUseSyntacticOwners = !!triggerReason && triggerReason.kind === "characterTyped"; // Bail out quickly in the middle of a string or comment, don't provide signature help unless the user explicitly requested it. - if (onlyUseSyntacticOwners && (isInString(sourceFile, position, startingToken) || isInComment(sourceFile, position))) { + if ( + onlyUseSyntacticOwners && (isInString(sourceFile, position, startingToken) || isInComment(sourceFile, position)) + ) { return undefined; } @@ -146,19 +154,35 @@ export function getSignatureHelpItems(program: Program, sourceFile: SourceFile, cancellationToken.throwIfCancellationRequested(); // Extra syntactic and semantic filtering of signature help - const candidateInfo = getCandidateOrTypeInfo(argumentInfo, typeChecker, sourceFile, startingToken, onlyUseSyntacticOwners); + const candidateInfo = getCandidateOrTypeInfo( + argumentInfo, + typeChecker, + sourceFile, + startingToken, + onlyUseSyntacticOwners, + ); cancellationToken.throwIfCancellationRequested(); if (!candidateInfo) { // We didn't have any sig help items produced by the TS compiler. If this is a JS // file, then see if we can figure out anything better. - return isSourceFileJS(sourceFile) ? createJSSignatureHelpItems(argumentInfo, program, cancellationToken) : undefined; + return isSourceFileJS(sourceFile) ? createJSSignatureHelpItems(argumentInfo, program, cancellationToken) + : undefined; } - return typeChecker.runWithCancellationToken(cancellationToken, typeChecker => - candidateInfo.kind === CandidateOrTypeKind.Candidate - ? createSignatureHelpItems(candidateInfo.candidates, candidateInfo.resolvedSignature, argumentInfo, sourceFile, typeChecker) - : createTypeHelpItems(candidateInfo.symbol, argumentInfo, sourceFile, typeChecker)); + return typeChecker.runWithCancellationToken( + cancellationToken, + typeChecker => + candidateInfo.kind === CandidateOrTypeKind.Candidate + ? createSignatureHelpItems( + candidateInfo.candidates, + candidateInfo.resolvedSignature, + argumentInfo, + sourceFile, + typeChecker, + ) + : createTypeHelpItems(candidateInfo.symbol, argumentInfo, sourceFile, typeChecker), + ); } const enum CandidateOrTypeKind { @@ -175,29 +199,49 @@ interface TypeInfo { readonly symbol: Symbol; } -function getCandidateOrTypeInfo({ invocation, argumentCount }: ArgumentListInfo, checker: TypeChecker, sourceFile: SourceFile, startingToken: Node, onlyUseSyntacticOwners: boolean): CandidateInfo | TypeInfo | undefined { +function getCandidateOrTypeInfo( + { invocation, argumentCount }: ArgumentListInfo, + checker: TypeChecker, + sourceFile: SourceFile, + startingToken: Node, + onlyUseSyntacticOwners: boolean, +): CandidateInfo | TypeInfo | undefined { switch (invocation.kind) { case InvocationKind.Call: { if (onlyUseSyntacticOwners && !isSyntacticOwner(startingToken, invocation.node, sourceFile)) { return undefined; } const candidates: Signature[] = []; - const resolvedSignature = checker.getResolvedSignatureForSignatureHelp(invocation.node, candidates, argumentCount)!; // TODO: GH#18217 - return candidates.length === 0 ? undefined : { kind: CandidateOrTypeKind.Candidate, candidates, resolvedSignature }; + const resolvedSignature = checker.getResolvedSignatureForSignatureHelp( + invocation.node, + candidates, + argumentCount, + )!; // TODO: GH#18217 + return candidates.length === 0 ? undefined + : { kind: CandidateOrTypeKind.Candidate, candidates, resolvedSignature }; } case InvocationKind.TypeArgs: { const { called } = invocation; - if (onlyUseSyntacticOwners && !containsPrecedingToken(startingToken, sourceFile, isIdentifier(called) ? called.parent : called)) { + if ( + onlyUseSyntacticOwners + && !containsPrecedingToken(startingToken, sourceFile, isIdentifier(called) ? called.parent : called) + ) { return undefined; } const candidates = getPossibleGenericSignatures(called, argumentCount, checker); - if (candidates.length !== 0) return { kind: CandidateOrTypeKind.Candidate, candidates, resolvedSignature: first(candidates) }; + if (candidates.length !== 0) { + return { kind: CandidateOrTypeKind.Candidate, candidates, resolvedSignature: first(candidates) }; + } const symbol = checker.getSymbolAtLocation(called); return symbol && { kind: CandidateOrTypeKind.Type, symbol }; } case InvocationKind.Contextual: - return { kind: CandidateOrTypeKind.Candidate, candidates: [invocation.signature], resolvedSignature: invocation.signature }; + return { + kind: CandidateOrTypeKind.Candidate, + candidates: [invocation.signature], + resolvedSignature: invocation.signature, + }; default: return Debug.assertNever(invocation); } @@ -220,31 +264,40 @@ function isSyntacticOwner(startingToken: Node, node: CallLikeExpression, sourceF } } -function createJSSignatureHelpItems(argumentInfo: ArgumentListInfo, program: Program, cancellationToken: CancellationToken): SignatureHelpItems | undefined { +function createJSSignatureHelpItems( + argumentInfo: ArgumentListInfo, + program: Program, + cancellationToken: CancellationToken, +): SignatureHelpItems | undefined { if (argumentInfo.invocation.kind === InvocationKind.Contextual) return undefined; // See if we can find some symbol with the call expression name that has call signatures. const expression = getExpressionFromInvocation(argumentInfo.invocation); const name = isPropertyAccessExpression(expression) ? expression.name.text : undefined; const typeChecker = program.getTypeChecker(); - return name === undefined ? undefined : firstDefined(program.getSourceFiles(), sourceFile => - firstDefined(sourceFile.getNamedDeclarations().get(name), declaration => { - const type = declaration.symbol && typeChecker.getTypeOfSymbolAtLocation(declaration.symbol, declaration); - const callSignatures = type && type.getCallSignatures(); - if (callSignatures && callSignatures.length) { - return typeChecker.runWithCancellationToken( - cancellationToken, - typeChecker => - createSignatureHelpItems( - callSignatures, - callSignatures[0], - argumentInfo, - sourceFile, - typeChecker, - /*useFullPrefix*/ true, - ), - ); - } - })); + return name === undefined ? undefined + : firstDefined( + program.getSourceFiles(), + sourceFile => + firstDefined(sourceFile.getNamedDeclarations().get(name), declaration => { + const type = declaration.symbol + && typeChecker.getTypeOfSymbolAtLocation(declaration.symbol, declaration); + const callSignatures = type && type.getCallSignatures(); + if (callSignatures && callSignatures.length) { + return typeChecker.runWithCancellationToken( + cancellationToken, + typeChecker => + createSignatureHelpItems( + callSignatures, + callSignatures[0], + argumentInfo, + sourceFile, + typeChecker, + /*useFullPrefix*/ true, + ), + ); + } + }), + ); } function containsPrecedingToken(startingToken: Node, sourceFile: SourceFile, container: Node) { @@ -272,13 +325,26 @@ export interface ArgumentInfoForCompletions { readonly argumentCount: number; } /** @internal */ -export function getArgumentInfoForCompletions(node: Node, position: number, sourceFile: SourceFile): ArgumentInfoForCompletions | undefined { +export function getArgumentInfoForCompletions( + node: Node, + position: number, + sourceFile: SourceFile, +): ArgumentInfoForCompletions | undefined { const info = getImmediatelyContainingArgumentInfo(node, position, sourceFile); return !info || info.isTypeParameterList || info.invocation.kind !== InvocationKind.Call ? undefined : { invocation: info.invocation.node, argumentCount: info.argumentCount, argumentIndex: info.argumentIndex }; } -function getArgumentOrParameterListInfo(node: Node, position: number, sourceFile: SourceFile): { readonly list: Node; readonly argumentIndex: number; readonly argumentCount: number; readonly argumentsSpan: TextSpan; } | undefined { +function getArgumentOrParameterListInfo( + node: Node, + position: number, + sourceFile: SourceFile, +): { + readonly list: Node; + readonly argumentIndex: number; + readonly argumentCount: number; + readonly argumentsSpan: TextSpan; +} | undefined { const info = getArgumentOrParameterListAndIndex(node, sourceFile); if (!info) return undefined; const { list, argumentIndex } = info; @@ -290,7 +356,10 @@ function getArgumentOrParameterListInfo(node: Node, position: number, sourceFile const argumentsSpan = getApplicableSpanForArguments(list, sourceFile); return { list, argumentIndex, argumentCount, argumentsSpan }; } -function getArgumentOrParameterListAndIndex(node: Node, sourceFile: SourceFile): { readonly list: Node; readonly argumentIndex: number; } | undefined { +function getArgumentOrParameterListAndIndex( + node: Node, + sourceFile: SourceFile, +): { readonly list: Node; readonly argumentIndex: number; } | undefined { if (node.kind === SyntaxKind.LessThanToken || node.kind === SyntaxKind.OpenParenToken) { // Find the list that starts right *after* the < or ( token. // If the user has just opened a list, consider this item 0. @@ -312,7 +381,11 @@ function getArgumentOrParameterListAndIndex(node: Node, sourceFile: SourceFile): * Returns relevant information for the argument list and the current argument if we are * in the argument of an invocation; returns undefined otherwise. */ -function getImmediatelyContainingArgumentInfo(node: Node, position: number, sourceFile: SourceFile): ArgumentListInfo | undefined { +function getImmediatelyContainingArgumentInfo( + node: Node, + position: number, + sourceFile: SourceFile, +): ArgumentListInfo | undefined { const { parent } = node; if (isCallOrNewExpression(parent)) { const invocation = parent; @@ -335,7 +408,13 @@ function getImmediatelyContainingArgumentInfo(node: Node, position: number, sour if (!info) return undefined; const { list, argumentIndex, argumentCount, argumentsSpan } = info; const isTypeParameterList = !!parent.typeArguments && parent.typeArguments.pos === list.pos; - return { isTypeParameterList, invocation: { kind: InvocationKind.Call, node: invocation }, argumentsSpan, argumentIndex, argumentCount }; + return { + isTypeParameterList, + invocation: { kind: InvocationKind.Call, node: invocation }, + argumentsSpan, + argumentIndex, + argumentCount, + }; } else if (isNoSubstitutionTemplateLiteral(node) && isTaggedTemplateExpression(parent)) { // Check if we're actually inside the template; @@ -390,14 +469,26 @@ function getImmediatelyContainingArgumentInfo(node: Node, position: number, sour const { called, nTypeArguments } = typeArgInfo; const invocation: Invocation = { kind: InvocationKind.TypeArgs, called }; const argumentsSpan = createTextSpanFromBounds(called.getStart(sourceFile), node.end); - return { isTypeParameterList: true, invocation, argumentsSpan, argumentIndex: nTypeArguments, argumentCount: nTypeArguments + 1 }; + return { + isTypeParameterList: true, + invocation, + argumentsSpan, + argumentIndex: nTypeArguments, + argumentCount: nTypeArguments + 1, + }; } return undefined; } } -function getImmediatelyContainingArgumentOrContextualParameterInfo(node: Node, position: number, sourceFile: SourceFile, checker: TypeChecker): ArgumentListInfo | undefined { - return tryGetParameterInfo(node, position, sourceFile, checker) || getImmediatelyContainingArgumentInfo(node, position, sourceFile); +function getImmediatelyContainingArgumentOrContextualParameterInfo( + node: Node, + position: number, + sourceFile: SourceFile, + checker: TypeChecker, +): ArgumentListInfo | undefined { + return tryGetParameterInfo(node, position, sourceFile, checker) + || getImmediatelyContainingArgumentInfo(node, position, sourceFile); } function getHighestBinary(b: BinaryExpression): BinaryExpression { @@ -408,7 +499,12 @@ function countBinaryExpressionParameters(b: BinaryExpression): number { return isBinaryExpression(b.left) ? countBinaryExpressionParameters(b.left) + 1 : 2; } -function tryGetParameterInfo(startingToken: Node, position: number, sourceFile: SourceFile, checker: TypeChecker): ArgumentListInfo | undefined { +function tryGetParameterInfo( + startingToken: Node, + position: number, + sourceFile: SourceFile, + checker: TypeChecker, +): ArgumentListInfo | undefined { const node = getAdjustedNode(startingToken); if (node === undefined) return undefined; @@ -425,7 +521,12 @@ function tryGetParameterInfo(startingToken: Node, position: number, sourceFile: const signature = lastOrUndefined(nonNullableContextualType.getCallSignatures()); if (signature === undefined) return undefined; - const invocation: ContextualInvocation = { kind: InvocationKind.Contextual, signature, node: startingToken, symbol: chooseBetterSymbol(symbol) }; + const invocation: ContextualInvocation = { + kind: InvocationKind.Contextual, + signature, + node: startingToken, + symbol: chooseBetterSymbol(symbol), + }; return { isTypeParameterList: false, invocation, argumentsSpan, argumentIndex, argumentCount }; } @@ -435,7 +536,11 @@ function getAdjustedNode(node: Node) { case SyntaxKind.CommaToken: return node; default: - return findAncestor(node.parent, n => isParameter(n) ? true : isBindingElement(n) || isObjectBindingPattern(n) || isArrayBindingPattern(n) ? false : "quit"); + return findAncestor( + node.parent, + n => isParameter(n) ? true + : isBindingElement(n) || isObjectBindingPattern(n) || isArrayBindingPattern(n) ? false : "quit", + ); } } @@ -445,7 +550,12 @@ interface ContextualSignatureLocationInfo { readonly argumentCount: number; readonly argumentsSpan: TextSpan; } -function getContextualSignatureLocationInfo(node: Node, sourceFile: SourceFile, position: number, checker: TypeChecker): ContextualSignatureLocationInfo | undefined { +function getContextualSignatureLocationInfo( + node: Node, + sourceFile: SourceFile, + position: number, + checker: TypeChecker, +): ContextualSignatureLocationInfo | undefined { const { parent } = node; switch (parent.kind) { case SyntaxKind.ParenthesizedExpression: @@ -455,14 +565,18 @@ function getContextualSignatureLocationInfo(node: Node, sourceFile: SourceFile, const info = getArgumentOrParameterListInfo(node, position, sourceFile); if (!info) return undefined; const { argumentIndex, argumentCount, argumentsSpan } = info; - const contextualType = isMethodDeclaration(parent) ? checker.getContextualTypeForObjectLiteralElement(parent) : checker.getContextualType(parent as ParenthesizedExpression | FunctionExpression | ArrowFunction); + const contextualType = isMethodDeclaration(parent) + ? checker.getContextualTypeForObjectLiteralElement(parent) + : checker.getContextualType(parent as ParenthesizedExpression | FunctionExpression | ArrowFunction); return contextualType && { contextualType, argumentIndex, argumentCount, argumentsSpan }; case SyntaxKind.BinaryExpression: { const highestBinary = getHighestBinary(parent as BinaryExpression); const contextualType = checker.getContextualType(highestBinary); - const argumentIndex = node.kind === SyntaxKind.OpenParenToken ? 0 : countBinaryExpressionParameters(parent as BinaryExpression) - 1; + const argumentIndex = node.kind === SyntaxKind.OpenParenToken ? 0 + : countBinaryExpressionParameters(parent as BinaryExpression) - 1; const argumentCount = countBinaryExpressionParameters(highestBinary); - return contextualType && { contextualType, argumentIndex, argumentCount, argumentsSpan: createTextSpanFromNode(parent) }; + return contextualType + && { contextualType, argumentIndex, argumentCount, argumentsSpan: createTextSpanFromNode(parent) }; } default: return undefined; @@ -472,7 +586,10 @@ function getContextualSignatureLocationInfo(node: Node, sourceFile: SourceFile, // The type of a function type node has a symbol at that node, but it's better to use the symbol for a parameter or type alias. function chooseBetterSymbol(s: Symbol): Symbol { return s.name === InternalSymbolName.Type - ? firstDefined(s.declarations, d => isFunctionTypeNode(d) ? tryCast(d.parent, canHaveSymbol)?.symbol : undefined) || s + ? firstDefined( + s.declarations, + d => isFunctionTypeNode(d) ? tryCast(d.parent, canHaveSymbol)?.symbol : undefined, + ) || s : s; } @@ -524,7 +641,12 @@ function getArgumentCount(argumentsList: Node, ignoreTrailingComma: boolean) { // spanIndex is either the index for a given template span. // This does not give appropriate results for a NoSubstitutionTemplateLiteral -function getArgumentIndexForTemplatePiece(spanIndex: number, node: Node, position: number, sourceFile: SourceFile): number { +function getArgumentIndexForTemplatePiece( + spanIndex: number, + node: Node, + position: number, + sourceFile: SourceFile, +): number { // Because the TemplateStringsArray is the first argument, we have to offset each substitution expression by 1. // There are three cases we can encounter: // 1. We are precisely in the template literal (argIndex = 0). @@ -548,9 +670,14 @@ function getArgumentIndexForTemplatePiece(spanIndex: number, node: Node, positio return spanIndex + 1; } -function getArgumentListInfoForTemplate(tagExpression: TaggedTemplateExpression, argumentIndex: number, sourceFile: SourceFile): ArgumentListInfo { +function getArgumentListInfoForTemplate( + tagExpression: TaggedTemplateExpression, + argumentIndex: number, + sourceFile: SourceFile, +): ArgumentListInfo { // argumentCount is either 1 or (numSpans + 1) to account for the template strings array argument. - const argumentCount = isNoSubstitutionTemplateLiteral(tagExpression.template) ? 1 : tagExpression.template.templateSpans.length + 1; + const argumentCount = isNoSubstitutionTemplateLiteral(tagExpression.template) ? 1 + : tagExpression.template.templateSpans.length + 1; if (argumentIndex !== 0) { Debug.assertLessThan(argumentIndex, argumentCount); } @@ -577,7 +704,10 @@ function getApplicableSpanForArguments(argumentsList: Node, sourceFile: SourceFi return createTextSpan(applicableSpanStart, applicableSpanEnd - applicableSpanStart); } -function getApplicableSpanForTaggedTemplate(taggedTemplate: TaggedTemplateExpression, sourceFile: SourceFile): TextSpan { +function getApplicableSpanForTaggedTemplate( + taggedTemplate: TaggedTemplateExpression, + sourceFile: SourceFile, +): TextSpan { const template = taggedTemplate.template; const applicableSpanStart = template.getStart(); let applicableSpanEnd = template.getEnd(); @@ -600,12 +730,27 @@ function getApplicableSpanForTaggedTemplate(taggedTemplate: TaggedTemplateExpres return createTextSpan(applicableSpanStart, applicableSpanEnd - applicableSpanStart); } -function getContainingArgumentInfo(node: Node, position: number, sourceFile: SourceFile, checker: TypeChecker, isManuallyInvoked: boolean): ArgumentListInfo | undefined { +function getContainingArgumentInfo( + node: Node, + position: number, + sourceFile: SourceFile, + checker: TypeChecker, + isManuallyInvoked: boolean, +): ArgumentListInfo | undefined { for (let n = node; !isSourceFile(n) && (isManuallyInvoked || !isBlock(n)); n = n.parent) { // If the node is not a subspan of its parent, this is a big problem. // There have been crashes that might be caused by this violation. - Debug.assert(rangeContainsRange(n.parent, n), "Not a subspan", () => `Child: ${Debug.formatSyntaxKind(n.kind)}, parent: ${Debug.formatSyntaxKind(n.parent.kind)}`); - const argumentInfo = getImmediatelyContainingArgumentOrContextualParameterInfo(n, position, sourceFile, checker); + Debug.assert( + rangeContainsRange(n.parent, n), + "Not a subspan", + () => `Child: ${Debug.formatSyntaxKind(n.kind)}, parent: ${Debug.formatSyntaxKind(n.parent.kind)}`, + ); + const argumentInfo = getImmediatelyContainingArgumentOrContextualParameterInfo( + n, + position, + sourceFile, + checker, + ); if (argumentInfo) { return argumentInfo; } @@ -620,15 +765,19 @@ function getChildListThatStartsWithOpenerToken(parent: Node, openerToken: Node, return children[indexOfOpenerToken + 1]; } -function getExpressionFromInvocation(invocation: CallInvocation | TypeArgsInvocation): Expression | JsxTagNameExpression { +function getExpressionFromInvocation( + invocation: CallInvocation | TypeArgsInvocation, +): Expression | JsxTagNameExpression { return invocation.kind === InvocationKind.Call ? getInvokedExpression(invocation.node) : invocation.called; } function getEnclosingDeclarationFromInvocation(invocation: Invocation): Node { - return invocation.kind === InvocationKind.Call ? invocation.node : invocation.kind === InvocationKind.TypeArgs ? invocation.called : invocation.node; + return invocation.kind === InvocationKind.Call ? invocation.node + : invocation.kind === InvocationKind.TypeArgs ? invocation.called : invocation.node; } -const signatureHelpNodeBuilderFlags = NodeBuilderFlags.OmitParameterModifiers | NodeBuilderFlags.IgnoreErrors | NodeBuilderFlags.UseAliasDefinedOutsideCurrentScope; +const signatureHelpNodeBuilderFlags = NodeBuilderFlags.OmitParameterModifiers | NodeBuilderFlags.IgnoreErrors + | NodeBuilderFlags.UseAliasDefinedOutsideCurrentScope; function createSignatureHelpItems( candidates: readonly Signature[], resolvedSignature: Signature, @@ -638,9 +787,28 @@ function createSignatureHelpItems( useFullPrefix?: boolean, ): SignatureHelpItems { const enclosingDeclaration = getEnclosingDeclarationFromInvocation(invocation); - const callTargetSymbol = invocation.kind === InvocationKind.Contextual ? invocation.symbol : (typeChecker.getSymbolAtLocation(getExpressionFromInvocation(invocation)) || useFullPrefix && resolvedSignature.declaration?.symbol); - const callTargetDisplayParts = callTargetSymbol ? symbolToDisplayParts(typeChecker, callTargetSymbol, useFullPrefix ? sourceFile : undefined, /*meaning*/ undefined) : emptyArray; - const items = map(candidates, candidateSignature => getSignatureHelpItem(candidateSignature, callTargetDisplayParts, isTypeParameterList, typeChecker, enclosingDeclaration, sourceFile)); + const callTargetSymbol = invocation.kind === InvocationKind.Contextual ? invocation.symbol + : (typeChecker.getSymbolAtLocation(getExpressionFromInvocation(invocation)) + || useFullPrefix && resolvedSignature.declaration?.symbol); + const callTargetDisplayParts = callTargetSymbol + ? symbolToDisplayParts( + typeChecker, + callTargetSymbol, + useFullPrefix ? sourceFile : undefined, + /*meaning*/ undefined, + ) : emptyArray; + const items = map( + candidates, + candidateSignature => + getSignatureHelpItem( + candidateSignature, + callTargetDisplayParts, + isTypeParameterList, + typeChecker, + enclosingDeclaration, + sourceFile, + ), + ); if (argumentIndex !== 0) { Debug.assertLessThan(argumentIndex, argumentCount); @@ -668,7 +836,13 @@ function createSignatureHelpItems( } Debug.assert(selectedItemIndex !== -1); // If candidates is non-empty it should always include bestSignature. We check for an empty candidates before calling this function. - const help = { items: flatMapToMutable(items, identity), applicableSpan, selectedItemIndex, argumentIndex, argumentCount }; + const help = { + items: flatMapToMutable(items, identity), + applicableSpan, + selectedItemIndex, + argumentIndex, + argumentCount, + }; const selected = help.items[selectedItemIndex]; if (selected.isVariadic) { const firstRest = findIndex(selected.parameters, p => !!p.isRest); @@ -691,36 +865,81 @@ function createTypeHelpItems( ): SignatureHelpItems | undefined { const typeParameters = checker.getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(symbol); if (!typeParameters) return undefined; - const items = [getTypeHelpItem(symbol, typeParameters, checker, getEnclosingDeclarationFromInvocation(invocation), sourceFile)]; + const items = [ + getTypeHelpItem(symbol, typeParameters, checker, getEnclosingDeclarationFromInvocation(invocation), sourceFile), + ]; return { items, applicableSpan, selectedItemIndex: 0, argumentIndex, argumentCount }; } -function getTypeHelpItem(symbol: Symbol, typeParameters: readonly TypeParameter[], checker: TypeChecker, enclosingDeclaration: Node, sourceFile: SourceFile): SignatureHelpItem { +function getTypeHelpItem( + symbol: Symbol, + typeParameters: readonly TypeParameter[], + checker: TypeChecker, + enclosingDeclaration: Node, + sourceFile: SourceFile, +): SignatureHelpItem { const typeSymbolDisplay = symbolToDisplayParts(checker, symbol); const printer = createPrinterWithRemoveComments(); - const parameters = typeParameters.map(t => createSignatureHelpParameterForTypeParameter(t, checker, enclosingDeclaration, sourceFile, printer)); + const parameters = typeParameters.map(t => + createSignatureHelpParameterForTypeParameter(t, checker, enclosingDeclaration, sourceFile, printer) + ); const documentation = symbol.getDocumentationComment(checker); const tags = symbol.getJsDocTags(checker); const prefixDisplayParts = [...typeSymbolDisplay, punctuationPart(SyntaxKind.LessThanToken)]; - return { isVariadic: false, prefixDisplayParts, suffixDisplayParts: [punctuationPart(SyntaxKind.GreaterThanToken)], separatorDisplayParts, parameters, documentation, tags }; + return { + isVariadic: false, + prefixDisplayParts, + suffixDisplayParts: [punctuationPart(SyntaxKind.GreaterThanToken)], + separatorDisplayParts, + parameters, + documentation, + tags, + }; } const separatorDisplayParts: SymbolDisplayPart[] = [punctuationPart(SyntaxKind.CommaToken), spacePart()]; -function getSignatureHelpItem(candidateSignature: Signature, callTargetDisplayParts: readonly SymbolDisplayPart[], isTypeParameterList: boolean, checker: TypeChecker, enclosingDeclaration: Node, sourceFile: SourceFile): SignatureHelpItem[] { - const infos = (isTypeParameterList ? itemInfoForTypeParameters : itemInfoForParameters)(candidateSignature, checker, enclosingDeclaration, sourceFile); +function getSignatureHelpItem( + candidateSignature: Signature, + callTargetDisplayParts: readonly SymbolDisplayPart[], + isTypeParameterList: boolean, + checker: TypeChecker, + enclosingDeclaration: Node, + sourceFile: SourceFile, +): SignatureHelpItem[] { + const infos = (isTypeParameterList ? itemInfoForTypeParameters : itemInfoForParameters)( + candidateSignature, + checker, + enclosingDeclaration, + sourceFile, + ); return map(infos, ({ isVariadic, parameters, prefix, suffix }) => { const prefixDisplayParts = [...callTargetDisplayParts, ...prefix]; - const suffixDisplayParts = [...suffix, ...returnTypeToDisplayParts(candidateSignature, enclosingDeclaration, checker)]; + const suffixDisplayParts = [ + ...suffix, + ...returnTypeToDisplayParts(candidateSignature, enclosingDeclaration, checker), + ]; const documentation = candidateSignature.getDocumentationComment(checker); const tags = candidateSignature.getJsDocTags(); - return { isVariadic, prefixDisplayParts, suffixDisplayParts, separatorDisplayParts, parameters, documentation, tags }; + return { + isVariadic, + prefixDisplayParts, + suffixDisplayParts, + separatorDisplayParts, + parameters, + documentation, + tags, + }; }); } -function returnTypeToDisplayParts(candidateSignature: Signature, enclosingDeclaration: Node, checker: TypeChecker): readonly SymbolDisplayPart[] { +function returnTypeToDisplayParts( + candidateSignature: Signature, + enclosingDeclaration: Node, + checker: TypeChecker, +): readonly SymbolDisplayPart[] { return mapToDisplayParts(writer => { writer.writePunctuation(":"); writer.writeSpace(" "); @@ -729,7 +948,12 @@ function returnTypeToDisplayParts(candidateSignature: Signature, enclosingDeclar checker.writeTypePredicate(predicate, enclosingDeclaration, /*flags*/ undefined, writer); } else { - checker.writeType(checker.getReturnTypeOfSignature(candidateSignature), enclosingDeclaration, /*flags*/ undefined, writer); + checker.writeType( + checker.getReturnTypeOfSignature(candidateSignature), + enclosingDeclaration, + /*flags*/ undefined, + writer, + ); } }); } @@ -741,55 +965,128 @@ interface SignatureHelpItemInfo { readonly suffix: readonly SymbolDisplayPart[]; } -function itemInfoForTypeParameters(candidateSignature: Signature, checker: TypeChecker, enclosingDeclaration: Node, sourceFile: SourceFile): SignatureHelpItemInfo[] { +function itemInfoForTypeParameters( + candidateSignature: Signature, + checker: TypeChecker, + enclosingDeclaration: Node, + sourceFile: SourceFile, +): SignatureHelpItemInfo[] { const typeParameters = (candidateSignature.target || candidateSignature).typeParameters; const printer = createPrinterWithRemoveComments(); - const parameters = (typeParameters || emptyArray).map(t => createSignatureHelpParameterForTypeParameter(t, checker, enclosingDeclaration, sourceFile, printer)); - const thisParameter = candidateSignature.thisParameter ? [checker.symbolToParameterDeclaration(candidateSignature.thisParameter, enclosingDeclaration, signatureHelpNodeBuilderFlags)!] : []; + const parameters = (typeParameters || emptyArray).map(t => + createSignatureHelpParameterForTypeParameter(t, checker, enclosingDeclaration, sourceFile, printer) + ); + const thisParameter = candidateSignature.thisParameter + ? [ + checker.symbolToParameterDeclaration( + candidateSignature.thisParameter, + enclosingDeclaration, + signatureHelpNodeBuilderFlags, + )!, + ] : []; return checker.getExpandedParameters(candidateSignature).map(paramList => { - const params = factory.createNodeArray([...thisParameter, ...map(paramList, param => checker.symbolToParameterDeclaration(param, enclosingDeclaration, signatureHelpNodeBuilderFlags)!)]); + const params = factory.createNodeArray([ + ...thisParameter, + ...map( + paramList, + param => + checker.symbolToParameterDeclaration(param, enclosingDeclaration, signatureHelpNodeBuilderFlags)!, + ), + ]); const parameterParts = mapToDisplayParts(writer => { printer.writeList(ListFormat.CallExpressionArguments, params, sourceFile, writer); }); - return { isVariadic: false, parameters, prefix: [punctuationPart(SyntaxKind.LessThanToken)], suffix: [punctuationPart(SyntaxKind.GreaterThanToken), ...parameterParts] }; + return { + isVariadic: false, + parameters, + prefix: [punctuationPart(SyntaxKind.LessThanToken)], + suffix: [punctuationPart(SyntaxKind.GreaterThanToken), ...parameterParts], + }; }); } -function itemInfoForParameters(candidateSignature: Signature, checker: TypeChecker, enclosingDeclaration: Node, sourceFile: SourceFile): SignatureHelpItemInfo[] { +function itemInfoForParameters( + candidateSignature: Signature, + checker: TypeChecker, + enclosingDeclaration: Node, + sourceFile: SourceFile, +): SignatureHelpItemInfo[] { const printer = createPrinterWithRemoveComments(); const typeParameterParts = mapToDisplayParts(writer => { if (candidateSignature.typeParameters && candidateSignature.typeParameters.length) { - const args = factory.createNodeArray(candidateSignature.typeParameters.map(p => checker.typeParameterToDeclaration(p, enclosingDeclaration, signatureHelpNodeBuilderFlags)!)); + const args = factory.createNodeArray( + candidateSignature.typeParameters.map(p => + checker.typeParameterToDeclaration(p, enclosingDeclaration, signatureHelpNodeBuilderFlags)! + ), + ); printer.writeList(ListFormat.TypeParameters, args, sourceFile, writer); } }); const lists = checker.getExpandedParameters(candidateSignature); - const isVariadic: (parameterList: readonly Symbol[]) => boolean = !checker.hasEffectiveRestParameter(candidateSignature) ? _ => false - : lists.length === 1 ? _ => true - : pList => !!(pList.length && tryCast(pList[pList.length - 1], isTransientSymbol)?.links.checkFlags! & CheckFlags.RestParameter); + const isVariadic: (parameterList: readonly Symbol[]) => boolean = + !checker.hasEffectiveRestParameter(candidateSignature) ? _ => false + : lists.length === 1 ? _ => true + : pList => + !!(pList.length + && tryCast(pList[pList.length - 1], isTransientSymbol)?.links.checkFlags! + & CheckFlags.RestParameter); return lists.map(parameterList => ({ isVariadic: isVariadic(parameterList), - parameters: parameterList.map(p => createSignatureHelpParameterForParameter(p, checker, enclosingDeclaration, sourceFile, printer)), + parameters: parameterList.map(p => + createSignatureHelpParameterForParameter(p, checker, enclosingDeclaration, sourceFile, printer) + ), prefix: [...typeParameterParts, punctuationPart(SyntaxKind.OpenParenToken)], suffix: [punctuationPart(SyntaxKind.CloseParenToken)], })); } -function createSignatureHelpParameterForParameter(parameter: Symbol, checker: TypeChecker, enclosingDeclaration: Node, sourceFile: SourceFile, printer: Printer): SignatureHelpParameter { +function createSignatureHelpParameterForParameter( + parameter: Symbol, + checker: TypeChecker, + enclosingDeclaration: Node, + sourceFile: SourceFile, + printer: Printer, +): SignatureHelpParameter { const displayParts = mapToDisplayParts(writer => { - const param = checker.symbolToParameterDeclaration(parameter, enclosingDeclaration, signatureHelpNodeBuilderFlags)!; + const param = checker.symbolToParameterDeclaration( + parameter, + enclosingDeclaration, + signatureHelpNodeBuilderFlags, + )!; printer.writeNode(EmitHint.Unspecified, param, sourceFile, writer); }); const isOptional = checker.isOptionalParameter(parameter.valueDeclaration as ParameterDeclaration); const isRest = isTransientSymbol(parameter) && !!(parameter.links.checkFlags & CheckFlags.RestParameter); - return { name: parameter.name, documentation: parameter.getDocumentationComment(checker), displayParts, isOptional, isRest }; + return { + name: parameter.name, + documentation: parameter.getDocumentationComment(checker), + displayParts, + isOptional, + isRest, + }; } -function createSignatureHelpParameterForTypeParameter(typeParameter: TypeParameter, checker: TypeChecker, enclosingDeclaration: Node, sourceFile: SourceFile, printer: Printer): SignatureHelpParameter { +function createSignatureHelpParameterForTypeParameter( + typeParameter: TypeParameter, + checker: TypeChecker, + enclosingDeclaration: Node, + sourceFile: SourceFile, + printer: Printer, +): SignatureHelpParameter { const displayParts = mapToDisplayParts(writer => { - const param = checker.typeParameterToDeclaration(typeParameter, enclosingDeclaration, signatureHelpNodeBuilderFlags)!; + const param = checker.typeParameterToDeclaration( + typeParameter, + enclosingDeclaration, + signatureHelpNodeBuilderFlags, + )!; printer.writeNode(EmitHint.Unspecified, param, sourceFile, writer); }); - return { name: typeParameter.symbol.name, documentation: typeParameter.symbol.getDocumentationComment(checker), displayParts, isOptional: false, isRest: false }; + return { + name: typeParameter.symbol.name, + documentation: typeParameter.symbol.getDocumentationComment(checker), + displayParts, + isOptional: false, + isRest: false, + }; } diff --git a/src/services/smartSelection.ts b/src/services/smartSelection.ts index d1cc5ca92472b..6df68e7df5dbd 100644 --- a/src/services/smartSelection.ts +++ b/src/services/smartSelection.ts @@ -76,7 +76,8 @@ export function getSmartSelectionRange(pos: number, sourceFile: SourceFile): Sel if (positionShouldSnapToNode(sourceFile, pos, node)) { if ( isFunctionBody(node) - && isFunctionLikeDeclaration(parentNode) && !positionsAreOnSameLine(node.getStart(sourceFile), node.getEnd(), sourceFile) + && isFunctionLikeDeclaration(parentNode) + && !positionsAreOnSameLine(node.getStart(sourceFile), node.getEnd(), sourceFile) ) { pushSelectionRange(node.getStart(sourceFile), node.getEnd()); } @@ -109,7 +110,8 @@ export function getSmartSelectionRange(pos: number, sourceFile: SourceFile): Sel // Blocks with braces, brackets, parens, or JSX tags on separate lines should be // selected from open to close, including whitespace but not including the braces/etc. themselves. - const isBetweenMultiLineBookends = isSyntaxList(node) && isListOpener(prevNode) && isListCloser(nextNode) + const isBetweenMultiLineBookends = isSyntaxList(node) && isListOpener(prevNode) + && isListCloser(nextNode) && !positionsAreOnSameLine(prevNode.getStart(), nextNode.getStart(), sourceFile); let start = isBetweenMultiLineBookends ? prevNode.getEnd() : node.getStart(); const end = isBetweenMultiLineBookends ? nextNode.getStart() : getEndPos(sourceFile, node); @@ -125,7 +127,10 @@ export function getSmartSelectionRange(pos: number, sourceFile: SourceFile): Sel // covering the JSDoc comment before diving further. if (isSyntaxList(node)) { const firstChild = node.getChildren()[0]; - if (firstChild && hasJSDocNodes(firstChild) && firstChild.jsDoc?.length && firstChild.getStart() !== node.pos) { + if ( + firstChild && hasJSDocNodes(firstChild) && firstChild.jsDoc?.length + && firstChild.getStart() !== node.pos + ) { start = Math.min(start, first(firstChild.jsDoc).getStart()); } } @@ -158,9 +163,9 @@ export function getSmartSelectionRange(pos: number, sourceFile: SourceFile): Sel if ( !selectionRange || ( // Skip ranges that are identical to the parent - !textSpansEqual(textSpan, selectionRange.textSpan) && + !textSpansEqual(textSpan, selectionRange.textSpan) // Skip ranges that don't contain the original position - textSpanIntersectsWithPosition(textSpan, pos) + && textSpanIntersectsWithPosition(textSpan, pos) ) ) { selectionRange = { textSpan, ...selectionRange && { parent: selectionRange } }; @@ -235,14 +240,20 @@ function getSelectionChildren(node: Node): readonly Node[] { Debug.assertEqual(openBraceToken.kind, SyntaxKind.OpenBraceToken); Debug.assertEqual(closeBraceToken.kind, SyntaxKind.CloseBraceToken); // Group `-/+readonly` and `-/+?` - const groupedWithPlusMinusTokens = groupChildren(children, child => - child === node.readonlyToken || child.kind === SyntaxKind.ReadonlyKeyword || - child === node.questionToken || child.kind === SyntaxKind.QuestionToken); + const groupedWithPlusMinusTokens = groupChildren( + children, + child => + child === node.readonlyToken || child.kind === SyntaxKind.ReadonlyKeyword + || child === node.questionToken || child.kind === SyntaxKind.QuestionToken, + ); // Group type parameter with surrounding brackets - const groupedWithBrackets = groupChildren(groupedWithPlusMinusTokens, ({ kind }) => - kind === SyntaxKind.OpenBracketToken || - kind === SyntaxKind.TypeParameter || - kind === SyntaxKind.CloseBracketToken); + const groupedWithBrackets = groupChildren( + groupedWithPlusMinusTokens, + ({ kind }) => + kind === SyntaxKind.OpenBracketToken + || kind === SyntaxKind.TypeParameter + || kind === SyntaxKind.CloseBracketToken, + ); return [ openBraceToken, // Pivot on `:` @@ -253,7 +264,10 @@ function getSelectionChildren(node: Node): readonly Node[] { // Group modifiers and property name, then pivot on `:`. if (isPropertySignature(node)) { - const children = groupChildren(node.getChildren(), child => child === node.name || contains(node.modifiers, child)); + const children = groupChildren( + node.getChildren(), + child => child === node.name || contains(node.modifiers, child), + ); const firstJSDocChild = children[0]?.kind === SyntaxKind.JSDoc ? children[0] : undefined; const withJSDocSeparated = firstJSDocChild ? children.slice(1) : children; const splittedChildren = splitChildren(withJSDocSeparated, ({ kind }) => kind === SyntaxKind.ColonToken); @@ -262,8 +276,14 @@ function getSelectionChildren(node: Node): readonly Node[] { // Group the parameter name with its `...`, then that group with its `?`, then pivot on `=`. if (isParameter(node)) { - const groupedDotDotDotAndName = groupChildren(node.getChildren(), child => child === node.dotDotDotToken || child === node.name); - const groupedWithQuestionToken = groupChildren(groupedDotDotDotAndName, child => child === groupedDotDotDotAndName[0] || child === node.questionToken); + const groupedDotDotDotAndName = groupChildren( + node.getChildren(), + child => child === node.dotDotDotToken || child === node.name, + ); + const groupedWithQuestionToken = groupChildren( + groupedDotDotDotAndName, + child => child === groupedDotDotDotAndName[0] || child === node.questionToken, + ); return splitChildren(groupedWithQuestionToken, ({ kind }) => kind === SyntaxKind.EqualsToken); } diff --git a/src/services/sourcemaps.ts b/src/services/sourcemaps.ts index 72947635e6ae0..703249e014e43 100644 --- a/src/services/sourcemaps.ts +++ b/src/services/sourcemaps.ts @@ -109,9 +109,15 @@ export function getSourceMapper(host: SourceMapperHost): SourceMapper { const options = program.getCompilerOptions(); const outPath = outFile(options); - const declarationPath = outPath ? - removeFileExtension(outPath) + Extension.Dts : - getDeclarationEmitOutputFilePathWorker(info.fileName, program.getCompilerOptions(), currentDirectory, program.getCommonSourceDirectory(), getCanonicalFileName); + const declarationPath = outPath + ? removeFileExtension(outPath) + Extension.Dts + : getDeclarationEmitOutputFilePathWorker( + info.fileName, + program.getCompilerOptions(), + currentDirectory, + program.getCommonSourceDirectory(), + getCanonicalFileName, + ); if (declarationPath === undefined) return undefined; const newLoc = getDocumentPositionMapper(declarationPath, info.fileName).getGeneratedPosition(info); @@ -147,9 +153,9 @@ export function getSourceMapper(host: SourceMapperHost): SourceMapper { // This can be called from source mapper in either source program or program that includes generated file function getSourceFileLike(fileName: string) { - return !host.getSourceFileLike ? - getSourceFile(fileName) || getOrCreateSourceFileLike(fileName) : - host.getSourceFileLike(fileName); + return !host.getSourceFileLike + ? getSourceFile(fileName) || getOrCreateSourceFileLike(fileName) + : host.getSourceFileLike(fileName); } function toLineColumnOffset(fileName: string, position: number): LineAndCharacter { @@ -169,7 +175,10 @@ export function getSourceMapper(host: SourceMapperHost): SourceMapper { * * @internal */ -export type ReadMapFile = (mapFileName: string, mapFileNameFromDts: string | undefined) => string | undefined | DocumentPositionMapper | false; +export type ReadMapFile = ( + mapFileName: string, + mapFileNameFromDts: string | undefined, +) => string | undefined | DocumentPositionMapper | false; /** @internal */ export function getDocumentPositionMapper( @@ -195,7 +204,8 @@ export function getDocumentPositionMapper( possibleMapLocations.push(mapFileName); } possibleMapLocations.push(generatedFileName + ".map"); - const originalMapFileName = mapFileName && getNormalizedAbsolutePath(mapFileName, getDirectoryPath(generatedFileName)); + const originalMapFileName = mapFileName + && getNormalizedAbsolutePath(mapFileName, getDirectoryPath(generatedFileName)); for (const location of possibleMapLocations) { const mapFileName = getNormalizedAbsolutePath(location, getDirectoryPath(generatedFileName)); const mapFileContents = readMapFile(mapFileName, originalMapFileName); diff --git a/src/services/stringCompletions.ts b/src/services/stringCompletions.ts index 657f104418fa5..97b7de9a9412a 100644 --- a/src/services/stringCompletions.ts +++ b/src/services/stringCompletions.ts @@ -205,8 +205,27 @@ export function getStringLiteralCompletions( } if (isInString(sourceFile, position, contextToken)) { if (!contextToken || !isStringLiteralLike(contextToken)) return undefined; - const entries = getStringLiteralCompletionEntries(sourceFile, contextToken, position, program.getTypeChecker(), options, host, preferences); - return convertStringLiteralCompletions(entries, contextToken, sourceFile, host, program, log, options, preferences, position, includeSymbol); + const entries = getStringLiteralCompletionEntries( + sourceFile, + contextToken, + position, + program.getTypeChecker(), + options, + host, + preferences, + ); + return convertStringLiteralCompletions( + entries, + contextToken, + sourceFile, + host, + program, + log, + options, + preferences, + position, + includeSymbol, + ); } } @@ -260,7 +279,13 @@ function convertStringLiteralCompletions( /*isRightOfOpenTag*/ undefined, includeSymbol, ); // Target will not be used, so arbitrary - return { isGlobalCompletion: false, isMemberCompletion: true, isNewIdentifierLocation: completion.hasIndexSignature, optionalReplacementSpan, entries }; + return { + isGlobalCompletion: false, + isMemberCompletion: true, + isNewIdentifierLocation: completion.hasIndexSignature, + optionalReplacementSpan, + entries, + }; } case StringLiteralCompletionKind.Types: { const entries = completion.types.map(type => ({ @@ -270,7 +295,13 @@ function convertStringLiteralCompletions( sortText: SortText.LocationPriority, replacementSpan: getReplacementSpanForContextToken(contextToken), })); - return { isGlobalCompletion: false, isMemberCompletion: false, isNewIdentifierLocation: completion.isNewIdentifier, optionalReplacementSpan, entries }; + return { + isGlobalCompletion: false, + isMemberCompletion: false, + isNewIdentifierLocation: completion.isNewIdentifier, + optionalReplacementSpan, + entries, + }; } default: return Debug.assertNever(completion); @@ -278,24 +309,64 @@ function convertStringLiteralCompletions( } /** @internal */ -export function getStringLiteralCompletionDetails(name: string, sourceFile: SourceFile, position: number, contextToken: Node | undefined, checker: TypeChecker, options: CompilerOptions, host: LanguageServiceHost, cancellationToken: CancellationToken, preferences: UserPreferences) { +export function getStringLiteralCompletionDetails( + name: string, + sourceFile: SourceFile, + position: number, + contextToken: Node | undefined, + checker: TypeChecker, + options: CompilerOptions, + host: LanguageServiceHost, + cancellationToken: CancellationToken, + preferences: UserPreferences, +) { if (!contextToken || !isStringLiteralLike(contextToken)) return undefined; - const completions = getStringLiteralCompletionEntries(sourceFile, contextToken, position, checker, options, host, preferences); - return completions && stringLiteralCompletionDetails(name, contextToken, completions, sourceFile, checker, cancellationToken); + const completions = getStringLiteralCompletionEntries( + sourceFile, + contextToken, + position, + checker, + options, + host, + preferences, + ); + return completions + && stringLiteralCompletionDetails(name, contextToken, completions, sourceFile, checker, cancellationToken); } -function stringLiteralCompletionDetails(name: string, location: Node, completion: StringLiteralCompletion, sourceFile: SourceFile, checker: TypeChecker, cancellationToken: CancellationToken): CompletionEntryDetails | undefined { +function stringLiteralCompletionDetails( + name: string, + location: Node, + completion: StringLiteralCompletion, + sourceFile: SourceFile, + checker: TypeChecker, + cancellationToken: CancellationToken, +): CompletionEntryDetails | undefined { switch (completion.kind) { case StringLiteralCompletionKind.Paths: { const match = find(completion.paths, p => p.name === name); - return match && createCompletionDetails(name, kindModifiersFromExtension(match.extension), match.kind, [textPart(name)]); + return match + && createCompletionDetails(name, kindModifiersFromExtension(match.extension), match.kind, [ + textPart(name), + ]); } case StringLiteralCompletionKind.Properties: { const match = find(completion.symbols, s => s.name === name); - return match && createCompletionDetailsForSymbol(match, match.name, checker, sourceFile, location, cancellationToken); + return match + && createCompletionDetailsForSymbol( + match, + match.name, + checker, + sourceFile, + location, + cancellationToken, + ); } case StringLiteralCompletionKind.Types: - return find(completion.types, t => t.value === name) ? createCompletionDetails(name, ScriptElementKindModifier.none, ScriptElementKind.string, [textPart(name)]) : undefined; + return find(completion.types, t => t.value === name) + ? createCompletionDetails(name, ScriptElementKindModifier.none, ScriptElementKind.string, [ + textPart(name), + ]) : undefined; default: return Debug.assertNever(completion); } @@ -304,7 +375,13 @@ function stringLiteralCompletionDetails(name: string, location: Node, completion function convertPathCompletions(pathCompletions: readonly PathCompletion[]): CompletionInfo { const isGlobalCompletion = false; // We don't want the editor to offer any other completions, such as snippets, inside a comment. const isNewIdentifierLocation = true; // The user may type in a path that doesn't yet exist, creating a "new identifier" with respect to the collection of identifiers the server is aware of. - const entries = pathCompletions.map(({ name, kind, span, extension }): CompletionEntry => ({ name, kind, kindModifiers: kindModifiersFromExtension(extension), sortText: SortText.LocationPriority, replacementSpan: span })); + const entries = pathCompletions.map(({ name, kind, span, extension }): CompletionEntry => ({ + name, + kind, + kindModifiers: kindModifiersFromExtension(extension), + sortText: SortText.LocationPriority, + replacementSpan: span, + })); return { isGlobalCompletion, isMemberCompletion: false, isNewIdentifierLocation, entries }; } function kindModifiersFromExtension(extension: Extension | undefined): ScriptElementKindModifier { @@ -357,14 +434,35 @@ interface StringLiteralCompletionsFromTypes { readonly types: readonly StringLiteralType[]; readonly isNewIdentifier: boolean; } -type StringLiteralCompletion = { readonly kind: StringLiteralCompletionKind.Paths; readonly paths: readonly PathCompletion[]; } | StringLiteralCompletionsFromProperties | StringLiteralCompletionsFromTypes; -function getStringLiteralCompletionEntries(sourceFile: SourceFile, node: StringLiteralLike, position: number, typeChecker: TypeChecker, compilerOptions: CompilerOptions, host: LanguageServiceHost, preferences: UserPreferences): StringLiteralCompletion | undefined { +type StringLiteralCompletion = + | { readonly kind: StringLiteralCompletionKind.Paths; readonly paths: readonly PathCompletion[]; } + | StringLiteralCompletionsFromProperties + | StringLiteralCompletionsFromTypes; +function getStringLiteralCompletionEntries( + sourceFile: SourceFile, + node: StringLiteralLike, + position: number, + typeChecker: TypeChecker, + compilerOptions: CompilerOptions, + host: LanguageServiceHost, + preferences: UserPreferences, +): StringLiteralCompletion | undefined { const parent = walkUpParentheses(node.parent); switch (parent.kind) { case SyntaxKind.LiteralType: { const grandParent = walkUpParentheses(parent.parent); if (grandParent.kind === SyntaxKind.ImportType) { - return { kind: StringLiteralCompletionKind.Paths, paths: getStringLiteralCompletionsFromModuleNames(sourceFile, node, compilerOptions, host, typeChecker, preferences) }; + return { + kind: StringLiteralCompletionKind.Paths, + paths: getStringLiteralCompletionsFromModuleNames( + sourceFile, + node, + compilerOptions, + host, + typeChecker, + preferences, + ), + }; } return fromUnionableLiteralType(grandParent); } @@ -404,11 +502,28 @@ function getStringLiteralCompletionEntries(sourceFile: SourceFile, node: StringL case SyntaxKind.NewExpression: case SyntaxKind.JsxAttribute: if (!isRequireCallArgument(node) && !isImportCall(parent)) { - const argumentInfo = SignatureHelp.getArgumentInfoForCompletions(parent.kind === SyntaxKind.JsxAttribute ? parent.parent : node, position, sourceFile); + const argumentInfo = SignatureHelp.getArgumentInfoForCompletions( + parent.kind === SyntaxKind.JsxAttribute ? parent.parent : node, + position, + sourceFile, + ); // Get string literal completions from specialized signatures of the target // i.e. declare function f(a: 'A'); // f("/*completion position*/") - return argumentInfo && (getStringLiteralCompletionsFromSignature(argumentInfo.invocation, node, argumentInfo, typeChecker) || getStringLiteralCompletionsFromSignature(argumentInfo.invocation, node, argumentInfo, typeChecker, CheckMode.Normal)) || fromContextualType(ContextFlags.None); + return argumentInfo + && (getStringLiteralCompletionsFromSignature( + argumentInfo.invocation, + node, + argumentInfo, + typeChecker, + ) + || getStringLiteralCompletionsFromSignature( + argumentInfo.invocation, + node, + argumentInfo, + typeChecker, + CheckMode.Normal, + )) || fromContextualType(ContextFlags.None); } // falls through (is `require("")` or `require(""` or `import("")`) @@ -421,7 +536,17 @@ function getStringLiteralCompletionEntries(sourceFile: SourceFile, node: StringL // import x = require("/*completion position*/"); // var y = require("/*completion position*/"); // export * from "/*completion position*/"; - return { kind: StringLiteralCompletionKind.Paths, paths: getStringLiteralCompletionsFromModuleNames(sourceFile, node, compilerOptions, host, typeChecker, preferences) }; + return { + kind: StringLiteralCompletionKind.Paths, + paths: getStringLiteralCompletionsFromModuleNames( + sourceFile, + node, + compilerOptions, + host, + typeChecker, + preferences, + ), + }; case SyntaxKind.CaseClause: const tracker = newCaseClauseTracker(typeChecker, (parent as CaseClause).parent.clauses); const contextualTypes = fromContextualType(); @@ -434,13 +559,19 @@ function getStringLiteralCompletionEntries(sourceFile: SourceFile, node: StringL return fromContextualType() || fromContextualType(ContextFlags.None); } - function fromUnionableLiteralType(grandParent: Node): StringLiteralCompletionsFromTypes | StringLiteralCompletionsFromProperties | undefined { + function fromUnionableLiteralType( + grandParent: Node, + ): StringLiteralCompletionsFromTypes | StringLiteralCompletionsFromProperties | undefined { switch (grandParent.kind) { case SyntaxKind.ExpressionWithTypeArguments: case SyntaxKind.TypeReference: { const typeArgument = findAncestor(parent, n => n.parent === grandParent) as LiteralTypeNode; if (typeArgument) { - return { kind: StringLiteralCompletionKind.Types, types: getStringLiteralTypes(typeChecker.getTypeArgumentConstraint(typeArgument)), isNewIdentifier: false }; + return { + kind: StringLiteralCompletionKind.Types, + types: getStringLiteralTypes(typeChecker.getTypeArgumentConstraint(typeArgument)), + isNewIdentifier: false, + }; } return undefined; } @@ -461,18 +592,31 @@ function getStringLiteralCompletionEntries(sourceFile: SourceFile, node: StringL if (!result) { return undefined; } - const alreadyUsedTypes = getAlreadyUsedTypesInStringLiteralUnion(grandParent as UnionTypeNode, parent as LiteralTypeNode); + const alreadyUsedTypes = getAlreadyUsedTypesInStringLiteralUnion( + grandParent as UnionTypeNode, + parent as LiteralTypeNode, + ); if (result.kind === StringLiteralCompletionKind.Properties) { - return { kind: StringLiteralCompletionKind.Properties, symbols: result.symbols.filter(sym => !contains(alreadyUsedTypes, sym.name)), hasIndexSignature: result.hasIndexSignature }; + return { + kind: StringLiteralCompletionKind.Properties, + symbols: result.symbols.filter(sym => !contains(alreadyUsedTypes, sym.name)), + hasIndexSignature: result.hasIndexSignature, + }; } - return { kind: StringLiteralCompletionKind.Types, types: result.types.filter(t => !contains(alreadyUsedTypes, t.value)), isNewIdentifier: false }; + return { + kind: StringLiteralCompletionKind.Types, + types: result.types.filter(t => !contains(alreadyUsedTypes, t.value)), + isNewIdentifier: false, + }; } default: return undefined; } } - function fromContextualType(contextFlags: ContextFlags = ContextFlags.Completions): StringLiteralCompletionsFromTypes | undefined { + function fromContextualType( + contextFlags: ContextFlags = ContextFlags.Completions, + ): StringLiteralCompletionsFromTypes | undefined { // Get completion for string literal from string literal type // i.e. var x: "hi" | "hello" = "/*completion position*/" const types = getStringLiteralTypes(getContextualTypeFromParent(node, typeChecker, contextFlags)); @@ -495,20 +639,35 @@ function walkUpParentheses(node: Node) { } function getAlreadyUsedTypesInStringLiteralUnion(union: UnionTypeNode, current: LiteralTypeNode): readonly string[] { - return mapDefined(union.types, type => type !== current && isLiteralTypeNode(type) && isStringLiteral(type.literal) ? type.literal.text : undefined); + return mapDefined( + union.types, + type => + type !== current && isLiteralTypeNode(type) && isStringLiteral(type.literal) ? type.literal.text + : undefined, + ); } -function getStringLiteralCompletionsFromSignature(call: CallLikeExpression, arg: StringLiteralLike, argumentInfo: SignatureHelp.ArgumentInfoForCompletions, checker: TypeChecker, checkMode = CheckMode.IsForStringLiteralArgumentCompletions): StringLiteralCompletionsFromTypes | undefined { +function getStringLiteralCompletionsFromSignature( + call: CallLikeExpression, + arg: StringLiteralLike, + argumentInfo: SignatureHelp.ArgumentInfoForCompletions, + checker: TypeChecker, + checkMode = CheckMode.IsForStringLiteralArgumentCompletions, +): StringLiteralCompletionsFromTypes | undefined { let isNewIdentifier = false; const uniques = new Map(); const candidates: Signature[] = []; - const editingArgument = isJsxOpeningLikeElement(call) ? Debug.checkDefined(findAncestor(arg.parent, isJsxAttribute)) : arg; + const editingArgument = isJsxOpeningLikeElement(call) ? Debug.checkDefined(findAncestor(arg.parent, isJsxAttribute)) + : arg; checker.getResolvedSignatureForStringLiteralCompletions(call, editingArgument, candidates, checkMode); const types = flatMap(candidates, candidate => { if (!signatureHasRestParameter(candidate) && argumentInfo.argumentCount > candidate.parameters.length) return; let type = candidate.getTypeParameterAtPosition(argumentInfo.argumentIndex); if (isJsxOpeningLikeElement(call)) { - const propType = checker.getTypeOfPropertyOfType(type, getTextOfJsxAttributeName((editingArgument as JsxAttribute).name)); + const propType = checker.getTypeOfPropertyOfType( + type, + getTextOfJsxAttributeName((editingArgument as JsxAttribute).name), + ); if (propType) { type = propType; } @@ -519,15 +678,23 @@ function getStringLiteralCompletionsFromSignature(call: CallLikeExpression, arg: return length(types) ? { kind: StringLiteralCompletionKind.Types, types, isNewIdentifier } : undefined; } -function stringLiteralCompletionsFromProperties(type: Type | undefined): StringLiteralCompletionsFromProperties | undefined { +function stringLiteralCompletionsFromProperties( + type: Type | undefined, +): StringLiteralCompletionsFromProperties | undefined { return type && { kind: StringLiteralCompletionKind.Properties, - symbols: filter(type.getApparentProperties(), prop => !(prop.valueDeclaration && isPrivateIdentifierClassElementDeclaration(prop.valueDeclaration))), + symbols: filter( + type.getApparentProperties(), + prop => !(prop.valueDeclaration && isPrivateIdentifierClassElementDeclaration(prop.valueDeclaration)), + ), hasIndexSignature: hasIndexSignature(type), }; } -function stringLiteralCompletionsForObjectLiteral(checker: TypeChecker, objectLiteralExpression: ObjectLiteralExpression): StringLiteralCompletionsFromProperties | undefined { +function stringLiteralCompletionsForObjectLiteral( + checker: TypeChecker, + objectLiteralExpression: ObjectLiteralExpression, +): StringLiteralCompletionsFromProperties | undefined { const contextualType = checker.getContextualType(objectLiteralExpression); if (!contextualType) return undefined; @@ -546,11 +713,15 @@ function stringLiteralCompletionsForObjectLiteral(checker: TypeChecker, objectLi }; } -function getStringLiteralTypes(type: Type | undefined, uniques = new Map()): readonly StringLiteralType[] { +function getStringLiteralTypes( + type: Type | undefined, + uniques = new Map(), +): readonly StringLiteralType[] { if (!type) return emptyArray; type = skipConstraint(type); - return type.isUnion() ? flatMap(type.types, t => getStringLiteralTypes(t, uniques)) : - type.isStringLiteral() && !(type.flags & TypeFlags.EnumLiteral) && addToSeen(uniques, type.value) ? [type] : emptyArray; + return type.isUnion() ? flatMap(type.types, t => getStringLiteralTypes(t, uniques)) + : type.isStringLiteral() && !(type.flags & TypeFlags.EnumLiteral) && addToSeen(uniques, type.value) ? [type] + : emptyArray; } interface NameAndKind { @@ -569,27 +740,83 @@ function directoryResult(name: string): NameAndKind { return nameAndKind(name, ScriptElementKind.directory, /*extension*/ undefined); } -function addReplacementSpans(text: string, textStart: number, names: readonly NameAndKind[]): readonly PathCompletion[] { +function addReplacementSpans( + text: string, + textStart: number, + names: readonly NameAndKind[], +): readonly PathCompletion[] { const span = getDirectoryFragmentTextSpan(text, textStart); const wholeSpan = text.length === 0 ? undefined : createTextSpan(textStart, text.length); - return names.map(({ name, kind, extension }): PathCompletion => Math.max(name.indexOf(directorySeparator), name.indexOf(altDirectorySeparator)) !== -1 ? { name, kind, extension, span: wholeSpan } : { name, kind, extension, span }); + return names.map(({ name, kind, extension }): PathCompletion => + Math.max(name.indexOf(directorySeparator), name.indexOf(altDirectorySeparator)) !== -1 + ? { name, kind, extension, span: wholeSpan } : { name, kind, extension, span } + ); } -function getStringLiteralCompletionsFromModuleNames(sourceFile: SourceFile, node: LiteralExpression, compilerOptions: CompilerOptions, host: LanguageServiceHost, typeChecker: TypeChecker, preferences: UserPreferences): readonly PathCompletion[] { - return addReplacementSpans(node.text, node.getStart(sourceFile) + 1, getStringLiteralCompletionsFromModuleNamesWorker(sourceFile, node, compilerOptions, host, typeChecker, preferences)); +function getStringLiteralCompletionsFromModuleNames( + sourceFile: SourceFile, + node: LiteralExpression, + compilerOptions: CompilerOptions, + host: LanguageServiceHost, + typeChecker: TypeChecker, + preferences: UserPreferences, +): readonly PathCompletion[] { + return addReplacementSpans( + node.text, + node.getStart(sourceFile) + 1, + getStringLiteralCompletionsFromModuleNamesWorker( + sourceFile, + node, + compilerOptions, + host, + typeChecker, + preferences, + ), + ); } -function getStringLiteralCompletionsFromModuleNamesWorker(sourceFile: SourceFile, node: LiteralExpression, compilerOptions: CompilerOptions, host: LanguageServiceHost, typeChecker: TypeChecker, preferences: UserPreferences): readonly NameAndKind[] { +function getStringLiteralCompletionsFromModuleNamesWorker( + sourceFile: SourceFile, + node: LiteralExpression, + compilerOptions: CompilerOptions, + host: LanguageServiceHost, + typeChecker: TypeChecker, + preferences: UserPreferences, +): readonly NameAndKind[] { const literalValue = normalizeSlashes(node.text); const mode = isStringLiteralLike(node) ? getModeForUsageLocation(sourceFile, node) : undefined; const scriptPath = sourceFile.path; const scriptDirectory = getDirectoryPath(scriptPath); - const extensionOptions = getExtensionOptions(compilerOptions, ReferenceKind.ModuleSpecifier, sourceFile, typeChecker, preferences, mode); + const extensionOptions = getExtensionOptions( + compilerOptions, + ReferenceKind.ModuleSpecifier, + sourceFile, + typeChecker, + preferences, + mode, + ); - return isPathRelativeToScript(literalValue) || !compilerOptions.baseUrl && !compilerOptions.paths && (isRootedDiskPath(literalValue) || isUrl(literalValue)) - ? getCompletionEntriesForRelativeModules(literalValue, scriptDirectory, compilerOptions, host, scriptPath, extensionOptions) - : getCompletionEntriesForNonRelativeModules(literalValue, scriptDirectory, mode, compilerOptions, host, extensionOptions, typeChecker); + return isPathRelativeToScript(literalValue) + || !compilerOptions.baseUrl && !compilerOptions.paths + && (isRootedDiskPath(literalValue) || isUrl(literalValue)) + ? getCompletionEntriesForRelativeModules( + literalValue, + scriptDirectory, + compilerOptions, + host, + scriptPath, + extensionOptions, + ) + : getCompletionEntriesForNonRelativeModules( + literalValue, + scriptDirectory, + mode, + compilerOptions, + host, + extensionOptions, + typeChecker, + ); } interface ExtensionOptions { @@ -600,7 +827,14 @@ interface ExtensionOptions { readonly resolutionMode?: ResolutionMode; } -function getExtensionOptions(compilerOptions: CompilerOptions, referenceKind: ReferenceKind, importingSourceFile: SourceFile, typeChecker?: TypeChecker, preferences?: UserPreferences, resolutionMode?: ResolutionMode): ExtensionOptions { +function getExtensionOptions( + compilerOptions: CompilerOptions, + referenceKind: ReferenceKind, + importingSourceFile: SourceFile, + typeChecker?: TypeChecker, + preferences?: UserPreferences, + resolutionMode?: ResolutionMode, +): ExtensionOptions { return { extensionsToSearch: flatten(getSupportedExtensionsForModuleResolution(compilerOptions, typeChecker)), referenceKind, @@ -609,7 +843,14 @@ function getExtensionOptions(compilerOptions: CompilerOptions, referenceKind: Re resolutionMode, }; } -function getCompletionEntriesForRelativeModules(literalValue: string, scriptDirectory: string, compilerOptions: CompilerOptions, host: LanguageServiceHost, scriptPath: Path, extensionOptions: ExtensionOptions) { +function getCompletionEntriesForRelativeModules( + literalValue: string, + scriptDirectory: string, + compilerOptions: CompilerOptions, + host: LanguageServiceHost, + scriptPath: Path, + extensionOptions: ExtensionOptions, +) { if (compilerOptions.rootDirs) { return getCompletionEntriesForDirectoryFragmentWithRootDirs( compilerOptions.rootDirs, @@ -622,11 +863,23 @@ function getCompletionEntriesForRelativeModules(literalValue: string, scriptDire ); } else { - return arrayFrom(getCompletionEntriesForDirectoryFragment(literalValue, scriptDirectory, extensionOptions, host, /*moduleSpecifierIsRelative*/ true, scriptPath).values()); + return arrayFrom( + getCompletionEntriesForDirectoryFragment( + literalValue, + scriptDirectory, + extensionOptions, + host, + /*moduleSpecifierIsRelative*/ true, + scriptPath, + ).values(), + ); } } -function getSupportedExtensionsForModuleResolution(compilerOptions: CompilerOptions, typeChecker?: TypeChecker): readonly string[][] { +function getSupportedExtensionsForModuleResolution( + compilerOptions: CompilerOptions, + typeChecker?: TypeChecker, +): readonly string[][] { /** file extensions from ambient modules declarations e.g. *.css */ const ambientModulesExtensions = !typeChecker ? [] : mapDefined(typeChecker.getAmbientModules(), module => { const name = module.name.slice(1, -1); @@ -636,21 +889,33 @@ function getSupportedExtensionsForModuleResolution(compilerOptions: CompilerOpti const extensions = [...getSupportedExtensions(compilerOptions), ambientModulesExtensions]; const moduleResolution = getEmitModuleResolutionKind(compilerOptions); - return moduleResolutionUsesNodeModules(moduleResolution) ? - getSupportedExtensionsWithJsonIfResolveJsonModule(compilerOptions, extensions) : - extensions; + return moduleResolutionUsesNodeModules(moduleResolution) + ? getSupportedExtensionsWithJsonIfResolveJsonModule(compilerOptions, extensions) + : extensions; } /** * Takes a script path and returns paths for all potential folders that could be merged with its * containing folder via the "rootDirs" compiler option */ -function getBaseDirectoriesFromRootDirs(rootDirs: string[], basePath: string, scriptDirectory: string, ignoreCase: boolean): readonly string[] { +function getBaseDirectoriesFromRootDirs( + rootDirs: string[], + basePath: string, + scriptDirectory: string, + ignoreCase: boolean, +): readonly string[] { // Make all paths absolute/normalized if they are not already - rootDirs = rootDirs.map(rootDirectory => normalizePath(isRootedDiskPath(rootDirectory) ? rootDirectory : combinePaths(basePath, rootDirectory))); + rootDirs = rootDirs.map(rootDirectory => + normalizePath(isRootedDiskPath(rootDirectory) ? rootDirectory : combinePaths(basePath, rootDirectory)) + ); // Determine the path to the directory containing the script relative to the root directory it is contained within - const relativeDirectory = firstDefined(rootDirs, rootDirectory => containsPath(rootDirectory, scriptDirectory, basePath, ignoreCase) ? scriptDirectory.substr(rootDirectory.length) : undefined)!; // TODO: GH#18217 + const relativeDirectory = firstDefined( + rootDirs, + rootDirectory => + containsPath(rootDirectory, scriptDirectory, basePath, ignoreCase) + ? scriptDirectory.substr(rootDirectory.length) : undefined, + )!; // TODO: GH#18217 // Now find a path for each potential directory that is to be merged with the one containing the script return deduplicate( @@ -660,11 +925,32 @@ function getBaseDirectoriesFromRootDirs(rootDirs: string[], basePath: string, sc ); } -function getCompletionEntriesForDirectoryFragmentWithRootDirs(rootDirs: string[], fragment: string, scriptDirectory: string, extensionOptions: ExtensionOptions, compilerOptions: CompilerOptions, host: LanguageServiceHost, exclude: string): readonly NameAndKind[] { +function getCompletionEntriesForDirectoryFragmentWithRootDirs( + rootDirs: string[], + fragment: string, + scriptDirectory: string, + extensionOptions: ExtensionOptions, + compilerOptions: CompilerOptions, + host: LanguageServiceHost, + exclude: string, +): readonly NameAndKind[] { const basePath = compilerOptions.project || host.getCurrentDirectory(); const ignoreCase = !(host.useCaseSensitiveFileNames && host.useCaseSensitiveFileNames()); const baseDirectories = getBaseDirectoriesFromRootDirs(rootDirs, basePath, scriptDirectory, ignoreCase); - return flatMap(baseDirectories, baseDirectory => arrayFrom(getCompletionEntriesForDirectoryFragment(fragment, baseDirectory, extensionOptions, host, /*moduleSpecifierIsRelative*/ true, exclude).values())); + return flatMap( + baseDirectories, + baseDirectory => + arrayFrom( + getCompletionEntriesForDirectoryFragment( + fragment, + baseDirectory, + extensionOptions, + host, + /*moduleSpecifierIsRelative*/ true, + exclude, + ).values(), + ), + ); } const enum ReferenceKind { @@ -710,14 +996,26 @@ function getCompletionEntriesForDirectoryFragment( // check for a version redirect const packageJsonPath = findPackageJson(baseDirectory, host); if (packageJsonPath) { - const packageJson = readJson(packageJsonPath, host as { readFile: (filename: string) => string | undefined; }); + const packageJson = readJson( + packageJsonPath, + host as { readFile: (filename: string) => string | undefined; }, + ); const typesVersions = (packageJson as any).typesVersions; if (typeof typesVersions === "object") { const versionPaths = getPackageJsonTypesVersionsPaths(typesVersions)?.paths; if (versionPaths) { const packageDirectory = getDirectoryPath(packageJsonPath); const pathInPackage = absolutePath.slice(ensureTrailingDirectorySeparator(packageDirectory).length); - if (addCompletionEntriesFromPaths(result, pathInPackage, packageDirectory, extensionOptions, host, versionPaths)) { + if ( + addCompletionEntriesFromPaths( + result, + pathInPackage, + packageDirectory, + extensionOptions, + host, + versionPaths, + ) + ) { // A true result means one of the `versionPaths` was matched, which will block relative resolution // to files and folders from here. All reachable paths given the pattern match are already added. return result; @@ -731,7 +1029,13 @@ function getCompletionEntriesForDirectoryFragment( if (!tryDirectoryExists(host, baseDirectory)) return result; // Enumerate the available files if possible - const files = tryReadDirectory(host, baseDirectory, extensionOptions.extensionsToSearch, /*exclude*/ undefined, /*include*/ ["./*"]); + const files = tryReadDirectory( + host, + baseDirectory, + extensionOptions.extensionsToSearch, + /*exclude*/ undefined, + /*include*/ ["./*"], + ); if (files) { for (let filePath of files) { @@ -740,7 +1044,11 @@ function getCompletionEntriesForDirectoryFragment( continue; } - const { name, extension } = getFilenameWithExtensionOption(getBaseFileName(filePath), host.getCompilationSettings(), extensionOptions); + const { name, extension } = getFilenameWithExtensionOption( + getBaseFileName(filePath), + host.getCompilationSettings(), + extensionOptions, + ); result.add(nameAndKind(name, ScriptElementKind.scriptElement, extension)); } } @@ -760,7 +1068,11 @@ function getCompletionEntriesForDirectoryFragment( return result; } -function getFilenameWithExtensionOption(name: string, compilerOptions: CompilerOptions, extensionOptions: ExtensionOptions): { name: string; extension: Extension | undefined; } { +function getFilenameWithExtensionOption( + name: string, + compilerOptions: CompilerOptions, + extensionOptions: ExtensionOptions, +): { name: string; extension: Extension | undefined; } { const nonJsResult = moduleSpecifiers.tryGetRealFileNameForNonJsDeclarationFileName(name); if (nonJsResult) { return { name: nonJsResult, extension: tryGetExtensionFromPath(nonJsResult) }; @@ -769,7 +1081,12 @@ function getFilenameWithExtensionOption(name: string, compilerOptions: CompilerO return { name, extension: tryGetExtensionFromPath(name) }; } - const endingPreference = getModuleSpecifierEndingPreference(extensionOptions.endingPreference, extensionOptions.resolutionMode, compilerOptions, extensionOptions.importingSourceFile); + const endingPreference = getModuleSpecifierEndingPreference( + extensionOptions.endingPreference, + extensionOptions.resolutionMode, + compilerOptions, + extensionOptions.importingSourceFile, + ); if (endingPreference === ModuleSpecifierEnding.TsExtension) { if (fileExtensionIsOneOf(name, supportedTSImplementationExtensions)) { return { name, extension: tryGetExtensionFromPath(name) }; @@ -781,8 +1098,8 @@ function getFilenameWithExtensionOption(name: string, compilerOptions: CompilerO } if ( - (endingPreference === ModuleSpecifierEnding.Minimal || endingPreference === ModuleSpecifierEnding.Index) && - fileExtensionIsOneOf(name, [Extension.Js, Extension.Jsx, Extension.Ts, Extension.Tsx, Extension.Dts]) + (endingPreference === ModuleSpecifierEnding.Minimal || endingPreference === ModuleSpecifierEnding.Index) + && fileExtensionIsOneOf(name, [Extension.Js, Extension.Jsx, Extension.Ts, Extension.Tsx, Extension.Dts]) ) { return { name: removeFileExtension(name), extension: tryGetExtensionFromPath(name) }; } @@ -810,7 +1127,16 @@ function addCompletionEntriesFromPaths( const lengthB = typeof patternB === "object" ? patternB.prefix.length : b.length; return compareValues(lengthB, lengthA); }; - return addCompletionEntriesFromPathsOrExports(result, fragment, baseDirectory, extensionOptions, host, getOwnKeys(paths), getPatternsForKey, comparePaths); + return addCompletionEntriesFromPathsOrExports( + result, + fragment, + baseDirectory, + extensionOptions, + host, + getOwnKeys(paths), + getPatternsForKey, + comparePaths, + ); } /** @returns whether `fragment` was a match for any `paths` (which should indicate whether any other path completions should be offered) */ @@ -834,7 +1160,8 @@ function addCompletionEntriesFromPathsOrExports( const pathPattern = tryParsePattern(keyWithoutLeadingDotSlash); if (!pathPattern) continue; const isMatch = typeof pathPattern === "object" && isPatternMatch(pathPattern, fragment); - const isLongestMatch = isMatch && (matchedPath === undefined || comparePaths(key, matchedPath) === Comparison.LessThan); + const isLongestMatch = isMatch + && (matchedPath === undefined || comparePaths(key, matchedPath) === Comparison.LessThan); if (isLongestMatch) { // If this is a higher priority match than anything we've seen so far, previous results from matches are invalid, e.g. // for `import {} from "some-package/|"` with a typesVersions: @@ -850,10 +1177,20 @@ function addCompletionEntriesFromPathsOrExports( matchedPath = key; pathResults = pathResults.filter(r => !r.matchedPattern); } - if (typeof pathPattern === "string" || matchedPath === undefined || comparePaths(key, matchedPath) !== Comparison.GreaterThan) { + if ( + typeof pathPattern === "string" || matchedPath === undefined + || comparePaths(key, matchedPath) !== Comparison.GreaterThan + ) { pathResults.push({ matchedPattern: isMatch, - results: getCompletionsForPathMapping(keyWithoutLeadingDotSlash, patterns, fragment, baseDirectory, extensionOptions, host) + results: getCompletionsForPathMapping( + keyWithoutLeadingDotSlash, + patterns, + fragment, + baseDirectory, + extensionOptions, + host, + ) .map(({ name, kind, extension }) => nameAndKind(name, kind, extension)), }); } @@ -887,7 +1224,15 @@ function getCompletionEntriesForNonRelativeModules( if (baseUrl) { const absolute = normalizePath(combinePaths(host.getCurrentDirectory(), baseUrl)); - getCompletionEntriesForDirectoryFragment(fragment, absolute, extensionOptions, host, /*moduleSpecifierIsRelative*/ false, /*exclude*/ undefined, result); + getCompletionEntriesForDirectoryFragment( + fragment, + absolute, + extensionOptions, + host, + /*moduleSpecifierIsRelative*/ false, + /*exclude*/ undefined, + result, + ); } if (paths) { @@ -908,7 +1253,11 @@ function getCompletionEntriesForNonRelativeModules( let foundGlobal = false; if (fragmentDirectory === undefined) { for (const moduleName of enumerateNodeModulesVisibleToScript(host, scriptPath)) { - const moduleResult = nameAndKind(moduleName, ScriptElementKind.externalModuleName, /*extension*/ undefined); + const moduleResult = nameAndKind( + moduleName, + ScriptElementKind.externalModuleName, + /*extension*/ undefined, + ); if (!result.has(moduleResult.name)) { foundGlobal = true; result.add(moduleResult); @@ -919,7 +1268,15 @@ function getCompletionEntriesForNonRelativeModules( let ancestorLookup: (directory: string) => void | undefined = ancestor => { const nodeModules = combinePaths(ancestor, "node_modules"); if (tryDirectoryExists(host, nodeModules)) { - getCompletionEntriesForDirectoryFragment(fragment, nodeModules, extensionOptions, host, /*moduleSpecifierIsRelative*/ false, /*exclude*/ undefined, result); + getCompletionEntriesForDirectoryFragment( + fragment, + nodeModules, + extensionOptions, + host, + /*moduleSpecifierIsRelative*/ false, + /*exclude*/ undefined, + result, + ); } }; if (fragmentDirectory && getResolvePackageJsonExports(compilerOptions)) { @@ -948,7 +1305,8 @@ function getCompletionEntriesForNonRelativeModules( return; // null exports or entrypoint only, no sub-modules available } const keys = getOwnKeys(exports); - const fragmentSubpath = components.join("/") + (components.length && hasTrailingDirectorySeparator(fragment) ? "/" : ""); + const fragmentSubpath = components.join("/") + + (components.length && hasTrailingDirectorySeparator(fragment) ? "/" : ""); const conditions = getConditions(compilerOptions, mode === ModuleKind.ESNext); addCompletionEntriesFromPathsOrExports( result, @@ -957,7 +1315,8 @@ function getCompletionEntriesForNonRelativeModules( extensionOptions, host, keys, - key => singleElementArray(getPatternFromFirstMatchingCondition(exports[key], conditions)), + key => + singleElementArray(getPatternFromFirstMatchingCondition(exports[key], conditions)), comparePatternKeys, ); return; @@ -979,7 +1338,10 @@ function getPatternFromFirstMatchingCondition(target: unknown, conditions: reado } if (target && typeof target === "object" && !isArray(target)) { for (const condition in target) { - if (condition === "default" || conditions.indexOf(condition) > -1 || isApplicableVersionedTypesKey(conditions, condition)) { + if ( + condition === "default" || conditions.indexOf(condition) > -1 + || isApplicableVersionedTypesKey(conditions, condition) + ) { const pattern = (target as MapLike)[condition]; return getPatternFromFirstMatchingCondition(pattern, conditions); } @@ -988,7 +1350,8 @@ function getPatternFromFirstMatchingCondition(target: unknown, conditions: reado } function getFragmentDirectory(fragment: string): string | undefined { - return containsSlash(fragment) ? hasTrailingDirectorySeparator(fragment) ? fragment : getDirectoryPath(fragment) : undefined; + return containsSlash(fragment) ? hasTrailingDirectorySeparator(fragment) ? fragment : getDirectoryPath(fragment) + : undefined; } function getCompletionsForPathMapping( @@ -1008,12 +1371,26 @@ function getCompletionsForPathMapping( const remainingFragment = tryRemovePrefix(fragment, pathPrefix); if (remainingFragment === undefined) { const starIsFullPathComponent = path[path.length - 2] === "/"; - return starIsFullPathComponent ? justPathMappingName(pathPrefix, ScriptElementKind.directory) : flatMap(patterns, pattern => getModulesForPathsPattern("", packageDirectory, pattern, extensionOptions, host)?.map(({ name, ...rest }) => ({ name: pathPrefix + name, ...rest }))); + return starIsFullPathComponent ? justPathMappingName(pathPrefix, ScriptElementKind.directory) + : flatMap( + patterns, + pattern => + getModulesForPathsPattern("", packageDirectory, pattern, extensionOptions, host)?.map(( + { name, ...rest }, + ) => ({ name: pathPrefix + name, ...rest })), + ); } - return flatMap(patterns, pattern => getModulesForPathsPattern(remainingFragment, packageDirectory, pattern, extensionOptions, host)); + return flatMap( + patterns, + pattern => getModulesForPathsPattern(remainingFragment, packageDirectory, pattern, extensionOptions, host), + ); - function justPathMappingName(name: string, kind: ScriptElementKind.directory | ScriptElementKind.scriptElement): readonly NameAndKind[] { - return startsWith(name, fragment) ? [{ name: removeTrailingDirectorySeparator(name), kind, extension: undefined }] : emptyArray; + function justPathMappingName( + name: string, + kind: ScriptElementKind.directory | ScriptElementKind.scriptElement, + ): readonly NameAndKind[] { + return startsWith(name, fragment) + ? [{ name: removeTrailingDirectorySeparator(name), kind, extension: undefined }] : emptyArray; } } @@ -1036,21 +1413,26 @@ function getModulesForPathsPattern( // The prefix has two effective parts: the directory path and the base component after the filepath that is not a // full directory component. For example: directory/path/of/prefix/base* const normalizedPrefix = resolvePath(parsed.prefix); - const normalizedPrefixDirectory = hasTrailingDirectorySeparator(parsed.prefix) ? normalizedPrefix : getDirectoryPath(normalizedPrefix); + const normalizedPrefixDirectory = hasTrailingDirectorySeparator(parsed.prefix) ? normalizedPrefix + : getDirectoryPath(normalizedPrefix); const normalizedPrefixBase = hasTrailingDirectorySeparator(parsed.prefix) ? "" : getBaseFileName(normalizedPrefix); const fragmentHasPath = containsSlash(fragment); - const fragmentDirectory = fragmentHasPath ? hasTrailingDirectorySeparator(fragment) ? fragment : getDirectoryPath(fragment) : undefined; + const fragmentDirectory = fragmentHasPath + ? hasTrailingDirectorySeparator(fragment) ? fragment : getDirectoryPath(fragment) : undefined; // Try and expand the prefix to include any path from the fragment so that we can limit the readDirectory call - const expandedPrefixDirectory = fragmentHasPath ? combinePaths(normalizedPrefixDirectory, normalizedPrefixBase + fragmentDirectory) : normalizedPrefixDirectory; + const expandedPrefixDirectory = fragmentHasPath + ? combinePaths(normalizedPrefixDirectory, normalizedPrefixBase + fragmentDirectory) : normalizedPrefixDirectory; const normalizedSuffix = normalizePath(parsed.suffix); const declarationExtension = normalizedSuffix && getDeclarationEmitExtensionForPath("_" + normalizedSuffix); - const matchingSuffixes = declarationExtension ? [changeExtension(normalizedSuffix, declarationExtension), normalizedSuffix] : [normalizedSuffix]; + const matchingSuffixes = declarationExtension + ? [changeExtension(normalizedSuffix, declarationExtension), normalizedSuffix] : [normalizedSuffix]; // Need to normalize after combining: If we combinePaths("a", "../b"), we want "b" and not "a/../b". const baseDirectory = normalizePath(combinePaths(packageDirectory, expandedPrefixDirectory)); - const completePrefix = fragmentHasPath ? baseDirectory : ensureTrailingDirectorySeparator(baseDirectory) + normalizedPrefixBase; + const completePrefix = fragmentHasPath ? baseDirectory + : ensureTrailingDirectorySeparator(baseDirectory) + normalizedPrefixBase; // If we have a suffix, then we read the directory all the way down to avoid returning completions for // directories that don't contain files that would match the suffix. A previous comment here was concerned @@ -1064,23 +1446,33 @@ function getModulesForPathsPattern( ? matchingSuffixes.map(suffix => "**/*" + suffix) : ["./*"]; - const matches = mapDefined(tryReadDirectory(host, baseDirectory, extensionOptions.extensionsToSearch, /*exclude*/ undefined, includeGlobs), match => { - const trimmedWithPattern = trimPrefixAndSuffix(match); - if (trimmedWithPattern) { - if (containsSlash(trimmedWithPattern)) { - return directoryResult(getPathComponents(removeLeadingDirectorySeparator(trimmedWithPattern))[1]); + const matches = mapDefined( + tryReadDirectory(host, baseDirectory, extensionOptions.extensionsToSearch, /*exclude*/ undefined, includeGlobs), + match => { + const trimmedWithPattern = trimPrefixAndSuffix(match); + if (trimmedWithPattern) { + if (containsSlash(trimmedWithPattern)) { + return directoryResult(getPathComponents(removeLeadingDirectorySeparator(trimmedWithPattern))[1]); + } + const { name, extension } = getFilenameWithExtensionOption( + trimmedWithPattern, + host.getCompilationSettings(), + extensionOptions, + ); + return nameAndKind(name, ScriptElementKind.scriptElement, extension); } - const { name, extension } = getFilenameWithExtensionOption(trimmedWithPattern, host.getCompilationSettings(), extensionOptions); - return nameAndKind(name, ScriptElementKind.scriptElement, extension); - } - }); + }, + ); // If we had a suffix, we already recursively searched for all possible files that could match // it and returned the directories leading to those files. Otherwise, assume any directory could // have something valid to import. const directories = normalizedSuffix ? emptyArray - : mapDefined(tryGetDirectories(host, baseDirectory), dir => dir === "node_modules" ? undefined : directoryResult(dir)); + : mapDefined( + tryGetDirectories(host, baseDirectory), + dir => dir === "node_modules" ? undefined : directoryResult(dir), + ); return [...matches, ...directories]; function trimPrefixAndSuffix(path: string): string | undefined { @@ -1099,25 +1491,39 @@ function removeLeadingDirectorySeparator(path: string): string { return path[0] === directorySeparator ? path.slice(1) : path; } -function getAmbientModuleCompletions(fragment: string, fragmentDirectory: string | undefined, checker: TypeChecker): readonly string[] { +function getAmbientModuleCompletions( + fragment: string, + fragmentDirectory: string | undefined, + checker: TypeChecker, +): readonly string[] { // Get modules that the type checker picked up const ambientModules = checker.getAmbientModules().map(sym => stripQuotes(sym.name)); - const nonRelativeModuleNames = ambientModules.filter(moduleName => startsWith(moduleName, fragment) && moduleName.indexOf("*") < 0); + const nonRelativeModuleNames = ambientModules.filter(moduleName => + startsWith(moduleName, fragment) && moduleName.indexOf("*") < 0 + ); // Nested modules of the form "module-name/sub" need to be adjusted to only return the string // after the last '/' that appears in the fragment because that's where the replacement span // starts if (fragmentDirectory !== undefined) { const moduleNameWithSeparator = ensureTrailingDirectorySeparator(fragmentDirectory); - return nonRelativeModuleNames.map(nonRelativeModuleName => removePrefix(nonRelativeModuleName, moduleNameWithSeparator)); + return nonRelativeModuleNames.map(nonRelativeModuleName => + removePrefix(nonRelativeModuleName, moduleNameWithSeparator) + ); } return nonRelativeModuleNames; } -function getTripleSlashReferenceCompletion(sourceFile: SourceFile, position: number, compilerOptions: CompilerOptions, host: LanguageServiceHost): readonly PathCompletion[] | undefined { +function getTripleSlashReferenceCompletion( + sourceFile: SourceFile, + position: number, + compilerOptions: CompilerOptions, + host: LanguageServiceHost, +): readonly PathCompletion[] | undefined { const token = getTokenAtPosition(sourceFile, position); const commentRanges = getLeadingCommentRanges(sourceFile.text, token.pos); - const range = commentRanges && find(commentRanges, commentRange => position >= commentRange.pos && position <= commentRange.end); + const range = commentRanges + && find(commentRanges, commentRange => position >= commentRange.pos && position <= commentRange.end); if (!range) { return undefined; } @@ -1129,13 +1535,35 @@ function getTripleSlashReferenceCompletion(sourceFile: SourceFile, position: num const [, prefix, kind, toComplete] = match; const scriptPath = getDirectoryPath(sourceFile.path); - const names = kind === "path" ? getCompletionEntriesForDirectoryFragment(toComplete, scriptPath, getExtensionOptions(compilerOptions, ReferenceKind.Filename, sourceFile), host, /*moduleSpecifierIsRelative*/ true, sourceFile.path) - : kind === "types" ? getCompletionEntriesFromTypings(host, compilerOptions, scriptPath, getFragmentDirectory(toComplete), getExtensionOptions(compilerOptions, ReferenceKind.ModuleSpecifier, sourceFile)) + const names = kind === "path" + ? getCompletionEntriesForDirectoryFragment( + toComplete, + scriptPath, + getExtensionOptions(compilerOptions, ReferenceKind.Filename, sourceFile), + host, + /*moduleSpecifierIsRelative*/ true, + sourceFile.path, + ) + : kind === "types" + ? getCompletionEntriesFromTypings( + host, + compilerOptions, + scriptPath, + getFragmentDirectory(toComplete), + getExtensionOptions(compilerOptions, ReferenceKind.ModuleSpecifier, sourceFile), + ) : Debug.fail(); return addReplacementSpans(toComplete, range.pos + prefix.length, arrayFrom(names.values())); } -function getCompletionEntriesFromTypings(host: LanguageServiceHost, options: CompilerOptions, scriptPath: string, fragmentDirectory: string | undefined, extensionOptions: ExtensionOptions, result = createNameAndKindSet()): NameAndKindSet { +function getCompletionEntriesFromTypings( + host: LanguageServiceHost, + options: CompilerOptions, + scriptPath: string, + fragmentDirectory: string | undefined, + extensionOptions: ExtensionOptions, + result = createNameAndKindSet(), +): NameAndKindSet { // Check for typings specified in compiler options const seen = new Map(); @@ -1168,9 +1596,21 @@ function getCompletionEntriesFromTypings(host: LanguageServiceHost, options: Com } else { const baseDirectory = combinePaths(directory, typeDirectoryName); - const remainingFragment = tryRemoveDirectoryPrefix(fragmentDirectory, packageName, hostGetCanonicalFileName(host)); + const remainingFragment = tryRemoveDirectoryPrefix( + fragmentDirectory, + packageName, + hostGetCanonicalFileName(host), + ); if (remainingFragment !== undefined) { - getCompletionEntriesForDirectoryFragment(remainingFragment, baseDirectory, extensionOptions, host, /*moduleSpecifierIsRelative*/ false, /*exclude*/ undefined, result); + getCompletionEntriesForDirectoryFragment( + remainingFragment, + baseDirectory, + extensionOptions, + host, + /*moduleSpecifierIsRelative*/ false, + /*exclude*/ undefined, + result, + ); } } } @@ -1203,7 +1643,8 @@ function getDirectoryFragmentTextSpan(text: string, textStart: number): TextSpan const offset = index !== -1 ? index + 1 : 0; // If the range is an identifier, span is unnecessary. const length = text.length - offset; - return length === 0 || isIdentifierText(text.substr(offset, length), ScriptTarget.ESNext) ? undefined : createTextSpan(textStart + offset, length); + return length === 0 || isIdentifierText(text.substr(offset, length), ScriptTarget.ESNext) ? undefined + : createTextSpan(textStart + offset, length); } // Returns true if the path is explicitly relative to the script (i.e. relative to . or ..) @@ -1230,7 +1671,12 @@ function isPathRelativeToScript(path: string) { */ const tripleSlashDirectiveFragmentRegex = /^(\/\/\/\s*(); /** @internal */ -export function computeSuggestionDiagnostics(sourceFile: SourceFile, program: Program, cancellationToken: CancellationToken): DiagnosticWithLocation[] { +export function computeSuggestionDiagnostics( + sourceFile: SourceFile, + program: Program, + cancellationToken: CancellationToken, +): DiagnosticWithLocation[] { program.getSemanticDiagnostics(sourceFile, cancellationToken); const diags: DiagnosticWithLocation[] = []; const checker = program.getTypeChecker(); - const isCommonJSFile = sourceFile.impliedNodeFormat === ModuleKind.CommonJS || fileExtensionIsOneOf(sourceFile.fileName, [Extension.Cts, Extension.Cjs]); + const isCommonJSFile = sourceFile.impliedNodeFormat === ModuleKind.CommonJS + || fileExtensionIsOneOf(sourceFile.fileName, [Extension.Cts, Extension.Cjs]); if ( - !isCommonJSFile && - sourceFile.commonJsModuleIndicator && - (programContainsEsModules(program) || compilerOptionsIndicateEsModules(program.getCompilerOptions())) && - containsTopLevelCommonjs(sourceFile) + !isCommonJSFile + && sourceFile.commonJsModuleIndicator + && (programContainsEsModules(program) || compilerOptionsIndicateEsModules(program.getCompilerOptions())) + && containsTopLevelCommonjs(sourceFile) ) { - diags.push(createDiagnosticForNode(getErrorNodeFromCommonJsIndicator(sourceFile.commonJsModuleIndicator), Diagnostics.File_is_a_CommonJS_module_it_may_be_converted_to_an_ES_module)); + diags.push( + createDiagnosticForNode( + getErrorNodeFromCommonJsIndicator(sourceFile.commonJsModuleIndicator), + Diagnostics.File_is_a_CommonJS_module_it_may_be_converted_to_an_ES_module, + ), + ); } const isJsFile = isSourceFileJS(sourceFile); @@ -89,9 +99,17 @@ export function computeSuggestionDiagnostics(sourceFile: SourceFile, program: Pr const importNode = importFromModuleSpecifier(moduleSpecifier); const name = importNameForConvertToDefaultImport(importNode); if (!name) continue; - const module = getResolvedModule(sourceFile, moduleSpecifier.text, getModeForUsageLocation(sourceFile, moduleSpecifier)); + const module = getResolvedModule( + sourceFile, + moduleSpecifier.text, + getModeForUsageLocation(sourceFile, moduleSpecifier), + ); const resolvedFile = module && program.getSourceFile(module.resolvedFileName); - if (resolvedFile && resolvedFile.externalModuleIndicator && resolvedFile.externalModuleIndicator !== true && isExportAssignment(resolvedFile.externalModuleIndicator) && resolvedFile.externalModuleIndicator.isExportEquals) { + if ( + resolvedFile && resolvedFile.externalModuleIndicator && resolvedFile.externalModuleIndicator !== true + && isExportAssignment(resolvedFile.externalModuleIndicator) + && resolvedFile.externalModuleIndicator.isExportEquals + ) { diags.push(createDiagnosticForNode(name, Diagnostics.Import_may_be_converted_to_a_default_import)); } } @@ -104,15 +122,20 @@ export function computeSuggestionDiagnostics(sourceFile: SourceFile, program: Pr function check(node: Node) { if (isJsFile) { if (canBeConvertedToClass(node, checker)) { - diags.push(createDiagnosticForNode(isVariableDeclaration(node.parent) ? node.parent.name : node, Diagnostics.This_constructor_function_may_be_converted_to_a_class_declaration)); + diags.push( + createDiagnosticForNode( + isVariableDeclaration(node.parent) ? node.parent.name : node, + Diagnostics.This_constructor_function_may_be_converted_to_a_class_declaration, + ), + ); } } else { if ( - isVariableStatement(node) && - node.parent === sourceFile && - node.declarationList.flags & NodeFlags.Const && - node.declarationList.declarations.length === 1 + isVariableStatement(node) + && node.parent === sourceFile + && node.declarationList.flags & NodeFlags.Const + && node.declarationList.declarations.length === 1 ) { const init = node.declarationList.declarations[0].initializer; if (init && isRequireCall(init, /*requireStringLiteralLikeArgument*/ true)) { @@ -122,11 +145,21 @@ export function computeSuggestionDiagnostics(sourceFile: SourceFile, program: Pr const jsdocTypedefNodes = codefix.getJSDocTypedefNodes(node); for (const jsdocTypedefNode of jsdocTypedefNodes) { - diags.push(createDiagnosticForNode(jsdocTypedefNode, Diagnostics.JSDoc_typedef_may_be_converted_to_TypeScript_type)); + diags.push( + createDiagnosticForNode( + jsdocTypedefNode, + Diagnostics.JSDoc_typedef_may_be_converted_to_TypeScript_type, + ), + ); } if (codefix.parameterShouldGetTypeFromJSDoc(node)) { - diags.push(createDiagnosticForNode(node.name || node, Diagnostics.JSDoc_types_may_be_moved_to_TypeScript_types)); + diags.push( + createDiagnosticForNode( + node.name || node, + Diagnostics.JSDoc_types_may_be_moved_to_TypeScript_types, + ), + ); } } @@ -142,12 +175,21 @@ function containsTopLevelCommonjs(sourceFile: SourceFile): boolean { return sourceFile.statements.some(statement => { switch (statement.kind) { case SyntaxKind.VariableStatement: - return (statement as VariableStatement).declarationList.declarations.some(decl => !!decl.initializer && isRequireCall(propertyAccessLeftHandSide(decl.initializer), /*requireStringLiteralLikeArgument*/ true)); + return (statement as VariableStatement).declarationList.declarations.some(decl => + !!decl.initializer + && isRequireCall( + propertyAccessLeftHandSide(decl.initializer), + /*requireStringLiteralLikeArgument*/ true, + ) + ); case SyntaxKind.ExpressionStatement: { const { expression } = statement as ExpressionStatement; - if (!isBinaryExpression(expression)) return isRequireCall(expression, /*requireStringLiteralLikeArgument*/ true); + if (!isBinaryExpression(expression)) { + return isRequireCall(expression, /*requireStringLiteralLikeArgument*/ true); + } const kind = getAssignmentDeclarationKind(expression); - return kind === AssignmentDeclarationKind.ExportsProperty || kind === AssignmentDeclarationKind.ModuleExports; + return kind === AssignmentDeclarationKind.ExportsProperty + || kind === AssignmentDeclarationKind.ModuleExports; } default: return false; @@ -163,7 +205,9 @@ function importNameForConvertToDefaultImport(node: AnyValidImportOrReExport): Id switch (node.kind) { case SyntaxKind.ImportDeclaration: const { importClause, moduleSpecifier } = node; - return importClause && !importClause.name && importClause.namedBindings && importClause.namedBindings.kind === SyntaxKind.NamespaceImport && isStringLiteral(moduleSpecifier) + return importClause && !importClause.name && importClause.namedBindings + && importClause.namedBindings.kind === SyntaxKind.NamespaceImport + && isStringLiteral(moduleSpecifier) ? importClause.namedBindings.name : undefined; case SyntaxKind.ImportEqualsDeclaration: @@ -173,22 +217,27 @@ function importNameForConvertToDefaultImport(node: AnyValidImportOrReExport): Id } } -function addConvertToAsyncFunctionDiagnostics(node: FunctionLikeDeclaration, checker: TypeChecker, diags: DiagnosticWithLocation[]): void { +function addConvertToAsyncFunctionDiagnostics( + node: FunctionLikeDeclaration, + checker: TypeChecker, + diags: DiagnosticWithLocation[], +): void { // need to check function before checking map so that deeper levels of nested callbacks are checked if (isConvertibleFunction(node, checker) && !visitedNestedConvertibleFunctions.has(getKeyFromNode(node))) { diags.push(createDiagnosticForNode( - !node.name && isVariableDeclaration(node.parent) && isIdentifier(node.parent.name) ? node.parent.name : node, + !node.name && isVariableDeclaration(node.parent) && isIdentifier(node.parent.name) ? node.parent.name + : node, Diagnostics.This_may_be_converted_to_an_async_function, )); } } function isConvertibleFunction(node: FunctionLikeDeclaration, checker: TypeChecker) { - return !isAsyncFunction(node) && - node.body && - isBlock(node.body) && - hasReturnStatementWithPromiseHandler(node.body, checker) && - returnsPromise(node, checker); + return !isAsyncFunction(node) + && node.body + && isBlock(node.body) + && hasReturnStatementWithPromiseHandler(node.body, checker) + && returnsPromise(node, checker); } /** @internal */ @@ -207,7 +256,10 @@ function hasReturnStatementWithPromiseHandler(body: Block, checker: TypeChecker) } /** @internal */ -export function isReturnStatementWithFixablePromiseHandler(node: Node, checker: TypeChecker): node is ReturnStatement & { expression: CallExpression; } { +export function isReturnStatementWithFixablePromiseHandler( + node: Node, + checker: TypeChecker, +): node is ReturnStatement & { expression: CallExpression; } { return isReturnStatement(node) && !!node.expression && isFixablePromiseHandler(node.expression, checker); } @@ -215,7 +267,10 @@ export function isReturnStatementWithFixablePromiseHandler(node: Node, checker: /** @internal */ export function isFixablePromiseHandler(node: Node, checker: TypeChecker): boolean { // ensure outermost call exists and is a promise handler - if (!isPromiseHandler(node) || !hasSupportedNumberOfArguments(node) || !node.arguments.every(arg => isFixablePromiseArgument(arg, checker))) { + if ( + !isPromiseHandler(node) || !hasSupportedNumberOfArguments(node) + || !node.arguments.every(arg => isFixablePromiseArgument(arg, checker)) + ) { return false; } @@ -223,7 +278,10 @@ export function isFixablePromiseHandler(node: Node, checker: TypeChecker): boole let currentNode = node.expression.expression; while (isPromiseHandler(currentNode) || isPropertyAccessExpression(currentNode)) { if (isCallExpression(currentNode)) { - if (!hasSupportedNumberOfArguments(currentNode) || !currentNode.arguments.every(arg => isFixablePromiseArgument(arg, checker))) { + if ( + !hasSupportedNumberOfArguments(currentNode) + || !currentNode.arguments.every(arg => isFixablePromiseArgument(arg, checker)) + ) { return false; } currentNode = currentNode.expression.expression; @@ -237,9 +295,9 @@ export function isFixablePromiseHandler(node: Node, checker: TypeChecker): boole function isPromiseHandler(node: Node): node is CallExpression & { readonly expression: PropertyAccessExpression; } { return isCallExpression(node) && ( - hasPropertyAccessExpressionWithName(node, "then") || - hasPropertyAccessExpressionWithName(node, "catch") || - hasPropertyAccessExpressionWithName(node, "finally") + hasPropertyAccessExpressionWithName(node, "then") + || hasPropertyAccessExpressionWithName(node, "catch") + || hasPropertyAccessExpressionWithName(node, "finally") ); } @@ -274,8 +332,11 @@ function isFixablePromiseArgument(arg: Expression, checker: TypeChecker): boolea if (!symbol) { return false; } - return checker.isUndefinedSymbol(symbol) || - some(skipAlias(symbol, checker).declarations, d => isFunctionLike(d) || hasInitializer(d) && !!d.initializer && isFunctionLike(d.initializer)); + return checker.isUndefinedSymbol(symbol) + || some( + skipAlias(symbol, checker).declarations, + d => isFunctionLike(d) || hasInitializer(d) && !!d.initializer && isFunctionLike(d.initializer), + ); } default: return false; @@ -304,7 +365,9 @@ function canBeConvertedToClass(node: Node, checker: TypeChecker): boolean { } /** @internal */ -export function canBeConvertedToAsync(node: Node): node is FunctionDeclaration | MethodDeclaration | FunctionExpression | ArrowFunction { +export function canBeConvertedToAsync( + node: Node, +): node is FunctionDeclaration | MethodDeclaration | FunctionExpression | ArrowFunction { switch (node.kind) { case SyntaxKind.FunctionDeclaration: case SyntaxKind.MethodDeclaration: diff --git a/src/services/symbolDisplay.ts b/src/services/symbolDisplay.ts index 6d453d135ef01..3932953d5a503 100644 --- a/src/services/symbolDisplay.ts +++ b/src/services/symbolDisplay.ts @@ -110,7 +110,8 @@ import { VariableDeclaration, } from "./_namespaces/ts"; -const symbolDisplayNodeBuilderFlags = NodeBuilderFlags.OmitParameterModifiers | NodeBuilderFlags.IgnoreErrors | NodeBuilderFlags.UseAliasDefinedOutsideCurrentScope; +const symbolDisplayNodeBuilderFlags = NodeBuilderFlags.OmitParameterModifiers | NodeBuilderFlags.IgnoreErrors + | NodeBuilderFlags.UseAliasDefinedOutsideCurrentScope; // TODO(drosen): use contextual SemanticMeaning. /** @internal */ @@ -122,8 +123,8 @@ export function getSymbolKind(typeChecker: TypeChecker, symbol: Symbol, location const flags = getCombinedLocalAndExportSymbolFlags(symbol); if (flags & SymbolFlags.Class) { - return getDeclarationOfKind(symbol, SyntaxKind.ClassExpression) ? - ScriptElementKind.localClassElement : ScriptElementKind.classElement; + return getDeclarationOfKind(symbol, SyntaxKind.ClassExpression) + ? ScriptElementKind.localClassElement : ScriptElementKind.classElement; } if (flags & SymbolFlags.Enum) return ScriptElementKind.enumElement; if (flags & SymbolFlags.TypeAlias) return ScriptElementKind.typeElement; @@ -136,7 +137,11 @@ export function getSymbolKind(typeChecker: TypeChecker, symbol: Symbol, location return result; } -function getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(typeChecker: TypeChecker, symbol: Symbol, location: Node): ScriptElementKind { +function getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar( + typeChecker: TypeChecker, + symbol: Symbol, + location: Node, +): ScriptElementKind { const roots = typeChecker.getRootSymbols(symbol); // If this is a method from a mapped type, leave as a method so long as it still has a call signature. if ( @@ -174,9 +179,13 @@ function getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(typeCheck else if (forEach(symbol.declarations, isLet)) { return ScriptElementKind.letElement; } - return isLocalVariableOrFunction(symbol) ? ScriptElementKind.localVariableElement : ScriptElementKind.variableElement; + return isLocalVariableOrFunction(symbol) ? ScriptElementKind.localVariableElement + : ScriptElementKind.variableElement; + } + if (flags & SymbolFlags.Function) { + return isLocalVariableOrFunction(symbol) ? ScriptElementKind.localFunctionElement + : ScriptElementKind.functionElement; } - if (flags & SymbolFlags.Function) return isLocalVariableOrFunction(symbol) ? ScriptElementKind.localFunctionElement : ScriptElementKind.functionElement; // FIXME: getter and setter use the same symbol. And it is rare to use only setter without getter, so in most cases the symbol always has getter flag. // So, even when the location is just on the declaration of setter, this function returns getter. if (flags & SymbolFlags.GetAccessor) return ScriptElementKind.memberGetAccessorElement; @@ -216,7 +225,8 @@ function getNormalizedSymbolModifiers(symbol: Symbol) { if (symbol.declarations && symbol.declarations.length) { const [declaration, ...declarations] = symbol.declarations; // omit deprecated flag if some declarations are not deprecated - const excludeFlags = length(declarations) && isDeprecatedDeclaration(declaration) && some(declarations, d => !isDeprecatedDeclaration(d)) + const excludeFlags = length(declarations) && isDeprecatedDeclaration(declaration) && some(declarations, d => + !isDeprecatedDeclaration(d)) ? ModifierFlags.Deprecated : ModifierFlags.None; const modifiers = getNodeModifiers(declaration, excludeFlags); @@ -256,27 +266,52 @@ export interface SymbolDisplayPartsDocumentationAndSymbolKind { tags: JSDocTagInfo[] | undefined; } -function getSymbolDisplayPartsDocumentationAndSymbolKindWorker(typeChecker: TypeChecker, symbol: Symbol, sourceFile: SourceFile, enclosingDeclaration: Node | undefined, location: Node, type: Type | undefined, semanticMeaning: SemanticMeaning, alias?: Symbol): SymbolDisplayPartsDocumentationAndSymbolKind { +function getSymbolDisplayPartsDocumentationAndSymbolKindWorker( + typeChecker: TypeChecker, + symbol: Symbol, + sourceFile: SourceFile, + enclosingDeclaration: Node | undefined, + location: Node, + type: Type | undefined, + semanticMeaning: SemanticMeaning, + alias?: Symbol, +): SymbolDisplayPartsDocumentationAndSymbolKind { const displayParts: SymbolDisplayPart[] = []; let documentation: SymbolDisplayPart[] = []; let tags: JSDocTagInfo[] = []; const symbolFlags = getCombinedLocalAndExportSymbolFlags(symbol); - let symbolKind = semanticMeaning & SemanticMeaning.Value ? getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(typeChecker, symbol, location) : ScriptElementKind.unknown; + let symbolKind = semanticMeaning & SemanticMeaning.Value + ? getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(typeChecker, symbol, location) + : ScriptElementKind.unknown; let hasAddedSymbolInfo = false; - const isThisExpression = location.kind === SyntaxKind.ThisKeyword && isInExpressionContext(location) || isThisInTypeQuery(location); + const isThisExpression = location.kind === SyntaxKind.ThisKeyword && isInExpressionContext(location) + || isThisInTypeQuery(location); let documentationFromAlias: SymbolDisplayPart[] | undefined; let tagsFromAlias: JSDocTagInfo[] | undefined; let hasMultipleSignatures = false; if (location.kind === SyntaxKind.ThisKeyword && !isThisExpression) { - return { displayParts: [keywordPart(SyntaxKind.ThisKeyword)], documentation: [], symbolKind: ScriptElementKind.primitiveType, tags: undefined }; + return { + displayParts: [keywordPart(SyntaxKind.ThisKeyword)], + documentation: [], + symbolKind: ScriptElementKind.primitiveType, + tags: undefined, + }; } // Class at constructor site need to be shown as constructor apart from property,method, vars - if (symbolKind !== ScriptElementKind.unknown || symbolFlags & SymbolFlags.Class || symbolFlags & SymbolFlags.Alias) { + if ( + symbolKind !== ScriptElementKind.unknown || symbolFlags & SymbolFlags.Class || symbolFlags & SymbolFlags.Alias + ) { // If symbol is accessor, they are allowed only if location is at declaration identifier of the accessor - if (symbolKind === ScriptElementKind.memberGetAccessorElement || symbolKind === ScriptElementKind.memberSetAccessorElement) { - const declaration = find(symbol.declarations as ((GetAccessorDeclaration | SetAccessorDeclaration | PropertyDeclaration)[]), declaration => declaration.name === location); + if ( + symbolKind === ScriptElementKind.memberGetAccessorElement + || symbolKind === ScriptElementKind.memberSetAccessorElement + ) { + const declaration = find( + symbol.declarations as ((GetAccessorDeclaration | SetAccessorDeclaration | PropertyDeclaration)[]), + declaration => declaration.name === location, + ); if (declaration) { switch (declaration.kind) { case SyntaxKind.GetAccessor: @@ -298,7 +333,8 @@ function getSymbolDisplayPartsDocumentationAndSymbolKindWorker(typeChecker: Type } let signature: Signature | undefined; - type ??= isThisExpression ? typeChecker.getTypeAtLocation(location) : typeChecker.getTypeOfSymbolAtLocation(symbol, location); + type ??= isThisExpression ? typeChecker.getTypeAtLocation(location) + : typeChecker.getTypeOfSymbolAtLocation(symbol, location); if (location.parent && location.parent.kind === SyntaxKind.PropertyAccessExpression) { const right = (location.parent as PropertyAccessExpression).name; @@ -309,21 +345,31 @@ function getSymbolDisplayPartsDocumentationAndSymbolKindWorker(typeChecker: Type } // try get the call/construct signature from the type if it matches - let callExpressionLike: CallExpression | NewExpression | JsxOpeningLikeElement | TaggedTemplateExpression | undefined; + let callExpressionLike: + | CallExpression + | NewExpression + | JsxOpeningLikeElement + | TaggedTemplateExpression + | undefined; if (isCallOrNewExpression(location)) { callExpressionLike = location; } else if (isCallExpressionTarget(location) || isNewExpressionTarget(location)) { callExpressionLike = location.parent as CallExpression | NewExpression; } - else if (location.parent && (isJsxOpeningLikeElement(location.parent) || isTaggedTemplateExpression(location.parent)) && isFunctionLike(symbol.valueDeclaration)) { + else if ( + location.parent && (isJsxOpeningLikeElement(location.parent) || isTaggedTemplateExpression(location.parent)) + && isFunctionLike(symbol.valueDeclaration) + ) { callExpressionLike = location.parent; } if (callExpressionLike) { signature = typeChecker.getResolvedSignature(callExpressionLike); // TODO: GH#18217 - const useConstructSignatures = callExpressionLike.kind === SyntaxKind.NewExpression || (isCallExpression(callExpressionLike) && callExpressionLike.expression.kind === SyntaxKind.SuperKeyword); + const useConstructSignatures = callExpressionLike.kind === SyntaxKind.NewExpression + || (isCallExpression(callExpressionLike) + && callExpressionLike.expression.kind === SyntaxKind.SuperKeyword); const allSignatures = useConstructSignatures ? type.getConstructSignatures() : type.getCallSignatures(); @@ -369,7 +415,17 @@ function getSymbolDisplayPartsDocumentationAndSymbolKindWorker(typeChecker: Type displayParts.push(punctuationPart(SyntaxKind.ColonToken)); displayParts.push(spacePart()); if (!(getObjectFlags(type) & ObjectFlags.Anonymous) && type.symbol) { - addRange(displayParts, symbolToDisplayParts(typeChecker, type.symbol, enclosingDeclaration, /*meaning*/ undefined, SymbolFormatFlags.AllowAnyNodeKind | SymbolFormatFlags.WriteTypeParametersOrArguments)); + addRange( + displayParts, + symbolToDisplayParts( + typeChecker, + type.symbol, + enclosingDeclaration, + /*meaning*/ undefined, + SymbolFormatFlags.AllowAnyNodeKind + | SymbolFormatFlags.WriteTypeParametersOrArguments, + ), + ); displayParts.push(lineBreakPart()); } if (useConstructSignatures) { @@ -392,16 +448,22 @@ function getSymbolDisplayPartsDocumentationAndSymbolKindWorker(typeChecker: Type } } else if ( - (isNameOfFunctionDeclaration(location) && !(symbolFlags & SymbolFlags.Accessor)) || // name of function declaration - (location.kind === SyntaxKind.ConstructorKeyword && location.parent.kind === SyntaxKind.Constructor) + (isNameOfFunctionDeclaration(location) && !(symbolFlags & SymbolFlags.Accessor)) // name of function declaration + || (location.kind === SyntaxKind.ConstructorKeyword && location.parent.kind === SyntaxKind.Constructor) ) { // At constructor keyword of constructor declaration // get the signature from the declaration and write it const functionDeclaration = location.parent as SignatureDeclaration; // Use function declaration to write the signatures only if the symbol corresponding to this declaration - const locationIsSymbolDeclaration = symbol.declarations && find(symbol.declarations, declaration => declaration === (location.kind === SyntaxKind.ConstructorKeyword ? functionDeclaration.parent : functionDeclaration)); + const locationIsSymbolDeclaration = symbol.declarations + && find(symbol.declarations, declaration => + declaration + === (location.kind === SyntaxKind.ConstructorKeyword ? functionDeclaration.parent + : functionDeclaration)); if (locationIsSymbolDeclaration) { - const allSignatures = functionDeclaration.kind === SyntaxKind.Constructor ? type.getNonNullableType().getConstructSignatures() : type.getNonNullableType().getCallSignatures(); + const allSignatures = functionDeclaration.kind === SyntaxKind.Constructor + ? type.getNonNullableType().getConstructSignatures() + : type.getNonNullableType().getCallSignatures(); if (!typeChecker.isImplementationOfOverload(functionDeclaration)) { signature = typeChecker.getSignatureFromDeclaration(functionDeclaration); // TODO: GH#18217 } @@ -417,8 +479,9 @@ function getSymbolDisplayPartsDocumentationAndSymbolKindWorker(typeChecker: Type else { // (function/method) symbol(..signature) addPrefixForAnyFunctionOrVar( - functionDeclaration.kind === SyntaxKind.CallSignature && - !(type.symbol.flags & SymbolFlags.TypeLiteral || type.symbol.flags & SymbolFlags.ObjectLiteral) ? type.symbol : symbol, + functionDeclaration.kind === SyntaxKind.CallSignature + && !(type.symbol.flags & SymbolFlags.TypeLiteral + || type.symbol.flags & SymbolFlags.ObjectLiteral) ? type.symbol : symbol, symbolKind, ); } @@ -462,7 +525,16 @@ function getSymbolDisplayPartsDocumentationAndSymbolKindWorker(typeChecker: Type displayParts.push(spacePart()); displayParts.push(operatorPart(SyntaxKind.EqualsToken)); displayParts.push(spacePart()); - addRange(displayParts, typeToDisplayParts(typeChecker, location.parent && isConstTypeReference(location.parent) ? typeChecker.getTypeAtLocation(location.parent) : typeChecker.getDeclaredTypeOfSymbol(symbol), enclosingDeclaration, TypeFormatFlags.InTypeAlias)); + addRange( + displayParts, + typeToDisplayParts( + typeChecker, + location.parent && isConstTypeReference(location.parent) + ? typeChecker.getTypeAtLocation(location.parent) : typeChecker.getDeclaredTypeOfSymbol(symbol), + enclosingDeclaration, + TypeFormatFlags.InTypeAlias, + ), + ); } if (symbolFlags & SymbolFlags.Enum) { prefixNextMeaning(); @@ -512,7 +584,15 @@ function getSymbolDisplayPartsDocumentationAndSymbolKindWorker(typeChecker: Type else if (declaration.kind !== SyntaxKind.CallSignature && declaration.name) { addFullSymbolName(declaration.symbol); } - addRange(displayParts, signatureToDisplayParts(typeChecker, signature, sourceFile, TypeFormatFlags.WriteTypeArgumentsOfSignature)); + addRange( + displayParts, + signatureToDisplayParts( + typeChecker, + signature, + sourceFile, + TypeFormatFlags.WriteTypeArgumentsOfSignature, + ), + ); } else if (isTypeAliasDeclaration(declaration)) { // Type alias type parameter @@ -537,7 +617,13 @@ function getSymbolDisplayPartsDocumentationAndSymbolKindWorker(typeChecker: Type displayParts.push(spacePart()); displayParts.push(operatorPart(SyntaxKind.EqualsToken)); displayParts.push(spacePart()); - displayParts.push(displayPart(getTextOfConstantValue(constantValue), typeof constantValue === "number" ? SymbolDisplayPartKind.numericLiteral : SymbolDisplayPartKind.stringLiteral)); + displayParts.push( + displayPart( + getTextOfConstantValue(constantValue), + typeof constantValue === "number" ? SymbolDisplayPartKind.numericLiteral + : SymbolDisplayPartKind.stringLiteral, + ), + ); } } } @@ -550,8 +636,8 @@ function getSymbolDisplayPartsDocumentationAndSymbolKindWorker(typeChecker: Type const resolvedNode = resolvedSymbol.declarations[0]; const declarationName = getNameOfDeclaration(resolvedNode); if (declarationName && !hasAddedSymbolInfo) { - const isExternalModuleDeclaration = isModuleWithStringLiteralName(resolvedNode) && - hasSyntacticModifier(resolvedNode, ModifierFlags.Ambient); + const isExternalModuleDeclaration = isModuleWithStringLiteralName(resolvedNode) + && hasSyntacticModifier(resolvedNode, ModifierFlags.Ambient); const shouldUseAliasName = symbol.name !== "default" && !isExternalModuleDeclaration; const resolvedInfo = getSymbolDisplayPartsDocumentationAndSymbolKindWorker( typeChecker, @@ -569,7 +655,10 @@ function getSymbolDisplayPartsDocumentationAndSymbolKindWorker(typeChecker: Type tagsFromAlias = resolvedInfo.tags; } else { - documentationFromAlias = resolvedSymbol.getContextualDocumentationComment(resolvedNode, typeChecker); + documentationFromAlias = resolvedSymbol.getContextualDocumentationComment( + resolvedNode, + typeChecker, + ); tagsFromAlias = resolvedSymbol.getJsDocTags(typeChecker); } } @@ -585,7 +674,12 @@ function getSymbolDisplayPartsDocumentationAndSymbolKindWorker(typeChecker: Type case SyntaxKind.ExportAssignment: displayParts.push(keywordPart(SyntaxKind.ExportKeyword)); displayParts.push(spacePart()); - displayParts.push(keywordPart((symbol.declarations[0] as ExportAssignment).isExportEquals ? SyntaxKind.EqualsToken : SyntaxKind.DefaultKeyword)); + displayParts.push( + keywordPart( + (symbol.declarations[0] as ExportAssignment).isExportEquals ? SyntaxKind.EqualsToken + : SyntaxKind.DefaultKeyword, + ), + ); break; case SyntaxKind.ExportSpecifier: displayParts.push(keywordPart(SyntaxKind.ExportKeyword)); @@ -605,11 +699,18 @@ function getSymbolDisplayPartsDocumentationAndSymbolKindWorker(typeChecker: Type displayParts.push(spacePart()); displayParts.push(keywordPart(SyntaxKind.RequireKeyword)); displayParts.push(punctuationPart(SyntaxKind.OpenParenToken)); - displayParts.push(displayPart(getTextOfNode(getExternalModuleImportEqualsDeclarationExpression(importEqualsDeclaration)), SymbolDisplayPartKind.stringLiteral)); + displayParts.push( + displayPart( + getTextOfNode(getExternalModuleImportEqualsDeclarationExpression(importEqualsDeclaration)), + SymbolDisplayPartKind.stringLiteral, + ), + ); displayParts.push(punctuationPart(SyntaxKind.CloseParenToken)); } else { - const internalAliasSymbol = typeChecker.getSymbolAtLocation(importEqualsDeclaration.moduleReference); + const internalAliasSymbol = typeChecker.getSymbolAtLocation( + importEqualsDeclaration.moduleReference, + ); if (internalAliasSymbol) { displayParts.push(spacePart()); displayParts.push(operatorPart(SyntaxKind.EqualsToken)); @@ -633,32 +734,47 @@ function getSymbolDisplayPartsDocumentationAndSymbolKindWorker(typeChecker: Type } // For properties, variables and local vars: show the type if ( - symbolKind === ScriptElementKind.memberVariableElement || - symbolKind === ScriptElementKind.memberAccessorVariableElement || - symbolKind === ScriptElementKind.memberGetAccessorElement || - symbolKind === ScriptElementKind.memberSetAccessorElement || - symbolKind === ScriptElementKind.jsxAttribute || - symbolFlags & SymbolFlags.Variable || - symbolKind === ScriptElementKind.localVariableElement || - symbolKind === ScriptElementKind.indexSignatureElement || - symbolKind === ScriptElementKind.variableUsingElement || - symbolKind === ScriptElementKind.variableAwaitUsingElement || - isThisExpression + symbolKind === ScriptElementKind.memberVariableElement + || symbolKind === ScriptElementKind.memberAccessorVariableElement + || symbolKind === ScriptElementKind.memberGetAccessorElement + || symbolKind === ScriptElementKind.memberSetAccessorElement + || symbolKind === ScriptElementKind.jsxAttribute + || symbolFlags & SymbolFlags.Variable + || symbolKind === ScriptElementKind.localVariableElement + || symbolKind === ScriptElementKind.indexSignatureElement + || symbolKind === ScriptElementKind.variableUsingElement + || symbolKind === ScriptElementKind.variableAwaitUsingElement + || isThisExpression ) { displayParts.push(punctuationPart(SyntaxKind.ColonToken)); displayParts.push(spacePart()); // If the type is type parameter, format it specially - if (type.symbol && type.symbol.flags & SymbolFlags.TypeParameter && symbolKind !== ScriptElementKind.indexSignatureElement) { + if ( + type.symbol && type.symbol.flags & SymbolFlags.TypeParameter + && symbolKind !== ScriptElementKind.indexSignatureElement + ) { const typeParameterParts = mapToDisplayParts(writer => { - const param = typeChecker.typeParameterToDeclaration(type as TypeParameter, enclosingDeclaration, symbolDisplayNodeBuilderFlags)!; - getPrinter().writeNode(EmitHint.Unspecified, param, getSourceFileOfNode(getParseTreeNode(enclosingDeclaration)), writer); + const param = typeChecker.typeParameterToDeclaration( + type as TypeParameter, + enclosingDeclaration, + symbolDisplayNodeBuilderFlags, + )!; + getPrinter().writeNode( + EmitHint.Unspecified, + param, + getSourceFileOfNode(getParseTreeNode(enclosingDeclaration)), + writer, + ); }); addRange(displayParts, typeParameterParts); } else { addRange(displayParts, typeToDisplayParts(typeChecker, type, enclosingDeclaration)); } - if (isTransientSymbol(symbol) && symbol.links.target && isTransientSymbol(symbol.links.target) && symbol.links.target.links.tupleLabelDeclaration) { + if ( + isTransientSymbol(symbol) && symbol.links.target && isTransientSymbol(symbol.links.target) + && symbol.links.target.links.tupleLabelDeclaration + ) { const labelDecl = symbol.links.target.links.tupleLabelDeclaration; Debug.assertNode(labelDecl.name, isIdentifier); displayParts.push(spacePart()); @@ -668,12 +784,12 @@ function getSymbolDisplayPartsDocumentationAndSymbolKindWorker(typeChecker: Type } } else if ( - symbolFlags & SymbolFlags.Function || - symbolFlags & SymbolFlags.Method || - symbolFlags & SymbolFlags.Constructor || - symbolFlags & SymbolFlags.Signature || - symbolFlags & SymbolFlags.Accessor || - symbolKind === ScriptElementKind.memberFunctionElement + symbolFlags & SymbolFlags.Function + || symbolFlags & SymbolFlags.Method + || symbolFlags & SymbolFlags.Constructor + || symbolFlags & SymbolFlags.Signature + || symbolFlags & SymbolFlags.Accessor + || symbolKind === ScriptElementKind.memberFunctionElement ) { const allSignatures = type.getNonNullableType().getCallSignatures(); if (allSignatures.length) { @@ -696,7 +812,10 @@ function getSymbolDisplayPartsDocumentationAndSymbolKindWorker(typeChecker: Type // For some special property access expressions like `exports.foo = foo` or `module.exports.foo = foo` // there documentation comments might be attached to the right hand side symbol of their declarations. // The pattern of such special property access is that the parent symbol is the symbol of the file. - if (symbol.parent && symbol.declarations && forEach(symbol.parent.declarations, declaration => declaration.kind === SyntaxKind.SourceFile)) { + if ( + symbol.parent && symbol.declarations + && forEach(symbol.parent.declarations, declaration => declaration.kind === SyntaxKind.SourceFile) + ) { for (const declaration of symbol.declarations) { if (!declaration.parent || declaration.parent.kind !== SyntaxKind.BinaryExpression) { continue; @@ -716,7 +835,10 @@ function getSymbolDisplayPartsDocumentationAndSymbolKindWorker(typeChecker: Type } } - if (documentation.length === 0 && isIdentifier(location) && symbol.valueDeclaration && isBindingElement(symbol.valueDeclaration)) { + if ( + documentation.length === 0 && isIdentifier(location) && symbol.valueDeclaration + && isBindingElement(symbol.valueDeclaration) + ) { const declaration = symbol.valueDeclaration; const parent = declaration.parent; if (isIdentifier(declaration.name) && isObjectBindingPattern(parent)) { @@ -796,7 +918,14 @@ function getSymbolDisplayPartsDocumentationAndSymbolKindWorker(typeChecker: Type fullSymbolDisplayParts.push(punctuationPart(SyntaxKind.CloseBracketToken)); } else { - fullSymbolDisplayParts = symbolToDisplayParts(typeChecker, symbolToDisplay, enclosingDeclaration || sourceFile, /*meaning*/ undefined, SymbolFormatFlags.WriteTypeParametersOrArguments | SymbolFormatFlags.UseOnlyExternalAliasing | SymbolFormatFlags.AllowAnyNodeKind); + fullSymbolDisplayParts = symbolToDisplayParts( + typeChecker, + symbolToDisplay, + enclosingDeclaration || sourceFile, + /*meaning*/ undefined, + SymbolFormatFlags.WriteTypeParametersOrArguments | SymbolFormatFlags.UseOnlyExternalAliasing + | SymbolFormatFlags.AllowAnyNodeKind, + ); } addRange(displayParts, fullSymbolDisplayParts); if (symbol.flags & SymbolFlags.Optional) { @@ -808,7 +937,13 @@ function getSymbolDisplayPartsDocumentationAndSymbolKindWorker(typeChecker: Type prefixNextMeaning(); if (symbolKind) { pushSymbolKind(symbolKind); - if (symbol && !some(symbol.declarations, d => isArrowFunction(d) || (isFunctionExpression(d) || isClassExpression(d)) && !d.name)) { + if ( + symbol + && !some( + symbol.declarations, + d => isArrowFunction(d) || (isFunctionExpression(d) || isClassExpression(d)) && !d.name, + ) + ) { displayParts.push(spacePart()); addFullSymbolName(symbol); } @@ -834,8 +969,20 @@ function getSymbolDisplayPartsDocumentationAndSymbolKindWorker(typeChecker: Type } } - function addSignatureDisplayParts(signature: Signature, allSignatures: readonly Signature[], flags = TypeFormatFlags.None) { - addRange(displayParts, signatureToDisplayParts(typeChecker, signature, enclosingDeclaration, flags | TypeFormatFlags.WriteTypeArgumentsOfSignature)); + function addSignatureDisplayParts( + signature: Signature, + allSignatures: readonly Signature[], + flags = TypeFormatFlags.None, + ) { + addRange( + displayParts, + signatureToDisplayParts( + typeChecker, + signature, + enclosingDeclaration, + flags | TypeFormatFlags.WriteTypeArgumentsOfSignature, + ), + ); if (allSignatures.length > 1) { displayParts.push(spacePart()); displayParts.push(punctuationPart(SyntaxKind.OpenParenToken)); @@ -856,8 +1003,17 @@ function getSymbolDisplayPartsDocumentationAndSymbolKindWorker(typeChecker: Type function writeTypeParametersOfSymbol(symbol: Symbol, enclosingDeclaration: Node | undefined) { const typeParameterParts = mapToDisplayParts(writer => { - const params = typeChecker.symbolToTypeParameterDeclarations(symbol, enclosingDeclaration, symbolDisplayNodeBuilderFlags); - getPrinter().writeList(ListFormat.TypeParameters, params, getSourceFileOfNode(getParseTreeNode(enclosingDeclaration)), writer); + const params = typeChecker.symbolToTypeParameterDeclarations( + symbol, + enclosingDeclaration, + symbolDisplayNodeBuilderFlags, + ); + getPrinter().writeList( + ListFormat.TypeParameters, + params, + getSourceFileOfNode(getParseTreeNode(enclosingDeclaration)), + writer, + ); }); addRange(displayParts, typeParameterParts); } @@ -865,8 +1021,25 @@ function getSymbolDisplayPartsDocumentationAndSymbolKindWorker(typeChecker: Type // TODO(drosen): Currently completion entry details passes the SemanticMeaning.All instead of using semanticMeaning of location /** @internal */ -export function getSymbolDisplayPartsDocumentationAndSymbolKind(typeChecker: TypeChecker, symbol: Symbol, sourceFile: SourceFile, enclosingDeclaration: Node | undefined, location: Node, semanticMeaning = getMeaningFromLocation(location), alias?: Symbol): SymbolDisplayPartsDocumentationAndSymbolKind { - return getSymbolDisplayPartsDocumentationAndSymbolKindWorker(typeChecker, symbol, sourceFile, enclosingDeclaration, location, /*type*/ undefined, semanticMeaning, alias); +export function getSymbolDisplayPartsDocumentationAndSymbolKind( + typeChecker: TypeChecker, + symbol: Symbol, + sourceFile: SourceFile, + enclosingDeclaration: Node | undefined, + location: Node, + semanticMeaning = getMeaningFromLocation(location), + alias?: Symbol, +): SymbolDisplayPartsDocumentationAndSymbolKind { + return getSymbolDisplayPartsDocumentationAndSymbolKindWorker( + typeChecker, + symbol, + sourceFile, + enclosingDeclaration, + location, + /*type*/ undefined, + semanticMeaning, + alias, + ); } function isLocalVariableOrFunction(symbol: Symbol) { @@ -880,7 +1053,9 @@ function isLocalVariableOrFunction(symbol: Symbol) { return true; } - if (declaration.kind !== SyntaxKind.VariableDeclaration && declaration.kind !== SyntaxKind.FunctionDeclaration) { + if ( + declaration.kind !== SyntaxKind.VariableDeclaration && declaration.kind !== SyntaxKind.FunctionDeclaration + ) { return false; } diff --git a/src/services/textChanges.ts b/src/services/textChanges.ts index 47f5cceabd8a7..8954ba8bbe821 100644 --- a/src/services/textChanges.ts +++ b/src/services/textChanges.ts @@ -346,11 +346,24 @@ interface NewFileInsertion { readonly statements: readonly (Statement | SyntaxKind.NewLineTrivia)[]; } -function getAdjustedRange(sourceFile: SourceFile, startNode: Node, endNode: Node, options: ConfigurableStartEnd): TextRange { - return { pos: getAdjustedStartPosition(sourceFile, startNode, options), end: getAdjustedEndPosition(sourceFile, endNode, options) }; +function getAdjustedRange( + sourceFile: SourceFile, + startNode: Node, + endNode: Node, + options: ConfigurableStartEnd, +): TextRange { + return { + pos: getAdjustedStartPosition(sourceFile, startNode, options), + end: getAdjustedEndPosition(sourceFile, endNode, options), + }; } -function getAdjustedStartPosition(sourceFile: SourceFile, node: Node, options: ConfigurableStartEnd, hasTrailingComment = false) { +function getAdjustedStartPosition( + sourceFile: SourceFile, + node: Node, + options: ConfigurableStartEnd, + hasTrailingComment = false, +) { const { leadingTriviaOption } = options; if (leadingTriviaOption === LeadingTriviaOption.Exclude) { return node.getStart(sourceFile); @@ -388,7 +401,8 @@ function getAdjustedStartPosition(sourceFile: SourceFile, node: Node, options: C if (hasTrailingComment) { // Check first for leading comments as if the node is the first import, we want to exclude the trivia; // otherwise we get the trailing comments. - const comment = getLeadingCommentRanges(sourceFile.text, fullStart)?.[0] || getTrailingCommentRanges(sourceFile.text, fullStart)?.[0]; + const comment = getLeadingCommentRanges(sourceFile.text, fullStart)?.[0] + || getTrailingCommentRanges(sourceFile.text, fullStart)?.[0]; if (comment) { return skipTrivia(sourceFile.text, comment.end, /*stopAfterLineBreak*/ true, /*stopAtComments*/ true); } @@ -397,14 +411,21 @@ function getAdjustedStartPosition(sourceFile: SourceFile, node: Node, options: C // get start position of the line following the line that contains fullstart position // (but only if the fullstart isn't the very beginning of the file) const nextLineStart = fullStart > 0 ? 1 : 0; - let adjustedStartPosition = getStartPositionOfLine(getLineOfLocalPosition(sourceFile, fullStartLine) + nextLineStart, sourceFile); + let adjustedStartPosition = getStartPositionOfLine( + getLineOfLocalPosition(sourceFile, fullStartLine) + nextLineStart, + sourceFile, + ); // skip whitespaces/newlines adjustedStartPosition = skipWhitespacesAndLineBreaks(sourceFile.text, adjustedStartPosition); return getStartPositionOfLine(getLineOfLocalPosition(sourceFile, adjustedStartPosition), sourceFile); } /** Return the end position of a multiline comment of it is on another line; otherwise returns `undefined`; */ -function getEndPositionOfMultilineTrailingComment(sourceFile: SourceFile, node: Node, options: ConfigurableEnd): number | undefined { +function getEndPositionOfMultilineTrailingComment( + sourceFile: SourceFile, + node: Node, + options: ConfigurableEnd, +): number | undefined { const { end } = node; const { trailingTriviaOption } = options; if (trailingTriviaOption === TrailingTriviaOption.Include) { @@ -416,7 +437,10 @@ function getEndPositionOfMultilineTrailingComment(sourceFile: SourceFile, node: for (const comment of comments) { // Single line can break the loop as trivia will only be this line. // Comments on subsequest lines are also ignored. - if (comment.kind === SyntaxKind.SingleLineCommentTrivia || getLineOfLocalPosition(sourceFile, comment.pos) > nodeEndLine) { + if ( + comment.kind === SyntaxKind.SingleLineCommentTrivia + || getLineOfLocalPosition(sourceFile, comment.pos) > nodeEndLine + ) { break; } @@ -425,7 +449,12 @@ function getEndPositionOfMultilineTrailingComment(sourceFile: SourceFile, node: // then is safe to return the end position. const commentEndLine = getLineOfLocalPosition(sourceFile, comment.end); if (commentEndLine > nodeEndLine) { - return skipTrivia(sourceFile.text, comment.end, /*stopAfterLineBreak*/ true, /*stopAtComments*/ true); + return skipTrivia( + sourceFile.text, + comment.end, + /*stopAfterLineBreak*/ true, + /*stopAtComments*/ true, + ); } } } @@ -441,7 +470,10 @@ function getAdjustedEndPosition(sourceFile: SourceFile, node: Node, options: Con return end; } if (trailingTriviaOption === TrailingTriviaOption.ExcludeWhitespace) { - const comments = concatenate(getTrailingCommentRanges(sourceFile.text, end), getLeadingCommentRanges(sourceFile.text, end)); + const comments = concatenate( + getTrailingCommentRanges(sourceFile.text, end), + getLeadingCommentRanges(sourceFile.text, end), + ); const realEnd = comments?.[comments.length - 1]?.end; if (realEnd) { return realEnd; @@ -456,7 +488,9 @@ function getAdjustedEndPosition(sourceFile: SourceFile, node: Node, options: Con const newEnd = skipTrivia(sourceFile.text, end, /*stopAfterLineBreak*/ true); - return newEnd !== end && (trailingTriviaOption === TrailingTriviaOption.Include || isLineBreak(sourceFile.text.charCodeAt(newEnd - 1))) + return newEnd !== end + && (trailingTriviaOption === TrailingTriviaOption.Include + || isLineBreak(sourceFile.text.charCodeAt(newEnd - 1))) ? newEnd : end; } @@ -464,8 +498,14 @@ function getAdjustedEndPosition(sourceFile: SourceFile, node: Node, options: Con /** * Checks if 'candidate' argument is a legal separator in the list that contains 'node' as an element */ -function isSeparator(node: Node, candidate: Node | undefined): candidate is Token { - return !!candidate && !!node.parent && (candidate.kind === SyntaxKind.CommaToken || (candidate.kind === SyntaxKind.SemicolonToken && node.parent.kind === SyntaxKind.ObjectLiteralExpression)); +function isSeparator( + node: Node, + candidate: Node | undefined, +): candidate is Token { + return !!candidate && !!node.parent + && (candidate.kind === SyntaxKind.CommaToken + || (candidate.kind === SyntaxKind.SemicolonToken + && node.parent.kind === SyntaxKind.ObjectLiteralExpression)); } /** @internal */ @@ -476,13 +516,20 @@ export interface TextChangesContext { } /** @internal */ -export type TypeAnnotatable = SignatureDeclaration | VariableDeclaration | ParameterDeclaration | PropertyDeclaration | PropertySignature; +export type TypeAnnotatable = + | SignatureDeclaration + | VariableDeclaration + | ParameterDeclaration + | PropertyDeclaration + | PropertySignature; /** @internal */ export type ThisTypeAnnotatable = FunctionDeclaration | FunctionExpression; /** @internal */ -export function isThisTypeAnnotatable(containingFunction: SignatureDeclaration): containingFunction is ThisTypeAnnotatable { +export function isThisTypeAnnotatable( + containingFunction: SignatureDeclaration, +): containingFunction is ThisTypeAnnotatable { return isFunctionExpression(containingFunction) || isFunctionDeclaration(containingFunction); } @@ -490,11 +537,23 @@ export function isThisTypeAnnotatable(containingFunction: SignatureDeclaration): export class ChangeTracker { private readonly changes: Change[] = []; private newFileChanges?: MultiMap; - private readonly classesWithNodesInsertedAtStart = new Map(); // Set implemented as Map - private readonly deletedNodes: { readonly sourceFile: SourceFile; readonly node: Node | NodeArray; }[] = []; + private readonly classesWithNodesInsertedAtStart = new Map< + number, + { + readonly node: ClassLikeDeclaration | InterfaceDeclaration | ObjectLiteralExpression; + readonly sourceFile: SourceFile; + } + >(); // Set implemented as Map + private readonly deletedNodes: { + readonly sourceFile: SourceFile; + readonly node: Node | NodeArray; + }[] = []; public static fromContext(context: TextChangesContext): ChangeTracker { - return new ChangeTracker(getNewLineOrDefaultFromHost(context.host, context.formatContext.options), context.formatContext); + return new ChangeTracker( + getNewLineOrDefaultFromHost(context.host, context.formatContext.options), + context.formatContext, + ); } public static with(context: TextChangesContext, cb: (tracker: ChangeTracker) => void): FileTextChanges[] { @@ -527,11 +586,20 @@ export class ChangeTracker { } /** Stop! Consider using `delete` instead, which has logic for deleting nodes from delimited lists. */ - public deleteNode(sourceFile: SourceFile, node: Node, options: ConfigurableStartEnd = { leadingTriviaOption: LeadingTriviaOption.IncludeAll }): void { + public deleteNode( + sourceFile: SourceFile, + node: Node, + options: ConfigurableStartEnd = { leadingTriviaOption: LeadingTriviaOption.IncludeAll }, + ): void { this.deleteRange(sourceFile, getAdjustedRange(sourceFile, node, node, options)); } - public deleteNodes(sourceFile: SourceFile, nodes: readonly Node[], options: ConfigurableStartEnd = { leadingTriviaOption: LeadingTriviaOption.IncludeAll }, hasTrailingComment: boolean): void { + public deleteNodes( + sourceFile: SourceFile, + nodes: readonly Node[], + options: ConfigurableStartEnd = { leadingTriviaOption: LeadingTriviaOption.IncludeAll }, + hasTrailingComment: boolean, + ): void { // When deleting multiple nodes we need to track if the end position is including multiline trailing comments. for (const node of nodes) { const pos = getAdjustedStartPosition(sourceFile, node, options, hasTrailingComment); @@ -544,50 +612,114 @@ export class ChangeTracker { } public deleteModifier(sourceFile: SourceFile, modifier: Modifier): void { - this.deleteRange(sourceFile, { pos: modifier.getStart(sourceFile), end: skipTrivia(sourceFile.text, modifier.end, /*stopAfterLineBreak*/ true) }); + this.deleteRange(sourceFile, { + pos: modifier.getStart(sourceFile), + end: skipTrivia(sourceFile.text, modifier.end, /*stopAfterLineBreak*/ true), + }); } - public deleteNodeRange(sourceFile: SourceFile, startNode: Node, endNode: Node, options: ConfigurableStartEnd = { leadingTriviaOption: LeadingTriviaOption.IncludeAll }): void { + public deleteNodeRange( + sourceFile: SourceFile, + startNode: Node, + endNode: Node, + options: ConfigurableStartEnd = { leadingTriviaOption: LeadingTriviaOption.IncludeAll }, + ): void { const startPosition = getAdjustedStartPosition(sourceFile, startNode, options); const endPosition = getAdjustedEndPosition(sourceFile, endNode, options); this.deleteRange(sourceFile, { pos: startPosition, end: endPosition }); } - public deleteNodeRangeExcludingEnd(sourceFile: SourceFile, startNode: Node, afterEndNode: Node | undefined, options: ConfigurableStartEnd = { leadingTriviaOption: LeadingTriviaOption.IncludeAll }): void { + public deleteNodeRangeExcludingEnd( + sourceFile: SourceFile, + startNode: Node, + afterEndNode: Node | undefined, + options: ConfigurableStartEnd = { leadingTriviaOption: LeadingTriviaOption.IncludeAll }, + ): void { const startPosition = getAdjustedStartPosition(sourceFile, startNode, options); - const endPosition = afterEndNode === undefined ? sourceFile.text.length : getAdjustedStartPosition(sourceFile, afterEndNode, options); + const endPosition = afterEndNode === undefined ? sourceFile.text.length + : getAdjustedStartPosition(sourceFile, afterEndNode, options); this.deleteRange(sourceFile, { pos: startPosition, end: endPosition }); } - public replaceRange(sourceFile: SourceFile, range: TextRange, newNode: Node, options: InsertNodeOptions = {}): void { + public replaceRange( + sourceFile: SourceFile, + range: TextRange, + newNode: Node, + options: InsertNodeOptions = {}, + ): void { this.changes.push({ kind: ChangeKind.ReplaceWithSingleNode, sourceFile, range, options, node: newNode }); } - public replaceNode(sourceFile: SourceFile, oldNode: Node, newNode: Node, options: ChangeNodeOptions = useNonAdjustedPositions): void { + public replaceNode( + sourceFile: SourceFile, + oldNode: Node, + newNode: Node, + options: ChangeNodeOptions = useNonAdjustedPositions, + ): void { this.replaceRange(sourceFile, getAdjustedRange(sourceFile, oldNode, oldNode, options), newNode, options); } - public replaceNodeRange(sourceFile: SourceFile, startNode: Node, endNode: Node, newNode: Node, options: ChangeNodeOptions = useNonAdjustedPositions): void { + public replaceNodeRange( + sourceFile: SourceFile, + startNode: Node, + endNode: Node, + newNode: Node, + options: ChangeNodeOptions = useNonAdjustedPositions, + ): void { this.replaceRange(sourceFile, getAdjustedRange(sourceFile, startNode, endNode, options), newNode, options); } - private replaceRangeWithNodes(sourceFile: SourceFile, range: TextRange, newNodes: readonly Node[], options: ReplaceWithMultipleNodesOptions & ConfigurableStartEnd = {}): void { + private replaceRangeWithNodes( + sourceFile: SourceFile, + range: TextRange, + newNodes: readonly Node[], + options: ReplaceWithMultipleNodesOptions & ConfigurableStartEnd = {}, + ): void { this.changes.push({ kind: ChangeKind.ReplaceWithMultipleNodes, sourceFile, range, options, nodes: newNodes }); } - public replaceNodeWithNodes(sourceFile: SourceFile, oldNode: Node, newNodes: readonly Node[], options: ChangeNodeOptions = useNonAdjustedPositions): void { - this.replaceRangeWithNodes(sourceFile, getAdjustedRange(sourceFile, oldNode, oldNode, options), newNodes, options); + public replaceNodeWithNodes( + sourceFile: SourceFile, + oldNode: Node, + newNodes: readonly Node[], + options: ChangeNodeOptions = useNonAdjustedPositions, + ): void { + this.replaceRangeWithNodes( + sourceFile, + getAdjustedRange(sourceFile, oldNode, oldNode, options), + newNodes, + options, + ); } public replaceNodeWithText(sourceFile: SourceFile, oldNode: Node, text: string): void { - this.replaceRangeWithText(sourceFile, getAdjustedRange(sourceFile, oldNode, oldNode, useNonAdjustedPositions), text); + this.replaceRangeWithText( + sourceFile, + getAdjustedRange(sourceFile, oldNode, oldNode, useNonAdjustedPositions), + text, + ); } - public replaceNodeRangeWithNodes(sourceFile: SourceFile, startNode: Node, endNode: Node, newNodes: readonly Node[], options: ReplaceWithMultipleNodesOptions & ConfigurableStartEnd = useNonAdjustedPositions): void { - this.replaceRangeWithNodes(sourceFile, getAdjustedRange(sourceFile, startNode, endNode, options), newNodes, options); + public replaceNodeRangeWithNodes( + sourceFile: SourceFile, + startNode: Node, + endNode: Node, + newNodes: readonly Node[], + options: ReplaceWithMultipleNodesOptions & ConfigurableStartEnd = useNonAdjustedPositions, + ): void { + this.replaceRangeWithNodes( + sourceFile, + getAdjustedRange(sourceFile, startNode, endNode, options), + newNodes, + options, + ); } - public nodeHasTrailingComment(sourceFile: SourceFile, oldNode: Node, configurableEnd: ConfigurableEnd = useNonAdjustedPositions): boolean { + public nodeHasTrailingComment( + sourceFile: SourceFile, + oldNode: Node, + configurableEnd: ConfigurableEnd = useNonAdjustedPositions, + ): boolean { return !!getEndPositionOfMultilineTrailingComment(sourceFile, oldNode, configurableEnd); } @@ -596,7 +728,11 @@ export class ChangeTracker { return next && next.kind === SyntaxKind.CommaToken ? next : undefined; } - public replacePropertyAssignment(sourceFile: SourceFile, oldNode: PropertyAssignment, newNode: PropertyAssignment): void { + public replacePropertyAssignment( + sourceFile: SourceFile, + oldNode: PropertyAssignment, + newNode: PropertyAssignment, + ): void { const suffix = this.nextCommaToken(sourceFile, oldNode) ? "" : ("," + this.newLineCharacter); this.replaceNode(sourceFile, oldNode, newNode, { suffix }); } @@ -605,7 +741,12 @@ export class ChangeTracker { this.replaceRange(sourceFile, createRange(pos), newNode, options); } - private insertNodesAt(sourceFile: SourceFile, pos: number, newNodes: readonly Node[], options: ReplaceWithMultipleNodesOptions = {}): void { + private insertNodesAt( + sourceFile: SourceFile, + pos: number, + newNodes: readonly Node[], + options: ReplaceWithMultipleNodesOptions = {}, + ): void { this.replaceRangeWithNodes(sourceFile, createRange(pos), newNodes, options); } @@ -613,15 +754,24 @@ export class ChangeTracker { this.insertAtTopOfFile(sourceFile, newNode, blankLineBetween); } - public insertNodesAtTopOfFile(sourceFile: SourceFile, newNodes: readonly Statement[], blankLineBetween: boolean): void { + public insertNodesAtTopOfFile( + sourceFile: SourceFile, + newNodes: readonly Statement[], + blankLineBetween: boolean, + ): void { this.insertAtTopOfFile(sourceFile, newNodes, blankLineBetween); } - private insertAtTopOfFile(sourceFile: SourceFile, insert: Statement | readonly Statement[], blankLineBetween: boolean): void { + private insertAtTopOfFile( + sourceFile: SourceFile, + insert: Statement | readonly Statement[], + blankLineBetween: boolean, + ): void { const pos = getInsertionPositionAtSourceFileTop(sourceFile); const options = { prefix: pos === 0 ? undefined : this.newLineCharacter, - suffix: (isLineBreak(sourceFile.text.charCodeAt(pos)) ? "" : this.newLineCharacter) + (blankLineBetween ? this.newLineCharacter : ""), + suffix: (isLineBreak(sourceFile.text.charCodeAt(pos)) ? "" : this.newLineCharacter) + + (blankLineBetween ? this.newLineCharacter : ""), }; if (isArray(insert)) { this.insertNodesAt(sourceFile, pos, insert, options); @@ -652,14 +802,22 @@ export class ChangeTracker { this.insertNodesAt(sourceFile, pos, insert, options); } - private insertStatementsInNewFile(fileName: string, statements: readonly (Statement | SyntaxKind.NewLineTrivia)[], oldFile?: SourceFile): void { + private insertStatementsInNewFile( + fileName: string, + statements: readonly (Statement | SyntaxKind.NewLineTrivia)[], + oldFile?: SourceFile, + ): void { if (!this.newFileChanges) { this.newFileChanges = createMultiMap(); } this.newFileChanges.add(fileName, { oldFile, statements }); } - public insertFirstParameter(sourceFile: SourceFile, parameters: NodeArray, newParam: ParameterDeclaration): void { + public insertFirstParameter( + sourceFile: SourceFile, + parameters: NodeArray, + newParam: ParameterDeclaration, + ): void { const p0 = firstOrUndefined(parameters); if (p0) { this.insertNodeBefore(sourceFile, p0, newParam); @@ -669,15 +827,42 @@ export class ChangeTracker { } } - public insertNodeBefore(sourceFile: SourceFile, before: Node, newNode: Node, blankLineBetween = false, options: ConfigurableStartEnd = {}): void { - this.insertNodeAt(sourceFile, getAdjustedStartPosition(sourceFile, before, options), newNode, this.getOptionsForInsertNodeBefore(before, newNode, blankLineBetween)); + public insertNodeBefore( + sourceFile: SourceFile, + before: Node, + newNode: Node, + blankLineBetween = false, + options: ConfigurableStartEnd = {}, + ): void { + this.insertNodeAt( + sourceFile, + getAdjustedStartPosition(sourceFile, before, options), + newNode, + this.getOptionsForInsertNodeBefore(before, newNode, blankLineBetween), + ); } - public insertNodesBefore(sourceFile: SourceFile, before: Node, newNodes: readonly Node[], blankLineBetween = false, options: ConfigurableStartEnd = {}): void { - this.insertNodesAt(sourceFile, getAdjustedStartPosition(sourceFile, before, options), newNodes, this.getOptionsForInsertNodeBefore(before, first(newNodes), blankLineBetween)); + public insertNodesBefore( + sourceFile: SourceFile, + before: Node, + newNodes: readonly Node[], + blankLineBetween = false, + options: ConfigurableStartEnd = {}, + ): void { + this.insertNodesAt( + sourceFile, + getAdjustedStartPosition(sourceFile, before, options), + newNodes, + this.getOptionsForInsertNodeBefore(before, first(newNodes), blankLineBetween), + ); } - public insertModifierAt(sourceFile: SourceFile, pos: number, modifier: SyntaxKind, options: InsertNodeOptions = {}): void { + public insertModifierAt( + sourceFile: SourceFile, + pos: number, + modifier: SyntaxKind, + options: InsertNodeOptions = {}, + ): void { this.insertNodeAt(sourceFile, pos, factory.createToken(modifier), options); } @@ -685,7 +870,12 @@ export class ChangeTracker { return this.insertModifierAt(sourceFile, before.getStart(sourceFile), modifier, { suffix: " " }); } - public insertCommentBeforeLine(sourceFile: SourceFile, lineNumber: number, position: number, commentText: string): void { + public insertCommentBeforeLine( + sourceFile: SourceFile, + lineNumber: number, + position: number, + commentText: string, + ): void { const lineStartPosition = getStartPositionOfLine(lineNumber, sourceFile); const startPosition = getFirstNonSpaceCharacterPosition(sourceFile.text, lineStartPosition); // First try to see if we can put the comment on the previous line. @@ -695,7 +885,9 @@ export class ChangeTracker { const insertAtLineStart = isValidLocationToAddComment(sourceFile, startPosition); const token = getTouchingToken(sourceFile, insertAtLineStart ? startPosition : position); const indent = sourceFile.text.slice(lineStartPosition, startPosition); - const text = `${insertAtLineStart ? "" : this.newLineCharacter}//${commentText}${this.newLineCharacter}${indent}`; + const text = `${ + insertAtLineStart ? "" : this.newLineCharacter + }//${commentText}${this.newLineCharacter}${indent}`; this.insertText(sourceFile, token.getStart(sourceFile), text); } @@ -715,14 +907,21 @@ export class ChangeTracker { } private createJSDocText(sourceFile: SourceFile, node: HasJSDoc) { - const comments = flatMap(node.jsDoc, jsDoc => isString(jsDoc.comment) ? factory.createJSDocText(jsDoc.comment) : jsDoc.comment) as JSDocComment[]; + const comments = flatMap( + node.jsDoc, + jsDoc => isString(jsDoc.comment) ? factory.createJSDocText(jsDoc.comment) : jsDoc.comment, + ) as JSDocComment[]; const jsDoc = singleOrUndefined(node.jsDoc); - return jsDoc && positionsAreOnSameLine(jsDoc.pos, jsDoc.end, sourceFile) && length(comments) === 0 ? undefined : - factory.createNodeArray(intersperse(comments, factory.createJSDocText("\n"))); + return jsDoc && positionsAreOnSameLine(jsDoc.pos, jsDoc.end, sourceFile) && length(comments) === 0 ? undefined + : factory.createNodeArray(intersperse(comments, factory.createJSDocText("\n"))); } public replaceJSDocComment(sourceFile: SourceFile, node: HasJSDoc, tags: readonly JSDocTag[]) { - this.insertJsdocCommentBefore(sourceFile, updateJSDocHost(node), factory.createJSDocComment(this.createJSDocText(sourceFile, node), factory.createNodeArray(tags))); + this.insertJsdocCommentBefore( + sourceFile, + updateJSDocHost(node), + factory.createJSDocComment(this.createJSDocText(sourceFile, node), factory.createNodeArray(tags)), + ); } public addJSDocTags(sourceFile: SourceFile, parent: HasJSDoc, newTags: readonly JSDocTag[]): void { @@ -761,7 +960,8 @@ export class ChangeTracker { } } else { - endNode = (node.kind === SyntaxKind.VariableDeclaration ? node.exclamationToken : node.questionToken) ?? node.name; + endNode = (node.kind === SyntaxKind.VariableDeclaration ? node.exclamationToken : node.questionToken) + ?? node.name; } this.insertNodeAt(sourceFile, endNode.end, type, { prefix: ": " }); @@ -775,9 +975,15 @@ export class ChangeTracker { this.insertNodeAt(sourceFile, start, type, { prefix: "this: ", suffix }); } - public insertTypeParameters(sourceFile: SourceFile, node: SignatureDeclaration, typeParameters: readonly TypeParameterDeclaration[]): void { + public insertTypeParameters( + sourceFile: SourceFile, + node: SignatureDeclaration, + typeParameters: readonly TypeParameterDeclaration[], + ): void { // If no `(`, is an arrow function `x => x`, so use the pos of the first parameter - const start = (findChildOfKind(node, SyntaxKind.OpenParenToken, sourceFile) || first(node.parameters)).getStart(sourceFile); + const start = (findChildOfKind(node, SyntaxKind.OpenParenToken, sourceFile) || first(node.parameters)).getStart( + sourceFile, + ); this.insertNodesAt(sourceFile, start, typeParameters, { prefix: "<", suffix: ">", joiner: ", " }); } @@ -800,7 +1006,11 @@ export class ChangeTracker { return Debug.failBadSyntaxKind(before); // We haven't handled this kind of node yet -- add it } - public insertNodeAtConstructorStart(sourceFile: SourceFile, ctr: ConstructorDeclaration, newStatement: Statement): void { + public insertNodeAtConstructorStart( + sourceFile: SourceFile, + ctr: ConstructorDeclaration, + newStatement: Statement, + ): void { const firstStatement = firstOrUndefined(ctr.body!.statements); if (!firstStatement || !ctr.body!.multiLine) { this.replaceConstructorBody(sourceFile, ctr, [newStatement, ...ctr.body!.statements]); @@ -810,8 +1020,15 @@ export class ChangeTracker { } } - public insertNodeAtConstructorStartAfterSuperCall(sourceFile: SourceFile, ctr: ConstructorDeclaration, newStatement: Statement): void { - const superCallStatement = find(ctr.body!.statements, stmt => isExpressionStatement(stmt) && isSuperCall(stmt.expression)); + public insertNodeAtConstructorStartAfterSuperCall( + sourceFile: SourceFile, + ctr: ConstructorDeclaration, + newStatement: Statement, + ): void { + const superCallStatement = find( + ctr.body!.statements, + stmt => isExpressionStatement(stmt) && isSuperCall(stmt.expression), + ); if (!superCallStatement || !ctr.body!.multiLine) { this.replaceConstructorBody(sourceFile, ctr, [...ctr.body!.statements, newStatement]); } @@ -820,7 +1037,11 @@ export class ChangeTracker { } } - public insertNodeAtConstructorEnd(sourceFile: SourceFile, ctr: ConstructorDeclaration, newStatement: Statement): void { + public insertNodeAtConstructorEnd( + sourceFile: SourceFile, + ctr: ConstructorDeclaration, + newStatement: Statement, + ): void { const lastStatement = lastOrUndefined(ctr.body!.statements); if (!lastStatement || !ctr.body!.multiLine) { this.replaceConstructorBody(sourceFile, ctr, [...ctr.body!.statements, newStatement]); @@ -830,36 +1051,62 @@ export class ChangeTracker { } } - private replaceConstructorBody(sourceFile: SourceFile, ctr: ConstructorDeclaration, statements: readonly Statement[]): void { + private replaceConstructorBody( + sourceFile: SourceFile, + ctr: ConstructorDeclaration, + statements: readonly Statement[], + ): void { this.replaceNode(sourceFile, ctr.body!, factory.createBlock(statements, /*multiLine*/ true)); } public insertNodeAtEndOfScope(sourceFile: SourceFile, scope: Node, newNode: Node): void { const pos = getAdjustedStartPosition(sourceFile, scope.getLastToken()!, {}); this.insertNodeAt(sourceFile, pos, newNode, { - prefix: isLineBreak(sourceFile.text.charCodeAt(scope.getLastToken()!.pos)) ? this.newLineCharacter : this.newLineCharacter + this.newLineCharacter, + prefix: isLineBreak(sourceFile.text.charCodeAt(scope.getLastToken()!.pos)) ? this.newLineCharacter + : this.newLineCharacter + this.newLineCharacter, suffix: this.newLineCharacter, }); } - public insertMemberAtStart(sourceFile: SourceFile, node: ClassLikeDeclaration | InterfaceDeclaration | TypeLiteralNode, newElement: ClassElement | PropertySignature | MethodSignature): void { + public insertMemberAtStart( + sourceFile: SourceFile, + node: ClassLikeDeclaration | InterfaceDeclaration | TypeLiteralNode, + newElement: ClassElement | PropertySignature | MethodSignature, + ): void { this.insertNodeAtStartWorker(sourceFile, node, newElement); } - public insertNodeAtObjectStart(sourceFile: SourceFile, obj: ObjectLiteralExpression, newElement: ObjectLiteralElementLike): void { + public insertNodeAtObjectStart( + sourceFile: SourceFile, + obj: ObjectLiteralExpression, + newElement: ObjectLiteralElementLike, + ): void { this.insertNodeAtStartWorker(sourceFile, obj, newElement); } - private insertNodeAtStartWorker(sourceFile: SourceFile, node: ClassLikeDeclaration | InterfaceDeclaration | ObjectLiteralExpression | TypeLiteralNode, newElement: ClassElement | ObjectLiteralElementLike | PropertySignature | MethodSignature): void { - const indentation = this.guessIndentationFromExistingMembers(sourceFile, node) ?? this.computeIndentationForNewMember(sourceFile, node); - this.insertNodeAt(sourceFile, getMembersOrProperties(node).pos, newElement, this.getInsertNodeAtStartInsertOptions(sourceFile, node, indentation)); + private insertNodeAtStartWorker( + sourceFile: SourceFile, + node: ClassLikeDeclaration | InterfaceDeclaration | ObjectLiteralExpression | TypeLiteralNode, + newElement: ClassElement | ObjectLiteralElementLike | PropertySignature | MethodSignature, + ): void { + const indentation = this.guessIndentationFromExistingMembers(sourceFile, node) + ?? this.computeIndentationForNewMember(sourceFile, node); + this.insertNodeAt( + sourceFile, + getMembersOrProperties(node).pos, + newElement, + this.getInsertNodeAtStartInsertOptions(sourceFile, node, indentation), + ); } /** * Tries to guess the indentation from the existing members of a class/interface/object. All members must be on * new lines and must share the same indentation. */ - private guessIndentationFromExistingMembers(sourceFile: SourceFile, node: ClassLikeDeclaration | InterfaceDeclaration | ObjectLiteralExpression | TypeLiteralNode) { + private guessIndentationFromExistingMembers( + sourceFile: SourceFile, + node: ClassLikeDeclaration | InterfaceDeclaration | ObjectLiteralExpression | TypeLiteralNode, + ) { let indentation: number | undefined; let lastRange: TextRange = node; for (const member of getMembersOrProperties(node)) { @@ -868,7 +1115,12 @@ export class ChangeTracker { return undefined; } const memberStart = member.getStart(sourceFile); - const memberIndentation = formatting.SmartIndenter.findFirstNonWhitespaceColumn(getLineStartPositionForPosition(memberStart, sourceFile), memberStart, sourceFile, this.formatContext.options); + const memberIndentation = formatting.SmartIndenter.findFirstNonWhitespaceColumn( + getLineStartPositionForPosition(memberStart, sourceFile), + memberStart, + sourceFile, + this.formatContext.options, + ); if (indentation === undefined) { indentation = memberIndentation; } @@ -881,13 +1133,25 @@ export class ChangeTracker { return indentation; } - private computeIndentationForNewMember(sourceFile: SourceFile, node: ClassLikeDeclaration | InterfaceDeclaration | ObjectLiteralExpression | TypeLiteralNode) { + private computeIndentationForNewMember( + sourceFile: SourceFile, + node: ClassLikeDeclaration | InterfaceDeclaration | ObjectLiteralExpression | TypeLiteralNode, + ) { const nodeStart = node.getStart(sourceFile); - return formatting.SmartIndenter.findFirstNonWhitespaceColumn(getLineStartPositionForPosition(nodeStart, sourceFile), nodeStart, sourceFile, this.formatContext.options) + return formatting.SmartIndenter.findFirstNonWhitespaceColumn( + getLineStartPositionForPosition(nodeStart, sourceFile), + nodeStart, + sourceFile, + this.formatContext.options, + ) + (this.formatContext.options.indentSize ?? 4); } - private getInsertNodeAtStartInsertOptions(sourceFile: SourceFile, node: ClassLikeDeclaration | InterfaceDeclaration | ObjectLiteralExpression | TypeLiteralNode, indentation: number): InsertNodeOptions { + private getInsertNodeAtStartInsertOptions( + sourceFile: SourceFile, + node: ClassLikeDeclaration | InterfaceDeclaration | ObjectLiteralExpression | TypeLiteralNode, + indentation: number, + ): InsertNodeOptions { // Rules: // - Always insert leading newline. // - For object literals: @@ -902,7 +1166,8 @@ export class ChangeTracker { const isEmpty = members.length === 0; const isFirstInsertion = addToSeen(this.classesWithNodesInsertedAtStart, getNodeId(node), { node, sourceFile }); const insertTrailingComma = isObjectLiteralExpression(node) && (!isJsonSourceFile(sourceFile) || !isEmpty); - const insertLeadingComma = isObjectLiteralExpression(node) && isJsonSourceFile(sourceFile) && isEmpty && !isFirstInsertion; + const insertLeadingComma = isObjectLiteralExpression(node) && isJsonSourceFile(sourceFile) && isEmpty + && !isFirstInsertion; return { indentation, prefix: (insertLeadingComma ? "," : "") + this.newLineCharacter, @@ -911,7 +1176,11 @@ export class ChangeTracker { } public insertNodeAfterComma(sourceFile: SourceFile, after: Node, newNode: Node): void { - const endPosition = this.insertNodeAfterWorker(sourceFile, this.nextCommaToken(sourceFile, after) || after, newNode); + const endPosition = this.insertNodeAfterWorker( + sourceFile, + this.nextCommaToken(sourceFile, after) || after, + newNode, + ); this.insertNodeAt(sourceFile, endPosition, newNode, this.getInsertNodeAfterOptions(sourceFile, after)); } @@ -945,7 +1214,8 @@ export class ChangeTracker { const options = this.getInsertNodeAfterOptionsWorker(after); return { ...options, - prefix: after.end === sourceFile.end && isStatement(after) ? (options.prefix ? `\n${options.prefix}` : "\n") : options.prefix, + prefix: after.end === sourceFile.end && isStatement(after) ? (options.prefix ? `\n${options.prefix}` : "\n") + : options.prefix, }; } @@ -975,14 +1245,21 @@ export class ChangeTracker { } } - public insertName(sourceFile: SourceFile, node: FunctionExpression | ClassExpression | ArrowFunction, name: string): void { + public insertName( + sourceFile: SourceFile, + node: FunctionExpression | ClassExpression | ArrowFunction, + name: string, + ): void { Debug.assert(!node.name); if (node.kind === SyntaxKind.ArrowFunction) { const arrow = findChildOfKind(node, SyntaxKind.EqualsGreaterThanToken, sourceFile)!; const lparen = findChildOfKind(node, SyntaxKind.OpenParenToken, sourceFile); if (lparen) { // `() => {}` --> `function f() {}` - this.insertNodesAt(sourceFile, lparen.getStart(sourceFile), [factory.createToken(SyntaxKind.FunctionKeyword), factory.createIdentifier(name)], { joiner: " " }); + this.insertNodesAt(sourceFile, lparen.getStart(sourceFile), [ + factory.createToken(SyntaxKind.FunctionKeyword), + factory.createIdentifier(name), + ], { joiner: " " }); deleteNode(this, sourceFile, arrow); } else { @@ -994,12 +1271,22 @@ export class ChangeTracker { if (node.body.kind !== SyntaxKind.Block) { // `() => 0` => `function f() { return 0; }` - this.insertNodesAt(sourceFile, node.body.getStart(sourceFile), [factory.createToken(SyntaxKind.OpenBraceToken), factory.createToken(SyntaxKind.ReturnKeyword)], { joiner: " ", suffix: " " }); - this.insertNodesAt(sourceFile, node.body.end, [factory.createToken(SyntaxKind.SemicolonToken), factory.createToken(SyntaxKind.CloseBraceToken)], { joiner: " " }); + this.insertNodesAt(sourceFile, node.body.getStart(sourceFile), [ + factory.createToken(SyntaxKind.OpenBraceToken), + factory.createToken(SyntaxKind.ReturnKeyword), + ], { joiner: " ", suffix: " " }); + this.insertNodesAt(sourceFile, node.body.end, [ + factory.createToken(SyntaxKind.SemicolonToken), + factory.createToken(SyntaxKind.CloseBraceToken), + ], { joiner: " " }); } } else { - const pos = findChildOfKind(node, node.kind === SyntaxKind.FunctionExpression ? SyntaxKind.FunctionKeyword : SyntaxKind.ClassKeyword, sourceFile)!.end; + const pos = findChildOfKind( + node, + node.kind === SyntaxKind.FunctionExpression ? SyntaxKind.FunctionKeyword : SyntaxKind.ClassKeyword, + sourceFile, + )!.end; this.insertNodeAt(sourceFile, pos, factory.createIdentifier(name), { prefix: " " }); } } @@ -1008,7 +1295,12 @@ export class ChangeTracker { this.insertText(sourceFile, node.getStart(sourceFile), "export "); } - public insertImportSpecifierAtIndex(sourceFile: SourceFile, importSpecifier: ImportSpecifier, namedImports: NamedImports, index: number) { + public insertImportSpecifierAtIndex( + sourceFile: SourceFile, + importSpecifier: ImportSpecifier, + namedImports: NamedImports, + index: number, + ) { const prevSpecifier = namedImports.elements[index - 1]; if (prevSpecifier) { this.insertNodeInListAfter(sourceFile, prevSpecifier, importSpecifier); @@ -1018,7 +1310,11 @@ export class ChangeTracker { sourceFile, namedImports.elements[0], importSpecifier, - !positionsAreOnSameLine(namedImports.elements[0].getStart(), namedImports.parent.parent.getStart(), sourceFile), + !positionsAreOnSameLine( + namedImports.elements[0].getStart(), + namedImports.parent.parent.getStart(), + sourceFile, + ), ); } } @@ -1028,7 +1324,12 @@ export class ChangeTracker { * i.e. arguments in arguments lists, parameters in parameter lists etc. * Note that separators are part of the node in statements and class elements. */ - public insertNodeInListAfter(sourceFile: SourceFile, after: Node, newNode: Node, containingList = formatting.SmartIndenter.getContainingList(after, sourceFile)): void { + public insertNodeInListAfter( + sourceFile: SourceFile, + after: Node, + newNode: Node, + containingList = formatting.SmartIndenter.getContainingList(after, sourceFile), + ): void { if (!containingList) { Debug.fail("node is not a list element"); return; @@ -1087,9 +1388,13 @@ export class ChangeTracker { else { // element has more than one element, pick separator from the list const tokenBeforeInsertPosition = findPrecedingToken(after.pos, sourceFile); - separator = isSeparator(after, tokenBeforeInsertPosition) ? tokenBeforeInsertPosition.kind : SyntaxKind.CommaToken; + separator = isSeparator(after, tokenBeforeInsertPosition) ? tokenBeforeInsertPosition.kind + : SyntaxKind.CommaToken; // determine if list is multiline by checking lines of after element and element that precedes it. - const afterMinusOneStartLinePosition = getLineStartPositionForPosition(containingList[index - 1].getStart(sourceFile), sourceFile); + const afterMinusOneStartLinePosition = getLineStartPositionForPosition( + containingList[index - 1].getStart(sourceFile), + sourceFile, + ); multilineList = afterMinusOneStartLinePosition !== afterStartLinePosition; } if (hasCommentsBeforeLineBreak(sourceFile.text, after.end)) { @@ -1100,14 +1405,22 @@ export class ChangeTracker { // insert separator immediately following the 'after' node to preserve comments in trailing trivia this.replaceRange(sourceFile, createRange(end), factory.createToken(separator)); // use the same indentation as 'after' item - const indentation = formatting.SmartIndenter.findFirstNonWhitespaceColumn(afterStartLinePosition, afterStart, sourceFile, this.formatContext.options); + const indentation = formatting.SmartIndenter.findFirstNonWhitespaceColumn( + afterStartLinePosition, + afterStart, + sourceFile, + this.formatContext.options, + ); // insert element before the line break on the line that contains 'after' element let insertPos = skipTrivia(sourceFile.text, end, /*stopAfterLineBreak*/ true, /*stopAtComments*/ false); // find position before "\n" or "\r\n" while (insertPos !== end && isLineBreak(sourceFile.text.charCodeAt(insertPos - 1))) { insertPos--; } - this.replaceRange(sourceFile, createRange(insertPos), newNode, { indentation, prefix: this.newLineCharacter }); + this.replaceRange(sourceFile, createRange(insertPos), newNode, { + indentation, + prefix: this.newLineCharacter, + }); } else { this.replaceRange(sourceFile, createRange(end), newNode, { prefix: `${tokenToString(separator)} ` }); @@ -1139,7 +1452,9 @@ export class ChangeTracker { private finishDeleteDeclarations(): void { const deletedNodesInLists = new Set(); // Stores nodes in lists that we already deleted. Used to avoid deleting `, ` twice in `a, b`. for (const { sourceFile, node } of this.deletedNodes) { - if (!this.deletedNodes.some(d => d.sourceFile === sourceFile && rangeContainsRangeExclusive(d.node, node))) { + if ( + !this.deletedNodes.some(d => d.sourceFile === sourceFile && rangeContainsRangeExclusive(d.node, node)) + ) { if (isArray(node)) { this.deleteRange(sourceFile, rangeOfTypeParameters(sourceFile, node)); } @@ -1156,7 +1471,10 @@ export class ChangeTracker { const lastNonDeletedIndex = findLastIndex(list, n => !deletedNodesInLists.has(n), list.length - 2); if (lastNonDeletedIndex !== -1) { - this.deleteRange(sourceFile, { pos: list[lastNonDeletedIndex].end, end: startPositionToDeleteNodeInList(sourceFile, list[lastNonDeletedIndex + 1]) }); + this.deleteRange(sourceFile, { + pos: list[lastNonDeletedIndex].end, + end: startPositionToDeleteNodeInList(sourceFile, list[lastNonDeletedIndex + 1]), + }); } }); } @@ -1170,16 +1488,27 @@ export class ChangeTracker { public getChanges(validate?: ValidateNonFormattedText): FileTextChanges[] { this.finishDeleteDeclarations(); this.finishClassesWithNodesInsertedAtStart(); - const changes = changesToText.getTextChangesFromChanges(this.changes, this.newLineCharacter, this.formatContext, validate); + const changes = changesToText.getTextChangesFromChanges( + this.changes, + this.newLineCharacter, + this.formatContext, + validate, + ); if (this.newFileChanges) { this.newFileChanges.forEach((insertions, fileName) => { - changes.push(changesToText.newFileChanges(fileName, insertions, this.newLineCharacter, this.formatContext)); + changes.push( + changesToText.newFileChanges(fileName, insertions, this.newLineCharacter, this.formatContext), + ); }); } return changes; } - public createNewFile(oldFile: SourceFile | undefined, fileName: string, statements: readonly (Statement | SyntaxKind.NewLineTrivia)[]): void { + public createNewFile( + oldFile: SourceFile | undefined, + fileName: string, + statements: readonly (Statement | SyntaxKind.NewLineTrivia)[], + ): void { this.insertStatementsInNewFile(fileName, statements, oldFile); } } @@ -1188,9 +1517,9 @@ function updateJSDocHost(parent: HasJSDoc): HasJSDoc { if (parent.kind !== SyntaxKind.ArrowFunction) { return parent; } - const jsDocNode = parent.parent.kind === SyntaxKind.PropertyDeclaration ? - parent.parent as HasJSDoc : - parent.parent.parent as HasJSDoc; + const jsDocNode = parent.parent.kind === SyntaxKind.PropertyDeclaration + ? parent.parent as HasJSDoc + : parent.parent.parent as HasJSDoc; jsDocNode.jsDoc = parent.jsDoc; return jsDocNode; } @@ -1203,32 +1532,65 @@ function tryMergeJsdocTags(oldTag: JSDocTag, newTag: JSDocTag): JSDocTag | undef case SyntaxKind.JSDocParameterTag: { const oldParam = oldTag as JSDocParameterTag; const newParam = newTag as JSDocParameterTag; - return isIdentifier(oldParam.name) && isIdentifier(newParam.name) && oldParam.name.escapedText === newParam.name.escapedText - ? factory.createJSDocParameterTag(/*tagName*/ undefined, newParam.name, /*isBracketed*/ false, newParam.typeExpression, newParam.isNameFirst, oldParam.comment) + return isIdentifier(oldParam.name) && isIdentifier(newParam.name) + && oldParam.name.escapedText === newParam.name.escapedText + ? factory.createJSDocParameterTag( + /*tagName*/ undefined, + newParam.name, + /*isBracketed*/ false, + newParam.typeExpression, + newParam.isNameFirst, + oldParam.comment, + ) : undefined; } case SyntaxKind.JSDocReturnTag: - return factory.createJSDocReturnTag(/*tagName*/ undefined, (newTag as JSDocReturnTag).typeExpression, oldTag.comment); + return factory.createJSDocReturnTag( + /*tagName*/ undefined, + (newTag as JSDocReturnTag).typeExpression, + oldTag.comment, + ); case SyntaxKind.JSDocTypeTag: - return factory.createJSDocTypeTag(/*tagName*/ undefined, (newTag as JSDocTypeTag).typeExpression, oldTag.comment); + return factory.createJSDocTypeTag( + /*tagName*/ undefined, + (newTag as JSDocTypeTag).typeExpression, + oldTag.comment, + ); } } // find first non-whitespace position in the leading trivia of the node function startPositionToDeleteNodeInList(sourceFile: SourceFile, node: Node): number { - return skipTrivia(sourceFile.text, getAdjustedStartPosition(sourceFile, node, { leadingTriviaOption: LeadingTriviaOption.IncludeAll }), /*stopAfterLineBreak*/ false, /*stopAtComments*/ true); + return skipTrivia( + sourceFile.text, + getAdjustedStartPosition(sourceFile, node, { leadingTriviaOption: LeadingTriviaOption.IncludeAll }), + /*stopAfterLineBreak*/ false, + /*stopAtComments*/ true, + ); } -function endPositionToDeleteNodeInList(sourceFile: SourceFile, node: Node, prevNode: Node | undefined, nextNode: Node): number { +function endPositionToDeleteNodeInList( + sourceFile: SourceFile, + node: Node, + prevNode: Node | undefined, + nextNode: Node, +): number { const end = startPositionToDeleteNodeInList(sourceFile, nextNode); - if (prevNode === undefined || positionsAreOnSameLine(getAdjustedEndPosition(sourceFile, node, {}), end, sourceFile)) { + if ( + prevNode === undefined || positionsAreOnSameLine(getAdjustedEndPosition(sourceFile, node, {}), end, sourceFile) + ) { return end; } const token = findPrecedingToken(nextNode.getStart(sourceFile), sourceFile); if (isSeparator(node, token)) { const prevToken = findPrecedingToken(node.getStart(sourceFile), sourceFile); if (isSeparator(prevNode, prevToken)) { - const pos = skipTrivia(sourceFile.text, token.getEnd(), /*stopAfterLineBreak*/ true, /*stopAtComments*/ true); + const pos = skipTrivia( + sourceFile.text, + token.getEnd(), + /*stopAfterLineBreak*/ true, + /*stopAtComments*/ true, + ); if (positionsAreOnSameLine(prevToken.getStart(sourceFile), token.getStart(sourceFile), sourceFile)) { return isLineBreak(sourceFile.text.charCodeAt(pos - 1)) ? pos - 1 : pos; } @@ -1240,12 +1602,17 @@ function endPositionToDeleteNodeInList(sourceFile: SourceFile, node: Node, prevN return end; } -function getClassOrObjectBraceEnds(cls: ClassLikeDeclaration | InterfaceDeclaration | ObjectLiteralExpression, sourceFile: SourceFile): [number | undefined, number | undefined] { +function getClassOrObjectBraceEnds( + cls: ClassLikeDeclaration | InterfaceDeclaration | ObjectLiteralExpression, + sourceFile: SourceFile, +): [number | undefined, number | undefined] { const open = findChildOfKind(cls, SyntaxKind.OpenBraceToken, sourceFile); const close = findChildOfKind(cls, SyntaxKind.CloseBraceToken, sourceFile); return [open?.end, close?.end]; } -function getMembersOrProperties(node: ClassLikeDeclaration | InterfaceDeclaration | ObjectLiteralExpression | TypeLiteralNode): NodeArray { +function getMembersOrProperties( + node: ClassLikeDeclaration | InterfaceDeclaration | ObjectLiteralExpression | TypeLiteralNode, +): NodeArray { return isObjectLiteralExpression(node) ? node.properties : node.members; } @@ -1253,23 +1620,44 @@ function getMembersOrProperties(node: ClassLikeDeclaration | InterfaceDeclaratio export type ValidateNonFormattedText = (node: Node, text: string) => void; namespace changesToText { - export function getTextChangesFromChanges(changes: readonly Change[], newLineCharacter: string, formatContext: formatting.FormatContext, validate: ValidateNonFormattedText | undefined): FileTextChanges[] { + export function getTextChangesFromChanges( + changes: readonly Change[], + newLineCharacter: string, + formatContext: formatting.FormatContext, + validate: ValidateNonFormattedText | undefined, + ): FileTextChanges[] { return mapDefined(group(changes, c => c.sourceFile.path), changesInFile => { const sourceFile = changesInFile[0].sourceFile; // order changes by start position // If the start position is the same, put the shorter range first, since an empty range (x, x) may precede (x, y) but not vice-versa. - const normalized = stableSort(changesInFile, (a, b) => (a.range.pos - b.range.pos) || (a.range.end - b.range.end)); + const normalized = stableSort( + changesInFile, + (a, b) => (a.range.pos - b.range.pos) || (a.range.end - b.range.end), + ); // verify that change intervals do not overlap, except possibly at end points. for (let i = 0; i < normalized.length - 1; i++) { - Debug.assert(normalized[i].range.end <= normalized[i + 1].range.pos, "Changes overlap", () => `${JSON.stringify(normalized[i].range)} and ${JSON.stringify(normalized[i + 1].range)}`); + Debug.assert( + normalized[i].range.end <= normalized[i + 1].range.pos, + "Changes overlap", + () => `${JSON.stringify(normalized[i].range)} and ${JSON.stringify(normalized[i + 1].range)}`, + ); } const textChanges = mapDefined(normalized, c => { const span = createTextSpanFromRange(c.range); - const targetSourceFile = c.kind === ChangeKind.ReplaceWithSingleNode ? getSourceFileOfNode(getOriginalNode(c.node)) ?? c.sourceFile : - c.kind === ChangeKind.ReplaceWithMultipleNodes ? getSourceFileOfNode(getOriginalNode(c.nodes[0])) ?? c.sourceFile : - c.sourceFile; - const newText = computeNewText(c, targetSourceFile, sourceFile, newLineCharacter, formatContext, validate); + const targetSourceFile = c.kind === ChangeKind.ReplaceWithSingleNode + ? getSourceFileOfNode(getOriginalNode(c.node)) ?? c.sourceFile + : c.kind === ChangeKind.ReplaceWithMultipleNodes + ? getSourceFileOfNode(getOriginalNode(c.nodes[0])) ?? c.sourceFile + : c.sourceFile; + const newText = computeNewText( + c, + targetSourceFile, + sourceFile, + newLineCharacter, + formatContext, + validate, + ); // Filter out redundant changes. if (span.length === newText.length && stringContainsAt(targetSourceFile.text, newText, span.start)) { return undefined; @@ -1282,20 +1670,55 @@ namespace changesToText { }); } - export function newFileChanges(fileName: string, insertions: readonly NewFileInsertion[], newLineCharacter: string, formatContext: formatting.FormatContext): FileTextChanges { - const text = newFileChangesWorker(getScriptKindFromFileName(fileName), insertions, newLineCharacter, formatContext); + export function newFileChanges( + fileName: string, + insertions: readonly NewFileInsertion[], + newLineCharacter: string, + formatContext: formatting.FormatContext, + ): FileTextChanges { + const text = newFileChangesWorker( + getScriptKindFromFileName(fileName), + insertions, + newLineCharacter, + formatContext, + ); return { fileName, textChanges: [createTextChange(createTextSpan(0, 0), text)], isNewFile: true }; } - export function newFileChangesWorker(scriptKind: ScriptKind, insertions: readonly NewFileInsertion[], newLineCharacter: string, formatContext: formatting.FormatContext): string { + export function newFileChangesWorker( + scriptKind: ScriptKind, + insertions: readonly NewFileInsertion[], + newLineCharacter: string, + formatContext: formatting.FormatContext, + ): string { // TODO: this emits the file, parses it back, then formats it that -- may be a less roundabout way to do this - const nonFormattedText = flatMap(insertions, insertion => insertion.statements.map(s => s === SyntaxKind.NewLineTrivia ? "" : getNonformattedText(s, insertion.oldFile, newLineCharacter).text)).join(newLineCharacter); - const sourceFile = createSourceFile("any file name", nonFormattedText, ScriptTarget.ESNext, /*setParentNodes*/ true, scriptKind); + const nonFormattedText = flatMap( + insertions, + insertion => + insertion.statements.map(s => + s === SyntaxKind.NewLineTrivia ? "" + : getNonformattedText(s, insertion.oldFile, newLineCharacter).text + ), + ).join(newLineCharacter); + const sourceFile = createSourceFile( + "any file name", + nonFormattedText, + ScriptTarget.ESNext, + /*setParentNodes*/ true, + scriptKind, + ); const changes = formatting.formatDocument(sourceFile, formatContext); return applyChanges(nonFormattedText, changes) + newLineCharacter; } - function computeNewText(change: Change, targetSourceFile: SourceFile, sourceFile: SourceFile, newLineCharacter: string, formatContext: formatting.FormatContext, validate: ValidateNonFormattedText | undefined): string { + function computeNewText( + change: Change, + targetSourceFile: SourceFile, + sourceFile: SourceFile, + newLineCharacter: string, + formatContext: formatting.FormatContext, + validate: ValidateNonFormattedText | undefined, + ): string { if (change.kind === ChangeKind.Remove) { return ""; } @@ -1304,27 +1727,56 @@ namespace changesToText { } const { options = {}, range: { pos } } = change; - const format = (n: Node) => getFormattedTextOfNode(n, targetSourceFile, sourceFile, pos, options, newLineCharacter, formatContext, validate); + const format = (n: Node) => + getFormattedTextOfNode( + n, + targetSourceFile, + sourceFile, + pos, + options, + newLineCharacter, + formatContext, + validate, + ); const text = change.kind === ChangeKind.ReplaceWithMultipleNodes - ? change.nodes.map(n => removeSuffix(format(n), newLineCharacter)).join(change.options?.joiner || newLineCharacter) + ? change.nodes.map(n => removeSuffix(format(n), newLineCharacter)).join( + change.options?.joiner || newLineCharacter, + ) : format(change.node); // strip initial indentation (spaces or tabs) if text will be inserted in the middle of the line - const noIndent = (options.indentation !== undefined || getLineStartPositionForPosition(pos, targetSourceFile) === pos) ? text : text.replace(/^\s+/, ""); + const noIndent = + (options.indentation !== undefined || getLineStartPositionForPosition(pos, targetSourceFile) === pos) ? text + : text.replace(/^\s+/, ""); return (options.prefix || "") + noIndent + ((!options.suffix || endsWith(noIndent, options.suffix)) ? "" : options.suffix); } /** Note: this may mutate `nodeIn`. */ - function getFormattedTextOfNode(nodeIn: Node, targetSourceFile: SourceFile, sourceFile: SourceFile, pos: number, { indentation, prefix, delta }: InsertNodeOptions, newLineCharacter: string, formatContext: formatting.FormatContext, validate: ValidateNonFormattedText | undefined): string { + function getFormattedTextOfNode( + nodeIn: Node, + targetSourceFile: SourceFile, + sourceFile: SourceFile, + pos: number, + { indentation, prefix, delta }: InsertNodeOptions, + newLineCharacter: string, + formatContext: formatting.FormatContext, + validate: ValidateNonFormattedText | undefined, + ): string { const { node, text } = getNonformattedText(nodeIn, targetSourceFile, newLineCharacter); if (validate) validate(node, text); const formatOptions = getFormatCodeSettingsForWriting(formatContext, targetSourceFile); const initialIndentation = indentation !== undefined ? indentation - : formatting.SmartIndenter.getIndentation(pos, sourceFile, formatOptions, prefix === newLineCharacter || getLineStartPositionForPosition(pos, targetSourceFile) === pos); + : formatting.SmartIndenter.getIndentation( + pos, + sourceFile, + formatOptions, + prefix === newLineCharacter || getLineStartPositionForPosition(pos, targetSourceFile) === pos, + ); if (delta === undefined) { - delta = formatting.SmartIndenter.shouldIndentChildNode(formatOptions, nodeIn) ? (formatOptions.indentSize || 0) : 0; + delta = formatting.SmartIndenter.shouldIndentChildNode(formatOptions, nodeIn) + ? (formatOptions.indentSize || 0) : 0; } const file: SourceFileLike = { @@ -1333,12 +1785,23 @@ namespace changesToText { return getLineAndCharacterOfPosition(this, pos); }, }; - const changes = formatting.formatNodeGivenIndentation(node, file, targetSourceFile.languageVariant, initialIndentation, delta, { ...formatContext, options: formatOptions }); + const changes = formatting.formatNodeGivenIndentation( + node, + file, + targetSourceFile.languageVariant, + initialIndentation, + delta, + { ...formatContext, options: formatOptions }, + ); return applyChanges(text, changes); } /** Note: output node may be mutated input node. */ - export function getNonformattedText(node: Node, sourceFile: SourceFile | undefined, newLineCharacter: string): { text: string; node: Node; } { + export function getNonformattedText( + node: Node, + sourceFile: SourceFile | undefined, + newLineCharacter: string, + ): { text: string; node: Node; } { const writer = createWriter(newLineCharacter); const newLine = getNewLineKind(newLineCharacter); createPrinter({ @@ -1376,7 +1839,13 @@ const textChangesTransformationContext: TransformationContext = { /** @internal */ export function assignPositionsToNode(node: Node): Node { - const visited = visitEachChild(node, assignPositionsToNode, textChangesTransformationContext, assignPositionsToNodeArray, assignPositionsToNode); + const visited = visitEachChild( + node, + assignPositionsToNode, + textChangesTransformationContext, + assignPositionsToNodeArray, + assignPositionsToNode, + ); // create proxy node for non synthesized nodes const newNode = nodeIsSynthesized(visited) ? visited : Object.create(visited) as Node; setTextRangePosEnd(newNode, getPos(node), getEnd(node)); @@ -1625,7 +2094,9 @@ function getInsertionPositionAtSourceFileTop(sourceFile: SourceFile): number { } if (sourceFile.statements.length) { - if (firstNodeLine === undefined) firstNodeLine = sourceFile.getLineAndCharacterOfPosition(sourceFile.statements[0].getStart()).line; + if (firstNodeLine === undefined) { + firstNodeLine = sourceFile.getLineAndCharacterOfPosition(sourceFile.statements[0].getStart()).line; + } const commentEndLine = sourceFile.getLineAndCharacterOfPosition(range.end).line; if (firstNodeLine < commentEndLine + 2) break; } @@ -1644,7 +2115,10 @@ function getInsertionPositionAtSourceFileTop(sourceFile: SourceFile): number { if (isLineBreak(charCode)) { position++; - if (position < text.length && charCode === CharacterCodes.carriageReturn && text.charCodeAt(position) === CharacterCodes.lineFeed) { + if ( + position < text.length && charCode === CharacterCodes.carriageReturn + && text.charCodeAt(position) === CharacterCodes.lineFeed + ) { position++; } } @@ -1654,23 +2128,30 @@ function getInsertionPositionAtSourceFileTop(sourceFile: SourceFile): number { /** @internal */ export function isValidLocationToAddComment(sourceFile: SourceFile, position: number) { - return !isInComment(sourceFile, position) && !isInString(sourceFile, position) && !isInTemplateString(sourceFile, position) && !isInJSXText(sourceFile, position); + return !isInComment(sourceFile, position) && !isInString(sourceFile, position) + && !isInTemplateString(sourceFile, position) && !isInJSXText(sourceFile, position); } function needSemicolonBetween(a: Node, b: Node): boolean { - return (isPropertySignature(a) || isPropertyDeclaration(a)) && isClassOrTypeElement(b) && b.name!.kind === SyntaxKind.ComputedPropertyName + return (isPropertySignature(a) || isPropertyDeclaration(a)) && isClassOrTypeElement(b) + && b.name!.kind === SyntaxKind.ComputedPropertyName || isStatementButNotDeclaration(a) && isStatementButNotDeclaration(b); // TODO: only if b would start with a `(` or `[` } namespace deleteDeclaration { - export function deleteDeclaration(changes: ChangeTracker, deletedNodesInLists: Set, sourceFile: SourceFile, node: Node): void { + export function deleteDeclaration( + changes: ChangeTracker, + deletedNodesInLists: Set, + sourceFile: SourceFile, + node: Node, + ): void { switch (node.kind) { case SyntaxKind.Parameter: { const oldFunction = node.parent; if ( - isArrowFunction(oldFunction) && - oldFunction.parameters.length === 1 && - !findChildOfKind(oldFunction, SyntaxKind.OpenParenToken, sourceFile) + isArrowFunction(oldFunction) + && oldFunction.parameters.length === 1 + && !findChildOfKind(oldFunction, SyntaxKind.OpenParenToken, sourceFile) ) { // Lambdas with exactly one parameter are special because, after removal, there // must be an empty parameter list (i.e. `()`) and this won't necessarily be the @@ -1685,16 +2166,19 @@ namespace deleteDeclaration { case SyntaxKind.ImportDeclaration: case SyntaxKind.ImportEqualsDeclaration: - const isFirstImport = sourceFile.imports.length && node === first(sourceFile.imports).parent || node === find(sourceFile.statements, isAnyImportSyntax); + const isFirstImport = sourceFile.imports.length && node === first(sourceFile.imports).parent + || node === find(sourceFile.statements, isAnyImportSyntax); // For first import, leave header comment in place, otherwise only delete JSDoc comments deleteNode(changes, sourceFile, node, { - leadingTriviaOption: isFirstImport ? LeadingTriviaOption.Exclude : hasJSDocNodes(node) ? LeadingTriviaOption.JSDoc : LeadingTriviaOption.StartLine, + leadingTriviaOption: isFirstImport ? LeadingTriviaOption.Exclude + : hasJSDocNodes(node) ? LeadingTriviaOption.JSDoc : LeadingTriviaOption.StartLine, }); break; case SyntaxKind.BindingElement: const pattern = (node as BindingElement).parent; - const preserveComma = pattern.kind === SyntaxKind.ArrayBindingPattern && node !== last(pattern.elements); + const preserveComma = pattern.kind === SyntaxKind.ArrayBindingPattern + && node !== last(pattern.elements); if (preserveComma) { deleteNode(changes, sourceFile, node); } @@ -1735,7 +2219,10 @@ namespace deleteDeclaration { case SyntaxKind.ClassDeclaration: case SyntaxKind.FunctionDeclaration: - deleteNode(changes, sourceFile, node, { leadingTriviaOption: hasJSDocNodes(node) ? LeadingTriviaOption.JSDoc : LeadingTriviaOption.StartLine }); + deleteNode(changes, sourceFile, node, { + leadingTriviaOption: hasJSDocNodes(node) ? LeadingTriviaOption.JSDoc + : LeadingTriviaOption.StartLine, + }); break; default: @@ -1766,7 +2253,12 @@ namespace deleteDeclaration { const nextToken = getTokenAtPosition(sourceFile, importClause.name!.end); if (nextToken && nextToken.kind === SyntaxKind.CommaToken) { // shift first non-whitespace position after comma to the start position of the node - const end = skipTrivia(sourceFile.text, nextToken.end, /*stopAfterLineBreak*/ false, /*stopAtComments*/ true); + const end = skipTrivia( + sourceFile.text, + nextToken.end, + /*stopAfterLineBreak*/ false, + /*stopAtComments*/ true, + ); changes.deleteRange(sourceFile, { pos: start, end }); } else { @@ -1792,12 +2284,21 @@ namespace deleteDeclaration { } } - function deleteVariableDeclaration(changes: ChangeTracker, deletedNodesInLists: Set, sourceFile: SourceFile, node: VariableDeclaration): void { + function deleteVariableDeclaration( + changes: ChangeTracker, + deletedNodesInLists: Set, + sourceFile: SourceFile, + node: VariableDeclaration, + ): void { const { parent } = node; if (parent.kind === SyntaxKind.CatchClause) { // TODO: There's currently no unused diagnostic for this, could be a suggestion - changes.deleteNodeRange(sourceFile, findChildOfKind(parent, SyntaxKind.OpenParenToken, sourceFile)!, findChildOfKind(parent, SyntaxKind.CloseParenToken, sourceFile)!); + changes.deleteNodeRange( + sourceFile, + findChildOfKind(parent, SyntaxKind.OpenParenToken, sourceFile)!, + findChildOfKind(parent, SyntaxKind.CloseParenToken, sourceFile)!, + ); return; } @@ -1818,7 +2319,9 @@ namespace deleteDeclaration { break; case SyntaxKind.VariableStatement: - deleteNode(changes, sourceFile, gp, { leadingTriviaOption: hasJSDocNodes(gp) ? LeadingTriviaOption.JSDoc : LeadingTriviaOption.StartLine }); + deleteNode(changes, sourceFile, gp, { + leadingTriviaOption: hasJSDocNodes(gp) ? LeadingTriviaOption.JSDoc : LeadingTriviaOption.StartLine, + }); break; default: @@ -1833,13 +2336,23 @@ namespace deleteDeclaration { * * @internal */ -export function deleteNode(changes: ChangeTracker, sourceFile: SourceFile, node: Node, options: ConfigurableStartEnd = { leadingTriviaOption: LeadingTriviaOption.IncludeAll }): void { +export function deleteNode( + changes: ChangeTracker, + sourceFile: SourceFile, + node: Node, + options: ConfigurableStartEnd = { leadingTriviaOption: LeadingTriviaOption.IncludeAll }, +): void { const startPosition = getAdjustedStartPosition(sourceFile, node, options); const endPosition = getAdjustedEndPosition(sourceFile, node, options); changes.deleteRange(sourceFile, { pos: startPosition, end: endPosition }); } -function deleteNodeInList(changes: ChangeTracker, deletedNodesInLists: Set, sourceFile: SourceFile, node: Node): void { +function deleteNodeInList( + changes: ChangeTracker, + deletedNodesInLists: Set, + sourceFile: SourceFile, + node: Node, +): void { const containingList = Debug.checkDefined(formatting.SmartIndenter.getContainingList(node, sourceFile)); const index = indexOfNode(containingList, node); Debug.assert(index !== -1); @@ -1855,6 +2368,7 @@ function deleteNodeInList(changes: ChangeTracker, deletedNodesInLists: Set changes.deleteRange(sourceFile, { pos: startPositionToDeleteNodeInList(sourceFile, node), - end: index === containingList.length - 1 ? getAdjustedEndPosition(sourceFile, node, {}) : endPositionToDeleteNodeInList(sourceFile, node, containingList[index - 1], containingList[index + 1]), + end: index === containingList.length - 1 ? getAdjustedEndPosition(sourceFile, node, {}) + : endPositionToDeleteNodeInList(sourceFile, node, containingList[index - 1], containingList[index + 1]), }); } diff --git a/src/services/transform.ts b/src/services/transform.ts index 85fae890c0984..67ee013360de5 100644 --- a/src/services/transform.ts +++ b/src/services/transform.ts @@ -17,11 +17,23 @@ import { * @param transformers An array of `TransformerFactory` callbacks used to process the transformation. * @param compilerOptions Optional compiler options. */ -export function transform(source: T | T[], transformers: TransformerFactory[], compilerOptions?: CompilerOptions): TransformationResult { +export function transform( + source: T | T[], + transformers: TransformerFactory[], + compilerOptions?: CompilerOptions, +): TransformationResult { const diagnostics: DiagnosticWithLocation[] = []; compilerOptions = fixupCompilerOptions(compilerOptions!, diagnostics); // TODO: GH#18217 const nodes = isArray(source) ? source : [source]; - const result = transformNodes(/*resolver*/ undefined, /*host*/ undefined, factory, compilerOptions, nodes, transformers, /*allowDtsFiles*/ true); + const result = transformNodes( + /*resolver*/ undefined, + /*host*/ undefined, + factory, + compilerOptions, + nodes, + transformers, + /*allowDtsFiles*/ true, + ); result.diagnostics = concatenate(result.diagnostics, diagnostics); return result; } diff --git a/src/services/transpile.ts b/src/services/transpile.ts index d68f49fd4a3ed..bd97358bc0001 100644 --- a/src/services/transpile.ts +++ b/src/services/transpile.ts @@ -61,7 +61,8 @@ const optionsRedundantWithVerbatimModuleSyntax = new Set([ export function transpileModule(input: string, transpileOptions: TranspileOptions): TranspileOutput { const diagnostics: Diagnostic[] = []; - const options: CompilerOptions = transpileOptions.compilerOptions ? fixupCompilerOptions(transpileOptions.compilerOptions, diagnostics) : {}; + const options: CompilerOptions = transpileOptions.compilerOptions + ? fixupCompilerOptions(transpileOptions.compilerOptions, diagnostics) : {}; // mix in default options const defaultOptions = getDefaultCompilerOptions(); @@ -112,13 +113,19 @@ export function transpileModule(input: string, transpileOptions: TranspileOption }; // if jsx is specified then treat file as .tsx - const inputFileName = transpileOptions.fileName || (transpileOptions.compilerOptions && transpileOptions.compilerOptions.jsx ? "module.tsx" : "module.ts"); + const inputFileName = transpileOptions.fileName + || (transpileOptions.compilerOptions && transpileOptions.compilerOptions.jsx ? "module.tsx" : "module.ts"); const sourceFile = createSourceFile( inputFileName, input, { languageVersion: getEmitScriptTarget(options), - impliedNodeFormat: getImpliedNodeFormatForFile(toPath(inputFileName, "", compilerHost.getCanonicalFileName), /*packageJsonInfoCache*/ undefined, compilerHost, options), + impliedNodeFormat: getImpliedNodeFormatForFile( + toPath(inputFileName, "", compilerHost.getCanonicalFileName), + /*packageJsonInfoCache*/ undefined, + compilerHost, + options, + ), setExternalModuleIndicator: getSetExternalModuleIndicator(options), }, ); @@ -141,7 +148,13 @@ export function transpileModule(input: string, transpileOptions: TranspileOption addRange(/*to*/ diagnostics, /*from*/ program.getOptionsDiagnostics()); } // Emit - program.emit(/*targetSourceFile*/ undefined, /*writeFile*/ undefined, /*cancellationToken*/ undefined, /*emitOnlyDtsFiles*/ undefined, transpileOptions.transformers); + program.emit( + /*targetSourceFile*/ undefined, + /*writeFile*/ undefined, + /*cancellationToken*/ undefined, + /*emitOnlyDtsFiles*/ undefined, + transpileOptions.transformers, + ); if (outputText === undefined) return Debug.fail("Output generation failed"); @@ -151,7 +164,13 @@ export function transpileModule(input: string, transpileOptions: TranspileOption /* * This is a shortcut function for transpileModule - it accepts transpileOptions as parameters and returns only outputText part of the result. */ -export function transpile(input: string, compilerOptions?: CompilerOptions, fileName?: string, diagnostics?: Diagnostic[], moduleName?: string): string { +export function transpile( + input: string, + compilerOptions?: CompilerOptions, + fileName?: string, + diagnostics?: Diagnostic[], + moduleName?: string, +): string { const output = transpileModule(input, { compilerOptions, fileName, reportDiagnostics: !!diagnostics, moduleName }); // addRange correctly handles cases when wither 'from' or 'to' argument is missing addRange(diagnostics, output.diagnostics); @@ -167,8 +186,11 @@ let commandLineOptionsStringToEnum: CommandLineOptionOfCustomType[]; */ export function fixupCompilerOptions(options: CompilerOptions, diagnostics: Diagnostic[]): CompilerOptions { // Lazily create this value to fix module loading errors. - commandLineOptionsStringToEnum = commandLineOptionsStringToEnum || - filter(optionDeclarations, o => typeof o.type === "object" && !forEachEntry(o.type, v => typeof v !== "number")) as CommandLineOptionOfCustomType[]; + commandLineOptionsStringToEnum = commandLineOptionsStringToEnum + || filter( + optionDeclarations, + o => typeof o.type === "object" && !forEachEntry(o.type, v => typeof v !== "number"), + ) as CommandLineOptionOfCustomType[]; options = cloneCompilerOptions(options); diff --git a/src/services/types.ts b/src/services/types.ts index 9c1fe3a73eb73..5a1321e01facb 100644 --- a/src/services/types.ts +++ b/src/services/types.ts @@ -67,7 +67,10 @@ declare module "../compiler/types" { /** @internal */ getLastToken(sourceFile?: SourceFileLike): Node | undefined; // eslint-disable-line @typescript-eslint/unified-signatures // See ts.forEachChild for documentation. - forEachChild(cbNode: (node: Node) => T | undefined, cbNodeArray?: (nodes: NodeArray) => T | undefined): T | undefined; + forEachChild( + cbNode: (node: Node) => T | undefined, + cbNodeArray?: (nodes: NodeArray) => T | undefined, + ): T | undefined; } } @@ -95,7 +98,10 @@ declare module "../compiler/types" { getDeclarations(): Declaration[] | undefined; getDocumentationComment(typeChecker: TypeChecker | undefined): SymbolDisplayPart[]; /** @internal */ - getContextualDocumentationComment(context: Node | undefined, checker: TypeChecker | undefined): SymbolDisplayPart[]; + getContextualDocumentationComment( + context: Node | undefined, + checker: TypeChecker | undefined, + ): SymbolDisplayPart[]; getJsDocTags(checker?: TypeChecker): JSDocTagInfo[]; /** @internal */ getContextualJsDocTags(context: Node | undefined, checker: TypeChecker | undefined): JSDocTagInfo[]; @@ -333,7 +339,13 @@ export interface LanguageServiceHost extends GetEffectiveTypeRootsHost, MinimalR * LS host can optionally implement these methods to support completions for module specifiers. * Without these methods, only completions for ambient modules will be provided. */ - readDirectory?(path: string, extensions?: readonly string[], exclude?: readonly string[], include?: readonly string[], depth?: number): string[]; + readDirectory?( + path: string, + extensions?: readonly string[], + exclude?: readonly string[], + include?: readonly string[], + depth?: number, + ): string[]; realpath?(path: string): string; /** @internal */ createHash?(data: string): string; @@ -357,10 +369,27 @@ export interface LanguageServiceHost extends GetEffectiveTypeRootsHost, MinimalR * If this is implemented, `getResolvedModuleWithFailedLookupLocationsFromCache` should be too. */ /** @deprecated supply resolveModuleNameLiterals instead for resolution that can handle newer resolution modes like nodenext */ - resolveModuleNames?(moduleNames: string[], containingFile: string, reusedNames: string[] | undefined, redirectedReference: ResolvedProjectReference | undefined, options: CompilerOptions, containingSourceFile?: SourceFile): (ResolvedModule | undefined)[]; - getResolvedModuleWithFailedLookupLocationsFromCache?(modulename: string, containingFile: string, resolutionMode?: ResolutionMode): ResolvedModuleWithFailedLookupLocations | undefined; + resolveModuleNames?( + moduleNames: string[], + containingFile: string, + reusedNames: string[] | undefined, + redirectedReference: ResolvedProjectReference | undefined, + options: CompilerOptions, + containingSourceFile?: SourceFile, + ): (ResolvedModule | undefined)[]; + getResolvedModuleWithFailedLookupLocationsFromCache?( + modulename: string, + containingFile: string, + resolutionMode?: ResolutionMode, + ): ResolvedModuleWithFailedLookupLocations | undefined; /** @deprecated supply resolveTypeReferenceDirectiveReferences instead for resolution that can handle newer resolution modes like nodenext */ - resolveTypeReferenceDirectives?(typeDirectiveNames: string[] | FileReference[], containingFile: string, redirectedReference: ResolvedProjectReference | undefined, options: CompilerOptions, containingFileMode?: ResolutionMode): (ResolvedTypeReferenceDirective | undefined)[]; + resolveTypeReferenceDirectives?( + typeDirectiveNames: string[] | FileReference[], + containingFile: string, + redirectedReference: ResolvedProjectReference | undefined, + options: CompilerOptions, + containingFileMode?: ResolutionMode, + ): (ResolvedTypeReferenceDirective | undefined)[]; resolveModuleNameLiterals?( moduleLiterals: readonly StringLiteralLike[], containingFile: string, @@ -412,9 +441,15 @@ export interface LanguageServiceHost extends GetEffectiveTypeRootsHost, MinimalR installPackage?(options: InstallPackageOptions): Promise; writeFile?(fileName: string, content: string): void; - /** @internal */ getDocumentPositionMapper?(generatedFileName: string, sourceFileName?: string): DocumentPositionMapper | undefined; + /** @internal */ getDocumentPositionMapper?( + generatedFileName: string, + sourceFileName?: string, + ): DocumentPositionMapper | undefined; /** @internal */ getSourceFileLike?(fileName: string): SourceFileLike | undefined; - /** @internal */ getPackageJsonsVisibleToFile?(fileName: string, rootDir?: string): readonly ProjectPackageJsonInfo[]; + /** @internal */ getPackageJsonsVisibleToFile?( + fileName: string, + rootDir?: string, + ): readonly ProjectPackageJsonInfo[]; /** @internal */ getNearestAncestorDirectoryWithPackageJson?(fileName: string): string | undefined; /** @internal */ getPackageJsonsForAutoImport?(rootDir?: string): readonly ProjectPackageJsonInfo[]; /** @internal */ getCachedExportInfoMap?(): ExportInfoMap; @@ -424,7 +459,11 @@ export interface LanguageServiceHost extends GetEffectiveTypeRootsHost, MinimalR /** @internal */ getPackageJsonAutoImportProvider?(): Program | undefined; /** @internal */ sendPerformanceEvent?(kind: PerformanceEvent["kind"], durationMs: number): void; getParsedCommandLine?(fileName: string): ParsedCommandLine | undefined; - /** @internal */ onReleaseParsedCommandLine?(configFileName: string, oldResolvedRef: ResolvedProjectReference | undefined, optionOptions: CompilerOptions): void; + /** @internal */ onReleaseParsedCommandLine?( + configFileName: string, + oldResolvedRef: ResolvedProjectReference | undefined, + optionOptions: CompilerOptions, + ): void; /** @internal */ getIncompleteCompletionsCache?(): IncompleteCompletionsCache; } @@ -501,11 +540,19 @@ export interface LanguageService { /** @deprecated Use getEncodedSyntacticClassifications instead. */ getSyntacticClassifications(fileName: string, span: TextSpan): ClassifiedSpan[]; - getSyntacticClassifications(fileName: string, span: TextSpan, format: SemanticClassificationFormat): ClassifiedSpan[] | ClassifiedSpan2020[]; + getSyntacticClassifications( + fileName: string, + span: TextSpan, + format: SemanticClassificationFormat, + ): ClassifiedSpan[] | ClassifiedSpan2020[]; /** @deprecated Use getEncodedSemanticClassifications instead. */ getSemanticClassifications(fileName: string, span: TextSpan): ClassifiedSpan[]; - getSemanticClassifications(fileName: string, span: TextSpan, format: SemanticClassificationFormat): ClassifiedSpan[] | ClassifiedSpan2020[]; + getSemanticClassifications( + fileName: string, + span: TextSpan, + format: SemanticClassificationFormat, + ): ClassifiedSpan[] | ClassifiedSpan2020[]; /** Encoded as triples of [start, length, ClassificationType]. */ getEncodedSyntacticClassifications(fileName: string, span: TextSpan): Classifications; @@ -519,7 +566,11 @@ export interface LanguageService { * @param format Which format to use, defaults to "original" * @returns a number array encoded as triples of [start, length, ClassificationType, ...]. */ - getEncodedSemanticClassifications(fileName: string, span: TextSpan, format?: SemanticClassificationFormat): Classifications; + getEncodedSemanticClassifications( + fileName: string, + span: TextSpan, + format?: SemanticClassificationFormat, + ): Classifications; /** * Gets completion entries at a particular position in a file. @@ -530,7 +581,12 @@ export interface LanguageService { * of code actions can be returned with the completions. * @param formattingSettings settings needed for calling formatting functions. */ - getCompletionsAtPosition(fileName: string, position: number, options: GetCompletionsAtPositionOptions | undefined, formattingSettings?: FormatCodeSettings): WithMetadata | undefined; + getCompletionsAtPosition( + fileName: string, + position: number, + options: GetCompletionsAtPositionOptions | undefined, + formattingSettings?: FormatCodeSettings, + ): WithMetadata | undefined; /** * Gets the extended details for a completion entry retrieved from `getCompletionsAtPosition`. @@ -553,7 +609,12 @@ export interface LanguageService { data: CompletionEntryData | undefined, ): CompletionEntryDetails | undefined; - getCompletionEntrySymbol(fileName: string, position: number, name: string, source: string | undefined): Symbol | undefined; + getCompletionEntrySymbol( + fileName: string, + position: number, + name: string, + source: string | undefined, + ): Symbol | undefined; /** * Gets semantic information about the identifier at a particular position in a @@ -568,22 +629,48 @@ export interface LanguageService { getBreakpointStatementAtPosition(fileName: string, position: number): TextSpan | undefined; - getSignatureHelpItems(fileName: string, position: number, options: SignatureHelpItemsOptions | undefined): SignatureHelpItems | undefined; + getSignatureHelpItems( + fileName: string, + position: number, + options: SignatureHelpItemsOptions | undefined, + ): SignatureHelpItems | undefined; getRenameInfo(fileName: string, position: number, preferences: UserPreferences): RenameInfo; /** @deprecated Use the signature with `UserPreferences` instead. */ getRenameInfo(fileName: string, position: number, options?: RenameInfoOptions): RenameInfo; - findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean, preferences: UserPreferences): readonly RenameLocation[] | undefined; + findRenameLocations( + fileName: string, + position: number, + findInStrings: boolean, + findInComments: boolean, + preferences: UserPreferences, + ): readonly RenameLocation[] | undefined; /** @deprecated Pass `providePrefixAndSuffixTextForRename` as part of a `UserPreferences` parameter. */ - findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean, providePrefixAndSuffixTextForRename?: boolean): readonly RenameLocation[] | undefined; + findRenameLocations( + fileName: string, + position: number, + findInStrings: boolean, + findInComments: boolean, + providePrefixAndSuffixTextForRename?: boolean, + ): readonly RenameLocation[] | undefined; getSmartSelectionRange(fileName: string, position: number): SelectionRange; /** @internal */ - getDefinitionAtPosition(fileName: string, position: number, searchOtherFilesOnly: false, stopAtAlias: boolean): readonly DefinitionInfo[] | undefined; + getDefinitionAtPosition( + fileName: string, + position: number, + searchOtherFilesOnly: false, + stopAtAlias: boolean, + ): readonly DefinitionInfo[] | undefined; /** @internal */ - getDefinitionAtPosition(fileName: string, position: number, searchOtherFilesOnly: boolean, stopAtAlias: false): readonly DefinitionInfo[] | undefined; + getDefinitionAtPosition( + fileName: string, + position: number, + searchOtherFilesOnly: boolean, + stopAtAlias: false, + ): readonly DefinitionInfo[] | undefined; getDefinitionAtPosition(fileName: string, position: number): readonly DefinitionInfo[] | undefined; getDefinitionAndBoundSpan(fileName: string, position: number): DefinitionInfoAndBoundSpan | undefined; getTypeDefinitionAtPosition(fileName: string, position: number): readonly DefinitionInfo[] | undefined; @@ -591,10 +678,19 @@ export interface LanguageService { getReferencesAtPosition(fileName: string, position: number): ReferenceEntry[] | undefined; findReferences(fileName: string, position: number): ReferencedSymbol[] | undefined; - getDocumentHighlights(fileName: string, position: number, filesToSearch: string[]): DocumentHighlights[] | undefined; + getDocumentHighlights( + fileName: string, + position: number, + filesToSearch: string[], + ): DocumentHighlights[] | undefined; getFileReferences(fileName: string): ReferenceEntry[]; - getNavigateToItems(searchValue: string, maxResultCount?: number, fileName?: string, excludeDtsFiles?: boolean): NavigateToItem[]; + getNavigateToItems( + searchValue: string, + maxResultCount?: number, + fileName?: string, + excludeDtsFiles?: boolean, + ): NavigateToItem[]; getNavigationBarItems(fileName: string): NavigationBarItem[]; getNavigationTree(fileName: string): NavigationTree; @@ -609,11 +705,26 @@ export interface LanguageService { getBraceMatchingAtPosition(fileName: string, position: number): TextSpan[]; getIndentationAtPosition(fileName: string, position: number, options: EditorOptions | EditorSettings): number; - getFormattingEditsForRange(fileName: string, start: number, end: number, options: FormatCodeOptions | FormatCodeSettings): TextChange[]; + getFormattingEditsForRange( + fileName: string, + start: number, + end: number, + options: FormatCodeOptions | FormatCodeSettings, + ): TextChange[]; getFormattingEditsForDocument(fileName: string, options: FormatCodeOptions | FormatCodeSettings): TextChange[]; - getFormattingEditsAfterKeystroke(fileName: string, position: number, key: string, options: FormatCodeOptions | FormatCodeSettings): TextChange[]; + getFormattingEditsAfterKeystroke( + fileName: string, + position: number, + key: string, + options: FormatCodeOptions | FormatCodeSettings, + ): TextChange[]; - getDocCommentTemplateAtPosition(fileName: string, position: number, options?: DocCommentTemplateOptions, formatOptions?: FormatCodeSettings): TextInsertion | undefined; + getDocCommentTemplateAtPosition( + fileName: string, + position: number, + options?: DocCommentTemplateOptions, + formatOptions?: FormatCodeSettings, + ): TextInsertion | undefined; isValidBraceCompletionAtPosition(fileName: string, position: number, openingBrace: number): boolean; /** @@ -631,18 +742,42 @@ export interface LanguageService { /** @internal */ clearSourceMapperCache(): void; - getCodeFixesAtPosition(fileName: string, start: number, end: number, errorCodes: readonly number[], formatOptions: FormatCodeSettings, preferences: UserPreferences): readonly CodeFixAction[]; - getCombinedCodeFix(scope: CombinedCodeFixScope, fixId: {}, formatOptions: FormatCodeSettings, preferences: UserPreferences): CombinedCodeActions; - - applyCodeActionCommand(action: CodeActionCommand, formatSettings?: FormatCodeSettings): Promise; - applyCodeActionCommand(action: CodeActionCommand[], formatSettings?: FormatCodeSettings): Promise; - applyCodeActionCommand(action: CodeActionCommand | CodeActionCommand[], formatSettings?: FormatCodeSettings): Promise; + getCodeFixesAtPosition( + fileName: string, + start: number, + end: number, + errorCodes: readonly number[], + formatOptions: FormatCodeSettings, + preferences: UserPreferences, + ): readonly CodeFixAction[]; + getCombinedCodeFix( + scope: CombinedCodeFixScope, + fixId: {}, + formatOptions: FormatCodeSettings, + preferences: UserPreferences, + ): CombinedCodeActions; + + applyCodeActionCommand( + action: CodeActionCommand, + formatSettings?: FormatCodeSettings, + ): Promise; + applyCodeActionCommand( + action: CodeActionCommand[], + formatSettings?: FormatCodeSettings, + ): Promise; + applyCodeActionCommand( + action: CodeActionCommand | CodeActionCommand[], + formatSettings?: FormatCodeSettings, + ): Promise; /** @deprecated `fileName` will be ignored */ applyCodeActionCommand(fileName: string, action: CodeActionCommand): Promise; /** @deprecated `fileName` will be ignored */ applyCodeActionCommand(fileName: string, action: CodeActionCommand[]): Promise; /** @deprecated `fileName` will be ignored */ - applyCodeActionCommand(fileName: string, action: CodeActionCommand | CodeActionCommand[]): Promise; + applyCodeActionCommand( + fileName: string, + action: CodeActionCommand | CodeActionCommand[], + ): Promise; /** * @param includeInteractiveActions Include refactor actions that require additional arguments to be @@ -650,11 +785,41 @@ export interface LanguageService { * property of each returned `RefactorActionInfo` and ensure they are able to collect the appropriate * arguments for any interactive action before offering it. */ - getApplicableRefactors(fileName: string, positionOrRange: number | TextRange, preferences: UserPreferences | undefined, triggerReason?: RefactorTriggerReason, kind?: string, includeInteractiveActions?: boolean): ApplicableRefactorInfo[]; - getEditsForRefactor(fileName: string, formatOptions: FormatCodeSettings, positionOrRange: number | TextRange, refactorName: string, actionName: string, preferences: UserPreferences | undefined, interactiveRefactorArguments?: InteractiveRefactorArguments): RefactorEditInfo | undefined; - getMoveToRefactoringFileSuggestions(fileName: string, positionOrRange: number | TextRange, preferences: UserPreferences | undefined, triggerReason?: RefactorTriggerReason, kind?: string): { newFileName: string; files: string[]; }; - organizeImports(args: OrganizeImportsArgs, formatOptions: FormatCodeSettings, preferences: UserPreferences | undefined): readonly FileTextChanges[]; - getEditsForFileRename(oldFilePath: string, newFilePath: string, formatOptions: FormatCodeSettings, preferences: UserPreferences | undefined): readonly FileTextChanges[]; + getApplicableRefactors( + fileName: string, + positionOrRange: number | TextRange, + preferences: UserPreferences | undefined, + triggerReason?: RefactorTriggerReason, + kind?: string, + includeInteractiveActions?: boolean, + ): ApplicableRefactorInfo[]; + getEditsForRefactor( + fileName: string, + formatOptions: FormatCodeSettings, + positionOrRange: number | TextRange, + refactorName: string, + actionName: string, + preferences: UserPreferences | undefined, + interactiveRefactorArguments?: InteractiveRefactorArguments, + ): RefactorEditInfo | undefined; + getMoveToRefactoringFileSuggestions( + fileName: string, + positionOrRange: number | TextRange, + preferences: UserPreferences | undefined, + triggerReason?: RefactorTriggerReason, + kind?: string, + ): { newFileName: string; files: string[]; }; + organizeImports( + args: OrganizeImportsArgs, + formatOptions: FormatCodeSettings, + preferences: UserPreferences | undefined, + ): readonly FileTextChanges[]; + getEditsForFileRename( + oldFilePath: string, + newFilePath: string, + formatOptions: FormatCodeSettings, + preferences: UserPreferences | undefined, + ): readonly FileTextChanges[]; getEmitOutput(fileName: string, emitOnlyDtsFiles?: boolean, forceDtsEmit?: boolean): EmitOutput; @@ -667,7 +832,10 @@ export interface LanguageService { /// Returns true if a suitable symbol was found in the project. /// May set isDefinition properties in `referencedSymbols` to false. /// May add elements to `knownSymbolSpans`. - /** @internal */ updateIsDefinitionOfReferencedSymbols(referencedSymbols: readonly ReferencedSymbol[], knownSymbolSpans: Set): boolean; + /** @internal */ updateIsDefinitionOfReferencedSymbols( + referencedSymbols: readonly ReferencedSymbol[], + knownSymbolSpans: Set, + ): boolean; toggleLineComment(fileName: string, textRange: TextRange): TextChange[]; toggleMultilineComment(fileName: string, textRange: TextRange): TextChange[]; @@ -1564,8 +1732,16 @@ export interface Classifier { * subsume the classification. * @deprecated Use getLexicalClassifications instead. */ - getClassificationsForLine(text: string, lexState: EndOfLineState, syntacticClassifierAbsent: boolean): ClassificationResult; - getEncodedLexicalClassifications(text: string, endOfLineState: EndOfLineState, syntacticClassifierAbsent: boolean): Classifications; + getClassificationsForLine( + text: string, + lexState: EndOfLineState, + syntacticClassifierAbsent: boolean, + ): ClassificationResult; + getEncodedLexicalClassifications( + text: string, + endOfLineState: EndOfLineState, + syntacticClassifierAbsent: boolean, + ): Classifications; } export const enum ScriptElementKind { @@ -1808,10 +1984,18 @@ export interface Refactor { kinds?: string[]; /** Compute the associated code actions */ - getEditsForAction(context: RefactorContext, actionName: string, interactiveRefactorArguments?: InteractiveRefactorArguments): RefactorEditInfo | undefined; + getEditsForAction( + context: RefactorContext, + actionName: string, + interactiveRefactorArguments?: InteractiveRefactorArguments, + ): RefactorEditInfo | undefined; /** Compute (quickly) which actions are available here */ - getAvailableActions(context: RefactorContext, includeInteractive?: boolean, interactiveRefactorArguments?: InteractiveRefactorArguments): readonly ApplicableRefactorInfo[]; + getAvailableActions( + context: RefactorContext, + includeInteractive?: boolean, + interactiveRefactorArguments?: InteractiveRefactorArguments, + ): readonly ApplicableRefactorInfo[]; } /** @internal */ diff --git a/src/services/utilities.ts b/src/services/utilities.ts index daf401d496379..c3a6b884f25ee 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -421,7 +421,8 @@ export function getMeaningFromDeclaration(node: Node): SemanticMeaning { case SyntaxKind.JSDocTypedefTag: // If it has no name node, it shares the name with the value declaration below it. - return (node as JSDocTypedefTag).name === undefined ? SemanticMeaning.Value | SemanticMeaning.Type : SemanticMeaning.Type; + return (node as JSDocTypedefTag).name === undefined ? SemanticMeaning.Value | SemanticMeaning.Type + : SemanticMeaning.Type; case SyntaxKind.EnumMember: case SyntaxKind.ClassDeclaration: @@ -504,8 +505,10 @@ function getMeaningFromRightHandSideOfImportEquals(node: Node): SemanticMeaning // import a = |b|; // Namespace // import a = |b.c|; // Value, type, namespace // import a = |b.c|.d; // Namespace - const name = node.kind === SyntaxKind.QualifiedName ? node : isQualifiedName(node.parent) && node.parent.right === node ? node.parent : undefined; - return name && name.parent.kind === SyntaxKind.ImportEqualsDeclaration ? SemanticMeaning.All : SemanticMeaning.Namespace; + const name = node.kind === SyntaxKind.QualifiedName ? node + : isQualifiedName(node.parent) && node.parent.right === node ? node.parent : undefined; + return name && name.parent.kind === SyntaxKind.ImportEqualsDeclaration ? SemanticMeaning.All + : SemanticMeaning.Namespace; } /** @internal */ @@ -545,10 +548,15 @@ function isPropertyAccessNamespaceReference(node: Node): boolean { isLastClause = (root as PropertyAccessExpression).name === node; } - if (!isLastClause && root.parent.kind === SyntaxKind.ExpressionWithTypeArguments && root.parent.parent.kind === SyntaxKind.HeritageClause) { + if ( + !isLastClause && root.parent.kind === SyntaxKind.ExpressionWithTypeArguments + && root.parent.parent.kind === SyntaxKind.HeritageClause + ) { const decl = root.parent.parent.parent; - return (decl.kind === SyntaxKind.ClassDeclaration && (root.parent.parent as HeritageClause).token === SyntaxKind.ImplementsKeyword) || - (decl.kind === SyntaxKind.InterfaceDeclaration && (root.parent.parent as HeritageClause).token === SyntaxKind.ExtendsKeyword); + return (decl.kind === SyntaxKind.ClassDeclaration + && (root.parent.parent as HeritageClause).token === SyntaxKind.ImplementsKeyword) + || (decl.kind === SyntaxKind.InterfaceDeclaration + && (root.parent.parent as HeritageClause).token === SyntaxKind.ExtendsKeyword); } return false; @@ -579,33 +587,89 @@ function isTypeReference(node: Node): boolean { } /** @internal */ -export function isCallExpressionTarget(node: Node, includeElementAccess = false, skipPastOuterExpressions = false): boolean { - return isCalleeWorker(node, isCallExpression, selectExpressionOfCallOrNewExpressionOrDecorator, includeElementAccess, skipPastOuterExpressions); +export function isCallExpressionTarget( + node: Node, + includeElementAccess = false, + skipPastOuterExpressions = false, +): boolean { + return isCalleeWorker( + node, + isCallExpression, + selectExpressionOfCallOrNewExpressionOrDecorator, + includeElementAccess, + skipPastOuterExpressions, + ); } /** @internal */ -export function isNewExpressionTarget(node: Node, includeElementAccess = false, skipPastOuterExpressions = false): boolean { - return isCalleeWorker(node, isNewExpression, selectExpressionOfCallOrNewExpressionOrDecorator, includeElementAccess, skipPastOuterExpressions); +export function isNewExpressionTarget( + node: Node, + includeElementAccess = false, + skipPastOuterExpressions = false, +): boolean { + return isCalleeWorker( + node, + isNewExpression, + selectExpressionOfCallOrNewExpressionOrDecorator, + includeElementAccess, + skipPastOuterExpressions, + ); } /** @internal */ -export function isCallOrNewExpressionTarget(node: Node, includeElementAccess = false, skipPastOuterExpressions = false): boolean { - return isCalleeWorker(node, isCallOrNewExpression, selectExpressionOfCallOrNewExpressionOrDecorator, includeElementAccess, skipPastOuterExpressions); +export function isCallOrNewExpressionTarget( + node: Node, + includeElementAccess = false, + skipPastOuterExpressions = false, +): boolean { + return isCalleeWorker( + node, + isCallOrNewExpression, + selectExpressionOfCallOrNewExpressionOrDecorator, + includeElementAccess, + skipPastOuterExpressions, + ); } /** @internal */ -export function isTaggedTemplateTag(node: Node, includeElementAccess = false, skipPastOuterExpressions = false): boolean { - return isCalleeWorker(node, isTaggedTemplateExpression, selectTagOfTaggedTemplateExpression, includeElementAccess, skipPastOuterExpressions); +export function isTaggedTemplateTag( + node: Node, + includeElementAccess = false, + skipPastOuterExpressions = false, +): boolean { + return isCalleeWorker( + node, + isTaggedTemplateExpression, + selectTagOfTaggedTemplateExpression, + includeElementAccess, + skipPastOuterExpressions, + ); } /** @internal */ export function isDecoratorTarget(node: Node, includeElementAccess = false, skipPastOuterExpressions = false): boolean { - return isCalleeWorker(node, isDecorator, selectExpressionOfCallOrNewExpressionOrDecorator, includeElementAccess, skipPastOuterExpressions); + return isCalleeWorker( + node, + isDecorator, + selectExpressionOfCallOrNewExpressionOrDecorator, + includeElementAccess, + skipPastOuterExpressions, + ); } /** @internal */ -export function isJsxOpeningLikeElementTagName(node: Node, includeElementAccess = false, skipPastOuterExpressions = false): boolean { - return isCalleeWorker(node, isJsxOpeningLikeElement, selectTagNameOfJsxOpeningLikeElement, includeElementAccess, skipPastOuterExpressions); +export function isJsxOpeningLikeElementTagName( + node: Node, + includeElementAccess = false, + skipPastOuterExpressions = false, +): boolean { + return isCalleeWorker( + node, + isJsxOpeningLikeElement, + selectTagNameOfJsxOpeningLikeElement, + includeElementAccess, + skipPastOuterExpressions, + ); } function selectExpressionOfCallOrNewExpressionOrDecorator(node: CallExpression | NewExpression | Decorator) { @@ -620,7 +684,15 @@ function selectTagNameOfJsxOpeningLikeElement(node: JsxOpeningLikeElement) { return node.tagName; } -function isCalleeWorker(node: Node, pred: (node: Node) => node is T, calleeSelector: (node: T) => Expression | JsxTagNameExpression, includeElementAccess: boolean, skipPastOuterExpressions: boolean) { +function isCalleeWorker< + T extends CallExpression | NewExpression | TaggedTemplateExpression | Decorator | JsxOpeningLikeElement, +>( + node: Node, + pred: (node: Node) => node is T, + calleeSelector: (node: T) => Expression | JsxTagNameExpression, + includeElementAccess: boolean, + skipPastOuterExpressions: boolean, +) { let target = includeElementAccess ? climbPastPropertyOrElementAccess(node) : climbPastPropertyAccess(node); if (skipPastOuterExpressions) { target = skipOuterExpressions(target); @@ -641,7 +713,10 @@ export function climbPastPropertyOrElementAccess(node: Node) { /** @internal */ export function getTargetLabel(referenceNode: Node, labelName: string): Identifier | undefined { while (referenceNode) { - if (referenceNode.kind === SyntaxKind.LabeledStatement && (referenceNode as LabeledStatement).label.escapedText === labelName) { + if ( + referenceNode.kind === SyntaxKind.LabeledStatement + && (referenceNode as LabeledStatement).label.escapedText === labelName + ) { return (referenceNode as LabeledStatement).label; } referenceNode = referenceNode.parent; @@ -704,7 +779,9 @@ export function isNameOfFunctionDeclaration(node: Node): boolean { } /** @internal */ -export function isLiteralNameOfPropertyDeclarationOrIndexAccess(node: StringLiteral | NumericLiteral | NoSubstitutionTemplateLiteral): boolean { +export function isLiteralNameOfPropertyDeclarationOrIndexAccess( + node: StringLiteral | NumericLiteral | NoSubstitutionTemplateLiteral, +): boolean { switch (node.parent.kind) { case SyntaxKind.PropertyDeclaration: case SyntaxKind.PropertySignature: @@ -729,8 +806,8 @@ export function isLiteralNameOfPropertyDeclarationOrIndexAccess(node: StringLite /** @internal */ export function isExpressionOfExternalModuleImportEqualsDeclaration(node: Node) { - return isExternalModuleImportEqualsDeclaration(node.parent.parent) && - getExternalModuleImportEqualsDeclarationExpression(node.parent.parent) === node; + return isExternalModuleImportEqualsDeclaration(node.parent.parent) + && getExternalModuleImportEqualsDeclarationExpression(node.parent.parent) === node; } /** @internal */ @@ -768,7 +845,8 @@ export function getContainerNode(node: Node): Declaration | undefined { export function getNodeKind(node: Node): ScriptElementKind { switch (node.kind) { case SyntaxKind.SourceFile: - return isExternalModule(node as SourceFile) ? ScriptElementKind.moduleElement : ScriptElementKind.scriptElement; + return isExternalModule(node as SourceFile) ? ScriptElementKind.moduleElement + : ScriptElementKind.scriptElement; case SyntaxKind.ModuleDeclaration: return ScriptElementKind.moduleElement; case SyntaxKind.ClassDeclaration: @@ -799,7 +877,8 @@ export function getNodeKind(node: Node): ScriptElementKind { return ScriptElementKind.memberFunctionElement; case SyntaxKind.PropertyAssignment: const { initializer } = node as PropertyAssignment; - return isFunctionLike(initializer) ? ScriptElementKind.memberFunctionElement : ScriptElementKind.memberVariableElement; + return isFunctionLike(initializer) ? ScriptElementKind.memberFunctionElement + : ScriptElementKind.memberVariableElement; case SyntaxKind.PropertyDeclaration: case SyntaxKind.PropertySignature: case SyntaxKind.ShorthandPropertyAssignment: @@ -819,7 +898,8 @@ export function getNodeKind(node: Node): ScriptElementKind { case SyntaxKind.EnumMember: return ScriptElementKind.enumMemberElement; case SyntaxKind.Parameter: - return hasSyntacticModifier(node, ModifierFlags.ParameterPropertyModifier) ? ScriptElementKind.memberVariableElement : ScriptElementKind.parameterElement; + return hasSyntacticModifier(node, ModifierFlags.ParameterPropertyModifier) + ? ScriptElementKind.memberVariableElement : ScriptElementKind.parameterElement; case SyntaxKind.ImportEqualsDeclaration: case SyntaxKind.ImportSpecifier: case SyntaxKind.ExportSpecifier: @@ -840,12 +920,14 @@ export function getNodeKind(node: Node): ScriptElementKind { const rightKind = getNodeKind(right); return rightKind === ScriptElementKind.unknown ? ScriptElementKind.constElement : rightKind; case AssignmentDeclarationKind.PrototypeProperty: - return isFunctionExpression(right) ? ScriptElementKind.memberFunctionElement : ScriptElementKind.memberVariableElement; + return isFunctionExpression(right) ? ScriptElementKind.memberFunctionElement + : ScriptElementKind.memberVariableElement; case AssignmentDeclarationKind.ThisProperty: return ScriptElementKind.memberVariableElement; // property case AssignmentDeclarationKind.Property: // static method / property - return isFunctionExpression(right) ? ScriptElementKind.memberFunctionElement : ScriptElementKind.memberVariableElement; + return isFunctionExpression(right) ? ScriptElementKind.memberFunctionElement + : ScriptElementKind.memberVariableElement; case AssignmentDeclarationKind.Prototype: return ScriptElementKind.localClassElement; default: { @@ -1026,8 +1108,8 @@ function isCompletedNode(n: Node | undefined, sourceFile: SourceFile): boolean { return isCompletedNode((n as IfStatement).thenStatement, sourceFile); case SyntaxKind.ExpressionStatement: - return isCompletedNode((n as ExpressionStatement).expression, sourceFile) || - hasChildOfKind(n, SyntaxKind.SemicolonToken, sourceFile); + return isCompletedNode((n as ExpressionStatement).expression, sourceFile) + || hasChildOfKind(n, SyntaxKind.SemicolonToken, sourceFile); case SyntaxKind.ArrayLiteralExpression: case SyntaxKind.ArrayBindingPattern: @@ -1067,7 +1149,8 @@ function isCompletedNode(n: Node | undefined, sourceFile: SourceFile): boolean { case SyntaxKind.VoidExpression: case SyntaxKind.YieldExpression: case SyntaxKind.SpreadElement: - const unaryWordExpression = n as (TypeOfExpression | DeleteExpression | VoidExpression | YieldExpression | SpreadElement); + const unaryWordExpression = + n as (TypeOfExpression | DeleteExpression | VoidExpression | YieldExpression | SpreadElement); return isCompletedNode(unaryWordExpression.expression, sourceFile); case SyntaxKind.TaggedTemplateExpression: @@ -1149,7 +1232,10 @@ export function findContainingList(node: Node): SyntaxList | undefined { // be parented by the container of the SyntaxList, not the SyntaxList itself. // In order to find the list item index, we first need to locate SyntaxList itself and then search // for the position of the relevant node (or comma). - const syntaxList = find(node.parent.getChildren(), (c): c is SyntaxList => isSyntaxList(c) && rangeContainsRange(c, node)); + const syntaxList = find( + node.parent.getChildren(), + (c): c is SyntaxList => isSyntaxList(c) && rangeContainsRange(c, node), + ); // Either we didn't find an appropriate list, or the list must contain us. Debug.assert(!syntaxList || contains(syntaxList.getChildren(), node)); return syntaxList; @@ -1213,7 +1299,10 @@ function getAncestorTypeNode(node: Node) { } /** @internal */ -export function getContextualTypeFromParentOrAncestorTypeNode(node: Expression, checker: TypeChecker): Type | undefined { +export function getContextualTypeFromParentOrAncestorTypeNode( + node: Expression, + checker: TypeChecker, +): Type | undefined { if (node.flags & (NodeFlags.JSDoc & ~NodeFlags.JavaScriptFile)) return undefined; const contextualType = getContextualTypeFromParent(node, checker); @@ -1330,16 +1419,18 @@ function getAdjustedLocation(node: Node, forRename: boolean): Node { // NOTE: If the node is a modifier, we don't adjust its location if it is the `default` modifier as that is handled // specially by `getSymbolAtLocation`. if ( - isModifier(node) && (forRename || node.kind !== SyntaxKind.DefaultKeyword) ? canHaveModifiers(parent) && contains(parent.modifiers, node) : - node.kind === SyntaxKind.ClassKeyword ? isClassDeclaration(parent) || isClassExpression(node) : - node.kind === SyntaxKind.FunctionKeyword ? isFunctionDeclaration(parent) || isFunctionExpression(node) : - node.kind === SyntaxKind.InterfaceKeyword ? isInterfaceDeclaration(parent) : - node.kind === SyntaxKind.EnumKeyword ? isEnumDeclaration(parent) : - node.kind === SyntaxKind.TypeKeyword ? isTypeAliasDeclaration(parent) : - node.kind === SyntaxKind.NamespaceKeyword || node.kind === SyntaxKind.ModuleKeyword ? isModuleDeclaration(parent) : - node.kind === SyntaxKind.ImportKeyword ? isImportEqualsDeclaration(parent) : - node.kind === SyntaxKind.GetKeyword ? isGetAccessorDeclaration(parent) : - node.kind === SyntaxKind.SetKeyword && isSetAccessorDeclaration(parent) + isModifier(node) && (forRename || node.kind !== SyntaxKind.DefaultKeyword) + ? canHaveModifiers(parent) && contains(parent.modifiers, node) + : node.kind === SyntaxKind.ClassKeyword ? isClassDeclaration(parent) || isClassExpression(node) + : node.kind === SyntaxKind.FunctionKeyword ? isFunctionDeclaration(parent) || isFunctionExpression(node) + : node.kind === SyntaxKind.InterfaceKeyword ? isInterfaceDeclaration(parent) + : node.kind === SyntaxKind.EnumKeyword ? isEnumDeclaration(parent) + : node.kind === SyntaxKind.TypeKeyword ? isTypeAliasDeclaration(parent) + : node.kind === SyntaxKind.NamespaceKeyword || node.kind === SyntaxKind.ModuleKeyword + ? isModuleDeclaration(parent) + : node.kind === SyntaxKind.ImportKeyword ? isImportEqualsDeclaration(parent) + : node.kind === SyntaxKind.GetKeyword ? isGetAccessorDeclaration(parent) + : node.kind === SyntaxKind.SetKeyword && isSetAccessorDeclaration(parent) ) { const location = getAdjustedLocationForDeclaration(parent, forRename); if (location) { @@ -1348,8 +1439,9 @@ function getAdjustedLocation(node: Node, forRename: boolean): Node { } // /**/ [|name|] ... if ( - (node.kind === SyntaxKind.VarKeyword || node.kind === SyntaxKind.ConstKeyword || node.kind === SyntaxKind.LetKeyword) && - isVariableDeclarationList(parent) && parent.declarations.length === 1 + (node.kind === SyntaxKind.VarKeyword || node.kind === SyntaxKind.ConstKeyword + || node.kind === SyntaxKind.LetKeyword) + && isVariableDeclarationList(parent) && parent.declarations.length === 1 ) { const decl = parent.declarations[0]; if (isIdentifier(decl.name)) { @@ -1384,10 +1476,10 @@ function getAdjustedLocation(node: Node, forRename: boolean): Node { // export * /**/as [|name|] ... if (node.kind === SyntaxKind.AsKeyword) { if ( - isImportSpecifier(parent) && parent.propertyName || - isExportSpecifier(parent) && parent.propertyName || - isNamespaceImport(parent) || - isNamespaceExport(parent) + isImportSpecifier(parent) && parent.propertyName + || isExportSpecifier(parent) && parent.propertyName + || isNamespaceImport(parent) + || isNamespaceExport(parent) ) { return parent.name; } @@ -1430,7 +1522,10 @@ function getAdjustedLocation(node: Node, forRename: boolean): Node { } // import ... /**/from "[|module|]"; // export ... /**/from "[|module|]"; - if (node.kind === SyntaxKind.FromKeyword && (isImportDeclaration(parent) || isExportDeclaration(parent)) && parent.moduleSpecifier) { + if ( + node.kind === SyntaxKind.FromKeyword && (isImportDeclaration(parent) || isExportDeclaration(parent)) + && parent.moduleSpecifier + ) { return parent.moduleSpecifier; } // class ... /**/extends [|name|] ... @@ -1438,7 +1533,10 @@ function getAdjustedLocation(node: Node, forRename: boolean): Node { // class ... /**/implements name1, name2 ... // interface ... /**/extends [|name|] ... // interface ... /**/extends name1, name2 ... - if ((node.kind === SyntaxKind.ExtendsKeyword || node.kind === SyntaxKind.ImplementsKeyword) && isHeritageClause(parent) && parent.token === node.kind) { + if ( + (node.kind === SyntaxKind.ExtendsKeyword || node.kind === SyntaxKind.ImplementsKeyword) + && isHeritageClause(parent) && parent.token === node.kind + ) { const location = getAdjustedLocationForHeritageClause(parent); if (location) { return location; @@ -1464,15 +1562,17 @@ function getAdjustedLocation(node: Node, forRename: boolean): Node { } // /**/keyof [|T|] if ( - node.kind === SyntaxKind.KeyOfKeyword && isTypeOperatorNode(parent) && parent.operator === SyntaxKind.KeyOfKeyword && - isTypeReferenceNode(parent.type) + node.kind === SyntaxKind.KeyOfKeyword && isTypeOperatorNode(parent) + && parent.operator === SyntaxKind.KeyOfKeyword + && isTypeReferenceNode(parent.type) ) { return parent.type.typeName; } // /**/readonly [|name|][] if ( - node.kind === SyntaxKind.ReadonlyKeyword && isTypeOperatorNode(parent) && parent.operator === SyntaxKind.ReadonlyKeyword && - isArrayTypeNode(parent.type) && isTypeReferenceNode(parent.type.elementType) + node.kind === SyntaxKind.ReadonlyKeyword && isTypeOperatorNode(parent) + && parent.operator === SyntaxKind.ReadonlyKeyword + && isArrayTypeNode(parent.type) && isTypeReferenceNode(parent.type.elementType) ) { return parent.type.elementType.typeName; } @@ -1488,12 +1588,12 @@ function getAdjustedLocation(node: Node, forRename: boolean): Node { // /**/yield obj.[|name|] // /**/delete obj.[|name|] if ( - node.kind === SyntaxKind.NewKeyword && isNewExpression(parent) || - node.kind === SyntaxKind.VoidKeyword && isVoidExpression(parent) || - node.kind === SyntaxKind.TypeOfKeyword && isTypeOfExpression(parent) || - node.kind === SyntaxKind.AwaitKeyword && isAwaitExpression(parent) || - node.kind === SyntaxKind.YieldKeyword && isYieldExpression(parent) || - node.kind === SyntaxKind.DeleteKeyword && isDeleteExpression(parent) + node.kind === SyntaxKind.NewKeyword && isNewExpression(parent) + || node.kind === SyntaxKind.VoidKeyword && isVoidExpression(parent) + || node.kind === SyntaxKind.TypeOfKeyword && isTypeOfExpression(parent) + || node.kind === SyntaxKind.AwaitKeyword && isAwaitExpression(parent) + || node.kind === SyntaxKind.YieldKeyword && isYieldExpression(parent) + || node.kind === SyntaxKind.DeleteKeyword && isDeleteExpression(parent) ) { if (parent.expression) { return skipOuterExpressions(parent.expression); @@ -1501,7 +1601,10 @@ function getAdjustedLocation(node: Node, forRename: boolean): Node { } // left /**/in [|name|] // left /**/instanceof [|name|] - if ((node.kind === SyntaxKind.InKeyword || node.kind === SyntaxKind.InstanceOfKeyword) && isBinaryExpression(parent) && parent.operatorToken === node) { + if ( + (node.kind === SyntaxKind.InKeyword || node.kind === SyntaxKind.InstanceOfKeyword) + && isBinaryExpression(parent) && parent.operatorToken === node + ) { return skipOuterExpressions(parent.right); } // left /**/as [|name|] @@ -1511,8 +1614,8 @@ function getAdjustedLocation(node: Node, forRename: boolean): Node { // for (... /**/in [|name|]) // for (... /**/of [|name|]) if ( - node.kind === SyntaxKind.InKeyword && isForInStatement(parent) || - node.kind === SyntaxKind.OfKeyword && isForOfStatement(parent) + node.kind === SyntaxKind.InKeyword && isForInStatement(parent) + || node.kind === SyntaxKind.OfKeyword && isForOfStatement(parent) ) { return skipOuterExpressions(parent.expression); } @@ -1546,7 +1649,11 @@ export function getAdjustedRenameLocation(node: Node): Node { * @internal */ export function getTouchingPropertyName(sourceFile: SourceFile, position: number): Node { - return getTouchingToken(sourceFile, position, n => isPropertyNameLiteral(n) || isKeyword(n.kind) || isPrivateIdentifier(n)); + return getTouchingToken( + sourceFile, + position, + n => isPropertyNameLiteral(n) || isKeyword(n.kind) || isPrivateIdentifier(n), + ); } /** @@ -1555,8 +1662,18 @@ export function getTouchingPropertyName(sourceFile: SourceFile, position: number * * @internal */ -export function getTouchingToken(sourceFile: SourceFile, position: number, includePrecedingTokenAtEndPosition?: (n: Node) => boolean): Node { - return getTokenAtPositionWorker(sourceFile, position, /*allowPositionInLeadingTrivia*/ false, includePrecedingTokenAtEndPosition, /*includeEndPosition*/ false); +export function getTouchingToken( + sourceFile: SourceFile, + position: number, + includePrecedingTokenAtEndPosition?: (n: Node) => boolean, +): Node { + return getTokenAtPositionWorker( + sourceFile, + position, + /*allowPositionInLeadingTrivia*/ false, + includePrecedingTokenAtEndPosition, + /*includeEndPosition*/ false, + ); } /** @@ -1565,11 +1682,23 @@ export function getTouchingToken(sourceFile: SourceFile, position: number, inclu * @internal */ export function getTokenAtPosition(sourceFile: SourceFile, position: number): Node { - return getTokenAtPositionWorker(sourceFile, position, /*allowPositionInLeadingTrivia*/ true, /*includePrecedingTokenAtEndPosition*/ undefined, /*includeEndPosition*/ false); + return getTokenAtPositionWorker( + sourceFile, + position, + /*allowPositionInLeadingTrivia*/ true, + /*includePrecedingTokenAtEndPosition*/ undefined, + /*includeEndPosition*/ false, + ); } /** Get the token whose text contains the position */ -function getTokenAtPositionWorker(sourceFile: SourceFile, position: number, allowPositionInLeadingTrivia: boolean, includePrecedingTokenAtEndPosition: ((n: Node) => boolean) | undefined, includeEndPosition: boolean): Node { +function getTokenAtPositionWorker( + sourceFile: SourceFile, + position: number, + allowPositionInLeadingTrivia: boolean, + includePrecedingTokenAtEndPosition: ((n: Node) => boolean) | undefined, + includeEndPosition: boolean, +): Node { let current: Node = sourceFile; let foundToken: Node | undefined; outer: @@ -1606,7 +1735,8 @@ function getTokenAtPositionWorker(sourceFile: SourceFile, position: number, allo return Comparison.LessThan; } - const start = allowPositionInLeadingTrivia ? children[middle].getFullStart() : children[middle].getStart(sourceFile, /*includeJsDocComment*/ true); + const start = allowPositionInLeadingTrivia ? children[middle].getFullStart() + : children[middle].getStart(sourceFile, /*includeJsDocComment*/ true); if (start > position) { return Comparison.GreaterThan; } @@ -1623,7 +1753,10 @@ function getTokenAtPositionWorker(sourceFile: SourceFile, position: number, allo } // this complex condition makes us left-recur around a zero-length node when includePrecedingTokenAtEndPosition is set, rather than right-recur on it - if (includePrecedingTokenAtEndPosition && start === position && children[middle - 1] && children[middle - 1].getEnd() === position && nodeContainsPosition(children[middle - 1])) { + if ( + includePrecedingTokenAtEndPosition && start === position && children[middle - 1] + && children[middle - 1].getEnd() === position && nodeContainsPosition(children[middle - 1]) + ) { return Comparison.GreaterThan; } return Comparison.LessThan; @@ -1645,7 +1778,8 @@ function getTokenAtPositionWorker(sourceFile: SourceFile, position: number, allo if (end < position) { return false; } - start ??= allowPositionInLeadingTrivia ? node.getFullStart() : node.getStart(sourceFile, /*includeJsDocComment*/ true); + start ??= allowPositionInLeadingTrivia ? node.getFullStart() + : node.getStart(sourceFile, /*includeJsDocComment*/ true); if (start > position) { // If this child begins after position, then all subsequent children will as well. return false; @@ -1712,9 +1846,9 @@ export function findNextToken(previousToken: Node, parent: Node, sourceFile: Sou return firstDefined(n.getChildren(sourceFile), child => { const shouldDiveInChildNode = // previous token is enclosed somewhere in the child - (child.pos <= previousToken.pos && child.end > previousToken.end) || + (child.pos <= previousToken.pos && child.end > previousToken.end) // previous token ends exactly at the beginning of child - (child.pos === previousToken.end); + || (child.pos === previousToken.end); return shouldDiveInChildNode && nodeHasTokens(child, sourceFile) ? find(child) : undefined; }); } @@ -1726,11 +1860,26 @@ export function findNextToken(previousToken: Node, parent: Node, sourceFile: Sou * * @internal */ -export function findPrecedingToken(position: number, sourceFile: SourceFileLike, startNode: Node, excludeJsdoc?: boolean): Node | undefined; -/** @internal */ -export function findPrecedingToken(position: number, sourceFile: SourceFile, startNode?: Node, excludeJsdoc?: boolean): Node | undefined; -/** @internal */ -export function findPrecedingToken(position: number, sourceFile: SourceFileLike, startNode?: Node, excludeJsdoc?: boolean): Node | undefined { +export function findPrecedingToken( + position: number, + sourceFile: SourceFileLike, + startNode: Node, + excludeJsdoc?: boolean, +): Node | undefined; +/** @internal */ +export function findPrecedingToken( + position: number, + sourceFile: SourceFile, + startNode?: Node, + excludeJsdoc?: boolean, +): Node | undefined; +/** @internal */ +export function findPrecedingToken( + position: number, + sourceFile: SourceFileLike, + startNode?: Node, + excludeJsdoc?: boolean, +): Node | undefined { const result = find((startNode || sourceFile) as Node); Debug.assert(!(result && isWhiteSpaceOnlyJsxText(result))); return result; @@ -1764,16 +1913,24 @@ export function findPrecedingToken(position: number, sourceFile: SourceFileLike, // 2) `position` is within the same span: we recurse on `child`. if (position < child.end) { const start = child.getStart(sourceFile, /*includeJsDoc*/ !excludeJsdoc); - const lookInPreviousChild = (start >= position) || // cursor in the leading trivia - !nodeHasTokens(child, sourceFile) || - isWhiteSpaceOnlyJsxText(child); + const lookInPreviousChild = (start >= position) // cursor in the leading trivia + || !nodeHasTokens(child, sourceFile) + || isWhiteSpaceOnlyJsxText(child); if (lookInPreviousChild) { // actual start of the node is past the position - previous token should be at the end of previous child - const candidate = findRightmostChildNodeWithTokens(children, /*exclusiveStartPosition*/ i, sourceFile, n.kind); + const candidate = findRightmostChildNodeWithTokens( + children, + /*exclusiveStartPosition*/ i, + sourceFile, + n.kind, + ); if (candidate) { // Ensure we recurse into JSDoc nodes with children. - if (!excludeJsdoc && isJSDocCommentContainingNode(candidate) && candidate.getChildren(sourceFile).length) { + if ( + !excludeJsdoc && isJSDocCommentContainingNode(candidate) + && candidate.getChildren(sourceFile).length + ) { return find(candidate); } return findRightmostToken(candidate, sourceFile); @@ -1787,13 +1944,21 @@ export function findPrecedingToken(position: number, sourceFile: SourceFileLike, } } - Debug.assert(startNode !== undefined || n.kind === SyntaxKind.SourceFile || n.kind === SyntaxKind.EndOfFileToken || isJSDocCommentContainingNode(n)); + Debug.assert( + startNode !== undefined || n.kind === SyntaxKind.SourceFile || n.kind === SyntaxKind.EndOfFileToken + || isJSDocCommentContainingNode(n), + ); // Here we know that none of child token nodes embrace the position, // the only known case is when position is at the end of the file. // Try to find the rightmost token in the file without filtering. // Namely we are skipping the check: 'position < node.end' - const candidate = findRightmostChildNodeWithTokens(children, /*exclusiveStartPosition*/ children.length, sourceFile, n.kind); + const candidate = findRightmostChildNodeWithTokens( + children, + /*exclusiveStartPosition*/ children.length, + sourceFile, + n.kind, + ); return candidate && findRightmostToken(candidate, sourceFile); } } @@ -1812,14 +1977,24 @@ function findRightmostToken(n: Node, sourceFile: SourceFileLike): Node | undefin return n; } - const candidate = findRightmostChildNodeWithTokens(children, /*exclusiveStartPosition*/ children.length, sourceFile, n.kind); + const candidate = findRightmostChildNodeWithTokens( + children, + /*exclusiveStartPosition*/ children.length, + sourceFile, + n.kind, + ); return candidate && findRightmostToken(candidate, sourceFile); } /** * Finds the rightmost child to the left of `children[exclusiveStartPosition]` which is a non-all-whitespace token or has constituent tokens. */ -function findRightmostChildNodeWithTokens(children: Node[], exclusiveStartPosition: number, sourceFile: SourceFileLike, parentKind: SyntaxKind): Node | undefined { +function findRightmostChildNodeWithTokens( + children: Node[], + exclusiveStartPosition: number, + sourceFile: SourceFileLike, + parentKind: SyntaxKind, +): Node | undefined { for (let i = exclusiveStartPosition - 1; i >= 0; i--) { const child = children[i]; @@ -1835,7 +2010,11 @@ function findRightmostChildNodeWithTokens(children: Node[], exclusiveStartPositi } /** @internal */ -export function isInString(sourceFile: SourceFile, position: number, previousToken = findPrecedingToken(position, sourceFile)): boolean { +export function isInString( + sourceFile: SourceFile, + position: number, + previousToken = findPrecedingToken(position, sourceFile), +): boolean { if (previousToken && isStringTextContainingNode(previousToken)) { const start = previousToken.getStart(sourceFile); const end = previousToken.getEnd(); @@ -1911,10 +2090,15 @@ export function isInJSXText(sourceFile: SourceFile, position: number) { if (isJsxText(token)) { return true; } - if (token.kind === SyntaxKind.OpenBraceToken && isJsxExpression(token.parent) && isJsxElement(token.parent.parent)) { + if ( + token.kind === SyntaxKind.OpenBraceToken && isJsxExpression(token.parent) && isJsxElement(token.parent.parent) + ) { return true; } - if (token.kind === SyntaxKind.LessThanToken && isJsxOpeningLikeElement(token.parent) && isJsxElement(token.parent.parent)) { + if ( + token.kind === SyntaxKind.LessThanToken && isJsxOpeningLikeElement(token.parent) + && isJsxElement(token.parent.parent) + ) { return true; } return false; @@ -1953,7 +2137,11 @@ export function isInsideJsxElement(sourceFile: SourceFile, position: number): bo } /** @internal */ -export function findPrecedingMatchingToken(token: Node, matchingTokenKind: SyntaxKind.OpenBraceToken | SyntaxKind.OpenParenToken | SyntaxKind.OpenBracketToken, sourceFile: SourceFile) { +export function findPrecedingMatchingToken( + token: Node, + matchingTokenKind: SyntaxKind.OpenBraceToken | SyntaxKind.OpenParenToken | SyntaxKind.OpenBracketToken, + sourceFile: SourceFile, +) { const closeTokenText = tokenToString(token.kind)!; const matchingTokenText = tokenToString(matchingTokenKind)!; const tokenFullStart = token.getFullStart(); @@ -1994,28 +2182,34 @@ export function findPrecedingMatchingToken(token: Node, matchingTokenKind: Synta /** @internal */ export function removeOptionality(type: Type, isOptionalExpression: boolean, isOptionalChain: boolean) { - return isOptionalExpression ? type.getNonNullableType() : - isOptionalChain ? type.getNonOptionalType() : - type; + return isOptionalExpression ? type.getNonNullableType() + : isOptionalChain ? type.getNonOptionalType() + : type; } /** @internal */ export function isPossiblyTypeArgumentPosition(token: Node, sourceFile: SourceFile, checker: TypeChecker): boolean { const info = getPossibleTypeArgumentsInfo(token, sourceFile); - return info !== undefined && (isPartOfTypeNode(info.called) || - getPossibleGenericSignatures(info.called, info.nTypeArguments, checker).length !== 0 || - isPossiblyTypeArgumentPosition(info.called, sourceFile, checker)); + return info !== undefined && (isPartOfTypeNode(info.called) + || getPossibleGenericSignatures(info.called, info.nTypeArguments, checker).length !== 0 + || isPossiblyTypeArgumentPosition(info.called, sourceFile, checker)); } /** @internal */ -export function getPossibleGenericSignatures(called: Expression, typeArgumentCount: number, checker: TypeChecker): readonly Signature[] { +export function getPossibleGenericSignatures( + called: Expression, + typeArgumentCount: number, + checker: TypeChecker, +): readonly Signature[] { let type = checker.getTypeAtLocation(called); if (isOptionalChain(called.parent)) { type = removeOptionality(type, isOptionalChainRoot(called.parent), /*isOptionalChain*/ true); } const signatures = isNewExpression(called.parent) ? type.getConstructSignatures() : type.getCallSignatures(); - return signatures.filter(candidate => !!candidate.typeParameters && candidate.typeParameters.length >= typeArgumentCount); + return signatures.filter(candidate => + !!candidate.typeParameters && candidate.typeParameters.length >= typeArgumentCount + ); } /** @internal */ @@ -2031,7 +2225,10 @@ export interface PossibleProgramFileInfo { // Get info for an expression like `f <` that may be the start of type arguments. /** @internal */ -export function getPossibleTypeArgumentsInfo(tokenIn: Node | undefined, sourceFile: SourceFile): PossibleTypeArgumentInfo | undefined { +export function getPossibleTypeArgumentsInfo( + tokenIn: Node | undefined, + sourceFile: SourceFile, +): PossibleTypeArgumentInfo | undefined { // This is a rare case, but one that saves on a _lot_ of work if true - if the source file has _no_ `<` character, // then there obviously can't be any type arguments - no expensive brace-matching backwards scanning required @@ -2141,7 +2338,11 @@ export function getPossibleTypeArgumentsInfo(tokenIn: Node | undefined, sourceFi * * @internal */ -export function isInComment(sourceFile: SourceFile, position: number, tokenAtPosition?: Node): CommentRange | undefined { +export function isInComment( + sourceFile: SourceFile, + position: number, + tokenAtPosition?: Node, +): CommentRange | undefined { return formatting.getRangeOfEnclosingComment(sourceFile, position, /*precedingToken*/ undefined, tokenAtPosition); } @@ -2167,7 +2368,9 @@ export function getNodeModifiers(node: Node, excludeFlags = ModifierFlags.None): if (flags & ModifierFlags.Private) result.push(ScriptElementKindModifier.privateMemberModifier); if (flags & ModifierFlags.Protected) result.push(ScriptElementKindModifier.protectedMemberModifier); if (flags & ModifierFlags.Public) result.push(ScriptElementKindModifier.publicMemberModifier); - if (flags & ModifierFlags.Static || isClassStaticBlockDeclaration(node)) result.push(ScriptElementKindModifier.staticModifier); + if (flags & ModifierFlags.Static || isClassStaticBlockDeclaration(node)) { + result.push(ScriptElementKindModifier.staticModifier); + } if (flags & ModifierFlags.Abstract) result.push(ScriptElementKindModifier.abstractModifier); if (flags & ModifierFlags.Export) result.push(ScriptElementKindModifier.exportedModifier); if (flags & ModifierFlags.Deprecated) result.push(ScriptElementKindModifier.deprecatedModifier); @@ -2183,7 +2386,10 @@ export function getTypeArgumentOrTypeParameterList(node: Node): NodeArray return (node as CallExpression).typeArguments; } - if (isFunctionLike(node) || node.kind === SyntaxKind.ClassDeclaration || node.kind === SyntaxKind.InterfaceDeclaration) { + if ( + isFunctionLike(node) || node.kind === SyntaxKind.ClassDeclaration + || node.kind === SyntaxKind.InterfaceDeclaration + ) { return (node as FunctionLikeDeclaration).typeParameters; } @@ -2218,14 +2424,16 @@ export function isStringAndEmptyAnonymousObjectIntersection(type: Type) { } const { types, checker } = type; - return types.length === 2 && - (areIntersectedTypesAvoidingStringReduction(checker, types[0], types[1]) || areIntersectedTypesAvoidingStringReduction(checker, types[1], types[0])); + return types.length === 2 + && (areIntersectedTypesAvoidingStringReduction(checker, types[0], types[1]) + || areIntersectedTypesAvoidingStringReduction(checker, types[1], types[0])); } /** @internal */ export function isInsideTemplateLiteral(node: TemplateLiteralToken, position: number, sourceFile: SourceFile): boolean { return isTemplateLiteralKind(node.kind) - && (node.getStart(sourceFile) < position && position < node.end) || (!!node.isUnterminated && position === node.end); + && (node.getStart(sourceFile) < position && position < node.end) + || (!!node.isUnterminated && position === node.end); } /** @internal */ @@ -2250,15 +2458,15 @@ export function cloneCompilerOptions(options: CompilerOptions): CompilerOptions /** @internal */ export function isArrayLiteralOrObjectLiteralDestructuringPattern(node: Node) { if ( - node.kind === SyntaxKind.ArrayLiteralExpression || - node.kind === SyntaxKind.ObjectLiteralExpression + node.kind === SyntaxKind.ArrayLiteralExpression + || node.kind === SyntaxKind.ObjectLiteralExpression ) { // [a,b,c] from: // [a, b, c] = someExpression; if ( - node.parent.kind === SyntaxKind.BinaryExpression && - (node.parent as BinaryExpression).left === node && - (node.parent as BinaryExpression).operatorToken.kind === SyntaxKind.EqualsToken + node.parent.kind === SyntaxKind.BinaryExpression + && (node.parent as BinaryExpression).left === node + && (node.parent as BinaryExpression).operatorToken.kind === SyntaxKind.EqualsToken ) { return true; } @@ -2266,8 +2474,8 @@ export function isArrayLiteralOrObjectLiteralDestructuringPattern(node: Node) { // [a, b, c] from: // for([a, b, c] of expression) if ( - node.parent.kind === SyntaxKind.ForOfStatement && - (node.parent as ForOfStatement).initializer === node + node.parent.kind === SyntaxKind.ForOfStatement + && (node.parent as ForOfStatement).initializer === node ) { return true; } @@ -2276,7 +2484,11 @@ export function isArrayLiteralOrObjectLiteralDestructuringPattern(node: Node) { // [x, [a, b, c] ] = someExpression // or // {x, a: {a, b, c} } = someExpression - if (isArrayLiteralOrObjectLiteralDestructuringPattern(node.parent.kind === SyntaxKind.PropertyAssignment ? node.parent.parent : node.parent)) { + if ( + isArrayLiteralOrObjectLiteralDestructuringPattern( + node.parent.kind === SyntaxKind.PropertyAssignment ? node.parent.parent : node.parent, + ) + ) { return true; } } @@ -2296,7 +2508,8 @@ export function isInNonReferenceComment(sourceFile: SourceFile, position: number function isInReferenceCommentWorker(sourceFile: SourceFile, position: number, shouldBeReference: boolean): boolean { const range = isInComment(sourceFile, position, /*tokenAtPosition*/ undefined); - return !!range && shouldBeReference === tripleSlashDirectivePrefixRegex.test(sourceFile.text.substring(range.pos, range.end)); + return !!range + && shouldBeReference === tripleSlashDirectivePrefixRegex.test(sourceFile.text.substring(range.pos, range.end)); } /** @internal */ @@ -2393,7 +2606,8 @@ export function isTypeKeywordTokenOrIdentifier(node: Node) { * @internal */ export function isExternalModuleSymbol(moduleSymbol: Symbol): boolean { - return !!(moduleSymbol.flags & SymbolFlags.Module) && moduleSymbol.name.charCodeAt(0) === CharacterCodes.doubleQuote; + return !!(moduleSymbol.flags & SymbolFlags.Module) + && moduleSymbol.name.charCodeAt(0) === CharacterCodes.doubleQuote; } /** @@ -2440,20 +2654,29 @@ export function getNameFromPropertyName(name: PropertyName): string | undefined /** @internal */ export function programContainsModules(program: Program): boolean { - return program.getSourceFiles().some(s => !s.isDeclarationFile && !program.isSourceFileFromExternalLibrary(s) && !!(s.externalModuleIndicator || s.commonJsModuleIndicator)); + return program.getSourceFiles().some(s => + !s.isDeclarationFile && !program.isSourceFileFromExternalLibrary(s) + && !!(s.externalModuleIndicator || s.commonJsModuleIndicator) + ); } /** @internal */ export function programContainsEsModules(program: Program): boolean { - return program.getSourceFiles().some(s => !s.isDeclarationFile && !program.isSourceFileFromExternalLibrary(s) && !!s.externalModuleIndicator); + return program.getSourceFiles().some(s => + !s.isDeclarationFile && !program.isSourceFileFromExternalLibrary(s) && !!s.externalModuleIndicator + ); } // TODO: this function is, at best, poorly named. Use sites are pretty suspicious. /** @internal */ export function compilerOptionsIndicateEsModules(compilerOptions: CompilerOptions): boolean { - return !!compilerOptions.module || getEmitScriptTarget(compilerOptions) >= ScriptTarget.ES2015 || !!compilerOptions.noEmit; + return !!compilerOptions.module || getEmitScriptTarget(compilerOptions) >= ScriptTarget.ES2015 + || !!compilerOptions.noEmit; } /** @internal */ -export function createModuleSpecifierResolutionHost(program: Program, host: LanguageServiceHost): ModuleSpecifierResolutionHost { +export function createModuleSpecifierResolutionHost( + program: Program, + host: LanguageServiceHost, +): ModuleSpecifierResolutionHost { // Mix in `getSymlinkCache` from Program when host doesn't have it // in order for non-Project hosts to have a symlinks cache. return { @@ -2474,7 +2697,10 @@ export function createModuleSpecifierResolutionHost(program: Program, host: Lang } /** @internal */ -export function getModuleSpecifierResolverHost(program: Program, host: LanguageServiceHost): SymbolTracker["moduleResolverHost"] { +export function getModuleSpecifierResolverHost( + program: Program, + host: LanguageServiceHost, +): SymbolTracker["moduleResolverHost"] { return { ...createModuleSpecifierResolutionHost(program, host), getCommonSourceDirectory: () => program.getCommonSourceDirectory(), @@ -2489,16 +2715,32 @@ export function moduleResolutionUsesNodeModules(moduleResolution: ModuleResoluti } /** @internal */ -export function makeImportIfNecessary(defaultImport: Identifier | undefined, namedImports: readonly ImportSpecifier[] | undefined, moduleSpecifier: string, quotePreference: QuotePreference): ImportDeclaration | undefined { - return defaultImport || namedImports && namedImports.length ? makeImport(defaultImport, namedImports, moduleSpecifier, quotePreference) : undefined; +export function makeImportIfNecessary( + defaultImport: Identifier | undefined, + namedImports: readonly ImportSpecifier[] | undefined, + moduleSpecifier: string, + quotePreference: QuotePreference, +): ImportDeclaration | undefined { + return defaultImport || namedImports && namedImports.length + ? makeImport(defaultImport, namedImports, moduleSpecifier, quotePreference) : undefined; } /** @internal */ -export function makeImport(defaultImport: Identifier | undefined, namedImports: readonly ImportSpecifier[] | undefined, moduleSpecifier: string | Expression, quotePreference: QuotePreference, isTypeOnly?: boolean): ImportDeclaration { +export function makeImport( + defaultImport: Identifier | undefined, + namedImports: readonly ImportSpecifier[] | undefined, + moduleSpecifier: string | Expression, + quotePreference: QuotePreference, + isTypeOnly?: boolean, +): ImportDeclaration { return factory.createImportDeclaration( /*modifiers*/ undefined, defaultImport || namedImports - ? factory.createImportClause(!!isTypeOnly, defaultImport, namedImports && namedImports.length ? factory.createNamedImports(namedImports) : undefined) + ? factory.createImportClause( + !!isTypeOnly, + defaultImport, + namedImports && namedImports.length ? factory.createNamedImports(namedImports) : undefined, + ) : undefined, typeof moduleSpecifier === "string" ? makeStringLiteral(moduleSpecifier, quotePreference) : moduleSpecifier, /*assertClause*/ undefined, @@ -2528,9 +2770,10 @@ export function getQuotePreference(sourceFile: SourceFile, preferences: UserPref } else { // ignore synthetic import added when importHelpers: true - const firstModuleSpecifier = sourceFile.imports && - find(sourceFile.imports, n => isStringLiteral(n) && !nodeIsSynthesized(n.parent)) as StringLiteral; - return firstModuleSpecifier ? quotePreferenceFromString(firstModuleSpecifier, sourceFile) : QuotePreference.Double; + const firstModuleSpecifier = sourceFile.imports + && find(sourceFile.imports, n => isStringLiteral(n) && !nodeIsSynthesized(n.parent)) as StringLiteral; + return firstModuleSpecifier ? quotePreferenceFromString(firstModuleSpecifier, sourceFile) + : QuotePreference.Double; } } @@ -2567,10 +2810,10 @@ export function symbolEscapedNameNoDefault(symbol: Symbol): __String | undefined /** @internal */ export function isModuleSpecifierLike(node: Node): node is StringLiteralLike { return isStringLiteralLike(node) && ( - isExternalModuleReference(node.parent) || - isImportDeclaration(node.parent) || - isRequireCall(node.parent, /*requireStringLiteralLikeArgument*/ false) && node.parent.arguments[0] === node || - isImportCall(node.parent) && node.parent.arguments[0] === node + isExternalModuleReference(node.parent) + || isImportDeclaration(node.parent) + || isRequireCall(node.parent, /*requireStringLiteralLikeArgument*/ false) && node.parent.arguments[0] === node + || isImportCall(node.parent) && node.parent.arguments[0] === node ); } @@ -2578,15 +2821,20 @@ export function isModuleSpecifierLike(node: Node): node is StringLiteralLike { export type ObjectBindingElementWithoutPropertyName = BindingElement & { name: Identifier; }; /** @internal */ -export function isObjectBindingElementWithoutPropertyName(bindingElement: Node): bindingElement is ObjectBindingElementWithoutPropertyName { - return isBindingElement(bindingElement) && - isObjectBindingPattern(bindingElement.parent) && - isIdentifier(bindingElement.name) && - !bindingElement.propertyName; +export function isObjectBindingElementWithoutPropertyName( + bindingElement: Node, +): bindingElement is ObjectBindingElementWithoutPropertyName { + return isBindingElement(bindingElement) + && isObjectBindingPattern(bindingElement.parent) + && isIdentifier(bindingElement.name) + && !bindingElement.propertyName; } /** @internal */ -export function getPropertySymbolFromBindingElement(checker: TypeChecker, bindingElement: ObjectBindingElementWithoutPropertyName): Symbol | undefined { +export function getPropertySymbolFromBindingElement( + checker: TypeChecker, + bindingElement: ObjectBindingElementWithoutPropertyName, +): Symbol | undefined { const typeOfPattern = checker.getTypeAtLocation(bindingElement.parent); return typeOfPattern && checker.getPropertyOfType(typeOfPattern, bindingElement.name.text); } @@ -2605,8 +2853,8 @@ export function getParentNodeInSpan(node: Node | undefined, file: SourceFile, sp } function spanContainsNode(span: TextSpan, node: Node, file: SourceFile): boolean { - return textSpanContainsPosition(span, node.getStart(file)) && - node.getEnd() <= textSpanEnd(span); + return textSpanContainsPosition(span, node.getStart(file)) + && node.getEnd() <= textSpanEnd(span); } /** @internal */ @@ -2615,25 +2863,47 @@ export function findModifier(node: Node, kind: Modifier["kind"]): Modifier | und } /** @internal */ -export function insertImports(changes: textChanges.ChangeTracker, sourceFile: SourceFile, imports: AnyImportOrRequireStatement | readonly AnyImportOrRequireStatement[], blankLineBetween: boolean, preferences: UserPreferences): void { +export function insertImports( + changes: textChanges.ChangeTracker, + sourceFile: SourceFile, + imports: AnyImportOrRequireStatement | readonly AnyImportOrRequireStatement[], + blankLineBetween: boolean, + preferences: UserPreferences, +): void { const decl = isArray(imports) ? imports[0] : imports; - const importKindPredicate: (node: Node) => node is AnyImportOrRequireStatement = decl.kind === SyntaxKind.VariableStatement ? isRequireVariableStatement : isAnyImportSyntax; + const importKindPredicate: (node: Node) => node is AnyImportOrRequireStatement = + decl.kind === SyntaxKind.VariableStatement ? isRequireVariableStatement : isAnyImportSyntax; const existingImportStatements = filter(sourceFile.statements, importKindPredicate); - let sortKind = isArray(imports) ? OrganizeImports.detectImportDeclarationSorting(imports, preferences) : SortKind.Both; + let sortKind = isArray(imports) ? OrganizeImports.detectImportDeclarationSorting(imports, preferences) + : SortKind.Both; const comparer = OrganizeImports.getOrganizeImportsComparer(preferences, sortKind === SortKind.CaseInsensitive); - const sortedNewImports = isArray(imports) ? stableSort(imports, (a, b) => OrganizeImports.compareImportsOrRequireStatements(a, b, comparer)) : [imports]; + const sortedNewImports = isArray(imports) + ? stableSort(imports, (a, b) => OrganizeImports.compareImportsOrRequireStatements(a, b, comparer)) : [imports]; if (!existingImportStatements.length) { changes.insertNodesAtTopOfFile(sourceFile, sortedNewImports, blankLineBetween); } - else if (existingImportStatements && (sortKind = OrganizeImports.detectImportDeclarationSorting(existingImportStatements, preferences))) { + else if ( + existingImportStatements + && (sortKind = OrganizeImports.detectImportDeclarationSorting(existingImportStatements, preferences)) + ) { const comparer = OrganizeImports.getOrganizeImportsComparer(preferences, sortKind === SortKind.CaseInsensitive); for (const newImport of sortedNewImports) { - const insertionIndex = OrganizeImports.getImportDeclarationInsertionIndex(existingImportStatements, newImport, comparer); + const insertionIndex = OrganizeImports.getImportDeclarationInsertionIndex( + existingImportStatements, + newImport, + comparer, + ); if (insertionIndex === 0) { // If the first import is top-of-file, insert after the leading comment which is likely the header. - const options = existingImportStatements[0] === sourceFile.statements[0] ? - { leadingTriviaOption: textChanges.LeadingTriviaOption.Exclude } : {}; - changes.insertNodeBefore(sourceFile, existingImportStatements[0], newImport, /*blankLineBetween*/ false, options); + const options = existingImportStatements[0] === sourceFile.statements[0] + ? { leadingTriviaOption: textChanges.LeadingTriviaOption.Exclude } : {}; + changes.insertNodeBefore( + sourceFile, + existingImportStatements[0], + newImport, + /*blankLineBetween*/ false, + options, + ); } else { const prevImport = existingImportStatements[insertionIndex - 1]; @@ -2653,7 +2923,10 @@ export function insertImports(changes: textChanges.ChangeTracker, sourceFile: So } /** @internal */ -export function getTypeKeywordOfTypeOnlyImport(importClause: ImportClause, sourceFile: SourceFile): Token { +export function getTypeKeywordOfTypeOnlyImport( + importClause: ImportClause, + sourceFile: SourceFile, +): Token { Debug.assert(importClause.isTypeOnly); return cast(importClause.getChildAt(0, sourceFile), isTypeKeywordToken); } @@ -2674,7 +2947,10 @@ export function documentSpansEqual(a: DocumentSpan, b: DocumentSpan): boolean { * * @internal */ -export function forEachUnique(array: readonly T[] | undefined, callback: (element: T, index: number) => U): U | undefined { +export function forEachUnique( + array: readonly T[] | undefined, + callback: (element: T, index: number) => U, +): U | undefined { if (array) { for (let i = 0; i < array.length; i++) { if (array.indexOf(array[i]) === i) { @@ -2700,17 +2976,29 @@ export function isTextWhiteSpaceLike(text: string, startPos: number, endPos: num } /** @internal */ -export function getMappedLocation(location: DocumentPosition, sourceMapper: SourceMapper, fileExists: ((path: string) => boolean) | undefined): DocumentPosition | undefined { +export function getMappedLocation( + location: DocumentPosition, + sourceMapper: SourceMapper, + fileExists: ((path: string) => boolean) | undefined, +): DocumentPosition | undefined { const mapsTo = sourceMapper.tryGetSourcePosition(location); return mapsTo && (!fileExists || fileExists(normalizePath(mapsTo.fileName)) ? mapsTo : undefined); } /** @internal */ -export function getMappedDocumentSpan(documentSpan: DocumentSpan, sourceMapper: SourceMapper, fileExists?: (path: string) => boolean): DocumentSpan | undefined { +export function getMappedDocumentSpan( + documentSpan: DocumentSpan, + sourceMapper: SourceMapper, + fileExists?: (path: string) => boolean, +): DocumentSpan | undefined { const { fileName, textSpan } = documentSpan; const newPosition = getMappedLocation({ fileName, pos: textSpan.start }, sourceMapper, fileExists); if (!newPosition) return undefined; - const newEndPosition = getMappedLocation({ fileName, pos: textSpan.start + textSpan.length }, sourceMapper, fileExists); + const newEndPosition = getMappedLocation( + { fileName, pos: textSpan.start + textSpan.length }, + sourceMapper, + fileExists, + ); const newLength = newEndPosition ? newEndPosition.pos - newPosition.pos : textSpan.length; // This shouldn't happen @@ -2728,7 +3016,11 @@ export function getMappedDocumentSpan(documentSpan: DocumentSpan, sourceMapper: } /** @internal */ -export function getMappedContextSpan(documentSpan: DocumentSpan, sourceMapper: SourceMapper, fileExists?: (path: string) => boolean): TextSpan | undefined { +export function getMappedContextSpan( + documentSpan: DocumentSpan, + sourceMapper: SourceMapper, + fileExists?: (path: string) => boolean, +): TextSpan | undefined { const contextSpanStart = documentSpan.contextSpan && getMappedLocation( { fileName: documentSpan.fileName, pos: documentSpan.contextSpan.start }, sourceMapper, @@ -2739,9 +3031,9 @@ export function getMappedContextSpan(documentSpan: DocumentSpan, sourceMapper: S sourceMapper, fileExists, ); - return contextSpanStart && contextSpanEnd ? - { start: contextSpanStart.pos, length: contextSpanEnd.pos - contextSpanStart.pos } : - undefined; + return contextSpanStart && contextSpanEnd + ? { start: contextSpanStart.pos, length: contextSpanEnd.pos - contextSpanStart.pos } + : undefined; } // #endregion @@ -2751,7 +3043,11 @@ export function getMappedContextSpan(documentSpan: DocumentSpan, sourceMapper: S /** @internal */ export function isFirstDeclarationOfSymbolParameter(symbol: Symbol) { const declaration = symbol.declarations ? firstOrUndefined(symbol.declarations) : undefined; - return !!findAncestor(declaration, n => isParameter(n) ? true : isBindingElement(n) || isObjectBindingPattern(n) || isArrayBindingPattern(n) ? false : "quit"); + return !!findAncestor( + declaration, + n => isParameter(n) ? true + : isBindingElement(n) || isObjectBindingPattern(n) || isArrayBindingPattern(n) ? false : "quit", + ); } const displayPartWriter = getDisplayPartWriter(); @@ -2855,7 +3151,8 @@ export function symbolPart(text: string, symbol: Symbol) { const flags = symbol.flags; if (flags & SymbolFlags.Variable) { - return isFirstDeclarationOfSymbolParameter(symbol) ? SymbolDisplayPartKind.parameterName : SymbolDisplayPartKind.localName; + return isFirstDeclarationOfSymbolParameter(symbol) ? SymbolDisplayPartKind.parameterName + : SymbolDisplayPartKind.localName; } if (flags & SymbolFlags.Property) return SymbolDisplayPartKind.propertyName; if (flags & SymbolFlags.GetAccessor) return SymbolDisplayPartKind.propertyName; @@ -2956,7 +3253,10 @@ export function linkPart(text: string) { } /** @internal */ -export function buildLinkParts(link: JSDocLink | JSDocLinkCode | JSDocLinkPlain, checker?: TypeChecker): SymbolDisplayPart[] { +export function buildLinkParts( + link: JSDocLink | JSDocLinkCode | JSDocLinkPlain, + checker?: TypeChecker, +): SymbolDisplayPart[] { const prefix = isJSDocLink(link) ? "link" : isJSDocLinkCode(link) ? "linkcode" : "linkplain"; @@ -3020,9 +3320,9 @@ const lineFeed = "\n"; * @internal */ export function getNewLineOrDefaultFromHost(host: FormattingHost, formatSettings: FormatCodeSettings | undefined) { - return formatSettings?.newLineCharacter || - host.getNewLine?.() || - lineFeed; + return formatSettings?.newLineCharacter + || host.getNewLine?.() + || lineFeed; } /** @internal */ @@ -3042,22 +3342,50 @@ export function mapToDisplayParts(writeDisplayParts: (writer: DisplayPartsSymbol } /** @internal */ -export function typeToDisplayParts(typechecker: TypeChecker, type: Type, enclosingDeclaration?: Node, flags: TypeFormatFlags = TypeFormatFlags.None): SymbolDisplayPart[] { +export function typeToDisplayParts( + typechecker: TypeChecker, + type: Type, + enclosingDeclaration?: Node, + flags: TypeFormatFlags = TypeFormatFlags.None, +): SymbolDisplayPart[] { return mapToDisplayParts(writer => { - typechecker.writeType(type, enclosingDeclaration, flags | TypeFormatFlags.MultilineObjectLiterals | TypeFormatFlags.UseAliasDefinedOutsideCurrentScope, writer); + typechecker.writeType( + type, + enclosingDeclaration, + flags | TypeFormatFlags.MultilineObjectLiterals | TypeFormatFlags.UseAliasDefinedOutsideCurrentScope, + writer, + ); }); } /** @internal */ -export function symbolToDisplayParts(typeChecker: TypeChecker, symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags, flags: SymbolFormatFlags = SymbolFormatFlags.None): SymbolDisplayPart[] { +export function symbolToDisplayParts( + typeChecker: TypeChecker, + symbol: Symbol, + enclosingDeclaration?: Node, + meaning?: SymbolFlags, + flags: SymbolFormatFlags = SymbolFormatFlags.None, +): SymbolDisplayPart[] { return mapToDisplayParts(writer => { - typeChecker.writeSymbol(symbol, enclosingDeclaration, meaning, flags | SymbolFormatFlags.UseAliasDefinedOutsideCurrentScope, writer); + typeChecker.writeSymbol( + symbol, + enclosingDeclaration, + meaning, + flags | SymbolFormatFlags.UseAliasDefinedOutsideCurrentScope, + writer, + ); }); } /** @internal */ -export function signatureToDisplayParts(typechecker: TypeChecker, signature: Signature, enclosingDeclaration?: Node, flags: TypeFormatFlags = TypeFormatFlags.None): SymbolDisplayPart[] { - flags |= TypeFormatFlags.UseAliasDefinedOutsideCurrentScope | TypeFormatFlags.MultilineObjectLiterals | TypeFormatFlags.WriteTypeArgumentsOfSignature | TypeFormatFlags.OmitParameterModifiers; +export function signatureToDisplayParts( + typechecker: TypeChecker, + signature: Signature, + enclosingDeclaration?: Node, + flags: TypeFormatFlags = TypeFormatFlags.None, +): SymbolDisplayPart[] { + flags |= TypeFormatFlags.UseAliasDefinedOutsideCurrentScope | TypeFormatFlags.MultilineObjectLiterals + | TypeFormatFlags.WriteTypeArgumentsOfSignature | TypeFormatFlags.OmitParameterModifiers; return mapToDisplayParts(writer => { typechecker.writeSignature(signature, enclosingDeclaration, flags, /*kind*/ undefined, writer); }); @@ -3166,9 +3494,11 @@ function getSynthesizedDeepCloneWorker(node: T, replaceNode?: (n if (visited === node) { // This only happens for leaf nodes - internal nodes always see their children change. - const clone = isStringLiteral(node) ? setOriginalNode(factory.createStringLiteralFromNode(node), node) as Node as T : - isNumericLiteral(node) ? setOriginalNode(factory.createNumericLiteral(node.text, node.numericLiteralFlags), node) as Node as T : - factory.cloneNode(node); + const clone = isStringLiteral(node) + ? setOriginalNode(factory.createStringLiteralFromNode(node), node) as Node as T + : isNumericLiteral(node) + ? setOriginalNode(factory.createNumericLiteral(node.text, node.numericLiteralFlags), node) as Node as T + : factory.cloneNode(node); return setTextRange(clone, node); } @@ -3182,11 +3512,20 @@ function getSynthesizedDeepCloneWorker(node: T, replaceNode?: (n /** @internal */ export function getSynthesizedDeepClones(nodes: NodeArray, includeTrivia?: boolean): NodeArray; /** @internal */ -export function getSynthesizedDeepClones(nodes: NodeArray | undefined, includeTrivia?: boolean): NodeArray | undefined; +export function getSynthesizedDeepClones( + nodes: NodeArray | undefined, + includeTrivia?: boolean, +): NodeArray | undefined; /** @internal */ -export function getSynthesizedDeepClones(nodes: NodeArray | undefined, includeTrivia = true): NodeArray | undefined { +export function getSynthesizedDeepClones( + nodes: NodeArray | undefined, + includeTrivia = true, +): NodeArray | undefined { if (nodes) { - const cloned = factory.createNodeArray(nodes.map(n => getSynthesizedDeepClone(n, includeTrivia)), nodes.hasTrailingComma); + const cloned = factory.createNodeArray( + nodes.map(n => getSynthesizedDeepClone(n, includeTrivia)), + nodes.hasTrailingComma, + ); setTextRange(cloned, nodes); return cloned; } @@ -3199,7 +3538,10 @@ export function getSynthesizedDeepClonesWithReplacements( includeTrivia: boolean, replaceNode: (node: Node) => Node | undefined, ): NodeArray { - return factory.createNodeArray(nodes.map(n => getSynthesizedDeepCloneWithReplacements(n, includeTrivia, replaceNode)), nodes.hasTrailingComma); + return factory.createNodeArray( + nodes.map(n => getSynthesizedDeepCloneWithReplacements(n, includeTrivia, replaceNode)), + nodes.hasTrailingComma, + ); } /** @@ -3278,7 +3620,12 @@ export function getUniqueName(baseName: string, sourceFile: SourceFile): string * * @internal */ -export function getRenameLocation(edits: readonly FileTextChanges[], renameFilename: string, name: string, preferLastLocation: boolean): number { +export function getRenameLocation( + edits: readonly FileTextChanges[], + renameFilename: string, + name: string, + preferLastLocation: boolean, +): number { let delta = 0; let lastPos = -1; for (const { fileName, textChanges } of edits) { @@ -3305,13 +3652,33 @@ export function getRenameLocation(edits: readonly FileTextChanges[], renameFilen } /** @internal */ -export function copyLeadingComments(sourceNode: Node, targetNode: Node, sourceFile: SourceFile, commentKind?: CommentKind, hasTrailingNewLine?: boolean) { - forEachLeadingCommentRange(sourceFile.text, sourceNode.pos, getAddCommentsFunction(targetNode, sourceFile, commentKind, hasTrailingNewLine, addSyntheticLeadingComment)); +export function copyLeadingComments( + sourceNode: Node, + targetNode: Node, + sourceFile: SourceFile, + commentKind?: CommentKind, + hasTrailingNewLine?: boolean, +) { + forEachLeadingCommentRange( + sourceFile.text, + sourceNode.pos, + getAddCommentsFunction(targetNode, sourceFile, commentKind, hasTrailingNewLine, addSyntheticLeadingComment), + ); } /** @internal */ -export function copyTrailingComments(sourceNode: Node, targetNode: Node, sourceFile: SourceFile, commentKind?: CommentKind, hasTrailingNewLine?: boolean) { - forEachTrailingCommentRange(sourceFile.text, sourceNode.end, getAddCommentsFunction(targetNode, sourceFile, commentKind, hasTrailingNewLine, addSyntheticTrailingComment)); +export function copyTrailingComments( + sourceNode: Node, + targetNode: Node, + sourceFile: SourceFile, + commentKind?: CommentKind, + hasTrailingNewLine?: boolean, +) { + forEachTrailingCommentRange( + sourceFile.text, + sourceNode.end, + getAddCommentsFunction(targetNode, sourceFile, commentKind, hasTrailingNewLine, addSyntheticTrailingComment), + ); } /** @@ -3323,11 +3690,27 @@ export function copyTrailingComments(sourceNode: Node, targetNode: Node, sourceF * * @internal */ -export function copyTrailingAsLeadingComments(sourceNode: Node, targetNode: Node, sourceFile: SourceFile, commentKind?: CommentKind, hasTrailingNewLine?: boolean) { - forEachTrailingCommentRange(sourceFile.text, sourceNode.pos, getAddCommentsFunction(targetNode, sourceFile, commentKind, hasTrailingNewLine, addSyntheticLeadingComment)); +export function copyTrailingAsLeadingComments( + sourceNode: Node, + targetNode: Node, + sourceFile: SourceFile, + commentKind?: CommentKind, + hasTrailingNewLine?: boolean, +) { + forEachTrailingCommentRange( + sourceFile.text, + sourceNode.pos, + getAddCommentsFunction(targetNode, sourceFile, commentKind, hasTrailingNewLine, addSyntheticLeadingComment), + ); } -function getAddCommentsFunction(targetNode: Node, sourceFile: SourceFile, commentKind: CommentKind | undefined, hasTrailingNewLine: boolean | undefined, cb: (node: Node, kind: CommentKind, text: string, hasTrailingNewLine?: boolean) => void) { +function getAddCommentsFunction( + targetNode: Node, + sourceFile: SourceFile, + commentKind: CommentKind | undefined, + hasTrailingNewLine: boolean | undefined, + cb: (node: Node, kind: CommentKind, text: string, hasTrailingNewLine?: boolean) => void, +) { return (pos: number, end: number, kind: CommentKind, htnl: boolean) => { if (kind === SyntaxKind.MultiLineCommentTrivia) { // Remove leading /* @@ -3339,7 +3722,12 @@ function getAddCommentsFunction(targetNode: Node, sourceFile: SourceFile, commen // Remove leading // pos += 2; } - cb(targetNode, commentKind || kind, sourceFile.text.slice(pos, end), hasTrailingNewLine !== undefined ? hasTrailingNewLine : htnl); + cb( + targetNode, + commentKind || kind, + sourceFile.text.slice(pos, end), + hasTrailingNewLine !== undefined ? hasTrailingNewLine : htnl, + ); }; } @@ -3360,7 +3748,11 @@ export function needsParentheses(expression: Expression): boolean { } /** @internal */ -export function getContextualTypeFromParent(node: Expression, checker: TypeChecker, contextFlags?: ContextFlags): Type | undefined { +export function getContextualTypeFromParent( + node: Expression, + checker: TypeChecker, + contextFlags?: ContextFlags, +): Type | undefined { const parent = walkUpParenthesizedExpressions(node.parent); switch (parent.kind) { case SyntaxKind.NewExpression: @@ -3383,7 +3775,8 @@ export function quote(sourceFile: SourceFile, preferences: UserPreferences, text // Editors can pass in undefined or empty string - we want to infer the preference in those cases. const quotePreference = getQuotePreference(sourceFile, preferences); const quoted = JSON.stringify(text); - return quotePreference === QuotePreference.Single ? `'${stripQuotes(quoted).replace(/'/g, "\\'").replace(/\\"/g, '"')}'` : quoted; + return quotePreference === QuotePreference.Single + ? `'${stripQuotes(quoted).replace(/'/g, "\\'").replace(/\\"/g, '"')}'` : quoted; } /** @internal */ @@ -3400,7 +3793,9 @@ export function isEqualityOperatorKind(kind: SyntaxKind): kind is EqualityOperat } /** @internal */ -export function isStringLiteralOrTemplate(node: Node): node is StringLiteralLike | TemplateExpression | TaggedTemplateExpression { +export function isStringLiteralOrTemplate( + node: Node, +): node is StringLiteralLike | TemplateExpression | TaggedTemplateExpression { switch (node.kind) { case SyntaxKind.StringLiteral: case SyntaxKind.NoSubstitutionTemplateLiteral: @@ -3426,13 +3821,20 @@ export function getSwitchedType(caseClause: CaseClause, checker: TypeChecker): T export const ANONYMOUS = "anonymous function"; /** @internal */ -export function getTypeNodeIfAccessible(type: Type, enclosingScope: Node, program: Program, host: LanguageServiceHost): TypeNode | undefined { +export function getTypeNodeIfAccessible( + type: Type, + enclosingScope: Node, + program: Program, + host: LanguageServiceHost, +): TypeNode | undefined { const checker = program.getTypeChecker(); let typeIsAccessible = true; const notAccessible = () => typeIsAccessible = false; const res = checker.typeToTypeNode(type, enclosingScope, NodeBuilderFlags.NoTruncation, { trackSymbol: (symbol, declaration, meaning) => { - typeIsAccessible = typeIsAccessible && checker.isSymbolAccessible(symbol, declaration, meaning, /*shouldComputeAliasToMarkVisible*/ false).accessibility === SymbolAccessibility.Accessible; + typeIsAccessible = typeIsAccessible + && checker.isSymbolAccessible(symbol, declaration, meaning, /*shouldComputeAliasToMarkVisible*/ false) + .accessibility === SymbolAccessibility.Accessible; return !typeIsAccessible; }, reportInaccessibleThisError: notAccessible, @@ -3567,7 +3969,9 @@ export function probablyUsesSemicolons(sourceFile: SourceFile): boolean { } else if (lastToken && lastToken.kind !== SyntaxKind.CommaToken) { const lastTokenLine = getLineAndCharacterOfPosition(sourceFile, lastToken.getStart(sourceFile)).line; - const nextTokenLine = getLineAndCharacterOfPosition(sourceFile, getSpanOfTokenAtPosition(sourceFile, lastToken.end).start).line; + const nextTokenLine = + getLineAndCharacterOfPosition(sourceFile, getSpanOfTokenAtPosition(sourceFile, lastToken.end).start) + .line; // Avoid counting missing semicolon in single-line objects: // `function f(p: { x: string /*no semicolon here is insignificant*/ }) {` if (lastTokenLine !== nextTokenLine) { @@ -3599,7 +4003,13 @@ export function tryGetDirectories(host: Pick, path: string, extensions?: readonly string[], exclude?: readonly string[], include?: readonly string[]): readonly string[] { +export function tryReadDirectory( + host: Pick, + path: string, + extensions?: readonly string[], + exclude?: readonly string[], + include?: readonly string[], +): readonly string[] { return tryIOAndConsumeErrors(host, host.readDirectory, path, extensions, exclude, include) || emptyArray; } @@ -3629,7 +4039,11 @@ export function tryIOAndConsumeErrors(host: unknown, toApply: ((...a: any[]) } /** @internal */ -export function findPackageJsons(startDirectory: string, host: Pick, stopDirectory?: string): string[] { +export function findPackageJsons( + startDirectory: string, + host: Pick, + stopDirectory?: string, +): string[] { const paths: string[] = []; forEachAncestorDirectory(startDirectory, ancestor => { if (ancestor === stopDirectory) { @@ -3657,7 +4071,10 @@ export function findPackageJson(directory: string, host: LanguageServiceHost): s } /** @internal */ -export function getPackageJsonsVisibleToFile(fileName: string, host: LanguageServiceHost): readonly ProjectPackageJsonInfo[] { +export function getPackageJsonsVisibleToFile( + fileName: string, + host: LanguageServiceHost, +): readonly ProjectPackageJsonInfo[] { if (!host.fileExists) { return []; } @@ -3677,7 +4094,10 @@ export function getPackageJsonsVisibleToFile(fileName: string, host: LanguageSer } /** @internal */ -export function createPackageJsonInfo(fileName: string, host: { readFile?(fileName: string): string | undefined; }): ProjectPackageJsonInfo | undefined { +export function createPackageJsonInfo( + fileName: string, + host: { readFile?(fileName: string): string | undefined; }, +): ProjectPackageJsonInfo | undefined { if (!host.readFile) { return undefined; } @@ -3732,8 +4152,14 @@ export function createPackageJsonInfo(fileName: string, host: { readFile?(fileNa /** @internal */ export interface PackageJsonImportFilter { - allowsImportingAmbientModule: (moduleSymbol: Symbol, moduleSpecifierResolutionHost: ModuleSpecifierResolutionHost) => boolean; - allowsImportingSourceFile: (sourceFile: SourceFile, moduleSpecifierResolutionHost: ModuleSpecifierResolutionHost) => boolean; + allowsImportingAmbientModule: ( + moduleSymbol: Symbol, + moduleSpecifierResolutionHost: ModuleSpecifierResolutionHost, + ) => boolean; + allowsImportingSourceFile: ( + sourceFile: SourceFile, + moduleSpecifierResolutionHost: ModuleSpecifierResolutionHost, + ) => boolean; /** * Use for a specific module specifier that has already been resolved. * Use `allowsImportingAmbientModule` or `allowsImportingSourceFile` to resolve @@ -3743,9 +4169,14 @@ export interface PackageJsonImportFilter { } /** @internal */ -export function createPackageJsonImportFilter(fromFile: SourceFile, preferences: UserPreferences, host: LanguageServiceHost): PackageJsonImportFilter { +export function createPackageJsonImportFilter( + fromFile: SourceFile, + preferences: UserPreferences, + host: LanguageServiceHost, +): PackageJsonImportFilter { const packageJsons = ( - (host.getPackageJsonsVisibleToFile && host.getPackageJsonsVisibleToFile(fromFile.fileName)) || getPackageJsonsVisibleToFile(fromFile.fileName, host) + (host.getPackageJsonsVisibleToFile && host.getPackageJsonsVisibleToFile(fromFile.fileName)) + || getPackageJsonsVisibleToFile(fromFile.fileName, host) ).filter(p => p.parseable); let usesNodeCoreModules: boolean | undefined; @@ -3767,7 +4198,10 @@ export function createPackageJsonImportFilter(fromFile: SourceFile, preferences: return false; } - function allowsImportingAmbientModule(moduleSymbol: Symbol, moduleSpecifierResolutionHost: ModuleSpecifierResolutionHost): boolean { + function allowsImportingAmbientModule( + moduleSymbol: Symbol, + moduleSpecifierResolutionHost: ModuleSpecifierResolutionHost, + ): boolean { if (!packageJsons.length || !moduleSymbol.valueDeclaration) { return true; } @@ -3789,19 +4223,25 @@ export function createPackageJsonImportFilter(fromFile: SourceFile, preferences: } const declaringSourceFile = moduleSymbol.valueDeclaration.getSourceFile(); - const declaringNodeModuleName = getNodeModulesPackageNameFromFileName(declaringSourceFile.fileName, moduleSpecifierResolutionHost); + const declaringNodeModuleName = getNodeModulesPackageNameFromFileName( + declaringSourceFile.fileName, + moduleSpecifierResolutionHost, + ); if (typeof declaringNodeModuleName === "undefined") { ambientModuleCache.set(moduleSymbol, true); return true; } - const result = moduleSpecifierIsCoveredByPackageJson(declaringNodeModuleName) || - moduleSpecifierIsCoveredByPackageJson(declaredModuleSpecifier); + const result = moduleSpecifierIsCoveredByPackageJson(declaringNodeModuleName) + || moduleSpecifierIsCoveredByPackageJson(declaredModuleSpecifier); ambientModuleCache.set(moduleSymbol, result); return result; } - function allowsImportingSourceFile(sourceFile: SourceFile, moduleSpecifierResolutionHost: ModuleSpecifierResolutionHost): boolean { + function allowsImportingSourceFile( + sourceFile: SourceFile, + moduleSpecifierResolutionHost: ModuleSpecifierResolutionHost, + ): boolean { if (!packageJsons.length) { return true; } @@ -3816,7 +4256,10 @@ export function createPackageJsonImportFilter(fromFile: SourceFile, preferences: } } - const moduleSpecifier = getNodeModulesPackageNameFromFileName(sourceFile.fileName, moduleSpecifierResolutionHost); + const moduleSpecifier = getNodeModulesPackageNameFromFileName( + sourceFile.fileName, + moduleSpecifierResolutionHost, + ); if (!moduleSpecifier) { sourceFileCache.set(sourceFile, true); return true; @@ -3853,7 +4296,10 @@ export function createPackageJsonImportFilter(fromFile: SourceFile, preferences: return false; } - function getNodeModulesPackageNameFromFileName(importedFileName: string, moduleSpecifierResolutionHost: ModuleSpecifierResolutionHost): string | undefined { + function getNodeModulesPackageNameFromFileName( + importedFileName: string, + moduleSpecifierResolutionHost: ModuleSpecifierResolutionHost, + ): string | undefined { if (!stringContains(importedFileName, "node_modules")) { return undefined; } @@ -3910,18 +4356,28 @@ export function isDiagnosticWithLocation(diagnostic: Diagnostic): diagnostic is } /** @internal */ -export function findDiagnosticForNode(node: Node, sortedFileDiagnostics: readonly Diagnostic[]): DiagnosticWithLocation | undefined { +export function findDiagnosticForNode( + node: Node, + sortedFileDiagnostics: readonly Diagnostic[], +): DiagnosticWithLocation | undefined { const span: Partial = createTextSpanFromNode(node); const index = binarySearchKey(sortedFileDiagnostics, span, identity, compareTextSpans); if (index >= 0) { const diagnostic = sortedFileDiagnostics[index]; - Debug.assertEqual(diagnostic.file, node.getSourceFile(), "Diagnostics proided to 'findDiagnosticForNode' must be from a single SourceFile"); + Debug.assertEqual( + diagnostic.file, + node.getSourceFile(), + "Diagnostics proided to 'findDiagnosticForNode' must be from a single SourceFile", + ); return cast(diagnostic, isDiagnosticWithLocation); } } /** @internal */ -export function getDiagnosticsWithinSpan(span: TextSpan, sortedFileDiagnostics: readonly Diagnostic[]): readonly DiagnosticWithLocation[] { +export function getDiagnosticsWithinSpan( + span: TextSpan, + sortedFileDiagnostics: readonly Diagnostic[], +): readonly DiagnosticWithLocation[] { let index = binarySearchKey(sortedFileDiagnostics, span.start, diag => diag.start, compareValues); if (index < 0) { index = ~index; @@ -3975,13 +4431,28 @@ export function getFixableErrorSpanExpression(sourceFile: SourceFile, span: Text */ export function mapOneOrMany(valueOrArray: T | readonly T[], f: (x: T, i: number) => U): U | U[]; /** @internal */ -export function mapOneOrMany(valueOrArray: T | readonly T[] | undefined, f: (x: T, i: number) => U): U | U[] | undefined; -/** @internal */ -export function mapOneOrMany(valueOrArray: T | readonly T[], f: (x: T, i: number) => U, resultSelector: (x: U[]) => U): U; -/** @internal */ -export function mapOneOrMany(valueOrArray: T | readonly T[] | undefined, f: (x: T, i: number) => U, resultSelector: (x: U[]) => U): U | undefined; -/** @internal */ -export function mapOneOrMany(valueOrArray: T | readonly T[] | undefined, f: (x: T, i: number) => U, resultSelector: (x: U[]) => U | U[] = identity): U | U[] | undefined { +export function mapOneOrMany( + valueOrArray: T | readonly T[] | undefined, + f: (x: T, i: number) => U, +): U | U[] | undefined; +/** @internal */ +export function mapOneOrMany( + valueOrArray: T | readonly T[], + f: (x: T, i: number) => U, + resultSelector: (x: U[]) => U, +): U; +/** @internal */ +export function mapOneOrMany( + valueOrArray: T | readonly T[] | undefined, + f: (x: T, i: number) => U, + resultSelector: (x: U[]) => U, +): U | undefined; +/** @internal */ +export function mapOneOrMany( + valueOrArray: T | readonly T[] | undefined, + f: (x: T, i: number) => U, + resultSelector: (x: U[]) => U | U[] = identity, +): U | U[] | undefined { return valueOrArray ? isArray(valueOrArray) ? resultSelector(map(valueOrArray, f)) : f(valueOrArray, 0) : undefined; } @@ -3995,12 +4466,23 @@ export function firstOrOnly(valueOrArray: T | readonly T[]): T { } /** @internal */ -export function getNamesForExportedSymbol(symbol: Symbol, scriptTarget: ScriptTarget | undefined): string | [lowercase: string, capitalized: string] { +export function getNamesForExportedSymbol( + symbol: Symbol, + scriptTarget: ScriptTarget | undefined, +): string | [lowercase: string, capitalized: string] { if (needsNameFromDeclaration(symbol)) { const fromDeclaration = getDefaultLikeExportNameFromDeclaration(symbol); if (fromDeclaration) return fromDeclaration; - const fileNameCase = codefix.moduleSymbolToValidIdentifier(getSymbolParentOrFail(symbol), scriptTarget, /*forceCapitalize*/ false); - const capitalized = codefix.moduleSymbolToValidIdentifier(getSymbolParentOrFail(symbol), scriptTarget, /*forceCapitalize*/ true); + const fileNameCase = codefix.moduleSymbolToValidIdentifier( + getSymbolParentOrFail(symbol), + scriptTarget, + /*forceCapitalize*/ false, + ); + const capitalized = codefix.moduleSymbolToValidIdentifier( + getSymbolParentOrFail(symbol), + scriptTarget, + /*forceCapitalize*/ true, + ); if (fileNameCase === capitalized) return fileNameCase; return [fileNameCase, capitalized]; } @@ -4008,7 +4490,11 @@ export function getNamesForExportedSymbol(symbol: Symbol, scriptTarget: ScriptTa } /** @internal */ -export function getNameForExportedSymbol(symbol: Symbol, scriptTarget: ScriptTarget | undefined, preferCapitalized?: boolean) { +export function getNameForExportedSymbol( + symbol: Symbol, + scriptTarget: ScriptTarget | undefined, + preferCapitalized?: boolean, +) { if (needsNameFromDeclaration(symbol)) { // Names for default exports: // - export default foo => foo @@ -4021,7 +4507,9 @@ export function getNameForExportedSymbol(symbol: Symbol, scriptTarget: ScriptTar } function needsNameFromDeclaration(symbol: Symbol) { - return !(symbol.flags & SymbolFlags.Transient) && (symbol.escapedName === InternalSymbolName.ExportEquals || symbol.escapedName === InternalSymbolName.Default); + return !(symbol.flags & SymbolFlags.Transient) + && (symbol.escapedName === InternalSymbolName.ExportEquals + || symbol.escapedName === InternalSymbolName.Default); } function getDefaultLikeExportNameFromDeclaration(symbol: Symbol): string | undefined { @@ -4042,13 +4530,14 @@ function getDefaultLikeExportNameFromDeclaration(symbol: Symbol): string | undef function getSymbolParentOrFail(symbol: Symbol) { return Debug.checkDefined( symbol.parent, - `Symbol parent was undefined. Flags: ${Debug.formatSymbolFlags(symbol.flags)}. ` + - `Declarations: ${ + `Symbol parent was undefined. Flags: ${Debug.formatSymbolFlags(symbol.flags)}. ` + + `Declarations: ${ symbol.declarations?.map(d => { const kind = Debug.formatSyntaxKind(d.kind); const inJS = isInJSFile(d); const { expression } = d as any; - return (inJS ? "[JS]" : "") + kind + (expression ? ` (expression: ${Debug.formatSyntaxKind(expression.kind)})` : ""); + return (inJS ? "[JS]" : "") + kind + + (expression ? ` (expression: ${Debug.formatSyntaxKind(expression.kind)})` : ""); }).join(", ") }.`, ); @@ -4103,7 +4592,8 @@ export function isNonGlobalDeclaration(declaration: Declaration) { return false; } // If the file is a module written in TypeScript, it still might be in a `declare global` augmentation - return isInJSFile(declaration) || !findAncestor(declaration, d => isModuleDeclaration(d) && isGlobalScopeAugmentation(d)); + return isInJSFile(declaration) + || !findAncestor(declaration, d => isModuleDeclaration(d) && isGlobalScopeAugmentation(d)); } /** @internal */ @@ -4140,9 +4630,14 @@ export function diagnosticToString(diag: DiagnosticOrDiagnosticAndArguments): st * * @internal */ -export function getFormatCodeSettingsForWriting({ options }: formatting.FormatContext, sourceFile: SourceFile): FormatCodeSettings { - const shouldAutoDetectSemicolonPreference = !options.semicolons || options.semicolons === SemicolonPreference.Ignore; - const shouldRemoveSemicolons = options.semicolons === SemicolonPreference.Remove || shouldAutoDetectSemicolonPreference && !probablyUsesSemicolons(sourceFile); +export function getFormatCodeSettingsForWriting( + { options }: formatting.FormatContext, + sourceFile: SourceFile, +): FormatCodeSettings { + const shouldAutoDetectSemicolonPreference = !options.semicolons + || options.semicolons === SemicolonPreference.Ignore; + const shouldRemoveSemicolons = options.semicolons === SemicolonPreference.Remove + || shouldAutoDetectSemicolonPreference && !probablyUsesSemicolons(sourceFile); return { ...options, semicolons: shouldRemoveSemicolons ? SemicolonPreference.Remove : SemicolonPreference.Ignore, @@ -4166,7 +4661,10 @@ export interface CaseClauseTracker { } /** @internal */ -export function newCaseClauseTracker(checker: TypeChecker, clauses: readonly (CaseClause | DefaultClause)[]): CaseClauseTracker { +export function newCaseClauseTracker( + checker: TypeChecker, + clauses: readonly (CaseClause | DefaultClause)[], +): CaseClauseTracker { const existingStrings = new Set(); const existingNumbers = new Set(); const existingBigInts = new Set(); @@ -4184,7 +4682,9 @@ export function newCaseClauseTracker(checker: TypeChecker, clauses: readonly (Ca existingNumbers.add(parseInt(expression.text)); break; case SyntaxKind.BigIntLiteral: - const parsedBigInt = parseBigInt(endsWith(expression.text, "n") ? expression.text.slice(0, -1) : expression.text); + const parsedBigInt = parseBigInt( + endsWith(expression.text, "n") ? expression.text.slice(0, -1) : expression.text, + ); if (parsedBigInt) { existingBigInts.add(pseudoBigIntToString(parsedBigInt)); } @@ -4231,7 +4731,12 @@ export function newCaseClauseTracker(checker: TypeChecker, clauses: readonly (Ca } /** @internal */ -export function fileShouldUseJavaScriptRequire(file: SourceFile | string, program: Program, host: LanguageServiceHost, preferRequire?: boolean) { +export function fileShouldUseJavaScriptRequire( + file: SourceFile | string, + program: Program, + host: LanguageServiceHost, + preferRequire?: boolean, +) { const fileName = typeof file === "string" ? file : file.fileName; if (!hasJSFileExtension(fileName)) { return false; @@ -4239,7 +4744,12 @@ export function fileShouldUseJavaScriptRequire(file: SourceFile | string, progra const compilerOptions = program.getCompilerOptions(); const moduleKind = getEmitModuleKind(compilerOptions); const impliedNodeFormat = typeof file === "string" - ? getImpliedNodeFormatForFile(toPath(file, host.getCurrentDirectory(), hostGetCanonicalFileName(host)), program.getPackageJsonInfoCache?.(), host, compilerOptions) + ? getImpliedNodeFormatForFile( + toPath(file, host.getCurrentDirectory(), hostGetCanonicalFileName(host)), + program.getPackageJsonInfoCache?.(), + host, + compilerOptions, + ) : file.impliedNodeFormat; if (impliedNodeFormat === ModuleKind.ESNext) { diff --git a/src/testRunner/compilerRunner.ts b/src/testRunner/compilerRunner.ts index e4479bb390133..3584eabedcccd 100644 --- a/src/testRunner/compilerRunner.ts +++ b/src/testRunner/compilerRunner.ts @@ -66,7 +66,10 @@ export class CompilerBaselineRunner extends RunnerBase { const files = this.tests.length > 0 ? this.tests : IO.enumerateTestFiles(this); files.forEach(test => { const file = typeof test === "string" ? test : test.file; - this.checkTestCodeOutput(vpath.normalizeSeparators(file), typeof test === "string" ? CompilerTest.getConfigurations(test) : test); + this.checkTestCodeOutput( + vpath.normalizeSeparators(file), + typeof test === "string" ? CompilerTest.getConfigurations(test) : test, + ); }); }); } @@ -177,7 +180,11 @@ class CompilerTest { // equivalent to other files on the file system not directly passed to the compiler (ie things that are referenced by other files) private otherFiles: Compiler.TestFile[]; - constructor(fileName: string, testCaseContent?: TestCaseParser.TestCaseContent, configurationOverrides?: TestCaseParser.CompilerSettings) { + constructor( + fileName: string, + testCaseContent?: TestCaseParser.TestCaseContent, + configurationOverrides?: TestCaseParser.CompilerSettings, + ) { const absoluteRootDir = vfs.srcFolder; this.fileName = fileName; this.justName = vpath.basename(fileName); @@ -205,7 +212,10 @@ class CompilerTest { } if (configurationOverrides) { - testCaseContent = { ...testCaseContent, settings: { ...testCaseContent.settings, ...configurationOverrides } }; + testCaseContent = { + ...testCaseContent, + settings: { ...testCaseContent.settings, ...configurationOverrides }, + }; } const units = testCaseContent.testUnitData; @@ -219,7 +229,11 @@ class CompilerTest { tsConfigOptions = ts.cloneCompilerOptions(testCaseContent.tsConfig.options); this.tsConfigFiles.push(this.createHarnessTestFile(testCaseContent.tsConfigFileUnitData!)); for (const unit of units) { - if (testCaseContent.tsConfig.fileNames.includes(ts.getNormalizedAbsolutePath(unit.name, absoluteRootDir))) { + if ( + testCaseContent.tsConfig.fileNames.includes( + ts.getNormalizedAbsolutePath(unit.name, absoluteRootDir), + ) + ) { this.toBeCompiled.push(this.createHarnessTestFile(unit)); } else { @@ -238,7 +252,10 @@ class CompilerTest { // If the last file in a test uses require or a triple slash reference we'll assume all other files will be brought in via references, // otherwise, assume all files are just meant to be in the same compilation session without explicit references to one another. - if (testCaseContent.settings.noImplicitReferences || /require\(/.test(lastUnit.content) || /reference\spath/.test(lastUnit.content)) { + if ( + testCaseContent.settings.noImplicitReferences || /require\(/.test(lastUnit.content) + || /reference\spath/.test(lastUnit.content) + ) { this.toBeCompiled.push(this.createHarnessTestFile(lastUnit)); units.forEach(unit => { if (unit.name !== lastUnit.name) { @@ -289,17 +306,21 @@ class CompilerTest { public verifyModuleResolution() { if (this.options.traceResolution) { - Baseline.runBaseline(this.configuredName.replace(/\.tsx?$/, ".trace.json"), JSON.stringify(this.result.traces.map(Utils.sanitizeTraceResolutionLogEntry), undefined, 4)); + Baseline.runBaseline( + this.configuredName.replace(/\.tsx?$/, ".trace.json"), + JSON.stringify(this.result.traces.map(Utils.sanitizeTraceResolutionLogEntry), undefined, 4), + ); } } public verifySourceMapRecord() { if (this.options.sourceMap || this.options.inlineSourceMap || this.options.declarationMap) { const record = Utils.removeTestPathPrefixes(this.result.getSourceMapRecord()!); - const baseline = (this.options.noEmitOnError && this.result.diagnostics.length !== 0) || record === undefined - // Because of the noEmitOnError option no files are created. We need to return null because baselining isn't required. - ? null // eslint-disable-line no-null/no-null - : record; + const baseline = + (this.options.noEmitOnError && this.result.diagnostics.length !== 0) || record === undefined + // Because of the noEmitOnError option no files are created. We need to return null because baselining isn't required. + ? null // eslint-disable-line no-null/no-null + : record; Baseline.runBaseline(this.configuredName.replace(/\.tsx?$/, ".sourcemap.txt"), baseline); } } @@ -333,8 +354,8 @@ class CompilerTest { return; } - const noTypesAndSymbols = this.harnessSettings.noTypesAndSymbols && - this.harnessSettings.noTypesAndSymbols.toLowerCase() === "true"; + const noTypesAndSymbols = this.harnessSettings.noTypesAndSymbols + && this.harnessSettings.noTypesAndSymbols.toLowerCase() === "true"; if (noTypesAndSymbols) { return; } @@ -343,7 +364,9 @@ class CompilerTest { this.configuredName, this.fileName, this.result.program!, - this.toBeCompiled.concat(this.otherFiles).filter(file => !!this.result.program!.getSourceFile(file.unitName)), + this.toBeCompiled.concat(this.otherFiles).filter(file => + !!this.result.program!.getSourceFile(file.unitName) + ), /*opts*/ undefined, /*multifile*/ undefined, /*skipTypeBaselines*/ undefined, diff --git a/src/testRunner/parallel/host.ts b/src/testRunner/parallel/host.ts index 126e06cff4e4a..aadc403cfeae9 100644 --- a/src/testRunner/parallel/host.ts +++ b/src/testRunner/parallel/host.ts @@ -40,7 +40,9 @@ export function start() { const { statSync } = require("fs") as typeof import("fs"); // NOTE: paths for module and types for FailedTestReporter _do not_ line up due to our use of --outFile for run.js - const FailedTestReporter = require(Utils.findUpFile("scripts/failed-tests.cjs")) as typeof import("../../../scripts/failed-tests.cjs"); + const FailedTestReporter = require( + Utils.findUpFile("scripts/failed-tests.cjs"), + ) as typeof import("../../../scripts/failed-tests.cjs"); const perfdataFileNameFragment = ".parallelperf"; const perfData = readSavedPerfData(configOption); @@ -213,7 +215,10 @@ export function start() { } function startDelayed(perfData: { [testHash: string]: number; } | undefined, totalCost: number) { - console.log(`Discovered ${tasks.length} unittest suites` + (newTasks.length ? ` and ${newTasks.length} new suites.` : ".")); + console.log( + `Discovered ${tasks.length} unittest suites` + + (newTasks.length ? ` and ${newTasks.length} new suites.` : "."), + ); console.log("Discovering runner-based tests..."); const discoverStart = +(new Date()); for (const runner of runners) { @@ -227,7 +232,8 @@ export function start() { catch { // May be a directory try { - size = IO.listFiles(path.join(runner.workingDirectory, file), /.*/g, { recursive: true }).reduce((acc, elem) => acc + statSync(elem).size, 0); + size = IO.listFiles(path.join(runner.workingDirectory, file), /.*/g, { recursive: true }) + .reduce((acc, elem) => acc + statSync(elem).size, 0); } catch { // Unknown test kind, just return 0 and let the historical analysis take over after one run @@ -276,11 +282,19 @@ export function start() { let closedWorkers = 0; for (let i = 0; i < workerCount; i++) { // TODO: Just send the config over the IPC channel or in the command line arguments - const config: TestConfig = { light: lightMode, listenForWork: true, runUnitTests, stackTraceLimit, timeout: globalTimeout }; + const config: TestConfig = { + light: lightMode, + listenForWork: true, + runUnitTests, + stackTraceLimit, + timeout: globalTimeout, + }; const configPath = ts.combinePaths(taskConfigsFolder, `task-config${i}.json`); IO.writeFile(configPath, JSON.stringify(config)); const worker: Worker = { - process: fork(process.argv[1], [`--config="${configPath}"`], { stdio: ["pipe", "pipe", "pipe", "ipc"] }), + process: fork(process.argv[1], [`--config="${configPath}"`], { + stdio: ["pipe", "pipe", "pipe", "ipc"], + }), accumulatedOutput: "", currentTasks: undefined, timer: undefined, @@ -293,7 +307,12 @@ export function start() { worker.process.stdout!.on("data", appendOutput); const killChild = (timeout: TaskTimeout) => { worker.process.kill(); - console.error(`Worker exceeded ${timeout.duration}ms timeout ${worker.currentTasks && worker.currentTasks.length ? `while running test '${worker.currentTasks[0].file}'.` : `during test setup.`}`); + console.error( + `Worker exceeded ${timeout.duration}ms timeout ${ + worker.currentTasks && worker.currentTasks.length + ? `while running test '${worker.currentTasks[0].file}'.` : `during test setup.` + }`, + ); return process.exit(2); }; worker.process.on("error", err => { @@ -311,9 +330,13 @@ export function start() { worker.process.on("message", (data: ParallelClientMessage) => { switch (data.type) { case "error": { - console.error(`Test worker encountered unexpected error${data.payload.name ? ` during the execution of test ${data.payload.name}` : ""} and was forced to close: + console.error( + `Test worker encountered unexpected error${ + data.payload.name ? ` during the execution of test ${data.payload.name}` : "" + } and was forced to close: Message: ${data.payload.error} - Stack: ${data.payload.stack}`); + Stack: ${data.payload.stack}`, + ); return process.exit(2); } case "timeout": { @@ -350,7 +373,11 @@ export function start() { while (nextProgress < progress) { nextProgress += progressUpdateInterval; } - updateProgress(progress, errorResults.length ? `${errorResults.length} failing` : `${totalPassing} passing`, errorResults.length ? "fail" : undefined); + updateProgress( + progress, + errorResults.length ? `${errorResults.length} failing` : `${totalPassing} passing`, + errorResults.length ? "fail" : undefined, + ); } if (data.type === "result") { @@ -370,7 +397,9 @@ export function start() { } worker.currentTasks = taskList; if (taskList.length === 1) { - worker.process.send({ type: "test", payload: taskList[0] } satisfies ParallelHostMessage); // TODO: GH#18217 + worker.process.send( + { type: "test", payload: taskList[0] } satisfies ParallelHostMessage, + ); // TODO: GH#18217 } else { worker.process.send({ type: "batch", payload: taskList } satisfies ParallelHostMessage); // TODO: GH#18217 @@ -385,14 +414,18 @@ export function start() { // It's only really worth doing an initial batching if there are a ton of files to go through (and they have estimates) if (totalFiles > 1000 && batchSize > 0) { console.log("Batching initial test lists..."); - const batches: { runner: TestRunnerKind | "unittest"; file: string; size: number; }[][] = new Array(batchCount); + const batches: { runner: TestRunnerKind | "unittest"; file: string; size: number; }[][] = new Array( + batchCount, + ); const doneBatching = new Array(batchCount); let scheduledTotal = 0; batcher: while (true) { for (let i = 0; i < batchCount; i++) { if (tasks.length <= workerCount) { // Keep a small reserve even in the suboptimally packed case - console.log(`Suboptimal packing detected: no tests remain to be stolen. Reduce packing fraction from ${packfraction} to fix.`); + console.log( + `Suboptimal packing detected: no tests remain to be stolen. Reduce packing fraction from ${packfraction} to fix.`, + ); break batcher; } if (doneBatching[i]) { @@ -422,7 +455,11 @@ export function start() { console.log(`${prefix}. Unprofiled tests including ${unknownValue} will be run first.`); } else { - console.log(`${prefix} with approximate total ${perfData ? "time" : "file sizes"} of ${perfData ? ms(batchSize) : `${Math.floor(batchSize)} bytes`} in each group. (${(scheduledTotal / totalCost * 100).toFixed(1)}% of total tests batched)`); + console.log( + `${prefix} with approximate total ${perfData ? "time" : "file sizes"} of ${ + perfData ? ms(batchSize) : `${Math.floor(batchSize)} bytes` + } in each group. (${(scheduledTotal / totalCost * 100).toFixed(1)}% of total tests batched)`, + ); } for (const worker of workers) { const payload = batches.pop(); @@ -456,12 +493,15 @@ export function start() { const summaryColor = isPartitionFail ? "fail" : "green"; const summarySymbol = isPartitionFail ? Base.symbols.err : Base.symbols.ok; - const summaryTests = (isPartitionFail ? totalPassing + "/" + (errorResults.length + totalPassing) : totalPassing) + " passing"; + const summaryTests = + (isPartitionFail ? totalPassing + "/" + (errorResults.length + totalPassing) : totalPassing) + + " passing"; const summaryDuration = "(" + ms(duration) + ")"; const savedUseColors = Base.useColors; Base.useColors = !noColors; - const summary = color(summaryColor, summarySymbol + " " + summaryTests) + " " + color("light", summaryDuration); + const summary = color(summaryColor, summarySymbol + " " + summaryTests) + " " + + color("light", summaryDuration); Base.useColors = savedUseColors; updateProgress(1, summary); @@ -546,7 +586,11 @@ export function start() { function replayTest(runner: Mocha.Runner, test: RemoteTest) { runner.emit("test", test); if (test.isFailed()) { - runner.emit("fail", test, "error" in test.info ? rebuildError(test.info) : new Error("Unknown error")); // eslint-disable-line local/no-in-operator + runner.emit( + "fail", + test, + "error" in test.info ? rebuildError(test.info) : new Error("Unknown error"), + ); // eslint-disable-line local/no-in-operator } else { runner.emit("pass", test); diff --git a/src/testRunner/parallel/shared.ts b/src/testRunner/parallel/shared.ts index 880f92f0c8e61..7d673ca5205d7 100644 --- a/src/testRunner/parallel/shared.ts +++ b/src/testRunner/parallel/shared.ts @@ -75,7 +75,11 @@ export interface ParallelTimeoutChangeMessage { payload: TaskTimeout; } -export type ParallelClientMessage = ParallelErrorMessage | ParallelResultMessage | ParallelBatchProgressMessage | ParallelTimeoutChangeMessage; +export type ParallelClientMessage = + | ParallelErrorMessage + | ParallelResultMessage + | ParallelBatchProgressMessage + | ParallelTimeoutChangeMessage; export function shimNoopTestInterface(global: Mocha.MochaGlobals) { global.before = ts.noop; diff --git a/src/testRunner/parallel/worker.ts b/src/testRunner/parallel/worker.ts index 3637721240732..9916b061f093c 100644 --- a/src/testRunner/parallel/worker.ts +++ b/src/testRunner/parallel/worker.ts @@ -115,16 +115,28 @@ export function start() { */ function shimTestInterface(rootSuite: Mocha.Suite, context: Mocha.MochaGlobals) { const suites = [rootSuite]; - context.before = (title: string | Mocha.Func | Mocha.AsyncFunc, fn?: Mocha.Func | Mocha.AsyncFunc) => suites[0].beforeAll(title as string, fn); - context.after = (title: string | Mocha.Func | Mocha.AsyncFunc, fn?: Mocha.Func | Mocha.AsyncFunc) => suites[0].afterAll(title as string, fn); - context.beforeEach = (title: string | Mocha.Func | Mocha.AsyncFunc, fn?: Mocha.Func | Mocha.AsyncFunc) => suites[0].beforeEach(title as string, fn); - context.afterEach = (title: string | Mocha.Func | Mocha.AsyncFunc, fn?: Mocha.Func | Mocha.AsyncFunc) => suites[0].afterEach(title as string, fn); - context.describe = context.context = ((title: string, fn: (this: Mocha.Suite) => void) => addSuite(title, fn)) as Mocha.SuiteFunction; - context.describe.skip = context.xdescribe = context.xcontext = (title: string) => addSuite(title, /*fn*/ undefined); + context.before = (title: string | Mocha.Func | Mocha.AsyncFunc, fn?: Mocha.Func | Mocha.AsyncFunc) => + suites[0].beforeAll(title as string, fn); + context.after = (title: string | Mocha.Func | Mocha.AsyncFunc, fn?: Mocha.Func | Mocha.AsyncFunc) => + suites[0].afterAll(title as string, fn); + context.beforeEach = (title: string | Mocha.Func | Mocha.AsyncFunc, fn?: Mocha.Func | Mocha.AsyncFunc) => + suites[0].beforeEach(title as string, fn); + context.afterEach = (title: string | Mocha.Func | Mocha.AsyncFunc, fn?: Mocha.Func | Mocha.AsyncFunc) => + suites[0].afterEach(title as string, fn); + context.describe = + context.context = + ((title: string, fn: (this: Mocha.Suite) => void) => addSuite(title, fn)) as Mocha.SuiteFunction; + context.describe.skip = context.xdescribe = context.xcontext = (title: string) => + addSuite(title, /*fn*/ undefined); context.describe.only = (title: string, fn?: (this: Mocha.Suite) => void) => addSuite(title, fn); - context.it = context.specify = ((title: string | Mocha.Func | Mocha.AsyncFunc, fn?: Mocha.Func | Mocha.AsyncFunc) => addTest(title, fn)) as Mocha.TestFunction; - context.it.skip = context.xit = context.xspecify = (title: string | Mocha.Func | Mocha.AsyncFunc) => addTest(typeof title === "function" ? title.name : title, /*fn*/ undefined); - context.it.only = (title: string | Mocha.Func | Mocha.AsyncFunc, fn?: Mocha.Func | Mocha.AsyncFunc) => addTest(title, fn); + context.it = + context.specify = + ((title: string | Mocha.Func | Mocha.AsyncFunc, fn?: Mocha.Func | Mocha.AsyncFunc) => + addTest(title, fn)) as Mocha.TestFunction; + context.it.skip = context.xit = context.xspecify = (title: string | Mocha.Func | Mocha.AsyncFunc) => + addTest(typeof title === "function" ? title.name : title, /*fn*/ undefined); + context.it.only = (title: string | Mocha.Func | Mocha.AsyncFunc, fn?: Mocha.Func | Mocha.AsyncFunc) => + addTest(title, fn); function addSuite(title: string, fn: ((this: Mocha.Suite) => void) | undefined): Mocha.Suite { const suite = new Suite(title, suites[0].ctx); @@ -138,7 +150,10 @@ export function start() { return suite; } - function addTest(title: string | Mocha.Func | Mocha.AsyncFunc, fn: Mocha.Func | Mocha.AsyncFunc | undefined): Mocha.Test { + function addTest( + title: string | Mocha.Func | Mocha.AsyncFunc, + fn: Mocha.Func | Mocha.AsyncFunc | undefined, + ): Mocha.Test { if (typeof title === "function") { fn = title; title = fn.name; diff --git a/src/testRunner/projectsRunner.ts b/src/testRunner/projectsRunner.ts index dd2a2f40f6ead..a84c2501ec940 100644 --- a/src/testRunner/projectsRunner.ts +++ b/src/testRunner/projectsRunner.ts @@ -61,21 +61,29 @@ export class ProjectRunner extends Harness.RunnerBase { private runProjectTestCase(testCaseFileName: string) { for (const { name, payload } of ProjectTestCase.getConfigurations(testCaseFileName)) { - describe("Compiling project for " + payload.testCase.scenario + ": testcase " + testCaseFileName + (name ? ` (${name})` : ``), () => { - let projectTestCase: ProjectTestCase | undefined; - before(() => { - projectTestCase = new ProjectTestCase(testCaseFileName, payload); - }); - it(`Correct module resolution tracing for ${testCaseFileName}`, () => projectTestCase && projectTestCase.verifyResolution()); - it(`Correct errors for ${testCaseFileName}`, () => projectTestCase && projectTestCase.verifyDiagnostics()); - it(`Correct JS output for ${testCaseFileName}`, () => projectTestCase && projectTestCase.verifyJavaScriptOutput()); - // NOTE: This check was commented out in previous code. Leaving this here to eventually be restored if needed. - // it(`Correct sourcemap content for ${testCaseFileName}`, () => projectTestCase && projectTestCase.verifySourceMapRecord()); - it(`Correct declarations for ${testCaseFileName}`, () => projectTestCase && projectTestCase.verifyDeclarations()); - after(() => { - projectTestCase = undefined; - }); - }); + describe( + "Compiling project for " + payload.testCase.scenario + ": testcase " + testCaseFileName + + (name ? ` (${name})` : ``), + () => { + let projectTestCase: ProjectTestCase | undefined; + before(() => { + projectTestCase = new ProjectTestCase(testCaseFileName, payload); + }); + it(`Correct module resolution tracing for ${testCaseFileName}`, () => + projectTestCase && projectTestCase.verifyResolution()); + it(`Correct errors for ${testCaseFileName}`, () => + projectTestCase && projectTestCase.verifyDiagnostics()); + it(`Correct JS output for ${testCaseFileName}`, () => + projectTestCase && projectTestCase.verifyJavaScriptOutput()); + // NOTE: This check was commented out in previous code. Leaving this here to eventually be restored if needed. + // it(`Correct sourcemap content for ${testCaseFileName}`, () => projectTestCase && projectTestCase.verifySourceMapRecord()); + it(`Correct declarations for ${testCaseFileName}`, () => + projectTestCase && projectTestCase.verifyDeclarations()); + after(() => { + projectTestCase = undefined; + }); + }, + ); } } } @@ -84,13 +92,20 @@ class ProjectCompilerHost extends fakes.CompilerHost { private _testCase: ProjectRunnerTestCase & ts.CompilerOptions; private _projectParseConfigHost: ProjectParseConfigHost | undefined; - constructor(sys: fakes.System | vfs.FileSystem, compilerOptions: ts.CompilerOptions, _testCaseJustName: string, testCase: ProjectRunnerTestCase & ts.CompilerOptions, _moduleKind: ts.ModuleKind) { + constructor( + sys: fakes.System | vfs.FileSystem, + compilerOptions: ts.CompilerOptions, + _testCaseJustName: string, + testCase: ProjectRunnerTestCase & ts.CompilerOptions, + _moduleKind: ts.ModuleKind, + ) { super(sys, compilerOptions); this._testCase = testCase; } public override get parseConfigHost(): fakes.ParseConfigHost { - return this._projectParseConfigHost || (this._projectParseConfigHost = new ProjectParseConfigHost(this.sys, this._testCase)); + return this._projectParseConfigHost + || (this._projectParseConfigHost = new ProjectParseConfigHost(this.sys, this._testCase)); } public override getDefaultLibFileName(_options: ts.CompilerOptions) { @@ -106,7 +121,13 @@ class ProjectParseConfigHost extends fakes.ParseConfigHost { this._testCase = testCase; } - public override readDirectory(path: string, extensions: string[], excludes: string[], includes: string[], depth: number): string[] { + public override readDirectory( + path: string, + extensions: string[], + excludes: string[], + includes: string[], + depth: number, + ): string[] { const result = super.readDirectory(path, extensions, excludes, includes, depth); const projectRoot = vpath.resolve(vfs.srcFolder, this._testCase.projectRoot); return result.map(item => @@ -160,14 +181,31 @@ class ProjectTestCase { const result = ts.readJsonConfigFile(configFileName, path => this.sys.readFile(path)); configFileSourceFiles.push(result); const configParseHost = new ProjectParseConfigHost(this.sys, this.testCase); - const configParseResult = ts.parseJsonSourceFileConfigFileContent(result, configParseHost, ts.getDirectoryPath(configFileName), this.compilerOptions); + const configParseResult = ts.parseJsonSourceFileConfigFileContent( + result, + configParseHost, + ts.getDirectoryPath(configFileName), + this.compilerOptions, + ); inputFiles = configParseResult.fileNames; this.compilerOptions = configParseResult.options; errors = [...result.parseDiagnostics, ...configParseResult.errors]; } - const compilerHost = new ProjectCompilerHost(this.sys, this.compilerOptions, this.testCaseJustName, this.testCase, moduleKind); - const projectCompilerResult = this.compileProjectFiles(moduleKind, configFileSourceFiles, () => inputFiles, compilerHost, this.compilerOptions); + const compilerHost = new ProjectCompilerHost( + this.sys, + this.compilerOptions, + this.testCaseJustName, + this.testCase, + moduleKind, + ); + const projectCompilerResult = this.compileProjectFiles( + moduleKind, + configFileSourceFiles, + () => inputFiles, + compilerHost, + this.compilerOptions, + ); this.compilerResult = { configFileSourceFiles, @@ -203,7 +241,11 @@ class ProjectTestCase { } const fs = vfs.createFromFileSystem(Harness.IO, /*ignoreCase*/ false); - fs.mountSync(vpath.resolve(Harness.IO.getWorkspaceRoot(), "tests"), vpath.combine(vfs.srcFolder, "tests"), vfs.createResolver(Harness.IO)); + fs.mountSync( + vpath.resolve(Harness.IO.getWorkspaceRoot(), "tests"), + vpath.combine(vfs.srcFolder, "tests"), + vfs.createResolver(Harness.IO), + ); fs.mkdirpSync(vpath.combine(vfs.srcFolder, testCase.projectRoot)); fs.chdir(vpath.combine(vfs.srcFolder, testCase.projectRoot)); fs.makeReadonly(); @@ -217,25 +259,39 @@ class ProjectTestCase { public verifyResolution() { const cwd = this.vfs.cwd(); const ignoreCase = this.vfs.ignoreCase; - const resolutionInfo: ProjectRunnerTestCaseResolutionInfo & ts.CompilerOptions = JSON.parse(JSON.stringify(this.testCase)); + const resolutionInfo: ProjectRunnerTestCaseResolutionInfo & ts.CompilerOptions = JSON.parse( + JSON.stringify(this.testCase), + ); resolutionInfo.resolvedInputFiles = this.compilerResult.program!.getSourceFiles() .map(({ fileName: input }) => - vpath.beneath(vfs.builtFolder, input, this.vfs.ignoreCase) || vpath.beneath(vfs.testLibFolder, input, this.vfs.ignoreCase) ? Utils.removeTestPathPrefixes(input) : - vpath.isAbsolute(input) ? vpath.relative(cwd, input, ignoreCase) : - input + vpath.beneath(vfs.builtFolder, input, this.vfs.ignoreCase) + || vpath.beneath(vfs.testLibFolder, input, this.vfs.ignoreCase) + ? Utils.removeTestPathPrefixes(input) + : vpath.isAbsolute(input) ? vpath.relative(cwd, input, ignoreCase) + : input ); resolutionInfo.emittedFiles = this.compilerResult.outputFiles! .map(output => output.meta.get("fileName") || output.file) - .map(output => Utils.removeTestPathPrefixes(vpath.isAbsolute(output) ? vpath.relative(cwd, output, ignoreCase) : output)); + .map(output => + Utils.removeTestPathPrefixes( + vpath.isAbsolute(output) ? vpath.relative(cwd, output, ignoreCase) : output, + ) + ); const content = JSON.stringify(resolutionInfo, undefined, " "); - Harness.Baseline.runBaseline(this.getBaselineFolder(this.compilerResult.moduleKind) + this.testCaseJustName + ".json", content); + Harness.Baseline.runBaseline( + this.getBaselineFolder(this.compilerResult.moduleKind) + this.testCaseJustName + ".json", + content, + ); } public verifyDiagnostics() { if (this.compilerResult.errors.length) { - Harness.Baseline.runBaseline(this.getBaselineFolder(this.compilerResult.moduleKind) + this.testCaseJustName + ".errors.txt", getErrorsBaseline(this.compilerResult)); + Harness.Baseline.runBaseline( + this.getBaselineFolder(this.compilerResult.moduleKind) + this.testCaseJustName + ".errors.txt", + getErrorsBaseline(this.compilerResult), + ); } } @@ -248,7 +304,8 @@ class ProjectTestCase { // convert file name to rooted name // if filename is not rooted - concat it with project root and then expand project root relative to current directory const fileName = output.meta.get("fileName") || output.file; - const diskFileName = vpath.isAbsolute(fileName) ? fileName : vpath.resolve(this.vfs.cwd(), fileName); + const diskFileName = vpath.isAbsolute(fileName) ? fileName + : vpath.resolve(this.vfs.cwd(), fileName); // compute file name relative to current directory (expanded project root) let diskRelativeName = vpath.relative(this.vfs.cwd(), diskFileName, this.vfs.ignoreCase); @@ -256,12 +313,20 @@ class ProjectTestCase { // If the generated output file resides in the parent folder or is rooted path, // we need to instead create files that can live in the project reference folder // but make sure extension of these files matches with the fileName the compiler asked to write - diskRelativeName = `diskFile${nonSubfolderDiskFiles}${vpath.extname(fileName, [".js.map", ".js", ".d.ts"], this.vfs.ignoreCase)}`; + diskRelativeName = `diskFile${nonSubfolderDiskFiles}${ + vpath.extname(fileName, [".js.map", ".js", ".d.ts"], this.vfs.ignoreCase) + }`; nonSubfolderDiskFiles++; } - const content = Utils.removeTestPathPrefixes(output.text, /*retainTrailingDirectorySeparator*/ true); - Harness.Baseline.runBaseline(this.getBaselineFolder(this.compilerResult.moduleKind) + diskRelativeName, content as string | null); // TODO: GH#18217 + const content = Utils.removeTestPathPrefixes( + output.text, + /*retainTrailingDirectorySeparator*/ true, + ); + Harness.Baseline.runBaseline( + this.getBaselineFolder(this.compilerResult.moduleKind) + diskRelativeName, + content as string | null, + ); // TODO: GH#18217 } catch (e) { errs.push(e); @@ -288,7 +353,10 @@ class ProjectTestCase { if (!this.compilerResult.errors.length && this.testCase.declaration) { const dTsCompileResult = this.compileDeclarations(this.compilerResult); if (dTsCompileResult && dTsCompileResult.errors.length) { - Harness.Baseline.runBaseline(this.getBaselineFolder(this.compilerResult.moduleKind) + this.testCaseJustName + ".dts.errors.txt", getErrorsBaseline(dTsCompileResult)); + Harness.Baseline.runBaseline( + this.getBaselineFolder(this.compilerResult.moduleKind) + this.testCaseJustName + ".dts.errors.txt", + getErrorsBaseline(dTsCompileResult), + ); } } } @@ -321,7 +389,13 @@ class ProjectTestCase { return url; } - private compileProjectFiles(moduleKind: ts.ModuleKind, configFileSourceFiles: readonly ts.SourceFile[], getInputFiles: () => readonly string[], compilerHost: ts.CompilerHost, compilerOptions: ts.CompilerOptions): CompileProjectFilesResult { + private compileProjectFiles( + moduleKind: ts.ModuleKind, + configFileSourceFiles: readonly ts.SourceFile[], + getInputFiles: () => readonly string[], + compilerHost: ts.CompilerHost, + compilerOptions: ts.CompilerOptions, + ): CompileProjectFilesResult { const program = ts.createProgram(getInputFiles(), compilerOptions, compilerHost); const errors = ts.getPreEmitDiagnostics(program); @@ -365,9 +439,14 @@ class ProjectTestCase { else if (!(compilerOptions.outFile || compilerOptions.out)) { let emitOutputFilePathWithoutExtension: string | undefined; if (compilerOptions.outDir) { - let sourceFilePath = ts.getNormalizedAbsolutePath(sourceFile.fileName, compilerResult.program!.getCurrentDirectory()); + let sourceFilePath = ts.getNormalizedAbsolutePath( + sourceFile.fileName, + compilerResult.program!.getCurrentDirectory(), + ); sourceFilePath = sourceFilePath.replace(compilerResult.program!.getCommonSourceDirectory(), ""); - emitOutputFilePathWithoutExtension = ts.removeFileExtension(ts.combinePaths(compilerOptions.outDir, sourceFilePath)); + emitOutputFilePathWithoutExtension = ts.removeFileExtension( + ts.combinePaths(compilerOptions.outDir, sourceFilePath), + ); } else { emitOutputFilePathWithoutExtension = ts.removeFileExtension(sourceFile.fileName); @@ -381,7 +460,8 @@ class ProjectTestCase { } } else { - const outputDtsFileName = ts.removeFileExtension(compilerOptions.outFile || compilerOptions.out!) + ts.Extension.Dts; + const outputDtsFileName = ts.removeFileExtension(compilerOptions.outFile || compilerOptions.out!) + + ts.Extension.Dts; const outputDtsFile = findOutputDtsFile(outputDtsFileName)!; if (!ts.contains(allInputFiles, outputDtsFile)) { allInputFiles.unshift(outputDtsFile); @@ -396,18 +476,33 @@ class ProjectTestCase { }); // Dont allow config files since we are compiling existing source options - const compilerHost = new ProjectCompilerHost(_vfs, compilerResult.compilerOptions!, this.testCaseJustName, this.testCase, compilerResult.moduleKind); - return this.compileProjectFiles(compilerResult.moduleKind, compilerResult.configFileSourceFiles, () => rootFiles, compilerHost, compilerResult.compilerOptions!); + const compilerHost = new ProjectCompilerHost( + _vfs, + compilerResult.compilerOptions!, + this.testCaseJustName, + this.testCase, + compilerResult.moduleKind, + ); + return this.compileProjectFiles( + compilerResult.moduleKind, + compilerResult.configFileSourceFiles, + () => rootFiles, + compilerHost, + compilerResult.compilerOptions!, + ); function findOutputDtsFile(fileName: string) { - return ts.forEach(compilerResult.outputFiles, outputFile => outputFile.meta.get("fileName") === fileName ? outputFile : undefined); + return ts.forEach( + compilerResult.outputFiles, + outputFile => outputFile.meta.get("fileName") === fileName ? outputFile : undefined, + ); } } } function moduleNameToString(moduleKind: ts.ModuleKind) { - return moduleKind === ts.ModuleKind.AMD ? "amd" : - moduleKind === ts.ModuleKind.CommonJS ? "node" : "none"; + return moduleKind === ts.ModuleKind.AMD ? "amd" + : moduleKind === ts.ModuleKind.CommonJS ? "node" : "none"; } function getErrorsBaseline(compilerResult: CompileProjectFilesResult) { @@ -421,9 +516,9 @@ function getErrorsBaseline(compilerResult: CompileProjectFilesResult) { } const inputFiles = inputSourceFiles.map(sourceFile => ({ - unitName: ts.isRootedDiskPath(sourceFile.fileName) ? - Harness.RunnerBase.removeFullPaths(sourceFile.fileName) : - sourceFile.fileName, + unitName: ts.isRootedDiskPath(sourceFile.fileName) + ? Harness.RunnerBase.removeFullPaths(sourceFile.fileName) + : sourceFile.fileName, content: sourceFile.text, })); diff --git a/src/testRunner/unittests/asserts.ts b/src/testRunner/unittests/asserts.ts index 0656156e852c0..9b38fb4302e98 100644 --- a/src/testRunner/unittests/asserts.ts +++ b/src/testRunner/unittests/asserts.ts @@ -2,9 +2,22 @@ import * as ts from "../_namespaces/ts"; describe("unittests:: assert", () => { it("deepEqual", () => { - assert.throws(() => assert.deepEqual(ts.factory.createNodeArray([ts.factory.createIdentifier("A")]), ts.factory.createNodeArray([ts.factory.createIdentifier("B")]))); - assert.throws(() => assert.deepEqual(ts.factory.createNodeArray([], /*hasTrailingComma*/ true), ts.factory.createNodeArray([], /*hasTrailingComma*/ false))); - assert.deepEqual(ts.factory.createNodeArray([ts.factory.createIdentifier("A")], /*hasTrailingComma*/ true), ts.factory.createNodeArray([ts.factory.createIdentifier("A")], /*hasTrailingComma*/ true)); + assert.throws(() => + assert.deepEqual( + ts.factory.createNodeArray([ts.factory.createIdentifier("A")]), + ts.factory.createNodeArray([ts.factory.createIdentifier("B")]), + ) + ); + assert.throws(() => + assert.deepEqual( + ts.factory.createNodeArray([], /*hasTrailingComma*/ true), + ts.factory.createNodeArray([], /*hasTrailingComma*/ false), + ) + ); + assert.deepEqual( + ts.factory.createNodeArray([ts.factory.createIdentifier("A")], /*hasTrailingComma*/ true), + ts.factory.createNodeArray([ts.factory.createIdentifier("A")], /*hasTrailingComma*/ true), + ); }); it("assertNever on string has correct error", () => { assert.throws(() => ts.Debug.assertNever("hi" as never), 'Debug Failure. Illegal value: "hi"'); diff --git a/src/testRunner/unittests/builder.ts b/src/testRunner/unittests/builder.ts index 65ad35bfd6c6c..79fee960eb820 100644 --- a/src/testRunner/unittests/builder.ts +++ b/src/testRunner/unittests/builder.ts @@ -94,7 +94,9 @@ function makeAssertChanges(getProgram: () => ts.Program): (fileNames: readonly s }; } -function makeAssertChangesWithCancellationToken(getProgram: () => ts.Program): (fileNames: readonly string[], cancelAfterEmitLength?: number) => void { +function makeAssertChangesWithCancellationToken( + getProgram: () => ts.Program, +): (fileNames: readonly string[], cancelAfterEmitLength?: number) => void { const host: ts.BuilderProgramHost = {}; let builderProgram: ts.EmitAndSemanticDiagnosticsBuilderProgram | undefined; let cancel = false; @@ -132,7 +134,11 @@ function makeAssertChangesWithCancellationToken(getProgram: () => ts.Program): ( }; } -function updateProgramFile(program: ProgramWithSourceTexts, fileName: string, fileContent: string): ProgramWithSourceTexts { +function updateProgramFile( + program: ProgramWithSourceTexts, + fileName: string, + fileContent: string, +): ProgramWithSourceTexts { return updateProgram(program, program.getRootFileNames(), program.getCompilerOptions(), files => { updateProgramText(files, fileName, fileContent); }); diff --git a/src/testRunner/unittests/canWatch.ts b/src/testRunner/unittests/canWatch.ts index 1c0738e7aec94..b4a1706ef8ed6 100644 --- a/src/testRunner/unittests/canWatch.ts +++ b/src/testRunner/unittests/canWatch.ts @@ -22,7 +22,8 @@ describe("unittests:: canWatch::", () => { baselineCanWatch( "canWatchAtTypes", - () => `Determines if given node_modules/@types can be watched.\r\nThese are the typeRoots calculated because user didnt specify typeRoots in compierOptions`, + () => + `Determines if given node_modules/@types can be watched.\r\nThese are the typeRoots calculated because user didnt specify typeRoots in compierOptions`, (paths, longestPathLength, baseline) => { const testType = "canWatchAtTypes"; const maxLengths = [longestPathLength + "/node_modules/@types".length, testType.length] as const; @@ -37,7 +38,8 @@ describe("unittests:: canWatch::", () => { baselineCanWatch( "canWatchAffectingLocation", - () => `Determines if package.json that was found during module resolution and change in it will affect resolution can be watched.`, + () => + `Determines if package.json that was found during module resolution and change in it will affect resolution can be watched.`, (paths, longestPathLength, baseline) => { const testType = "canWatchAffectingLocation"; const maxLengths = [longestPathLength + "/package.json".length, testType.length] as const; @@ -59,20 +61,45 @@ describe("unittests:: canWatch::", () => { ) { baselineCanWatch( scenario, - () => `Determines whether to watch given failed lookup location (file that didnt exist) when resolving module.\r\nIt also determines the directory to watch and whether to watch it recursively or not.`, + () => + `Determines whether to watch given failed lookup location (file that didnt exist) when resolving module.\r\nIt also determines the directory to watch and whether to watch it recursively or not.`, (paths, longestPathLength, baseline) => { const recursive = "Recursive"; const maxLength = longestPathLength + ts.combinePaths(forPath, "dir/subdir/somefile.d.ts").length; const maxLengths = [maxLength, maxLength, recursive.length] as const; baselineCanWatchForRoot(paths, baseline, (rootPathCompoments, root) => { - pushHeader(baseline, ["Location", "getDirectoryToWatchFailedLookupLocation", recursive], maxLengths); + pushHeader( + baseline, + ["Location", "getDirectoryToWatchFailedLookupLocation", recursive], + maxLengths, + ); paths.forEach(path => { - baselineGetDirectoryToWatchFailedLookupLocation(combinePaths(path, forPath, "somefile.d.ts"), root, rootPathCompoments, maxLengths); - baselineGetDirectoryToWatchFailedLookupLocation(combinePaths(path, forPath, "dir/somefile.d.ts"), root, rootPathCompoments, maxLengths); - baselineGetDirectoryToWatchFailedLookupLocation(combinePaths(path, forPath, "dir/subdir/somefile.d.ts"), root, rootPathCompoments, maxLengths); + baselineGetDirectoryToWatchFailedLookupLocation( + combinePaths(path, forPath, "somefile.d.ts"), + root, + rootPathCompoments, + maxLengths, + ); + baselineGetDirectoryToWatchFailedLookupLocation( + combinePaths(path, forPath, "dir/somefile.d.ts"), + root, + rootPathCompoments, + maxLengths, + ); + baselineGetDirectoryToWatchFailedLookupLocation( + combinePaths(path, forPath, "dir/subdir/somefile.d.ts"), + root, + rootPathCompoments, + maxLengths, + ); }); }); - function baselineGetDirectoryToWatchFailedLookupLocation(path: ts.Path, root: ts.Path, rootPathCompoments: Readonly, maxLengths: readonly number[]) { + function baselineGetDirectoryToWatchFailedLookupLocation( + path: ts.Path, + root: ts.Path, + rootPathCompoments: Readonly, + maxLengths: readonly number[], + ) { const result = ts.getDirectoryToWatchFailedLookupLocation( path, path, @@ -81,7 +108,11 @@ describe("unittests:: canWatch::", () => { rootPathCompoments, ts.returnUndefined, ); - pushRow(baseline, [path, result ? result.dir : "", result ? `${!result.nonRecursive}` : ""], maxLengths); + pushRow( + baseline, + [path, result ? result.dir : "", result ? `${!result.nonRecursive}` : ""], + maxLengths, + ); } }, ); @@ -89,7 +120,8 @@ describe("unittests:: canWatch::", () => { baselineCanWatch( "getDirectoryToWatchFailedLookupLocationFromTypeRoot", - () => `When watched typeRoot handler is invoked, this method determines the directory for which the failedLookupLocation would need to be invalidated.\r\nSince this is invoked only when watching default typeRoot and is used to handle flaky directory watchers, this is used as a fail safe where if failed lookup starts with returned directory we will invalidate that resolution.`, + () => + `When watched typeRoot handler is invoked, this method determines the directory for which the failedLookupLocation would need to be invalidated.\r\nSince this is invoked only when watching default typeRoot and is used to handle flaky directory watchers, this is used as a fail safe where if failed lookup starts with returned directory we will invalidate that resolution.`, (paths, longestPathLength, baseline) => { const maxLength = longestPathLength + "/node_modules/@types".length; const maxLengths = [maxLength, maxLength] as const; @@ -113,7 +145,11 @@ describe("unittests:: canWatch::", () => { }, ); - function baselineCanWatchForRoot(paths: readonly ts.Path[], baseline: string[], baselineForRoot: (rootPathCompoments: Readonly, root: ts.Path) => void) { + function baselineCanWatchForRoot( + paths: readonly ts.Path[], + baseline: string[], + baselineForRoot: (rootPathCompoments: Readonly, root: ts.Path) => void, + ) { paths.forEach(rootDirForResolution => { const root = ts.getRootDirectoryOfResolutionCache(rootDirForResolution, ts.returnUndefined) as ts.Path; assert(root === rootDirForResolution); diff --git a/src/testRunner/unittests/config/commandLineParsing.ts b/src/testRunner/unittests/config/commandLineParsing.ts index cb40ec6527ac4..b6fa0fc6110e6 100644 --- a/src/testRunner/unittests/config/commandLineParsing.ts +++ b/src/testRunner/unittests/config/commandLineParsing.ts @@ -2,11 +2,18 @@ import * as Harness from "../../_namespaces/Harness"; import * as ts from "../../_namespaces/ts"; describe("unittests:: config:: commandLineParsing:: parseCommandLine", () => { - function assertParseResult(subScenario: string, commandLine: string[], workerDiagnostic?: () => ts.ParseCommandLineWorkerDiagnostics) { + function assertParseResult( + subScenario: string, + commandLine: string[], + workerDiagnostic?: () => ts.ParseCommandLineWorkerDiagnostics, + ) { it(subScenario, () => { const baseline: string[] = []; baseline.push(commandLine.join(" ")); - const parsed = ts.parseCommandLineWorker(workerDiagnostic?.() || ts.compilerOptionsDidYouMeanDiagnostics, commandLine); + const parsed = ts.parseCommandLineWorker( + workerDiagnostic?.() || ts.compilerOptionsDidYouMeanDiagnostics, + commandLine, + ); baseline.push("CompilerOptions::"); baseline.push(JSON.stringify(parsed.options, /*replacer*/ undefined, " ")); baseline.push("WatchOptions::"); @@ -19,7 +26,10 @@ describe("unittests:: config:: commandLineParsing:: parseCommandLine", () => { getCanonicalFileName: ts.identity, getNewLine: () => "\n", })); - Harness.Baseline.runBaseline(`config/commandLineParsing/parseCommandLine/${subScenario}.js`, baseline.join("\n")); + Harness.Baseline.runBaseline( + `config/commandLineParsing/parseCommandLine/${subScenario}.js`, + baseline.join("\n"), + ); }); } @@ -54,11 +64,35 @@ describe("unittests:: config:: commandLineParsing:: parseCommandLine", () => { // --lib es5, es7 0.ts assertParseResult("Parse --lib option with trailing white-space", ["--lib", "es5, ", "es7", "0.ts"]); // --lib es5,es2015.symbol.wellknown --target es5 0.ts - assertParseResult("Parse multiple compiler flags with input files at the end", ["--lib", "es5,es2015.symbol.wellknown", "--target", "es5", "0.ts"]); + assertParseResult("Parse multiple compiler flags with input files at the end", [ + "--lib", + "es5,es2015.symbol.wellknown", + "--target", + "es5", + "0.ts", + ]); // --module commonjs --target es5 0.ts --lib es5,es2015.symbol.wellknown - assertParseResult("Parse multiple compiler flags with input files in the middle", ["--module", "commonjs", "--target", "es5", "0.ts", "--lib", "es5,es2015.symbol.wellknown"]); + assertParseResult("Parse multiple compiler flags with input files in the middle", [ + "--module", + "commonjs", + "--target", + "es5", + "0.ts", + "--lib", + "es5,es2015.symbol.wellknown", + ]); // --module commonjs --target es5 --lib es5 0.ts --library es2015.array,es2015.symbol.wellknown - assertParseResult("Parse multiple library compiler flags ", ["--module", "commonjs", "--target", "es5", "--lib", "es5", "0.ts", "--lib", "es2015.core, es2015.symbol.wellknown "]); + assertParseResult("Parse multiple library compiler flags ", [ + "--module", + "commonjs", + "--target", + "es5", + "--lib", + "es5", + "0.ts", + "--lib", + "es2015.core, es2015.symbol.wellknown ", + ]); assertParseResult("Parse explicit boolean flag value", ["--strictNullChecks", "false", "0.ts"]); assertParseResult("Parse non boolean argument after boolean flag", ["--noImplicitAny", "t", "0.ts"]); assertParseResult("Parse implicit boolean flag value", ["--strictNullChecks"]); @@ -178,7 +212,13 @@ describe("unittests:: config:: commandLineParsing:: parseCommandLine", () => { }); }); - assertParseResult("allows tsconfig only option to be set to null", ["--composite", "null", "-tsBuildInfoFile", "null", "0.ts"]); + assertParseResult("allows tsconfig only option to be set to null", [ + "--composite", + "null", + "-tsBuildInfoFile", + "null", + "0.ts", + ]); describe("Watch options", () => { assertParseResult("parse --watchFile", ["--watchFile", "UseFsEvents", "0.ts"]); @@ -211,15 +251,28 @@ describe("unittests:: config:: commandLineParsing:: parseBuildOptions", () => { getCanonicalFileName: ts.identity, getNewLine: () => "\n", })); - Harness.Baseline.runBaseline(`config/commandLineParsing/parseBuildOptions/${subScenario}.js`, baseline.join("\n")); + Harness.Baseline.runBaseline( + `config/commandLineParsing/parseBuildOptions/${subScenario}.js`, + baseline.join("\n"), + ); }); } assertParseResult("parse build without any options ", []); assertParseResult("Parse multiple options", ["--verbose", "--force", "tests"]); assertParseResult("Parse option with invalid option", ["--verbose", "--invalidOption"]); assertParseResult("Parse multiple flags with input projects at the end", ["--force", "--verbose", "src", "tests"]); - assertParseResult("Parse multiple flags with input projects in the middle", ["--force", "src", "tests", "--verbose"]); - assertParseResult("Parse multiple flags with input projects in the beginning", ["src", "tests", "--force", "--verbose"]); + assertParseResult("Parse multiple flags with input projects in the middle", [ + "--force", + "src", + "tests", + "--verbose", + ]); + assertParseResult("Parse multiple flags with input projects in the beginning", [ + "src", + "tests", + "--force", + "--verbose", + ]); assertParseResult("parse build with --incremental", ["--incremental", "tests"]); assertParseResult("parse build with --locale en-us", ["--locale", "en-us", "src"]); assertParseResult("parse build with --tsBuildInfoFile", ["--tsBuildInfoFile", "build.tsbuildinfo", "tests"]); diff --git a/src/testRunner/unittests/config/configurationExtension.ts b/src/testRunner/unittests/config/configurationExtension.ts index 96bfc206db8ca..f70e2c9d5e98f 100644 --- a/src/testRunner/unittests/config/configurationExtension.ts +++ b/src/testRunner/unittests/config/configurationExtension.ts @@ -242,7 +242,12 @@ function createFileSystem(ignoreCase: boolean, cwd: string, root: string) { files: ["../main.ts"], }), "dev/configs/extendsArrayFifth.json": JSON.stringify({ - extends: ["./extendsArrayFirst", "./extendsArraySecond", "./extendsArrayThird", "./extendsArrayFourth"], + extends: [ + "./extendsArrayFirst", + "./extendsArraySecond", + "./extendsArrayThird", + "./extendsArrayFourth", + ], files: [], }), "dev/extendsArrayFails.json": JSON.stringify({ @@ -258,7 +263,9 @@ function createFileSystem(ignoreCase: boolean, cwd: string, root: string) { } const caseInsensitiveBasePath = "c:/dev/"; -const caseInsensitiveHost = new fakes.ParseConfigHost(createFileSystem(/*ignoreCase*/ true, caseInsensitiveBasePath, "c:/")); +const caseInsensitiveHost = new fakes.ParseConfigHost( + createFileSystem(/*ignoreCase*/ true, caseInsensitiveBasePath, "c:/"), +); const caseSensitiveBasePath = "/dev/"; const caseSensitiveHost = new fakes.ParseConfigHost(createFileSystem(/*ignoreCase*/ false, caseSensitiveBasePath, "/")); @@ -274,7 +281,10 @@ describe("unittests:: config:: configurationExtension", () => { } baselineParsedCommandLine("can resolve an extension with a base extension", "tsconfig.json"); - baselineParsedCommandLine("can resolve an extension with a base extension that overrides options", "tsconfig.nostrictnull.json"); + baselineParsedCommandLine( + "can resolve an extension with a base extension that overrides options", + "tsconfig.nostrictnull.json", + ); baselineParsedCommandLine("can report errors on circular imports", "circular.json"); baselineParsedCommandLine("can report missing configurations", "missing.json"); baselineParsedCommandLine("can report errors in extended configs", "failure.json"); @@ -286,12 +296,27 @@ describe("unittests:: config:: configurationExtension", () => { baselineParsedCommandLine("can overwrite top-level files using extended []", "configs/fifth.json"); baselineParsedCommandLine("can lookup via tsconfig field", "tsconfig.extendsBox.json"); baselineParsedCommandLine("can lookup via package-relative path", "tsconfig.extendsStrict.json"); - baselineParsedCommandLine("can lookup via non-redirected-to package-relative path", "tsconfig.extendsUnStrict.json"); - baselineParsedCommandLine("can lookup via package-relative path with extension", "tsconfig.extendsStrictExtension.json"); + baselineParsedCommandLine( + "can lookup via non-redirected-to package-relative path", + "tsconfig.extendsUnStrict.json", + ); + baselineParsedCommandLine( + "can lookup via package-relative path with extension", + "tsconfig.extendsStrictExtension.json", + ); baselineParsedCommandLine("can lookup via an implicit tsconfig", "tsconfig.extendsBoxImplied.json"); - baselineParsedCommandLine("can lookup via an implicit tsconfig in a package-relative directory", "tsconfig.extendsBoxImpliedUnstrict.json"); - baselineParsedCommandLine("can lookup via an implicit tsconfig in a package-relative directory with name", "tsconfig.extendsBoxImpliedUnstrictExtension.json"); - baselineParsedCommandLine("can lookup via an implicit tsconfig in a package-relative directory with extension", "tsconfig.extendsBoxImpliedPath.json"); + baselineParsedCommandLine( + "can lookup via an implicit tsconfig in a package-relative directory", + "tsconfig.extendsBoxImpliedUnstrict.json", + ); + baselineParsedCommandLine( + "can lookup via an implicit tsconfig in a package-relative directory with name", + "tsconfig.extendsBoxImpliedUnstrictExtension.json", + ); + baselineParsedCommandLine( + "can lookup via an implicit tsconfig in a package-relative directory with extension", + "tsconfig.extendsBoxImpliedPath.json", + ); baselineParsedCommandLine("can lookup via an package.json exports", "tsconfig.extendsFoo.json"); baselineExtendsSourceFile("adds extendedSourceFiles only once", "configs/fourth.json"); @@ -334,7 +359,10 @@ describe("unittests:: config:: configurationExtension", () => { baseline.push("ExtendedSourceFiles::", ...sourceFile.extendedSourceFiles!); ts.parseJsonSourceFileConfigFileContent(sourceFile, host, dir, {}, ts.getBaseFileName(entry)); baseline.push("After reusing sourceFile ExtendedSourceFiles::", ...sourceFile.extendedSourceFiles!); - Harness.Baseline.runBaseline(`config/configurationExtension/${name} ${testName}.js`, baseline.join("\n")); + Harness.Baseline.runBaseline( + `config/configurationExtension/${name} ${testName}.js`, + baseline.join("\n"), + ); }); } }); diff --git a/src/testRunner/unittests/config/convertCompilerOptionsFromJson.ts b/src/testRunner/unittests/config/convertCompilerOptionsFromJson.ts index aa0f4eb239d88..e974d8cf0159d 100644 --- a/src/testRunner/unittests/config/convertCompilerOptionsFromJson.ts +++ b/src/testRunner/unittests/config/convertCompilerOptionsFromJson.ts @@ -14,7 +14,12 @@ describe("unittests:: config:: convertCompilerOptionsFromJson", () => { ); } - function baselineCompilerOptionsJsonText(subScenario: string, jsonText: string, configFileName: string, skipJson = true) { + function baselineCompilerOptionsJsonText( + subScenario: string, + jsonText: string, + configFileName: string, + skipJson = true, + ) { baselineParseConfig({ scenario: "convertCompilerOptionsFromJson", subScenario, @@ -36,7 +41,8 @@ describe("unittests:: config:: convertCompilerOptionsFromJson", () => { jsonText, configFileName, basePath: "/apath", - baselineParsed: (baseline, parsed) => baseline.push("CompilerOptions::", JSON.stringify(parsed.options, undefined, " ")), + baselineParsed: (baseline, parsed) => + baseline.push("CompilerOptions::", JSON.stringify(parsed.options, undefined, " ")), }], skipJson, }); diff --git a/src/testRunner/unittests/config/convertTypeAcquisitionFromJson.ts b/src/testRunner/unittests/config/convertTypeAcquisitionFromJson.ts index a24e5f61b75d0..43a1565b7ac83 100644 --- a/src/testRunner/unittests/config/convertTypeAcquisitionFromJson.ts +++ b/src/testRunner/unittests/config/convertTypeAcquisitionFromJson.ts @@ -29,7 +29,8 @@ describe("unittests:: config:: convertTypeAcquisitionFromJson", () => { jsonText, configFileName, basePath: "/apath", - baselineParsed: (baseline, parsed) => baseline.push("TypeAcquisition::", JSON.stringify(parsed.typeAcquisition, undefined, " ")), + baselineParsed: (baseline, parsed) => + baseline.push("TypeAcquisition::", JSON.stringify(parsed.typeAcquisition, undefined, " ")), }]; }, }); diff --git a/src/testRunner/unittests/config/helpers.ts b/src/testRunner/unittests/config/helpers.ts index 17cac54e7931a..f6e08a4be80d1 100644 --- a/src/testRunner/unittests/config/helpers.ts +++ b/src/testRunner/unittests/config/helpers.ts @@ -83,11 +83,28 @@ function baselineParseConfigWith( it(jsonTest, () => { const baseline: string[] = []; header?.(baseline); - for (const { createHost, jsonText, configFileName, existingOptions, basePath, existingWatchOptions, baselineParsed } of input()) { + for ( + const { + createHost, + jsonText, + configFileName, + existingOptions, + basePath, + existingWatchOptions, + baselineParsed, + } of input() + ) { const host = createHost(baseline); if (!skipFs) baselineParseConfigHost(baseline, host); baseline.push(`configFileName:: ${configFileName}`); - const parsed = getParsed(jsonText, configFileName, host, basePath, existingOptions, existingWatchOptions); + const parsed = getParsed( + jsonText, + configFileName, + host, + basePath, + existingOptions, + existingWatchOptions, + ); baselineParsed(baseline, parsed); if (!skipErrors) { baseline.push("Errors::"); diff --git a/src/testRunner/unittests/config/initializeTSConfig.ts b/src/testRunner/unittests/config/initializeTSConfig.ts index d2965cdca7c17..b13f281a593c4 100644 --- a/src/testRunner/unittests/config/initializeTSConfig.ts +++ b/src/testRunner/unittests/config/initializeTSConfig.ts @@ -20,17 +20,38 @@ describe("unittests:: config:: initTSConfig", () => { initTSConfigCorrectly("Initialized TSConfig with boolean value compiler options", ["--init", "--noUnusedLocals"]); - initTSConfigCorrectly("Initialized TSConfig with enum value compiler options", ["--init", "--target", "es5", "--jsx", "react"]); + initTSConfigCorrectly("Initialized TSConfig with enum value compiler options", [ + "--init", + "--target", + "es5", + "--jsx", + "react", + ]); initTSConfigCorrectly("Initialized TSConfig with list compiler options", ["--init", "--types", "jquery,mocha"]); - initTSConfigCorrectly("Initialized TSConfig with list compiler options with enum value", ["--init", "--lib", "es5,es2015.core"]); + initTSConfigCorrectly("Initialized TSConfig with list compiler options with enum value", [ + "--init", + "--lib", + "es5,es2015.core", + ]); initTSConfigCorrectly("Initialized TSConfig with incorrect compiler option", ["--init", "--someNonExistOption"]); - initTSConfigCorrectly("Initialized TSConfig with incorrect compiler option value", ["--init", "--lib", "nonExistLib,es5,es2015.promise"]); - - initTSConfigCorrectly("Initialized TSConfig with advanced options", ["--init", "--declaration", "--declarationDir", "lib", "--skipLibCheck", "--noErrorTruncation"]); + initTSConfigCorrectly("Initialized TSConfig with incorrect compiler option value", [ + "--init", + "--lib", + "nonExistLib,es5,es2015.promise", + ]); + + initTSConfigCorrectly("Initialized TSConfig with advanced options", [ + "--init", + "--declaration", + "--declarationDir", + "lib", + "--skipLibCheck", + "--noErrorTruncation", + ]); initTSConfigCorrectly("Initialized TSConfig with --help", ["--init", "--help"]); diff --git a/src/testRunner/unittests/config/matchFiles.ts b/src/testRunner/unittests/config/matchFiles.ts index 172bf5f687351..58e198f02e9cf 100644 --- a/src/testRunner/unittests/config/matchFiles.ts +++ b/src/testRunner/unittests/config/matchFiles.ts @@ -153,7 +153,13 @@ function baselineMatches(subScenario: string, json: any, host: fakes.ParseConfig basePath, baselineParsed: (baseline, parsed) => { const wildcardDirectories = parsed.wildcardDirectories ? {} as ts.MapLike : undefined; - if (parsed.wildcardDirectories) ts.getOwnKeys(parsed.wildcardDirectories).forEach(dir => wildcardDirectories![dir] = `WatchDirectoryFlags.${(ts as any).WatchDirectoryFlags[parsed.wildcardDirectories![dir]]}`); + if (parsed.wildcardDirectories) { + ts.getOwnKeys(parsed.wildcardDirectories).forEach(dir => + wildcardDirectories![dir] = `WatchDirectoryFlags.${ + (ts as any).WatchDirectoryFlags[parsed.wildcardDirectories![dir]] + }` + ); + } baseline.push( "Result", JSON.stringify( @@ -926,8 +932,18 @@ describe("unittests:: config:: matchFiles", () => { ); }); - baselineMatches("can include files in the same order on multiple platforms case sensitive", {}, caseSensitiveOrderingDiffersWithCaseHost, caseSensitiveBasePath); - baselineMatches("can include files in the same order on multiple platforms case insensitive", {}, caseInsensitiveOrderingDiffersWithCaseHost, caseInsensitiveBasePath); + baselineMatches( + "can include files in the same order on multiple platforms case sensitive", + {}, + caseSensitiveOrderingDiffersWithCaseHost, + caseSensitiveBasePath, + ); + baselineMatches( + "can include files in the same order on multiple platforms case insensitive", + {}, + caseInsensitiveOrderingDiffersWithCaseHost, + caseInsensitiveBasePath, + ); describe("when recursive symlinked directories are present", () => { const fs = new vfs.FileSystem(/*ignoreCase*/ true, { diff --git a/src/testRunner/unittests/config/showConfig.ts b/src/testRunner/unittests/config/showConfig.ts index f870707801cd3..47ba51c794367 100644 --- a/src/testRunner/unittests/config/showConfig.ts +++ b/src/testRunner/unittests/config/showConfig.ts @@ -11,7 +11,9 @@ describe("unittests:: config:: showConfig", () => { const configPath = ts.combinePaths(cwd, "tsconfig.json"); const configContents = configJson ? JSON.stringify(configJson) : undefined; const configParseHost: ts.ParseConfigFileHost = { - fileExists: path => ts.comparePaths(ts.getNormalizedAbsolutePath(path, cwd), configPath) === ts.Comparison.EqualTo ? true : false, + fileExists: path => + ts.comparePaths(ts.getNormalizedAbsolutePath(path, cwd), configPath) === ts.Comparison.EqualTo + ? true : false, getCurrentDirectory() { return cwd; }, @@ -22,11 +24,17 @@ describe("unittests:: config:: showConfig", () => { readDirectory() { return []; }, - readFile: path => ts.comparePaths(ts.getNormalizedAbsolutePath(path, cwd), configPath) === ts.Comparison.EqualTo ? configContents : undefined, + readFile: path => + ts.comparePaths(ts.getNormalizedAbsolutePath(path, cwd), configPath) === ts.Comparison.EqualTo + ? configContents : undefined, }; let commandLine = ts.parseCommandLine(commandLinesArgs); if (commandLine.options.project) { - const result = ts.getParsedCommandLineOfConfigFile(commandLine.options.project, commandLine.options, configParseHost); + const result = ts.getParsedCommandLineOfConfigFile( + commandLine.options.project, + commandLine.options, + configParseHost, + ); if (result) { commandLine = result; } @@ -45,17 +53,38 @@ describe("unittests:: config:: showConfig", () => { showTSConfigCorrectly("Show TSConfig with boolean value compiler options", ["--showConfig", "--noUnusedLocals"]); - showTSConfigCorrectly("Show TSConfig with enum value compiler options", ["--showConfig", "--target", "es5", "--jsx", "react"]); + showTSConfigCorrectly("Show TSConfig with enum value compiler options", [ + "--showConfig", + "--target", + "es5", + "--jsx", + "react", + ]); showTSConfigCorrectly("Show TSConfig with list compiler options", ["--showConfig", "--types", "jquery,mocha"]); - showTSConfigCorrectly("Show TSConfig with list compiler options with enum value", ["--showConfig", "--lib", "es5,es2015.core"]); + showTSConfigCorrectly("Show TSConfig with list compiler options with enum value", [ + "--showConfig", + "--lib", + "es5,es2015.core", + ]); showTSConfigCorrectly("Show TSConfig with incorrect compiler option", ["--showConfig", "--someNonExistOption"]); - showTSConfigCorrectly("Show TSConfig with incorrect compiler option value", ["--showConfig", "--lib", "nonExistLib,es5,es2015.promise"]); - - showTSConfigCorrectly("Show TSConfig with advanced options", ["--showConfig", "--declaration", "--declarationDir", "lib", "--skipLibCheck", "--noErrorTruncation"]); + showTSConfigCorrectly("Show TSConfig with incorrect compiler option value", [ + "--showConfig", + "--lib", + "nonExistLib,es5,es2015.promise", + ]); + + showTSConfigCorrectly("Show TSConfig with advanced options", [ + "--showConfig", + "--declaration", + "--declarationDir", + "lib", + "--skipLibCheck", + "--noErrorTruncation", + ]); showTSConfigCorrectly("Show TSConfig with compileOnSave and more", ["-p", "tsconfig.json"], { compilerOptions: { @@ -192,8 +221,8 @@ describe("unittests:: config:: showConfig", () => { } } - const configObject = optionValue && - (isCompilerOptions ? { compilerOptions: optionValue } : { watchOptions: optionValue }); + const configObject = optionValue + && (isCompilerOptions ? { compilerOptions: optionValue } : { watchOptions: optionValue }); showTSConfigCorrectly(`Shows tsconfig for single option/${option.name}`, args, configObject); } }); diff --git a/src/testRunner/unittests/config/tsconfigParsing.ts b/src/testRunner/unittests/config/tsconfigParsing.ts index e0121594605c6..c3906365847e8 100644 --- a/src/testRunner/unittests/config/tsconfigParsing.ts +++ b/src/testRunner/unittests/config/tsconfigParsing.ts @@ -43,7 +43,10 @@ describe("unittests:: config:: tsconfigParsing:: parseConfigFileTextToJson", () input: () => scenario().map(({ jsonText, configFileName, basePath, allFileList }) => ({ createHost: () => { - const files = allFileList.reduce((files, value) => (files[value] = "", files), {} as vfs.FileSet); + const files = allFileList.reduce( + (files, value) => (files[value] = "", files), + {} as vfs.FileSet, + ); files[ts.combinePaths(basePath, configFileName)] = jsonText; return new fakes.ParseConfigHost( new vfs.FileSystem( @@ -234,7 +237,10 @@ describe("unittests:: config:: tsconfigParsing:: parseConfigFileTextToJson", () const configJsonObject = ts.convertToObject(result, result.parseDiagnostics); baseline.push("Result::", JSON.stringify(configJsonObject, undefined, " ")); baseline.push("Errors::", formatErrors(result.parseDiagnostics)); - Harness.Baseline.runBaseline(`config/tsconfigParsing/parse and re-emit tsconfig.json file with diagnostics.js`, baseline.join("\n")); + Harness.Baseline.runBaseline( + `config/tsconfigParsing/parse and re-emit tsconfig.json file with diagnostics.js`, + baseline.join("\n"), + ); }); baselinedParsed("generates errors for empty files list", () => [{ @@ -355,7 +361,10 @@ describe("unittests:: config:: tsconfigParsing:: parseConfigFileTextToJson", () allFileList: ["/apath/a.ts"], }]); - function baselineWildcards(subScenario: string, scenario: () => { configFileName: string; jsonText: string; basePath: string; }[]) { + function baselineWildcards( + subScenario: string, + scenario: () => { configFileName: string; jsonText: string; basePath: string; }[], + ) { baselineParseConfig({ scenario: "tsconfigParsing", subScenario, @@ -373,7 +382,13 @@ describe("unittests:: config:: tsconfigParsing:: parseConfigFileTextToJson", () basePath, baselineParsed: (baseline, parsed) => { baseline.push("Wildcards::"); - ts.getOwnKeys(parsed.wildcardDirectories!).forEach(dir => baseline.push(`${dir}: WatchDirectoryFlags.${(ts as any).WatchDirectoryFlags[parsed.wildcardDirectories![dir]]}`)); + ts.getOwnKeys(parsed.wildcardDirectories!).forEach(dir => + baseline.push( + `${dir}: WatchDirectoryFlags.${ + (ts as any).WatchDirectoryFlags[parsed.wildcardDirectories![dir]] + }`, + ) + ); }, })), skipErrors: true, @@ -388,11 +403,14 @@ describe("unittests:: config:: tsconfigParsing:: parseConfigFileTextToJson", () basePath: "/foo.bar", }]); - baselineWildcards("correctly parses wild card directories from implicit glob when two keys differ only in directory seperator", () => [{ - configFileName: "/foo.bar/tsconfig.json", - jsonText: JSON.stringify({ - include: ["./", "./**/*.json"], - }), - basePath: "/foo", - }]); + baselineWildcards( + "correctly parses wild card directories from implicit glob when two keys differ only in directory seperator", + () => [{ + configFileName: "/foo.bar/tsconfig.json", + jsonText: JSON.stringify({ + include: ["./", "./**/*.json"], + }), + basePath: "/foo", + }], + ); }); diff --git a/src/testRunner/unittests/convertToBase64.ts b/src/testRunner/unittests/convertToBase64.ts index e801451208ef9..6f6b6366681cf 100644 --- a/src/testRunner/unittests/convertToBase64.ts +++ b/src/testRunner/unittests/convertToBase64.ts @@ -9,7 +9,9 @@ describe("unittests:: convertToBase64", () => { if (Buffer) { it("Converts ASCII charaters correctly", () => { - runTest(" !\"#$ %&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"); + runTest( + " !\"#$ %&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~", + ); }); it("Converts escape sequences correctly", () => { diff --git a/src/testRunner/unittests/customTransforms.ts b/src/testRunner/unittests/customTransforms.ts index c401275203d63..28cd14065ff77 100644 --- a/src/testRunner/unittests/customTransforms.ts +++ b/src/testRunner/unittests/customTransforms.ts @@ -2,7 +2,12 @@ import * as Harness from "../_namespaces/Harness"; import * as ts from "../_namespaces/ts"; describe("unittests:: customTransforms", () => { - function emitsCorrectly(name: string, sources: { file: string; text: string; }[], customTransformers: ts.CustomTransformers, options: ts.CompilerOptions = {}) { + function emitsCorrectly( + name: string, + sources: { file: string; text: string; }[], + customTransformers: ts.CustomTransformers, + options: ts.CompilerOptions = {}, + ) { it(name, () => { const roots = sources.map(source => ts.createSourceFile(source.file, source.text, ts.ScriptTarget.ES2015)); const fileMap = ts.arrayToMap(roots, file => file.fileName); @@ -20,8 +25,17 @@ describe("unittests:: customTransforms", () => { writeFile: (fileName, text) => outputs.set(fileName, text), }; - const program = ts.createProgram(ts.arrayFrom(fileMap.keys()), { newLine: ts.NewLineKind.LineFeed, ...options }, host); - program.emit(/*targetSourceFile*/ undefined, host.writeFile, /*cancellationToken*/ undefined, /*emitOnlyDtsFiles*/ false, customTransformers); + const program = ts.createProgram(ts.arrayFrom(fileMap.keys()), { + newLine: ts.NewLineKind.LineFeed, + ...options, + }, host); + program.emit( + /*targetSourceFile*/ undefined, + host.writeFile, + /*cancellationToken*/ undefined, + /*emitOnlyDtsFiles*/ false, + customTransformers, + ); let content = ""; for (const [file, text] of outputs.entries()) { if (content) content += "\n\n"; @@ -54,7 +68,12 @@ describe("unittests:: customTransforms", () => { } } function visitFunction(node: ts.FunctionDeclaration) { - ts.addSyntheticLeadingComment(node, ts.SyntaxKind.MultiLineCommentTrivia, "@before", /*hasTrailingNewLine*/ true); + ts.addSyntheticLeadingComment( + node, + ts.SyntaxKind.MultiLineCommentTrivia, + "@before", + /*hasTrailingNewLine*/ true, + ); return node; } }; @@ -91,7 +110,9 @@ describe("unittests:: customTransforms", () => { before: [ context => node => ts.visitNode(node, function visitor(node: ts.Node): ts.Node { - if (ts.isStringLiteral(node) && node.text === "change") return ts.factory.createStringLiteral("changed"); + if (ts.isStringLiteral(node) && node.text === "change") { + return ts.factory.createStringLiteral("changed"); + } return ts.visitEachChild(node, visitor, context); }, ts.isSourceFile), ], @@ -124,7 +145,8 @@ describe("unittests:: customTransforms", () => { text, fileName: "another.html", lineMap, - getLineAndCharacterOfPosition: pos => ts.computeLineAndCharacterOfPosition(lineMap, pos), + getLineAndCharacterOfPosition: pos => + ts.computeLineAndCharacterOfPosition(lineMap, pos), }, }); return node; @@ -159,7 +181,8 @@ describe("unittests:: customTransforms", () => { }, ts.isSourceFile); return { transformSourceFile, - transformBundle: node => ts.factory.createBundle(ts.map(node.sourceFiles, transformSourceFile), node.prepends), + transformBundle: node => + ts.factory.createBundle(ts.map(node.sourceFiles, transformSourceFile), node.prepends), }; }, ], diff --git a/src/testRunner/unittests/factory.ts b/src/testRunner/unittests/factory.ts index 903388588aa69..88a45eb611848 100644 --- a/src/testRunner/unittests/factory.ts +++ b/src/testRunner/unittests/factory.ts @@ -2,7 +2,11 @@ import * as ts from "../_namespaces/ts"; describe("unittests:: FactoryAPI", () => { function assertSyntaxKind(node: ts.Node, expected: ts.SyntaxKind) { - assert.strictEqual(node.kind, expected, `Actual: ${ts.Debug.formatSyntaxKind(node.kind)} Expected: ${ts.Debug.formatSyntaxKind(expected)}`); + assert.strictEqual( + node.kind, + expected, + `Actual: ${ts.Debug.formatSyntaxKind(node.kind)} Expected: ${ts.Debug.formatSyntaxKind(expected)}`, + ); } describe("factory.createExportAssignment", () => { it("parenthesizes default export if necessary", () => { @@ -15,19 +19,58 @@ describe("unittests:: FactoryAPI", () => { assertSyntaxKind(node.expression, ts.SyntaxKind.ParenthesizedExpression); } - const clazz = ts.factory.createClassExpression(/*modifiers*/ undefined, "C", /*typeParameters*/ undefined, /*heritageClauses*/ undefined, [ - ts.factory.createPropertyDeclaration([ts.factory.createToken(ts.SyntaxKind.StaticKeyword)], "prop", /*questionOrExclamationToken*/ undefined, /*type*/ undefined, ts.factory.createStringLiteral("1")), - ]); + const clazz = ts.factory.createClassExpression( + /*modifiers*/ undefined, + "C", + /*typeParameters*/ undefined, + /*heritageClauses*/ undefined, + [ + ts.factory.createPropertyDeclaration( + [ts.factory.createToken(ts.SyntaxKind.StaticKeyword)], + "prop", + /*questionOrExclamationToken*/ undefined, + /*type*/ undefined, + ts.factory.createStringLiteral("1"), + ), + ], + ); checkExpression(clazz); checkExpression(ts.factory.createPropertyAccessExpression(clazz, "prop")); - const func = ts.factory.createFunctionExpression(/*modifiers*/ undefined, /*asteriskToken*/ undefined, "fn", /*typeParameters*/ undefined, /*parameters*/ undefined, /*type*/ undefined, ts.factory.createBlock([])); + const func = ts.factory.createFunctionExpression( + /*modifiers*/ undefined, + /*asteriskToken*/ undefined, + "fn", + /*typeParameters*/ undefined, + /*parameters*/ undefined, + /*type*/ undefined, + ts.factory.createBlock([]), + ); checkExpression(func); - checkExpression(ts.factory.createCallExpression(func, /*typeArguments*/ undefined, /*argumentsArray*/ undefined)); - checkExpression(ts.factory.createTaggedTemplateExpression(func, /*typeArguments*/ undefined, ts.factory.createNoSubstitutionTemplateLiteral(""))); + checkExpression( + ts.factory.createCallExpression(func, /*typeArguments*/ undefined, /*argumentsArray*/ undefined), + ); + checkExpression( + ts.factory.createTaggedTemplateExpression( + func, + /*typeArguments*/ undefined, + ts.factory.createNoSubstitutionTemplateLiteral(""), + ), + ); - checkExpression(ts.factory.createBinaryExpression(ts.factory.createStringLiteral("a"), ts.SyntaxKind.CommaToken, ts.factory.createStringLiteral("b"))); - checkExpression(ts.factory.createCommaListExpression([ts.factory.createStringLiteral("a"), ts.factory.createStringLiteral("b")])); + checkExpression( + ts.factory.createBinaryExpression( + ts.factory.createStringLiteral("a"), + ts.SyntaxKind.CommaToken, + ts.factory.createStringLiteral("b"), + ), + ); + checkExpression( + ts.factory.createCommaListExpression([ + ts.factory.createStringLiteral("a"), + ts.factory.createStringLiteral("b"), + ]), + ); }); }); @@ -47,10 +90,30 @@ describe("unittests:: FactoryAPI", () => { checkBody(ts.factory.createObjectLiteralExpression()); checkBody(ts.factory.createPropertyAccessExpression(ts.factory.createObjectLiteralExpression(), "prop")); - checkBody(ts.factory.createAsExpression(ts.factory.createPropertyAccessExpression(ts.factory.createObjectLiteralExpression(), "prop"), ts.factory.createTypeReferenceNode("T", /*typeArguments*/ undefined))); - checkBody(ts.factory.createNonNullExpression(ts.factory.createPropertyAccessExpression(ts.factory.createObjectLiteralExpression(), "prop"))); - checkBody(ts.factory.createCommaListExpression([ts.factory.createStringLiteral("a"), ts.factory.createStringLiteral("b")])); - checkBody(ts.factory.createBinaryExpression(ts.factory.createStringLiteral("a"), ts.SyntaxKind.CommaToken, ts.factory.createStringLiteral("b"))); + checkBody( + ts.factory.createAsExpression( + ts.factory.createPropertyAccessExpression(ts.factory.createObjectLiteralExpression(), "prop"), + ts.factory.createTypeReferenceNode("T", /*typeArguments*/ undefined), + ), + ); + checkBody( + ts.factory.createNonNullExpression( + ts.factory.createPropertyAccessExpression(ts.factory.createObjectLiteralExpression(), "prop"), + ), + ); + checkBody( + ts.factory.createCommaListExpression([ + ts.factory.createStringLiteral("a"), + ts.factory.createStringLiteral("b"), + ]), + ); + checkBody( + ts.factory.createBinaryExpression( + ts.factory.createStringLiteral("a"), + ts.SyntaxKind.CommaToken, + ts.factory.createStringLiteral("b"), + ), + ); }); }); @@ -67,7 +130,10 @@ describe("unittests:: FactoryAPI", () => { ); function checkRhs(operator: ts.BinaryOperator, expectParens: boolean) { const node = ts.factory.createBinaryExpression(lhs, operator, rhs); - assertSyntaxKind(node.right, expectParens ? ts.SyntaxKind.ParenthesizedExpression : ts.SyntaxKind.ArrowFunction); + assertSyntaxKind( + node.right, + expectParens ? ts.SyntaxKind.ParenthesizedExpression : ts.SyntaxKind.ArrowFunction, + ); } checkRhs(ts.SyntaxKind.CommaToken, /*expectParens*/ false); diff --git a/src/testRunner/unittests/helpers.ts b/src/testRunner/unittests/helpers.ts index b01502e93b8f6..fa5f015935922 100644 --- a/src/testRunner/unittests/helpers.ts +++ b/src/testRunner/unittests/helpers.ts @@ -31,7 +31,13 @@ export interface TestCompilerHost extends ts.CompilerHost { export class SourceText implements ts.IScriptSnapshot { private fullText: string | undefined; - constructor(private references: string, private importsAndExports: string, private program: string, private changedPart = ChangedPart.none, private version = 0) { + constructor( + private references: string, + private importsAndExports: string, + private program: string, + private changedPart = ChangedPart.none, + private version = 0, + ) { } static New(references: string, importsAndExports: string, program: string): SourceText { @@ -47,15 +53,33 @@ export class SourceText implements ts.IScriptSnapshot { public updateReferences(newReferences: string): SourceText { ts.Debug.assert(newReferences !== undefined); - return new SourceText(newReferences + newLine, this.importsAndExports, this.program, this.changedPart | ChangedPart.references, this.version + 1); + return new SourceText( + newReferences + newLine, + this.importsAndExports, + this.program, + this.changedPart | ChangedPart.references, + this.version + 1, + ); } public updateImportsAndExports(newImportsAndExports: string): SourceText { ts.Debug.assert(newImportsAndExports !== undefined); - return new SourceText(this.references, newImportsAndExports + newLine, this.program, this.changedPart | ChangedPart.importsAndExports, this.version + 1); + return new SourceText( + this.references, + newImportsAndExports + newLine, + this.program, + this.changedPart | ChangedPart.importsAndExports, + this.version + 1, + ); } public updateProgram(newProgram: string): SourceText { ts.Debug.assert(newProgram !== undefined); - return new SourceText(this.references, this.importsAndExports, newProgram, this.changedPart | ChangedPart.program, this.version + 1); + return new SourceText( + this.references, + this.importsAndExports, + newProgram, + this.changedPart | ChangedPart.program, + this.version + 1, + ); } public getFullText() { @@ -84,7 +108,10 @@ export class SourceText implements ts.IScriptSnapshot { newLength = this.importsAndExports.length; break; case ChangedPart.program: - oldSpan = ts.createTextSpan(oldText.references.length + oldText.importsAndExports.length, oldText.program.length); + oldSpan = ts.createTextSpan( + oldText.references.length + oldText.importsAndExports.length, + oldText.program.length, + ); newLength = this.program.length; break; default: @@ -102,7 +129,12 @@ function createSourceFileWithText(fileName: string, sourceText: SourceText, targ return file; } -export function createTestCompilerHost(texts: readonly NamedSourceText[], target: ts.ScriptTarget, oldProgram?: ProgramWithSourceTexts, useGetSourceFileByPath?: boolean) { +export function createTestCompilerHost( + texts: readonly NamedSourceText[], + target: ts.ScriptTarget, + oldProgram?: ProgramWithSourceTexts, + useGetSourceFileByPath?: boolean, +) { const files = ts.arrayToMap(texts, t => t.name, t => { if (oldProgram) { let oldFile = oldProgram.getSourceFile(t.name) as SourceFileWithText; @@ -137,13 +169,21 @@ export function createTestCompilerHost(texts: readonly NamedSourceText[], target }, }; if (useGetSourceFileByPath) { - const filesByPath = ts.mapEntries(files, (fileName, file) => [ts.toPath(fileName, "", getCanonicalFileName), file]); + const filesByPath = ts.mapEntries( + files, + (fileName, file) => [ts.toPath(fileName, "", getCanonicalFileName), file], + ); result.getSourceFileByPath = (_fileName, path) => filesByPath.get(path); } return result; } -export function newProgram(texts: NamedSourceText[], rootNames: string[], options: ts.CompilerOptions, useGetSourceFileByPath?: boolean): ProgramWithSourceTexts { +export function newProgram( + texts: NamedSourceText[], + rootNames: string[], + options: ts.CompilerOptions, + useGetSourceFileByPath?: boolean, +): ProgramWithSourceTexts { const host = createTestCompilerHost(texts, options.target!, /*oldProgram*/ undefined, useGetSourceFileByPath); const program = ts.createProgram(rootNames, options, host) as ProgramWithSourceTexts; program.sourceTexts = texts; @@ -151,7 +191,14 @@ export function newProgram(texts: NamedSourceText[], rootNames: string[], option return program; } -export function updateProgram(oldProgram: ProgramWithSourceTexts, rootNames: readonly string[], options: ts.CompilerOptions, updater: (files: NamedSourceText[]) => void, newTexts?: NamedSourceText[], useGetSourceFileByPath?: boolean) { +export function updateProgram( + oldProgram: ProgramWithSourceTexts, + rootNames: readonly string[], + options: ts.CompilerOptions, + updater: (files: NamedSourceText[]) => void, + newTexts?: NamedSourceText[], + useGetSourceFileByPath?: boolean, +) { if (!newTexts) { newTexts = oldProgram.sourceTexts!.slice(0); } diff --git a/src/testRunner/unittests/helpers/baseline.ts b/src/testRunner/unittests/helpers/baseline.ts index 2daac68548942..d5061340314d0 100644 --- a/src/testRunner/unittests/helpers/baseline.ts +++ b/src/testRunner/unittests/helpers/baseline.ts @@ -14,7 +14,9 @@ export interface CommandLineCallbacks { getPrograms: () => readonly CommandLineProgram[]; } -function isAnyProgram(program: ts.Program | ts.BuilderProgram | ts.ParsedCommandLine): program is ts.Program | ts.BuilderProgram { +function isAnyProgram( + program: ts.Program | ts.BuilderProgram | ts.ParsedCommandLine, +): program is ts.Program | ts.BuilderProgram { return !!(program as ts.Program | ts.BuilderProgram).getCompilerOptions; } export function commandLineCallbacks( @@ -28,9 +30,9 @@ export function commandLineCallbacks( if (isAnyProgram(program)) { baselineBuildInfo(program.getCompilerOptions(), sys, originalReadCall); (programs || (programs = [])).push( - ts.isBuilderProgram(program) ? - [program.getProgram(), program] : - [program], + ts.isBuilderProgram(program) + ? [program.getProgram(), program] + : [program], ); } else { @@ -45,7 +47,12 @@ export function commandLineCallbacks( }; } -export function baselinePrograms(baseline: string[], getPrograms: () => readonly CommandLineProgram[], oldPrograms: readonly (CommandLineProgram | undefined)[], baselineDependencies: boolean | undefined) { +export function baselinePrograms( + baseline: string[], + getPrograms: () => readonly CommandLineProgram[], + oldPrograms: readonly (CommandLineProgram | undefined)[], + baselineDependencies: boolean | undefined, +) { const programs = getPrograms(); for (let i = 0; i < programs.length; i++) { baselineProgram(baseline, programs[i], oldPrograms[i], baselineDependencies); @@ -53,7 +60,12 @@ export function baselinePrograms(baseline: string[], getPrograms: () => readonly return programs; } -function baselineProgram(baseline: string[], [program, builderProgram]: CommandLineProgram, oldProgram: CommandLineProgram | undefined, baselineDependencies: boolean | undefined) { +function baselineProgram( + baseline: string[], + [program, builderProgram]: CommandLineProgram, + oldProgram: CommandLineProgram | undefined, + baselineDependencies: boolean | undefined, +) { if (program !== oldProgram?.[0]) { const options = program.getCompilerOptions(); baseline.push(`Program root files: ${JSON.stringify(program.getRootFileNames())}`); @@ -76,7 +88,10 @@ function baselineProgram(baseline: string[], [program, builderProgram]: CommandL if (state.semanticDiagnosticsPerFile?.size) { baseline.push("Semantic diagnostics in builder refreshed for::"); for (const file of program.getSourceFiles()) { - if (!internalState.semanticDiagnosticsFromOldState || !internalState.semanticDiagnosticsFromOldState.has(file.resolvedPath)) { + if ( + !internalState.semanticDiagnosticsFromOldState + || !internalState.semanticDiagnosticsFromOldState.has(file.resolvedPath) + ) { baseline.push(file.fileName); } } @@ -129,7 +144,13 @@ export function generateSourceMapBaselineFiles(sys: ts.System & { writtenFiles: } } -function generateBundleFileSectionInfo(sys: ts.System, originalReadCall: ts.System["readFile"], baselineRecorder: Harness.Compiler.WriterAggregator, bundleFileInfo: ts.BundleFileInfo | undefined, outFile: string | undefined) { +function generateBundleFileSectionInfo( + sys: ts.System, + originalReadCall: ts.System["readFile"], + baselineRecorder: Harness.Compiler.WriterAggregator, + bundleFileInfo: ts.BundleFileInfo | undefined, + outFile: string | undefined, +) { if (!ts.length(bundleFileInfo && bundleFileInfo.sections) && !outFile) return; // Nothing to baseline const content = outFile && sys.fileExists(outFile) ? originalReadCall.call(sys, outFile, "utf8")! : ""; @@ -164,13 +185,20 @@ function generateBundleFileSectionInfo(sys: ts.System, originalReadCall: ts.Syst } function writeSectionHeader(section: ts.BundleFileSection) { - baselineRecorder.WriteLine(`${section.kind}: (${section.pos}-${section.end})${section.data ? ":: " + section.data : ""}${section.kind === ts.BundleFileSectionKind.Prepend ? " texts:: " + section.texts.length : ""}`); + baselineRecorder.WriteLine( + `${section.kind}: (${section.pos}-${section.end})${section.data ? ":: " + section.data : ""}${ + section.kind === ts.BundleFileSectionKind.Prepend ? " texts:: " + section.texts.length : "" + }`, + ); } } export type ReadableProgramBuildInfoDiagnostic = string | [string, readonly ts.ReusableDiagnostic[]]; export type ReadableBuilderFileEmit = string & { __readableBuilderFileEmit: any; }; -export type ReadableProgramBuilderInfoFilePendingEmit = [original: string | [string], emitKind: ReadableBuilderFileEmit]; +export type ReadableProgramBuilderInfoFilePendingEmit = [ + original: string | [string], + emitKind: ReadableBuilderFileEmit, +]; export type ReadableProgramBuildInfoEmitSignature = string | [string, ts.EmitSignature | []]; export type ReadableProgramBuildInfoFileInfo = Omit & { impliedFormat: string | undefined; @@ -179,48 +207,71 @@ export type ReadableProgramBuildInfoFileInfo = Omit & { - fileNamesList: readonly (readonly string[])[] | undefined; - fileInfos: ts.MapLike>; - root: readonly ReadableProgramBuildInfoRoot[]; - referencedMap: ts.MapLike | undefined; - exportedModulesMap: ts.MapLike | undefined; - semanticDiagnosticsPerFile: readonly ReadableProgramBuildInfoDiagnostic[] | undefined; - affectedFilesPendingEmit: readonly ReadableProgramBuilderInfoFilePendingEmit[] | undefined; - changeFileSet: readonly string[] | undefined; - emitSignatures: readonly ReadableProgramBuildInfoEmitSignature[] | undefined; -}; -export type ReadableProgramBuildInfoBundlePendingEmit = [emitKind: ReadableBuilderFileEmit, original: ts.ProgramBuildInfoBundlePendingEmit]; -export type ReadableProgramBundleEmitBuildInfo = Omit & { - fileInfos: ts.MapLike>; - root: readonly ReadableProgramBuildInfoRoot[]; - pendingEmit: ReadableProgramBuildInfoBundlePendingEmit | undefined; -}; +export type ReadableProgramMultiFileEmitBuildInfo = + & Omit< + ts.ProgramMultiFileEmitBuildInfo, + | "fileIdsList" + | "fileInfos" + | "root" + | "referencedMap" + | "exportedModulesMap" + | "semanticDiagnosticsPerFile" + | "affectedFilesPendingEmit" + | "changeFileSet" + | "emitSignatures" + > + & { + fileNamesList: readonly (readonly string[])[] | undefined; + fileInfos: ts.MapLike>; + root: readonly ReadableProgramBuildInfoRoot[]; + referencedMap: ts.MapLike | undefined; + exportedModulesMap: ts.MapLike | undefined; + semanticDiagnosticsPerFile: readonly ReadableProgramBuildInfoDiagnostic[] | undefined; + affectedFilesPendingEmit: readonly ReadableProgramBuilderInfoFilePendingEmit[] | undefined; + changeFileSet: readonly string[] | undefined; + emitSignatures: readonly ReadableProgramBuildInfoEmitSignature[] | undefined; + }; +export type ReadableProgramBuildInfoBundlePendingEmit = [ + emitKind: ReadableBuilderFileEmit, + original: ts.ProgramBuildInfoBundlePendingEmit, +]; +export type ReadableProgramBundleEmitBuildInfo = + & Omit + & { + fileInfos: ts.MapLike>; + root: readonly ReadableProgramBuildInfoRoot[]; + pendingEmit: ReadableProgramBuildInfoBundlePendingEmit | undefined; + }; export type ReadableProgramBuildInfo = ReadableProgramMultiFileEmitBuildInfo | ReadableProgramBundleEmitBuildInfo; -export function isReadableProgramBundleEmitBuildInfo(info: ReadableProgramBuildInfo | undefined): info is ReadableProgramBundleEmitBuildInfo { +export function isReadableProgramBundleEmitBuildInfo( + info: ReadableProgramBuildInfo | undefined, +): info is ReadableProgramBundleEmitBuildInfo { return !!info && !!ts.outFile(info.options || {}); } -export type ReadableBuildInfo = Omit & { program: ReadableProgramBuildInfo | undefined; size: number; }; +export type ReadableBuildInfo = Omit & { + program: ReadableProgramBuildInfo | undefined; + size: number; +}; function generateBuildInfoProgramBaseline(sys: ts.System, buildInfoPath: string, buildInfo: ts.BuildInfo) { let program: ReadableProgramBuildInfo | undefined; let fileNamesList: string[][] | undefined; if (buildInfo.program && ts.isProgramBundleEmitBuildInfo(buildInfo.program)) { const fileInfos: ReadableProgramBundleEmitBuildInfo["fileInfos"] = {}; buildInfo.program?.fileInfos?.forEach((fileInfo, index) => - fileInfos[toFileName(index + 1 as ts.ProgramBuildInfoFileId)] = ts.isString(fileInfo) ? - fileInfo : - toReadableFileInfo(fileInfo, ts.identity) + fileInfos[toFileName(index + 1 as ts.ProgramBuildInfoFileId)] = ts.isString(fileInfo) + ? fileInfo + : toReadableFileInfo(fileInfo, ts.identity) ); const pendingEmit = buildInfo.program.pendingEmit; program = { ...buildInfo.program, fileInfos, root: buildInfo.program.root.map(toReadableProgramBuildInfoRoot), - pendingEmit: pendingEmit === undefined ? - undefined : - [ + pendingEmit: pendingEmit === undefined + ? undefined + : [ toReadableBuilderFileEmit(ts.toProgramEmitPending(pendingEmit, buildInfo.program.options)), pendingEmit, ], @@ -228,9 +279,15 @@ function generateBuildInfoProgramBaseline(sys: ts.System, buildInfoPath: string, } else if (buildInfo.program) { const fileInfos: ReadableProgramMultiFileEmitBuildInfo["fileInfos"] = {}; - buildInfo.program?.fileInfos?.forEach((fileInfo, index) => fileInfos[toFileName(index + 1 as ts.ProgramBuildInfoFileId)] = toReadableFileInfo(fileInfo, ts.toBuilderStateFileInfoForMultiEmit)); + buildInfo.program?.fileInfos?.forEach((fileInfo, index) => + fileInfos[toFileName(index + 1 as ts.ProgramBuildInfoFileId)] = toReadableFileInfo( + fileInfo, + ts.toBuilderStateFileInfoForMultiEmit, + ) + ); fileNamesList = buildInfo.program.fileIdsList?.map(fileIdsListId => fileIdsListId.map(toFileName)); - const fullEmitForOptions = buildInfo.program.affectedFilesPendingEmit ? ts.getBuilderFileEmit(buildInfo.program.options || {}) : undefined; + const fullEmitForOptions = buildInfo.program.affectedFilesPendingEmit + ? ts.getBuilderFileEmit(buildInfo.program.options || {}) : undefined; program = buildInfo.program && { fileNames: buildInfo.program.fileNames, fileNamesList, @@ -240,16 +297,18 @@ function generateBuildInfoProgramBaseline(sys: ts.System, buildInfoPath: string, referencedMap: toMapOfReferencedSet(buildInfo.program.referencedMap), exportedModulesMap: toMapOfReferencedSet(buildInfo.program.exportedModulesMap), semanticDiagnosticsPerFile: buildInfo.program.semanticDiagnosticsPerFile?.map(d => - ts.isNumber(d) ? - toFileName(d) : - [toFileName(d[0]), d[1]] + ts.isNumber(d) + ? toFileName(d) + : [toFileName(d[0]), d[1]] + ), + affectedFilesPendingEmit: buildInfo.program.affectedFilesPendingEmit?.map(value => + toReadableProgramBuilderInfoFilePendingEmit(value, fullEmitForOptions!) ), - affectedFilesPendingEmit: buildInfo.program.affectedFilesPendingEmit?.map(value => toReadableProgramBuilderInfoFilePendingEmit(value, fullEmitForOptions!)), changeFileSet: buildInfo.program.changeFileSet?.map(toFileName), emitSignatures: buildInfo.program.emitSignatures?.map(s => - ts.isNumber(s) ? - toFileName(s) : - [toFileName(s[0]), s[1]] + ts.isNumber(s) + ? toFileName(s) + : [toFileName(s[0]), s[1]] ), latestChangedDtsFile: buildInfo.program.latestChangedDtsFile, }; @@ -287,12 +346,16 @@ function generateBuildInfoProgramBaseline(sys: ts.System, buildInfoPath: string, return fileNamesList![fileIdsListId - 1]; } - function toReadableFileInfo(original: T, toFileInfo: (fileInfo: T) => ts.BuilderState.FileInfo): ReadableProgramBuildInfoFileInfo { + function toReadableFileInfo( + original: T, + toFileInfo: (fileInfo: T) => ts.BuilderState.FileInfo, + ): ReadableProgramBuildInfoFileInfo { const info = toFileInfo(original); return { original: ts.isString(original) ? undefined : original, ...info, - impliedFormat: info.impliedFormat && ts.getNameOfCompilerOptionValue(info.impliedFormat, ts.moduleOptionDeclaration.type), + impliedFormat: info.impliedFormat + && ts.getNameOfCompilerOptionValue(info.impliedFormat, ts.moduleOptionDeclaration.type), }; } @@ -303,7 +366,9 @@ function generateBuildInfoProgramBaseline(sys: ts.System, buildInfoPath: string, return [original, readable]; } - function toMapOfReferencedSet(referenceMap: ts.ProgramBuildInfoReferencedMap | undefined): ts.MapLike | undefined { + function toMapOfReferencedSet( + referenceMap: ts.ProgramBuildInfoReferencedMap | undefined, + ): ts.MapLike | undefined { if (!referenceMap) return undefined; const result: ts.MapLike = {}; for (const [fileNamesKey, fileNamesListKey] of referenceMap) { @@ -312,7 +377,10 @@ function generateBuildInfoProgramBaseline(sys: ts.System, buildInfoPath: string, return result; } - function toReadableProgramBuilderInfoFilePendingEmit(value: ts.ProgramBuilderInfoFilePendingEmit, fullEmitForOptions: ts.BuilderFileEmit): ReadableProgramBuilderInfoFilePendingEmit { + function toReadableProgramBuilderInfoFilePendingEmit( + value: ts.ProgramBuilderInfoFilePendingEmit, + fullEmitForOptions: ts.BuilderFileEmit, + ): ReadableProgramBuilderInfoFilePendingEmit { return [ ts.isNumber(value) ? toFileName(value) : [toFileName(value[0])], toReadableBuilderFileEmit(ts.toBuilderFileEmit(value, fullEmitForOptions)), @@ -348,24 +416,43 @@ export function baselineBuildInfo( if (!buildInfoPath || !sys.writtenFiles!.has(toPathWithSystem(sys, buildInfoPath))) return; if (!sys.fileExists(buildInfoPath)) return; - const buildInfo = ts.getBuildInfo(buildInfoPath, (originalReadCall || sys.readFile).call(sys, buildInfoPath, "utf8")!); + const buildInfo = ts.getBuildInfo( + buildInfoPath, + (originalReadCall || sys.readFile).call(sys, buildInfoPath, "utf8")!, + ); if (!buildInfo) return sys.writeFile(`${buildInfoPath}.baseline.txt`, "Error reading valid buildinfo file"); generateBuildInfoProgramBaseline(sys, buildInfoPath, buildInfo); if (!ts.outFile(options)) return; const { jsFilePath, declarationFilePath } = ts.getOutputPathsForBundle(options, /*forceDtsPaths*/ false); const bundle = buildInfo.bundle; - if (!bundle || (!ts.length(bundle.js && bundle.js.sections) && !ts.length(bundle.dts && bundle.dts.sections))) return; + if (!bundle || (!ts.length(bundle.js && bundle.js.sections) && !ts.length(bundle.dts && bundle.dts.sections))) { + return; + } // Write the baselines: const baselineRecorder = new Harness.Compiler.WriterAggregator(); generateBundleFileSectionInfo(sys, originalReadCall || sys.readFile, baselineRecorder, bundle.js, jsFilePath); - generateBundleFileSectionInfo(sys, originalReadCall || sys.readFile, baselineRecorder, bundle.dts, declarationFilePath); + generateBundleFileSectionInfo( + sys, + originalReadCall || sys.readFile, + baselineRecorder, + bundle.dts, + declarationFilePath, + ); baselineRecorder.Close(); const text = baselineRecorder.lines.join("\r\n"); sys.writeFile(`${buildInfoPath}.baseline.txt`, text); } -export function tscBaselineName(scenario: string, subScenario: string, commandLineArgs: readonly string[], isWatch?: boolean, suffix?: string) { - return `${ts.isBuild(commandLineArgs) ? "tsbuild" : "tsc"}${isWatch ? "Watch" : ""}/${scenario}/${subScenario.split(" ").join("-")}${suffix ? suffix : ""}.js`; +export function tscBaselineName( + scenario: string, + subScenario: string, + commandLineArgs: readonly string[], + isWatch?: boolean, + suffix?: string, +) { + return `${ts.isBuild(commandLineArgs) ? "tsbuild" : "tsc"}${isWatch ? "Watch" : ""}/${scenario}/${ + subScenario.split(" ").join("-") + }${suffix ? suffix : ""}.js`; } diff --git a/src/testRunner/unittests/helpers/libraryResolution.ts b/src/testRunner/unittests/helpers/libraryResolution.ts index d435a4c2892ab..5cfb7b9279863 100644 --- a/src/testRunner/unittests/helpers/libraryResolution.ts +++ b/src/testRunner/unittests/helpers/libraryResolution.ts @@ -25,7 +25,12 @@ function getFsContentsForLibResolution(libRedirection?: boolean): FsContents { /// `, "/home/src/projects/project1/tsconfig.json": JSON.stringify({ - compilerOptions: { composite: true, typeRoots: ["./typeroot1"], lib: ["es5", "dom"], traceResolution: true }, + compilerOptions: { + composite: true, + typeRoots: ["./typeroot1"], + lib: ["es5", "dom"], + traceResolution: true, + }, }), "/home/src/projects/project1/typeroot1/sometype/index.d.ts": `export type TheNum = "type1";`, "/home/src/projects/project2/utils.d.ts": `export const y = 10;`, @@ -54,7 +59,8 @@ function getFsContentsForLibResolution(libRedirection?: boolean): FsContents { "/home/src/projects/node_modules/@typescript/lib-esnext/index.d.ts": libContent, "/home/src/projects/node_modules/@typescript/lib-dom/index.d.ts": "interface DOMInterface { }", "/home/src/projects/node_modules/@typescript/lib-webworker/index.d.ts": "interface WebworkerInterface { }", - "/home/src/projects/node_modules/@typescript/lib-scripthost/index.d.ts": "interface ScriptHostInterface { }", + "/home/src/projects/node_modules/@typescript/lib-scripthost/index.d.ts": + "interface ScriptHostInterface { }", } : undefined, }; } @@ -90,7 +96,17 @@ export function getServerHosForLibResolution(libRedirection?: true) { } export function getCommandLineArgsForLibResolution(withoutConfig: true | undefined) { - return withoutConfig ? - ["project1/core.d.ts", "project1/utils.d.ts", "project1/file.ts", "project1/index.ts", "project1/file2.ts", "--lib", "es5,dom", "--traceResolution", "--explainFiles"] : - ["-p", "project1", "--explainFiles"]; + return withoutConfig + ? [ + "project1/core.d.ts", + "project1/utils.d.ts", + "project1/file.ts", + "project1/index.ts", + "project1/file2.ts", + "--lib", + "es5,dom", + "--traceResolution", + "--explainFiles", + ] + : ["-p", "project1", "--explainFiles"]; } diff --git a/src/testRunner/unittests/helpers/node10Result.ts b/src/testRunner/unittests/helpers/node10Result.ts index 7ab2f528b423d..17c8722567743 100644 --- a/src/testRunner/unittests/helpers/node10Result.ts +++ b/src/testRunner/unittests/helpers/node10Result.ts @@ -26,7 +26,11 @@ export function getFsConentsForNode10ResultAtTypesPackageJson(packageName: strin ); } -export function getFsContentsForNode10ResultPackageJson(packageName: string, addTypes: boolean, addTypesCondition: boolean) { +export function getFsContentsForNode10ResultPackageJson( + packageName: string, + addTypes: boolean, + addTypesCondition: boolean, +) { return JSON.stringify( { name: packageName, @@ -60,21 +64,39 @@ function mjs(packageName: string) { export function getFsContentsForNode10Result(): FsContents { return { - "/home/src/projects/project/node_modules/@types/bar/package.json": getFsConentsForNode10ResultAtTypesPackageJson("bar", /*addTypesCondition*/ false), + "/home/src/projects/project/node_modules/@types/bar/package.json": + getFsConentsForNode10ResultAtTypesPackageJson("bar", /*addTypesCondition*/ false), "/home/src/projects/project/node_modules/@types/bar/index.d.ts": getFsContentsForNode10ResultDts("bar"), - "/home/src/projects/project/node_modules/bar/package.json": getFsContentsForNode10ResultPackageJson("bar", /*addTypes*/ false, /*addTypesCondition*/ false), + "/home/src/projects/project/node_modules/bar/package.json": getFsContentsForNode10ResultPackageJson( + "bar", + /*addTypes*/ false, + /*addTypesCondition*/ false, + ), "/home/src/projects/project/node_modules/bar/index.js": js("bar"), "/home/src/projects/project/node_modules/bar/index.mjs": mjs("bar"), - "/home/src/projects/project/node_modules/foo/package.json": getFsContentsForNode10ResultPackageJson("foo", /*addTypes*/ true, /*addTypesCondition*/ false), + "/home/src/projects/project/node_modules/foo/package.json": getFsContentsForNode10ResultPackageJson( + "foo", + /*addTypes*/ true, + /*addTypesCondition*/ false, + ), "/home/src/projects/project/node_modules/foo/index.js": js("foo"), "/home/src/projects/project/node_modules/foo/index.mjs": mjs("foo"), "/home/src/projects/project/node_modules/foo/index.d.ts": getFsContentsForNode10ResultDts("foo"), - "/home/src/projects/project/node_modules/@types/bar2/package.json": getFsConentsForNode10ResultAtTypesPackageJson("bar2", /*addTypesCondition*/ true), + "/home/src/projects/project/node_modules/@types/bar2/package.json": + getFsConentsForNode10ResultAtTypesPackageJson("bar2", /*addTypesCondition*/ true), "/home/src/projects/project/node_modules/@types/bar2/index.d.ts": getFsContentsForNode10ResultDts("bar2"), - "/home/src/projects/project/node_modules/bar2/package.json": getFsContentsForNode10ResultPackageJson("bar2", /*addTypes*/ false, /*addTypesCondition*/ false), + "/home/src/projects/project/node_modules/bar2/package.json": getFsContentsForNode10ResultPackageJson( + "bar2", + /*addTypes*/ false, + /*addTypesCondition*/ false, + ), "/home/src/projects/project/node_modules/bar2/index.js": js("bar2"), "/home/src/projects/project/node_modules/bar2/index.mjs": mjs("bar2"), - "/home/src/projects/project/node_modules/foo2/package.json": getFsContentsForNode10ResultPackageJson("foo2", /*addTypes*/ true, /*addTypesCondition*/ true), + "/home/src/projects/project/node_modules/foo2/package.json": getFsContentsForNode10ResultPackageJson( + "foo2", + /*addTypes*/ true, + /*addTypesCondition*/ true, + ), "/home/src/projects/project/node_modules/foo2/index.js": js("foo2"), "/home/src/projects/project/node_modules/foo2/index.mjs": mjs("foo2"), "/home/src/projects/project/node_modules/foo2/index.d.ts": getFsContentsForNode10ResultDts("foo2"), diff --git a/src/testRunner/unittests/helpers/solutionBuilder.ts b/src/testRunner/unittests/helpers/solutionBuilder.ts index da77ca79ed0b3..06e064694d3bc 100644 --- a/src/testRunner/unittests/helpers/solutionBuilder.ts +++ b/src/testRunner/unittests/helpers/solutionBuilder.ts @@ -23,13 +23,22 @@ export function createSolutionBuilderHostForBaseline( ) { if (sys instanceof fakes.System) makeSystemReadyForBaseline(sys, versionToWrite); const { cb } = commandLineCallbacks(sys, originalRead); - const host = ts.createSolutionBuilderHost(sys, /*createProgram*/ undefined, ts.createDiagnosticReporter(sys, /*pretty*/ true), ts.createBuilderStatusReporter(sys, /*pretty*/ true)); + const host = ts.createSolutionBuilderHost( + sys, + /*createProgram*/ undefined, + ts.createDiagnosticReporter(sys, /*pretty*/ true), + ts.createBuilderStatusReporter(sys, /*pretty*/ true), + ); host.afterProgramEmitAndDiagnostics = cb; host.afterEmitBundle = cb; return host; } -export function createSolutionBuilder(system: TestServerHost, rootNames: readonly string[], originalRead?: TestServerHost["readFile"]) { +export function createSolutionBuilder( + system: TestServerHost, + rootNames: readonly string[], + originalRead?: TestServerHost["readFile"], +) { const host = createSolutionBuilderHostForBaseline(system, /*versionToWrite*/ undefined, originalRead); return ts.createSolutionBuilder(host, rootNames, {}); } @@ -40,7 +49,11 @@ export function ensureErrorFreeBuild(host: TestServerHost, rootNames: readonly s assert.equal(host.getOutput().length, 0, JSON.stringify(host.getOutput(), /*replacer*/ undefined, " ")); } -export function solutionBuildWithBaseline(sys: TestServerHost, solutionRoots: readonly string[], originalRead?: TestServerHost["readFile"]) { +export function solutionBuildWithBaseline( + sys: TestServerHost, + solutionRoots: readonly string[], + originalRead?: TestServerHost["readFile"], +) { const originalReadFile = sys.readFile; const originalWrite = sys.write; const originalWriteFile = sys.writeFile; @@ -60,6 +73,10 @@ export function solutionBuildWithBaseline(sys: TestServerHost, solutionRoots: re return sys; } -export function createSystemWithSolutionBuild(solutionRoots: readonly string[], files: FileOrFolderOrSymLinkMap | readonly FileOrFolderOrSymLink[], params?: TestServerHostCreationParameters) { +export function createSystemWithSolutionBuild( + solutionRoots: readonly string[], + files: FileOrFolderOrSymLinkMap | readonly FileOrFolderOrSymLink[], + params?: TestServerHostCreationParameters, +) { return solutionBuildWithBaseline(createWatchedSystem(files, params), solutionRoots); } diff --git a/src/testRunner/unittests/helpers/tsc.ts b/src/testRunner/unittests/helpers/tsc.ts index 29abecfcfc5c7..f28a91041bcec 100644 --- a/src/testRunner/unittests/helpers/tsc.ts +++ b/src/testRunner/unittests/helpers/tsc.ts @@ -73,7 +73,10 @@ export function testTscCompileLike(input: TestTscCompileLike) { const fs = inputFs.shadow(); // Create system - const sys = new fakes.System(fs, { executingFilePath: `${fs.meta.get("defaultLibLocation")}/tsc`, env: environmentVariables }) as TscCompileSystem; + const sys = new fakes.System(fs, { + executingFilePath: `${fs.meta.get("defaultLibLocation")}/tsc`, + env: environmentVariables, + }) as TscCompileSystem; sys.storeFilesChangingSignatureDuringEmit = true; sys.write(`${sys.getExecutingFilePath()} ${commandLineArgs.join(" ")}\n`); sys.exit = exitCode => sys.exitCode = exitCode; @@ -82,9 +85,9 @@ export function testTscCompileLike(input: TestTscCompileLike) { additionalBaseline?.(sys); fs.makeReadonly(); sys.baseLine = () => { - const baseFsPatch = diffWithInitial ? - inputFs.diff(initialFs, { includeChangedFileWithSameContent: true }) : - inputFs.diff(/*base*/ undefined, { baseIsNotShadowRoot: true }); + const baseFsPatch = diffWithInitial + ? inputFs.diff(initialFs, { includeChangedFileWithSameContent: true }) + : inputFs.diff(/*base*/ undefined, { baseIsNotShadowRoot: true }); const patch = fs.diff(inputFs, { includeChangedFileWithSameContent: true }); return { file: tscBaselineName(scenario, subScenario, commandLineArgs), @@ -155,7 +158,12 @@ export function testTscCompile(input: TestTscCompile) { } function additionalBaseline(sys: TscCompileSystem) { - const { baselineSourceMap, baselineReadFileCalls, baselinePrograms: shouldBaselinePrograms, baselineDependencies } = input; + const { + baselineSourceMap, + baselineReadFileCalls, + baselinePrograms: shouldBaselinePrograms, + baselineDependencies, + } = input; if (input.computeDtsSignatures) storeDtsSignatures(sys, getPrograms!()); if (shouldBaselinePrograms) { const baseline: string[] = []; @@ -178,7 +186,10 @@ function storeDtsSignatures(sys: TscCompileSystem, programs: readonly CommandLin if (!buildInfoPath) continue; sys.dtsSignaures ??= new Map(); const dtsSignatureData = new Map(); - sys.dtsSignaures.set(`${toPathWithSystem(sys, buildInfoPath)}.readable.baseline.txt` as ts.Path, dtsSignatureData); + sys.dtsSignaures.set( + `${toPathWithSystem(sys, buildInfoPath)}.readable.baseline.txt` as ts.Path, + dtsSignatureData, + ); const state = builderProgram.getState(); state.hasCalledUpdateShapeSignature?.forEach(resolvedPath => { const file = program.getSourceFileByPath(resolvedPath); @@ -190,8 +201,13 @@ function storeDtsSignatures(sys: TscCompileSystem, programs: readonly CommandLin /*cancellationToken*/ undefined, sys, (signature, sourceFiles) => { - const exportedModules = ts.BuilderState.getExportedModules(state.exportedModulesMap && sourceFiles[0].exportedModulesFromDeclarationEmit); - dtsSignatureData.set(relativeToBuildInfo(resolvedPath), { signature, exportedModules: exportedModules && ts.arrayFrom(exportedModules.keys(), relativeToBuildInfo) }); + const exportedModules = ts.BuilderState.getExportedModules( + state.exportedModulesMap && sourceFiles[0].exportedModulesFromDeclarationEmit, + ); + dtsSignatureData.set(relativeToBuildInfo(resolvedPath), { + signature, + exportedModules: exportedModules && ts.arrayFrom(exportedModules.keys(), relativeToBuildInfo), + }); }, ); }); @@ -199,8 +215,12 @@ function storeDtsSignatures(sys: TscCompileSystem, programs: readonly CommandLin function relativeToBuildInfo(path: string) { const currentDirectory = program.getCurrentDirectory(); const getCanonicalFileName = ts.createGetCanonicalFileName(program.useCaseSensitiveFileNames()); - const buildInfoDirectory = ts.getDirectoryPath(ts.getNormalizedAbsolutePath(buildInfoPath!, currentDirectory)); - return ts.ensurePathIsNonModuleName(ts.getRelativePathFromDirectory(buildInfoDirectory, path, getCanonicalFileName)); + const buildInfoDirectory = ts.getDirectoryPath( + ts.getNormalizedAbsolutePath(buildInfoPath!, currentDirectory), + ); + return ts.ensurePathIsNonModuleName( + ts.getRelativePathFromDirectory(buildInfoDirectory, path, getCanonicalFileName), + ); } } } @@ -221,7 +241,10 @@ export interface VerifyTscCompileLike { /** * Verify by baselining after initializing FS and custom compile */ -export function verifyTscCompileLike(verifier: (input: T) => { baseLine: TscCompileSystem["baseLine"]; }, input: T) { +export function verifyTscCompileLike( + verifier: (input: T) => { baseLine: TscCompileSystem["baseLine"]; }, + input: T, +) { describe(`tsc ${input.commandLineArgs.join(" ")} ${input.scenario}:: ${input.subScenario}`, () => { describe(input.scenario, () => { describe(input.subScenario, () => { @@ -279,26 +302,44 @@ function verifyTscEditDiscrepancies({ const incrementalBuildText = newSys.readFile(outputFile); if (ts.isBuildInfoFile(outputFile)) { // Check only presence and absence and not text as we will do that for readable baseline - if (!sys.fileExists(`${outputFile}.readable.baseline.txt`)) addBaseline(`Readable baseline not present in clean build:: File:: ${outputFile}`); - if (!newSys.fileExists(`${outputFile}.readable.baseline.txt`)) addBaseline(`Readable baseline not present in incremental build:: File:: ${outputFile}`); - verifyPresenceAbsence(incrementalBuildText, cleanBuildText, `Incremental and clean tsbuildinfo file presence differs:: File:: ${outputFile}`); + if (!sys.fileExists(`${outputFile}.readable.baseline.txt`)) { + addBaseline(`Readable baseline not present in clean build:: File:: ${outputFile}`); + } + if (!newSys.fileExists(`${outputFile}.readable.baseline.txt`)) { + addBaseline(`Readable baseline not present in incremental build:: File:: ${outputFile}`); + } + verifyPresenceAbsence( + incrementalBuildText, + cleanBuildText, + `Incremental and clean tsbuildinfo file presence differs:: File:: ${outputFile}`, + ); } else if (!ts.fileExtensionIs(outputFile, ".tsbuildinfo.readable.baseline.txt")) { verifyTextEqual(incrementalBuildText, cleanBuildText, `File: ${outputFile}`); } else if (incrementalBuildText !== cleanBuildText) { // Verify build info without affectedFilesPendingEmit - const { buildInfo: incrementalBuildInfo, readableBuildInfo: incrementalReadableBuildInfo } = getBuildInfoForIncrementalCorrectnessCheck(incrementalBuildText); - const { buildInfo: cleanBuildInfo, readableBuildInfo: cleanReadableBuildInfo } = getBuildInfoForIncrementalCorrectnessCheck(cleanBuildText); + const { buildInfo: incrementalBuildInfo, readableBuildInfo: incrementalReadableBuildInfo } = + getBuildInfoForIncrementalCorrectnessCheck(incrementalBuildText); + const { buildInfo: cleanBuildInfo, readableBuildInfo: cleanReadableBuildInfo } = + getBuildInfoForIncrementalCorrectnessCheck(cleanBuildText); const dtsSignaures = sys.dtsSignaures?.get(outputFile); - verifyTextEqual(incrementalBuildInfo, cleanBuildInfo, `TsBuild info text without affectedFilesPendingEmit:: ${outputFile}::`); + verifyTextEqual( + incrementalBuildInfo, + cleanBuildInfo, + `TsBuild info text without affectedFilesPendingEmit:: ${outputFile}::`, + ); // Verify file info sigantures verifyMapLike( incrementalReadableBuildInfo?.program?.fileInfos as ReadableProgramMultiFileEmitBuildInfo["fileInfos"], cleanReadableBuildInfo?.program?.fileInfos as ReadableProgramMultiFileEmitBuildInfo["fileInfos"], (key, incrementalFileInfo, cleanFileInfo) => { const dtsForKey = dtsSignaures?.get(key); - if (!incrementalFileInfo || !cleanFileInfo || incrementalFileInfo.signature !== cleanFileInfo.signature && (!dtsForKey || incrementalFileInfo.signature !== dtsForKey.signature)) { + if ( + !incrementalFileInfo || !cleanFileInfo + || incrementalFileInfo.signature !== cleanFileInfo.signature + && (!dtsForKey || incrementalFileInfo.signature !== dtsForKey.signature) + ) { return [ `Incremental signature is neither dts signature nor file version for File:: ${key}`, `Incremental:: ${JSON.stringify(incrementalFileInfo, /*replacer*/ undefined, 2)}`, @@ -318,14 +359,16 @@ function verifyTscEditDiscrepancies({ (key, incrementalReferenceSet, cleanReferenceSet) => { const dtsForKey = dtsSignaures?.get(key); if ( - !ts.arrayIsEqualTo(incrementalReferenceSet, cleanReferenceSet) && - (!dtsForKey || !ts.arrayIsEqualTo(incrementalReferenceSet, dtsForKey.exportedModules)) + !ts.arrayIsEqualTo(incrementalReferenceSet, cleanReferenceSet) + && (!dtsForKey || !ts.arrayIsEqualTo(incrementalReferenceSet, dtsForKey.exportedModules)) ) { return [ `Incremental Reference set is neither from dts nor files reference map for File:: ${key}::`, `Incremental:: ${JSON.stringify(incrementalReferenceSet, /*replacer*/ undefined, 2)}`, `Clean:: ${JSON.stringify(cleanReferenceSet, /*replacer*/ undefined, 2)}`, - `DtsExportsMap:: ${JSON.stringify(dtsForKey?.exportedModules, /*replacer*/ undefined, 2)}`, + `DtsExportsMap:: ${ + JSON.stringify(dtsForKey?.exportedModules, /*replacer*/ undefined, 2) + }`, ]; } }, @@ -344,8 +387,12 @@ function verifyTscEditDiscrepancies({ incrementalReadableBuildInfo.program.affectedFilesPendingEmit.forEach(([actualFileOrArray]) => { const actualFile = ts.isString(actualFileOrArray) ? actualFileOrArray : actualFileOrArray[0]; expectedIndex = ts.findIndex( - (cleanReadableBuildInfo!.program! as ReadableProgramMultiFileEmitBuildInfo).affectedFilesPendingEmit, - ([expectedFileOrArray]) => actualFile === (ts.isString(expectedFileOrArray) ? expectedFileOrArray : expectedFileOrArray[0]), + (cleanReadableBuildInfo!.program! as ReadableProgramMultiFileEmitBuildInfo) + .affectedFilesPendingEmit, + ([expectedFileOrArray]) => + actualFile + === (ts.isString(expectedFileOrArray) ? expectedFileOrArray + : expectedFileOrArray[0]), expectedIndex, ); if (expectedIndex === -1) { @@ -361,7 +408,9 @@ function verifyTscEditDiscrepancies({ } } } - if (!headerAdded && discrepancyExplanation) addBaseline("*** Supplied discrepancy explanation but didnt file any difference"); + if (!headerAdded && discrepancyExplanation) { + addBaseline("*** Supplied discrepancy explanation but didnt file any difference"); + } return baselines; function verifyTextEqual(incrementalText: string | undefined, cleanText: string | undefined, message: string) { @@ -412,7 +461,10 @@ function verifyTscEditDiscrepancies({ function addBaseline(...text: string[]) { if (!baselines || !headerAdded) { - (baselines ||= []).push(`${index}:: ${caption}`, ...(discrepancyExplanation?.() || ["*** Needs explanation"])); + (baselines ||= []).push( + `${index}:: ${caption}`, + ...(discrepancyExplanation?.() || ["*** Needs explanation"]), + ); headerAdded = true; } baselines.push(...text); @@ -425,13 +477,24 @@ function getBuildInfoForIncrementalCorrectnessCheck(text: string | undefined): { } { if (!text) return { buildInfo: text }; const readableBuildInfo = JSON.parse(text) as ReadableBuildInfo; - let sanitizedFileInfos: ts.MapLike | ReadableProgramBuildInfoFileInfo, "signature" | "original"> & { signature: undefined; original: undefined; }> | undefined; + let sanitizedFileInfos: + | ts.MapLike< + | string + | Omit< + | ReadableProgramBuildInfoFileInfo + | ReadableProgramBuildInfoFileInfo, + "signature" | "original" + > + & { signature: undefined; original: undefined; } + > + | undefined; if (readableBuildInfo.program?.fileInfos) { sanitizedFileInfos = {}; for (const id in readableBuildInfo.program.fileInfos) { if (ts.hasProperty(readableBuildInfo.program.fileInfos, id)) { const info = readableBuildInfo.program.fileInfos[id]; - sanitizedFileInfos[id] = ts.isString(info) ? info : { ...info, signature: undefined, original: undefined }; + sanitizedFileInfos[id] = ts.isString(info) ? info + : { ...info, signature: undefined, original: undefined }; } } } @@ -538,8 +601,9 @@ export function verifyTsc({ }); return { file, - text: `currentDirectory:: ${sys.getCurrentDirectory()} useCaseSensitiveFileNames: ${sys.useCaseSensitiveFileNames}\r\n` + - texts.join("\r\n"), + text: + `currentDirectory:: ${sys.getCurrentDirectory()} useCaseSensitiveFileNames: ${sys.useCaseSensitiveFileNames}\r\n` + + texts.join("\r\n"), }; }, })); diff --git a/src/testRunner/unittests/helpers/tscWatch.ts b/src/testRunner/unittests/helpers/tscWatch.ts index e21c7de9f9f36..e800f8562a42f 100644 --- a/src/testRunner/unittests/helpers/tscWatch.ts +++ b/src/testRunner/unittests/helpers/tscWatch.ts @@ -29,7 +29,11 @@ export const commonFile2: File = { content: "let y = 1", }; -export type WatchOrSolution = void | ts.SolutionBuilder | ts.WatchOfConfigFile | ts.WatchOfFilesAndCompilerOptions; +export type WatchOrSolution = + | void + | ts.SolutionBuilder + | ts.WatchOfConfigFile + | ts.WatchOfFilesAndCompilerOptions; export interface TscWatchCompileChange { caption: string; edit: (sys: TscWatchSystem) => void; @@ -43,7 +47,9 @@ export interface TscWatchCheckOptions { baselineSourceMap?: boolean; baselineDependencies?: boolean; } -export interface TscWatchCompileBase extends TscWatchCheckOptions { +export interface TscWatchCompileBase + extends TscWatchCheckOptions +{ scenario: string; subScenario: string; commandLineArgs: readonly string[]; @@ -101,7 +107,10 @@ export interface TestServerHostWithTimeoutLogging { export type TscWatchSystem = TestServerHostTrackingWrittenFiles & TestServerHostWithTimeoutLogging; -function changeToTestServerHostWithTimeoutLogging(inputHost: TestServerHostTrackingWrittenFiles, baseline: string[]): TscWatchSystem { +function changeToTestServerHostWithTimeoutLogging( + inputHost: TestServerHostTrackingWrittenFiles, + baseline: string[], +): TscWatchSystem { const host = inputHost as TscWatchSystem; const originalRunQueuedTimeoutCallbacks = host.runQueuedTimeoutCallbacks; const originalRunQueuedImmediateCallbacks = host.runQueuedImmediateCallbacks; @@ -117,7 +126,13 @@ function changeToTestServerHostWithTimeoutLogging(inputHost: TestServerHostTrack function runQueuedTimeoutCallbacks(timeoutId?: number) { baseline.push(`Before running ${host.timeoutCallbacks.log()}`); - if (timeoutId !== undefined) baseline.push(`Invoking ${host.timeoutCallbacks.callbackType} callback:: timeoutId:: ${timeoutId}:: ${host.timeoutCallbacks.map[timeoutId].args[0]}`); + if (timeoutId !== undefined) { + baseline.push( + `Invoking ${host.timeoutCallbacks.callbackType} callback:: timeoutId:: ${timeoutId}:: ${ + host.timeoutCallbacks.map[timeoutId].args[0] + }`, + ); + } originalRunQueuedTimeoutCallbacks.call(host, timeoutId); baseline.push(`After running ${host.timeoutCallbacks.log()}`); } @@ -138,13 +153,18 @@ export interface BaselineBase { export interface Baseline extends BaselineBase, CommandLineCallbacks { } -export function createBaseline(system: TestServerHost, modifySystem?: (sys: TestServerHost, originalRead: TestServerHost["readFile"]) => void): Baseline { +export function createBaseline( + system: TestServerHost, + modifySystem?: (sys: TestServerHost, originalRead: TestServerHost["readFile"]) => void, +): Baseline { const originalRead = system.readFile; const initialSys = patchHostForBuildInfoReadWrite(system); modifySystem?.(initialSys, originalRead); const baseline: string[] = []; const sys = changeToTestServerHostWithTimeoutLogging(changeToHostTrackingWrittenFiles(initialSys), baseline); - baseline.push(`currentDirectory:: ${sys.getCurrentDirectory()} useCaseSensitiveFileNames: ${sys.useCaseSensitiveFileNames}`); + baseline.push( + `currentDirectory:: ${sys.getCurrentDirectory()} useCaseSensitiveFileNames: ${sys.useCaseSensitiveFileNames}`, + ); baseline.push("Input::"); sys.diff(baseline); const { cb, getPrograms } = commandLineCallbacks(sys); @@ -152,18 +172,28 @@ export function createBaseline(system: TestServerHost, modifySystem?: (sys: Test } export function createSolutionBuilderWithWatchHostForBaseline(sys: TestServerHost, cb: ts.ExecuteCommandLineCallbacks) { - const host = ts.createSolutionBuilderWithWatchHost(sys, /*createProgram*/ undefined, ts.createDiagnosticReporter(sys, /*pretty*/ true), ts.createBuilderStatusReporter(sys, /*pretty*/ true), ts.createWatchStatusReporter(sys, /*pretty*/ true)); + const host = ts.createSolutionBuilderWithWatchHost( + sys, + /*createProgram*/ undefined, + ts.createDiagnosticReporter(sys, /*pretty*/ true), + ts.createBuilderStatusReporter(sys, /*pretty*/ true), + ts.createWatchStatusReporter(sys, /*pretty*/ true), + ); host.afterProgramEmitAndDiagnostics = cb; host.afterEmitBundle = cb; return host; } -interface CreateWatchCompilerHostOfConfigFileForBaseline extends ts.CreateWatchCompilerHostOfConfigFileInput { +interface CreateWatchCompilerHostOfConfigFileForBaseline + extends ts.CreateWatchCompilerHostOfConfigFileInput +{ system: TestServerHost; cb: ts.ExecuteCommandLineCallbacks; } -export function createWatchCompilerHostOfConfigFileForBaseline( +export function createWatchCompilerHostOfConfigFileForBaseline< + T extends ts.BuilderProgram = ts.EmitAndSemanticDiagnosticsBuilderProgram, +>( input: CreateWatchCompilerHostOfConfigFileForBaseline, ) { const host = ts.createWatchCompilerHostOfConfigFile({ @@ -175,11 +205,15 @@ export function createWatchCompilerHostOfConfigFileForBaseline extends ts.CreateWatchCompilerHostOfFilesAndCompilerOptionsInput { +interface CreateWatchCompilerHostOfFilesAndCompilerOptionsForBaseline + extends ts.CreateWatchCompilerHostOfFilesAndCompilerOptionsInput +{ system: TestServerHost; cb: ts.ExecuteCommandLineCallbacks; } -export function createWatchCompilerHostOfFilesAndCompilerOptionsForBaseline( +export function createWatchCompilerHostOfFilesAndCompilerOptionsForBaseline< + T extends ts.BuilderProgram = ts.EmitAndSemanticDiagnosticsBuilderProgram, +>( input: CreateWatchCompilerHostOfFilesAndCompilerOptionsForBaseline, ) { const host = ts.createWatchCompilerHostOfFilesAndCompilerOptions({ @@ -191,7 +225,10 @@ export function createWatchCompilerHostOfFilesAndCompilerOptionsForBaseline(host: ts.WatchCompilerHost, cb: ts.ExecuteCommandLineCallbacks) { +function updateWatchHostForBaseline( + host: ts.WatchCompilerHost, + cb: ts.ExecuteCommandLineCallbacks, +) { const emitFilesAndReportErrors = host.afterProgramCreate!; host.afterProgramCreate = builderProgram => { emitFilesAndReportErrors.call(host, builderProgram); @@ -200,7 +237,12 @@ function updateWatchHostForBaseline(host: ts.WatchC return host; } -export function applyEdit(sys: BaselineBase["sys"], baseline: BaselineBase["baseline"], edit: TscWatchCompileChange["edit"], caption?: TscWatchCompileChange["caption"]) { +export function applyEdit( + sys: BaselineBase["sys"], + baseline: BaselineBase["baseline"], + edit: TscWatchCompileChange["edit"], + caption?: TscWatchCompileChange["caption"], +) { const oldSnap = sys.snap(); baseline.push(`Change::${caption ? " " + caption : ""}`, ""); edit(sys); @@ -254,7 +296,10 @@ export function runWatchBaseline readonly CommandLineProgram[]; } -export function watchBaseline({ baseline, getPrograms, oldPrograms, sys, oldSnap, baselineSourceMap, baselineDependencies }: WatchBaseline) { +export function watchBaseline( + { baseline, getPrograms, oldPrograms, sys, oldSnap, baselineSourceMap, baselineDependencies }: WatchBaseline, +) { if (baselineSourceMap) generateSourceMapBaselineFiles(sys); sys.serializeOutput(baseline); const programs = baselinePrograms(baseline, getPrograms, oldPrograms, baselineDependencies); diff --git a/src/testRunner/unittests/helpers/tsserver.ts b/src/testRunner/unittests/helpers/tsserver.ts index ba2c9aac2e52b..e2188f417ce18 100644 --- a/src/testRunner/unittests/helpers/tsserver.ts +++ b/src/testRunner/unittests/helpers/tsserver.ts @@ -44,7 +44,10 @@ export const customTypesMap = { }; function replaceAll(source: string, searchValue: string, replaceValue: string): string { - let result: string | undefined = (source as string & { replaceAll: typeof source.replace; }).replaceAll?.(searchValue, replaceValue); + let result: string | undefined = (source as string & { replaceAll: typeof source.replace; }).replaceAll?.( + searchValue, + replaceValue, + ); if (result !== undefined) { return result; @@ -147,15 +150,27 @@ export function createLoggerWritingToConsole(host: TestServerHost): Logger { function sanitizeLog(s: string): string { s = s.replace(/Elapsed::?\s*\d+(?:\.\d+)?ms/g, "Elapsed:: *ms"); s = s.replace(/"updateGraphDurationMs":\s*\d+(?:\.\d+)?/g, `"updateGraphDurationMs": *`); - s = s.replace(/"createAutoImportProviderProgramDurationMs":\s*\d+(?:\.\d+)?/g, `"createAutoImportProviderProgramDurationMs": *`); + s = s.replace( + /"createAutoImportProviderProgramDurationMs":\s*\d+(?:\.\d+)?/g, + `"createAutoImportProviderProgramDurationMs": *`, + ); s = replaceAll(s, ts.version, "FakeVersion"); s = s.replace(/getCompletionData: Get current token: \d+(?:\.\d+)?/g, `getCompletionData: Get current token: *`); s = s.replace(/getCompletionData: Is inside comment: \d+(?:\.\d+)?/g, `getCompletionData: Is inside comment: *`); s = s.replace(/getCompletionData: Get previous token: \d+(?:\.\d+)?/g, `getCompletionData: Get previous token: *`); - s = s.replace(/getCompletionsAtPosition: isCompletionListBlocker: \d+(?:\.\d+)?/g, `getCompletionsAtPosition: isCompletionListBlocker: *`); + s = s.replace( + /getCompletionsAtPosition: isCompletionListBlocker: \d+(?:\.\d+)?/g, + `getCompletionsAtPosition: isCompletionListBlocker: *`, + ); s = s.replace(/getCompletionData: Semantic work: \d+(?:\.\d+)?/g, `getCompletionData: Semantic work: *`); - s = s.replace(/getCompletionsAtPosition: getCompletionEntriesFromSymbols: \d+(?:\.\d+)?/g, `getCompletionsAtPosition: getCompletionEntriesFromSymbols: *`); - s = s.replace(/forEachExternalModuleToImportFrom autoImportProvider: \d+(?:\.\d+)?/g, `forEachExternalModuleToImportFrom autoImportProvider: *`); + s = s.replace( + /getCompletionsAtPosition: getCompletionEntriesFromSymbols: \d+(?:\.\d+)?/g, + `getCompletionsAtPosition: getCompletionEntriesFromSymbols: *`, + ); + s = s.replace( + /forEachExternalModuleToImportFrom autoImportProvider: \d+(?:\.\d+)?/g, + `forEachExternalModuleToImportFrom autoImportProvider: *`, + ); s = s.replace(/getExportInfoMap: done in \d+(?:\.\d+)?/g, `getExportInfoMap: done in *`); s = s.replace(/collectAutoImports: \d+(?:\.\d+)?/g, `collectAutoImports: *`); s = s.replace(/continuePreviousIncompleteResponse: \d+(?:\.\d+)?/g, `continuePreviousIncompleteResponse: *`); @@ -167,7 +182,11 @@ function sanitizeLog(s: string): string { export function createLoggerWithInMemoryLogs(host: TestServerHost): Logger { const logger = createHasErrorMessageLogger(); const logs: string[] = []; - if (host) logs.push(`currentDirectory:: ${host.getCurrentDirectory()} useCaseSensitiveFileNames: ${host.useCaseSensitiveFileNames}`); + if (host) { + logs.push( + `currentDirectory:: ${host.getCurrentDirectory()} useCaseSensitiveFileNames: ${host.useCaseSensitiveFileNames}`, + ); + } return handleLoggerGroup({ ...logger, logs, @@ -179,13 +198,18 @@ export function createLoggerWithInMemoryLogs(host: TestServerHost): Logger { export function baselineTsserverLogs(scenario: string, subScenario: string, sessionOrService: { logger: Logger; }) { ts.Debug.assert(sessionOrService.logger.logs?.length); // Ensure caller used in memory logger - Harness.Baseline.runBaseline(`tsserver/${scenario}/${subScenario.split(" ").join("-")}.js`, sessionOrService.logger.logs.join("\r\n")); + Harness.Baseline.runBaseline( + `tsserver/${scenario}/${subScenario.split(" ").join("-")}.js`, + sessionOrService.logger.logs.join("\r\n"), + ); } export function appendAllScriptInfos(session: TestSession) { session.logger.log(""); session.logger.log(`ScriptInfos:`); - session.getProjectService().filenameToScriptInfo.forEach(info => session.logger.log(`path: ${info.path} fileName: ${info.fileName}`)); + session.getProjectService().filenameToScriptInfo.forEach(info => + session.logger.log(`path: ${info.path} fileName: ${info.fileName}`) + ); session.logger.log(""); } @@ -212,7 +236,11 @@ interface TypesRegistryFile { entries: ts.MapLike>; } -function loadTypesRegistryFile(typesRegistryFilePath: string, host: TestServerHost, log: ts.server.typingsInstaller.Log): Map> { +function loadTypesRegistryFile( + typesRegistryFilePath: string, + host: TestServerHost, + log: ts.server.typingsInstaller.Log, +): Map> { if (!host.fileExists(typesRegistryFilePath)) { if (log.isEnabled()) { log.writeLine(`Types registry file '${typesRegistryFilePath}' does not exist`); @@ -225,7 +253,11 @@ function loadTypesRegistryFile(typesRegistryFilePath: string, host: TestServerHo } catch (e) { if (log.isEnabled()) { - log.writeLine(`Error when loading types registry file '${typesRegistryFilePath}': ${(e as Error).message}, ${(e as Error).stack}`); + log.writeLine( + `Error when loading types registry file '${typesRegistryFilePath}': ${(e as Error).message}, ${ + (e as Error).stack + }`, + ); } return new Map>(); } @@ -233,7 +265,10 @@ function loadTypesRegistryFile(typesRegistryFilePath: string, host: TestServerHo const typesRegistryPackageName = "types-registry"; function getTypesRegistryFileLocation(globalTypingsCacheLocation: string): string { - return ts.combinePaths(ts.normalizeSlashes(globalTypingsCacheLocation), `node_modules/${typesRegistryPackageName}/index.json`); + return ts.combinePaths( + ts.normalizeSlashes(globalTypingsCacheLocation), + `node_modules/${typesRegistryPackageName}/index.json`, + ); } export class TestTypingsInstallerWorker extends ts.server.typingsInstaller.TypingsInstaller { @@ -273,11 +308,11 @@ export class TestTypingsInstallerWorker extends ts.server.typingsInstaller.Typin path: getTypesRegistryFileLocation(globalTypingsCacheLocation), content: JSON.stringify( createTypesRegistryFileContent( - typesRegistry ? - ts.isString(typesRegistry) ? - [typesRegistry] : - typesRegistry : - ts.emptyArray, + typesRegistry + ? ts.isString(typesRegistry) + ? [typesRegistry] + : typesRegistry + : ts.emptyArray, ), undefined, " ", @@ -286,7 +321,11 @@ export class TestTypingsInstallerWorker extends ts.server.typingsInstaller.Typin if (this.log.isEnabled()) { this.log.writeLine(`TI:: Updated ${typesRegistryPackageName} npm package`); } - this.typesRegistry = loadTypesRegistryFile(getTypesRegistryFileLocation(globalTypingsCacheLocation), installTypingHost, this.log); + this.typesRegistry = loadTypesRegistryFile( + getTypesRegistryFileLocation(globalTypingsCacheLocation), + installTypingHost, + this.log, + ); if (this.log.isEnabled()) { (installTypingHost as TestSessionAndServiceHost).baselineHost("TI:: typing installer creation complete"); } @@ -299,7 +338,9 @@ export class TestTypingsInstallerWorker extends ts.server.typingsInstaller.Typin this.postExecActions = []; for (const action of actionsToRun) { if (this.log.isEnabled()) { - this.log.writeLine(`#${action.requestId} with arguments'${JSON.stringify(action.packageNames)}':: ${action.success}`); + this.log.writeLine( + `#${action.requestId} with arguments'${JSON.stringify(action.packageNames)}':: ${action.success}`, + ); } action.callback(action.success); } @@ -313,7 +354,12 @@ export class TestTypingsInstallerWorker extends ts.server.typingsInstaller.Typin return this.installTypingHost; } - installWorker(requestId: number, packageNames: string[], _cwd: string, cb: ts.server.typingsInstaller.RequestCompletedAction): void { + installWorker( + requestId: number, + packageNames: string[], + _cwd: string, + cb: ts.server.typingsInstaller.RequestCompletedAction, + ): void { if (this.log.isEnabled()) { this.log.writeLine(`#${requestId} with arguments'${JSON.stringify(packageNames)}'.`); } @@ -328,12 +374,26 @@ export class TestTypingsInstallerWorker extends ts.server.typingsInstaller.Typin else this.projectService.watchTypingLocations(response); } - enqueueInstallTypingsRequest(project: ts.server.Project, typeAcquisition: ts.TypeAcquisition, unresolvedImports: ts.SortedReadonlyArray) { - const request = ts.server.createInstallTypingsRequest(project, typeAcquisition, unresolvedImports, this.globalTypingsCacheLocation); + enqueueInstallTypingsRequest( + project: ts.server.Project, + typeAcquisition: ts.TypeAcquisition, + unresolvedImports: ts.SortedReadonlyArray, + ) { + const request = ts.server.createInstallTypingsRequest( + project, + typeAcquisition, + unresolvedImports, + this.globalTypingsCacheLocation, + ); this.install(request); } - addPostExecAction(stdout: string | string[], requestId: number, packageNames: string[], cb: ts.server.typingsInstaller.RequestCompletedAction) { + addPostExecAction( + stdout: string | string[], + requestId: number, + packageNames: string[], + cb: ts.server.typingsInstaller.RequestCompletedAction, + ) { const out = ts.isString(stdout) ? stdout : createNpmPackageJsonString(stdout); const action: PostExecAction = { success: !!out, @@ -345,7 +405,9 @@ export class TestTypingsInstallerWorker extends ts.server.typingsInstaller.Typin } } -export class TestTypingsInstaller implements ts.server.ITypingsInstaller { +export class TestTypingsInstaller + implements ts.server.ITypingsInstaller +{ protected projectService!: ts.server.ProjectService; public installer!: T; constructor( @@ -369,13 +431,29 @@ export class TestTypingsInstaller) { + enqueueInstallTypingsRequest( + project: ts.server.Project, + typeAcquisition: ts.TypeAcquisition, + unresolvedImports: ts.SortedReadonlyArray, + ) { if (!this.installer) { if (this.workerConstructor) { - this.installer ??= new this.workerConstructor(this.globalTypingsCacheLocation, this.throttleLimit, this.installTypingHost, this.logger, this.typesRegistry); + this.installer ??= new this.workerConstructor( + this.globalTypingsCacheLocation, + this.throttleLimit, + this.installTypingHost, + this.logger, + this.typesRegistry, + ); } else { - this.installer = new TestTypingsInstallerWorker(this.globalTypingsCacheLocation, this.throttleLimit, this.installTypingHost, this.logger, this.typesRegistry) as T; + this.installer = new TestTypingsInstallerWorker( + this.globalTypingsCacheLocation, + this.throttleLimit, + this.installTypingHost, + this.logger, + this.typesRegistry, + ) as T; } this.installer.attach(this.projectService); } @@ -465,7 +543,13 @@ function patchHostTimeouts( function runQueuedTimeoutCallbacks(timeoutId?: number) { host.baselineHost(`Before running ${host.timeoutCallbacks.log()}`); - if (timeoutId !== undefined) logger.log(`Invoking ${host.timeoutCallbacks.callbackType} callback:: timeoutId:: ${timeoutId}:: ${host.timeoutCallbacks.map[timeoutId].args[0]}`); + if (timeoutId !== undefined) { + logger.log( + `Invoking ${host.timeoutCallbacks.callbackType} callback:: timeoutId:: ${timeoutId}:: ${ + host.timeoutCallbacks.map[timeoutId].args[0] + }`, + ); + } originalRunQueuedTimeoutCallbacks.call(host, timeoutId); host.baselineHost(`After running ${host.timeoutCallbacks.log()}`); } @@ -500,7 +584,10 @@ export class TestSession extends ts.server.Session { constructor(opts: TestSessionOptions) { super(opts); this.logger = opts.logger; - ts.Debug.assert(opts.allowNonBaseliningLogger || this.logger.hasLevel(ts.server.LogLevel.verbose), "Use Baselining logger and baseline tsserver log or create using allowNonBaseliningLogger"); + ts.Debug.assert( + opts.allowNonBaseliningLogger || this.logger.hasLevel(ts.server.LogLevel.verbose), + "Use Baselining logger and baseline tsserver log or create using allowNonBaseliningLogger", + ); this.testhost = patchHostTimeouts( changeToHostTrackingWrittenFiles(this.host as TestServerHost), this.logger, @@ -526,7 +613,18 @@ export class TestSession extends ts.server.Session { } const response = super.executeCommand(request); if (this.logger.hasLevel(ts.server.LogLevel.verbose)) { - this.logger.info(`response:${ts.server.indent(JSON.stringify(response.response === ts.getSupportedCodeFixes() ? { ...response, response: "ts.getSupportedCodeFixes()" } : response, undefined, 2))}`); + this.logger.info( + `response:${ + ts.server.indent( + JSON.stringify( + response.response === ts.getSupportedCodeFixes() + ? { ...response, response: "ts.getSupportedCodeFixes()" } : response, + undefined, + 2, + ), + ) + }`, + ); this.testhost.baselineHost("After request"); } return response; @@ -544,7 +642,12 @@ export class TestSession extends ts.server.Session { export function createSession(host: TestServerHost, opts: Partial = {}) { const logger = opts.logger || createHasErrorMessageLogger(); if (opts.typingsInstaller === undefined) { - opts.typingsInstaller = new TestTypingsInstaller(host.getHostSpecificPath("/a/data/"), /*throttleLimit*/ 5, host, logger); + opts.typingsInstaller = new TestTypingsInstaller( + host.getHostSpecificPath("/a/data/"), + /*throttleLimit*/ 5, + host, + logger, + ); } if (opts.eventHandler !== undefined) { @@ -587,7 +690,13 @@ export function createSessionWithCustomEventHandler(host: TestServerHost, opts?: break; // Map diagnostics case ts.server.ConfigFileDiagEvent: - data = { ...data, diagnostics: ts.map(event.data.diagnostics, diagnostic => ts.server.formatDiagnosticToProtocol(diagnostic, /*includeFileName*/ true)) }; + data = { + ...data, + diagnostics: ts.map( + event.data.diagnostics, + diagnostic => ts.server.formatDiagnosticToProtocol(diagnostic, /*includeFileName*/ true), + ), + }; break; default: ts.Debug.assertNever(event); @@ -603,7 +712,14 @@ export interface TestProjectServiceOptions extends ts.server.ProjectServiceOptio export class TestProjectService extends ts.server.ProjectService { public testhost: TestSessionAndServiceHost; - constructor(host: TestServerHost, public override logger: Logger, cancellationToken: ts.HostCancellationToken, useSingleInferredProject: boolean, typingsInstaller: ts.server.ITypingsInstaller, opts: Partial = {}) { + constructor( + host: TestServerHost, + public override logger: Logger, + cancellationToken: ts.HostCancellationToken, + useSingleInferredProject: boolean, + typingsInstaller: ts.server.ITypingsInstaller, + opts: Partial = {}, + ) { super({ host, logger, @@ -616,7 +732,10 @@ export class TestProjectService extends ts.server.ProjectService { incrementalVerifier, ...opts, }); - ts.Debug.assert(opts.allowNonBaseliningLogger || this.logger.hasLevel(ts.server.LogLevel.verbose), "Use Baselining logger and baseline tsserver log or create using allowNonBaseliningLogger"); + ts.Debug.assert( + opts.allowNonBaseliningLogger || this.logger.hasLevel(ts.server.LogLevel.verbose), + "Use Baselining logger and baseline tsserver log or create using allowNonBaseliningLogger", + ); this.testhost = patchHostTimeouts( changeToHostTrackingWrittenFiles(this.host as TestServerHost), this.logger, @@ -628,11 +747,23 @@ export class TestProjectService extends ts.server.ProjectService { export function createProjectService(host: TestServerHost, options?: Partial) { const cancellationToken = options?.cancellationToken || ts.server.nullCancellationToken; const logger = options?.logger || createHasErrorMessageLogger(); - const useSingleInferredProject = options?.useSingleInferredProject !== undefined ? options.useSingleInferredProject : false; - return new TestProjectService(host, logger, cancellationToken, useSingleInferredProject, options?.typingsInstaller || ts.server.nullTypingsInstaller, options); + const useSingleInferredProject = options?.useSingleInferredProject !== undefined ? options.useSingleInferredProject + : false; + return new TestProjectService( + host, + logger, + cancellationToken, + useSingleInferredProject, + options?.typingsInstaller || ts.server.nullTypingsInstaller, + options, + ); } -export function protocolLocationFromSubstring(str: string, substring: string, options?: SpanFromSubstringOptions): ts.server.protocol.Location { +export function protocolLocationFromSubstring( + str: string, + substring: string, + options?: SpanFromSubstringOptions, +): ts.server.protocol.Location { const start = nthIndexOf(str, substring, options ? options.index : 0); ts.Debug.assert(start !== -1); return protocolToLocation(str)(start); @@ -646,7 +777,11 @@ export function protocolToLocation(text: string): (pos: number) => ts.server.pro }; } -export function protocolTextSpanFromSubstring(str: string, substring: string, options?: SpanFromSubstringOptions): ts.server.protocol.TextSpan { +export function protocolTextSpanFromSubstring( + str: string, + substring: string, + options?: SpanFromSubstringOptions, +): ts.server.protocol.TextSpan { const span = textSpanFromSubstring(str, substring, options); const toLocation = protocolToLocation(str); return { start: toLocation(span.start), end: toLocation(ts.textSpanEnd(span)) }; @@ -658,7 +793,11 @@ export function textSpanFromSubstring(str: string, substring: string, options?: return ts.createTextSpan(start, substring.length); } -export function protocolFileLocationFromSubstring(file: File, substring: string, options?: SpanFromSubstringOptions): ts.server.protocol.FileLocationRequestArgs { +export function protocolFileLocationFromSubstring( + file: File, + substring: string, + options?: SpanFromSubstringOptions, +): ts.server.protocol.FileLocationRequestArgs { return { file: file.path, ...protocolLocationFromSubstring(file.content, substring, options) }; } @@ -700,7 +839,11 @@ export class TestServerCancellationToken implements ts.server.ServerCancellation } resetRequest(requestId: number) { - this.logger.log(`TestServerCancellationToken:: resetRequest:: ${requestId} is ${requestId === this.currentId ? "as expected" : `expected to be ${this.currentId}`}`); + this.logger.log( + `TestServerCancellationToken:: resetRequest:: ${requestId} is ${ + requestId === this.currentId ? "as expected" : `expected to be ${this.currentId}` + }`, + ); assert.equal(requestId, this.currentId, "unexpected request id in cancellation"); this.currentId = undefined; } @@ -710,7 +853,8 @@ export class TestServerCancellationToken implements ts.server.ServerCancellation // If the request id is the request to cancel and isCancellationRequestedCount // has been met then cancel the request. Ex: cancel the request if it is a // nav bar request & isCancellationRequested() has already been called three times. - const result = this.requestToCancel === this.currentId && this.isCancellationRequestedCount >= this.cancelAfterRequest; + const result = this.requestToCancel === this.currentId + && this.isCancellationRequestedCount >= this.cancelAfterRequest; if (result) this.logger.log(`TestServerCancellationToken:: Cancellation is requested`); return result; } @@ -734,16 +878,16 @@ export function openFilesForSession( for (const file of files) { session.executeCommandSeq({ command: ts.server.protocol.CommandTypes.Open, - arguments: ts.isString(file) ? - { file } : - "file" in file ? // eslint-disable-line local/no-in-operator - { + arguments: ts.isString(file) + ? { file } + : "file" in file // eslint-disable-line local/no-in-operator + ? { file: typeof file.file === "string" ? file.file : file.file.path, projectRootPath: file.projectRootPath, fileContent: file.content, scriptKindName: file.scriptKindName, - } : - { file: file.path }, + } + : { file: file.path }, }); } } @@ -772,18 +916,25 @@ export function openExternalProjectsForSession(projects: ts.server.protocol.Exte } export function setCompilerOptionsForInferredProjectsRequestForSession( - options: ts.server.protocol.InferredProjectCompilerOptions | ts.server.protocol.SetCompilerOptionsForInferredProjectsArgs, + options: + | ts.server.protocol.InferredProjectCompilerOptions + | ts.server.protocol.SetCompilerOptionsForInferredProjectsArgs, session: TestSession, ) { session.executeCommandSeq({ command: ts.server.protocol.CommandTypes.CompilerOptionsForInferredProjects, - arguments: "options" in options ? // eslint-disable-line local/no-in-operator - options as ts.server.protocol.SetCompilerOptionsForInferredProjectsArgs : - { options }, + arguments: "options" in options // eslint-disable-line local/no-in-operator + ? options as ts.server.protocol.SetCompilerOptionsForInferredProjectsArgs + : { options }, }); } -export function logDiagnostics(sessionOrService: TestSession | TestProjectService, diagnosticsType: string, project: ts.server.Project, diagnostics: readonly ts.Diagnostic[]) { +export function logDiagnostics( + sessionOrService: TestSession | TestProjectService, + diagnosticsType: string, + project: ts.server.Project, + diagnostics: readonly ts.Diagnostic[], +) { sessionOrService.logger.info(`${diagnosticsType}:: ${diagnostics.length}`); diagnostics.forEach(d => sessionOrService.logger.info(ts.formatDiagnostic(d, project))); } @@ -815,7 +966,9 @@ export interface CheckAllErrors extends VerifyGetErrRequestBase { function checkAllErrors({ session, existingTimeouts, files, skip }: CheckAllErrors) { ts.Debug.assert(session.logger.logs?.length); for (let i = 0; i < files.length; i++) { - session.testhost.runQueuedTimeoutCallbacks(existingTimeouts ? session.testhost.getNextTimeoutId() - 1 : undefined); + session.testhost.runQueuedTimeoutCallbacks( + existingTimeouts ? session.testhost.getNextTimeoutId() - 1 : undefined, + ); if (!skip?.[i]?.semantic) session.testhost.runQueuedImmediateCallbacks(); if (!skip?.[i]?.suggestion) session.testhost.runQueuedImmediateCallbacks(); } @@ -836,7 +989,9 @@ function verifyErrorsUsingGeterr({ scenario, subScenario, allFiles, openFiles, g }); } -function verifyErrorsUsingGeterrForProject({ scenario, subScenario, allFiles, openFiles, getErrForProjectRequest }: VerifyGetErrScenario) { +function verifyErrorsUsingGeterrForProject( + { scenario, subScenario, allFiles, openFiles, getErrForProjectRequest }: VerifyGetErrScenario, +) { it("verifies the errors in projects", () => { const host = createServerHost([...allFiles(), libFile]); const session = createSession(host, { canUseEvents: true, logger: createLoggerWithInMemoryLogs(host) }); @@ -853,7 +1008,9 @@ function verifyErrorsUsingGeterrForProject({ scenario, subScenario, allFiles, op }); } -function verifyErrorsUsingSyncMethods({ scenario, subScenario, allFiles, openFiles, syncDiagnostics }: VerifyGetErrScenario) { +function verifyErrorsUsingSyncMethods( + { scenario, subScenario, allFiles, openFiles, syncDiagnostics }: VerifyGetErrScenario, +) { it("verifies the errors using sync commands", () => { const host = createServerHost([...allFiles(), libFile]); const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) }); @@ -913,9 +1070,17 @@ export function createHostWithSolutionBuild(files: readonly FileOrFolderOrSymLin } export function logInferredProjectsOrphanStatus(projectService: ts.server.ProjectService) { - projectService.inferredProjects.forEach(inferredProject => (projectService.logger as Logger).log(`Inferred project: ${inferredProject.projectName} isOrphan:: ${inferredProject.isOrphan()} isClosed: ${inferredProject.isClosed()}`)); + projectService.inferredProjects.forEach(inferredProject => + (projectService.logger as Logger).log( + `Inferred project: ${inferredProject.projectName} isOrphan:: ${inferredProject.isOrphan()} isClosed: ${inferredProject.isClosed()}`, + ) + ); } export function logConfiguredProjectsHasOpenRefStatus(projectService: ts.server.ProjectService) { - projectService.configuredProjects.forEach(configuredProject => (projectService.logger as Logger).log(`Configured project: ${configuredProject.projectName} hasOpenRef:: ${configuredProject.hasOpenRef()} isClosed: ${configuredProject.isClosed()}`)); + projectService.configuredProjects.forEach(configuredProject => + (projectService.logger as Logger).log( + `Configured project: ${configuredProject.projectName} hasOpenRef:: ${configuredProject.hasOpenRef()} isClosed: ${configuredProject.isClosed()}`, + ) + ); } diff --git a/src/testRunner/unittests/helpers/vfs.ts b/src/testRunner/unittests/helpers/vfs.ts index e0f16f4adc1c8..f6303e5ff4402 100644 --- a/src/testRunner/unittests/helpers/vfs.ts +++ b/src/testRunner/unittests/helpers/vfs.ts @@ -16,9 +16,9 @@ export interface FsOptions { export type FsOptionsOrLibContentsToAppend = FsOptions | string; function valueOfFsOptions(options: FsOptionsOrLibContentsToAppend | undefined, key: keyof FsOptions) { - return typeof options === "string" ? - key === "libContentToAppend" ? options : undefined : - options?.[key]; + return typeof options === "string" + ? key === "libContentToAppend" ? options : undefined + : options?.[key]; } /** @@ -50,7 +50,10 @@ export function loadProjectFromFiles( }); const libContentToAppend = valueOfFsOptions(options, "libContentToAppend"); fs.mkdirpSync(defaultLibLocation); - fs.writeFileSync(`${defaultLibLocation}/lib.d.ts`, libContentToAppend ? `${libContent}${libContentToAppend}` : libContent); + fs.writeFileSync( + `${defaultLibLocation}/lib.d.ts`, + libContentToAppend ? `${libContent}${libContentToAppend}` : libContent, + ); fs.makeReadonly(); return fs; } diff --git a/src/testRunner/unittests/helpers/virtualFileSystemWithWatch.ts b/src/testRunner/unittests/helpers/virtualFileSystemWithWatch.ts index ce7d6382c761d..504a8c6fd0b55 100644 --- a/src/testRunner/unittests/helpers/virtualFileSystemWithWatch.ts +++ b/src/testRunner/unittests/helpers/virtualFileSystemWithWatch.ts @@ -79,11 +79,17 @@ export interface TestServerHostCreationParameters { inodeWatching?: boolean; } -export function createWatchedSystem(fileOrFolderList: FileOrFolderOrSymLinkMap | readonly FileOrFolderOrSymLink[], params?: TestServerHostCreationParameters): TestServerHost { +export function createWatchedSystem( + fileOrFolderList: FileOrFolderOrSymLinkMap | readonly FileOrFolderOrSymLink[], + params?: TestServerHostCreationParameters, +): TestServerHost { return new TestServerHost(fileOrFolderList, params); } -export function createServerHost(fileOrFolderList: FileOrFolderOrSymLinkMap | readonly FileOrFolderOrSymLink[], params?: TestServerHostCreationParameters): TestServerHost { +export function createServerHost( + fileOrFolderList: FileOrFolderOrSymLinkMap | readonly FileOrFolderOrSymLink[], + params?: TestServerHostCreationParameters, +): TestServerHost { const host = new TestServerHost(fileOrFolderList, params); // Just like sys, patch the host to use writeFile patchWriteFileEnsuringDirectory(host); @@ -199,7 +205,8 @@ class Callbacks { const { args } = this.map[Number(timeoutId)]; details.push(`${timeoutId}: ${args[0]}`); } - return `${this.callbackType} callback:: count: ${details.length}` + (details.length ? "\r\n" + details.join("\r\n") : ""); + return `${this.callbackType} callback:: count: ${details.length}` + + (details.length ? "\r\n" + details.join("\r\n") : ""); } private invokeCallback(timeoutId: number) { @@ -405,9 +412,9 @@ export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost, if (isArray(fileOrFolderOrSymLinkList)) { fileOrFolderOrSymLinkList.forEach(f => this.ensureFileOrFolder( - !this.windowsStyleRoot ? - f : - { ...f, path: this.getHostSpecificPath(f.path) }, + !this.windowsStyleRoot + ? f + : { ...f, path: this.getHostSpecificPath(f.path) }, ) ); } @@ -438,7 +445,12 @@ export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost, if (options && options.invokeFileDeleteCreateAsPartInsteadOfChange) { this.removeFileOrFolder(currentEntry, /*isRenaming*/ false, options); - this.ensureFileOrFolder({ path: filePath, content }, /*ignoreWatchInvokedWithTriggerAsFileCreate*/ undefined, /*ignoreParentWatch*/ undefined, options); + this.ensureFileOrFolder( + { path: filePath, content }, + /*ignoreWatchInvokedWithTriggerAsFileCreate*/ undefined, + /*ignoreParentWatch*/ undefined, + options, + ); } else { currentEntry.content = content; @@ -447,11 +459,28 @@ export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost, if (options && options.invokeDirectoryWatcherInsteadOfFileChanged) { const directoryFullPath = getDirectoryPath(currentEntry.fullPath); this.invokeFileWatcher(directoryFullPath, FileWatcherEventKind.Changed, currentEntry.modifiedTime); - this.invokeFsWatchesCallbacks(directoryFullPath, "rename", currentEntry.modifiedTime, currentEntry.fullPath, options.useTildeAsSuffixInRenameEventFileName); - this.invokeRecursiveFsWatches(directoryFullPath, "rename", currentEntry.modifiedTime, currentEntry.fullPath, options.useTildeAsSuffixInRenameEventFileName); + this.invokeFsWatchesCallbacks( + directoryFullPath, + "rename", + currentEntry.modifiedTime, + currentEntry.fullPath, + options.useTildeAsSuffixInRenameEventFileName, + ); + this.invokeRecursiveFsWatches( + directoryFullPath, + "rename", + currentEntry.modifiedTime, + currentEntry.fullPath, + options.useTildeAsSuffixInRenameEventFileName, + ); } else { - this.invokeFileAndFsWatches(currentEntry.fullPath, FileWatcherEventKind.Changed, currentEntry.modifiedTime, options?.useTildeAsSuffixInRenameEventFileName); + this.invokeFileAndFsWatches( + currentEntry.fullPath, + FileWatcherEventKind.Changed, + currentEntry.modifiedTime, + options?.useTildeAsSuffixInRenameEventFileName, + ); } } } @@ -518,7 +547,12 @@ export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost, } } - ensureFileOrFolder(fileOrDirectoryOrSymLink: FileOrFolderOrSymLink, ignoreWatchInvokedWithTriggerAsFileCreate?: boolean, ignoreParentWatch?: boolean, options?: Partial) { + ensureFileOrFolder( + fileOrDirectoryOrSymLink: FileOrFolderOrSymLink, + ignoreWatchInvokedWithTriggerAsFileCreate?: boolean, + ignoreParentWatch?: boolean, + options?: Partial, + ) { if (isFile(fileOrDirectoryOrSymLink)) { const file = this.toFsFile(fileOrDirectoryOrSymLink); // file may already exist when updating existing type declaration file @@ -540,7 +574,11 @@ export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost, } } - private ensureFolder(fullPath: string, ignoreWatch: boolean | undefined, options: Partial | undefined): FsFolder { + private ensureFolder( + fullPath: string, + ignoreWatch: boolean | undefined, + options: Partial | undefined, + ): FsFolder { const path = this.toPath(fullPath); let folder = this.fs.get(path) as FsFolder; if (!folder) { @@ -562,9 +600,18 @@ export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost, return folder; } - private addFileOrFolderInFolder(folder: FsFolder, fileOrDirectory: FsFile | FsFolder | FsSymLink, ignoreWatch?: boolean, options?: Partial) { + private addFileOrFolderInFolder( + folder: FsFolder, + fileOrDirectory: FsFile | FsFolder | FsSymLink, + ignoreWatch?: boolean, + options?: Partial, + ) { if (!this.fs.has(fileOrDirectory.path)) { - insertSorted(folder.entries, fileOrDirectory, (a, b) => compareStringsCaseSensitive(getBaseFileName(a.path), getBaseFileName(b.path))); + insertSorted( + folder.entries, + fileOrDirectory, + (a, b) => compareStringsCaseSensitive(getBaseFileName(a.path), getBaseFileName(b.path)), + ); } folder.modifiedTime = this.now(); this.fs.set(fileOrDirectory.path, fileOrDirectory); @@ -575,12 +622,26 @@ export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost, } const inodeWatching = this.inodeWatching; if (options?.skipInodeCheckOnCreate) this.inodeWatching = false; - this.invokeFileAndFsWatches(fileOrDirectory.fullPath, FileWatcherEventKind.Created, fileOrDirectory.modifiedTime, options?.useTildeAsSuffixInRenameEventFileName); - this.invokeFileAndFsWatches(folder.fullPath, FileWatcherEventKind.Changed, fileOrDirectory.modifiedTime, options?.useTildeAsSuffixInRenameEventFileName); + this.invokeFileAndFsWatches( + fileOrDirectory.fullPath, + FileWatcherEventKind.Created, + fileOrDirectory.modifiedTime, + options?.useTildeAsSuffixInRenameEventFileName, + ); + this.invokeFileAndFsWatches( + folder.fullPath, + FileWatcherEventKind.Changed, + fileOrDirectory.modifiedTime, + options?.useTildeAsSuffixInRenameEventFileName, + ); this.inodeWatching = inodeWatching; } - private removeFileOrFolder(fileOrDirectory: FsFile | FsFolder | FsSymLink, isRenaming?: boolean, options?: Partial) { + private removeFileOrFolder( + fileOrDirectory: FsFile | FsFolder | FsSymLink, + isRenaming?: boolean, + options?: Partial, + ) { const basePath = getDirectoryPath(fileOrDirectory.path); const baseFolder = this.fs.get(basePath) as FsFolder; if (basePath !== fileOrDirectory.path) { @@ -593,9 +654,23 @@ export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost, if (isFsFolder(fileOrDirectory)) { Debug.assert(fileOrDirectory.entries.length === 0 || isRenaming); } - if (!options?.ignoreDelete) this.invokeFileAndFsWatches(fileOrDirectory.fullPath, FileWatcherEventKind.Deleted, /*modifiedTime*/ undefined, options?.useTildeAsSuffixInRenameEventFileName); + if (!options?.ignoreDelete) { + this.invokeFileAndFsWatches( + fileOrDirectory.fullPath, + FileWatcherEventKind.Deleted, + /*modifiedTime*/ undefined, + options?.useTildeAsSuffixInRenameEventFileName, + ); + } this.inodes?.delete(fileOrDirectory.path); - if (!options?.ignoreDelete) this.invokeFileAndFsWatches(baseFolder.fullPath, FileWatcherEventKind.Changed, baseFolder.modifiedTime, options?.useTildeAsSuffixInRenameEventFileName); + if (!options?.ignoreDelete) { + this.invokeFileAndFsWatches( + baseFolder.fullPath, + FileWatcherEventKind.Changed, + baseFolder.modifiedTime, + options?.useTildeAsSuffixInRenameEventFileName, + ); + } } deleteFile(filePath: string) { @@ -651,7 +726,9 @@ export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost, recursive: boolean, cb: FsWatchCallback, ) { - if (this.runWithFallbackPolling) throw new Error("Need to use fallback polling instead of file system native watching"); + if (this.runWithFallbackPolling) { + throw new Error("Need to use fallback polling instead of file system native watching"); + } const path = this.toFullPath(fileOrDirectory); // Error if the path does not exist if (this.inodeWatching && !this.inodes?.has(path)) throw new Error(); @@ -668,34 +745,70 @@ export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost, } invokeFileWatcher(fileFullPath: string, eventKind: FileWatcherEventKind, modifiedTime: Date | undefined) { - invokeWatcherCallbacks(this.watchedFiles.get(this.toPath(fileFullPath)), ({ cb }) => cb(fileFullPath, eventKind, modifiedTime)); + invokeWatcherCallbacks( + this.watchedFiles.get(this.toPath(fileFullPath)), + ({ cb }) => cb(fileFullPath, eventKind, modifiedTime), + ); } - private fsWatchCallback(map: MultiMap, fullPath: string, eventName: "rename" | "change", modifiedTime: Date | undefined, entryFullPath: string | undefined, useTildeSuffix: boolean | undefined) { + private fsWatchCallback( + map: MultiMap, + fullPath: string, + eventName: "rename" | "change", + modifiedTime: Date | undefined, + entryFullPath: string | undefined, + useTildeSuffix: boolean | undefined, + ) { const path = this.toPath(fullPath); const currentInode = this.inodes?.get(path); invokeWatcherCallbacks(map.get(path), ({ cb, inode }) => { // TODO:: if (this.inodeWatching && inode !== undefined && inode !== currentInode) return; let relativeFileName = entryFullPath ? this.getRelativePathToDirectory(fullPath, entryFullPath) : ""; - if (useTildeSuffix) relativeFileName = (relativeFileName ? relativeFileName : getBaseFileName(fullPath)) + "~"; + if (useTildeSuffix) { + relativeFileName = (relativeFileName ? relativeFileName : getBaseFileName(fullPath)) + "~"; + } cb(eventName, relativeFileName, modifiedTime); }); } - invokeFsWatchesCallbacks(fullPath: string, eventName: "rename" | "change", modifiedTime?: Date, entryFullPath?: string, useTildeSuffix?: boolean) { + invokeFsWatchesCallbacks( + fullPath: string, + eventName: "rename" | "change", + modifiedTime?: Date, + entryFullPath?: string, + useTildeSuffix?: boolean, + ) { this.fsWatchCallback(this.fsWatches, fullPath, eventName, modifiedTime, entryFullPath, useTildeSuffix); } - invokeFsWatchesRecursiveCallbacks(fullPath: string, eventName: "rename" | "change", modifiedTime?: Date, entryFullPath?: string, useTildeSuffix?: boolean) { + invokeFsWatchesRecursiveCallbacks( + fullPath: string, + eventName: "rename" | "change", + modifiedTime?: Date, + entryFullPath?: string, + useTildeSuffix?: boolean, + ) { this.fsWatchCallback(this.fsWatchesRecursive, fullPath, eventName, modifiedTime, entryFullPath, useTildeSuffix); } private getRelativePathToDirectory(directoryFullPath: string, fileFullPath: string) { - return getRelativePathToDirectoryOrUrl(directoryFullPath, fileFullPath, this.currentDirectory, this.getCanonicalFileName, /*isAbsolutePathAnUrl*/ false); + return getRelativePathToDirectoryOrUrl( + directoryFullPath, + fileFullPath, + this.currentDirectory, + this.getCanonicalFileName, + /*isAbsolutePathAnUrl*/ false, + ); } - private invokeRecursiveFsWatches(fullPath: string, eventName: "rename" | "change", modifiedTime?: Date, entryFullPath?: string, useTildeSuffix?: boolean) { + private invokeRecursiveFsWatches( + fullPath: string, + eventName: "rename" | "change", + modifiedTime?: Date, + entryFullPath?: string, + useTildeSuffix?: boolean, + ) { this.invokeFsWatchesRecursiveCallbacks(fullPath, eventName, modifiedTime, entryFullPath, useTildeSuffix); const basePath = getDirectoryPath(fullPath); if (this.getCanonicalFileName(fullPath) !== this.getCanonicalFileName(basePath)) { @@ -703,15 +816,30 @@ export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost, } } - invokeFsWatches(fullPath: string, eventName: "rename" | "change", modifiedTime: Date | undefined, useTildeSuffix: boolean | undefined) { + invokeFsWatches( + fullPath: string, + eventName: "rename" | "change", + modifiedTime: Date | undefined, + useTildeSuffix: boolean | undefined, + ) { this.invokeFsWatchesCallbacks(fullPath, eventName, modifiedTime, fullPath, useTildeSuffix); this.invokeFsWatchesCallbacks(getDirectoryPath(fullPath), eventName, modifiedTime, fullPath, useTildeSuffix); this.invokeRecursiveFsWatches(fullPath, eventName, modifiedTime, /*entryFullPath*/ undefined, useTildeSuffix); } - private invokeFileAndFsWatches(fileOrFolderFullPath: string, eventKind: FileWatcherEventKind, modifiedTime?: Date, useTildeSuffix?: boolean) { + private invokeFileAndFsWatches( + fileOrFolderFullPath: string, + eventKind: FileWatcherEventKind, + modifiedTime?: Date, + useTildeSuffix?: boolean, + ) { this.invokeFileWatcher(fileOrFolderFullPath, eventKind, modifiedTime); - this.invokeFsWatches(fileOrFolderFullPath, eventKind === FileWatcherEventKind.Changed ? "change" : "rename", modifiedTime, useTildeSuffix); + this.invokeFsWatches( + fileOrFolderFullPath, + eventKind === FileWatcherEventKind.Changed ? "change" : "rename", + modifiedTime, + useTildeSuffix, + ); } private toFsEntry(path: string): FSEntryBase { @@ -742,7 +870,11 @@ export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost, return fsFolder; } - private getRealFsEntry(isFsEntry: (fsEntry: FSEntry) => fsEntry is T, path: Path, fsEntry = this.fs.get(path)!): T | undefined { + private getRealFsEntry( + isFsEntry: (fsEntry: FSEntry) => fsEntry is T, + path: Path, + fsEntry = this.fs.get(path)!, + ): T | undefined { if (isFsEntry(fsEntry)) { return fsEntry; } @@ -827,32 +959,51 @@ export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost, const path = this.toFullPath(s); const folder = this.getRealFolder(path); if (folder) { - return mapDefined(folder.entries, entry => this.isFsFolder(entry) ? getBaseFileName(entry.fullPath) : undefined); + return mapDefined( + folder.entries, + entry => this.isFsFolder(entry) ? getBaseFileName(entry.fullPath) : undefined, + ); } Debug.fail(folder ? "getDirectories called on file" : "getDirectories called on missing folder"); return []; } - readDirectory(path: string, extensions?: readonly string[], exclude?: readonly string[], include?: readonly string[], depth?: number): string[] { - return matchFiles(path, extensions, exclude, include, this.useCaseSensitiveFileNames, this.getCurrentDirectory(), depth, dir => { - const directories: string[] = []; - const files: string[] = []; - const folder = this.getRealFolder(this.toPath(dir)); - if (folder) { - folder.entries.forEach(entry => { - if (this.isFsFolder(entry)) { - directories.push(getBaseFileName(entry.fullPath)); - } - else if (this.isFsFile(entry)) { - files.push(getBaseFileName(entry.fullPath)); - } - else { - Debug.fail("Unknown entry"); - } - }); - } - return { directories, files }; - }, path => this.realpath(path)); + readDirectory( + path: string, + extensions?: readonly string[], + exclude?: readonly string[], + include?: readonly string[], + depth?: number, + ): string[] { + return matchFiles( + path, + extensions, + exclude, + include, + this.useCaseSensitiveFileNames, + this.getCurrentDirectory(), + depth, + dir => { + const directories: string[] = []; + const files: string[] = []; + const folder = this.getRealFolder(this.toPath(dir)); + if (folder) { + folder.entries.forEach(entry => { + if (this.isFsFolder(entry)) { + directories.push(getBaseFileName(entry.fullPath)); + } + else if (this.isFsFile(entry)) { + files.push(getBaseFileName(entry.fullPath)); + } + else { + Debug.fail("Unknown entry"); + } + }); + } + return { directories, files }; + }, + path => this.realpath(path), + ); } createHash(s: string): string { @@ -1009,9 +1160,19 @@ export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost, private serializedFsWatchesRecursive: Map | undefined; serializeWatches(baseline: string[] = []) { if (!this.hasWatchChanges) return baseline; - this.serializedWatchedFiles = serializeMultiMap(baseline, "PolledWatches", this.watchedFiles, this.serializedWatchedFiles); + this.serializedWatchedFiles = serializeMultiMap( + baseline, + "PolledWatches", + this.watchedFiles, + this.serializedWatchedFiles, + ); this.serializedFsWatches = serializeMultiMap(baseline, "FsWatches", this.fsWatches, this.serializedFsWatches); - this.serializedFsWatchesRecursive = serializeMultiMap(baseline, "FsWatchesRecursive", this.fsWatchesRecursive, this.serializedFsWatchesRecursive); + this.serializedFsWatchesRecursive = serializeMultiMap( + baseline, + "FsWatchesRecursive", + this.fsWatchesRecursive, + this.serializedFsWatchesRecursive, + ); this.hasWatchChanges = false; return baseline; } @@ -1057,7 +1218,13 @@ function diffFsSymLink(baseline: string[], fsEntry: FsSymLink, newInode: number function inodeString(inode: number | undefined) { return inode !== undefined ? ` Inode:: ${inode}` : ""; } -function diffFsEntry(baseline: string[], oldFsEntry: FSEntry | undefined, newFsEntry: FSEntry | undefined, newInode: number | undefined, writtenFiles: Map | undefined): void { +function diffFsEntry( + baseline: string[], + oldFsEntry: FSEntry | undefined, + newFsEntry: FSEntry | undefined, + newInode: number | undefined, + writtenFiles: Map | undefined, +): void { const file = newFsEntry && newFsEntry.fullPath; if (isFsFile(oldFsEntry)) { if (isFsFile(newFsEntry)) { @@ -1066,7 +1233,9 @@ function diffFsEntry(baseline: string[], oldFsEntry: FSEntry | undefined, newFsE } else if (oldFsEntry.modifiedTime !== newFsEntry.modifiedTime) { if (oldFsEntry.fullPath !== newFsEntry.fullPath) { - baseline.push(`//// [${file}] file was renamed from file ${oldFsEntry.fullPath}${inodeString(newInode)}`); + baseline.push( + `//// [${file}] file was renamed from file ${oldFsEntry.fullPath}${inodeString(newInode)}`, + ); } else if (writtenFiles && !writtenFiles.has(newFsEntry.path)) { baseline.push(`//// [${file}] file changed its modified time${inodeString(newInode)}`); @@ -1090,7 +1259,11 @@ function diffFsEntry(baseline: string[], oldFsEntry: FSEntry | undefined, newFsE } else if (oldFsEntry.modifiedTime !== newFsEntry.modifiedTime) { if (oldFsEntry.fullPath !== newFsEntry.fullPath) { - baseline.push(`//// [${file}] symlink was renamed from symlink ${oldFsEntry.fullPath}${inodeString(newInode)}`); + baseline.push( + `//// [${file}] symlink was renamed from symlink ${oldFsEntry.fullPath}${ + inodeString(newInode) + }`, + ); } else if (writtenFiles && !writtenFiles.has(newFsEntry.path)) { baseline.push(`//// [${file}] symlink changed its modified time${inodeString(newInode)}`); @@ -1115,7 +1288,12 @@ function diffFsEntry(baseline: string[], oldFsEntry: FSEntry | undefined, newFsE } } -function serializeMultiMap(baseline: string[], caption: string, multiMap: MultiMap, serialized: Map | undefined) { +function serializeMultiMap( + baseline: string[], + caption: string, + multiMap: MultiMap, + serialized: Map | undefined, +) { let hasChange = diffMap(baseline, caption, multiMap, serialized, /*deleted*/ false); hasChange = diffMap(baseline, caption, serialized, multiMap, /*deleted*/ true) || hasChange; if (hasChange) { diff --git a/src/testRunner/unittests/incrementalParser.ts b/src/testRunner/unittests/incrementalParser.ts index a42044d0a67db..caaea4e8019d3 100644 --- a/src/testRunner/unittests/incrementalParser.ts +++ b/src/testRunner/unittests/incrementalParser.ts @@ -1,23 +1,45 @@ import * as ts from "../_namespaces/ts"; import * as Utils from "../_namespaces/Utils"; -function withChange(text: ts.IScriptSnapshot, start: number, length: number, newText: string): { text: ts.IScriptSnapshot; textChangeRange: ts.TextChangeRange; } { +function withChange( + text: ts.IScriptSnapshot, + start: number, + length: number, + newText: string, +): { text: ts.IScriptSnapshot; textChangeRange: ts.TextChangeRange; } { const contents = ts.getSnapshotText(text); const newContents = contents.substr(0, start) + newText + contents.substring(start + length); - return { text: ts.ScriptSnapshot.fromString(newContents), textChangeRange: ts.createTextChangeRange(ts.createTextSpan(start, length), newText.length) }; + return { + text: ts.ScriptSnapshot.fromString(newContents), + textChangeRange: ts.createTextChangeRange(ts.createTextSpan(start, length), newText.length), + }; } -function withInsert(text: ts.IScriptSnapshot, start: number, newText: string): { text: ts.IScriptSnapshot; textChangeRange: ts.TextChangeRange; } { +function withInsert( + text: ts.IScriptSnapshot, + start: number, + newText: string, +): { text: ts.IScriptSnapshot; textChangeRange: ts.TextChangeRange; } { return withChange(text, start, 0, newText); } -function withDelete(text: ts.IScriptSnapshot, start: number, length: number): { text: ts.IScriptSnapshot; textChangeRange: ts.TextChangeRange; } { +function withDelete( + text: ts.IScriptSnapshot, + start: number, + length: number, +): { text: ts.IScriptSnapshot; textChangeRange: ts.TextChangeRange; } { return withChange(text, start, length, ""); } function createTree(text: ts.IScriptSnapshot, version: string) { - return ts.createLanguageServiceSourceFile(/*fileName:*/ "", text, ts.ScriptTarget.Latest, version, /*setNodeParents*/ true); + return ts.createLanguageServiceSourceFile( + /*fileName:*/ "", + text, + ts.ScriptTarget.Latest, + version, + /*setNodeParents*/ true, + ); } function assertSameDiagnostics(file1: ts.SourceFile, file2: ts.SourceFile) { @@ -44,7 +66,13 @@ function assertSameDiagnostics(file1: ts.SourceFile, file2: ts.SourceFile) { // be a good thing. If it decreases, that's not great (less reusability), but that may be // unavoidable. If it does decrease an investigation should be done to make sure that things // are still ok and we're still appropriately reusing most of the tree. -function compareTrees(oldText: ts.IScriptSnapshot, newText: ts.IScriptSnapshot, textChangeRange: ts.TextChangeRange, expectedReusedElements: number, oldTree?: ts.SourceFile) { +function compareTrees( + oldText: ts.IScriptSnapshot, + newText: ts.IScriptSnapshot, + textChangeRange: ts.TextChangeRange, + expectedReusedElements: number, + oldTree?: ts.SourceFile, +) { oldTree = oldTree || createTree(oldText, /*version:*/ "."); Utils.assertInvariants(oldTree, /*parent:*/ undefined); @@ -53,7 +81,12 @@ function compareTrees(oldText: ts.IScriptSnapshot, newText: ts.IScriptSnapshot, Utils.assertInvariants(newTree, /*parent:*/ undefined); // Create a tree for the new text, in an incremental fashion. - const incrementalNewTree = ts.updateLanguageServiceSourceFile(oldTree, newText, oldTree.version + ".", textChangeRange); + const incrementalNewTree = ts.updateLanguageServiceSourceFile( + oldTree, + newText, + oldTree.version + ".", + textChangeRange, + ); Utils.assertInvariants(incrementalNewTree, /*parent:*/ undefined); // We should get the same tree when doign a full or incremental parse. @@ -100,7 +133,8 @@ function deleteCode(source: string, index: number, toDelete: string) { for (let i = 0; i < repeat; i++) { const oldText = ts.ScriptSnapshot.fromString(source); const newTextAndChange = withDelete(oldText, index, 1); - const newTree = compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, -1, oldTree).incrementalNewTree; + const newTree = compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, -1, oldTree) + .incrementalNewTree; source = ts.getSnapshotText(newTextAndChange.text); oldTree = newTree; @@ -113,7 +147,8 @@ function insertCode(source: string, index: number, toInsert: string) { for (let i = 0; i < repeat; i++) { const oldText = ts.ScriptSnapshot.fromString(source); const newTextAndChange = withInsert(oldText, index + i, toInsert.charAt(i)); - const newTree = compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, -1, oldTree).incrementalNewTree; + const newTree = compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, -1, oldTree) + .incrementalNewTree; source = ts.getSnapshotText(newTextAndChange.text); oldTree = newTree; @@ -122,13 +157,13 @@ function insertCode(source: string, index: number, toInsert: string) { describe("unittests:: Incremental Parser", () => { it("Inserting into method", () => { - const source = "class C {\r\n" + - " public foo1() { }\r\n" + - " public foo2() {\r\n" + - " return 1;\r\n" + - " }\r\n" + - " public foo3() { }\r\n" + - "}"; + const source = "class C {\r\n" + + " public foo1() { }\r\n" + + " public foo2() {\r\n" + + " return 1;\r\n" + + " }\r\n" + + " public foo3() { }\r\n" + + "}"; const oldText = ts.ScriptSnapshot.fromString(source); const semicolonIndex = source.indexOf(";"); @@ -138,13 +173,13 @@ describe("unittests:: Incremental Parser", () => { }); it("Deleting from method", () => { - const source = "class C {\r\n" + - " public foo1() { }\r\n" + - " public foo2() {\r\n" + - " return 1 + 1;\r\n" + - " }\r\n" + - " public foo3() { }\r\n" + - "}"; + const source = "class C {\r\n" + + " public foo1() { }\r\n" + + " public foo2() {\r\n" + + " return 1 + 1;\r\n" + + " }\r\n" + + " public foo3() { }\r\n" + + "}"; const index = source.indexOf("+ 1"); const oldText = ts.ScriptSnapshot.fromString(source); @@ -213,11 +248,11 @@ describe("unittests:: Incremental Parser", () => { it("Parameter 1", () => { // Should be able to reuse all the parameters. - const source = "class C {\r\n" + - " public foo2(a, b, c, d) {\r\n" + - " return 1;\r\n" + - " }\r\n" + - "}"; + const source = "class C {\r\n" + + " public foo2(a, b, c, d) {\r\n" + + " return 1;\r\n" + + " }\r\n" + + "}"; const semicolonIndex = source.indexOf(";"); const oldText = ts.ScriptSnapshot.fromString(source); @@ -287,7 +322,8 @@ describe("unittests:: Incremental Parser", () => { }); it("Strict mode 5", () => { - const source = "'use blahhh';\r\nfoo1();\r\nfoo2();\r\nfoo3();\r\nfoo4();\r\nfoo4();\r\nfoo6();\r\nfoo7();\r\nfoo8();\r\nfoo9();\r\n"; + const source = + "'use blahhh';\r\nfoo1();\r\nfoo2();\r\nfoo3();\r\nfoo4();\r\nfoo4();\r\nfoo6();\r\nfoo7();\r\nfoo8();\r\nfoo9();\r\n"; const index = source.indexOf("b"); const oldText = ts.ScriptSnapshot.fromString(source); @@ -297,7 +333,8 @@ describe("unittests:: Incremental Parser", () => { }); it("Strict mode 6", () => { - const source = "'use strict';\r\nfoo1();\r\nfoo2();\r\nfoo3();\r\nfoo4();\r\nfoo4();\r\nfoo6();\r\nfoo7();\r\nfoo8();\r\nfoo9();\r\n"; + const source = + "'use strict';\r\nfoo1();\r\nfoo2();\r\nfoo3();\r\nfoo4();\r\nfoo4();\r\nfoo6();\r\nfoo7();\r\nfoo8();\r\nfoo9();\r\n"; const index = source.indexOf("s"); const oldText = ts.ScriptSnapshot.fromString(source); @@ -307,7 +344,8 @@ describe("unittests:: Incremental Parser", () => { }); it("Strict mode 7", () => { - const source = "'use blahhh';\r\nfoo1();\r\nfoo2();\r\nfoo3();\r\nfoo4();\r\nfoo4();\r\nfoo6();\r\nfoo7();\r\nfoo8();\r\nfoo9();\r\n"; + const source = + "'use blahhh';\r\nfoo1();\r\nfoo2();\r\nfoo3();\r\nfoo4();\r\nfoo4();\r\nfoo6();\r\nfoo7();\r\nfoo8();\r\nfoo9();\r\n"; const index = source.indexOf("f"); const oldText = ts.ScriptSnapshot.fromString(source); @@ -519,7 +557,8 @@ describe("unittests:: Incremental Parser", () => { }); it("Delete semicolon", () => { - const source = "export class Foo {\r\n}\r\n\r\nexport var foo = new Foo();\r\n\r\n export function test(foo: Foo) {\r\n return true;\r\n }\r\n"; + const source = + "export class Foo {\r\n}\r\n\r\nexport var foo = new Foo();\r\n\r\n export function test(foo: Foo) {\r\n return true;\r\n }\r\n"; const oldText = ts.ScriptSnapshot.fromString(source); const index = source.lastIndexOf(";"); @@ -734,7 +773,8 @@ module m3 { }\ }); it("Moving index signatures from class to interface in strict mode", () => { - const source = '"use strict"; class C { public [a: number]: string; public [a: number]: string; public [a: number]: string }'; + const source = + '"use strict"; class C { public [a: number]: string; public [a: number]: string; public [a: number]: string }'; const oldText = ts.ScriptSnapshot.fromString(source); const newTextAndChange = withChange(oldText, 14, "class".length, "interface"); @@ -743,7 +783,8 @@ module m3 { }\ }); it("Moving index signatures from interface to class", () => { - const source = "interface C { public [a: number]: string; public [a: number]: string; public [a: number]: string }"; + const source = + "interface C { public [a: number]: string; public [a: number]: string; public [a: number]: string }"; const oldText = ts.ScriptSnapshot.fromString(source); const newTextAndChange = withChange(oldText, 0, "interface".length, "class"); @@ -752,7 +793,8 @@ module m3 { }\ }); it("Moving index signatures from interface to class in strict mode", () => { - const source = '"use strict"; interface C { public [a: number]: string; public [a: number]: string; public [a: number]: string }'; + const source = + '"use strict"; interface C { public [a: number]: string; public [a: number]: string; public [a: number]: string }'; const oldText = ts.ScriptSnapshot.fromString(source); const newTextAndChange = withChange(oldText, 14, "interface".length, "class"); @@ -791,7 +833,12 @@ module m3 { }\ const source = `class Greeter { constructor(element: HTMLElement) { } }`; const oldText = ts.ScriptSnapshot.fromString(source); const newTextAndChange = withChange(oldText, 15, 0, "\n"); - const { oldTree, incrementalNewTree } = compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, -1); + const { oldTree, incrementalNewTree } = compareTrees( + oldText, + newTextAndChange.text, + newTextAndChange.textChangeRange, + -1, + ); ts.bindSourceFile(oldTree, {}); ts.bindSourceFile(incrementalNewTree, {}); assert.equal(oldTree.transformFlags, incrementalNewTree.transformFlags); @@ -807,22 +854,22 @@ module m3 { }\ }); it("Type after incomplete enum 1", () => { - const source = "function foo() {\r\n" + - " function getOccurrencesAtPosition() {\r\n" + - " switch (node) {\r\n" + - " enum \r\n" + - " }\r\n" + - " \r\n" + - " return undefined;\r\n" + - " \r\n" + - " function keywordToReferenceEntry() {\r\n" + - " }\r\n" + - " }\r\n" + - " \r\n" + - " return {\r\n" + - " getEmitOutput: (fileName): Bar => null,\r\n" + - " };\r\n" + - " }"; + const source = "function foo() {\r\n" + + " function getOccurrencesAtPosition() {\r\n" + + " switch (node) {\r\n" + + " enum \r\n" + + " }\r\n" + + " \r\n" + + " return undefined;\r\n" + + " \r\n" + + " function keywordToReferenceEntry() {\r\n" + + " }\r\n" + + " }\r\n" + + " \r\n" + + " return {\r\n" + + " getEmitOutput: (fileName): Bar => null,\r\n" + + " };\r\n" + + " }"; const index = source.indexOf("enum ") + "enum ".length; insertCode(source, index, "Fo"); @@ -863,8 +910,16 @@ module m3 { }\ verifyScenario("when changing text that adds another comment", verifyChangeDirectiveType); verifyScenario("when changing text that keeps the comment but adds more nodes", verifyReuseChange); - function verifyCommentDirectives(oldText: ts.IScriptSnapshot, newTextAndChange: { text: ts.IScriptSnapshot; textChangeRange: ts.TextChangeRange; }) { - const { incrementalNewTree, newTree } = compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, -1); + function verifyCommentDirectives( + oldText: ts.IScriptSnapshot, + newTextAndChange: { text: ts.IScriptSnapshot; textChangeRange: ts.TextChangeRange; }, + ) { + const { incrementalNewTree, newTree } = compareTrees( + oldText, + newTextAndChange.text, + newTextAndChange.textChangeRange, + -1, + ); assert.deepEqual(incrementalNewTree.commentDirectives, newTree.commentDirectives); } @@ -906,14 +961,19 @@ module m3 { }\ function verifyDelete(atIndex: number, singleIgnore?: true) { const index = getIndexOfTsIgnoreComment(atIndex); - const oldText = ts.ScriptSnapshot.fromString(textWithIgnoreCommentFrom(textWithIgnoreComment, singleIgnore)); + const oldText = ts.ScriptSnapshot.fromString( + textWithIgnoreCommentFrom(textWithIgnoreComment, singleIgnore), + ); const newTextAndChange = withDelete(oldText, index, tsIgnoreComment.length); verifyCommentDirectives(oldText, newTextAndChange); } function verifyInsert(atIndex: number, singleIgnore?: true) { const index = getIndexOfTsIgnoreComment(atIndex); - const source = textWithIgnoreCommentFrom(textWithIgnoreComment.slice(0, index) + textWithIgnoreComment.slice(index + tsIgnoreComment.length), singleIgnore); + const source = textWithIgnoreCommentFrom( + textWithIgnoreComment.slice(0, index) + textWithIgnoreComment.slice(index + tsIgnoreComment.length), + singleIgnore, + ); const oldText = ts.ScriptSnapshot.fromString(source); const newTextAndChange = withInsert(oldText, index, tsIgnoreComment); verifyCommentDirectives(oldText, newTextAndChange); @@ -921,14 +981,19 @@ module m3 { }\ function verifyChangeToBlah(atIndex: number, singleIgnore?: true) { const index = getIndexOfTsIgnoreComment(atIndex) + tsIgnoreComment.indexOf("@"); - const oldText = ts.ScriptSnapshot.fromString(textWithIgnoreCommentFrom(textWithIgnoreComment, singleIgnore)); + const oldText = ts.ScriptSnapshot.fromString( + textWithIgnoreCommentFrom(textWithIgnoreComment, singleIgnore), + ); const newTextAndChange = withChange(oldText, index, 1, "blah "); verifyCommentDirectives(oldText, newTextAndChange); } function verifyChangeBackToDirective(atIndex: number, singleIgnore?: true) { const index = getIndexOfTsIgnoreComment(atIndex) + tsIgnoreComment.indexOf("@"); - const source = textWithIgnoreCommentFrom(textWithIgnoreComment.slice(0, index) + "blah " + textWithIgnoreComment.slice(index + 1), singleIgnore); + const source = textWithIgnoreCommentFrom( + textWithIgnoreComment.slice(0, index) + "blah " + textWithIgnoreComment.slice(index + 1), + singleIgnore, + ); const oldText = ts.ScriptSnapshot.fromString(source); const newTextAndChange = withChange(oldText, index, "blah ".length, "@"); verifyCommentDirectives(oldText, newTextAndChange); @@ -937,7 +1002,10 @@ module m3 { }\ function verifyDeletingBlah(atIndex: number, singleIgnore?: true) { const tsIgnoreIndex = getIndexOfTsIgnoreComment(atIndex); const index = tsIgnoreIndex + tsIgnoreComment.indexOf("@"); - const source = textWithIgnoreCommentFrom(textWithIgnoreComment.slice(0, index) + "blah " + textWithIgnoreComment.slice(index + 1), singleIgnore); + const source = textWithIgnoreCommentFrom( + textWithIgnoreComment.slice(0, index) + "blah " + textWithIgnoreComment.slice(index + 1), + singleIgnore, + ); const oldText = ts.ScriptSnapshot.fromString(source); const newTextAndChange = withDelete(oldText, tsIgnoreIndex, tsIgnoreComment.length + "blah".length); verifyCommentDirectives(oldText, newTextAndChange); @@ -945,7 +1013,9 @@ module m3 { }\ function verifyChangeDirectiveType(atIndex: number, singleIgnore?: true) { const index = getIndexOfTsIgnoreComment(atIndex) + tsIgnoreComment.indexOf("ignore"); - const oldText = ts.ScriptSnapshot.fromString(textWithIgnoreCommentFrom(textWithIgnoreComment, singleIgnore)); + const oldText = ts.ScriptSnapshot.fromString( + textWithIgnoreCommentFrom(textWithIgnoreComment, singleIgnore), + ); const newTextAndChange = withChange(oldText, index, "ignore".length, "expect-error"); verifyCommentDirectives(oldText, newTextAndChange); } diff --git a/src/testRunner/unittests/jsDocParsing.ts b/src/testRunner/unittests/jsDocParsing.ts index 56ba3a9cc05eb..914865ea46a1a 100644 --- a/src/testRunner/unittests/jsDocParsing.ts +++ b/src/testRunner/unittests/jsDocParsing.ts @@ -9,7 +9,10 @@ describe("unittests:: JSDocParsing", () => { const typeAndDiagnostics = ts.parseJSDocTypeExpressionForTests(content); assert.isTrue(typeAndDiagnostics && typeAndDiagnostics.diagnostics.length === 0, "no errors issued"); - Harness.Baseline.runBaseline("JSDocParsing/TypeExpressions.parsesCorrectly." + name + ".json", Utils.sourceFileToJSON(typeAndDiagnostics!.jsDocTypeExpression.type)); + Harness.Baseline.runBaseline( + "JSDocParsing/TypeExpressions.parsesCorrectly." + name + ".json", + Utils.sourceFileToJSON(typeAndDiagnostics!.jsDocTypeExpression.type), + ); }); } @@ -98,7 +101,14 @@ describe("unittests:: JSDocParsing", () => { ts.Debug.fail("Comment has at least one diagnostic: " + comment.diagnostics[0].messageText); } - Harness.Baseline.runBaseline("JSDocParsing/DocComments.parsesCorrectly." + name + ".json", JSON.stringify(comment.jsDoc, (_, v) => v && v.pos !== undefined ? JSON.parse(Utils.sourceFileToJSON(v)) : v, 4)); + Harness.Baseline.runBaseline( + "JSDocParsing/DocComments.parsesCorrectly." + name + ".json", + JSON.stringify( + comment.jsDoc, + (_, v) => v && v.pos !== undefined ? JSON.parse(Utils.sourceFileToJSON(v)) : v, + 4, + ), + ); }); } @@ -486,7 +496,12 @@ oh.no }); describe("getFirstToken", () => { it("gets jsdoc", () => { - const root = ts.createSourceFile("foo.ts", "/** comment */var a = true;", ts.ScriptTarget.ES5, /*setParentNodes*/ true); + const root = ts.createSourceFile( + "foo.ts", + "/** comment */var a = true;", + ts.ScriptTarget.ES5, + /*setParentNodes*/ true, + ); assert.isDefined(root); assert.equal(root.kind, ts.SyntaxKind.SourceFile); const first = root.getFirstToken(); @@ -496,7 +511,12 @@ oh.no }); describe("getLastToken", () => { it("gets jsdoc", () => { - const root = ts.createSourceFile("foo.ts", "var a = true;/** comment */", ts.ScriptTarget.ES5, /*setParentNodes*/ true); + const root = ts.createSourceFile( + "foo.ts", + "var a = true;/** comment */", + ts.ScriptTarget.ES5, + /*setParentNodes*/ true, + ); assert.isDefined(root); const last = root.getLastToken(); assert.isDefined(last); @@ -505,7 +525,12 @@ oh.no }); describe("getStart", () => { it("runs when node with JSDoc but no parent pointers", () => { - const root = ts.createSourceFile("foo.ts", "/** */var a = true;", ts.ScriptTarget.ES5, /*setParentNodes*/ false); + const root = ts.createSourceFile( + "foo.ts", + "/** */var a = true;", + ts.ScriptTarget.ES5, + /*setParentNodes*/ false, + ); root.statements[0].getStart(root, /*includeJsDocComment*/ true); }); }); diff --git a/src/testRunner/unittests/moduleResolution.ts b/src/testRunner/unittests/moduleResolution.ts index 332ecb96d22e6..58c606219eb3a 100644 --- a/src/testRunner/unittests/moduleResolution.ts +++ b/src/testRunner/unittests/moduleResolution.ts @@ -7,7 +7,11 @@ interface File { symlinks?: string[]; } -function createModuleResolutionHost(baselines: string[], hasDirectoryExists: boolean, ...files: File[]): ts.ModuleResolutionHost { +function createModuleResolutionHost( + baselines: string[], + hasDirectoryExists: boolean, + ...files: File[] +): ts.ModuleResolutionHost { const map = new Map(); for (const file of files) { map.set(file.name, file); @@ -38,7 +42,10 @@ function createModuleResolutionHost(baselines: string[], hasDirectoryExists: boo realpath, directoryExists: path => directories.has(path), fileExists: path => { - assert.isTrue(directories.has(ts.getDirectoryPath(path)), `'fileExists' '${path}' request in non-existing directory`); + assert.isTrue( + directories.has(ts.getDirectoryPath(path)), + `'fileExists' '${path}' request in non-existing directory`, + ); return map.has(path); }, useCaseSensitiveFileNames: true, @@ -62,17 +69,34 @@ function runBaseline(scenario: string, baselines: readonly string[]) { describe("unittests:: moduleResolution:: Node module resolution - relative paths", () => { // node module resolution does _not_ implicitly append these extensions to an extensionless path (though will still attempt to load them if explicitly) - const nonImplicitExtensions = [ts.Extension.Mts, ts.Extension.Dmts, ts.Extension.Mjs, ts.Extension.Cts, ts.Extension.Dcts, ts.Extension.Cjs]; + const nonImplicitExtensions = [ + ts.Extension.Mts, + ts.Extension.Dmts, + ts.Extension.Mjs, + ts.Extension.Cts, + ts.Extension.Dcts, + ts.Extension.Cjs, + ]; const autoExtensions = ts.filter(ts.supportedTSExtensionsFlat, e => nonImplicitExtensions.indexOf(e) === -1); it("load as file", () => { const baselines: string[] = []; - testLoadAsFile("load as file with relative name in current directory", "/foo/bar/baz.ts", "/foo/bar/foo", "./foo"); + testLoadAsFile( + "load as file with relative name in current directory", + "/foo/bar/baz.ts", + "/foo/bar/foo", + "./foo", + ); testLoadAsFile("load as file with relative name in parent directory", "/foo/bar/baz.ts", "/foo/foo", "../foo"); testLoadAsFile("load as file with name starting with directory seperator", "/foo/bar/baz.ts", "/foo", "/foo"); testLoadAsFile("load as file with name starting with window root", "c:/foo/bar/baz.ts", "c:/foo", "c:/foo"); runBaseline("relative module name as file", baselines); - function testLoadAsFile(scenario: string, containingFileName: string, moduleFileNameNoExt: string, moduleName: string): void { + function testLoadAsFile( + scenario: string, + containingFileName: string, + moduleFileNameNoExt: string, + moduleName: string, + ): void { baselines.push(scenario); for (const ext of autoExtensions) { test(ext, /*hasDirectoryExists*/ true); @@ -82,8 +106,17 @@ describe("unittests:: moduleResolution:: Node module resolution - relative paths function test(ext: string, hasDirectoryExists: boolean) { const containingFile = { name: containingFileName }; const moduleFile = { name: moduleFileNameNoExt + ext }; - baselines.push(`Resolving "${moduleName}" from ${containingFile.name} when module has extension: ${ext}${hasDirectoryExists ? "" : " with host that doesnt have directoryExists"}`); - const resolution = ts.nodeModuleNameResolver(moduleName, containingFile.name, {}, createModuleResolutionHost(baselines, hasDirectoryExists, containingFile, moduleFile)); + baselines.push( + `Resolving "${moduleName}" from ${containingFile.name} when module has extension: ${ext}${ + hasDirectoryExists ? "" : " with host that doesnt have directoryExists" + }`, + ); + const resolution = ts.nodeModuleNameResolver( + moduleName, + containingFile.name, + {}, + createModuleResolutionHost(baselines, hasDirectoryExists, containingFile, moduleFile), + ); baselines.push(`Resolution:: ${JSON.stringify(resolution, /*replacer*/ undefined, 2)}`); baselines.push(""); } @@ -92,13 +125,25 @@ describe("unittests:: moduleResolution:: Node module resolution - relative paths it("module name as directory - load from 'typings'", () => { const baselines: string[] = []; - testLoadingFromPackageJson("/a/b/c/d.ts", "/a/b/c/bar/package.json", "c/d/e.d.ts", "/a/b/c/bar/c/d/e.d.ts", "./bar"); + testLoadingFromPackageJson( + "/a/b/c/d.ts", + "/a/b/c/bar/package.json", + "c/d/e.d.ts", + "/a/b/c/bar/c/d/e.d.ts", + "./bar", + ); testLoadingFromPackageJson("/a/b/c/d.ts", "/a/bar/package.json", "e.d.ts", "/a/bar/e.d.ts", "../../bar"); testLoadingFromPackageJson("/a/b/c/d.ts", "/bar/package.json", "e.d.ts", "/bar/e.d.ts", "/bar"); testLoadingFromPackageJson("c:/a/b/c/d.ts", "c:/bar/package.json", "e.d.ts", "c:/bar/e.d.ts", "c:/bar"); runBaseline("relative module name as directory", baselines); - function testLoadingFromPackageJson(containingFileName: string, packageJsonFileName: string, fieldRef: string, moduleFileName: string, moduleName: string): void { + function testLoadingFromPackageJson( + containingFileName: string, + packageJsonFileName: string, + fieldRef: string, + moduleFileName: string, + moduleName: string, + ): void { test(/*hasDirectoryExists*/ true); test(/*hasDirectoryExists*/ false); @@ -106,8 +151,17 @@ describe("unittests:: moduleResolution:: Node module resolution - relative paths const containingFile = { name: containingFileName }; const packageJson = { name: packageJsonFileName, content: JSON.stringify({ typings: fieldRef }) }; const moduleFile = { name: moduleFileName }; - baselines.push(`Resolving "${moduleName}" from ${containingFile.name} with typings: ${fieldRef}${hasDirectoryExists ? "" : " with host that doesnt have directoryExists"}`); - const resolution = ts.nodeModuleNameResolver(moduleName, containingFile.name, {}, createModuleResolutionHost(baselines, hasDirectoryExists, containingFile, packageJson, moduleFile)); + baselines.push( + `Resolving "${moduleName}" from ${containingFile.name} with typings: ${fieldRef}${ + hasDirectoryExists ? "" : " with host that doesnt have directoryExists" + }`, + ); + const resolution = ts.nodeModuleNameResolver( + moduleName, + containingFile.name, + {}, + createModuleResolutionHost(baselines, hasDirectoryExists, containingFile, packageJson, moduleFile), + ); baselines.push(`Resolution:: ${JSON.stringify(resolution, /*replacer*/ undefined, 2)}`); baselines.push(""); } @@ -134,8 +188,24 @@ describe("unittests:: moduleResolution:: Node module resolution - relative paths const indexPath = "/node_modules/b/index.d.ts"; const indexFile = { name: indexPath }; - baselines.push(`Resolving "b" from ${containingFile.name} with typings: ${JSON.stringify(typings)}${hasDirectoryExists ? "" : " with host that doesnt have directoryExists"}`); - const resolution = ts.nodeModuleNameResolver("b", containingFile.name, {}, createModuleResolutionHost(baselines, hasDirectoryExists, containingFile, packageJson, moduleFile, indexFile)); + baselines.push( + `Resolving "b" from ${containingFile.name} with typings: ${JSON.stringify(typings)}${ + hasDirectoryExists ? "" : " with host that doesnt have directoryExists" + }`, + ); + const resolution = ts.nodeModuleNameResolver( + "b", + containingFile.name, + {}, + createModuleResolutionHost( + baselines, + hasDirectoryExists, + containingFile, + packageJson, + moduleFile, + indexFile, + ), + ); baselines.push(`Resolution:: ${JSON.stringify(resolution, /*replacer*/ undefined, 2)}`); baselines.push(""); } @@ -151,8 +221,17 @@ describe("unittests:: moduleResolution:: Node module resolution - relative paths const containingFile = { name: "/a/b/c.ts" }; const packageJson = { name: "/a/b/foo/package.json", content: JSON.stringify({ main: "/c/d" }) }; const indexFile = { name: "/a/b/foo/index.d.ts" }; - baselines.push(`Resolving "./foo" from ${containingFile.name}${hasDirectoryExists ? "" : " with host that doesnt have directoryExists"}`); - const resolution = ts.nodeModuleNameResolver("./foo", containingFile.name, {}, createModuleResolutionHost(baselines, hasDirectoryExists, containingFile, packageJson, indexFile)); + baselines.push( + `Resolving "./foo" from ${containingFile.name}${ + hasDirectoryExists ? "" : " with host that doesnt have directoryExists" + }`, + ); + const resolution = ts.nodeModuleNameResolver( + "./foo", + containingFile.name, + {}, + createModuleResolutionHost(baselines, hasDirectoryExists, containingFile, packageJson, indexFile), + ); baselines.push(`Resolution:: ${JSON.stringify(resolution, /*replacer*/ undefined, 2)}`); baselines.push(""); } @@ -263,8 +342,17 @@ describe("unittests:: moduleResolution:: Node module resolution - non-relative p function test(hasDirectoryExists: boolean) { const containingFile = { name: "/a/b/c/d/e.ts" }; const moduleFile = { name: "/a/b/node_modules/foo.ts" }; - baselines.push(`Resolving "foo" from ${containingFile.name}${hasDirectoryExists ? "" : " with host that doesnt have directoryExists"}`); - const resolution = ts.nodeModuleNameResolver("foo", containingFile.name, {}, createModuleResolutionHost(baselines, hasDirectoryExists, containingFile, moduleFile)); + baselines.push( + `Resolving "foo" from ${containingFile.name}${ + hasDirectoryExists ? "" : " with host that doesnt have directoryExists" + }`, + ); + const resolution = ts.nodeModuleNameResolver( + "foo", + containingFile.name, + {}, + createModuleResolutionHost(baselines, hasDirectoryExists, containingFile, moduleFile), + ); baselines.push(`Resolution:: ${JSON.stringify(resolution, /*replacer*/ undefined, 2)}`); baselines.push(""); } @@ -279,8 +367,17 @@ describe("unittests:: moduleResolution:: Node module resolution - non-relative p function test(hasDirectoryExists: boolean) { const containingFile = { name: "/a/b/c/d/e.ts" }; const moduleFile = { name: "/a/b/node_modules/foo.d.ts" }; - baselines.push(`Resolving "foo" from ${containingFile.name}${hasDirectoryExists ? "" : " with host that doesnt have directoryExists"}`); - const resolution = ts.nodeModuleNameResolver("foo", containingFile.name, {}, createModuleResolutionHost(baselines, hasDirectoryExists, containingFile, moduleFile)); + baselines.push( + `Resolving "foo" from ${containingFile.name}${ + hasDirectoryExists ? "" : " with host that doesnt have directoryExists" + }`, + ); + const resolution = ts.nodeModuleNameResolver( + "foo", + containingFile.name, + {}, + createModuleResolutionHost(baselines, hasDirectoryExists, containingFile, moduleFile), + ); baselines.push(`Resolution:: ${JSON.stringify(resolution, /*replacer*/ undefined, 2)}`); baselines.push(""); } @@ -295,8 +392,17 @@ describe("unittests:: moduleResolution:: Node module resolution - non-relative p function test(hasDirectoryExists: boolean) { const containingFile: File = { name: "/a/node_modules/b/c/node_modules/d/e.ts" }; const moduleFile: File = { name: "/a/node_modules/foo/index.d.ts" }; - baselines.push(`Resolving "foo" from ${containingFile.name}${hasDirectoryExists ? "" : " with host that doesnt have directoryExists"}`); - const resolution = ts.nodeModuleNameResolver("foo", containingFile.name, {}, createModuleResolutionHost(baselines, hasDirectoryExists, containingFile, moduleFile)); + baselines.push( + `Resolving "foo" from ${containingFile.name}${ + hasDirectoryExists ? "" : " with host that doesnt have directoryExists" + }`, + ); + const resolution = ts.nodeModuleNameResolver( + "foo", + containingFile.name, + {}, + createModuleResolutionHost(baselines, hasDirectoryExists, containingFile, moduleFile), + ); baselines.push(`Resolution:: ${JSON.stringify(resolution, /*replacer*/ undefined, 2)}`); baselines.push(""); } @@ -380,7 +486,13 @@ describe("unittests:: moduleResolution:: Node module resolution - non-relative p }); describe("unittests:: moduleResolution:: Relative imports", () => { - function test(scenario: string, filesMapLike: ts.MapLike, currentDirectory: string, rootFiles: string[], relativeNamesToCheck: string[]) { + function test( + scenario: string, + filesMapLike: ts.MapLike, + currentDirectory: string, + rootFiles: string[], + relativeNamesToCheck: string[], + ) { it(scenario, () => { const files = new Map(Object.entries(filesMapLike)); const baselines: string[] = []; @@ -418,7 +530,9 @@ describe("unittests:: moduleResolution:: Relative imports", () => { // try to get file using a relative name for (const relativeFileName of relativeNamesToCheck) { - baselines.push(`getSourceFile by ${relativeFileName}: ${program.getSourceFile(relativeFileName)?.fileName}`); + baselines.push( + `getSourceFile by ${relativeFileName}: ${program.getSourceFile(relativeFileName)?.fileName}`, + ); } runBaseline(scenario, baselines); @@ -519,7 +633,10 @@ describe("unittests:: moduleResolution:: Files with different casing with forceC readFile: ts.notImplemented, }; const program = ts.createProgram(rootFiles, options, host); - const diagnostics = ts.sortAndDeduplicateDiagnostics([...program.getSemanticDiagnostics(), ...program.getOptionsDiagnostics()]); + const diagnostics = ts.sortAndDeduplicateDiagnostics([ + ...program.getSemanticDiagnostics(), + ...program.getOptionsDiagnostics(), + ]); baselines.push("Diagnostics::"); baselines.push(ts.formatDiagnostics(diagnostics, host), ""); runBaseline(scenario, baselines); @@ -655,19 +772,31 @@ describe("unittests:: moduleResolution:: baseUrl augmented module resolution", ( for (const moduleResolution of [ts.ModuleResolutionKind.Node10, ts.ModuleResolutionKind.Classic]) { const options: ts.CompilerOptions = { moduleResolution, baseUrl: "/root" }; { - baselines.push(`Resolving "folder2/file2" from ${file1.name}${hasDirectoryExists ? "" : " with host that doesnt have directoryExists"}`); + baselines.push( + `Resolving "folder2/file2" from ${file1.name}${ + hasDirectoryExists ? "" : " with host that doesnt have directoryExists" + }`, + ); const result = ts.resolveModuleName("folder2/file2", file1.name, options, host); baselines.push(`Resolution:: ${JSON.stringify(result, /*replacer*/ undefined, 2)}`); baselines.push(""); } { - baselines.push(`Resolving "./file3" from ${file2.name}${hasDirectoryExists ? "" : " with host that doesnt have directoryExists"}`); + baselines.push( + `Resolving "./file3" from ${file2.name}${ + hasDirectoryExists ? "" : " with host that doesnt have directoryExists" + }`, + ); const result = ts.resolveModuleName("./file3", file2.name, options, host); baselines.push(`Resolution:: ${JSON.stringify(result, /*replacer*/ undefined, 2)}`); baselines.push(""); } { - baselines.push(`Resolving "/root/folder1/file1" from ${file2.name}${hasDirectoryExists ? "" : " with host that doesnt have directoryExists"}`); + baselines.push( + `Resolving "/root/folder1/file1" from ${file2.name}${ + hasDirectoryExists ? "" : " with host that doesnt have directoryExists" + }`, + ); const result = ts.resolveModuleName("/root/folder1/file1", file2.name, options, host); baselines.push(`Resolution:: ${JSON.stringify(result, /*replacer*/ undefined, 2)}`); baselines.push(""); @@ -687,7 +816,10 @@ describe("unittests:: moduleResolution:: baseUrl augmented module resolution", ( const main: File = { name: "/root/a/b/main.ts" }; const m1: File = { name: "/root/m1.ts" }; // load file as module const m2: File = { name: "/root/m2/index.d.ts" }; // load folder as module - const m3: File = { name: "/root/m3/package.json", content: JSON.stringify({ typings: "dist/typings.d.ts" }) }; + const m3: File = { + name: "/root/m3/package.json", + content: JSON.stringify({ typings: "dist/typings.d.ts" }), + }; const m3Typings: File = { name: "/root/m3/dist/typings.d.ts" }; const m4: File = { name: "/root/node_modules/m4.ts" }; // fallback to node @@ -700,7 +832,11 @@ describe("unittests:: moduleResolution:: baseUrl augmented module resolution", ( check("m4", main); function check(name: string, caller: File) { - baselines.push(`Resolving "${name}" from ${caller.name}${hasDirectoryExists ? "" : " with host that doesnt have directoryExists"}`); + baselines.push( + `Resolving "${name}" from ${caller.name}${ + hasDirectoryExists ? "" : " with host that doesnt have directoryExists" + }`, + ); const result = ts.resolveModuleName(name, caller.name, options, host); baselines.push(`Resolution:: ${JSON.stringify(result, /*replacer*/ undefined, 2)}`); baselines.push(""); @@ -719,14 +855,22 @@ describe("unittests:: moduleResolution:: baseUrl augmented module resolution", ( const m1: File = { name: "/root/x/m1.ts" }; // load from base url const m2: File = { name: "/m2.ts" }; // fallback to classic - const options: ts.CompilerOptions = { moduleResolution: ts.ModuleResolutionKind.Classic, baseUrl: "/root/x", jsx: ts.JsxEmit.React }; + const options: ts.CompilerOptions = { + moduleResolution: ts.ModuleResolutionKind.Classic, + baseUrl: "/root/x", + jsx: ts.JsxEmit.React, + }; const host = createModuleResolutionHost(baselines, hasDirectoryExists, main, m1, m2); check("m1", main); check("m2", main); function check(name: string, caller: File) { - baselines.push(`Resolving "${name}" from ${caller.name}${hasDirectoryExists ? "" : " with host that doesnt have directoryExists"}`); + baselines.push( + `Resolving "${name}" from ${caller.name}${ + hasDirectoryExists ? "" : " with host that doesnt have directoryExists" + }`, + ); const result = ts.resolveModuleName(name, caller.name, options, host); baselines.push(`Resolution:: ${JSON.stringify(result, /*replacer*/ undefined, 2)}`); baselines.push(""); @@ -746,11 +890,24 @@ describe("unittests:: moduleResolution:: baseUrl augmented module resolution", ( const file1: File = { name: "/root/folder1/file1.ts" }; const file2: File = { name: "/root/generated/folder1/file2.ts" }; // load remapped file as module const file3: File = { name: "/root/generated/folder2/file3/index.d.ts" }; // load folder a module - const file4Typings: File = { name: "/root/generated/folder2/file4/package.json", content: JSON.stringify({ typings: "dist/types.d.ts" }) }; + const file4Typings: File = { + name: "/root/generated/folder2/file4/package.json", + content: JSON.stringify({ typings: "dist/types.d.ts" }), + }; const file4: File = { name: "/root/generated/folder2/file4/dist/types.d.ts" }; // load file pointed by typings const file5: File = { name: "/root/someanotherfolder/file5/index.d.ts" }; // load remapped module from folder const file6: File = { name: "/root/node_modules/file6.ts" }; // fallback to node - const host = createModuleResolutionHost(baselines, hasDirectoryExists, file1, file2, file3, file4, file4Typings, file5, file6); + const host = createModuleResolutionHost( + baselines, + hasDirectoryExists, + file1, + file2, + file3, + file4, + file4Typings, + file5, + file6, + ); const options: ts.CompilerOptions = { moduleResolution: ts.ModuleResolutionKind.Node10, @@ -778,7 +935,11 @@ describe("unittests:: moduleResolution:: baseUrl augmented module resolution", ( check("file6"); function check(name: string) { - baselines.push(`Resolving "${name}" from ${main.name}${hasDirectoryExists ? "" : " with host that doesnt have directoryExists"}`); + baselines.push( + `Resolving "${name}" from ${main.name}${ + hasDirectoryExists ? "" : " with host that doesnt have directoryExists" + }`, + ); const result = ts.resolveModuleName(name, main.name, options, host); baselines.push(`Resolution:: ${JSON.stringify(result, /*replacer*/ undefined, 2)}`); baselines.push(""); @@ -823,7 +984,11 @@ describe("unittests:: moduleResolution:: baseUrl augmented module resolution", ( check("folder1/file3"); function check(name: string) { - baselines.push(`Resolving "${name}" from ${main.name}${hasDirectoryExists ? "" : " with host that doesnt have directoryExists"}`); + baselines.push( + `Resolving "${name}" from ${main.name}${ + hasDirectoryExists ? "" : " with host that doesnt have directoryExists" + }`, + ); const result = ts.resolveModuleName(name, main.name, options, host); baselines.push(`Resolution:: ${JSON.stringify(result, /*replacer*/ undefined, 2)}`); baselines.push(""); @@ -855,7 +1020,11 @@ describe("unittests:: moduleResolution:: baseUrl augmented module resolution", ( check("../folder1/file1_1", file3); function check(name: string, container: File) { - baselines.push(`Resolving "${name}" from ${container.name}${hasDirectoryExists ? "" : " with host that doesnt have directoryExists"}`); + baselines.push( + `Resolving "${name}" from ${container.name}${ + hasDirectoryExists ? "" : " with host that doesnt have directoryExists" + }`, + ); const result = ts.resolveModuleName(name, container.name, options, host); baselines.push(`Resolution:: ${JSON.stringify(result, /*replacer*/ undefined, 2)}`); baselines.push(""); @@ -887,7 +1056,11 @@ describe("unittests:: moduleResolution:: baseUrl augmented module resolution", ( check("folder1/file1_1", file3); function check(name: string, container: File) { - baselines.push(`Resolving "${name}" from ${container.name}${hasDirectoryExists ? "" : " with host that doesnt have directoryExists"}`); + baselines.push( + `Resolving "${name}" from ${container.name}${ + hasDirectoryExists ? "" : " with host that doesnt have directoryExists" + }`, + ); const result = ts.resolveModuleName(name, container.name, options, host); baselines.push(`Resolution:: ${JSON.stringify(result, /*replacer*/ undefined, 2)}`); baselines.push(""); @@ -903,7 +1076,10 @@ describe("unittests:: moduleResolution:: baseUrl augmented module resolution", ( function test(hasDirectoryExists: boolean) { const app: File = { name: "/root/src/app.ts" }; - const libsPackage: File = { name: "/root/src/libs/guid/package.json", content: JSON.stringify({ typings: "dist/guid.d.ts" }) }; + const libsPackage: File = { + name: "/root/src/libs/guid/package.json", + content: JSON.stringify({ typings: "dist/guid.d.ts" }), + }; const libsTypings: File = { name: "/root/src/libs/guid/dist/guid.d.ts" }; const host = createModuleResolutionHost(baselines, hasDirectoryExists, app, libsPackage, libsTypings); const options: ts.CompilerOptions = { @@ -913,7 +1089,11 @@ describe("unittests:: moduleResolution:: baseUrl augmented module resolution", ( "libs/guid": ["src/libs/guid"], }, }; - baselines.push(`Resolving "libs/guid" from ${app.name}${hasDirectoryExists ? "" : " with host that doesnt have directoryExists"}`); + baselines.push( + `Resolving "libs/guid" from ${app.name}${ + hasDirectoryExists ? "" : " with host that doesnt have directoryExists" + }`, + ); const result = ts.resolveModuleName("libs/guid", app.name, options, host); baselines.push(`Resolution:: ${JSON.stringify(result, /*replacer*/ undefined, 2)}`); baselines.push(""); @@ -929,22 +1109,60 @@ describe("unittests:: moduleResolution:: ModuleResolutionHost.directoryExists", directoryExists: _ => false, }; - const result = ts.resolveModuleName("someName", "/a/b/c/d", { moduleResolution: ts.ModuleResolutionKind.Node10 }, host); + const result = ts.resolveModuleName("someName", "/a/b/c/d", { + moduleResolution: ts.ModuleResolutionKind.Node10, + }, host); assert(!result.resolvedModule); }); }); describe("unittests:: moduleResolution:: Type reference directive resolution: ", () => { - function testWorker(baselines: string[], hasDirectoryExists: boolean, typesRoot: string | undefined, typeDirective: string, initialFile: File, targetFile: File, ...otherFiles: File[]) { - const host = createModuleResolutionHost(baselines, hasDirectoryExists, ...[initialFile, targetFile].concat(...otherFiles)); - baselines.push(`Resolving "${typeDirective}" from ${initialFile.name} typesRoots: ${typesRoot ? `[${typesRoot}]` : undefined}${hasDirectoryExists ? "" : " with host that doesnt have directoryExists"}`); - const result = ts.resolveTypeReferenceDirective(typeDirective, initialFile.name, typesRoot ? { typeRoots: [typesRoot] } : {}, host); + function testWorker( + baselines: string[], + hasDirectoryExists: boolean, + typesRoot: string | undefined, + typeDirective: string, + initialFile: File, + targetFile: File, + ...otherFiles: File[] + ) { + const host = createModuleResolutionHost( + baselines, + hasDirectoryExists, + ...[initialFile, targetFile].concat(...otherFiles), + ); + baselines.push( + `Resolving "${typeDirective}" from ${initialFile.name} typesRoots: ${ + typesRoot ? `[${typesRoot}]` : undefined + }${hasDirectoryExists ? "" : " with host that doesnt have directoryExists"}`, + ); + const result = ts.resolveTypeReferenceDirective( + typeDirective, + initialFile.name, + typesRoot ? { typeRoots: [typesRoot] } : {}, + host, + ); baselines.push(`Resolution:: ${JSON.stringify(result, /*replacer*/ undefined, 2)}`); baselines.push(""); } - function test(baselines: string[], typesRoot: string, typeDirective: string, initialFile: File, targetFile: File, ...otherFiles: File[]) { - testWorker(baselines, /*hasDirectoryExists*/ false, typesRoot, typeDirective, initialFile, targetFile, ...otherFiles); + function test( + baselines: string[], + typesRoot: string, + typeDirective: string, + initialFile: File, + targetFile: File, + ...otherFiles: File[] + ) { + testWorker( + baselines, + /*hasDirectoryExists*/ false, + typesRoot, + typeDirective, + initialFile, + targetFile, + ...otherFiles, + ); } it("Can be resolved from primary location", () => { @@ -957,7 +1175,10 @@ describe("unittests:: moduleResolution:: Type reference directive resolution: ", { const f1 = { name: "/root/src/app.ts" }; const f2 = { name: "/root/src/types/lib/typings/lib.d.ts" }; - const packageFile = { name: "/root/src/types/lib/package.json", content: JSON.stringify({ types: "typings/lib.d.ts" }) }; + const packageFile = { + name: "/root/src/types/lib/package.json", + content: JSON.stringify({ types: "typings/lib.d.ts" }), + }; test(baselines, /*typesRoot*/ "/root/src/types", /* typeDirective */ "lib", f1, f2, packageFile); } { @@ -968,7 +1189,10 @@ describe("unittests:: moduleResolution:: Type reference directive resolution: ", { const f1 = { name: "/root/src/app.ts" }; const f2 = { name: "/root/src/node_modules/lib/typings/lib.d.ts" }; - const packageFile = { name: "/root/src/node_modules/lib/package.json", content: JSON.stringify({ types: "typings/lib.d.ts" }) }; + const packageFile = { + name: "/root/src/node_modules/lib/package.json", + content: JSON.stringify({ types: "typings/lib.d.ts" }), + }; test(baselines, /*typesRoot*/ "/root/src/types", /* typeDirective */ "lib", f1, f2, packageFile); } { @@ -979,7 +1203,10 @@ describe("unittests:: moduleResolution:: Type reference directive resolution: ", { const f1 = { name: "/root/src/app.ts" }; const f2 = { name: "/root/src/node_modules/@types/lib/typings/lib.d.ts" }; - const packageFile = { name: "/root/src/node_modules/@types/lib/package.json", content: JSON.stringify({ types: "typings/lib.d.ts" }) }; + const packageFile = { + name: "/root/src/node_modules/@types/lib/package.json", + content: JSON.stringify({ types: "typings/lib.d.ts" }), + }; test(baselines, /*typesRoot*/ "/root/src/types", /* typeDirective */ "lib", f1, f2, packageFile); } runBaseline("type reference from primary location", baselines); @@ -999,7 +1226,10 @@ describe("unittests:: moduleResolution:: Type reference directive resolution: ", { const f1 = { name: "/root/src/app.ts" }; const f2 = { name: "/root/node_modules/lib/typings/lib.d.ts" }; - const packageFile = { name: "/root/node_modules/lib/package.json", content: JSON.stringify({ typings: "typings/lib.d.ts" }) }; + const packageFile = { + name: "/root/node_modules/lib/package.json", + content: JSON.stringify({ typings: "typings/lib.d.ts" }), + }; test(baselines, /*typesRoot*/ "/root/src/types", /* typeDirective */ "lib", f1, f2, packageFile); } { @@ -1010,7 +1240,10 @@ describe("unittests:: moduleResolution:: Type reference directive resolution: ", { const f1 = { name: "/root/src/app.ts" }; const f2 = { name: "/root/node_modules/@types/lib/typings/lib.d.ts" }; - const packageFile = { name: "/root/node_modules/@types/lib/package.json", content: JSON.stringify({ typings: "typings/lib.d.ts" }) }; + const packageFile = { + name: "/root/node_modules/@types/lib/package.json", + content: JSON.stringify({ typings: "typings/lib.d.ts" }), + }; test(baselines, /*typesRoot*/ "/root/src/types", /* typeDirective */ "lib", f1, f2, packageFile); } runBaseline("type reference from secondary location", baselines); @@ -1033,7 +1266,10 @@ describe("unittests:: moduleResolution:: Type reference directive resolution: ", files.forEach(file => baselines.push(`//// [${file.name}]\n${file.content || ""}`, "")); const names = ts.map(files, f => f.name); - const sourceFiles = ts.arrayToMap(ts.map(files, f => ts.createSourceFile(f.name, f.content, ts.ScriptTarget.ES2015)), f => f.fileName); + const sourceFiles = ts.arrayToMap( + ts.map(files, f => ts.createSourceFile(f.name, f.content, ts.ScriptTarget.ES2015)), + f => f.fileName, + ); const compilerHost: ts.CompilerHost = { fileExists: fileName => sourceFiles.has(fileName), getSourceFile: fileName => sourceFiles.get(fileName), @@ -1124,8 +1360,22 @@ describe("unittests:: moduleResolution:: Type reference directive resolution: ", const baselines: string[] = []; const initialFile = { name: "/root/src/background/app.ts" }; const targetFile = { name: "/root/src/typedefs/filesystem.d.ts" }; - testWorker(baselines, /*hasDirectoryExists*/ true, /*typesRoot*/ undefined, /*typeDirective*/ "../typedefs/filesystem", initialFile, targetFile); - testWorker(baselines, /*hasDirectoryExists*/ false, /*typesRoot*/ undefined, /*typeDirective*/ "../typedefs/filesystem", initialFile, targetFile); + testWorker( + baselines, + /*hasDirectoryExists*/ true, + /*typesRoot*/ undefined, + /*typeDirective*/ "../typedefs/filesystem", + initialFile, + targetFile, + ); + testWorker( + baselines, + /*hasDirectoryExists*/ false, + /*typesRoot*/ undefined, + /*typeDirective*/ "../typedefs/filesystem", + initialFile, + targetFile, + ); runBaseline("typeReferenceDirective is relative and in a sibling folder", baselines); }); }); diff --git a/src/testRunner/unittests/parsePseudoBigInt.ts b/src/testRunner/unittests/parsePseudoBigInt.ts index affe01a2d0d3d..52e3f835ca2f8 100644 --- a/src/testRunner/unittests/parsePseudoBigInt.ts +++ b/src/testRunner/unittests/parsePseudoBigInt.ts @@ -55,7 +55,9 @@ describe("unittests:: BigInt literal base conversions", () => { "123456789012345678901234567890", ); assert.equal( - ts.parsePseudoBigInt("0b1100011101110100100001111111101101100001101110011111000001110111001001110001111110000101011010010n"), + ts.parsePseudoBigInt( + "0b1100011101110100100001111111101101100001101110011111000001110111001001110001111110000101011010010n", + ), "123456789012345678901234567890", ); assert.equal( diff --git a/src/testRunner/unittests/paths.ts b/src/testRunner/unittests/paths.ts index 33de6b314914c..8bc2567eb24d7 100644 --- a/src/testRunner/unittests/paths.ts +++ b/src/testRunner/unittests/paths.ts @@ -285,11 +285,23 @@ describe("unittests:: core paths", () => { assert.strictEqual(ts.getRelativePathFromDirectory("file:///a/", "file:///a", /*ignoreCase*/ false), ""); assert.strictEqual(ts.getRelativePathFromDirectory("file:///a", "file:///", /*ignoreCase*/ false), ".."); assert.strictEqual(ts.getRelativePathFromDirectory("file:///a", "file:///b", /*ignoreCase*/ false), "../b"); - assert.strictEqual(ts.getRelativePathFromDirectory("file:///a/b", "file:///b", /*ignoreCase*/ false), "../../b"); - assert.strictEqual(ts.getRelativePathFromDirectory("file:///a/b/c", "file:///b", /*ignoreCase*/ false), "../../../b"); - assert.strictEqual(ts.getRelativePathFromDirectory("file:///a/b/c", "file:///b/c", /*ignoreCase*/ false), "../../../b/c"); + assert.strictEqual( + ts.getRelativePathFromDirectory("file:///a/b", "file:///b", /*ignoreCase*/ false), + "../../b", + ); + assert.strictEqual( + ts.getRelativePathFromDirectory("file:///a/b/c", "file:///b", /*ignoreCase*/ false), + "../../../b", + ); + assert.strictEqual( + ts.getRelativePathFromDirectory("file:///a/b/c", "file:///b/c", /*ignoreCase*/ false), + "../../../b/c", + ); assert.strictEqual(ts.getRelativePathFromDirectory("file:///a/b/c", "file:///a/b", /*ignoreCase*/ false), ".."); - assert.strictEqual(ts.getRelativePathFromDirectory("file:///c:", "file:///d:", /*ignoreCase*/ false), "file:///d:/"); + assert.strictEqual( + ts.getRelativePathFromDirectory("file:///c:", "file:///d:", /*ignoreCase*/ false), + "file:///d:/", + ); }); it("toFileNameLowerCase", () => { assert.strictEqual( diff --git a/src/testRunner/unittests/printer.ts b/src/testRunner/unittests/printer.ts index dd724ed73f855..22843fe13d1dc 100644 --- a/src/testRunner/unittests/printer.ts +++ b/src/testRunner/unittests/printer.ts @@ -5,9 +5,16 @@ import * as vfs from "../_namespaces/vfs"; describe("unittests:: PrinterAPI", () => { function makePrintsCorrectly(prefix: string) { - return function printsCorrectly(name: string, options: ts.PrinterOptions, printCallback: (printer: ts.Printer) => string) { + return function printsCorrectly( + name: string, + options: ts.PrinterOptions, + printCallback: (printer: ts.Printer) => string, + ) { it(name, () => { - Harness.Baseline.runBaseline(`printerApi/${prefix}.${name}.js`, printCallback(ts.createPrinter({ newLine: ts.NewLineKind.CarriageReturnLineFeed, ...options }))); + Harness.Baseline.runBaseline( + `printerApi/${prefix}.${name}.js`, + printCallback(ts.createPrinter({ newLine: ts.NewLineKind.CarriageReturnLineFeed, ...options })), + ); }); }; } @@ -64,13 +71,34 @@ describe("unittests:: PrinterAPI", () => { // https://github.com/microsoft/TypeScript/issues/14948 // eslint-disable-next-line no-template-curly-in-string - printsCorrectly("templateLiteral", {}, printer => printer.printFile(ts.createSourceFile("source.ts", "let greeting = `Hi ${name}, how are you?`;", ts.ScriptTarget.ES2017))); + printsCorrectly( + "templateLiteral", + {}, + printer => + printer.printFile( + ts.createSourceFile( + "source.ts", + "let greeting = `Hi ${name}, how are you?`;", + ts.ScriptTarget.ES2017, + ), + ), + ); // https://github.com/microsoft/TypeScript/issues/18071 - printsCorrectly("regularExpressionLiteral", {}, printer => printer.printFile(ts.createSourceFile("source.ts", "let regex = /abc/;", ts.ScriptTarget.ES2017))); + printsCorrectly( + "regularExpressionLiteral", + {}, + printer => + printer.printFile(ts.createSourceFile("source.ts", "let regex = /abc/;", ts.ScriptTarget.ES2017)), + ); // https://github.com/microsoft/TypeScript/issues/22239 - printsCorrectly("importStatementRemoveComments", { removeComments: true }, printer => printer.printFile(ts.createSourceFile("source.ts", "import {foo} from 'foo';", ts.ScriptTarget.ESNext))); + printsCorrectly( + "importStatementRemoveComments", + { removeComments: true }, + printer => + printer.printFile(ts.createSourceFile("source.ts", "import {foo} from 'foo';", ts.ScriptTarget.ESNext)), + ); printsCorrectly("classHeritageClauses", {}, printer => printer.printFile(ts.createSourceFile( "source.ts", @@ -121,7 +149,8 @@ describe("unittests:: PrinterAPI", () => { const host = new fakes.CompilerHost( new vfs.FileSystem(/*ignoreCase*/ true, { files: { - "/test.d.ts": `/// \n/// \n/// { ts.EmitHint.Unspecified, ts.factory.createNewExpression( ts.factory.createPropertyAccessExpression( - ts.factory.createCallExpression(ts.factory.createIdentifier("f"), /*typeArguments*/ undefined, /*argumentsArray*/ undefined), + ts.factory.createCallExpression( + ts.factory.createIdentifier("f"), + /*typeArguments*/ undefined, + /*argumentsArray*/ undefined, + ), "x", ), /*typeArguments*/ undefined, diff --git a/src/testRunner/unittests/programApi.ts b/src/testRunner/unittests/programApi.ts index 1d3d9528db3d4..f21aba788c7f9 100644 --- a/src/testRunner/unittests/programApi.ts +++ b/src/testRunner/unittests/programApi.ts @@ -9,7 +9,12 @@ function verifyMissingFilePaths(missingPaths: readonly ts.Path[], expected: read const map = new Set(expected); for (const missing of missingPaths) { const value = map.has(missing); - assert.isTrue(value, `${missing} to be ${value === undefined ? "not present" : "present only once"}, in actual: ${missingPaths} expected: ${expected}`); + assert.isTrue( + value, + `${missing} to be ${ + value === undefined ? "not present" : "present only once" + }, in actual: ${missingPaths} expected: ${expected}`, + ); map.delete(missing); } const notFound = ts.arrayFrom(ts.mapDefinedIterator(map.keys(), k => map.has(k) ? k : undefined)); @@ -31,10 +36,10 @@ describe("unittests:: programApi:: Program.getMissingFilePaths", () => { const referenceFile = new documents.TextDocument( referenceFileName, - '/// \n' + // Absolute - '/// \n' + // Relative - '/// \n' + // Unqualified - '/// \n', // No extension + '/// \n' // Absolute + + '/// \n' // Relative + + '/// \n' // Unqualified + + '/// \n', // No extension ); const testCompilerHost = new fakes.CompilerHost( @@ -65,7 +70,11 @@ describe("unittests:: programApi:: Program.getMissingFilePaths", () => { }); it("handles a mix of present and missing root files", () => { - const program = ts.createProgram(["./nonexistent0.ts", emptyFileRelativePath, "./nonexistent1.ts"], options, testCompilerHost); + const program = ts.createProgram( + ["./nonexistent0.ts", emptyFileRelativePath, "./nonexistent1.ts"], + options, + testCompilerHost, + ); const missing = program.getMissingFilePaths(); verifyMissingFilePaths(missing, ["d:/pretend/nonexistent0.ts", "d:/pretend/nonexistent1.ts"]); }); @@ -112,7 +121,11 @@ describe("unittests:: programApi:: Program.getMissingFilePaths", () => { }`; const host: ts.CompilerHost = { - getSourceFile: (fileName: string, languageVersion: ts.ScriptTarget, _onError?: (message: string) => void) => { + getSourceFile: ( + fileName: string, + languageVersion: ts.ScriptTarget, + _onError?: (message: string) => void, + ) => { return fileName === "test.ts" ? ts.createSourceFile(fileName, testSource, languageVersion) : undefined; }, getDefaultLibFileName: () => "", @@ -136,7 +149,10 @@ describe("unittests:: programApi:: Program.getMissingFilePaths", () => { const program = ts.createProgram(["test.ts"], { module: ts.ModuleKind.ES2015 }, host); assert(program.getSourceFiles().length === 1, "expected 'getSourceFiles' length to be 1"); assert(program.getMissingFilePaths().length === 0, "expected 'getMissingFilePaths' length to be 0"); - assert((program.getFileProcessingDiagnostics()?.length || 0) === 0, "expected 'getFileProcessingDiagnostics' length to be 0"); + assert( + (program.getFileProcessingDiagnostics()?.length || 0) === 0, + "expected 'getFileProcessingDiagnostics' length to be 0", + ); }); }); @@ -147,13 +163,23 @@ describe("unittests:: Program.isSourceFileFromExternalLibrary", () => { const bar = new documents.TextDocument("/node_modules/bar/index.d.ts", 'import * as foo from "foo";'); const fooPackageJsonText = '{ "name": "foo", "version": "1.2.3" }'; const fooIndexText = "export const x: number;"; - const barFooPackage = new documents.TextDocument("/node_modules/bar/node_modules/foo/package.json", fooPackageJsonText); + const barFooPackage = new documents.TextDocument( + "/node_modules/bar/node_modules/foo/package.json", + fooPackageJsonText, + ); const barFooIndex = new documents.TextDocument("/node_modules/bar/node_modules/foo/index.d.ts", fooIndexText); const fooPackage = new documents.TextDocument("/node_modules/foo/package.json", fooPackageJsonText); const fooIndex = new documents.TextDocument("/node_modules/foo/index.d.ts", fooIndexText); - const fs = vfs.createFromFileSystem(Harness.IO, /*ignoreCase*/ false, { documents: [a, bar, barFooPackage, barFooIndex, fooPackage, fooIndex], cwd: "/" }); - const program = ts.createProgram(["/a.ts"], ts.emptyOptions, new fakes.CompilerHost(fs, { newLine: ts.NewLineKind.LineFeed })); + const fs = vfs.createFromFileSystem(Harness.IO, /*ignoreCase*/ false, { + documents: [a, bar, barFooPackage, barFooIndex, fooPackage, fooIndex], + cwd: "/", + }); + const program = ts.createProgram( + ["/a.ts"], + ts.emptyOptions, + new fakes.CompilerHost(fs, { newLine: ts.NewLineKind.LineFeed }), + ); assertIsExternal(program, [a, bar, barFooIndex, fooIndex], f => f !== a); }); @@ -161,15 +187,27 @@ describe("unittests:: Program.isSourceFileFromExternalLibrary", () => { const a = new documents.TextDocument("/a.ts", '/// '); const fooIndex = new documents.TextDocument("/node_modules/foo/index.d.ts", "declare const foo: number;"); const fs = vfs.createFromFileSystem(Harness.IO, /*ignoreCase*/ false, { documents: [a, fooIndex], cwd: "/" }); - const program = ts.createProgram(["/a.ts"], ts.emptyOptions, new fakes.CompilerHost(fs, { newLine: ts.NewLineKind.LineFeed })); + const program = ts.createProgram( + ["/a.ts"], + ts.emptyOptions, + new fakes.CompilerHost(fs, { newLine: ts.NewLineKind.LineFeed }), + ); assertIsExternal(program, [a, fooIndex], f => f !== a); }); - function assertIsExternal(program: ts.Program, files: readonly documents.TextDocument[], isExternalExpected: (file: documents.TextDocument) => boolean): void { + function assertIsExternal( + program: ts.Program, + files: readonly documents.TextDocument[], + isExternalExpected: (file: documents.TextDocument) => boolean, + ): void { for (const file of files) { const actual = program.isSourceFileFromExternalLibrary(program.getSourceFile(file.file)!); const expected = isExternalExpected(file); - assert.equal(actual, expected, `Expected ${file.file} isSourceFileFromExternalLibrary to be ${expected}, got ${actual}`); + assert.equal( + actual, + expected, + `Expected ${file.file} isSourceFileFromExternalLibrary to be ${expected}, got ${actual}`, + ); } } }); @@ -180,7 +218,11 @@ describe("unittests:: Program.getNodeCount / Program.getIdentifierCount", () => const pkg = new documents.TextDocument("/package.json", '{"version": "1.0.0"}'); const fs = vfs.createFromFileSystem(Harness.IO, /*ignoreCase*/ false, { documents: [main, pkg], cwd: "/" }); - const program = ts.createProgram(["/main.ts"], { resolveJsonModule: true }, new fakes.CompilerHost(fs, { newLine: ts.NewLineKind.LineFeed })); + const program = ts.createProgram( + ["/main.ts"], + { resolveJsonModule: true }, + new fakes.CompilerHost(fs, { newLine: ts.NewLineKind.LineFeed }), + ); const json = program.getSourceFile("/package.json")!; assert.equal(json.scriptKind, ts.ScriptKind.JSON); @@ -197,10 +239,16 @@ describe("unittests:: programApi:: Program.getTypeChecker / Program.getSemanticD const main = new documents.TextDocument("/main.ts", "0 as const"); const fs = vfs.createFromFileSystem(Harness.IO, /*ignoreCase*/ false, { documents: [main], cwd: "/" }); - const program = ts.createProgram(["/main.ts"], {}, new fakes.CompilerHost(fs, { newLine: ts.NewLineKind.LineFeed })); + const program = ts.createProgram( + ["/main.ts"], + {}, + new fakes.CompilerHost(fs, { newLine: ts.NewLineKind.LineFeed }), + ); const typeChecker = program.getTypeChecker(); const sourceFile = program.getSourceFile("main.ts")!; - typeChecker.getTypeAtLocation(((sourceFile.statements[0] as ts.ExpressionStatement).expression as ts.AsExpression).type); + typeChecker.getTypeAtLocation( + ((sourceFile.statements[0] as ts.ExpressionStatement).expression as ts.AsExpression).type, + ); const diag = program.getSemanticDiagnostics(); assert.isEmpty(diag); }); @@ -209,7 +257,11 @@ describe("unittests:: programApi:: Program.getTypeChecker / Program.getSemanticD const mod = new documents.TextDocument("/module.d.ts", "declare const foo: any;"); const fs = vfs.createFromFileSystem(Harness.IO, /*ignoreCase*/ false, { documents: [main, mod], cwd: "/" }); - const program = ts.createProgram(["/main.ts"], {}, new fakes.CompilerHost(fs, { newLine: ts.NewLineKind.LineFeed })); + const program = ts.createProgram( + ["/main.ts"], + {}, + new fakes.CompilerHost(fs, { newLine: ts.NewLineKind.LineFeed }), + ); const sourceFile = program.getSourceFile("main.ts")!; const typeChecker = program.getTypeChecker(); diff --git a/src/testRunner/unittests/publicApi.ts b/src/testRunner/unittests/publicApi.ts index 2adc444b663e4..3143a6816ef69 100644 --- a/src/testRunner/unittests/publicApi.ts +++ b/src/testRunner/unittests/publicApi.ts @@ -32,7 +32,10 @@ describe("unittests:: Public APIs", () => { }; const host = new fakes.CompilerHost(sys, options); const result = compiler.compileFiles(host, [`${vfs.srcFolder}/${fileName}`], options); - assert(!result.diagnostics || !result.diagnostics.length, Harness.Compiler.minimalDiagnosticsToString(result.diagnostics, /*pretty*/ true)); + assert( + !result.diagnostics || !result.diagnostics.length, + Harness.Compiler.minimalDiagnosticsToString(result.diagnostics, /*pretty*/ true), + ); }); } @@ -62,7 +65,10 @@ describe("unittests:: Public APIs:: token to string", () => { describe("unittests:: Public APIs:: createPrivateIdentifier", () => { it("throws when name doesn't start with #", () => { - assert.throw(() => ts.factory.createPrivateIdentifier("not"), "Debug Failure. First character of private identifier must be #: not"); + assert.throw( + () => ts.factory.createPrivateIdentifier("not"), + "Debug Failure. First character of private identifier must be #: not", + ); }); }); @@ -76,7 +82,12 @@ describe("unittests:: Public APIs:: JSDoc newlines", () => { */ function test() {}`; - const testSourceFile = ts.createSourceFile(testFilePath, testFileText, ts.ScriptTarget.Latest, /*setParentNodes*/ true); + const testSourceFile = ts.createSourceFile( + testFilePath, + testFileText, + ts.ScriptTarget.Latest, + /*setParentNodes*/ true, + ); const funcDec = testSourceFile.statements.find(ts.isFunctionDeclaration)!; const tags = ts.getJSDocTags(funcDec); assert.isDefined(tags[0].comment); @@ -162,7 +173,8 @@ describe("unittests:: Public APIs:: getTypeAtLocation", () => { const checker = program.getTypeChecker(); const file = program.getSourceFile("/file.ts")!; - const [declaration] = (ts.findLast(file.statements, ts.isVariableStatement) as ts.VariableStatement).declarationList.declarations; + const [declaration] = + (ts.findLast(file.statements, ts.isVariableStatement) as ts.VariableStatement).declarationList.declarations; assert.equal(checker.getTypeAtLocation(declaration.initializer!).flags, ts.TypeFlags.Object); }); @@ -183,7 +195,8 @@ describe("unittests:: Public APIs:: getTypeAtLocation", () => { const checker = program.getTypeChecker(); const file = program.getSourceFile("/file.ts")!; - const [declaration] = (ts.findLast(file.statements, ts.isVariableStatement) as ts.VariableStatement).declarationList.declarations; + const [declaration] = + (ts.findLast(file.statements, ts.isVariableStatement) as ts.VariableStatement).declarationList.declarations; assert.equal(checker.getTypeAtLocation(declaration).flags, ts.TypeFlags.Any); }); }); @@ -200,11 +213,19 @@ describe("unittests:: Public APIs:: validateLocaleAndSetLanguage", () => { getExecutingFilePath: () => "/tsc.js", resolvePath: ts.identity, fileExists: fileName => { - assert.isTrue(expectedToReadFile, `Locale : ${locale} ${expectedToReadFile ? "should" : "should not"} check if ${fileName} exists.`); + assert.isTrue( + expectedToReadFile, + `Locale : ${locale} ${ + expectedToReadFile ? "should" : "should not" + } check if ${fileName} exists.`, + ); return expectedToReadFile; }, readFile: fileName => { - assert.isTrue(expectedToReadFile, `Locale : ${locale} ${expectedToReadFile ? "should" : "should not"} read ${fileName}.`); + assert.isTrue( + expectedToReadFile, + `Locale : ${locale} ${expectedToReadFile ? "should" : "should not"} read ${fileName}.`, + ); // Throw error here so that actual change to localized diagnostics messages doesnt take place throw new Error("cannot read file"); }, diff --git a/src/testRunner/unittests/reuseProgramStructure.ts b/src/testRunner/unittests/reuseProgramStructure.ts index e066c5a334536..dbf94350e5d44 100644 --- a/src/testRunner/unittests/reuseProgramStructure.ts +++ b/src/testRunner/unittests/reuseProgramStructure.ts @@ -21,7 +21,13 @@ import { describe("unittests:: Reuse program structure:: General", () => { function baselineCache(baselines: string[], cacheType: string, cache: ts.ModeAwareCache | undefined) { baselines.push(`${cacheType}: ${!cache ? cache : ""}`); - cache?.forEach((resolved, key, mode) => baselines.push(`${key}: ${mode ? ts.getNameOfCompilerOptionValue(mode, ts.moduleOptionDeclaration.type) + ": " : ""}${JSON.stringify(resolved, /*replacer*/ undefined, 2)}`)); + cache?.forEach((resolved, key, mode) => + baselines.push( + `${key}: ${mode ? ts.getNameOfCompilerOptionValue(mode, ts.moduleOptionDeclaration.type) + ": " : ""}${ + JSON.stringify(resolved, /*replacer*/ undefined, 2) + }`, + ) + ); } function baselineProgram(baselines: string[], program: ts.Program, host?: TestCompilerHost) { baselines.push(`Program Reused:: ${(ts as any).StructureIsReused[program.structureIsReused]}`); @@ -86,7 +92,10 @@ describe("unittests:: Reuse program structure:: General", () => { { name: "/a.ts", text: SourceText.New("", "import {b} from 'b'", "var a = b;") }, { name: "/node_modules/b/index.d.ts", text: SourceText.New("", "export * from './internal';", "") }, { name: "/node_modules/b/internal.d.ts", text: SourceText.New("", "", "export const b = 1;") }, - { name: "/node_modules/b/package.json", text: SourceText.New("", "", JSON.stringify({ name: "b", version: "1.2.3" })) }, + { + name: "/node_modules/b/package.json", + text: SourceText.New("", "", JSON.stringify({ name: "b", version: "1.2.3" })), + }, ]; const options: ts.CompilerOptions = { target, moduleResolution: ts.ModuleResolutionKind.Node10 }; @@ -171,16 +180,29 @@ describe("unittests:: Reuse program structure:: General", () => { const program1 = newProgram(getFiles(), ["a.ts"], { target, module: ts.ModuleKind.CommonJS, rootDir: "/a/b" }); const baselines: string[] = []; baselineProgram(baselines, program1); - const program2 = updateProgram(program1, ["a.ts"], { target, module: ts.ModuleKind.CommonJS, rootDir: "/a/c" }, ts.noop); + const program2 = updateProgram( + program1, + ["a.ts"], + { target, module: ts.ModuleKind.CommonJS, rootDir: "/a/c" }, + ts.noop, + ); baselineProgram(baselines, program2); runBaseline("rootdir changes", baselines); }); it("fails if config path changes", () => { - const program1 = newProgram(getFiles(), ["a.ts"], { target, module: ts.ModuleKind.CommonJS, configFilePath: "/a/b/tsconfig.json" }); + const program1 = newProgram(getFiles(), ["a.ts"], { + target, + module: ts.ModuleKind.CommonJS, + configFilePath: "/a/b/tsconfig.json", + }); const baselines: string[] = []; baselineProgram(baselines, program1); - const program2 = updateProgram(program1, ["a.ts"], { target, module: ts.ModuleKind.CommonJS, configFilePath: "/a/c/tsconfig.json" }, ts.noop); + const program2 = updateProgram(program1, ["a.ts"], { + target, + module: ts.ModuleKind.CommonJS, + configFilePath: "/a/c/tsconfig.json", + }, ts.noop); baselineProgram(baselines, program2); runBaseline("config path changes", baselines); }); @@ -201,7 +223,10 @@ describe("unittests:: Reuse program structure:: General", () => { const program1 = newProgram(files, ["a.ts"], options); const baselines: string[] = []; baselineProgram(baselines, program1); - const newTexts: NamedSourceText[] = files.concat([{ name: "non-existing-file.ts", text: SourceText.New("", "", `var x = 1`) }]); + const newTexts: NamedSourceText[] = files.concat([{ + name: "non-existing-file.ts", + text: SourceText.New("", "", `var x = 1`), + }]); const program2 = updateProgram(program1, ["a.ts"], options, ts.noop, newTexts); baselineProgram(baselines, program2); runBaseline("missing file is created", baselines); @@ -267,7 +292,10 @@ describe("unittests:: Reuse program structure:: General", () => { let sourceFile = program1.getSourceFile("/a.ts")!; const baselines: string[] = []; baselineProgram(baselines, program1, host); - sourceFile = ts.updateSourceFile(sourceFile, "'use strict';" + sourceFile.text, { newLength: "'use strict';".length, span: { start: 0, length: 0 } }); + sourceFile = ts.updateSourceFile(sourceFile, "'use strict';" + sourceFile.text, { + newLength: "'use strict';".length, + span: { start: 0, length: 0 }, + }); baselines.push(`parent pointers are updated: ${sourceFile.statements[2].getSourceFile() === sourceFile}`); const updateHost: TestCompilerHost = { ...host, @@ -315,10 +343,20 @@ describe("unittests:: Reuse program structure:: General", () => { }); it("fetches imports after npm install", () => { - const file1Ts = { name: "file1.ts", text: SourceText.New("", `import * as a from "a";`, "const myX: number = a.x;") }; + const file1Ts = { + name: "file1.ts", + text: SourceText.New("", `import * as a from "a";`, "const myX: number = a.x;"), + }; const file2Ts = { name: "file2.ts", text: SourceText.New("", "", "") }; - const indexDTS = { name: "node_modules/a/index.d.ts", text: SourceText.New("", "export declare let x: number;", "") }; - const options: ts.CompilerOptions = { target: ts.ScriptTarget.ES2015, traceResolution: true, moduleResolution: ts.ModuleResolutionKind.Node10 }; + const indexDTS = { + name: "node_modules/a/index.d.ts", + text: SourceText.New("", "export declare let x: number;", ""), + }; + const options: ts.CompilerOptions = { + target: ts.ScriptTarget.ES2015, + traceResolution: true, + moduleResolution: ts.ModuleResolutionKind.Node10, + }; const rootFiles = [file1Ts, file2Ts]; const filesAfterNpmInstall = [file1Ts, file2Ts, indexDTS]; const initialProgram = newProgram(rootFiles, rootFiles.map(f => f.name), options); @@ -362,8 +400,14 @@ describe("unittests:: Reuse program structure:: General", () => { { name: "a2.ts", text: SourceText.New("", "", "let x = 1;") }, { name: "b1.ts", text: SourceText.New("", "export class B { x: number; }", "") }, { name: "b2.ts", text: SourceText.New("", "export class B { x: number; }", "") }, - { name: "node_modules/@types/typerefs1/index.d.ts", text: SourceText.New("", "", "declare let z: string;") }, - { name: "node_modules/@types/typerefs2/index.d.ts", text: SourceText.New("", "", "declare let z: string;") }, + { + name: "node_modules/@types/typerefs1/index.d.ts", + text: SourceText.New("", "", "declare let z: string;"), + }, + { + name: "node_modules/@types/typerefs2/index.d.ts", + text: SourceText.New("", "", "declare let z: string;"), + }, { name: "f1.ts", text: SourceText.New( @@ -382,13 +426,19 @@ describe("unittests:: Reuse program structure:: General", () => { }, ]; - const options: ts.CompilerOptions = { target: ts.ScriptTarget.ES2015, traceResolution: true, moduleResolution: ts.ModuleResolutionKind.Classic }; + const options: ts.CompilerOptions = { + target: ts.ScriptTarget.ES2015, + traceResolution: true, + moduleResolution: ts.ModuleResolutionKind.Classic, + }; const program1 = newProgram(files, files.map(f => f.name), options); const baselines: string[] = []; baselineProgram(baselines, program1); const indexOfF1 = 6; const program2 = updateProgram(program1, program1.getRootFileNames(), options, f => { - const newSourceText = f[indexOfF1].text.updateReferences(`/// ${newLine}/// `); + const newSourceText = f[indexOfF1].text.updateReferences( + `/// ${newLine}/// `, + ); f[indexOfF1] = { name: "f1.ts", text: newSourceText }; }); baselineProgram(baselines, program2); @@ -433,7 +483,10 @@ describe("unittests:: Reuse program structure:: General", () => { const root = "/a.ts"; const compilerOptions = { target, moduleResolution: ts.ModuleResolutionKind.Node10 }; - function createRedirectProgram(useGetSourceFileByPath: boolean, options?: { bText: string; bVersion: string; }): ProgramWithSourceTexts { + function createRedirectProgram( + useGetSourceFileByPath: boolean, + options?: { bText: string; bVersion: string; }, + ): ProgramWithSourceTexts { const files: NamedSourceText[] = [ { name: "/node_modules/a/index.d.ts", @@ -453,11 +506,19 @@ describe("unittests:: Reuse program structure:: General", () => { }, { name: bxIndex, - text: SourceText.New("", "", options ? options.bText : "export default class X { private x: number; }"), + text: SourceText.New( + "", + "", + options ? options.bText : "export default class X { private x: number; }", + ), }, { name: bxPackage, - text: SourceText.New("", "", JSON.stringify({ name: "x", version: options ? options.bVersion : "1.2.3" })), + text: SourceText.New( + "", + "", + JSON.stringify({ name: "x", version: options ? options.bVersion : "1.2.3" }), + ), }, { name: root, @@ -468,12 +529,26 @@ describe("unittests:: Reuse program structure:: General", () => { return newProgram(files, [root], compilerOptions, useGetSourceFileByPath); } - function updateRedirectProgram(program: ProgramWithSourceTexts, updater: (files: NamedSourceText[]) => void, useGetSourceFileByPath: boolean): ProgramWithSourceTexts { - return updateProgram(program, [root], compilerOptions, updater, /*newTexts*/ undefined, useGetSourceFileByPath); + function updateRedirectProgram( + program: ProgramWithSourceTexts, + updater: (files: NamedSourceText[]) => void, + useGetSourceFileByPath: boolean, + ): ProgramWithSourceTexts { + return updateProgram( + program, + [root], + compilerOptions, + updater, + /*newTexts*/ undefined, + useGetSourceFileByPath, + ); } function runRedirectsBaseline(scenario: string, useGetSourceFileByPath: boolean, baselines: readonly string[]) { - return runBaseline(`redirect${useGetSourceFileByPath ? " with getSourceFileByPath" : ""} ${scenario}`, baselines); + return runBaseline( + `redirect${useGetSourceFileByPath ? " with getSourceFileByPath" : ""} ${scenario}`, + baselines, + ); } function verifyRedirects(useGetSourceFileByPath: boolean) { @@ -495,7 +570,11 @@ describe("unittests:: Reuse program structure:: General", () => { baselineProgram(baselines, program1); const program2 = updateRedirectProgram(program1, files => { - updateProgramText(files, axIndex, "export default class X { private x: number; private y: number; }"); + updateProgramText( + files, + axIndex, + "export default class X { private x: number; private y: number; }", + ); updateProgramText(files, axPackage, JSON.stringify('{ name: "x", version: "1.2.4" }')); }, useGetSourceFileByPath); baselineProgram(baselines, program2); @@ -508,7 +587,11 @@ describe("unittests:: Reuse program structure:: General", () => { baselineProgram(baselines, program1); const program2 = updateRedirectProgram(program1, files => { - updateProgramText(files, bxIndex, "export default class X { private x: number; private y: number; }"); + updateProgramText( + files, + bxIndex, + "export default class X { private x: number; private y: number; }", + ); updateProgramText(files, bxPackage, JSON.stringify({ name: "x", version: "1.2.4" })); }, useGetSourceFileByPath); baselineProgram(baselines, program2); @@ -516,7 +599,10 @@ describe("unittests:: Reuse program structure:: General", () => { }); it("Previously duplicate packages -> program structure not reused", () => { - const program1 = createRedirectProgram(useGetSourceFileByPath, { bVersion: "1.2.4", bText: "export = class X { private x: number; }" }); + const program1 = createRedirectProgram(useGetSourceFileByPath, { + bVersion: "1.2.4", + bText: "export = class X { private x: number; }", + }); const baselines: string[] = []; baselineProgram(baselines, program1); @@ -595,7 +681,14 @@ describe("unittests:: Reuse program structure:: isProgramUptoDate", () => { configFileName, system, })).getCurrentProgram().getProgram(); - const { fileNames, options } = ts.parseConfigFileWithSystem(configFileName, {}, /*extendedConfigCache*/ undefined, /*watchOptionsToExtend*/ undefined, system, ts.notImplemented)!; // TODO: GH#18217 + const { fileNames, options } = ts.parseConfigFileWithSystem( + configFileName, + {}, + /*extendedConfigCache*/ undefined, + /*watchOptionsToExtend*/ undefined, + system, + ts.notImplemented, + )!; // TODO: GH#18217 verifyProgramIsUptoDate(program, fileNames, options); } @@ -678,7 +771,12 @@ describe("unittests:: Reuse program structure:: isProgramUptoDate", () => { content: JSON.stringify({ compilerOptions }), }; - verifyProgram([app, module1, module2, module3, libFile, configFile], [app.path], compilerOptions, configFile.path); + verifyProgram( + [app, module1, module2, module3, libFile, configFile], + [app.path], + compilerOptions, + configFile.path, + ); }); it("has include paths specified in tsconfig file", () => { @@ -715,7 +813,10 @@ describe("unittests:: Reuse program structure:: isProgramUptoDate", () => { path: "/src/tsconfig.json", content: JSON.stringify({ compilerOptions, include: ["packages/**/*.ts"] }), }; - verifyProgramWithConfigFile(createWatchedSystem([app, module1, module2, module3, libFile, configFile]), configFile.path); + verifyProgramWithConfigFile( + createWatchedSystem([app, module1, module2, module3, libFile, configFile]), + configFile.path, + ); }); it("has the same root file names", () => { const module1: File = { diff --git a/src/testRunner/unittests/semver.ts b/src/testRunner/unittests/semver.ts index 241a2f7209e0b..a61173669797b 100644 --- a/src/testRunner/unittests/semver.ts +++ b/src/testRunner/unittests/semver.ts @@ -4,7 +4,10 @@ import * as Utils from "../_namespaces/Utils"; import theory = Utils.theory; describe("unittests:: semver", () => { describe("Version", () => { - function assertVersion(version: ts.Version, [major, minor, patch, prerelease, build]: [number, number, number, string[]?, string[]?]) { + function assertVersion( + version: ts.Version, + [major, minor, patch, prerelease, build]: [number, number, number, string[]?, string[]?], + ) { assert.strictEqual(version.major, major); assert.strictEqual(version.minor, minor); assert.strictEqual(version.patch, patch); @@ -17,7 +20,10 @@ describe("unittests:: semver", () => { }); it("parts", () => { assertVersion(new ts.Version(1, 2, 3, "pre.4", "build.5"), [1, 2, 3, ["pre", "4"], ["build", "5"]]); - assertVersion(new ts.Version(1, 2, 3, ["pre", "4"], ["build", "5"]), [1, 2, 3, ["pre", "4"], ["build", "5"]]); + assertVersion(new ts.Version(1, 2, 3, ["pre", "4"], ["build", "5"]), [1, 2, 3, ["pre", "4"], [ + "build", + "5", + ]]); assertVersion(new ts.Version(1, 2, 3), [1, 2, 3]); assertVersion(new ts.Version(1, 2), [1, 2, 0]); assertVersion(new ts.Version(1), [1, 0, 0]); @@ -26,7 +32,10 @@ describe("unittests:: semver", () => { it("toString", () => { assert.strictEqual(new ts.Version(1, 2, 3, "pre.4", "build.5").toString(), "1.2.3-pre.4+build.5"); assert.strictEqual(new ts.Version(1, 2, 3, "pre.4").toString(), "1.2.3-pre.4"); - assert.strictEqual(new ts.Version(1, 2, 3, /*prerelease*/ undefined, "build.5").toString(), "1.2.3+build.5"); + assert.strictEqual( + new ts.Version(1, 2, 3, /*prerelease*/ undefined, "build.5").toString(), + "1.2.3+build.5", + ); assert.strictEqual(new ts.Version(1, 2, 3).toString(), "1.2.3"); assert.strictEqual(new ts.Version(1, 2).toString(), "1.2.0"); assert.strictEqual(new ts.Version(1).toString(), "1.0.0"); @@ -47,47 +56,92 @@ describe("unittests:: semver", () => { // https://semver.org/#spec-item-11 // > When major, minor, and patch are equal, a pre-release version has lower // > precedence than a normal version. - assert.strictEqual(new ts.Version("1.0.0").compareTo(new ts.Version("1.0.0-pre")), ts.Comparison.GreaterThan); - assert.strictEqual(new ts.Version("1.0.1-pre").compareTo(new ts.Version("1.0.0")), ts.Comparison.GreaterThan); + assert.strictEqual( + new ts.Version("1.0.0").compareTo(new ts.Version("1.0.0-pre")), + ts.Comparison.GreaterThan, + ); + assert.strictEqual( + new ts.Version("1.0.1-pre").compareTo(new ts.Version("1.0.0")), + ts.Comparison.GreaterThan, + ); assert.strictEqual(new ts.Version("1.0.0-pre").compareTo(new ts.Version("1.0.0")), ts.Comparison.LessThan); // https://semver.org/#spec-item-11 // > identifiers consisting of only digits are compared numerically assert.strictEqual(new ts.Version("1.0.0-0").compareTo(new ts.Version("1.0.0-1")), ts.Comparison.LessThan); - assert.strictEqual(new ts.Version("1.0.0-1").compareTo(new ts.Version("1.0.0-0")), ts.Comparison.GreaterThan); + assert.strictEqual( + new ts.Version("1.0.0-1").compareTo(new ts.Version("1.0.0-0")), + ts.Comparison.GreaterThan, + ); assert.strictEqual(new ts.Version("1.0.0-2").compareTo(new ts.Version("1.0.0-10")), ts.Comparison.LessThan); - assert.strictEqual(new ts.Version("1.0.0-10").compareTo(new ts.Version("1.0.0-2")), ts.Comparison.GreaterThan); + assert.strictEqual( + new ts.Version("1.0.0-10").compareTo(new ts.Version("1.0.0-2")), + ts.Comparison.GreaterThan, + ); assert.strictEqual(new ts.Version("1.0.0-0").compareTo(new ts.Version("1.0.0-0")), ts.Comparison.EqualTo); // https://semver.org/#spec-item-11 // > identifiers with letters or hyphens are compared lexically in ASCII sort order. assert.strictEqual(new ts.Version("1.0.0-a").compareTo(new ts.Version("1.0.0-b")), ts.Comparison.LessThan); - assert.strictEqual(new ts.Version("1.0.0-a-2").compareTo(new ts.Version("1.0.0-a-10")), ts.Comparison.GreaterThan); - assert.strictEqual(new ts.Version("1.0.0-b").compareTo(new ts.Version("1.0.0-a")), ts.Comparison.GreaterThan); + assert.strictEqual( + new ts.Version("1.0.0-a-2").compareTo(new ts.Version("1.0.0-a-10")), + ts.Comparison.GreaterThan, + ); + assert.strictEqual( + new ts.Version("1.0.0-b").compareTo(new ts.Version("1.0.0-a")), + ts.Comparison.GreaterThan, + ); assert.strictEqual(new ts.Version("1.0.0-a").compareTo(new ts.Version("1.0.0-a")), ts.Comparison.EqualTo); assert.strictEqual(new ts.Version("1.0.0-A").compareTo(new ts.Version("1.0.0-a")), ts.Comparison.LessThan); // https://semver.org/#spec-item-11 // > Numeric identifiers always have lower precedence than non-numeric identifiers. - assert.strictEqual(new ts.Version("1.0.0-0").compareTo(new ts.Version("1.0.0-alpha")), ts.Comparison.LessThan); - assert.strictEqual(new ts.Version("1.0.0-alpha").compareTo(new ts.Version("1.0.0-0")), ts.Comparison.GreaterThan); + assert.strictEqual( + new ts.Version("1.0.0-0").compareTo(new ts.Version("1.0.0-alpha")), + ts.Comparison.LessThan, + ); + assert.strictEqual( + new ts.Version("1.0.0-alpha").compareTo(new ts.Version("1.0.0-0")), + ts.Comparison.GreaterThan, + ); assert.strictEqual(new ts.Version("1.0.0-0").compareTo(new ts.Version("1.0.0-0")), ts.Comparison.EqualTo); - assert.strictEqual(new ts.Version("1.0.0-alpha").compareTo(new ts.Version("1.0.0-alpha")), ts.Comparison.EqualTo); + assert.strictEqual( + new ts.Version("1.0.0-alpha").compareTo(new ts.Version("1.0.0-alpha")), + ts.Comparison.EqualTo, + ); // https://semver.org/#spec-item-11 // > A larger set of pre-release fields has a higher precedence than a smaller set, if all // > of the preceding identifiers are equal. - assert.strictEqual(new ts.Version("1.0.0-alpha").compareTo(new ts.Version("1.0.0-alpha.0")), ts.Comparison.LessThan); - assert.strictEqual(new ts.Version("1.0.0-alpha.0").compareTo(new ts.Version("1.0.0-alpha")), ts.Comparison.GreaterThan); + assert.strictEqual( + new ts.Version("1.0.0-alpha").compareTo(new ts.Version("1.0.0-alpha.0")), + ts.Comparison.LessThan, + ); + assert.strictEqual( + new ts.Version("1.0.0-alpha.0").compareTo(new ts.Version("1.0.0-alpha")), + ts.Comparison.GreaterThan, + ); // https://semver.org/#spec-item-11 // > Precedence for two pre-release versions with the same major, minor, and patch version // > MUST be determined by comparing each dot separated identifier from left to right until // > a difference is found [...] - assert.strictEqual(new ts.Version("1.0.0-a.0.b.1").compareTo(new ts.Version("1.0.0-a.0.b.2")), ts.Comparison.LessThan); - assert.strictEqual(new ts.Version("1.0.0-a.0.b.1").compareTo(new ts.Version("1.0.0-b.0.a.1")), ts.Comparison.LessThan); - assert.strictEqual(new ts.Version("1.0.0-a.0.b.2").compareTo(new ts.Version("1.0.0-a.0.b.1")), ts.Comparison.GreaterThan); - assert.strictEqual(new ts.Version("1.0.0-b.0.a.1").compareTo(new ts.Version("1.0.0-a.0.b.1")), ts.Comparison.GreaterThan); + assert.strictEqual( + new ts.Version("1.0.0-a.0.b.1").compareTo(new ts.Version("1.0.0-a.0.b.2")), + ts.Comparison.LessThan, + ); + assert.strictEqual( + new ts.Version("1.0.0-a.0.b.1").compareTo(new ts.Version("1.0.0-b.0.a.1")), + ts.Comparison.LessThan, + ); + assert.strictEqual( + new ts.Version("1.0.0-a.0.b.2").compareTo(new ts.Version("1.0.0-a.0.b.1")), + ts.Comparison.GreaterThan, + ); + assert.strictEqual( + new ts.Version("1.0.0-b.0.a.1").compareTo(new ts.Version("1.0.0-a.0.b.1")), + ts.Comparison.GreaterThan, + ); // https://semver.org/#spec-item-11 // > Build metadata does not figure into precedence @@ -181,7 +235,11 @@ describe("unittests:: semver", () => { function assertRange(rangeText: string, versionText: string, inRange: boolean) { const range = new ts.VersionRange(rangeText); const version = new ts.Version(versionText); - assert.strictEqual(range.test(version), inRange, `Expected version '${version}' ${inRange ? `to be` : `to not be`} in range '${rangeText}' (${range})`); + assert.strictEqual( + range.test(version), + inRange, + `Expected version '${version}' ${inRange ? `to be` : `to not be`} in range '${rangeText}' (${range})`, + ); } theory("comparators", assertRange, [ diff --git a/src/testRunner/unittests/services/cancellableLanguageServiceOperations.ts b/src/testRunner/unittests/services/cancellableLanguageServiceOperations.ts index ca397ab02d125..0de18f24a70d3 100644 --- a/src/testRunner/unittests/services/cancellableLanguageServiceOperations.ts +++ b/src/testRunner/unittests/services/cancellableLanguageServiceOperations.ts @@ -9,9 +9,14 @@ describe("unittests:: services:: cancellableLanguageServiceOperations", () => { foo(f); `; it("can cancel signature help mid-request", () => { - verifyOperationCancelledAfter(file, 4, service => - // Two calls are top-level in services, one is the root type, and the second should be for the parameter type - service.getSignatureHelpItems("file.ts", file.lastIndexOf("f"), ts.emptyOptions)!, r => assert.exists(r.items[0])); + verifyOperationCancelledAfter( + file, + 4, + service => + // Two calls are top-level in services, one is the root type, and the second should be for the parameter type + service.getSignatureHelpItems("file.ts", file.lastIndexOf("f"), ts.emptyOptions)!, + r => assert.exists(r.items[0]), + ); }); it("can cancel find all references mid-request", () => { @@ -50,7 +55,15 @@ describe("unittests:: services:: cancellableLanguageServiceOperations", () => { }; verifyOperationCancelledAfter(file, 1, service => // The LS doesn't do any top-level checks on the token for completion entry details, so the first check is within the checker - service.getCompletionEntryDetails("file.ts", file.lastIndexOf("f"), "foo", options, /*source*/ undefined, {}, /*data*/ undefined)!, r => assert.exists(r.displayParts)); + service.getCompletionEntryDetails( + "file.ts", + file.lastIndexOf("f"), + "foo", + options, + /*source*/ undefined, + {}, + /*data*/ undefined, + )!, r => assert.exists(r.displayParts)); }); it("can cancel suggestion diagnostics mid-request", () => { @@ -68,7 +81,15 @@ describe("unittests:: services:: cancellableLanguageServiceOperations", () => { }); }); -function verifyOperationCancelledAfter(content: string, cancelAfter: number, operation: (service: ts.LanguageService) => T, validator: (arg: T) => void, fileName?: string, fileContent?: string, options?: ts.CompilerOptions) { +function verifyOperationCancelledAfter( + content: string, + cancelAfter: number, + operation: (service: ts.LanguageService) => T, + validator: (arg: T) => void, + fileName?: string, + fileContent?: string, + options?: ts.CompilerOptions, +) { let checks = 0; const token: ts.HostCancellationToken = { isCancellationRequested() { diff --git a/src/testRunner/unittests/services/colorization.ts b/src/testRunner/unittests/services/colorization.ts index 27232e8fd0b95..f1aea82db5ef1 100644 --- a/src/testRunner/unittests/services/colorization.ts +++ b/src/testRunner/unittests/services/colorization.ts @@ -12,7 +12,9 @@ interface ClassificationEntry { describe("unittests:: services:: Colorization", () => { // Use the shim adapter to ensure test coverage of the shim layer for the classifier - const languageServiceAdapter = new Harness.LanguageService.ShimLanguageServiceAdapter(/*preprocessToResolve*/ false); + const languageServiceAdapter = new Harness.LanguageService.ShimLanguageServiceAdapter( + /*preprocessToResolve*/ false, + ); const classifier = languageServiceAdapter.getClassifier(); function getEntryAtPosition(result: ts.ClassificationResult, position: number) { @@ -54,105 +56,253 @@ describe("unittests:: services:: Colorization", () => { // TODO: GH#18217 return { value, classification: undefined!, position: 0 }; } - function createClassification(value: string, classification: ts.TokenClass, position?: number): ClassificationEntry { + function createClassification( + value: string, + classification: ts.TokenClass, + position?: number, + ): ClassificationEntry { return { value, classification, position }; } - function testLexicalClassification(text: string, initialEndOfLineState: ts.EndOfLineState, ...expectedEntries: ClassificationEntry[]): void { - const result = classifier.getClassificationsForLine(text, initialEndOfLineState, /*syntacticClassifierAbsent*/ false); + function testLexicalClassification( + text: string, + initialEndOfLineState: ts.EndOfLineState, + ...expectedEntries: ClassificationEntry[] + ): void { + const result = classifier.getClassificationsForLine( + text, + initialEndOfLineState, + /*syntacticClassifierAbsent*/ false, + ); for (const expectedEntry of expectedEntries) { if (expectedEntry.classification === undefined) { - assert.equal(result.finalLexState, expectedEntry.value, "final endOfLineState does not match expected."); + assert.equal( + result.finalLexState, + expectedEntry.value, + "final endOfLineState does not match expected.", + ); } else { - const actualEntryPosition = expectedEntry.position !== undefined ? expectedEntry.position : text.indexOf(expectedEntry.value); - assert(actualEntryPosition >= 0, "token: '" + expectedEntry.value + "' does not exit in text: '" + text + "'."); + const actualEntryPosition = expectedEntry.position !== undefined ? expectedEntry.position + : text.indexOf(expectedEntry.value); + assert( + actualEntryPosition >= 0, + "token: '" + expectedEntry.value + "' does not exit in text: '" + text + "'.", + ); const actualEntry = getEntryAtPosition(result, actualEntryPosition)!; - assert(actualEntry, "Could not find classification entry for '" + expectedEntry.value + "' at position: " + actualEntryPosition); - assert.equal(actualEntry.classification, expectedEntry.classification, "Classification class does not match expected. Expected: " + ts.TokenClass[expectedEntry.classification] + ", Actual: " + ts.TokenClass[actualEntry.classification]); - assert.equal(actualEntry.length, expectedEntry.value.length, "Classification length does not match expected. Expected: " + ts.TokenClass[expectedEntry.value.length] + ", Actual: " + ts.TokenClass[actualEntry.length]); + assert( + actualEntry, + "Could not find classification entry for '" + expectedEntry.value + "' at position: " + + actualEntryPosition, + ); + assert.equal( + actualEntry.classification, + expectedEntry.classification, + "Classification class does not match expected. Expected: " + + ts.TokenClass[expectedEntry.classification] + ", Actual: " + + ts.TokenClass[actualEntry.classification], + ); + assert.equal( + actualEntry.length, + expectedEntry.value.length, + "Classification length does not match expected. Expected: " + + ts.TokenClass[expectedEntry.value.length] + ", Actual: " + ts.TokenClass[actualEntry.length], + ); } } } describe("test getClassifications", () => { it("returns correct token classes", () => { - testLexicalClassification('var x: string = "foo" ?? "bar"; //Hello', ts.EndOfLineState.None, keyword("var"), whitespace(" "), identifier("x"), punctuation(":"), keyword("string"), operator("="), stringLiteral('"foo"'), whitespace(" "), operator("??"), stringLiteral('"foo"'), comment("//Hello"), punctuation(";")); + testLexicalClassification( + 'var x: string = "foo" ?? "bar"; //Hello', + ts.EndOfLineState.None, + keyword("var"), + whitespace(" "), + identifier("x"), + punctuation(":"), + keyword("string"), + operator("="), + stringLiteral('"foo"'), + whitespace(" "), + operator("??"), + stringLiteral('"foo"'), + comment("//Hello"), + punctuation(";"), + ); }); it("correctly classifies a comment after a divide operator", () => { - testLexicalClassification("1 / 2 // comment", ts.EndOfLineState.None, numberLiteral("1"), whitespace(" "), operator("/"), numberLiteral("2"), comment("// comment")); + testLexicalClassification( + "1 / 2 // comment", + ts.EndOfLineState.None, + numberLiteral("1"), + whitespace(" "), + operator("/"), + numberLiteral("2"), + comment("// comment"), + ); }); it("correctly classifies a literal after a divide operator", () => { - testLexicalClassification("1 / 2, 3 / 4", ts.EndOfLineState.None, numberLiteral("1"), whitespace(" "), operator("/"), numberLiteral("2"), numberLiteral("3"), numberLiteral("4"), operator(",")); + testLexicalClassification( + "1 / 2, 3 / 4", + ts.EndOfLineState.None, + numberLiteral("1"), + whitespace(" "), + operator("/"), + numberLiteral("2"), + numberLiteral("3"), + numberLiteral("4"), + operator(","), + ); }); it("correctly classifies a multiline string with one backslash", () => { - testLexicalClassification("'line1\\", ts.EndOfLineState.None, stringLiteral("'line1\\"), finalEndOfLineState(ts.EndOfLineState.InSingleQuoteStringLiteral)); + testLexicalClassification( + "'line1\\", + ts.EndOfLineState.None, + stringLiteral("'line1\\"), + finalEndOfLineState(ts.EndOfLineState.InSingleQuoteStringLiteral), + ); }); it("correctly classifies a multiline string with three backslashes", () => { - testLexicalClassification("'line1\\\\\\", ts.EndOfLineState.None, stringLiteral("'line1\\\\\\"), finalEndOfLineState(ts.EndOfLineState.InSingleQuoteStringLiteral)); + testLexicalClassification( + "'line1\\\\\\", + ts.EndOfLineState.None, + stringLiteral("'line1\\\\\\"), + finalEndOfLineState(ts.EndOfLineState.InSingleQuoteStringLiteral), + ); }); it("correctly classifies an unterminated single-line string with no backslashes", () => { - testLexicalClassification("'line1", ts.EndOfLineState.None, stringLiteral("'line1"), finalEndOfLineState(ts.EndOfLineState.None)); + testLexicalClassification( + "'line1", + ts.EndOfLineState.None, + stringLiteral("'line1"), + finalEndOfLineState(ts.EndOfLineState.None), + ); }); it("correctly classifies an unterminated single-line string with two backslashes", () => { - testLexicalClassification("'line1\\\\", ts.EndOfLineState.None, stringLiteral("'line1\\\\"), finalEndOfLineState(ts.EndOfLineState.None)); + testLexicalClassification( + "'line1\\\\", + ts.EndOfLineState.None, + stringLiteral("'line1\\\\"), + finalEndOfLineState(ts.EndOfLineState.None), + ); }); it("correctly classifies an unterminated single-line string with four backslashes", () => { - testLexicalClassification("'line1\\\\\\\\", ts.EndOfLineState.None, stringLiteral("'line1\\\\\\\\"), finalEndOfLineState(ts.EndOfLineState.None)); + testLexicalClassification( + "'line1\\\\\\\\", + ts.EndOfLineState.None, + stringLiteral("'line1\\\\\\\\"), + finalEndOfLineState(ts.EndOfLineState.None), + ); }); it("correctly classifies the continuing line of a multiline string ending in one backslash", () => { - testLexicalClassification("\\", ts.EndOfLineState.InDoubleQuoteStringLiteral, stringLiteral("\\"), finalEndOfLineState(ts.EndOfLineState.InDoubleQuoteStringLiteral)); + testLexicalClassification( + "\\", + ts.EndOfLineState.InDoubleQuoteStringLiteral, + stringLiteral("\\"), + finalEndOfLineState(ts.EndOfLineState.InDoubleQuoteStringLiteral), + ); }); it("correctly classifies the continuing line of a multiline string ending in three backslashes", () => { - testLexicalClassification("\\", ts.EndOfLineState.InDoubleQuoteStringLiteral, stringLiteral("\\"), finalEndOfLineState(ts.EndOfLineState.InDoubleQuoteStringLiteral)); + testLexicalClassification( + "\\", + ts.EndOfLineState.InDoubleQuoteStringLiteral, + stringLiteral("\\"), + finalEndOfLineState(ts.EndOfLineState.InDoubleQuoteStringLiteral), + ); }); it("correctly classifies the last line of an unterminated multiline string ending in no backslashes", () => { - testLexicalClassification(" ", ts.EndOfLineState.InDoubleQuoteStringLiteral, stringLiteral(" "), finalEndOfLineState(ts.EndOfLineState.None)); + testLexicalClassification( + " ", + ts.EndOfLineState.InDoubleQuoteStringLiteral, + stringLiteral(" "), + finalEndOfLineState(ts.EndOfLineState.None), + ); }); it("correctly classifies the last line of an unterminated multiline string ending in two backslashes", () => { - testLexicalClassification("\\\\", ts.EndOfLineState.InDoubleQuoteStringLiteral, stringLiteral("\\\\"), finalEndOfLineState(ts.EndOfLineState.None)); + testLexicalClassification( + "\\\\", + ts.EndOfLineState.InDoubleQuoteStringLiteral, + stringLiteral("\\\\"), + finalEndOfLineState(ts.EndOfLineState.None), + ); }); it("correctly classifies the last line of an unterminated multiline string ending in four backslashes", () => { - testLexicalClassification("\\\\\\\\", ts.EndOfLineState.InDoubleQuoteStringLiteral, stringLiteral("\\\\\\\\"), finalEndOfLineState(ts.EndOfLineState.None)); + testLexicalClassification( + "\\\\\\\\", + ts.EndOfLineState.InDoubleQuoteStringLiteral, + stringLiteral("\\\\\\\\"), + finalEndOfLineState(ts.EndOfLineState.None), + ); }); it("correctly classifies the last line of a multiline string", () => { - testLexicalClassification("'", ts.EndOfLineState.InSingleQuoteStringLiteral, stringLiteral("'"), finalEndOfLineState(ts.EndOfLineState.None)); + testLexicalClassification( + "'", + ts.EndOfLineState.InSingleQuoteStringLiteral, + stringLiteral("'"), + finalEndOfLineState(ts.EndOfLineState.None), + ); }); it("correctly classifies an unterminated multiline comment", () => { - testLexicalClassification("/*", ts.EndOfLineState.None, comment("/*"), finalEndOfLineState(ts.EndOfLineState.InMultiLineCommentTrivia)); + testLexicalClassification( + "/*", + ts.EndOfLineState.None, + comment("/*"), + finalEndOfLineState(ts.EndOfLineState.InMultiLineCommentTrivia), + ); }); it("correctly classifies the termination of a multiline comment", () => { - testLexicalClassification(" */ ", ts.EndOfLineState.InMultiLineCommentTrivia, comment(" */"), finalEndOfLineState(ts.EndOfLineState.None)); + testLexicalClassification( + " */ ", + ts.EndOfLineState.InMultiLineCommentTrivia, + comment(" */"), + finalEndOfLineState(ts.EndOfLineState.None), + ); }); it("correctly classifies the continuation of a multiline comment", () => { - testLexicalClassification("LOREM IPSUM DOLOR ", ts.EndOfLineState.InMultiLineCommentTrivia, comment("LOREM IPSUM DOLOR "), finalEndOfLineState(ts.EndOfLineState.InMultiLineCommentTrivia)); + testLexicalClassification( + "LOREM IPSUM DOLOR ", + ts.EndOfLineState.InMultiLineCommentTrivia, + comment("LOREM IPSUM DOLOR "), + finalEndOfLineState(ts.EndOfLineState.InMultiLineCommentTrivia), + ); }); it("correctly classifies an unterminated multiline comment on a line ending in '/*/'", () => { - testLexicalClassification(" /*/", ts.EndOfLineState.None, comment("/*/"), finalEndOfLineState(ts.EndOfLineState.InMultiLineCommentTrivia)); + testLexicalClassification( + " /*/", + ts.EndOfLineState.None, + comment("/*/"), + finalEndOfLineState(ts.EndOfLineState.InMultiLineCommentTrivia), + ); }); it("correctly classifies an unterminated multiline comment with trailing space", () => { - testLexicalClassification("/* ", ts.EndOfLineState.None, comment("/* "), finalEndOfLineState(ts.EndOfLineState.InMultiLineCommentTrivia)); + testLexicalClassification( + "/* ", + ts.EndOfLineState.None, + comment("/* "), + finalEndOfLineState(ts.EndOfLineState.InMultiLineCommentTrivia), + ); }); it("correctly classifies a keyword after a dot", () => { @@ -164,7 +314,14 @@ describe("unittests:: services:: Colorization", () => { }); it("correctly classifies a keyword after a dot separated by comment trivia", () => { - testLexicalClassification("a./*hello world*/ var", ts.EndOfLineState.None, identifier("a"), punctuation("."), comment("/*hello world*/"), identifier("var")); + testLexicalClassification( + "a./*hello world*/ var", + ts.EndOfLineState.None, + identifier("a"), + punctuation("."), + comment("/*hello world*/"), + identifier("var"), + ); }); it("classifies a property access with whitespace around the dot", () => { @@ -172,47 +329,140 @@ describe("unittests:: services:: Colorization", () => { }); it("classifies a keyword after a dot on previous line", () => { - testLexicalClassification("var", ts.EndOfLineState.None, keyword("var"), finalEndOfLineState(ts.EndOfLineState.None)); + testLexicalClassification( + "var", + ts.EndOfLineState.None, + keyword("var"), + finalEndOfLineState(ts.EndOfLineState.None), + ); }); it("classifies multiple keywords properly", () => { - testLexicalClassification("public static", ts.EndOfLineState.None, keyword("public"), keyword("static"), finalEndOfLineState(ts.EndOfLineState.None)); + testLexicalClassification( + "public static", + ts.EndOfLineState.None, + keyword("public"), + keyword("static"), + finalEndOfLineState(ts.EndOfLineState.None), + ); - testLexicalClassification("public var", ts.EndOfLineState.None, keyword("public"), identifier("var"), finalEndOfLineState(ts.EndOfLineState.None)); + testLexicalClassification( + "public var", + ts.EndOfLineState.None, + keyword("public"), + identifier("var"), + finalEndOfLineState(ts.EndOfLineState.None), + ); }); it("classifies a single line no substitution template string correctly", () => { - testLexicalClassification("`number number public string`", ts.EndOfLineState.None, stringLiteral("`number number public string`"), finalEndOfLineState(ts.EndOfLineState.None)); + testLexicalClassification( + "`number number public string`", + ts.EndOfLineState.None, + stringLiteral("`number number public string`"), + finalEndOfLineState(ts.EndOfLineState.None), + ); }); it("classifies substitution parts of a template string correctly", () => { - testLexicalClassification("`number '${ 1 + 1 }' string '${ 'hello' }'`", ts.EndOfLineState.None, stringLiteral("`number '${"), numberLiteral("1"), operator("+"), numberLiteral("1"), stringLiteral("}' string '${"), stringLiteral("'hello'"), stringLiteral("}'`"), finalEndOfLineState(ts.EndOfLineState.None)); + testLexicalClassification( + "`number '${ 1 + 1 }' string '${ 'hello' }'`", + ts.EndOfLineState.None, + stringLiteral("`number '${"), + numberLiteral("1"), + operator("+"), + numberLiteral("1"), + stringLiteral("}' string '${"), + stringLiteral("'hello'"), + stringLiteral("}'`"), + finalEndOfLineState(ts.EndOfLineState.None), + ); }); it("classifies an unterminated no substitution template string correctly", () => { - testLexicalClassification("`hello world", ts.EndOfLineState.None, stringLiteral("`hello world"), finalEndOfLineState(ts.EndOfLineState.InTemplateHeadOrNoSubstitutionTemplate)); + testLexicalClassification( + "`hello world", + ts.EndOfLineState.None, + stringLiteral("`hello world"), + finalEndOfLineState(ts.EndOfLineState.InTemplateHeadOrNoSubstitutionTemplate), + ); }); it("classifies the entire line of an unterminated multiline no-substitution/head template", () => { - testLexicalClassification("...", ts.EndOfLineState.InTemplateHeadOrNoSubstitutionTemplate, stringLiteral("..."), finalEndOfLineState(ts.EndOfLineState.InTemplateHeadOrNoSubstitutionTemplate)); + testLexicalClassification( + "...", + ts.EndOfLineState.InTemplateHeadOrNoSubstitutionTemplate, + stringLiteral("..."), + finalEndOfLineState(ts.EndOfLineState.InTemplateHeadOrNoSubstitutionTemplate), + ); }); it("classifies the entire line of an unterminated multiline template middle/end", () => { - testLexicalClassification("...", ts.EndOfLineState.InTemplateMiddleOrTail, stringLiteral("..."), finalEndOfLineState(ts.EndOfLineState.InTemplateMiddleOrTail)); + testLexicalClassification( + "...", + ts.EndOfLineState.InTemplateMiddleOrTail, + stringLiteral("..."), + finalEndOfLineState(ts.EndOfLineState.InTemplateMiddleOrTail), + ); }); it("classifies a termination of a multiline template head", () => { - testLexicalClassification("...${", ts.EndOfLineState.InTemplateHeadOrNoSubstitutionTemplate, stringLiteral("...${"), finalEndOfLineState(ts.EndOfLineState.InTemplateSubstitutionPosition)); + testLexicalClassification( + "...${", + ts.EndOfLineState.InTemplateHeadOrNoSubstitutionTemplate, + stringLiteral("...${"), + finalEndOfLineState(ts.EndOfLineState.InTemplateSubstitutionPosition), + ); }); it("classifies the termination of a multiline no substitution template", () => { - testLexicalClassification("...`", ts.EndOfLineState.InTemplateHeadOrNoSubstitutionTemplate, stringLiteral("...`"), finalEndOfLineState(ts.EndOfLineState.None)); + testLexicalClassification( + "...`", + ts.EndOfLineState.InTemplateHeadOrNoSubstitutionTemplate, + stringLiteral("...`"), + finalEndOfLineState(ts.EndOfLineState.None), + ); }); it("classifies the substitution parts and middle/tail of a multiline template string", () => { - testLexicalClassification("${ 1 + 1 }...`", ts.EndOfLineState.InTemplateHeadOrNoSubstitutionTemplate, stringLiteral("${"), numberLiteral("1"), operator("+"), numberLiteral("1"), stringLiteral("}...`"), finalEndOfLineState(ts.EndOfLineState.None)); + testLexicalClassification( + "${ 1 + 1 }...`", + ts.EndOfLineState.InTemplateHeadOrNoSubstitutionTemplate, + stringLiteral("${"), + numberLiteral("1"), + operator("+"), + numberLiteral("1"), + stringLiteral("}...`"), + finalEndOfLineState(ts.EndOfLineState.None), + ); }); it("classifies a template middle and propagates the end of line state", () => { - testLexicalClassification("${ 1 + 1 }...`", ts.EndOfLineState.InTemplateHeadOrNoSubstitutionTemplate, stringLiteral("${"), numberLiteral("1"), operator("+"), numberLiteral("1"), stringLiteral("}...`"), finalEndOfLineState(ts.EndOfLineState.None)); + testLexicalClassification( + "${ 1 + 1 }...`", + ts.EndOfLineState.InTemplateHeadOrNoSubstitutionTemplate, + stringLiteral("${"), + numberLiteral("1"), + operator("+"), + numberLiteral("1"), + stringLiteral("}...`"), + finalEndOfLineState(ts.EndOfLineState.None), + ); }); it("classifies substitution expressions with curly braces appropriately", () => { let pos = 0; let lastLength = 0; - testLexicalClassification("...${ () => { } } ${ { x: `1` } }...`", ts.EndOfLineState.InTemplateHeadOrNoSubstitutionTemplate, stringLiteral(track("...${"), pos), punctuation(track(" ", "("), pos), punctuation(track(")"), pos), punctuation(track(" ", "=>"), pos), punctuation(track(" ", "{"), pos), punctuation(track(" ", "}"), pos), stringLiteral(track(" ", "} ${"), pos), punctuation(track(" ", "{"), pos), identifier(track(" ", "x"), pos), punctuation(track(":"), pos), stringLiteral(track(" ", "`1`"), pos), punctuation(track(" ", "}"), pos), stringLiteral(track(" ", "}...`"), pos), finalEndOfLineState(ts.EndOfLineState.None)); + testLexicalClassification( + "...${ () => { } } ${ { x: `1` } }...`", + ts.EndOfLineState.InTemplateHeadOrNoSubstitutionTemplate, + stringLiteral(track("...${"), pos), + punctuation(track(" ", "("), pos), + punctuation(track(")"), pos), + punctuation(track(" ", "=>"), pos), + punctuation(track(" ", "{"), pos), + punctuation(track(" ", "}"), pos), + stringLiteral(track(" ", "} ${"), pos), + punctuation(track(" ", "{"), pos), + identifier(track(" ", "x"), pos), + punctuation(track(":"), pos), + stringLiteral(track(" ", "`1`"), pos), + punctuation(track(" ", "}"), pos), + stringLiteral(track(" ", "}...`"), pos), + finalEndOfLineState(ts.EndOfLineState.None), + ); // Adjusts 'pos' by accounting for the length of each portion of the string, // but only return the last given string @@ -226,13 +476,37 @@ describe("unittests:: services:: Colorization", () => { }); it("classifies partially written generics correctly.", () => { - testLexicalClassification("Foo { @@ -325,7 +599,20 @@ class D { }\r\n\ }); it("'of' keyword", () => { - testLexicalClassification("for (var of of of) { }", ts.EndOfLineState.None, keyword("for"), punctuation("("), keyword("var"), keyword("of"), keyword("of"), keyword("of"), punctuation(")"), punctuation("{"), punctuation("}"), finalEndOfLineState(ts.EndOfLineState.None)); + testLexicalClassification( + "for (var of of of) { }", + ts.EndOfLineState.None, + keyword("for"), + punctuation("("), + keyword("var"), + keyword("of"), + keyword("of"), + keyword("of"), + punctuation(")"), + punctuation("{"), + punctuation("}"), + finalEndOfLineState(ts.EndOfLineState.None), + ); }); }); }); diff --git a/src/testRunner/unittests/services/convertToAsyncFunction.ts b/src/testRunner/unittests/services/convertToAsyncFunction.ts index 657fd6a222727..d024df40daaa9 100644 --- a/src/testRunner/unittests/services/convertToAsyncFunction.ts +++ b/src/testRunner/unittests/services/convertToAsyncFunction.ts @@ -288,7 +288,9 @@ type WithSkipAndOnly = ((...args: T) => void) & { only: (...args: T) => void; }; -function createTestWrapper(fn: (it: Mocha.PendingTestFunction, ...args: T) => void): WithSkipAndOnly { +function createTestWrapper( + fn: (it: Mocha.PendingTestFunction, ...args: T) => void, +): WithSkipAndOnly { wrapped.skip = (...args: T) => fn(it.skip, ...args); wrapped.only = (...args: T) => fn(it.only, ...args); return wrapped; @@ -310,7 +312,13 @@ const enum ConvertToAsyncTestFlags { ExpectFailed = ExpectNoSuggestionDiagnostic | ExpectNoAction, } -function testConvertToAsyncFunction(it: Mocha.PendingTestFunction, caption: string, text: string, baselineFolder: string, flags: ConvertToAsyncTestFlags) { +function testConvertToAsyncFunction( + it: Mocha.PendingTestFunction, + caption: string, + text: string, + baselineFolder: string, + flags: ConvertToAsyncTestFlags, +) { const includeLib = !!(flags & ConvertToAsyncTestFlags.IncludeLib); const includeModule = !!(flags & ConvertToAsyncTestFlags.IncludeModule); const expectSuggestionDiagnostic = !!(flags & ConvertToAsyncTestFlags.ExpectSuggestionDiagnostic); @@ -318,7 +326,10 @@ function testConvertToAsyncFunction(it: Mocha.PendingTestFunction, caption: stri const expectAction = !!(flags & ConvertToAsyncTestFlags.ExpectAction); const expectNoAction = !!(flags & ConvertToAsyncTestFlags.ExpectNoAction); const expectFailure = expectNoSuggestionDiagnostic || expectNoAction; - ts.Debug.assert(!(expectSuggestionDiagnostic && expectNoSuggestionDiagnostic), "Cannot combine both 'ExpectSuggestionDiagnostic' and 'ExpectNoSuggestionDiagnostic'"); + ts.Debug.assert( + !(expectSuggestionDiagnostic && expectNoSuggestionDiagnostic), + "Cannot combine both 'ExpectSuggestionDiagnostic' and 'ExpectNoSuggestionDiagnostic'", + ); ts.Debug.assert(!(expectAction && expectNoAction), "Cannot combine both 'ExpectAction' and 'ExpectNoAction'"); const t = extractTest(text); @@ -360,11 +371,17 @@ function testConvertToAsyncFunction(it: Mocha.PendingTestFunction, caption: stri }; const diagnostics = languageService.getSuggestionDiagnostics(f.path); - const diagnostic = ts.find(diagnostics, diagnostic => - diagnostic.messageText === ts.Diagnostics.This_may_be_converted_to_an_async_function.message && - diagnostic.start === context.span.start && diagnostic.length === context.span.length); + const diagnostic = ts.find( + diagnostics, + diagnostic => + diagnostic.messageText === ts.Diagnostics.This_may_be_converted_to_an_async_function.message + && diagnostic.start === context.span.start && diagnostic.length === context.span.length, + ); const actions = ts.codefix.getFixes(context); - const action = ts.find(actions, action => action.description === ts.Diagnostics.Convert_to_async_function.message); + const action = ts.find( + actions, + action => action.description === ts.Diagnostics.Convert_to_async_function.message, + ); let outputText: string | null; if (action?.changes.length) { @@ -378,7 +395,8 @@ function testConvertToAsyncFunction(it: Mocha.PendingTestFunction, caption: stri const newText = ts.textChanges.applyChanges(sourceFile.text, changes[0].textChanges); data.push(newText); - const diagProgram = makeLanguageService({ path, content: newText }, includeLib, includeModule).getProgram()!; + const diagProgram = makeLanguageService({ path, content: newText }, includeLib, includeModule) + .getProgram()!; assert.isFalse(hasSyntacticDiagnostics(diagProgram)); outputText = data.join(newLineCharacter); } @@ -427,23 +445,56 @@ function testConvertToAsyncFunction(it: Mocha.PendingTestFunction, caption: stri } const _testConvertToAsyncFunction = createTestWrapper((it, caption: string, text: string) => { - testConvertToAsyncFunction(it, caption, text, "convertToAsyncFunction", ConvertToAsyncTestFlags.IncludeLib | ConvertToAsyncTestFlags.ExpectSuccess); + testConvertToAsyncFunction( + it, + caption, + text, + "convertToAsyncFunction", + ConvertToAsyncTestFlags.IncludeLib | ConvertToAsyncTestFlags.ExpectSuccess, + ); }); const _testConvertToAsyncFunctionFailed = createTestWrapper((it, caption: string, text: string) => { - testConvertToAsyncFunction(it, caption, text, "convertToAsyncFunction", ConvertToAsyncTestFlags.IncludeLib | ConvertToAsyncTestFlags.ExpectFailed); + testConvertToAsyncFunction( + it, + caption, + text, + "convertToAsyncFunction", + ConvertToAsyncTestFlags.IncludeLib | ConvertToAsyncTestFlags.ExpectFailed, + ); }); const _testConvertToAsyncFunctionFailedSuggestion = createTestWrapper((it, caption: string, text: string) => { - testConvertToAsyncFunction(it, caption, text, "convertToAsyncFunction", ConvertToAsyncTestFlags.IncludeLib | ConvertToAsyncTestFlags.ExpectNoSuggestionDiagnostic | ConvertToAsyncTestFlags.ExpectAction); + testConvertToAsyncFunction( + it, + caption, + text, + "convertToAsyncFunction", + ConvertToAsyncTestFlags.IncludeLib | ConvertToAsyncTestFlags.ExpectNoSuggestionDiagnostic + | ConvertToAsyncTestFlags.ExpectAction, + ); }); const _testConvertToAsyncFunctionFailedAction = createTestWrapper((it, caption: string, text: string) => { - testConvertToAsyncFunction(it, caption, text, "convertToAsyncFunction", ConvertToAsyncTestFlags.IncludeLib | ConvertToAsyncTestFlags.ExpectSuggestionDiagnostic | ConvertToAsyncTestFlags.ExpectNoAction); + testConvertToAsyncFunction( + it, + caption, + text, + "convertToAsyncFunction", + ConvertToAsyncTestFlags.IncludeLib | ConvertToAsyncTestFlags.ExpectSuggestionDiagnostic + | ConvertToAsyncTestFlags.ExpectNoAction, + ); }); const _testConvertToAsyncFunctionWithModule = createTestWrapper((it, caption: string, text: string) => { - testConvertToAsyncFunction(it, caption, text, "convertToAsyncFunction", ConvertToAsyncTestFlags.IncludeLib | ConvertToAsyncTestFlags.IncludeModule | ConvertToAsyncTestFlags.ExpectSuccess); + testConvertToAsyncFunction( + it, + caption, + text, + "convertToAsyncFunction", + ConvertToAsyncTestFlags.IncludeLib | ConvertToAsyncTestFlags.IncludeModule + | ConvertToAsyncTestFlags.ExpectSuccess, + ); }); describe("unittests:: services:: convertToAsyncFunction", () => { diff --git a/src/testRunner/unittests/services/documentRegistry.ts b/src/testRunner/unittests/services/documentRegistry.ts index 93d51c5b6d0e4..87078f86e5f93 100644 --- a/src/testRunner/unittests/services/documentRegistry.ts +++ b/src/testRunner/unittests/services/documentRegistry.ts @@ -5,8 +5,18 @@ describe("unittests:: services:: DocumentRegistry", () => { const documentRegistry = ts.createDocumentRegistry(); const defaultCompilerOptions = ts.getDefaultCompilerOptions(); - const f1 = documentRegistry.acquireDocument("file1.ts", defaultCompilerOptions, ts.ScriptSnapshot.fromString("var x = 1;"), /* version */ "1"); - const f2 = documentRegistry.acquireDocument("file1.ts", defaultCompilerOptions, ts.ScriptSnapshot.fromString("var x = 1;"), /* version */ "1"); + const f1 = documentRegistry.acquireDocument( + "file1.ts", + defaultCompilerOptions, + ts.ScriptSnapshot.fromString("var x = 1;"), + /* version */ "1", + ); + const f2 = documentRegistry.acquireDocument( + "file1.ts", + defaultCompilerOptions, + ts.ScriptSnapshot.fromString("var x = 1;"), + /* version */ "1", + ); assert(f1 === f2, "DocumentRegistry should return the same document for the same name"); }); @@ -17,25 +27,50 @@ describe("unittests:: services:: DocumentRegistry", () => { // change compilation setting that doesn't affect parsing - should have the same document compilerOptions.declaration = true; - const f1 = documentRegistry.acquireDocument("file1.ts", compilerOptions, ts.ScriptSnapshot.fromString("var x = 1;"), /* version */ "1"); + const f1 = documentRegistry.acquireDocument( + "file1.ts", + compilerOptions, + ts.ScriptSnapshot.fromString("var x = 1;"), + /* version */ "1", + ); compilerOptions.declaration = false; - const f2 = documentRegistry.acquireDocument("file1.ts", compilerOptions, ts.ScriptSnapshot.fromString("var x = 1;"), /* version */ "1"); + const f2 = documentRegistry.acquireDocument( + "file1.ts", + compilerOptions, + ts.ScriptSnapshot.fromString("var x = 1;"), + /* version */ "1", + ); assert(f1 === f2, "Expected to have the same document instance"); // change value of compilation setting that is used during production of AST - new document is required compilerOptions.target = ts.ScriptTarget.ES3; - const f3 = documentRegistry.acquireDocument("file1.ts", compilerOptions, ts.ScriptSnapshot.fromString("var x = 1;"), /* version */ "1"); + const f3 = documentRegistry.acquireDocument( + "file1.ts", + compilerOptions, + ts.ScriptSnapshot.fromString("var x = 1;"), + /* version */ "1", + ); assert(f1 !== f3, "Changed target: Expected to have different instances of document"); compilerOptions.preserveConstEnums = true; - const f4 = documentRegistry.acquireDocument("file1.ts", compilerOptions, ts.ScriptSnapshot.fromString("var x = 1;"), /* version */ "1"); + const f4 = documentRegistry.acquireDocument( + "file1.ts", + compilerOptions, + ts.ScriptSnapshot.fromString("var x = 1;"), + /* version */ "1", + ); assert(f3 === f4, "Changed preserveConstEnums: Expected to have the same instance of the document"); compilerOptions.module = ts.ModuleKind.System; - const f5 = documentRegistry.acquireDocument("file1.ts", compilerOptions, ts.ScriptSnapshot.fromString("var x = 1;"), /* version */ "1"); + const f5 = documentRegistry.acquireDocument( + "file1.ts", + compilerOptions, + ts.ScriptSnapshot.fromString("var x = 1;"), + /* version */ "1", + ); assert(f4 !== f5, "Changed module: Expected to have different instances of the document"); }); @@ -45,10 +80,20 @@ describe("unittests:: services:: DocumentRegistry", () => { const defaultCompilerOptions = ts.getDefaultCompilerOptions(); // Simulate one LS getting the document. - documentRegistry.acquireDocument("file1.ts", defaultCompilerOptions, ts.ScriptSnapshot.fromString("var x = 1;"), /* version */ "1"); + documentRegistry.acquireDocument( + "file1.ts", + defaultCompilerOptions, + ts.ScriptSnapshot.fromString("var x = 1;"), + /* version */ "1", + ); // Simulate another LS getting the document at another version. - const f2 = documentRegistry.acquireDocument("file1.ts", defaultCompilerOptions, ts.ScriptSnapshot.fromString("var x = 1;"), /* version */ "2"); + const f2 = documentRegistry.acquireDocument( + "file1.ts", + defaultCompilerOptions, + ts.ScriptSnapshot.fromString("var x = 1;"), + /* version */ "2", + ); assert(f2.version === "2"); }); @@ -61,7 +106,8 @@ describe("unittests:: services:: DocumentRegistry", () => { const snapshot = ts.ScriptSnapshot.fromString(contents); // Always treat any change as a full change. - snapshot.getChangeRange = () => ts.createTextChangeRange(ts.createTextSpan(0, contents.length), contents.length); + snapshot.getChangeRange = () => + ts.createTextChangeRange(ts.createTextSpan(0, contents.length), contents.length); // Simulate one LS getting the document. documentRegistry.acquireDocument("file1.ts", defaultCompilerOptions, snapshot, /* version */ "1"); diff --git a/src/testRunner/unittests/services/extract/helpers.ts b/src/testRunner/unittests/services/extract/helpers.ts index 65995d34c5537..111b45e4c1808 100644 --- a/src/testRunner/unittests/services/extract/helpers.ts +++ b/src/testRunner/unittests/services/extract/helpers.ts @@ -28,8 +28,9 @@ export function extractTest(source: string): Test { while (pos < source.length) { if ( - source.charCodeAt(pos) === ts.CharacterCodes.openBracket && - (source.charCodeAt(pos + 1) === ts.CharacterCodes.hash || source.charCodeAt(pos + 1) === ts.CharacterCodes.$) + source.charCodeAt(pos) === ts.CharacterCodes.openBracket + && (source.charCodeAt(pos + 1) === ts.CharacterCodes.hash + || source.charCodeAt(pos + 1) === ts.CharacterCodes.$) ) { const saved = pos; pos += 2; @@ -50,7 +51,10 @@ export function extractTest(source: string): Test { pos = saved; } } - else if (source.charCodeAt(pos) === ts.CharacterCodes.bar && source.charCodeAt(pos + 1) === ts.CharacterCodes.closeBracket) { + else if ( + source.charCodeAt(pos) === ts.CharacterCodes.bar + && source.charCodeAt(pos + 1) === ts.CharacterCodes.closeBracket + ) { text += source.substring(lastPos, pos); activeRanges[activeRanges.length - 1].end = text.length; const range = activeRanges.pop()!; @@ -87,14 +91,22 @@ export const notImplementedHost: ts.LanguageServiceHost = { fileExists: ts.notImplemented, }; -export function testExtractSymbol(caption: string, text: string, baselineFolder: string, description: ts.DiagnosticMessage, includeLib?: boolean) { +export function testExtractSymbol( + caption: string, + text: string, + baselineFolder: string, + description: ts.DiagnosticMessage, + includeLib?: boolean, +) { const t = extractTest(text); const selectionRange = t.ranges.get("selection")!; if (!selectionRange) { throw new Error(`Test ${caption} does not specify selection range`); } - [ts.Extension.Ts, ts.Extension.Js].forEach(extension => it(`${caption} [${extension}]`, () => runBaseline(extension))); + [ts.Extension.Ts, ts.Extension.Js].forEach(extension => + it(`${caption} [${extension}]`, () => runBaseline(extension)) + ); function runBaseline(extension: ts.Extension) { const path = "/a" + extension; @@ -117,8 +129,15 @@ export function testExtractSymbol(caption: string, text: string, baselineFolder: formatContext: ts.formatting.getFormatContext(ts.testFormatSettings, notImplementedHost), preferences: ts.emptyOptions, }; - const rangeToExtract = ts.refactor.extractSymbol.getRangeToExtract(sourceFile, ts.createTextSpanFromRange(selectionRange)); - assert.equal(rangeToExtract.errors, undefined, rangeToExtract.errors && "Range error: " + rangeToExtract.errors[0].messageText); + const rangeToExtract = ts.refactor.extractSymbol.getRangeToExtract( + sourceFile, + ts.createTextSpanFromRange(selectionRange), + ); + assert.equal( + rangeToExtract.errors, + undefined, + rangeToExtract.errors && "Range error: " + rangeToExtract.errors[0].messageText, + ); const infos = ts.refactor.extractSymbol.getRefactorActionsToExtractSymbol(context); const actions = ts.find(infos, info => info.description === description.message)!.actions; @@ -126,7 +145,10 @@ export function testExtractSymbol(caption: string, text: string, baselineFolder: data.push(`// ==ORIGINAL==`); data.push(text.replace("[#|", "/*[#|*/").replace("|]", "/*|]*/")); for (const action of actions) { - const { renameLocation, edits } = ts.refactor.extractSymbol.getRefactorEditsToExtractSymbol(context, action.name)!; + const { renameLocation, edits } = ts.refactor.extractSymbol.getRefactorEditsToExtractSymbol( + context, + action.name, + )!; assert.lengthOf(edits, 1); data.push(`// ==SCOPE::${action.description}==`); const newText = ts.textChanges.applyChanges(sourceFile.text, edits[0].textChanges); @@ -180,8 +202,14 @@ export function testExtractSymbolFailed(caption: string, text: string, descripti formatContext: ts.formatting.getFormatContext(ts.testFormatSettings, notImplementedHost), preferences: ts.emptyOptions, }; - const rangeToExtract = ts.refactor.extractSymbol.getRangeToExtract(sourceFile, ts.createTextSpanFromRange(selectionRange)); - assert.isUndefined(rangeToExtract.errors, rangeToExtract.errors && "Range error: " + rangeToExtract.errors[0].messageText); + const rangeToExtract = ts.refactor.extractSymbol.getRangeToExtract( + sourceFile, + ts.createTextSpanFromRange(selectionRange), + ); + assert.isUndefined( + rangeToExtract.errors, + rangeToExtract.errors && "Range error: " + rangeToExtract.errors[0].messageText, + ); const infos = ts.refactor.extractSymbol.getRefactorActionsToExtractSymbol(context); assert.isUndefined(ts.find(infos, info => info.description === description.message)); }); diff --git a/src/testRunner/unittests/services/extract/ranges.ts b/src/testRunner/unittests/services/extract/ranges.ts index ce0312d3f1288..79251e275f624 100644 --- a/src/testRunner/unittests/services/extract/ranges.ts +++ b/src/testRunner/unittests/services/extract/ranges.ts @@ -11,7 +11,11 @@ function testExtractRangeFailed(caption: string, s: string, expectedErrors: stri if (!selectionRange) { throw new Error(`Test ${s} does not specify selection range`); } - const result = ts.refactor.extractSymbol.getRangeToExtract(file, ts.createTextSpanFromRange(selectionRange), /*invoked*/ false); + const result = ts.refactor.extractSymbol.getRangeToExtract( + file, + ts.createTextSpanFromRange(selectionRange), + /*invoked*/ false, + ); assert(result.targetRange === undefined, "failure expected"); const sortedErrors = result.errors.map(e => e.messageText as string).sort(); assert.deepEqual(sortedErrors, expectedErrors.sort(), "unexpected errors"); @@ -333,7 +337,10 @@ function f() { } } `, - [ts.refactor.extractSymbol.Messages.cannotExtractRangeContainingLabeledBreakOrContinueStatementWithTargetOutsideOfTheRange.message], + [ + ts.refactor.extractSymbol.Messages + .cannotExtractRangeContainingLabeledBreakOrContinueStatementWithTargetOutsideOfTheRange.message, + ], ); testExtractRangeFailed( @@ -404,7 +411,9 @@ switch (x) { [ts.refactor.extractSymbol.Messages.cannotExtractRangeContainingConditionalBreakOrContinueStatements.message], ); - testExtractRangeFailed("extractRangeFailed9", `var x = ([#||]1 + 2);`, [ts.refactor.extractSymbol.Messages.cannotExtractEmpty.message]); + testExtractRangeFailed("extractRangeFailed9", `var x = ([#||]1 + 2);`, [ + ts.refactor.extractSymbol.Messages.cannotExtractEmpty.message, + ]); testExtractRangeFailed( "extractRangeFailed10", @@ -434,9 +443,13 @@ switch (x) { [ts.refactor.extractSymbol.Messages.cannotExtractRangeContainingConditionalBreakOrContinueStatements.message], ); - testExtractRangeFailed("extractRangeFailed12", `let [#|x|];`, [ts.refactor.extractSymbol.Messages.statementOrExpressionExpected.message]); + testExtractRangeFailed("extractRangeFailed12", `let [#|x|];`, [ + ts.refactor.extractSymbol.Messages.statementOrExpressionExpected.message, + ]); - testExtractRangeFailed("extractRangeFailed13", `[#|return;|]`, [ts.refactor.extractSymbol.Messages.cannotExtractRange.message]); + testExtractRangeFailed("extractRangeFailed13", `[#|return;|]`, [ + ts.refactor.extractSymbol.Messages.cannotExtractRange.message, + ]); testExtractRangeFailed( "extractRangeFailed14", @@ -484,9 +497,15 @@ switch (x) { [ts.refactor.extractSymbol.Messages.cannotExtractRange.message], ); - testExtractRangeFailed("extractRangeFailed18", `[#|{ 1;|] }`, [ts.refactor.extractSymbol.Messages.cannotExtractRange.message]); + testExtractRangeFailed("extractRangeFailed18", `[#|{ 1;|] }`, [ + ts.refactor.extractSymbol.Messages.cannotExtractRange.message, + ]); - testExtractRangeFailed("extractRangeFailed19", `[#|/** @type {number} */|] const foo = 1;`, [ts.refactor.extractSymbol.Messages.cannotExtractJSDoc.message]); + testExtractRangeFailed("extractRangeFailed19", `[#|/** @type {number} */|] const foo = 1;`, [ + ts.refactor.extractSymbol.Messages.cannotExtractJSDoc.message, + ]); - testExtractRangeFailed("extract-method-not-for-token-expression-statement", `[#|a|]`, [ts.refactor.extractSymbol.Messages.cannotExtractIdentifier.message]); + testExtractRangeFailed("extract-method-not-for-token-expression-statement", `[#|a|]`, [ + ts.refactor.extractSymbol.Messages.cannotExtractIdentifier.message, + ]); }); diff --git a/src/testRunner/unittests/services/extract/symbolWalker.ts b/src/testRunner/unittests/services/extract/symbolWalker.ts index 48a2121a4f565..a5bf6380b7c84 100644 --- a/src/testRunner/unittests/services/extract/symbolWalker.ts +++ b/src/testRunner/unittests/services/extract/symbolWalker.ts @@ -2,7 +2,11 @@ import * as Harness from "../../../_namespaces/Harness"; import * as ts from "../../../_namespaces/ts"; describe("unittests:: services:: extract:: Symbol Walker", () => { - function test(description: string, source: string, verifier: (file: ts.SourceFile, checker: ts.TypeChecker) => void) { + function test( + description: string, + source: string, + verifier: (file: ts.SourceFile, checker: ts.TypeChecker) => void, + ) { it(description, () => { const result = Harness.Compiler.compileFiles( [{ diff --git a/src/testRunner/unittests/services/hostNewLineSupport.ts b/src/testRunner/unittests/services/hostNewLineSupport.ts index a509a29e16f48..6a289d7c5f03e 100644 --- a/src/testRunner/unittests/services/hostNewLineSupport.ts +++ b/src/testRunner/unittests/services/hostNewLineSupport.ts @@ -36,9 +36,22 @@ describe("unittests:: services:: hostNewLineSupport", () => { const result = ls.getEmitOutput("input.ts"); assert(!result.emitSkipped, "emit was skipped"); assert(result.outputFiles.length === 1, "a number of files other than 1 was output"); - assert(result.outputFiles[0].name === "input.js", `Expected output file name input.js, but got ${result.outputFiles[0].name}`); - assert(result.outputFiles[0].text.match(options.newLine === ts.NewLineKind.CarriageReturnLineFeed ? /\r\n/ : /[^\r]\n/), "expected to find appropriate newlines"); - assert(!result.outputFiles[0].text.match(options.newLine === ts.NewLineKind.CarriageReturnLineFeed ? /[^\r]\n/ : /\r\n/), "expected not to find inappropriate newlines"); + assert( + result.outputFiles[0].name === "input.js", + `Expected output file name input.js, but got ${result.outputFiles[0].name}`, + ); + assert( + result.outputFiles[0].text.match( + options.newLine === ts.NewLineKind.CarriageReturnLineFeed ? /\r\n/ : /[^\r]\n/, + ), + "expected to find appropriate newlines", + ); + assert( + !result.outputFiles[0].text.match( + options.newLine === ts.NewLineKind.CarriageReturnLineFeed ? /[^\r]\n/ : /\r\n/, + ), + "expected not to find inappropriate newlines", + ); } function verifyBothNewLines(content: string) { @@ -54,8 +67,16 @@ describe("unittests:: services:: hostNewLineSupport", () => { }]); const span = ls.getOutliningSpans("input.ts")[0]; const textAfterSpanCollapse = content.substring(span.textSpan.start + span.textSpan.length); - assert(textAfterSpanCollapse.match(options.newLine === ts.NewLineKind.CarriageReturnLineFeed ? /\r\n/ : /[^\r]\n/), "expected to find appropriate newlines"); - assert(!textAfterSpanCollapse.match(options.newLine === ts.NewLineKind.CarriageReturnLineFeed ? /[^\r]\n/ : /\r\n/), "expected not to find inappropriate newlines"); + assert( + textAfterSpanCollapse.match(options.newLine === ts.NewLineKind.CarriageReturnLineFeed ? /\r\n/ : /[^\r]\n/), + "expected to find appropriate newlines", + ); + assert( + !textAfterSpanCollapse.match( + options.newLine === ts.NewLineKind.CarriageReturnLineFeed ? /[^\r]\n/ : /\r\n/, + ), + "expected not to find inappropriate newlines", + ); } it("should exist and respect provided compiler options", () => { @@ -67,10 +88,16 @@ describe("unittests:: services:: hostNewLineSupport", () => { }); it("should respect CRLF line endings around outlining spans", () => { - verifyOutliningSpanNewLines('// comment not included\r\n// #region name\r\nlet x: string = "x";\r\n// #endregion name\r\n', { newLine: ts.NewLineKind.CarriageReturnLineFeed }); + verifyOutliningSpanNewLines( + '// comment not included\r\n// #region name\r\nlet x: string = "x";\r\n// #endregion name\r\n', + { newLine: ts.NewLineKind.CarriageReturnLineFeed }, + ); }); it("should respect LF line endings around outlining spans", () => { - verifyOutliningSpanNewLines('// comment not included\n// #region name\nlet x: string = "x";\n// #endregion name\n\n', { newLine: ts.NewLineKind.LineFeed }); + verifyOutliningSpanNewLines( + '// comment not included\n// #region name\nlet x: string = "x";\n// #endregion name\n\n', + { newLine: ts.NewLineKind.LineFeed }, + ); }); }); diff --git a/src/testRunner/unittests/services/languageService.ts b/src/testRunner/unittests/services/languageService.ts index 128eec74a2a09..a8dac2a1531d7 100644 --- a/src/testRunner/unittests/services/languageService.ts +++ b/src/testRunner/unittests/services/languageService.ts @@ -121,7 +121,10 @@ export function Component(x: Config): any;`, // Change other projectVersion = "2"; - files.set("/project/other.ts", { version: "2", text: `export function foo() { } export function bar() { }` }); + files.set("/project/other.ts", { + version: "2", + text: `export function foo() { } export function bar() { }`, + }); const program3 = ls.getProgram()!; assert.notStrictEqual(program2, program3); verifyProgramFiles(program3); @@ -185,14 +188,19 @@ export function Component(x: Config): any;`, content: `class class2 {}`, }; const system = createServerHost([config1, class1, class1Dts, config2, class2, libFile]); - const result = ts.getParsedCommandLineOfConfigFile(`/user/username/projects/myproject/projects/project2/tsconfig.json`, /*optionsToExtend*/ undefined, { - useCaseSensitiveFileNames: true, - fileExists: path => system.fileExists(path), - readFile: path => system.readFile(path), - getCurrentDirectory: () => system.getCurrentDirectory(), - readDirectory: (path, extensions, excludes, includes, depth) => system.readDirectory(path, extensions, excludes, includes, depth), - onUnRecoverableConfigFileDiagnostic: ts.noop, - })!; + const result = ts.getParsedCommandLineOfConfigFile( + `/user/username/projects/myproject/projects/project2/tsconfig.json`, + /*optionsToExtend*/ undefined, + { + useCaseSensitiveFileNames: true, + fileExists: path => system.fileExists(path), + readFile: path => system.readFile(path), + getCurrentDirectory: () => system.getCurrentDirectory(), + readDirectory: (path, extensions, excludes, includes, depth) => + system.readDirectory(path, extensions, excludes, includes, depth), + onUnRecoverableConfigFileDiagnostic: ts.noop, + }, + )!; const host: ts.LanguageServiceHost = { useCaseSensitiveFileNames: ts.returnTrue, useSourceOfProjectReferenceRedirect, @@ -208,7 +216,8 @@ export function Component(x: Config): any;`, const text = system.readFile(path); return text ? ts.ScriptSnapshot.fromString(text) : undefined; }, - readDirectory: (path, extensions, excludes, includes, depth) => system.readDirectory(path, extensions, excludes, includes, depth), + readDirectory: (path, extensions, excludes, includes, depth) => + system.readDirectory(path, extensions, excludes, includes, depth), getCurrentDirectory: () => system.getCurrentDirectory(), getDefaultLibFileName: () => libFile.path, getProjectReferences: () => result.projectReferences, @@ -231,10 +240,16 @@ export function Component(x: Config): any;`, [libFile.path, class1.path, class3, class2.path], ); // Add excluded file to referenced project - system.ensureFileOrFolder({ path: `/user/username/projects/myproject/projects/project1/temp/file.d.ts`, content: `declare class file {}` }); + system.ensureFileOrFolder({ + path: `/user/username/projects/myproject/projects/project1/temp/file.d.ts`, + content: `declare class file {}`, + }); assert.strictEqual(ls.getProgram(), program); // Add output from new class to referenced project - system.writeFile(`/user/username/projects/myproject/projects/project1/class3.d.ts`, `declare class class3 {}`); + system.writeFile( + `/user/username/projects/myproject/projects/project1/class3.d.ts`, + `declare class class3 {}`, + ); assert.strictEqual(ls.getProgram(), program); }); @@ -262,7 +277,10 @@ export function Component(x: Config): any;`, [libFile.path, class1Dts.path, class3Dts, class2.path], ); // Add excluded file to referenced project - system.ensureFileOrFolder({ path: `/user/username/projects/myproject/projects/project1/temp/file.d.ts`, content: `declare class file {}` }); + system.ensureFileOrFolder({ + path: `/user/username/projects/myproject/projects/project1/temp/file.d.ts`, + content: `declare class file {}`, + }); assert.strictEqual(ls.getProgram(), program2); // Delete output from new class to referenced project system.deleteFile(class3Dts); diff --git a/src/testRunner/unittests/services/organizeImports.ts b/src/testRunner/unittests/services/organizeImports.ts index ba87f5acba615..eeac990fbe8a3 100644 --- a/src/testRunner/unittests/services/organizeImports.ts +++ b/src/testRunner/unittests/services/organizeImports.ts @@ -46,9 +46,18 @@ describe("unittests:: services:: organizeImports", () => { }); function assertSortsBefore(importString1: string, importString2: string) { - const [{ moduleSpecifier: moduleSpecifier1 }, { moduleSpecifier: moduleSpecifier2 }] = parseImports(importString1, importString2); - assert.equal(ts.OrganizeImports.compareModuleSpecifiers(moduleSpecifier1, moduleSpecifier2, /*ignoreCase*/ true), ts.Comparison.LessThan); - assert.equal(ts.OrganizeImports.compareModuleSpecifiers(moduleSpecifier2, moduleSpecifier1, /*ignoreCase*/ true), ts.Comparison.GreaterThan); + const [{ moduleSpecifier: moduleSpecifier1 }, { moduleSpecifier: moduleSpecifier2 }] = parseImports( + importString1, + importString2, + ); + assert.equal( + ts.OrganizeImports.compareModuleSpecifiers(moduleSpecifier1, moduleSpecifier2, /*ignoreCase*/ true), + ts.Comparison.LessThan, + ); + assert.equal( + ts.OrganizeImports.compareModuleSpecifiers(moduleSpecifier2, moduleSpecifier1, /*ignoreCase*/ true), + ts.Comparison.GreaterThan, + ); } }); @@ -365,7 +374,11 @@ export const Other = 1; content: "function F() { }", }; const languageService = makeLanguageService(testFile); - const changes = languageService.organizeImports({ type: "file", fileName: testFile.path }, ts.testFormatSettings, ts.emptyOptions); + const changes = languageService.organizeImports( + { type: "file", fileName: testFile.path }, + ts.testFormatSettings, + ts.emptyOptions, + ); assert.isEmpty(changes); }); @@ -375,7 +388,11 @@ export const Other = 1; content: "declare module '*';", }; const languageService = makeLanguageService(testFile); - const changes = languageService.organizeImports({ type: "file", fileName: testFile.path }, ts.testFormatSettings, ts.emptyOptions); + const changes = languageService.organizeImports( + { type: "file", fileName: testFile.path }, + ts.testFormatSettings, + ts.emptyOptions, + ); assert.isEmpty(changes); }); @@ -385,7 +402,11 @@ export const Other = 1; content: `import { f } from 'foo';\nf();`, }; const languageService = makeLanguageService(testFile); - const changes = languageService.organizeImports({ type: "file", fileName: testFile.path }, ts.testFormatSettings, ts.emptyOptions); + const changes = languageService.organizeImports( + { type: "file", fileName: testFile.path }, + ts.testFormatSettings, + ts.emptyOptions, + ); assert.isEmpty(changes); }); @@ -480,7 +501,11 @@ D; content: `import { f } from 'foo';\nf();`, }; const languageService = makeLanguageService(testFile); - const changes = languageService.organizeImports({ type: "file", fileName: testFile.path }, ts.testFormatSettings, ts.emptyOptions); + const changes = languageService.organizeImports( + { type: "file", fileName: testFile.path }, + ts.testFormatSettings, + ts.emptyOptions, + ); assert.isEmpty(changes); }); @@ -501,7 +526,11 @@ import { } from "lib"; `, }; const languageService = makeLanguageService(testFile); - const changes = languageService.organizeImports({ type: "file", fileName: testFile.path }, ts.testFormatSettings, ts.emptyOptions); + const changes = languageService.organizeImports( + { type: "file", fileName: testFile.path }, + ts.testFormatSettings, + ts.emptyOptions, + ); assert.isEmpty(changes); }); @@ -519,9 +548,12 @@ declare module 'caseless' { }`, }); - testOrganizeImports("Unused_preserve_imports_for_module_augmentation_in_non_declaration_file", /*skipDestructiveCodeActions*/ false, { - path: "/test.ts", - content: ` + testOrganizeImports( + "Unused_preserve_imports_for_module_augmentation_in_non_declaration_file", + /*skipDestructiveCodeActions*/ false, + { + path: "/test.ts", + content: ` import foo from 'foo'; import { Caseless } from 'caseless'; @@ -531,7 +563,8 @@ declare module 'caseless' { test(name: KeyType): boolean; } }`, - }); + }, + ); it("Unused_false_positive_shorthand_assignment", () => { const testFile = { @@ -542,7 +575,11 @@ const o = { x }; `, }; const languageService = makeLanguageService(testFile); - const changes = languageService.organizeImports({ type: "file", fileName: testFile.path }, ts.testFormatSettings, ts.emptyOptions); + const changes = languageService.organizeImports( + { type: "file", fileName: testFile.path }, + ts.testFormatSettings, + ts.emptyOptions, + ); assert.isEmpty(changes); }); @@ -555,7 +592,11 @@ export { x }; `, }; const languageService = makeLanguageService(testFile); - const changes = languageService.organizeImports({ type: "file", fileName: testFile.path }, ts.testFormatSettings, ts.emptyOptions); + const changes = languageService.organizeImports( + { type: "file", fileName: testFile.path }, + ts.testFormatSettings, + ts.emptyOptions, + ); assert.isEmpty(changes); }); @@ -960,14 +1001,32 @@ export * from "lib"; testOrganizeImports(`${testName}.exports`, /*skipDestructiveCodeActions*/ true, testFile, ...otherFiles); } - function testOrganizeImports(testName: string, skipDestructiveCodeActions: boolean, testFile: File, ...otherFiles: File[]) { - it(testName, () => runBaseline(`organizeImports/${testName}.ts`, skipDestructiveCodeActions, testFile, ...otherFiles)); + function testOrganizeImports( + testName: string, + skipDestructiveCodeActions: boolean, + testFile: File, + ...otherFiles: File[] + ) { + it( + testName, + () => + runBaseline(`organizeImports/${testName}.ts`, skipDestructiveCodeActions, testFile, ...otherFiles), + ); } - function runBaseline(baselinePath: string, skipDestructiveCodeActions: boolean, testFile: File, ...otherFiles: File[]) { + function runBaseline( + baselinePath: string, + skipDestructiveCodeActions: boolean, + testFile: File, + ...otherFiles: File[] + ) { const { path: testPath, content: testContent } = testFile; const languageService = makeLanguageService(testFile, ...otherFiles); - const changes = languageService.organizeImports({ skipDestructiveCodeActions, type: "file", fileName: testPath }, ts.testFormatSettings, ts.emptyOptions); + const changes = languageService.organizeImports( + { skipDestructiveCodeActions, type: "file", fileName: testPath }, + ts.testFormatSettings, + ts.emptyOptions, + ); assert.equal(changes.length, 1); assert.equal(changes[0].fileName, testPath); @@ -985,22 +1044,39 @@ export * from "lib"; function makeLanguageService(...files: File[]) { const host = createServerHost(files); - const projectService = createProjectService(host, { useSingleInferredProject: true, allowNonBaseliningLogger: true }); - projectService.setCompilerOptionsForInferredProjects({ jsx: files.some(f => f.path.endsWith("x")) ? ts.JsxEmit.React : ts.JsxEmit.None }); + const projectService = createProjectService(host, { + useSingleInferredProject: true, + allowNonBaseliningLogger: true, + }); + projectService.setCompilerOptionsForInferredProjects({ + jsx: files.some(f => f.path.endsWith("x")) ? ts.JsxEmit.React : ts.JsxEmit.None, + }); files.forEach(f => projectService.openClientFile(f.path)); return projectService.inferredProjects[0].getLanguageService(); } }); function parseImports(...importStrings: string[]): readonly ts.ImportDeclaration[] { - const sourceFile = ts.createSourceFile("a.ts", importStrings.join("\n"), ts.ScriptTarget.ES2015, /*setParentNodes*/ true, ts.ScriptKind.TS); + const sourceFile = ts.createSourceFile( + "a.ts", + importStrings.join("\n"), + ts.ScriptTarget.ES2015, + /*setParentNodes*/ true, + ts.ScriptKind.TS, + ); const imports = ts.filter(sourceFile.statements, ts.isImportDeclaration); assert.equal(imports.length, importStrings.length); return imports; } function parseExports(...exportStrings: string[]): readonly ts.ExportDeclaration[] { - const sourceFile = ts.createSourceFile("a.ts", exportStrings.join("\n"), ts.ScriptTarget.ES2015, /*setParentNodes*/ true, ts.ScriptKind.TS); + const sourceFile = ts.createSourceFile( + "a.ts", + exportStrings.join("\n"), + ts.ScriptTarget.ES2015, + /*setParentNodes*/ true, + ts.ScriptKind.TS, + ); const exports = ts.filter(sourceFile.statements, ts.isExportDeclaration); assert.equal(exports.length, exportStrings.length); return exports; diff --git a/src/testRunner/unittests/services/patternMatcher.ts b/src/testRunner/unittests/services/patternMatcher.ts index d48dd97220b59..1307479226c60 100644 --- a/src/testRunner/unittests/services/patternMatcher.ts +++ b/src/testRunner/unittests/services/patternMatcher.ts @@ -135,7 +135,10 @@ describe("unittests:: services:: PatternMatcher", () => { }); it("TwoUppercaseCharacters", () => { - assertSegmentMatch("SimpleUIElement", "SiUI", { kind: ts.PatternMatchKind.camelCase, isCaseSensitive: true }); + assertSegmentMatch("SimpleUIElement", "SiUI", { + kind: ts.PatternMatchKind.camelCase, + isCaseSensitive: true, + }); }); it("PreferCaseSensitiveLowercasePattern", () => { @@ -179,7 +182,10 @@ describe("unittests:: services:: PatternMatcher", () => { }); it("AllLowerPattern1", () => { - assertSegmentMatch("FogBarChangedEventArgs", "changedeventargs", { kind: ts.PatternMatchKind.substring, isCaseSensitive: false }); + assertSegmentMatch("FogBarChangedEventArgs", "changedeventargs", { + kind: ts.PatternMatchKind.substring, + isCaseSensitive: false, + }); }); it("AllLowerPattern2", () => { @@ -197,55 +203,94 @@ describe("unittests:: services:: PatternMatcher", () => { describe("MultiWordPattern", () => { it("ExactWithLowercase", () => { - assertSegmentMatch("AddMetadataReference", "addmetadatareference", { kind: ts.PatternMatchKind.exact, isCaseSensitive: false }); + assertSegmentMatch("AddMetadataReference", "addmetadatareference", { + kind: ts.PatternMatchKind.exact, + isCaseSensitive: false, + }); }); it("SingleLowercasedSearchWord1", () => { - assertSegmentMatch("AddMetadataReference", "add", { kind: ts.PatternMatchKind.prefix, isCaseSensitive: false }); + assertSegmentMatch("AddMetadataReference", "add", { + kind: ts.PatternMatchKind.prefix, + isCaseSensitive: false, + }); }); it("SingleLowercasedSearchWord2", () => { - assertSegmentMatch("AddMetadataReference", "metadata", { kind: ts.PatternMatchKind.substring, isCaseSensitive: false }); + assertSegmentMatch("AddMetadataReference", "metadata", { + kind: ts.PatternMatchKind.substring, + isCaseSensitive: false, + }); }); it("SingleUppercaseSearchWord1", () => { - assertSegmentMatch("AddMetadataReference", "Add", { kind: ts.PatternMatchKind.prefix, isCaseSensitive: true }); + assertSegmentMatch("AddMetadataReference", "Add", { + kind: ts.PatternMatchKind.prefix, + isCaseSensitive: true, + }); }); it("SingleUppercaseSearchWord2", () => { - assertSegmentMatch("AddMetadataReference", "Metadata", { kind: ts.PatternMatchKind.substring, isCaseSensitive: true }); + assertSegmentMatch("AddMetadataReference", "Metadata", { + kind: ts.PatternMatchKind.substring, + isCaseSensitive: true, + }); }); it("SingleUppercaseSearchLetter1", () => { - assertSegmentMatch("AddMetadataReference", "A", { kind: ts.PatternMatchKind.prefix, isCaseSensitive: true }); + assertSegmentMatch("AddMetadataReference", "A", { + kind: ts.PatternMatchKind.prefix, + isCaseSensitive: true, + }); }); it("SingleUppercaseSearchLetter2", () => { - assertSegmentMatch("AddMetadataReference", "M", { kind: ts.PatternMatchKind.substring, isCaseSensitive: true }); + assertSegmentMatch("AddMetadataReference", "M", { + kind: ts.PatternMatchKind.substring, + isCaseSensitive: true, + }); }); it("TwoLowercaseWords0", () => { - assertSegmentMatch("AddMetadataReference", "add metadata", { kind: ts.PatternMatchKind.prefix, isCaseSensitive: false }); + assertSegmentMatch("AddMetadataReference", "add metadata", { + kind: ts.PatternMatchKind.prefix, + isCaseSensitive: false, + }); }); it("TwoLowercaseWords1", () => { - assertSegmentMatch("AddMetadataReference", "A M", { kind: ts.PatternMatchKind.prefix, isCaseSensitive: true }); + assertSegmentMatch("AddMetadataReference", "A M", { + kind: ts.PatternMatchKind.prefix, + isCaseSensitive: true, + }); }); it("TwoLowercaseWords2", () => { - assertSegmentMatch("AddMetadataReference", "AM", { kind: ts.PatternMatchKind.camelCase, isCaseSensitive: true }); + assertSegmentMatch("AddMetadataReference", "AM", { + kind: ts.PatternMatchKind.camelCase, + isCaseSensitive: true, + }); }); it("TwoLowercaseWords3", () => { - assertSegmentMatch("AddMetadataReference", "ref Metadata", { kind: ts.PatternMatchKind.substring, isCaseSensitive: true }); + assertSegmentMatch("AddMetadataReference", "ref Metadata", { + kind: ts.PatternMatchKind.substring, + isCaseSensitive: true, + }); }); it("TwoLowercaseWords4", () => { - assertSegmentMatch("AddMetadataReference", "ref M", { kind: ts.PatternMatchKind.substring, isCaseSensitive: true }); + assertSegmentMatch("AddMetadataReference", "ref M", { + kind: ts.PatternMatchKind.substring, + isCaseSensitive: true, + }); }); it("MixedCamelCase", () => { - assertSegmentMatch("AddMetadataReference", "AMRe", { kind: ts.PatternMatchKind.camelCase, isCaseSensitive: true }); + assertSegmentMatch("AddMetadataReference", "AMRe", { + kind: ts.PatternMatchKind.camelCase, + isCaseSensitive: true, + }); }); it("BlankPattern", () => { @@ -257,15 +302,24 @@ describe("unittests:: services:: PatternMatcher", () => { }); it("EachWordSeparately1", () => { - assertSegmentMatch("AddMetadataReference", "add Meta", { kind: ts.PatternMatchKind.prefix, isCaseSensitive: false }); + assertSegmentMatch("AddMetadataReference", "add Meta", { + kind: ts.PatternMatchKind.prefix, + isCaseSensitive: false, + }); }); it("EachWordSeparately2", () => { - assertSegmentMatch("AddMetadataReference", "Add meta", { kind: ts.PatternMatchKind.prefix, isCaseSensitive: true }); + assertSegmentMatch("AddMetadataReference", "Add meta", { + kind: ts.PatternMatchKind.prefix, + isCaseSensitive: true, + }); }); it("EachWordSeparately3", () => { - assertSegmentMatch("AddMetadataReference", "Add Meta", { kind: ts.PatternMatchKind.prefix, isCaseSensitive: true }); + assertSegmentMatch("AddMetadataReference", "Add Meta", { + kind: ts.PatternMatchKind.prefix, + isCaseSensitive: true, + }); }); it("MixedCasing", () => { @@ -299,15 +353,24 @@ describe("unittests:: services:: PatternMatcher", () => { }); it("DottedPattern3", () => { - assertFullMatch("Foo.Bar.Baz", "Quux", "B.B.Q", { kind: ts.PatternMatchKind.prefix, isCaseSensitive: true }); + assertFullMatch("Foo.Bar.Baz", "Quux", "B.B.Q", { + kind: ts.PatternMatchKind.prefix, + isCaseSensitive: true, + }); }); it("DottedPattern4", () => { - assertFullMatch("Foo.Bar.Baz", "Quux", "Baz.Quux", { kind: ts.PatternMatchKind.exact, isCaseSensitive: true }); + assertFullMatch("Foo.Bar.Baz", "Quux", "Baz.Quux", { + kind: ts.PatternMatchKind.exact, + isCaseSensitive: true, + }); }); it("DottedPattern5", () => { - assertFullMatch("Foo.Bar.Baz", "Quux", "F.B.B.Quux", { kind: ts.PatternMatchKind.prefix, isCaseSensitive: true }); + assertFullMatch("Foo.Bar.Baz", "Quux", "F.B.B.Quux", { + kind: ts.PatternMatchKind.prefix, + isCaseSensitive: true, + }); }); it("DottedPattern6", () => { @@ -328,8 +391,16 @@ describe("unittests:: services:: PatternMatcher", () => { assert.equal(ts.createPatternMatcher(pattern), undefined); } - function assertFullMatch(dottedContainer: string, candidate: string, pattern: string, expected: ts.PatternMatch | undefined): void { - assert.deepEqual(ts.createPatternMatcher(pattern)!.getFullMatch(dottedContainer.split("."), candidate), expected); + function assertFullMatch( + dottedContainer: string, + candidate: string, + pattern: string, + expected: ts.PatternMatch | undefined, + ): void { + assert.deepEqual( + ts.createPatternMatcher(pattern)!.getFullMatch(dottedContainer.split("."), candidate), + expected, + ); } function spanListToSubstrings(identifier: string, spans: ts.TextSpan[]) { diff --git a/src/testRunner/unittests/services/preProcessFile.ts b/src/testRunner/unittests/services/preProcessFile.ts index 1bd38bb2e0851..e6d2e60f7ca75 100644 --- a/src/testRunner/unittests/services/preProcessFile.ts +++ b/src/testRunner/unittests/services/preProcessFile.ts @@ -1,15 +1,37 @@ import * as ts from "../../_namespaces/ts"; describe("unittests:: services:: PreProcessFile:", () => { - function test(sourceText: string, readImportFile: boolean, detectJavaScriptImports: boolean, expectedPreProcess: ts.PreProcessedFileInfo): void { + function test( + sourceText: string, + readImportFile: boolean, + detectJavaScriptImports: boolean, + expectedPreProcess: ts.PreProcessedFileInfo, + ): void { const resultPreProcess = ts.preProcessFile(sourceText, readImportFile, detectJavaScriptImports); - assert.equal(resultPreProcess.isLibFile, expectedPreProcess.isLibFile, "Pre-processed file has different value for isLibFile. Expected: " + expectedPreProcess.isLibFile + ". Actual: " + resultPreProcess.isLibFile); + assert.equal( + resultPreProcess.isLibFile, + expectedPreProcess.isLibFile, + "Pre-processed file has different value for isLibFile. Expected: " + expectedPreProcess.isLibFile + + ". Actual: " + resultPreProcess.isLibFile, + ); checkFileReferenceList("Imported files", expectedPreProcess.importedFiles, resultPreProcess.importedFiles); - checkFileReferenceList("Referenced files", expectedPreProcess.referencedFiles, resultPreProcess.referencedFiles); - checkFileReferenceList("Type reference directives", expectedPreProcess.typeReferenceDirectives, resultPreProcess.typeReferenceDirectives); - checkFileReferenceList("Lib reference directives", expectedPreProcess.libReferenceDirectives, resultPreProcess.libReferenceDirectives); + checkFileReferenceList( + "Referenced files", + expectedPreProcess.referencedFiles, + resultPreProcess.referencedFiles, + ); + checkFileReferenceList( + "Type reference directives", + expectedPreProcess.typeReferenceDirectives, + resultPreProcess.typeReferenceDirectives, + ); + checkFileReferenceList( + "Lib reference directives", + expectedPreProcess.libReferenceDirectives, + resultPreProcess.libReferenceDirectives, + ); assert.deepEqual(resultPreProcess.ambientExternalModules, expectedPreProcess.ambientExternalModules); } @@ -18,30 +40,51 @@ describe("unittests:: services:: PreProcessFile:", () => { if (expected === actual) { return; } - assert.deepEqual(actual, expected, `Expected [${kind}] ${JSON.stringify(expected)}, got ${JSON.stringify(actual)}`); + assert.deepEqual( + actual, + expected, + `Expected [${kind}] ${JSON.stringify(expected)}, got ${JSON.stringify(actual)}`, + ); } describe("Test preProcessFiles,", () => { it("Correctly return referenced files from triple slash", () => { - test('///' + "\n" + '///' + "\n" + '///' + "\n" + '///', /*readImportFile*/ true, /*detectJavaScriptImports*/ false, { - referencedFiles: [{ fileName: "refFile1.ts", pos: 22, end: 33 }, { fileName: "refFile2.ts", pos: 59, end: 70 }, { fileName: "refFile3.ts", pos: 94, end: 105 }, { fileName: "..\\refFile4d.ts", pos: 131, end: 146 }], - importedFiles: [] as ts.FileReference[], - typeReferenceDirectives: [], - libReferenceDirectives: [], - ambientExternalModules: undefined, - isLibFile: false, - }); + test( + '///' + "\n" + '///' + "\n" + + '///' + "\n" + '///', + /*readImportFile*/ true, + /*detectJavaScriptImports*/ false, + { + referencedFiles: [ + { fileName: "refFile1.ts", pos: 22, end: 33 }, + { fileName: "refFile2.ts", pos: 59, end: 70 }, + { fileName: "refFile3.ts", pos: 94, end: 105 }, + { fileName: "..\\refFile4d.ts", pos: 131, end: 146 }, + ], + importedFiles: [] as ts.FileReference[], + typeReferenceDirectives: [], + libReferenceDirectives: [], + ambientExternalModules: undefined, + isLibFile: false, + }, + ); }); it("Do not return reference path because of invalid triple-slash syntax", () => { - test('///' + "\n" + '///' + "\n" + '///' + "\n" + '///', /*readImportFile*/ true, /*detectJavaScriptImports*/ false, { - referencedFiles: [] as ts.FileReference[], - importedFiles: [] as ts.FileReference[], - typeReferenceDirectives: [], - libReferenceDirectives: [], - ambientExternalModules: undefined, - isLibFile: false, - }); + test( + '///' + "\n" + '///' + "\n" + + '///' + "\n" + '///', + /*readImportFile*/ true, + /*detectJavaScriptImports*/ false, + { + referencedFiles: [] as ts.FileReference[], + importedFiles: [] as ts.FileReference[], + typeReferenceDirectives: [], + libReferenceDirectives: [], + ambientExternalModules: undefined, + isLibFile: false, + }, + ); }); it("Do not return reference path of non-imports", () => { @@ -67,69 +110,106 @@ describe("unittests:: services:: PreProcessFile:", () => { }); it("Correctly return imported files", () => { - test('import i1 = require("r1.ts"); import i2 =require("r2.ts"); import i3= require("r3.ts"); import i4=require("r4.ts"); import i5 = require ("r5.ts");', /*readImportFile*/ true, /*detectJavaScriptImports*/ false, { - referencedFiles: [] as ts.FileReference[], - typeReferenceDirectives: [], - libReferenceDirectives: [], - importedFiles: [{ fileName: "r1.ts", pos: 20, end: 25 }, { fileName: "r2.ts", pos: 49, end: 54 }, { fileName: "r3.ts", pos: 78, end: 83 }, { fileName: "r4.ts", pos: 106, end: 111 }, { fileName: "r5.ts", pos: 138, end: 143 }], - ambientExternalModules: undefined, - isLibFile: false, - }); + test( + 'import i1 = require("r1.ts"); import i2 =require("r2.ts"); import i3= require("r3.ts"); import i4=require("r4.ts"); import i5 = require ("r5.ts");', + /*readImportFile*/ true, + /*detectJavaScriptImports*/ false, + { + referencedFiles: [] as ts.FileReference[], + typeReferenceDirectives: [], + libReferenceDirectives: [], + importedFiles: [ + { fileName: "r1.ts", pos: 20, end: 25 }, + { fileName: "r2.ts", pos: 49, end: 54 }, + { fileName: "r3.ts", pos: 78, end: 83 }, + { fileName: "r4.ts", pos: 106, end: 111 }, + { fileName: "r5.ts", pos: 138, end: 143 }, + ], + ambientExternalModules: undefined, + isLibFile: false, + }, + ); }); it("Do not return imported files if readImportFiles argument is false", () => { - test('import i1 = require("r1.ts"); import i2 =require("r2.ts"); import i3= require("r3.ts"); import i4=require("r4.ts"); import i5 = require ("r5.ts");', /*readImportFile*/ false, /*detectJavaScriptImports*/ false, { - referencedFiles: [] as ts.FileReference[], - typeReferenceDirectives: [], - libReferenceDirectives: [], - importedFiles: [] as ts.FileReference[], - ambientExternalModules: undefined, - isLibFile: false, - }); + test( + 'import i1 = require("r1.ts"); import i2 =require("r2.ts"); import i3= require("r3.ts"); import i4=require("r4.ts"); import i5 = require ("r5.ts");', + /*readImportFile*/ false, + /*detectJavaScriptImports*/ false, + { + referencedFiles: [] as ts.FileReference[], + typeReferenceDirectives: [], + libReferenceDirectives: [], + importedFiles: [] as ts.FileReference[], + ambientExternalModules: undefined, + isLibFile: false, + }, + ); }); it("Do not return import path because of invalid import syntax", () => { - test('import i1 require("r1.ts"); import = require("r2.ts") import i3= require("r3.ts"); import i5', /*readImportFile*/ true, /*detectJavaScriptImports*/ false, { - referencedFiles: [] as ts.FileReference[], - typeReferenceDirectives: [], - libReferenceDirectives: [], - importedFiles: [{ fileName: "r3.ts", pos: 73, end: 78 }], - ambientExternalModules: undefined, - isLibFile: false, - }); + test( + 'import i1 require("r1.ts"); import = require("r2.ts") import i3= require("r3.ts"); import i5', + /*readImportFile*/ true, + /*detectJavaScriptImports*/ false, + { + referencedFiles: [] as ts.FileReference[], + typeReferenceDirectives: [], + libReferenceDirectives: [], + importedFiles: [{ fileName: "r3.ts", pos: 73, end: 78 }], + ambientExternalModules: undefined, + isLibFile: false, + }, + ); }); it("Correctly return referenced files and import files", () => { - test('///' + "\n" + '///' + "\n" + 'import i1 = require("r1.ts"); import i2 =require("r2.ts");', /*readImportFile*/ true, /*detectJavaScriptImports*/ false, { - referencedFiles: [{ fileName: "refFile1.ts", pos: 20, end: 31 }, { fileName: "refFile2.ts", pos: 57, end: 68 }], - typeReferenceDirectives: [], - libReferenceDirectives: [], - importedFiles: [{ fileName: "r1.ts", pos: 92, end: 97 }, { fileName: "r2.ts", pos: 121, end: 126 }], - ambientExternalModules: undefined, - isLibFile: false, - }); + test( + '///' + "\n" + '///' + "\n" + + 'import i1 = require("r1.ts"); import i2 =require("r2.ts");', + /*readImportFile*/ true, + /*detectJavaScriptImports*/ false, + { + referencedFiles: [{ fileName: "refFile1.ts", pos: 20, end: 31 }, { + fileName: "refFile2.ts", + pos: 57, + end: 68, + }], + typeReferenceDirectives: [], + libReferenceDirectives: [], + importedFiles: [{ fileName: "r1.ts", pos: 92, end: 97 }, { fileName: "r2.ts", pos: 121, end: 126 }], + ambientExternalModules: undefined, + isLibFile: false, + }, + ); }); it("Correctly return referenced files and import files even with some invalid syntax", () => { - test('///' + "\n" + '///' + "\n" + 'import i1 = require("r1.ts"); import = require("r2.ts"); import i2 = require("r3.ts");', /*readImportFile*/ true, /*detectJavaScriptImports*/ false, { - referencedFiles: [{ fileName: "refFile1.ts", pos: 20, end: 31 }], - typeReferenceDirectives: [], - libReferenceDirectives: [], - importedFiles: [{ fileName: "r1.ts", pos: 91, end: 96 }, { fileName: "r3.ts", pos: 148, end: 153 }], - ambientExternalModules: undefined, - isLibFile: false, - }); + test( + '///' + "\n" + '///' + "\n" + + 'import i1 = require("r1.ts"); import = require("r2.ts"); import i2 = require("r3.ts");', + /*readImportFile*/ true, + /*detectJavaScriptImports*/ false, + { + referencedFiles: [{ fileName: "refFile1.ts", pos: 20, end: 31 }], + typeReferenceDirectives: [], + libReferenceDirectives: [], + importedFiles: [{ fileName: "r1.ts", pos: 91, end: 96 }, { fileName: "r3.ts", pos: 148, end: 153 }], + ambientExternalModules: undefined, + isLibFile: false, + }, + ); }); it("Correctly return ES6 imports", () => { test( - 'import * as ns from "m1";' + "\n" + - 'import def, * as ns from "m2";' + "\n" + - 'import def from "m3";' + "\n" + - 'import {a} from "m4";' + "\n" + - 'import {a as A} from "m5";' + "\n" + - 'import {a as A, b, c as C} from "m6";' + "\n" + - 'import def , {a, b, c as C} from "m7";' + "\n", + 'import * as ns from "m1";' + "\n" + + 'import def, * as ns from "m2";' + "\n" + + 'import def from "m3";' + "\n" + + 'import {a} from "m4";' + "\n" + + 'import {a as A} from "m5";' + "\n" + + 'import {a as A, b, c as C} from "m6";' + "\n" + + 'import def , {a, b, c as C} from "m7";' + "\n", /*readImportFile*/ true, /*detectJavaScriptImports*/ false, { @@ -154,20 +234,20 @@ describe("unittests:: services:: PreProcessFile:", () => { it("Correctly ignore commented imports following template expression", () => { /* eslint-disable no-template-curly-in-string */ test( - "/**" + "\n" + - " * Before" + "\n" + - " * ```" + "\n" + - ' * import * as a from "a";' + "\n" + - " * ```" + "\n" + - " */" + "\n" + - "type Foo = `${string}`;" + "\n" + - "/**" + "\n" + - " * After" + "\n" + - " * ```" + "\n" + - ' * import { B } from "b";' + "\n" + - ' * import * as c from "c";' + "\n" + - " * ```" + "\n" + - " */", + "/**" + "\n" + + " * Before" + "\n" + + " * ```" + "\n" + + ' * import * as a from "a";' + "\n" + + " * ```" + "\n" + + " */" + "\n" + + "type Foo = `${string}`;" + "\n" + + "/**" + "\n" + + " * After" + "\n" + + " * ```" + "\n" + + ' * import { B } from "b";' + "\n" + + ' * import * as c from "c";' + "\n" + + " * ```" + "\n" + + " */", /*readImportFile*/ true, /*detectJavaScriptImports*/ true, { @@ -184,14 +264,19 @@ describe("unittests:: services:: PreProcessFile:", () => { it("Ignores imports in template strings", () => { /* eslint-disable no-template-curly-in-string */ - test('a ? `&${a}` : `#${b}`;\n\n `import("${moduleSpecifier}").${id}`;', /*readImportFile*/ true, /*detectJavaScriptImports*/ true, { - referencedFiles: [], - typeReferenceDirectives: [], - libReferenceDirectives: [], - importedFiles: [], - ambientExternalModules: undefined, - isLibFile: false, - }); + test( + 'a ? `&${a}` : `#${b}`;\n\n `import("${moduleSpecifier}").${id}`;', + /*readImportFile*/ true, + /*detectJavaScriptImports*/ true, + { + referencedFiles: [], + typeReferenceDirectives: [], + libReferenceDirectives: [], + importedFiles: [], + ambientExternalModules: undefined, + isLibFile: false, + }, + ); /* eslint-enable no-template-curly-in-string */ }); @@ -213,9 +298,9 @@ describe("unittests:: services:: PreProcessFile:", () => { it("Correctly returns dynamic imports from template expression", () => { /* eslint-disable no-template-curly-in-string */ test( - "`${(
Text `` ${} text {} " + "\n" + - '${import("a")} {import("b")} ' + "\n" + - '${/* A comment */} ${/* import("ignored") */}
)}`', + "`${(
Text `` ${} text {} " + "\n" + + '${import("a")} {import("b")} ' + "\n" + + '${/* A comment */} ${/* import("ignored") */}
)}`', /*readImportFile*/ true, /*detectJavaScriptImports*/ true, { @@ -235,46 +320,56 @@ describe("unittests:: services:: PreProcessFile:", () => { it("Correctly returns dynamic imports from nested template expression", () => { /* eslint-disable no-template-curly-in-string */ - test('`${foo(`${bar(`${import("a")} ${import("b")}`, `${baz(`${import("c") ${import("d")}`)}`)}`)}`', /*readImportFile*/ true, /*detectJavaScriptImports*/ true, { - referencedFiles: [], - typeReferenceDirectives: [], - libReferenceDirectives: [], - importedFiles: [ - { fileName: "a", pos: 24, end: 25 }, - { fileName: "b", pos: 39, end: 40 }, - { fileName: "c", pos: 64, end: 65 }, - { fileName: "d", pos: 78, end: 79 }, - ], - ambientExternalModules: undefined, - isLibFile: false, - }); + test( + '`${foo(`${bar(`${import("a")} ${import("b")}`, `${baz(`${import("c") ${import("d")}`)}`)}`)}`', + /*readImportFile*/ true, + /*detectJavaScriptImports*/ true, + { + referencedFiles: [], + typeReferenceDirectives: [], + libReferenceDirectives: [], + importedFiles: [ + { fileName: "a", pos: 24, end: 25 }, + { fileName: "b", pos: 39, end: 40 }, + { fileName: "c", pos: 64, end: 65 }, + { fileName: "d", pos: 78, end: 79 }, + ], + ambientExternalModules: undefined, + isLibFile: false, + }, + ); /* eslint-enable no-template-curly-in-string */ }); it("Correctly returns dynamic imports from tagged template expression", () => { /* eslint-disable no-template-curly-in-string */ - test('foo`${ fn({ a: 100 }, import("a"), `${import("b")}`, import("c"), `${import("d")} foo`, import("e")) }`', /*readImportFile*/ true, /*detectJavaScriptImports*/ true, { - referencedFiles: [], - typeReferenceDirectives: [], - libReferenceDirectives: [], - importedFiles: [ - { fileName: "a", pos: 29, end: 30 }, - { fileName: "b", pos: 45, end: 46 }, - { fileName: "c", pos: 60, end: 61 }, - { fileName: "d", pos: 76, end: 77 }, - { fileName: "e", pos: 95, end: 96 }, - ], - ambientExternalModules: undefined, - isLibFile: false, - }); + test( + 'foo`${ fn({ a: 100 }, import("a"), `${import("b")}`, import("c"), `${import("d")} foo`, import("e")) }`', + /*readImportFile*/ true, + /*detectJavaScriptImports*/ true, + { + referencedFiles: [], + typeReferenceDirectives: [], + libReferenceDirectives: [], + importedFiles: [ + { fileName: "a", pos: 29, end: 30 }, + { fileName: "b", pos: 45, end: 46 }, + { fileName: "c", pos: 60, end: 61 }, + { fileName: "d", pos: 76, end: 77 }, + { fileName: "e", pos: 95, end: 96 }, + ], + ambientExternalModules: undefined, + isLibFile: false, + }, + ); /* eslint-enable no-template-curly-in-string */ }); it("Correctly returns dynamic imports from template expression and imports following it", () => { /* eslint-disable no-template-curly-in-string */ test( - 'const x = `hello ${await import("a").default}`;' + "\n\n" + - 'import { y } from "b";', + 'const x = `hello ${await import("a").default}`;' + "\n\n" + + 'import { y } from "b";', /*readImportFile*/ true, /*detectJavaScriptImports*/ true, { @@ -295,10 +390,10 @@ describe("unittests:: services:: PreProcessFile:", () => { it("Correctly returns dynamic imports from template expressions and other imports", () => { /* eslint-disable no-template-curly-in-string */ test( - 'const x = `x ${await import("a").default}`;' + "\n\n" + - 'import { y } from "b";' + "\n" + - 'const y = `y ${import("c")}`;' + "\n\n" + - 'import { d } from "d";', + 'const x = `x ${await import("a").default}`;' + "\n\n" + + 'import { y } from "b";' + "\n" + + 'const y = `y ${import("c")}`;' + "\n\n" + + 'import { d } from "d";', /*readImportFile*/ true, /*detectJavaScriptImports*/ true, { @@ -331,10 +426,10 @@ describe("unittests:: services:: PreProcessFile:", () => { it("Correctly return ES6 exports", () => { test( - 'export * from "m1";' + "\n" + - 'export {a} from "m2";' + "\n" + - 'export {a as A} from "m3";' + "\n" + - 'export {a as A, b, c as C} from "m4";' + "\n", + 'export * from "m1";' + "\n" + + 'export {a} from "m2";' + "\n" + + 'export {a as A} from "m3";' + "\n" + + 'export {a as A, b, c as C} from "m4";' + "\n", /*readImportFile*/ true, /*detectJavaScriptImports*/ false, { @@ -355,18 +450,18 @@ describe("unittests:: services:: PreProcessFile:", () => { it("Correctly handles import types", () => { test( - 'import type * as ns from "m1";' + "\n" + - 'import type def, * as ns from "m2";' + "\n" + - 'import type def from "m3";' + "\n" + - 'import type {a} from "m4";' + "\n" + - 'import type {a as A} from "m5";' + "\n" + - 'import type {a as A, b, c as C} from "m6";' + "\n" + - 'import type def , {a, b, c as C} from "m7";' + "\n" + - 'import type from "m8";' + "\n" + - 'import type T = require("m9");' + "\n" + - 'import type = require("m10");' + "\n" + - 'export import type T = require("m11");' + "\n" + - 'export import type = require("m12");' + "\n", + 'import type * as ns from "m1";' + "\n" + + 'import type def, * as ns from "m2";' + "\n" + + 'import type def from "m3";' + "\n" + + 'import type {a} from "m4";' + "\n" + + 'import type {a as A} from "m5";' + "\n" + + 'import type {a as A, b, c as C} from "m6";' + "\n" + + 'import type def , {a, b, c as C} from "m7";' + "\n" + + 'import type from "m8";' + "\n" + + 'import type T = require("m9");' + "\n" + + 'import type = require("m10");' + "\n" + + 'export import type T = require("m11");' + "\n" + + 'export import type = require("m12");' + "\n", /*readImportFile*/ true, /*detectJavaScriptImports*/ false, { @@ -395,10 +490,10 @@ describe("unittests:: services:: PreProcessFile:", () => { it("Correctly handles export types", () => { test( - 'export type * from "m1";' + "\n" + - 'export type {a} from "m2";' + "\n" + - 'export type {a as A} from "m3";' + "\n" + - 'export type {a as A, b, c as C} from "m4";' + "\n", + 'export type * from "m1";' + "\n" + + 'export type {a} from "m2";' + "\n" + + 'export type {a as A} from "m3";' + "\n" + + 'export type {a as A, b, c as C} from "m4";' + "\n", /*readImportFile*/ true, /*detectJavaScriptImports*/ false, { @@ -419,9 +514,9 @@ describe("unittests:: services:: PreProcessFile:", () => { it("Correctly handles import type node", () => { test( - 'const x: import("m1") = { x: 0, y: 0 };' + "\n" + - 'let y: import("m2").Bar.I = { a: "", b: 0 };' + "\n" + - 'let shim: typeof import("m3") = { Bar: Bar2 };' + "\n", + 'const x: import("m1") = { x: 0, y: 0 };' + "\n" + + 'let y: import("m2").Bar.I = { a: "", b: 0 };' + "\n" + + 'let shim: typeof import("m3") = { Bar: Bar2 };' + "\n", /*readImportFile*/ true, /*detectJavaScriptImports*/ false, { @@ -787,10 +882,10 @@ describe("unittests:: services:: PreProcessFile:", () => { it("Correctly handles dynamic imports with template literals", () => { test( - "const m1 = import('mod1');" + "\n" + - "const m2 = import(`mod2`);" + "\n" + - "Promise.all([import('mod3'), import(`mod4`)]);" + "\n" + - "import(/* webpackChunkName: 'module5' */ `mod5`);" + "\n", + "const m1 = import('mod1');" + "\n" + + "const m2 = import(`mod2`);" + "\n" + + "Promise.all([import('mod3'), import(`mod4`)]);" + "\n" + + "import(/* webpackChunkName: 'module5' */ `mod5`);" + "\n", /*readImportFile*/ true, /*detectJavaScriptImports*/ false, { @@ -812,9 +907,9 @@ describe("unittests:: services:: PreProcessFile:", () => { it("Correctly handles require calls with template literals in JS files", () => { test( - "const m1 = require(`mod1`);" + "\n" + - "f(require(`mod2`));" + "\n" + - "const a = { x: require(`mod3`) };" + "\n", + "const m1 = require(`mod1`);" + "\n" + + "f(require(`mod2`));" + "\n" + + "const a = { x: require(`mod3`) };" + "\n", /*readImportFile*/ true, /*detectJavaScriptImports*/ true, { @@ -833,17 +928,22 @@ describe("unittests:: services:: PreProcessFile:", () => { }); it("Correctly handles dependency lists in define(modName, [deplist]) calls with template literals in JS files", () => { - test("define(`mod`, [`mod1`, `mod2`], (m1, m2) => {});", /*readImportFile*/ true, /*detectJavaScriptImports*/ true, { - referencedFiles: [], - typeReferenceDirectives: [], - libReferenceDirectives: [], - importedFiles: [ - { fileName: "mod1", pos: 15, end: 19 }, - { fileName: "mod2", pos: 23, end: 27 }, - ], - ambientExternalModules: undefined, - isLibFile: false, - }); + test( + "define(`mod`, [`mod1`, `mod2`], (m1, m2) => {});", + /*readImportFile*/ true, + /*detectJavaScriptImports*/ true, + { + referencedFiles: [], + typeReferenceDirectives: [], + libReferenceDirectives: [], + importedFiles: [ + { fileName: "mod1", pos: 15, end: 19 }, + { fileName: "mod2", pos: 23, end: 27 }, + ], + ambientExternalModules: undefined, + isLibFile: false, + }, + ); }); }); }); diff --git a/src/testRunner/unittests/services/textChanges.ts b/src/testRunner/unittests/services/textChanges.ts index 57b3e206ef283..00b430ce2b176 100644 --- a/src/testRunner/unittests/services/textChanges.ts +++ b/src/testRunner/unittests/services/textChanges.ts @@ -24,7 +24,11 @@ describe("unittests:: services:: textChanges", () => { const newLineCharacter = ts.getNewLineCharacter(printerOptions); function getRuleProvider(placeOpenBraceOnNewLineForFunctions: boolean): ts.formatting.FormatContext { - return ts.formatting.getFormatContext(placeOpenBraceOnNewLineForFunctions ? { ...ts.testFormatSettings, placeOpenBraceOnNewLineForFunctions: true } : ts.testFormatSettings, notImplementedHost); + return ts.formatting.getFormatContext( + placeOpenBraceOnNewLineForFunctions + ? { ...ts.testFormatSettings, placeOpenBraceOnNewLineForFunctions: true } : ts.testFormatSettings, + notImplementedHost, + ); } // validate that positions that were recovered from the printed text actually match positions that will be created if the same text is parsed. @@ -49,7 +53,13 @@ describe("unittests:: services:: textChanges", () => { } } - function runSingleFileTest(caption: string, placeOpenBraceOnNewLineForFunctions: boolean, text: string, validateNodes: boolean, testBlock: (sourceFile: ts.SourceFile, changeTracker: ts.textChanges.ChangeTracker) => void) { + function runSingleFileTest( + caption: string, + placeOpenBraceOnNewLineForFunctions: boolean, + text: string, + validateNodes: boolean, + testBlock: (sourceFile: ts.SourceFile, changeTracker: ts.textChanges.ChangeTracker) => void, + ) { it(caption, () => { const sourceFile = ts.createSourceFile("source.ts", text, ts.ScriptTarget.ES2015, /*setParentNodes*/ true); const rulesProvider = getRuleProvider(placeOpenBraceOnNewLineForFunctions); @@ -59,7 +69,10 @@ describe("unittests:: services:: textChanges", () => { assert.equal(changes.length, 1); assert.equal(changes[0].fileName, sourceFile.fileName); const modified = ts.textChanges.applyChanges(sourceFile.text, changes[0].textChanges); - Harness.Baseline.runBaseline(`textChanges/${caption}.js`, `===ORIGINAL===${newLineCharacter}${text}${newLineCharacter}===MODIFIED===${newLineCharacter}${modified}`); + Harness.Baseline.runBaseline( + `textChanges/${caption}.js`, + `===ORIGINAL===${newLineCharacter}${text}${newLineCharacter}===MODIFIED===${newLineCharacter}${modified}`, + ); }); } @@ -85,30 +98,38 @@ namespace M } } }`; - runSingleFileTest("extractMethodLike", /*placeOpenBraceOnNewLineForFunctions*/ true, text, /*validateNodes*/ true, (sourceFile, changeTracker) => { - const statements = (findChild("foo", sourceFile) as ts.FunctionDeclaration).body!.statements.slice(1); - const newFunction = ts.factory.createFunctionDeclaration( - /*modifiers*/ undefined, - /*asteriskToken*/ undefined, - /*name*/ "bar", - /*typeParameters*/ undefined, - /*parameters*/ ts.emptyArray, - /*type*/ ts.factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword), - /*body */ ts.factory.createBlock(statements), - ); + runSingleFileTest( + "extractMethodLike", + /*placeOpenBraceOnNewLineForFunctions*/ true, + text, + /*validateNodes*/ true, + (sourceFile, changeTracker) => { + const statements = (findChild("foo", sourceFile) as ts.FunctionDeclaration).body!.statements.slice(1); + const newFunction = ts.factory.createFunctionDeclaration( + /*modifiers*/ undefined, + /*asteriskToken*/ undefined, + /*name*/ "bar", + /*typeParameters*/ undefined, + /*parameters*/ ts.emptyArray, + /*type*/ ts.factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword), + /*body */ ts.factory.createBlock(statements), + ); - changeTracker.insertNodeBefore(sourceFile, /*before*/ findChild("M2", sourceFile), newFunction); + changeTracker.insertNodeBefore(sourceFile, /*before*/ findChild("M2", sourceFile), newFunction); - // replace statements with return statement - const newStatement = ts.factory.createReturnStatement( - ts.factory.createCallExpression( - /*expression*/ newFunction.name!, - /*typeArguments*/ undefined, - /*argumentsArray*/ ts.emptyArray, - ), - ); - changeTracker.replaceNodeRange(sourceFile, statements[0], ts.last(statements), newStatement, { suffix: newLineCharacter }); - }); + // replace statements with return statement + const newStatement = ts.factory.createReturnStatement( + ts.factory.createCallExpression( + /*expression*/ newFunction.name!, + /*typeArguments*/ undefined, + /*argumentsArray*/ ts.emptyArray, + ), + ); + changeTracker.replaceNodeRange(sourceFile, statements[0], ts.last(statements), newStatement, { + suffix: newLineCharacter, + }); + }, + ); } { const text = ` @@ -120,9 +141,18 @@ function bar() { return 2; } `; - runSingleFileTest("deleteRange1", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - changeTracker.deleteRange(sourceFile, { pos: text.indexOf("function foo"), end: text.indexOf("function bar") }); - }); + runSingleFileTest( + "deleteRange1", + /*placeOpenBraceOnNewLineForFunctions*/ false, + text, + /*validateNodes*/ false, + (sourceFile, changeTracker) => { + changeTracker.deleteRange(sourceFile, { + pos: text.indexOf("function foo"), + end: text.indexOf("function bar"), + }); + }, + ); } function findVariableStatementContaining(name: string, sourceFile: ts.SourceFile): ts.VariableStatement { return ts.cast(findVariableDeclarationContaining(name, sourceFile).parent.parent, ts.isVariableStatement); @@ -140,21 +170,58 @@ var x = 1; // some comment - 1 var y = 2; // comment 3 var z = 3; // comment 4 `; - runSingleFileTest("deleteNode1", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - deleteNode(changeTracker, sourceFile, findVariableStatementContaining("y", sourceFile)); - }); - runSingleFileTest("deleteNode2", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - deleteNode(changeTracker, sourceFile, findVariableStatementContaining("y", sourceFile), { leadingTriviaOption: ts.textChanges.LeadingTriviaOption.Exclude }); - }); - runSingleFileTest("deleteNode3", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - deleteNode(changeTracker, sourceFile, findVariableStatementContaining("y", sourceFile), { trailingTriviaOption: ts.textChanges.TrailingTriviaOption.Exclude }); - }); - runSingleFileTest("deleteNode4", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - deleteNode(changeTracker, sourceFile, findVariableStatementContaining("y", sourceFile), { leadingTriviaOption: ts.textChanges.LeadingTriviaOption.Exclude, trailingTriviaOption: ts.textChanges.TrailingTriviaOption.Exclude }); - }); - runSingleFileTest("deleteNode5", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - deleteNode(changeTracker, sourceFile, findVariableStatementContaining("x", sourceFile)); - }); + runSingleFileTest( + "deleteNode1", + /*placeOpenBraceOnNewLineForFunctions*/ false, + text, + /*validateNodes*/ false, + (sourceFile, changeTracker) => { + deleteNode(changeTracker, sourceFile, findVariableStatementContaining("y", sourceFile)); + }, + ); + runSingleFileTest( + "deleteNode2", + /*placeOpenBraceOnNewLineForFunctions*/ false, + text, + /*validateNodes*/ false, + (sourceFile, changeTracker) => { + deleteNode(changeTracker, sourceFile, findVariableStatementContaining("y", sourceFile), { + leadingTriviaOption: ts.textChanges.LeadingTriviaOption.Exclude, + }); + }, + ); + runSingleFileTest( + "deleteNode3", + /*placeOpenBraceOnNewLineForFunctions*/ false, + text, + /*validateNodes*/ false, + (sourceFile, changeTracker) => { + deleteNode(changeTracker, sourceFile, findVariableStatementContaining("y", sourceFile), { + trailingTriviaOption: ts.textChanges.TrailingTriviaOption.Exclude, + }); + }, + ); + runSingleFileTest( + "deleteNode4", + /*placeOpenBraceOnNewLineForFunctions*/ false, + text, + /*validateNodes*/ false, + (sourceFile, changeTracker) => { + deleteNode(changeTracker, sourceFile, findVariableStatementContaining("y", sourceFile), { + leadingTriviaOption: ts.textChanges.LeadingTriviaOption.Exclude, + trailingTriviaOption: ts.textChanges.TrailingTriviaOption.Exclude, + }); + }, + ); + runSingleFileTest( + "deleteNode5", + /*placeOpenBraceOnNewLineForFunctions*/ false, + text, + /*validateNodes*/ false, + (sourceFile, changeTracker) => { + deleteNode(changeTracker, sourceFile, findVariableStatementContaining("x", sourceFile)); + }, + ); } { const text = ` @@ -166,21 +233,74 @@ var z = 3; // comment 5 // comment 6 var a = 4; // comment 7 `; - runSingleFileTest("deleteNodeRange1", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - changeTracker.deleteNodeRange(sourceFile, findVariableStatementContaining("y", sourceFile), findVariableStatementContaining("z", sourceFile)); - }); - runSingleFileTest("deleteNodeRange2", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - changeTracker.deleteNodeRange(sourceFile, findVariableStatementContaining("y", sourceFile), findVariableStatementContaining("z", sourceFile), { leadingTriviaOption: ts.textChanges.LeadingTriviaOption.Exclude }); - }); - runSingleFileTest("deleteNodeRange3", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - changeTracker.deleteNodeRange(sourceFile, findVariableStatementContaining("y", sourceFile), findVariableStatementContaining("z", sourceFile), { trailingTriviaOption: ts.textChanges.TrailingTriviaOption.Exclude }); - }); - runSingleFileTest("deleteNodeRange4", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - changeTracker.deleteNodeRange(sourceFile, findVariableStatementContaining("y", sourceFile), findVariableStatementContaining("z", sourceFile), { leadingTriviaOption: ts.textChanges.LeadingTriviaOption.Exclude, trailingTriviaOption: ts.textChanges.TrailingTriviaOption.Exclude }); - }); + runSingleFileTest( + "deleteNodeRange1", + /*placeOpenBraceOnNewLineForFunctions*/ false, + text, + /*validateNodes*/ false, + (sourceFile, changeTracker) => { + changeTracker.deleteNodeRange( + sourceFile, + findVariableStatementContaining("y", sourceFile), + findVariableStatementContaining("z", sourceFile), + ); + }, + ); + runSingleFileTest( + "deleteNodeRange2", + /*placeOpenBraceOnNewLineForFunctions*/ false, + text, + /*validateNodes*/ false, + (sourceFile, changeTracker) => { + changeTracker.deleteNodeRange( + sourceFile, + findVariableStatementContaining("y", sourceFile), + findVariableStatementContaining("z", sourceFile), + { leadingTriviaOption: ts.textChanges.LeadingTriviaOption.Exclude }, + ); + }, + ); + runSingleFileTest( + "deleteNodeRange3", + /*placeOpenBraceOnNewLineForFunctions*/ false, + text, + /*validateNodes*/ false, + (sourceFile, changeTracker) => { + changeTracker.deleteNodeRange( + sourceFile, + findVariableStatementContaining("y", sourceFile), + findVariableStatementContaining("z", sourceFile), + { trailingTriviaOption: ts.textChanges.TrailingTriviaOption.Exclude }, + ); + }, + ); + runSingleFileTest( + "deleteNodeRange4", + /*placeOpenBraceOnNewLineForFunctions*/ false, + text, + /*validateNodes*/ false, + (sourceFile, changeTracker) => { + changeTracker.deleteNodeRange( + sourceFile, + findVariableStatementContaining("y", sourceFile), + findVariableStatementContaining("z", sourceFile), + { + leadingTriviaOption: ts.textChanges.LeadingTriviaOption.Exclude, + trailingTriviaOption: ts.textChanges.TrailingTriviaOption.Exclude, + }, + ); + }, + ); } function createTestVariableDeclaration(name: string) { - return ts.factory.createVariableDeclaration(name, /*exclamationToken*/ undefined, /*type*/ undefined, ts.factory.createObjectLiteralExpression([ts.factory.createPropertyAssignment("p1", ts.factory.createNumericLiteral(1))], /*multiLine*/ true)); + return ts.factory.createVariableDeclaration( + name, + /*exclamationToken*/ undefined, + /*type*/ undefined, + ts.factory.createObjectLiteralExpression([ + ts.factory.createPropertyAssignment("p1", ts.factory.createNumericLiteral(1)), + ], /*multiLine*/ true), + ); } function createTestClass() { return ts.factory.createClassDeclaration( @@ -193,7 +313,10 @@ var a = 4; // comment 7 ts.factory.createHeritageClause( ts.SyntaxKind.ImplementsKeyword, [ - ts.factory.createExpressionWithTypeArguments(ts.factory.createIdentifier("interface1"), /*typeArguments*/ undefined), + ts.factory.createExpressionWithTypeArguments( + ts.factory.createIdentifier("interface1"), + /*typeArguments*/ undefined, + ), ], ), ], @@ -217,17 +340,48 @@ var y = 2; // comment 4 var z = 3; // comment 5 // comment 6 var a = 4; // comment 7`; - runSingleFileTest("replaceRange", /*placeOpenBraceOnNewLineForFunctions*/ true, text, /*validateNodes*/ true, (sourceFile, changeTracker) => { - changeTracker.replaceRange(sourceFile, { pos: text.indexOf("var y"), end: text.indexOf("var a") }, createTestClass(), { suffix: newLineCharacter }); - }); - runSingleFileTest("replaceRangeWithForcedIndentation", /*placeOpenBraceOnNewLineForFunctions*/ true, text, /*validateNodes*/ true, (sourceFile, changeTracker) => { - changeTracker.replaceRange(sourceFile, { pos: text.indexOf("var y"), end: text.indexOf("var a") }, createTestClass(), { suffix: newLineCharacter, indentation: 8, delta: 0 }); - }); + runSingleFileTest( + "replaceRange", + /*placeOpenBraceOnNewLineForFunctions*/ true, + text, + /*validateNodes*/ true, + (sourceFile, changeTracker) => { + changeTracker.replaceRange( + sourceFile, + { pos: text.indexOf("var y"), end: text.indexOf("var a") }, + createTestClass(), + { suffix: newLineCharacter }, + ); + }, + ); + runSingleFileTest( + "replaceRangeWithForcedIndentation", + /*placeOpenBraceOnNewLineForFunctions*/ true, + text, + /*validateNodes*/ true, + (sourceFile, changeTracker) => { + changeTracker.replaceRange( + sourceFile, + { pos: text.indexOf("var y"), end: text.indexOf("var a") }, + createTestClass(), + { suffix: newLineCharacter, indentation: 8, delta: 0 }, + ); + }, + ); - runSingleFileTest("replaceRangeNoLineBreakBefore", /*placeOpenBraceOnNewLineForFunctions*/ true, `const x = 1, y = "2";`, /*validateNodes*/ false, (sourceFile, changeTracker) => { - const newNode = createTestVariableDeclaration("z1"); - changeTracker.replaceRange(sourceFile, { pos: sourceFile.text.indexOf("y"), end: sourceFile.text.indexOf(";") }, newNode); - }); + runSingleFileTest( + "replaceRangeNoLineBreakBefore", + /*placeOpenBraceOnNewLineForFunctions*/ true, + `const x = 1, y = "2";`, + /*validateNodes*/ false, + (sourceFile, changeTracker) => { + const newNode = createTestVariableDeclaration("z1"); + changeTracker.replaceRange(sourceFile, { + pos: sourceFile.text.indexOf("y"), + end: sourceFile.text.indexOf(";"), + }, newNode); + }, + ); } { const text = ` @@ -235,10 +389,16 @@ namespace A { const x = 1, y = "2"; } `; - runSingleFileTest("replaceNode1NoLineBreakBefore", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - const newNode = createTestVariableDeclaration("z1"); - changeTracker.replaceNode(sourceFile, findChild("y", sourceFile), newNode); - }); + runSingleFileTest( + "replaceNode1NoLineBreakBefore", + /*placeOpenBraceOnNewLineForFunctions*/ false, + text, + /*validateNodes*/ false, + (sourceFile, changeTracker) => { + const newNode = createTestVariableDeclaration("z1"); + changeTracker.replaceNode(sourceFile, findChild("y", sourceFile), newNode); + }, + ); } { const text = ` @@ -249,21 +409,86 @@ var y = 2; // comment 4 var z = 3; // comment 5 // comment 6 var a = 4; // comment 7`; - runSingleFileTest("replaceNode1", /*placeOpenBraceOnNewLineForFunctions*/ true, text, /*validateNodes*/ true, (sourceFile, changeTracker) => { - changeTracker.replaceNode(sourceFile, findVariableStatementContaining("y", sourceFile), createTestClass(), { suffix: newLineCharacter }); - }); - runSingleFileTest("replaceNode2", /*placeOpenBraceOnNewLineForFunctions*/ true, text, /*validateNodes*/ true, (sourceFile, changeTracker) => { - changeTracker.replaceNode(sourceFile, findVariableStatementContaining("y", sourceFile), createTestClass(), { leadingTriviaOption: ts.textChanges.LeadingTriviaOption.Exclude, suffix: newLineCharacter, prefix: newLineCharacter }); - }); - runSingleFileTest("replaceNode3", /*placeOpenBraceOnNewLineForFunctions*/ true, text, /*validateNodes*/ true, (sourceFile, changeTracker) => { - changeTracker.replaceNode(sourceFile, findVariableStatementContaining("y", sourceFile), createTestClass(), { trailingTriviaOption: ts.textChanges.TrailingTriviaOption.Exclude, suffix: newLineCharacter }); - }); - runSingleFileTest("replaceNode4", /*placeOpenBraceOnNewLineForFunctions*/ true, text, /*validateNodes*/ true, (sourceFile, changeTracker) => { - changeTracker.replaceNode(sourceFile, findVariableStatementContaining("y", sourceFile), createTestClass(), { leadingTriviaOption: ts.textChanges.LeadingTriviaOption.Exclude, trailingTriviaOption: ts.textChanges.TrailingTriviaOption.Exclude }); - }); - runSingleFileTest("replaceNode5", /*placeOpenBraceOnNewLineForFunctions*/ true, text, /*validateNodes*/ true, (sourceFile, changeTracker) => { - changeTracker.replaceNode(sourceFile, findVariableStatementContaining("x", sourceFile), createTestClass(), { leadingTriviaOption: ts.textChanges.LeadingTriviaOption.Exclude, trailingTriviaOption: ts.textChanges.TrailingTriviaOption.Exclude }); - }); + runSingleFileTest( + "replaceNode1", + /*placeOpenBraceOnNewLineForFunctions*/ true, + text, + /*validateNodes*/ true, + (sourceFile, changeTracker) => { + changeTracker.replaceNode( + sourceFile, + findVariableStatementContaining("y", sourceFile), + createTestClass(), + { suffix: newLineCharacter }, + ); + }, + ); + runSingleFileTest( + "replaceNode2", + /*placeOpenBraceOnNewLineForFunctions*/ true, + text, + /*validateNodes*/ true, + (sourceFile, changeTracker) => { + changeTracker.replaceNode( + sourceFile, + findVariableStatementContaining("y", sourceFile), + createTestClass(), + { + leadingTriviaOption: ts.textChanges.LeadingTriviaOption.Exclude, + suffix: newLineCharacter, + prefix: newLineCharacter, + }, + ); + }, + ); + runSingleFileTest( + "replaceNode3", + /*placeOpenBraceOnNewLineForFunctions*/ true, + text, + /*validateNodes*/ true, + (sourceFile, changeTracker) => { + changeTracker.replaceNode( + sourceFile, + findVariableStatementContaining("y", sourceFile), + createTestClass(), + { trailingTriviaOption: ts.textChanges.TrailingTriviaOption.Exclude, suffix: newLineCharacter }, + ); + }, + ); + runSingleFileTest( + "replaceNode4", + /*placeOpenBraceOnNewLineForFunctions*/ true, + text, + /*validateNodes*/ true, + (sourceFile, changeTracker) => { + changeTracker.replaceNode( + sourceFile, + findVariableStatementContaining("y", sourceFile), + createTestClass(), + { + leadingTriviaOption: ts.textChanges.LeadingTriviaOption.Exclude, + trailingTriviaOption: ts.textChanges.TrailingTriviaOption.Exclude, + }, + ); + }, + ); + runSingleFileTest( + "replaceNode5", + /*placeOpenBraceOnNewLineForFunctions*/ true, + text, + /*validateNodes*/ true, + (sourceFile, changeTracker) => { + changeTracker.replaceNode( + sourceFile, + findVariableStatementContaining("x", sourceFile), + createTestClass(), + { + leadingTriviaOption: ts.textChanges.LeadingTriviaOption.Exclude, + trailingTriviaOption: ts.textChanges.TrailingTriviaOption.Exclude, + }, + ); + }, + ); } { const text = ` @@ -274,18 +499,73 @@ var y = 2; // comment 4 var z = 3; // comment 5 // comment 6 var a = 4; // comment 7`; - runSingleFileTest("replaceNodeRange1", /*placeOpenBraceOnNewLineForFunctions*/ true, text, /*validateNodes*/ true, (sourceFile, changeTracker) => { - changeTracker.replaceNodeRange(sourceFile, findVariableStatementContaining("y", sourceFile), findVariableStatementContaining("z", sourceFile), createTestClass(), { suffix: newLineCharacter }); - }); - runSingleFileTest("replaceNodeRange2", /*placeOpenBraceOnNewLineForFunctions*/ true, text, /*validateNodes*/ true, (sourceFile, changeTracker) => { - changeTracker.replaceNodeRange(sourceFile, findVariableStatementContaining("y", sourceFile), findVariableStatementContaining("z", sourceFile), createTestClass(), { leadingTriviaOption: ts.textChanges.LeadingTriviaOption.Exclude, suffix: newLineCharacter, prefix: newLineCharacter }); - }); - runSingleFileTest("replaceNodeRange3", /*placeOpenBraceOnNewLineForFunctions*/ true, text, /*validateNodes*/ true, (sourceFile, changeTracker) => { - changeTracker.replaceNodeRange(sourceFile, findVariableStatementContaining("y", sourceFile), findVariableStatementContaining("z", sourceFile), createTestClass(), { trailingTriviaOption: ts.textChanges.TrailingTriviaOption.Exclude, suffix: newLineCharacter }); - }); - runSingleFileTest("replaceNodeRange4", /*placeOpenBraceOnNewLineForFunctions*/ true, text, /*validateNodes*/ true, (sourceFile, changeTracker) => { - changeTracker.replaceNodeRange(sourceFile, findVariableStatementContaining("y", sourceFile), findVariableStatementContaining("z", sourceFile), createTestClass(), { leadingTriviaOption: ts.textChanges.LeadingTriviaOption.Exclude, trailingTriviaOption: ts.textChanges.TrailingTriviaOption.Exclude }); - }); + runSingleFileTest( + "replaceNodeRange1", + /*placeOpenBraceOnNewLineForFunctions*/ true, + text, + /*validateNodes*/ true, + (sourceFile, changeTracker) => { + changeTracker.replaceNodeRange( + sourceFile, + findVariableStatementContaining("y", sourceFile), + findVariableStatementContaining("z", sourceFile), + createTestClass(), + { suffix: newLineCharacter }, + ); + }, + ); + runSingleFileTest( + "replaceNodeRange2", + /*placeOpenBraceOnNewLineForFunctions*/ true, + text, + /*validateNodes*/ true, + (sourceFile, changeTracker) => { + changeTracker.replaceNodeRange( + sourceFile, + findVariableStatementContaining("y", sourceFile), + findVariableStatementContaining("z", sourceFile), + createTestClass(), + { + leadingTriviaOption: ts.textChanges.LeadingTriviaOption.Exclude, + suffix: newLineCharacter, + prefix: newLineCharacter, + }, + ); + }, + ); + runSingleFileTest( + "replaceNodeRange3", + /*placeOpenBraceOnNewLineForFunctions*/ true, + text, + /*validateNodes*/ true, + (sourceFile, changeTracker) => { + changeTracker.replaceNodeRange( + sourceFile, + findVariableStatementContaining("y", sourceFile), + findVariableStatementContaining("z", sourceFile), + createTestClass(), + { trailingTriviaOption: ts.textChanges.TrailingTriviaOption.Exclude, suffix: newLineCharacter }, + ); + }, + ); + runSingleFileTest( + "replaceNodeRange4", + /*placeOpenBraceOnNewLineForFunctions*/ true, + text, + /*validateNodes*/ true, + (sourceFile, changeTracker) => { + changeTracker.replaceNodeRange( + sourceFile, + findVariableStatementContaining("y", sourceFile), + findVariableStatementContaining("z", sourceFile), + createTestClass(), + { + leadingTriviaOption: ts.textChanges.LeadingTriviaOption.Exclude, + trailingTriviaOption: ts.textChanges.TrailingTriviaOption.Exclude, + }, + ); + }, + ); } { const text = ` @@ -296,12 +576,32 @@ var y; // comment 4 var z = 3; // comment 5 // comment 6 var a = 4; // comment 7`; - runSingleFileTest("insertNodeBefore3", /*placeOpenBraceOnNewLineForFunctions*/ true, text, /*validateNodes*/ true, (sourceFile, changeTracker) => { - changeTracker.insertNodeBefore(sourceFile, findVariableStatementContaining("y", sourceFile), createTestClass()); - }); - runSingleFileTest("insertNodeAfterVariableDeclaration", /*placeOpenBraceOnNewLineForFunctions*/ true, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - changeTracker.insertNodeAfter(sourceFile, findVariableDeclarationContaining("y", sourceFile), createTestVariableDeclaration("z1")); - }); + runSingleFileTest( + "insertNodeBefore3", + /*placeOpenBraceOnNewLineForFunctions*/ true, + text, + /*validateNodes*/ true, + (sourceFile, changeTracker) => { + changeTracker.insertNodeBefore( + sourceFile, + findVariableStatementContaining("y", sourceFile), + createTestClass(), + ); + }, + ); + runSingleFileTest( + "insertNodeAfterVariableDeclaration", + /*placeOpenBraceOnNewLineForFunctions*/ true, + text, + /*validateNodes*/ false, + (sourceFile, changeTracker) => { + changeTracker.insertNodeAfter( + sourceFile, + findVariableDeclarationContaining("y", sourceFile), + createTestVariableDeclaration("z1"), + ); + }, + ); } { const text = ` @@ -314,23 +614,58 @@ namespace M { // comment 6 var a = 4; // comment 7 }`; - runSingleFileTest("insertNodeBefore1", /*placeOpenBraceOnNewLineForFunctions*/ true, text, /*validateNodes*/ true, (sourceFile, changeTracker) => { - changeTracker.insertNodeBefore(sourceFile, findVariableStatementContaining("y", sourceFile), createTestClass()); - }); - runSingleFileTest("insertNodeBefore2", /*placeOpenBraceOnNewLineForFunctions*/ true, text, /*validateNodes*/ true, (sourceFile, changeTracker) => { - changeTracker.insertNodeBefore(sourceFile, findChild("M", sourceFile), createTestClass()); - }); - runSingleFileTest("insertNodeAfter1", /*placeOpenBraceOnNewLineForFunctions*/ true, text, /*validateNodes*/ true, (sourceFile, changeTracker) => { - changeTracker.insertNodeAfter(sourceFile, findVariableStatementContaining("y", sourceFile), createTestClass()); - }); - runSingleFileTest("insertNodeAfter2", /*placeOpenBraceOnNewLineForFunctions*/ true, text, /*validateNodes*/ true, (sourceFile, changeTracker) => { - changeTracker.insertNodeAfter(sourceFile, findChild("M", sourceFile), createTestClass()); - }); + runSingleFileTest( + "insertNodeBefore1", + /*placeOpenBraceOnNewLineForFunctions*/ true, + text, + /*validateNodes*/ true, + (sourceFile, changeTracker) => { + changeTracker.insertNodeBefore( + sourceFile, + findVariableStatementContaining("y", sourceFile), + createTestClass(), + ); + }, + ); + runSingleFileTest( + "insertNodeBefore2", + /*placeOpenBraceOnNewLineForFunctions*/ true, + text, + /*validateNodes*/ true, + (sourceFile, changeTracker) => { + changeTracker.insertNodeBefore(sourceFile, findChild("M", sourceFile), createTestClass()); + }, + ); + runSingleFileTest( + "insertNodeAfter1", + /*placeOpenBraceOnNewLineForFunctions*/ true, + text, + /*validateNodes*/ true, + (sourceFile, changeTracker) => { + changeTracker.insertNodeAfter( + sourceFile, + findVariableStatementContaining("y", sourceFile), + createTestClass(), + ); + }, + ); + runSingleFileTest( + "insertNodeAfter2", + /*placeOpenBraceOnNewLineForFunctions*/ true, + text, + /*validateNodes*/ true, + (sourceFile, changeTracker) => { + changeTracker.insertNodeAfter(sourceFile, findChild("M", sourceFile), createTestClass()); + }, + ); } function findConstructor(sourceFile: ts.SourceFile): ts.ConstructorDeclaration { const classDecl = sourceFile.statements[0] as ts.ClassDeclaration; - return ts.find(classDecl.members, (m): m is ts.ConstructorDeclaration => ts.isConstructorDeclaration(m) && !!m.body)!; + return ts.find( + classDecl.members, + (m): m is ts.ConstructorDeclaration => ts.isConstructorDeclaration(m) && !!m.body, + )!; } function createTestSuperCall() { const superCall = ts.factory.createCallExpression( @@ -348,9 +683,19 @@ class A { } } `; - runSingleFileTest("insertNodeAtConstructorStart", /*placeOpenBraceOnNewLineForFunctions*/ false, text1, /*validateNodes*/ false, (sourceFile, changeTracker) => { - changeTracker.insertNodeAtConstructorStart(sourceFile, findConstructor(sourceFile), createTestSuperCall()); - }); + runSingleFileTest( + "insertNodeAtConstructorStart", + /*placeOpenBraceOnNewLineForFunctions*/ false, + text1, + /*validateNodes*/ false, + (sourceFile, changeTracker) => { + changeTracker.insertNodeAtConstructorStart( + sourceFile, + findConstructor(sourceFile), + createTestSuperCall(), + ); + }, + ); const text2 = ` class A { constructor() { @@ -358,9 +703,19 @@ class A { } } `; - runSingleFileTest("insertNodeAfter4", /*placeOpenBraceOnNewLineForFunctions*/ false, text2, /*validateNodes*/ false, (sourceFile, changeTracker) => { - changeTracker.insertNodeAfter(sourceFile, findVariableStatementContaining("x", sourceFile), createTestSuperCall()); - }); + runSingleFileTest( + "insertNodeAfter4", + /*placeOpenBraceOnNewLineForFunctions*/ false, + text2, + /*validateNodes*/ false, + (sourceFile, changeTracker) => { + changeTracker.insertNodeAfter( + sourceFile, + findVariableStatementContaining("x", sourceFile), + createTestSuperCall(), + ); + }, + ); const text3 = ` class A { constructor() { @@ -368,33 +723,79 @@ class A { } } `; - runSingleFileTest("insertNodeAtConstructorStart-block with newline", /*placeOpenBraceOnNewLineForFunctions*/ false, text3, /*validateNodes*/ false, (sourceFile, changeTracker) => { - changeTracker.insertNodeAtConstructorStart(sourceFile, findConstructor(sourceFile), createTestSuperCall()); - }); + runSingleFileTest( + "insertNodeAtConstructorStart-block with newline", + /*placeOpenBraceOnNewLineForFunctions*/ false, + text3, + /*validateNodes*/ false, + (sourceFile, changeTracker) => { + changeTracker.insertNodeAtConstructorStart( + sourceFile, + findConstructor(sourceFile), + createTestSuperCall(), + ); + }, + ); } { const text = `var a = 1, b = 2, c = 3;`; - runSingleFileTest("deleteNodeInList1", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - changeTracker.delete(sourceFile, findChild("a", sourceFile)); - }); - runSingleFileTest("deleteNodeInList2", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - changeTracker.delete(sourceFile, findChild("b", sourceFile)); - }); - runSingleFileTest("deleteNodeInList3", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - changeTracker.delete(sourceFile, findChild("c", sourceFile)); - }); + runSingleFileTest( + "deleteNodeInList1", + /*placeOpenBraceOnNewLineForFunctions*/ false, + text, + /*validateNodes*/ false, + (sourceFile, changeTracker) => { + changeTracker.delete(sourceFile, findChild("a", sourceFile)); + }, + ); + runSingleFileTest( + "deleteNodeInList2", + /*placeOpenBraceOnNewLineForFunctions*/ false, + text, + /*validateNodes*/ false, + (sourceFile, changeTracker) => { + changeTracker.delete(sourceFile, findChild("b", sourceFile)); + }, + ); + runSingleFileTest( + "deleteNodeInList3", + /*placeOpenBraceOnNewLineForFunctions*/ false, + text, + /*validateNodes*/ false, + (sourceFile, changeTracker) => { + changeTracker.delete(sourceFile, findChild("c", sourceFile)); + }, + ); } { const text = `var a = 1,b = 2,c = 3;`; - runSingleFileTest("deleteNodeInList1_1", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - changeTracker.delete(sourceFile, findChild("a", sourceFile)); - }); - runSingleFileTest("deleteNodeInList2_1", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - changeTracker.delete(sourceFile, findChild("b", sourceFile)); - }); - runSingleFileTest("deleteNodeInList3_1", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - changeTracker.delete(sourceFile, findChild("c", sourceFile)); - }); + runSingleFileTest( + "deleteNodeInList1_1", + /*placeOpenBraceOnNewLineForFunctions*/ false, + text, + /*validateNodes*/ false, + (sourceFile, changeTracker) => { + changeTracker.delete(sourceFile, findChild("a", sourceFile)); + }, + ); + runSingleFileTest( + "deleteNodeInList2_1", + /*placeOpenBraceOnNewLineForFunctions*/ false, + text, + /*validateNodes*/ false, + (sourceFile, changeTracker) => { + changeTracker.delete(sourceFile, findChild("b", sourceFile)); + }, + ); + runSingleFileTest( + "deleteNodeInList3_1", + /*placeOpenBraceOnNewLineForFunctions*/ false, + text, + /*validateNodes*/ false, + (sourceFile, changeTracker) => { + changeTracker.delete(sourceFile, findChild("c", sourceFile)); + }, + ); } { const text = ` @@ -403,15 +804,33 @@ namespace M { b = 2, c = 3; }`; - runSingleFileTest("deleteNodeInList4", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - changeTracker.delete(sourceFile, findChild("a", sourceFile)); - }); - runSingleFileTest("deleteNodeInList5", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - changeTracker.delete(sourceFile, findChild("b", sourceFile)); - }); - runSingleFileTest("deleteNodeInList6", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - changeTracker.delete(sourceFile, findChild("c", sourceFile)); - }); + runSingleFileTest( + "deleteNodeInList4", + /*placeOpenBraceOnNewLineForFunctions*/ false, + text, + /*validateNodes*/ false, + (sourceFile, changeTracker) => { + changeTracker.delete(sourceFile, findChild("a", sourceFile)); + }, + ); + runSingleFileTest( + "deleteNodeInList5", + /*placeOpenBraceOnNewLineForFunctions*/ false, + text, + /*validateNodes*/ false, + (sourceFile, changeTracker) => { + changeTracker.delete(sourceFile, findChild("b", sourceFile)); + }, + ); + runSingleFileTest( + "deleteNodeInList6", + /*placeOpenBraceOnNewLineForFunctions*/ false, + text, + /*validateNodes*/ false, + (sourceFile, changeTracker) => { + changeTracker.delete(sourceFile, findChild("c", sourceFile)); + }, + ); } { const text = ` @@ -422,45 +841,99 @@ namespace M { // comment 4 c = 3; // comment 5 }`; - runSingleFileTest("deleteNodeInList4_1", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - changeTracker.delete(sourceFile, findChild("a", sourceFile)); - }); - runSingleFileTest("deleteNodeInList5_1", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - changeTracker.delete(sourceFile, findChild("b", sourceFile)); - }); - runSingleFileTest("deleteNodeInList6_1", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - changeTracker.delete(sourceFile, findChild("c", sourceFile)); - }); + runSingleFileTest( + "deleteNodeInList4_1", + /*placeOpenBraceOnNewLineForFunctions*/ false, + text, + /*validateNodes*/ false, + (sourceFile, changeTracker) => { + changeTracker.delete(sourceFile, findChild("a", sourceFile)); + }, + ); + runSingleFileTest( + "deleteNodeInList5_1", + /*placeOpenBraceOnNewLineForFunctions*/ false, + text, + /*validateNodes*/ false, + (sourceFile, changeTracker) => { + changeTracker.delete(sourceFile, findChild("b", sourceFile)); + }, + ); + runSingleFileTest( + "deleteNodeInList6_1", + /*placeOpenBraceOnNewLineForFunctions*/ false, + text, + /*validateNodes*/ false, + (sourceFile, changeTracker) => { + changeTracker.delete(sourceFile, findChild("c", sourceFile)); + }, + ); } { const text = ` function foo(a: number, b: string, c = true) { return 1; }`; - runSingleFileTest("deleteNodeInList7", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - changeTracker.delete(sourceFile, findChild("a", sourceFile)); - }); - runSingleFileTest("deleteNodeInList8", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - changeTracker.delete(sourceFile, findChild("b", sourceFile)); - }); - runSingleFileTest("deleteNodeInList9", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - changeTracker.delete(sourceFile, findChild("c", sourceFile)); - }); + runSingleFileTest( + "deleteNodeInList7", + /*placeOpenBraceOnNewLineForFunctions*/ false, + text, + /*validateNodes*/ false, + (sourceFile, changeTracker) => { + changeTracker.delete(sourceFile, findChild("a", sourceFile)); + }, + ); + runSingleFileTest( + "deleteNodeInList8", + /*placeOpenBraceOnNewLineForFunctions*/ false, + text, + /*validateNodes*/ false, + (sourceFile, changeTracker) => { + changeTracker.delete(sourceFile, findChild("b", sourceFile)); + }, + ); + runSingleFileTest( + "deleteNodeInList9", + /*placeOpenBraceOnNewLineForFunctions*/ false, + text, + /*validateNodes*/ false, + (sourceFile, changeTracker) => { + changeTracker.delete(sourceFile, findChild("c", sourceFile)); + }, + ); } { const text = ` function foo(a: number,b: string,c = true) { return 1; }`; - runSingleFileTest("deleteNodeInList10", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - changeTracker.delete(sourceFile, findChild("a", sourceFile)); - }); - runSingleFileTest("deleteNodeInList11", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - changeTracker.delete(sourceFile, findChild("b", sourceFile)); - }); - runSingleFileTest("deleteNodeInList12", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - changeTracker.delete(sourceFile, findChild("c", sourceFile)); - }); + runSingleFileTest( + "deleteNodeInList10", + /*placeOpenBraceOnNewLineForFunctions*/ false, + text, + /*validateNodes*/ false, + (sourceFile, changeTracker) => { + changeTracker.delete(sourceFile, findChild("a", sourceFile)); + }, + ); + runSingleFileTest( + "deleteNodeInList11", + /*placeOpenBraceOnNewLineForFunctions*/ false, + text, + /*validateNodes*/ false, + (sourceFile, changeTracker) => { + changeTracker.delete(sourceFile, findChild("b", sourceFile)); + }, + ); + runSingleFileTest( + "deleteNodeInList12", + /*placeOpenBraceOnNewLineForFunctions*/ false, + text, + /*validateNodes*/ false, + (sourceFile, changeTracker) => { + changeTracker.delete(sourceFile, findChild("c", sourceFile)); + }, + ); } { const text = ` @@ -470,100 +943,309 @@ function foo( c = true) { return 1; }`; - runSingleFileTest("deleteNodeInList13", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - changeTracker.delete(sourceFile, findChild("a", sourceFile)); - }); - runSingleFileTest("deleteNodeInList14", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - changeTracker.delete(sourceFile, findChild("b", sourceFile)); - }); - runSingleFileTest("deleteNodeInList15", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - changeTracker.delete(sourceFile, findChild("c", sourceFile)); - }); + runSingleFileTest( + "deleteNodeInList13", + /*placeOpenBraceOnNewLineForFunctions*/ false, + text, + /*validateNodes*/ false, + (sourceFile, changeTracker) => { + changeTracker.delete(sourceFile, findChild("a", sourceFile)); + }, + ); + runSingleFileTest( + "deleteNodeInList14", + /*placeOpenBraceOnNewLineForFunctions*/ false, + text, + /*validateNodes*/ false, + (sourceFile, changeTracker) => { + changeTracker.delete(sourceFile, findChild("b", sourceFile)); + }, + ); + runSingleFileTest( + "deleteNodeInList15", + /*placeOpenBraceOnNewLineForFunctions*/ false, + text, + /*validateNodes*/ false, + (sourceFile, changeTracker) => { + changeTracker.delete(sourceFile, findChild("c", sourceFile)); + }, + ); } { const text = ` const x = 1, y = 2;`; - runSingleFileTest("insertNodeInListAfter1", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), ts.factory.createVariableDeclaration("z", /*exclamationToken*/ undefined, /*type*/ undefined, ts.factory.createNumericLiteral(1))); - }); - runSingleFileTest("insertNodeInListAfter2", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - changeTracker.insertNodeInListAfter(sourceFile, findChild("y", sourceFile), ts.factory.createVariableDeclaration("z", /*exclamationToken*/ undefined, /*type*/ undefined, ts.factory.createNumericLiteral(1))); - }); + runSingleFileTest( + "insertNodeInListAfter1", + /*placeOpenBraceOnNewLineForFunctions*/ false, + text, + /*validateNodes*/ false, + (sourceFile, changeTracker) => { + changeTracker.insertNodeInListAfter( + sourceFile, + findChild("x", sourceFile), + ts.factory.createVariableDeclaration( + "z", + /*exclamationToken*/ undefined, + /*type*/ undefined, + ts.factory.createNumericLiteral(1), + ), + ); + }, + ); + runSingleFileTest( + "insertNodeInListAfter2", + /*placeOpenBraceOnNewLineForFunctions*/ false, + text, + /*validateNodes*/ false, + (sourceFile, changeTracker) => { + changeTracker.insertNodeInListAfter( + sourceFile, + findChild("y", sourceFile), + ts.factory.createVariableDeclaration( + "z", + /*exclamationToken*/ undefined, + /*type*/ undefined, + ts.factory.createNumericLiteral(1), + ), + ); + }, + ); } { const text = ` const /*x*/ x = 1, /*y*/ y = 2;`; - runSingleFileTest("insertNodeInListAfter3", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), ts.factory.createVariableDeclaration("z", /*exclamationToken*/ undefined, /*type*/ undefined, ts.factory.createNumericLiteral(1))); - }); - runSingleFileTest("insertNodeInListAfter4", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - changeTracker.insertNodeInListAfter(sourceFile, findChild("y", sourceFile), ts.factory.createVariableDeclaration("z", /*exclamationToken*/ undefined, /*type*/ undefined, ts.factory.createNumericLiteral(1))); - }); + runSingleFileTest( + "insertNodeInListAfter3", + /*placeOpenBraceOnNewLineForFunctions*/ false, + text, + /*validateNodes*/ false, + (sourceFile, changeTracker) => { + changeTracker.insertNodeInListAfter( + sourceFile, + findChild("x", sourceFile), + ts.factory.createVariableDeclaration( + "z", + /*exclamationToken*/ undefined, + /*type*/ undefined, + ts.factory.createNumericLiteral(1), + ), + ); + }, + ); + runSingleFileTest( + "insertNodeInListAfter4", + /*placeOpenBraceOnNewLineForFunctions*/ false, + text, + /*validateNodes*/ false, + (sourceFile, changeTracker) => { + changeTracker.insertNodeInListAfter( + sourceFile, + findChild("y", sourceFile), + ts.factory.createVariableDeclaration( + "z", + /*exclamationToken*/ undefined, + /*type*/ undefined, + ts.factory.createNumericLiteral(1), + ), + ); + }, + ); } { const text = ` const x = 1;`; - runSingleFileTest("insertNodeInListAfter5", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), ts.factory.createVariableDeclaration("z", /*exclamationToken*/ undefined, /*type*/ undefined, ts.factory.createNumericLiteral(1))); - }); + runSingleFileTest( + "insertNodeInListAfter5", + /*placeOpenBraceOnNewLineForFunctions*/ false, + text, + /*validateNodes*/ false, + (sourceFile, changeTracker) => { + changeTracker.insertNodeInListAfter( + sourceFile, + findChild("x", sourceFile), + ts.factory.createVariableDeclaration( + "z", + /*exclamationToken*/ undefined, + /*type*/ undefined, + ts.factory.createNumericLiteral(1), + ), + ); + }, + ); } { const text = ` const x = 1, y = 2;`; - runSingleFileTest("insertNodeInListAfter6", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), ts.factory.createVariableDeclaration("z", /*exclamationToken*/ undefined, /*type*/ undefined, ts.factory.createNumericLiteral(1))); - }); - runSingleFileTest("insertNodeInListAfter7", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - changeTracker.insertNodeInListAfter(sourceFile, findChild("y", sourceFile), ts.factory.createVariableDeclaration("z", /*exclamationToken*/ undefined, /*type*/ undefined, ts.factory.createNumericLiteral(1))); - }); + runSingleFileTest( + "insertNodeInListAfter6", + /*placeOpenBraceOnNewLineForFunctions*/ false, + text, + /*validateNodes*/ false, + (sourceFile, changeTracker) => { + changeTracker.insertNodeInListAfter( + sourceFile, + findChild("x", sourceFile), + ts.factory.createVariableDeclaration( + "z", + /*exclamationToken*/ undefined, + /*type*/ undefined, + ts.factory.createNumericLiteral(1), + ), + ); + }, + ); + runSingleFileTest( + "insertNodeInListAfter7", + /*placeOpenBraceOnNewLineForFunctions*/ false, + text, + /*validateNodes*/ false, + (sourceFile, changeTracker) => { + changeTracker.insertNodeInListAfter( + sourceFile, + findChild("y", sourceFile), + ts.factory.createVariableDeclaration( + "z", + /*exclamationToken*/ undefined, + /*type*/ undefined, + ts.factory.createNumericLiteral(1), + ), + ); + }, + ); } { const text = ` const /*x*/ x = 1, /*y*/ y = 2;`; - runSingleFileTest("insertNodeInListAfter8", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), ts.factory.createVariableDeclaration("z", /*exclamationToken*/ undefined, /*type*/ undefined, ts.factory.createNumericLiteral(1))); - }); - runSingleFileTest("insertNodeInListAfter9", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - changeTracker.insertNodeInListAfter(sourceFile, findChild("y", sourceFile), ts.factory.createVariableDeclaration("z", /*exclamationToken*/ undefined, /*type*/ undefined, ts.factory.createNumericLiteral(1))); - }); + runSingleFileTest( + "insertNodeInListAfter8", + /*placeOpenBraceOnNewLineForFunctions*/ false, + text, + /*validateNodes*/ false, + (sourceFile, changeTracker) => { + changeTracker.insertNodeInListAfter( + sourceFile, + findChild("x", sourceFile), + ts.factory.createVariableDeclaration( + "z", + /*exclamationToken*/ undefined, + /*type*/ undefined, + ts.factory.createNumericLiteral(1), + ), + ); + }, + ); + runSingleFileTest( + "insertNodeInListAfter9", + /*placeOpenBraceOnNewLineForFunctions*/ false, + text, + /*validateNodes*/ false, + (sourceFile, changeTracker) => { + changeTracker.insertNodeInListAfter( + sourceFile, + findChild("y", sourceFile), + ts.factory.createVariableDeclaration( + "z", + /*exclamationToken*/ undefined, + /*type*/ undefined, + ts.factory.createNumericLiteral(1), + ), + ); + }, + ); } { const text = ` import { x } from "bar"`; - runSingleFileTest("insertNodeInListAfter10", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), ts.factory.createImportSpecifier(/*isTypeOnly*/ false, ts.factory.createIdentifier("b"), ts.factory.createIdentifier("a"))); - }); + runSingleFileTest( + "insertNodeInListAfter10", + /*placeOpenBraceOnNewLineForFunctions*/ false, + text, + /*validateNodes*/ false, + (sourceFile, changeTracker) => { + changeTracker.insertNodeInListAfter( + sourceFile, + findChild("x", sourceFile), + ts.factory.createImportSpecifier( + /*isTypeOnly*/ false, + ts.factory.createIdentifier("b"), + ts.factory.createIdentifier("a"), + ), + ); + }, + ); } { const text = ` import { x // this is x } from "bar"`; - runSingleFileTest("insertNodeInListAfter11", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), ts.factory.createImportSpecifier(/*isTypeOnly*/ false, ts.factory.createIdentifier("b"), ts.factory.createIdentifier("a"))); - }); + runSingleFileTest( + "insertNodeInListAfter11", + /*placeOpenBraceOnNewLineForFunctions*/ false, + text, + /*validateNodes*/ false, + (sourceFile, changeTracker) => { + changeTracker.insertNodeInListAfter( + sourceFile, + findChild("x", sourceFile), + ts.factory.createImportSpecifier( + /*isTypeOnly*/ false, + ts.factory.createIdentifier("b"), + ts.factory.createIdentifier("a"), + ), + ); + }, + ); } { const text = ` import { x } from "bar"`; - runSingleFileTest("insertNodeInListAfter12", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), ts.factory.createImportSpecifier(/*isTypeOnly*/ false, /*propertyName*/ undefined, ts.factory.createIdentifier("a"))); - }); + runSingleFileTest( + "insertNodeInListAfter12", + /*placeOpenBraceOnNewLineForFunctions*/ false, + text, + /*validateNodes*/ false, + (sourceFile, changeTracker) => { + changeTracker.insertNodeInListAfter( + sourceFile, + findChild("x", sourceFile), + ts.factory.createImportSpecifier( + /*isTypeOnly*/ false, + /*propertyName*/ undefined, + ts.factory.createIdentifier("a"), + ), + ); + }, + ); } { const text = ` import { x // this is x } from "bar"`; - runSingleFileTest("insertNodeInListAfter13", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), ts.factory.createImportSpecifier(/*isTypeOnly*/ false, /*propertyName*/ undefined, ts.factory.createIdentifier("a"))); - }); + runSingleFileTest( + "insertNodeInListAfter13", + /*placeOpenBraceOnNewLineForFunctions*/ false, + text, + /*validateNodes*/ false, + (sourceFile, changeTracker) => { + changeTracker.insertNodeInListAfter( + sourceFile, + findChild("x", sourceFile), + ts.factory.createImportSpecifier( + /*isTypeOnly*/ false, + /*propertyName*/ undefined, + ts.factory.createIdentifier("a"), + ), + ); + }, + ); } { const text = ` @@ -571,9 +1253,23 @@ import { x0, x } from "bar"`; - runSingleFileTest("insertNodeInListAfter14", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), ts.factory.createImportSpecifier(/*isTypeOnly*/ false, ts.factory.createIdentifier("b"), ts.factory.createIdentifier("a"))); - }); + runSingleFileTest( + "insertNodeInListAfter14", + /*placeOpenBraceOnNewLineForFunctions*/ false, + text, + /*validateNodes*/ false, + (sourceFile, changeTracker) => { + changeTracker.insertNodeInListAfter( + sourceFile, + findChild("x", sourceFile), + ts.factory.createImportSpecifier( + /*isTypeOnly*/ false, + ts.factory.createIdentifier("b"), + ts.factory.createIdentifier("a"), + ), + ); + }, + ); } { const text = ` @@ -581,9 +1277,23 @@ import { x0, x // this is x } from "bar"`; - runSingleFileTest("insertNodeInListAfter15", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), ts.factory.createImportSpecifier(/*isTypeOnly*/ false, ts.factory.createIdentifier("b"), ts.factory.createIdentifier("a"))); - }); + runSingleFileTest( + "insertNodeInListAfter15", + /*placeOpenBraceOnNewLineForFunctions*/ false, + text, + /*validateNodes*/ false, + (sourceFile, changeTracker) => { + changeTracker.insertNodeInListAfter( + sourceFile, + findChild("x", sourceFile), + ts.factory.createImportSpecifier( + /*isTypeOnly*/ false, + ts.factory.createIdentifier("b"), + ts.factory.createIdentifier("a"), + ), + ); + }, + ); } { const text = ` @@ -591,9 +1301,23 @@ import { x0, x } from "bar"`; - runSingleFileTest("insertNodeInListAfter16", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), ts.factory.createImportSpecifier(/*isTypeOnly*/ false, /*propertyName*/ undefined, ts.factory.createIdentifier("a"))); - }); + runSingleFileTest( + "insertNodeInListAfter16", + /*placeOpenBraceOnNewLineForFunctions*/ false, + text, + /*validateNodes*/ false, + (sourceFile, changeTracker) => { + changeTracker.insertNodeInListAfter( + sourceFile, + findChild("x", sourceFile), + ts.factory.createImportSpecifier( + /*isTypeOnly*/ false, + /*propertyName*/ undefined, + ts.factory.createIdentifier("a"), + ), + ); + }, + ); } { const text = ` @@ -601,26 +1325,68 @@ import { x0, x // this is x } from "bar"`; - runSingleFileTest("insertNodeInListAfter17", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), ts.factory.createImportSpecifier(/*isTypeOnly*/ false, /*propertyName*/ undefined, ts.factory.createIdentifier("a"))); - }); + runSingleFileTest( + "insertNodeInListAfter17", + /*placeOpenBraceOnNewLineForFunctions*/ false, + text, + /*validateNodes*/ false, + (sourceFile, changeTracker) => { + changeTracker.insertNodeInListAfter( + sourceFile, + findChild("x", sourceFile), + ts.factory.createImportSpecifier( + /*isTypeOnly*/ false, + /*propertyName*/ undefined, + ts.factory.createIdentifier("a"), + ), + ); + }, + ); } { const text = ` import { x0, x } from "bar"`; - runSingleFileTest("insertNodeInListAfter18", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), ts.factory.createImportSpecifier(/*isTypeOnly*/ false, /*propertyName*/ undefined, ts.factory.createIdentifier("a"))); - }); + runSingleFileTest( + "insertNodeInListAfter18", + /*placeOpenBraceOnNewLineForFunctions*/ false, + text, + /*validateNodes*/ false, + (sourceFile, changeTracker) => { + changeTracker.insertNodeInListAfter( + sourceFile, + findChild("x", sourceFile), + ts.factory.createImportSpecifier( + /*isTypeOnly*/ false, + /*propertyName*/ undefined, + ts.factory.createIdentifier("a"), + ), + ); + }, + ); } { const runTest = (name: string, text: string) => - runSingleFileTest(name, /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - for (const specifier of ["x3", "x4", "x5"]) { - changeTracker.insertNodeInListAfter(sourceFile, findChild("x2", sourceFile), ts.factory.createImportSpecifier(/*isTypeOnly*/ false, /*propertyName*/ undefined, ts.factory.createIdentifier(specifier))); - } - }); + runSingleFileTest( + name, + /*placeOpenBraceOnNewLineForFunctions*/ false, + text, + /*validateNodes*/ false, + (sourceFile, changeTracker) => { + for (const specifier of ["x3", "x4", "x5"]) { + changeTracker.insertNodeInListAfter( + sourceFile, + findChild("x2", sourceFile), + ts.factory.createImportSpecifier( + /*isTypeOnly*/ false, + /*propertyName*/ undefined, + ts.factory.createIdentifier(specifier), + ), + ); + } + }, + ); const crlfText = 'import {\r\nx1,\r\nx2\r\n} from "bar";'; runTest("insertNodeInListAfter19", crlfText); @@ -633,18 +1399,30 @@ import { class A { x; }`; - runSingleFileTest("insertNodeAfterMultipleNodes", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - const newNodes = []; - for (let i = 0; i < 11 /*error doesn't occur with fewer nodes*/; ++i) { - newNodes.push( - ts.factory.createPropertyDeclaration(/*modifiers*/ undefined, i + "", /*questionOrExclamationToken*/ undefined, /*type*/ undefined, /*initializer*/ undefined), - ); - } - const insertAfter = findChild("x", sourceFile); - for (const newNode of newNodes) { - changeTracker.insertNodeAfter(sourceFile, insertAfter, newNode); - } - }); + runSingleFileTest( + "insertNodeAfterMultipleNodes", + /*placeOpenBraceOnNewLineForFunctions*/ false, + text, + /*validateNodes*/ false, + (sourceFile, changeTracker) => { + const newNodes = []; + for (let i = 0; i < 11 /*error doesn't occur with fewer nodes*/; ++i) { + newNodes.push( + ts.factory.createPropertyDeclaration( + /*modifiers*/ undefined, + i + "", + /*questionOrExclamationToken*/ undefined, + /*type*/ undefined, + /*initializer*/ undefined, + ), + ); + } + const insertAfter = findChild("x", sourceFile); + for (const newNode of newNodes) { + changeTracker.insertNodeAfter(sourceFile, insertAfter, newNode); + } + }, + ); } { const text = ` @@ -652,9 +1430,25 @@ class A { x } `; - runSingleFileTest("insertNodeAfterInClass1", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - changeTracker.insertNodeAfter(sourceFile, findChild("x", sourceFile), ts.factory.createPropertyDeclaration(/*modifiers*/ undefined, "a", /*questionOrExclamationToken*/ undefined, ts.factory.createKeywordTypeNode(ts.SyntaxKind.BooleanKeyword), /*initializer*/ undefined)); - }); + runSingleFileTest( + "insertNodeAfterInClass1", + /*placeOpenBraceOnNewLineForFunctions*/ false, + text, + /*validateNodes*/ false, + (sourceFile, changeTracker) => { + changeTracker.insertNodeAfter( + sourceFile, + findChild("x", sourceFile), + ts.factory.createPropertyDeclaration( + /*modifiers*/ undefined, + "a", + /*questionOrExclamationToken*/ undefined, + ts.factory.createKeywordTypeNode(ts.SyntaxKind.BooleanKeyword), + /*initializer*/ undefined, + ), + ); + }, + ); } { const text = ` @@ -662,9 +1456,25 @@ class A { x; } `; - runSingleFileTest("insertNodeAfterInClass2", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - changeTracker.insertNodeAfter(sourceFile, findChild("x", sourceFile), ts.factory.createPropertyDeclaration(/*modifiers*/ undefined, "a", /*questionOrExclamationToken*/ undefined, ts.factory.createKeywordTypeNode(ts.SyntaxKind.BooleanKeyword), /*initializer*/ undefined)); - }); + runSingleFileTest( + "insertNodeAfterInClass2", + /*placeOpenBraceOnNewLineForFunctions*/ false, + text, + /*validateNodes*/ false, + (sourceFile, changeTracker) => { + changeTracker.insertNodeAfter( + sourceFile, + findChild("x", sourceFile), + ts.factory.createPropertyDeclaration( + /*modifiers*/ undefined, + "a", + /*questionOrExclamationToken*/ undefined, + ts.factory.createKeywordTypeNode(ts.SyntaxKind.BooleanKeyword), + /*initializer*/ undefined, + ), + ); + }, + ); } { const text = ` @@ -673,9 +1483,15 @@ class A { y = 1; } `; - runSingleFileTest("deleteNodeAfterInClass1", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - deleteNode(changeTracker, sourceFile, findChild("x", sourceFile)); - }); + runSingleFileTest( + "deleteNodeAfterInClass1", + /*placeOpenBraceOnNewLineForFunctions*/ false, + text, + /*validateNodes*/ false, + (sourceFile, changeTracker) => { + deleteNode(changeTracker, sourceFile, findChild("x", sourceFile)); + }, + ); } { const text = ` @@ -684,9 +1500,15 @@ class A { y = 1; } `; - runSingleFileTest("deleteNodeAfterInClass2", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - deleteNode(changeTracker, sourceFile, findChild("x", sourceFile)); - }); + runSingleFileTest( + "deleteNodeAfterInClass2", + /*placeOpenBraceOnNewLineForFunctions*/ false, + text, + /*validateNodes*/ false, + (sourceFile, changeTracker) => { + deleteNode(changeTracker, sourceFile, findChild("x", sourceFile)); + }, + ); } { const text = ` @@ -694,16 +1516,22 @@ class A { x = foo } `; - runSingleFileTest("insertNodeInClassAfterNodeWithoutSeparator1", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - const newNode = ts.factory.createPropertyDeclaration( - /*modifiers*/ undefined, - ts.factory.createComputedPropertyName(ts.factory.createNumericLiteral(1)), - /*questionOrExclamationToken*/ undefined, - ts.factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword), - /*initializer*/ undefined, - ); - changeTracker.insertNodeAfter(sourceFile, findChild("x", sourceFile), newNode); - }); + runSingleFileTest( + "insertNodeInClassAfterNodeWithoutSeparator1", + /*placeOpenBraceOnNewLineForFunctions*/ false, + text, + /*validateNodes*/ false, + (sourceFile, changeTracker) => { + const newNode = ts.factory.createPropertyDeclaration( + /*modifiers*/ undefined, + ts.factory.createComputedPropertyName(ts.factory.createNumericLiteral(1)), + /*questionOrExclamationToken*/ undefined, + ts.factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword), + /*initializer*/ undefined, + ); + changeTracker.insertNodeAfter(sourceFile, findChild("x", sourceFile), newNode); + }, + ); } { const text = ` @@ -712,16 +1540,22 @@ class A { } } `; - runSingleFileTest("insertNodeInClassAfterNodeWithoutSeparator2", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - const newNode = ts.factory.createPropertyDeclaration( - /*modifiers*/ undefined, - ts.factory.createComputedPropertyName(ts.factory.createNumericLiteral(1)), - /*questionOrExclamationToken*/ undefined, - ts.factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword), - /*initializer*/ undefined, - ); - changeTracker.insertNodeAfter(sourceFile, findChild("x", sourceFile), newNode); - }); + runSingleFileTest( + "insertNodeInClassAfterNodeWithoutSeparator2", + /*placeOpenBraceOnNewLineForFunctions*/ false, + text, + /*validateNodes*/ false, + (sourceFile, changeTracker) => { + const newNode = ts.factory.createPropertyDeclaration( + /*modifiers*/ undefined, + ts.factory.createComputedPropertyName(ts.factory.createNumericLiteral(1)), + /*questionOrExclamationToken*/ undefined, + ts.factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword), + /*initializer*/ undefined, + ); + changeTracker.insertNodeAfter(sourceFile, findChild("x", sourceFile), newNode); + }, + ); } { const text = ` @@ -729,16 +1563,22 @@ interface A { x } `; - runSingleFileTest("insertNodeInInterfaceAfterNodeWithoutSeparator1", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - const newNode = ts.factory.createPropertyDeclaration( - /*modifiers*/ undefined, - ts.factory.createComputedPropertyName(ts.factory.createNumericLiteral(1)), - /*questionOrExclamationToken*/ undefined, - ts.factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword), - /*initializer*/ undefined, - ); - changeTracker.insertNodeAfter(sourceFile, findChild("x", sourceFile), newNode); - }); + runSingleFileTest( + "insertNodeInInterfaceAfterNodeWithoutSeparator1", + /*placeOpenBraceOnNewLineForFunctions*/ false, + text, + /*validateNodes*/ false, + (sourceFile, changeTracker) => { + const newNode = ts.factory.createPropertyDeclaration( + /*modifiers*/ undefined, + ts.factory.createComputedPropertyName(ts.factory.createNumericLiteral(1)), + /*questionOrExclamationToken*/ undefined, + ts.factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword), + /*initializer*/ undefined, + ); + changeTracker.insertNodeAfter(sourceFile, findChild("x", sourceFile), newNode); + }, + ); } { const text = ` @@ -746,24 +1586,38 @@ interface A { x() } `; - runSingleFileTest("insertNodeInInterfaceAfterNodeWithoutSeparator2", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - const newNode = ts.factory.createPropertyDeclaration( - /*modifiers*/ undefined, - ts.factory.createComputedPropertyName(ts.factory.createNumericLiteral(1)), - /*questionOrExclamationToken*/ undefined, - ts.factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword), - /*initializer*/ undefined, - ); - changeTracker.insertNodeAfter(sourceFile, findChild("x", sourceFile), newNode); - }); + runSingleFileTest( + "insertNodeInInterfaceAfterNodeWithoutSeparator2", + /*placeOpenBraceOnNewLineForFunctions*/ false, + text, + /*validateNodes*/ false, + (sourceFile, changeTracker) => { + const newNode = ts.factory.createPropertyDeclaration( + /*modifiers*/ undefined, + ts.factory.createComputedPropertyName(ts.factory.createNumericLiteral(1)), + /*questionOrExclamationToken*/ undefined, + ts.factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword), + /*initializer*/ undefined, + ); + changeTracker.insertNodeAfter(sourceFile, findChild("x", sourceFile), newNode); + }, + ); } { const text = ` let x = foo `; - runSingleFileTest("insertNodeInStatementListAfterNodeWithoutSeparator1", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - const newNode = ts.factory.createExpressionStatement(ts.factory.createParenthesizedExpression(ts.factory.createNumericLiteral(1))); - changeTracker.insertNodeAfter(sourceFile, findVariableStatementContaining("x", sourceFile), newNode); - }); + runSingleFileTest( + "insertNodeInStatementListAfterNodeWithoutSeparator1", + /*placeOpenBraceOnNewLineForFunctions*/ false, + text, + /*validateNodes*/ false, + (sourceFile, changeTracker) => { + const newNode = ts.factory.createExpressionStatement( + ts.factory.createParenthesizedExpression(ts.factory.createNumericLiteral(1)), + ); + changeTracker.insertNodeAfter(sourceFile, findVariableStatementContaining("x", sourceFile), newNode); + }, + ); } }); diff --git a/src/testRunner/unittests/services/transpile.ts b/src/testRunner/unittests/services/transpile.ts index ddb040d7af356..b2d1383030438 100644 --- a/src/testRunner/unittests/services/transpile.ts +++ b/src/testRunner/unittests/services/transpile.ts @@ -40,7 +40,8 @@ describe("unittests:: services:: Transpile", () => { transpileOptions.reportDiagnostics = true; - const justName = "transpile/" + name.replace(/[^a-z0-9\-. ()=]/ig, "") + (transpileOptions.compilerOptions.jsx ? ts.Extension.Tsx : ts.Extension.Ts); + const justName = "transpile/" + name.replace(/[^a-z0-9\-. ()=]/ig, "") + + (transpileOptions.compilerOptions.jsx ? ts.Extension.Tsx : ts.Extension.Ts); const toBeCompiled = [{ unitName, content: input, @@ -52,7 +53,13 @@ describe("unittests:: services:: Transpile", () => { if (canUseOldTranspile) { oldTranspileDiagnostics = []; - oldTranspileResult = ts.transpile(input, transpileOptions.compilerOptions, transpileOptions.fileName, oldTranspileDiagnostics, transpileOptions.moduleName); + oldTranspileResult = ts.transpile( + input, + transpileOptions.compilerOptions, + transpileOptions.fileName, + oldTranspileDiagnostics, + transpileOptions.moduleName, + ); } }); @@ -64,23 +71,37 @@ describe("unittests:: services:: Transpile", () => { /* eslint-disable no-null/no-null */ it("Correct errors for " + justName, () => { - Harness.Baseline.runBaseline(justName.replace(/\.tsx?$/, ".errors.txt"), transpileResult.diagnostics!.length === 0 ? null : Harness.Compiler.getErrorBaseline(toBeCompiled, transpileResult.diagnostics!)); + Harness.Baseline.runBaseline( + justName.replace(/\.tsx?$/, ".errors.txt"), + transpileResult.diagnostics!.length === 0 ? null + : Harness.Compiler.getErrorBaseline(toBeCompiled, transpileResult.diagnostics!), + ); }); if (canUseOldTranspile) { it("Correct errors (old transpile) for " + justName, () => { - Harness.Baseline.runBaseline(justName.replace(/\.tsx?$/, ".oldTranspile.errors.txt"), oldTranspileDiagnostics.length === 0 ? null : Harness.Compiler.getErrorBaseline(toBeCompiled, oldTranspileDiagnostics)); + Harness.Baseline.runBaseline( + justName.replace(/\.tsx?$/, ".oldTranspile.errors.txt"), + oldTranspileDiagnostics.length === 0 ? null + : Harness.Compiler.getErrorBaseline(toBeCompiled, oldTranspileDiagnostics), + ); }); } /* eslint-enable no-null/no-null */ it("Correct output for " + justName, () => { - Harness.Baseline.runBaseline(justName.replace(/\.tsx?$/, ts.Extension.Js), transpileResult.outputText); + Harness.Baseline.runBaseline( + justName.replace(/\.tsx?$/, ts.Extension.Js), + transpileResult.outputText, + ); }); if (canUseOldTranspile) { it("Correct output (old transpile) for " + justName, () => { - Harness.Baseline.runBaseline(justName.replace(/\.tsx?$/, ".oldTranspile.js"), oldTranspileResult); + Harness.Baseline.runBaseline( + justName.replace(/\.tsx?$/, ".oldTranspile.js"), + oldTranspileResult, + ); }); } }); @@ -142,7 +163,10 @@ var x = 0;`, }); transpilesCorrectly("Sets module name", "var x = 1; export {};", { - options: { compilerOptions: { module: ts.ModuleKind.System, newLine: ts.NewLineKind.LineFeed }, moduleName: "NamedModule" }, + options: { + compilerOptions: { module: ts.ModuleKind.System, newLine: ts.NewLineKind.LineFeed }, + moduleName: "NamedModule", + }, }); transpilesCorrectly("No extra errors for file without extension", `"use strict";\r\nvar x = 0;`, { @@ -152,49 +176,58 @@ var x = 0;`, transpilesCorrectly( "Rename dependencies - System", - `import {foo} from "SomeName";\n` + - `declare function use(a: any);\n` + - `use(foo);`, + `import {foo} from "SomeName";\n` + + `declare function use(a: any);\n` + + `use(foo);`, { - options: { compilerOptions: { module: ts.ModuleKind.System, newLine: ts.NewLineKind.LineFeed }, renamedDependencies: { SomeName: "SomeOtherName" } }, + options: { + compilerOptions: { module: ts.ModuleKind.System, newLine: ts.NewLineKind.LineFeed }, + renamedDependencies: { SomeName: "SomeOtherName" }, + }, }, ); transpilesCorrectly( "Rename dependencies - AMD", - `import {foo} from "SomeName";\n` + - `declare function use(a: any);\n` + - `use(foo);`, + `import {foo} from "SomeName";\n` + + `declare function use(a: any);\n` + + `use(foo);`, { - options: { compilerOptions: { module: ts.ModuleKind.AMD, newLine: ts.NewLineKind.LineFeed }, renamedDependencies: { SomeName: "SomeOtherName" } }, + options: { + compilerOptions: { module: ts.ModuleKind.AMD, newLine: ts.NewLineKind.LineFeed }, + renamedDependencies: { SomeName: "SomeOtherName" }, + }, }, ); transpilesCorrectly( "Rename dependencies - UMD", - `import {foo} from "SomeName";\n` + - `declare function use(a: any);\n` + - `use(foo);`, + `import {foo} from "SomeName";\n` + + `declare function use(a: any);\n` + + `use(foo);`, { - options: { compilerOptions: { module: ts.ModuleKind.UMD, newLine: ts.NewLineKind.LineFeed }, renamedDependencies: { SomeName: "SomeOtherName" } }, + options: { + compilerOptions: { module: ts.ModuleKind.UMD, newLine: ts.NewLineKind.LineFeed }, + renamedDependencies: { SomeName: "SomeOtherName" }, + }, }, ); transpilesCorrectly( "Transpile with emit decorators and emit metadata", - `import {db} from './db';\n` + - `function someDecorator(target) {\n` + - ` return target;\n` + - `} \n` + - `@someDecorator\n` + - `class MyClass {\n` + - ` db: db;\n` + - ` constructor(db: db) {\n` + - ` this.db = db;\n` + - ` this.db.doSomething(); \n` + - ` }\n` + - `}\n` + - `export {MyClass}; \n`, + `import {db} from './db';\n` + + `function someDecorator(target) {\n` + + ` return target;\n` + + `} \n` + + `@someDecorator\n` + + `class MyClass {\n` + + ` db: db;\n` + + ` constructor(db: db) {\n` + + ` this.db = db;\n` + + ` this.db.doSomething(); \n` + + ` }\n` + + `}\n` + + `export {MyClass}; \n`, { options: { compilerOptions: { @@ -219,7 +252,11 @@ var x = 0;`, }); transpilesCorrectly("transpile .js files", "const a = 10;", { - options: { compilerOptions: { newLine: ts.NewLineKind.LineFeed, module: ts.ModuleKind.CommonJS }, fileName: "input.js", reportDiagnostics: true }, + options: { + compilerOptions: { newLine: ts.NewLineKind.LineFeed, module: ts.ModuleKind.CommonJS }, + fileName: "input.js", + reportDiagnostics: true, + }, }); transpilesCorrectly("Supports urls in file name", "var x", { @@ -245,12 +282,20 @@ var x = 0;`, }); transpilesCorrectly("Support options with lib values", "const a = 10;", { - options: { compilerOptions: { lib: ["es6", "dom"], module: ts.ModuleKind.CommonJS }, fileName: "input.js", reportDiagnostics: true }, + options: { + compilerOptions: { lib: ["es6", "dom"], module: ts.ModuleKind.CommonJS }, + fileName: "input.js", + reportDiagnostics: true, + }, testVerbatimModuleSyntax: true, }); transpilesCorrectly("Support options with types values", "const a = 10;", { - options: { compilerOptions: { types: ["jquery", "typescript"], module: ts.ModuleKind.CommonJS }, fileName: "input.js", reportDiagnostics: true }, + options: { + compilerOptions: { types: ["jquery", "typescript"], module: ts.ModuleKind.CommonJS }, + fileName: "input.js", + reportDiagnostics: true, + }, testVerbatimModuleSyntax: true, }); @@ -260,7 +305,11 @@ var x = 0;`, }); transpilesCorrectly("Supports setting 'allowSyntheticDefaultImports'", "x;", { - options: { compilerOptions: { allowSyntheticDefaultImports: true }, fileName: "input.js", reportDiagnostics: true }, + options: { + compilerOptions: { allowSyntheticDefaultImports: true }, + fileName: "input.js", + reportDiagnostics: true, + }, testVerbatimModuleSyntax: true, }); @@ -295,7 +344,11 @@ var x = 0;`, }); transpilesCorrectly("Supports setting 'declarationDir'", "x;", { - options: { compilerOptions: { declarationDir: "out/declarations" }, fileName: "input.js", reportDiagnostics: true }, + options: { + compilerOptions: { declarationDir: "out/declarations" }, + fileName: "input.js", + reportDiagnostics: true, + }, testVerbatimModuleSyntax: true, }); @@ -305,7 +358,11 @@ var x = 0;`, }); transpilesCorrectly("Supports setting 'emitDecoratorMetadata'", "x;", { - options: { compilerOptions: { emitDecoratorMetadata: true, experimentalDecorators: true }, fileName: "input.js", reportDiagnostics: true }, + options: { + compilerOptions: { emitDecoratorMetadata: true, experimentalDecorators: true }, + fileName: "input.js", + reportDiagnostics: true, + }, testVerbatimModuleSyntax: true, }); @@ -315,7 +372,11 @@ var x = 0;`, }); transpilesCorrectly("Supports setting 'forceConsistentCasingInFileNames'", "x;", { - options: { compilerOptions: { forceConsistentCasingInFileNames: true }, fileName: "input.js", reportDiagnostics: true }, + options: { + compilerOptions: { forceConsistentCasingInFileNames: true }, + fileName: "input.js", + reportDiagnostics: true, + }, testVerbatimModuleSyntax: true, }); @@ -349,12 +410,20 @@ var x = 0;`, }); transpilesCorrectly("Supports setting 'moduleResolution'", "x;", { - options: { compilerOptions: { moduleResolution: ts.ModuleResolutionKind.Node10 }, fileName: "input.js", reportDiagnostics: true }, + options: { + compilerOptions: { moduleResolution: ts.ModuleResolutionKind.Node10 }, + fileName: "input.js", + reportDiagnostics: true, + }, testVerbatimModuleSyntax: true, }); transpilesCorrectly("Supports setting 'newLine'", "x;", { - options: { compilerOptions: { newLine: ts.NewLineKind.CarriageReturnLineFeed }, fileName: "input.js", reportDiagnostics: true }, + options: { + compilerOptions: { newLine: ts.NewLineKind.CarriageReturnLineFeed }, + fileName: "input.js", + reportDiagnostics: true, + }, testVerbatimModuleSyntax: true, }); @@ -379,7 +448,11 @@ var x = 0;`, }); transpilesCorrectly("Supports setting 'noFallthroughCasesInSwitch'", "x;", { - options: { compilerOptions: { noFallthroughCasesInSwitch: true }, fileName: "input.js", reportDiagnostics: true }, + options: { + compilerOptions: { noFallthroughCasesInSwitch: true }, + fileName: "input.js", + reportDiagnostics: true, + }, testVerbatimModuleSyntax: true, }); @@ -429,7 +502,11 @@ var x = 0;`, }); transpilesCorrectly("Supports setting 'paths'", "x;", { - options: { compilerOptions: { paths: { "*": ["./generated*"] } }, fileName: "input.js", reportDiagnostics: true }, + options: { + compilerOptions: { paths: { "*": ["./generated*"] } }, + fileName: "input.js", + reportDiagnostics: true, + }, testVerbatimModuleSyntax: true, }); @@ -449,7 +526,11 @@ var x = 0;`, }); transpilesCorrectly("Supports setting 'jsxFragmentFactory'", "x;", { - options: { compilerOptions: { jsxFactory: "x", jsxFragmentFactory: "frag" }, fileName: "input.js", reportDiagnostics: true }, + options: { + compilerOptions: { jsxFactory: "x", jsxFragmentFactory: "frag" }, + fileName: "input.js", + reportDiagnostics: true, + }, testVerbatimModuleSyntax: true, }); @@ -489,12 +570,20 @@ var x = 0;`, }); transpilesCorrectly("Supports setting 'suppressExcessPropertyErrors'", "x;", { - options: { compilerOptions: { suppressExcessPropertyErrors: true }, fileName: "input.js", reportDiagnostics: true }, + options: { + compilerOptions: { suppressExcessPropertyErrors: true }, + fileName: "input.js", + reportDiagnostics: true, + }, testVerbatimModuleSyntax: true, }); transpilesCorrectly("Supports setting 'suppressImplicitAnyIndexErrors'", "x;", { - options: { compilerOptions: { suppressImplicitAnyIndexErrors: true }, fileName: "input.js", reportDiagnostics: true }, + options: { + compilerOptions: { suppressImplicitAnyIndexErrors: true }, + fileName: "input.js", + reportDiagnostics: true, + }, testVerbatimModuleSyntax: true, }); @@ -524,18 +613,22 @@ var x = 0;`, }); transpilesCorrectly("Supports setting 'tsbuildinfo'", "x;", { - options: { compilerOptions: { incremental: true, tsBuildInfoFile: "./folder/config.tsbuildinfo" }, fileName: "input.js", reportDiagnostics: true }, + options: { + compilerOptions: { incremental: true, tsBuildInfoFile: "./folder/config.tsbuildinfo" }, + fileName: "input.js", + reportDiagnostics: true, + }, testVerbatimModuleSyntax: true, }); transpilesCorrectly( "Correctly serialize metadata when transpile with CommonJS option", - `import * as ng from "angular2/core";` + - `declare function foo(...args: any[]);` + - `@foo` + - `export class MyClass1 {` + - ` constructor(private _elementRef: ng.ElementRef){}` + - `}`, + `import * as ng from "angular2/core";` + + `declare function foo(...args: any[]);` + + `@foo` + + `export class MyClass1 {` + + ` constructor(private _elementRef: ng.ElementRef){}` + + `}`, { options: { compilerOptions: { @@ -552,12 +645,12 @@ var x = 0;`, transpilesCorrectly( "Correctly serialize metadata when transpile with System option", - `import * as ng from "angular2/core";` + - `declare function foo(...args: any[]);` + - `@foo` + - `export class MyClass1 {` + - ` constructor(private _elementRef: ng.ElementRef){}` + - `}`, + `import * as ng from "angular2/core";` + + `declare function foo(...args: any[]);` + + `@foo` + + `export class MyClass1 {` + + ` constructor(private _elementRef: ng.ElementRef){}` + + `}`, { options: { compilerOptions: { @@ -601,8 +694,8 @@ export * as alias from './file';`, transpilesCorrectly( "Elides import equals referenced only by export type", - `import IFoo = Namespace.IFoo;` + - `export type { IFoo };`, + `import IFoo = Namespace.IFoo;` + + `export type { IFoo };`, { options: { compilerOptions: { module: ts.ModuleKind.CommonJS } }, }, @@ -610,8 +703,8 @@ export * as alias from './file';`, transpilesCorrectly( "Does not elide import equals referenced only by export type", - `import IFoo = Namespace.IFoo;` + - `export type { IFoo };`, + `import IFoo = Namespace.IFoo;` + + `export type { IFoo };`, { options: { compilerOptions: { module: ts.ModuleKind.CommonJS } }, testVerbatimModuleSyntax: "only", @@ -620,8 +713,8 @@ export * as alias from './file';`, transpilesCorrectly( "Elides import equals referenced only by type only export specifier", - `import IFoo = Namespace.IFoo;` + - `export { type IFoo };`, + `import IFoo = Namespace.IFoo;` + + `export { type IFoo };`, { options: { compilerOptions: { module: ts.ModuleKind.CommonJS } }, }, @@ -629,8 +722,8 @@ export * as alias from './file';`, transpilesCorrectly( "Does not elide import equals referenced only by type only export specifier", - `import IFoo = Namespace.IFoo;` + - `export { type IFoo };`, + `import IFoo = Namespace.IFoo;` + + `export { type IFoo };`, { options: { compilerOptions: { module: ts.ModuleKind.CommonJS } }, testVerbatimModuleSyntax: "only", @@ -642,10 +735,20 @@ export * as alias from './file';`, testVerbatimModuleSyntax: true, }); - transpilesCorrectly("Ignores `allowImportingTsExtensions` without `noEmit` error", `import { foo } from "./foo.ts";`, { - options: { compilerOptions: { module: ts.ModuleKind.ESNext, allowImportingTsExtensions: true, target: ts.ScriptTarget.ESNext } }, - testVerbatimModuleSyntax: true, - }); + transpilesCorrectly( + "Ignores `allowImportingTsExtensions` without `noEmit` error", + `import { foo } from "./foo.ts";`, + { + options: { + compilerOptions: { + module: ts.ModuleKind.ESNext, + allowImportingTsExtensions: true, + target: ts.ScriptTarget.ESNext, + }, + }, + testVerbatimModuleSyntax: true, + }, + ); transpilesCorrectly( "Preserves exported const merged with type-only import", diff --git a/src/testRunner/unittests/services/utilities.ts b/src/testRunner/unittests/services/utilities.ts index 91b82462b479e..60c5b928a2bf1 100644 --- a/src/testRunner/unittests/services/utilities.ts +++ b/src/testRunner/unittests/services/utilities.ts @@ -15,7 +15,10 @@ describe("unittests:: services:: utilities", () => { /*setParentNodes*/ true, ); // can't use ts.getTokenAtPosition because it returns back the wrong token - const param = ts.forEachChildRecursively(sourceFile, node => node.kind === ts.SyntaxKind.Parameter ? node : undefined)!; + const param = ts.forEachChildRecursively( + sourceFile, + node => node.kind === ts.SyntaxKind.Parameter ? node : undefined, + )!; const jsDoc = param.getChildren()[0]; const token = jsDoc.getLastToken()!; const result = ts.findPrecedingMatchingToken(token, ts.SyntaxKind.OpenBraceToken, sourceFile); diff --git a/src/testRunner/unittests/transform.ts b/src/testRunner/unittests/transform.ts index 766a1d9f8ec9a..5bdbb8efac941 100644 --- a/src/testRunner/unittests/transform.ts +++ b/src/testRunner/unittests/transform.ts @@ -42,7 +42,9 @@ describe("unittests:: TransformAPI", () => { return (file: ts.SourceFile) => ts.visitNode(file, visitor, ts.isSourceFile); } - function replaceIdentifiersNamedOldNameWithNewName(context: ts.TransformationContext) { + function replaceIdentifiersNamedOldNameWithNewName( + context: ts.TransformationContext, + ) { const previousOnSubstituteNode = context.onSubstituteNode; context.enableSubstitution(ts.SyntaxKind.Identifier); context.onSubstituteNode = (hint, node) => { @@ -79,7 +81,10 @@ describe("unittests:: TransformAPI", () => { } function transformSourceFile(sourceText: string, transformers: ts.TransformerFactory[]) { - const transformed = ts.transform(ts.createSourceFile("source.ts", sourceText, ts.ScriptTarget.ES2015), transformers); + const transformed = ts.transform( + ts.createSourceFile("source.ts", sourceText, ts.ScriptTarget.ES2015), + transformers, + ); const printer = ts.createPrinter({ newLine: ts.NewLineKind.CarriageReturnLineFeed }, { onEmitNode: transformed.emitNodeWithNotification, substituteNode: transformed.substituteNode, @@ -264,8 +269,18 @@ describe("unittests:: TransformAPI", () => { const result = ts.factory.updateSourceFile( sourceFile, ts.factory.createNodeArray([ - ts.factory.createClassDeclaration(/*modifiers*/ undefined, "Foo", /*typeParameters*/ undefined, /*heritageClauses*/ undefined, /*members*/ undefined!), // TODO: GH#18217 - ts.factory.createModuleDeclaration(/*modifiers*/ undefined, ts.factory.createIdentifier("Foo"), ts.factory.createModuleBlock([ts.factory.createEmptyStatement()])), + ts.factory.createClassDeclaration( + /*modifiers*/ undefined, + "Foo", + /*typeParameters*/ undefined, + /*heritageClauses*/ undefined, + /*members*/ undefined!, + ), // TODO: GH#18217 + ts.factory.createModuleDeclaration( + /*modifiers*/ undefined, + ts.factory.createIdentifier("Foo"), + ts.factory.createModuleBlock([ts.factory.createEmptyStatement()]), + ), ]), ); return result; @@ -307,9 +322,18 @@ describe("unittests:: TransformAPI", () => { if (node.kind === ts.SyntaxKind.ExportDeclaration) { const ed = node as ts.Node as ts.ExportDeclaration; const exports = [{ name: "x" }]; - const exportSpecifiers = exports.map(e => ts.factory.createExportSpecifier(/*isTypeOnly*/ false, e.name, e.name)); + const exportSpecifiers = exports.map(e => + ts.factory.createExportSpecifier(/*isTypeOnly*/ false, e.name, e.name) + ); const exportClause = ts.factory.createNamedExports(exportSpecifiers); - const newEd = ts.factory.updateExportDeclaration(ed, ed.modifiers, ed.isTypeOnly, exportClause, ed.moduleSpecifier, ed.assertClause); + const newEd = ts.factory.updateExportDeclaration( + ed, + ed.modifiers, + ed.isTypeOnly, + exportClause, + ed.moduleSpecifier, + ed.assertClause, + ); return newEd as ts.Node as T; } @@ -373,9 +397,24 @@ describe("unittests:: TransformAPI", () => { }; function visitNode(sf: ts.SourceFile) { // produce `class Foo { @Bar baz() {} }`; - const classDecl = ts.factory.createClassDeclaration(/*modifiers*/ undefined, "Foo", /*typeParameters*/ undefined, /*heritageClauses*/ undefined, [ - ts.factory.createMethodDeclaration([ts.factory.createDecorator(ts.factory.createIdentifier("Bar"))], /*asteriskToken*/ undefined, "baz", /*questionToken*/ undefined, /*typeParameters*/ undefined, [], /*type*/ undefined, ts.factory.createBlock([])), - ]); + const classDecl = ts.factory.createClassDeclaration( + /*modifiers*/ undefined, + "Foo", + /*typeParameters*/ undefined, + /*heritageClauses*/ undefined, + [ + ts.factory.createMethodDeclaration( + [ts.factory.createDecorator(ts.factory.createIdentifier("Bar"))], + /*asteriskToken*/ undefined, + "baz", + /*questionToken*/ undefined, + /*typeParameters*/ undefined, + [], + /*type*/ undefined, + ts.factory.createBlock([]), + ), + ], + ); return ts.factory.updateSourceFile(sf, [classDecl]); } } @@ -413,21 +452,42 @@ describe("unittests:: TransformAPI", () => { function visitNode(sf: ts.SourceFile) { // produce `class Foo { constructor(@Dec private x) {} }`; // The decorator is required to trigger ts.ts transformations. - const classDecl = ts.factory.createClassDeclaration([], "Foo", /*typeParameters*/ undefined, /*heritageClauses*/ undefined, [ - ts.factory.createConstructorDeclaration(/*modifiers*/ undefined, [ - ts.factory.createParameterDeclaration([ts.factory.createDecorator(ts.factory.createIdentifier("Dec")), ts.factory.createModifier(ts.SyntaxKind.PrivateKeyword)], /*dotDotDotToken*/ undefined, "x"), - ], ts.factory.createBlock([])), - ]); + const classDecl = ts.factory.createClassDeclaration( + [], + "Foo", + /*typeParameters*/ undefined, + /*heritageClauses*/ undefined, + [ + ts.factory.createConstructorDeclaration(/*modifiers*/ undefined, [ + ts.factory.createParameterDeclaration( + [ + ts.factory.createDecorator(ts.factory.createIdentifier("Dec")), + ts.factory.createModifier(ts.SyntaxKind.PrivateKeyword), + ], + /*dotDotDotToken*/ undefined, + "x", + ), + ], ts.factory.createBlock([])), + ], + ); return ts.factory.updateSourceFile(sf, [classDecl]); } } }); function baselineDeclarationTransform(text: string, opts: ts.TranspileOptions) { - const fs = vfs.createFromFileSystem(Harness.IO, /*ignoreCase*/ true, { documents: [new documents.TextDocument("/.src/index.ts", text)] }); + const fs = vfs.createFromFileSystem(Harness.IO, /*ignoreCase*/ true, { + documents: [new documents.TextDocument("/.src/index.ts", text)], + }); const host = new fakes.CompilerHost(fs, opts.compilerOptions); const program = ts.createProgram(["/.src/index.ts"], opts.compilerOptions!, host); - program.emit(program.getSourceFile("/.src/index.ts"), (p, s, bom) => host.writeFile(p, s, bom), /*cancellationToken*/ undefined, /*emitOnlyDtsFiles*/ true, opts.transformers); + program.emit( + program.getSourceFile("/.src/index.ts"), + (p, s, bom) => host.writeFile(p, s, bom), + /*cancellationToken*/ undefined, + /*emitOnlyDtsFiles*/ true, + opts.transformers, + ); return fs.readFileSync("/.src/index.d.ts").toString(); } @@ -439,7 +499,13 @@ describe("unittests:: TransformAPI", () => { function rootTransform(node: T): ts.VisitResult { if (nodeFilter(node)) { ts.setEmitFlags(node, ts.EmitFlags.NoLeadingComments); - ts.setSyntheticLeadingComments(node, [{ kind: ts.SyntaxKind.MultiLineCommentTrivia, text: "comment", pos: -1, end: -1, hasTrailingNewLine: true }]); + ts.setSyntheticLeadingComments(node, [{ + kind: ts.SyntaxKind.MultiLineCommentTrivia, + text: "comment", + pos: -1, + end: -1, + hasTrailingNewLine: true, + }]); } return ts.visitEachChild(node, rootTransform, context); } @@ -497,7 +563,12 @@ export {Value}; `, { transformers: { - before: [addSyntheticComment(n => ts.isImportDeclaration(n) || ts.isExportDeclaration(n) || ts.isImportSpecifier(n) || ts.isExportSpecifier(n))], + before: [ + addSyntheticComment(n => + ts.isImportDeclaration(n) || ts.isExportDeclaration(n) || ts.isImportSpecifier(n) + || ts.isExportSpecifier(n) + ), + ], }, compilerOptions: { target: ts.ScriptTarget.ES5, @@ -523,7 +594,12 @@ class Clazz { `, { transformers: { - before: [addSyntheticComment(n => ts.isPropertyDeclaration(n) || ts.isParameterPropertyDeclaration(n, n.parent) || ts.isClassDeclaration(n) || ts.isConstructorDeclaration(n))], + before: [ + addSyntheticComment(n => + ts.isPropertyDeclaration(n) || ts.isParameterPropertyDeclaration(n, n.parent) + || ts.isClassDeclaration(n) || ts.isConstructorDeclaration(n) + ), + ], }, compilerOptions: { target: ts.ScriptTarget.ES2015, @@ -582,7 +658,13 @@ module MyModule { }; function rootTransform(node: T): ts.Node { if (ts.isVariableDeclaration(node)) { - return ts.factory.updateVariableDeclaration(node, ts.factory.createIdentifier("newName"), /*exclamationToken*/ undefined, /*type*/ undefined, node.initializer); + return ts.factory.updateVariableDeclaration( + node, + ts.factory.createIdentifier("newName"), + /*exclamationToken*/ undefined, + /*type*/ undefined, + node.initializer, + ); } return ts.visitEachChild(node, rootTransform, context); } @@ -592,7 +674,10 @@ module MyModule { // https://github.com/Microsoft/TypeScript/issues/24709 testBaseline("issue24709", () => { const fs = vfs.createFromFileSystem(Harness.IO, /*ignoreCase*/ true); - const transformed = ts.transform(ts.createSourceFile("source.ts", "class X { echo(x: string) { return x; } }", ts.ScriptTarget.ES3), [transformSourceFile]); + const transformed = ts.transform( + ts.createSourceFile("source.ts", "class X { echo(x: string) { return x; } }", ts.ScriptTarget.ES3), + [transformSourceFile], + ); const transformedSourceFile = transformed.transformed[0]; transformed.dispose(); const host = new fakes.CompilerHost(fs); @@ -658,18 +743,32 @@ module MyModule { }; function rootTransform(node: T): ts.Node { if (ts.isClassLike(node)) { - const newMembers = [ts.factory.createPropertyDeclaration([ts.factory.createModifier(ts.SyntaxKind.StaticKeyword)], "newField", /*questionOrExclamationToken*/ undefined, /*type*/ undefined, ts.factory.createStringLiteral("x"))]; - ts.setSyntheticLeadingComments(newMembers[0], [{ kind: ts.SyntaxKind.MultiLineCommentTrivia, text: "comment", pos: -1, end: -1, hasTrailingNewLine: true }]); - return ts.isClassDeclaration(node) ? - ts.factory.updateClassDeclaration( + const newMembers = [ + ts.factory.createPropertyDeclaration( + [ts.factory.createModifier(ts.SyntaxKind.StaticKeyword)], + "newField", + /*questionOrExclamationToken*/ undefined, + /*type*/ undefined, + ts.factory.createStringLiteral("x"), + ), + ]; + ts.setSyntheticLeadingComments(newMembers[0], [{ + kind: ts.SyntaxKind.MultiLineCommentTrivia, + text: "comment", + pos: -1, + end: -1, + hasTrailingNewLine: true, + }]); + return ts.isClassDeclaration(node) + ? ts.factory.updateClassDeclaration( node, node.modifiers, node.name, node.typeParameters, node.heritageClauses, newMembers, - ) : - ts.factory.updateClassExpression( + ) + : ts.factory.updateClassExpression( node, node.modifiers, node.name, diff --git a/src/testRunner/unittests/tsbuild/amdModulesWithOut.ts b/src/testRunner/unittests/tsbuild/amdModulesWithOut.ts index cb1f7ba78a9a1..a90cfc48c3b0b 100644 --- a/src/testRunner/unittests/tsbuild/amdModulesWithOut.ts +++ b/src/testRunner/unittests/tsbuild/amdModulesWithOut.ts @@ -176,7 +176,12 @@ ${internal} export enum internalEnum { a, b, c }`, describe("when the module resolution finds original source file", () => { function modifyFs(fs: vfs.FileSystem) { // Make lib to output to parent dir - replaceText(fs, "/src/lib/tsconfig.json", `"outFile": "module.js"`, `"outFile": "../module.js", "rootDir": "../"`); + replaceText( + fs, + "/src/lib/tsconfig.json", + `"outFile": "module.js"`, + `"outFile": "../module.js", "rootDir": "../"`, + ); // Change reference to file1 module to resolve to lib/file1 replaceText(fs, "/src/app/file3.ts", "file1", "lib/file1"); } diff --git a/src/testRunner/unittests/tsbuild/commandLine.ts b/src/testRunner/unittests/tsbuild/commandLine.ts index 56f7aa0d988ce..b962ac9d4df79 100644 --- a/src/testRunner/unittests/tsbuild/commandLine.ts +++ b/src/testRunner/unittests/tsbuild/commandLine.ts @@ -90,7 +90,10 @@ describe("unittests:: tsbuild:: commandLine::", () => { noChangeRun, withOptionChange("with declaration and declarationMap", "--declaration", "--declarationMap"), noChangeWithSubscenario("should re-emit only dts so they dont contain sourcemap"), - withOptionChangeAndDiscrepancyExplanation("with emitDeclarationOnly should not emit anything", "--emitDeclarationOnly"), + withOptionChangeAndDiscrepancyExplanation( + "with emitDeclarationOnly should not emit anything", + "--emitDeclarationOnly", + ), noChangeRun, localChange(), withOptionChangeAndDiscrepancyExplanation("with declaration should not emit anything", "--declaration"), @@ -111,7 +114,9 @@ describe("unittests:: tsbuild:: commandLine::", () => { noChangeRun, withOptionChange("with declaration and declarationMap", "--declaration", "--declarationMap"), noChangeWithSubscenario("should re-emit only dts so they dont contain sourcemap"), - withEmitDeclarationOnlyChangeAndDiscrepancyExplanation("with emitDeclarationOnly should not emit anything"), + withEmitDeclarationOnlyChangeAndDiscrepancyExplanation( + "with emitDeclarationOnly should not emit anything", + ), noChangeRun, localChange(), withOptionChangeAndDiscrepancyExplanation("with declaration should not emit anything", "--declaration"), @@ -138,7 +143,11 @@ describe("unittests:: tsbuild:: commandLine::", () => { withOptionChange("with sourceMap", "--sourceMap"), noChangeWithSubscenario("emit js files"), withOptionChange("with declaration and declarationMap", "--declaration", "--declarationMap"), - withOptionChange("with declaration and declarationMap, should not re-emit", "--declaration", "--declarationMap"), + withOptionChange( + "with declaration and declarationMap, should not re-emit", + "--declaration", + "--declarationMap", + ), ], baselinePrograms: true, }); @@ -160,7 +169,11 @@ describe("unittests:: tsbuild:: commandLine::", () => { withOptionChange("with sourceMap", "--sourceMap"), noChangeWithSubscenario("emit js files"), withOptionChange("with declaration and declarationMap", "--declaration", "--declarationMap"), - withOptionChange("with declaration and declarationMap, should not re-emit", "--declaration", "--declarationMap"), + withOptionChange( + "with declaration and declarationMap, should not re-emit", + "--declaration", + "--declarationMap", + ), ], baselinePrograms: true, }); @@ -180,8 +193,12 @@ describe("unittests:: tsbuild:: commandLine::", () => { references: [{ path: "../../project1/src" }], }), "/src/project2/src/e.ts": `export const e = 10;`, - "/src/project2/src/f.ts": `import { a } from "${options.outFile ? "a" : "../../project1/src/a"}"; export const f = a;`, - "/src/project2/src/g.ts": `import { b } from "${options.outFile ? "b" : "../../project1/src/b"}"; export const g = b;`, + "/src/project2/src/f.ts": `import { a } from "${ + options.outFile ? "a" : "../../project1/src/a" + }"; export const f = a;`, + "/src/project2/src/g.ts": `import { b } from "${ + options.outFile ? "b" : "../../project1/src/b" + }"; export const g = b;`, }); } function verifyWithIncremental(options: ts.CompilerOptions) { @@ -275,13 +292,20 @@ describe("unittests:: tsbuild:: commandLine::", () => { baselinePrograms: true, }); function subScenario(text: string) { - return `${text}${options.composite ? "" : " with declaration and incremental"}${options.outFile ? " with outFile" : ""}`; + return `${text}${options.composite ? "" : " with declaration and incremental"}${ + options.outFile ? " with outFile" : "" + }`; } } verifyWithIncremental({ composite: true }); verifyWithIncremental({ incremental: true, declaration: true }); verifyWithIncremental({ composite: true, outFile: "../outFile.js", module: ts.ModuleKind.AMD }); - verifyWithIncremental({ incremental: true, declaration: true, outFile: "../outFile.js", module: ts.ModuleKind.AMD }); + verifyWithIncremental({ + incremental: true, + declaration: true, + outFile: "../outFile.js", + module: ts.ModuleKind.AMD, + }); verifyTsc({ scenario: "commandLine", @@ -403,7 +427,13 @@ describe("unittests:: tsbuild:: commandLine::", () => { verifyTsc({ scenario: "commandLine", subScenario: "emitDeclarationOnly false on commandline with declaration with outFile", - fs: () => fs({ declaration: true, emitDeclarationOnly: true, outFile: "../outFile.js", module: ts.ModuleKind.AMD }), + fs: () => + fs({ + declaration: true, + emitDeclarationOnly: true, + outFile: "../outFile.js", + module: ts.ModuleKind.AMD, + }), commandLineArgs: ["--b", "/src/project2/src", "--verbose"], edits: [ noChangeRun, diff --git a/src/testRunner/unittests/tsbuild/emitDeclarationOnly.ts b/src/testRunner/unittests/tsbuild/emitDeclarationOnly.ts index a6ad5a3198433..f674ac7a65f82 100644 --- a/src/testRunner/unittests/tsbuild/emitDeclarationOnly.ts +++ b/src/testRunner/unittests/tsbuild/emitDeclarationOnly.ts @@ -18,13 +18,15 @@ describe("unittests:: tsbuild:: on project with emitDeclarationOnly set to true" function verifyEmitDeclarationOnly(disableMap?: true) { verifyTsc({ - subScenario: `only dts output in circular import project with emitDeclarationOnly${disableMap ? "" : " and declarationMap"}`, + subScenario: `only dts output in circular import project with emitDeclarationOnly${ + disableMap ? "" : " and declarationMap" + }`, fs: () => projFs, scenario: "emitDeclarationOnly", commandLineArgs: ["--b", "/src", "--verbose"], - modifyFs: disableMap ? - (fs => replaceText(fs, "/src/tsconfig.json", `"declarationMap": true,`, "")) : - undefined, + modifyFs: disableMap + ? (fs => replaceText(fs, "/src/tsconfig.json", `"declarationMap": true,`, "")) + : undefined, edits: [{ caption: "incremental-declaration-changes", edit: fs => replaceText(fs, "/src/src/a.ts", "b: B;", "b: B; foo: any;"), diff --git a/src/testRunner/unittests/tsbuild/fileDelete.ts b/src/testRunner/unittests/tsbuild/fileDelete.ts index c748507ff6267..74419f2201d6a 100644 --- a/src/testRunner/unittests/tsbuild/fileDelete.ts +++ b/src/testRunner/unittests/tsbuild/fileDelete.ts @@ -66,7 +66,12 @@ describe("unittests:: tsbuild:: fileDelete::", () => { scenario: "fileDelete", subScenario: `detects deleted file with outFile`, commandLineArgs: ["--b", "/src/main/tsconfig.json", "-v", "--traceResolution", "--explainFiles"], - fs: () => fs({ composite: true, outFile: "../childResult.js", module: ts.ModuleKind.AMD }, { composite: true, outFile: "../mainResult.js", module: ts.ModuleKind.AMD }), + fs: () => + fs({ composite: true, outFile: "../childResult.js", module: ts.ModuleKind.AMD }, { + composite: true, + outFile: "../mainResult.js", + module: ts.ModuleKind.AMD, + }), edits: [{ caption: "delete child2 file", edit: fs => fs.rimrafSync("/src/child/child2.ts"), diff --git a/src/testRunner/unittests/tsbuild/graphOrdering.ts b/src/testRunner/unittests/tsbuild/graphOrdering.ts index 0adf5d3b26903..4091783f35c36 100644 --- a/src/testRunner/unittests/tsbuild/graphOrdering.ts +++ b/src/testRunner/unittests/tsbuild/graphOrdering.ts @@ -50,7 +50,11 @@ describe("unittests:: tsbuild - graph-ordering", () => { }); function checkGraphOrdering(rootNames: string[], expectedBuildSet: string[], circular?: true) { - const builder = ts.createSolutionBuilder(host!, rootNames.map(getProjectFileName), { dry: true, force: false, verbose: false }); + const builder = ts.createSolutionBuilder(host!, rootNames.map(getProjectFileName), { + dry: true, + force: false, + verbose: false, + }); const buildOrder = builder.getBuildOrder(); assert.equal(ts.isCircularBuildOrder(buildOrder), !!circular); const buildQueue = ts.getBuildOrderFromAnyBuildOrder(buildOrder); @@ -61,7 +65,11 @@ describe("unittests:: tsbuild - graph-ordering", () => { const child = getProjectFileName(dep[0]); if (buildQueue.indexOf(child) < 0) continue; const parent = getProjectFileName(dep[1]); - assert.isAbove(buildQueue.indexOf(child), buildQueue.indexOf(parent), `Expecting child ${child} to be built after parent ${parent}`); + assert.isAbove( + buildQueue.indexOf(child), + buildQueue.indexOf(parent), + `Expecting child ${child} to be built after parent ${parent}`, + ); } } } @@ -73,8 +81,12 @@ describe("unittests:: tsbuild - graph-ordering", () => { function writeProjects(fileSystem: vfs.FileSystem, projectNames: string[], deps: [string, string][]): string[] { const projFileNames: string[] = []; for (const dep of deps) { - if (projectNames.indexOf(dep[0]) < 0) throw new Error(`Invalid dependency - project ${dep[0]} does not exist`); - if (projectNames.indexOf(dep[1]) < 0) throw new Error(`Invalid dependency - project ${dep[1]} does not exist`); + if (projectNames.indexOf(dep[0]) < 0) { + throw new Error(`Invalid dependency - project ${dep[0]} does not exist`); + } + if (projectNames.indexOf(dep[1]) < 0) { + throw new Error(`Invalid dependency - project ${dep[1]} does not exist`); + } } for (const proj of projectNames) { fileSystem.mkdirpSync(`/project/${proj}`); diff --git a/src/testRunner/unittests/tsbuild/moduleResolution.ts b/src/testRunner/unittests/tsbuild/moduleResolution.ts index 2a239547eef3e..17880c167f8d0 100644 --- a/src/testRunner/unittests/tsbuild/moduleResolution.ts +++ b/src/testRunner/unittests/tsbuild/moduleResolution.ts @@ -75,14 +75,16 @@ describe("unittests:: tsbuild:: moduleResolution:: handles the modules and optio verifyTscWatch({ scenario: "moduleResolution", - subScenario: `resolves specifier in output declaration file from referenced project correctly with preserveSymlinks`, + subScenario: + `resolves specifier in output declaration file from referenced project correctly with preserveSymlinks`, sys: () => sys({ preserveSymlinks: true }), commandLineArgs: ["-b", "packages/pkg1", "--verbose", "--traceResolution"], }); verifyTsc({ scenario: "moduleResolution", - subScenario: `type reference resolution uses correct options for different resolution options referenced project`, + subScenario: + `type reference resolution uses correct options for different resolution options referenced project`, fs: () => loadProjectFromFiles({ "/src/packages/pkg1_index.ts": `export const theNum: TheNum = "type1";`, @@ -98,7 +100,13 @@ describe("unittests:: tsbuild:: moduleResolution:: handles the modules and optio }), "/src/packages/typeroot2/sometype/index.d.ts": Utils.dedent`declare type TheNum2 = "type2";`, }), - commandLineArgs: ["-b", "/src/packages/pkg1.tsconfig.json", "/src/packages/pkg2.tsconfig.json", "--verbose", "--traceResolution"], + commandLineArgs: [ + "-b", + "/src/packages/pkg1.tsconfig.json", + "/src/packages/pkg2.tsconfig.json", + "--verbose", + "--traceResolution", + ], }); }); @@ -130,7 +138,14 @@ describe("unittests:: tsbuild:: moduleResolution:: impliedNodeFormat differs bet }), }), modifyFs: fs => fs.writeFileSync("/lib/lib.es2022.full.d.ts", libFile.content), - commandLineArgs: ["-b", "/src/projects/a", "/src/projects/b", "--verbose", "--traceResolution", "--explainFiles"], + commandLineArgs: [ + "-b", + "/src/projects/a", + "/src/projects/b", + "--verbose", + "--traceResolution", + "--explainFiles", + ], edits: noChangeOnlyRuns, }); }); diff --git a/src/testRunner/unittests/tsbuild/noEmit.ts b/src/testRunner/unittests/tsbuild/noEmit.ts index 39b1282c8e003..e574221b21517 100644 --- a/src/testRunner/unittests/tsbuild/noEmit.ts +++ b/src/testRunner/unittests/tsbuild/noEmit.ts @@ -33,7 +33,12 @@ describe("unittests:: tsbuild:: noEmit", () => { function verifyNoEmit(subScenario: string, aTsContent: string) { verifyNoEmitWorker(subScenario, aTsContent, ["--b", "/src/tsconfig.json", "-v"]); - verifyNoEmitWorker(`${subScenario} with incremental`, aTsContent, ["--b", "/src/tsconfig.json", "-v", "--incremental"]); + verifyNoEmitWorker(`${subScenario} with incremental`, aTsContent, [ + "--b", + "/src/tsconfig.json", + "-v", + "--incremental", + ]); } verifyNoEmit("syntax errors", `const a = "hello`); diff --git a/src/testRunner/unittests/tsbuild/outFile.ts b/src/testRunner/unittests/tsbuild/outFile.ts index 92df313b09741..95531f85602be 100644 --- a/src/testRunner/unittests/tsbuild/outFile.ts +++ b/src/testRunner/unittests/tsbuild/outFile.ts @@ -461,14 +461,16 @@ ${internal} enum internalEnum { a, b, c }`, verifyOutFileScenario({ subScenario: "stripInternal", modifyFs: stripInternalScenario, - modifyAgainFs: fs => replaceText(fs, "/src/first/first_PART1.ts", `/*@internal*/ interface`, "interface"), + modifyAgainFs: fs => + replaceText(fs, "/src/first/first_PART1.ts", `/*@internal*/ interface`, "interface"), }); // Verify ignore dtsChanged verifyOutFileScenario({ subScenario: "stripInternal with comments emit enabled", modifyFs: fs => stripInternalScenario(fs, /*removeCommentsDisabled*/ true), - modifyAgainFs: fs => replaceText(fs, "/src/first/first_PART1.ts", `/*@internal*/ interface`, "interface"), + modifyAgainFs: fs => + replaceText(fs, "/src/first/first_PART1.ts", `/*@internal*/ interface`, "interface"), ignoreDtsChanged: true, baselineOnly: true, }); @@ -477,7 +479,8 @@ ${internal} enum internalEnum { a, b, c }`, verifyOutFileScenario({ subScenario: "stripInternal jsdoc style comment", modifyFs: fs => stripInternalScenario(fs, /*removeCommentsDisabled*/ false, /*jsDocStyle*/ true), - modifyAgainFs: fs => replaceText(fs, "/src/first/first_PART1.ts", `/**@internal*/ interface`, "interface"), + modifyAgainFs: fs => + replaceText(fs, "/src/first/first_PART1.ts", `/**@internal*/ interface`, "interface"), ignoreDtsChanged: true, baselineOnly: true, }); @@ -502,7 +505,11 @@ ${internal} enum internalEnum { a, b, c }`, replaceText(fs, "/src/third/tsconfig.json", `{ "path": "../first", "prepend": true },`, ""); } - function stripInternalWithDependentOrder(fs: vfs.FileSystem, removeCommentsDisabled?: boolean, jsDocStyle?: boolean) { + function stripInternalWithDependentOrder( + fs: vfs.FileSystem, + removeCommentsDisabled?: boolean, + jsDocStyle?: boolean, + ) { stripInternalScenario(fs, removeCommentsDisabled, jsDocStyle); makeOneTwoThreeDependOrder(fs); } @@ -511,14 +518,16 @@ ${internal} enum internalEnum { a, b, c }`, verifyOutFileScenario({ subScenario: "stripInternal when one-two-three are prepended in order", modifyFs: stripInternalWithDependentOrder, - modifyAgainFs: fs => replaceText(fs, "/src/first/first_PART1.ts", `/*@internal*/ interface`, "interface"), + modifyAgainFs: fs => + replaceText(fs, "/src/first/first_PART1.ts", `/*@internal*/ interface`, "interface"), }); // Verify ignore dtsChanged verifyOutFileScenario({ subScenario: "stripInternal with comments emit enabled when one-two-three are prepended in order", modifyFs: fs => stripInternalWithDependentOrder(fs, /*removeCommentsDisabled*/ true), - modifyAgainFs: fs => replaceText(fs, "/src/first/first_PART1.ts", `/*@internal*/ interface`, "interface"), + modifyAgainFs: fs => + replaceText(fs, "/src/first/first_PART1.ts", `/*@internal*/ interface`, "interface"), ignoreDtsChanged: true, baselineOnly: true, }); @@ -526,16 +535,20 @@ ${internal} enum internalEnum { a, b, c }`, // Verify ignore dtsChanged verifyOutFileScenario({ subScenario: "stripInternal jsdoc style comment when one-two-three are prepended in order", - modifyFs: fs => stripInternalWithDependentOrder(fs, /*removeCommentsDisabled*/ false, /*jsDocStyle*/ true), - modifyAgainFs: fs => replaceText(fs, "/src/first/first_PART1.ts", `/**@internal*/ interface`, "interface"), + modifyFs: fs => + stripInternalWithDependentOrder(fs, /*removeCommentsDisabled*/ false, /*jsDocStyle*/ true), + modifyAgainFs: fs => + replaceText(fs, "/src/first/first_PART1.ts", `/**@internal*/ interface`, "interface"), ignoreDtsChanged: true, baselineOnly: true, }); // Verify ignore dtsChanged verifyOutFileScenario({ - subScenario: "stripInternal jsdoc style with comments emit enabled when one-two-three are prepended in order", - modifyFs: fs => stripInternalWithDependentOrder(fs, /*removeCommentsDisabled*/ true, /*jsDocStyle*/ true), + subScenario: + "stripInternal jsdoc style with comments emit enabled when one-two-three are prepended in order", + modifyFs: fs => + stripInternalWithDependentOrder(fs, /*removeCommentsDisabled*/ true, /*jsDocStyle*/ true), ignoreDtsChanged: true, baselineOnly: true, }); @@ -700,8 +713,18 @@ ${internal} enum internalEnum { a, b, c }`, commandLineArgs: ["--b", "/src/third", "--verbose"], modifyFs: fs => { // No prepend - replaceText(fs, "/src/third/tsconfig.json", `{ "path": "../first", "prepend": true }`, `{ "path": "../first" }`); - replaceText(fs, "/src/third/tsconfig.json", `{ "path": "../second", "prepend": true }`, `{ "path": "../second" }`); + replaceText( + fs, + "/src/third/tsconfig.json", + `{ "path": "../first", "prepend": true }`, + `{ "path": "../first" }`, + ); + replaceText( + fs, + "/src/third/tsconfig.json", + `{ "path": "../second", "prepend": true }`, + `{ "path": "../second" }`, + ); // Non Modules replaceText(fs, "/src/first/tsconfig.json", `"composite": true,`, `"composite": true, "module": "none",`); diff --git a/src/testRunner/unittests/tsbuild/outputPaths.ts b/src/testRunner/unittests/tsbuild/outputPaths.ts index 5383e9129db69..db5654e15f172 100644 --- a/src/testRunner/unittests/tsbuild/outputPaths.ts +++ b/src/testRunner/unittests/tsbuild/outputPaths.ts @@ -22,7 +22,10 @@ describe("unittests:: tsbuild - output file paths", () => { noChangeProject, ]; - function verify(input: Pick, expectedOuptutNames: readonly string[]) { + function verify( + input: Pick, + expectedOuptutNames: readonly string[], + ) { verifyTsc({ scenario: "outputPaths", commandLineArgs: ["--b", "/src/tsconfig.json", "-v"], @@ -30,11 +33,20 @@ describe("unittests:: tsbuild - output file paths", () => { }); it("verify getOutputFileNames", () => { - const sys = new fakes.System(input.fs().makeReadonly(), { executingFilePath: "/lib/tsc" }) as TscCompileSystem; + const sys = new fakes.System(input.fs().makeReadonly(), { + executingFilePath: "/lib/tsc", + }) as TscCompileSystem; assert.deepEqual( ts.getOutputFileNames( - ts.parseConfigFileWithSystem("/src/tsconfig.json", {}, /*extendedConfigCache*/ undefined, {}, sys, ts.noop)!, + ts.parseConfigFileWithSystem( + "/src/tsconfig.json", + {}, + /*extendedConfigCache*/ undefined, + {}, + sys, + ts.noop, + )!, "/src/src/index.ts", /*ignoreCase*/ false, ), diff --git a/src/testRunner/unittests/tsbuild/publicApi.ts b/src/testRunner/unittests/tsbuild/publicApi.ts index 5c9f03001d789..a4a5db634a147 100644 --- a/src/testRunner/unittests/tsbuild/publicApi.ts +++ b/src/testRunner/unittests/tsbuild/publicApi.ts @@ -72,7 +72,12 @@ export function f22() { } // trailing`, buildHost.afterProgramEmitAndDiagnostics = cb; buildHost.afterEmitBundle = cb; const builder = ts.createSolutionBuilder(buildHost, [commandLineArgs[1]], { verbose: true }); - const exitStatus = builder.build(/*project*/ undefined, /*cancellationToken*/ undefined, /*writeFile*/ undefined, getCustomTransformers); + const exitStatus = builder.build( + /*project*/ undefined, + /*cancellationToken*/ undefined, + /*writeFile*/ undefined, + getCustomTransformers, + ); sys.exit(exitStatus); sys.write(`exitCode:: ExitStatus.${ts.ExitStatus[sys.exitCode as ts.ExitStatus]}\n`); const baseline: string[] = []; @@ -106,7 +111,12 @@ ${patch ? vfs.formatPatch(patch) : ""}`, } } function visitFunction(node: ts.FunctionDeclaration) { - ts.addSyntheticLeadingComment(node, ts.SyntaxKind.MultiLineCommentTrivia, `@before${project}`, /*hasTrailingNewLine*/ true); + ts.addSyntheticLeadingComment( + node, + ts.SyntaxKind.MultiLineCommentTrivia, + `@before${project}`, + /*hasTrailingNewLine*/ true, + ); return node; } }; diff --git a/src/testRunner/unittests/tsbuild/resolveJsonModule.ts b/src/testRunner/unittests/tsbuild/resolveJsonModule.ts index ceac563a00a7f..6a7df66ae6e09 100644 --- a/src/testRunner/unittests/tsbuild/resolveJsonModule.ts +++ b/src/testRunner/unittests/tsbuild/resolveJsonModule.ts @@ -68,7 +68,13 @@ export default hello.hello`, subScenario: "sourcemap", fs: () => projFs, commandLineArgs: ["--b", "src/tsconfig_withFiles.json", "--verbose", "--explainFiles"], - modifyFs: fs => replaceText(fs, "src/tsconfig_withFiles.json", `"composite": true,`, `"composite": true, "sourceMap": true,`), + modifyFs: fs => + replaceText( + fs, + "src/tsconfig_withFiles.json", + `"composite": true,`, + `"composite": true, "sourceMap": true,`, + ), edits: noChangeOnlyRuns, }); diff --git a/src/testRunner/unittests/tsbuild/sample.ts b/src/testRunner/unittests/tsbuild/sample.ts index 6bea86bc8f002..2b5fd66bbc9a7 100644 --- a/src/testRunner/unittests/tsbuild/sample.ts +++ b/src/testRunner/unittests/tsbuild/sample.ts @@ -88,7 +88,12 @@ describe("unittests:: tsbuild:: on 'sample1' project", () => { fs.writeFileSync( "/src/logic/tsconfig.json", JSON.stringify({ - compilerOptions: { composite: true, declaration: true, sourceMap: true, declarationDir: "out/decls" }, + compilerOptions: { + composite: true, + declaration: true, + sourceMap: true, + declarationDir: "out/decls", + }, references: [{ path: "../core" }], }), ), @@ -176,7 +181,12 @@ describe("unittests:: tsbuild:: on 'sample1' project", () => { { caption: "rebuilds when tsconfig changes", edit: fs => { - replaceText(fs, "/src/tests/tsconfig.json", `"composite": true`, `"composite": true, "target": "es2020"`); + replaceText( + fs, + "/src/tests/tsconfig.json", + `"composite": true`, + `"composite": true, "target": "es2020"`, + ); fs.writeFileSync("/lib/lib.es2020.full.d.ts", libContent); }, }, @@ -207,11 +217,23 @@ describe("unittests:: tsbuild:: on 'sample1' project", () => { edits: [ { caption: "Disable declarationMap", - edit: fs => replaceText(fs, "/src/core/tsconfig.json", `"declarationMap": true,`, `"declarationMap": false,`), + edit: fs => + replaceText( + fs, + "/src/core/tsconfig.json", + `"declarationMap": true,`, + `"declarationMap": false,`, + ), }, { caption: "Enable declarationMap", - edit: fs => replaceText(fs, "/src/core/tsconfig.json", `"declarationMap": false,`, `"declarationMap": true,`), + edit: fs => + replaceText( + fs, + "/src/core/tsconfig.json", + `"declarationMap": false,`, + `"declarationMap": true,`, + ), }, ], }); @@ -261,10 +283,16 @@ describe("unittests:: tsbuild:: on 'sample1' project", () => { verifyTscCompileLike(testTscCompileLike, { scenario: "sample1", - subScenario: "does not rebuild if there is no program and bundle in the ts build info event if version doesnt match ts version", + subScenario: + "does not rebuild if there is no program and bundle in the ts build info event if version doesnt match ts version", fs: () => { const fs = projFs.shadow(); - const host = fakes.SolutionBuilderHost.create(fs, /*options*/ undefined, /*setParentNodes*/ undefined, ts.createAbstractBuilder); + const host = fakes.SolutionBuilderHost.create( + fs, + /*options*/ undefined, + /*setParentNodes*/ undefined, + ts.createAbstractBuilder, + ); const builder = ts.createSolutionBuilder(host, ["/src/tests"], { verbose: true }); builder.build(); fs.makeReadonly(); @@ -285,8 +313,16 @@ describe("unittests:: tsbuild:: on 'sample1' project", () => { fs: () => projFs, commandLineArgs: ["--b", "/src/tests", "--verbose"], modifyFs: fs => { - fs.writeFileSync("/src/tests/tsconfig.base.json", JSON.stringify({ compilerOptions: { target: "es3" } })); - replaceText(fs, "/src/tests/tsconfig.json", `"references": [`, `"extends": "./tsconfig.base.json", "references": [`); + fs.writeFileSync( + "/src/tests/tsconfig.base.json", + JSON.stringify({ compilerOptions: { target: "es3" } }), + ); + replaceText( + fs, + "/src/tests/tsconfig.json", + `"references": [`, + `"extends": "./tsconfig.base.json", "references": [`, + ); }, edits: [{ caption: "incremental-declaration-changes", @@ -353,7 +389,10 @@ describe("unittests:: tsbuild:: on 'sample1' project", () => { verifyBuildNextResult(); // logic verifyBuildNextResult(); // tests verifyBuildNextResult(); // All Done - Harness.Baseline.runBaseline(`tsbuild/sample1/building-using-getNextInvalidatedProject.js`, baseline.join("\r\n")); + Harness.Baseline.runBaseline( + `tsbuild/sample1/building-using-getNextInvalidatedProject.js`, + baseline.join("\r\n"), + ); function verifyBuildNextResult() { const project = builder.getNextInvalidatedProject(); @@ -423,7 +462,11 @@ describe("unittests:: tsbuild:: on 'sample1' project", () => { ); const host = createSolutionBuilderHostForBaseline(system); - const builder = ts.createSolutionBuilder(host, [testsConfig.path], { dry: false, force: false, verbose: false }); + const builder = ts.createSolutionBuilder(host, [testsConfig.path], { + dry: false, + force: false, + verbose: false, + }); builder.build(); baselineState("Build of project"); @@ -568,7 +611,13 @@ class someClass2 { }`, ), edits: [{ caption: "incremental-declaration-changes", - edit: fs => replaceText(fs, "/src/core/tsconfig.json", `"incremental": true,`, `"incremental": true, "declaration": true,`), + edit: fs => + replaceText( + fs, + "/src/core/tsconfig.json", + `"incremental": true,`, + `"incremental": true, "declaration": true,`, + ), }], }); @@ -653,7 +702,8 @@ class someClass2 { }`, ), edits: [{ caption: "incremental-declaration-changes", - edit: fs => replaceText(fs, "/src/tests/tsconfig.json", `"esModuleInterop": false`, `"esModuleInterop": true`), + edit: fs => + replaceText(fs, "/src/tests/tsconfig.json", `"esModuleInterop": false`, `"esModuleInterop": true`), }], }); diff --git a/src/testRunner/unittests/tsbuildWatch/demo.ts b/src/testRunner/unittests/tsbuildWatch/demo.ts index 891c57e593fa7..3414d5e0270df 100644 --- a/src/testRunner/unittests/tsbuildWatch/demo.ts +++ b/src/testRunner/unittests/tsbuildWatch/demo.ts @@ -25,7 +25,10 @@ describe("unittests:: tsbuildWatch:: watchMode:: with demo project", () => { zooFiles = subProjectFiles("zoo", ["tsconfig.json", "zoo.ts"]); solutionFile = projectFile("tsconfig.json"); baseConfig = projectFile("tsconfig-base.json"); - allFiles = [...coreFiles, ...animalFiles, ...zooFiles, solutionFile, baseConfig, { path: libFile.path, content: libContent }]; + allFiles = [...coreFiles, ...animalFiles, ...zooFiles, solutionFile, baseConfig, { + path: libFile.path, + content: libContent, + }]; }); after(() => { diff --git a/src/testRunner/unittests/tsbuildWatch/libraryResolution.ts b/src/testRunner/unittests/tsbuildWatch/libraryResolution.ts index dd2c4f0e2ac2e..d34a3ea233be3 100644 --- a/src/testRunner/unittests/tsbuildWatch/libraryResolution.ts +++ b/src/testRunner/unittests/tsbuildWatch/libraryResolution.ts @@ -11,7 +11,17 @@ describe("unittests:: tsbuildWatch:: watchMode:: libraryResolution:: library fil scenario: "libraryResolution", subScenario: `with config${libRedirection ? " with redirection" : ""}`, sys: () => getSysForLibResolution(libRedirection), - commandLineArgs: ["-b", "-w", "project1", "project2", "project3", "project4", "--verbose", "--explainFiles", "--extendedDiagnostics"], + commandLineArgs: [ + "-b", + "-w", + "project1", + "project2", + "project3", + "project4", + "--verbose", + "--explainFiles", + "--extendedDiagnostics", + ], }); } verify(); diff --git a/src/testRunner/unittests/tsbuildWatch/moduleResolution.ts b/src/testRunner/unittests/tsbuildWatch/moduleResolution.ts index 9c2a9a7281456..e402ed53be871 100644 --- a/src/testRunner/unittests/tsbuildWatch/moduleResolution.ts +++ b/src/testRunner/unittests/tsbuildWatch/moduleResolution.ts @@ -16,8 +16,14 @@ describe("unittests:: tsbuildWatch:: watchMode:: moduleResolution", () => { sys: () => createWatchedSystem( [ - { path: `/user/username/projects/myproject/project1/index.ts`, content: `import { foo } from "file";` }, - { path: `/user/username/projects/myproject/project1/node_modules/file/index.d.ts`, content: "export const foo = 10;" }, + { + path: `/user/username/projects/myproject/project1/index.ts`, + content: `import { foo } from "file";`, + }, + { + path: `/user/username/projects/myproject/project1/node_modules/file/index.d.ts`, + content: "export const foo = 10;", + }, { path: `/user/username/projects/myproject/project1/tsconfig.json`, content: JSON.stringify({ @@ -25,7 +31,10 @@ describe("unittests:: tsbuildWatch:: watchMode:: moduleResolution", () => { files: ["index.ts"], }), }, - { path: `/user/username/projects/myproject/project2/index.ts`, content: `import { foo } from "file";` }, + { + path: `/user/username/projects/myproject/project2/index.ts`, + content: `import { foo } from "file";`, + }, { path: `/user/username/projects/myproject/project2/file.d.ts`, content: "export const foo = 10;" }, { path: `/user/username/projects/myproject/project2/tsconfig.json`, @@ -34,8 +43,14 @@ describe("unittests:: tsbuildWatch:: watchMode:: moduleResolution", () => { files: ["index.ts"], }), }, - { path: `/user/username/projects/myproject/node_modules/@types/foo/index.d.ts`, content: "export const foo = 10;" }, - { path: `/user/username/projects/myproject/node_modules/@types/bar/index.d.ts`, content: "export const bar = 10;" }, + { + path: `/user/username/projects/myproject/node_modules/@types/foo/index.d.ts`, + content: "export const foo = 10;", + }, + { + path: `/user/username/projects/myproject/node_modules/@types/bar/index.d.ts`, + content: "export const bar = 10;", + }, { path: `/user/username/projects/myproject/tsconfig.json`, content: JSON.stringify({ @@ -62,7 +77,8 @@ describe("unittests:: tsbuildWatch:: watchMode:: moduleResolution", () => { verifyTscWatch({ scenario: "moduleResolution", - subScenario: `resolves specifier in output declaration file from referenced project correctly with cts and mts extensions`, + subScenario: + `resolves specifier in output declaration file from referenced project correctly with cts and mts extensions`, sys: () => createWatchedSystem([ { @@ -127,24 +143,46 @@ describe("unittests:: tsbuildWatch:: watchMode:: moduleResolution", () => { edits: [ { caption: "reports import errors after change to package file", - edit: sys => sys.replaceFileText(`/user/username/projects/myproject/packages/pkg1/package.json`, `"module"`, `"commonjs"`), + edit: sys => + sys.replaceFileText( + `/user/username/projects/myproject/packages/pkg1/package.json`, + `"module"`, + `"commonjs"`, + ), timeouts: sys => sys.runQueuedTimeoutCallbacks(), }, { caption: "removes those errors when a package file is changed back", - edit: sys => sys.replaceFileText(`/user/username/projects/myproject/packages/pkg1/package.json`, `"commonjs"`, `"module"`), + edit: sys => + sys.replaceFileText( + `/user/username/projects/myproject/packages/pkg1/package.json`, + `"commonjs"`, + `"module"`, + ), timeouts: sys => sys.runQueuedTimeoutCallbacks(), }, { caption: "reports import errors after change to package file", - edit: sys => sys.replaceFileText(`/user/username/projects/myproject/packages/pkg1/package.json`, `"module"`, `"commonjs"`), + edit: sys => + sys.replaceFileText( + `/user/username/projects/myproject/packages/pkg1/package.json`, + `"module"`, + `"commonjs"`, + ), timeouts: sys => sys.runQueuedTimeoutCallbacks(), }, { caption: "removes those errors when a package file is changed to cjs extensions", edit: sys => { - sys.replaceFileText(`/user/username/projects/myproject/packages/pkg2/package.json`, `"build/index.js"`, `"build/index.cjs"`); - sys.renameFile(`/user/username/projects/myproject/packages/pkg2/index.ts`, `/user/username/projects/myproject/packages/pkg2/index.cts`); + sys.replaceFileText( + `/user/username/projects/myproject/packages/pkg2/package.json`, + `"build/index.js"`, + `"build/index.cjs"`, + ); + sys.renameFile( + `/user/username/projects/myproject/packages/pkg2/index.ts`, + `/user/username/projects/myproject/packages/pkg2/index.cts`, + ); }, timeouts: sys => { sys.runQueuedTimeoutCallbacks(); // building pkg2 @@ -222,12 +260,22 @@ describe("unittests:: tsbuildWatch:: watchMode:: moduleResolution", () => { edits: [ { caption: "reports import errors after change to package file", - edit: sys => sys.replaceFileText(`/user/username/projects/myproject/packages/pkg2/package.json`, `index.js`, `other.js`), + edit: sys => + sys.replaceFileText( + `/user/username/projects/myproject/packages/pkg2/package.json`, + `index.js`, + `other.js`, + ), timeouts: sys => sys.runQueuedTimeoutCallbacks(), }, { caption: "removes those errors when a package file is changed back", - edit: sys => sys.replaceFileText(`/user/username/projects/myproject/packages/pkg2/package.json`, `other.js`, `index.js`), + edit: sys => + sys.replaceFileText( + `/user/username/projects/myproject/packages/pkg2/package.json`, + `other.js`, + `index.js`, + ), timeouts: sys => sys.runQueuedTimeoutCallbacks(), }, ], diff --git a/src/testRunner/unittests/tsbuildWatch/noEmit.ts b/src/testRunner/unittests/tsbuildWatch/noEmit.ts index 161f6dbefcd40..f8b43fb52e1cd 100644 --- a/src/testRunner/unittests/tsbuildWatch/noEmit.ts +++ b/src/testRunner/unittests/tsbuildWatch/noEmit.ts @@ -20,14 +20,21 @@ describe("unittests:: tsbuildWatch:: watchMode:: with noEmit", () => { { path: libFile.path, content: libContent }, { path: `/user/username/projects/myproject/a.js`, content: "" }, { path: `/user/username/projects/myproject/b.ts`, content: "" }, - { path: `/user/username/projects/myproject/tsconfig.json`, content: JSON.stringify({ compilerOptions: { allowJs: true, noEmit: true } }) }, + { + path: `/user/username/projects/myproject/tsconfig.json`, + content: JSON.stringify({ compilerOptions: { allowJs: true, noEmit: true } }), + }, ], { currentDirectory: "/user/username/projects/myproject" }, ), edits: [ { caption: "No change", - edit: sys => sys.writeFile(`/user/username/projects/myproject/a.js`, sys.readFile(`/user/username/projects/myproject/a.js`)!), + edit: sys => + sys.writeFile( + `/user/username/projects/myproject/a.js`, + sys.readFile(`/user/username/projects/myproject/a.js`)!, + ), // build project timeouts: sys => sys.runQueuedTimeoutCallbacks(), }, diff --git a/src/testRunner/unittests/tsbuildWatch/noEmitOnError.ts b/src/testRunner/unittests/tsbuildWatch/noEmitOnError.ts index 22e5a713141a7..c6dda491c3257 100644 --- a/src/testRunner/unittests/tsbuildWatch/noEmitOnError.ts +++ b/src/testRunner/unittests/tsbuildWatch/noEmitOnError.ts @@ -23,7 +23,11 @@ describe("unittests:: tsbuildWatch:: watchMode:: with noEmitOnError", () => { const noChange: TscWatchCompileChange = { caption: "No change", - edit: sys => sys.writeFile(`/user/username/projects/noEmitOnError/src/main.ts`, sys.readFile(`/user/username/projects/noEmitOnError/src/main.ts`)!), + edit: sys => + sys.writeFile( + `/user/username/projects/noEmitOnError/src/main.ts`, + sys.readFile(`/user/username/projects/noEmitOnError/src/main.ts`)!, + ), // build project timeouts: sys => sys.runQueuedTimeoutCallbacks(), }; diff --git a/src/testRunner/unittests/tsbuildWatch/programUpdates.ts b/src/testRunner/unittests/tsbuildWatch/programUpdates.ts index 6e418029d90b8..2fb740fee2ef2 100644 --- a/src/testRunner/unittests/tsbuildWatch/programUpdates.ts +++ b/src/testRunner/unittests/tsbuildWatch/programUpdates.ts @@ -26,7 +26,12 @@ describe("unittests:: tsbuildWatch:: watchMode:: program updates", () => { } type ReadonlyFile = Readonly; /** [tsconfig, index] | [tsconfig, index, anotherModule, someDecl] */ - type SubProjectFiles = [tsconfig: ReadonlyFile, index: ReadonlyFile] | [tsconfig: ReadonlyFile, index: ReadonlyFile, anotherModule: ReadonlyFile, someDecl: ReadonlyFile]; + type SubProjectFiles = [tsconfig: ReadonlyFile, index: ReadonlyFile] | [ + tsconfig: ReadonlyFile, + index: ReadonlyFile, + anotherModule: ReadonlyFile, + someDecl: ReadonlyFile, + ]; function projectFilePath(subProject: SubProject, baseFileName: string) { return `${getTsBuildProjectFilePath("sample1", subProject)}/${baseFileName.toLowerCase()}`; } @@ -46,10 +51,18 @@ describe("unittests:: tsbuildWatch:: watchMode:: program updates", () => { return [tsconfig, index, anotherModule, someDecl]; } - function changeFile(fileName: string | (() => string), content: string | (() => string), caption: string): TscWatchCompileChange { + function changeFile( + fileName: string | (() => string), + content: string | (() => string), + caption: string, + ): TscWatchCompileChange { return { caption, - edit: sys => sys.writeFile(ts.isString(fileName) ? fileName : fileName(), ts.isString(content) ? content : content()), + edit: sys => + sys.writeFile( + ts.isString(fileName) ? fileName : fileName(), + ts.isString(content) ? content : content(), + ), timeouts: sys => sys.runQueuedTimeoutCallbacks(), // Builds core }; } @@ -88,9 +101,13 @@ describe("unittests:: tsbuildWatch:: watchMode:: program updates", () => { }); it("verify building references watches only those projects", () => { - const { sys, baseline, oldSnap, cb, getPrograms } = createBaseline(createWatchedSystem(allFiles, { currentDirectory: "/user/username/projects" })); + const { sys, baseline, oldSnap, cb, getPrograms } = createBaseline( + createWatchedSystem(allFiles, { currentDirectory: "/user/username/projects" }), + ); const host = createSolutionBuilderWithWatchHostForBaseline(sys, cb); - const solutionBuilder = ts.createSolutionBuilderWithWatch(host, [`sample1/${SubProject.tests}`], { watch: true }); + const solutionBuilder = ts.createSolutionBuilderWithWatch(host, [`sample1/${SubProject.tests}`], { + watch: true, + }); solutionBuilder.buildReferences(`sample1/${SubProject.tests}`); runWatchBaseline({ scenario: "programUpdates", @@ -273,7 +290,12 @@ export class someClass2 { }`), const logicTsConfig: File = { path: logic[0].path, content: JSON.stringify({ - compilerOptions: { ignoreDeprecations: "5.0", composite: true, declaration: true, outFile: "index.js" }, + compilerOptions: { + ignoreDeprecations: "5.0", + composite: true, + declaration: true, + outFile: "index.js", + }, references: [{ path: "../core", prepend: true }], }), }; @@ -281,7 +303,9 @@ export class someClass2 { }`), path: logic[1].path, content: `function bar() { return foo() + 1 };`, }; - return createWatchedSystem([libFile, coreTsConfig, coreIndex, logicTsConfig, logicIndex], { currentDirectory: "/user/username/projects" }); + return createWatchedSystem([libFile, coreTsConfig, coreIndex, logicTsConfig, logicIndex], { + currentDirectory: "/user/username/projects", + }); }, edits: [ changeCore(() => @@ -428,7 +452,8 @@ let x: string = 10;`, const changeFileWithoutError: TscWatchCompileChange = { caption: "Change fileWithoutError", - edit: sys => sys.writeFile(fileWithoutError.path, fileWithoutError.content.replace(/myClass/g, "myClass2")), + edit: sys => + sys.writeFile(fileWithoutError.path, fileWithoutError.content.replace(/myClass/g, "myClass2")), timeouts: sys => sys.runQueuedTimeoutCallbacks(), }; @@ -469,7 +494,8 @@ let x: string = 10;`, verifyTscWatch({ scenario: "programUpdates", - subScenario: "reportErrors/declarationEmitErrors/introduceError/when fixing errors only changed file is emitted", + subScenario: + "reportErrors/declarationEmitErrors/introduceError/when fixing errors only changed file is emitted", commandLineArgs: ["-b", "-w", subProject], sys: () => createWatchedSystem( @@ -549,7 +575,9 @@ export function someFn() { }`, }, }), }; - return createWatchedSystem([index, configFile, libFile], { currentDirectory: "/user/username/projects/myproject" }); + return createWatchedSystem([index, configFile, libFile], { + currentDirectory: "/user/username/projects/myproject", + }); }, edits: [ { @@ -590,8 +618,13 @@ export function someFn() { }`, commandLineArgs: ["-b", "-w", `sample1/${SubProject.core}`, "-verbose"], sys: () => { const [coreConfig, ...rest] = core; - const newCoreConfig: File = { path: coreConfig.path, content: JSON.stringify({ compilerOptions: { composite: true, outDir: "outDir" } }) }; - return createWatchedSystem([libFile, newCoreConfig, ...rest], { currentDirectory: "/user/username/projects" }); + const newCoreConfig: File = { + path: coreConfig.path, + content: JSON.stringify({ compilerOptions: { composite: true, outDir: "outDir" } }), + }; + return createWatchedSystem([libFile, newCoreConfig, ...rest], { + currentDirectory: "/user/username/projects", + }); }, edits: [ noopChange, @@ -607,7 +640,14 @@ export function someFn() { }`, verifyTscWatch({ scenario: "programUpdates", subScenario: "works with extended source files", - commandLineArgs: ["-b", "-w", "-v", "project1.tsconfig.json", "project2.tsconfig.json", "project3.tsconfig.json"], + commandLineArgs: [ + "-b", + "-w", + "-v", + "project1.tsconfig.json", + "project2.tsconfig.json", + "project3.tsconfig.json", + ], sys: () => { const alphaExtendedConfigFile: File = { path: "/a/b/alpha.tsconfig.json", @@ -674,7 +714,11 @@ export function someFn() { }`, const project3Config: File = { path: "/a/b/project3.tsconfig.json", content: JSON.stringify({ - extends: ["./extendsConfig1.tsconfig.json", "./extendsConfig2.tsconfig.json", "./extendsConfig3.tsconfig.json"], + extends: [ + "./extendsConfig1.tsconfig.json", + "./extendsConfig2.tsconfig.json", + "./extendsConfig3.tsconfig.json", + ], compilerOptions: { composite: false, }, diff --git a/src/testRunner/unittests/tsbuildWatch/projectsBuilding.ts b/src/testRunner/unittests/tsbuildWatch/projectsBuilding.ts index 851af314be0e2..4648a2f6233c1 100644 --- a/src/testRunner/unittests/tsbuildWatch/projectsBuilding.ts +++ b/src/testRunner/unittests/tsbuildWatch/projectsBuilding.ts @@ -31,9 +31,9 @@ describe("unittests:: tsbuildWatch:: watchMode:: projectsBuilding", () => { path: `/user/username/projects/myproject/pkg${index}/tsconfig.json`, content: JSON.stringify({ compilerOptions: { composite: true }, - references: index === 0 ? - undefined : - [{ path: `../pkg0` }], + references: index === 0 + ? undefined + : [{ path: `../pkg0` }], }), }, ]; @@ -66,13 +66,15 @@ describe("unittests:: tsbuildWatch:: watchMode:: projectsBuilding", () => { edits: [ { caption: "dts doesn't change", - edit: sys => sys.appendFile(`/user/username/projects/myproject/pkg0/index.ts`, `const someConst2 = 10;`), + edit: sys => + sys.appendFile(`/user/username/projects/myproject/pkg0/index.ts`, `const someConst2 = 10;`), timeouts: sys => sys.runQueuedTimeoutCallbacks(), // Build pkg0 and update timestamps }, noopChange, { caption: "dts change", - edit: sys => sys.appendFile(`/user/username/projects/myproject/pkg0/index.ts`, `export const someConst = 10;`), + edit: sys => + sys.appendFile(`/user/username/projects/myproject/pkg0/index.ts`, `export const someConst = 10;`), timeouts: sys => sys.runQueuedTimeoutCallbacks(), // Build pkg0 }, checkBuildPkg(1, 2), @@ -91,13 +93,15 @@ describe("unittests:: tsbuildWatch:: watchMode:: projectsBuilding", () => { edits: [ { caption: "dts doesn't change", - edit: sys => sys.appendFile(`/user/username/projects/myproject/pkg0/index.ts`, `const someConst2 = 10;`), + edit: sys => + sys.appendFile(`/user/username/projects/myproject/pkg0/index.ts`, `const someConst2 = 10;`), timeouts: sys => sys.runQueuedTimeoutCallbacks(), // Build pkg0 and update timestamps }, noopChange, { caption: "dts change", - edit: sys => sys.appendFile(`/user/username/projects/myproject/pkg0/index.ts`, `export const someConst = 10;`), + edit: sys => + sys.appendFile(`/user/username/projects/myproject/pkg0/index.ts`, `export const someConst = 10;`), timeouts: sys => sys.runQueuedTimeoutCallbacks(), // Build pkg0 }, checkBuildPkg(1, 4), @@ -116,13 +120,15 @@ describe("unittests:: tsbuildWatch:: watchMode:: projectsBuilding", () => { edits: [ { caption: "dts doesn't change", - edit: sys => sys.appendFile(`/user/username/projects/myproject/pkg0/index.ts`, `const someConst2 = 10;`), + edit: sys => + sys.appendFile(`/user/username/projects/myproject/pkg0/index.ts`, `const someConst2 = 10;`), timeouts: sys => sys.runQueuedTimeoutCallbacks(), // Build pkg0 and update timestamps }, noopChange, { caption: "dts change", - edit: sys => sys.appendFile(`/user/username/projects/myproject/pkg0/index.ts`, `export const someConst = 10;`), + edit: sys => + sys.appendFile(`/user/username/projects/myproject/pkg0/index.ts`, `export const someConst = 10;`), timeouts: sys => sys.runQueuedTimeoutCallbacks(), // Build pkg0 }, checkBuildPkg(1, 5), @@ -130,13 +136,15 @@ describe("unittests:: tsbuildWatch:: watchMode:: projectsBuilding", () => { noopChange, { caption: "dts change2", - edit: sys => sys.appendFile(`/user/username/projects/myproject/pkg0/index.ts`, `export const someConst3 = 10;`), + edit: sys => + sys.appendFile(`/user/username/projects/myproject/pkg0/index.ts`, `export const someConst3 = 10;`), timeouts: sys => sys.runQueuedTimeoutCallbacks(), // Build pkg0 }, checkBuildPkg(1, 5), { caption: "change while building", - edit: sys => sys.appendFile(`/user/username/projects/myproject/pkg0/index.ts`, `const someConst4 = 10;`), + edit: sys => + sys.appendFile(`/user/username/projects/myproject/pkg0/index.ts`, `const someConst4 = 10;`), timeouts: sys => sys.runQueuedTimeoutCallbacks(), // Build pkg0 }, checkBuildPkg(6, 2), @@ -155,13 +163,15 @@ describe("unittests:: tsbuildWatch:: watchMode:: projectsBuilding", () => { edits: [ { caption: "dts doesn't change", - edit: sys => sys.appendFile(`/user/username/projects/myproject/pkg0/index.ts`, `const someConst2 = 10;`), + edit: sys => + sys.appendFile(`/user/username/projects/myproject/pkg0/index.ts`, `const someConst2 = 10;`), timeouts: sys => sys.runQueuedTimeoutCallbacks(), // Build pkg0 and update timestamps }, noopChange, { caption: "dts change", - edit: sys => sys.appendFile(`/user/username/projects/myproject/pkg0/index.ts`, `export const someConst = 10;`), + edit: sys => + sys.appendFile(`/user/username/projects/myproject/pkg0/index.ts`, `export const someConst = 10;`), timeouts: sys => sys.runQueuedTimeoutCallbacks(), // Build pkg0 }, checkBuildPkg(1, 5), @@ -172,20 +182,23 @@ describe("unittests:: tsbuildWatch:: watchMode:: projectsBuilding", () => { noopChange, { caption: "dts change2", - edit: sys => sys.appendFile(`/user/username/projects/myproject/pkg0/index.ts`, `export const someConst3 = 10;`), + edit: sys => + sys.appendFile(`/user/username/projects/myproject/pkg0/index.ts`, `export const someConst3 = 10;`), timeouts: sys => sys.runQueuedTimeoutCallbacks(), // Build pkg0 }, checkBuildPkg(1, 5), checkBuildPkg(6, 5), { caption: "change while building", - edit: sys => sys.appendFile(`/user/username/projects/myproject/pkg0/index.ts`, `const someConst4 = 10;`), + edit: sys => + sys.appendFile(`/user/username/projects/myproject/pkg0/index.ts`, `const someConst4 = 10;`), timeouts: sys => sys.runQueuedTimeoutCallbacks(), // Build pkg0 }, checkBuildPkg(11, 5), { caption: "change while building: dts changes", - edit: sys => sys.appendFile(`/user/username/projects/myproject/pkg0/index.ts`, `export const someConst5 = 10;`), + edit: sys => + sys.appendFile(`/user/username/projects/myproject/pkg0/index.ts`, `export const someConst5 = 10;`), timeouts: sys => sys.runQueuedTimeoutCallbacks(), // Build pkg0 }, checkBuildPkg(1, 5), diff --git a/src/testRunner/unittests/tsbuildWatch/publicApi.ts b/src/testRunner/unittests/tsbuildWatch/publicApi.ts index 2f5ba8f5f648e..6caefdf5e37cc 100644 --- a/src/testRunner/unittests/tsbuildWatch/publicApi.ts +++ b/src/testRunner/unittests/tsbuildWatch/publicApi.ts @@ -51,7 +51,11 @@ export enum e2 { } export function f22() { } // trailing`, }; const commandLineArgs = ["--b", "--w"]; - const { sys, baseline, oldSnap, cb, getPrograms } = createBaseline(createWatchedSystem([libFile, solution, sharedConfig, sharedIndex, webpackConfig, webpackIndex], { currentDirectory: "/user/username/projects/myproject" })); + const { sys, baseline, oldSnap, cb, getPrograms } = createBaseline( + createWatchedSystem([libFile, solution, sharedConfig, sharedIndex, webpackConfig, webpackIndex], { + currentDirectory: "/user/username/projects/myproject", + }), + ); const buildHost = createSolutionBuilderWithWatchHostForBaseline(sys, cb); buildHost.getCustomTransformers = getCustomTransformers; const builder = ts.createSolutionBuilderWithWatch(buildHost, [solution.path], { verbose: true }); @@ -89,7 +93,12 @@ export function f22() { } // trailing`, } } function visitFunction(node: ts.FunctionDeclaration) { - ts.addSyntheticLeadingComment(node, ts.SyntaxKind.MultiLineCommentTrivia, `@before${project}`, /*hasTrailingNewLine*/ true); + ts.addSyntheticLeadingComment( + node, + ts.SyntaxKind.MultiLineCommentTrivia, + `@before${project}`, + /*hasTrailingNewLine*/ true, + ); return node; } }; diff --git a/src/testRunner/unittests/tsbuildWatch/reexport.ts b/src/testRunner/unittests/tsbuildWatch/reexport.ts index 1184a781da54f..0bae309e5de4a 100644 --- a/src/testRunner/unittests/tsbuildWatch/reexport.ts +++ b/src/testRunner/unittests/tsbuildWatch/reexport.ts @@ -42,7 +42,8 @@ describe("unittests:: tsbuildWatch:: watchMode:: with reexport when referenced p }, { caption: "Fix error", - edit: sys => sys.replaceFileText(`/user/username/projects/reexport/src/pure/session.ts`, "bar: ", "// bar: "), + edit: sys => + sys.replaceFileText(`/user/username/projects/reexport/src/pure/session.ts`, "bar: ", "// bar: "), timeouts: sys => { sys.runQueuedTimeoutCallbacks(); // build src/pure sys.runQueuedTimeoutCallbacks(); // build src/main and src diff --git a/src/testRunner/unittests/tsbuildWatch/watchEnvironment.ts b/src/testRunner/unittests/tsbuildWatch/watchEnvironment.ts index 64904c3e6e913..0170fd29bb169 100644 --- a/src/testRunner/unittests/tsbuildWatch/watchEnvironment.ts +++ b/src/testRunner/unittests/tsbuildWatch/watchEnvironment.ts @@ -26,7 +26,10 @@ describe("unittests:: tsbuildWatch:: watchEnvironment:: tsbuild:: watchMode:: wi writePkgReferences(system); const { sys, baseline, oldSnap, cb, getPrograms } = createBaseline(system); const host = createSolutionBuilderWithWatchHostForBaseline(sys, cb); - const solutionBuilder = ts.createSolutionBuilderWithWatch(host, ["tsconfig.json"], { watch: true, verbose: true }); + const solutionBuilder = ts.createSolutionBuilderWithWatch(host, ["tsconfig.json"], { + watch: true, + verbose: true, + }); solutionBuilder.build(); runWatchBaseline({ scenario: "watchEnvironment", diff --git a/src/testRunner/unittests/tsc/cancellationToken.ts b/src/testRunner/unittests/tsc/cancellationToken.ts index 8deb7cee76083..d205d80898896 100644 --- a/src/testRunner/unittests/tsc/cancellationToken.ts +++ b/src/testRunner/unittests/tsc/cancellationToken.ts @@ -122,7 +122,10 @@ describe("unittests:: tsc:: builder cancellationToken", () => { noChange("Clean build"); baselineCleanBuild(); - Harness.Baseline.runBaseline(`tsc/cancellationToken/${scenario.split(" ").join("-")}.js`, baseline.join("\r\n")); + Harness.Baseline.runBaseline( + `tsc/cancellationToken/${scenario.split(" ").join("-")}.js`, + baseline.join("\r\n"), + ); function noChange(caption: string) { oldSnap = applyEdit(sys, baseline, ts.noop, caption); @@ -134,13 +137,13 @@ describe("unittests:: tsc:: builder cancellationToken", () => { } function createIncrementalProgram() { - builderProgram = useBuildInfo ? - ts.createIncrementalProgram({ + builderProgram = useBuildInfo + ? ts.createIncrementalProgram({ rootNames: parsedConfig.fileNames, options: parsedConfig.options, host, - }) : - builderProgram = builderProgram = ts.createEmitAndSemanticDiagnosticsBuilderProgram( + }) + : builderProgram = builderProgram = ts.createEmitAndSemanticDiagnosticsBuilderProgram( parsedConfig.fileNames, parsedConfig.options, host, diff --git a/src/testRunner/unittests/tsc/composite.ts b/src/testRunner/unittests/tsc/composite.ts index a42d0cb4cc5bd..d881cda28f9f2 100644 --- a/src/testRunner/unittests/tsc/composite.ts +++ b/src/testRunner/unittests/tsc/composite.ts @@ -74,7 +74,8 @@ describe("unittests:: tsc:: composite::", () => { verifyTsc({ scenario: "composite", - subScenario: "when setting composite false and tsbuildinfo as null on command line but has tsbuild info in config", + subScenario: + "when setting composite false and tsbuildinfo as null on command line but has tsbuild info in config", fs: () => loadProjectFromFiles({ "/src/project/src/main.ts": "export const x = 10;", diff --git a/src/testRunner/unittests/tsc/declarationEmit.ts b/src/testRunner/unittests/tsc/declarationEmit.ts index 87383cad99c63..70b738cad5a2b 100644 --- a/src/testRunner/unittests/tsc/declarationEmit.ts +++ b/src/testRunner/unittests/tsc/declarationEmit.ts @@ -18,13 +18,19 @@ describe("unittests:: tsc:: declarationEmit::", () => { changeCaseFileTestPath: (path: string) => boolean; } - function changeCaseFile(file: FileOrFolderOrSymLink, testPath: (path: string) => boolean, replacePath: (path: string) => string): FileOrFolderOrSymLink { - return !isSymLink(file) || !testPath(file.symLink) ? - testPath(file.path) ? { ...file, path: replacePath(file.path) } : file : - { path: testPath(file.path) ? replacePath(file.path) : file.path, symLink: replacePath(file.symLink) }; + function changeCaseFile( + file: FileOrFolderOrSymLink, + testPath: (path: string) => boolean, + replacePath: (path: string) => string, + ): FileOrFolderOrSymLink { + return !isSymLink(file) || !testPath(file.symLink) + ? testPath(file.path) ? { ...file, path: replacePath(file.path) } : file + : { path: testPath(file.path) ? replacePath(file.path) : file.path, symLink: replacePath(file.symLink) }; } - function verifyDeclarationEmit({ subScenario, files, rootProject, changeCaseFileTestPath }: VerifyDeclarationEmitInput) { + function verifyDeclarationEmit( + { subScenario, files, rootProject, changeCaseFileTestPath }: VerifyDeclarationEmitInput, + ) { describe(subScenario, () => { verifyTscWatch({ scenario: "declarationEmit", @@ -41,7 +47,9 @@ describe("unittests:: tsc:: declarationEmit::", () => { subScenario: caseChangeScenario, sys: () => createWatchedSystem( - files.map(f => changeCaseFile(f, changeCaseFileTestPath, str => str.replace("myproject", "myProject"))), + files.map(f => + changeCaseFile(f, changeCaseFileTestPath, str => str.replace("myproject", "myProject")) + ), { currentDirectory: "/user/username/projects/myproject" }, ), commandLineArgs: ["-p", rootProject, "--explainFiles"], @@ -121,21 +129,37 @@ describe("unittests:: tsc:: declarationEmit::", () => { rootProject: "plugin-one", files: [ { path: `/user/username/projects/myproject/plugin-two/index.d.ts`, content: pluginTwoDts() }, - { path: `/user/username/projects/myproject/plugin-two/node_modules/typescript-fsa/package.json`, content: fsaPackageJson() }, - { path: `/user/username/projects/myproject/plugin-two/node_modules/typescript-fsa/index.d.ts`, content: fsaIndex() }, + { + path: `/user/username/projects/myproject/plugin-two/node_modules/typescript-fsa/package.json`, + content: fsaPackageJson(), + }, + { + path: `/user/username/projects/myproject/plugin-two/node_modules/typescript-fsa/index.d.ts`, + content: fsaIndex(), + }, { path: `/user/username/projects/myproject/plugin-one/tsconfig.json`, content: pluginOneConfig() }, { path: `/user/username/projects/myproject/plugin-one/index.ts`, content: pluginOneIndex() }, { path: `/user/username/projects/myproject/plugin-one/action.ts`, content: pluginOneAction() }, - { path: `/user/username/projects/myproject/plugin-one/node_modules/typescript-fsa/package.json`, content: fsaPackageJson() }, - { path: `/user/username/projects/myproject/plugin-one/node_modules/typescript-fsa/index.d.ts`, content: fsaIndex() }, - { path: `/user/username/projects/myproject/plugin-one/node_modules/plugin-two`, symLink: `/user/username/projects/myproject/plugin-two` }, + { + path: `/user/username/projects/myproject/plugin-one/node_modules/typescript-fsa/package.json`, + content: fsaPackageJson(), + }, + { + path: `/user/username/projects/myproject/plugin-one/node_modules/typescript-fsa/index.d.ts`, + content: fsaIndex(), + }, + { + path: `/user/username/projects/myproject/plugin-one/node_modules/plugin-two`, + symLink: `/user/username/projects/myproject/plugin-two`, + }, libFile, ], changeCaseFileTestPath: str => ts.stringContains(str, "/plugin-two"), }); verifyDeclarationEmit({ - subScenario: "when same version is referenced through source and another symlinked package with indirect link", + subScenario: + "when same version is referenced through source and another symlinked package with indirect link", rootProject: "plugin-one", files: [ { @@ -146,19 +170,37 @@ describe("unittests:: tsc:: declarationEmit::", () => { main: "dist/commonjs/index.js", }), }, - { path: `/user/username/projects/myproject/plugin-two/dist/commonjs/index.d.ts`, content: pluginTwoDts() }, - { path: `/user/username/projects/myproject/plugin-two/node_modules/typescript-fsa/package.json`, content: fsaPackageJson() }, - { path: `/user/username/projects/myproject/plugin-two/node_modules/typescript-fsa/index.d.ts`, content: fsaIndex() }, + { + path: `/user/username/projects/myproject/plugin-two/dist/commonjs/index.d.ts`, + content: pluginTwoDts(), + }, + { + path: `/user/username/projects/myproject/plugin-two/node_modules/typescript-fsa/package.json`, + content: fsaPackageJson(), + }, + { + path: `/user/username/projects/myproject/plugin-two/node_modules/typescript-fsa/index.d.ts`, + content: fsaIndex(), + }, { path: `/user/username/projects/myproject/plugin-one/tsconfig.json`, content: pluginOneConfig() }, { path: `/user/username/projects/myproject/plugin-one/index.ts`, content: `${pluginOneIndex()} ${pluginOneAction()}`, }, - { path: `/user/username/projects/myproject/plugin-one/node_modules/typescript-fsa/package.json`, content: fsaPackageJson() }, - { path: `/user/username/projects/myproject/plugin-one/node_modules/typescript-fsa/index.d.ts`, content: fsaIndex() }, + { + path: `/user/username/projects/myproject/plugin-one/node_modules/typescript-fsa/package.json`, + content: fsaPackageJson(), + }, + { + path: `/user/username/projects/myproject/plugin-one/node_modules/typescript-fsa/index.d.ts`, + content: fsaIndex(), + }, { path: `/temp/yarn/data/link/plugin-two`, symLink: `/user/username/projects/myproject/plugin-two` }, - { path: `/user/username/projects/myproject/plugin-one/node_modules/plugin-two`, symLink: `/temp/yarn/data/link/plugin-two` }, + { + path: `/user/username/projects/myproject/plugin-one/node_modules/plugin-two`, + symLink: `/temp/yarn/data/link/plugin-two`, + }, libFile, ], changeCaseFileTestPath: str => ts.stringContains(str, "/plugin-two"), diff --git a/src/testRunner/unittests/tsc/incremental.ts b/src/testRunner/unittests/tsc/incremental.ts index 6232fc3b59bee..d9a282276a070 100644 --- a/src/testRunner/unittests/tsc/incremental.ts +++ b/src/testRunner/unittests/tsc/incremental.ts @@ -37,7 +37,14 @@ describe("unittests:: tsc:: incremental::", () => { ] }`, }), - commandLineArgs: ["--incremental", "--p", "src/project", "--tsBuildInfoFile", "src/project/.tsbuildinfo", "--explainFiles"], + commandLineArgs: [ + "--incremental", + "--p", + "src/project", + "--tsBuildInfoFile", + "src/project/.tsbuildinfo", + "--explainFiles", + ], edits: noChangeOnlyRuns, }); @@ -122,7 +129,11 @@ describe("unittests:: tsc:: incremental::", () => { projFs = undefined!; }); - function verifyNoEmitOnError(subScenario: string, fixModifyFs: TestTscEdit["edit"], modifyFs?: TestTscEdit["edit"]) { + function verifyNoEmitOnError( + subScenario: string, + fixModifyFs: TestTscEdit["edit"], + modifyFs?: TestTscEdit["edit"], + ) { verifyTsc({ scenario: "incremental", subScenario, @@ -186,9 +197,9 @@ const a: string = 10;`, ...noChangeRun, caption: "No Change run with noEmit", commandLineArgs: ["--p", "src/project", "--noEmit"], - discrepancyExplanation: compilerOptions.composite ? - discrepancyExplanation : - undefined, + discrepancyExplanation: compilerOptions.composite + ? discrepancyExplanation + : undefined, }; const noChangeRunWithEmit: TestTscEdit = { ...noChangeRun, @@ -214,9 +225,9 @@ const a: string = 10;`, caption: "Introduce error but still noEmit", commandLineArgs: ["--p", "src/project", "--noEmit"], edit: fs => replaceText(fs, "/src/project/src/class.ts", "prop", "prop1"), - discrepancyExplanation: compilerOptions.composite ? - discrepancyExplanation : - undefined, + discrepancyExplanation: compilerOptions.composite + ? discrepancyExplanation + : undefined, }, { caption: "Fix error and emit", @@ -238,9 +249,9 @@ const a: string = 10;`, caption: "Fix error and no emit", commandLineArgs: ["--p", "src/project", "--noEmit"], edit: fs => replaceText(fs, "/src/project/src/class.ts", "prop1", "prop"), - discrepancyExplanation: compilerOptions.composite ? - discrepancyExplanation : - undefined, + discrepancyExplanation: compilerOptions.composite + ? discrepancyExplanation + : undefined, }, noChangeRunWithEmit, noChangeRunWithNoEmit, @@ -264,9 +275,9 @@ const a: string = 10;`, { caption: "Fix error and no emit", edit: fs => replaceText(fs, "/src/project/src/class.ts", "prop1", "prop"), - discrepancyExplanation: compilerOptions.composite ? - discrepancyExplanation : - undefined, + discrepancyExplanation: compilerOptions.composite + ? discrepancyExplanation + : undefined, }, noChangeRunWithEmit, ], @@ -348,7 +359,8 @@ const a: string = 10;`, }, { caption: "Write file that could not be resolved", - edit: fs => fs.writeFileSync(`/src/project/src/fileNotFound.ts`, "function something2() { return 20; }"), + edit: fs => + fs.writeFileSync(`/src/project/src/fileNotFound.ts`, "function something2() { return 20; }"), }, { caption: "Modify main file", @@ -382,7 +394,14 @@ declare global { "/src/project/node_modules/react/jsx-runtime.js": "export {}", // js needs to be present so there's a resolution result "/src/project/node_modules/@types/react/index.d.ts": getJsxLibraryContent(), // doesn't contain a jsx-runtime definition "/src/project/src/index.tsx": `export const App = () =>
;`, - "/src/project/tsconfig.json": JSON.stringify({ compilerOptions: { module: "commonjs", jsx: "react-jsx", incremental: true, jsxImportSource: "react" } }), + "/src/project/tsconfig.json": JSON.stringify({ + compilerOptions: { + module: "commonjs", + jsx: "react-jsx", + incremental: true, + jsxImportSource: "react", + }, + }), }), commandLineArgs: ["--p", "src/project"], }); @@ -395,7 +414,14 @@ declare global { "/src/project/node_modules/react/jsx-runtime.js": "export {}", // js needs to be present so there's a resolution result "/src/project/node_modules/@types/react/index.d.ts": getJsxLibraryContent(), // doesn't contain a jsx-runtime definition "/src/project/src/index.tsx": `export const App = () =>
;`, - "/src/project/tsconfig.json": JSON.stringify({ compilerOptions: { module: "commonjs", jsx: "react-jsx", incremental: true, jsxImportSource: "react" } }), + "/src/project/tsconfig.json": JSON.stringify({ + compilerOptions: { + module: "commonjs", + jsx: "react-jsx", + incremental: true, + jsxImportSource: "react", + }, + }), }), commandLineArgs: ["--p", "src/project", "--strict"], }); @@ -584,7 +610,9 @@ console.log(a);`, function verifyModifierChange(declaration: boolean) { verifyTsc({ scenario: "incremental", - subScenario: `change to modifier of class expression field${declaration ? " with declaration emit enabled" : ""}`, + subScenario: `change to modifier of class expression field${ + declaration ? " with declaration emit enabled" : "" + }`, commandLineArgs: ["-p", "src/project", "--incremental"], fs: () => loadProjectFromFiles({ @@ -779,7 +807,10 @@ console.log(a);`, noChangeRun, withOptionChange("with declaration and declarationMap", "--declaration", "--declarationMap"), noChangeWithSubscenario("should re-emit only dts so they dont contain sourcemap"), - withOptionChangeAndDiscrepancyExplanation("with emitDeclarationOnly should not emit anything", "--emitDeclarationOnly"), + withOptionChangeAndDiscrepancyExplanation( + "with emitDeclarationOnly should not emit anything", + "--emitDeclarationOnly", + ), noChangeRun, localChange(), withOptionChangeAndDiscrepancyExplanation("with declaration should not emit anything", "--declaration"), @@ -802,7 +833,9 @@ console.log(a);`, noChangeRun, withOptionChange("with declaration and declarationMap", "--declaration", "--declarationMap"), noChangeWithSubscenario("should re-emit only dts so they dont contain sourcemap"), - withEmitDeclarationOnlyChangeAndDiscrepancyExplanation("with emitDeclarationOnly should not emit anything"), + withEmitDeclarationOnlyChangeAndDiscrepancyExplanation( + "with emitDeclarationOnly should not emit anything", + ), noChangeRun, localChange(), withOptionChangeAndDiscrepancyExplanation("with declaration should not emit anything", "--declaration"), @@ -831,7 +864,11 @@ console.log(a);`, withOptionChange("with sourceMap", "--sourceMap"), noChangeWithSubscenario("emit js files"), withOptionChange("with declaration and declarationMap", "--declaration", "--declarationMap"), - withOptionChange("with declaration and declarationMap, should not re-emit", "--declaration", "--declarationMap"), + withOptionChange( + "with declaration and declarationMap, should not re-emit", + "--declaration", + "--declarationMap", + ), ], baselinePrograms: true, }); @@ -853,7 +890,11 @@ console.log(a);`, withOptionChange("with sourceMap", "--sourceMap"), noChangeWithSubscenario("emit js files"), withOptionChange("with declaration and declarationMap", "--declaration", "--declarationMap"), - withOptionChange("with declaration and declarationMap, should not re-emit", "--declaration", "--declarationMap"), + withOptionChange( + "with declaration and declarationMap, should not re-emit", + "--declaration", + "--declarationMap", + ), ], baselinePrograms: true, }); diff --git a/src/testRunner/unittests/tsc/moduleResolution.ts b/src/testRunner/unittests/tsc/moduleResolution.ts index 0ff875796ccc6..4e235aec14c24 100644 --- a/src/testRunner/unittests/tsc/moduleResolution.ts +++ b/src/testRunner/unittests/tsc/moduleResolution.ts @@ -29,27 +29,51 @@ describe("unittests:: tsc:: moduleResolution::", () => { }, { caption: "add the node10Result in @types", - edit: fs => fs.writeFileSync("/home/src/projects/project/node_modules/@types/bar/index.d.ts", getFsContentsForNode10ResultDts("bar")), + edit: fs => + fs.writeFileSync( + "/home/src/projects/project/node_modules/@types/bar/index.d.ts", + getFsContentsForNode10ResultDts("bar"), + ), }, { caption: "add the ndoe10Result in package/types", - edit: fs => fs.writeFileSync("/home/src/projects/project/node_modules/foo/index.d.ts", getFsContentsForNode10ResultDts("foo")), + edit: fs => + fs.writeFileSync( + "/home/src/projects/project/node_modules/foo/index.d.ts", + getFsContentsForNode10ResultDts("foo"), + ), }, { caption: "update package.json from @types so error is fixed", - edit: fs => fs.writeFileSync("/home/src/projects/project/node_modules/@types/bar/package.json", getFsConentsForNode10ResultAtTypesPackageJson("bar", /*addTypesCondition*/ true)), + edit: fs => + fs.writeFileSync( + "/home/src/projects/project/node_modules/@types/bar/package.json", + getFsConentsForNode10ResultAtTypesPackageJson("bar", /*addTypesCondition*/ true), + ), }, { caption: "update package.json so error is fixed", - edit: fs => fs.writeFileSync("/home/src/projects/project/node_modules/foo/package.json", getFsContentsForNode10ResultPackageJson("foo", /*addTypes*/ true, /*addTypesCondition*/ true)), + edit: fs => + fs.writeFileSync( + "/home/src/projects/project/node_modules/foo/package.json", + getFsContentsForNode10ResultPackageJson("foo", /*addTypes*/ true, /*addTypesCondition*/ true), + ), }, { caption: "update package.json from @types so error is introduced", - edit: fs => fs.writeFileSync("/home/src/projects/project/node_modules/@types/bar2/package.json", getFsConentsForNode10ResultAtTypesPackageJson("bar2", /*addTypesCondition*/ false)), + edit: fs => + fs.writeFileSync( + "/home/src/projects/project/node_modules/@types/bar2/package.json", + getFsConentsForNode10ResultAtTypesPackageJson("bar2", /*addTypesCondition*/ false), + ), }, { caption: "update package.json so error is introduced", - edit: fs => fs.writeFileSync("/home/src/projects/project/node_modules/foo2/package.json", getFsContentsForNode10ResultPackageJson("foo2", /*addTypes*/ true, /*addTypesCondition*/ false)), + edit: fs => + fs.writeFileSync( + "/home/src/projects/project/node_modules/foo2/package.json", + getFsContentsForNode10ResultPackageJson("foo2", /*addTypes*/ true, /*addTypesCondition*/ false), + ), }, { caption: "delete the node10Result in @types", @@ -61,11 +85,19 @@ describe("unittests:: tsc:: moduleResolution::", () => { }, { caption: "add the node10Result in @types", - edit: fs => fs.writeFileSync("/home/src/projects/project/node_modules/@types/bar2/index.d.ts", getFsContentsForNode10ResultDts("bar2")), + edit: fs => + fs.writeFileSync( + "/home/src/projects/project/node_modules/@types/bar2/index.d.ts", + getFsContentsForNode10ResultDts("bar2"), + ), }, { caption: "add the ndoe10Result in package/types", - edit: fs => fs.writeFileSync("/home/src/projects/project/node_modules/foo2/index.d.ts", getFsContentsForNode10ResultDts("foo2")), + edit: fs => + fs.writeFileSync( + "/home/src/projects/project/node_modules/foo2/index.d.ts", + getFsContentsForNode10ResultDts("foo2"), + ), }, ], }); diff --git a/src/testRunner/unittests/tsc/runWithoutArgs.ts b/src/testRunner/unittests/tsc/runWithoutArgs.ts index d92f526aaf39d..5947dd1c99f7f 100644 --- a/src/testRunner/unittests/tsc/runWithoutArgs.ts +++ b/src/testRunner/unittests/tsc/runWithoutArgs.ts @@ -16,7 +16,8 @@ describe("unittests:: tsc:: runWithoutArgs::", () => { verifyTsc({ scenario: "runWithoutArgs", - subScenario: "show help with ExitStatus.DiagnosticsPresent_OutputsSkipped when host can't provide terminal width", + subScenario: + "show help with ExitStatus.DiagnosticsPresent_OutputsSkipped when host can't provide terminal width", fs: () => loadProjectFromFiles({}), commandLineArgs: [], }); diff --git a/src/testRunner/unittests/tscWatch/consoleClearing.ts b/src/testRunner/unittests/tscWatch/consoleClearing.ts index 60d1cb0e9690e..8e233fc15f820 100644 --- a/src/testRunner/unittests/tscWatch/consoleClearing.ts +++ b/src/testRunner/unittests/tscWatch/consoleClearing.ts @@ -69,7 +69,8 @@ describe("unittests:: tsc-watch:: console clearing", () => { }); verifyTscWatch({ scenario, - subScenario: "when preserveWatchOutput is true in config file/when createWatchProgram is invoked with configFileParseResult on WatchCompilerHostOfConfigFile", + subScenario: + "when preserveWatchOutput is true in config file/when createWatchProgram is invoked with configFileParseResult on WatchCompilerHostOfConfigFile", commandLineArgs: ["--w", "-p", configFile.path], sys: () => createWatchedSystem(files), edits: makeChangeToFile, diff --git a/src/testRunner/unittests/tscWatch/emit.ts b/src/testRunner/unittests/tscWatch/emit.ts index f2866743888f9..2c370e7044515 100644 --- a/src/testRunner/unittests/tscWatch/emit.ts +++ b/src/testRunner/unittests/tscWatch/emit.ts @@ -50,11 +50,13 @@ describe("unittests:: tsc-watch:: emit with outFile or out setting", () => { sys: () => { const file1: File = { path: "/a/b/output/AnotherDependency/file1.d.ts", - content: "declare namespace Common.SomeComponent.DynamicMenu { enum Z { Full = 0, Min = 1, Average = 2, } }", + content: + "declare namespace Common.SomeComponent.DynamicMenu { enum Z { Full = 0, Min = 1, Average = 2, } }", }; const file2: File = { path: "/a/b/dependencies/file2.d.ts", - content: "declare namespace Dependencies.SomeComponent { export class SomeClass { version: string; } }", + content: + "declare namespace Dependencies.SomeComponent { export class SomeClass { version: string; } }", }; const file3: File = { path: "/a/b/project/src/main.ts", @@ -62,14 +64,15 @@ describe("unittests:: tsc-watch:: emit with outFile or out setting", () => { }; const file4: File = { path: "/a/b/project/src/main2.ts", - content: "namespace main.file4 { import DynamicMenu = Common.SomeComponent.DynamicMenu; export function foo(a: DynamicMenu.z) { } }", + content: + "namespace main.file4 { import DynamicMenu = Common.SomeComponent.DynamicMenu; export function foo(a: DynamicMenu.z) { } }", }; const configFile: File = { path: "/a/b/project/tsconfig.json", content: JSON.stringify({ - compilerOptions: useOutFile ? - { outFile: "../output/common.js", target: "es5" } : - { outDir: "../output", target: "es5" }, + compilerOptions: useOutFile + ? { outFile: "../output/common.js", target: "es5" } + : { outDir: "../output", target: "es5" }, files: [file1.path, file2.path, file3.path, file4.path], }), }; @@ -139,11 +142,20 @@ describe("unittests:: tsc-watch:: emit for configured projects", () => { content: JSON.stringify(configObj || {}), }; const additionalFiles = getAdditionalFileOrFolder?.() || ts.emptyArray; - const files = [moduleFile1, file1Consumer1, file1Consumer2, globalFile3, moduleFile2, configFile, libFile, ...additionalFiles]; + const files = [ + moduleFile1, + file1Consumer1, + file1Consumer2, + globalFile3, + moduleFile2, + configFile, + libFile, + ...additionalFiles, + ]; return createWatchedSystem( - firstReloadFileList ? - ts.map(firstReloadFileList, fileName => ts.find(files, file => file.path === fileName)!) : - files, + firstReloadFileList + ? ts.map(firstReloadFileList, fileName => ts.find(files, file => file.path === fileName)!) + : files, ); }, edits: changes, @@ -160,12 +172,18 @@ describe("unittests:: tsc-watch:: emit for configured projects", () => { }; verifyTscWatchEmit({ - subScenario: "should contains only itself if a module file's shape didn't change, and all files referencing it if its shape changed", + subScenario: + "should contains only itself if a module file's shape didn't change, and all files referencing it if its shape changed", changes: [ changeModuleFile1Shape, { - caption: "Change the content of moduleFile1 to `export var T: number;export function Foo() { console.log('hi'); };`", - edit: sys => sys.writeFile(moduleFile1Path, `export var T: number;export function Foo() { console.log('hi'); };`), + caption: + "Change the content of moduleFile1 to `export var T: number;export function Foo() { console.log('hi'); };`", + edit: sys => + sys.writeFile( + moduleFile1Path, + `export var T: number;export function Foo() { console.log('hi'); };`, + ), timeouts: sys => sys.runQueuedTimeoutCallbacks(), }, ], @@ -186,7 +204,8 @@ describe("unittests:: tsc-watch:: emit for configured projects", () => { timeouts: sys => sys.runQueuedTimeoutCallbacks(), }, { - caption: "Change the content of moduleFile1 to `export var T: number;export var T2: string;export function Foo() { };`", + caption: + "Change the content of moduleFile1 to `export var T: number;export var T2: string;export function Foo() { };`", edit: sys => sys.writeFile(moduleFile1Path, `export let y = Foo();`), timeouts: sys => sys.runQueuedTimeoutCallbacks(), }, @@ -451,7 +470,8 @@ describe("unittests:: tsc-watch:: emit file content", () => { edits: [ { caption: "Append content to file3", - edit: sys => sys.appendFile("/user/someone/projects/myproject/file3.ts", "function foo2() { return 2; }"), + edit: sys => + sys.appendFile("/user/someone/projects/myproject/file3.ts", "function foo2() { return 2; }"), timeouts: sys => sys.runQueuedTimeoutCallbacks(), }, ], @@ -481,7 +501,10 @@ describe("unittests:: tsc-watch:: emit file content", () => { edits: [ { caption: "file is deleted and then created to modify content", - edit: sys => sys.appendFile("/home/username/project/app/file.ts", "\nvar b = 10;", { invokeFileDeleteCreateAsPartInsteadOfChange: true }), + edit: sys => + sys.appendFile("/home/username/project/app/file.ts", "\nvar b = 10;", { + invokeFileDeleteCreateAsPartInsteadOfChange: true, + }), timeouts: sys => sys.runQueuedTimeoutCallbacks(), }, ], @@ -491,7 +514,8 @@ describe("unittests:: tsc-watch:: emit file content", () => { describe("unittests:: tsc-watch:: emit with when module emit is specified as node", () => { verifyTscWatch({ scenario, - subScenario: "when module emit is specified as node/when instead of filechanged recursive directory watcher is invoked", + subScenario: + "when module emit is specified as node/when instead of filechanged recursive directory watcher is invoked", commandLineArgs: ["--w", "--p", "/a/rootFolder/project/tsconfig.json"], sys: () => { const configFile: File = { diff --git a/src/testRunner/unittests/tscWatch/emitAndErrorUpdates.ts b/src/testRunner/unittests/tscWatch/emitAndErrorUpdates.ts index f46e0db56b05e..f397acb5c8a67 100644 --- a/src/testRunner/unittests/tscWatch/emitAndErrorUpdates.ts +++ b/src/testRunner/unittests/tscWatch/emitAndErrorUpdates.ts @@ -299,21 +299,34 @@ export class Data { function verifyTransitiveExports(subScenario: string, files: readonly File[]) { verifyEmitAndErrorUpdates({ subScenario: `transitive exports/${subScenario}`, - files: () => [lib1ToolsInterface, lib1ToolsPublic, app, lib2Public, lib1Public, ...files, config, libFile], + files: + () => [lib1ToolsInterface, lib1ToolsPublic, app, lib2Public, lib1Public, ...files, config, libFile], changes: [ { caption: "Rename property title to title2 of interface ITest to initialize signatures", - edit: sys => sys.writeFile(lib1ToolsInterface.path, lib1ToolsInterface.content.replace("title", "title2")), + edit: sys => + sys.writeFile( + lib1ToolsInterface.path, + lib1ToolsInterface.content.replace("title", "title2"), + ), timeouts: sys => sys.runQueuedTimeoutCallbacks(), }, { caption: "Rename property title2 to title of interface ITest to revert back to original text", - edit: sys => sys.writeFile(lib1ToolsInterface.path, lib1ToolsInterface.content.replace("title2", "title")), + edit: sys => + sys.writeFile( + lib1ToolsInterface.path, + lib1ToolsInterface.content.replace("title2", "title"), + ), timeouts: sys => sys.runQueuedTimeoutCallbacks(), }, { caption: "Rename property title to title2 of interface ITest", - edit: sys => sys.writeFile(lib1ToolsInterface.path, lib1ToolsInterface.content.replace("title", "title2")), + edit: sys => + sys.writeFile( + lib1ToolsInterface.path, + lib1ToolsInterface.content.replace("title", "title2"), + ), timeouts: sys => sys.runQueuedTimeoutCallbacks(), }, ], @@ -363,7 +376,11 @@ export class Data2 { } const noChange: TscWatchCompileChange = { caption: "No change", - edit: sys => sys.writeFile(`/user/username/projects/noEmitOnError/src/main.ts`, sys.readFile(`/user/username/projects/noEmitOnError/src/main.ts`)!), + edit: sys => + sys.writeFile( + `/user/username/projects/noEmitOnError/src/main.ts`, + sys.readFile(`/user/username/projects/noEmitOnError/src/main.ts`)!, + ), // build project timeouts: sys => sys.runQueuedTimeoutCallbacks(), }; @@ -372,7 +389,10 @@ export class Data2 { currentDirectory: `/user/username/projects/noEmitOnError`, files: () => ["shared/types/db.ts", "src/main.ts", "src/other.ts", "tsconfig.json"] - .map(f => getTsBuildProjectFile("noEmitOnError", f)).concat({ path: libFile.path, content: libContent }), + .map(f => getTsBuildProjectFile("noEmitOnError", f)).concat({ + path: libFile.path, + content: libContent, + }), changes: [ noChange, change( diff --git a/src/testRunner/unittests/tscWatch/forceConsistentCasingInFileNames.ts b/src/testRunner/unittests/tscWatch/forceConsistentCasingInFileNames.ts index a1b5de3e42c38..303b7c5f0cea5 100644 --- a/src/testRunner/unittests/tscWatch/forceConsistentCasingInFileNames.ts +++ b/src/testRunner/unittests/tscWatch/forceConsistentCasingInFileNames.ts @@ -26,7 +26,9 @@ describe("unittests:: tsc-watch:: forceConsistentCasingInFileNames", () => { }), }; - function verifyConsistentFileNames({ subScenario, changes }: { subScenario: string; changes: TscWatchCompileChange[]; }) { + function verifyConsistentFileNames( + { subScenario, changes }: { subScenario: string; changes: TscWatchCompileChange[]; }, + ) { verifyTscWatch({ scenario: "forceConsistentCasingInFileNames", subScenario, @@ -79,7 +81,9 @@ describe("unittests:: tsc-watch:: forceConsistentCasingInFileNames", () => { path: `/user/username/projects/myproject/tsconfig.json`, content: JSON.stringify({ compilerOptions: { forceConsistentCasingInFileNames: true } }), }; - return createWatchedSystem([moduleA, moduleB, moduleC, libFile, tsconfig], { currentDirectory: "/user/username/projects/myproject" }); + return createWatchedSystem([moduleA, moduleB, moduleC, libFile, tsconfig], { + currentDirectory: "/user/username/projects/myproject", + }); }, edits: [ { @@ -128,7 +132,11 @@ export const Fragment: unique symbol; { path: `/user/username/projects/myproject/tsconfig.json`, content: JSON.stringify({ - compilerOptions: { jsx: "react-jsx", jsxImportSource: "react", forceConsistentCasingInFileNames: true }, + compilerOptions: { + jsx: "react-jsx", + jsxImportSource: "react", + forceConsistentCasingInFileNames: true, + }, files: ["node_modules/react/Jsx-Runtime/index.d.ts", "index.tsx"], }), }, @@ -161,7 +169,10 @@ a;b; path: `${windowsStyleRoot}/${projectRootRelative}/tsconfig.json`, content: JSON.stringify({ compilerOptions: { forceConsistentCasingInFileNames: true } }), }; - return createWatchedSystem([moduleA, moduleB, libFile, tsconfig], { windowsStyleRoot, useCaseSensitiveFileNames: false }); + return createWatchedSystem([moduleA, moduleB, libFile, tsconfig], { + windowsStyleRoot, + useCaseSensitiveFileNames: false, + }); }, edits: [ { @@ -211,7 +222,9 @@ a;b; path: `/user/username/projects/myproject/tsconfig.json`, content: JSON.stringify({ compilerOptions: { forceConsistentCasingInFileNames: true } }), }; - return createWatchedSystem([moduleA, symlinkA, moduleB, libFile, tsconfig], { currentDirectory: "/user/username/projects/myproject" }); + return createWatchedSystem([moduleA, symlinkA, moduleB, libFile, tsconfig], { + currentDirectory: "/user/username/projects/myproject", + }); }, edits: [ { @@ -228,11 +241,36 @@ a;b; }); } - verifyFileSymlink("when both file symlink target and import match disk", `/user/username/projects/myproject/XY.ts`, `/user/username/projects/myproject/XY.ts`, `./XY`); - verifyFileSymlink("when file symlink target matches disk but import does not", `/user/username/projects/myproject/XY.ts`, `/user/username/projects/myproject/Xy.ts`, `./XY`); - verifyFileSymlink("when import matches disk but file symlink target does not", `/user/username/projects/myproject/XY.ts`, `/user/username/projects/myproject/XY.ts`, `./Xy`); - verifyFileSymlink("when import and file symlink target agree but do not match disk", `/user/username/projects/myproject/XY.ts`, `/user/username/projects/myproject/Xy.ts`, `./Xy`); - verifyFileSymlink("when import, file symlink target, and disk are all different", `/user/username/projects/myproject/XY.ts`, `/user/username/projects/myproject/Xy.ts`, `./yX`); + verifyFileSymlink( + "when both file symlink target and import match disk", + `/user/username/projects/myproject/XY.ts`, + `/user/username/projects/myproject/XY.ts`, + `./XY`, + ); + verifyFileSymlink( + "when file symlink target matches disk but import does not", + `/user/username/projects/myproject/XY.ts`, + `/user/username/projects/myproject/Xy.ts`, + `./XY`, + ); + verifyFileSymlink( + "when import matches disk but file symlink target does not", + `/user/username/projects/myproject/XY.ts`, + `/user/username/projects/myproject/XY.ts`, + `./Xy`, + ); + verifyFileSymlink( + "when import and file symlink target agree but do not match disk", + `/user/username/projects/myproject/XY.ts`, + `/user/username/projects/myproject/Xy.ts`, + `./Xy`, + ); + verifyFileSymlink( + "when import, file symlink target, and disk are all different", + `/user/username/projects/myproject/XY.ts`, + `/user/username/projects/myproject/Xy.ts`, + `./yX`, + ); function verifyDirSymlink(subScenario: string, diskPath: string, targetPath: string, importedPath: string) { verifyTscWatch({ @@ -263,9 +301,17 @@ a;b; const tsconfig: File = { path: `/user/username/projects/myproject/tsconfig.json`, // Use outFile because otherwise the real and linked files will have the same output path - content: JSON.stringify({ compilerOptions: { forceConsistentCasingInFileNames: true, outFile: "out.js", module: "system" } }), + content: JSON.stringify({ + compilerOptions: { + forceConsistentCasingInFileNames: true, + outFile: "out.js", + module: "system", + }, + }), }; - return createWatchedSystem([moduleA, symlinkA, moduleB, libFile, tsconfig], { currentDirectory: "/user/username/projects/myproject" }); + return createWatchedSystem([moduleA, symlinkA, moduleB, libFile, tsconfig], { + currentDirectory: "/user/username/projects/myproject", + }); }, edits: [ { @@ -282,11 +328,36 @@ a;b; }); } - verifyDirSymlink("when both directory symlink target and import match disk", `/user/username/projects/myproject/XY`, `/user/username/projects/myproject/XY`, `./XY`); - verifyDirSymlink("when directory symlink target matches disk but import does not", `/user/username/projects/myproject/XY`, `/user/username/projects/myproject/Xy`, `./XY`); - verifyDirSymlink("when import matches disk but directory symlink target does not", `/user/username/projects/myproject/XY`, `/user/username/projects/myproject/XY`, `./Xy`); - verifyDirSymlink("when import and directory symlink target agree but do not match disk", `/user/username/projects/myproject/XY`, `/user/username/projects/myproject/Xy`, `./Xy`); - verifyDirSymlink("when import, directory symlink target, and disk are all different", `/user/username/projects/myproject/XY`, `/user/username/projects/myproject/Xy`, `./yX`); + verifyDirSymlink( + "when both directory symlink target and import match disk", + `/user/username/projects/myproject/XY`, + `/user/username/projects/myproject/XY`, + `./XY`, + ); + verifyDirSymlink( + "when directory symlink target matches disk but import does not", + `/user/username/projects/myproject/XY`, + `/user/username/projects/myproject/Xy`, + `./XY`, + ); + verifyDirSymlink( + "when import matches disk but directory symlink target does not", + `/user/username/projects/myproject/XY`, + `/user/username/projects/myproject/XY`, + `./Xy`, + ); + verifyDirSymlink( + "when import and directory symlink target agree but do not match disk", + `/user/username/projects/myproject/XY`, + `/user/username/projects/myproject/Xy`, + `./Xy`, + ); + verifyDirSymlink( + "when import, directory symlink target, and disk are all different", + `/user/username/projects/myproject/XY`, + `/user/username/projects/myproject/Xy`, + `./yX`, + ); verifyTscWatch({ scenario: "forceConsistentCasingInFileNames", diff --git a/src/testRunner/unittests/tscWatch/incremental.ts b/src/testRunner/unittests/tscWatch/incremental.ts index c2218d1ae6037..0d119bde3968e 100644 --- a/src/testRunner/unittests/tscWatch/incremental.ts +++ b/src/testRunner/unittests/tscWatch/incremental.ts @@ -49,7 +49,9 @@ describe("unittests:: tsc-watch:: emit file --incremental", () => { { subScenario, files, optionsToExtend, modifyFs }: VerifyIncrementalWatchEmitInput, incremental: boolean, ) { - const { sys, baseline, oldSnap, cb, getPrograms } = createBaseline(createWatchedSystem(files(), { currentDirectory: project })); + const { sys, baseline, oldSnap, cb, getPrograms } = createBaseline( + createWatchedSystem(files(), { currentDirectory: project }), + ); if (incremental) sys.exit = exitCode => sys.exitCode = exitCode; const argsToPass = [incremental ? "-i" : "-w", ...(optionsToExtend || ts.emptyArray)]; baseline.push(`${sys.getExecutingFilePath()} ${argsToPass.join(" ")}`); @@ -61,7 +63,12 @@ describe("unittests:: tsc-watch:: emit file --incremental", () => { build(oldSnap); } - Harness.Baseline.runBaseline(`${ts.isBuild(argsToPass) ? "tsbuild/watchMode" : "tscWatch"}/incremental/${subScenario.split(" ").join("-")}-${incremental ? "incremental" : "watch"}.js`, baseline.join("\r\n")); + Harness.Baseline.runBaseline( + `${ts.isBuild(argsToPass) ? "tsbuild/watchMode" : "tscWatch"}/incremental/${ + subScenario.split(" ").join("-") + }-${incremental ? "incremental" : "watch"}.js`, + baseline.join("\r\n"), + ); function build(oldSnap: SystemSnap) { const closer = ts.executeCommandLine( @@ -154,9 +161,18 @@ describe("unittests:: tsc-watch:: emit file --incremental", () => { }); it("verify that state is read correctly", () => { - const system = createWatchedSystem([libFile, file1, fileModified, config], { currentDirectory: project }); + const system = createWatchedSystem([libFile, file1, fileModified, config], { + currentDirectory: project, + }); const reportDiagnostic = ts.createDiagnosticReporter(system); - const parsedConfig = ts.parseConfigFileWithSystem("tsconfig.json", {}, /*extendedConfigCache*/ undefined, /*watchOptionsToExtend*/ undefined, system, reportDiagnostic)!; + const parsedConfig = ts.parseConfigFileWithSystem( + "tsconfig.json", + {}, + /*extendedConfigCache*/ undefined, + /*watchOptionsToExtend*/ undefined, + system, + reportDiagnostic, + )!; ts.performIncrementalCompilation({ rootNames: parsedConfig.fileNames, options: parsedConfig.options, @@ -166,7 +182,14 @@ describe("unittests:: tsc-watch:: emit file --incremental", () => { system, }); - const command = ts.parseConfigFileWithSystem("tsconfig.json", {}, /*extendedConfigCache*/ undefined, /*watchOptionsToExtend*/ undefined, system, ts.noop)!; + const command = ts.parseConfigFileWithSystem( + "tsconfig.json", + {}, + /*extendedConfigCache*/ undefined, + /*watchOptionsToExtend*/ undefined, + system, + ts.noop, + )!; const builderProgram = ts.createIncrementalProgram({ rootNames: command.fileNames, options: command.options, @@ -307,7 +330,12 @@ export interface A { }); describe("with option jsxImportSource", () => { - const jsxImportSourceOptions = { module: "commonjs", jsx: "react-jsx", incremental: true, jsxImportSource: "react" }; + const jsxImportSourceOptions = { + module: "commonjs", + jsx: "react-jsx", + incremental: true, + jsxImportSource: "react", + }; const jsxLibraryContent = `export namespace JSX { interface Element {} interface IntrinsicElements { @@ -326,13 +354,26 @@ export const Fragment: unique symbol; files: () => [ { path: libFile.path, content: libContent }, { path: `${project}/node_modules/react/jsx-runtime/index.d.ts`, content: jsxLibraryContent }, - { path: `${project}/node_modules/react/package.json`, content: JSON.stringify({ name: "react", version: "0.0.1" }) }, - { path: `${project}/node_modules/preact/jsx-runtime/index.d.ts`, content: jsxLibraryContent.replace("propA", "propB") }, - { path: `${project}/node_modules/preact/package.json`, content: JSON.stringify({ name: "preact", version: "0.0.1" }) }, + { + path: `${project}/node_modules/react/package.json`, + content: JSON.stringify({ name: "react", version: "0.0.1" }), + }, + { + path: `${project}/node_modules/preact/jsx-runtime/index.d.ts`, + content: jsxLibraryContent.replace("propA", "propB"), + }, + { + path: `${project}/node_modules/preact/package.json`, + content: JSON.stringify({ name: "preact", version: "0.0.1" }), + }, { path: `${project}/index.tsx`, content: `export const App = () =>
;` }, { path: configFile.path, content: JSON.stringify({ compilerOptions: jsxImportSourceOptions }) }, ], - modifyFs: host => host.writeFile(configFile.path, JSON.stringify({ compilerOptions: { ...jsxImportSourceOptions, jsxImportSource: "preact" } })), + modifyFs: host => + host.writeFile( + configFile.path, + JSON.stringify({ compilerOptions: { ...jsxImportSourceOptions, jsxImportSource: "preact" } }), + ), optionsToExtend: ["--explainFiles"], }); @@ -348,7 +389,10 @@ export const Fragment: unique symbol; host.createDirectory(`${project}/node_modules/react`); host.createDirectory(`${project}/node_modules/react/jsx-runtime`); host.writeFile(`${project}/node_modules/react/jsx-runtime/index.d.ts`, jsxLibraryContent); - host.writeFile(`${project}/node_modules/react/package.json`, JSON.stringify({ name: "react", version: "0.0.1" })); + host.writeFile( + `${project}/node_modules/react/package.json`, + JSON.stringify({ name: "react", version: "0.0.1" }), + ); }, }); @@ -357,7 +401,10 @@ export const Fragment: unique symbol; files: () => [ { path: libFile.path, content: libContent }, { path: `${project}/node_modules/react/jsx-runtime/index.d.ts`, content: jsxLibraryContent }, - { path: `${project}/node_modules/react/package.json`, content: JSON.stringify({ name: "react", version: "0.0.1" }) }, + { + path: `${project}/node_modules/react/package.json`, + content: JSON.stringify({ name: "react", version: "0.0.1" }), + }, { path: `${project}/index.tsx`, content: `export const App = () =>
;` }, { path: configFile.path, content: JSON.stringify({ compilerOptions: jsxImportSourceOptions }) }, ], @@ -371,8 +418,14 @@ export const Fragment: unique symbol; subScenario: "importHelpers backing types removed", files: () => [ { path: libFile.path, content: libContent }, - { path: `${project}/node_modules/tslib/index.d.ts`, content: "export function __assign(...args: any[]): any;" }, - { path: `${project}/node_modules/tslib/package.json`, content: JSON.stringify({ name: "tslib", version: "0.0.1" }) }, + { + path: `${project}/node_modules/tslib/index.d.ts`, + content: "export function __assign(...args: any[]): any;", + }, + { + path: `${project}/node_modules/tslib/package.json`, + content: JSON.stringify({ name: "tslib", version: "0.0.1" }), + }, { path: `${project}/index.tsx`, content: `export const x = {...{}};` }, { path: configFile.path, content: JSON.stringify({ compilerOptions: { importHelpers: true } }) }, ], @@ -388,14 +441,26 @@ export const Fragment: unique symbol; subScenario: "editing module augmentation", files: () => [ { path: libFile.path, content: libContent }, - { path: `${project}/node_modules/classnames/index.d.ts`, content: `export interface Result {} export default function classNames(): Result;` }, - { path: `${project}/src/types/classnames.d.ts`, content: `export {}; declare module "classnames" { interface Result { foo } }` }, + { + path: `${project}/node_modules/classnames/index.d.ts`, + content: `export interface Result {} export default function classNames(): Result;`, + }, + { + path: `${project}/src/types/classnames.d.ts`, + content: `export {}; declare module "classnames" { interface Result { foo } }`, + }, { path: `${project}/src/index.ts`, content: `import classNames from "classnames"; classNames().foo;` }, - { path: configFile.path, content: JSON.stringify({ compilerOptions: { module: "commonjs", incremental: true } }) }, + { + path: configFile.path, + content: JSON.stringify({ compilerOptions: { module: "commonjs", incremental: true } }), + }, ], modifyFs: host => { // delete 'foo' - host.writeFile(`${project}/src/types/classnames.d.ts`, `export {}; declare module "classnames" { interface Result {} }`); + host.writeFile( + `${project}/src/types/classnames.d.ts`, + `export {}; declare module "classnames" { interface Result {} }`, + ); }, }); }); diff --git a/src/testRunner/unittests/tscWatch/libraryResolution.ts b/src/testRunner/unittests/tscWatch/libraryResolution.ts index fe6e1447b8fa7..5ef3f57a3ee0f 100644 --- a/src/testRunner/unittests/tscWatch/libraryResolution.ts +++ b/src/testRunner/unittests/tscWatch/libraryResolution.ts @@ -13,7 +13,10 @@ describe("unittests:: tsc-watch:: libraryResolution", () => { return ["-w", ...getCommandLineArgsForLibResolution(withoutConfig), "--extendedDiagnostics"]; } - function editOptions(withoutConfig: true | undefined, changeLib: (sys: TscWatchSystem) => void): TscWatchCompileChange[] { + function editOptions( + withoutConfig: true | undefined, + changeLib: (sys: TscWatchSystem) => void, + ): TscWatchCompileChange[] { return withoutConfig ? [] : [ { caption: "change program options to update module resolution", @@ -60,7 +63,11 @@ describe("unittests:: tsc-watch:: libraryResolution", () => { edits: [ { caption: "write redirect file dom", - edit: sys => sys.ensureFileOrFolder({ path: "/home/src/projects/node_modules/@typescript/lib-dom/index.d.ts", content: "interface DOMInterface { }" }), + edit: sys => + sys.ensureFileOrFolder({ + path: "/home/src/projects/node_modules/@typescript/lib-dom/index.d.ts", + content: "interface DOMInterface { }", + }), timeouts: sys => { sys.runQueuedTimeoutCallbacks(); sys.runQueuedTimeoutCallbacks(); @@ -81,10 +88,21 @@ describe("unittests:: tsc-watch:: libraryResolution", () => { edit: sys => sys.deleteFile("/home/src/projects/node_modules/@typescript/lib-dom/index.d.ts"), timeouts: sys => sys.runQueuedTimeoutCallbacks(), }, - ...editOptions(withoutConfig, sys => sys.ensureFileOrFolder({ path: "/home/src/projects/node_modules/@typescript/lib-dom/index.d.ts", content: "interface DOMInterface { }" })), + ...editOptions( + withoutConfig, + sys => + sys.ensureFileOrFolder({ + path: "/home/src/projects/node_modules/@typescript/lib-dom/index.d.ts", + content: "interface DOMInterface { }", + }), + ), { caption: "write redirect file webworker", - edit: sys => sys.ensureFileOrFolder({ path: "/home/src/projects/node_modules/@typescript/lib-webworker/index.d.ts", content: "interface WebworkerInterface { }" }), + edit: sys => + sys.ensureFileOrFolder({ + path: "/home/src/projects/node_modules/@typescript/lib-webworker/index.d.ts", + content: "interface WebworkerInterface { }", + }), timeouts: sys => { sys.runQueuedTimeoutCallbacks(); sys.runQueuedTimeoutCallbacks(); @@ -121,13 +139,20 @@ describe("unittests:: tsc-watch:: libraryResolution", () => { }, { caption: "write redirect file dom", - edit: sys => sys.ensureFileOrFolder({ path: "/home/src/projects/node_modules/@typescript/lib-dom/index.d.ts", content: "interface DOMInterface { }" }), + edit: sys => + sys.ensureFileOrFolder({ + path: "/home/src/projects/node_modules/@typescript/lib-dom/index.d.ts", + content: "interface DOMInterface { }", + }), timeouts: sys => { sys.runQueuedTimeoutCallbacks(); sys.runQueuedTimeoutCallbacks(); }, }, - ...editOptions(withoutConfig, sys => sys.deleteFile("/home/src/projects/node_modules/@typescript/lib-dom/index.d.ts")), + ...editOptions( + withoutConfig, + sys => sys.deleteFile("/home/src/projects/node_modules/@typescript/lib-dom/index.d.ts"), + ), { caption: "delete redirect file webworker", edit: sys => sys.deleteFile("/home/src/projects/node_modules/@typescript/lib-webworker/index.d.ts"), @@ -135,7 +160,11 @@ describe("unittests:: tsc-watch:: libraryResolution", () => { }, { caption: "write redirect file webworker", - edit: sys => sys.ensureFileOrFolder({ path: "/home/src/projects/node_modules/@typescript/lib-webworker/index.d.ts", content: "interface WebworkerInterface { }" }), + edit: sys => + sys.ensureFileOrFolder({ + path: "/home/src/projects/node_modules/@typescript/lib-webworker/index.d.ts", + content: "interface WebworkerInterface { }", + }), timeouts: sys => { sys.runQueuedTimeoutCallbacks(); sys.runQueuedTimeoutCallbacks(); diff --git a/src/testRunner/unittests/tscWatch/moduleResolution.ts b/src/testRunner/unittests/tscWatch/moduleResolution.ts index 10a7a86a1614b..d94617f22f77e 100644 --- a/src/testRunner/unittests/tscWatch/moduleResolution.ts +++ b/src/testRunner/unittests/tscWatch/moduleResolution.ts @@ -72,7 +72,12 @@ describe("unittests:: tsc-watch:: moduleResolution", () => { edits: [ { caption: "reports import errors after change to package file", - edit: sys => sys.replaceFileText(`/user/username/projects/myproject/packages/pkg2/package.json`, `index.js`, `other.js`), + edit: sys => + sys.replaceFileText( + `/user/username/projects/myproject/packages/pkg2/package.json`, + `index.js`, + `other.js`, + ), timeouts: sys => { sys.runQueuedTimeoutCallbacks(); // invalidates failed lookups sys.runQueuedTimeoutCallbacks(); // actual update @@ -80,7 +85,12 @@ describe("unittests:: tsc-watch:: moduleResolution", () => { }, { caption: "removes those errors when a package file is changed back", - edit: sys => sys.replaceFileText(`/user/username/projects/myproject/packages/pkg2/package.json`, `other.js`, `index.js`), + edit: sys => + sys.replaceFileText( + `/user/username/projects/myproject/packages/pkg2/package.json`, + `other.js`, + `index.js`, + ), timeouts: sys => { sys.runQueuedTimeoutCallbacks(); // invalidates failed lookups sys.runQueuedTimeoutCallbacks(); // actual update @@ -137,7 +147,8 @@ describe("unittests:: tsc-watch:: moduleResolution", () => { commandLineArgs: ["-w", "--traceResolution"], edits: [{ caption: "Add import to index2", - edit: sys => sys.prependFile(`/user/username/projects/myproject/index2.ts`, `import * as me from "./index.js";`), + edit: sys => + sys.prependFile(`/user/username/projects/myproject/index2.ts`, `import * as me from "./index.js";`), timeouts: sys => sys.runQueuedTimeoutCallbacks(), }], }); @@ -201,7 +212,11 @@ describe("unittests:: tsc-watch:: moduleResolution", () => { }, { caption: "Modify package.json file to remove type module", - edit: sys => sys.writeFile(`/user/username/projects/myproject/package.json`, JSON.stringify({ name: "app", version: "1.0.0" })), + edit: sys => + sys.writeFile( + `/user/username/projects/myproject/package.json`, + JSON.stringify({ name: "app", version: "1.0.0" }), + ), timeouts: host => { host.runQueuedTimeoutCallbacks(); // Failed lookup updates host.runQueuedTimeoutCallbacks(); // Actual update @@ -255,7 +270,11 @@ describe("unittests:: tsc-watch:: moduleResolution", () => { edits: [ { caption: "Modify package.json file to remove type module", - edit: sys => sys.writeFile(`/user/username/projects/myproject/package.json`, JSON.stringify({ name: "app", version: "1.0.0" })), + edit: sys => + sys.writeFile( + `/user/username/projects/myproject/package.json`, + JSON.stringify({ name: "app", version: "1.0.0" }), + ), timeouts: host => { host.runQueuedTimeoutCallbacks(); // Failed lookup updates host.runQueuedTimeoutCallbacks(); // Actual update @@ -287,7 +306,11 @@ describe("unittests:: tsc-watch:: moduleResolution", () => { }, { caption: "Modify package json file to without type module", - edit: sys => sys.writeFile(`/user/username/projects/myproject/package.json`, JSON.stringify({ name: "app", version: "1.0.0" })), + edit: sys => + sys.writeFile( + `/user/username/projects/myproject/package.json`, + JSON.stringify({ name: "app", version: "1.0.0" }), + ), timeouts: host => { host.runQueuedTimeoutCallbacks(); // Failed lookup updates host.runQueuedTimeoutCallbacks(); // Actual update @@ -370,7 +393,11 @@ describe("unittests:: tsc-watch:: moduleResolution", () => { edits: [ { caption: "modify aFile by adding import", - edit: sys => sys.appendFile(`/user/username/projects/myproject/a.ts`, `import type { ImportInterface } from "pkg" assert { "resolution-mode": "import" }`), + edit: sys => + sys.appendFile( + `/user/username/projects/myproject/a.ts`, + `import type { ImportInterface } from "pkg" assert { "resolution-mode": "import" }`, + ), timeouts: sys => sys.runQueuedTimeoutCallbacks(), }, ], @@ -460,7 +487,11 @@ describe("unittests:: tsc-watch:: moduleResolution", () => { edits: [ { caption: "modify aFile by adding import", - edit: sys => sys.prependFile(`/user/username/projects/myproject/a.ts`, `/// \n`), + edit: sys => + sys.prependFile( + `/user/username/projects/myproject/a.ts`, + `/// \n`, + ), timeouts: sys => sys.runQueuedTimeoutCallbacks(), }, ], @@ -469,7 +500,8 @@ describe("unittests:: tsc-watch:: moduleResolution", () => { verifyTscWatch({ scenario: "moduleResolution", subScenario: "node10Result", - sys: () => createWatchedSystem(getFsContentsForNode10Result(), { currentDirectory: "/home/src/projects/project" }), + sys: () => + createWatchedSystem(getFsContentsForNode10Result(), { currentDirectory: "/home/src/projects/project" }), commandLineArgs: ["-w", "--extendedDiagnostics"], edits: [ { @@ -490,7 +522,11 @@ describe("unittests:: tsc-watch:: moduleResolution", () => { }, { caption: "add the node10Result in @types", - edit: sys => sys.writeFile("/home/src/projects/project/node_modules/@types/bar/index.d.ts", getFsContentsForNode10ResultDts("bar")), + edit: sys => + sys.writeFile( + "/home/src/projects/project/node_modules/@types/bar/index.d.ts", + getFsContentsForNode10ResultDts("bar"), + ), timeouts: sys => { sys.runQueuedTimeoutCallbacks(); sys.runQueuedTimeoutCallbacks(); @@ -498,7 +534,11 @@ describe("unittests:: tsc-watch:: moduleResolution", () => { }, { caption: "add the ndoe10Result in package/types", - edit: sys => sys.writeFile("/home/src/projects/project/node_modules/foo/index.d.ts", getFsContentsForNode10ResultDts("foo")), + edit: sys => + sys.writeFile( + "/home/src/projects/project/node_modules/foo/index.d.ts", + getFsContentsForNode10ResultDts("foo"), + ), timeouts: sys => { sys.runQueuedTimeoutCallbacks(); sys.runQueuedTimeoutCallbacks(); @@ -506,7 +546,11 @@ describe("unittests:: tsc-watch:: moduleResolution", () => { }, { caption: "update package.json from @types so error is fixed", - edit: sys => sys.writeFile("/home/src/projects/project/node_modules/@types/bar/package.json", getFsConentsForNode10ResultAtTypesPackageJson("bar", /*addTypesCondition*/ true)), + edit: sys => + sys.writeFile( + "/home/src/projects/project/node_modules/@types/bar/package.json", + getFsConentsForNode10ResultAtTypesPackageJson("bar", /*addTypesCondition*/ true), + ), timeouts: sys => { sys.runQueuedTimeoutCallbacks(); sys.runQueuedTimeoutCallbacks(); @@ -514,7 +558,11 @@ describe("unittests:: tsc-watch:: moduleResolution", () => { }, { caption: "update package.json so error is fixed", - edit: sys => sys.writeFile("/home/src/projects/project/node_modules/foo/package.json", getFsContentsForNode10ResultPackageJson("foo", /*addTypes*/ true, /*addTypesCondition*/ true)), + edit: sys => + sys.writeFile( + "/home/src/projects/project/node_modules/foo/package.json", + getFsContentsForNode10ResultPackageJson("foo", /*addTypes*/ true, /*addTypesCondition*/ true), + ), timeouts: sys => { sys.runQueuedTimeoutCallbacks(); sys.runQueuedTimeoutCallbacks(); @@ -522,7 +570,11 @@ describe("unittests:: tsc-watch:: moduleResolution", () => { }, { caption: "update package.json from @types so error is introduced", - edit: sys => sys.writeFile("/home/src/projects/project/node_modules/@types/bar2/package.json", getFsConentsForNode10ResultAtTypesPackageJson("bar2", /*addTypesCondition*/ false)), + edit: sys => + sys.writeFile( + "/home/src/projects/project/node_modules/@types/bar2/package.json", + getFsConentsForNode10ResultAtTypesPackageJson("bar2", /*addTypesCondition*/ false), + ), timeouts: sys => { sys.runQueuedTimeoutCallbacks(); sys.runQueuedTimeoutCallbacks(); @@ -530,7 +582,11 @@ describe("unittests:: tsc-watch:: moduleResolution", () => { }, { caption: "update package.json so error is introduced", - edit: sys => sys.writeFile("/home/src/projects/project/node_modules/foo2/package.json", getFsContentsForNode10ResultPackageJson("foo2", /*addTypes*/ true, /*addTypesCondition*/ false)), + edit: sys => + sys.writeFile( + "/home/src/projects/project/node_modules/foo2/package.json", + getFsContentsForNode10ResultPackageJson("foo2", /*addTypes*/ true, /*addTypesCondition*/ false), + ), timeouts: sys => { sys.runQueuedTimeoutCallbacks(); sys.runQueuedTimeoutCallbacks(); @@ -554,7 +610,11 @@ describe("unittests:: tsc-watch:: moduleResolution", () => { }, { caption: "add the node10Result in @types", - edit: sys => sys.writeFile("/home/src/projects/project/node_modules/@types/bar2/index.d.ts", getFsContentsForNode10ResultDts("bar2")), + edit: sys => + sys.writeFile( + "/home/src/projects/project/node_modules/@types/bar2/index.d.ts", + getFsContentsForNode10ResultDts("bar2"), + ), timeouts: sys => { sys.runQueuedTimeoutCallbacks(); sys.runQueuedTimeoutCallbacks(); @@ -562,7 +622,11 @@ describe("unittests:: tsc-watch:: moduleResolution", () => { }, { caption: "add the ndoe10Result in package/types", - edit: sys => sys.writeFile("/home/src/projects/project/node_modules/foo2/index.d.ts", getFsContentsForNode10ResultDts("foo2")), + edit: sys => + sys.writeFile( + "/home/src/projects/project/node_modules/foo2/index.d.ts", + getFsContentsForNode10ResultDts("foo2"), + ), timeouts: sys => { sys.runQueuedTimeoutCallbacks(); sys.runQueuedTimeoutCallbacks(); diff --git a/src/testRunner/unittests/tscWatch/nodeNextWatch.ts b/src/testRunner/unittests/tscWatch/nodeNextWatch.ts index 9f66c823ab3e2..476fec768425f 100644 --- a/src/testRunner/unittests/tscWatch/nodeNextWatch.ts +++ b/src/testRunner/unittests/tscWatch/nodeNextWatch.ts @@ -47,7 +47,10 @@ describe("unittests:: tsc-watch:: nodeNextWatch:: emit when module emit is speci path: "/project/src/deps.d.ts", content: `declare module "thing";`, }; - return createWatchedSystem([configFile, file1, declFile, packageFile, { ...libFile, path: "/a/lib/lib.es2020.full.d.ts" }]); + return createWatchedSystem([configFile, file1, declFile, packageFile, { + ...libFile, + path: "/a/lib/lib.es2020.full.d.ts", + }]); }, edits: [ { diff --git a/src/testRunner/unittests/tscWatch/programUpdates.ts b/src/testRunner/unittests/tscWatch/programUpdates.ts index 5338f3b30dd4f..7d2bc00d9a230 100644 --- a/src/testRunner/unittests/tscWatch/programUpdates.ts +++ b/src/testRunner/unittests/tscWatch/programUpdates.ts @@ -164,7 +164,8 @@ describe("unittests:: tsc-watch:: program updates", () => { verifyTscWatch({ scenario, - subScenario: "handles the missing files - that were added to program because they were added with tripleSlashRefs", + subScenario: + "handles the missing files - that were added to program because they were added with tripleSlashRefs", commandLineArgs: ["-w", "/a/b/commonFile1.ts"], sys: () => { const file1: File = { @@ -373,7 +374,11 @@ export class A { sys.modifyFile( "/tsconfig.json", JSON.stringify({ - compilerOptions: { target: "es6", importsNotUsedAsValues: "error", experimentalDecorators: true }, + compilerOptions: { + target: "es6", + importsNotUsedAsValues: "error", + experimentalDecorators: true, + }, }), ), timeouts: sys => sys.runQueuedTimeoutCallbacks(), @@ -384,7 +389,12 @@ export class A { sys.modifyFile( "/tsconfig.json", JSON.stringify({ - compilerOptions: { target: "es6", importsNotUsedAsValues: "error", experimentalDecorators: true, emitDecoratorMetadata: true }, + compilerOptions: { + target: "es6", + importsNotUsedAsValues: "error", + experimentalDecorators: true, + emitDecoratorMetadata: true, + }, }), ), timeouts: sys => sys.runQueuedTimeoutCallbacks(), @@ -622,7 +632,9 @@ export class A { path: "/a/d/f3.ts", content: "export let y = 1;", }; - const { sys, baseline, oldSnap, cb, getPrograms } = createBaseline(createWatchedSystem([libFile, file1, file2, file3])); + const { sys, baseline, oldSnap, cb, getPrograms } = createBaseline( + createWatchedSystem([libFile, file1, file2, file3]), + ); const host = createWatchCompilerHostOfFilesAndCompilerOptionsForBaseline({ rootFiles: [file2.path, file3.path], system: sys, @@ -661,7 +673,10 @@ export class A { sys.logTimeoutQueueLength(); baseline.push(`First program is not updated:: ${getPrograms() === ts.emptyArray}`); baseline.push(`Second program is not updated:: ${getPrograms2() === ts.emptyArray}`); - Harness.Baseline.runBaseline(`tscWatch/${scenario}/two-watch-programs-are-not-affected-by-each-other.js`, baseline.join("\r\n")); + Harness.Baseline.runBaseline( + `tscWatch/${scenario}/two-watch-programs-are-not-affected-by-each-other.js`, + baseline.join("\r\n"), + ); }); verifyTscWatch({ @@ -686,7 +701,8 @@ export class A { verifyTscWatch({ scenario, - subScenario: "can correctly update configured project when set of root files has changed (new file in list of files)", + subScenario: + "can correctly update configured project when set of root files has changed (new file in list of files)", commandLineArgs: ["-w", "-p", configFilePath], sys: () => { const file1 = { @@ -706,7 +722,8 @@ export class A { edits: [ { caption: "Modify config to make f2 as root too", - edit: sys => sys.writeFile(configFilePath, JSON.stringify({ compilerOptions: {}, files: ["f1.ts", "f2.ts"] })), + edit: sys => + sys.writeFile(configFilePath, JSON.stringify({ compilerOptions: {}, files: ["f1.ts", "f2.ts"] })), timeouts: sys => sys.runQueuedTimeoutCallbacks(), }, ], @@ -714,7 +731,8 @@ export class A { verifyTscWatch({ scenario, - subScenario: "correctly parses wild card directories from implicit glob when two keys differ only in directory seperator", + subScenario: + "correctly parses wild card directories from implicit glob when two keys differ only in directory seperator", commandLineArgs: ["-w", "--extendedDiagnostics"], sys: () => { const file1 = { @@ -729,7 +747,9 @@ export class A { path: `/user/username/projects/myproject/tsconfig.json`, content: JSON.stringify({ compilerOptions: { composite: true }, include: ["./", "./**/*.json"] }), }; - return createWatchedSystem([file1, file2, libFile, configFile], { currentDirectory: "/user/username/projects/myproject" }); + return createWatchedSystem([file1, file2, libFile, configFile], { + currentDirectory: "/user/username/projects/myproject", + }); }, edits: [ { @@ -739,7 +759,8 @@ export class A { }, { caption: "Import new file", - edit: sys => sys.prependFile(`/user/username/projects/myproject/f1.ts`, `import { z } from "./new-file";`), + edit: sys => + sys.prependFile(`/user/username/projects/myproject/f1.ts`, `import { z } from "./new-file";`), timeouts: sys => sys.runQueuedTimeoutCallbacks(), }, ], @@ -758,12 +779,15 @@ export class A { path: `/user/username/projects/myproject/Project/tsconfig.json`, content: JSON.stringify({ include: [".", "./**/*.json"] }), }; - return createWatchedSystem([file1, libFile, configFile], { currentDirectory: `/user/username/projects/myproject/Project` }); + return createWatchedSystem([file1, libFile, configFile], { + currentDirectory: `/user/username/projects/myproject/Project`, + }); }, edits: [ { caption: "Write file2", - edit: sys => sys.writeFile(`/user/username/projects/myproject/Project/file2.ts`, "export const y = 10;"), + edit: sys => + sys.writeFile(`/user/username/projects/myproject/Project/file2.ts`, "export const y = 10;"), timeouts: sys => sys.runQueuedTimeoutCallbacks(), }, ], @@ -791,7 +815,11 @@ export class A { edits: [ { caption: "Modify config to set outFile option", - edit: sys => sys.writeFile(configFilePath, JSON.stringify({ compilerOptions: { outFile: "out.js" }, files: ["f1.ts", "f2.ts"] })), + edit: sys => + sys.writeFile( + configFilePath, + JSON.stringify({ compilerOptions: { outFile: "out.js" }, files: ["f1.ts", "f2.ts"] }), + ), timeouts: sys => sys.runQueuedTimeoutCallbacks(), }, ], @@ -900,7 +928,9 @@ declare const eval: any`, }, ), }; - return createWatchedSystem([libES5, libES2015Promise, app, config1], { executingFilePath: "/compiler/tsc.js" }); + return createWatchedSystem([libES5, libES2015Promise, app, config1], { + executingFilePath: "/compiler/tsc.js", + }); }, edits: [ { @@ -959,14 +989,21 @@ declare const eval: any`, const changeModuleFileToModuleFile1: TscWatchCompileChange = { caption: "Rename moduleFile to moduleFile1", edit: sys => { - sys.renameFile("/users/username/projects/project/moduleFile.ts", "/users/username/projects/project/moduleFile1.ts"); + sys.renameFile( + "/users/username/projects/project/moduleFile.ts", + "/users/username/projects/project/moduleFile1.ts", + ); sys.deleteFile("/users/username/projects/project/moduleFile.js"); }, timeouts: runQueuedTimeoutCallbacksTwice, }; const changeModuleFile1ToModuleFile: TscWatchCompileChange = { caption: "Rename moduleFile1 back to moduleFile", - edit: sys => sys.renameFile("/users/username/projects/project/moduleFile1.ts", "/users/username/projects/project/moduleFile.ts"), + edit: sys => + sys.renameFile( + "/users/username/projects/project/moduleFile1.ts", + "/users/username/projects/project/moduleFile.ts", + ), timeouts: runQueuedTimeoutCallbacksTwice, }; @@ -1020,9 +1057,9 @@ declare const eval: any`, function verifyTypesLoad(includeTypeRoots: boolean) { verifyTscWatch({ scenario, - subScenario: includeTypeRoots ? - "types should not load from config file path if config exists but does not specifies typeRoots" : - "types should load from config file path if config exists", + subScenario: includeTypeRoots + ? "types should not load from config file path if config exists but does not specifies typeRoots" + : "types should load from config file path if config exists", commandLineArgs: ["-w", "-p", configFilePath], sys: () => { const f1 = { @@ -1031,7 +1068,9 @@ declare const eval: any`, }; const config = { path: configFilePath, - content: JSON.stringify({ compilerOptions: { types: ["node"], typeRoots: includeTypeRoots ? [] : undefined } }), + content: JSON.stringify({ + compilerOptions: { types: ["node"], typeRoots: includeTypeRoots ? [] : undefined }, + }), }; const node = { path: "/a/b/node_modules/@types/node/index.d.ts", @@ -1062,7 +1101,8 @@ declare const eval: any`, edits: [ { caption: "Create module file", - edit: sys => sys.writeFile("/users/username/projects/project/moduleFile.ts", "export function bar() { }"), + edit: sys => + sys.writeFile("/users/username/projects/project/moduleFile.ts", "export function bar() { }"), timeouts: runQueuedTimeoutCallbacksTwice, }, ], @@ -1151,7 +1191,8 @@ declare const eval: any`, verifyTscWatch({ scenario, - subScenario: "non-existing directories listed in config file input array should be tolerated without crashing the server", + subScenario: + "non-existing directories listed in config file input array should be tolerated without crashing the server", commandLineArgs: ["-w", "-p", configFilePath], sys: () => { const configFile = { @@ -1171,7 +1212,8 @@ declare const eval: any`, verifyTscWatch({ scenario, - subScenario: "non-existing directories listed in config file input array should be able to handle @types if input file list is empty", + subScenario: + "non-existing directories listed in config file input array should be able to handle @types if input file list is empty", commandLineArgs: ["-w", "-p", "/a/tsconfig.json"], sys: () => { const f = { @@ -1224,7 +1266,8 @@ declare const eval: any`, verifyTscWatch({ scenario, - subScenario: "Options Diagnostic locations reported correctly with changes in configFile contents when options change", + subScenario: + "Options Diagnostic locations reported correctly with changes in configFile contents when options change", commandLineArgs: ["-w", "-p", configFilePath], sys: () => { const file = { @@ -1285,13 +1328,16 @@ declare const eval: any`, compilerOptions: compilerOptionsToConfigJson(options), }), }; - return createWatchedSystem([file1, file2, libFile, tsconfig], { currentDirectory: "/user/username/projects/myproject" }); + return createWatchedSystem([file1, file2, libFile, tsconfig], { + currentDirectory: "/user/username/projects/myproject", + }); }, edits: [ noopChange, { caption: "Add new file", - edit: sys => sys.writeFile(`/user/username/projects/myproject/src/file3.ts`, `export const y = 10;`), + edit: sys => + sys.writeFile(`/user/username/projects/myproject/src/file3.ts`, `export const y = 10;`), timeouts: sys => sys.runQueuedTimeoutCallbacks(), // To update program and failed lookups }, noopChange, @@ -1383,7 +1429,8 @@ export function two() { edits: [ { caption: "Rename file1 to file2", - edit: sys => sys.renameFile("/home/username/project/src/file1.ts", "/home/username/project/src/file2.ts"), + edit: sys => + sys.renameFile("/home/username/project/src/file1.ts", "/home/username/project/src/file2.ts"), timeouts: sys => sys.runQueuedTimeoutCallbacks(), }, ], @@ -1392,7 +1439,12 @@ export function two() { function changeParameterTypeOfBFile(parameterName: string, toType: string): TscWatchCompileChange { return { caption: `Changed ${parameterName} type to ${toType}`, - edit: sys => sys.replaceFileText(`/user/username/projects/myproject/b.ts`, new RegExp(`${parameterName}: [a-z]*`), `${parameterName}: ${toType}`), + edit: sys => + sys.replaceFileText( + `/user/username/projects/myproject/b.ts`, + new RegExp(`${parameterName}: [a-z]*`), + `${parameterName}: ${toType}`, + ), timeouts: sys => sys.runQueuedTimeoutCallbacks(), }; } @@ -1424,7 +1476,9 @@ export default test;`, }, }), }; - return createWatchedSystem([aFile, bFile, libFile, tsconfigFile], { currentDirectory: "/user/username/projects/myproject" }); + return createWatchedSystem([aFile, bFile, libFile, tsconfigFile], { + currentDirectory: "/user/username/projects/myproject", + }); }, edits: [ changeParameterTypeOfBFile("x", "string"), @@ -1448,22 +1502,36 @@ foo().hello`, path: `/user/username/projects/myproject/tsconfig.json`, content: JSON.stringify({ compilerOptions: {} }), }; - return createWatchedSystem([aFile, config, libFile], { currentDirectory: "/user/username/projects/myproject" }); + return createWatchedSystem([aFile, config, libFile], { + currentDirectory: "/user/username/projects/myproject", + }); }, edits: [ { caption: "Enable strict null checks", - edit: sys => sys.writeFile(`/user/username/projects/myproject/tsconfig.json`, JSON.stringify({ compilerOptions: { strictNullChecks: true } })), + edit: sys => + sys.writeFile( + `/user/username/projects/myproject/tsconfig.json`, + JSON.stringify({ compilerOptions: { strictNullChecks: true } }), + ), timeouts: sys => sys.runQueuedTimeoutCallbacks(), }, { caption: "Set always strict false", - edit: sys => sys.writeFile(`/user/username/projects/myproject/tsconfig.json`, JSON.stringify({ compilerOptions: { strict: true, alwaysStrict: false } })), // Avoid changing 'alwaysStrict' or must re-bind + edit: sys => + sys.writeFile( + `/user/username/projects/myproject/tsconfig.json`, + JSON.stringify({ compilerOptions: { strict: true, alwaysStrict: false } }), + ), // Avoid changing 'alwaysStrict' or must re-bind timeouts: sys => sys.runQueuedTimeoutCallbacks(), }, { caption: "Disable strict", - edit: sys => sys.writeFile(`/user/username/projects/myproject/tsconfig.json`, JSON.stringify({ compilerOptions: {} })), + edit: sys => + sys.writeFile( + `/user/username/projects/myproject/tsconfig.json`, + JSON.stringify({ compilerOptions: {} }), + ), timeouts: sys => sys.runQueuedTimeoutCallbacks(), }, ], @@ -1491,12 +1559,18 @@ v === 'foo';`, path: `/user/username/projects/myproject/tsconfig.json`, content: JSON.stringify({ compilerOptions: {} }), }; - return createWatchedSystem([aFile, config, libFile], { currentDirectory: "/user/username/projects/myproject" }); + return createWatchedSystem([aFile, config, libFile], { + currentDirectory: "/user/username/projects/myproject", + }); }, edits: [ { caption: "Enable noErrorTruncation", - edit: sys => sys.writeFile(`/user/username/projects/myproject/tsconfig.json`, JSON.stringify({ compilerOptions: { noErrorTruncation: true } })), + edit: sys => + sys.writeFile( + `/user/username/projects/myproject/tsconfig.json`, + JSON.stringify({ compilerOptions: { noErrorTruncation: true } }), + ), timeouts: sys => sys.runQueuedTimeoutCallbacks(), }, ], @@ -1521,7 +1595,11 @@ class D extends C { prop = 1; }`, edits: [ { caption: "Enable useDefineForClassFields", - edit: sys => sys.writeFile(`/tsconfig.json`, JSON.stringify({ compilerOptions: { target: "es6", useDefineForClassFields: true } })), + edit: sys => + sys.writeFile( + `/tsconfig.json`, + JSON.stringify({ compilerOptions: { target: "es6", useDefineForClassFields: true } }), + ), timeouts: sys => sys.runQueuedTimeoutCallbacks(), }, ], @@ -1545,22 +1623,36 @@ export function f(p: C) { return p; }`, path: `/user/username/projects/myproject/tsconfig.json`, content: JSON.stringify({ compilerOptions: {} }), }; - return createWatchedSystem([aFile, bFile, config, libFile], { currentDirectory: "/user/username/projects/myproject" }); + return createWatchedSystem([aFile, bFile, config, libFile], { + currentDirectory: "/user/username/projects/myproject", + }); }, edits: [ { caption: 'Set to "remove"', - edit: sys => sys.writeFile(`/user/username/projects/myproject/tsconfig.json`, JSON.stringify({ compilerOptions: { importsNotUsedAsValues: "remove" } })), + edit: sys => + sys.writeFile( + `/user/username/projects/myproject/tsconfig.json`, + JSON.stringify({ compilerOptions: { importsNotUsedAsValues: "remove" } }), + ), timeouts: sys => sys.runQueuedTimeoutCallbacks(), }, { caption: 'Set to "error"', - edit: sys => sys.writeFile(`/user/username/projects/myproject/tsconfig.json`, JSON.stringify({ compilerOptions: { importsNotUsedAsValues: "error" } })), + edit: sys => + sys.writeFile( + `/user/username/projects/myproject/tsconfig.json`, + JSON.stringify({ compilerOptions: { importsNotUsedAsValues: "error" } }), + ), timeouts: sys => sys.runQueuedTimeoutCallbacks(), }, { caption: 'Set to "preserve"', - edit: sys => sys.writeFile(`/user/username/projects/myproject/tsconfig.json`, JSON.stringify({ compilerOptions: { importsNotUsedAsValues: "preserve" } })), + edit: sys => + sys.writeFile( + `/user/username/projects/myproject/tsconfig.json`, + JSON.stringify({ compilerOptions: { importsNotUsedAsValues: "preserve" } }), + ), timeouts: sys => sys.runQueuedTimeoutCallbacks(), }, ], @@ -1588,7 +1680,11 @@ export function f(p: C) { return p; }`, edits: [ { caption: "Enable forceConsistentCasingInFileNames", - edit: sys => sys.writeFile(`/tsconfig.json`, JSON.stringify({ compilerOptions: { forceConsistentCasingInFileNames: true } })), + edit: sys => + sys.writeFile( + `/tsconfig.json`, + JSON.stringify({ compilerOptions: { forceConsistentCasingInFileNames: true } }), + ), timeouts: sys => sys.runQueuedTimeoutCallbacks(), }, ], @@ -1611,12 +1707,18 @@ export function f(p: C) { return p; }`, path: `/user/username/projects/myproject/tsconfig.json`, content: JSON.stringify({ compilerOptions: { moduleResolution: "node" } }), }; - return createWatchedSystem([aFile, jsonFile, config, libFile], { currentDirectory: "/user/username/projects/myproject" }); + return createWatchedSystem([aFile, jsonFile, config, libFile], { + currentDirectory: "/user/username/projects/myproject", + }); }, edits: [ { caption: "Enable resolveJsonModule", - edit: sys => sys.writeFile(`/user/username/projects/myproject/tsconfig.json`, JSON.stringify({ compilerOptions: { moduleResolution: "node", resolveJsonModule: true } })), + edit: sys => + sys.writeFile( + `/user/username/projects/myproject/tsconfig.json`, + JSON.stringify({ compilerOptions: { moduleResolution: "node", resolveJsonModule: true } }), + ), timeouts: sys => sys.runQueuedTimeoutCallbacks(), }, ], @@ -1637,7 +1739,9 @@ export function f(p: C) { return p; }`, path: `/user/username/projects/myproject/tsconfig.json`, content: "{}", }; - return createWatchedSystem([aFile, config, libFile], { currentDirectory: "/user/username/projects/myproject" }); + return createWatchedSystem([aFile, config, libFile], { + currentDirectory: "/user/username/projects/myproject", + }); }, edits: [ { @@ -1680,11 +1784,18 @@ interface Document { scenario, subScenario: `updates errors in lib file/${subScenario}`, commandLineArgs: ["-w", aFile.path, ...commandLineOptions], - sys: () => createWatchedSystem([aFile, libFileWithDocument], { currentDirectory: "/user/username/projects/myproject" }), + sys: () => + createWatchedSystem([aFile, libFileWithDocument], { + currentDirectory: "/user/username/projects/myproject", + }), edits: [ { caption: "Remove document declaration from file", - edit: sys => sys.writeFile(aFile.path, aFile.content.replace(fieldWithoutReadonly, "var x: string;")), + edit: sys => + sys.writeFile( + aFile.path, + aFile.content.replace(fieldWithoutReadonly, "var x: string;"), + ), timeouts: sys => sys.runQueuedTimeoutCallbacks(), }, { @@ -1761,7 +1872,9 @@ interface Document { path: `/user/username/projects/myproject/tsconfig.json`, content: "{}", }; - return createWatchedSystem([aFile, bFile, configFile, libFileWithDocument], { currentDirectory: "/user/username/projects/myproject" }); + return createWatchedSystem([aFile, bFile, configFile, libFileWithDocument], { + currentDirectory: "/user/username/projects/myproject", + }); }, edits: [ changeWhenLibCheckChanges({ skipLibCheck: true }), @@ -1795,7 +1908,9 @@ const b: string = a;`, }, }), }; - return createWatchedSystem([aFile, bFile, configFile, libFile], { currentDirectory: "/user/username/projects/myproject" }); + return createWatchedSystem([aFile, bFile, configFile, libFile], { + currentDirectory: "/user/username/projects/myproject", + }); }, edits: [ { @@ -1828,7 +1943,9 @@ const b: string = a;`, }, }), }; - return createWatchedSystem([aFile, bFile, configFile, libFile], { currentDirectory: "/user/username/projects/myproject" }); + return createWatchedSystem([aFile, bFile, configFile, libFile], { + currentDirectory: "/user/username/projects/myproject", + }); }, edits: [ { @@ -1862,12 +1979,18 @@ import { x } from "../b";`, }, }), }; - return createWatchedSystem([index, configFile, libFile], { currentDirectory: "/user/username/projects/myproject" }); + return createWatchedSystem([index, configFile, libFile], { + currentDirectory: "/user/username/projects/myproject", + }); }, edits: [ { caption: "Update 'jsx' to 'react'", - edit: sys => sys.writeFile(`/user/username/projects/myproject/tsconfig.json`, '{ "compilerOptions": { "jsx": "react" } }'), + edit: sys => + sys.writeFile( + `/user/username/projects/myproject/tsconfig.json`, + '{ "compilerOptions": { "jsx": "react" } }', + ), timeouts: sys => sys.runQueuedTimeoutCallbacks(), }, ], @@ -1991,12 +2114,18 @@ import { x } from "../b";`, include: ["client/**/*", "folder2"], }), }; - return createWatchedSystem([module1, module2, symlink, config, libFile], { currentDirectory: "/user/username/projects/myproject" }); + return createWatchedSystem([module1, module2, symlink, config, libFile], { + currentDirectory: "/user/username/projects/myproject", + }); }, edits: [ { caption: "Add module3 to folder2", - edit: sys => sys.writeFile(`/user/username/projects/myproject/client/linktofolder2/module3.ts`, `import * as M from "folder1/module1";`), + edit: sys => + sys.writeFile( + `/user/username/projects/myproject/client/linktofolder2/module3.ts`, + `import * as M from "folder1/module1";`, + ), timeouts: sys => sys.runQueuedTimeoutCallbacks(), }, ], @@ -2005,7 +2134,12 @@ import { x } from "../b";`, verifyTscWatch({ scenario, subScenario: "when new file is added to the referenced project", - commandLineArgs: ["-w", "-p", `/user/username/projects/myproject/projects/project2/tsconfig.json`, "--extendedDiagnostics"], + commandLineArgs: [ + "-w", + "-p", + `/user/username/projects/myproject/projects/project2/tsconfig.json`, + "--extendedDiagnostics", + ], sys: () => { const config1: File = { path: `/user/username/projects/myproject/projects/project1/tsconfig.json`, @@ -2047,17 +2181,26 @@ import { x } from "../b";`, edits: [ { caption: "Add class3 to project1", - edit: sys => sys.writeFile(`/user/username/projects/myproject/projects/project1/class3.ts`, `class class3 {}`), + edit: sys => + sys.writeFile(`/user/username/projects/myproject/projects/project1/class3.ts`, `class class3 {}`), timeouts: sys => sys.runQueuedTimeoutCallbacks(), }, { caption: "Add output of class3", - edit: sys => sys.writeFile(`/user/username/projects/myproject/projects/project1/class3.d.ts`, `declare class class3 {}`), + edit: sys => + sys.writeFile( + `/user/username/projects/myproject/projects/project1/class3.d.ts`, + `declare class class3 {}`, + ), timeouts: sys => sys.runQueuedTimeoutCallbacks(), }, { caption: "Add excluded file to project1", - edit: sys => sys.ensureFileOrFolder({ path: `/user/username/projects/myproject/projects/project1/temp/file.d.ts`, content: `declare class file {}` }), + edit: sys => + sys.ensureFileOrFolder({ + path: `/user/username/projects/myproject/projects/project1/temp/file.d.ts`, + content: `declare class file {}`, + }), timeouts: sys => sys.logTimeoutQueueLength(), }, { @@ -2067,7 +2210,11 @@ import { x } from "../b";`, }, { caption: "Add output of class3", - edit: sys => sys.writeFile(`/user/username/projects/myproject/projects/project1/class3.d.ts`, `declare class class3 {}`), + edit: sys => + sys.writeFile( + `/user/username/projects/myproject/projects/project1/class3.d.ts`, + `declare class class3 {}`, + ), timeouts: sys => sys.runQueuedTimeoutCallbacks(), }, ], @@ -2086,7 +2233,9 @@ import { x } from "../b";`, path: `/user/username/projects/myproject/tsconfig.json`, content: `{}`, }; - return createWatchedSystem([module1, config, libFile], { currentDirectory: "/user/username/projects/myproject" }); + return createWatchedSystem([module1, config, libFile], { + currentDirectory: "/user/username/projects/myproject", + }); }, edits: [ { @@ -2119,7 +2268,9 @@ import { x } from "../b";`, }, }), }; - return createWatchedSystem([module1, module2, config, libFile], { currentDirectory: "/user/username/projects/myproject" }); + return createWatchedSystem([module1, module2, config, libFile], { + currentDirectory: "/user/username/projects/myproject", + }); }, edits: [ { diff --git a/src/testRunner/unittests/tscWatch/projectsWithReferences.ts b/src/testRunner/unittests/tscWatch/projectsWithReferences.ts index 1fe3bc5200e05..c15001a5d5459 100644 --- a/src/testRunner/unittests/tscWatch/projectsWithReferences.ts +++ b/src/testRunner/unittests/tscWatch/projectsWithReferences.ts @@ -48,7 +48,10 @@ describe("unittests:: tsc-watch:: projects with references: invoking when refere { caption: "non local edit in logic ts, and build logic", edit: sys => { - sys.appendFile(getTsBuildProjectFilePath("sample1", "logic/index.ts"), `export function gfoo() { }`); + sys.appendFile( + getTsBuildProjectFilePath("sample1", "logic/index.ts"), + `export function gfoo() { }`, + ); const solutionBuilder = createSolutionBuilder(sys, ["logic"]); solutionBuilder.build(); }, @@ -102,7 +105,10 @@ describe("unittests:: tsc-watch:: projects with references: invoking when refere { caption: "non local edit b ts, and build b", edit: sys => { - sys.appendFile(getTsBuildProjectFilePath("transitiveReferences", "b.ts"), `export function gfoo() { }`); + sys.appendFile( + getTsBuildProjectFilePath("transitiveReferences", "b.ts"), + `export function gfoo() { }`, + ); const solutionBuilder = createSolutionBuilder(sys, ["tsconfig.b.json"]); solutionBuilder.build(); }, @@ -115,23 +121,42 @@ describe("unittests:: tsc-watch:: projects with references: invoking when refere path: getTsBuildProjectFilePath("transitiveReferences", "nrefs/a.d.ts"), content: sys.readFile(getTsBuildProjectFilePath("transitiveReferences", "refs/a.d.ts"))!, }); - changeCompilerOpitonsPaths(sys, getTsBuildProjectFilePath("transitiveReferences", "tsconfig.c.json"), { "@ref/*": ["./nrefs/*"] }); + changeCompilerOpitonsPaths( + sys, + getTsBuildProjectFilePath("transitiveReferences", "tsconfig.c.json"), + { "@ref/*": ["./nrefs/*"] }, + ); }, timeouts: sys => sys.runQueuedTimeoutCallbacks(), }, { caption: "Revert config file edit", - edit: sys => changeCompilerOpitonsPaths(sys, getTsBuildProjectFilePath("transitiveReferences", "tsconfig.c.json"), { "@ref/*": ["./refs/*"] }), + edit: sys => + changeCompilerOpitonsPaths( + sys, + getTsBuildProjectFilePath("transitiveReferences", "tsconfig.c.json"), + { "@ref/*": ["./refs/*"] }, + ), timeouts: sys => sys.runQueuedTimeoutCallbacks(), }, { caption: "edit in referenced config file", - edit: sys => changeCompilerOpitonsPaths(sys, getTsBuildProjectFilePath("transitiveReferences", "tsconfig.b.json"), { "@ref/*": ["./nrefs/*"] }), + edit: sys => + changeCompilerOpitonsPaths( + sys, + getTsBuildProjectFilePath("transitiveReferences", "tsconfig.b.json"), + { "@ref/*": ["./nrefs/*"] }, + ), timeouts: sys => sys.runQueuedTimeoutCallbacks(), }, { caption: "Revert referenced config file edit", - edit: sys => changeCompilerOpitonsPaths(sys, getTsBuildProjectFilePath("transitiveReferences", "tsconfig.b.json"), { "@ref/*": ["./refs/*"] }), + edit: sys => + changeCompilerOpitonsPaths( + sys, + getTsBuildProjectFilePath("transitiveReferences", "tsconfig.b.json"), + { "@ref/*": ["./refs/*"] }, + ), timeouts: sys => sys.runQueuedTimeoutCallbacks(), }, { @@ -246,7 +271,10 @@ X;`, { caption: "non local edit b ts, and build b", edit: sys => { - sys.appendFile(getTsBuildProjectFilePath("transitiveReferences", "b/index.ts"), `export function gfoo() { }`); + sys.appendFile( + getTsBuildProjectFilePath("transitiveReferences", "b/index.ts"), + `export function gfoo() { }`, + ); const solutionBuilder = createSolutionBuilder(sys, ["b"]); solutionBuilder.build(); }, @@ -259,23 +287,42 @@ X;`, path: getTsBuildProjectFilePath("transitiveReferences", "nrefs/a.d.ts"), content: sys.readFile(getTsBuildProjectFilePath("transitiveReferences", "refs/a.d.ts"))!, }); - changeCompilerOpitonsPaths(sys, getTsBuildProjectFilePath("transitiveReferences", "c/tsconfig.json"), { "@ref/*": ["../nrefs/*"] }); + changeCompilerOpitonsPaths( + sys, + getTsBuildProjectFilePath("transitiveReferences", "c/tsconfig.json"), + { "@ref/*": ["../nrefs/*"] }, + ); }, timeouts: sys => sys.runQueuedTimeoutCallbacks(), }, { caption: "Revert config file edit", - edit: sys => changeCompilerOpitonsPaths(sys, getTsBuildProjectFilePath("transitiveReferences", "c/tsconfig.json"), { "@ref/*": ["../refs/*"] }), + edit: sys => + changeCompilerOpitonsPaths( + sys, + getTsBuildProjectFilePath("transitiveReferences", "c/tsconfig.json"), + { "@ref/*": ["../refs/*"] }, + ), timeouts: sys => sys.runQueuedTimeoutCallbacks(), }, { caption: "edit in referenced config file", - edit: sys => changeCompilerOpitonsPaths(sys, getTsBuildProjectFilePath("transitiveReferences", "b/tsconfig.json"), { "@ref/*": ["../nrefs/*"] }), + edit: sys => + changeCompilerOpitonsPaths( + sys, + getTsBuildProjectFilePath("transitiveReferences", "b/tsconfig.json"), + { "@ref/*": ["../nrefs/*"] }, + ), timeouts: sys => sys.runQueuedTimeoutCallbacks(), }, { caption: "Revert referenced config file edit", - edit: sys => changeCompilerOpitonsPaths(sys, getTsBuildProjectFilePath("transitiveReferences", "b/tsconfig.json"), { "@ref/*": ["../refs/*"] }), + edit: sys => + changeCompilerOpitonsPaths( + sys, + getTsBuildProjectFilePath("transitiveReferences", "b/tsconfig.json"), + { "@ref/*": ["../refs/*"] }, + ), timeouts: sys => sys.runQueuedTimeoutCallbacks(), }, { @@ -368,7 +415,10 @@ X;`, { caption: "non local edit b ts, and build b", edit: sys => { - sys.appendFile(getTsBuildProjectFilePath("transitiveReferences", "b/index.ts"), `export function gfoo() { }`); + sys.appendFile( + getTsBuildProjectFilePath("transitiveReferences", "b/index.ts"), + `export function gfoo() { }`, + ); const solutionBuilder = createSolutionBuilder(sys, ["b"]); solutionBuilder.build(); }, @@ -381,23 +431,42 @@ X;`, path: getTsBuildProjectFilePath("transitiveReferences", "nrefs/a.d.ts"), content: sys.readFile(getTsBuildProjectFilePath("transitiveReferences", "refs/a.d.ts"))!, }); - changeCompilerOpitonsPaths(sys, getTsBuildProjectFilePath("transitiveReferences", "c/tsconfig.json"), { "@ref/*": ["../nrefs/*"] }); + changeCompilerOpitonsPaths( + sys, + getTsBuildProjectFilePath("transitiveReferences", "c/tsconfig.json"), + { "@ref/*": ["../nrefs/*"] }, + ); }, timeouts: sys => sys.runQueuedTimeoutCallbacks(), }, { caption: "Revert config file edit", - edit: sys => changeCompilerOpitonsPaths(sys, getTsBuildProjectFilePath("transitiveReferences", "c/tsconfig.json"), { "@ref/*": ["../refs/*"] }), + edit: sys => + changeCompilerOpitonsPaths( + sys, + getTsBuildProjectFilePath("transitiveReferences", "c/tsconfig.json"), + { "@ref/*": ["../refs/*"] }, + ), timeouts: sys => sys.runQueuedTimeoutCallbacks(), }, { caption: "edit in referenced config file", - edit: sys => changeCompilerOpitonsPaths(sys, getTsBuildProjectFilePath("transitiveReferences", "b/tsconfig.json"), { "@ref/*": ["../nrefs/*"] }), + edit: sys => + changeCompilerOpitonsPaths( + sys, + getTsBuildProjectFilePath("transitiveReferences", "b/tsconfig.json"), + { "@ref/*": ["../nrefs/*"] }, + ), timeouts: sys => sys.runQueuedTimeoutCallbacks(), }, { caption: "Revert referenced config file edit", - edit: sys => changeCompilerOpitonsPaths(sys, getTsBuildProjectFilePath("transitiveReferences", "b/tsconfig.json"), { "@ref/*": ["../refs/*"] }), + edit: sys => + changeCompilerOpitonsPaths( + sys, + getTsBuildProjectFilePath("transitiveReferences", "b/tsconfig.json"), + { "@ref/*": ["../refs/*"] }, + ), timeouts: sys => sys.runQueuedTimeoutCallbacks(), }, { @@ -457,7 +526,11 @@ X;`, { caption: "change declration map in core", edit: sys => { - sys.replaceFileText(getTsBuildProjectFilePath("sample1", "core/tsconfig.json"), `"declarationMap": true,`, `"declarationMap": false,`); + sys.replaceFileText( + getTsBuildProjectFilePath("sample1", "core/tsconfig.json"), + `"declarationMap": true,`, + `"declarationMap": false,`, + ); const solutionBuilder = createSolutionBuilder(sys, ["core"]); solutionBuilder.build(); }, diff --git a/src/testRunner/unittests/tscWatch/resolutionCache.ts b/src/testRunner/unittests/tscWatch/resolutionCache.ts index 0ab9c2bbf0c58..a95413585f136 100644 --- a/src/testRunner/unittests/tscWatch/resolutionCache.ts +++ b/src/testRunner/unittests/tscWatch/resolutionCache.ts @@ -28,7 +28,9 @@ describe("unittests:: tsc-watch:: resolutionCache:: tsc-watch module resolution content: `foo()`, }; - const { sys, baseline, oldSnap, cb, getPrograms } = createBaseline(createWatchedSystem([root, imported, libFile])); + const { sys, baseline, oldSnap, cb, getPrograms } = createBaseline( + createWatchedSystem([root, imported, libFile]), + ); const host = createWatchCompilerHostOfFilesAndCompilerOptionsForBaseline({ rootFiles: [root.path], system: sys, @@ -172,7 +174,9 @@ describe("unittests:: tsc-watch:: resolutionCache:: tsc-watch module resolution content: `export const y = 1;export const x = 10;`, }; - const { sys, baseline, oldSnap, cb, getPrograms } = createBaseline(createWatchedSystem([root, imported, libFile])); + const { sys, baseline, oldSnap, cb, getPrograms } = createBaseline( + createWatchedSystem([root, imported, libFile]), + ); const host = createWatchCompilerHostOfFilesAndCompilerOptionsForBaseline({ rootFiles: [root.path], system: sys, @@ -269,7 +273,11 @@ declare module "fs" { verifyTscWatch({ scenario, subScenario: "works when included file with ambient module changes", - commandLineArgs: ["--w", "/users/username/projects/project/foo.ts", "/users/username/projects/project/bar.d.ts"], + commandLineArgs: [ + "--w", + "/users/username/projects/project/foo.ts", + "/users/username/projects/project/bar.d.ts", + ], sys: () => { const root = { path: "/users/username/projects/project/foo.ts", @@ -340,7 +348,9 @@ declare module "fs" { }, }), }; - return createWatchedSystem([file1, file2, module1, libFile, configFile], { currentDirectory: "/a/b/projects/myProject/" }); + return createWatchedSystem([file1, file2, module1, libFile, configFile], { + currentDirectory: "/a/b/projects/myProject/", + }); }, edits: [ { @@ -364,12 +374,18 @@ declare module "fs" { path: `/user/username/projects/myproject/node_modules2/@types/qqq/index.d.ts`, content: "export {}", }; - return createWatchedSystem([file, libFile, module], { currentDirectory: "/user/username/projects/myproject" }); + return createWatchedSystem([file, libFile, module], { + currentDirectory: "/user/username/projects/myproject", + }); }, edits: [ { caption: "npm install", - edit: sys => sys.renameFolder(`/user/username/projects/myproject/node_modules2`, `/user/username/projects/myproject/node_modules`), + edit: sys => + sys.renameFolder( + `/user/username/projects/myproject/node_modules2`, + `/user/username/projects/myproject/node_modules`, + ), timeouts: sys => sys.runQueuedTimeoutCallbacks(), }, ], @@ -401,7 +417,8 @@ declare module "fs" { caption: "npm install file and folder that start with '.'", edit: sys => sys.ensureFileOrFolder({ - path: `/user/username/projects/myproject/node_modules/.cache/babel-loader/89c02171edab901b9926470ba6d5677e.ts`, + path: + `/user/username/projects/myproject/node_modules/.cache/babel-loader/89c02171edab901b9926470ba6d5677e.ts`, content: JSON.stringify({ something: 10 }), }), timeouts: sys => sys.logTimeoutQueueLength(), @@ -445,7 +462,8 @@ declare module "fs" { }), }); sys.ensureFileOrFolder({ - path: `/user/username/projects/myproject/node_modules/@myapp/ts-types/types/somefile.define.d.ts`, + path: + `/user/username/projects/myproject/node_modules/@myapp/ts-types/types/somefile.define.d.ts`, content: ` declare namespace myapp { function component(str: string): number; @@ -462,7 +480,9 @@ declare namespace myapp { edit: ts.noop, timeouts: (sys, [[oldProgram, oldBuilderProgram]], watchorSolution) => { sys.logTimeoutQueueLength(); - const newProgram = (watchorSolution as ts.WatchOfConfigFile).getProgram(); + const newProgram = + (watchorSolution as ts.WatchOfConfigFile) + .getProgram(); assert.strictEqual(newProgram, oldBuilderProgram, "No change so builder program should be same"); assert.strictEqual(newProgram.getProgram(), oldProgram, "No change so program should be same"); }, @@ -494,7 +514,12 @@ declare namespace myapp { }; const linkedPackageJson: File = { path: `${linkedPackageRoot}/package.json`, - content: JSON.stringify({ name: "@scoped/linked-package", version: "0.0.1", types: "dist/index.d.ts", main: "dist/index.js" }), + content: JSON.stringify({ + name: "@scoped/linked-package", + version: "0.0.1", + types: "dist/index.d.ts", + main: "dist/index.js", + }), }; const linkedPackageIndex: File = { path: `${linkedPackageRoot}/dist/index.d.ts`, @@ -504,7 +529,15 @@ declare namespace myapp { path: `${linkedPackageRoot}/dist/other.d.ts`, content: 'export declare const Foo = "BAR";', }; - const files = [libFile, mainFile, config, linkedPackageInMain, linkedPackageJson, linkedPackageIndex, linkedPackageOther]; + const files = [ + libFile, + mainFile, + config, + linkedPackageInMain, + linkedPackageJson, + linkedPackageIndex, + linkedPackageOther, + ]; return createWatchedSystem(files, { currentDirectory: mainPackageRoot }); }, }); @@ -537,7 +570,8 @@ declare namespace NodeJS { } verifyTscWatch({ scenario, - subScenario: "works when installing something in node_modules or @types when there is no notification from fs for index file", + subScenario: + "works when installing something in node_modules or @types when there is no notification from fs for index file", commandLineArgs: ["--w", `--extendedDiagnostics`], sys: () => { const file: File = { @@ -549,12 +583,21 @@ declare namespace NodeJS { content: "{}", }; const { nodeAtTypesIndex, nodeAtTypesBase, nodeAtTypes36Base, nodeAtTypesGlobals } = getNodeAtTypes(); - return createWatchedSystem([file, libFile, tsconfig, nodeAtTypesIndex, nodeAtTypesBase, nodeAtTypes36Base, nodeAtTypesGlobals], { currentDirectory: "/user/username/projects/myproject" }); + return createWatchedSystem([ + file, + libFile, + tsconfig, + nodeAtTypesIndex, + nodeAtTypesBase, + nodeAtTypes36Base, + nodeAtTypesGlobals, + ], { currentDirectory: "/user/username/projects/myproject" }); }, edits: [ { caption: "npm ci step one: remove all node_modules files", - edit: sys => sys.deleteFolder(`/user/username/projects/myproject/node_modules/@types`, /*recursive*/ true), + edit: sys => + sys.deleteFolder(`/user/username/projects/myproject/node_modules/@types`, /*recursive*/ true), timeouts: sys => sys.runQueuedTimeoutCallbacks(), }, { @@ -568,13 +611,16 @@ declare namespace NodeJS { }, { caption: `npm ci step three: create atTypes node folder`, - edit: sys => sys.ensureFileOrFolder({ path: `/user/username/projects/myproject/node_modules/@types/node` }), + edit: sys => + sys.ensureFileOrFolder({ path: `/user/username/projects/myproject/node_modules/@types/node` }), timeouts: sys => sys.runQueuedTimeoutCallbacks(), }, { - caption: `npm ci step four: create atTypes write all the files but dont invoke watcher for index.d.ts`, + caption: + `npm ci step four: create atTypes write all the files but dont invoke watcher for index.d.ts`, edit: sys => { - const { nodeAtTypesIndex, nodeAtTypesBase, nodeAtTypes36Base, nodeAtTypesGlobals } = getNodeAtTypes(); + const { nodeAtTypesIndex, nodeAtTypesBase, nodeAtTypes36Base, nodeAtTypesGlobals } = + getNodeAtTypes(); sys.ensureFileOrFolder(nodeAtTypesBase); sys.ensureFileOrFolder(nodeAtTypesIndex, /*ignoreWatchInvokedWithTriggerAsFileCreate*/ true); sys.ensureFileOrFolder(nodeAtTypes36Base, /*ignoreWatchInvokedWithTriggerAsFileCreate*/ true); @@ -619,7 +665,11 @@ declare namespace NodeJS { edits: [ { caption: "write file not resolved by import", - edit: sys => sys.ensureFileOrFolder({ path: "/users/username/projects/project/node_modules/pkg1/index.d.ts", content: `export interface Import1 {}` }), + edit: sys => + sys.ensureFileOrFolder({ + path: "/users/username/projects/project/node_modules/pkg1/index.d.ts", + content: `export interface Import1 {}`, + }), timeouts: sys => { sys.runQueuedTimeoutCallbacks(); // failed lookup sys.runQueuedTimeoutCallbacks(); // actual update @@ -627,7 +677,11 @@ declare namespace NodeJS { }, { caption: "write file not resolved by typeRef", - edit: sys => sys.ensureFileOrFolder({ path: "/users/username/projects/project/node_modules/pkg3/index.d.ts", content: `export interface Import3 {}` }), + edit: sys => + sys.ensureFileOrFolder({ + path: "/users/username/projects/project/node_modules/pkg3/index.d.ts", + content: `export interface Import3 {}`, + }), timeouts: sys => { sys.runQueuedTimeoutCallbacks(); // failed lookup sys.runQueuedTimeoutCallbacks(); // actual update diff --git a/src/testRunner/unittests/tscWatch/resolveJsonModuleWithIncremental.ts b/src/testRunner/unittests/tscWatch/resolveJsonModuleWithIncremental.ts index ca6bd441fa680..d0d5b9c2aa09d 100644 --- a/src/testRunner/unittests/tscWatch/resolveJsonModuleWithIncremental.ts +++ b/src/testRunner/unittests/tscWatch/resolveJsonModuleWithIncremental.ts @@ -21,7 +21,11 @@ describe("unittests:: tsc-watch:: resolveJsonModuleWithIncremental:: emit file - commandLineArgs: ["--p", "src/project", "-i", "-w"], edits: [{ caption: "Change json setting", - edit: sys => sys.writeFile("/src/project/tsconfig.json", JSON.stringify({ compilerOptions: { resolveJsonModule: false } }, null, 4)), // eslint-disable-line no-null/no-null + edit: sys => + sys.writeFile( + "/src/project/tsconfig.json", + JSON.stringify({ compilerOptions: { resolveJsonModule: false } }, null, 4), + ), // eslint-disable-line no-null/no-null timeouts: sys => sys.runQueuedTimeoutCallbacks(), }], }); diff --git a/src/testRunner/unittests/tscWatch/sourceOfProjectReferenceRedirect.ts b/src/testRunner/unittests/tscWatch/sourceOfProjectReferenceRedirect.ts index 9977c12c6c604..15caef25c48a6 100644 --- a/src/testRunner/unittests/tscWatch/sourceOfProjectReferenceRedirect.ts +++ b/src/testRunner/unittests/tscWatch/sourceOfProjectReferenceRedirect.ts @@ -73,7 +73,16 @@ describe("unittests:: tsc-watch:: watchAPI:: with sourceOfProjectReferenceRedire const indexTs = getTsBuildProjectFile("demo", "animals/index.ts"); const animalsConfig = getTsBuildProjectFile("demo", "animals/tsconfig.json"); return { - files: [{ path: libFile.path, content: libContent }, baseConfig, coreTs, coreConfig, animalTs, dogTs, indexTs, animalsConfig], + files: [ + { path: libFile.path, content: libContent }, + baseConfig, + coreTs, + coreConfig, + animalTs, + dogTs, + indexTs, + animalsConfig, + ], config: animalsConfig.path, subScenario: "with simple project", }; diff --git a/src/testRunner/unittests/tscWatch/watchApi.ts b/src/testRunner/unittests/tscWatch/watchApi.ts index 2620266a6028d..b927f278d5a0f 100644 --- a/src/testRunner/unittests/tscWatch/watchApi.ts +++ b/src/testRunner/unittests/tscWatch/watchApi.ts @@ -92,9 +92,12 @@ describe("unittests:: tsc-watch:: watchAPI:: tsc-watch with custom module resolu system: sys, cb, }); - host.resolveModuleNames = (moduleNames, containingFile, _reusedNames, _redirectedReference, options) => moduleNames.map(m => ts.resolveModuleName(m, containingFile, options, host).resolvedModule); + host.resolveModuleNames = (moduleNames, containingFile, _reusedNames, _redirectedReference, options) => + moduleNames.map(m => ts.resolveModuleName(m, containingFile, options, host).resolvedModule); // Invalidate resolutions only when ts file is created - if (implementHasInvalidatedResolution) host.hasInvalidatedResolutions = () => sys.fileExists(`/user/username/projects/myproject/other.ts`); + if (implementHasInvalidatedResolution) { + host.hasInvalidatedResolutions = () => sys.fileExists(`/user/username/projects/myproject/other.ts`); + } const watch = ts.createWatchProgram(host); runWatchBaseline({ scenario: "watchApi", @@ -112,7 +115,11 @@ describe("unittests:: tsc-watch:: watchAPI:: tsc-watch with custom module resolu }, { caption: "change other file", - edit: sys => sys.appendFile(`/user/username/projects/myproject/other.d.ts`, "export function bar(): void;"), + edit: sys => + sys.appendFile( + `/user/username/projects/myproject/other.d.ts`, + "export function bar(): void;", + ), timeouts: sys => sys.runQueuedTimeoutCallbacks(), }, { @@ -128,7 +135,10 @@ describe("unittests:: tsc-watch:: watchAPI:: tsc-watch with custom module resolu }); }); } - verifyWatch("host implements does not implement hasInvalidatedResolutions", /*implementHasInvalidatedResolution*/ false); + verifyWatch( + "host implements does not implement hasInvalidatedResolutions", + /*implementHasInvalidatedResolution*/ false, + ); verifyWatch("host implements hasInvalidatedResolutions", /*implementHasInvalidatedResolution*/ true); }); }); @@ -186,7 +196,9 @@ describe("unittests:: tsc-watch:: watchAPI:: when watchHost does not implement s path: `/user/username/projects/myproject/main.ts`, content: "const x = 10;", }; - const { sys, baseline, oldSnap, cb, getPrograms } = createBaseline(createWatchedSystem([config, mainFile, libFile])); + const { sys, baseline, oldSnap, cb, getPrograms } = createBaseline( + createWatchedSystem([config, mainFile, libFile]), + ); const host = createWatchCompilerHostOfConfigFileForBaseline({ configFileName: config.path, system: sys, @@ -311,8 +323,18 @@ describe("unittests:: tsc-watch:: watchAPI:: when watchHost uses createSemanticD function verifyOutputs(baseline: string[], sys: ts.System, emitSys: ts.System) { baseline.push("Checking if output is same as EmitAndSemanticDiagnosticsBuilderProgram::"); - for (const output of [`/user/username/projects/myproject/main.js`, `/user/username/projects/myproject/main.d.ts`, `/user/username/projects/myproject/other.js`, `/user/username/projects/myproject/other.d.ts`, `/user/username/projects/myproject/tsconfig.tsbuildinfo`]) { - baseline.push(`Output file text for ${output} is same:: ${sys.readFile(output) === emitSys.readFile(output)}`); + for ( + const output of [ + `/user/username/projects/myproject/main.js`, + `/user/username/projects/myproject/main.d.ts`, + `/user/username/projects/myproject/other.js`, + `/user/username/projects/myproject/other.d.ts`, + `/user/username/projects/myproject/tsconfig.tsbuildinfo`, + ] + ) { + baseline.push( + `Output file text for ${output} is same:: ${sys.readFile(output) === emitSys.readFile(output)}`, + ); } baseline.push(""); } @@ -351,7 +373,10 @@ describe("unittests:: tsc-watch:: watchAPI:: when watchHost uses createSemanticD } it("verifies that noEmit is handled on createSemanticDiagnosticsBuilderProgram and typechecking happens only on affected files", () => { - const { sys, baseline, oldSnap, cb, getPrograms, config, mainFile } = createSystem("{}", "export const x = 10;"); + const { sys, baseline, oldSnap, cb, getPrograms, config, mainFile } = createSystem( + "{}", + "export const x = 10;", + ); const host = createWatchCompilerHostOfConfigFileForBaseline({ configFileName: config.path, optionsToExtend: { noEmit: true }, @@ -389,22 +414,60 @@ describe("unittests:: tsc-watch:: watchAPI:: when watchHost uses createSemanticD const { sys, config, mainFile, emitSys } = result; // No Emit - verifyBuilder(baseline, emitBaseline, config, sys, emitSys, ts.createEmitAndSemanticDiagnosticsBuilderProgram, { noEmit: true }); + verifyBuilder( + baseline, + emitBaseline, + config, + sys, + emitSys, + ts.createEmitAndSemanticDiagnosticsBuilderProgram, + { noEmit: true }, + ); // Emit on both sys should result in same output - verifyBuilder(baseline, emitBaseline, config, sys, emitSys, ts.createEmitAndSemanticDiagnosticsBuilderProgram); + verifyBuilder( + baseline, + emitBaseline, + config, + sys, + emitSys, + ts.createEmitAndSemanticDiagnosticsBuilderProgram, + ); // Change file - applyChangeForBuilderTest(baseline, emitBaseline, sys, emitSys, sys => sys.appendFile(mainFile.path, "\n// SomeComment"), "Add comment"); + applyChangeForBuilderTest( + baseline, + emitBaseline, + sys, + emitSys, + sys => sys.appendFile(mainFile.path, "\n// SomeComment"), + "Add comment", + ); // Verify noEmit results in same output - verifyBuilder(baseline, emitBaseline, config, sys, emitSys, ts.createSemanticDiagnosticsBuilderProgram, { noEmit: true }); + verifyBuilder(baseline, emitBaseline, config, sys, emitSys, ts.createSemanticDiagnosticsBuilderProgram, { + noEmit: true, + }); // Emit on both sys should result in same output - verifyBuilder(baseline, emitBaseline, config, sys, emitSys, ts.createEmitAndSemanticDiagnosticsBuilderProgram); + verifyBuilder( + baseline, + emitBaseline, + config, + sys, + emitSys, + ts.createEmitAndSemanticDiagnosticsBuilderProgram, + ); // Change file - applyChangeForBuilderTest(baseline, emitBaseline, sys, emitSys, sys => sys.appendFile(mainFile.path, "\n// SomeComment"), "Add comment"); + applyChangeForBuilderTest( + baseline, + emitBaseline, + sys, + emitSys, + sys => sys.appendFile(mainFile.path, "\n// SomeComment"), + "Add comment", + ); // Emit on both the builders should result in same files verifyBuilder(baseline, emitBaseline, config, sys, emitSys, ts.createSemanticDiagnosticsBuilderProgram); @@ -414,10 +477,16 @@ describe("unittests:: tsc-watch:: watchAPI:: when watchHost uses createSemanticD emitBaseline = undefined!; }); it("noEmit with composite writes the tsbuildinfo with pending affected files correctly", () => { - Harness.Baseline.runBaseline(`tscWatch/watchApi/noEmit-with-composite-with-semantic-builder.js`, baseline.join("\r\n")); + Harness.Baseline.runBaseline( + `tscWatch/watchApi/noEmit-with-composite-with-semantic-builder.js`, + baseline.join("\r\n"), + ); }); it("baseline in createEmitAndSemanticDiagnosticsBuilderProgram:: noEmit with composite writes the tsbuildinfo with pending affected files correctly", () => { - Harness.Baseline.runBaseline(`tscWatch/watchApi/noEmit-with-composite-with-emit-builder.js`, emitBaseline.join("\r\n")); + Harness.Baseline.runBaseline( + `tscWatch/watchApi/noEmit-with-composite-with-emit-builder.js`, + emitBaseline.join("\r\n"), + ); }); }); @@ -436,30 +505,53 @@ describe("unittests:: tsc-watch:: watchAPI:: when watchHost uses createSemanticD verifyBuilder(baseline, emitBaseline, config, sys, emitSys, ts.createSemanticDiagnosticsBuilderProgram); // Change file - applyChangeForBuilderTest(baseline, emitBaseline, sys, emitSys, sys => sys.appendFile(mainFile.path, "\n// SomeComment"), "Add comment"); + applyChangeForBuilderTest( + baseline, + emitBaseline, + sys, + emitSys, + sys => sys.appendFile(mainFile.path, "\n// SomeComment"), + "Add comment", + ); // Verify noEmit results in same output verifyBuilder(baseline, emitBaseline, config, sys, emitSys, ts.createSemanticDiagnosticsBuilderProgram); // Fix error const fixed = "export const x = 10;"; - applyChangeForBuilderTest(baseline, emitBaseline, sys, emitSys, sys => sys.writeFile(mainFile.path, fixed), "Fix error"); + applyChangeForBuilderTest( + baseline, + emitBaseline, + sys, + emitSys, + sys => sys.writeFile(mainFile.path, fixed), + "Fix error", + ); // Emit on both the builders should result in same files verifyBuilder(baseline, emitBaseline, config, sys, emitSys, ts.createSemanticDiagnosticsBuilderProgram); }); it("noEmitOnError with composite writes the tsbuildinfo with pending affected files correctly", () => { - Harness.Baseline.runBaseline(`tscWatch/watchApi/noEmitOnError-with-composite-with-semantic-builder.js`, baseline.join("\r\n")); + Harness.Baseline.runBaseline( + `tscWatch/watchApi/noEmitOnError-with-composite-with-semantic-builder.js`, + baseline.join("\r\n"), + ); }); it("baseline in createEmitAndSemanticDiagnosticsBuilderProgram:: noEmitOnError with composite writes the tsbuildinfo with pending affected files correctly", () => { - Harness.Baseline.runBaseline(`tscWatch/watchApi/noEmitOnError-with-composite-with-emit-builder.js`, emitBaseline.join("\r\n")); + Harness.Baseline.runBaseline( + `tscWatch/watchApi/noEmitOnError-with-composite-with-emit-builder.js`, + emitBaseline.join("\r\n"), + ); }); }); it("SemanticDiagnosticsBuilderProgram emitDtsOnly does not update affected files pending emit", () => { // Initial - const { sys, baseline, config, mainFile } = createSystem(JSON.stringify({ compilerOptions: { composite: true, noEmitOnError: true } }), "export const x: string = 10;"); + const { sys, baseline, config, mainFile } = createSystem( + JSON.stringify({ compilerOptions: { composite: true, noEmitOnError: true } }), + "export const x: string = 10;", + ); createWatch(baseline, config, sys, ts.createSemanticDiagnosticsBuilderProgram); // Fix error and emit @@ -480,9 +572,17 @@ describe("unittests:: tsc-watch:: watchAPI:: when watchHost uses createSemanticD const diagnostics = ts.sortAndDeduplicateDiagnostics(program.getSemanticDiagnostics()); diagnostics.forEach(reportDiagnostic); // Buildinfo should still have affectedFilesPendingEmit since we are only emitting dts files - program.emit(/*targetSourceFile*/ undefined, /*writeFile*/ undefined, /*cancellationToken*/ undefined, /*emitOnlyDtsFiles*/ true); + program.emit( + /*targetSourceFile*/ undefined, + /*writeFile*/ undefined, + /*cancellationToken*/ undefined, + /*emitOnlyDtsFiles*/ true, + ); reportWatchStatus( - ts.createCompilerDiagnostic(ts.getWatchErrorSummaryDiagnosticMessage(diagnostics.length), diagnostics.length), + ts.createCompilerDiagnostic( + ts.getWatchErrorSummaryDiagnosticMessage(diagnostics.length), + diagnostics.length, + ), sys.newLine, program.getCompilerOptions(), diagnostics.length, @@ -555,7 +655,8 @@ describe("unittests:: tsc-watch:: watchAPI:: when getParsedCommandLine is implem fileExists: path => system.fileExists(path), readFile: path => system.readFile(path), getCurrentDirectory: () => system.getCurrentDirectory(), - readDirectory: (path, extensions, excludes, includes, depth) => system.readDirectory(path, extensions, excludes, includes, depth), + readDirectory: (path, extensions, excludes, includes, depth) => + system.readDirectory(path, extensions, excludes, includes, depth), onUnRecoverableConfigFileDiagnostic: ts.noop, }); }; @@ -575,18 +676,29 @@ describe("unittests:: tsc-watch:: watchAPI:: when getParsedCommandLine is implem caption: "Add class3 to project1", edit: sys => { calledGetParsedCommandLine.clear(); - sys.writeFile(`/user/username/projects/myproject/projects/project1/class3.ts`, `class class3 {}`); + sys.writeFile( + `/user/username/projects/myproject/projects/project1/class3.ts`, + `class class3 {}`, + ); }, timeouts: sys => sys.runQueuedTimeoutCallbacks(), }, { caption: "Add excluded file to project1", - edit: sys => sys.ensureFileOrFolder({ path: `/user/username/projects/myproject/projects/project1/temp/file.d.ts`, content: `declare class file {}` }), + edit: sys => + sys.ensureFileOrFolder({ + path: `/user/username/projects/myproject/projects/project1/temp/file.d.ts`, + content: `declare class file {}`, + }), timeouts: sys => sys.logTimeoutQueueLength(), }, { caption: "Add output of class3", - edit: sys => sys.writeFile(`/user/username/projects/myproject/projects/project1/class3.d.ts`, `declare class class3 {}`), + edit: sys => + sys.writeFile( + `/user/username/projects/myproject/projects/project1/class3.d.ts`, + `declare class class3 {}`, + ), timeouts: sys => sys.logTimeoutQueueLength(), }, ], @@ -598,7 +710,8 @@ describe("unittests:: tsc-watch:: watchAPI:: when getParsedCommandLine is implem const { watch, baseline, config2, calledGetParsedCommandLine } = setup(); runWatchBaseline({ scenario: "watchApi", - subScenario: "when new file is added to the referenced project with host implementing getParsedCommandLine without implementing useSourceOfProjectReferenceRedirect", + subScenario: + "when new file is added to the referenced project with host implementing getParsedCommandLine without implementing useSourceOfProjectReferenceRedirect", commandLineArgs: ["--w", "-p", config2.path, "--extendedDiagnostics"], ...baseline, edits: [ @@ -606,18 +719,29 @@ describe("unittests:: tsc-watch:: watchAPI:: when getParsedCommandLine is implem caption: "Add class3 to project1", edit: sys => { calledGetParsedCommandLine.clear(); - sys.writeFile(`/user/username/projects/myproject/projects/project1/class3.ts`, `class class3 {}`); + sys.writeFile( + `/user/username/projects/myproject/projects/project1/class3.ts`, + `class class3 {}`, + ); }, timeouts: sys => sys.runQueuedTimeoutCallbacks(), }, { caption: "Add class3 output to project1", - edit: sys => sys.writeFile(`/user/username/projects/myproject/projects/project1/class3.d.ts`, `declare class class3 {}`), + edit: sys => + sys.writeFile( + `/user/username/projects/myproject/projects/project1/class3.d.ts`, + `declare class class3 {}`, + ), timeouts: sys => sys.runQueuedTimeoutCallbacks(), }, { caption: "Add excluded file to project1", - edit: sys => sys.ensureFileOrFolder({ path: `/user/username/projects/myproject/projects/project1/temp/file.d.ts`, content: `declare class file {}` }), + edit: sys => + sys.ensureFileOrFolder({ + path: `/user/username/projects/myproject/projects/project1/temp/file.d.ts`, + content: `declare class file {}`, + }), timeouts: sys => sys.logTimeoutQueueLength(), }, { @@ -627,7 +751,11 @@ describe("unittests:: tsc-watch:: watchAPI:: when getParsedCommandLine is implem }, { caption: "Add output of class3", - edit: sys => sys.writeFile(`/user/username/projects/myproject/projects/project1/class3.d.ts`, `declare class class3 {}`), + edit: sys => + sys.writeFile( + `/user/username/projects/myproject/projects/project1/class3.d.ts`, + `declare class class3 {}`, + ), timeouts: sys => sys.runQueuedTimeoutCallbacks(), }, ], @@ -677,7 +805,12 @@ describe("unittests:: tsc-watch:: watchAPI:: when builder emit occurs with emitO caption: "Emit with emitOnlyDts shouldnt emit anything", edit: () => { const program = watch.getCurrentProgram(); - program.emit(/*targetSourceFile*/ undefined, /*writeFile*/ undefined, /*cancellationToken*/ undefined, /*emitOnlyDtsFiles*/ true); + program.emit( + /*targetSourceFile*/ undefined, + /*writeFile*/ undefined, + /*cancellationToken*/ undefined, + /*emitOnlyDtsFiles*/ true, + ); baseline.cb(program); }, timeouts: sys => sys.logTimeoutQueueLength(), @@ -695,7 +828,12 @@ describe("unittests:: tsc-watch:: watchAPI:: when builder emit occurs with emitO caption: "Emit with emitOnlyDts shouldnt emit anything", edit: () => { const program = watch.getCurrentProgram(); - program.emit(/*targetSourceFile*/ undefined, /*writeFile*/ undefined, /*cancellationToken*/ undefined, /*emitOnlyDtsFiles*/ true); + program.emit( + /*targetSourceFile*/ undefined, + /*writeFile*/ undefined, + /*cancellationToken*/ undefined, + /*emitOnlyDtsFiles*/ true, + ); baseline.cb(program); }, timeouts: sys => sys.logTimeoutQueueLength(), @@ -719,7 +857,12 @@ describe("unittests:: tsc-watch:: watchAPI:: when builder emit occurs with emitO } else { program.getSemanticDiagnostics(); // Get Diagnostics - program.emit(/*targetSourceFile*/ undefined, /*writeFile*/ undefined, /*cancellationToken*/ undefined, /*emitOnlyDtsFiles*/ true); + program.emit( + /*targetSourceFile*/ undefined, + /*writeFile*/ undefined, + /*cancellationToken*/ undefined, + /*emitOnlyDtsFiles*/ true, + ); baseline.cb(program); } } @@ -762,7 +905,8 @@ describe("unittests:: tsc-watch:: watchAPI:: when creating program with project fileExists: path => system.fileExists(path), readFile: path => system.readFile(path), getCurrentDirectory: () => system.getCurrentDirectory(), - readDirectory: (path, extensions, excludes, includes, depth) => system.readDirectory(path, extensions, excludes, includes, depth), + readDirectory: (path, extensions, excludes, includes, depth) => + system.readDirectory(path, extensions, excludes, includes, depth), onUnRecoverableConfigFileDiagnostic: ts.noop, }, )!; diff --git a/src/testRunner/unittests/tscWatch/watchEnvironment.ts b/src/testRunner/unittests/tscWatch/watchEnvironment.ts index fb9b5c362540c..23ad8b46c2071 100644 --- a/src/testRunner/unittests/tscWatch/watchEnvironment.ts +++ b/src/testRunner/unittests/tscWatch/watchEnvironment.ts @@ -66,7 +66,8 @@ describe("unittests:: tsc-watch:: watchEnvironment:: tsc-watch with different po timeouts: (sys, programs) => { const initialProgram = programs[0][0]; const mediumPollingIntervalThreshold = ts.unchangedPollThresholds[ts.PollingInterval.Medium]; - const newThreshold = ts.unchangedPollThresholds[ts.PollingInterval.Low] + mediumPollingIntervalThreshold; + const newThreshold = ts.unchangedPollThresholds[ts.PollingInterval.Low] + + mediumPollingIntervalThreshold; for (let fileUnchangeDetected = 1; fileUnchangeDetected < newThreshold; fileUnchangeDetected++) { // For high + Medium/low polling interval sys.runQueuedTimeoutCallbacks(); @@ -182,9 +183,15 @@ describe("unittests:: tsc-watch:: watchEnvironment:: tsc-watch with different po verifyRenamingFileInSubFolder("uses watchFile when renaming file in subfolder", Tsc_WatchDirectory.WatchFile); - verifyRenamingFileInSubFolder("uses non recursive watchDirectory when renaming file in subfolder", Tsc_WatchDirectory.NonRecursiveWatchDirectory); + verifyRenamingFileInSubFolder( + "uses non recursive watchDirectory when renaming file in subfolder", + Tsc_WatchDirectory.NonRecursiveWatchDirectory, + ); - verifyRenamingFileInSubFolder("uses non recursive dynamic polling when renaming file in subfolder", Tsc_WatchDirectory.DynamicPolling); + verifyRenamingFileInSubFolder( + "uses non recursive dynamic polling when renaming file in subfolder", + Tsc_WatchDirectory.DynamicPolling, + ); verifyTscWatch({ scenario, @@ -288,7 +295,11 @@ describe("unittests:: tsc-watch:: watchEnvironment:: tsc-watch with different po }, { caption: "npm install index file in file2", - edit: sys => sys.writeFile(`/user/username/projects/myproject/node_modules/file2/index.d.ts`, `export const x = 10;`), + edit: sys => + sys.writeFile( + `/user/username/projects/myproject/node_modules/file2/index.d.ts`, + `export const x = 10;`, + ), timeouts: sys => sys.logTimeoutQueueLength(), // To update folder structure }, { @@ -333,7 +344,8 @@ describe("unittests:: tsc-watch:: watchEnvironment:: tsc-watch with different po noopChange, { caption: "Add new file, should schedule and run timeout to update directory watcher", - edit: sys => sys.writeFile(`/user/username/projects/myproject/src/file3.ts`, `export const y = 10;`), + edit: sys => + sys.writeFile(`/user/username/projects/myproject/src/file3.ts`, `export const y = 10;`), timeouts: sys => sys.runQueuedTimeoutCallbacks(), // Update the child watch }, { @@ -342,7 +354,8 @@ describe("unittests:: tsc-watch:: watchEnvironment:: tsc-watch with different po timeouts: sys => sys.runQueuedTimeoutCallbacks(), // Scheduling failed lookup update and program update }, { - caption: "After program emit with new file, should schedule and run timeout to update directory watcher", + caption: + "After program emit with new file, should schedule and run timeout to update directory watcher", edit: ts.noop, timeouts: sys => sys.runQueuedTimeoutCallbacks(), // Update the child watch }, @@ -374,7 +387,11 @@ describe("unittests:: tsc-watch:: watchEnvironment:: tsc-watch with different po noopChange, { caption: "rename the file", - edit: sys => sys.renameFile(`/user/username/projects/myproject/src/file2.ts`, `/user/username/projects/myproject/src/renamed.ts`), + edit: sys => + sys.renameFile( + `/user/username/projects/myproject/src/file2.ts`, + `/user/username/projects/myproject/src/renamed.ts`, + ), // 1. For updating program and 2. for updating child watches timeouts: sys => sys.runQueuedTimeoutCallbacks(1), // Update program }, @@ -487,7 +504,10 @@ describe("unittests:: tsc-watch:: watchEnvironment:: tsc-watch with different po content: "export function temp(): string;", }; const files = [libFile, main, bar, foo, fooBar, temp, configFile]; - return createWatchedSystem(files, { currentDirectory: "/user/username/projects/myproject", runWithoutRecursiveWatches }); + return createWatchedSystem(files, { + currentDirectory: "/user/username/projects/myproject", + runWithoutRecursiveWatches, + }); } function verifyWorker(...additionalFlags: string[]) { @@ -499,7 +519,12 @@ describe("unittests:: tsc-watch:: watchEnvironment:: tsc-watch with different po edits: [ { caption: "Change foo", - edit: sys => sys.replaceFileText(`/user/username/projects/myproject/node_modules/bar/foo.d.ts`, "foo", "fooBar"), + edit: sys => + sys.replaceFileText( + `/user/username/projects/myproject/node_modules/bar/foo.d.ts`, + "foo", + "fooBar", + ), timeouts: sys => sys.logTimeoutQueueLength(), }, ], @@ -513,7 +538,8 @@ describe("unittests:: tsc-watch:: watchEnvironment:: tsc-watch with different po edits: [ { caption: "delete fooBar", - edit: sys => sys.deleteFile(`/user/username/projects/myproject/node_modules/bar/fooBar.d.ts`), + edit: sys => + sys.deleteFile(`/user/username/projects/myproject/node_modules/bar/fooBar.d.ts`), timeouts: sys => sys.logTimeoutQueueLength(), }, ], @@ -521,7 +547,9 @@ describe("unittests:: tsc-watch:: watchEnvironment:: tsc-watch with different po verifyTscWatch({ scenario, - subScenario: `watchOptions/with excludeDirectories option with recursive directory watching${additionalFlags.join("")}`, + subScenario: `watchOptions/with excludeDirectories option with recursive directory watching${ + additionalFlags.join("") + }`, commandLineArgs: ["-w", ...additionalFlags], sys: () => sys({ excludeDirectories: ["**/temp"] }, /*runWithoutRecursiveWatches*/ true), edits: [ @@ -532,7 +560,11 @@ describe("unittests:: tsc-watch:: watchEnvironment:: tsc-watch with different po }, { caption: "add new folder to temp", - edit: sys => sys.ensureFileOrFolder({ path: `/user/username/projects/myproject/node_modules/bar/temp/fooBar/index.d.ts`, content: "export function temp(): string;" }), + edit: sys => + sys.ensureFileOrFolder({ + path: `/user/username/projects/myproject/node_modules/bar/temp/fooBar/index.d.ts`, + content: "export function temp(): string;", + }), timeouts: sys => sys.logTimeoutQueueLength(), }, ], @@ -567,15 +599,24 @@ describe("unittests:: tsc-watch:: watchEnvironment:: tsc-watch with different po // vm's wq generates this kind of event // Skip delete event so inode changes but when the create's rename occurs file is on disk edit: sys => - sys.modifyFile(`/user/username/projects/myproject/foo.ts`, `export declare function foo2(): string;`, { - invokeFileDeleteCreateAsPartInsteadOfChange: true, - ignoreDelete: true, - }), + sys.modifyFile( + `/user/username/projects/myproject/foo.ts`, + `export declare function foo2(): string;`, + { + invokeFileDeleteCreateAsPartInsteadOfChange: true, + ignoreDelete: true, + }, + ), timeouts: sys => sys.runQueuedTimeoutCallbacks(), }, { caption: "Replace file with rename event that fixes error", - edit: sys => sys.modifyFile(`/user/username/projects/myproject/foo.ts`, `export declare function foo(): string;`, { invokeFileDeleteCreateAsPartInsteadOfChange: true }), + edit: sys => + sys.modifyFile( + `/user/username/projects/myproject/foo.ts`, + `export declare function foo(): string;`, + { invokeFileDeleteCreateAsPartInsteadOfChange: true }, + ), timeouts: sys => sys.runQueuedTimeoutCallbacks(), }, ], @@ -592,7 +633,10 @@ describe("unittests:: tsc-watch:: watchEnvironment:: tsc-watch with different po [libFile.path]: libFile.content, [`/user/username/projects/myproject/main.ts`]: `import { foo } from "./foo"; foo();`, [`/user/username/projects/myproject/foo.d.ts`]: `export function foo(): string;`, - [`/user/username/projects/myproject/tsconfig.json`]: JSON.stringify({ watchOptions: { watchFile: "useFsEvents" }, files: ["foo.d.ts", "main.ts"] }), + [`/user/username/projects/myproject/tsconfig.json`]: JSON.stringify({ + watchOptions: { watchFile: "useFsEvents" }, + files: ["foo.d.ts", "main.ts"], + }), }, { currentDirectory: "/user/username/projects/myproject", @@ -602,12 +646,20 @@ describe("unittests:: tsc-watch:: watchEnvironment:: tsc-watch with different po edits: [ { caption: "Replace file with rename event that introduces error", - edit: sys => sys.modifyFile(`/user/username/projects/myproject/foo.d.ts`, `export function foo2(): string;`, { invokeFileDeleteCreateAsPartInsteadOfChange: true }), + edit: sys => + sys.modifyFile( + `/user/username/projects/myproject/foo.d.ts`, + `export function foo2(): string;`, + { invokeFileDeleteCreateAsPartInsteadOfChange: true }, + ), timeouts: sys => sys.runQueuedTimeoutCallbacks(), }, { caption: "Replace file with rename event that fixes error", - edit: sys => sys.modifyFile(`/user/username/projects/myproject/foo.d.ts`, `export function foo(): string;`, { invokeFileDeleteCreateAsPartInsteadOfChange: true }), + edit: sys => + sys.modifyFile(`/user/username/projects/myproject/foo.d.ts`, `export function foo(): string;`, { + invokeFileDeleteCreateAsPartInsteadOfChange: true, + }), timeouts: sys => sys.runQueuedTimeoutCallbacks(), }, ], @@ -623,7 +675,10 @@ describe("unittests:: tsc-watch:: watchEnvironment:: tsc-watch with different po [libFile.path]: libFile.content, [`/user/username/projects/myproject/main.ts`]: `import { foo } from "./foo"; foo();`, [`/user/username/projects/myproject/foo.d.ts`]: `export function foo(): string;`, - [`/user/username/projects/myproject/tsconfig.json`]: JSON.stringify({ watchOptions: { watchFile: "useFsEvents" }, files: ["foo.d.ts", "main.ts"] }), + [`/user/username/projects/myproject/tsconfig.json`]: JSON.stringify({ + watchOptions: { watchFile: "useFsEvents" }, + files: ["foo.d.ts", "main.ts"], + }), }, { currentDirectory: "/user/username/projects/myproject", @@ -633,12 +688,24 @@ describe("unittests:: tsc-watch:: watchEnvironment:: tsc-watch with different po edits: [ { caption: "Replace file with rename event that introduces error", - edit: sys => sys.modifyFile(`/user/username/projects/myproject/foo.d.ts`, `export function foo2(): string;`, { invokeFileDeleteCreateAsPartInsteadOfChange: true, useTildeAsSuffixInRenameEventFileName: true }), + edit: sys => + sys.modifyFile( + `/user/username/projects/myproject/foo.d.ts`, + `export function foo2(): string;`, + { + invokeFileDeleteCreateAsPartInsteadOfChange: true, + useTildeAsSuffixInRenameEventFileName: true, + }, + ), timeouts: sys => sys.runQueuedTimeoutCallbacks(), }, { caption: "Replace file with rename event that fixes error", - edit: sys => sys.modifyFile(`/user/username/projects/myproject/foo.d.ts`, `export function foo(): string;`, { invokeFileDeleteCreateAsPartInsteadOfChange: true, useTildeAsSuffixInRenameEventFileName: true }), + edit: sys => + sys.modifyFile(`/user/username/projects/myproject/foo.d.ts`, `export function foo(): string;`, { + invokeFileDeleteCreateAsPartInsteadOfChange: true, + useTildeAsSuffixInRenameEventFileName: true, + }), timeouts: sys => sys.runQueuedTimeoutCallbacks(), }, ], @@ -646,7 +713,8 @@ describe("unittests:: tsc-watch:: watchEnvironment:: tsc-watch with different po verifyTscWatch({ scenario, - subScenario: `fsWatch/when using file watching thats on inode when rename occurs when file is still on the disk`, + subScenario: + `fsWatch/when using file watching thats on inode when rename occurs when file is still on the disk`, commandLineArgs: ["-w", "--extendedDiagnostics"], sys: () => createWatchedSystem( @@ -670,16 +738,25 @@ describe("unittests:: tsc-watch:: watchEnvironment:: tsc-watch with different po // vm's wq generates this kind of event // Skip delete event so inode changes but when the create's rename occurs file is on disk edit: sys => - sys.modifyFile(`/user/username/projects/myproject/foo.ts`, `export declare function foo2(): string;`, { - invokeFileDeleteCreateAsPartInsteadOfChange: true, - ignoreDelete: true, - skipInodeCheckOnCreate: true, - }), + sys.modifyFile( + `/user/username/projects/myproject/foo.ts`, + `export declare function foo2(): string;`, + { + invokeFileDeleteCreateAsPartInsteadOfChange: true, + ignoreDelete: true, + skipInodeCheckOnCreate: true, + }, + ), timeouts: sys => sys.runQueuedTimeoutCallbacks(), }, { caption: "Replace file with rename event that fixes error", - edit: sys => sys.modifyFile(`/user/username/projects/myproject/foo.ts`, `export declare function foo(): string;`, { invokeFileDeleteCreateAsPartInsteadOfChange: true }), + edit: sys => + sys.modifyFile( + `/user/username/projects/myproject/foo.ts`, + `export declare function foo(): string;`, + { invokeFileDeleteCreateAsPartInsteadOfChange: true }, + ), timeouts: sys => sys.runQueuedTimeoutCallbacks(), }, ], @@ -703,7 +780,13 @@ describe("unittests:: tsc-watch:: watchEnvironment:: tsc-watch with different po }, { caption: "receive another change event without modifying the file", - edit: sys => sys.invokeFsWatches("/user/username/projects/project/main.ts", "change", /*modifiedTime*/ undefined, /*useTildeSuffix*/ undefined), + edit: sys => + sys.invokeFsWatches( + "/user/username/projects/project/main.ts", + "change", + /*modifiedTime*/ undefined, + /*useTildeSuffix*/ undefined, + ), timeouts: sys => sys.runQueuedTimeoutCallbacks(), }, { @@ -713,7 +796,13 @@ describe("unittests:: tsc-watch:: watchEnvironment:: tsc-watch with different po }, { caption: "receive another change event without modifying the file", - edit: sys => sys.invokeFsWatches("/user/username/projects/project/main.ts", "change", /*modifiedTime*/ undefined, /*useTildeSuffix*/ undefined), + edit: sys => + sys.invokeFsWatches( + "/user/username/projects/project/main.ts", + "change", + /*modifiedTime*/ undefined, + /*useTildeSuffix*/ undefined, + ), timeouts: sys => sys.runQueuedTimeoutCallbacks(), }, ], diff --git a/src/testRunner/unittests/tsserver/autoImportProvider.ts b/src/testRunner/unittests/tsserver/autoImportProvider.ts index dfa7eb11506cd..c42c6b23cb89a 100644 --- a/src/testRunner/unittests/tsserver/autoImportProvider.ts +++ b/src/testRunner/unittests/tsserver/autoImportProvider.ts @@ -49,7 +49,9 @@ describe("unittests:: tsserver:: autoImportProvider", () => { indexTs, ]); openFilesForSession([indexTs], session); - assert.isUndefined(projectService.configuredProjects.get(tsconfig.path)!.getLanguageService().getAutoImportProvider()); + assert.isUndefined( + projectService.configuredProjects.get(tsconfig.path)!.getLanguageService().getAutoImportProvider(), + ); baselineTsserverLogs("autoImportProvider", "without dependencies listed", session); }); @@ -62,7 +64,9 @@ describe("unittests:: tsserver:: autoImportProvider", () => { { path: indexTs.path, content: "import '@angular/forms';" }, ]); openFilesForSession([indexTs], session); - assert.isUndefined(projectService.configuredProjects.get(tsconfig.path)!.getLanguageService().getAutoImportProvider()); + assert.isUndefined( + projectService.configuredProjects.get(tsconfig.path)!.getLanguageService().getAutoImportProvider(), + ); baselineTsserverLogs("autoImportProvider", "dependencies are already in main program", session); }); @@ -87,15 +91,37 @@ describe("unittests:: tsserver:: autoImportProvider", () => { }); it("Auto-importable file is in inferred project until imported", () => { - const { projectService, session, updateFile } = setup([angularFormsDts, angularFormsPackageJson, tsconfig, packageJson, indexTs]); + const { projectService, session, updateFile } = setup([ + angularFormsDts, + angularFormsPackageJson, + tsconfig, + packageJson, + indexTs, + ]); openFilesForSession([angularFormsDts], session); - session.logger.log(`Default Project for ${angularFormsDts.path}:: ${projectService.getDefaultProjectForFile(angularFormsDts.path as ts.server.NormalizedPath, /*ensureProject*/ true)?.projectName}`); + session.logger.log( + `Default Project for ${angularFormsDts.path}:: ${projectService.getDefaultProjectForFile( + angularFormsDts.path as ts.server.NormalizedPath, + /*ensureProject*/ true, + )?.projectName}`, + ); updateFile(indexTs.path, "import '@angular/forms'"); - session.logger.log(`Default Project for ${angularFormsDts.path}:: ${projectService.getDefaultProjectForFile(angularFormsDts.path as ts.server.NormalizedPath, /*ensureProject*/ true)?.projectName}`); + session.logger.log( + `Default Project for ${angularFormsDts.path}:: ${projectService.getDefaultProjectForFile( + angularFormsDts.path as ts.server.NormalizedPath, + /*ensureProject*/ true, + )?.projectName}`, + ); - assert.isUndefined(projectService.configuredProjects.get(tsconfig.path)!.getLanguageService().getAutoImportProvider()); - baselineTsserverLogs("autoImportProvider", "Auto-importable file is in inferred project until imported", session); + assert.isUndefined( + projectService.configuredProjects.get(tsconfig.path)!.getLanguageService().getAutoImportProvider(), + ); + baselineTsserverLogs( + "autoImportProvider", + "Auto-importable file is in inferred project until imported", + session, + ); }); it("Responds to package.json changes", () => { @@ -108,7 +134,9 @@ describe("unittests:: tsserver:: autoImportProvider", () => { ]); openFilesForSession([indexTs], session); - assert.isUndefined(projectService.configuredProjects.get(tsconfig.path)!.getLanguageService().getAutoImportProvider()); + assert.isUndefined( + projectService.configuredProjects.get(tsconfig.path)!.getLanguageService().getAutoImportProvider(), + ); host.writeFile(packageJson.path, packageJson.content); assert.ok(projectService.configuredProjects.get(tsconfig.path)!.getLanguageService().getAutoImportProvider()); @@ -125,7 +153,8 @@ describe("unittests:: tsserver:: autoImportProvider", () => { ]); openFilesForSession([indexTs], session); - const autoImportProvider = projectService.configuredProjects.get(tsconfig.path)!.getLanguageService().getAutoImportProvider(); + const autoImportProvider = projectService.configuredProjects.get(tsconfig.path)!.getLanguageService() + .getAutoImportProvider(); assert.ok(autoImportProvider); updateFile(indexTs.path, "console.log(0)"); @@ -133,7 +162,11 @@ describe("unittests:: tsserver:: autoImportProvider", () => { projectService.configuredProjects.get(tsconfig.path)!.getLanguageService().getAutoImportProvider(), autoImportProvider, ); - baselineTsserverLogs("autoImportProvider", "Reuses autoImportProvider when program structure is unchanged", session); + baselineTsserverLogs( + "autoImportProvider", + "Reuses autoImportProvider when program structure is unchanged", + session, + ); }); it("Closes AutoImportProviderProject when host project closes", () => { @@ -154,7 +187,11 @@ describe("unittests:: tsserver:: autoImportProvider", () => { hostProject.close(); assert.ok(autoImportProviderProject && autoImportProviderProject.isClosed()); assert.isUndefined(hostProject.autoImportProviderHost); - baselineTsserverLogs("autoImportProvider", "Closes AutoImportProviderProject when host project closes", session); + baselineTsserverLogs( + "autoImportProvider", + "Closes AutoImportProviderProject when host project closes", + session, + ); }); it("Does not schedule ensureProjectForOpenFiles on AutoImportProviderProject creation", () => { @@ -176,7 +213,11 @@ describe("unittests:: tsserver:: autoImportProvider", () => { host.writeFile(packageJson.path, packageJson.content); hostProject.getPackageJsonAutoImportProvider(); assert.isFalse(projectService.pendingEnsureProjectForOpenFiles); - baselineTsserverLogs("autoImportProvider", "Does not schedule ensureProjectForOpenFiles on AutoImportProviderProject creation", session); + baselineTsserverLogs( + "autoImportProvider", + "Does not schedule ensureProjectForOpenFiles on AutoImportProviderProject creation", + session, + ); }); it("Responds to automatic changes in node_modules", () => { @@ -192,7 +233,9 @@ describe("unittests:: tsserver:: autoImportProvider", () => { openFilesForSession([indexTs], session); const project = projectService.configuredProjects.get(tsconfig.path)!; - const completionsBefore = project.getLanguageService().getCompletionsAtPosition(indexTs.path, 0, { includeCompletionsForModuleExports: true }); + const completionsBefore = project.getLanguageService().getCompletionsAtPosition(indexTs.path, 0, { + includeCompletionsForModuleExports: true, + }); assert.isTrue(completionsBefore?.entries.some(c => c.name === "PatternValidator")); // Directory watchers only fire for add/remove, not change. @@ -201,7 +244,9 @@ describe("unittests:: tsserver:: autoImportProvider", () => { host.writeFile(angularFormsDts.path, ""); const autoImportProvider = project.getLanguageService().getAutoImportProvider(); - const completionsAfter = project.getLanguageService().getCompletionsAtPosition(indexTs.path, 0, { includeCompletionsForModuleExports: true }); + const completionsAfter = project.getLanguageService().getCompletionsAtPosition(indexTs.path, 0, { + includeCompletionsForModuleExports: true, + }); assert.equal(autoImportProvider!.getSourceFile(angularFormsDts.path)!.getText(), ""); assert.isFalse(completionsAfter?.entries.some(c => c.name === "PatternValidator")); baselineTsserverLogs("autoImportProvider", "Responds to automatic changes in node_modules", session); @@ -220,11 +265,15 @@ describe("unittests:: tsserver:: autoImportProvider", () => { openFilesForSession([indexTs, angularFormsDts], session); const project = projectService.configuredProjects.get(tsconfig.path)!; - const completionsBefore = project.getLanguageService().getCompletionsAtPosition(indexTs.path, 0, { includeCompletionsForModuleExports: true }); + const completionsBefore = project.getLanguageService().getCompletionsAtPosition(indexTs.path, 0, { + includeCompletionsForModuleExports: true, + }); assert.isTrue(completionsBefore?.entries.some(c => c.name === "PatternValidator")); updateFile(angularFormsDts.path, "export class ValidatorPattern {}"); - const completionsAfter = project.getLanguageService().getCompletionsAtPosition(indexTs.path, 0, { includeCompletionsForModuleExports: true }); + const completionsAfter = project.getLanguageService().getCompletionsAtPosition(indexTs.path, 0, { + includeCompletionsForModuleExports: true, + }); assert.isFalse(completionsAfter?.entries.some(c => c.name === "PatternValidator")); assert.isTrue(completionsAfter?.entries.some(c => c.name === "ValidatorPattern")); baselineTsserverLogs("autoImportProvider", "Responds to manual changes in node_modules", session); @@ -240,7 +289,9 @@ describe("unittests:: tsserver:: autoImportProvider", () => { ]); openFilesForSession([indexTs], session); - assert.isUndefined(projectService.configuredProjects.get(tsconfig.path)!.getLanguageService().getAutoImportProvider()); + assert.isUndefined( + projectService.configuredProjects.get(tsconfig.path)!.getLanguageService().getAutoImportProvider(), + ); host.writeFile(packageJson.path, packageJson.content); assert.ok(projectService.configuredProjects.get(tsconfig.path)!.getLanguageService().getAutoImportProvider()); @@ -265,21 +316,37 @@ describe("unittests:: tsserver:: autoImportProvider", () => { openFilesForSession([indexTs], session); const project = projectService.configuredProjects.get(tsconfig.path)!; assert.isUndefined(project.getPackageJsonAutoImportProvider()); - baselineTsserverLogs("autoImportProvider", "Does not create an auto import provider if there are too many dependencies", session); + baselineTsserverLogs( + "autoImportProvider", + "Does not create an auto import provider if there are too many dependencies", + session, + ); }); it("Shared source files between AutoImportProvider and main program do not cause duplicate entries in export info map", () => { const files = [ // node_modules/memfs - AutoImportProvider only - { path: "/node_modules/memfs/package.json", content: `{ "name": "memfs", "version": "1.0.0", "types": "lib/index.d.ts" }` }, - { path: "/node_modules/memfs/lib/index.d.ts", content: `/// \nexport declare class Volume {}` }, + { + path: "/node_modules/memfs/package.json", + content: `{ "name": "memfs", "version": "1.0.0", "types": "lib/index.d.ts" }`, + }, + { + path: "/node_modules/memfs/lib/index.d.ts", + content: `/// \nexport declare class Volume {}`, + }, // node_modules/@types/node - AutoImportProvider and main program - { path: "/node_modules/@types/node/package.json", content: `{ "name": "@types/node", "version": "1.0.0" }` }, + { + path: "/node_modules/@types/node/package.json", + content: `{ "name": "@types/node", "version": "1.0.0" }`, + }, { path: "/node_modules/@types/node/index.d.ts", content: `export declare class Stats {}` }, // root - { path: "/package.json", content: `{ "dependencies": { "memfs": "*" }, "devDependencies": { "@types/node": "*" } }` }, + { + path: "/package.json", + content: `{ "dependencies": { "memfs": "*" }, "devDependencies": { "@types/node": "*" } }`, + }, { path: "/tsconfig.json", content: `{ "compilerOptions": { "types": ["node"] }` }, { path: "/index.ts", content: `export {};` }, ]; @@ -301,7 +368,11 @@ describe("unittests:: tsserver:: autoImportProvider", () => { assert.equal(seenSymbolNames.size, 2); assert.ok(seenSymbolNames.has("Stats")); assert.ok(seenSymbolNames.has("Volume")); - baselineTsserverLogs("autoImportProvider", "Shared source files between AutoImportProvider and main program", session); + baselineTsserverLogs( + "autoImportProvider", + "Shared source files between AutoImportProvider and main program", + session, + ); }); }); @@ -318,7 +389,10 @@ describe("unittests:: tsserver:: autoImportProvider - monorepo", () => { // packages/a { path: "/packages/a/package.json", content: packageJson.content }, - { path: "/packages/a/tsconfig.json", content: `{ "compilerOptions": { "composite": true }, "references": [{ "path": "../b" }] }` }, + { + path: "/packages/a/tsconfig.json", + content: `{ "compilerOptions": { "composite": true }, "references": [{ "path": "../b" }] }`, + }, { path: "/packages/a/index.ts", content: "import { B } from '../b';" }, // packages/b @@ -333,28 +407,49 @@ describe("unittests:: tsserver:: autoImportProvider - monorepo", () => { findAllReferences("/packages/b/index.ts", 1, "export class B".length - 1); // Project for A is created - ensure it doesn't have an autoImportProvider - assert.isUndefined(projectService.configuredProjects.get("/packages/a/tsconfig.json")!.getLanguageService().getAutoImportProvider()); - baselineTsserverLogs("autoImportProvider", "Does not create auto import providers upon opening projects for find-all-references", session); + assert.isUndefined( + projectService.configuredProjects.get("/packages/a/tsconfig.json")!.getLanguageService() + .getAutoImportProvider(), + ); + baselineTsserverLogs( + "autoImportProvider", + "Does not create auto import providers upon opening projects for find-all-references", + session, + ); }); it("Does not close when root files are redirects that don't actually exist", () => { const files = [ // packages/a { path: "/packages/a/package.json", content: `{ "dependencies": { "b": "*" } }` }, - { path: "/packages/a/tsconfig.json", content: `{ "compilerOptions": { "composite": true }, "references": [{ "path": "./node_modules/b" }] }` }, + { + path: "/packages/a/tsconfig.json", + content: `{ "compilerOptions": { "composite": true }, "references": [{ "path": "./node_modules/b" }] }`, + }, { path: "/packages/a/index.ts", content: "" }, // packages/b { path: "/packages/a/node_modules/b/package.json", content: `{ "types": "dist/index.d.ts" }` }, - { path: "/packages/a/node_modules/b/tsconfig.json", content: `{ "compilerOptions": { "composite": true, "outDir": "dist" } }` }, + { + path: "/packages/a/node_modules/b/tsconfig.json", + content: `{ "compilerOptions": { "composite": true, "outDir": "dist" } }`, + }, { path: "/packages/a/node_modules/b/index.ts", content: `export class B {}` }, ]; const { projectService, session } = setup(files); openFilesForSession([files[2]], session); - assert.isDefined(projectService.configuredProjects.get("/packages/a/tsconfig.json")!.getPackageJsonAutoImportProvider()); - assert.isDefined(projectService.configuredProjects.get("/packages/a/tsconfig.json")!.getPackageJsonAutoImportProvider()); - baselineTsserverLogs("autoImportProvider", "Does not close when root files are redirects that dont actually exist", session); + assert.isDefined( + projectService.configuredProjects.get("/packages/a/tsconfig.json")!.getPackageJsonAutoImportProvider(), + ); + assert.isDefined( + projectService.configuredProjects.get("/packages/a/tsconfig.json")!.getPackageJsonAutoImportProvider(), + ); + baselineTsserverLogs( + "autoImportProvider", + "Does not close when root files are redirects that dont actually exist", + session, + ); }); it("Can use the same document registry bucket key as main program", () => { diff --git a/src/testRunner/unittests/tsserver/cachingFileSystemInformation.ts b/src/testRunner/unittests/tsserver/cachingFileSystemInformation.ts index 56ffdffa297bb..72a74fbf9d629 100644 --- a/src/testRunner/unittests/tsserver/cachingFileSystemInformation.ts +++ b/src/testRunner/unittests/tsserver/cachingFileSystemInformation.ts @@ -31,13 +31,15 @@ describe("unittests:: tsserver:: CachingFileSystemInformation:: tsserverProjectS type CalledMaps = CalledMapsWithSingleArg | CalledMapsWithFiveArgs; type CalledWithFiveArgs = [readonly string[], readonly string[], readonly string[], number]; function createLoggerTrackingHostCalls(host: TestServerHost) { - const calledMaps: Record> & Record> = { - fileExists: setCallsTrackingWithSingleArgFn(CalledMapsWithSingleArg.fileExists), - directoryExists: setCallsTrackingWithSingleArgFn(CalledMapsWithSingleArg.directoryExists), - getDirectories: setCallsTrackingWithSingleArgFn(CalledMapsWithSingleArg.getDirectories), - readFile: setCallsTrackingWithSingleArgFn(CalledMapsWithSingleArg.readFile), - readDirectory: setCallsTrackingWithFiveArgFn(CalledMapsWithFiveArgs.readDirectory), - }; + const calledMaps: + & Record> + & Record> = { + fileExists: setCallsTrackingWithSingleArgFn(CalledMapsWithSingleArg.fileExists), + directoryExists: setCallsTrackingWithSingleArgFn(CalledMapsWithSingleArg.directoryExists), + getDirectories: setCallsTrackingWithSingleArgFn(CalledMapsWithSingleArg.getDirectories), + readFile: setCallsTrackingWithSingleArgFn(CalledMapsWithSingleArg.readFile), + readDirectory: setCallsTrackingWithFiveArgFn(CalledMapsWithFiveArgs.readDirectory), + }; return logCacheAndClear; @@ -62,7 +64,10 @@ describe("unittests:: tsserver:: CachingFileSystemInformation:: tsserverProjectS } function logCacheEntry(logger: Logger, callback: CalledMaps) { - const result = Array.from<[string, (true | CalledWithFiveArgs)[]], { key: string; count: number; }>(calledMaps[callback].entries(), ([key, arr]) => ({ key, count: arr.length })); + const result = Array.from<[string, (true | CalledWithFiveArgs)[]], { key: string; count: number; }>( + calledMaps[callback].entries(), + ([key, arr]) => ({ key, count: arr.length }), + ); logger.info(`${callback}:: ${JSON.stringify(result)}`); calledMaps[callback].clear(); } @@ -133,7 +138,11 @@ describe("unittests:: tsserver:: CachingFileSystemInformation:: tsserverProjectS logCacheAndClear(projectService.logger); // setting compiler options discards module resolution cache - projectService.setCompilerOptionsForInferredProjects({ module: ts.ModuleKind.AMD, noLib: true, target: ts.ScriptTarget.ES5 }); + projectService.setCompilerOptionsForInferredProjects({ + module: ts.ModuleKind.AMD, + noLib: true, + target: ts.ScriptTarget.ES5, + }); logSemanticDiagnostics(projectService, project, imported); logCacheAndClear(projectService.logger); baselineTsserverLogs("cachingFileSystemInformation", "works using legacy resolution logic", projectService); @@ -309,7 +318,13 @@ describe("unittests:: tsserver:: CachingFileSystemInformation:: tsserverProjectS projectService.openClientFile(file3.path); logCacheAndClear(projectService.logger); - baselineTsserverLogs("cachingFileSystemInformation", `watchDirectories for config file with case ${useCaseSensitiveFileNames ? "" : "in"}sensitive file system`, projectService); + baselineTsserverLogs( + "cachingFileSystemInformation", + `watchDirectories for config file with case ${ + useCaseSensitiveFileNames ? "" : "in" + }sensitive file system`, + projectService, + ); }); } verifyWatchDirectoriesCaseSensitivity(/*useCaseSensitiveFileNames*/ false); @@ -354,7 +369,11 @@ describe("unittests:: tsserver:: CachingFileSystemInformation:: tsserverProjectS logSemanticDiagnostics(service, project, file1); logSemanticDiagnostics(service, project, file2); - baselineTsserverLogs("cachingFileSystemInformation", `includes the parent folder FLLs in ${resolution} module resolution mode`, service); + baselineTsserverLogs( + "cachingFileSystemInformation", + `includes the parent folder FLLs in ${resolution} module resolution mode`, + service, + ); } it("Includes the parent folder FLLs in node module resolution mode", () => { @@ -421,8 +440,16 @@ describe("unittests:: tsserver:: CachingFileSystemInformation:: tsserverProjectS { path: "/a/b/node_modules/.staging/symbol-observable-24bcbbff" }, { path: "/a/b/node_modules/.staging/rxjs-22375c61" }, { path: "/a/b/node_modules/.staging/typescript-8493ea5d" }, - { path: "/a/b/node_modules/.staging/symbol-observable-24bcbbff/package.json", content: '{\n "name": "symbol-observable",\n "version": "1.0.4",\n "description": "Symbol.observable ponyfill",\n "license": "MIT",\n "repository": "blesh/symbol-observable",\n "author": {\n "name": "Ben Lesh",\n "email": "ben@benlesh.com"\n },\n "engines": {\n "node": ">=0.10.0"\n },\n "scripts": {\n "test": "npm run build && mocha && tsc ./ts-test/test.ts && node ./ts-test/test.js && check-es3-syntax -p lib/ --kill",\n "build": "babel es --out-dir lib",\n "prepublish": "npm test"\n },\n "files": [\n "' }, - { path: "/a/b/node_modules/.staging/lodash-b0733faa/package.json", content: '{\n "name": "lodash",\n "version": "4.17.4",\n "description": "Lodash modular utilities.",\n "keywords": "modules, stdlib, util",\n "homepage": "https://lodash.com/",\n "repository": "lodash/lodash",\n "icon": "https://lodash.com/icon.svg",\n "license": "MIT",\n "main": "lodash.js",\n "author": "John-David Dalton (http://allyoucanleet.com/)",\n "contributors": [\n "John-David Dalton (http://allyoucanleet.com/)",\n "Mathias Bynens =0.10.0"\n },\n "scripts": {\n "test": "npm run build && mocha && tsc ./ts-test/test.ts && node ./ts-test/test.js && check-es3-syntax -p lib/ --kill",\n "build": "babel es --out-dir lib",\n "prepublish": "npm test"\n },\n "files": [\n "', + }, + { + path: "/a/b/node_modules/.staging/lodash-b0733faa/package.json", + content: + '{\n "name": "lodash",\n "version": "4.17.4",\n "description": "Lodash modular utilities.",\n "keywords": "modules, stdlib, util",\n "homepage": "https://lodash.com/",\n "repository": "lodash/lodash",\n "icon": "https://lodash.com/icon.svg",\n "license": "MIT",\n "main": "lodash.js",\n "author": "John-David Dalton (http://allyoucanleet.com/)",\n "contributors": [\n "John-David Dalton (http://allyoucanleet.com/)",\n "Mathias Bynens =4.2.0"\n },\n "devDependencies": {\n "@types/browserify": "latest",\n "@types/chai": "latest",\n "@types/convert-source-map": "latest",\n "@types/del": "latest",\n "@types/glob": "latest",\n "@types/gulp": "latest",\n "@types/gulp-concat": "latest",\n "@types/gulp-help": "latest",\n "@types/gulp-newer": "latest",\n "@types/gulp-sourcemaps": "latest",\n "@types/merge2": "latest",\n "@types/minimatch": "latest",\n "@types/minimist": "latest",\n "@types/mkdirp": "latest",\n "@types/mocha": "latest",\n "@types/node": "latest",\n "@types/q": "latest",\n "@types/run-sequence": "latest",\n "@types/through2": "latest",\n "browserify": "latest",\n "chai": "latest",\n "convert-source-map": "latest",\n "del": "latest",\n "gulp": "latest",\n "gulp-clone": "latest",\n "gulp-concat": "latest",\n "gulp-help": "latest",\n "gulp-insert": "latest",\n "gulp-newer": "latest",\n "gulp-sourcemaps": "latest",\n "gulp-typescript": "latest",\n "into-stream": "latest",\n "istanbul": "latest",\n "jake": "latest",\n "merge2": "latest",\n "minimist": "latest",\n "mkdirp": "latest",\n "mocha": "latest",\n "mocha-fivemat-progress-reporter": "latest",\n "q": "latest",\n "run-sequence": "latest",\n "sorcery": "latest",\n "through2": "latest",\n "travis-fold": "latest",\n "ts-node": "latest",\n "eslint": "5.16.0",\n "typescript": "^2.4"\n },\n "scripts": {\n "pretest": "jake tests",\n "test": "jake runtests-parallel",\n "build": "npm run build:compiler && npm run build:tests",\n "build:compiler": "jake local",\n "build:tests": "jake tests",\n "start": "node lib/tsc",\n "clean": "jake clean",\n "gulp": "gulp",\n "jake": "jake",\n "lint": "jake lint",\n "setup-hooks": "node scripts/link-hooks.js"\n },\n "browser": {\n "buffer": false,\n "fs": false,\n "os": false,\n "path": false\n }\n}', }, - { path: "/a/b/node_modules/.staging/symbol-observable-24bcbbff/index.js", content: "module.exports = require('./lib/index');\n" }, - { path: "/a/b/node_modules/.staging/symbol-observable-24bcbbff/index.d.ts", content: "declare const observableSymbol: symbol;\nexport default observableSymbol;\n" }, + { + path: "/a/b/node_modules/.staging/symbol-observable-24bcbbff/index.js", + content: "module.exports = require('./lib/index');\n", + }, + { + path: "/a/b/node_modules/.staging/symbol-observable-24bcbbff/index.d.ts", + content: "declare const observableSymbol: symbol;\nexport default observableSymbol;\n", + }, { path: "/a/b/node_modules/.staging/symbol-observable-24bcbbff/lib" }, - { path: "/a/b/node_modules/.staging/symbol-observable-24bcbbff/lib/index.js", content: "'use strict';\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _ponyfill = require('./ponyfill');\n\nvar _ponyfill2 = _interopRequireDefault(_ponyfill);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }\n\nvar root; /* global window */\n\n\nif (typeof self !== 'undefined') {\n root = self;\n} else if (typeof window !== 'undefined') {\n root = window;\n} else if (typeof global !== 'undefined') {\n root = global;\n} else if (typeof module !== 'undefined') {\n root = module;\n} else {\n root = Function('return this')();\n}\n\nvar result = (0, _ponyfill2['default'])(root);\nexports['default'] = result;" }, + { + path: "/a/b/node_modules/.staging/symbol-observable-24bcbbff/lib/index.js", + content: + "'use strict';\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _ponyfill = require('./ponyfill');\n\nvar _ponyfill2 = _interopRequireDefault(_ponyfill);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }\n\nvar root; /* global window */\n\n\nif (typeof self !== 'undefined') {\n root = self;\n} else if (typeof window !== 'undefined') {\n root = window;\n} else if (typeof global !== 'undefined') {\n root = global;\n} else if (typeof module !== 'undefined') {\n root = module;\n} else {\n root = Function('return this')();\n}\n\nvar result = (0, _ponyfill2['default'])(root);\nexports['default'] = result;", + }, ].map(getRootedFileOrFolder); verifyAfterPartialOrCompleteNpmInstall(); @@ -448,7 +485,10 @@ describe("unittests:: tsserver:: CachingFileSystemInformation:: tsserverProjectS content: '{\n "name": "@types/lodash",\n "version": "4.14.74",\n "description": "TypeScript definitions for Lo-Dash",\n "license": "MIT",\n "contributors": [\n {\n "name": "Brian Zengel",\n "url": "https://github.com/bczengel"\n },\n {\n "name": "Ilya Mochalov",\n "url": "https://github.com/chrootsu"\n },\n {\n "name": "Stepan Mikhaylyuk",\n "url": "https://github.com/stepancar"\n },\n {\n "name": "Eric L Anderson",\n "url": "https://github.com/ericanderson"\n },\n {\n "name": "AJ Richardson",\n "url": "https://github.com/aj-r"\n },\n {\n "name": "Junyoung Clare Jang",\n "url": "https://github.com/ailrun"\n }\n ],\n "main": "",\n "repository": {\n "type": "git",\n "url": "https://www.github.com/DefinitelyTyped/DefinitelyTyped.git"\n },\n "scripts": {},\n "dependencies": {},\n "typesPublisherContentHash": "12af578ffaf8d86d2df37e591857906a86b983fa9258414326544a0fe6af0de8",\n "typeScriptVersion": "2.2"\n}', }, - { path: "/a/b/node_modules/.staging/lodash-b0733faa/index.js", content: "module.exports = require('./lodash');" }, + { + path: "/a/b/node_modules/.staging/lodash-b0733faa/index.js", + content: "module.exports = require('./lodash');", + }, { path: "/a/b/node_modules/.staging/typescript-8493ea5d/package.json.3017591594", content: "" }, ].map(getRootedFileOrFolder)); // Since we added/removed in .staging no timeout @@ -463,7 +503,11 @@ describe("unittests:: tsserver:: CachingFileSystemInformation:: tsserverProjectS { path: "/a/b/node_modules/.staging/rxjs-22375c61/bundles" }, { path: "/a/b/node_modules/.staging/rxjs-22375c61/operator" }, { path: "/a/b/node_modules/.staging/rxjs-22375c61/src/add/observable/dom" }, - { path: "/a/b/node_modules/.staging/@types/lodash-e56c4fe7/index.d.ts", content: "\n// Stub for lodash\nexport = _;\nexport as namespace _;\ndeclare var _: _.LoDashStatic;\ndeclare namespace _ {\n interface LoDashStatic {\n someProp: string;\n }\n class SomeClass {\n someMethod(): void;\n }\n}" }, + { + path: "/a/b/node_modules/.staging/@types/lodash-e56c4fe7/index.d.ts", + content: + "\n// Stub for lodash\nexport = _;\nexport as namespace _;\ndeclare var _: _.LoDashStatic;\ndeclare namespace _ {\n interface LoDashStatic {\n someProp: string;\n }\n class SomeClass {\n someMethod(): void;\n }\n}", + }, ].map(getRootedFileOrFolder)); verifyAfterPartialOrCompleteNpmInstall(); @@ -509,7 +553,10 @@ describe("unittests:: tsserver:: CachingFileSystemInformation:: tsserverProjectS baselineTsserverLogs( "cachingFileSystemInformation", - `npm install works when ${timeoutDuringPartialInstallation ? "timeout occurs inbetween installation" : "timeout occurs after installation"}`, + `npm install works when ${ + timeoutDuringPartialInstallation ? "timeout occurs inbetween installation" + : "timeout occurs after installation" + }`, projectService, ); @@ -566,7 +613,11 @@ describe("unittests:: tsserver:: CachingFileSystemInformation:: tsserverProjectS host.writeFile(debugTypesFile.path, debugTypesFile.content); host.runQueuedTimeoutCallbacks(); logSemanticDiagnostics(service, project, app); - baselineTsserverLogs("cachingFileSystemInformation", "when node_modules dont receive event for the @types file addition", service); + baselineTsserverLogs( + "cachingFileSystemInformation", + "when node_modules dont receive event for the @types file addition", + service, + ); }); it("when creating new file in symlinked folder", () => { diff --git a/src/testRunner/unittests/tsserver/cancellationToken.ts b/src/testRunner/unittests/tsserver/cancellationToken.ts index 5fc573e00f3fb..67643a4d02143 100644 --- a/src/testRunner/unittests/tsserver/cancellationToken.ts +++ b/src/testRunner/unittests/tsserver/cancellationToken.ts @@ -30,7 +30,8 @@ describe("unittests:: tsserver:: cancellationToken", () => { const host = createServerHost([f1]); const cancellationToken: ts.server.ServerCancellationToken = { isCancellationRequested: () => false, - setRequest: requestId => session.logger.log(`ServerCancellationToken:: Cancellation Request id:: ${requestId}`), + setRequest: requestId => + session.logger.log(`ServerCancellationToken:: Cancellation Request id:: ${requestId}`), resetRequest: ts.noop, }; @@ -207,7 +208,9 @@ describe("unittests:: tsserver:: cancellationToken", () => { } baselineTsserverLogs("cancellationT", "Lower priority tasks are cancellable", session); - function verifyExecuteCommandSeqIsCancellable(request: TestSessionRequest) { + function verifyExecuteCommandSeqIsCancellable( + request: TestSessionRequest, + ) { // Set the next request to be cancellable // The cancellation token will cancel the request the third time // isCancellationRequested() is called. @@ -218,10 +221,14 @@ describe("unittests:: tsserver:: cancellationToken", () => { session.executeCommandSeq(request); } catch (e) { - session.logger.log(`Exception is OperationCanceledException: ${e instanceof ts.OperationCanceledException}`); + session.logger.log( + `Exception is OperationCanceledException: ${e instanceof ts.OperationCanceledException}`, + ); operationCanceledExceptionThrown = true; } - if (!operationCanceledExceptionThrown) session.logger.log("Operation Canceled Exception not thrown for request: " + JSON.stringify(request)); + if (!operationCanceledExceptionThrown) { + session.logger.log("Operation Canceled Exception not thrown for request: " + JSON.stringify(request)); + } } }); }); diff --git a/src/testRunner/unittests/tsserver/compileOnSave.ts b/src/testRunner/unittests/tsserver/compileOnSave.ts index 0dcd6bb7dd740..16f50af26f1ee 100644 --- a/src/testRunner/unittests/tsserver/compileOnSave.ts +++ b/src/testRunner/unittests/tsserver/compileOnSave.ts @@ -55,7 +55,15 @@ describe("unittests:: tsserver:: compileOnSave:: affected list", () => { it("should contains only itself if a module file's shape didn't change, and all files referencing it if its shape changed", () => { const { moduleFile1, file1Consumer1, file1Consumer2, moduleFile2, globalFile3, configFile } = files(); - const host = createServerHost([moduleFile1, file1Consumer1, file1Consumer2, globalFile3, moduleFile2, configFile, libFile]); + const host = createServerHost([ + moduleFile1, + file1Consumer1, + file1Consumer2, + globalFile3, + moduleFile2, + configFile, + libFile, + ]); const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) }); openFilesForSession([moduleFile1, file1Consumer1], session); @@ -102,7 +110,15 @@ describe("unittests:: tsserver:: compileOnSave:: affected list", () => { it("should be up-to-date with the reference map changes", () => { const { moduleFile1, file1Consumer1, file1Consumer2, moduleFile2, globalFile3, configFile } = files(); - const host = createServerHost([moduleFile1, file1Consumer1, file1Consumer2, globalFile3, moduleFile2, configFile, libFile]); + const host = createServerHost([ + moduleFile1, + file1Consumer1, + file1Consumer2, + globalFile3, + moduleFile2, + configFile, + libFile, + ]); const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) }); openFilesForSession([moduleFile1, file1Consumer1], session); @@ -175,7 +191,15 @@ describe("unittests:: tsserver:: compileOnSave:: affected list", () => { it("should be up-to-date with changes made in non-open files", () => { const { moduleFile1, file1Consumer1, file1Consumer2, moduleFile2, globalFile3, configFile } = files(); - const host = createServerHost([moduleFile1, file1Consumer1, file1Consumer2, globalFile3, moduleFile2, configFile, libFile]); + const host = createServerHost([ + moduleFile1, + file1Consumer1, + file1Consumer2, + globalFile3, + moduleFile2, + configFile, + libFile, + ]); const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) }); openFilesForSession([moduleFile1], session); @@ -208,7 +232,15 @@ describe("unittests:: tsserver:: compileOnSave:: affected list", () => { it("should be up-to-date with deleted files", () => { const { moduleFile1, file1Consumer1, file1Consumer2, moduleFile2, globalFile3, configFile } = files(); - const host = createServerHost([moduleFile1, file1Consumer1, file1Consumer2, globalFile3, moduleFile2, configFile, libFile]); + const host = createServerHost([ + moduleFile1, + file1Consumer1, + file1Consumer2, + globalFile3, + moduleFile2, + configFile, + libFile, + ]); const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) }); openFilesForSession([moduleFile1], session); @@ -239,7 +271,15 @@ describe("unittests:: tsserver:: compileOnSave:: affected list", () => { it("should be up-to-date with newly created files", () => { const { moduleFile1, file1Consumer1, file1Consumer2, moduleFile2, globalFile3, configFile } = files(); - const host = createServerHost([moduleFile1, file1Consumer1, file1Consumer2, globalFile3, moduleFile2, configFile, libFile]); + const host = createServerHost([ + moduleFile1, + file1Consumer1, + file1Consumer2, + globalFile3, + moduleFile2, + configFile, + libFile, + ]); const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) }); openFilesForSession([moduleFile1], session); @@ -338,7 +378,15 @@ describe("unittests:: tsserver:: compileOnSave:: affected list", () => { it("should return all files if a global file changed shape", () => { const { moduleFile1, file1Consumer1, file1Consumer2, moduleFile2, globalFile3, configFile } = files(); - const host = createServerHost([moduleFile1, file1Consumer1, file1Consumer2, globalFile3, moduleFile2, configFile, libFile]); + const host = createServerHost([ + moduleFile1, + file1Consumer1, + file1Consumer2, + globalFile3, + moduleFile2, + configFile, + libFile, + ]); const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) }); openFilesForSession([globalFile3], session); @@ -417,7 +465,14 @@ describe("unittests:: tsserver:: compileOnSave:: affected list", () => { }`, }; - const host = createServerHost([moduleFile1, file1Consumer1, file1Consumer2, configFile2, configFile, libFile]); + const host = createServerHost([ + moduleFile1, + file1Consumer1, + file1Consumer2, + configFile2, + configFile, + libFile, + ]); const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) }); openFilesForSession([moduleFile1, file1Consumer1], session); @@ -503,7 +558,14 @@ describe("unittests:: tsserver:: compileOnSave:: affected list", () => { path: "/a/b/file1Consumer1Consumer1.ts", content: `import {y} from "./file1Consumer1";`, }; - const host = createServerHost([moduleFile1, file1Consumer1, file1Consumer1Consumer1, globalFile3, configFile, libFile]); + const host = createServerHost([ + moduleFile1, + file1Consumer1, + file1Consumer1Consumer1, + globalFile3, + configFile, + libFile, + ]); const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) }); openFilesForSession([moduleFile1, file1Consumer1], session); @@ -630,7 +692,12 @@ describe("unittests:: tsserver:: compileOnSave:: affected list", () => { }); describe("for changes in declaration files", () => { - function testDTS(subScenario: string, dtsFileContents: string, tsFileContents: string, opts: ts.CompilerOptions) { + function testDTS( + subScenario: string, + dtsFileContents: string, + tsFileContents: string, + opts: ts.CompilerOptions, + ) { it(subScenario, () => { const dtsFile = { path: "/a/runtime/a.d.ts", @@ -728,7 +795,9 @@ describe("unittests:: tsserver:: compileOnSave:: affected list", () => { }); } test("compileOnSaveAffectedFileList projectUsesOutFile should not be returned if not set", {}); - test("compileOnSaveAffectedFileList projectUsesOutFile should be true if outFile is set", { outFile: "/a/out.js" }); + test("compileOnSaveAffectedFileList projectUsesOutFile should be true if outFile is set", { + outFile: "/a/out.js", + }); test("compileOnSaveAffectedFileList projectUsesOutFile should be true if out is set", { out: "/a/out.js" }); }); }); @@ -749,7 +818,9 @@ describe("unittests:: tsserver:: compileOnSave:: EmitFile test", () => { }; const host = createServerHost([f], { newLine }); logger.host = host; - logger.log(`currentDirectory:: ${host.getCurrentDirectory()} useCaseSensitiveFileNames: ${host.useCaseSensitiveFileNames} newLine: ${host.newLine}`); + logger.log( + `currentDirectory:: ${host.getCurrentDirectory()} useCaseSensitiveFileNames: ${host.useCaseSensitiveFileNames} newLine: ${host.newLine}`, + ); const session = createSession(host, { logger }); openFilesForSession([f], session); session.executeCommandSeq({ @@ -969,7 +1040,11 @@ function bar() { // Change file2 get affected file list = will return only file2 if --declaration otherwise all files verifyLocalEdit(file2, "world", "hello"); - baselineTsserverLogs("compileOnSave", `emit in project${hasModule ? " with module" : ""}${declaration ? " with dts emit" : ""}`, session); + baselineTsserverLogs( + "compileOnSave", + `emit in project${hasModule ? " with module" : ""}${declaration ? " with dts emit" : ""}`, + session, + ); function verifyFileSave(file: File) { session.executeCommandSeq({ @@ -1019,8 +1094,20 @@ describe("unittests:: tsserver:: compileOnSave:: CompileOnSaveAffectedFileListRe } function logDirtyOfProjects(session: TestSession) { - session.logger.log(`Project1 is dirty: ${session.getProjectService().configuredProjects.get(`/user/username/projects/myproject/app1/tsconfig.json`)!.dirty}`); - session.logger.log(`Project2 is dirty: ${session.getProjectService().configuredProjects.get(`/user/username/projects/myproject/app2/tsconfig.json`)!.dirty}`); + session.logger.log( + `Project1 is dirty: ${ + session.getProjectService().configuredProjects.get( + `/user/username/projects/myproject/app1/tsconfig.json`, + )!.dirty + }`, + ); + session.logger.log( + `Project2 is dirty: ${ + session.getProjectService().configuredProjects.get( + `/user/username/projects/myproject/app2/tsconfig.json`, + )!.dirty + }`, + ); } function verify(subScenario: string, commandArgs: ts.server.protocol.FileRequestArgs) { diff --git a/src/testRunner/unittests/tsserver/completions.ts b/src/testRunner/unittests/tsserver/completions.ts index 01f6415a0cb8a..5ac9cd1ca0623 100644 --- a/src/testRunner/unittests/tsserver/completions.ts +++ b/src/testRunner/unittests/tsserver/completions.ts @@ -50,7 +50,11 @@ describe("unittests:: tsserver:: completions", () => { command: ts.server.protocol.CommandTypes.CompletionDetails, arguments: { ...requestLocation, - entryNames: [{ name: "foo", source: "/a", data: { exportName: "foo", fileName: "/a.ts", exportMapKey } }], + entryNames: [{ + name: "foo", + source: "/a", + data: { exportName: "foo", fileName: "/a.ts", exportMapKey }, + }], }, }); @@ -62,7 +66,11 @@ describe("unittests:: tsserver:: completions", () => { command: ts.server.protocol.CommandTypes.CompletionDetailsFull, arguments: { ...requestLocation, - entryNames: [{ name: "foo", source: "/a", data: { exportName: "foo", fileName: "/a.ts", exportMapKey } }], + entryNames: [{ + name: "foo", + source: "/a", + data: { exportName: "foo", fileName: "/a.ts", exportMapKey }, + }], }, }); baselineTsserverLogs("completions", "works", session); @@ -194,6 +202,10 @@ export interface BrowserRouterProps { includeInsertTextCompletions: true, }, }); - baselineTsserverLogs("completions", "works when files are included from two different drives of windows", session); + baselineTsserverLogs( + "completions", + "works when files are included from two different drives of windows", + session, + ); }); }); diff --git a/src/testRunner/unittests/tsserver/completionsIncomplete.ts b/src/testRunner/unittests/tsserver/completionsIncomplete.ts index e98ffd9b7742c..026060c495d33 100644 --- a/src/testRunner/unittests/tsserver/completionsIncomplete.ts +++ b/src/testRunner/unittests/tsserver/completionsIncomplete.ts @@ -17,7 +17,12 @@ function createExportingModuleFile(path: string, exportPrefix: string, exportCou }; } -function createExportingModuleFiles(pathPrefix: string, fileCount: number, exportCount: number, getExportPrefix: (fileIndex: number) => string): File[] { +function createExportingModuleFiles( + pathPrefix: string, + fileCount: number, + exportCount: number, + getExportPrefix: (fileIndex: number) => string, +): File[] { return ts.arrayOf(fileCount, fileIndex => createExportingModuleFile( `${pathPrefix}_${fileIndex}.ts`, @@ -26,8 +31,18 @@ function createExportingModuleFiles(pathPrefix: string, fileCount: number, expor )); } -function createNodeModulesPackage(packageName: string, fileCount: number, exportCount: number, getExportPrefix: (fileIndex: number) => string): File[] { - const exportingFiles = createExportingModuleFiles(`/node_modules/${packageName}/file`, fileCount, exportCount, getExportPrefix); +function createNodeModulesPackage( + packageName: string, + fileCount: number, + exportCount: number, + getExportPrefix: (fileIndex: number) => string, +): File[] { + const exportingFiles = createExportingModuleFiles( + `/node_modules/${packageName}/file`, + fileCount, + exportCount, + getExportPrefix, + ); return [ { path: `/node_modules/${packageName}/package.json`, @@ -36,7 +51,13 @@ function createNodeModulesPackage(packageName: string, fileCount: number, export { path: `/node_modules/${packageName}/index.d.ts`, content: exportingFiles - .map(f => `export * from "./${ts.removeFileExtension(ts.convertToRelativePath(f.path, `/node_modules/${packageName}/`, ts.identity))}";`) + .map(f => + `export * from "./${ + ts.removeFileExtension( + ts.convertToRelativePath(f.path, `/node_modules/${packageName}/`, ts.identity), + ) + }";` + ) .join("\n") + `\nexport default function main(): void;`, }, ...exportingFiles, @@ -61,24 +82,47 @@ const packageJsonFile: File = { describe("unittests:: tsserver:: completionsIncomplete", () => { it("works", () => { const excessFileCount = ts.Completions.moduleSpecifierResolutionLimit + 50; - const exportingFiles = createExportingModuleFiles(`/lib/a`, ts.Completions.moduleSpecifierResolutionLimit + excessFileCount, 1, i => `aa_${i}_`); + const exportingFiles = createExportingModuleFiles( + `/lib/a`, + ts.Completions.moduleSpecifierResolutionLimit + excessFileCount, + 1, + i => `aa_${i}_`, + ); const { typeToTriggerCompletions, session } = setup([tsconfigFile, indexFile, ...exportingFiles]); openFilesForSession([indexFile], session); typeToTriggerCompletions(indexFile.path, "a", completions => { assert(completions.isIncomplete); - assert.lengthOf(completions.entries.filter(entry => (entry.data as any)?.moduleSpecifier), ts.Completions.moduleSpecifierResolutionLimit); - assert.lengthOf(completions.entries.filter(entry => entry.source && !(entry.data as any)?.moduleSpecifier), excessFileCount); - assert.deepEqual(completions.optionalReplacementSpan, { start: { line: 1, offset: 1 }, end: { line: 1, offset: 2 } }); + assert.lengthOf( + completions.entries.filter(entry => (entry.data as any)?.moduleSpecifier), + ts.Completions.moduleSpecifierResolutionLimit, + ); + assert.lengthOf( + completions.entries.filter(entry => entry.source && !(entry.data as any)?.moduleSpecifier), + excessFileCount, + ); + assert.deepEqual(completions.optionalReplacementSpan, { + start: { line: 1, offset: 1 }, + end: { line: 1, offset: 2 }, + }); }) .continueTyping("a", completions => { assert(completions.isIncomplete); - assert.lengthOf(completions.entries.filter(entry => (entry.data as any)?.moduleSpecifier), ts.Completions.moduleSpecifierResolutionLimit * 2); - assert.deepEqual(completions.optionalReplacementSpan, { start: { line: 1, offset: 1 }, end: { line: 1, offset: 3 } }); + assert.lengthOf( + completions.entries.filter(entry => (entry.data as any)?.moduleSpecifier), + ts.Completions.moduleSpecifierResolutionLimit * 2, + ); + assert.deepEqual(completions.optionalReplacementSpan, { + start: { line: 1, offset: 1 }, + end: { line: 1, offset: 3 }, + }); }) .continueTyping("_", completions => { assert(!completions.isIncomplete); - assert.lengthOf(completions.entries.filter(entry => (entry.data as any)?.moduleSpecifier), exportingFiles.length); + assert.lengthOf( + completions.entries.filter(entry => (entry.data as any)?.moduleSpecifier), + exportingFiles.length, + ); }); baselineTsserverLogs("completionsIncomplete", "works", session); }); @@ -91,19 +135,32 @@ describe("unittests:: tsserver:: completionsIncomplete", () => { typeToTriggerCompletions(indexFile.path, "a", completions => { assert(!completions.isIncomplete); }); - baselineTsserverLogs("completionsIncomplete", "resolves more when available from module specifier cache (1)", session); + baselineTsserverLogs( + "completionsIncomplete", + "resolves more when available from module specifier cache (1)", + session, + ); }); it("resolves more when available from module specifier cache (2)", () => { const excessFileCount = 50; - const exportingFiles = createExportingModuleFiles(`/lib/a`, ts.Completions.moduleSpecifierResolutionLimit + excessFileCount, 1, i => `aa_${i}_`); + const exportingFiles = createExportingModuleFiles( + `/lib/a`, + ts.Completions.moduleSpecifierResolutionLimit + excessFileCount, + 1, + i => `aa_${i}_`, + ); const { typeToTriggerCompletions, session } = setup([tsconfigFile, indexFile, ...exportingFiles]); openFilesForSession([indexFile], session); typeToTriggerCompletions(indexFile.path, "a", completions => assert(completions.isIncomplete)) .backspace() .type("a", completions => assert(!completions.isIncomplete)); - baselineTsserverLogs("completionsIncomplete", "resolves more when available from module specifier cache (2)", session); + baselineTsserverLogs( + "completionsIncomplete", + "resolves more when available from module specifier cache (2)", + session, + ); }); it("ambient module specifier resolutions do not count against the resolution limit", () => { @@ -112,27 +169,58 @@ describe("unittests:: tsserver:: completionsIncomplete", () => { content: `declare module "ambient_${i}" { export const aa_${i} = ${i}; }`, })); - const exportingFiles = createExportingModuleFiles(`/lib/a`, ts.Completions.moduleSpecifierResolutionLimit, 5, i => `aa_${i}_`); - const { typeToTriggerCompletions, session } = setup([tsconfigFile, indexFile, ...ambientFiles, ...exportingFiles]); + const exportingFiles = createExportingModuleFiles( + `/lib/a`, + ts.Completions.moduleSpecifierResolutionLimit, + 5, + i => `aa_${i}_`, + ); + const { typeToTriggerCompletions, session } = setup([ + tsconfigFile, + indexFile, + ...ambientFiles, + ...exportingFiles, + ]); openFilesForSession([indexFile], session); typeToTriggerCompletions(indexFile.path, "a", completions => { assert(!completions.isIncomplete); - assert.lengthOf(completions.entries.filter(e => (e.data as any)?.moduleSpecifier), ambientFiles.length * 5 + exportingFiles.length); + assert.lengthOf( + completions.entries.filter(e => (e.data as any)?.moduleSpecifier), + ambientFiles.length * 5 + exportingFiles.length, + ); }); - baselineTsserverLogs("completionsIncomplete", "ambient module specifier resolutions do not count against the resolution limit", session); + baselineTsserverLogs( + "completionsIncomplete", + "ambient module specifier resolutions do not count against the resolution limit", + session, + ); }); it("works with PackageJsonAutoImportProvider", () => { - const exportingFiles = createExportingModuleFiles(`/lib/a`, ts.Completions.moduleSpecifierResolutionLimit, 1, i => `aa_${i}_`); + const exportingFiles = createExportingModuleFiles( + `/lib/a`, + ts.Completions.moduleSpecifierResolutionLimit, + 1, + i => `aa_${i}_`, + ); const nodeModulesPackage = createNodeModulesPackage("dep-a", 50, 1, i => `depA_${i}_`); - const { typeToTriggerCompletions, assertCompletionDetailsOk, session } = setup([tsconfigFile, packageJsonFile, indexFile, ...exportingFiles, ...nodeModulesPackage]); + const { typeToTriggerCompletions, assertCompletionDetailsOk, session } = setup([ + tsconfigFile, + packageJsonFile, + indexFile, + ...exportingFiles, + ...nodeModulesPackage, + ]); openFilesForSession([indexFile], session); typeToTriggerCompletions(indexFile.path, "a", completions => assert(completions.isIncomplete)) .continueTyping("_", completions => { assert(!completions.isIncomplete); - assert.lengthOf(completions.entries.filter(entry => (entry.data as any)?.moduleSpecifier?.startsWith("dep-a")), 50); + assert.lengthOf( + completions.entries.filter(entry => (entry.data as any)?.moduleSpecifier?.startsWith("dep-a")), + 50, + ); assertCompletionDetailsOk( indexFile.path, completions.entries.find(entry => (entry.data as any)?.moduleSpecifier?.startsWith("dep-a"))!, @@ -149,7 +237,12 @@ describe("unittests:: tsserver:: completionsIncomplete", () => { declare const exp: {} & { [K in Signals]: K }; export = exp;`, }; - const exportingFiles = createExportingModuleFiles("/lib/a", ts.Completions.moduleSpecifierResolutionLimit, 1, i => `S${i}`); + const exportingFiles = createExportingModuleFiles( + "/lib/a", + ts.Completions.moduleSpecifierResolutionLimit, + 1, + i => `S${i}`, + ); const { typeToTriggerCompletions, session } = setup([tsconfigFile, indexFile, ...exportingFiles, constantsDts]); openFilesForSession([indexFile], session); @@ -185,12 +278,25 @@ function setup(files: File[]) { return { host, session, projectService, typeToTriggerCompletions, assertCompletionDetailsOk }; - function typeToTriggerCompletions(fileName: string, typedCharacters: string, cb?: (completions: ts.server.protocol.CompletionInfo) => void) { - const project = projectService.getDefaultProjectForFile(ts.server.toNormalizedPath(fileName), /*ensureProject*/ true)!; + function typeToTriggerCompletions( + fileName: string, + typedCharacters: string, + cb?: (completions: ts.server.protocol.CompletionInfo) => void, + ) { + const project = projectService.getDefaultProjectForFile( + ts.server.toNormalizedPath(fileName), + /*ensureProject*/ true, + )!; return type(typedCharacters, cb, /*isIncompleteContinuation*/ false); - function type(typedCharacters: string, cb: ((completions: ts.server.protocol.CompletionInfo) => void) | undefined, isIncompleteContinuation: boolean) { - const file = ts.Debug.checkDefined(project.getLanguageService(/*ensureSynchronized*/ true).getProgram()?.getSourceFile(fileName)); + function type( + typedCharacters: string, + cb: ((completions: ts.server.protocol.CompletionInfo) => void) | undefined, + isIncompleteContinuation: boolean, + ) { + const file = ts.Debug.checkDefined( + project.getLanguageService(/*ensureSynchronized*/ true).getProgram()?.getSourceFile(fileName), + ); const { line, character } = ts.getLineAndCharacterOfPosition(file, file.text.length); const oneBasedEditPosition = { line: line + 1, offset: character + 1 }; session.executeCommandSeq({ @@ -222,17 +328,25 @@ function setup(files: File[]) { cb?.(ts.Debug.checkDefined(response)); return { backspace, - continueTyping: (typedCharacters: string, cb: (completions: ts.server.protocol.CompletionInfo) => void) => { + continueTyping: ( + typedCharacters: string, + cb: (completions: ts.server.protocol.CompletionInfo) => void, + ) => { return type(typedCharacters, cb, !!response.isIncomplete); }, }; } function backspace(n = 1) { - const file = ts.Debug.checkDefined(project.getLanguageService(/*ensureSynchronized*/ true).getProgram()?.getSourceFile(fileName)); + const file = ts.Debug.checkDefined( + project.getLanguageService(/*ensureSynchronized*/ true).getProgram()?.getSourceFile(fileName), + ); const startLineCharacter = ts.getLineAndCharacterOfPosition(file, file.text.length - n); const endLineCharacter = ts.getLineAndCharacterOfPosition(file, file.text.length); - const oneBasedStartPosition = { line: startLineCharacter.line + 1, offset: startLineCharacter.character + 1 }; + const oneBasedStartPosition = { + line: startLineCharacter.line + 1, + offset: startLineCharacter.character + 1, + }; const oneBasedEndPosition = { line: endLineCharacter.line + 1, offset: endLineCharacter.character + 1 }; session.executeCommandSeq({ command: ts.server.protocol.CommandTypes.UpdateOpen, @@ -258,8 +372,13 @@ function setup(files: File[]) { } function assertCompletionDetailsOk(fileName: string, entry: ts.server.protocol.CompletionEntry) { - const project = projectService.getDefaultProjectForFile(ts.server.toNormalizedPath(fileName), /*ensureProject*/ true)!; - const file = ts.Debug.checkDefined(project.getLanguageService(/*ensureSynchronized*/ true).getProgram()?.getSourceFile(fileName)); + const project = projectService.getDefaultProjectForFile( + ts.server.toNormalizedPath(fileName), + /*ensureProject*/ true, + )!; + const file = ts.Debug.checkDefined( + project.getLanguageService(/*ensureSynchronized*/ true).getProgram()?.getSourceFile(fileName), + ); const { line, character } = ts.getLineAndCharacterOfPosition(file, file.text.length - 1); const details = session.executeCommandSeq({ command: ts.server.protocol.CommandTypes.CompletionDetails, @@ -277,7 +396,11 @@ function setup(files: File[]) { assert(details[0]); assert(details[0].codeActions); - assert(details[0].codeActions[0].changes[0].textChanges[0].newText.includes(`"${(entry.data as any).moduleSpecifier}"`)); + assert( + details[0].codeActions[0].changes[0].textChanges[0].newText.includes( + `"${(entry.data as any).moduleSpecifier}"`, + ), + ); return details; } } diff --git a/src/testRunner/unittests/tsserver/configFileSearch.ts b/src/testRunner/unittests/tsserver/configFileSearch.ts index e250ae54fa965..6e95d8c1f608b 100644 --- a/src/testRunner/unittests/tsserver/configFileSearch.ts +++ b/src/testRunner/unittests/tsserver/configFileSearch.ts @@ -50,7 +50,11 @@ describe("unittests:: tsserver:: configFileSearch:: searching for config file", // Delete config file - should create inferred project and not configured project host.deleteFile(configFile.path); host.runQueuedTimeoutCallbacks(); - baselineTsserverLogs("configFileSearch", "should use projectRootPath when searching for inferred project again", service); + baselineTsserverLogs( + "configFileSearch", + "should use projectRootPath when searching for inferred project again", + service, + ); }); it("should use projectRootPath when searching for inferred project again 2", () => { @@ -79,7 +83,11 @@ describe("unittests:: tsserver:: configFileSearch:: searching for config file", // Delete config file - should create inferred project with project root path set host.deleteFile(configFile.path); host.runQueuedTimeoutCallbacks(); - baselineTsserverLogs("configFileSearch", "should use projectRootPath when searching for inferred project again 2", service); + baselineTsserverLogs( + "configFileSearch", + "should use projectRootPath when searching for inferred project again 2", + service, + ); }); describe("when the opened file is not from project root", () => { @@ -95,7 +103,12 @@ describe("unittests:: tsserver:: configFileSearch:: searching for config file", function openClientFile(files: File[]) { const host = createServerHost(files); const projectService = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) }); - projectService.openClientFile(file.path, /*fileContent*/ undefined, /*scriptKind*/ undefined, "/a/b/projects/proj"); + projectService.openClientFile( + file.path, + /*fileContent*/ undefined, + /*scriptKind*/ undefined, + "/a/b/projects/proj", + ); return { host, projectService }; } @@ -128,7 +141,9 @@ describe("unittests:: tsserver:: configFileSearch:: searching for config file", function verifyConfigFileWatch(scenario: string, projectRootPath: string | undefined) { it(scenario, () => { const path = `/root/teams/VSCode68/Shared Documents/General/jt-ts-test-workspace/x.js`; - const host = createServerHost([libFile, { path, content: "const x = 10" }], { useCaseSensitiveFileNames: true }); + const host = createServerHost([libFile, { path, content: "const x = 10" }], { + useCaseSensitiveFileNames: true, + }); const service = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) }); service.openClientFile(path, /*fileContent*/ undefined, /*scriptKind*/ undefined, projectRootPath); baselineTsserverLogs("configFileSearch", scenario, service); diff --git a/src/testRunner/unittests/tsserver/configuredProjects.ts b/src/testRunner/unittests/tsserver/configuredProjects.ts index 0f524e010e49b..38d46e6850fb0 100644 --- a/src/testRunner/unittests/tsserver/configuredProjects.ts +++ b/src/testRunner/unittests/tsserver/configuredProjects.ts @@ -53,7 +53,10 @@ describe("unittests:: tsserver:: ConfiguredProjects", () => { const { configFileName, configFileErrors } = projectService.openClientFile(file1.path); assert(configFileName, "should find config file"); - assert.isTrue(!configFileErrors || configFileErrors.length === 0, `expect no errors in config file, got ${JSON.stringify(configFileErrors)}`); + assert.isTrue( + !configFileErrors || configFileErrors.length === 0, + `expect no errors in config file, got ${JSON.stringify(configFileErrors)}`, + ); baselineTsserverLogs("configuredProjects", "create configured project without file list", projectService); }); @@ -85,7 +88,10 @@ describe("unittests:: tsserver:: ConfiguredProjects", () => { const { configFileName, configFileErrors } = projectService.openClientFile(file1.path); assert(configFileName, "should find config file"); - assert.isTrue(!configFileErrors || configFileErrors.length === 0, `expect no errors in config file, got ${JSON.stringify(configFileErrors)}`); + assert.isTrue( + !configFileErrors || configFileErrors.length === 0, + `expect no errors in config file, got ${JSON.stringify(configFileErrors)}`, + ); baselineTsserverLogs("configuredProjects", "create configured project with the file list", projectService); }); @@ -120,7 +126,11 @@ describe("unittests:: tsserver:: ConfiguredProjects", () => { host.deleteFile(configFile.path); host.runQueuedTimeoutCallbacks(); // Refresh inferred projects - baselineTsserverLogs("configuredProjects", "add and then remove a config file in a folder with loose files", projectService); + baselineTsserverLogs( + "configuredProjects", + "add and then remove a config file in a folder with loose files", + projectService, + ); }); it("add new files to a configured project without file list", () => { @@ -135,7 +145,11 @@ describe("unittests:: tsserver:: ConfiguredProjects", () => { // add a new ts file host.writeFile(commonFile2.path, commonFile2.content); host.runQueuedTimeoutCallbacks(); - baselineTsserverLogs("configuredProjects", "add new files to a configured project without file list", projectService); + baselineTsserverLogs( + "configuredProjects", + "add new files to a configured project without file list", + projectService, + ); }); it("should ignore non-existing files specified in the config file", () => { @@ -153,7 +167,11 @@ describe("unittests:: tsserver:: ConfiguredProjects", () => { const projectService = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) }); projectService.openClientFile(commonFile1.path); projectService.openClientFile(commonFile2.path); - baselineTsserverLogs("configuredProjects", "should ignore non-existing files specified in the config file", projectService); + baselineTsserverLogs( + "configuredProjects", + "should ignore non-existing files specified in the config file", + projectService, + ); }); it("handle recreated files correctly", () => { @@ -245,7 +263,11 @@ describe("unittests:: tsserver:: ConfiguredProjects", () => { // Open random file and it will reuse first inferred project projectService.openClientFile(randomFile.path); - baselineTsserverLogs("configuredProjects", "should properly handle module resolution changes in config file", projectService); + baselineTsserverLogs( + "configuredProjects", + "should properly handle module resolution changes in config file", + projectService, + ); }); it("should keep the configured project when the opened file is referenced by the project but not its root", () => { @@ -271,7 +293,11 @@ describe("unittests:: tsserver:: ConfiguredProjects", () => { projectService.openClientFile(file1.path); projectService.closeClientFile(file1.path); projectService.openClientFile(file2.path); - baselineTsserverLogs("configuredProjects", "should keep the configured project when the opened file is referenced by the project but not its root", projectService); + baselineTsserverLogs( + "configuredProjects", + "should keep the configured project when the opened file is referenced by the project but not its root", + projectService, + ); }); it("should tolerate config file errors and still try to build a project", () => { @@ -288,7 +314,11 @@ describe("unittests:: tsserver:: ConfiguredProjects", () => { const host = createServerHost([commonFile1, commonFile2, libFile, configFile]); const projectService = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) }); projectService.openClientFile(commonFile1.path); - baselineTsserverLogs("configuredProjects", "should tolerate config file errors and still try to build a project", projectService); + baselineTsserverLogs( + "configuredProjects", + "should tolerate config file errors and still try to build a project", + projectService, + ); }); it("should reuse same project if file is opened from the configured project that has no open files", () => { @@ -310,7 +340,10 @@ describe("unittests:: tsserver:: ConfiguredProjects", () => { }`, }; const host = createServerHost([file1, file2, configFile, libFile]); - const projectService = createProjectService(host, { useSingleInferredProject: true, logger: createLoggerWithInMemoryLogs(host) }); + const projectService = createProjectService(host, { + useSingleInferredProject: true, + logger: createLoggerWithInMemoryLogs(host), + }); projectService.openClientFile(file1.path); logConfiguredProjectsHasOpenRefStatus(projectService); // file1 @@ -319,7 +352,11 @@ describe("unittests:: tsserver:: ConfiguredProjects", () => { projectService.openClientFile(file2.path); logConfiguredProjectsHasOpenRefStatus(projectService); // file2 - baselineTsserverLogs("configuredProjects", "should reuse same project if file is opened from the configured project that has no open files", projectService); + baselineTsserverLogs( + "configuredProjects", + "should reuse same project if file is opened from the configured project that has no open files", + projectService, + ); }); it("should not close configured project after closing last open file, but should be closed on next file open if its not the file from same project", () => { @@ -337,7 +374,10 @@ describe("unittests:: tsserver:: ConfiguredProjects", () => { }`, }; const host = createServerHost([file1, configFile, libFile]); - const projectService = createProjectService(host, { useSingleInferredProject: true, logger: createLoggerWithInMemoryLogs(host) }); + const projectService = createProjectService(host, { + useSingleInferredProject: true, + logger: createLoggerWithInMemoryLogs(host), + }); projectService.openClientFile(file1.path); logConfiguredProjectsHasOpenRefStatus(projectService); // file1 @@ -346,7 +386,11 @@ describe("unittests:: tsserver:: ConfiguredProjects", () => { projectService.openClientFile(libFile.path); logConfiguredProjectsHasOpenRefStatus(projectService); // No files + project closed - baselineTsserverLogs("configuredProjects", "should not close configured project after closing last open file, but should be closed on next file open if its not the file from same project", projectService); + baselineTsserverLogs( + "configuredProjects", + "should not close configured project after closing last open file, but should be closed on next file open if its not the file from same project", + projectService, + ); }); it("open file become a part of configured project if it is referenced from root file", () => { @@ -377,7 +421,11 @@ describe("unittests:: tsserver:: ConfiguredProjects", () => { host.writeFile(configFile.path, configFile.content); host.runQueuedTimeoutCallbacks(); // load configured project from disk + ensureProjectsForOpenFiles logInferredProjectsOrphanStatus(projectService); - baselineTsserverLogs("configuredProjects", "open file become a part of configured project if it is referenced from root file", projectService); + baselineTsserverLogs( + "configuredProjects", + "open file become a part of configured project if it is referenced from root file", + projectService, + ); }); it("can correctly update configured project when set of root files has changed (new file on disk)", () => { @@ -403,7 +451,11 @@ describe("unittests:: tsserver:: ConfiguredProjects", () => { host.runQueuedTimeoutCallbacks(); - baselineTsserverLogs("configuredProjects", "can correctly update configured project when set of root files has changed (new file on disk)", projectService); + baselineTsserverLogs( + "configuredProjects", + "can correctly update configured project when set of root files has changed (new file on disk)", + projectService, + ); }); it("can correctly update configured project when set of root files has changed (new file in list of files)", () => { @@ -428,7 +480,11 @@ describe("unittests:: tsserver:: ConfiguredProjects", () => { host.writeFile(configFile.path, JSON.stringify({ compilerOptions: {}, files: ["f1.ts", "f2.ts"] })); host.runQueuedTimeoutCallbacks(); - baselineTsserverLogs("configuredProjects", "can correctly update configured project when set of root files has changed (new file in list of files)", projectService); + baselineTsserverLogs( + "configuredProjects", + "can correctly update configured project when set of root files has changed (new file in list of files)", + projectService, + ); }); it("can update configured project when set of root files was not changed", () => { @@ -450,10 +506,17 @@ describe("unittests:: tsserver:: ConfiguredProjects", () => { projectService.openClientFile(file1.path); - host.writeFile(configFile.path, JSON.stringify({ compilerOptions: { outFile: "out.js" }, files: ["f1.ts", "f2.ts"] })); + host.writeFile( + configFile.path, + JSON.stringify({ compilerOptions: { outFile: "out.js" }, files: ["f1.ts", "f2.ts"] }), + ); host.runQueuedTimeoutCallbacks(); - baselineTsserverLogs("configuredProjects", "can update configured project when set of root files was not changed", projectService); + baselineTsserverLogs( + "configuredProjects", + "can update configured project when set of root files was not changed", + projectService, + ); }); it("Open ref of configured project when open file gets added to the project as part of configured file update", () => { @@ -516,7 +579,11 @@ describe("unittests:: tsserver:: ConfiguredProjects", () => { projectService.testhost.baselineHost("File5 written"); projectService.openClientFile(file5.path); - baselineTsserverLogs("configuredProjects", "Open ref of configured project when open file gets added to the project as part of configured file update", projectService); + baselineTsserverLogs( + "configuredProjects", + "Open ref of configured project when open file gets added to the project as part of configured file update", + projectService, + ); }); it("Open ref of configured project when open file gets added to the project as part of configured file update buts its open file references are all closed when the update happens", () => { @@ -567,7 +634,11 @@ describe("unittests:: tsserver:: ConfiguredProjects", () => { host.runQueuedTimeoutCallbacks(); logConfiguredProjectsHasOpenRefStatus(projectService); // file2 logInferredProjectsOrphanStatus(projectService); - baselineTsserverLogs("configuredProjects", "Open ref of configured project when open file gets added to the project as part of configured file update buts its open file references are all closed when the update happens", projectService); + baselineTsserverLogs( + "configuredProjects", + "Open ref of configured project when open file gets added to the project as part of configured file update buts its open file references are all closed when the update happens", + projectService, + ); }); it("files are properly detached when language service is disabled", () => { @@ -589,7 +660,8 @@ describe("unittests:: tsserver:: ConfiguredProjects", () => { }; const host = createServerHost([f1, f2, f3, config]); const originalGetFileSize = host.getFileSize; - host.getFileSize = (filePath: string) => filePath === f2.path ? ts.server.maxProgramSizeForNonTsFiles + 1 : originalGetFileSize.call(host, filePath); + host.getFileSize = (filePath: string) => + filePath === f2.path ? ts.server.maxProgramSizeForNonTsFiles + 1 : originalGetFileSize.call(host, filePath); const projectService = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) }); projectService.openClientFile(f1.path); @@ -601,7 +673,11 @@ describe("unittests:: tsserver:: ConfiguredProjects", () => { for (const f of [f1, f2, f3]) { // All the script infos should be present and contain the project since it is still alive. const scriptInfo = projectService.getScriptInfoForNormalizedPath(ts.server.toNormalizedPath(f.path))!; - projectService.logger.log(`Containing projects for ${f.path}:: ${scriptInfo.containingProjects.map(p => p.projectName).join(",")}`); + projectService.logger.log( + `Containing projects for ${f.path}:: ${ + scriptInfo.containingProjects.map(p => p.projectName).join(",") + }`, + ); } const f4 = { @@ -616,7 +692,11 @@ describe("unittests:: tsserver:: ConfiguredProjects", () => { // All the script infos should not be present since the project is closed and orphan script infos are collected assert.isUndefined(projectService.getScriptInfoForNormalizedPath(ts.server.toNormalizedPath(f.path))); } - baselineTsserverLogs("configuredProjects", "files are properly detached when language service is disabled", projectService); + baselineTsserverLogs( + "configuredProjects", + "files are properly detached when language service is disabled", + projectService, + ); }); it("syntactic features work even if language service is disabled", () => { @@ -634,10 +714,15 @@ describe("unittests:: tsserver:: ConfiguredProjects", () => { }; const host = createServerHost([f1, f2, config]); const originalGetFileSize = host.getFileSize; - host.getFileSize = (filePath: string) => filePath === f2.path ? ts.server.maxProgramSizeForNonTsFiles + 1 : originalGetFileSize.call(host, filePath); + host.getFileSize = (filePath: string) => + filePath === f2.path ? ts.server.maxProgramSizeForNonTsFiles + 1 : originalGetFileSize.call(host, filePath); const session = createSession(host, { canUseEvents: true, logger: createLoggerWithInMemoryLogs(host) }); openFilesForSession([f1], session); - session.logger.log(`Language languageServiceEnabled:: ${session.getProjectService().configuredProjects.get(config.path)!.languageServiceEnabled}`); + session.logger.log( + `Language languageServiceEnabled:: ${ + session.getProjectService().configuredProjects.get(config.path)!.languageServiceEnabled + }`, + ); session.executeCommandSeq({ command: ts.server.protocol.CommandTypes.FormatFull, @@ -645,7 +730,11 @@ describe("unittests:: tsserver:: ConfiguredProjects", () => { file: f1.path, }, }); - baselineTsserverLogs("configuredProjects", "syntactic features work even if language service is disabled", session); + baselineTsserverLogs( + "configuredProjects", + "syntactic features work even if language service is disabled", + session, + ); }); it("when multiple projects are open, detects correct default project", () => { @@ -700,7 +789,11 @@ declare var console: { const session = createSession(host, { canUseEvents: true, logger: createLoggerWithInMemoryLogs(host) }); openFilesForSession([fooIndex, barIndex], session); verifyGetErrRequest({ session, files: [barIndex, fooIndex] }); - baselineTsserverLogs("configuredProjects", "when multiple projects are open detects correct default project", session); + baselineTsserverLogs( + "configuredProjects", + "when multiple projects are open detects correct default project", + session, + ); }); it("when file name starts with ^", () => { @@ -741,21 +834,24 @@ declare var console: { path: `/user/username/projects/myproject/src/sub/fooBar.ts`, content: "export function fooBar() { }", }; - function verifySessionWorker({ withExclude, openFileBeforeCreating }: VerifySession, errorOnNewFileBeforeOldFile: boolean) { + function verifySessionWorker( + { withExclude, openFileBeforeCreating }: VerifySession, + errorOnNewFileBeforeOldFile: boolean, + ) { const host = createServerHost([ foo, bar, libFile, { path: `/user/username/projects/myproject/src/sub` }, - withExclude ? - { + withExclude + ? { path: config.path, content: JSON.stringify({ include: ["./src"], exclude: ["./src/sub"], }), - } : - config, + } + : config, ]); const session = createSession(host, { canUseEvents: true, @@ -785,12 +881,20 @@ declare var console: { } verifyGetErrRequest({ session, - files: errorOnNewFileBeforeOldFile ? - [fooBar, foo] : - [foo, fooBar], + files: errorOnNewFileBeforeOldFile + ? [fooBar, foo] + : [foo, fooBar], existingTimeouts: !withExclude, }); - baselineTsserverLogs("configuredProjects", `creating new file and then open it ${openFileBeforeCreating ? "before" : "after"} watcher is invoked, ask errors on it ${errorOnNewFileBeforeOldFile ? "before" : "after"} old one${withExclude ? " without file being in config" : ""}`, session); + baselineTsserverLogs( + "configuredProjects", + `creating new file and then open it ${ + openFileBeforeCreating ? "before" : "after" + } watcher is invoked, ask errors on it ${errorOnNewFileBeforeOldFile ? "before" : "after"} old one${ + withExclude ? " without file being in config" : "" + }`, + session, + ); } interface VerifySession { withExclude?: boolean; @@ -878,8 +982,16 @@ foo();`, endOffset: 1, }, }); - session.logger.log(`Default project for file: ${fooDts}: ${service.tryGetDefaultProjectForFile(ts.server.toNormalizedPath(fooDts))?.projectName}`); - baselineTsserverLogs("configuredProjects", "when default configured project does not contain the file", session); + session.logger.log( + `Default project for file: ${fooDts}: ${service.tryGetDefaultProjectForFile( + ts.server.toNormalizedPath(fooDts), + )?.projectName}`, + ); + baselineTsserverLogs( + "configuredProjects", + "when default configured project does not contain the file", + session, + ); }); describe("watches extended config files", () => { @@ -917,13 +1029,22 @@ foo();`, content: `let b = 1;`, }; - const host = createServerHost([alphaExtendedConfig, aConfig, aFile, bravoExtendedConfig, bConfig, bFile, ...(additionalFiles || ts.emptyArray)]); + const host = createServerHost([ + alphaExtendedConfig, + aConfig, + aFile, + bravoExtendedConfig, + bConfig, + bFile, + ...(additionalFiles || ts.emptyArray), + ]); const projectService = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) }); return { host, projectService, aFile, bFile, aConfig, bConfig, alphaExtendedConfig, bravoExtendedConfig }; } it("should watch the extended configs of multiple projects", () => { - const { host, projectService, aFile, bFile, bConfig, alphaExtendedConfig, bravoExtendedConfig } = getService(); + const { host, projectService, aFile, bFile, bConfig, alphaExtendedConfig, bravoExtendedConfig } = + getService(); projectService.openClientFile(aFile.path); projectService.openClientFile(bFile.path); @@ -959,7 +1080,11 @@ foo();`, host.writeFile(alphaExtendedConfig.path, "{}"); host.runQueuedTimeoutCallbacks(); - baselineTsserverLogs("configuredProjects", "should watch the extended configs of multiple projects", projectService); + baselineTsserverLogs( + "configuredProjects", + "should watch the extended configs of multiple projects", + projectService, + ); }); it("should stop watching the extended configs of closed projects", () => { @@ -984,7 +1109,11 @@ foo();`, projectService.closeClientFile(aFile.path); projectService.closeClientFile(dummy.path); projectService.openClientFile(dummy.path); - baselineTsserverLogs("configuredProjects", "should stop watching the extended configs of closed projects", projectService); + baselineTsserverLogs( + "configuredProjects", + "should stop watching the extended configs of closed projects", + projectService, + ); }); }); }); @@ -1037,7 +1166,11 @@ describe("unittests:: tsserver:: ConfiguredProjects:: non-existing directories l projectService.openClientFile(f.path); // Since f refers to config file as the default project, it needs to be kept alive - baselineTsserverLogs("configuredProjects", "should be able to handle @types if input file list is empty", projectService); + baselineTsserverLogs( + "configuredProjects", + "should be able to handle @types if input file list is empty", + projectService, + ); }); it("should tolerate invalid include files that start in subDirectory", () => { @@ -1062,7 +1195,11 @@ describe("unittests:: tsserver:: ConfiguredProjects:: non-existing directories l projectService.openClientFile(f.path); // Since f refers to config file as the default project, it needs to be kept alive - baselineTsserverLogs("configuredProjects", "should tolerate invalid include files that start in subDirectory", projectService); + baselineTsserverLogs( + "configuredProjects", + "should tolerate invalid include files that start in subDirectory", + projectService, + ); }); it("Changed module resolution reflected when specifying files list", () => { @@ -1093,7 +1230,11 @@ describe("unittests:: tsserver:: ConfiguredProjects:: non-existing directories l // On next file open the files file2a should be closed and not watched any more projectService.openClientFile(file2.path); - baselineTsserverLogs("configuredProjects", "changed module resolution reflected when specifying files list", projectService); + baselineTsserverLogs( + "configuredProjects", + "changed module resolution reflected when specifying files list", + projectService, + ); }); it("Failed lookup locations uses parent most node_modules directory", () => { @@ -1125,7 +1266,11 @@ describe("unittests:: tsserver:: ConfiguredProjects:: non-existing directories l const host = createServerHost(files); const projectService = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) }); projectService.openClientFile(file1.path); - baselineTsserverLogs("configuredProjects", "failed lookup locations uses parent most node_modules directory", projectService); + baselineTsserverLogs( + "configuredProjects", + "failed lookup locations uses parent most node_modules directory", + projectService, + ); }); }); @@ -1144,12 +1289,16 @@ describe("unittests:: tsserver:: ConfiguredProjects:: when reading tsconfig file const session = createSession(host, { canUseEvents: true, logger: createLoggerWithInMemoryLogs(host) }); const originalReadFile = host.readFile; host.readFile = f => { - return f === configFile.path ? - undefined : - originalReadFile.call(host, f); + return f === configFile.path + ? undefined + : originalReadFile.call(host, f); }; openFilesForSession([file1], session); - baselineTsserverLogs("configuredProjects", "should be tolerated without crashing the server when reading tsconfig file fails", session); + baselineTsserverLogs( + "configuredProjects", + "should be tolerated without crashing the server when reading tsconfig file fails", + session, + ); }); }); diff --git a/src/testRunner/unittests/tsserver/declarationFileMaps.ts b/src/testRunner/unittests/tsserver/declarationFileMaps.ts index 2f63d0c8b21ee..a301bbefeff37 100644 --- a/src/testRunner/unittests/tsserver/declarationFileMaps.ts +++ b/src/testRunner/unittests/tsserver/declarationFileMaps.ts @@ -15,9 +15,18 @@ import { function checkDeclarationFiles(file: File, session: TestSession): void { openFilesForSession([file], session); - const project = ts.Debug.checkDefined(session.getProjectService().getDefaultProjectForFile(file.path as ts.server.NormalizedPath, /*ensureProject*/ false)); + const project = ts.Debug.checkDefined( + session.getProjectService().getDefaultProjectForFile( + file.path as ts.server.NormalizedPath, + /*ensureProject*/ false, + ), + ); const program = project.getCurrentProgram()!; - const output = ts.getFileEmitOutput(program, ts.Debug.checkDefined(program.getSourceFile(file.path)), /*emitOnlyDtsFiles*/ true); + const output = ts.getFileEmitOutput( + program, + ts.Debug.checkDefined(program.getSourceFile(file.path)), + /*emitOnlyDtsFiles*/ true, + ); session.logger.log(`ts.getFileEmitOutput: ${file.path}: ${JSON.stringify(output, undefined, " ")}`); closeFilesForSession([file], session); } @@ -51,7 +60,8 @@ describe("unittests:: tsserver:: with declaration file maps:: project references const aDts: File = { path: "/a/bin/a.d.ts", // ${""} is needed to mangle the sourceMappingURL part or it breaks the build - content: `export declare function fnA(): void;\nexport interface IfaceA {\n}\nexport declare const instanceA: IfaceA;\n//# source${""}MappingURL=a.d.ts.map`, + content: + `export declare function fnA(): void;\nexport interface IfaceA {\n}\nexport declare const instanceA: IfaceA;\n//# source${""}MappingURL=a.d.ts.map`, }; const bTs: File = { @@ -85,12 +95,14 @@ describe("unittests:: tsserver:: with declaration file maps:: project references const userTs: File = { path: "/user/user.ts", - content: 'import * as a from "../a/bin/a";\nimport * as b from "../b/bin/b";\nexport function fnUser() { a.fnA(); b.fnB(); a.instanceA; }', + content: + 'import * as a from "../a/bin/a";\nimport * as b from "../b/bin/b";\nexport function fnUser() { a.fnA(); b.fnB(); a.instanceA; }', }; const userTsForConfigProject: File = { path: "/user/user.ts", - content: 'import * as a from "../a/a";\nimport * as b from "../b/b";\nexport function fnUser() { a.fnA(); b.fnB(); a.instanceA; }', + content: + 'import * as a from "../a/a";\nimport * as b from "../b/b";\nexport function fnUser() { a.fnA(); b.fnB(); a.instanceA; }', }; const userTsconfig: File = { @@ -102,7 +114,18 @@ describe("unittests:: tsserver:: with declaration file maps:: project references }; function makeSampleProjects(addUserTsConfig?: boolean, keepAllFiles?: boolean) { - const host = createServerHost([aTs, aTsconfig, aDtsMap, aDts, bTsconfig, bTs, bDtsMap, bDts, ...(addUserTsConfig ? [userTsForConfigProject, userTsconfig] : [userTs]), dummyFile]); + const host = createServerHost([ + aTs, + aTsconfig, + aDtsMap, + aDts, + bTsconfig, + bTs, + bDtsMap, + bDts, + ...(addUserTsConfig ? [userTsForConfigProject, userTsconfig] : [userTs]), + dummyFile, + ]); const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) }); checkDeclarationFiles(aTs, session); @@ -269,14 +292,29 @@ describe("unittests:: tsserver:: with declaration file maps:: project references const aTs: File = { path: "/a/a.ts", content: `function f() {}` }; const aTsconfig: File = { path: "/a/tsconfig.json", - content: JSON.stringify({ compilerOptions: { declaration: true, declarationMap: true, outFile: "../bin/a.js" } }), + content: JSON.stringify({ + compilerOptions: { declaration: true, declarationMap: true, outFile: "../bin/a.js" }, + }), }; const bTs: File = { path: "/b/b.ts", content: `f();` }; - const bTsconfig: File = { path: "/b/tsconfig.json", content: JSON.stringify({ references: [{ path: "../a" }] }) }; - const aDts: File = { path: "/bin/a.d.ts", content: `declare function f(): void;\n//# sourceMappingURL=a.d.ts.map` }; + const bTsconfig: File = { + path: "/b/tsconfig.json", + content: JSON.stringify({ references: [{ path: "../a" }] }), + }; + const aDts: File = { + path: "/bin/a.d.ts", + content: `declare function f(): void;\n//# sourceMappingURL=a.d.ts.map`, + }; const aDtsMap: File = { path: "/bin/a.d.ts.map", - content: JSON.stringify({ version: 3, file: "a.d.ts", sourceRoot: "", sources: ["../a/a.ts"], names: [], mappings: "AAAA,iBAAS,CAAC,SAAK" }), + content: JSON.stringify({ + version: 3, + file: "a.d.ts", + sourceRoot: "", + sources: ["../a/a.ts"], + names: [], + mappings: "AAAA,iBAAS,CAAC,SAAK", + }), }; const host = createServerHost([aTs, aTsconfig, bTs, bTsconfig, aDts, aDtsMap]); @@ -391,7 +429,11 @@ describe("unittests:: tsserver:: with declaration file maps:: project references newFilePath: "/a/src/a1.ts", }, }); - baselineTsserverLogs("declarationFileMaps", "getEditsForFileRename when referencing project doesnt include file and its renamed", session); + baselineTsserverLogs( + "declarationFileMaps", + "getEditsForFileRename when referencing project doesnt include file and its renamed", + session, + ); }); it("does not jump to source if inlined sources", () => { diff --git a/src/testRunner/unittests/tsserver/documentRegistry.ts b/src/testRunner/unittests/tsserver/documentRegistry.ts index ffde566529c04..0b71a8b01fa1f 100644 --- a/src/testRunner/unittests/tsserver/documentRegistry.ts +++ b/src/testRunner/unittests/tsserver/documentRegistry.ts @@ -57,13 +57,19 @@ describe("unittests:: tsserver:: documentRegistry:: document registry in project function changeFileToNotImportModule(service: TestProjectService) { const info = service.getScriptInfo(file.path)!; - service.applyChangesToFile(info, ts.singleIterator({ span: { start: 0, length: importModuleContent.length }, newText: "" })); + service.applyChangesToFile( + info, + ts.singleIterator({ span: { start: 0, length: importModuleContent.length }, newText: "" }), + ); checkProject(service, /*moduleIsOrphan*/ true); } function changeFileToImportModule(service: TestProjectService) { const info = service.getScriptInfo(file.path)!; - service.applyChangesToFile(info, ts.singleIterator({ span: { start: 0, length: 0 }, newText: importModuleContent })); + service.applyChangesToFile( + info, + ts.singleIterator({ span: { start: 0, length: 0 }, newText: importModuleContent }), + ); checkProject(service, /*moduleIsOrphan*/ false); } @@ -106,14 +112,21 @@ describe("unittests:: tsserver:: documentRegistry:: document registry in project assert.notEqual(moduleInfo.cacheSourceFile!.sourceFile, sourceFile); assert.equal(project.getSourceFile(moduleInfo.path), moduleInfo.cacheSourceFile!.sourceFile); assert.equal(moduleInfo.cacheSourceFile!.sourceFile.text, updatedModuleContent); - baselineTsserverLogs("documentRegistry", "Caches the source file if script info is orphan, and orphan script info changes", service); + baselineTsserverLogs( + "documentRegistry", + "Caches the source file if script info is orphan, and orphan script info changes", + service, + ); }); }); describe("unittests:: tsserver:: documentRegistry:: works when reusing orphan script info with different scriptKind", () => { it("works when reusing orphan script info with different scriptKind", () => { const host = createServerHost({}); - const session = createSession(host, { useInferredProjectPerProjectRoot: true, logger: createLoggerWithInMemoryLogs(host) }); + const session = createSession(host, { + useInferredProjectPerProjectRoot: true, + logger: createLoggerWithInMemoryLogs(host), + }); const newText = "exrpot const x = 10;"; const content = `import x from 'react';\n${newText}`; openFilesForSession([ @@ -142,6 +155,10 @@ describe("unittests:: tsserver:: documentRegistry:: works when reusing orphan sc ], }, }); - baselineTsserverLogs("documentRegistry", "works when reusing orphan script info with different scriptKind", session); + baselineTsserverLogs( + "documentRegistry", + "works when reusing orphan script info with different scriptKind", + session, + ); }); }); diff --git a/src/testRunner/unittests/tsserver/dynamicFiles.ts b/src/testRunner/unittests/tsserver/dynamicFiles.ts index 644deb0e908f1..42bc1c298f3ea 100644 --- a/src/testRunner/unittests/tsserver/dynamicFiles.ts +++ b/src/testRunner/unittests/tsserver/dynamicFiles.ts @@ -38,7 +38,10 @@ describe("unittests:: tsserver:: dynamicFiles:: Untitled files", () => { const aTs: File = { path: "/proj/a.ts", content: "" }; const tsconfig: File = { path: "/proj/tsconfig.json", content: "{}" }; const host = createServerHost([aTs, tsconfig]); - const session = createSession(host, { useInferredProjectPerProjectRoot: true, logger: createLoggerWithInMemoryLogs(host) }); + const session = createSession(host, { + useInferredProjectPerProjectRoot: true, + logger: createLoggerWithInMemoryLogs(host), + }); openFilesForSession([aTs], session); @@ -46,7 +49,8 @@ describe("unittests:: tsserver:: dynamicFiles:: Untitled files", () => { command: ts.server.protocol.CommandTypes.Open, arguments: { file: untitledFile, - fileContent: `/// \nlet foo = 1;\nfooo/**/`, + fileContent: + `/// \nlet foo = 1;\nfooo/**/`, scriptKindName: "TS", projectRootPath: "/proj", }, @@ -71,9 +75,17 @@ describe("unittests:: tsserver:: dynamicFiles:: Untitled files", () => { path: `/user/username/projects/myproject/tsconfig.json`, content: "{}", }; - const host = createServerHost([config, libFile], { useCaseSensitiveFileNames: true, currentDirectory: "/user/username/projects/myproject" }); + const host = createServerHost([config, libFile], { + useCaseSensitiveFileNames: true, + currentDirectory: "/user/username/projects/myproject", + }); const service = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) }); - service.openClientFile(untitledFile, "const x = 10;", /*scriptKind*/ undefined, "/user/username/projects/myproject"); + service.openClientFile( + untitledFile, + "const x = 10;", + /*scriptKind*/ undefined, + "/user/username/projects/myproject", + ); verifyDynamic(service, `/user/username/projects/myproject/${untitledFile}`); const untitled: File = { @@ -82,11 +94,21 @@ describe("unittests:: tsserver:: dynamicFiles:: Untitled files", () => { }; host.writeFile(untitled.path, untitled.content); service.testhost.logTimeoutQueueLength(); - service.openClientFile(untitled.path, untitled.content, /*scriptKind*/ undefined, "/user/username/projects/myproject"); + service.openClientFile( + untitled.path, + untitled.content, + /*scriptKind*/ undefined, + "/user/username/projects/myproject", + ); service.closeClientFile(untitledFile); - service.openClientFile(untitledFile, "const x = 10;", /*scriptKind*/ undefined, "/user/username/projects/myproject"); + service.openClientFile( + untitledFile, + "const x = 10;", + /*scriptKind*/ undefined, + "/user/username/projects/myproject", + ); verifyDynamic(service, `/user/username/projects/myproject/${untitledFile}`); baselineTsserverLogs("dynamicFiles", "opening untitled files", service); }); @@ -101,8 +123,16 @@ describe("unittests:: tsserver:: dynamicFiles:: Untitled files", () => { content: "const y = 10", }; const host = createServerHost([config, file, libFile], { useCaseSensitiveFileNames: true }); - const service = createProjectService(host, { useInferredProjectPerProjectRoot: true, logger: createLoggerWithInMemoryLogs(host) }); - service.openClientFile(untitledFile, "const x = 10;", /*scriptKind*/ undefined, "/user/username/projects/myproject"); + const service = createProjectService(host, { + useInferredProjectPerProjectRoot: true, + logger: createLoggerWithInMemoryLogs(host), + }); + service.openClientFile( + untitledFile, + "const x = 10;", + /*scriptKind*/ undefined, + "/user/username/projects/myproject", + ); verifyDynamic(service, `/user/username/projects/myproject/${untitledFile}`); // Close untitled file @@ -110,12 +140,19 @@ describe("unittests:: tsserver:: dynamicFiles:: Untitled files", () => { // Open file from configured project which should collect inferredProject service.openClientFile(file.path); - baselineTsserverLogs("dynamicFiles", "opening and closing untitled files when projectRootPath is different from currentDirectory", service); + baselineTsserverLogs( + "dynamicFiles", + "opening and closing untitled files when projectRootPath is different from currentDirectory", + service, + ); }); it("when changing scriptKind of the untitled files", () => { const host = createServerHost([libFile], { useCaseSensitiveFileNames: true }); - const service = createProjectService(host, { useInferredProjectPerProjectRoot: true, logger: createLoggerWithInMemoryLogs(host) }); + const service = createProjectService(host, { + useInferredProjectPerProjectRoot: true, + logger: createLoggerWithInMemoryLogs(host), + }); service.openClientFile(untitledFile, "const x = 10;", ts.ScriptKind.TS, "/user/username/projects/myproject"); const program = service.inferredProjects[0].getCurrentProgram()!; const sourceFile = program.getSourceFile(untitledFile)!; @@ -158,7 +195,10 @@ describe("unittests:: tsserver:: dynamicFiles:: ", () => { baselineTsserverLogs("dynamicFiles", "dynamic file without external project", session); }); - verifyPathRecognizedAsDynamic("dynamic file with reference paths without external project", "^walkThroughSnippet:/Users/UserName/projects/someProject/out/someFile#1.js"); + verifyPathRecognizedAsDynamic( + "dynamic file with reference paths without external project", + "^walkThroughSnippet:/Users/UserName/projects/someProject/out/someFile#1.js", + ); describe("dynamic file with projectRootPath", () => { const file: File = { @@ -174,8 +214,13 @@ describe("unittests:: tsserver:: dynamicFiles:: ", () => { content: "let y = 10;", }; it("with useInferredProjectPerProjectRoot", () => { - const host = createServerHost([libFile, configFile, configProjectFile], { useCaseSensitiveFileNames: true }); - const session = createSession(host, { useInferredProjectPerProjectRoot: true, logger: createLoggerWithInMemoryLogs(host) }); + const host = createServerHost([libFile, configFile, configProjectFile], { + useCaseSensitiveFileNames: true, + }); + const session = createSession(host, { + useInferredProjectPerProjectRoot: true, + logger: createLoggerWithInMemoryLogs(host), + }); openFilesForSession([{ file: file.path, projectRootPath: "/user/username/projects/myproject" }], session); const projectService = session.getProjectService(); @@ -191,14 +236,25 @@ describe("unittests:: tsserver:: dynamicFiles:: ", () => { // Without project root const file2Path = file.path.replace("#1", "#2"); openFilesForSession([{ file: file2Path, content: file.content }], session); - baselineTsserverLogs("dynamicFiles", "dynamic file with projectRootPath with useInferredProjectPerProjectRoot", session); + baselineTsserverLogs( + "dynamicFiles", + "dynamic file with projectRootPath with useInferredProjectPerProjectRoot", + session, + ); }); it("fails when useInferredProjectPerProjectRoot is false", () => { - const host = createServerHost([libFile, configFile, configProjectFile], { useCaseSensitiveFileNames: true }); + const host = createServerHost([libFile, configFile, configProjectFile], { + useCaseSensitiveFileNames: true, + }); const projectService = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) }); try { - projectService.openClientFile(file.path, file.content, /*scriptKind*/ undefined, "/user/username/projects/myproject"); + projectService.openClientFile( + file.path, + file.content, + /*scriptKind*/ undefined, + "/user/username/projects/myproject", + ); } catch (e) { assert.strictEqual( @@ -208,12 +264,19 @@ describe("unittests:: tsserver:: dynamicFiles:: ", () => { } const file2Path = file.path.replace("#1", "#2"); projectService.openClientFile(file2Path, file.content); - baselineTsserverLogs("dynamicFiles", "dynamic file with projectRootPath fails when useInferredProjectPerProjectRoot is false", projectService); + baselineTsserverLogs( + "dynamicFiles", + "dynamic file with projectRootPath fails when useInferredProjectPerProjectRoot is false", + projectService, + ); }); }); describe("verify accepts known schemas as dynamic file", () => { - verifyPathRecognizedAsDynamic("walkThroughSnippet", "walkThroughSnippet:/usr/share/code/resources/app/out/vs/workbench/contrib/welcome/walkThrough/browser/editor/^vs_code_editor_walkthrough.md#1.ts"); + verifyPathRecognizedAsDynamic( + "walkThroughSnippet", + "walkThroughSnippet:/usr/share/code/resources/app/out/vs/workbench/contrib/welcome/walkThrough/browser/editor/^vs_code_editor_walkthrough.md#1.ts", + ); verifyPathRecognizedAsDynamic("untitled", "untitled:/Users/matb/projects/san/^newFile.ts"); }); }); diff --git a/src/testRunner/unittests/tsserver/events/largeFileReferenced.ts b/src/testRunner/unittests/tsserver/events/largeFileReferenced.ts index 7406af24c15ad..dfddd0ef63516 100644 --- a/src/testRunner/unittests/tsserver/events/largeFileReferenced.ts +++ b/src/testRunner/unittests/tsserver/events/largeFileReferenced.ts @@ -40,12 +40,19 @@ describe("unittests:: tsserver:: events:: LargeFileReferencedEvent with large fi }; const tsconfig: File = { path: `/user/username/projects/myproject/tsconfig.json`, - content: JSON.stringify({ files: ["src/file.ts", getLargeFile(useLargeTsFile)], compilerOptions: { target: 1, allowJs: true } }), + content: JSON.stringify({ + files: ["src/file.ts", getLargeFile(useLargeTsFile)], + compilerOptions: { target: 1, allowJs: true }, + }), }; const files = [file, libFile, tsconfig]; const session = createSessionWithEventHandler(files, useLargeTsFile); openFilesForSession([file], session); - baselineTsserverLogs("events/largeFileReferenced", `when large ${getFileType(useLargeTsFile)} file is included by tsconfig`, session); + baselineTsserverLogs( + "events/largeFileReferenced", + `when large ${getFileType(useLargeTsFile)} file is included by tsconfig`, + session, + ); }); it("when large file is included by module resolution", () => { @@ -56,7 +63,11 @@ describe("unittests:: tsserver:: events:: LargeFileReferencedEvent with large fi const files = [file, libFile]; const session = createSessionWithEventHandler(files, useLargeTsFile); openFilesForSession([file], session); - baselineTsserverLogs("events/largeFileReferenced", `when large ${getFileType(useLargeTsFile)} file is included by module resolution`, session); + baselineTsserverLogs( + "events/largeFileReferenced", + `when large ${getFileType(useLargeTsFile)} file is included by module resolution`, + session, + ); }); } diff --git a/src/testRunner/unittests/tsserver/events/projectLanguageServiceState.ts b/src/testRunner/unittests/tsserver/events/projectLanguageServiceState.ts index 4f854dca732d9..704b2bbf75295 100644 --- a/src/testRunner/unittests/tsserver/events/projectLanguageServiceState.ts +++ b/src/testRunner/unittests/tsserver/events/projectLanguageServiceState.ts @@ -32,16 +32,29 @@ describe("unittests:: tsserver:: events:: ProjectLanguageServiceStateEvent", () }; const host = createServerHost([f1, f2, config]); const originalGetFileSize = host.getFileSize; - host.getFileSize = (filePath: string) => filePath === f2.path ? ts.server.maxProgramSizeForNonTsFiles + 1 : originalGetFileSize.call(host, filePath); + host.getFileSize = (filePath: string) => + filePath === f2.path ? ts.server.maxProgramSizeForNonTsFiles + 1 : originalGetFileSize.call(host, filePath); const session = createSession(host, { canUseEvents: true, logger: createLoggerWithInMemoryLogs(host) }); openFilesForSession([f1], session); - session.logger.log(`Language service enabled: ${session.getProjectService().configuredProjects.get(config.path)!.languageServiceEnabled}`); + session.logger.log( + `Language service enabled: ${ + session.getProjectService().configuredProjects.get(config.path)!.languageServiceEnabled + }`, + ); host.writeFile(configWithExclude.path, configWithExclude.content); host.runQueuedTimeoutCallbacks(); - session.logger.log(`Language service enabled: ${session.getProjectService().configuredProjects.get(config.path)!.languageServiceEnabled}`); - baselineTsserverLogs("events/projectLanguageServiceState", "language service disabled events are triggered", session); + session.logger.log( + `Language service enabled: ${ + session.getProjectService().configuredProjects.get(config.path)!.languageServiceEnabled + }`, + ); + baselineTsserverLogs( + "events/projectLanguageServiceState", + "language service disabled events are triggered", + session, + ); }); it("Large file size is determined correctly", () => { diff --git a/src/testRunner/unittests/tsserver/events/projectLoading.ts b/src/testRunner/unittests/tsserver/events/projectLoading.ts index 98295f81aaf4a..90c1e27f1c38e 100644 --- a/src/testRunner/unittests/tsserver/events/projectLoading.ts +++ b/src/testRunner/unittests/tsserver/events/projectLoading.ts @@ -30,7 +30,10 @@ describe("unittests:: tsserver:: events:: ProjectLoadingStart and ProjectLoading const configBPath = `/user/username/projects/b/tsconfig.json`; const files = [libFile, aTs, configA]; - function verifyProjectLoadingStartAndFinish(sessionType: string, createSession: (host: TestServerHost) => TestSession) { + function verifyProjectLoadingStartAndFinish( + sessionType: string, + createSession: (host: TestServerHost) => TestSession, + ) { describe(sessionType, () => { it("when project is created by open file", () => { const bTs: File = { @@ -45,7 +48,11 @@ describe("unittests:: tsserver:: events:: ProjectLoadingStart and ProjectLoading const session = createSession(host); openFilesForSession([aTs], session); openFilesForSession([bTs], session); - baselineTsserverLogs("events/projectLoading", `project is created by open file ${sessionType}`, session); + baselineTsserverLogs( + "events/projectLoading", + `project is created by open file ${sessionType}`, + session, + ); }); it("when change is detected in the config file", () => { @@ -55,7 +62,11 @@ describe("unittests:: tsserver:: events:: ProjectLoadingStart and ProjectLoading host.writeFile(configA.path, configA.content); host.runQueuedTimeoutCallbacks(); - baselineTsserverLogs("events/projectLoading", `change is detected in the config file ${sessionType}`, session); + baselineTsserverLogs( + "events/projectLoading", + `change is detected in the config file ${sessionType}`, + session, + ); }); it("when change is detected in an extended config file", () => { @@ -75,7 +86,11 @@ describe("unittests:: tsserver:: events:: ProjectLoadingStart and ProjectLoading host.writeFile(configA.path, configA.content); host.runQueuedTimeoutCallbacks(); - baselineTsserverLogs("events/projectLoading", `change is detected in an extended config file ${sessionType}`, session); + baselineTsserverLogs( + "events/projectLoading", + `change is detected in an extended config file ${sessionType}`, + session, + ); }); describe("when opening original location project", () => { @@ -97,7 +112,8 @@ describe("unittests:: tsserver:: events:: ProjectLoadingStart and ProjectLoading }; const aDTsMap: File = { path: `/user/username/projects/a/a.d.ts.map`, - content: `{"version":3,"file":"a.d.ts","sourceRoot":"","sources":["./a.ts"],"names":[],"mappings":"AAAA,qBAAa,CAAC;CAAI"}`, + content: + `{"version":3,"file":"a.d.ts","sourceRoot":"","sources":["./a.ts"],"names":[],"mappings":"AAAA,qBAAa,CAAC;CAAI"}`, }; const bTs: File = { path: bTsPath, @@ -126,7 +142,13 @@ describe("unittests:: tsserver:: events:: ProjectLoadingStart and ProjectLoading ...protocolLocationFromSubstring(bTs.content, "A()"), }, }); - baselineTsserverLogs("events/projectLoading", `opening original location project${disableSourceOfProjectReferenceRedirect ? " disableSourceOfProjectReferenceRedirect" : ""} ${sessionType}`, session); + baselineTsserverLogs( + "events/projectLoading", + `opening original location project${ + disableSourceOfProjectReferenceRedirect ? " disableSourceOfProjectReferenceRedirect" : "" + } ${sessionType}`, + session, + ); } }); @@ -152,13 +174,21 @@ describe("unittests:: tsserver:: events:: ProjectLoadingStart and ProjectLoading it("when lazyConfiguredProjectsFromExternalProject is false", () => { const session = createSessionAndOpenProject(/*lazyConfiguredProjectsFromExternalProject*/ false); - baselineTsserverLogs("events/projectLoading", `lazyConfiguredProjectsFromExternalProject is false ${sessionType}`, session); + baselineTsserverLogs( + "events/projectLoading", + `lazyConfiguredProjectsFromExternalProject is false ${sessionType}`, + session, + ); }); it("when lazyConfiguredProjectsFromExternalProject is true and file is opened", () => { const session = createSessionAndOpenProject(/*lazyConfiguredProjectsFromExternalProject*/ true); openFilesForSession([aTs], session); - baselineTsserverLogs("events/projectLoading", `lazyConfiguredProjectsFromExternalProject is true and file is opened ${sessionType}`, session); + baselineTsserverLogs( + "events/projectLoading", + `lazyConfiguredProjectsFromExternalProject is true and file is opened ${sessionType}`, + session, + ); }); it("when lazyConfiguredProjectsFromExternalProject is disabled", () => { @@ -169,7 +199,11 @@ describe("unittests:: tsserver:: events:: ProjectLoadingStart and ProjectLoading preferences: { lazyConfiguredProjectsFromExternalProject: false }, }, }); - baselineTsserverLogs("events/projectLoading", `lazyConfiguredProjectsFromExternalProject is disabled ${sessionType}`, session); + baselineTsserverLogs( + "events/projectLoading", + `lazyConfiguredProjectsFromExternalProject is disabled ${sessionType}`, + session, + ); }); }); }); diff --git a/src/testRunner/unittests/tsserver/events/projectUpdatedInBackground.ts b/src/testRunner/unittests/tsserver/events/projectUpdatedInBackground.ts index 8f113d43c0162..5d5b85762004e 100644 --- a/src/testRunner/unittests/tsserver/events/projectUpdatedInBackground.ts +++ b/src/testRunner/unittests/tsserver/events/projectUpdatedInBackground.ts @@ -15,7 +15,10 @@ import { } from "../../helpers/virtualFileSystemWithWatch"; describe("unittests:: tsserver:: events:: ProjectsUpdatedInBackground", () => { - function verifyProjectsUpdatedInBackgroundEvent(scenario: string, createSession: (host: TestServerHost) => TestSession) { + function verifyProjectsUpdatedInBackgroundEvent( + scenario: string, + createSession: (host: TestServerHost) => TestSession, + ) { it("when adding new file", () => { const commonFile1: File = { path: "/users/username/projects/project/file1.ts", @@ -74,7 +77,11 @@ describe("unittests:: tsserver:: events:: ProjectsUpdatedInBackground", () => { host.writeFile(f2.path, "export let x = 11"); host.runQueuedTimeoutCallbacks(); - baselineTsserverLogs("events/projectUpdatedInBackground", `${scenario} and ${subScenario}`, session); + baselineTsserverLogs( + "events/projectUpdatedInBackground", + `${scenario} and ${subScenario}`, + session, + ); }); } verifyEventWithOutSettings("when both options are not set"); @@ -94,7 +101,9 @@ describe("unittests:: tsserver:: events:: ProjectsUpdatedInBackground", () => { /** initial list of files to reload in fs and first file in this list being the file to open */ firstReloadFileList?: string[]; } - function getInitialState({ configObj = {}, getAdditionalFileOrFolder, firstReloadFileList }: InitialStateParams = {}) { + function getInitialState( + { configObj = {}, getAdditionalFileOrFolder, firstReloadFileList }: InitialStateParams = {}, + ) { const moduleFile1: File = { path: moduleFile1Path, content: "export function Foo() { };", @@ -126,9 +135,19 @@ describe("unittests:: tsserver:: events:: ProjectsUpdatedInBackground", () => { content: JSON.stringify(configObj || { compilerOptions: {} }), }; - const files: File[] = [file1Consumer1, moduleFile1, file1Consumer2, moduleFile2, ...additionalFiles, globalFile3, libFile, configFile]; + const files: File[] = [ + file1Consumer1, + moduleFile1, + file1Consumer2, + moduleFile2, + ...additionalFiles, + globalFile3, + libFile, + configFile, + ]; - const filesToReload = firstReloadFileList?.map(fileName => ts.find(files, file => file.path === fileName)!) || files; + const filesToReload = + firstReloadFileList?.map(fileName => ts.find(files, file => file.path === fileName)!) || files; const host = createServerHost([filesToReload[0], configFile]); // Initial project creation @@ -177,7 +196,11 @@ describe("unittests:: tsserver:: events:: ProjectsUpdatedInBackground", () => { // Change the content of moduleFile1 to `export var T: number;export function Foo() { console.log('hi'); };` host.writeFile(moduleFile1.path, `export var T: number;export function Foo() { console.log('hi'); };`); host.runQueuedTimeoutCallbacks(); - baselineTsserverLogs("events/projectUpdatedInBackground", `${scenario} and should contains only itself`, session); + baselineTsserverLogs( + "events/projectUpdatedInBackground", + `${scenario} and should contains only itself`, + session, + ); }); it("should be up-to-date with the reference map changes", () => { @@ -196,7 +219,10 @@ describe("unittests:: tsserver:: events:: ProjectsUpdatedInBackground", () => { host.runQueuedTimeoutCallbacks(); // Change the content of moduleFile1 to `export var T: number;export var T2: string;export function Foo() { };` - host.writeFile(moduleFile1.path, `export var T: number;export var T2: string;export function Foo() { };`); + host.writeFile( + moduleFile1.path, + `export var T: number;export var T2: string;export function Foo() { };`, + ); host.runQueuedTimeoutCallbacks(); // Multiple file edits in one go: @@ -206,7 +232,11 @@ describe("unittests:: tsserver:: events:: ProjectsUpdatedInBackground", () => { updateContentOfOpenFile(file1Consumer1, `export let y = Foo();`); host.writeFile(moduleFile1.path, `export var T: number;export function Foo() { };`); host.runQueuedTimeoutCallbacks(); - baselineTsserverLogs("events/projectUpdatedInBackground", `${scenario} and should be up-to-date with the reference map changes`, session); + baselineTsserverLogs( + "events/projectUpdatedInBackground", + `${scenario} and should be up-to-date with the reference map changes`, + session, + ); }); it("should be up-to-date with deleted files", () => { @@ -218,16 +248,27 @@ describe("unittests:: tsserver:: events:: ProjectsUpdatedInBackground", () => { // Delete file1Consumer2 host.deleteFile(file1Consumer2.path); host.runQueuedTimeoutCallbacks(); - baselineTsserverLogs("events/projectUpdatedInBackground", `${scenario} and should be up-to-date with deleted files`, session); + baselineTsserverLogs( + "events/projectUpdatedInBackground", + `${scenario} and should be up-to-date with deleted files`, + session, + ); }); it("should be up-to-date with newly created files", () => { const { host, moduleFile1, session } = getInitialState(); host.writeFile(moduleFile1.path, `export var T: number;export function Foo() { };`); - host.writeFile("/users/username/projects/project/file1Consumer3.ts", `import {Foo} from "./moduleFile1"; let y = Foo();`); + host.writeFile( + "/users/username/projects/project/file1Consumer3.ts", + `import {Foo} from "./moduleFile1"; let y = Foo();`, + ); host.runQueuedTimeoutCallbacks(); - baselineTsserverLogs("events/projectUpdatedInBackground", `${scenario} and should be up-to-date with newly created files`, session); + baselineTsserverLogs( + "events/projectUpdatedInBackground", + `${scenario} and should be up-to-date with newly created files`, + session, + ); }); it("should detect changes in non-root files", () => { @@ -241,7 +282,11 @@ describe("unittests:: tsserver:: events:: ProjectsUpdatedInBackground", () => { // change file1 internal, and verify only file1 is affected host.writeFile(moduleFile1.path, moduleFile1.content + "var T1: number;"); host.runQueuedTimeoutCallbacks(); - baselineTsserverLogs("events/projectUpdatedInBackground", `${scenario} and should detect changes in non-root files`, session); + baselineTsserverLogs( + "events/projectUpdatedInBackground", + `${scenario} and should detect changes in non-root files`, + session, + ); }); it("should return all files if a global file changed shape", () => { @@ -249,7 +294,11 @@ describe("unittests:: tsserver:: events:: ProjectsUpdatedInBackground", () => { host.writeFile(globalFile3.path, globalFile3.content + "var T2: string;"); host.runQueuedTimeoutCallbacks(); - baselineTsserverLogs("events/projectUpdatedInBackground", `${scenario} and should return all files if a global file changed shape`, session); + baselineTsserverLogs( + "events/projectUpdatedInBackground", + `${scenario} and should return all files if a global file changed shape`, + session, + ); }); it("should always return the file itself if '--isolatedModules' is specified", () => { @@ -259,7 +308,11 @@ describe("unittests:: tsserver:: events:: ProjectsUpdatedInBackground", () => { host.writeFile(moduleFile1.path, `export var T: number;export function Foo() { };`); host.runQueuedTimeoutCallbacks(); - baselineTsserverLogs("events/projectUpdatedInBackground", `${scenario} and should always return the file itself if --isolatedModules is specified`, session); + baselineTsserverLogs( + "events/projectUpdatedInBackground", + `${scenario} and should always return the file itself if --isolatedModules is specified`, + session, + ); }); it("should always return the file itself if '--out' or '--outFile' is specified", () => { @@ -270,7 +323,11 @@ describe("unittests:: tsserver:: events:: ProjectsUpdatedInBackground", () => { host.writeFile(moduleFile1.path, `export var T: number;export function Foo() { };`); host.runQueuedTimeoutCallbacks(); - baselineTsserverLogs("events/projectUpdatedInBackground", `${scenario} and should always return the file itself if --out or --outFile is specified`, session); + baselineTsserverLogs( + "events/projectUpdatedInBackground", + `${scenario} and should always return the file itself if --out or --outFile is specified`, + session, + ); }); it("should return cascaded affected file list", () => { @@ -293,7 +350,11 @@ describe("unittests:: tsserver:: events:: ProjectsUpdatedInBackground", () => { updateContentOfOpenFile(file1Consumer1, file1Consumer1.content + "export var T2: number;"); host.writeFile(moduleFile1.path, `export var T2: number;export function Foo() { };`); host.runQueuedTimeoutCallbacks(); - baselineTsserverLogs("events/projectUpdatedInBackground", `${scenario} and should return cascaded affected file list`, session); + baselineTsserverLogs( + "events/projectUpdatedInBackground", + `${scenario} and should return cascaded affected file list`, + session, + ); }); it("should work fine for files with circular references", () => { @@ -316,7 +377,11 @@ describe("unittests:: tsserver:: events:: ProjectsUpdatedInBackground", () => { host.writeFile(file2.path, file2.content + "export var t3 = 10;"); host.runQueuedTimeoutCallbacks(); - baselineTsserverLogs("events/projectUpdatedInBackground", `${scenario} and should work fine for files with circular references`, session); + baselineTsserverLogs( + "events/projectUpdatedInBackground", + `${scenario} and should work fine for files with circular references`, + session, + ); }); it("should detect removed code file", () => { @@ -333,7 +398,11 @@ describe("unittests:: tsserver:: events:: ProjectsUpdatedInBackground", () => { host.deleteFile(moduleFile1Path); host.runQueuedTimeoutCallbacks(); - baselineTsserverLogs("events/projectUpdatedInBackground", `${scenario} and should detect removed code file`, session); + baselineTsserverLogs( + "events/projectUpdatedInBackground", + `${scenario} and should detect removed code file`, + session, + ); }); it("should detect non-existing code file", () => { @@ -354,14 +423,22 @@ describe("unittests:: tsserver:: events:: ProjectsUpdatedInBackground", () => { // Create module File2 and see both files are saved host.writeFile(moduleFile2.path, moduleFile2.content); host.runQueuedTimeoutCallbacks(); - baselineTsserverLogs("events/projectUpdatedInBackground", `${scenario} and should detect non-existing code file`, session); + baselineTsserverLogs( + "events/projectUpdatedInBackground", + `${scenario} and should detect non-existing code file`, + session, + ); }); }); describe("resolution when resolution cache size", () => { - function verifyWithMaxCacheLimit(subScenario: string, useSlashRootAsSomeNotRootFolderInUserDirectory: boolean) { + function verifyWithMaxCacheLimit( + subScenario: string, + useSlashRootAsSomeNotRootFolderInUserDirectory: boolean, + ) { it(subScenario, () => { - const rootFolder = useSlashRootAsSomeNotRootFolderInUserDirectory ? "/user/username/rootfolder/otherfolder/" : "/"; + const rootFolder = useSlashRootAsSomeNotRootFolderInUserDirectory + ? "/user/username/rootfolder/otherfolder/" : "/"; const file1: File = { path: rootFolder + "a/b/project/file1.ts", content: 'import a from "file2"', @@ -391,16 +468,29 @@ describe("unittests:: tsserver:: events:: ProjectsUpdatedInBackground", () => { host.runQueuedTimeoutCallbacks(); // For invalidation host.runQueuedTimeoutCallbacks(); // For actual update - baselineTsserverLogs("events/projectUpdatedInBackground", `${scenario} and ${subScenario}`, session); + baselineTsserverLogs( + "events/projectUpdatedInBackground", + `${scenario} and ${subScenario}`, + session, + ); }); } - verifyWithMaxCacheLimit("project is not at root level", /*useSlashRootAsSomeNotRootFolderInUserDirectory*/ true); - verifyWithMaxCacheLimit("project is at root level", /*useSlashRootAsSomeNotRootFolderInUserDirectory*/ false); + verifyWithMaxCacheLimit( + "project is not at root level", + /*useSlashRootAsSomeNotRootFolderInUserDirectory*/ true, + ); + verifyWithMaxCacheLimit( + "project is at root level", + /*useSlashRootAsSomeNotRootFolderInUserDirectory*/ false, + ); }); } describe("when event handler is set in the session", () => { - verifyProjectsUpdatedInBackgroundEvent("when event handler is set in the session", createSessionWithCustomEventHandler); + verifyProjectsUpdatedInBackgroundEvent( + "when event handler is set in the session", + createSessionWithCustomEventHandler, + ); }); describe("when event handler is not set but session is created with canUseEvents = true", () => { diff --git a/src/testRunner/unittests/tsserver/exportMapCache.ts b/src/testRunner/unittests/tsserver/exportMapCache.ts index bcf6b3b38fd71..2759cd7214bba 100644 --- a/src/testRunner/unittests/tsserver/exportMapCache.ts +++ b/src/testRunner/unittests/tsserver/exportMapCache.ts @@ -80,7 +80,11 @@ describe("unittests:: tsserver:: exportMapCache", () => { project.getPackageJsonAutoImportProvider(); assert.ok(exportMapCache.isUsableByFile(bTs.path as ts.Path)); assert.ok(!exportMapCache.isEmpty()); - baselineTsserverLogs("exportMapCache", "does not invalidate the cache when package.json is changed inconsequentially", session); + baselineTsserverLogs( + "exportMapCache", + "does not invalidate the cache when package.json is changed inconsequentially", + session, + ); }); it("invalidates the cache when package.json change results in AutoImportProvider change", () => { @@ -90,7 +94,11 @@ describe("unittests:: tsserver:: exportMapCache", () => { project.getPackageJsonAutoImportProvider(); assert.ok(!exportMapCache.isUsableByFile(bTs.path as ts.Path)); assert.ok(exportMapCache.isEmpty()); - baselineTsserverLogs("exportMapCache", "invalidates the cache when package.json change results in AutoImportProvider change", session); + baselineTsserverLogs( + "exportMapCache", + "invalidates the cache when package.json change results in AutoImportProvider change", + session, + ); }); it("does not store transient symbols through program updates", () => { @@ -222,19 +230,40 @@ describe("unittests:: tsserver:: exportMapCache", () => { }, }); - baselineTsserverLogs("exportMapCache", "invalidates the cache when a file is opened with different contents", session); + baselineTsserverLogs( + "exportMapCache", + "invalidates the cache when a file is opened with different contents", + session, + ); }); }); function setup() { - const host = createServerHost([aTs, bTs, ambientDeclaration, tsconfig, packageJson, mobxPackageJson, mobxDts, exportEqualsMappedType]); + const host = createServerHost([ + aTs, + bTs, + ambientDeclaration, + tsconfig, + packageJson, + mobxPackageJson, + mobxDts, + exportEqualsMappedType, + ]); const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) }); openFilesForSession([aTs, bTs], session); const projectService = session.getProjectService(); const project = projectService.configuredProjects.get(tsconfig.path)!; triggerCompletions(); const checker = project.getLanguageService().getProgram()!.getTypeChecker(); - return { host, project, projectService, session, exportMapCache: project.getCachedExportInfoMap(), checker, triggerCompletions }; + return { + host, + project, + projectService, + session, + exportMapCache: project.getCachedExportInfoMap(), + checker, + triggerCompletions, + }; function triggerCompletions() { const requestLocation: ts.server.protocol.FileLocationRequestArgs = { diff --git a/src/testRunner/unittests/tsserver/externalProjects.ts b/src/testRunner/unittests/tsserver/externalProjects.ts index 5c6727ba5310d..405f405b7f2d1 100644 --- a/src/testRunner/unittests/tsserver/externalProjects.ts +++ b/src/testRunner/unittests/tsserver/externalProjects.ts @@ -42,7 +42,10 @@ describe("unittests:: tsserver:: externalProjects", () => { preferences: { lazyConfiguredProjectsFromExternalProject }, }, }); - const upperCaseConfigFilePath = ts.combinePaths(ts.getDirectoryPath(config.path).toUpperCase(), ts.getBaseFileName(config.path)); + const upperCaseConfigFilePath = ts.combinePaths( + ts.getDirectoryPath(config.path).toUpperCase(), + ts.getBaseFileName(config.path), + ); openExternalProjectForSession({ projectFileName: "/a/b/project.csproj", rootFiles: toExternalFiles([f1.path, upperCaseConfigFilePath]), @@ -50,7 +53,13 @@ describe("unittests:: tsserver:: externalProjects", () => { }, session); openFilesForSession([f1], session); - baselineTsserverLogs("externalProjects", `can handle tsconfig file name with difference casing${lazyConfiguredProjectsFromExternalProject ? " with lazyConfiguredProjectsFromExternalProject" : ""}`, session); + baselineTsserverLogs( + "externalProjects", + `can handle tsconfig file name with difference casing${ + lazyConfiguredProjectsFromExternalProject ? " with lazyConfiguredProjectsFromExternalProject" : "" + }`, + session, + ); } it("when lazyConfiguredProjectsFromExternalProject not set", () => { @@ -78,7 +87,13 @@ describe("unittests:: tsserver:: externalProjects", () => { const proxy = Harness.LanguageService.makeDefaultProxy(info); proxy.getSemanticDiagnostics = filename => { const prev = info.languageService.getSemanticDiagnostics(filename); - const sourceFile: ts.SourceFile = info.project.getSourceFile(ts.toPath(filename, /*basePath*/ undefined, ts.createGetCanonicalFileName(info.serverHost.useCaseSensitiveFileNames)))!; + const sourceFile: ts.SourceFile = info.project.getSourceFile( + ts.toPath( + filename, + /*basePath*/ undefined, + ts.createGetCanonicalFileName(info.serverHost.useCaseSensitiveFileNames), + ), + )!; prev.push({ category: ts.DiagnosticCategory.Warning, file: sourceFile, @@ -95,7 +110,10 @@ describe("unittests:: tsserver:: externalProjects", () => { error: undefined, }; }; - const session = createSession(host, { globalPlugins: ["myplugin"], logger: createLoggerWithInMemoryLogs(host) }); + const session = createSession(host, { + globalPlugins: ["myplugin"], + logger: createLoggerWithInMemoryLogs(host), + }); openExternalProjectsForSession([p1], session); session.executeCommandSeq({ @@ -121,7 +139,11 @@ describe("unittests:: tsserver:: externalProjects", () => { path: "/c/app.ts", content: "let x = 1", }; - const makeProject = (f: File) => ({ projectFileName: f.path + ".csproj", rootFiles: [toExternalFile(f.path)], options: {} }); + const makeProject = (f: File) => ({ + projectFileName: f.path + ".csproj", + rootFiles: [toExternalFile(f.path)], + options: {}, + }); const p1 = makeProject(f1); const p2 = makeProject(f2); const p3 = makeProject(f3); @@ -157,7 +179,11 @@ describe("unittests:: tsserver:: externalProjects", () => { // close client file - external project should still exists projectService.closeClientFile(file1.path); projectService.closeExternalProject(externalProjectName); - baselineTsserverLogs("externalProjects", "should not close external project with no open files", projectService); + baselineTsserverLogs( + "externalProjects", + "should not close external project with no open files", + projectService, + ); }); it("external project for dynamic file", () => { @@ -286,7 +312,11 @@ describe("unittests:: tsserver:: externalProjects", () => { // configured project is alive since it is opened as part of external project projectService.closeExternalProject(externalProjectName); - baselineTsserverLogs("externalProjects", "external project with included config file opened after configured project", projectService); + baselineTsserverLogs( + "externalProjects", + "external project with included config file opened after configured project", + projectService, + ); }); it("external project with included config file opened after configured project and then closed", () => { @@ -320,7 +350,11 @@ describe("unittests:: tsserver:: externalProjects", () => { projectService.closeClientFile(file1.path); projectService.openClientFile(file2.path); - baselineTsserverLogs("externalProjects", "external project with included config file opened after configured project and then closed", projectService); + baselineTsserverLogs( + "externalProjects", + "external project with included config file opened after configured project and then closed", + projectService, + ); }); it("can correctly update external project when set of root files has changed", () => { @@ -335,10 +369,22 @@ describe("unittests:: tsserver:: externalProjects", () => { const host = createServerHost([file1, file2]); const projectService = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) }); - projectService.openExternalProject({ projectFileName: "project", options: {}, rootFiles: toExternalFiles([file1.path]) }); + projectService.openExternalProject({ + projectFileName: "project", + options: {}, + rootFiles: toExternalFiles([file1.path]), + }); - projectService.openExternalProject({ projectFileName: "project", options: {}, rootFiles: toExternalFiles([file1.path, file2.path]) }); - baselineTsserverLogs("externalProjects", "can correctly update external project when set of root files has changed", projectService); + projectService.openExternalProject({ + projectFileName: "project", + options: {}, + rootFiles: toExternalFiles([file1.path, file2.path]), + }); + baselineTsserverLogs( + "externalProjects", + "can correctly update external project when set of root files has changed", + projectService, + ); }); it("can update external project when set of root files was not changed", () => { @@ -358,10 +404,22 @@ describe("unittests:: tsserver:: externalProjects", () => { const host = createServerHost([file1, file2, file3]); const projectService = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) }); - projectService.openExternalProject({ projectFileName: "project", options: { moduleResolution: ts.ModuleResolutionKind.Node10 }, rootFiles: toExternalFiles([file1.path, file2.path]) }); + projectService.openExternalProject({ + projectFileName: "project", + options: { moduleResolution: ts.ModuleResolutionKind.Node10 }, + rootFiles: toExternalFiles([file1.path, file2.path]), + }); - projectService.openExternalProject({ projectFileName: "project", options: { moduleResolution: ts.ModuleResolutionKind.Classic }, rootFiles: toExternalFiles([file1.path, file2.path]) }); - baselineTsserverLogs("externalProjects", "can update external project when set of root files was not changed", projectService); + projectService.openExternalProject({ + projectFileName: "project", + options: { moduleResolution: ts.ModuleResolutionKind.Classic }, + rootFiles: toExternalFiles([file1.path, file2.path]), + }); + baselineTsserverLogs( + "externalProjects", + "can update external project when set of root files was not changed", + projectService, + ); }); it("language service disabled state is updated in external projects", () => { @@ -375,7 +433,8 @@ describe("unittests:: tsserver:: externalProjects", () => { }; const host = createServerHost([f1, f2]); const originalGetFileSize = host.getFileSize; - host.getFileSize = (filePath: string) => filePath === f2.path ? ts.server.maxProgramSizeForNonTsFiles + 1 : originalGetFileSize.call(host, filePath); + host.getFileSize = (filePath: string) => + filePath === f2.path ? ts.server.maxProgramSizeForNonTsFiles + 1 : originalGetFileSize.call(host, filePath); const service = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) }); const projectFileName = "/a/proj.csproj"; @@ -400,7 +459,11 @@ describe("unittests:: tsserver:: externalProjects", () => { options: {}, }); assert.isFalse(service.externalProjects[0].languageServiceEnabled, "language service should be disabled - 2"); - baselineTsserverLogs("externalProjects", "language service disabled state is updated in external projects", service); + baselineTsserverLogs( + "externalProjects", + "language service disabled state is updated in external projects", + service, + ); }); describe("deleting config file opened from the external project works", () => { @@ -436,7 +499,13 @@ describe("unittests:: tsserver:: externalProjects", () => { externalProject.rootFiles.length = 1; projectService.openExternalProjects([externalProject]); - baselineTsserverLogs("externalProjects", `deleting config file opened from the external project works${lazyConfiguredProjectsFromExternalProject ? " with lazyConfiguredProjectsFromExternalProject" : ""}`, projectService); + baselineTsserverLogs( + "externalProjects", + `deleting config file opened from the external project works${ + lazyConfiguredProjectsFromExternalProject ? " with lazyConfiguredProjectsFromExternalProject" : "" + }`, + projectService, + ); } it("when lazyConfiguredProjectsFromExternalProject not set", () => { verifyDeletingConfigFile(/*lazyConfiguredProjectsFromExternalProject*/ false); @@ -491,7 +560,13 @@ describe("unittests:: tsserver:: externalProjects", () => { rootFiles: toExternalFiles([f1.path, f2.path]), options: {}, }); - baselineTsserverLogs("externalProjects", `correctly handling add or remove tsconfig - 1${lazyConfiguredProjectsFromExternalProject ? " with lazyConfiguredProjectsFromExternalProject" : ""}`, projectService); + baselineTsserverLogs( + "externalProjects", + `correctly handling add or remove tsconfig - 1${ + lazyConfiguredProjectsFromExternalProject ? " with lazyConfiguredProjectsFromExternalProject" : "" + }`, + projectService, + ); } it("when lazyConfiguredProjectsFromExternalProject not set", () => { verifyAddRemoveConfig(/*lazyConfiguredProjectsFromExternalProject*/ false); @@ -572,7 +647,13 @@ describe("unittests:: tsserver:: externalProjects", () => { // close all projects - no projects should be opened projectService.closeExternalProject(projectName); - baselineTsserverLogs("externalProjects", `correctly handling add or remove tsconfig - 2${lazyConfiguredProjectsFromExternalProject ? " with lazyConfiguredProjectsFromExternalProject" : ""}`, projectService); + baselineTsserverLogs( + "externalProjects", + `correctly handling add or remove tsconfig - 2${ + lazyConfiguredProjectsFromExternalProject ? " with lazyConfiguredProjectsFromExternalProject" : "" + }`, + projectService, + ); } it("when lazyConfiguredProjectsFromExternalProject not set", () => { @@ -629,14 +710,20 @@ describe("unittests:: tsserver:: externalProjects", () => { }, ), }; - const host = createServerHost([libES5, libES2015Promise, app, config1], { executingFilePath: "/compiler/tsc.js" }); + const host = createServerHost([libES5, libES2015Promise, app, config1], { + executingFilePath: "/compiler/tsc.js", + }); const projectService = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) }); projectService.openClientFile(app.path); host.writeFile(config2.path, config2.content); host.runQueuedTimeoutCallbacks(); - baselineTsserverLogs("externalProjects", "correctly handles changes in lib section of config file", projectService); + baselineTsserverLogs( + "externalProjects", + "correctly handles changes in lib section of config file", + projectService, + ); }); it("should handle non-existing directories in config file", () => { @@ -663,7 +750,11 @@ describe("unittests:: tsserver:: externalProjects", () => { projectService.openClientFile(f.path); logConfiguredProjectsHasOpenRefStatus(projectService); - baselineTsserverLogs("externalProjects", "should handle non-existing directories in config file", projectService); + baselineTsserverLogs( + "externalProjects", + "should handle non-existing directories in config file", + projectService, + ); }); it("handles loads existing configured projects of external projects when lazyConfiguredProjectsFromExternalProject is disabled", () => { @@ -699,7 +790,11 @@ describe("unittests:: tsserver:: externalProjects", () => { } as ts.server.protocol.ExternalProject); const project2 = service.configuredProjects.get(config.path)!; assert.equal(project2.pendingReload, ts.ConfigFileProgramReloadLevel.None); // External project referenced configured project loaded - baselineTsserverLogs("externalProjects", "handles loads existing configured projects of external projects when lazyConfiguredProjectsFromExternalProject is disabled", service); + baselineTsserverLogs( + "externalProjects", + "handles loads existing configured projects of external projects when lazyConfiguredProjectsFromExternalProject is disabled", + service, + ); }); it("handles creation of external project with jsconfig before jsconfig creation watcher is invoked", () => { @@ -727,7 +822,9 @@ describe("unittests:: tsserver:: externalProjects", () => { rootFiles: [{ fileName: tsconfig.path }, { fileName: jsFilePath }], options: { allowJs: false }, }]); - service.applyChangesInOpenFiles(ts.singleIterator({ fileName: jsFilePath, scriptKind: ts.ScriptKind.JS, content: "" })); + service.applyChangesInOpenFiles( + ts.singleIterator({ fileName: jsFilePath, scriptKind: ts.ScriptKind.JS, content: "" }), + ); // write jsconfig file const jsConfig: File = { @@ -744,7 +841,11 @@ describe("unittests:: tsserver:: externalProjects", () => { options: { allowJs: false }, }]); logInferredProjectsOrphanStatus(service); - baselineTsserverLogs("externalProjects", "handles creation of external project with jsconfig before jsconfig creation watcher is invoked", service); + baselineTsserverLogs( + "externalProjects", + "handles creation of external project with jsconfig before jsconfig creation watcher is invoked", + service, + ); }); it("does not crash if external file does not exist", () => { diff --git a/src/testRunner/unittests/tsserver/findAllReferences.ts b/src/testRunner/unittests/tsserver/findAllReferences.ts index e194b58fe7bb1..d807cd6fe798b 100644 --- a/src/testRunner/unittests/tsserver/findAllReferences.ts +++ b/src/testRunner/unittests/tsserver/findAllReferences.ts @@ -129,7 +129,11 @@ const bar: Bar = { const loadingIndicatorScriptInfo = session.getProjectService().getScriptInfo(files[3].path)!; // At this point, we haven't updated `babel-loader` project yet, // so `babel-loader` is still a containing project of `loading-indicator` file. - assert(loadingIndicatorScriptInfo.containingProjects.find(p => p.projectName === "/packages/babel-loader/tsconfig.json")); + assert( + loadingIndicatorScriptInfo.containingProjects.find(p => + p.projectName === "/packages/babel-loader/tsconfig.json" + ), + ); // When calling find all references, // we shouldn't crash due to using outdated information on a file's containig projects. session.executeCommandSeq({ @@ -140,6 +144,10 @@ const bar: Bar = { offset: 5, }, }); - baselineTsserverLogs("findAllReferences", "does not try to open a file in a project that was updated and no longer has the file", session); + baselineTsserverLogs( + "findAllReferences", + "does not try to open a file in a project that was updated and no longer has the file", + session, + ); }); }); diff --git a/src/testRunner/unittests/tsserver/forceConsistentCasingInFileNames.ts b/src/testRunner/unittests/tsserver/forceConsistentCasingInFileNames.ts index 2ef7a891b2afc..84f1fe513a095 100644 --- a/src/testRunner/unittests/tsserver/forceConsistentCasingInFileNames.ts +++ b/src/testRunner/unittests/tsserver/forceConsistentCasingInFileNames.ts @@ -45,7 +45,9 @@ describe("unittests:: tsserver:: forceConsistentCasingInFileNames", () => { content: JSON.stringify({ extends: "./tsconfig.all.json" }), }; - const host = createServerHost([file1, file2, file2Dts, libFile, tsconfig, tsconfigAll], { useCaseSensitiveFileNames: false }); + const host = createServerHost([file1, file2, file2Dts, libFile, tsconfig, tsconfigAll], { + useCaseSensitiveFileNames: false, + }); const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) }); openFilesForSession([file1], session); @@ -55,7 +57,11 @@ describe("unittests:: tsserver:: forceConsistentCasingInFileNames", () => { projectFileName: tsconfig.path, }, }); - baselineTsserverLogs("forceConsistentCasingInFileNames", "works when extends is specified with a case insensitive file system", session); + baselineTsserverLogs( + "forceConsistentCasingInFileNames", + "works when extends is specified with a case insensitive file system", + session, + ); }); it("works when renaming file with different casing", () => { @@ -82,7 +88,11 @@ describe("unittests:: tsserver:: forceConsistentCasingInFileNames", () => { const newLoggerPath = loggerFile.path.toLowerCase(); host.renameFile(loggerFile.path, newLoggerPath); closeFilesForSession([loggerFile], session); - openFilesForSession([{ file: newLoggerPath, content: loggerFile.content, projectRootPath: "/user/username/projects/myproject" }], session); + openFilesForSession([{ + file: newLoggerPath, + content: loggerFile.content, + projectRootPath: "/user/username/projects/myproject", + }], session); // Apply edits for rename openFilesForSession([{ file: anotherFile, projectRootPath: "/user/username/projects/myproject" }], session); @@ -104,7 +114,11 @@ describe("unittests:: tsserver:: forceConsistentCasingInFileNames", () => { // Check errors in both files verifyGetErrRequest({ session, files: [newLoggerPath, anotherFile] }); - baselineTsserverLogs("forceConsistentCasingInFileNames", "works when renaming file with different casing", session); + baselineTsserverLogs( + "forceConsistentCasingInFileNames", + "works when renaming file with different casing", + session, + ); }); it("when changing module name with different casing", () => { @@ -146,6 +160,10 @@ describe("unittests:: tsserver:: forceConsistentCasingInFileNames", () => { // Check errors in both files verifyGetErrRequest({ session, files: [anotherFile] }); - baselineTsserverLogs("forceConsistentCasingInFileNames", "when changing module name with different casing", session); + baselineTsserverLogs( + "forceConsistentCasingInFileNames", + "when changing module name with different casing", + session, + ); }); }); diff --git a/src/testRunner/unittests/tsserver/formatSettings.ts b/src/testRunner/unittests/tsserver/formatSettings.ts index a0d55ac41a5ed..aca29c7674607 100644 --- a/src/testRunner/unittests/tsserver/formatSettings.ts +++ b/src/testRunner/unittests/tsserver/formatSettings.ts @@ -22,34 +22,71 @@ describe("unittests:: tsserver:: formatSettings", () => { const defaultSettings = session.getProjectService().getFormatCodeOptions(f1.path as ts.server.NormalizedPath); // set global settings - const newGlobalSettings1 = { ...defaultSettings, placeOpenBraceOnNewLineForControlBlocks: !defaultSettings.placeOpenBraceOnNewLineForControlBlocks }; + const newGlobalSettings1 = { + ...defaultSettings, + placeOpenBraceOnNewLineForControlBlocks: !defaultSettings.placeOpenBraceOnNewLineForControlBlocks, + }; session.executeCommandSeq({ command: ts.server.protocol.CommandTypes.Configure, arguments: { formatOptions: newGlobalSettings1 }, }); // get format options for file - should be equal to new global settings - session.logger.log(`FormatCodeOptions should be global:: ${f1.path}:: ${JSON.stringify(session.getProjectService().getFormatCodeOptions(ts.server.toNormalizedPath(f1.path)), undefined, " ")}`); + session.logger.log( + `FormatCodeOptions should be global:: ${f1.path}:: ${ + JSON.stringify( + session.getProjectService().getFormatCodeOptions(ts.server.toNormalizedPath(f1.path)), + undefined, + " ", + ) + }`, + ); // set per file format options - const newPerFileSettings = { ...defaultSettings, insertSpaceAfterCommaDelimiter: !defaultSettings.insertSpaceAfterCommaDelimiter }; + const newPerFileSettings = { + ...defaultSettings, + insertSpaceAfterCommaDelimiter: !defaultSettings.insertSpaceAfterCommaDelimiter, + }; session.executeCommandSeq({ command: ts.server.protocol.CommandTypes.Configure, arguments: { formatOptions: newPerFileSettings, file: f1.path }, }); // get format options for file - should be equal to new per-file settings - session.logger.log(`FormatCodeOptions should be per file:: ${f1.path}:: ${JSON.stringify(session.getProjectService().getFormatCodeOptions(ts.server.toNormalizedPath(f1.path)), undefined, " ")}`); + session.logger.log( + `FormatCodeOptions should be per file:: ${f1.path}:: ${ + JSON.stringify( + session.getProjectService().getFormatCodeOptions(ts.server.toNormalizedPath(f1.path)), + undefined, + " ", + ) + }`, + ); // set new global settings - they should not affect ones that were set per-file - const newGlobalSettings2 = { ...defaultSettings, insertSpaceAfterSemicolonInForStatements: !defaultSettings.insertSpaceAfterSemicolonInForStatements }; + const newGlobalSettings2 = { + ...defaultSettings, + insertSpaceAfterSemicolonInForStatements: !defaultSettings.insertSpaceAfterSemicolonInForStatements, + }; session.executeCommandSeq({ command: ts.server.protocol.CommandTypes.Configure, arguments: { formatOptions: newGlobalSettings2 }, }); // get format options for file - should be equal to new per-file settings - session.logger.log(`FormatCodeOptions should be per file:: ${f1.path}:: ${JSON.stringify(session.getProjectService().getFormatCodeOptions(ts.server.toNormalizedPath(f1.path)), undefined, " ")}`); - baselineTsserverLogs("formatSettings", "works when extends is specified with a case insensitive file system", session); + session.logger.log( + `FormatCodeOptions should be per file:: ${f1.path}:: ${ + JSON.stringify( + session.getProjectService().getFormatCodeOptions(ts.server.toNormalizedPath(f1.path)), + undefined, + " ", + ) + }`, + ); + baselineTsserverLogs( + "formatSettings", + "works when extends is specified with a case insensitive file system", + session, + ); }); }); diff --git a/src/testRunner/unittests/tsserver/getEditsForFileRename.ts b/src/testRunner/unittests/tsserver/getEditsForFileRename.ts index d7ebe9570845b..3fb0f97d22c62 100644 --- a/src/testRunner/unittests/tsserver/getEditsForFileRename.ts +++ b/src/testRunner/unittests/tsserver/getEditsForFileRename.ts @@ -28,7 +28,11 @@ describe("unittests:: tsserver:: getEditsForFileRename", () => { const host = createServerHost([userTs, newTs, tsconfig]); const options: ts.CompilerOptions = {}; - const moduleResolutionCache = ts.createModuleResolutionCache(host.getCurrentDirectory(), ts.createGetCanonicalFileName(host.useCaseSensitiveFileNames), options); + const moduleResolutionCache = ts.createModuleResolutionCache( + host.getCurrentDirectory(), + ts.createGetCanonicalFileName(host.useCaseSensitiveFileNames), + options, + ); const lsHost: ts.LanguageServiceHost = { getCompilationSettings: () => options, getScriptFileNames: () => [newTs.path, userTs.path], @@ -41,8 +45,17 @@ describe("unittests:: tsserver:: getEditsForFileRename", () => { getDefaultLibFileName: options => ts.getDefaultLibFileName(options), readFile: path => host.readFile(path), fileExists: path => host.fileExists(path), - resolveModuleNames: (moduleNames, containingFile) => moduleNames.map(name => ts.resolveModuleName(name, containingFile, options, lsHost, moduleResolutionCache).resolvedModule), - getResolvedModuleWithFailedLookupLocationsFromCache: (moduleName, containingFile, mode) => moduleResolutionCache.getFromDirectoryCache(moduleName, mode, ts.getDirectoryPath(containingFile), /*redirectedReference*/ undefined), + resolveModuleNames: (moduleNames, containingFile) => + moduleNames.map(name => + ts.resolveModuleName(name, containingFile, options, lsHost, moduleResolutionCache).resolvedModule + ), + getResolvedModuleWithFailedLookupLocationsFromCache: (moduleName, containingFile, mode) => + moduleResolutionCache.getFromDirectoryCache( + moduleName, + mode, + ts.getDirectoryPath(containingFile), + /*redirectedReference*/ undefined, + ), }; const service = ts.createLanguageService(lsHost); const edits = service.getEditsForFileRename("/old.ts", "/new.ts", ts.testFormatSettings, ts.emptyOptions); diff --git a/src/testRunner/unittests/tsserver/getExportReferences.ts b/src/testRunner/unittests/tsserver/getExportReferences.ts index 1219a07c2f3b1..c8347e7f67282 100644 --- a/src/testRunner/unittests/tsserver/getExportReferences.ts +++ b/src/testRunner/unittests/tsserver/getExportReferences.ts @@ -68,7 +68,11 @@ export const { nest: [valueE, { valueF }] } = { nest: [0, { valueF: 1 }] }; command: ts.server.protocol.CommandTypes.References, arguments: protocolFileLocationFromSubstring(modTs, "renamedD"), }); - baselineTsserverLogs("getExportReferences", "object declaration references that renames destructured property", session); + baselineTsserverLogs( + "getExportReferences", + "object declaration references that renames destructured property", + session, + ); }); it("should get nested object declaration references", () => { diff --git a/src/testRunner/unittests/tsserver/getMoveToRefactoringFileSuggestions.ts b/src/testRunner/unittests/tsserver/getMoveToRefactoringFileSuggestions.ts index 67aa8b3f9d353..bf958bcd1cd2f 100644 --- a/src/testRunner/unittests/tsserver/getMoveToRefactoringFileSuggestions.ts +++ b/src/testRunner/unittests/tsserver/getMoveToRefactoringFileSuggestions.ts @@ -38,14 +38,27 @@ import { value1 } from "../node_modules/.cache/someFile.d.ts";`, path: "/project/tsconfig.json", content: "{}", }; - const host = createServerHost([file1, file2, file3, file3, file4, nodeModulesFile1, nodeModulesFile2, tsconfig]); + const host = createServerHost([ + file1, + file2, + file3, + file3, + file4, + nodeModulesFile1, + nodeModulesFile2, + tsconfig, + ]); const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) }); openFilesForSession([file1], session); session.executeCommandSeq({ command: ts.server.protocol.CommandTypes.GetMoveToRefactoringFileSuggestions, arguments: { file: file1.path, line: 1, offset: 11 }, }); - baselineTsserverLogs("getMoveToRefactoringFileSuggestions", "works for suggesting a list of files, excluding node_modules within a project", session); + baselineTsserverLogs( + "getMoveToRefactoringFileSuggestions", + "works for suggesting a list of files, excluding node_modules within a project", + session, + ); }); it("suggests only .ts file for a .ts filepath", () => { const file1: File = { @@ -61,7 +74,20 @@ import { value1 } from "../node_modules/.cache/someFile.d.ts";`, const file5: File = { path: "/file5.js", content: "" }; const file6: File = { path: "/file6.d.ts", content: "" }; const file7: File = { path: "/file7.ts", content: "" }; - const tsconfig: File = { path: "/tsconfig.json", content: JSON.stringify({ files: ["./file1.ts", "./file2.tsx", "./file3.mts", "./file4.cts", "./file5.js", "./file6.d.ts", "./file7.ts"] }) }; + const tsconfig: File = { + path: "/tsconfig.json", + content: JSON.stringify({ + files: [ + "./file1.ts", + "./file2.tsx", + "./file3.mts", + "./file4.cts", + "./file5.js", + "./file6.d.ts", + "./file7.ts", + ], + }), + }; const host = createServerHost([file1, file2, file3, file4, file5, file6, file7, tsconfig]); const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) }); @@ -71,7 +97,11 @@ import { value1 } from "../node_modules/.cache/someFile.d.ts";`, command: ts.server.protocol.CommandTypes.GetMoveToRefactoringFileSuggestions, arguments: { file: file1.path, line: 1, offset: 11 }, }); - baselineTsserverLogs("getMoveToRefactoringFileSuggestions", "suggests only .ts file for a .ts filepath", session); + baselineTsserverLogs( + "getMoveToRefactoringFileSuggestions", + "suggests only .ts file for a .ts filepath", + session, + ); }); it("suggests only .js file for a .js filepath", () => { const file1: File = { @@ -82,7 +112,10 @@ import { value1 } from "../node_modules/.cache/someFile.d.ts";`, const file3: File = { path: "/file3.mts", content: "" }; const file4: File = { path: "/file4.ts", content: "" }; const file5: File = { path: "/file5.js", content: "" }; - const tsconfig: File = { path: "/tsconfig.json", content: JSON.stringify({ files: ["./file1.js", "./file2.js", "./file3.mts", "./file4.ts", "./file5.js"] }) }; + const tsconfig: File = { + path: "/tsconfig.json", + content: JSON.stringify({ files: ["./file1.js", "./file2.js", "./file3.mts", "./file4.ts", "./file5.js"] }), + }; const host = createServerHost([file1, file2, file3, file4, file5, tsconfig]); const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) }); @@ -92,7 +125,11 @@ import { value1 } from "../node_modules/.cache/someFile.d.ts";`, command: ts.server.protocol.CommandTypes.GetMoveToRefactoringFileSuggestions, arguments: { file: file1.path, line: 1, offset: 7 }, }); - baselineTsserverLogs("getMoveToRefactoringFileSuggestions", "suggests only .js file for a .js filepath", session); + baselineTsserverLogs( + "getMoveToRefactoringFileSuggestions", + "suggests only .js file for a .js filepath", + session, + ); }); it("skips lib.d.ts files", () => { const file1: File = { @@ -102,7 +139,10 @@ import { value1 } from "../node_modules/.cache/someFile.d.ts";`, const file2: File = { path: "/a/lib.d.ts", content: "" }; const file3: File = { path: "/a/file3.d.ts", content: "" }; const file4: File = { path: "/a/lib.es6.d.ts", content: "" }; - const tsconfig: File = { path: "/tsconfig.json", content: JSON.stringify({ files: ["./file1.d.ts", "./a/lib.d.ts", "./a/file3.d.ts", "/a/lib.es6.d.ts"] }) }; + const tsconfig: File = { + path: "/tsconfig.json", + content: JSON.stringify({ files: ["./file1.d.ts", "./a/lib.d.ts", "./a/file3.d.ts", "/a/lib.es6.d.ts"] }), + }; const host = createServerHost([file1, file2, file3, file4, tsconfig]); const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) }); diff --git a/src/testRunner/unittests/tsserver/importHelpers.ts b/src/testRunner/unittests/tsserver/importHelpers.ts index ad355231c2593..dba1ac21e5cf0 100644 --- a/src/testRunner/unittests/tsserver/importHelpers.ts +++ b/src/testRunner/unittests/tsserver/importHelpers.ts @@ -21,7 +21,11 @@ describe("unittests:: tsserver:: importHelpers", () => { }; const host = createServerHost([f1, tslib]); const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) }); - openExternalProjectForSession({ projectFileName: "p", rootFiles: [toExternalFile(f1.path)], options: { importHelpers: true } }, session); + openExternalProjectForSession({ + projectFileName: "p", + rootFiles: [toExternalFile(f1.path)], + options: { importHelpers: true }, + }, session); baselineTsserverLogs("importHelpers", "should not crash in tsserver", session); }); }); diff --git a/src/testRunner/unittests/tsserver/inconsistentErrorInEditor.ts b/src/testRunner/unittests/tsserver/inconsistentErrorInEditor.ts index 3a80c1437731d..2c9c789d24bdc 100644 --- a/src/testRunner/unittests/tsserver/inconsistentErrorInEditor.ts +++ b/src/testRunner/unittests/tsserver/inconsistentErrorInEditor.ts @@ -11,7 +11,11 @@ import { describe("unittests:: tsserver:: inconsistentErrorInEditor", () => { it("should not error", () => { const host = createServerHost([]); - const session = createSession(host, { canUseEvents: true, noGetErrOnBackgroundUpdate: true, logger: createLoggerWithInMemoryLogs(host) }); + const session = createSession(host, { + canUseEvents: true, + noGetErrOnBackgroundUpdate: true, + logger: createLoggerWithInMemoryLogs(host), + }); session.executeCommandSeq({ command: ts.server.protocol.CommandTypes.UpdateOpen, arguments: { @@ -20,7 +24,8 @@ describe("unittests:: tsserver:: inconsistentErrorInEditor", () => { openFiles: [ { file: "^/untitled/ts-nul-authority/Untitled-1", - fileContent: "export function foo() {\r\n /*$*/return bar;\r\n}\r\n\r\nexport function bar(x: T) {\r\n return x;\r\n}\r\n\r\nlet x = foo()(42);", + fileContent: + "export function foo() {\r\n /*$*/return bar;\r\n}\r\n\r\nexport function bar(x: T) {\r\n return x;\r\n}\r\n\r\nlet x = foo()(42);", scriptKindName: "TS", }, ], @@ -43,7 +48,11 @@ describe("unittests:: tsserver:: inconsistentErrorInEditor", () => { describe("unittests:: tsserver:: inconsistentErrorInEditor2", () => { it("should not error", () => { const host = createServerHost([]); - const session = createSession(host, { canUseEvents: true, noGetErrOnBackgroundUpdate: true, logger: createLoggerWithInMemoryLogs(host) }); + const session = createSession(host, { + canUseEvents: true, + noGetErrOnBackgroundUpdate: true, + logger: createLoggerWithInMemoryLogs(host), + }); session.executeCommandSeq({ command: ts.server.protocol.CommandTypes.UpdateOpen, arguments: { @@ -52,7 +61,8 @@ describe("unittests:: tsserver:: inconsistentErrorInEditor2", () => { openFiles: [ { file: "^/untitled/ts-nul-authority/Untitled-1", - fileContent: "function fn(Foo: number) {\r\n type Foo = typeof Foo;\r\n return 0 as any as {x: Foo};\r\n}", + fileContent: + "function fn(Foo: number) {\r\n type Foo = typeof Foo;\r\n return 0 as any as {x: Foo};\r\n}", scriptKindName: "TS", }, ], diff --git a/src/testRunner/unittests/tsserver/inferredProjects.ts b/src/testRunner/unittests/tsserver/inferredProjects.ts index 70582bc098712..e16bda2866d6c 100644 --- a/src/testRunner/unittests/tsserver/inferredProjects.ts +++ b/src/testRunner/unittests/tsserver/inferredProjects.ts @@ -63,14 +63,21 @@ describe("unittests:: tsserver:: inferredProjects", () => { }; const host = createServerHost([file1, file2, file3, libFile]); - const projectService = createProjectService(host, { useSingleInferredProject: true, logger: createLoggerWithInMemoryLogs(host) }); + const projectService = createProjectService(host, { + useSingleInferredProject: true, + logger: createLoggerWithInMemoryLogs(host), + }); projectService.openClientFile(file1.path); projectService.openClientFile(file2.path); projectService.openClientFile(file3.path); host.writeFile(configFile.path, configFile.content); host.runQueuedTimeoutCallbacks(); // load configured project from disk + ensureProjectsForOpenFiles - baselineTsserverLogs("inferredProjects", "should use only one inferred project if useOneInferredProject is set", projectService); + baselineTsserverLogs( + "inferredProjects", + "should use only one inferred project if useOneInferredProject is set", + projectService, + ); }); it("disable inferred project", () => { @@ -80,11 +87,17 @@ describe("unittests:: tsserver:: inferredProjects", () => { }; const host = createServerHost([file1]); - const projectService = createProjectService(host, { useSingleInferredProject: true, serverMode: ts.LanguageServiceMode.Syntactic, logger: createLoggerWithInMemoryLogs(host) }); + const projectService = createProjectService(host, { + useSingleInferredProject: true, + serverMode: ts.LanguageServiceMode.Syntactic, + logger: createLoggerWithInMemoryLogs(host), + }); projectService.openClientFile(file1.path, file1.content); - projectService.logger.log(`LanguageServiceEnabled:: ${projectService.inferredProjects[0].languageServiceEnabled}`); + projectService.logger.log( + `LanguageServiceEnabled:: ${projectService.inferredProjects[0].languageServiceEnabled}`, + ); baselineTsserverLogs("inferredProjects", "disable inferred project", projectService); }); @@ -182,7 +195,11 @@ describe("unittests:: tsserver:: inferredProjects", () => { { path: "/c/file3.ts", content: "let z = 4;" }, ]; const host = createServerHost(files, { useCaseSensitiveFileNames }); - const session = createSession(host, { useSingleInferredProject: true, useInferredProjectPerProjectRoot: true, logger: createLoggerWithInMemoryLogs(host) }); + const session = createSession(host, { + useSingleInferredProject: true, + useInferredProjectPerProjectRoot: true, + logger: createLoggerWithInMemoryLogs(host), + }); setCompilerOptionsForInferredProjectsRequestForSession({ allowJs: true, target: ts.ScriptTarget.ESNext, @@ -216,8 +233,17 @@ describe("unittests:: tsserver:: inferredProjects", () => { closeClientFiles(); baselineTsserverLogs("inferredProjects", subScenario, session); - function openClientFiles(projectRoots: [string | undefined, string | undefined, string | undefined, string | undefined]) { - files.forEach((file, index) => openFilesForSession([{ file: file.path, content: file.content, scriptKindName: "JS", projectRootPath: projectRoots[index] }], session)); + function openClientFiles( + projectRoots: [string | undefined, string | undefined, string | undefined, string | undefined], + ) { + files.forEach((file, index) => + openFilesForSession([{ + file: file.path, + content: file.content, + scriptKindName: "JS", + projectRootPath: projectRoots[index], + }], session) + ); } function closeClientFiles() { @@ -226,8 +252,14 @@ describe("unittests:: tsserver:: inferredProjects", () => { }); } - verifyProjectRootWithCaseSensitivity("inferred projects per project root with case sensitive system", /*useCaseSensitiveFileNames*/ true); - verifyProjectRootWithCaseSensitivity("inferred projects per project root with case insensitive system", /*useCaseSensitiveFileNames*/ false); + verifyProjectRootWithCaseSensitivity( + "inferred projects per project root with case sensitive system", + /*useCaseSensitiveFileNames*/ true, + ); + verifyProjectRootWithCaseSensitivity( + "inferred projects per project root with case insensitive system", + /*useCaseSensitiveFileNames*/ false, + ); it("should still retain configured project created while opening the file", () => { const appFile: File = { @@ -261,7 +293,11 @@ describe("unittests:: tsserver:: inferredProjects", () => { // When opening file that doesnt fall back to the config file, we remove the config project openFilesForSession([libFile], session); - baselineTsserverLogs("inferredProjects", "should still retain configured project created while opening the file", session); + baselineTsserverLogs( + "inferredProjects", + "should still retain configured project created while opening the file", + session, + ); }); it("regression test - should infer typeAcquisition for inferred projects when set undefined", () => { @@ -275,8 +311,16 @@ describe("unittests:: tsserver:: inferredProjects", () => { const inferredProject = projectService.inferredProjects[0]; projectService.logger.log(`typeAcquisition : setting to undefined`); inferredProject.setTypeAcquisition(undefined); - projectService.logger.log(`typeAcquisition should be inferred for inferred projects: ${JSON.stringify(inferredProject.getTypeAcquisition(), undefined, " ")}`); - baselineTsserverLogs("inferredProjects", "regression test - should infer typeAcquisition for inferred projects when set undefined", projectService); + projectService.logger.log( + `typeAcquisition should be inferred for inferred projects: ${ + JSON.stringify(inferredProject.getTypeAcquisition(), undefined, " ") + }`, + ); + baselineTsserverLogs( + "inferredProjects", + "regression test - should infer typeAcquisition for inferred projects when set undefined", + projectService, + ); }); it("Setting compiler options for inferred projects when there are no open files should not schedule any refresh", () => { @@ -287,6 +331,10 @@ describe("unittests:: tsserver:: inferredProjects", () => { target: ts.ScriptTarget.ES2015, }, session); session.testhost.logTimeoutQueueLength(); - baselineTsserverLogs("inferredProjects", "Setting compiler options for inferred projects when there are no open files should not schedule any refresh", session); + baselineTsserverLogs( + "inferredProjects", + "Setting compiler options for inferred projects when there are no open files should not schedule any refresh", + session, + ); }); }); diff --git a/src/testRunner/unittests/tsserver/inlayHints.ts b/src/testRunner/unittests/tsserver/inlayHints.ts index b2c7e0a3d1a5d..fbc3bb25e63f6 100644 --- a/src/testRunner/unittests/tsserver/inlayHints.ts +++ b/src/testRunner/unittests/tsserver/inlayHints.ts @@ -44,14 +44,20 @@ describe("unittests:: tsserver:: inlayHints", () => { session.executeCommandSeq({ command: ts.server.protocol.CommandTypes.UpdateOpen, arguments: { - changedFiles: [{ fileName: app.path, textChanges: [{ start: { line: 1, offset: 39 }, end: { line: 1, offset: 39 }, newText: "//" }] }], + changedFiles: [{ + fileName: app.path, + textChanges: [{ start: { line: 1, offset: 39 }, end: { line: 1, offset: 39 }, newText: "//" }], + }], }, }); verifyInlayHintResponse(session); session.executeCommandSeq({ command: ts.server.protocol.CommandTypes.UpdateOpen, arguments: { - changedFiles: [{ fileName: app.path, textChanges: [{ start: { line: 1, offset: 41 }, end: { line: 1, offset: 41 }, newText: "c" }] }], + changedFiles: [{ + fileName: app.path, + textChanges: [{ start: { line: 1, offset: 41 }, end: { line: 1, offset: 41 }, newText: "c" }], + }], }, }); verifyInlayHintResponse(session); diff --git a/src/testRunner/unittests/tsserver/jsdocTag.ts b/src/testRunner/unittests/tsserver/jsdocTag.ts index b3023da35d8b9..5900914bd8217 100644 --- a/src/testRunner/unittests/tsserver/jsdocTag.ts +++ b/src/testRunner/unittests/tsserver/jsdocTag.ts @@ -61,10 +61,14 @@ var x = 1 ;`, }; - assertQuickInfoJSDoc("for quickinfo, should provide display parts plus a span for a working link in a tag", linkInTag, { - command: ts.server.protocol.CommandTypes.Quickinfo, - displayPartsForJSDoc: true, - }); + assertQuickInfoJSDoc( + "for quickinfo, should provide display parts plus a span for a working link in a tag", + linkInTag, + { + command: ts.server.protocol.CommandTypes.Quickinfo, + displayPartsForJSDoc: true, + }, + ); assertQuickInfoJSDoc("for quickinfo, should provide a string for a working link in a tag", linkInTag, { command: ts.server.protocol.CommandTypes.Quickinfo, @@ -81,20 +85,28 @@ var x = 1 displayPartsForJSDoc: false, }); - assertQuickInfoJSDoc("for quickinfo-full, should provide display parts plus a span for a working link in a tag", linkInTag, { - command: ts.server.protocol.CommandTypes.QuickinfoFull, - displayPartsForJSDoc: true, - }); + assertQuickInfoJSDoc( + "for quickinfo-full, should provide display parts plus a span for a working link in a tag", + linkInTag, + { + command: ts.server.protocol.CommandTypes.QuickinfoFull, + displayPartsForJSDoc: true, + }, + ); assertQuickInfoJSDoc("for quickinfo-full, should provide a string for a working link in a tag", linkInTag, { command: ts.server.protocol.CommandTypes.QuickinfoFull, displayPartsForJSDoc: false, }); - assertQuickInfoJSDoc("for quickinfo-full, should provide display parts plus a span for a working link in a comment", linkInComment, { - command: ts.server.protocol.CommandTypes.QuickinfoFull, - displayPartsForJSDoc: true, - }); + assertQuickInfoJSDoc( + "for quickinfo-full, should provide display parts plus a span for a working link in a comment", + linkInComment, + { + command: ts.server.protocol.CommandTypes.QuickinfoFull, + displayPartsForJSDoc: true, + }, + ); assertQuickInfoJSDoc("for quickinfo-full, should provide a string for a working link in a comment", linkInComment, { command: ts.server.protocol.CommandTypes.QuickinfoFull, diff --git a/src/testRunner/unittests/tsserver/languageService.ts b/src/testRunner/unittests/tsserver/languageService.ts index b7f3646716c7f..4db3656854e92 100644 --- a/src/testRunner/unittests/tsserver/languageService.ts +++ b/src/testRunner/unittests/tsserver/languageService.ts @@ -19,7 +19,10 @@ describe("unittests:: tsserver:: languageService", () => { path: "/a/b/app.ts", content: "let x = 1;", }; - const host = createServerHost([lib, f], { executingFilePath: "/a/Lib/tsc.js", useCaseSensitiveFileNames: true }); + const host = createServerHost([lib, f], { + executingFilePath: "/a/Lib/tsc.js", + useCaseSensitiveFileNames: true, + }); const projectService = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) }); projectService.openClientFile(f.path); projectService.inferredProjects[0].getLanguageService().getProgram(); @@ -36,7 +39,8 @@ describe("unittests:: tsserver:: languageService", () => { }, { path: `/project/a/tsconfig.json`, - content: `{ "compilerOptions": { "paths": { "foo": ["./foo.d.ts"] } }, "files": ["./index.ts", "./foo.d.ts"] }`, + content: + `{ "compilerOptions": { "paths": { "foo": ["./foo.d.ts"] } }, "files": ["./index.ts", "./foo.d.ts"] }`, }, { path: `/project/a/foo.d.ts`, @@ -50,7 +54,8 @@ describe("unittests:: tsserver:: languageService", () => { }, { path: `/project/b/tsconfig.json`, - content: `{ "compilerOptions": { "paths": { "foo": ["./foo.d.ts"] } }, "files": ["./index.ts", "./foo.d.ts"] }`, + content: + `{ "compilerOptions": { "paths": { "foo": ["./foo.d.ts"] } }, "files": ["./index.ts", "./foo.d.ts"] }`, }, { path: `/project/b/foo.d.ts`, @@ -72,14 +77,20 @@ describe("unittests:: tsserver:: languageService", () => { projectService, `getSemanticDiagnostics:: ${files[1].path}`, projectService.configuredProjects.get(files[1].path)!, - projectService.configuredProjects.get(files[1].path)!.getLanguageService().getProgram()!.getSemanticDiagnostics(), + projectService.configuredProjects.get(files[1].path)!.getLanguageService().getProgram()! + .getSemanticDiagnostics(), ); logDiagnostics( projectService, `getSemanticDiagnostics:: ${files[4].path}`, projectService.configuredProjects.get(files[4].path)!, - projectService.configuredProjects.get(files[4].path)!.getLanguageService().getProgram()!.getSemanticDiagnostics(), + projectService.configuredProjects.get(files[4].path)!.getLanguageService().getProgram()! + .getSemanticDiagnostics(), + ); + baselineTsserverLogs( + "languageService", + "should support multiple projects with the same file under differing paths settings", + projectService, ); - baselineTsserverLogs("languageService", "should support multiple projects with the same file under differing paths settings", projectService); }); }); diff --git a/src/testRunner/unittests/tsserver/libraryResolution.ts b/src/testRunner/unittests/tsserver/libraryResolution.ts index 99a1d09942044..7aadb4d5a9fbe 100644 --- a/src/testRunner/unittests/tsserver/libraryResolution.ts +++ b/src/testRunner/unittests/tsserver/libraryResolution.ts @@ -13,7 +13,10 @@ describe("unittests:: tsserver:: libraryResolution", () => { const host = getServerHosForLibResolution(); const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) }); openFilesForSession(["/home/src/projects/project1/index.ts"], session); - host.ensureFileOrFolder({ path: "/home/src/projects/node_modules/@typescript/lib-dom/index.d.ts", content: "interface DOMInterface { }" }); + host.ensureFileOrFolder({ + path: "/home/src/projects/node_modules/@typescript/lib-dom/index.d.ts", + content: "interface DOMInterface { }", + }); host.runQueuedTimeoutCallbacks(); host.runQueuedTimeoutCallbacks(); host.appendFile("/home/src/projects/project1/file.ts", "export const xyz = 10;"); @@ -45,9 +48,15 @@ describe("unittests:: tsserver:: libraryResolution", () => { }, }), ); - host.ensureFileOrFolder({ path: "/home/src/projects/node_modules/@typescript/lib-dom/index.d.ts", content: "interface DOMInterface { }" }); + host.ensureFileOrFolder({ + path: "/home/src/projects/node_modules/@typescript/lib-dom/index.d.ts", + content: "interface DOMInterface { }", + }); host.runQueuedTimeoutCallbacks(); - host.ensureFileOrFolder({ path: "/home/src/projects/node_modules/@typescript/lib-webworker/index.d.ts", content: "interface WebWorkerInterface { }" }); + host.ensureFileOrFolder({ + path: "/home/src/projects/node_modules/@typescript/lib-webworker/index.d.ts", + content: "interface WebWorkerInterface { }", + }); host.runQueuedTimeoutCallbacks(); host.runQueuedTimeoutCallbacks(); host.deleteFile("/home/src/projects/node_modules/@typescript/lib-webworker/index.d.ts"); @@ -64,7 +73,10 @@ describe("unittests:: tsserver:: libraryResolution", () => { host.runQueuedTimeoutCallbacks(); host.deleteFile("/home/src/projects/project1/core.d.ts"); host.runQueuedTimeoutCallbacks(); - host.ensureFileOrFolder({ path: "/home/src/projects/node_modules/@typescript/lib-dom/index.d.ts", content: "interface DOMInterface { }" }); + host.ensureFileOrFolder({ + path: "/home/src/projects/node_modules/@typescript/lib-dom/index.d.ts", + content: "interface DOMInterface { }", + }); host.runQueuedTimeoutCallbacks(); host.runQueuedTimeoutCallbacks(); host.writeFile( @@ -94,7 +106,10 @@ describe("unittests:: tsserver:: libraryResolution", () => { host.runQueuedTimeoutCallbacks(); host.deleteFile("/home/src/projects/node_modules/@typescript/lib-webworker/index.d.ts"); host.runQueuedTimeoutCallbacks(); - host.ensureFileOrFolder({ path: "/home/src/projects/node_modules/@typescript/lib-webworker/index.d.ts", content: "interface WebWorkerInterface { }" }); + host.ensureFileOrFolder({ + path: "/home/src/projects/node_modules/@typescript/lib-webworker/index.d.ts", + content: "interface WebWorkerInterface { }", + }); host.runQueuedTimeoutCallbacks(); host.runQueuedTimeoutCallbacks(); baselineTsserverLogs("libraryResolution", "with config with redirection", session); diff --git a/src/testRunner/unittests/tsserver/maxNodeModuleJsDepth.ts b/src/testRunner/unittests/tsserver/maxNodeModuleJsDepth.ts index 2f4fe30e0d392..1e0c5a3a4b4f3 100644 --- a/src/testRunner/unittests/tsserver/maxNodeModuleJsDepth.ts +++ b/src/testRunner/unittests/tsserver/maxNodeModuleJsDepth.ts @@ -28,11 +28,19 @@ describe("unittests:: tsserver:: maxNodeModuleJsDepth for inferred projects", () const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) }); openFilesForSession([file1], session); - session.logger.log(`maxNodeModuleJsDepth: ${session.getProjectService().inferredProjects[0].getCompilationSettings().maxNodeModuleJsDepth}`); + session.logger.log( + `maxNodeModuleJsDepth: ${ + session.getProjectService().inferredProjects[0].getCompilationSettings().maxNodeModuleJsDepth + }`, + ); // Assert the option sticks setCompilerOptionsForInferredProjectsRequestForSession({ target: ts.ScriptTarget.ES2016 }, session); - session.logger.log(`maxNodeModuleJsDepth: ${session.getProjectService().inferredProjects[0].getCompilationSettings().maxNodeModuleJsDepth}`); + session.logger.log( + `maxNodeModuleJsDepth: ${ + session.getProjectService().inferredProjects[0].getCompilationSettings().maxNodeModuleJsDepth + }`, + ); baselineTsserverLogs("maxNodeModuleJsDepth", "should be set to 2 if the project has js root files", session); }); @@ -47,16 +55,35 @@ describe("unittests:: tsserver:: maxNodeModuleJsDepth for inferred projects", () }; const host = createServerHost([file1, file2, libFile]); - const session = createSession(host, { useSingleInferredProject: true, logger: createLoggerWithInMemoryLogs(host) }); + const session = createSession(host, { + useSingleInferredProject: true, + logger: createLoggerWithInMemoryLogs(host), + }); openFilesForSession([file1], session); - session.logger.log(`maxNodeModuleJsDepth: ${session.getProjectService().inferredProjects[0].getCompilationSettings().maxNodeModuleJsDepth}`); + session.logger.log( + `maxNodeModuleJsDepth: ${ + session.getProjectService().inferredProjects[0].getCompilationSettings().maxNodeModuleJsDepth + }`, + ); openFilesForSession([file2], session); - session.logger.log(`maxNodeModuleJsDepth: ${session.getProjectService().inferredProjects[0].getCompilationSettings().maxNodeModuleJsDepth}`); + session.logger.log( + `maxNodeModuleJsDepth: ${ + session.getProjectService().inferredProjects[0].getCompilationSettings().maxNodeModuleJsDepth + }`, + ); closeFilesForSession([file2], session); - session.logger.log(`maxNodeModuleJsDepth: ${session.getProjectService().inferredProjects[0].getCompilationSettings().maxNodeModuleJsDepth}`); - baselineTsserverLogs("maxNodeModuleJsDepth", "should return to normal state when all js root files are removed from project", session); + session.logger.log( + `maxNodeModuleJsDepth: ${ + session.getProjectService().inferredProjects[0].getCompilationSettings().maxNodeModuleJsDepth + }`, + ); + baselineTsserverLogs( + "maxNodeModuleJsDepth", + "should return to normal state when all js root files are removed from project", + session, + ); }); }); diff --git a/src/testRunner/unittests/tsserver/metadataInResponse.ts b/src/testRunner/unittests/tsserver/metadataInResponse.ts index 9bc2dc2c0af79..726f3ddefcd01 100644 --- a/src/testRunner/unittests/tsserver/metadataInResponse.ts +++ b/src/testRunner/unittests/tsserver/metadataInResponse.ts @@ -59,7 +59,11 @@ describe("unittests:: tsserver:: with metadataInResponse::", () => { command: ts.server.protocol.CommandTypes.Completions, arguments: completionRequestArgs, }); - baselineTsserverLogs("metadataInResponse", "can pass through metadata when the command returns array", session); + baselineTsserverLogs( + "metadataInResponse", + "can pass through metadata when the command returns array", + session, + ); }); it("can pass through metadata when the command returns object", () => { @@ -70,7 +74,11 @@ describe("unittests:: tsserver:: with metadataInResponse::", () => { command: ts.server.protocol.CommandTypes.CompletionInfo, arguments: completionRequestArgs, }); - baselineTsserverLogs("metadataInResponse", "can pass through metadata when the command returns object", session); + baselineTsserverLogs( + "metadataInResponse", + "can pass through metadata when the command returns object", + session, + ); }); it("returns undefined correctly", () => { diff --git a/src/testRunner/unittests/tsserver/moduleResolution.ts b/src/testRunner/unittests/tsserver/moduleResolution.ts index 8fd1665d5d0d4..585d07175475a 100644 --- a/src/testRunner/unittests/tsserver/moduleResolution.ts +++ b/src/testRunner/unittests/tsserver/moduleResolution.ts @@ -50,7 +50,10 @@ describe("unittests:: tsserver:: moduleResolution", () => { } `, }; - const host = createServerHost([configFile, fileA, fileB, packageFile, { ...libFile, path: "/a/lib/lib.es2016.full.d.ts" }]); + const host = createServerHost([configFile, fileA, fileB, packageFile, { + ...libFile, + path: "/a/lib/lib.es2016.full.d.ts", + }]); const session = createSession(host, { canUseEvents: true, logger: createLoggerWithInMemoryLogs(host) }); openFilesForSession([fileA], session); return { @@ -147,7 +150,11 @@ describe("unittests:: tsserver:: moduleResolution", () => { host.runQueuedTimeoutCallbacks(); // Actual update verifyErr(); - baselineTsserverLogs("moduleResolution", "package json file is edited when package json with type module exists", session); + baselineTsserverLogs( + "moduleResolution", + "package json file is edited when package json with type module exists", + session, + ); }); }); @@ -163,25 +170,49 @@ describe("unittests:: tsserver:: moduleResolution", () => { verifyErrors(); host.deleteFile("/home/src/projects/project/node_modules/foo/index.d.ts"); verifyErrors(); - host.writeFile("/home/src/projects/project/node_modules/@types/bar/index.d.ts", getFsContentsForNode10ResultDts("bar")); + host.writeFile( + "/home/src/projects/project/node_modules/@types/bar/index.d.ts", + getFsContentsForNode10ResultDts("bar"), + ); verifyErrors(); - host.writeFile("/home/src/projects/project/node_modules/foo/index.d.ts", getFsContentsForNode10ResultDts("foo")); + host.writeFile( + "/home/src/projects/project/node_modules/foo/index.d.ts", + getFsContentsForNode10ResultDts("foo"), + ); verifyErrors(); - host.writeFile("/home/src/projects/project/node_modules/@types/bar/package.json", getFsConentsForNode10ResultAtTypesPackageJson("bar", /*addTypesCondition*/ true)); + host.writeFile( + "/home/src/projects/project/node_modules/@types/bar/package.json", + getFsConentsForNode10ResultAtTypesPackageJson("bar", /*addTypesCondition*/ true), + ); verifyErrors(); - host.writeFile("/home/src/projects/project/node_modules/foo/package.json", getFsContentsForNode10ResultPackageJson("foo", /*addTypes*/ true, /*addTypesCondition*/ true)); + host.writeFile( + "/home/src/projects/project/node_modules/foo/package.json", + getFsContentsForNode10ResultPackageJson("foo", /*addTypes*/ true, /*addTypesCondition*/ true), + ); verifyErrors(); - host.writeFile("/home/src/projects/project/node_modules/@types/bar2/package.json", getFsConentsForNode10ResultAtTypesPackageJson("bar2", /*addTypesCondition*/ false)); + host.writeFile( + "/home/src/projects/project/node_modules/@types/bar2/package.json", + getFsConentsForNode10ResultAtTypesPackageJson("bar2", /*addTypesCondition*/ false), + ); verifyErrors(); - host.writeFile("/home/src/projects/project/node_modules/foo2/package.json", getFsContentsForNode10ResultPackageJson("foo2", /*addTypes*/ true, /*addTypesCondition*/ false)); + host.writeFile( + "/home/src/projects/project/node_modules/foo2/package.json", + getFsContentsForNode10ResultPackageJson("foo2", /*addTypes*/ true, /*addTypesCondition*/ false), + ); verifyErrors(); host.deleteFile("/home/src/projects/project/node_modules/@types/bar2/index.d.ts"); verifyErrors(); host.deleteFile("/home/src/projects/project/node_modules/foo2/index.d.ts"); verifyErrors(); - host.writeFile("/home/src/projects/project/node_modules/@types/bar2/index.d.ts", getFsContentsForNode10ResultDts("bar2")); + host.writeFile( + "/home/src/projects/project/node_modules/@types/bar2/index.d.ts", + getFsContentsForNode10ResultDts("bar2"), + ); verifyErrors(); - host.writeFile("/home/src/projects/project/node_modules/foo2/index.d.ts", getFsContentsForNode10ResultDts("foo2")); + host.writeFile( + "/home/src/projects/project/node_modules/foo2/index.d.ts", + getFsContentsForNode10ResultDts("foo2"), + ); verifyErrors(); baselineTsserverLogs("moduleResolution", "node10Result", session); diff --git a/src/testRunner/unittests/tsserver/moduleSpecifierCache.ts b/src/testRunner/unittests/tsserver/moduleSpecifierCache.ts index acc39d3981dd2..b80e6289bad2c 100644 --- a/src/testRunner/unittests/tsserver/moduleSpecifierCache.ts +++ b/src/testRunner/unittests/tsserver/moduleSpecifierCache.ts @@ -51,7 +51,10 @@ const mobxDts: File = { describe("unittests:: tsserver:: moduleSpecifierCache", () => { it("caches importability within a file", () => { const { session, moduleSpecifierCache } = setup(); - session.logger.info(`importability: ${moduleSpecifierCache.get(bTs.path as ts.Path, aTs.path as ts.Path, {}, {})?.isBlockedByPackageJsonDependencies}`); + session.logger.info( + `importability: ${moduleSpecifierCache.get(bTs.path as ts.Path, aTs.path as ts.Path, {}, {}) + ?.isBlockedByPackageJsonDependencies}`, + ); baselineTsserverLogs("moduleSpecifierCache", "caches importability within a file", session); }); @@ -59,7 +62,15 @@ describe("unittests:: tsserver:: moduleSpecifierCache", () => { const { session, moduleSpecifierCache, triggerCompletions } = setup(); // Completion at an import statement will calculate and cache module specifiers triggerCompletions({ file: cTs.path, line: 1, offset: cTs.content.length + 1 }); - session.logger.info(`mobxCache: ${JSON.stringify(moduleSpecifierCache.get(cTs.path as ts.Path, mobxDts.path as ts.Path, {}, {}), undefined, " ")}`); + session.logger.info( + `mobxCache: ${ + JSON.stringify( + moduleSpecifierCache.get(cTs.path as ts.Path, mobxDts.path as ts.Path, {}, {}), + undefined, + " ", + ) + }`, + ); baselineTsserverLogs("moduleSpecifierCache", "caches module specifiers within a file", session); }); @@ -70,14 +81,21 @@ describe("unittests:: tsserver:: moduleSpecifierCache", () => { host.writeFile("/node_modules/.staging/mobx-12345678/package.json", "{}"); host.runQueuedTimeoutCallbacks(); assert.equal(moduleSpecifierCache.count(), 0); - baselineTsserverLogs("moduleSpecifierCache", "invalidates module specifiers when changes happen in contained node_modules directories", session); + baselineTsserverLogs( + "moduleSpecifierCache", + "invalidates module specifiers when changes happen in contained node_modules directories", + session, + ); }); it("does not invalidate the cache when new files are added", () => { const { session, host, moduleSpecifierCache } = setup(); host.writeFile("/src/a2.ts", aTs.content); host.runQueuedTimeoutCallbacks(); - session.logger.info(`importability: ${moduleSpecifierCache.get(bTs.path as ts.Path, aTs.path as ts.Path, {}, {})?.isBlockedByPackageJsonDependencies}`); + session.logger.info( + `importability: ${moduleSpecifierCache.get(bTs.path as ts.Path, aTs.path as ts.Path, {}, {}) + ?.isBlockedByPackageJsonDependencies}`, + ); baselineTsserverLogs("moduleSpecifierCache", "does not invalidate the cache when new files are added", session); }); @@ -86,7 +104,11 @@ describe("unittests:: tsserver:: moduleSpecifierCache", () => { host.renameFile(bSymlink.path, "/src/b-link2.ts"); host.runQueuedTimeoutCallbacks(); session.logger.info(`moduleSpecifierCache count: ${moduleSpecifierCache.count()}`); - baselineTsserverLogs("moduleSpecifierCache", "invalidates the cache when symlinks are added or removed", session); + baselineTsserverLogs( + "moduleSpecifierCache", + "invalidates the cache when symlinks are added or removed", + session, + ); }); it("invalidates the cache when local package.json changes", () => { @@ -102,7 +124,11 @@ describe("unittests:: tsserver:: moduleSpecifierCache", () => { host.writeFile(tsconfig.path, `{ "compilerOptions": { "moduleResolution": "classic" }, "include": ["src"] }`); host.runQueuedTimeoutCallbacks(); session.logger.info(`moduleSpecifierCache count: ${moduleSpecifierCache.count()}`); - baselineTsserverLogs("moduleSpecifierCache", "invalidates the cache when module resolution settings change", session); + baselineTsserverLogs( + "moduleSpecifierCache", + "invalidates the cache when module resolution settings change", + session, + ); }); it("invalidates the cache when user preferences change", () => { @@ -132,13 +158,31 @@ describe("unittests:: tsserver:: moduleSpecifierCache", () => { baselineTsserverLogs("moduleSpecifierCache", "invalidates the cache when user preferences change", session); function getWithPreferences(preferences: ts.UserPreferences) { - session.logger.info(`moduleSpecifierCache for ${JSON.stringify(preferences)} (${bTs.path} -> ${aTs.path}) ${JSON.stringify(moduleSpecifierCache.get(bTs.path as ts.Path, aTs.path as ts.Path, preferences, {}), undefined, " ")}`); + session.logger.info( + `moduleSpecifierCache for ${JSON.stringify(preferences)} (${bTs.path} -> ${aTs.path}) ${ + JSON.stringify( + moduleSpecifierCache.get(bTs.path as ts.Path, aTs.path as ts.Path, preferences, {}), + undefined, + " ", + ) + }`, + ); } }); }); function setup() { - const host = createServerHost([aTs, bTs, cTs, bSymlink, ambientDeclaration, tsconfig, packageJson, mobxPackageJson, mobxDts]); + const host = createServerHost([ + aTs, + bTs, + cTs, + bSymlink, + ambientDeclaration, + tsconfig, + packageJson, + mobxPackageJson, + mobxDts, + ]); const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) }); openFilesForSession([aTs, bTs, cTs], session); const projectService = session.getProjectService(); @@ -156,7 +200,14 @@ function setup() { }); triggerCompletions({ file: bTs.path, line: 1, offset: 3 }); - return { host, project, projectService, session, moduleSpecifierCache: project.getModuleSpecifierCache(), triggerCompletions }; + return { + host, + project, + projectService, + session, + moduleSpecifierCache: project.getModuleSpecifierCache(), + triggerCompletions, + }; function triggerCompletions(requestLocation: ts.server.protocol.FileLocationRequestArgs) { session.executeCommandSeq({ diff --git a/src/testRunner/unittests/tsserver/openFile.ts b/src/testRunner/unittests/tsserver/openFile.ts index 110357c2b0327..b3b3f38d3826f 100644 --- a/src/testRunner/unittests/tsserver/openFile.ts +++ b/src/testRunner/unittests/tsserver/openFile.ts @@ -77,7 +77,12 @@ describe("unittests:: tsserver:: Open-file", () => { baselineTsserverLogs("openfile", subScenario, service); function verifyConfigFileName(file: File, projectRoot: string) { - const { configFileName } = service.openClientFile(file.path, /*fileContent*/ undefined, /*scriptKind*/ undefined, projectRoot); + const { configFileName } = service.openClientFile( + file.path, + /*fileContent*/ undefined, + /*scriptKind*/ undefined, + projectRoot, + ); service.logger.log(`file: ${file.path} configFile: ${configFileName}`); service.closeClientFile(file.path); } @@ -129,7 +134,12 @@ describe("unittests:: tsserver:: Open-file", () => { function verifyProject(aFileContent: string) { service.openClientFile(aFile.path, aFileContent, ts.ScriptKind.TS, projectFolder); - service.logger.log(`aFileContent: ${service.configuredProjects.get(configFile.path)!.getCurrentProgram()?.getSourceFile(aFile.path)!.text}`); + service.logger.log( + `aFileContent: ${ + service.configuredProjects.get(configFile.path)!.getCurrentProgram()?.getSourceFile(aFile.path)! + .text + }`, + ); } }); @@ -185,7 +195,11 @@ bar();`, }, }); verifyGetErrRequest({ session, files: [file] }); - baselineTsserverLogs("openfile", "when file makes edits to add/remove comment directives, they are handled correcrly", session); + baselineTsserverLogs( + "openfile", + "when file makes edits to add/remove comment directives, they are handled correcrly", + session, + ); }); describe("opening file and refreshing program", () => { @@ -269,7 +283,11 @@ bar();`, session.getProjectService().configuredProjects.get("/project/tsconfig.json")!.updateGraph(); host.appendFile("/project/b.ts", "export const x = 10;"); host.runQueuedTimeoutCallbacks(); - baselineTsserverLogs("openfile", "edits on file and then close does not refresh sourceFile if contents match", session); + baselineTsserverLogs( + "openfile", + "edits on file and then close does not refresh sourceFile if contents match", + session, + ); }); }); }); diff --git a/src/testRunner/unittests/tsserver/packageJsonInfo.ts b/src/testRunner/unittests/tsserver/packageJsonInfo.ts index 573e014a6f765..57cda4f68bb75 100644 --- a/src/testRunner/unittests/tsserver/packageJsonInfo.ts +++ b/src/testRunner/unittests/tsserver/packageJsonInfo.ts @@ -61,7 +61,11 @@ describe("unittests:: tsserver:: packageJsonInfo::", () => { packageJsonInfo = projectService.packageJsonCache.getInDirectory("/" as ts.Path)!; assert.isUndefined(packageJsonInfo.dependencies); - baselineTsserverLogs("packageJsonInfo", "detects new package.json files that are added, caches them, and watches them", session); + baselineTsserverLogs( + "packageJsonInfo", + "detects new package.json files that are added, caches them, and watches them", + session, + ); }); it("finds package.json on demand, watches for deletion, and removes them from cache", () => { @@ -74,7 +78,11 @@ describe("unittests:: tsserver:: packageJsonInfo::", () => { host.deleteFile(packageJson.path); session.testhost.baselineHost("delete packageJson"); assert.isUndefined(projectService.packageJsonCache.getInDirectory("/" as ts.Path)); - baselineTsserverLogs("packageJsonInfo", "finds package.json on demand, watches for deletion, and removes them from cache", session); + baselineTsserverLogs( + "packageJsonInfo", + "finds package.json on demand, watches for deletion, and removes them from cache", + session, + ); }); it("finds multiple package.json files when present", () => { @@ -90,7 +98,10 @@ describe("unittests:: tsserver:: packageJsonInfo::", () => { it("handles errors in json parsing of package.json", () => { const packageJsonContent = `{ "mod" }`; - const { session, projectService, host } = setup([tsConfig, { path: packageJson.path, content: packageJsonContent }]); + const { session, projectService, host } = setup([tsConfig, { + path: packageJson.path, + content: packageJsonContent, + }]); projectService.getPackageJsonsVisibleToFile("/src/whatever/blah.ts" as ts.Path); const packageJsonInfo = projectService.packageJsonCache.getInDirectory("/" as ts.Path)!; assert.isFalse(packageJsonInfo.parseable); @@ -109,7 +120,10 @@ describe("unittests:: tsserver:: packageJsonInfo::", () => { it("handles empty package.json", () => { const packageJsonContent = ""; - const { session, projectService, host } = setup([tsConfig, { path: packageJson.path, content: packageJsonContent }]); + const { session, projectService, host } = setup([tsConfig, { + path: packageJson.path, + content: packageJsonContent, + }]); projectService.getPackageJsonsVisibleToFile("/src/whatever/blah.ts" as ts.Path); const packageJsonInfo = projectService.packageJsonCache.getInDirectory("/" as ts.Path)!; assert.isFalse(packageJsonInfo.parseable); diff --git a/src/testRunner/unittests/tsserver/partialSemanticServer.ts b/src/testRunner/unittests/tsserver/partialSemanticServer.ts index cbe2c337ab335..1c9dd0c1f1150 100644 --- a/src/testRunner/unittests/tsserver/partialSemanticServer.ts +++ b/src/testRunner/unittests/tsserver/partialSemanticServer.ts @@ -117,7 +117,8 @@ import { something } from "something"; command: ts.server.protocol.CommandTypes.SyntacticDiagnosticsSync, arguments: { file: file1.path }, }; - const response = session.executeCommandSeq(request).response as ts.server.protocol.SyntacticDiagnosticsSyncResponse["body"]; + const response = session.executeCommandSeq(request) + .response as ts.server.protocol.SyntacticDiagnosticsSyncResponse["body"]; assert.isDefined(response); assert.equal(response!.length, 1); assert.equal((response![0] as ts.server.protocol.Diagnostic).text, expectedErrorMessage); @@ -174,7 +175,11 @@ function fooB() { }`, logger: createLoggerWithInMemoryLogs(host), }); openFilesForSession([file1], session); - baselineTsserverLogs("partialSemanticServer", "should not include referenced files from unopened files", session); + baselineTsserverLogs( + "partialSemanticServer", + "should not include referenced files from unopened files", + session, + ); }); it("should not crash when external module name resolution is reused", () => { @@ -187,7 +192,11 @@ function fooB() { }`, // Open file with non relative external module name openFilesForSession([file2], session); - baselineTsserverLogs("partialSemanticServer", "should not crash when external module name resolution is reused", session); + baselineTsserverLogs( + "partialSemanticServer", + "should not crash when external module name resolution is reused", + session, + ); }); it("should not create autoImportProvider or handle package jsons", () => { @@ -211,15 +220,30 @@ function fooB() { }`, path: "/index.ts", content: "", }; - const host = createServerHost([angularFormsDts, angularFormsPackageJson, tsconfig, packageJson, indexTs, libFile]); - const session = createSession(host, { serverMode: ts.LanguageServiceMode.PartialSemantic, useSingleInferredProject: true, logger: createLoggerWithInMemoryLogs(host) }); + const host = createServerHost([ + angularFormsDts, + angularFormsPackageJson, + tsconfig, + packageJson, + indexTs, + libFile, + ]); + const session = createSession(host, { + serverMode: ts.LanguageServiceMode.PartialSemantic, + useSingleInferredProject: true, + logger: createLoggerWithInMemoryLogs(host), + }); const service = session.getProjectService(); openFilesForSession([indexTs], session); const project = service.inferredProjects[0]; assert.isFalse(project.autoImportProviderHost); assert.isUndefined(project.getPackageJsonAutoImportProvider()); assert.deepEqual(project.getPackageJsonsForAutoImport(), ts.emptyArray); - baselineTsserverLogs("partialSemanticServer", "should not create autoImportProvider or handle package jsons", session); + baselineTsserverLogs( + "partialSemanticServer", + "should not create autoImportProvider or handle package jsons", + session, + ); }); it("should support go-to-definition on module specifiers", () => { diff --git a/src/testRunner/unittests/tsserver/plugins.ts b/src/testRunner/unittests/tsserver/plugins.ts index 503c0702d1633..da37ac6094a4c 100644 --- a/src/testRunner/unittests/tsserver/plugins.ts +++ b/src/testRunner/unittests/tsserver/plugins.ts @@ -69,7 +69,9 @@ describe("unittests:: tsserver:: plugins:: loading", () => { path: "/tsconfig.json", content: "{}", }; - const { session } = createHostWithPlugin([aTs, tsconfig, libFile], { globalPlugins: [...expectedToLoad, ...notToLoad] }); + const { session } = createHostWithPlugin([aTs, tsconfig, libFile], { + globalPlugins: [...expectedToLoad, ...notToLoad], + }); openFilesForSession([aTs], session); baselineTsserverLogs("plugins", "With global plugins", session); }); @@ -132,7 +134,11 @@ describe("unittests:: tsserver:: plugins:: loading", () => { }; const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) }); openFilesForSession([aTs], session); - session.logger.log(`ExternalFiles:: ${JSON.stringify(session.getProjectService().configuredProjects.get(tsconfig.path)!.getExternalFiles())}`); + session.logger.log( + `ExternalFiles:: ${ + JSON.stringify(session.getProjectService().configuredProjects.get(tsconfig.path)!.getExternalFiles()) + }`, + ); host.writeFile( tsconfig.path, @@ -143,7 +149,11 @@ describe("unittests:: tsserver:: plugins:: loading", () => { }), ); host.runQueuedTimeoutCallbacks(); - session.logger.log(`ExternalFiles:: ${JSON.stringify(session.getProjectService().configuredProjects.get(tsconfig.path)!.getExternalFiles())}`); + session.logger.log( + `ExternalFiles:: ${ + JSON.stringify(session.getProjectService().configuredProjects.get(tsconfig.path)!.getExternalFiles()) + }`, + ); baselineTsserverLogs("plugins", "gets external files with config file reload", session); }); diff --git a/src/testRunner/unittests/tsserver/pluginsAsync.ts b/src/testRunner/unittests/tsserver/pluginsAsync.ts index a14caeb845734..6275792e306dc 100644 --- a/src/testRunner/unittests/tsserver/pluginsAsync.ts +++ b/src/testRunner/unittests/tsserver/pluginsAsync.ts @@ -17,7 +17,11 @@ import { describe("unittests:: tsserver:: pluginsAsync:: async loaded plugins", () => { function setup(globalPlugins: string[]) { const host = createServerHost([libFile]); - const session = createSession(host, { canUseEvents: true, globalPlugins, logger: createLoggerWithInMemoryLogs(host) }); + const session = createSession(host, { + canUseEvents: true, + globalPlugins, + logger: createLoggerWithInMemoryLogs(host), + }); return { host, session }; } @@ -40,7 +44,9 @@ describe("unittests:: tsserver:: pluginsAsync:: async loaded plugins", () => { openFilesForSession([{ file: "^memfs:/foo.ts", content: "" }], session); const projectService = session.getProjectService(); - session.logger.log(`This should be false because 'executeCommand' should have already triggered plugin enablement asynchronously and there are no plugin enablements currently being processed`); + session.logger.log( + `This should be false because 'executeCommand' should have already triggered plugin enablement asynchronously and there are no plugin enablements currently being processed`, + ); session.logger.log(`hasNewPluginEnablementRequests:: ${projectService.hasNewPluginEnablementRequests()}`); session.logger.log(`Should be true because async imports have already been triggered in the background`); @@ -51,7 +57,9 @@ describe("unittests:: tsserver:: pluginsAsync:: async loaded plugins", () => { await projectService.waitForPendingPlugins(); - session.logger.log(`at this point all plugin modules should have been instantiated and all plugins should have been invoked`); + session.logger.log( + `at this point all plugin modules should have been instantiated and all plugins should have been invoked`, + ); session.logger.log(`pluginModuleInstantiated:: ${pluginModuleInstantiated}`); session.logger.log(`pluginInvoked:: ${pluginInvoked}`); @@ -89,7 +97,11 @@ describe("unittests:: tsserver:: pluginsAsync:: async loaded plugins", () => { // wait for load to complete await projectService.waitForPendingPlugins(); - baselineTsserverLogs("pluginsAsync", "plugins evaluation in correct order even if imports resolve out of order", session); + baselineTsserverLogs( + "pluginsAsync", + "plugins evaluation in correct order even if imports resolve out of order", + session, + ); }); it("sends projectsUpdatedInBackground event", async () => { @@ -140,7 +152,9 @@ describe("unittests:: tsserver:: pluginsAsync:: async loaded plugins", () => { host.runQueuedTimeoutCallbacks(); - session.logger.log(`External files before plugin after plugin is loaded: ${project.getExternalFiles().join(",")}`); + session.logger.log( + `External files before plugin after plugin is loaded: ${project.getExternalFiles().join(",")}`, + ); baselineTsserverLogs("pluginsAsync", "adds external files", session); }); diff --git a/src/testRunner/unittests/tsserver/projectErrors.ts b/src/testRunner/unittests/tsserver/projectErrors.ts index 80a82f97fa5a9..2c7e3629836a2 100644 --- a/src/testRunner/unittests/tsserver/projectErrors.ts +++ b/src/testRunner/unittests/tsserver/projectErrors.ts @@ -224,7 +224,11 @@ describe("unittests:: tsserver:: projectErrors:: are reported as appropriate", ( content: "class c { }", }; const host = createServerHost([libFile, fileInRoot, fileInProjectRoot]); - const session = createSession(host, { canUseEvents: true, logger: createLoggerWithInMemoryLogs(host), useInferredProjectPerProjectRoot: true }); + const session = createSession(host, { + canUseEvents: true, + logger: createLoggerWithInMemoryLogs(host), + useInferredProjectPerProjectRoot: true, + }); const untitledFile = "untitled:Untitled-1"; const refPathNotFound1 = "../../../../../../typings/@epic/Core.d.ts"; @@ -244,7 +248,13 @@ describe("unittests:: tsserver:: projectErrors:: are reported as appropriate", ( // Since this is not js project so no typings are queued verifyGetErrRequest({ session, files: [untitledFile] }); - baselineTsserverLogs("projectErrors", `when opening new file that doesnt exist on disk yet ${useProjectRoot ? "with projectRoot" : "without projectRoot"}`, session); + baselineTsserverLogs( + "projectErrors", + `when opening new file that doesnt exist on disk yet ${ + useProjectRoot ? "with projectRoot" : "without projectRoot" + }`, + session, + ); } it("has projectRoot", () => { @@ -320,14 +330,25 @@ describe("unittests:: tsserver:: projectErrors:: are reported as appropriate", ( }; const files = [libFile, app, serverUtilities, backendTest]; const host = createServerHost(files); - const session = createSession(host, { useInferredProjectPerProjectRoot: true, canUseEvents: true, logger: createLoggerWithInMemoryLogs(host) }); + const session = createSession(host, { + useInferredProjectPerProjectRoot: true, + canUseEvents: true, + logger: createLoggerWithInMemoryLogs(host), + }); openFilesForSession([{ file: app, projectRootPath: "/user/username/projects/myproject" }], session); openFilesForSession([{ file: backendTest, projectRootPath: "/user/username/projects/myproject" }], session); verifyGetErrRequest({ session, files: [backendTest.path, app.path] }); closeFilesForSession([backendTest], session); - openFilesForSession([{ file: serverUtilities.path, projectRootPath: "/user/username/projects/myproject" }], session); + openFilesForSession( + [{ file: serverUtilities.path, projectRootPath: "/user/username/projects/myproject" }], + session, + ); verifyGetErrRequest({ session, files: [serverUtilities.path, app.path] }); - baselineTsserverLogs("projectErrors", `reports errors correctly when file referenced by inferred project root, is opened right after closing the root file`, session); + baselineTsserverLogs( + "projectErrors", + `reports errors correctly when file referenced by inferred project root, is opened right after closing the root file`, + session, + ); }); it("Correct errors when resolution resolves to file that has same ambient module and is also module", () => { @@ -375,7 +396,11 @@ declare module '@custom/plugin' { }, }); verifyGetErrRequest({ session, files: [aFile] }); - baselineTsserverLogs("projectErrors", `correct errors when resolution resolves to file that has same ambient module and is also module`, session); + baselineTsserverLogs( + "projectErrors", + `correct errors when resolution resolves to file that has same ambient module and is also module`, + session, + ); }); describe("when semantic error returns includes global error", () => { @@ -418,7 +443,11 @@ describe("unittests:: tsserver:: Project Errors for Configure file diagnostics e const host = createServerHost([file, libFile, configFile]); const session = createSession(host, { canUseEvents: true, logger: createLoggerWithInMemoryLogs(host) }); openFilesForSession([file], session); - baselineTsserverLogs("projectErrors", "configFileDiagnostic events are generated when the config file has errors", session); + baselineTsserverLogs( + "projectErrors", + "configFileDiagnostic events are generated when the config file has errors", + session, + ); }); it("are generated when the config file doesn't have errors", () => { @@ -435,7 +464,11 @@ describe("unittests:: tsserver:: Project Errors for Configure file diagnostics e const host = createServerHost([file, libFile, configFile]); const session = createSession(host, { canUseEvents: true, logger: createLoggerWithInMemoryLogs(host) }); openFilesForSession([file], session); - baselineTsserverLogs("projectErrors", "configFileDiagnostic events are generated when the config file doesnt have errors", session); + baselineTsserverLogs( + "projectErrors", + "configFileDiagnostic events are generated when the config file doesnt have errors", + session, + ); }); it("are generated when the config file changes", () => { @@ -467,7 +500,11 @@ describe("unittests:: tsserver:: Project Errors for Configure file diagnostics e }`; host.writeFile(configFile.path, configFile.content); host.runQueuedTimeoutCallbacks(); - baselineTsserverLogs("projectErrors", "configFileDiagnostic events are generated when the config file changes", session); + baselineTsserverLogs( + "projectErrors", + "configFileDiagnostic events are generated when the config file changes", + session, + ); }); it("are not generated when the config file does not include file opened and config file has errors", () => { @@ -499,7 +536,11 @@ describe("unittests:: tsserver:: Project Errors for Configure file diagnostics e openFilesForSession([file], session); // We generate only if project is created when opening file from the project openFilesForSession([file3], session); - baselineTsserverLogs("projectErrors", "configFileDiagnostic events are not generated when the config file does not include file opened and config file has errors", session); + baselineTsserverLogs( + "projectErrors", + "configFileDiagnostic events are not generated when the config file does not include file opened and config file has errors", + session, + ); }); it("are not generated when the config file has errors but suppressDiagnosticEvents is true", () => { @@ -517,9 +558,17 @@ describe("unittests:: tsserver:: Project Errors for Configure file diagnostics e }`, }; const host = createServerHost([file, libFile, configFile]); - const session = createSession(host, { canUseEvents: true, suppressDiagnosticEvents: true, logger: createLoggerWithInMemoryLogs(host) }); + const session = createSession(host, { + canUseEvents: true, + suppressDiagnosticEvents: true, + logger: createLoggerWithInMemoryLogs(host), + }); openFilesForSession([file], session); - baselineTsserverLogs("projectErrors", "configFileDiagnostic events are not generated when the config file has errors but suppressDiagnosticEvents is true", session); + baselineTsserverLogs( + "projectErrors", + "configFileDiagnostic events are not generated when the config file has errors but suppressDiagnosticEvents is true", + session, + ); }); it("are not generated when the config file does not include file opened and doesnt contain any errors", () => { @@ -548,7 +597,11 @@ describe("unittests:: tsserver:: Project Errors for Configure file diagnostics e openFilesForSession([file], session); // We generate only if project is created when opening file from the project openFilesForSession([file3], session); - baselineTsserverLogs("projectErrors", "configFileDiagnostic events are not generated when the config file does not include file opened and doesnt contain any errors", session); + baselineTsserverLogs( + "projectErrors", + "configFileDiagnostic events are not generated when the config file does not include file opened and doesnt contain any errors", + session, + ); }); it("contains the project reference errors", () => { @@ -568,7 +621,11 @@ describe("unittests:: tsserver:: Project Errors for Configure file diagnostics e const host = createServerHost([file, libFile, configFile]); const session = createSession(host, { canUseEvents: true, logger: createLoggerWithInMemoryLogs(host) }); openFilesForSession([file], session); - baselineTsserverLogs("projectErrors", "configFileDiagnostic events contains the project reference errors", session); + baselineTsserverLogs( + "projectErrors", + "configFileDiagnostic events contains the project reference errors", + session, + ); }); }); @@ -645,7 +702,8 @@ describe("unittests:: tsserver:: projectErrors:: reports Options Diagnostic loca "mapRoot": "./" } }`; - const configFileContentWithComment = configFileContentBeforeComment + configFileContentComment + configFileContentAfterComment; + const configFileContentWithComment = configFileContentBeforeComment + configFileContentComment + + configFileContentAfterComment; const configFileContentWithoutCommentLine = configFileContentBeforeComment + configFileContentAfterComment; const configFile = { @@ -674,7 +732,8 @@ describe("unittests:: tsserver:: projectErrors:: reports Options Diagnostic loca describe("unittests:: tsserver:: projectErrors:: with config file change", () => { it("Updates diagnostics when '--noUnusedLabels' changes", () => { const aTs: File = { path: "/a.ts", content: "label: while (1) {}" }; - const options = (allowUnusedLabels: boolean) => `{ "compilerOptions": { "allowUnusedLabels": ${allowUnusedLabels} } }`; + const options = (allowUnusedLabels: boolean) => + `{ "compilerOptions": { "allowUnusedLabels": ${allowUnusedLabels} } }`; const tsconfig: File = { path: "/tsconfig.json", content: options(/*allowUnusedLabels*/ true) }; const host = createServerHost([aTs, tsconfig]); @@ -726,7 +785,11 @@ console.log(blabla);`, include: ["./src/*.ts", "./src/*.json"], }); verifyGetErrRequest({ session, files: [test] }); - baselineTsserverLogs("projectErrors", `should not report incorrect error when json is root file found by tsconfig`, session); + baselineTsserverLogs( + "projectErrors", + `should not report incorrect error when json is root file found by tsconfig`, + session, + ); }); it("should report error when json is not root file found by tsconfig", () => { @@ -734,7 +797,11 @@ console.log(blabla);`, include: ["./src/*.ts"], }); verifyGetErrRequest({ session, files: [test] }); - baselineTsserverLogs("projectErrors", `should report error when json is not root file found by tsconfig`, session); + baselineTsserverLogs( + "projectErrors", + `should report error when json is not root file found by tsconfig`, + session, + ); }); }); @@ -772,15 +839,29 @@ describe("unittests:: tsserver:: projectErrors:: with npm install when", () => { verifyWhileNpmInstall(); filesAndFoldersToAdd = [ - { path: `/user/username/projects/myproject/node_modules/.staging/@angular/platform-browser-dynamic-5efaaa1a` }, - { path: `/user/username/projects/myproject/node_modules/.staging/@angular/cli-c1e44b05/models/analytics.d.ts`, content: `export const x = 10;` }, - { path: `/user/username/projects/myproject/node_modules/.staging/@angular/core-0963aebf/index.d.ts`, content: `export const y = 10;` }, + { + path: + `/user/username/projects/myproject/node_modules/.staging/@angular/platform-browser-dynamic-5efaaa1a`, + }, + { + path: + `/user/username/projects/myproject/node_modules/.staging/@angular/cli-c1e44b05/models/analytics.d.ts`, + content: `export const x = 10;`, + }, + { + path: `/user/username/projects/myproject/node_modules/.staging/@angular/core-0963aebf/index.d.ts`, + content: `export const y = 10;`, + }, ]; // Since we added/removed in .staging no timeout verifyWhileNpmInstall(); filesAndFoldersToAdd = []; - host.ensureFileOrFolder(moduleFile, /*ignoreWatchInvokedWithTriggerAsFileCreate*/ true, /*ignoreParentWatch*/ true); + host.ensureFileOrFolder( + moduleFile, + /*ignoreWatchInvokedWithTriggerAsFileCreate*/ true, + /*ignoreParentWatch*/ true, + ); // Since we added/removed in .staging no timeout verifyWhileNpmInstall(); @@ -791,7 +872,11 @@ describe("unittests:: tsserver:: projectErrors:: with npm install when", () => { // Additional watch for watching script infos from node_modules verifyWhileNpmInstall(); - baselineTsserverLogs("projectErrors", `npm install when timeout occurs ${timeoutDuringPartialInstallation ? "inbetween" : "after"} installation`, session); + baselineTsserverLogs( + "projectErrors", + `npm install when timeout occurs ${timeoutDuringPartialInstallation ? "inbetween" : "after"} installation`, + session, + ); function verifyWhileNpmInstall() { filesAndFoldersToAdd.forEach(f => host.ensureFileOrFolder(f)); @@ -802,7 +887,11 @@ describe("unittests:: tsserver:: projectErrors:: with npm install when", () => { else { session.testhost.logTimeoutQueueLength(); } - verifyGetErrRequest({ session, files: [main], existingTimeouts: !npmInstallComplete && !timeoutDuringPartialInstallation }); + verifyGetErrRequest({ + session, + files: [main], + existingTimeouts: !npmInstallComplete && !timeoutDuringPartialInstallation, + }); } } diff --git a/src/testRunner/unittests/tsserver/projectReferenceCompileOnSave.ts b/src/testRunner/unittests/tsserver/projectReferenceCompileOnSave.ts index 121a59a925243..49a92747aa780 100644 --- a/src/testRunner/unittests/tsserver/projectReferenceCompileOnSave.ts +++ b/src/testRunner/unittests/tsserver/projectReferenceCompileOnSave.ts @@ -76,7 +76,11 @@ fn2(); command: ts.server.protocol.CommandTypes.EmitOutput, arguments: { file: usageTs.path }, }); - baselineTsserverLogs("projectReferenceCompileOnSave", "when dependency project is not open and save on usage", session); + baselineTsserverLogs( + "projectReferenceCompileOnSave", + "when dependency project is not open and save on usage", + session, + ); }); it("with initial file open, with specifying project file", () => { const host = createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]); @@ -100,7 +104,11 @@ fn2(); command: ts.server.protocol.CommandTypes.EmitOutput, arguments: { file: usageTs.path, projectFileName: usageConfig.path }, }); - baselineTsserverLogs("projectReferenceCompileOnSave", "when dependency project is not open and save on usage with project", session); + baselineTsserverLogs( + "projectReferenceCompileOnSave", + "when dependency project is not open and save on usage with project", + session, + ); }); it("with local change to dependency, without specifying project file", () => { const host = createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]); @@ -130,7 +138,11 @@ fn2(); command: ts.server.protocol.CommandTypes.EmitOutput, arguments: { file: usageTs.path }, }); - baselineTsserverLogs("projectReferenceCompileOnSave", "when dependency project is not open and save on usage and local change to dependency", session); + baselineTsserverLogs( + "projectReferenceCompileOnSave", + "when dependency project is not open and save on usage and local change to dependency", + session, + ); }); it("with local change to dependency, with specifying project file", () => { const host = createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]); @@ -160,7 +172,11 @@ fn2(); command: ts.server.protocol.CommandTypes.EmitOutput, arguments: { file: usageTs.path, projectFileName: usageConfig.path }, }); - baselineTsserverLogs("projectReferenceCompileOnSave", "when dependency project is not open and save on usage with project and local change to dependency", session); + baselineTsserverLogs( + "projectReferenceCompileOnSave", + "when dependency project is not open and save on usage with project and local change to dependency", + session, + ); }); it("with local change to usage, without specifying project file", () => { const host = createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]); @@ -201,7 +217,11 @@ fn2(); command: ts.server.protocol.CommandTypes.EmitOutput, arguments: { file: usageTs.path }, }); - baselineTsserverLogs("projectReferenceCompileOnSave", "when dependency project is not open and save on usage and local change to usage", session); + baselineTsserverLogs( + "projectReferenceCompileOnSave", + "when dependency project is not open and save on usage and local change to usage", + session, + ); }); it("with local change to usage, with specifying project file", () => { const host = createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]); @@ -242,7 +262,11 @@ fn2(); command: ts.server.protocol.CommandTypes.EmitOutput, arguments: { file: usageTs.path, projectFileName: usageConfig.path }, }); - baselineTsserverLogs("projectReferenceCompileOnSave", "when dependency project is not open and save on usage with project and local change to usage", session); + baselineTsserverLogs( + "projectReferenceCompileOnSave", + "when dependency project is not open and save on usage with project and local change to usage", + session, + ); }); it("with change to dependency, without specifying project file", () => { const host = createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]); @@ -272,7 +296,11 @@ fn2(); command: ts.server.protocol.CommandTypes.EmitOutput, arguments: { file: usageTs.path }, }); - baselineTsserverLogs("projectReferenceCompileOnSave", "when dependency project is not open and save on usage and change to depenedency", session); + baselineTsserverLogs( + "projectReferenceCompileOnSave", + "when dependency project is not open and save on usage and change to depenedency", + session, + ); }); it("with change to dependency, with specifying project file", () => { const host = createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]); @@ -302,7 +330,11 @@ fn2(); command: ts.server.protocol.CommandTypes.EmitOutput, arguments: { file: usageTs.path, projectFileName: usageConfig.path }, }); - baselineTsserverLogs("projectReferenceCompileOnSave", "when dependency project is not open and save on usage with project and change to depenedency", session); + baselineTsserverLogs( + "projectReferenceCompileOnSave", + "when dependency project is not open and save on usage with project and change to depenedency", + session, + ); }); it("with change to usage, without specifying project file", () => { const host = createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]); @@ -343,7 +375,11 @@ fn2(); command: ts.server.protocol.CommandTypes.EmitOutput, arguments: { file: usageTs.path }, }); - baselineTsserverLogs("projectReferenceCompileOnSave", "when dependency project is not open and save on usage and change to usage", session); + baselineTsserverLogs( + "projectReferenceCompileOnSave", + "when dependency project is not open and save on usage and change to usage", + session, + ); }); it("with change to usage, with specifying project file", () => { const host = createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]); @@ -384,7 +420,11 @@ fn2(); command: ts.server.protocol.CommandTypes.EmitOutput, arguments: { file: usageTs.path, projectFileName: usageConfig.path }, }); - baselineTsserverLogs("projectReferenceCompileOnSave", "when dependency project is not open and save on usage with project and change to usage", session); + baselineTsserverLogs( + "projectReferenceCompileOnSave", + "when dependency project is not open and save on usage with project and change to usage", + session, + ); }); }); @@ -411,7 +451,11 @@ fn2(); command: ts.server.protocol.CommandTypes.EmitOutput, arguments: { file: dependencyTs.path }, }); - baselineTsserverLogs("projectReferenceCompileOnSave", "when dependency project is not open and save on dependency", session); + baselineTsserverLogs( + "projectReferenceCompileOnSave", + "when dependency project is not open and save on dependency", + session, + ); }); it("with initial file open, with specifying project file", () => { const host = createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]); @@ -435,7 +479,11 @@ fn2(); command: ts.server.protocol.CommandTypes.EmitOutput, arguments: { file: dependencyTs.path, projectFileName: usageConfig.path }, }); - baselineTsserverLogs("projectReferenceCompileOnSave", "when dependency project is not open and save on dependency with project", session); + baselineTsserverLogs( + "projectReferenceCompileOnSave", + "when dependency project is not open and save on dependency with project", + session, + ); }); it("with local change to dependency, without specifying project file", () => { const host = createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]); @@ -465,7 +513,11 @@ fn2(); command: ts.server.protocol.CommandTypes.EmitOutput, arguments: { file: dependencyTs.path }, }); - baselineTsserverLogs("projectReferenceCompileOnSave", "when dependency project is not open and save on dependency and local change to dependency", session); + baselineTsserverLogs( + "projectReferenceCompileOnSave", + "when dependency project is not open and save on dependency and local change to dependency", + session, + ); }); it("with local change to dependency, with specifying project file", () => { const host = createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]); @@ -495,7 +547,11 @@ fn2(); command: ts.server.protocol.CommandTypes.EmitOutput, arguments: { file: dependencyTs.path, projectFileName: usageConfig.path }, }); - baselineTsserverLogs("projectReferenceCompileOnSave", "when dependency project is not open and save on dependency with project and local change to dependency", session); + baselineTsserverLogs( + "projectReferenceCompileOnSave", + "when dependency project is not open and save on dependency with project and local change to dependency", + session, + ); }); it("with local change to usage, without specifying project file", () => { const host = createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]); @@ -536,7 +592,11 @@ fn2(); command: ts.server.protocol.CommandTypes.EmitOutput, arguments: { file: dependencyTs.path }, }); - baselineTsserverLogs("projectReferenceCompileOnSave", "when dependency project is not open and save on dependency and local change to usage", session); + baselineTsserverLogs( + "projectReferenceCompileOnSave", + "when dependency project is not open and save on dependency and local change to usage", + session, + ); }); it("with local change to usage, with specifying project file", () => { const host = createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]); @@ -577,7 +637,11 @@ fn2(); command: ts.server.protocol.CommandTypes.EmitOutput, arguments: { file: dependencyTs.path, projectFileName: usageConfig.path }, }); - baselineTsserverLogs("projectReferenceCompileOnSave", "when dependency project is not open and save on dependency with project and local change to usage", session); + baselineTsserverLogs( + "projectReferenceCompileOnSave", + "when dependency project is not open and save on dependency with project and local change to usage", + session, + ); }); it("with change to dependency, without specifying project file", () => { const host = createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]); @@ -607,7 +671,11 @@ fn2(); command: ts.server.protocol.CommandTypes.EmitOutput, arguments: { file: dependencyTs.path }, }); - baselineTsserverLogs("projectReferenceCompileOnSave", "when dependency project is not open and save on dependency and change to dependency", session); + baselineTsserverLogs( + "projectReferenceCompileOnSave", + "when dependency project is not open and save on dependency and change to dependency", + session, + ); }); it("with change to dependency, with specifying project file", () => { const host = createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]); @@ -637,7 +705,11 @@ fn2(); command: ts.server.protocol.CommandTypes.EmitOutput, arguments: { file: dependencyTs.path, projectFileName: usageConfig.path }, }); - baselineTsserverLogs("projectReferenceCompileOnSave", "when dependency project is not open and save on dependency with project and change to dependency", session); + baselineTsserverLogs( + "projectReferenceCompileOnSave", + "when dependency project is not open and save on dependency with project and change to dependency", + session, + ); }); it("with change to usage, without specifying project file", () => { const host = createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]); @@ -678,7 +750,11 @@ fn2(); command: ts.server.protocol.CommandTypes.EmitOutput, arguments: { file: dependencyTs.path }, }); - baselineTsserverLogs("projectReferenceCompileOnSave", "when dependency project is not open and save on dependency and change to usage", session); + baselineTsserverLogs( + "projectReferenceCompileOnSave", + "when dependency project is not open and save on dependency and change to usage", + session, + ); }); it("with change to usage, with specifying project file", () => { const host = createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]); @@ -719,7 +795,11 @@ fn2(); command: ts.server.protocol.CommandTypes.EmitOutput, arguments: { file: dependencyTs.path, projectFileName: usageConfig.path }, }); - baselineTsserverLogs("projectReferenceCompileOnSave", "when dependency project is not open and save on dependency with project and change to usage", session); + baselineTsserverLogs( + "projectReferenceCompileOnSave", + "when dependency project is not open and save on dependency with project and change to usage", + session, + ); }); }); }); @@ -813,7 +893,11 @@ fn2(); command: ts.server.protocol.CommandTypes.EmitOutput, arguments: { file: usageTs.path }, }); - baselineTsserverLogs("projectReferenceCompileOnSave", "save on usage and local change to dependency", session); + baselineTsserverLogs( + "projectReferenceCompileOnSave", + "save on usage and local change to dependency", + session, + ); }); it("with local change to dependency, with specifying project file", () => { const host = createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]); @@ -854,7 +938,11 @@ fn2(); command: ts.server.protocol.CommandTypes.EmitOutput, arguments: { file: usageTs.path, projectFileName: usageConfig.path }, }); - baselineTsserverLogs("projectReferenceCompileOnSave", "save on usage and local change to dependency with file", session); + baselineTsserverLogs( + "projectReferenceCompileOnSave", + "save on usage and local change to dependency with file", + session, + ); }); it("with local change to usage, without specifying project file", () => { const host = createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]); @@ -895,7 +983,11 @@ fn2(); command: ts.server.protocol.CommandTypes.EmitOutput, arguments: { file: usageTs.path }, }); - baselineTsserverLogs("projectReferenceCompileOnSave", "save on usage and local change to usage", session); + baselineTsserverLogs( + "projectReferenceCompileOnSave", + "save on usage and local change to usage", + session, + ); }); it("with local change to usage, with specifying project file", () => { const host = createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]); @@ -936,7 +1028,11 @@ fn2(); command: ts.server.protocol.CommandTypes.EmitOutput, arguments: { file: usageTs.path, projectFileName: usageConfig.path }, }); - baselineTsserverLogs("projectReferenceCompileOnSave", "save on usage and local change to usage with project", session); + baselineTsserverLogs( + "projectReferenceCompileOnSave", + "save on usage and local change to usage with project", + session, + ); }); it("with change to dependency, without specifying project file", () => { const host = createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]); @@ -977,7 +1073,11 @@ fn2(); command: ts.server.protocol.CommandTypes.EmitOutput, arguments: { file: usageTs.path }, }); - baselineTsserverLogs("projectReferenceCompileOnSave", "save on usage and change to dependency", session); + baselineTsserverLogs( + "projectReferenceCompileOnSave", + "save on usage and change to dependency", + session, + ); }); it("with change to dependency, with specifying project file", () => { const host = createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]); @@ -1018,7 +1118,11 @@ fn2(); command: ts.server.protocol.CommandTypes.EmitOutput, arguments: { file: usageTs.path, projectFileName: usageConfig.path }, }); - baselineTsserverLogs("projectReferenceCompileOnSave", "save on usage with project and change to dependency", session); + baselineTsserverLogs( + "projectReferenceCompileOnSave", + "save on usage with project and change to dependency", + session, + ); }); it("with change to usage, without specifying project file", () => { const host = createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]); @@ -1099,7 +1203,11 @@ fn2(); command: ts.server.protocol.CommandTypes.EmitOutput, arguments: { file: usageTs.path, projectFileName: usageConfig.path }, }); - baselineTsserverLogs("projectReferenceCompileOnSave", "save on usage with project and change to usage", session); + baselineTsserverLogs( + "projectReferenceCompileOnSave", + "save on usage with project and change to usage", + session, + ); }); }); @@ -1167,7 +1275,11 @@ fn2(); command: ts.server.protocol.CommandTypes.EmitOutput, arguments: { file: dependencyTs.path, projectFileName: usageConfig.path }, }); - baselineTsserverLogs("projectReferenceCompileOnSave", "save on dependency with usage project and local change to dependency", session); + baselineTsserverLogs( + "projectReferenceCompileOnSave", + "save on dependency with usage project and local change to dependency", + session, + ); }); it("with local change to usage, with specifying project file", () => { const host = createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]); @@ -1208,7 +1320,11 @@ fn2(); command: ts.server.protocol.CommandTypes.EmitOutput, arguments: { file: dependencyTs.path, projectFileName: usageConfig.path }, }); - baselineTsserverLogs("projectReferenceCompileOnSave", "save on dependency with usage project and local change to usage", session); + baselineTsserverLogs( + "projectReferenceCompileOnSave", + "save on dependency with usage project and local change to usage", + session, + ); }); it("with change to dependency, with specifying project file", () => { const host = createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]); @@ -1249,7 +1365,11 @@ fn2(); command: ts.server.protocol.CommandTypes.EmitOutput, arguments: { file: dependencyTs.path, projectFileName: usageConfig.path }, }); - baselineTsserverLogs("projectReferenceCompileOnSave", "save on dependency with usage project and change to dependency", session); + baselineTsserverLogs( + "projectReferenceCompileOnSave", + "save on dependency with usage project and change to dependency", + session, + ); }); it("with change to usage, with specifying project file", () => { const host = createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]); @@ -1290,7 +1410,11 @@ fn2(); command: ts.server.protocol.CommandTypes.EmitOutput, arguments: { file: dependencyTs.path, projectFileName: usageConfig.path }, }); - baselineTsserverLogs("projectReferenceCompileOnSave", "save on dependency with usage project and change to usage", session); + baselineTsserverLogs( + "projectReferenceCompileOnSave", + "save on dependency with usage project and change to usage", + session, + ); }); }); @@ -1382,7 +1506,11 @@ fn2(); command: ts.server.protocol.CommandTypes.EmitOutput, arguments: { file: dependencyTs.path }, }); - baselineTsserverLogs("projectReferenceCompileOnSave", "save on dependency and local change to dependency", session); + baselineTsserverLogs( + "projectReferenceCompileOnSave", + "save on dependency and local change to dependency", + session, + ); }); it("with local change to dependency, with specifying project file", () => { const host = createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]); @@ -1423,7 +1551,11 @@ fn2(); command: ts.server.protocol.CommandTypes.EmitOutput, arguments: { file: dependencyTs.path, projectFileName: dependencyConfig.path }, }); - baselineTsserverLogs("projectReferenceCompileOnSave", "save on dependency with project and local change to dependency", session); + baselineTsserverLogs( + "projectReferenceCompileOnSave", + "save on dependency with project and local change to dependency", + session, + ); }); it("with local change to usage, without specifying project file", () => { const host = createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]); @@ -1464,7 +1596,11 @@ fn2(); command: ts.server.protocol.CommandTypes.EmitOutput, arguments: { file: dependencyTs.path }, }); - baselineTsserverLogs("projectReferenceCompileOnSave", "save on dependency and local change to usage", session); + baselineTsserverLogs( + "projectReferenceCompileOnSave", + "save on dependency and local change to usage", + session, + ); }); it("with local change to usage, with specifying project file", () => { const host = createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]); @@ -1505,7 +1641,11 @@ fn2(); command: ts.server.protocol.CommandTypes.EmitOutput, arguments: { file: dependencyTs.path, projectFileName: dependencyConfig.path }, }); - baselineTsserverLogs("projectReferenceCompileOnSave", "save on dependency with project and local change to usage", session); + baselineTsserverLogs( + "projectReferenceCompileOnSave", + "save on dependency with project and local change to usage", + session, + ); }); it("with change to dependency, without specifying project file", () => { const host = createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]); @@ -1546,7 +1686,11 @@ fn2(); command: ts.server.protocol.CommandTypes.EmitOutput, arguments: { file: dependencyTs.path }, }); - baselineTsserverLogs("projectReferenceCompileOnSave", "save on dependency and change to dependency", session); + baselineTsserverLogs( + "projectReferenceCompileOnSave", + "save on dependency and change to dependency", + session, + ); }); it("with change to dependency, with specifying project file", () => { const host = createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]); @@ -1587,7 +1731,11 @@ fn2(); command: ts.server.protocol.CommandTypes.EmitOutput, arguments: { file: dependencyTs.path, projectFileName: dependencyConfig.path }, }); - baselineTsserverLogs("projectReferenceCompileOnSave", "save on dependency with project and change to dependency", session); + baselineTsserverLogs( + "projectReferenceCompileOnSave", + "save on dependency with project and change to dependency", + session, + ); }); it("with change to usage, without specifying project file", () => { const host = createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]); @@ -1628,7 +1776,11 @@ fn2(); command: ts.server.protocol.CommandTypes.EmitOutput, arguments: { file: dependencyTs.path }, }); - baselineTsserverLogs("projectReferenceCompileOnSave", "save on dependency and change to usage", session); + baselineTsserverLogs( + "projectReferenceCompileOnSave", + "save on dependency and change to usage", + session, + ); }); it("with change to usage, with specifying project file", () => { const host = createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]); @@ -1669,7 +1821,11 @@ fn2(); command: ts.server.protocol.CommandTypes.EmitOutput, arguments: { file: dependencyTs.path, projectFileName: dependencyConfig.path }, }); - baselineTsserverLogs("projectReferenceCompileOnSave", "save on dependency with project and change to usage", session); + baselineTsserverLogs( + "projectReferenceCompileOnSave", + "save on dependency with project and change to usage", + session, + ); }); }); }); @@ -1731,7 +1887,9 @@ describe("unittests:: tsserver:: with project references and compile on save wit } }`, }; - const host = createServerHost([libFile, tsbaseJson, buttonConfig, buttonSource, siblingConfig, siblingSource], { useCaseSensitiveFileNames: true }); + const host = createServerHost([libFile, tsbaseJson, buttonConfig, buttonSource, siblingConfig, siblingSource], { + useCaseSensitiveFileNames: true, + }); // ts build should succeed ensureErrorFreeBuild(host, [siblingConfig.path]); @@ -1746,6 +1904,10 @@ describe("unittests:: tsserver:: with project references and compile on save wit projectFileName: siblingConfig.path, }, }); - baselineTsserverLogs("projectReferenceCompileOnSave", "compile on save emits same output as project build with external project", session); + baselineTsserverLogs( + "projectReferenceCompileOnSave", + "compile on save emits same output as project build with external project", + session, + ); }); }); diff --git a/src/testRunner/unittests/tsserver/projectReferenceErrors.ts b/src/testRunner/unittests/tsserver/projectReferenceErrors.ts index 088eaeae560cd..d17b3df0796ad 100644 --- a/src/testRunner/unittests/tsserver/projectReferenceErrors.ts +++ b/src/testRunner/unittests/tsserver/projectReferenceErrors.ts @@ -10,7 +10,13 @@ describe("unittests:: tsserver:: with project references and error reporting", ( const dependecyLocation = `/user/username/projects/myproject/dependency`; const usageLocation = `/user/username/projects/myproject/usage`; - function verifyUsageAndDependency(scenario: string, dependencyTs: File, dependencyConfig: File, usageTs: File, usageConfig: File) { + function verifyUsageAndDependency( + scenario: string, + dependencyTs: File, + dependencyConfig: File, + usageTs: File, + usageConfig: File, + ) { function usageProjectDiagnostics(): GetErrForProjectDiagnostics { return { project: usageTs, files: [usageTs, dependencyTs] }; } diff --git a/src/testRunner/unittests/tsserver/projectReferences.ts b/src/testRunner/unittests/tsserver/projectReferences.ts index 00b764b72f10a..15558f1b498a2 100644 --- a/src/testRunner/unittests/tsserver/projectReferences.ts +++ b/src/testRunner/unittests/tsserver/projectReferences.ts @@ -188,7 +188,13 @@ function foo() { command: ts.server.protocol.CommandTypes.References, arguments: protocolFileLocationFromSubstring(keyboardTs, searchStr), }); - baselineTsserverLogs("projectReferences", `root file is file from referenced project${disableSourceOfProjectReferenceRedirect ? " and using declaration maps" : ""}`, session); + baselineTsserverLogs( + "projectReferences", + `root file is file from referenced project${ + disableSourceOfProjectReferenceRedirect ? " and using declaration maps" : "" + }`, + session, + ); } it(`when using declaration file maps to navigate between projects`, () => { @@ -267,7 +273,11 @@ function foo() { service.testhost.baselineHost("a2Ts modified"); assert.isTrue(projectA.dirty); projectA.updateGraph(); - baselineTsserverLogs("projectReferences", "reusing d.ts files from composite and non composite projects", service); + baselineTsserverLogs( + "projectReferences", + "reusing d.ts files from composite and non composite projects", + service, + ); }); describe("when references are monorepo like with symlinks", () => { @@ -300,13 +310,18 @@ function foo() { }); } - function verifySession(scenario: string, { bPackageJson, aTest, bFoo, bBar, bSymlink }: Packages, alreadyBuilt: boolean, extraOptions: ts.CompilerOptions) { + function verifySession( + scenario: string, + { bPackageJson, aTest, bFoo, bBar, bSymlink }: Packages, + alreadyBuilt: boolean, + extraOptions: ts.CompilerOptions, + ) { const aConfig = config("A", extraOptions, ["../B"]); const bConfig = config("B", extraOptions); const files = [libFile, bPackageJson, aConfig, bConfig, aTest, bFoo, bBar, bSymlink]; - const host = alreadyBuilt ? - createHostWithSolutionBuild(files, [aConfig.path]) : - createServerHost(files); + const host = alreadyBuilt + ? createHostWithSolutionBuild(files, [aConfig.path]) + : createServerHost(files); // Create symlink in node module const session = createSession(host, { canUseEvents: true, logger: createLoggerWithInMemoryLogs(host) }); @@ -326,7 +341,13 @@ function foo() { }, }); verifyGetErrRequest({ session, files: [aTest] }); - baselineTsserverLogs("projectReferences", `monorepo like with symlinks ${scenario} and solution is ${alreadyBuilt ? "built" : "not built"}${extraOptions.preserveSymlinks ? " with preserveSymlinks" : ""}`, session); + baselineTsserverLogs( + "projectReferences", + `monorepo like with symlinks ${scenario} and solution is ${alreadyBuilt ? "built" : "not built"}${ + extraOptions.preserveSymlinks ? " with preserveSymlinks" : "" + }`, + session, + ); } function config(packageName: string, extraOptions: ts.CompilerOptions, references?: string[]): File { @@ -353,30 +374,33 @@ function foo() { } function verifyMonoRepoLike(scope = "") { - verifySymlinkScenario(`when packageJson has types field and has index.ts${scope ? " with scoped package" : ""}`, () => ({ - bPackageJson: { - path: `/user/username/projects/myproject/packages/B/package.json`, - content: JSON.stringify({ - main: "lib/index.js", - types: "lib/index.d.ts", - }), - }, - aTest: file( - "A", - "index.ts", - `import { foo } from '${scope}b'; + verifySymlinkScenario( + `when packageJson has types field and has index.ts${scope ? " with scoped package" : ""}`, + () => ({ + bPackageJson: { + path: `/user/username/projects/myproject/packages/B/package.json`, + content: JSON.stringify({ + main: "lib/index.js", + types: "lib/index.d.ts", + }), + }, + aTest: file( + "A", + "index.ts", + `import { foo } from '${scope}b'; import { bar } from '${scope}b/lib/bar'; foo(); bar(); `, - ), - bFoo: file("B", "index.ts", `export function foo() { }`), - bBar: file("B", "bar.ts", `export function bar() { }`), - bSymlink: { - path: `/user/username/projects/myproject/node_modules/${scope}b`, - symLink: `/user/username/projects/myproject/packages/B`, - }, - })); + ), + bFoo: file("B", "index.ts", `export function foo() { }`), + bBar: file("B", "bar.ts", `export function bar() { }`), + bSymlink: { + path: `/user/username/projects/myproject/node_modules/${scope}b`, + symLink: `/user/username/projects/myproject/packages/B`, + }, + }), + ); verifySymlinkScenario(`when referencing file from subFolder${scope ? " with scoped package" : ""}`, () => ({ bPackageJson: { @@ -467,11 +491,24 @@ testCompositeFunction('why hello there', 42);`, path: `/user/username/projects/myproject/node_modules/emit-composite`, symLink: `/user/username/projects/myproject/packages/emit-composite`, }; - const host = createServerHost([libFile, compositeConfig, compositePackageJson, compositeIndex, compositeTestModule, consumerConfig, consumerIndex, symlink], { useCaseSensitiveFileNames: true }); + const host = createServerHost([ + libFile, + compositeConfig, + compositePackageJson, + compositeIndex, + compositeTestModule, + consumerConfig, + consumerIndex, + symlink, + ], { useCaseSensitiveFileNames: true }); const session = createSession(host, { canUseEvents: true, logger: createLoggerWithInMemoryLogs(host) }); openFilesForSession([consumerIndex], session); verifyGetErrRequest({ session, files: [consumerIndex] }); - baselineTsserverLogs("projectReferences", `when the referenced projects have allowJs and emitDeclarationOnly`, session); + baselineTsserverLogs( + "projectReferences", + `when the referenced projects have allowJs and emitDeclarationOnly`, + session, + ); }); it("when finding local reference doesnt load ancestor/sibling projects", () => { @@ -536,7 +573,16 @@ testCompositeFunction('why hello there', 42);`, }`, }; - const files = [libFile, solution, compilerConfig, typesFile, programFile, servicesConfig, servicesFile, libFile]; + const files = [ + libFile, + solution, + compilerConfig, + typesFile, + programFile, + servicesConfig, + servicesFile, + libFile, + ]; const host = createServerHost(files); const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) }); openFilesForSession([programFile], session); @@ -554,7 +600,11 @@ testCompositeFunction('why hello there', 42);`, command: ts.server.protocol.CommandTypes.References, arguments: protocolFileLocationFromSubstring(programFile, "getSourceFiles"), }); - baselineTsserverLogs("projectReferences", `finding local reference doesnt load ancestor/sibling projects`, session); + baselineTsserverLogs( + "projectReferences", + `finding local reference doesnt load ancestor/sibling projects`, + session, + ); }); it("when finding references in overlapping projects", () => { @@ -656,7 +706,19 @@ testCompositeFunction('why hello there', 42);`, `, }; - const files = [libFile, solutionConfig, aConfig, aFile, bConfig, bFile, cConfig, cFile, dConfig, dFile, libFile]; + const files = [ + libFile, + solutionConfig, + aConfig, + aFile, + bConfig, + bFile, + cConfig, + cFile, + dConfig, + dFile, + libFile, + ]; const host = createServerHost(files); const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) }); openFilesForSession([bFile], session); @@ -731,7 +793,17 @@ ${usage}`, path: `${solutionLocation}/shared/src/index.ts`, content: definition, }; - const host = createServerHost([libFile, solution, libFile, apiConfig, apiFile, appConfig, appFile, sharedConfig, sharedFile]); + const host = createServerHost([ + libFile, + solution, + libFile, + apiConfig, + apiFile, + appConfig, + appFile, + sharedConfig, + sharedFile, + ]); const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) }); openFilesForSession([apiFile], session); @@ -847,7 +919,16 @@ export const foo = local;`, }`, }; - const files = [libFile, solution, compilerConfig, typesFile, programFile, servicesConfig, servicesFile, libFile]; + const files = [ + libFile, + solution, + compilerConfig, + typesFile, + programFile, + servicesConfig, + servicesFile, + libFile, + ]; const host = createServerHost(files); const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) }); openFilesForSession([programFile], session); @@ -858,7 +939,11 @@ export const foo = local;`, command: ts.server.protocol.CommandTypes.References, arguments: protocolFileLocationFromSubstring(programFile, "getSourceFiles"), }); - baselineTsserverLogs("projectReferences", `with disableSolutionSearching solution and siblings are not loaded`, session); + baselineTsserverLogs( + "projectReferences", + `with disableSolutionSearching solution and siblings are not loaded`, + session, + ); }); describe("when default project is solution project", () => { @@ -886,7 +971,8 @@ export { foo }; }; const mainDtsMap: File = { path: `/user/username/projects/myproject/target/src/main.d.ts.map`, - content: `{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../src/main.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,mBAAmB,CAAC;AAExC,OAAO,EAAC,GAAG,EAAC,CAAC"}`, + content: + `{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../src/main.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,mBAAmB,CAAC;AAExC,OAAO,EAAC,GAAG,EAAC,CAAC"}`, }; const helperDts: File = { path: `/user/username/projects/myproject/target/src/helpers/functions.d.ts`, @@ -895,7 +981,8 @@ export { foo }; }; const helperDtsMap: File = { path: `/user/username/projects/myproject/target/src/helpers/functions.d.ts.map`, - content: `{"version":3,"file":"functions.d.ts","sourceRoot":"","sources":["../../../src/helpers/functions.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,GAAG,IAAI,CAAC"}`, + content: + `{"version":3,"file":"functions.d.ts","sourceRoot":"","sources":["../../../src/helpers/functions.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,GAAG,IAAI,CAAC"}`, }; const tsconfigIndirect3: File = { path: `/user/username/projects/myproject/indirect3/tsconfig.json`, @@ -965,7 +1052,11 @@ export function bar() {}`, const info = service.getScriptInfoForPath(main.path as ts.Path)!; session.logger.startGroup(); session.logger.info(`getDefaultProject for ${main.path}: ${info.getDefaultProject().projectName}`); - session.logger.info(`findDefaultConfiguredProject for ${main.path}: ${service.findDefaultConfiguredProject(info)!.projectName}`); + session.logger.info( + `findDefaultConfiguredProject for ${main.path}: ${ + service.findDefaultConfiguredProject(info)!.projectName + }`, + ); session.logger.endGroup(); // Verify errors @@ -1032,7 +1123,10 @@ export function bar() {}`, const info = service.getScriptInfoForPath(main.path as ts.Path)!; session.logger.startGroup(); session.logger.info(`getDefaultProject for ${main.path}: ${info.getDefaultProject().projectName}`); - session.logger.info(`findDefaultConfiguredProject for ${main.path}: ${service.findDefaultConfiguredProject(info)?.projectName}`); + session.logger.info( + `findDefaultConfiguredProject for ${main.path}: ${service.findDefaultConfiguredProject(info) + ?.projectName}`, + ); session.logger.endGroup(); // Verify collection of script infos @@ -1079,7 +1173,8 @@ export function bar() {}`, it("disables looking into the child project if disableReferencedProjectLoad is set in indirect project", () => { const { tsconfigIndirect, indirect } = getIndirectProject("1", { disableReferencedProjectLoad: true }); verifyDisableReferencedProjectLoad({ - scenario: "disables looking into the child project if disableReferencedProjectLoad is set in indirect project", + scenario: + "disables looking into the child project if disableReferencedProjectLoad is set in indirect project", configRefs: ["./tsconfig-indirect1.json"], additionalFiles: [tsconfigIndirect, indirect], }); @@ -1089,7 +1184,8 @@ export function bar() {}`, const { tsconfigIndirect, indirect } = getIndirectProject("1", { disableReferencedProjectLoad: true }); const { tsconfigIndirect: tsconfigIndirect2, indirect: indirect2 } = getIndirectProject("2"); verifyDisableReferencedProjectLoad({ - scenario: "disables looking into the child project if disableReferencedProjectLoad is set in first indirect project but not in another one", + scenario: + "disables looking into the child project if disableReferencedProjectLoad is set in first indirect project but not in another one", configRefs: ["./tsconfig-indirect1.json", "./tsconfig-indirect2.json"], additionalFiles: [tsconfigIndirect, indirect, tsconfigIndirect2, indirect2], }); @@ -1102,7 +1198,8 @@ export function bar() {}`, content: fileResolvingToMainDts.content, }; verifySolutionScenario({ - scenario: "solution with its own files and project found is not solution but references open file through project reference", + scenario: + "solution with its own files and project found is not solution but references open file through project reference", solutionFiles: [`./own/main.ts`], solutionOptions: { outDir: "./target/", @@ -1139,7 +1236,8 @@ bar;`, content: fileResolvingToMainDts.content, }; verifyDisableReferencedProjectLoad({ - scenario: "solution with its own files and disables looking into the child project if disableReferencedProjectLoad is set", + scenario: + "solution with its own files and disables looking into the child project if disableReferencedProjectLoad is set", solutionFiles: [`./own/main.ts`], solutionOptions: { outDir: "./target/", @@ -1159,7 +1257,8 @@ bar;`, }; const { tsconfigIndirect, indirect } = getIndirectProject("1", { disableReferencedProjectLoad: true }); verifyDisableReferencedProjectLoad({ - scenario: "solution with its own files and disables looking into the child project if disableReferencedProjectLoad is set in indirect project", + scenario: + "solution with its own files and disables looking into the child project if disableReferencedProjectLoad is set in indirect project", solutionFiles: [`./own/main.ts`], solutionOptions: { outDir: "./target/", @@ -1179,7 +1278,8 @@ bar;`, const { tsconfigIndirect, indirect } = getIndirectProject("1", { disableReferencedProjectLoad: true }); const { tsconfigIndirect: tsconfigIndirect2, indirect: indirect2 } = getIndirectProject("2"); verifyDisableReferencedProjectLoad({ - scenario: "solution with its own files and disables looking into the child project if disableReferencedProjectLoad is set in first indirect project but not in another one", + scenario: + "solution with its own files and disables looking into the child project if disableReferencedProjectLoad is set in first indirect project but not in another one", solutionFiles: [`./own/main.ts`], solutionOptions: { outDir: "./target/", @@ -1244,14 +1344,21 @@ bar;`, host.runQueuedTimeoutCallbacks(); // Add excluded file to referenced project - host.ensureFileOrFolder({ path: `/user/username/projects/myproject/projects/project1/temp/file.d.ts`, content: `declare class file {}` }); + host.ensureFileOrFolder({ + path: `/user/username/projects/myproject/projects/project1/temp/file.d.ts`, + content: `declare class file {}`, + }); host.runQueuedTimeoutCallbacks(); // Add output from new class to referenced project const class3Dts = `/user/username/projects/myproject/projects/project1/class3.d.ts`; host.writeFile(class3Dts, `declare class class3 {}`); host.runQueuedTimeoutCallbacks(); - baselineTsserverLogs("projectReferences", `new file is added to the referenced project when referenced project is not open`, session); + baselineTsserverLogs( + "projectReferences", + `new file is added to the referenced project when referenced project is not open`, + session, + ); }); it("when referenced project is open", () => { @@ -1263,13 +1370,20 @@ bar;`, host.writeFile(class3, `class class3 {}`); host.runQueuedTimeoutCallbacks(); // Add excluded file to referenced project - host.ensureFileOrFolder({ path: `/user/username/projects/myproject/projects/project1/temp/file.d.ts`, content: `declare class file {}` }); + host.ensureFileOrFolder({ + path: `/user/username/projects/myproject/projects/project1/temp/file.d.ts`, + content: `declare class file {}`, + }); host.runQueuedTimeoutCallbacks(); // Add output from new class to referenced project const class3Dts = `/user/username/projects/myproject/projects/project1/class3.d.ts`; host.writeFile(class3Dts, `declare class class3 {}`); host.runQueuedTimeoutCallbacks(); - baselineTsserverLogs("projectReferences", `new file is added to the referenced project when referenced project is open`, session); + baselineTsserverLogs( + "projectReferences", + `new file is added to the referenced project when referenced project is open`, + session, + ); }); it("when referenced project is not open with disableSourceOfProjectReferenceRedirect", () => { @@ -1284,7 +1398,10 @@ bar;`, host.writeFile(class3Dts, `declare class class3 {}`); host.runQueuedTimeoutCallbacks(); // Add excluded file to referenced project - host.ensureFileOrFolder({ path: `/user/username/projects/myproject/projects/project1/temp/file.d.ts`, content: `declare class file {}` }); + host.ensureFileOrFolder({ + path: `/user/username/projects/myproject/projects/project1/temp/file.d.ts`, + content: `declare class file {}`, + }); host.runQueuedTimeoutCallbacks(); // Delete output from new class to referenced project host.deleteFile(class3Dts); @@ -1292,7 +1409,11 @@ bar;`, // Write back output of new class to referenced project host.writeFile(class3Dts, `declare class class3 {}`); host.runQueuedTimeoutCallbacks(); - baselineTsserverLogs("projectReferences", `new file is added to the referenced project when referenced project is not open with disableSourceOfProjectReferenceRedirect`, session); + baselineTsserverLogs( + "projectReferences", + `new file is added to the referenced project when referenced project is not open with disableSourceOfProjectReferenceRedirect`, + session, + ); }); it("when referenced project is open with disableSourceOfProjectReferenceRedirect", () => { @@ -1308,7 +1429,10 @@ bar;`, host.writeFile(class3Dts, `declare class class3 {}`); host.runQueuedTimeoutCallbacks(); // Add excluded file to referenced project - host.ensureFileOrFolder({ path: `/user/username/projects/myproject/projects/project1/temp/file.d.ts`, content: `declare class file {}` }); + host.ensureFileOrFolder({ + path: `/user/username/projects/myproject/projects/project1/temp/file.d.ts`, + content: `declare class file {}`, + }); host.runQueuedTimeoutCallbacks(); // Delete output from new class to referenced project host.deleteFile(class3Dts); @@ -1316,7 +1440,11 @@ bar;`, // Write back output of new class to referenced project host.writeFile(class3Dts, `declare class class3 {}`); host.runQueuedTimeoutCallbacks(); - baselineTsserverLogs("projectReferences", `new file is added to the referenced project when referenced project is open with disableSourceOfProjectReferenceRedirect`, session); + baselineTsserverLogs( + "projectReferences", + `new file is added to the referenced project when referenced project is open with disableSourceOfProjectReferenceRedirect`, + session, + ); }); }); @@ -1379,7 +1507,17 @@ bar;`, path: `/user/username/projects/myproject/node_modules/shared`, symLink: `/user/username/projects/myproject/shared`, }; - const files = [solnConfig, sharedConfig, sharedIndex, sharedPackage, appConfig, appBar, appIndex, sharedSymlink, libFile]; + const files = [ + solnConfig, + sharedConfig, + sharedIndex, + sharedPackage, + appConfig, + appBar, + appIndex, + sharedSymlink, + libFile, + ]; const host = createServerHost(files); if (built) { solutionBuildWithBaseline(host, [solnConfig.path]); @@ -1398,7 +1536,13 @@ bar;`, errorCodes: [ts.Diagnostics.Cannot_find_name_0.code], }, }); - baselineTsserverLogs("projectReferences", `auto import with referenced project${built ? " when built" : ""}${disableSourceOfProjectReferenceRedirect ? " with disableSourceOfProjectReferenceRedirect" : ""}`, session); + baselineTsserverLogs( + "projectReferences", + `auto import with referenced project${built ? " when built" : ""}${ + disableSourceOfProjectReferenceRedirect ? " with disableSourceOfProjectReferenceRedirect" : "" + }`, + session, + ); } it("when project is built", () => { @@ -1413,7 +1557,11 @@ bar;`, }); it("when files from two projects are open and one project references", () => { - function getPackageAndFile(packageName: string, references?: string[], optionsToExtend?: ts.CompilerOptions): [file: File, config: File] { + function getPackageAndFile( + packageName: string, + references?: string[], + optionsToExtend?: ts.CompilerOptions, + ): [file: File, config: File] { const file: File = { path: `/user/username/projects/myproject/${packageName}/src/file1.ts`, content: `export const ${packageName}Const = 10;`, @@ -1427,14 +1575,30 @@ bar;`, }; return [file, config]; } - const [mainFile, mainConfig] = getPackageAndFile("main", ["core", "indirect", "noCoreRef1", "indirectDisabledChildLoad1", "indirectDisabledChildLoad2", "refToCoreRef3", "indirectNoCoreRef"]); + const [mainFile, mainConfig] = getPackageAndFile("main", [ + "core", + "indirect", + "noCoreRef1", + "indirectDisabledChildLoad1", + "indirectDisabledChildLoad2", + "refToCoreRef3", + "indirectNoCoreRef", + ]); const [coreFile, coreConfig] = getPackageAndFile("core"); const [noCoreRef1File, noCoreRef1Config] = getPackageAndFile("noCoreRef1"); const [indirectFile, indirectConfig] = getPackageAndFile("indirect", ["coreRef1"]); const [coreRef1File, coreRef1Config] = getPackageAndFile("coreRef1", ["core"]); - const [indirectDisabledChildLoad1File, indirectDisabledChildLoad1Config] = getPackageAndFile("indirectDisabledChildLoad1", ["coreRef2"], { disableReferencedProjectLoad: true }); + const [indirectDisabledChildLoad1File, indirectDisabledChildLoad1Config] = getPackageAndFile( + "indirectDisabledChildLoad1", + ["coreRef2"], + { disableReferencedProjectLoad: true }, + ); const [coreRef2File, coreRef2Config] = getPackageAndFile("coreRef2", ["core"]); - const [indirectDisabledChildLoad2File, indirectDisabledChildLoad2Config] = getPackageAndFile("indirectDisabledChildLoad2", ["coreRef3"], { disableReferencedProjectLoad: true }); + const [indirectDisabledChildLoad2File, indirectDisabledChildLoad2Config] = getPackageAndFile( + "indirectDisabledChildLoad2", + ["coreRef3"], + { disableReferencedProjectLoad: true }, + ); const [coreRef3File, coreRef3Config] = getPackageAndFile("coreRef3", ["core"]); const [refToCoreRef3File, refToCoreRef3Config] = getPackageAndFile("refToCoreRef3", ["coreRef3"]); const [indirectNoCoreRefFile, indirectNoCoreRefConfig] = getPackageAndFile("indirectNoCoreRef", ["noCoreRef2"]); @@ -1475,7 +1639,11 @@ bar;`, command: ts.server.protocol.CommandTypes.References, arguments: protocolFileLocationFromSubstring(coreFile, `coreConst`), }); - baselineTsserverLogs("projectReferences", `when files from two projects are open and one project references`, session); + baselineTsserverLogs( + "projectReferences", + `when files from two projects are open and one project references`, + session, + ); }); describe("find refs to decl in other proj", () => { @@ -1521,7 +1689,8 @@ const b: B = new B();`, const dtsMapB: File = { path: `/user/username/projects/myproject/b/lib/index.d.ts.map`, - content: `{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,qBAAa,CAAC;IACV,CAAC;CACJ"}`, + content: + `{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,qBAAa,CAAC;IACV,CAAC;CACJ"}`, }; function baselineDisableReferencedProjectLoad( @@ -1531,10 +1700,10 @@ const b: B = new B();`, dtsMapPresent: boolean, ) { // Mangled to stay under windows path length limit - const subScenario = `when proj ${projectAlreadyLoaded ? "is" : "is not"} loaded` + - ` and refd proj loading is ${disableReferencedProjectLoad ? "disabled" : "enabled"}` + - ` and proj ref redirects are ${disableSourceOfProjectReferenceRedirect ? "disabled" : "enabled"}` + - ` and a decl map is ${dtsMapPresent ? "present" : "missing"}`; + const subScenario = `when proj ${projectAlreadyLoaded ? "is" : "is not"} loaded` + + ` and refd proj loading is ${disableReferencedProjectLoad ? "disabled" : "enabled"}` + + ` and proj ref redirects are ${disableSourceOfProjectReferenceRedirect ? "disabled" : "enabled"}` + + ` and a decl map is ${dtsMapPresent ? "present" : "missing"}`; const compilerOptions: ts.CompilerOptions = { disableReferencedProjectLoad, disableSourceOfProjectReferenceRedirect, @@ -1550,7 +1719,15 @@ const b: B = new B();`, }`, }; - const host = createServerHost([configA, indexA, configB, indexB, helperB, dtsB, ...(dtsMapPresent ? [dtsMapB] : [])]); + const host = createServerHost([ + configA, + indexA, + configB, + indexB, + helperB, + dtsB, + ...(dtsMapPresent ? [dtsMapB] : []), + ]); const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) }); openFilesForSession([indexA, ...(projectAlreadyLoaded ? [helperB] : [])], session); diff --git a/src/testRunner/unittests/tsserver/projectReferencesSourcemap.ts b/src/testRunner/unittests/tsserver/projectReferencesSourcemap.ts index 5f5ecb64d682e..d81ac9cc106e5 100644 --- a/src/testRunner/unittests/tsserver/projectReferencesSourcemap.ts +++ b/src/testRunner/unittests/tsserver/projectReferencesSourcemap.ts @@ -31,7 +31,9 @@ export function fn5() { } }; const dependencyConfig: File = { path: `${dependecyLocation}/tsconfig.json`, - content: JSON.stringify({ compilerOptions: { composite: true, declarationMap: true, declarationDir: "../decls" } }), + content: JSON.stringify({ + compilerOptions: { composite: true, declarationMap: true, declarationDir: "../decls" }, + }), }; const mainTs: File = { @@ -117,9 +119,18 @@ fn5(); equal: boolean, debugInfo?: string, ) { - assert.strictEqual(session.getProjectService().filenameToScriptInfo.get(dtsMapPath), dependencyMap, `${debugInfo} dependencyMap`); + assert.strictEqual( + session.getProjectService().filenameToScriptInfo.get(dtsMapPath), + dependencyMap, + `${debugInfo} dependencyMap`, + ); if (dependencyMap) { - verifyEquality(dependencyMap.documentPositionMapper, documentPositionMapper, equal, `${debugInfo} DocumentPositionMapper`); + verifyEquality( + dependencyMap.documentPositionMapper, + documentPositionMapper, + equal, + `${debugInfo} DocumentPositionMapper`, + ); } } @@ -174,7 +185,12 @@ fn5(); } } verifyEquality(dtsMapInfo, existingDependencyMap, existingMapEqual, `${debugInfo} dependencyMap`); - verifyEquality(existingDocumentPositionMapper, dtsMapInfo?.documentPositionMapper, existingDocumentPositionMapperEqual, `${debugInfo} DocumentPositionMapper`); + verifyEquality( + existingDocumentPositionMapper, + dtsMapInfo?.documentPositionMapper, + existingDocumentPositionMapperEqual, + `${debugInfo} DocumentPositionMapper`, + ); sourceMapPath = dtsInfo?.sourceMapFilePath; dependencyMap = dtsMapInfo; documentPositionMapper = dependencyMap?.documentPositionMapper; @@ -208,7 +224,11 @@ fn5(); type OnHostCreate = (host: TestServerHost) => void; type CreateSessionFn = (onHostCreate?: OnHostCreate) => { host: TestServerHost; session: TestSession; }; - function setupWith(createSession: CreateSessionFn, openFiles: readonly File[], onHostCreate: OnHostCreate | undefined) { + function setupWith( + createSession: CreateSessionFn, + openFiles: readonly File[], + onHostCreate: OnHostCreate | undefined, + ) { const result = createSession(onHostCreate); openFilesForSession(openFiles, result.session); return result; @@ -301,7 +321,10 @@ fn5(); } describe("from project that uses dependency: goToDef", () => { - function setupWithActionWith(setup: (onHostCreate?: OnHostCreate) => ReturnType, onHostCreate: OnHostCreate | undefined) { + function setupWithActionWith( + setup: (onHostCreate?: OnHostCreate) => ReturnType, + onHostCreate: OnHostCreate | undefined, + ) { const result = setup(onHostCreate); result.session.executeCommandSeq(goToDefFromMainTs(1)); return { ...result, ...getDocumentPositionMapper(result.session) }; @@ -327,7 +350,11 @@ fn5(); /*existingDocumentPositionMapperEqual*/ false, ); verifyScriptInfoCollectionWith(session, [mainTs]); - baselineTsserverLogs("projectReferencesSourcemap", "usageProject/configHasNoReference/can go to definition correctly", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "usageProject/configHasNoReference/can go to definition correctly", + session, + ); }); // Edit @@ -349,7 +376,11 @@ fn5(); /*existingMapEqual*/ true, /*existingDocumentPositionMapperEqual*/ true, ); - baselineTsserverLogs("projectReferencesSourcemap", "usageProject/configHasNoReference/usage file changes with timeout before request", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "usageProject/configHasNoReference/usage file changes with timeout before request", + session, + ); }); it(`when usage file changes, document position mapper doesnt change, when timeout does not occur before request`, () => { // Create DocumentPositionMapper @@ -367,7 +398,11 @@ fn5(); /*existingMapEqual*/ true, /*existingDocumentPositionMapperEqual*/ true, ); - baselineTsserverLogs("projectReferencesSourcemap", "usageProject/configHasNoReference/usage file changes", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "usageProject/configHasNoReference/usage file changes", + session, + ); }); // Edit dts to add new fn @@ -389,7 +424,11 @@ fn5(); /*existingMapEqual*/ true, /*existingDocumentPositionMapperEqual*/ true, ); - baselineTsserverLogs("projectReferencesSourcemap", "usageProject/configHasNoReference/dependency dts changes with timeout before request", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "usageProject/configHasNoReference/dependency dts changes with timeout before request", + session, + ); }); it(`when dependency .d.ts changes, document position mapper doesnt change, when timeout does not occur before request`, () => { // Create DocumentPositionMapper @@ -407,7 +446,11 @@ fn5(); /*existingMapEqual*/ true, /*existingDocumentPositionMapperEqual*/ true, ); - baselineTsserverLogs("projectReferencesSourcemap", "usageProject/configHasNoReference/dependency dts changes", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "usageProject/configHasNoReference/dependency dts changes", + session, + ); }); // Edit map file to represent added new line @@ -429,7 +472,11 @@ fn5(); /*existingMapEqual*/ true, /*existingDocumentPositionMapperEqual*/ false, ); - baselineTsserverLogs("projectReferencesSourcemap", "usageProject/configHasNoReference/dependency dtsMap changes with timeout before request", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "usageProject/configHasNoReference/dependency dtsMap changes with timeout before request", + session, + ); }); it(`when dependency file's map changes, when timeout does not occur before request`, () => { // Create DocumentPositionMapper @@ -447,7 +494,11 @@ fn5(); /*existingMapEqual*/ true, /*existingDocumentPositionMapperEqual*/ false, ); - baselineTsserverLogs("projectReferencesSourcemap", "usageProject/configHasNoReference/dependency dtsMap changes", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "usageProject/configHasNoReference/dependency dtsMap changes", + session, + ); }); it(`with depedency files map file, when file is not present`, () => { @@ -462,7 +513,11 @@ fn5(); /*existingDocumentPositionMapperEqual*/ true, ); verifyScriptInfoCollectionWith(session, [mainTs]); - baselineTsserverLogs("projectReferencesSourcemap", "usageProject/configHasNoReference/dependency dtsMap not present", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "usageProject/configHasNoReference/dependency dtsMap not present", + session, + ); }); it(`with depedency files map file, when file is created after actions on projects`, () => { let fileContents: string; @@ -481,7 +536,11 @@ fn5(); /*existingDocumentPositionMapperEqual*/ false, ); verifyScriptInfoCollectionWith(session, [mainTs]); - baselineTsserverLogs("projectReferencesSourcemap", "usageProject/configHasNoReference/dependency dtsMap created", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "usageProject/configHasNoReference/dependency dtsMap created", + session, + ); }); it(`with depedency files map file, when file is deleted after actions on the projects`, () => { const { host, session, dependencyMap, documentPositionMapper } = setupWithAction(); @@ -497,7 +556,11 @@ fn5(); /*existingDocumentPositionMapperEqual*/ false, ); verifyScriptInfoCollectionWith(session, [mainTs]); - baselineTsserverLogs("projectReferencesSourcemap", "usageProject/configHasNoReference/dependency dtsMap deleted", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "usageProject/configHasNoReference/dependency dtsMap deleted", + session, + ); }); it(`with depedency .d.ts file, when file is not present`, () => { @@ -512,7 +575,11 @@ fn5(); /*existingDocumentPositionMapperEqual*/ true, ); verifyScriptInfoCollectionWith(session, [mainTs]); - baselineTsserverLogs("projectReferencesSourcemap", "usageProject/configHasNoReference/dependency dts not present", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "usageProject/configHasNoReference/dependency dts not present", + session, + ); }); it(`with depedency .d.ts file, when file is created after actions on projects`, () => { let fileContents: string; @@ -531,7 +598,11 @@ fn5(); /*existingDocumentPositionMapperEqual*/ false, ); verifyScriptInfoCollectionWith(session, [mainTs]); - baselineTsserverLogs("projectReferencesSourcemap", "usageProject/configHasNoReference/dependency dts created", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "usageProject/configHasNoReference/dependency dts created", + session, + ); }); it(`with depedency .d.ts file, when file is deleted after actions on the projects`, () => { const { host, session, dependencyMap, documentPositionMapper } = setupWithAction(); @@ -547,7 +618,11 @@ fn5(); /*existingDocumentPositionMapperEqual*/ true, ); verifyScriptInfoCollectionWith(session, [mainTs]); - baselineTsserverLogs("projectReferencesSourcemap", "usageProject/configHasNoReference/dependency dts deleted", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "usageProject/configHasNoReference/dependency dts deleted", + session, + ); }); }); describe("when main tsconfig has project reference", () => { @@ -570,7 +645,11 @@ fn5(); /*existingDocumentPositionMapperEqual*/ true, ); verifyScriptInfoCollectionWith(session, [mainTs]); - baselineTsserverLogs("projectReferencesSourcemap", "usageProject/configWithReference/can go to definition correctly", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "usageProject/configWithReference/can go to definition correctly", + session, + ); }); // Edit @@ -592,7 +671,11 @@ fn5(); /*existingMapEqual*/ true, /*existingDocumentPositionMapperEqual*/ true, ); - baselineTsserverLogs("projectReferencesSourcemap", "usageProject/configWithReference/usage file changes with timeout before request", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "usageProject/configWithReference/usage file changes with timeout before request", + session, + ); }); it(`when usage file changes, document position mapper doesnt change, when timeout does not occur before request`, () => { // Create DocumentPositionMapper @@ -610,7 +693,11 @@ fn5(); /*existingMapEqual*/ true, /*existingDocumentPositionMapperEqual*/ true, ); - baselineTsserverLogs("projectReferencesSourcemap", "usageProject/configWithReference/usage file changes", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "usageProject/configWithReference/usage file changes", + session, + ); }); // Edit dts to add new fn @@ -632,7 +719,11 @@ fn5(); /*existingMapEqual*/ true, /*existingDocumentPositionMapperEqual*/ true, ); - baselineTsserverLogs("projectReferencesSourcemap", "usageProject/configWithReference/dependency dts changes with timeout before request", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "usageProject/configWithReference/dependency dts changes with timeout before request", + session, + ); }); it(`when dependency .d.ts changes, document position mapper doesnt change, when timeout does not occur before request`, () => { // Create DocumentPositionMapper @@ -650,7 +741,11 @@ fn5(); /*existingMapEqual*/ true, /*existingDocumentPositionMapperEqual*/ true, ); - baselineTsserverLogs("projectReferencesSourcemap", "usageProject/configWithReference/dependency dts changes", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "usageProject/configWithReference/dependency dts changes", + session, + ); }); // Edit map file to represent added new line @@ -672,7 +767,11 @@ fn5(); /*existingMapEqual*/ true, /*existingDocumentPositionMapperEqual*/ true, ); - baselineTsserverLogs("projectReferencesSourcemap", "usageProject/configWithReference/dependency dtsMap changes with timeout before request", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "usageProject/configWithReference/dependency dtsMap changes with timeout before request", + session, + ); }); it(`when dependency file's map changes, when timeout does not occur before request`, () => { // Create DocumentPositionMapper @@ -690,7 +789,11 @@ fn5(); /*existingMapEqual*/ true, /*existingDocumentPositionMapperEqual*/ true, ); - baselineTsserverLogs("projectReferencesSourcemap", "usageProject/configWithReference/dependency dtsMap changes", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "usageProject/configWithReference/dependency dtsMap changes", + session, + ); }); it(`with depedency files map file, when file is not present`, () => { @@ -705,7 +808,11 @@ fn5(); /*existingDocumentPositionMapperEqual*/ true, ); verifyScriptInfoCollectionWith(session, [mainTs]); - baselineTsserverLogs("projectReferencesSourcemap", "usageProject/configWithReference/dependency dtsMap not present", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "usageProject/configWithReference/dependency dtsMap not present", + session, + ); }); it(`with depedency files map file, when file is created after actions on projects`, () => { let fileContents: string; @@ -724,7 +831,11 @@ fn5(); /*existingDocumentPositionMapperEqual*/ true, ); verifyScriptInfoCollectionWith(session, [mainTs]); - baselineTsserverLogs("projectReferencesSourcemap", "usageProject/configWithReference/dependency dtsMap created", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "usageProject/configWithReference/dependency dtsMap created", + session, + ); }); it(`with depedency files map file, when file is deleted after actions on the projects`, () => { const { host, session, dependencyMap, documentPositionMapper } = setupWithAction(); @@ -740,7 +851,11 @@ fn5(); /*existingDocumentPositionMapperEqual*/ true, ); verifyScriptInfoCollectionWith(session, [mainTs]); - baselineTsserverLogs("projectReferencesSourcemap", "usageProject/configWithReference/dependency dtsMap deleted", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "usageProject/configWithReference/dependency dtsMap deleted", + session, + ); }); it(`with depedency .d.ts file, when file is not present`, () => { @@ -755,7 +870,11 @@ fn5(); /*existingDocumentPositionMapperEqual*/ true, ); verifyScriptInfoCollectionWith(session, [mainTs]); - baselineTsserverLogs("projectReferencesSourcemap", "usageProject/configWithReference/dependency dts not present", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "usageProject/configWithReference/dependency dts not present", + session, + ); }); it(`with depedency .d.ts file, when file is created after actions on projects`, () => { let fileContents: string; @@ -774,7 +893,11 @@ fn5(); /*existingDocumentPositionMapperEqual*/ true, ); verifyScriptInfoCollectionWith(session, [mainTs]); - baselineTsserverLogs("projectReferencesSourcemap", "usageProject/configWithReference/dependency dts created", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "usageProject/configWithReference/dependency dts created", + session, + ); }); it(`with depedency .d.ts file, when file is deleted after actions on the projects`, () => { const { host, session, dependencyMap, documentPositionMapper } = setupWithAction(); @@ -790,7 +913,11 @@ fn5(); /*existingDocumentPositionMapperEqual*/ true, ); verifyScriptInfoCollectionWith(session, [mainTs]); - baselineTsserverLogs("projectReferencesSourcemap", "usageProject/configWithReference/dependency dts deleted", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "usageProject/configWithReference/dependency dts deleted", + session, + ); }); it(`when defining project source changes, when timeout occurs before request`, () => { // Create DocumentPositionMapper @@ -815,7 +942,11 @@ ${dependencyTs.content}`, /*existingMapEqual*/ true, /*existingDocumentPositionMapperEqual*/ true, ); - baselineTsserverLogs("projectReferencesSourcemap", "usageProject/configWithReference/dependency source changes with timeout before request", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "usageProject/configWithReference/dependency source changes with timeout before request", + session, + ); }); it(`when defining project source changes, when timeout does not occur before request`, () => { // Create DocumentPositionMapper @@ -838,7 +969,11 @@ ${dependencyTs.content}`, /*existingMapEqual*/ true, /*existingDocumentPositionMapperEqual*/ true, ); - baselineTsserverLogs("projectReferencesSourcemap", "usageProject/configWithReference/dependency source changes", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "usageProject/configWithReference/dependency source changes", + session, + ); }); it("when projects are not built", () => { @@ -854,7 +989,11 @@ ${dependencyTs.content}`, /*existingDocumentPositionMapperEqual*/ true, ); verifyScriptInfoCollectionWith(session, [mainTs]); - baselineTsserverLogs("projectReferencesSourcemap", "usageProject/configWithReference/when projects are not built", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "usageProject/configWithReference/when projects are not built", + session, + ); }); }); describe("when main tsconfig has disableSourceOfProjectReferenceRedirect along with project reference", () => { @@ -877,7 +1016,11 @@ ${dependencyTs.content}`, /*existingDocumentPositionMapperEqual*/ false, ); verifyScriptInfoCollectionWith(session, [mainTs]); - baselineTsserverLogs("projectReferencesSourcemap", "usageProject/disabledSourceRef/can go to definition correctly", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "usageProject/disabledSourceRef/can go to definition correctly", + session, + ); }); // Edit @@ -899,7 +1042,11 @@ ${dependencyTs.content}`, /*existingMapEqual*/ true, /*existingDocumentPositionMapperEqual*/ true, ); - baselineTsserverLogs("projectReferencesSourcemap", "usageProject/disabledSourceRef/usage file changes with timeout before request", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "usageProject/disabledSourceRef/usage file changes with timeout before request", + session, + ); }); it(`when usage file changes, document position mapper doesnt change, when timeout does not occur before request`, () => { // Create DocumentPositionMapper @@ -917,7 +1064,11 @@ ${dependencyTs.content}`, /*existingMapEqual*/ true, /*existingDocumentPositionMapperEqual*/ true, ); - baselineTsserverLogs("projectReferencesSourcemap", "usageProject/disabledSourceRef/usage file changes", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "usageProject/disabledSourceRef/usage file changes", + session, + ); }); // Edit dts to add new fn @@ -939,7 +1090,11 @@ ${dependencyTs.content}`, /*existingMapEqual*/ true, /*existingDocumentPositionMapperEqual*/ true, ); - baselineTsserverLogs("projectReferencesSourcemap", "usageProject/disabledSourceRef/dependency dts changes with timeout before request", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "usageProject/disabledSourceRef/dependency dts changes with timeout before request", + session, + ); }); it(`when dependency .d.ts changes, document position mapper doesnt change, when timeout does not occur before request`, () => { // Create DocumentPositionMapper @@ -957,7 +1112,11 @@ ${dependencyTs.content}`, /*existingMapEqual*/ true, /*existingDocumentPositionMapperEqual*/ true, ); - baselineTsserverLogs("projectReferencesSourcemap", "usageProject/disabledSourceRef/dependency dts changes", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "usageProject/disabledSourceRef/dependency dts changes", + session, + ); }); // Edit map file to represent added new line @@ -979,7 +1138,11 @@ ${dependencyTs.content}`, /*existingMapEqual*/ true, /*existingDocumentPositionMapperEqual*/ false, ); - baselineTsserverLogs("projectReferencesSourcemap", "usageProject/disabledSourceRef/dependency dtsMap changes with timeout before request", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "usageProject/disabledSourceRef/dependency dtsMap changes with timeout before request", + session, + ); }); it(`when dependency file's map changes, when timeout does not occur before request`, () => { // Create DocumentPositionMapper @@ -997,7 +1160,11 @@ ${dependencyTs.content}`, /*existingMapEqual*/ true, /*existingDocumentPositionMapperEqual*/ false, ); - baselineTsserverLogs("projectReferencesSourcemap", "usageProject/disabledSourceRef/dependency dtsMap changes", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "usageProject/disabledSourceRef/dependency dtsMap changes", + session, + ); }); it(`with depedency files map file, when file is not present`, () => { @@ -1012,7 +1179,11 @@ ${dependencyTs.content}`, /*existingDocumentPositionMapperEqual*/ true, ); verifyScriptInfoCollectionWith(session, [mainTs]); - baselineTsserverLogs("projectReferencesSourcemap", "usageProject/disabledSourceRef/dependency dtsMap not present", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "usageProject/disabledSourceRef/dependency dtsMap not present", + session, + ); }); it(`with depedency files map file, when file is created after actions on projects`, () => { let fileContents: string; @@ -1031,7 +1202,11 @@ ${dependencyTs.content}`, /*existingDocumentPositionMapperEqual*/ false, ); verifyScriptInfoCollectionWith(session, [mainTs]); - baselineTsserverLogs("projectReferencesSourcemap", "usageProject/disabledSourceRef/dependency dtsMap created", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "usageProject/disabledSourceRef/dependency dtsMap created", + session, + ); }); it(`with depedency files map file, when file is deleted after actions on the projects`, () => { const { host, session, dependencyMap, documentPositionMapper } = setupWithAction(); @@ -1047,7 +1222,11 @@ ${dependencyTs.content}`, /*existingDocumentPositionMapperEqual*/ false, ); verifyScriptInfoCollectionWith(session, [mainTs]); - baselineTsserverLogs("projectReferencesSourcemap", "usageProject/disabledSourceRef/dependency dtsMap deleted", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "usageProject/disabledSourceRef/dependency dtsMap deleted", + session, + ); }); it(`with depedency .d.ts file, when file is not present`, () => { @@ -1062,7 +1241,11 @@ ${dependencyTs.content}`, /*existingDocumentPositionMapperEqual*/ true, ); verifyScriptInfoCollectionWith(session, [mainTs]); - baselineTsserverLogs("projectReferencesSourcemap", "usageProject/disabledSourceRef/dependency dts not present", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "usageProject/disabledSourceRef/dependency dts not present", + session, + ); }); it(`with depedency .d.ts file, when file is created after actions on projects`, () => { let fileContents: string; @@ -1081,7 +1264,11 @@ ${dependencyTs.content}`, /*existingDocumentPositionMapperEqual*/ false, ); verifyScriptInfoCollectionWith(session, [mainTs]); - baselineTsserverLogs("projectReferencesSourcemap", "usageProject/disabledSourceRef/dependency dts created", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "usageProject/disabledSourceRef/dependency dts created", + session, + ); }); it(`with depedency .d.ts file, when file is deleted after actions on the projects`, () => { const { host, session, dependencyMap, documentPositionMapper } = setupWithAction(); @@ -1097,13 +1284,20 @@ ${dependencyTs.content}`, /*existingDocumentPositionMapperEqual*/ true, ); verifyScriptInfoCollectionWith(session, [mainTs]); - baselineTsserverLogs("projectReferencesSourcemap", "usageProject/disabledSourceRef/dependency dts deleted", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "usageProject/disabledSourceRef/dependency dts deleted", + session, + ); }); }); }); describe("from defining project: rename", () => { - function setupWithActionWith(setup: (onHostCreate?: OnHostCreate) => ReturnType, onHostCreate: OnHostCreate | undefined) { + function setupWithActionWith( + setup: (onHostCreate?: OnHostCreate) => ReturnType, + onHostCreate: OnHostCreate | undefined, + ) { const result = setup(onHostCreate); result.session.executeCommandSeq(renameFromDependencyTs(1)); return { ...result, ...getDocumentPositionMapper(result.session) }; @@ -1129,7 +1323,11 @@ ${dependencyTs.content}`, /*existingDocumentPositionMapperEqual*/ false, ); verifyScriptInfoCollectionWith(session, [dependencyTs]); - baselineTsserverLogs("projectReferencesSourcemap", "dependency/configHasNoReference/rename locations", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "dependency/configHasNoReference/rename locations", + session, + ); }); // Edit @@ -1151,7 +1349,11 @@ ${dependencyTs.content}`, /*existingMapEqual*/ true, /*existingDocumentPositionMapperEqual*/ true, ); - baselineTsserverLogs("projectReferencesSourcemap", "dependency/configHasNoReference/usage file changes with timeout before request", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "dependency/configHasNoReference/usage file changes with timeout before request", + session, + ); }); it(`when usage file changes, document position mapper doesnt change, when timeout does not occur before request`, () => { // Create DocumentPositionMapper @@ -1169,7 +1371,11 @@ ${dependencyTs.content}`, /*existingMapEqual*/ true, /*existingDocumentPositionMapperEqual*/ true, ); - baselineTsserverLogs("projectReferencesSourcemap", "dependency/configHasNoReference/usage file changes", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "dependency/configHasNoReference/usage file changes", + session, + ); }); // Edit dts to add new fn @@ -1191,7 +1397,11 @@ ${dependencyTs.content}`, /*existingMapEqual*/ true, /*existingDocumentPositionMapperEqual*/ true, ); - baselineTsserverLogs("projectReferencesSourcemap", "dependency/configHasNoReference/dependency dts changes with timeout before request", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "dependency/configHasNoReference/dependency dts changes with timeout before request", + session, + ); }); it(`when dependency .d.ts changes, document position mapper doesnt change, when timeout does not occur before request`, () => { // Create DocumentPositionMapper @@ -1209,7 +1419,11 @@ ${dependencyTs.content}`, /*existingMapEqual*/ true, /*existingDocumentPositionMapperEqual*/ true, ); - baselineTsserverLogs("projectReferencesSourcemap", "dependency/configHasNoReference/dependency dts changes", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "dependency/configHasNoReference/dependency dts changes", + session, + ); }); // Edit map file to represent added new line @@ -1231,7 +1445,11 @@ ${dependencyTs.content}`, /*existingMapEqual*/ true, /*existingDocumentPositionMapperEqual*/ false, ); - baselineTsserverLogs("projectReferencesSourcemap", "dependency/configHasNoReference/dependency dtsMap changes with timeout before request", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "dependency/configHasNoReference/dependency dtsMap changes with timeout before request", + session, + ); }); it(`when dependency file's map changes, when timeout does not occur before request`, () => { // Create DocumentPositionMapper @@ -1249,7 +1467,11 @@ ${dependencyTs.content}`, /*existingMapEqual*/ true, /*existingDocumentPositionMapperEqual*/ false, ); - baselineTsserverLogs("projectReferencesSourcemap", "dependency/configHasNoReference/dependency dtsMap changes", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "dependency/configHasNoReference/dependency dtsMap changes", + session, + ); }); it(`with depedency files map file, when file is not present`, () => { @@ -1264,7 +1486,11 @@ ${dependencyTs.content}`, /*existingDocumentPositionMapperEqual*/ true, ); verifyScriptInfoCollectionWith(session, [dependencyTs]); - baselineTsserverLogs("projectReferencesSourcemap", "dependency/configHasNoReference/dependency dtsMap not present", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "dependency/configHasNoReference/dependency dtsMap not present", + session, + ); }); it(`with depedency files map file, when file is created after actions on projects`, () => { let fileContents: string; @@ -1283,7 +1509,11 @@ ${dependencyTs.content}`, /*existingDocumentPositionMapperEqual*/ false, ); verifyScriptInfoCollectionWith(session, [dependencyTs]); - baselineTsserverLogs("projectReferencesSourcemap", "dependency/configHasNoReference/dependency dtsMap created", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "dependency/configHasNoReference/dependency dtsMap created", + session, + ); }); it(`with depedency files map file, when file is deleted after actions on the projects`, () => { const { host, session, dependencyMap, documentPositionMapper } = setupWithAction(); @@ -1299,7 +1529,11 @@ ${dependencyTs.content}`, /*existingDocumentPositionMapperEqual*/ false, ); verifyScriptInfoCollectionWith(session, [dependencyTs]); - baselineTsserverLogs("projectReferencesSourcemap", "dependency/configHasNoReference/dependency dtsMap deleted", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "dependency/configHasNoReference/dependency dtsMap deleted", + session, + ); }); it(`with depedency .d.ts file, when file is not present`, () => { @@ -1314,7 +1548,11 @@ ${dependencyTs.content}`, /*existingDocumentPositionMapperEqual*/ true, ); verifyScriptInfoCollectionWith(session, [dependencyTs]); - baselineTsserverLogs("projectReferencesSourcemap", "dependency/configHasNoReference/dependency dts not present", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "dependency/configHasNoReference/dependency dts not present", + session, + ); }); it(`with depedency .d.ts file, when file is created after actions on projects`, () => { let fileContents: string; @@ -1333,7 +1571,11 @@ ${dependencyTs.content}`, /*existingDocumentPositionMapperEqual*/ false, ); verifyScriptInfoCollectionWith(session, [dependencyTs]); - baselineTsserverLogs("projectReferencesSourcemap", "dependency/configHasNoReference/dependency dts created", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "dependency/configHasNoReference/dependency dts created", + session, + ); }); it(`with depedency .d.ts file, when file is deleted after actions on the projects`, () => { const { host, session, dependencyMap, documentPositionMapper } = setupWithAction(); @@ -1349,7 +1591,11 @@ ${dependencyTs.content}`, /*existingDocumentPositionMapperEqual*/ true, ); verifyScriptInfoCollectionWith(session, [dependencyTs]); - baselineTsserverLogs("projectReferencesSourcemap", "dependency/configHasNoReference/dependency dts deleted", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "dependency/configHasNoReference/dependency dts deleted", + session, + ); }); }); describe("when main tsconfig has project reference", () => { @@ -1372,7 +1618,11 @@ ${dependencyTs.content}`, /*existingDocumentPositionMapperEqual*/ false, ); verifyScriptInfoCollectionWith(session, [dependencyTs]); - baselineTsserverLogs("projectReferencesSourcemap", "dependency/configWithReference/rename locations", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "dependency/configWithReference/rename locations", + session, + ); }); // Edit @@ -1394,7 +1644,11 @@ ${dependencyTs.content}`, /*existingMapEqual*/ true, /*existingDocumentPositionMapperEqual*/ true, ); - baselineTsserverLogs("projectReferencesSourcemap", "dependency/configWithReference/usage file changes with timeout before request", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "dependency/configWithReference/usage file changes with timeout before request", + session, + ); }); it(`when usage file changes, document position mapper doesnt change, when timeout does not occur before request`, () => { // Create DocumentPositionMapper @@ -1412,7 +1666,11 @@ ${dependencyTs.content}`, /*existingMapEqual*/ true, /*existingDocumentPositionMapperEqual*/ true, ); - baselineTsserverLogs("projectReferencesSourcemap", "dependency/configWithReference/usage file changes", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "dependency/configWithReference/usage file changes", + session, + ); }); // Edit dts to add new fn @@ -1434,7 +1692,11 @@ ${dependencyTs.content}`, /*existingMapEqual*/ true, /*existingDocumentPositionMapperEqual*/ true, ); - baselineTsserverLogs("projectReferencesSourcemap", "dependency/configWithReference/dependency dts changes with timeout before request", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "dependency/configWithReference/dependency dts changes with timeout before request", + session, + ); }); it(`when dependency .d.ts changes, document position mapper doesnt change, when timeout does not occur before request`, () => { // Create DocumentPositionMapper @@ -1452,7 +1714,11 @@ ${dependencyTs.content}`, /*existingMapEqual*/ true, /*existingDocumentPositionMapperEqual*/ true, ); - baselineTsserverLogs("projectReferencesSourcemap", "dependency/configWithReference/dependency dts changes", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "dependency/configWithReference/dependency dts changes", + session, + ); }); // Edit map file to represent added new line @@ -1474,7 +1740,11 @@ ${dependencyTs.content}`, /*existingMapEqual*/ true, /*existingDocumentPositionMapperEqual*/ false, ); - baselineTsserverLogs("projectReferencesSourcemap", "dependency/configWithReference/dependency dtsMap changes with timeout before request", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "dependency/configWithReference/dependency dtsMap changes with timeout before request", + session, + ); }); it(`when dependency file's map changes, when timeout does not occur before request`, () => { // Create DocumentPositionMapper @@ -1492,7 +1762,11 @@ ${dependencyTs.content}`, /*existingMapEqual*/ true, /*existingDocumentPositionMapperEqual*/ false, ); - baselineTsserverLogs("projectReferencesSourcemap", "dependency/configWithReference/dependency dtsMap changes", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "dependency/configWithReference/dependency dtsMap changes", + session, + ); }); it(`with depedency files map file, when file is not present`, () => { @@ -1507,7 +1781,11 @@ ${dependencyTs.content}`, /*existingDocumentPositionMapperEqual*/ true, ); verifyScriptInfoCollectionWith(session, [dependencyTs]); - baselineTsserverLogs("projectReferencesSourcemap", "dependency/configWithReference/dependency dtsMap not present", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "dependency/configWithReference/dependency dtsMap not present", + session, + ); }); it(`with depedency files map file, when file is created after actions on projects`, () => { let fileContents: string; @@ -1526,7 +1804,11 @@ ${dependencyTs.content}`, /*existingDocumentPositionMapperEqual*/ false, ); verifyScriptInfoCollectionWith(session, [dependencyTs]); - baselineTsserverLogs("projectReferencesSourcemap", "dependency/configWithReference/dependency dtsMap created", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "dependency/configWithReference/dependency dtsMap created", + session, + ); }); it(`with depedency files map file, when file is deleted after actions on the projects`, () => { const { host, session, dependencyMap, documentPositionMapper } = setupWithAction(); @@ -1542,7 +1824,11 @@ ${dependencyTs.content}`, /*existingDocumentPositionMapperEqual*/ false, ); verifyScriptInfoCollectionWith(session, [dependencyTs]); - baselineTsserverLogs("projectReferencesSourcemap", "dependency/configWithReference/dependency dtsMap deleted", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "dependency/configWithReference/dependency dtsMap deleted", + session, + ); }); it(`with depedency .d.ts file, when file is not present`, () => { @@ -1557,7 +1843,11 @@ ${dependencyTs.content}`, /*existingDocumentPositionMapperEqual*/ true, ); verifyScriptInfoCollectionWith(session, [dependencyTs]); - baselineTsserverLogs("projectReferencesSourcemap", "dependency/configWithReference/dependency dts not present", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "dependency/configWithReference/dependency dts not present", + session, + ); }); it(`with depedency .d.ts file, when file is created after actions on projects`, () => { let fileContents: string; @@ -1576,7 +1866,11 @@ ${dependencyTs.content}`, /*existingDocumentPositionMapperEqual*/ false, ); verifyScriptInfoCollectionWith(session, [dependencyTs]); - baselineTsserverLogs("projectReferencesSourcemap", "dependency/configWithReference/dependency dts created", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "dependency/configWithReference/dependency dts created", + session, + ); }); it(`with depedency .d.ts file, when file is deleted after actions on the projects`, () => { const { host, session, dependencyMap, documentPositionMapper } = setupWithAction(); @@ -1592,7 +1886,11 @@ ${dependencyTs.content}`, /*existingDocumentPositionMapperEqual*/ true, ); verifyScriptInfoCollectionWith(session, [dependencyTs]); - baselineTsserverLogs("projectReferencesSourcemap", "dependency/configWithReference/dependency dts deleted", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "dependency/configWithReference/dependency dts deleted", + session, + ); }); it(`when defining project source changes, when timeout occurs before request`, () => { // Create DocumentPositionMapper @@ -1624,7 +1922,11 @@ ${dependencyTs.content}`, /*existingMapEqual*/ false, /*existingDocumentPositionMapperEqual*/ false, ); - baselineTsserverLogs("projectReferencesSourcemap", "dependency/configWithReference/dependency source changes with timeout before request", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "dependency/configWithReference/dependency source changes with timeout before request", + session, + ); }); it(`when defining project source changes, when timeout does not occur before request`, () => { // Create DocumentPositionMapper @@ -1654,7 +1956,11 @@ ${dependencyTs.content}`, /*existingMapEqual*/ false, /*existingDocumentPositionMapperEqual*/ false, ); - baselineTsserverLogs("projectReferencesSourcemap", "dependency/configWithReference/dependency source changes", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "dependency/configWithReference/dependency source changes", + session, + ); }); it("when projects are not built", () => { @@ -1670,7 +1976,11 @@ ${dependencyTs.content}`, /*existingDocumentPositionMapperEqual*/ true, ); verifyScriptInfoCollectionWith(session, [dependencyTs]); - baselineTsserverLogs("projectReferencesSourcemap", "dependency/configWithReference/when projects are not built", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "dependency/configWithReference/when projects are not built", + session, + ); }); }); describe("when main tsconfig has disableSourceOfProjectReferenceRedirect along with project reference", () => { @@ -1693,7 +2003,11 @@ ${dependencyTs.content}`, /*existingDocumentPositionMapperEqual*/ false, ); verifyScriptInfoCollectionWith(session, [dependencyTs]); - baselineTsserverLogs("projectReferencesSourcemap", "dependency/disabledSourceRef/rename locations", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "dependency/disabledSourceRef/rename locations", + session, + ); }); // Edit @@ -1715,7 +2029,11 @@ ${dependencyTs.content}`, /*existingMapEqual*/ true, /*existingDocumentPositionMapperEqual*/ true, ); - baselineTsserverLogs("projectReferencesSourcemap", "dependency/disabledSourceRef/usage file changes with timeout before request", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "dependency/disabledSourceRef/usage file changes with timeout before request", + session, + ); }); it(`when usage file changes, document position mapper doesnt change, when timeout does not occur before request`, () => { // Create DocumentPositionMapper @@ -1733,7 +2051,11 @@ ${dependencyTs.content}`, /*existingMapEqual*/ true, /*existingDocumentPositionMapperEqual*/ true, ); - baselineTsserverLogs("projectReferencesSourcemap", "dependency/disabledSourceRef/usage file changes", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "dependency/disabledSourceRef/usage file changes", + session, + ); }); // Edit dts to add new fn @@ -1755,7 +2077,11 @@ ${dependencyTs.content}`, /*existingMapEqual*/ true, /*existingDocumentPositionMapperEqual*/ true, ); - baselineTsserverLogs("projectReferencesSourcemap", "dependency/disabledSourceRef/dependency dts changes with timeout before request", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "dependency/disabledSourceRef/dependency dts changes with timeout before request", + session, + ); }); it(`when dependency .d.ts changes, document position mapper doesnt change, when timeout does not occur before request`, () => { // Create DocumentPositionMapper @@ -1773,7 +2099,11 @@ ${dependencyTs.content}`, /*existingMapEqual*/ true, /*existingDocumentPositionMapperEqual*/ true, ); - baselineTsserverLogs("projectReferencesSourcemap", "dependency/disabledSourceRef/dependency dts changes", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "dependency/disabledSourceRef/dependency dts changes", + session, + ); }); // Edit map file to represent added new line @@ -1795,7 +2125,11 @@ ${dependencyTs.content}`, /*existingMapEqual*/ true, /*existingDocumentPositionMapperEqual*/ false, ); - baselineTsserverLogs("projectReferencesSourcemap", "dependency/disabledSourceRef/dependency dtsMap changes with timeout before request", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "dependency/disabledSourceRef/dependency dtsMap changes with timeout before request", + session, + ); }); it(`when dependency file's map changes, when timeout does not occur before request`, () => { // Create DocumentPositionMapper @@ -1813,7 +2147,11 @@ ${dependencyTs.content}`, /*existingMapEqual*/ true, /*existingDocumentPositionMapperEqual*/ false, ); - baselineTsserverLogs("projectReferencesSourcemap", "dependency/disabledSourceRef/dependency dtsMap changes", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "dependency/disabledSourceRef/dependency dtsMap changes", + session, + ); }); it(`with depedency files map file, when file is not present`, () => { @@ -1828,7 +2166,11 @@ ${dependencyTs.content}`, /*existingDocumentPositionMapperEqual*/ true, ); verifyScriptInfoCollectionWith(session, [dependencyTs]); - baselineTsserverLogs("projectReferencesSourcemap", "dependency/disabledSourceRef/dependency dtsMap not present", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "dependency/disabledSourceRef/dependency dtsMap not present", + session, + ); }); it(`with depedency files map file, when file is created after actions on projects`, () => { let fileContents: string; @@ -1847,7 +2189,11 @@ ${dependencyTs.content}`, /*existingDocumentPositionMapperEqual*/ false, ); verifyScriptInfoCollectionWith(session, [dependencyTs]); - baselineTsserverLogs("projectReferencesSourcemap", "dependency/disabledSourceRef/dependency dtsMap created", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "dependency/disabledSourceRef/dependency dtsMap created", + session, + ); }); it(`with depedency files map file, when file is deleted after actions on the projects`, () => { const { host, session, dependencyMap, documentPositionMapper } = setupWithAction(); @@ -1863,7 +2209,11 @@ ${dependencyTs.content}`, /*existingDocumentPositionMapperEqual*/ false, ); verifyScriptInfoCollectionWith(session, [dependencyTs]); - baselineTsserverLogs("projectReferencesSourcemap", "dependency/disabledSourceRef/dependency dtsMap deleted", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "dependency/disabledSourceRef/dependency dtsMap deleted", + session, + ); }); it(`with depedency .d.ts file, when file is not present`, () => { @@ -1878,7 +2228,11 @@ ${dependencyTs.content}`, /*existingDocumentPositionMapperEqual*/ true, ); verifyScriptInfoCollectionWith(session, [dependencyTs]); - baselineTsserverLogs("projectReferencesSourcemap", "dependency/disabledSourceRef/dependency dts not present", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "dependency/disabledSourceRef/dependency dts not present", + session, + ); }); it(`with depedency .d.ts file, when file is created after actions on projects`, () => { let fileContents: string; @@ -1897,7 +2251,11 @@ ${dependencyTs.content}`, /*existingDocumentPositionMapperEqual*/ false, ); verifyScriptInfoCollectionWith(session, [dependencyTs]); - baselineTsserverLogs("projectReferencesSourcemap", "dependency/disabledSourceRef/dependency dts created", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "dependency/disabledSourceRef/dependency dts created", + session, + ); }); it(`with depedency .d.ts file, when file is deleted after actions on the projects`, () => { const { host, session, dependencyMap, documentPositionMapper } = setupWithAction(); @@ -1913,13 +2271,20 @@ ${dependencyTs.content}`, /*existingDocumentPositionMapperEqual*/ true, ); verifyScriptInfoCollectionWith(session, [dependencyTs]); - baselineTsserverLogs("projectReferencesSourcemap", "dependency/disabledSourceRef/dependency dts deleted", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "dependency/disabledSourceRef/dependency dts deleted", + session, + ); }); }); }); describe("when opening depedency and usage project: goToDef and rename", () => { - function setupWithActionWith(setup: (onHostCreate?: OnHostCreate) => ReturnType, onHostCreate: OnHostCreate | undefined) { + function setupWithActionWith( + setup: (onHostCreate?: OnHostCreate) => ReturnType, + onHostCreate: OnHostCreate | undefined, + ) { const result = setup(onHostCreate); result.session.executeCommandSeq(goToDefFromMainTs(1)); result.session.executeCommandSeq(renameFromDependencyTs(1)); @@ -1955,7 +2320,11 @@ ${dependencyTs.content}`, /*existingDocumentPositionMapperEqual*/ true, ); verifyScriptInfoCollectionWith(session, [mainTs, dependencyTs]); - baselineTsserverLogs("projectReferencesSourcemap", "dependencyAndUsage/configHasNoReference/goToDef and rename locations", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "dependencyAndUsage/configHasNoReference/goToDef and rename locations", + session, + ); }); // Edit @@ -1986,7 +2355,11 @@ ${dependencyTs.content}`, /*existingMapEqual*/ true, /*existingDocumentPositionMapperEqual*/ true, ); - baselineTsserverLogs("projectReferencesSourcemap", "dependencyAndUsage/configHasNoReference/usage file changes with timeout before request", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "dependencyAndUsage/configHasNoReference/usage file changes with timeout before request", + session, + ); }); it(`when usage file changes, document position mapper doesnt change, when timeout does not occur before request`, () => { // Create DocumentPositionMapper @@ -2013,7 +2386,11 @@ ${dependencyTs.content}`, /*existingMapEqual*/ true, /*existingDocumentPositionMapperEqual*/ true, ); - baselineTsserverLogs("projectReferencesSourcemap", "dependencyAndUsage/configHasNoReference/usage file changes", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "dependencyAndUsage/configHasNoReference/usage file changes", + session, + ); }); // Edit dts to add new fn @@ -2043,7 +2420,11 @@ ${dependencyTs.content}`, /*existingMapEqual*/ true, /*existingDocumentPositionMapperEqual*/ true, ); - baselineTsserverLogs("projectReferencesSourcemap", "dependencyAndUsage/configHasNoReference/dependency dts changes with timeout before request", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "dependencyAndUsage/configHasNoReference/dependency dts changes with timeout before request", + session, + ); }); it(`when dependency .d.ts changes, document position mapper doesnt change, when timeout does not occur before request`, () => { // Create DocumentPositionMapper @@ -2069,7 +2450,11 @@ ${dependencyTs.content}`, /*existingMapEqual*/ true, /*existingDocumentPositionMapperEqual*/ true, ); - baselineTsserverLogs("projectReferencesSourcemap", "dependencyAndUsage/configHasNoReference/dependency dts changes", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "dependencyAndUsage/configHasNoReference/dependency dts changes", + session, + ); }); // Edit map file to represent added new line @@ -2100,7 +2485,11 @@ ${dependencyTs.content}`, /*existingMapEqual*/ true, /*existingDocumentPositionMapperEqual*/ true, ); - baselineTsserverLogs("projectReferencesSourcemap", "dependencyAndUsage/configHasNoReference/dependency dtsMap changes with timeout before request", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "dependencyAndUsage/configHasNoReference/dependency dtsMap changes with timeout before request", + session, + ); }); it(`when dependency file's map changes, when timeout does not occur before request`, () => { // Create DocumentPositionMapper @@ -2127,7 +2516,11 @@ ${dependencyTs.content}`, /*existingMapEqual*/ true, /*existingDocumentPositionMapperEqual*/ true, ); - baselineTsserverLogs("projectReferencesSourcemap", "dependencyAndUsage/configHasNoReference/dependency dtsMap changes", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "dependencyAndUsage/configHasNoReference/dependency dtsMap changes", + session, + ); }); it(`with depedency files map file, when file is not present`, () => { @@ -2150,7 +2543,11 @@ ${dependencyTs.content}`, /*existingDocumentPositionMapperEqual*/ true, ); verifyScriptInfoCollectionWith(session, [mainTs, dependencyTs]); - baselineTsserverLogs("projectReferencesSourcemap", "dependencyAndUsage/configHasNoReference/dependency dtsMap not present", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "dependencyAndUsage/configHasNoReference/dependency dtsMap not present", + session, + ); }); it(`with depedency files map file, when file is created after actions on projects`, () => { let fileContents: string; @@ -2168,7 +2565,8 @@ ${dependencyTs.content}`, /*existingMapEqual*/ false, /*existingDocumentPositionMapperEqual*/ false, ); - const { dependencyMap: newDependencyMap, documentPositionMapper: newDocumentPositionMapper } = getDocumentPositionMapper(session); + const { dependencyMap: newDependencyMap, documentPositionMapper: newDocumentPositionMapper } = + getDocumentPositionMapper(session); verifyAllFnAction( session, renameFromDependencyTs, @@ -2178,7 +2576,11 @@ ${dependencyTs.content}`, /*existingDocumentPositionMapperEqual*/ true, ); verifyScriptInfoCollectionWith(session, [mainTs, dependencyTs]); - baselineTsserverLogs("projectReferencesSourcemap", "dependencyAndUsage/configHasNoReference/dependency dtsMap created", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "dependencyAndUsage/configHasNoReference/dependency dtsMap created", + session, + ); }); it(`with depedency files map file, when file is deleted after actions on the projects`, () => { const { host, session, dependencyMap, documentPositionMapper } = setupWithAction(); @@ -2193,7 +2595,8 @@ ${dependencyTs.content}`, /*existingMapEqual*/ false, /*existingDocumentPositionMapperEqual*/ false, ); - const { dependencyMap: newDependencyMap, documentPositionMapper: newDocumentPositionMapper } = getDocumentPositionMapper(session); + const { dependencyMap: newDependencyMap, documentPositionMapper: newDocumentPositionMapper } = + getDocumentPositionMapper(session); verifyAllFnAction( session, renameFromDependencyTs, @@ -2203,7 +2606,11 @@ ${dependencyTs.content}`, /*existingDocumentPositionMapperEqual*/ true, ); verifyScriptInfoCollectionWith(session, [mainTs, dependencyTs]); - baselineTsserverLogs("projectReferencesSourcemap", "dependencyAndUsage/configHasNoReference/dependency dtsMap deleted", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "dependencyAndUsage/configHasNoReference/dependency dtsMap deleted", + session, + ); }); it(`with depedency .d.ts file, when file is not present`, () => { @@ -2225,7 +2632,11 @@ ${dependencyTs.content}`, /*existingDocumentPositionMapperEqual*/ true, ); verifyScriptInfoCollectionWith(session, [mainTs, dependencyTs]); - baselineTsserverLogs("projectReferencesSourcemap", "dependencyAndUsage/configHasNoReference/dependency dts not present", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "dependencyAndUsage/configHasNoReference/dependency dts not present", + session, + ); }); it(`with depedency .d.ts file, when file is created after actions on projects`, () => { let fileContents: string; @@ -2243,7 +2654,8 @@ ${dependencyTs.content}`, /*existingMapEqual*/ false, /*existingDocumentPositionMapperEqual*/ false, ); - const { dependencyMap: newDependencyMap, documentPositionMapper: newDocumentPositionMapper } = getDocumentPositionMapper(session); + const { dependencyMap: newDependencyMap, documentPositionMapper: newDocumentPositionMapper } = + getDocumentPositionMapper(session); verifyAllFnAction( session, renameFromDependencyTs, @@ -2253,7 +2665,11 @@ ${dependencyTs.content}`, /*existingDocumentPositionMapperEqual*/ true, ); verifyScriptInfoCollectionWith(session, [mainTs, dependencyTs]); - baselineTsserverLogs("projectReferencesSourcemap", "dependencyAndUsage/configHasNoReference/dependency dts created", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "dependencyAndUsage/configHasNoReference/dependency dts created", + session, + ); }); it(`with depedency .d.ts file, when file is deleted after actions on the projects`, () => { const { host, session, dependencyMap, documentPositionMapper } = setupWithAction(); @@ -2277,7 +2693,11 @@ ${dependencyTs.content}`, /*existingDocumentPositionMapperEqual*/ true, ); verifyScriptInfoCollectionWith(session, [mainTs, dependencyTs]); - baselineTsserverLogs("projectReferencesSourcemap", "dependencyAndUsage/configHasNoReference/dependency dts deleted", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "dependencyAndUsage/configHasNoReference/dependency dts deleted", + session, + ); }); }); describe("when main tsconfig has project reference", () => { @@ -2308,7 +2728,11 @@ ${dependencyTs.content}`, /*existingDocumentPositionMapperEqual*/ false, ); verifyScriptInfoCollectionWith(session, [mainTs, dependencyTs]); - baselineTsserverLogs("projectReferencesSourcemap", "dependencyAndUsage/configWithReference/gotoDef and rename locations", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "dependencyAndUsage/configWithReference/gotoDef and rename locations", + session, + ); }); // Edit @@ -2339,7 +2763,11 @@ ${dependencyTs.content}`, /*existingMapEqual*/ true, /*existingDocumentPositionMapperEqual*/ true, ); - baselineTsserverLogs("projectReferencesSourcemap", "dependencyAndUsage/configWithReference/usage file changes with timeout before request", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "dependencyAndUsage/configWithReference/usage file changes with timeout before request", + session, + ); }); it(`when usage file changes, document position mapper doesnt change, when timeout does not occur before request`, () => { // Create DocumentPositionMapper @@ -2366,7 +2794,11 @@ ${dependencyTs.content}`, /*existingMapEqual*/ true, /*existingDocumentPositionMapperEqual*/ true, ); - baselineTsserverLogs("projectReferencesSourcemap", "dependencyAndUsage/configWithReference/usage file changes", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "dependencyAndUsage/configWithReference/usage file changes", + session, + ); }); // Edit dts to add new fn @@ -2396,7 +2828,11 @@ ${dependencyTs.content}`, /*existingMapEqual*/ true, /*existingDocumentPositionMapperEqual*/ true, ); - baselineTsserverLogs("projectReferencesSourcemap", "dependencyAndUsage/configWithReference/dependency dts changes with timeout before request", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "dependencyAndUsage/configWithReference/dependency dts changes with timeout before request", + session, + ); }); it(`when dependency .d.ts changes, document position mapper doesnt change, when timeout does not occur before request`, () => { // Create DocumentPositionMapper @@ -2422,7 +2858,11 @@ ${dependencyTs.content}`, /*existingMapEqual*/ true, /*existingDocumentPositionMapperEqual*/ true, ); - baselineTsserverLogs("projectReferencesSourcemap", "dependencyAndUsage/configWithReference/dependency dts changes", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "dependencyAndUsage/configWithReference/dependency dts changes", + session, + ); }); // Edit map file to represent added new line @@ -2452,7 +2892,11 @@ ${dependencyTs.content}`, /*existingMapEqual*/ true, /*existingDocumentPositionMapperEqual*/ false, ); - baselineTsserverLogs("projectReferencesSourcemap", "dependencyAndUsage/configWithReference/dependency dtsMap changes with timeout before request", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "dependencyAndUsage/configWithReference/dependency dtsMap changes with timeout before request", + session, + ); }); it(`when dependency file's map changes, when timeout does not occur before request`, () => { // Create DocumentPositionMapper @@ -2478,7 +2922,11 @@ ${dependencyTs.content}`, /*existingMapEqual*/ true, /*existingDocumentPositionMapperEqual*/ false, ); - baselineTsserverLogs("projectReferencesSourcemap", "dependencyAndUsage/configWithReference/dependency dtsMap changes", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "dependencyAndUsage/configWithReference/dependency dtsMap changes", + session, + ); }); it(`with depedency files map file, when file is not present`, () => { @@ -2501,7 +2949,11 @@ ${dependencyTs.content}`, /*existingDocumentPositionMapperEqual*/ true, ); verifyScriptInfoCollectionWith(session, [mainTs, dependencyTs]); - baselineTsserverLogs("projectReferencesSourcemap", "dependencyAndUsage/configWithReference/dependency dtsMap not present", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "dependencyAndUsage/configWithReference/dependency dtsMap not present", + session, + ); }); it(`with depedency files map file, when file is created after actions on projects`, () => { let fileContents: string; @@ -2529,7 +2981,11 @@ ${dependencyTs.content}`, /*existingDocumentPositionMapperEqual*/ false, ); verifyScriptInfoCollectionWith(session, [mainTs, dependencyTs]); - baselineTsserverLogs("projectReferencesSourcemap", "dependencyAndUsage/configWithReference/dependency dtsMap created", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "dependencyAndUsage/configWithReference/dependency dtsMap created", + session, + ); }); it(`with depedency files map file, when file is deleted after actions on the projects`, () => { const { host, session, dependencyMap, documentPositionMapper } = setupWithAction(); @@ -2554,7 +3010,11 @@ ${dependencyTs.content}`, /*existingDocumentPositionMapperEqual*/ false, ); verifyScriptInfoCollectionWith(session, [mainTs, dependencyTs]); - baselineTsserverLogs("projectReferencesSourcemap", "dependencyAndUsage/configWithReference/dependency dtsMap deleted", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "dependencyAndUsage/configWithReference/dependency dtsMap deleted", + session, + ); }); it(`with depedency .d.ts file, when file is not present`, () => { @@ -2577,7 +3037,11 @@ ${dependencyTs.content}`, /*existingDocumentPositionMapperEqual*/ true, ); verifyScriptInfoCollectionWith(session, [mainTs, dependencyTs]); - baselineTsserverLogs("projectReferencesSourcemap", "dependencyAndUsage/configWithReference/dependency dts not present", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "dependencyAndUsage/configWithReference/dependency dts not present", + session, + ); }); it(`with depedency .d.ts file, when file is created after actions on projects`, () => { let fileContents: string; @@ -2604,7 +3068,11 @@ ${dependencyTs.content}`, /*existingDocumentPositionMapperEqual*/ false, ); verifyScriptInfoCollectionWith(session, [mainTs, dependencyTs]); - baselineTsserverLogs("projectReferencesSourcemap", "dependencyAndUsage/configWithReference/dependency dts created", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "dependencyAndUsage/configWithReference/dependency dts created", + session, + ); }); it(`with depedency .d.ts file, when file is deleted after actions on the projects`, () => { const { host, session, dependencyMap, documentPositionMapper } = setupWithAction(); @@ -2628,7 +3096,11 @@ ${dependencyTs.content}`, /*existingDocumentPositionMapperEqual*/ true, ); verifyScriptInfoCollectionWith(session, [mainTs, dependencyTs]); - baselineTsserverLogs("projectReferencesSourcemap", "dependencyAndUsage/configWithReference/dependency dts deleted", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "dependencyAndUsage/configWithReference/dependency dts deleted", + session, + ); }); it(`when defining project source changes, when timeout occurs before request`, () => { // Create DocumentPositionMapper @@ -2668,7 +3140,11 @@ ${dependencyTs.content}`, /*existingMapEqual*/ true, /*existingDocumentPositionMapperEqual*/ true, ); - baselineTsserverLogs("projectReferencesSourcemap", "dependencyAndUsage/configWithReference/dependency source changes with timeout before request", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "dependencyAndUsage/configWithReference/dependency source changes with timeout before request", + session, + ); }); it(`when defining project source changes, when timeout does not occur before request`, () => { // Create DocumentPositionMapper @@ -2706,7 +3182,11 @@ ${dependencyTs.content}`, /*existingMapEqual*/ true, /*existingDocumentPositionMapperEqual*/ true, ); - baselineTsserverLogs("projectReferencesSourcemap", "dependencyAndUsage/configWithReference/dependency source changes", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "dependencyAndUsage/configWithReference/dependency source changes", + session, + ); }); it("when projects are not built", () => { @@ -2730,7 +3210,11 @@ ${dependencyTs.content}`, /*existingDocumentPositionMapperEqual*/ true, ); verifyScriptInfoCollectionWith(session, [mainTs, dependencyTs]); - baselineTsserverLogs("projectReferencesSourcemap", "dependencyAndUsage/configWithReference/when projects are not built", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "dependencyAndUsage/configWithReference/when projects are not built", + session, + ); }); }); describe("when main tsconfig has disableSourceOfProjectReferenceRedirect along with project reference", () => { @@ -2762,7 +3246,11 @@ ${dependencyTs.content}`, /*existingDocumentPositionMapperEqual*/ true, ); verifyScriptInfoCollectionWith(session, [mainTs, dependencyTs]); - baselineTsserverLogs("projectReferencesSourcemap", "dependencyAndUsage/disabledSourceRef/gotoDef and rename locations", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "dependencyAndUsage/disabledSourceRef/gotoDef and rename locations", + session, + ); }); // Edit @@ -2793,7 +3281,11 @@ ${dependencyTs.content}`, /*existingMapEqual*/ true, /*existingDocumentPositionMapperEqual*/ true, ); - baselineTsserverLogs("projectReferencesSourcemap", "dependencyAndUsage/disabledSourceRef/usage file changes with timeout before request", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "dependencyAndUsage/disabledSourceRef/usage file changes with timeout before request", + session, + ); }); it(`when usage file changes, document position mapper doesnt change, when timeout does not occur before request`, () => { // Create DocumentPositionMapper @@ -2820,7 +3312,11 @@ ${dependencyTs.content}`, /*existingMapEqual*/ true, /*existingDocumentPositionMapperEqual*/ true, ); - baselineTsserverLogs("projectReferencesSourcemap", "dependencyAndUsage/disabledSourceRef/usage file changes", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "dependencyAndUsage/disabledSourceRef/usage file changes", + session, + ); }); // Edit dts to add new fn @@ -2850,7 +3346,11 @@ ${dependencyTs.content}`, /*existingMapEqual*/ true, /*existingDocumentPositionMapperEqual*/ true, ); - baselineTsserverLogs("projectReferencesSourcemap", "dependencyAndUsage/disabledSourceRef/dependency dts changes with timeout before request", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "dependencyAndUsage/disabledSourceRef/dependency dts changes with timeout before request", + session, + ); }); it(`when dependency .d.ts changes, document position mapper doesnt change, when timeout does not occur before request`, () => { // Create DocumentPositionMapper @@ -2876,7 +3376,11 @@ ${dependencyTs.content}`, /*existingMapEqual*/ true, /*existingDocumentPositionMapperEqual*/ true, ); - baselineTsserverLogs("projectReferencesSourcemap", "dependencyAndUsage/disabledSourceRef/dependency dts changes", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "dependencyAndUsage/disabledSourceRef/dependency dts changes", + session, + ); }); // Edit map file to represent added new line @@ -2907,7 +3411,11 @@ ${dependencyTs.content}`, /*existingMapEqual*/ true, /*existingDocumentPositionMapperEqual*/ true, ); - baselineTsserverLogs("projectReferencesSourcemap", "dependencyAndUsage/disabledSourceRef/dependency dtsMap changes with timeout before request", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "dependencyAndUsage/disabledSourceRef/dependency dtsMap changes with timeout before request", + session, + ); }); it(`when dependency file's map changes, when timeout does not occur before request`, () => { // Create DocumentPositionMapper @@ -2934,7 +3442,11 @@ ${dependencyTs.content}`, /*existingMapEqual*/ true, /*existingDocumentPositionMapperEqual*/ true, ); - baselineTsserverLogs("projectReferencesSourcemap", "dependencyAndUsage/disabledSourceRef/dependency dtsMap changes", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "dependencyAndUsage/disabledSourceRef/dependency dtsMap changes", + session, + ); }); it(`with depedency files map file, when file is not present`, () => { @@ -2957,7 +3469,11 @@ ${dependencyTs.content}`, /*existingDocumentPositionMapperEqual*/ true, ); verifyScriptInfoCollectionWith(session, [mainTs, dependencyTs]); - baselineTsserverLogs("projectReferencesSourcemap", "dependencyAndUsage/disabledSourceRef/dependency dtsMap not present", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "dependencyAndUsage/disabledSourceRef/dependency dtsMap not present", + session, + ); }); it(`with depedency files map file, when file is created after actions on projects`, () => { let fileContents: string; @@ -2975,7 +3491,8 @@ ${dependencyTs.content}`, /*existingMapEqual*/ false, /*existingDocumentPositionMapperEqual*/ false, ); - const { dependencyMap: newDependencyMap, documentPositionMapper: newDocumentPositionMapper } = getDocumentPositionMapper(session); + const { dependencyMap: newDependencyMap, documentPositionMapper: newDocumentPositionMapper } = + getDocumentPositionMapper(session); verifyAllFnAction( session, renameFromDependencyTs, @@ -2985,7 +3502,11 @@ ${dependencyTs.content}`, /*existingDocumentPositionMapperEqual*/ true, ); verifyScriptInfoCollectionWith(session, [mainTs, dependencyTs]); - baselineTsserverLogs("projectReferencesSourcemap", "dependencyAndUsage/disabledSourceRef/dependency dtsMap created", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "dependencyAndUsage/disabledSourceRef/dependency dtsMap created", + session, + ); }); it(`with depedency files map file, when file is deleted after actions on the projects`, () => { const { host, session, dependencyMap, documentPositionMapper } = setupWithAction(); @@ -3000,7 +3521,8 @@ ${dependencyTs.content}`, /*existingMapEqual*/ false, /*existingDocumentPositionMapperEqual*/ false, ); - const { dependencyMap: newDependencyMap, documentPositionMapper: newDocumentPositionMapper } = getDocumentPositionMapper(session); + const { dependencyMap: newDependencyMap, documentPositionMapper: newDocumentPositionMapper } = + getDocumentPositionMapper(session); verifyAllFnAction( session, renameFromDependencyTs, @@ -3010,7 +3532,11 @@ ${dependencyTs.content}`, /*existingDocumentPositionMapperEqual*/ true, ); verifyScriptInfoCollectionWith(session, [mainTs, dependencyTs]); - baselineTsserverLogs("projectReferencesSourcemap", "dependencyAndUsage/disabledSourceRef/dependency dtsMap deleted", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "dependencyAndUsage/disabledSourceRef/dependency dtsMap deleted", + session, + ); }); it(`with depedency .d.ts file, when file is not present`, () => { @@ -3033,7 +3559,11 @@ ${dependencyTs.content}`, /*existingDocumentPositionMapperEqual*/ true, ); verifyScriptInfoCollectionWith(session, [mainTs, dependencyTs]); - baselineTsserverLogs("projectReferencesSourcemap", "dependencyAndUsage/disabledSourceRef/dependency dts not present", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "dependencyAndUsage/disabledSourceRef/dependency dts not present", + session, + ); }); it(`with depedency .d.ts file, when file is created after actions on projects`, () => { let fileContents: string; @@ -3051,7 +3581,8 @@ ${dependencyTs.content}`, /*existingMapEqual*/ false, /*existingDocumentPositionMapperEqual*/ false, ); - const { dependencyMap: newDependencyMap, documentPositionMapper: newDocumentPositionMapper } = getDocumentPositionMapper(session); + const { dependencyMap: newDependencyMap, documentPositionMapper: newDocumentPositionMapper } = + getDocumentPositionMapper(session); verifyAllFnAction( session, renameFromDependencyTs, @@ -3061,7 +3592,11 @@ ${dependencyTs.content}`, /*existingDocumentPositionMapperEqual*/ true, ); verifyScriptInfoCollectionWith(session, [mainTs, dependencyTs]); - baselineTsserverLogs("projectReferencesSourcemap", "dependencyAndUsage/disabledSourceRef/dependency dts created", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "dependencyAndUsage/disabledSourceRef/dependency dts created", + session, + ); }); it(`with depedency .d.ts file, when file is deleted after actions on the projects`, () => { const { host, session, dependencyMap, documentPositionMapper } = setupWithAction(); @@ -3085,7 +3620,11 @@ ${dependencyTs.content}`, /*existingDocumentPositionMapperEqual*/ true, ); verifyScriptInfoCollectionWith(session, [mainTs, dependencyTs]); - baselineTsserverLogs("projectReferencesSourcemap", "dependencyAndUsage/disabledSourceRef/dependency dts deleted", session); + baselineTsserverLogs( + "projectReferencesSourcemap", + "dependencyAndUsage/disabledSourceRef/dependency dts deleted", + session, + ); }); }); }); diff --git a/src/testRunner/unittests/tsserver/projects.ts b/src/testRunner/unittests/tsserver/projects.ts index fa3203176d90e..345d795292a4a 100644 --- a/src/testRunner/unittests/tsserver/projects.ts +++ b/src/testRunner/unittests/tsserver/projects.ts @@ -75,7 +75,11 @@ describe("unittests:: tsserver:: projects::", () => { host.runQueuedTimeoutCallbacks(); // Update the configured project + refresh inferred projects openFilesForSession([commonFile2], session); - baselineTsserverLogs("projects", "should create new inferred projects for files excluded from a configured project", session); + baselineTsserverLogs( + "projects", + "should create new inferred projects for files excluded from a configured project", + session, + ); }); it("should disable features when the files are too large", () => { @@ -100,11 +104,23 @@ describe("unittests:: tsserver:: projects::", () => { const host = createServerHost([file1, file2, file3]); const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) }); - openExternalProjectForSession({ rootFiles: toExternalFiles([file1.path]), options: {}, projectFileName: proj1name }, session); + openExternalProjectForSession({ + rootFiles: toExternalFiles([file1.path]), + options: {}, + projectFileName: proj1name, + }, session); - openExternalProjectForSession({ rootFiles: toExternalFiles([file2.path]), options: {}, projectFileName: proj2name }, session); + openExternalProjectForSession({ + rootFiles: toExternalFiles([file2.path]), + options: {}, + projectFileName: proj2name, + }, session); - openExternalProjectForSession({ rootFiles: toExternalFiles([file3.path]), options: {}, projectFileName: proj3name }, session); + openExternalProjectForSession({ + rootFiles: toExternalFiles([file3.path]), + options: {}, + projectFileName: proj3name, + }, session); baselineTsserverLogs("projects", "should disable features when the files are too large", session); }); @@ -123,12 +139,23 @@ describe("unittests:: tsserver:: projects::", () => { const projName = "proj1"; const host = createServerHost([file1, file2]); - const session = createSession(host, { useSingleInferredProject: true, logger: createLoggerWithInMemoryLogs(host) }); + const session = createSession(host, { + useSingleInferredProject: true, + logger: createLoggerWithInMemoryLogs(host), + }); - openExternalProjectForSession({ rootFiles: toExternalFiles([file1.path, file2.path]), options: {}, projectFileName: projName }, session); + openExternalProjectForSession({ + rootFiles: toExternalFiles([file1.path, file2.path]), + options: {}, + projectFileName: projName, + }, session); openFilesForSession([file2], session); - baselineTsserverLogs("projects", "should not crash when opening a file in a project with a disabled language service", session); + baselineTsserverLogs( + "projects", + "should not crash when opening a file in a project with a disabled language service", + session, + ); }); describe("ignoreConfigFiles", () => { @@ -149,7 +176,11 @@ describe("unittests:: tsserver:: projects::", () => { const externalProjectName = "externalproject"; const host = createServerHost([file1, config1]); - const projectService = createProjectService(host, { useSingleInferredProject: true, serverMode: ts.LanguageServiceMode.Syntactic, logger: createLoggerWithInMemoryLogs(host) }); + const projectService = createProjectService(host, { + useSingleInferredProject: true, + serverMode: ts.LanguageServiceMode.Syntactic, + logger: createLoggerWithInMemoryLogs(host), + }); projectService.openExternalProject({ rootFiles: toExternalFiles([file1.path, config1.path]), options: {}, @@ -175,7 +206,11 @@ describe("unittests:: tsserver:: projects::", () => { }; const host = createServerHost([file1, config1]); - const projectService = createProjectService(host, { useSingleInferredProject: true, serverMode: ts.LanguageServiceMode.Syntactic, logger: createLoggerWithInMemoryLogs(host) }); + const projectService = createProjectService(host, { + useSingleInferredProject: true, + serverMode: ts.LanguageServiceMode.Syntactic, + logger: createLoggerWithInMemoryLogs(host), + }); projectService.openClientFile(file1.path, file1.content); baselineTsserverLogs("projects", "loose file included in config file (openClientFile)", projectService); }); @@ -196,7 +231,11 @@ describe("unittests:: tsserver:: projects::", () => { }; const host = createServerHost([file1, config1]); - const projectService = createProjectService(host, { useSingleInferredProject: true, serverMode: ts.LanguageServiceMode.Syntactic, logger: createLoggerWithInMemoryLogs(host) }); + const projectService = createProjectService(host, { + useSingleInferredProject: true, + serverMode: ts.LanguageServiceMode.Syntactic, + logger: createLoggerWithInMemoryLogs(host), + }); projectService.applyChangesInOpenFiles(ts.singleIterator({ fileName: file1.path, content: file1.content })); baselineTsserverLogs("projects", "loose file included in config file (applyCodeChanges)", projectService); @@ -215,7 +254,11 @@ describe("unittests:: tsserver:: projects::", () => { const host = createServerHost([f1, f2, libFile]); const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) }); - openExternalProjectForSession({ projectFileName: "/a/b/project", rootFiles: toExternalFiles([f1.path, f2.path]), options: {} }, session); + openExternalProjectForSession({ + projectFileName: "/a/b/project", + rootFiles: toExternalFiles([f1.path, f2.path]), + options: {}, + }, session); openFilesForSession([f1, { file: f2.path, content: "let x: string" }], session); // should contain completions for string @@ -245,7 +288,11 @@ describe("unittests:: tsserver:: projects::", () => { const host = createServerHost([f1, f2, libFile]); const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) }); - openExternalProjectForSession({ projectFileName: "/a/b/project", rootFiles: [{ fileName: f1.path }, { fileName: f2.path, hasMixedContent: true }], options: {} }, session); + openExternalProjectForSession({ + projectFileName: "/a/b/project", + rootFiles: [{ fileName: f1.path }, { fileName: f2.path, hasMixedContent: true }], + options: {}, + }, session); openFilesForSession([f1, { file: f2.path, content: "let somelongname: string" }], session); session.executeCommandSeq({ @@ -323,8 +370,16 @@ describe("unittests:: tsserver:: projects::", () => { const host = createServerHost([file1, office, customTypesMap]); const projectService = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) }); try { - projectService.openExternalProject({ projectFileName: "project", options: {}, rootFiles: toExternalFiles([file1.path, office.path]) }); - projectService.logger.log(`TypeAcquisition:: ${JSON.stringify(projectService.externalProjects[0].getTypeAcquisition(), undefined, " ")}`); + projectService.openExternalProject({ + projectFileName: "project", + options: {}, + rootFiles: toExternalFiles([file1.path, office.path]), + }); + projectService.logger.log( + `TypeAcquisition:: ${ + JSON.stringify(projectService.externalProjects[0].getTypeAcquisition(), undefined, " ") + }`, + ); } finally { projectService.resetSafeList(); @@ -353,7 +408,14 @@ describe("unittests:: tsserver:: projects::", () => { installPackage: ts.notImplemented, enqueueInstallTypingsRequest: (proj, typeAcquisition, unresolvedImports) => { assert.isUndefined(request); - request = JSON.stringify(ts.server.createInstallTypingsRequest(proj, typeAcquisition, unresolvedImports || ts.server.emptyArray, cachePath)); + request = JSON.stringify( + ts.server.createInstallTypingsRequest( + proj, + typeAcquisition, + unresolvedImports || ts.server.emptyArray, + cachePath, + ), + ); }, attach: ts.noop, onProjectClosed: ts.noop, @@ -361,8 +423,15 @@ describe("unittests:: tsserver:: projects::", () => { }; const projectName = "project"; - const projectService = createProjectService(host, { typingsInstaller, logger: createLoggerWithInMemoryLogs(host) }); - projectService.openExternalProject({ projectFileName: projectName, options: {}, rootFiles: toExternalFiles([file1.path, constructorFile.path, bliss.path]) }); + const projectService = createProjectService(host, { + typingsInstaller, + logger: createLoggerWithInMemoryLogs(host), + }); + projectService.openExternalProject({ + projectFileName: projectName, + options: {}, + rootFiles: toExternalFiles([file1.path, constructorFile.path, bliss.path]), + }); assert.equal( request, JSON.stringify({ @@ -389,7 +458,11 @@ describe("unittests:: tsserver:: projects::", () => { projectService.testhost.logTimeoutQueueLength(); assert.isUndefined(request); - baselineTsserverLogs("projects", "file with name constructor.js doesnt cause issue with typeAcquisition when safe type list", projectService); + baselineTsserverLogs( + "projects", + "file with name constructor.js doesnt cause issue with typeAcquisition when safe type list", + projectService, + ); }); it("ignores files excluded by the default type list", () => { @@ -425,8 +498,16 @@ describe("unittests:: tsserver:: projects::", () => { const host = createServerHost(files); const projectService = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) }); try { - projectService.openExternalProject({ projectFileName: "project", options: {}, rootFiles: toExternalFiles(files.map(f => f.path)) }); - projectService.logger.log(`TypeAcquisition:: ${JSON.stringify(projectService.externalProjects[0].getTypeAcquisition(), undefined, " ")}`); + projectService.openExternalProject({ + projectFileName: "project", + options: {}, + rootFiles: toExternalFiles(files.map(f => f.path)), + }); + projectService.logger.log( + `TypeAcquisition:: ${ + JSON.stringify(projectService.externalProjects[0].getTypeAcquisition(), undefined, " ") + }`, + ); } finally { projectService.resetSafeList(); @@ -466,7 +547,12 @@ describe("unittests:: tsserver:: projects::", () => { const host = createServerHost([file1, file2, file3, customTypesMap]); const projectService = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) }); try { - projectService.openExternalProject({ projectFileName: "project", options: {}, rootFiles: toExternalFiles([file1.path, file2.path]), typeAcquisition: { enable: true } }); + projectService.openExternalProject({ + projectFileName: "project", + options: {}, + rootFiles: toExternalFiles([file1.path, file2.path]), + typeAcquisition: { enable: true }, + }); } finally { projectService.resetSafeList(); @@ -529,7 +615,9 @@ describe("unittests:: tsserver:: projects::", () => { const projectService = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) }); projectService.applyChangesInOpenFiles(ts.singleIterator(tsFile)); const projs = projectService.synchronizeProjectList([]); - projectService.findProject(projs[0].info!.projectName)!.getLanguageService().getNavigationBarItems(tsFile.fileName); + projectService.findProject(projs[0].info!.projectName)!.getLanguageService().getNavigationBarItems( + tsFile.fileName, + ); projectService.synchronizeProjectList([projs[0].info!]); projectService.applyChangesInOpenFiles(ts.singleIterator(jsFile)); baselineTsserverLogs("projects", "regression test for crash in acquireOrUpdateDocument", projectService); @@ -687,14 +775,24 @@ describe("unittests:: tsserver:: projects::", () => { // Specify .html extension as mixed content in a configure host request const extraFileExtensions = [{ extension: ".html", scriptKind: ts.ScriptKind.JS, isMixedContent: true }]; - verfiy(config1, createServerHost([file1, file2, config1, libFile], { executingFilePath: ts.combinePaths(ts.getDirectoryPath(libFile.path), "tsc.js") })); + verfiy( + config1, + createServerHost([file1, file2, config1, libFile], { + executingFilePath: ts.combinePaths(ts.getDirectoryPath(libFile.path), "tsc.js"), + }), + ); // #2. Ensure no errors when allowJs is false const config2 = { path: "/a/b/tsconfig.json", content: JSON.stringify({ compilerOptions: { allowJs: false } }), }; - verfiy(config2, createServerHost([file1, file2, config2, libFile], { executingFilePath: ts.combinePaths(ts.getDirectoryPath(libFile.path), "tsc.js") })); + verfiy( + config2, + createServerHost([file1, file2, config2, libFile], { + executingFilePath: ts.combinePaths(ts.getDirectoryPath(libFile.path), "tsc.js"), + }), + ); // #3. Ensure no errors when compiler options aren't specified const config3 = { @@ -702,7 +800,12 @@ describe("unittests:: tsserver:: projects::", () => { content: JSON.stringify({}), }; - verfiy(config3, createServerHost([file1, file2, config3, libFile], { executingFilePath: ts.combinePaths(ts.getDirectoryPath(libFile.path), "tsc.js") })); + verfiy( + config3, + createServerHost([file1, file2, config3, libFile], { + executingFilePath: ts.combinePaths(ts.getDirectoryPath(libFile.path), "tsc.js"), + }), + ); // #4. Ensure no errors when files are explicitly specified in tsconfig const config4 = { @@ -710,7 +813,12 @@ describe("unittests:: tsserver:: projects::", () => { content: JSON.stringify({ compilerOptions: { allowJs: true }, files: [file1.path, file2.path] }), }; - verfiy(config4, createServerHost([file1, file2, config4, libFile], { executingFilePath: ts.combinePaths(ts.getDirectoryPath(libFile.path), "tsc.js") })); + verfiy( + config4, + createServerHost([file1, file2, config4, libFile], { + executingFilePath: ts.combinePaths(ts.getDirectoryPath(libFile.path), "tsc.js"), + }), + ); // #4. Ensure no errors when files are explicitly excluded in tsconfig const config5 = { @@ -718,12 +826,19 @@ describe("unittests:: tsserver:: projects::", () => { content: JSON.stringify({ compilerOptions: { allowJs: true }, exclude: [file2.path] }), }; - const session = verfiy(config5, createServerHost([file1, file2, config5, libFile], { executingFilePath: ts.combinePaths(ts.getDirectoryPath(libFile.path), "tsc.js") })); + const session = verfiy( + config5, + createServerHost([file1, file2, config5, libFile], { + executingFilePath: ts.combinePaths(ts.getDirectoryPath(libFile.path), "tsc.js"), + }), + ); baselineTsserverLogs("projects", "no tsconfig script block diagnostic errors", session); function verfiy(config: File, host: TestServerHost) { logger.host = host; - logger.log(`currentDirectory:: ${host.getCurrentDirectory()} useCaseSensitiveFileNames: ${host.useCaseSensitiveFileNames}`); + logger.log( + `currentDirectory:: ${host.getCurrentDirectory()} useCaseSensitiveFileNames: ${host.useCaseSensitiveFileNames}`, + ); const session = createSession(host, { logger }); session.executeCommandSeq({ command: ts.server.protocol.CommandTypes.Configure, @@ -758,12 +873,19 @@ describe("unittests:: tsserver:: projects::", () => { projectService.applyChangesInOpenFiles( /*openFiles*/ undefined, - /*changedFiles*/ ts.singleIterator({ fileName: file1.path, changes: ts.singleIterator({ span: ts.createTextSpan(0, file1.path.length), newText: "let y = 1" }) }), + /*changedFiles*/ ts.singleIterator({ + fileName: file1.path, + changes: ts.singleIterator({ span: ts.createTextSpan(0, file1.path.length), newText: "let y = 1" }), + }), /*closedFiles*/ undefined, ); projectService.ensureInferredProjectsUpToDate_TestOnly(); - baselineTsserverLogs("projects", "project structure update is deferred if files are not added or removed", projectService); + baselineTsserverLogs( + "projects", + "project structure update is deferred if files are not added or removed", + projectService, + ); }); it("files with mixed content are handled correctly", () => { @@ -774,7 +896,11 @@ describe("unittests:: tsserver:: projects::", () => { const host = createServerHost([file1]); const projectService = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) }); const projectFileName = "projectFileName"; - projectService.openExternalProject({ projectFileName, options: {}, rootFiles: [{ fileName: file1.path, scriptKind: ts.ScriptKind.JS, hasMixedContent: true }] }); + projectService.openExternalProject({ + projectFileName, + options: {}, + rootFiles: [{ fileName: file1.path, scriptKind: ts.ScriptKind.JS, hasMixedContent: true }], + }); const project = projectService.externalProjects[0]; @@ -803,13 +929,20 @@ describe("unittests:: tsserver:: projects::", () => { content: "{x: 1}", }; const host = createServerHost([file1]); - const projectService = createProjectService(host, { useSingleInferredProject: true, logger: createLoggerWithInMemoryLogs(host) }); + const projectService = createProjectService(host, { + useSingleInferredProject: true, + logger: createLoggerWithInMemoryLogs(host), + }); projectService.setCompilerOptionsForInferredProjects({ target: ts.ScriptTarget.ES5, allowJs: false }); projectService.openClientFile(file1.path); - projectService.inferredProjects[0].getLanguageService(/*ensureSynchronized*/ false).getOutliningSpans(file1.path); + projectService.inferredProjects[0].getLanguageService(/*ensureSynchronized*/ false).getOutliningSpans( + file1.path, + ); projectService.setCompilerOptionsForInferredProjects({ target: ts.ScriptTarget.ES5, allowJs: true }); projectService.getScriptInfo(file1.path)!.editContent(0, 0, " "); - projectService.inferredProjects[0].getLanguageService(/*ensureSynchronized*/ false).getOutliningSpans(file1.path); + projectService.inferredProjects[0].getLanguageService(/*ensureSynchronized*/ false).getOutliningSpans( + file1.path, + ); projectService.closeClientFile(file1.path); baselineTsserverLogs("projects", "syntax tree cache handles changes in project settings", projectService); }); @@ -908,7 +1041,11 @@ describe("unittests:: tsserver:: projects::", () => { files: [f1.path], }, } as ts.server.protocol.GeterrRequest); - baselineTsserverLogs("projects", "getting errors from closed script info does not throw exception because of getting project from orphan script info", session); + baselineTsserverLogs( + "projects", + "getting errors from closed script info does not throw exception because of getting project from orphan script info", + session, + ); }); it("Properly handle Windows-style outDir", () => { @@ -1037,7 +1174,11 @@ describe("unittests:: tsserver:: projects::", () => { command: ts.server.protocol.CommandTypes.GetApplicableRefactors, arguments: { file: file2.path, startLine: 1, startOffset, endLine: 1, endOffset: startOffset + 1 }, }); - baselineTsserverLogs("projects", "requests are done on file on pendingReload but has svc for previous version", session); + baselineTsserverLogs( + "projects", + "requests are done on file on pendingReload but has svc for previous version", + session, + ); }); describe("includes deferred files in the project context", () => { @@ -1065,7 +1206,11 @@ describe("unittests:: tsserver:: projects::", () => { }); // Configure the deferred extension. - const extraFileExtensions = [{ extension: ".deferred", scriptKind: ts.ScriptKind.Deferred, isMixedContent: true }]; + const extraFileExtensions = [{ + extension: ".deferred", + scriptKind: ts.ScriptKind.Deferred, + isMixedContent: true, + }]; session.executeCommandSeq({ command: ts.server.protocol.CommandTypes.Configure, arguments: { extraFileExtensions }, @@ -1086,9 +1231,20 @@ describe("unittests:: tsserver:: projects::", () => { } // Allow allowNonTsExtensions will be set to true for deferred extensions. - session.logger.info(`Has allowNonTsExtension: ${session.getProjectService().configuredProjects.get(tsconfig.path)!.getCompilerOptions().allowNonTsExtensions}`); + session.logger.info( + `Has allowNonTsExtension: ${ + session.getProjectService().configuredProjects.get(tsconfig.path)!.getCompilerOptions() + .allowNonTsExtensions + }`, + ); - baselineTsserverLogs("projects", `deferred files in the project context${lazyConfiguredProjectsFromExternalProject ? " with lazyConfiguredProjectsFromExternalProject" : ""}`, session); + baselineTsserverLogs( + "projects", + `deferred files in the project context${ + lazyConfiguredProjectsFromExternalProject ? " with lazyConfiguredProjectsFromExternalProject" : "" + }`, + session, + ); } it("when lazyConfiguredProjectsFromExternalProject not set", () => { @@ -1138,7 +1294,9 @@ describe("unittests:: tsserver:: projects::", () => { function verifyFile2InfoIsOrphan() { const info = ts.Debug.checkDefined(service.getScriptInfoForPath(file2.path as ts.Path)); - service.logger.log(`Containing projects for ${file2.path}:: ${info.containingProjects.map(p => p.projectName).join(",")}`); + service.logger.log( + `Containing projects for ${file2.path}:: ${info.containingProjects.map(p => p.projectName).join(",")}`, + ); } }); @@ -1159,7 +1317,11 @@ describe("unittests:: tsserver:: projects::", () => { host.modifyFile(file1.path, file1.content, { invokeFileDeleteCreateAsPartInsteadOfChange: true }); service.testhost.logTimeoutQueueLength(); - baselineTsserverLogs("projects", "no project structure update on directory watch invoke on open file save", service); + baselineTsserverLogs( + "projects", + "no project structure update on directory watch invoke on open file save", + service, + ); }); it("synchronizeProjectList provides redirect info when requested", () => { @@ -1247,7 +1409,10 @@ describe("unittests:: tsserver:: projects::", () => { command: ts.server.protocol.CommandTypes.SynchronizeProjectList, arguments: { knownProjects: [], includeProjectReferenceRedirectInfo: true }, }); - const knownProjects = session.getProjectService().synchronizeProjectList([], /*includeProjectReferenceRedirectInfo*/ true); + const knownProjects = session.getProjectService().synchronizeProjectList( + [], + /*includeProjectReferenceRedirectInfo*/ true, + ); host.modifyFile( configA.path, @@ -1265,9 +1430,16 @@ describe("unittests:: tsserver:: projects::", () => { session.executeCommandSeq({ command: ts.server.protocol.CommandTypes.SynchronizeProjectList, - arguments: { knownProjects: knownProjects.map(proj => proj.info!), includeProjectReferenceRedirectInfo: true }, + arguments: { + knownProjects: knownProjects.map(proj => proj.info!), + includeProjectReferenceRedirectInfo: true, + }, }); - baselineTsserverLogs("projects", "synchronizeProjectList provides updates to redirect info when requested", session); + baselineTsserverLogs( + "projects", + "synchronizeProjectList provides updates to redirect info when requested", + session, + ); }); it("synchronizeProjectList returns correct information when base configuration file cannot be resolved", () => { @@ -1286,7 +1458,11 @@ describe("unittests:: tsserver:: projects::", () => { command: ts.server.protocol.CommandTypes.SynchronizeProjectList, arguments: { knownProjects: [], includeProjectReferenceRedirectInfo: false }, }); - baselineTsserverLogs("projects", "synchronizeProjectList returns correct information when base configuration file cannot be resolved", session); + baselineTsserverLogs( + "projects", + "synchronizeProjectList returns correct information when base configuration file cannot be resolved", + session, + ); }); it("synchronizeProjectList returns correct information when base configuration file cannot be resolved and redirect info is requested", () => { @@ -1305,7 +1481,11 @@ describe("unittests:: tsserver:: projects::", () => { command: ts.server.protocol.CommandTypes.SynchronizeProjectList, arguments: { knownProjects: [], includeProjectReferenceRedirectInfo: true }, }); - baselineTsserverLogs("projects", "synchronizeProjectList returns correct information when base configuration file cannot be resolved and redirect info is requested", session); + baselineTsserverLogs( + "projects", + "synchronizeProjectList returns correct information when base configuration file cannot be resolved and redirect info is requested", + session, + ); }); it("handles delayed directory watch invoke on file creation", () => { @@ -1328,7 +1508,11 @@ describe("unittests:: tsserver:: projects::", () => { }; const files = [fileSubA, fileB, config, libFile]; const host = createServerHost(files); - const session = createSession(host, { canUseEvents: true, noGetErrOnBackgroundUpdate: true, logger: createLoggerWithInMemoryLogs(host) }); + const session = createSession(host, { + canUseEvents: true, + noGetErrOnBackgroundUpdate: true, + logger: createLoggerWithInMemoryLogs(host), + }); openFile(fileB); openFile(fileSubA); @@ -1382,13 +1566,18 @@ describe("unittests:: tsserver:: projects::", () => { service.openClientFile(commonFile1.path); const project = service.inferredProjects[0]; // Intentionally create scriptinfo and attach it to project - const info = service.getOrCreateScriptInfoForNormalizedPath(commonFile2.path as ts.server.NormalizedPath, /*openedByClient*/ false)!; + const info = service.getOrCreateScriptInfoForNormalizedPath( + commonFile2.path as ts.server.NormalizedPath, + /*openedByClient*/ false, + )!; info.attachToProject(project); try { service.applyChangesInOpenFiles(/*openFiles*/ undefined, /*changedFiles*/ undefined, [commonFile1.path]); } catch (e) { - assert.isTrue(e.message.indexOf("Debug Failure. False expression: Found script Info still attached to project") === 0); + assert.isTrue( + e.message.indexOf("Debug Failure. False expression: Found script Info still attached to project") === 0, + ); } baselineTsserverLogs("projects", "assert when removing project", service); }); @@ -1405,7 +1594,10 @@ describe("unittests:: tsserver:: projects::", () => { { path: nodeModulesProjectPath1, content: "{}" }, { path: nodeModulesFilePath2, content: "{}" }, ]); - const projectService = createProjectService(serverHost, { useSingleInferredProject: true, logger: createLoggerWithInMemoryLogs(serverHost) }); + const projectService = createProjectService(serverHost, { + useSingleInferredProject: true, + logger: createLoggerWithInMemoryLogs(serverHost), + }); const openRootFileResult = projectService.openClientFile(rootFilePath); assert.strictEqual(openRootFileResult.configFileName?.toString(), rootProjectPath); @@ -1416,11 +1608,18 @@ describe("unittests:: tsserver:: projects::", () => { const openNodeModulesFileResult2 = projectService.openClientFile(nodeModulesFilePath2); assert.isUndefined(openNodeModulesFileResult2.configFileName); - baselineTsserverLogs("projects", "does not look beyond node_modules folders for default configured projects", projectService); + baselineTsserverLogs( + "projects", + "does not look beyond node_modules folders for default configured projects", + projectService, + ); }); describe("file opened is in configured project that will be removed", () => { - function runOnTs(scenario: string, getRequest: (innerFile: File) => TestSessionRequest) { + function runOnTs( + scenario: string, + getRequest: (innerFile: File) => TestSessionRequest, + ) { it(scenario, () => { const testsConfig: File = { path: `/user/username/projects/myproject/playground/tsconfig.json`, diff --git a/src/testRunner/unittests/tsserver/projectsWithReferences.ts b/src/testRunner/unittests/tsserver/projectsWithReferences.ts index a261c7adbbef0..bad5f293ffd10 100644 --- a/src/testRunner/unittests/tsserver/projectsWithReferences.ts +++ b/src/testRunner/unittests/tsserver/projectsWithReferences.ts @@ -20,7 +20,17 @@ describe("unittests:: tsserver:: projects with references: invoking when referen const logicIndex = getTsBuildProjectFile("sample1", "logic/index.ts"); const testsConfig = getTsBuildProjectFile("sample1", "tests/tsconfig.json"); const testsIndex = getTsBuildProjectFile("sample1", "tests/index.ts"); - const host = createServerHost([libFile, coreConfig, coreIndex, coreAnotherModule, coreSomeDecl, logicConfig, logicIndex, testsConfig, testsIndex]); + const host = createServerHost([ + libFile, + coreConfig, + coreIndex, + coreAnotherModule, + coreSomeDecl, + logicConfig, + logicIndex, + testsConfig, + testsIndex, + ]); const logger = createLoggerWithInMemoryLogs(host); const service = createProjectService(host, { logger }); service.openClientFile(testsIndex.path); @@ -139,7 +149,11 @@ export class A {}`, // revert the edit on config file host.writeFile(bConfig.path, bConfig.content); host.runQueuedTimeoutCallbacks(); - baselineTsserverLogs("projectsWithReferences", "transitive references with edit in referenced config file", service); + baselineTsserverLogs( + "projectsWithReferences", + "transitive references with edit in referenced config file", + service, + ); }); it("deleting referenced config file", () => { @@ -150,7 +164,11 @@ export class A {}`, // revert host.writeFile(bConfig.path, bConfig.content); host.runQueuedTimeoutCallbacks(); // Schedules failed lookup invalidation - baselineTsserverLogs("projectsWithReferences", "transitive references with deleting referenced config file", service); + baselineTsserverLogs( + "projectsWithReferences", + "transitive references with deleting referenced config file", + service, + ); }); it("deleting transitively referenced config file", () => { @@ -161,7 +179,11 @@ export class A {}`, // revert host.writeFile(aConfig.path, aConfig.content); host.runQueuedTimeoutCallbacks(); // Schedules failed lookup invalidation - baselineTsserverLogs("projectsWithReferences", "transitive references with deleting transitively referenced config file", service); + baselineTsserverLogs( + "projectsWithReferences", + "transitive references with deleting transitively referenced config file", + service, + ); }); }); @@ -218,7 +240,11 @@ export class A {}`, // non local edit host.appendFile(bTs.path, `export function gFoo() { }`); host.runQueuedTimeoutCallbacks(); - baselineTsserverLogs("projectsWithReferences", "trasitive references without files with non local edit", service); + baselineTsserverLogs( + "projectsWithReferences", + "trasitive references without files with non local edit", + service, + ); }); it("edit on config file", () => { @@ -236,7 +262,11 @@ export class A {}`, // revert the edit on config file host.writeFile(cConfig.path, cConfig.content); host.runQueuedTimeoutCallbacks(); - baselineTsserverLogs("projectsWithReferences", "trasitive references without files with edit on config file", service); + baselineTsserverLogs( + "projectsWithReferences", + "trasitive references without files with edit on config file", + service, + ); }); it("edit in referenced config file", () => { @@ -254,7 +284,11 @@ export class A {}`, // revert the edit on config file host.writeFile(bConfig.path, bConfig.content); host.runQueuedTimeoutCallbacks(); - baselineTsserverLogs("projectsWithReferences", "trasitive references without files with edit in referenced config file", service); + baselineTsserverLogs( + "projectsWithReferences", + "trasitive references without files with edit in referenced config file", + service, + ); }); it("deleting referenced config file", () => { @@ -265,7 +299,11 @@ export class A {}`, // revert host.writeFile(bConfig.path, bConfig.content); host.runQueuedTimeoutCallbacks(); // Schedules failed lookup invalidation - baselineTsserverLogs("projectsWithReferences", "trasitive references without files with deleting referenced config file", service); + baselineTsserverLogs( + "projectsWithReferences", + "trasitive references without files with deleting referenced config file", + service, + ); }); it("deleting transitively referenced config file", () => { @@ -276,7 +314,11 @@ export class A {}`, // revert host.writeFile(aConfig.path, aConfig.content); host.runQueuedTimeoutCallbacks(); // Schedules failed lookup invalidation - baselineTsserverLogs("projectsWithReferences", "trasitive references without files with deleting transitively referenced config file", service); + baselineTsserverLogs( + "projectsWithReferences", + "trasitive references without files with deleting transitively referenced config file", + service, + ); }); }); }); diff --git a/src/testRunner/unittests/tsserver/refactors.ts b/src/testRunner/unittests/tsserver/refactors.ts index 21b09170fb8e8..1fd721847f16c 100644 --- a/src/testRunner/unittests/tsserver/refactors.ts +++ b/src/testRunner/unittests/tsserver/refactors.ts @@ -195,6 +195,10 @@ describe("unittests:: tsserver:: refactors", () => { interactiveRefactorArguments: { targetFile: "/Foo/a.ts" }, }, }); - baselineTsserverLogs("refactors", "handles moving statements to a TS file that is not included in the TS project", session); + baselineTsserverLogs( + "refactors", + "handles moving statements to a TS file that is not included in the TS project", + session, + ); }); }); diff --git a/src/testRunner/unittests/tsserver/reloadProjects.ts b/src/testRunner/unittests/tsserver/reloadProjects.ts index fd9cc1503dc17..a590056e5e8ca 100644 --- a/src/testRunner/unittests/tsserver/reloadProjects.ts +++ b/src/testRunner/unittests/tsserver/reloadProjects.ts @@ -79,7 +79,10 @@ describe("unittests:: tsserver:: reloadProjects", () => { it("inferred project", () => { const host = createServerHost([libFile, file1, file2]); - const session = createSession(host, { useInferredProjectPerProjectRoot: true, logger: createLoggerWithInMemoryLogs(host) }); + const session = createSession(host, { + useInferredProjectPerProjectRoot: true, + logger: createLoggerWithInMemoryLogs(host), + }); session.executeCommandSeq({ command: ts.server.protocol.CommandTypes.Configure, arguments: { watchOptions: { excludeFiles: [file2.path] } }, diff --git a/src/testRunner/unittests/tsserver/rename.ts b/src/testRunner/unittests/tsserver/rename.ts index 7c37001e3c144..821b9a30c521e 100644 --- a/src/testRunner/unittests/tsserver/rename.ts +++ b/src/testRunner/unittests/tsserver/rename.ts @@ -105,7 +105,11 @@ describe("unittests:: tsserver:: rename", () => { command: ts.server.protocol.CommandTypes.Rename, arguments: protocolFileLocationFromSubstring(bTs, "aTest("), }); - baselineTsserverLogs("rename", "export default anonymous function works with prefixText and suffixText when disabled", session); + baselineTsserverLogs( + "rename", + "export default anonymous function works with prefixText and suffixText when disabled", + session, + ); }); it("rename behavior is based on file of rename initiation", () => { diff --git a/src/testRunner/unittests/tsserver/resolutionCache.ts b/src/testRunner/unittests/tsserver/resolutionCache.ts index 2899df58217ad..2bf17c61edee0 100644 --- a/src/testRunner/unittests/tsserver/resolutionCache.ts +++ b/src/testRunner/unittests/tsserver/resolutionCache.ts @@ -201,7 +201,11 @@ describe("unittests:: tsserver:: resolutionCache:: tsserverProjectSystem add the }; const host = createServerHost([file]); - const session = createSession(host, { canUseEvents: true, suppressDiagnosticEvents: true, logger: createLoggerWithInMemoryLogs(host) }); + const session = createSession(host, { + canUseEvents: true, + suppressDiagnosticEvents: true, + logger: createLoggerWithInMemoryLogs(host), + }); session.executeCommandSeq({ command: ts.server.protocol.CommandTypes.Open, @@ -272,7 +276,11 @@ describe("unittests:: tsserver:: resolutionCache:: tsserverProjectSystem rename command: ts.server.protocol.CommandTypes.SemanticDiagnosticsSync, arguments: { file: file1.path }, }); - baselineTsserverLogs("resolutionCache", "renaming module should restore the states for inferred projects", session); + baselineTsserverLogs( + "resolutionCache", + "renaming module should restore the states for inferred projects", + session, + ); }); it("should restore the states for configured projects", () => { @@ -311,7 +319,11 @@ describe("unittests:: tsserver:: resolutionCache:: tsserverProjectSystem rename command: ts.server.protocol.CommandTypes.SemanticDiagnosticsSync, arguments: { file: file1.path }, }); - baselineTsserverLogs("resolutionCache", "renaming module should restore the states for configured projects", session); + baselineTsserverLogs( + "resolutionCache", + "renaming module should restore the states for configured projects", + session, + ); }); it("should property handle missing config files", () => { @@ -326,12 +338,20 @@ describe("unittests:: tsserver:: resolutionCache:: tsserverProjectSystem rename const projectName = "project1"; const host = createServerHost([f1]); const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) }); - openExternalProjectForSession({ rootFiles: toExternalFiles([f1.path, config.path]), options: {}, projectFileName: projectName }, session); + openExternalProjectForSession({ + rootFiles: toExternalFiles([f1.path, config.path]), + options: {}, + projectFileName: projectName, + }, session); // should have one external project since config file is missing host.writeFile(config.path, config.content); - openExternalProjectForSession({ rootFiles: toExternalFiles([f1.path, config.path]), options: {}, projectFileName: projectName }, session); + openExternalProjectForSession({ + rootFiles: toExternalFiles([f1.path, config.path]), + options: {}, + projectFileName: projectName, + }, session); baselineTsserverLogs("resolutionCache", "should property handle missing config files", session); }); @@ -344,7 +364,9 @@ describe("unittests:: tsserver:: resolutionCache:: tsserverProjectSystem rename }; const config = { path: "/a/b/tsconfig.json", - content: JSON.stringify({ compilerOptions: { types: ["node"], typeRoots: includeTypeRoots ? [] : undefined } }), + content: JSON.stringify({ + compilerOptions: { types: ["node"], typeRoots: includeTypeRoots ? [] : undefined }, + }), }; const node = { path: "/a/b/node_modules/@types/node/index.d.ts", @@ -360,7 +382,10 @@ describe("unittests:: tsserver:: resolutionCache:: tsserverProjectSystem rename }); } verifyTypesLoad("types should load from config file path if config exists", /*includeTypeRoots*/ false); - verifyTypesLoad("types should not load from config file path if config exists but does not specifies typeRoots", /*includeTypeRoots*/ true); + verifyTypesLoad( + "types should not load from config file path if config exists but does not specifies typeRoots", + /*includeTypeRoots*/ true, + ); }); }); @@ -398,7 +423,10 @@ describe("unittests:: tsserver:: resolutionCache:: tsserverProjectSystem module it("relative module name", () => { const fileContent = `import { module1 } from "./module1";import { module2 } from "../module2";`; const { file1, file2 } = getFiles(fileContent); - const { module1, module2 } = getModules(`/user/username/projects/myproject/src/module1.ts`, `/user/username/projects/myproject/module2.ts`); + const { module1, module2 } = getModules( + `/user/username/projects/myproject/src/module1.ts`, + `/user/username/projects/myproject/module2.ts`, + ); const files = [module1, module2, file1, file2, configFile, libFile]; const host = createServerHost(files); const service = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) }); @@ -414,7 +442,10 @@ describe("unittests:: tsserver:: resolutionCache:: tsserverProjectSystem module it("non relative module name", () => { const fileContent = `import { module1 } from "module1";import { module2 } from "module2";`; const { file1, file2 } = getFiles(fileContent); - const { module1, module2 } = getModules(`/user/username/projects/myproject/src/node_modules/module1/index.ts`, `/user/username/projects/myproject/node_modules/module2/index.ts`); + const { module1, module2 } = getModules( + `/user/username/projects/myproject/src/node_modules/module1/index.ts`, + `/user/username/projects/myproject/node_modules/module2/index.ts`, + ); const files = [module1, module2, file1, file2, configFile, libFile]; const host = createServerHost(files); const service = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) }); @@ -428,7 +459,12 @@ describe("unittests:: tsserver:: resolutionCache:: tsserverProjectSystem module }); describe("from files in different folders", () => { - function getFiles(fileContent1: string, fileContent2 = fileContent1, fileContent3 = fileContent1, fileContent4 = fileContent1) { + function getFiles( + fileContent1: string, + fileContent2 = fileContent1, + fileContent3 = fileContent1, + fileContent4 = fileContent1, + ) { const file1: File = { path: `/user/username/projects/myproject/product/src/file1.ts`, content: fileContent1, @@ -454,7 +490,10 @@ describe("unittests:: tsserver:: resolutionCache:: tsserverProjectSystem module const fileContent3 = `import { module1 } from "../../src/module1";import { module2 } from "../../module2";`; const fileContent4 = `import { module1 } from "../src/module1}";import { module2 } from "../module2";`; const { file1, file2, file3, file4 } = getFiles(fileContent1, fileContent2, fileContent3, fileContent4); - const { module1, module2 } = getModules(`/user/username/projects/myproject/product/src/module1.ts`, `/user/username/projects/myproject/product/module2.ts`); + const { module1, module2 } = getModules( + `/user/username/projects/myproject/product/src/module1.ts`, + `/user/username/projects/myproject/product/module2.ts`, + ); const files = [module1, module2, file1, file2, file3, file4, configFile, libFile]; const host = createServerHost(files); const service = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) }); @@ -471,7 +510,10 @@ describe("unittests:: tsserver:: resolutionCache:: tsserverProjectSystem module it("non relative module name", () => { const fileContent = `import { module1 } from "module1";import { module2 } from "module2";`; const { file1, file2, file3, file4 } = getFiles(fileContent); - const { module1, module2 } = getModules(`/user/username/projects/myproject/product/node_modules/module1/index.ts`, `/user/username/projects/myproject/node_modules/module2/index.ts`); + const { module1, module2 } = getModules( + `/user/username/projects/myproject/product/node_modules/module1/index.ts`, + `/user/username/projects/myproject/node_modules/module2/index.ts`, + ); const files = [module1, module2, file1, file2, file3, file4, configFile, libFile]; const host = createServerHost(files); const service = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) }); @@ -482,7 +524,11 @@ describe("unittests:: tsserver:: resolutionCache:: tsserverProjectSystem module host.writeFile(file3.path, file3.content + fileContent); host.writeFile(file4.path, file4.content + fileContent); host.runQueuedTimeoutCallbacks(); - baselineTsserverLogs("resolutionCache", "non relative module name from files in different folders", service); + baselineTsserverLogs( + "resolutionCache", + "non relative module name from files in different folders", + service, + ); }); it("non relative module name from inferred project", () => { @@ -491,9 +537,18 @@ describe("unittests:: tsserver:: resolutionCache:: tsserverProjectSystem module const file2Name = "./feature/file2"; const file3Name = "../test/src/file3"; const file4Name = "../test/file4"; - const importModuleContent = `import { module1 } from "${module1Name}";import { module2 } from "${module2Name}";`; - const { file1, file2, file3, file4 } = getFiles(`import "${file2Name}"; import "${file4Name}"; import "${file3Name}"; ${importModuleContent}`, importModuleContent, importModuleContent, importModuleContent); - const { module1, module2 } = getModules(`/user/username/projects/myproject/product/node_modules/module1/index.ts`, `/user/username/projects/myproject/node_modules/module2/index.ts`); + const importModuleContent = + `import { module1 } from "${module1Name}";import { module2 } from "${module2Name}";`; + const { file1, file2, file3, file4 } = getFiles( + `import "${file2Name}"; import "${file4Name}"; import "${file3Name}"; ${importModuleContent}`, + importModuleContent, + importModuleContent, + importModuleContent, + ); + const { module1, module2 } = getModules( + `/user/username/projects/myproject/product/node_modules/module1/index.ts`, + `/user/username/projects/myproject/node_modules/module2/index.ts`, + ); const files = [module1, module2, file1, file2, file3, file4, libFile]; const host = createServerHost(files); const service = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) }); @@ -553,10 +608,22 @@ export const x = 10;`, }), }; - const files = [...(useNodeFile ? [nodeFile] : []), electronFile, srcFile, moduleFile, configFile, libFile]; + const files = [ + ...(useNodeFile ? [nodeFile] : []), + electronFile, + srcFile, + moduleFile, + configFile, + libFile, + ]; const host = createServerHost(files); const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) }); - openFilesForSession([{ file: srcFile.path, content: srcFile.content, scriptKindName: "TS", projectRootPath: "/user/username/projects/myproject" }], session); + openFilesForSession([{ + file: srcFile.path, + content: srcFile.content, + scriptKindName: "TS", + projectRootPath: "/user/username/projects/myproject", + }], session); baselineTsserverLogs("resolutionCache", scenario, session); }); } @@ -566,7 +633,8 @@ export const x = 10;`, describe("ignores files/folder changes in node_modules that start with '.'", () => { const npmCacheFile: File = { - path: `/user/username/projects/myproject/node_modules/.cache/babel-loader/89c02171edab901b9926470ba6d5677e.ts`, + path: + `/user/username/projects/myproject/node_modules/.cache/babel-loader/89c02171edab901b9926470ba6d5677e.ts`, content: JSON.stringify({ something: 10 }), }; const file1: File = { @@ -586,7 +654,11 @@ export const x = 10;`, host.ensureFileOrFolder(npmCacheFile); service.testhost.logTimeoutQueueLength(); - baselineTsserverLogs("resolutionCache", "when watching node_modules in inferred project for failed lookup/closed script infos", service); + baselineTsserverLogs( + "resolutionCache", + "when watching node_modules in inferred project for failed lookup/closed script infos", + service, + ); }); it("when watching node_modules as part of wild card directories in config project", () => { const config: File = { @@ -601,7 +673,11 @@ export const x = 10;`, host.ensureFileOrFolder(npmCacheFile); service.testhost.logTimeoutQueueLength(); - baselineTsserverLogs("resolutionCache", "when watching node_modules as part of wild card directories in config project", service); + baselineTsserverLogs( + "resolutionCache", + "when watching node_modules as part of wild card directories in config project", + service, + ); }); }); @@ -612,7 +688,10 @@ export const x = 10;`, path: `/user/username/projects/myproject/src/file1.ts`, content: fileContent, }; - const { module1, module2 } = getModules(`/user/username/projects/myproject/src/node_modules/module1/index.ts`, `/user/username/projects/myproject/node_modules/module2/index.ts`); + const { module1, module2 } = getModules( + `/user/username/projects/myproject/src/node_modules/module1/index.ts`, + `/user/username/projects/myproject/node_modules/module2/index.ts`, + ); const files = [module1, module2, file1, configFile, libFile]; const host = createServerHost(files); const service = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) }); diff --git a/src/testRunner/unittests/tsserver/session.ts b/src/testRunner/unittests/tsserver/session.ts index ad14f4e71acf1..f35eaa62a82c0 100644 --- a/src/testRunner/unittests/tsserver/session.ts +++ b/src/testRunner/unittests/tsserver/session.ts @@ -171,7 +171,10 @@ describe("unittests:: tsserver:: Session:: General functionality", () => { session.onMessage(JSON.stringify(configureRequest)); - assert.equal(session.getProjectService().getFormatCodeOptions("" as ts.server.NormalizedPath).indentStyle, ts.IndentStyle.Block); + assert.equal( + session.getProjectService().getFormatCodeOptions("" as ts.server.NormalizedPath).indentStyle, + ts.IndentStyle.Block, + ); const setOptionsRequest: ts.server.protocol.SetCompilerOptionsForInferredProjectsRequest = { command: ts.server.protocol.CommandTypes.CompilerOptionsForInferredProjects, @@ -216,7 +219,9 @@ describe("unittests:: tsserver:: Session:: General functionality", () => { }); describe("onMessage", () => { - const allCommandNames: ts.server.protocol.CommandTypes[] = Object.values((ts.server.protocol as any).CommandTypes); + const allCommandNames: ts.server.protocol.CommandTypes[] = Object.values( + (ts.server.protocol as any).CommandTypes, + ); it("should not throw when commands are executed with invalid arguments", () => { let i = 0; @@ -389,7 +394,9 @@ describe("unittests:: tsserver:: Session:: exceptions", () => { const command = "testhandler"; class TestSession extends ts.server.Session { lastSent: ts.server.protocol.Message | undefined; - private exceptionRaisingHandler(_request: ts.server.protocol.Request): { response?: any; responseRequired: boolean; } { + private exceptionRaisingHandler( + _request: ts.server.protocol.Request, + ): { response?: any; responseRequired: boolean; } { f1(); return ts.Debug.fail(); // unreachable, throw to make compiler happy function f1() { diff --git a/src/testRunner/unittests/tsserver/skipLibCheck.ts b/src/testRunner/unittests/tsserver/skipLibCheck.ts index 067d87544b13d..8e3e766b20738 100644 --- a/src/testRunner/unittests/tsserver/skipLibCheck.ts +++ b/src/testRunner/unittests/tsserver/skipLibCheck.ts @@ -150,7 +150,11 @@ describe("unittests:: tsserver:: with skipLibCheck", () => { command: ts.server.protocol.CommandTypes.SemanticDiagnosticsSync, arguments: { file: dTsFile2.path }, }); - baselineTsserverLogs("skipLibCheck", "should not report bind errors for declaration files with skipLibCheck=true", session); + baselineTsserverLogs( + "skipLibCheck", + "should not report bind errors for declaration files with skipLibCheck=true", + session, + ); }); it("should report semantic errors for loose JS files with '// @ts-check' and skipLibCheck=true", () => { diff --git a/src/testRunner/unittests/tsserver/symLinks.ts b/src/testRunner/unittests/tsserver/symLinks.ts index c93305a9fc8fb..81a4987a1b1f1 100644 --- a/src/testRunner/unittests/tsserver/symLinks.ts +++ b/src/testRunner/unittests/tsserver/symLinks.ts @@ -137,68 +137,101 @@ new C();`, } function verifyModuleResolution(withPathMapping: boolean) { - describe(withPathMapping ? "when tsconfig file contains path mapping" : "when tsconfig does not contain path mapping", () => { - const filesWithSources = [libFile, recognizersDateTimeSrcFile, withPathMapping ? recognizerDateTimeTsconfigWithPathMapping : recognizerDateTimeTsconfigWithoutPathMapping, recognizerTextSrcFile, recongnizerTextPackageJson]; - it("when project compiles from sources", () => { - const host = createServerHost(filesWithSources); - const session = createSessionAndOpenFile(host); - verifyGetErrRequest({ session, files: [recognizersDateTimeSrcFile] }); - - host.ensureFileOrFolder(nodeModulesRecorgnizersText); - host.writeFile(recongnizerTextDistTypingFile.path, recongnizerTextDistTypingFile.content); - host.runQueuedTimeoutCallbacks(); // Scheduled invalidation of resolutions - host.runQueuedTimeoutCallbacks(); // Actual update - - verifyGetErrRequest({ session, files: [recognizersDateTimeSrcFile] }); - - // Change config file's module resolution affecting option - const config = JSON.parse(host.readFile(recognizerDateTimeTsconfigPath)!); - host.writeFile( - recognizerDateTimeTsconfigPath, - JSON.stringify({ - ...config, - compilerOptions: { ...config.compilerOptions, resolveJsonModule: true }, - }), - ); - host.runQueuedTimeoutCallbacks(); // Scheduled invalidation of resolutions - host.runQueuedTimeoutCallbacks(); // Actual update - - baselineTsserverLogs("symLinks", `module resolution${withPathMapping ? " with path mapping" : ""} when project compiles from sources`, session); - }); - - it("when project has node_modules setup but doesnt have modules in typings folder and then recompiles", () => { - const host = createServerHost([...filesWithSources, nodeModulesRecorgnizersText]); - const session = createSessionAndOpenFile(host); - verifyGetErrRequest({ session, files: [recognizersDateTimeSrcFile] }); - - host.writeFile(recongnizerTextDistTypingFile.path, recongnizerTextDistTypingFile.content); - host.runQueuedTimeoutCallbacks(); // Scheduled invalidation of resolutions - host.runQueuedTimeoutCallbacks(); // Actual update - - verifyGetErrRequest({ session, files: [recognizersDateTimeSrcFile] }); - baselineTsserverLogs("symLinks", `module resolution${withPathMapping ? " with path mapping" : ""} when project has node_modules setup but doesnt have modules in typings folder and then recompiles`, session); - }); - - it("when project recompiles after deleting generated folders", () => { - const host = createServerHost([...filesWithSources, nodeModulesRecorgnizersText, recongnizerTextDistTypingFile]); - const session = createSessionAndOpenFile(host); - - verifyGetErrRequest({ session, files: [recognizersDateTimeSrcFile] }); - - host.deleteFolder(recognizersTextDist, /*recursive*/ true); - host.runQueuedTimeoutCallbacks(); // Scheduled invalidation of resolutions - host.runQueuedTimeoutCallbacks(); // Actual update - - verifyGetErrRequest({ session, files: [recognizersDateTimeSrcFile] }); - - host.ensureFileOrFolder(recongnizerTextDistTypingFile); - host.runQueuedTimeoutCallbacks(); // Scheduled invalidation of resolutions - host.runQueuedTimeoutCallbacks(); // Actual update - - verifyGetErrRequest({ session, files: [recognizersDateTimeSrcFile] }); - baselineTsserverLogs("symLinks", `module resolution${withPathMapping ? " with path mapping" : ""} when project recompiles after deleting generated folders`, session); - }); - }); + describe( + withPathMapping ? "when tsconfig file contains path mapping" + : "when tsconfig does not contain path mapping", + () => { + const filesWithSources = [ + libFile, + recognizersDateTimeSrcFile, + withPathMapping ? recognizerDateTimeTsconfigWithPathMapping + : recognizerDateTimeTsconfigWithoutPathMapping, + recognizerTextSrcFile, + recongnizerTextPackageJson, + ]; + it("when project compiles from sources", () => { + const host = createServerHost(filesWithSources); + const session = createSessionAndOpenFile(host); + verifyGetErrRequest({ session, files: [recognizersDateTimeSrcFile] }); + + host.ensureFileOrFolder(nodeModulesRecorgnizersText); + host.writeFile(recongnizerTextDistTypingFile.path, recongnizerTextDistTypingFile.content); + host.runQueuedTimeoutCallbacks(); // Scheduled invalidation of resolutions + host.runQueuedTimeoutCallbacks(); // Actual update + + verifyGetErrRequest({ session, files: [recognizersDateTimeSrcFile] }); + + // Change config file's module resolution affecting option + const config = JSON.parse(host.readFile(recognizerDateTimeTsconfigPath)!); + host.writeFile( + recognizerDateTimeTsconfigPath, + JSON.stringify({ + ...config, + compilerOptions: { ...config.compilerOptions, resolveJsonModule: true }, + }), + ); + host.runQueuedTimeoutCallbacks(); // Scheduled invalidation of resolutions + host.runQueuedTimeoutCallbacks(); // Actual update + + baselineTsserverLogs( + "symLinks", + `module resolution${ + withPathMapping ? " with path mapping" : "" + } when project compiles from sources`, + session, + ); + }); + + it("when project has node_modules setup but doesnt have modules in typings folder and then recompiles", () => { + const host = createServerHost([...filesWithSources, nodeModulesRecorgnizersText]); + const session = createSessionAndOpenFile(host); + verifyGetErrRequest({ session, files: [recognizersDateTimeSrcFile] }); + + host.writeFile(recongnizerTextDistTypingFile.path, recongnizerTextDistTypingFile.content); + host.runQueuedTimeoutCallbacks(); // Scheduled invalidation of resolutions + host.runQueuedTimeoutCallbacks(); // Actual update + + verifyGetErrRequest({ session, files: [recognizersDateTimeSrcFile] }); + baselineTsserverLogs( + "symLinks", + `module resolution${ + withPathMapping ? " with path mapping" : "" + } when project has node_modules setup but doesnt have modules in typings folder and then recompiles`, + session, + ); + }); + + it("when project recompiles after deleting generated folders", () => { + const host = createServerHost([ + ...filesWithSources, + nodeModulesRecorgnizersText, + recongnizerTextDistTypingFile, + ]); + const session = createSessionAndOpenFile(host); + + verifyGetErrRequest({ session, files: [recognizersDateTimeSrcFile] }); + + host.deleteFolder(recognizersTextDist, /*recursive*/ true); + host.runQueuedTimeoutCallbacks(); // Scheduled invalidation of resolutions + host.runQueuedTimeoutCallbacks(); // Actual update + + verifyGetErrRequest({ session, files: [recognizersDateTimeSrcFile] }); + + host.ensureFileOrFolder(recongnizerTextDistTypingFile); + host.runQueuedTimeoutCallbacks(); // Scheduled invalidation of resolutions + host.runQueuedTimeoutCallbacks(); // Actual update + + verifyGetErrRequest({ session, files: [recognizersDateTimeSrcFile] }); + baselineTsserverLogs( + "symLinks", + `module resolution${ + withPathMapping ? " with path mapping" : "" + } when project recompiles after deleting generated folders`, + session, + ); + }); + }, + ); } verifyModuleResolution(/*withPathMapping*/ false); diff --git a/src/testRunner/unittests/tsserver/symlinkCache.ts b/src/testRunner/unittests/tsserver/symlinkCache.ts index 38536a64b499e..634e1cfcbcb4a 100644 --- a/src/testRunner/unittests/tsserver/symlinkCache.ts +++ b/src/testRunner/unittests/tsserver/symlinkCache.ts @@ -68,7 +68,11 @@ describe("unittests:: tsserver:: symlinkCache", () => { project.getSymlinkCache()?.getSymlinkedDirectories()?.get(link.path + "/" as ts.Path), { real: "/packages/dep/", realPath: "/packages/dep/" as ts.Path }, ); - baselineTsserverLogs("symlinkCache", "contains symlinks discovered by project references resolution after program creation", session); + baselineTsserverLogs( + "symlinkCache", + "contains symlinks discovered by project references resolution after program creation", + session, + ); }); it("works for paths close to the root", () => { diff --git a/src/testRunner/unittests/tsserver/syntacticServer.ts b/src/testRunner/unittests/tsserver/syntacticServer.ts index 9a48ff07d7d87..5f575bdaac793 100644 --- a/src/testRunner/unittests/tsserver/syntacticServer.ts +++ b/src/testRunner/unittests/tsserver/syntacticServer.ts @@ -42,11 +42,18 @@ import { something } from "something"; content: "{}", }; const host = createServerHost([file1, file2, file3, something, libFile, configFile]); - const session = createSession(host, { serverMode: ts.LanguageServiceMode.Syntactic, useSingleInferredProject: true, logger: createLoggerWithInMemoryLogs(host) }); + const session = createSession(host, { + serverMode: ts.LanguageServiceMode.Syntactic, + useSingleInferredProject: true, + logger: createLoggerWithInMemoryLogs(host), + }); return { host, session, file1, file2, file3, something, configFile }; } - function verifySessionException(session: TestSession, request: TestSessionRequest) { + function verifySessionException( + session: TestSession, + request: TestSessionRequest, + ) { try { session.executeCommandSeq(request); } @@ -153,7 +160,11 @@ function fooB() { }`, content: "{}", }; const host = createServerHost([file1, file2, file3, something, libFile, configFile]); - const session = createSession(host, { serverMode: ts.LanguageServiceMode.Syntactic, useSingleInferredProject: true, logger: createLoggerWithInMemoryLogs(host) }); + const session = createSession(host, { + serverMode: ts.LanguageServiceMode.Syntactic, + useSingleInferredProject: true, + logger: createLoggerWithInMemoryLogs(host), + }); const service = session.getProjectService(); openFilesForSession([file1], session); const project = service.inferredProjects[0]; diff --git a/src/testRunner/unittests/tsserver/syntaxOperations.ts b/src/testRunner/unittests/tsserver/syntaxOperations.ts index bff763b829789..719cd6735bbe0 100644 --- a/src/testRunner/unittests/tsserver/syntaxOperations.ts +++ b/src/testRunner/unittests/tsserver/syntaxOperations.ts @@ -75,7 +75,10 @@ export function Test2() { host.writeFile(unitTest1.path, unitTest1WithChangedContent.content); host.runQueuedTimeoutCallbacks(); - openFilesForSession([{ file: unitTest1WithChangedContent, content: unitTest1WithChangedContent.content }], session); + openFilesForSession( + [{ file: unitTest1WithChangedContent, content: unitTest1WithChangedContent.content }], + session, + ); session.executeCommandSeq({ command: ts.server.protocol.CommandTypes.NavBarFull, diff --git a/src/testRunner/unittests/tsserver/telemetry.ts b/src/testRunner/unittests/tsserver/telemetry.ts index e7fd1c6814dd0..ab9009f567488 100644 --- a/src/testRunner/unittests/tsserver/telemetry.ts +++ b/src/testRunner/unittests/tsserver/telemetry.ts @@ -43,7 +43,9 @@ describe("unittests:: tsserver:: project telemetry", () => { }); it("counts files by extension", () => { - const files = ["ts.ts", "tsx.tsx", "moo.ts", "dts.d.ts", "jsx.jsx", "js.js", "badExtension.badExtension"].map(f => makeFile(`/src/${f}`)); + const files = ["ts.ts", "tsx.tsx", "moo.ts", "dts.d.ts", "jsx.jsx", "js.js", "badExtension.badExtension"].map( + f => makeFile(`/src/${f}`), + ); const notIncludedFile = makeFile("/bin/ts.js"); const compilerOptions: ts.CompilerOptions = { allowJs: true }; const tsconfig = makeFile("/tsconfig.json", { compilerOptions, include: ["src"] }); @@ -152,7 +154,11 @@ describe("unittests:: tsserver:: project telemetry", () => { logger: createLoggerWithInMemoryLogs(host), }); openFilesForSession([file], session); - baselineTsserverLogs("telemetry", "sends telemetry for extends, files, include, exclude, and compileOnSave", session); + baselineTsserverLogs( + "telemetry", + "sends telemetry for extends, files, include, exclude, and compileOnSave", + session, + ); }); const autoJsCompilerOptions = { diff --git a/src/testRunner/unittests/tsserver/textStorage.ts b/src/testRunner/unittests/tsserver/textStorage.ts index 8b82e33628cb9..0440eca35a2ee 100644 --- a/src/testRunner/unittests/tsserver/textStorage.ts +++ b/src/testRunner/unittests/tsserver/textStorage.ts @@ -20,7 +20,11 @@ describe("unittests:: tsserver:: Text storage", () => { }; function getDummyScriptInfo(fileName: string) { - return { fileName, closeSourceMapFileWatcher: ts.noop, isDynamicOrHasMixedContent: ts.returnFalse } as ts.server.ScriptInfo; + return { + fileName, + closeSourceMapFileWatcher: ts.noop, + isDynamicOrHasMixedContent: ts.returnFalse, + } as ts.server.ScriptInfo; } it("text based storage should be have exactly the same as script version cache", () => { @@ -40,20 +44,32 @@ describe("unittests:: tsserver:: Text storage", () => { for (let offset = 0; offset < end - start; offset++) { const pos1 = ts1.lineOffsetToPosition(line + 1, offset + 1); const pos2 = ts2.lineOffsetToPosition(line + 1, offset + 1); - assert.strictEqual(pos1, pos2, `lineOffsetToPosition ${line + 1}-${offset + 1}: expected ${pos1} to equal ${pos2}`); + assert.strictEqual( + pos1, + pos2, + `lineOffsetToPosition ${line + 1}-${offset + 1}: expected ${pos1} to equal ${pos2}`, + ); } const { start: start1, length: length1 } = ts1.lineToTextSpan(line); const { start: start2, length: length2 } = ts2.lineToTextSpan(line); assert.strictEqual(start1, start2, `lineToTextSpan ${line}::start:: expected ${start1} to equal ${start2}`); - assert.strictEqual(length1, length2, `lineToTextSpan ${line}::length:: expected ${length1} to equal ${length2}`); + assert.strictEqual( + length1, + length2, + `lineToTextSpan ${line}::length:: expected ${length1} to equal ${length2}`, + ); } for (let pos = 0; pos < f.content.length; pos++) { const { line: line1, offset: offset1 } = ts1.positionToLineOffset(pos); const { line: line2, offset: offset2 } = ts2.positionToLineOffset(pos); assert.strictEqual(line1, line2, `positionToLineOffset ${pos}::line:: expected ${line1} to equal ${line2}`); - assert.strictEqual(offset1, offset2, `positionToLineOffset ${pos}::offset:: expected ${offset1} to equal ${offset2}`); + assert.strictEqual( + offset1, + offset2, + `positionToLineOffset ${pos}::offset:: expected ${offset1} to equal ${offset2}`, + ); } }); @@ -124,7 +140,11 @@ describe("unittests:: tsserver:: Text storage", () => { assert.isFalse(ts1.hasScriptVersionCache_TestOnly()); assert.strictEqual(largeFile.content.length, ts1.getTelemetryFileSize()); - baselineTsserverLogs("textStorage", "should be able to return the file size when a JS file is too large to load into text", projectService); + baselineTsserverLogs( + "textStorage", + "should be able to return the file size when a JS file is too large to load into text", + projectService, + ); }); it("should return the file size without reloading the file", () => { diff --git a/src/testRunner/unittests/tsserver/typeAquisition.ts b/src/testRunner/unittests/tsserver/typeAquisition.ts index 4c4524e90f730..5366791d0d345 100644 --- a/src/testRunner/unittests/tsserver/typeAquisition.ts +++ b/src/testRunner/unittests/tsserver/typeAquisition.ts @@ -24,7 +24,11 @@ describe("unittests:: tsserver:: typeAquisition:: autoDiscovery", () => { const projectService = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) }); projectService.openExternalProject({ projectFileName: "/a/b/proj.csproj", - rootFiles: [toExternalFile(file2.path), { fileName: file1.path, hasMixedContent: true, scriptKind: ts.ScriptKind.JS }], + rootFiles: [toExternalFile(file2.path), { + fileName: file1.path, + hasMixedContent: true, + scriptKind: ts.ScriptKind.JS, + }], options: {}, }); const typeAcquisition = projectService.externalProjects[0].getTypeAcquisition(); diff --git a/src/testRunner/unittests/tsserver/typeOnlyImportChains.ts b/src/testRunner/unittests/tsserver/typeOnlyImportChains.ts index e8810c193400f..7d5667114ddbf 100644 --- a/src/testRunner/unittests/tsserver/typeOnlyImportChains.ts +++ b/src/testRunner/unittests/tsserver/typeOnlyImportChains.ts @@ -136,7 +136,11 @@ describe("unittests:: tsserver:: typeOnlyImportChains", () => { content: "import { a } from './c'; new a.A();", }; - assertUsageError("namedExport exportNamespaceFrom typeOnlyNamedImport namedExport namedImport", [a, b, c, d], d); + assertUsageError( + "namedExport exportNamespaceFrom typeOnlyNamedImport namedExport namedImport", + [a, b, c, d], + d, + ); }); it("named export -> type-only export from -> export namespace from -> named import", () => { diff --git a/src/testRunner/unittests/tsserver/typeReferenceDirectives.ts b/src/testRunner/unittests/tsserver/typeReferenceDirectives.ts index c0caf9bab9ca6..04d04eb3ccd5e 100644 --- a/src/testRunner/unittests/tsserver/typeReferenceDirectives.ts +++ b/src/testRunner/unittests/tsserver/typeReferenceDirectives.ts @@ -62,7 +62,11 @@ declare class TestLib { openFilesForSession([testFile], session); host.writeFile(appLib.path, appLib.content.replace("test()", "test2()")); host.runQueuedTimeoutCallbacks(); - baselineTsserverLogs("typeReferenceDirectives", "when typeReferenceDirective contains UpperCasePackage", session); + baselineTsserverLogs( + "typeReferenceDirectives", + "when typeReferenceDirective contains UpperCasePackage", + session, + ); }); it("when typeReferenceDirective is relative path and in a sibling folder", () => { @@ -89,6 +93,10 @@ declare class TestLib { const host = createServerHost(files); const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) }); openFilesForSession([file], session); - baselineTsserverLogs("typeReferenceDirectives", "when typeReferenceDirective is relative path and in a sibling folder", session); + baselineTsserverLogs( + "typeReferenceDirectives", + "when typeReferenceDirective is relative path and in a sibling folder", + session, + ); }); }); diff --git a/src/testRunner/unittests/tsserver/typingsInstaller.ts b/src/testRunner/unittests/tsserver/typingsInstaller.ts index 1befbe4b6f155..19b41bf2e4211 100644 --- a/src/testRunner/unittests/tsserver/typingsInstaller.ts +++ b/src/testRunner/unittests/tsserver/typingsInstaller.ts @@ -33,7 +33,12 @@ interface InstallerParams { type InstallWorkerThrowingError = string; type InstallWorkerExecutingCommand = [installedTypings: string[] | string, typingFiles: File[]]; -type CustomInstallWorker = (installer: TestTypingsInstallerWorker, requestId: number, packageNames: string[], cb: ts.server.typingsInstaller.RequestCompletedAction) => void; +type CustomInstallWorker = ( + installer: TestTypingsInstallerWorker, + requestId: number, + packageNames: string[], + cb: ts.server.typingsInstaller.RequestCompletedAction, +) => void; function createTestTypingInstaller( host: TestServerHost, @@ -60,7 +65,12 @@ function createTestTypingInstallerWithInstallWorker( host, logger, class extends TestTypingsInstallerWorker { - override installWorker(requestId: number, packageNames: string[], _cwd: string, cb: ts.server.typingsInstaller.RequestCompletedAction) { + override installWorker( + requestId: number, + packageNames: string[], + _cwd: string, + cb: ts.server.typingsInstaller.RequestCompletedAction, + ) { this.log.writeLine(`#${requestId} with arguments'${JSON.stringify(packageNames)}'.`); if (ts.isString(installWorker)) { assert(false, installWorker); @@ -77,7 +87,15 @@ function createTestTypingInstallerWithInstallWorker( ); } -function executeCommand(self: TestTypingsInstallerWorker, requestId: number, packageNames: string[], host: TestServerHost, installedTypings: string[] | string, typingFiles: File[], cb: ts.server.typingsInstaller.RequestCompletedAction): void { +function executeCommand( + self: TestTypingsInstallerWorker, + requestId: number, + packageNames: string[], + host: TestServerHost, + installedTypings: string[] | string, + typingFiles: File[], + cb: ts.server.typingsInstaller.RequestCompletedAction, +): void { self.addPostExecAction(installedTypings, requestId, packageNames, success => { (host as TestSessionAndServiceHost).baselineHost("TI:: Before installWorker"); for (const file of typingFiles) { @@ -256,7 +274,11 @@ describe("unittests:: tsserver:: typingsInstaller:: General functionality", () = projectService.testhost.logTimeoutQueueLength(); // files should not be removed from project if ATA is skipped - baselineTsserverLogs("typingsInstaller", "inferred projects with disableFilenameBasedTypeAcquisition", projectService); + baselineTsserverLogs( + "typingsInstaller", + "inferred projects with disableFilenameBasedTypeAcquisition", + projectService, + ); }); it("external project - no type acquisition, no .d.ts/js files", () => { @@ -457,7 +479,11 @@ describe("unittests:: tsserver:: typingsInstaller:: General functionality", () = typeAcquisition: { enable: false }, }); - baselineTsserverLogs("typingsInstaller", "external projects no type acquisition with enable false", projectService); + baselineTsserverLogs( + "typingsInstaller", + "external projects no type acquisition with enable false", + projectService, + ); }); it("external project - type acquisition with disableFilenameBasedTypeAcquisition:true", () => { @@ -488,7 +514,11 @@ describe("unittests:: tsserver:: typingsInstaller:: General functionality", () = typingsInstaller.installer.executePendingCommands(); // files should not be removed from project if ATA is skipped - baselineTsserverLogs("typingsInstaller", "external projects type acquisition with disableFilenameBasedTypeAcquisition", projectService); + baselineTsserverLogs( + "typingsInstaller", + "external projects type acquisition with disableFilenameBasedTypeAcquisition", + projectService, + ); }); it("external project - no type acquisition, with js & ts files", () => { @@ -521,7 +551,11 @@ describe("unittests:: tsserver:: typingsInstaller:: General functionality", () = typeAcquisition: {}, }); - baselineTsserverLogs("typingsInstaller", "external projects no type acquisition with js ts files", projectService); + baselineTsserverLogs( + "typingsInstaller", + "external projects no type acquisition with js ts files", + projectService, + ); }); it("external project - with type acquisition, with only js, d.ts files", () => { @@ -573,7 +607,12 @@ describe("unittests:: tsserver:: typingsInstaller:: General functionality", () = const typingsInstaller = createTestTypingInstallerWithInstallWorker( host, logger, - [["@types/commander", "@types/express", "@types/jquery", "@types/moment"], [commander, express, jquery, moment]], + [["@types/commander", "@types/express", "@types/jquery", "@types/moment"], [ + commander, + express, + jquery, + moment, + ]], { typesRegistry: ["jquery", "commander", "moment", "express"] }, ); @@ -723,7 +762,15 @@ describe("unittests:: tsserver:: typingsInstaller:: General functionality", () = else { typingFiles = [grunt, gulp]; } - executeCommand(installer, requestId, packageNames, host, typingFiles.map(f => f.typings), typingFiles, cb); + executeCommand( + installer, + requestId, + packageNames, + host, + typingFiles.map(f => f.typings), + typingFiles, + cb, + ); }, { throttleLimit: 1, typesRegistry: ["commander", "jquery", "lodash", "cordova", "gulp", "grunt"] }, ); @@ -870,7 +917,16 @@ describe("unittests:: tsserver:: typingsInstaller:: General functionality", () = path: "/tmp/node_modules/@types/jquery/index.d.ts", content: "", }; - const host = createServerHost([app, jsconfig, pkgJson, commander, commanderPackage, jquery, jqueryPackage, nestedPackage]); + const host = createServerHost([ + app, + jsconfig, + pkgJson, + commander, + commanderPackage, + jquery, + jqueryPackage, + nestedPackage, + ]); const logger = createLoggerWithInMemoryLogs(host); const typingsInstaller = createTestTypingInstallerWithInstallWorker( host, @@ -879,7 +935,11 @@ describe("unittests:: tsserver:: typingsInstaller:: General functionality", () = { globalTypingsCacheLocation: "/tmp", typesRegistry: ["jquery", "nested", "commander"] }, ); - const projectService = createProjectService(host, { useSingleInferredProject: true, typingsInstaller, logger }); + const projectService = createProjectService(host, { + useSingleInferredProject: true, + typingsInstaller, + logger, + }); projectService.openClientFile(app.path); typingsInstaller.installer.executePendingCommands(); @@ -1052,7 +1112,11 @@ describe("unittests:: tsserver:: typingsInstaller:: General functionality", () = const typingsInstaller = createTestTypingInstallerWithInstallWorker( host, logger, - [["@types/node", "@types/commander", `@types/${emberComponentDirectory}`], [node, commander, emberComponent]], + [["@types/node", "@types/commander", `@types/${emberComponentDirectory}`], [ + node, + commander, + emberComponent, + ]], { globalTypingsCacheLocation: cachePath, typesRegistry: ["node", "commander"] }, ); const service = createProjectService(host, { typingsInstaller, logger }); @@ -1083,7 +1147,10 @@ describe("unittests:: tsserver:: typingsInstaller:: General functionality", () = const typingsInstaller = createTestTypingInstallerWithInstallWorker( host, logger, - [typeNames.map(name => `@types/${name}`), typeNames.map((name): File => ({ path: typePath(name), content: "" }))], + [ + typeNames.map(name => `@types/${name}`), + typeNames.map((name): File => ({ path: typePath(name), content: "" })), + ], { globalTypingsCacheLocation: cachePath, typesRegistry: typeNames }, ); const service = createProjectService(host, { @@ -1131,7 +1198,11 @@ describe("unittests:: tsserver:: typingsInstaller:: General functionality", () = ); typingsInstaller.installer.executePendingCommands(); - baselineTsserverLogs("typingsInstaller", "pick typing names from nonrelative unresolved imports", projectService); + baselineTsserverLogs( + "typingsInstaller", + "pick typing names from nonrelative unresolved imports", + projectService, + ); }); it("cached unresolved typings are not recomputed if program structure did not change", () => { @@ -1173,7 +1244,11 @@ describe("unittests:: tsserver:: typingsInstaller:: General functionality", () = proj.updateGraph(); const version2 = proj.lastCachedUnresolvedImportsList; assert.strictEqual(version1, version2, "set of unresolved imports should change"); - baselineTsserverLogs("typingsInstaller", "cached unresolved typings are not recomputed if program structure did not change", session); + baselineTsserverLogs( + "typingsInstaller", + "cached unresolved typings are not recomputed if program structure did not change", + session, + ); }); it("multiple projects", () => { @@ -1249,7 +1324,15 @@ describe("unittests:: tsserver:: typingsInstaller:: General functionality", () = else { typingFiles = [jquery]; } - executeCommand(installer, requestId, packageNames, host, typingFiles.map(f => f.typings), typingFiles, cb); + executeCommand( + installer, + requestId, + packageNames, + host, + typingFiles.map(f => f.typings), + typingFiles, + cb, + ); }, { typesRegistry: ["jquery", "commander"] }, ); @@ -1397,34 +1480,81 @@ describe("unittests:: tsserver:: typingsInstaller:: Validate package name:", () }); it("package non URI safe characters are not supported", () => { assert.equal(validatePackageName(" scope "), NameValidationResult.NameContainsNonURISafeCharacters); - assert.equal(validatePackageName("; say ‘Hello from TypeScript!’ #"), NameValidationResult.NameContainsNonURISafeCharacters); + assert.equal( + validatePackageName("; say ‘Hello from TypeScript!’ #"), + NameValidationResult.NameContainsNonURISafeCharacters, + ); assert.equal(validatePackageName("a/b/c"), NameValidationResult.NameContainsNonURISafeCharacters); }); it("scoped package name is supported", () => { assert.equal(validatePackageName("@scope/bar"), NameValidationResult.Ok); }); it("scoped name in scoped package name cannot start with dot", () => { - assert.deepEqual(validatePackageName("@.scope/bar"), { name: ".scope", isScopeName: true, result: NameValidationResult.NameStartsWithDot }); - assert.deepEqual(validatePackageName("@.scope/.bar"), { name: ".scope", isScopeName: true, result: NameValidationResult.NameStartsWithDot }); + assert.deepEqual(validatePackageName("@.scope/bar"), { + name: ".scope", + isScopeName: true, + result: NameValidationResult.NameStartsWithDot, + }); + assert.deepEqual(validatePackageName("@.scope/.bar"), { + name: ".scope", + isScopeName: true, + result: NameValidationResult.NameStartsWithDot, + }); }); it("scope name in scoped package name cannot start with underscore", () => { - assert.deepEqual(validatePackageName("@_scope/bar"), { name: "_scope", isScopeName: true, result: NameValidationResult.NameStartsWithUnderscore }); - assert.deepEqual(validatePackageName("@_scope/_bar"), { name: "_scope", isScopeName: true, result: NameValidationResult.NameStartsWithUnderscore }); + assert.deepEqual(validatePackageName("@_scope/bar"), { + name: "_scope", + isScopeName: true, + result: NameValidationResult.NameStartsWithUnderscore, + }); + assert.deepEqual(validatePackageName("@_scope/_bar"), { + name: "_scope", + isScopeName: true, + result: NameValidationResult.NameStartsWithUnderscore, + }); }); it("scope name in scoped package name with non URI safe characters are not supported", () => { - assert.deepEqual(validatePackageName("@ scope /bar"), { name: " scope ", isScopeName: true, result: NameValidationResult.NameContainsNonURISafeCharacters }); - assert.deepEqual(validatePackageName("@; say ‘Hello from TypeScript!’ #/bar"), { name: "; say ‘Hello from TypeScript!’ #", isScopeName: true, result: NameValidationResult.NameContainsNonURISafeCharacters }); - assert.deepEqual(validatePackageName("@ scope / bar "), { name: " scope ", isScopeName: true, result: NameValidationResult.NameContainsNonURISafeCharacters }); + assert.deepEqual(validatePackageName("@ scope /bar"), { + name: " scope ", + isScopeName: true, + result: NameValidationResult.NameContainsNonURISafeCharacters, + }); + assert.deepEqual(validatePackageName("@; say ‘Hello from TypeScript!’ #/bar"), { + name: "; say ‘Hello from TypeScript!’ #", + isScopeName: true, + result: NameValidationResult.NameContainsNonURISafeCharacters, + }); + assert.deepEqual(validatePackageName("@ scope / bar "), { + name: " scope ", + isScopeName: true, + result: NameValidationResult.NameContainsNonURISafeCharacters, + }); }); it("package name in scoped package name cannot start with dot", () => { - assert.deepEqual(validatePackageName("@scope/.bar"), { name: ".bar", isScopeName: false, result: NameValidationResult.NameStartsWithDot }); + assert.deepEqual(validatePackageName("@scope/.bar"), { + name: ".bar", + isScopeName: false, + result: NameValidationResult.NameStartsWithDot, + }); }); it("package name in scoped package name cannot start with underscore", () => { - assert.deepEqual(validatePackageName("@scope/_bar"), { name: "_bar", isScopeName: false, result: NameValidationResult.NameStartsWithUnderscore }); + assert.deepEqual(validatePackageName("@scope/_bar"), { + name: "_bar", + isScopeName: false, + result: NameValidationResult.NameStartsWithUnderscore, + }); }); it("package name in scoped package name with non URI safe characters are not supported", () => { - assert.deepEqual(validatePackageName("@scope/ bar "), { name: " bar ", isScopeName: false, result: NameValidationResult.NameContainsNonURISafeCharacters }); - assert.deepEqual(validatePackageName("@scope/; say ‘Hello from TypeScript!’ #"), { name: "; say ‘Hello from TypeScript!’ #", isScopeName: false, result: NameValidationResult.NameContainsNonURISafeCharacters }); + assert.deepEqual(validatePackageName("@scope/ bar "), { + name: " bar ", + isScopeName: false, + result: NameValidationResult.NameContainsNonURISafeCharacters, + }); + assert.deepEqual(validatePackageName("@scope/; say ‘Hello from TypeScript!’ #"), { + name: "; say ‘Hello from TypeScript!’ #", + isScopeName: false, + result: NameValidationResult.NameContainsNonURISafeCharacters, + }); }); }); @@ -1477,7 +1607,18 @@ describe("unittests:: tsserver:: typingsInstaller:: discover typings", () => { const host = createServerHost([app, jquery, chroma]); const logger = trackingLogger(); - const result = ts.JsTyping.discoverTypings(host, logger.log, [app.path, jquery.path, chroma.path], ts.getDirectoryPath(app.path as ts.Path), safeList, ts.emptyMap, { enable: true }, ts.emptyArray, ts.emptyMap, ts.emptyOptions); + const result = ts.JsTyping.discoverTypings( + host, + logger.log, + [app.path, jquery.path, chroma.path], + ts.getDirectoryPath(app.path as ts.Path), + safeList, + ts.emptyMap, + { enable: true }, + ts.emptyArray, + ts.emptyMap, + ts.emptyOptions, + ); const finish = logger.finish(); assert.deepEqual(finish, [ 'Inferred typings from file names: ["jquery","chroma-js"]', @@ -1497,7 +1638,18 @@ describe("unittests:: tsserver:: typingsInstaller:: discover typings", () => { for (const name of ts.JsTyping.nodeCoreModuleList) { const logger = trackingLogger(); - const result = ts.JsTyping.discoverTypings(host, logger.log, [f.path], ts.getDirectoryPath(f.path as ts.Path), emptySafeList, cache, { enable: true }, [name, "somename"], ts.emptyMap, ts.emptyOptions); + const result = ts.JsTyping.discoverTypings( + host, + logger.log, + [f.path], + ts.getDirectoryPath(f.path as ts.Path), + emptySafeList, + cache, + { enable: true }, + [name, "somename"], + ts.emptyMap, + ts.emptyOptions, + ); assert.deepEqual(logger.finish(), [ 'Inferred typings from unresolved imports: ["node","somename"]', 'Result: {"cachedTypingPaths":[],"newTypingNames":["node","somename"],"filesToWatch":["/a/b/bower_components","/a/b/node_modules"]}', @@ -1516,10 +1668,25 @@ describe("unittests:: tsserver:: typingsInstaller:: discover typings", () => { content: "", }; const host = createServerHost([f, node]); - const cache = new Map(Object.entries({ node: { typingLocation: node.path, version: new ts.Version("1.3.0") } })); + const cache = new Map( + Object.entries({ + node: { typingLocation: node.path, version: new ts.Version("1.3.0") }, + }), + ); const registry = createTypesRegistry("node"); const logger = trackingLogger(); - const result = ts.JsTyping.discoverTypings(host, logger.log, [f.path], ts.getDirectoryPath(f.path as ts.Path), emptySafeList, cache, { enable: true }, ["fs", "bar"], registry, ts.emptyOptions); + const result = ts.JsTyping.discoverTypings( + host, + logger.log, + [f.path], + ts.getDirectoryPath(f.path as ts.Path), + emptySafeList, + cache, + { enable: true }, + ["fs", "bar"], + registry, + ts.emptyOptions, + ); assert.deepEqual(logger.finish(), [ 'Inferred typings from unresolved imports: ["node","bar"]', 'Result: {"cachedTypingPaths":["/a/b/node.d.ts"],"newTypingNames":["bar"],"filesToWatch":["/a/b/bower_components","/a/b/node_modules"]}', @@ -1538,9 +1705,24 @@ describe("unittests:: tsserver:: typingsInstaller:: discover typings", () => { content: "", }; const host = createServerHost([f, node]); - const cache = new Map(Object.entries({ node: { typingLocation: node.path, version: new ts.Version("1.3.0") } })); + const cache = new Map( + Object.entries({ + node: { typingLocation: node.path, version: new ts.Version("1.3.0") }, + }), + ); const logger = trackingLogger(); - const result = ts.JsTyping.discoverTypings(host, logger.log, [f.path], ts.getDirectoryPath(f.path as ts.Path), emptySafeList, cache, { enable: true }, ["fs", "bar"], ts.emptyMap, ts.emptyOptions); + const result = ts.JsTyping.discoverTypings( + host, + logger.log, + [f.path], + ts.getDirectoryPath(f.path as ts.Path), + emptySafeList, + cache, + { enable: true }, + ["fs", "bar"], + ts.emptyMap, + ts.emptyOptions, + ); assert.deepEqual(logger.finish(), [ 'Inferred typings from unresolved imports: ["node","bar"]', 'Result: {"cachedTypingPaths":[],"newTypingNames":["node","bar"],"filesToWatch":["/a/b/bower_components","/a/b/node_modules"]}', @@ -1565,7 +1747,18 @@ describe("unittests:: tsserver:: typingsInstaller:: discover typings", () => { const host = createServerHost([app, a, b]); const cache = new Map(); const logger = trackingLogger(); - const result = ts.JsTyping.discoverTypings(host, logger.log, [app.path], ts.getDirectoryPath(app.path as ts.Path), emptySafeList, cache, { enable: true }, /*unresolvedImports*/ [], ts.emptyMap, ts.emptyOptions); + const result = ts.JsTyping.discoverTypings( + host, + logger.log, + [app.path], + ts.getDirectoryPath(app.path as ts.Path), + emptySafeList, + cache, + { enable: true }, + /*unresolvedImports*/ [], + ts.emptyMap, + ts.emptyOptions, + ); assert.deepEqual(logger.finish(), [ 'Searching for typing names in /node_modules; all files: ["/node_modules/a/package.json"]', ' Found package names: ["a"]', @@ -1591,7 +1784,18 @@ describe("unittests:: tsserver:: typingsInstaller:: discover typings", () => { const host = createServerHost([app, a]); const cache = new Map(); const logger = trackingLogger(); - const result = ts.JsTyping.discoverTypings(host, logger.log, [app.path], ts.getDirectoryPath(app.path as ts.Path), emptySafeList, cache, { enable: true }, /*unresolvedImports*/ [], ts.emptyMap, ts.emptyOptions); + const result = ts.JsTyping.discoverTypings( + host, + logger.log, + [app.path], + ts.getDirectoryPath(app.path as ts.Path), + emptySafeList, + cache, + { enable: true }, + /*unresolvedImports*/ [], + ts.emptyMap, + ts.emptyOptions, + ); assert.deepEqual(logger.finish(), [ 'Searching for typing names in /node_modules; all files: ["/node_modules/@a/b/package.json"]', ' Found package names: ["@a/b"]', @@ -1625,7 +1829,18 @@ describe("unittests:: tsserver:: typingsInstaller:: discover typings", () => { })); const registry = createTypesRegistry("node", "commander"); const logger = trackingLogger(); - const result = ts.JsTyping.discoverTypings(host, logger.log, [app.path], ts.getDirectoryPath(app.path as ts.Path), emptySafeList, cache, { enable: true }, ["http", "commander"], registry, ts.emptyOptions); + const result = ts.JsTyping.discoverTypings( + host, + logger.log, + [app.path], + ts.getDirectoryPath(app.path as ts.Path), + emptySafeList, + cache, + { enable: true }, + ["http", "commander"], + registry, + ts.emptyOptions, + ); assert.deepEqual(logger.finish(), [ 'Inferred typings from unresolved imports: ["node","commander"]', 'Result: {"cachedTypingPaths":["/a/cache/node_modules/@types/node/index.d.ts"],"newTypingNames":["commander"],"filesToWatch":["/a/bower_components","/a/node_modules"]}', @@ -1651,7 +1866,18 @@ describe("unittests:: tsserver:: typingsInstaller:: discover typings", () => { const registry = createTypesRegistry("node"); registry.delete(`ts${ts.versionMajorMinor}`); const logger = trackingLogger(); - const result = ts.JsTyping.discoverTypings(host, logger.log, [app.path], ts.getDirectoryPath(app.path as ts.Path), emptySafeList, cache, { enable: true }, ["http"], registry, ts.emptyOptions); + const result = ts.JsTyping.discoverTypings( + host, + logger.log, + [app.path], + ts.getDirectoryPath(app.path as ts.Path), + emptySafeList, + cache, + { enable: true }, + ["http"], + registry, + ts.emptyOptions, + ); assert.deepEqual(logger.finish(), [ 'Inferred typings from unresolved imports: ["node"]', 'Result: {"cachedTypingPaths":[],"newTypingNames":["node"],"filesToWatch":["/a/bower_components","/a/node_modules"]}', @@ -1682,7 +1908,18 @@ describe("unittests:: tsserver:: typingsInstaller:: discover typings", () => { const registry = createTypesRegistry("node", "commander"); registry.get("node")![`ts${ts.versionMajorMinor}`] = "1.3.0-next.1"; const logger = trackingLogger(); - const result = ts.JsTyping.discoverTypings(host, logger.log, [app.path], ts.getDirectoryPath(app.path as ts.Path), emptySafeList, cache, { enable: true }, ["http", "commander"], registry, ts.emptyOptions); + const result = ts.JsTyping.discoverTypings( + host, + logger.log, + [app.path], + ts.getDirectoryPath(app.path as ts.Path), + emptySafeList, + cache, + { enable: true }, + ["http", "commander"], + registry, + ts.emptyOptions, + ); assert.deepEqual(logger.finish(), [ 'Inferred typings from unresolved imports: ["node","commander"]', 'Result: {"cachedTypingPaths":[],"newTypingNames":["node","commander"],"filesToWatch":["/a/bower_components","/a/node_modules"]}', @@ -2282,8 +2519,14 @@ describe("unittests:: tsserver:: typingsInstaller:: npm installation command", ( "@types/react-content-loader@ts2.8", ]; const expectedCommands = [ - ts.server.typingsInstaller.getNpmCommandForInstallation(npmPath, tsVersion, packageNames, packageNames.length).command, - ts.server.typingsInstaller.getNpmCommandForInstallation(npmPath, tsVersion, packageNames, packageNames.length - Math.ceil(packageNames.length / 2)).command, + ts.server.typingsInstaller.getNpmCommandForInstallation(npmPath, tsVersion, packageNames, packageNames.length) + .command, + ts.server.typingsInstaller.getNpmCommandForInstallation( + npmPath, + tsVersion, + packageNames, + packageNames.length - Math.ceil(packageNames.length / 2), + ).command, ]; it("works when the command is too long to install all packages at once", () => { const commands: string[] = []; @@ -2312,12 +2555,18 @@ describe("unittests:: tsserver:: typingsInstaller:: recomputing resolutions of u const foooPath = "/a/b/node_modules/fooo/index.d.ts"; function verifyResolvedModuleOfFooo(project: ts.server.Project) { ts.server.updateProjectIfDirty(project); - const foooResolution = project.getLanguageService().getProgram()!.getSourceFileByPath(appPath)!.resolvedModules!.get("fooo", /*mode*/ undefined)!.resolvedModule!; + const foooResolution = project.getLanguageService().getProgram()!.getSourceFileByPath(appPath)!.resolvedModules! + .get("fooo", /*mode*/ undefined)!.resolvedModule!; assert.equal(foooResolution.resolvedFileName, foooPath); return foooResolution; } - function verifyUnresolvedImportResolutions(scenario: string, appContents: string, typingNames: string[], typingFiles: File[]) { + function verifyUnresolvedImportResolutions( + scenario: string, + appContents: string, + typingNames: string[], + typingFiles: File[], + ) { const app: File = { path: appPath, content: `${appContents}import * as x from "fooo";`, @@ -2507,11 +2756,25 @@ describe("unittests:: tsserver:: typingsInstaller:: tsserver:: with inferred Pro }), }; - const files = [file, packageJsonInCurrentDirectory, packageJsonOfPkgcurrentdirectory, indexOfPkgcurrentdirectory, typingsCachePackageJson, typingsCachePackageLockJson]; + const files = [ + file, + packageJsonInCurrentDirectory, + packageJsonOfPkgcurrentdirectory, + indexOfPkgcurrentdirectory, + typingsCachePackageJson, + typingsCachePackageLockJson, + ]; const host = createServerHost(files, { currentDirectory }); const logger = createLoggerWithInMemoryLogs(host); - const typingsInstaller = new TestTypingsInstaller(typingsCache, /*throttleLimit*/ 5, host, logger, /*workerConstructor*/ undefined, "pkgcurrentdirectory"); + const typingsInstaller = new TestTypingsInstaller( + typingsCache, + /*throttleLimit*/ 5, + host, + logger, + /*workerConstructor*/ undefined, + "pkgcurrentdirectory", + ); const projectService = createProjectService(host, { typingsInstaller, logger }); diff --git a/src/testRunner/unittests/tsserver/versionCache.ts b/src/testRunner/unittests/tsserver/versionCache.ts index fefccff86f876..bd44bb4a4c6df 100644 --- a/src/testRunner/unittests/tsserver/versionCache.ts +++ b/src/testRunner/unittests/tsserver/versionCache.ts @@ -9,7 +9,13 @@ function lineColToPosition(lineIndex: ts.server.LineIndex, line: number, col: nu return lineIndex.absolutePositionOfStartOfLine(line) + (col - 1); } -function validateEdit(lineIndex: ts.server.LineIndex, sourceText: string, position: number, deleteLength: number, insertString: string): void { +function validateEdit( + lineIndex: ts.server.LineIndex, + sourceText: string, + position: number, + deleteLength: number, + insertString: string, +): void { const checkText = editFlat(position, deleteLength, insertString, sourceText); const snapshot = lineIndex.edit(position, deleteLength, insertString); const editedText = snapshot.getText(0, snapshot.getLength()); @@ -155,7 +161,11 @@ and grew 1cm per day`; }); it(`Insert multiple line breaks`, () => { - validateEditAtPosition(21, 1, "cr...\r\ncr...\r\ncr...\r\ncr...\r\ncr...\r\ncr...\r\ncr...\r\ncr...\r\ncr...\r\ncr...\r\ncr...\r\ncr"); + validateEditAtPosition( + 21, + 1, + "cr...\r\ncr...\r\ncr...\r\ncr...\r\ncr...\r\ncr...\r\ncr...\r\ncr...\r\ncr...\r\ncr...\r\ncr...\r\ncr", + ); }); it(`Insert multiple line breaks`, () => { @@ -315,7 +325,11 @@ describe(`unittests:: tsserver:: VersionCache stress test`, () => { const lp = lineIndex.positionToLineOffset(rsa[i]); const lac = ts.computeLineAndCharacterOfPosition(lineMap, rsa[i]); assert.equal(lac.line + 1, lp.line, "Line number mismatch " + (lac.line + 1) + " " + lp.line + " " + i); - assert.equal(lac.character, lp.offset - 1, "Character offset mismatch " + lac.character + " " + (lp.offset - 1) + " " + i); + assert.equal( + lac.character, + lp.offset - 1, + "Character offset mismatch " + lac.character + " " + (lp.offset - 1) + " " + i, + ); } }); diff --git a/src/testRunner/unittests/tsserver/watchEnvironment.ts b/src/testRunner/unittests/tsserver/watchEnvironment.ts index 49f69189c7db5..9de1ce5fdedeb 100644 --- a/src/testRunner/unittests/tsserver/watchEnvironment.ts +++ b/src/testRunner/unittests/tsserver/watchEnvironment.ts @@ -136,7 +136,9 @@ it(`unittests:: tsserver:: watchEnvironment:: tsserverProjectSystem recursive wa }; const environmentVariables = new Map(); environmentVariables.set("TSC_WATCHDIRECTORY", Tsc_WatchDirectory.NonRecursiveWatchDirectory); - const host = createServerHost([index, file1, configFile, libFile, nodeModulesExistingUnusedFile], { environmentVariables }); + const host = createServerHost([index, file1, configFile, libFile, nodeModulesExistingUnusedFile], { + environmentVariables, + }); const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) }); openFilesForSession([index], session); @@ -175,7 +177,11 @@ it(`unittests:: tsserver:: watchEnvironment:: tsserverProjectSystem recursive wa session.testhost.logTimeoutQueueLength(); }); - baselineTsserverLogs("watchEnvironment", `recursive directory does not watch files starting with dot in node_modules`, session); + baselineTsserverLogs( + "watchEnvironment", + `recursive directory does not watch files starting with dot in node_modules`, + session, + ); }); it("unittests:: tsserver:: watchEnvironment:: tsserverProjectSystem watching files with network style paths", () => { @@ -196,7 +202,9 @@ it("unittests:: tsserver:: watchEnvironment:: tsserverProjectSystem watching fil ); logger.host = host; logger.info(`For files of style ${path}`); - logger.log(`currentDirectory:: ${host.getCurrentDirectory()} useCaseSensitiveFileNames: ${host.useCaseSensitiveFileNames}`); + logger.log( + `currentDirectory:: ${host.getCurrentDirectory()} useCaseSensitiveFileNames: ${host.useCaseSensitiveFileNames}`, + ); const session = createSession(host, { logger }); openFilesForSession([file], session); } @@ -251,7 +259,10 @@ describe("unittests:: tsserver:: watchEnvironment:: handles watch compiler optio content: "{}", }; const files = [libFile, commonFile2, configFile]; - const host = createServerHost(files.concat(commonFile1), { runWithoutRecursiveWatches: true, runWithFallbackPolling: true }); + const host = createServerHost(files.concat(commonFile1), { + runWithoutRecursiveWatches: true, + runWithFallbackPolling: true, + }); const logger = createLoggerWithInMemoryLogs(host); const session = createSession(host, { logger }); session.executeCommandSeq({ @@ -310,7 +321,10 @@ describe("unittests:: tsserver:: watchEnvironment:: handles watch compiler optio }), }; const files = [libFile, commonFile2, configFile]; - const host = createServerHost(files.concat(commonFile1), { runWithoutRecursiveWatches: true, runWithFallbackPolling: true }); + const host = createServerHost(files.concat(commonFile1), { + runWithoutRecursiveWatches: true, + runWithFallbackPolling: true, + }); const logger = createLoggerWithInMemoryLogs(host); const session = createSession(host, { logger }); session.executeCommandSeq({ @@ -421,7 +435,10 @@ describe("unittests:: tsserver:: watchEnvironment:: handles watch compiler optio const { main, bar, foo } = setupFiles(); const files = [libFile, main, bar, foo]; const host = createServerHost(files, { currentDirectory: "/user/username/projects/myproject" }); - const session = createSession(host, { useInferredProjectPerProjectRoot: true, logger: createLoggerWithInMemoryLogs(host) }); + const session = createSession(host, { + useInferredProjectPerProjectRoot: true, + logger: createLoggerWithInMemoryLogs(host), + }); setupConfigureHost(session, configureHost); setCompilerOptionsForInferredProjectsRequestForSession({ options: { excludeDirectories: ["node_modules"] }, @@ -445,8 +462,14 @@ describe("unittests:: tsserver:: watchEnvironment:: handles watch compiler optio const { main, bar, foo } = setupFiles(); const files = [libFile, main, bar, foo]; const host = createServerHost(files, { currentDirectory: "/user/username/projects/myproject" }); - const service = createProjectService(host, { useInferredProjectPerProjectRoot: true, logger: createLoggerWithInMemoryLogs(host) }); - service.setCompilerOptionsForInferredProjects({ excludeDirectories: ["**/../*"] }, "/user/username/projects/myproject"); + const service = createProjectService(host, { + useInferredProjectPerProjectRoot: true, + logger: createLoggerWithInMemoryLogs(host), + }); + service.setCompilerOptionsForInferredProjects( + { excludeDirectories: ["**/../*"] }, + "/user/username/projects/myproject", + ); service.openClientFile(main.path, main.content, ts.ScriptKind.TS, "/user/username/projects/myproject"); const project = service.inferredProjects[0]; service.logger.info(JSON.stringify(project.getAllProjectErrors(), undefined, 2)); diff --git a/src/tsserver/nodeServer.ts b/src/tsserver/nodeServer.ts index 0ed4bac6b228a..169703e9e6e65 100644 --- a/src/tsserver/nodeServer.ts +++ b/src/tsserver/nodeServer.ts @@ -136,8 +136,8 @@ function parseLoggingEnvironmentString(logEnvStr: string | undefined): LogOption let pathStart = args[initialIndex]; let extraPartCounter = 0; if ( - pathStart.charCodeAt(0) === CharacterCodes.doubleQuote && - pathStart.charCodeAt(pathStart.length - 1) !== CharacterCodes.doubleQuote + pathStart.charCodeAt(0) === CharacterCodes.doubleQuote + && pathStart.charCodeAt(pathStart.length - 1) !== CharacterCodes.doubleQuote ) { for (let i = initialIndex + 1; i < args.length; i++) { pathStart += " "; @@ -170,7 +170,11 @@ function parseServerMode(): LanguageServiceMode | string | undefined { export function initializeNodeSystem(): StartInput { const sys = Debug.checkDefined(ts.sys) as ServerHost; const childProcess: { - execFileSync(file: string, args: string[], options: { stdio: "ignore"; env: MapLike; }): string | Buffer; + execFileSync( + file: string, + args: string[], + options: { stdio: "ignore"; env: MapLike; }, + ): string | Buffer; } = require("child_process"); interface Stats { @@ -321,7 +325,10 @@ export function initializeNodeSystem(): StartInput { let canWrite = true; if (useWatchGuard) { - const currentDrive = extractWatchDirectoryCacheKey(sys.resolvePath(sys.getCurrentDirectory()), /*currentDriveKey*/ undefined); + const currentDrive = extractWatchDirectoryCacheKey( + sys.resolvePath(sys.getCurrentDirectory()), + /*currentDriveKey*/ undefined, + ); const statusCache = new Map(); sys.watchDirectory = (path, callback, recursive, options) => { const cacheKey = extractWatchDirectoryCacheKey(path, currentDrive); @@ -335,7 +342,10 @@ export function initializeNodeSystem(): StartInput { if (logger.hasLevel(LogLevel.verbose)) { logger.info(`Starting ${process.execPath} with args:${stringifyIndented(args)}`); } - childProcess.execFileSync(process.execPath, args, { stdio: "ignore", env: { ELECTRON_RUN_AS_NODE: "1" } }); + childProcess.execFileSync(process.execPath, args, { + stdio: "ignore", + env: { ELECTRON_RUN_AS_NODE: "1" }, + }); status = true; if (logger.hasLevel(LogLevel.verbose)) { logger.info(`WatchGuard for path ${path} returned: OK`); @@ -481,7 +491,12 @@ export function initializeNodeSystem(): StartInput { // This is the function that catches the exceptions when watching directory, and yet lets project service continue to function // Eg. on linux the number of watches are limited and one could easily exhaust watches and the exception ENOSPC is thrown when creating watcher at that point - function watchDirectorySwallowingException(path: string, callback: DirectoryWatcherCallback, recursive?: boolean, options?: WatchOptions): FileWatcher { + function watchDirectorySwallowingException( + path: string, + callback: DirectoryWatcherCallback, + recursive?: boolean, + options?: WatchOptions, + ): FileWatcher { try { return originalWatchDirectory(path, callback, recursive, options); } @@ -498,7 +513,11 @@ function parseEventPort(eventPortStr: string | undefined) { } function startNodeSession(options: StartSessionOptions, logger: Logger, cancellationToken: ServerCancellationToken) { const childProcess: { - fork(modulePath: string, args: string[], options?: { execArgv: string[]; env?: MapLike; }): NodeChildProcess; + fork( + modulePath: string, + args: string[], + options?: { execArgv: string[]; env?: MapLike; }, + ): NodeChildProcess; } = require("child_process"); const os: { @@ -542,7 +561,10 @@ function startNodeSession(options: StartSessionOptions, logger: Logger, cancella // buffer, but we have yet to find a way to retrieve that value. private static readonly maxActiveRequestCount = 10; private static readonly requestDelayMillis = 100; - private packageInstalledPromise: { resolve(value: ApplyCodeActionCommandResult): void; reject(reason: unknown): void; } | undefined; + private packageInstalledPromise: { + resolve(value: ApplyCodeActionCommandResult): void; + reject(reason: unknown): void; + } | undefined; constructor( private readonly telemetryEnabled: boolean, @@ -592,7 +614,13 @@ function startNodeSession(options: StartSessionOptions, logger: Logger, cancella args.push(Arguments.EnableTelemetry); } if (this.logger.loggingEnabled() && this.logger.getLogFileName()) { - args.push(Arguments.LogFile, combinePaths(getDirectoryPath(normalizeSlashes(this.logger.getLogFileName()!)), `ti-${process.pid}.log`)); + args.push( + Arguments.LogFile, + combinePaths( + getDirectoryPath(normalizeSlashes(this.logger.getLogFileName()!)), + `ti-${process.pid}.log`, + ), + ); } if (this.typingSafeListLocation) { args.push(Arguments.TypingSafeListLocation, this.typingSafeListLocation); @@ -644,7 +672,11 @@ function startNodeSession(options: StartSessionOptions, logger: Logger, cancella this.installer.send(rq); } - enqueueInstallTypingsRequest(project: Project, typeAcquisition: TypeAcquisition, unresolvedImports: SortedReadonlyArray): void { + enqueueInstallTypingsRequest( + project: Project, + typeAcquisition: TypeAcquisition, + unresolvedImports: SortedReadonlyArray, + ): void { const request = createInstallTypingsRequest(project, typeAcquisition, unresolvedImports); if (this.logger.hasLevel(LogLevel.verbose)) { if (this.logger.hasLevel(LogLevel.verbose)) { @@ -673,7 +705,17 @@ function startNodeSession(options: StartSessionOptions, logger: Logger, cancella } } - private handleMessage(response: TypesRegistryResponse | PackageInstalledResponse | SetTypings | InvalidateCachedTypings | BeginInstallTypes | EndInstallTypes | InitializationFailedResponse | server.WatchTypingLocations) { + private handleMessage( + response: + | TypesRegistryResponse + | PackageInstalledResponse + | SetTypings + | InvalidateCachedTypings + | BeginInstallTypes + | EndInstallTypes + | InitializationFailedResponse + | server.WatchTypingLocations, + ) { if (this.logger.hasLevel(LogLevel.verbose)) { this.logger.info(`Received response:${stringifyIndented(response)}`); } @@ -702,7 +744,8 @@ function startNodeSession(options: StartSessionOptions, logger: Logger, cancella const body: protocol.TypesInstallerInitializationFailedEventBody = { message: response.message, }; - const eventName: protocol.TypesInstallerInitializationFailedEventName = "typesInstallerInitializationFailed"; + const eventName: protocol.TypesInstallerInitializationFailedEventName = + "typesInstallerInitializationFailed"; this.event(body, eventName); break; } @@ -802,7 +845,17 @@ function startNodeSession(options: StartSessionOptions, logger: Logger, cancella const typingsInstaller = disableAutomaticTypingAcquisition ? undefined - : new NodeTypingsInstaller(telemetryEnabled, logger, host, getGlobalTypingsCacheLocation(), typingSafeListLocation, typesMapLocation, npmLocation, validateDefaultNpmLocation, event); + : new NodeTypingsInstaller( + telemetryEnabled, + logger, + host, + getGlobalTypingsCacheLocation(), + typingSafeListLocation, + typesMapLocation, + npmLocation, + validateDefaultNpmLocation, + event, + ); super({ host, @@ -834,7 +887,10 @@ function startNodeSession(options: StartSessionOptions, logger: Logger, cancella } override event(body: T, eventName: string): void { - Debug.assert(!!this.constructed, "Should only call `IOSession.prototype.event` on an initialized IOSession"); + Debug.assert( + !!this.constructed, + "Should only call `IOSession.prototype.event` on an initialized IOSession", + ); if (this.canUseEvents && this.eventPort) { if (!this.eventSocket) { @@ -855,7 +911,10 @@ function startNodeSession(options: StartSessionOptions, logger: Logger, cancella } private writeToEventSocket(body: object, eventName: string): void { - this.eventSocket!.write(formatMessage(toEvent(eventName, body), this.logger, this.byteLength, this.host.newLine), "utf8"); + this.eventSocket!.write( + formatMessage(toEvent(eventName, body), this.logger, this.byteLength, this.host.newLine), + "utf8", + ); } override exit() { @@ -909,7 +968,8 @@ function startNodeSession(options: StartSessionOptions, logger: Logger, cancella const eventPort: number | undefined = parseEventPort(findArgument("--eventPort")); const typingSafeListLocation = findArgument(Arguments.TypingSafeListLocation)!; // TODO: GH#18217 - const typesMapLocation = findArgument(Arguments.TypesMapLocation) || combinePaths(getDirectoryPath(sys.getExecutingFilePath()), "typesMap.json"); + const typesMapLocation = findArgument(Arguments.TypesMapLocation) + || combinePaths(getDirectoryPath(sys.getExecutingFilePath()), "typesMap.json"); const npmLocation = findArgument(Arguments.NpmLocation); const validateDefaultNpmLocation = hasArgument(Arguments.ValidateDefaultNpmLocation); const disableAutomaticTypingAcquisition = hasArgument("--disableAutomaticTypingAcquisition"); @@ -935,13 +995,17 @@ function startNodeSession(options: StartSessionOptions, logger: Logger, cancella function getGlobalTypingsCacheLocation() { switch (process.platform) { case "win32": { - const basePath = process.env.LOCALAPPDATA || - process.env.APPDATA || - (os.homedir && os.homedir()) || - process.env.USERPROFILE || - (process.env.HOMEDRIVE && process.env.HOMEPATH && normalizeSlashes(process.env.HOMEDRIVE + process.env.HOMEPATH)) || - os.tmpdir(); - return combinePaths(combinePaths(normalizeSlashes(basePath), "Microsoft/TypeScript"), versionMajorMinor); + const basePath = process.env.LOCALAPPDATA + || process.env.APPDATA + || (os.homedir && os.homedir()) + || process.env.USERPROFILE + || (process.env.HOMEDRIVE && process.env.HOMEPATH + && normalizeSlashes(process.env.HOMEDRIVE + process.env.HOMEPATH)) + || os.tmpdir(); + return combinePaths( + combinePaths(normalizeSlashes(basePath), "Microsoft/TypeScript"), + versionMajorMinor, + ); } case "openbsd": case "freebsd": @@ -962,10 +1026,10 @@ function startNodeSession(options: StartSessionOptions, logger: Logger, cancella return process.env.XDG_CACHE_HOME; } const usersDir = platformIsDarwin ? "Users" : "home"; - const homePath = (os.homedir && os.homedir()) || - process.env.HOME || - ((process.env.LOGNAME || process.env.USER) && `/${usersDir}/${process.env.LOGNAME || process.env.USER}`) || - os.tmpdir(); + const homePath = (os.homedir && os.homedir()) + || process.env.HOME + || ((process.env.LOGNAME || process.env.USER) && `/${usersDir}/${process.env.LOGNAME || process.env.USER}`) + || os.tmpdir(); const cacheFolder = platformIsDarwin ? "Library/Caches" : ".cache"; diff --git a/src/tsserver/server.ts b/src/tsserver/server.ts index 9ee38169e0057..4bb3fd289c0b7 100644 --- a/src/tsserver/server.ts +++ b/src/tsserver/server.ts @@ -23,11 +23,16 @@ function findArgumentStringArray(argName: string): readonly string[] { return arg.split(",").filter(name => name !== ""); } -function start({ args, logger, cancellationToken, serverMode, unknownServerMode, startSession: startServer }: StartInput, platform: string) { +function start( + { args, logger, cancellationToken, serverMode, unknownServerMode, startSession: startServer }: StartInput, + platform: string, +) { logger.info(`Starting TS Server`); logger.info(`Version: ${version}`); logger.info(`Arguments: ${args.join(" ")}`); - logger.info(`Platform: ${platform} NodeVersion: ${process.version} CaseSensitive: ${sys.useCaseSensitiveFileNames}`); + logger.info( + `Platform: ${platform} NodeVersion: ${process.version} CaseSensitive: ${sys.useCaseSensitiveFileNames}`, + ); logger.info(`ServerMode: ${serverMode} hasUnknownServerMode: ${unknownServerMode}`); setStackTraceLimit(); diff --git a/src/typingsInstaller/nodeTypingsInstaller.ts b/src/typingsInstaller/nodeTypingsInstaller.ts index 841e106ef925f..3c1303aec5b6b 100644 --- a/src/typingsInstaller/nodeTypingsInstaller.ts +++ b/src/typingsInstaller/nodeTypingsInstaller.ts @@ -56,7 +56,11 @@ class FileLog implements Log { } /** Used if `--npmLocation` is not passed. */ -function getDefaultNPMLocation(processName: string, validateDefaultNpmLocation: boolean, host: InstallTypingHost): string { +function getDefaultNPMLocation( + processName: string, + validateDefaultNpmLocation: boolean, + host: InstallTypingHost, +): string { if (path.basename(processName).indexOf("node") === 0) { const npmPath = path.join(path.dirname(process.argv[0]), "npm"); if (!validateDefaultNpmLocation) { @@ -73,7 +77,11 @@ interface TypesRegistryFile { entries: MapLike>; } -function loadTypesRegistryFile(typesRegistryFilePath: string, host: InstallTypingHost, log: Log): Map> { +function loadTypesRegistryFile( + typesRegistryFilePath: string, + host: InstallTypingHost, + log: Log, +): Map> { if (!host.fileExists(typesRegistryFilePath)) { if (log.isEnabled()) { log.writeLine(`Types registry file '${typesRegistryFilePath}' does not exist`); @@ -86,7 +94,11 @@ function loadTypesRegistryFile(typesRegistryFilePath: string, host: InstallTypin } catch (e) { if (log.isEnabled()) { - log.writeLine(`Error when loading types registry file '${typesRegistryFilePath}': ${(e as Error).message}, ${(e as Error).stack}`); + log.writeLine( + `Error when loading types registry file '${typesRegistryFilePath}': ${(e as Error).message}, ${ + (e as Error).stack + }`, + ); } return new Map>(); } @@ -94,7 +106,10 @@ function loadTypesRegistryFile(typesRegistryFilePath: string, host: InstallTypin const typesRegistryPackageName = "types-registry"; function getTypesRegistryFileLocation(globalTypingsCacheLocation: string): string { - return combinePaths(normalizeSlashes(globalTypingsCacheLocation), `node_modules/${typesRegistryPackageName}/index.json`); + return combinePaths( + normalizeSlashes(globalTypingsCacheLocation), + `node_modules/${typesRegistryPackageName}/index.json`, + ); } interface ExecSyncOptions { @@ -110,17 +125,33 @@ export class NodeTypingsInstaller extends TypingsInstaller { private delayedInitializationError: InitializationFailedResponse | undefined; - constructor(globalTypingsCacheLocation: string, typingSafeListLocation: string, typesMapLocation: string, npmLocation: string | undefined, validateDefaultNpmLocation: boolean, throttleLimit: number, log: Log) { + constructor( + globalTypingsCacheLocation: string, + typingSafeListLocation: string, + typesMapLocation: string, + npmLocation: string | undefined, + validateDefaultNpmLocation: boolean, + throttleLimit: number, + log: Log, + ) { const libDirectory = getDirectoryPath(normalizePath(sys.getExecutingFilePath())); super( sys, globalTypingsCacheLocation, - typingSafeListLocation ? toPath(typingSafeListLocation, "", createGetCanonicalFileName(sys.useCaseSensitiveFileNames)) : toPath("typingSafeList.json", libDirectory, createGetCanonicalFileName(sys.useCaseSensitiveFileNames)), - typesMapLocation ? toPath(typesMapLocation, "", createGetCanonicalFileName(sys.useCaseSensitiveFileNames)) : toPath("typesMap.json", libDirectory, createGetCanonicalFileName(sys.useCaseSensitiveFileNames)), + typingSafeListLocation + ? toPath(typingSafeListLocation, "", createGetCanonicalFileName(sys.useCaseSensitiveFileNames)) + : toPath( + "typingSafeList.json", + libDirectory, + createGetCanonicalFileName(sys.useCaseSensitiveFileNames), + ), + typesMapLocation ? toPath(typesMapLocation, "", createGetCanonicalFileName(sys.useCaseSensitiveFileNames)) + : toPath("typesMap.json", libDirectory, createGetCanonicalFileName(sys.useCaseSensitiveFileNames)), throttleLimit, log, ); - this.npmPath = npmLocation !== undefined ? npmLocation : getDefaultNPMLocation(process.argv[0], validateDefaultNpmLocation, this.installTypingHost); + this.npmPath = npmLocation !== undefined ? npmLocation + : getDefaultNPMLocation(process.argv[0], validateDefaultNpmLocation, this.installTypingHost); // If the NPM path contains spaces and isn't wrapped in quotes, do so. if (stringContains(this.npmPath, " ") && this.npmPath[0] !== `"`) { @@ -128,7 +159,11 @@ export class NodeTypingsInstaller extends TypingsInstaller { } if (this.log.isEnabled()) { this.log.writeLine(`Process id: ${process.pid}`); - this.log.writeLine(`NPM location: ${this.npmPath} (explicit '${Arguments.NpmLocation}' ${npmLocation === undefined ? "not " : ""} provided)`); + this.log.writeLine( + `NPM location: ${this.npmPath} (explicit '${Arguments.NpmLocation}' ${ + npmLocation === undefined ? "not " : "" + } provided)`, + ); this.log.writeLine(`validateDefaultNpmLocation: ${validateDefaultNpmLocation}`); } ({ execSync: this.nodeExecSync } = require("child_process")); @@ -139,7 +174,10 @@ export class NodeTypingsInstaller extends TypingsInstaller { if (this.log.isEnabled()) { this.log.writeLine(`Updating ${typesRegistryPackageName} npm package...`); } - this.execSyncAndLog(`${this.npmPath} install --ignore-scripts ${typesRegistryPackageName}@${this.latestDistTag}`, { cwd: globalTypingsCacheLocation }); + this.execSyncAndLog( + `${this.npmPath} install --ignore-scripts ${typesRegistryPackageName}@${this.latestDistTag}`, + { cwd: globalTypingsCacheLocation }, + ); if (this.log.isEnabled()) { this.log.writeLine(`Updated ${typesRegistryPackageName} npm package`); } @@ -156,7 +194,11 @@ export class NodeTypingsInstaller extends TypingsInstaller { }; } - this.typesRegistry = loadTypesRegistryFile(getTypesRegistryFileLocation(globalTypingsCacheLocation), this.installTypingHost, this.log); + this.typesRegistry = loadTypesRegistryFile( + getTypesRegistryFileLocation(globalTypingsCacheLocation), + this.installTypingHost, + this.log, + ); } handleRequest(req: TypingInstallerRequestUnion) { @@ -186,13 +228,24 @@ export class NodeTypingsInstaller extends TypingsInstaller { const cwd = getDirectoryOfPackageJson(fileName, this.installTypingHost) || projectRootPath; if (cwd) { this.installWorker(-1, [packageName], cwd, success => { - const message = success ? `Package ${packageName} installed.` : `There was an error installing ${packageName}.`; - const response: PackageInstalledResponse = { kind: ActionPackageInstalled, projectName, success, message }; + const message = success ? `Package ${packageName} installed.` + : `There was an error installing ${packageName}.`; + const response: PackageInstalledResponse = { + kind: ActionPackageInstalled, + projectName, + success, + message, + }; this.sendResponse(response); }); } else { - const response: PackageInstalledResponse = { kind: ActionPackageInstalled, projectName, success: false, message: "Could not determine a project root path." }; + const response: PackageInstalledResponse = { + kind: ActionPackageInstalled, + projectName, + success: false, + message: "Could not determine a project root path.", + }; this.sendResponse(response); } break; @@ -212,12 +265,22 @@ export class NodeTypingsInstaller extends TypingsInstaller { } } - protected installWorker(requestId: number, packageNames: string[], cwd: string, onRequestCompleted: RequestCompletedAction): void { + protected installWorker( + requestId: number, + packageNames: string[], + cwd: string, + onRequestCompleted: RequestCompletedAction, + ): void { if (this.log.isEnabled()) { this.log.writeLine(`#${requestId} with arguments'${JSON.stringify(packageNames)}'.`); } const start = Date.now(); - const hasError = installNpmPackages(this.npmPath, version, packageNames, command => this.execSyncAndLog(command, { cwd })); + const hasError = installNpmPackages( + this.npmPath, + version, + packageNames, + command => this.execSyncAndLog(command, { cwd }), + ); if (this.log.isEnabled()) { this.log.writeLine(`npm install #${requestId} took: ${Date.now() - start} ms`); } @@ -238,7 +301,11 @@ export class NodeTypingsInstaller extends TypingsInstaller { } catch (error) { const { stdout, stderr } = error; - this.log.writeLine(` Failed. stdout:${indent(sys.newLine, stdout)}${sys.newLine} stderr:${indent(sys.newLine, stderr)}`); + this.log.writeLine( + ` Failed. stdout:${indent(sys.newLine, stdout)}${sys.newLine} stderr:${ + indent(sys.newLine, stderr) + }`, + ); return true; } } @@ -273,7 +340,15 @@ process.on("disconnect", () => { }); let installer: NodeTypingsInstaller | undefined; process.on("message", (req: TypingInstallerRequestUnion) => { - installer ??= new NodeTypingsInstaller(globalTypingsCacheLocation!, typingSafeListLocation!, typesMapLocation!, npmLocation, validateDefaultNpmLocation, /*throttleLimit*/ 5, log); // TODO: GH#18217 + installer ??= new NodeTypingsInstaller( + globalTypingsCacheLocation!, + typingSafeListLocation!, + typesMapLocation!, + npmLocation, + validateDefaultNpmLocation, + /*throttleLimit*/ 5, + log, + ); // TODO: GH#18217 installer.handleRequest(req); }); diff --git a/src/typingsInstallerCore/typingsInstaller.ts b/src/typingsInstallerCore/typingsInstaller.ts index 5e185406e07c6..cd547e4a9bb7c 100644 --- a/src/typingsInstallerCore/typingsInstaller.ts +++ b/src/typingsInstallerCore/typingsInstaller.ts @@ -50,9 +50,16 @@ const nullLog: Log = { writeLine: noop, }; -function typingToFileName(cachePath: string, packageName: string, installTypingHost: InstallTypingHost, log: Log): string | undefined { +function typingToFileName( + cachePath: string, + packageName: string, + installTypingHost: InstallTypingHost, + log: Log, +): string | undefined { try { - const result = resolveModuleName(packageName, combinePaths(cachePath, "index.d.ts"), { moduleResolution: ModuleResolutionKind.Node10 }, installTypingHost); + const result = resolveModuleName(packageName, combinePaths(cachePath, "index.d.ts"), { + moduleResolution: ModuleResolutionKind.Node10, + }, installTypingHost); return result.resolvedModule && result.resolvedModule.resolvedFileName; } catch (e) { @@ -64,7 +71,12 @@ function typingToFileName(cachePath: string, packageName: string, installTypingH } /** @internal */ -export function installNpmPackages(npmPath: string, tsVersion: string, packageNames: string[], install: (command: string) => boolean) { +export function installNpmPackages( + npmPath: string, + tsVersion: string, + packageNames: string[], + install: (command: string) => boolean, +) { let hasError = false; for (let remaining = packageNames.length; remaining > 0;) { const result = getNpmCommandForInstallation(npmPath, tsVersion, packageNames, remaining); @@ -75,11 +87,19 @@ export function installNpmPackages(npmPath: string, tsVersion: string, packageNa } /** @internal */ -export function getNpmCommandForInstallation(npmPath: string, tsVersion: string, packageNames: string[], remaining: number) { +export function getNpmCommandForInstallation( + npmPath: string, + tsVersion: string, + packageNames: string[], + remaining: number, +) { const sliceStart = packageNames.length - remaining; let command: string, toSlice = remaining; while (true) { - command = `${npmPath} install --ignore-scripts ${(toSlice === packageNames.length ? packageNames : packageNames.slice(sliceStart, sliceStart + toSlice)).join(" ")} --save-dev --user-agent="typesInstaller/${tsVersion}"`; + command = `${npmPath} install --ignore-scripts ${ + (toSlice === packageNames.length ? packageNames : packageNames.slice(sliceStart, sliceStart + toSlice)) + .join(" ") + } --save-dev --user-agent="typesInstaller/${tsVersion}"`; if (command.length < 8000) { break; } @@ -122,7 +142,9 @@ export abstract class TypingsInstaller { ) { const isLoggingEnabled = this.log.isEnabled(); if (isLoggingEnabled) { - this.log.writeLine(`Global cache location '${globalCachePath}', safe file path '${safeListPath}', types map path ${typesMapLocation}`); + this.log.writeLine( + `Global cache location '${globalCachePath}', safe file path '${safeListPath}', types map path ${typesMapLocation}`, + ); } this.processCacheLocation(this.globalCachePath); } @@ -189,7 +211,12 @@ export abstract class TypingsInstaller { // install typings if (discoverTypingsResult.newTypingNames.length) { - this.installTypings(req, req.cachePath || this.globalCachePath, discoverTypingsResult.cachedTypingPaths, discoverTypingsResult.newTypingNames); + this.installTypings( + req, + req.cachePath || this.globalCachePath, + discoverTypingsResult.cachedTypingPaths, + discoverTypingsResult.newTypingNames, + ); } else { this.sendResponse(this.createSetTypings(req, discoverTypingsResult.cachedTypingPaths)); @@ -258,7 +285,9 @@ export abstract class TypingsInstaller { } if (this.log.isEnabled()) { - this.log.writeLine(`New typing for package ${packageName} from '${typingFile}' conflicts with existing typing file '${existingTypingFile}'`); + this.log.writeLine( + `New typing for package ${packageName} from '${typingFile}' conflicts with existing typing file '${existingTypingFile}'`, + ); } } if (this.log.isEnabled()) { @@ -270,7 +299,10 @@ export abstract class TypingsInstaller { continue; } - const newTyping: JsTyping.CachedTyping = { typingLocation: typingFile, version: new Version(version) }; + const newTyping: JsTyping.CachedTyping = { + typingLocation: typingFile, + version: new Version(version), + }; this.packageNameToTypingLocation.set(packageName, newTyping); } } @@ -285,22 +317,38 @@ export abstract class TypingsInstaller { return mapDefined(typingsToInstall, typing => { const typingKey = mangleScopedPackageName(typing); if (this.missingTypingsSet.has(typingKey)) { - if (this.log.isEnabled()) this.log.writeLine(`'${typing}':: '${typingKey}' is in missingTypingsSet - skipping...`); + if (this.log.isEnabled()) { + this.log.writeLine(`'${typing}':: '${typingKey}' is in missingTypingsSet - skipping...`); + } return undefined; } const validationResult = JsTyping.validatePackageName(typing); if (validationResult !== JsTyping.NameValidationResult.Ok) { // add typing name to missing set so we won't process it again this.missingTypingsSet.add(typingKey); - if (this.log.isEnabled()) this.log.writeLine(JsTyping.renderPackageNameValidationFailure(validationResult, typing)); + if (this.log.isEnabled()) { + this.log.writeLine(JsTyping.renderPackageNameValidationFailure(validationResult, typing)); + } return undefined; } if (!this.typesRegistry.has(typingKey)) { - if (this.log.isEnabled()) this.log.writeLine(`'${typing}':: Entry for package '${typingKey}' does not exist in local types registry - skipping...`); + if (this.log.isEnabled()) { + this.log.writeLine( + `'${typing}':: Entry for package '${typingKey}' does not exist in local types registry - skipping...`, + ); + } return undefined; } - if (this.packageNameToTypingLocation.get(typingKey) && JsTyping.isTypingUpToDate(this.packageNameToTypingLocation.get(typingKey)!, this.typesRegistry.get(typingKey)!)) { - if (this.log.isEnabled()) this.log.writeLine(`'${typing}':: '${typingKey}' already has an up-to-date typing - skipping...`); + if ( + this.packageNameToTypingLocation.get(typingKey) + && JsTyping.isTypingUpToDate( + this.packageNameToTypingLocation.get(typingKey)!, + this.typesRegistry.get(typingKey)!, + ) + ) { + if (this.log.isEnabled()) { + this.log.writeLine(`'${typing}':: '${typingKey}' already has an up-to-date typing - skipping...`); + } return undefined; } return typingKey; @@ -321,7 +369,12 @@ export abstract class TypingsInstaller { } } - private installTypings(req: DiscoverTypings, cachePath: string, currentlyCachedTypings: string[], typingsToInstall: string[]) { + private installTypings( + req: DiscoverTypings, + cachePath: string, + currentlyCachedTypings: string[], + typingsToInstall: string[], + ) { if (this.log.isEnabled()) { this.log.writeLine(`Installing typings ${JSON.stringify(typingsToInstall)}`); } @@ -352,7 +405,11 @@ export abstract class TypingsInstaller { try { if (!ok) { if (this.log.isEnabled()) { - this.log.writeLine(`install request failed, marking packages as missing to prevent repeated requests: ${JSON.stringify(filteredTypings)}`); + this.log.writeLine( + `install request failed, marking packages as missing to prevent repeated requests: ${ + JSON.stringify(filteredTypings) + }`, + ); } for (const typing of filteredTypings) { this.missingTypingsSet.add(typing); @@ -439,7 +496,12 @@ export abstract class TypingsInstaller { }; } - private installTypingsAsync(requestId: number, packageNames: string[], cwd: string, onRequestCompleted: RequestCompletedAction): void { + private installTypingsAsync( + requestId: number, + packageNames: string[], + cwd: string, + onRequestCompleted: RequestCompletedAction, + ): void { this.pendingRunRequests.unshift({ requestId, packageNames, cwd, onRequestCompleted }); this.executeWithThrottling(); } @@ -456,8 +518,15 @@ export abstract class TypingsInstaller { } } - protected abstract installWorker(requestId: number, packageNames: string[], cwd: string, onRequestCompleted: RequestCompletedAction): void; - protected abstract sendResponse(response: SetTypings | InvalidateCachedTypings | BeginInstallTypes | EndInstallTypes | WatchTypingLocations): void; + protected abstract installWorker( + requestId: number, + packageNames: string[], + cwd: string, + onRequestCompleted: RequestCompletedAction, + ): void; + protected abstract sendResponse( + response: SetTypings | InvalidateCachedTypings | BeginInstallTypes | EndInstallTypes | WatchTypingLocations, + ): void; protected readonly latestDistTag = "latest"; } diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index dcea4be64289a..92a4a5a774ce1 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -24,7 +24,15 @@ declare namespace ts { type EventInitializationFailed = "event::initializationFailed"; type ActionWatchTypingLocations = "action::watchTypingLocations"; interface TypingInstallerResponse { - readonly kind: ActionSet | ActionInvalidate | EventTypesRegistry | ActionPackageInstalled | EventBeginInstallTypes | EventEndInstallTypes | EventInitializationFailed | ActionWatchTypingLocations; + readonly kind: + | ActionSet + | ActionInvalidate + | EventTypesRegistry + | ActionPackageInstalled + | EventBeginInstallTypes + | EventEndInstallTypes + | EventInitializationFailed + | ActionWatchTypingLocations; } interface TypingInstallerRequestWithProjectName { readonly projectName: string; @@ -2060,7 +2068,10 @@ declare namespace ts { */ triggerReason?: SignatureHelpTriggerReason; } - type SignatureHelpTriggerReason = SignatureHelpInvokedReason | SignatureHelpCharacterTypedReason | SignatureHelpRetriggeredReason; + type SignatureHelpTriggerReason = + | SignatureHelpInvokedReason + | SignatureHelpCharacterTypedReason + | SignatureHelpRetriggeredReason; /** * Signals that the user manually requested signature help. * The language service will unconditionally attempt to provide a result. @@ -2818,7 +2829,11 @@ declare namespace ts { */ readonly useLabelDetailsInCompletionEntries?: boolean; readonly allowIncompleteCompletions?: boolean; - readonly importModuleSpecifierPreference?: "shortest" | "project-relative" | "relative" | "non-relative"; + readonly importModuleSpecifierPreference?: + | "shortest" + | "project-relative" + | "relative" + | "non-relative"; /** Determines whether we import `foo/index.ts` as "foo", "foo/index", or "foo/index.js" */ readonly importModuleSpecifierEnding?: "auto" | "minimal" | "index" | "js"; readonly allowTextChangesInNewFiles?: boolean; @@ -3063,7 +3078,14 @@ declare namespace ts { private installRunCount; private inFlightRequestCount; abstract readonly typesRegistry: Map>; - constructor(installTypingHost: InstallTypingHost, globalCachePath: string, safeListPath: Path, typesMapLocation: Path, throttleLimit: number, log?: Log); + constructor( + installTypingHost: InstallTypingHost, + globalCachePath: string, + safeListPath: Path, + typesMapLocation: Path, + throttleLimit: number, + log?: Log, + ); closeProject(req: CloseProject): void; private closeWatchers; install(req: DiscoverTypings): void; @@ -3077,8 +3099,20 @@ declare namespace ts { private createSetTypings; private installTypingsAsync; private executeWithThrottling; - protected abstract installWorker(requestId: number, packageNames: string[], cwd: string, onRequestCompleted: RequestCompletedAction): void; - protected abstract sendResponse(response: SetTypings | InvalidateCachedTypings | BeginInstallTypes | EndInstallTypes | WatchTypingLocations): void; + protected abstract installWorker( + requestId: number, + packageNames: string[], + cwd: string, + onRequestCompleted: RequestCompletedAction, + ): void; + protected abstract sendResponse( + response: + | SetTypings + | InvalidateCachedTypings + | BeginInstallTypes + | EndInstallTypes + | WatchTypingLocations, + ): void; protected readonly latestDistTag = "latest"; } } @@ -3100,8 +3134,18 @@ declare namespace ts { /** @deprecated Use {@link ModuleImportResult} instead. */ type RequireResult = ModuleImportResult; interface ServerHost extends System { - watchFile(path: string, callback: FileWatcherCallback, pollingInterval?: number, options?: WatchOptions): FileWatcher; - watchDirectory(path: string, callback: DirectoryWatcherCallback, recursive?: boolean, options?: WatchOptions): FileWatcher; + watchFile( + path: string, + callback: FileWatcherCallback, + pollingInterval?: number, + options?: WatchOptions, + ): FileWatcher; + watchDirectory( + path: string, + callback: DirectoryWatcherCallback, + recursive?: boolean, + options?: WatchOptions, + ): FileWatcher; setTimeout(callback: (...args: any[]) => void, ms: number, ...args: any[]): any; clearTimeout(timeoutId: any): void; setImmediate(callback: (...args: any[]) => void, ...args: any[]): any; @@ -3110,9 +3154,18 @@ declare namespace ts { trace?(s: string): void; require?(initialPath: string, moduleName: string): ModuleImportResult; } - function createInstallTypingsRequest(project: Project, typeAcquisition: TypeAcquisition, unresolvedImports: SortedReadonlyArray, cachePath?: string): DiscoverTypings; + function createInstallTypingsRequest( + project: Project, + typeAcquisition: TypeAcquisition, + unresolvedImports: SortedReadonlyArray, + cachePath?: string, + ): DiscoverTypings; function toNormalizedPath(fileName: string): NormalizedPath; - function normalizedPathToPath(normalizedPath: NormalizedPath, currentDirectory: string, getCanonicalFileName: (f: string) => string): Path; + function normalizedPathToPath( + normalizedPath: NormalizedPath, + currentDirectory: string, + getCanonicalFileName: (f: string) => string, + ): Path; function asNormalizedPath(fileName: string): NormalizedPath; function createNormalizedPathMap(): NormalizedPathMap; function isInferredProjectName(name: string): boolean; @@ -3168,7 +3221,14 @@ declare namespace ts { readonly containingProjects: Project[]; private formatSettings; private preferences; - constructor(host: ServerHost, fileName: NormalizedPath, scriptKind: ScriptKind, hasMixedContent: boolean, path: Path, initialVersion?: number); + constructor( + host: ServerHost, + fileName: NormalizedPath, + scriptKind: ScriptKind, + hasMixedContent: boolean, + path: Path, + initialVersion?: number, + ); isScriptOpen(): boolean; open(newText: string | undefined): void; close(fileExists?: boolean): void; @@ -3208,7 +3268,11 @@ declare namespace ts { interface ITypingsInstaller { isKnownTypesPackageName(name: string): boolean; installPackage(options: InstallPackageOptionsWithProject): Promise; - enqueueInstallTypingsRequest(p: Project, typeAcquisition: TypeAcquisition, unresolvedImports: SortedReadonlyArray | undefined): void; + enqueueInstallTypingsRequest( + p: Project, + typeAcquisition: TypeAcquisition, + unresolvedImports: SortedReadonlyArray | undefined, + ): void; attach(projectService: ProjectService): void; onProjectClosed(p: Project): void; readonly globalTypingsCacheLocation: string | undefined; @@ -3290,7 +3354,12 @@ declare namespace ts { private readonly cancellationToken; isNonTsProject(): boolean; isJsOnlyProject(): boolean; - static resolveModule(moduleName: string, initialDir: string, host: ServerHost, log: (message: string) => void): {} | undefined; + static resolveModule( + moduleName: string, + initialDir: string, + host: ServerHost, + log: (message: string) => void, + ): {} | undefined; isKnownTypesPackageName(name: string): boolean; installPackage(options: InstallPackageOptions): Promise; private get typingsCache(); @@ -3308,7 +3377,13 @@ declare namespace ts { getCurrentDirectory(): string; getDefaultLibFileName(): string; useCaseSensitiveFileNames(): boolean; - readDirectory(path: string, extensions?: readonly string[], exclude?: readonly string[], include?: readonly string[], depth?: number): string[]; + readDirectory( + path: string, + extensions?: readonly string[], + exclude?: readonly string[], + include?: readonly string[], + depth?: number, + ): string[]; readFile(fileName: string): string | undefined; writeFile(fileName: string, content: string): void; fileExists(file: string): boolean; @@ -3332,7 +3407,10 @@ declare namespace ts { /** * Returns true if emit was conducted */ - emitFile(scriptInfo: ScriptInfo, writeFile: (path: string, data: string, writeByteOrderMark?: boolean) => void): EmitResult; + emitFile( + scriptInfo: ScriptInfo, + writeFile: (path: string, data: string, writeByteOrderMark?: boolean) => void, + ): EmitResult; enableLanguageService(): void; disableLanguageService(lastFileExceededProgramSize?: string): void; getProjectName(): string; @@ -3347,7 +3425,10 @@ declare namespace ts { getRootScriptInfos(): ts.server.ScriptInfo[]; getScriptInfos(): ScriptInfo[]; getExcludedFiles(): readonly NormalizedPath[]; - getFileNames(excludeFilesFromExternalLibraries?: boolean, excludeConfigFiles?: boolean): ts.server.NormalizedPath[]; + getFileNames( + excludeFilesFromExternalLibraries?: boolean, + excludeConfigFiles?: boolean, + ): ts.server.NormalizedPath[]; hasConfigFile(configFilePath: NormalizedPath): boolean; containsScriptInfo(info: ScriptInfo): boolean; containsFile(filename: NormalizedPath, requireOpen?: boolean): boolean; @@ -3453,11 +3534,20 @@ declare namespace ts { getExcludedFiles(): readonly ts.server.NormalizedPath[]; } function convertFormatOptions(protocolOptions: protocol.FormatCodeSettings): FormatCodeSettings; - function convertCompilerOptions(protocolOptions: protocol.ExternalProjectCompilerOptions): CompilerOptions & protocol.CompileOnSaveMixin; - function convertWatchOptions(protocolOptions: protocol.ExternalProjectCompilerOptions, currentDirectory?: string): WatchOptionsAndErrors | undefined; - function convertTypeAcquisition(protocolOptions: protocol.InferredProjectCompilerOptions): TypeAcquisition | undefined; + function convertCompilerOptions( + protocolOptions: protocol.ExternalProjectCompilerOptions, + ): CompilerOptions & protocol.CompileOnSaveMixin; + function convertWatchOptions( + protocolOptions: protocol.ExternalProjectCompilerOptions, + currentDirectory?: string, + ): WatchOptionsAndErrors | undefined; + function convertTypeAcquisition( + protocolOptions: protocol.InferredProjectCompilerOptions, + ): TypeAcquisition | undefined; function tryConvertScriptKindName(scriptKindName: protocol.ScriptKindName | ScriptKind): ScriptKind; - function convertScriptKindName(scriptKindName: protocol.ScriptKindName): ScriptKind.Unknown | ScriptKind.JS | ScriptKind.JSX | ScriptKind.TS | ScriptKind.TSX; + function convertScriptKindName( + scriptKindName: protocol.ScriptKindName, + ): ScriptKind.Unknown | ScriptKind.JS | ScriptKind.JSX | ScriptKind.TS | ScriptKind.TSX; const maxProgramSizeForNonTsFiles: number; const ProjectsUpdatedInBackgroundEvent = "projectsUpdatedInBackground"; interface ProjectsUpdatedInBackgroundEvent { @@ -3570,7 +3660,15 @@ declare namespace ts { interface OpenFileInfo { readonly checkJs: boolean; } - type ProjectServiceEvent = LargeFileReferencedEvent | ProjectsUpdatedInBackgroundEvent | ProjectLoadingStartEvent | ProjectLoadingFinishEvent | ConfigFileDiagEvent | ProjectLanguageServiceStateEvent | ProjectInfoTelemetryEvent | OpenFileInfoTelemetryEvent; + type ProjectServiceEvent = + | LargeFileReferencedEvent + | ProjectsUpdatedInBackgroundEvent + | ProjectLoadingStartEvent + | ProjectLoadingFinishEvent + | ConfigFileDiagEvent + | ProjectLanguageServiceStateEvent + | ProjectInfoTelemetryEvent + | OpenFileInfoTelemetryEvent; type ProjectServiceEventHandler = (event: ProjectServiceEvent) => void; interface SafeList { [name: string]: { @@ -3692,7 +3790,10 @@ declare namespace ts { updateTypingsForProject(response: SetTypings | InvalidateCachedTypings | PackageInstalledResponse): void; private delayUpdateProjectGraph; private delayUpdateProjectGraphs; - setCompilerOptionsForInferredProjects(projectCompilerOptions: protocol.InferredProjectCompilerOptions, projectRootPath?: string): void; + setCompilerOptionsForInferredProjects( + projectCompilerOptions: protocol.InferredProjectCompilerOptions, + projectRootPath?: string, + ): void; findProject(projectName: string): Project | undefined; getDefaultProjectForFile(fileName: NormalizedPath, ensureProject: boolean): Project | undefined; private doEnsureDefaultProjectForFile; @@ -3775,9 +3876,16 @@ declare namespace ts { private stopWatchingScriptInfo; private getOrCreateScriptInfoNotOpenedByClientForNormalizedPath; private getOrCreateScriptInfoOpenedByClientForNormalizedPath; - getOrCreateScriptInfoForNormalizedPath(fileName: NormalizedPath, openedByClient: boolean, fileContent?: string, scriptKind?: ScriptKind, hasMixedContent?: boolean, hostToQueryFileExistsOn?: { - fileExists(path: string): boolean; - }): ScriptInfo | undefined; + getOrCreateScriptInfoForNormalizedPath( + fileName: NormalizedPath, + openedByClient: boolean, + fileContent?: string, + scriptKind?: ScriptKind, + hasMixedContent?: boolean, + hostToQueryFileExistsOn?: { + fileExists(path: string): boolean; + }, + ): ScriptInfo | undefined; private getOrCreateScriptInfoWorker; /** * This gets the script info for the normalized path. If the path is not rooted disk path then the open script info with project root context is preferred @@ -3818,14 +3926,25 @@ declare namespace ts { * @param filename is absolute pathname * @param fileContent is a known version of the file content that is more up to date than the one on disk */ - openClientFile(fileName: string, fileContent?: string, scriptKind?: ScriptKind, projectRootPath?: string): OpenConfiguredProjectResult; + openClientFile( + fileName: string, + fileContent?: string, + scriptKind?: ScriptKind, + projectRootPath?: string, + ): OpenConfiguredProjectResult; private findExternalProjectContainingOpenScriptInfo; private getOrCreateOpenScriptInfo; private assignProjectToOpenedScriptInfo; private createAncestorProjects; private ensureProjectChildren; private cleanupAfterOpeningFile; - openClientFileWithNormalizedPath(fileName: NormalizedPath, fileContent?: string, scriptKind?: ScriptKind, hasMixedContent?: boolean, projectRootPath?: NormalizedPath): OpenConfiguredProjectResult; + openClientFileWithNormalizedPath( + fileName: NormalizedPath, + fileContent?: string, + scriptKind?: ScriptKind, + hasMixedContent?: boolean, + projectRootPath?: NormalizedPath, + ): OpenConfiguredProjectResult; private removeOrphanConfiguredProjects; private removeOrphanScriptInfos; private telemetryOnOpenFile; @@ -3850,7 +3969,12 @@ declare namespace ts { private enableRequestedPluginsForProjectAsync; configurePlugin(args: protocol.ConfigurePluginRequestArguments): void; } - function formatMessage(msg: T, logger: Logger, byteLength: (s: string, encoding: BufferEncoding) => number, newLine: string): string; + function formatMessage( + msg: T, + logger: Logger, + byteLength: (s: string, encoding: BufferEncoding) => number, + newLine: string, + ): string; interface ServerCancellationToken extends HostCancellationToken { setRequest(requestId: number): void; resetRequest(requestId: number): void; @@ -4502,8 +4626,21 @@ declare namespace ts { FirstJSDocTagNode = 334, LastJSDocTagNode = 357, } - type TriviaSyntaxKind = SyntaxKind.SingleLineCommentTrivia | SyntaxKind.MultiLineCommentTrivia | SyntaxKind.NewLineTrivia | SyntaxKind.WhitespaceTrivia | SyntaxKind.ShebangTrivia | SyntaxKind.ConflictMarkerTrivia; - type LiteralSyntaxKind = SyntaxKind.NumericLiteral | SyntaxKind.BigIntLiteral | SyntaxKind.StringLiteral | SyntaxKind.JsxText | SyntaxKind.JsxTextAllWhiteSpaces | SyntaxKind.RegularExpressionLiteral | SyntaxKind.NoSubstitutionTemplateLiteral; + type TriviaSyntaxKind = + | SyntaxKind.SingleLineCommentTrivia + | SyntaxKind.MultiLineCommentTrivia + | SyntaxKind.NewLineTrivia + | SyntaxKind.WhitespaceTrivia + | SyntaxKind.ShebangTrivia + | SyntaxKind.ConflictMarkerTrivia; + type LiteralSyntaxKind = + | SyntaxKind.NumericLiteral + | SyntaxKind.BigIntLiteral + | SyntaxKind.StringLiteral + | SyntaxKind.JsxText + | SyntaxKind.JsxTextAllWhiteSpaces + | SyntaxKind.RegularExpressionLiteral + | SyntaxKind.NoSubstitutionTemplateLiteral; type PseudoLiteralSyntaxKind = SyntaxKind.TemplateHead | SyntaxKind.TemplateMiddle | SyntaxKind.TemplateTail; type PunctuationSyntaxKind = | SyntaxKind.OpenBraceToken @@ -4651,11 +4788,72 @@ declare namespace ts { | SyntaxKind.WhileKeyword | SyntaxKind.WithKeyword | SyntaxKind.YieldKeyword; - type ModifierSyntaxKind = SyntaxKind.AbstractKeyword | SyntaxKind.AccessorKeyword | SyntaxKind.AsyncKeyword | SyntaxKind.ConstKeyword | SyntaxKind.DeclareKeyword | SyntaxKind.DefaultKeyword | SyntaxKind.ExportKeyword | SyntaxKind.InKeyword | SyntaxKind.PrivateKeyword | SyntaxKind.ProtectedKeyword | SyntaxKind.PublicKeyword | SyntaxKind.ReadonlyKeyword | SyntaxKind.OutKeyword | SyntaxKind.OverrideKeyword | SyntaxKind.StaticKeyword; - type KeywordTypeSyntaxKind = SyntaxKind.AnyKeyword | SyntaxKind.BigIntKeyword | SyntaxKind.BooleanKeyword | SyntaxKind.IntrinsicKeyword | SyntaxKind.NeverKeyword | SyntaxKind.NumberKeyword | SyntaxKind.ObjectKeyword | SyntaxKind.StringKeyword | SyntaxKind.SymbolKeyword | SyntaxKind.UndefinedKeyword | SyntaxKind.UnknownKeyword | SyntaxKind.VoidKeyword; - type TokenSyntaxKind = SyntaxKind.Unknown | SyntaxKind.EndOfFileToken | TriviaSyntaxKind | LiteralSyntaxKind | PseudoLiteralSyntaxKind | PunctuationSyntaxKind | SyntaxKind.Identifier | KeywordSyntaxKind; - type JsxTokenSyntaxKind = SyntaxKind.LessThanSlashToken | SyntaxKind.EndOfFileToken | SyntaxKind.ConflictMarkerTrivia | SyntaxKind.JsxText | SyntaxKind.JsxTextAllWhiteSpaces | SyntaxKind.OpenBraceToken | SyntaxKind.LessThanToken; - type JSDocSyntaxKind = SyntaxKind.EndOfFileToken | SyntaxKind.WhitespaceTrivia | SyntaxKind.AtToken | SyntaxKind.NewLineTrivia | SyntaxKind.AsteriskToken | SyntaxKind.OpenBraceToken | SyntaxKind.CloseBraceToken | SyntaxKind.LessThanToken | SyntaxKind.GreaterThanToken | SyntaxKind.OpenBracketToken | SyntaxKind.CloseBracketToken | SyntaxKind.EqualsToken | SyntaxKind.CommaToken | SyntaxKind.DotToken | SyntaxKind.Identifier | SyntaxKind.BacktickToken | SyntaxKind.HashToken | SyntaxKind.Unknown | KeywordSyntaxKind; + type ModifierSyntaxKind = + | SyntaxKind.AbstractKeyword + | SyntaxKind.AccessorKeyword + | SyntaxKind.AsyncKeyword + | SyntaxKind.ConstKeyword + | SyntaxKind.DeclareKeyword + | SyntaxKind.DefaultKeyword + | SyntaxKind.ExportKeyword + | SyntaxKind.InKeyword + | SyntaxKind.PrivateKeyword + | SyntaxKind.ProtectedKeyword + | SyntaxKind.PublicKeyword + | SyntaxKind.ReadonlyKeyword + | SyntaxKind.OutKeyword + | SyntaxKind.OverrideKeyword + | SyntaxKind.StaticKeyword; + type KeywordTypeSyntaxKind = + | SyntaxKind.AnyKeyword + | SyntaxKind.BigIntKeyword + | SyntaxKind.BooleanKeyword + | SyntaxKind.IntrinsicKeyword + | SyntaxKind.NeverKeyword + | SyntaxKind.NumberKeyword + | SyntaxKind.ObjectKeyword + | SyntaxKind.StringKeyword + | SyntaxKind.SymbolKeyword + | SyntaxKind.UndefinedKeyword + | SyntaxKind.UnknownKeyword + | SyntaxKind.VoidKeyword; + type TokenSyntaxKind = + | SyntaxKind.Unknown + | SyntaxKind.EndOfFileToken + | TriviaSyntaxKind + | LiteralSyntaxKind + | PseudoLiteralSyntaxKind + | PunctuationSyntaxKind + | SyntaxKind.Identifier + | KeywordSyntaxKind; + type JsxTokenSyntaxKind = + | SyntaxKind.LessThanSlashToken + | SyntaxKind.EndOfFileToken + | SyntaxKind.ConflictMarkerTrivia + | SyntaxKind.JsxText + | SyntaxKind.JsxTextAllWhiteSpaces + | SyntaxKind.OpenBraceToken + | SyntaxKind.LessThanToken; + type JSDocSyntaxKind = + | SyntaxKind.EndOfFileToken + | SyntaxKind.WhitespaceTrivia + | SyntaxKind.AtToken + | SyntaxKind.NewLineTrivia + | SyntaxKind.AsteriskToken + | SyntaxKind.OpenBraceToken + | SyntaxKind.CloseBraceToken + | SyntaxKind.LessThanToken + | SyntaxKind.GreaterThanToken + | SyntaxKind.OpenBracketToken + | SyntaxKind.CloseBracketToken + | SyntaxKind.EqualsToken + | SyntaxKind.CommaToken + | SyntaxKind.DotToken + | SyntaxKind.Identifier + | SyntaxKind.BacktickToken + | SyntaxKind.HashToken + | SyntaxKind.Unknown + | KeywordSyntaxKind; enum NodeFlags { None = 0, Let = 1, @@ -4747,7 +4945,10 @@ declare namespace ts { getText(sourceFile?: SourceFile): string; getFirstToken(sourceFile?: SourceFile): Node | undefined; getLastToken(sourceFile?: SourceFile): Node | undefined; - forEachChild(cbNode: (node: Node) => T | undefined, cbNodeArray?: (nodes: NodeArray) => T | undefined): T | undefined; + forEachChild( + cbNode: (node: Node) => T | undefined, + cbNodeArray?: (nodes: NodeArray) => T | undefined, + ): T | undefined; } interface JSDocContainer extends Node { _jsdocContainerBrand: any; @@ -4823,12 +5024,71 @@ declare namespace ts { | VariableStatement | WhileStatement | WithStatement; - type HasType = SignatureDeclaration | VariableDeclaration | ParameterDeclaration | PropertySignature | PropertyDeclaration | TypePredicateNode | ParenthesizedTypeNode | TypeOperatorNode | MappedTypeNode | AssertionExpression | TypeAliasDeclaration | JSDocTypeExpression | JSDocNonNullableType | JSDocNullableType | JSDocOptionalType | JSDocVariadicType; - type HasTypeArguments = CallExpression | NewExpression | TaggedTemplateExpression | JsxOpeningElement | JsxSelfClosingElement; + type HasType = + | SignatureDeclaration + | VariableDeclaration + | ParameterDeclaration + | PropertySignature + | PropertyDeclaration + | TypePredicateNode + | ParenthesizedTypeNode + | TypeOperatorNode + | MappedTypeNode + | AssertionExpression + | TypeAliasDeclaration + | JSDocTypeExpression + | JSDocNonNullableType + | JSDocNullableType + | JSDocOptionalType + | JSDocVariadicType; + type HasTypeArguments = + | CallExpression + | NewExpression + | TaggedTemplateExpression + | JsxOpeningElement + | JsxSelfClosingElement; type HasInitializer = HasExpressionInitializer | ForStatement | ForInStatement | ForOfStatement | JsxAttribute; - type HasExpressionInitializer = VariableDeclaration | ParameterDeclaration | BindingElement | PropertyDeclaration | PropertyAssignment | EnumMember; - type HasDecorators = ParameterDeclaration | PropertyDeclaration | MethodDeclaration | GetAccessorDeclaration | SetAccessorDeclaration | ClassExpression | ClassDeclaration; - type HasModifiers = TypeParameterDeclaration | ParameterDeclaration | ConstructorTypeNode | PropertySignature | PropertyDeclaration | MethodSignature | MethodDeclaration | ConstructorDeclaration | GetAccessorDeclaration | SetAccessorDeclaration | IndexSignatureDeclaration | FunctionExpression | ArrowFunction | ClassExpression | VariableStatement | FunctionDeclaration | ClassDeclaration | InterfaceDeclaration | TypeAliasDeclaration | EnumDeclaration | ModuleDeclaration | ImportEqualsDeclaration | ImportDeclaration | ExportAssignment | ExportDeclaration; + type HasExpressionInitializer = + | VariableDeclaration + | ParameterDeclaration + | BindingElement + | PropertyDeclaration + | PropertyAssignment + | EnumMember; + type HasDecorators = + | ParameterDeclaration + | PropertyDeclaration + | MethodDeclaration + | GetAccessorDeclaration + | SetAccessorDeclaration + | ClassExpression + | ClassDeclaration; + type HasModifiers = + | TypeParameterDeclaration + | ParameterDeclaration + | ConstructorTypeNode + | PropertySignature + | PropertyDeclaration + | MethodSignature + | MethodDeclaration + | ConstructorDeclaration + | GetAccessorDeclaration + | SetAccessorDeclaration + | IndexSignatureDeclaration + | FunctionExpression + | ArrowFunction + | ClassExpression + | VariableStatement + | FunctionDeclaration + | ClassDeclaration + | InterfaceDeclaration + | TypeAliasDeclaration + | EnumDeclaration + | ModuleDeclaration + | ImportEqualsDeclaration + | ImportDeclaration + | ExportAssignment + | ExportDeclaration; interface NodeArray extends ReadonlyArray, ReadonlyTextRange { readonly hasTrailingComma: boolean; } @@ -4875,7 +5135,22 @@ declare namespace ts { type OutKeyword = ModifierToken; type OverrideKeyword = ModifierToken; type StaticKeyword = ModifierToken; - type Modifier = AbstractKeyword | AccessorKeyword | AsyncKeyword | ConstKeyword | DeclareKeyword | DefaultKeyword | ExportKeyword | InKeyword | PrivateKeyword | ProtectedKeyword | PublicKeyword | OutKeyword | OverrideKeyword | ReadonlyKeyword | StaticKeyword; + type Modifier = + | AbstractKeyword + | AccessorKeyword + | AsyncKeyword + | ConstKeyword + | DeclareKeyword + | DefaultKeyword + | ExportKeyword + | InKeyword + | PrivateKeyword + | ProtectedKeyword + | PublicKeyword + | OutKeyword + | OverrideKeyword + | ReadonlyKeyword + | StaticKeyword; type ModifierLike = Modifier | Decorator; type AccessibilityModifier = PublicKeyword | PrivateKeyword | ProtectedKeyword; type ParameterPropertyModifier = AccessibilityModifier | ReadonlyKeyword; @@ -4916,7 +5191,13 @@ declare namespace ts { type EntityName = Identifier | QualifiedName; type PropertyName = Identifier | StringLiteral | NumericLiteral | ComputedPropertyName | PrivateIdentifier; type MemberName = Identifier | PrivateIdentifier; - type DeclarationName = PropertyName | JsxAttributeName | StringLiteralLike | ElementAccessExpression | BindingPattern | EntityNameExpression; + type DeclarationName = + | PropertyName + | JsxAttributeName + | StringLiteralLike + | ElementAccessExpression + | BindingPattern + | EntityNameExpression; interface Declaration extends Node { _declarationBrand: any; } @@ -4960,7 +5241,20 @@ declare namespace ts { readonly parameters: NodeArray; readonly type?: TypeNode | undefined; } - type SignatureDeclaration = CallSignatureDeclaration | ConstructSignatureDeclaration | MethodSignature | IndexSignatureDeclaration | FunctionTypeNode | ConstructorTypeNode | JSDocFunctionType | FunctionDeclaration | MethodDeclaration | ConstructorDeclaration | AccessorDeclaration | FunctionExpression | ArrowFunction; + type SignatureDeclaration = + | CallSignatureDeclaration + | ConstructSignatureDeclaration + | MethodSignature + | IndexSignatureDeclaration + | FunctionTypeNode + | ConstructorTypeNode + | JSDocFunctionType + | FunctionDeclaration + | MethodDeclaration + | ConstructorDeclaration + | AccessorDeclaration + | FunctionExpression + | ArrowFunction; interface CallSignatureDeclaration extends SignatureDeclarationBase, TypeElement, LocalsContainer { readonly kind: SyntaxKind.CallSignature; } @@ -5025,7 +5319,12 @@ declare namespace ts { readonly name?: PropertyName; } /** Unlike ObjectLiteralElement, excludes JSXAttribute and JSXSpreadAttribute. */ - type ObjectLiteralElementLike = PropertyAssignment | ShorthandPropertyAssignment | SpreadAssignment | MethodDeclaration | AccessorDeclaration; + type ObjectLiteralElementLike = + | PropertyAssignment + | ShorthandPropertyAssignment + | SpreadAssignment + | MethodDeclaration + | AccessorDeclaration; interface PropertyAssignment extends ObjectLiteralElement, JSDocContainer { readonly kind: SyntaxKind.PropertyAssignment; readonly parent: ObjectLiteralExpression; @@ -5044,7 +5343,18 @@ declare namespace ts { readonly parent: ObjectLiteralExpression; readonly expression: Expression; } - type VariableLikeDeclaration = VariableDeclaration | ParameterDeclaration | BindingElement | PropertyDeclaration | PropertyAssignment | PropertySignature | JsxAttribute | ShorthandPropertyAssignment | EnumMember | JSDocPropertyTag | JSDocParameterTag; + type VariableLikeDeclaration = + | VariableDeclaration + | ParameterDeclaration + | BindingElement + | PropertyDeclaration + | PropertyAssignment + | PropertySignature + | JsxAttribute + | ShorthandPropertyAssignment + | EnumMember + | JSDocPropertyTag + | JSDocParameterTag; interface ObjectBindingPattern extends Node { readonly kind: SyntaxKind.ObjectBindingPattern; readonly parent: VariableDeclaration | ParameterDeclaration | BindingElement; @@ -5072,7 +5382,14 @@ declare namespace ts { readonly exclamationToken?: ExclamationToken | undefined; readonly body?: Block | Expression | undefined; } - type FunctionLikeDeclaration = FunctionDeclaration | MethodDeclaration | GetAccessorDeclaration | SetAccessorDeclaration | ConstructorDeclaration | FunctionExpression | ArrowFunction; + type FunctionLikeDeclaration = + | FunctionDeclaration + | MethodDeclaration + | GetAccessorDeclaration + | SetAccessorDeclaration + | ConstructorDeclaration + | FunctionExpression + | ArrowFunction; /** @deprecated Use SignatureDeclaration */ type FunctionLike = SignatureDeclaration; interface FunctionDeclaration extends FunctionLikeDeclarationBase, DeclarationStatement, LocalsContainer { @@ -5087,14 +5404,24 @@ declare namespace ts { readonly modifiers?: NodeArray; readonly name: PropertyName; } - interface MethodDeclaration extends FunctionLikeDeclarationBase, ClassElement, ObjectLiteralElement, JSDocContainer, LocalsContainer, FlowContainer { + interface MethodDeclaration + extends + FunctionLikeDeclarationBase, + ClassElement, + ObjectLiteralElement, + JSDocContainer, + LocalsContainer, + FlowContainer + { readonly kind: SyntaxKind.MethodDeclaration; readonly parent: ClassLikeDeclaration | ObjectLiteralExpression; readonly modifiers?: NodeArray | undefined; readonly name: PropertyName; readonly body?: FunctionBody | undefined; } - interface ConstructorDeclaration extends FunctionLikeDeclarationBase, ClassElement, JSDocContainer, LocalsContainer { + interface ConstructorDeclaration + extends FunctionLikeDeclarationBase, ClassElement, JSDocContainer, LocalsContainer + { readonly kind: SyntaxKind.Constructor; readonly parent: ClassLikeDeclaration; readonly modifiers?: NodeArray | undefined; @@ -5105,14 +5432,32 @@ declare namespace ts { readonly kind: SyntaxKind.SemicolonClassElement; readonly parent: ClassLikeDeclaration; } - interface GetAccessorDeclaration extends FunctionLikeDeclarationBase, ClassElement, TypeElement, ObjectLiteralElement, JSDocContainer, LocalsContainer, FlowContainer { + interface GetAccessorDeclaration + extends + FunctionLikeDeclarationBase, + ClassElement, + TypeElement, + ObjectLiteralElement, + JSDocContainer, + LocalsContainer, + FlowContainer + { readonly kind: SyntaxKind.GetAccessor; readonly parent: ClassLikeDeclaration | ObjectLiteralExpression | TypeLiteralNode | InterfaceDeclaration; readonly modifiers?: NodeArray; readonly name: PropertyName; readonly body?: FunctionBody; } - interface SetAccessorDeclaration extends FunctionLikeDeclarationBase, ClassElement, TypeElement, ObjectLiteralElement, JSDocContainer, LocalsContainer, FlowContainer { + interface SetAccessorDeclaration + extends + FunctionLikeDeclarationBase, + ClassElement, + TypeElement, + ObjectLiteralElement, + JSDocContainer, + LocalsContainer, + FlowContainer + { readonly kind: SyntaxKind.SetAccessor; readonly parent: ClassLikeDeclaration | ObjectLiteralExpression | TypeLiteralNode | InterfaceDeclaration; readonly modifiers?: NodeArray; @@ -5134,7 +5479,9 @@ declare namespace ts { interface TypeNode extends Node { _typeNodeBrand: any; } - interface KeywordTypeNode extends KeywordToken, TypeNode { + interface KeywordTypeNode + extends KeywordToken, TypeNode + { readonly kind: TKind; } interface ImportTypeAssertionContainer extends Node { @@ -5293,7 +5640,13 @@ declare namespace ts { interface UpdateExpression extends UnaryExpression { _updateExpressionBrand: any; } - type PrefixUnaryOperator = SyntaxKind.PlusPlusToken | SyntaxKind.MinusMinusToken | SyntaxKind.PlusToken | SyntaxKind.MinusToken | SyntaxKind.TildeToken | SyntaxKind.ExclamationToken; + type PrefixUnaryOperator = + | SyntaxKind.PlusPlusToken + | SyntaxKind.MinusMinusToken + | SyntaxKind.PlusToken + | SyntaxKind.MinusToken + | SyntaxKind.TildeToken + | SyntaxKind.ExclamationToken; interface PrefixUnaryExpression extends UpdateExpression { readonly kind: SyntaxKind.PrefixUnaryExpression; readonly operator: PrefixUnaryOperator; @@ -5365,21 +5718,52 @@ declare namespace ts { type MultiplicativeOperatorOrHigher = ExponentiationOperator | MultiplicativeOperator; type AdditiveOperator = SyntaxKind.PlusToken | SyntaxKind.MinusToken; type AdditiveOperatorOrHigher = MultiplicativeOperatorOrHigher | AdditiveOperator; - type ShiftOperator = SyntaxKind.LessThanLessThanToken | SyntaxKind.GreaterThanGreaterThanToken | SyntaxKind.GreaterThanGreaterThanGreaterThanToken; + type ShiftOperator = + | SyntaxKind.LessThanLessThanToken + | SyntaxKind.GreaterThanGreaterThanToken + | SyntaxKind.GreaterThanGreaterThanGreaterThanToken; type ShiftOperatorOrHigher = AdditiveOperatorOrHigher | ShiftOperator; - type RelationalOperator = SyntaxKind.LessThanToken | SyntaxKind.LessThanEqualsToken | SyntaxKind.GreaterThanToken | SyntaxKind.GreaterThanEqualsToken | SyntaxKind.InstanceOfKeyword | SyntaxKind.InKeyword; + type RelationalOperator = + | SyntaxKind.LessThanToken + | SyntaxKind.LessThanEqualsToken + | SyntaxKind.GreaterThanToken + | SyntaxKind.GreaterThanEqualsToken + | SyntaxKind.InstanceOfKeyword + | SyntaxKind.InKeyword; type RelationalOperatorOrHigher = ShiftOperatorOrHigher | RelationalOperator; - type EqualityOperator = SyntaxKind.EqualsEqualsToken | SyntaxKind.EqualsEqualsEqualsToken | SyntaxKind.ExclamationEqualsEqualsToken | SyntaxKind.ExclamationEqualsToken; + type EqualityOperator = + | SyntaxKind.EqualsEqualsToken + | SyntaxKind.EqualsEqualsEqualsToken + | SyntaxKind.ExclamationEqualsEqualsToken + | SyntaxKind.ExclamationEqualsToken; type EqualityOperatorOrHigher = RelationalOperatorOrHigher | EqualityOperator; type BitwiseOperator = SyntaxKind.AmpersandToken | SyntaxKind.BarToken | SyntaxKind.CaretToken; type BitwiseOperatorOrHigher = EqualityOperatorOrHigher | BitwiseOperator; type LogicalOperator = SyntaxKind.AmpersandAmpersandToken | SyntaxKind.BarBarToken; type LogicalOperatorOrHigher = BitwiseOperatorOrHigher | LogicalOperator; - type CompoundAssignmentOperator = SyntaxKind.PlusEqualsToken | SyntaxKind.MinusEqualsToken | SyntaxKind.AsteriskAsteriskEqualsToken | SyntaxKind.AsteriskEqualsToken | SyntaxKind.SlashEqualsToken | SyntaxKind.PercentEqualsToken | SyntaxKind.AmpersandEqualsToken | SyntaxKind.BarEqualsToken | SyntaxKind.CaretEqualsToken | SyntaxKind.LessThanLessThanEqualsToken | SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken | SyntaxKind.GreaterThanGreaterThanEqualsToken | SyntaxKind.BarBarEqualsToken | SyntaxKind.AmpersandAmpersandEqualsToken | SyntaxKind.QuestionQuestionEqualsToken; + type CompoundAssignmentOperator = + | SyntaxKind.PlusEqualsToken + | SyntaxKind.MinusEqualsToken + | SyntaxKind.AsteriskAsteriskEqualsToken + | SyntaxKind.AsteriskEqualsToken + | SyntaxKind.SlashEqualsToken + | SyntaxKind.PercentEqualsToken + | SyntaxKind.AmpersandEqualsToken + | SyntaxKind.BarEqualsToken + | SyntaxKind.CaretEqualsToken + | SyntaxKind.LessThanLessThanEqualsToken + | SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken + | SyntaxKind.GreaterThanGreaterThanEqualsToken + | SyntaxKind.BarBarEqualsToken + | SyntaxKind.AmpersandAmpersandEqualsToken + | SyntaxKind.QuestionQuestionEqualsToken; type AssignmentOperator = SyntaxKind.EqualsToken | CompoundAssignmentOperator; type AssignmentOperatorOrHigher = SyntaxKind.QuestionQuestionToken | LogicalOperatorOrHigher | AssignmentOperator; type BinaryOperator = AssignmentOperatorOrHigher | SyntaxKind.CommaToken; - type LogicalOrCoalescingAssignmentOperator = SyntaxKind.AmpersandAmpersandEqualsToken | SyntaxKind.BarBarEqualsToken | SyntaxKind.QuestionQuestionEqualsToken; + type LogicalOrCoalescingAssignmentOperator = + | SyntaxKind.AmpersandAmpersandEqualsToken + | SyntaxKind.BarBarEqualsToken + | SyntaxKind.QuestionQuestionEqualsToken; type BinaryOperatorToken = Token; interface BinaryExpression extends Expression, Declaration, JSDocContainer { readonly kind: SyntaxKind.BinaryExpression; @@ -5399,11 +5783,33 @@ declare namespace ts { readonly left: ArrayLiteralExpression; } type DestructuringAssignment = ObjectDestructuringAssignment | ArrayDestructuringAssignment; - type BindingOrAssignmentElement = VariableDeclaration | ParameterDeclaration | ObjectBindingOrAssignmentElement | ArrayBindingOrAssignmentElement; - type ObjectBindingOrAssignmentElement = BindingElement | PropertyAssignment | ShorthandPropertyAssignment | SpreadAssignment; - type ArrayBindingOrAssignmentElement = BindingElement | OmittedExpression | SpreadElement | ArrayLiteralExpression | ObjectLiteralExpression | AssignmentExpression | Identifier | PropertyAccessExpression | ElementAccessExpression; + type BindingOrAssignmentElement = + | VariableDeclaration + | ParameterDeclaration + | ObjectBindingOrAssignmentElement + | ArrayBindingOrAssignmentElement; + type ObjectBindingOrAssignmentElement = + | BindingElement + | PropertyAssignment + | ShorthandPropertyAssignment + | SpreadAssignment; + type ArrayBindingOrAssignmentElement = + | BindingElement + | OmittedExpression + | SpreadElement + | ArrayLiteralExpression + | ObjectLiteralExpression + | AssignmentExpression + | Identifier + | PropertyAccessExpression + | ElementAccessExpression; type BindingOrAssignmentElementRestIndicator = DotDotDotToken | SpreadElement | SpreadAssignment; - type BindingOrAssignmentElementTarget = BindingOrAssignmentPattern | Identifier | PropertyAccessExpression | ElementAccessExpression | OmittedExpression; + type BindingOrAssignmentElementTarget = + | BindingOrAssignmentPattern + | Identifier + | PropertyAccessExpression + | ElementAccessExpression + | OmittedExpression; type ObjectBindingOrAssignmentPattern = ObjectBindingPattern | ObjectLiteralExpression; type ArrayBindingOrAssignmentPattern = ArrayBindingPattern | ArrayLiteralExpression; type AssignmentPattern = ObjectLiteralExpression | ArrayLiteralExpression; @@ -5418,13 +5824,17 @@ declare namespace ts { } type FunctionBody = Block; type ConciseBody = FunctionBody | Expression; - interface FunctionExpression extends PrimaryExpression, FunctionLikeDeclarationBase, JSDocContainer, LocalsContainer, FlowContainer { + interface FunctionExpression + extends PrimaryExpression, FunctionLikeDeclarationBase, JSDocContainer, LocalsContainer, FlowContainer + { readonly kind: SyntaxKind.FunctionExpression; readonly modifiers?: NodeArray; readonly name?: Identifier; readonly body: FunctionBody; } - interface ArrowFunction extends Expression, FunctionLikeDeclarationBase, JSDocContainer, LocalsContainer, FlowContainer { + interface ArrowFunction + extends Expression, FunctionLikeDeclarationBase, JSDocContainer, LocalsContainer, FlowContainer + { readonly kind: SyntaxKind.ArrowFunction; readonly modifiers?: NodeArray; readonly equalsGreaterThanToken: EqualsGreaterThanToken; @@ -5462,7 +5872,13 @@ declare namespace ts { interface BigIntLiteral extends LiteralExpression { readonly kind: SyntaxKind.BigIntLiteral; } - type LiteralToken = NumericLiteral | BigIntLiteral | StringLiteral | JsxText | RegularExpressionLiteral | NoSubstitutionTemplateLiteral; + type LiteralToken = + | NumericLiteral + | BigIntLiteral + | StringLiteral + | JsxText + | RegularExpressionLiteral + | NoSubstitutionTemplateLiteral; interface TemplateHead extends TemplateLiteralLikeNode { readonly kind: SyntaxKind.TemplateHead; readonly parent: TemplateExpression | TemplateLiteralTypeNode; @@ -5582,7 +5998,12 @@ declare namespace ts { readonly typeArguments?: NodeArray; readonly template: TemplateLiteral; } - type CallLikeExpression = CallExpression | NewExpression | TaggedTemplateExpression | Decorator | JsxOpeningLikeElement; + type CallLikeExpression = + | CallExpression + | NewExpression + | TaggedTemplateExpression + | Decorator + | JsxOpeningLikeElement; interface AsExpression extends Expression { readonly kind: SyntaxKind.AsExpression; readonly expression: Expression; @@ -5826,8 +6247,17 @@ declare namespace ts { readonly block: Block; } type ObjectTypeDeclaration = ClassLikeDeclaration | InterfaceDeclaration | TypeLiteralNode; - type DeclarationWithTypeParameters = DeclarationWithTypeParameterChildren | JSDocTypedefTag | JSDocCallbackTag | JSDocSignature; - type DeclarationWithTypeParameterChildren = SignatureDeclaration | ClassLikeDeclaration | InterfaceDeclaration | TypeAliasDeclaration | JSDocTemplateTag; + type DeclarationWithTypeParameters = + | DeclarationWithTypeParameterChildren + | JSDocTypedefTag + | JSDocCallbackTag + | JSDocSignature; + type DeclarationWithTypeParameterChildren = + | SignatureDeclaration + | ClassLikeDeclaration + | InterfaceDeclaration + | TypeAliasDeclaration + | JSDocTemplateTag; interface ClassLikeDeclarationBase extends NamedDeclaration, JSDocContainer { readonly kind: SyntaxKind.ClassDeclaration | SyntaxKind.ClassExpression; readonly name?: Identifier; @@ -6013,7 +6443,13 @@ declare namespace ts { readonly name: Identifier; } type ImportOrExportSpecifier = ImportSpecifier | ExportSpecifier; - type TypeOnlyCompatibleAliasDeclaration = ImportClause | ImportEqualsDeclaration | NamespaceImport | ImportOrExportSpecifier | ExportDeclaration | NamespaceExport; + type TypeOnlyCompatibleAliasDeclaration = + | ImportClause + | ImportEqualsDeclaration + | NamespaceImport + | ImportOrExportSpecifier + | ExportDeclaration + | NamespaceExport; type TypeOnlyImportDeclaration = | ImportClause & { readonly isTypeOnly: true; @@ -6307,7 +6743,15 @@ declare namespace ts { Label = 12, Condition = 96, } - type FlowNode = FlowStart | FlowLabel | FlowAssignment | FlowCondition | FlowSwitchClause | FlowArrayMutation | FlowCall | FlowReduceLabel; + type FlowNode = + | FlowStart + | FlowLabel + | FlowAssignment + | FlowCondition + | FlowSwitchClause + | FlowArrayMutation + | FlowCall + | FlowReduceLabel; interface FlowNodeBase { flags: FlowFlags; id?: number; @@ -6490,7 +6934,14 @@ declare namespace ts { readonly operator: SyntaxKind.MinusToken; readonly operand: NumericLiteral; } - type JsonObjectExpression = ObjectLiteralExpression | ArrayLiteralExpression | JsonMinusNumericLiteral | NumericLiteral | StringLiteral | BooleanLiteral | NullLiteral; + type JsonObjectExpression = + | ObjectLiteralExpression + | ArrayLiteralExpression + | JsonMinusNumericLiteral + | NumericLiteral + | StringLiteral + | BooleanLiteral + | NullLiteral; interface JsonObjectExpressionStatement extends ExpressionStatement { readonly expression: JsonObjectExpression; } @@ -6502,7 +6953,13 @@ declare namespace ts { } interface ParseConfigHost extends ModuleResolutionHost { useCaseSensitiveFileNames: boolean; - readDirectory(rootDir: string, extensions: readonly string[], excludes: readonly string[] | undefined, includes: readonly string[], depth?: number): readonly string[]; + readDirectory( + rootDir: string, + extensions: readonly string[], + excludes: readonly string[] | undefined, + includes: readonly string[], + depth?: number, + ): readonly string[]; /** * Gets a value indicating whether the specified path exists and is a file. * @param path The path to test. @@ -6521,7 +6978,14 @@ declare namespace ts { }; interface WriteFileCallbackData { } - type WriteFileCallback = (fileName: string, text: string, writeByteOrderMark: boolean, onError?: (message: string) => void, sourceFiles?: readonly SourceFile[], data?: WriteFileCallbackData) => void; + type WriteFileCallback = ( + fileName: string, + text: string, + writeByteOrderMark: boolean, + onError?: (message: string) => void, + sourceFiles?: readonly SourceFile[], + data?: WriteFileCallbackData, + ) => void; class OperationCanceledException { } interface CancellationToken { @@ -6549,13 +7013,25 @@ declare namespace ts { * used for writing the JavaScript and declaration files. Otherwise, the writeFile parameter * will be invoked when writing the JavaScript and declaration files. */ - emit(targetSourceFile?: SourceFile, writeFile?: WriteFileCallback, cancellationToken?: CancellationToken, emitOnlyDtsFiles?: boolean, customTransformers?: CustomTransformers): EmitResult; + emit( + targetSourceFile?: SourceFile, + writeFile?: WriteFileCallback, + cancellationToken?: CancellationToken, + emitOnlyDtsFiles?: boolean, + customTransformers?: CustomTransformers, + ): EmitResult; getOptionsDiagnostics(cancellationToken?: CancellationToken): readonly Diagnostic[]; getGlobalDiagnostics(cancellationToken?: CancellationToken): readonly Diagnostic[]; - getSyntacticDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): readonly DiagnosticWithLocation[]; + getSyntacticDiagnostics( + sourceFile?: SourceFile, + cancellationToken?: CancellationToken, + ): readonly DiagnosticWithLocation[]; /** The first time this is called, it will return global diagnostics (no location). */ getSemanticDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): readonly Diagnostic[]; - getDeclarationDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): readonly DiagnosticWithLocation[]; + getDeclarationDiagnostics( + sourceFile?: SourceFile, + cancellationToken?: CancellationToken, + ): readonly DiagnosticWithLocation[]; getConfigFileParsingDiagnostics(): readonly Diagnostic[]; /** * Gets a type checker that can be used to semantically analyze source files in the program. @@ -6643,25 +7119,60 @@ declare namespace ts { getNonNullableType(type: Type): Type; getTypeArguments(type: TypeReference): readonly Type[]; /** Note that the resulting nodes cannot be checked. */ - typeToTypeNode(type: Type, enclosingDeclaration: Node | undefined, flags: NodeBuilderFlags | undefined): TypeNode | undefined; + typeToTypeNode( + type: Type, + enclosingDeclaration: Node | undefined, + flags: NodeBuilderFlags | undefined, + ): TypeNode | undefined; /** Note that the resulting nodes cannot be checked. */ - signatureToSignatureDeclaration(signature: Signature, kind: SyntaxKind, enclosingDeclaration: Node | undefined, flags: NodeBuilderFlags | undefined): + signatureToSignatureDeclaration( + signature: Signature, + kind: SyntaxKind, + enclosingDeclaration: Node | undefined, + flags: NodeBuilderFlags | undefined, + ): | SignatureDeclaration & { typeArguments?: NodeArray; } | undefined; /** Note that the resulting nodes cannot be checked. */ - indexInfoToIndexSignatureDeclaration(indexInfo: IndexInfo, enclosingDeclaration: Node | undefined, flags: NodeBuilderFlags | undefined): IndexSignatureDeclaration | undefined; + indexInfoToIndexSignatureDeclaration( + indexInfo: IndexInfo, + enclosingDeclaration: Node | undefined, + flags: NodeBuilderFlags | undefined, + ): IndexSignatureDeclaration | undefined; /** Note that the resulting nodes cannot be checked. */ - symbolToEntityName(symbol: Symbol, meaning: SymbolFlags, enclosingDeclaration: Node | undefined, flags: NodeBuilderFlags | undefined): EntityName | undefined; + symbolToEntityName( + symbol: Symbol, + meaning: SymbolFlags, + enclosingDeclaration: Node | undefined, + flags: NodeBuilderFlags | undefined, + ): EntityName | undefined; /** Note that the resulting nodes cannot be checked. */ - symbolToExpression(symbol: Symbol, meaning: SymbolFlags, enclosingDeclaration: Node | undefined, flags: NodeBuilderFlags | undefined): Expression | undefined; + symbolToExpression( + symbol: Symbol, + meaning: SymbolFlags, + enclosingDeclaration: Node | undefined, + flags: NodeBuilderFlags | undefined, + ): Expression | undefined; /** Note that the resulting nodes cannot be checked. */ - symbolToTypeParameterDeclarations(symbol: Symbol, enclosingDeclaration: Node | undefined, flags: NodeBuilderFlags | undefined): NodeArray | undefined; + symbolToTypeParameterDeclarations( + symbol: Symbol, + enclosingDeclaration: Node | undefined, + flags: NodeBuilderFlags | undefined, + ): NodeArray | undefined; /** Note that the resulting nodes cannot be checked. */ - symbolToParameterDeclaration(symbol: Symbol, enclosingDeclaration: Node | undefined, flags: NodeBuilderFlags | undefined): ParameterDeclaration | undefined; + symbolToParameterDeclaration( + symbol: Symbol, + enclosingDeclaration: Node | undefined, + flags: NodeBuilderFlags | undefined, + ): ParameterDeclaration | undefined; /** Note that the resulting nodes cannot be checked. */ - typeParameterToDeclaration(parameter: TypeParameter, enclosingDeclaration: Node | undefined, flags: NodeBuilderFlags | undefined): TypeParameterDeclaration | undefined; + typeParameterToDeclaration( + parameter: TypeParameter, + enclosingDeclaration: Node | undefined, + flags: NodeBuilderFlags | undefined, + ): TypeParameterDeclaration | undefined; getSymbolsInScope(location: Node, meaning: SymbolFlags): Symbol[]; getSymbolAtLocation(node: Node): Symbol | undefined; getSymbolsOfParameterPropertyDeclaration(parameter: ParameterDeclaration, parameterName: string): Symbol[]; @@ -6684,9 +7195,19 @@ declare namespace ts { getTypeOfAssignmentPattern(pattern: AssignmentPattern): Type; getTypeAtLocation(node: Node): Type; getTypeFromTypeNode(node: TypeNode): Type; - signatureToString(signature: Signature, enclosingDeclaration?: Node, flags?: TypeFormatFlags, kind?: SignatureKind): string; + signatureToString( + signature: Signature, + enclosingDeclaration?: Node, + flags?: TypeFormatFlags, + kind?: SignatureKind, + ): string; typeToString(type: Type, enclosingDeclaration?: Node, flags?: TypeFormatFlags): string; - symbolToString(symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags, flags?: SymbolFormatFlags): string; + symbolToString( + symbol: Symbol, + enclosingDeclaration?: Node, + meaning?: SymbolFlags, + flags?: SymbolFormatFlags, + ): string; typePredicateToString(predicate: TypePredicate, enclosingDeclaration?: Node, flags?: TypeFormatFlags): string; getFullyQualifiedName(symbol: Symbol): string; getAugmentedPropertiesOfType(type: Type): Symbol[]; @@ -6698,14 +7219,23 @@ declare namespace ts { * returns undefined if the node is not valid. * @param argumentCount Apparent number of arguments, passed in case of a possibly incomplete call. This should come from an ArgumentListInfo. See `signatureHelp.ts`. */ - getResolvedSignature(node: CallLikeExpression, candidatesOutArray?: Signature[], argumentCount?: number): Signature | undefined; + getResolvedSignature( + node: CallLikeExpression, + candidatesOutArray?: Signature[], + argumentCount?: number, + ): Signature | undefined; getSignatureFromDeclaration(declaration: SignatureDeclaration): Signature | undefined; isImplementationOfOverload(node: SignatureDeclaration): boolean | undefined; isUndefinedSymbol(symbol: Symbol): boolean; isArgumentsSymbol(symbol: Symbol): boolean; isUnknownSymbol(symbol: Symbol): boolean; - getConstantValue(node: EnumMember | PropertyAccessExpression | ElementAccessExpression): string | number | undefined; - isValidPropertyAccess(node: PropertyAccessExpression | QualifiedName | ImportTypeNode, propertyName: string): boolean; + getConstantValue( + node: EnumMember | PropertyAccessExpression | ElementAccessExpression, + ): string | number | undefined; + isValidPropertyAccess( + node: PropertyAccessExpression | QualifiedName | ImportTypeNode, + propertyName: string, + ): boolean; /** Follow all aliases to get the original symbol. */ getAliasedSymbol(symbol: Symbol): Symbol; /** Follow a *single* alias to get the immediately aliased symbol. */ @@ -6874,7 +7404,11 @@ declare namespace ts { parameterIndex: number; type: Type | undefined; } - type TypePredicate = ThisTypePredicate | IdentifierTypePredicate | AssertsThisTypePredicate | AssertsIdentifierTypePredicate; + type TypePredicate = + | ThisTypePredicate + | IdentifierTypePredicate + | AssertsThisTypePredicate + | AssertsIdentifierTypePredicate; enum SymbolFlags { None = 0, FunctionScopedVariable = 1, @@ -7401,7 +7935,17 @@ declare namespace ts { DynamicPriority = 2, FixedChunkSize = 3, } - type CompilerOptionsValue = string | number | boolean | (string | number)[] | string[] | MapLike | PluginImport[] | ProjectReference[] | null | undefined; + type CompilerOptionsValue = + | string + | number + | boolean + | (string | number)[] + | string[] + | MapLike + | PluginImport[] + | ProjectReference[] + | null + | undefined; interface CompilerOptions { allowImportingTsExtensions?: boolean; allowJs?: boolean; @@ -7716,8 +8260,19 @@ declare namespace ts { readonly resolvedTypeReferenceDirective: ResolvedTypeReferenceDirective | undefined; } interface CompilerHost extends ModuleResolutionHost { - getSourceFile(fileName: string, languageVersionOrOptions: ScriptTarget | CreateSourceFileOptions, onError?: (message: string) => void, shouldCreateNewSourceFile?: boolean): SourceFile | undefined; - getSourceFileByPath?(fileName: string, path: Path, languageVersionOrOptions: ScriptTarget | CreateSourceFileOptions, onError?: (message: string) => void, shouldCreateNewSourceFile?: boolean): SourceFile | undefined; + getSourceFile( + fileName: string, + languageVersionOrOptions: ScriptTarget | CreateSourceFileOptions, + onError?: (message: string) => void, + shouldCreateNewSourceFile?: boolean, + ): SourceFile | undefined; + getSourceFileByPath?( + fileName: string, + path: Path, + languageVersionOrOptions: ScriptTarget | CreateSourceFileOptions, + onError?: (message: string) => void, + shouldCreateNewSourceFile?: boolean, + ): SourceFile | undefined; getCancellationToken?(): CancellationToken; getDefaultLibFileName(options: CompilerOptions): string; getDefaultLibLocation?(): string; @@ -7726,9 +8281,22 @@ declare namespace ts { getCanonicalFileName(fileName: string): string; useCaseSensitiveFileNames(): boolean; getNewLine(): string; - readDirectory?(rootDir: string, extensions: readonly string[], excludes: readonly string[] | undefined, includes: readonly string[], depth?: number): string[]; + readDirectory?( + rootDir: string, + extensions: readonly string[], + excludes: readonly string[] | undefined, + includes: readonly string[], + depth?: number, + ): string[]; /** @deprecated supply resolveModuleNameLiterals instead for resolution that can handle newer resolution modes like nodenext */ - resolveModuleNames?(moduleNames: string[], containingFile: string, reusedNames: string[] | undefined, redirectedReference: ResolvedProjectReference | undefined, options: CompilerOptions, containingSourceFile?: SourceFile): (ResolvedModule | undefined)[]; + resolveModuleNames?( + moduleNames: string[], + containingFile: string, + reusedNames: string[] | undefined, + redirectedReference: ResolvedProjectReference | undefined, + options: CompilerOptions, + containingSourceFile?: SourceFile, + ): (ResolvedModule | undefined)[]; /** * Returns the module resolution cache used by a provided `resolveModuleNames` implementation so that any non-name module resolution operations (eg, package.json lookup) can reuse it */ @@ -7738,9 +8306,29 @@ declare namespace ts { * * This method is a companion for 'resolveModuleNames' and is used to resolve 'types' references to actual type declaration files */ - resolveTypeReferenceDirectives?(typeReferenceDirectiveNames: string[] | readonly FileReference[], containingFile: string, redirectedReference: ResolvedProjectReference | undefined, options: CompilerOptions, containingFileMode?: ResolutionMode): (ResolvedTypeReferenceDirective | undefined)[]; - resolveModuleNameLiterals?(moduleLiterals: readonly StringLiteralLike[], containingFile: string, redirectedReference: ResolvedProjectReference | undefined, options: CompilerOptions, containingSourceFile: SourceFile, reusedNames: readonly StringLiteralLike[] | undefined): readonly ResolvedModuleWithFailedLookupLocations[]; - resolveTypeReferenceDirectiveReferences?(typeDirectiveReferences: readonly T[], containingFile: string, redirectedReference: ResolvedProjectReference | undefined, options: CompilerOptions, containingSourceFile: SourceFile | undefined, reusedNames: readonly T[] | undefined): readonly ResolvedTypeReferenceDirectiveWithFailedLookupLocations[]; + resolveTypeReferenceDirectives?( + typeReferenceDirectiveNames: string[] | readonly FileReference[], + containingFile: string, + redirectedReference: ResolvedProjectReference | undefined, + options: CompilerOptions, + containingFileMode?: ResolutionMode, + ): (ResolvedTypeReferenceDirective | undefined)[]; + resolveModuleNameLiterals?( + moduleLiterals: readonly StringLiteralLike[], + containingFile: string, + redirectedReference: ResolvedProjectReference | undefined, + options: CompilerOptions, + containingSourceFile: SourceFile, + reusedNames: readonly StringLiteralLike[] | undefined, + ): readonly ResolvedModuleWithFailedLookupLocations[]; + resolveTypeReferenceDirectiveReferences?( + typeDirectiveReferences: readonly T[], + containingFile: string, + redirectedReference: ResolvedProjectReference | undefined, + options: CompilerOptions, + containingSourceFile: SourceFile | undefined, + reusedNames: readonly T[] | undefined, + ): readonly ResolvedTypeReferenceDirectiveWithFailedLookupLocations[]; getEnvironmentVariable?(name: string): string | undefined; /** If provided along with custom resolveModuleNames or resolveTypeReferenceDirectives, used to determine if unchanged file path needs to re-resolve modules/type reference directives */ hasInvalidatedResolutions?(filePath: Path): boolean; @@ -7836,7 +8424,10 @@ declare namespace ts { createNumericLiteral(value: string | number, numericLiteralFlags?: TokenFlags): NumericLiteral; createBigIntLiteral(value: string | PseudoBigInt): BigIntLiteral; createStringLiteral(text: string, isSingleQuote?: boolean): StringLiteral; - createStringLiteralFromNode(sourceNode: PropertyNameLiteral | PrivateIdentifier, isSingleQuote?: boolean): StringLiteral; + createStringLiteralFromNode( + sourceNode: PropertyNameLiteral | PrivateIdentifier, + isSingleQuote?: boolean, + ): StringLiteral; createRegularExpressionLiteral(text: string): RegularExpressionLiteral; createIdentifier(text: string): Identifier; /** @@ -7848,7 +8439,10 @@ declare namespace ts { * during emit so that the variable can be referenced in a nested function body. This is an alternative to * setting `EmitFlags.ReuseTempVariableScope` on the nested function itself. */ - createTempVariable(recordTempVariable: ((node: Identifier) => void) | undefined, reservedInNestedScopes?: boolean): Identifier; + createTempVariable( + recordTempVariable: ((node: Identifier) => void) | undefined, + reservedInNestedScopes?: boolean, + ): Identifier; /** * Create a unique temporary variable for use in a loop. * @param reservedInNestedScopes When `true`, reserves the temporary variable name in all nested scopes @@ -7885,55 +8479,251 @@ declare namespace ts { updateQualifiedName(node: QualifiedName, left: EntityName, right: Identifier): QualifiedName; createComputedPropertyName(expression: Expression): ComputedPropertyName; updateComputedPropertyName(node: ComputedPropertyName, expression: Expression): ComputedPropertyName; - createTypeParameterDeclaration(modifiers: readonly Modifier[] | undefined, name: string | Identifier, constraint?: TypeNode, defaultType?: TypeNode): TypeParameterDeclaration; - updateTypeParameterDeclaration(node: TypeParameterDeclaration, modifiers: readonly Modifier[] | undefined, name: Identifier, constraint: TypeNode | undefined, defaultType: TypeNode | undefined): TypeParameterDeclaration; - createParameterDeclaration(modifiers: readonly ModifierLike[] | undefined, dotDotDotToken: DotDotDotToken | undefined, name: string | BindingName, questionToken?: QuestionToken, type?: TypeNode, initializer?: Expression): ParameterDeclaration; - updateParameterDeclaration(node: ParameterDeclaration, modifiers: readonly ModifierLike[] | undefined, dotDotDotToken: DotDotDotToken | undefined, name: string | BindingName, questionToken: QuestionToken | undefined, type: TypeNode | undefined, initializer: Expression | undefined): ParameterDeclaration; + createTypeParameterDeclaration( + modifiers: readonly Modifier[] | undefined, + name: string | Identifier, + constraint?: TypeNode, + defaultType?: TypeNode, + ): TypeParameterDeclaration; + updateTypeParameterDeclaration( + node: TypeParameterDeclaration, + modifiers: readonly Modifier[] | undefined, + name: Identifier, + constraint: TypeNode | undefined, + defaultType: TypeNode | undefined, + ): TypeParameterDeclaration; + createParameterDeclaration( + modifiers: readonly ModifierLike[] | undefined, + dotDotDotToken: DotDotDotToken | undefined, + name: string | BindingName, + questionToken?: QuestionToken, + type?: TypeNode, + initializer?: Expression, + ): ParameterDeclaration; + updateParameterDeclaration( + node: ParameterDeclaration, + modifiers: readonly ModifierLike[] | undefined, + dotDotDotToken: DotDotDotToken | undefined, + name: string | BindingName, + questionToken: QuestionToken | undefined, + type: TypeNode | undefined, + initializer: Expression | undefined, + ): ParameterDeclaration; createDecorator(expression: Expression): Decorator; updateDecorator(node: Decorator, expression: Expression): Decorator; - createPropertySignature(modifiers: readonly Modifier[] | undefined, name: PropertyName | string, questionToken: QuestionToken | undefined, type: TypeNode | undefined): PropertySignature; - updatePropertySignature(node: PropertySignature, modifiers: readonly Modifier[] | undefined, name: PropertyName, questionToken: QuestionToken | undefined, type: TypeNode | undefined): PropertySignature; - createPropertyDeclaration(modifiers: readonly ModifierLike[] | undefined, name: string | PropertyName, questionOrExclamationToken: QuestionToken | ExclamationToken | undefined, type: TypeNode | undefined, initializer: Expression | undefined): PropertyDeclaration; - updatePropertyDeclaration(node: PropertyDeclaration, modifiers: readonly ModifierLike[] | undefined, name: string | PropertyName, questionOrExclamationToken: QuestionToken | ExclamationToken | undefined, type: TypeNode | undefined, initializer: Expression | undefined): PropertyDeclaration; - createMethodSignature(modifiers: readonly Modifier[] | undefined, name: string | PropertyName, questionToken: QuestionToken | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined): MethodSignature; - updateMethodSignature(node: MethodSignature, modifiers: readonly Modifier[] | undefined, name: PropertyName, questionToken: QuestionToken | undefined, typeParameters: NodeArray | undefined, parameters: NodeArray, type: TypeNode | undefined): MethodSignature; - createMethodDeclaration(modifiers: readonly ModifierLike[] | undefined, asteriskToken: AsteriskToken | undefined, name: string | PropertyName, questionToken: QuestionToken | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined): MethodDeclaration; - updateMethodDeclaration(node: MethodDeclaration, modifiers: readonly ModifierLike[] | undefined, asteriskToken: AsteriskToken | undefined, name: PropertyName, questionToken: QuestionToken | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined): MethodDeclaration; - createConstructorDeclaration(modifiers: readonly ModifierLike[] | undefined, parameters: readonly ParameterDeclaration[], body: Block | undefined): ConstructorDeclaration; - updateConstructorDeclaration(node: ConstructorDeclaration, modifiers: readonly ModifierLike[] | undefined, parameters: readonly ParameterDeclaration[], body: Block | undefined): ConstructorDeclaration; - createGetAccessorDeclaration(modifiers: readonly ModifierLike[] | undefined, name: string | PropertyName, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined): GetAccessorDeclaration; - updateGetAccessorDeclaration(node: GetAccessorDeclaration, modifiers: readonly ModifierLike[] | undefined, name: PropertyName, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined): GetAccessorDeclaration; - createSetAccessorDeclaration(modifiers: readonly ModifierLike[] | undefined, name: string | PropertyName, parameters: readonly ParameterDeclaration[], body: Block | undefined): SetAccessorDeclaration; - updateSetAccessorDeclaration(node: SetAccessorDeclaration, modifiers: readonly ModifierLike[] | undefined, name: PropertyName, parameters: readonly ParameterDeclaration[], body: Block | undefined): SetAccessorDeclaration; - createCallSignature(typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined): CallSignatureDeclaration; - updateCallSignature(node: CallSignatureDeclaration, typeParameters: NodeArray | undefined, parameters: NodeArray, type: TypeNode | undefined): CallSignatureDeclaration; - createConstructSignature(typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined): ConstructSignatureDeclaration; - updateConstructSignature(node: ConstructSignatureDeclaration, typeParameters: NodeArray | undefined, parameters: NodeArray, type: TypeNode | undefined): ConstructSignatureDeclaration; - createIndexSignature(modifiers: readonly ModifierLike[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode): IndexSignatureDeclaration; - updateIndexSignature(node: IndexSignatureDeclaration, modifiers: readonly ModifierLike[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode): IndexSignatureDeclaration; + createPropertySignature( + modifiers: readonly Modifier[] | undefined, + name: PropertyName | string, + questionToken: QuestionToken | undefined, + type: TypeNode | undefined, + ): PropertySignature; + updatePropertySignature( + node: PropertySignature, + modifiers: readonly Modifier[] | undefined, + name: PropertyName, + questionToken: QuestionToken | undefined, + type: TypeNode | undefined, + ): PropertySignature; + createPropertyDeclaration( + modifiers: readonly ModifierLike[] | undefined, + name: string | PropertyName, + questionOrExclamationToken: QuestionToken | ExclamationToken | undefined, + type: TypeNode | undefined, + initializer: Expression | undefined, + ): PropertyDeclaration; + updatePropertyDeclaration( + node: PropertyDeclaration, + modifiers: readonly ModifierLike[] | undefined, + name: string | PropertyName, + questionOrExclamationToken: QuestionToken | ExclamationToken | undefined, + type: TypeNode | undefined, + initializer: Expression | undefined, + ): PropertyDeclaration; + createMethodSignature( + modifiers: readonly Modifier[] | undefined, + name: string | PropertyName, + questionToken: QuestionToken | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + parameters: readonly ParameterDeclaration[], + type: TypeNode | undefined, + ): MethodSignature; + updateMethodSignature( + node: MethodSignature, + modifiers: readonly Modifier[] | undefined, + name: PropertyName, + questionToken: QuestionToken | undefined, + typeParameters: NodeArray | undefined, + parameters: NodeArray, + type: TypeNode | undefined, + ): MethodSignature; + createMethodDeclaration( + modifiers: readonly ModifierLike[] | undefined, + asteriskToken: AsteriskToken | undefined, + name: string | PropertyName, + questionToken: QuestionToken | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + parameters: readonly ParameterDeclaration[], + type: TypeNode | undefined, + body: Block | undefined, + ): MethodDeclaration; + updateMethodDeclaration( + node: MethodDeclaration, + modifiers: readonly ModifierLike[] | undefined, + asteriskToken: AsteriskToken | undefined, + name: PropertyName, + questionToken: QuestionToken | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + parameters: readonly ParameterDeclaration[], + type: TypeNode | undefined, + body: Block | undefined, + ): MethodDeclaration; + createConstructorDeclaration( + modifiers: readonly ModifierLike[] | undefined, + parameters: readonly ParameterDeclaration[], + body: Block | undefined, + ): ConstructorDeclaration; + updateConstructorDeclaration( + node: ConstructorDeclaration, + modifiers: readonly ModifierLike[] | undefined, + parameters: readonly ParameterDeclaration[], + body: Block | undefined, + ): ConstructorDeclaration; + createGetAccessorDeclaration( + modifiers: readonly ModifierLike[] | undefined, + name: string | PropertyName, + parameters: readonly ParameterDeclaration[], + type: TypeNode | undefined, + body: Block | undefined, + ): GetAccessorDeclaration; + updateGetAccessorDeclaration( + node: GetAccessorDeclaration, + modifiers: readonly ModifierLike[] | undefined, + name: PropertyName, + parameters: readonly ParameterDeclaration[], + type: TypeNode | undefined, + body: Block | undefined, + ): GetAccessorDeclaration; + createSetAccessorDeclaration( + modifiers: readonly ModifierLike[] | undefined, + name: string | PropertyName, + parameters: readonly ParameterDeclaration[], + body: Block | undefined, + ): SetAccessorDeclaration; + updateSetAccessorDeclaration( + node: SetAccessorDeclaration, + modifiers: readonly ModifierLike[] | undefined, + name: PropertyName, + parameters: readonly ParameterDeclaration[], + body: Block | undefined, + ): SetAccessorDeclaration; + createCallSignature( + typeParameters: readonly TypeParameterDeclaration[] | undefined, + parameters: readonly ParameterDeclaration[], + type: TypeNode | undefined, + ): CallSignatureDeclaration; + updateCallSignature( + node: CallSignatureDeclaration, + typeParameters: NodeArray | undefined, + parameters: NodeArray, + type: TypeNode | undefined, + ): CallSignatureDeclaration; + createConstructSignature( + typeParameters: readonly TypeParameterDeclaration[] | undefined, + parameters: readonly ParameterDeclaration[], + type: TypeNode | undefined, + ): ConstructSignatureDeclaration; + updateConstructSignature( + node: ConstructSignatureDeclaration, + typeParameters: NodeArray | undefined, + parameters: NodeArray, + type: TypeNode | undefined, + ): ConstructSignatureDeclaration; + createIndexSignature( + modifiers: readonly ModifierLike[] | undefined, + parameters: readonly ParameterDeclaration[], + type: TypeNode, + ): IndexSignatureDeclaration; + updateIndexSignature( + node: IndexSignatureDeclaration, + modifiers: readonly ModifierLike[] | undefined, + parameters: readonly ParameterDeclaration[], + type: TypeNode, + ): IndexSignatureDeclaration; createTemplateLiteralTypeSpan(type: TypeNode, literal: TemplateMiddle | TemplateTail): TemplateLiteralTypeSpan; - updateTemplateLiteralTypeSpan(node: TemplateLiteralTypeSpan, type: TypeNode, literal: TemplateMiddle | TemplateTail): TemplateLiteralTypeSpan; + updateTemplateLiteralTypeSpan( + node: TemplateLiteralTypeSpan, + type: TypeNode, + literal: TemplateMiddle | TemplateTail, + ): TemplateLiteralTypeSpan; createClassStaticBlockDeclaration(body: Block): ClassStaticBlockDeclaration; updateClassStaticBlockDeclaration(node: ClassStaticBlockDeclaration, body: Block): ClassStaticBlockDeclaration; createKeywordTypeNode(kind: TKind): KeywordTypeNode; - createTypePredicateNode(assertsModifier: AssertsKeyword | undefined, parameterName: Identifier | ThisTypeNode | string, type: TypeNode | undefined): TypePredicateNode; - updateTypePredicateNode(node: TypePredicateNode, assertsModifier: AssertsKeyword | undefined, parameterName: Identifier | ThisTypeNode, type: TypeNode | undefined): TypePredicateNode; + createTypePredicateNode( + assertsModifier: AssertsKeyword | undefined, + parameterName: Identifier | ThisTypeNode | string, + type: TypeNode | undefined, + ): TypePredicateNode; + updateTypePredicateNode( + node: TypePredicateNode, + assertsModifier: AssertsKeyword | undefined, + parameterName: Identifier | ThisTypeNode, + type: TypeNode | undefined, + ): TypePredicateNode; createTypeReferenceNode(typeName: string | EntityName, typeArguments?: readonly TypeNode[]): TypeReferenceNode; - updateTypeReferenceNode(node: TypeReferenceNode, typeName: EntityName, typeArguments: NodeArray | undefined): TypeReferenceNode; - createFunctionTypeNode(typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode): FunctionTypeNode; - updateFunctionTypeNode(node: FunctionTypeNode, typeParameters: NodeArray | undefined, parameters: NodeArray, type: TypeNode): FunctionTypeNode; - createConstructorTypeNode(modifiers: readonly Modifier[] | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode): ConstructorTypeNode; - updateConstructorTypeNode(node: ConstructorTypeNode, modifiers: readonly Modifier[] | undefined, typeParameters: NodeArray | undefined, parameters: NodeArray, type: TypeNode): ConstructorTypeNode; + updateTypeReferenceNode( + node: TypeReferenceNode, + typeName: EntityName, + typeArguments: NodeArray | undefined, + ): TypeReferenceNode; + createFunctionTypeNode( + typeParameters: readonly TypeParameterDeclaration[] | undefined, + parameters: readonly ParameterDeclaration[], + type: TypeNode, + ): FunctionTypeNode; + updateFunctionTypeNode( + node: FunctionTypeNode, + typeParameters: NodeArray | undefined, + parameters: NodeArray, + type: TypeNode, + ): FunctionTypeNode; + createConstructorTypeNode( + modifiers: readonly Modifier[] | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + parameters: readonly ParameterDeclaration[], + type: TypeNode, + ): ConstructorTypeNode; + updateConstructorTypeNode( + node: ConstructorTypeNode, + modifiers: readonly Modifier[] | undefined, + typeParameters: NodeArray | undefined, + parameters: NodeArray, + type: TypeNode, + ): ConstructorTypeNode; createTypeQueryNode(exprName: EntityName, typeArguments?: readonly TypeNode[]): TypeQueryNode; - updateTypeQueryNode(node: TypeQueryNode, exprName: EntityName, typeArguments?: readonly TypeNode[]): TypeQueryNode; + updateTypeQueryNode( + node: TypeQueryNode, + exprName: EntityName, + typeArguments?: readonly TypeNode[], + ): TypeQueryNode; createTypeLiteralNode(members: readonly TypeElement[] | undefined): TypeLiteralNode; updateTypeLiteralNode(node: TypeLiteralNode, members: NodeArray): TypeLiteralNode; createArrayTypeNode(elementType: TypeNode): ArrayTypeNode; updateArrayTypeNode(node: ArrayTypeNode, elementType: TypeNode): ArrayTypeNode; createTupleTypeNode(elements: readonly (TypeNode | NamedTupleMember)[]): TupleTypeNode; updateTupleTypeNode(node: TupleTypeNode, elements: readonly (TypeNode | NamedTupleMember)[]): TupleTypeNode; - createNamedTupleMember(dotDotDotToken: DotDotDotToken | undefined, name: Identifier, questionToken: QuestionToken | undefined, type: TypeNode): NamedTupleMember; - updateNamedTupleMember(node: NamedTupleMember, dotDotDotToken: DotDotDotToken | undefined, name: Identifier, questionToken: QuestionToken | undefined, type: TypeNode): NamedTupleMember; + createNamedTupleMember( + dotDotDotToken: DotDotDotToken | undefined, + name: Identifier, + questionToken: QuestionToken | undefined, + type: TypeNode, + ): NamedTupleMember; + updateNamedTupleMember( + node: NamedTupleMember, + dotDotDotToken: DotDotDotToken | undefined, + name: Identifier, + questionToken: QuestionToken | undefined, + type: TypeNode, + ): NamedTupleMember; createOptionalTypeNode(type: TypeNode): OptionalTypeNode; updateOptionalTypeNode(node: OptionalTypeNode, type: TypeNode): OptionalTypeNode; createRestTypeNode(type: TypeNode): RestTypeNode; @@ -7942,59 +8732,234 @@ declare namespace ts { updateUnionTypeNode(node: UnionTypeNode, types: NodeArray): UnionTypeNode; createIntersectionTypeNode(types: readonly TypeNode[]): IntersectionTypeNode; updateIntersectionTypeNode(node: IntersectionTypeNode, types: NodeArray): IntersectionTypeNode; - createConditionalTypeNode(checkType: TypeNode, extendsType: TypeNode, trueType: TypeNode, falseType: TypeNode): ConditionalTypeNode; - updateConditionalTypeNode(node: ConditionalTypeNode, checkType: TypeNode, extendsType: TypeNode, trueType: TypeNode, falseType: TypeNode): ConditionalTypeNode; + createConditionalTypeNode( + checkType: TypeNode, + extendsType: TypeNode, + trueType: TypeNode, + falseType: TypeNode, + ): ConditionalTypeNode; + updateConditionalTypeNode( + node: ConditionalTypeNode, + checkType: TypeNode, + extendsType: TypeNode, + trueType: TypeNode, + falseType: TypeNode, + ): ConditionalTypeNode; createInferTypeNode(typeParameter: TypeParameterDeclaration): InferTypeNode; updateInferTypeNode(node: InferTypeNode, typeParameter: TypeParameterDeclaration): InferTypeNode; - createImportTypeNode(argument: TypeNode, assertions?: ImportTypeAssertionContainer, qualifier?: EntityName, typeArguments?: readonly TypeNode[], isTypeOf?: boolean): ImportTypeNode; - updateImportTypeNode(node: ImportTypeNode, argument: TypeNode, assertions: ImportTypeAssertionContainer | undefined, qualifier: EntityName | undefined, typeArguments: readonly TypeNode[] | undefined, isTypeOf?: boolean): ImportTypeNode; + createImportTypeNode( + argument: TypeNode, + assertions?: ImportTypeAssertionContainer, + qualifier?: EntityName, + typeArguments?: readonly TypeNode[], + isTypeOf?: boolean, + ): ImportTypeNode; + updateImportTypeNode( + node: ImportTypeNode, + argument: TypeNode, + assertions: ImportTypeAssertionContainer | undefined, + qualifier: EntityName | undefined, + typeArguments: readonly TypeNode[] | undefined, + isTypeOf?: boolean, + ): ImportTypeNode; createParenthesizedType(type: TypeNode): ParenthesizedTypeNode; updateParenthesizedType(node: ParenthesizedTypeNode, type: TypeNode): ParenthesizedTypeNode; createThisTypeNode(): ThisTypeNode; - createTypeOperatorNode(operator: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.ReadonlyKeyword, type: TypeNode): TypeOperatorNode; + createTypeOperatorNode( + operator: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.ReadonlyKeyword, + type: TypeNode, + ): TypeOperatorNode; updateTypeOperatorNode(node: TypeOperatorNode, type: TypeNode): TypeOperatorNode; createIndexedAccessTypeNode(objectType: TypeNode, indexType: TypeNode): IndexedAccessTypeNode; - updateIndexedAccessTypeNode(node: IndexedAccessTypeNode, objectType: TypeNode, indexType: TypeNode): IndexedAccessTypeNode; - createMappedTypeNode(readonlyToken: ReadonlyKeyword | PlusToken | MinusToken | undefined, typeParameter: TypeParameterDeclaration, nameType: TypeNode | undefined, questionToken: QuestionToken | PlusToken | MinusToken | undefined, type: TypeNode | undefined, members: NodeArray | undefined): MappedTypeNode; - updateMappedTypeNode(node: MappedTypeNode, readonlyToken: ReadonlyKeyword | PlusToken | MinusToken | undefined, typeParameter: TypeParameterDeclaration, nameType: TypeNode | undefined, questionToken: QuestionToken | PlusToken | MinusToken | undefined, type: TypeNode | undefined, members: NodeArray | undefined): MappedTypeNode; + updateIndexedAccessTypeNode( + node: IndexedAccessTypeNode, + objectType: TypeNode, + indexType: TypeNode, + ): IndexedAccessTypeNode; + createMappedTypeNode( + readonlyToken: ReadonlyKeyword | PlusToken | MinusToken | undefined, + typeParameter: TypeParameterDeclaration, + nameType: TypeNode | undefined, + questionToken: QuestionToken | PlusToken | MinusToken | undefined, + type: TypeNode | undefined, + members: NodeArray | undefined, + ): MappedTypeNode; + updateMappedTypeNode( + node: MappedTypeNode, + readonlyToken: ReadonlyKeyword | PlusToken | MinusToken | undefined, + typeParameter: TypeParameterDeclaration, + nameType: TypeNode | undefined, + questionToken: QuestionToken | PlusToken | MinusToken | undefined, + type: TypeNode | undefined, + members: NodeArray | undefined, + ): MappedTypeNode; createLiteralTypeNode(literal: LiteralTypeNode["literal"]): LiteralTypeNode; updateLiteralTypeNode(node: LiteralTypeNode, literal: LiteralTypeNode["literal"]): LiteralTypeNode; - createTemplateLiteralType(head: TemplateHead, templateSpans: readonly TemplateLiteralTypeSpan[]): TemplateLiteralTypeNode; - updateTemplateLiteralType(node: TemplateLiteralTypeNode, head: TemplateHead, templateSpans: readonly TemplateLiteralTypeSpan[]): TemplateLiteralTypeNode; + createTemplateLiteralType( + head: TemplateHead, + templateSpans: readonly TemplateLiteralTypeSpan[], + ): TemplateLiteralTypeNode; + updateTemplateLiteralType( + node: TemplateLiteralTypeNode, + head: TemplateHead, + templateSpans: readonly TemplateLiteralTypeSpan[], + ): TemplateLiteralTypeNode; createObjectBindingPattern(elements: readonly BindingElement[]): ObjectBindingPattern; - updateObjectBindingPattern(node: ObjectBindingPattern, elements: readonly BindingElement[]): ObjectBindingPattern; + updateObjectBindingPattern( + node: ObjectBindingPattern, + elements: readonly BindingElement[], + ): ObjectBindingPattern; createArrayBindingPattern(elements: readonly ArrayBindingElement[]): ArrayBindingPattern; - updateArrayBindingPattern(node: ArrayBindingPattern, elements: readonly ArrayBindingElement[]): ArrayBindingPattern; - createBindingElement(dotDotDotToken: DotDotDotToken | undefined, propertyName: string | PropertyName | undefined, name: string | BindingName, initializer?: Expression): BindingElement; - updateBindingElement(node: BindingElement, dotDotDotToken: DotDotDotToken | undefined, propertyName: PropertyName | undefined, name: BindingName, initializer: Expression | undefined): BindingElement; + updateArrayBindingPattern( + node: ArrayBindingPattern, + elements: readonly ArrayBindingElement[], + ): ArrayBindingPattern; + createBindingElement( + dotDotDotToken: DotDotDotToken | undefined, + propertyName: string | PropertyName | undefined, + name: string | BindingName, + initializer?: Expression, + ): BindingElement; + updateBindingElement( + node: BindingElement, + dotDotDotToken: DotDotDotToken | undefined, + propertyName: PropertyName | undefined, + name: BindingName, + initializer: Expression | undefined, + ): BindingElement; createArrayLiteralExpression(elements?: readonly Expression[], multiLine?: boolean): ArrayLiteralExpression; - updateArrayLiteralExpression(node: ArrayLiteralExpression, elements: readonly Expression[]): ArrayLiteralExpression; - createObjectLiteralExpression(properties?: readonly ObjectLiteralElementLike[], multiLine?: boolean): ObjectLiteralExpression; - updateObjectLiteralExpression(node: ObjectLiteralExpression, properties: readonly ObjectLiteralElementLike[]): ObjectLiteralExpression; + updateArrayLiteralExpression( + node: ArrayLiteralExpression, + elements: readonly Expression[], + ): ArrayLiteralExpression; + createObjectLiteralExpression( + properties?: readonly ObjectLiteralElementLike[], + multiLine?: boolean, + ): ObjectLiteralExpression; + updateObjectLiteralExpression( + node: ObjectLiteralExpression, + properties: readonly ObjectLiteralElementLike[], + ): ObjectLiteralExpression; createPropertyAccessExpression(expression: Expression, name: string | MemberName): PropertyAccessExpression; - updatePropertyAccessExpression(node: PropertyAccessExpression, expression: Expression, name: MemberName): PropertyAccessExpression; - createPropertyAccessChain(expression: Expression, questionDotToken: QuestionDotToken | undefined, name: string | MemberName): PropertyAccessChain; - updatePropertyAccessChain(node: PropertyAccessChain, expression: Expression, questionDotToken: QuestionDotToken | undefined, name: MemberName): PropertyAccessChain; + updatePropertyAccessExpression( + node: PropertyAccessExpression, + expression: Expression, + name: MemberName, + ): PropertyAccessExpression; + createPropertyAccessChain( + expression: Expression, + questionDotToken: QuestionDotToken | undefined, + name: string | MemberName, + ): PropertyAccessChain; + updatePropertyAccessChain( + node: PropertyAccessChain, + expression: Expression, + questionDotToken: QuestionDotToken | undefined, + name: MemberName, + ): PropertyAccessChain; createElementAccessExpression(expression: Expression, index: number | Expression): ElementAccessExpression; - updateElementAccessExpression(node: ElementAccessExpression, expression: Expression, argumentExpression: Expression): ElementAccessExpression; - createElementAccessChain(expression: Expression, questionDotToken: QuestionDotToken | undefined, index: number | Expression): ElementAccessChain; - updateElementAccessChain(node: ElementAccessChain, expression: Expression, questionDotToken: QuestionDotToken | undefined, argumentExpression: Expression): ElementAccessChain; - createCallExpression(expression: Expression, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[] | undefined): CallExpression; - updateCallExpression(node: CallExpression, expression: Expression, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[]): CallExpression; - createCallChain(expression: Expression, questionDotToken: QuestionDotToken | undefined, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[] | undefined): CallChain; - updateCallChain(node: CallChain, expression: Expression, questionDotToken: QuestionDotToken | undefined, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[]): CallChain; - createNewExpression(expression: Expression, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[] | undefined): NewExpression; - updateNewExpression(node: NewExpression, expression: Expression, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[] | undefined): NewExpression; - createTaggedTemplateExpression(tag: Expression, typeArguments: readonly TypeNode[] | undefined, template: TemplateLiteral): TaggedTemplateExpression; - updateTaggedTemplateExpression(node: TaggedTemplateExpression, tag: Expression, typeArguments: readonly TypeNode[] | undefined, template: TemplateLiteral): TaggedTemplateExpression; + updateElementAccessExpression( + node: ElementAccessExpression, + expression: Expression, + argumentExpression: Expression, + ): ElementAccessExpression; + createElementAccessChain( + expression: Expression, + questionDotToken: QuestionDotToken | undefined, + index: number | Expression, + ): ElementAccessChain; + updateElementAccessChain( + node: ElementAccessChain, + expression: Expression, + questionDotToken: QuestionDotToken | undefined, + argumentExpression: Expression, + ): ElementAccessChain; + createCallExpression( + expression: Expression, + typeArguments: readonly TypeNode[] | undefined, + argumentsArray: readonly Expression[] | undefined, + ): CallExpression; + updateCallExpression( + node: CallExpression, + expression: Expression, + typeArguments: readonly TypeNode[] | undefined, + argumentsArray: readonly Expression[], + ): CallExpression; + createCallChain( + expression: Expression, + questionDotToken: QuestionDotToken | undefined, + typeArguments: readonly TypeNode[] | undefined, + argumentsArray: readonly Expression[] | undefined, + ): CallChain; + updateCallChain( + node: CallChain, + expression: Expression, + questionDotToken: QuestionDotToken | undefined, + typeArguments: readonly TypeNode[] | undefined, + argumentsArray: readonly Expression[], + ): CallChain; + createNewExpression( + expression: Expression, + typeArguments: readonly TypeNode[] | undefined, + argumentsArray: readonly Expression[] | undefined, + ): NewExpression; + updateNewExpression( + node: NewExpression, + expression: Expression, + typeArguments: readonly TypeNode[] | undefined, + argumentsArray: readonly Expression[] | undefined, + ): NewExpression; + createTaggedTemplateExpression( + tag: Expression, + typeArguments: readonly TypeNode[] | undefined, + template: TemplateLiteral, + ): TaggedTemplateExpression; + updateTaggedTemplateExpression( + node: TaggedTemplateExpression, + tag: Expression, + typeArguments: readonly TypeNode[] | undefined, + template: TemplateLiteral, + ): TaggedTemplateExpression; createTypeAssertion(type: TypeNode, expression: Expression): TypeAssertion; updateTypeAssertion(node: TypeAssertion, type: TypeNode, expression: Expression): TypeAssertion; createParenthesizedExpression(expression: Expression): ParenthesizedExpression; updateParenthesizedExpression(node: ParenthesizedExpression, expression: Expression): ParenthesizedExpression; - createFunctionExpression(modifiers: readonly Modifier[] | undefined, asteriskToken: AsteriskToken | undefined, name: string | Identifier | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[] | undefined, type: TypeNode | undefined, body: Block): FunctionExpression; - updateFunctionExpression(node: FunctionExpression, modifiers: readonly Modifier[] | undefined, asteriskToken: AsteriskToken | undefined, name: Identifier | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: Block): FunctionExpression; - createArrowFunction(modifiers: readonly Modifier[] | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, equalsGreaterThanToken: EqualsGreaterThanToken | undefined, body: ConciseBody): ArrowFunction; - updateArrowFunction(node: ArrowFunction, modifiers: readonly Modifier[] | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, equalsGreaterThanToken: EqualsGreaterThanToken, body: ConciseBody): ArrowFunction; + createFunctionExpression( + modifiers: readonly Modifier[] | undefined, + asteriskToken: AsteriskToken | undefined, + name: string | Identifier | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + parameters: readonly ParameterDeclaration[] | undefined, + type: TypeNode | undefined, + body: Block, + ): FunctionExpression; + updateFunctionExpression( + node: FunctionExpression, + modifiers: readonly Modifier[] | undefined, + asteriskToken: AsteriskToken | undefined, + name: Identifier | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + parameters: readonly ParameterDeclaration[], + type: TypeNode | undefined, + body: Block, + ): FunctionExpression; + createArrowFunction( + modifiers: readonly Modifier[] | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + parameters: readonly ParameterDeclaration[], + type: TypeNode | undefined, + equalsGreaterThanToken: EqualsGreaterThanToken | undefined, + body: ConciseBody, + ): ArrowFunction; + updateArrowFunction( + node: ArrowFunction, + modifiers: readonly Modifier[] | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + parameters: readonly ParameterDeclaration[], + type: TypeNode | undefined, + equalsGreaterThanToken: EqualsGreaterThanToken, + body: ConciseBody, + ): ArrowFunction; createDeleteExpression(expression: Expression): DeleteExpression; updateDeleteExpression(node: DeleteExpression, expression: Expression): DeleteExpression; createTypeOfExpression(expression: Expression): TypeOfExpression; @@ -8007,12 +8972,38 @@ declare namespace ts { updatePrefixUnaryExpression(node: PrefixUnaryExpression, operand: Expression): PrefixUnaryExpression; createPostfixUnaryExpression(operand: Expression, operator: PostfixUnaryOperator): PostfixUnaryExpression; updatePostfixUnaryExpression(node: PostfixUnaryExpression, operand: Expression): PostfixUnaryExpression; - createBinaryExpression(left: Expression, operator: BinaryOperator | BinaryOperatorToken, right: Expression): BinaryExpression; - updateBinaryExpression(node: BinaryExpression, left: Expression, operator: BinaryOperator | BinaryOperatorToken, right: Expression): BinaryExpression; - createConditionalExpression(condition: Expression, questionToken: QuestionToken | undefined, whenTrue: Expression, colonToken: ColonToken | undefined, whenFalse: Expression): ConditionalExpression; - updateConditionalExpression(node: ConditionalExpression, condition: Expression, questionToken: QuestionToken, whenTrue: Expression, colonToken: ColonToken, whenFalse: Expression): ConditionalExpression; + createBinaryExpression( + left: Expression, + operator: BinaryOperator | BinaryOperatorToken, + right: Expression, + ): BinaryExpression; + updateBinaryExpression( + node: BinaryExpression, + left: Expression, + operator: BinaryOperator | BinaryOperatorToken, + right: Expression, + ): BinaryExpression; + createConditionalExpression( + condition: Expression, + questionToken: QuestionToken | undefined, + whenTrue: Expression, + colonToken: ColonToken | undefined, + whenFalse: Expression, + ): ConditionalExpression; + updateConditionalExpression( + node: ConditionalExpression, + condition: Expression, + questionToken: QuestionToken, + whenTrue: Expression, + colonToken: ColonToken, + whenFalse: Expression, + ): ConditionalExpression; createTemplateExpression(head: TemplateHead, templateSpans: readonly TemplateSpan[]): TemplateExpression; - updateTemplateExpression(node: TemplateExpression, head: TemplateHead, templateSpans: readonly TemplateSpan[]): TemplateExpression; + updateTemplateExpression( + node: TemplateExpression, + head: TemplateHead, + templateSpans: readonly TemplateSpan[], + ): TemplateExpression; createTemplateHead(text: string, rawText?: string, templateFlags?: TokenFlags): TemplateHead; createTemplateHead(text: string | undefined, rawText: string, templateFlags?: TokenFlags): TemplateHead; createTemplateMiddle(text: string, rawText?: string, templateFlags?: TokenFlags): TemplateMiddle; @@ -8023,14 +9014,38 @@ declare namespace ts { createNoSubstitutionTemplateLiteral(text: string | undefined, rawText: string): NoSubstitutionTemplateLiteral; createYieldExpression(asteriskToken: AsteriskToken, expression: Expression): YieldExpression; createYieldExpression(asteriskToken: undefined, expression: Expression | undefined): YieldExpression; - updateYieldExpression(node: YieldExpression, asteriskToken: AsteriskToken | undefined, expression: Expression | undefined): YieldExpression; + updateYieldExpression( + node: YieldExpression, + asteriskToken: AsteriskToken | undefined, + expression: Expression | undefined, + ): YieldExpression; createSpreadElement(expression: Expression): SpreadElement; updateSpreadElement(node: SpreadElement, expression: Expression): SpreadElement; - createClassExpression(modifiers: readonly ModifierLike[] | undefined, name: string | Identifier | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, heritageClauses: readonly HeritageClause[] | undefined, members: readonly ClassElement[]): ClassExpression; - updateClassExpression(node: ClassExpression, modifiers: readonly ModifierLike[] | undefined, name: Identifier | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, heritageClauses: readonly HeritageClause[] | undefined, members: readonly ClassElement[]): ClassExpression; + createClassExpression( + modifiers: readonly ModifierLike[] | undefined, + name: string | Identifier | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + heritageClauses: readonly HeritageClause[] | undefined, + members: readonly ClassElement[], + ): ClassExpression; + updateClassExpression( + node: ClassExpression, + modifiers: readonly ModifierLike[] | undefined, + name: Identifier | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + heritageClauses: readonly HeritageClause[] | undefined, + members: readonly ClassElement[], + ): ClassExpression; createOmittedExpression(): OmittedExpression; - createExpressionWithTypeArguments(expression: Expression, typeArguments: readonly TypeNode[] | undefined): ExpressionWithTypeArguments; - updateExpressionWithTypeArguments(node: ExpressionWithTypeArguments, expression: Expression, typeArguments: readonly TypeNode[] | undefined): ExpressionWithTypeArguments; + createExpressionWithTypeArguments( + expression: Expression, + typeArguments: readonly TypeNode[] | undefined, + ): ExpressionWithTypeArguments; + updateExpressionWithTypeArguments( + node: ExpressionWithTypeArguments, + expression: Expression, + typeArguments: readonly TypeNode[] | undefined, + ): ExpressionWithTypeArguments; createAsExpression(expression: Expression, type: TypeNode): AsExpression; updateAsExpression(node: AsExpression, expression: Expression, type: TypeNode): AsExpression; createNonNullExpression(expression: Expression): NonNullExpression; @@ -8040,29 +9055,76 @@ declare namespace ts { createMetaProperty(keywordToken: MetaProperty["keywordToken"], name: Identifier): MetaProperty; updateMetaProperty(node: MetaProperty, name: Identifier): MetaProperty; createSatisfiesExpression(expression: Expression, type: TypeNode): SatisfiesExpression; - updateSatisfiesExpression(node: SatisfiesExpression, expression: Expression, type: TypeNode): SatisfiesExpression; + updateSatisfiesExpression( + node: SatisfiesExpression, + expression: Expression, + type: TypeNode, + ): SatisfiesExpression; createTemplateSpan(expression: Expression, literal: TemplateMiddle | TemplateTail): TemplateSpan; - updateTemplateSpan(node: TemplateSpan, expression: Expression, literal: TemplateMiddle | TemplateTail): TemplateSpan; + updateTemplateSpan( + node: TemplateSpan, + expression: Expression, + literal: TemplateMiddle | TemplateTail, + ): TemplateSpan; createSemicolonClassElement(): SemicolonClassElement; createBlock(statements: readonly Statement[], multiLine?: boolean): Block; updateBlock(node: Block, statements: readonly Statement[]): Block; - createVariableStatement(modifiers: readonly ModifierLike[] | undefined, declarationList: VariableDeclarationList | readonly VariableDeclaration[]): VariableStatement; - updateVariableStatement(node: VariableStatement, modifiers: readonly ModifierLike[] | undefined, declarationList: VariableDeclarationList): VariableStatement; + createVariableStatement( + modifiers: readonly ModifierLike[] | undefined, + declarationList: VariableDeclarationList | readonly VariableDeclaration[], + ): VariableStatement; + updateVariableStatement( + node: VariableStatement, + modifiers: readonly ModifierLike[] | undefined, + declarationList: VariableDeclarationList, + ): VariableStatement; createEmptyStatement(): EmptyStatement; createExpressionStatement(expression: Expression): ExpressionStatement; updateExpressionStatement(node: ExpressionStatement, expression: Expression): ExpressionStatement; createIfStatement(expression: Expression, thenStatement: Statement, elseStatement?: Statement): IfStatement; - updateIfStatement(node: IfStatement, expression: Expression, thenStatement: Statement, elseStatement: Statement | undefined): IfStatement; + updateIfStatement( + node: IfStatement, + expression: Expression, + thenStatement: Statement, + elseStatement: Statement | undefined, + ): IfStatement; createDoStatement(statement: Statement, expression: Expression): DoStatement; updateDoStatement(node: DoStatement, statement: Statement, expression: Expression): DoStatement; createWhileStatement(expression: Expression, statement: Statement): WhileStatement; updateWhileStatement(node: WhileStatement, expression: Expression, statement: Statement): WhileStatement; - createForStatement(initializer: ForInitializer | undefined, condition: Expression | undefined, incrementor: Expression | undefined, statement: Statement): ForStatement; - updateForStatement(node: ForStatement, initializer: ForInitializer | undefined, condition: Expression | undefined, incrementor: Expression | undefined, statement: Statement): ForStatement; + createForStatement( + initializer: ForInitializer | undefined, + condition: Expression | undefined, + incrementor: Expression | undefined, + statement: Statement, + ): ForStatement; + updateForStatement( + node: ForStatement, + initializer: ForInitializer | undefined, + condition: Expression | undefined, + incrementor: Expression | undefined, + statement: Statement, + ): ForStatement; createForInStatement(initializer: ForInitializer, expression: Expression, statement: Statement): ForInStatement; - updateForInStatement(node: ForInStatement, initializer: ForInitializer, expression: Expression, statement: Statement): ForInStatement; - createForOfStatement(awaitModifier: AwaitKeyword | undefined, initializer: ForInitializer, expression: Expression, statement: Statement): ForOfStatement; - updateForOfStatement(node: ForOfStatement, awaitModifier: AwaitKeyword | undefined, initializer: ForInitializer, expression: Expression, statement: Statement): ForOfStatement; + updateForInStatement( + node: ForInStatement, + initializer: ForInitializer, + expression: Expression, + statement: Statement, + ): ForInStatement; + createForOfStatement( + awaitModifier: AwaitKeyword | undefined, + initializer: ForInitializer, + expression: Expression, + statement: Statement, + ): ForOfStatement; + updateForOfStatement( + node: ForOfStatement, + awaitModifier: AwaitKeyword | undefined, + initializer: ForInitializer, + expression: Expression, + statement: Statement, + ): ForOfStatement; createContinueStatement(label?: string | Identifier): ContinueStatement; updateContinueStatement(node: ContinueStatement, label: Identifier | undefined): ContinueStatement; createBreakStatement(label?: string | Identifier): BreakStatement; @@ -8077,59 +9139,235 @@ declare namespace ts { updateLabeledStatement(node: LabeledStatement, label: Identifier, statement: Statement): LabeledStatement; createThrowStatement(expression: Expression): ThrowStatement; updateThrowStatement(node: ThrowStatement, expression: Expression): ThrowStatement; - createTryStatement(tryBlock: Block, catchClause: CatchClause | undefined, finallyBlock: Block | undefined): TryStatement; - updateTryStatement(node: TryStatement, tryBlock: Block, catchClause: CatchClause | undefined, finallyBlock: Block | undefined): TryStatement; + createTryStatement( + tryBlock: Block, + catchClause: CatchClause | undefined, + finallyBlock: Block | undefined, + ): TryStatement; + updateTryStatement( + node: TryStatement, + tryBlock: Block, + catchClause: CatchClause | undefined, + finallyBlock: Block | undefined, + ): TryStatement; createDebuggerStatement(): DebuggerStatement; - createVariableDeclaration(name: string | BindingName, exclamationToken?: ExclamationToken, type?: TypeNode, initializer?: Expression): VariableDeclaration; - updateVariableDeclaration(node: VariableDeclaration, name: BindingName, exclamationToken: ExclamationToken | undefined, type: TypeNode | undefined, initializer: Expression | undefined): VariableDeclaration; - createVariableDeclarationList(declarations: readonly VariableDeclaration[], flags?: NodeFlags): VariableDeclarationList; - updateVariableDeclarationList(node: VariableDeclarationList, declarations: readonly VariableDeclaration[]): VariableDeclarationList; - createFunctionDeclaration(modifiers: readonly ModifierLike[] | undefined, asteriskToken: AsteriskToken | undefined, name: string | Identifier | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined): FunctionDeclaration; - updateFunctionDeclaration(node: FunctionDeclaration, modifiers: readonly ModifierLike[] | undefined, asteriskToken: AsteriskToken | undefined, name: Identifier | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined): FunctionDeclaration; - createClassDeclaration(modifiers: readonly ModifierLike[] | undefined, name: string | Identifier | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, heritageClauses: readonly HeritageClause[] | undefined, members: readonly ClassElement[]): ClassDeclaration; - updateClassDeclaration(node: ClassDeclaration, modifiers: readonly ModifierLike[] | undefined, name: Identifier | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, heritageClauses: readonly HeritageClause[] | undefined, members: readonly ClassElement[]): ClassDeclaration; - createInterfaceDeclaration(modifiers: readonly ModifierLike[] | undefined, name: string | Identifier, typeParameters: readonly TypeParameterDeclaration[] | undefined, heritageClauses: readonly HeritageClause[] | undefined, members: readonly TypeElement[]): InterfaceDeclaration; - updateInterfaceDeclaration(node: InterfaceDeclaration, modifiers: readonly ModifierLike[] | undefined, name: Identifier, typeParameters: readonly TypeParameterDeclaration[] | undefined, heritageClauses: readonly HeritageClause[] | undefined, members: readonly TypeElement[]): InterfaceDeclaration; - createTypeAliasDeclaration(modifiers: readonly ModifierLike[] | undefined, name: string | Identifier, typeParameters: readonly TypeParameterDeclaration[] | undefined, type: TypeNode): TypeAliasDeclaration; - updateTypeAliasDeclaration(node: TypeAliasDeclaration, modifiers: readonly ModifierLike[] | undefined, name: Identifier, typeParameters: readonly TypeParameterDeclaration[] | undefined, type: TypeNode): TypeAliasDeclaration; - createEnumDeclaration(modifiers: readonly ModifierLike[] | undefined, name: string | Identifier, members: readonly EnumMember[]): EnumDeclaration; - updateEnumDeclaration(node: EnumDeclaration, modifiers: readonly ModifierLike[] | undefined, name: Identifier, members: readonly EnumMember[]): EnumDeclaration; - createModuleDeclaration(modifiers: readonly ModifierLike[] | undefined, name: ModuleName, body: ModuleBody | undefined, flags?: NodeFlags): ModuleDeclaration; - updateModuleDeclaration(node: ModuleDeclaration, modifiers: readonly ModifierLike[] | undefined, name: ModuleName, body: ModuleBody | undefined): ModuleDeclaration; + createVariableDeclaration( + name: string | BindingName, + exclamationToken?: ExclamationToken, + type?: TypeNode, + initializer?: Expression, + ): VariableDeclaration; + updateVariableDeclaration( + node: VariableDeclaration, + name: BindingName, + exclamationToken: ExclamationToken | undefined, + type: TypeNode | undefined, + initializer: Expression | undefined, + ): VariableDeclaration; + createVariableDeclarationList( + declarations: readonly VariableDeclaration[], + flags?: NodeFlags, + ): VariableDeclarationList; + updateVariableDeclarationList( + node: VariableDeclarationList, + declarations: readonly VariableDeclaration[], + ): VariableDeclarationList; + createFunctionDeclaration( + modifiers: readonly ModifierLike[] | undefined, + asteriskToken: AsteriskToken | undefined, + name: string | Identifier | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + parameters: readonly ParameterDeclaration[], + type: TypeNode | undefined, + body: Block | undefined, + ): FunctionDeclaration; + updateFunctionDeclaration( + node: FunctionDeclaration, + modifiers: readonly ModifierLike[] | undefined, + asteriskToken: AsteriskToken | undefined, + name: Identifier | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + parameters: readonly ParameterDeclaration[], + type: TypeNode | undefined, + body: Block | undefined, + ): FunctionDeclaration; + createClassDeclaration( + modifiers: readonly ModifierLike[] | undefined, + name: string | Identifier | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + heritageClauses: readonly HeritageClause[] | undefined, + members: readonly ClassElement[], + ): ClassDeclaration; + updateClassDeclaration( + node: ClassDeclaration, + modifiers: readonly ModifierLike[] | undefined, + name: Identifier | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + heritageClauses: readonly HeritageClause[] | undefined, + members: readonly ClassElement[], + ): ClassDeclaration; + createInterfaceDeclaration( + modifiers: readonly ModifierLike[] | undefined, + name: string | Identifier, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + heritageClauses: readonly HeritageClause[] | undefined, + members: readonly TypeElement[], + ): InterfaceDeclaration; + updateInterfaceDeclaration( + node: InterfaceDeclaration, + modifiers: readonly ModifierLike[] | undefined, + name: Identifier, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + heritageClauses: readonly HeritageClause[] | undefined, + members: readonly TypeElement[], + ): InterfaceDeclaration; + createTypeAliasDeclaration( + modifiers: readonly ModifierLike[] | undefined, + name: string | Identifier, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + type: TypeNode, + ): TypeAliasDeclaration; + updateTypeAliasDeclaration( + node: TypeAliasDeclaration, + modifiers: readonly ModifierLike[] | undefined, + name: Identifier, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + type: TypeNode, + ): TypeAliasDeclaration; + createEnumDeclaration( + modifiers: readonly ModifierLike[] | undefined, + name: string | Identifier, + members: readonly EnumMember[], + ): EnumDeclaration; + updateEnumDeclaration( + node: EnumDeclaration, + modifiers: readonly ModifierLike[] | undefined, + name: Identifier, + members: readonly EnumMember[], + ): EnumDeclaration; + createModuleDeclaration( + modifiers: readonly ModifierLike[] | undefined, + name: ModuleName, + body: ModuleBody | undefined, + flags?: NodeFlags, + ): ModuleDeclaration; + updateModuleDeclaration( + node: ModuleDeclaration, + modifiers: readonly ModifierLike[] | undefined, + name: ModuleName, + body: ModuleBody | undefined, + ): ModuleDeclaration; createModuleBlock(statements: readonly Statement[]): ModuleBlock; updateModuleBlock(node: ModuleBlock, statements: readonly Statement[]): ModuleBlock; createCaseBlock(clauses: readonly CaseOrDefaultClause[]): CaseBlock; updateCaseBlock(node: CaseBlock, clauses: readonly CaseOrDefaultClause[]): CaseBlock; createNamespaceExportDeclaration(name: string | Identifier): NamespaceExportDeclaration; - updateNamespaceExportDeclaration(node: NamespaceExportDeclaration, name: Identifier): NamespaceExportDeclaration; - createImportEqualsDeclaration(modifiers: readonly ModifierLike[] | undefined, isTypeOnly: boolean, name: string | Identifier, moduleReference: ModuleReference): ImportEqualsDeclaration; - updateImportEqualsDeclaration(node: ImportEqualsDeclaration, modifiers: readonly ModifierLike[] | undefined, isTypeOnly: boolean, name: Identifier, moduleReference: ModuleReference): ImportEqualsDeclaration; - createImportDeclaration(modifiers: readonly ModifierLike[] | undefined, importClause: ImportClause | undefined, moduleSpecifier: Expression, assertClause?: AssertClause): ImportDeclaration; - updateImportDeclaration(node: ImportDeclaration, modifiers: readonly ModifierLike[] | undefined, importClause: ImportClause | undefined, moduleSpecifier: Expression, assertClause: AssertClause | undefined): ImportDeclaration; - createImportClause(isTypeOnly: boolean, name: Identifier | undefined, namedBindings: NamedImportBindings | undefined): ImportClause; - updateImportClause(node: ImportClause, isTypeOnly: boolean, name: Identifier | undefined, namedBindings: NamedImportBindings | undefined): ImportClause; + updateNamespaceExportDeclaration( + node: NamespaceExportDeclaration, + name: Identifier, + ): NamespaceExportDeclaration; + createImportEqualsDeclaration( + modifiers: readonly ModifierLike[] | undefined, + isTypeOnly: boolean, + name: string | Identifier, + moduleReference: ModuleReference, + ): ImportEqualsDeclaration; + updateImportEqualsDeclaration( + node: ImportEqualsDeclaration, + modifiers: readonly ModifierLike[] | undefined, + isTypeOnly: boolean, + name: Identifier, + moduleReference: ModuleReference, + ): ImportEqualsDeclaration; + createImportDeclaration( + modifiers: readonly ModifierLike[] | undefined, + importClause: ImportClause | undefined, + moduleSpecifier: Expression, + assertClause?: AssertClause, + ): ImportDeclaration; + updateImportDeclaration( + node: ImportDeclaration, + modifiers: readonly ModifierLike[] | undefined, + importClause: ImportClause | undefined, + moduleSpecifier: Expression, + assertClause: AssertClause | undefined, + ): ImportDeclaration; + createImportClause( + isTypeOnly: boolean, + name: Identifier | undefined, + namedBindings: NamedImportBindings | undefined, + ): ImportClause; + updateImportClause( + node: ImportClause, + isTypeOnly: boolean, + name: Identifier | undefined, + namedBindings: NamedImportBindings | undefined, + ): ImportClause; createAssertClause(elements: NodeArray, multiLine?: boolean): AssertClause; updateAssertClause(node: AssertClause, elements: NodeArray, multiLine?: boolean): AssertClause; createAssertEntry(name: AssertionKey, value: Expression): AssertEntry; updateAssertEntry(node: AssertEntry, name: AssertionKey, value: Expression): AssertEntry; createImportTypeAssertionContainer(clause: AssertClause, multiLine?: boolean): ImportTypeAssertionContainer; - updateImportTypeAssertionContainer(node: ImportTypeAssertionContainer, clause: AssertClause, multiLine?: boolean): ImportTypeAssertionContainer; + updateImportTypeAssertionContainer( + node: ImportTypeAssertionContainer, + clause: AssertClause, + multiLine?: boolean, + ): ImportTypeAssertionContainer; createNamespaceImport(name: Identifier): NamespaceImport; updateNamespaceImport(node: NamespaceImport, name: Identifier): NamespaceImport; createNamespaceExport(name: Identifier): NamespaceExport; updateNamespaceExport(node: NamespaceExport, name: Identifier): NamespaceExport; createNamedImports(elements: readonly ImportSpecifier[]): NamedImports; updateNamedImports(node: NamedImports, elements: readonly ImportSpecifier[]): NamedImports; - createImportSpecifier(isTypeOnly: boolean, propertyName: Identifier | undefined, name: Identifier): ImportSpecifier; - updateImportSpecifier(node: ImportSpecifier, isTypeOnly: boolean, propertyName: Identifier | undefined, name: Identifier): ImportSpecifier; - createExportAssignment(modifiers: readonly ModifierLike[] | undefined, isExportEquals: boolean | undefined, expression: Expression): ExportAssignment; - updateExportAssignment(node: ExportAssignment, modifiers: readonly ModifierLike[] | undefined, expression: Expression): ExportAssignment; - createExportDeclaration(modifiers: readonly ModifierLike[] | undefined, isTypeOnly: boolean, exportClause: NamedExportBindings | undefined, moduleSpecifier?: Expression, assertClause?: AssertClause): ExportDeclaration; - updateExportDeclaration(node: ExportDeclaration, modifiers: readonly ModifierLike[] | undefined, isTypeOnly: boolean, exportClause: NamedExportBindings | undefined, moduleSpecifier: Expression | undefined, assertClause: AssertClause | undefined): ExportDeclaration; + createImportSpecifier( + isTypeOnly: boolean, + propertyName: Identifier | undefined, + name: Identifier, + ): ImportSpecifier; + updateImportSpecifier( + node: ImportSpecifier, + isTypeOnly: boolean, + propertyName: Identifier | undefined, + name: Identifier, + ): ImportSpecifier; + createExportAssignment( + modifiers: readonly ModifierLike[] | undefined, + isExportEquals: boolean | undefined, + expression: Expression, + ): ExportAssignment; + updateExportAssignment( + node: ExportAssignment, + modifiers: readonly ModifierLike[] | undefined, + expression: Expression, + ): ExportAssignment; + createExportDeclaration( + modifiers: readonly ModifierLike[] | undefined, + isTypeOnly: boolean, + exportClause: NamedExportBindings | undefined, + moduleSpecifier?: Expression, + assertClause?: AssertClause, + ): ExportDeclaration; + updateExportDeclaration( + node: ExportDeclaration, + modifiers: readonly ModifierLike[] | undefined, + isTypeOnly: boolean, + exportClause: NamedExportBindings | undefined, + moduleSpecifier: Expression | undefined, + assertClause: AssertClause | undefined, + ): ExportDeclaration; createNamedExports(elements: readonly ExportSpecifier[]): NamedExports; updateNamedExports(node: NamedExports, elements: readonly ExportSpecifier[]): NamedExports; - createExportSpecifier(isTypeOnly: boolean, propertyName: string | Identifier | undefined, name: string | Identifier): ExportSpecifier; - updateExportSpecifier(node: ExportSpecifier, isTypeOnly: boolean, propertyName: Identifier | undefined, name: Identifier): ExportSpecifier; + createExportSpecifier( + isTypeOnly: boolean, + propertyName: string | Identifier | undefined, + name: string | Identifier, + ): ExportSpecifier; + updateExportSpecifier( + node: ExportSpecifier, + isTypeOnly: boolean, + propertyName: Identifier | undefined, + name: Identifier, + ): ExportSpecifier; createExternalModuleReference(expression: Expression): ExternalModuleReference; updateExternalModuleReference(node: ExternalModuleReference, expression: Expression): ExternalModuleReference; createJSDocAllType(): JSDocAllType; @@ -8140,8 +9378,15 @@ declare namespace ts { updateJSDocNullableType(node: JSDocNullableType, type: TypeNode): JSDocNullableType; createJSDocOptionalType(type: TypeNode): JSDocOptionalType; updateJSDocOptionalType(node: JSDocOptionalType, type: TypeNode): JSDocOptionalType; - createJSDocFunctionType(parameters: readonly ParameterDeclaration[], type: TypeNode | undefined): JSDocFunctionType; - updateJSDocFunctionType(node: JSDocFunctionType, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined): JSDocFunctionType; + createJSDocFunctionType( + parameters: readonly ParameterDeclaration[], + type: TypeNode | undefined, + ): JSDocFunctionType; + updateJSDocFunctionType( + node: JSDocFunctionType, + parameters: readonly ParameterDeclaration[], + type: TypeNode | undefined, + ): JSDocFunctionType; createJSDocVariadicType(type: TypeNode): JSDocVariadicType; updateJSDocVariadicType(node: JSDocVariadicType, type: TypeNode): JSDocVariadicType; createJSDocNamepathType(type: TypeNode): JSDocNamepathType; @@ -8151,90 +9396,378 @@ declare namespace ts { createJSDocNameReference(name: EntityName | JSDocMemberName): JSDocNameReference; updateJSDocNameReference(node: JSDocNameReference, name: EntityName | JSDocMemberName): JSDocNameReference; createJSDocMemberName(left: EntityName | JSDocMemberName, right: Identifier): JSDocMemberName; - updateJSDocMemberName(node: JSDocMemberName, left: EntityName | JSDocMemberName, right: Identifier): JSDocMemberName; + updateJSDocMemberName( + node: JSDocMemberName, + left: EntityName | JSDocMemberName, + right: Identifier, + ): JSDocMemberName; createJSDocLink(name: EntityName | JSDocMemberName | undefined, text: string): JSDocLink; updateJSDocLink(node: JSDocLink, name: EntityName | JSDocMemberName | undefined, text: string): JSDocLink; createJSDocLinkCode(name: EntityName | JSDocMemberName | undefined, text: string): JSDocLinkCode; - updateJSDocLinkCode(node: JSDocLinkCode, name: EntityName | JSDocMemberName | undefined, text: string): JSDocLinkCode; + updateJSDocLinkCode( + node: JSDocLinkCode, + name: EntityName | JSDocMemberName | undefined, + text: string, + ): JSDocLinkCode; createJSDocLinkPlain(name: EntityName | JSDocMemberName | undefined, text: string): JSDocLinkPlain; - updateJSDocLinkPlain(node: JSDocLinkPlain, name: EntityName | JSDocMemberName | undefined, text: string): JSDocLinkPlain; - createJSDocTypeLiteral(jsDocPropertyTags?: readonly JSDocPropertyLikeTag[], isArrayType?: boolean): JSDocTypeLiteral; - updateJSDocTypeLiteral(node: JSDocTypeLiteral, jsDocPropertyTags: readonly JSDocPropertyLikeTag[] | undefined, isArrayType: boolean | undefined): JSDocTypeLiteral; - createJSDocSignature(typeParameters: readonly JSDocTemplateTag[] | undefined, parameters: readonly JSDocParameterTag[], type?: JSDocReturnTag): JSDocSignature; - updateJSDocSignature(node: JSDocSignature, typeParameters: readonly JSDocTemplateTag[] | undefined, parameters: readonly JSDocParameterTag[], type: JSDocReturnTag | undefined): JSDocSignature; - createJSDocTemplateTag(tagName: Identifier | undefined, constraint: JSDocTypeExpression | undefined, typeParameters: readonly TypeParameterDeclaration[], comment?: string | NodeArray): JSDocTemplateTag; - updateJSDocTemplateTag(node: JSDocTemplateTag, tagName: Identifier | undefined, constraint: JSDocTypeExpression | undefined, typeParameters: readonly TypeParameterDeclaration[], comment: string | NodeArray | undefined): JSDocTemplateTag; - createJSDocTypedefTag(tagName: Identifier | undefined, typeExpression?: JSDocTypeExpression | JSDocTypeLiteral, fullName?: Identifier | JSDocNamespaceDeclaration, comment?: string | NodeArray): JSDocTypedefTag; - updateJSDocTypedefTag(node: JSDocTypedefTag, tagName: Identifier | undefined, typeExpression: JSDocTypeExpression | JSDocTypeLiteral | undefined, fullName: Identifier | JSDocNamespaceDeclaration | undefined, comment: string | NodeArray | undefined): JSDocTypedefTag; - createJSDocParameterTag(tagName: Identifier | undefined, name: EntityName, isBracketed: boolean, typeExpression?: JSDocTypeExpression, isNameFirst?: boolean, comment?: string | NodeArray): JSDocParameterTag; - updateJSDocParameterTag(node: JSDocParameterTag, tagName: Identifier | undefined, name: EntityName, isBracketed: boolean, typeExpression: JSDocTypeExpression | undefined, isNameFirst: boolean, comment: string | NodeArray | undefined): JSDocParameterTag; - createJSDocPropertyTag(tagName: Identifier | undefined, name: EntityName, isBracketed: boolean, typeExpression?: JSDocTypeExpression, isNameFirst?: boolean, comment?: string | NodeArray): JSDocPropertyTag; - updateJSDocPropertyTag(node: JSDocPropertyTag, tagName: Identifier | undefined, name: EntityName, isBracketed: boolean, typeExpression: JSDocTypeExpression | undefined, isNameFirst: boolean, comment: string | NodeArray | undefined): JSDocPropertyTag; - createJSDocTypeTag(tagName: Identifier | undefined, typeExpression: JSDocTypeExpression, comment?: string | NodeArray): JSDocTypeTag; - updateJSDocTypeTag(node: JSDocTypeTag, tagName: Identifier | undefined, typeExpression: JSDocTypeExpression, comment: string | NodeArray | undefined): JSDocTypeTag; - createJSDocSeeTag(tagName: Identifier | undefined, nameExpression: JSDocNameReference | undefined, comment?: string | NodeArray): JSDocSeeTag; - updateJSDocSeeTag(node: JSDocSeeTag, tagName: Identifier | undefined, nameExpression: JSDocNameReference | undefined, comment?: string | NodeArray): JSDocSeeTag; - createJSDocReturnTag(tagName: Identifier | undefined, typeExpression?: JSDocTypeExpression, comment?: string | NodeArray): JSDocReturnTag; - updateJSDocReturnTag(node: JSDocReturnTag, tagName: Identifier | undefined, typeExpression: JSDocTypeExpression | undefined, comment: string | NodeArray | undefined): JSDocReturnTag; - createJSDocThisTag(tagName: Identifier | undefined, typeExpression: JSDocTypeExpression, comment?: string | NodeArray): JSDocThisTag; - updateJSDocThisTag(node: JSDocThisTag, tagName: Identifier | undefined, typeExpression: JSDocTypeExpression | undefined, comment: string | NodeArray | undefined): JSDocThisTag; - createJSDocEnumTag(tagName: Identifier | undefined, typeExpression: JSDocTypeExpression, comment?: string | NodeArray): JSDocEnumTag; - updateJSDocEnumTag(node: JSDocEnumTag, tagName: Identifier | undefined, typeExpression: JSDocTypeExpression, comment: string | NodeArray | undefined): JSDocEnumTag; - createJSDocCallbackTag(tagName: Identifier | undefined, typeExpression: JSDocSignature, fullName?: Identifier | JSDocNamespaceDeclaration, comment?: string | NodeArray): JSDocCallbackTag; - updateJSDocCallbackTag(node: JSDocCallbackTag, tagName: Identifier | undefined, typeExpression: JSDocSignature, fullName: Identifier | JSDocNamespaceDeclaration | undefined, comment: string | NodeArray | undefined): JSDocCallbackTag; - createJSDocOverloadTag(tagName: Identifier | undefined, typeExpression: JSDocSignature, comment?: string | NodeArray): JSDocOverloadTag; - updateJSDocOverloadTag(node: JSDocOverloadTag, tagName: Identifier | undefined, typeExpression: JSDocSignature, comment: string | NodeArray | undefined): JSDocOverloadTag; - createJSDocAugmentsTag(tagName: Identifier | undefined, className: JSDocAugmentsTag["class"], comment?: string | NodeArray): JSDocAugmentsTag; - updateJSDocAugmentsTag(node: JSDocAugmentsTag, tagName: Identifier | undefined, className: JSDocAugmentsTag["class"], comment: string | NodeArray | undefined): JSDocAugmentsTag; - createJSDocImplementsTag(tagName: Identifier | undefined, className: JSDocImplementsTag["class"], comment?: string | NodeArray): JSDocImplementsTag; - updateJSDocImplementsTag(node: JSDocImplementsTag, tagName: Identifier | undefined, className: JSDocImplementsTag["class"], comment: string | NodeArray | undefined): JSDocImplementsTag; - createJSDocAuthorTag(tagName: Identifier | undefined, comment?: string | NodeArray): JSDocAuthorTag; - updateJSDocAuthorTag(node: JSDocAuthorTag, tagName: Identifier | undefined, comment: string | NodeArray | undefined): JSDocAuthorTag; + updateJSDocLinkPlain( + node: JSDocLinkPlain, + name: EntityName | JSDocMemberName | undefined, + text: string, + ): JSDocLinkPlain; + createJSDocTypeLiteral( + jsDocPropertyTags?: readonly JSDocPropertyLikeTag[], + isArrayType?: boolean, + ): JSDocTypeLiteral; + updateJSDocTypeLiteral( + node: JSDocTypeLiteral, + jsDocPropertyTags: readonly JSDocPropertyLikeTag[] | undefined, + isArrayType: boolean | undefined, + ): JSDocTypeLiteral; + createJSDocSignature( + typeParameters: readonly JSDocTemplateTag[] | undefined, + parameters: readonly JSDocParameterTag[], + type?: JSDocReturnTag, + ): JSDocSignature; + updateJSDocSignature( + node: JSDocSignature, + typeParameters: readonly JSDocTemplateTag[] | undefined, + parameters: readonly JSDocParameterTag[], + type: JSDocReturnTag | undefined, + ): JSDocSignature; + createJSDocTemplateTag( + tagName: Identifier | undefined, + constraint: JSDocTypeExpression | undefined, + typeParameters: readonly TypeParameterDeclaration[], + comment?: string | NodeArray, + ): JSDocTemplateTag; + updateJSDocTemplateTag( + node: JSDocTemplateTag, + tagName: Identifier | undefined, + constraint: JSDocTypeExpression | undefined, + typeParameters: readonly TypeParameterDeclaration[], + comment: string | NodeArray | undefined, + ): JSDocTemplateTag; + createJSDocTypedefTag( + tagName: Identifier | undefined, + typeExpression?: JSDocTypeExpression | JSDocTypeLiteral, + fullName?: Identifier | JSDocNamespaceDeclaration, + comment?: string | NodeArray, + ): JSDocTypedefTag; + updateJSDocTypedefTag( + node: JSDocTypedefTag, + tagName: Identifier | undefined, + typeExpression: JSDocTypeExpression | JSDocTypeLiteral | undefined, + fullName: Identifier | JSDocNamespaceDeclaration | undefined, + comment: string | NodeArray | undefined, + ): JSDocTypedefTag; + createJSDocParameterTag( + tagName: Identifier | undefined, + name: EntityName, + isBracketed: boolean, + typeExpression?: JSDocTypeExpression, + isNameFirst?: boolean, + comment?: string | NodeArray, + ): JSDocParameterTag; + updateJSDocParameterTag( + node: JSDocParameterTag, + tagName: Identifier | undefined, + name: EntityName, + isBracketed: boolean, + typeExpression: JSDocTypeExpression | undefined, + isNameFirst: boolean, + comment: string | NodeArray | undefined, + ): JSDocParameterTag; + createJSDocPropertyTag( + tagName: Identifier | undefined, + name: EntityName, + isBracketed: boolean, + typeExpression?: JSDocTypeExpression, + isNameFirst?: boolean, + comment?: string | NodeArray, + ): JSDocPropertyTag; + updateJSDocPropertyTag( + node: JSDocPropertyTag, + tagName: Identifier | undefined, + name: EntityName, + isBracketed: boolean, + typeExpression: JSDocTypeExpression | undefined, + isNameFirst: boolean, + comment: string | NodeArray | undefined, + ): JSDocPropertyTag; + createJSDocTypeTag( + tagName: Identifier | undefined, + typeExpression: JSDocTypeExpression, + comment?: string | NodeArray, + ): JSDocTypeTag; + updateJSDocTypeTag( + node: JSDocTypeTag, + tagName: Identifier | undefined, + typeExpression: JSDocTypeExpression, + comment: string | NodeArray | undefined, + ): JSDocTypeTag; + createJSDocSeeTag( + tagName: Identifier | undefined, + nameExpression: JSDocNameReference | undefined, + comment?: string | NodeArray, + ): JSDocSeeTag; + updateJSDocSeeTag( + node: JSDocSeeTag, + tagName: Identifier | undefined, + nameExpression: JSDocNameReference | undefined, + comment?: string | NodeArray, + ): JSDocSeeTag; + createJSDocReturnTag( + tagName: Identifier | undefined, + typeExpression?: JSDocTypeExpression, + comment?: string | NodeArray, + ): JSDocReturnTag; + updateJSDocReturnTag( + node: JSDocReturnTag, + tagName: Identifier | undefined, + typeExpression: JSDocTypeExpression | undefined, + comment: string | NodeArray | undefined, + ): JSDocReturnTag; + createJSDocThisTag( + tagName: Identifier | undefined, + typeExpression: JSDocTypeExpression, + comment?: string | NodeArray, + ): JSDocThisTag; + updateJSDocThisTag( + node: JSDocThisTag, + tagName: Identifier | undefined, + typeExpression: JSDocTypeExpression | undefined, + comment: string | NodeArray | undefined, + ): JSDocThisTag; + createJSDocEnumTag( + tagName: Identifier | undefined, + typeExpression: JSDocTypeExpression, + comment?: string | NodeArray, + ): JSDocEnumTag; + updateJSDocEnumTag( + node: JSDocEnumTag, + tagName: Identifier | undefined, + typeExpression: JSDocTypeExpression, + comment: string | NodeArray | undefined, + ): JSDocEnumTag; + createJSDocCallbackTag( + tagName: Identifier | undefined, + typeExpression: JSDocSignature, + fullName?: Identifier | JSDocNamespaceDeclaration, + comment?: string | NodeArray, + ): JSDocCallbackTag; + updateJSDocCallbackTag( + node: JSDocCallbackTag, + tagName: Identifier | undefined, + typeExpression: JSDocSignature, + fullName: Identifier | JSDocNamespaceDeclaration | undefined, + comment: string | NodeArray | undefined, + ): JSDocCallbackTag; + createJSDocOverloadTag( + tagName: Identifier | undefined, + typeExpression: JSDocSignature, + comment?: string | NodeArray, + ): JSDocOverloadTag; + updateJSDocOverloadTag( + node: JSDocOverloadTag, + tagName: Identifier | undefined, + typeExpression: JSDocSignature, + comment: string | NodeArray | undefined, + ): JSDocOverloadTag; + createJSDocAugmentsTag( + tagName: Identifier | undefined, + className: JSDocAugmentsTag["class"], + comment?: string | NodeArray, + ): JSDocAugmentsTag; + updateJSDocAugmentsTag( + node: JSDocAugmentsTag, + tagName: Identifier | undefined, + className: JSDocAugmentsTag["class"], + comment: string | NodeArray | undefined, + ): JSDocAugmentsTag; + createJSDocImplementsTag( + tagName: Identifier | undefined, + className: JSDocImplementsTag["class"], + comment?: string | NodeArray, + ): JSDocImplementsTag; + updateJSDocImplementsTag( + node: JSDocImplementsTag, + tagName: Identifier | undefined, + className: JSDocImplementsTag["class"], + comment: string | NodeArray | undefined, + ): JSDocImplementsTag; + createJSDocAuthorTag( + tagName: Identifier | undefined, + comment?: string | NodeArray, + ): JSDocAuthorTag; + updateJSDocAuthorTag( + node: JSDocAuthorTag, + tagName: Identifier | undefined, + comment: string | NodeArray | undefined, + ): JSDocAuthorTag; createJSDocClassTag(tagName: Identifier | undefined, comment?: string | NodeArray): JSDocClassTag; - updateJSDocClassTag(node: JSDocClassTag, tagName: Identifier | undefined, comment: string | NodeArray | undefined): JSDocClassTag; - createJSDocPublicTag(tagName: Identifier | undefined, comment?: string | NodeArray): JSDocPublicTag; - updateJSDocPublicTag(node: JSDocPublicTag, tagName: Identifier | undefined, comment: string | NodeArray | undefined): JSDocPublicTag; - createJSDocPrivateTag(tagName: Identifier | undefined, comment?: string | NodeArray): JSDocPrivateTag; - updateJSDocPrivateTag(node: JSDocPrivateTag, tagName: Identifier | undefined, comment: string | NodeArray | undefined): JSDocPrivateTag; - createJSDocProtectedTag(tagName: Identifier | undefined, comment?: string | NodeArray): JSDocProtectedTag; - updateJSDocProtectedTag(node: JSDocProtectedTag, tagName: Identifier | undefined, comment: string | NodeArray | undefined): JSDocProtectedTag; - createJSDocReadonlyTag(tagName: Identifier | undefined, comment?: string | NodeArray): JSDocReadonlyTag; - updateJSDocReadonlyTag(node: JSDocReadonlyTag, tagName: Identifier | undefined, comment: string | NodeArray | undefined): JSDocReadonlyTag; + updateJSDocClassTag( + node: JSDocClassTag, + tagName: Identifier | undefined, + comment: string | NodeArray | undefined, + ): JSDocClassTag; + createJSDocPublicTag( + tagName: Identifier | undefined, + comment?: string | NodeArray, + ): JSDocPublicTag; + updateJSDocPublicTag( + node: JSDocPublicTag, + tagName: Identifier | undefined, + comment: string | NodeArray | undefined, + ): JSDocPublicTag; + createJSDocPrivateTag( + tagName: Identifier | undefined, + comment?: string | NodeArray, + ): JSDocPrivateTag; + updateJSDocPrivateTag( + node: JSDocPrivateTag, + tagName: Identifier | undefined, + comment: string | NodeArray | undefined, + ): JSDocPrivateTag; + createJSDocProtectedTag( + tagName: Identifier | undefined, + comment?: string | NodeArray, + ): JSDocProtectedTag; + updateJSDocProtectedTag( + node: JSDocProtectedTag, + tagName: Identifier | undefined, + comment: string | NodeArray | undefined, + ): JSDocProtectedTag; + createJSDocReadonlyTag( + tagName: Identifier | undefined, + comment?: string | NodeArray, + ): JSDocReadonlyTag; + updateJSDocReadonlyTag( + node: JSDocReadonlyTag, + tagName: Identifier | undefined, + comment: string | NodeArray | undefined, + ): JSDocReadonlyTag; createJSDocUnknownTag(tagName: Identifier, comment?: string | NodeArray): JSDocUnknownTag; - updateJSDocUnknownTag(node: JSDocUnknownTag, tagName: Identifier, comment: string | NodeArray | undefined): JSDocUnknownTag; - createJSDocDeprecatedTag(tagName: Identifier | undefined, comment?: string | NodeArray): JSDocDeprecatedTag; - updateJSDocDeprecatedTag(node: JSDocDeprecatedTag, tagName: Identifier | undefined, comment?: string | NodeArray): JSDocDeprecatedTag; - createJSDocOverrideTag(tagName: Identifier | undefined, comment?: string | NodeArray): JSDocOverrideTag; - updateJSDocOverrideTag(node: JSDocOverrideTag, tagName: Identifier | undefined, comment?: string | NodeArray): JSDocOverrideTag; - createJSDocThrowsTag(tagName: Identifier, typeExpression: JSDocTypeExpression | undefined, comment?: string | NodeArray): JSDocThrowsTag; - updateJSDocThrowsTag(node: JSDocThrowsTag, tagName: Identifier | undefined, typeExpression: JSDocTypeExpression | undefined, comment?: string | NodeArray | undefined): JSDocThrowsTag; - createJSDocSatisfiesTag(tagName: Identifier | undefined, typeExpression: JSDocTypeExpression, comment?: string | NodeArray): JSDocSatisfiesTag; - updateJSDocSatisfiesTag(node: JSDocSatisfiesTag, tagName: Identifier | undefined, typeExpression: JSDocTypeExpression, comment: string | NodeArray | undefined): JSDocSatisfiesTag; + updateJSDocUnknownTag( + node: JSDocUnknownTag, + tagName: Identifier, + comment: string | NodeArray | undefined, + ): JSDocUnknownTag; + createJSDocDeprecatedTag( + tagName: Identifier | undefined, + comment?: string | NodeArray, + ): JSDocDeprecatedTag; + updateJSDocDeprecatedTag( + node: JSDocDeprecatedTag, + tagName: Identifier | undefined, + comment?: string | NodeArray, + ): JSDocDeprecatedTag; + createJSDocOverrideTag( + tagName: Identifier | undefined, + comment?: string | NodeArray, + ): JSDocOverrideTag; + updateJSDocOverrideTag( + node: JSDocOverrideTag, + tagName: Identifier | undefined, + comment?: string | NodeArray, + ): JSDocOverrideTag; + createJSDocThrowsTag( + tagName: Identifier, + typeExpression: JSDocTypeExpression | undefined, + comment?: string | NodeArray, + ): JSDocThrowsTag; + updateJSDocThrowsTag( + node: JSDocThrowsTag, + tagName: Identifier | undefined, + typeExpression: JSDocTypeExpression | undefined, + comment?: string | NodeArray | undefined, + ): JSDocThrowsTag; + createJSDocSatisfiesTag( + tagName: Identifier | undefined, + typeExpression: JSDocTypeExpression, + comment?: string | NodeArray, + ): JSDocSatisfiesTag; + updateJSDocSatisfiesTag( + node: JSDocSatisfiesTag, + tagName: Identifier | undefined, + typeExpression: JSDocTypeExpression, + comment: string | NodeArray | undefined, + ): JSDocSatisfiesTag; createJSDocText(text: string): JSDocText; updateJSDocText(node: JSDocText, text: string): JSDocText; - createJSDocComment(comment?: string | NodeArray | undefined, tags?: readonly JSDocTag[] | undefined): JSDoc; - updateJSDocComment(node: JSDoc, comment: string | NodeArray | undefined, tags: readonly JSDocTag[] | undefined): JSDoc; - createJsxElement(openingElement: JsxOpeningElement, children: readonly JsxChild[], closingElement: JsxClosingElement): JsxElement; - updateJsxElement(node: JsxElement, openingElement: JsxOpeningElement, children: readonly JsxChild[], closingElement: JsxClosingElement): JsxElement; - createJsxSelfClosingElement(tagName: JsxTagNameExpression, typeArguments: readonly TypeNode[] | undefined, attributes: JsxAttributes): JsxSelfClosingElement; - updateJsxSelfClosingElement(node: JsxSelfClosingElement, tagName: JsxTagNameExpression, typeArguments: readonly TypeNode[] | undefined, attributes: JsxAttributes): JsxSelfClosingElement; - createJsxOpeningElement(tagName: JsxTagNameExpression, typeArguments: readonly TypeNode[] | undefined, attributes: JsxAttributes): JsxOpeningElement; - updateJsxOpeningElement(node: JsxOpeningElement, tagName: JsxTagNameExpression, typeArguments: readonly TypeNode[] | undefined, attributes: JsxAttributes): JsxOpeningElement; + createJSDocComment( + comment?: string | NodeArray | undefined, + tags?: readonly JSDocTag[] | undefined, + ): JSDoc; + updateJSDocComment( + node: JSDoc, + comment: string | NodeArray | undefined, + tags: readonly JSDocTag[] | undefined, + ): JSDoc; + createJsxElement( + openingElement: JsxOpeningElement, + children: readonly JsxChild[], + closingElement: JsxClosingElement, + ): JsxElement; + updateJsxElement( + node: JsxElement, + openingElement: JsxOpeningElement, + children: readonly JsxChild[], + closingElement: JsxClosingElement, + ): JsxElement; + createJsxSelfClosingElement( + tagName: JsxTagNameExpression, + typeArguments: readonly TypeNode[] | undefined, + attributes: JsxAttributes, + ): JsxSelfClosingElement; + updateJsxSelfClosingElement( + node: JsxSelfClosingElement, + tagName: JsxTagNameExpression, + typeArguments: readonly TypeNode[] | undefined, + attributes: JsxAttributes, + ): JsxSelfClosingElement; + createJsxOpeningElement( + tagName: JsxTagNameExpression, + typeArguments: readonly TypeNode[] | undefined, + attributes: JsxAttributes, + ): JsxOpeningElement; + updateJsxOpeningElement( + node: JsxOpeningElement, + tagName: JsxTagNameExpression, + typeArguments: readonly TypeNode[] | undefined, + attributes: JsxAttributes, + ): JsxOpeningElement; createJsxClosingElement(tagName: JsxTagNameExpression): JsxClosingElement; updateJsxClosingElement(node: JsxClosingElement, tagName: JsxTagNameExpression): JsxClosingElement; - createJsxFragment(openingFragment: JsxOpeningFragment, children: readonly JsxChild[], closingFragment: JsxClosingFragment): JsxFragment; + createJsxFragment( + openingFragment: JsxOpeningFragment, + children: readonly JsxChild[], + closingFragment: JsxClosingFragment, + ): JsxFragment; createJsxText(text: string, containsOnlyTriviaWhiteSpaces?: boolean): JsxText; updateJsxText(node: JsxText, text: string, containsOnlyTriviaWhiteSpaces?: boolean): JsxText; createJsxOpeningFragment(): JsxOpeningFragment; createJsxJsxClosingFragment(): JsxClosingFragment; - updateJsxFragment(node: JsxFragment, openingFragment: JsxOpeningFragment, children: readonly JsxChild[], closingFragment: JsxClosingFragment): JsxFragment; + updateJsxFragment( + node: JsxFragment, + openingFragment: JsxOpeningFragment, + children: readonly JsxChild[], + closingFragment: JsxClosingFragment, + ): JsxFragment; createJsxAttribute(name: JsxAttributeName, initializer: JsxAttributeValue | undefined): JsxAttribute; - updateJsxAttribute(node: JsxAttribute, name: JsxAttributeName, initializer: JsxAttributeValue | undefined): JsxAttribute; + updateJsxAttribute( + node: JsxAttribute, + name: JsxAttributeName, + initializer: JsxAttributeValue | undefined, + ): JsxAttribute; createJsxAttributes(properties: readonly JsxAttributeLike[]): JsxAttributes; updateJsxAttributes(node: JsxAttributes, properties: readonly JsxAttributeLike[]): JsxAttributes; createJsxSpreadAttribute(expression: Expression): JsxSpreadAttribute; updateJsxSpreadAttribute(node: JsxSpreadAttribute, expression: Expression): JsxSpreadAttribute; - createJsxExpression(dotDotDotToken: DotDotDotToken | undefined, expression: Expression | undefined): JsxExpression; + createJsxExpression( + dotDotDotToken: DotDotDotToken | undefined, + expression: Expression | undefined, + ): JsxExpression; updateJsxExpression(node: JsxExpression, expression: Expression | undefined): JsxExpression; createJsxNamespacedName(namespace: Identifier, name: Identifier): JsxNamespacedName; updateJsxNamespacedName(node: JsxNamespacedName, namespace: Identifier, name: Identifier): JsxNamespacedName; @@ -8242,31 +9775,77 @@ declare namespace ts { updateCaseClause(node: CaseClause, expression: Expression, statements: readonly Statement[]): CaseClause; createDefaultClause(statements: readonly Statement[]): DefaultClause; updateDefaultClause(node: DefaultClause, statements: readonly Statement[]): DefaultClause; - createHeritageClause(token: HeritageClause["token"], types: readonly ExpressionWithTypeArguments[]): HeritageClause; + createHeritageClause( + token: HeritageClause["token"], + types: readonly ExpressionWithTypeArguments[], + ): HeritageClause; updateHeritageClause(node: HeritageClause, types: readonly ExpressionWithTypeArguments[]): HeritageClause; - createCatchClause(variableDeclaration: string | BindingName | VariableDeclaration | undefined, block: Block): CatchClause; - updateCatchClause(node: CatchClause, variableDeclaration: VariableDeclaration | undefined, block: Block): CatchClause; + createCatchClause( + variableDeclaration: string | BindingName | VariableDeclaration | undefined, + block: Block, + ): CatchClause; + updateCatchClause( + node: CatchClause, + variableDeclaration: VariableDeclaration | undefined, + block: Block, + ): CatchClause; createPropertyAssignment(name: string | PropertyName, initializer: Expression): PropertyAssignment; - updatePropertyAssignment(node: PropertyAssignment, name: PropertyName, initializer: Expression): PropertyAssignment; - createShorthandPropertyAssignment(name: string | Identifier, objectAssignmentInitializer?: Expression): ShorthandPropertyAssignment; - updateShorthandPropertyAssignment(node: ShorthandPropertyAssignment, name: Identifier, objectAssignmentInitializer: Expression | undefined): ShorthandPropertyAssignment; + updatePropertyAssignment( + node: PropertyAssignment, + name: PropertyName, + initializer: Expression, + ): PropertyAssignment; + createShorthandPropertyAssignment( + name: string | Identifier, + objectAssignmentInitializer?: Expression, + ): ShorthandPropertyAssignment; + updateShorthandPropertyAssignment( + node: ShorthandPropertyAssignment, + name: Identifier, + objectAssignmentInitializer: Expression | undefined, + ): ShorthandPropertyAssignment; createSpreadAssignment(expression: Expression): SpreadAssignment; updateSpreadAssignment(node: SpreadAssignment, expression: Expression): SpreadAssignment; createEnumMember(name: string | PropertyName, initializer?: Expression): EnumMember; updateEnumMember(node: EnumMember, name: PropertyName, initializer: Expression | undefined): EnumMember; - createSourceFile(statements: readonly Statement[], endOfFileToken: EndOfFileToken, flags: NodeFlags): SourceFile; - updateSourceFile(node: SourceFile, statements: readonly Statement[], isDeclarationFile?: boolean, referencedFiles?: readonly FileReference[], typeReferences?: readonly FileReference[], hasNoDefaultLib?: boolean, libReferences?: readonly FileReference[]): SourceFile; + createSourceFile( + statements: readonly Statement[], + endOfFileToken: EndOfFileToken, + flags: NodeFlags, + ): SourceFile; + updateSourceFile( + node: SourceFile, + statements: readonly Statement[], + isDeclarationFile?: boolean, + referencedFiles?: readonly FileReference[], + typeReferences?: readonly FileReference[], + hasNoDefaultLib?: boolean, + libReferences?: readonly FileReference[], + ): SourceFile; createNotEmittedStatement(original: Node): NotEmittedStatement; createPartiallyEmittedExpression(expression: Expression, original?: Node): PartiallyEmittedExpression; - updatePartiallyEmittedExpression(node: PartiallyEmittedExpression, expression: Expression): PartiallyEmittedExpression; + updatePartiallyEmittedExpression( + node: PartiallyEmittedExpression, + expression: Expression, + ): PartiallyEmittedExpression; createCommaListExpression(elements: readonly Expression[]): CommaListExpression; updateCommaListExpression(node: CommaListExpression, elements: readonly Expression[]): CommaListExpression; createBundle(sourceFiles: readonly SourceFile[]): Bundle; - /** @deprecated*/ createBundle(sourceFiles: readonly SourceFile[], prepends?: readonly (UnparsedSource | InputFiles)[]): Bundle; + /** @deprecated*/ createBundle( + sourceFiles: readonly SourceFile[], + prepends?: readonly (UnparsedSource | InputFiles)[], + ): Bundle; updateBundle(node: Bundle, sourceFiles: readonly SourceFile[]): Bundle; - /** @deprecated*/ updateBundle(node: Bundle, sourceFiles: readonly SourceFile[], prepends?: readonly (UnparsedSource | InputFiles)[]): Bundle; + /** @deprecated*/ updateBundle( + node: Bundle, + sourceFiles: readonly SourceFile[], + prepends?: readonly (UnparsedSource | InputFiles)[], + ): Bundle; createComma(left: Expression, right: Expression): BinaryExpression; - createAssignment(left: ObjectLiteralExpression | ArrayLiteralExpression, right: Expression): DestructuringAssignment; + createAssignment( + left: ObjectLiteralExpression | ArrayLiteralExpression, + right: Expression, + ): DestructuringAssignment; createAssignment(left: Expression, right: Expression): AssignmentExpression; createLogicalOr(left: Expression, right: Expression): BinaryExpression; createLogicalAnd(left: Expression, right: Expression): BinaryExpression; @@ -8299,13 +9878,25 @@ declare namespace ts { createPostfixIncrement(operand: Expression): PostfixUnaryExpression; createPostfixDecrement(operand: Expression): PostfixUnaryExpression; createImmediatelyInvokedFunctionExpression(statements: readonly Statement[]): CallExpression; - createImmediatelyInvokedFunctionExpression(statements: readonly Statement[], param: ParameterDeclaration, paramValue: Expression): CallExpression; + createImmediatelyInvokedFunctionExpression( + statements: readonly Statement[], + param: ParameterDeclaration, + paramValue: Expression, + ): CallExpression; createImmediatelyInvokedArrowFunction(statements: readonly Statement[]): ImmediatelyInvokedArrowFunction; - createImmediatelyInvokedArrowFunction(statements: readonly Statement[], param: ParameterDeclaration, paramValue: Expression): ImmediatelyInvokedArrowFunction; + createImmediatelyInvokedArrowFunction( + statements: readonly Statement[], + param: ParameterDeclaration, + paramValue: Expression, + ): ImmediatelyInvokedArrowFunction; createVoidZero(): VoidExpression; createExportDefault(expression: Expression): ExportAssignment; createExternalModuleExport(exportName: Identifier): ExportDeclaration; - restoreOuterExpressions(outerExpression: Expression | undefined, innerExpression: Expression, kinds?: OuterExpressionKinds): Expression; + restoreOuterExpressions( + outerExpression: Expression | undefined, + innerExpression: Expression, + kinds?: OuterExpressionKinds, + ): Expression; } interface CoreTransformationContext { readonly factory: NodeFactory; @@ -8403,7 +9994,9 @@ declare namespace ts { /** * A function that accepts and possibly transforms a node. */ - type Visitor = (node: TIn) => VisitResult; + type Visitor = ( + node: TIn, + ) => VisitResult; /** * A function that walks a node using the given visitor, lifting node arrays into single nodes, * returning an node which satisfies the test. @@ -8417,8 +10010,18 @@ declare namespace ts { * For the canonical implementation of this type, @see {visitNode}. */ interface NodeVisitor { - (node: TIn, visitor: Visitor, TVisited>, test: (node: Node) => node is TOut, lift?: (node: readonly Node[]) => Node): TOut | (TIn & undefined) | (TVisited & undefined); - (node: TIn, visitor: Visitor, TVisited>, test?: (node: Node) => boolean, lift?: (node: readonly Node[]) => Node): Node | (TIn & undefined) | (TVisited & undefined); + ( + node: TIn, + visitor: Visitor, TVisited>, + test: (node: Node) => node is TOut, + lift?: (node: readonly Node[]) => Node, + ): TOut | (TIn & undefined) | (TVisited & undefined); + ( + node: TIn, + visitor: Visitor, TVisited>, + test?: (node: Node) => boolean, + lift?: (node: readonly Node[]) => Node, + ): Node | (TIn & undefined) | (TVisited & undefined); } /** * A function that walks a node array using the given visitor, returning an array whose contents satisfy the test. @@ -8432,8 +10035,20 @@ declare namespace ts { * For the canonical implementation of this type, @see {visitNodes}. */ interface NodesVisitor { - | undefined, TOut extends Node>(nodes: TInArray, visitor: Visitor, test: (node: Node) => node is TOut, start?: number, count?: number): NodeArray | (TInArray & undefined); - | undefined>(nodes: TInArray, visitor: Visitor, test?: (node: Node) => boolean, start?: number, count?: number): NodeArray | (TInArray & undefined); + | undefined, TOut extends Node>( + nodes: TInArray, + visitor: Visitor, + test: (node: Node) => node is TOut, + start?: number, + count?: number, + ): NodeArray | (TInArray & undefined); + | undefined>( + nodes: TInArray, + visitor: Visitor, + test?: (node: Node) => boolean, + start?: number, + count?: number, + ): NodeArray | (TInArray & undefined); } type VisitResult = T | readonly Node[]; interface Printer { @@ -8653,7 +10268,17 @@ declare namespace ts { } type FileWatcherCallback = (fileName: string, eventKind: FileWatcherEventKind, modifiedTime?: Date) => void; type DirectoryWatcherCallback = (fileName: string) => void; - type BufferEncoding = "ascii" | "utf8" | "utf-8" | "utf16le" | "ucs2" | "ucs-2" | "base64" | "latin1" | "binary" | "hex"; + type BufferEncoding = + | "ascii" + | "utf8" + | "utf-8" + | "utf16le" + | "ucs2" + | "ucs-2" + | "base64" + | "latin1" + | "binary" + | "hex"; interface System { args: string[]; newLine: string; @@ -8668,8 +10293,18 @@ declare namespace ts { * @pollingInterval - this parameter is used in polling-based watchers and ignored in watchers that * use native OS file watching */ - watchFile?(path: string, callback: FileWatcherCallback, pollingInterval?: number, options?: WatchOptions): FileWatcher; - watchDirectory?(path: string, callback: DirectoryWatcherCallback, recursive?: boolean, options?: WatchOptions): FileWatcher; + watchFile?( + path: string, + callback: FileWatcherCallback, + pollingInterval?: number, + options?: WatchOptions, + ): FileWatcher; + watchDirectory?( + path: string, + callback: DirectoryWatcherCallback, + recursive?: boolean, + options?: WatchOptions, + ): FileWatcher; resolvePath(path: string): string; fileExists(path: string): boolean; directoryExists(path: string): boolean; @@ -8677,7 +10312,13 @@ declare namespace ts { getExecutingFilePath(): string; getCurrentDirectory(): string; getDirectories(path: string): string[]; - readDirectory(path: string, extensions?: readonly string[], exclude?: readonly string[], include?: readonly string[], depth?: number): string[]; + readDirectory( + path: string, + extensions?: readonly string[], + exclude?: readonly string[], + include?: readonly string[], + depth?: number, + ): string[]; getModifiedTime?(path: string): Date | undefined; setModifiedTime?(path: string, time: Date): void; deleteFile?(path: string): void; @@ -8708,19 +10349,61 @@ declare namespace ts { function isWhiteSpaceSingleLine(ch: number): boolean; function isLineBreak(ch: number): boolean; function couldStartTrivia(text: string, pos: number): boolean; - function forEachLeadingCommentRange(text: string, pos: number, cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean) => U): U | undefined; - function forEachLeadingCommentRange(text: string, pos: number, cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean, state: T) => U, state: T): U | undefined; - function forEachTrailingCommentRange(text: string, pos: number, cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean) => U): U | undefined; - function forEachTrailingCommentRange(text: string, pos: number, cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean, state: T) => U, state: T): U | undefined; - function reduceEachLeadingCommentRange(text: string, pos: number, cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean, state: T) => U, state: T, initial: U): U | undefined; - function reduceEachTrailingCommentRange(text: string, pos: number, cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean, state: T) => U, state: T, initial: U): U | undefined; + function forEachLeadingCommentRange( + text: string, + pos: number, + cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean) => U, + ): U | undefined; + function forEachLeadingCommentRange( + text: string, + pos: number, + cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean, state: T) => U, + state: T, + ): U | undefined; + function forEachTrailingCommentRange( + text: string, + pos: number, + cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean) => U, + ): U | undefined; + function forEachTrailingCommentRange( + text: string, + pos: number, + cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean, state: T) => U, + state: T, + ): U | undefined; + function reduceEachLeadingCommentRange( + text: string, + pos: number, + cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean, state: T) => U, + state: T, + initial: U, + ): U | undefined; + function reduceEachTrailingCommentRange( + text: string, + pos: number, + cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean, state: T) => U, + state: T, + initial: U, + ): U | undefined; function getLeadingCommentRanges(text: string, pos: number): CommentRange[] | undefined; function getTrailingCommentRanges(text: string, pos: number): CommentRange[] | undefined; /** Optionally, get the shebang */ function getShebang(text: string): string | undefined; function isIdentifierStart(ch: number, languageVersion: ScriptTarget | undefined): boolean; - function isIdentifierPart(ch: number, languageVersion: ScriptTarget | undefined, identifierVariant?: LanguageVariant): boolean; - function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean, languageVariant?: LanguageVariant, textInitial?: string, onError?: ErrorCallback, start?: number, length?: number): Scanner; + function isIdentifierPart( + ch: number, + languageVersion: ScriptTarget | undefined, + identifierVariant?: LanguageVariant, + ): boolean; + function createScanner( + languageVersion: ScriptTarget, + skipTrivia: boolean, + languageVariant?: LanguageVariant, + textInitial?: string, + onError?: ErrorCallback, + start?: number, + length?: number, + ): Scanner; type ErrorCallback = (message: DiagnosticMessage, length: number, arg0?: any) => void; interface Scanner { /** @deprecated use {@link getTokenFullStart} */ @@ -8818,14 +10501,20 @@ declare namespace ts { function getOriginalNode(node: Node): Node; function getOriginalNode(node: Node, nodeTest: (node: Node) => node is T): T; function getOriginalNode(node: Node | undefined): Node | undefined; - function getOriginalNode(node: Node | undefined, nodeTest: (node: Node) => node is T): T | undefined; + function getOriginalNode( + node: Node | undefined, + nodeTest: (node: Node) => node is T, + ): T | undefined; /** * Iterates through the parent chain of a node and performs the callback on each parent until the callback * returns a truthy value, then returns that value. * If no such value is found, it applies the callback until the parent pointer is undefined or the callback returns "quit" * At that point findAncestor returns undefined. */ - function findAncestor(node: Node | undefined, callback: (element: Node) => element is T): T | undefined; + function findAncestor( + node: Node | undefined, + callback: (element: Node) => element is T, + ): T | undefined; function findAncestor(node: Node | undefined, callback: (element: Node) => boolean | "quit"): Node | undefined; /** * Gets a value indicating whether a node originated in the parse tree. @@ -8964,7 +10653,9 @@ declare namespace ts { * /** @type {Id} / * function id(x) { return x } */ - function getEffectiveTypeParameterDeclarations(node: DeclarationWithTypeParameters): readonly TypeParameterDeclaration[]; + function getEffectiveTypeParameterDeclarations( + node: DeclarationWithTypeParameters, + ): readonly TypeParameterDeclaration[]; function getEffectiveConstraintOfTypeParameter(node: TypeParameterDeclaration): TypeNode | undefined; function isMemberName(node: Node): node is MemberName; function isPropertyAccessChain(node: Node): node is PropertyAccessChain; @@ -9030,14 +10721,19 @@ declare namespace ts { function isCallOrNewExpression(node: Node): node is CallExpression | NewExpression; function isTemplateLiteral(node: Node): node is TemplateLiteral; function isLeftHandSideExpression(node: Node): node is LeftHandSideExpression; - function isLiteralTypeLiteral(node: Node): node is NullLiteral | BooleanLiteral | LiteralExpression | PrefixUnaryExpression; + function isLiteralTypeLiteral( + node: Node, + ): node is NullLiteral | BooleanLiteral | LiteralExpression | PrefixUnaryExpression; /** * Determines whether a node is an expression based only on its kind. */ function isExpression(node: Node): node is Expression; function isAssertionExpression(node: Node): node is AssertionExpression; function isIterationStatement(node: Node, lookInLabeledStatements: false): node is IterationStatement; - function isIterationStatement(node: Node, lookInLabeledStatements: boolean): node is IterationStatement | LabeledStatement; + function isIterationStatement( + node: Node, + lookInLabeledStatements: boolean, + ): node is IterationStatement | LabeledStatement; function isConciseBody(node: Node): node is ConciseBody; function isForInitializer(node: Node): node is ForInitializer; function isModuleBody(node: Node): node is ModuleBody; @@ -9089,19 +10785,45 @@ declare namespace ts { /** @deprecated */ function createUnparsedSourceFile(text: string): UnparsedSource; /** @deprecated */ - function createUnparsedSourceFile(inputFile: InputFiles, type: "js" | "dts", stripInternal?: boolean): UnparsedSource; + function createUnparsedSourceFile( + inputFile: InputFiles, + type: "js" | "dts", + stripInternal?: boolean, + ): UnparsedSource; /** @deprecated */ - function createUnparsedSourceFile(text: string, mapPath: string | undefined, map: string | undefined): UnparsedSource; + function createUnparsedSourceFile( + text: string, + mapPath: string | undefined, + map: string | undefined, + ): UnparsedSource; /** @deprecated */ function createInputFiles(javascriptText: string, declarationText: string): InputFiles; /** @deprecated */ - function createInputFiles(javascriptText: string, declarationText: string, javascriptMapPath: string | undefined, javascriptMapText: string | undefined, declarationMapPath: string | undefined, declarationMapText: string | undefined): InputFiles; + function createInputFiles( + javascriptText: string, + declarationText: string, + javascriptMapPath: string | undefined, + javascriptMapText: string | undefined, + declarationMapPath: string | undefined, + declarationMapText: string | undefined, + ): InputFiles; /** @deprecated */ - function createInputFiles(readFileText: (path: string) => string | undefined, javascriptPath: string, javascriptMapPath: string | undefined, declarationPath: string, declarationMapPath: string | undefined, buildInfoPath: string | undefined): InputFiles; + function createInputFiles( + readFileText: (path: string) => string | undefined, + javascriptPath: string, + javascriptMapPath: string | undefined, + declarationPath: string, + declarationMapPath: string | undefined, + buildInfoPath: string | undefined, + ): InputFiles; /** * Create an external source map source file reference */ - function createSourceMapSource(fileName: string, text: string, skipTrivia?: (pos: number) => number): SourceMapSource; + function createSourceMapSource( + fileName: string, + text: string, + skipTrivia?: (pos: number) => number, + ): SourceMapSource; function setOriginalNode(node: T, original: Node | undefined): T; const factory: NodeFactory; /** @@ -9139,10 +10861,20 @@ declare namespace ts { function setCommentRange(node: T, range: TextRange): T; function getSyntheticLeadingComments(node: Node): SynthesizedComment[] | undefined; function setSyntheticLeadingComments(node: T, comments: SynthesizedComment[] | undefined): T; - function addSyntheticLeadingComment(node: T, kind: SyntaxKind.SingleLineCommentTrivia | SyntaxKind.MultiLineCommentTrivia, text: string, hasTrailingNewLine?: boolean): T; + function addSyntheticLeadingComment( + node: T, + kind: SyntaxKind.SingleLineCommentTrivia | SyntaxKind.MultiLineCommentTrivia, + text: string, + hasTrailingNewLine?: boolean, + ): T; function getSyntheticTrailingComments(node: Node): SynthesizedComment[] | undefined; function setSyntheticTrailingComments(node: T, comments: SynthesizedComment[] | undefined): T; - function addSyntheticTrailingComment(node: T, kind: SyntaxKind.SingleLineCommentTrivia | SyntaxKind.MultiLineCommentTrivia, text: string, hasTrailingNewLine?: boolean): T; + function addSyntheticTrailingComment( + node: T, + kind: SyntaxKind.SingleLineCommentTrivia | SyntaxKind.MultiLineCommentTrivia, + text: string, + hasTrailingNewLine?: boolean, + ): T; function moveSyntheticComments(node: T, original: Node): T; /** * Gets the constant value to emit for an expression representing an enum. @@ -9407,8 +11139,18 @@ declare namespace ts { * @remarks `forEachChild` must visit the children of a node in the order * that they appear in the source code. The language service depends on this property to locate nodes by position. */ - function forEachChild(node: Node, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined; - function createSourceFile(fileName: string, sourceText: string, languageVersionOrOptions: ScriptTarget | CreateSourceFileOptions, setParentNodes?: boolean, scriptKind?: ScriptKind): SourceFile; + function forEachChild( + node: Node, + cbNode: (node: Node) => T | undefined, + cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined; + function createSourceFile( + fileName: string, + sourceText: string, + languageVersionOrOptions: ScriptTarget | CreateSourceFileOptions, + setParentNodes?: boolean, + scriptKind?: ScriptKind, + ): SourceFile; function parseIsolatedEntityName(text: string, languageVersion: ScriptTarget): EntityName | undefined; /** * Parse json text into SyntaxTree and return node and parse errors if any @@ -9417,7 +11159,12 @@ declare namespace ts { */ function parseJsonText(fileName: string, sourceText: string): JsonSourceFile; function isExternalModule(file: SourceFile): boolean; - function updateSourceFile(sourceFile: SourceFile, newText: string, textChangeRange: TextChangeRange, aggressiveChecks?: boolean): SourceFile; + function updateSourceFile( + sourceFile: SourceFile, + newText: string, + textChangeRange: TextChangeRange, + aggressiveChecks?: boolean, + ): SourceFile; interface CreateSourceFileOptions { languageVersion: ScriptTarget; /** @@ -9433,11 +11180,21 @@ declare namespace ts { */ setExternalModuleIndicator?: (file: SourceFile) => void; } - function parseCommandLine(commandLine: readonly string[], readFile?: (path: string) => string | undefined): ParsedCommandLine; + function parseCommandLine( + commandLine: readonly string[], + readFile?: (path: string) => string | undefined, + ): ParsedCommandLine; /** * Reads the config file, reports errors if any and exits if the config file cannot be found */ - function getParsedCommandLineOfConfigFile(configFileName: string, optionsToExtend: CompilerOptions | undefined, host: ParseConfigFileHost, extendedConfigCache?: Map, watchOptionsToExtend?: WatchOptions, extraFileExtensions?: readonly FileExtensionInfo[]): ParsedCommandLine | undefined; + function getParsedCommandLineOfConfigFile( + configFileName: string, + optionsToExtend: CompilerOptions | undefined, + host: ParseConfigFileHost, + extendedConfigCache?: Map, + watchOptionsToExtend?: WatchOptions, + extraFileExtensions?: readonly FileExtensionInfo[], + ): ParsedCommandLine | undefined; /** * Read tsconfig.json file * @param fileName The path to the config file @@ -9471,7 +11228,17 @@ declare namespace ts { * @param basePath A root directory to resolve relative path entries in the config * file to. e.g. outDir */ - function parseJsonConfigFileContent(json: any, host: ParseConfigHost, basePath: string, existingOptions?: CompilerOptions, configFileName?: string, resolutionStack?: Path[], extraFileExtensions?: readonly FileExtensionInfo[], extendedConfigCache?: Map, existingWatchOptions?: WatchOptions): ParsedCommandLine; + function parseJsonConfigFileContent( + json: any, + host: ParseConfigHost, + basePath: string, + existingOptions?: CompilerOptions, + configFileName?: string, + resolutionStack?: Path[], + extraFileExtensions?: readonly FileExtensionInfo[], + extendedConfigCache?: Map, + existingWatchOptions?: WatchOptions, + ): ParsedCommandLine; /** * Parse the contents of a config file (tsconfig.json). * @param jsonNode The contents of the config file to parse @@ -9479,7 +11246,17 @@ declare namespace ts { * @param basePath A root directory to resolve relative path entries in the config * file to. e.g. outDir */ - function parseJsonSourceFileConfigFileContent(sourceFile: TsConfigSourceFile, host: ParseConfigHost, basePath: string, existingOptions?: CompilerOptions, configFileName?: string, resolutionStack?: Path[], extraFileExtensions?: readonly FileExtensionInfo[], extendedConfigCache?: Map, existingWatchOptions?: WatchOptions): ParsedCommandLine; + function parseJsonSourceFileConfigFileContent( + sourceFile: TsConfigSourceFile, + host: ParseConfigHost, + basePath: string, + existingOptions?: CompilerOptions, + configFileName?: string, + resolutionStack?: Path[], + extraFileExtensions?: readonly FileExtensionInfo[], + extendedConfigCache?: Map, + existingWatchOptions?: WatchOptions, + ): ParsedCommandLine; function convertCompilerOptionsFromJson(jsonOptions: any, basePath: string, configFileName?: string): { options: CompilerOptions; errors: Diagnostic[]; @@ -9524,7 +11301,15 @@ declare namespace ts { * This is possible in case if resolution is performed for directives specified via 'types' parameter. In this case initial path for secondary lookups * is assumed to be the same as root directory of the project. */ - function resolveTypeReferenceDirective(typeReferenceDirectiveName: string, containingFile: string | undefined, options: CompilerOptions, host: ModuleResolutionHost, redirectedReference?: ResolvedProjectReference, cache?: TypeReferenceDirectiveResolutionCache, resolutionMode?: ResolutionMode): ResolvedTypeReferenceDirectiveWithFailedLookupLocations; + function resolveTypeReferenceDirective( + typeReferenceDirectiveName: string, + containingFile: string | undefined, + options: CompilerOptions, + host: ModuleResolutionHost, + redirectedReference?: ResolvedProjectReference, + cache?: TypeReferenceDirectiveResolutionCache, + resolutionMode?: ResolutionMode, + ): ResolvedTypeReferenceDirectiveWithFailedLookupLocations; /** * Given a set of options, returns the set of type directive names * that should be included for this program automatically. @@ -9534,14 +11319,63 @@ declare namespace ts { * this list is only the set of defaults that are implicitly included. */ function getAutomaticTypeDirectiveNames(options: CompilerOptions, host: ModuleResolutionHost): string[]; - function createModuleResolutionCache(currentDirectory: string, getCanonicalFileName: (s: string) => string, options?: CompilerOptions, packageJsonInfoCache?: PackageJsonInfoCache): ModuleResolutionCache; - function createTypeReferenceDirectiveResolutionCache(currentDirectory: string, getCanonicalFileName: (s: string) => string, options?: CompilerOptions, packageJsonInfoCache?: PackageJsonInfoCache): TypeReferenceDirectiveResolutionCache; - function resolveModuleNameFromCache(moduleName: string, containingFile: string, cache: ModuleResolutionCache, mode?: ResolutionMode): ResolvedModuleWithFailedLookupLocations | undefined; - function resolveModuleName(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache?: ModuleResolutionCache, redirectedReference?: ResolvedProjectReference, resolutionMode?: ResolutionMode): ResolvedModuleWithFailedLookupLocations; - function bundlerModuleNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache?: ModuleResolutionCache, redirectedReference?: ResolvedProjectReference): ResolvedModuleWithFailedLookupLocations; - function nodeModuleNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache?: ModuleResolutionCache, redirectedReference?: ResolvedProjectReference): ResolvedModuleWithFailedLookupLocations; - function classicNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache?: NonRelativeModuleNameResolutionCache, redirectedReference?: ResolvedProjectReference): ResolvedModuleWithFailedLookupLocations; - interface TypeReferenceDirectiveResolutionCache extends PerDirectoryResolutionCache, NonRelativeNameResolutionCache, PackageJsonInfoCache { + function createModuleResolutionCache( + currentDirectory: string, + getCanonicalFileName: (s: string) => string, + options?: CompilerOptions, + packageJsonInfoCache?: PackageJsonInfoCache, + ): ModuleResolutionCache; + function createTypeReferenceDirectiveResolutionCache( + currentDirectory: string, + getCanonicalFileName: (s: string) => string, + options?: CompilerOptions, + packageJsonInfoCache?: PackageJsonInfoCache, + ): TypeReferenceDirectiveResolutionCache; + function resolveModuleNameFromCache( + moduleName: string, + containingFile: string, + cache: ModuleResolutionCache, + mode?: ResolutionMode, + ): ResolvedModuleWithFailedLookupLocations | undefined; + function resolveModuleName( + moduleName: string, + containingFile: string, + compilerOptions: CompilerOptions, + host: ModuleResolutionHost, + cache?: ModuleResolutionCache, + redirectedReference?: ResolvedProjectReference, + resolutionMode?: ResolutionMode, + ): ResolvedModuleWithFailedLookupLocations; + function bundlerModuleNameResolver( + moduleName: string, + containingFile: string, + compilerOptions: CompilerOptions, + host: ModuleResolutionHost, + cache?: ModuleResolutionCache, + redirectedReference?: ResolvedProjectReference, + ): ResolvedModuleWithFailedLookupLocations; + function nodeModuleNameResolver( + moduleName: string, + containingFile: string, + compilerOptions: CompilerOptions, + host: ModuleResolutionHost, + cache?: ModuleResolutionCache, + redirectedReference?: ResolvedProjectReference, + ): ResolvedModuleWithFailedLookupLocations; + function classicNameResolver( + moduleName: string, + containingFile: string, + compilerOptions: CompilerOptions, + host: ModuleResolutionHost, + cache?: NonRelativeModuleNameResolutionCache, + redirectedReference?: ResolvedProjectReference, + ): ResolvedModuleWithFailedLookupLocations; + interface TypeReferenceDirectiveResolutionCache + extends + PerDirectoryResolutionCache, + NonRelativeNameResolutionCache, + PackageJsonInfoCache + { } interface ModeAwareCache { get(key: string, mode: ResolutionMode): T | undefined; @@ -9556,8 +11390,16 @@ declare namespace ts { * This assumes that any module id will have the same resolution for sibling files located in the same folder. */ interface PerDirectoryResolutionCache { - getFromDirectoryCache(name: string, mode: ResolutionMode, directoryName: string, redirectedReference: ResolvedProjectReference | undefined): T | undefined; - getOrCreateCacheForDirectory(directoryName: string, redirectedReference?: ResolvedProjectReference): ModeAwareCache; + getFromDirectoryCache( + name: string, + mode: ResolutionMode, + directoryName: string, + redirectedReference: ResolvedProjectReference | undefined, + ): T | undefined; + getOrCreateCacheForDirectory( + directoryName: string, + redirectedReference?: ResolvedProjectReference, + ): ModeAwareCache; clear(): void; /** * Updates with the current compilerOptions the cache will operate with. @@ -9566,8 +11408,17 @@ declare namespace ts { update(options: CompilerOptions): void; } interface NonRelativeNameResolutionCache { - getFromNonRelativeNameCache(nonRelativeName: string, mode: ResolutionMode, directoryName: string, redirectedReference: ResolvedProjectReference | undefined): T | undefined; - getOrCreateCacheForNonRelativeName(nonRelativeName: string, mode: ResolutionMode, redirectedReference?: ResolvedProjectReference): PerNonRelativeNameCache; + getFromNonRelativeNameCache( + nonRelativeName: string, + mode: ResolutionMode, + directoryName: string, + redirectedReference: ResolvedProjectReference | undefined, + ): T | undefined; + getOrCreateCacheForNonRelativeName( + nonRelativeName: string, + mode: ResolutionMode, + redirectedReference?: ResolvedProjectReference, + ): PerNonRelativeNameCache; clear(): void; /** * Updates with the current compilerOptions the cache will operate with. @@ -9579,16 +11430,27 @@ declare namespace ts { get(directory: string): T | undefined; set(directory: string, result: T): void; } - interface ModuleResolutionCache extends PerDirectoryResolutionCache, NonRelativeModuleNameResolutionCache, PackageJsonInfoCache { + interface ModuleResolutionCache + extends + PerDirectoryResolutionCache, + NonRelativeModuleNameResolutionCache, + PackageJsonInfoCache + { getPackageJsonInfoCache(): PackageJsonInfoCache; } /** * Stored map from non-relative module name to a table: directory -> result of module lookup in this directory * We support only non-relative module names because resolution of relative module names is usually more deterministic and thus less expensive. */ - interface NonRelativeModuleNameResolutionCache extends NonRelativeNameResolutionCache, PackageJsonInfoCache { + interface NonRelativeModuleNameResolutionCache + extends NonRelativeNameResolutionCache, PackageJsonInfoCache + { /** @deprecated Use getOrCreateCacheForNonRelativeName */ - getOrCreateCacheForModuleName(nonRelativeModuleName: string, mode: ResolutionMode, redirectedReference?: ResolvedProjectReference): PerModuleNameCache; + getOrCreateCacheForModuleName( + nonRelativeModuleName: string, + mode: ResolutionMode, + redirectedReference?: ResolvedProjectReference, + ): PerModuleNameCache; } interface PackageJsonInfoCache { clear(): void; @@ -9608,7 +11470,12 @@ declare namespace ts { * @param test A callback to execute to verify the Node is valid. * @param lift An optional callback to execute to lift a NodeArray into a valid Node. */ - function visitNode(node: TIn, visitor: Visitor, TVisited>, test: (node: Node) => node is TOut, lift?: (node: readonly Node[]) => Node): TOut | (TIn & undefined) | (TVisited & undefined); + function visitNode( + node: TIn, + visitor: Visitor, TVisited>, + test: (node: Node) => node is TOut, + lift?: (node: readonly Node[]) => Node, + ): TOut | (TIn & undefined) | (TVisited & undefined); /** * Visits a Node using the supplied visitor, possibly returning a new Node in its place. * @@ -9623,7 +11490,12 @@ declare namespace ts { * @param test A callback to execute to verify the Node is valid. * @param lift An optional callback to execute to lift a NodeArray into a valid Node. */ - function visitNode(node: TIn, visitor: Visitor, TVisited>, test?: (node: Node) => boolean, lift?: (node: readonly Node[]) => Node): Node | (TIn & undefined) | (TVisited & undefined); + function visitNode( + node: TIn, + visitor: Visitor, TVisited>, + test?: (node: Node) => boolean, + lift?: (node: readonly Node[]) => Node, + ): Node | (TIn & undefined) | (TVisited & undefined); /** * Visits a NodeArray using the supplied visitor, possibly returning a new NodeArray in its place. * @@ -9639,7 +11511,13 @@ declare namespace ts { * @param start An optional value indicating the starting offset at which to start visiting. * @param count An optional value indicating the maximum number of nodes to visit. */ - function visitNodes | undefined, TOut extends Node>(nodes: TInArray, visitor: Visitor, test: (node: Node) => node is TOut, start?: number, count?: number): NodeArray | (TInArray & undefined); + function visitNodes | undefined, TOut extends Node>( + nodes: TInArray, + visitor: Visitor, + test: (node: Node) => node is TOut, + start?: number, + count?: number, + ): NodeArray | (TInArray & undefined); /** * Visits a NodeArray using the supplied visitor, possibly returning a new NodeArray in its place. * @@ -9655,18 +11533,41 @@ declare namespace ts { * @param start An optional value indicating the starting offset at which to start visiting. * @param count An optional value indicating the maximum number of nodes to visit. */ - function visitNodes | undefined>(nodes: TInArray, visitor: Visitor, test?: (node: Node) => boolean, start?: number, count?: number): NodeArray | (TInArray & undefined); + function visitNodes | undefined>( + nodes: TInArray, + visitor: Visitor, + test?: (node: Node) => boolean, + start?: number, + count?: number, + ): NodeArray | (TInArray & undefined); /** * Starts a new lexical environment and visits a statement list, ending the lexical environment * and merging hoisted declarations upon completion. */ - function visitLexicalEnvironment(statements: NodeArray, visitor: Visitor, context: TransformationContext, start?: number, ensureUseStrict?: boolean, nodesVisitor?: NodesVisitor): NodeArray; + function visitLexicalEnvironment( + statements: NodeArray, + visitor: Visitor, + context: TransformationContext, + start?: number, + ensureUseStrict?: boolean, + nodesVisitor?: NodesVisitor, + ): NodeArray; /** * Starts a new lexical environment and visits a parameter list, suspending the lexical * environment upon completion. */ - function visitParameterList(nodes: NodeArray, visitor: Visitor, context: TransformationContext, nodesVisitor?: NodesVisitor): NodeArray; - function visitParameterList(nodes: NodeArray | undefined, visitor: Visitor, context: TransformationContext, nodesVisitor?: NodesVisitor): NodeArray | undefined; + function visitParameterList( + nodes: NodeArray, + visitor: Visitor, + context: TransformationContext, + nodesVisitor?: NodesVisitor, + ): NodeArray; + function visitParameterList( + nodes: NodeArray | undefined, + visitor: Visitor, + context: TransformationContext, + nodesVisitor?: NodesVisitor, + ): NodeArray | undefined; /** * Resumes a suspended lexical environment and visits a function body, ending the lexical * environment and merging hoisted declarations upon completion. @@ -9676,7 +11577,11 @@ declare namespace ts { * Resumes a suspended lexical environment and visits a function body, ending the lexical * environment and merging hoisted declarations upon completion. */ - function visitFunctionBody(node: FunctionBody | undefined, visitor: Visitor, context: TransformationContext): FunctionBody | undefined; + function visitFunctionBody( + node: FunctionBody | undefined, + visitor: Visitor, + context: TransformationContext, + ): FunctionBody | undefined; /** * Resumes a suspended lexical environment and visits a concise body, ending the lexical * environment and merging hoisted declarations upon completion. @@ -9691,7 +11596,11 @@ declare namespace ts { * @param visitor The visitor to use when visiting expressions whose result will not be discarded at runtime. * @param discardVisitor The visitor to use when visiting expressions whose result will be discarded at runtime. Defaults to {@link visitor}. */ - function visitCommaListElements(elements: NodeArray, visitor: Visitor, discardVisitor?: Visitor): NodeArray; + function visitCommaListElements( + elements: NodeArray, + visitor: Visitor, + discardVisitor?: Visitor, + ): NodeArray; /** * Visits each child of a Node using the supplied visitor, possibly returning a new Node of the same kind in its place. * @@ -9707,18 +11616,43 @@ declare namespace ts { * @param visitor The callback used to visit each child. * @param context A lexical environment context for the visitor. */ - function visitEachChild(node: T | undefined, visitor: Visitor, context: TransformationContext, nodesVisitor?: typeof visitNodes, tokenVisitor?: Visitor): T | undefined; + function visitEachChild( + node: T | undefined, + visitor: Visitor, + context: TransformationContext, + nodesVisitor?: typeof visitNodes, + tokenVisitor?: Visitor, + ): T | undefined; function getTsBuildInfoEmitOutputFilePath(options: CompilerOptions): string | undefined; - function getOutputFileNames(commandLine: ParsedCommandLine, inputFileName: string, ignoreCase: boolean): readonly string[]; + function getOutputFileNames( + commandLine: ParsedCommandLine, + inputFileName: string, + ignoreCase: boolean, + ): readonly string[]; function createPrinter(printerOptions?: PrinterOptions, handlers?: PrintHandlers): Printer; - function findConfigFile(searchPath: string, fileExists: (fileName: string) => boolean, configName?: string): string | undefined; + function findConfigFile( + searchPath: string, + fileExists: (fileName: string) => boolean, + configName?: string, + ): string | undefined; function resolveTripleslashReference(moduleName: string, containingFile: string): string; function createCompilerHost(options: CompilerOptions, setParentNodes?: boolean): CompilerHost; - function getPreEmitDiagnostics(program: Program, sourceFile?: SourceFile, cancellationToken?: CancellationToken): readonly Diagnostic[]; + function getPreEmitDiagnostics( + program: Program, + sourceFile?: SourceFile, + cancellationToken?: CancellationToken, + ): readonly Diagnostic[]; function formatDiagnostics(diagnostics: readonly Diagnostic[], host: FormatDiagnosticsHost): string; function formatDiagnostic(diagnostic: Diagnostic, host: FormatDiagnosticsHost): string; - function formatDiagnosticsWithColorAndContext(diagnostics: readonly Diagnostic[], host: FormatDiagnosticsHost): string; - function flattenDiagnosticMessageText(diag: string | DiagnosticMessageChain | undefined, newLine: string, indent?: number): string; + function formatDiagnosticsWithColorAndContext( + diagnostics: readonly Diagnostic[], + host: FormatDiagnosticsHost, + ): string; + function flattenDiagnosticMessageText( + diag: string | DiagnosticMessageChain | undefined, + newLine: string, + indent?: number, + ): string; /** * Calculates the resulting resolution mode for some reference in some file - this is generally the explicitly * provided resolution mode in the reference, unless one is not present, in which case it is the mode of the containing file. @@ -9755,7 +11689,12 @@ declare namespace ts { * @param options The compiler options to perform the analysis under - relevant options are `moduleResolution` and `traceResolution` * @returns `undefined` if the path has no relevant implied format, `ModuleKind.ESNext` for esm format, and `ModuleKind.CommonJS` for cjs format */ - function getImpliedNodeFormatForFile(fileName: Path, packageJsonInfoCache: PackageJsonInfoCache | undefined, host: ModuleResolutionHost, options: CompilerOptions): ResolutionMode; + function getImpliedNodeFormatForFile( + fileName: Path, + packageJsonInfoCache: PackageJsonInfoCache | undefined, + host: ModuleResolutionHost, + options: CompilerOptions, + ): ResolutionMode; /** * Create a new 'Program' instance. A Program is an immutable collection of 'SourceFile's and a 'CompilerOptions' * that represent a compilation unit. @@ -9781,7 +11720,13 @@ declare namespace ts { * @param configFileParsingDiagnostics - error during config file parsing * @returns A 'Program' object. */ - function createProgram(rootNames: readonly string[], options: CompilerOptions, host?: CompilerHost, oldProgram?: Program, configFileParsingDiagnostics?: readonly Diagnostic[]): Program; + function createProgram( + rootNames: readonly string[], + options: CompilerOptions, + host?: CompilerHost, + oldProgram?: Program, + configFileParsingDiagnostics?: readonly Diagnostic[], + ): Program; /** * Returns the target config filename of a project reference. * Note: The file might not exist. @@ -9804,19 +11749,55 @@ declare namespace ts { /** * Create the builder to manage semantic diagnostics and cache them */ - function createSemanticDiagnosticsBuilderProgram(newProgram: Program, host: BuilderProgramHost, oldProgram?: SemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: readonly Diagnostic[]): SemanticDiagnosticsBuilderProgram; - function createSemanticDiagnosticsBuilderProgram(rootNames: readonly string[] | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: SemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: readonly Diagnostic[], projectReferences?: readonly ProjectReference[]): SemanticDiagnosticsBuilderProgram; + function createSemanticDiagnosticsBuilderProgram( + newProgram: Program, + host: BuilderProgramHost, + oldProgram?: SemanticDiagnosticsBuilderProgram, + configFileParsingDiagnostics?: readonly Diagnostic[], + ): SemanticDiagnosticsBuilderProgram; + function createSemanticDiagnosticsBuilderProgram( + rootNames: readonly string[] | undefined, + options: CompilerOptions | undefined, + host?: CompilerHost, + oldProgram?: SemanticDiagnosticsBuilderProgram, + configFileParsingDiagnostics?: readonly Diagnostic[], + projectReferences?: readonly ProjectReference[], + ): SemanticDiagnosticsBuilderProgram; /** * Create the builder that can handle the changes in program and iterate through changed files * to emit the those files and manage semantic diagnostics cache as well */ - function createEmitAndSemanticDiagnosticsBuilderProgram(newProgram: Program, host: BuilderProgramHost, oldProgram?: EmitAndSemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: readonly Diagnostic[]): EmitAndSemanticDiagnosticsBuilderProgram; - function createEmitAndSemanticDiagnosticsBuilderProgram(rootNames: readonly string[] | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: EmitAndSemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: readonly Diagnostic[], projectReferences?: readonly ProjectReference[]): EmitAndSemanticDiagnosticsBuilderProgram; + function createEmitAndSemanticDiagnosticsBuilderProgram( + newProgram: Program, + host: BuilderProgramHost, + oldProgram?: EmitAndSemanticDiagnosticsBuilderProgram, + configFileParsingDiagnostics?: readonly Diagnostic[], + ): EmitAndSemanticDiagnosticsBuilderProgram; + function createEmitAndSemanticDiagnosticsBuilderProgram( + rootNames: readonly string[] | undefined, + options: CompilerOptions | undefined, + host?: CompilerHost, + oldProgram?: EmitAndSemanticDiagnosticsBuilderProgram, + configFileParsingDiagnostics?: readonly Diagnostic[], + projectReferences?: readonly ProjectReference[], + ): EmitAndSemanticDiagnosticsBuilderProgram; /** * Creates a builder thats just abstraction over program and can be used with watch */ - function createAbstractBuilder(newProgram: Program, host: BuilderProgramHost, oldProgram?: BuilderProgram, configFileParsingDiagnostics?: readonly Diagnostic[]): BuilderProgram; - function createAbstractBuilder(rootNames: readonly string[] | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: BuilderProgram, configFileParsingDiagnostics?: readonly Diagnostic[], projectReferences?: readonly ProjectReference[]): BuilderProgram; + function createAbstractBuilder( + newProgram: Program, + host: BuilderProgramHost, + oldProgram?: BuilderProgram, + configFileParsingDiagnostics?: readonly Diagnostic[], + ): BuilderProgram; + function createAbstractBuilder( + rootNames: readonly string[] | undefined, + options: CompilerOptions | undefined, + host?: CompilerHost, + oldProgram?: BuilderProgram, + configFileParsingDiagnostics?: readonly Diagnostic[], + projectReferences?: readonly ProjectReference[], + ): BuilderProgram; type AffectedFileResult = { result: T; affected: SourceFile | Program; @@ -9871,7 +11852,10 @@ declare namespace ts { /** * Get the declaration diagnostics, for all source files if source file is not supplied */ - getDeclarationDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): readonly DiagnosticWithLocation[]; + getDeclarationDiagnostics( + sourceFile?: SourceFile, + cancellationToken?: CancellationToken, + ): readonly DiagnosticWithLocation[]; /** * Get all the dependencies of the file */ @@ -9896,7 +11880,13 @@ declare namespace ts { * The first of writeFile if provided, writeFile of BuilderProgramHost if provided, writeFile of compiler host * in that order would be used to write the files */ - emit(targetSourceFile?: SourceFile, writeFile?: WriteFileCallback, cancellationToken?: CancellationToken, emitOnlyDtsFiles?: boolean, customTransformers?: CustomTransformers): EmitResult; + emit( + targetSourceFile?: SourceFile, + writeFile?: WriteFileCallback, + cancellationToken?: CancellationToken, + emitOnlyDtsFiles?: boolean, + customTransformers?: CustomTransformers, + ): EmitResult; /** * Get the current directory of the program */ @@ -9910,7 +11900,10 @@ declare namespace ts { * Gets the semantic diagnostics from the program for the next affected file and caches it * Returns undefined if the iteration is complete */ - getSemanticDiagnosticsOfNextAffectedFile(cancellationToken?: CancellationToken, ignoreSourceFile?: (sourceFile: SourceFile) => boolean): AffectedFileResult; + getSemanticDiagnosticsOfNextAffectedFile( + cancellationToken?: CancellationToken, + ignoreSourceFile?: (sourceFile: SourceFile) => boolean, + ): AffectedFileResult; } /** * The builder that can handle the changes in program and iterate through changed file to emit the files @@ -9922,20 +11915,51 @@ declare namespace ts { * The first of writeFile if provided, writeFile of BuilderProgramHost if provided, writeFile of compiler host * in that order would be used to write the files */ - emitNextAffectedFile(writeFile?: WriteFileCallback, cancellationToken?: CancellationToken, emitOnlyDtsFiles?: boolean, customTransformers?: CustomTransformers): AffectedFileResult; - } - function readBuilderProgram(compilerOptions: CompilerOptions, host: ReadBuildProgramHost): EmitAndSemanticDiagnosticsBuilderProgram | undefined; + emitNextAffectedFile( + writeFile?: WriteFileCallback, + cancellationToken?: CancellationToken, + emitOnlyDtsFiles?: boolean, + customTransformers?: CustomTransformers, + ): AffectedFileResult; + } + function readBuilderProgram( + compilerOptions: CompilerOptions, + host: ReadBuildProgramHost, + ): EmitAndSemanticDiagnosticsBuilderProgram | undefined; function createIncrementalCompilerHost(options: CompilerOptions, system?: System): CompilerHost; - function createIncrementalProgram({ rootNames, options, configFileParsingDiagnostics, projectReferences, host, createProgram }: IncrementalProgramOptions): T; + function createIncrementalProgram( + { rootNames, options, configFileParsingDiagnostics, projectReferences, host, createProgram }: + IncrementalProgramOptions, + ): T; /** * Create the watch compiler host for either configFile or fileNames and its options */ - function createWatchCompilerHost(configFileName: string, optionsToExtend: CompilerOptions | undefined, system: System, createProgram?: CreateProgram, reportDiagnostic?: DiagnosticReporter, reportWatchStatus?: WatchStatusReporter, watchOptionsToExtend?: WatchOptions, extraFileExtensions?: readonly FileExtensionInfo[]): WatchCompilerHostOfConfigFile; - function createWatchCompilerHost(rootFiles: string[], options: CompilerOptions, system: System, createProgram?: CreateProgram, reportDiagnostic?: DiagnosticReporter, reportWatchStatus?: WatchStatusReporter, projectReferences?: readonly ProjectReference[], watchOptions?: WatchOptions): WatchCompilerHostOfFilesAndCompilerOptions; + function createWatchCompilerHost( + configFileName: string, + optionsToExtend: CompilerOptions | undefined, + system: System, + createProgram?: CreateProgram, + reportDiagnostic?: DiagnosticReporter, + reportWatchStatus?: WatchStatusReporter, + watchOptionsToExtend?: WatchOptions, + extraFileExtensions?: readonly FileExtensionInfo[], + ): WatchCompilerHostOfConfigFile; + function createWatchCompilerHost( + rootFiles: string[], + options: CompilerOptions, + system: System, + createProgram?: CreateProgram, + reportDiagnostic?: DiagnosticReporter, + reportWatchStatus?: WatchStatusReporter, + projectReferences?: readonly ProjectReference[], + watchOptions?: WatchOptions, + ): WatchCompilerHostOfFilesAndCompilerOptions; /** * Creates the watch from the host for root files and compiler options */ - function createWatchProgram(host: WatchCompilerHostOfFilesAndCompilerOptions): WatchOfFilesAndCompilerOptions; + function createWatchProgram( + host: WatchCompilerHostOfFilesAndCompilerOptions, + ): WatchOfFilesAndCompilerOptions; /** * Creates the watch from the host for config file */ @@ -9953,17 +11977,44 @@ declare namespace ts { host?: CompilerHost; createProgram?: CreateProgram; } - type WatchStatusReporter = (diagnostic: Diagnostic, newLine: string, options: CompilerOptions, errorCount?: number) => void; + type WatchStatusReporter = ( + diagnostic: Diagnostic, + newLine: string, + options: CompilerOptions, + errorCount?: number, + ) => void; /** Create the program with rootNames and options, if they are undefined, oldProgram and new configFile diagnostics create new program */ - type CreateProgram = (rootNames: readonly string[] | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: T, configFileParsingDiagnostics?: readonly Diagnostic[], projectReferences?: readonly ProjectReference[] | undefined) => T; + type CreateProgram = ( + rootNames: readonly string[] | undefined, + options: CompilerOptions | undefined, + host?: CompilerHost, + oldProgram?: T, + configFileParsingDiagnostics?: readonly Diagnostic[], + projectReferences?: readonly ProjectReference[] | undefined, + ) => T; /** Host that has watch functionality used in --watch mode */ interface WatchHost { /** If provided, called with Diagnostic message that informs about change in watch status */ - onWatchStatusChange?(diagnostic: Diagnostic, newLine: string, options: CompilerOptions, errorCount?: number): void; + onWatchStatusChange?( + diagnostic: Diagnostic, + newLine: string, + options: CompilerOptions, + errorCount?: number, + ): void; /** Used to watch changes in source files, missing files needed to update the program or config file */ - watchFile(path: string, callback: FileWatcherCallback, pollingInterval?: number, options?: WatchOptions): FileWatcher; + watchFile( + path: string, + callback: FileWatcherCallback, + pollingInterval?: number, + options?: WatchOptions, + ): FileWatcher; /** Used to watch resolved module's failed lookup locations, config file specs, type roots where auto type reference directives are added */ - watchDirectory(path: string, callback: DirectoryWatcherCallback, recursive?: boolean, options?: WatchOptions): FileWatcher; + watchDirectory( + path: string, + callback: DirectoryWatcherCallback, + recursive?: boolean, + options?: WatchOptions, + ): FileWatcher; /** If provided, will be used to set delayed compilation, so that multiple changes in short span are compiled together */ setTimeout?(callback: (...args: any[]) => void, ms: number, ...args: any[]): any; /** If provided, will be used to reset existing delayed compilation */ @@ -9995,7 +12046,13 @@ declare namespace ts { /** If provided, used in resolutions as well as handling directory structure */ getDirectories?(path: string): string[]; /** If provided, used to cache and handle directory structure modifications */ - readDirectory?(path: string, extensions?: readonly string[], exclude?: readonly string[], include?: readonly string[], depth?: number): string[]; + readDirectory?( + path: string, + extensions?: readonly string[], + exclude?: readonly string[], + include?: readonly string[], + depth?: number, + ): string[]; /** Symbol links resolution */ realpath?(path: string): string; /** If provided would be used to write log about compilation */ @@ -10007,15 +12064,42 @@ declare namespace ts { * * If provided, used to resolve the module names, otherwise typescript's default module resolution */ - resolveModuleNames?(moduleNames: string[], containingFile: string, reusedNames: string[] | undefined, redirectedReference: ResolvedProjectReference | undefined, options: CompilerOptions, containingSourceFile?: SourceFile): (ResolvedModule | undefined)[]; + resolveModuleNames?( + moduleNames: string[], + containingFile: string, + reusedNames: string[] | undefined, + redirectedReference: ResolvedProjectReference | undefined, + options: CompilerOptions, + containingSourceFile?: SourceFile, + ): (ResolvedModule | undefined)[]; /** * @deprecated supply resolveTypeReferenceDirectiveReferences instead for resolution that can handle newer resolution modes like nodenext * * If provided, used to resolve type reference directives, otherwise typescript's default resolution */ - resolveTypeReferenceDirectives?(typeReferenceDirectiveNames: string[] | readonly FileReference[], containingFile: string, redirectedReference: ResolvedProjectReference | undefined, options: CompilerOptions, containingFileMode?: ResolutionMode): (ResolvedTypeReferenceDirective | undefined)[]; - resolveModuleNameLiterals?(moduleLiterals: readonly StringLiteralLike[], containingFile: string, redirectedReference: ResolvedProjectReference | undefined, options: CompilerOptions, containingSourceFile: SourceFile, reusedNames: readonly StringLiteralLike[] | undefined): readonly ResolvedModuleWithFailedLookupLocations[]; - resolveTypeReferenceDirectiveReferences?(typeDirectiveReferences: readonly T[], containingFile: string, redirectedReference: ResolvedProjectReference | undefined, options: CompilerOptions, containingSourceFile: SourceFile | undefined, reusedNames: readonly T[] | undefined): readonly ResolvedTypeReferenceDirectiveWithFailedLookupLocations[]; + resolveTypeReferenceDirectives?( + typeReferenceDirectiveNames: string[] | readonly FileReference[], + containingFile: string, + redirectedReference: ResolvedProjectReference | undefined, + options: CompilerOptions, + containingFileMode?: ResolutionMode, + ): (ResolvedTypeReferenceDirective | undefined)[]; + resolveModuleNameLiterals?( + moduleLiterals: readonly StringLiteralLike[], + containingFile: string, + redirectedReference: ResolvedProjectReference | undefined, + options: CompilerOptions, + containingSourceFile: SourceFile, + reusedNames: readonly StringLiteralLike[] | undefined, + ): readonly ResolvedModuleWithFailedLookupLocations[]; + resolveTypeReferenceDirectiveReferences?( + typeDirectiveReferences: readonly T[], + containingFile: string, + redirectedReference: ResolvedProjectReference | undefined, + options: CompilerOptions, + containingSourceFile: SourceFile | undefined, + reusedNames: readonly T[] | undefined, + ): readonly ResolvedTypeReferenceDirectiveWithFailedLookupLocations[]; /** If provided along with custom resolveModuleNames or resolveTypeReferenceDirectives, used to determine if unchanged file path needs to re-resolve modules/type reference directives */ hasInvalidatedResolutions?(filePath: Path): boolean; /** @@ -10046,7 +12130,9 @@ declare namespace ts { /** * Host to create watch with config file */ - interface WatchCompilerHostOfConfigFile extends WatchCompilerHost, ConfigFileDiagnosticsReporter { + interface WatchCompilerHostOfConfigFile + extends WatchCompilerHost, ConfigFileDiagnosticsReporter + { /** Name of the config file to compile */ configFileName: string; /** Options to extend */ @@ -10057,7 +12143,13 @@ declare namespace ts { * Used to generate source file names from the config file and its include, exclude, files rules * and also to cache the directory stucture */ - readDirectory(path: string, extensions?: readonly string[], exclude?: readonly string[], include?: readonly string[], depth?: number): string[]; + readDirectory( + path: string, + extensions?: readonly string[], + exclude?: readonly string[], + include?: readonly string[], + depth?: number, + ): string[]; } interface Watch { /** Synchronize with host and get updated program */ @@ -10081,10 +12173,31 @@ declare namespace ts { * Create a function that reports watch status by writing to the system and handles the formating of the diagnostic */ function createBuilderStatusReporter(system: System, pretty?: boolean): DiagnosticReporter; - function createSolutionBuilderHost(system?: System, createProgram?: CreateProgram, reportDiagnostic?: DiagnosticReporter, reportSolutionBuilderStatus?: DiagnosticReporter, reportErrorSummary?: ReportEmitErrorSummary): SolutionBuilderHost; - function createSolutionBuilderWithWatchHost(system?: System, createProgram?: CreateProgram, reportDiagnostic?: DiagnosticReporter, reportSolutionBuilderStatus?: DiagnosticReporter, reportWatchStatus?: WatchStatusReporter): SolutionBuilderWithWatchHost; - function createSolutionBuilder(host: SolutionBuilderHost, rootNames: readonly string[], defaultOptions: BuildOptions): SolutionBuilder; - function createSolutionBuilderWithWatch(host: SolutionBuilderWithWatchHost, rootNames: readonly string[], defaultOptions: BuildOptions, baseWatchOptions?: WatchOptions): SolutionBuilder; + function createSolutionBuilderHost( + system?: System, + createProgram?: CreateProgram, + reportDiagnostic?: DiagnosticReporter, + reportSolutionBuilderStatus?: DiagnosticReporter, + reportErrorSummary?: ReportEmitErrorSummary, + ): SolutionBuilderHost; + function createSolutionBuilderWithWatchHost( + system?: System, + createProgram?: CreateProgram, + reportDiagnostic?: DiagnosticReporter, + reportSolutionBuilderStatus?: DiagnosticReporter, + reportWatchStatus?: WatchStatusReporter, + ): SolutionBuilderWithWatchHost; + function createSolutionBuilder( + host: SolutionBuilderHost, + rootNames: readonly string[], + defaultOptions: BuildOptions, + ): SolutionBuilder; + function createSolutionBuilderWithWatch( + host: SolutionBuilderWithWatchHost, + rootNames: readonly string[], + defaultOptions: BuildOptions, + baseWatchOptions?: WatchOptions, + ): SolutionBuilder; interface BuildOptions { dry?: boolean; force?: boolean; @@ -10126,9 +12239,19 @@ declare namespace ts { interface SolutionBuilderWithWatchHost extends SolutionBuilderHostBase, WatchHost { } interface SolutionBuilder { - build(project?: string, cancellationToken?: CancellationToken, writeFile?: WriteFileCallback, getCustomTransformers?: (project: string) => CustomTransformers): ExitStatus; + build( + project?: string, + cancellationToken?: CancellationToken, + writeFile?: WriteFileCallback, + getCustomTransformers?: (project: string) => CustomTransformers, + ): ExitStatus; clean(project?: string): ExitStatus; - buildReferences(project: string, cancellationToken?: CancellationToken, writeFile?: WriteFileCallback, getCustomTransformers?: (project: string) => CustomTransformers): ExitStatus; + buildReferences( + project: string, + cancellationToken?: CancellationToken, + writeFile?: WriteFileCallback, + getCustomTransformers?: (project: string) => CustomTransformers, + ): ExitStatus; cleanReferences(project?: string): ExitStatus; getNextInvalidatedProject(cancellationToken?: CancellationToken): InvalidatedProject | undefined; } @@ -10143,7 +12266,11 @@ declare namespace ts { /** * To dispose this project and ensure that all the necessary actions are taken and state is updated accordingly */ - done(cancellationToken?: CancellationToken, writeFile?: WriteFileCallback, customTransformers?: CustomTransformers): ExitStatus; + done( + cancellationToken?: CancellationToken, + writeFile?: WriteFileCallback, + customTransformers?: CustomTransformers, + ): ExitStatus; getCompilerOptions(): CompilerOptions; getCurrentDirectory(): string; } @@ -10163,21 +12290,42 @@ declare namespace ts { getSyntacticDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): readonly Diagnostic[]; getAllDependencies(sourceFile: SourceFile): readonly string[]; getSemanticDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): readonly Diagnostic[]; - getSemanticDiagnosticsOfNextAffectedFile(cancellationToken?: CancellationToken, ignoreSourceFile?: (sourceFile: SourceFile) => boolean): AffectedFileResult; - emit(targetSourceFile?: SourceFile, writeFile?: WriteFileCallback, cancellationToken?: CancellationToken, emitOnlyDtsFiles?: boolean, customTransformers?: CustomTransformers): EmitResult | undefined; + getSemanticDiagnosticsOfNextAffectedFile( + cancellationToken?: CancellationToken, + ignoreSourceFile?: (sourceFile: SourceFile) => boolean, + ): AffectedFileResult; + emit( + targetSourceFile?: SourceFile, + writeFile?: WriteFileCallback, + cancellationToken?: CancellationToken, + emitOnlyDtsFiles?: boolean, + customTransformers?: CustomTransformers, + ): EmitResult | undefined; } /** @deprecated */ interface UpdateBundleProject extends InvalidatedProjectBase { readonly kind: InvalidatedProjectKind.UpdateBundle; - emit(writeFile?: WriteFileCallback, customTransformers?: CustomTransformers): EmitResult | BuildInvalidedProject | undefined; - } - type InvalidatedProject = UpdateOutputFileStampsProject | BuildInvalidedProject | UpdateBundleProject; + emit( + writeFile?: WriteFileCallback, + customTransformers?: CustomTransformers, + ): EmitResult | BuildInvalidedProject | undefined; + } + type InvalidatedProject = + | UpdateOutputFileStampsProject + | BuildInvalidedProject + | UpdateBundleProject; namespace JsTyping { interface TypingResolutionHost { directoryExists(path: string): boolean; fileExists(fileName: string): boolean; readFile(path: string, encoding?: string): string | undefined; - readDirectory(rootDir: string, extensions: readonly string[], excludes: readonly string[] | undefined, includes: readonly string[] | undefined, depth?: number): string[]; + readDirectory( + rootDir: string, + extensions: readonly string[], + excludes: readonly string[] | undefined, + includes: readonly string[] | undefined, + depth?: number, + ): string[]; } } function getDefaultFormatCodeSettings(newLineCharacter?: string): FormatCodeSettings; @@ -10251,18 +12399,55 @@ declare namespace ts { trace?(s: string): void; error?(s: string): void; useCaseSensitiveFileNames?(): boolean; - readDirectory?(path: string, extensions?: readonly string[], exclude?: readonly string[], include?: readonly string[], depth?: number): string[]; + readDirectory?( + path: string, + extensions?: readonly string[], + exclude?: readonly string[], + include?: readonly string[], + depth?: number, + ): string[]; realpath?(path: string): string; readFile(path: string, encoding?: string): string | undefined; fileExists(path: string): boolean; getTypeRootsVersion?(): number; /** @deprecated supply resolveModuleNameLiterals instead for resolution that can handle newer resolution modes like nodenext */ - resolveModuleNames?(moduleNames: string[], containingFile: string, reusedNames: string[] | undefined, redirectedReference: ResolvedProjectReference | undefined, options: CompilerOptions, containingSourceFile?: SourceFile): (ResolvedModule | undefined)[]; - getResolvedModuleWithFailedLookupLocationsFromCache?(modulename: string, containingFile: string, resolutionMode?: ResolutionMode): ResolvedModuleWithFailedLookupLocations | undefined; + resolveModuleNames?( + moduleNames: string[], + containingFile: string, + reusedNames: string[] | undefined, + redirectedReference: ResolvedProjectReference | undefined, + options: CompilerOptions, + containingSourceFile?: SourceFile, + ): (ResolvedModule | undefined)[]; + getResolvedModuleWithFailedLookupLocationsFromCache?( + modulename: string, + containingFile: string, + resolutionMode?: ResolutionMode, + ): ResolvedModuleWithFailedLookupLocations | undefined; /** @deprecated supply resolveTypeReferenceDirectiveReferences instead for resolution that can handle newer resolution modes like nodenext */ - resolveTypeReferenceDirectives?(typeDirectiveNames: string[] | FileReference[], containingFile: string, redirectedReference: ResolvedProjectReference | undefined, options: CompilerOptions, containingFileMode?: ResolutionMode): (ResolvedTypeReferenceDirective | undefined)[]; - resolveModuleNameLiterals?(moduleLiterals: readonly StringLiteralLike[], containingFile: string, redirectedReference: ResolvedProjectReference | undefined, options: CompilerOptions, containingSourceFile: SourceFile, reusedNames: readonly StringLiteralLike[] | undefined): readonly ResolvedModuleWithFailedLookupLocations[]; - resolveTypeReferenceDirectiveReferences?(typeDirectiveReferences: readonly T[], containingFile: string, redirectedReference: ResolvedProjectReference | undefined, options: CompilerOptions, containingSourceFile: SourceFile | undefined, reusedNames: readonly T[] | undefined): readonly ResolvedTypeReferenceDirectiveWithFailedLookupLocations[]; + resolveTypeReferenceDirectives?( + typeDirectiveNames: string[] | FileReference[], + containingFile: string, + redirectedReference: ResolvedProjectReference | undefined, + options: CompilerOptions, + containingFileMode?: ResolutionMode, + ): (ResolvedTypeReferenceDirective | undefined)[]; + resolveModuleNameLiterals?( + moduleLiterals: readonly StringLiteralLike[], + containingFile: string, + redirectedReference: ResolvedProjectReference | undefined, + options: CompilerOptions, + containingSourceFile: SourceFile, + reusedNames: readonly StringLiteralLike[] | undefined, + ): readonly ResolvedModuleWithFailedLookupLocations[]; + resolveTypeReferenceDirectiveReferences?( + typeDirectiveReferences: readonly T[], + containingFile: string, + redirectedReference: ResolvedProjectReference | undefined, + options: CompilerOptions, + containingSourceFile: SourceFile | undefined, + reusedNames: readonly T[] | undefined, + ): readonly ResolvedTypeReferenceDirectiveWithFailedLookupLocations[]; getDirectories?(directoryName: string): string[]; /** * Gets a set of custom transformers to use during emit. @@ -10331,10 +12516,18 @@ declare namespace ts { getCompilerOptionsDiagnostics(): Diagnostic[]; /** @deprecated Use getEncodedSyntacticClassifications instead. */ getSyntacticClassifications(fileName: string, span: TextSpan): ClassifiedSpan[]; - getSyntacticClassifications(fileName: string, span: TextSpan, format: SemanticClassificationFormat): ClassifiedSpan[] | ClassifiedSpan2020[]; + getSyntacticClassifications( + fileName: string, + span: TextSpan, + format: SemanticClassificationFormat, + ): ClassifiedSpan[] | ClassifiedSpan2020[]; /** @deprecated Use getEncodedSemanticClassifications instead. */ getSemanticClassifications(fileName: string, span: TextSpan): ClassifiedSpan[]; - getSemanticClassifications(fileName: string, span: TextSpan, format: SemanticClassificationFormat): ClassifiedSpan[] | ClassifiedSpan2020[]; + getSemanticClassifications( + fileName: string, + span: TextSpan, + format: SemanticClassificationFormat, + ): ClassifiedSpan[] | ClassifiedSpan2020[]; /** Encoded as triples of [start, length, ClassificationType]. */ getEncodedSyntacticClassifications(fileName: string, span: TextSpan): Classifications; /** @@ -10346,7 +12539,11 @@ declare namespace ts { * @param format Which format to use, defaults to "original" * @returns a number array encoded as triples of [start, length, ClassificationType, ...]. */ - getEncodedSemanticClassifications(fileName: string, span: TextSpan, format?: SemanticClassificationFormat): Classifications; + getEncodedSemanticClassifications( + fileName: string, + span: TextSpan, + format?: SemanticClassificationFormat, + ): Classifications; /** * Gets completion entries at a particular position in a file. * @@ -10356,7 +12553,12 @@ declare namespace ts { * of code actions can be returned with the completions. * @param formattingSettings settings needed for calling formatting functions. */ - getCompletionsAtPosition(fileName: string, position: number, options: GetCompletionsAtPositionOptions | undefined, formattingSettings?: FormatCodeSettings): WithMetadata | undefined; + getCompletionsAtPosition( + fileName: string, + position: number, + options: GetCompletionsAtPositionOptions | undefined, + formattingSettings?: FormatCodeSettings, + ): WithMetadata | undefined; /** * Gets the extended details for a completion entry retrieved from `getCompletionsAtPosition`. * @@ -10368,8 +12570,21 @@ declare namespace ts { * @param preferences User settings, can be undefined for backwards compatibility * @param data `data` property from the completion entry */ - getCompletionEntryDetails(fileName: string, position: number, entryName: string, formatOptions: FormatCodeOptions | FormatCodeSettings | undefined, source: string | undefined, preferences: UserPreferences | undefined, data: CompletionEntryData | undefined): CompletionEntryDetails | undefined; - getCompletionEntrySymbol(fileName: string, position: number, name: string, source: string | undefined): Symbol | undefined; + getCompletionEntryDetails( + fileName: string, + position: number, + entryName: string, + formatOptions: FormatCodeOptions | FormatCodeSettings | undefined, + source: string | undefined, + preferences: UserPreferences | undefined, + data: CompletionEntryData | undefined, + ): CompletionEntryDetails | undefined; + getCompletionEntrySymbol( + fileName: string, + position: number, + name: string, + source: string | undefined, + ): Symbol | undefined; /** * Gets semantic information about the identifier at a particular position in a * file. Quick info is what you typically see when you hover in an editor. @@ -10380,13 +12595,29 @@ declare namespace ts { getQuickInfoAtPosition(fileName: string, position: number): QuickInfo | undefined; getNameOrDottedNameSpan(fileName: string, startPos: number, endPos: number): TextSpan | undefined; getBreakpointStatementAtPosition(fileName: string, position: number): TextSpan | undefined; - getSignatureHelpItems(fileName: string, position: number, options: SignatureHelpItemsOptions | undefined): SignatureHelpItems | undefined; + getSignatureHelpItems( + fileName: string, + position: number, + options: SignatureHelpItemsOptions | undefined, + ): SignatureHelpItems | undefined; getRenameInfo(fileName: string, position: number, preferences: UserPreferences): RenameInfo; /** @deprecated Use the signature with `UserPreferences` instead. */ getRenameInfo(fileName: string, position: number, options?: RenameInfoOptions): RenameInfo; - findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean, preferences: UserPreferences): readonly RenameLocation[] | undefined; + findRenameLocations( + fileName: string, + position: number, + findInStrings: boolean, + findInComments: boolean, + preferences: UserPreferences, + ): readonly RenameLocation[] | undefined; /** @deprecated Pass `providePrefixAndSuffixTextForRename` as part of a `UserPreferences` parameter. */ - findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean, providePrefixAndSuffixTextForRename?: boolean): readonly RenameLocation[] | undefined; + findRenameLocations( + fileName: string, + position: number, + findInStrings: boolean, + findInComments: boolean, + providePrefixAndSuffixTextForRename?: boolean, + ): readonly RenameLocation[] | undefined; getSmartSelectionRange(fileName: string, position: number): SelectionRange; getDefinitionAtPosition(fileName: string, position: number): readonly DefinitionInfo[] | undefined; getDefinitionAndBoundSpan(fileName: string, position: number): DefinitionInfoAndBoundSpan | undefined; @@ -10394,9 +12625,18 @@ declare namespace ts { getImplementationAtPosition(fileName: string, position: number): readonly ImplementationLocation[] | undefined; getReferencesAtPosition(fileName: string, position: number): ReferenceEntry[] | undefined; findReferences(fileName: string, position: number): ReferencedSymbol[] | undefined; - getDocumentHighlights(fileName: string, position: number, filesToSearch: string[]): DocumentHighlights[] | undefined; + getDocumentHighlights( + fileName: string, + position: number, + filesToSearch: string[], + ): DocumentHighlights[] | undefined; getFileReferences(fileName: string): ReferenceEntry[]; - getNavigateToItems(searchValue: string, maxResultCount?: number, fileName?: string, excludeDtsFiles?: boolean): NavigateToItem[]; + getNavigateToItems( + searchValue: string, + maxResultCount?: number, + fileName?: string, + excludeDtsFiles?: boolean, + ): NavigateToItem[]; getNavigationBarItems(fileName: string): NavigationBarItem[]; getNavigationTree(fileName: string): NavigationTree; prepareCallHierarchy(fileName: string, position: number): CallHierarchyItem | CallHierarchyItem[] | undefined; @@ -10407,10 +12647,25 @@ declare namespace ts { getTodoComments(fileName: string, descriptors: TodoCommentDescriptor[]): TodoComment[]; getBraceMatchingAtPosition(fileName: string, position: number): TextSpan[]; getIndentationAtPosition(fileName: string, position: number, options: EditorOptions | EditorSettings): number; - getFormattingEditsForRange(fileName: string, start: number, end: number, options: FormatCodeOptions | FormatCodeSettings): TextChange[]; + getFormattingEditsForRange( + fileName: string, + start: number, + end: number, + options: FormatCodeOptions | FormatCodeSettings, + ): TextChange[]; getFormattingEditsForDocument(fileName: string, options: FormatCodeOptions | FormatCodeSettings): TextChange[]; - getFormattingEditsAfterKeystroke(fileName: string, position: number, key: string, options: FormatCodeOptions | FormatCodeSettings): TextChange[]; - getDocCommentTemplateAtPosition(fileName: string, position: number, options?: DocCommentTemplateOptions, formatOptions?: FormatCodeSettings): TextInsertion | undefined; + getFormattingEditsAfterKeystroke( + fileName: string, + position: number, + key: string, + options: FormatCodeOptions | FormatCodeSettings, + ): TextChange[]; + getDocCommentTemplateAtPosition( + fileName: string, + position: number, + options?: DocCommentTemplateOptions, + formatOptions?: FormatCodeSettings, + ): TextInsertion | undefined; isValidBraceCompletionAtPosition(fileName: string, position: number, openingBrace: number): boolean; /** * This will return a defined result if the position is after the `>` of the opening tag, or somewhere in the text, of a JSXElement with no closing tag. @@ -10420,31 +12675,85 @@ declare namespace ts { getLinkedEditingRangeAtPosition(fileName: string, position: number): LinkedEditingInfo | undefined; getSpanOfEnclosingComment(fileName: string, position: number, onlyMultiLine: boolean): TextSpan | undefined; toLineColumnOffset?(fileName: string, position: number): LineAndCharacter; - getCodeFixesAtPosition(fileName: string, start: number, end: number, errorCodes: readonly number[], formatOptions: FormatCodeSettings, preferences: UserPreferences): readonly CodeFixAction[]; - getCombinedCodeFix(scope: CombinedCodeFixScope, fixId: {}, formatOptions: FormatCodeSettings, preferences: UserPreferences): CombinedCodeActions; - applyCodeActionCommand(action: CodeActionCommand, formatSettings?: FormatCodeSettings): Promise; - applyCodeActionCommand(action: CodeActionCommand[], formatSettings?: FormatCodeSettings): Promise; - applyCodeActionCommand(action: CodeActionCommand | CodeActionCommand[], formatSettings?: FormatCodeSettings): Promise; + getCodeFixesAtPosition( + fileName: string, + start: number, + end: number, + errorCodes: readonly number[], + formatOptions: FormatCodeSettings, + preferences: UserPreferences, + ): readonly CodeFixAction[]; + getCombinedCodeFix( + scope: CombinedCodeFixScope, + fixId: {}, + formatOptions: FormatCodeSettings, + preferences: UserPreferences, + ): CombinedCodeActions; + applyCodeActionCommand( + action: CodeActionCommand, + formatSettings?: FormatCodeSettings, + ): Promise; + applyCodeActionCommand( + action: CodeActionCommand[], + formatSettings?: FormatCodeSettings, + ): Promise; + applyCodeActionCommand( + action: CodeActionCommand | CodeActionCommand[], + formatSettings?: FormatCodeSettings, + ): Promise; /** @deprecated `fileName` will be ignored */ applyCodeActionCommand(fileName: string, action: CodeActionCommand): Promise; /** @deprecated `fileName` will be ignored */ applyCodeActionCommand(fileName: string, action: CodeActionCommand[]): Promise; /** @deprecated `fileName` will be ignored */ - applyCodeActionCommand(fileName: string, action: CodeActionCommand | CodeActionCommand[]): Promise; + applyCodeActionCommand( + fileName: string, + action: CodeActionCommand | CodeActionCommand[], + ): Promise; /** * @param includeInteractiveActions Include refactor actions that require additional arguments to be * passed when calling `getEditsForRefactor`. When true, clients should inspect the `isInteractive` * property of each returned `RefactorActionInfo` and ensure they are able to collect the appropriate * arguments for any interactive action before offering it. */ - getApplicableRefactors(fileName: string, positionOrRange: number | TextRange, preferences: UserPreferences | undefined, triggerReason?: RefactorTriggerReason, kind?: string, includeInteractiveActions?: boolean): ApplicableRefactorInfo[]; - getEditsForRefactor(fileName: string, formatOptions: FormatCodeSettings, positionOrRange: number | TextRange, refactorName: string, actionName: string, preferences: UserPreferences | undefined, interactiveRefactorArguments?: InteractiveRefactorArguments): RefactorEditInfo | undefined; - getMoveToRefactoringFileSuggestions(fileName: string, positionOrRange: number | TextRange, preferences: UserPreferences | undefined, triggerReason?: RefactorTriggerReason, kind?: string): { + getApplicableRefactors( + fileName: string, + positionOrRange: number | TextRange, + preferences: UserPreferences | undefined, + triggerReason?: RefactorTriggerReason, + kind?: string, + includeInteractiveActions?: boolean, + ): ApplicableRefactorInfo[]; + getEditsForRefactor( + fileName: string, + formatOptions: FormatCodeSettings, + positionOrRange: number | TextRange, + refactorName: string, + actionName: string, + preferences: UserPreferences | undefined, + interactiveRefactorArguments?: InteractiveRefactorArguments, + ): RefactorEditInfo | undefined; + getMoveToRefactoringFileSuggestions( + fileName: string, + positionOrRange: number | TextRange, + preferences: UserPreferences | undefined, + triggerReason?: RefactorTriggerReason, + kind?: string, + ): { newFileName: string; files: string[]; }; - organizeImports(args: OrganizeImportsArgs, formatOptions: FormatCodeSettings, preferences: UserPreferences | undefined): readonly FileTextChanges[]; - getEditsForFileRename(oldFilePath: string, newFilePath: string, formatOptions: FormatCodeSettings, preferences: UserPreferences | undefined): readonly FileTextChanges[]; + organizeImports( + args: OrganizeImportsArgs, + formatOptions: FormatCodeSettings, + preferences: UserPreferences | undefined, + ): readonly FileTextChanges[]; + getEditsForFileRename( + oldFilePath: string, + newFilePath: string, + formatOptions: FormatCodeSettings, + preferences: UserPreferences | undefined, + ): readonly FileTextChanges[]; getEmitOutput(fileName: string, emitOnlyDtsFiles?: boolean, forceDtsEmit?: boolean): EmitOutput; getProgram(): Program | undefined; toggleLineComment(fileName: string, textRange: TextRange): TextChange[]; @@ -10508,7 +12817,10 @@ declare namespace ts { interface SignatureHelpItemsOptions { triggerReason?: SignatureHelpTriggerReason; } - type SignatureHelpTriggerReason = SignatureHelpInvokedReason | SignatureHelpCharacterTypedReason | SignatureHelpRetriggeredReason; + type SignatureHelpTriggerReason = + | SignatureHelpInvokedReason + | SignatureHelpCharacterTypedReason + | SignatureHelpRetriggeredReason; /** * Signals that the user manually requested signature help. * The language service will unconditionally attempt to provide a result. @@ -11187,8 +13499,16 @@ declare namespace ts { * subsume the classification. * @deprecated Use getLexicalClassifications instead. */ - getClassificationsForLine(text: string, lexState: EndOfLineState, syntacticClassifierAbsent: boolean): ClassificationResult; - getEncodedLexicalClassifications(text: string, endOfLineState: EndOfLineState, syntacticClassifierAbsent: boolean): Classifications; + getClassificationsForLine( + text: string, + lexState: EndOfLineState, + syntacticClassifierAbsent: boolean, + ): ClassificationResult; + getEncodedLexicalClassifications( + text: string, + endOfLineState: EndOfLineState, + syntacticClassifierAbsent: boolean, + ): Classifications; } enum ScriptElementKind { unknown = "", @@ -11400,8 +13720,24 @@ declare namespace ts { * @param version Current version of the file. Only used if the file was not found * in the registry and a new one was created. */ - acquireDocument(fileName: string, compilationSettingsOrHost: CompilerOptions | MinimalResolutionCacheHost, scriptSnapshot: IScriptSnapshot, version: string, scriptKind?: ScriptKind, sourceFileOptions?: CreateSourceFileOptions | ScriptTarget): SourceFile; - acquireDocumentWithKey(fileName: string, path: Path, compilationSettingsOrHost: CompilerOptions | MinimalResolutionCacheHost, key: DocumentRegistryBucketKey, scriptSnapshot: IScriptSnapshot, version: string, scriptKind?: ScriptKind, sourceFileOptions?: CreateSourceFileOptions | ScriptTarget): SourceFile; + acquireDocument( + fileName: string, + compilationSettingsOrHost: CompilerOptions | MinimalResolutionCacheHost, + scriptSnapshot: IScriptSnapshot, + version: string, + scriptKind?: ScriptKind, + sourceFileOptions?: CreateSourceFileOptions | ScriptTarget, + ): SourceFile; + acquireDocumentWithKey( + fileName: string, + path: Path, + compilationSettingsOrHost: CompilerOptions | MinimalResolutionCacheHost, + key: DocumentRegistryBucketKey, + scriptSnapshot: IScriptSnapshot, + version: string, + scriptKind?: ScriptKind, + sourceFileOptions?: CreateSourceFileOptions | ScriptTarget, + ): SourceFile; /** * Request an updated version of an already existing SourceFile with a given fileName * and compilationSettings. The update will in-turn call updateLanguageServiceSourceFile @@ -11417,8 +13753,24 @@ declare namespace ts { * @param scriptSnapshot Text of the file. * @param version Current version of the file. */ - updateDocument(fileName: string, compilationSettingsOrHost: CompilerOptions | MinimalResolutionCacheHost, scriptSnapshot: IScriptSnapshot, version: string, scriptKind?: ScriptKind, sourceFileOptions?: CreateSourceFileOptions | ScriptTarget): SourceFile; - updateDocumentWithKey(fileName: string, path: Path, compilationSettingsOrHost: CompilerOptions | MinimalResolutionCacheHost, key: DocumentRegistryBucketKey, scriptSnapshot: IScriptSnapshot, version: string, scriptKind?: ScriptKind, sourceFileOptions?: CreateSourceFileOptions | ScriptTarget): SourceFile; + updateDocument( + fileName: string, + compilationSettingsOrHost: CompilerOptions | MinimalResolutionCacheHost, + scriptSnapshot: IScriptSnapshot, + version: string, + scriptKind?: ScriptKind, + sourceFileOptions?: CreateSourceFileOptions | ScriptTarget, + ): SourceFile; + updateDocumentWithKey( + fileName: string, + path: Path, + compilationSettingsOrHost: CompilerOptions | MinimalResolutionCacheHost, + key: DocumentRegistryBucketKey, + scriptSnapshot: IScriptSnapshot, + version: string, + scriptKind?: ScriptKind, + sourceFileOptions?: CreateSourceFileOptions | ScriptTarget, + ): SourceFile; getKeyForCompilationSettings(settings: CompilerOptions): DocumentRegistryBucketKey; /** * Informs the DocumentRegistry that a file is not needed any longer. @@ -11444,19 +13796,39 @@ declare namespace ts { * @param scriptKind The script kind of the file to be released * @param impliedNodeFormat The implied source file format of the file to be released */ - releaseDocument(fileName: string, compilationSettings: CompilerOptions, scriptKind: ScriptKind, impliedNodeFormat: ResolutionMode): void; + releaseDocument( + fileName: string, + compilationSettings: CompilerOptions, + scriptKind: ScriptKind, + impliedNodeFormat: ResolutionMode, + ): void; /** * @deprecated pass scriptKind for and impliedNodeFormat correctness */ releaseDocumentWithKey(path: Path, key: DocumentRegistryBucketKey, scriptKind?: ScriptKind): void; - releaseDocumentWithKey(path: Path, key: DocumentRegistryBucketKey, scriptKind: ScriptKind, impliedNodeFormat: ResolutionMode): void; + releaseDocumentWithKey( + path: Path, + key: DocumentRegistryBucketKey, + scriptKind: ScriptKind, + impliedNodeFormat: ResolutionMode, + ): void; reportStats(): string; } type DocumentRegistryBucketKey = string & { __bucketKey: any; }; - function preProcessFile(sourceText: string, readImportFiles?: boolean, detectJavaScriptImports?: boolean): PreProcessedFileInfo; + function preProcessFile( + sourceText: string, + readImportFiles?: boolean, + detectJavaScriptImports?: boolean, + ): PreProcessedFileInfo; function transpileModule(input: string, transpileOptions: TranspileOptions): TranspileOutput; - function transpile(input: string, compilerOptions?: CompilerOptions, fileName?: string, diagnostics?: Diagnostic[], moduleName?: string): string; + function transpile( + input: string, + compilerOptions?: CompilerOptions, + fileName?: string, + diagnostics?: Diagnostic[], + moduleName?: string, + ): string; interface TranspileOptions { compilerOptions?: CompilerOptions; fileName?: string; @@ -11474,9 +13846,26 @@ declare namespace ts { function displayPartsToString(displayParts: SymbolDisplayPart[] | undefined): string; function getDefaultCompilerOptions(): CompilerOptions; function getSupportedCodeFixes(): readonly string[]; - function createLanguageServiceSourceFile(fileName: string, scriptSnapshot: IScriptSnapshot, scriptTargetOrOptions: ScriptTarget | CreateSourceFileOptions, version: string, setNodeParents: boolean, scriptKind?: ScriptKind): SourceFile; - function updateLanguageServiceSourceFile(sourceFile: SourceFile, scriptSnapshot: IScriptSnapshot, version: string, textChangeRange: TextChangeRange | undefined, aggressiveChecks?: boolean): SourceFile; - function createLanguageService(host: LanguageServiceHost, documentRegistry?: DocumentRegistry, syntaxOnlyOrLanguageServiceMode?: boolean | LanguageServiceMode): LanguageService; + function createLanguageServiceSourceFile( + fileName: string, + scriptSnapshot: IScriptSnapshot, + scriptTargetOrOptions: ScriptTarget | CreateSourceFileOptions, + version: string, + setNodeParents: boolean, + scriptKind?: ScriptKind, + ): SourceFile; + function updateLanguageServiceSourceFile( + sourceFile: SourceFile, + scriptSnapshot: IScriptSnapshot, + version: string, + textChangeRange: TextChangeRange | undefined, + aggressiveChecks?: boolean, + ): SourceFile; + function createLanguageService( + host: LanguageServiceHost, + documentRegistry?: DocumentRegistry, + syntaxOnlyOrLanguageServiceMode?: boolean | LanguageServiceMode, + ): LanguageService; /** * Get the path of the default library files (lib.d.ts) as distributed with the typescript * node package. @@ -11491,6 +13880,10 @@ declare namespace ts { * @param transformers An array of `TransformerFactory` callbacks used to process the transformation. * @param compilerOptions Optional compiler options. */ - function transform(source: T | T[], transformers: TransformerFactory[], compilerOptions?: CompilerOptions): TransformationResult; + function transform( + source: T | T[], + transformers: TransformerFactory[], + compilerOptions?: CompilerOptions, + ): TransformationResult; } export = ts; diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 3b4edb2fdf5c0..2c3f9b5b7306d 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -442,8 +442,21 @@ declare namespace ts { FirstJSDocTagNode = 334, LastJSDocTagNode = 357, } - type TriviaSyntaxKind = SyntaxKind.SingleLineCommentTrivia | SyntaxKind.MultiLineCommentTrivia | SyntaxKind.NewLineTrivia | SyntaxKind.WhitespaceTrivia | SyntaxKind.ShebangTrivia | SyntaxKind.ConflictMarkerTrivia; - type LiteralSyntaxKind = SyntaxKind.NumericLiteral | SyntaxKind.BigIntLiteral | SyntaxKind.StringLiteral | SyntaxKind.JsxText | SyntaxKind.JsxTextAllWhiteSpaces | SyntaxKind.RegularExpressionLiteral | SyntaxKind.NoSubstitutionTemplateLiteral; + type TriviaSyntaxKind = + | SyntaxKind.SingleLineCommentTrivia + | SyntaxKind.MultiLineCommentTrivia + | SyntaxKind.NewLineTrivia + | SyntaxKind.WhitespaceTrivia + | SyntaxKind.ShebangTrivia + | SyntaxKind.ConflictMarkerTrivia; + type LiteralSyntaxKind = + | SyntaxKind.NumericLiteral + | SyntaxKind.BigIntLiteral + | SyntaxKind.StringLiteral + | SyntaxKind.JsxText + | SyntaxKind.JsxTextAllWhiteSpaces + | SyntaxKind.RegularExpressionLiteral + | SyntaxKind.NoSubstitutionTemplateLiteral; type PseudoLiteralSyntaxKind = SyntaxKind.TemplateHead | SyntaxKind.TemplateMiddle | SyntaxKind.TemplateTail; type PunctuationSyntaxKind = | SyntaxKind.OpenBraceToken @@ -591,11 +604,72 @@ declare namespace ts { | SyntaxKind.WhileKeyword | SyntaxKind.WithKeyword | SyntaxKind.YieldKeyword; - type ModifierSyntaxKind = SyntaxKind.AbstractKeyword | SyntaxKind.AccessorKeyword | SyntaxKind.AsyncKeyword | SyntaxKind.ConstKeyword | SyntaxKind.DeclareKeyword | SyntaxKind.DefaultKeyword | SyntaxKind.ExportKeyword | SyntaxKind.InKeyword | SyntaxKind.PrivateKeyword | SyntaxKind.ProtectedKeyword | SyntaxKind.PublicKeyword | SyntaxKind.ReadonlyKeyword | SyntaxKind.OutKeyword | SyntaxKind.OverrideKeyword | SyntaxKind.StaticKeyword; - type KeywordTypeSyntaxKind = SyntaxKind.AnyKeyword | SyntaxKind.BigIntKeyword | SyntaxKind.BooleanKeyword | SyntaxKind.IntrinsicKeyword | SyntaxKind.NeverKeyword | SyntaxKind.NumberKeyword | SyntaxKind.ObjectKeyword | SyntaxKind.StringKeyword | SyntaxKind.SymbolKeyword | SyntaxKind.UndefinedKeyword | SyntaxKind.UnknownKeyword | SyntaxKind.VoidKeyword; - type TokenSyntaxKind = SyntaxKind.Unknown | SyntaxKind.EndOfFileToken | TriviaSyntaxKind | LiteralSyntaxKind | PseudoLiteralSyntaxKind | PunctuationSyntaxKind | SyntaxKind.Identifier | KeywordSyntaxKind; - type JsxTokenSyntaxKind = SyntaxKind.LessThanSlashToken | SyntaxKind.EndOfFileToken | SyntaxKind.ConflictMarkerTrivia | SyntaxKind.JsxText | SyntaxKind.JsxTextAllWhiteSpaces | SyntaxKind.OpenBraceToken | SyntaxKind.LessThanToken; - type JSDocSyntaxKind = SyntaxKind.EndOfFileToken | SyntaxKind.WhitespaceTrivia | SyntaxKind.AtToken | SyntaxKind.NewLineTrivia | SyntaxKind.AsteriskToken | SyntaxKind.OpenBraceToken | SyntaxKind.CloseBraceToken | SyntaxKind.LessThanToken | SyntaxKind.GreaterThanToken | SyntaxKind.OpenBracketToken | SyntaxKind.CloseBracketToken | SyntaxKind.EqualsToken | SyntaxKind.CommaToken | SyntaxKind.DotToken | SyntaxKind.Identifier | SyntaxKind.BacktickToken | SyntaxKind.HashToken | SyntaxKind.Unknown | KeywordSyntaxKind; + type ModifierSyntaxKind = + | SyntaxKind.AbstractKeyword + | SyntaxKind.AccessorKeyword + | SyntaxKind.AsyncKeyword + | SyntaxKind.ConstKeyword + | SyntaxKind.DeclareKeyword + | SyntaxKind.DefaultKeyword + | SyntaxKind.ExportKeyword + | SyntaxKind.InKeyword + | SyntaxKind.PrivateKeyword + | SyntaxKind.ProtectedKeyword + | SyntaxKind.PublicKeyword + | SyntaxKind.ReadonlyKeyword + | SyntaxKind.OutKeyword + | SyntaxKind.OverrideKeyword + | SyntaxKind.StaticKeyword; + type KeywordTypeSyntaxKind = + | SyntaxKind.AnyKeyword + | SyntaxKind.BigIntKeyword + | SyntaxKind.BooleanKeyword + | SyntaxKind.IntrinsicKeyword + | SyntaxKind.NeverKeyword + | SyntaxKind.NumberKeyword + | SyntaxKind.ObjectKeyword + | SyntaxKind.StringKeyword + | SyntaxKind.SymbolKeyword + | SyntaxKind.UndefinedKeyword + | SyntaxKind.UnknownKeyword + | SyntaxKind.VoidKeyword; + type TokenSyntaxKind = + | SyntaxKind.Unknown + | SyntaxKind.EndOfFileToken + | TriviaSyntaxKind + | LiteralSyntaxKind + | PseudoLiteralSyntaxKind + | PunctuationSyntaxKind + | SyntaxKind.Identifier + | KeywordSyntaxKind; + type JsxTokenSyntaxKind = + | SyntaxKind.LessThanSlashToken + | SyntaxKind.EndOfFileToken + | SyntaxKind.ConflictMarkerTrivia + | SyntaxKind.JsxText + | SyntaxKind.JsxTextAllWhiteSpaces + | SyntaxKind.OpenBraceToken + | SyntaxKind.LessThanToken; + type JSDocSyntaxKind = + | SyntaxKind.EndOfFileToken + | SyntaxKind.WhitespaceTrivia + | SyntaxKind.AtToken + | SyntaxKind.NewLineTrivia + | SyntaxKind.AsteriskToken + | SyntaxKind.OpenBraceToken + | SyntaxKind.CloseBraceToken + | SyntaxKind.LessThanToken + | SyntaxKind.GreaterThanToken + | SyntaxKind.OpenBracketToken + | SyntaxKind.CloseBracketToken + | SyntaxKind.EqualsToken + | SyntaxKind.CommaToken + | SyntaxKind.DotToken + | SyntaxKind.Identifier + | SyntaxKind.BacktickToken + | SyntaxKind.HashToken + | SyntaxKind.Unknown + | KeywordSyntaxKind; enum NodeFlags { None = 0, Let = 1, @@ -687,7 +761,10 @@ declare namespace ts { getText(sourceFile?: SourceFile): string; getFirstToken(sourceFile?: SourceFile): Node | undefined; getLastToken(sourceFile?: SourceFile): Node | undefined; - forEachChild(cbNode: (node: Node) => T | undefined, cbNodeArray?: (nodes: NodeArray) => T | undefined): T | undefined; + forEachChild( + cbNode: (node: Node) => T | undefined, + cbNodeArray?: (nodes: NodeArray) => T | undefined, + ): T | undefined; } interface JSDocContainer extends Node { _jsdocContainerBrand: any; @@ -763,12 +840,71 @@ declare namespace ts { | VariableStatement | WhileStatement | WithStatement; - type HasType = SignatureDeclaration | VariableDeclaration | ParameterDeclaration | PropertySignature | PropertyDeclaration | TypePredicateNode | ParenthesizedTypeNode | TypeOperatorNode | MappedTypeNode | AssertionExpression | TypeAliasDeclaration | JSDocTypeExpression | JSDocNonNullableType | JSDocNullableType | JSDocOptionalType | JSDocVariadicType; - type HasTypeArguments = CallExpression | NewExpression | TaggedTemplateExpression | JsxOpeningElement | JsxSelfClosingElement; + type HasType = + | SignatureDeclaration + | VariableDeclaration + | ParameterDeclaration + | PropertySignature + | PropertyDeclaration + | TypePredicateNode + | ParenthesizedTypeNode + | TypeOperatorNode + | MappedTypeNode + | AssertionExpression + | TypeAliasDeclaration + | JSDocTypeExpression + | JSDocNonNullableType + | JSDocNullableType + | JSDocOptionalType + | JSDocVariadicType; + type HasTypeArguments = + | CallExpression + | NewExpression + | TaggedTemplateExpression + | JsxOpeningElement + | JsxSelfClosingElement; type HasInitializer = HasExpressionInitializer | ForStatement | ForInStatement | ForOfStatement | JsxAttribute; - type HasExpressionInitializer = VariableDeclaration | ParameterDeclaration | BindingElement | PropertyDeclaration | PropertyAssignment | EnumMember; - type HasDecorators = ParameterDeclaration | PropertyDeclaration | MethodDeclaration | GetAccessorDeclaration | SetAccessorDeclaration | ClassExpression | ClassDeclaration; - type HasModifiers = TypeParameterDeclaration | ParameterDeclaration | ConstructorTypeNode | PropertySignature | PropertyDeclaration | MethodSignature | MethodDeclaration | ConstructorDeclaration | GetAccessorDeclaration | SetAccessorDeclaration | IndexSignatureDeclaration | FunctionExpression | ArrowFunction | ClassExpression | VariableStatement | FunctionDeclaration | ClassDeclaration | InterfaceDeclaration | TypeAliasDeclaration | EnumDeclaration | ModuleDeclaration | ImportEqualsDeclaration | ImportDeclaration | ExportAssignment | ExportDeclaration; + type HasExpressionInitializer = + | VariableDeclaration + | ParameterDeclaration + | BindingElement + | PropertyDeclaration + | PropertyAssignment + | EnumMember; + type HasDecorators = + | ParameterDeclaration + | PropertyDeclaration + | MethodDeclaration + | GetAccessorDeclaration + | SetAccessorDeclaration + | ClassExpression + | ClassDeclaration; + type HasModifiers = + | TypeParameterDeclaration + | ParameterDeclaration + | ConstructorTypeNode + | PropertySignature + | PropertyDeclaration + | MethodSignature + | MethodDeclaration + | ConstructorDeclaration + | GetAccessorDeclaration + | SetAccessorDeclaration + | IndexSignatureDeclaration + | FunctionExpression + | ArrowFunction + | ClassExpression + | VariableStatement + | FunctionDeclaration + | ClassDeclaration + | InterfaceDeclaration + | TypeAliasDeclaration + | EnumDeclaration + | ModuleDeclaration + | ImportEqualsDeclaration + | ImportDeclaration + | ExportAssignment + | ExportDeclaration; interface NodeArray extends ReadonlyArray, ReadonlyTextRange { readonly hasTrailingComma: boolean; } @@ -815,7 +951,22 @@ declare namespace ts { type OutKeyword = ModifierToken; type OverrideKeyword = ModifierToken; type StaticKeyword = ModifierToken; - type Modifier = AbstractKeyword | AccessorKeyword | AsyncKeyword | ConstKeyword | DeclareKeyword | DefaultKeyword | ExportKeyword | InKeyword | PrivateKeyword | ProtectedKeyword | PublicKeyword | OutKeyword | OverrideKeyword | ReadonlyKeyword | StaticKeyword; + type Modifier = + | AbstractKeyword + | AccessorKeyword + | AsyncKeyword + | ConstKeyword + | DeclareKeyword + | DefaultKeyword + | ExportKeyword + | InKeyword + | PrivateKeyword + | ProtectedKeyword + | PublicKeyword + | OutKeyword + | OverrideKeyword + | ReadonlyKeyword + | StaticKeyword; type ModifierLike = Modifier | Decorator; type AccessibilityModifier = PublicKeyword | PrivateKeyword | ProtectedKeyword; type ParameterPropertyModifier = AccessibilityModifier | ReadonlyKeyword; @@ -856,7 +1007,13 @@ declare namespace ts { type EntityName = Identifier | QualifiedName; type PropertyName = Identifier | StringLiteral | NumericLiteral | ComputedPropertyName | PrivateIdentifier; type MemberName = Identifier | PrivateIdentifier; - type DeclarationName = PropertyName | JsxAttributeName | StringLiteralLike | ElementAccessExpression | BindingPattern | EntityNameExpression; + type DeclarationName = + | PropertyName + | JsxAttributeName + | StringLiteralLike + | ElementAccessExpression + | BindingPattern + | EntityNameExpression; interface Declaration extends Node { _declarationBrand: any; } @@ -900,7 +1057,20 @@ declare namespace ts { readonly parameters: NodeArray; readonly type?: TypeNode | undefined; } - type SignatureDeclaration = CallSignatureDeclaration | ConstructSignatureDeclaration | MethodSignature | IndexSignatureDeclaration | FunctionTypeNode | ConstructorTypeNode | JSDocFunctionType | FunctionDeclaration | MethodDeclaration | ConstructorDeclaration | AccessorDeclaration | FunctionExpression | ArrowFunction; + type SignatureDeclaration = + | CallSignatureDeclaration + | ConstructSignatureDeclaration + | MethodSignature + | IndexSignatureDeclaration + | FunctionTypeNode + | ConstructorTypeNode + | JSDocFunctionType + | FunctionDeclaration + | MethodDeclaration + | ConstructorDeclaration + | AccessorDeclaration + | FunctionExpression + | ArrowFunction; interface CallSignatureDeclaration extends SignatureDeclarationBase, TypeElement, LocalsContainer { readonly kind: SyntaxKind.CallSignature; } @@ -965,7 +1135,12 @@ declare namespace ts { readonly name?: PropertyName; } /** Unlike ObjectLiteralElement, excludes JSXAttribute and JSXSpreadAttribute. */ - type ObjectLiteralElementLike = PropertyAssignment | ShorthandPropertyAssignment | SpreadAssignment | MethodDeclaration | AccessorDeclaration; + type ObjectLiteralElementLike = + | PropertyAssignment + | ShorthandPropertyAssignment + | SpreadAssignment + | MethodDeclaration + | AccessorDeclaration; interface PropertyAssignment extends ObjectLiteralElement, JSDocContainer { readonly kind: SyntaxKind.PropertyAssignment; readonly parent: ObjectLiteralExpression; @@ -984,7 +1159,18 @@ declare namespace ts { readonly parent: ObjectLiteralExpression; readonly expression: Expression; } - type VariableLikeDeclaration = VariableDeclaration | ParameterDeclaration | BindingElement | PropertyDeclaration | PropertyAssignment | PropertySignature | JsxAttribute | ShorthandPropertyAssignment | EnumMember | JSDocPropertyTag | JSDocParameterTag; + type VariableLikeDeclaration = + | VariableDeclaration + | ParameterDeclaration + | BindingElement + | PropertyDeclaration + | PropertyAssignment + | PropertySignature + | JsxAttribute + | ShorthandPropertyAssignment + | EnumMember + | JSDocPropertyTag + | JSDocParameterTag; interface ObjectBindingPattern extends Node { readonly kind: SyntaxKind.ObjectBindingPattern; readonly parent: VariableDeclaration | ParameterDeclaration | BindingElement; @@ -1012,7 +1198,14 @@ declare namespace ts { readonly exclamationToken?: ExclamationToken | undefined; readonly body?: Block | Expression | undefined; } - type FunctionLikeDeclaration = FunctionDeclaration | MethodDeclaration | GetAccessorDeclaration | SetAccessorDeclaration | ConstructorDeclaration | FunctionExpression | ArrowFunction; + type FunctionLikeDeclaration = + | FunctionDeclaration + | MethodDeclaration + | GetAccessorDeclaration + | SetAccessorDeclaration + | ConstructorDeclaration + | FunctionExpression + | ArrowFunction; /** @deprecated Use SignatureDeclaration */ type FunctionLike = SignatureDeclaration; interface FunctionDeclaration extends FunctionLikeDeclarationBase, DeclarationStatement, LocalsContainer { @@ -1027,14 +1220,24 @@ declare namespace ts { readonly modifiers?: NodeArray; readonly name: PropertyName; } - interface MethodDeclaration extends FunctionLikeDeclarationBase, ClassElement, ObjectLiteralElement, JSDocContainer, LocalsContainer, FlowContainer { + interface MethodDeclaration + extends + FunctionLikeDeclarationBase, + ClassElement, + ObjectLiteralElement, + JSDocContainer, + LocalsContainer, + FlowContainer + { readonly kind: SyntaxKind.MethodDeclaration; readonly parent: ClassLikeDeclaration | ObjectLiteralExpression; readonly modifiers?: NodeArray | undefined; readonly name: PropertyName; readonly body?: FunctionBody | undefined; } - interface ConstructorDeclaration extends FunctionLikeDeclarationBase, ClassElement, JSDocContainer, LocalsContainer { + interface ConstructorDeclaration + extends FunctionLikeDeclarationBase, ClassElement, JSDocContainer, LocalsContainer + { readonly kind: SyntaxKind.Constructor; readonly parent: ClassLikeDeclaration; readonly modifiers?: NodeArray | undefined; @@ -1045,14 +1248,32 @@ declare namespace ts { readonly kind: SyntaxKind.SemicolonClassElement; readonly parent: ClassLikeDeclaration; } - interface GetAccessorDeclaration extends FunctionLikeDeclarationBase, ClassElement, TypeElement, ObjectLiteralElement, JSDocContainer, LocalsContainer, FlowContainer { + interface GetAccessorDeclaration + extends + FunctionLikeDeclarationBase, + ClassElement, + TypeElement, + ObjectLiteralElement, + JSDocContainer, + LocalsContainer, + FlowContainer + { readonly kind: SyntaxKind.GetAccessor; readonly parent: ClassLikeDeclaration | ObjectLiteralExpression | TypeLiteralNode | InterfaceDeclaration; readonly modifiers?: NodeArray; readonly name: PropertyName; readonly body?: FunctionBody; } - interface SetAccessorDeclaration extends FunctionLikeDeclarationBase, ClassElement, TypeElement, ObjectLiteralElement, JSDocContainer, LocalsContainer, FlowContainer { + interface SetAccessorDeclaration + extends + FunctionLikeDeclarationBase, + ClassElement, + TypeElement, + ObjectLiteralElement, + JSDocContainer, + LocalsContainer, + FlowContainer + { readonly kind: SyntaxKind.SetAccessor; readonly parent: ClassLikeDeclaration | ObjectLiteralExpression | TypeLiteralNode | InterfaceDeclaration; readonly modifiers?: NodeArray; @@ -1074,7 +1295,9 @@ declare namespace ts { interface TypeNode extends Node { _typeNodeBrand: any; } - interface KeywordTypeNode extends KeywordToken, TypeNode { + interface KeywordTypeNode + extends KeywordToken, TypeNode + { readonly kind: TKind; } interface ImportTypeAssertionContainer extends Node { @@ -1233,7 +1456,13 @@ declare namespace ts { interface UpdateExpression extends UnaryExpression { _updateExpressionBrand: any; } - type PrefixUnaryOperator = SyntaxKind.PlusPlusToken | SyntaxKind.MinusMinusToken | SyntaxKind.PlusToken | SyntaxKind.MinusToken | SyntaxKind.TildeToken | SyntaxKind.ExclamationToken; + type PrefixUnaryOperator = + | SyntaxKind.PlusPlusToken + | SyntaxKind.MinusMinusToken + | SyntaxKind.PlusToken + | SyntaxKind.MinusToken + | SyntaxKind.TildeToken + | SyntaxKind.ExclamationToken; interface PrefixUnaryExpression extends UpdateExpression { readonly kind: SyntaxKind.PrefixUnaryExpression; readonly operator: PrefixUnaryOperator; @@ -1305,21 +1534,52 @@ declare namespace ts { type MultiplicativeOperatorOrHigher = ExponentiationOperator | MultiplicativeOperator; type AdditiveOperator = SyntaxKind.PlusToken | SyntaxKind.MinusToken; type AdditiveOperatorOrHigher = MultiplicativeOperatorOrHigher | AdditiveOperator; - type ShiftOperator = SyntaxKind.LessThanLessThanToken | SyntaxKind.GreaterThanGreaterThanToken | SyntaxKind.GreaterThanGreaterThanGreaterThanToken; + type ShiftOperator = + | SyntaxKind.LessThanLessThanToken + | SyntaxKind.GreaterThanGreaterThanToken + | SyntaxKind.GreaterThanGreaterThanGreaterThanToken; type ShiftOperatorOrHigher = AdditiveOperatorOrHigher | ShiftOperator; - type RelationalOperator = SyntaxKind.LessThanToken | SyntaxKind.LessThanEqualsToken | SyntaxKind.GreaterThanToken | SyntaxKind.GreaterThanEqualsToken | SyntaxKind.InstanceOfKeyword | SyntaxKind.InKeyword; + type RelationalOperator = + | SyntaxKind.LessThanToken + | SyntaxKind.LessThanEqualsToken + | SyntaxKind.GreaterThanToken + | SyntaxKind.GreaterThanEqualsToken + | SyntaxKind.InstanceOfKeyword + | SyntaxKind.InKeyword; type RelationalOperatorOrHigher = ShiftOperatorOrHigher | RelationalOperator; - type EqualityOperator = SyntaxKind.EqualsEqualsToken | SyntaxKind.EqualsEqualsEqualsToken | SyntaxKind.ExclamationEqualsEqualsToken | SyntaxKind.ExclamationEqualsToken; + type EqualityOperator = + | SyntaxKind.EqualsEqualsToken + | SyntaxKind.EqualsEqualsEqualsToken + | SyntaxKind.ExclamationEqualsEqualsToken + | SyntaxKind.ExclamationEqualsToken; type EqualityOperatorOrHigher = RelationalOperatorOrHigher | EqualityOperator; type BitwiseOperator = SyntaxKind.AmpersandToken | SyntaxKind.BarToken | SyntaxKind.CaretToken; type BitwiseOperatorOrHigher = EqualityOperatorOrHigher | BitwiseOperator; type LogicalOperator = SyntaxKind.AmpersandAmpersandToken | SyntaxKind.BarBarToken; type LogicalOperatorOrHigher = BitwiseOperatorOrHigher | LogicalOperator; - type CompoundAssignmentOperator = SyntaxKind.PlusEqualsToken | SyntaxKind.MinusEqualsToken | SyntaxKind.AsteriskAsteriskEqualsToken | SyntaxKind.AsteriskEqualsToken | SyntaxKind.SlashEqualsToken | SyntaxKind.PercentEqualsToken | SyntaxKind.AmpersandEqualsToken | SyntaxKind.BarEqualsToken | SyntaxKind.CaretEqualsToken | SyntaxKind.LessThanLessThanEqualsToken | SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken | SyntaxKind.GreaterThanGreaterThanEqualsToken | SyntaxKind.BarBarEqualsToken | SyntaxKind.AmpersandAmpersandEqualsToken | SyntaxKind.QuestionQuestionEqualsToken; + type CompoundAssignmentOperator = + | SyntaxKind.PlusEqualsToken + | SyntaxKind.MinusEqualsToken + | SyntaxKind.AsteriskAsteriskEqualsToken + | SyntaxKind.AsteriskEqualsToken + | SyntaxKind.SlashEqualsToken + | SyntaxKind.PercentEqualsToken + | SyntaxKind.AmpersandEqualsToken + | SyntaxKind.BarEqualsToken + | SyntaxKind.CaretEqualsToken + | SyntaxKind.LessThanLessThanEqualsToken + | SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken + | SyntaxKind.GreaterThanGreaterThanEqualsToken + | SyntaxKind.BarBarEqualsToken + | SyntaxKind.AmpersandAmpersandEqualsToken + | SyntaxKind.QuestionQuestionEqualsToken; type AssignmentOperator = SyntaxKind.EqualsToken | CompoundAssignmentOperator; type AssignmentOperatorOrHigher = SyntaxKind.QuestionQuestionToken | LogicalOperatorOrHigher | AssignmentOperator; type BinaryOperator = AssignmentOperatorOrHigher | SyntaxKind.CommaToken; - type LogicalOrCoalescingAssignmentOperator = SyntaxKind.AmpersandAmpersandEqualsToken | SyntaxKind.BarBarEqualsToken | SyntaxKind.QuestionQuestionEqualsToken; + type LogicalOrCoalescingAssignmentOperator = + | SyntaxKind.AmpersandAmpersandEqualsToken + | SyntaxKind.BarBarEqualsToken + | SyntaxKind.QuestionQuestionEqualsToken; type BinaryOperatorToken = Token; interface BinaryExpression extends Expression, Declaration, JSDocContainer { readonly kind: SyntaxKind.BinaryExpression; @@ -1339,11 +1599,33 @@ declare namespace ts { readonly left: ArrayLiteralExpression; } type DestructuringAssignment = ObjectDestructuringAssignment | ArrayDestructuringAssignment; - type BindingOrAssignmentElement = VariableDeclaration | ParameterDeclaration | ObjectBindingOrAssignmentElement | ArrayBindingOrAssignmentElement; - type ObjectBindingOrAssignmentElement = BindingElement | PropertyAssignment | ShorthandPropertyAssignment | SpreadAssignment; - type ArrayBindingOrAssignmentElement = BindingElement | OmittedExpression | SpreadElement | ArrayLiteralExpression | ObjectLiteralExpression | AssignmentExpression | Identifier | PropertyAccessExpression | ElementAccessExpression; + type BindingOrAssignmentElement = + | VariableDeclaration + | ParameterDeclaration + | ObjectBindingOrAssignmentElement + | ArrayBindingOrAssignmentElement; + type ObjectBindingOrAssignmentElement = + | BindingElement + | PropertyAssignment + | ShorthandPropertyAssignment + | SpreadAssignment; + type ArrayBindingOrAssignmentElement = + | BindingElement + | OmittedExpression + | SpreadElement + | ArrayLiteralExpression + | ObjectLiteralExpression + | AssignmentExpression + | Identifier + | PropertyAccessExpression + | ElementAccessExpression; type BindingOrAssignmentElementRestIndicator = DotDotDotToken | SpreadElement | SpreadAssignment; - type BindingOrAssignmentElementTarget = BindingOrAssignmentPattern | Identifier | PropertyAccessExpression | ElementAccessExpression | OmittedExpression; + type BindingOrAssignmentElementTarget = + | BindingOrAssignmentPattern + | Identifier + | PropertyAccessExpression + | ElementAccessExpression + | OmittedExpression; type ObjectBindingOrAssignmentPattern = ObjectBindingPattern | ObjectLiteralExpression; type ArrayBindingOrAssignmentPattern = ArrayBindingPattern | ArrayLiteralExpression; type AssignmentPattern = ObjectLiteralExpression | ArrayLiteralExpression; @@ -1358,13 +1640,17 @@ declare namespace ts { } type FunctionBody = Block; type ConciseBody = FunctionBody | Expression; - interface FunctionExpression extends PrimaryExpression, FunctionLikeDeclarationBase, JSDocContainer, LocalsContainer, FlowContainer { + interface FunctionExpression + extends PrimaryExpression, FunctionLikeDeclarationBase, JSDocContainer, LocalsContainer, FlowContainer + { readonly kind: SyntaxKind.FunctionExpression; readonly modifiers?: NodeArray; readonly name?: Identifier; readonly body: FunctionBody; } - interface ArrowFunction extends Expression, FunctionLikeDeclarationBase, JSDocContainer, LocalsContainer, FlowContainer { + interface ArrowFunction + extends Expression, FunctionLikeDeclarationBase, JSDocContainer, LocalsContainer, FlowContainer + { readonly kind: SyntaxKind.ArrowFunction; readonly modifiers?: NodeArray; readonly equalsGreaterThanToken: EqualsGreaterThanToken; @@ -1402,7 +1688,13 @@ declare namespace ts { interface BigIntLiteral extends LiteralExpression { readonly kind: SyntaxKind.BigIntLiteral; } - type LiteralToken = NumericLiteral | BigIntLiteral | StringLiteral | JsxText | RegularExpressionLiteral | NoSubstitutionTemplateLiteral; + type LiteralToken = + | NumericLiteral + | BigIntLiteral + | StringLiteral + | JsxText + | RegularExpressionLiteral + | NoSubstitutionTemplateLiteral; interface TemplateHead extends TemplateLiteralLikeNode { readonly kind: SyntaxKind.TemplateHead; readonly parent: TemplateExpression | TemplateLiteralTypeNode; @@ -1522,7 +1814,12 @@ declare namespace ts { readonly typeArguments?: NodeArray; readonly template: TemplateLiteral; } - type CallLikeExpression = CallExpression | NewExpression | TaggedTemplateExpression | Decorator | JsxOpeningLikeElement; + type CallLikeExpression = + | CallExpression + | NewExpression + | TaggedTemplateExpression + | Decorator + | JsxOpeningLikeElement; interface AsExpression extends Expression { readonly kind: SyntaxKind.AsExpression; readonly expression: Expression; @@ -1766,8 +2063,17 @@ declare namespace ts { readonly block: Block; } type ObjectTypeDeclaration = ClassLikeDeclaration | InterfaceDeclaration | TypeLiteralNode; - type DeclarationWithTypeParameters = DeclarationWithTypeParameterChildren | JSDocTypedefTag | JSDocCallbackTag | JSDocSignature; - type DeclarationWithTypeParameterChildren = SignatureDeclaration | ClassLikeDeclaration | InterfaceDeclaration | TypeAliasDeclaration | JSDocTemplateTag; + type DeclarationWithTypeParameters = + | DeclarationWithTypeParameterChildren + | JSDocTypedefTag + | JSDocCallbackTag + | JSDocSignature; + type DeclarationWithTypeParameterChildren = + | SignatureDeclaration + | ClassLikeDeclaration + | InterfaceDeclaration + | TypeAliasDeclaration + | JSDocTemplateTag; interface ClassLikeDeclarationBase extends NamedDeclaration, JSDocContainer { readonly kind: SyntaxKind.ClassDeclaration | SyntaxKind.ClassExpression; readonly name?: Identifier; @@ -1953,7 +2259,13 @@ declare namespace ts { readonly name: Identifier; } type ImportOrExportSpecifier = ImportSpecifier | ExportSpecifier; - type TypeOnlyCompatibleAliasDeclaration = ImportClause | ImportEqualsDeclaration | NamespaceImport | ImportOrExportSpecifier | ExportDeclaration | NamespaceExport; + type TypeOnlyCompatibleAliasDeclaration = + | ImportClause + | ImportEqualsDeclaration + | NamespaceImport + | ImportOrExportSpecifier + | ExportDeclaration + | NamespaceExport; type TypeOnlyImportDeclaration = | ImportClause & { readonly isTypeOnly: true; @@ -2247,7 +2559,15 @@ declare namespace ts { Label = 12, Condition = 96, } - type FlowNode = FlowStart | FlowLabel | FlowAssignment | FlowCondition | FlowSwitchClause | FlowArrayMutation | FlowCall | FlowReduceLabel; + type FlowNode = + | FlowStart + | FlowLabel + | FlowAssignment + | FlowCondition + | FlowSwitchClause + | FlowArrayMutation + | FlowCall + | FlowReduceLabel; interface FlowNodeBase { flags: FlowFlags; id?: number; @@ -2430,7 +2750,14 @@ declare namespace ts { readonly operator: SyntaxKind.MinusToken; readonly operand: NumericLiteral; } - type JsonObjectExpression = ObjectLiteralExpression | ArrayLiteralExpression | JsonMinusNumericLiteral | NumericLiteral | StringLiteral | BooleanLiteral | NullLiteral; + type JsonObjectExpression = + | ObjectLiteralExpression + | ArrayLiteralExpression + | JsonMinusNumericLiteral + | NumericLiteral + | StringLiteral + | BooleanLiteral + | NullLiteral; interface JsonObjectExpressionStatement extends ExpressionStatement { readonly expression: JsonObjectExpression; } @@ -2442,7 +2769,13 @@ declare namespace ts { } interface ParseConfigHost extends ModuleResolutionHost { useCaseSensitiveFileNames: boolean; - readDirectory(rootDir: string, extensions: readonly string[], excludes: readonly string[] | undefined, includes: readonly string[], depth?: number): readonly string[]; + readDirectory( + rootDir: string, + extensions: readonly string[], + excludes: readonly string[] | undefined, + includes: readonly string[], + depth?: number, + ): readonly string[]; /** * Gets a value indicating whether the specified path exists and is a file. * @param path The path to test. @@ -2461,7 +2794,14 @@ declare namespace ts { }; interface WriteFileCallbackData { } - type WriteFileCallback = (fileName: string, text: string, writeByteOrderMark: boolean, onError?: (message: string) => void, sourceFiles?: readonly SourceFile[], data?: WriteFileCallbackData) => void; + type WriteFileCallback = ( + fileName: string, + text: string, + writeByteOrderMark: boolean, + onError?: (message: string) => void, + sourceFiles?: readonly SourceFile[], + data?: WriteFileCallbackData, + ) => void; class OperationCanceledException { } interface CancellationToken { @@ -2489,13 +2829,25 @@ declare namespace ts { * used for writing the JavaScript and declaration files. Otherwise, the writeFile parameter * will be invoked when writing the JavaScript and declaration files. */ - emit(targetSourceFile?: SourceFile, writeFile?: WriteFileCallback, cancellationToken?: CancellationToken, emitOnlyDtsFiles?: boolean, customTransformers?: CustomTransformers): EmitResult; + emit( + targetSourceFile?: SourceFile, + writeFile?: WriteFileCallback, + cancellationToken?: CancellationToken, + emitOnlyDtsFiles?: boolean, + customTransformers?: CustomTransformers, + ): EmitResult; getOptionsDiagnostics(cancellationToken?: CancellationToken): readonly Diagnostic[]; getGlobalDiagnostics(cancellationToken?: CancellationToken): readonly Diagnostic[]; - getSyntacticDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): readonly DiagnosticWithLocation[]; + getSyntacticDiagnostics( + sourceFile?: SourceFile, + cancellationToken?: CancellationToken, + ): readonly DiagnosticWithLocation[]; /** The first time this is called, it will return global diagnostics (no location). */ getSemanticDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): readonly Diagnostic[]; - getDeclarationDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): readonly DiagnosticWithLocation[]; + getDeclarationDiagnostics( + sourceFile?: SourceFile, + cancellationToken?: CancellationToken, + ): readonly DiagnosticWithLocation[]; getConfigFileParsingDiagnostics(): readonly Diagnostic[]; /** * Gets a type checker that can be used to semantically analyze source files in the program. @@ -2583,25 +2935,60 @@ declare namespace ts { getNonNullableType(type: Type): Type; getTypeArguments(type: TypeReference): readonly Type[]; /** Note that the resulting nodes cannot be checked. */ - typeToTypeNode(type: Type, enclosingDeclaration: Node | undefined, flags: NodeBuilderFlags | undefined): TypeNode | undefined; + typeToTypeNode( + type: Type, + enclosingDeclaration: Node | undefined, + flags: NodeBuilderFlags | undefined, + ): TypeNode | undefined; /** Note that the resulting nodes cannot be checked. */ - signatureToSignatureDeclaration(signature: Signature, kind: SyntaxKind, enclosingDeclaration: Node | undefined, flags: NodeBuilderFlags | undefined): + signatureToSignatureDeclaration( + signature: Signature, + kind: SyntaxKind, + enclosingDeclaration: Node | undefined, + flags: NodeBuilderFlags | undefined, + ): | SignatureDeclaration & { typeArguments?: NodeArray; } | undefined; /** Note that the resulting nodes cannot be checked. */ - indexInfoToIndexSignatureDeclaration(indexInfo: IndexInfo, enclosingDeclaration: Node | undefined, flags: NodeBuilderFlags | undefined): IndexSignatureDeclaration | undefined; + indexInfoToIndexSignatureDeclaration( + indexInfo: IndexInfo, + enclosingDeclaration: Node | undefined, + flags: NodeBuilderFlags | undefined, + ): IndexSignatureDeclaration | undefined; /** Note that the resulting nodes cannot be checked. */ - symbolToEntityName(symbol: Symbol, meaning: SymbolFlags, enclosingDeclaration: Node | undefined, flags: NodeBuilderFlags | undefined): EntityName | undefined; + symbolToEntityName( + symbol: Symbol, + meaning: SymbolFlags, + enclosingDeclaration: Node | undefined, + flags: NodeBuilderFlags | undefined, + ): EntityName | undefined; /** Note that the resulting nodes cannot be checked. */ - symbolToExpression(symbol: Symbol, meaning: SymbolFlags, enclosingDeclaration: Node | undefined, flags: NodeBuilderFlags | undefined): Expression | undefined; + symbolToExpression( + symbol: Symbol, + meaning: SymbolFlags, + enclosingDeclaration: Node | undefined, + flags: NodeBuilderFlags | undefined, + ): Expression | undefined; /** Note that the resulting nodes cannot be checked. */ - symbolToTypeParameterDeclarations(symbol: Symbol, enclosingDeclaration: Node | undefined, flags: NodeBuilderFlags | undefined): NodeArray | undefined; + symbolToTypeParameterDeclarations( + symbol: Symbol, + enclosingDeclaration: Node | undefined, + flags: NodeBuilderFlags | undefined, + ): NodeArray | undefined; /** Note that the resulting nodes cannot be checked. */ - symbolToParameterDeclaration(symbol: Symbol, enclosingDeclaration: Node | undefined, flags: NodeBuilderFlags | undefined): ParameterDeclaration | undefined; + symbolToParameterDeclaration( + symbol: Symbol, + enclosingDeclaration: Node | undefined, + flags: NodeBuilderFlags | undefined, + ): ParameterDeclaration | undefined; /** Note that the resulting nodes cannot be checked. */ - typeParameterToDeclaration(parameter: TypeParameter, enclosingDeclaration: Node | undefined, flags: NodeBuilderFlags | undefined): TypeParameterDeclaration | undefined; + typeParameterToDeclaration( + parameter: TypeParameter, + enclosingDeclaration: Node | undefined, + flags: NodeBuilderFlags | undefined, + ): TypeParameterDeclaration | undefined; getSymbolsInScope(location: Node, meaning: SymbolFlags): Symbol[]; getSymbolAtLocation(node: Node): Symbol | undefined; getSymbolsOfParameterPropertyDeclaration(parameter: ParameterDeclaration, parameterName: string): Symbol[]; @@ -2624,9 +3011,19 @@ declare namespace ts { getTypeOfAssignmentPattern(pattern: AssignmentPattern): Type; getTypeAtLocation(node: Node): Type; getTypeFromTypeNode(node: TypeNode): Type; - signatureToString(signature: Signature, enclosingDeclaration?: Node, flags?: TypeFormatFlags, kind?: SignatureKind): string; + signatureToString( + signature: Signature, + enclosingDeclaration?: Node, + flags?: TypeFormatFlags, + kind?: SignatureKind, + ): string; typeToString(type: Type, enclosingDeclaration?: Node, flags?: TypeFormatFlags): string; - symbolToString(symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags, flags?: SymbolFormatFlags): string; + symbolToString( + symbol: Symbol, + enclosingDeclaration?: Node, + meaning?: SymbolFlags, + flags?: SymbolFormatFlags, + ): string; typePredicateToString(predicate: TypePredicate, enclosingDeclaration?: Node, flags?: TypeFormatFlags): string; getFullyQualifiedName(symbol: Symbol): string; getAugmentedPropertiesOfType(type: Type): Symbol[]; @@ -2638,14 +3035,23 @@ declare namespace ts { * returns undefined if the node is not valid. * @param argumentCount Apparent number of arguments, passed in case of a possibly incomplete call. This should come from an ArgumentListInfo. See `signatureHelp.ts`. */ - getResolvedSignature(node: CallLikeExpression, candidatesOutArray?: Signature[], argumentCount?: number): Signature | undefined; + getResolvedSignature( + node: CallLikeExpression, + candidatesOutArray?: Signature[], + argumentCount?: number, + ): Signature | undefined; getSignatureFromDeclaration(declaration: SignatureDeclaration): Signature | undefined; isImplementationOfOverload(node: SignatureDeclaration): boolean | undefined; isUndefinedSymbol(symbol: Symbol): boolean; isArgumentsSymbol(symbol: Symbol): boolean; isUnknownSymbol(symbol: Symbol): boolean; - getConstantValue(node: EnumMember | PropertyAccessExpression | ElementAccessExpression): string | number | undefined; - isValidPropertyAccess(node: PropertyAccessExpression | QualifiedName | ImportTypeNode, propertyName: string): boolean; + getConstantValue( + node: EnumMember | PropertyAccessExpression | ElementAccessExpression, + ): string | number | undefined; + isValidPropertyAccess( + node: PropertyAccessExpression | QualifiedName | ImportTypeNode, + propertyName: string, + ): boolean; /** Follow all aliases to get the original symbol. */ getAliasedSymbol(symbol: Symbol): Symbol; /** Follow a *single* alias to get the immediately aliased symbol. */ @@ -2814,7 +3220,11 @@ declare namespace ts { parameterIndex: number; type: Type | undefined; } - type TypePredicate = ThisTypePredicate | IdentifierTypePredicate | AssertsThisTypePredicate | AssertsIdentifierTypePredicate; + type TypePredicate = + | ThisTypePredicate + | IdentifierTypePredicate + | AssertsThisTypePredicate + | AssertsIdentifierTypePredicate; enum SymbolFlags { None = 0, FunctionScopedVariable = 1, @@ -3341,7 +3751,17 @@ declare namespace ts { DynamicPriority = 2, FixedChunkSize = 3, } - type CompilerOptionsValue = string | number | boolean | (string | number)[] | string[] | MapLike | PluginImport[] | ProjectReference[] | null | undefined; + type CompilerOptionsValue = + | string + | number + | boolean + | (string | number)[] + | string[] + | MapLike + | PluginImport[] + | ProjectReference[] + | null + | undefined; interface CompilerOptions { allowImportingTsExtensions?: boolean; allowJs?: boolean; @@ -3656,8 +4076,19 @@ declare namespace ts { readonly resolvedTypeReferenceDirective: ResolvedTypeReferenceDirective | undefined; } interface CompilerHost extends ModuleResolutionHost { - getSourceFile(fileName: string, languageVersionOrOptions: ScriptTarget | CreateSourceFileOptions, onError?: (message: string) => void, shouldCreateNewSourceFile?: boolean): SourceFile | undefined; - getSourceFileByPath?(fileName: string, path: Path, languageVersionOrOptions: ScriptTarget | CreateSourceFileOptions, onError?: (message: string) => void, shouldCreateNewSourceFile?: boolean): SourceFile | undefined; + getSourceFile( + fileName: string, + languageVersionOrOptions: ScriptTarget | CreateSourceFileOptions, + onError?: (message: string) => void, + shouldCreateNewSourceFile?: boolean, + ): SourceFile | undefined; + getSourceFileByPath?( + fileName: string, + path: Path, + languageVersionOrOptions: ScriptTarget | CreateSourceFileOptions, + onError?: (message: string) => void, + shouldCreateNewSourceFile?: boolean, + ): SourceFile | undefined; getCancellationToken?(): CancellationToken; getDefaultLibFileName(options: CompilerOptions): string; getDefaultLibLocation?(): string; @@ -3666,9 +4097,22 @@ declare namespace ts { getCanonicalFileName(fileName: string): string; useCaseSensitiveFileNames(): boolean; getNewLine(): string; - readDirectory?(rootDir: string, extensions: readonly string[], excludes: readonly string[] | undefined, includes: readonly string[], depth?: number): string[]; + readDirectory?( + rootDir: string, + extensions: readonly string[], + excludes: readonly string[] | undefined, + includes: readonly string[], + depth?: number, + ): string[]; /** @deprecated supply resolveModuleNameLiterals instead for resolution that can handle newer resolution modes like nodenext */ - resolveModuleNames?(moduleNames: string[], containingFile: string, reusedNames: string[] | undefined, redirectedReference: ResolvedProjectReference | undefined, options: CompilerOptions, containingSourceFile?: SourceFile): (ResolvedModule | undefined)[]; + resolveModuleNames?( + moduleNames: string[], + containingFile: string, + reusedNames: string[] | undefined, + redirectedReference: ResolvedProjectReference | undefined, + options: CompilerOptions, + containingSourceFile?: SourceFile, + ): (ResolvedModule | undefined)[]; /** * Returns the module resolution cache used by a provided `resolveModuleNames` implementation so that any non-name module resolution operations (eg, package.json lookup) can reuse it */ @@ -3678,9 +4122,29 @@ declare namespace ts { * * This method is a companion for 'resolveModuleNames' and is used to resolve 'types' references to actual type declaration files */ - resolveTypeReferenceDirectives?(typeReferenceDirectiveNames: string[] | readonly FileReference[], containingFile: string, redirectedReference: ResolvedProjectReference | undefined, options: CompilerOptions, containingFileMode?: ResolutionMode): (ResolvedTypeReferenceDirective | undefined)[]; - resolveModuleNameLiterals?(moduleLiterals: readonly StringLiteralLike[], containingFile: string, redirectedReference: ResolvedProjectReference | undefined, options: CompilerOptions, containingSourceFile: SourceFile, reusedNames: readonly StringLiteralLike[] | undefined): readonly ResolvedModuleWithFailedLookupLocations[]; - resolveTypeReferenceDirectiveReferences?(typeDirectiveReferences: readonly T[], containingFile: string, redirectedReference: ResolvedProjectReference | undefined, options: CompilerOptions, containingSourceFile: SourceFile | undefined, reusedNames: readonly T[] | undefined): readonly ResolvedTypeReferenceDirectiveWithFailedLookupLocations[]; + resolveTypeReferenceDirectives?( + typeReferenceDirectiveNames: string[] | readonly FileReference[], + containingFile: string, + redirectedReference: ResolvedProjectReference | undefined, + options: CompilerOptions, + containingFileMode?: ResolutionMode, + ): (ResolvedTypeReferenceDirective | undefined)[]; + resolveModuleNameLiterals?( + moduleLiterals: readonly StringLiteralLike[], + containingFile: string, + redirectedReference: ResolvedProjectReference | undefined, + options: CompilerOptions, + containingSourceFile: SourceFile, + reusedNames: readonly StringLiteralLike[] | undefined, + ): readonly ResolvedModuleWithFailedLookupLocations[]; + resolveTypeReferenceDirectiveReferences?( + typeDirectiveReferences: readonly T[], + containingFile: string, + redirectedReference: ResolvedProjectReference | undefined, + options: CompilerOptions, + containingSourceFile: SourceFile | undefined, + reusedNames: readonly T[] | undefined, + ): readonly ResolvedTypeReferenceDirectiveWithFailedLookupLocations[]; getEnvironmentVariable?(name: string): string | undefined; /** If provided along with custom resolveModuleNames or resolveTypeReferenceDirectives, used to determine if unchanged file path needs to re-resolve modules/type reference directives */ hasInvalidatedResolutions?(filePath: Path): boolean; @@ -3776,7 +4240,10 @@ declare namespace ts { createNumericLiteral(value: string | number, numericLiteralFlags?: TokenFlags): NumericLiteral; createBigIntLiteral(value: string | PseudoBigInt): BigIntLiteral; createStringLiteral(text: string, isSingleQuote?: boolean): StringLiteral; - createStringLiteralFromNode(sourceNode: PropertyNameLiteral | PrivateIdentifier, isSingleQuote?: boolean): StringLiteral; + createStringLiteralFromNode( + sourceNode: PropertyNameLiteral | PrivateIdentifier, + isSingleQuote?: boolean, + ): StringLiteral; createRegularExpressionLiteral(text: string): RegularExpressionLiteral; createIdentifier(text: string): Identifier; /** @@ -3788,7 +4255,10 @@ declare namespace ts { * during emit so that the variable can be referenced in a nested function body. This is an alternative to * setting `EmitFlags.ReuseTempVariableScope` on the nested function itself. */ - createTempVariable(recordTempVariable: ((node: Identifier) => void) | undefined, reservedInNestedScopes?: boolean): Identifier; + createTempVariable( + recordTempVariable: ((node: Identifier) => void) | undefined, + reservedInNestedScopes?: boolean, + ): Identifier; /** * Create a unique temporary variable for use in a loop. * @param reservedInNestedScopes When `true`, reserves the temporary variable name in all nested scopes @@ -3825,55 +4295,251 @@ declare namespace ts { updateQualifiedName(node: QualifiedName, left: EntityName, right: Identifier): QualifiedName; createComputedPropertyName(expression: Expression): ComputedPropertyName; updateComputedPropertyName(node: ComputedPropertyName, expression: Expression): ComputedPropertyName; - createTypeParameterDeclaration(modifiers: readonly Modifier[] | undefined, name: string | Identifier, constraint?: TypeNode, defaultType?: TypeNode): TypeParameterDeclaration; - updateTypeParameterDeclaration(node: TypeParameterDeclaration, modifiers: readonly Modifier[] | undefined, name: Identifier, constraint: TypeNode | undefined, defaultType: TypeNode | undefined): TypeParameterDeclaration; - createParameterDeclaration(modifiers: readonly ModifierLike[] | undefined, dotDotDotToken: DotDotDotToken | undefined, name: string | BindingName, questionToken?: QuestionToken, type?: TypeNode, initializer?: Expression): ParameterDeclaration; - updateParameterDeclaration(node: ParameterDeclaration, modifiers: readonly ModifierLike[] | undefined, dotDotDotToken: DotDotDotToken | undefined, name: string | BindingName, questionToken: QuestionToken | undefined, type: TypeNode | undefined, initializer: Expression | undefined): ParameterDeclaration; + createTypeParameterDeclaration( + modifiers: readonly Modifier[] | undefined, + name: string | Identifier, + constraint?: TypeNode, + defaultType?: TypeNode, + ): TypeParameterDeclaration; + updateTypeParameterDeclaration( + node: TypeParameterDeclaration, + modifiers: readonly Modifier[] | undefined, + name: Identifier, + constraint: TypeNode | undefined, + defaultType: TypeNode | undefined, + ): TypeParameterDeclaration; + createParameterDeclaration( + modifiers: readonly ModifierLike[] | undefined, + dotDotDotToken: DotDotDotToken | undefined, + name: string | BindingName, + questionToken?: QuestionToken, + type?: TypeNode, + initializer?: Expression, + ): ParameterDeclaration; + updateParameterDeclaration( + node: ParameterDeclaration, + modifiers: readonly ModifierLike[] | undefined, + dotDotDotToken: DotDotDotToken | undefined, + name: string | BindingName, + questionToken: QuestionToken | undefined, + type: TypeNode | undefined, + initializer: Expression | undefined, + ): ParameterDeclaration; createDecorator(expression: Expression): Decorator; updateDecorator(node: Decorator, expression: Expression): Decorator; - createPropertySignature(modifiers: readonly Modifier[] | undefined, name: PropertyName | string, questionToken: QuestionToken | undefined, type: TypeNode | undefined): PropertySignature; - updatePropertySignature(node: PropertySignature, modifiers: readonly Modifier[] | undefined, name: PropertyName, questionToken: QuestionToken | undefined, type: TypeNode | undefined): PropertySignature; - createPropertyDeclaration(modifiers: readonly ModifierLike[] | undefined, name: string | PropertyName, questionOrExclamationToken: QuestionToken | ExclamationToken | undefined, type: TypeNode | undefined, initializer: Expression | undefined): PropertyDeclaration; - updatePropertyDeclaration(node: PropertyDeclaration, modifiers: readonly ModifierLike[] | undefined, name: string | PropertyName, questionOrExclamationToken: QuestionToken | ExclamationToken | undefined, type: TypeNode | undefined, initializer: Expression | undefined): PropertyDeclaration; - createMethodSignature(modifiers: readonly Modifier[] | undefined, name: string | PropertyName, questionToken: QuestionToken | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined): MethodSignature; - updateMethodSignature(node: MethodSignature, modifiers: readonly Modifier[] | undefined, name: PropertyName, questionToken: QuestionToken | undefined, typeParameters: NodeArray | undefined, parameters: NodeArray, type: TypeNode | undefined): MethodSignature; - createMethodDeclaration(modifiers: readonly ModifierLike[] | undefined, asteriskToken: AsteriskToken | undefined, name: string | PropertyName, questionToken: QuestionToken | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined): MethodDeclaration; - updateMethodDeclaration(node: MethodDeclaration, modifiers: readonly ModifierLike[] | undefined, asteriskToken: AsteriskToken | undefined, name: PropertyName, questionToken: QuestionToken | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined): MethodDeclaration; - createConstructorDeclaration(modifiers: readonly ModifierLike[] | undefined, parameters: readonly ParameterDeclaration[], body: Block | undefined): ConstructorDeclaration; - updateConstructorDeclaration(node: ConstructorDeclaration, modifiers: readonly ModifierLike[] | undefined, parameters: readonly ParameterDeclaration[], body: Block | undefined): ConstructorDeclaration; - createGetAccessorDeclaration(modifiers: readonly ModifierLike[] | undefined, name: string | PropertyName, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined): GetAccessorDeclaration; - updateGetAccessorDeclaration(node: GetAccessorDeclaration, modifiers: readonly ModifierLike[] | undefined, name: PropertyName, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined): GetAccessorDeclaration; - createSetAccessorDeclaration(modifiers: readonly ModifierLike[] | undefined, name: string | PropertyName, parameters: readonly ParameterDeclaration[], body: Block | undefined): SetAccessorDeclaration; - updateSetAccessorDeclaration(node: SetAccessorDeclaration, modifiers: readonly ModifierLike[] | undefined, name: PropertyName, parameters: readonly ParameterDeclaration[], body: Block | undefined): SetAccessorDeclaration; - createCallSignature(typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined): CallSignatureDeclaration; - updateCallSignature(node: CallSignatureDeclaration, typeParameters: NodeArray | undefined, parameters: NodeArray, type: TypeNode | undefined): CallSignatureDeclaration; - createConstructSignature(typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined): ConstructSignatureDeclaration; - updateConstructSignature(node: ConstructSignatureDeclaration, typeParameters: NodeArray | undefined, parameters: NodeArray, type: TypeNode | undefined): ConstructSignatureDeclaration; - createIndexSignature(modifiers: readonly ModifierLike[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode): IndexSignatureDeclaration; - updateIndexSignature(node: IndexSignatureDeclaration, modifiers: readonly ModifierLike[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode): IndexSignatureDeclaration; + createPropertySignature( + modifiers: readonly Modifier[] | undefined, + name: PropertyName | string, + questionToken: QuestionToken | undefined, + type: TypeNode | undefined, + ): PropertySignature; + updatePropertySignature( + node: PropertySignature, + modifiers: readonly Modifier[] | undefined, + name: PropertyName, + questionToken: QuestionToken | undefined, + type: TypeNode | undefined, + ): PropertySignature; + createPropertyDeclaration( + modifiers: readonly ModifierLike[] | undefined, + name: string | PropertyName, + questionOrExclamationToken: QuestionToken | ExclamationToken | undefined, + type: TypeNode | undefined, + initializer: Expression | undefined, + ): PropertyDeclaration; + updatePropertyDeclaration( + node: PropertyDeclaration, + modifiers: readonly ModifierLike[] | undefined, + name: string | PropertyName, + questionOrExclamationToken: QuestionToken | ExclamationToken | undefined, + type: TypeNode | undefined, + initializer: Expression | undefined, + ): PropertyDeclaration; + createMethodSignature( + modifiers: readonly Modifier[] | undefined, + name: string | PropertyName, + questionToken: QuestionToken | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + parameters: readonly ParameterDeclaration[], + type: TypeNode | undefined, + ): MethodSignature; + updateMethodSignature( + node: MethodSignature, + modifiers: readonly Modifier[] | undefined, + name: PropertyName, + questionToken: QuestionToken | undefined, + typeParameters: NodeArray | undefined, + parameters: NodeArray, + type: TypeNode | undefined, + ): MethodSignature; + createMethodDeclaration( + modifiers: readonly ModifierLike[] | undefined, + asteriskToken: AsteriskToken | undefined, + name: string | PropertyName, + questionToken: QuestionToken | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + parameters: readonly ParameterDeclaration[], + type: TypeNode | undefined, + body: Block | undefined, + ): MethodDeclaration; + updateMethodDeclaration( + node: MethodDeclaration, + modifiers: readonly ModifierLike[] | undefined, + asteriskToken: AsteriskToken | undefined, + name: PropertyName, + questionToken: QuestionToken | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + parameters: readonly ParameterDeclaration[], + type: TypeNode | undefined, + body: Block | undefined, + ): MethodDeclaration; + createConstructorDeclaration( + modifiers: readonly ModifierLike[] | undefined, + parameters: readonly ParameterDeclaration[], + body: Block | undefined, + ): ConstructorDeclaration; + updateConstructorDeclaration( + node: ConstructorDeclaration, + modifiers: readonly ModifierLike[] | undefined, + parameters: readonly ParameterDeclaration[], + body: Block | undefined, + ): ConstructorDeclaration; + createGetAccessorDeclaration( + modifiers: readonly ModifierLike[] | undefined, + name: string | PropertyName, + parameters: readonly ParameterDeclaration[], + type: TypeNode | undefined, + body: Block | undefined, + ): GetAccessorDeclaration; + updateGetAccessorDeclaration( + node: GetAccessorDeclaration, + modifiers: readonly ModifierLike[] | undefined, + name: PropertyName, + parameters: readonly ParameterDeclaration[], + type: TypeNode | undefined, + body: Block | undefined, + ): GetAccessorDeclaration; + createSetAccessorDeclaration( + modifiers: readonly ModifierLike[] | undefined, + name: string | PropertyName, + parameters: readonly ParameterDeclaration[], + body: Block | undefined, + ): SetAccessorDeclaration; + updateSetAccessorDeclaration( + node: SetAccessorDeclaration, + modifiers: readonly ModifierLike[] | undefined, + name: PropertyName, + parameters: readonly ParameterDeclaration[], + body: Block | undefined, + ): SetAccessorDeclaration; + createCallSignature( + typeParameters: readonly TypeParameterDeclaration[] | undefined, + parameters: readonly ParameterDeclaration[], + type: TypeNode | undefined, + ): CallSignatureDeclaration; + updateCallSignature( + node: CallSignatureDeclaration, + typeParameters: NodeArray | undefined, + parameters: NodeArray, + type: TypeNode | undefined, + ): CallSignatureDeclaration; + createConstructSignature( + typeParameters: readonly TypeParameterDeclaration[] | undefined, + parameters: readonly ParameterDeclaration[], + type: TypeNode | undefined, + ): ConstructSignatureDeclaration; + updateConstructSignature( + node: ConstructSignatureDeclaration, + typeParameters: NodeArray | undefined, + parameters: NodeArray, + type: TypeNode | undefined, + ): ConstructSignatureDeclaration; + createIndexSignature( + modifiers: readonly ModifierLike[] | undefined, + parameters: readonly ParameterDeclaration[], + type: TypeNode, + ): IndexSignatureDeclaration; + updateIndexSignature( + node: IndexSignatureDeclaration, + modifiers: readonly ModifierLike[] | undefined, + parameters: readonly ParameterDeclaration[], + type: TypeNode, + ): IndexSignatureDeclaration; createTemplateLiteralTypeSpan(type: TypeNode, literal: TemplateMiddle | TemplateTail): TemplateLiteralTypeSpan; - updateTemplateLiteralTypeSpan(node: TemplateLiteralTypeSpan, type: TypeNode, literal: TemplateMiddle | TemplateTail): TemplateLiteralTypeSpan; + updateTemplateLiteralTypeSpan( + node: TemplateLiteralTypeSpan, + type: TypeNode, + literal: TemplateMiddle | TemplateTail, + ): TemplateLiteralTypeSpan; createClassStaticBlockDeclaration(body: Block): ClassStaticBlockDeclaration; updateClassStaticBlockDeclaration(node: ClassStaticBlockDeclaration, body: Block): ClassStaticBlockDeclaration; createKeywordTypeNode(kind: TKind): KeywordTypeNode; - createTypePredicateNode(assertsModifier: AssertsKeyword | undefined, parameterName: Identifier | ThisTypeNode | string, type: TypeNode | undefined): TypePredicateNode; - updateTypePredicateNode(node: TypePredicateNode, assertsModifier: AssertsKeyword | undefined, parameterName: Identifier | ThisTypeNode, type: TypeNode | undefined): TypePredicateNode; + createTypePredicateNode( + assertsModifier: AssertsKeyword | undefined, + parameterName: Identifier | ThisTypeNode | string, + type: TypeNode | undefined, + ): TypePredicateNode; + updateTypePredicateNode( + node: TypePredicateNode, + assertsModifier: AssertsKeyword | undefined, + parameterName: Identifier | ThisTypeNode, + type: TypeNode | undefined, + ): TypePredicateNode; createTypeReferenceNode(typeName: string | EntityName, typeArguments?: readonly TypeNode[]): TypeReferenceNode; - updateTypeReferenceNode(node: TypeReferenceNode, typeName: EntityName, typeArguments: NodeArray | undefined): TypeReferenceNode; - createFunctionTypeNode(typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode): FunctionTypeNode; - updateFunctionTypeNode(node: FunctionTypeNode, typeParameters: NodeArray | undefined, parameters: NodeArray, type: TypeNode): FunctionTypeNode; - createConstructorTypeNode(modifiers: readonly Modifier[] | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode): ConstructorTypeNode; - updateConstructorTypeNode(node: ConstructorTypeNode, modifiers: readonly Modifier[] | undefined, typeParameters: NodeArray | undefined, parameters: NodeArray, type: TypeNode): ConstructorTypeNode; + updateTypeReferenceNode( + node: TypeReferenceNode, + typeName: EntityName, + typeArguments: NodeArray | undefined, + ): TypeReferenceNode; + createFunctionTypeNode( + typeParameters: readonly TypeParameterDeclaration[] | undefined, + parameters: readonly ParameterDeclaration[], + type: TypeNode, + ): FunctionTypeNode; + updateFunctionTypeNode( + node: FunctionTypeNode, + typeParameters: NodeArray | undefined, + parameters: NodeArray, + type: TypeNode, + ): FunctionTypeNode; + createConstructorTypeNode( + modifiers: readonly Modifier[] | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + parameters: readonly ParameterDeclaration[], + type: TypeNode, + ): ConstructorTypeNode; + updateConstructorTypeNode( + node: ConstructorTypeNode, + modifiers: readonly Modifier[] | undefined, + typeParameters: NodeArray | undefined, + parameters: NodeArray, + type: TypeNode, + ): ConstructorTypeNode; createTypeQueryNode(exprName: EntityName, typeArguments?: readonly TypeNode[]): TypeQueryNode; - updateTypeQueryNode(node: TypeQueryNode, exprName: EntityName, typeArguments?: readonly TypeNode[]): TypeQueryNode; + updateTypeQueryNode( + node: TypeQueryNode, + exprName: EntityName, + typeArguments?: readonly TypeNode[], + ): TypeQueryNode; createTypeLiteralNode(members: readonly TypeElement[] | undefined): TypeLiteralNode; updateTypeLiteralNode(node: TypeLiteralNode, members: NodeArray): TypeLiteralNode; createArrayTypeNode(elementType: TypeNode): ArrayTypeNode; updateArrayTypeNode(node: ArrayTypeNode, elementType: TypeNode): ArrayTypeNode; createTupleTypeNode(elements: readonly (TypeNode | NamedTupleMember)[]): TupleTypeNode; updateTupleTypeNode(node: TupleTypeNode, elements: readonly (TypeNode | NamedTupleMember)[]): TupleTypeNode; - createNamedTupleMember(dotDotDotToken: DotDotDotToken | undefined, name: Identifier, questionToken: QuestionToken | undefined, type: TypeNode): NamedTupleMember; - updateNamedTupleMember(node: NamedTupleMember, dotDotDotToken: DotDotDotToken | undefined, name: Identifier, questionToken: QuestionToken | undefined, type: TypeNode): NamedTupleMember; + createNamedTupleMember( + dotDotDotToken: DotDotDotToken | undefined, + name: Identifier, + questionToken: QuestionToken | undefined, + type: TypeNode, + ): NamedTupleMember; + updateNamedTupleMember( + node: NamedTupleMember, + dotDotDotToken: DotDotDotToken | undefined, + name: Identifier, + questionToken: QuestionToken | undefined, + type: TypeNode, + ): NamedTupleMember; createOptionalTypeNode(type: TypeNode): OptionalTypeNode; updateOptionalTypeNode(node: OptionalTypeNode, type: TypeNode): OptionalTypeNode; createRestTypeNode(type: TypeNode): RestTypeNode; @@ -3882,59 +4548,234 @@ declare namespace ts { updateUnionTypeNode(node: UnionTypeNode, types: NodeArray): UnionTypeNode; createIntersectionTypeNode(types: readonly TypeNode[]): IntersectionTypeNode; updateIntersectionTypeNode(node: IntersectionTypeNode, types: NodeArray): IntersectionTypeNode; - createConditionalTypeNode(checkType: TypeNode, extendsType: TypeNode, trueType: TypeNode, falseType: TypeNode): ConditionalTypeNode; - updateConditionalTypeNode(node: ConditionalTypeNode, checkType: TypeNode, extendsType: TypeNode, trueType: TypeNode, falseType: TypeNode): ConditionalTypeNode; + createConditionalTypeNode( + checkType: TypeNode, + extendsType: TypeNode, + trueType: TypeNode, + falseType: TypeNode, + ): ConditionalTypeNode; + updateConditionalTypeNode( + node: ConditionalTypeNode, + checkType: TypeNode, + extendsType: TypeNode, + trueType: TypeNode, + falseType: TypeNode, + ): ConditionalTypeNode; createInferTypeNode(typeParameter: TypeParameterDeclaration): InferTypeNode; updateInferTypeNode(node: InferTypeNode, typeParameter: TypeParameterDeclaration): InferTypeNode; - createImportTypeNode(argument: TypeNode, assertions?: ImportTypeAssertionContainer, qualifier?: EntityName, typeArguments?: readonly TypeNode[], isTypeOf?: boolean): ImportTypeNode; - updateImportTypeNode(node: ImportTypeNode, argument: TypeNode, assertions: ImportTypeAssertionContainer | undefined, qualifier: EntityName | undefined, typeArguments: readonly TypeNode[] | undefined, isTypeOf?: boolean): ImportTypeNode; + createImportTypeNode( + argument: TypeNode, + assertions?: ImportTypeAssertionContainer, + qualifier?: EntityName, + typeArguments?: readonly TypeNode[], + isTypeOf?: boolean, + ): ImportTypeNode; + updateImportTypeNode( + node: ImportTypeNode, + argument: TypeNode, + assertions: ImportTypeAssertionContainer | undefined, + qualifier: EntityName | undefined, + typeArguments: readonly TypeNode[] | undefined, + isTypeOf?: boolean, + ): ImportTypeNode; createParenthesizedType(type: TypeNode): ParenthesizedTypeNode; updateParenthesizedType(node: ParenthesizedTypeNode, type: TypeNode): ParenthesizedTypeNode; createThisTypeNode(): ThisTypeNode; - createTypeOperatorNode(operator: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.ReadonlyKeyword, type: TypeNode): TypeOperatorNode; + createTypeOperatorNode( + operator: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.ReadonlyKeyword, + type: TypeNode, + ): TypeOperatorNode; updateTypeOperatorNode(node: TypeOperatorNode, type: TypeNode): TypeOperatorNode; createIndexedAccessTypeNode(objectType: TypeNode, indexType: TypeNode): IndexedAccessTypeNode; - updateIndexedAccessTypeNode(node: IndexedAccessTypeNode, objectType: TypeNode, indexType: TypeNode): IndexedAccessTypeNode; - createMappedTypeNode(readonlyToken: ReadonlyKeyword | PlusToken | MinusToken | undefined, typeParameter: TypeParameterDeclaration, nameType: TypeNode | undefined, questionToken: QuestionToken | PlusToken | MinusToken | undefined, type: TypeNode | undefined, members: NodeArray | undefined): MappedTypeNode; - updateMappedTypeNode(node: MappedTypeNode, readonlyToken: ReadonlyKeyword | PlusToken | MinusToken | undefined, typeParameter: TypeParameterDeclaration, nameType: TypeNode | undefined, questionToken: QuestionToken | PlusToken | MinusToken | undefined, type: TypeNode | undefined, members: NodeArray | undefined): MappedTypeNode; + updateIndexedAccessTypeNode( + node: IndexedAccessTypeNode, + objectType: TypeNode, + indexType: TypeNode, + ): IndexedAccessTypeNode; + createMappedTypeNode( + readonlyToken: ReadonlyKeyword | PlusToken | MinusToken | undefined, + typeParameter: TypeParameterDeclaration, + nameType: TypeNode | undefined, + questionToken: QuestionToken | PlusToken | MinusToken | undefined, + type: TypeNode | undefined, + members: NodeArray | undefined, + ): MappedTypeNode; + updateMappedTypeNode( + node: MappedTypeNode, + readonlyToken: ReadonlyKeyword | PlusToken | MinusToken | undefined, + typeParameter: TypeParameterDeclaration, + nameType: TypeNode | undefined, + questionToken: QuestionToken | PlusToken | MinusToken | undefined, + type: TypeNode | undefined, + members: NodeArray | undefined, + ): MappedTypeNode; createLiteralTypeNode(literal: LiteralTypeNode["literal"]): LiteralTypeNode; updateLiteralTypeNode(node: LiteralTypeNode, literal: LiteralTypeNode["literal"]): LiteralTypeNode; - createTemplateLiteralType(head: TemplateHead, templateSpans: readonly TemplateLiteralTypeSpan[]): TemplateLiteralTypeNode; - updateTemplateLiteralType(node: TemplateLiteralTypeNode, head: TemplateHead, templateSpans: readonly TemplateLiteralTypeSpan[]): TemplateLiteralTypeNode; + createTemplateLiteralType( + head: TemplateHead, + templateSpans: readonly TemplateLiteralTypeSpan[], + ): TemplateLiteralTypeNode; + updateTemplateLiteralType( + node: TemplateLiteralTypeNode, + head: TemplateHead, + templateSpans: readonly TemplateLiteralTypeSpan[], + ): TemplateLiteralTypeNode; createObjectBindingPattern(elements: readonly BindingElement[]): ObjectBindingPattern; - updateObjectBindingPattern(node: ObjectBindingPattern, elements: readonly BindingElement[]): ObjectBindingPattern; + updateObjectBindingPattern( + node: ObjectBindingPattern, + elements: readonly BindingElement[], + ): ObjectBindingPattern; createArrayBindingPattern(elements: readonly ArrayBindingElement[]): ArrayBindingPattern; - updateArrayBindingPattern(node: ArrayBindingPattern, elements: readonly ArrayBindingElement[]): ArrayBindingPattern; - createBindingElement(dotDotDotToken: DotDotDotToken | undefined, propertyName: string | PropertyName | undefined, name: string | BindingName, initializer?: Expression): BindingElement; - updateBindingElement(node: BindingElement, dotDotDotToken: DotDotDotToken | undefined, propertyName: PropertyName | undefined, name: BindingName, initializer: Expression | undefined): BindingElement; + updateArrayBindingPattern( + node: ArrayBindingPattern, + elements: readonly ArrayBindingElement[], + ): ArrayBindingPattern; + createBindingElement( + dotDotDotToken: DotDotDotToken | undefined, + propertyName: string | PropertyName | undefined, + name: string | BindingName, + initializer?: Expression, + ): BindingElement; + updateBindingElement( + node: BindingElement, + dotDotDotToken: DotDotDotToken | undefined, + propertyName: PropertyName | undefined, + name: BindingName, + initializer: Expression | undefined, + ): BindingElement; createArrayLiteralExpression(elements?: readonly Expression[], multiLine?: boolean): ArrayLiteralExpression; - updateArrayLiteralExpression(node: ArrayLiteralExpression, elements: readonly Expression[]): ArrayLiteralExpression; - createObjectLiteralExpression(properties?: readonly ObjectLiteralElementLike[], multiLine?: boolean): ObjectLiteralExpression; - updateObjectLiteralExpression(node: ObjectLiteralExpression, properties: readonly ObjectLiteralElementLike[]): ObjectLiteralExpression; + updateArrayLiteralExpression( + node: ArrayLiteralExpression, + elements: readonly Expression[], + ): ArrayLiteralExpression; + createObjectLiteralExpression( + properties?: readonly ObjectLiteralElementLike[], + multiLine?: boolean, + ): ObjectLiteralExpression; + updateObjectLiteralExpression( + node: ObjectLiteralExpression, + properties: readonly ObjectLiteralElementLike[], + ): ObjectLiteralExpression; createPropertyAccessExpression(expression: Expression, name: string | MemberName): PropertyAccessExpression; - updatePropertyAccessExpression(node: PropertyAccessExpression, expression: Expression, name: MemberName): PropertyAccessExpression; - createPropertyAccessChain(expression: Expression, questionDotToken: QuestionDotToken | undefined, name: string | MemberName): PropertyAccessChain; - updatePropertyAccessChain(node: PropertyAccessChain, expression: Expression, questionDotToken: QuestionDotToken | undefined, name: MemberName): PropertyAccessChain; + updatePropertyAccessExpression( + node: PropertyAccessExpression, + expression: Expression, + name: MemberName, + ): PropertyAccessExpression; + createPropertyAccessChain( + expression: Expression, + questionDotToken: QuestionDotToken | undefined, + name: string | MemberName, + ): PropertyAccessChain; + updatePropertyAccessChain( + node: PropertyAccessChain, + expression: Expression, + questionDotToken: QuestionDotToken | undefined, + name: MemberName, + ): PropertyAccessChain; createElementAccessExpression(expression: Expression, index: number | Expression): ElementAccessExpression; - updateElementAccessExpression(node: ElementAccessExpression, expression: Expression, argumentExpression: Expression): ElementAccessExpression; - createElementAccessChain(expression: Expression, questionDotToken: QuestionDotToken | undefined, index: number | Expression): ElementAccessChain; - updateElementAccessChain(node: ElementAccessChain, expression: Expression, questionDotToken: QuestionDotToken | undefined, argumentExpression: Expression): ElementAccessChain; - createCallExpression(expression: Expression, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[] | undefined): CallExpression; - updateCallExpression(node: CallExpression, expression: Expression, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[]): CallExpression; - createCallChain(expression: Expression, questionDotToken: QuestionDotToken | undefined, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[] | undefined): CallChain; - updateCallChain(node: CallChain, expression: Expression, questionDotToken: QuestionDotToken | undefined, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[]): CallChain; - createNewExpression(expression: Expression, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[] | undefined): NewExpression; - updateNewExpression(node: NewExpression, expression: Expression, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[] | undefined): NewExpression; - createTaggedTemplateExpression(tag: Expression, typeArguments: readonly TypeNode[] | undefined, template: TemplateLiteral): TaggedTemplateExpression; - updateTaggedTemplateExpression(node: TaggedTemplateExpression, tag: Expression, typeArguments: readonly TypeNode[] | undefined, template: TemplateLiteral): TaggedTemplateExpression; + updateElementAccessExpression( + node: ElementAccessExpression, + expression: Expression, + argumentExpression: Expression, + ): ElementAccessExpression; + createElementAccessChain( + expression: Expression, + questionDotToken: QuestionDotToken | undefined, + index: number | Expression, + ): ElementAccessChain; + updateElementAccessChain( + node: ElementAccessChain, + expression: Expression, + questionDotToken: QuestionDotToken | undefined, + argumentExpression: Expression, + ): ElementAccessChain; + createCallExpression( + expression: Expression, + typeArguments: readonly TypeNode[] | undefined, + argumentsArray: readonly Expression[] | undefined, + ): CallExpression; + updateCallExpression( + node: CallExpression, + expression: Expression, + typeArguments: readonly TypeNode[] | undefined, + argumentsArray: readonly Expression[], + ): CallExpression; + createCallChain( + expression: Expression, + questionDotToken: QuestionDotToken | undefined, + typeArguments: readonly TypeNode[] | undefined, + argumentsArray: readonly Expression[] | undefined, + ): CallChain; + updateCallChain( + node: CallChain, + expression: Expression, + questionDotToken: QuestionDotToken | undefined, + typeArguments: readonly TypeNode[] | undefined, + argumentsArray: readonly Expression[], + ): CallChain; + createNewExpression( + expression: Expression, + typeArguments: readonly TypeNode[] | undefined, + argumentsArray: readonly Expression[] | undefined, + ): NewExpression; + updateNewExpression( + node: NewExpression, + expression: Expression, + typeArguments: readonly TypeNode[] | undefined, + argumentsArray: readonly Expression[] | undefined, + ): NewExpression; + createTaggedTemplateExpression( + tag: Expression, + typeArguments: readonly TypeNode[] | undefined, + template: TemplateLiteral, + ): TaggedTemplateExpression; + updateTaggedTemplateExpression( + node: TaggedTemplateExpression, + tag: Expression, + typeArguments: readonly TypeNode[] | undefined, + template: TemplateLiteral, + ): TaggedTemplateExpression; createTypeAssertion(type: TypeNode, expression: Expression): TypeAssertion; updateTypeAssertion(node: TypeAssertion, type: TypeNode, expression: Expression): TypeAssertion; createParenthesizedExpression(expression: Expression): ParenthesizedExpression; updateParenthesizedExpression(node: ParenthesizedExpression, expression: Expression): ParenthesizedExpression; - createFunctionExpression(modifiers: readonly Modifier[] | undefined, asteriskToken: AsteriskToken | undefined, name: string | Identifier | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[] | undefined, type: TypeNode | undefined, body: Block): FunctionExpression; - updateFunctionExpression(node: FunctionExpression, modifiers: readonly Modifier[] | undefined, asteriskToken: AsteriskToken | undefined, name: Identifier | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: Block): FunctionExpression; - createArrowFunction(modifiers: readonly Modifier[] | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, equalsGreaterThanToken: EqualsGreaterThanToken | undefined, body: ConciseBody): ArrowFunction; - updateArrowFunction(node: ArrowFunction, modifiers: readonly Modifier[] | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, equalsGreaterThanToken: EqualsGreaterThanToken, body: ConciseBody): ArrowFunction; + createFunctionExpression( + modifiers: readonly Modifier[] | undefined, + asteriskToken: AsteriskToken | undefined, + name: string | Identifier | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + parameters: readonly ParameterDeclaration[] | undefined, + type: TypeNode | undefined, + body: Block, + ): FunctionExpression; + updateFunctionExpression( + node: FunctionExpression, + modifiers: readonly Modifier[] | undefined, + asteriskToken: AsteriskToken | undefined, + name: Identifier | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + parameters: readonly ParameterDeclaration[], + type: TypeNode | undefined, + body: Block, + ): FunctionExpression; + createArrowFunction( + modifiers: readonly Modifier[] | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + parameters: readonly ParameterDeclaration[], + type: TypeNode | undefined, + equalsGreaterThanToken: EqualsGreaterThanToken | undefined, + body: ConciseBody, + ): ArrowFunction; + updateArrowFunction( + node: ArrowFunction, + modifiers: readonly Modifier[] | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + parameters: readonly ParameterDeclaration[], + type: TypeNode | undefined, + equalsGreaterThanToken: EqualsGreaterThanToken, + body: ConciseBody, + ): ArrowFunction; createDeleteExpression(expression: Expression): DeleteExpression; updateDeleteExpression(node: DeleteExpression, expression: Expression): DeleteExpression; createTypeOfExpression(expression: Expression): TypeOfExpression; @@ -3947,12 +4788,38 @@ declare namespace ts { updatePrefixUnaryExpression(node: PrefixUnaryExpression, operand: Expression): PrefixUnaryExpression; createPostfixUnaryExpression(operand: Expression, operator: PostfixUnaryOperator): PostfixUnaryExpression; updatePostfixUnaryExpression(node: PostfixUnaryExpression, operand: Expression): PostfixUnaryExpression; - createBinaryExpression(left: Expression, operator: BinaryOperator | BinaryOperatorToken, right: Expression): BinaryExpression; - updateBinaryExpression(node: BinaryExpression, left: Expression, operator: BinaryOperator | BinaryOperatorToken, right: Expression): BinaryExpression; - createConditionalExpression(condition: Expression, questionToken: QuestionToken | undefined, whenTrue: Expression, colonToken: ColonToken | undefined, whenFalse: Expression): ConditionalExpression; - updateConditionalExpression(node: ConditionalExpression, condition: Expression, questionToken: QuestionToken, whenTrue: Expression, colonToken: ColonToken, whenFalse: Expression): ConditionalExpression; + createBinaryExpression( + left: Expression, + operator: BinaryOperator | BinaryOperatorToken, + right: Expression, + ): BinaryExpression; + updateBinaryExpression( + node: BinaryExpression, + left: Expression, + operator: BinaryOperator | BinaryOperatorToken, + right: Expression, + ): BinaryExpression; + createConditionalExpression( + condition: Expression, + questionToken: QuestionToken | undefined, + whenTrue: Expression, + colonToken: ColonToken | undefined, + whenFalse: Expression, + ): ConditionalExpression; + updateConditionalExpression( + node: ConditionalExpression, + condition: Expression, + questionToken: QuestionToken, + whenTrue: Expression, + colonToken: ColonToken, + whenFalse: Expression, + ): ConditionalExpression; createTemplateExpression(head: TemplateHead, templateSpans: readonly TemplateSpan[]): TemplateExpression; - updateTemplateExpression(node: TemplateExpression, head: TemplateHead, templateSpans: readonly TemplateSpan[]): TemplateExpression; + updateTemplateExpression( + node: TemplateExpression, + head: TemplateHead, + templateSpans: readonly TemplateSpan[], + ): TemplateExpression; createTemplateHead(text: string, rawText?: string, templateFlags?: TokenFlags): TemplateHead; createTemplateHead(text: string | undefined, rawText: string, templateFlags?: TokenFlags): TemplateHead; createTemplateMiddle(text: string, rawText?: string, templateFlags?: TokenFlags): TemplateMiddle; @@ -3963,14 +4830,38 @@ declare namespace ts { createNoSubstitutionTemplateLiteral(text: string | undefined, rawText: string): NoSubstitutionTemplateLiteral; createYieldExpression(asteriskToken: AsteriskToken, expression: Expression): YieldExpression; createYieldExpression(asteriskToken: undefined, expression: Expression | undefined): YieldExpression; - updateYieldExpression(node: YieldExpression, asteriskToken: AsteriskToken | undefined, expression: Expression | undefined): YieldExpression; + updateYieldExpression( + node: YieldExpression, + asteriskToken: AsteriskToken | undefined, + expression: Expression | undefined, + ): YieldExpression; createSpreadElement(expression: Expression): SpreadElement; updateSpreadElement(node: SpreadElement, expression: Expression): SpreadElement; - createClassExpression(modifiers: readonly ModifierLike[] | undefined, name: string | Identifier | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, heritageClauses: readonly HeritageClause[] | undefined, members: readonly ClassElement[]): ClassExpression; - updateClassExpression(node: ClassExpression, modifiers: readonly ModifierLike[] | undefined, name: Identifier | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, heritageClauses: readonly HeritageClause[] | undefined, members: readonly ClassElement[]): ClassExpression; + createClassExpression( + modifiers: readonly ModifierLike[] | undefined, + name: string | Identifier | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + heritageClauses: readonly HeritageClause[] | undefined, + members: readonly ClassElement[], + ): ClassExpression; + updateClassExpression( + node: ClassExpression, + modifiers: readonly ModifierLike[] | undefined, + name: Identifier | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + heritageClauses: readonly HeritageClause[] | undefined, + members: readonly ClassElement[], + ): ClassExpression; createOmittedExpression(): OmittedExpression; - createExpressionWithTypeArguments(expression: Expression, typeArguments: readonly TypeNode[] | undefined): ExpressionWithTypeArguments; - updateExpressionWithTypeArguments(node: ExpressionWithTypeArguments, expression: Expression, typeArguments: readonly TypeNode[] | undefined): ExpressionWithTypeArguments; + createExpressionWithTypeArguments( + expression: Expression, + typeArguments: readonly TypeNode[] | undefined, + ): ExpressionWithTypeArguments; + updateExpressionWithTypeArguments( + node: ExpressionWithTypeArguments, + expression: Expression, + typeArguments: readonly TypeNode[] | undefined, + ): ExpressionWithTypeArguments; createAsExpression(expression: Expression, type: TypeNode): AsExpression; updateAsExpression(node: AsExpression, expression: Expression, type: TypeNode): AsExpression; createNonNullExpression(expression: Expression): NonNullExpression; @@ -3980,29 +4871,76 @@ declare namespace ts { createMetaProperty(keywordToken: MetaProperty["keywordToken"], name: Identifier): MetaProperty; updateMetaProperty(node: MetaProperty, name: Identifier): MetaProperty; createSatisfiesExpression(expression: Expression, type: TypeNode): SatisfiesExpression; - updateSatisfiesExpression(node: SatisfiesExpression, expression: Expression, type: TypeNode): SatisfiesExpression; + updateSatisfiesExpression( + node: SatisfiesExpression, + expression: Expression, + type: TypeNode, + ): SatisfiesExpression; createTemplateSpan(expression: Expression, literal: TemplateMiddle | TemplateTail): TemplateSpan; - updateTemplateSpan(node: TemplateSpan, expression: Expression, literal: TemplateMiddle | TemplateTail): TemplateSpan; + updateTemplateSpan( + node: TemplateSpan, + expression: Expression, + literal: TemplateMiddle | TemplateTail, + ): TemplateSpan; createSemicolonClassElement(): SemicolonClassElement; createBlock(statements: readonly Statement[], multiLine?: boolean): Block; updateBlock(node: Block, statements: readonly Statement[]): Block; - createVariableStatement(modifiers: readonly ModifierLike[] | undefined, declarationList: VariableDeclarationList | readonly VariableDeclaration[]): VariableStatement; - updateVariableStatement(node: VariableStatement, modifiers: readonly ModifierLike[] | undefined, declarationList: VariableDeclarationList): VariableStatement; + createVariableStatement( + modifiers: readonly ModifierLike[] | undefined, + declarationList: VariableDeclarationList | readonly VariableDeclaration[], + ): VariableStatement; + updateVariableStatement( + node: VariableStatement, + modifiers: readonly ModifierLike[] | undefined, + declarationList: VariableDeclarationList, + ): VariableStatement; createEmptyStatement(): EmptyStatement; createExpressionStatement(expression: Expression): ExpressionStatement; updateExpressionStatement(node: ExpressionStatement, expression: Expression): ExpressionStatement; createIfStatement(expression: Expression, thenStatement: Statement, elseStatement?: Statement): IfStatement; - updateIfStatement(node: IfStatement, expression: Expression, thenStatement: Statement, elseStatement: Statement | undefined): IfStatement; + updateIfStatement( + node: IfStatement, + expression: Expression, + thenStatement: Statement, + elseStatement: Statement | undefined, + ): IfStatement; createDoStatement(statement: Statement, expression: Expression): DoStatement; updateDoStatement(node: DoStatement, statement: Statement, expression: Expression): DoStatement; createWhileStatement(expression: Expression, statement: Statement): WhileStatement; updateWhileStatement(node: WhileStatement, expression: Expression, statement: Statement): WhileStatement; - createForStatement(initializer: ForInitializer | undefined, condition: Expression | undefined, incrementor: Expression | undefined, statement: Statement): ForStatement; - updateForStatement(node: ForStatement, initializer: ForInitializer | undefined, condition: Expression | undefined, incrementor: Expression | undefined, statement: Statement): ForStatement; + createForStatement( + initializer: ForInitializer | undefined, + condition: Expression | undefined, + incrementor: Expression | undefined, + statement: Statement, + ): ForStatement; + updateForStatement( + node: ForStatement, + initializer: ForInitializer | undefined, + condition: Expression | undefined, + incrementor: Expression | undefined, + statement: Statement, + ): ForStatement; createForInStatement(initializer: ForInitializer, expression: Expression, statement: Statement): ForInStatement; - updateForInStatement(node: ForInStatement, initializer: ForInitializer, expression: Expression, statement: Statement): ForInStatement; - createForOfStatement(awaitModifier: AwaitKeyword | undefined, initializer: ForInitializer, expression: Expression, statement: Statement): ForOfStatement; - updateForOfStatement(node: ForOfStatement, awaitModifier: AwaitKeyword | undefined, initializer: ForInitializer, expression: Expression, statement: Statement): ForOfStatement; + updateForInStatement( + node: ForInStatement, + initializer: ForInitializer, + expression: Expression, + statement: Statement, + ): ForInStatement; + createForOfStatement( + awaitModifier: AwaitKeyword | undefined, + initializer: ForInitializer, + expression: Expression, + statement: Statement, + ): ForOfStatement; + updateForOfStatement( + node: ForOfStatement, + awaitModifier: AwaitKeyword | undefined, + initializer: ForInitializer, + expression: Expression, + statement: Statement, + ): ForOfStatement; createContinueStatement(label?: string | Identifier): ContinueStatement; updateContinueStatement(node: ContinueStatement, label: Identifier | undefined): ContinueStatement; createBreakStatement(label?: string | Identifier): BreakStatement; @@ -4017,59 +4955,235 @@ declare namespace ts { updateLabeledStatement(node: LabeledStatement, label: Identifier, statement: Statement): LabeledStatement; createThrowStatement(expression: Expression): ThrowStatement; updateThrowStatement(node: ThrowStatement, expression: Expression): ThrowStatement; - createTryStatement(tryBlock: Block, catchClause: CatchClause | undefined, finallyBlock: Block | undefined): TryStatement; - updateTryStatement(node: TryStatement, tryBlock: Block, catchClause: CatchClause | undefined, finallyBlock: Block | undefined): TryStatement; + createTryStatement( + tryBlock: Block, + catchClause: CatchClause | undefined, + finallyBlock: Block | undefined, + ): TryStatement; + updateTryStatement( + node: TryStatement, + tryBlock: Block, + catchClause: CatchClause | undefined, + finallyBlock: Block | undefined, + ): TryStatement; createDebuggerStatement(): DebuggerStatement; - createVariableDeclaration(name: string | BindingName, exclamationToken?: ExclamationToken, type?: TypeNode, initializer?: Expression): VariableDeclaration; - updateVariableDeclaration(node: VariableDeclaration, name: BindingName, exclamationToken: ExclamationToken | undefined, type: TypeNode | undefined, initializer: Expression | undefined): VariableDeclaration; - createVariableDeclarationList(declarations: readonly VariableDeclaration[], flags?: NodeFlags): VariableDeclarationList; - updateVariableDeclarationList(node: VariableDeclarationList, declarations: readonly VariableDeclaration[]): VariableDeclarationList; - createFunctionDeclaration(modifiers: readonly ModifierLike[] | undefined, asteriskToken: AsteriskToken | undefined, name: string | Identifier | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined): FunctionDeclaration; - updateFunctionDeclaration(node: FunctionDeclaration, modifiers: readonly ModifierLike[] | undefined, asteriskToken: AsteriskToken | undefined, name: Identifier | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined): FunctionDeclaration; - createClassDeclaration(modifiers: readonly ModifierLike[] | undefined, name: string | Identifier | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, heritageClauses: readonly HeritageClause[] | undefined, members: readonly ClassElement[]): ClassDeclaration; - updateClassDeclaration(node: ClassDeclaration, modifiers: readonly ModifierLike[] | undefined, name: Identifier | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, heritageClauses: readonly HeritageClause[] | undefined, members: readonly ClassElement[]): ClassDeclaration; - createInterfaceDeclaration(modifiers: readonly ModifierLike[] | undefined, name: string | Identifier, typeParameters: readonly TypeParameterDeclaration[] | undefined, heritageClauses: readonly HeritageClause[] | undefined, members: readonly TypeElement[]): InterfaceDeclaration; - updateInterfaceDeclaration(node: InterfaceDeclaration, modifiers: readonly ModifierLike[] | undefined, name: Identifier, typeParameters: readonly TypeParameterDeclaration[] | undefined, heritageClauses: readonly HeritageClause[] | undefined, members: readonly TypeElement[]): InterfaceDeclaration; - createTypeAliasDeclaration(modifiers: readonly ModifierLike[] | undefined, name: string | Identifier, typeParameters: readonly TypeParameterDeclaration[] | undefined, type: TypeNode): TypeAliasDeclaration; - updateTypeAliasDeclaration(node: TypeAliasDeclaration, modifiers: readonly ModifierLike[] | undefined, name: Identifier, typeParameters: readonly TypeParameterDeclaration[] | undefined, type: TypeNode): TypeAliasDeclaration; - createEnumDeclaration(modifiers: readonly ModifierLike[] | undefined, name: string | Identifier, members: readonly EnumMember[]): EnumDeclaration; - updateEnumDeclaration(node: EnumDeclaration, modifiers: readonly ModifierLike[] | undefined, name: Identifier, members: readonly EnumMember[]): EnumDeclaration; - createModuleDeclaration(modifiers: readonly ModifierLike[] | undefined, name: ModuleName, body: ModuleBody | undefined, flags?: NodeFlags): ModuleDeclaration; - updateModuleDeclaration(node: ModuleDeclaration, modifiers: readonly ModifierLike[] | undefined, name: ModuleName, body: ModuleBody | undefined): ModuleDeclaration; + createVariableDeclaration( + name: string | BindingName, + exclamationToken?: ExclamationToken, + type?: TypeNode, + initializer?: Expression, + ): VariableDeclaration; + updateVariableDeclaration( + node: VariableDeclaration, + name: BindingName, + exclamationToken: ExclamationToken | undefined, + type: TypeNode | undefined, + initializer: Expression | undefined, + ): VariableDeclaration; + createVariableDeclarationList( + declarations: readonly VariableDeclaration[], + flags?: NodeFlags, + ): VariableDeclarationList; + updateVariableDeclarationList( + node: VariableDeclarationList, + declarations: readonly VariableDeclaration[], + ): VariableDeclarationList; + createFunctionDeclaration( + modifiers: readonly ModifierLike[] | undefined, + asteriskToken: AsteriskToken | undefined, + name: string | Identifier | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + parameters: readonly ParameterDeclaration[], + type: TypeNode | undefined, + body: Block | undefined, + ): FunctionDeclaration; + updateFunctionDeclaration( + node: FunctionDeclaration, + modifiers: readonly ModifierLike[] | undefined, + asteriskToken: AsteriskToken | undefined, + name: Identifier | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + parameters: readonly ParameterDeclaration[], + type: TypeNode | undefined, + body: Block | undefined, + ): FunctionDeclaration; + createClassDeclaration( + modifiers: readonly ModifierLike[] | undefined, + name: string | Identifier | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + heritageClauses: readonly HeritageClause[] | undefined, + members: readonly ClassElement[], + ): ClassDeclaration; + updateClassDeclaration( + node: ClassDeclaration, + modifiers: readonly ModifierLike[] | undefined, + name: Identifier | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + heritageClauses: readonly HeritageClause[] | undefined, + members: readonly ClassElement[], + ): ClassDeclaration; + createInterfaceDeclaration( + modifiers: readonly ModifierLike[] | undefined, + name: string | Identifier, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + heritageClauses: readonly HeritageClause[] | undefined, + members: readonly TypeElement[], + ): InterfaceDeclaration; + updateInterfaceDeclaration( + node: InterfaceDeclaration, + modifiers: readonly ModifierLike[] | undefined, + name: Identifier, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + heritageClauses: readonly HeritageClause[] | undefined, + members: readonly TypeElement[], + ): InterfaceDeclaration; + createTypeAliasDeclaration( + modifiers: readonly ModifierLike[] | undefined, + name: string | Identifier, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + type: TypeNode, + ): TypeAliasDeclaration; + updateTypeAliasDeclaration( + node: TypeAliasDeclaration, + modifiers: readonly ModifierLike[] | undefined, + name: Identifier, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + type: TypeNode, + ): TypeAliasDeclaration; + createEnumDeclaration( + modifiers: readonly ModifierLike[] | undefined, + name: string | Identifier, + members: readonly EnumMember[], + ): EnumDeclaration; + updateEnumDeclaration( + node: EnumDeclaration, + modifiers: readonly ModifierLike[] | undefined, + name: Identifier, + members: readonly EnumMember[], + ): EnumDeclaration; + createModuleDeclaration( + modifiers: readonly ModifierLike[] | undefined, + name: ModuleName, + body: ModuleBody | undefined, + flags?: NodeFlags, + ): ModuleDeclaration; + updateModuleDeclaration( + node: ModuleDeclaration, + modifiers: readonly ModifierLike[] | undefined, + name: ModuleName, + body: ModuleBody | undefined, + ): ModuleDeclaration; createModuleBlock(statements: readonly Statement[]): ModuleBlock; updateModuleBlock(node: ModuleBlock, statements: readonly Statement[]): ModuleBlock; createCaseBlock(clauses: readonly CaseOrDefaultClause[]): CaseBlock; updateCaseBlock(node: CaseBlock, clauses: readonly CaseOrDefaultClause[]): CaseBlock; createNamespaceExportDeclaration(name: string | Identifier): NamespaceExportDeclaration; - updateNamespaceExportDeclaration(node: NamespaceExportDeclaration, name: Identifier): NamespaceExportDeclaration; - createImportEqualsDeclaration(modifiers: readonly ModifierLike[] | undefined, isTypeOnly: boolean, name: string | Identifier, moduleReference: ModuleReference): ImportEqualsDeclaration; - updateImportEqualsDeclaration(node: ImportEqualsDeclaration, modifiers: readonly ModifierLike[] | undefined, isTypeOnly: boolean, name: Identifier, moduleReference: ModuleReference): ImportEqualsDeclaration; - createImportDeclaration(modifiers: readonly ModifierLike[] | undefined, importClause: ImportClause | undefined, moduleSpecifier: Expression, assertClause?: AssertClause): ImportDeclaration; - updateImportDeclaration(node: ImportDeclaration, modifiers: readonly ModifierLike[] | undefined, importClause: ImportClause | undefined, moduleSpecifier: Expression, assertClause: AssertClause | undefined): ImportDeclaration; - createImportClause(isTypeOnly: boolean, name: Identifier | undefined, namedBindings: NamedImportBindings | undefined): ImportClause; - updateImportClause(node: ImportClause, isTypeOnly: boolean, name: Identifier | undefined, namedBindings: NamedImportBindings | undefined): ImportClause; + updateNamespaceExportDeclaration( + node: NamespaceExportDeclaration, + name: Identifier, + ): NamespaceExportDeclaration; + createImportEqualsDeclaration( + modifiers: readonly ModifierLike[] | undefined, + isTypeOnly: boolean, + name: string | Identifier, + moduleReference: ModuleReference, + ): ImportEqualsDeclaration; + updateImportEqualsDeclaration( + node: ImportEqualsDeclaration, + modifiers: readonly ModifierLike[] | undefined, + isTypeOnly: boolean, + name: Identifier, + moduleReference: ModuleReference, + ): ImportEqualsDeclaration; + createImportDeclaration( + modifiers: readonly ModifierLike[] | undefined, + importClause: ImportClause | undefined, + moduleSpecifier: Expression, + assertClause?: AssertClause, + ): ImportDeclaration; + updateImportDeclaration( + node: ImportDeclaration, + modifiers: readonly ModifierLike[] | undefined, + importClause: ImportClause | undefined, + moduleSpecifier: Expression, + assertClause: AssertClause | undefined, + ): ImportDeclaration; + createImportClause( + isTypeOnly: boolean, + name: Identifier | undefined, + namedBindings: NamedImportBindings | undefined, + ): ImportClause; + updateImportClause( + node: ImportClause, + isTypeOnly: boolean, + name: Identifier | undefined, + namedBindings: NamedImportBindings | undefined, + ): ImportClause; createAssertClause(elements: NodeArray, multiLine?: boolean): AssertClause; updateAssertClause(node: AssertClause, elements: NodeArray, multiLine?: boolean): AssertClause; createAssertEntry(name: AssertionKey, value: Expression): AssertEntry; updateAssertEntry(node: AssertEntry, name: AssertionKey, value: Expression): AssertEntry; createImportTypeAssertionContainer(clause: AssertClause, multiLine?: boolean): ImportTypeAssertionContainer; - updateImportTypeAssertionContainer(node: ImportTypeAssertionContainer, clause: AssertClause, multiLine?: boolean): ImportTypeAssertionContainer; + updateImportTypeAssertionContainer( + node: ImportTypeAssertionContainer, + clause: AssertClause, + multiLine?: boolean, + ): ImportTypeAssertionContainer; createNamespaceImport(name: Identifier): NamespaceImport; updateNamespaceImport(node: NamespaceImport, name: Identifier): NamespaceImport; createNamespaceExport(name: Identifier): NamespaceExport; updateNamespaceExport(node: NamespaceExport, name: Identifier): NamespaceExport; createNamedImports(elements: readonly ImportSpecifier[]): NamedImports; updateNamedImports(node: NamedImports, elements: readonly ImportSpecifier[]): NamedImports; - createImportSpecifier(isTypeOnly: boolean, propertyName: Identifier | undefined, name: Identifier): ImportSpecifier; - updateImportSpecifier(node: ImportSpecifier, isTypeOnly: boolean, propertyName: Identifier | undefined, name: Identifier): ImportSpecifier; - createExportAssignment(modifiers: readonly ModifierLike[] | undefined, isExportEquals: boolean | undefined, expression: Expression): ExportAssignment; - updateExportAssignment(node: ExportAssignment, modifiers: readonly ModifierLike[] | undefined, expression: Expression): ExportAssignment; - createExportDeclaration(modifiers: readonly ModifierLike[] | undefined, isTypeOnly: boolean, exportClause: NamedExportBindings | undefined, moduleSpecifier?: Expression, assertClause?: AssertClause): ExportDeclaration; - updateExportDeclaration(node: ExportDeclaration, modifiers: readonly ModifierLike[] | undefined, isTypeOnly: boolean, exportClause: NamedExportBindings | undefined, moduleSpecifier: Expression | undefined, assertClause: AssertClause | undefined): ExportDeclaration; + createImportSpecifier( + isTypeOnly: boolean, + propertyName: Identifier | undefined, + name: Identifier, + ): ImportSpecifier; + updateImportSpecifier( + node: ImportSpecifier, + isTypeOnly: boolean, + propertyName: Identifier | undefined, + name: Identifier, + ): ImportSpecifier; + createExportAssignment( + modifiers: readonly ModifierLike[] | undefined, + isExportEquals: boolean | undefined, + expression: Expression, + ): ExportAssignment; + updateExportAssignment( + node: ExportAssignment, + modifiers: readonly ModifierLike[] | undefined, + expression: Expression, + ): ExportAssignment; + createExportDeclaration( + modifiers: readonly ModifierLike[] | undefined, + isTypeOnly: boolean, + exportClause: NamedExportBindings | undefined, + moduleSpecifier?: Expression, + assertClause?: AssertClause, + ): ExportDeclaration; + updateExportDeclaration( + node: ExportDeclaration, + modifiers: readonly ModifierLike[] | undefined, + isTypeOnly: boolean, + exportClause: NamedExportBindings | undefined, + moduleSpecifier: Expression | undefined, + assertClause: AssertClause | undefined, + ): ExportDeclaration; createNamedExports(elements: readonly ExportSpecifier[]): NamedExports; updateNamedExports(node: NamedExports, elements: readonly ExportSpecifier[]): NamedExports; - createExportSpecifier(isTypeOnly: boolean, propertyName: string | Identifier | undefined, name: string | Identifier): ExportSpecifier; - updateExportSpecifier(node: ExportSpecifier, isTypeOnly: boolean, propertyName: Identifier | undefined, name: Identifier): ExportSpecifier; + createExportSpecifier( + isTypeOnly: boolean, + propertyName: string | Identifier | undefined, + name: string | Identifier, + ): ExportSpecifier; + updateExportSpecifier( + node: ExportSpecifier, + isTypeOnly: boolean, + propertyName: Identifier | undefined, + name: Identifier, + ): ExportSpecifier; createExternalModuleReference(expression: Expression): ExternalModuleReference; updateExternalModuleReference(node: ExternalModuleReference, expression: Expression): ExternalModuleReference; createJSDocAllType(): JSDocAllType; @@ -4080,8 +5194,15 @@ declare namespace ts { updateJSDocNullableType(node: JSDocNullableType, type: TypeNode): JSDocNullableType; createJSDocOptionalType(type: TypeNode): JSDocOptionalType; updateJSDocOptionalType(node: JSDocOptionalType, type: TypeNode): JSDocOptionalType; - createJSDocFunctionType(parameters: readonly ParameterDeclaration[], type: TypeNode | undefined): JSDocFunctionType; - updateJSDocFunctionType(node: JSDocFunctionType, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined): JSDocFunctionType; + createJSDocFunctionType( + parameters: readonly ParameterDeclaration[], + type: TypeNode | undefined, + ): JSDocFunctionType; + updateJSDocFunctionType( + node: JSDocFunctionType, + parameters: readonly ParameterDeclaration[], + type: TypeNode | undefined, + ): JSDocFunctionType; createJSDocVariadicType(type: TypeNode): JSDocVariadicType; updateJSDocVariadicType(node: JSDocVariadicType, type: TypeNode): JSDocVariadicType; createJSDocNamepathType(type: TypeNode): JSDocNamepathType; @@ -4091,90 +5212,378 @@ declare namespace ts { createJSDocNameReference(name: EntityName | JSDocMemberName): JSDocNameReference; updateJSDocNameReference(node: JSDocNameReference, name: EntityName | JSDocMemberName): JSDocNameReference; createJSDocMemberName(left: EntityName | JSDocMemberName, right: Identifier): JSDocMemberName; - updateJSDocMemberName(node: JSDocMemberName, left: EntityName | JSDocMemberName, right: Identifier): JSDocMemberName; + updateJSDocMemberName( + node: JSDocMemberName, + left: EntityName | JSDocMemberName, + right: Identifier, + ): JSDocMemberName; createJSDocLink(name: EntityName | JSDocMemberName | undefined, text: string): JSDocLink; updateJSDocLink(node: JSDocLink, name: EntityName | JSDocMemberName | undefined, text: string): JSDocLink; createJSDocLinkCode(name: EntityName | JSDocMemberName | undefined, text: string): JSDocLinkCode; - updateJSDocLinkCode(node: JSDocLinkCode, name: EntityName | JSDocMemberName | undefined, text: string): JSDocLinkCode; + updateJSDocLinkCode( + node: JSDocLinkCode, + name: EntityName | JSDocMemberName | undefined, + text: string, + ): JSDocLinkCode; createJSDocLinkPlain(name: EntityName | JSDocMemberName | undefined, text: string): JSDocLinkPlain; - updateJSDocLinkPlain(node: JSDocLinkPlain, name: EntityName | JSDocMemberName | undefined, text: string): JSDocLinkPlain; - createJSDocTypeLiteral(jsDocPropertyTags?: readonly JSDocPropertyLikeTag[], isArrayType?: boolean): JSDocTypeLiteral; - updateJSDocTypeLiteral(node: JSDocTypeLiteral, jsDocPropertyTags: readonly JSDocPropertyLikeTag[] | undefined, isArrayType: boolean | undefined): JSDocTypeLiteral; - createJSDocSignature(typeParameters: readonly JSDocTemplateTag[] | undefined, parameters: readonly JSDocParameterTag[], type?: JSDocReturnTag): JSDocSignature; - updateJSDocSignature(node: JSDocSignature, typeParameters: readonly JSDocTemplateTag[] | undefined, parameters: readonly JSDocParameterTag[], type: JSDocReturnTag | undefined): JSDocSignature; - createJSDocTemplateTag(tagName: Identifier | undefined, constraint: JSDocTypeExpression | undefined, typeParameters: readonly TypeParameterDeclaration[], comment?: string | NodeArray): JSDocTemplateTag; - updateJSDocTemplateTag(node: JSDocTemplateTag, tagName: Identifier | undefined, constraint: JSDocTypeExpression | undefined, typeParameters: readonly TypeParameterDeclaration[], comment: string | NodeArray | undefined): JSDocTemplateTag; - createJSDocTypedefTag(tagName: Identifier | undefined, typeExpression?: JSDocTypeExpression | JSDocTypeLiteral, fullName?: Identifier | JSDocNamespaceDeclaration, comment?: string | NodeArray): JSDocTypedefTag; - updateJSDocTypedefTag(node: JSDocTypedefTag, tagName: Identifier | undefined, typeExpression: JSDocTypeExpression | JSDocTypeLiteral | undefined, fullName: Identifier | JSDocNamespaceDeclaration | undefined, comment: string | NodeArray | undefined): JSDocTypedefTag; - createJSDocParameterTag(tagName: Identifier | undefined, name: EntityName, isBracketed: boolean, typeExpression?: JSDocTypeExpression, isNameFirst?: boolean, comment?: string | NodeArray): JSDocParameterTag; - updateJSDocParameterTag(node: JSDocParameterTag, tagName: Identifier | undefined, name: EntityName, isBracketed: boolean, typeExpression: JSDocTypeExpression | undefined, isNameFirst: boolean, comment: string | NodeArray | undefined): JSDocParameterTag; - createJSDocPropertyTag(tagName: Identifier | undefined, name: EntityName, isBracketed: boolean, typeExpression?: JSDocTypeExpression, isNameFirst?: boolean, comment?: string | NodeArray): JSDocPropertyTag; - updateJSDocPropertyTag(node: JSDocPropertyTag, tagName: Identifier | undefined, name: EntityName, isBracketed: boolean, typeExpression: JSDocTypeExpression | undefined, isNameFirst: boolean, comment: string | NodeArray | undefined): JSDocPropertyTag; - createJSDocTypeTag(tagName: Identifier | undefined, typeExpression: JSDocTypeExpression, comment?: string | NodeArray): JSDocTypeTag; - updateJSDocTypeTag(node: JSDocTypeTag, tagName: Identifier | undefined, typeExpression: JSDocTypeExpression, comment: string | NodeArray | undefined): JSDocTypeTag; - createJSDocSeeTag(tagName: Identifier | undefined, nameExpression: JSDocNameReference | undefined, comment?: string | NodeArray): JSDocSeeTag; - updateJSDocSeeTag(node: JSDocSeeTag, tagName: Identifier | undefined, nameExpression: JSDocNameReference | undefined, comment?: string | NodeArray): JSDocSeeTag; - createJSDocReturnTag(tagName: Identifier | undefined, typeExpression?: JSDocTypeExpression, comment?: string | NodeArray): JSDocReturnTag; - updateJSDocReturnTag(node: JSDocReturnTag, tagName: Identifier | undefined, typeExpression: JSDocTypeExpression | undefined, comment: string | NodeArray | undefined): JSDocReturnTag; - createJSDocThisTag(tagName: Identifier | undefined, typeExpression: JSDocTypeExpression, comment?: string | NodeArray): JSDocThisTag; - updateJSDocThisTag(node: JSDocThisTag, tagName: Identifier | undefined, typeExpression: JSDocTypeExpression | undefined, comment: string | NodeArray | undefined): JSDocThisTag; - createJSDocEnumTag(tagName: Identifier | undefined, typeExpression: JSDocTypeExpression, comment?: string | NodeArray): JSDocEnumTag; - updateJSDocEnumTag(node: JSDocEnumTag, tagName: Identifier | undefined, typeExpression: JSDocTypeExpression, comment: string | NodeArray | undefined): JSDocEnumTag; - createJSDocCallbackTag(tagName: Identifier | undefined, typeExpression: JSDocSignature, fullName?: Identifier | JSDocNamespaceDeclaration, comment?: string | NodeArray): JSDocCallbackTag; - updateJSDocCallbackTag(node: JSDocCallbackTag, tagName: Identifier | undefined, typeExpression: JSDocSignature, fullName: Identifier | JSDocNamespaceDeclaration | undefined, comment: string | NodeArray | undefined): JSDocCallbackTag; - createJSDocOverloadTag(tagName: Identifier | undefined, typeExpression: JSDocSignature, comment?: string | NodeArray): JSDocOverloadTag; - updateJSDocOverloadTag(node: JSDocOverloadTag, tagName: Identifier | undefined, typeExpression: JSDocSignature, comment: string | NodeArray | undefined): JSDocOverloadTag; - createJSDocAugmentsTag(tagName: Identifier | undefined, className: JSDocAugmentsTag["class"], comment?: string | NodeArray): JSDocAugmentsTag; - updateJSDocAugmentsTag(node: JSDocAugmentsTag, tagName: Identifier | undefined, className: JSDocAugmentsTag["class"], comment: string | NodeArray | undefined): JSDocAugmentsTag; - createJSDocImplementsTag(tagName: Identifier | undefined, className: JSDocImplementsTag["class"], comment?: string | NodeArray): JSDocImplementsTag; - updateJSDocImplementsTag(node: JSDocImplementsTag, tagName: Identifier | undefined, className: JSDocImplementsTag["class"], comment: string | NodeArray | undefined): JSDocImplementsTag; - createJSDocAuthorTag(tagName: Identifier | undefined, comment?: string | NodeArray): JSDocAuthorTag; - updateJSDocAuthorTag(node: JSDocAuthorTag, tagName: Identifier | undefined, comment: string | NodeArray | undefined): JSDocAuthorTag; + updateJSDocLinkPlain( + node: JSDocLinkPlain, + name: EntityName | JSDocMemberName | undefined, + text: string, + ): JSDocLinkPlain; + createJSDocTypeLiteral( + jsDocPropertyTags?: readonly JSDocPropertyLikeTag[], + isArrayType?: boolean, + ): JSDocTypeLiteral; + updateJSDocTypeLiteral( + node: JSDocTypeLiteral, + jsDocPropertyTags: readonly JSDocPropertyLikeTag[] | undefined, + isArrayType: boolean | undefined, + ): JSDocTypeLiteral; + createJSDocSignature( + typeParameters: readonly JSDocTemplateTag[] | undefined, + parameters: readonly JSDocParameterTag[], + type?: JSDocReturnTag, + ): JSDocSignature; + updateJSDocSignature( + node: JSDocSignature, + typeParameters: readonly JSDocTemplateTag[] | undefined, + parameters: readonly JSDocParameterTag[], + type: JSDocReturnTag | undefined, + ): JSDocSignature; + createJSDocTemplateTag( + tagName: Identifier | undefined, + constraint: JSDocTypeExpression | undefined, + typeParameters: readonly TypeParameterDeclaration[], + comment?: string | NodeArray, + ): JSDocTemplateTag; + updateJSDocTemplateTag( + node: JSDocTemplateTag, + tagName: Identifier | undefined, + constraint: JSDocTypeExpression | undefined, + typeParameters: readonly TypeParameterDeclaration[], + comment: string | NodeArray | undefined, + ): JSDocTemplateTag; + createJSDocTypedefTag( + tagName: Identifier | undefined, + typeExpression?: JSDocTypeExpression | JSDocTypeLiteral, + fullName?: Identifier | JSDocNamespaceDeclaration, + comment?: string | NodeArray, + ): JSDocTypedefTag; + updateJSDocTypedefTag( + node: JSDocTypedefTag, + tagName: Identifier | undefined, + typeExpression: JSDocTypeExpression | JSDocTypeLiteral | undefined, + fullName: Identifier | JSDocNamespaceDeclaration | undefined, + comment: string | NodeArray | undefined, + ): JSDocTypedefTag; + createJSDocParameterTag( + tagName: Identifier | undefined, + name: EntityName, + isBracketed: boolean, + typeExpression?: JSDocTypeExpression, + isNameFirst?: boolean, + comment?: string | NodeArray, + ): JSDocParameterTag; + updateJSDocParameterTag( + node: JSDocParameterTag, + tagName: Identifier | undefined, + name: EntityName, + isBracketed: boolean, + typeExpression: JSDocTypeExpression | undefined, + isNameFirst: boolean, + comment: string | NodeArray | undefined, + ): JSDocParameterTag; + createJSDocPropertyTag( + tagName: Identifier | undefined, + name: EntityName, + isBracketed: boolean, + typeExpression?: JSDocTypeExpression, + isNameFirst?: boolean, + comment?: string | NodeArray, + ): JSDocPropertyTag; + updateJSDocPropertyTag( + node: JSDocPropertyTag, + tagName: Identifier | undefined, + name: EntityName, + isBracketed: boolean, + typeExpression: JSDocTypeExpression | undefined, + isNameFirst: boolean, + comment: string | NodeArray | undefined, + ): JSDocPropertyTag; + createJSDocTypeTag( + tagName: Identifier | undefined, + typeExpression: JSDocTypeExpression, + comment?: string | NodeArray, + ): JSDocTypeTag; + updateJSDocTypeTag( + node: JSDocTypeTag, + tagName: Identifier | undefined, + typeExpression: JSDocTypeExpression, + comment: string | NodeArray | undefined, + ): JSDocTypeTag; + createJSDocSeeTag( + tagName: Identifier | undefined, + nameExpression: JSDocNameReference | undefined, + comment?: string | NodeArray, + ): JSDocSeeTag; + updateJSDocSeeTag( + node: JSDocSeeTag, + tagName: Identifier | undefined, + nameExpression: JSDocNameReference | undefined, + comment?: string | NodeArray, + ): JSDocSeeTag; + createJSDocReturnTag( + tagName: Identifier | undefined, + typeExpression?: JSDocTypeExpression, + comment?: string | NodeArray, + ): JSDocReturnTag; + updateJSDocReturnTag( + node: JSDocReturnTag, + tagName: Identifier | undefined, + typeExpression: JSDocTypeExpression | undefined, + comment: string | NodeArray | undefined, + ): JSDocReturnTag; + createJSDocThisTag( + tagName: Identifier | undefined, + typeExpression: JSDocTypeExpression, + comment?: string | NodeArray, + ): JSDocThisTag; + updateJSDocThisTag( + node: JSDocThisTag, + tagName: Identifier | undefined, + typeExpression: JSDocTypeExpression | undefined, + comment: string | NodeArray | undefined, + ): JSDocThisTag; + createJSDocEnumTag( + tagName: Identifier | undefined, + typeExpression: JSDocTypeExpression, + comment?: string | NodeArray, + ): JSDocEnumTag; + updateJSDocEnumTag( + node: JSDocEnumTag, + tagName: Identifier | undefined, + typeExpression: JSDocTypeExpression, + comment: string | NodeArray | undefined, + ): JSDocEnumTag; + createJSDocCallbackTag( + tagName: Identifier | undefined, + typeExpression: JSDocSignature, + fullName?: Identifier | JSDocNamespaceDeclaration, + comment?: string | NodeArray, + ): JSDocCallbackTag; + updateJSDocCallbackTag( + node: JSDocCallbackTag, + tagName: Identifier | undefined, + typeExpression: JSDocSignature, + fullName: Identifier | JSDocNamespaceDeclaration | undefined, + comment: string | NodeArray | undefined, + ): JSDocCallbackTag; + createJSDocOverloadTag( + tagName: Identifier | undefined, + typeExpression: JSDocSignature, + comment?: string | NodeArray, + ): JSDocOverloadTag; + updateJSDocOverloadTag( + node: JSDocOverloadTag, + tagName: Identifier | undefined, + typeExpression: JSDocSignature, + comment: string | NodeArray | undefined, + ): JSDocOverloadTag; + createJSDocAugmentsTag( + tagName: Identifier | undefined, + className: JSDocAugmentsTag["class"], + comment?: string | NodeArray, + ): JSDocAugmentsTag; + updateJSDocAugmentsTag( + node: JSDocAugmentsTag, + tagName: Identifier | undefined, + className: JSDocAugmentsTag["class"], + comment: string | NodeArray | undefined, + ): JSDocAugmentsTag; + createJSDocImplementsTag( + tagName: Identifier | undefined, + className: JSDocImplementsTag["class"], + comment?: string | NodeArray, + ): JSDocImplementsTag; + updateJSDocImplementsTag( + node: JSDocImplementsTag, + tagName: Identifier | undefined, + className: JSDocImplementsTag["class"], + comment: string | NodeArray | undefined, + ): JSDocImplementsTag; + createJSDocAuthorTag( + tagName: Identifier | undefined, + comment?: string | NodeArray, + ): JSDocAuthorTag; + updateJSDocAuthorTag( + node: JSDocAuthorTag, + tagName: Identifier | undefined, + comment: string | NodeArray | undefined, + ): JSDocAuthorTag; createJSDocClassTag(tagName: Identifier | undefined, comment?: string | NodeArray): JSDocClassTag; - updateJSDocClassTag(node: JSDocClassTag, tagName: Identifier | undefined, comment: string | NodeArray | undefined): JSDocClassTag; - createJSDocPublicTag(tagName: Identifier | undefined, comment?: string | NodeArray): JSDocPublicTag; - updateJSDocPublicTag(node: JSDocPublicTag, tagName: Identifier | undefined, comment: string | NodeArray | undefined): JSDocPublicTag; - createJSDocPrivateTag(tagName: Identifier | undefined, comment?: string | NodeArray): JSDocPrivateTag; - updateJSDocPrivateTag(node: JSDocPrivateTag, tagName: Identifier | undefined, comment: string | NodeArray | undefined): JSDocPrivateTag; - createJSDocProtectedTag(tagName: Identifier | undefined, comment?: string | NodeArray): JSDocProtectedTag; - updateJSDocProtectedTag(node: JSDocProtectedTag, tagName: Identifier | undefined, comment: string | NodeArray | undefined): JSDocProtectedTag; - createJSDocReadonlyTag(tagName: Identifier | undefined, comment?: string | NodeArray): JSDocReadonlyTag; - updateJSDocReadonlyTag(node: JSDocReadonlyTag, tagName: Identifier | undefined, comment: string | NodeArray | undefined): JSDocReadonlyTag; + updateJSDocClassTag( + node: JSDocClassTag, + tagName: Identifier | undefined, + comment: string | NodeArray | undefined, + ): JSDocClassTag; + createJSDocPublicTag( + tagName: Identifier | undefined, + comment?: string | NodeArray, + ): JSDocPublicTag; + updateJSDocPublicTag( + node: JSDocPublicTag, + tagName: Identifier | undefined, + comment: string | NodeArray | undefined, + ): JSDocPublicTag; + createJSDocPrivateTag( + tagName: Identifier | undefined, + comment?: string | NodeArray, + ): JSDocPrivateTag; + updateJSDocPrivateTag( + node: JSDocPrivateTag, + tagName: Identifier | undefined, + comment: string | NodeArray | undefined, + ): JSDocPrivateTag; + createJSDocProtectedTag( + tagName: Identifier | undefined, + comment?: string | NodeArray, + ): JSDocProtectedTag; + updateJSDocProtectedTag( + node: JSDocProtectedTag, + tagName: Identifier | undefined, + comment: string | NodeArray | undefined, + ): JSDocProtectedTag; + createJSDocReadonlyTag( + tagName: Identifier | undefined, + comment?: string | NodeArray, + ): JSDocReadonlyTag; + updateJSDocReadonlyTag( + node: JSDocReadonlyTag, + tagName: Identifier | undefined, + comment: string | NodeArray | undefined, + ): JSDocReadonlyTag; createJSDocUnknownTag(tagName: Identifier, comment?: string | NodeArray): JSDocUnknownTag; - updateJSDocUnknownTag(node: JSDocUnknownTag, tagName: Identifier, comment: string | NodeArray | undefined): JSDocUnknownTag; - createJSDocDeprecatedTag(tagName: Identifier | undefined, comment?: string | NodeArray): JSDocDeprecatedTag; - updateJSDocDeprecatedTag(node: JSDocDeprecatedTag, tagName: Identifier | undefined, comment?: string | NodeArray): JSDocDeprecatedTag; - createJSDocOverrideTag(tagName: Identifier | undefined, comment?: string | NodeArray): JSDocOverrideTag; - updateJSDocOverrideTag(node: JSDocOverrideTag, tagName: Identifier | undefined, comment?: string | NodeArray): JSDocOverrideTag; - createJSDocThrowsTag(tagName: Identifier, typeExpression: JSDocTypeExpression | undefined, comment?: string | NodeArray): JSDocThrowsTag; - updateJSDocThrowsTag(node: JSDocThrowsTag, tagName: Identifier | undefined, typeExpression: JSDocTypeExpression | undefined, comment?: string | NodeArray | undefined): JSDocThrowsTag; - createJSDocSatisfiesTag(tagName: Identifier | undefined, typeExpression: JSDocTypeExpression, comment?: string | NodeArray): JSDocSatisfiesTag; - updateJSDocSatisfiesTag(node: JSDocSatisfiesTag, tagName: Identifier | undefined, typeExpression: JSDocTypeExpression, comment: string | NodeArray | undefined): JSDocSatisfiesTag; + updateJSDocUnknownTag( + node: JSDocUnknownTag, + tagName: Identifier, + comment: string | NodeArray | undefined, + ): JSDocUnknownTag; + createJSDocDeprecatedTag( + tagName: Identifier | undefined, + comment?: string | NodeArray, + ): JSDocDeprecatedTag; + updateJSDocDeprecatedTag( + node: JSDocDeprecatedTag, + tagName: Identifier | undefined, + comment?: string | NodeArray, + ): JSDocDeprecatedTag; + createJSDocOverrideTag( + tagName: Identifier | undefined, + comment?: string | NodeArray, + ): JSDocOverrideTag; + updateJSDocOverrideTag( + node: JSDocOverrideTag, + tagName: Identifier | undefined, + comment?: string | NodeArray, + ): JSDocOverrideTag; + createJSDocThrowsTag( + tagName: Identifier, + typeExpression: JSDocTypeExpression | undefined, + comment?: string | NodeArray, + ): JSDocThrowsTag; + updateJSDocThrowsTag( + node: JSDocThrowsTag, + tagName: Identifier | undefined, + typeExpression: JSDocTypeExpression | undefined, + comment?: string | NodeArray | undefined, + ): JSDocThrowsTag; + createJSDocSatisfiesTag( + tagName: Identifier | undefined, + typeExpression: JSDocTypeExpression, + comment?: string | NodeArray, + ): JSDocSatisfiesTag; + updateJSDocSatisfiesTag( + node: JSDocSatisfiesTag, + tagName: Identifier | undefined, + typeExpression: JSDocTypeExpression, + comment: string | NodeArray | undefined, + ): JSDocSatisfiesTag; createJSDocText(text: string): JSDocText; updateJSDocText(node: JSDocText, text: string): JSDocText; - createJSDocComment(comment?: string | NodeArray | undefined, tags?: readonly JSDocTag[] | undefined): JSDoc; - updateJSDocComment(node: JSDoc, comment: string | NodeArray | undefined, tags: readonly JSDocTag[] | undefined): JSDoc; - createJsxElement(openingElement: JsxOpeningElement, children: readonly JsxChild[], closingElement: JsxClosingElement): JsxElement; - updateJsxElement(node: JsxElement, openingElement: JsxOpeningElement, children: readonly JsxChild[], closingElement: JsxClosingElement): JsxElement; - createJsxSelfClosingElement(tagName: JsxTagNameExpression, typeArguments: readonly TypeNode[] | undefined, attributes: JsxAttributes): JsxSelfClosingElement; - updateJsxSelfClosingElement(node: JsxSelfClosingElement, tagName: JsxTagNameExpression, typeArguments: readonly TypeNode[] | undefined, attributes: JsxAttributes): JsxSelfClosingElement; - createJsxOpeningElement(tagName: JsxTagNameExpression, typeArguments: readonly TypeNode[] | undefined, attributes: JsxAttributes): JsxOpeningElement; - updateJsxOpeningElement(node: JsxOpeningElement, tagName: JsxTagNameExpression, typeArguments: readonly TypeNode[] | undefined, attributes: JsxAttributes): JsxOpeningElement; + createJSDocComment( + comment?: string | NodeArray | undefined, + tags?: readonly JSDocTag[] | undefined, + ): JSDoc; + updateJSDocComment( + node: JSDoc, + comment: string | NodeArray | undefined, + tags: readonly JSDocTag[] | undefined, + ): JSDoc; + createJsxElement( + openingElement: JsxOpeningElement, + children: readonly JsxChild[], + closingElement: JsxClosingElement, + ): JsxElement; + updateJsxElement( + node: JsxElement, + openingElement: JsxOpeningElement, + children: readonly JsxChild[], + closingElement: JsxClosingElement, + ): JsxElement; + createJsxSelfClosingElement( + tagName: JsxTagNameExpression, + typeArguments: readonly TypeNode[] | undefined, + attributes: JsxAttributes, + ): JsxSelfClosingElement; + updateJsxSelfClosingElement( + node: JsxSelfClosingElement, + tagName: JsxTagNameExpression, + typeArguments: readonly TypeNode[] | undefined, + attributes: JsxAttributes, + ): JsxSelfClosingElement; + createJsxOpeningElement( + tagName: JsxTagNameExpression, + typeArguments: readonly TypeNode[] | undefined, + attributes: JsxAttributes, + ): JsxOpeningElement; + updateJsxOpeningElement( + node: JsxOpeningElement, + tagName: JsxTagNameExpression, + typeArguments: readonly TypeNode[] | undefined, + attributes: JsxAttributes, + ): JsxOpeningElement; createJsxClosingElement(tagName: JsxTagNameExpression): JsxClosingElement; updateJsxClosingElement(node: JsxClosingElement, tagName: JsxTagNameExpression): JsxClosingElement; - createJsxFragment(openingFragment: JsxOpeningFragment, children: readonly JsxChild[], closingFragment: JsxClosingFragment): JsxFragment; + createJsxFragment( + openingFragment: JsxOpeningFragment, + children: readonly JsxChild[], + closingFragment: JsxClosingFragment, + ): JsxFragment; createJsxText(text: string, containsOnlyTriviaWhiteSpaces?: boolean): JsxText; updateJsxText(node: JsxText, text: string, containsOnlyTriviaWhiteSpaces?: boolean): JsxText; createJsxOpeningFragment(): JsxOpeningFragment; createJsxJsxClosingFragment(): JsxClosingFragment; - updateJsxFragment(node: JsxFragment, openingFragment: JsxOpeningFragment, children: readonly JsxChild[], closingFragment: JsxClosingFragment): JsxFragment; + updateJsxFragment( + node: JsxFragment, + openingFragment: JsxOpeningFragment, + children: readonly JsxChild[], + closingFragment: JsxClosingFragment, + ): JsxFragment; createJsxAttribute(name: JsxAttributeName, initializer: JsxAttributeValue | undefined): JsxAttribute; - updateJsxAttribute(node: JsxAttribute, name: JsxAttributeName, initializer: JsxAttributeValue | undefined): JsxAttribute; + updateJsxAttribute( + node: JsxAttribute, + name: JsxAttributeName, + initializer: JsxAttributeValue | undefined, + ): JsxAttribute; createJsxAttributes(properties: readonly JsxAttributeLike[]): JsxAttributes; updateJsxAttributes(node: JsxAttributes, properties: readonly JsxAttributeLike[]): JsxAttributes; createJsxSpreadAttribute(expression: Expression): JsxSpreadAttribute; updateJsxSpreadAttribute(node: JsxSpreadAttribute, expression: Expression): JsxSpreadAttribute; - createJsxExpression(dotDotDotToken: DotDotDotToken | undefined, expression: Expression | undefined): JsxExpression; + createJsxExpression( + dotDotDotToken: DotDotDotToken | undefined, + expression: Expression | undefined, + ): JsxExpression; updateJsxExpression(node: JsxExpression, expression: Expression | undefined): JsxExpression; createJsxNamespacedName(namespace: Identifier, name: Identifier): JsxNamespacedName; updateJsxNamespacedName(node: JsxNamespacedName, namespace: Identifier, name: Identifier): JsxNamespacedName; @@ -4182,31 +5591,77 @@ declare namespace ts { updateCaseClause(node: CaseClause, expression: Expression, statements: readonly Statement[]): CaseClause; createDefaultClause(statements: readonly Statement[]): DefaultClause; updateDefaultClause(node: DefaultClause, statements: readonly Statement[]): DefaultClause; - createHeritageClause(token: HeritageClause["token"], types: readonly ExpressionWithTypeArguments[]): HeritageClause; + createHeritageClause( + token: HeritageClause["token"], + types: readonly ExpressionWithTypeArguments[], + ): HeritageClause; updateHeritageClause(node: HeritageClause, types: readonly ExpressionWithTypeArguments[]): HeritageClause; - createCatchClause(variableDeclaration: string | BindingName | VariableDeclaration | undefined, block: Block): CatchClause; - updateCatchClause(node: CatchClause, variableDeclaration: VariableDeclaration | undefined, block: Block): CatchClause; + createCatchClause( + variableDeclaration: string | BindingName | VariableDeclaration | undefined, + block: Block, + ): CatchClause; + updateCatchClause( + node: CatchClause, + variableDeclaration: VariableDeclaration | undefined, + block: Block, + ): CatchClause; createPropertyAssignment(name: string | PropertyName, initializer: Expression): PropertyAssignment; - updatePropertyAssignment(node: PropertyAssignment, name: PropertyName, initializer: Expression): PropertyAssignment; - createShorthandPropertyAssignment(name: string | Identifier, objectAssignmentInitializer?: Expression): ShorthandPropertyAssignment; - updateShorthandPropertyAssignment(node: ShorthandPropertyAssignment, name: Identifier, objectAssignmentInitializer: Expression | undefined): ShorthandPropertyAssignment; + updatePropertyAssignment( + node: PropertyAssignment, + name: PropertyName, + initializer: Expression, + ): PropertyAssignment; + createShorthandPropertyAssignment( + name: string | Identifier, + objectAssignmentInitializer?: Expression, + ): ShorthandPropertyAssignment; + updateShorthandPropertyAssignment( + node: ShorthandPropertyAssignment, + name: Identifier, + objectAssignmentInitializer: Expression | undefined, + ): ShorthandPropertyAssignment; createSpreadAssignment(expression: Expression): SpreadAssignment; updateSpreadAssignment(node: SpreadAssignment, expression: Expression): SpreadAssignment; createEnumMember(name: string | PropertyName, initializer?: Expression): EnumMember; updateEnumMember(node: EnumMember, name: PropertyName, initializer: Expression | undefined): EnumMember; - createSourceFile(statements: readonly Statement[], endOfFileToken: EndOfFileToken, flags: NodeFlags): SourceFile; - updateSourceFile(node: SourceFile, statements: readonly Statement[], isDeclarationFile?: boolean, referencedFiles?: readonly FileReference[], typeReferences?: readonly FileReference[], hasNoDefaultLib?: boolean, libReferences?: readonly FileReference[]): SourceFile; + createSourceFile( + statements: readonly Statement[], + endOfFileToken: EndOfFileToken, + flags: NodeFlags, + ): SourceFile; + updateSourceFile( + node: SourceFile, + statements: readonly Statement[], + isDeclarationFile?: boolean, + referencedFiles?: readonly FileReference[], + typeReferences?: readonly FileReference[], + hasNoDefaultLib?: boolean, + libReferences?: readonly FileReference[], + ): SourceFile; createNotEmittedStatement(original: Node): NotEmittedStatement; createPartiallyEmittedExpression(expression: Expression, original?: Node): PartiallyEmittedExpression; - updatePartiallyEmittedExpression(node: PartiallyEmittedExpression, expression: Expression): PartiallyEmittedExpression; + updatePartiallyEmittedExpression( + node: PartiallyEmittedExpression, + expression: Expression, + ): PartiallyEmittedExpression; createCommaListExpression(elements: readonly Expression[]): CommaListExpression; updateCommaListExpression(node: CommaListExpression, elements: readonly Expression[]): CommaListExpression; createBundle(sourceFiles: readonly SourceFile[]): Bundle; - /** @deprecated*/ createBundle(sourceFiles: readonly SourceFile[], prepends?: readonly (UnparsedSource | InputFiles)[]): Bundle; + /** @deprecated*/ createBundle( + sourceFiles: readonly SourceFile[], + prepends?: readonly (UnparsedSource | InputFiles)[], + ): Bundle; updateBundle(node: Bundle, sourceFiles: readonly SourceFile[]): Bundle; - /** @deprecated*/ updateBundle(node: Bundle, sourceFiles: readonly SourceFile[], prepends?: readonly (UnparsedSource | InputFiles)[]): Bundle; + /** @deprecated*/ updateBundle( + node: Bundle, + sourceFiles: readonly SourceFile[], + prepends?: readonly (UnparsedSource | InputFiles)[], + ): Bundle; createComma(left: Expression, right: Expression): BinaryExpression; - createAssignment(left: ObjectLiteralExpression | ArrayLiteralExpression, right: Expression): DestructuringAssignment; + createAssignment( + left: ObjectLiteralExpression | ArrayLiteralExpression, + right: Expression, + ): DestructuringAssignment; createAssignment(left: Expression, right: Expression): AssignmentExpression; createLogicalOr(left: Expression, right: Expression): BinaryExpression; createLogicalAnd(left: Expression, right: Expression): BinaryExpression; @@ -4239,13 +5694,25 @@ declare namespace ts { createPostfixIncrement(operand: Expression): PostfixUnaryExpression; createPostfixDecrement(operand: Expression): PostfixUnaryExpression; createImmediatelyInvokedFunctionExpression(statements: readonly Statement[]): CallExpression; - createImmediatelyInvokedFunctionExpression(statements: readonly Statement[], param: ParameterDeclaration, paramValue: Expression): CallExpression; + createImmediatelyInvokedFunctionExpression( + statements: readonly Statement[], + param: ParameterDeclaration, + paramValue: Expression, + ): CallExpression; createImmediatelyInvokedArrowFunction(statements: readonly Statement[]): ImmediatelyInvokedArrowFunction; - createImmediatelyInvokedArrowFunction(statements: readonly Statement[], param: ParameterDeclaration, paramValue: Expression): ImmediatelyInvokedArrowFunction; + createImmediatelyInvokedArrowFunction( + statements: readonly Statement[], + param: ParameterDeclaration, + paramValue: Expression, + ): ImmediatelyInvokedArrowFunction; createVoidZero(): VoidExpression; createExportDefault(expression: Expression): ExportAssignment; createExternalModuleExport(exportName: Identifier): ExportDeclaration; - restoreOuterExpressions(outerExpression: Expression | undefined, innerExpression: Expression, kinds?: OuterExpressionKinds): Expression; + restoreOuterExpressions( + outerExpression: Expression | undefined, + innerExpression: Expression, + kinds?: OuterExpressionKinds, + ): Expression; } interface CoreTransformationContext { readonly factory: NodeFactory; @@ -4343,7 +5810,9 @@ declare namespace ts { /** * A function that accepts and possibly transforms a node. */ - type Visitor = (node: TIn) => VisitResult; + type Visitor = ( + node: TIn, + ) => VisitResult; /** * A function that walks a node using the given visitor, lifting node arrays into single nodes, * returning an node which satisfies the test. @@ -4357,8 +5826,18 @@ declare namespace ts { * For the canonical implementation of this type, @see {visitNode}. */ interface NodeVisitor { - (node: TIn, visitor: Visitor, TVisited>, test: (node: Node) => node is TOut, lift?: (node: readonly Node[]) => Node): TOut | (TIn & undefined) | (TVisited & undefined); - (node: TIn, visitor: Visitor, TVisited>, test?: (node: Node) => boolean, lift?: (node: readonly Node[]) => Node): Node | (TIn & undefined) | (TVisited & undefined); + ( + node: TIn, + visitor: Visitor, TVisited>, + test: (node: Node) => node is TOut, + lift?: (node: readonly Node[]) => Node, + ): TOut | (TIn & undefined) | (TVisited & undefined); + ( + node: TIn, + visitor: Visitor, TVisited>, + test?: (node: Node) => boolean, + lift?: (node: readonly Node[]) => Node, + ): Node | (TIn & undefined) | (TVisited & undefined); } /** * A function that walks a node array using the given visitor, returning an array whose contents satisfy the test. @@ -4372,8 +5851,20 @@ declare namespace ts { * For the canonical implementation of this type, @see {visitNodes}. */ interface NodesVisitor { - | undefined, TOut extends Node>(nodes: TInArray, visitor: Visitor, test: (node: Node) => node is TOut, start?: number, count?: number): NodeArray | (TInArray & undefined); - | undefined>(nodes: TInArray, visitor: Visitor, test?: (node: Node) => boolean, start?: number, count?: number): NodeArray | (TInArray & undefined); + | undefined, TOut extends Node>( + nodes: TInArray, + visitor: Visitor, + test: (node: Node) => node is TOut, + start?: number, + count?: number, + ): NodeArray | (TInArray & undefined); + | undefined>( + nodes: TInArray, + visitor: Visitor, + test?: (node: Node) => boolean, + start?: number, + count?: number, + ): NodeArray | (TInArray & undefined); } type VisitResult = T | readonly Node[]; interface Printer { @@ -4593,7 +6084,17 @@ declare namespace ts { } type FileWatcherCallback = (fileName: string, eventKind: FileWatcherEventKind, modifiedTime?: Date) => void; type DirectoryWatcherCallback = (fileName: string) => void; - type BufferEncoding = "ascii" | "utf8" | "utf-8" | "utf16le" | "ucs2" | "ucs-2" | "base64" | "latin1" | "binary" | "hex"; + type BufferEncoding = + | "ascii" + | "utf8" + | "utf-8" + | "utf16le" + | "ucs2" + | "ucs-2" + | "base64" + | "latin1" + | "binary" + | "hex"; interface System { args: string[]; newLine: string; @@ -4608,8 +6109,18 @@ declare namespace ts { * @pollingInterval - this parameter is used in polling-based watchers and ignored in watchers that * use native OS file watching */ - watchFile?(path: string, callback: FileWatcherCallback, pollingInterval?: number, options?: WatchOptions): FileWatcher; - watchDirectory?(path: string, callback: DirectoryWatcherCallback, recursive?: boolean, options?: WatchOptions): FileWatcher; + watchFile?( + path: string, + callback: FileWatcherCallback, + pollingInterval?: number, + options?: WatchOptions, + ): FileWatcher; + watchDirectory?( + path: string, + callback: DirectoryWatcherCallback, + recursive?: boolean, + options?: WatchOptions, + ): FileWatcher; resolvePath(path: string): string; fileExists(path: string): boolean; directoryExists(path: string): boolean; @@ -4617,7 +6128,13 @@ declare namespace ts { getExecutingFilePath(): string; getCurrentDirectory(): string; getDirectories(path: string): string[]; - readDirectory(path: string, extensions?: readonly string[], exclude?: readonly string[], include?: readonly string[], depth?: number): string[]; + readDirectory( + path: string, + extensions?: readonly string[], + exclude?: readonly string[], + include?: readonly string[], + depth?: number, + ): string[]; getModifiedTime?(path: string): Date | undefined; setModifiedTime?(path: string, time: Date): void; deleteFile?(path: string): void; @@ -4648,19 +6165,61 @@ declare namespace ts { function isWhiteSpaceSingleLine(ch: number): boolean; function isLineBreak(ch: number): boolean; function couldStartTrivia(text: string, pos: number): boolean; - function forEachLeadingCommentRange(text: string, pos: number, cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean) => U): U | undefined; - function forEachLeadingCommentRange(text: string, pos: number, cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean, state: T) => U, state: T): U | undefined; - function forEachTrailingCommentRange(text: string, pos: number, cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean) => U): U | undefined; - function forEachTrailingCommentRange(text: string, pos: number, cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean, state: T) => U, state: T): U | undefined; - function reduceEachLeadingCommentRange(text: string, pos: number, cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean, state: T) => U, state: T, initial: U): U | undefined; - function reduceEachTrailingCommentRange(text: string, pos: number, cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean, state: T) => U, state: T, initial: U): U | undefined; + function forEachLeadingCommentRange( + text: string, + pos: number, + cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean) => U, + ): U | undefined; + function forEachLeadingCommentRange( + text: string, + pos: number, + cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean, state: T) => U, + state: T, + ): U | undefined; + function forEachTrailingCommentRange( + text: string, + pos: number, + cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean) => U, + ): U | undefined; + function forEachTrailingCommentRange( + text: string, + pos: number, + cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean, state: T) => U, + state: T, + ): U | undefined; + function reduceEachLeadingCommentRange( + text: string, + pos: number, + cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean, state: T) => U, + state: T, + initial: U, + ): U | undefined; + function reduceEachTrailingCommentRange( + text: string, + pos: number, + cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean, state: T) => U, + state: T, + initial: U, + ): U | undefined; function getLeadingCommentRanges(text: string, pos: number): CommentRange[] | undefined; function getTrailingCommentRanges(text: string, pos: number): CommentRange[] | undefined; /** Optionally, get the shebang */ function getShebang(text: string): string | undefined; function isIdentifierStart(ch: number, languageVersion: ScriptTarget | undefined): boolean; - function isIdentifierPart(ch: number, languageVersion: ScriptTarget | undefined, identifierVariant?: LanguageVariant): boolean; - function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean, languageVariant?: LanguageVariant, textInitial?: string, onError?: ErrorCallback, start?: number, length?: number): Scanner; + function isIdentifierPart( + ch: number, + languageVersion: ScriptTarget | undefined, + identifierVariant?: LanguageVariant, + ): boolean; + function createScanner( + languageVersion: ScriptTarget, + skipTrivia: boolean, + languageVariant?: LanguageVariant, + textInitial?: string, + onError?: ErrorCallback, + start?: number, + length?: number, + ): Scanner; type ErrorCallback = (message: DiagnosticMessage, length: number, arg0?: any) => void; interface Scanner { /** @deprecated use {@link getTokenFullStart} */ @@ -4758,14 +6317,20 @@ declare namespace ts { function getOriginalNode(node: Node): Node; function getOriginalNode(node: Node, nodeTest: (node: Node) => node is T): T; function getOriginalNode(node: Node | undefined): Node | undefined; - function getOriginalNode(node: Node | undefined, nodeTest: (node: Node) => node is T): T | undefined; + function getOriginalNode( + node: Node | undefined, + nodeTest: (node: Node) => node is T, + ): T | undefined; /** * Iterates through the parent chain of a node and performs the callback on each parent until the callback * returns a truthy value, then returns that value. * If no such value is found, it applies the callback until the parent pointer is undefined or the callback returns "quit" * At that point findAncestor returns undefined. */ - function findAncestor(node: Node | undefined, callback: (element: Node) => element is T): T | undefined; + function findAncestor( + node: Node | undefined, + callback: (element: Node) => element is T, + ): T | undefined; function findAncestor(node: Node | undefined, callback: (element: Node) => boolean | "quit"): Node | undefined; /** * Gets a value indicating whether a node originated in the parse tree. @@ -4904,7 +6469,9 @@ declare namespace ts { * /** @type {Id} / * function id(x) { return x } */ - function getEffectiveTypeParameterDeclarations(node: DeclarationWithTypeParameters): readonly TypeParameterDeclaration[]; + function getEffectiveTypeParameterDeclarations( + node: DeclarationWithTypeParameters, + ): readonly TypeParameterDeclaration[]; function getEffectiveConstraintOfTypeParameter(node: TypeParameterDeclaration): TypeNode | undefined; function isMemberName(node: Node): node is MemberName; function isPropertyAccessChain(node: Node): node is PropertyAccessChain; @@ -4970,14 +6537,19 @@ declare namespace ts { function isCallOrNewExpression(node: Node): node is CallExpression | NewExpression; function isTemplateLiteral(node: Node): node is TemplateLiteral; function isLeftHandSideExpression(node: Node): node is LeftHandSideExpression; - function isLiteralTypeLiteral(node: Node): node is NullLiteral | BooleanLiteral | LiteralExpression | PrefixUnaryExpression; + function isLiteralTypeLiteral( + node: Node, + ): node is NullLiteral | BooleanLiteral | LiteralExpression | PrefixUnaryExpression; /** * Determines whether a node is an expression based only on its kind. */ function isExpression(node: Node): node is Expression; function isAssertionExpression(node: Node): node is AssertionExpression; function isIterationStatement(node: Node, lookInLabeledStatements: false): node is IterationStatement; - function isIterationStatement(node: Node, lookInLabeledStatements: boolean): node is IterationStatement | LabeledStatement; + function isIterationStatement( + node: Node, + lookInLabeledStatements: boolean, + ): node is IterationStatement | LabeledStatement; function isConciseBody(node: Node): node is ConciseBody; function isForInitializer(node: Node): node is ForInitializer; function isModuleBody(node: Node): node is ModuleBody; @@ -5029,19 +6601,45 @@ declare namespace ts { /** @deprecated */ function createUnparsedSourceFile(text: string): UnparsedSource; /** @deprecated */ - function createUnparsedSourceFile(inputFile: InputFiles, type: "js" | "dts", stripInternal?: boolean): UnparsedSource; + function createUnparsedSourceFile( + inputFile: InputFiles, + type: "js" | "dts", + stripInternal?: boolean, + ): UnparsedSource; /** @deprecated */ - function createUnparsedSourceFile(text: string, mapPath: string | undefined, map: string | undefined): UnparsedSource; + function createUnparsedSourceFile( + text: string, + mapPath: string | undefined, + map: string | undefined, + ): UnparsedSource; /** @deprecated */ function createInputFiles(javascriptText: string, declarationText: string): InputFiles; /** @deprecated */ - function createInputFiles(javascriptText: string, declarationText: string, javascriptMapPath: string | undefined, javascriptMapText: string | undefined, declarationMapPath: string | undefined, declarationMapText: string | undefined): InputFiles; + function createInputFiles( + javascriptText: string, + declarationText: string, + javascriptMapPath: string | undefined, + javascriptMapText: string | undefined, + declarationMapPath: string | undefined, + declarationMapText: string | undefined, + ): InputFiles; /** @deprecated */ - function createInputFiles(readFileText: (path: string) => string | undefined, javascriptPath: string, javascriptMapPath: string | undefined, declarationPath: string, declarationMapPath: string | undefined, buildInfoPath: string | undefined): InputFiles; + function createInputFiles( + readFileText: (path: string) => string | undefined, + javascriptPath: string, + javascriptMapPath: string | undefined, + declarationPath: string, + declarationMapPath: string | undefined, + buildInfoPath: string | undefined, + ): InputFiles; /** * Create an external source map source file reference */ - function createSourceMapSource(fileName: string, text: string, skipTrivia?: (pos: number) => number): SourceMapSource; + function createSourceMapSource( + fileName: string, + text: string, + skipTrivia?: (pos: number) => number, + ): SourceMapSource; function setOriginalNode(node: T, original: Node | undefined): T; const factory: NodeFactory; /** @@ -5079,10 +6677,20 @@ declare namespace ts { function setCommentRange(node: T, range: TextRange): T; function getSyntheticLeadingComments(node: Node): SynthesizedComment[] | undefined; function setSyntheticLeadingComments(node: T, comments: SynthesizedComment[] | undefined): T; - function addSyntheticLeadingComment(node: T, kind: SyntaxKind.SingleLineCommentTrivia | SyntaxKind.MultiLineCommentTrivia, text: string, hasTrailingNewLine?: boolean): T; + function addSyntheticLeadingComment( + node: T, + kind: SyntaxKind.SingleLineCommentTrivia | SyntaxKind.MultiLineCommentTrivia, + text: string, + hasTrailingNewLine?: boolean, + ): T; function getSyntheticTrailingComments(node: Node): SynthesizedComment[] | undefined; function setSyntheticTrailingComments(node: T, comments: SynthesizedComment[] | undefined): T; - function addSyntheticTrailingComment(node: T, kind: SyntaxKind.SingleLineCommentTrivia | SyntaxKind.MultiLineCommentTrivia, text: string, hasTrailingNewLine?: boolean): T; + function addSyntheticTrailingComment( + node: T, + kind: SyntaxKind.SingleLineCommentTrivia | SyntaxKind.MultiLineCommentTrivia, + text: string, + hasTrailingNewLine?: boolean, + ): T; function moveSyntheticComments(node: T, original: Node): T; /** * Gets the constant value to emit for an expression representing an enum. @@ -5347,8 +6955,18 @@ declare namespace ts { * @remarks `forEachChild` must visit the children of a node in the order * that they appear in the source code. The language service depends on this property to locate nodes by position. */ - function forEachChild(node: Node, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined; - function createSourceFile(fileName: string, sourceText: string, languageVersionOrOptions: ScriptTarget | CreateSourceFileOptions, setParentNodes?: boolean, scriptKind?: ScriptKind): SourceFile; + function forEachChild( + node: Node, + cbNode: (node: Node) => T | undefined, + cbNodes?: (nodes: NodeArray) => T | undefined, + ): T | undefined; + function createSourceFile( + fileName: string, + sourceText: string, + languageVersionOrOptions: ScriptTarget | CreateSourceFileOptions, + setParentNodes?: boolean, + scriptKind?: ScriptKind, + ): SourceFile; function parseIsolatedEntityName(text: string, languageVersion: ScriptTarget): EntityName | undefined; /** * Parse json text into SyntaxTree and return node and parse errors if any @@ -5357,7 +6975,12 @@ declare namespace ts { */ function parseJsonText(fileName: string, sourceText: string): JsonSourceFile; function isExternalModule(file: SourceFile): boolean; - function updateSourceFile(sourceFile: SourceFile, newText: string, textChangeRange: TextChangeRange, aggressiveChecks?: boolean): SourceFile; + function updateSourceFile( + sourceFile: SourceFile, + newText: string, + textChangeRange: TextChangeRange, + aggressiveChecks?: boolean, + ): SourceFile; interface CreateSourceFileOptions { languageVersion: ScriptTarget; /** @@ -5373,11 +6996,21 @@ declare namespace ts { */ setExternalModuleIndicator?: (file: SourceFile) => void; } - function parseCommandLine(commandLine: readonly string[], readFile?: (path: string) => string | undefined): ParsedCommandLine; + function parseCommandLine( + commandLine: readonly string[], + readFile?: (path: string) => string | undefined, + ): ParsedCommandLine; /** * Reads the config file, reports errors if any and exits if the config file cannot be found */ - function getParsedCommandLineOfConfigFile(configFileName: string, optionsToExtend: CompilerOptions | undefined, host: ParseConfigFileHost, extendedConfigCache?: Map, watchOptionsToExtend?: WatchOptions, extraFileExtensions?: readonly FileExtensionInfo[]): ParsedCommandLine | undefined; + function getParsedCommandLineOfConfigFile( + configFileName: string, + optionsToExtend: CompilerOptions | undefined, + host: ParseConfigFileHost, + extendedConfigCache?: Map, + watchOptionsToExtend?: WatchOptions, + extraFileExtensions?: readonly FileExtensionInfo[], + ): ParsedCommandLine | undefined; /** * Read tsconfig.json file * @param fileName The path to the config file @@ -5411,7 +7044,17 @@ declare namespace ts { * @param basePath A root directory to resolve relative path entries in the config * file to. e.g. outDir */ - function parseJsonConfigFileContent(json: any, host: ParseConfigHost, basePath: string, existingOptions?: CompilerOptions, configFileName?: string, resolutionStack?: Path[], extraFileExtensions?: readonly FileExtensionInfo[], extendedConfigCache?: Map, existingWatchOptions?: WatchOptions): ParsedCommandLine; + function parseJsonConfigFileContent( + json: any, + host: ParseConfigHost, + basePath: string, + existingOptions?: CompilerOptions, + configFileName?: string, + resolutionStack?: Path[], + extraFileExtensions?: readonly FileExtensionInfo[], + extendedConfigCache?: Map, + existingWatchOptions?: WatchOptions, + ): ParsedCommandLine; /** * Parse the contents of a config file (tsconfig.json). * @param jsonNode The contents of the config file to parse @@ -5419,7 +7062,17 @@ declare namespace ts { * @param basePath A root directory to resolve relative path entries in the config * file to. e.g. outDir */ - function parseJsonSourceFileConfigFileContent(sourceFile: TsConfigSourceFile, host: ParseConfigHost, basePath: string, existingOptions?: CompilerOptions, configFileName?: string, resolutionStack?: Path[], extraFileExtensions?: readonly FileExtensionInfo[], extendedConfigCache?: Map, existingWatchOptions?: WatchOptions): ParsedCommandLine; + function parseJsonSourceFileConfigFileContent( + sourceFile: TsConfigSourceFile, + host: ParseConfigHost, + basePath: string, + existingOptions?: CompilerOptions, + configFileName?: string, + resolutionStack?: Path[], + extraFileExtensions?: readonly FileExtensionInfo[], + extendedConfigCache?: Map, + existingWatchOptions?: WatchOptions, + ): ParsedCommandLine; function convertCompilerOptionsFromJson(jsonOptions: any, basePath: string, configFileName?: string): { options: CompilerOptions; errors: Diagnostic[]; @@ -5464,7 +7117,15 @@ declare namespace ts { * This is possible in case if resolution is performed for directives specified via 'types' parameter. In this case initial path for secondary lookups * is assumed to be the same as root directory of the project. */ - function resolveTypeReferenceDirective(typeReferenceDirectiveName: string, containingFile: string | undefined, options: CompilerOptions, host: ModuleResolutionHost, redirectedReference?: ResolvedProjectReference, cache?: TypeReferenceDirectiveResolutionCache, resolutionMode?: ResolutionMode): ResolvedTypeReferenceDirectiveWithFailedLookupLocations; + function resolveTypeReferenceDirective( + typeReferenceDirectiveName: string, + containingFile: string | undefined, + options: CompilerOptions, + host: ModuleResolutionHost, + redirectedReference?: ResolvedProjectReference, + cache?: TypeReferenceDirectiveResolutionCache, + resolutionMode?: ResolutionMode, + ): ResolvedTypeReferenceDirectiveWithFailedLookupLocations; /** * Given a set of options, returns the set of type directive names * that should be included for this program automatically. @@ -5474,14 +7135,63 @@ declare namespace ts { * this list is only the set of defaults that are implicitly included. */ function getAutomaticTypeDirectiveNames(options: CompilerOptions, host: ModuleResolutionHost): string[]; - function createModuleResolutionCache(currentDirectory: string, getCanonicalFileName: (s: string) => string, options?: CompilerOptions, packageJsonInfoCache?: PackageJsonInfoCache): ModuleResolutionCache; - function createTypeReferenceDirectiveResolutionCache(currentDirectory: string, getCanonicalFileName: (s: string) => string, options?: CompilerOptions, packageJsonInfoCache?: PackageJsonInfoCache): TypeReferenceDirectiveResolutionCache; - function resolveModuleNameFromCache(moduleName: string, containingFile: string, cache: ModuleResolutionCache, mode?: ResolutionMode): ResolvedModuleWithFailedLookupLocations | undefined; - function resolveModuleName(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache?: ModuleResolutionCache, redirectedReference?: ResolvedProjectReference, resolutionMode?: ResolutionMode): ResolvedModuleWithFailedLookupLocations; - function bundlerModuleNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache?: ModuleResolutionCache, redirectedReference?: ResolvedProjectReference): ResolvedModuleWithFailedLookupLocations; - function nodeModuleNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache?: ModuleResolutionCache, redirectedReference?: ResolvedProjectReference): ResolvedModuleWithFailedLookupLocations; - function classicNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache?: NonRelativeModuleNameResolutionCache, redirectedReference?: ResolvedProjectReference): ResolvedModuleWithFailedLookupLocations; - interface TypeReferenceDirectiveResolutionCache extends PerDirectoryResolutionCache, NonRelativeNameResolutionCache, PackageJsonInfoCache { + function createModuleResolutionCache( + currentDirectory: string, + getCanonicalFileName: (s: string) => string, + options?: CompilerOptions, + packageJsonInfoCache?: PackageJsonInfoCache, + ): ModuleResolutionCache; + function createTypeReferenceDirectiveResolutionCache( + currentDirectory: string, + getCanonicalFileName: (s: string) => string, + options?: CompilerOptions, + packageJsonInfoCache?: PackageJsonInfoCache, + ): TypeReferenceDirectiveResolutionCache; + function resolveModuleNameFromCache( + moduleName: string, + containingFile: string, + cache: ModuleResolutionCache, + mode?: ResolutionMode, + ): ResolvedModuleWithFailedLookupLocations | undefined; + function resolveModuleName( + moduleName: string, + containingFile: string, + compilerOptions: CompilerOptions, + host: ModuleResolutionHost, + cache?: ModuleResolutionCache, + redirectedReference?: ResolvedProjectReference, + resolutionMode?: ResolutionMode, + ): ResolvedModuleWithFailedLookupLocations; + function bundlerModuleNameResolver( + moduleName: string, + containingFile: string, + compilerOptions: CompilerOptions, + host: ModuleResolutionHost, + cache?: ModuleResolutionCache, + redirectedReference?: ResolvedProjectReference, + ): ResolvedModuleWithFailedLookupLocations; + function nodeModuleNameResolver( + moduleName: string, + containingFile: string, + compilerOptions: CompilerOptions, + host: ModuleResolutionHost, + cache?: ModuleResolutionCache, + redirectedReference?: ResolvedProjectReference, + ): ResolvedModuleWithFailedLookupLocations; + function classicNameResolver( + moduleName: string, + containingFile: string, + compilerOptions: CompilerOptions, + host: ModuleResolutionHost, + cache?: NonRelativeModuleNameResolutionCache, + redirectedReference?: ResolvedProjectReference, + ): ResolvedModuleWithFailedLookupLocations; + interface TypeReferenceDirectiveResolutionCache + extends + PerDirectoryResolutionCache, + NonRelativeNameResolutionCache, + PackageJsonInfoCache + { } interface ModeAwareCache { get(key: string, mode: ResolutionMode): T | undefined; @@ -5496,8 +7206,16 @@ declare namespace ts { * This assumes that any module id will have the same resolution for sibling files located in the same folder. */ interface PerDirectoryResolutionCache { - getFromDirectoryCache(name: string, mode: ResolutionMode, directoryName: string, redirectedReference: ResolvedProjectReference | undefined): T | undefined; - getOrCreateCacheForDirectory(directoryName: string, redirectedReference?: ResolvedProjectReference): ModeAwareCache; + getFromDirectoryCache( + name: string, + mode: ResolutionMode, + directoryName: string, + redirectedReference: ResolvedProjectReference | undefined, + ): T | undefined; + getOrCreateCacheForDirectory( + directoryName: string, + redirectedReference?: ResolvedProjectReference, + ): ModeAwareCache; clear(): void; /** * Updates with the current compilerOptions the cache will operate with. @@ -5506,8 +7224,17 @@ declare namespace ts { update(options: CompilerOptions): void; } interface NonRelativeNameResolutionCache { - getFromNonRelativeNameCache(nonRelativeName: string, mode: ResolutionMode, directoryName: string, redirectedReference: ResolvedProjectReference | undefined): T | undefined; - getOrCreateCacheForNonRelativeName(nonRelativeName: string, mode: ResolutionMode, redirectedReference?: ResolvedProjectReference): PerNonRelativeNameCache; + getFromNonRelativeNameCache( + nonRelativeName: string, + mode: ResolutionMode, + directoryName: string, + redirectedReference: ResolvedProjectReference | undefined, + ): T | undefined; + getOrCreateCacheForNonRelativeName( + nonRelativeName: string, + mode: ResolutionMode, + redirectedReference?: ResolvedProjectReference, + ): PerNonRelativeNameCache; clear(): void; /** * Updates with the current compilerOptions the cache will operate with. @@ -5519,16 +7246,27 @@ declare namespace ts { get(directory: string): T | undefined; set(directory: string, result: T): void; } - interface ModuleResolutionCache extends PerDirectoryResolutionCache, NonRelativeModuleNameResolutionCache, PackageJsonInfoCache { + interface ModuleResolutionCache + extends + PerDirectoryResolutionCache, + NonRelativeModuleNameResolutionCache, + PackageJsonInfoCache + { getPackageJsonInfoCache(): PackageJsonInfoCache; } /** * Stored map from non-relative module name to a table: directory -> result of module lookup in this directory * We support only non-relative module names because resolution of relative module names is usually more deterministic and thus less expensive. */ - interface NonRelativeModuleNameResolutionCache extends NonRelativeNameResolutionCache, PackageJsonInfoCache { + interface NonRelativeModuleNameResolutionCache + extends NonRelativeNameResolutionCache, PackageJsonInfoCache + { /** @deprecated Use getOrCreateCacheForNonRelativeName */ - getOrCreateCacheForModuleName(nonRelativeModuleName: string, mode: ResolutionMode, redirectedReference?: ResolvedProjectReference): PerModuleNameCache; + getOrCreateCacheForModuleName( + nonRelativeModuleName: string, + mode: ResolutionMode, + redirectedReference?: ResolvedProjectReference, + ): PerModuleNameCache; } interface PackageJsonInfoCache { clear(): void; @@ -5548,7 +7286,12 @@ declare namespace ts { * @param test A callback to execute to verify the Node is valid. * @param lift An optional callback to execute to lift a NodeArray into a valid Node. */ - function visitNode(node: TIn, visitor: Visitor, TVisited>, test: (node: Node) => node is TOut, lift?: (node: readonly Node[]) => Node): TOut | (TIn & undefined) | (TVisited & undefined); + function visitNode( + node: TIn, + visitor: Visitor, TVisited>, + test: (node: Node) => node is TOut, + lift?: (node: readonly Node[]) => Node, + ): TOut | (TIn & undefined) | (TVisited & undefined); /** * Visits a Node using the supplied visitor, possibly returning a new Node in its place. * @@ -5563,7 +7306,12 @@ declare namespace ts { * @param test A callback to execute to verify the Node is valid. * @param lift An optional callback to execute to lift a NodeArray into a valid Node. */ - function visitNode(node: TIn, visitor: Visitor, TVisited>, test?: (node: Node) => boolean, lift?: (node: readonly Node[]) => Node): Node | (TIn & undefined) | (TVisited & undefined); + function visitNode( + node: TIn, + visitor: Visitor, TVisited>, + test?: (node: Node) => boolean, + lift?: (node: readonly Node[]) => Node, + ): Node | (TIn & undefined) | (TVisited & undefined); /** * Visits a NodeArray using the supplied visitor, possibly returning a new NodeArray in its place. * @@ -5579,7 +7327,13 @@ declare namespace ts { * @param start An optional value indicating the starting offset at which to start visiting. * @param count An optional value indicating the maximum number of nodes to visit. */ - function visitNodes | undefined, TOut extends Node>(nodes: TInArray, visitor: Visitor, test: (node: Node) => node is TOut, start?: number, count?: number): NodeArray | (TInArray & undefined); + function visitNodes | undefined, TOut extends Node>( + nodes: TInArray, + visitor: Visitor, + test: (node: Node) => node is TOut, + start?: number, + count?: number, + ): NodeArray | (TInArray & undefined); /** * Visits a NodeArray using the supplied visitor, possibly returning a new NodeArray in its place. * @@ -5595,18 +7349,41 @@ declare namespace ts { * @param start An optional value indicating the starting offset at which to start visiting. * @param count An optional value indicating the maximum number of nodes to visit. */ - function visitNodes | undefined>(nodes: TInArray, visitor: Visitor, test?: (node: Node) => boolean, start?: number, count?: number): NodeArray | (TInArray & undefined); + function visitNodes | undefined>( + nodes: TInArray, + visitor: Visitor, + test?: (node: Node) => boolean, + start?: number, + count?: number, + ): NodeArray | (TInArray & undefined); /** * Starts a new lexical environment and visits a statement list, ending the lexical environment * and merging hoisted declarations upon completion. */ - function visitLexicalEnvironment(statements: NodeArray, visitor: Visitor, context: TransformationContext, start?: number, ensureUseStrict?: boolean, nodesVisitor?: NodesVisitor): NodeArray; + function visitLexicalEnvironment( + statements: NodeArray, + visitor: Visitor, + context: TransformationContext, + start?: number, + ensureUseStrict?: boolean, + nodesVisitor?: NodesVisitor, + ): NodeArray; /** * Starts a new lexical environment and visits a parameter list, suspending the lexical * environment upon completion. */ - function visitParameterList(nodes: NodeArray, visitor: Visitor, context: TransformationContext, nodesVisitor?: NodesVisitor): NodeArray; - function visitParameterList(nodes: NodeArray | undefined, visitor: Visitor, context: TransformationContext, nodesVisitor?: NodesVisitor): NodeArray | undefined; + function visitParameterList( + nodes: NodeArray, + visitor: Visitor, + context: TransformationContext, + nodesVisitor?: NodesVisitor, + ): NodeArray; + function visitParameterList( + nodes: NodeArray | undefined, + visitor: Visitor, + context: TransformationContext, + nodesVisitor?: NodesVisitor, + ): NodeArray | undefined; /** * Resumes a suspended lexical environment and visits a function body, ending the lexical * environment and merging hoisted declarations upon completion. @@ -5616,7 +7393,11 @@ declare namespace ts { * Resumes a suspended lexical environment and visits a function body, ending the lexical * environment and merging hoisted declarations upon completion. */ - function visitFunctionBody(node: FunctionBody | undefined, visitor: Visitor, context: TransformationContext): FunctionBody | undefined; + function visitFunctionBody( + node: FunctionBody | undefined, + visitor: Visitor, + context: TransformationContext, + ): FunctionBody | undefined; /** * Resumes a suspended lexical environment and visits a concise body, ending the lexical * environment and merging hoisted declarations upon completion. @@ -5631,7 +7412,11 @@ declare namespace ts { * @param visitor The visitor to use when visiting expressions whose result will not be discarded at runtime. * @param discardVisitor The visitor to use when visiting expressions whose result will be discarded at runtime. Defaults to {@link visitor}. */ - function visitCommaListElements(elements: NodeArray, visitor: Visitor, discardVisitor?: Visitor): NodeArray; + function visitCommaListElements( + elements: NodeArray, + visitor: Visitor, + discardVisitor?: Visitor, + ): NodeArray; /** * Visits each child of a Node using the supplied visitor, possibly returning a new Node of the same kind in its place. * @@ -5647,18 +7432,43 @@ declare namespace ts { * @param visitor The callback used to visit each child. * @param context A lexical environment context for the visitor. */ - function visitEachChild(node: T | undefined, visitor: Visitor, context: TransformationContext, nodesVisitor?: typeof visitNodes, tokenVisitor?: Visitor): T | undefined; + function visitEachChild( + node: T | undefined, + visitor: Visitor, + context: TransformationContext, + nodesVisitor?: typeof visitNodes, + tokenVisitor?: Visitor, + ): T | undefined; function getTsBuildInfoEmitOutputFilePath(options: CompilerOptions): string | undefined; - function getOutputFileNames(commandLine: ParsedCommandLine, inputFileName: string, ignoreCase: boolean): readonly string[]; + function getOutputFileNames( + commandLine: ParsedCommandLine, + inputFileName: string, + ignoreCase: boolean, + ): readonly string[]; function createPrinter(printerOptions?: PrinterOptions, handlers?: PrintHandlers): Printer; - function findConfigFile(searchPath: string, fileExists: (fileName: string) => boolean, configName?: string): string | undefined; + function findConfigFile( + searchPath: string, + fileExists: (fileName: string) => boolean, + configName?: string, + ): string | undefined; function resolveTripleslashReference(moduleName: string, containingFile: string): string; function createCompilerHost(options: CompilerOptions, setParentNodes?: boolean): CompilerHost; - function getPreEmitDiagnostics(program: Program, sourceFile?: SourceFile, cancellationToken?: CancellationToken): readonly Diagnostic[]; + function getPreEmitDiagnostics( + program: Program, + sourceFile?: SourceFile, + cancellationToken?: CancellationToken, + ): readonly Diagnostic[]; function formatDiagnostics(diagnostics: readonly Diagnostic[], host: FormatDiagnosticsHost): string; function formatDiagnostic(diagnostic: Diagnostic, host: FormatDiagnosticsHost): string; - function formatDiagnosticsWithColorAndContext(diagnostics: readonly Diagnostic[], host: FormatDiagnosticsHost): string; - function flattenDiagnosticMessageText(diag: string | DiagnosticMessageChain | undefined, newLine: string, indent?: number): string; + function formatDiagnosticsWithColorAndContext( + diagnostics: readonly Diagnostic[], + host: FormatDiagnosticsHost, + ): string; + function flattenDiagnosticMessageText( + diag: string | DiagnosticMessageChain | undefined, + newLine: string, + indent?: number, + ): string; /** * Calculates the resulting resolution mode for some reference in some file - this is generally the explicitly * provided resolution mode in the reference, unless one is not present, in which case it is the mode of the containing file. @@ -5695,7 +7505,12 @@ declare namespace ts { * @param options The compiler options to perform the analysis under - relevant options are `moduleResolution` and `traceResolution` * @returns `undefined` if the path has no relevant implied format, `ModuleKind.ESNext` for esm format, and `ModuleKind.CommonJS` for cjs format */ - function getImpliedNodeFormatForFile(fileName: Path, packageJsonInfoCache: PackageJsonInfoCache | undefined, host: ModuleResolutionHost, options: CompilerOptions): ResolutionMode; + function getImpliedNodeFormatForFile( + fileName: Path, + packageJsonInfoCache: PackageJsonInfoCache | undefined, + host: ModuleResolutionHost, + options: CompilerOptions, + ): ResolutionMode; /** * Create a new 'Program' instance. A Program is an immutable collection of 'SourceFile's and a 'CompilerOptions' * that represent a compilation unit. @@ -5721,7 +7536,13 @@ declare namespace ts { * @param configFileParsingDiagnostics - error during config file parsing * @returns A 'Program' object. */ - function createProgram(rootNames: readonly string[], options: CompilerOptions, host?: CompilerHost, oldProgram?: Program, configFileParsingDiagnostics?: readonly Diagnostic[]): Program; + function createProgram( + rootNames: readonly string[], + options: CompilerOptions, + host?: CompilerHost, + oldProgram?: Program, + configFileParsingDiagnostics?: readonly Diagnostic[], + ): Program; /** * Returns the target config filename of a project reference. * Note: The file might not exist. @@ -5744,19 +7565,55 @@ declare namespace ts { /** * Create the builder to manage semantic diagnostics and cache them */ - function createSemanticDiagnosticsBuilderProgram(newProgram: Program, host: BuilderProgramHost, oldProgram?: SemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: readonly Diagnostic[]): SemanticDiagnosticsBuilderProgram; - function createSemanticDiagnosticsBuilderProgram(rootNames: readonly string[] | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: SemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: readonly Diagnostic[], projectReferences?: readonly ProjectReference[]): SemanticDiagnosticsBuilderProgram; + function createSemanticDiagnosticsBuilderProgram( + newProgram: Program, + host: BuilderProgramHost, + oldProgram?: SemanticDiagnosticsBuilderProgram, + configFileParsingDiagnostics?: readonly Diagnostic[], + ): SemanticDiagnosticsBuilderProgram; + function createSemanticDiagnosticsBuilderProgram( + rootNames: readonly string[] | undefined, + options: CompilerOptions | undefined, + host?: CompilerHost, + oldProgram?: SemanticDiagnosticsBuilderProgram, + configFileParsingDiagnostics?: readonly Diagnostic[], + projectReferences?: readonly ProjectReference[], + ): SemanticDiagnosticsBuilderProgram; /** * Create the builder that can handle the changes in program and iterate through changed files * to emit the those files and manage semantic diagnostics cache as well */ - function createEmitAndSemanticDiagnosticsBuilderProgram(newProgram: Program, host: BuilderProgramHost, oldProgram?: EmitAndSemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: readonly Diagnostic[]): EmitAndSemanticDiagnosticsBuilderProgram; - function createEmitAndSemanticDiagnosticsBuilderProgram(rootNames: readonly string[] | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: EmitAndSemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: readonly Diagnostic[], projectReferences?: readonly ProjectReference[]): EmitAndSemanticDiagnosticsBuilderProgram; + function createEmitAndSemanticDiagnosticsBuilderProgram( + newProgram: Program, + host: BuilderProgramHost, + oldProgram?: EmitAndSemanticDiagnosticsBuilderProgram, + configFileParsingDiagnostics?: readonly Diagnostic[], + ): EmitAndSemanticDiagnosticsBuilderProgram; + function createEmitAndSemanticDiagnosticsBuilderProgram( + rootNames: readonly string[] | undefined, + options: CompilerOptions | undefined, + host?: CompilerHost, + oldProgram?: EmitAndSemanticDiagnosticsBuilderProgram, + configFileParsingDiagnostics?: readonly Diagnostic[], + projectReferences?: readonly ProjectReference[], + ): EmitAndSemanticDiagnosticsBuilderProgram; /** * Creates a builder thats just abstraction over program and can be used with watch */ - function createAbstractBuilder(newProgram: Program, host: BuilderProgramHost, oldProgram?: BuilderProgram, configFileParsingDiagnostics?: readonly Diagnostic[]): BuilderProgram; - function createAbstractBuilder(rootNames: readonly string[] | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: BuilderProgram, configFileParsingDiagnostics?: readonly Diagnostic[], projectReferences?: readonly ProjectReference[]): BuilderProgram; + function createAbstractBuilder( + newProgram: Program, + host: BuilderProgramHost, + oldProgram?: BuilderProgram, + configFileParsingDiagnostics?: readonly Diagnostic[], + ): BuilderProgram; + function createAbstractBuilder( + rootNames: readonly string[] | undefined, + options: CompilerOptions | undefined, + host?: CompilerHost, + oldProgram?: BuilderProgram, + configFileParsingDiagnostics?: readonly Diagnostic[], + projectReferences?: readonly ProjectReference[], + ): BuilderProgram; type AffectedFileResult = { result: T; affected: SourceFile | Program; @@ -5811,7 +7668,10 @@ declare namespace ts { /** * Get the declaration diagnostics, for all source files if source file is not supplied */ - getDeclarationDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): readonly DiagnosticWithLocation[]; + getDeclarationDiagnostics( + sourceFile?: SourceFile, + cancellationToken?: CancellationToken, + ): readonly DiagnosticWithLocation[]; /** * Get all the dependencies of the file */ @@ -5836,7 +7696,13 @@ declare namespace ts { * The first of writeFile if provided, writeFile of BuilderProgramHost if provided, writeFile of compiler host * in that order would be used to write the files */ - emit(targetSourceFile?: SourceFile, writeFile?: WriteFileCallback, cancellationToken?: CancellationToken, emitOnlyDtsFiles?: boolean, customTransformers?: CustomTransformers): EmitResult; + emit( + targetSourceFile?: SourceFile, + writeFile?: WriteFileCallback, + cancellationToken?: CancellationToken, + emitOnlyDtsFiles?: boolean, + customTransformers?: CustomTransformers, + ): EmitResult; /** * Get the current directory of the program */ @@ -5850,7 +7716,10 @@ declare namespace ts { * Gets the semantic diagnostics from the program for the next affected file and caches it * Returns undefined if the iteration is complete */ - getSemanticDiagnosticsOfNextAffectedFile(cancellationToken?: CancellationToken, ignoreSourceFile?: (sourceFile: SourceFile) => boolean): AffectedFileResult; + getSemanticDiagnosticsOfNextAffectedFile( + cancellationToken?: CancellationToken, + ignoreSourceFile?: (sourceFile: SourceFile) => boolean, + ): AffectedFileResult; } /** * The builder that can handle the changes in program and iterate through changed file to emit the files @@ -5862,20 +7731,51 @@ declare namespace ts { * The first of writeFile if provided, writeFile of BuilderProgramHost if provided, writeFile of compiler host * in that order would be used to write the files */ - emitNextAffectedFile(writeFile?: WriteFileCallback, cancellationToken?: CancellationToken, emitOnlyDtsFiles?: boolean, customTransformers?: CustomTransformers): AffectedFileResult; - } - function readBuilderProgram(compilerOptions: CompilerOptions, host: ReadBuildProgramHost): EmitAndSemanticDiagnosticsBuilderProgram | undefined; + emitNextAffectedFile( + writeFile?: WriteFileCallback, + cancellationToken?: CancellationToken, + emitOnlyDtsFiles?: boolean, + customTransformers?: CustomTransformers, + ): AffectedFileResult; + } + function readBuilderProgram( + compilerOptions: CompilerOptions, + host: ReadBuildProgramHost, + ): EmitAndSemanticDiagnosticsBuilderProgram | undefined; function createIncrementalCompilerHost(options: CompilerOptions, system?: System): CompilerHost; - function createIncrementalProgram({ rootNames, options, configFileParsingDiagnostics, projectReferences, host, createProgram }: IncrementalProgramOptions): T; + function createIncrementalProgram( + { rootNames, options, configFileParsingDiagnostics, projectReferences, host, createProgram }: + IncrementalProgramOptions, + ): T; /** * Create the watch compiler host for either configFile or fileNames and its options */ - function createWatchCompilerHost(configFileName: string, optionsToExtend: CompilerOptions | undefined, system: System, createProgram?: CreateProgram, reportDiagnostic?: DiagnosticReporter, reportWatchStatus?: WatchStatusReporter, watchOptionsToExtend?: WatchOptions, extraFileExtensions?: readonly FileExtensionInfo[]): WatchCompilerHostOfConfigFile; - function createWatchCompilerHost(rootFiles: string[], options: CompilerOptions, system: System, createProgram?: CreateProgram, reportDiagnostic?: DiagnosticReporter, reportWatchStatus?: WatchStatusReporter, projectReferences?: readonly ProjectReference[], watchOptions?: WatchOptions): WatchCompilerHostOfFilesAndCompilerOptions; + function createWatchCompilerHost( + configFileName: string, + optionsToExtend: CompilerOptions | undefined, + system: System, + createProgram?: CreateProgram, + reportDiagnostic?: DiagnosticReporter, + reportWatchStatus?: WatchStatusReporter, + watchOptionsToExtend?: WatchOptions, + extraFileExtensions?: readonly FileExtensionInfo[], + ): WatchCompilerHostOfConfigFile; + function createWatchCompilerHost( + rootFiles: string[], + options: CompilerOptions, + system: System, + createProgram?: CreateProgram, + reportDiagnostic?: DiagnosticReporter, + reportWatchStatus?: WatchStatusReporter, + projectReferences?: readonly ProjectReference[], + watchOptions?: WatchOptions, + ): WatchCompilerHostOfFilesAndCompilerOptions; /** * Creates the watch from the host for root files and compiler options */ - function createWatchProgram(host: WatchCompilerHostOfFilesAndCompilerOptions): WatchOfFilesAndCompilerOptions; + function createWatchProgram( + host: WatchCompilerHostOfFilesAndCompilerOptions, + ): WatchOfFilesAndCompilerOptions; /** * Creates the watch from the host for config file */ @@ -5893,17 +7793,44 @@ declare namespace ts { host?: CompilerHost; createProgram?: CreateProgram; } - type WatchStatusReporter = (diagnostic: Diagnostic, newLine: string, options: CompilerOptions, errorCount?: number) => void; + type WatchStatusReporter = ( + diagnostic: Diagnostic, + newLine: string, + options: CompilerOptions, + errorCount?: number, + ) => void; /** Create the program with rootNames and options, if they are undefined, oldProgram and new configFile diagnostics create new program */ - type CreateProgram = (rootNames: readonly string[] | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: T, configFileParsingDiagnostics?: readonly Diagnostic[], projectReferences?: readonly ProjectReference[] | undefined) => T; + type CreateProgram = ( + rootNames: readonly string[] | undefined, + options: CompilerOptions | undefined, + host?: CompilerHost, + oldProgram?: T, + configFileParsingDiagnostics?: readonly Diagnostic[], + projectReferences?: readonly ProjectReference[] | undefined, + ) => T; /** Host that has watch functionality used in --watch mode */ interface WatchHost { /** If provided, called with Diagnostic message that informs about change in watch status */ - onWatchStatusChange?(diagnostic: Diagnostic, newLine: string, options: CompilerOptions, errorCount?: number): void; + onWatchStatusChange?( + diagnostic: Diagnostic, + newLine: string, + options: CompilerOptions, + errorCount?: number, + ): void; /** Used to watch changes in source files, missing files needed to update the program or config file */ - watchFile(path: string, callback: FileWatcherCallback, pollingInterval?: number, options?: WatchOptions): FileWatcher; + watchFile( + path: string, + callback: FileWatcherCallback, + pollingInterval?: number, + options?: WatchOptions, + ): FileWatcher; /** Used to watch resolved module's failed lookup locations, config file specs, type roots where auto type reference directives are added */ - watchDirectory(path: string, callback: DirectoryWatcherCallback, recursive?: boolean, options?: WatchOptions): FileWatcher; + watchDirectory( + path: string, + callback: DirectoryWatcherCallback, + recursive?: boolean, + options?: WatchOptions, + ): FileWatcher; /** If provided, will be used to set delayed compilation, so that multiple changes in short span are compiled together */ setTimeout?(callback: (...args: any[]) => void, ms: number, ...args: any[]): any; /** If provided, will be used to reset existing delayed compilation */ @@ -5935,7 +7862,13 @@ declare namespace ts { /** If provided, used in resolutions as well as handling directory structure */ getDirectories?(path: string): string[]; /** If provided, used to cache and handle directory structure modifications */ - readDirectory?(path: string, extensions?: readonly string[], exclude?: readonly string[], include?: readonly string[], depth?: number): string[]; + readDirectory?( + path: string, + extensions?: readonly string[], + exclude?: readonly string[], + include?: readonly string[], + depth?: number, + ): string[]; /** Symbol links resolution */ realpath?(path: string): string; /** If provided would be used to write log about compilation */ @@ -5947,15 +7880,42 @@ declare namespace ts { * * If provided, used to resolve the module names, otherwise typescript's default module resolution */ - resolveModuleNames?(moduleNames: string[], containingFile: string, reusedNames: string[] | undefined, redirectedReference: ResolvedProjectReference | undefined, options: CompilerOptions, containingSourceFile?: SourceFile): (ResolvedModule | undefined)[]; + resolveModuleNames?( + moduleNames: string[], + containingFile: string, + reusedNames: string[] | undefined, + redirectedReference: ResolvedProjectReference | undefined, + options: CompilerOptions, + containingSourceFile?: SourceFile, + ): (ResolvedModule | undefined)[]; /** * @deprecated supply resolveTypeReferenceDirectiveReferences instead for resolution that can handle newer resolution modes like nodenext * * If provided, used to resolve type reference directives, otherwise typescript's default resolution */ - resolveTypeReferenceDirectives?(typeReferenceDirectiveNames: string[] | readonly FileReference[], containingFile: string, redirectedReference: ResolvedProjectReference | undefined, options: CompilerOptions, containingFileMode?: ResolutionMode): (ResolvedTypeReferenceDirective | undefined)[]; - resolveModuleNameLiterals?(moduleLiterals: readonly StringLiteralLike[], containingFile: string, redirectedReference: ResolvedProjectReference | undefined, options: CompilerOptions, containingSourceFile: SourceFile, reusedNames: readonly StringLiteralLike[] | undefined): readonly ResolvedModuleWithFailedLookupLocations[]; - resolveTypeReferenceDirectiveReferences?(typeDirectiveReferences: readonly T[], containingFile: string, redirectedReference: ResolvedProjectReference | undefined, options: CompilerOptions, containingSourceFile: SourceFile | undefined, reusedNames: readonly T[] | undefined): readonly ResolvedTypeReferenceDirectiveWithFailedLookupLocations[]; + resolveTypeReferenceDirectives?( + typeReferenceDirectiveNames: string[] | readonly FileReference[], + containingFile: string, + redirectedReference: ResolvedProjectReference | undefined, + options: CompilerOptions, + containingFileMode?: ResolutionMode, + ): (ResolvedTypeReferenceDirective | undefined)[]; + resolveModuleNameLiterals?( + moduleLiterals: readonly StringLiteralLike[], + containingFile: string, + redirectedReference: ResolvedProjectReference | undefined, + options: CompilerOptions, + containingSourceFile: SourceFile, + reusedNames: readonly StringLiteralLike[] | undefined, + ): readonly ResolvedModuleWithFailedLookupLocations[]; + resolveTypeReferenceDirectiveReferences?( + typeDirectiveReferences: readonly T[], + containingFile: string, + redirectedReference: ResolvedProjectReference | undefined, + options: CompilerOptions, + containingSourceFile: SourceFile | undefined, + reusedNames: readonly T[] | undefined, + ): readonly ResolvedTypeReferenceDirectiveWithFailedLookupLocations[]; /** If provided along with custom resolveModuleNames or resolveTypeReferenceDirectives, used to determine if unchanged file path needs to re-resolve modules/type reference directives */ hasInvalidatedResolutions?(filePath: Path): boolean; /** @@ -5986,7 +7946,9 @@ declare namespace ts { /** * Host to create watch with config file */ - interface WatchCompilerHostOfConfigFile extends WatchCompilerHost, ConfigFileDiagnosticsReporter { + interface WatchCompilerHostOfConfigFile + extends WatchCompilerHost, ConfigFileDiagnosticsReporter + { /** Name of the config file to compile */ configFileName: string; /** Options to extend */ @@ -5997,7 +7959,13 @@ declare namespace ts { * Used to generate source file names from the config file and its include, exclude, files rules * and also to cache the directory stucture */ - readDirectory(path: string, extensions?: readonly string[], exclude?: readonly string[], include?: readonly string[], depth?: number): string[]; + readDirectory( + path: string, + extensions?: readonly string[], + exclude?: readonly string[], + include?: readonly string[], + depth?: number, + ): string[]; } interface Watch { /** Synchronize with host and get updated program */ @@ -6021,10 +7989,31 @@ declare namespace ts { * Create a function that reports watch status by writing to the system and handles the formating of the diagnostic */ function createBuilderStatusReporter(system: System, pretty?: boolean): DiagnosticReporter; - function createSolutionBuilderHost(system?: System, createProgram?: CreateProgram, reportDiagnostic?: DiagnosticReporter, reportSolutionBuilderStatus?: DiagnosticReporter, reportErrorSummary?: ReportEmitErrorSummary): SolutionBuilderHost; - function createSolutionBuilderWithWatchHost(system?: System, createProgram?: CreateProgram, reportDiagnostic?: DiagnosticReporter, reportSolutionBuilderStatus?: DiagnosticReporter, reportWatchStatus?: WatchStatusReporter): SolutionBuilderWithWatchHost; - function createSolutionBuilder(host: SolutionBuilderHost, rootNames: readonly string[], defaultOptions: BuildOptions): SolutionBuilder; - function createSolutionBuilderWithWatch(host: SolutionBuilderWithWatchHost, rootNames: readonly string[], defaultOptions: BuildOptions, baseWatchOptions?: WatchOptions): SolutionBuilder; + function createSolutionBuilderHost( + system?: System, + createProgram?: CreateProgram, + reportDiagnostic?: DiagnosticReporter, + reportSolutionBuilderStatus?: DiagnosticReporter, + reportErrorSummary?: ReportEmitErrorSummary, + ): SolutionBuilderHost; + function createSolutionBuilderWithWatchHost( + system?: System, + createProgram?: CreateProgram, + reportDiagnostic?: DiagnosticReporter, + reportSolutionBuilderStatus?: DiagnosticReporter, + reportWatchStatus?: WatchStatusReporter, + ): SolutionBuilderWithWatchHost; + function createSolutionBuilder( + host: SolutionBuilderHost, + rootNames: readonly string[], + defaultOptions: BuildOptions, + ): SolutionBuilder; + function createSolutionBuilderWithWatch( + host: SolutionBuilderWithWatchHost, + rootNames: readonly string[], + defaultOptions: BuildOptions, + baseWatchOptions?: WatchOptions, + ): SolutionBuilder; interface BuildOptions { dry?: boolean; force?: boolean; @@ -6066,9 +8055,19 @@ declare namespace ts { interface SolutionBuilderWithWatchHost extends SolutionBuilderHostBase, WatchHost { } interface SolutionBuilder { - build(project?: string, cancellationToken?: CancellationToken, writeFile?: WriteFileCallback, getCustomTransformers?: (project: string) => CustomTransformers): ExitStatus; + build( + project?: string, + cancellationToken?: CancellationToken, + writeFile?: WriteFileCallback, + getCustomTransformers?: (project: string) => CustomTransformers, + ): ExitStatus; clean(project?: string): ExitStatus; - buildReferences(project: string, cancellationToken?: CancellationToken, writeFile?: WriteFileCallback, getCustomTransformers?: (project: string) => CustomTransformers): ExitStatus; + buildReferences( + project: string, + cancellationToken?: CancellationToken, + writeFile?: WriteFileCallback, + getCustomTransformers?: (project: string) => CustomTransformers, + ): ExitStatus; cleanReferences(project?: string): ExitStatus; getNextInvalidatedProject(cancellationToken?: CancellationToken): InvalidatedProject | undefined; } @@ -6083,7 +8082,11 @@ declare namespace ts { /** * To dispose this project and ensure that all the necessary actions are taken and state is updated accordingly */ - done(cancellationToken?: CancellationToken, writeFile?: WriteFileCallback, customTransformers?: CustomTransformers): ExitStatus; + done( + cancellationToken?: CancellationToken, + writeFile?: WriteFileCallback, + customTransformers?: CustomTransformers, + ): ExitStatus; getCompilerOptions(): CompilerOptions; getCurrentDirectory(): string; } @@ -6103,21 +8106,42 @@ declare namespace ts { getSyntacticDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): readonly Diagnostic[]; getAllDependencies(sourceFile: SourceFile): readonly string[]; getSemanticDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): readonly Diagnostic[]; - getSemanticDiagnosticsOfNextAffectedFile(cancellationToken?: CancellationToken, ignoreSourceFile?: (sourceFile: SourceFile) => boolean): AffectedFileResult; - emit(targetSourceFile?: SourceFile, writeFile?: WriteFileCallback, cancellationToken?: CancellationToken, emitOnlyDtsFiles?: boolean, customTransformers?: CustomTransformers): EmitResult | undefined; + getSemanticDiagnosticsOfNextAffectedFile( + cancellationToken?: CancellationToken, + ignoreSourceFile?: (sourceFile: SourceFile) => boolean, + ): AffectedFileResult; + emit( + targetSourceFile?: SourceFile, + writeFile?: WriteFileCallback, + cancellationToken?: CancellationToken, + emitOnlyDtsFiles?: boolean, + customTransformers?: CustomTransformers, + ): EmitResult | undefined; } /** @deprecated */ interface UpdateBundleProject extends InvalidatedProjectBase { readonly kind: InvalidatedProjectKind.UpdateBundle; - emit(writeFile?: WriteFileCallback, customTransformers?: CustomTransformers): EmitResult | BuildInvalidedProject | undefined; - } - type InvalidatedProject = UpdateOutputFileStampsProject | BuildInvalidedProject | UpdateBundleProject; + emit( + writeFile?: WriteFileCallback, + customTransformers?: CustomTransformers, + ): EmitResult | BuildInvalidedProject | undefined; + } + type InvalidatedProject = + | UpdateOutputFileStampsProject + | BuildInvalidedProject + | UpdateBundleProject; namespace JsTyping { interface TypingResolutionHost { directoryExists(path: string): boolean; fileExists(fileName: string): boolean; readFile(path: string, encoding?: string): string | undefined; - readDirectory(rootDir: string, extensions: readonly string[], excludes: readonly string[] | undefined, includes: readonly string[] | undefined, depth?: number): string[]; + readDirectory( + rootDir: string, + extensions: readonly string[], + excludes: readonly string[] | undefined, + includes: readonly string[] | undefined, + depth?: number, + ): string[]; } } namespace server { @@ -6130,7 +8154,15 @@ declare namespace ts { type EventInitializationFailed = "event::initializationFailed"; type ActionWatchTypingLocations = "action::watchTypingLocations"; interface TypingInstallerResponse { - readonly kind: ActionSet | ActionInvalidate | EventTypesRegistry | ActionPackageInstalled | EventBeginInstallTypes | EventEndInstallTypes | EventInitializationFailed | ActionWatchTypingLocations; + readonly kind: + | ActionSet + | ActionInvalidate + | EventTypesRegistry + | ActionPackageInstalled + | EventBeginInstallTypes + | EventEndInstallTypes + | EventInitializationFailed + | ActionWatchTypingLocations; } interface TypingInstallerRequestWithProjectName { readonly projectName: string; @@ -6275,18 +8307,55 @@ declare namespace ts { trace?(s: string): void; error?(s: string): void; useCaseSensitiveFileNames?(): boolean; - readDirectory?(path: string, extensions?: readonly string[], exclude?: readonly string[], include?: readonly string[], depth?: number): string[]; + readDirectory?( + path: string, + extensions?: readonly string[], + exclude?: readonly string[], + include?: readonly string[], + depth?: number, + ): string[]; realpath?(path: string): string; readFile(path: string, encoding?: string): string | undefined; fileExists(path: string): boolean; getTypeRootsVersion?(): number; /** @deprecated supply resolveModuleNameLiterals instead for resolution that can handle newer resolution modes like nodenext */ - resolveModuleNames?(moduleNames: string[], containingFile: string, reusedNames: string[] | undefined, redirectedReference: ResolvedProjectReference | undefined, options: CompilerOptions, containingSourceFile?: SourceFile): (ResolvedModule | undefined)[]; - getResolvedModuleWithFailedLookupLocationsFromCache?(modulename: string, containingFile: string, resolutionMode?: ResolutionMode): ResolvedModuleWithFailedLookupLocations | undefined; + resolveModuleNames?( + moduleNames: string[], + containingFile: string, + reusedNames: string[] | undefined, + redirectedReference: ResolvedProjectReference | undefined, + options: CompilerOptions, + containingSourceFile?: SourceFile, + ): (ResolvedModule | undefined)[]; + getResolvedModuleWithFailedLookupLocationsFromCache?( + modulename: string, + containingFile: string, + resolutionMode?: ResolutionMode, + ): ResolvedModuleWithFailedLookupLocations | undefined; /** @deprecated supply resolveTypeReferenceDirectiveReferences instead for resolution that can handle newer resolution modes like nodenext */ - resolveTypeReferenceDirectives?(typeDirectiveNames: string[] | FileReference[], containingFile: string, redirectedReference: ResolvedProjectReference | undefined, options: CompilerOptions, containingFileMode?: ResolutionMode): (ResolvedTypeReferenceDirective | undefined)[]; - resolveModuleNameLiterals?(moduleLiterals: readonly StringLiteralLike[], containingFile: string, redirectedReference: ResolvedProjectReference | undefined, options: CompilerOptions, containingSourceFile: SourceFile, reusedNames: readonly StringLiteralLike[] | undefined): readonly ResolvedModuleWithFailedLookupLocations[]; - resolveTypeReferenceDirectiveReferences?(typeDirectiveReferences: readonly T[], containingFile: string, redirectedReference: ResolvedProjectReference | undefined, options: CompilerOptions, containingSourceFile: SourceFile | undefined, reusedNames: readonly T[] | undefined): readonly ResolvedTypeReferenceDirectiveWithFailedLookupLocations[]; + resolveTypeReferenceDirectives?( + typeDirectiveNames: string[] | FileReference[], + containingFile: string, + redirectedReference: ResolvedProjectReference | undefined, + options: CompilerOptions, + containingFileMode?: ResolutionMode, + ): (ResolvedTypeReferenceDirective | undefined)[]; + resolveModuleNameLiterals?( + moduleLiterals: readonly StringLiteralLike[], + containingFile: string, + redirectedReference: ResolvedProjectReference | undefined, + options: CompilerOptions, + containingSourceFile: SourceFile, + reusedNames: readonly StringLiteralLike[] | undefined, + ): readonly ResolvedModuleWithFailedLookupLocations[]; + resolveTypeReferenceDirectiveReferences?( + typeDirectiveReferences: readonly T[], + containingFile: string, + redirectedReference: ResolvedProjectReference | undefined, + options: CompilerOptions, + containingSourceFile: SourceFile | undefined, + reusedNames: readonly T[] | undefined, + ): readonly ResolvedTypeReferenceDirectiveWithFailedLookupLocations[]; getDirectories?(directoryName: string): string[]; /** * Gets a set of custom transformers to use during emit. @@ -6355,10 +8424,18 @@ declare namespace ts { getCompilerOptionsDiagnostics(): Diagnostic[]; /** @deprecated Use getEncodedSyntacticClassifications instead. */ getSyntacticClassifications(fileName: string, span: TextSpan): ClassifiedSpan[]; - getSyntacticClassifications(fileName: string, span: TextSpan, format: SemanticClassificationFormat): ClassifiedSpan[] | ClassifiedSpan2020[]; + getSyntacticClassifications( + fileName: string, + span: TextSpan, + format: SemanticClassificationFormat, + ): ClassifiedSpan[] | ClassifiedSpan2020[]; /** @deprecated Use getEncodedSemanticClassifications instead. */ getSemanticClassifications(fileName: string, span: TextSpan): ClassifiedSpan[]; - getSemanticClassifications(fileName: string, span: TextSpan, format: SemanticClassificationFormat): ClassifiedSpan[] | ClassifiedSpan2020[]; + getSemanticClassifications( + fileName: string, + span: TextSpan, + format: SemanticClassificationFormat, + ): ClassifiedSpan[] | ClassifiedSpan2020[]; /** Encoded as triples of [start, length, ClassificationType]. */ getEncodedSyntacticClassifications(fileName: string, span: TextSpan): Classifications; /** @@ -6370,7 +8447,11 @@ declare namespace ts { * @param format Which format to use, defaults to "original" * @returns a number array encoded as triples of [start, length, ClassificationType, ...]. */ - getEncodedSemanticClassifications(fileName: string, span: TextSpan, format?: SemanticClassificationFormat): Classifications; + getEncodedSemanticClassifications( + fileName: string, + span: TextSpan, + format?: SemanticClassificationFormat, + ): Classifications; /** * Gets completion entries at a particular position in a file. * @@ -6380,7 +8461,12 @@ declare namespace ts { * of code actions can be returned with the completions. * @param formattingSettings settings needed for calling formatting functions. */ - getCompletionsAtPosition(fileName: string, position: number, options: GetCompletionsAtPositionOptions | undefined, formattingSettings?: FormatCodeSettings): WithMetadata | undefined; + getCompletionsAtPosition( + fileName: string, + position: number, + options: GetCompletionsAtPositionOptions | undefined, + formattingSettings?: FormatCodeSettings, + ): WithMetadata | undefined; /** * Gets the extended details for a completion entry retrieved from `getCompletionsAtPosition`. * @@ -6392,8 +8478,21 @@ declare namespace ts { * @param preferences User settings, can be undefined for backwards compatibility * @param data `data` property from the completion entry */ - getCompletionEntryDetails(fileName: string, position: number, entryName: string, formatOptions: FormatCodeOptions | FormatCodeSettings | undefined, source: string | undefined, preferences: UserPreferences | undefined, data: CompletionEntryData | undefined): CompletionEntryDetails | undefined; - getCompletionEntrySymbol(fileName: string, position: number, name: string, source: string | undefined): Symbol | undefined; + getCompletionEntryDetails( + fileName: string, + position: number, + entryName: string, + formatOptions: FormatCodeOptions | FormatCodeSettings | undefined, + source: string | undefined, + preferences: UserPreferences | undefined, + data: CompletionEntryData | undefined, + ): CompletionEntryDetails | undefined; + getCompletionEntrySymbol( + fileName: string, + position: number, + name: string, + source: string | undefined, + ): Symbol | undefined; /** * Gets semantic information about the identifier at a particular position in a * file. Quick info is what you typically see when you hover in an editor. @@ -6404,13 +8503,29 @@ declare namespace ts { getQuickInfoAtPosition(fileName: string, position: number): QuickInfo | undefined; getNameOrDottedNameSpan(fileName: string, startPos: number, endPos: number): TextSpan | undefined; getBreakpointStatementAtPosition(fileName: string, position: number): TextSpan | undefined; - getSignatureHelpItems(fileName: string, position: number, options: SignatureHelpItemsOptions | undefined): SignatureHelpItems | undefined; + getSignatureHelpItems( + fileName: string, + position: number, + options: SignatureHelpItemsOptions | undefined, + ): SignatureHelpItems | undefined; getRenameInfo(fileName: string, position: number, preferences: UserPreferences): RenameInfo; /** @deprecated Use the signature with `UserPreferences` instead. */ getRenameInfo(fileName: string, position: number, options?: RenameInfoOptions): RenameInfo; - findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean, preferences: UserPreferences): readonly RenameLocation[] | undefined; + findRenameLocations( + fileName: string, + position: number, + findInStrings: boolean, + findInComments: boolean, + preferences: UserPreferences, + ): readonly RenameLocation[] | undefined; /** @deprecated Pass `providePrefixAndSuffixTextForRename` as part of a `UserPreferences` parameter. */ - findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean, providePrefixAndSuffixTextForRename?: boolean): readonly RenameLocation[] | undefined; + findRenameLocations( + fileName: string, + position: number, + findInStrings: boolean, + findInComments: boolean, + providePrefixAndSuffixTextForRename?: boolean, + ): readonly RenameLocation[] | undefined; getSmartSelectionRange(fileName: string, position: number): SelectionRange; getDefinitionAtPosition(fileName: string, position: number): readonly DefinitionInfo[] | undefined; getDefinitionAndBoundSpan(fileName: string, position: number): DefinitionInfoAndBoundSpan | undefined; @@ -6418,9 +8533,18 @@ declare namespace ts { getImplementationAtPosition(fileName: string, position: number): readonly ImplementationLocation[] | undefined; getReferencesAtPosition(fileName: string, position: number): ReferenceEntry[] | undefined; findReferences(fileName: string, position: number): ReferencedSymbol[] | undefined; - getDocumentHighlights(fileName: string, position: number, filesToSearch: string[]): DocumentHighlights[] | undefined; + getDocumentHighlights( + fileName: string, + position: number, + filesToSearch: string[], + ): DocumentHighlights[] | undefined; getFileReferences(fileName: string): ReferenceEntry[]; - getNavigateToItems(searchValue: string, maxResultCount?: number, fileName?: string, excludeDtsFiles?: boolean): NavigateToItem[]; + getNavigateToItems( + searchValue: string, + maxResultCount?: number, + fileName?: string, + excludeDtsFiles?: boolean, + ): NavigateToItem[]; getNavigationBarItems(fileName: string): NavigationBarItem[]; getNavigationTree(fileName: string): NavigationTree; prepareCallHierarchy(fileName: string, position: number): CallHierarchyItem | CallHierarchyItem[] | undefined; @@ -6431,10 +8555,25 @@ declare namespace ts { getTodoComments(fileName: string, descriptors: TodoCommentDescriptor[]): TodoComment[]; getBraceMatchingAtPosition(fileName: string, position: number): TextSpan[]; getIndentationAtPosition(fileName: string, position: number, options: EditorOptions | EditorSettings): number; - getFormattingEditsForRange(fileName: string, start: number, end: number, options: FormatCodeOptions | FormatCodeSettings): TextChange[]; + getFormattingEditsForRange( + fileName: string, + start: number, + end: number, + options: FormatCodeOptions | FormatCodeSettings, + ): TextChange[]; getFormattingEditsForDocument(fileName: string, options: FormatCodeOptions | FormatCodeSettings): TextChange[]; - getFormattingEditsAfterKeystroke(fileName: string, position: number, key: string, options: FormatCodeOptions | FormatCodeSettings): TextChange[]; - getDocCommentTemplateAtPosition(fileName: string, position: number, options?: DocCommentTemplateOptions, formatOptions?: FormatCodeSettings): TextInsertion | undefined; + getFormattingEditsAfterKeystroke( + fileName: string, + position: number, + key: string, + options: FormatCodeOptions | FormatCodeSettings, + ): TextChange[]; + getDocCommentTemplateAtPosition( + fileName: string, + position: number, + options?: DocCommentTemplateOptions, + formatOptions?: FormatCodeSettings, + ): TextInsertion | undefined; isValidBraceCompletionAtPosition(fileName: string, position: number, openingBrace: number): boolean; /** * This will return a defined result if the position is after the `>` of the opening tag, or somewhere in the text, of a JSXElement with no closing tag. @@ -6444,31 +8583,85 @@ declare namespace ts { getLinkedEditingRangeAtPosition(fileName: string, position: number): LinkedEditingInfo | undefined; getSpanOfEnclosingComment(fileName: string, position: number, onlyMultiLine: boolean): TextSpan | undefined; toLineColumnOffset?(fileName: string, position: number): LineAndCharacter; - getCodeFixesAtPosition(fileName: string, start: number, end: number, errorCodes: readonly number[], formatOptions: FormatCodeSettings, preferences: UserPreferences): readonly CodeFixAction[]; - getCombinedCodeFix(scope: CombinedCodeFixScope, fixId: {}, formatOptions: FormatCodeSettings, preferences: UserPreferences): CombinedCodeActions; - applyCodeActionCommand(action: CodeActionCommand, formatSettings?: FormatCodeSettings): Promise; - applyCodeActionCommand(action: CodeActionCommand[], formatSettings?: FormatCodeSettings): Promise; - applyCodeActionCommand(action: CodeActionCommand | CodeActionCommand[], formatSettings?: FormatCodeSettings): Promise; + getCodeFixesAtPosition( + fileName: string, + start: number, + end: number, + errorCodes: readonly number[], + formatOptions: FormatCodeSettings, + preferences: UserPreferences, + ): readonly CodeFixAction[]; + getCombinedCodeFix( + scope: CombinedCodeFixScope, + fixId: {}, + formatOptions: FormatCodeSettings, + preferences: UserPreferences, + ): CombinedCodeActions; + applyCodeActionCommand( + action: CodeActionCommand, + formatSettings?: FormatCodeSettings, + ): Promise; + applyCodeActionCommand( + action: CodeActionCommand[], + formatSettings?: FormatCodeSettings, + ): Promise; + applyCodeActionCommand( + action: CodeActionCommand | CodeActionCommand[], + formatSettings?: FormatCodeSettings, + ): Promise; /** @deprecated `fileName` will be ignored */ applyCodeActionCommand(fileName: string, action: CodeActionCommand): Promise; /** @deprecated `fileName` will be ignored */ applyCodeActionCommand(fileName: string, action: CodeActionCommand[]): Promise; /** @deprecated `fileName` will be ignored */ - applyCodeActionCommand(fileName: string, action: CodeActionCommand | CodeActionCommand[]): Promise; + applyCodeActionCommand( + fileName: string, + action: CodeActionCommand | CodeActionCommand[], + ): Promise; /** * @param includeInteractiveActions Include refactor actions that require additional arguments to be * passed when calling `getEditsForRefactor`. When true, clients should inspect the `isInteractive` * property of each returned `RefactorActionInfo` and ensure they are able to collect the appropriate * arguments for any interactive action before offering it. */ - getApplicableRefactors(fileName: string, positionOrRange: number | TextRange, preferences: UserPreferences | undefined, triggerReason?: RefactorTriggerReason, kind?: string, includeInteractiveActions?: boolean): ApplicableRefactorInfo[]; - getEditsForRefactor(fileName: string, formatOptions: FormatCodeSettings, positionOrRange: number | TextRange, refactorName: string, actionName: string, preferences: UserPreferences | undefined, interactiveRefactorArguments?: InteractiveRefactorArguments): RefactorEditInfo | undefined; - getMoveToRefactoringFileSuggestions(fileName: string, positionOrRange: number | TextRange, preferences: UserPreferences | undefined, triggerReason?: RefactorTriggerReason, kind?: string): { + getApplicableRefactors( + fileName: string, + positionOrRange: number | TextRange, + preferences: UserPreferences | undefined, + triggerReason?: RefactorTriggerReason, + kind?: string, + includeInteractiveActions?: boolean, + ): ApplicableRefactorInfo[]; + getEditsForRefactor( + fileName: string, + formatOptions: FormatCodeSettings, + positionOrRange: number | TextRange, + refactorName: string, + actionName: string, + preferences: UserPreferences | undefined, + interactiveRefactorArguments?: InteractiveRefactorArguments, + ): RefactorEditInfo | undefined; + getMoveToRefactoringFileSuggestions( + fileName: string, + positionOrRange: number | TextRange, + preferences: UserPreferences | undefined, + triggerReason?: RefactorTriggerReason, + kind?: string, + ): { newFileName: string; files: string[]; }; - organizeImports(args: OrganizeImportsArgs, formatOptions: FormatCodeSettings, preferences: UserPreferences | undefined): readonly FileTextChanges[]; - getEditsForFileRename(oldFilePath: string, newFilePath: string, formatOptions: FormatCodeSettings, preferences: UserPreferences | undefined): readonly FileTextChanges[]; + organizeImports( + args: OrganizeImportsArgs, + formatOptions: FormatCodeSettings, + preferences: UserPreferences | undefined, + ): readonly FileTextChanges[]; + getEditsForFileRename( + oldFilePath: string, + newFilePath: string, + formatOptions: FormatCodeSettings, + preferences: UserPreferences | undefined, + ): readonly FileTextChanges[]; getEmitOutput(fileName: string, emitOnlyDtsFiles?: boolean, forceDtsEmit?: boolean): EmitOutput; getProgram(): Program | undefined; toggleLineComment(fileName: string, textRange: TextRange): TextChange[]; @@ -6532,7 +8725,10 @@ declare namespace ts { interface SignatureHelpItemsOptions { triggerReason?: SignatureHelpTriggerReason; } - type SignatureHelpTriggerReason = SignatureHelpInvokedReason | SignatureHelpCharacterTypedReason | SignatureHelpRetriggeredReason; + type SignatureHelpTriggerReason = + | SignatureHelpInvokedReason + | SignatureHelpCharacterTypedReason + | SignatureHelpRetriggeredReason; /** * Signals that the user manually requested signature help. * The language service will unconditionally attempt to provide a result. @@ -7211,8 +9407,16 @@ declare namespace ts { * subsume the classification. * @deprecated Use getLexicalClassifications instead. */ - getClassificationsForLine(text: string, lexState: EndOfLineState, syntacticClassifierAbsent: boolean): ClassificationResult; - getEncodedLexicalClassifications(text: string, endOfLineState: EndOfLineState, syntacticClassifierAbsent: boolean): Classifications; + getClassificationsForLine( + text: string, + lexState: EndOfLineState, + syntacticClassifierAbsent: boolean, + ): ClassificationResult; + getEncodedLexicalClassifications( + text: string, + endOfLineState: EndOfLineState, + syntacticClassifierAbsent: boolean, + ): Classifications; } enum ScriptElementKind { unknown = "", @@ -7424,8 +9628,24 @@ declare namespace ts { * @param version Current version of the file. Only used if the file was not found * in the registry and a new one was created. */ - acquireDocument(fileName: string, compilationSettingsOrHost: CompilerOptions | MinimalResolutionCacheHost, scriptSnapshot: IScriptSnapshot, version: string, scriptKind?: ScriptKind, sourceFileOptions?: CreateSourceFileOptions | ScriptTarget): SourceFile; - acquireDocumentWithKey(fileName: string, path: Path, compilationSettingsOrHost: CompilerOptions | MinimalResolutionCacheHost, key: DocumentRegistryBucketKey, scriptSnapshot: IScriptSnapshot, version: string, scriptKind?: ScriptKind, sourceFileOptions?: CreateSourceFileOptions | ScriptTarget): SourceFile; + acquireDocument( + fileName: string, + compilationSettingsOrHost: CompilerOptions | MinimalResolutionCacheHost, + scriptSnapshot: IScriptSnapshot, + version: string, + scriptKind?: ScriptKind, + sourceFileOptions?: CreateSourceFileOptions | ScriptTarget, + ): SourceFile; + acquireDocumentWithKey( + fileName: string, + path: Path, + compilationSettingsOrHost: CompilerOptions | MinimalResolutionCacheHost, + key: DocumentRegistryBucketKey, + scriptSnapshot: IScriptSnapshot, + version: string, + scriptKind?: ScriptKind, + sourceFileOptions?: CreateSourceFileOptions | ScriptTarget, + ): SourceFile; /** * Request an updated version of an already existing SourceFile with a given fileName * and compilationSettings. The update will in-turn call updateLanguageServiceSourceFile @@ -7441,8 +9661,24 @@ declare namespace ts { * @param scriptSnapshot Text of the file. * @param version Current version of the file. */ - updateDocument(fileName: string, compilationSettingsOrHost: CompilerOptions | MinimalResolutionCacheHost, scriptSnapshot: IScriptSnapshot, version: string, scriptKind?: ScriptKind, sourceFileOptions?: CreateSourceFileOptions | ScriptTarget): SourceFile; - updateDocumentWithKey(fileName: string, path: Path, compilationSettingsOrHost: CompilerOptions | MinimalResolutionCacheHost, key: DocumentRegistryBucketKey, scriptSnapshot: IScriptSnapshot, version: string, scriptKind?: ScriptKind, sourceFileOptions?: CreateSourceFileOptions | ScriptTarget): SourceFile; + updateDocument( + fileName: string, + compilationSettingsOrHost: CompilerOptions | MinimalResolutionCacheHost, + scriptSnapshot: IScriptSnapshot, + version: string, + scriptKind?: ScriptKind, + sourceFileOptions?: CreateSourceFileOptions | ScriptTarget, + ): SourceFile; + updateDocumentWithKey( + fileName: string, + path: Path, + compilationSettingsOrHost: CompilerOptions | MinimalResolutionCacheHost, + key: DocumentRegistryBucketKey, + scriptSnapshot: IScriptSnapshot, + version: string, + scriptKind?: ScriptKind, + sourceFileOptions?: CreateSourceFileOptions | ScriptTarget, + ): SourceFile; getKeyForCompilationSettings(settings: CompilerOptions): DocumentRegistryBucketKey; /** * Informs the DocumentRegistry that a file is not needed any longer. @@ -7468,19 +9704,39 @@ declare namespace ts { * @param scriptKind The script kind of the file to be released * @param impliedNodeFormat The implied source file format of the file to be released */ - releaseDocument(fileName: string, compilationSettings: CompilerOptions, scriptKind: ScriptKind, impliedNodeFormat: ResolutionMode): void; + releaseDocument( + fileName: string, + compilationSettings: CompilerOptions, + scriptKind: ScriptKind, + impliedNodeFormat: ResolutionMode, + ): void; /** * @deprecated pass scriptKind for and impliedNodeFormat correctness */ releaseDocumentWithKey(path: Path, key: DocumentRegistryBucketKey, scriptKind?: ScriptKind): void; - releaseDocumentWithKey(path: Path, key: DocumentRegistryBucketKey, scriptKind: ScriptKind, impliedNodeFormat: ResolutionMode): void; + releaseDocumentWithKey( + path: Path, + key: DocumentRegistryBucketKey, + scriptKind: ScriptKind, + impliedNodeFormat: ResolutionMode, + ): void; reportStats(): string; } type DocumentRegistryBucketKey = string & { __bucketKey: any; }; - function preProcessFile(sourceText: string, readImportFiles?: boolean, detectJavaScriptImports?: boolean): PreProcessedFileInfo; + function preProcessFile( + sourceText: string, + readImportFiles?: boolean, + detectJavaScriptImports?: boolean, + ): PreProcessedFileInfo; function transpileModule(input: string, transpileOptions: TranspileOptions): TranspileOutput; - function transpile(input: string, compilerOptions?: CompilerOptions, fileName?: string, diagnostics?: Diagnostic[], moduleName?: string): string; + function transpile( + input: string, + compilerOptions?: CompilerOptions, + fileName?: string, + diagnostics?: Diagnostic[], + moduleName?: string, + ): string; interface TranspileOptions { compilerOptions?: CompilerOptions; fileName?: string; @@ -7498,9 +9754,26 @@ declare namespace ts { function displayPartsToString(displayParts: SymbolDisplayPart[] | undefined): string; function getDefaultCompilerOptions(): CompilerOptions; function getSupportedCodeFixes(): readonly string[]; - function createLanguageServiceSourceFile(fileName: string, scriptSnapshot: IScriptSnapshot, scriptTargetOrOptions: ScriptTarget | CreateSourceFileOptions, version: string, setNodeParents: boolean, scriptKind?: ScriptKind): SourceFile; - function updateLanguageServiceSourceFile(sourceFile: SourceFile, scriptSnapshot: IScriptSnapshot, version: string, textChangeRange: TextChangeRange | undefined, aggressiveChecks?: boolean): SourceFile; - function createLanguageService(host: LanguageServiceHost, documentRegistry?: DocumentRegistry, syntaxOnlyOrLanguageServiceMode?: boolean | LanguageServiceMode): LanguageService; + function createLanguageServiceSourceFile( + fileName: string, + scriptSnapshot: IScriptSnapshot, + scriptTargetOrOptions: ScriptTarget | CreateSourceFileOptions, + version: string, + setNodeParents: boolean, + scriptKind?: ScriptKind, + ): SourceFile; + function updateLanguageServiceSourceFile( + sourceFile: SourceFile, + scriptSnapshot: IScriptSnapshot, + version: string, + textChangeRange: TextChangeRange | undefined, + aggressiveChecks?: boolean, + ): SourceFile; + function createLanguageService( + host: LanguageServiceHost, + documentRegistry?: DocumentRegistry, + syntaxOnlyOrLanguageServiceMode?: boolean | LanguageServiceMode, + ): LanguageService; /** * Get the path of the default library files (lib.d.ts) as distributed with the typescript * node package. @@ -7515,6 +9788,10 @@ declare namespace ts { * @param transformers An array of `TransformerFactory` callbacks used to process the transformation. * @param compilerOptions Optional compiler options. */ - function transform(source: T | T[], transformers: TransformerFactory[], compilerOptions?: CompilerOptions): TransformationResult; + function transform( + source: T | T[], + transformers: TransformerFactory[], + compilerOptions?: CompilerOptions, + ): TransformationResult; } export = ts; diff --git a/tests/baselines/reference/goToTypeDefinition_arrayType.baseline.jsonc b/tests/baselines/reference/goToTypeDefinition_arrayType.baseline.jsonc index 1dc5b63951e85..d0365a7afb2af 100644 --- a/tests/baselines/reference/goToTypeDefinition_arrayType.baseline.jsonc +++ b/tests/baselines/reference/goToTypeDefinition_arrayType.baseline.jsonc @@ -179,20 +179,29 @@ // * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array. // * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value. // */ -// reduce(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U; +// reduce( +// callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, +// initialValue: U, +// ): U; // /** // * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function. // * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array. // * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value. // */ // reduceRight(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T): T; -// reduceRight(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue: T): T; +// reduceRight( +// callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, +// initialValue: T, +// ): T; // /** // * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function. // * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array. // * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value. // */ -// reduceRight(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U; +// reduceRight( +// callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, +// initialValue: U, +// ): U; // // [n: number]: T; // }|> @@ -432,20 +441,29 @@ // * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array. // * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value. // */ -// reduce(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U; +// reduce( +// callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, +// initialValue: U, +// ): U; // /** // * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function. // * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array. // * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value. // */ // reduceRight(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T): T; -// reduceRight(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue: T): T; +// reduceRight( +// callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, +// initialValue: T, +// ): T; // /** // * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function. // * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array. // * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value. // */ -// reduceRight(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U; +// reduceRight( +// callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, +// initialValue: U, +// ): U; // // [n: number]: T; // }|> diff --git a/tests/baselines/reference/goToTypeDefinition_promiseType.baseline.jsonc b/tests/baselines/reference/goToTypeDefinition_promiseType.baseline.jsonc index f84caf2e46250..d611501b18b06 100644 --- a/tests/baselines/reference/goToTypeDefinition_promiseType.baseline.jsonc +++ b/tests/baselines/reference/goToTypeDefinition_promiseType.baseline.jsonc @@ -19,14 +19,19 @@ // * @param onrejected The callback to execute when the Promise is rejected. // * @returns A Promise for the completion of which ever callback is executed. // */ -// then(onfulfilled?: ((value: T) => TResult1 | PromiseLike) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike) | undefined | null): Promise; +// then( +// onfulfilled?: ((value: T) => TResult1 | PromiseLike) | undefined | null, +// onrejected?: ((reason: any) => TResult2 | PromiseLike) | undefined | null, +// ): Promise; // // /** // * Attaches a callback for only the rejection of the Promise. // * @param onrejected The callback to execute when the Promise is rejected. // * @returns A Promise for the completion of the callback. // */ -// catch(onrejected?: ((reason: any) => TResult | PromiseLike) | undefined | null): Promise; +// catch( +// onrejected?: ((reason: any) => TResult | PromiseLike) | undefined | null, +// ): Promise; // }|> // // /** @@ -80,14 +85,19 @@ // * @param onrejected The callback to execute when the Promise is rejected. // * @returns A Promise for the completion of which ever callback is executed. // */ -// then(onfulfilled?: ((value: T) => TResult1 | PromiseLike) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike) | undefined | null): Promise; +// then( +// onfulfilled?: ((value: T) => TResult1 | PromiseLike) | undefined | null, +// onrejected?: ((reason: any) => TResult2 | PromiseLike) | undefined | null, +// ): Promise; // // /** // * Attaches a callback for only the rejection of the Promise. // * @param onrejected The callback to execute when the Promise is rejected. // * @returns A Promise for the completion of the callback. // */ -// catch(onrejected?: ((reason: any) => TResult | PromiseLike) | undefined | null): Promise; +// catch( +// onrejected?: ((reason: any) => TResult | PromiseLike) | undefined | null, +// ): Promise; // }|> // // /**