From 16b146f882cf8a16c3b3217b0641a7011e702229 Mon Sep 17 00:00:00 2001 From: Arthur Ozga Date: Mon, 28 Nov 2016 15:26:55 -0600 Subject: [PATCH] Use array instead of map --- ...sDoesntImplementInheritedAbstractMember.ts | 17 ++++--- .../fixClassIncorrectlyImplementsInterface.ts | 22 +++++---- src/services/codefixes/fixes.ts | 4 +- src/services/utilities.ts | 47 +++---------------- 4 files changed, 33 insertions(+), 57 deletions(-) diff --git a/src/services/codefixes/fixClassDoesntImplementInheritedAbstractMember.ts b/src/services/codefixes/fixClassDoesntImplementInheritedAbstractMember.ts index 65a6d4aba05..e91507a6140 100644 --- a/src/services/codefixes/fixClassDoesntImplementInheritedAbstractMember.ts +++ b/src/services/codefixes/fixClassDoesntImplementInheritedAbstractMember.ts @@ -13,14 +13,12 @@ namespace ts.codefix { const startPos = classDecl.members.pos; const InstantiatedExtendsType = checker.getTypeFromTypeReference(getClassExtendsHeritageClauseElement(classDecl)); + // Note that this is ultimately derived from a map indexed by symbol names, + // so duplicates cannot occur. const extendsSymbols = checker.getPropertiesOfType(InstantiatedExtendsType); - let extendsAbstractSymbolsMap = createMap(); - for (const symbol of extendsSymbols) { - extendsAbstractSymbolsMap[symbol.getName()] = symbol; - } - extendsAbstractSymbolsMap = filterAbstractAndNonPrivate(extendsAbstractSymbolsMap); + const abstractAndNonPrivateExtendsSymbols = extendsSymbols.filter(symbolPointsToNonPrivateAndAbstractMember); - const insertion = getMissingMembersInsertion(classDecl, extendsAbstractSymbolsMap, checker, context.newLineCharacter); + const insertion = getMissingMembersInsertion(classDecl, abstractAndNonPrivateExtendsSymbols, checker, context.newLineCharacter); if (insertion.length > 0) { return [{ @@ -37,6 +35,13 @@ namespace ts.codefix { } return undefined; + + function symbolPointsToNonPrivateAndAbstractMember(symbol: Symbol): boolean { + const decls = symbol.getDeclarations(); + Debug.assert(!!(decls && decls.length > 0)); + const flags = getModifierFlags(decls[0]); + return !(flags & ModifierFlags.Private) && !!(flags & ModifierFlags.Abstract); + } } }); } \ No newline at end of file diff --git a/src/services/codefixes/fixClassIncorrectlyImplementsInterface.ts b/src/services/codefixes/fixClassIncorrectlyImplementsInterface.ts index 902ccf96b62..605e362cae8 100644 --- a/src/services/codefixes/fixClassIncorrectlyImplementsInterface.ts +++ b/src/services/codefixes/fixClassIncorrectlyImplementsInterface.ts @@ -16,22 +16,28 @@ namespace ts.codefix { const startPos: number = classDecl.members.pos; const implementedTypeNodes = getClassImplementsHeritageClauseElements(classDecl); - const implementedTypes = implementedTypeNodes.map(checker.getTypeFromTypeReference); - const implementedTypeSymbols = implementedTypes.map(checker.getPropertiesOfType); const result: CodeAction[] = []; - for (const symbols of implementedTypeSymbols) { - const symbolMap = createMap(); - for (const symbol of symbols) { - symbolMap[symbol.getName()] = symbol; - } - const insertion = getMissingMembersInsertion(classDecl, filterNonPrivate(symbolMap), checker, context.newLineCharacter); + for (const implementedTypeNode of implementedTypeNodes) { + const implementedType = checker.getTypeFromTypeReference(implementedTypeNode); + // Note that this is ultimately derived from a map indexed by symbol names, + // so duplicates cannot occur. + const implementedTypeSymbols = checker.getPropertiesOfType(implementedType); + const nonPrivateMembers = implementedTypeSymbols.filter(symbolRefersToNonPrivateMember); + + const insertion = getMissingMembersInsertion(classDecl, nonPrivateMembers, checker, context.newLineCharacter); pushAction(result, insertion, getLocaleSpecificMessage(Diagnostics.Implement_interface_on_class)); } return result; + function symbolRefersToNonPrivateMember(symbol: Symbol): boolean { + const decls = symbol.getDeclarations(); + Debug.assert(!!(decls && decls.length > 0)); + return !(getModifierFlags(decls[0]) & ModifierFlags.Private); + } + function pushAction(result: CodeAction[], insertion: string, description: string): void { if (insertion && insertion.length) { const newAction: CodeAction = { diff --git a/src/services/codefixes/fixes.ts b/src/services/codefixes/fixes.ts index c04ff83f6fa..da6dcde16c3 100644 --- a/src/services/codefixes/fixes.ts +++ b/src/services/codefixes/fixes.ts @@ -3,6 +3,6 @@ /// /// /// -/// -/// +/// +/// diff --git a/src/services/utilities.ts b/src/services/utilities.ts index 58fc82d1d7f..863baeb5045 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -1362,51 +1362,16 @@ namespace ts { /** * Finds members of the resolved type that are missing in the class pointed to by class decl * and generates source code for the missing members. - * @param possiblyMissingSymbols The collection of symbols to filter. + * @param possiblyMissingSymbols The collection of symbols to filter and then get insertions for. */ - export function getMissingMembersInsertion(classDeclaration: ClassLikeDeclaration, possiblyMissingSymbols: Map, checker: TypeChecker, newlineChar: string): string { - const missingMembers = filterMissingMembers(possiblyMissingSymbols, classDeclaration.symbol.members); - return getInsertionsForMembers(missingMembers, classDeclaration, checker, newlineChar); - } + export function getMissingMembersInsertion(classDeclaration: ClassLikeDeclaration, possiblyMissingSymbols: Symbol[], checker: TypeChecker, newlineChar: string): string { + const classMembers = classDeclaration.symbol.members; + const missingMembers = possiblyMissingSymbols.filter(symbol => !(symbol.getName() in classMembers)); - /** - * Finds the symbols in source but not target, generating a new map with the differences. - */ - function filterMissingMembers(sourceSymbols: Map, targetSymbols: Map): Map { - const result: Map = createMap(); - for (const sourceName in sourceSymbols) { - if (!(sourceName in targetSymbols)) { - result[sourceName] = sourceSymbols[sourceName]; - } - } - return result; - } - - function filterSymbolMapByDeclaration(symbolMap: Map, pred: (decl: Declaration) => boolean): Map { - const result = createMap(); - for (const key in symbolMap) { - const declaration = symbolMap[key].getDeclarations(); - Debug.assert(!!(declaration && declaration.length)); - if (pred(declaration[0])) { - result[key] = symbolMap[key]; - } - } - return result; - } - - export function filterAbstractAndNonPrivate(symbolMap: Map) { - return filterSymbolMapByDeclaration(symbolMap, decl => !(getModifierFlags(decl) & ModifierFlags.Private) && !!(getModifierFlags(decl) & ModifierFlags.Abstract)); - } - - export function filterNonPrivate(symbolMap: Map) { - return filterSymbolMapByDeclaration(symbolMap, decl => !(getModifierFlags(decl) & ModifierFlags.Private)); - } - - function getInsertionsForMembers(symbolMap: MapLike, enclosingDeclaration: ClassLikeDeclaration, checker: TypeChecker, newlineChar: string): string { let insertion = ""; - for (const symbolName in symbolMap) { - insertion = insertion.concat(getInsertionForMemberSymbol(symbolMap[symbolName], enclosingDeclaration, checker, newlineChar)); + for (const symbol of missingMembers) { + insertion = insertion.concat(getInsertionForMemberSymbol(symbol, classDeclaration, checker, newlineChar)); } return insertion; }