diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index 6bb5e981e0470..b3c10e3c84951 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -1,4 +1,5 @@ import { + addToSeen, AlternateModeDiagnostics, append, arrayFrom, @@ -2629,7 +2630,7 @@ 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].dependencies, dep => providedKeys.has(dep))) { + if (!providedKeys.has(option) && optionDependsOn(option, providedKeys)) { const implied = computedOptions[option].computeValue(configParseResult.options); const defaultValue = computedOptions[option].computeValue({}); if (implied !== defaultValue) { @@ -2641,6 +2642,18 @@ export function convertToTSConfig(configParseResult: ParsedCommandLine, configFi return config; } +function optionDependsOn(option: string, dependsOn: Set): boolean { + const seen = new Set(); + return optionDependsOnRecursive(option); + + function optionDependsOnRecursive(option: string): boolean { + if (addToSeen(seen, option)) { + return some(computedOptions[option]?.dependencies, dep => dependsOn.has(dep) || optionDependsOnRecursive(dep)); + } + return false; + } +} + /** @internal */ export function optionMapToObject(optionMap: Map): object { return Object.fromEntries(optionMap); diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index e7c719aeae1cb..f293167598c5c 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -8193,15 +8193,11 @@ export function getLastChild(node: Node): Node | undefined { * * @internal */ -export function addToSeen(seen: Map, key: K): boolean; -/** @internal */ -export function addToSeen(seen: Map, key: K, value: T): boolean; -/** @internal */ -export function addToSeen(seen: Map, key: K, value: T = true as any): boolean { +export function addToSeen(seen: Set, key: K): boolean { if (seen.has(key)) { return false; } - seen.set(key, value); + seen.add(key); return true; } diff --git a/src/loc/lcl/chs/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/chs/diagnosticMessages/diagnosticMessages.generated.json.lcl index 022e52596211f..9fc8214143d81 100644 --- a/src/loc/lcl/chs/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/chs/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -2784,11 +2784,11 @@ - + - + - + @@ -5040,11 +5040,11 @@ - + - + - + @@ -11548,7 +11548,7 @@ - + diff --git a/src/loc/lcl/cht/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/cht/diagnosticMessages/diagnosticMessages.generated.json.lcl index ecd0b0c37a253..29b5b6df78089 100644 --- a/src/loc/lcl/cht/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/cht/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -2784,11 +2784,11 @@ - + - + - + @@ -5040,11 +5040,11 @@ - + - + - + diff --git a/src/loc/lcl/csy/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/csy/diagnosticMessages/diagnosticMessages.generated.json.lcl index 8645686398b53..266ee953659d9 100644 --- a/src/loc/lcl/csy/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/csy/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -2793,11 +2793,11 @@ - + - + - + @@ -5049,11 +5049,11 @@ - + - + - + diff --git a/src/loc/lcl/deu/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/deu/diagnosticMessages/diagnosticMessages.generated.json.lcl index 9a29964da07c6..ba23d0392aac1 100644 --- a/src/loc/lcl/deu/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/deu/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -2781,11 +2781,11 @@ - + - + - + @@ -5037,11 +5037,11 @@ - + - + - + diff --git a/src/loc/lcl/esn/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/esn/diagnosticMessages/diagnosticMessages.generated.json.lcl index f67ad2e0c2cde..d7c8533e119d4 100644 --- a/src/loc/lcl/esn/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/esn/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -2796,11 +2796,11 @@ - + - + - + @@ -5052,9 +5052,9 @@ - + - + diff --git a/src/loc/lcl/fra/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/fra/diagnosticMessages/diagnosticMessages.generated.json.lcl index f42e1754622cd..97df1cdcaca7f 100644 --- a/src/loc/lcl/fra/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/fra/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -2796,11 +2796,11 @@ - + - + - + @@ -5052,11 +5052,11 @@ - + - + - + diff --git a/src/loc/lcl/ita/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/ita/diagnosticMessages/diagnosticMessages.generated.json.lcl index 994182cdd3044..a545736da880a 100644 --- a/src/loc/lcl/ita/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/ita/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -2784,11 +2784,11 @@ - + - + - + @@ -5040,9 +5040,9 @@ - + - + diff --git a/src/loc/lcl/jpn/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/jpn/diagnosticMessages/diagnosticMessages.generated.json.lcl index c60d588a467ff..4ac9ca5d2d18b 100644 --- a/src/loc/lcl/jpn/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/jpn/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -2784,11 +2784,11 @@ - + - + - + @@ -5040,9 +5040,9 @@ - + - + diff --git a/src/loc/lcl/kor/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/kor/diagnosticMessages/diagnosticMessages.generated.json.lcl index 581be53afacc9..0112bb4853d22 100644 --- a/src/loc/lcl/kor/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/kor/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -2784,11 +2784,11 @@ - + - + - + @@ -5040,9 +5040,9 @@ - + - + diff --git a/src/loc/lcl/plk/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/plk/diagnosticMessages/diagnosticMessages.generated.json.lcl index a349f251ecfd8..605b3c8049d88 100644 --- a/src/loc/lcl/plk/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/plk/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -2774,11 +2774,11 @@ - + - + - + @@ -5030,11 +5030,11 @@ - + - + - + diff --git a/src/loc/lcl/ptb/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/ptb/diagnosticMessages/diagnosticMessages.generated.json.lcl index 6ae46444d5970..4b9bb462fe834 100644 --- a/src/loc/lcl/ptb/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/ptb/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -2777,11 +2777,11 @@ - + - + - + @@ -5033,11 +5033,11 @@ - + - + - + @@ -7877,11 +7877,11 @@ - + - + - + @@ -8417,6 +8417,15 @@ + + + + + + + + + @@ -9833,6 +9842,15 @@ + + + + + + + + + @@ -10595,15 +10613,6 @@ - - - - - - - - - @@ -13049,6 +13058,15 @@ + + + + + + + + + @@ -15080,6 +15098,24 @@ + + + + + + + + + + + + + + + + + + @@ -15233,6 +15269,24 @@ + + + + + + + + + + + + + + + + + + @@ -15440,6 +15494,15 @@ + + + + + + + + + @@ -17015,6 +17078,15 @@ + + + + + + + + + diff --git a/src/loc/lcl/rus/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/rus/diagnosticMessages/diagnosticMessages.generated.json.lcl index 2b24dd9886909..a7e54d070f910 100644 --- a/src/loc/lcl/rus/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/rus/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -2783,11 +2783,11 @@ - + - + - + @@ -5039,9 +5039,9 @@ - + - + diff --git a/src/loc/lcl/trk/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/trk/diagnosticMessages/diagnosticMessages.generated.json.lcl index cc9de64248792..e6c4b5f4216e0 100644 --- a/src/loc/lcl/trk/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/trk/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -2777,11 +2777,11 @@ - + - + - + @@ -5033,11 +5033,11 @@ - + - + - + diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index ae25654acaf3a..23f8d844c9856 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -1297,7 +1297,7 @@ export class ProjectService { */ private readonly filenameToScriptInfoVersion = new Map(); // Set of all '.js' files ever opened. - private readonly allJsFilesForOpenFileTelemetry = new Map(); + private readonly allJsFilesForOpenFileTelemetry = new Set(); /** * Map to the real path of the infos diff --git a/src/services/codefixes/convertConstToLet.ts b/src/services/codefixes/convertConstToLet.ts index 8497cb2ee8053..9337c0819e26d 100644 --- a/src/services/codefixes/convertConstToLet.ts +++ b/src/services/codefixes/convertConstToLet.ts @@ -36,7 +36,7 @@ registerCodeFix({ }, getAllCodeActions: context => { const { program } = context; - const seen = new Map(); + const seen = new Set(); return createCombinedCodeActions(textChanges.ChangeTracker.with(context, changes => { eachDiagnostic(context, errorCodes, diag => { diff --git a/src/services/codefixes/convertToTypeOnlyExport.ts b/src/services/codefixes/convertToTypeOnlyExport.ts index 5f2e80f4c8481..c5f0d6b3d92ba 100644 --- a/src/services/codefixes/convertToTypeOnlyExport.ts +++ b/src/services/codefixes/convertToTypeOnlyExport.ts @@ -36,7 +36,7 @@ registerCodeFix({ }, fixIds: [fixId], getAllCodeActions: function getAllCodeActionsToConvertToTypeOnlyExport(context) { - const fixedExportDeclarations = new Map(); + const fixedExportDeclarations = new Set(); return codeFixAll(context, errorCodes, (changes, diag) => { const exportSpecifier = getExportSpecifierForDiagnosticSpan(diag, context.sourceFile); if (exportSpecifier && addToSeen(fixedExportDeclarations, getNodeId(exportSpecifier.parent.parent))) { diff --git a/src/services/codefixes/fixAddMissingConstraint.ts b/src/services/codefixes/fixAddMissingConstraint.ts index ba1e7aa0279c2..34c0bf9ab2bb5 100644 --- a/src/services/codefixes/fixAddMissingConstraint.ts +++ b/src/services/codefixes/fixAddMissingConstraint.ts @@ -63,7 +63,7 @@ registerCodeFix({ fixIds: [fixId], getAllCodeActions: context => { const { program, preferences, host } = context; - const seen = new Map(); + const seen = new Set(); return createCombinedCodeActions(textChanges.ChangeTracker.with(context, changes => { eachDiagnostic(context, errorCodes, diag => { diff --git a/src/services/codefixes/fixAddMissingMember.ts b/src/services/codefixes/fixAddMissingMember.ts index 87f931a62b145..f448482e4ed9a 100644 --- a/src/services/codefixes/fixAddMissingMember.ts +++ b/src/services/codefixes/fixAddMissingMember.ts @@ -182,7 +182,7 @@ registerCodeFix({ getAllCodeActions: context => { const { program, fixId } = context; const checker = program.getTypeChecker(); - const seen = new Map(); + const seen = new Set(); const typeDeclToMembers = new Map(); return createCombinedCodeActions(textChanges.ChangeTracker.with(context, changes => { diff --git a/src/services/codefixes/fixAwaitInSyncFunction.ts b/src/services/codefixes/fixAwaitInSyncFunction.ts index d6b5d766caf12..ffcbeaed776ab 100644 --- a/src/services/codefixes/fixAwaitInSyncFunction.ts +++ b/src/services/codefixes/fixAwaitInSyncFunction.ts @@ -44,7 +44,7 @@ registerCodeFix({ }, fixIds: [fixId], getAllCodeActions: function getAllCodeActionsToFixAwaitInSyncFunction(context) { - const seen = new Map(); + const seen = new Set(); return codeFixAll(context, errorCodes, (changes, diag) => { const nodes = getNodes(diag.file, diag.start); if (!nodes || !addToSeen(seen, getNodeId(nodes.insertBefore))) return; diff --git a/src/services/codefixes/fixClassDoesntImplementInheritedAbstractMember.ts b/src/services/codefixes/fixClassDoesntImplementInheritedAbstractMember.ts index 8f77976267f1b..5ebecd78f1c96 100644 --- a/src/services/codefixes/fixClassDoesntImplementInheritedAbstractMember.ts +++ b/src/services/codefixes/fixClassDoesntImplementInheritedAbstractMember.ts @@ -44,7 +44,7 @@ registerCodeFix({ }, fixIds: [fixId], getAllCodeActions: function getAllCodeActionsToFixClassDoesntImplementInheritedAbstractMember(context) { - const seenClassDeclarations = new Map(); + const seenClassDeclarations = new Set(); return codeFixAll(context, errorCodes, (changes, diag) => { const classDeclaration = getClass(diag.file, diag.start); if (addToSeen(seenClassDeclarations, getNodeId(classDeclaration))) { diff --git a/src/services/codefixes/fixClassIncorrectlyImplementsInterface.ts b/src/services/codefixes/fixClassIncorrectlyImplementsInterface.ts index a0dd5aa5e5899..49298f9058053 100644 --- a/src/services/codefixes/fixClassIncorrectlyImplementsInterface.ts +++ b/src/services/codefixes/fixClassIncorrectlyImplementsInterface.ts @@ -55,7 +55,7 @@ registerCodeFix({ }, fixIds: [fixId], getAllCodeActions(context) { - const seenClassDeclarations = new Map(); + const seenClassDeclarations = new Set(); return codeFixAll(context, errorCodes, (changes, diag) => { const classDeclaration = getClass(diag.file, diag.start); if (addToSeen(seenClassDeclarations, getNodeId(classDeclaration))) { diff --git a/src/services/codefixes/fixClassSuperMustPrecedeThisAccess.ts b/src/services/codefixes/fixClassSuperMustPrecedeThisAccess.ts index a3585ace24d79..cf54c1c3d4753 100644 --- a/src/services/codefixes/fixClassSuperMustPrecedeThisAccess.ts +++ b/src/services/codefixes/fixClassSuperMustPrecedeThisAccess.ts @@ -38,7 +38,7 @@ registerCodeFix({ fixIds: [fixId], getAllCodeActions(context) { const { sourceFile } = context; - const seenClasses = new Map(); // Ensure we only do this once per class. + const seenClasses = new Set(); // Ensure we only do this once per class. return codeFixAll(context, errorCodes, (changes, diag) => { const nodes = getNodes(diag.file, diag.start); if (!nodes) return; diff --git a/src/services/completions.ts b/src/services/completions.ts index 05bd0275f32bb..e05e06844366f 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -3592,7 +3592,7 @@ function getCompletionData( let importSpecifierResolver: codefix.ImportSpecifierResolver | undefined; const symbolToOriginInfoMap: SymbolOriginInfoMap = []; const symbolToSortTextMap: SymbolSortTextMap = []; - const seenPropertySymbols = new Map(); + const seenPropertySymbols = new Set(); const isTypeOnlyLocation = isTypeOnlyCompletion(); const getModuleSpecifierResolutionHost = memoizeOne((isFromPackageJson: boolean) => { return createModuleSpecifierResolutionHost(isFromPackageJson ? host.getPackageJsonAutoImportProvider!()! : program, host); @@ -6058,14 +6058,14 @@ function isArrowFunctionBody(node: Node) { } /** True if symbol is a type or a module containing at least one type. */ -function symbolCanBeReferencedAtTypeLocation(symbol: Symbol, checker: TypeChecker, seenModules = new Map()): boolean { +function symbolCanBeReferencedAtTypeLocation(symbol: Symbol, checker: TypeChecker, seenModules = new Set()): boolean { // Since an alias can be merged with a local declaration, we need to test both the alias and its target. // This code used to just test the result of `skipAlias`, but that would ignore any locally introduced meanings. return nonAliasCanBeReferencedAtTypeLocation(symbol) || nonAliasCanBeReferencedAtTypeLocation(skipAlias(symbol.exportSymbol || symbol, checker)); function nonAliasCanBeReferencedAtTypeLocation(symbol: Symbol): boolean { return !!(symbol.flags & SymbolFlags.Type) || checker.isUnknownSymbol(symbol) || - !!(symbol.flags & SymbolFlags.Module) && addToSeen(seenModules, getSymbolId(symbol)) && + !!(symbol.flags & SymbolFlags.Module) && addToSeen(seenModules, symbol) && checker.getExportsOfModule(symbol).some(e => symbolCanBeReferencedAtTypeLocation(e, checker, seenModules)); } } diff --git a/src/services/exportInfoMap.ts b/src/services/exportInfoMap.ts index acfb3765c7ca2..f1f88c6ad42ef 100644 --- a/src/services/exportInfoMap.ts +++ b/src/services/exportInfoMap.ts @@ -555,7 +555,7 @@ export function getExportInfoMap(importingFile: SourceFile | FutureSourceFile, h try { forEachExternalModuleToImportFrom(program, host, preferences, /*useAutoImportProvider*/ true, (moduleSymbol, moduleFile, program, isFromPackageJson) => { if (++moduleCount % 100 === 0) cancellationToken?.throwIfCancellationRequested(); - const seenExports = new Map<__String, true>(); + const seenExports = new Set<__String>(); const checker = program.getTypeChecker(); const defaultInfo = getDefaultLikeExportInfo(moduleSymbol, checker); // Note: I think we shouldn't actually see resolved module symbols here, but weird merges @@ -634,7 +634,7 @@ function getNamesForExportedSymbol(defaultExport: Symbol, checker: TypeChecker, export function forEachNameOfDefaultExport(defaultExport: Symbol, checker: TypeChecker, scriptTarget: ScriptTarget | undefined, cb: (name: string, capitalizedName?: string) => T | undefined): T | undefined { let chain: Symbol[] | undefined; let current: Symbol | undefined = defaultExport; - const seen = new Map(); + const seen = new Set(); while (current) { // The predecessor to this function also looked for a name on the `localSymbol` diff --git a/src/services/findAllReferences.ts b/src/services/findAllReferences.ts index 74aeb9c5be05c..710a01b1c2dea 100644 --- a/src/services/findAllReferences.ts +++ b/src/services/findAllReferences.ts @@ -251,7 +251,6 @@ import { SymbolDisplayPart, SymbolDisplayPartKind, SymbolFlags, - SymbolId, symbolName, SyntaxKind, textPart, @@ -544,7 +543,7 @@ export function getImplementationsAtPosition(program: Program, cancellationToken } else if (entries) { const queue = createQueue(entries); - const seenNodes = new Map(); + const seenNodes = new Set(); while (!queue.isEmpty()) { const entry = queue.dequeue() as NodeEntry; if (!addToSeen(seenNodes, getNodeId(entry.node))) { @@ -2666,7 +2665,7 @@ export namespace Core { * The value of previousIterationSymbol is undefined when the function is first called. */ function getPropertySymbolsFromBaseTypes(symbol: Symbol, propertyName: string, checker: TypeChecker, cb: (symbol: Symbol) => T | undefined): T | undefined { - const seen = new Map(); + const seen = new Set(); return recur(symbol); function recur(symbol: Symbol): T | undefined { @@ -2674,7 +2673,7 @@ export namespace Core { // interface C extends C { // /*findRef*/propName: string; // } - if (!(symbol.flags & (SymbolFlags.Class | SymbolFlags.Interface)) || !addToSeen(seen, getSymbolId(symbol))) return; + if (!(symbol.flags & (SymbolFlags.Class | SymbolFlags.Interface)) || !addToSeen(seen, symbol)) return; return firstDefined(symbol.declarations, declaration => firstDefined(getAllSuperTypeNodes(declaration), typeReference => { diff --git a/src/services/refactors/extractType.ts b/src/services/refactors/extractType.ts index b6f4c97b55a5d..5201313f97288 100644 --- a/src/services/refactors/extractType.ts +++ b/src/services/refactors/extractType.ts @@ -247,7 +247,7 @@ function flattenTypeLiteralNodeReference(checker: TypeChecker, selection: TypeNo } if (isIntersectionTypeNode(selection)) { const result: TypeElement[] = []; - const seen = new Map(); + const seen = new Set(); for (const type of selection.types) { const flattenedTypeMembers = flattenTypeLiteralNodeReference(checker, type); if (!flattenedTypeMembers || !flattenedTypeMembers.every(type => type.name && addToSeen(seen, getNameFromPropertyName(type.name) as string))) { diff --git a/src/services/stringCompletions.ts b/src/services/stringCompletions.ts index 7c41dd5e103cf..b5cf950c337ae 100644 --- a/src/services/stringCompletions.ts +++ b/src/services/stringCompletions.ts @@ -555,7 +555,7 @@ function getAlreadyUsedTypesInStringLiteralUnion(union: UnionTypeNode, current: function getStringLiteralCompletionsFromSignature(call: CallLikeExpression, arg: StringLiteralLike, argumentInfo: SignatureHelp.ArgumentInfoForCompletions, checker: TypeChecker): StringLiteralCompletionsFromTypes | undefined { let isNewIdentifier = false; - const uniques = new Map(); + const uniques = new Set(); const editingArgument = isJsxOpeningLikeElement(call) ? Debug.checkDefined(findAncestor(arg.parent, isJsxAttribute)) : arg; const candidates = checker.getCandidateSignaturesForStringLiteralCompletions(call, editingArgument); const types = flatMap(candidates, candidate => { @@ -600,7 +600,7 @@ function stringLiteralCompletionsForObjectLiteral(checker: TypeChecker, objectLi }; } -function getStringLiteralTypes(type: Type | undefined, uniques = new Map()): readonly StringLiteralType[] { +function getStringLiteralTypes(type: Type | undefined, uniques = new Set()): readonly StringLiteralType[] { if (!type) return emptyArray; type = skipConstraint(type); return type.isUnion() ? flatMap(type.types, t => getStringLiteralTypes(t, uniques)) : diff --git a/src/services/textChanges.ts b/src/services/textChanges.ts index e73da8490b683..196f5389555b6 100644 --- a/src/services/textChanges.ts +++ b/src/services/textChanges.ts @@ -1,5 +1,4 @@ import { - addToSeen, ArrowFunction, BindingElement, CharacterCodes, @@ -493,7 +492,7 @@ export function isThisTypeAnnotatable(containingFunction: SignatureDeclaration): export class ChangeTracker { private readonly changes: Change[] = []; private newFileChanges?: MultiMap; - private readonly classesWithNodesInsertedAtStart = new Map(); // Set implemented as Map + private readonly classesWithNodesInsertedAtStart = new Map(); // Set implemented as Map private readonly deletedNodes: { readonly sourceFile: SourceFile; readonly node: Node | NodeArray; }[] = []; public static fromContext(context: TextChangesContext): ChangeTracker { @@ -903,7 +902,10 @@ export class ChangeTracker { const members = getMembersOrProperties(node); const isEmpty = members.length === 0; - const isFirstInsertion = addToSeen(this.classesWithNodesInsertedAtStart, getNodeId(node), { node, sourceFile }); + const isFirstInsertion = !this.classesWithNodesInsertedAtStart.has(getNodeId(node)); + if (isFirstInsertion) { + this.classesWithNodesInsertedAtStart.set(getNodeId(node), { node, sourceFile }); + } const insertTrailingComma = isObjectLiteralExpression(node) && (!isJsonSourceFile(sourceFile) || !isEmpty); const insertLeadingComma = isObjectLiteralExpression(node) && isJsonSourceFile(sourceFile) && isEmpty && !isFirstInsertion; return { @@ -1246,7 +1248,7 @@ function endPositionToDeleteNodeInList(sourceFile: SourceFile, node: Node, prevN return end; } -function getClassOrObjectBraceEnds(cls: ClassLikeDeclaration | InterfaceDeclaration | ObjectLiteralExpression, sourceFile: SourceFile): [number | undefined, number | undefined] { +function getClassOrObjectBraceEnds(cls: ClassLikeDeclaration | InterfaceDeclaration | ObjectLiteralExpression | TypeLiteralNode | EnumDeclaration, sourceFile: SourceFile): [number | undefined, number | undefined] { const open = findChildOfKind(cls, SyntaxKind.OpenBraceToken, sourceFile); const close = findChildOfKind(cls, SyntaxKind.CloseBraceToken, sourceFile); return [open?.end, close?.end]; diff --git a/src/testRunner/unittests/config/showConfig.ts b/src/testRunner/unittests/config/showConfig.ts index 350b18c06edd8..9000ce035cb62 100644 --- a/src/testRunner/unittests/config/showConfig.ts +++ b/src/testRunner/unittests/config/showConfig.ts @@ -57,6 +57,8 @@ describe("unittests:: config:: showConfig", () => { showTSConfigCorrectly("Show TSConfig with advanced options", ["--showConfig", "--declaration", "--declarationDir", "lib", "--skipLibCheck", "--noErrorTruncation"]); + showTSConfigCorrectly("Show TSConfig with transitively implied options", ["--showConfig", "--module", "nodenext"]); + showTSConfigCorrectly("Show TSConfig with compileOnSave and more", ["-p", "tsconfig.json"], { compilerOptions: { esModuleInterop: true, diff --git a/tests/baselines/reference/config/showConfig/Show TSConfig with transitively implied options/tsconfig.json b/tests/baselines/reference/config/showConfig/Show TSConfig with transitively implied options/tsconfig.json new file mode 100644 index 0000000000000..3afdb1cd6278d --- /dev/null +++ b/tests/baselines/reference/config/showConfig/Show TSConfig with transitively implied options/tsconfig.json @@ -0,0 +1,13 @@ +{ + "compilerOptions": { + "module": "nodenext", + "target": "esnext", + "moduleResolution": "nodenext", + "moduleDetection": "force", + "esModuleInterop": true, + "allowSyntheticDefaultImports": true, + "resolvePackageJsonExports": true, + "resolvePackageJsonImports": true, + "useDefineForClassFields": true + } +}