mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-26 21:05:54 -06:00
add missing index signature support
This commit is contained in:
parent
c1a41b9f3c
commit
2f51b363bf
@ -14,19 +14,37 @@ namespace ts.codefix {
|
||||
}
|
||||
|
||||
const startPos: number = classDecl.members.pos;
|
||||
|
||||
const classType = checker.getTypeAtLocation(classDecl);
|
||||
const implementedTypeNodes = getClassImplementsHeritageClauseElements(classDecl);
|
||||
|
||||
const result: CodeAction[] = [];
|
||||
|
||||
const hasNumericIndexSignature = !!checker.getIndexTypeOfType(classType, IndexKind.Number);
|
||||
const hasStringIndexSignature = !!checker.getIndexTypeOfType(classType, IndexKind.String);
|
||||
|
||||
for (const implementedTypeNode of implementedTypeNodes) {
|
||||
const implementedType = checker.getTypeFromTypeReference(implementedTypeNode);
|
||||
const implementedType = checker.getTypeFromTypeReference(implementedTypeNode) as InterfaceTypeWithDeclaredMembers;
|
||||
// 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);
|
||||
let insertion = "";
|
||||
|
||||
if (!hasNumericIndexSignature) {
|
||||
const typeNumericIndexInfo = implementedType.declaredNumberIndexInfo;
|
||||
if (typeNumericIndexInfo) {
|
||||
insertion = checker.indexSignatureToString(typeNumericIndexInfo, SyntaxKind.NumberKeyword, classDecl);
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasStringIndexSignature) {
|
||||
const typeStringIndexInfo = implementedType.declaredStringIndexInfo;
|
||||
if (typeStringIndexInfo) {
|
||||
insertion += checker.indexSignatureToString(typeStringIndexInfo, SyntaxKind.StringKeyword, classDecl);
|
||||
}
|
||||
}
|
||||
|
||||
insertion += getMissingMembersInsertion(classDecl, nonPrivateMembers, checker, context.newLineCharacter);
|
||||
const message = formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Implement_interface_0), [implementedTypeNode.getText()]);
|
||||
if (insertion) {
|
||||
pushAction(result, insertion, message);
|
||||
|
||||
@ -5,7 +5,7 @@ namespace ts.codefix {
|
||||
* 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 and then get insertions for.
|
||||
* @returns undefined iff there is no insertion available.
|
||||
* @returns Empty string iff there are no member insertions.
|
||||
*/
|
||||
export function getMissingMembersInsertion(classDeclaration: ClassLikeDeclaration, possiblyMissingSymbols: Symbol[], checker: TypeChecker, newlineChar: string): string {
|
||||
const classMembers = classDeclaration.symbol.members;
|
||||
@ -16,9 +16,12 @@ namespace ts.codefix {
|
||||
for (const symbol of missingMembers) {
|
||||
insertion = insertion.concat(getInsertionForMemberSymbol(symbol, classDeclaration, checker, newlineChar));
|
||||
}
|
||||
return insertion.length > 0 ? insertion : undefined;
|
||||
return insertion;
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns Empty string iff there we can't figure out a representation for `symbol` in `enclosingDeclaration`.
|
||||
*/
|
||||
function getInsertionForMemberSymbol(symbol: Symbol, enclosingDeclaration: ClassLikeDeclaration, checker: TypeChecker, newlineChar: string): string {
|
||||
// const name = symbol.getName();
|
||||
const type = checker.getTypeOfSymbolAtLocation(symbol, enclosingDeclaration);
|
||||
@ -28,8 +31,9 @@ namespace ts.codefix {
|
||||
}
|
||||
|
||||
const declaration = declarations[0] as Declaration;
|
||||
const name = declaration.name.getText();
|
||||
const name = declaration.name ? declaration.name.getText() : undefined;
|
||||
const visibility = getVisibilityPrefix(getModifierFlags(declaration));
|
||||
|
||||
switch (declaration.kind) {
|
||||
case SyntaxKind.GetAccessor:
|
||||
case SyntaxKind.SetAccessor:
|
||||
@ -77,14 +81,6 @@ namespace ts.codefix {
|
||||
result += `${visibility}${name}${sigString}${getMethodBodyStub(newlineChar)}`;
|
||||
|
||||
return result;
|
||||
case SyntaxKind.ComputedPropertyName:
|
||||
if (hasDynamicName(declaration)) {
|
||||
return "";
|
||||
}
|
||||
throw new Error("Not implemented, computed property name.");
|
||||
case SyntaxKind.IndexSignature:
|
||||
throw new Error("Not implemented.");
|
||||
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
//// [1](): string;
|
||||
//// [2]: boolean;
|
||||
//// }
|
||||
|
||||
////
|
||||
//// class C implements I {[| |]}
|
||||
|
||||
verify.rangeAfterCodeFix(`
|
||||
|
||||
@ -0,0 +1,14 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
|
||||
//// interface I {
|
||||
//// [x: number]: I;
|
||||
//// [y: string]: I;
|
||||
//// }
|
||||
////
|
||||
//// class C implements I {[| |]}
|
||||
|
||||
verify.rangeAfterCodeFix(`
|
||||
[x: number]: I;
|
||||
[y: string]: I;
|
||||
`);
|
||||
@ -0,0 +1,11 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
//// interface I4 {
|
||||
//// [x: string, y: number]: number;
|
||||
//// }
|
||||
////
|
||||
//// class C implements I {[| |]}
|
||||
|
||||
verify.not.codeFixAvailable();
|
||||
|
||||
|
||||
@ -0,0 +1,12 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
//// interface I {
|
||||
//// [x: number]: I;
|
||||
//// }
|
||||
////
|
||||
//// class C implements I {[|
|
||||
//// |]}
|
||||
|
||||
verify.rangeAfterCodeFix(`
|
||||
[x: number]: I;
|
||||
`);
|
||||
@ -0,0 +1,11 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
//// interface I {
|
||||
//// [x: string]: number;
|
||||
//// }
|
||||
////
|
||||
//// class C implements I {[| |]}
|
||||
|
||||
verify.rangeAfterCodeFix(`
|
||||
[x: string]: number;
|
||||
`);
|
||||
Loading…
x
Reference in New Issue
Block a user