From b9ae36cfbee88109cea0b4e035230f02e5e3a2f3 Mon Sep 17 00:00:00 2001 From: Arthur Ozga Date: Fri, 9 Dec 2016 13:25:58 -0800 Subject: [PATCH] Simplify index signature generation --- src/compiler/checker.ts | 21 ++++++++----- src/compiler/types.ts | 4 +-- .../fixClassIncorrectlyImplementsInterface.ts | 31 +++++++++---------- 3 files changed, 29 insertions(+), 27 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index f75ba15254b..862e3d4f932 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -2037,7 +2037,7 @@ namespace ts { return result; } - function indexSignatureToString(info: IndexInfo, kind: SyntaxKind, enclosingDeclaration?: Node): string { + function indexSignatureToString(info: IndexInfo, kind: IndexKind, enclosingDeclaration?: Node): string { const writer = getSingleLineStringWriter(); getSymbolDisplayBuilder().buildIndexSignatureDisplay(info, writer, kind, enclosingDeclaration); const result = writer.string(); @@ -2557,8 +2557,8 @@ namespace ts { writePunctuation(writer, SyntaxKind.SemicolonToken); writer.writeLine(); } - buildIndexSignatureDisplay(resolved.stringIndexInfo, writer, SyntaxKind.StringKeyword, enclosingDeclaration, globalFlags, symbolStack); - buildIndexSignatureDisplay(resolved.numberIndexInfo, writer, SyntaxKind.NumberKeyword, enclosingDeclaration, globalFlags, symbolStack); + buildIndexSignatureDisplay(resolved.stringIndexInfo, writer, IndexKind.String, enclosingDeclaration, globalFlags, symbolStack); + buildIndexSignatureDisplay(resolved.numberIndexInfo, writer, IndexKind.Number, enclosingDeclaration, globalFlags, symbolStack); for (const p of resolved.properties) { const t = getTypeOfSymbol(p); if (p.flags & (SymbolFlags.Function | SymbolFlags.Method) && !getPropertiesOfObjectType(t).length) { @@ -2791,10 +2791,7 @@ namespace ts { buildReturnTypeDisplay(signature, writer, enclosingDeclaration, flags, symbolStack); } - /** - * @param keyword The keyword for the type of IndexSignature. Must be one of SyntaxKind.NumberKeyword or SyntaxKind.StringKeyword. - */ - function buildIndexSignatureDisplay(info: IndexInfo, writer: SymbolWriter, keyword: SyntaxKind, enclosingDeclaration?: Node, globalFlags?: TypeFormatFlags, symbolStack?: Symbol[]) { + function buildIndexSignatureDisplay(info: IndexInfo, writer: SymbolWriter, kind: IndexKind, enclosingDeclaration?: Node, globalFlags?: TypeFormatFlags, symbolStack?: Symbol[]) { if (info) { if (info.isReadonly) { writeKeyword(writer, SyntaxKind.ReadonlyKeyword); @@ -2804,7 +2801,15 @@ namespace ts { writer.writeParameter(info.declaration ? declarationNameToString(info.declaration.parameters[0].name) : "x"); writePunctuation(writer, SyntaxKind.ColonToken); writeSpace(writer); - writeKeyword(writer, keyword); + switch (kind) { + case IndexKind.Number: + writeKeyword(writer, SyntaxKind.NumberKeyword); + break; + case IndexKind.String: + writeKeyword(writer, SyntaxKind.StringKeyword); + break; + } + writePunctuation(writer, SyntaxKind.CloseBracketToken); writePunctuation(writer, SyntaxKind.ColonToken); writeSpace(writer); diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 81b4005ae5e..dfb71e29540 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -2353,7 +2353,7 @@ namespace ts { getTypeAtLocation(node: Node): Type; getTypeFromTypeReference(node: TypeReferenceNode | ExpressionWithTypeArguments | JSDocTypeReference): Type; signatureToString(signature: Signature, enclosingDeclaration?: Node, flags?: TypeFormatFlags, kind?: SignatureKind): string; - indexSignatureToString(info: IndexInfo, kind: SyntaxKind, enclosingDeclaration?: Node): string; + indexSignatureToString(info: IndexInfo, kind: IndexKind, enclosingDeclaration?: Node): string; typeToString(type: Type, enclosingDeclaration?: Node, flags?: TypeFormatFlags): string; symbolToString(symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags): string; createSymbol(flags: SymbolFlags, name: string): Symbol; @@ -2398,7 +2398,7 @@ namespace ts { buildTypeDisplay(type: Type, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; buildSymbolDisplay(symbol: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, meaning?: SymbolFlags, flags?: SymbolFormatFlags): void; buildSignatureDisplay(signatures: Signature, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, kind?: SignatureKind): void; - buildIndexSignatureDisplay(info: IndexInfo, writer: SymbolWriter, keyword: SyntaxKind, enclosingDeclaration?: Node, globalFlags?: TypeFormatFlags, symbolStack?: Symbol[]): void; + buildIndexSignatureDisplay(info: IndexInfo, writer: SymbolWriter, kind: IndexKind, enclosingDeclaration?: Node, globalFlags?: TypeFormatFlags, symbolStack?: Symbol[]): void; buildParameterDisplay(parameter: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; buildTypeParameterDisplay(tp: TypeParameter, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; buildTypePredicateDisplay(predicate: TypePredicate, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; diff --git a/src/services/codefixes/fixClassIncorrectlyImplementsInterface.ts b/src/services/codefixes/fixClassIncorrectlyImplementsInterface.ts index 11db00eb43c..900b2c21720 100644 --- a/src/services/codefixes/fixClassIncorrectlyImplementsInterface.ts +++ b/src/services/codefixes/fixClassIncorrectlyImplementsInterface.ts @@ -22,29 +22,16 @@ namespace ts.codefix { const hasStringIndexSignature = !!checker.getIndexTypeOfType(classType, IndexKind.String); for (const implementedTypeNode of implementedTypeNodes) { - const implementedType = checker.getTypeFromTypeReference(implementedTypeNode) as InterfaceTypeWithDeclaredMembers; + const implementedType = checker.getTypeFromTypeReference(implementedTypeNode) as InterfaceType; // 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); - let insertion = ""; - - if (!hasNumericIndexSignature) { - const typeNumericIndexInfo = checker.getIndexInfoOfType(implementedType, IndexKind.Number); - if (typeNumericIndexInfo) { - insertion = checker.indexSignatureToString(typeNumericIndexInfo, SyntaxKind.NumberKeyword, classDecl); - } - } - - if (!hasStringIndexSignature) { - const typeStringIndexInfo = checker.getIndexInfoOfType(implementedType, IndexKind.String); - if (typeStringIndexInfo) { - insertion += checker.indexSignatureToString(typeStringIndexInfo, SyntaxKind.StringKeyword, classDecl); - } - } - + let insertion = getMissingIndexSignatureInsertion(implementedType, IndexKind.Number, classDecl, hasNumericIndexSignature); + insertion += getMissingIndexSignatureInsertion(implementedType, IndexKind.String, classDecl, hasStringIndexSignature); insertion += getMissingMembersInsertion(classDecl, nonPrivateMembers, checker, context.newLineCharacter); + const message = formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Implement_interface_0), [implementedTypeNode.getText()]); if (insertion) { pushAction(result, insertion, message); @@ -53,6 +40,16 @@ namespace ts.codefix { return result; + function getMissingIndexSignatureInsertion(type: InterfaceType, kind: IndexKind, enclosingDeclaration: ClassLikeDeclaration, hasIndexSigOfKind: boolean) { + if (!hasIndexSigOfKind) { + const IndexInfoOfKind = checker.getIndexInfoOfType(type, kind); + if (IndexInfoOfKind) { + return checker.indexSignatureToString(IndexInfoOfKind, kind, enclosingDeclaration); + } + } + return ""; + } + function symbolRefersToNonPrivateMember(symbol: Symbol): boolean { const decls = symbol.getDeclarations(); Debug.assert(!!(decls && decls.length > 0));