From 3ddb26ae8d4515766040ecf3c789a329552c4a1a Mon Sep 17 00:00:00 2001 From: Isabel Duan Date: Mon, 5 Aug 2024 15:02:16 -0700 Subject: [PATCH 01/27] turn on compiler flag --- src/tsconfig-base.json | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tsconfig-base.json b/src/tsconfig-base.json index e4615aa785424..d0727f454b7f6 100644 --- a/src/tsconfig-base.json +++ b/src/tsconfig-base.json @@ -14,6 +14,7 @@ "sourceMap": true, "composite": true, "emitDeclarationOnly": true, + "isolatedDeclarations": true, "strict": true, "strictBindCallApply": false, From 49676b51425fb69cccbf7af4572292777aef45a1 Mon Sep 17 00:00:00 2001 From: Isabel Duan Date: Mon, 12 Aug 2024 20:03:04 -0700 Subject: [PATCH 02/27] mostly generated by quickfixes (some formatting) --- src/compiler/binder.ts | 2 +- src/compiler/builder.ts | 13 +- src/compiler/builderState.ts | 16 +- src/compiler/checker.ts | 4 +- src/compiler/commandLineParser.ts | 25 +- src/compiler/core.ts | 56 +- src/compiler/debug.ts | 22 +- src/compiler/emitter.ts | 24 +- src/compiler/executeCommandLine.ts | 2 +- src/compiler/expressionToTypeNode.ts | 10 +- src/compiler/factory/emitHelpers.ts | 2 +- src/compiler/factory/emitNode.ts | 36 +- src/compiler/factory/nodeChildren.ts | 4 +- src/compiler/factory/nodeFactory.ts | 4 +- src/compiler/factory/utilities.ts | 38 +- src/compiler/moduleNameResolver.ts | 24 +- src/compiler/moduleSpecifiers.ts | 4 +- src/compiler/parser.ts | 14 +- src/compiler/path.ts | 32 +- src/compiler/performance.ts | 22 +- src/compiler/performanceCore.ts | 4 +- src/compiler/program.ts | 28 +- src/compiler/resolutionCache.ts | 8 +- src/compiler/scanner.ts | 14 +- src/compiler/semver.ts | 18 +- src/compiler/sourcemap.ts | 12 +- src/compiler/symbolWalker.ts | 2 +- src/compiler/sys.ts | 24 +- src/compiler/tracing.ts | 18 +- src/compiler/transformer.ts | 4 +- src/compiler/transformers/classThis.ts | 2 +- src/compiler/transformers/declarations.ts | 6 +- .../transformers/declarations/diagnostics.ts | 4 +- src/compiler/transformers/es2017.ts | 2 +- .../module/impliedNodeFormatDependent.ts | 2 +- src/compiler/transformers/ts.ts | 2 +- src/compiler/transformers/utilities.ts | 26 +- src/compiler/tsbuildPublic.ts | 4 +- src/compiler/types.ts | 73 ++- src/compiler/utilities.ts | 513 +++++++++++------- src/compiler/utilitiesPublic.ts | 52 +- src/compiler/visitorPublic.ts | 4 +- src/compiler/watch.ts | 28 +- src/compiler/watchPublic.ts | 4 +- src/compiler/watchUtilities.ts | 14 +- 45 files changed, 727 insertions(+), 495 deletions(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 5c94dde5cc597..724a344122dd6 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -510,7 +510,7 @@ export function createFlowNode(flags: FlowFlags, node: unknown, antecedent: Flow const binder = /* @__PURE__ */ createBinder(); /** @internal */ -export function bindSourceFile(file: SourceFile, options: CompilerOptions) { +export function bindSourceFile(file: SourceFile, options: CompilerOptions): void { performance.mark("beforeBind"); binder(file, options); performance.mark("afterBind"); diff --git a/src/compiler/builder.ts b/src/compiler/builder.ts index 6b0d7a24b3f2f..40d3fca7ac2a7 100644 --- a/src/compiler/builder.ts +++ b/src/compiler/builder.ts @@ -277,7 +277,7 @@ function toBuilderProgramStateWithDefinedProgram(state: ReusableBuilderProgramSt * * @internal */ -export function getBuilderFileEmit(options: CompilerOptions) { +export function getBuilderFileEmit(options: CompilerOptions): BuilderFileEmit { let result = BuilderFileEmit.Js; if (options.sourceMap) result = result | BuilderFileEmit.JsMap; if (options.inlineSourceMap) result = result | BuilderFileEmit.JsInlineMap; @@ -733,7 +733,7 @@ export function getPendingEmitKindWithSeen( seenOldOptionsOrEmitKind: CompilerOptions | BuilderFileEmit | undefined, emitOnlyDtsFiles: boolean | undefined, isForDtsErrors: boolean, -) { +): BuilderFileEmit { let pendingKind = getPendingEmitKind(optionsOrEmitKind, seenOldOptionsOrEmitKind); if (emitOnlyDtsFiles) pendingKind = pendingKind & BuilderFileEmit.AllDts; if (isForDtsErrors) pendingKind = pendingKind & BuilderFileEmit.DtsErrors; @@ -1623,7 +1623,7 @@ export function computeSignatureWithDiagnostics( text: string, host: HostForComputeHash, data: WriteFileCallbackData | undefined, -) { +): string { text = getTextHandlingSourceMapForSignature(text, data); let sourceFileDirectory: string | undefined; if (data?.diagnostics?.length) { @@ -2395,7 +2395,10 @@ export function getBuildInfoFileVersionMap( program: IncrementalBuildInfo, buildInfoPath: string, host: Pick, -) { +): { + fileInfos: Map; + roots: Map; +} { const buildInfoDirectory = getDirectoryPath(getNormalizedAbsolutePath(buildInfoPath, host.getCurrentDirectory())); const getCanonicalFileName = createGetCanonicalFileName(host.useCaseSensitiveFileNames()); const fileInfos = new Map(); @@ -2440,7 +2443,7 @@ export function getNonIncrementalBuildInfoRoots( buildInfo: BuildInfo, buildInfoPath: string, host: Pick, -) { +): Path[] | undefined { if (!isNonIncrementalBuildInfo(buildInfo)) return undefined; const buildInfoDirectory = getDirectoryPath(getNormalizedAbsolutePath(buildInfoPath, host.getCurrentDirectory())); const getCanonicalFileName = createGetCanonicalFileName(host.useCaseSensitiveFileNames()); diff --git a/src/compiler/builderState.ts b/src/compiler/builderState.ts index 0e571d233d7e8..cf9932e94631b 100644 --- a/src/compiler/builderState.ts +++ b/src/compiler/builderState.ts @@ -292,11 +292,11 @@ 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): boolean | undefined { return oldState && !oldState.referencedMap === !newReferencedMap; } - export function createReferencedMap(options: CompilerOptions) { + export function createReferencedMap(options: CompilerOptions): ManyToManyPathMap | undefined { return options.module !== ModuleKind.None && !options.outFile ? createManyToManyPathMap() : undefined; @@ -346,7 +346,7 @@ export namespace BuilderState { /** * Releases needed properties */ - export function releaseCache(state: BuilderState) { + export function releaseCache(state: BuilderState): void { state.allFilesExcludingDefaultLibraryFile = undefined; state.allFileNames = undefined; } @@ -391,7 +391,7 @@ export namespace BuilderState { return (state.referencedMap ? getFilesAffectedByUpdatedShapeWhenModuleEmit : getFilesAffectedByUpdatedShapeWhenNonModuleEmit)(state, programOfThisState, sourceFile, cancellationToken, host); } - export function updateSignatureOfFile(state: BuilderState, signature: string | undefined, path: Path) { + export function updateSignatureOfFile(state: BuilderState, signature: string | undefined, path: Path): void { state.fileInfos.get(path)!.signature = signature; (state.hasCalledUpdateShapeSignature ||= new Set()).add(path); } @@ -402,7 +402,7 @@ export namespace BuilderState { cancellationToken: CancellationToken | undefined, host: HostForComputeHash, onNewSignature: (signature: string, sourceFiles: readonly SourceFile[]) => void, - ) { + ): void { programOfThisState.emit( sourceFile, (fileName, text, _writeByteOrderMark, _onError, sourceFiles, data) => { @@ -434,8 +434,8 @@ export namespace BuilderState { sourceFile: SourceFile, cancellationToken: CancellationToken | undefined, host: HostForComputeHash, - useFileVersionAsSignature = state.useFileVersionAsSignature, - ) { + useFileVersionAsSignature: boolean | undefined = state.useFileVersionAsSignature, + ): boolean { // If we have cached the result for this file, that means hence forth we should assume file shape is uptodate if (state.hasCalledUpdateShapeSignature?.has(sourceFile.resolvedPath)) return false; @@ -507,7 +507,7 @@ export namespace BuilderState { /** * Gets the files referenced by the the file path */ - export function getReferencedByPaths(state: Readonly, referencedFilePath: Path) { + export function getReferencedByPaths(state: Readonly, referencedFilePath: Path): Path[] { const keys = state.referencedMap!.getKeys(referencedFilePath); return keys ? arrayFrom(keys.keys()) : []; } diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 6233873ab6de1..21e841abd0144 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -1447,7 +1447,7 @@ export function getSymbolId(symbol: Symbol): SymbolId { } /** @internal */ -export function isInstantiatedModule(node: ModuleDeclaration, preserveConstEnums: boolean) { +export function isInstantiatedModule(node: ModuleDeclaration, preserveConstEnums: boolean): boolean { const moduleState = getModuleInstanceState(node); return moduleState === ModuleInstanceState.Instantiated || (preserveConstEnums && moduleState === ModuleInstanceState.ConstEnumOnly); @@ -52446,7 +52446,7 @@ function getIterationTypesKeyFromIterationTypeKind(typeKind: IterationTypeKind) } /** @internal */ -export function signatureHasRestParameter(s: Signature) { +export function signatureHasRestParameter(s: Signature): boolean { return !!(s.flags & SignatureFlags.HasRestParameter); } diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index 1775bce71232e..a7906a9a08f06 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -138,7 +138,7 @@ 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: Map = 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 @@ -248,7 +248,7 @@ const libEntries: [string, string][] = [ * * @internal */ -export const libs = libEntries.map(entry => entry[0]); +export const libs: string[] = libEntries.map(entry => entry[0]); /** * A map of lib names to lib files. This map is used both for parsing the "lib" command line @@ -256,7 +256,7 @@ export const libs = libEntries.map(entry => entry[0]); * * @internal */ -export const libMap = new Map(libEntries); +export const libMap: Map = new Map(libEntries); // Watch related options @@ -1791,7 +1791,7 @@ function createDiagnosticForInvalidCustomType(opt: CommandLineOptionOfCustomType } /** @internal */ -export function parseCustomTypeOption(opt: CommandLineOptionOfCustomType, value: string | undefined, errors: Diagnostic[]) { +export function parseCustomTypeOption(opt: CommandLineOptionOfCustomType, value: string | undefined, errors: Diagnostic[]): string | number | undefined { return convertJsonOptionOfCustomType(opt, (value ?? "").trim(), errors); } @@ -1858,7 +1858,12 @@ export function parseCommandLineWorker( diagnostics: ParseCommandLineWorkerDiagnostics, commandLine: readonly string[], readFile?: (path: string) => string | undefined, -) { +): { + options: OptionsBase; + watchOptions: WatchOptions | undefined; + fileNames: string[]; + errors: Diagnostic[]; +} { const options = {} as OptionsBase; let watchOptions: WatchOptions | undefined; const fileNames: string[] = []; @@ -2850,7 +2855,7 @@ export function generateTSConfig(options: CompilerOptions, fileNames: readonly s } /** @internal */ -export function convertToOptionsWithAbsolutePaths(options: CompilerOptions, toAbsolutePath: (path: string) => string) { +export function convertToOptionsWithAbsolutePaths(options: CompilerOptions, toAbsolutePath: (path: string) => string): CompilerOptions { const result: CompilerOptions = {}; const optionsNameMap = getOptionsNameMap().optionsNameMap; @@ -2911,7 +2916,7 @@ export function parseJsonSourceFileConfigFileContent(sourceFile: TsConfigSourceF } /** @internal */ -export function setConfigFileInOptions(options: CompilerOptions, configFile: TsConfigSourceFile | undefined) { +export function setConfigFileInOptions(options: CompilerOptions, configFile: TsConfigSourceFile | undefined): void { if (configFile) { Object.defineProperty(options, "configFile", { enumerable: false, writable: false, value: configFile }); } @@ -3228,12 +3233,12 @@ function shouldReportNoInputFiles(fileNames: string[], canJsonReportNoInutFiles: } /** @internal */ -export function canJsonReportNoInputFiles(raw: any) { +export function canJsonReportNoInputFiles(raw: any): boolean { return !hasProperty(raw, "files") && !hasProperty(raw, "references"); } /** @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): boolean { const existingErrors = configParseDiagnostics.length; if (shouldReportNoInputFiles(fileNames, canJsonReportNoInutFiles)) { configParseDiagnostics.push(getErrorForNoInputFiles(configFileSpecs, configFileName)); @@ -3921,7 +3926,7 @@ export function matchesExclude( excludeSpecs: readonly string[] | undefined, useCaseSensitiveFileNames: boolean, currentDirectory: string, -) { +): boolean { return matchesExcludeWorker( pathToCheck, filter(excludeSpecs, spec => !invalidDotDotAfterRecursiveWildcard(spec)), diff --git a/src/compiler/core.ts b/src/compiler/core.ts index fc692f1a65d2b..9dac1832e5266 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -329,7 +329,7 @@ export function map(array: readonly T[] | undefined, f: (x: T, i: number) } /** @internal */ -export function* mapIterator(iter: Iterable, mapFn: (x: T) => U) { +export function* mapIterator(iter: Iterable, mapFn: (x: T) => U): Generator { for (const x of iter) { yield mapFn(x); } @@ -434,7 +434,7 @@ export function flatMapToMutable(array: readonly T[] | undefined, mapfn: ( } /** @internal */ -export function* flatMapIterator(iter: Iterable, mapfn: (x: T) => readonly U[] | Iterable | undefined) { +export function* flatMapIterator(iter: Iterable, mapfn: (x: T) => readonly U[] | Iterable | undefined): Generator { for (const x of iter) { const iter2 = mapfn(x); if (!iter2) continue; @@ -505,7 +505,7 @@ export function mapDefined(array: readonly T[] | undefined, mapFn: (x: T, } /** @internal */ -export function* mapDefinedIterator(iter: Iterable, mapFn: (x: T) => U | undefined) { +export function* mapDefinedIterator(iter: Iterable, mapFn: (x: T) => U | undefined): Generator { for (const x of iter) { const value = mapFn(x); if (value !== undefined) { @@ -515,7 +515,7 @@ export function* mapDefinedIterator(iter: Iterable, mapFn: (x: T) => U } /** @internal */ -export function getOrUpdate(map: Map, key: K, callback: () => V) { +export function getOrUpdate(map: Map, key: K, callback: () => V): V { if (map.has(key)) { return map.get(key)!; } @@ -525,7 +525,7 @@ export function getOrUpdate(map: Map, key: K, callback: () => V) { } /** @internal */ -export function tryAddToSet(set: Set, value: T) { +export function tryAddToSet(set: Set, value: T): boolean { if (!set.has(value)) { set.add(value); return true; @@ -534,7 +534,7 @@ export function tryAddToSet(set: Set, value: T) { } /** @internal */ -export function* singleIterator(value: T) { +export function* singleIterator(value: T): Generator { yield value; } @@ -1039,14 +1039,14 @@ export function toSorted(array: readonly T[], comparer?: Comparer): Sorted } /** @internal */ -export function* arrayReverseIterator(array: readonly T[]) { +export function* arrayReverseIterator(array: readonly T[]): Generator { for (let i = array.length - 1; i >= 0; i--) { yield array[i]; } } /** @internal */ -export function rangeEquals(array1: readonly T[], array2: readonly T[], pos: number, end: number) { +export function rangeEquals(array1: readonly T[], array2: readonly T[], pos: number, end: number): boolean { while (pos < end) { if (array1[pos] !== array2[pos]) { return false; @@ -1346,7 +1346,7 @@ export function arrayFrom(iterator: Iterable, map?: (t: T) => U): (T | } /** @internal */ -export function assign(t: T, ...args: (T | undefined)[]) { +export function assign(t: T, ...args: (T | undefined)[]): T { for (const arg of args) { if (arg === undefined) continue; for (const p in arg) { @@ -1366,7 +1366,7 @@ 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): boolean { if (left === right) return true; if (!left || !right) return false; for (const key in left) { @@ -1509,7 +1509,7 @@ export function extend(first: T1, second: T2): T1 & T2 { } /** @internal */ -export function copyProperties(first: T1, second: T2) { +export function copyProperties(first: T1, second: T2): void { for (const id in second) { if (hasOwnProperty.call(second, id)) { (first as any)[id] = second[id]; @@ -1824,7 +1824,7 @@ export function returnUndefined(): undefined { * * @internal */ -export function identity(x: T) { +export function identity(x: T): T { return x; } @@ -1871,7 +1871,7 @@ const fileNameLowerCaseRegExp = /[^\u0130\u0131\u00DFa-z0-9\\/:\-_. ]+/g; * * @internal */ -export function toFileNameLowerCase(x: string) { +export function toFileNameLowerCase(x: string): string { return fileNameLowerCaseRegExp.test(x) ? x.replace(fileNameLowerCaseRegExp, toLowerCase) : x; @@ -1933,7 +1933,7 @@ export const enum AssertionLevel { export type AnyFunction = (...args: never[]) => void; /** @internal */ -export function equateValues(a: T, b: T) { +export function equateValues(a: T, b: T): boolean { return a === b; } @@ -1947,7 +1947,7 @@ export function equateValues(a: T, b: T) { * * @internal */ -export function equateStringsCaseInsensitive(a: string, b: string) { +export function equateStringsCaseInsensitive(a: string, b: string): boolean { return a === b || a !== undefined && b !== undefined @@ -1962,7 +1962,7 @@ export function equateStringsCaseInsensitive(a: string, b: string) { * * @internal */ -export function equateStringsCaseSensitive(a: string, b: string) { +export function equateStringsCaseSensitive(a: string, b: string): boolean { return equateValues(a, b); } @@ -2026,7 +2026,7 @@ export function min(items: readonly T[], compare: Comparer): T | undefined * * @internal */ -export function compareStringsCaseInsensitive(a: string, b: string) { +export function compareStringsCaseInsensitive(a: string, b: string): Comparison { if (a === b) return Comparison.EqualTo; if (a === undefined) return Comparison.LessThan; if (b === undefined) return Comparison.GreaterThan; @@ -2047,7 +2047,7 @@ export function compareStringsCaseInsensitive(a: string, b: string) { * * @internal */ -export function compareStringsCaseInsensitiveEslintCompatible(a: string, b: string) { +export function compareStringsCaseInsensitiveEslintCompatible(a: string, b: string): Comparison { if (a === b) return Comparison.EqualTo; if (a === undefined) return Comparison.LessThan; if (b === undefined) return Comparison.GreaterThan; @@ -2073,7 +2073,7 @@ export function compareStringsCaseSensitive(a: string | undefined, b: string | u } /** @internal */ -export function getStringComparer(ignoreCase?: boolean) { +export function getStringComparer(ignoreCase?: boolean): typeof compareStringsCaseInsensitive { return ignoreCase ? compareStringsCaseInsensitive : compareStringsCaseSensitive; } @@ -2103,12 +2103,12 @@ let uiComparerCaseSensitive: Comparer | undefined; let uiLocale: string | undefined; /** @internal */ -export function getUILocale() { +export function getUILocale(): string | undefined { return uiLocale; } /** @internal */ -export function setUILocale(value: string | undefined) { +export function setUILocale(value: string | undefined): void { if (uiLocale !== value) { uiLocale = value; uiComparerCaseSensitive = undefined; @@ -2127,7 +2127,7 @@ export function setUILocale(value: string | undefined) { * * @internal */ -export function compareStringsCaseSensitiveUI(a: string, b: string) { +export function compareStringsCaseSensitiveUI(a: string, b: string): Comparison { uiComparerCaseSensitive ??= createUIStringComparer(uiLocale); return uiComparerCaseSensitive(a, b); } @@ -2265,7 +2265,7 @@ export function tryRemoveSuffix(str: string, suffix: string): string | undefined * * @internal */ -export function removeMinAndVersionNumbers(fileName: string) { +export function removeMinAndVersionNumbers(fileName: string): string { // We used to use the regex /[.-]((min)|(\d+(\.\d+)*))$/ and would just .replace it twice. // Unfortunately, that regex has O(n^2) performance because v8 doesn't match from the end of the string. // Instead, we now essentially scan the filename (backwards) ourselves. @@ -2353,7 +2353,7 @@ function unorderedRemoveItemAt(array: T[], index: number): void { * * @internal */ -export function unorderedRemoveItem(array: T[], item: T) { +export function unorderedRemoveItem(array: T[], item: T): boolean { return unorderedRemoveFirstItemWhere(array, element => element === item); } @@ -2441,7 +2441,7 @@ export function tryRemovePrefix(str: string, prefix: string, getCanonicalFileNam } /** @internal */ -export function isPatternMatch({ prefix, suffix }: Pattern, candidate: string) { +export function isPatternMatch({ prefix, suffix }: Pattern, candidate: string): boolean { return candidate.length >= prefix.length + suffix.length && startsWith(candidate, prefix) && endsWith(candidate, suffix); @@ -2449,7 +2449,7 @@ export function isPatternMatch({ prefix, suffix }: Pattern, candidate: string) { /** @internal */ export function and(f: (arg: T) => boolean, g: (arg: T) => boolean) { - return (arg: T) => f(arg) && g(arg); + return (arg: T): boolean => f(arg) && g(arg); } /** @internal */ @@ -2486,7 +2486,7 @@ 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): boolean { unchanged ??= noop; let newIndex = 0; let oldIndex = 0; @@ -2525,7 +2525,7 @@ export function enumerateInsertsAndDeletes(newItems: readonly T[], oldItem } /** @internal */ -export function cartesianProduct(arrays: readonly T[][]) { +export function cartesianProduct(arrays: readonly T[][]): T[][] { const result: T[][] = []; cartesianProductWorker(arrays, result, /*outer*/ undefined, 0); return result; diff --git a/src/compiler/debug.ts b/src/compiler/debug.ts index 298c628907eed..4bc7949044285 100644 --- a/src/compiler/debug.ts +++ b/src/compiler/debug.ts @@ -113,7 +113,7 @@ export interface LoggingHost { export namespace Debug { /* eslint-disable prefer-const */ let currentAssertionLevel = AssertionLevel.None; - export let currentLogLevel = LogLevel.Warning; + export let currentLogLevel: LogLevel = LogLevel.Warning; export let isDebugging = false; export let loggingHost: LoggingHost | undefined; /* eslint-enable prefer-const */ @@ -154,11 +154,11 @@ export namespace Debug { const assertionCache: Partial> = {}; - export function getAssertionLevel() { + export function getAssertionLevel(): AssertionLevel { return currentAssertionLevel; } - export function setAssertionLevel(level: AssertionLevel) { + export function setAssertionLevel(level: AssertionLevel): void { const prevAssertionLevel = currentAssertionLevel; currentAssertionLevel = level; @@ -365,7 +365,7 @@ export namespace Debug { export function type(value: unknown): asserts value is T; export function type(_value: unknown) {} - export function getFunctionName(func: AnyFunction) { + export function getFunctionName(func: AnyFunction): any { if (typeof func !== "function") { return ""; } @@ -386,7 +386,7 @@ export namespace Debug { /** * Formats an enum value as a string for debugging and debug assertions. */ - export function formatEnum(value = 0, enumObject: any, isFlags?: boolean) { + export function formatEnum(value = 0, enumObject: any, isFlags?: boolean): string { const members = getEnumMembers(enumObject); if (value === 0) { return members.length > 0 && members[0][0] === 0 ? members[0][1] : "0"; @@ -549,7 +549,7 @@ export namespace Debug { } } - export function attachFlowNodeDebugInfo(flowNode: FlowNode) { + export function attachFlowNodeDebugInfo(flowNode: FlowNode): FlowNode { if (isDebugInfoEnabled) { if (typeof Object.setPrototypeOf === "function") { // if we're in es2015, attach the method to a shared prototype for `FlowNode` @@ -589,7 +589,7 @@ export namespace Debug { } } - export function attachNodeArrayDebugInfo(array: NodeArray) { + export function attachNodeArrayDebugInfo(array: NodeArray): void { if (isDebugInfoEnabled) { if (typeof Object.setPrototypeOf === "function") { // if we're in es2015, attach the method to a shared prototype for `NodeArray` @@ -610,7 +610,7 @@ export namespace Debug { /** * Injects debug information into frequently used types. */ - export function enableDebugInfo() { + export function enableDebugInfo(): void { if (isDebugInfoEnabled) return; // avoid recomputing @@ -806,7 +806,7 @@ export namespace Debug { isDebugInfoEnabled = true; } - export function formatVariance(varianceFlags: VarianceFlags) { + export function formatVariance(varianceFlags: VarianceFlags): string { const variance = varianceFlags & VarianceFlags.VarianceMask; let result = variance === VarianceFlags.Invariant ? "in out" : variance === VarianceFlags.Bivariant ? "[bivariant]" : @@ -861,11 +861,11 @@ m2: ${(this.mapper2 as unknown as DebugTypeMapper).__debugToString().split("\n") return mapper; } - export function printControlFlowGraph(flowNode: FlowNode) { + export function printControlFlowGraph(flowNode: FlowNode): void { return console.log(formatControlFlowGraph(flowNode)); } - export function formatControlFlowGraph(flowNode: FlowNode) { + export function formatControlFlowGraph(flowNode: FlowNode): string { let nextDebugFlowId = -1; function getDebugFlowNodeId(f: FlowNode) { diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 6f68329ba0a90..5cca7805911be 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -428,7 +428,7 @@ import * as performance from "./_namespaces/ts.performance.js"; const brackets = createBracketsMap(); /** @internal */ -export function isBuildInfoFile(file: string) { +export function isBuildInfoFile(file: string): boolean { return fileExtensionIs(file, Extension.TsBuildInfo); } @@ -450,7 +450,7 @@ export function forEachEmittedFile( forceDtsEmit = false, onlyBuildInfo?: boolean, includeBuildInfo?: boolean, -) { +): T | undefined { const sourceFiles = isArray(sourceFilesOrTargetSourceFile) ? sourceFilesOrTargetSourceFile : getSourceFilesToEmit(host, sourceFilesOrTargetSourceFile, forceDtsEmit); const options = host.getCompilerOptions(); if (!onlyBuildInfo) { @@ -478,7 +478,7 @@ export function forEachEmittedFile( } } -export function getTsBuildInfoEmitOutputFilePath(options: CompilerOptions) { +export function getTsBuildInfoEmitOutputFilePath(options: CompilerOptions): string | undefined { const configFile = options.configFilePath; if (!canEmitTsBuildInfo(options)) return undefined; if (options.tsBuildInfoFile) return options.tsBuildInfoFile; @@ -500,7 +500,7 @@ export function getTsBuildInfoEmitOutputFilePath(options: CompilerOptions) { } /** @internal */ -export function canEmitTsBuildInfo(options: CompilerOptions) { +export function canEmitTsBuildInfo(options: CompilerOptions): boolean { return isIncrementalCompilation(options) || !!options.tscBuild; } @@ -561,12 +561,12 @@ function getOutputPathWithoutChangingExt( } /** @internal */ -export function getOutputDeclarationFileName(inputFileName: string, configFile: ParsedCommandLine, ignoreCase: boolean, getCommonSourceDirectory = () => getCommonSourceDirectoryOfConfig(configFile, ignoreCase)) { +export function getOutputDeclarationFileName(inputFileName: string, configFile: ParsedCommandLine, ignoreCase: boolean, getCommonSourceDirectory = (): string => getCommonSourceDirectoryOfConfig(configFile, ignoreCase)): string { return getOutputDeclarationFileNameWorker(inputFileName, configFile.options, ignoreCase, getCommonSourceDirectory); } /** @internal */ -export function getOutputDeclarationFileNameWorker(inputFileName: string, options: CompilerOptions, ignoreCase: boolean, getCommonSourceDirectory: () => string) { +export function getOutputDeclarationFileNameWorker(inputFileName: string, options: CompilerOptions, ignoreCase: boolean, getCommonSourceDirectory: () => string): string { return changeExtension( getOutputPathWithoutChangingExt(inputFileName, ignoreCase, options.declarationDir || options.outDir, getCommonSourceDirectory), getDeclarationEmitExtensionForPath(inputFileName), @@ -722,7 +722,7 @@ export function getFirstProjectOutput(configFile: ParsedCommandLine, ignoreCase: } /** @internal */ -export function emitResolverSkipsTypeChecking(emitOnly: boolean | EmitOnly | undefined, forceDtsEmit: boolean | undefined) { +export function emitResolverSkipsTypeChecking(emitOnly: boolean | EmitOnly | undefined, forceDtsEmit: boolean | undefined): boolean { return !!forceDtsEmit && !!emitOnly; } @@ -1113,7 +1113,7 @@ export function emitFiles( } /** @internal */ -export function getBuildInfoText(buildInfo: BuildInfo) { +export function getBuildInfoText(buildInfo: BuildInfo): string { return JSON.stringify(buildInfo); } @@ -1174,16 +1174,16 @@ const enum PipelinePhase { } /** @internal */ -export const createPrinterWithDefaults = /* @__PURE__ */ memoize(() => createPrinter({})); +export const createPrinterWithDefaults: () => Printer = /* @__PURE__ */ memoize(() => createPrinter({})); /** @internal */ -export const createPrinterWithRemoveComments = /* @__PURE__ */ memoize(() => createPrinter({ removeComments: true })); +export const createPrinterWithRemoveComments: () => Printer = /* @__PURE__ */ memoize(() => createPrinter({ removeComments: true })); /** @internal */ -export const createPrinterWithRemoveCommentsNeverAsciiEscape = /* @__PURE__ */ memoize(() => createPrinter({ removeComments: true, neverAsciiEscape: true })); +export const createPrinterWithRemoveCommentsNeverAsciiEscape: () => Printer = /* @__PURE__ */ memoize(() => createPrinter({ removeComments: true, neverAsciiEscape: true })); /** @internal */ -export const createPrinterWithRemoveCommentsOmitTrailingSemicolon = /* @__PURE__ */ memoize(() => createPrinter({ removeComments: true, omitTrailingSemicolon: true })); +export const createPrinterWithRemoveCommentsOmitTrailingSemicolon: () => Printer = /* @__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. diff --git a/src/compiler/executeCommandLine.ts b/src/compiler/executeCommandLine.ts index 0f8fdd25ccc2a..b3b92260081d7 100644 --- a/src/compiler/executeCommandLine.ts +++ b/src/compiler/executeCommandLine.ts @@ -733,7 +733,7 @@ function executeCommandLineWorker( } /** @internal */ -export function isBuild(commandLineArgs: readonly string[]) { +export function isBuild(commandLineArgs: readonly string[]): boolean { if (commandLineArgs.length > 0 && commandLineArgs[0].charCodeAt(0) === CharacterCodes.minus) { const firstOption = commandLineArgs[0].slice(commandLineArgs[0].charCodeAt(1) === CharacterCodes.minus ? 2 : 1).toLowerCase(); return firstOption === "build" || firstOption === "b"; diff --git a/src/compiler/expressionToTypeNode.ts b/src/compiler/expressionToTypeNode.ts index 48f8434137bc9..f984fbdb2bd86 100644 --- a/src/compiler/expressionToTypeNode.ts +++ b/src/compiler/expressionToTypeNode.ts @@ -66,7 +66,15 @@ import { } from "./_namespaces/ts.js"; /** @internal */ -export function createSyntacticTypeNodeBuilder(options: CompilerOptions, resolver: SyntacticTypeNodeBuilderResolver) { +export function createSyntacticTypeNodeBuilder( + options: CompilerOptions, + resolver: SyntacticTypeNodeBuilderResolver, +): { + typeFromExpression: (node: Expression, context: SyntacticTypeNodeBuilderContext, isConstContext?: boolean, requiresAddingUndefined?: boolean, preserveLiterals?: boolean) => boolean | undefined; + serializeTypeOfDeclaration: (node: HasInferredType, context: SyntacticTypeNodeBuilderContext) => boolean | undefined; + serializeReturnTypeForSignature: (node: SignatureDeclaration | JSDocSignature, context: SyntacticTypeNodeBuilderContext) => boolean | undefined; + serializeTypeOfExpression: (expr: Expression, context: SyntacticTypeNodeBuilderContext, addUndefined?: boolean, preserveLiterals?: boolean) => boolean; +} { const strictNullChecks = getStrictOptionValue(options, "strictNullChecks"); return { diff --git a/src/compiler/factory/emitHelpers.ts b/src/compiler/factory/emitHelpers.ts index 3b3dc97ddb43f..17e28a9438e5f 100644 --- a/src/compiler/factory/emitHelpers.ts +++ b/src/compiler/factory/emitHelpers.ts @@ -685,7 +685,7 @@ export function createEmitHelperFactory(context: TransformationContext): EmitHel } /** @internal */ -export function compareEmitHelpers(x: EmitHelper, y: EmitHelper) { +export function compareEmitHelpers(x: EmitHelper, y: EmitHelper): Comparison { if (x === y) return Comparison.EqualTo; if (x.priority === y.priority) return Comparison.EqualTo; if (x.priority === undefined) return Comparison.GreaterThan; diff --git a/src/compiler/factory/emitNode.ts b/src/compiler/factory/emitNode.ts index 5b90c578148d1..beadc29d4ca6b 100644 --- a/src/compiler/factory/emitNode.ts +++ b/src/compiler/factory/emitNode.ts @@ -59,7 +59,7 @@ export function getOrCreateEmitNode(node: Node): EmitNode { * Clears any `EmitNode` entries from parse-tree nodes. * @param sourceFile A source file. */ -export function disposeEmitNodes(sourceFile: SourceFile | undefined) { +export function disposeEmitNodes(sourceFile: SourceFile | undefined): void { // During transformation we may need to annotate a parse tree node with transient // transformation properties. As parse tree nodes live longer than transformation // nodes, we need to make sure we reclaim any memory allocated for custom ranges @@ -89,7 +89,7 @@ export function removeAllComments(node: T): T { /** * Sets flags that control emit behavior of a node. */ -export function setEmitFlags(node: T, emitFlags: EmitFlags) { +export function setEmitFlags(node: T, emitFlags: EmitFlags): T { getOrCreateEmitNode(node).flags = emitFlags; return node; } @@ -99,7 +99,7 @@ export function setEmitFlags(node: T, emitFlags: EmitFlags) { * * @internal */ -export function addEmitFlags(node: T, emitFlags: EmitFlags) { +export function addEmitFlags(node: T, emitFlags: EmitFlags): T { const emitNode = getOrCreateEmitNode(node); emitNode.flags = emitNode.flags | emitFlags; return node; @@ -110,7 +110,7 @@ export function addEmitFlags(node: T, emitFlags: EmitFlags) { * * @internal */ -export function setInternalEmitFlags(node: T, emitFlags: InternalEmitFlags) { +export function setInternalEmitFlags(node: T, emitFlags: InternalEmitFlags): T { getOrCreateEmitNode(node).internalFlags = emitFlags; return node; } @@ -120,7 +120,7 @@ export function setInternalEmitFlags(node: T, emitFlags: Interna * * @internal */ -export function addInternalEmitFlags(node: T, emitFlags: InternalEmitFlags) { +export function addInternalEmitFlags(node: T, emitFlags: InternalEmitFlags): T { const emitNode = getOrCreateEmitNode(node); emitNode.internalFlags = emitNode.internalFlags | emitFlags; return node; @@ -136,7 +136,7 @@ export function getSourceMapRange(node: Node): SourceMapRange { /** * Sets a custom text range to use when emitting source maps. */ -export function setSourceMapRange(node: T, range: SourceMapRange | undefined) { +export function setSourceMapRange(node: T, range: SourceMapRange | undefined): T { getOrCreateEmitNode(node).sourceMapRange = range; return node; } @@ -151,7 +151,7 @@ export function getTokenSourceMapRange(node: Node, token: SyntaxKind): SourceMap /** * Sets the TextRange to use for source maps for a token of a node. */ -export function setTokenSourceMapRange(node: T, token: SyntaxKind, range: SourceMapRange | undefined) { +export function setTokenSourceMapRange(node: T, token: SyntaxKind, range: SourceMapRange | undefined): T { const emitNode = getOrCreateEmitNode(node); const tokenSourceMapRanges = emitNode.tokenSourceMapRanges ?? (emitNode.tokenSourceMapRanges = []); tokenSourceMapRanges[token] = range; @@ -163,7 +163,7 @@ export function setTokenSourceMapRange(node: T, token: SyntaxKin * * @internal */ -export function getStartsOnNewLine(node: Node) { +export function getStartsOnNewLine(node: Node): boolean | undefined { return node.emitNode?.startsOnNewLine; } @@ -172,7 +172,7 @@ export function getStartsOnNewLine(node: Node) { * * @internal */ -export function setStartsOnNewLine(node: T, newLine: boolean) { +export function setStartsOnNewLine(node: T, newLine: boolean): T { getOrCreateEmitNode(node).startsOnNewLine = newLine; return node; } @@ -187,7 +187,7 @@ export function getCommentRange(node: Node): TextRange { /** * Sets a custom text range to use when emitting comments. */ -export function setCommentRange(node: T, range: TextRange) { +export function setCommentRange(node: T, range: TextRange): T { getOrCreateEmitNode(node).commentRange = range; return node; } @@ -196,12 +196,12 @@ export function getSyntheticLeadingComments(node: Node): SynthesizedComment[] | return node.emitNode?.leadingComments; } -export function setSyntheticLeadingComments(node: T, comments: SynthesizedComment[] | undefined) { +export function setSyntheticLeadingComments(node: T, comments: SynthesizedComment[] | undefined): T { getOrCreateEmitNode(node).leadingComments = comments; return node; } -export function addSyntheticLeadingComment(node: T, kind: SyntaxKind.SingleLineCommentTrivia | SyntaxKind.MultiLineCommentTrivia, text: string, hasTrailingNewLine?: boolean) { +export function addSyntheticLeadingComment(node: T, kind: SyntaxKind.SingleLineCommentTrivia | SyntaxKind.MultiLineCommentTrivia, text: string, hasTrailingNewLine?: boolean): T { return setSyntheticLeadingComments(node, append(getSyntheticLeadingComments(node), { kind, pos: -1, end: -1, hasTrailingNewLine, text })); } @@ -209,12 +209,12 @@ export function getSyntheticTrailingComments(node: Node): SynthesizedComment[] | return node.emitNode?.trailingComments; } -export function setSyntheticTrailingComments(node: T, comments: SynthesizedComment[] | undefined) { +export function setSyntheticTrailingComments(node: T, comments: SynthesizedComment[] | undefined): T { getOrCreateEmitNode(node).trailingComments = comments; return node; } -export function addSyntheticTrailingComment(node: T, kind: SyntaxKind.SingleLineCommentTrivia | SyntaxKind.MultiLineCommentTrivia, text: string, hasTrailingNewLine?: boolean) { +export function addSyntheticTrailingComment(node: T, kind: SyntaxKind.SingleLineCommentTrivia | SyntaxKind.MultiLineCommentTrivia, text: string, hasTrailingNewLine?: boolean): T { return setSyntheticTrailingComments(node, append(getSyntheticTrailingComments(node), { kind, pos: -1, end: -1, hasTrailingNewLine, text })); } @@ -286,7 +286,7 @@ export function getEmitHelpers(node: Node): EmitHelper[] | undefined { /** * Moves matching emit helpers from a source node to a target node. */ -export function moveEmitHelpers(source: Node, target: Node, predicate: (helper: EmitHelper) => boolean) { +export function moveEmitHelpers(source: Node, target: Node, predicate: (helper: EmitHelper) => boolean): void { const sourceEmitNode = source.emitNode; const sourceEmitHelpers = sourceEmitNode && sourceEmitNode.helpers; if (!some(sourceEmitHelpers)) return; @@ -348,7 +348,7 @@ export function getTypeNode(node: T): TypeNode | undefined { } /** @internal */ -export function setIdentifierTypeArguments(node: T, typeArguments: NodeArray | undefined) { +export function setIdentifierTypeArguments(node: T, typeArguments: NodeArray | undefined): T { getOrCreateEmitNode(node).identifierTypeArguments = typeArguments; return node; } @@ -359,7 +359,7 @@ export function getIdentifierTypeArguments(node: Identifier): NodeArray(node: T, autoGenerate: AutoGenerateInfo | undefined) { +export function setIdentifierAutoGenerate(node: T, autoGenerate: AutoGenerateInfo | undefined): T { getOrCreateEmitNode(node).autoGenerate = autoGenerate; return node; } @@ -370,7 +370,7 @@ export function getIdentifierAutoGenerate(node: Identifier | PrivateIdentifier): } /** @internal */ -export function setIdentifierGeneratedImportReference(node: T, value: ImportSpecifier | undefined) { +export function setIdentifierGeneratedImportReference(node: T, value: ImportSpecifier | undefined): T { getOrCreateEmitNode(node).generatedImportReference = value; return node; } diff --git a/src/compiler/factory/nodeChildren.ts b/src/compiler/factory/nodeChildren.ts index 3946ee89417bc..da8e074415e00 100644 --- a/src/compiler/factory/nodeChildren.ts +++ b/src/compiler/factory/nodeChildren.ts @@ -41,7 +41,7 @@ export function setNodeChildren(node: Node, sourceFile: SourceFileLike, children } /** @internal */ -export function unsetNodeChildren(node: Node, origSourceFile: SourceFileLike) { +export function unsetNodeChildren(node: Node, origSourceFile: SourceFileLike): void { if (node.kind === SyntaxKind.SyntaxList) { // Syntax lists are synthesized and we store their children directly on them. // They are a special case where we expect incremental parsing to toss them away entirely @@ -52,7 +52,7 @@ export function unsetNodeChildren(node: Node, origSourceFile: SourceFileLike) { } /** @internal */ -export function transferSourceFileChildren(sourceFile: SourceFileLike, targetSourceFile: SourceFileLike) { +export function transferSourceFileChildren(sourceFile: SourceFileLike, targetSourceFile: SourceFileLike): void { const map = sourceFileToNodeChildren.get(sourceFile); if (map !== undefined) { sourceFileToNodeChildren.delete(sourceFile); diff --git a/src/compiler/factory/nodeFactory.ts b/src/compiler/factory/nodeFactory.ts index c90e4c71f19f5..54362db2ac350 100644 --- a/src/compiler/factory/nodeFactory.ts +++ b/src/compiler/factory/nodeFactory.ts @@ -476,7 +476,7 @@ export const enum NodeFactoryFlags { const nodeFactoryPatchers: ((factory: NodeFactory) => void)[] = []; /** @internal @knipignore */ -export function addNodeFactoryPatcher(fn: (factory: NodeFactory) => void) { +export function addNodeFactoryPatcher(fn: (factory: NodeFactory) => void): void { nodeFactoryPatchers.push(fn); } @@ -7382,7 +7382,7 @@ const syntheticFactory: BaseNodeFactory = { createBaseNode: kind => makeSynthetic(baseFactory.createBaseNode(kind)), }; -export const factory = createNodeFactory(NodeFactoryFlags.NoIndentationOnFreshPropertyAccess, syntheticFactory); +export const factory: NodeFactory = createNodeFactory(NodeFactoryFlags.NoIndentationOnFreshPropertyAccess, syntheticFactory); let SourceMapSource: new (fileName: string, text: string, skipTrivia?: (pos: number) => number) => SourceMapSource; diff --git a/src/compiler/factory/utilities.ts b/src/compiler/factory/utilities.ts index 852017bd5012e..c91221a8dd9da 100644 --- a/src/compiler/factory/utilities.ts +++ b/src/compiler/factory/utilities.ts @@ -179,7 +179,7 @@ import { // Compound nodes /** @internal */ -export function createEmptyExports(factory: NodeFactory) { +export function createEmptyExports(factory: NodeFactory): ExportDeclaration { return factory.createExportDeclaration(/*modifiers*/ undefined, /*isTypeOnly*/ false, factory.createNamedExports([]), /*moduleSpecifier*/ undefined); } @@ -512,7 +512,13 @@ 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, +): Expression { 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"); @@ -546,7 +552,7 @@ export function expandPreOrPostfixIncrementOrDecrementExpression(factory: NodeFa * * @internal */ -export function isInternalName(node: Identifier) { +export function isInternalName(node: Identifier): boolean { return (getEmitFlags(node) & EmitFlags.InternalName) !== 0; } @@ -555,7 +561,7 @@ export function isInternalName(node: Identifier) { * * @internal */ -export function isLocalName(node: Identifier) { +export function isLocalName(node: Identifier): boolean { return (getEmitFlags(node) & EmitFlags.LocalName) !== 0; } @@ -565,7 +571,7 @@ export function isLocalName(node: Identifier) { * * @internal */ -export function isExportName(node: Identifier) { +export function isExportName(node: Identifier): boolean { return (getEmitFlags(node) & EmitFlags.ExportName) !== 0; } @@ -589,7 +595,7 @@ export function findUseStrictPrologue(statements: readonly Statement[]): Stateme } /** @internal */ -export function startsWithUseStrict(statements: readonly Statement[]) { +export function startsWithUseStrict(statements: readonly Statement[]): boolean { const firstStatement = firstOrUndefined(statements); return firstStatement !== undefined && isPrologueDirective(firstStatement) @@ -621,7 +627,7 @@ export function getJSDocTypeAssertionType(node: JSDocTypeAssertion): TypeNode { } /** @internal */ -export function isOuterExpression(node: Node, kinds = OuterExpressionKinds.All): node is OuterExpression { +export function isOuterExpression(node: Node, kinds: OuterExpressionKinds = OuterExpressionKinds.All): node is OuterExpression { switch (node.kind) { case SyntaxKind.ParenthesizedExpression: if (kinds & OuterExpressionKinds.ExcludeJSDocTypeAssertion && isJSDocTypeAssertion(node)) { @@ -656,7 +662,7 @@ export function skipOuterExpressions(node: Node, kinds = OuterExpressionKinds.Al } /** @internal */ -export function walkUpOuterExpressions(node: Expression, kinds = OuterExpressionKinds.All): Node { +export function walkUpOuterExpressions(node: Expression, kinds: OuterExpressionKinds = OuterExpressionKinds.All): Node { let parent = node.parent; while (isOuterExpression(parent, kinds)) { parent = parent.parent; @@ -671,21 +677,21 @@ export function startOnNewLine(node: T): T { } /** @internal */ -export function getExternalHelpersModuleName(node: SourceFile) { +export function getExternalHelpersModuleName(node: SourceFile): Identifier | undefined { const parseNode = getOriginalNode(node, isSourceFile); const emitNode = parseNode && parseNode.emitNode; return emitNode && emitNode.externalHelpersModuleName; } /** @internal */ -export function hasRecordedExternalHelpers(sourceFile: SourceFile) { +export function hasRecordedExternalHelpers(sourceFile: SourceFile): boolean { const parseNode = getOriginalNode(sourceFile, isSourceFile); const emitNode = parseNode && parseNode.emitNode; return !!emitNode && (!!emitNode.externalHelpersModuleName || !!emitNode.externalHelpers); } /** @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): ImportDeclaration | undefined { if (compilerOptions.importHelpers && isEffectiveExternalModule(sourceFile, compilerOptions)) { let namedBindings: NamedImportBindings | undefined; const moduleKind = getEmitModuleKind(compilerOptions); @@ -800,7 +806,7 @@ 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): StringLiteral | undefined { const moduleName = getExternalModuleName(importNode); if (moduleName && isStringLiteral(moduleName)) { return tryGetModuleNameFromDeclaration(importNode, host, factory, resolver, compilerOptions) @@ -1078,7 +1084,7 @@ export function getElementsOfBindingOrAssignmentPattern(name: BindingOrAssignmen } /** @internal */ -export function getJSDocTypeAliasName(fullName: JSDocNamespaceBody | undefined) { +export function getJSDocTypeAliasName(fullName: JSDocNamespaceBody | undefined): Identifier | undefined { if (fullName) { let rightNode = fullName; while (true) { @@ -1504,7 +1510,7 @@ export function elideNodes(factory: NodeFactory, nodes: NodeArra * * @internal */ -export function getNodeForGeneratedName(name: GeneratedIdentifier | GeneratedPrivateIdentifier) { +export function getNodeForGeneratedName(name: GeneratedIdentifier | GeneratedPrivateIdentifier): Node | GeneratedIdentifier | GeneratedPrivateIdentifier { const autoGenerate = name.emitNode.autoGenerate; if (autoGenerate.flags & GeneratedIdentifierFlags.Node) { const autoGenerateId = autoGenerate.id; @@ -1597,7 +1603,7 @@ 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): PropertyDeclaration { return factory.updatePropertyDeclaration( node, modifiers, @@ -1711,7 +1717,7 @@ function flattenCommaListWorker(node: Expression, expressions: Expression[]) { * * @internal */ -export function flattenCommaList(node: Expression) { +export function flattenCommaList(node: Expression): Expression[] { const expressions: Expression[] = []; flattenCommaListWorker(node, expressions); return expressions; diff --git a/src/compiler/moduleNameResolver.ts b/src/compiler/moduleNameResolver.ts index 850a8a7f381cb..dcbc239381b10 100644 --- a/src/compiler/moduleNameResolver.ts +++ b/src/compiler/moduleNameResolver.ts @@ -296,7 +296,7 @@ function initializeResolutionField(value: T[]): T[] | undefined { return value.length ? value : undefined; } /** @internal */ -export function updateResolutionField(to: T[] | undefined, value: T[] | undefined) { +export function updateResolutionField(to: T[] | undefined, value: T[] | undefined): T[] | undefined { if (!value?.length) return to; if (!to?.length) return value; to.push(...value); @@ -453,7 +453,10 @@ function readPackageJsonTypesVersionPaths(jsonContent: PackageJson, state: Modul let typeScriptVersion: Version | undefined; /** @internal */ -export function getPackageJsonTypesVersionsPaths(typesVersions: MapLike>) { +export function getPackageJsonTypesVersionsPaths(typesVersions: MapLike>): { + version: string; + paths: MapLike; +} | undefined { if (!typeScriptVersion) typeScriptVersion = new Version(version); for (const key in typesVersions) { @@ -747,7 +750,7 @@ function getNodeResolutionFeatures(options: CompilerOptions) { } /** @internal */ -export function getConditions(options: CompilerOptions, resolutionMode?: ResolutionMode) { +export function getConditions(options: CompilerOptions, resolutionMode?: ResolutionMode): string[] { const moduleResolution = getEmitModuleResolutionKind(options); if (resolutionMode === undefined) { if (moduleResolution === ModuleResolutionKind.Bundler) { @@ -951,7 +954,7 @@ function compilerOptionValueToString(value: unknown): string { } /** @internal */ -export function getKeyForCompilerOptions(options: CompilerOptions, affectingOptionDeclarations: readonly CommandLineOption[]) { +export function getKeyForCompilerOptions(options: CompilerOptions, affectingOptionDeclarations: readonly CommandLineOption[]): string { return affectingOptionDeclarations.map(option => compilerOptionValueToString(getCompilerOptionValue(options, option))).join("|") + `|${options.pathsBasePath}`; } @@ -1382,7 +1385,10 @@ export function createTypeReferenceDirectiveResolutionCache( } /** @internal */ -export function getOptionsForLibraryResolution(options: CompilerOptions) { +export function getOptionsForLibraryResolution(options: CompilerOptions): { + moduleResolution: ModuleResolutionKind; + traceResolution: boolean | undefined; +} { return { moduleResolution: ModuleResolutionKind.Node10, traceResolution: options.traceResolution }; } @@ -2553,7 +2559,7 @@ export function parsePackageName(moduleName: string): { packageName: string; res } /** @internal */ -export function allKeysStartWithDot(obj: MapLike) { +export function allKeysStartWithDot(obj: MapLike): boolean { return every(getOwnKeys(obj), k => startsWith(k, ".")); } @@ -2674,7 +2680,7 @@ function loadModuleFromImports(extensions: Extensions, moduleName: string, direc * From https://github.com/nodejs/node/blob/8f39f51cbbd3b2de14b9ee896e26421cc5b20121/lib/internal/modules/esm/resolve.js#L722 - * "longest" has some nuance as to what "longest" means in the presence of pattern trailers */ -export function comparePatternKeys(a: string, b: string) { +export function comparePatternKeys(a: string, b: string): 1 | 0 | -1 { const aPatternIndex = a.indexOf("*"); const bPatternIndex = b.indexOf("*"); const baseLenA = aPatternIndex === -1 ? a.length : aPatternIndex + 1; @@ -2962,7 +2968,7 @@ function getLoadModuleFromTargetImportOrExport(extensions: Extensions, state: Mo } /** @internal */ -export function isApplicableVersionedTypesKey(conditions: readonly string[], key: string) { +export function isApplicableVersionedTypesKey(conditions: readonly string[], key: string): boolean { if (!conditions.includes("types")) return false; // only apply versioned types conditions if the types condition is applied if (!startsWith(key, "types@")) return false; const range = VersionRange.tryParse(key.substring("types@".length)); @@ -3302,7 +3308,7 @@ function resolveFromTypeRoot(moduleName: string, state: ModuleResolutionState) { // Program errors validate that `noEmit` or `emitDeclarationOnly` is also set, // so this function doesn't check them to avoid propagating errors. /** @internal */ -export function shouldAllowImportingTsExtension(compilerOptions: CompilerOptions, fromFileName?: string) { +export function shouldAllowImportingTsExtension(compilerOptions: CompilerOptions, fromFileName?: string): boolean | "" | undefined { return !!compilerOptions.allowImportingTsExtensions || fromFileName && isDeclarationFileName(fromFileName); } diff --git a/src/compiler/moduleSpecifiers.ts b/src/compiler/moduleSpecifiers.ts index f380ff56a02f6..bed14f9628c1b 100644 --- a/src/compiler/moduleSpecifiers.ts +++ b/src/compiler/moduleSpecifiers.ts @@ -357,7 +357,7 @@ export function getModuleSpecifiersWithCacheInfo( importingSourceFile: SourceFile | FutureSourceFile, host: ModuleSpecifierResolutionHost, userPreferences: UserPreferences, - options: ModuleSpecifierOptions = {}, + options: ModuleSpecifierOptions | undefined = {}, forAutoImport: boolean, ): ModuleSpecifierResult { let computedWithoutCache = false; @@ -1309,7 +1309,7 @@ function processEnding(fileName: string, allowedEndings: readonly ModuleSpecifie } /** @internal */ -export function tryGetRealFileNameForNonJsDeclarationFileName(fileName: string) { +export function tryGetRealFileNameForNonJsDeclarationFileName(fileName: string): string | undefined { const baseName = getBaseFileName(fileName); if (!endsWith(fileName, Extension.Ts) || !baseName.includes(".d.") || fileExtensionIsOneOf(baseName, [Extension.Dts])) return undefined; const noExtension = removeExtension(fileName, Extension.Ts); diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index b20d4b8b8b52e..e6d068a796fa7 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -458,14 +458,14 @@ function visitNodes(cbNode: (node: Node) => T, cbNodes: ((node: NodeArray 0; } @@ -66,7 +66,7 @@ export function isRootedDiskPath(path: string) { * * @internal */ -export function isDiskPathRoot(path: string) { +export function isDiskPathRoot(path: string): boolean { const rootLength = getEncodedRootLength(path); return rootLength > 0 && rootLength === path.length; } @@ -137,7 +137,7 @@ export function fileExtensionIsOneOf(path: string, extensions: readonly string[] * * @internal */ -export function hasTrailingDirectorySeparator(path: string) { +export function hasTrailingDirectorySeparator(path: string): boolean { return path.length > 0 && isAnyDirectorySeparator(path.charCodeAt(path.length - 1)); } @@ -247,7 +247,7 @@ function getEncodedRootLength(path: string): number { * * @internal */ -export function getRootLength(path: string) { +export function getRootLength(path: string): number { const rootLength = getEncodedRootLength(path); return rootLength < 0 ? ~rootLength : rootLength; } @@ -509,7 +509,7 @@ export function getPathComponents(path: string, currentDirectory = "") { * * @internal */ -export function getPathFromPathComponents(pathComponents: readonly T[], length?: number) { +export function getPathFromPathComponents(pathComponents: readonly T[], length?: number): T { if (pathComponents.length === 0) return "" as T; const root = pathComponents[0] && ensureTrailingDirectorySeparator(pathComponents[0]); @@ -535,7 +535,7 @@ export function normalizeSlashes(path: string): string { * * @internal */ -export function reducePathComponents(components: readonly string[]) { +export function reducePathComponents(components: readonly string[]): string[] { if (!some(components)) return []; const reduced = [components[0]]; for (let i = 1; i < components.length; i++) { @@ -619,12 +619,12 @@ export function resolvePath(path: string, ...paths: (string | undefined)[]): str * * @internal */ -export function getNormalizedPathComponents(path: string, currentDirectory: string | undefined) { +export function getNormalizedPathComponents(path: string, currentDirectory: string | undefined): string[] { return reducePathComponents(getPathComponents(path, currentDirectory)); } /** @internal */ -export function getNormalizedAbsolutePath(fileName: string, currentDirectory: string | undefined) { +export function getNormalizedAbsolutePath(fileName: string, currentDirectory: string | undefined): string { return getPathFromPathComponents(getNormalizedPathComponents(fileName, currentDirectory)); } @@ -654,7 +654,7 @@ function getPathWithoutRoot(pathComponents: readonly string[]) { } /** @internal */ -export function getNormalizedAbsolutePathWithoutRoot(fileName: string, currentDirectory: string | undefined) { +export function getNormalizedAbsolutePathWithoutRoot(fileName: string, currentDirectory: string | undefined): string { return getPathWithoutRoot(getNormalizedPathComponents(fileName, currentDirectory)); } @@ -767,7 +767,7 @@ export function changeAnyExtension(path: string, ext: string, extensions?: strin * changeFullExtension("file.d.ts", ".js") === "file.js" * ``` */ -export function changeFullExtension(path: string, newExtension: string) { +export function changeFullExtension(path: string, newExtension: string): string { const declarationExtension = getDeclarationFileExtension(path); if (declarationExtension) { return path.slice(0, path.length - declarationExtension.length) + @@ -822,7 +822,7 @@ function comparePathsWorker(a: string, b: string, componentComparer: (a: string, * * @internal */ -export function comparePathsCaseSensitive(a: string, b: string) { +export function comparePathsCaseSensitive(a: string, b: string): Comparison { return comparePathsWorker(a, b, compareStringsCaseSensitive); } @@ -831,7 +831,7 @@ export function comparePathsCaseSensitive(a: string, b: string) { * * @internal */ -export function comparePathsCaseInsensitive(a: string, b: string) { +export function comparePathsCaseInsensitive(a: string, b: string): Comparison { return comparePathsWorker(a, b, compareStringsCaseInsensitive); } @@ -960,12 +960,12 @@ export function convertToRelativePath(absoluteOrRelativePath: string, basePath: } /** @internal */ -export function getRelativePathFromFile(from: string, to: string, getCanonicalFileName: GetCanonicalFileName) { +export function getRelativePathFromFile(from: string, to: string, getCanonicalFileName: GetCanonicalFileName): string { return ensurePathIsNonModuleName(getRelativePathFromDirectory(getDirectoryPath(from), to, getCanonicalFileName)); } /** @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): string { const pathComponents = getPathComponentsRelativeTo( resolvePath(currentDirectory, directoryPathOrUrl), resolvePath(currentDirectory, relativeOrAbsolutePath), @@ -1010,6 +1010,6 @@ export function forEachAncestorDirectory(directory: P, call } /** @internal */ -export function isNodeModulesDirectory(dirPath: Path) { +export function isNodeModulesDirectory(dirPath: Path): boolean { return endsWith(dirPath, "/node_modules"); } diff --git a/src/compiler/performance.ts b/src/compiler/performance.ts index 6784d1d0f7dce..e176474b37ba8 100644 --- a/src/compiler/performance.ts +++ b/src/compiler/performance.ts @@ -26,7 +26,7 @@ export interface Timer { } /** @internal */ -export function createTimerIf(condition: boolean, measureName: string, startMarkName: string, endMarkName: string) { +export function createTimerIf(condition: boolean, measureName: string, startMarkName: string, endMarkName: string): Timer { return condition ? createTimer(measureName, startMarkName, endMarkName) : nullTimer; } @@ -71,7 +71,7 @@ const durations = new Map(); * * @internal */ -export function mark(markName: string) { +export function mark(markName: string): void { if (enabled) { const count = counts.get(markName) ?? 0; counts.set(markName, count + 1); @@ -94,7 +94,7 @@ export function mark(markName: string) { * * @internal */ -export function measure(measureName: string, startMarkName?: string, endMarkName?: string) { +export function measure(measureName: string, startMarkName?: string, endMarkName?: string): void { if (enabled) { const end = (endMarkName !== undefined ? marks.get(endMarkName) : undefined) ?? timestamp(); const start = (startMarkName !== undefined ? marks.get(startMarkName) : undefined) ?? timeorigin; @@ -111,7 +111,7 @@ export function measure(measureName: string, startMarkName?: string, endMarkName * * @internal */ -export function getCount(markName: string) { +export function getCount(markName: string): number { return counts.get(markName) || 0; } @@ -122,7 +122,7 @@ export function getCount(markName: string) { * * @internal */ -export function getDuration(measureName: string) { +export function getDuration(measureName: string): number { return durations.get(measureName) || 0; } @@ -133,24 +133,24 @@ export function getDuration(measureName: string) { * * @internal */ -export function forEachMeasure(cb: (measureName: string, duration: number) => void) { +export function forEachMeasure(cb: (measureName: string, duration: number) => void): void { durations.forEach((duration, measureName) => cb(measureName, duration)); } /** @internal */ -export function forEachMark(cb: (markName: string) => void) { +export function forEachMark(cb: (markName: string) => void): void { marks.forEach((_time, markName) => cb(markName)); } /** @internal */ -export function clearMeasures(name?: string) { +export function clearMeasures(name?: string): void { if (name !== undefined) durations.delete(name); else durations.clear(); performanceImpl?.clearMeasures(name); } /** @internal */ -export function clearMarks(name?: string) { +export function clearMarks(name?: string): void { if (name !== undefined) { counts.delete(name); marks.delete(name); @@ -167,7 +167,7 @@ export function clearMarks(name?: string) { * * @internal */ -export function isEnabled() { +export function isEnabled(): boolean { return enabled; } @@ -199,7 +199,7 @@ export function enable(system: System = sys) { * * @internal */ -export function disable() { +export function disable(): void { if (enabled) { marks.clear(); counts.clear(); diff --git a/src/compiler/performanceCore.ts b/src/compiler/performanceCore.ts index ba03e7a3314b9..38d8badace719 100644 --- a/src/compiler/performanceCore.ts +++ b/src/compiler/performanceCore.ts @@ -90,7 +90,7 @@ const nativePerformanceHooks = tryGetPerformanceHooks(); const nativePerformanceTime = nativePerformanceHooks?.performanceTime; /** @internal */ -export function tryGetNativePerformanceHooks() { +export function tryGetNativePerformanceHooks(): PerformanceHooks | undefined { return nativePerformanceHooks; } @@ -99,4 +99,4 @@ export function tryGetNativePerformanceHooks() { * * @internal */ -export const timestamp = nativePerformanceTime ? () => nativePerformanceTime.now() : Date.now; +export const timestamp: () => number = nativePerformanceTime ? () => nativePerformanceTime.now() : Date.now; diff --git a/src/compiler/program.ts b/src/compiler/program.ts index bd9b42caae953..2824a29ee33b4 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -519,7 +519,15 @@ export function changeCompilerHostLikeToUseCache( host: CompilerHostLikeForCache, toPath: (fileName: string) => Path, getSourceFile?: CompilerHost["getSourceFile"], -) { +): { + originalReadFile: (fileName: string, encoding?: string) => string | undefined; + originalFileExists: (fileName: string) => boolean; + originalDirectoryExists: ((directory: string) => boolean) | undefined; + originalCreateDirectory: ((directory: string) => void) | undefined; + originalWriteFile: WriteFileCallback | undefined; + getSourceFileWithCache: ((fileName: string, languageVersionOrOptions: ScriptTarget | CreateSourceFileOptions, onError?: (message: string) => void, shouldCreateNewSourceFile?: boolean) => SourceFile | undefined) | undefined; + readFileWithCache: (fileName: string) => string | undefined; +} { const originalReadFile = host.readFile; const originalFileExists = host.fileExists; const originalDirectoryExists = host.directoryExists; @@ -702,7 +710,7 @@ function getCategoryFormat(category: DiagnosticCategory): ForegroundColorEscapeS } /** @internal */ -export function formatColorAndReset(text: string, formatStyle: string) { +export function formatColorAndReset(text: string, formatStyle: string): string { return formatStyle + text + resetEscapeSequence; } @@ -761,7 +769,7 @@ 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: typeof formatColorAndReset = formatColorAndReset): string { 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; @@ -852,7 +860,7 @@ export interface SourceFileImportsList { * 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. */ -export function getModeForFileReference(ref: FileReference | string, containingFileMode: ResolutionMode) { +export function getModeForFileReference(ref: FileReference | string, containingFileMode: ResolutionMode): ResolutionMode { return (isString(ref) ? containingFileMode : ref.resolutionMode) || containingFileMode; } @@ -879,7 +887,7 @@ export function getModeForResolutionAtIndex(file: SourceFileImportsList, index: } /** @internal */ -export function isExclusivelyTypeOnlyImportOrExport(decl: ImportDeclaration | ExportDeclaration | JSDocImportTag) { +export function isExclusivelyTypeOnlyImportOrExport(decl: ImportDeclaration | ExportDeclaration | JSDocImportTag): boolean { if (isExportDeclaration(decl)) { return decl.isTypeOnly; } @@ -927,7 +935,7 @@ export function isExclusivelyTypeOnlyImportOrExport(decl: ImportDeclaration | Ex * should be the options of the referenced project, not the referencing project. * @returns The final resolution mode of the import */ -export function getModeForUsageLocation(file: SourceFile, usage: StringLiteralLike, compilerOptions: CompilerOptions) { +export function getModeForUsageLocation(file: SourceFile, usage: StringLiteralLike, compilerOptions: CompilerOptions): ResolutionMode { return getModeForUsageLocationWorker(file, usage, compilerOptions); } @@ -980,7 +988,7 @@ function getEmitSyntaxForUsageLocationWorker(file: Pick void) { +export function getResolutionModeOverride(node: ImportAttributes | undefined, grammarErrorOnNode?: (node: Node, diagnostic: DiagnosticMessage) => void): ModuleKind.CommonJS | ModuleKind.ESNext | undefined { if (!node) return undefined; if (length(node.elements) !== 1) { grammarErrorOnNode?.( @@ -1180,13 +1188,13 @@ 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): string { const containingDirectory = options.configFilePath ? getDirectoryPath(options.configFilePath) : currentDirectory; return combinePaths(containingDirectory, `__lib_node_modules_lookup_${libFileName}__.ts`); } /** @internal */ -export function getLibraryNameFromLibFileName(libFileName: string) { +export function getLibraryNameFromLibFileName(libFileName: string): string { // Support resolving to lib.dom.d.ts -> @typescript/lib-dom, and // lib.dom.iterable.d.ts -> @typescript/lib-dom/iterable // lib.es2015.symbol.wellknown.d.ts -> @typescript/lib-es2015/symbol-wellknown @@ -1391,7 +1399,7 @@ export function getImpliedNodeFormatForFileWorker( packageJsonInfoCache: PackageJsonInfoCache | undefined, host: ModuleResolutionHost, options: CompilerOptions, -) { +): ModuleKind.CommonJS | ModuleKind.ESNext | Partial | undefined { const moduleResolution = getEmitModuleResolutionKind(options); const shouldLookupFromPackageJson = ModuleResolutionKind.Node16 <= moduleResolution && moduleResolution <= ModuleResolutionKind.NodeNext || pathContainsNodeModules(fileName); diff --git a/src/compiler/resolutionCache.ts b/src/compiler/resolutionCache.ts index 65c41be92f883..6c6a3090fac52 100644 --- a/src/compiler/resolutionCache.ts +++ b/src/compiler/resolutionCache.ts @@ -304,7 +304,7 @@ function perceivedOsRootLengthForWatching(pathComponents: Readonly, length?: number) { +export function canWatchDirectoryOrFile(pathComponents: Readonly, length?: number): boolean { if (length === undefined) length = pathComponents.length; // Ignore "/", "c:/" // ignore "/user", "c:/users" or "c:/folderAtRoot" @@ -314,7 +314,7 @@ export function canWatchDirectoryOrFile(pathComponents: Readonly string | undefined) { +export function getRootDirectoryOfResolutionCache(rootDirForResolution: string, getCurrentDirectory: () => string | undefined): string { const normalized = getNormalizedAbsolutePath(rootDirForResolution, getCurrentDirectory()); return !isDiskPathRoot(normalized) ? removeTrailingDirectorySeparator(normalized) : diff --git a/src/compiler/scanner.ts b/src/compiler/scanner.ts index ce01171fcaafe..fb318bce41a91 100644 --- a/src/compiler/scanner.ts +++ b/src/compiler/scanner.ts @@ -384,7 +384,7 @@ function lookupInUnicodeMap(code: number, map: readonly number[]): boolean { } /** @internal */ -export function isUnicodeIdentifierStart(code: number, languageVersion: ScriptTarget | undefined) { +export function isUnicodeIdentifierStart(code: number, languageVersion: ScriptTarget | undefined): boolean { return languageVersion! >= ScriptTarget.ES2015 ? lookupInUnicodeMap(code, unicodeESNextIdentifierStart) : lookupInUnicodeMap(code, unicodeES5IdentifierStart); @@ -515,7 +515,7 @@ export function computeLineAndCharacterOfPosition(lineStarts: readonly number[], * @internal * We assume the first line starts at position 0 and 'position' is non-negative. */ -export function computeLineOfPosition(lineStarts: readonly number[], position: number, lowerBound?: number) { +export function computeLineOfPosition(lineStarts: readonly number[], position: number, lowerBound?: number): number { let lineNumber = binarySearch(lineStarts, position, identity, compareValues, lowerBound); if (lineNumber < 0) { // If the actual position was not found, @@ -532,7 +532,7 @@ export function computeLineOfPosition(lineStarts: readonly number[], position: n } /** @internal */ -export function getLinesBetweenPositions(sourceFile: SourceFileLike, pos1: number, pos2: number) { +export function getLinesBetweenPositions(sourceFile: SourceFileLike, pos1: number, pos2: number): number { if (pos1 === pos2) return 0; const lineStarts = getLineStarts(sourceFile); const lower = Math.min(pos1, pos2); @@ -939,11 +939,11 @@ export function forEachTrailingCommentRange(text: string, pos: number, cb: 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): U | undefined { 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): U | undefined { return iterateCommentRanges(/*reduce*/ true, text, pos, /*trailing*/ true, cb, state, initial); } @@ -1017,7 +1017,7 @@ const enum ClassSetExpressionType { } // 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 = 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 */ @@ -4053,7 +4053,7 @@ function utf16EncodeAsStringFallback(codePoint: number) { const utf16EncodeAsStringWorker: (codePoint: number) => string = (String as any).fromCodePoint ? codePoint => (String as any).fromCodePoint(codePoint) : utf16EncodeAsStringFallback; /** @internal */ -export function utf16EncodeAsString(codePoint: number) { +export function utf16EncodeAsString(codePoint: number): string { return utf16EncodeAsStringWorker(codePoint); } diff --git a/src/compiler/semver.ts b/src/compiler/semver.ts index 2e472e3af5af1..fb456853f2e6e 100644 --- a/src/compiler/semver.ts +++ b/src/compiler/semver.ts @@ -44,7 +44,7 @@ const numericIdentifierRegExp = /^(0|[1-9]\d*)$/; * @internal */ export class Version { - static readonly zero = new Version(0, 0, 0, ["0"]); + static readonly zero: Version = new Version(0, 0, 0, ["0"]); readonly major: number; readonly minor: number; @@ -77,7 +77,7 @@ export class Version { this.build = buildArray; } - static tryParse(text: string) { + static tryParse(text: string): Version | undefined { const result = tryParseComponents(text); if (!result) return undefined; @@ -85,7 +85,7 @@ export class Version { return new Version(major, minor, patch, prerelease, build); } - compareTo(other: Version | undefined) { + compareTo(other: Version | undefined): Comparison { // https://semver.org/#spec-item-11 // > Precedence is determined by the first difference when comparing each of these // > identifiers from left to right as follows: Major, minor, and patch versions are @@ -106,7 +106,7 @@ export class Version { || comparePrereleaseIdentifiers(this.prerelease, other.prerelease); } - increment(field: "major" | "minor" | "patch") { + increment(field: "major" | "minor" | "patch"): Version { switch (field) { case "major": return new Version(this.major + 1, 0, 0); @@ -119,7 +119,7 @@ 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[]; }): Version { const { major = this.major, minor = this.minor, @@ -130,7 +130,7 @@ export class Version { return new Version(major, minor, patch, prerelease, build); } - toString() { + toString(): string { let result = `${this.major}.${this.minor}.${this.patch}`; if (some(this.prerelease)) result += `-${this.prerelease.join(".")}`; if (some(this.build)) result += `+${this.build.join(".")}`; @@ -210,7 +210,7 @@ export class VersionRange { this._alternatives = spec ? Debug.checkDefined(parseRange(spec), "Invalid range spec.") : emptyArray; } - static tryParse(text: string) { + static tryParse(text: string): VersionRange | undefined { const sets = parseRange(text); if (sets) { const range = new VersionRange(""); @@ -224,12 +224,12 @@ export class VersionRange { * Tests whether a version matches the range. This is equivalent to `satisfies(version, range, { includePrerelease: true })`. * in `node-semver`. */ - test(version: Version | string) { + test(version: Version | string): boolean { if (typeof version === "string") version = new Version(version); return testDisjunction(version, this._alternatives); } - toString() { + toString(): string { return formatDisjunction(this._alternatives); } } diff --git a/src/compiler/sourcemap.ts b/src/compiler/sourcemap.ts index fff807e98cf6a..4148450083e15 100644 --- a/src/compiler/sourcemap.ts +++ b/src/compiler/sourcemap.ts @@ -360,12 +360,12 @@ export function createSourceMapGenerator(host: EmitHost, file: string, sourceRoo // Sometimes tools can see the following line as a source mapping url comment, so we mangle it a bit (the [M]) /** @internal */ -export const sourceMapCommentRegExpDontCareLineStart = /\/\/[@#] source[M]appingURL=(.+)\r?\n?$/; +export const sourceMapCommentRegExpDontCareLineStart: RegExp = /\/\/[@#] source[M]appingURL=(.+)\r?\n?$/; /** @internal */ -export const sourceMapCommentRegExp = /^\/\/[@#] source[M]appingURL=(.+)\r?\n?$/; +export const sourceMapCommentRegExp: RegExp = /^\/\/[@#] source[M]appingURL=(.+)\r?\n?$/; /** @internal */ -export const whitespaceOrMapCommentRegExp = /^\s*(\/\/[@#] .*)?$/; +export const whitespaceOrMapCommentRegExp: RegExp = /^\s*(\/\/[@#] .*)?$/; /** @internal */ export interface LineInfo { @@ -386,7 +386,7 @@ export function getLineInfo(text: string, lineStarts: readonly number[]): LineIn * * @internal */ -export function tryGetSourceMappingURL(lineInfo: LineInfo) { +export function tryGetSourceMappingURL(lineInfo: LineInfo): string | undefined { for (let index = lineInfo.getLineCount() - 1; index >= 0; index--) { const line = lineInfo.getLineText(index); const comment = sourceMapCommentRegExp.exec(line); @@ -419,7 +419,7 @@ function isRawSourceMap(x: any): x is RawSourceMap { /* eslint-enable no-restricted-syntax */ /** @internal */ -export function tryParseRawSourceMap(text: string) { +export function tryParseRawSourceMap(text: string): RawSourceMap | undefined { try { const parsed = JSON.parse(text); if (isRawSourceMap(parsed)) { @@ -616,7 +616,7 @@ export function decodeMappings(mappings: string): MappingsDecoder { } /** @internal */ -export function sameMapping(left: T, right: T) { +export function sameMapping(left: T, right: T): boolean { return left === right || left.generatedLine === right.generatedLine && left.generatedCharacter === right.generatedCharacter diff --git a/src/compiler/symbolWalker.ts b/src/compiler/symbolWalker.ts index 6942028d9af79..3f1181236f90a 100644 --- a/src/compiler/symbolWalker.ts +++ b/src/compiler/symbolWalker.ts @@ -38,7 +38,7 @@ export function createGetSymbolWalker( getConstraintOfTypeParameter: (typeParameter: TypeParameter) => Type | undefined, getFirstIdentifier: (node: EntityNameOrEntityNameExpression) => Identifier, getTypeArguments: (type: TypeReference) => readonly Type[], -) { +): (accept?: (symbol: Symbol) => boolean) => SymbolWalker { return getSymbolWalker; function getSymbolWalker(accept: (symbol: Symbol) => boolean = () => true): SymbolWalker { diff --git a/src/compiler/sys.ts b/src/compiler/sys.ts index a279719aeb205..2ead4af477910 100644 --- a/src/compiler/sys.ts +++ b/src/compiler/sys.ts @@ -71,7 +71,7 @@ export function generateDjb2Hash(data: string): string { * * @internal */ -export function setStackTraceLimit() { +export function setStackTraceLimit(): void { if ((Error as any).stackTraceLimit < 100) { // Also tests that we won't set the property if it doesn't exist. (Error as any).stackTraceLimit = 100; } @@ -104,10 +104,10 @@ export type HostWatchFile = (fileName: string, callback: FileWatcherCallback, po 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 +export const missingFileModifiedTime: Date = new Date(0); // Any subsequent modification will occur after this time /** @internal */ -export function getModifiedTime(host: { getModifiedTime: NonNullable; }, fileName: string) { +export function getModifiedTime(host: { getModifiedTime: NonNullable; }, fileName: string): Date { return host.getModifiedTime(fileName) || missingFileModifiedTime; } @@ -128,7 +128,11 @@ function createPollingIntervalBasedLevels(levels: Levels) { const defaultChunkLevels: Levels = { Low: 32, Medium: 64, High: 256 }; let pollingChunkSize = createPollingIntervalBasedLevels(defaultChunkLevels); /** @internal */ -export let unchangedPollThresholds = createPollingIntervalBasedLevels(defaultChunkLevels); +export let unchangedPollThresholds: { + 250: number; + 500: number; + 2000: number; +} = createPollingIntervalBasedLevels(defaultChunkLevels); function setCustomPollingValues(system: System) { if (!system.getEnvironmentVariable) { @@ -550,7 +554,7 @@ function onWatchedFileStat(watchedFile: WatchedFile, modifiedTime: Date): boolea } /** @internal */ -export function getFileWatcherEventKind(oldTime: number, newTime: number) { +export function getFileWatcherEventKind(oldTime: number, newTime: number): FileWatcherEventKind { return oldTime === 0 ? FileWatcherEventKind.Created : newTime === 0 @@ -559,17 +563,17 @@ export function getFileWatcherEventKind(oldTime: number, newTime: number) { } /** @internal */ -export const ignoredPaths = ["/node_modules/.", "/.git", "/.#"]; +export const ignoredPaths: string[] = ["/node_modules/.", "/.git", "/.#"]; let curSysLog: (s: string) => void = noop; /** @internal */ -export function sysLog(s: string) { +export function sysLog(s: string): void { return curSysLog(s); } /** @internal */ -export function setSysLog(logger: typeof sysLog) { +export function setSysLog(logger: typeof sysLog): void { curSysLog = logger; } @@ -1375,7 +1379,7 @@ export function createSystemWatchFunctions({ * * @internal */ -export function patchWriteFileEnsuringDirectory(sys: System) { +export function patchWriteFileEnsuringDirectory(sys: System): void { // patch writefile to create folder before writing the file const originalWriteFile = sys.writeFile; sys.writeFile = (path, data, writeBom) => @@ -1997,7 +2001,7 @@ export let sys: System = (() => { })(); /** @internal @knipignore */ -export function setSys(s: System) { +export function setSys(s: System): void { sys = s; } diff --git a/src/compiler/tracing.ts b/src/compiler/tracing.ts index 94e9bd57c83b6..5d7138d1c22eb 100644 --- a/src/compiler/tracing.ts +++ b/src/compiler/tracing.ts @@ -55,7 +55,7 @@ export namespace tracingEnabled { } /** Starts tracing for the given project. */ - export function startTracing(tracingMode: Mode, traceDir: string, configFilePath?: string) { + export function startTracing(tracingMode: Mode, traceDir: string, configFilePath?: string): void { Debug.assert(!tracing, "Tracing already started"); if (fs === undefined) { @@ -105,7 +105,7 @@ export namespace tracingEnabled { } /** Stops tracing for the in-progress project and dumps the type catalog. */ - export function stopTracing() { + export function stopTracing(): void { Debug.assert(tracing, "Tracing is not in progress"); Debug.assert(!!typeCatalog.length === (mode !== "server")); // Have a type catalog iff not in server mode @@ -139,7 +139,7 @@ export namespace tracingEnabled { Session = "session", } - export function instant(phase: Phase, name: string, args?: Args) { + export function instant(phase: Phase, name: string, args?: Args): void { writeEvent("I", phase, name, args, `"s":"g"`); } @@ -151,18 +151,18 @@ export namespace tracingEnabled { * In the future we might implement an exit handler to dump unfinished events which would deprecate * these operations. */ - export function push(phase: Phase, name: string, args?: Args, separateBeginAndEnd = false) { + export function push(phase: Phase, name: string, args?: Args, separateBeginAndEnd = false): void { if (separateBeginAndEnd) { writeEvent("B", phase, name, args); } eventStack.push({ phase, name, args, time: 1000 * timestamp(), separateBeginAndEnd }); } - export function pop(results?: Args) { + export function pop(results?: Args): void { Debug.assert(eventStack.length > 0); writeStackEvent(eventStack.length - 1, 1000 * timestamp(), results); eventStack.length--; } - export function popAll() { + export function popAll(): void { const endTime = 1000 * timestamp(); for (let i = eventStack.length - 1; i >= 0; i--) { writeStackEvent(i, endTime); @@ -348,7 +348,7 @@ export namespace tracingEnabled { performance.measure("Dump types", "beginDumpTypes", "endDumpTypes"); } - export function dumpLegend() { + export function dumpLegend(): void { if (!legendPath) { return; } @@ -365,9 +365,9 @@ export namespace tracingEnabled { // define after tracingEnabled is initialized /** @internal */ -export const startTracing = tracingEnabled.startTracing; +export const startTracing: typeof tracingEnabled.startTracing = tracingEnabled.startTracing; /** @internal */ -export const dumpTracingLegend = tracingEnabled.dumpLegend; +export const dumpTracingLegend: typeof tracingEnabled.dumpLegend = tracingEnabled.dumpLegend; /** @internal */ export interface TracingNode { diff --git a/src/compiler/transformer.ts b/src/compiler/transformer.ts index bd181e5f3c028..0d499f3a08298 100644 --- a/src/compiler/transformer.ts +++ b/src/compiler/transformer.ts @@ -222,12 +222,12 @@ function wrapDeclarationTransformerFactory(transformer: TransformerFactory void) { +export function noEmitNotification(hint: EmitHint, node: Node, callback: (hint: EmitHint, node: Node) => void): void { callback(hint, node); } diff --git a/src/compiler/transformers/classThis.ts b/src/compiler/transformers/classThis.ts index e357c9b6e4f8b..86eb48346e50e 100644 --- a/src/compiler/transformers/classThis.ts +++ b/src/compiler/transformers/classThis.ts @@ -87,7 +87,7 @@ export function isClassThisAssignmentBlock(node: Node): node is ClassThisAssignm * `_classThis` (or similar) variable. * @internal */ -export function classHasClassThisAssignment(node: ClassLikeDeclaration) { +export function classHasClassThisAssignment(node: ClassLikeDeclaration): boolean { return !!node.emitNode?.classThis && some(node.members, isClassThisAssignmentBlock); } diff --git a/src/compiler/transformers/declarations.ts b/src/compiler/transformers/declarations.ts index 166431a745069..cabc22a07ca86 100644 --- a/src/compiler/transformers/declarations.ts +++ b/src/compiler/transformers/declarations.ts @@ -251,7 +251,11 @@ const declarationEmitNodeBuilderFlags = NodeBuilderFlags.MultilineObjectLiterals * * @internal */ -export function transformDeclarations(context: TransformationContext) { +export function transformDeclarations(context: TransformationContext): { + (node: Bundle): Bundle; + (node: SourceFile): SourceFile; + (node: SourceFile | Bundle): SourceFile | Bundle; +} { const throwDiagnostic = () => Debug.fail("Diagnostic emitted without context"); let getSymbolAccessibilityDiagnostic: GetSymbolAccessibilityDiagnostic = throwDiagnostic; let needsDeclare = true; diff --git a/src/compiler/transformers/declarations/diagnostics.ts b/src/compiler/transformers/declarations/diagnostics.ts index 22bb998ae60bf..c1a8fef8522cb 100644 --- a/src/compiler/transformers/declarations/diagnostics.ts +++ b/src/compiler/transformers/declarations/diagnostics.ts @@ -161,7 +161,7 @@ export function canProduceDiagnostics(node: Node): node is DeclarationDiagnostic } /** @internal */ -export function createGetSymbolAccessibilityDiagnosticForNodeName(node: DeclarationDiagnosticProducing) { +export function createGetSymbolAccessibilityDiagnosticForNodeName(node: DeclarationDiagnosticProducing): (symbolAccessibilityResult: SymbolAccessibilityResult) => SymbolAccessibilityDiagnostic | undefined { if (isSetAccessor(node) || isGetAccessor(node)) { return getAccessorNameVisibilityError; } @@ -603,7 +603,7 @@ export function createGetSymbolAccessibilityDiagnosticForNode(node: DeclarationD } /** @internal */ -export function createGetIsolatedDeclarationErrors(resolver: EmitResolver) { +export function createGetIsolatedDeclarationErrors(resolver: EmitResolver): (node: Node) => DiagnosticWithLocation { const relatedSuggestionByDeclarationKind = { [SyntaxKind.ArrowFunction]: Diagnostics.Add_a_return_type_to_the_function_expression, [SyntaxKind.FunctionExpression]: Diagnostics.Add_a_return_type_to_the_function_expression, diff --git a/src/compiler/transformers/es2017.ts b/src/compiler/transformers/es2017.ts index e1f0c9756b242..f7e3769286c3a 100644 --- a/src/compiler/transformers/es2017.ts +++ b/src/compiler/transformers/es2017.ts @@ -1055,7 +1055,7 @@ 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>): VariableStatement { // 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.hasNodeCheckFlag(node, NodeCheckFlags.MethodWithSuperPropertyAssignmentInAsync); diff --git a/src/compiler/transformers/module/impliedNodeFormatDependent.ts b/src/compiler/transformers/module/impliedNodeFormatDependent.ts index 7a5bf9e210fcd..8a7ce9af79373 100644 --- a/src/compiler/transformers/module/impliedNodeFormatDependent.ts +++ b/src/compiler/transformers/module/impliedNodeFormatDependent.ts @@ -14,7 +14,7 @@ import { } from "../../_namespaces/ts.js"; /** @internal */ -export function transformImpliedNodeFormatDependentModule(context: TransformationContext) { +export function transformImpliedNodeFormatDependentModule(context: TransformationContext): (node: SourceFile | Bundle) => SourceFile | Bundle { const previousOnSubstituteNode = context.onSubstituteNode; const previousOnEmitNode = context.onEmitNode; diff --git a/src/compiler/transformers/ts.ts b/src/compiler/transformers/ts.ts index 668da90d8e696..1414d4f9662b8 100644 --- a/src/compiler/transformers/ts.ts +++ b/src/compiler/transformers/ts.ts @@ -231,7 +231,7 @@ const enum ClassFacts { } /** @internal */ -export function transformTypeScript(context: TransformationContext) { +export function transformTypeScript(context: TransformationContext): (node: SourceFile | Bundle) => SourceFile | Bundle { const { factory, getEmitHelperFactory: emitHelpers, diff --git a/src/compiler/transformers/utilities.ts b/src/compiler/transformers/utilities.ts index fd1501e1d068d..bf59af6097718 100644 --- a/src/compiler/transformers/utilities.ts +++ b/src/compiler/transformers/utilities.ts @@ -96,7 +96,7 @@ import { } from "../_namespaces/ts.js"; /** @internal */ -export function getOriginalNodeId(node: Node) { +export function getOriginalNodeId(node: Node): number { node = getOriginalNode(node); return node ? getNodeId(node) : 0; } @@ -381,19 +381,19 @@ function multiMapSparseArrayAdd(map: V[][], key: number, value: V): V[] { export class IdentifierNameMap { private readonly _map = new Map(); - get size() { + get size(): number { return this._map.size; } - has(key: Identifier) { + has(key: Identifier): boolean { return this._map.has(IdentifierNameMap.toKey(key)); } - get(key: Identifier) { + get(key: Identifier): V | undefined { return this._map.get(IdentifierNameMap.toKey(key)); } - set(key: Identifier, value: V) { + set(key: Identifier, value: V): this { this._map.set(IdentifierNameMap.toKey(key), value); return this; } @@ -406,7 +406,7 @@ export class IdentifierNameMap { this._map.clear(); } - values() { + values(): IterableIterator { return this._map.values(); } @@ -460,7 +460,7 @@ class IdentifierNameMultiMap extends IdentifierNameMap { * * @internal */ -export function isSimpleCopiableExpression(expression: Expression) { +export function isSimpleCopiableExpression(expression: Expression): boolean { return isStringLiteralLike(expression) || expression.kind === SyntaxKind.NumericLiteral || isKeyword(expression.kind) || @@ -474,7 +474,7 @@ export function isSimpleCopiableExpression(expression: Expression) { * * @internal */ -export function isSimpleInlineableExpression(expression: Expression) { +export function isSimpleInlineableExpression(expression: Expression): boolean { return !isIdentifier(expression) && isSimpleCopiableExpression(expression); } @@ -560,7 +560,7 @@ function findSuperStatementIndexPathWorker(statements: NodeArray, sta * * @internal */ -export function findSuperStatementIndexPath(statements: NodeArray, start: number) { +export function findSuperStatementIndexPath(statements: NodeArray, start: number): number[] { const indices: number[] = []; findSuperStatementIndexPathWorker(statements, start, indices); return indices; @@ -821,7 +821,7 @@ export function newPrivateEnvironment(data: TData): PrivateEnviro export function getPrivateIdentifier( privateEnv: PrivateEnvironment | undefined, name: PrivateIdentifier, -) { +): TEntry | undefined { return isGeneratedPrivateIdentifier(name) ? privateEnv?.generatedIdentifiers?.get(getNodeForGeneratedName(name)) : privateEnv?.identifiers?.get(name.escapedText); @@ -832,7 +832,7 @@ export function setPrivateIdentifier( privateEnv: PrivateEnvironment, name: PrivateIdentifier, entry: TEntry, -) { +): void { if (isGeneratedPrivateIdentifier(name)) { privateEnv.generatedIdentifiers ??= new Map(); privateEnv.generatedIdentifiers.set(getNodeForGeneratedName(name), entry); @@ -851,7 +851,7 @@ export function accessPrivateIdentifier< >( env: LexicalEnvironment | undefined, name: PrivateIdentifier, -) { +): TPrivateEntry | undefined { return walkUpLexicalEnvironments(env, env => getPrivateIdentifier(env.privateEnv, name)); } @@ -860,6 +860,6 @@ function isSimpleParameter(node: ParameterDeclaration) { } /** @internal */ -export function isSimpleParameterList(nodes: NodeArray) { +export function isSimpleParameterList(nodes: NodeArray): boolean { return every(nodes, isSimpleParameter); } diff --git a/src/compiler/tsbuildPublic.ts b/src/compiler/tsbuildPublic.ts index 7b9b398cf2d0a..475aec9c4ec12 100644 --- a/src/compiler/tsbuildPublic.ts +++ b/src/compiler/tsbuildPublic.ts @@ -300,13 +300,13 @@ function createSolutionBuilderHostBase(system: System, return host; } -export function createSolutionBuilderHost(system = sys, createProgram?: CreateProgram, reportDiagnostic?: DiagnosticReporter, reportSolutionBuilderStatus?: DiagnosticReporter, reportErrorSummary?: ReportEmitErrorSummary) { +export function createSolutionBuilderHost(system: System = sys, createProgram?: CreateProgram, reportDiagnostic?: DiagnosticReporter, reportSolutionBuilderStatus?: DiagnosticReporter, reportErrorSummary?: ReportEmitErrorSummary): SolutionBuilderHost { 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) { +export function createSolutionBuilderWithWatchHost(system: System = sys, createProgram?: CreateProgram, reportDiagnostic?: DiagnosticReporter, reportSolutionBuilderStatus?: DiagnosticReporter, reportWatchStatus?: WatchStatusReporter): SolutionBuilderWithWatchHost { const host = createSolutionBuilderHostBase(system, createProgram, reportDiagnostic, reportSolutionBuilderStatus) as SolutionBuilderWithWatchHost; const watchHost = createWatchHost(system, reportWatchStatus); copyProperties(host, watchHost); diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 564fa64e1294c..be578eeacf8d9 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -10055,7 +10055,78 @@ export interface PragmaDefinition !isJsonEqual(getCompilerOptionValue(oldOptions, o), getCompilerOptionValue(newOptions, o))); } @@ -772,12 +772,12 @@ export function usingSingleLineStringWriter(action: (writer: EmitTextWriter) => } /** @internal */ -export function getFullWidth(node: Node) { +export function getFullWidth(node: Node): number { return node.end - node.pos; } /** @internal */ -export function projectReferenceIsEqualTo(oldRef: ProjectReference, newRef: ProjectReference) { +export function projectReferenceIsEqualTo(oldRef: ProjectReference, newRef: ProjectReference): boolean { return oldRef.path === newRef.path && !oldRef.prepend === !newRef.prepend && !oldRef.circular === !newRef.circular; @@ -798,17 +798,17 @@ export function moduleResolutionIsEqualTo(oldResolution: ResolvedModuleWithFaile } /** @internal */ -export function getResolvedModuleFromResolution(resolution: ResolvedModuleWithFailedLookupLocations) { +export function getResolvedModuleFromResolution(resolution: ResolvedModuleWithFailedLookupLocations): ResolvedModuleFull | undefined { return resolution.resolvedModule; } /** @internal */ -export function getResolvedTypeReferenceDirectiveFromResolution(resolution: ResolvedTypeReferenceDirectiveWithFailedLookupLocations) { +export function getResolvedTypeReferenceDirectiveFromResolution(resolution: ResolvedTypeReferenceDirectiveWithFailedLookupLocations): ResolvedTypeReferenceDirective | undefined { return resolution.resolvedTypeReferenceDirective; } /** @internal */ -export function createModuleNotFoundChain(sourceFile: SourceFile, host: TypeCheckerHost, moduleReference: string, mode: ResolutionMode, packageName: string) { +export function createModuleNotFoundChain(sourceFile: SourceFile, host: TypeCheckerHost, moduleReference: string, mode: ResolutionMode, packageName: string): DiagnosticMessageChain { const alternateResult = host.getResolvedModule(sourceFile, moduleReference, mode)?.alternateResult; const alternateResultMessage = alternateResult && (getEmitModuleResolutionKind(host.getCompilerOptions()) === ModuleResolutionKind.Node10 ? [Diagnostics.There_are_types_at_0_but_this_result_could_not_be_resolved_under_your_current_moduleResolution_setting_Consider_updating_to_node16_nodenext_or_bundler, [alternateResult]] as const @@ -847,7 +847,7 @@ export function createModuleNotFoundChain(sourceFile: SourceFile, host: TypeChec } /** @internal */ -export function createModeMismatchDetails(currentSourceFile: SourceFile) { +export function createModeMismatchDetails(currentSourceFile: SourceFile): DiagnosticMessageChain { const ext = tryGetExtensionFromPath(currentSourceFile.fileName); const scope = currentSourceFile.packageJsonScope; const targetExt = ext === Extension.Ts ? Extension.Mts : ext === Extension.Js ? Extension.Mjs : undefined; @@ -966,7 +966,7 @@ export function getSourceFileOfNode(node: Node | undefined): SourceFile | undefi } /** @internal */ -export function getSourceFileOfModule(module: Symbol) { +export function getSourceFileOfModule(module: Symbol): SourceFile | undefined { return getSourceFileOfNode(module.valueDeclaration || getNonAugmentationDeclaration(module)); } @@ -976,7 +976,7 @@ export function isPlainJsFile(file: SourceFile | undefined, checkJs: boolean | u } /** @internal */ -export function isStatementWithLocals(node: Node) { +export function isStatementWithLocals(node: Node): boolean { switch (node.kind) { case SyntaxKind.Block: case SyntaxKind.CaseBlock: @@ -1070,7 +1070,7 @@ export function nodeIsPresent(node: Node | undefined): boolean { * Tests whether `child` is a grammar error on `parent`. * @internal */ -export function isGrammarError(parent: Node, child: Node | NodeArray) { +export function isGrammarError(parent: Node, child: Node | NodeArray): boolean { if (isTypeParameterDeclaration(parent)) return child === parent.expression; if (isClassStaticBlockDeclaration(parent)) return child === parent.modifiers; if (isPropertySignature(parent)) return child === parent.initializer; @@ -1156,7 +1156,7 @@ export function insertStatementAfterCustomPrologue(to: T[], * * @internal */ -export function isRecognizedTripleSlashComment(text: string, commentPos: number, commentEnd: number) { +export function isRecognizedTripleSlashComment(text: string, commentPos: number, commentEnd: number): boolean { // 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 ( @@ -1177,7 +1177,7 @@ export function isRecognizedTripleSlashComment(text: string, commentPos: number, } /** @internal */ -export function isPinnedComment(text: string, start: number) { +export function isPinnedComment(text: string, start: number): boolean { return text.charCodeAt(start + 1) === CharacterCodes.asterisk && text.charCodeAt(start + 2) === CharacterCodes.exclamation; } @@ -1335,7 +1335,7 @@ function getPos(range: Node) { * * @internal */ -export function indexOfNode(nodeArray: readonly Node[], node: Node) { +export function indexOfNode(nodeArray: readonly Node[], node: Node): number { return binarySearch(nodeArray, node, getPos, compareValues); } @@ -1364,7 +1364,7 @@ export function getInternalEmitFlags(node: Node): InternalEmitFlags { export type ScriptTargetFeatures = ReadonlyMap>; /** @internal */ -export const getScriptTargetFeatures = /* @__PURE__ */ memoize((): ScriptTargetFeatures => +export const getScriptTargetFeatures: () => ScriptTargetFeatures = /* @__PURE__ */ memoize((): ScriptTargetFeatures => new Map(Object.entries({ Array: new Map(Object.entries({ es2015: [ @@ -1826,7 +1826,7 @@ export const enum GetLiteralTextFlags { } /** @internal */ -export function getLiteralText(node: LiteralLikeNode, sourceFile: SourceFile | undefined, flags: GetLiteralTextFlags) { +export function getLiteralText(node: LiteralLikeNode, sourceFile: SourceFile | undefined, flags: GetLiteralTextFlags): string { // If we don't need to downlevel and we can reach the original source text using // the node's parent reference, then simply get the text as it was originally written. if (sourceFile && canUseOriginalText(node, flags)) { @@ -1900,7 +1900,7 @@ function canUseOriginalText(node: LiteralLikeNode, flags: GetLiteralTextFlags): } /** @internal */ -export function getTextOfConstantValue(value: string | number) { +export function getTextOfConstantValue(value: string | number): string { return isString(value) ? `"${escapeString(value)}"` : "" + value; } @@ -1912,13 +1912,13 @@ export function makeIdentifierFromModuleName(moduleName: string): string { } /** @internal */ -export function isBlockOrCatchScoped(declaration: Declaration) { +export function isBlockOrCatchScoped(declaration: Declaration): boolean { return (getCombinedNodeFlags(declaration) & NodeFlags.BlockScoped) !== 0 || isCatchClauseVariableDeclarationOrBindingElement(declaration); } /** @internal */ -export function isCatchClauseVariableDeclarationOrBindingElement(declaration: Declaration) { +export function isCatchClauseVariableDeclarationOrBindingElement(declaration: Declaration): boolean { const node = getRootDeclaration(declaration); return node.kind === SyntaxKind.VariableDeclaration && node.parent.kind === SyntaxKind.CatchClause; } @@ -1980,7 +1980,7 @@ export function isExternalModuleAugmentation(node: Node): node is AmbientModuleD } /** @internal */ -export function isModuleAugmentationExternal(node: AmbientModuleDeclaration) { +export function isModuleAugmentationExternal(node: AmbientModuleDeclaration): boolean { // external module augmentation is a ambient module declaration that is either: // - defined in the top level scope and source file is an external module // - defined inside ambient module declaration located in the top level scope and source file not an external module @@ -1994,7 +1994,7 @@ export function isModuleAugmentationExternal(node: AmbientModuleDeclaration) { } /** @internal */ -export function getNonAugmentationDeclaration(symbol: Symbol) { +export function getNonAugmentationDeclaration(symbol: Symbol): Declaration | undefined { return symbol.declarations?.find(d => !isExternalModuleAugmentation(d) && !(isModuleDeclaration(d) && isGlobalScopeAugmentation(d))); } @@ -2003,7 +2003,7 @@ function isCommonJSContainingModuleKind(kind: ModuleKind) { } /** @internal */ -export function isEffectiveExternalModule(node: SourceFile, compilerOptions: CompilerOptions) { +export function isEffectiveExternalModule(node: SourceFile, compilerOptions: CompilerOptions): boolean { return isExternalModule(node) || (isCommonJSContainingModuleKind(getEmitModuleKind(compilerOptions)) && !!node.commonJsModuleIndicator); } @@ -2012,7 +2012,7 @@ export function isEffectiveExternalModule(node: SourceFile, compilerOptions: Com * * @internal */ -export function isEffectiveStrictModeSourceFile(node: SourceFile, compilerOptions: CompilerOptions) { +export function isEffectiveStrictModeSourceFile(node: SourceFile, compilerOptions: CompilerOptions): boolean { // We can only verify strict mode for JS/TS files switch (node.scriptKind) { case ScriptKind.JS: @@ -2043,7 +2043,7 @@ export function isEffectiveStrictModeSourceFile(node: SourceFile, compilerOption } /** @internal */ -export function isAmbientPropertyDeclaration(node: PropertyDeclaration) { +export function isAmbientPropertyDeclaration(node: PropertyDeclaration): boolean { return !!(node.flags & NodeFlags.Ambient) || hasSyntacticModifier(node, ModifierFlags.Ambient); } @@ -2195,7 +2195,7 @@ export function forEachEnclosingBlockScopeContainer(node: Node, cb: (container: // Computed property names will just be emitted as "[]", where is the source // text of the expression in the computed property. /** @internal */ -export function declarationNameToString(name: DeclarationName | QualifiedName | undefined) { +export function declarationNameToString(name: DeclarationName | QualifiedName | undefined): string { return !name || getFullWidth(name) === 0 ? "(Missing)" : getTextOfNode(name); } @@ -2365,7 +2365,7 @@ export function getSpanOfTokenAtPosition(sourceFile: SourceFile, pos: number): T } /** @internal */ -export function scanTokenAtPosition(sourceFile: SourceFile, pos: number) { +export function scanTokenAtPosition(sourceFile: SourceFile, pos: number): SyntaxKind { const scanner = createScanner(sourceFile.languageVersion, /*skipTrivia*/ true, sourceFile.languageVariant, sourceFile.text, /*onError*/ undefined, pos); scanner.scan(); return scanner.getToken(); @@ -2479,7 +2479,7 @@ export function getErrorSpanForNode(sourceFile: SourceFile, node: Node): TextSpa } /** @internal */ -export function isGlobalSourceFile(node: Node) { +export function isGlobalSourceFile(node: Node): boolean { return node.kind === SyntaxKind.SourceFile && !isExternalOrCommonJsModule(node as SourceFile); } @@ -2531,7 +2531,7 @@ export function isVarConst(node: VariableDeclaration | VariableDeclarationList): * Gets whether a bound `VariableDeclaration` or `VariableDeclarationList` is part of a `const`, `using` or `await using` declaration. * @internal */ -export function isVarConstLike(node: VariableDeclaration | VariableDeclarationList) { +export function isVarConstLike(node: VariableDeclaration | VariableDeclarationList): boolean { const blockScopeKind = getCombinedNodeFlags(node) & NodeFlags.BlockScoped; return blockScopeKind === NodeFlags.Const || blockScopeKind === NodeFlags.Using || @@ -2575,12 +2575,12 @@ export function isPrologueDirective(node: Node): node is PrologueDirective { } /** @internal */ -export function isCustomPrologue(node: Statement) { +export function isCustomPrologue(node: Statement): boolean { return !!(getEmitFlags(node) & EmitFlags.CustomPrologue); } /** @internal */ -export function isHoistedFunction(node: Statement) { +export function isHoistedFunction(node: Statement): boolean { return isCustomPrologue(node) && isFunctionDeclaration(node); } @@ -2591,19 +2591,19 @@ function isHoistedVariable(node: VariableDeclaration) { } /** @internal */ -export function isHoistedVariableStatement(node: Statement) { +export function isHoistedVariableStatement(node: Statement): boolean { return isCustomPrologue(node) && isVariableStatement(node) && every(node.declarationList.declarations, isHoistedVariable); } /** @internal */ -export function getLeadingCommentRangesOfNode(node: Node, sourceFileOfNode: SourceFile) { +export function getLeadingCommentRangesOfNode(node: Node, sourceFileOfNode: SourceFile): CommentRange[] | undefined { return node.kind !== SyntaxKind.JsxText ? getLeadingCommentRanges(sourceFileOfNode.text, node.pos) : undefined; } /** @internal */ -export function getJSDocCommentRanges(node: Node, text: string) { +export function getJSDocCommentRanges(node: Node, text: string): CommentRange[] | undefined { const commentRanges = (node.kind === SyntaxKind.Parameter || node.kind === SyntaxKind.TypeParameter || node.kind === SyntaxKind.FunctionExpression || @@ -2806,7 +2806,7 @@ export function forEachYieldExpression(body: Block, visitor: (expr: YieldExpress * * @internal */ -export function getRestParameterElementType(node: TypeNode | undefined) { +export function getRestParameterElementType(node: TypeNode | undefined): TypeNode | undefined { if (node && node.kind === SyntaxKind.ArrayType) { return (node as ArrayTypeNode).elementType; } @@ -2855,20 +2855,20 @@ export function isVariableLikeOrAccessor(node: Node): node is AccessorDeclaratio } /** @internal */ -export function isVariableDeclarationInVariableStatement(node: VariableDeclaration) { +export function isVariableDeclarationInVariableStatement(node: VariableDeclaration): boolean { return node.parent.kind === SyntaxKind.VariableDeclarationList && node.parent.parent.kind === SyntaxKind.VariableStatement; } /** @internal */ -export function isCommonJsExportedExpression(node: Node) { +export function isCommonJsExportedExpression(node: Node): boolean { if (!isInJSFile(node)) return false; return (isObjectLiteralExpression(node.parent) && isBinaryExpression(node.parent.parent) && getAssignmentDeclarationKind(node.parent.parent) === AssignmentDeclarationKind.ModuleExports) || isCommonJsExportPropertyAssignment(node.parent); } /** @internal */ -export function isCommonJsExportPropertyAssignment(node: Node) { +export function isCommonJsExportPropertyAssignment(node: Node): boolean { if (!isInJSFile(node)) return false; return (isBinaryExpression(node) && getAssignmentDeclarationKind(node) === AssignmentDeclarationKind.ExportsProperty); } @@ -2881,7 +2881,7 @@ export function isValidESSymbolDeclaration(node: Node): boolean { } /** @internal */ -export function introducesArgumentsExoticObject(node: Node) { +export function introducesArgumentsExoticObject(node: Node): boolean { switch (node.kind) { case SyntaxKind.MethodDeclaration: case SyntaxKind.MethodSignature: @@ -2936,7 +2936,7 @@ 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): T | undefined { return forEach(objectLiteral?.properties, property => { if (!isPropertyAssignment(property)) return undefined; const propName = tryGetTextOfPropertyName(property.name); @@ -2971,7 +2971,7 @@ export function getTsConfigPropArrayElementValue(tsConfigSourceFile: TsConfigSou } /** @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): T | undefined { return forEachPropertyAssignment(getTsConfigObjectLiteralExpression(tsConfigSourceFile), propKey, callback); } @@ -3132,7 +3132,7 @@ export function isThisContainerOrFunctionBlock(node: Node): boolean { } /** @internal */ -export function isInTopLevelContext(node: Node) { +export function isInTopLevelContext(node: Node): boolean { // 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) { node = node.parent; @@ -3142,7 +3142,7 @@ export function isInTopLevelContext(node: Node) { } /** @internal */ -export function getNewTargetContainer(node: Node) { +export function getNewTargetContainer(node: Node): FunctionDeclaration | ConstructorDeclaration | FunctionExpression | undefined { const container = getThisContainer(node, /*includeArrowFunctions*/ false, /*includeClassComputedPropertyName*/ false); if (container) { switch (container.kind) { @@ -3465,7 +3465,7 @@ export function isEmptyStringLiteral(node: StringLiteral): boolean { } /** @internal */ -export function isJSXTagName(node: Node) { +export function isJSXTagName(node: Node): boolean { const { parent } = node; if ( parent.kind === SyntaxKind.JsxOpeningElement || @@ -3605,7 +3605,7 @@ export function isInExpressionContext(node: Node): boolean { } /** @internal */ -export function isPartOfTypeQuery(node: Node) { +export function isPartOfTypeQuery(node: Node): boolean { while (node.kind === SyntaxKind.QualifiedName || node.kind === SyntaxKind.Identifier) { node = node.parent; } @@ -3623,13 +3623,13 @@ export function isExternalModuleImportEqualsDeclaration(node: Node): node is Imp } /** @internal */ -export function getExternalModuleImportEqualsDeclarationExpression(node: Node) { +export function getExternalModuleImportEqualsDeclarationExpression(node: Node): Expression { Debug.assert(isExternalModuleImportEqualsDeclaration(node)); return ((node as ImportEqualsDeclaration).moduleReference as ExternalModuleReference).expression; } /** @internal */ -export function getExternalModuleRequireArgument(node: Node) { +export function getExternalModuleRequireArgument(node: Node): false | StringLiteral { return isVariableDeclarationInitializedToBareOrAccessedRequire(node) && (getLeftmostAccessExpression(node.initializer) as CallExpression).arguments[0] as StringLiteral; } @@ -3659,7 +3659,7 @@ export function isInJsonFile(node: Node | undefined): boolean { } /** @internal */ -export function isSourceFileNotJson(file: SourceFile) { +export function isSourceFileNotJson(file: SourceFile): boolean { return !isJsonSourceFile(file); } @@ -3669,7 +3669,7 @@ export function isInJSDoc(node: Node | undefined): boolean { } /** @internal */ -export function isJSDocIndexSignature(node: TypeReferenceNode | ExpressionWithTypeArguments) { +export function isJSDocIndexSignature(node: TypeReferenceNode | ExpressionWithTypeArguments): boolean | undefined { return isTypeReferenceNode(node) && isIdentifier(node.typeName) && node.typeName.escapedText === "Object" && @@ -3743,7 +3743,7 @@ export function isRequireVariableStatement(node: Node): node is RequireVariableS } /** @internal */ -export function isSingleOrDoubleQuote(charCode: number) { +export function isSingleOrDoubleQuote(charCode: number): boolean { return charCode === CharacterCodes.singleQuote || charCode === CharacterCodes.doubleQuote; } @@ -3753,7 +3753,7 @@ export function isStringDoubleQuoted(str: StringLiteralLike, sourceFile: SourceF } /** @internal */ -export function isAssignmentDeclaration(decl: Declaration) { +export function isAssignmentDeclaration(decl: Declaration): boolean { return isBinaryExpression(decl) || isAccessExpression(decl) || isIdentifier(decl) || isCallExpression(decl); } @@ -3762,7 +3762,7 @@ export function isAssignmentDeclaration(decl: Declaration) { * * @internal */ -export function getEffectiveInitializer(node: HasExpressionInitializer) { +export function getEffectiveInitializer(node: HasExpressionInitializer): Expression | undefined { if ( isInJSFile(node) && node.initializer && isBinaryExpression(node.initializer) && @@ -3779,7 +3779,7 @@ export function getEffectiveInitializer(node: HasExpressionInitializer) { * * @internal */ -export function getDeclaredExpandoInitializer(node: HasExpressionInitializer) { +export function getDeclaredExpandoInitializer(node: HasExpressionInitializer): Expression | undefined { const init = getEffectiveInitializer(node); return init && getExpandoInitializer(init, isPrototypeAccess(node.name)); } @@ -3860,7 +3860,7 @@ function getDefaultedExpandoInitializer(name: Expression, initializer: Expressio } /** @internal */ -export function isDefaultedExpandoInitializer(node: BinaryExpression) { +export function isDefaultedExpandoInitializer(node: BinaryExpression): boolean | undefined { const name = isVariableDeclaration(node.parent) ? node.parent.name : isBinaryExpression(node.parent) && node.parent.operatorToken.kind === SyntaxKind.EqualsToken ? node.parent.left : undefined; @@ -3925,12 +3925,12 @@ export function getRightMostAssignedExpression(node: Expression): Expression { } /** @internal */ -export function isExportsIdentifier(node: Node) { +export function isExportsIdentifier(node: Node): boolean { return isIdentifier(node) && node.escapedText === "exports"; } /** @internal */ -export function isModuleIdentifier(node: Node) { +export function isModuleIdentifier(node: Node): boolean { return isIdentifier(node) && node.escapedText === "module"; } @@ -4002,7 +4002,7 @@ export function isBindableStaticNameExpression(node: Node, excludeThisKeyword?: } /** @internal */ -export function getNameOrArgument(expr: PropertyAccessExpression | LiteralLikeElementAccessExpression) { +export function getNameOrArgument(expr: PropertyAccessExpression | LiteralLikeElementAccessExpression): MemberName | (Expression & (NumericLiteral | StringLiteralLike)) { if (isPropertyAccessExpression(expr)) { return expr.name; } @@ -4111,7 +4111,7 @@ export function getAssignmentDeclarationPropertyAccessKind(lhs: AccessExpression } /** @internal */ -export function getInitializerOfBinaryExpression(expr: BinaryExpression) { +export function getInitializerOfBinaryExpression(expr: BinaryExpression): Expression { while (isBinaryExpression(expr.right)) { expr = expr.right; } @@ -4152,7 +4152,7 @@ export function setValueDeclaration(symbol: Symbol, node: Declaration): void { } /** @internal */ -export function isFunctionSymbol(symbol: Symbol | undefined) { +export function isFunctionSymbol(symbol: Symbol | undefined): boolean | undefined { if (!symbol || !symbol.valueDeclaration) { return false; } @@ -4284,25 +4284,22 @@ export function forEachImportClauseDeclaration(node: ImportClause, action: (d } /** @internal */ -export function hasQuestionToken(node: Node) { - if (node) { - switch (node.kind) { - case SyntaxKind.Parameter: - case SyntaxKind.MethodDeclaration: - case SyntaxKind.MethodSignature: - case SyntaxKind.ShorthandPropertyAssignment: - case SyntaxKind.PropertyAssignment: - case SyntaxKind.PropertyDeclaration: - case SyntaxKind.PropertySignature: - return (node as ParameterDeclaration | MethodDeclaration | PropertyDeclaration).questionToken !== undefined; - } +export function hasQuestionToken(node: Node): boolean { + switch (node.kind) { + case SyntaxKind.Parameter: + case SyntaxKind.MethodDeclaration: + case SyntaxKind.MethodSignature: + case SyntaxKind.ShorthandPropertyAssignment: + case SyntaxKind.PropertyAssignment: + case SyntaxKind.PropertyDeclaration: + case SyntaxKind.PropertySignature: + return (node as ParameterDeclaration | MethodDeclaration | PropertyDeclaration).questionToken !== undefined; } - return false; } /** @internal */ -export function isJSDocConstructSignature(node: Node) { +export function isJSDocConstructSignature(node: Node): boolean { const param = isJSDocFunctionType(node) ? firstOrUndefined(node.parameters) : undefined; const name = tryCast(param && param.name, isIdentifier); return !!name && name.escapedText === "new"; @@ -4537,7 +4534,7 @@ function ownsJSDocTag(hostNode: Node, tag: JSDocTag) { } /** @internal */ -export function getNextJSDocCommentLocation(node: Node) { +export function getNextJSDocCommentLocation(node: Node): Node | undefined { const parent = node.parent; if ( parent.kind === SyntaxKind.PropertyAssignment || @@ -4594,7 +4591,7 @@ export function getParameterSymbolFromJSDoc(node: JSDocParameterTag): Symbol | u } /** @internal */ -export function getEffectiveContainerForJSDocTemplateTag(node: JSDocTemplateTag) { +export function getEffectiveContainerForJSDocTemplateTag(node: JSDocTemplateTag): SignatureDeclaration | JSDocTypedefTag | JSDocCallbackTag | JSDocEnumTag | undefined { if (isJSDoc(node.parent) && node.parent.tags) { // A @template tag belongs to any @typedef, @callback, or @enum tags in the same comment block, if they exist. const typeAlias = find(node.parent.tags, isJSDocTypeAlias); @@ -4836,12 +4833,12 @@ function walkUp(node: Node, kind: SyntaxKind) { } /** @internal */ -export function walkUpParenthesizedTypes(node: Node) { +export function walkUpParenthesizedTypes(node: Node): Node { return walkUp(node, SyntaxKind.ParenthesizedType); } /** @internal */ -export function walkUpParenthesizedExpressions(node: Node) { +export function walkUpParenthesizedExpressions(node: Node): Node { return walkUp(node, SyntaxKind.ParenthesizedExpression); } @@ -4939,7 +4936,7 @@ export function getDeclarationFromName(name: Node): Declaration | undefined { } /** @internal */ -export function isLiteralComputedPropertyDeclarationName(node: Node) { +export function isLiteralComputedPropertyDeclarationName(node: Node): boolean { return isStringOrNumericLiteralLike(node) && node.parent.kind === SyntaxKind.ComputedPropertyName && isDeclaration(node.parent.parent); @@ -5000,7 +4997,7 @@ export function getAliasDeclarationFromName(node: EntityName): Declaration | und } /** @internal */ -export function isAliasableExpression(e: Expression) { +export function isAliasableExpression(e: Expression): boolean { return isEntityNameExpression(e) || isClassExpression(e); } @@ -5022,7 +5019,7 @@ export function getPropertyAssignmentAliasLikeExpression(node: PropertyAssignmen } /** @internal */ -export function getEffectiveBaseTypeNode(node: ClassLikeDeclaration | InterfaceDeclaration) { +export function getEffectiveBaseTypeNode(node: ClassLikeDeclaration | InterfaceDeclaration): ExpressionWithTypeArguments | undefined { const baseType = getClassExtendsHeritageElement(node); if (baseType && isInJSFile(node)) { // Prefer an @augments tag because it may have type parameters. @@ -5035,7 +5032,7 @@ export function getEffectiveBaseTypeNode(node: ClassLikeDeclaration | InterfaceD } /** @internal */ -export function getClassExtendsHeritageElement(node: ClassLikeDeclaration | InterfaceDeclaration) { +export function getClassExtendsHeritageElement(node: ClassLikeDeclaration | InterfaceDeclaration): ExpressionWithTypeArguments | undefined { const heritageClause = getHeritageClause(node.heritageClauses, SyntaxKind.ExtendsKeyword); return heritageClause && heritageClause.types.length > 0 ? heritageClause.types[0] : undefined; } @@ -5063,13 +5060,13 @@ export function getAllSuperTypeNodes(node: Node): readonly TypeNode[] { } /** @internal */ -export function getInterfaceBaseTypeNodes(node: InterfaceDeclaration) { +export function getInterfaceBaseTypeNodes(node: InterfaceDeclaration): NodeArray | undefined { const heritageClause = getHeritageClause(node.heritageClauses, SyntaxKind.ExtendsKeyword); return heritageClause ? heritageClause.types : undefined; } /** @internal */ -export function getHeritageClause(clauses: NodeArray | undefined, kind: SyntaxKind) { +export function getHeritageClause(clauses: NodeArray | undefined, kind: SyntaxKind): HeritageClause | undefined { if (clauses) { for (const clause of clauses) { if (clause.token === kind) { @@ -5118,7 +5115,7 @@ export function isNonContextualKeyword(token: SyntaxKind): boolean { } /** @internal */ -export function isStringANonContextualKeyword(name: string) { +export function isStringANonContextualKeyword(name: string): boolean { const token = stringToToken(name); return token !== undefined && isNonContextualKeyword(token); } @@ -5145,7 +5142,7 @@ export const enum FunctionFlags { } /** @internal */ -export function getFunctionFlags(node: SignatureDeclaration | undefined) { +export function getFunctionFlags(node: SignatureDeclaration | undefined): FunctionFlags { if (!node) { return FunctionFlags.Invalid; } @@ -5411,7 +5408,7 @@ export function isNamedEvaluation(node: Node, cb?: (node: AnonymousFunctionDefin } /** @internal */ -export function isPushOrUnshiftIdentifier(node: Identifier) { +export function isPushOrUnshiftIdentifier(node: Identifier): boolean { return node.escapedText === "push" || node.escapedText === "unshift"; } @@ -5464,14 +5461,14 @@ export const enum Associativity { } /** @internal */ -export function getExpressionAssociativity(expression: Expression) { +export function getExpressionAssociativity(expression: Expression): Associativity { const operator = getOperator(expression); const hasArguments = expression.kind === SyntaxKind.NewExpression && (expression as NewExpression).arguments !== undefined; return getOperatorAssociativity(expression.kind, operator, hasArguments); } /** @internal */ -export function getOperatorAssociativity(kind: SyntaxKind, operator: SyntaxKind, hasArguments?: boolean) { +export function getOperatorAssociativity(kind: SyntaxKind, operator: SyntaxKind, hasArguments?: boolean): Associativity { switch (kind) { case SyntaxKind.NewExpression: return hasArguments ? Associativity.Left : Associativity.Right; @@ -5511,7 +5508,7 @@ export function getOperatorAssociativity(kind: SyntaxKind, operator: SyntaxKind, } /** @internal */ -export function getExpressionPrecedence(expression: Expression) { +export function getExpressionPrecedence(expression: Expression): OperatorPrecedence { const operator = getOperator(expression); const hasArguments = expression.kind === SyntaxKind.NewExpression && (expression as NewExpression).arguments !== undefined; return getOperatorPrecedence(expression.kind, operator, hasArguments); @@ -5723,7 +5720,7 @@ export const enum OperatorPrecedence { } /** @internal */ -export function getOperatorPrecedence(nodeKind: SyntaxKind, operatorKind: SyntaxKind, hasArguments?: boolean) { +export function getOperatorPrecedence(nodeKind: SyntaxKind, operatorKind: SyntaxKind, hasArguments?: boolean): OperatorPrecedence { switch (nodeKind) { case SyntaxKind.CommaListExpression: return OperatorPrecedence.Comma; @@ -5873,7 +5870,7 @@ export function getBinaryOperatorPrecedence(kind: SyntaxKind): OperatorPrecedenc } /** @internal */ -export function getSemanticJsxChildren(children: readonly JsxChild[]) { +export function getSemanticJsxChildren(children: readonly JsxChild[]): readonly JsxChild[] { return filter(children, i => { switch (i.kind) { case SyntaxKind.JsxExpression: @@ -6076,7 +6073,7 @@ function getJsxAttributeStringReplacement(c: string) { } /** @internal */ -export function escapeJsxAttributeString(s: string, quoteChar?: CharacterCodes.doubleQuote | CharacterCodes.singleQuote) { +export function escapeJsxAttributeString(s: string, quoteChar?: CharacterCodes.doubleQuote | CharacterCodes.singleQuote): string { const escapedCharsRegExp = quoteChar === CharacterCodes.singleQuote ? jsxSingleQuoteEscapedCharsRegExp : jsxDoubleQuoteEscapedCharsRegExp; return s.replace(escapedCharsRegExp, getJsxAttributeStringReplacement); @@ -6089,7 +6086,7 @@ export function escapeJsxAttributeString(s: string, quoteChar?: CharacterCodes.d * * @internal */ -export function stripQuotes(name: string) { +export function stripQuotes(name: string): string { const length = name.length; if (length >= 2 && name.charCodeAt(0) === name.charCodeAt(length - 1) && isQuoteOrBacktick(name.charCodeAt(0))) { return name.substring(1, length - 1); @@ -6104,14 +6101,14 @@ function isQuoteOrBacktick(charCode: number) { } /** @internal */ -export function isIntrinsicJsxName(name: __String | string) { +export function isIntrinsicJsxName(name: __String | string): boolean { const ch = (name as string).charCodeAt(0); return (ch >= CharacterCodes.a && ch <= CharacterCodes.z) || (name as string).includes("-"); } const indentStrings: string[] = ["", " "]; /** @internal */ -export function getIndentString(level: number) { +export function getIndentString(level: number): string { // prepopulate cache const singleLevel = indentStrings[1]; for (let current = indentStrings.length; current <= level; current++) { @@ -6367,7 +6364,7 @@ export function getExternalModuleNameFromPath(host: ResolveModuleNameResolutionH } /** @internal */ -export function getOwnEmitOutputFilePath(fileName: string, host: EmitHost, extension: string) { +export function getOwnEmitOutputFilePath(fileName: string, host: EmitHost, extension: string): string { const compilerOptions = host.getCompilerOptions(); let emitOutputFilePathWithoutExtension: string; if (compilerOptions.outDir) { @@ -6381,7 +6378,7 @@ export function getOwnEmitOutputFilePath(fileName: string, host: EmitHost, exten } /** @internal */ -export function getDeclarationEmitOutputFilePath(fileName: string, host: EmitHost) { +export function getDeclarationEmitOutputFilePath(fileName: string, host: EmitHost): string { return getDeclarationEmitOutputFilePathWorker(fileName, host.getCompilerOptions(), host); } @@ -6397,7 +6394,7 @@ export function getDeclarationEmitOutputFilePathWorker(fileName: string, options } /** @internal */ -export function getDeclarationEmitExtensionForPath(path: string) { +export function getDeclarationEmitExtensionForPath(path: string): Extension.Dts | Extension.Dmts | Extension.Dcts | ".d.json.ts" { 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 @@ -6409,7 +6406,7 @@ export function getDeclarationEmitExtensionForPath(path: string) { * * @internal */ -export function getPossibleOriginalInputExtensionForExtension(path: string) { +export function getPossibleOriginalInputExtensionForExtension(path: string): Extension[] { 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] : @@ -6421,7 +6418,7 @@ export function getPossibleOriginalInputExtensionForExtension(path: string) { * * @internal */ -export function getPathsBasePath(options: CompilerOptions, host: { getCurrentDirectory?(): string; }) { +export function getPathsBasePath(options: CompilerOptions, host: { getCurrentDirectory?(): string; }): string | undefined { if (!options.paths) return undefined; return options.baseUrl ?? Debug.checkDefined(options.pathsBasePath || host.getCurrentDirectory?.(), "Encountered 'paths' without a 'baseUrl', config file, or host 'getCurrentDirectory'."); } @@ -6473,7 +6470,7 @@ 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): boolean { const options = host.getCompilerOptions(); // Js files are emitted only if option is enabled if (options.noEmitForJsFiles && isSourceFileJS(sourceFile)) return false; @@ -6515,7 +6512,7 @@ function getSourceFilePathInNewDirWorker(fileName: string, newDirPath: string, c } /** @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): void { host.writeFile( fileName, text, @@ -6561,7 +6558,7 @@ export function writeFileEnsuringDirectories( } /** @internal */ -export function getLineOfLocalPosition(sourceFile: SourceFile, pos: number) { +export function getLineOfLocalPosition(sourceFile: SourceFile, pos: number): number { const lineStarts = getLineStarts(sourceFile); return computeLineOfPosition(lineStarts, pos); } @@ -6765,7 +6762,7 @@ function emitNewLineBeforeLeadingCommentsOfPosition(lineMap: readonly number[], } /** @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): void { // If the leading comments start on different line than the start of node, write new line if ( pos !== commentPos && @@ -6818,7 +6815,10 @@ 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): { + nodePos: number; + detachedCommentEndPos: number; +} | undefined { let leadingComments: CommentRange[] | undefined; let currentDetachedCommentInfo: { nodePos: number; detachedCommentEndPos: number; } | undefined; if (removeComments) { @@ -6880,7 +6880,7 @@ 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): void { if (text.charCodeAt(commentPos + 1) === CharacterCodes.asterisk) { const firstCommentLineAndCharacter = computeLineAndCharacterOfPosition(lineMap, commentPos); const lineCount = lineMap.length; @@ -6978,12 +6978,12 @@ function calculateIndent(text: string, pos: number, end: number) { } /** @internal */ -export function hasEffectiveModifiers(node: Node) { +export function hasEffectiveModifiers(node: Node): boolean { return getEffectiveModifierFlags(node) !== ModifierFlags.None; } /** @internal */ -export function hasSyntacticModifiers(node: Node) { +export function hasSyntacticModifiers(node: Node): boolean { return getSyntacticModifierFlags(node) !== ModifierFlags.None; } @@ -6998,7 +6998,7 @@ export function hasSyntacticModifier(node: Node, flags: ModifierFlags): boolean } /** @internal */ -export function isStatic(node: Node) { +export function isStatic(node: Node): boolean { // https://tc39.es/ecma262/#sec-static-semantics-isstatic return isClassElement(node) && hasStaticModifier(node) || isClassStaticBlockDeclaration(node); } @@ -7151,7 +7151,7 @@ export function getSyntacticModifierFlagsNoCache(node: Node): ModifierFlags { } /** @internal */ -export function modifiersToFlags(modifiers: readonly ModifierLike[] | undefined) { +export function modifiersToFlags(modifiers: readonly ModifierLike[] | undefined): ModifierFlags { let flags = ModifierFlags.None; if (modifiers) { for (const modifier of modifiers) { @@ -7366,20 +7366,20 @@ export function isPrototypeAccess(node: Node): node is BindableStaticAccessExpre } /** @internal */ -export function isRightSideOfQualifiedNameOrPropertyAccess(node: Node) { +export function isRightSideOfQualifiedNameOrPropertyAccess(node: Node): boolean { 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 */ -export function isRightSideOfAccessExpression(node: Node) { +export function isRightSideOfAccessExpression(node: Node): boolean { return !!node.parent && (isPropertyAccessExpression(node.parent) && node.parent.name === node || isElementAccessExpression(node.parent) && node.parent.argumentExpression === node); } /** @internal */ -export function isRightSideOfQualifiedNameOrPropertyAccessOrJSDocMemberName(node: Node) { +export function isRightSideOfQualifiedNameOrPropertyAccessOrJSDocMemberName(node: Node): boolean { return isQualifiedName(node.parent) && node.parent.right === node || isPropertyAccessExpression(node.parent) && node.parent.name === node || isJSDocMemberName(node.parent) && node.parent.right === node; @@ -7390,7 +7390,7 @@ export function isInstanceOfExpression(node: Node): node is InstanceofExpression } /** @internal */ -export function isRightSideOfInstanceofExpression(node: Node) { +export function isRightSideOfInstanceofExpression(node: Node): boolean { return isInstanceOfExpression(node.parent) && node === node.parent.right; } @@ -7407,7 +7407,7 @@ export function isEmptyArrayLiteral(expression: Node): boolean { } /** @internal */ -export function getLocalSymbolForExportDefault(symbol: Symbol) { +export function getLocalSymbolForExportDefault(symbol: Symbol): Symbol | undefined { if (!isExportDefaultSymbol(symbol) || !symbol.declarations) return undefined; for (const decl of symbol.declarations) { if (decl.localSymbol) return decl.localSymbol; @@ -7598,7 +7598,7 @@ export function readJson(path: string, host: { readFile(fileName: string): strin } /** @internal */ -export function tryParseJson(text: string) { +export function tryParseJson(text: string): any { try { return JSON.parse(text); } @@ -7704,12 +7704,12 @@ export function createTokenRange(pos: number, token: SyntaxKind): TextRange { } /** @internal */ -export function rangeIsOnSingleLine(range: TextRange, sourceFile: SourceFile) { +export function rangeIsOnSingleLine(range: TextRange, sourceFile: SourceFile): boolean { return rangeStartIsOnSameLineAsRangeEnd(range, range, sourceFile); } /** @internal */ -export function rangeStartPositionsAreOnSameLine(range1: TextRange, range2: TextRange, sourceFile: SourceFile) { +export function rangeStartPositionsAreOnSameLine(range1: TextRange, range2: TextRange, sourceFile: SourceFile): boolean { return positionsAreOnSameLine( getStartPositionOfRange(range1, sourceFile, /*includeComments*/ false), getStartPositionOfRange(range2, sourceFile, /*includeComments*/ false), @@ -7718,28 +7718,28 @@ export function rangeStartPositionsAreOnSameLine(range1: TextRange, range2: Text } /** @internal */ -export function rangeEndPositionsAreOnSameLine(range1: TextRange, range2: TextRange, sourceFile: SourceFile) { +export function rangeEndPositionsAreOnSameLine(range1: TextRange, range2: TextRange, sourceFile: SourceFile): boolean { return positionsAreOnSameLine(range1.end, range2.end, sourceFile); } /** @internal @knipignore */ -export function rangeStartIsOnSameLineAsRangeEnd(range1: TextRange, range2: TextRange, sourceFile: SourceFile) { +export function rangeStartIsOnSameLineAsRangeEnd(range1: TextRange, range2: TextRange, sourceFile: SourceFile): boolean { return positionsAreOnSameLine(getStartPositionOfRange(range1, sourceFile, /*includeComments*/ false), range2.end, sourceFile); } /** @internal */ -export function rangeEndIsOnSameLineAsRangeStart(range1: TextRange, range2: TextRange, sourceFile: SourceFile) { +export function rangeEndIsOnSameLineAsRangeStart(range1: TextRange, range2: TextRange, sourceFile: SourceFile): boolean { 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): number { const range2Start = getStartPositionOfRange(range2, sourceFile, includeSecondRangeComments); return getLinesBetweenPositions(sourceFile, range1.end, range2Start); } /** @internal @knipignore */ -export function getLinesBetweenRangeEndPositions(range1: TextRange, range2: TextRange, sourceFile: SourceFile) { +export function getLinesBetweenRangeEndPositions(range1: TextRange, range2: TextRange, sourceFile: SourceFile): number { return getLinesBetweenPositions(sourceFile, range1.end, range2.end); } @@ -7749,24 +7749,24 @@ export function isNodeArrayMultiLine(list: NodeArray, sourceFile: SourceFi } /** @internal */ -export function positionsAreOnSameLine(pos1: number, pos2: number, sourceFile: SourceFile) { +export function positionsAreOnSameLine(pos1: number, pos2: number, sourceFile: SourceFile): boolean { return getLinesBetweenPositions(sourceFile, pos1, pos2) === 0; } /** @internal @knipignore */ -export function getStartPositionOfRange(range: TextRange, sourceFile: SourceFile, includeComments: boolean) { +export function getStartPositionOfRange(range: TextRange, sourceFile: SourceFile, includeComments: boolean): number { 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): number { 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): number { const nextPos = skipTrivia(sourceFile.text, pos, /*stopAfterLineBreak*/ false, includeComments); return getLinesBetweenPositions(sourceFile, pos, Math.min(stopPos, nextPos)); } @@ -7785,7 +7785,7 @@ function getPreviousNonWhitespacePosition(pos: number, stopPos = 0, sourceFile: * * @internal */ -export function isDeclarationNameOfEnumOrNamespace(node: Identifier) { +export function isDeclarationNameOfEnumOrNamespace(node: Identifier): boolean { const parseNode = getParseTreeNode(node); if (parseNode) { switch (parseNode.parent.kind) { @@ -7798,7 +7798,7 @@ export function isDeclarationNameOfEnumOrNamespace(node: Identifier) { } /** @internal */ -export function getInitializedVariables(node: VariableDeclarationList) { +export function getInitializedVariables(node: VariableDeclarationList): readonly InitializedVariableDeclaration[] { return filter(node.declarations, isInitializedVariable); } @@ -7808,13 +7808,13 @@ export function isInitializedVariable(node: Node): node is InitializedVariableDe } /** @internal */ -export function isWatchSet(options: CompilerOptions) { +export function isWatchSet(options: CompilerOptions): boolean | undefined { // Firefox has Object.prototype.watch return options.watch && hasProperty(options, "watch"); } /** @internal */ -export function closeFileWatcher(watcher: FileWatcher) { +export function closeFileWatcher(watcher: FileWatcher): void { watcher.close(); } @@ -7847,7 +7847,7 @@ export function getDeclarationModifierFlagsFromSymbol(s: Symbol, isWrite = false } /** @internal */ -export function skipAlias(symbol: Symbol, checker: TypeChecker) { +export function skipAlias(symbol: Symbol, checker: TypeChecker): Symbol { return symbol.flags & SymbolFlags.Alias ? checker.getAliasedSymbol(symbol) : symbol; } @@ -7861,12 +7861,12 @@ export function getCombinedLocalAndExportSymbolFlags(symbol: Symbol): SymbolFlag } /** @internal */ -export function isWriteOnlyAccess(node: Node) { +export function isWriteOnlyAccess(node: Node): boolean { return accessKind(node) === AccessKind.Write; } /** @internal */ -export function isWriteAccess(node: Node) { +export function isWriteAccess(node: Node): boolean { return accessKind(node) !== AccessKind.Read; } @@ -7948,7 +7948,7 @@ 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): void { // Remove all map.forEach(onDeleteValue); map.clear(); @@ -8140,7 +8140,7 @@ export function isAccessExpression(node: Node): node is AccessExpression { } /** @internal */ -export function getNameOfAccessExpression(node: AccessExpression) { +export function getNameOfAccessExpression(node: AccessExpression): Expression { if (node.kind === SyntaxKind.PropertyAccessExpression) { return node.name; } @@ -8200,7 +8200,7 @@ export function forEachNameInAccessChainWalkingLeft(name: MemberName | String } /** @internal */ -export function getLeftmostExpression(node: Expression, stopAtCallExpressions: boolean) { +export function getLeftmostExpression(node: Expression, stopAtCallExpressions: boolean): Expression { while (true) { switch (node.kind) { case SyntaxKind.PostfixUnaryExpression: @@ -8251,7 +8251,7 @@ export interface ObjectAllocator { getSourceMapSourceConstructor(): new (fileName: string, text: string, skipTrivia?: (pos: number) => number) => SourceMapSource; } -function Symbol(this: Symbol, flags: SymbolFlags, name: __String) { +function Symbol(this: Symbol, flags: SymbolFlags, name: __String): void { // Note: if modifying this, be sure to update SymbolObject in src/services/services.ts this.flags = flags; this.escapedName = name; @@ -8269,7 +8269,7 @@ function Symbol(this: Symbol, flags: SymbolFlags, name: __String) { (this as any).links = undefined; // used by TransientSymbol } -function Type(this: Type, checker: TypeChecker, flags: TypeFlags) { +function Type(this: Type, checker: TypeChecker, flags: TypeFlags): void { // Note: if modifying this, be sure to update TypeObject in src/services/services.ts this.flags = flags; if (Debug.isDebugging || tracing) { @@ -8277,7 +8277,7 @@ function Type(this: Type, checker: TypeChecker, flags: TypeFlags) { } } -function Signature(this: Signature, checker: TypeChecker, flags: SignatureFlags) { +function Signature(this: Signature, checker: TypeChecker, flags: SignatureFlags): void { // Note: if modifying this, be sure to update SignatureObject in src/services/services.ts this.flags = flags; if (Debug.isDebugging) { @@ -8285,7 +8285,7 @@ function Signature(this: Signature, checker: TypeChecker, flags: SignatureFlags) } } -function Node(this: Mutable, kind: SyntaxKind, pos: number, end: number) { +function Node(this: Mutable, kind: SyntaxKind, pos: number, end: number): void { // Note: if modifying this, be sure to update NodeObject in src/services/services.ts this.pos = pos; this.end = end; @@ -8299,7 +8299,7 @@ function Node(this: Mutable, kind: SyntaxKind, pos: number, end: number) { this.emitNode = undefined; } -function Token(this: Mutable, kind: SyntaxKind, pos: number, end: number) { +function Token(this: Mutable, kind: SyntaxKind, pos: number, end: number): void { // Note: if modifying this, be sure to update TokenOrIdentifierObject in src/services/services.ts this.pos = pos; this.end = end; @@ -8311,7 +8311,7 @@ function Token(this: Mutable, kind: SyntaxKind, pos: number, end: number) this.emitNode = undefined; } -function Identifier(this: Mutable, kind: SyntaxKind, pos: number, end: number) { +function Identifier(this: Mutable, kind: SyntaxKind, pos: number, end: number): void { // Note: if modifying this, be sure to update TokenOrIdentifierObject in src/services/services.ts this.pos = pos; this.end = end; @@ -8324,7 +8324,7 @@ function Identifier(this: Mutable, kind: SyntaxKind, pos: number, end: num this.emitNode = undefined; } -function SourceMapSource(this: SourceMapSource, fileName: string, text: string, skipTrivia?: (pos: number) => number) { +function SourceMapSource(this: SourceMapSource, fileName: string, text: string, skipTrivia?: (pos: number) => number): void { // Note: if modifying this, be sure to update SourceMapSourceObject in src/services/services.ts this.fileName = fileName; this.text = text; @@ -8351,13 +8351,13 @@ const objectAllocatorPatchers: ((objectAllocator: ObjectAllocator) => void)[] = * @internal * @knipignore */ -export function addObjectAllocatorPatcher(fn: (objectAllocator: ObjectAllocator) => void) { +export function addObjectAllocatorPatcher(fn: (objectAllocator: ObjectAllocator) => void): void { objectAllocatorPatchers.push(fn); fn(objectAllocator); } /** @internal */ -export function setObjectAllocator(alloc: ObjectAllocator) { +export function setObjectAllocator(alloc: ObjectAllocator): void { Object.assign(objectAllocator, alloc); forEach(objectAllocatorPatchers, fn => fn(objectAllocator)); } @@ -8370,21 +8370,21 @@ export function formatStringFromArgs(text: string, args: DiagnosticArguments): s let localizedDiagnosticMessages: MapLike | undefined; /** @internal */ -export function setLocalizedDiagnosticMessages(messages: MapLike | undefined) { +export function setLocalizedDiagnosticMessages(messages: MapLike | undefined): void { localizedDiagnosticMessages = messages; } /** @internal */ // If the localized messages json is unset, and if given function use it to set the json -export function maybeSetLocalizedDiagnosticMessages(getMessages: undefined | (() => MapLike | undefined)) { +export function maybeSetLocalizedDiagnosticMessages(getMessages: undefined | (() => MapLike | undefined)): void { if (!localizedDiagnosticMessages && getMessages) { localizedDiagnosticMessages = getMessages(); } } /** @internal */ -export function getLocaleSpecificMessage(message: DiagnosticMessage) { +export function getLocaleSpecificMessage(message: DiagnosticMessage): string { return localizedDiagnosticMessages && localizedDiagnosticMessages[message.key] || message.message; } @@ -8728,7 +8728,7 @@ function messageTextEqualityComparer(m1: string | DiagnosticMessageChain, m2: st } /** @internal */ -export function getLanguageVariant(scriptKind: ScriptKind) { +export function getLanguageVariant(scriptKind: ScriptKind): LanguageVariant { // .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; } @@ -8794,7 +8794,7 @@ export function getSetExternalModuleIndicator(options: CompilerOptions): (file: * Returns true if an `import` and a `require` of the same module specifier * can resolve to a different file. */ -export function importSyntaxAffectsModuleResolution(options: CompilerOptions) { +export function importSyntaxAffectsModuleResolution(options: CompilerOptions): boolean { const moduleResolution = getEmitModuleResolutionKind(options); return ModuleResolutionKind.Node16 <= moduleResolution && moduleResolution <= ModuleResolutionKind.NodeNext || getResolvePackageJsonExports(options) @@ -8814,7 +8814,108 @@ function createComputedCompilerOptions) => boolean; + }; + allowSyntheticDefaultImports: { + dependencies: ("module" | "moduleResolution" | "target")[]; + computeValue: (compilerOptions: Pick) => boolean; + }; + alwaysStrict: { + dependencies: "strict"[]; + computeValue: (compilerOptions: Pick) => boolean; + }; + declaration: { + dependencies: "composite"[]; + computeValue: (compilerOptions: Pick) => boolean; + }; + declarationMap: { + dependencies: ("declaration" | "composite")[]; + computeValue: (compilerOptions: Pick) => boolean; + }; + isolatedModules: { + dependencies: "verbatimModuleSyntax"[]; + computeValue: (compilerOptions: Pick) => boolean; + }; + module: { + dependencies: "target"[]; + computeValue: (compilerOptions: Pick) => ModuleKind; + }; + moduleResolution: { + dependencies: ("module" | "target")[]; + computeValue: (compilerOptions: Pick) => ModuleResolutionKind; + }; + moduleDetection: { + dependencies: ("module" | "target")[]; + computeValue: (compilerOptions: Pick) => ModuleDetectionKind; + }; + noImplicitAny: { + dependencies: "strict"[]; + computeValue: (compilerOptions: Pick) => boolean; + }; + noImplicitThis: { + dependencies: "strict"[]; + computeValue: (compilerOptions: Pick) => boolean; + }; + preserveConstEnums: { + dependencies: ("isolatedModules" | "verbatimModuleSyntax")[]; + computeValue: (compilerOptions: Pick) => boolean; + }; + incremental: { + dependencies: "composite"[]; + computeValue: (compilerOptions: Pick) => boolean; + }; + resolvePackageJsonExports: { + dependencies: "moduleResolution"[]; + computeValue: (compilerOptions: Pick) => boolean; + }; + resolvePackageJsonImports: { + dependencies: ("moduleResolution" | "resolvePackageJsonExports")[]; + computeValue: (compilerOptions: Pick) => boolean; + }; + strictFunctionTypes: { + dependencies: "strict"[]; + computeValue: (compilerOptions: Pick) => boolean; + }; + strictBindCallApply: { + dependencies: "strict"[]; + computeValue: (compilerOptions: Pick) => boolean; + }; + strictNullChecks: { + dependencies: "strict"[]; + computeValue: (compilerOptions: Pick) => boolean; + }; + strictPropertyInitialization: { + dependencies: "strict"[]; + computeValue: (compilerOptions: Pick) => boolean; + }; + strictBuiltinIteratorReturn: { + dependencies: "strict"[]; + computeValue: (compilerOptions: Pick) => boolean; + }; + target: { + dependencies: "module"[]; + computeValue: (compilerOptions: Pick) => ScriptTarget; + }; + useUnknownInCatchVariables: { + dependencies: "strict"[]; + computeValue: (compilerOptions: Pick) => boolean; + }; + resolveJsonModule: { + dependencies: ("module" | "moduleResolution" | "target")[]; + computeValue: (compilerOptions: Pick) => boolean; + }; + esModuleInterop: { + dependencies: ("module" | "target")[]; + computeValue: (compilerOptions: Pick) => boolean; + }; + useDefineForClassFields: { + dependencies: ("module" | "target")[]; + computeValue: (compilerOptions: Pick) => boolean; + }; +} = createComputedCompilerOptions({ target: { dependencies: ["module"], computeValue: compilerOptions => { @@ -9041,45 +9142,45 @@ export const computedOptions = createComputedCompilerOptions({ }); /** @internal */ -export const getEmitScriptTarget = computedOptions.target.computeValue; +export const getEmitScriptTarget: (compilerOptions: Pick) => ScriptTarget = computedOptions.target.computeValue; /** @internal */ -export const getEmitModuleKind = computedOptions.module.computeValue; +export const getEmitModuleKind: (compilerOptions: Pick) => ModuleKind = computedOptions.module.computeValue; /** @internal */ -export const getEmitModuleResolutionKind = computedOptions.moduleResolution.computeValue; +export const getEmitModuleResolutionKind: (compilerOptions: Pick) => ModuleResolutionKind = computedOptions.moduleResolution.computeValue; /** @internal @knipignore */ -export const getEmitModuleDetectionKind = computedOptions.moduleDetection.computeValue; +export const getEmitModuleDetectionKind: (compilerOptions: Pick) => ModuleDetectionKind = computedOptions.moduleDetection.computeValue; /** @internal */ -export const getIsolatedModules = computedOptions.isolatedModules.computeValue; +export const getIsolatedModules: (compilerOptions: Pick) => boolean = computedOptions.isolatedModules.computeValue; /** @internal */ -export const getESModuleInterop = computedOptions.esModuleInterop.computeValue; +export const getESModuleInterop: (compilerOptions: Pick) => boolean = computedOptions.esModuleInterop.computeValue; /** @internal */ -export const getAllowSyntheticDefaultImports = computedOptions.allowSyntheticDefaultImports.computeValue; +export const getAllowSyntheticDefaultImports: (compilerOptions: Pick) => boolean = computedOptions.allowSyntheticDefaultImports.computeValue; /** @internal */ -export const getResolvePackageJsonExports = computedOptions.resolvePackageJsonExports.computeValue; +export const getResolvePackageJsonExports: (compilerOptions: Pick) => boolean = computedOptions.resolvePackageJsonExports.computeValue; /** @internal */ -export const getResolvePackageJsonImports = computedOptions.resolvePackageJsonImports.computeValue; +export const getResolvePackageJsonImports: (compilerOptions: Pick) => boolean = computedOptions.resolvePackageJsonImports.computeValue; /** @internal */ -export const getResolveJsonModule = computedOptions.resolveJsonModule.computeValue; +export const getResolveJsonModule: (compilerOptions: Pick) => boolean = computedOptions.resolveJsonModule.computeValue; /** @internal */ -export const getEmitDeclarations = computedOptions.declaration.computeValue; +export const getEmitDeclarations: (compilerOptions: Pick) => boolean = computedOptions.declaration.computeValue; /** @internal */ -export const shouldPreserveConstEnums = computedOptions.preserveConstEnums.computeValue; +export const shouldPreserveConstEnums: (compilerOptions: Pick) => boolean = computedOptions.preserveConstEnums.computeValue; /** @internal */ -export const isIncrementalCompilation = computedOptions.incremental.computeValue; +export const isIncrementalCompilation: (compilerOptions: Pick) => boolean = computedOptions.incremental.computeValue; /** @internal */ -export const getAreDeclarationMapsEnabled = computedOptions.declarationMap.computeValue; +export const getAreDeclarationMapsEnabled: (compilerOptions: Pick) => boolean = computedOptions.declarationMap.computeValue; /** @internal */ -export const getAllowJSCompilerOption = computedOptions.allowJs.computeValue; +export const getAllowJSCompilerOption: (compilerOptions: Pick) => boolean = computedOptions.allowJs.computeValue; /** @internal */ -export const getUseDefineForClassFields = computedOptions.useDefineForClassFields.computeValue; +export const getUseDefineForClassFields: (compilerOptions: Pick) => boolean = computedOptions.useDefineForClassFields.computeValue; /** @internal */ -export function emitModuleKindIsNonNodeESM(moduleKind: ModuleKind) { +export function emitModuleKindIsNonNodeESM(moduleKind: ModuleKind): boolean { return moduleKind >= ModuleKind.ES2015 && moduleKind <= ModuleKind.ESNext; } /** @internal */ -export function hasJsonModuleEmitEnabled(options: CompilerOptions) { +export function hasJsonModuleEmitEnabled(options: CompilerOptions): boolean { switch (getEmitModuleKind(options)) { case ModuleKind.None: case ModuleKind.System: @@ -9128,7 +9229,7 @@ export function getNameOfScriptTarget(scriptTarget: ScriptTarget): string | unde } /** @internal */ -export function getEmitStandardClassFields(compilerOptions: CompilerOptions) { +export function getEmitStandardClassFields(compilerOptions: CompilerOptions): boolean { return compilerOptions.useDefineForClassFields !== false && getEmitScriptTarget(compilerOptions) >= ScriptTarget.ES2022; } @@ -9179,7 +9280,7 @@ export function getJSXImplicitImportBase(compilerOptions: CompilerOptions, file? } /** @internal */ -export function getJSXRuntimeImport(base: string | undefined, options: CompilerOptions) { +export function getJSXRuntimeImport(base: string | undefined, options: CompilerOptions): string | undefined { return base ? `${base}/${options.jsx === JsxEmit.ReactJSXDev ? "jsx-dev-runtime" : "jsx-runtime"}` : undefined; } @@ -9346,7 +9447,7 @@ export function tryRemoveDirectoryPrefix(path: string, dirPath: string, getCanon const reservedCharacterPattern = /[^\w\s/]/g; /** @internal */ -export function regExpEscape(text: string) { +export function regExpEscape(text: string): string { return text.replace(reservedCharacterPattern, escapeRegExpCharacter); } @@ -9438,7 +9539,7 @@ export function isImplicitGlob(lastPathComponent: string): boolean { } /** @internal */ -export function getPatternFromSpec(spec: string, basePath: string, usage: "files" | "directories" | "exclude") { +export function getPatternFromSpec(spec: string, basePath: string, usage: "files" | "directories" | "exclude"): string | undefined { const pattern = spec && getSubPatternFromSpec(spec, basePath, usage, wildcardMatchers[usage]); return pattern && `^(${pattern})${usage === "exclude" ? "($|/)" : "$"}`; } @@ -9888,7 +9989,7 @@ 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[]): boolean { if (!fileName) return false; const supportedExtensions = getSupportedExtensions(compilerOptions, extraFileExtensions); @@ -9906,7 +10007,7 @@ function numberOfDirectorySeparators(str: string) { } /** @internal */ -export function compareNumberOfDirectorySeparators(path1: string, path2: string) { +export function compareNumberOfDirectorySeparators(path1: string, path2: string): Comparison { return compareValues( numberOfDirectorySeparators(path1), numberOfDirectorySeparators(path2), @@ -9981,7 +10082,7 @@ export function extensionIsTS(ext: string): boolean { } /** @internal */ -export function resolutionExtensionIsTSOrJson(ext: string) { +export function resolutionExtensionIsTSOrJson(ext: string): boolean { return extensionIsTS(ext) || ext === Extension.Json; } @@ -10007,7 +10108,7 @@ export function tryGetExtensionFromPath(path: string): Extension | undefined { } /** @internal */ -export function isCheckJsEnabledForFile(sourceFile: SourceFile, compilerOptions: CompilerOptions) { +export function isCheckJsEnabledForFile(sourceFile: SourceFile, compilerOptions: CompilerOptions): boolean | undefined { return sourceFile.checkJsDirective ? sourceFile.checkJsDirective.enabled : compilerOptions.checkJs; } @@ -10101,7 +10202,7 @@ export function skipTypeChecking( sourceFile: SourceFile, options: CompilerOptions, host: HostWithIsSourceOfProjectReferenceRedirect, -) { +): boolean { return skipTypeCheckingWorker(sourceFile, options, host, /*ignoreNoCheck*/ false); } @@ -10110,7 +10211,7 @@ export function skipTypeCheckingIgnoringNoCheck( sourceFile: SourceFile, options: CompilerOptions, host: HostWithIsSourceOfProjectReferenceRedirect, -) { +): boolean { return skipTypeCheckingWorker(sourceFile, options, host, /*ignoreNoCheck*/ true); } @@ -10131,7 +10232,7 @@ function skipTypeCheckingWorker( } /** @internal */ -export function canIncludeBindAndCheckDiagnostics(sourceFile: SourceFile, options: CompilerOptions) { +export function canIncludeBindAndCheckDiagnostics(sourceFile: SourceFile, options: CompilerOptions): boolean { if (!!sourceFile.checkJsDirective && sourceFile.checkJsDirective.enabled === false) return false; if ( sourceFile.scriptKind === ScriptKind.TS || @@ -10329,7 +10430,7 @@ export function isIdentifierTypeReference(node: Node): node is TypeReferenceNode } /** @internal */ -export function arrayIsHomogeneous(array: readonly T[], comparer: EqualityComparer = equateValues) { +export function arrayIsHomogeneous(array: readonly T[], comparer: EqualityComparer = equateValues): boolean { if (array.length < 2) return true; const first = array[0]; for (let i = 1, length = array.length; i < length; i++) { @@ -10344,7 +10445,7 @@ export function arrayIsHomogeneous(array: readonly T[], comparer: EqualityCom * * @internal */ -export function setTextRangePos(range: T, pos: number) { +export function setTextRangePos(range: T, pos: number): T { (range as TextRange).pos = pos; return range; } @@ -10354,7 +10455,7 @@ export function setTextRangePos(range: T, pos: numb * * @internal */ -export function setTextRangeEnd(range: T, end: number) { +export function setTextRangeEnd(range: T, end: number): T { (range as TextRange).end = end; return range; } @@ -10364,7 +10465,7 @@ export function setTextRangeEnd(range: T, end: numb * * @internal */ -export function setTextRangePosEnd(range: T, pos: number, end: number) { +export function setTextRangePosEnd(range: T, pos: number, end: number): T { return setTextRangeEnd(setTextRangePos(range, pos), end); } @@ -10374,7 +10475,7 @@ export function setTextRangePosEnd(range: T, pos: n * * @internal */ -export function setTextRangePosWidth(range: T, pos: number, width: number) { +export function setTextRangePosWidth(range: T, pos: number, width: number): T { return setTextRangePosEnd(range, pos, pos + width); } @@ -10457,7 +10558,7 @@ function isPackedElement(node: Expression) { * * @internal */ -export function isPackedArrayLiteral(node: Expression) { +export function isPackedArrayLiteral(node: Expression): boolean { return isArrayLiteralExpression(node) && every(node.elements, isPackedElement); } @@ -10504,7 +10605,7 @@ export function expressionResultIsUnused(node: Expression): boolean { } /** @internal */ -export function containsIgnoredPath(path: string) { +export function containsIgnoredPath(path: string): boolean { return some(ignoredPaths, p => path.includes(p)); } @@ -10580,7 +10681,7 @@ export function getContainingNodeArray(node: Node): NodeArray | undefined } /** @internal */ -export function hasContextSensitiveParameters(node: FunctionLikeDeclaration) { +export function hasContextSensitiveParameters(node: FunctionLikeDeclaration): boolean { // Functions with type parameters are not context sensitive. if (!node.typeParameters) { // Functions with any parameters that lack type annotations are context sensitive. @@ -10605,7 +10706,7 @@ export function isInfinityOrNaNString(name: string | __String): boolean { } /** @internal */ -export function isCatchClauseVariableDeclaration(node: Node) { +export function isCatchClauseVariableDeclaration(node: Node): boolean { return node.kind === SyntaxKind.VariableDeclaration && node.parent.kind === SyntaxKind.CatchClause; } @@ -10620,7 +10721,7 @@ export function escapeSnippetText(text: string): string { } /** @internal */ -export function isNumericLiteralName(name: string | __String) { +export function isNumericLiteralName(name: string | __String): boolean { // The intent of numeric names is that // - they are names with text in a numeric form, and that // - setting properties/indexing with them is always equivalent to doing so with the numeric literal 'numLit', @@ -10646,7 +10747,7 @@ export function isNumericLiteralName(name: string | __String) { } /** @internal */ -export function createPropertyNameNodeForIdentifierOrLiteral(name: string, target: ScriptTarget, singleQuote: boolean, stringNamed: boolean, isMethod: boolean) { +export function createPropertyNameNodeForIdentifierOrLiteral(name: string, target: ScriptTarget, singleQuote: boolean, stringNamed: boolean, isMethod: boolean): Identifier | StringLiteral | NumericLiteral { const isMethodNamedNew = isMethod && name === "new"; return !isMethodNamedNew && isIdentifierText(name, target) ? factory.createIdentifier(name) : !stringNamed && !isMethodNamedNew && isNumericLiteralName(name) && +name >= 0 ? factory.createNumericLiteral(+name) : @@ -10778,7 +10879,7 @@ export function hasTabstop(node: Node): boolean { } /** @internal */ -export function isJSDocOptionalParameter(node: ParameterDeclaration) { +export function isJSDocOptionalParameter(node: ParameterDeclaration): boolean { 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 @@ -10815,12 +10916,12 @@ export function isJSDocSatisfiesExpression(node: Node): node is JSDocSatisfiesEx } /** @internal */ -export function getJSDocSatisfiesExpressionType(node: JSDocSatisfiesExpression) { +export function getJSDocSatisfiesExpressionType(node: JSDocSatisfiesExpression): TypeNode { return Debug.checkDefined(tryGetJSDocSatisfiesTypeNode(node)); } /** @internal */ -export function tryGetJSDocSatisfiesTypeNode(node: Node) { +export function tryGetJSDocSatisfiesTypeNode(node: Node): TypeNode | undefined { const tag = getJSDocSatisfiesTag(node); return tag && tag.typeExpression && tag.typeExpression.type; } @@ -10853,7 +10954,7 @@ export function getTextOfJsxNamespacedName(node: JsxNamespacedName) { } /** @internal */ -export function intrinsicTagNameToString(node: Identifier | JsxNamespacedName) { +export function intrinsicTagNameToString(node: Identifier | JsxNamespacedName): string { return isIdentifier(node) ? idText(node) : getTextOfJsxNamespacedName(node); } @@ -10885,7 +10986,7 @@ export function isExpandoPropertyDeclaration(declaration: Declaration | undefine } /** @internal */ -export function hasResolutionModeOverride(node: ImportTypeNode | ImportDeclaration | ExportDeclaration | JSDocImportTag | undefined) { +export function hasResolutionModeOverride(node: ImportTypeNode | ImportDeclaration | ExportDeclaration | JSDocImportTag | undefined): boolean { if (node === undefined) { return false; } @@ -10904,7 +11005,7 @@ export function replaceFirstStar(s: string, replacement: string): string { } /** @internal */ -export function getNameFromImportAttribute(node: ImportAttribute) { +export function getNameFromImportAttribute(node: ImportAttribute): __String { return isIdentifier(node.name) ? node.name.escapedText : escapeLeadingUnderscores(node.name.text); } @@ -11015,7 +11116,10 @@ export function evaluatorResult(value: T, } /** @internal */ -export function createEvaluator({ evaluateElementAccessExpression, evaluateEntityNameExpression }: EvaluationResolver) { +export function createEvaluator({ evaluateElementAccessExpression, evaluateEntityNameExpression }: EvaluationResolver): { + (expr: TemplateExpression, location?: Declaration): EvaluatorResult; + (expr: Expression, location?: Declaration): EvaluatorResult; +} { function evaluate(expr: TemplateExpression, location?: Declaration): EvaluatorResult; function evaluate(expr: Expression, location?: Declaration): EvaluatorResult; function evaluate(expr: Expression, location?: Declaration): EvaluatorResult { @@ -11145,7 +11249,7 @@ export function createEvaluator({ evaluateElementAccessExpression, evaluateEntit } /** @internal */ -export function isConstAssertion(location: Node) { +export function isConstAssertion(location: Node): boolean { return (isAssertionExpression(location) && isConstTypeReference(location.type)) || (isJSDocTypeTag(location) && isConstTypeReference(location.typeExpression)); } @@ -11199,7 +11303,14 @@ export function createNameResolver({ associatedDeclarationForContainingInitializerOrBindingName: ParameterDeclaration | BindingElement | undefined, withinDeferredContext: boolean, ) => void; -}) { +}): ( + location: Node | undefined, + nameArg: __String | Identifier, + meaning: SymbolFlags, + nameNotFoundMessage: DiagnosticMessage | undefined, + isUse: boolean, + excludeGlobals?: boolean, +) => Symbol | undefined { /* eslint-disable no-var */ var isolatedModulesLikeFlagName = compilerOptions.verbatimModuleSyntax ? "verbatimModuleSyntax" : "isolatedModules"; /* eslint-disable no-var */ @@ -11751,7 +11862,7 @@ export function isPrimitiveLiteralValue(node: Expression, includeBigInt = true): } /** @internal */ -export function unwrapParenthesizedExpression(o: Expression) { +export function unwrapParenthesizedExpression(o: Expression): Expression { while (o.kind === SyntaxKind.ParenthesizedExpression) { o = (o as ParenthesizedExpression).expression; } diff --git a/src/compiler/utilitiesPublic.ts b/src/compiler/utilitiesPublic.ts index dfc3f2d069bde..79f1f6fba0d03 100644 --- a/src/compiler/utilitiesPublic.ts +++ b/src/compiler/utilitiesPublic.ts @@ -330,15 +330,15 @@ export function getDefaultLibFileName(options: CompilerOptions): string { } } -export function textSpanEnd(span: TextSpan) { +export function textSpanEnd(span: TextSpan): number { return span.start + span.length; } -export function textSpanIsEmpty(span: TextSpan) { +export function textSpanIsEmpty(span: TextSpan): boolean { return span.length === 0; } -export function textSpanContainsPosition(span: TextSpan, position: number) { +export function textSpanContainsPosition(span: TextSpan, position: number): boolean { return position >= span.start && position < textSpanEnd(span); } @@ -348,21 +348,21 @@ export function textRangeContainsPositionInclusive(range: TextRange, position: n } // Returns true if 'span' contains 'other'. -export function textSpanContainsTextSpan(span: TextSpan, other: TextSpan) { +export function textSpanContainsTextSpan(span: TextSpan, other: TextSpan): boolean { return other.start >= span.start && textSpanEnd(other) <= textSpanEnd(span); } /** @internal */ -export function textSpanContainsTextRange(span: TextSpan, range: TextRange) { +export function textSpanContainsTextRange(span: TextSpan, range: TextRange): boolean { return range.pos >= span.start && range.end <= textSpanEnd(span); } /** @internal */ -export function textRangeContainsTextSpan(range: TextRange, span: TextSpan) { +export function textRangeContainsTextSpan(range: TextRange, span: TextSpan): boolean { return span.start >= range.pos && textSpanEnd(span) <= range.end; } -export function textSpanOverlapsWith(span: TextSpan, other: TextSpan) { +export function textSpanOverlapsWith(span: TextSpan, other: TextSpan): boolean { return textSpanOverlap(span, other) !== undefined; } @@ -439,15 +439,15 @@ export function createTextSpan(start: number, length: number): TextSpan { return { start, length }; } -export function createTextSpanFromBounds(start: number, end: number) { +export function createTextSpanFromBounds(start: number, end: number): TextSpan { return createTextSpan(start, end - start); } -export function textChangeRangeNewSpan(range: TextChangeRange) { +export function textChangeRangeNewSpan(range: TextChangeRange): TextSpan { return createTextSpan(range.span.start, range.newLength); } -export function textChangeRangeIsUnchanged(range: TextChangeRange) { +export function textChangeRangeIsUnchanged(range: TextChangeRange): boolean { return textSpanIsEmpty(range.span) && range.newLength === 0; } @@ -459,7 +459,7 @@ export function createTextChangeRange(span: TextSpan, newLength: number): TextCh return { span, newLength }; } -export const unchangedTextChangeRange = createTextChangeRange(createTextSpan(0, 0), 0); +export const unchangedTextChangeRange: TextChangeRange = createTextChangeRange(createTextSpan(0, 0), 0); /** * Called to merge all the changes that occurred across several versions of a script snapshot @@ -669,7 +669,7 @@ 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: string[] = ["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, @@ -679,7 +679,7 @@ export function validateLocaleAndSetLanguage( locale: string, sys: { getExecutingFilePath(): string; resolvePath(path: string): string; fileExists(fileName: string): boolean; readFile(fileName: string): string | undefined; }, errors?: Diagnostic[], -) { +): void { const lowerCaseLocale = locale.toLowerCase(); const matchResult = /^([a-z]+)([_-]([a-z]+))?$/.exec(lowerCaseLocale); @@ -913,7 +913,7 @@ function getDeclarationIdentifier(node: Declaration | Expression): Identifier | } /** @internal */ -export function nodeHasName(statement: Node, name: Identifier) { +export function nodeHasName(statement: Node, name: Identifier): boolean { if (isNamedDeclaration(statement) && isIdentifier(statement.name) && idText(statement.name as Identifier) === idText(name)) { return true; } @@ -1276,7 +1276,7 @@ export function getAllJSDocTagsOfKind(node: Node, kind: SyntaxKind): readonly JS } /** Gets the text of a jsdoc comment, flattening links to their text. */ -export function getTextOfJSDocComment(comment?: string | NodeArray) { +export function getTextOfJSDocComment(comment?: string | NodeArray): string | undefined { return typeof comment === "string" ? comment : comment?.map(c => c.kind === SyntaxKind.JSDocText ? c.text : formatJSDocLink(c)).join(""); } @@ -1398,17 +1398,17 @@ export function isExpressionOfOptionalChainRoot(node: Node): node is Expression * * @internal */ -export function isOutermostOptionalChain(node: OptionalChain) { +export function isOutermostOptionalChain(node: OptionalChain): boolean { return !isOptionalChain(node.parent) // cases 1, 2, and 3 || isOptionalChainRoot(node.parent) // case 4 || node !== node.parent.expression; // case 5 } -export function isNullishCoalesce(node: Node) { +export function isNullishCoalesce(node: Node): boolean { return node.kind === SyntaxKind.BinaryExpression && (node as BinaryExpression).operatorToken.kind === SyntaxKind.QuestionQuestionToken; } -export function isConstTypeReference(node: Node) { +export function isConstTypeReference(node: Node): boolean { return isTypeReferenceNode(node) && isIdentifier(node.typeName) && node.typeName.escapedText === "const" && !node.typeArguments; } @@ -1444,7 +1444,7 @@ export function isJSDocPropertyLikeTag(node: Node): node is JSDocPropertyLikeTag // they may be used with transformations. /** @internal */ -export function isNodeKind(kind: SyntaxKind) { +export function isNodeKind(kind: SyntaxKind): boolean { return kind >= SyntaxKind.FirstNode; } @@ -1485,7 +1485,7 @@ export function isLiteralExpression(node: Node): node is LiteralExpression { } /** @internal */ -export function isLiteralExpressionOfObject(node: Node) { +export function isLiteralExpressionOfObject(node: Node): boolean { switch (node.kind) { case SyntaxKind.ObjectLiteralExpression: case SyntaxKind.ArrayLiteralExpression: @@ -1568,7 +1568,7 @@ export function isGeneratedPrivateIdentifier(node: Node): node is GeneratedPriva } /** @internal */ -export function isFileLevelReservedGeneratedIdentifier(node: GeneratedIdentifier) { +export function isFileLevelReservedGeneratedIdentifier(node: GeneratedIdentifier): boolean { const flags = node.emitNode.autoGenerate.flags; return !!(flags & GeneratedIdentifierFlags.FileLevel) && !!(flags & GeneratedIdentifierFlags.Optimistic) @@ -2111,17 +2111,17 @@ function isScopeMarker(node: Node) { } /** @internal */ -export function hasScopeMarker(statements: readonly Statement[]) { +export function hasScopeMarker(statements: readonly Statement[]): boolean { return some(statements, isScopeMarker); } /** @internal */ -export function needsScopeMarker(result: Statement) { +export function needsScopeMarker(result: Statement): boolean { return !isAnyImportOrReExport(result) && !isExportAssignment(result) && !hasSyntacticModifier(result, ModifierFlags.Export) && !isAmbientModule(result); } /** @internal */ -export function isExternalModuleIndicator(result: Statement) { +export function isExternalModuleIndicator(result: Statement): boolean { // Exported top-level member indicates moduleness return isAnyImportOrReExport(result) || isExportAssignment(result) || hasSyntacticModifier(result, ModifierFlags.Export); } @@ -2569,7 +2569,7 @@ export function isTypeReferenceType(node: Node): node is TypeReferenceType { const MAX_SMI_X86 = 0x3fff_ffff; /** @internal */ -export function guessIndentation(lines: string[]) { +export function guessIndentation(lines: string[]): number | undefined { let indentation = MAX_SMI_X86; for (const line of lines) { if (!line.length) { @@ -2614,7 +2614,7 @@ function hasInternalAnnotation(range: CommentRange, sourceFile: SourceFile) { return comment.includes("@internal"); } -export function isInternalDeclaration(node: Node, sourceFile?: SourceFile) { +export function isInternalDeclaration(node: Node, sourceFile?: SourceFile): boolean { sourceFile ??= getSourceFileOfNode(node); const parseTreeNode = getParseTreeNode(node); if (parseTreeNode && parseTreeNode.kind === SyntaxKind.Parameter) { diff --git a/src/compiler/visitorPublic.ts b/src/compiler/visitorPublic.ts index f3e71e026d9be..dbd49379e5750 100644 --- a/src/compiler/visitorPublic.ts +++ b/src/compiler/visitorPublic.ts @@ -379,7 +379,7 @@ 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): NodeArray { context.startLexicalEnvironment(); statements = nodesVisitor(statements, visitor, isStatement, start); if (ensureUseStrict) statements = context.factory.ensureUseStrict(statements); @@ -561,7 +561,7 @@ export function visitIterationBody(body: Statement, visitor: Visitor, context: T * @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}. */ -export function visitCommaListElements(elements: NodeArray, visitor: Visitor, discardVisitor = visitor): NodeArray { +export function visitCommaListElements(elements: NodeArray, visitor: Visitor, discardVisitor: Visitor = visitor): NodeArray { if (discardVisitor === visitor || elements.length <= 1) { return visitNodes(elements, visitor, isExpression); } diff --git a/src/compiler/watch.ts b/src/compiler/watch.ts index 89c6f13b102c7..b8d21491a517d 100644 --- a/src/compiler/watch.ts +++ b/src/compiler/watch.ts @@ -173,7 +173,7 @@ function getPlainDiagnosticFollowingNewLines(diagnostic: Diagnostic, newLine: st * * @internal */ -export function getLocaleTimeString(system: System) { +export function getLocaleTimeString(system: System): string { return !system.now ? new Date().toLocaleTimeString() : // On some systems / builds of Node, there's a non-breaking space between the time and AM/PM. @@ -225,7 +225,7 @@ export function parseConfigFileWithSystem(configFileName: string, optionsToExten } /** @internal */ -export function getErrorCountForSummary(diagnostics: readonly Diagnostic[]) { +export function getErrorCountForSummary(diagnostics: readonly Diagnostic[]): number { return countWhere(diagnostics, diagnostic => diagnostic.category === DiagnosticCategory.Error); } @@ -256,7 +256,7 @@ export function getFilesInErrorForSummary(diagnostics: readonly Diagnostic[]): ( } /** @internal */ -export function getWatchErrorSummaryDiagnosticMessage(errorCount: number) { +export function getWatchErrorSummaryDiagnosticMessage(errorCount: number): DiagnosticMessage { return errorCount === 1 ? Diagnostics.Found_1_error_Watching_for_file_changes : Diagnostics.Found_0_errors_Watching_for_file_changes; @@ -277,7 +277,7 @@ export function getErrorSummaryText( filesInError: readonly (ReportFileInError | undefined)[], newLine: string, host: HasCurrentDirectory, -) { +): string { if (errorCount === 0) return ""; const nonNilFiles = filesInError.filter(fileInError => fileInError !== undefined); const distinctFileNamesWithLines = nonNilFiles.map(fileInError => `${fileInError.fileName}:${fileInError.line}`) @@ -347,7 +347,7 @@ function listFiles(program: Program | T, write: (s: st } /** @internal */ -export function explainFiles(program: Program, write: (s: string) => void) { +export function explainFiles(program: Program, write: (s: string) => void): void { const reasons = program.getFileIncludeReasons(); const relativeFileName = (fileName: string) => convertToRelativePath(fileName, program.getCurrentDirectory(), program.getCanonicalFileName); for (const file of program.getSourceFiles()) { @@ -412,7 +412,7 @@ export function explainIfFileIsRedirectAndImpliedFormat( } /** @internal */ -export function getMatchedFileSpec(program: Program, fileName: string) { +export function getMatchedFileSpec(program: Program, fileName: string): string | undefined { const configFile = program.getCompilerOptions().configFile; if (!configFile?.configFileSpecs?.validatedFilesSpec) return undefined; @@ -423,7 +423,7 @@ export function getMatchedFileSpec(program: Program, fileName: string) { } /** @internal */ -export function getMatchedIncludeSpec(program: Program, fileName: string) { +export function getMatchedIncludeSpec(program: Program, fileName: string): string | true | undefined { const configFile = program.getCompilerOptions().configFile; if (!configFile?.configFileSpecs?.validatedIncludeSpecs) return undefined; @@ -639,7 +639,7 @@ export function emitFilesAndReportErrorsAndGetExitStatus noopFileWatcher; +export const returnNoopFileWatcher = (): FileWatcher => noopFileWatcher; /** @internal */ -export function createWatchHost(system = sys, reportWatchStatus?: WatchStatusReporter): WatchHost { +export function createWatchHost(system: System = sys, reportWatchStatus?: WatchStatusReporter): WatchHost { const onWatchStatusChange = reportWatchStatus || createWatchStatusReporter(system); return { onWatchStatusChange, @@ -741,7 +741,7 @@ export interface WatchFactoryWithLog extends WatchFactory(host: WatchFactoryHost & { trace?(s: string): void; }, options: { extendedDiagnostics?: boolean; diagnostics?: boolean; }) { +export function createWatchFactory(host: WatchFactoryHost & { trace?(s: string): void; }, options: { extendedDiagnostics?: boolean; diagnostics?: boolean; }): WatchFactoryWithLog { 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; @@ -784,7 +784,7 @@ export function createCompilerHostFromProgramHost(host: ProgramHost, getCom } /** @internal */ -export function getSourceFileVersionAsHashFromText(host: Pick, text: string) { +export function getSourceFileVersionAsHashFromText(host: Pick, text: string): string { // If text can contain the sourceMapUrl ignore sourceMapUrl for calcualting hash if (text.match(sourceMapCommentRegExpDontCareLineStart)) { let lineEnd = text.length; @@ -823,7 +823,7 @@ export function getSourceFileVersionAsHashFromText(host: Pick { const result = originalGetSourceFile.call(compilerHost, ...args); @@ -982,7 +982,7 @@ export interface IncrementalCompilationOptions { system?: System; } /** @internal */ -export function performIncrementalCompilation(input: IncrementalCompilationOptions) { +export function performIncrementalCompilation(input: IncrementalCompilationOptions): ExitStatus.Success | ExitStatus.DiagnosticsPresent_OutputsSkipped | ExitStatus.DiagnosticsPresent_OutputsGenerated { const system = input.system || sys; const host = input.host || (input.host = createIncrementalCompilerHost(input.options, system)); const builderProgram = createIncrementalProgram(input); diff --git a/src/compiler/watchPublic.ts b/src/compiler/watchPublic.ts index 69147b946af34..c511ec228a64c 100644 --- a/src/compiler/watchPublic.ts +++ b/src/compiler/watchPublic.ts @@ -103,7 +103,7 @@ export interface ReadBuildProgramHost { /** @internal */ getBuildInfo?(fileName: string, configFilePath: string | undefined): BuildInfo | undefined; } -export function readBuilderProgram(compilerOptions: CompilerOptions, host: ReadBuildProgramHost) { +export function readBuilderProgram(compilerOptions: CompilerOptions, host: ReadBuildProgramHost): EmitAndSemanticDiagnosticsBuilderProgram | undefined { const buildInfoPath = getTsBuildInfoEmitOutputFilePath(compilerOptions); if (!buildInfoPath) return undefined; let buildInfo; @@ -120,7 +120,7 @@ export function readBuilderProgram(compilerOptions: CompilerOptions, host: ReadB return createBuilderProgramUsingIncrementalBuildInfo(buildInfo, buildInfoPath, host); } -export function createIncrementalCompilerHost(options: CompilerOptions, system = sys): CompilerHost { +export function createIncrementalCompilerHost(options: CompilerOptions, system: System = sys): CompilerHost { const host = createCompilerHostWorker(options, /*setParentNodes*/ undefined, system); host.createHash = maybeBind(system, system.createHash); host.storeSignatureInfo = system.storeSignatureInfo; diff --git a/src/compiler/watchUtilities.ts b/src/compiler/watchUtilities.ts index 793a5b51ee3db..256fc7f174053 100644 --- a/src/compiler/watchUtilities.ts +++ b/src/compiler/watchUtilities.ts @@ -398,7 +398,7 @@ export function updateSharedExtendedConfigFileWatcher( extendedConfigFilesMap: Map>, createExtendedConfigFileWatch: (extendedConfigPath: string, extendedConfigFilePath: Path) => FileWatcher, toPath: (fileName: string) => Path, -) { +): void { const extendedConfigs = arrayToMap(options?.configFile?.extendedSourceFiles || emptyArray, toPath); // remove project from all unrelated watchers extendedConfigFilesMap.forEach((watcher, extendedConfigFilePath) => { @@ -437,7 +437,7 @@ export function updateSharedExtendedConfigFileWatcher( export function clearSharedExtendedConfigFileWatcher( projectPath: T, extendedConfigFilesMap: Map>, -) { +): void { extendedConfigFilesMap.forEach(watcher => { if (watcher.projects.delete(projectPath)) watcher.close(); }); @@ -452,7 +452,7 @@ export function cleanExtendedConfigCache( extendedConfigCache: Map, extendedConfigFilePath: Path, toPath: (fileName: string) => Path, -) { +): void { if (!extendedConfigCache.delete(extendedConfigFilePath)) return; extendedConfigCache.forEach(({ extendedResult }, key) => { if (extendedResult.extendedSourceFiles?.some(extendedFile => toPath(extendedFile) === extendedConfigFilePath)) { @@ -470,7 +470,7 @@ export function updateMissingFilePathsWatch( program: Program, missingFileWatches: Map, createMissingFileWatch: (missingFilePath: Path, missingFileName: string) => FileWatcher, -) { +): void { // Update the missing file paths watcher mutateMap( missingFileWatches, @@ -503,7 +503,7 @@ export function updateWatchingWildcardDirectories( existingWatchedForWildcards: Map>, wildcardDirectories: MapLike | undefined, watchDirectory: (directory: string, flags: WatchDirectoryFlags) => T, -) { +): void { if (wildcardDirectories) { mutateMap( existingWatchedForWildcards, @@ -653,7 +653,7 @@ export function isIgnoredFileFromWildCardWatching({ } /** @internal */ -export function isEmittedFileOfProgram(program: Program | undefined, file: string) { +export function isEmittedFileOfProgram(program: Program | undefined, file: string): boolean { if (!program) { return false; } @@ -830,6 +830,6 @@ export function getFallbackOptions(options: WatchOptions | undefined): WatchOpti } /** @internal */ -export function closeFileWatcherOf(objWithWatcher: T) { +export function closeFileWatcherOf(objWithWatcher: T): void { objWithWatcher.watcher.close(); } From 6e50be81d8f529e3320801a1508dde29f2f4fee1 Mon Sep 17 00:00:00 2001 From: Isabel Duan Date: Mon, 12 Aug 2024 20:03:15 -0700 Subject: [PATCH 03/27] update generate diagnostic messages script to provide type for DiagnosticMessages --- scripts/processDiagnosticMessages.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/processDiagnosticMessages.mjs b/scripts/processDiagnosticMessages.mjs index b3f398b802c18..35e1e8f4bb149 100644 --- a/scripts/processDiagnosticMessages.mjs +++ b/scripts/processDiagnosticMessages.mjs @@ -101,7 +101,7 @@ function buildInfoFileOutput(messageTable, inputFilePathRel) { 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(` ${propName}: diag(${code}, DiagnosticCategory.${category}, "${createKey(propName, code)}", ${JSON.stringify(name)}${argReportsUnnecessary}${argElidedInCompatabilityPyramid}${argReportsDeprecated}) as DiagnosticMessage,`); }); result.push("};"); From 6a6c1f91e5006924c20b09ec8c0f914f6f8248c1 Mon Sep 17 00:00:00 2001 From: Isabel Duan Date: Mon, 12 Aug 2024 21:04:38 -0700 Subject: [PATCH 04/27] update ScriptTarget and LanguageFeatureMinimumTarget enums --- src/compiler/types.ts | 87 ++++++++++++++++++++++++++----------------- 1 file changed, 53 insertions(+), 34 deletions(-) diff --git a/src/compiler/types.ts b/src/compiler/types.ts index be578eeacf8d9..2d23578b3d47d 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -7541,6 +7541,7 @@ export const enum ScriptKind { // NOTE: We must reevaluate the target for upcoming features when each successive TC39 edition is ratified in // June of each year. This includes changes to `LanguageFeatureMinimumTarget`, `ScriptTarget`, // transformers/esnext.ts, commandLineParser.ts, and the contents of each lib/esnext.*.d.ts file. +// IF UPDATING 'ScriptTarget', ALSO UPDATE 'LanguageFeatureMinimumTarget' (if needed) export const enum ScriptTarget { /** @deprecated */ ES3 = 0, @@ -8306,62 +8307,80 @@ export type EmitHelperUniqueNameCallback = (name: string) => string; * @internal */ export const enum LanguageFeatureMinimumTarget { + // These are copied from 'ScriptTarget' since under isolatedDeclarations, enums cannot have references to external symbols. + // Make sure these are updated alongside any changes to 'ScriptTarget'. + /**@deprecated */ + ES3 = 0, + ES5 = 1, + ES2015 = 2, + ES2016 = 3, + ES2017 = 4, + ES2018 = 5, + ES2019 = 6, + ES2020 = 7, + ES2021 = 8, + ES2022 = 9, + ES2023 = 10, + ESNext = 99, + JSON = 100, + Latest = ESNext, + // ES2015 Features - Classes = ScriptTarget.ES2015, - ForOf = ScriptTarget.ES2015, - Generators = ScriptTarget.ES2015, - Iteration = ScriptTarget.ES2015, - SpreadElements = ScriptTarget.ES2015, - RestElements = ScriptTarget.ES2015, - TaggedTemplates = ScriptTarget.ES2015, - DestructuringAssignment = ScriptTarget.ES2015, - BindingPatterns = ScriptTarget.ES2015, - ArrowFunctions = ScriptTarget.ES2015, - BlockScopedVariables = ScriptTarget.ES2015, - ObjectAssign = ScriptTarget.ES2015, - RegularExpressionFlagsUnicode = ScriptTarget.ES2015, - RegularExpressionFlagsSticky = ScriptTarget.ES2015, + Classes = ES2015, + ForOf = ES2015, + Generators = ES2015, + Iteration = ES2015, + SpreadElements = ES2015, + RestElements = ES2015, + TaggedTemplates = ES2015, + DestructuringAssignment = ES2015, + BindingPatterns = ES2015, + ArrowFunctions = ES2015, + BlockScopedVariables = ES2015, + ObjectAssign = ES2015, + RegularExpressionFlagsUnicode = ES2015, + RegularExpressionFlagsSticky = ES2015, // ES2016 Features - Exponentiation = ScriptTarget.ES2016, // `x ** y` + Exponentiation = ES2016, // `x ** y` // ES2017 Features - AsyncFunctions = ScriptTarget.ES2017, // `async function f() {}` + AsyncFunctions = ES2017, // `async function f() {}` // ES2018 Features - ForAwaitOf = ScriptTarget.ES2018, // `for await (const x of y)` - AsyncGenerators = ScriptTarget.ES2018, // `async function * f() { }` - AsyncIteration = ScriptTarget.ES2018, // `Symbol.asyncIterator` - ObjectSpreadRest = ScriptTarget.ES2018, // `{ ...obj }` - RegularExpressionFlagsDotAll = ScriptTarget.ES2018, + ForAwaitOf = ES2018, // `for await (const x of y)` + AsyncGenerators = ES2018, // `async function * f() { }` + AsyncIteration = ES2018, // `Symbol.asyncIterator` + ObjectSpreadRest = ES2018, // `{ ...obj }` + RegularExpressionFlagsDotAll = ES2018, // ES2019 Features - BindinglessCatch = ScriptTarget.ES2019, // `try { } catch { }` + BindinglessCatch = ES2019, // `try { } catch { }` // ES2020 Features - BigInt = ScriptTarget.ES2020, // `0n` - NullishCoalesce = ScriptTarget.ES2020, // `a ?? b` - OptionalChaining = ScriptTarget.ES2020, // `a?.b` + BigInt = ES2020, // `0n` + NullishCoalesce = ES2020, // `a ?? b` + OptionalChaining = ES2020, // `a?.b` // ES2021 Features - LogicalAssignment = ScriptTarget.ES2021, // `a ||= b`, `a &&= b`, `a ??= b` + LogicalAssignment = ES2021, // `a ||= b`, `a &&= b`, `a ??= b` // ES2022 Features - TopLevelAwait = ScriptTarget.ES2022, - ClassFields = ScriptTarget.ES2022, - PrivateNamesAndClassStaticBlocks = ScriptTarget.ES2022, // `class C { static {} #x = y, #m() {} }`, `#x in y` - RegularExpressionFlagsHasIndices = ScriptTarget.ES2022, + TopLevelAwait = ES2022, + ClassFields = ES2022, + PrivateNamesAndClassStaticBlocks = ES2022, // `class C { static {} #x = y, #m() {} }`, `#x in y` + RegularExpressionFlagsHasIndices = ES2022, // ES2023 Features - ShebangComments = ScriptTarget.ESNext, + ShebangComments = ESNext, // Upcoming Features // NOTE: We must reevaluate the target for upcoming features when each successive TC39 edition is ratified in // June of each year. This includes changes to `LanguageFeatureMinimumTarget`, `ScriptTarget`, // transformers/esnext.ts, commandLineParser.ts, and the contents of each lib/esnext.*.d.ts file. - UsingAndAwaitUsing = ScriptTarget.ESNext, // `using x = y`, `await using x = y` - ClassAndClassElementDecorators = ScriptTarget.ESNext, // `@dec class C {}`, `class C { @dec m() {} }` - RegularExpressionFlagsUnicodeSets = ScriptTarget.ESNext, + UsingAndAwaitUsing = ESNext, // `using x = y`, `await using x = y` + ClassAndClassElementDecorators = ESNext, // `@dec class C {}`, `class C { @dec m() {} }` + RegularExpressionFlagsUnicodeSets = ESNext, } // dprint-ignore From 6c6c89a5724a27da177fb3024e8ab70e1318cb42 Mon Sep 17 00:00:00 2001 From: Isabel Duan Date: Mon, 12 Aug 2024 21:24:13 -0700 Subject: [PATCH 05/27] generated codefixes on services --- src/deprecatedCompat/deprecate.ts | 2 +- src/jsTyping/jsTyping.ts | 6 +- src/jsTyping/shared.ts | 2 +- src/services/breakpoints.ts | 2 +- src/services/codeFixProvider.ts | 6 +- src/services/codefixes/helpers.ts | 15 +-- src/services/codefixes/importFixes.ts | 2 +- src/services/exportInfoMap.ts | 9 +- src/services/findAllReferences.ts | 2 +- src/services/formatting/formatting.ts | 2 +- src/services/formatting/formattingContext.ts | 6 +- src/services/formatting/smartIndenter.ts | 7 +- src/services/jsDoc.ts | 2 +- src/services/organizeImports.ts | 10 +- src/services/refactorProvider.ts | 2 +- src/services/refactors/convertImport.ts | 2 +- src/services/refactors/extractSymbol.ts | 22 ++-- src/services/refactors/helpers.ts | 4 +- src/services/refactors/moveToFile.ts | 10 +- src/services/services.ts | 4 +- src/services/sourcemaps.ts | 2 +- src/services/stringCompletions.ts | 2 +- src/services/symbolDisplay.ts | 2 +- src/services/textChanges.ts | 14 +-- src/services/types.ts | 2 +- src/services/utilities.ts | 104 +++++++++---------- src/typingsInstallerCore/typingsInstaller.ts | 19 ++-- 27 files changed, 137 insertions(+), 125 deletions(-) diff --git a/src/deprecatedCompat/deprecate.ts b/src/deprecatedCompat/deprecate.ts index 595376a5222d1..634c6e89a58c4 100644 --- a/src/deprecatedCompat/deprecate.ts +++ b/src/deprecatedCompat/deprecate.ts @@ -9,7 +9,7 @@ import { export let enableDeprecationWarnings = true; -export function setEnableDeprecationWarnings(value: boolean) { +export function setEnableDeprecationWarnings(value: boolean): void { enableDeprecationWarnings = value; } diff --git a/src/jsTyping/jsTyping.ts b/src/jsTyping/jsTyping.ts index 48594168e9b80..3aaba439ec081 100644 --- a/src/jsTyping/jsTyping.ts +++ b/src/jsTyping/jsTyping.ts @@ -56,7 +56,7 @@ export interface CachedTyping { } /** @internal */ -export function isTypingUpToDate(cachedTyping: CachedTyping, availableTypingVersions: MapLike) { +export function isTypingUpToDate(cachedTyping: CachedTyping, availableTypingVersions: MapLike): boolean { const availableVersion = new Version(getProperty(availableTypingVersions, `ts${versionMajorMinor}`) || getProperty(availableTypingVersions, "latest")!); return availableVersion.compareTo(cachedTyping.version) <= 0; } @@ -117,10 +117,10 @@ const prefixedNodeCoreModuleList = unprefixedNodeCoreModuleList.map(name => `nod export const nodeCoreModuleList: readonly string[] = [...unprefixedNodeCoreModuleList, ...prefixedNodeCoreModuleList]; /** @internal */ -export const nodeCoreModules = new Set(nodeCoreModuleList); +export const nodeCoreModules: Set = new Set(nodeCoreModuleList); /** @internal */ -export function nonRelativeModuleNameForTypingCache(moduleName: string) { +export function nonRelativeModuleNameForTypingCache(moduleName: string): string { return nodeCoreModules.has(moduleName) ? "node" : moduleName; } diff --git a/src/jsTyping/shared.ts b/src/jsTyping/shared.ts index ddf13a4c9f9d7..9689eebaeda66 100644 --- a/src/jsTyping/shared.ts +++ b/src/jsTyping/shared.ts @@ -45,7 +45,7 @@ export namespace Arguments { } /** @internal */ -export function hasArgument(argumentName: string) { +export function hasArgument(argumentName: string): boolean { return sys.args.includes(argumentName); } diff --git a/src/services/breakpoints.ts b/src/services/breakpoints.ts index 17d20da69ee92..b3e53fed929b5 100644 --- a/src/services/breakpoints.ts +++ b/src/services/breakpoints.ts @@ -77,7 +77,7 @@ import { * * @internal */ -export function spanInSourceFileAtLocation(sourceFile: SourceFile, position: number) { +export function spanInSourceFileAtLocation(sourceFile: SourceFile, position: number): TextSpan | undefined { // Cannot set breakpoint in dts file if (sourceFile.isDeclarationFile) { return undefined; diff --git a/src/services/codeFixProvider.ts b/src/services/codeFixProvider.ts index 686a96dea6c8e..7dbf939b4da05 100644 --- a/src/services/codeFixProvider.ts +++ b/src/services/codeFixProvider.ts @@ -29,7 +29,7 @@ const errorCodeToFixes = createMultiMap(); const fixIdToRegistration = new Map(); /** @internal */ -export function createCodeFixActionWithoutFixAll(fixName: string, changes: FileTextChanges[], description: DiagnosticOrDiagnosticAndArguments) { +export function createCodeFixActionWithoutFixAll(fixName: string, changes: FileTextChanges[], description: DiagnosticOrDiagnosticAndArguments): CodeFixAction { return createCodeFixActionWorker(fixName, diagnosticToString(description), changes, /*fixId*/ undefined, /*fixAllDescription*/ undefined); } @@ -39,7 +39,7 @@ export function createCodeFixAction(fixName: string, changes: FileTextChanges[], } /** @internal */ -export function createCodeFixActionMaybeFixAll(fixName: string, changes: FileTextChanges[], description: DiagnosticOrDiagnosticAndArguments, fixId?: {}, fixAllDescription?: DiagnosticOrDiagnosticAndArguments, command?: CodeActionCommand) { +export function createCodeFixActionMaybeFixAll(fixName: string, changes: FileTextChanges[], description: DiagnosticOrDiagnosticAndArguments, fixId?: {}, fixAllDescription?: DiagnosticOrDiagnosticAndArguments, command?: CodeActionCommand): CodeFixAction { return createCodeFixActionWorker(fixName, diagnosticToString(description), changes, fixId, fixAllDescription && diagnosticToString(fixAllDescription), command); } @@ -48,7 +48,7 @@ function createCodeFixActionWorker(fixName: string, description: string, changes } /** @internal */ -export function registerCodeFix(reg: CodeFixRegistration) { +export function registerCodeFix(reg: CodeFixRegistration): void { for (const error of reg.errorCodes) { errorCodeToFixesArray = undefined; errorCodeToFixes.add(String(error), reg); diff --git a/src/services/codefixes/helpers.ts b/src/services/codefixes/helpers.ts index 0524080520582..7d5782225ed44 100644 --- a/src/services/codefixes/helpers.ts +++ b/src/services/codefixes/helpers.ts @@ -179,7 +179,7 @@ export function addNewNodeForMemberSymbol( importAdder: ImportAdder | undefined, addClassElement: (node: AddNode) => void, body: Block | undefined, - preserveOptional = PreserveOptionalFlags.All, + preserveOptional: PreserveOptionalFlags = PreserveOptionalFlags.All, isAmbient = false, ): void { const declarations = symbol.getDeclarations(); @@ -383,7 +383,7 @@ export function createSignatureDeclarationFromSignature( optional: boolean | undefined, enclosingDeclaration: Node | undefined, importAdder: ImportAdder | undefined, -) { +): FunctionDeclaration | MethodDeclaration | FunctionExpression | ArrowFunction | undefined { const program = context.program; const checker = program.getTypeChecker(); const scriptTarget = getEmitScriptTarget(program.getCompilerOptions()); @@ -845,7 +845,7 @@ export function setJsonCompilerOptionValues( changeTracker: textChanges.ChangeTracker, configFile: TsConfigSourceFile, options: [string, Expression][], -) { +): undefined { const tsconfigObjectLiteral = getTsConfigObjectLiteralExpression(configFile); if (!tsconfigObjectLiteral) return undefined; @@ -884,7 +884,7 @@ export function setJsonCompilerOptionValue( configFile: TsConfigSourceFile, optionName: string, optionValue: Expression, -) { +): void { setJsonCompilerOptionValues(changeTracker, configFile, [[optionName, optionValue]]); } @@ -903,7 +903,10 @@ function findJsonProperty(obj: ObjectLiteralExpression, name: string): PropertyA * * @internal */ -export function tryGetAutoImportableReferenceFromTypeNode(importTypeNode: TypeNode | undefined, scriptTarget: ScriptTarget) { +export function tryGetAutoImportableReferenceFromTypeNode(importTypeNode: TypeNode | undefined, scriptTarget: ScriptTarget): { + typeNode: TypeNode; + symbols: Symbol[]; +} | undefined { let symbols: Symbol[] | undefined; const typeNode = visitNode(importTypeNode, visit, isTypeNode); if (symbols && typeNode) { @@ -941,7 +944,7 @@ function replaceFirstIdentifierOfEntityName(name: EntityName, newIdentifier: Ide } /** @internal */ -export function importSymbols(importAdder: ImportAdder, symbols: readonly Symbol[]) { +export function importSymbols(importAdder: ImportAdder, symbols: readonly Symbol[]): void { symbols.forEach(s => importAdder.addImportFromExportedSymbol(s, /*isValidTypeOnlyUseSite*/ true)); } diff --git a/src/services/codefixes/importFixes.ts b/src/services/codefixes/importFixes.ts index aa5efcee15861..09e9a1f849ebb 100644 --- a/src/services/codefixes/importFixes.ts +++ b/src/services/codefixes/importFixes.ts @@ -841,7 +841,7 @@ 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): CodeAction | undefined { const compilerOptions = program.getCompilerOptions(); const symbolName = single(getSymbolNamesToImport(sourceFile, program.getTypeChecker(), symbolToken, compilerOptions)); const fix = getTypeOnlyPromotionFix(sourceFile, symbolToken, symbolName, program); diff --git a/src/services/exportInfoMap.ts b/src/services/exportInfoMap.ts index 4873d6eac42f0..26ce662787c15 100644 --- a/src/services/exportInfoMap.ts +++ b/src/services/exportInfoMap.ts @@ -422,7 +422,7 @@ export function forEachExternalModuleToImportFrom( preferences: UserPreferences, useAutoImportProvider: boolean, cb: (module: Symbol, moduleFile: SourceFile | undefined, program: Program, isFromPackageJson: boolean) => void, -) { +): void { const useCaseSensitiveFileNames = hostUsesCaseSensitiveFileNames(host); const excludePatterns = preferences.autoImportFileExcludePatterns && getIsExcludedPatterns(preferences, useCaseSensitiveFileNames); @@ -487,7 +487,7 @@ function getIsExcluded(excludePatterns: readonly RegExp[], host: LanguageService } /** @internal */ -export function getIsFileExcluded(host: LanguageServiceHost, preferences: UserPreferences) { +export function getIsFileExcluded(host: LanguageServiceHost, preferences: UserPreferences): ({ fileName, path }: SourceFile) => boolean { if (!preferences.autoImportFileExcludePatterns) return () => false; return getIsExcluded(getIsExcludedPatterns(preferences, hostUsesCaseSensitiveFileNames(host)), host); } @@ -559,7 +559,10 @@ export function getExportInfoMap(importingFile: SourceFile | FutureSourceFile, h } /** @internal */ -export function getDefaultLikeExportInfo(moduleSymbol: Symbol, checker: TypeChecker) { +export function getDefaultLikeExportInfo(moduleSymbol: Symbol, checker: TypeChecker): { + symbol: Symbol; + exportKind: ExportKind; +} | undefined { const exportEquals = checker.resolveExternalModuleSymbol(moduleSymbol); if (exportEquals !== moduleSymbol) return { symbol: exportEquals, exportKind: ExportKind.ExportEquals }; const defaultExport = checker.tryGetMemberInModuleExports(InternalSymbolName.Default, moduleSymbol); diff --git a/src/services/findAllReferences.ts b/src/services/findAllReferences.ts index 6e11dac1419fd..74aeb9c5be05c 100644 --- a/src/services/findAllReferences.ts +++ b/src/services/findAllReferences.ts @@ -1051,7 +1051,7 @@ export namespace Core { return mergeReferences(program, moduleReferences, references, moduleReferencesOfExportTarget); } - export function getAdjustedNode(node: Node, options: Options) { + export function getAdjustedNode(node: Node, options: Options): Node { if (options.use === FindReferencesUse.References) { node = getAdjustedReferenceLocation(node); } diff --git a/src/services/formatting/formatting.ts b/src/services/formatting/formatting.ts index 2dc19c021e302..e641b0f2b0434 100644 --- a/src/services/formatting/formatting.ts +++ b/src/services/formatting/formatting.ts @@ -1377,7 +1377,7 @@ export function getRangeOfEnclosingComment( sourceFile: SourceFile, position: number, precedingToken?: Node | null, // eslint-disable-line no-restricted-syntax - tokenAtPosition = getTokenAtPosition(sourceFile, position), + tokenAtPosition: Node = getTokenAtPosition(sourceFile, position), ): CommentRange | undefined { const jsdoc = findAncestor(tokenAtPosition, isJSDoc); if (jsdoc) tokenAtPosition = jsdoc.parent; diff --git a/src/services/formatting/formattingContext.ts b/src/services/formatting/formattingContext.ts index f41b7ee0ca283..ff73e9c578241 100644 --- a/src/services/formatting/formattingContext.ts +++ b/src/services/formatting/formattingContext.ts @@ -35,7 +35,7 @@ export class FormattingContext { 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): void { this.currentTokenSpan = Debug.checkDefined(currentRange); this.currentTokenParent = Debug.checkDefined(currentTokenParent); this.nextTokenSpan = Debug.checkDefined(nextRange); @@ -76,7 +76,7 @@ export class FormattingContext { return this.tokensAreOnSameLine; } - public ContextNodeBlockIsOnOneLine() { + public ContextNodeBlockIsOnOneLine(): boolean { if (this.contextNodeBlockIsOnOneLine === undefined) { this.contextNodeBlockIsOnOneLine = this.BlockIsOnOneLine(this.contextNode); } @@ -84,7 +84,7 @@ export class FormattingContext { return this.contextNodeBlockIsOnOneLine; } - public NextNodeBlockIsOnOneLine() { + public NextNodeBlockIsOnOneLine(): boolean { if (this.nextNodeBlockIsOnOneLine === undefined) { this.nextNodeBlockIsOnOneLine = this.BlockIsOnOneLine(this.nextTokenParent); } diff --git a/src/services/formatting/smartIndenter.ts b/src/services/formatting/smartIndenter.ts index c2141602f1108..c6ed975a1a516 100644 --- a/src/services/formatting/smartIndenter.ts +++ b/src/services/formatting/smartIndenter.ts @@ -233,7 +233,7 @@ export namespace SmartIndenter { return getIndentationForNodeWorker(n, start, ignoreActualIndentationRange, /*indentationDelta*/ 0, sourceFile, /*isNextChild*/ false, options); } - export function getBaseIndentation(options: EditorSettings) { + export function getBaseIndentation(options: EditorSettings): number { return options.baseIndentSize || 0; } @@ -602,7 +602,10 @@ 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): { + column: number; + character: number; + } { let character = 0; let column = 0; for (let pos = startPos; pos < endPos; pos++) { diff --git a/src/services/jsDoc.ts b/src/services/jsDoc.ts index cbefd89bf8403..0f8cb859d6822 100644 --- a/src/services/jsDoc.ts +++ b/src/services/jsDoc.ts @@ -383,7 +383,7 @@ export function getJSDocTagNameCompletions(): CompletionEntry[] { } /** @internal */ -export const getJSDocTagNameCompletionDetails = getJSDocTagCompletionDetails; +export const getJSDocTagNameCompletionDetails: typeof getJSDocTagCompletionDetails = getJSDocTagCompletionDetails; /** @internal */ export function getJSDocTagCompletions(): CompletionEntry[] { diff --git a/src/services/organizeImports.ts b/src/services/organizeImports.ts index e7cc236947c84..1508ba7672d5e 100644 --- a/src/services/organizeImports.ts +++ b/src/services/organizeImports.ts @@ -914,19 +914,19 @@ export function getNamedImportSpecifierComparerWithDetection(importDecl: ImportD } /** @internal */ -export function getImportDeclarationInsertionIndex(sortedImports: readonly AnyImportOrRequireStatement[], newImport: AnyImportOrRequireStatement, comparer: Comparer) { +export function getImportDeclarationInsertionIndex(sortedImports: readonly AnyImportOrRequireStatement[], newImport: AnyImportOrRequireStatement, comparer: Comparer): number { 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) { +export function getImportSpecifierInsertionIndex(sortedImports: readonly ImportSpecifier[], newImport: ImportSpecifier, comparer: Comparer): number { const index = binarySearch(sortedImports, newImport, identity, comparer); return index < 0 ? ~index : index; } /** @internal */ -export function compareImportsOrRequireStatements(s1: AnyImportOrRequireStatement, s2: AnyImportOrRequireStatement, comparer: Comparer) { +export function compareImportsOrRequireStatements(s1: AnyImportOrRequireStatement, s2: AnyImportOrRequireStatement, comparer: Comparer): Comparison { return compareModuleSpecifiersWorker(getModuleSpecifierExpression(s1), getModuleSpecifierExpression(s2), comparer) || compareImportKind(s1, s2); } @@ -950,7 +950,7 @@ export function testCoalesceImports(importGroup: readonly ImportDeclaration[], i * @deprecated Only used for testing * @internal */ -export function testCoalesceExports(exportGroup: readonly ExportDeclaration[], ignoreCase: boolean, preferences?: UserPreferences) { +export function testCoalesceExports(exportGroup: readonly ExportDeclaration[], ignoreCase: boolean, preferences?: UserPreferences): readonly ExportDeclaration[] { const comparer = (s1: ExportSpecifier, s2: ExportSpecifier) => compareImportOrExportSpecifiers(s1, s2, getOrganizeImportsOrdinalStringComparer(ignoreCase), { organizeImportsTypeOrder: preferences?.organizeImportsTypeOrder ?? "last" }); return coalesceExportsWorker(exportGroup, comparer); } @@ -959,7 +959,7 @@ export function testCoalesceExports(exportGroup: readonly ExportDeclaration[], i * @deprecated Only used for testing * @internal */ -export function compareModuleSpecifiers(m1: Expression | undefined, m2: Expression | undefined, ignoreCase?: boolean) { +export function compareModuleSpecifiers(m1: Expression | undefined, m2: Expression | undefined, ignoreCase?: boolean): Comparison { const comparer = getOrganizeImportsOrdinalStringComparer(!!ignoreCase); return compareModuleSpecifiersWorker(m1, m2, comparer); } diff --git a/src/services/refactorProvider.ts b/src/services/refactorProvider.ts index 1b21149070931..b341d18124404 100644 --- a/src/services/refactorProvider.ts +++ b/src/services/refactorProvider.ts @@ -18,7 +18,7 @@ const refactors = new Map(); * * @internal */ -export function registerRefactor(name: string, refactor: Refactor) { +export function registerRefactor(name: string, refactor: Refactor): void { refactors.set(name, refactor); } diff --git a/src/services/refactors/convertImport.ts b/src/services/refactors/convertImport.ts index b0071598b3bb7..1b21d2d5beb02 100644 --- a/src/services/refactors/convertImport.ts +++ b/src/services/refactors/convertImport.ts @@ -210,7 +210,7 @@ function getLeftOfPropertyAccessOrQualifiedName(propertyAccessOrQualifiedName: P } /** @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: boolean = getShouldUseDefault(program, toConvert.parent)): void { const checker = program.getTypeChecker(); const importDecl = toConvert.parent.parent; const { moduleSpecifier } = importDecl; diff --git a/src/services/refactors/extractSymbol.ts b/src/services/refactors/extractSymbol.ts index d5ebc4e3c040d..b87f85e5ecaea 100644 --- a/src/services/refactors/extractSymbol.ts +++ b/src/services/refactors/extractSymbol.ts @@ -386,17 +386,17 @@ export namespace Messages { 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 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 typeWillNotBeVisibleInTheNewScope: DiagnosticMessage = createMessage("Type will not visible in the new scope."); + export const functionWillNotBeVisibleInTheNewScope: DiagnosticMessage = createMessage("Function will not visible in the new scope."); + export const cannotExtractIdentifier: DiagnosticMessage = createMessage("Select more than a single identifier."); + export const cannotExtractExportedEntity: DiagnosticMessage = createMessage("Cannot extract exported declaration"); + export const cannotWriteInExpression: DiagnosticMessage = createMessage("Cannot write back side-effects when extracting an expression"); + export const cannotExtractReadonlyPropertyInitializerOutsideConstructor: DiagnosticMessage = createMessage("Cannot move initialization of read-only class property outside of the constructor"); + export const cannotExtractAmbientBlock: DiagnosticMessage = createMessage("Cannot extract code from ambient contexts"); + export const cannotAccessVariablesFromNestedScopes: DiagnosticMessage = createMessage("Cannot access variables from nested scopes"); + export const cannotExtractToJSClass: DiagnosticMessage = createMessage("Cannot extract constant to a class scope in JS"); + export const cannotExtractToExpressionArrowFunction: DiagnosticMessage = createMessage("Cannot extract constant to an arrow function without a block"); + export const cannotExtractFunctionsContainingThisToMethod: DiagnosticMessage = createMessage("Cannot extract functions containing this to method"); } /** @internal */ diff --git a/src/services/refactors/helpers.ts b/src/services/refactors/helpers.ts index 459979c3ef0dc..38fc8b965f4b9 100644 --- a/src/services/refactors/helpers.ts +++ b/src/services/refactors/helpers.ts @@ -55,7 +55,7 @@ export function refactorKindBeginsWith(known: string, requested: string | undefi * * @internal */ -export function getIdentifierForNode(node: Node, scope: FunctionLikeDeclaration | SourceFile | ModuleBlock | ClassLikeDeclaration, checker: TypeChecker, file: SourceFile) { +export function getIdentifierForNode(node: Node, scope: FunctionLikeDeclaration | SourceFile | ModuleBlock | ClassLikeDeclaration, checker: TypeChecker, file: SourceFile): string { return 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); @@ -69,7 +69,7 @@ export function addTargetFileImports( checker: TypeChecker, program: Program, importAdder: codefix.ImportAdder, -) { +): void { /** * Recomputing the imports is preferred with importAdder because it manages multiple import additions for a file and writes then to a ChangeTracker, * but sometimes it fails because of unresolved imports from files, or when a source file is not available for the target file (in this case when creating a new file). diff --git a/src/services/refactors/moveToFile.ts b/src/services/refactors/moveToFile.ts index da6d806a06f30..2553326a31092 100644 --- a/src/services/refactors/moveToFile.ts +++ b/src/services/refactors/moveToFile.ts @@ -244,7 +244,7 @@ export function getNewStatementsAndRemoveFromOldFile( preferences: UserPreferences, importAdderForNewFile: codefix.ImportAdder, importAdderForOldFile: codefix.ImportAdder, -) { +): void { const checker = program.getTypeChecker(); const prologueDirectives = takeWhile(oldFile.statements, isPrologueDirective); @@ -309,7 +309,7 @@ function deleteUnusedOldImports(oldFile: SourceFile, toMove: readonly Statement[ } /** @internal */ -export function addExportsInOldFile(oldFile: SourceFile, targetFileImportsFromOldFile: Map, changes: textChanges.ChangeTracker, useEsModuleSyntax: boolean) { +export function addExportsInOldFile(oldFile: SourceFile, targetFileImportsFromOldFile: Map, changes: textChanges.ChangeTracker, useEsModuleSyntax: boolean): void { const markSeenTop = nodeSeenTracker(); // Needed because multiple declarations may appear in `const x = 0, y = 1;`. targetFileImportsFromOldFile.forEach((_, symbol) => { if (!symbol.declarations) { @@ -510,7 +510,7 @@ export function addImportsForMovedSymbols( targetFileName: string, importAdder: codefix.ImportAdder, program: Program, -) { +): void { for (const [symbol, isValidTypeOnlyUseSite] of symbols) { const symbolName = getNameForExportedSymbol(symbol, getEmitScriptTarget(program.getCompilerOptions())); const exportKind = symbol.name === "default" && symbol.parent ? ExportKind.Default : ExportKind.Named; @@ -838,7 +838,7 @@ export function getStatementsToMove(context: RefactorContext): ToMove | undefine } /** @internal */ -export function containsJsx(statements: readonly Statement[] | undefined) { +export function containsJsx(statements: readonly Statement[] | undefined): Statement | undefined { return find(statements, statement => !!(statement.transformFlags & TransformFlags.ContainsJsx)); } @@ -1119,7 +1119,7 @@ function getOverloadRangeToMove(sourceFile: SourceFile, statement: Statement) { } /** @internal */ -export function getExistingLocals(sourceFile: SourceFile, statements: readonly Statement[], checker: TypeChecker) { +export function getExistingLocals(sourceFile: SourceFile, statements: readonly Statement[], checker: TypeChecker): Set { const existingLocals = new Set(); for (const moduleSpecifier of sourceFile.imports) { const declaration = importFromModuleSpecifier(moduleSpecifier); diff --git a/src/services/services.ts b/src/services/services.ts index f20e99cc88c0a..e215543e3546b 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -1363,7 +1363,7 @@ function isCamelCase(s: string) { return !s.length || s.charAt(0) === s.charAt(0).toLowerCase(); } -export function displayPartsToString(displayParts: SymbolDisplayPart[] | undefined) { +export function displayPartsToString(displayParts: SymbolDisplayPart[] | undefined): string { if (displayParts) { return map(displayParts, displayPart => displayPart.text).join(""); } @@ -1379,7 +1379,7 @@ export function getDefaultCompilerOptions(): CompilerOptions { }; } -export function getSupportedCodeFixes() { +export function getSupportedCodeFixes(): readonly string[] { return codefix.getSupportedErrorCodes(); } diff --git a/src/services/sourcemaps.ts b/src/services/sourcemaps.ts index dffc7f51ea8e4..85cf595924869 100644 --- a/src/services/sourcemaps.ts +++ b/src/services/sourcemaps.ts @@ -183,7 +183,7 @@ export function getDocumentPositionMapper( generatedFileName: string, generatedFileLineInfo: LineInfo, readMapFile: ReadMapFile, -) { +): DocumentPositionMapper | undefined { let mapFileName = tryGetSourceMappingURL(generatedFileLineInfo); if (mapFileName) { const match = base64UrlRegExp.exec(mapFileName); diff --git a/src/services/stringCompletions.ts b/src/services/stringCompletions.ts index a26959d57f2dc..93c72925b691e 100644 --- a/src/services/stringCompletions.ts +++ b/src/services/stringCompletions.ts @@ -299,7 +299,7 @@ function convertStringLiteralCompletions( } /** @internal */ -export function getStringLiteralCompletionDetails(name: string, sourceFile: SourceFile, position: number, contextToken: Node | undefined, program: Program, host: LanguageServiceHost, cancellationToken: CancellationToken, preferences: UserPreferences) { +export function getStringLiteralCompletionDetails(name: string, sourceFile: SourceFile, position: number, contextToken: Node | undefined, program: Program, host: LanguageServiceHost, cancellationToken: CancellationToken, preferences: UserPreferences): CompletionEntryDetails | undefined { if (!contextToken || !isStringLiteralLike(contextToken)) return undefined; const completions = getStringLiteralCompletionEntries(sourceFile, contextToken, position, program, host, preferences); return completions && stringLiteralCompletionDetails(name, contextToken, completions, sourceFile, program.getTypeChecker(), cancellationToken); diff --git a/src/services/symbolDisplay.ts b/src/services/symbolDisplay.ts index 5ba8170b17b32..adcd705ff59c0 100644 --- a/src/services/symbolDisplay.ts +++ b/src/services/symbolDisplay.ts @@ -866,7 +866,7 @@ 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 { +export function getSymbolDisplayPartsDocumentationAndSymbolKind(typeChecker: TypeChecker, symbol: Symbol, sourceFile: SourceFile, enclosingDeclaration: Node | undefined, location: Node, semanticMeaning: SemanticMeaning = getMeaningFromLocation(location), alias?: Symbol): SymbolDisplayPartsDocumentationAndSymbolKind { return getSymbolDisplayPartsDocumentationAndSymbolKindWorker(typeChecker, symbol, sourceFile, enclosingDeclaration, location, /*type*/ undefined, semanticMeaning, alias); } diff --git a/src/services/textChanges.ts b/src/services/textChanges.ts index b02caba811bc0..e73da8490b683 100644 --- a/src/services/textChanges.ts +++ b/src/services/textChanges.ts @@ -509,7 +509,7 @@ export class ChangeTracker { /** Public for tests only. Other callers should use `ChangeTracker.with`. */ constructor(private readonly newLineCharacter: string, private readonly formatContext: formatting.FormatContext) {} - public pushRaw(sourceFile: SourceFile, change: FileTextChanges) { + public pushRaw(sourceFile: SourceFile, change: FileTextChanges): void { Debug.assertEqual(sourceFile.fileName, change.fileName); for (const c of change.textChanges) { this.changes.push({ @@ -534,7 +534,7 @@ export class ChangeTracker { 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 | undefined = { 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); @@ -724,7 +724,7 @@ export class ChangeTracker { factory.createNodeArray(intersperse(comments, factory.createJSDocText("\n"))); } - public replaceJSDocComment(sourceFile: SourceFile, node: HasJSDoc, tags: readonly JSDocTag[]) { + public replaceJSDocComment(sourceFile: SourceFile, node: HasJSDoc, tags: readonly JSDocTag[]): void { this.insertJsdocCommentBefore(sourceFile, updateJSDocHost(node), factory.createJSDocComment(this.createJSDocText(sourceFile, node), factory.createNodeArray(tags))); } @@ -1011,7 +1011,7 @@ 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): void { const prevSpecifier = namedImports.elements[index - 1]; if (prevSpecifier) { this.insertNodeInListAfter(sourceFile, prevSpecifier, importSpecifier); @@ -1031,7 +1031,7 @@ 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: NodeArray | undefined = formatting.SmartIndenter.getContainingList(after, sourceFile)): void { if (!containingList) { Debug.fail("node is not a list element"); return; @@ -1121,7 +1121,7 @@ export class ChangeTracker { } } - public parenthesizeExpression(sourceFile: SourceFile, expression: Expression) { + public parenthesizeExpression(sourceFile: SourceFile, expression: Expression): void { this.replaceRange(sourceFile, rangeOfNode(expression), factory.createParenthesizedExpression(expression)); } @@ -1659,7 +1659,7 @@ function getInsertionPositionAtSourceFileTop(sourceFile: SourceFile): number { } /** @internal */ -export function isValidLocationToAddComment(sourceFile: SourceFile, position: number) { +export function isValidLocationToAddComment(sourceFile: SourceFile, position: number): boolean { return !isInComment(sourceFile, position) && !isInString(sourceFile, position) && !isInTemplateString(sourceFile, position) && !isInJSXText(sourceFile, position); } diff --git a/src/services/types.ts b/src/services/types.ts index 10befea4c5386..30e4ee715d2af 100644 --- a/src/services/types.ts +++ b/src/services/types.ts @@ -1232,7 +1232,7 @@ export function getDefaultFormatCodeSettings(newLineCharacter?: string): FormatC } /** @internal */ -export const testFormatSettings = getDefaultFormatCodeSettings("\n"); +export const testFormatSettings: FormatCodeSettings = getDefaultFormatCodeSettings("\n"); export interface DefinitionInfo extends DocumentSpan { kind: ScriptElementKind; diff --git a/src/services/utilities.ts b/src/services/utilities.ts index 55ab684196e3c..c3303b53f4e8e 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -523,7 +523,7 @@ function getMeaningFromRightHandSideOfImportEquals(node: Node): SemanticMeaning } /** @internal */ -export function isInRightSideOfInternalImportEqualsDeclaration(node: Node) { +export function isInRightSideOfInternalImportEqualsDeclaration(node: Node): boolean { while (node.parent.kind === SyntaxKind.QualifiedName) { node = node.parent; } @@ -643,7 +643,7 @@ function isCalleeWorker token.getStart(sourceFile); } /** @internal */ -export function isInJSXText(sourceFile: SourceFile, position: number) { +export function isInJSXText(sourceFile: SourceFile, position: number): boolean { const token = getTokenAtPosition(sourceFile, position); if (isJsxText(token)) { return true; @@ -1965,7 +1965,7 @@ 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): Node | undefined { const closeTokenText = tokenToString(token.kind)!; const matchingTokenText = tokenToString(matchingTokenKind); const tokenFullStart = token.getFullStart(); @@ -2169,7 +2169,7 @@ function nodeHasTokens(n: Node, sourceFile: SourceFileLike): boolean { } /** @internal */ -export function getNodeModifiers(node: Node, excludeFlags = ModifierFlags.None): string { +export function getNodeModifiers(node: Node, excludeFlags: ModifierFlags = ModifierFlags.None): string { const result: string[] = []; const flags = isDeclaration(node) ? getCombinedNodeFlagsAlwaysIncludeJSDoc(node) & ~excludeFlags @@ -2223,7 +2223,7 @@ function areIntersectedTypesAvoidingStringReduction(checker: TypeChecker, t1: Ty } /** @internal */ -export function isStringAndEmptyAnonymousObjectIntersection(type: Type) { +export function isStringAndEmptyAnonymousObjectIntersection(type: Type): boolean { if (!type.isIntersection()) { return false; } @@ -2240,7 +2240,7 @@ export function isInsideTemplateLiteral(node: TemplateLiteralToken, position: nu } /** @internal */ -export function isAccessibilityModifier(kind: SyntaxKind) { +export function isAccessibilityModifier(kind: SyntaxKind): boolean { switch (kind) { case SyntaxKind.PublicKeyword: case SyntaxKind.PrivateKeyword: @@ -2259,7 +2259,7 @@ export function cloneCompilerOptions(options: CompilerOptions): CompilerOptions } /** @internal */ -export function isArrayLiteralOrObjectLiteralDestructuringPattern(node: Node) { +export function isArrayLiteralOrObjectLiteralDestructuringPattern(node: Node): boolean { if ( node.kind === SyntaxKind.ArrayLiteralExpression || node.kind === SyntaxKind.ObjectLiteralExpression @@ -2311,7 +2311,7 @@ function isInReferenceCommentWorker(sourceFile: SourceFile, position: number, sh } /** @internal */ -export function getReplacementSpanForContextToken(contextToken: Node | undefined, position: number) { +export function getReplacementSpanForContextToken(contextToken: Node | undefined, position: number): TextSpan | undefined { if (!contextToken) return undefined; switch (contextToken.kind) { @@ -2329,7 +2329,7 @@ export function createTextSpanFromNode(node: Node, sourceFile?: SourceFile, endN } /** @internal */ -export function createTextSpanFromStringLiteralLikeContent(node: StringLiteralLike, position: number) { +export function createTextSpanFromStringLiteralLikeContent(node: StringLiteralLike, position: number): TextSpan | undefined { let replacementEnd = node.getEnd() - 1; if (node.isUnterminated) { // we return no replacement range only if unterminated string is empty @@ -2398,7 +2398,7 @@ function isTypeKeywordToken(node: Node): node is Token { } /** @internal */ -export function isTypeKeywordTokenOrIdentifier(node: Node) { +export function isTypeKeywordTokenOrIdentifier(node: Node): boolean { return isTypeKeywordToken(node) || isIdentifier(node) && node.text === "type"; } @@ -2770,7 +2770,7 @@ export function getMappedContextSpan(documentSpan: DocumentSpan, sourceMapper: S // Display-part writer helpers // #region /** @internal */ -export function isFirstDeclarationOfSymbolParameter(symbol: Symbol) { +export function isFirstDeclarationOfSymbolParameter(symbol: Symbol): boolean { const declaration = symbol.declarations ? firstOrUndefined(symbol.declarations) : undefined; return !!findAncestor(declaration, n => isParameter(n) ? true : isBindingElement(n) || isObjectBindingPattern(n) || isArrayBindingPattern(n) ? false : "quit"); } @@ -2901,37 +2901,37 @@ export function displayPart(text: string, kind: SymbolDisplayPartKind): SymbolDi } /** @internal */ -export function spacePart() { +export function spacePart(): SymbolDisplayPart { return displayPart(" ", SymbolDisplayPartKind.space); } /** @internal */ -export function keywordPart(kind: SyntaxKind) { +export function keywordPart(kind: SyntaxKind): SymbolDisplayPart { return displayPart(tokenToString(kind)!, SymbolDisplayPartKind.keyword); } /** @internal */ -export function punctuationPart(kind: SyntaxKind) { +export function punctuationPart(kind: SyntaxKind): SymbolDisplayPart { return displayPart(tokenToString(kind)!, SymbolDisplayPartKind.punctuation); } /** @internal */ -export function operatorPart(kind: SyntaxKind) { +export function operatorPart(kind: SyntaxKind): SymbolDisplayPart { return displayPart(tokenToString(kind)!, SymbolDisplayPartKind.operator); } /** @internal */ -export function parameterNamePart(text: string) { +export function parameterNamePart(text: string): SymbolDisplayPart { return displayPart(text, SymbolDisplayPartKind.parameterName); } /** @internal */ -export function propertyNamePart(text: string) { +export function propertyNamePart(text: string): SymbolDisplayPart { return displayPart(text, SymbolDisplayPartKind.propertyName); } /** @internal */ -export function textOrKeywordPart(text: string) { +export function textOrKeywordPart(text: string): SymbolDisplayPart { const kind = stringToToken(text); return kind === undefined ? textPart(text) @@ -2939,17 +2939,17 @@ export function textOrKeywordPart(text: string) { } /** @internal */ -export function textPart(text: string) { +export function textPart(text: string): SymbolDisplayPart { return displayPart(text, SymbolDisplayPartKind.text); } /** @internal */ -export function typeAliasNamePart(text: string) { +export function typeAliasNamePart(text: string): SymbolDisplayPart { return displayPart(text, SymbolDisplayPartKind.aliasName); } /** @internal */ -export function typeParameterNamePart(text: string) { +export function typeParameterNamePart(text: string): SymbolDisplayPart { return displayPart(text, SymbolDisplayPartKind.typeParameterName); } @@ -3038,14 +3038,14 @@ const lineFeed = "\n"; * * @internal */ -export function getNewLineOrDefaultFromHost(host: FormattingHost, formatSettings: FormatCodeSettings | undefined) { +export function getNewLineOrDefaultFromHost(host: FormattingHost, formatSettings: FormatCodeSettings | undefined): string { return formatSettings?.newLineCharacter || host.getNewLine?.() || lineFeed; } /** @internal */ -export function lineBreakPart() { +export function lineBreakPart(): SymbolDisplayPart { return displayPart("\n", SymbolDisplayPartKind.lineBreak); } @@ -3113,12 +3113,12 @@ function isAliasSymbol(symbol: Symbol): boolean { } /** @internal */ -export function getUniqueSymbolId(symbol: Symbol, checker: TypeChecker) { +export function getUniqueSymbolId(symbol: Symbol, checker: TypeChecker): number { return getSymbolId(skipAlias(symbol, checker)); } /** @internal */ -export function getFirstNonSpaceCharacterPosition(text: string, position: number) { +export function getFirstNonSpaceCharacterPosition(text: string, position: number): number { while (isWhiteSpaceLike(text.charCodeAt(position))) { position += 1; } @@ -3126,7 +3126,7 @@ export function getFirstNonSpaceCharacterPosition(text: string, position: number } /** @internal */ -export function getPrecedingNonSpaceCharacterPosition(text: string, position: number) { +export function getPrecedingNonSpaceCharacterPosition(text: string, position: number): number { while (position > -1 && isWhiteSpaceSingleLine(text.charCodeAt(position))) { position -= 1; } @@ -3217,7 +3217,7 @@ export function getSynthesizedDeepClonesWithReplacements( * * @internal */ -export function suppressLeadingAndTrailingTrivia(node: Node) { +export function suppressLeadingAndTrailingTrivia(node: Node): void { suppressLeadingTrivia(node); suppressTrailingTrivia(node); } @@ -3227,7 +3227,7 @@ export function suppressLeadingAndTrailingTrivia(node: Node) { * * @internal */ -export function suppressLeadingTrivia(node: Node) { +export function suppressLeadingTrivia(node: Node): void { addEmitFlagsRecursively(node, EmitFlags.NoLeadingComments, getFirstChild); } @@ -3236,12 +3236,12 @@ export function suppressLeadingTrivia(node: Node) { * * @internal @knipignore */ -export function suppressTrailingTrivia(node: Node) { +export function suppressTrailingTrivia(node: Node): void { addEmitFlagsRecursively(node, EmitFlags.NoTrailingComments, getLastChild); } /** @internal */ -export function copyComments(sourceNode: Node, targetNode: Node) { +export function copyComments(sourceNode: Node, targetNode: Node): void { const sourceFile = sourceNode.getSourceFile(); const text = sourceFile.text; if (hasLeadingLineBreak(sourceNode, text)) { @@ -3315,12 +3315,12 @@ export function getRenameLocation(edits: readonly FileTextChanges[], renameFilen } /** @internal */ -export function copyLeadingComments(sourceNode: Node, targetNode: Node, sourceFile: SourceFile, commentKind?: CommentKind, hasTrailingNewLine?: boolean) { +export function copyLeadingComments(sourceNode: Node, targetNode: Node, sourceFile: SourceFile, commentKind?: CommentKind, hasTrailingNewLine?: boolean): void { 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) { +export function copyTrailingComments(sourceNode: Node, targetNode: Node, sourceFile: SourceFile, commentKind?: CommentKind, hasTrailingNewLine?: boolean): void { forEachTrailingCommentRange(sourceFile.text, sourceNode.end, getAddCommentsFunction(targetNode, sourceFile, commentKind, hasTrailingNewLine, addSyntheticTrailingComment)); } @@ -3333,7 +3333,7 @@ export function copyTrailingComments(sourceNode: Node, targetNode: Node, sourceF * * @internal */ -export function copyTrailingAsLeadingComments(sourceNode: Node, targetNode: Node, sourceFile: SourceFile, commentKind?: CommentKind, hasTrailingNewLine?: boolean) { +export function copyTrailingAsLeadingComments(sourceNode: Node, targetNode: Node, sourceFile: SourceFile, commentKind?: CommentKind, hasTrailingNewLine?: boolean): void { forEachTrailingCommentRange(sourceFile.text, sourceNode.pos, getAddCommentsFunction(targetNode, sourceFile, commentKind, hasTrailingNewLine, addSyntheticLeadingComment)); } @@ -3995,7 +3995,7 @@ export function firstOrOnly(valueOrArray: T | readonly T[]): T { * instead, which searches for names of re-exported defaults/namespaces in target files. * @internal */ -export function getNameForExportedSymbol(symbol: Symbol, scriptTarget: ScriptTarget | undefined, preferCapitalized?: boolean) { +export function getNameForExportedSymbol(symbol: Symbol, scriptTarget: ScriptTarget | undefined, preferCapitalized?: boolean): string { if (symbol.escapedName === InternalSymbolName.ExportEquals || symbol.escapedName === InternalSymbolName.Default) { // Names for default exports: // - export default foo => foo @@ -4098,7 +4098,7 @@ export function moduleSpecifierToValidIdentifier(moduleSpecifier: string, target * * @internal */ -export function stringContainsAt(haystack: string, needle: string, startIndex: number) { +export function stringContainsAt(haystack: string, needle: string, startIndex: number): boolean { const needleLength = needle.length; if (needleLength + startIndex > haystack.length) { return false; @@ -4115,7 +4115,7 @@ export function startsWithUnderscore(name: string): boolean { } /** @internal */ -export function isDeprecatedDeclaration(decl: Declaration) { +export function isDeprecatedDeclaration(decl: Declaration): boolean { return !!(getCombinedNodeFlagsAlwaysIncludeJSDoc(decl) & ModifierFlags.Deprecated); } @@ -4158,12 +4158,12 @@ export function getFormatCodeSettingsForWriting({ options }: formatting.FormatCo } /** @internal */ -export function jsxModeNeedsExplicitImport(jsx: JsxEmit | undefined) { +export function jsxModeNeedsExplicitImport(jsx: JsxEmit | undefined): jsx is JsxEmit.React | JsxEmit.ReactNative { return jsx === JsxEmit.React || jsx === JsxEmit.ReactNative; } /** @internal */ -export function isSourceFileFromLibrary(program: Program, node: SourceFile) { +export function isSourceFileFromLibrary(program: Program, node: SourceFile): boolean { return program.isSourceFileFromExternalLibrary(node) || program.isSourceFileDefaultLibrary(node); } @@ -4239,7 +4239,7 @@ 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): boolean | undefined { const fileName = typeof file === "string" ? file : file.fileName; if (!hasJSFileExtension(fileName)) { return false; diff --git a/src/typingsInstallerCore/typingsInstaller.ts b/src/typingsInstallerCore/typingsInstaller.ts index fe42a37272cc1..ce9c607b83c02 100644 --- a/src/typingsInstallerCore/typingsInstaller.ts +++ b/src/typingsInstallerCore/typingsInstaller.ts @@ -73,7 +73,7 @@ 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): boolean { let hasError = false; for (let remaining = packageNames.length; remaining > 0;) { const result = getNpmCommandForInstallation(npmPath, tsVersion, packageNames, remaining); @@ -84,7 +84,10 @@ 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): { + command: string; + remaining: number; +} { const sliceStart = packageNames.length - remaining; let command: string, toSlice = remaining; while (true) { @@ -126,7 +129,7 @@ export abstract class TypingsInstaller { private readonly safeListPath: Path, private readonly typesMapLocation: Path, private readonly throttleLimit: number, - protected readonly log = nullLog, + protected readonly log: Log = nullLog, ) { const isLoggingEnabled = this.log.isEnabled(); if (isLoggingEnabled) { @@ -136,7 +139,7 @@ export abstract class TypingsInstaller { } /** @internal */ - handleRequest(req: TypingInstallerRequestUnion) { + handleRequest(req: TypingInstallerRequestUnion): void { switch (req.kind) { case "discover": this.install(req); @@ -162,7 +165,7 @@ export abstract class TypingsInstaller { } } - closeProject(req: CloseProject) { + closeProject(req: CloseProject): void { this.closeWatchers(req.projectName); } @@ -186,7 +189,7 @@ export abstract class TypingsInstaller { } } - install(req: DiscoverTypings) { + install(req: DiscoverTypings): void { if (this.log.isEnabled()) { this.log.writeLine(`Got install request${stringifyIndented(req)}`); } @@ -231,7 +234,7 @@ export abstract class TypingsInstaller { } /** @internal */ - installPackage(req: InstallPackageRequest) { + installPackage(req: InstallPackageRequest): void { const { fileName, packageName, projectName, projectRootPath, id } = req; const cwd = forEachAncestorDirectory(getDirectoryPath(fileName), directory => { if (this.installTypingHost.fileExists(combinePaths(directory, "package.json"))) { @@ -373,7 +376,7 @@ export abstract class TypingsInstaller { }); } - protected ensurePackageDirectoryExists(directory: string) { + protected ensurePackageDirectoryExists(directory: string): void { const npmConfigPath = combinePaths(directory, "package.json"); if (this.log.isEnabled()) { this.log.writeLine(`Npm config file: ${npmConfigPath}`); From 756703880a1ac70362eafd88feee08df55b4f7b5 Mon Sep 17 00:00:00 2001 From: Isabel Duan Date: Mon, 12 Aug 2024 22:00:03 -0700 Subject: [PATCH 06/27] generated codefixes on server --- src/server/editorServices.ts | 130 +++++------ src/server/project.ts | 232 +++++++++---------- src/server/scriptInfo.ts | 52 ++--- src/server/scriptVersionCache.ts | 39 ++-- src/server/session.ts | 14 +- src/server/typingInstallerAdapter.ts | 6 +- src/server/utilities.ts | 6 +- src/server/utilitiesPublic.ts | 2 +- src/tsserver/common.ts | 2 +- src/typingsInstaller/nodeTypingsInstaller.ts | 4 +- 10 files changed, 245 insertions(+), 242 deletions(-) diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index 14427e48b456c..caf6ab7bd5407 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -189,9 +189,9 @@ import { } from "./_namespaces/ts.server.js"; import * as protocol from "./protocol.js"; -export const maxProgramSizeForNonTsFiles = 20 * 1024 * 1024; +export const maxProgramSizeForNonTsFiles: number = 20 * 1024 * 1024; /** @internal */ -export const maxFileSize = 4 * 1024 * 1024; +export const maxFileSize: number = 4 * 1024 * 1024; export const ProjectsUpdatedInBackgroundEvent = "projectsUpdatedInBackground"; export const ProjectLoadingStartEvent = "projectLoadingStart"; @@ -490,7 +490,7 @@ export function tryConvertScriptKindName(scriptKindName: protocol.ScriptKindName return isString(scriptKindName) ? convertScriptKindName(scriptKindName) : scriptKindName; } -export function convertScriptKindName(scriptKindName: protocol.ScriptKindName) { +export function convertScriptKindName(scriptKindName: protocol.ScriptKindName): ScriptKind.Unknown | ScriptKind.JS | ScriptKind.JSX | ScriptKind.TS | ScriptKind.TSX { switch (scriptKindName) { case "JS": return ScriptKind.JS; @@ -986,7 +986,7 @@ function isScriptInfoWatchedFromNodeModules(info: ScriptInfo) { * returns true if project updated with new program * @internal */ -export function updateProjectIfDirty(project: Project) { +export function updateProjectIfDirty(project: Project): boolean { project.invalidateResolutionsOfFailedLookupLocations(); return project.dirty && !project.updateGraph(); } @@ -1195,7 +1195,7 @@ export class ProjectService { * * @internal */ - readonly filenameToScriptInfo = new Map(); + readonly filenameToScriptInfo: Map = new Map(); private readonly nodeModulesWatchers = new Map(); /** * Contains all the deleted script info's version information so that @@ -1230,11 +1230,11 @@ export class ProjectService { */ readonly configuredProjects: Map = new Map(); /** @internal */ - readonly newInferredProjectName = createProjectNameFactoryWithCounter(makeInferredProjectName); + readonly newInferredProjectName: () => string = createProjectNameFactoryWithCounter(makeInferredProjectName); /** @internal */ - readonly newAutoImportProviderProjectName = createProjectNameFactoryWithCounter(makeAutoImportProviderProjectName); + readonly newAutoImportProviderProjectName: () => string = createProjectNameFactoryWithCounter(makeAutoImportProviderProjectName); /** @internal */ - readonly newAuxiliaryProjectName = createProjectNameFactoryWithCounter(makeAuxiliaryProjectName); + readonly newAuxiliaryProjectName: () => string = createProjectNameFactoryWithCounter(makeAuxiliaryProjectName); /** * Open files: with value being project root path, and key being Path of the file that is open */ @@ -1267,7 +1267,7 @@ export class ProjectService { * * @internal */ - readonly configFileExistenceInfoCache = new Map(); + readonly configFileExistenceInfoCache: Map = new Map(); /** @internal */ readonly throttledOperations: ThrottledOperations; private readonly hostConfiguration: HostConfiguration; @@ -1329,7 +1329,7 @@ export class ProjectService { private currentPluginEnablementPromise?: Promise; /** @internal */ baseline: (title?: string) => void = noop; - /** @internal */ verifyDocumentRegistry = noop; + /** @internal */ verifyDocumentRegistry: typeof noop = noop; /** @internal */ verifyProgram: (project: Project) => void = noop; /** @internal */ onProjectCreation: (project: Project) => void = noop; /** @internal */ canUseWatchEvents: boolean; @@ -1406,22 +1406,22 @@ export class ProjectService { opts.incrementalVerifier?.(this); } - toPath(fileName: string) { + toPath(fileName: string): Path { return toPath(fileName, this.currentDirectory, this.toCanonicalFileName); } /** @internal */ - getExecutingFilePath() { + getExecutingFilePath(): string { return this.getNormalizedAbsolutePath(this.host.getExecutingFilePath()); } /** @internal */ - getNormalizedAbsolutePath(fileName: string) { + getNormalizedAbsolutePath(fileName: string): string { return getNormalizedAbsolutePath(fileName, this.host.getCurrentDirectory()); } /** @internal */ - setDocument(key: DocumentRegistryBucketKeyWithMode, path: Path, sourceFile: SourceFile) { + setDocument(key: DocumentRegistryBucketKeyWithMode, path: Path, sourceFile: SourceFile): void { const info = Debug.checkDefined(this.getScriptInfoForPath(path)); info.cacheSourceFile = { key, sourceFile }; } @@ -1433,17 +1433,17 @@ export class ProjectService { } /** @internal */ - ensureInferredProjectsUpToDate_TestOnly() { + ensureInferredProjectsUpToDate_TestOnly(): void { this.ensureProjectStructuresUptoDate(); } /** @internal */ - getCompilerOptionsForInferredProjects() { + getCompilerOptionsForInferredProjects(): CompilerOptions | undefined { return this.compilerOptionsForInferredProjects; } /** @internal */ - onUpdateLanguageServiceStateForProject(project: Project, languageServiceEnabled: boolean) { + onUpdateLanguageServiceStateForProject(project: Project, languageServiceEnabled: boolean): void { if (!this.eventHandler) { return; } @@ -1507,12 +1507,12 @@ export class ProjectService { } /** @internal */ - watchTypingLocations(response: WatchTypingLocations) { + watchTypingLocations(response: WatchTypingLocations): void { this.findProject(response.projectName)?.watchTypingLocations(response.files); } /** @internal */ - delayEnsureProjectForOpenFiles() { + delayEnsureProjectForOpenFiles(): void { if (!this.openFiles.size) return; this.pendingEnsureProjectForOpenFiles = true; this.throttledOperations.schedule(ensureProjectForOpenFileSchedule, /*delay*/ 2500, () => { @@ -1545,12 +1545,12 @@ export class ProjectService { } /** @internal */ - hasPendingProjectUpdate(project: Project) { + hasPendingProjectUpdate(project: Project): boolean { return this.pendingProjectUpdates.has(project.getProjectName()); } /** @internal */ - sendProjectsUpdatedInBackgroundEvent() { + sendProjectsUpdatedInBackgroundEvent(): void { if (!this.eventHandler) { return; } @@ -1565,7 +1565,7 @@ export class ProjectService { } /** @internal */ - sendLargeFileReferencedEvent(file: string, fileSize: number) { + sendLargeFileReferencedEvent(file: string, fileSize: number): void { if (!this.eventHandler) { return; } @@ -1578,7 +1578,7 @@ export class ProjectService { } /** @internal */ - sendProjectLoadingStartEvent(project: ConfiguredProject, reason: string) { + sendProjectLoadingStartEvent(project: ConfiguredProject, reason: string): void { if (!this.eventHandler) { return; } @@ -1591,7 +1591,7 @@ export class ProjectService { } /** @internal */ - sendProjectLoadingFinishEvent(project: ConfiguredProject) { + sendProjectLoadingFinishEvent(project: ConfiguredProject): void { if (!this.eventHandler || !project.sendLoadingProjectFinish) { return; } @@ -1605,14 +1605,14 @@ export class ProjectService { } /** @internal */ - sendPerformanceEvent(kind: PerformanceEvent["kind"], durationMs: number) { + sendPerformanceEvent(kind: PerformanceEvent["kind"], durationMs: number): void { if (this.performanceEventHandler) { this.performanceEventHandler({ kind, durationMs }); } } /** @internal */ - delayUpdateProjectGraphAndEnsureProjectStructureForOpenFiles(project: Project) { + delayUpdateProjectGraphAndEnsureProjectStructureForOpenFiles(project: Project): void { this.delayUpdateProjectGraph(project); this.delayEnsureProjectForOpenFiles(); } @@ -1688,14 +1688,14 @@ export class ProjectService { } /** @internal */ - forEachProject(cb: (project: Project) => void) { + forEachProject(cb: (project: Project) => void): void { this.externalProjects.forEach(cb); this.configuredProjects.forEach(cb); this.inferredProjects.forEach(cb); } /** @internal */ - forEachEnabledProject(cb: (project: Project) => void) { + forEachEnabledProject(cb: (project: Project) => void): void { this.forEachProject(project => { if (!project.isOrphan() && project.languageServiceEnabled) { cb(project); @@ -1746,7 +1746,7 @@ export class ProjectService { (this.logErrorForScriptInfoNotFound(isString(fileNameOrScriptInfo) ? fileNameOrScriptInfo : fileNameOrScriptInfo.fileName), Errors.ThrowNoProject()); } - getScriptInfoEnsuringProjectsUptoDate(uncheckedFileName: string) { + getScriptInfoEnsuringProjectsUptoDate(uncheckedFileName: string): ScriptInfo | undefined { this.ensureProjectStructuresUptoDate(); return this.getScriptInfo(uncheckedFileName); } @@ -1773,7 +1773,7 @@ export class ProjectService { } } - getFormatCodeOptions(file: NormalizedPath) { + getFormatCodeOptions(file: NormalizedPath): FormatCodeSettings { const info = this.getScriptInfoForNormalizedPath(file); return info && info.getFormatCodeSettings() || this.hostConfiguration.formatCodeOptions; } @@ -2123,7 +2123,7 @@ export class ProjectService { } /** @internal */ - assignOrphanScriptInfoToInferredProject(info: ScriptInfo, projectRootPath: NormalizedPath | undefined) { + assignOrphanScriptInfoToInferredProject(info: ScriptInfo, projectRootPath: NormalizedPath | undefined): InferredProject { Debug.assert(info.isOrphan()); const project = this.getOrCreateInferredProjectForProjectRootPathIfEnabled(info, projectRootPath) || this.getOrCreateSingleInferredProjectIfEnabled() || @@ -2327,7 +2327,7 @@ export class ProjectService { } /** @internal */ - releaseParsedConfig(canonicalConfigFilePath: NormalizedPath, forProject: ConfiguredProject) { + releaseParsedConfig(canonicalConfigFilePath: NormalizedPath, forProject: ConfiguredProject): void { const configFileExistenceInfo = this.configFileExistenceInfoCache.get(canonicalConfigFilePath)!; if (!configFileExistenceInfo.config?.projects.delete(forProject.canonicalConfigFilePath)) return; // If there are still projects watching this config file existence and config, there is nothing to do @@ -2365,7 +2365,7 @@ export class ProjectService { * so that we handle the watches and inferred project root data * @internal */ - stopWatchingConfigFilesForScriptInfo(info: ScriptInfo) { + stopWatchingConfigFilesForScriptInfo(info: ScriptInfo): void { if (this.serverMode !== LanguageServiceMode.Semantic) return; const isRootOfInferredProject = this.rootOfInferredProjects.delete(info); const isOpen = info.isScriptOpen(); @@ -2421,7 +2421,7 @@ export class ProjectService { * * @internal */ - startWatchingConfigFilesForInferredProjectRoot(info: ScriptInfo) { + startWatchingConfigFilesForInferredProjectRoot(info: ScriptInfo): void { if (this.serverMode !== LanguageServiceMode.Semantic) return; Debug.assert(info.isScriptOpen()); // Set this file as the root of inferred project @@ -2517,7 +2517,7 @@ export class ProjectService { } /** @internal */ - findDefaultConfiguredProject(info: ScriptInfo) { + findDefaultConfiguredProject(info: ScriptInfo): ConfiguredProject | undefined { return info.isScriptOpen() ? this.tryFindDefaultConfiguredProjectForOpenScriptInfo( info, @@ -2576,7 +2576,7 @@ export class ProjectService { * when findFromCacheOnly is true only looked up in cache instead of hitting disk to figure things out * @internal */ - getConfigFileNameForFile(info: OpenScriptInfoOrClosedOrConfigFileInfo, findFromCacheOnly: boolean) { + getConfigFileNameForFile(info: OpenScriptInfoOrClosedOrConfigFileInfo, findFromCacheOnly: boolean): NormalizedPath | undefined { // If we are using already cached values, look for values from pending update as well const fromCache = this.getConfigFileNameForFileFromCache(info, findFromCacheOnly); if (fromCache !== undefined) return fromCache || undefined; @@ -2735,7 +2735,7 @@ export class ProjectService { } /** @internal */ - createConfiguredProject(configFileName: NormalizedPath, reason: string) { + createConfiguredProject(configFileName: NormalizedPath, reason: string): ConfiguredProject { tracing?.instant(tracing.Phase.Session, "createConfiguredProject", { configFilePath: configFileName }); this.logger.info(`Creating configuration project ${configFileName}`); const canonicalConfigFilePath = asNormalizedPath(this.toCanonicalFileName(configFileName)); @@ -2921,7 +2921,7 @@ export class ProjectService { } /** @internal */ - watchWildcards(configFileName: NormalizedPath, { exists, config }: ConfigFileExistenceInfo, forProject: ConfiguredProject) { + watchWildcards(configFileName: NormalizedPath, { exists, config }: ConfigFileExistenceInfo, forProject: ConfiguredProject): void { config!.projects.set(forProject.canonicalConfigFilePath, true); if (exists) { if (config!.watchedDirectories && !config!.watchedDirectoriesStale) return; @@ -2942,7 +2942,7 @@ export class ProjectService { } /** @internal */ - stopWatchingWildCards(canonicalConfigFilePath: NormalizedPath, forProject: ConfiguredProject) { + stopWatchingWildCards(canonicalConfigFilePath: NormalizedPath, forProject: ConfiguredProject): void { const configFileExistenceInfo = this.configFileExistenceInfoCache.get(canonicalConfigFilePath)!; if ( !configFileExistenceInfo.config || @@ -3048,7 +3048,7 @@ export class ProjectService { * * @internal */ - reloadFileNamesOfConfiguredProject(project: ConfiguredProject) { + reloadFileNamesOfConfiguredProject(project: ConfiguredProject): boolean { const fileNames = this.reloadFileNamesOfParsedConfig(project.getConfigFilePath(), this.configFileExistenceInfoCache.get(project.canonicalConfigFilePath)!.config!); project.updateErrorOnNoInputFiles(fileNames); this.updateNonInferredProjectFiles(project, fileNames.concat(project.getExternalFiles(ProgramUpdateLevel.RootNamesAndUpdate)), fileNamePropertyReader); @@ -3072,7 +3072,7 @@ export class ProjectService { } /** @internal */ - setFileNamesOfAutpImportProviderOrAuxillaryProject(project: AutoImportProviderProject | AuxiliaryProject, fileNames: readonly string[]) { + setFileNamesOfAutpImportProviderOrAuxillaryProject(project: AutoImportProviderProject | AuxiliaryProject, fileNames: readonly string[]): void { this.updateNonInferredProjectFiles(project, fileNames, fileNamePropertyReader); } @@ -3081,7 +3081,7 @@ export class ProjectService { project: ConfiguredProject, reason: string, reloadedProjects: Set, - ) { + ): boolean { if (!tryAddToSet(reloadedProjects, project)) return false; this.clearSemanticCache(project); this.reloadConfiguredProject(project, reloadReason(reason)); @@ -3093,7 +3093,7 @@ export class ProjectService { * * @internal */ - reloadConfiguredProject(project: ConfiguredProject, reason: string) { + reloadConfiguredProject(project: ConfiguredProject, reason: string): void { project.isInitialLoadPending = returnFalse; project.pendingUpdateReason = undefined; project.pendingUpdateLevel = ProgramUpdateLevel.Update; @@ -3118,7 +3118,7 @@ export class ProjectService { } /** @internal */ - sendConfigFileDiagEvent(project: ConfiguredProject, triggerFile: NormalizedPath | undefined, force: boolean) { + sendConfigFileDiagEvent(project: ConfiguredProject, triggerFile: NormalizedPath | undefined, force: boolean): boolean { if (!this.eventHandler || this.suppressDiagnosticEvents) return false; const diagnostics = project.getLanguageService().getCompilerOptionsDiagnostics(); diagnostics.push(...project.getAllProjectErrors()); @@ -3241,7 +3241,7 @@ export class ProjectService { currentDirectory: string, hostToQueryFileExistsOn: DirectoryStructureHost, deferredDeleteOk: boolean, - ) { + ): ScriptInfo | undefined { return this.getOrCreateScriptInfoNotOpenedByClientForNormalizedPath( toNormalizedPath(uncheckedFileName), currentDirectory, @@ -3252,7 +3252,7 @@ export class ProjectService { ); } - getScriptInfo(uncheckedFileName: string) { + getScriptInfo(uncheckedFileName: string): ScriptInfo | undefined { return this.getScriptInfoForNormalizedPath(toNormalizedPath(uncheckedFileName)); } @@ -3500,7 +3500,7 @@ export class ProjectService { scriptKind?: ScriptKind, hasMixedContent?: boolean, hostToQueryFileExistsOn?: { fileExists(path: string): boolean; }, - ) { + ): ScriptInfo | undefined { return this.getOrCreateScriptInfoWorker( fileName, this.currentDirectory, @@ -3569,12 +3569,12 @@ 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) { + getScriptInfoForNormalizedPath(fileName: NormalizedPath): ScriptInfo | undefined { return !isRootedDiskPath(fileName) && this.openFilesWithNonRootedDiskPath.get(this.toCanonicalFileName(fileName)) || this.getScriptInfoForPath(normalizedPathToPath(fileName, this.currentDirectory, this.toCanonicalFileName)); } - getScriptInfoForPath(fileName: Path) { + getScriptInfoForPath(fileName: Path): ScriptInfo | undefined { const info = this.filenameToScriptInfo.get(fileName); return !info || !info.deferredDelete ? info : undefined; } @@ -3747,11 +3747,11 @@ export class ProjectService { } /** @internal */ - setPerformanceEventHandler(performanceEventHandler: PerformanceEventHandler) { + setPerformanceEventHandler(performanceEventHandler: PerformanceEventHandler): void { this.performanceEventHandler = performanceEventHandler; } - setHostConfiguration(args: protocol.ConfigureRequestArguments) { + setHostConfiguration(args: protocol.ConfigureRequestArguments): void { if (args.file) { const info = this.getScriptInfoForNormalizedPath(toNormalizedPath(args.file)); if (info) { @@ -3819,7 +3819,7 @@ export class ProjectService { } /** @internal */ - getWatchOptions(project: Project) { + getWatchOptions(project: Project): WatchOptions | undefined { return this.getWatchOptionsFromProjectWatchOptions(project.getWatchOptions(), project.getCurrentDirectory()); } @@ -3834,7 +3834,7 @@ export class ProjectService { projectOptions || hostWatchOptions; } - closeLog() { + closeLog(): void { this.logger.close(); } @@ -3842,7 +3842,7 @@ export class ProjectService { * This function rebuilds the project for every file opened by the client * This does not reload contents of open files from disk. But we could do that if needed */ - reloadProjects() { + reloadProjects(): void { this.logger.info("reload projects."); // If we want this to also reload open files from disk, we could do that, // but then we need to make sure we arent calling this function @@ -4367,7 +4367,7 @@ export class ProjectService { } /** @internal */ - loadAncestorProjectTree(forProjects?: ReadonlyCollection) { + loadAncestorProjectTree(forProjects?: ReadonlyCollection): void { forProjects ??= new Set( mapDefinedIterator(this.configuredProjects.entries(), ([key, project]) => !project.isInitialLoadPending() ? key : undefined), ); @@ -4508,7 +4508,7 @@ export class ProjectService { toRetainConfiguredProjects: Set | undefined, openFilesWithRetainedConfiguredProject: Set | undefined, externalProjectsRetainingConfiguredProjects: Set | undefined, - ) { + ): Set { const toRemoveConfiguredProjects = new Set(this.configuredProjects.values()); const markOriginalProjectsAsUsed = (project: Project) => { if (project.originalConfiguredProjects && (isConfiguredProject(project) || !project.isOrphan())) { @@ -4763,7 +4763,7 @@ export class ProjectService { } /** @internal */ - applyChangesToFile(scriptInfo: ScriptInfo, changes: Iterable) { + applyChangesToFile(scriptInfo: ScriptInfo, changes: Iterable): void { for (const change of changes) { scriptInfo.editContent(change.span.start, change.span.start + change.span.length, change.newText); } @@ -5017,7 +5017,7 @@ export class ProjectService { } } - hasDeferredExtension() { + hasDeferredExtension(): boolean { for (const extension of this.hostConfiguration.extraFileExtensions!) { // TODO: GH#18217 if (extension.scriptKind === ScriptKind.Deferred) { return true; @@ -5031,7 +5031,7 @@ export class ProjectService { * Performs the initial steps of enabling a plugin by finding and instantiating the module for a plugin either asynchronously or synchronously * @internal */ - requestEnablePlugin(project: Project, pluginConfigEntry: PluginImport, searchPaths: string[]) { + requestEnablePlugin(project: Project, pluginConfigEntry: PluginImport, searchPaths: string[]): void { 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"); return; @@ -5095,12 +5095,12 @@ export class ProjectService { } /** @internal */ - hasNewPluginEnablementRequests() { + hasNewPluginEnablementRequests(): boolean { return !!this.pendingPluginEnablements; } /** @internal */ - hasPendingPluginEnablements() { + hasPendingPluginEnablements(): boolean { return !!this.currentPluginEnablementPromise; } @@ -5109,7 +5109,7 @@ export class ProjectService { * * @internal */ - async waitForPendingPlugins() { + async waitForPendingPlugins(): Promise { while (this.currentPluginEnablementPromise) { await this.currentPluginEnablementPromise; } @@ -5120,7 +5120,7 @@ export class ProjectService { * * @internal */ - enableRequestedPlugins() { + enableRequestedPlugins(): void { if (this.pendingPluginEnablements) { void this.enableRequestedPluginsAsync(); } @@ -5177,7 +5177,7 @@ export class ProjectService { if (sendProjectsUpdatedInBackgroundEvent) this.sendProjectsUpdatedInBackgroundEvent(); } - configurePlugin(args: protocol.ConfigurePluginRequestArguments) { + configurePlugin(args: protocol.ConfigurePluginRequestArguments): void { // For any projects that already have the plugin loaded, configure the plugin this.forEachEnabledProject(project => project.onPluginConfigurationChanged(args.pluginName, args.configuration)); @@ -5288,7 +5288,7 @@ export class ProjectService { } /** @internal */ - getIncompleteCompletionsCache() { + getIncompleteCompletionsCache(): IncompleteCompletionsCache { return this.incompleteCompletionsCache ||= createIncompleteCompletionsCache(); } } diff --git a/src/server/project.ts b/src/server/project.ts index f6408125d9deb..eaf7100ebe840 100644 --- a/src/server/project.ts +++ b/src/server/project.ts @@ -377,7 +377,7 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo * * @internal */ - cachedUnresolvedImportsPerFile = new Map(); + cachedUnresolvedImportsPerFile: Map = new Map(); /** @internal */ lastCachedUnresolvedImportsList: SortedReadonlyArray | undefined; @@ -465,12 +465,12 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo private readonly cancellationToken: ThrottledCancellationToken; - public isNonTsProject() { + public isNonTsProject(): boolean { updateProjectIfDirty(this); return allFilesAreJsOrDts(this); } - public isJsOnlyProject() { + public isJsOnlyProject(): boolean { updateProjectIfDirty(this); return hasOneOrMoreJsAndNoTsFiles(this); } @@ -554,7 +554,7 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo /** @internal */ protected typeAcquisition: TypeAcquisition | undefined; /** @internal */ - createHash = maybeBind(this.projectService.host, this.projectService.host.createHash); + createHash: ((data: string) => string) | undefined = maybeBind(this.projectService.host, this.projectService.host.createHash); /** @internal*/ preferNonRecursiveWatch: boolean | undefined; readonly jsDocParsingMode: JSDocParsingMode | undefined; @@ -643,7 +643,7 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo } /** @internal */ - getGlobalTypingsCacheLocation() { + getGlobalTypingsCacheLocation(): string | undefined { return this.getGlobalCache(); } @@ -663,20 +663,20 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo } // Method of LanguageServiceHost - getCompilationSettings() { + getCompilationSettings(): ts.CompilerOptions { return this.compilerOptions; } // Method to support public API - getCompilerOptions() { + getCompilerOptions(): ts.CompilerOptions { return this.getCompilationSettings(); } - getNewLine() { + getNewLine(): string { return this.projectService.host.newLine; } - getProjectVersion() { + getProjectVersion(): string { return this.projectStateVersion.toString(); } @@ -684,7 +684,7 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo return undefined; } - getScriptFileNames() { + getScriptFileNames(): string[] { if (!this.rootFilesMap.size) { return ts.emptyArray; } @@ -718,12 +718,12 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo return scriptInfo; } - getScriptKind(fileName: string) { + getScriptKind(fileName: string): ts.ScriptKind { const info = this.projectService.getScriptInfoForPath(this.toPath(fileName)); return (info && info.scriptKind)!; // TODO: GH#18217 } - getScriptVersion(filename: string) { + getScriptVersion(filename: string): string { // Don't attach to the project if version is asked const info = this.projectService.getOrCreateScriptInfoNotOpenedByClient( @@ -750,12 +750,12 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo return this.currentDirectory; } - getDefaultLibFileName() { + getDefaultLibFileName(): string { const nodeModuleBinDir = getDirectoryPath(normalizePath(this.projectService.getExecutingFilePath())); return combinePaths(nodeModuleBinDir, getDefaultLibFileName(this.compilerOptions)); } - useCaseSensitiveFileNames() { + useCaseSensitiveFileNames(): boolean { return this.projectService.host.useCaseSensitiveFileNames; } @@ -820,12 +820,12 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo } /** @internal */ - toPath(fileName: string) { + toPath(fileName: string): ts.Path { return toPath(fileName, this.currentDirectory, this.projectService.toCanonicalFileName); } /** @internal */ - watchDirectoryOfFailedLookupLocation(directory: string, cb: DirectoryWatcherCallback, flags: WatchDirectoryFlags) { + watchDirectoryOfFailedLookupLocation(directory: string, cb: DirectoryWatcherCallback, flags: WatchDirectoryFlags): ts.FileWatcher { return this.projectService.watchFactory.watchDirectory( directory, cb, @@ -837,7 +837,7 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo } /** @internal */ - watchAffectingFileLocation(file: string, cb: FileWatcherCallback) { + watchAffectingFileLocation(file: string, cb: FileWatcherCallback): ts.FileWatcher { return this.projectService.watchFactory.watchFile( file, cb, @@ -849,12 +849,12 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo } /** @internal */ - clearInvalidateResolutionOfFailedLookupTimer() { + clearInvalidateResolutionOfFailedLookupTimer(): boolean { return this.projectService.throttledOperations.cancel(`${this.getProjectName()}FailedLookupInvalidation`); } /** @internal */ - scheduleInvalidateResolutionsOfFailedLookupLocations() { + scheduleInvalidateResolutionsOfFailedLookupLocations(): void { this.projectService.throttledOperations.schedule(`${this.getProjectName()}FailedLookupInvalidation`, /*delay*/ 1000, () => { if (this.resolutionCache.invalidateResolutionsOfFailedLookupLocations()) { this.projectService.delayUpdateProjectGraphAndEnsureProjectStructureForOpenFiles(this); @@ -863,7 +863,7 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo } /** @internal */ - invalidateResolutionsOfFailedLookupLocations() { + invalidateResolutionsOfFailedLookupLocations(): void { if ( this.clearInvalidateResolutionOfFailedLookupTimer() && this.resolutionCache.invalidateResolutionsOfFailedLookupLocations() @@ -874,12 +874,12 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo } /** @internal */ - onInvalidatedResolution() { + onInvalidatedResolution(): void { this.projectService.delayUpdateProjectGraphAndEnsureProjectStructureForOpenFiles(this); } /** @internal */ - watchTypeRootsDirectory(directory: string, cb: DirectoryWatcherCallback, flags: WatchDirectoryFlags) { + watchTypeRootsDirectory(directory: string, cb: DirectoryWatcherCallback, flags: WatchDirectoryFlags): ts.FileWatcher { return this.projectService.watchFactory.watchDirectory( directory, cb, @@ -891,38 +891,38 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo } /** @internal */ - hasChangedAutomaticTypeDirectiveNames() { + hasChangedAutomaticTypeDirectiveNames(): boolean { return this.resolutionCache.hasChangedAutomaticTypeDirectiveNames(); } /** @internal */ - onChangedAutomaticTypeDirectiveNames() { + onChangedAutomaticTypeDirectiveNames(): void { this.projectService.delayUpdateProjectGraphAndEnsureProjectStructureForOpenFiles(this); } /** @internal */ - getGlobalCache() { + getGlobalCache(): string | undefined { return this.getTypeAcquisition().enable ? this.projectService.typingsInstaller.globalTypingsCacheLocation : undefined; } /** @internal */ - globalCacheResolutionModuleName = JsTyping.nonRelativeModuleNameForTypingCache; + globalCacheResolutionModuleName: typeof JsTyping.nonRelativeModuleNameForTypingCache = JsTyping.nonRelativeModuleNameForTypingCache; /** @internal */ - fileIsOpen(filePath: Path) { + fileIsOpen(filePath: Path): boolean { return this.projectService.openFiles.has(filePath); } /** @internal */ - writeLog(s: string) { + writeLog(s: string): void { this.projectService.logger.info(s); } - log(s: string) { + log(s: string): void { this.writeLog(s); } - error(s: string) { + error(s: string): void { this.projectService.logger.msg(s, Msg.Err); } @@ -946,7 +946,7 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo return this.projectErrors || emptyArray; } - setProjectErrors(projectErrors: Diagnostic[] | undefined) { + setProjectErrors(projectErrors: Diagnostic[] | undefined): void { this.projectErrors = projectErrors; } @@ -963,7 +963,7 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo } /** @internal */ - clearSourceMapperCache() { + clearSourceMapperCache(): void { this.languageService.clearSourceMapperCache(); } @@ -973,12 +973,12 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo } /** @internal */ - getSourceFileLike(fileName: string) { + getSourceFileLike(fileName: string): ts.SourceFileLike | undefined { return this.projectService.getSourceFileLike(fileName, this); } /** @internal */ - shouldEmitFile(scriptInfo: ScriptInfo | undefined) { + shouldEmitFile(scriptInfo: ScriptInfo | undefined): boolean | undefined { return scriptInfo && !scriptInfo.isDynamicOrHasMixedContent() && !this.program!.isSourceOfProjectReferenceRedirect(scriptInfo.path); @@ -1032,7 +1032,7 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo return { emitSkipped, diagnostics }; } - enableLanguageService() { + enableLanguageService(): void { if (this.languageServiceEnabled || this.projectService.serverMode === LanguageServiceMode.Syntactic) { return; } @@ -1042,7 +1042,7 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo } /** @internal */ - cleanupProgram() { + cleanupProgram(): void { if (this.program) { // Root files are always attached to the project irrespective of program for (const f of this.program.getSourceFiles()) { @@ -1053,7 +1053,7 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo } } - disableLanguageService(lastFileExceededProgramSize?: string) { + disableLanguageService(lastFileExceededProgramSize?: string): void { if (!this.languageServiceEnabled) { return; } @@ -1073,7 +1073,7 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo this.projectService.onUpdateLanguageServiceStateForProject(this, /*languageServiceEnabled*/ false); } - getProjectName() { + getProjectName(): string { return this.projectName; } @@ -1100,7 +1100,7 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo })); } - getSourceFile(path: Path) { + getSourceFile(path: Path): ts.SourceFile | undefined { if (!this.program) { return undefined; } @@ -1113,7 +1113,7 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo return path === options.configFilePath ? options.configFile : this.getSourceFile(path); } - close() { + close(): void { if (this.typingsCache) this.projectService.typingsInstaller.onProjectClosed(this); this.typingsCache = undefined; this.closeWatchingTypingLocations(); @@ -1176,11 +1176,11 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo } } - isClosed() { + isClosed(): boolean { return this.rootFilesMap === undefined; } - hasRoots() { + hasRoots(): boolean { return !!this.rootFilesMap?.size; } @@ -1194,11 +1194,11 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo } /** @internal */ - getRootFilesMap() { + getRootFilesMap(): Map { return this.rootFilesMap; } - getRootScriptInfos() { + getRootScriptInfos(): ts.server.ScriptInfo[] { return arrayFrom(ts.mapDefinedIterator(this.rootFilesMap.values(), value => value.info)); } @@ -1218,7 +1218,7 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo return emptyArray; } - getFileNames(excludeFilesFromExternalLibraries?: boolean, excludeConfigFiles?: boolean) { + getFileNames(excludeFilesFromExternalLibraries?: boolean, excludeConfigFiles?: boolean): ts.server.NormalizedPath[] { if (!this.program) { return []; } @@ -1256,14 +1256,14 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo } /** @internal */ - getFileNamesWithRedirectInfo(includeProjectReferenceRedirectInfo: boolean) { + getFileNamesWithRedirectInfo(includeProjectReferenceRedirectInfo: boolean): ts.server.protocol.FileWithProjectReferenceRedirectInfo[] { return this.getFileNames().map((fileName): protocol.FileWithProjectReferenceRedirectInfo => ({ fileName, isSourceOfProjectReferenceRedirect: includeProjectReferenceRedirectInfo && this.isSourceOfProjectReferenceRedirect(fileName), })); } - hasConfigFile(configFilePath: NormalizedPath) { + hasConfigFile(configFilePath: NormalizedPath): boolean { if (this.program && this.languageServiceEnabled) { const configFile = this.program.getCompilerOptions().configFile; if (configFile) { @@ -1297,12 +1297,12 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo return false; } - isRoot(info: ScriptInfo) { + isRoot(info: ScriptInfo): boolean { return this.rootFilesMap?.get(info.path)?.info === info; } // add a root file to project - addRoot(info: ScriptInfo, fileName?: NormalizedPath) { + addRoot(info: ScriptInfo, fileName?: NormalizedPath): void { Debug.assert(!this.isRoot(info)); this.rootFilesMap.set(info.path, { fileName: fileName || info.fileName, info }); info.attachToProject(this); @@ -1311,13 +1311,13 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo } // add a root file that doesnt exist on host - addMissingFileRoot(fileName: NormalizedPath) { + addMissingFileRoot(fileName: NormalizedPath): void { const path = this.projectService.toPath(fileName); this.rootFilesMap.set(path, { fileName }); this.markAsDirty(); } - removeFile(info: ScriptInfo, fileExists: boolean, detachFromProject: boolean) { + removeFile(info: ScriptInfo, fileExists: boolean, detachFromProject: boolean): void { if (this.isRoot(info)) { this.removeRoot(info); } @@ -1337,12 +1337,12 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo this.markAsDirty(); } - registerFileUpdate(fileName: string) { + registerFileUpdate(fileName: string): void { (this.updatedFileNames || (this.updatedFileNames = new Set())).add(fileName); } /** @internal */ - markFileAsDirty(changedFile: Path) { + markFileAsDirty(changedFile: Path): void { this.markAsDirty(); if (this.exportMapCache && !this.exportMapCache.isEmpty()) { (this.changedFilesForExportMapCache ||= new Set()).add(changedFile); @@ -1350,7 +1350,7 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo } /** @internal */ - markAsDirty() { + markAsDirty(): void { if (!this.dirty) { this.projectStateVersion++; this.dirty = true; @@ -1358,13 +1358,13 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo } /** @internal */ - markAutoImportProviderAsDirty() { + markAutoImportProviderAsDirty(): void { if (!this.autoImportProviderHost) this.autoImportProviderHost = undefined; this.autoImportProviderHost?.markAsDirty(); } /** @internal */ - onAutoImportProviderSettingsChanged() { + onAutoImportProviderSettingsChanged(): void { if (this.autoImportProviderHost === false) { this.autoImportProviderHost = undefined; } @@ -1374,7 +1374,7 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo } /** @internal */ - onPackageJsonChange() { + onPackageJsonChange(): void { this.moduleSpecifierCache.clear(); if (this.autoImportProviderHost) { this.autoImportProviderHost.markAsDirty(); @@ -1382,7 +1382,7 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo } /** @internal */ - onFileAddedOrRemoved(isSymlink: boolean | undefined) { + onFileAddedOrRemoved(isSymlink: boolean | undefined): void { this.hasAddedorRemovedFiles = true; if (isSymlink) { this.hasAddedOrRemovedSymlinks = true; @@ -1390,7 +1390,7 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo } /** @internal */ - onDiscoveredSymlink() { + onDiscoveredSymlink(): void { this.hasAddedOrRemovedSymlinks = true; } @@ -1400,7 +1400,7 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo _oldOptions: CompilerOptions, hasSourceFileByPath: boolean, newSourceFileByResolvedPath: SourceFile | undefined, - ) { + ): void { if ( !newSourceFileByResolvedPath || (oldSourceFile.resolvedPath === oldSourceFile.path && newSourceFileByResolvedPath.resolvedPath !== oldSourceFile.path) @@ -1416,7 +1416,7 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo updateFromProjectInProgress = false; /** @internal */ - updateFromProject() { + updateFromProject(): void { updateProjectIfDirty(this); } @@ -1475,7 +1475,7 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo } /** @internal */ - enqueueInstallTypingsForProject(forceRefresh: boolean) { + enqueueInstallTypingsForProject(forceRefresh: boolean): void { const typeAcquisition = this.getTypeAcquisition(); if (!typeAcquisition || !typeAcquisition.enable || this.projectService.typingsInstaller === nullTypingsInstaller) { @@ -1503,7 +1503,7 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo } /** @internal */ - updateTypingFiles(compilerOptions: CompilerOptions, typeAcquisition: TypeAcquisition, unresolvedImports: SortedReadonlyArray, newTypings: string[]) { + updateTypingFiles(compilerOptions: CompilerOptions, typeAcquisition: TypeAcquisition, unresolvedImports: SortedReadonlyArray, newTypings: string[]): void { this.typingsCache = { compilerOptions, typeAcquisition, @@ -1530,7 +1530,7 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo } /** @internal */ - watchTypingLocations(files: readonly string[] | undefined) { + watchTypingLocations(files: readonly string[] | undefined): void { if (!files) { this.typingWatchers!.isInvoked = false; return; @@ -1791,7 +1791,7 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo } /** @internal */ - sendPerformanceEvent(kind: PerformanceEvent["kind"], durationMs: number) { + sendPerformanceEvent(kind: PerformanceEvent["kind"], durationMs: number): void { this.projectService.sendPerformanceEvent(kind, durationMs); } @@ -1839,7 +1839,7 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo } /** @internal */ - addGeneratedFileWatch(generatedFile: string, sourceFile: string) { + addGeneratedFileWatch(generatedFile: string, sourceFile: string): void { if (this.compilerOptions.outFile) { // Single watcher if (!this.generatedFilesMap) { @@ -1904,11 +1904,11 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo return scriptInfo; } - getScriptInfo(uncheckedFileName: string) { + getScriptInfo(uncheckedFileName: string): ts.server.ScriptInfo | undefined { return this.projectService.getScriptInfo(uncheckedFileName); } - filesToString(writeProjectFileNames: boolean) { + filesToString(writeProjectFileNames: boolean): string { return this.filesToStringWorker(writeProjectFileNames, /*writeFileExplaination*/ true, /*writeFileVersionAndText*/ false); } @@ -1930,7 +1930,7 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo } /** @internal */ - print(writeProjectFileNames: boolean, writeFileExplaination: boolean, writeFileVersionAndText: boolean) { + print(writeProjectFileNames: boolean, writeFileExplaination: boolean, writeFileVersionAndText: boolean): void { this.writeLog(`Project '${this.projectName}' (${ProjectKind[this.projectKind]})`); this.writeLog(this.filesToStringWorker( writeProjectFileNames && this.projectService.logger.hasLevel(LogLevel.verbose), @@ -1944,7 +1944,7 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo this.noDtsResolutionProject?.print(/*writeProjectFileNames*/ false, /*writeFileExplaination*/ false, /*writeFileVersionAndText*/ false); } - setCompilerOptions(compilerOptions: CompilerOptions) { + setCompilerOptions(compilerOptions: CompilerOptions): void { if (compilerOptions) { compilerOptions.allowNonTsExtensions = true; const oldOptions = this.compilerOptions; @@ -1963,7 +1963,7 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo } /** @internal */ - setWatchOptions(watchOptions: WatchOptions | undefined) { + setWatchOptions(watchOptions: WatchOptions | undefined): void { this.watchOptions = watchOptions; } @@ -1978,7 +1978,7 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo } } - getTypeAcquisition() { + getTypeAcquisition(): ts.TypeAcquisition { return this.typeAcquisition || {}; } @@ -2093,12 +2093,12 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo } /** @internal */ - isSourceOfProjectReferenceRedirect(fileName: string) { + isSourceOfProjectReferenceRedirect(fileName: string): boolean { return !!this.program && this.program.isSourceOfProjectReferenceRedirect(fileName); } /** @internal */ - protected getGlobalPluginSearchPaths() { + protected getGlobalPluginSearchPaths(): string[] { // Search any globally-specified probe paths, then our peer node_modules return [ ...this.projectService.pluginProbeLocations, @@ -2137,7 +2137,7 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo } /** @internal */ - enableProxy(pluginModuleFactory: PluginModuleFactory, configEntry: PluginImport) { + enableProxy(pluginModuleFactory: PluginModuleFactory, configEntry: PluginImport): void { try { if (typeof pluginModuleFactory !== "function") { this.projectService.logger.info(`Skipped loading plugin ${configEntry.name} because it did not expose a proper factory function`); @@ -2172,7 +2172,7 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo } /** @internal */ - onPluginConfigurationChanged(pluginName: string, configuration: any) { + onPluginConfigurationChanged(pluginName: string, configuration: any): void { this.plugins.filter(plugin => plugin.name === pluginName).forEach(plugin => { if (plugin.module.onConfigurationChanged) { plugin.module.onConfigurationChanged(configuration); @@ -2181,7 +2181,7 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo } /** Starts a new check for diagnostics. Call this if some file has updated that would cause diagnostics to be changed. */ - refreshDiagnostics() { + refreshDiagnostics(): void { this.projectService.sendProjectsUpdatedInBackgroundEvent(); } @@ -2202,22 +2202,22 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo } /** @internal */ - getPackageJsonCache() { + getPackageJsonCache(): ts.server.PackageJsonCache { return this.projectService.packageJsonCache; } /** @internal */ - getCachedExportInfoMap() { + getCachedExportInfoMap(): ts.ExportInfoMap { return this.exportMapCache ||= createCacheableExportInfoMap(this); } /** @internal */ - clearCachedExportInfoMap() { + clearCachedExportInfoMap(): void { this.exportMapCache?.clear(); } /** @internal */ - getModuleSpecifierCache() { + getModuleSpecifierCache(): ts.ModuleSpecifierCache { return this.moduleSpecifierCache; } @@ -2294,12 +2294,12 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo } /** @internal */ - watchNodeModulesForPackageJsonChanges(directoryPath: string) { + watchNodeModulesForPackageJsonChanges(directoryPath: string): ts.FileWatcher { return this.projectService.watchPackageJsonsInNodeModules(directoryPath, this); } /** @internal */ - getIncompleteCompletionsCache() { + getIncompleteCompletionsCache(): ts.IncompleteCompletionsCache { return this.projectService.getIncompleteCompletionsCache(); } @@ -2317,7 +2317,7 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo } /** @internal */ - runWithTemporaryFileUpdate(rootFile: string, updatedText: string, cb: (updatedProgram: Program, originalProgram: Program | undefined, updatedFile: SourceFile) => void) { + runWithTemporaryFileUpdate(rootFile: string, updatedText: string, cb: (updatedProgram: Program, originalProgram: Program | undefined, updatedFile: SourceFile) => void): void { const originalProgram = this.program; const rootSourceFile = Debug.checkDefined(this.program?.getSourceFile(rootFile), "Expected file to be part of program"); const originalText = Debug.checkDefined(rootSourceFile.getFullText()); @@ -2391,14 +2391,14 @@ function extractUnresolvedImportsFromSourceFile( export class InferredProject extends Project { private _isJsInferredProject = false; - toggleJsInferredProject(isJsInferredProject: boolean) { + toggleJsInferredProject(isJsInferredProject: boolean): void { if (isJsInferredProject !== this._isJsInferredProject) { this._isJsInferredProject = isJsInferredProject; this.setCompilerOptions(); } } - override setCompilerOptions(options?: CompilerOptions) { + override setCompilerOptions(options?: CompilerOptions): void { // Avoid manipulating the given options directly if (!options && !this.getCompilationSettings()) { return; @@ -2456,7 +2456,7 @@ export class InferredProject extends Project { this.enableGlobalPlugins(this.getCompilerOptions()); } - override addRoot(info: ScriptInfo) { + override addRoot(info: ScriptInfo): void { Debug.assert(info.isScriptOpen()); this.projectService.startWatchingConfigFilesForInferredProjectRoot(info); if (!this._isJsInferredProject && info.isJavaScript()) { @@ -2468,7 +2468,7 @@ export class InferredProject extends Project { super.addRoot(info); } - override removeRoot(info: ScriptInfo) { + override removeRoot(info: ScriptInfo): void { this.projectService.stopWatchingConfigFilesForScriptInfo(info); super.removeRoot(info); // Delay toggling to isJsInferredProject = false till we actually need it again @@ -2480,11 +2480,11 @@ export class InferredProject extends Project { } /** @internal */ - override isOrphan() { + override isOrphan(): boolean { return !this.hasRoots(); } - isProjectWithSingleRoot() { + isProjectWithSingleRoot(): boolean { // - 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 @@ -2492,7 +2492,7 @@ export class InferredProject extends Project { this.getRootScriptInfos().length === 1; } - override close() { + override close(): void { forEach(this.getRootScriptInfos(), info => this.projectService.stopWatchingConfigFilesForScriptInfo(info)); super.close(); } @@ -2738,7 +2738,7 @@ export class AutoImportProviderProject extends Project { } /** @internal */ - isEmpty() { + isEmpty(): boolean { return !some(this.rootFileNames); } @@ -2747,7 +2747,7 @@ export class AutoImportProviderProject extends Project { return true; } - override updateGraph() { + override updateGraph(): boolean { let rootFileNames = this.rootFileNames; if (!rootFileNames) { rootFileNames = AutoImportProviderProject.getRootFileNames( @@ -2774,17 +2774,17 @@ export class AutoImportProviderProject extends Project { return; } - override hasRoots() { + override hasRoots(): boolean { return !!this.rootFileNames?.length; } /** @internal */ - override markAsDirty() { + override markAsDirty(): void { this.rootFileNames = undefined; super.markAsDirty(); } - override getScriptFileNames() { + override getScriptFileNames(): string[] { return this.rootFileNames || ts.emptyArray; } @@ -2806,22 +2806,22 @@ export class AutoImportProviderProject extends Project { throw new Error("AutoImportProviderProject cannot provide its own host; use `hostProject.getModuleResolutionHostForAutomImportProvider()` instead."); } - override getProjectReferences() { + override getProjectReferences(): readonly ts.ProjectReference[] | undefined { return this.hostProject.getProjectReferences(); } /** @internal */ - override includePackageJsonAutoImports() { + override includePackageJsonAutoImports(): ts.PackageJsonAutoImportPreference { return PackageJsonAutoImportPreference.Off; } /** @internal */ - override getSymlinkCache() { + override getSymlinkCache(): ts.SymlinkCache { return this.hostProject.getSymlinkCache(); } /** @internal */ - override getModuleResolutionCache() { + override getModuleResolutionCache(): ts.ModuleResolutionCache | undefined { return this.hostProject.getCurrentProgram()?.getModuleResolutionCache(); } } @@ -2838,7 +2838,7 @@ export class ConfiguredProject extends Project { pendingUpdateReason: string | undefined; /** @internal */ - openFileWatchTriggered = new Map(); + openFileWatchTriggered: Map = new Map(); /** @internal */ canConfigFileJsonReportNoInputFiles = false; @@ -2887,7 +2887,7 @@ export class ConfiguredProject extends Project { } /** @internal */ - setCompilerHost(host: CompilerHost) { + setCompilerHost(host: CompilerHost): void { this.compilerHost = host; } @@ -2897,12 +2897,12 @@ export class ConfiguredProject extends Project { } /** @internal */ - override useSourceOfProjectReferenceRedirect() { + override useSourceOfProjectReferenceRedirect(): boolean { return this.languageServiceEnabled; } /** @internal */ - override getParsedCommandLine(fileName: string) { + override getParsedCommandLine(fileName: string): ts.ParsedCommandLine | undefined { const configFileName = asNormalizedPath(normalizePath(fileName)); const canonicalConfigFilePath = asNormalizedPath(this.projectService.toCanonicalFileName(configFileName)); // Ensure the config file existience info is cached @@ -2920,7 +2920,7 @@ export class ConfiguredProject extends Project { } /** @internal */ - onReleaseParsedCommandLine(fileName: string) { + onReleaseParsedCommandLine(fileName: string): void { this.releaseParsedConfig(asNormalizedPath(this.projectService.toCanonicalFileName(asNormalizedPath(normalizePath(fileName))))); } @@ -2981,7 +2981,7 @@ export class ConfiguredProject extends Project { return this.directoryStructureHost as CachedDirectoryStructureHost; } - getConfigFilePath() { + getConfigFilePath(): ts.server.NormalizedPath { return asNormalizedPath(this.getProjectName()); } @@ -2989,13 +2989,13 @@ export class ConfiguredProject extends Project { return this.projectReferences; } - updateReferences(refs: readonly ProjectReference[] | undefined) { + updateReferences(refs: readonly ProjectReference[] | undefined): void { this.projectReferences = refs; this.potentialProjectReferences = undefined; } /** @internal */ - setPotentialProjectReference(canonicalConfigPath: NormalizedPath) { + setPotentialProjectReference(canonicalConfigPath: NormalizedPath): void { Debug.assert(this.isInitialLoadPending()); (this.potentialProjectReferences || (this.potentialProjectReferences = new Set())).add(canonicalConfigPath); } @@ -3054,11 +3054,11 @@ export class ConfiguredProject extends Project { return this.projectErrors || emptyArray; } - override setProjectErrors(projectErrors: Diagnostic[]) { + override setProjectErrors(projectErrors: Diagnostic[]): void { this.projectErrors = projectErrors; } - override close() { + override close(): void { this.projectService.configFileExistenceInfoCache.forEach((_configFileExistenceInfo, canonicalConfigFilePath) => this.releaseParsedConfig(canonicalConfigFilePath)); this.projectErrors = undefined; this.openFileWatchTriggered.clear(); @@ -3067,13 +3067,13 @@ export class ConfiguredProject extends Project { } /** @internal */ - override markAsDirty() { + override markAsDirty(): void { if (this.deferredClose) return; super.markAsDirty(); } /** @internal */ - isSolution() { + isSolution(): boolean { return this.getRootFilesMap().size === 0 && !this.canConfigFileJsonReportNoInputFiles; } @@ -3083,12 +3083,12 @@ export class ConfiguredProject extends Project { return !!this.deferredClose; } - getEffectiveTypeRoots() { + getEffectiveTypeRoots(): string[] { return getEffectiveTypeRoots(this.getCompilationSettings(), this) || []; } /** @internal */ - updateErrorOnNoInputFiles(fileNames: string[]) { + updateErrorOnNoInputFiles(fileNames: string[]): void { updateErrorForNoInputFiles(fileNames, this.getConfigFilePath(), this.getCompilerOptions().configFile!.configFileSpecs!, this.projectErrors!, this.canConfigFileJsonReportNoInputFiles); } } @@ -3105,13 +3105,13 @@ export class ExternalProject extends Project { this.enableGlobalPlugins(this.getCompilerOptions()); } - override updateGraph() { + override updateGraph(): boolean { const result = super.updateGraph(); this.projectService.sendProjectTelemetry(this); return result; } - override getExcludedFiles() { + override getExcludedFiles(): readonly ts.server.NormalizedPath[] { return this.excludedFiles; } } diff --git a/src/server/scriptInfo.ts b/src/server/scriptInfo.ts index c974871f4d20c..afadbe12d50b7 100644 --- a/src/server/scriptInfo.ts +++ b/src/server/scriptInfo.ts @@ -100,13 +100,13 @@ export class TextStorage { this.version = initialVersion || 0; } - public getVersion() { + public getVersion(): string { return this.svc ? `SVC-${this.version}-${this.svc.getSnapshotVersion()}` : `Text-${this.version}`; } - public hasScriptVersionCache_TestOnly() { + public hasScriptVersionCache_TestOnly(): boolean { return this.svc !== undefined; } @@ -120,7 +120,7 @@ export class TextStorage { } /** Public for testing */ - public useText(newText: string) { + public useText(newText: string): void { this.svc = undefined; this.text = newText; this.textSnapshot = undefined; @@ -130,7 +130,7 @@ export class TextStorage { this.version++; } - public edit(start: number, end: number, newText: string) { + public edit(start: number, end: number, newText: string): void { this.switchToScriptVersionCache().edit(start, end - start, newText); this.ownFileText = false; this.text = undefined; @@ -174,7 +174,7 @@ export class TextStorage { * Reads the contents from tempFile(if supplied) or own file and sets it as contents * returns true if text changed */ - public reloadWithFileText(tempFileName?: string) { + public reloadWithFileText(tempFileName?: string): boolean { const { text: newText, fileSize } = tempFileName || !this.info.isDynamicOrHasMixedContent() ? this.getFileTextAndSize(tempFileName) : { text: "", fileSize: undefined }; @@ -196,13 +196,13 @@ export class TextStorage { * Schedule reload from the disk if its not already scheduled and its not own text * returns true when scheduling reload */ - public scheduleReloadIfNeeded() { + public scheduleReloadIfNeeded(): boolean { return !this.pendingReloadFromDisk && !this.ownFileText ? this.pendingReloadFromDisk = true : false; } - public delayReloadFromFileIntoText() { + public delayReloadFromFileIntoText(): void { this.pendingReloadFromDisk = true; } @@ -345,7 +345,7 @@ export class TextStorage { } } -export function isDynamicFileName(fileName: NormalizedPath) { +export function isDynamicFileName(fileName: NormalizedPath): boolean { return fileName[0] === "^" || ((fileName.includes("walkThroughSnippet:/") || fileName.includes("untitled:/")) && getBaseFileName(fileName)[0] === "^") || @@ -428,15 +428,15 @@ export class ScriptInfo { } /** @internal */ - public isDynamicOrHasMixedContent() { + public isDynamicOrHasMixedContent(): boolean { return this.hasMixedContent || this.isDynamic; } - public isScriptOpen() { + public isScriptOpen(): boolean { return this.textStorage.isOpen; } - public open(newText: string | undefined) { + public open(newText: string | undefined): void { this.textStorage.isOpen = true; if ( newText !== undefined && @@ -447,14 +447,14 @@ export class ScriptInfo { } } - public close(fileExists = true) { + public close(fileExists = true): void { this.textStorage.isOpen = false; if (fileExists && this.textStorage.scheduleReloadIfNeeded()) { this.markContainingProjectsAsDirty(); } } - public getSnapshot() { + public getSnapshot(): IScriptSnapshot { return this.textStorage.getSnapshot(); } @@ -510,7 +510,7 @@ export class ScriptInfo { return isNew; } - isAttached(project: Project) { + isAttached(project: Project): boolean { // unrolled for common cases switch (this.containingProjects.length) { case 0: @@ -524,7 +524,7 @@ export class ScriptInfo { } } - detachFromProject(project: Project) { + detachFromProject(project: Project): void { // unrolled for common cases switch (this.containingProjects.length) { case 0: @@ -554,7 +554,7 @@ export class ScriptInfo { } } - detachAllProjects() { + detachAllProjects(): void { for (const p of this.containingProjects) { if (isConfiguredProject(p)) { p.getCachedDirectoryStructureHost().addOrDeleteFile(this.fileName, this.path, FileWatcherEventKind.Deleted); @@ -572,7 +572,7 @@ export class ScriptInfo { clear(this.containingProjects); } - getDefaultProject() { + getDefaultProject(): Project { switch (this.containingProjects.length) { case 0: return Errors.ThrowNoProject(); @@ -654,18 +654,18 @@ export class ScriptInfo { return this.textStorage.getVersion(); } - saveTo(fileName: string) { + saveTo(fileName: string): void { this.host.writeFile(fileName, getSnapshotText(this.textStorage.getSnapshot())); } /** @internal */ - delayReloadNonMixedContentFile() { + delayReloadNonMixedContentFile(): void { Debug.assert(!this.isDynamicOrHasMixedContent()); this.textStorage.delayReloadFromFileIntoText(); this.markContainingProjectsAsDirty(); } - reloadFromFile(tempFileName?: NormalizedPath) { + reloadFromFile(tempFileName?: NormalizedPath): boolean { if (this.textStorage.reloadWithFileText(tempFileName)) { this.markContainingProjectsAsDirty(); return true; @@ -678,18 +678,18 @@ export class ScriptInfo { this.markContainingProjectsAsDirty(); } - markContainingProjectsAsDirty() { + markContainingProjectsAsDirty(): void { for (const p of this.containingProjects) { p.markFileAsDirty(this.path); } } - isOrphan() { + isOrphan(): boolean { return this.deferredDelete || !forEach(this.containingProjects, p => !p.isOrphan()); } /** @internal */ - isContainedByBackgroundProject() { + isContainedByBackgroundProject(): boolean { return some( this.containingProjects, isBackgroundProject, @@ -699,7 +699,7 @@ export class ScriptInfo { /** * @param line 1 based index */ - lineToTextSpan(line: number) { + lineToTextSpan(line: number): TextSpan { return this.textStorage.lineToTextSpan(line); } @@ -721,12 +721,12 @@ export class ScriptInfo { return location; } - public isJavaScript() { + public isJavaScript(): boolean { return this.scriptKind === ScriptKind.JS || this.scriptKind === ScriptKind.JSX; } /** @internal */ - closeSourceMapFileWatcher() { + closeSourceMapFileWatcher(): void { if (this.sourceMapFilePath && !isString(this.sourceMapFilePath)) { closeFileWatcherOf(this.sourceMapFilePath); this.sourceMapFilePath = undefined; diff --git a/src/server/scriptVersionCache.ts b/src/server/scriptVersionCache.ts index 306e310f23ee3..55a957928a1ae 100644 --- a/src/server/scriptVersionCache.ts +++ b/src/server/scriptVersionCache.ts @@ -287,7 +287,7 @@ export class ScriptVersionCache { } // REVIEW: can optimize by coalescing simple edits - edit(pos: number, deleteLen: number, insertedText?: string) { + edit(pos: number, deleteLen: number, insertedText?: string): void { this.changes.push(new TextChange(pos, deleteLen, insertedText)); if ( this.changes.length > ScriptVersionCache.changeNumberThreshold || @@ -345,7 +345,7 @@ export class ScriptVersionCache { return createTextSpan(absolutePosition, len); } - getTextChangesBetweenVersions(oldVersion: number, newVersion: number) { + getTextChangesBetweenVersions(oldVersion: number, newVersion: number): TextChangeRange | undefined { if (oldVersion < newVersion) { if (oldVersion >= this.minVersion) { const textChangeRanges: TextChangeRange[] = []; @@ -366,11 +366,11 @@ export class ScriptVersionCache { } } - getLineCount() { + getLineCount(): number { return this._getSnapshot().index.getLineCount(); } - static fromString(script: string) { + static fromString(script: string): ScriptVersionCache { const svc = new ScriptVersionCache(); const snap = new LineIndexSnapshot(0, svc, new LineIndex()); svc.versions[svc.currentVersion] = snap; @@ -423,7 +423,7 @@ export class LineIndex { return this.root.charOffsetToLineInfo(1, position); } - getLineCount() { + getLineCount(): number { return this.root.lineCount(); } @@ -438,7 +438,7 @@ export class LineIndex { } } - load(lines: string[]) { + load(lines: string[]): void { if (lines.length > 0) { const leaves: LineLeaf[] = []; for (let i = 0; i < lines.length; i++) { @@ -451,11 +451,11 @@ export class LineIndex { } } - walk(rangeStart: number, rangeLength: number, walkFns: LineIndexWalker) { + walk(rangeStart: number, rangeLength: number, walkFns: LineIndexWalker): void { this.root.walk(rangeStart, rangeLength, walkFns); } - getText(rangeStart: number, rangeLength: number) { + getText(rangeStart: number, rangeLength: number): string { let accum = ""; if ((rangeLength > 0) && (rangeStart < this.root.charCount())) { this.walk(rangeStart, rangeLength, { @@ -473,7 +473,7 @@ export class LineIndex { return this.root.charCount(); } - every(f: (ll: LineLeaf, s: number, len: number) => boolean, rangeStart: number, rangeEnd?: number) { + every(f: (ll: LineLeaf, s: number, len: number) => boolean, rangeStart: number, rangeEnd?: number): boolean { if (!rangeEnd) { rangeEnd = this.root.charCount(); } @@ -559,7 +559,10 @@ export class LineIndex { return this.buildTreeFromBottom(interiorNodes); } - static linesFromText(text: string) { + static linesFromText(text: string): { + lines: string[]; + lineMap: number[]; + } { const lineMap = computeLineStarts(text); if (lineMap.length === 0) { @@ -595,7 +598,7 @@ export class LineNode implements LineCollection { return false; } - updateCounts() { + updateCounts(): void { this.totalChars = 0; this.totalLines = 0; for (const child of this.children) { @@ -627,7 +630,7 @@ export class LineNode implements LineCollection { } } - walk(rangeStart: number, rangeLength: number, walkFns: LineIndexWalker) { + walk(rangeStart: number, rangeLength: number, walkFns: LineIndexWalker): void { // assume (rangeStart < this.totalChars) && (rangeLength <= this.totalChars) let childIndex = 0; let childCharCount = this.children[childIndex].charCount(); @@ -748,7 +751,7 @@ export class LineNode implements LineCollection { return splitNode; } - remove(child: LineCollection) { + remove(child: LineCollection): void { const childIndex = this.findChildIndex(child); const clen = this.children.length; if (childIndex < (clen - 1)) { @@ -765,7 +768,7 @@ export class LineNode implements LineCollection { return childIndex; } - insertAt(child: LineCollection, nodes: LineCollection[]) { + insertAt(child: LineCollection, nodes: LineCollection[]): LineNode[] { let childIndex = this.findChildIndex(child); const clen = this.children.length; const nodeCount = nodes.length; @@ -825,11 +828,11 @@ export class LineNode implements LineCollection { Debug.assert(this.children.length <= lineCollectionCapacity); } - charCount() { + charCount(): number { return this.totalChars; } - lineCount() { + lineCount(): number { return this.totalLines; } } @@ -843,11 +846,11 @@ export class LineLeaf implements LineCollection { return true; } - walk(rangeStart: number, rangeLength: number, walkFns: LineIndexWalker) { + walk(rangeStart: number, rangeLength: number, walkFns: LineIndexWalker): void { walkFns.leaf(rangeStart, rangeLength, this); } - charCount() { + charCount(): number { return this.text.length; } diff --git a/src/server/session.ts b/src/server/session.ts index fd0ed26586dc7..039c9d4238b7e 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -316,7 +316,7 @@ function allEditsBeforePos(edits: readonly TextChange[], pos: number): boolean { /** @deprecated use ts.server.protocol.CommandTypes */ export type CommandNames = protocol.CommandTypes; /** @deprecated use ts.server.protocol.CommandTypes */ -export const CommandNames = (protocol as any).CommandTypes; +export const CommandNames: CommandNames = (protocol as any).CommandTypes; export function formatMessage(msg: T, logger: Logger, byteLength: (s: string, encoding: BufferEncoding) => number, newLine: string): string { const verboseLogging = logger.hasLevel(LogLevel.verbose); @@ -1227,7 +1227,7 @@ export class Session implements EventSender { this.logger.msg(msg, Msg.Err); } - public send(msg: protocol.Message) { + public send(msg: protocol.Message): void { if (msg.type === "event" && !this.canUseEvents) { if (this.logger.hasLevel(LogLevel.verbose)) { this.logger.info(`Session does not support events: ignored event: ${stringifyIndented(msg)}`); @@ -1237,7 +1237,7 @@ export class Session implements EventSender { this.writeMessage(msg); } - protected writeMessage(msg: protocol.Message) { + protected writeMessage(msg: protocol.Message): void { const msgText = formatMessage(msg, this.logger, this.byteLength, this.host.newLine); this.host.write(msgText); } @@ -3289,12 +3289,12 @@ export class Session implements EventSender { return outgoingCalls.map(call => this.toProtocolCallHierarchyOutgoingCall(call, scriptInfo)); } - getCanonicalFileName(fileName: string) { + getCanonicalFileName(fileName: string): string { const name = this.host.useCaseSensitiveFileNames ? fileName : toFileNameLowerCase(fileName); return normalizePath(name); } - exit() {/*overridden*/} + exit(): void {/*overridden*/} private notRequired(request: protocol.Request | undefined): HandlerResponse { if (request) this.doOutput(/*info*/ undefined, request.command, request.seq, /*success*/ true, this.performanceData); @@ -3710,7 +3710,7 @@ export class Session implements EventSender { }, })); - public addProtocolHandler(command: string, handler: (request: protocol.Request) => HandlerResponse) { + public addProtocolHandler(command: string, handler: (request: protocol.Request) => HandlerResponse): void { if (this.handlers.has(command)) { throw new Error(`Protocol handler already exists for command "${command}"`); } @@ -3759,7 +3759,7 @@ export class Session implements EventSender { } } - public onMessage(message: TMessage) { + public onMessage(message: TMessage): void { this.gcTimer.scheduleCollect(); let start: [number, number] | undefined; const currentPerformanceData = this.performanceData; diff --git a/src/server/typingInstallerAdapter.ts b/src/server/typingInstallerAdapter.ts index 5f8e90b7f837d..f92b6bf2a8405 100644 --- a/src/server/typingInstallerAdapter.ts +++ b/src/server/typingInstallerAdapter.ts @@ -104,7 +104,7 @@ export abstract class TypingsInstallerAdapter implements ITypingsInstaller { return promise; } - attach(projectService: ProjectService) { + attach(projectService: ProjectService): void { this.projectService = projectService; this.installer = this.createInstallerProcess(); } @@ -131,7 +131,7 @@ export abstract class TypingsInstallerAdapter implements ITypingsInstaller { } } - handleMessage(response: TypesRegistryResponse | PackageInstalledResponse | SetTypings | InvalidateCachedTypings | BeginInstallTypes | EndInstallTypes | InitializationFailedResponse | server.WatchTypingLocations) { + handleMessage(response: TypesRegistryResponse | PackageInstalledResponse | SetTypings | InvalidateCachedTypings | BeginInstallTypes | EndInstallTypes | InitializationFailedResponse | server.WatchTypingLocations): void { if (this.logger.hasLevel(LogLevel.verbose)) { this.logger.info(`TIAdapter:: Received response:${stringifyIndented(response)}`); } @@ -234,7 +234,7 @@ export abstract class TypingsInstallerAdapter implements ITypingsInstaller { } } - scheduleRequest(request: DiscoverTypings) { + scheduleRequest(request: DiscoverTypings): void { if (this.logger.hasLevel(LogLevel.verbose)) { this.logger.info(`TIAdapter:: Scheduling request for: ${request.projectName}`); } diff --git a/src/server/utilities.ts b/src/server/utilities.ts index 5ea8cd876f3e7..5466d4c448d28 100644 --- a/src/server/utilities.ts +++ b/src/server/utilities.ts @@ -20,7 +20,7 @@ export class ThrottledOperations { * of the new one. (Note that the amount of time the canceled operation had been * waiting does not affect the amount of time that the new operation waits.) */ - public schedule(operationId: string, delay: number, cb: () => void) { + public schedule(operationId: string, delay: number, cb: () => void): void { const pendingTimeout = this.pendingTimeouts.get(operationId); if (pendingTimeout) { // another operation was already scheduled for this id - cancel it @@ -33,7 +33,7 @@ export class ThrottledOperations { } } - public cancel(operationId: string) { + public cancel(operationId: string): boolean { const pendingTimeout = this.pendingTimeouts.get(operationId); if (!pendingTimeout) return false; this.host.clearTimeout(pendingTimeout); @@ -55,7 +55,7 @@ export class GcTimer { constructor(private readonly host: ServerHost, private readonly delay: number, private readonly logger: Logger) { } - public scheduleCollect() { + public scheduleCollect(): void { if (!this.host.gc || this.timerId !== undefined) { // no global.gc or collection was already scheduled - skip this request return; diff --git a/src/server/utilitiesPublic.ts b/src/server/utilitiesPublic.ts index c0ce5dfea1295..2476292715de0 100644 --- a/src/server/utilitiesPublic.ts +++ b/src/server/utilitiesPublic.ts @@ -117,7 +117,7 @@ export interface ProjectOptions { configHasExcludeProperty: boolean; } -export function isInferredProjectName(name: string) { +export function isInferredProjectName(name: string): boolean { // POSIX defines /dev/null as a device - there should be no file with this prefix return /dev\/null\/inferredProject\d+\*/.test(name); } diff --git a/src/tsserver/common.ts b/src/tsserver/common.ts index 01fd6db7dcf7c..89647f6032c82 100644 --- a/src/tsserver/common.ts +++ b/src/tsserver/common.ts @@ -1,7 +1,7 @@ import * as ts from "../typescript/typescript.js"; /** @internal */ -export function getLogLevel(level: string | undefined) { +export function getLogLevel(level: string | undefined): ts.server.LogLevel | undefined { if (level) { const l = level.toLowerCase(); for (const name in ts.server.LogLevel) { diff --git a/src/typingsInstaller/nodeTypingsInstaller.ts b/src/typingsInstaller/nodeTypingsInstaller.ts index 984d7b80c5b7e..34d7a235e3045 100644 --- a/src/typingsInstaller/nodeTypingsInstaller.ts +++ b/src/typingsInstaller/nodeTypingsInstaller.ts @@ -135,7 +135,7 @@ export class NodeTypingsInstaller extends ts.server.typingsInstaller.TypingsInst this.typesRegistry = loadTypesRegistryFile(getTypesRegistryFileLocation(globalTypingsCacheLocation), this.installTypingHost, this.log); } - override handleRequest(req: ts.server.TypingInstallerRequestUnion) { + override handleRequest(req: ts.server.TypingInstallerRequestUnion): void { if (this.delayedInitializationError) { // report initializationFailed error this.sendResponse(this.delayedInitializationError); @@ -144,7 +144,7 @@ export class NodeTypingsInstaller extends ts.server.typingsInstaller.TypingsInst super.handleRequest(req); } - protected sendResponse(response: ts.server.TypingInstallerResponseUnion) { + protected sendResponse(response: ts.server.TypingInstallerResponseUnion): void { if (this.log.isEnabled()) { this.log.writeLine(`Sending response:${ts.server.stringifyIndented(response)}`); } From 4c1bc99e7460c3ea2dfb6e66f5a810ebc582db9e Mon Sep 17 00:00:00 2001 From: Isabel Duan Date: Tue, 13 Aug 2024 00:31:24 -0700 Subject: [PATCH 07/27] generated codefixes harness --- src/harness/harnessIO.ts | 63 ++++++++++++------ src/harness/harnessLanguageService.ts | 42 ++++++------ src/harness/incrementalUtils.ts | 8 +-- src/harness/sourceMapRecorder.ts | 4 +- src/harness/vfsUtil.ts | 93 +++++++++++++++------------ src/harness/vpathUtil.ts | 12 ++-- src/harness/watchUtils.ts | 2 +- 7 files changed, 130 insertions(+), 94 deletions(-) diff --git a/src/harness/harnessIO.ts b/src/harness/harnessIO.ts index d73092a297aeb..bd3e2fdc83783 100644 --- a/src/harness/harnessIO.ts +++ b/src/harness/harnessIO.ts @@ -44,7 +44,7 @@ export interface IO { } export let IO: IO; -export function setHarnessIO(io: IO) { +export function setHarnessIO(io: IO): void { IO = io; } @@ -173,7 +173,7 @@ export type SourceMapEmitterCallback = ( export let userSpecifiedRoot = ""; export let lightMode = false; /* eslint-enable prefer-const */ -export function setLightMode(flag: boolean) { +export function setLightMode(flag: boolean): void { lightMode = flag; } @@ -186,23 +186,23 @@ export namespace Compiler { public lines: string[] = []; public currentLine: string = undefined!; - public Write(str: string) { + public Write(str: string): void { // out of memory usage concerns avoid using + or += if we're going to do any manipulation of this string later this.currentLine = [this.currentLine || "", str].join(""); } - public WriteLine(str: string) { + public WriteLine(str: string): void { // out of memory usage concerns avoid using + or += if we're going to do any manipulation of this string later this.lines.push([this.currentLine || "", str].join("")); this.currentLine = undefined!; } - public Close() { + public Close(): void { if (this.currentLine !== undefined) this.lines.push(this.currentLine); this.currentLine = undefined!; } - public reset() { + public reset(): void { this.lines = []; this.currentLine = undefined!; } @@ -212,7 +212,7 @@ export namespace Compiler { fileName: string, sourceText: string, languageVersionOrOptions: ts.ScriptTarget | ts.CreateSourceFileOptions, - ) { + ): ts.SourceFile { // We'll only assert invariants outside of light mode. const shouldAssertInvariants = !lightMode; @@ -235,7 +235,7 @@ export namespace Compiler { // Cache of lib files from "built/local" export let libFileNameSourceFileMap: Map | undefined; - export function getDefaultLibrarySourceFile(fileName = defaultLibFileName): ts.SourceFile | undefined { + export function getDefaultLibrarySourceFile(fileName: string = defaultLibFileName): ts.SourceFile | undefined { if (!isDefaultLibraryFile(fileName)) { return undefined; } @@ -517,7 +517,11 @@ export namespace Compiler { } } - export function compileDeclarationFiles(context: DeclarationCompilationContext | undefined, symlinks: vfs.FileSet | undefined) { + export function compileDeclarationFiles(context: DeclarationCompilationContext | undefined, symlinks: vfs.FileSet | undefined): { + declInputFiles: TestFile[]; + declOtherFiles: TestFile[]; + declResult: CompileFilesResult; + } | undefined { if (!context) { return; } @@ -526,12 +530,12 @@ export namespace Compiler { return { declInputFiles, declOtherFiles, declResult: output }; } - export function minimalDiagnosticsToString(diagnostics: readonly ts.Diagnostic[], pretty?: boolean) { + export function minimalDiagnosticsToString(diagnostics: readonly ts.Diagnostic[], pretty?: boolean): string { const host = { getCanonicalFileName, getCurrentDirectory: () => "", getNewLine: () => IO.newLine() }; 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): string { let outputLines = ""; const gen = iterateErrorBaseline(inputFiles, diagnostics, { pretty }); for (const value of gen) { @@ -706,11 +710,21 @@ export namespace Compiler { 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) { + export function doErrorBaseline(baselinePath: string, inputFiles: readonly TestFile[], errors: readonly ts.Diagnostic[], pretty?: boolean): void { Baseline.runBaseline(baselinePath.replace(/\.tsx?$/, ".errors.txt"), !errors || (errors.length === 0) ? null : getErrorBaseline(inputFiles, errors, pretty)); // eslint-disable-line no-restricted-syntax } - 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, + ): void { // 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 @@ -901,7 +915,7 @@ 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): void { const declMaps = ts.getAreDeclarationMapsEnabled(options); if (options.inlineSourceMap) { if (result.maps.size > 0 && !declMaps) { @@ -947,7 +961,16 @@ export namespace Compiler { return "\n//// https://sokra.github.io/source-map-visualization" + hash + "\n"; } - export function doJsEmitBaseline(baselinePath: string, header: string, options: ts.CompilerOptions, result: CompileFilesResult, tsConfigFiles: readonly TestFile[], toBeCompiled: readonly TestFile[], otherFiles: readonly TestFile[], harnessSettings: TestCaseParser.CompilerSettings) { + export function doJsEmitBaseline( + baselinePath: string, + header: string, + options: ts.CompilerOptions, + result: CompileFilesResult, + tsConfigFiles: readonly TestFile[], + toBeCompiled: readonly TestFile[], + otherFiles: readonly TestFile[], + harnessSettings: TestCaseParser.CompilerSettings, + ): void { 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."); } @@ -1079,7 +1102,7 @@ export namespace Compiler { return resultName; } - export function sanitizeTestFilePath(name: string) { + export function sanitizeTestFilePath(name: string): string { const path = ts.toPath(ts.normalizeSlashes(name.replace(/[\^<>:"|?*%]/g, "_")).replace(/\.\.\//g, "__dotdot/"), "", Utils.canonicalizeForHarness); if (ts.startsWith(path, "/")) { return path.substring(1); @@ -1219,7 +1242,7 @@ export function getFileBasedTestConfigurations(settings: TestCaseParser.Compiler /** * Compute a description for this configuration based on its entries */ -export function getFileBasedTestConfigurationDescription(configuration: FileBasedTestConfiguration) { +export function getFileBasedTestConfigurationDescription(configuration: FileBasedTestConfiguration): string { let name = ""; if (configuration) { const keys = Object.keys(configuration).sort(); @@ -1250,7 +1273,7 @@ export namespace TestCaseParser { const optionRegex = /^[/]{2}\s*@(\w+)\s*:\s*([^\r\n]*)/gm; // multiple matches on multiple lines const linkRegex = /^[/]{2}\s*@link\s*:\s*([^\r\n]*)\s*->\s*([^\r\n]*)/gm; // multiple matches on multiple lines - export function parseSymlinkFromTest(line: string, symlinks: vfs.FileSet | undefined, absoluteRootDir?: string) { + export function parseSymlinkFromTest(line: string, symlinks: vfs.FileSet | undefined, absoluteRootDir?: string): vfs.FileSet | undefined { const linkMetaData = linkRegex.exec(line); linkRegex.lastIndex = 0; if (!linkMetaData) return undefined; @@ -1280,7 +1303,7 @@ 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: CompilerSettings = extractCompilerSettings(code)): TestCaseContent { // List of all the subfiles we've parsed out const testUnitData: TestUnitData[] = []; @@ -1425,7 +1448,7 @@ export namespace Baseline { PrintDiff?: true; } - export function localPath(fileName: string, baselineFolder?: string, subfolder?: string) { + export function localPath(fileName: string, baselineFolder?: string, subfolder?: string): string { if (baselineFolder === undefined) { return baselinePath(fileName, "local", "tests/baselines", subfolder); } diff --git a/src/harness/harnessLanguageService.ts b/src/harness/harnessLanguageService.ts index 4dfd58a297a96..6a62ed1007ff9 100644 --- a/src/harness/harnessLanguageService.ts +++ b/src/harness/harnessLanguageService.ts @@ -113,7 +113,7 @@ class ScriptSnapshot implements ts.IScriptSnapshot { } class DefaultHostCancellationToken implements ts.HostCancellationToken { - public static readonly instance = new DefaultHostCancellationToken(); + public static readonly instance: DefaultHostCancellationToken = new DefaultHostCancellationToken(); public isCancellationRequested() { return false; @@ -129,16 +129,16 @@ export interface LanguageServiceAdapter { } export abstract class LanguageServiceAdapterHost { - public readonly sys = new fakes.System(new vfs.FileSystem(/*ignoreCase*/ true, { cwd: virtualFileSystemRoot })); + public readonly sys: fakes.System = new fakes.System(new vfs.FileSystem(/*ignoreCase*/ true, { cwd: virtualFileSystemRoot })); public typesRegistry: Map | undefined; private scriptInfos: collections.SortedMap; public jsDocParsingMode: ts.JSDocParsingMode | undefined; - constructor(protected cancellationToken = DefaultHostCancellationToken.instance, protected settings = ts.getDefaultCompilerOptions()) { + constructor(protected cancellationToken: DefaultHostCancellationToken = DefaultHostCancellationToken.instance, protected settings: ts.CompilerOptions = ts.getDefaultCompilerOptions()) { this.scriptInfos = new collections.SortedMap({ comparer: this.vfs.stringComparer, sort: "insertion" }); } - public get vfs() { + public get vfs(): vfs.FileSystem { return this.sys.vfs; } @@ -185,7 +185,7 @@ export abstract class LanguageServiceAdapterHost { } } - public directoryExists(path: string) { + public directoryExists(path: string): boolean { return this.vfs.statSync(path).isDirectory(); } @@ -214,7 +214,7 @@ export abstract class LanguageServiceAdapterHost { }); } - public editScript(fileName: string, start: number, end: number, newText: string) { + public editScript(fileName: string, start: number, end: number, newText: string): void { const script = this.getScriptInfo(fileName); if (script) { script.editContent(start, end, newText); @@ -244,7 +244,7 @@ export abstract class LanguageServiceAdapterHost { return ts.computePositionOfLineAndCharacter(script.getLineMap(), lineAndCharacter.line, lineAndCharacter.character); } - useCaseSensitiveFileNames() { + useCaseSensitiveFileNames(): boolean { return !this.vfs.ignoreCase; } } @@ -259,13 +259,13 @@ class NativeLanguageServiceHost extends LanguageServiceAdapterHost implements ts return "/Library/Caches/typescript"; } - installPackage = ts.notImplemented; + installPackage: typeof ts.notImplemented = ts.notImplemented; - getCompilationSettings() { + getCompilationSettings(): ts.CompilerOptions { return this.settings; } - getCancellationToken() { + getCancellationToken(): DefaultHostCancellationToken { return this.cancellationToken; } @@ -323,14 +323,14 @@ class NativeLanguageServiceHost extends LanguageServiceAdapterHost implements ts return 0; } - log = ts.noop; - trace = ts.noop; - error = ts.noop; + log: typeof ts.noop = ts.noop; + trace: typeof ts.noop = ts.noop; + error: typeof ts.noop = ts.noop; } export class NativeLanguageServiceAdapter implements LanguageServiceAdapter { private host: NativeLanguageServiceHost; - getLogger = ts.returnUndefined; + getLogger: typeof ts.returnUndefined = ts.returnUndefined; constructor(cancellationToken?: ts.HostCancellationToken, options?: ts.CompilerOptions) { this.host = new NativeLanguageServiceHost(cancellationToken, options); } @@ -356,10 +356,10 @@ class SessionClientHost extends NativeLanguageServiceHost implements ts.server.S super(cancellationToken, settings); } - onMessage = ts.noop; - writeMessage = ts.noop; + onMessage: typeof ts.noop = ts.noop; + writeMessage: typeof ts.noop = ts.noop; - setClient(client: ts.server.SessionClient) { + setClient(client: ts.server.SessionClient): void { this.client = client; } @@ -368,7 +368,7 @@ class SessionClientHost extends NativeLanguageServiceHost implements ts.server.S this.client.openFile(fileName, content, scriptKindName); } - override editScript(fileName: string, start: number, end: number, newText: string) { + override editScript(fileName: string, start: number, end: number, newText: string): void { const changeArgs = this.client.createChangeFileRequestArgs(fileName, start, end, newText); super.editScript(fileName, start, end, newText); this.client.changeFile(fileName, changeArgs); @@ -662,10 +662,10 @@ export class ServerLanguageServiceAdapter implements LanguageServiceAdapter { this.client = client; this.host = clientHost; } - getLogger() { + getLogger(): LoggerWithInMemoryLogs { return this.logger; } - getHost() { + getHost(): SessionClientHost { return this.host; } getLanguageService(): ts.LanguageService { @@ -677,7 +677,7 @@ export class ServerLanguageServiceAdapter implements LanguageServiceAdapter { getPreProcessedFileInfo(): ts.PreProcessedFileInfo { throw new Error("getPreProcessedFileInfo is not available using the server interface."); } - assertTextConsistent(fileName: string) { + assertTextConsistent(fileName: string): void { const serverText = this.server.getText(fileName); const clientText = this.host.readFile(fileName); ts.Debug.assert( diff --git a/src/harness/incrementalUtils.ts b/src/harness/incrementalUtils.ts index 72df2718621e8..234a327deb88a 100644 --- a/src/harness/incrementalUtils.ts +++ b/src/harness/incrementalUtils.ts @@ -1,6 +1,6 @@ import * as ts from "./_namespaces/ts.js"; -export function reportDocumentRegistryStats(documentRegistry: ts.DocumentRegistry) { +export function reportDocumentRegistryStats(documentRegistry: ts.DocumentRegistry): string[] { const str: string[] = []; documentRegistry.getBuckets().forEach((bucketEntries, key) => { str.push(` Key:: ${key}`); @@ -193,7 +193,7 @@ function getProgramStructure(program: ts.Program | undefined) { return baseline.join("\n"); } -export function verifyProgramStructure(expectedProgram: ts.Program, actualProgram: ts.Program, projectName: string) { +export function verifyProgramStructure(expectedProgram: ts.Program, actualProgram: ts.Program, projectName: string): void { const actual = getProgramStructure(actualProgram); const expected = getProgramStructure(expectedProgram); ts.Debug.assert(actual === expected, `Program verification:: ${projectName}`); @@ -204,7 +204,7 @@ export function verifyResolutionCache( actualProgram: ts.Program, resolutionHostCacheHost: ts.ResolutionCacheHost, projectName: string, -) { +): void { const currentDirectory = resolutionHostCacheHost.getCurrentDirectory!(); const expected = ts.createResolutionCache(resolutionHostCacheHost, actual.rootDirForResolution, /*logChangesWhenResolvingModule*/ false); expected.startCachingPerDirectoryResolution(); @@ -626,7 +626,7 @@ export interface IncrementalVerifierCallbacks { afterVerification?(dataFromBefore: any): void; } -export function incrementalVerifier(service: ts.server.ProjectService) { +export function incrementalVerifier(service: ts.server.ProjectService): void { service.verifyDocumentRegistry = withIncrementalVerifierCallbacks(service, verifyDocumentRegistry); service.verifyProgram = withIncrementalVerifierCallbacks(service, verifyProgram); service.onProjectCreation = onProjectCreation; diff --git a/src/harness/sourceMapRecorder.ts b/src/harness/sourceMapRecorder.ts index 44a6c12edf935..11366f98c5076 100644 --- a/src/harness/sourceMapRecorder.ts +++ b/src/harness/sourceMapRecorder.ts @@ -277,7 +277,7 @@ 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[]): string { const sourceMapRecorder = new Compiler.WriterAggregator(); for (let i = 0; i < sourceMapDataList.length; i++) { @@ -324,7 +324,7 @@ export function getSourceMapRecord(sourceMapDataList: readonly ts.SourceMapEmitR return sourceMapRecorder.lines.join("\r\n"); } -export function getSourceMapRecordWithSystem(sys: ts.System, sourceMapFile: string) { +export function getSourceMapRecordWithSystem(sys: ts.System, sourceMapFile: string): string { const sourceMapRecorder = new Compiler.WriterAggregator(); let prevSourceFile: documents.TextDocument | undefined; const files = new Map(); diff --git a/src/harness/vfsUtil.ts b/src/harness/vfsUtil.ts index 7e6e76d545d19..916690fc7de39 100644 --- a/src/harness/vfsUtil.ts +++ b/src/harness/vfsUtil.ts @@ -111,14 +111,14 @@ export class FileSystem { /** * Gets a value indicating whether the file system is read-only. */ - public get isReadonly() { + public get isReadonly(): boolean { return Object.isFrozen(this); } /** * Makes the file system read-only. */ - public makeReadonly() { + public makeReadonly(): this { Object.freeze(this); return this; } @@ -126,7 +126,7 @@ export class FileSystem { /** * Gets the file system shadowed by this file system. */ - public get shadowRoot() { + public get shadowRoot(): FileSystem | undefined { return this._shadowRoot; } @@ -135,7 +135,7 @@ export class FileSystem { * generating file system patches using `.diff()` from one snapshot to the next. Performs * no action if this file system is read-only. */ - public snapshot() { + public snapshot(): void { if (this.isReadonly) return; const fs = new FileSystem(this.ignoreCase, { time: this._time }); fs._lazy = this._lazy; @@ -153,7 +153,7 @@ export class FileSystem { * original, allowing multiple copies of the same core file system without multiple copies * of the same data. */ - public shadow(ignoreCase = this.ignoreCase) { + public shadow(ignoreCase: boolean = this.ignoreCase): FileSystem { 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."); const fs = new FileSystem(ignoreCase, { time: this._time }); @@ -201,7 +201,7 @@ export class FileSystem { * * @link - http://pubs.opengroup.org/onlinepubs/9699919799/functions/getcwd.html */ - public cwd() { + public cwd(): string { if (!this._cwd) throw new Error("The current working directory has not been set."); const { node } = this._walk(this._cwd); if (!node) throw createIOError("ENOENT"); @@ -214,7 +214,7 @@ export class FileSystem { * * @link http://pubs.opengroup.org/onlinepubs/9699919799/functions/chdir.html */ - public chdir(path: string) { + public chdir(path: string): void { if (this.isReadonly) throw createIOError("EPERM"); path = this._resolve(path); const { node } = this._walk(path); @@ -226,7 +226,7 @@ export class FileSystem { /** * Pushes the current directory onto the directory stack and changes the current working directory to the supplied path. */ - public pushd(path?: string) { + public pushd(path?: string): void { if (this.isReadonly) throw createIOError("EPERM"); if (path) path = this._resolve(path); if (this._cwd) { @@ -241,7 +241,7 @@ export class FileSystem { /** * Pops the previous directory from the location stack and changes the current directory to that directory. */ - public popd() { + public popd(): void { if (this.isReadonly) throw createIOError("EPERM"); const path = this._dirStack && this._dirStack.pop(); if (path) { @@ -252,7 +252,7 @@ export class FileSystem { /** * Update the file system with a set of files. */ - public apply(files: FileSet) { + public apply(files: FileSet): void { this._applyFiles(files, this._cwd); } @@ -262,7 +262,7 @@ export class FileSystem { * @param axis The axis along which to traverse. * @param traversal The traversal scheme to use. */ - public scanSync(path: string, axis: Axis, traversal: Traversal) { + public scanSync(path: string, axis: Axis, traversal: Traversal): string[] { path = this._resolve(path); const results: string[] = []; this._scan(path, this._stat(this._walk(path)), axis, traversal, /*noFollow*/ false, results); @@ -275,7 +275,7 @@ export class FileSystem { * @param axis The axis along which to traverse. * @param traversal The traversal scheme to use. */ - public lscanSync(path: string, axis: Axis, traversal: Traversal) { + public lscanSync(path: string, axis: Axis, traversal: Traversal): string[] { path = this._resolve(path); const results: string[] = []; this._scan(path, this._stat(this._walk(path, /*noFollow*/ true)), axis, traversal, /*noFollow*/ true, results); @@ -321,7 +321,7 @@ export class FileSystem { * @param target The path in this virtual file system. * @param resolver An object used to resolve files in `source`. */ - public mountSync(source: string, target: string, resolver: FileSystemResolver) { + public mountSync(source: string, target: string, resolver: FileSystemResolver): void { if (this.isReadonly) throw createIOError("EROFS"); source = vpath.validate(source, vpath.ValidationFlags.Absolute); @@ -339,7 +339,7 @@ export class FileSystem { /** * Recursively remove all files and directories underneath the provided path. */ - public rimrafSync(path: string) { + public rimrafSync(path: string): void { try { const stats = this.lstatSync(path); if (stats.isFile() || stats.isSymbolicLink()) { @@ -361,7 +361,7 @@ export class FileSystem { /** * Make a directory and all of its parent paths (if they don't exist). */ - public mkdirpSync(path: string) { + public mkdirpSync(path: string): void { path = this._resolve(path); const result = this._walk(path, /*noFollow*/ true, (error, result) => { if (error.code === "ENOENT") { @@ -410,7 +410,7 @@ export class FileSystem { /** * Determines whether a path exists. */ - public existsSync(path: string) { + public existsSync(path: string): boolean { const result = this._walk(this._resolve(path), /*noFollow*/ true, () => "stop"); return result !== undefined && result.node !== undefined; } @@ -422,7 +422,7 @@ export class FileSystem { * * NOTE: do not rename this method as it is intended to align with the same named export of the "fs" module. */ - public statSync(path: string) { + public statSync(path: string): Stats { return this._stat(this._walk(this._resolve(path))); } @@ -431,7 +431,7 @@ export class FileSystem { * * NOTE: do not rename this method as it is intended to align with the same named export of the "fs" module. */ - public utimesSync(path: string, atime: Date, mtime: Date) { + public utimesSync(path: string, atime: Date, mtime: Date): void { if (this.isReadonly) throw createIOError("EROFS"); if (!isFinite(+atime) || !isFinite(+mtime)) throw createIOError("EINVAL"); @@ -451,7 +451,7 @@ export class FileSystem { * * NOTE: do not rename this method as it is intended to align with the same named export of the "fs" module. */ - public lstatSync(path: string) { + public lstatSync(path: string): Stats { return this._stat(this._walk(this._resolve(path), /*noFollow*/ true)); } @@ -481,7 +481,7 @@ export class FileSystem { * * NOTE: do not rename this method as it is intended to align with the same named export of the "fs" module. */ - public readdirSync(path: string) { + public readdirSync(path: string): string[] { const { node } = this._walk(this._resolve(path)); if (!node) throw createIOError("ENOENT"); if (!isDirectory(node)) throw createIOError("ENOTDIR"); @@ -495,7 +495,7 @@ export class FileSystem { * * NOTE: do not rename this method as it is intended to align with the same named export of the "fs" module. */ - public mkdirSync(path: string) { + public mkdirSync(path: string): void { if (this.isReadonly) throw createIOError("EROFS"); this._mkdir(this._walk(this._resolve(path), /*noFollow*/ true)); @@ -515,7 +515,7 @@ export class FileSystem { * * NOTE: do not rename this method as it is intended to align with the same named export of the "fs" module. */ - public rmdirSync(path: string) { + public rmdirSync(path: string): void { if (this.isReadonly) throw createIOError("EROFS"); path = this._resolve(path); @@ -534,7 +534,7 @@ export class FileSystem { * * NOTE: do not rename this method as it is intended to align with the same named export of the "fs" module. */ - public linkSync(oldpath: string, newpath: string) { + public linkSync(oldpath: string, newpath: string): void { if (this.isReadonly) throw createIOError("EROFS"); const { node } = this._walk(this._resolve(oldpath)); @@ -555,7 +555,7 @@ export class FileSystem { * * NOTE: do not rename this method as it is intended to align with the same named export of the "fs" module. */ - public unlinkSync(path: string) { + public unlinkSync(path: string): void { if (this.isReadonly) throw createIOError("EROFS"); const { parent, links, node, basename } = this._walk(this._resolve(path), /*noFollow*/ true); @@ -573,7 +573,7 @@ export class FileSystem { * * NOTE: do not rename this method as it is intended to align with the same named export of the "fs" module. */ - public renameSync(oldpath: string, newpath: string) { + public renameSync(oldpath: string, newpath: string): void { if (this.isReadonly) throw createIOError("EROFS"); const { parent: oldParent, links: oldParentLinks, node, basename: oldBasename } = this._walk(this._resolve(oldpath), /*noFollow*/ true); @@ -607,7 +607,7 @@ export class FileSystem { * * NOTE: do not rename this method as it is intended to align with the same named export of the "fs" module. */ - public symlinkSync(target: string, linkpath: string) { + public symlinkSync(target: string, linkpath: string): void { if (this.isReadonly) throw createIOError("EROFS"); const { parent, links, node: existingNode, basename } = this._walk(this._resolve(linkpath), /*noFollow*/ true); @@ -627,7 +627,7 @@ export class FileSystem { * * NOTE: do not rename this method as it is intended to align with the same named export of the "fs" module. */ - public realpathSync(path: string) { + public realpathSync(path: string): string { const { realpath } = this._walk(this._resolve(path)); return realpath; } @@ -666,7 +666,7 @@ export class FileSystem { * NOTE: do not rename this method as it is intended to align with the same named export of the "fs" module. */ // eslint-disable-next-line no-restricted-syntax - public writeFileSync(path: string, data: string | Buffer, encoding: string | null = null) { + public writeFileSync(path: string, data: string | Buffer, encoding: string | null = null): void { if (this.isReadonly) throw createIOError("EROFS"); const { parent, links, node: existingNode, basename } = this._walk(this._resolve(path), /*noFollow*/ false); @@ -694,7 +694,7 @@ export class FileSystem { * Generates a `FileSet` patch containing all the entries in this `FileSystem` that are not in `base`. * @param base The base file system. If not provided, this file system's `shadowRoot` is used (if present). */ - public diff(base?: FileSystem | undefined, options: DiffOptions = {}) { + public diff(base?: FileSystem | undefined, options: DiffOptions = {}): FileSet | undefined { if (!base && !options.baseIsNotShadowRoot) base = this.shadowRoot; const differences: FileSet = {}; const hasDifferences = base ? @@ -707,7 +707,7 @@ export class FileSystem { /** * Generates a `FileSet` patch containing all the entries in `changed` that are not in `base`. */ - public static diff(changed: FileSystem, base: FileSystem, options: DiffOptions = {}) { + public static diff(changed: FileSystem, base: FileSystem, options: DiffOptions = {}): FileSet | undefined { const differences: FileSet = {}; return FileSystem.rootDiff(differences, changed, base, options) ? differences : @@ -1253,7 +1253,7 @@ 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 = {}): FileSystem { const fs = getBuiltLocal(host, ignoreCase).shadow(); if (meta) { for (const key of Object.keys(meta)) { @@ -1331,30 +1331,43 @@ export class Stats { this.birthtime = new Date(this.birthtimeMs); } - public isFile() { + public isFile(): boolean { return (this.mode & S_IFMT) === S_IFREG; } - public isDirectory() { + public isDirectory(): boolean { return (this.mode & S_IFMT) === S_IFDIR; } - public isSymbolicLink() { + public isSymbolicLink(): boolean { return (this.mode & S_IFMT) === S_IFLNK; } - public isBlockDevice() { + public isBlockDevice(): boolean { return (this.mode & S_IFMT) === S_IFBLK; } - public isCharacterDevice() { + public isCharacterDevice(): boolean { return (this.mode & S_IFMT) === S_IFCHR; } - public isFIFO() { + public isFIFO(): boolean { return (this.mode & S_IFMT) === S_IFIFO; } - public isSocket() { + public isSocket(): boolean { return (this.mode & S_IFMT) === S_IFSOCK; } } -export const IOErrorMessages = Object.freeze({ +export const IOErrorMessages: Readonly<{ + EACCES: "access denied"; + EIO: "an I/O error occurred"; + ENOENT: "no such file or directory"; + EEXIST: "file already exists"; + ELOOP: "too many symbolic links encountered"; + ENOTDIR: "no such directory"; + EISDIR: "path is a directory"; + EBADF: "invalid file descriptor"; + EINVAL: "invalid value"; + ENOTEMPTY: "directory not empty"; + EPERM: "operation not permitted"; + EROFS: "file system is read-only"; +}> = Object.freeze({ EACCES: "access denied", EIO: "an I/O error occurred", ENOENT: "no such file or directory", @@ -1369,7 +1382,7 @@ export const IOErrorMessages = Object.freeze({ EROFS: "file system is read-only", }); -export function createIOError(code: keyof typeof IOErrorMessages, details = "") { +export function createIOError(code: keyof typeof IOErrorMessages, details = ""): NodeJS.ErrnoException { const err: NodeJS.ErrnoException = new Error(`${code}: ${IOErrorMessages[code]} ${details}`); err.code = code; if (Error.captureStackTrace) Error.captureStackTrace(err, createIOError); diff --git a/src/harness/vpathUtil.ts b/src/harness/vpathUtil.ts index c7c1ef4ce47c8..6fa2e5ed1386f 100644 --- a/src/harness/vpathUtil.ts +++ b/src/harness/vpathUtil.ts @@ -102,32 +102,32 @@ function validateComponents(components: string[], flags: ValidationFlags, hasTra return true; } -export function validate(path: string, flags: ValidationFlags = ValidationFlags.RelativeOrAbsolute) { +export function validate(path: string, flags: ValidationFlags = ValidationFlags.RelativeOrAbsolute): string { const components = parse(path); const trailing = hasTrailingSeparator(path); if (!validateComponents(components, flags, trailing)) throw vfs.createIOError("ENOENT"); return components.length > 1 && trailing ? format(reduce(components)) + sep : format(reduce(components)); } -export function isDeclaration(path: string) { +export function isDeclaration(path: string): boolean { return ts.isDeclarationFileName(path); } -export function isSourceMap(path: string) { +export function isSourceMap(path: string): boolean { return extname(path, ".map", /*ignoreCase*/ false).length > 0; } const javaScriptSourceMapExtensions: readonly string[] = [".js.map", ".jsx.map"]; -export function isJavaScriptSourceMap(path: string) { +export function isJavaScriptSourceMap(path: string): boolean { return extname(path, javaScriptSourceMapExtensions, /*ignoreCase*/ false).length > 0; } -export function isJson(path: string) { +export function isJson(path: string): boolean { return extname(path, ".json", /*ignoreCase*/ false).length > 0; } -export function isDefaultLibrary(path: string) { +export function isDefaultLibrary(path: string): boolean { return isDeclaration(path) && basename(path).startsWith("lib."); } diff --git a/src/harness/watchUtils.ts b/src/harness/watchUtils.ts index 194a4d3225b2d..6e74673b2dd68 100644 --- a/src/harness/watchUtils.ts +++ b/src/harness/watchUtils.ts @@ -186,7 +186,7 @@ export function createWatchUtils( } } -export function serializeMultiMap(baseline: string[], caption: string, multiMap: MultiMap, serialized: Map | undefined) { +export function serializeMultiMap(baseline: string[], caption: string, multiMap: MultiMap, serialized: Map | undefined): Map | undefined { let hasChange = diffMap(baseline, caption, multiMap, serialized, /*deleted*/ false); hasChange = diffMap(baseline, caption, serialized, multiMap, /*deleted*/ true) || hasChange; if (hasChange) { From 5c13c8d42cb456a271ebc313eddba9474857d84f Mon Sep 17 00:00:00 2001 From: Isabel Duan Date: Tue, 13 Aug 2024 00:31:54 -0700 Subject: [PATCH 08/27] lint --- src/compiler/commandLineParser.ts | 4 ++-- src/compiler/core.ts | 4 ++-- src/jsTyping/jsTyping.ts | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index a7906a9a08f06..22ea16af8af26 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -138,7 +138,7 @@ const jsxOptionMap = new Map(Object.entries({ })); /** @internal */ -export const inverseJsxOptionMap: Map = new Map(mapIterator(jsxOptionMap.entries(), ([key, value]: [string, JsxEmit]) => ["" + value, key] as const)); +export const inverseJsxOptionMap: Map = 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 @@ -256,7 +256,7 @@ export const libs: string[] = libEntries.map(entry => entry[0]); * * @internal */ -export const libMap: Map = new Map(libEntries); +export const libMap: Map = new Map(libEntries); // Watch related options diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 9dac1832e5266..97089a62215fb 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -505,10 +505,10 @@ export function mapDefined(array: readonly T[] | undefined, mapFn: (x: T, } /** @internal */ -export function* mapDefinedIterator(iter: Iterable, mapFn: (x: T) => U | undefined): Generator { +export function* mapDefinedIterator(iter: Iterable, mapFn: (x: T) => U | undefined): Generator, void, unknown> { for (const x of iter) { const value = mapFn(x); - if (value !== undefined) { + if (value !== undefined && value !== null) { // eslint-disable-line no-restricted-syntax yield value; } } diff --git a/src/jsTyping/jsTyping.ts b/src/jsTyping/jsTyping.ts index 3aaba439ec081..7e3a358c7e161 100644 --- a/src/jsTyping/jsTyping.ts +++ b/src/jsTyping/jsTyping.ts @@ -117,7 +117,7 @@ const prefixedNodeCoreModuleList = unprefixedNodeCoreModuleList.map(name => `nod export const nodeCoreModuleList: readonly string[] = [...unprefixedNodeCoreModuleList, ...prefixedNodeCoreModuleList]; /** @internal */ -export const nodeCoreModules: Set = new Set(nodeCoreModuleList); +export const nodeCoreModules: Set = new Set(nodeCoreModuleList); /** @internal */ export function nonRelativeModuleNameForTypingCache(moduleName: string): string { From 4e5524b0123092fcb22f107fc1c76fa13c883a02 Mon Sep 17 00:00:00 2001 From: Isabel Duan Date: Tue, 13 Aug 2024 00:36:35 -0700 Subject: [PATCH 09/27] update generateDiagnosticMessages script for eslint --- scripts/processDiagnosticMessages.mjs | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/processDiagnosticMessages.mjs b/scripts/processDiagnosticMessages.mjs index 35e1e8f4bb149..4e41f43c5946e 100644 --- a/scripts/processDiagnosticMessages.mjs +++ b/scripts/processDiagnosticMessages.mjs @@ -92,6 +92,7 @@ function buildInfoFileOutput(messageTable, inputFilePathRel) { " return { code, category, key, message, reportsUnnecessary, elidedInCompatabilityPyramid, reportsDeprecated };", "}", "", + "/* eslint-disable @typescript-eslint/no-unnecessary-type-assertion*/", // type assertions are needed for isolatedDeclarations "/** @internal */", "export const Diagnostics = {", ]; From 0bd2108eff3fa5ea45dabb692a53706e0f574416 Mon Sep 17 00:00:00 2001 From: Isabel Duan Date: Tue, 13 Aug 2024 00:55:22 -0700 Subject: [PATCH 10/27] generated codefixes harness 2 --- src/harness/client.ts | 25 +- src/harness/collectionsImpl.ts | 28 +- src/harness/compilerImpl.ts | 2 +- src/harness/documentsUtil.ts | 8 +- src/harness/evaluatorImpl.ts | 4 +- src/harness/fakesHosts.ts | 72 ++--- src/harness/fourslashImpl.ts | 244 ++++++++-------- src/harness/fourslashInterfaceImpl.ts | 356 +++++++++++++---------- src/harness/harnessUtils.ts | 24 +- src/harness/projectServiceStateLogger.ts | 2 +- src/harness/runnerbase.ts | 8 +- src/harness/util.ts | 8 +- 12 files changed, 429 insertions(+), 352 deletions(-) diff --git a/src/harness/client.ts b/src/harness/client.ts index e1daecdc82dec..aeff3d2cd04ac 100644 --- a/src/harness/client.ts +++ b/src/harness/client.ts @@ -203,7 +203,7 @@ export class SessionClient implements LanguageService { } /** @internal */ - configure(preferences: UserPreferences) { + configure(preferences: UserPreferences): void { this.preferences = preferences; const args: protocol.ConfigureRequestArguments = { preferences }; const request = this.processRequest(protocol.CommandTypes.Configure, args); @@ -211,14 +211,14 @@ export class SessionClient implements LanguageService { } /** @internal */ - setFormattingOptions(formatOptions: FormatCodeSettings) { + setFormattingOptions(formatOptions: FormatCodeSettings): void { const args: protocol.ConfigureRequestArguments = { formatOptions }; const request = this.processRequest(protocol.CommandTypes.Configure, args); this.processResponse(request, /*expectEmptyBody*/ true); } /** @internal */ - setCompilerOptionsForInferredProjects(options: protocol.CompilerOptions) { + setCompilerOptionsForInferredProjects(options: protocol.CompilerOptions): void { const args: protocol.SetCompilerOptionsForInferredProjectsArgs = { options }; const request = this.processRequest(protocol.CommandTypes.CompilerOptionsForInferredProjects, args); this.processResponse(request, /*expectEmptyBody*/ false); @@ -247,7 +247,10 @@ export class SessionClient implements LanguageService { this.processResponse(request, /*expectEmptyBody*/ true); } - toLineColumnOffset(fileName: string, position: number) { + toLineColumnOffset(fileName: string, position: number): { + line: number; + character: number; + } { const { line, offset } = this.positionToOneBasedLineOffset(fileName, position); return { line, character: offset }; } @@ -580,7 +583,7 @@ export class SessionClient implements LanguageService { return renameInfo; } - getSmartSelectionRange() { + getSmartSelectionRange(): never { return notImplemented(); } @@ -766,9 +769,9 @@ export class SessionClient implements LanguageService { ({ fixName, description, changes: this.convertChanges(changes, file), commands: commands as CodeActionCommand[], fixId, fixAllDescription })); } - getCombinedCodeFix = notImplemented; + getCombinedCodeFix: typeof notImplemented = notImplemented; - applyCodeActionCommand = notImplemented; + applyCodeActionCommand: typeof notImplemented = notImplemented; provideInlayHints(file: string, span: TextSpan): InlayHint[] { const { start, length } = span; @@ -796,7 +799,7 @@ export class SessionClient implements LanguageService { }); } - mapCode = notImplemented; + mapCode: typeof notImplemented = notImplemented; private createFileLocationOrRangeRequestArgs(positionOrRange: number | TextRange, fileName: string): protocol.FileLocationOrRangeRequestArgs { return typeof positionOrRange === "number" @@ -902,7 +905,7 @@ export class SessionClient implements LanguageService { return notImplemented(); } - getEditsForFileRename() { + getEditsForFileRename(): never { return notImplemented(); } @@ -992,7 +995,7 @@ export class SessionClient implements LanguageService { }; } - provideCallHierarchyIncomingCalls(fileName: string, position: number) { + provideCallHierarchyIncomingCalls(fileName: string, position: number): CallHierarchyIncomingCall[] { const args = this.createFileLocationRequestArgs(fileName, position); const request = this.processRequest(protocol.CommandTypes.ProvideCallHierarchyIncomingCalls, args); const response = this.processResponse(request); @@ -1006,7 +1009,7 @@ export class SessionClient implements LanguageService { }; } - provideCallHierarchyOutgoingCalls(fileName: string, position: number) { + provideCallHierarchyOutgoingCalls(fileName: string, position: number): CallHierarchyOutgoingCall[] { const args = this.createFileLocationRequestArgs(fileName, position); const request = this.processRequest(protocol.CommandTypes.ProvideCallHierarchyOutgoingCalls, args); const response = this.processResponse(request); diff --git a/src/harness/collectionsImpl.ts b/src/harness/collectionsImpl.ts index 6c0da4353a987..d32fefb2c14a9 100644 --- a/src/harness/collectionsImpl.ts +++ b/src/harness/collectionsImpl.ts @@ -23,11 +23,11 @@ export class SortedMap { } } - public get size() { + public get size(): number { return this._keys.length; } - public get comparer() { + public get comparer(): (a: K, b: K) => number { return this._comparer; } @@ -35,11 +35,11 @@ export class SortedMap { return "SortedMap"; } - public has(key: K) { + public has(key: K): boolean { return ts.binarySearch(this._keys, key, ts.identity, this._comparer) >= 0; } - public get(key: K) { + public get(key: K): V | undefined { const index = ts.binarySearch(this._keys, key, ts.identity, this._comparer); return index >= 0 ? this._values[index] : undefined; } @@ -49,7 +49,7 @@ export class SortedMap { return index >= 0 ? [this._keys[index], this._values[index]] : undefined; } - public set(key: K, value: V) { + public set(key: K, value: V): this { const index = ts.binarySearch(this._keys, key, ts.identity, this._comparer); if (index >= 0) { this._values[index] = value; @@ -64,7 +64,7 @@ export class SortedMap { return this; } - public delete(key: K) { + public delete(key: K): boolean { const index = ts.binarySearch(this._keys, key, ts.identity, this._comparer); if (index >= 0) { this.writePreamble(); @@ -77,7 +77,7 @@ export class SortedMap { return false; } - public clear() { + public clear(): void { if (this.size > 0) { this.writePreamble(); this._keys.length = 0; @@ -87,7 +87,7 @@ export class SortedMap { } } - public forEach(callback: (value: V, key: K, collection: this) => void, thisArg?: any) { + public forEach(callback: (value: V, key: K, collection: this) => void, thisArg?: any): void { const keys = this._keys; const values = this._values; const indices = this.getIterationOrder(); @@ -112,7 +112,7 @@ export class SortedMap { } } - public *keys() { + public *keys(): Generator { const keys = this._keys; const indices = this.getIterationOrder(); const version = this._version; @@ -135,7 +135,7 @@ export class SortedMap { return undefined; } - public *values() { + public *values(): Generator { const values = this._values; const indices = this.getIterationOrder(); const version = this._version; @@ -158,7 +158,7 @@ export class SortedMap { return undefined; } - public *entries() { + public *entries(): Generator<[K, V], undefined, unknown> { const keys = this._keys; const values = this._values; const indices = this.getIterationOrder(); @@ -184,7 +184,7 @@ export class SortedMap { return undefined; } - public [Symbol.iterator]() { + public [Symbol.iterator](): Generator<[K, V], undefined, unknown> { return this.entries(); } @@ -255,7 +255,7 @@ export class Metadata { return this._size; } - public get parent() { + public get parent(): Metadata | undefined { return this._parent; } @@ -292,7 +292,7 @@ export class Metadata { this._version++; } - public forEach(callback: (value: any, key: string, map: this) => void) { + public forEach(callback: (value: any, key: string, map: this) => void): void { for (const key in this._map) { callback(this._map[key], Metadata._unescapeKey(key), this); } diff --git a/src/harness/compilerImpl.ts b/src/harness/compilerImpl.ts index 90393622d9308..6e49f20090703 100644 --- a/src/harness/compilerImpl.ts +++ b/src/harness/compilerImpl.ts @@ -225,7 +225,7 @@ export class CompilationResult { return vpath.changeExtension(path, ext); } - public getNumberOfJsFiles(includeJson: boolean) { + public getNumberOfJsFiles(includeJson: boolean): number { if (includeJson) { return this.js.size; } diff --git a/src/harness/documentsUtil.ts b/src/harness/documentsUtil.ts index 8a96d4d290f3e..fb22a342de2eb 100644 --- a/src/harness/documentsUtil.ts +++ b/src/harness/documentsUtil.ts @@ -22,7 +22,7 @@ export class TextDocument { return this._lineStarts || (this._lineStarts = ts.computeLineStarts(this.text)); } - public static fromTestFile(file: Harness.Compiler.TestFile) { + public static fromTestFile(file: Harness.Compiler.TestFile): TextDocument { return new TextDocument( file.unitName, file.content, @@ -31,7 +31,7 @@ export class TextDocument { ); } - public asTestFile() { + public asTestFile(): Harness.Compiler.TestFile { return this._testFile || (this._testFile = { unitName: this.file, content: this.text, @@ -140,7 +140,7 @@ export class SourceMap { this.mappings = mappings; } - public static getUrl(text: string) { + public static getUrl(text: string): string | undefined { let match: RegExpExecArray | null; // eslint-disable-line no-restricted-syntax let lastMatch: RegExpExecArray | undefined; while (match = SourceMap._sourceMappingURLRegExp.exec(text)) { @@ -149,7 +149,7 @@ export class SourceMap { return lastMatch ? lastMatch[1] : undefined; } - public static fromUrl(url: string) { + public static fromUrl(url: string): SourceMap | undefined { const match = SourceMap._dataURLRegExp.exec(url); return match ? new SourceMap(/*mapFile*/ undefined, ts.sys.base64decode!(match[1])) : undefined; } diff --git a/src/harness/evaluatorImpl.ts b/src/harness/evaluatorImpl.ts index 9fdeed5b6cdc7..30960d0321b4e 100644 --- a/src/harness/evaluatorImpl.ts +++ b/src/harness/evaluatorImpl.ts @@ -33,7 +33,7 @@ for (const symbolName of symbolNames) { } } -export function evaluateTypeScript(source: string | { files: vfs.FileSet; rootFiles: string[]; main: string; }, options?: ts.CompilerOptions, globals?: Record) { +export function evaluateTypeScript(source: string | { files: vfs.FileSet; rootFiles: string[]; main: string; }, options?: ts.CompilerOptions, globals?: Record): any { 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 = { @@ -62,7 +62,7 @@ export function evaluateTypeScript(source: string | { files: vfs.FileSet; rootFi return loader.import(output.file); } -export function evaluateJavaScript(sourceText: string, globals?: Record, sourceFile = sourceFileJs) { +export function evaluateJavaScript(sourceText: string, globals?: Record, sourceFile: string = sourceFileJs): any { globals = { Symbol: FakeSymbol, ...globals }; const fs = new vfs.FileSystem(/*ignoreCase*/ false, { files: { [sourceFile]: sourceText } }); return new CommonJsLoader(fs, globals).import(sourceFile); diff --git a/src/harness/fakesHosts.ts b/src/harness/fakesHosts.ts index cbd2a285080a4..b07036168082a 100644 --- a/src/harness/fakesHosts.ts +++ b/src/harness/fakesHosts.ts @@ -41,19 +41,19 @@ export class System implements ts.System { } private testTerminalWidth = Number.parseInt(this.getEnvironmentVariable("TS_TEST_TERMINAL_WIDTH")); - getWidthOfTerminal = Number.isNaN(this.testTerminalWidth) ? undefined : () => this.testTerminalWidth; + getWidthOfTerminal: (() => number) | undefined = Number.isNaN(this.testTerminalWidth) ? undefined : () => this.testTerminalWidth; // Pretty output writeOutputIsTTY() { return true; } - public write(message: string) { + public write(message: string): void { if (ts.Debug.isDebugging) console.log(message); this.output.push(message); } - public readFile(path: string) { + public readFile(path: string): string | undefined { try { const content = this.vfs.readFileSync(path, "utf8"); return content === undefined ? undefined : Utils.removeByteOrderMark(content); @@ -68,16 +68,16 @@ export class System implements ts.System { this.vfs.writeFileSync(path, writeByteOrderMark ? Utils.addUTF8ByteOrderMark(data) : data); } - public deleteFile(path: string) { + public deleteFile(path: string): void { this.vfs.unlinkSync(path); } - public fileExists(path: string) { + public fileExists(path: string): boolean { const stats = this._getStats(path); return stats ? stats.isFile() : false; } - public directoryExists(path: string) { + public directoryExists(path: string): boolean { const stats = this._getStats(path); return stats ? stats.isDirectory() : false; } @@ -86,11 +86,11 @@ export class System implements ts.System { this.vfs.mkdirpSync(path); } - public getCurrentDirectory() { + public getCurrentDirectory(): string { return this.vfs.cwd(); } - public getDirectories(path: string) { + public getDirectories(path: string): string[] { const result: string[] = []; try { for (const file of this.vfs.readdirSync(path)) { @@ -128,31 +128,31 @@ export class System implements ts.System { return { files, directories }; } - public exit(exitCode?: number) { + public exit(exitCode?: number): void { this.exitCode = exitCode; throw processExitSentinel; } - public getFileSize(path: string) { + public getFileSize(path: string): number { const stats = this._getStats(path); return stats && stats.isFile() ? stats.size : 0; } - public resolvePath(path: string) { + public resolvePath(path: string): string { return vpath.resolve(this.vfs.cwd(), path); } - public getExecutingFilePath() { + public getExecutingFilePath(): string { if (this._executingFilePath === undefined) return ts.notImplemented(); return this._executingFilePath; } - public getModifiedTime(path: string) { + public getModifiedTime(path: string): Date { const stats = this._getStats(path); return stats ? stats.mtime : undefined!; // TODO: GH#18217 } - public setModifiedTime(path: string, time: Date) { + public setModifiedTime(path: string, time: Date): void { try { this.vfs.utimesSync(path, time, time); } @@ -163,7 +163,7 @@ export class System implements ts.System { return `${ts.generateDjb2Hash(data)}-${data}`; } - public realpath(path: string) { + public realpath(path: string): string { try { return this.vfs.realpathSync(path); } @@ -185,7 +185,7 @@ export class System implements ts.System { } } - now() { + now(): Date { return new Date(this.vfs.time()); } } @@ -201,11 +201,11 @@ export class ParseConfigHost implements ts.ParseConfigHost { this.sys = sys; } - public get vfs() { + public get vfs(): vfs.FileSystem { return this.sys.vfs; } - public get useCaseSensitiveFileNames() { + public get useCaseSensitiveFileNames(): boolean { return this.sys.useCaseSensitiveFileNames; } @@ -247,7 +247,7 @@ export class CompilerHost implements ts.CompilerHost { public readonly outputs: documents.TextDocument[] = []; private readonly _outputsMap: collections.SortedMap; public readonly traces: string[] = []; - public readonly shouldAssertInvariants = !Harness.lightMode; + public readonly shouldAssertInvariants: boolean = !Harness.lightMode; public readonly jsDocParsingMode: ts.JSDocParsingMode | undefined; private _setParentNodes: boolean; @@ -255,7 +255,7 @@ export class CompilerHost implements ts.CompilerHost { private _parseConfigHost: ParseConfigHost | undefined; private _newLine: string; - constructor(sys: System | vfs.FileSystem, options = ts.getDefaultCompilerOptions(), setParentNodes = false, jsDocParsingMode?: ts.JSDocParsingMode) { + constructor(sys: System | vfs.FileSystem, options: ts.CompilerOptions = ts.getDefaultCompilerOptions(), setParentNodes = false, jsDocParsingMode?: ts.JSDocParsingMode) { if (sys instanceof vfs.FileSystem) sys = new System(sys); this.sys = sys; this.defaultLibLocation = sys.vfs.meta.get("defaultLibLocation") || ""; @@ -266,11 +266,11 @@ export class CompilerHost implements ts.CompilerHost { this.jsDocParsingMode = jsDocParsingMode; } - public get vfs() { + public get vfs(): vfs.FileSystem { return this.sys.vfs; } - public get parseConfigHost() { + public get parseConfigHost(): ParseConfigHost { return this._parseConfigHost || (this._parseConfigHost = new ParseConfigHost(this.sys)); } @@ -290,7 +290,7 @@ export class CompilerHost implements ts.CompilerHost { return this.sys.useCaseSensitiveFileNames ? fileName : fileName.toLowerCase(); } - public deleteFile(fileName: string) { + public deleteFile(fileName: string): void { this.sys.deleteFile(fileName); } @@ -302,11 +302,11 @@ export class CompilerHost implements ts.CompilerHost { return this.sys.directoryExists(directoryName); } - public getModifiedTime(fileName: string) { + public getModifiedTime(fileName: string): Date { return this.sys.getModifiedTime(fileName); } - public setModifiedTime(fileName: string, time: Date) { + public setModifiedTime(fileName: string, time: Date): void { return this.sys.setModifiedTime(fileName, time); } @@ -322,7 +322,7 @@ export class CompilerHost implements ts.CompilerHost { return this.sys.readFile(path); } - public writeFile(fileName: string, content: string, writeByteOrderMark: boolean) { + public writeFile(fileName: string, content: string, writeByteOrderMark: boolean): void { if (writeByteOrderMark) content = Utils.addUTF8ByteOrderMark(content); this.sys.writeFile(fileName, content); @@ -537,7 +537,7 @@ function diagnosticToText({ kind, diagnostic: { relatedInformation, ...diagnosti export const version = "FakeTSVersion"; -export function patchHostForBuildInfoReadWrite(sys: T) { +export function patchHostForBuildInfoReadWrite(sys: T): T { const originalReadFile = sys.readFile; sys.readFile = (path, encoding) => { const value = originalReadFile.call(sys, path, encoding); @@ -551,7 +551,7 @@ export function patchHostForBuildInfoReadWrite(sys: T) { return patchHostForBuildInfoWrite(sys, version); } -export function patchHostForBuildInfoWrite(sys: T, version: string) { +export function patchHostForBuildInfoWrite(sys: T, version: string): T { const originalWrite = sys.write; sys.write = msg => originalWrite.call(sys, msg.replace(ts.version, version)); const originalWriteFile = sys.writeFile; @@ -576,7 +576,7 @@ export class SolutionBuilderHost extends CompilerHost implements ts.SolutionBuil this.createProgram = createProgram || ts.createEmitAndSemanticDiagnosticsBuilderProgram as unknown as ts.CreateProgram; } - static create(sys: System | vfs.FileSystem, options?: ts.CompilerOptions, setParentNodes?: boolean, createProgram?: ts.CreateProgram, jsDocParsingMode?: ts.JSDocParsingMode) { + static create(sys: System | vfs.FileSystem, options?: ts.CompilerOptions, setParentNodes?: boolean, createProgram?: ts.CreateProgram, jsDocParsingMode?: ts.JSDocParsingMode): SolutionBuilderHost { const host = new SolutionBuilderHost(sys, options, setParentNodes, createProgram, jsDocParsingMode); patchHostForBuildInfoReadWrite(host.sys); return host; @@ -588,19 +588,19 @@ export class SolutionBuilderHost extends CompilerHost implements ts.SolutionBuil diagnostics: SolutionBuilderDiagnostic[] = []; - reportDiagnostic(diagnostic: ts.Diagnostic) { + reportDiagnostic(diagnostic: ts.Diagnostic): void { this.diagnostics.push({ kind: DiagnosticKind.Error, diagnostic }); } - reportSolutionBuilderStatus(diagnostic: ts.Diagnostic) { + reportSolutionBuilderStatus(diagnostic: ts.Diagnostic): void { this.diagnostics.push({ kind: DiagnosticKind.Status, diagnostic }); } - clearDiagnostics() { + clearDiagnostics(): void { this.diagnostics.length = 0; } - assertDiagnosticMessages(...expectedDiagnostics: ExpectedDiagnostic[]) { + assertDiagnosticMessages(...expectedDiagnostics: ExpectedDiagnostic[]): void { const actual = this.diagnostics.slice().map(diagnosticToText); const expected = expectedDiagnostics.map(expectedDiagnosticToText); assert.deepEqual( @@ -612,7 +612,7 @@ Expected: ${JSON.stringify(expected, /*replacer*/ undefined, " ")}`, ); } - assertErrors(...expectedDiagnostics: ExpectedErrorDiagnostic[]) { + assertErrors(...expectedDiagnostics: ExpectedErrorDiagnostic[]): void { const actual = this.diagnostics.filter(d => d.kind === DiagnosticKind.Error).map(diagnosticToText); const expected = expectedDiagnostics.map(expectedDiagnosticToText); assert.deepEqual( @@ -625,7 +625,7 @@ Actual All:: ${JSON.stringify(this.diagnostics.slice().map(diagnosticToText), /* ); } - printDiagnostics(header = "== Diagnostics ==") { + printDiagnostics(header = "== Diagnostics =="): void { const out = ts.createDiagnosticReporter(ts.sys); ts.sys.write(header + "\r\n"); for (const { diagnostic } of this.diagnostics) { @@ -633,7 +633,7 @@ Actual All:: ${JSON.stringify(this.diagnostics.slice().map(diagnosticToText), /* } } - now() { + now(): Date { return this.sys.now(); } } diff --git a/src/harness/fourslashImpl.ts b/src/harness/fourslashImpl.ts index 4d3d6cea32e69..ae2c953fbfb53 100644 --- a/src/harness/fourslashImpl.ts +++ b/src/harness/fourslashImpl.ts @@ -173,7 +173,7 @@ export class TestCancellationToken implements ts.HostCancellationToken { } } -export function verifyOperationIsCancelled(f: () => void) { +export function verifyOperationIsCancelled(f: () => void): void { try { f(); } @@ -505,7 +505,7 @@ export class TestState { else this.baselineFromTest.push({ command, actual, ext }); } - baselineTest() { + baselineTest(): void { if (this.baselineFromTest) { Harness.Baseline.runBaseline( this.getBaselineFileNameForContainingTestFile(this.baselineFromTest[0].ext), @@ -514,7 +514,7 @@ export class TestState { } } - baselineTsserverLog() { + baselineTsserverLog(): void { if (this.logger) { Harness.Baseline.runBaseline( `tsserver/fourslashServer/${ts.getBaseFileName(this.originalInputFileName).replace(".ts", ".js")}`, @@ -532,7 +532,7 @@ export class TestState { } // Entry points from fourslash.ts - public goToMarker(name: string | Marker = "") { + public goToMarker(name: string | Marker = ""): void { const marker = ts.isString(name) ? this.getMarkerByName(name) : name; if (this.activeFile.fileName !== marker.fileName) { this.openFile(marker.fileName); @@ -553,7 +553,7 @@ export class TestState { this.goToRangeStart(markerOrRange); } - public goToEachMarker(markers: readonly Marker[], action: (marker: Marker, index: number) => void) { + public goToEachMarker(markers: readonly Marker[], action: (marker: Marker, index: number) => void): void { assert(markers.length); for (let i = 0; i < markers.length; i++) { this.goToMarker(markers[i]); @@ -561,7 +561,7 @@ export class TestState { } } - public goToEachRange(action: (range: Range) => void) { + public goToEachRange(action: (range: Range) => void): void { const ranges = this.getRanges(); assert(ranges.length); for (const range of ranges) { @@ -578,7 +578,7 @@ export class TestState { })!; } - public goToPosition(positionOrLineAndCharacter: number | ts.LineAndCharacter) { + public goToPosition(positionOrLineAndCharacter: number | ts.LineAndCharacter): void { const pos = typeof positionOrLineAndCharacter === "number" ? positionOrLineAndCharacter : this.languageServiceAdapterHost.lineAndCharacterToPosition(this.activeFile.fileName, positionOrLineAndCharacter); @@ -586,7 +586,7 @@ export class TestState { this.selectionEnd = -1; } - public select(startMarker: string, endMarker: string) { + public select(startMarker: string, endMarker: string): void { const start = this.getMarkerByName(startMarker), end = this.getMarkerByName(endMarker); ts.Debug.assert(start.fileName === end.fileName); if (this.activeFile.fileName !== start.fileName) { @@ -596,7 +596,7 @@ export class TestState { this.selectionEnd = end.position; } - public selectAllInFile(fileName: string) { + public selectAllInFile(fileName: string): void { this.openFile(fileName); this.goToPosition(0); this.selectionEnd = this.activeFile.content.length; @@ -607,13 +607,13 @@ export class TestState { this.selectionEnd = range.end; } - public selectLine(index: number) { + public selectLine(index: number): void { 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) { + public moveCaretRight(count = 1): void { this.currentCaretPosition += count; this.currentCaretPosition = Math.min(this.currentCaretPosition, this.getFileContent(this.activeFile.fileName).length); this.selectionEnd = -1; @@ -628,7 +628,7 @@ export class TestState { this.languageServiceAdapterHost.openFile(fileToOpen.fileName, content, scriptKindName); } - public verifyErrorExistsBetweenMarkers(startMarkerName: string, endMarkerName: string, shouldExist: boolean) { + public verifyErrorExistsBetweenMarkers(startMarkerName: string, endMarkerName: string, shouldExist: boolean): void { 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; @@ -641,7 +641,7 @@ export class TestState { } } - public verifyOrganizeImports(newContent: string, mode?: ts.OrganizeImportsMode, preferences?: ts.UserPreferences) { + public verifyOrganizeImports(newContent: string, mode?: ts.OrganizeImportsMode, preferences?: ts.UserPreferences): void { const changes = this.languageService.organizeImports({ fileName: this.activeFile.fileName, type: "file", mode }, this.formatCodeSettings, preferences); this.applyChanges(changes); this.verifyFileContent(this.activeFile.fileName, newContent); @@ -682,7 +682,7 @@ export class TestState { }); } - public verifyErrorExistsAfterMarker(markerName: string, shouldExist: boolean, after: boolean) { + public verifyErrorExistsAfterMarker(markerName: string, shouldExist: boolean, after: boolean): void { const marker: Marker = this.getMarkerByName(markerName); let predicate: (errorMinChar: number, errorLimChar: number, startPos: number, endPos: number | undefined) => boolean; @@ -744,7 +744,7 @@ export class TestState { return "global"; } - public verifyNoErrors() { + public verifyNoErrors(): void { ts.forEachKey(this.inputFiles, fileName => { if ( !ts.isAnySupportedFileExtension(fileName) @@ -763,7 +763,7 @@ export class TestState { }); } - public verifyErrorExistsAtRange(range: Range, code: number, expectedMessage?: string) { + public verifyErrorExistsAtRange(range: Range, code: number, expectedMessage?: string): void { const span = ts.createTextSpanFromRange(range); const hasMatchingError = ts.some( this.getDiagnostics(range.fileName), @@ -779,7 +779,7 @@ export class TestState { } } - public verifyNumberOfErrorsInCurrentFile(expected: number) { + public verifyNumberOfErrorsInCurrentFile(expected: number): void { const errors = this.getDiagnostics(this.activeFile.fileName); const actual = errors.length; @@ -791,7 +791,7 @@ export class TestState { } } - public verifyEval(expr: string, value: any) { + public verifyEval(expr: string, value: any): void { const emit = this.languageService.getEmitOutput(this.activeFile.fileName); if (emit.outputFiles.length !== 1) { throw new Error("Expected exactly one output from emit of " + this.activeFile.fileName); @@ -871,7 +871,7 @@ export class TestState { public baselineGoToDefinition( markerOrRange: MarkerOrNameOrRange[] | undefined, rangeText: string[] | undefined, - ) { + ): void { this.baselineEachMarkerOrRange("goToDefinition", markerOrRange, rangeText, markerOrRange => this.baselineGoToDefs( "/*GOTO DEF*/", @@ -883,7 +883,7 @@ export class TestState { public baselineGetDefinitionAtPosition( markerOrRange: MarkerOrNameOrRange[] | undefined, rangeText: string[] | undefined, - ) { + ): void { this.baselineEachMarkerOrRange("getDefinitionAtPosition", markerOrRange, rangeText, markerOrRange => this.baselineGoToDefs( "/*GOTO DEF POS*/", @@ -895,7 +895,7 @@ export class TestState { public baselineGoToSourceDefinition( markerOrRange: MarkerOrNameOrRange[] | undefined, rangeText: string[] | undefined, - ) { + ): void { if (this.testType !== FourSlashTestType.Server) { this.raiseError("goToSourceDefinition may only be used in fourslash/server tests."); } @@ -912,7 +912,7 @@ export class TestState { public baselineGoToType( markerOrRange: MarkerOrNameOrRange[] | undefined, rangeText: string[] | undefined, - ) { + ): void { this.baselineEachMarkerOrRange("goToType", markerOrRange, rangeText, markerOrRange => this.baselineGoToDefs( "/*GOTO TYPE*/", @@ -924,7 +924,7 @@ export class TestState { public baselineGoToImplementation( markerOrRange: MarkerOrNameOrRange[] | undefined, rangeText: string[] | undefined, - ) { + ): void { this.baselineEachMarkerOrRange("goToImplementation", markerOrRange, rangeText, markerOrRange => this.baselineGoToDefs( "/*GOTO IMPL*/", @@ -988,7 +988,15 @@ export class TestState { this.baseline("Inlay Hints", annotations.join("\n\n")); } - public verifyCompletions(options: FourSlashInterface.VerifyCompletionsOptions) { + public verifyCompletions(options: FourSlashInterface.VerifyCompletionsOptions): { + andApplyCodeAction: (options: { + name: string; + source: string; + description: string; + newFileContent?: string; + newRangeContent?: string; + }) => void; + } | undefined { if (options.marker === undefined) { return this.verifyCompletionsWorker(options); } @@ -1382,7 +1390,7 @@ export class TestState { public baselineFindAllReferences( markerOrRange: MarkerOrNameOrRange[] | undefined, rangeText: string[] | undefined, - ) { + ): void { this.baselineEachMarkerOrRange("findAllReferences", markerOrRange, rangeText, markerOrRange => { this.goToMarkerOrNameOrRange(markerOrRange); const references = this.findReferencesAtCaret(); @@ -1432,7 +1440,7 @@ export class TestState { }); } - public baselineGetFileReferences(fileNames: string[]) { + public baselineGetFileReferences(fileNames: string[]): void { this.baselineArray("getFileReferences", fileNames, fileName => { const references = this.languageService.getFileReferences(fileName); return `// fileName: ${fileName}\n\n` + this.getBaselineForDocumentSpansWithFileContents( @@ -1810,7 +1818,7 @@ export class TestState { return this.languageService.findReferences(this.activeFile.fileName, this.currentCaretPosition); } - public getSyntacticDiagnostics(expected: readonly FourSlashInterface.Diagnostic[]) { + public getSyntacticDiagnostics(expected: readonly FourSlashInterface.Diagnostic[]): void { const diagnostics = this.languageService.getSyntacticDiagnostics(this.activeFile.fileName); this.testDiagnostics(expected, diagnostics, "error"); } @@ -1819,7 +1827,7 @@ export class TestState { return this.languageService.getSemanticDiagnostics(this.activeFile.fileName); } - public verifySemanticDiagnostics(expected: readonly FourSlashInterface.Diagnostic[]) { + public verifySemanticDiagnostics(expected: readonly FourSlashInterface.Diagnostic[]): void { const diagnostics = this.getSemanticDiagnostics(); this.testDiagnostics(expected, diagnostics, "error"); } @@ -1832,7 +1840,7 @@ export class TestState { ranges: ts.TextRange[], expectedDiagnostics: readonly FourSlashInterface.Diagnostic[] | undefined, expectedRanges: ts.TextRange[] | undefined, - ) { + ): void { const diagnosticsResult = this.languageService.getRegionSemanticDiagnostics(this.activeFile.fileName, ranges); if (diagnosticsResult && expectedDiagnostics) { this.testDiagnostics(expectedDiagnostics, diagnosticsResult.diagnostics, "error"); @@ -1875,14 +1883,14 @@ 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; }[]): void { if (typeof markerName === "string") this.goToMarker(markerName); else this.goToRangeStart(markerName); this.verifyQuickInfoString(expectedText, expectedDocumentation, expectedTags); } - public verifyQuickInfos(namesAndTexts: { [name: string]: string | [string, string]; }) { + public verifyQuickInfos(namesAndTexts: { [name: string]: string | [string, string]; }): void { for (const name in namesAndTexts) { if (ts.hasProperty(namesAndTexts, name)) { const text = namesAndTexts[name]; @@ -1898,7 +1906,7 @@ 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; }[]): void { if (expectedDocumentation === "") { throw new Error("Use 'undefined' instead of empty string for `expectedDocumentation`"); } @@ -1923,7 +1931,7 @@ export class TestState { } } - public verifyQuickInfoDisplayParts(kind: string, kindModifiers: string, textSpan: TextSpan, displayParts: ts.SymbolDisplayPart[], documentation: ts.SymbolDisplayPart[], tags: ts.JSDocTagInfo[] | undefined) { + public verifyQuickInfoDisplayParts(kind: string, kindModifiers: string, textSpan: TextSpan, displayParts: ts.SymbolDisplayPart[], documentation: ts.SymbolDisplayPart[], tags: ts.JSDocTagInfo[] | undefined): void { 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")); @@ -1946,7 +1954,7 @@ export class TestState { markerOrRange: ArrayOrSingle | undefined, rangeText: ArrayOrSingle | undefined, options: FourSlashInterface.RenameOptions | undefined, - ) { + ): void { this.baselineEachMarkerOrRangeArrayOrSingle("findRenameLocations", markerOrRange, rangeText, markerOrRange => { const { fileName, position } = ts.isString(markerOrRange) ? this.getMarkerByName(markerOrRange) : @@ -1991,7 +1999,7 @@ export class TestState { }); } - public verifyQuickInfoExists(negative: boolean) { + public verifyQuickInfoExists(negative: boolean): void { const actualQuickInfo = this.languageService.getQuickInfoAtPosition(this.activeFile.fileName, this.currentCaretPosition); if (negative) { if (actualQuickInfo) { @@ -2005,7 +2013,7 @@ 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)[]): void { if (markers.length) { for (const marker of markers) { this.goToMarker(marker); @@ -2024,7 +2032,7 @@ export class TestState { } } - public verifySignatureHelp(optionses: readonly FourSlashInterface.VerifySignatureHelpOptions[]) { + public verifySignatureHelp(optionses: readonly FourSlashInterface.VerifySignatureHelpOptions[]): void { for (const options of optionses) { if (options.marker === undefined) { this.verifySignatureHelpWorker(options); @@ -2151,7 +2159,7 @@ export class TestState { } } - public verifyRenameInfoFailed(message?: string, preferences?: ts.UserPreferences) { + public verifyRenameInfoFailed(message?: string, preferences?: ts.UserPreferences): void { const allowRenameOfImportPath = preferences?.allowRenameOfImportPath === undefined ? true : preferences.allowRenameOfImportPath; const renameInfo = this.languageService.getRenameInfo(this.activeFile.fileName, this.currentCaretPosition, { ...preferences, allowRenameOfImportPath }); if (renameInfo.canRename) { @@ -2302,11 +2310,11 @@ export class TestState { return resultString; } - public getBreakpointStatementLocation(pos: number) { + public getBreakpointStatementLocation(pos: number): ts.TextSpan | undefined { return this.languageService.getBreakpointStatementAtPosition(this.activeFile.fileName, pos); } - public baselineCurrentFileBreakpointLocations() { + public baselineCurrentFileBreakpointLocations(): void { this.baseline("breakpoints", this.baselineCurrentFileLocations(pos => this.getBreakpointStatementLocation(pos)!)); } @@ -2385,7 +2393,7 @@ export class TestState { return result; } - public baselineSyntacticDiagnostics() { + public baselineSyntacticDiagnostics(): void { const files = this.getCompilerTestFiles(); const result = this.getSyntacticDiagnosticBaselineText(files); this.baseline("Syntax Diagnostics", result); @@ -2398,7 +2406,7 @@ export class TestState { })); } - public baselineSyntacticAndSemanticDiagnostics() { + public baselineSyntacticAndSemanticDiagnostics(): void { const files = ts.filter(this.getCompilerTestFiles(), f => !ts.endsWith(f.unitName, ".json")); const result = this.getSyntacticDiagnosticBaselineText(files) + Harness.IO.newLine() @@ -2423,7 +2431,7 @@ export class TestState { return result; } - public baselineQuickInfo() { + public baselineQuickInfo(): void { const result = ts.arrayFrom(this.testData.markerPositions.entries(), ([name, marker]) => ({ marker: { ...marker, name }, item: this.languageService.getQuickInfoAtPosition(marker.fileName, marker.position), @@ -2441,7 +2449,7 @@ export class TestState { this.baseline("QuickInfo", annotations + "\n\n" + stringify(result)); } - public baselineSignatureHelp() { + public baselineSignatureHelp(): void { const result = ts.arrayFrom(this.testData.markerPositions.entries(), ([name, marker]) => ({ marker: { ...marker, name }, item: this.languageService.getSignatureHelpItems(marker.fileName, marker.position, /*options*/ undefined), @@ -2475,7 +2483,7 @@ export class TestState { this.baseline("SignatureHelp", annotations + "\n\n" + stringify(result)); } - public baselineCompletions(preferences?: ts.UserPreferences) { + public baselineCompletions(preferences?: ts.UserPreferences): void { const result = ts.arrayFrom(this.testData.markerPositions.entries(), ([name, marker]) => { this.goToMarker(marker); const completions = this.getCompletionListAtCaret(preferences); @@ -2582,7 +2590,7 @@ export class TestState { .join("\n\n"); } - public baselineSmartSelection() { + public baselineSmartSelection(): void { const n = "\n"; const markers = this.getMarkers(); const fileContent = this.activeFile.content; @@ -2614,25 +2622,25 @@ export class TestState { this.baseline("Smart Selection", text); } - public printBreakpointLocation(pos: number) { + public printBreakpointLocation(pos: number): void { Harness.IO.log("\n**Pos: " + pos + " " + this.spanInfoToString(this.getBreakpointStatementLocation(pos)!, " ")); } - public printBreakpointAtCurrentLocation() { + public printBreakpointAtCurrentLocation(): void { this.printBreakpointLocation(this.currentCaretPosition); } - public printCurrentParameterHelp() { + public printCurrentParameterHelp(): void { const help = this.languageService.getSignatureHelpItems(this.activeFile.fileName, this.currentCaretPosition, /*options*/ undefined); Harness.IO.log(stringify(help)); } - public printCurrentQuickInfo() { + public printCurrentQuickInfo(): void { const quickInfo = this.languageService.getQuickInfoAtPosition(this.activeFile.fileName, this.currentCaretPosition)!; Harness.IO.log("Quick Info: " + quickInfo.displayParts!.map(part => part.text).join("")); } - public printErrorList() { + public printErrorList(): void { const syntacticErrors = this.languageService.getSyntacticDiagnostics(this.activeFile.fileName); const semanticErrors = this.languageService.getSemanticDiagnostics(this.activeFile.fileName); const errorList = ts.concatenate(syntacticErrors, semanticErrors); @@ -2649,7 +2657,7 @@ export class TestState { } } - public printCurrentFileState(showWhitespace: boolean, makeCaretVisible: boolean) { + public printCurrentFileState(showWhitespace: boolean, makeCaretVisible: boolean): void { for (const file of this.testData.files) { const active = this.activeFile === file; Harness.IO.log(`=== Script (${file.fileName}) ${(active ? "(active, cursor at |)" : "")} ===`); @@ -2664,7 +2672,7 @@ export class TestState { } } - public printCurrentSignatureHelp() { + public printCurrentSignatureHelp(): void { const help = this.getSignatureHelp(ts.emptyOptions)!; Harness.IO.log(stringify(help.items[help.selectedItemIndex])); } @@ -2680,7 +2688,7 @@ export class TestState { }); } - public printCompletionListMembers(preferences: ts.UserPreferences | undefined) { + public printCompletionListMembers(preferences: ts.UserPreferences | undefined): void { const completions = this.getCompletionListAtCaret(preferences); this.printMembersOrCompletions(completions); } @@ -2697,11 +2705,11 @@ export class TestState { Harness.IO.log(formattedEntries.join("\n")); } - public printContext() { + public printContext(): void { ts.forEach(this.languageServiceAdapterHost.getFilenames(), Harness.IO.log); } - public deleteChar(count = 1) { + public deleteChar(count = 1): void { let offset = this.currentCaretPosition; const ch = ""; @@ -2726,12 +2734,12 @@ export class TestState { this.checkPostEditInvariants(); } - public replace(start: number, length: number, text: string) { + public replace(start: number, length: number, text: string): void { this.editScriptAndUpdateMarkers(this.activeFile.fileName, start, start + length, text); this.checkPostEditInvariants(); } - public deleteLineRange(startIndex: number, endIndexInclusive: number) { + public deleteLineRange(startIndex: number, endIndexInclusive: number): void { 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, ""); @@ -2741,7 +2749,7 @@ export class TestState { return { fileName: this.activeFile.fileName, position: this.currentCaretPosition }; } - public deleteCharBehindMarker(count = 1) { + public deleteCharBehindMarker(count = 1): void { let offset = this.currentCaretPosition; const ch = ""; const checkCadence = (count >> 2) + 1; @@ -2762,7 +2770,7 @@ export class TestState { } // Enters lines of text at the current caret position - public type(text: string, highFidelity = false) { + public type(text: string, highFidelity = false): void { let offset = this.currentCaretPosition; const prevChar = " "; const checkCadence = (text.length >> 2) + 1; @@ -2812,7 +2820,7 @@ export class TestState { } // Enters text as if the user had pasted it - public paste(text: string) { + public paste(text: string): void { const start = this.currentCaretPosition; this.editScriptAndUpdateMarkers(this.activeFile.fileName, this.currentCaretPosition, this.currentCaretPosition, text); this.checkPostEditInvariants(); @@ -2909,17 +2917,17 @@ export class TestState { return oldFormatCodeOptions; } - public formatDocument() { + public formatDocument(): void { const edits = this.languageService.getFormattingEditsForDocument(this.activeFile.fileName, this.formatCodeSettings); this.applyEdits(this.activeFile.fileName, edits); } - public formatSelection(start: number, end: number) { + public formatSelection(start: number, end: number): void { const edits = this.languageService.getFormattingEditsForRange(this.activeFile.fileName, start, end, this.formatCodeSettings); this.applyEdits(this.activeFile.fileName, edits); } - public formatOnType(pos: number, key: string) { + public formatOnType(pos: number, key: string): void { const edits = this.languageService.getFormattingEditsAfterKeystroke(this.activeFile.fileName, pos, key, this.formatCodeSettings); this.applyEdits(this.activeFile.fileName, edits); } @@ -2948,16 +2956,16 @@ export class TestState { return text.replace(/\s/g, ""); } - public goToBOF() { + public goToBOF(): void { this.goToPosition(0); } - public goToEOF() { + public goToEOF(): void { const len = this.getFileContent(this.activeFile.fileName).length; this.goToPosition(len); } - public goToRangeStart({ fileName, pos }: Range) { + public goToRangeStart({ fileName, pos }: Range): void { this.openFile(fileName); this.goToPosition(pos); } @@ -2975,7 +2983,7 @@ export class TestState { return this.testData.ranges; } - public getRangesInFile(fileName = this.activeFile.fileName) { + public getRangesInFile(fileName: string = this.activeFile.fileName): Range[] { return this.getRanges().filter(r => r.fileName === fileName); } @@ -2994,7 +3002,7 @@ export class TestState { return this.getFileContent(fileName).slice(pos, end); } - public verifyCaretAtMarker(markerName = "") { + public verifyCaretAtMarker(markerName = ""): void { 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}"`); @@ -3011,7 +3019,7 @@ export class TestState { return this.languageService.getIndentationAtPosition(fileName, position, formatOptions); } - public verifyIndentationAtCurrentPosition(numberOfSpaces: number, indentStyle: ts.IndentStyle = ts.IndentStyle.Smart, baseIndentSize = 0) { + public verifyIndentationAtCurrentPosition(numberOfSpaces: number, indentStyle: ts.IndentStyle = ts.IndentStyle.Smart, baseIndentSize = 0): void { const actual = this.getIndentation(this.activeFile.fileName, this.currentCaretPosition, indentStyle, baseIndentSize); const lineCol = this.getLineColStringAtPosition(this.currentCaretPosition); if (actual !== numberOfSpaces) { @@ -3019,7 +3027,7 @@ export class TestState { } } - 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): void { const actual = this.getIndentation(fileName, position, indentStyle, baseIndentSize); const lineCol = this.getLineColStringAtPosition(position); if (actual !== numberOfSpaces) { @@ -3027,14 +3035,14 @@ export class TestState { } } - public verifyCurrentLineContent(text: string) { + public verifyCurrentLineContent(text: string): void { const actual = this.getCurrentLineContent(); if (actual !== text) { throw new Error("verifyCurrentLineContent\n" + displayExpectedAndActualString(text, actual, /*quoted*/ true)); } } - public verifyCurrentFileContent(text: string) { + public verifyCurrentFileContent(text: string): void { this.verifyFileContent(this.activeFile.fileName, text); } @@ -3052,14 +3060,14 @@ export class TestState { this.verifyFileContent(fileName, before); } - public verifyTextAtCaretIs(text: string) { + public verifyTextAtCaretIs(text: string): void { 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) { + public verifyCurrentNameOrDottedNameSpanText(text: string): undefined { const span = this.languageService.getNameOrDottedNameSpan(this.activeFile.fileName, this.currentCaretPosition, this.currentCaretPosition); if (!span) { return this.raiseError("verifyCurrentNameOrDottedNameSpanText\n" + displayExpectedAndActualString('"' + text + '"', "undefined")); @@ -3075,14 +3083,14 @@ export class TestState { return this.languageService.getNameOrDottedNameSpan(this.activeFile.fileName, pos, pos); } - public baselineCurrentFileNameOrDottedNameSpans() { + public baselineCurrentFileNameOrDottedNameSpans(): void { this.baseline( "NameOrDottedNameSpans", this.baselineCurrentFileLocations(pos => this.getNameOrDottedNameSpan(pos)!), ); } - public printNameOrDottedNameSpans(pos: number) { + public printNameOrDottedNameSpans(pos: number): void { Harness.IO.log(this.spanInfoToString(this.getNameOrDottedNameSpan(pos)!, "**")); } @@ -3183,7 +3191,7 @@ export class TestState { } } - public verifyProjectInfo(expected: string[]) { + public verifyProjectInfo(expected: string[]): void { if (this.testType === FourSlashTestType.Server) { const actual = (this.languageService as ts.server.SessionClient).getProjectInfo( this.activeFile.fileName, @@ -3198,7 +3206,7 @@ export class TestState { } } - public replaceWithSemanticClassifications(format: ts.SemanticClassificationFormat.TwentyTwenty) { + public replaceWithSemanticClassifications(format: ts.SemanticClassificationFormat.TwentyTwenty): void { 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) { @@ -3217,32 +3225,32 @@ export class TestState { // fs.writeFileSync(testfilePath, newfile); } - public verifyEncodedSyntacticClassificationsLength(expected: number) { + public verifyEncodedSyntacticClassificationsLength(expected: number): void { 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}`); } } - public verifyEncodedSemanticClassificationsLength(format: ts.SemanticClassificationFormat, expected: number) { + public verifyEncodedSemanticClassificationsLength(format: ts.SemanticClassificationFormat, expected: number): void { 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}`); } } - public verifySemanticClassifications(format: ts.SemanticClassificationFormat, expected: { classificationType: string | number; text?: string; }[]) { + public verifySemanticClassifications(format: ts.SemanticClassificationFormat, expected: { classificationType: string | number; text?: string; }[]): void { 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; }[]) { + public verifySyntacticClassifications(expected: { classificationType: string; text: string; }[]): void { const actual = this.languageService.getSyntacticClassifications(this.activeFile.fileName, ts.createTextSpan(0, this.activeFile.content.length)); this.verifyClassifications(expected, actual, this.activeFile.content); } - public printOutliningSpans() { + public printOutliningSpans(): void { const spans = this.languageService.getOutliningSpans(this.activeFile.fileName); Harness.IO.log(`Outlining spans (${spans.length} items)\nResults:`); Harness.IO.log(stringify(spans)); @@ -3264,7 +3272,7 @@ export class TestState { Harness.IO.log(`\nMockup:\n${annotated}`); } - public verifyOutliningSpans(spans: Range[], kind?: "comment" | "region" | "code" | "imports") { + public verifyOutliningSpans(spans: Range[], kind?: "comment" | "region" | "code" | "imports"): void { const actual = this.languageService.getOutliningSpans(this.activeFile.fileName); const filterActual = ts.filter(actual, f => kind === undefined ? true : f.kind === kind); @@ -3282,7 +3290,7 @@ export class TestState { }); } - public verifyOutliningHintSpans(spans: Range[]) { + public verifyOutliningHintSpans(spans: Range[]): void { const actual = this.languageService.getOutliningSpans(this.activeFile.fileName); if (actual.length !== spans.length) { @@ -3296,7 +3304,7 @@ export class TestState { }); } - public verifyTodoComments(descriptors: string[], spans: Range[]) { + public verifyTodoComments(descriptors: string[], spans: Range[]): void { const actual = this.languageService.getTodoComments(this.activeFile.fileName, descriptors.map(d => ({ text: d, priority: 0 }))); if (actual.length !== spans.length) { @@ -3318,7 +3326,7 @@ export class TestState { * @param errorCode The error code that generated the code action. * @param index The nth (0-index-based) codeaction available generated by errorCode. */ - public getAndApplyCodeActions(errorCode?: number, index?: number) { + public getAndApplyCodeActions(errorCode?: number, index?: number): void { const fileName = this.activeFile.fileName; const fixes = this.getCodeFixes(fileName, errorCode); if (index === undefined) { @@ -3336,7 +3344,7 @@ export class TestState { this.applyChanges(fixes[index].changes); } - public applyCodeActionFromCompletion(markerName: string | undefined, options: FourSlashInterface.VerifyCompletionActionOptions) { + public applyCodeActionFromCompletion(markerName: string | undefined, options: FourSlashInterface.VerifyCompletionActionOptions): undefined { if (markerName !== undefined) { this.goToMarker(markerName); } @@ -3364,7 +3372,7 @@ export class TestState { this.verifyNewContentAfterChange(options, ts.flatMap(codeActions, a => a.changes.map(c => c.fileName))); } - public verifyRangeIs(expectedText: string, includeWhiteSpace?: boolean) { + public verifyRangeIs(expectedText: string, includeWhiteSpace?: boolean): void { this.verifyTextMatches(this.rangeText(this.getOnlyRange()), !!includeWhiteSpace, expectedText); } @@ -3388,7 +3396,7 @@ 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): void { this.getAndApplyCodeActions(errorCode, index); this.verifyRangeIs(expectedText, includeWhiteSpace); } @@ -3407,7 +3415,7 @@ export class TestState { this.verifyNewContent({ newFileContent }, changes); } - public verifyCodeFix(options: FourSlashInterface.VerifyCodeFixOptions) { + public verifyCodeFix(options: FourSlashInterface.VerifyCodeFixOptions): void { const fileName = this.activeFile.fileName; const actions = this.getCodeFixes(fileName, options.errorCode, options.preferences); let index = options.index; @@ -3534,7 +3542,7 @@ 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): void { const { fileName } = this.activeFile; const ranges = this.getRanges().filter(r => r.fileName === fileName); if (ranges.length > 1) { @@ -3584,7 +3592,7 @@ export class TestState { }); } - public verifyImportFixModuleSpecifiers(markerName: string, moduleSpecifiers: string[], preferences?: ts.UserPreferences) { + public verifyImportFixModuleSpecifiers(markerName: string, moduleSpecifiers: string[], preferences?: ts.UserPreferences): void { const marker = this.getMarkerByName(markerName); const codeFixes = this.getCodeFixes(marker.fileName, ts.Diagnostics.Cannot_find_name_0.code, { includeCompletionsForModuleExports: true, @@ -3607,7 +3615,7 @@ export class TestState { this.verifyNewContent({ newFileContent: options.newFileContents }, editInfo.edits); } - public verifyDocCommentTemplate(expected: ts.TextInsertion | undefined, options?: ts.DocCommentTemplateOptions) { + public verifyDocCommentTemplate(expected: ts.TextInsertion | undefined, options?: ts.DocCommentTemplateOptions): void { const name = "verifyDocCommentTemplate"; const actual = this.languageService.getDocCommentTemplateAtPosition(this.activeFile.fileName, this.currentCaretPosition, options || { generateReturnInDocTemplate: true }, this.formatCodeSettings)!; @@ -3633,7 +3641,7 @@ export class TestState { } } - public verifyBraceCompletionAtPosition(negative: boolean, openingBrace: string) { + public verifyBraceCompletionAtPosition(negative: boolean, openingBrace: string): void { const openBraceMap = new Map(Object.entries({ "(": ts.CharacterCodes.openParen, "{": ts.CharacterCodes.openBrace, @@ -3662,7 +3670,7 @@ export class TestState { } } - public baselineAutoImports(markerName: string, fullNamesForCodeFix?: string[], preferences?: ts.UserPreferences) { + public baselineAutoImports(markerName: string, fullNamesForCodeFix?: string[], preferences?: ts.UserPreferences): void { const marker = this.getMarkerByName(markerName); const completionPreferences = { includeCompletionsForModuleExports: true, @@ -3816,7 +3824,7 @@ export class TestState { } } - public verifyMatchingBracePosition(bracePosition: number, expectedMatchPosition: number) { + public verifyMatchingBracePosition(bracePosition: number, expectedMatchPosition: number): void { const actual = this.languageService.getBraceMatchingAtPosition(this.activeFile.fileName, bracePosition); if (actual.length !== 2) { @@ -3839,7 +3847,7 @@ export class TestState { } } - public verifyNoMatchingBracePosition(bracePosition: number) { + public verifyNoMatchingBracePosition(bracePosition: number): void { const actual = this.languageService.getBraceMatchingAtPosition(this.activeFile.fileName, bracePosition); if (actual.length !== 0) { @@ -3847,7 +3855,7 @@ export class TestState { } } - public verifySpanOfEnclosingComment(negative: boolean, onlyMultiLineDiverges?: boolean) { + public verifySpanOfEnclosingComment(negative: boolean, onlyMultiLineDiverges?: boolean): void { const expected = !negative; const position = this.currentCaretPosition; const fileName = this.activeFile.fileName; @@ -3885,11 +3893,11 @@ export class TestState { } } - public verifyNavigationBar(json: any, options: { checkSpans?: boolean; } | undefined) { + public verifyNavigationBar(json: any, options: { checkSpans?: boolean; } | undefined): void { this.verifyNavigationTreeOrBar(json, this.languageService.getNavigationBarItems(this.activeFile.fileName), "Bar", options); } - public verifyNavigationTree(json: any, options: { checkSpans?: boolean; } | undefined) { + public verifyNavigationTree(json: any, options: { checkSpans?: boolean; } | undefined): void { this.verifyNavigationTreeOrBar(json, this.languageService.getNavigationTree(this.activeFile.fileName), "Tree", options); } @@ -3916,7 +3924,7 @@ export class TestState { } } - public printNavigationItems(searchValue: string) { + public printNavigationItems(searchValue: string): void { const items = this.languageService.getNavigateToItems(searchValue); Harness.IO.log(`NavigationItems list (${items.length} items)`); for (const item of items) { @@ -3924,7 +3932,7 @@ export class TestState { } } - public printNavigationBar() { + public printNavigationBar(): void { const items = this.languageService.getNavigationBarItems(this.activeFile.fileName); Harness.IO.log(`Navigation bar (${items.length} items)`); for (const item of items) { @@ -3941,7 +3949,7 @@ export class TestState { markerOrRange: ArrayOrSingle | undefined, rangeText: ArrayOrSingle | undefined, options: FourSlashInterface.VerifyDocumentHighlightsOptions | undefined, - ) { + ): void { this.baselineEachMarkerOrRangeArrayOrSingle( "documentHighlights", markerOrRange, @@ -3987,7 +3995,7 @@ export class TestState { } } - public verifyCodeFixAllAvailable(negative: boolean, fixName: string) { + public verifyCodeFixAllAvailable(negative: boolean, fixName: string): void { const availableFixes = this.getCodeFixes(this.activeFile.fileName); const hasFix = availableFixes.some(fix => fix.fixName === fixName && fix.fixId); if (negative && hasFix) { @@ -4007,7 +4015,7 @@ export class TestState { } } - public verifyApplicableRefactorAvailableAtMarker(negative: boolean, markerName: string) { + public verifyApplicableRefactorAvailableAtMarker(negative: boolean, markerName: string): void { 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.`); @@ -4024,7 +4032,7 @@ export class TestState { }; } - public verifyRefactorAvailable(negative: boolean, triggerReason: ts.RefactorTriggerReason, name: string, actionName?: string, actionDescription?: string, kind?: string, preferences = ts.emptyOptions, includeInteractiveActions?: boolean) { + public verifyRefactorAvailable(negative: boolean, triggerReason: ts.RefactorTriggerReason, name: string, actionName?: string, actionDescription?: string, kind?: string, preferences: {} = ts.emptyOptions, includeInteractiveActions?: boolean): void { let refactors = this.getApplicableRefactorsAtSelection(triggerReason, kind, preferences, includeInteractiveActions); refactors = refactors.filter(r => r.name === name); @@ -4055,7 +4063,7 @@ export class TestState { } } - public verifyRefactorKindsAvailable(kind: string, expected: string[], preferences = ts.emptyOptions) { + public verifyRefactorKindsAvailable(kind: string, expected: string[], preferences: {} = ts.emptyOptions): void { const refactors = this.getApplicableRefactorsAtSelection("invoked", kind, preferences); const availableKinds = ts.flatMap(refactors, refactor => refactor.actions).map(action => action.kind); assert.deepEqual(availableKinds.sort(), expected.sort(), `Expected kinds to be equal`); @@ -4065,7 +4073,7 @@ export class TestState { assert.deepEqual(unique(this.getApplicableRefactorsAtSelection(), r => r.name), names); } - public verifyApplicableRefactorAvailableForRange(negative: boolean) { + public verifyApplicableRefactorAvailableForRange(negative: boolean): void { const ranges = this.getRanges(); if (!(ranges && ranges.length === 1)) { throw new Error("Exactly one refactor range is allowed per test."); @@ -4080,7 +4088,7 @@ export class TestState { } } - public applyRefactor({ refactorName, actionName, actionDescription, newContent: newContentWithRenameMarker, triggerReason }: FourSlashInterface.ApplyRefactorOptions) { + public applyRefactor({ refactorName, actionName, actionDescription, newContent: newContentWithRenameMarker, triggerReason }: FourSlashInterface.ApplyRefactorOptions): void { const range = this.getSelection(); const refactors = this.getApplicableRefactorsAtSelection(triggerReason); const refactorsWithName = refactors.filter(r => r.name === refactorName); @@ -4141,7 +4149,7 @@ export class TestState { } } - public noMoveToNewFile() { + public noMoveToNewFile(): void { const ranges = this.getRanges(); assert(ranges.length); for (const range of ranges) { @@ -4211,7 +4219,7 @@ export class TestState { refactorNameToApply: string, actionName: string, formattingOptions?: ts.FormatCodeSettings, - ) { + ): void { formattingOptions = formattingOptions || this.formatCodeSettings; const marker = this.getMarkerByName(markerName); @@ -4234,7 +4242,7 @@ export class TestState { } } - public printAvailableCodeFixes() { + public printAvailableCodeFixes(): void { const codeFixes = this.getCodeFixes(this.activeFile.fileName); Harness.IO.log(stringify(codeFixes)); } @@ -4364,7 +4372,7 @@ export class TestState { return text; } - public baselineCallHierarchy() { + public baselineCallHierarchy(): void { const callHierarchyItem = this.languageService.prepareCallHierarchy(this.activeFile.fileName, this.currentCaretPosition); const text = callHierarchyItem ? ts.mapOneOrMany(callHierarchyItem, item => this.formatCallHierarchy(item), result => result.join("")) : "none"; this.baseline("Call Hierarchy", text, ".callHierarchy.txt"); @@ -4456,7 +4464,7 @@ export class TestState { return `line ${(pos.line + 1)}, col ${pos.character}`; } - public getMarkerByName(markerName: string) { + public getMarkerByName(markerName: string): Marker { const markerPos = this.testData.markerPositions.get(markerName); if (markerPos === undefined) { throw new Error(`Unknown marker "${markerName}" Available markers: ${this.getMarkerNames().map(m => '"' + m + '"').join(", ")}`); @@ -4504,7 +4512,7 @@ export class TestState { (this.languageService as ts.server.SessionClient).configurePlugin(pluginName, configuration); } - public setCompilerOptionsForInferredProjects(options: ts.server.protocol.CompilerOptions) { + public setCompilerOptionsForInferredProjects(options: ts.server.protocol.CompilerOptions): void { ts.Debug.assert(this.testType === FourSlashTestType.Server); (this.languageService as ts.server.SessionClient).setCompilerOptionsForInferredProjects(options); } @@ -4647,7 +4655,7 @@ export interface FourSlashServerLogBaseliner { baseline?: () => void; } -export function runFourSlashTest(basePath: string, testType: FourSlashTestType, fileName: string, serverLogBaseliner?: FourSlashServerLogBaseliner) { +export function runFourSlashTest(basePath: string, testType: FourSlashTestType, fileName: string, serverLogBaseliner?: FourSlashServerLogBaseliner): void { const content = Harness.IO.readFile(fileName)!; runFourSlashTestContent(basePath, testType, content, fileName, serverLogBaseliner); } diff --git a/src/harness/fourslashInterfaceImpl.ts b/src/harness/fourslashInterfaceImpl.ts index eaa9699158914..707b8545d62a2 100644 --- a/src/harness/fourslashInterfaceImpl.ts +++ b/src/harness/fourslashInterfaceImpl.ts @@ -17,7 +17,7 @@ export class Test { return this.state.getMarkerByName(name); } - public markerName(m: FourSlash.Marker) { + public markerName(m: FourSlash.Marker): string { return this.state.markerName(m); } @@ -83,7 +83,7 @@ export class GoTo { // Moves the caret to the specified marker, // or the anonymous marker ('/**/') if no name // is given - public marker(name?: string | FourSlash.Marker) { + public marker(name?: string | FourSlash.Marker): void { this.state.goToMarker(name); } @@ -94,19 +94,19 @@ export class GoTo { this.state.goToEachMarker(markers, typeof a === "function" ? a : b!); } - public rangeStart(range: FourSlash.Range) { + public rangeStart(range: FourSlash.Range): void { this.state.goToRangeStart(range); } - public eachRange(action: (range: FourSlash.Range) => void) { + public eachRange(action: (range: FourSlash.Range) => void): void { this.state.goToEachRange(action); } - public bof() { + public bof(): void { this.state.goToBOF(); } - public eof() { + public eof(): void { this.state.goToEOF(); } @@ -124,11 +124,11 @@ export class GoTo { this.state.openFile(indexOrName, content, scriptKindName); } - public select(startMarker: string, endMarker: string) { + public select(startMarker: string, endMarker: string): void { this.state.select(startMarker, endMarker); } - public selectAllInFile(fileName: string) { + public selectAllInFile(fileName: string): void { this.state.selectAllInFile(fileName); } @@ -146,7 +146,7 @@ export class VerifyNegatable { } } - public assertHasRanges(ranges: FourSlash.Range[]) { + public assertHasRanges(ranges: FourSlash.Range[]): void { assert(ranges.length !== 0, "Array of ranges is expected to be non-empty"); } @@ -166,23 +166,23 @@ export class VerifyNegatable { this.state.verifySignatureHelp(options); } - public errorExistsBetweenMarkers(startMarker: string, endMarker: string) { + public errorExistsBetweenMarkers(startMarker: string, endMarker: string): void { this.state.verifyErrorExistsBetweenMarkers(startMarker, endMarker, !this.negative); } - public errorExistsAfterMarker(markerName = "") { + public errorExistsAfterMarker(markerName = ""): void { this.state.verifyErrorExistsAfterMarker(markerName, !this.negative, /*after*/ true); } - public errorExistsBeforeMarker(markerName = "") { + public errorExistsBeforeMarker(markerName = ""): void { this.state.verifyErrorExistsAfterMarker(markerName, !this.negative, /*after*/ false); } - public quickInfoExists() { + public quickInfoExists(): void { this.state.verifyQuickInfoExists(this.negative); } - public isValidBraceCompletionAtPosition(openingBrace: string) { + public isValidBraceCompletionAtPosition(openingBrace: string): void { this.state.verifyBraceCompletionAtPosition(this.negative, openingBrace); } @@ -198,27 +198,27 @@ export class VerifyNegatable { this.state.baselineLinkedEditing(); } - public isInCommentAtPosition(onlyMultiLineDiverges?: boolean) { + public isInCommentAtPosition(onlyMultiLineDiverges?: boolean): void { this.state.verifySpanOfEnclosingComment(this.negative, onlyMultiLineDiverges); } - public codeFix(options: VerifyCodeFixOptions) { + public codeFix(options: VerifyCodeFixOptions): void { this.state.verifyCodeFix(options); } - public codeFixAvailable(options?: VerifyCodeFixAvailableOptions[]) { + public codeFixAvailable(options?: VerifyCodeFixAvailableOptions[]): void { this.state.verifyCodeFixAvailable(this.negative, options); } - public codeFixAllAvailable(fixName: string) { + public codeFixAllAvailable(fixName: string): void { this.state.verifyCodeFixAllAvailable(this.negative, fixName); } - public applicableRefactorAvailableAtMarker(markerName: string) { + public applicableRefactorAvailableAtMarker(markerName: string): void { this.state.verifyApplicableRefactorAvailableAtMarker(this.negative, markerName); } - public applicableRefactorAvailableForRange() { + public applicableRefactorAvailableForRange(): void { this.state.verifyApplicableRefactorAvailableForRange(this.negative); } @@ -226,31 +226,31 @@ export class VerifyNegatable { this.state.verifyRefactorsAvailable(names); } - public refactorAvailable(name: string, actionName?: string, actionDescription?: string, kind?: string, preferences = ts.emptyOptions, includeInteractiveActions?: boolean) { + public refactorAvailable(name: string, actionName?: string, actionDescription?: string, kind?: string, preferences: {} = ts.emptyOptions, includeInteractiveActions?: boolean): void { this.state.verifyRefactorAvailable(this.negative, "implicit", name, actionName, actionDescription, kind, preferences, includeInteractiveActions); } - public refactorAvailableForTriggerReason(triggerReason: ts.RefactorTriggerReason, name: string, actionName?: string, actionDescription?: string, kind?: string, preferences = ts.emptyOptions, includeInteractiveActions?: boolean) { + public refactorAvailableForTriggerReason(triggerReason: ts.RefactorTriggerReason, name: string, actionName?: string, actionDescription?: string, kind?: string, preferences: {} = ts.emptyOptions, includeInteractiveActions?: boolean): void { this.state.verifyRefactorAvailable(this.negative, triggerReason, name, actionName, actionDescription, kind, preferences, includeInteractiveActions); } - public refactorKindAvailable(kind: string, expected: string[], preferences = ts.emptyOptions) { + public refactorKindAvailable(kind: string, expected: string[], preferences: {} = ts.emptyOptions): void { this.state.verifyRefactorKindsAvailable(kind, expected, preferences); } - public toggleLineComment(newFileContent: string) { + public toggleLineComment(newFileContent: string): void { this.state.toggleLineComment(newFileContent); } - public toggleMultilineComment(newFileContent: string) { + public toggleMultilineComment(newFileContent: string): void { this.state.toggleMultilineComment(newFileContent); } - public commentSelection(newFileContent: string) { + public commentSelection(newFileContent: string): void { this.state.commentSelection(newFileContent); } - public uncommentSelection(newFileContent: string) { + public uncommentSelection(newFileContent: string): void { this.state.uncommentSelection(newFileContent); } @@ -264,7 +264,15 @@ export class Verify extends VerifyNegatable { super(state); } - public completions(...optionsArray: VerifyCompletionsOptions[]) { + public completions(...optionsArray: VerifyCompletionsOptions[]): { + andApplyCodeAction: (options: { + name: string; + source: string; + description: string; + newFileContent?: string; + newRangeContent?: string; + }) => void; + } | undefined { if (optionsArray.length === 1) { return this.state.verifyCompletions(optionsArray[0]); } @@ -278,35 +286,35 @@ export class Verify extends VerifyNegatable { }; } - public baselineInlayHints(span: ts.TextSpan, preference?: ts.UserPreferences) { + public baselineInlayHints(span: ts.TextSpan, preference?: ts.UserPreferences): void { 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; }[]): void { 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; }[]): void { this.state.verifyQuickInfoAt(markerName, expectedText, expectedDocumentation, expectedTags); } - public quickInfos(namesAndTexts: { [name: string]: string; }) { + public quickInfos(namesAndTexts: { [name: string]: string; }): void { this.state.verifyQuickInfos(namesAndTexts); } - public caretAtMarker(markerName?: string) { + public caretAtMarker(markerName?: string): void { this.state.verifyCaretAtMarker(markerName); } - public indentationIs(numberOfSpaces: number) { + public indentationIs(numberOfSpaces: number): void { 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 = ts.IndentStyle.Smart, baseIndentSize = 0): void { this.state.verifyIndentationAtPosition(fileName, position, numberOfSpaces, indentStyle, baseIndentSize); } - public textAtCaretIs(text: string) { + public textAtCaretIs(text: string): void { this.state.verifyTextAtCaretIs(text); } @@ -315,15 +323,15 @@ export class Verify extends VerifyNegatable { * the emitted output, then compares (using ===) the result of that expression * to 'value'. Do not use this function with external modules as it is not supported. */ - public eval(expr: string, value: any) { + public eval(expr: string, value: any): void { this.state.verifyEval(expr, value); } - public currentLineContentIs(text: string) { + public currentLineContentIs(text: string): void { this.state.verifyCurrentLineContent(text); } - public currentFileContentIs(text: string) { + public currentFileContentIs(text: string): void { this.state.verifyCurrentFileContent(text); } @@ -339,95 +347,95 @@ export class Verify extends VerifyNegatable { this.state.verifyGetEmitOutputContentsForCurrentFile(expected); } - public symbolAtLocation(startRange: FourSlash.Range, ...declarationRanges: FourSlash.Range[]) { + public symbolAtLocation(startRange: FourSlash.Range, ...declarationRanges: FourSlash.Range[]): void { this.state.verifySymbolAtLocation(startRange, declarationRanges); } - public typeOfSymbolAtLocation(range: FourSlash.Range, symbol: ts.Symbol, expected: string) { + public typeOfSymbolAtLocation(range: FourSlash.Range, symbol: ts.Symbol, expected: string): void { this.state.verifyTypeOfSymbolAtLocation(range, symbol, expected); } - public typeAtLocation(range: FourSlash.Range, expected: string) { + public typeAtLocation(range: FourSlash.Range, expected: string): void { this.state.verifyTypeAtLocation(range, expected); } - public baselineFindAllReferences(...markerOrRange: FourSlash.MarkerOrNameOrRange[]) { + public baselineFindAllReferences(...markerOrRange: FourSlash.MarkerOrNameOrRange[]): void { this.state.baselineFindAllReferences(markerOrRange, /*rangeText*/ undefined); } - public baselineFindAllReferencesAtRangesWithText(...rangeText: string[]) { + public baselineFindAllReferencesAtRangesWithText(...rangeText: string[]): void { this.state.baselineFindAllReferences(/*markerOrRange*/ undefined, rangeText); } - public baselineGetFileReferences(...fileName: string[]) { + public baselineGetFileReferences(...fileName: string[]): void { this.state.baselineGetFileReferences(fileName); } - public baselineGoToDefinition(...markerOrRange: FourSlash.MarkerOrNameOrRange[]) { + public baselineGoToDefinition(...markerOrRange: FourSlash.MarkerOrNameOrRange[]): void { this.state.baselineGoToDefinition(markerOrRange, /*rangeText*/ undefined); } - public baselineGoToDefinitionAtRangesWithText(...rangeText: string[]) { + public baselineGoToDefinitionAtRangesWithText(...rangeText: string[]): void { this.state.baselineGoToDefinition(/*markerOrRange*/ undefined, rangeText); } - public baselineGetDefinitionAtPosition(...markerOrRange: FourSlash.MarkerOrNameOrRange[]) { + public baselineGetDefinitionAtPosition(...markerOrRange: FourSlash.MarkerOrNameOrRange[]): void { this.state.baselineGetDefinitionAtPosition(markerOrRange, /*rangeText*/ undefined); } - public baselineGetDefinitionAtRangesWithText(...rangeText: string[]) { + public baselineGetDefinitionAtRangesWithText(...rangeText: string[]): void { this.state.baselineGetDefinitionAtPosition(/*markerOrRange*/ undefined, rangeText); } - public baselineGoToSourceDefinition(...markerOrRange: FourSlash.MarkerOrNameOrRange[]) { + public baselineGoToSourceDefinition(...markerOrRange: FourSlash.MarkerOrNameOrRange[]): void { this.state.baselineGoToSourceDefinition(markerOrRange, /*rangeText*/ undefined); } - public baselineGoToSourceDefinitionAtRangesWithText(...rangeText: string[]) { + public baselineGoToSourceDefinitionAtRangesWithText(...rangeText: string[]): void { this.state.baselineGoToSourceDefinition(/*markerOrRange*/ undefined, rangeText); } - public baselineGoToType(...markerOrRange: FourSlash.MarkerOrNameOrRange[]) { + public baselineGoToType(...markerOrRange: FourSlash.MarkerOrNameOrRange[]): void { this.state.baselineGoToType(markerOrRange, /*rangeText*/ undefined); } - public baselineGoToTypeAtRangesWithText(...rangeText: string[]) { + public baselineGoToTypeAtRangesWithText(...rangeText: string[]): void { this.state.baselineGoToType(/*markerOrRange*/ undefined, rangeText); } - public baselineGoToImplementation(...markerOrRange: FourSlash.MarkerOrNameOrRange[]) { + public baselineGoToImplementation(...markerOrRange: FourSlash.MarkerOrNameOrRange[]): void { this.state.baselineGoToImplementation(markerOrRange, /*rangeText*/ undefined); } - public baselineGoToImplementationAtRangesWithText(...rangeText: string[]) { + public baselineGoToImplementationAtRangesWithText(...rangeText: string[]): void { this.state.baselineGoToImplementation(/*markerOrRange*/ undefined, rangeText); } - public baselineDocumentHighlights(markerOrRange?: ArrayOrSingle, options?: VerifyDocumentHighlightsOptions) { + public baselineDocumentHighlights(markerOrRange?: ArrayOrSingle, options?: VerifyDocumentHighlightsOptions): void { this.state.baselineDocumentHighlights(markerOrRange, /*rangeText*/ undefined, options); } - public baselineDocumentHighlightsAtRangesWithText(rangeText?: ArrayOrSingle, options?: VerifyDocumentHighlightsOptions) { + public baselineDocumentHighlightsAtRangesWithText(rangeText?: ArrayOrSingle, options?: VerifyDocumentHighlightsOptions): void { this.state.baselineDocumentHighlights(/*markerOrRange*/ undefined, rangeText, options); } - public noErrors() { + public noErrors(): void { this.state.verifyNoErrors(); } - public errorExistsAtRange(range: FourSlash.Range, code: number, message?: string) { + public errorExistsAtRange(range: FourSlash.Range, code: number, message?: string): void { this.state.verifyErrorExistsAtRange(range, code, message); } - public numberOfErrorsInCurrentFile(expected: number) { + public numberOfErrorsInCurrentFile(expected: number): void { this.state.verifyNumberOfErrorsInCurrentFile(expected); } - public baselineCurrentFileBreakpointLocations() { + public baselineCurrentFileBreakpointLocations(): void { this.state.baselineCurrentFileBreakpointLocations(); } - public baselineCurrentFileNameOrDottedNameSpans() { + public baselineCurrentFileNameOrDottedNameSpans(): void { this.state.baselineCurrentFileNameOrDottedNameSpans(); } @@ -435,64 +443,64 @@ export class Verify extends VerifyNegatable { this.state.verifyGetEmitOutput(expectedOutputFiles); } - public baselineGetEmitOutput() { + public baselineGetEmitOutput(): void { this.state.baselineGetEmitOutput(); } - public baselineQuickInfo() { + public baselineQuickInfo(): void { this.state.baselineQuickInfo(); } - public baselineSignatureHelp() { + public baselineSignatureHelp(): void { this.state.baselineSignatureHelp(); } - public baselineCompletions(preferences?: ts.UserPreferences) { + public baselineCompletions(preferences?: ts.UserPreferences): void { this.state.baselineCompletions(preferences); } - public baselineSmartSelection() { + public baselineSmartSelection(): void { this.state.baselineSmartSelection(); } - public baselineSyntacticDiagnostics() { + public baselineSyntacticDiagnostics(): void { this.state.baselineSyntacticDiagnostics(); } - public baselineSyntacticAndSemanticDiagnostics() { + public baselineSyntacticAndSemanticDiagnostics(): void { this.state.baselineSyntacticAndSemanticDiagnostics(); } - public nameOrDottedNameSpanTextIs(text: string) { + public nameOrDottedNameSpanTextIs(text: string): void { this.state.verifyCurrentNameOrDottedNameSpanText(text); } - public outliningSpansInCurrentFile(spans: FourSlash.Range[], kind?: "comment" | "region" | "code" | "imports") { + public outliningSpansInCurrentFile(spans: FourSlash.Range[], kind?: "comment" | "region" | "code" | "imports"): void { this.state.verifyOutliningSpans(spans, kind); } - public outliningHintSpansInCurrentFile(spans: FourSlash.Range[]) { + public outliningHintSpansInCurrentFile(spans: FourSlash.Range[]): void { this.state.verifyOutliningHintSpans(spans); } - public todoCommentsInCurrentFile(descriptors: string[]) { + public todoCommentsInCurrentFile(descriptors: string[]): void { this.state.verifyTodoComments(descriptors, this.state.getRanges()); } - public matchingBracePositionInCurrentFile(bracePosition: number, expectedMatchPosition: number) { + public matchingBracePositionInCurrentFile(bracePosition: number, expectedMatchPosition: number): void { this.state.verifyMatchingBracePosition(bracePosition, expectedMatchPosition); } - public noMatchingBracePositionInCurrentFile(bracePosition: number) { + public noMatchingBracePositionInCurrentFile(bracePosition: number): void { 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): void { this.state.goToMarker(marker); this.state.verifyDocCommentTemplate({ newText: expectedText.replace(/\r?\n/g, ts.testFormatSettings.newLineCharacter!), caretOffset: expectedOffset }, options); } - public noDocCommentTemplateAt(marker: string | FourSlash.Marker) { + public noDocCommentTemplateAt(marker: string | FourSlash.Marker): void { this.state.goToMarker(marker); this.state.verifyDocCommentTemplate(/*expected*/ undefined); } @@ -525,19 +533,19 @@ export class Verify extends VerifyNegatable { this.state.verifyImportFixAtPosition(expectedTextArray, errorCode, preferences); } - public importFixModuleSpecifiers(marker: string, moduleSpecifiers: string[], preferences?: ts.UserPreferences) { + public importFixModuleSpecifiers(marker: string, moduleSpecifiers: string[], preferences?: ts.UserPreferences): void { this.state.verifyImportFixModuleSpecifiers(marker, moduleSpecifiers, preferences); } - public baselineAutoImports(marker: string, fullNamesForCodeFix?: string[], options?: ts.UserPreferences) { + public baselineAutoImports(marker: string, fullNamesForCodeFix?: string[], options?: ts.UserPreferences): void { this.state.baselineAutoImports(marker, fullNamesForCodeFix, options); } - public navigationBar(json: any, options?: { checkSpans?: boolean; }) { + public navigationBar(json: any, options?: { checkSpans?: boolean; }): void { this.state.verifyNavigationBar(json, options); } - public navigationTree(json: any, options?: { checkSpans?: boolean; }) { + public navigationTree(json: any, options?: { checkSpans?: boolean; }): void { this.state.verifyNavigationTree(json, options); } @@ -548,26 +556,26 @@ export class Verify extends VerifyNegatable { /** * This method *requires* a contiguous, complete, and ordered stream of classifications for a file. */ - public syntacticClassificationsAre(...classifications: { classificationType: string; text: string; }[]) { + public syntacticClassificationsAre(...classifications: { classificationType: string; text: string; }[]): void { this.state.verifySyntacticClassifications(classifications); } - public encodedSyntacticClassificationsLength(length: number) { + public encodedSyntacticClassificationsLength(length: number): void { this.state.verifyEncodedSyntacticClassificationsLength(length); } - public encodedSemanticClassificationsLength(format: ts.SemanticClassificationFormat, length: number) { + public encodedSemanticClassificationsLength(format: ts.SemanticClassificationFormat, length: number): void { this.state.verifyEncodedSemanticClassificationsLength(format, length); } /** * This method *requires* an ordered stream of classifications for a file, and spans are highly recommended. */ - public semanticClassificationsAre(format: ts.SemanticClassificationFormat, ...classifications: Classification[]) { + public semanticClassificationsAre(format: ts.SemanticClassificationFormat, ...classifications: Classification[]): void { this.state.verifySemanticClassifications(format, classifications); } - public replaceWithSemanticClassifications(format: ts.SemanticClassificationFormat.TwentyTwenty) { + public replaceWithSemanticClassifications(format: ts.SemanticClassificationFormat.TwentyTwenty): void { this.state.replaceWithSemanticClassifications(format); } @@ -579,31 +587,31 @@ export class Verify extends VerifyNegatable { fileToRename?: string, expectedRange?: FourSlash.Range, preferences?: ts.UserPreferences, - ) { + ): void { this.state.verifyRenameInfoSucceeded(displayName, fullDisplayName, kind, kindModifiers, fileToRename, expectedRange, preferences); } - public renameInfoFailed(message?: string, preferences?: ts.UserPreferences) { + public renameInfoFailed(message?: string, preferences?: ts.UserPreferences): void { this.state.verifyRenameInfoFailed(message, preferences); } - public baselineRename(markerOrRange?: ArrayOrSingle, options?: RenameOptions) { + public baselineRename(markerOrRange?: ArrayOrSingle, options?: RenameOptions): void { this.state.baselineRename(markerOrRange, /*rangeText*/ undefined, options); } - public baselineRenameAtRangesWithText(rangeText?: ArrayOrSingle, options?: RenameOptions) { + public baselineRenameAtRangesWithText(rangeText?: ArrayOrSingle, options?: RenameOptions): void { this.state.baselineRename(/*markerOrRange*/ undefined, 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[]): void { this.state.verifyQuickInfoDisplayParts(kind, kindModifiers, textSpan, displayParts, documentation, tags); } - public getSyntacticDiagnostics(expected: readonly Diagnostic[]) { + public getSyntacticDiagnostics(expected: readonly Diagnostic[]): void { this.state.getSyntacticDiagnostics(expected); } - public getSemanticDiagnostics(expected: readonly Diagnostic[]) { + public getSemanticDiagnostics(expected: readonly Diagnostic[]): void { this.state.verifySemanticDiagnostics(expected); } @@ -611,23 +619,23 @@ export class Verify extends VerifyNegatable { ranges: ts.TextRange[], expectedDiagnostics: readonly Diagnostic[], expectedRanges: ts.TextRange[] | undefined, - ) { + ): void { this.state.getRegionSemanticDiagnostics(ranges, expectedDiagnostics, expectedRanges); } - public getSuggestionDiagnostics(expected: readonly Diagnostic[]) { + public getSuggestionDiagnostics(expected: readonly Diagnostic[]): void { this.state.getSuggestionDiagnostics(expected); } - public ProjectInfo(expected: string[]) { + public ProjectInfo(expected: string[]): void { this.state.verifyProjectInfo(expected); } - public getEditsForFileRename(options: GetEditsForFileRenameOptions) { + public getEditsForFileRename(options: GetEditsForFileRenameOptions): void { this.state.getEditsForFileRename(options); } - public baselineCallHierarchy() { + public baselineCallHierarchy(): void { this.state.baselineCallHierarchy(); } @@ -655,70 +663,70 @@ export class Verify extends VerifyNegatable { export class Edit { constructor(private state: FourSlash.TestState) { } - public caretPosition() { + public caretPosition(): FourSlash.Marker { return this.state.caretPosition(); } - public backspace(count?: number) { + public backspace(count?: number): void { this.state.deleteCharBehindMarker(count); } - public deleteAtCaret(times?: number) { + public deleteAtCaret(times?: number): void { this.state.deleteChar(times); } - public replace(start: number, length: number, text: string) { + public replace(start: number, length: number, text: string): void { this.state.replace(start, length, text); } - public paste(text: string) { + public paste(text: string): void { this.state.paste(text); } - public insert(text: string) { + public insert(text: string): void { this.insertLines(text); } - public insertLine(text: string) { + public insertLine(text: string): void { this.insertLines(text + "\n"); } - public insertLines(...lines: string[]) { + public insertLines(...lines: string[]): void { this.state.type(lines.join("\n")); } - public deleteLine(index: number) { + public deleteLine(index: number): void { this.deleteLineRange(index, index); } - public deleteLineRange(startIndex: number, endIndexInclusive: number) { + public deleteLineRange(startIndex: number, endIndexInclusive: number): void { this.state.deleteLineRange(startIndex, endIndexInclusive); } - public replaceLine(index: number, text: string) { + public replaceLine(index: number, text: string): void { this.state.selectLine(index); this.state.type(text); } - public moveRight(count?: number) { + public moveRight(count?: number): void { this.state.moveCaretRight(count); } - public moveLeft(count?: number) { + public moveLeft(count?: number): void { if (typeof count === "undefined") { count = 1; } this.state.moveCaretRight(count * -1); } - public enableFormatting() { + public enableFormatting(): void { this.state.enableFormatting = true; } - public disableFormatting() { + public disableFormatting(): void { this.state.enableFormatting = false; } - public applyRefactor(options: ApplyRefactorOptions) { + public applyRefactor(options: ApplyRefactorOptions): void { this.state.applyRefactor(options); } } @@ -727,66 +735,66 @@ export class Debug { constructor(private state: FourSlash.TestState) { } - public printCurrentParameterHelp() { + public printCurrentParameterHelp(): void { this.state.printCurrentParameterHelp(); } - public printCurrentFileState() { + public printCurrentFileState(): void { this.state.printCurrentFileState(/*showWhitespace*/ false, /*makeCaretVisible*/ true); } - public printCurrentFileStateWithWhitespace() { + public printCurrentFileStateWithWhitespace(): void { this.state.printCurrentFileState(/*showWhitespace*/ true, /*makeCaretVisible*/ true); } - public printCurrentFileStateWithoutCaret() { + public printCurrentFileStateWithoutCaret(): void { this.state.printCurrentFileState(/*showWhitespace*/ false, /*makeCaretVisible*/ false); } - public printCurrentQuickInfo() { + public printCurrentQuickInfo(): void { this.state.printCurrentQuickInfo(); } - public printCurrentSignatureHelp() { + public printCurrentSignatureHelp(): void { this.state.printCurrentSignatureHelp(); } - public printCompletionListMembers(options: ts.UserPreferences | undefined) { + public printCompletionListMembers(options: ts.UserPreferences | undefined): void { this.state.printCompletionListMembers(options); } - public printAvailableCodeFixes() { + public printAvailableCodeFixes(): void { this.state.printAvailableCodeFixes(); } - public printBreakpointLocation(pos: number) { + public printBreakpointLocation(pos: number): void { this.state.printBreakpointLocation(pos); } - public printBreakpointAtCurrentLocation() { + public printBreakpointAtCurrentLocation(): void { this.state.printBreakpointAtCurrentLocation(); } - public printNameOrDottedNameSpans(pos: number) { + public printNameOrDottedNameSpans(pos: number): void { this.state.printNameOrDottedNameSpans(pos); } - public printErrorList() { + public printErrorList(): void { this.state.printErrorList(); } - public printNavigationItems(searchValue = ".*") { + public printNavigationItems(searchValue = ".*"): void { this.state.printNavigationItems(searchValue); } - public printNavigationBar() { + public printNavigationBar(): void { this.state.printNavigationBar(); } - public printContext() { + public printContext(): void { this.state.printContext(); } - public printOutliningSpans() { + public printOutliningSpans(): void { this.state.printOutliningSpans(); } } @@ -795,7 +803,7 @@ export class Format { constructor(private state: FourSlash.TestState) { } - public document() { + public document(): void { this.state.formatDocument(); } @@ -803,15 +811,15 @@ export class Format { return this.state.copyFormatOptions(); } - public setFormatOptions(options: ts.FormatCodeOptions) { + public setFormatOptions(options: ts.FormatCodeOptions): ts.FormatCodeSettings { return this.state.setFormatOptions(options); } - public selection(startMarker: string, endMarker: string) { + public selection(startMarker: string, endMarker: string): void { this.state.formatSelection(this.state.getMarkerByName(startMarker).position, this.state.getMarkerByName(endMarker).position); } - public onType(posMarker: string, key: string) { + public onType(posMarker: string, key: string): void { this.state.formatOnType(this.state.getMarkerByName(posMarker).position, key); } @@ -824,11 +832,11 @@ export class Cancellation { constructor(private state: FourSlash.TestState) { } - public resetCancelled() { + public resetCancelled(): void { this.state.resetCancelled(); } - public setCancelled(numberOfCalls = 0) { + public setCancelled(numberOfCalls = 0): void { this.state.setCancelled(numberOfCalls); } } @@ -848,7 +856,59 @@ interface ModernClassification { type Classification = OlderClassification | ModernClassification; -export function classification(format: ts.SemanticClassificationFormat) { +export function classification(format: ts.SemanticClassificationFormat): { + semanticToken: (identifier: string, text: string, _position: number) => Classification; + comment?: undefined; + identifier?: undefined; + keyword?: undefined; + numericLiteral?: undefined; + operator?: undefined; + stringLiteral?: undefined; + whiteSpace?: undefined; + text?: undefined; + punctuation?: undefined; + docCommentTagName?: undefined; + className?: undefined; + enumName?: undefined; + interfaceName?: undefined; + moduleName?: undefined; + typeParameterName?: undefined; + parameterName?: undefined; + typeAliasName?: undefined; + jsxOpenTagName?: undefined; + jsxCloseTagName?: undefined; + jsxSelfClosingTagName?: undefined; + jsxAttribute?: undefined; + jsxText?: undefined; + jsxAttributeStringLiteralValue?: undefined; + getClassification?: undefined; +} | { + comment: (text: string, position?: number) => Classification; + identifier: (text: string, position?: number) => Classification; + keyword: (text: string, position?: number) => Classification; + numericLiteral: (text: string, position?: number) => Classification; + operator: (text: string, position?: number) => Classification; + stringLiteral: (text: string, position?: number) => Classification; + whiteSpace: (text: string, position?: number) => Classification; + text: (text: string, position?: number) => Classification; + punctuation: (text: string, position?: number) => Classification; + docCommentTagName: (text: string, position?: number) => Classification; + className: (text: string, position?: number) => Classification; + enumName: (text: string, position?: number) => Classification; + interfaceName: (text: string, position?: number) => Classification; + moduleName: (text: string, position?: number) => Classification; + typeParameterName: (text: string, position?: number) => Classification; + parameterName: (text: string, position?: number) => Classification; + typeAliasName: (text: string, position?: number) => Classification; + jsxOpenTagName: (text: string, position?: number) => Classification; + jsxCloseTagName: (text: string, position?: number) => Classification; + jsxSelfClosingTagName: (text: string, position?: number) => Classification; + jsxAttribute: (text: string, position?: number) => Classification; + jsxText: (text: string, position?: number) => Classification; + jsxAttributeStringLiteralValue: (text: string, position?: number) => Classification; + getClassification: (classificationType: ts.ClassificationTypeNames, text: string, position?: number) => Classification; + semanticToken?: undefined; +} { function semanticToken(identifier: string, text: string, _position: number): Classification { return { classificationType: identifier, @@ -1137,7 +1197,7 @@ export namespace Completion { return Object.assign(sorted([...providedByHarness, ...providedByTest]), { plusFunctionName: functionName, plusArgument: providedByTest }); } - export function typeKeywordsPlus(plus: readonly ExpectedCompletionEntry[]) { + export function typeKeywordsPlus(plus: readonly ExpectedCompletionEntry[]): ExpectedExactCompletionsPlus { return combineExpectedCompletionEntries("typeKeywordsPlus", typeKeywords, plus); } @@ -1268,8 +1328,8 @@ export namespace Completion { kind: "module", sortText: SortText.GlobalsOrKeywords, }; - export const globalTypes = globalTypesPlus([]); - export function globalTypesPlus(plus: readonly ExpectedCompletionEntry[]) { + export const globalTypes: ExpectedExactCompletionsPlus = globalTypesPlus([]); + export function globalTypesPlus(plus: readonly ExpectedCompletionEntry[]): ExpectedExactCompletionsPlus { return combineExpectedCompletionEntries( "globalTypesPlus", [globalThisEntry, ...globalTypeDecls, ...typeKeywords], @@ -1332,7 +1392,7 @@ export namespace Completion { "static", ].map(keywordEntry); - export const classElementInJsKeywords = getInJsKeywords(classElementKeywords); + export const classElementInJsKeywords: readonly ExpectedCompletionEntryObject[] = getInJsKeywords(classElementKeywords); export const constructorParameterKeywords: readonly ExpectedCompletionEntryObject[] = ["override", "private", "protected", "public", "readonly"].map((name): ExpectedCompletionEntryObject => ({ name, @@ -1350,7 +1410,7 @@ export namespace Completion { propertyEntry("caller"), ].sort(compareExpectedCompletionEntries); - export function functionMembersPlus(plus: readonly ExpectedCompletionEntryObject[]) { + export function functionMembersPlus(plus: readonly ExpectedCompletionEntryObject[]): ExpectedExactCompletionsPlus { return combineExpectedCompletionEntries("functionMembersPlus", functionMembers, plus); } @@ -1383,7 +1443,7 @@ export namespace Completion { propertyEntry("prototype"), ].sort(compareExpectedCompletionEntries); - export function functionMembersWithPrototypePlus(plus: readonly ExpectedCompletionEntryObject[]) { + export function functionMembersWithPrototypePlus(plus: readonly ExpectedCompletionEntryObject[]): ExpectedCompletionEntryObject[] { return [...functionMembersWithPrototype, ...plus].sort(compareExpectedCompletionEntries); } @@ -1472,7 +1532,7 @@ export namespace Completion { } }); - export const statementInJsKeywords = getInJsKeywords(statementKeywords); + export const statementInJsKeywords: readonly ExpectedCompletionEntryObject[] = getInJsKeywords(statementKeywords); export const globalsVars: readonly ExpectedCompletionEntryObject[] = [ varEntry("Array"), @@ -1675,7 +1735,7 @@ export namespace Completion { "yield", ].map(keywordEntry); - export const globalInJsKeywords = getInJsKeywords(globalKeywords); + export const globalInJsKeywords: readonly ExpectedCompletionEntryObject[] = getInJsKeywords(globalKeywords); export const insideMethodKeywords: readonly ExpectedCompletionEntryObject[] = [ "as", @@ -1727,7 +1787,7 @@ export namespace Completion { "yield", ].map(keywordEntry); - export const insideMethodInJsKeywords = getInJsKeywords(insideMethodKeywords); + export const insideMethodInJsKeywords: readonly ExpectedCompletionEntryObject[] = getInJsKeywords(insideMethodKeywords); export const globals: readonly ExpectedCompletionEntryObject[] = [ globalThisEntry, @@ -1743,7 +1803,7 @@ export namespace Completion { ...globalInJsKeywords, ].sort(compareExpectedCompletionEntries); - export function globalsPlus(plus: readonly ExpectedCompletionEntry[], options?: { noLib?: boolean; }) { + export function globalsPlus(plus: readonly ExpectedCompletionEntry[], options?: { noLib?: boolean; }): ExpectedExactCompletionsPlus { return combineExpectedCompletionEntries("globalsPlus", [ globalThisEntry, ...options?.noLib ? [] : globalsVars, @@ -1752,7 +1812,7 @@ export namespace Completion { ], plus); } - export function globalsInJsPlus(plus: readonly ExpectedCompletionEntry[], options?: { noLib?: boolean; }) { + export function globalsInJsPlus(plus: readonly ExpectedCompletionEntry[], options?: { noLib?: boolean; }): ExpectedExactCompletionsPlus { return combineExpectedCompletionEntries("globalsInJsPlus", [ globalThisEntry, ...options?.noLib ? [] : globalsVars, diff --git a/src/harness/harnessUtils.ts b/src/harness/harnessUtils.ts index b049c51d5f416..8852511f38503 100644 --- a/src/harness/harnessUtils.ts +++ b/src/harness/harnessUtils.ts @@ -6,7 +6,7 @@ export function encodeString(s: string): string { return Buffer.from(s).toString("utf8"); } -export function evalFile(fileContents: string, fileName: string, nodeContext?: any) { +export function evalFile(fileContents: string, fileName: string, nodeContext?: any): void { if (nodeContext) { vm.runInNewContext(fileContents, nodeContext, fileName); } @@ -16,7 +16,7 @@ export function evalFile(fileContents: string, fileName: string, nodeContext?: a } /** Splits the given string on \r\n, or on only \n if that fails, or on only \r if *that* fails. */ -export function splitContentByNewlines(content: string) { +export function splitContentByNewlines(content: string): string[] { // Split up the input file by line // Note: IE JS engine incorrectly handles consecutive delimiters here when using RegExp split, so // we have to use string-based splitting instead and try to figure out the delimiting chars @@ -32,7 +32,7 @@ export function splitContentByNewlines(content: string) { } /** Reads a file under /tests */ -export function readTestFile(path: string) { +export function readTestFile(path: string): string | undefined { if (!path.includes("tests")) { path = "tests/" + path; } @@ -64,9 +64,9 @@ export function memoize(f: T, memoKey: (...anything: a } as any); } -export const canonicalizeForHarness = ts.createGetCanonicalFileName(/*useCaseSensitiveFileNames*/ false); // This is done so tests work on windows _and_ linux +export const canonicalizeForHarness: ts.GetCanonicalFileName = ts.createGetCanonicalFileName(/*useCaseSensitiveFileNames*/ false); // This is done so tests work on windows _and_ linux -export function assertInvariants(node: ts.Node | undefined, parent: ts.Node | undefined) { +export function assertInvariants(node: ts.Node | undefined, parent: ts.Node | undefined): void { const queue: [ts.Node | undefined, ts.Node | undefined][] = [[node, parent]]; for (const [node, parent] of queue) { assertInvariantsWorker(node, parent); @@ -149,7 +149,13 @@ function isNodeOrArray(a: any): boolean { return a !== undefined && typeof a.pos === "number"; } -export function convertDiagnostics(diagnostics: readonly ts.Diagnostic[]) { +export function convertDiagnostics(diagnostics: readonly ts.Diagnostic[]): { + start: number | undefined; + length: number | undefined; + messageText: string; + category: string; + code: number; +}[] { return diagnostics.map(convertDiagnostic); } @@ -247,7 +253,7 @@ export function sourceFileToJSON(file: ts.Node): string { } } -export function assertDiagnosticsEquals(array1: readonly ts.Diagnostic[], array2: readonly ts.Diagnostic[]) { +export function assertDiagnosticsEquals(array1: readonly ts.Diagnostic[], array2: readonly ts.Diagnostic[]): void { if (array1 === array2) { return; } @@ -273,7 +279,7 @@ export function assertDiagnosticsEquals(array1: readonly ts.Diagnostic[], array2 } } -export function assertStructuralEquals(node1: ts.Node, node2: ts.Node) { +export function assertStructuralEquals(node1: ts.Node, node2: ts.Node): void { if (node1 === node2) { return; } @@ -330,7 +336,7 @@ function findChildName(parent: any, child: any) { const maxHarnessFrames = 1; -export function filterStack(error: Error, stackTraceLimit = Infinity) { +export function filterStack(error: Error, stackTraceLimit: number = Infinity): Error { const stack = (error as any).stack as string; if (stack) { const lines = stack.split(/\r\n?|\n/g); diff --git a/src/harness/projectServiceStateLogger.ts b/src/harness/projectServiceStateLogger.ts index 599769b8e734b..ea67addd0d2c5 100644 --- a/src/harness/projectServiceStateLogger.ts +++ b/src/harness/projectServiceStateLogger.ts @@ -66,7 +66,7 @@ enum Diff { type StatePropertyLog = string | string[]; type StateItemLog = [string, StatePropertyLog[]]; -export function patchServiceForStateBaseline(service: ProjectService) { +export function patchServiceForStateBaseline(service: ProjectService): void { if (!service.logger.isTestLogger || !service.logger.hasLevel(LogLevel.verbose)) return; if (service.baseline !== noop) return; // Already patched diff --git a/src/harness/runnerbase.ts b/src/harness/runnerbase.ts index 17c6e5cb556a2..5a74d813422ef 100644 --- a/src/harness/runnerbase.ts +++ b/src/harness/runnerbase.ts @@ -12,10 +12,10 @@ export let shards = 1; export let shardId = 1; // The following have setters as while they're read here in the harness, they're only set in the runner -export function setShards(count: number) { +export function setShards(count: number): void { shards = count; } -export function setShardId(id: number) { +export function setShardId(id: number): void { shardId = id; } @@ -24,7 +24,7 @@ export abstract class RunnerBase { public tests: string[] = []; /** Add a source file to the runner's list of tests that need to be initialized with initializeTests */ - public addTest(fileName: string) { + public addTest(fileName: string): void { this.tests.push(fileName); } @@ -53,7 +53,7 @@ export abstract class RunnerBase { public abstract initializeTests(): void; /** Replaces instances of full paths with fileNames only */ - static removeFullPaths(path: string) { + static removeFullPaths(path: string): string { // If its a full path (starts with "C:" or "/") replace with just the filename let fixedPath = /^(\w:|\/)/.test(path) ? ts.getBaseFileName(path) : path; diff --git a/src/harness/util.ts b/src/harness/util.ts index 4b0f7e28b9a09..cd9496607edf8 100644 --- a/src/harness/util.ts +++ b/src/harness/util.ts @@ -21,14 +21,14 @@ const replaceTypesVersionsMessage = createDiagnosticMessageReplacer( ([entry, , moduleName], compilerVersion) => [entry, compilerVersion, moduleName], ); -export function sanitizeTraceResolutionLogEntry(text: string) { +export function sanitizeTraceResolutionLogEntry(text: string): string { return text && replaceTypesVersionsMessage(text, "3.1.0-dev"); } /** * Removes leading indentation from a template literal string. */ -export function dedent(array: TemplateStringsArray, ...args: any[]) { +export function dedent(array: TemplateStringsArray, ...args: any[]): string { let text = array[0]; for (let i = 0; i < args.length; i++) { text += args[i]; @@ -97,11 +97,11 @@ export function removeByteOrderMark(text: string): string { return length ? text.slice(length) : text; } -export function addUTF8ByteOrderMark(text: string) { +export function addUTF8ByteOrderMark(text: string): string { return getByteOrderMarkLength(text) === 0 ? "\u00EF\u00BB\u00BF" + text : text; } -export function theory(name: string, cb: (...args: T) => void, data: T[]) { +export function theory(name: string, cb: (...args: T) => void, data: T[]): void { for (const entry of data) { it(`${name}(${entry.map(formatTheoryDatum).join(", ")})`, () => cb(...entry)); } From eeb61656c39146461c990961763a2329962e1aaa Mon Sep 17 00:00:00 2001 From: Isabel Duan Date: Tue, 13 Aug 2024 01:08:42 -0700 Subject: [PATCH 11/27] generated codefixes testrunner --- src/testRunner/compilerRunner.ts | 8 +- src/testRunner/fourslashRunner.ts | 6 +- src/testRunner/parallel/host.ts | 2 +- src/testRunner/parallel/shared.ts | 2 +- src/testRunner/parallel/worker.ts | 2 +- src/testRunner/projectsRunner.ts | 4 +- src/testRunner/transpileRunner.ts | 6 +- src/testRunner/unittests/config/helpers.ts | 4 +- src/testRunner/unittests/helpers.ts | 12 +- .../unittests/helpers/alternateResult.ts | 4 +- src/testRunner/unittests/helpers/baseline.ts | 8 +- src/testRunner/unittests/helpers/contents.ts | 9 +- .../unittests/helpers/declarationEmit.ts | 6 +- .../helpers/demoProjectReferences.ts | 8 +- src/testRunner/unittests/helpers/extends.ts | 2 +- .../unittests/helpers/libraryResolution.ts | 14 ++- .../monorepoSymlinkedSiblingPackages.ts | 2 +- src/testRunner/unittests/helpers/noCheck.ts | 2 +- src/testRunner/unittests/helpers/noEmit.ts | 8 +- .../unittests/helpers/noEmitOnError.ts | 4 +- .../unittests/helpers/projectRoots.ts | 2 +- .../helpers/sampleProjectReferences.ts | 10 +- .../unittests/helpers/solutionBuilder.ts | 8 +- .../unittests/helpers/transitiveReferences.ts | 6 +- src/testRunner/unittests/helpers/tsc.ts | 14 +-- src/testRunner/unittests/helpers/tscWatch.ts | 16 +-- src/testRunner/unittests/helpers/tsserver.ts | 48 ++++---- .../unittests/helpers/typingsInstaller.ts | 4 +- src/testRunner/unittests/helpers/vfs.ts | 24 ++-- .../helpers/virtualFileSystemWithWatch.ts | 114 +++++++++--------- .../unittests/services/extract/helpers.ts | 4 +- 31 files changed, 186 insertions(+), 177 deletions(-) diff --git a/src/testRunner/compilerRunner.ts b/src/testRunner/compilerRunner.ts index 8ec63a8b7b921..aed00f47656b3 100644 --- a/src/testRunner/compilerRunner.ts +++ b/src/testRunner/compilerRunner.ts @@ -46,17 +46,17 @@ export class CompilerBaselineRunner extends RunnerBase { this.basePath += "/" + this.testSuiteName; } - public kind() { + public kind(): TestRunnerKind { return this.testSuiteName; } private testFiles: string[] | undefined; - public enumerateTestFiles() { + public enumerateTestFiles(): string[] { // see also: `enumerateTestFiles` in tests/webTestServer.ts return this.testFiles ??= this.enumerateFiles(this.basePath, /\.tsx?$/, { recursive: true }); } - public initializeTests() { + public initializeTests(): void { describe(this.testSuiteName + " tests", () => { describe("Setup compiler for compiler baselines", () => { this.parseOptions(); @@ -70,7 +70,7 @@ export class CompilerBaselineRunner extends RunnerBase { }); } - public checkTestCodeOutput(fileName: string, test?: CompilerFileBasedTest) { + public checkTestCodeOutput(fileName: string, test?: CompilerFileBasedTest): void { if (test && ts.some(test.configurations)) { test.configurations.forEach(configuration => { describe(`${this.testSuiteName} tests for ${fileName}${configuration ? ` (${getFileBasedTestConfigurationDescription(configuration)})` : ``}`, () => { diff --git a/src/testRunner/fourslashRunner.ts b/src/testRunner/fourslashRunner.ts index e1a0535963ca3..841cfd0b9b051 100644 --- a/src/testRunner/fourslashRunner.ts +++ b/src/testRunner/fourslashRunner.ts @@ -26,16 +26,16 @@ export class FourSlashRunner extends RunnerBase { } } - public enumerateTestFiles() { + public enumerateTestFiles(): string[] { // see also: `enumerateTestFiles` in tests/webTestServer.ts return this.enumerateFiles(this.basePath, /\.ts/i, { recursive: false }); } - public kind() { + public kind(): TestRunnerKind { return this.testSuiteName; } - public initializeTests() { + public initializeTests(): void { if (this.tests.length === 0) { this.tests = IO.enumerateTestFiles(this); } diff --git a/src/testRunner/parallel/host.ts b/src/testRunner/parallel/host.ts index 0df41fb73e2fd..400971655c6b4 100644 --- a/src/testRunner/parallel/host.ts +++ b/src/testRunner/parallel/host.ts @@ -33,7 +33,7 @@ import { import * as ts from "../_namespaces/ts.js"; import * as Utils from "../_namespaces/Utils.js"; -export function start(importTests: () => Promise) { +export function start(importTests: () => Promise): void { const Base = Mocha.reporters.Base; const color = Base.color; const cursor = Base.cursor; diff --git a/src/testRunner/parallel/shared.ts b/src/testRunner/parallel/shared.ts index 53d310eefcf15..e0adb6db04163 100644 --- a/src/testRunner/parallel/shared.ts +++ b/src/testRunner/parallel/shared.ts @@ -75,7 +75,7 @@ export interface ParallelTimeoutChangeMessage { export type ParallelClientMessage = ParallelErrorMessage | ParallelResultMessage | ParallelBatchProgressMessage | ParallelTimeoutChangeMessage; -export function shimNoopTestInterface(global: Mocha.MochaGlobals) { +export function shimNoopTestInterface(global: Mocha.MochaGlobals): void { global.before = ts.noop; global.after = ts.noop; global.beforeEach = ts.noop; diff --git a/src/testRunner/parallel/worker.ts b/src/testRunner/parallel/worker.ts index 23c089ef35411..0dde6ae90cab3 100644 --- a/src/testRunner/parallel/worker.ts +++ b/src/testRunner/parallel/worker.ts @@ -17,7 +17,7 @@ import { UnitTestTask, } from "../_namespaces/Harness.Parallel.js"; -export function start(importTests: () => Promise) { +export function start(importTests: () => Promise): void { // This brings in the tests after we finish setting things up and yield to the event loop. const importTestsPromise = importTests(); diff --git a/src/testRunner/projectsRunner.ts b/src/testRunner/projectsRunner.ts index fa5d15a11a13e..5befdf497dff2 100644 --- a/src/testRunner/projectsRunner.ts +++ b/src/testRunner/projectsRunner.ts @@ -38,7 +38,7 @@ interface BatchCompileProjectTestCaseResult extends CompileProjectFilesResult { } export class ProjectRunner extends Harness.RunnerBase { - public enumerateTestFiles() { + public enumerateTestFiles(): string[] { const all = this.enumerateFiles("tests/cases/project", /\.json$/, { recursive: true }); if (Harness.shards === 1) { return all; @@ -50,7 +50,7 @@ export class ProjectRunner extends Harness.RunnerBase { return "project"; } - public initializeTests() { + public initializeTests(): void { describe("projects tests", () => { const tests = this.tests.length === 0 ? this.enumerateTestFiles() : this.tests; for (const test of tests) { diff --git a/src/testRunner/transpileRunner.ts b/src/testRunner/transpileRunner.ts index 5ef62de5c806e..3926aa9b7d88e 100644 --- a/src/testRunner/transpileRunner.ts +++ b/src/testRunner/transpileRunner.ts @@ -14,16 +14,16 @@ export class TranspileRunner extends RunnerBase { protected basePath = "tests/cases/transpile"; protected testSuiteName: TestRunnerKind = "transpile"; - public enumerateTestFiles() { + public enumerateTestFiles(): string[] { // see also: `enumerateTestFiles` in tests/webTestServer.ts return this.enumerateFiles(this.basePath, /\.[cm]?[tj]sx?/i, { recursive: true }); } - public kind() { + public kind(): TestRunnerKind { return this.testSuiteName; } - public initializeTests() { + public initializeTests(): void { if (this.tests.length === 0) { this.tests = IO.enumerateTestFiles(this); } diff --git a/src/testRunner/unittests/config/helpers.ts b/src/testRunner/unittests/config/helpers.ts index 5a5aa78c24fed..084238fcd0499 100644 --- a/src/testRunner/unittests/config/helpers.ts +++ b/src/testRunner/unittests/config/helpers.ts @@ -65,12 +65,12 @@ export interface BaselineParseConfigInput { skipFs?: boolean; header?(baseline: string[]): void; } -export function baselineParseConfig(input: BaselineParseConfigInput) { +export function baselineParseConfig(input: BaselineParseConfigInput): void { if (!input.skipJson) baselineParseConfigWith("with json api", getParsedCommandJson, input); baselineParseConfigWith("with jsonSourceFile api", getParsedCommandJsonSourceFile, input); } -export function baselineParseConfigHost(baseline: string[], host: fakes.ParseConfigHost) { +export function baselineParseConfigHost(baseline: string[], host: fakes.ParseConfigHost): void { baseline.push("Fs::", vfs.formatPatch(host.sys.vfs.diff(/*base*/ undefined, { baseIsNotShadowRoot: true })!)); } diff --git a/src/testRunner/unittests/helpers.ts b/src/testRunner/unittests/helpers.ts index 026fdf7df5428..fc46832a59bb0 100644 --- a/src/testRunner/unittests/helpers.ts +++ b/src/testRunner/unittests/helpers.ts @@ -32,7 +32,7 @@ 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 = ChangedPart.none, private version = 0) { } static New(references: string, importsAndExports: string, program: string): SourceText { @@ -59,7 +59,7 @@ export class SourceText implements ts.IScriptSnapshot { return new SourceText(this.references, this.importsAndExports, newProgram, this.changedPart | ChangedPart.program, this.version + 1); } - public getFullText() { + public getFullText(): string { return this.fullText || (this.fullText = this.references + this.importsAndExports + this.program); } @@ -103,7 +103,7 @@ function createSourceFileWithText(fileName: string, sourceText: SourceText, targ return file; } -export function createTestCompilerHost(texts: readonly NamedSourceText[], target: ts.ScriptTarget, oldProgram?: ProgramWithSourceTexts, useGetSourceFileByPath?: boolean, useCaseSensitiveFileNames?: boolean) { +export function createTestCompilerHost(texts: readonly NamedSourceText[], target: ts.ScriptTarget, oldProgram?: ProgramWithSourceTexts, useGetSourceFileByPath?: boolean, useCaseSensitiveFileNames?: boolean): TestCompilerHost { const files = ts.arrayToMap(texts, t => t.name, t => { if (oldProgram) { let oldFile = oldProgram.getSourceFile(t.name) as SourceFileWithText; @@ -163,7 +163,7 @@ function programToProgramWithSourceTexts(program: ts.Program, texts: NamedSource return result; } -export function updateProgram(oldProgram: ProgramWithSourceTexts, rootNames: readonly string[], options: ts.CompilerOptions, updater: (files: NamedSourceText[]) => void, newTexts?: NamedSourceText[], useGetSourceFileByPath?: boolean, useCaseSensitiveFileNames?: boolean) { +export function updateProgram(oldProgram: ProgramWithSourceTexts, rootNames: readonly string[], options: ts.CompilerOptions, updater: (files: NamedSourceText[]) => void, newTexts?: NamedSourceText[], useGetSourceFileByPath?: boolean, useCaseSensitiveFileNames?: boolean): ProgramWithSourceTexts { if (!newTexts) { newTexts = oldProgram.sourceTexts!.slice(0); } @@ -177,11 +177,11 @@ export function updateProgram(oldProgram: ProgramWithSourceTexts, rootNames: rea ); } -export function updateProgramText(files: readonly NamedSourceText[], fileName: string, newProgramText: string) { +export function updateProgramText(files: readonly NamedSourceText[], fileName: string, newProgramText: string): void { const file = ts.find(files, f => f.name === fileName)!; file.text = file.text.updateProgram(newProgramText); } -export function jsonToReadableText(json: any) { +export function jsonToReadableText(json: any): string { return JSON.stringify(json, undefined, 2); } diff --git a/src/testRunner/unittests/helpers/alternateResult.ts b/src/testRunner/unittests/helpers/alternateResult.ts index 265f9c0c0f767..8156155837155 100644 --- a/src/testRunner/unittests/helpers/alternateResult.ts +++ b/src/testRunner/unittests/helpers/alternateResult.ts @@ -3,7 +3,7 @@ import { jsonToReadableText } from "../helpers.js"; import { FsContents } from "./contents.js"; import { libFile } from "./virtualFileSystemWithWatch.js"; -export function getFsConentsForAlternateResultAtTypesPackageJson(packageName: string, addTypesCondition: boolean) { +export function getFsConentsForAlternateResultAtTypesPackageJson(packageName: string, addTypesCondition: boolean): string { return jsonToReadableText({ name: `@types/${packageName}`, version: "1.0.0", @@ -17,7 +17,7 @@ export function getFsConentsForAlternateResultAtTypesPackageJson(packageName: st }); } -export function getFsContentsForAlternateResultPackageJson(packageName: string, addTypes: boolean, addTypesCondition: boolean) { +export function getFsContentsForAlternateResultPackageJson(packageName: string, addTypes: boolean, addTypesCondition: boolean): string { return jsonToReadableText({ name: packageName, version: "1.0.0", diff --git a/src/testRunner/unittests/helpers/baseline.ts b/src/testRunner/unittests/helpers/baseline.ts index 7f5cc3e7390cd..84183f87fafef 100644 --- a/src/testRunner/unittests/helpers/baseline.ts +++ b/src/testRunner/unittests/helpers/baseline.ts @@ -5,7 +5,7 @@ import { jsonToReadableText } from "../helpers.js"; import { TscCompileSystem } from "./tsc.js"; import { TestServerHost } from "./virtualFileSystemWithWatch.js"; -export function sanitizeSysOutput(output: string) { +export function sanitizeSysOutput(output: string): string { return output .replace(/Elapsed::\s[0-9]+(?:\.\d+)?ms/g, "Elapsed:: *ms") .replace(/[0-9][0-9]:[0-9][0-9]:[0-9][0-9]\s(A|P)M/g, "HH:MM:SS AM"); @@ -48,7 +48,7 @@ export function commandLineCallbacks( }; } -export function baselinePrograms(baseline: string[], programs: readonly CommandLineProgram[], oldPrograms: readonly (CommandLineProgram | undefined)[], baselineDependencies: boolean | undefined) { +export function baselinePrograms(baseline: string[], programs: readonly CommandLineProgram[], oldPrograms: readonly (CommandLineProgram | undefined)[], baselineDependencies: boolean | undefined): void { for (let i = 0; i < programs.length; i++) { baselineProgram(baseline, programs[i], oldPrograms[i], baselineDependencies); } @@ -127,7 +127,7 @@ function baselineProgram(baseline: string[], [program, builderProgram]: CommandL baseline.push(""); } -export function generateSourceMapBaselineFiles(sys: ts.System & { writtenFiles: ts.ReadonlyCollection; }) { +export function generateSourceMapBaselineFiles(sys: ts.System & { writtenFiles: ts.ReadonlyCollection; }): void { const mapFileNames = ts.mapDefinedIterator(sys.writtenFiles.keys(), f => f.endsWith(".map") ? f : undefined); for (const mapFile of mapFileNames) { const text = Harness.SourceMapRecorder.getSourceMapRecordWithSystem(sys, mapFile); @@ -398,7 +398,7 @@ export function baselineBuildInfo( options: ts.CompilerOptions, sys: TscCompileSystem | TestServerHost, originalReadCall?: ts.System["readFile"], -) { +): void { const buildInfoPath = ts.getTsBuildInfoEmitOutputFilePath(options); if (!buildInfoPath || !sys.writtenFiles!.has(toPathWithSystem(sys, buildInfoPath))) return; if (!sys.fileExists(buildInfoPath)) return; diff --git a/src/testRunner/unittests/helpers/contents.ts b/src/testRunner/unittests/helpers/contents.ts index 943093d2704af..9ba679d24b208 100644 --- a/src/testRunner/unittests/helpers/contents.ts +++ b/src/testRunner/unittests/helpers/contents.ts @@ -1,11 +1,11 @@ import * as ts from "../../_namespaces/ts.js"; import { libFile } from "./virtualFileSystemWithWatch.js"; -export function compilerOptionsToConfigJson(options: ts.CompilerOptions) { +export function compilerOptionsToConfigJson(options: ts.CompilerOptions): object { return ts.optionMapToObject(ts.serializeCompilerOptions(options)); } -export const libContent = `${libFile.content} +export const libContent: string = `${libFile.content} interface ReadonlyArray {} declare const console: { log(msg: any): void; };`; @@ -28,6 +28,9 @@ export function libPath(forLib: string) { return `${ts.getDirectoryPath(libFile.path)}/lib.${forLib}.d.ts`; } -export function getProjectConfigWithNodeNext(withNodeNext: boolean | undefined) { +export function getProjectConfigWithNodeNext(withNodeNext: boolean | undefined): { + module: string; + target: string; +} | undefined { return withNodeNext ? { module: "nodenext", target: "es5" } : undefined; } diff --git a/src/testRunner/unittests/helpers/declarationEmit.ts b/src/testRunner/unittests/helpers/declarationEmit.ts index c99e2e0c2472d..f888384f5624b 100644 --- a/src/testRunner/unittests/helpers/declarationEmit.ts +++ b/src/testRunner/unittests/helpers/declarationEmit.ts @@ -5,7 +5,7 @@ import { jsonToReadableText } from "../helpers.js"; import { libContent } from "./contents.js"; import { loadProjectFromFiles } from "./vfs.js"; -export function getFsForDeclarationEmitWithErrors(options: CompilerOptions, incremental: true | undefined) { +export function getFsForDeclarationEmitWithErrors(options: CompilerOptions, incremental: true | undefined): FileSystem { return loadProjectFromFiles({ "/src/project/tsconfig.json": jsonToReadableText({ compilerOptions: { @@ -40,7 +40,7 @@ export function getFsForDeclarationEmitWithErrors(options: CompilerOptions, incr }); } -export function getFsForDeclarationEmitWithErrorsWithOutFile(options: CompilerOptions, incremental: true | undefined) { +export function getFsForDeclarationEmitWithErrorsWithOutFile(options: CompilerOptions, incremental: true | undefined): FileSystem { return loadProjectFromFiles({ "/src/project/tsconfig.json": jsonToReadableText({ compilerOptions: { @@ -74,7 +74,7 @@ export function forEachDeclarationEmitWithErrorsScenario( fs: () => FileSystem, ) => void, withComposite: boolean, -) { +): void { for (const outFile of [false, true]) { for (const incremental of [undefined, true] as const) { action( diff --git a/src/testRunner/unittests/helpers/demoProjectReferences.ts b/src/testRunner/unittests/helpers/demoProjectReferences.ts index 9276fbc8d88cd..13eaf9e69f523 100644 --- a/src/testRunner/unittests/helpers/demoProjectReferences.ts +++ b/src/testRunner/unittests/helpers/demoProjectReferences.ts @@ -1,4 +1,5 @@ import { dedent } from "../../_namespaces/Utils.js"; +import { FileSystem } from "../../_namespaces/vfs.js"; import { jsonToReadableText } from "../helpers.js"; import { FsContents, @@ -8,9 +9,10 @@ import { loadProjectFromFiles } from "./vfs.js"; import { createWatchedSystem, libFile, + TestServerHost, } from "./virtualFileSystemWithWatch.js"; -export function getFsContentsForDemoProjectReferencesCoreConfig(additional?: object) { +export function getFsContentsForDemoProjectReferencesCoreConfig(additional?: object): string { return jsonToReadableText({ extends: "../tsconfig-base.json", compilerOptions: { @@ -128,7 +130,7 @@ export function getFsContentsForDemoProjectReferences(): FsContents { }; } -export function getFsForDemoProjectReferences() { +export function getFsForDemoProjectReferences(): FileSystem { return loadProjectFromFiles( getFsContentsForDemoProjectReferences(), { @@ -138,7 +140,7 @@ export function getFsForDemoProjectReferences() { ); } -export function getSysForDemoProjectReferences() { +export function getSysForDemoProjectReferences(): TestServerHost { return createWatchedSystem( getFsContentsForDemoProjectReferences(), { diff --git a/src/testRunner/unittests/helpers/extends.ts b/src/testRunner/unittests/helpers/extends.ts index a67007064efaa..a776622926a4b 100644 --- a/src/testRunner/unittests/helpers/extends.ts +++ b/src/testRunner/unittests/helpers/extends.ts @@ -86,7 +86,7 @@ export function getConfigDirExtendsSys(): FsContents { }; } -export function modifyFirstExtendedConfigOfConfigDirExtendsSys(sys: TestServerHost) { +export function modifyFirstExtendedConfigOfConfigDirExtendsSys(sys: TestServerHost): void { sys.modifyFile( "/home/src/projects/configs/first/tsconfig.json", jsonToReadableText({ diff --git a/src/testRunner/unittests/helpers/libraryResolution.ts b/src/testRunner/unittests/helpers/libraryResolution.ts index bbe0b0c22052d..9b2b8f1b8724c 100644 --- a/src/testRunner/unittests/helpers/libraryResolution.ts +++ b/src/testRunner/unittests/helpers/libraryResolution.ts @@ -1,4 +1,5 @@ import { dedent } from "../../_namespaces/Utils.js"; +import { FileSystem } from "../../_namespaces/vfs.js"; import { jsonToReadableText } from "../helpers.js"; import { FsContents, @@ -8,6 +9,7 @@ import { loadProjectFromFiles } from "./vfs.js"; import { createServerHost, createWatchedSystem, + TestServerHost, } from "./virtualFileSystemWithWatch.js"; function getFsContentsForLibResolution(libRedirection?: boolean): FsContents { @@ -56,7 +58,7 @@ function getFsContentsForLibResolution(libRedirection?: boolean): FsContents { }; } -export function getFsForLibResolution(libRedirection: true | undefined) { +export function getFsForLibResolution(libRedirection: true | undefined): FileSystem { return loadProjectFromFiles( getFsContentsForLibResolution(libRedirection), { @@ -66,7 +68,7 @@ export function getFsForLibResolution(libRedirection: true | undefined) { ); } -export function getSysForLibResolution(libRedirection?: true) { +export function getSysForLibResolution(libRedirection?: true): TestServerHost { return createWatchedSystem( getFsContentsForLibResolution(libRedirection), { @@ -76,7 +78,7 @@ export function getSysForLibResolution(libRedirection?: true) { ); } -export function getServerHostForLibResolution(libRedirection?: true) { +export function getServerHostForLibResolution(libRedirection?: true): TestServerHost { return createServerHost( getFsContentsForLibResolution(libRedirection), { @@ -86,7 +88,7 @@ export function getServerHostForLibResolution(libRedirection?: true) { ); } -export function getCommandLineArgsForLibResolution(withoutConfig: true | undefined) { +export function getCommandLineArgsForLibResolution(withoutConfig: true | undefined): string[] { 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"]; @@ -115,7 +117,7 @@ function getFsContentsForLibResolutionUnknown(): FsContents { }; } -export function getFsForLibResolutionUnknown() { +export function getFsForLibResolutionUnknown(): FileSystem { return loadProjectFromFiles( getFsContentsForLibResolutionUnknown(), { @@ -125,7 +127,7 @@ export function getFsForLibResolutionUnknown() { ); } -export function getSysForLibResolutionUnknown() { +export function getSysForLibResolutionUnknown(): TestServerHost { return createWatchedSystem( getFsContentsForLibResolutionUnknown(), { diff --git a/src/testRunner/unittests/helpers/monorepoSymlinkedSiblingPackages.ts b/src/testRunner/unittests/helpers/monorepoSymlinkedSiblingPackages.ts index 6da5b685f939d..c3136d38da2e7 100644 --- a/src/testRunner/unittests/helpers/monorepoSymlinkedSiblingPackages.ts +++ b/src/testRunner/unittests/helpers/monorepoSymlinkedSiblingPackages.ts @@ -279,7 +279,7 @@ export function forEachMonorepoSymlinkScenario( edits: () => readonly TscWatchCompileChange[], indexFile: string, ) => void, -) { +): void { describe("monorepoSymlinkedSiblingPackages:: monorepo style sibling packages symlinked", () => { forEachMonorepoSymlinkedSiblingPackagesSys(forTsserver, action); }); diff --git a/src/testRunner/unittests/helpers/noCheck.ts b/src/testRunner/unittests/helpers/noCheck.ts index edf9580c57b97..1b977770ed218 100644 --- a/src/testRunner/unittests/helpers/noCheck.ts +++ b/src/testRunner/unittests/helpers/noCheck.ts @@ -6,7 +6,7 @@ import { } from "./tsc.js"; import { loadProjectFromFiles } from "./vfs.js"; -export function forEachTscScenarioWithNoCheck(buildType: "-b" | "-p") { +export function forEachTscScenarioWithNoCheck(buildType: "-b" | "-p"): void { const commandLineArgs = buildType === "-b" ? ["-b", "/src/tsconfig.json", "-v"] : ["-p", "/src/tsconfig.json"]; diff --git a/src/testRunner/unittests/helpers/noEmit.ts b/src/testRunner/unittests/helpers/noEmit.ts index b097144ec9f0e..4cabe301e719c 100644 --- a/src/testRunner/unittests/helpers/noEmit.ts +++ b/src/testRunner/unittests/helpers/noEmit.ts @@ -154,7 +154,7 @@ function forEachNoEmitChangesWorker(commandType: string[], compilerOptions: Comp } } -export function forEachNoEmitChanges(commandType: string[]) { +export function forEachNoEmitChanges(commandType: string[]): void { describe("when noEmit changes between compilation", () => { forEachNoEmitChangesWorker(commandType, { incremental: true }); forEachNoEmitChangesWorker(commandType, { incremental: true, declaration: true }); @@ -217,7 +217,7 @@ function editsForDtsChanges( ]; } -export function forEachNoEmitDtsChanges(commandType: string[]) { +export function forEachNoEmitDtsChanges(commandType: string[]): void { describe("dts errors with declaration enable changes", () => { if (commandType[0] !== "-b") return; // Only test non multiple file errors with -b [false, true].forEach(asModules => @@ -350,7 +350,7 @@ function forEachNoEmitAndErrors( }); } -export function forEachNoEmitTsc(commandType: string[]) { +export function forEachNoEmitTsc(commandType: string[]): void { forEachNoEmitAndErrors((subScenario, fsContents, aTsContent, fixedATsContent, compilerOptions) => verifyTsc({ scenario: "noEmit", @@ -394,7 +394,7 @@ export function forEachNoEmitTsc(commandType: string[]) { ); } -export function forEachNoEmitTscWatch(commandType: string[]) { +export function forEachNoEmitTscWatch(commandType: string[]): void { forEachNoEmitAndErrors((subScenario, fsContents, aTsContent, fixedATsContent, compilerOptions) => verifyTscWatch({ scenario: "noEmit", diff --git a/src/testRunner/unittests/helpers/noEmitOnError.ts b/src/testRunner/unittests/helpers/noEmitOnError.ts index 38ec1b458d9b0..011ca87c4be92 100644 --- a/src/testRunner/unittests/helpers/noEmitOnError.ts +++ b/src/testRunner/unittests/helpers/noEmitOnError.ts @@ -111,7 +111,7 @@ function getNoEmitOnErrorErrorsType(): [subScenario: string, mainErrorContent: s ]; } -export function forEachNoEmitOnErrorScenarioTsc(commandLineArgs: string[]) { +export function forEachNoEmitOnErrorScenarioTsc(commandLineArgs: string[]): void { getNoEmitOnErrorErrorsType().forEach(([subScenario, mainErrorContent, fixedErrorContent]) => forEachNoEmitOnErrorScenario( subScenario, @@ -145,7 +145,7 @@ export function forEachNoEmitOnErrorScenarioTsc(commandLineArgs: string[]) { ); } -export function forEachNoEmitOnErrorScenarioTscWatch(commandLineArgs: string[]) { +export function forEachNoEmitOnErrorScenarioTscWatch(commandLineArgs: string[]): void { const errorTypes = getNoEmitOnErrorErrorsType(); forEachNoEmitOnErrorScenario( "noEmitOnError", diff --git a/src/testRunner/unittests/helpers/projectRoots.ts b/src/testRunner/unittests/helpers/projectRoots.ts index 916290bfd49ec..e34f590596caa 100644 --- a/src/testRunner/unittests/helpers/projectRoots.ts +++ b/src/testRunner/unittests/helpers/projectRoots.ts @@ -60,7 +60,7 @@ function getFsContentsForRootsFromReferencedProject(serverFirst: boolean): FsCon }; } -export function forEachScenarioForRootsFromReferencedProject(action: (subScenario: string, getFsContents: () => FsContents) => void) { +export function forEachScenarioForRootsFromReferencedProject(action: (subScenario: string, getFsContents: () => FsContents) => void): void { action("when root file is from referenced project", () => getFsContentsForRootsFromReferencedProject(/*serverFirst*/ true)); action("when root file is from referenced project and shared is first", () => getFsContentsForRootsFromReferencedProject(/*serverFirst*/ false)); } diff --git a/src/testRunner/unittests/helpers/sampleProjectReferences.ts b/src/testRunner/unittests/helpers/sampleProjectReferences.ts index 7c5634c0120e3..e61705dc18652 100644 --- a/src/testRunner/unittests/helpers/sampleProjectReferences.ts +++ b/src/testRunner/unittests/helpers/sampleProjectReferences.ts @@ -1,4 +1,5 @@ import { dedent } from "../../_namespaces/Utils.js"; +import { FileSystem } from "../../_namespaces/vfs.js"; import { jsonToReadableText } from "../helpers.js"; import { FsContents, @@ -9,9 +10,10 @@ import { createServerHost, createWatchedSystem, libFile, + TestServerHost, } from "./virtualFileSystemWithWatch.js"; -export function getFsContentsForSampleProjectReferencesLogicConfig(withNodeNext?: boolean) { +export function getFsContentsForSampleProjectReferencesLogicConfig(withNodeNext?: boolean): string { return jsonToReadableText({ compilerOptions: { ...getProjectConfigWithNodeNext(withNodeNext), @@ -81,7 +83,7 @@ export function getFsContentsForSampleProjectReferences(withNodeNext?: boolean): }; } -export function getFsForSampleProjectReferences() { +export function getFsForSampleProjectReferences(): FileSystem { return loadProjectFromFiles( getFsContentsForSampleProjectReferences(), { @@ -91,7 +93,7 @@ export function getFsForSampleProjectReferences() { ); } -export function getSysForSampleProjectReferences(withNodeNext?: boolean) { +export function getSysForSampleProjectReferences(withNodeNext?: boolean): TestServerHost { return createWatchedSystem( getFsContentsForSampleProjectReferences(withNodeNext), { @@ -100,7 +102,7 @@ export function getSysForSampleProjectReferences(withNodeNext?: boolean) { ); } -export function getServerHostForSampleProjectReferences() { +export function getServerHostForSampleProjectReferences(): TestServerHost { return createServerHost( getFsContentsForSampleProjectReferences(), { diff --git a/src/testRunner/unittests/helpers/solutionBuilder.ts b/src/testRunner/unittests/helpers/solutionBuilder.ts index 7225deed28def..fd09c5293ade9 100644 --- a/src/testRunner/unittests/helpers/solutionBuilder.ts +++ b/src/testRunner/unittests/helpers/solutionBuilder.ts @@ -15,7 +15,7 @@ export function createSolutionBuilderHostForBaseline( sys: TscCompileSystem | TestServerHost, versionToWrite?: string, originalRead?: (TscCompileSystem | TestServerHost)["readFile"], -) { +): ts.SolutionBuilderHost { 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)); @@ -23,18 +23,18 @@ export function createSolutionBuilderHostForBaseline( return host; } -export function createSolutionBuilder(system: TestServerHost, rootNames: readonly string[], originalRead?: TestServerHost["readFile"]) { +export function createSolutionBuilder(system: TestServerHost, rootNames: readonly string[], originalRead?: TestServerHost["readFile"]): ts.SolutionBuilder { const host = createSolutionBuilderHostForBaseline(system, /*versionToWrite*/ undefined, originalRead); return ts.createSolutionBuilder(host, rootNames, {}); } -export function ensureErrorFreeBuild(host: TestServerHost, rootNames: readonly string[]) { +export function ensureErrorFreeBuild(host: TestServerHost, rootNames: readonly string[]): void { // ts build should succeed solutionBuildWithBaseline(host, rootNames); assert.equal(host.getOutput().length, 0, jsonToReadableText(host.getOutput())); } -export function solutionBuildWithBaseline(sys: TestServerHost, solutionRoots: readonly string[], originalRead?: TestServerHost["readFile"]) { +export function solutionBuildWithBaseline(sys: TestServerHost, solutionRoots: readonly string[], originalRead?: TestServerHost["readFile"]): TestServerHost { if (sys.writtenFiles === undefined) { const originalReadFile = sys.readFile; const originalWrite = sys.write; diff --git a/src/testRunner/unittests/helpers/transitiveReferences.ts b/src/testRunner/unittests/helpers/transitiveReferences.ts index 7bfc10aec4792..1ae79b9650f37 100644 --- a/src/testRunner/unittests/helpers/transitiveReferences.ts +++ b/src/testRunner/unittests/helpers/transitiveReferences.ts @@ -7,14 +7,14 @@ import { } from "./contents.js"; import { libFile } from "./virtualFileSystemWithWatch.js"; -export function getFsContentsForTransitiveReferencesRefsAdts() { +export function getFsContentsForTransitiveReferencesRefsAdts(): string { return dedent` export class X {} export class A {} `; } -export function getFsContentsForTransitiveReferencesBConfig(withNodeNext: boolean) { +export function getFsContentsForTransitiveReferencesBConfig(withNodeNext: boolean): string { return jsonToReadableText({ compilerOptions: { ...getProjectConfigWithNodeNext(withNodeNext), @@ -29,7 +29,7 @@ export function getFsContentsForTransitiveReferencesBConfig(withNodeNext: boolea }); } -export function getFsContentsForTransitiveReferencesAConfig(withNodeNext: boolean) { +export function getFsContentsForTransitiveReferencesAConfig(withNodeNext: boolean): string { return jsonToReadableText({ compilerOptions: { ...getProjectConfigWithNodeNext(withNodeNext), diff --git a/src/testRunner/unittests/helpers/tsc.ts b/src/testRunner/unittests/helpers/tsc.ts index 078b7bc74e131..a41a10fb5a96c 100644 --- a/src/testRunner/unittests/helpers/tsc.ts +++ b/src/testRunner/unittests/helpers/tsc.ts @@ -33,7 +33,7 @@ export const noChangeRun: TestTscEdit = { caption: "no-change-run", edit: ts.noop, }; -export const noChangeOnlyRuns = [noChangeRun]; +export const noChangeOnlyRuns: TestTscEdit[] = [noChangeRun]; export interface TestTscCompile extends TestTscCompileLikeBase { baselineSourceMap?: boolean; @@ -56,7 +56,7 @@ export interface TestTscCompileLike extends TestTscCompileLikeBase { /** * Initialize FS, run compile function and save baseline */ -export function testTscCompileLike(input: TestTscCompileLike) { +export function testTscCompileLike(input: TestTscCompileLike): TscCompileSystem { const initialFs = input.fs(); const inputFs = initialFs.shadow(); const { @@ -101,7 +101,7 @@ ${patch ? vfs.formatPatch(patch) : ""}`, return sys; } -export function makeSystemReadyForBaseline(sys: TscCompileSystem, versionToWrite?: string) { +export function makeSystemReadyForBaseline(sys: TscCompileSystem, versionToWrite?: string): void { if (versionToWrite) { fakes.patchHostForBuildInfoWrite(sys, versionToWrite); } @@ -124,7 +124,7 @@ export function makeSystemReadyForBaseline(sys: TscCompileSystem, versionToWrite /** * Initialize Fs, execute command line and save baseline */ -export function testTscCompile(input: TestTscCompile) { +export function testTscCompile(input: TestTscCompile): TscCompileSystem { let actualReadFileMap: ts.MapLike | undefined; let getPrograms: CommandLineCallbacks["getPrograms"] | undefined; return testTscCompileLike({ @@ -205,7 +205,7 @@ function storeDtsSignatures(sys: TscCompileSystem, programs: readonly CommandLin } } -export function verifyTscBaseline(sys: () => { baseLine: TscCompileSystem["baseLine"]; }) { +export function verifyTscBaseline(sys: () => { baseLine: TscCompileSystem["baseLine"]; }): void { it(`Generates files matching the baseline`, () => { const { file, text } = sys().baseLine(); Harness.Baseline.runBaseline(file, text); @@ -221,7 +221,7 @@ 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): void { describe(`tsc ${input.commandLineArgs.join(" ")} ${input.scenario}:: ${input.subScenario}`, () => { describe(input.scenario, () => { describe(input.subScenario, () => { @@ -562,7 +562,7 @@ export function verifyTsc({ baselineReadFileCalls, baselinePrograms, edits, -}: VerifyTscWithEditsInput) { +}: VerifyTscWithEditsInput): void { describe(`tsc ${commandLineArgs.join(" ")} ${scenario}:: ${subScenario}`, () => { let sys: TscCompileSystem; let baseFs: vfs.FileSystem; diff --git a/src/testRunner/unittests/helpers/tscWatch.ts b/src/testRunner/unittests/helpers/tscWatch.ts index a8fe3fe3d4d7f..9469281e72548 100644 --- a/src/testRunner/unittests/helpers/tscWatch.ts +++ b/src/testRunner/unittests/helpers/tscWatch.ts @@ -127,7 +127,7 @@ export function createBaseline(system: TestServerHost, modifySystem?: (sys: Test return { sys, baseline, cb, getPrograms }; } -export function createSolutionBuilderWithWatchHostForBaseline(sys: TestServerHost, cb: ts.ExecuteCommandLineCallbacks) { +export function createSolutionBuilderWithWatchHostForBaseline(sys: TestServerHost, cb: ts.ExecuteCommandLineCallbacks): ts.SolutionBuilderWithWatchHost { 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; return host; @@ -140,7 +140,7 @@ interface CreateWatchCompilerHostOfConfigFileForBaseline( input: CreateWatchCompilerHostOfConfigFileForBaseline, -) { +): ts.WatchCompilerHostOfConfigFile { const host = ts.createWatchCompilerHostOfConfigFile({ ...input, reportDiagnostic: ts.createDiagnosticReporter(input.system, /*pretty*/ true), @@ -156,7 +156,7 @@ interface CreateWatchCompilerHostOfFilesAndCompilerOptionsForBaseline( input: CreateWatchCompilerHostOfFilesAndCompilerOptionsForBaseline, -) { +): ts.WatchCompilerHostOfFilesAndCompilerOptions { const host = ts.createWatchCompilerHostOfFilesAndCompilerOptions({ ...input, reportDiagnostic: ts.createDiagnosticReporter(input.system, /*pretty*/ true), @@ -175,7 +175,7 @@ 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"]): void { baseline.push(`Change::${caption ? " " + caption : ""}`, ""); edit(sys); baseline.push("Input::"); @@ -200,7 +200,7 @@ export function runWatchBaseline) { +}: RunWatchBaseline): void { baseline.push(`${sys.getExecutingFilePath()} ${commandLineArgs.join(" ")}`); let programs = watchBaseline({ baseline, @@ -231,7 +231,7 @@ export function runWatchBaseline { if (arg.charCodeAt(0) !== ts.CharacterCodes.minus) return false; const option = arg.slice(arg.charCodeAt(1) === ts.CharacterCodes.minus ? 2 : 1).toLowerCase(); @@ -256,7 +256,7 @@ export function watchBaseline({ caption, resolutionCache, useSourceOfProjectReferenceRedirect, -}: WatchBaseline) { +}: WatchBaseline): readonly CommandLineProgram[] { if (baselineSourceMap) generateSourceMapBaselineFiles(sys); const programs = getPrograms(); sys.writtenFiles.forEach((value, key) => { @@ -323,7 +323,7 @@ function verifyProgramStructureAndResolutionCache( export interface VerifyTscWatch extends TscWatchCompile { baselineIncremental?: boolean; } -export function verifyTscWatch(input: VerifyTscWatch) { +export function verifyTscWatch(input: VerifyTscWatch): void { describe(input.scenario, () => { describe(input.subScenario, () => { tscWatchCompile(input); diff --git a/src/testRunner/unittests/helpers/tsserver.ts b/src/testRunner/unittests/helpers/tsserver.ts index 4f50d08b09793..acd2ce9d40357 100644 --- a/src/testRunner/unittests/helpers/tsserver.ts +++ b/src/testRunner/unittests/helpers/tsserver.ts @@ -27,7 +27,7 @@ import { TestServerHostTrackingWrittenFiles, } from "./virtualFileSystemWithWatch.js"; -export function baselineTsserverLogs(scenario: string, subScenario: string, sessionOrService: { logger: LoggerWithInMemoryLogs; }) { +export function baselineTsserverLogs(scenario: string, subScenario: string, sessionOrService: { logger: LoggerWithInMemoryLogs; }): void { Harness.Baseline.runBaseline(`tsserver/${scenario}/${subScenario.split(" ").join("-")}.js`, sessionOrService.logger.logs.join("\r\n")); } @@ -35,7 +35,7 @@ export function toExternalFile(fileName: string): ts.server.protocol.ExternalFil return { fileName }; } -export function toExternalFiles(fileNames: string[]) { +export function toExternalFiles(fileNames: string[]): ts.server.protocol.ExternalFile[] { return ts.map(fileNames, toExternalFile); } @@ -47,7 +47,7 @@ export function patchHostTimeouts( inputHost: TestServerHostTrackingWrittenFiles, session: TestSession | undefined, logger: LoggerWithInMemoryLogs, -) { +): TestSessionAndServiceHost { const host = inputHost as TestSessionAndServiceHost; host.service = session?.getProjectService(); if (session) patchServiceForStateBaseline(session.getProjectService()); @@ -216,7 +216,7 @@ export class TestSession extends ts.server.Session { public override logger!: LoggerWithInMemoryLogs; public override readonly typingsInstaller!: TestTypingsInstallerAdapter; public serverCancellationToken: TestServerCancellationToken; - public watchChanges = new Map(); + public watchChanges: Map = new Map(); constructor(optsOrHost: TestSessionConstructorOptions) { const opts = getTestSessionPartialOptionsAndHost(optsOrHost); @@ -255,19 +255,19 @@ export class TestSession extends ts.server.Session { if (opts.canUseWatchEvents) patchSessionToHandleWatchEvents(this); } - getProjectService() { + getProjectService(): ts.server.ProjectService { return this.projectService; } - public getSeq() { + public getSeq(): number { return this.seq; } - public getNextSeq() { + public getNextSeq(): number { return this.seq + 1; } - public override executeCommand(request: ts.server.protocol.Request) { + public override executeCommand(request: ts.server.protocol.Request): ts.server.HandlerResponse { if (this.logger.hasLevel(ts.server.LogLevel.verbose)) { this.host.baselineHost("Before request"); this.logger.info(`request:${ts.server.stringifyIndented(request)}`); @@ -280,7 +280,7 @@ export class TestSession extends ts.server.Session { return response; } - public executeCommandSeq(inputRequest: TestSessionRequest) { + public executeCommandSeq(inputRequest: TestSessionRequest): ts.server.HandlerResponse { this.seq++; const request: T = inputRequest as T; request.seq = this.seq; @@ -288,7 +288,7 @@ export class TestSession extends ts.server.Session { return this.executeCommand(request); } - public invokeWatchChanges() { + public invokeWatchChanges(): void { const changes = ts.singleOrMany(ts.arrayFrom(this.watchChanges.values())); this.watchChanges.clear(); this.executeCommandSeq({ @@ -301,7 +301,7 @@ export class TestSession extends ts.server.Session { export function createSessionWithCustomEventHandler( optsOrHost: TestSessionConstructorOptions, customAction?: (event: ts.server.ProjectServiceEvent) => void, -) { +): TestSession { const opts = getTestSessionPartialOptionsAndHost(optsOrHost); opts.eventHandler = eventHandler; const session = new TestSession(opts); @@ -402,24 +402,24 @@ export class TestServerCancellationToken implements ts.server.ServerCancellation constructor(private logger: LoggerWithInMemoryLogs, private cancelAfterRequest = 0) { } - setRequest(requestId: number) { + setRequest(requestId: number): void { this.currentId = requestId; this.logger.log(`TestServerCancellationToken:: Cancellation Request id:: ${requestId}`); } - setRequestToCancel(requestId: number) { + setRequestToCancel(requestId: number): void { this.logger.log(`TestServerCancellationToken:: Setting request to cancel:: ${requestId}`); this.resetToken(); this.requestToCancel = requestId; } - resetRequest(requestId: number) { + resetRequest(requestId: number): void { 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; } - isCancellationRequested() { + isCancellationRequested(): boolean { this.isCancellationRequestedCount++; // 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 @@ -429,7 +429,7 @@ export class TestServerCancellationToken implements ts.server.ServerCancellation return result; } - resetToken() { + resetToken(): void { this.currentId = -1; this.isCancellationRequestedCount = 0; this.requestToCancel = -1; @@ -471,14 +471,14 @@ export function closeFilesForSession(files: readonly (File | string)[], session: } } -export function openExternalProjectForSession(project: ts.server.protocol.ExternalProject, session: TestSession) { +export function openExternalProjectForSession(project: ts.server.protocol.ExternalProject, session: TestSession): void { session.executeCommandSeq({ command: ts.server.protocol.CommandTypes.OpenExternalProject, arguments: project, }); } -export function openExternalProjectsForSession(projects: ts.server.protocol.ExternalProject[], session: TestSession) { +export function openExternalProjectsForSession(projects: ts.server.protocol.ExternalProject[], session: TestSession): void { session.executeCommandSeq({ command: ts.server.protocol.CommandTypes.OpenExternalProjects, arguments: { projects }, @@ -488,7 +488,7 @@ export function openExternalProjectsForSession(projects: ts.server.protocol.Exte export function setCompilerOptionsForInferredProjectsRequestForSession( options: ts.server.protocol.InferredProjectCompilerOptions | ts.server.protocol.SetCompilerOptionsForInferredProjectsArgs, session: TestSession, -) { +): void { session.executeCommandSeq({ command: ts.server.protocol.CommandTypes.CompilerOptionsForInferredProjects, arguments: "options" in options ? // eslint-disable-line local/no-in-operator @@ -497,7 +497,7 @@ export function setCompilerOptionsForInferredProjectsRequestForSession( }); } -export function logDiagnostics(sessionOrService: TestSession, diagnosticsType: string, project: ts.server.Project, diagnostics: readonly ts.Diagnostic[]) { +export function logDiagnostics(sessionOrService: TestSession, diagnosticsType: string, project: ts.server.Project, diagnostics: readonly ts.Diagnostic[]): void { sessionOrService.logger.info(`${diagnosticsType}:: ${diagnostics.length}`); diagnostics.forEach(d => sessionOrService.logger.info(ts.formatDiagnostic(d, project))); } @@ -509,7 +509,7 @@ export interface VerifyGetErrRequest extends VerifyGetErrRequestBase { files: readonly (string | File | FileRangesRequestArgs)[]; skip?: CheckAllErrors["skip"]; } -export function verifyGetErrRequest(request: VerifyGetErrRequest) { +export function verifyGetErrRequest(request: VerifyGetErrRequest): void { const { session, files } = request; session.executeCommandSeq({ command: ts.server.protocol.CommandTypes.Geterr, @@ -619,13 +619,13 @@ export interface VerifyGetErrScenario { getErrForProjectRequest: () => readonly GetErrForProjectDiagnostics[]; syncDiagnostics: () => readonly SyncDiagnostics[]; } -export function verifyGetErrScenario(scenario: VerifyGetErrScenario) { +export function verifyGetErrScenario(scenario: VerifyGetErrScenario): void { verifyErrorsUsingGeterr(scenario); verifyErrorsUsingGeterrForProject(scenario); verifyErrorsUsingSyncMethods(scenario); } -export function createHostWithSolutionBuild(files: readonly FileOrFolderOrSymLink[], rootNames: readonly string[]) { +export function createHostWithSolutionBuild(files: readonly FileOrFolderOrSymLink[], rootNames: readonly string[]): TestServerHost { const host = createServerHost(files); // ts build should succeed ensureErrorFreeBuild(host, rootNames); @@ -636,7 +636,7 @@ export function forEachTscWatchEdit( session: TestSession, edits: readonly TscWatchCompileChange[], action: () => void, -) { +): void { edits.forEach(edit => { session.logger.log(edit.caption); edit.edit(session.host); diff --git a/src/testRunner/unittests/helpers/typingsInstaller.ts b/src/testRunner/unittests/helpers/typingsInstaller.ts index 752992304827d..5048016b87857 100644 --- a/src/testRunner/unittests/helpers/typingsInstaller.ts +++ b/src/testRunner/unittests/helpers/typingsInstaller.ts @@ -161,7 +161,7 @@ export class TestTypingsInstallerWorker extends ts.server.typingsInstaller.Typin ); } - sendResponse(response: ts.server.SetTypings | ts.server.InvalidateCachedTypings | ts.server.BeginInstallTypes | ts.server.EndInstallTypes | ts.server.WatchTypingLocations | ts.server.PackageInstalledResponse) { + sendResponse(response: ts.server.SetTypings | ts.server.InvalidateCachedTypings | ts.server.BeginInstallTypes | ts.server.EndInstallTypes | ts.server.WatchTypingLocations | ts.server.PackageInstalledResponse): void { this.log.writeLine(`Sending response:${stringifyIndented(response)}`); this.testTypingInstaller.handleMessage(response); } @@ -240,6 +240,6 @@ function createTypesRegistryFileContent(list: readonly string[]): TypesRegistryF return { entries }; } -export function createTypesRegistry(...list: string[]) { +export function createTypesRegistry(...list: string[]): Map> { return new Map(Object.entries(createTypesRegistryFileContent(list).entries)); } diff --git a/src/testRunner/unittests/helpers/vfs.ts b/src/testRunner/unittests/helpers/vfs.ts index cd8ec94018a12..7b95f07da7e6a 100644 --- a/src/testRunner/unittests/helpers/vfs.ts +++ b/src/testRunner/unittests/helpers/vfs.ts @@ -36,7 +36,7 @@ export function loadProjectFromFiles( return fs; } -export function replaceText(fs: vfs.FileSystem, path: string, oldText: string, newText: string) { +export function replaceText(fs: vfs.FileSystem, path: string, oldText: string, newText: string): void { if (!fs.statSync(path).isFile()) { throw new Error(`File ${path} does not exist`); } @@ -48,7 +48,7 @@ export function replaceText(fs: vfs.FileSystem, path: string, oldText: string, n fs.writeFileSync(path, newContent, "utf-8"); } -export function prependText(fs: vfs.FileSystem, path: string, additionalContent: string) { +export function prependText(fs: vfs.FileSystem, path: string, additionalContent: string): void { if (!fs.statSync(path).isFile()) { throw new Error(`File ${path} does not exist`); } @@ -56,7 +56,7 @@ export function prependText(fs: vfs.FileSystem, path: string, additionalContent: fs.writeFileSync(path, `${additionalContent}${old}`, "utf-8"); } -export function appendText(fs: vfs.FileSystem, path: string, additionalContent: string) { +export function appendText(fs: vfs.FileSystem, path: string, additionalContent: string): void { if (!fs.statSync(path).isFile()) { throw new Error(`File ${path} does not exist`); } @@ -64,11 +64,11 @@ export function appendText(fs: vfs.FileSystem, path: string, additionalContent: fs.writeFileSync(path, `${old}${additionalContent}`); } -export function enableStrict(fs: vfs.FileSystem, path: string) { +export function enableStrict(fs: vfs.FileSystem, path: string): void { replaceText(fs, path, `"strict": false`, `"strict": true`); } -export function addTestPrologue(fs: vfs.FileSystem, path: string, prologue: string) { +export function addTestPrologue(fs: vfs.FileSystem, path: string, prologue: string): void { prependText( fs, path, @@ -77,7 +77,7 @@ export function addTestPrologue(fs: vfs.FileSystem, path: string, prologue: stri ); } -export function addShebang(fs: vfs.FileSystem, project: string, file: string) { +export function addShebang(fs: vfs.FileSystem, project: string, file: string): void { prependText( fs, `src/${project}/${file}.ts`, @@ -95,23 +95,23 @@ function nonrestContent(project: string, file: string) { return `function for${project}${file}Rest() { }`; } -export function addRest(fs: vfs.FileSystem, project: string, file: string) { +export function addRest(fs: vfs.FileSystem, project: string, file: string): void { appendText(fs, `src/${project}/${file}.ts`, restContent(project, file)); } -export function removeRest(fs: vfs.FileSystem, project: string, file: string) { +export function removeRest(fs: vfs.FileSystem, project: string, file: string): void { replaceText(fs, `src/${project}/${file}.ts`, restContent(project, file), nonrestContent(project, file)); } -export function addStubFoo(fs: vfs.FileSystem, project: string, file: string) { +export function addStubFoo(fs: vfs.FileSystem, project: string, file: string): void { appendText(fs, `src/${project}/${file}.ts`, nonrestContent(project, file)); } -export function changeStubToRest(fs: vfs.FileSystem, project: string, file: string) { +export function changeStubToRest(fs: vfs.FileSystem, project: string, file: string): void { replaceText(fs, `src/${project}/${file}.ts`, nonrestContent(project, file), restContent(project, file)); } -export function addSpread(fs: vfs.FileSystem, project: string, file: string) { +export function addSpread(fs: vfs.FileSystem, project: string, file: string): void { const path = `src/${project}/${file}.ts`; const content = fs.readFileSync(path, "utf8"); fs.writeFileSync( @@ -135,7 +135,7 @@ export function getTripleSlashRef(project: string) { return `/src/${project}/tripleRef.d.ts`; } -export function addTripleSlashRef(fs: vfs.FileSystem, project: string, file: string) { +export function addTripleSlashRef(fs: vfs.FileSystem, project: string, file: string): void { fs.writeFileSync(getTripleSlashRef(project), `declare class ${project}${file} { }`); prependText( fs, diff --git a/src/testRunner/unittests/helpers/virtualFileSystemWithWatch.ts b/src/testRunner/unittests/helpers/virtualFileSystemWithWatch.ts index 03f49e7d600f9..a618ce776a665 100644 --- a/src/testRunner/unittests/helpers/virtualFileSystemWithWatch.ts +++ b/src/testRunner/unittests/helpers/virtualFileSystemWithWatch.ts @@ -175,7 +175,7 @@ interface CallbackData { time: number; } class Callbacks { - readonly map = new Map(); + readonly map: Map = new Map(); private nextId = 1; invoke: (invokeKey?: number) => void = invokeKey => this.invokeWorker(invokeKey); private hasChanges = false; @@ -184,11 +184,11 @@ class Callbacks { constructor(private host: TestServerHost, readonly callbackType: string, private readonly swallowExitException?: boolean) { } - getNextId() { + getNextId(): number { return this.nextId; } - register(cb: TimeOutCallback, args: any[], ms?: number) { + register(cb: TimeOutCallback, args: any[], ms?: number): number { const timeoutId = this.nextId; this.nextId++; this.map.set(timeoutId, { cb, args, ms, time: this.host.getTime() }); @@ -196,13 +196,13 @@ class Callbacks { return timeoutId; } - unregister(id: any) { + unregister(id: any): void { if (typeof id === "number") { this.hasChanges = this.map.delete(id) || this.hasChanges; } } - log(logChanges?: boolean) { + log(logChanges?: boolean): string { const details: string[] = []; this.map.forEach(({ args }, timeoutId) => { details.push(`${timeoutId}: ${args[0]}${!logChanges || this.serializedKeys.has(timeoutId) ? "" : " *new*"}`); @@ -236,7 +236,7 @@ class Callbacks { cb(...args); } - invokeWorker(invokeKey?: number) { + invokeWorker(invokeKey?: number): void { try { if (invokeKey) return this.invokeCallback(invokeKey); @@ -256,7 +256,7 @@ class Callbacks { } } - switchToBaseliningInvoke(logger: StateLogger, serializeOutputOrder: SerializeOutputOrder) { + switchToBaseliningInvoke(logger: StateLogger, serializeOutputOrder: SerializeOutputOrder): void { this.invoke = invokeKey => { logger.log(`Before running ${this.log()}`); this.host.serializeState(logger.logs, serializeOutputOrder); @@ -267,7 +267,7 @@ class Callbacks { }; } - serialize(baseline: string[]) { + serialize(baseline: string[]): void { if (this.hasChanges) { baseline.push(this.log(/*logChanges*/ true), ""); this.hasChanges = false; @@ -346,9 +346,9 @@ export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost, private time = timeIncrements; getCanonicalFileName: (s: string) => string; toPath: (f: string) => Path; - readonly timeoutCallbacks = new Callbacks(this, "Timeout", /*swallowExitException*/ true); - readonly immediateCallbacks = new Callbacks(this, "Immedidate"); - readonly pendingInstalls = new Callbacks(this, "PendingInstalls"); + readonly timeoutCallbacks: Callbacks = new Callbacks(this, "Timeout", /*swallowExitException*/ true); + readonly immediateCallbacks: Callbacks = new Callbacks(this, "Immedidate"); + readonly pendingInstalls: Callbacks = new Callbacks(this, "PendingInstalls"); readonly screenClears: number[] = []; readonly watchUtils: WatchUtils; @@ -436,39 +436,39 @@ export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost, return true; } - getNewLine() { + getNewLine(): string { return this.newLine; } - toNormalizedAbsolutePath(s: string) { + toNormalizedAbsolutePath(s: string): string { return getNormalizedAbsolutePath(s, this.currentDirectory); } - toFullPath(s: string) { + toFullPath(s: string): Path { return this.toPath(this.toNormalizedAbsolutePath(s)); } - getHostSpecificPath(s: string) { + getHostSpecificPath(s: string): string { if (this.windowsStyleRoot && s.startsWith(directorySeparator)) { return this.windowsStyleRoot + s.substring(1); } return s; } - now() { + now(): Date { this.time += timeIncrements; return new Date(this.time); } - getTime() { + getTime(): number { return this.time; } - setTime(time: number) { + setTime(time: number): void { this.time = time; } - switchToBaseliningInvoke(logger: StateLogger, serializeOutputOrder: SerializeOutputOrder) { + switchToBaseliningInvoke(logger: StateLogger, serializeOutputOrder: SerializeOutputOrder): void { const originalSetTime = this.setTime; this.setTime = time => { logger.log(`Host is moving to new time`); @@ -508,7 +508,7 @@ export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost, this.ensureFileOrFolder({ path: !this.windowsStyleRoot ? "/" : this.getHostSpecificPath("/") }); } - modifyFile(filePath: string, content: string, options?: Partial) { + modifyFile(filePath: string, content: string, options?: Partial): void { const path = this.toFullPath(filePath); const currentEntry = this.fs.get(path); if (!currentEntry || !isFsFile(currentEntry)) { @@ -536,7 +536,7 @@ export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost, } } - renameFile(fileName: string, newFileName: string) { + renameFile(fileName: string, newFileName: string): void { const fullPath = getNormalizedAbsolutePath(fileName, this.currentDirectory); const path = this.toPath(fullPath); const file = this.fs.get(path) as FsFile; @@ -556,7 +556,7 @@ export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost, this.addFileOrFolderInFolder(baseFolder, newFile); } - renameFolder(folderName: string, newFolderName: string) { + renameFolder(folderName: string, newFolderName: string): void { const fullPath = getNormalizedAbsolutePath(folderName, this.currentDirectory); const path = this.toPath(fullPath); const folder = this.fs.get(path) as FsFolder; @@ -598,7 +598,7 @@ 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): void { if (isFile(fileOrDirectoryOrSymLink)) { const file = this.toFsFile(fileOrDirectoryOrSymLink); // file may already exist when updating existing type declaration file @@ -683,13 +683,13 @@ export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost, this.inodes?.delete(fileOrDirectory.path); } - deleteFile(filePath: string) { + deleteFile(filePath: string): void { const file = this.getRealFileOrFolder(filePath); Debug.assert(isFsFile(file)); this.removeFileOrFolder(file); } - deleteFolder(folderPath: string, recursive?: boolean) { + deleteFolder(folderPath: string, recursive?: boolean): void { const path = this.toFullPath(folderPath); const currentEntry = this.fs.get(path); Debug.assert(isFsFolder(currentEntry)); @@ -718,7 +718,7 @@ export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost, fileOrDirectory: string, recursive: boolean, cb: FsWatchCallback, - ) { + ): FsWatchWorkerWatcher { if (this.runWithFallbackPolling) throw new Error("Need to use fallback polling instead of file system native watching"); let inode: number | undefined; if (this.inodeWatching) { @@ -740,7 +740,7 @@ export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost, return result; } - invokeFileWatcher(fileFullPath: string, eventKind: FileWatcherEventKind, modifiedTime: Date | undefined) { + invokeFileWatcher(fileFullPath: string, eventKind: FileWatcherEventKind, modifiedTime: Date | undefined): void { this.watchUtils.pollingWatches.forEach(fileFullPath, ({ cb }, fullPath) => cb(fullPath, eventKind, modifiedTime)); } @@ -755,11 +755,11 @@ export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost, }); } - invokeFsWatchesCallbacks(fullPath: string, eventName: "rename" | "change", eventFullPath: string | undefined, useTildeSuffix?: boolean) { + invokeFsWatchesCallbacks(fullPath: string, eventName: "rename" | "change", eventFullPath: string | undefined, useTildeSuffix?: boolean): void { this.fsWatchCallback(this.watchUtils.fsWatches, fullPath, eventName, eventFullPath, useTildeSuffix); } - invokeFsWatchesRecursiveCallbacks(fullPath: string, eventName: "rename" | "change", eventFullPath: string | undefined, useTildeSuffix?: boolean) { + invokeFsWatchesRecursiveCallbacks(fullPath: string, eventName: "rename" | "change", eventFullPath: string | undefined, useTildeSuffix?: boolean): void { this.fsWatchCallback(this.watchUtils.fsWatchesRecursive, fullPath, eventName, eventFullPath, useTildeSuffix); } @@ -775,7 +775,7 @@ export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost, } } - invokeFsWatches(fullPath: string, eventName: "rename" | "change", eventFullPath: string | undefined, useTildeSuffix: boolean | undefined) { + invokeFsWatches(fullPath: string, eventName: "rename" | "change", eventFullPath: string | undefined, useTildeSuffix: boolean | undefined): void { this.invokeFsWatchesCallbacks(fullPath, eventName, eventFullPath, useTildeSuffix); this.invokeFsWatchesCallbacks(getDirectoryPath(fullPath), eventName, eventFullPath, useTildeSuffix); this.invokeRecursiveFsWatches(fullPath, eventName, eventFullPath, useTildeSuffix); @@ -862,20 +862,20 @@ export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost, return this.getRealFsEntry((entry): entry is FsFile | FsFolder => !!entry && !isFsSymLink(entry), this.toFullPath(s)); } - fileSystemEntryExists(s: string, entryKind: FileSystemEntryKind) { + fileSystemEntryExists(s: string, entryKind: FileSystemEntryKind): boolean { return entryKind === FileSystemEntryKind.File ? this.fileExists(s) : this.directoryExists(s); } - fileExists(s: string) { + fileExists(s: string): boolean { const path = this.toFullPath(s); return !!this.getRealFile(path); } - getModifiedTime(s: string) { + getModifiedTime(s: string): Date | undefined { return this.getRealFileOrFolder(s)?.modifiedTime; } - setModifiedTime(s: string, date: Date) { + setModifiedTime(s: string, date: Date): void { const fsEntry = this.getRealFileOrFolder(s); if (fsEntry) { fsEntry.modifiedTime = date; @@ -888,7 +888,7 @@ export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost, return fsEntry ? fsEntry.content : undefined; } - getFileSize(s: string) { + getFileSize(s: string): number { const path = this.toFullPath(s); const entry = this.fs.get(path)!; if (isFsFile(entry)) { @@ -897,7 +897,7 @@ export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost, return undefined!; // TODO: GH#18217 } - directoryExists(s: string) { + directoryExists(s: string): boolean { const path = this.toFullPath(s); return !!this.getRealFolder(path); } @@ -943,11 +943,11 @@ export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost, } // TOOD: record and invoke callbacks to simulate timer events - setTimeout(callback: TimeOutCallback, ms: number, ...args: any[]) { + setTimeout(callback: TimeOutCallback, ms: number, ...args: any[]): number { return this.timeoutCallbacks.register(callback, args, ms); } - getNextTimeoutId() { + getNextTimeoutId(): number { return this.timeoutCallbacks.getNextId(); } @@ -959,15 +959,15 @@ export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost, this.screenClears.push(this.output.length); } - runQueuedTimeoutCallbacks(timeoutId?: number) { + runQueuedTimeoutCallbacks(timeoutId?: number): void { this.timeoutCallbacks.invoke(timeoutId); } - runQueuedImmediateCallbacks() { + runQueuedImmediateCallbacks(): void { this.immediateCallbacks.invoke(); } - setImmediate(callback: TimeOutCallback, ...args: any[]) { + setImmediate(callback: TimeOutCallback, ...args: any[]): number { return this.immediateCallbacks.register(callback, args); } @@ -975,11 +975,11 @@ export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost, this.immediateCallbacks.unregister(timeoutId); } - scheduleInstall(cb: TimeOutCallback, ...args: any[]) { + scheduleInstall(cb: TimeOutCallback, ...args: any[]): void { this.pendingInstalls.register(cb, args); } - runPendingInstalls() { + runPendingInstalls(): void { this.pendingInstalls.invoke(); } @@ -1023,12 +1023,12 @@ export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost, this.modifyFile(path, this.readFile(path) + content, options); } - replaceFileText(file: string, searchValue: string | RegExp, replaceValue: string) { + replaceFileText(file: string, searchValue: string | RegExp, replaceValue: string): void { const content = Debug.checkDefined(this.readFile(file)); this.writeFile(file, content.replace(searchValue, replaceValue)); } - write(message: string) { + write(message: string): void { if (Debug.isDebugging) console.log(message); this.output.push(message); } @@ -1037,12 +1037,12 @@ export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost, return this.output; } - clearOutput() { + clearOutput(): void { clear(this.output); this.screenClears.length = 0; } - serializeOutput(baseline: string[]) { + serializeOutput(baseline: string[]): void { const output = this.getOutput(); if (!this.output.length && !this.screenClears.length) return; let start = 0; @@ -1068,7 +1068,7 @@ export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost, }); } - serializeState(baseline: string[], serializeOutput: SerializeOutputOrder) { + serializeState(baseline: string[], serializeOutput: SerializeOutputOrder): void { if (serializeOutput === SerializeOutputOrder.BeforeDiff) this.serializeOutput(baseline); this.diff(baseline); if (serializeOutput === SerializeOutputOrder.AfterDiff) this.serializeOutput(baseline); @@ -1081,7 +1081,7 @@ export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost, writtenFiles?: Map; private serializedDiff = new Map(); - diff(baseline: string[]) { + diff(baseline: string[]): void { this.fs.forEach((newFsEntry, path) => { diffFsEntry(baseline, this.serializedDiff.get(path), newFsEntry, this.inodes?.get(path), this.writtenFiles); }); @@ -1096,7 +1096,7 @@ export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost, this.writtenFiles?.clear(); } - serializeWatches(baseline?: string[]) { + serializeWatches(baseline?: string[]): string[] { return this.watchUtils.serializeWatches(baseline); } @@ -1119,14 +1119,14 @@ export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost, } exitCode: number | undefined; - readonly resolvePath = (s: string) => s; - readonly getExecutingFilePath = () => this.executingFilePath; - readonly getCurrentDirectory = () => this.currentDirectory; - exit(exitCode?: number) { + readonly resolvePath = (s: string): string => s; + readonly getExecutingFilePath = (): string => this.executingFilePath; + readonly getCurrentDirectory = (): string => this.currentDirectory; + exit(exitCode?: number): void { this.exitCode = exitCode; throw new Error(exitMessage); } - getEnvironmentVariable(name: string) { + getEnvironmentVariable(name: string): string { return this.environmentVariables && this.environmentVariables.get(name) || ""; } } @@ -1208,7 +1208,7 @@ function baselineOutputs(baseline: string[], output: readonly string[], start: n export type TestServerHostTrackingWrittenFiles = TestServerHost & { writtenFiles: Map; }; -export function changeToHostTrackingWrittenFiles(inputHost: TestServerHost) { +export function changeToHostTrackingWrittenFiles(inputHost: TestServerHost): TestServerHostTrackingWrittenFiles { const host = inputHost as TestServerHostTrackingWrittenFiles; if (host.writtenFiles) return host; const originalWriteFile = host.writeFile; @@ -1221,7 +1221,7 @@ export function changeToHostTrackingWrittenFiles(inputHost: TestServerHost) { return host; } -export function osFlavorToString(osFlavor: TestServerHostOsFlavor) { +export function osFlavorToString(osFlavor: TestServerHostOsFlavor): "Windows" | "MacOs" | "Linux" { switch (osFlavor) { case TestServerHostOsFlavor.Windows: return "Windows"; diff --git a/src/testRunner/unittests/services/extract/helpers.ts b/src/testRunner/unittests/services/extract/helpers.ts index 4a75167cd1563..e2ed6681880e1 100644 --- a/src/testRunner/unittests/services/extract/helpers.ts +++ b/src/testRunner/unittests/services/extract/helpers.ts @@ -112,7 +112,7 @@ 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): void { const t = extractTest(text); const selectionRange = t.ranges.get("selection")!; if (!selectionRange) { @@ -179,7 +179,7 @@ export function testExtractSymbol(caption: string, text: string, baselineFolder: } } -export function testExtractSymbolFailed(caption: string, text: string, description: ts.DiagnosticMessage) { +export function testExtractSymbolFailed(caption: string, text: string, description: ts.DiagnosticMessage): void { it(caption, () => { const t = extractTest(text); const selectionRange = t.ranges.get("selection"); From 58a7fcf8a5b9b0b5724b7104fa14d4d69e9de89f Mon Sep 17 00:00:00 2001 From: Isabel Duan Date: Tue, 13 Aug 2024 11:04:03 -0700 Subject: [PATCH 12/27] update baselines --- src/server/session.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/server/session.ts b/src/server/session.ts index 039c9d4238b7e..c34a18a56011d 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -316,7 +316,7 @@ function allEditsBeforePos(edits: readonly TextChange[], pos: number): boolean { /** @deprecated use ts.server.protocol.CommandTypes */ export type CommandNames = protocol.CommandTypes; /** @deprecated use ts.server.protocol.CommandTypes */ -export const CommandNames: CommandNames = (protocol as any).CommandTypes; +export const CommandNames: any = (protocol as any).CommandTypes; export function formatMessage(msg: T, logger: Logger, byteLength: (s: string, encoding: BufferEncoding) => number, newLine: string): string { const verboseLogging = logger.hasLevel(LogLevel.verbose); From 326123f57186753e7ac9bc0b47a3823122cf0689 Mon Sep 17 00:00:00 2001 From: Isabel Duan Date: Tue, 13 Aug 2024 13:52:01 -0700 Subject: [PATCH 13/27] remove extra generated ts. --- src/server/project.ts | 47 +++++++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/src/server/project.ts b/src/server/project.ts index eaf7100ebe840..993286429aa44 100644 --- a/src/server/project.ts +++ b/src/server/project.ts @@ -68,6 +68,7 @@ import { HasInvalidatedLibResolutions, HasInvalidatedResolutions, HostCancellationToken, + IncompleteCompletionsCache, inferredTypesContainingFile, InstallPackageOptions, IScriptSnapshot, @@ -85,6 +86,7 @@ import { memoize, ModuleResolutionCache, ModuleResolutionHost, + ModuleSpecifierCache, noop, noopFileWatcher, normalizePath, @@ -115,6 +117,7 @@ import { sortAndDeduplicate, SortedReadonlyArray, SourceFile, + SourceFileLike, SourceMapper, startsWith, StringLiteralLike, @@ -377,7 +380,7 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo * * @internal */ - cachedUnresolvedImportsPerFile: Map = new Map(); + cachedUnresolvedImportsPerFile: Map = new Map(); /** @internal */ lastCachedUnresolvedImportsList: SortedReadonlyArray | undefined; @@ -663,12 +666,12 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo } // Method of LanguageServiceHost - getCompilationSettings(): ts.CompilerOptions { + getCompilationSettings(): CompilerOptions { return this.compilerOptions; } // Method to support public API - getCompilerOptions(): ts.CompilerOptions { + getCompilerOptions(): CompilerOptions { return this.getCompilationSettings(); } @@ -718,7 +721,7 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo return scriptInfo; } - getScriptKind(fileName: string): ts.ScriptKind { + getScriptKind(fileName: string): ScriptKind { const info = this.projectService.getScriptInfoForPath(this.toPath(fileName)); return (info && info.scriptKind)!; // TODO: GH#18217 } @@ -820,12 +823,12 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo } /** @internal */ - toPath(fileName: string): ts.Path { + toPath(fileName: string): Path { return toPath(fileName, this.currentDirectory, this.projectService.toCanonicalFileName); } /** @internal */ - watchDirectoryOfFailedLookupLocation(directory: string, cb: DirectoryWatcherCallback, flags: WatchDirectoryFlags): ts.FileWatcher { + watchDirectoryOfFailedLookupLocation(directory: string, cb: DirectoryWatcherCallback, flags: WatchDirectoryFlags): FileWatcher { return this.projectService.watchFactory.watchDirectory( directory, cb, @@ -837,7 +840,7 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo } /** @internal */ - watchAffectingFileLocation(file: string, cb: FileWatcherCallback): ts.FileWatcher { + watchAffectingFileLocation(file: string, cb: FileWatcherCallback): FileWatcher { return this.projectService.watchFactory.watchFile( file, cb, @@ -879,7 +882,7 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo } /** @internal */ - watchTypeRootsDirectory(directory: string, cb: DirectoryWatcherCallback, flags: WatchDirectoryFlags): ts.FileWatcher { + watchTypeRootsDirectory(directory: string, cb: DirectoryWatcherCallback, flags: WatchDirectoryFlags): FileWatcher { return this.projectService.watchFactory.watchDirectory( directory, cb, @@ -973,7 +976,7 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo } /** @internal */ - getSourceFileLike(fileName: string): ts.SourceFileLike | undefined { + getSourceFileLike(fileName: string): SourceFileLike | undefined { return this.projectService.getSourceFileLike(fileName, this); } @@ -1100,7 +1103,7 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo })); } - getSourceFile(path: Path): ts.SourceFile | undefined { + getSourceFile(path: Path): SourceFile | undefined { if (!this.program) { return undefined; } @@ -1194,7 +1197,7 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo } /** @internal */ - getRootFilesMap(): Map { + getRootFilesMap(): Map { return this.rootFilesMap; } @@ -1978,7 +1981,7 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo } } - getTypeAcquisition(): ts.TypeAcquisition { + getTypeAcquisition(): TypeAcquisition { return this.typeAcquisition || {}; } @@ -2207,7 +2210,7 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo } /** @internal */ - getCachedExportInfoMap(): ts.ExportInfoMap { + getCachedExportInfoMap(): ExportInfoMap { return this.exportMapCache ||= createCacheableExportInfoMap(this); } @@ -2217,7 +2220,7 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo } /** @internal */ - getModuleSpecifierCache(): ts.ModuleSpecifierCache { + getModuleSpecifierCache(): ModuleSpecifierCache { return this.moduleSpecifierCache; } @@ -2294,12 +2297,12 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo } /** @internal */ - watchNodeModulesForPackageJsonChanges(directoryPath: string): ts.FileWatcher { + watchNodeModulesForPackageJsonChanges(directoryPath: string): FileWatcher { return this.projectService.watchPackageJsonsInNodeModules(directoryPath, this); } /** @internal */ - getIncompleteCompletionsCache(): ts.IncompleteCompletionsCache { + getIncompleteCompletionsCache(): IncompleteCompletionsCache { return this.projectService.getIncompleteCompletionsCache(); } @@ -2806,22 +2809,22 @@ export class AutoImportProviderProject extends Project { throw new Error("AutoImportProviderProject cannot provide its own host; use `hostProject.getModuleResolutionHostForAutomImportProvider()` instead."); } - override getProjectReferences(): readonly ts.ProjectReference[] | undefined { + override getProjectReferences(): readonly ProjectReference[] | undefined { return this.hostProject.getProjectReferences(); } /** @internal */ - override includePackageJsonAutoImports(): ts.PackageJsonAutoImportPreference { + override includePackageJsonAutoImports(): PackageJsonAutoImportPreference { return PackageJsonAutoImportPreference.Off; } /** @internal */ - override getSymlinkCache(): ts.SymlinkCache { + override getSymlinkCache(): SymlinkCache { return this.hostProject.getSymlinkCache(); } /** @internal */ - override getModuleResolutionCache(): ts.ModuleResolutionCache | undefined { + override getModuleResolutionCache(): ModuleResolutionCache | undefined { return this.hostProject.getCurrentProgram()?.getModuleResolutionCache(); } } @@ -2838,7 +2841,7 @@ export class ConfiguredProject extends Project { pendingUpdateReason: string | undefined; /** @internal */ - openFileWatchTriggered: Map = new Map(); + openFileWatchTriggered: Map = new Map(); /** @internal */ canConfigFileJsonReportNoInputFiles = false; @@ -2902,7 +2905,7 @@ export class ConfiguredProject extends Project { } /** @internal */ - override getParsedCommandLine(fileName: string): ts.ParsedCommandLine | undefined { + override getParsedCommandLine(fileName: string): ParsedCommandLine | undefined { const configFileName = asNormalizedPath(normalizePath(fileName)); const canonicalConfigFilePath = asNormalizedPath(this.projectService.toCanonicalFileName(configFileName)); // Ensure the config file existience info is cached From 303d726bd902c1e0a7fc34496e75d7af44e3c526 Mon Sep 17 00:00:00 2001 From: Isabel Duan Date: Tue, 13 Aug 2024 15:50:32 -0700 Subject: [PATCH 14/27] make commentpragma type --- src/compiler/types.ts | 146 +++++++++++++++++++++--------------------- 1 file changed, 73 insertions(+), 73 deletions(-) diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 2d23578b3d47d..0a8d63efc33e6 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -10074,78 +10074,7 @@ export interface PragmaDefinition = Concre : never; /** @internal */ -export type ConcretePragmaSpecs = typeof commentPragmas; +export interface ConcretePragmaSpecs { + readonly "reference": { + readonly args: readonly [{ + readonly name: "types"; + readonly optional: true; + readonly captureSpan: true; + }, { + readonly name: "lib"; + readonly optional: true; + readonly captureSpan: true; + }, { + readonly name: "path"; + readonly optional: true; + readonly captureSpan: true; + }, { + readonly name: "no-default-lib"; + readonly optional: true; + }, { + readonly name: "resolution-mode"; + readonly optional: true; + }, { + readonly name: "preserve"; + readonly optional: true; + }]; + readonly kind: PragmaKindFlags.TripleSlashXML; + }; + readonly "amd-dependency": { + readonly args: readonly [{ + readonly name: "path"; + }, { + readonly name: "name"; + readonly optional: true; + }]; + readonly kind: PragmaKindFlags.TripleSlashXML; + }; + readonly "amd-module": { + readonly args: readonly [{ + readonly name: "name"; + }]; + readonly kind: PragmaKindFlags.TripleSlashXML; + }; + readonly "ts-check": { + readonly kind: PragmaKindFlags.SingleLine; + }; + readonly "ts-nocheck": { + readonly kind: PragmaKindFlags.SingleLine; + }; + readonly "jsx": { + readonly args: readonly [{ + readonly name: "factory"; + }]; + readonly kind: PragmaKindFlags.MultiLine; + }; + readonly "jsxfrag": { + readonly args: readonly [{ + readonly name: "factory"; + }]; + readonly kind: PragmaKindFlags.MultiLine; + }; + readonly "jsximportsource": { + readonly args: readonly [{ + readonly name: "factory"; + }]; + readonly kind: PragmaKindFlags.MultiLine; + }; + readonly "jsxruntime": { + readonly args: readonly [{ + readonly name: "factory"; + }]; + readonly kind: PragmaKindFlags.MultiLine; + }; +} /** @internal */ export type PragmaPseudoMap = { [K in keyof ConcretePragmaSpecs]: { arguments: PragmaArgumentType; range: CommentRange; }; }; From 7d3ccb313f1619a30b7c3a495f179a17dcc3cd63 Mon Sep 17 00:00:00 2001 From: Isabel Duan Date: Wed, 14 Aug 2024 13:20:51 -0700 Subject: [PATCH 15/27] update baselines --- tests/baselines/reference/api/typescript.d.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 8275e4222820c..9720af3b78415 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -2842,14 +2842,14 @@ declare namespace ts { readonly jsDocParsingMode: JSDocParsingMode | undefined; isKnownTypesPackageName(name: string): boolean; installPackage(options: InstallPackageOptions): Promise; - getCompilationSettings(): ts.CompilerOptions; - getCompilerOptions(): ts.CompilerOptions; + getCompilationSettings(): CompilerOptions; + getCompilerOptions(): CompilerOptions; getNewLine(): string; getProjectVersion(): string; getProjectReferences(): readonly ProjectReference[] | undefined; getScriptFileNames(): string[]; private getOrCreateScriptInfoAndAttachToProject; - getScriptKind(fileName: string): ts.ScriptKind; + getScriptKind(fileName: string): ScriptKind; getScriptVersion(filename: string): string; getScriptSnapshot(filename: string): IScriptSnapshot | undefined; getCancellationToken(): HostCancellationToken; @@ -2885,7 +2885,7 @@ declare namespace ts { getProjectName(): string; protected removeLocalTypingsFromTypeAcquisition(newTypeAcquisition: TypeAcquisition): TypeAcquisition; getExternalFiles(updateLevel?: ProgramUpdateLevel): SortedReadonlyArray; - getSourceFile(path: Path): ts.SourceFile | undefined; + getSourceFile(path: Path): SourceFile | undefined; close(): void; private detachScriptInfoIfNotRoot; isClosed(): boolean; @@ -2924,7 +2924,7 @@ declare namespace ts { private filesToStringWorker; setCompilerOptions(compilerOptions: CompilerOptions): void; setTypeAcquisition(newTypeAcquisition: TypeAcquisition | undefined): void; - getTypeAcquisition(): ts.TypeAcquisition; + getTypeAcquisition(): TypeAcquisition; protected removeRoot(info: ScriptInfo): void; protected enableGlobalPlugins(options: CompilerOptions): void; protected enablePlugin(pluginConfigEntry: PluginImport, searchPaths: string[]): void; @@ -2958,7 +2958,7 @@ declare namespace ts { getScriptFileNames(): string[]; getLanguageService(): never; getHostForAutoImportProvider(): never; - getProjectReferences(): readonly ts.ProjectReference[] | undefined; + getProjectReferences(): readonly ProjectReference[] | undefined; } /** * If a file is opened, the server will look for a tsconfig (or jsconfig) From b89abd1aaf50b810e025e0e18ee3b25806a7e55f Mon Sep 17 00:00:00 2001 From: Isabel Duan Date: Wed, 14 Aug 2024 13:52:18 -0700 Subject: [PATCH 16/27] add as const and reduce duplications --- src/compiler/utilitiesPublic.ts | 2 +- src/harness/vfsUtil.ts | 19 ++++--------------- 2 files changed, 5 insertions(+), 16 deletions(-) diff --git a/src/compiler/utilitiesPublic.ts b/src/compiler/utilitiesPublic.ts index 79f1f6fba0d03..076016e137858 100644 --- a/src/compiler/utilitiesPublic.ts +++ b/src/compiler/utilitiesPublic.ts @@ -669,7 +669,7 @@ function getNodeFlags(node: Node) { } /** @internal */ -export const supportedLocaleDirectories: string[] = ["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"] as const; /** * Checks to see if the locale is in the appropriate format, diff --git a/src/harness/vfsUtil.ts b/src/harness/vfsUtil.ts index 916690fc7de39..1995d79ab6da0 100644 --- a/src/harness/vfsUtil.ts +++ b/src/harness/vfsUtil.ts @@ -1354,20 +1354,8 @@ export class Stats { } } -export const IOErrorMessages: Readonly<{ - EACCES: "access denied"; - EIO: "an I/O error occurred"; - ENOENT: "no such file or directory"; - EEXIST: "file already exists"; - ELOOP: "too many symbolic links encountered"; - ENOTDIR: "no such directory"; - EISDIR: "path is a directory"; - EBADF: "invalid file descriptor"; - EINVAL: "invalid value"; - ENOTEMPTY: "directory not empty"; - EPERM: "operation not permitted"; - EROFS: "file system is read-only"; -}> = Object.freeze({ +// IOErrorMessages is defined like this to reduce duplication for --isolatedDeclarations +const TemplateIOErrorMessages = { EACCES: "access denied", EIO: "an I/O error occurred", ENOENT: "no such file or directory", @@ -1380,7 +1368,8 @@ export const IOErrorMessages: Readonly<{ ENOTEMPTY: "directory not empty", EPERM: "operation not permitted", EROFS: "file system is read-only", -}); +} as const; +export const IOErrorMessages: typeof TemplateIOErrorMessages = Object.freeze(TemplateIOErrorMessages); export function createIOError(code: keyof typeof IOErrorMessages, details = ""): NodeJS.ErrnoException { const err: NodeJS.ErrnoException = new Error(`${code}: ${IOErrorMessages[code]} ${details}`); From ad0fb2af3f84f6591482ed9e88d39e9c1e9bd2de Mon Sep 17 00:00:00 2001 From: Isabel Duan Date: Thu, 12 Sep 2024 09:58:55 -0700 Subject: [PATCH 17/27] add missing type annotations from merge --- src/compiler/factory/utilities.ts | 2 +- src/compiler/utilities.ts | 6 +- src/compiler/utilitiesPublic.ts | 2 +- src/harness/fakesHosts.ts | 215 ---------- src/server/project.ts | 4 +- .../unittests/helpers/alternateResult.ts | 129 +++++- src/testRunner/unittests/helpers/baseline.ts | 152 ++++++- .../helpers/demoProjectReferences.ts | 38 +- src/testRunner/unittests/helpers/extends.ts | 40 +- .../unittests/helpers/libraryResolution.ts | 285 +++++++++---- src/testRunner/unittests/helpers/noEmit.ts | 156 ++++--- .../unittests/helpers/projectRoots.ts | 2 +- .../helpers/sampleProjectReferences.ts | 68 +-- .../unittests/helpers/solutionBuilder.ts | 90 +++- src/testRunner/unittests/helpers/tsc.ts | 399 ++++++------------ src/testRunner/unittests/helpers/tscWatch.ts | 4 +- src/testRunner/unittests/helpers/tsserver.ts | 4 +- .../helpers/virtualFileSystemWithWatch.ts | 332 +++++++++++---- .../unittests/services/extract/helpers.ts | 22 +- 19 files changed, 1048 insertions(+), 902 deletions(-) diff --git a/src/compiler/factory/utilities.ts b/src/compiler/factory/utilities.ts index 1f0195735585c..9f7cc54ef7508 100644 --- a/src/compiler/factory/utilities.ts +++ b/src/compiler/factory/utilities.ts @@ -693,7 +693,7 @@ export function hasRecordedExternalHelpers(sourceFile: SourceFile): boolean { } /** @internal */ -export function createExternalHelpersImportDeclarationIfNeeded(nodeFactory: NodeFactory, helperFactory: EmitHelperFactory, sourceFile: SourceFile, compilerOptions: CompilerOptions, hasExportStarsToExportValues?: boolean, hasImportStar?: boolean, hasImportDefault?: boolean): ImportDeclaration | undefined { +export function createExternalHelpersImportDeclarationIfNeeded(nodeFactory: NodeFactory, helperFactory: EmitHelperFactory, sourceFile: SourceFile, compilerOptions: CompilerOptions, hasExportStarsToExportValues?: boolean, hasImportStar?: boolean, hasImportDefault?: boolean): ImportDeclaration | ImportEqualsDeclaration | undefined { if (compilerOptions.importHelpers && isEffectiveExternalModule(sourceFile, compilerOptions)) { const moduleKind = getEmitModuleKind(compilerOptions); const impliedModuleKind = getImpliedNodeFormatForEmitWorker(sourceFile, compilerOptions); diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index a0c5f79976899..c14d1066c5c2b 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -12010,13 +12010,13 @@ const unprefixedNodeCoreModulesList = [ ]; /** @internal */ -export const unprefixedNodeCoreModules = new Set(unprefixedNodeCoreModulesList); +export const unprefixedNodeCoreModules: Set = new Set(unprefixedNodeCoreModulesList); // await fetch('https://nodejs.org/docs/latest/api/all.json').then(r => r.text()).then(t => // new Set(t.match(/(?<=')node:.+?(?=')/g)) // .difference(new Set(require('module').builtinModules.map(x => `node:${x}`)))) /** @internal */ -export const exclusivelyPrefixedNodeCoreModules = new Set([ +export const exclusivelyPrefixedNodeCoreModules: Set = new Set([ "node:sea", "node:sqlite", "node:test", @@ -12024,7 +12024,7 @@ export const exclusivelyPrefixedNodeCoreModules = new Set([ ]); /** @internal */ -export const nodeCoreModules = new Set([ +export const nodeCoreModules: Set = new Set([ ...unprefixedNodeCoreModulesList, ...unprefixedNodeCoreModulesList.map(name => `node:${name}`), ...exclusivelyPrefixedNodeCoreModules, diff --git a/src/compiler/utilitiesPublic.ts b/src/compiler/utilitiesPublic.ts index 7bdf35c47fdfa..e4788842a2df7 100644 --- a/src/compiler/utilitiesPublic.ts +++ b/src/compiler/utilitiesPublic.ts @@ -304,7 +304,7 @@ export function sortAndDeduplicateDiagnostics(diagnostics: } /** @internal */ -export const targetToLibMap = new Map([ +export const targetToLibMap: Map = new Map([ [ScriptTarget.ESNext, "lib.esnext.full.d.ts"], [ScriptTarget.ES2023, "lib.es2023.full.d.ts"], [ScriptTarget.ES2022, "lib.es2022.full.d.ts"], diff --git a/src/harness/fakesHosts.ts b/src/harness/fakesHosts.ts index b07036168082a..37dab2eadbadd 100644 --- a/src/harness/fakesHosts.ts +++ b/src/harness/fakesHosts.ts @@ -422,218 +422,3 @@ export class CompilerHost implements ts.CompilerHost { return parsed; } } - -export type ExpectedDiagnosticMessage = [ts.DiagnosticMessage, ...(string | number)[]]; -export interface ExpectedDiagnosticMessageChain { - message: ExpectedDiagnosticMessage; - next?: ExpectedDiagnosticMessageChain[]; -} - -export interface ExpectedDiagnosticLocation { - file: string; - start: number; - length: number; -} -export interface ExpectedDiagnosticRelatedInformation extends ExpectedDiagnosticMessageChain { - location?: ExpectedDiagnosticLocation; -} - -export enum DiagnosticKind { - Error = "Error", - Status = "Status", -} -export interface ExpectedErrorDiagnostic extends ExpectedDiagnosticRelatedInformation { - relatedInformation?: ExpectedDiagnosticRelatedInformation[]; -} - -export type ExpectedDiagnostic = ExpectedDiagnosticMessage | ExpectedErrorDiagnostic; - -interface SolutionBuilderDiagnostic { - kind: DiagnosticKind; - diagnostic: ts.Diagnostic; -} - -function indentedText(indent: number, text: string) { - if (!indent) return text; - let indentText = ""; - for (let i = 0; i < indent; i++) { - indentText += " "; - } - return ` -${indentText}${text}`; -} - -function expectedDiagnosticMessageToText([message, ...args]: ExpectedDiagnosticMessage) { - let text = ts.getLocaleSpecificMessage(message); - if (args.length) { - text = ts.formatStringFromArgs(text, args); - } - return text; -} - -function expectedDiagnosticMessageChainToText({ message, next }: ExpectedDiagnosticMessageChain, indent = 0) { - let text = indentedText(indent, expectedDiagnosticMessageToText(message)); - if (next) { - indent++; - next.forEach(kid => text += expectedDiagnosticMessageChainToText(kid, indent)); - } - return text; -} - -function expectedDiagnosticRelatedInformationToText({ location, ...diagnosticMessage }: ExpectedDiagnosticRelatedInformation) { - const text = expectedDiagnosticMessageChainToText(diagnosticMessage); - if (location) { - const { file, start, length } = location; - return `${file}(${start}:${length}):: ${text}`; - } - return text; -} - -function expectedErrorDiagnosticToText({ relatedInformation, ...diagnosticRelatedInformation }: ExpectedErrorDiagnostic) { - let text = `${DiagnosticKind.Error}!: ${expectedDiagnosticRelatedInformationToText(diagnosticRelatedInformation)}`; - if (relatedInformation) { - for (const kid of relatedInformation) { - text += ` - related:: ${expectedDiagnosticRelatedInformationToText(kid)}`; - } - } - return text; -} - -function expectedDiagnosticToText(errorOrStatus: ExpectedDiagnostic) { - return ts.isArray(errorOrStatus) ? - `${DiagnosticKind.Status}!: ${expectedDiagnosticMessageToText(errorOrStatus)}` : - expectedErrorDiagnosticToText(errorOrStatus); -} - -function diagnosticMessageChainToText({ messageText, next }: ts.DiagnosticMessageChain, indent = 0) { - let text = indentedText(indent, messageText); - if (next) { - indent++; - next.forEach(kid => text += diagnosticMessageChainToText(kid, indent)); - } - return text; -} - -function diagnosticRelatedInformationToText({ file, start, length, messageText }: ts.DiagnosticRelatedInformation) { - const text = typeof messageText === "string" ? - messageText : - diagnosticMessageChainToText(messageText); - return file ? - `${file.fileName}(${start}:${length}):: ${text}` : - text; -} - -function diagnosticToText({ kind, diagnostic: { relatedInformation, ...diagnosticRelatedInformation } }: SolutionBuilderDiagnostic) { - let text = `${kind}!: ${diagnosticRelatedInformationToText(diagnosticRelatedInformation)}`; - if (relatedInformation) { - for (const kid of relatedInformation) { - text += ` - related:: ${diagnosticRelatedInformationToText(kid)}`; - } - } - return text; -} - -export const version = "FakeTSVersion"; - -export function patchHostForBuildInfoReadWrite(sys: T): T { - const originalReadFile = sys.readFile; - sys.readFile = (path, encoding) => { - const value = originalReadFile.call(sys, path, encoding); - if (!value || !ts.isBuildInfoFile(path)) return value; - const buildInfo = ts.getBuildInfo(path, value); - if (!buildInfo) return value; - ts.Debug.assert(buildInfo.version === version); - buildInfo.version = ts.version; - return ts.getBuildInfoText(buildInfo); - }; - return patchHostForBuildInfoWrite(sys, version); -} - -export function patchHostForBuildInfoWrite(sys: T, version: string): T { - const originalWrite = sys.write; - sys.write = msg => originalWrite.call(sys, msg.replace(ts.version, version)); - const originalWriteFile = sys.writeFile; - sys.writeFile = (fileName: string, content: string, writeByteOrderMark: boolean) => { - if (ts.isBuildInfoFile(fileName)) { - const buildInfo = ts.getBuildInfo(fileName, content); - if (buildInfo) { - buildInfo.version = version; - return originalWriteFile.call(sys, fileName, ts.getBuildInfoText(buildInfo), writeByteOrderMark); - } - } - return originalWriteFile.call(sys, fileName, content, writeByteOrderMark); - }; - return sys; -} - -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, jsDocParsingMode?: ts.JSDocParsingMode) { - super(sys, options, setParentNodes, jsDocParsingMode); - this.createProgram = createProgram || ts.createEmitAndSemanticDiagnosticsBuilderProgram as unknown as ts.CreateProgram; - } - - static create(sys: System | vfs.FileSystem, options?: ts.CompilerOptions, setParentNodes?: boolean, createProgram?: ts.CreateProgram, jsDocParsingMode?: ts.JSDocParsingMode): SolutionBuilderHost { - const host = new SolutionBuilderHost(sys, options, setParentNodes, createProgram, jsDocParsingMode); - patchHostForBuildInfoReadWrite(host.sys); - return host; - } - - createHash(data: string) { - return `${ts.generateDjb2Hash(data)}-${data}`; - } - - diagnostics: SolutionBuilderDiagnostic[] = []; - - reportDiagnostic(diagnostic: ts.Diagnostic): void { - this.diagnostics.push({ kind: DiagnosticKind.Error, diagnostic }); - } - - reportSolutionBuilderStatus(diagnostic: ts.Diagnostic): void { - this.diagnostics.push({ kind: DiagnosticKind.Status, diagnostic }); - } - - clearDiagnostics(): void { - this.diagnostics.length = 0; - } - - assertDiagnosticMessages(...expectedDiagnostics: ExpectedDiagnostic[]): void { - const actual = this.diagnostics.slice().map(diagnosticToText); - const expected = expectedDiagnostics.map(expectedDiagnosticToText); - assert.deepEqual( - actual, - expected, - `Diagnostic arrays did not match: -Actual: ${JSON.stringify(actual, /*replacer*/ undefined, " ")} -Expected: ${JSON.stringify(expected, /*replacer*/ undefined, " ")}`, - ); - } - - assertErrors(...expectedDiagnostics: ExpectedErrorDiagnostic[]): void { - const actual = this.diagnostics.filter(d => d.kind === DiagnosticKind.Error).map(diagnosticToText); - const expected = expectedDiagnostics.map(expectedDiagnosticToText); - assert.deepEqual( - actual, - expected, - `Diagnostics arrays did not match: -Actual: ${JSON.stringify(actual, /*replacer*/ undefined, " ")} -Expected: ${JSON.stringify(expected, /*replacer*/ undefined, " ")} -Actual All:: ${JSON.stringify(this.diagnostics.slice().map(diagnosticToText), /*replacer*/ undefined, " ")}`, - ); - } - - printDiagnostics(header = "== Diagnostics =="): void { - const out = ts.createDiagnosticReporter(ts.sys); - ts.sys.write(header + "\r\n"); - for (const { diagnostic } of this.diagnostics) { - out(diagnostic); - } - } - - now(): Date { - return this.sys.now(); - } -} diff --git a/src/server/project.ts b/src/server/project.ts index dd51fd9cdd097..c0b58b93dfdd7 100644 --- a/src/server/project.ts +++ b/src/server/project.ts @@ -909,7 +909,7 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo } /** @internal */ - globalCacheResolutionModuleName = JsTyping.nonRelativeModuleNameForTypingCache; + globalCacheResolutionModuleName: typeof JsTyping.nonRelativeModuleNameForTypingCache = JsTyping.nonRelativeModuleNameForTypingCache; /** @internal */ fileIsOpen(filePath: Path): boolean { @@ -2339,7 +2339,7 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo } /** @internal */ - getCompilerOptionsForNoDtsResolutionProject() { + getCompilerOptionsForNoDtsResolutionProject(): ts.CompilerOptions { return { ...this.getCompilerOptions(), noDtsResolution: true, diff --git a/src/testRunner/unittests/helpers/alternateResult.ts b/src/testRunner/unittests/helpers/alternateResult.ts index 8156155837155..65e334417f761 100644 --- a/src/testRunner/unittests/helpers/alternateResult.ts +++ b/src/testRunner/unittests/helpers/alternateResult.ts @@ -1,9 +1,9 @@ import { dedent } from "../../_namespaces/Utils.js"; import { jsonToReadableText } from "../helpers.js"; -import { FsContents } from "./contents.js"; -import { libFile } from "./virtualFileSystemWithWatch.js"; +import { TscWatchCompileChange } from "./tscWatch.js"; +import { TestServerHost } from "./virtualFileSystemWithWatch.js"; -export function getFsConentsForAlternateResultAtTypesPackageJson(packageName: string, addTypesCondition: boolean): string { +function getFsConentsForAlternateResultAtTypesPackageJson(packageName: string, addTypesCondition: boolean) { return jsonToReadableText({ name: `@types/${packageName}`, version: "1.0.0", @@ -17,7 +17,7 @@ export function getFsConentsForAlternateResultAtTypesPackageJson(packageName: st }); } -export function getFsContentsForAlternateResultPackageJson(packageName: string, addTypes: boolean, addTypesCondition: boolean): string { +function getFsContentsForAlternateResultPackageJson(packageName: string, addTypes: boolean, addTypesCondition: boolean) { return jsonToReadableText({ name: packageName, version: "1.0.0", @@ -33,7 +33,7 @@ export function getFsContentsForAlternateResultPackageJson(packageName: string, }); } -export function getFsContentsForAlternateResultDts(packageName: string) { +function getFsContentsForAlternateResultDts(packageName: string) { return `export declare const ${packageName}: number;`; } @@ -45,8 +45,8 @@ function mjs(packageName: string) { return `export const ${packageName} = 1;`; } -export function getFsContentsForAlternateResult(): FsContents { - return { +function getSysForAlternateResult(forTsserver: boolean) { + return TestServerHost.getCreateWatchedSystem(forTsserver)({ "/home/src/projects/project/node_modules/@types/bar/package.json": getFsConentsForAlternateResultAtTypesPackageJson("bar", /*addTypesCondition*/ false), "/home/src/projects/project/node_modules/@types/bar/index.d.ts": getFsContentsForAlternateResultDts("bar"), "/home/src/projects/project/node_modules/bar/package.json": getFsContentsForAlternateResultPackageJson("bar", /*addTypes*/ false, /*addTypesCondition*/ false), @@ -81,6 +81,117 @@ export function getFsContentsForAlternateResult(): FsContents { }, files: ["index.mts"], }), - [libFile.path]: libFile.content, - }; + }, { currentDirectory: "/home/src/projects/project" }); +} + +export function verifyAlternateResultScenario( + forTsserver: boolean, + action: ( + scenario: string, + sys: () => TestServerHost, + edits: () => readonly TscWatchCompileChange[], + ) => void, +): void { + action( + "alternateResult", + () => getSysForAlternateResult(forTsserver), + () => [ + { + caption: "delete the alternateResult in @types", + edit: sys => sys.deleteFile("/home/src/projects/project/node_modules/@types/bar/index.d.ts"), + timeouts: sys => { + sys.runQueuedTimeoutCallbacks(); + sys.runQueuedTimeoutCallbacks(); + }, + }, + { + caption: "delete the ndoe10Result in package/types", + edit: sys => sys.deleteFile("/home/src/projects/project/node_modules/foo/index.d.ts"), + timeouts: sys => { + sys.runQueuedTimeoutCallbacks(); + sys.runQueuedTimeoutCallbacks(); + }, + }, + { + caption: "add the alternateResult in @types", + edit: sys => sys.writeFile("/home/src/projects/project/node_modules/@types/bar/index.d.ts", getFsContentsForAlternateResultDts("bar")), + timeouts: sys => { + sys.runQueuedTimeoutCallbacks(); + sys.runQueuedTimeoutCallbacks(); + }, + }, + { + caption: "add the alternateResult in package/types", + edit: sys => sys.writeFile("/home/src/projects/project/node_modules/foo/index.d.ts", getFsContentsForAlternateResultDts("foo")), + timeouts: sys => { + sys.runQueuedTimeoutCallbacks(); + sys.runQueuedTimeoutCallbacks(); + }, + }, + { + caption: "update package.json from @types so error is fixed", + edit: sys => sys.writeFile("/home/src/projects/project/node_modules/@types/bar/package.json", getFsConentsForAlternateResultAtTypesPackageJson("bar", /*addTypesCondition*/ true)), + timeouts: sys => { + sys.runQueuedTimeoutCallbacks(); + sys.runQueuedTimeoutCallbacks(); + }, + }, + { + caption: "update package.json so error is fixed", + edit: sys => sys.writeFile("/home/src/projects/project/node_modules/foo/package.json", getFsContentsForAlternateResultPackageJson("foo", /*addTypes*/ true, /*addTypesCondition*/ true)), + timeouts: sys => { + sys.runQueuedTimeoutCallbacks(); + sys.runQueuedTimeoutCallbacks(); + }, + }, + { + caption: "update package.json from @types so error is introduced", + edit: sys => sys.writeFile("/home/src/projects/project/node_modules/@types/bar2/package.json", getFsConentsForAlternateResultAtTypesPackageJson("bar2", /*addTypesCondition*/ false)), + timeouts: sys => { + sys.runQueuedTimeoutCallbacks(); + sys.runQueuedTimeoutCallbacks(); + }, + }, + { + caption: "update package.json so error is introduced", + edit: sys => sys.writeFile("/home/src/projects/project/node_modules/foo2/package.json", getFsContentsForAlternateResultPackageJson("foo2", /*addTypes*/ true, /*addTypesCondition*/ false)), + timeouts: sys => { + sys.runQueuedTimeoutCallbacks(); + sys.runQueuedTimeoutCallbacks(); + }, + }, + { + caption: "delete the alternateResult in @types", + edit: sys => sys.deleteFile("/home/src/projects/project/node_modules/@types/bar2/index.d.ts"), + timeouts: sys => { + sys.runQueuedTimeoutCallbacks(); + sys.runQueuedTimeoutCallbacks(); + }, + }, + { + caption: "delete the ndoe10Result in package/types", + edit: sys => sys.deleteFile("/home/src/projects/project/node_modules/foo2/index.d.ts"), + timeouts: sys => { + sys.runQueuedTimeoutCallbacks(); + sys.runQueuedTimeoutCallbacks(); + }, + }, + { + caption: "add the alternateResult in @types", + edit: sys => sys.writeFile("/home/src/projects/project/node_modules/@types/bar2/index.d.ts", getFsContentsForAlternateResultDts("bar2")), + timeouts: sys => { + sys.runQueuedTimeoutCallbacks(); + sys.runQueuedTimeoutCallbacks(); + }, + }, + { + caption: "add the ndoe10Result in package/types", + edit: sys => sys.writeFile("/home/src/projects/project/node_modules/foo2/index.d.ts", getFsContentsForAlternateResultDts("foo2")), + timeouts: sys => { + sys.runQueuedTimeoutCallbacks(); + sys.runQueuedTimeoutCallbacks(); + }, + }, + ], + ); } diff --git a/src/testRunner/unittests/helpers/baseline.ts b/src/testRunner/unittests/helpers/baseline.ts index 84183f87fafef..97146d59b03cb 100644 --- a/src/testRunner/unittests/helpers/baseline.ts +++ b/src/testRunner/unittests/helpers/baseline.ts @@ -1,15 +1,13 @@ -import * as fakes from "../../_namespaces/fakes.js"; -import * as Harness from "../../_namespaces/Harness.js"; +import { SourceMapRecorder } from "../../_namespaces/Harness.js"; import * as ts from "../../_namespaces/ts.js"; import { jsonToReadableText } from "../helpers.js"; -import { TscCompileSystem } from "./tsc.js"; -import { TestServerHost } from "./virtualFileSystemWithWatch.js"; - -export function sanitizeSysOutput(output: string): string { - return output - .replace(/Elapsed::\s[0-9]+(?:\.\d+)?ms/g, "Elapsed:: *ms") - .replace(/[0-9][0-9]:[0-9][0-9]:[0-9][0-9]\s(A|P)M/g, "HH:MM:SS AM"); -} +import { + changeToHostTrackingWrittenFiles, + SerializeOutputOrder, + StateLogger, + TestServerHost, + TestServerHostTrackingWrittenFiles, +} from "./virtualFileSystemWithWatch.js"; export type CommandLineProgram = [ts.Program, ts.BuilderProgram?]; export interface CommandLineCallbacks { @@ -21,7 +19,7 @@ function isAnyProgram(program: ts.Program | ts.BuilderProgram | ts.ParsedCommand return !!(program as ts.Program | ts.BuilderProgram).getCompilerOptions; } export function commandLineCallbacks( - sys: TscCompileSystem | TestServerHost, + sys: TestServerHost, originalReadCall?: ts.System["readFile"], ): CommandLineCallbacks { let programs: CommandLineProgram[] | undefined; @@ -48,7 +46,12 @@ export function commandLineCallbacks( }; } -export function baselinePrograms(baseline: string[], programs: readonly CommandLineProgram[], oldPrograms: readonly (CommandLineProgram | undefined)[], baselineDependencies: boolean | undefined): void { +function baselinePrograms( + baseline: string[], + programs: readonly CommandLineProgram[], + oldPrograms: readonly (CommandLineProgram | undefined)[], + baselineDependencies: boolean | undefined, +) { for (let i = 0; i < programs.length; i++) { baselineProgram(baseline, programs[i], oldPrograms[i], baselineDependencies); } @@ -127,10 +130,10 @@ function baselineProgram(baseline: string[], [program, builderProgram]: CommandL baseline.push(""); } -export function generateSourceMapBaselineFiles(sys: ts.System & { writtenFiles: ts.ReadonlyCollection; }): void { +function generateSourceMapBaselineFiles(sys: ts.System & { writtenFiles: ts.ReadonlyCollection; }) { const mapFileNames = ts.mapDefinedIterator(sys.writtenFiles.keys(), f => f.endsWith(".map") ? f : undefined); for (const mapFile of mapFileNames) { - const text = Harness.SourceMapRecorder.getSourceMapRecordWithSystem(sys, mapFile); + const text = SourceMapRecorder.getSourceMapRecordWithSystem(sys, mapFile); sys.writeFile(`${mapFile}.baseline.txt`, text); } } @@ -228,7 +231,7 @@ export interface ReadableBuildInfo extends ts.BuildInfo { function generateBuildInfoBaseline(sys: ts.System, buildInfoPath: string, buildInfo: ts.BuildInfo) { let fileIdsList: string[][] | undefined; let result; - const version = buildInfo.version === ts.version ? fakes.version : buildInfo.version; + const version = buildInfo.version === ts.version ? fakeTsVersion : buildInfo.version; if (!ts.isIncrementalBuildInfo(buildInfo)) { result = { ...buildInfo, @@ -396,7 +399,7 @@ export function toPathWithSystem(sys: ts.System, fileName: string): ts.Path { export function baselineBuildInfo( options: ts.CompilerOptions, - sys: TscCompileSystem | TestServerHost, + sys: TestServerHost, originalReadCall?: ts.System["readFile"], ): void { const buildInfoPath = ts.getTsBuildInfoEmitOutputFilePath(options); @@ -408,6 +411,119 @@ export function baselineBuildInfo( generateBuildInfoBaseline(sys, buildInfoPath, buildInfo); } -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 isWatch(commandLineArgs: readonly string[]): boolean | undefined { + return ts.forEach(commandLineArgs, arg => { + if (arg.charCodeAt(0) !== ts.CharacterCodes.minus) return false; + const option = arg.slice(arg.charCodeAt(1) === ts.CharacterCodes.minus ? 2 : 1).toLowerCase(); + return option === "watch" || option === "w"; + }); +} + +export type TscWatchSystem = TestServerHostTrackingWrittenFiles; + +function changeToTestServerHostWithTimeoutLogging(host: TestServerHostTrackingWrittenFiles, baseline: string[]): TscWatchSystem { + const logger: StateLogger = { + log: s => baseline.push(s), + logs: baseline, + }; + host.switchToBaseliningInvoke(logger, SerializeOutputOrder.BeforeDiff); + return host; +} + +export interface BaselineBase { + baseline: string[]; + sys: TscWatchSystem; +} + +export interface Baseline extends BaselineBase, CommandLineCallbacks { +} + +export const fakeTsVersion = "FakeTSVersion"; + +export function patchHostForBuildInfoReadWrite(sys: T): T { + const originalReadFile = sys.readFile; + sys.readFile = (path, encoding) => { + const value = originalReadFile.call(sys, path, encoding); + if (!value || !ts.isBuildInfoFile(path)) return value; + const buildInfo = ts.getBuildInfo(path, value); + if (!buildInfo) return value; + ts.Debug.assert(buildInfo.version === fakeTsVersion); + buildInfo.version = ts.version; + return ts.getBuildInfoText(buildInfo); + }; + return patchHostForBuildInfoWrite(sys, fakeTsVersion); +} + +export function patchHostForBuildInfoWrite(sys: T, version: string): T { + const originalWrite = sys.write; + sys.write = msg => originalWrite.call(sys, msg.replace(ts.version, version)); + const originalWriteFile = sys.writeFile; + sys.writeFile = (fileName: string, content: string, writeByteOrderMark: boolean) => { + if (ts.isBuildInfoFile(fileName)) { + const buildInfo = ts.getBuildInfo(fileName, content); + if (buildInfo) { + buildInfo.version = version; + return originalWriteFile.call(sys, fileName, ts.getBuildInfoText(buildInfo), writeByteOrderMark); + } + } + return originalWriteFile.call(sys, fileName, content, writeByteOrderMark); + }; + return sys; +} + +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("Input::"); + sys.serializeState(baseline, SerializeOutputOrder.None); + const { cb, getPrograms } = commandLineCallbacks(sys); + return { sys, baseline, cb, getPrograms }; +} + +export function applyEdit( + sys: BaselineBase["sys"], + baseline: BaselineBase["baseline"], + edit: (sys: TscWatchSystem) => void, + caption?: string, +): void { + baseline.push(`Change::${caption ? " " + caption : ""}`, ""); + edit(sys); + baseline.push("Input::"); + sys.serializeState(baseline, SerializeOutputOrder.AfterDiff); +} + +export function baselineAfterTscCompile( + sys: BaselineBase["sys"], + baseline: BaselineBase["baseline"], + getPrograms: CommandLineCallbacks["getPrograms"], + oldPrograms: readonly (CommandLineProgram | undefined)[], + baselineSourceMap: boolean | undefined, + shouldBaselinePrograms: boolean | undefined, + baselineDependencies: boolean | undefined, +): readonly CommandLineProgram[] { + if (baselineSourceMap) generateSourceMapBaselineFiles(sys); + const programs = getPrograms(); + sys.writtenFiles.forEach((value, key) => { + // When buildinfo is same for two projects, + // it gives error and doesnt write buildinfo but because buildInfo is written for one project, + // readable baseline will be written two times for those two projects with same contents and is ok + ts.Debug.assert(value === 1 || ts.endsWith(key, "baseline.txt"), `Expected to write file ${key} only once`); + }); + sys.serializeState(baseline, SerializeOutputOrder.BeforeDiff); + if (shouldBaselinePrograms) { + baselinePrograms(baseline, programs, oldPrograms, baselineDependencies); + } + baseline.push(`exitCode:: ExitStatus.${ts.ExitStatus[sys.exitCode as ts.ExitStatus]}`, ""); + return programs; +} + +export function tscBaselineName(scenario: string, subScenario: string, commandLineArgs: readonly string[], suffix?: string) { + return `${ts.isBuildCommand(commandLineArgs) ? "tsbuild" : "tsc"}${isWatch(commandLineArgs) ? "Watch" : ""}/${scenario}/${subScenario.split(" ").join("-")}${suffix ? suffix : ""}.js`; } diff --git a/src/testRunner/unittests/helpers/demoProjectReferences.ts b/src/testRunner/unittests/helpers/demoProjectReferences.ts index 13eaf9e69f523..38e7360f704c4 100644 --- a/src/testRunner/unittests/helpers/demoProjectReferences.ts +++ b/src/testRunner/unittests/helpers/demoProjectReferences.ts @@ -1,16 +1,6 @@ import { dedent } from "../../_namespaces/Utils.js"; -import { FileSystem } from "../../_namespaces/vfs.js"; import { jsonToReadableText } from "../helpers.js"; -import { - FsContents, - libContent, -} from "./contents.js"; -import { loadProjectFromFiles } from "./vfs.js"; -import { - createWatchedSystem, - libFile, - TestServerHost, -} from "./virtualFileSystemWithWatch.js"; +import { TestServerHost } from "./virtualFileSystemWithWatch.js"; export function getFsContentsForDemoProjectReferencesCoreConfig(additional?: object): string { return jsonToReadableText({ @@ -22,8 +12,8 @@ export function getFsContentsForDemoProjectReferencesCoreConfig(additional?: obj ...additional, }); } -export function getFsContentsForDemoProjectReferences(): FsContents { - return { +export function getSysForDemoProjectReferences(): TestServerHost { + return TestServerHost.createWatchedSystem({ "/user/username/projects/demo/animals/animal.ts": dedent` export type Size = "small" | "medium" | "large"; export default interface Animal { @@ -126,25 +116,5 @@ export function getFsContentsForDemoProjectReferences(): FsContents { }, ], }), - [libFile.path]: libContent, - }; -} - -export function getFsForDemoProjectReferences(): FileSystem { - return loadProjectFromFiles( - getFsContentsForDemoProjectReferences(), - { - cwd: "/user/username/projects/demo", - executingFilePath: libFile.path, - }, - ); -} - -export function getSysForDemoProjectReferences(): TestServerHost { - return createWatchedSystem( - getFsContentsForDemoProjectReferences(), - { - currentDirectory: "/user/username/projects/demo", - }, - ); + }, { currentDirectory: "/user/username/projects/demo" }); } diff --git a/src/testRunner/unittests/helpers/extends.ts b/src/testRunner/unittests/helpers/extends.ts index a776622926a4b..204825cf58ad0 100644 --- a/src/testRunner/unittests/helpers/extends.ts +++ b/src/testRunner/unittests/helpers/extends.ts @@ -1,15 +1,10 @@ import { dedent } from "../../_namespaces/Utils.js"; import { jsonToReadableText } from "../helpers.js"; -import { FsContents } from "./contents.js"; -import { - createServerHost, - createWatchedSystem, - libFile, - TestServerHost, -} from "./virtualFileSystemWithWatch.js"; +import { TscWatchCompileChange } from "./tscWatch.js"; +import { TestServerHost } from "./virtualFileSystemWithWatch.js"; export function getSymlinkedExtendsSys(forTsserver?: true): TestServerHost { - return (!forTsserver ? createWatchedSystem : createServerHost)({ + return TestServerHost.getCreateWatchedSystem(forTsserver)({ "/users/user/projects/myconfigs/node_modules/@something/tsconfig-node/tsconfig.json": jsonToReadableText({ extends: "@something/tsconfig-base/tsconfig.json", compilerOptions: { @@ -29,12 +24,11 @@ export function getSymlinkedExtendsSys(forTsserver?: true): TestServerHost { "/users/user/projects/myproject/node_modules/@something/tsconfig-node": { symLink: "/users/user/projects/myconfigs/node_modules/@something/tsconfig-node", }, - [libFile.path]: libFile.content, }, { currentDirectory: "/users/user/projects/myproject" }); } -export function getConfigDirExtendsSys(): FsContents { - return { +export function getConfigDirExtendsSys(forTsserver?: boolean): TestServerHost { + return TestServerHost.getCreateWatchedSystem(forTsserver)({ "/home/src/projects/configs/first/tsconfig.json": jsonToReadableText({ extends: "../second/tsconfig.json", include: ["${configDir}/src"], // eslint-disable-line no-template-curly-in-string @@ -82,11 +76,10 @@ export function getConfigDirExtendsSys(): FsContents { "/home/src/projects/myproject/root2/other/sometype2/index.d.ts": dedent` export const k = 10; `, - [libFile.path]: libFile.content, - }; + }, { currentDirectory: "/home/src/projects/myproject" }); } -export function modifyFirstExtendedConfigOfConfigDirExtendsSys(sys: TestServerHost): void { +function modifyFirstExtendedConfigOfConfigDirExtendsSys(sys: TestServerHost) { sys.modifyFile( "/home/src/projects/configs/first/tsconfig.json", jsonToReadableText({ @@ -99,3 +92,22 @@ export function modifyFirstExtendedConfigOfConfigDirExtendsSys(sys: TestServerHo }), ); } + +export function forConfigDirExtendsSysScenario( + forTsserver: boolean, + action: ( + scenario: string, + sys: () => TestServerHost, + edits: () => readonly TscWatchCompileChange[], + ) => void, +): void { + action( + "configDir template", + () => getConfigDirExtendsSys(forTsserver), + () => [{ + caption: "edit extended config file", + edit: modifyFirstExtendedConfigOfConfigDirExtendsSys, + timeouts: sys => sys.runQueuedTimeoutCallbacks(), + }], + ); +} diff --git a/src/testRunner/unittests/helpers/libraryResolution.ts b/src/testRunner/unittests/helpers/libraryResolution.ts index 9b2b8f1b8724c..aa113a86f8629 100644 --- a/src/testRunner/unittests/helpers/libraryResolution.ts +++ b/src/testRunner/unittests/helpers/libraryResolution.ts @@ -1,91 +1,217 @@ +import { emptyArray } from "../../_namespaces/ts.js"; import { dedent } from "../../_namespaces/Utils.js"; -import { FileSystem } from "../../_namespaces/vfs.js"; import { jsonToReadableText } from "../helpers.js"; +import { TscWatchSystem } from "./baseline.js"; +import { getTypeScriptLibTestLocation } from "./contents.js"; +import { TscWatchCompileChange } from "./tscWatch.js"; import { - FsContents, - libContent, -} from "./contents.js"; -import { loadProjectFromFiles } from "./vfs.js"; -import { - createServerHost, - createWatchedSystem, + libFile, TestServerHost, } from "./virtualFileSystemWithWatch.js"; -function getFsContentsForLibResolution(libRedirection?: boolean): FsContents { - return { - "/home/src/projects/project1/utils.d.ts": `export const y = 10;`, - "/home/src/projects/project1/file.ts": `export const file = 10;`, - "/home/src/projects/project1/core.d.ts": `export const core = 10;`, - "/home/src/projects/project1/index.ts": `export const x = "type1";`, - "/home/src/projects/project1/file2.ts": dedent` +function getSysForLibResolution(libRedirection?: boolean, forTsserver?: boolean) { + return TestServerHost.getCreateWatchedSystem(forTsserver)({ + "/home/src/workspace/projects/project1/utils.d.ts": `export const y = 10;`, + "/home/src/workspace/projects/project1/file.ts": `export const file = 10;`, + "/home/src/workspace/projects/project1/core.d.ts": `export const core = 10;`, + "/home/src/workspace/projects/project1/index.ts": `export const x = "type1";`, + "/home/src/workspace/projects/project1/file2.ts": dedent` /// /// /// `, - "/home/src/projects/project1/tsconfig.json": jsonToReadableText({ + "/home/src/workspace/projects/project1/tsconfig.json": jsonToReadableText({ 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;`, - "/home/src/projects/project2/index.ts": `export const y = 10`, - "/home/src/projects/project2/tsconfig.json": jsonToReadableText({ + "/home/src/workspace/projects/project1/typeroot1/sometype/index.d.ts": `export type TheNum = "type1";`, + "/home/src/workspace/projects/project2/utils.d.ts": `export const y = 10;`, + "/home/src/workspace/projects/project2/index.ts": `export const y = 10`, + "/home/src/workspace/projects/project2/tsconfig.json": jsonToReadableText({ compilerOptions: { composite: true, lib: ["es5", "dom"], traceResolution: true }, }), - "/home/src/projects/project3/utils.d.ts": `export const y = 10;`, - "/home/src/projects/project3/index.ts": `export const z = 10`, - "/home/src/projects/project3/tsconfig.json": jsonToReadableText({ + "/home/src/workspace/projects/project3/utils.d.ts": `export const y = 10;`, + "/home/src/workspace/projects/project3/index.ts": `export const z = 10`, + "/home/src/workspace/projects/project3/tsconfig.json": jsonToReadableText({ compilerOptions: { composite: true, lib: ["es5", "dom"], traceResolution: true }, }), - "/home/src/projects/project4/utils.d.ts": `export const y = 10;`, - "/home/src/projects/project4/index.ts": `export const z = 10`, - "/home/src/projects/project4/tsconfig.json": jsonToReadableText({ + "/home/src/workspace/projects/project4/utils.d.ts": `export const y = 10;`, + "/home/src/workspace/projects/project4/index.ts": `export const z = 10`, + "/home/src/workspace/projects/project4/tsconfig.json": jsonToReadableText({ compilerOptions: { composite: true, lib: ["esnext", "dom", "webworker"], traceResolution: true }, }), - "/home/src/lib/lib.es5.d.ts": libContent, - "/home/src/lib/lib.esnext.d.ts": libContent, - "/home/src/lib/lib.dom.d.ts": "interface DOMInterface { }", - "/home/src/lib/lib.webworker.d.ts": "interface WebWorkerInterface { }", - "/home/src/lib/lib.scripthost.d.ts": "interface ScriptHostInterface { }", - "/home/src/projects/node_modules/@typescript/unlreated/index.d.ts": "export const unrelated = 10;", + [getTypeScriptLibTestLocation("dom")]: "interface DOMInterface { }", + [getTypeScriptLibTestLocation("webworker")]: "interface WebWorkerInterface { }", + [getTypeScriptLibTestLocation("scripthost")]: "interface ScriptHostInterface { }", + "/home/src/workspace/projects/node_modules/@typescript/unlreated/index.d.ts": "export const unrelated = 10;", ...libRedirection ? { - "/home/src/projects/node_modules/@typescript/lib-es5/index.d.ts": libContent, - "/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/workspace/projects/node_modules/@typescript/lib-es5/index.d.ts": libFile.content, + "/home/src/workspace/projects/node_modules/@typescript/lib-esnext/index.d.ts": libFile.content, + "/home/src/workspace/projects/node_modules/@typescript/lib-dom/index.d.ts": "interface DOMInterface { }", + "/home/src/workspace/projects/node_modules/@typescript/lib-webworker/index.d.ts": "interface WebWorkerInterface { }", + "/home/src/workspace/projects/node_modules/@typescript/lib-scripthost/index.d.ts": "interface ScriptHostInterface { }", } : undefined, - }; + }, { currentDirectory: "/home/src/workspace/projects" }); } -export function getFsForLibResolution(libRedirection: true | undefined): FileSystem { - return loadProjectFromFiles( - getFsContentsForLibResolution(libRedirection), - { - cwd: "/home/src/projects", - executingFilePath: "/home/src/lib/tsc.js", - }, - ); +function getLibResolutionEditOptions( + withoutConfig: true | undefined, + changeLib: (sys: TscWatchSystem) => void, +): readonly TscWatchCompileChange[] { + return withoutConfig ? + emptyArray : + [ + { + caption: "change program options to update module resolution", + edit: sys => + sys.writeFile( + "/home/src/workspace/projects/project1/tsconfig.json", + jsonToReadableText({ + compilerOptions: { + composite: true, + typeRoots: ["./typeroot1", "./typeroot2"], + lib: ["es5", "dom"], + traceResolution: true, + }, + }), + ), + timeouts: sys => { + sys.runQueuedTimeoutCallbacks(); + sys.runQueuedTimeoutCallbacks(); + }, + }, + { + caption: "change program options to update module resolution and also update lib file", + edit: sys => { + sys.writeFile( + "/home/src/workspace/projects/project1/tsconfig.json", + jsonToReadableText({ + compilerOptions: { + composite: true, + typeRoots: ["./typeroot1"], + lib: ["es5", "dom"], + traceResolution: true, + }, + }), + ); + changeLib(sys); + }, + timeouts: sys => { + sys.runQueuedTimeoutCallbacks(); + sys.runQueuedTimeoutCallbacks(); + }, + }, + ]; } -export function getSysForLibResolution(libRedirection?: true): TestServerHost { - return createWatchedSystem( - getFsContentsForLibResolution(libRedirection), +function getLibResolutionWithoutRedirection(withoutConfig: true | undefined): readonly TscWatchCompileChange[] { + return [ + { + caption: "write redirect file dom", + edit: sys => sys.ensureFileOrFolder({ path: "/home/src/workspace/projects/node_modules/@typescript/lib-dom/index.d.ts", content: "interface DOMInterface { }" }), + timeouts: sys => { + sys.runQueuedTimeoutCallbacks(); + sys.runQueuedTimeoutCallbacks(); + }, + }, + { + caption: "edit file", + edit: sys => sys.appendFile("/home/src/workspace/projects/project1/file.ts", "export const xyz = 10;"), + timeouts: sys => sys.runQueuedTimeoutCallbacks(), + }, { - currentDirectory: "/home/src/projects", - executingFilePath: "/home/src/lib/tsc.js", + caption: "delete core", + edit: sys => sys.deleteFile("/home/src/workspace/projects/project1/core.d.ts"), + timeouts: sys => sys.runQueuedTimeoutCallbacks(), }, - ); + { + caption: "delete redirect file dom", + edit: sys => sys.deleteFile("/home/src/workspace/projects/node_modules/@typescript/lib-dom/index.d.ts"), + timeouts: sys => sys.runQueuedTimeoutCallbacks(), + }, + ...getLibResolutionEditOptions( + withoutConfig, + sys => + sys.ensureFileOrFolder({ + path: "/home/src/workspace/projects/node_modules/@typescript/lib-dom/index.d.ts", + content: "interface DOMInterface { }", + }), + ), + { + caption: "write redirect file webworker", + edit: sys => sys.ensureFileOrFolder({ path: "/home/src/workspace/projects/node_modules/@typescript/lib-webworker/index.d.ts", content: "interface WebWorkerInterface { }" }), + timeouts: sys => { + sys.runQueuedTimeoutCallbacks(); + sys.runQueuedTimeoutCallbacks(); + }, + }, + { + caption: "delete redirect file webworker", + edit: sys => sys.deleteFile("/home/src/workspace/projects/node_modules/@typescript/lib-webworker/index.d.ts"), + timeouts: sys => sys.runQueuedTimeoutCallbacks(), + }, + ]; } -export function getServerHostForLibResolution(libRedirection?: true): TestServerHost { - return createServerHost( - getFsContentsForLibResolution(libRedirection), +function getLibResolutionWithRedirection(withoutConfig: true | undefined): readonly TscWatchCompileChange[] { + return [ + { + caption: "delete redirect file dom", + edit: sys => sys.deleteFile("/home/src/workspace/projects/node_modules/@typescript/lib-dom/index.d.ts"), + timeouts: sys => sys.runQueuedTimeoutCallbacks(), + }, + { + caption: "edit file", + edit: sys => sys.appendFile("/home/src/workspace/projects/project1/file.ts", "export const xyz = 10;"), + timeouts: sys => sys.runQueuedTimeoutCallbacks(), + }, + { + caption: "delete core", + edit: sys => sys.deleteFile("/home/src/workspace/projects/project1/core.d.ts"), + timeouts: sys => sys.runQueuedTimeoutCallbacks(), + }, + { + caption: "write redirect file dom", + edit: sys => sys.ensureFileOrFolder({ path: "/home/src/workspace/projects/node_modules/@typescript/lib-dom/index.d.ts", content: "interface DOMInterface { }" }), + timeouts: sys => { + sys.runQueuedTimeoutCallbacks(); + sys.runQueuedTimeoutCallbacks(); + }, + }, + ...getLibResolutionEditOptions( + withoutConfig, + sys => sys.deleteFile("/home/src/workspace/projects/node_modules/@typescript/lib-dom/index.d.ts"), + ), { - currentDirectory: "/home/src/projects", - executingFilePath: "/home/src/lib/tsc.js", + caption: "delete redirect file webworker", + edit: sys => sys.deleteFile("/home/src/workspace/projects/node_modules/@typescript/lib-webworker/index.d.ts"), + timeouts: sys => sys.runQueuedTimeoutCallbacks(), }, - ); + { + caption: "write redirect file webworker", + edit: sys => sys.ensureFileOrFolder({ path: "/home/src/workspace/projects/node_modules/@typescript/lib-webworker/index.d.ts", content: "interface WebWorkerInterface { }" }), + timeouts: sys => { + sys.runQueuedTimeoutCallbacks(); + sys.runQueuedTimeoutCallbacks(); + }, + }, + ]; +} + +export function forEachLibResolutionScenario( + forTsserver: boolean, + withoutConfig: true | undefined, + action: (scenario: string, sys: () => TestServerHost, edits: () => readonly TscWatchCompileChange[]) => void, +): void { + [undefined, true].forEach(libRedirection => { + action( + `${withoutConfig ? "without" : "with"} config${libRedirection ? " with redirection" : ""}`, + () => getSysForLibResolution(libRedirection, forTsserver), + () => + libRedirection ? + getLibResolutionWithRedirection(withoutConfig) : + getLibResolutionWithoutRedirection(withoutConfig), + ); + }); } export function getCommandLineArgsForLibResolution(withoutConfig: true | undefined): string[] { @@ -94,45 +220,24 @@ export function getCommandLineArgsForLibResolution(withoutConfig: true | undefin ["-p", "project1", "--explainFiles"]; } -function getFsContentsForLibResolutionUnknown(): FsContents { - return { - "/home/src/projects/project1/utils.d.ts": `export const y = 10;`, - "/home/src/projects/project1/file.ts": `export const file = 10;`, - "/home/src/projects/project1/core.d.ts": `export const core = 10;`, - "/home/src/projects/project1/index.ts": `export const x = "type1";`, - "/home/src/projects/project1/file2.ts": dedent` +export function getSysForLibResolutionUnknown(): TestServerHost { + return TestServerHost.createWatchedSystem({ + "/home/src/workspace/projects/project1/utils.d.ts": `export const y = 10;`, + "/home/src/workspace/projects/project1/file.ts": `export const file = 10;`, + "/home/src/workspace/projects/project1/core.d.ts": `export const core = 10;`, + "/home/src/workspace/projects/project1/index.ts": `export const x = "type1";`, + "/home/src/workspace/projects/project1/file2.ts": dedent` /// /// /// `, - "/home/src/projects/project1/tsconfig.json": jsonToReadableText({ + "/home/src/workspace/projects/project1/tsconfig.json": jsonToReadableText({ compilerOptions: { composite: true, traceResolution: true, }, }), - "/home/src/lib/lib.d.ts": libContent, - "/home/src/lib/lib.webworker.d.ts": "interface WebWorkerInterface { }", - "/home/src/lib/lib.scripthost.d.ts": "interface ScriptHostInterface { }", - }; -} - -export function getFsForLibResolutionUnknown(): FileSystem { - return loadProjectFromFiles( - getFsContentsForLibResolutionUnknown(), - { - cwd: "/home/src/projects", - executingFilePath: "/home/src/lib/tsc.js", - }, - ); -} - -export function getSysForLibResolutionUnknown(): TestServerHost { - return createWatchedSystem( - getFsContentsForLibResolutionUnknown(), - { - currentDirectory: "/home/src/projects", - executingFilePath: "/home/src/lib/tsc.js", - }, - ); + [getTypeScriptLibTestLocation("webworker")]: "interface WebWorkerInterface { }", + [getTypeScriptLibTestLocation("scripthost")]: "interface ScriptHostInterface { }", + }, { currentDirectory: "/home/src/workspace/projects" }); } diff --git a/src/testRunner/unittests/helpers/noEmit.ts b/src/testRunner/unittests/helpers/noEmit.ts index 4cabe301e719c..ccf3d04431e58 100644 --- a/src/testRunner/unittests/helpers/noEmit.ts +++ b/src/testRunner/unittests/helpers/noEmit.ts @@ -6,25 +6,14 @@ import { } from "../../_namespaces/ts.js"; import { dedent } from "../../_namespaces/Utils.js"; import { jsonToReadableText } from "../helpers.js"; -import { - compilerOptionsToConfigJson, - FsContents, - libContent, -} from "./contents.js"; +import { compilerOptionsToConfigJson } from "./contents.js"; import { noChangeRun, TestTscEdit, verifyTsc, } from "./tsc.js"; import { verifyTscWatch } from "./tscWatch.js"; -import { - loadProjectFromFiles, - replaceText, -} from "./vfs.js"; -import { - createWatchedSystem, - libFile, -} from "./virtualFileSystemWithWatch.js"; +import { TestServerHost } from "./virtualFileSystemWithWatch.js"; function forEachNoEmitChangesWorker(commandType: string[], compilerOptions: CompilerOptions) { const discrepancyExplanation = () => [ @@ -34,7 +23,7 @@ function forEachNoEmitChangesWorker(commandType: string[], compilerOptions: Comp const noChangeRunWithNoEmit: TestTscEdit = { ...noChangeRun, caption: "No Change run with noEmit", - commandLineArgs: [...commandType, "src/project", "--noEmit"], + commandLineArgs: [...commandType, ".", "--noEmit"], discrepancyExplanation: compilerOptions.composite ? discrepancyExplanation : undefined, @@ -42,7 +31,7 @@ function forEachNoEmitChangesWorker(commandType: string[], compilerOptions: Comp const noChangeRunWithEmit: TestTscEdit = { ...noChangeRun, caption: "No Change run with emit", - commandLineArgs: [...commandType, "src/project"], + commandLineArgs: [...commandType, "."], }; let optionsString = ""; for (const key in compilerOptions) { @@ -57,22 +46,22 @@ function forEachNoEmitChangesWorker(commandType: string[], compilerOptions: Comp verifyTsc({ scenario: "noEmit", subScenario: scenarioName("changes"), - commandLineArgs: [...commandType, "src/project"], - fs, + commandLineArgs: [...commandType, "."], + sys, edits: [ noChangeRunWithNoEmit, noChangeRunWithNoEmit, { caption: "Introduce error but still noEmit", - commandLineArgs: [...commandType, "src/project", "--noEmit"], - edit: fs => replaceText(fs, "/src/project/src/class.ts", "prop", "prop1"), + commandLineArgs: [...commandType, ".", "--noEmit"], + edit: sys => sys.replaceFileText("/home/src/workspaces/project/src/class.ts", "prop", "prop1"), discrepancyExplanation: compilerOptions.composite ? discrepancyExplanation : undefined, }, { caption: "Fix error and emit", - edit: fs => replaceText(fs, "/src/project/src/class.ts", "prop1", "prop"), + edit: sys => sys.replaceFileText("/home/src/workspaces/project/src/class.ts", "prop1", "prop"), }, noChangeRunWithEmit, noChangeRunWithNoEmit, @@ -80,7 +69,7 @@ function forEachNoEmitChangesWorker(commandType: string[], compilerOptions: Comp noChangeRunWithEmit, { caption: "Introduce error and emit", - edit: fs => replaceText(fs, "/src/project/src/class.ts", "prop", "prop1"), + edit: sys => sys.replaceFileText("/home/src/workspaces/project/src/class.ts", "prop", "prop1"), }, noChangeRunWithEmit, noChangeRunWithNoEmit, @@ -88,8 +77,8 @@ function forEachNoEmitChangesWorker(commandType: string[], compilerOptions: Comp noChangeRunWithEmit, { caption: "Fix error and no emit", - commandLineArgs: [...commandType, "src/project", "--noEmit"], - edit: fs => replaceText(fs, "/src/project/src/class.ts", "prop1", "prop"), + commandLineArgs: [...commandType, ".", "--noEmit"], + edit: sys => sys.replaceFileText("/home/src/workspaces/project/src/class.ts", "prop1", "prop"), discrepancyExplanation: compilerOptions.composite ? discrepancyExplanation : undefined, @@ -104,18 +93,18 @@ function forEachNoEmitChangesWorker(commandType: string[], compilerOptions: Comp verifyTsc({ scenario: "noEmit", subScenario: scenarioName("changes with initial noEmit"), - commandLineArgs: [...commandType, "src/project", "--noEmit"], - fs, + commandLineArgs: [...commandType, ".", "--noEmit"], + sys, edits: [ noChangeRunWithEmit, { caption: "Introduce error with emit", - commandLineArgs: [...commandType, "src/project"], - edit: fs => replaceText(fs, "/src/project/src/class.ts", "prop", "prop1"), + commandLineArgs: [...commandType, "."], + edit: sys => sys.replaceFileText("/home/src/workspaces/project/src/class.ts", "prop", "prop1"), }, { caption: "Fix error and no emit", - edit: fs => replaceText(fs, "/src/project/src/class.ts", "prop1", "prop"), + edit: sys => sys.replaceFileText("/home/src/workspaces/project/src/class.ts", "prop1", "prop"), discrepancyExplanation: compilerOptions.composite ? discrepancyExplanation : undefined, @@ -124,30 +113,30 @@ function forEachNoEmitChangesWorker(commandType: string[], compilerOptions: Comp ], }); - function fs() { - return loadProjectFromFiles({ - "/src/project/src/class.ts": dedent` + function sys() { + return TestServerHost.createWatchedSystem({ + "/home/src/workspaces/project/src/class.ts": dedent` export class classC { prop = 1; }`, - "/src/project/src/indirectClass.ts": dedent` + "/home/src/workspaces/project/src/indirectClass.ts": dedent` import { classC } from './class'; export class indirectClass { classC = new classC(); }`, - "/src/project/src/directUse.ts": dedent` + "/home/src/workspaces/project/src/directUse.ts": dedent` import { indirectClass } from './indirectClass'; new indirectClass().classC.prop;`, - "/src/project/src/indirectUse.ts": dedent` + "/home/src/workspaces/project/src/indirectUse.ts": dedent` import { indirectClass } from './indirectClass'; new indirectClass().classC.prop;`, - "/src/project/src/noChangeFile.ts": dedent` + "/home/src/workspaces/project/src/noChangeFile.ts": dedent` export function writeLog(s: string) { }`, - "/src/project/src/noChangeFileWithEmitSpecificError.ts": dedent` + "/home/src/workspaces/project/src/noChangeFileWithEmitSpecificError.ts": dedent` function someFunc(arguments: boolean, ...rest: any[]) { }`, - "/src/project/tsconfig.json": jsonToReadableText({ + "/home/src/workspaces/project/tsconfig.json": jsonToReadableText({ compilerOptions: compilerOptionsToConfigJson(compilerOptions), }), }); @@ -176,12 +165,12 @@ function editsForDtsChanges( { caption: "With declaration enabled noEmit - Should report errors", edit: noop, - commandLineArgs: [...commandType, "/home/src/projects/project", "--noEmit", "--declaration"], + commandLineArgs: [...commandType, ".", "--noEmit", "--declaration"], }, { caption: "With declaration and declarationMap noEmit - Should report errors", edit: noop, - commandLineArgs: [...commandType, "/home/src/projects/project", "--noEmit", "--declaration", "--declarationMap"], + commandLineArgs: [...commandType, ".", "--noEmit", "--declaration", "--declarationMap"], }, incremental ? { ...noChangeRun, @@ -193,21 +182,21 @@ function editsForDtsChanges( { caption: "Dts Emit with error", edit: noop, - commandLineArgs: [...commandType, "/home/src/projects/project", "--declaration"], + commandLineArgs: [...commandType, ".", "--declaration"], }, { caption: "Fix the error", - edit: fs => fs.writeFileSync("/home/src/projects/project/a.ts", aContent.replace("private", "public")), + edit: sys => sys.writeFile("/home/src/projects/project/a.ts", aContent.replace("private", "public")), }, { caption: "With declaration enabled noEmit", edit: noop, - commandLineArgs: [...commandType, "/home/src/projects/project", "--noEmit", "--declaration"], + commandLineArgs: [...commandType, ".", "--noEmit", "--declaration"], }, { caption: "With declaration and declarationMap noEmit", edit: noop, - commandLineArgs: [...commandType, "/home/src/projects/project", "--noEmit", "--declaration", "--declarationMap"], + commandLineArgs: [...commandType, ".", "--noEmit", "--declaration", "--declarationMap"], // Multi file still needs to report error so will emit build info (for pending dtsMap) discrepancyExplanation: incremental && !multiFile ? () => [ "Clean build will have declaration and declarationMap", @@ -228,16 +217,16 @@ export function forEachNoEmitDtsChanges(commandType: string[]): void { verifyTsc({ scenario: "noEmit", subScenario: `${options.outFile ? "outFile" : "multiFile"}/dts errors with declaration enable changes${incremental ? " with incremental" : ""}${asModules ? " as modules" : ""}`, - commandLineArgs: [...commandType, "/home/src/projects/project", "--noEmit"], - fs: () => - loadProjectFromFiles({ + commandLineArgs: [...commandType, ".", "--noEmit"], + sys: () => + TestServerHost.createWatchedSystem({ "/home/src/projects/project/a.ts": aContent, "/home/src/projects/project/tsconfig.json": jsonToReadableText({ compilerOptions: { ...options, incremental }, }), - }), - modifyFs: asModules ? - fs => fs.writeFileSync("/home/src/projects/project/b.ts", `export const b = 10;`) : + }, { currentDirectory: "/home/src/projects/project" }), + modifySystem: asModules ? + sys => sys.writeFile("/home/src/projects/project/b.ts", `export const b = 10;`) : undefined, edits: editsForDtsChanges(commandType, aContent, incremental, /*multiFile*/ false), baselinePrograms: true, @@ -253,9 +242,9 @@ export function forEachNoEmitDtsChanges(commandType: string[]): void { verifyTsc({ scenario: "noEmit", subScenario: `${options.outFile ? "outFile" : "multiFile"}/dts errors with declaration enable changes with multiple files`, - commandLineArgs: [...commandType, "/home/src/projects/project", "--noEmit"], - fs: () => - loadProjectFromFiles({ + commandLineArgs: [...commandType, ".", "--noEmit"], + sys: () => + TestServerHost.createWatchedSystem({ "/home/src/projects/project/a.ts": aContent, "/home/src/projects/project/b.ts": `export const b = 10;`, "/home/src/projects/project/c.ts": aContent.replace("a", "c"), @@ -263,13 +252,13 @@ export function forEachNoEmitDtsChanges(commandType: string[]): void { "/home/src/projects/project/tsconfig.json": jsonToReadableText({ compilerOptions: { ...options, incremental: true }, }), - }), + }, { currentDirectory: "/home/src/projects/project" }), edits: [ ...editsForDtsChanges(commandType, aContent, /*incremental*/ true, /*multiFile*/ true), { caption: "Fix the another ", - edit: fs => fs.writeFileSync("/home/src/projects/project/c.ts", aContent.replace("a", "c").replace("private", "public")), - commandLineArgs: [...commandType, "/home/src/projects/project", "--noEmit", "--declaration", "--declarationMap"], + edit: sys => sys.writeFile("/home/src/projects/project/c.ts", aContent.replace("a", "c").replace("private", "public")), + commandLineArgs: [...commandType, ".", "--noEmit", "--declaration", "--declarationMap"], }, ], baselinePrograms: true, @@ -284,7 +273,7 @@ function forEachNoEmitAndErrorsWorker( additionalOptions: CompilerOptions | undefined, action: ( subScenario: string, - fsContents: FsContents, + sys: () => TestServerHost, aTsContent: string, fixedATsContent: string, compilerOptions: CompilerOptions, @@ -300,16 +289,18 @@ function forEachNoEmitAndErrorsWorker( incremental, ...additionalOptions, }; - const fsContents: FsContents = { - "/home/src/projects/project/a.ts": aContent, - "/home/src/projects/project/tsconfig.json": jsonToReadableText({ - compilerOptions: compilerOptionsToConfigJson(compilerOptions), - }), - }; - if (asModules) fsContents["/home/src/projects/project/b.ts"] = `export const b = 10;`; action( `${options.outFile ? "outFile" : "multiFile"}/${subScenario}${incremental ? " with incremental" : ""}${asModules ? " as modules" : ""}`, - fsContents, + () => { + const sys = TestServerHost.createWatchedSystem({ + "/home/src/projects/project/a.ts": aContent, + "/home/src/projects/project/tsconfig.json": jsonToReadableText({ + compilerOptions: compilerOptionsToConfigJson(compilerOptions), + }), + }, { currentDirectory: "/home/src/projects/project" }); + if (asModules) sys.writeFile("/home/src/projects/project/b.ts", `export const b = 10;`); + return sys; + }, aContent, `${asModules ? "export " : ""}const a = "hello";`, compilerOptions, @@ -322,7 +313,7 @@ function forEachNoEmitAndErrorsWorker( function forEachNoEmitAndErrors( action: ( subScenario: string, - fsContents: FsContents, + sys: () => TestServerHost, aTsContent: string, fixedATsContent: string, compilerOptions: CompilerOptions, @@ -351,28 +342,28 @@ function forEachNoEmitAndErrors( } export function forEachNoEmitTsc(commandType: string[]): void { - forEachNoEmitAndErrors((subScenario, fsContents, aTsContent, fixedATsContent, compilerOptions) => + forEachNoEmitAndErrors((subScenario, sys, aTsContent, fixedATsContent, compilerOptions) => verifyTsc({ scenario: "noEmit", subScenario, - commandLineArgs: [...commandType, "/home/src/projects/project", "--noEmit"], - fs: () => loadProjectFromFiles(fsContents), + commandLineArgs: [...commandType, ".", "--noEmit"], + sys, edits: [ noChangeRun, { caption: "Fix error", - edit: fs => fs.writeFileSync("/home/src/projects/project/a.ts", fixedATsContent), + edit: sys => sys.writeFile("/home/src/projects/project/a.ts", fixedATsContent), }, noChangeRun, { caption: "Emit after fixing error", edit: noop, - commandLineArgs: [...commandType, "/home/src/projects/project"], + commandLineArgs: [...commandType, "."], }, noChangeRun, { caption: "Introduce error", - edit: fs => fs.writeFileSync("/home/src/projects/project/a.ts", aTsContent), + edit: sys => sys.writeFile("/home/src/projects/project/a.ts", aTsContent), discrepancyExplanation: compilerOptions.incremental && subScenario.indexOf("multiFile/syntax") !== -1 ? () => [ "DtsSignature of ts files: Incremental build have dts signature for ts files from emit so its not d.ts or same as file version", ] : undefined, @@ -380,7 +371,7 @@ export function forEachNoEmitTsc(commandType: string[]): void { { caption: "Emit when error", edit: noop, - commandLineArgs: [...commandType, "/home/src/projects/project"], + commandLineArgs: [...commandType, "."], }, compilerOptions.incremental && subScenario.indexOf("multiFile/syntax") !== -1 ? { ...noChangeRun, @@ -395,20 +386,23 @@ export function forEachNoEmitTsc(commandType: string[]): void { } export function forEachNoEmitTscWatch(commandType: string[]): void { - forEachNoEmitAndErrors((subScenario, fsContents, aTsContent, fixedATsContent, compilerOptions) => + forEachNoEmitAndErrors((subScenario, sys, aTsContent, fixedATsContent, compilerOptions) => verifyTscWatch({ scenario: "noEmit", subScenario, - commandLineArgs: [...commandType, "/home/src/projects/project", "-w"], + commandLineArgs: [...commandType, "-w"], sys: () => { - fsContents["/home/src/projects/project/tsconfig.json"] = jsonToReadableText({ - compilerOptions: compilerOptionsToConfigJson({ - ...compilerOptions, - noEmit: true, + const result = sys(); + result.writeFile( + "/home/src/projects/project/tsconfig.json", + jsonToReadableText({ + compilerOptions: compilerOptionsToConfigJson({ + ...compilerOptions, + noEmit: true, + }), }), - }); - fsContents[libFile.path] = libContent; - return createWatchedSystem(fsContents); + ); + return result; }, edits: [ { diff --git a/src/testRunner/unittests/helpers/projectRoots.ts b/src/testRunner/unittests/helpers/projectRoots.ts index 2792d8062b04e..111038f493c13 100644 --- a/src/testRunner/unittests/helpers/projectRoots.ts +++ b/src/testRunner/unittests/helpers/projectRoots.ts @@ -66,7 +66,7 @@ export function forEachScenarioForRootsFromReferencedProject( sys: () => TestServerHost, edits: () => readonly TscWatchCompileChange[], ) => void, -) { +): void { [true, false].forEach(serverFirst => action( `when root file is from referenced project${!serverFirst ? " and shared is first" : ""}`, diff --git a/src/testRunner/unittests/helpers/sampleProjectReferences.ts b/src/testRunner/unittests/helpers/sampleProjectReferences.ts index e61705dc18652..fbafb4d43d277 100644 --- a/src/testRunner/unittests/helpers/sampleProjectReferences.ts +++ b/src/testRunner/unittests/helpers/sampleProjectReferences.ts @@ -1,17 +1,8 @@ import { dedent } from "../../_namespaces/Utils.js"; -import { FileSystem } from "../../_namespaces/vfs.js"; import { jsonToReadableText } from "../helpers.js"; -import { - FsContents, - getProjectConfigWithNodeNext, -} from "./contents.js"; -import { loadProjectFromFiles } from "./vfs.js"; -import { - createServerHost, - createWatchedSystem, - libFile, - TestServerHost, -} from "./virtualFileSystemWithWatch.js"; +import { getProjectConfigWithNodeNext } from "./contents.js"; +import { solutionBuildWithBaseline } from "./solutionBuilder.js"; +import { TestServerHost } from "./virtualFileSystemWithWatch.js"; export function getFsContentsForSampleProjectReferencesLogicConfig(withNodeNext?: boolean): string { return jsonToReadableText({ @@ -28,9 +19,13 @@ export function getFsContentsForSampleProjectReferencesLogicConfig(withNodeNext? ], }); } -export function getFsContentsForSampleProjectReferences(withNodeNext?: boolean): FsContents { - return { - [libFile.path]: libFile.content, + +export function getSysForSampleProjectReferences( + withNodeNext?: boolean, + skipReferenceCoreFromTest?: boolean, + forTsserver?: boolean, +): TestServerHost { + return TestServerHost.getCreateWatchedSystem(forTsserver)({ "/user/username/projects/sample1/core/tsconfig.json": jsonToReadableText({ compilerOptions: { ...getProjectConfigWithNodeNext(withNodeNext), @@ -57,10 +52,14 @@ export function getFsContentsForSampleProjectReferences(withNodeNext?: boolean): export const m = mod; `, "/user/username/projects/sample1/tests/tsconfig.json": jsonToReadableText({ - references: [ - { path: "../core" }, - { path: "../logic" }, - ], + references: !skipReferenceCoreFromTest ? + [ + { path: "../core" }, + { path: "../logic" }, + ] : + [ + { path: "../logic" }, + ], files: ["index.ts"], compilerOptions: { ...getProjectConfigWithNodeNext(withNodeNext), @@ -80,33 +79,12 @@ export function getFsContentsForSampleProjectReferences(withNodeNext?: boolean): import * as mod from '../core/anotherModule'; export const m = mod; `, - }; -} - -export function getFsForSampleProjectReferences(): FileSystem { - return loadProjectFromFiles( - getFsContentsForSampleProjectReferences(), - { - cwd: "/user/username/projects/sample1", - executingFilePath: libFile.path, - }, - ); + }, { currentDirectory: "/user/username/projects/sample1" }); } -export function getSysForSampleProjectReferences(withNodeNext?: boolean): TestServerHost { - return createWatchedSystem( - getFsContentsForSampleProjectReferences(withNodeNext), - { - currentDirectory: "/user/username/projects/sample1", - }, - ); -} - -export function getServerHostForSampleProjectReferences(): TestServerHost { - return createServerHost( - getFsContentsForSampleProjectReferences(), - { - currentDirectory: "/user/username/projects/sample1", - }, +export function getSysForSampleProjectReferencesBuilt(withNodeNext?: boolean): TestServerHost { + return solutionBuildWithBaseline( + getSysForSampleProjectReferences(withNodeNext), + ["tests"], ); } diff --git a/src/testRunner/unittests/helpers/solutionBuilder.ts b/src/testRunner/unittests/helpers/solutionBuilder.ts index fd09c5293ade9..5e4d32a990514 100644 --- a/src/testRunner/unittests/helpers/solutionBuilder.ts +++ b/src/testRunner/unittests/helpers/solutionBuilder.ts @@ -1,31 +1,48 @@ -import * as fakes from "../../_namespaces/fakes.js"; import * as ts from "../../_namespaces/ts.js"; import { jsonToReadableText } from "../helpers.js"; -import { commandLineCallbacks } from "./baseline.js"; import { - makeSystemReadyForBaseline, - TscCompileSystem, + CommandLineCallbacks, + commandLineCallbacks, + patchHostForBuildInfoReadWrite, + patchHostForBuildInfoWrite, + TscWatchSystem, +} from "./baseline.js"; +import { + verifyTsc, + VerifyTscWithEditsInput, } from "./tsc.js"; import { changeToHostTrackingWrittenFiles, TestServerHost, } from "./virtualFileSystemWithWatch.js"; +export type SolutionBuilderHostWithGetPrograms = + & ts.SolutionBuilderHost + & { getPrograms: CommandLineCallbacks["getPrograms"]; }; export function createSolutionBuilderHostForBaseline( - sys: TscCompileSystem | TestServerHost, - versionToWrite?: string, - originalRead?: (TscCompileSystem | TestServerHost)["readFile"], -): ts.SolutionBuilderHost { - 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)); + sys: TscWatchSystem, + originalRead?: TestServerHost["readFile"], +): ts.SolutionBuilderHost & { getPrograms: CommandLineCallbacks["getPrograms"]; } { + const { cb, getPrograms } = commandLineCallbacks(sys, originalRead); + const host = ts.createSolutionBuilderHost( + sys, + /*createProgram*/ undefined, + ts.createDiagnosticReporter(sys, /*pretty*/ true), + ts.createBuilderStatusReporter(sys, /*pretty*/ true), + ) as SolutionBuilderHostWithGetPrograms; host.afterProgramEmitAndDiagnostics = cb; + host.getPrograms = getPrograms; return host; } -export function createSolutionBuilder(system: TestServerHost, rootNames: readonly string[], originalRead?: TestServerHost["readFile"]): ts.SolutionBuilder { - const host = createSolutionBuilderHostForBaseline(system, /*versionToWrite*/ undefined, originalRead); - return ts.createSolutionBuilder(host, rootNames, {}); +export function createSolutionBuilder( + system: TscWatchSystem, + rootNames: readonly string[], + buildOptions?: ts.BuildOptions, + originalRead?: TestServerHost["readFile"], +): ts.SolutionBuilder { + const host = createSolutionBuilderHostForBaseline(system, originalRead); + return ts.createSolutionBuilder(host, rootNames, buildOptions ?? {}); } export function ensureErrorFreeBuild(host: TestServerHost, rootNames: readonly string[]): void { @@ -34,16 +51,25 @@ export function ensureErrorFreeBuild(host: TestServerHost, rootNames: readonly s assert.equal(host.getOutput().length, 0, jsonToReadableText(host.getOutput())); } -export function solutionBuildWithBaseline(sys: TestServerHost, solutionRoots: readonly string[], originalRead?: TestServerHost["readFile"]): TestServerHost { +export function solutionBuildWithBaseline( + sys: TestServerHost, + solutionRoots: readonly string[], + buildOptions?: ts.BuildOptions, + versionToWrite?: string, + originalRead?: TestServerHost["readFile"], +): TestServerHost { if (sys.writtenFiles === undefined) { const originalReadFile = sys.readFile; const originalWrite = sys.write; const originalWriteFile = sys.writeFile; const solutionBuilder = createSolutionBuilder( changeToHostTrackingWrittenFiles( - fakes.patchHostForBuildInfoReadWrite(sys), + versionToWrite ? + patchHostForBuildInfoWrite(sys, versionToWrite) : + patchHostForBuildInfoReadWrite(sys), ), solutionRoots, + buildOptions, originalRead, ); solutionBuilder.build(); @@ -51,11 +77,41 @@ export function solutionBuildWithBaseline(sys: TestServerHost, solutionRoots: re sys.write = originalWrite; sys.writeFile = originalWriteFile; sys.writtenFiles = undefined; + sys.clearOutput(); return sys; } else { - const solutionBuilder = createSolutionBuilder(sys, solutionRoots); + const solutionBuilder = createSolutionBuilder(sys as TscWatchSystem, solutionRoots, buildOptions, originalRead); solutionBuilder.build(); return sys; } } + +export function verifySolutionBuilderWithDifferentTsVersion(input: VerifyTscWithEditsInput, rootNames: readonly string[]): void { + describe(input.subScenario, () => { + let originalReadFile: TscWatchSystem["readFile"]; + let originalWriteFile: TscWatchSystem["writeFile"]; + verifyTsc({ + ...input, + sys: () => { + const sys = input.sys(); + originalReadFile = sys.readFile; + originalWriteFile = sys.writeFile; + return sys; + }, + compile: sys => { + sys.readFile = originalReadFile; + sys.writeFile = originalWriteFile; + originalReadFile = undefined!; + originalWriteFile = undefined!; + sys.writtenFiles = undefined!; + // Buildinfo will have version which does not match with current ts version + changeToHostTrackingWrittenFiles(patchHostForBuildInfoWrite(sys, "FakeTSCurrentVersion")); + const buildHost = createSolutionBuilderHostForBaseline(sys); + const builder = ts.createSolutionBuilder(buildHost, rootNames, { verbose: true }); + sys.exit(builder.build()); + return buildHost.getPrograms; + }, + }); + }); +} diff --git a/src/testRunner/unittests/helpers/tsc.ts b/src/testRunner/unittests/helpers/tsc.ts index a41a10fb5a96c..85cc75125190c 100644 --- a/src/testRunner/unittests/helpers/tsc.ts +++ b/src/testRunner/unittests/helpers/tsc.ts @@ -1,33 +1,32 @@ -import * as fakes from "../../_namespaces/fakes.js"; -import * as Harness from "../../_namespaces/Harness.js"; +import { Baseline } from "../../_namespaces/Harness.js"; import * as ts from "../../_namespaces/ts.js"; -import * as vfs from "../../_namespaces/vfs.js"; import { jsonToReadableText } from "../helpers.js"; import { - baselinePrograms, + applyEdit, + baselineAfterTscCompile as baseline_baselineAfterTscCompile, + BaselineBase, CommandLineCallbacks, commandLineCallbacks, CommandLineProgram, - generateSourceMapBaselineFiles, + createBaseline, isReadableIncrementalBuildInfo, isReadableIncrementalBundleEmitBuildInfo, isReadableIncrementalMultiFileEmitBuildInfo, + isWatch, ReadableBuildInfo, ReadableIncrementalBuildInfo, ReadableIncrementalBuildInfoFileInfo, ReadableIncrementalBundleEmitBuildInfo, ReadableIncrementalMultiFileEmitBuildInfo, - sanitizeSysOutput, toPathWithSystem, tscBaselineName, + TscWatchSystem, } from "./baseline.js"; - -export type TscCompileSystem = fakes.System & { - writtenFiles: Set; - baseLine(): { file: string; text: string; }; - dtsSignaures?: Map>; - storeSignatureInfo?: boolean; -}; +import { + isFsFile, + TestServerHost, + TestServerHostSnapshot, +} from "./virtualFileSystemWithWatch.js"; export const noChangeRun: TestTscEdit = { caption: "no-change-run", @@ -35,106 +34,40 @@ export const noChangeRun: TestTscEdit = { }; export const noChangeOnlyRuns: TestTscEdit[] = [noChangeRun]; -export interface TestTscCompile extends TestTscCompileLikeBase { +export interface TestTscCompile { + commandLineArgs: readonly string[]; + sys: () => TestServerHost; + modifySystem?: (fs: TestServerHost) => void; + computeDtsSignatures?: boolean; + getWrittenFiles?: boolean; baselineSourceMap?: boolean; baselineReadFileCalls?: boolean; baselinePrograms?: boolean; baselineDependencies?: boolean; + compile?: (sys: TscWatchSystem) => CommandLineCallbacks["getPrograms"]; } -export interface TestTscCompileLikeBase extends VerifyTscCompileLike { - diffWithInitial?: boolean; - modifyFs?: (fs: vfs.FileSystem) => void; - computeDtsSignatures?: boolean; - environmentVariables?: Record; -} - -export interface TestTscCompileLike extends TestTscCompileLikeBase { - compile: (sys: TscCompileSystem) => void; - additionalBaseline?: (sys: TscCompileSystem) => void; -} /** - * Initialize FS, run compile function and save baseline + * Initialize Fs, execute command line and save baseline */ -export function testTscCompileLike(input: TestTscCompileLike): TscCompileSystem { - const initialFs = input.fs(); - const inputFs = initialFs.shadow(); - const { - scenario, - subScenario, - diffWithInitial, - commandLineArgs, - modifyFs, - environmentVariables, - compile: worker, - additionalBaseline, - } = input; - if (modifyFs) modifyFs(inputFs); - inputFs.makeReadonly(); - const fs = inputFs.shadow(); - - // Create system - const sys = new fakes.System(fs, { executingFilePath: `${fs.meta.get("defaultLibLocation")}/tsc`, env: environmentVariables }) as TscCompileSystem; - sys.storeSignatureInfo = true; - sys.write(`${sys.getExecutingFilePath()} ${commandLineArgs.join(" ")}\n`); +function initialTestTscCompile(input: TestTscCompile) { + const { sys, baseline } = createBaseline(input.sys(), input.modifySystem); sys.exit = exitCode => sys.exitCode = exitCode; - worker(sys); - sys.write(`exitCode:: ExitStatus.${ts.ExitStatus[sys.exitCode as ts.ExitStatus]}\n`); - additionalBaseline?.(sys); - fs.makeReadonly(); - sys.baseLine = () => { - 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), - text: `Input:: -${baseFsPatch ? vfs.formatPatch(baseFsPatch) : ""} - -Output:: -${sys.output.map(sanitizeSysOutput).join("")} - -${patch ? vfs.formatPatch(patch) : ""}`, - }; - }; - return sys; -} - -export function makeSystemReadyForBaseline(sys: TscCompileSystem, versionToWrite?: string): void { - if (versionToWrite) { - fakes.patchHostForBuildInfoWrite(sys, versionToWrite); - } - else { - fakes.patchHostForBuildInfoReadWrite(sys); - } - const writtenFiles = sys.writtenFiles = new Set(); - const originalWriteFile = sys.writeFile; - sys.writeFile = (fileName, content, writeByteOrderMark) => { - const path = toPathWithSystem(sys, fileName); - // When buildinfo is same for two projects, - // it gives error and doesnt write buildinfo but because buildInfo is written for one project, - // readable baseline will be written two times for those two projects with same contents and is ok - ts.Debug.assert(!writtenFiles.has(path) || ts.endsWith(path, "baseline.txt")); - writtenFiles.add(path); - return originalWriteFile.call(sys, fileName, content, writeByteOrderMark); - }; + ts.Debug.assert(!isWatch(input.commandLineArgs), "use verifyTscWatch"); + return testTscCompileWith(sys, baseline, input); } /** - * Initialize Fs, execute command line and save baseline + * execute command line and save baseline */ -export function testTscCompile(input: TestTscCompile): TscCompileSystem { +function testTscCompileWith( + sys: BaselineBase["sys"], + baseline: BaselineBase["baseline"], + input: TestTscCompileBaselineInput & Pick, +) { let actualReadFileMap: ts.MapLike | undefined; let getPrograms: CommandLineCallbacks["getPrograms"] | undefined; - return testTscCompileLike({ - ...input, - compile: commandLineCompile, - additionalBaseline, - }); - - function commandLineCompile(sys: TscCompileSystem) { - makeSystemReadyForBaseline(sys); + if (!input.compile) { actualReadFileMap = {}; const originalReadFile = sys.readFile; if (input.baselineReadFileCalls) { @@ -146,7 +79,6 @@ export function testTscCompile(input: TestTscCompile): TscCompileSystem { return originalReadFile.call(sys, path); }; } - const result = commandLineCallbacks(sys, originalReadFile); ts.executeCommandLine( sys, @@ -156,33 +88,57 @@ export function testTscCompile(input: TestTscCompile): TscCompileSystem { sys.readFile = originalReadFile; getPrograms = result.getPrograms; } - - function additionalBaseline(sys: TscCompileSystem) { - const { baselineSourceMap, baselineReadFileCalls, baselinePrograms: shouldBaselinePrograms, baselineDependencies } = input; - const programs = getPrograms!(); - if (input.computeDtsSignatures) storeDtsSignatures(sys, programs); - if (shouldBaselinePrograms) { - const baseline: string[] = []; - baselinePrograms(baseline, programs, ts.emptyArray, baselineDependencies); - sys.write(baseline.join("\n")); - } - if (baselineReadFileCalls) { - sys.write(`readFiles:: ${jsonToReadableText(actualReadFileMap)} `); - } - if (baselineSourceMap) generateSourceMapBaselineFiles(sys); - actualReadFileMap = undefined; - getPrograms = undefined; + else { + getPrograms = input.compile(sys); + } + const { dtsSignatures, writtenFiles } = baselineAfterTscCompile(sys, baseline, input, getPrograms, actualReadFileMap); + return { sys, baseline, dtsSignatures, writtenFiles }; +} +type TestTscCompileBaselineInput = Pick< + TestTscCompile, + | "commandLineArgs" + | "computeDtsSignatures" + | "getWrittenFiles" + | "baselineSourceMap" + | "baselineReadFileCalls" + | "baselinePrograms" + | "baselineDependencies" +>; +function baselineAfterTscCompile( + sys: BaselineBase["sys"], + baseline: BaselineBase["baseline"], + input: TestTscCompileBaselineInput, + getPrograms: () => readonly CommandLineProgram[], + actualReadFileMap: ts.MapLike | undefined, +) { + baseline.push(`${sys.getExecutingFilePath()} ${input.commandLineArgs.join(" ")}`); + const writtenFiles = input.getWrittenFiles ? new Set(sys.writtenFiles.keys()) : undefined; + const programs = baseline_baselineAfterTscCompile( + sys, + baseline, + getPrograms, + ts.emptyArray, + input.baselineSourceMap, + input.baselinePrograms, + input.baselineDependencies, + ); + const dtsSignatures = input.computeDtsSignatures ? storeDtsSignatures(sys, programs) : undefined; + if (input.baselineReadFileCalls) { + baseline.push(`readFiles:: ${jsonToReadableText(actualReadFileMap)} `); } + actualReadFileMap = undefined; + return { dtsSignatures, writtenFiles }; } -function storeDtsSignatures(sys: TscCompileSystem, programs: readonly CommandLineProgram[]) { +function storeDtsSignatures(sys: TscWatchSystem, programs: readonly CommandLineProgram[]) { + let dtsSignatures: Map> | undefined; for (const [program, builderProgram] of programs) { if (!builderProgram) continue; const buildInfoPath = ts.getTsBuildInfoEmitOutputFilePath(program.getCompilerOptions()); if (!buildInfoPath) continue; - sys.dtsSignaures ??= new Map(); + dtsSignatures ??= new Map(); const dtsSignatureData = new Map(); - sys.dtsSignaures.set(`${toPathWithSystem(sys, buildInfoPath)}.readable.baseline.txt` as ts.Path, dtsSignatureData); + dtsSignatures.set(`${toPathWithSystem(sys, buildInfoPath)}.readable.baseline.txt` as ts.Path, dtsSignatureData); builderProgram.state.hasCalledUpdateShapeSignature?.forEach(resolvedPath => { const file = program.getSourceFileByPath(resolvedPath); if (!file || file.isDeclarationFile) return; @@ -203,84 +159,36 @@ function storeDtsSignatures(sys: TscCompileSystem, programs: readonly CommandLin return ts.ensurePathIsNonModuleName(ts.getRelativePathFromDirectory(buildInfoDirectory, path, getCanonicalFileName)); } } + return dtsSignatures; } -export function verifyTscBaseline(sys: () => { baseLine: TscCompileSystem["baseLine"]; }): void { - it(`Generates files matching the baseline`, () => { - const { file, text } = sys().baseLine(); - Harness.Baseline.runBaseline(file, text); - }); -} -export interface VerifyTscCompileLike { - scenario: string; - subScenario: string; - commandLineArgs: readonly string[]; - fs: () => vfs.FileSystem; -} - -/** - * Verify by baselining after initializing FS and custom compile - */ -export function verifyTscCompileLike(verifier: (input: T) => { baseLine: TscCompileSystem["baseLine"]; }, input: T): void { - describe(`tsc ${input.commandLineArgs.join(" ")} ${input.scenario}:: ${input.subScenario}`, () => { - describe(input.scenario, () => { - describe(input.subScenario, () => { - verifyTscBaseline(() => - verifier({ - ...input, - fs: () => input.fs().makeReadonly(), - }) - ); - }); - }); - }); -} - -interface VerifyTscEditDiscrepanciesInput { - index: number; - edits: readonly TestTscEdit[]; - scenario: TestTscCompile["scenario"]; - baselines: string[] | undefined; - commandLineArgs: TestTscCompile["commandLineArgs"]; - modifyFs: TestTscCompile["modifyFs"]; - baseFs: vfs.FileSystem; - newSys: TscCompileSystem; - environmentVariables: TestTscCompile["environmentVariables"]; -} -function verifyTscEditDiscrepancies({ - index, - edits, - scenario, - commandLineArgs, - environmentVariables, - baselines, - modifyFs, - baseFs, - newSys, -}: VerifyTscEditDiscrepanciesInput): string[] | undefined { - const { caption, discrepancyExplanation } = edits[index]; - const sys = testTscCompile({ - scenario, - subScenario: caption, - fs: () => baseFs.makeReadonly(), - commandLineArgs: edits[index].commandLineArgs || commandLineArgs, - modifyFs: fs => { - if (modifyFs) modifyFs(fs); +function verifyTscEditDiscrepancies( + input: VerifyTscWithEditsInput, + index: number, + snaps: readonly TestServerHostSnapshot[], + baselines: string[] | undefined, +): string[] | undefined { + const result = initialTestTscCompile({ + ...input, + modifySystem: fs => { + input.modifySystem?.(fs); for (let i = 0; i <= index; i++) { - edits[i].edit(fs); + input.edits![i].edit(fs as TscWatchSystem); } }, - environmentVariables, + commandLineArgs: input.edits![index].commandLineArgs ?? input.commandLineArgs, computeDtsSignatures: true, + getWrittenFiles: true, }); let headerAdded = false; - for (const outputFile of sys.writtenFiles.keys()) { - const cleanBuildText = sys.readFile(outputFile); - const incrementalBuildText = newSys.readFile(outputFile); + for (const outputFile of result.writtenFiles!.keys()) { + const cleanBuildText = result.sys.readFile(outputFile); + const incrementalFsEntry = snaps[index].get(outputFile); + const incrementalBuildText = isFsFile(incrementalFsEntry) ? incrementalFsEntry.content : undefined; 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}`); + if (!result.sys.fileExists(`${outputFile}.readable.baseline.txt`)) addBaseline(`Readable baseline not present in clean build:: File:: ${outputFile}`); + if (!isFsFile(snaps[index].get(`${outputFile}.readable.baseline.txt` as ts.Path))) 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")) { @@ -290,14 +198,14 @@ function verifyTscEditDiscrepancies({ // Verify build info without affectedFilesPendingEmit const { buildInfo: incrementalBuildInfo, readableBuildInfo: incrementalReadableBuildInfo } = getBuildInfoForIncrementalCorrectnessCheck(incrementalBuildText); const { buildInfo: cleanBuildInfo, readableBuildInfo: cleanReadableBuildInfo } = getBuildInfoForIncrementalCorrectnessCheck(cleanBuildText); - const dtsSignaures = sys.dtsSignaures?.get(outputFile); + const dtsSignatures = result.dtsSignatures?.get(outputFile); verifyTextEqual(incrementalBuildInfo, cleanBuildInfo, `TsBuild info text without affectedFilesPendingEmit:: ${outputFile}::`); // Verify file info sigantures verifyMapLike( (incrementalReadableBuildInfo as ReadableIncrementalMultiFileEmitBuildInfo)?.fileInfos, (cleanReadableBuildInfo as ReadableIncrementalMultiFileEmitBuildInfo)?.fileInfos, (key, incrementalFileInfo, cleanFileInfo) => { - const dtsForKey = dtsSignaures?.get(key); + const dtsForKey = dtsSignatures?.get(key); if ( !incrementalFileInfo || !cleanFileInfo || @@ -436,7 +344,7 @@ function verifyTscEditDiscrepancies({ }); } } - if (!headerAdded && discrepancyExplanation) addBaseline("*** Supplied discrepancy explanation but didnt find any difference"); + if (!headerAdded && input.edits![index].discrepancyExplanation) addBaseline("*** Supplied discrepancy explanation but didnt find any difference"); return baselines; function verifyTextEqual(incrementalText: string | undefined, cleanText: string | undefined, message: string) { @@ -487,7 +395,7 @@ function verifyTscEditDiscrepancies({ function addBaseline(...text: string[]) { if (!baselines || !headerAdded) { - (baselines ||= []).push(`${index}:: ${caption}`, ...(discrepancyExplanation?.() || ["*** Needs explanation"])); + (baselines ||= []).push(`${index}:: ${input.edits![index].caption}`, ...(input.edits![index].discrepancyExplanation?.() || ["*** Needs explanation"])); headerAdded = true; } baselines.push(...text); @@ -537,107 +445,56 @@ function getBuildInfoForIncrementalCorrectnessCheck(text: string | undefined): { } export interface TestTscEdit { - edit: (fs: vfs.FileSystem) => void; + edit: (sys: TscWatchSystem) => void; caption: string; commandLineArgs?: readonly string[]; /** An array of lines to be printed in order when a discrepancy is detected */ discrepancyExplanation?: () => readonly string[]; } -export interface VerifyTscWithEditsInput extends TestTscCompile { +export interface VerifyTscWithEditsInput extends Omit { + scenario: string; + subScenario: string; edits?: readonly TestTscEdit[]; } /** * Verify non watch tsc invokcation after each edit */ -export function verifyTsc({ - subScenario, - fs, - scenario, - commandLineArgs, - environmentVariables, - baselineSourceMap, - modifyFs, - baselineReadFileCalls, - baselinePrograms, - edits, -}: VerifyTscWithEditsInput): void { - describe(`tsc ${commandLineArgs.join(" ")} ${scenario}:: ${subScenario}`, () => { - let sys: TscCompileSystem; - let baseFs: vfs.FileSystem; - let editsSys: TscCompileSystem[] | undefined; - before(() => { - baseFs = fs().makeReadonly(); - sys = testTscCompile({ - scenario, - subScenario, - fs: () => baseFs, - commandLineArgs, - modifyFs, - baselineSourceMap, - baselineReadFileCalls, - baselinePrograms, - environmentVariables, - }); - edits?.forEach(( - { edit, caption, commandLineArgs: editCommandLineArgs }, - index, - ) => { - (editsSys || (editsSys = [])).push(testTscCompile({ - scenario, - subScenario: caption, - diffWithInitial: true, - fs: () => index === 0 ? sys.vfs : editsSys![index - 1].vfs, - commandLineArgs: editCommandLineArgs || commandLineArgs, - modifyFs: edit, - baselineSourceMap, - baselineReadFileCalls, - baselinePrograms, - environmentVariables, - })); - }); - }); +export function verifyTsc(input: VerifyTscWithEditsInput): void { + describe(`tsc ${input.commandLineArgs.join(" ")} ${input.scenario}:: ${input.subScenario}`, () => { + let snaps: TestServerHostSnapshot[] | undefined; after(() => { - baseFs = undefined!; - sys = undefined!; - editsSys = undefined!; + snaps = undefined; }); - verifyTscBaseline(() => ({ - baseLine: () => { - const { file, text } = sys.baseLine(); - const texts: string[] = [text]; - editsSys?.forEach((sys, index) => { - const incrementalScenario = edits![index]; - texts.push(""); - texts.push(`Change:: ${incrementalScenario.caption}`); - texts.push(sys.baseLine().text); + it("baseline for the tsc compiles", () => { + const { sys, baseline } = initialTestTscCompile(input); + input.edits?.forEach(edit => { + applyEdit(sys, baseline, edit.edit, edit.caption); + testTscCompileWith(sys, baseline, { + ...input, + commandLineArgs: edit.commandLineArgs ?? input.commandLineArgs, }); - return { - file, - text: `currentDirectory:: ${sys.getCurrentDirectory()} useCaseSensitiveFileNames: ${sys.useCaseSensitiveFileNames}\r\n` + - texts.join("\r\n"), - }; - }, - })); - if (edits?.length) { + (snaps ??= []).push(sys.getSnap()); + }); + Baseline.runBaseline( + tscBaselineName(input.scenario, input.subScenario, input.commandLineArgs), + baseline.join("\r\n"), + ); + }); + if (input.edits?.length) { it("tsc invocation after edit and clean build correctness", () => { let baselines: string[] | undefined; - for (let index = 0; index < edits.length; index++) { - baselines = verifyTscEditDiscrepancies({ + for (let index = 0; index < input.edits!.length; index++) { + baselines = verifyTscEditDiscrepancies( + input, index, - edits, - scenario, + snaps!, baselines, - baseFs, - newSys: editsSys![index], - commandLineArgs, - modifyFs, - environmentVariables, - }); + ); } - Harness.Baseline.runBaseline( - tscBaselineName(scenario, subScenario, commandLineArgs, /*isWatch*/ undefined, "-discrepancies"), + Baseline.runBaseline( + tscBaselineName(input.scenario, input.subScenario, input.commandLineArgs, "-discrepancies"), baselines ? baselines.join("\r\n") : null, // eslint-disable-line no-restricted-syntax ); }); diff --git a/src/testRunner/unittests/helpers/tscWatch.ts b/src/testRunner/unittests/helpers/tscWatch.ts index 6d3475f3e7489..2e6dbc2b8c970 100644 --- a/src/testRunner/unittests/helpers/tscWatch.ts +++ b/src/testRunner/unittests/helpers/tscWatch.ts @@ -80,7 +80,7 @@ function tscWatchCompile(input: TscWatchCompile) { }); } -export function createSolutionBuilderWithWatchHostForBaseline(sys: TestServerHost, cb: ts.ExecuteCommandLineCallbacks) { +export function createSolutionBuilderWithWatchHostForBaseline(sys: TestServerHost, cb: ts.ExecuteCommandLineCallbacks): ts.SolutionBuilderWithWatchHost { 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; return host; @@ -194,7 +194,7 @@ export function watchBaseline({ caption, resolutionCache, useSourceOfProjectReferenceRedirect, -}: WatchBaseline) { +}: WatchBaseline): readonly CommandLineProgram[] { const programs = baselineAfterTscCompile( sys, baseline, diff --git a/src/testRunner/unittests/helpers/tsserver.ts b/src/testRunner/unittests/helpers/tsserver.ts index 52af244683990..a2a49e953178e 100644 --- a/src/testRunner/unittests/helpers/tsserver.ts +++ b/src/testRunner/unittests/helpers/tsserver.ts @@ -25,7 +25,7 @@ import { TestServerHostTrackingWrittenFiles, } from "./virtualFileSystemWithWatch.js"; -export function baselineTsserverLogs(scenario: string, subScenario: string, sessionOrService: { logger: LoggerWithInMemoryLogs; }) { +export function baselineTsserverLogs(scenario: string, subScenario: string, sessionOrService: { logger: LoggerWithInMemoryLogs; }): void { Baseline.runBaseline(`tsserver/${scenario}/${subScenario.split(" ").join("-")}.js`, sessionOrService.logger.logs.join("\r\n")); } @@ -625,7 +625,7 @@ export function verifyGetErrScenario(scenario: VerifyGetErrScenario): void { verifyErrorsUsingSyncMethods(scenario); } -export function createHostWithSolutionBuild(files: readonly FileOrFolderOrSymLink[], rootNames: readonly string[]) { +export function createHostWithSolutionBuild(files: readonly FileOrFolderOrSymLink[], rootNames: readonly string[]): TestServerHost { const host = TestServerHost.createServerHost(files); // ts build should succeed ensureErrorFreeBuild(host, rootNames); diff --git a/src/testRunner/unittests/helpers/virtualFileSystemWithWatch.ts b/src/testRunner/unittests/helpers/virtualFileSystemWithWatch.ts index a618ce776a665..525be1383f17e 100644 --- a/src/testRunner/unittests/helpers/virtualFileSystemWithWatch.ts +++ b/src/testRunner/unittests/helpers/virtualFileSystemWithWatch.ts @@ -1,5 +1,11 @@ +import { + harnessSessionCurrentDirectory, + harnessTypingInstallerCacheLocation, +} from "../../../harness/harnessLanguageService.js"; +import { replaceAll } from "../../../harness/tsserverLogger.js"; import { createWatchUtils, + ensureWatchablePath, Watches, WatchUtils, } from "../../../harness/watchUtils.js"; @@ -18,6 +24,7 @@ import { createSystemWatchFunctions, Debug, directorySeparator, + emptyArray, FileSystemEntryKind, FileWatcherCallback, FileWatcherEventKind, @@ -36,6 +43,7 @@ import { insertSorted, isArray, isString, + libMap, mapDefined, matchFiles, ModuleImportResult, @@ -47,14 +55,23 @@ import { server, SortedArray, sys, + targetToLibMap, toPath, } from "../../_namespaces/ts.js"; import { typingsInstaller } from "../../_namespaces/ts.server.js"; import { timeIncrements } from "../../_namespaces/vfs.js"; -import { sanitizeSysOutput } from "./baseline.js"; +import { jsonToReadableText } from "../helpers.js"; +import { + getPathForTypeScriptTestLocation, + tscTypeScriptTestLocation, +} from "./contents.js"; +import { + createTypesRegistryFileContent, + getTypesRegistryFileLocation, +} from "./typingsInstaller.js"; export const libFile: File = { - path: "/a/lib/lib.d.ts", + path: getPathForTypeScriptTestLocation("lib.d.ts"), content: `/// interface Boolean {} interface Function {} @@ -65,13 +82,11 @@ interface Number { toExponential: any; } interface Object {} interface RegExp {} interface String { charAt: any; } -interface Array { length: number; [n: number]: T; }`, +interface Array { length: number; [n: number]: T; } +interface ReadonlyArray {} +declare const console: { log(msg: any): void; };`, }; -function getExecutingFilePathFromLibFile(): string { - return combinePaths(getDirectoryPath(libFile.path), "tsc.js"); -} - export const enum TestServerHostOsFlavor { Windows, MacOs, @@ -87,45 +102,47 @@ export interface TestServerHostCreationParameters { environmentVariables?: Map; runWithFallbackPolling?: boolean; osFlavor?: TestServerHostOsFlavor; + typingsInstallerGlobalCacheLocation?: string; + typingsInstallerTypesRegistry?: string | readonly string[]; } -export function createWatchedSystem(fileOrFolderList: FileOrFolderOrSymLinkMap | readonly FileOrFolderOrSymLink[], params?: TestServerHostCreationParameters): TestServerHost { - return new TestServerHost(fileOrFolderList, params); +export interface WatchableExempt { + /** Add this field to true only if its the interesting scenario about what to watch */ + watchableExempt?: boolean; } -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); - return host; -} - -export interface File { +export interface File extends WatchableExempt { path: string; content: string; fileSize?: number; } -export interface Folder { +export interface Folder extends WatchableExempt { path: string; } -export interface SymLink { +export interface SymLink extends WatchableExempt { /** Location of the symlink. */ path: string; /** Relative path to the real file. */ symLink: string; } +export interface LibFile extends WatchableExempt { + path: string; + libFile: true; +} + export type FileOrFolderOrSymLink = File | Folder | SymLink; +export type FileOrFolderOrSymLinkOrLibFile = FileOrFolderOrSymLink | LibFile; export interface FileOrFolderOrSymLinkMap { [path: string]: string | Omit | Omit | undefined; } -export function isFile(fileOrFolderOrSymLink: FileOrFolderOrSymLink): fileOrFolderOrSymLink is File { - return isString((fileOrFolderOrSymLink as File).content); +export function isFile(fileOrFolderOrSymLink: FileOrFolderOrSymLinkOrLibFile): fileOrFolderOrSymLink is File | LibFile { + return isString((fileOrFolderOrSymLink as File).content) || (fileOrFolderOrSymLink as LibFile).libFile; } -export function isSymLink(fileOrFolderOrSymLink: FileOrFolderOrSymLink): fileOrFolderOrSymLink is SymLink { +export function isSymLink(fileOrFolderOrSymLink: FileOrFolderOrSymLinkOrLibFile): fileOrFolderOrSymLink is SymLink { return isString((fileOrFolderOrSymLink as SymLink).symLink); } @@ -140,6 +157,11 @@ interface FsFile extends FSEntryBase { fileSize?: number; } +interface FsLibFile extends FSEntryBase { + content?: string; + libFile: true; +} + interface FsFolder extends FSEntryBase { entries: SortedArray; } @@ -148,16 +170,29 @@ interface FsSymLink extends FSEntryBase { symLink: string; } -export type FSEntry = FsFile | FsFolder | FsSymLink; +export type FSEntry = FsFile | FsFolder | FsSymLink | FsLibFile; +export type FSFileOrLibFile = FsFile | FsLibFile; function isFsFolder(s: FSEntry | undefined): s is FsFolder { return !!s && isArray((s as FsFolder).entries); } -function isFsFile(s: FSEntry | undefined): s is FsFile { +function isFsFileOrFsLibFile(s: FSEntry | undefined) { + return isFsFile(s) || isFsLibFile(s); +} + +function isFsLibFile(s: FSEntry | undefined): s is FsLibFile { + return !!s && (s as FsLibFile).libFile; +} + +export function isFsFile(s: FSEntry | undefined): s is FsFile { return !!s && isString((s as FsFile).content); } +function getFsFileOrLibFileContent(entry: FSFileOrLibFile) { + return entry.content ?? (entry.content = libFile.content); +} + function isFsSymLink(s: FSEntry | undefined): s is FsSymLink { return !!s && isString((s as FsSymLink).symLink); } @@ -337,6 +372,28 @@ export enum SerializeOutputOrder { BeforeDiff, AfterDiff, } + +export type TestServerHostSnapshot = Map; + +export function cloneFsMap(fs: Map): TestServerHostSnapshot { + const snap = new Map(); + const clonedMap = new Map(); + const getCloned = (entry: FSEntry) => { + const existing = clonedMap.get(entry); + if (existing) return existing; + const cloned = clone(entry); + clonedMap.set(entry, cloned); + if (isFsFolder(cloned)) { + cloned.entries = cloned.entries.map(clone) as SortedArray; + } + return cloned; + }; + fs.forEach((value, key) => { + snap.set(key, getCloned(value)); + }); + return snap; +} + export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost, ModuleResolutionHost { args: string[] = []; @@ -369,7 +426,9 @@ export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost, service?: server.ProjectService; osFlavor: TestServerHostOsFlavor; preferNonRecursiveWatch: boolean; - constructor( + globalTypingsCacheLocation: string; + private readonly typesRegistry: string | readonly string[] | undefined; + private constructor( fileOrFolderorSymLinkList: FileOrFolderOrSymLinkMap | readonly FileOrFolderOrSymLink[], { useCaseSensitiveFileNames, @@ -380,6 +439,8 @@ export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost, environmentVariables, runWithFallbackPolling, osFlavor, + typingsInstallerGlobalCacheLocation, + typingsInstallerTypesRegistry, }: TestServerHostCreationParameters = {}, ) { this.useCaseSensitiveFileNames = !!useCaseSensitiveFileNames; @@ -387,12 +448,11 @@ export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost, this.osFlavor = osFlavor || TestServerHostOsFlavor.Windows; this.windowsStyleRoot = windowsStyleRoot; this.environmentVariables = environmentVariables; - currentDirectory = currentDirectory || "/"; + this.currentDirectory = this.getHostSpecificPath(currentDirectory ?? harnessSessionCurrentDirectory); this.getCanonicalFileName = createGetCanonicalFileName(!!useCaseSensitiveFileNames); this.watchUtils = createWatchUtils("PolledWatches", "FsWatches", s => this.getCanonicalFileName(s), this); - this.toPath = s => toPath(s, currentDirectory, this.getCanonicalFileName); - this.executingFilePath = this.getHostSpecificPath(executingFilePath || getExecutingFilePathFromLibFile()); - this.currentDirectory = this.getHostSpecificPath(currentDirectory); + this.toPath = s => toPath(s, this.currentDirectory, this.getCanonicalFileName); + this.executingFilePath = this.getHostSpecificPath(executingFilePath ?? tscTypeScriptTestLocation); this.runWithFallbackPolling = !!runWithFallbackPolling; const tscWatchFile = this.environmentVariables && this.environmentVariables.get("TSC_WATCHFILE"); const tscWatchDirectory = this.environmentVariables && this.environmentVariables.get("TSC_WATCHDIRECTORY"); @@ -424,6 +484,87 @@ export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost, this.watchFile = watchFile; this.watchDirectory = watchDirectory; this.reloadFS(fileOrFolderorSymLinkList); + + // Ensure current directory exists + this.ensureFileOrFolder({ path: this.currentDirectory }); + + // Ensure libs + this.ensureFileOrFolder({ + path: combinePaths(getDirectoryPath(this.executingFilePath), "lib.d.ts"), + content: libFile.content, + }); + targetToLibMap.forEach(libFile => this.ensureLib(libFile)); + libMap.forEach(libFile => this.ensureLib(libFile)); + + // Ensure global cache location has required data + this.globalTypingsCacheLocation = this.getHostSpecificPath( + typingsInstallerGlobalCacheLocation ?? + harnessTypingInstallerCacheLocation, + ); + this.typesRegistry = typingsInstallerTypesRegistry; + if (this.directoryExists(this.globalTypingsCacheLocation)) { + // Package.json + const npmConfigPath = combinePaths(this.globalTypingsCacheLocation, "package.json"); + if (!this.fileExists(npmConfigPath)) { + this.writeFile(npmConfigPath, '{ "private": true }'); + } + // Typings registry + this.ensureTypingRegistryFile(); + } + } + + private ensureLib(path: string) { + this.ensureFileOrFolder({ + path: combinePaths(getDirectoryPath(this.executingFilePath), path), + libFile: true, + }); + } + + ensureTypingRegistryFile(): void { + this.ensureFileOrFolder({ + path: getTypesRegistryFileLocation(this.globalTypingsCacheLocation), + content: jsonToReadableText(createTypesRegistryFileContent( + this.typesRegistry ? + isString(this.typesRegistry) ? + [this.typesRegistry] : + this.typesRegistry : + emptyArray, + )), + }); + } + + static createWatchedSystem( + fileOrFolderList: FileOrFolderOrSymLinkMap | readonly FileOrFolderOrSymLink[], + params?: Omit, + ): TestServerHost { + const useDefaultCurrentDirectory = !params?.currentDirectory; + if (useDefaultCurrentDirectory) (params ??= {}).currentDirectory = "/home/src/workspaces/project"; + else ensureWatchablePath(params!.currentDirectory!, `currentDirectory: ${params!.currentDirectory}`); + const host = new TestServerHost(fileOrFolderList, params); + if (useDefaultCurrentDirectory && fileOrFolderList !== emptyArray) { + const folder = host.getRealFolder(host.toPath(host.currentDirectory))!; + Debug.assert( + folder.entries.length, + `currentDirectory: Not specified, using default as "/home/src/workspaces/project". The files specified do not belong to it.`, + ); + } + return host; + } + + static createServerHost( + fileOrFolderList: FileOrFolderOrSymLinkMap | readonly FileOrFolderOrSymLink[], + params?: Omit & { overrideCurrentDirectory?: string; }, + ): TestServerHost { + if ((params as TestServerHostCreationParameters)?.currentDirectory) (params as TestServerHostCreationParameters).currentDirectory = undefined; + if (params) (params as TestServerHostCreationParameters).currentDirectory = params?.overrideCurrentDirectory; + const host = new TestServerHost(fileOrFolderList, params); + // Just like sys, patch the host to use writeFile + patchWriteFileEnsuringDirectory(host); + return host; + } + + static getCreateWatchedSystem(forTsserver: boolean | undefined): typeof TestServerHost.createWatchedSystem | typeof TestServerHost.createServerHost { + return (!forTsserver ? TestServerHost.createWatchedSystem : TestServerHost.createServerHost); } private nextInode = 0; @@ -449,8 +590,13 @@ export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost, } getHostSpecificPath(s: string): string { - if (this.windowsStyleRoot && s.startsWith(directorySeparator)) { - return this.windowsStyleRoot + s.substring(1); + if (this.windowsStyleRoot) { + let result = s; + if (s.startsWith(directorySeparator)) { + result = this.windowsStyleRoot + s.substring(1); + } + if (!result.startsWith(directorySeparator)) result = replaceAll(result, directorySeparator, "\\"); + return result; } return s; } @@ -479,11 +625,16 @@ export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost, this.pendingInstalls.switchToBaseliningInvoke(logger, serializeOutputOrder); } + private ensureInitialFileOrFolder(f: FileOrFolderOrSymLink) { + if (!f.watchableExempt) ensureWatchablePath(getDirectoryPath(f.path), `Directory path of FileOrFolderOrSymLink: ${f.path}`); + this.ensureFileOrFolder(f); + } + private reloadFS(fileOrFolderOrSymLinkList: FileOrFolderOrSymLinkMap | readonly FileOrFolderOrSymLink[]) { Debug.assert(this.fs.size === 0); if (isArray(fileOrFolderOrSymLinkList)) { fileOrFolderOrSymLinkList.forEach(f => - this.ensureFileOrFolder( + this.ensureInitialFileOrFolder( !this.windowsStyleRoot ? f : { ...f, path: this.getHostSpecificPath(f.path) }, @@ -496,10 +647,10 @@ export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost, const path = this.getHostSpecificPath(key); const value = fileOrFolderOrSymLinkList[key]; if (isString(value)) { - this.ensureFileOrFolder({ path, content: value }); + this.ensureInitialFileOrFolder({ path, content: value }); } else { - this.ensureFileOrFolder({ path, ...value }); + this.ensureInitialFileOrFolder({ path, ...value }); } } } @@ -511,11 +662,11 @@ export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost, modifyFile(filePath: string, content: string, options?: Partial): void { const path = this.toFullPath(filePath); const currentEntry = this.fs.get(path); - if (!currentEntry || !isFsFile(currentEntry)) { + if (!currentEntry || !isFsFileOrFsLibFile(currentEntry)) { throw new Error(`file not present: ${filePath}`); } - if (options && options.invokeFileDeleteCreateAsPartInsteadOfChange) { + if (isFsLibFile(currentEntry) || options?.invokeFileDeleteCreateAsPartInsteadOfChange) { this.removeFileOrFolder(currentEntry, /*isRenaming*/ false, options); this.ensureFileOrFolder({ path: filePath, content }, /*ignoreWatchInvokedWithTriggerAsFileCreate*/ undefined, /*ignoreParentWatch*/ undefined, options); } @@ -547,42 +698,42 @@ export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost, // Add updated folder with new folder name const newFullPath = getNormalizedAbsolutePath(newFileName, this.currentDirectory); - const newFile = this.toFsFile({ path: newFullPath, content: file.content }); + const newFile = this.toFsFileOrLibFile({ path: newFullPath, content: file.content }); const newPath = newFile.path; - const basePath = getDirectoryPath(path); + const basePath = getDirectoryPath(newPath); Debug.assert(basePath !== path); - Debug.assert(basePath === getDirectoryPath(newPath)); + this.ensureFileOrFolder({ path: getDirectoryPath(newFullPath) }); const baseFolder = this.fs.get(basePath) as FsFolder; this.addFileOrFolderInFolder(baseFolder, newFile); } - renameFolder(folderName: string, newFolderName: string): void { + renameFolder(folderName: string, newFolderName: string, skipFolderEntryWatches?: true): void { const fullPath = getNormalizedAbsolutePath(folderName, this.currentDirectory); const path = this.toPath(fullPath); const folder = this.fs.get(path) as FsFolder; Debug.assert(!!folder); + const newFullPath = getNormalizedAbsolutePath(newFolderName, this.currentDirectory); + const newFolder = this.toFsFolder(newFullPath); + + // Invoke watches for files in the folder as deleted (from old path) + this.renameFolderEntries(folder, newFolder, skipFolderEntryWatches); + // Only remove the folder this.removeFileOrFolder(folder, /*isRenaming*/ true); // Add updated folder with new folder name - const newFullPath = getNormalizedAbsolutePath(newFolderName, this.currentDirectory); - const newFolder = this.toFsFolder(newFullPath); const newPath = newFolder.path; - const basePath = getDirectoryPath(path); - Debug.assert(basePath !== path); - Debug.assert(basePath === getDirectoryPath(newPath)); + const basePath = getDirectoryPath(newPath); + this.ensureFileOrFolder({ path: getDirectoryPath(newFullPath) }); const baseFolder = this.fs.get(basePath) as FsFolder; this.addFileOrFolderInFolder(baseFolder, newFolder); - - // Invoke watches for files in the folder as deleted (from old path) - this.renameFolderEntries(folder, newFolder); } - private renameFolderEntries(oldFolder: FsFolder, newFolder: FsFolder) { + private renameFolderEntries(oldFolder: FsFolder, newFolder: FsFolder, skipWatches: true | undefined) { for (const entry of oldFolder.entries) { this.fs.delete(entry.path); - this.invokeFileAndFsWatches(entry.fullPath, FileWatcherEventKind.Deleted, entry.fullPath); + if (!skipWatches) this.invokeFileAndFsWatches(entry.fullPath, FileWatcherEventKind.Deleted, entry.fullPath); entry.fullPath = combinePaths(newFolder.fullPath, getBaseFileName(entry.fullPath)); entry.path = this.toPath(entry.fullPath); @@ -591,16 +742,16 @@ export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost, } this.fs.set(entry.path, entry); this.setInode(entry.path); - this.invokeFileAndFsWatches(entry.fullPath, FileWatcherEventKind.Created, entry.fullPath); + if (!skipWatches) this.invokeFileAndFsWatches(entry.fullPath, FileWatcherEventKind.Created, entry.fullPath); if (isFsFolder(entry)) { - this.renameFolderEntries(entry, entry); + this.renameFolderEntries(entry, entry, skipWatches); } } } - ensureFileOrFolder(fileOrDirectoryOrSymLink: FileOrFolderOrSymLink, ignoreWatchInvokedWithTriggerAsFileCreate?: boolean, ignoreParentWatch?: boolean, options?: Partial): void { + ensureFileOrFolder(fileOrDirectoryOrSymLink: FileOrFolderOrSymLinkOrLibFile, ignoreWatchInvokedWithTriggerAsFileCreate?: boolean, ignoreParentWatch?: boolean, options?: Partial): void { if (isFile(fileOrDirectoryOrSymLink)) { - const file = this.toFsFile(fileOrDirectoryOrSymLink); + const file = this.toFsFileOrLibFile(fileOrDirectoryOrSymLink); // file may already exist when updating existing type declaration file if (!this.fs.get(file.path)) { const baseFolder = this.ensureFolder(getDirectoryPath(file.fullPath), ignoreParentWatch, options); @@ -642,7 +793,7 @@ 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: FSEntry, ignoreWatch?: boolean, options?: Partial) { if (!this.fs.has(fileOrDirectory.path)) { insertSorted(folder.entries, fileOrDirectory, (a, b) => compareStringsCaseSensitive(getBaseFileName(a.path), getBaseFileName(b.path))); } @@ -666,7 +817,7 @@ export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost, this.inodeWatching = inodeWatching; } - private removeFileOrFolder(fileOrDirectory: FsFile | FsFolder | FsSymLink, isRenaming?: boolean, options?: Partial) { + private removeFileOrFolder(fileOrDirectory: FSEntry, isRenaming?: boolean, options?: Partial) { const basePath = getDirectoryPath(fileOrDirectory.path); const baseFolder = this.fs.get(basePath) as FsFolder; if (basePath !== fileOrDirectory.path) { @@ -683,9 +834,15 @@ export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost, this.inodes?.delete(fileOrDirectory.path); } + rimrafSync(fileOrFolderPath: string): void { + const fileOrFolder = this.getRealFileOrFolder(fileOrFolderPath); + if (isFsFileOrFsLibFile(fileOrFolder)) this.removeFileOrFolder(fileOrFolder); + else if (isFsFolder(fileOrFolder)) this.deleteFolder(fileOrFolder.fullPath, /*recursive*/ true); + } + deleteFile(filePath: string): void { const file = this.getRealFileOrFolder(filePath); - Debug.assert(isFsFile(file)); + Debug.assert(isFsFileOrFsLibFile(file)); this.removeFileOrFolder(file); } @@ -801,10 +958,11 @@ export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost, }; } - private toFsFile(file: File): FsFile { - const fsFile = this.toFsEntry(file.path) as FsFile; - fsFile.content = file.content; - fsFile.fileSize = file.fileSize; + private toFsFileOrLibFile(file: File | LibFile): FsFile | FsLibFile { + const fsFile = this.toFsEntry(file.path) as FsFile & FsLibFile; + fsFile.content = (file as File).content; + fsFile.fileSize = (file as File).fileSize; + fsFile.libFile = (file as LibFile).libFile; return fsFile; } @@ -846,8 +1004,8 @@ export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost, return !!this.getRealFile(fsEntry.path, fsEntry); } - private getRealFile(path: Path, fsEntry?: FSEntry): FsFile | undefined { - return this.getRealFsEntry(isFsFile, path, fsEntry); + private getRealFile(path: Path, fsEntry?: FSEntry): FSFileOrLibFile | undefined { + return this.getRealFsEntry(isFsFileOrFsLibFile, path, fsEntry); } private isFsFolder(fsEntry: FSEntry) { @@ -885,14 +1043,14 @@ export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost, readFile(s: string): string | undefined { const fsEntry = this.getRealFile(this.toFullPath(s)); - return fsEntry ? fsEntry.content : undefined; + return fsEntry ? getFsFileOrLibFileContent(fsEntry) : undefined; } getFileSize(s: string): number { const path = this.toFullPath(s); const entry = this.fs.get(path)!; - if (isFsFile(entry)) { - return entry.fileSize ? entry.fileSize : entry.content.length; + if (isFsFileOrFsLibFile(entry)) { + return (entry as FsFile).fileSize ? (entry as FsFile).fileSize! : getFsFileOrLibFileContent(entry).length; } return undefined!; // TODO: GH#18217 } @@ -996,7 +1154,7 @@ export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost, } writeFile(path: string, content: string): void { - const file = this.toFsFile({ path, content }); + const file = this.toFsFileOrLibFile({ path, content }); // base folder has to be present const base = getDirectoryPath(file.path); @@ -1057,15 +1215,12 @@ export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost, this.clearOutput(); } + getSnap(): TestServerHostSnapshot { + return cloneFsMap(this.fs); + } + private snap() { - this.serializedDiff = new Map(); - this.fs.forEach((value, key) => { - const cloneValue = clone(value); - if (isFsFolder(cloneValue)) { - cloneValue.entries = cloneValue.entries.map(clone) as SortedArray; - } - this.serializedDiff.set(key, cloneValue); - }); + this.serializedDiff = cloneFsMap(this.fs); } serializeState(baseline: string[], serializeOutput: SerializeOutputOrder): void { @@ -1080,7 +1235,7 @@ export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost, } writtenFiles?: Map; - private serializedDiff = new Map(); + private serializedDiff: TestServerHostSnapshot = new Map(); diff(baseline: string[]): void { this.fs.forEach((newFsEntry, path) => { diffFsEntry(baseline, this.serializedDiff.get(path), newFsEntry, this.inodes?.get(path), this.writtenFiles); @@ -1131,19 +1286,24 @@ export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost, } } -function diffFsFile(baseline: string[], fsEntry: FsFile, newInode: number | undefined) { - baseline.push(`//// [${fsEntry.fullPath}]${inodeString(newInode)}\r\n${fsEntry.content}`, ""); +function diffFsFile(baseline: string[], fsEntry: FSFileOrLibFile, newInode: number | undefined) { + if (!isFsLibFile(fsEntry)) { + baseline.push(`//// [${fsEntry.fullPath}]${inodeString(newInode)}\r\n${fsEntry.content}`, ""); + } + else if (fsEntry.content) { + baseline.push(`//// [${fsEntry.fullPath}] *Lib*${inodeString(newInode)}`, ""); + } } function diffFsSymLink(baseline: string[], fsEntry: FsSymLink, newInode: number | undefined) { - baseline.push(`//// [${fsEntry.fullPath}] symlink(${fsEntry.symLink})${inodeString(newInode)}`); + baseline.push(`//// [${fsEntry.fullPath}] symlink(${fsEntry.symLink})${inodeString(newInode)}`, ""); } 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 { const file = newFsEntry && newFsEntry.fullPath; - if (isFsFile(oldFsEntry)) { - if (isFsFile(newFsEntry)) { + if (isFsFileOrFsLibFile(oldFsEntry)) { + if (isFsFileOrFsLibFile(newFsEntry)) { if (oldFsEntry.content !== newFsEntry.content) { diffFsFile(baseline, newFsEntry, newInode); } @@ -1185,12 +1345,12 @@ function diffFsEntry(baseline: string[], oldFsEntry: FSEntry | undefined, newFsE } else { baseline.push(`//// [${oldFsEntry.fullPath}] deleted symlink`); - if (isFsFile(newFsEntry)) { + if (isFsFileOrFsLibFile(newFsEntry)) { diffFsFile(baseline, newFsEntry, newInode); } } } - else if (isFsFile(newFsEntry)) { + else if (isFsFileOrFsLibFile(newFsEntry)) { diffFsFile(baseline, newFsEntry, newInode); } else if (isFsSymLink(newFsEntry)) { @@ -1206,6 +1366,12 @@ function baselineOutputs(baseline: string[], output: readonly string[], start: n if (baselinedOutput) baseline.push(baselinedOutput.join("")); } +function sanitizeSysOutput(output: string) { + return output + .replace(/Elapsed::\s\d+(?:\.\d+)?ms/g, "Elapsed:: *ms") + .replace(/\d\d:\d\d:\d\d\s(?:A|P)M/g, "HH:MM:SS AM"); +} + export type TestServerHostTrackingWrittenFiles = TestServerHost & { writtenFiles: Map; }; export function changeToHostTrackingWrittenFiles(inputHost: TestServerHost): TestServerHostTrackingWrittenFiles { diff --git a/src/testRunner/unittests/services/extract/helpers.ts b/src/testRunner/unittests/services/extract/helpers.ts index e2ed6681880e1..b733b89f50c9c 100644 --- a/src/testRunner/unittests/services/extract/helpers.ts +++ b/src/testRunner/unittests/services/extract/helpers.ts @@ -3,11 +3,7 @@ import { createHasErrorMessageLogger } from "../../../../harness/tsserverLogger. import * as Harness from "../../../_namespaces/Harness.js"; import * as ts from "../../../_namespaces/ts.js"; import { customTypesMap } from "../../helpers/typingsInstaller.js"; -import { - createServerHost, - libFile, - TestServerHost, -} from "../../helpers/virtualFileSystemWithWatch.js"; +import { TestServerHost } from "../../helpers/virtualFileSystemWithWatch.js"; export interface TestProjectServiceOptions extends ts.server.ProjectServiceOptions { host: TestServerHost; @@ -112,7 +108,7 @@ export const notImplementedHost: ts.LanguageServiceHost = { fileExists: ts.notImplemented, }; -export function testExtractSymbol(caption: string, text: string, baselineFolder: string, description: ts.DiagnosticMessage, includeLib?: boolean): void { +export function testExtractSymbol(caption: string, text: string, baselineFolder: string, description: ts.DiagnosticMessage): void { const t = extractTest(text); const selectionRange = t.ranges.get("selection")!; if (!selectionRange) { @@ -122,8 +118,8 @@ export function testExtractSymbol(caption: string, text: string, baselineFolder: [ts.Extension.Ts, ts.Extension.Js].forEach(extension => it(`${caption} [${extension}]`, () => runBaseline(extension))); function runBaseline(extension: ts.Extension) { - const path = "/a" + extension; - const { program } = makeProgram({ path, content: t.source }, includeLib); + const path = "/home/src/workspaces/project/a" + extension; + const { program } = makeProgram({ path, content: t.source }); if (hasSyntacticDiagnostics(program)) { // Don't bother generating JS baselines for inputs that aren't valid JS. @@ -158,14 +154,14 @@ export function testExtractSymbol(caption: string, text: string, baselineFolder: const newTextWithRename = newText.slice(0, renameLocation) + "/*RENAME*/" + newText.slice(renameLocation); data.push(newTextWithRename); - const { program: diagProgram } = makeProgram({ path, content: newText }, includeLib); + const { program: diagProgram } = makeProgram({ path, content: newText }); assert.isFalse(hasSyntacticDiagnostics(diagProgram)); } Harness.Baseline.runBaseline(`${baselineFolder}/${caption}${extension}`, data.join(newLineCharacter)); } - function makeProgram(f: { path: string; content: string; }, includeLib?: boolean) { - const host = createServerHost(includeLib ? [f, libFile] : [f]); // libFile is expensive to parse repeatedly - only test when required + function makeProgram(f: { path: string; content: string; }) { + const host = TestServerHost.createServerHost([f]); // libFile is expensive to parse repeatedly - only test when required const projectService = new TestProjectService(host); projectService.openClientFile(f.path); const program = projectService.inferredProjects[0].getLanguageService().getProgram()!; @@ -187,10 +183,10 @@ export function testExtractSymbolFailed(caption: string, text: string, descripti throw new Error(`Test ${caption} does not specify selection range`); } const f = { - path: "/a.ts", + path: "/home/src/workspaces/project/a.ts", content: t.source, }; - const host = createServerHost([f, libFile]); + const host = TestServerHost.createServerHost([f]); const projectService = new TestProjectService(host); projectService.openClientFile(f.path); const program = projectService.inferredProjects[0].getLanguageService().getProgram()!; From f59570415c21a5e433305cb8f71e6b3cd8127e0c Mon Sep 17 00:00:00 2001 From: Isabel Duan Date: Thu, 12 Sep 2024 10:21:26 -0700 Subject: [PATCH 18/27] fix tests --- src/compiler/executeCommandLine.ts | 2 +- src/harness/watchUtils.ts | 2 +- src/testRunner/unittests/helpers/contents.ts | 11 +++++++---- .../helpers/forceConsistentCasingInFileNames.ts | 2 +- .../unittests/helpers/transitiveReferences.ts | 2 +- 5 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/compiler/executeCommandLine.ts b/src/compiler/executeCommandLine.ts index e8d22cf7ca6dc..ca166635ac5c1 100644 --- a/src/compiler/executeCommandLine.ts +++ b/src/compiler/executeCommandLine.ts @@ -728,7 +728,7 @@ function executeCommandLineWorker( } } -/** @internal Returns true if commandline is --build and needs to be parsed useing parseBuildCommand */ +/** Returns true if commandline is --build and needs to be parsed useing parseBuildCommand */ export function isBuildCommand(commandLineArgs: readonly string[]): boolean { if (commandLineArgs.length > 0 && commandLineArgs[0].charCodeAt(0) === CharacterCodes.minus) { const firstOption = commandLineArgs[0].slice(commandLineArgs[0].charCodeAt(1) === CharacterCodes.minus ? 2 : 1).toLowerCase(); diff --git a/src/harness/watchUtils.ts b/src/harness/watchUtils.ts index acf92d91c70e0..5875264317424 100644 --- a/src/harness/watchUtils.ts +++ b/src/harness/watchUtils.ts @@ -14,7 +14,7 @@ import { System, } from "./_namespaces/ts.js"; -export function ensureWatchablePath(path: string, locationType: string) { +export function ensureWatchablePath(path: string, locationType: string): void { Debug.assert( canWatchDirectoryOrFilePath(path as Path), `Not a watchable location: ${locationType} like "/home/src/workspaces/project" or refer canWatchDirectoryOrFile for more allowed locations`, diff --git a/src/testRunner/unittests/helpers/contents.ts b/src/testRunner/unittests/helpers/contents.ts index 3299451fdbdb2..0baa1f850d2f2 100644 --- a/src/testRunner/unittests/helpers/contents.ts +++ b/src/testRunner/unittests/helpers/contents.ts @@ -5,12 +5,12 @@ import { import * as ts from "../../_namespaces/ts.js"; /** Default typescript and lib installs location for tests */ -export const tscTypeScriptTestLocation = getPathForTypeScriptTestLocation("tsc.js"); -export function getPathForTypeScriptTestLocation(fileName: string) { +export const tscTypeScriptTestLocation: string = getPathForTypeScriptTestLocation("tsc.js"); +export function getPathForTypeScriptTestLocation(fileName: string): string { return ts.combinePaths(harnessSessionLibLocation, fileName); } -export function getTypeScriptLibTestLocation(libName: string) { +export function getTypeScriptLibTestLocation(libName: string): string { return getPathForTypeScriptTestLocation(ts.libMap.get(libName) ?? `lib.${libName}.d.ts`); } @@ -33,6 +33,9 @@ interface Symbol { } `; -export function getProjectConfigWithNodeNext(withNodeNext: boolean | undefined) { +export function getProjectConfigWithNodeNext(withNodeNext: boolean | undefined): { + module: string; + target: string; +} | undefined { return withNodeNext ? { module: "nodenext", target: "es5" } : undefined; } diff --git a/src/testRunner/unittests/helpers/forceConsistentCasingInFileNames.ts b/src/testRunner/unittests/helpers/forceConsistentCasingInFileNames.ts index 48cc0e08fc955..a8546156d1abb 100644 --- a/src/testRunner/unittests/helpers/forceConsistentCasingInFileNames.ts +++ b/src/testRunner/unittests/helpers/forceConsistentCasingInFileNames.ts @@ -2,7 +2,7 @@ import { dedent } from "../../_namespaces/Utils.js"; import { jsonToReadableText } from "../helpers.js"; import { TestServerHost } from "./virtualFileSystemWithWatch.js"; -export function getSysForMultipleErrorsForceConsistentCasingInFileNames(forTsserver?: boolean) { +export function getSysForMultipleErrorsForceConsistentCasingInFileNames(forTsserver?: boolean): TestServerHost { return TestServerHost.getCreateWatchedSystem(forTsserver)({ "/home/src/projects/project/src/struct.d.ts": dedent` import * as xs1 from "fp-ts/lib/Struct"; diff --git a/src/testRunner/unittests/helpers/transitiveReferences.ts b/src/testRunner/unittests/helpers/transitiveReferences.ts index f2a034ee4fb2d..8d7dd8b5cb673 100644 --- a/src/testRunner/unittests/helpers/transitiveReferences.ts +++ b/src/testRunner/unittests/helpers/transitiveReferences.ts @@ -35,7 +35,7 @@ export function getFsContentsForTransitiveReferencesAConfig(withNodeNext: boolea }); } -export function getSysForTransitiveReferences(withNodeNext?: boolean) { +export function getSysForTransitiveReferences(withNodeNext?: boolean): TestServerHost { return TestServerHost.createWatchedSystem({ "/user/username/projects/transitiveReferences/refs/a.d.ts": getFsContentsForTransitiveReferencesRefsAdts(), "/user/username/projects/transitiveReferences/a.ts": dedent` From fc90f1142d5860461847006126c1952edaa0e25d Mon Sep 17 00:00:00 2001 From: Isabel Duan Date: Thu, 12 Sep 2024 10:26:03 -0700 Subject: [PATCH 19/27] update iterators for 5.6 --- src/compiler/core.ts | 5 +++-- src/harness/collectionsImpl.ts | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 6e74d4618cec0..ef83fefd533e0 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -505,10 +505,11 @@ export function mapDefined(array: readonly T[] | undefined, mapFn: (x: T, } /** @internal */ -export function* mapDefinedIterator(iter: Iterable, mapFn: (x: T) => U | undefined): Generator, void, unknown> { +// eslint-disable-next-line no-restricted-syntax +export function* mapDefinedIterator(iter: Iterable, mapFn: (x: T) => U | undefined): Generator { for (const x of iter) { const value = mapFn(x); - if (value !== undefined && value !== null) { // eslint-disable-line no-restricted-syntax + if (value !== undefined) { yield value; } } diff --git a/src/harness/collectionsImpl.ts b/src/harness/collectionsImpl.ts index d32fefb2c14a9..9f8fe7399acd7 100644 --- a/src/harness/collectionsImpl.ts +++ b/src/harness/collectionsImpl.ts @@ -112,7 +112,7 @@ export class SortedMap { } } - public *keys(): Generator { + public *keys(): Generator { const keys = this._keys; const indices = this.getIterationOrder(); const version = this._version; @@ -135,7 +135,7 @@ export class SortedMap { return undefined; } - public *values(): Generator { + public *values(): Generator { const values = this._values; const indices = this.getIterationOrder(); const version = this._version; From 14860a36b80715186dc214fa2c71be1ffa214faa Mon Sep 17 00:00:00 2001 From: Isabel Duan Date: Thu, 12 Sep 2024 18:11:01 -0700 Subject: [PATCH 20/27] refactor types --- src/compiler/builder.ts | 6 +- src/compiler/commandLineParser.ts | 15 +- src/compiler/debug.ts | 2 +- src/compiler/emitter.ts | 7 +- src/compiler/expressionToTypeNode.ts | 8 +- src/compiler/moduleNameResolver.ts | 26 ++- src/compiler/parser.ts | 7 +- src/compiler/program.ts | 15 +- src/compiler/scanner.ts | 14 +- src/compiler/sys.ts | 6 +- src/compiler/transformers/declarations.ts | 7 +- .../module/impliedNodeFormatDependent.ts | 3 +- src/compiler/transformers/ts.ts | 3 +- src/compiler/transformers/utilities.ts | 2 +- src/compiler/tsbuildPublic.ts | 19 +- src/compiler/types.ts | 170 +++++++++++------- src/compiler/utilities.ts | 73 ++++---- src/compiler/watch.ts | 5 +- src/harness/client.ts | 6 +- src/harness/fourslashImpl.ts | 10 +- src/harness/fourslashInterfaceImpl.ts | 20 ++- src/server/editorServices.ts | 2 +- src/server/project.ts | 19 +- src/services/stringCompletions.ts | 11 +- src/services/symbolDisplay.ts | 10 +- tests/baselines/reference/api/typescript.d.ts | 12 +- 26 files changed, 272 insertions(+), 206 deletions(-) diff --git a/src/compiler/builder.ts b/src/compiler/builder.ts index 40d3fca7ac2a7..0fe55014a5f85 100644 --- a/src/compiler/builder.ts +++ b/src/compiler/builder.ts @@ -89,6 +89,7 @@ import { WriteFileCallback, WriteFileCallbackData, } from "./_namespaces/ts.js"; +import { BuildInfoFileVersionMap } from "./types.js"; /** @internal */ export interface ReusableDiagnostic extends ReusableDiagnosticRelatedInformation { @@ -2395,10 +2396,7 @@ export function getBuildInfoFileVersionMap( program: IncrementalBuildInfo, buildInfoPath: string, host: Pick, -): { - fileInfos: Map; - roots: Map; -} { +): BuildInfoFileVersionMap { const buildInfoDirectory = getDirectoryPath(getNormalizedAbsolutePath(buildInfoPath, host.getCurrentDirectory())); const getCanonicalFileName = createGetCanonicalFileName(host.useCaseSensitiveFileNames()); const fileInfos = new Map(); diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index f605aec2f4f40..7ced116d86840 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -1835,6 +1835,14 @@ export interface OptionsBase { [option: string]: CompilerOptionsValue | TsConfigSourceFile | undefined; } +/** @internal */ +export interface BaseParsedCommandLine { + options: OptionsBase; + watchOptions: WatchOptions | undefined; + fileNames: string[]; + errors: Diagnostic[]; +} + /** @internal */ export interface ParseCommandLineWorkerDiagnostics extends DidYouMeanOptionsDiagnostics { getOptionsNameMap: () => OptionsNameMap; @@ -1875,12 +1883,7 @@ export function parseCommandLineWorker( diagnostics: ParseCommandLineWorkerDiagnostics, commandLine: readonly string[], readFile?: (path: string) => string | undefined, -): { - options: OptionsBase; - watchOptions: WatchOptions | undefined; - fileNames: string[]; - errors: Diagnostic[]; -} { +): BaseParsedCommandLine { const options = {} as OptionsBase; let watchOptions: WatchOptions | undefined; const fileNames: string[] = []; diff --git a/src/compiler/debug.ts b/src/compiler/debug.ts index 166ed9025be25..42e8637ac178a 100644 --- a/src/compiler/debug.ts +++ b/src/compiler/debug.ts @@ -365,7 +365,7 @@ export namespace Debug { export function type(value: unknown): asserts value is T; export function type(_value: unknown) {} - export function getFunctionName(func: AnyFunction): any { + export function getFunctionName(func: AnyFunction): string { if (typeof func !== "function") { return ""; } diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index dcc71fd16dc14..e63bfd783ced2 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -561,7 +561,12 @@ function getOutputPathWithoutChangingExt( } /** @internal */ -export function getOutputDeclarationFileName(inputFileName: string, configFile: ParsedCommandLine, ignoreCase: boolean, getCommonSourceDirectory = (): string => getCommonSourceDirectoryOfConfig(configFile, ignoreCase)): string { +export function getOutputDeclarationFileName( + inputFileName: string, + configFile: ParsedCommandLine, + ignoreCase: boolean, + getCommonSourceDirectory = (): string => getCommonSourceDirectoryOfConfig(configFile, ignoreCase), +): string { return getOutputDeclarationFileNameWorker(inputFileName, configFile.options, ignoreCase, getCommonSourceDirectory); } diff --git a/src/compiler/expressionToTypeNode.ts b/src/compiler/expressionToTypeNode.ts index bc0b7201ca1f2..1c6e045f0f0bd 100644 --- a/src/compiler/expressionToTypeNode.ts +++ b/src/compiler/expressionToTypeNode.ts @@ -55,6 +55,7 @@ import { PropertySignature, SetAccessorDeclaration, SignatureDeclaration, + SyntacticNodeBuilder, SyntacticTypeNodeBuilderContext, SyntacticTypeNodeBuilderResolver, SyntaxKind, @@ -69,12 +70,7 @@ import { export function createSyntacticTypeNodeBuilder( options: CompilerOptions, resolver: SyntacticTypeNodeBuilderResolver, -): { - typeFromExpression: (node: Expression, context: SyntacticTypeNodeBuilderContext, isConstContext?: boolean, requiresAddingUndefined?: boolean, preserveLiterals?: boolean) => boolean | undefined; - serializeTypeOfDeclaration: (node: HasInferredType, context: SyntacticTypeNodeBuilderContext) => boolean | undefined; - serializeReturnTypeForSignature: (node: SignatureDeclaration | JSDocSignature, context: SyntacticTypeNodeBuilderContext) => boolean | undefined; - serializeTypeOfExpression: (expr: Expression, context: SyntacticTypeNodeBuilderContext, addUndefined?: boolean, preserveLiterals?: boolean) => boolean; -} { +): SyntacticNodeBuilder { const strictNullChecks = getStrictOptionValue(options, "strictNullChecks"); return { diff --git a/src/compiler/moduleNameResolver.ts b/src/compiler/moduleNameResolver.ts index d26bc48a9ca57..bf64791da0005 100644 --- a/src/compiler/moduleNameResolver.ts +++ b/src/compiler/moduleNameResolver.ts @@ -454,10 +454,7 @@ function readPackageJsonTypesVersionPaths(jsonContent: PackageJson, state: Modul let typeScriptVersion: Version | undefined; /** @internal */ -export function getPackageJsonTypesVersionsPaths(typesVersions: MapLike>): { - version: string; - paths: MapLike; -} | undefined { +export function getPackageJsonTypesVersionsPaths(typesVersions: MapLike>): VersionPaths | undefined { if (!typeScriptVersion) typeScriptVersion = new Version(version); for (const key in typesVersions) { @@ -1386,10 +1383,7 @@ export function createTypeReferenceDirectiveResolutionCache( } /** @internal */ -export function getOptionsForLibraryResolution(options: CompilerOptions): { - moduleResolution: ModuleResolutionKind; - traceResolution: boolean | undefined; -} { +export function getOptionsForLibraryResolution(options: CompilerOptions): CompilerOptions { return { moduleResolution: ModuleResolutionKind.Node10, traceResolution: options.traceResolution }; } @@ -2683,18 +2677,18 @@ function loadModuleFromImports(extensions: Extensions, moduleName: string, direc * From https://github.com/nodejs/node/blob/8f39f51cbbd3b2de14b9ee896e26421cc5b20121/lib/internal/modules/esm/resolve.js#L722 - * "longest" has some nuance as to what "longest" means in the presence of pattern trailers */ -export function comparePatternKeys(a: string, b: string): 1 | 0 | -1 { +export function comparePatternKeys(a: string, b: string): Comparison { const aPatternIndex = a.indexOf("*"); const bPatternIndex = b.indexOf("*"); const baseLenA = aPatternIndex === -1 ? a.length : aPatternIndex + 1; const baseLenB = bPatternIndex === -1 ? b.length : bPatternIndex + 1; - if (baseLenA > baseLenB) return -1; - if (baseLenB > baseLenA) return 1; - if (aPatternIndex === -1) return 1; - if (bPatternIndex === -1) return -1; - if (a.length > b.length) return -1; - if (b.length > a.length) return 1; - return 0; + if (baseLenA > baseLenB) return Comparison.LessThan; + if (baseLenB > baseLenA) return Comparison.GreaterThan; + if (aPatternIndex === -1) return Comparison.GreaterThan; + if (bPatternIndex === -1) return Comparison.LessThan; + if (a.length > b.length) return Comparison.LessThan; + if (b.length > a.length) return Comparison.GreaterThan; + return Comparison.EqualTo; } function loadModuleFromImportsOrExports(extensions: Extensions, state: ModuleResolutionState, cache: ModuleResolutionCache | undefined, redirectedReference: ResolvedProjectReference | undefined, moduleName: string, lookupTable: object, scope: PackageJsonInfo, isImports: boolean): SearchResult | undefined { diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index b325e97d64cf7..1f007410f11c5 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -1404,10 +1404,13 @@ export function updateSourceFile(sourceFile: SourceFile, newText: string, textCh } /** @internal */ -export function parseIsolatedJSDocComment(content: string, start?: number, length?: number): { +export interface JsDocWithDiagnostics { jsDoc: JSDoc; diagnostics: Diagnostic[]; -} | undefined { +} + +/** @internal */ +export function parseIsolatedJSDocComment(content: string, start?: number, length?: number): JsDocWithDiagnostics | undefined { const result = Parser.JSDocParser.parseIsolatedJSDocComment(content, start, length); if (result && result.jsDoc) { // because the jsDocComment was parsed out of the source file, it might diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 053382b84b647..3dfcd0d2d69b8 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -517,11 +517,7 @@ export interface CompilerHostLikeForCache { } /** @internal */ -export function changeCompilerHostLikeToUseCache( - host: CompilerHostLikeForCache, - toPath: (fileName: string) => Path, - getSourceFile?: CompilerHost["getSourceFile"], -): { +export interface CompilerHostLikeWithCache { originalReadFile: (fileName: string, encoding?: string) => string | undefined; originalFileExists: (fileName: string) => boolean; originalDirectoryExists: ((directory: string) => boolean) | undefined; @@ -529,7 +525,14 @@ export function changeCompilerHostLikeToUseCache( originalWriteFile: WriteFileCallback | undefined; getSourceFileWithCache: ((fileName: string, languageVersionOrOptions: ScriptTarget | CreateSourceFileOptions, onError?: (message: string) => void, shouldCreateNewSourceFile?: boolean) => SourceFile | undefined) | undefined; readFileWithCache: (fileName: string) => string | undefined; -} { +} + +/** @internal */ +export function changeCompilerHostLikeToUseCache( + host: CompilerHostLikeForCache, + toPath: (fileName: string) => Path, + getSourceFile?: CompilerHost["getSourceFile"], +): CompilerHostLikeWithCache { const originalReadFile = host.readFile; const originalFileExists = host.fileExists; const originalDirectoryExists = host.directoryExists; diff --git a/src/compiler/scanner.ts b/src/compiler/scanner.ts index fb318bce41a91..2f2a480300547 100644 --- a/src/compiler/scanner.ts +++ b/src/compiler/scanner.ts @@ -295,7 +295,7 @@ const charCodeToRegExpFlag = new Map([ [CharacterCodes.y, RegularExpressionFlags.Sticky], ]); -const regExpFlagToFirstAvailableLanguageVersion = new Map([ +const regExpFlagToFirstAvailableLanguageVersion = new Map([ [RegularExpressionFlags.HasIndices, LanguageFeatureMinimumTarget.RegularExpressionFlagsHasIndices], [RegularExpressionFlags.DotAll, LanguageFeatureMinimumTarget.RegularExpressionFlagsDotAll], [RegularExpressionFlags.Unicode, LanguageFeatureMinimumTarget.RegularExpressionFlagsUnicode], @@ -1017,7 +1017,15 @@ const enum ClassSetExpressionType { } // Creates a scanner over a (possibly unspecified) range of a piece of text. -export function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean, languageVariant: LanguageVariant = LanguageVariant.Standard, textInitial?: string, onError?: ErrorCallback, start?: number, length?: number): Scanner { +export function createScanner( + languageVersion: ScriptTarget, + skipTrivia: boolean, + languageVariant: 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 */ @@ -3599,7 +3607,7 @@ export function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean } function checkRegularExpressionFlagAvailability(flag: RegularExpressionFlags, size: number) { - const availableFrom = regExpFlagToFirstAvailableLanguageVersion.get(flag) as ScriptTarget | undefined; + const availableFrom = regExpFlagToFirstAvailableLanguageVersion.get(flag); if (availableFrom && languageVersion < availableFrom) { error(Diagnostics.This_regular_expression_flag_is_only_available_when_targeting_0_or_later, pos, size, getNameOfScriptTarget(availableFrom)); } diff --git a/src/compiler/sys.ts b/src/compiler/sys.ts index 52a89099cf2b1..15eac0bee07b4 100644 --- a/src/compiler/sys.ts +++ b/src/compiler/sys.ts @@ -128,11 +128,7 @@ function createPollingIntervalBasedLevels(levels: Levels) { const defaultChunkLevels: Levels = { Low: 32, Medium: 64, High: 256 }; let pollingChunkSize = createPollingIntervalBasedLevels(defaultChunkLevels); /** @internal */ -export let unchangedPollThresholds: { - 250: number; - 500: number; - 2000: number; -} = createPollingIntervalBasedLevels(defaultChunkLevels); +export let unchangedPollThresholds: { [K in PollingInterval]: number; } = createPollingIntervalBasedLevels(defaultChunkLevels); function setCustomPollingValues(system: System) { if (!system.getEnvironmentVariable) { diff --git a/src/compiler/transformers/declarations.ts b/src/compiler/transformers/declarations.ts index 08683627cc944..5777a3395b3d3 100644 --- a/src/compiler/transformers/declarations.ts +++ b/src/compiler/transformers/declarations.ts @@ -213,6 +213,7 @@ import { visitNodes, VisitResult, } from "../_namespaces/ts.js"; +import { DeclarationTransformer } from "../types.js"; /** @internal */ export function getDeclarationDiagnostics( @@ -253,11 +254,7 @@ const declarationEmitInternalNodeBuilderFlags = InternalNodeBuilderFlags.AllowUn * * @internal */ -export function transformDeclarations(context: TransformationContext): { - (node: Bundle): Bundle; - (node: SourceFile): SourceFile; - (node: SourceFile | Bundle): SourceFile | Bundle; -} { +export function transformDeclarations(context: TransformationContext): DeclarationTransformer { const throwDiagnostic = () => Debug.fail("Diagnostic emitted without context"); let getSymbolAccessibilityDiagnostic: GetSymbolAccessibilityDiagnostic = throwDiagnostic; let needsDeclare = true; diff --git a/src/compiler/transformers/module/impliedNodeFormatDependent.ts b/src/compiler/transformers/module/impliedNodeFormatDependent.ts index 8a7ce9af79373..c793c3abe3c54 100644 --- a/src/compiler/transformers/module/impliedNodeFormatDependent.ts +++ b/src/compiler/transformers/module/impliedNodeFormatDependent.ts @@ -10,11 +10,12 @@ import { SyntaxKind, TransformationContext, transformECMAScriptModule, + Transformer, transformModule, } from "../../_namespaces/ts.js"; /** @internal */ -export function transformImpliedNodeFormatDependentModule(context: TransformationContext): (node: SourceFile | Bundle) => SourceFile | Bundle { +export function transformImpliedNodeFormatDependentModule(context: TransformationContext): Transformer { const previousOnSubstituteNode = context.onSubstituteNode; const previousOnEmitNode = context.onEmitNode; diff --git a/src/compiler/transformers/ts.ts b/src/compiler/transformers/ts.ts index 4d0d900df6fd1..75a6a34a55b1c 100644 --- a/src/compiler/transformers/ts.ts +++ b/src/compiler/transformers/ts.ts @@ -190,6 +190,7 @@ import { takeWhile, TextRange, TransformationContext, + Transformer, TransformFlags, VariableDeclaration, VariableStatement, @@ -231,7 +232,7 @@ const enum ClassFacts { } /** @internal */ -export function transformTypeScript(context: TransformationContext): (node: SourceFile | Bundle) => SourceFile | Bundle { +export function transformTypeScript(context: TransformationContext): Transformer { const { factory, getEmitHelperFactory: emitHelpers, diff --git a/src/compiler/transformers/utilities.ts b/src/compiler/transformers/utilities.ts index 11c07a3ae56f0..0079aa25aab16 100644 --- a/src/compiler/transformers/utilities.ts +++ b/src/compiler/transformers/utilities.ts @@ -406,7 +406,7 @@ export class IdentifierNameMap { this._map.clear(); } - values(): IterableIterator { + values(): MapIterator { return this._map.values(); } diff --git a/src/compiler/tsbuildPublic.ts b/src/compiler/tsbuildPublic.ts index efdcdb7502e23..be2074ed22d28 100644 --- a/src/compiler/tsbuildPublic.ts +++ b/src/compiler/tsbuildPublic.ts @@ -4,6 +4,7 @@ import { assertType, BuilderProgram, BuildInfo, + BuildInfoFileVersionMap, CancellationToken, canJsonReportNoInputFiles, changeCompilerHostLikeToUseCache, @@ -301,13 +302,25 @@ function createSolutionBuilderHostBase(system: System, return host; } -export function createSolutionBuilderHost(system: System = sys, createProgram?: CreateProgram, reportDiagnostic?: DiagnosticReporter, reportSolutionBuilderStatus?: DiagnosticReporter, reportErrorSummary?: ReportEmitErrorSummary): SolutionBuilderHost { +export function createSolutionBuilderHost( + system: System = sys, + createProgram?: CreateProgram, + reportDiagnostic?: DiagnosticReporter, + reportSolutionBuilderStatus?: DiagnosticReporter, + reportErrorSummary?: ReportEmitErrorSummary, +): SolutionBuilderHost { const host = createSolutionBuilderHostBase(system, createProgram, reportDiagnostic, reportSolutionBuilderStatus) as SolutionBuilderHost; host.reportErrorSummary = reportErrorSummary; return host; } -export function createSolutionBuilderWithWatchHost(system: System = sys, createProgram?: CreateProgram, reportDiagnostic?: DiagnosticReporter, reportSolutionBuilderStatus?: DiagnosticReporter, reportWatchStatus?: WatchStatusReporter): SolutionBuilderWithWatchHost { +export function createSolutionBuilderWithWatchHost( + system: System = sys, + createProgram?: CreateProgram, + reportDiagnostic?: DiagnosticReporter, + reportSolutionBuilderStatus?: DiagnosticReporter, + reportWatchStatus?: WatchStatusReporter, +): SolutionBuilderWithWatchHost { const host = createSolutionBuilderHostBase(system, createProgram, reportDiagnostic, reportSolutionBuilderStatus) as SolutionBuilderWithWatchHost; const watchHost = createWatchHost(system, reportWatchStatus); copyProperties(host, watchHost); @@ -1601,7 +1614,7 @@ function getUpToDateStatusWorker(state: SolutionBuilde /** True if input file has changed timestamp but text is not changed, we can then do only timestamp updates on output to make it look up-to-date later */ let pseudoInputUpToDate = false; const seenRoots = new Set(); - let buildInfoVersionMap: ReturnType | undefined; + let buildInfoVersionMap: BuildInfoFileVersionMap | undefined; // Get timestamps of input files for (const inputFile of project.fileNames) { const inputTime = getModifiedTime(state, inputFile); diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 942229044d7a1..ec2aa28b019ff 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -4966,6 +4966,14 @@ export interface EmitTransformers { declarationTransformers: readonly TransformerFactory[]; } +/** @internal */ + +export interface DeclarationTransformer { + (node: Bundle): Bundle; + (node: SourceFile): SourceFile; + (node: SourceFile | Bundle): SourceFile | Bundle; +} + export interface SourceMapSpan { /** Line number in the .js file. */ emittedLine: number; @@ -7575,7 +7583,6 @@ export const enum ScriptKind { // NOTE: We must reevaluate the target for upcoming features when each successive TC39 edition is ratified in // June of each year. This includes changes to `LanguageFeatureMinimumTarget`, `ScriptTarget`, // transformers/esnext.ts, commandLineParser.ts, and the contents of each lib/esnext.*.d.ts file. -// IF UPDATING 'ScriptTarget', ALSO UPDATE 'LanguageFeatureMinimumTarget' (if needed) export const enum ScriptTarget { /** @deprecated */ ES3 = 0, @@ -8335,87 +8342,98 @@ export type EmitHelper = ScopedEmitHelper | UnscopedEmitHelper; export type EmitHelperUniqueNameCallback = (name: string) => string; -/** - * Indicates the minimum `ScriptTarget` (inclusive) after which a specific language feature is no longer transpiled. - * - * @internal - */ -export const enum LanguageFeatureMinimumTarget { - // These are copied from 'ScriptTarget' since under isolatedDeclarations, enums cannot have references to external symbols. - // Make sure these are updated alongside any changes to 'ScriptTarget'. - /**@deprecated */ - ES3 = 0, - ES5 = 1, - ES2015 = 2, - ES2016 = 3, - ES2017 = 4, - ES2018 = 5, - ES2019 = 6, - ES2020 = 7, - ES2021 = 8, - ES2022 = 9, - ES2023 = 10, - ESNext = 99, - JSON = 100, - Latest = ESNext, - +/** @internal */ +export type LanugageFeatures = // ES2015 Features - Classes = ES2015, - ForOf = ES2015, - Generators = ES2015, - Iteration = ES2015, - SpreadElements = ES2015, - RestElements = ES2015, - TaggedTemplates = ES2015, - DestructuringAssignment = ES2015, - BindingPatterns = ES2015, - ArrowFunctions = ES2015, - BlockScopedVariables = ES2015, - ObjectAssign = ES2015, - RegularExpressionFlagsUnicode = ES2015, - RegularExpressionFlagsSticky = ES2015, - + | "Classes" + | "ForOf" + | "Generators" + | "Iteration" + | "SpreadElements" + | "RestElements" + | "TaggedTemplates" + | "DestructuringAssignment" + | "BindingPatterns" + | "ArrowFunctions" + | "BlockScopedVariables" + | "ObjectAssign" + | "RegularExpressionFlagsUnicode" + | "RegularExpressionFlagsSticky" // ES2016 Features - Exponentiation = ES2016, // `x ** y` - + | "Exponentiation" // `x ** y` // ES2017 Features - AsyncFunctions = ES2017, // `async function f() {}` - + | "AsyncFunctions" // `async function f() {}` // ES2018 Features - ForAwaitOf = ES2018, // `for await (const x of y)` - AsyncGenerators = ES2018, // `async function * f() { }` - AsyncIteration = ES2018, // `Symbol.asyncIterator` - ObjectSpreadRest = ES2018, // `{ ...obj }` - RegularExpressionFlagsDotAll = ES2018, - + | "ForAwaitOf" // `for await (const x of y)` + | "AsyncGenerators" // `async function * f() { }` + | "AsyncIteration" // `Symbol.asyncIterator` + | "ObjectSpreadRest" // `{ ...obj }` + | "RegularExpressionFlagsDotAll" // ES2019 Features - BindinglessCatch = ES2019, // `try { } catch { }` - + | "BindinglessCatch" // `try { } catch { }` // ES2020 Features - BigInt = ES2020, // `0n` - NullishCoalesce = ES2020, // `a ?? b` - OptionalChaining = ES2020, // `a?.b` - + | "BigInt" // `0n` + | "NullishCoalesce" // `a ?? b` + | "OptionalChaining" // `a?.b` // ES2021 Features - LogicalAssignment = ES2021, // `a ||= b`, `a &&= b`, `a ??= b` - + | "LogicalAssignment" // `a ||= b`| `a &&= b`| `a ??= b` // ES2022 Features - TopLevelAwait = ES2022, - ClassFields = ES2022, - PrivateNamesAndClassStaticBlocks = ES2022, // `class C { static {} #x = y, #m() {} }`, `#x in y` - RegularExpressionFlagsHasIndices = ES2022, - + | "TopLevelAwait" + | "ClassFields" + | "PrivateNamesAndClassStaticBlocks" // `class C { static {} #x = y| #m() {} }`| `#x in y` + | "RegularExpressionFlagsHasIndices" // ES2023 Features - ShebangComments = ESNext, - + | "ShebangComments" // Upcoming Features // NOTE: We must reevaluate the target for upcoming features when each successive TC39 edition is ratified in // June of each year. This includes changes to `LanguageFeatureMinimumTarget`, `ScriptTarget`, // transformers/esnext.ts, commandLineParser.ts, and the contents of each lib/esnext.*.d.ts file. - UsingAndAwaitUsing = ESNext, // `using x = y`, `await using x = y` - ClassAndClassElementDecorators = ESNext, // `@dec class C {}`, `class C { @dec m() {} }` - RegularExpressionFlagsUnicodeSets = ESNext, -} + | "UsingAndAwaitUsing" + | "ClassAndClassElementDecorators" // `using x = y`, `await using x = y` + | "RegularExpressionFlagsUnicodeSets" // `@dec class C {}`, `class C { @dec m() {} }` +; + +/** + * Indicates the minimum `ScriptTarget` (inclusive) after which a specific language feature is no longer transpiled. + * + * @internal + */ +export const LanguageFeatureMinimumTarget: Record = { + Classes: ScriptTarget.ES2015, + ForOf: ScriptTarget.ES2015, + Generators: ScriptTarget.ES2015, + Iteration: ScriptTarget.ES2015, + SpreadElements: ScriptTarget.ES2015, + RestElements: ScriptTarget.ES2015, + TaggedTemplates: ScriptTarget.ES2015, + DestructuringAssignment: ScriptTarget.ES2015, + BindingPatterns: ScriptTarget.ES2015, + ArrowFunctions: ScriptTarget.ES2015, + BlockScopedVariables: ScriptTarget.ES2015, + ObjectAssign: ScriptTarget.ES2015, + RegularExpressionFlagsUnicode: ScriptTarget.ES2015, + RegularExpressionFlagsSticky: ScriptTarget.ES2015, + Exponentiation: ScriptTarget.ES2016, + AsyncFunctions: ScriptTarget.ES2017, + ForAwaitOf: ScriptTarget.ES2018, + AsyncGenerators: ScriptTarget.ES2018, + AsyncIteration: ScriptTarget.ES2018, + ObjectSpreadRest: ScriptTarget.ES2018, + RegularExpressionFlagsDotAll: ScriptTarget.ES2018, + BindinglessCatch: ScriptTarget.ES2019, + BigInt: ScriptTarget.ES2020, + NullishCoalesce: ScriptTarget.ES2020, + OptionalChaining: ScriptTarget.ES2020, + LogicalAssignment: ScriptTarget.ES2021, + TopLevelAwait: ScriptTarget.ES2022, + ClassFields: ScriptTarget.ES2022, + PrivateNamesAndClassStaticBlocks: ScriptTarget.ES2022, + RegularExpressionFlagsHasIndices: ScriptTarget.ES2022, + ShebangComments: ScriptTarget.ESNext, + UsingAndAwaitUsing: ScriptTarget.ESNext, + ClassAndClassElementDecorators: ScriptTarget.ESNext, + RegularExpressionFlagsUnicodeSets: ScriptTarget.ESNext, +}; // dprint-ignore /** @@ -9683,6 +9701,12 @@ export interface BuildInfo { version: string; } +/** @internal */ +export interface BuildInfoFileVersionMap { + fileInfos: Map; + roots: Map; +} + export interface PrintHandlers { /** * A hook used by the Printer when generating unique names to avoid collisions with @@ -10500,3 +10524,11 @@ export interface SyntacticTypeNodeBuilderResolver { requiresAddingImplicitUndefined(parameter: ParameterDeclaration | JSDocParameterTag, enclosingDeclaration: Node | undefined): boolean; isDefinitelyReferenceToGlobalSymbolObject(node: Node): boolean; } +/** @internal */ + +export interface SyntacticNodeBuilder { + typeFromExpression: (node: Expression, context: SyntacticTypeNodeBuilderContext, isConstContext?: boolean, requiresAddingUndefined?: boolean, preserveLiterals?: boolean) => boolean | undefined; + serializeTypeOfDeclaration: (node: HasInferredType, context: SyntacticTypeNodeBuilderContext) => boolean | undefined; + serializeReturnTypeForSignature: (node: SignatureDeclaration | JSDocSignature, context: SyntacticTypeNodeBuilderContext) => boolean | undefined; + serializeTypeOfExpression: (expr: Expression, context: SyntacticTypeNodeBuilderContext, addUndefined?: boolean, preserveLiterals?: boolean) => boolean; +} diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index c14d1066c5c2b..bb825bb1f5345 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -6812,16 +6812,27 @@ function emitComments( } } +/** @internal */ +export interface DetachedCommentInfo { + nodePos: number; + detachedCommentEndPos: number; +} + /** * Detached comment is a comment at the top of file or function body that is separated from * the next statement by space. * * @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): { - nodePos: number; - detachedCommentEndPos: number; -} | undefined { +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, +): DetachedCommentInfo | undefined { let leadingComments: CommentRange[] | undefined; let currentDetachedCommentInfo: { nodePos: number; detachedCommentEndPos: number; } | undefined; if (removeComments) { @@ -11319,20 +11330,7 @@ export function findConstructorDeclaration(node: ClassLikeDeclaration): Construc } /** @internal */ -export function createNameResolver({ - compilerOptions, - requireSymbol, - argumentsSymbol, - error, - getSymbolOfDeclaration, - globals, - lookup, - setRequiresScopeChangeCache = returnUndefined, - getRequiresScopeChangeCache = returnUndefined, - onPropertyWithInvalidInitializer = returnFalse, - onFailedToResolveSymbol = returnUndefined, - onSuccessfullyResolvedSymbol = returnUndefined, -}: { +export interface NameResolverOptions { compilerOptions: CompilerOptions; getSymbolOfDeclaration: (node: Declaration) => Symbol; error: (location: Node | undefined, message: DiagnosticMessage, ...args: DiagnosticArguments) => void; @@ -11343,28 +11341,35 @@ export function createNameResolver({ setRequiresScopeChangeCache: undefined | ((node: FunctionLikeDeclaration, value: boolean) => void); getRequiresScopeChangeCache: undefined | ((node: FunctionLikeDeclaration) => boolean | undefined); onPropertyWithInvalidInitializer?: (location: Node | undefined, name: __String, declaration: PropertyDeclaration, result: Symbol | undefined) => boolean; - onFailedToResolveSymbol?: ( - location: Node | undefined, - name: __String | Identifier, - meaning: SymbolFlags, - nameNotFoundMessage: DiagnosticMessage, - ) => void; - onSuccessfullyResolvedSymbol?: ( - location: Node | undefined, - result: Symbol, - meaning: SymbolFlags, - lastLocation: Node | undefined, - associatedDeclarationForContainingInitializerOrBindingName: ParameterDeclaration | BindingElement | undefined, - withinDeferredContext: boolean, - ) => void; -}): ( + onFailedToResolveSymbol?: (location: Node | undefined, name: __String | Identifier, meaning: SymbolFlags, nameNotFoundMessage: DiagnosticMessage) => void; + onSuccessfullyResolvedSymbol?: (location: Node | undefined, result: Symbol, meaning: SymbolFlags, lastLocation: Node | undefined, associatedDeclarationForContainingInitializerOrBindingName: ParameterDeclaration | BindingElement | undefined, withinDeferredContext: boolean) => void; +} + +/** @internal */ +export type NameResolver = ( location: Node | undefined, nameArg: __String | Identifier, meaning: SymbolFlags, nameNotFoundMessage: DiagnosticMessage | undefined, isUse: boolean, excludeGlobals?: boolean, -) => Symbol | undefined { +) => Symbol | undefined; + +/** @internal */ +export function createNameResolver({ + compilerOptions, + requireSymbol, + argumentsSymbol, + error, + getSymbolOfDeclaration, + globals, + lookup, + setRequiresScopeChangeCache = returnUndefined, + getRequiresScopeChangeCache = returnUndefined, + onPropertyWithInvalidInitializer = returnFalse, + onFailedToResolveSymbol = returnUndefined, + onSuccessfullyResolvedSymbol = returnUndefined, +}: NameResolverOptions): NameResolver { /* eslint-disable no-var */ var isolatedModulesLikeFlagName = compilerOptions.verbatimModuleSyntax ? "verbatimModuleSyntax" : "isolatedModules"; /* eslint-disable no-var */ diff --git a/src/compiler/watch.ts b/src/compiler/watch.ts index b8d21491a517d..a859bcc60009d 100644 --- a/src/compiler/watch.ts +++ b/src/compiler/watch.ts @@ -639,7 +639,7 @@ export function emitFilesAndReportErrorsAndGetExitStatus void; - } | undefined { + public verifyCompletions(options: FourSlashInterface.VerifyCompletionsOptions): FourSlashInterface.CompletionsResult | undefined { if (options.marker === undefined) { return this.verifyCompletionsWorker(options); } diff --git a/src/harness/fourslashInterfaceImpl.ts b/src/harness/fourslashInterfaceImpl.ts index 707b8545d62a2..8af5de8cdc5ba 100644 --- a/src/harness/fourslashInterfaceImpl.ts +++ b/src/harness/fourslashInterfaceImpl.ts @@ -259,20 +259,22 @@ export class VerifyNegatable { } } +export interface CompletionsResult { + andApplyCodeAction: (options: { + name: string; + source: string; + description: string; + newFileContent?: string; + newRangeContent?: string; + }) => void; +} + export class Verify extends VerifyNegatable { constructor(state: FourSlash.TestState) { super(state); } - public completions(...optionsArray: VerifyCompletionsOptions[]): { - andApplyCodeAction: (options: { - name: string; - source: string; - description: string; - newFileContent?: string; - newRangeContent?: string; - }) => void; - } | undefined { + public completions(...optionsArray: VerifyCompletionsOptions[]): CompletionsResult | undefined { if (optionsArray.length === 1) { return this.state.verifyCompletions(optionsArray[0]); } diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index 1fe982b0d1229..4c9d3900ff824 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -489,7 +489,7 @@ export function tryConvertScriptKindName(scriptKindName: protocol.ScriptKindName return isString(scriptKindName) ? convertScriptKindName(scriptKindName) : scriptKindName; } -export function convertScriptKindName(scriptKindName: protocol.ScriptKindName): ScriptKind.Unknown | ScriptKind.JS | ScriptKind.JSX | ScriptKind.TS | ScriptKind.TSX { +export function convertScriptKindName(scriptKindName: protocol.ScriptKindName): ScriptKind { switch (scriptKindName) { case "JS": return ScriptKind.JS; diff --git a/src/server/project.ts b/src/server/project.ts index c0b58b93dfdd7..f662f4ffcbb00 100644 --- a/src/server/project.ts +++ b/src/server/project.ts @@ -149,6 +149,7 @@ import { Msg, NormalizedPath, nullTypingsInstaller, + PackageJsonCache, PackageJsonWatcher, ProjectOptions, ProjectService, @@ -1197,11 +1198,11 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo } /** @internal */ - getRootFilesMap(): Map { + getRootFilesMap(): Map { return this.rootFilesMap; } - getRootScriptInfos(): ts.server.ScriptInfo[] { + getRootScriptInfos(): ScriptInfo[] { return arrayFrom(ts.mapDefinedIterator(this.rootFilesMap.values(), value => value.info)); } @@ -1221,7 +1222,7 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo return emptyArray; } - getFileNames(excludeFilesFromExternalLibraries?: boolean, excludeConfigFiles?: boolean): ts.server.NormalizedPath[] { + getFileNames(excludeFilesFromExternalLibraries?: boolean, excludeConfigFiles?: boolean): NormalizedPath[] { if (!this.program) { return []; } @@ -1259,7 +1260,7 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo } /** @internal */ - getFileNamesWithRedirectInfo(includeProjectReferenceRedirectInfo: boolean): ts.server.protocol.FileWithProjectReferenceRedirectInfo[] { + getFileNamesWithRedirectInfo(includeProjectReferenceRedirectInfo: boolean): protocol.FileWithProjectReferenceRedirectInfo[] { return this.getFileNames().map((fileName): protocol.FileWithProjectReferenceRedirectInfo => ({ fileName, isSourceOfProjectReferenceRedirect: includeProjectReferenceRedirectInfo && this.isSourceOfProjectReferenceRedirect(fileName), @@ -1905,7 +1906,7 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo return scriptInfo; } - getScriptInfo(uncheckedFileName: string): ts.server.ScriptInfo | undefined { + getScriptInfo(uncheckedFileName: string): ScriptInfo | undefined { return this.projectService.getScriptInfo(uncheckedFileName); } @@ -2203,7 +2204,7 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo } /** @internal */ - getPackageJsonCache(): ts.server.PackageJsonCache { + getPackageJsonCache(): PackageJsonCache { return this.projectService.packageJsonCache; } @@ -2339,7 +2340,7 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo } /** @internal */ - getCompilerOptionsForNoDtsResolutionProject(): ts.CompilerOptions { + getCompilerOptionsForNoDtsResolutionProject(): CompilerOptions { return { ...this.getCompilerOptions(), noDtsResolution: true, @@ -3020,7 +3021,7 @@ export class ConfiguredProject extends Project { return this.directoryStructureHost as CachedDirectoryStructureHost; } - getConfigFilePath(): ts.server.NormalizedPath { + getConfigFilePath(): NormalizedPath { return asNormalizedPath(this.getProjectName()); } @@ -3169,7 +3170,7 @@ export class ExternalProject extends Project { return result; } - override getExcludedFiles(): readonly ts.server.NormalizedPath[] { + override getExcludedFiles(): readonly NormalizedPath[] { return this.excludedFiles; } } diff --git a/src/services/stringCompletions.ts b/src/services/stringCompletions.ts index f4e14d4ea0047..7c41dd5e103cf 100644 --- a/src/services/stringCompletions.ts +++ b/src/services/stringCompletions.ts @@ -298,7 +298,16 @@ function convertStringLiteralCompletions( } /** @internal */ -export function getStringLiteralCompletionDetails(name: string, sourceFile: SourceFile, position: number, contextToken: Node | undefined, program: Program, host: LanguageServiceHost, cancellationToken: CancellationToken, preferences: UserPreferences): CompletionEntryDetails | undefined { +export function getStringLiteralCompletionDetails( + name: string, + sourceFile: SourceFile, + position: number, + contextToken: Node | undefined, + program: Program, + host: LanguageServiceHost, + cancellationToken: CancellationToken, + preferences: UserPreferences, +): CompletionEntryDetails | undefined { if (!contextToken || !isStringLiteralLike(contextToken)) return undefined; const completions = getStringLiteralCompletionEntries(sourceFile, contextToken, position, program, host, preferences); return completions && stringLiteralCompletionDetails(name, contextToken, completions, sourceFile, program.getTypeChecker(), cancellationToken); diff --git a/src/services/symbolDisplay.ts b/src/services/symbolDisplay.ts index adcd705ff59c0..6c49848435e70 100644 --- a/src/services/symbolDisplay.ts +++ b/src/services/symbolDisplay.ts @@ -866,7 +866,15 @@ 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: SemanticMeaning = getMeaningFromLocation(location), alias?: Symbol): SymbolDisplayPartsDocumentationAndSymbolKind { +export function getSymbolDisplayPartsDocumentationAndSymbolKind( + typeChecker: TypeChecker, + symbol: Symbol, + sourceFile: SourceFile, + enclosingDeclaration: Node | undefined, + location: Node, + semanticMeaning: SemanticMeaning = getMeaningFromLocation(location), + alias?: Symbol, +): SymbolDisplayPartsDocumentationAndSymbolKind { return getSymbolDisplayPartsDocumentationAndSymbolKindWorker(typeChecker, symbol, sourceFile, enclosingDeclaration, location, /*type*/ undefined, semanticMeaning, alias); } diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index b36f22373e53d..304462086e8a8 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -2890,10 +2890,10 @@ declare namespace ts { isClosed(): boolean; hasRoots(): boolean; getRootFiles(): NormalizedPath[]; - getRootScriptInfos(): ts.server.ScriptInfo[]; + getRootScriptInfos(): ScriptInfo[]; getScriptInfos(): ScriptInfo[]; getExcludedFiles(): readonly NormalizedPath[]; - getFileNames(excludeFilesFromExternalLibraries?: boolean, excludeConfigFiles?: boolean): ts.server.NormalizedPath[]; + getFileNames(excludeFilesFromExternalLibraries?: boolean, excludeConfigFiles?: boolean): NormalizedPath[]; hasConfigFile(configFilePath: NormalizedPath): boolean; containsScriptInfo(info: ScriptInfo): boolean; containsFile(filename: NormalizedPath, requireOpen?: boolean): boolean; @@ -2918,7 +2918,7 @@ declare namespace ts { private isValidGeneratedFileWatcher; private clearGeneratedFileWatch; getScriptInfoForNormalizedPath(fileName: NormalizedPath): ScriptInfo | undefined; - getScriptInfo(uncheckedFileName: string): ts.server.ScriptInfo | undefined; + getScriptInfo(uncheckedFileName: string): ScriptInfo | undefined; filesToString(writeProjectFileNames: boolean): string; private filesToStringWorker; setCompilerOptions(compilerOptions: CompilerOptions): void; @@ -2973,7 +2973,7 @@ declare namespace ts { * @returns: true if set of files in the project stays the same and false - otherwise. */ updateGraph(): boolean; - getConfigFilePath(): ts.server.NormalizedPath; + getConfigFilePath(): NormalizedPath; getProjectReferences(): readonly ProjectReference[] | undefined; updateReferences(refs: readonly ProjectReference[] | undefined): void; /** @@ -2997,14 +2997,14 @@ declare namespace ts { compileOnSaveEnabled: boolean; excludedFiles: readonly NormalizedPath[]; updateGraph(): boolean; - getExcludedFiles(): readonly ts.server.NormalizedPath[]; + getExcludedFiles(): readonly 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 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; const maxProgramSizeForNonTsFiles: number; const ProjectsUpdatedInBackgroundEvent = "projectsUpdatedInBackground"; interface ProjectsUpdatedInBackgroundEvent { From 2bc5c904107f8bcec1d5ddc662ce5ecf65d7140c Mon Sep 17 00:00:00 2001 From: Isabel Duan Date: Thu, 12 Sep 2024 18:24:09 -0700 Subject: [PATCH 21/27] fix function --- src/compiler/moduleNameResolver.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/compiler/moduleNameResolver.ts b/src/compiler/moduleNameResolver.ts index bf64791da0005..879b65100ed56 100644 --- a/src/compiler/moduleNameResolver.ts +++ b/src/compiler/moduleNameResolver.ts @@ -3332,8 +3332,8 @@ function resolveFromTypeRoot(moduleName: string, state: ModuleResolutionState) { // Program errors validate that `noEmit` or `emitDeclarationOnly` is also set, // so this function doesn't check them to avoid propagating errors. /** @internal */ -export function shouldAllowImportingTsExtension(compilerOptions: CompilerOptions, fromFileName?: string): boolean | "" | undefined { - return !!compilerOptions.allowImportingTsExtensions || fromFileName && isDeclarationFileName(fromFileName); +export function shouldAllowImportingTsExtension(compilerOptions: CompilerOptions, fromFileName?: string): boolean | undefined { + return !!compilerOptions.allowImportingTsExtensions || (fromFileName !== undefined) && isDeclarationFileName(fromFileName); } /** From de60e62073e5de1d8cbf76e663be38ca34ba51e6 Mon Sep 17 00:00:00 2001 From: Isabel Duan Date: Thu, 12 Sep 2024 23:06:57 -0700 Subject: [PATCH 22/27] address comments, remove extra lines --- src/compiler/builder.ts | 2 +- src/compiler/moduleNameResolver.ts | 2 +- src/compiler/transformers/declarations.ts | 2 +- src/compiler/types.ts | 3 +-- src/services/exportInfoMap.ts | 2 +- 5 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/compiler/builder.ts b/src/compiler/builder.ts index 0fe55014a5f85..1c472cebead0d 100644 --- a/src/compiler/builder.ts +++ b/src/compiler/builder.ts @@ -8,6 +8,7 @@ import { BuilderProgramHost, BuilderState, BuildInfo, + BuildInfoFileVersionMap, CancellationToken, CommandLineOption, compareStringsCaseSensitive, @@ -89,7 +90,6 @@ import { WriteFileCallback, WriteFileCallbackData, } from "./_namespaces/ts.js"; -import { BuildInfoFileVersionMap } from "./types.js"; /** @internal */ export interface ReusableDiagnostic extends ReusableDiagnosticRelatedInformation { diff --git a/src/compiler/moduleNameResolver.ts b/src/compiler/moduleNameResolver.ts index 879b65100ed56..0c99662d8e59b 100644 --- a/src/compiler/moduleNameResolver.ts +++ b/src/compiler/moduleNameResolver.ts @@ -3333,7 +3333,7 @@ function resolveFromTypeRoot(moduleName: string, state: ModuleResolutionState) { // so this function doesn't check them to avoid propagating errors. /** @internal */ export function shouldAllowImportingTsExtension(compilerOptions: CompilerOptions, fromFileName?: string): boolean | undefined { - return !!compilerOptions.allowImportingTsExtensions || (fromFileName !== undefined) && isDeclarationFileName(fromFileName); + return !!compilerOptions.allowImportingTsExtensions || !!fromFileName && isDeclarationFileName(fromFileName); } /** diff --git a/src/compiler/transformers/declarations.ts b/src/compiler/transformers/declarations.ts index 5777a3395b3d3..9158d2ddca48f 100644 --- a/src/compiler/transformers/declarations.ts +++ b/src/compiler/transformers/declarations.ts @@ -30,6 +30,7 @@ import { DeclarationDiagnosticProducing, DeclarationName, declarationNameToString, + DeclarationTransformer, Diagnostics, DiagnosticWithLocation, EmitFlags, @@ -213,7 +214,6 @@ import { visitNodes, VisitResult, } from "../_namespaces/ts.js"; -import { DeclarationTransformer } from "../types.js"; /** @internal */ export function getDeclarationDiagnostics( diff --git a/src/compiler/types.ts b/src/compiler/types.ts index ec2aa28b019ff..7efdcf113d1c6 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -4967,7 +4967,6 @@ export interface EmitTransformers { } /** @internal */ - export interface DeclarationTransformer { (node: Bundle): Bundle; (node: SourceFile): SourceFile; @@ -10524,8 +10523,8 @@ export interface SyntacticTypeNodeBuilderResolver { requiresAddingImplicitUndefined(parameter: ParameterDeclaration | JSDocParameterTag, enclosingDeclaration: Node | undefined): boolean; isDefinitelyReferenceToGlobalSymbolObject(node: Node): boolean; } -/** @internal */ +/** @internal */ export interface SyntacticNodeBuilder { typeFromExpression: (node: Expression, context: SyntacticTypeNodeBuilderContext, isConstContext?: boolean, requiresAddingUndefined?: boolean, preserveLiterals?: boolean) => boolean | undefined; serializeTypeOfDeclaration: (node: HasInferredType, context: SyntacticTypeNodeBuilderContext) => boolean | undefined; diff --git a/src/services/exportInfoMap.ts b/src/services/exportInfoMap.ts index 9d07ba4b885bf..1bfa8ab018580 100644 --- a/src/services/exportInfoMap.ts +++ b/src/services/exportInfoMap.ts @@ -527,7 +527,7 @@ function getIsExcluded(excludePatterns: readonly RegExp[], host: LanguageService } /** @internal */ -export function getIsFileExcluded(host: LanguageServiceHost, preferences: UserPreferences): ({ fileName, path }: SourceFile) => boolean { +export function getIsFileExcluded(host: LanguageServiceHost, preferences: UserPreferences): (sourceFile: SourceFile) => boolean { if (!preferences.autoImportFileExcludePatterns) return () => false; return getIsExcluded(getIsExcludedPatterns(preferences, hostUsesCaseSensitiveFileNames(host)), host); } From 27bede69ee6b22ae3ffdc1790cc2f6bd7b0eb193 Mon Sep 17 00:00:00 2001 From: Isabel Duan Date: Thu, 12 Sep 2024 23:25:20 -0700 Subject: [PATCH 23/27] use languageFeatures index --- src/compiler/scanner.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/compiler/scanner.ts b/src/compiler/scanner.ts index 2f2a480300547..50e827c17bd24 100644 --- a/src/compiler/scanner.ts +++ b/src/compiler/scanner.ts @@ -21,6 +21,7 @@ import { KeywordSyntaxKind, LanguageFeatureMinimumTarget, LanguageVariant, + LanugageFeatures, LineAndCharacter, MapLike, parsePseudoBigInt, @@ -295,7 +296,7 @@ const charCodeToRegExpFlag = new Map([ [CharacterCodes.y, RegularExpressionFlags.Sticky], ]); -const regExpFlagToFirstAvailableLanguageVersion = new Map([ +const regExpFlagToFirstAvailableLanguageVersion = new Map([ [RegularExpressionFlags.HasIndices, LanguageFeatureMinimumTarget.RegularExpressionFlagsHasIndices], [RegularExpressionFlags.DotAll, LanguageFeatureMinimumTarget.RegularExpressionFlagsDotAll], [RegularExpressionFlags.Unicode, LanguageFeatureMinimumTarget.RegularExpressionFlagsUnicode], From f498dcb4b474f31fe8789c91f8c7ce0828a482e0 Mon Sep 17 00:00:00 2001 From: Isabel Duan Date: Fri, 13 Sep 2024 11:41:13 -0700 Subject: [PATCH 24/27] Update src/testRunner/unittests/helpers/contents.ts with options object Co-authored-by: Sheetal Nandi --- src/testRunner/unittests/helpers/contents.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/testRunner/unittests/helpers/contents.ts b/src/testRunner/unittests/helpers/contents.ts index 0baa1f850d2f2..780ca4b1d81ee 100644 --- a/src/testRunner/unittests/helpers/contents.ts +++ b/src/testRunner/unittests/helpers/contents.ts @@ -33,9 +33,6 @@ interface Symbol { } `; -export function getProjectConfigWithNodeNext(withNodeNext: boolean | undefined): { - module: string; - target: string; -} | undefined { +export function getProjectConfigWithNodeNext(withNodeNext: boolean | undefined): object | undefined { return withNodeNext ? { module: "nodenext", target: "es5" } : undefined; } From 1c559c483560875b2a0b2e91b2ac01642bf35a38 Mon Sep 17 00:00:00 2001 From: Andrew Branch Date: Fri, 13 Sep 2024 12:44:16 -0700 Subject: [PATCH 25/27] Simplify computed options --- src/compiler/commandLineParser.ts | 8 +- src/compiler/utilities.ts | 168 +++++++----------------------- 2 files changed, 39 insertions(+), 137 deletions(-) diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index 7ced116d86840..77cb6afd6e81d 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -2610,11 +2610,11 @@ export function convertToTSConfig(configParseResult: ParsedCommandLine, configFi const providedKeys = new Set(optionMap.keys()); const impliedCompilerOptions: Record = {}; for (const option in computedOptions) { - if (!providedKeys.has(option) && some(computedOptions[option as keyof typeof computedOptions].dependencies, dep => providedKeys.has(dep))) { - const implied = computedOptions[option as keyof typeof computedOptions].computeValue(configParseResult.options); - const defaultValue = computedOptions[option as keyof typeof computedOptions].computeValue({}); + if (!providedKeys.has(option) && some(computedOptions[option].dependencies, dep => providedKeys.has(dep))) { + const implied = computedOptions[option].computeValue(configParseResult.options); + const defaultValue = computedOptions[option].computeValue({}); if (implied !== defaultValue) { - impliedCompilerOptions[option] = computedOptions[option as keyof typeof computedOptions].computeValue(configParseResult.options); + impliedCompilerOptions[option] = computedOptions[option].computeValue(configParseResult.options); } } } diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index bb825bb1f5345..14d3597cf0161 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -67,6 +67,7 @@ import { compareValues, Comparison, CompilerOptions, + CompilerOptionsValue, ComputedPropertyName, computeLineAndCharacterOfPosition, computeLineOfPosition, @@ -8830,109 +8831,7 @@ function createComputedCompilerOptions) => boolean; - }; - allowSyntheticDefaultImports: { - dependencies: ("module" | "moduleResolution" | "target")[]; - computeValue: (compilerOptions: Pick) => boolean; - }; - alwaysStrict: { - dependencies: "strict"[]; - computeValue: (compilerOptions: Pick) => boolean; - }; - declaration: { - dependencies: "composite"[]; - computeValue: (compilerOptions: Pick) => boolean; - }; - declarationMap: { - dependencies: ("declaration" | "composite")[]; - computeValue: (compilerOptions: Pick) => boolean; - }; - isolatedModules: { - dependencies: "verbatimModuleSyntax"[]; - computeValue: (compilerOptions: Pick) => boolean; - }; - module: { - dependencies: "target"[]; - computeValue: (compilerOptions: Pick) => ModuleKind; - }; - moduleResolution: { - dependencies: ("module" | "target")[]; - computeValue: (compilerOptions: Pick) => ModuleResolutionKind; - }; - moduleDetection: { - dependencies: ("module" | "target")[]; - computeValue: (compilerOptions: Pick) => ModuleDetectionKind; - }; - noImplicitAny: { - dependencies: "strict"[]; - computeValue: (compilerOptions: Pick) => boolean; - }; - noImplicitThis: { - dependencies: "strict"[]; - computeValue: (compilerOptions: Pick) => boolean; - }; - preserveConstEnums: { - dependencies: ("isolatedModules" | "verbatimModuleSyntax")[]; - computeValue: (compilerOptions: Pick) => boolean; - }; - incremental: { - dependencies: "composite"[]; - computeValue: (compilerOptions: Pick) => boolean; - }; - resolvePackageJsonExports: { - dependencies: "moduleResolution"[]; - computeValue: (compilerOptions: Pick) => boolean; - }; - resolvePackageJsonImports: { - dependencies: ("moduleResolution" | "resolvePackageJsonExports")[]; - computeValue: (compilerOptions: Pick) => boolean; - }; - strictFunctionTypes: { - dependencies: "strict"[]; - computeValue: (compilerOptions: Pick) => boolean; - }; - strictBindCallApply: { - dependencies: "strict"[]; - computeValue: (compilerOptions: Pick) => boolean; - }; - strictNullChecks: { - dependencies: "strict"[]; - computeValue: (compilerOptions: Pick) => boolean; - }; - strictPropertyInitialization: { - dependencies: "strict"[]; - computeValue: (compilerOptions: Pick) => boolean; - }; - strictBuiltinIteratorReturn: { - dependencies: "strict"[]; - computeValue: (compilerOptions: Pick) => boolean; - }; - target: { - dependencies: "module"[]; - computeValue: (compilerOptions: Pick) => ScriptTarget; - }; - useUnknownInCatchVariables: { - dependencies: "strict"[]; - computeValue: (compilerOptions: Pick) => boolean; - }; - resolveJsonModule: { - dependencies: ("module" | "moduleResolution" | "target")[]; - computeValue: (compilerOptions: Pick) => boolean; - }; - esModuleInterop: { - dependencies: ("module" | "target")[]; - computeValue: (compilerOptions: Pick) => boolean; - }; - useDefineForClassFields: { - dependencies: ("module" | "target")[]; - computeValue: (compilerOptions: Pick) => boolean; - }; -} = createComputedCompilerOptions({ +const _computedOptions = createComputedCompilerOptions({ target: { dependencies: ["module"], computeValue: compilerOptions => { @@ -8948,7 +8847,7 @@ export const computedOptions: { computeValue: (compilerOptions): ModuleKind => { return typeof compilerOptions.module === "number" ? compilerOptions.module : - computedOptions.target.computeValue(compilerOptions) >= ScriptTarget.ES2015 ? ModuleKind.ES2015 : ModuleKind.CommonJS; + _computedOptions.target.computeValue(compilerOptions) >= ScriptTarget.ES2015 ? ModuleKind.ES2015 : ModuleKind.CommonJS; }, }, moduleResolution: { @@ -8956,7 +8855,7 @@ export const computedOptions: { computeValue: (compilerOptions): ModuleResolutionKind => { let moduleResolution = compilerOptions.moduleResolution; if (moduleResolution === undefined) { - switch (computedOptions.module.computeValue(compilerOptions)) { + switch (_computedOptions.module.computeValue(compilerOptions)) { case ModuleKind.CommonJS: moduleResolution = ModuleResolutionKind.Node10; break; @@ -8981,8 +8880,8 @@ export const computedOptions: { dependencies: ["module", "target"], computeValue: (compilerOptions): ModuleDetectionKind => { return compilerOptions.moduleDetection || - (computedOptions.module.computeValue(compilerOptions) === ModuleKind.Node16 || - computedOptions.module.computeValue(compilerOptions) === ModuleKind.NodeNext ? ModuleDetectionKind.Force : ModuleDetectionKind.Auto); + (_computedOptions.module.computeValue(compilerOptions) === ModuleKind.Node16 || + _computedOptions.module.computeValue(compilerOptions) === ModuleKind.NodeNext ? ModuleDetectionKind.Force : ModuleDetectionKind.Auto); }, }, isolatedModules: { @@ -8997,7 +8896,7 @@ export const computedOptions: { if (compilerOptions.esModuleInterop !== undefined) { return compilerOptions.esModuleInterop; } - switch (computedOptions.module.computeValue(compilerOptions)) { + switch (_computedOptions.module.computeValue(compilerOptions)) { case ModuleKind.Node16: case ModuleKind.NodeNext: case ModuleKind.Preserve: @@ -9012,15 +8911,15 @@ export const computedOptions: { if (compilerOptions.allowSyntheticDefaultImports !== undefined) { return compilerOptions.allowSyntheticDefaultImports; } - return computedOptions.esModuleInterop.computeValue(compilerOptions) - || computedOptions.module.computeValue(compilerOptions) === ModuleKind.System - || computedOptions.moduleResolution.computeValue(compilerOptions) === ModuleResolutionKind.Bundler; + return _computedOptions.esModuleInterop.computeValue(compilerOptions) + || _computedOptions.module.computeValue(compilerOptions) === ModuleKind.System + || _computedOptions.moduleResolution.computeValue(compilerOptions) === ModuleResolutionKind.Bundler; }, }, resolvePackageJsonExports: { dependencies: ["moduleResolution"], computeValue: (compilerOptions): boolean => { - const moduleResolution = computedOptions.moduleResolution.computeValue(compilerOptions); + const moduleResolution = _computedOptions.moduleResolution.computeValue(compilerOptions); if (!moduleResolutionSupportsPackageJsonExportsAndImports(moduleResolution)) { return false; } @@ -9039,7 +8938,7 @@ export const computedOptions: { resolvePackageJsonImports: { dependencies: ["moduleResolution", "resolvePackageJsonExports"], computeValue: (compilerOptions): boolean => { - const moduleResolution = computedOptions.moduleResolution.computeValue(compilerOptions); + const moduleResolution = _computedOptions.moduleResolution.computeValue(compilerOptions); if (!moduleResolutionSupportsPackageJsonExportsAndImports(moduleResolution)) { return false; } @@ -9061,7 +8960,7 @@ export const computedOptions: { if (compilerOptions.resolveJsonModule !== undefined) { return compilerOptions.resolveJsonModule; } - return computedOptions.moduleResolution.computeValue(compilerOptions) === ModuleResolutionKind.Bundler; + return _computedOptions.moduleResolution.computeValue(compilerOptions) === ModuleResolutionKind.Bundler; }, }, declaration: { @@ -9073,7 +8972,7 @@ export const computedOptions: { preserveConstEnums: { dependencies: ["isolatedModules", "verbatimModuleSyntax"], computeValue: (compilerOptions): boolean => { - return !!(compilerOptions.preserveConstEnums || computedOptions.isolatedModules.computeValue(compilerOptions)); + return !!(compilerOptions.preserveConstEnums || _computedOptions.isolatedModules.computeValue(compilerOptions)); }, }, incremental: { @@ -9085,7 +8984,7 @@ export const computedOptions: { declarationMap: { dependencies: ["declaration", "composite"], computeValue: (compilerOptions): boolean => { - return !!(compilerOptions.declarationMap && computedOptions.declaration.computeValue(compilerOptions)); + return !!(compilerOptions.declarationMap && _computedOptions.declaration.computeValue(compilerOptions)); }, }, allowJs: { @@ -9098,7 +8997,7 @@ export const computedOptions: { dependencies: ["target", "module"], computeValue: (compilerOptions): boolean => { return compilerOptions.useDefineForClassFields === undefined - ? computedOptions.target.computeValue(compilerOptions) >= ScriptTarget.ES2022 + ? _computedOptions.target.computeValue(compilerOptions) >= ScriptTarget.ES2022 : compilerOptions.useDefineForClassFields; }, }, @@ -9159,37 +9058,40 @@ export const computedOptions: { }); /** @internal */ -export const getEmitScriptTarget: (compilerOptions: Pick) => ScriptTarget = computedOptions.target.computeValue; +export const computedOptions: Record CompilerOptionsValue; }> = _computedOptions; + +/** @internal */ +export const getEmitScriptTarget: (compilerOptions: CompilerOptions) => ScriptTarget = _computedOptions.target.computeValue; /** @internal */ -export const getEmitModuleKind: (compilerOptions: Pick) => ModuleKind = computedOptions.module.computeValue; +export const getEmitModuleKind: (compilerOptions: Pick) => ModuleKind = _computedOptions.module.computeValue; /** @internal */ -export const getEmitModuleResolutionKind: (compilerOptions: Pick) => ModuleResolutionKind = computedOptions.moduleResolution.computeValue; +export const getEmitModuleResolutionKind: (compilerOptions: CompilerOptions) => ModuleResolutionKind = _computedOptions.moduleResolution.computeValue; /** @internal @knipignore */ -export const getEmitModuleDetectionKind: (compilerOptions: Pick) => ModuleDetectionKind = computedOptions.moduleDetection.computeValue; +export const getEmitModuleDetectionKind: (compilerOptions: CompilerOptions) => ModuleDetectionKind = _computedOptions.moduleDetection.computeValue; /** @internal */ -export const getIsolatedModules: (compilerOptions: Pick) => boolean = computedOptions.isolatedModules.computeValue; +export const getIsolatedModules: (compilerOptions: CompilerOptions) => boolean = _computedOptions.isolatedModules.computeValue; /** @internal */ -export const getESModuleInterop: (compilerOptions: Pick) => boolean = computedOptions.esModuleInterop.computeValue; +export const getESModuleInterop: (compilerOptions: CompilerOptions) => boolean = _computedOptions.esModuleInterop.computeValue; /** @internal */ -export const getAllowSyntheticDefaultImports: (compilerOptions: Pick) => boolean = computedOptions.allowSyntheticDefaultImports.computeValue; +export const getAllowSyntheticDefaultImports: (compilerOptions: CompilerOptions) => boolean = _computedOptions.allowSyntheticDefaultImports.computeValue; /** @internal */ -export const getResolvePackageJsonExports: (compilerOptions: Pick) => boolean = computedOptions.resolvePackageJsonExports.computeValue; +export const getResolvePackageJsonExports: (compilerOptions: CompilerOptions) => boolean = _computedOptions.resolvePackageJsonExports.computeValue; /** @internal */ -export const getResolvePackageJsonImports: (compilerOptions: Pick) => boolean = computedOptions.resolvePackageJsonImports.computeValue; +export const getResolvePackageJsonImports: (compilerOptions: CompilerOptions) => boolean = _computedOptions.resolvePackageJsonImports.computeValue; /** @internal */ -export const getResolveJsonModule: (compilerOptions: Pick) => boolean = computedOptions.resolveJsonModule.computeValue; +export const getResolveJsonModule: (compilerOptions: CompilerOptions) => boolean = _computedOptions.resolveJsonModule.computeValue; /** @internal */ -export const getEmitDeclarations: (compilerOptions: Pick) => boolean = computedOptions.declaration.computeValue; +export const getEmitDeclarations: (compilerOptions: CompilerOptions) => boolean = _computedOptions.declaration.computeValue; /** @internal */ -export const shouldPreserveConstEnums: (compilerOptions: Pick) => boolean = computedOptions.preserveConstEnums.computeValue; +export const shouldPreserveConstEnums: (compilerOptions: CompilerOptions) => boolean = _computedOptions.preserveConstEnums.computeValue; /** @internal */ -export const isIncrementalCompilation: (compilerOptions: Pick) => boolean = computedOptions.incremental.computeValue; +export const isIncrementalCompilation: (compilerOptions: CompilerOptions) => boolean = _computedOptions.incremental.computeValue; /** @internal */ -export const getAreDeclarationMapsEnabled: (compilerOptions: Pick) => boolean = computedOptions.declarationMap.computeValue; +export const getAreDeclarationMapsEnabled: (compilerOptions: CompilerOptions) => boolean = _computedOptions.declarationMap.computeValue; /** @internal */ -export const getAllowJSCompilerOption: (compilerOptions: Pick) => boolean = computedOptions.allowJs.computeValue; +export const getAllowJSCompilerOption: (compilerOptions: CompilerOptions) => boolean = _computedOptions.allowJs.computeValue; /** @internal */ -export const getUseDefineForClassFields: (compilerOptions: Pick) => boolean = computedOptions.useDefineForClassFields.computeValue; +export const getUseDefineForClassFields: (compilerOptions: CompilerOptions) => boolean = _computedOptions.useDefineForClassFields.computeValue; /** @internal */ export function emitModuleKindIsNonNodeESM(moduleKind: ModuleKind): boolean { From 6296b1489c08d53ae84f7c7a1f60e262a59fb90a Mon Sep 17 00:00:00 2001 From: Isabel Duan Date: Fri, 13 Sep 2024 13:57:29 -0700 Subject: [PATCH 26/27] remove eslint rule --- eslint.config.mjs | 1 + src/compiler/commandLineParser.ts | 4 ++-- src/compiler/utilities.ts | 6 +++--- src/compiler/utilitiesPublic.ts | 2 +- src/server/editorServices.ts | 6 +++--- src/server/project.ts | 8 ++++---- src/testRunner/unittests/helpers/tsserver.ts | 2 +- .../unittests/helpers/virtualFileSystemWithWatch.ts | 2 +- 8 files changed, 16 insertions(+), 15 deletions(-) diff --git a/eslint.config.mjs b/eslint.config.mjs index 9fd6276e584fc..bc30b791311be 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -118,6 +118,7 @@ export default tseslint.config( "@typescript-eslint/ban-ts-comment": "off", "@typescript-eslint/class-literal-property-style": "off", "@typescript-eslint/consistent-indexed-object-style": "off", + "@typescript-eslint/consistent-generic-constructors": "off", "@typescript-eslint/no-duplicate-enum-values": "off", "@typescript-eslint/no-empty-function": "off", "@typescript-eslint/no-namespace": "off", diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index 77cb6afd6e81d..830fb26370426 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -138,7 +138,7 @@ const jsxOptionMap = new Map(Object.entries({ })); /** @internal */ -export const inverseJsxOptionMap: Map = new Map(mapIterator(jsxOptionMap.entries(), ([key, value]: [string, JsxEmit]) => ["" + value, key] as const)); +export const inverseJsxOptionMap: Map = 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 @@ -256,7 +256,7 @@ export const libs: string[] = libEntries.map(entry => entry[0]); * * @internal */ -export const libMap: Map = new Map(libEntries); +export const libMap: Map = new Map(libEntries); // Watch related options diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 14d3597cf0161..c7ade289737ca 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -11917,13 +11917,13 @@ const unprefixedNodeCoreModulesList = [ ]; /** @internal */ -export const unprefixedNodeCoreModules: Set = new Set(unprefixedNodeCoreModulesList); +export const unprefixedNodeCoreModules: Set = new Set(unprefixedNodeCoreModulesList); // await fetch('https://nodejs.org/docs/latest/api/all.json').then(r => r.text()).then(t => // new Set(t.match(/(?<=')node:.+?(?=')/g)) // .difference(new Set(require('module').builtinModules.map(x => `node:${x}`)))) /** @internal */ -export const exclusivelyPrefixedNodeCoreModules: Set = new Set([ +export const exclusivelyPrefixedNodeCoreModules: Set = new Set([ "node:sea", "node:sqlite", "node:test", @@ -11931,7 +11931,7 @@ export const exclusivelyPrefixedNodeCoreModules: Set = new Set([ ]); /** @internal */ -export const nodeCoreModules: Set = new Set([ +export const nodeCoreModules: Set = new Set([ ...unprefixedNodeCoreModulesList, ...unprefixedNodeCoreModulesList.map(name => `node:${name}`), ...exclusivelyPrefixedNodeCoreModules, diff --git a/src/compiler/utilitiesPublic.ts b/src/compiler/utilitiesPublic.ts index e4788842a2df7..462ebc6da06d4 100644 --- a/src/compiler/utilitiesPublic.ts +++ b/src/compiler/utilitiesPublic.ts @@ -304,7 +304,7 @@ export function sortAndDeduplicateDiagnostics(diagnostics: } /** @internal */ -export const targetToLibMap: Map = new Map([ +export const targetToLibMap: Map = new Map([ [ScriptTarget.ESNext, "lib.esnext.full.d.ts"], [ScriptTarget.ES2023, "lib.es2023.full.d.ts"], [ScriptTarget.ES2022, "lib.es2022.full.d.ts"], diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index 4c9d3900ff824..ff54e74d4123e 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -1194,7 +1194,7 @@ export class ProjectService { /** * projects specified by a tsconfig.json file */ - readonly configuredProjects: Map = new Map(); + readonly configuredProjects: Map = new Map(); /** @internal */ readonly newInferredProjectName: () => string = createProjectNameFactoryWithCounter(makeInferredProjectName); /** @internal */ @@ -1204,7 +1204,7 @@ export class ProjectService { /** * Open files: with value being project root path, and key being Path of the file that is open */ - readonly openFiles: Map = new Map(); + readonly openFiles: Map = new Map(); /** Config files looked up and cached config files for open script info */ private readonly configFileForOpenFiles = new Map(); /** Set of open script infos that are root of inferred project */ @@ -1233,7 +1233,7 @@ export class ProjectService { * * @internal */ - readonly configFileExistenceInfoCache: Map = new Map(); + readonly configFileExistenceInfoCache: Map = new Map(); /** @internal */ readonly throttledOperations: ThrottledOperations; private readonly hostConfiguration: HostConfiguration; diff --git a/src/server/project.ts b/src/server/project.ts index f662f4ffcbb00..6df9e1aca3e4a 100644 --- a/src/server/project.ts +++ b/src/server/project.ts @@ -382,7 +382,7 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo * * @internal */ - cachedUnresolvedImportsPerFile: Map = new Map(); + cachedUnresolvedImportsPerFile: Map = new Map(); /** @internal */ lastCachedUnresolvedImportsList: SortedReadonlyArray | undefined; @@ -2027,8 +2027,8 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo info => info.isSourceOfProjectReferenceRedirect, ); - const added: Map = new Map(); - const removed: Map = new Map(); + const added: Map = new Map(); + const removed: Map = new Map(); const updated: string[] = updatedFileNames ? arrayFrom(updatedFileNames.keys()) : []; const updatedRedirects: protocol.FileWithProjectReferenceRedirectInfo[] = []; @@ -2868,7 +2868,7 @@ export class ConfiguredProject extends Project { pendingUpdateReason: string | undefined; /** @internal */ - openFileWatchTriggered: Map = new Map(); + openFileWatchTriggered: Map = new Map(); /** @internal */ canConfigFileJsonReportNoInputFiles = false; diff --git a/src/testRunner/unittests/helpers/tsserver.ts b/src/testRunner/unittests/helpers/tsserver.ts index a2a49e953178e..f8c5a4a81de7a 100644 --- a/src/testRunner/unittests/helpers/tsserver.ts +++ b/src/testRunner/unittests/helpers/tsserver.ts @@ -216,7 +216,7 @@ export class TestSession extends ts.server.Session { public override logger!: LoggerWithInMemoryLogs; public override readonly typingsInstaller!: TestTypingsInstallerAdapter; public serverCancellationToken: TestServerCancellationToken; - public watchChanges: Map = new Map(); + public watchChanges: Map = new Map(); constructor(optsOrHost: TestSessionConstructorOptions) { const opts = getTestSessionPartialOptionsAndHost(optsOrHost); diff --git a/src/testRunner/unittests/helpers/virtualFileSystemWithWatch.ts b/src/testRunner/unittests/helpers/virtualFileSystemWithWatch.ts index 525be1383f17e..f4cd771c092d4 100644 --- a/src/testRunner/unittests/helpers/virtualFileSystemWithWatch.ts +++ b/src/testRunner/unittests/helpers/virtualFileSystemWithWatch.ts @@ -210,7 +210,7 @@ interface CallbackData { time: number; } class Callbacks { - readonly map: Map = new Map(); + readonly map: Map = new Map(); private nextId = 1; invoke: (invokeKey?: number) => void = invokeKey => this.invokeWorker(invokeKey); private hasChanges = false; From bea72051e2b7a443b979b890b30ee9a38c79cf99 Mon Sep 17 00:00:00 2001 From: Isabel Duan Date: Fri, 13 Sep 2024 15:22:49 -0700 Subject: [PATCH 27/27] comments --- src/compiler/moduleNameResolver.ts | 2 +- src/compiler/program.ts | 4 ++-- src/compiler/sys.ts | 2 +- src/compiler/transformers/declarations.ts | 9 +++------ src/compiler/types.ts | 7 ------- src/server/editorServices.ts | 2 +- 6 files changed, 8 insertions(+), 18 deletions(-) diff --git a/src/compiler/moduleNameResolver.ts b/src/compiler/moduleNameResolver.ts index 0c99662d8e59b..aedc7beca8c47 100644 --- a/src/compiler/moduleNameResolver.ts +++ b/src/compiler/moduleNameResolver.ts @@ -3332,7 +3332,7 @@ function resolveFromTypeRoot(moduleName: string, state: ModuleResolutionState) { // Program errors validate that `noEmit` or `emitDeclarationOnly` is also set, // so this function doesn't check them to avoid propagating errors. /** @internal */ -export function shouldAllowImportingTsExtension(compilerOptions: CompilerOptions, fromFileName?: string): boolean | undefined { +export function shouldAllowImportingTsExtension(compilerOptions: CompilerOptions, fromFileName?: string): boolean { return !!compilerOptions.allowImportingTsExtensions || !!fromFileName && isDeclarationFileName(fromFileName); } diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 3dfcd0d2d69b8..ad18f43b29e35 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -993,7 +993,7 @@ function getEmitSyntaxForUsageLocationWorker(file: Pick void): ModuleKind.CommonJS | ModuleKind.ESNext | undefined { +export function getResolutionModeOverride(node: ImportAttributes | undefined, grammarErrorOnNode?: (node: Node, diagnostic: DiagnosticMessage) => void): ResolutionMode | undefined { if (!node) return undefined; if (length(node.elements) !== 1) { grammarErrorOnNode?.( @@ -1404,7 +1404,7 @@ export function getImpliedNodeFormatForFileWorker( packageJsonInfoCache: PackageJsonInfoCache | undefined, host: ModuleResolutionHost, options: CompilerOptions, -): ModuleKind.CommonJS | ModuleKind.ESNext | Partial | undefined { +): ResolutionMode | Partial | undefined { const moduleResolution = getEmitModuleResolutionKind(options); const shouldLookupFromPackageJson = ModuleResolutionKind.Node16 <= moduleResolution && moduleResolution <= ModuleResolutionKind.NodeNext || pathContainsNodeModules(fileName); diff --git a/src/compiler/sys.ts b/src/compiler/sys.ts index 15eac0bee07b4..f0414f26d24db 100644 --- a/src/compiler/sys.ts +++ b/src/compiler/sys.ts @@ -559,7 +559,7 @@ export function getFileWatcherEventKind(oldTime: number, newTime: number): FileW } /** @internal */ -export const ignoredPaths: string[] = ["/node_modules/.", "/.git", "/.#"]; +export const ignoredPaths: readonly string[] = ["/node_modules/.", "/.git", "/.#"]; let curSysLog: (s: string) => void = noop; diff --git a/src/compiler/transformers/declarations.ts b/src/compiler/transformers/declarations.ts index 9158d2ddca48f..ba19f34fe0af9 100644 --- a/src/compiler/transformers/declarations.ts +++ b/src/compiler/transformers/declarations.ts @@ -30,7 +30,6 @@ import { DeclarationDiagnosticProducing, DeclarationName, declarationNameToString, - DeclarationTransformer, Diagnostics, DiagnosticWithLocation, EmitFlags, @@ -197,6 +196,7 @@ import { SymbolTracker, SyntaxKind, TransformationContext, + Transformer, transformNodes, tryCast, TypeAliasDeclaration, @@ -254,7 +254,7 @@ const declarationEmitInternalNodeBuilderFlags = InternalNodeBuilderFlags.AllowUn * * @internal */ -export function transformDeclarations(context: TransformationContext): DeclarationTransformer { +export function transformDeclarations(context: TransformationContext): Transformer { const throwDiagnostic = () => Debug.fail("Diagnostic emitted without context"); let getSymbolAccessibilityDiagnostic: GetSymbolAccessibilityDiagnostic = throwDiagnostic; let needsDeclare = true; @@ -437,10 +437,7 @@ export function transformDeclarations(context: TransformationContext): Declarati return result; } - function transformRoot(node: Bundle): Bundle; - function transformRoot(node: SourceFile): SourceFile; - function transformRoot(node: SourceFile | Bundle): SourceFile | Bundle; - function transformRoot(node: SourceFile | Bundle) { + function transformRoot(node: SourceFile | Bundle): SourceFile | Bundle { if (node.kind === SyntaxKind.SourceFile && node.isDeclarationFile) { return node; } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 7efdcf113d1c6..590911b3f6e99 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -4966,13 +4966,6 @@ export interface EmitTransformers { declarationTransformers: readonly TransformerFactory[]; } -/** @internal */ -export interface DeclarationTransformer { - (node: Bundle): Bundle; - (node: SourceFile): SourceFile; - (node: SourceFile | Bundle): SourceFile | Bundle; -} - export interface SourceMapSpan { /** Line number in the .js file. */ emittedLine: number; diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index ff54e74d4123e..1a9e6ed5b920f 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -1161,7 +1161,7 @@ export class ProjectService { * * @internal */ - readonly filenameToScriptInfo: Map = new Map(); + readonly filenameToScriptInfo: Map = new Map(); private readonly nodeModulesWatchers = new Map(); /** * Contains all the deleted script info's version information so that