diff --git a/src/services/codefixes/helpers.ts b/src/services/codefixes/helpers.ts
index 7e4cf36f1f0..ef0ca1a9a57 100644
--- a/src/services/codefixes/helpers.ts
+++ b/src/services/codefixes/helpers.ts
@@ -20,15 +20,17 @@ namespace ts.codefix {
}
function getInsertionForMemberSymbol(symbol: Symbol, enclosingDeclaration: ClassLikeDeclaration, checker: TypeChecker, newlineChar: string): string {
- const name = symbol.getName();
+ // const name = symbol.getName();
const type = checker.getTypeOfSymbolAtLocation(symbol, enclosingDeclaration);
const declarations = symbol.getDeclarations();
if (!(declarations && declarations.length)) {
return "";
}
- const node = declarations[0];
- const visibility = getVisibilityPrefix(getModifierFlags(node));
- switch (node.kind) {
+
+ const declaration = declarations[0] as Declaration;
+ const name = declaration.name.getText();
+ const visibility = getVisibilityPrefix(getModifierFlags(declaration));
+ switch (declaration.kind) {
case SyntaxKind.GetAccessor:
case SyntaxKind.SetAccessor:
case SyntaxKind.PropertySignature:
@@ -68,14 +70,15 @@ namespace ts.codefix {
bodySig = checker.getSignatureFromDeclaration(declarations[declarations.length - 1] as SignatureDeclaration);
}
else {
- bodySig = createBodyDeclarationSignatureWithAnyTypes(declarations as SignatureDeclaration[], signatures, enclosingDeclaration, checker);
+ Debug.assert(declarations.length === signatures.length);
+ bodySig = createBodySignatureWithAnyTypes(signatures, enclosingDeclaration, checker);
}
const sigString = checker.signatureToString(bodySig, enclosingDeclaration, TypeFormatFlags.SuppressAnyReturnType, SignatureKind.Call);
result += `${visibility}${name}${sigString}${getMethodBodyStub(newlineChar)}`;
return result;
case SyntaxKind.ComputedPropertyName:
- if (hasDynamicName(node)) {
+ if (hasDynamicName(declaration)) {
return "";
}
throw new Error("Not implemented, computed property name.");
@@ -87,22 +90,25 @@ namespace ts.codefix {
}
}
- function createBodyDeclarationSignatureWithAnyTypes(signatureDecls: SignatureDeclaration[], signatures: Signature[], enclosingDeclaration: ClassLikeDeclaration, checker: TypeChecker): Signature {
- Debug.assert(signatureDecls.length === signatures.length);
+ function createBodySignatureWithAnyTypes(signatures: Signature[], enclosingDeclaration: ClassLikeDeclaration, checker: TypeChecker): Signature {
const newSignatureDeclaration = createNode(SyntaxKind.CallSignature) as SignatureDeclaration;
newSignatureDeclaration.parent = enclosingDeclaration;
- newSignatureDeclaration.name = signatureDecls[0].name;
+ newSignatureDeclaration.name = signatures[0].getDeclaration().name;
- let maxArgs = -1, maxArgsIndex = 0;
+ let maxArgs = -1;
let minArgumentCount = signatures[0].minArgumentCount;
let hasRestParameter = false;
+ let allMaxArgsAreRest = true;
for (let i = 0; i < signatures.length; i++) {
const sig = signatures[i];
minArgumentCount = Math.min(sig.minArgumentCount, minArgumentCount);
if (sig.parameters.length > maxArgs) {
maxArgs = sig.parameters.length;
- maxArgsIndex = i;
+ allMaxArgsAreRest = sig.hasRestParameter;
+ }
+ else if (sig.parameters.length === maxArgs) {
+ allMaxArgsAreRest = allMaxArgsAreRest && sig.hasRestParameter;
}
hasRestParameter = hasRestParameter || sig.hasRestParameter;
}
@@ -120,10 +126,6 @@ namespace ts.codefix {
if (hasRestParameter) {
lastParameter.dotDotDotToken = createToken(SyntaxKind.DotDotDotToken);
- let allMaxArgsAreRest = true;
- for (const sig of signatures) {
- allMaxArgsAreRest = allMaxArgsAreRest && sig.parameters[maxArgs - 1] && sig.hasRestParameter;
- }
if (!allMaxArgsAreRest) {
const newParameter = createParameterDeclaration(maxArgs - 1, minArgumentCount, newSignatureDeclaration);
newSignatureDeclaration.parameters.push(newParameter);
@@ -137,13 +139,13 @@ namespace ts.codefix {
return checker.getSignatureFromDeclaration(newSignatureDeclaration);
- function createParameterDeclaration(index: number, minArgCount: number, enclosingSignature: SignatureDeclaration): ParameterDeclaration {
+ function createParameterDeclaration(index: number, minArgCount: number, enclosingSignatureDeclaration: SignatureDeclaration): ParameterDeclaration {
const newParameter = createNode(SyntaxKind.Parameter) as ParameterDeclaration;
newParameter.symbol = checker.createSymbol(SymbolFlags.FunctionScopedVariable, "arg" + index);
newParameter.symbol.valueDeclaration = newParameter;
newParameter.symbol.declarations = [newParameter];
newParameter.type = anyTypeNode;
- newParameter.parent = enclosingSignature;
+ newParameter.parent = enclosingSignatureDeclaration;
if (index >= minArgCount) {
newParameter.questionToken = optionalToken;
}
diff --git a/tests/cases/fourslash/codeFixClassExtendsAbstractMethod.ts b/tests/cases/fourslash/codeFixClassExtendsAbstractMethod.ts
index bf9eba11c8e..587b5d9b2b7 100644
--- a/tests/cases/fourslash/codeFixClassExtendsAbstractMethod.ts
+++ b/tests/cases/fourslash/codeFixClassExtendsAbstractMethod.ts
@@ -12,7 +12,7 @@ verify.rangeAfterCodeFix(`
f(a: number, b: string): boolean;
f(a: string, b: number): Function;
f(a: string): Function;
- f(arg0: any, arg1? any) {
- throw new Error("Method not implemented");
+ f(arg0: any, arg1?: any) {
+ throw new Error('Method not implemented.');
}
`);
diff --git a/tests/cases/fourslash/codeFixUnImplementedInterface39 - Copy (3).ts b/tests/cases/fourslash/codeFixUnImplementedInterface39 - Copy (3).ts
deleted file mode 100644
index f81dea49782..00000000000
--- a/tests/cases/fourslash/codeFixUnImplementedInterface39 - Copy (3).ts
+++ /dev/null
@@ -1,18 +0,0 @@
-///
-
-//// namespace N1 {
-//// export interface I1 {
-//// f1():string;
-//// }
-//// }
-//// interface I1 {
-//// f1();
-//// }
-////
-//// class C1 implements N1.I1 {[|
-//// |]}
-
-verify.rangeAfterCodeFix(`f1(): string{
- throw new Error('Method not implemented.');
-}
-`);
diff --git a/tests/cases/fourslash/codeFixUnImplementedInterface39 - Copy (4).ts b/tests/cases/fourslash/codeFixUnImplementedInterface39 - Copy (4).ts
deleted file mode 100644
index f81dea49782..00000000000
--- a/tests/cases/fourslash/codeFixUnImplementedInterface39 - Copy (4).ts
+++ /dev/null
@@ -1,18 +0,0 @@
-///
-
-//// namespace N1 {
-//// export interface I1 {
-//// f1():string;
-//// }
-//// }
-//// interface I1 {
-//// f1();
-//// }
-////
-//// class C1 implements N1.I1 {[|
-//// |]}
-
-verify.rangeAfterCodeFix(`f1(): string{
- throw new Error('Method not implemented.');
-}
-`);
diff --git a/tests/cases/fourslash/codeFixUnImplementedInterface39 - Copy (5).ts b/tests/cases/fourslash/codeFixUnImplementedInterface39 - Copy (5).ts
deleted file mode 100644
index f81dea49782..00000000000
--- a/tests/cases/fourslash/codeFixUnImplementedInterface39 - Copy (5).ts
+++ /dev/null
@@ -1,18 +0,0 @@
-///
-
-//// namespace N1 {
-//// export interface I1 {
-//// f1():string;
-//// }
-//// }
-//// interface I1 {
-//// f1();
-//// }
-////
-//// class C1 implements N1.I1 {[|
-//// |]}
-
-verify.rangeAfterCodeFix(`f1(): string{
- throw new Error('Method not implemented.');
-}
-`);
diff --git a/tests/cases/fourslash/codeFixUnImplementedInterface39 - Copy (6).ts b/tests/cases/fourslash/codeFixUnImplementedInterface39 - Copy (6).ts
deleted file mode 100644
index f81dea49782..00000000000
--- a/tests/cases/fourslash/codeFixUnImplementedInterface39 - Copy (6).ts
+++ /dev/null
@@ -1,18 +0,0 @@
-///
-
-//// namespace N1 {
-//// export interface I1 {
-//// f1():string;
-//// }
-//// }
-//// interface I1 {
-//// f1();
-//// }
-////
-//// class C1 implements N1.I1 {[|
-//// |]}
-
-verify.rangeAfterCodeFix(`f1(): string{
- throw new Error('Method not implemented.');
-}
-`);
diff --git a/tests/cases/fourslash/codeFixUnImplementedInterfaceComputedPropertyNameWellKnownSymbols.ts b/tests/cases/fourslash/codeFixUnImplementedInterfaceComputedPropertyNameWellKnownSymbols.ts
new file mode 100644
index 00000000000..ffad13e74de
--- /dev/null
+++ b/tests/cases/fourslash/codeFixUnImplementedInterfaceComputedPropertyNameWellKnownSymbols.ts
@@ -0,0 +1,53 @@
+///
+
+// @lib: es2017
+
+//// interface I {
+//// [Symbol.hasInstance](o: any): boolean;
+//// [Symbol.isConcatSpreadable]: boolean;
+//// [Symbol.iterator](): Iterator;
+//// [Symbol.match]: boolean;
+//// [Symbol.replace](...args);
+//// [Symbol.search](str: string): number;
+//// [Symbol.species](): Species;
+//// [Symbol.split](str: string, limit?: number): string[];
+//// [Symbol.toPrimitive](hint: "number"): number;
+//// [Symbol.toPrimitive](hint: "default"): number;
+//// [Symbol.toPrimitive](hint: "string"): string;
+//// [Symbol.toStringTag]: string;
+//// [Symbol.unscopables]: any;
+//// }
+////
+//// class C implements I {[| |]}
+
+
+verify.rangeAfterCodeFix(`
+ [Symbol.hasInstance](o: any): boolean {
+ throw new Error('Method not implemented.');
+ }
+ [Symbol.isConcatSpreadable]: boolean;
+ [Symbol.iterator]() {
+ throw new Error('Method not implemented.');
+ }
+ [Symbol.match]: boolean;
+ [Symbol.replace](...args: {}) {
+ throw new Error('Method not implemented.');
+ }
+ [Symbol.search](str: string): number {
+ throw new Error('Method not implemented.');
+ }
+ [Symbol.species](): number {
+ throw new Error('Method not implemented.');
+ }
+ [Symbol.split](str: string, limit?: number): {} {
+ throw new Error('Method not implemented.');
+ }
+ [Symbol.toPrimitive](hint: "number"): number;
+ [Symbol.toPrimitive](hint: "default"): number;
+ [Symbol.toPrimitive](hint: "string"): string;
+ [Symbol.toPrimitive](arg0: any) {
+ throw new Error('Method not implemented.');
+ }
+ [Symbol.toStringTag]: string;
+ [Symbol.unscopables]: any;
+`);