Use array instead of map

This commit is contained in:
Arthur Ozga 2016-11-28 15:26:55 -06:00
parent 680af0f782
commit 16b146f882
4 changed files with 33 additions and 57 deletions

View File

@ -13,14 +13,12 @@ namespace ts.codefix {
const startPos = classDecl.members.pos;
const InstantiatedExtendsType = <InterfaceType>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<Symbol>();
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);
}
}
});
}

View File

@ -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<Symbol>();
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 = {

View File

@ -3,6 +3,6 @@
/// <reference path="fixClassSuperMustPrecedeThisAccess.ts" />
/// <reference path="fixConstructorForDerivedNeedSuperCall.ts" />
/// <reference path="fixExtendsInterfaceBecomesImplements.ts" />
///<reference path='unusedIdentifierFixes.ts' />
///<reference path='importFixes.ts' />
/// <reference path='unusedIdentifierFixes.ts' />
/// <reference path='importFixes.ts' />

View File

@ -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<Symbol>, 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<Symbol>, targetSymbols: Map<Symbol>): Map<Symbol> {
const result: Map<Symbol> = createMap<Symbol>();
for (const sourceName in sourceSymbols) {
if (!(sourceName in targetSymbols)) {
result[sourceName] = sourceSymbols[sourceName];
}
}
return result;
}
function filterSymbolMapByDeclaration(symbolMap: Map<Symbol>, pred: (decl: Declaration) => boolean): Map<Symbol> {
const result = createMap<Symbol>();
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<Symbol>) {
return filterSymbolMapByDeclaration(symbolMap, decl => !(getModifierFlags(decl) & ModifierFlags.Private) && !!(getModifierFlags(decl) & ModifierFlags.Abstract));
}
export function filterNonPrivate(symbolMap: Map<Symbol>) {
return filterSymbolMapByDeclaration(symbolMap, decl => !(getModifierFlags(decl) & ModifierFlags.Private));
}
function getInsertionsForMembers(symbolMap: MapLike<Symbol>, 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;
}