diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts
index bf3fd23ffd2ff..41c965fb8457d 100644
--- a/src/compiler/checker.ts
+++ b/src/compiler/checker.ts
@@ -21221,9 +21221,10 @@ namespace ts {
(isCallSignatureDeclaration(param.parent) || isMethodSignature(param.parent) || isFunctionTypeNode(param.parent)) &&
param.parent.parameters.indexOf(param) > -1 &&
(resolveName(param, param.name.escapedText, SymbolFlags.Type, undefined, param.name.escapedText, /*isUse*/ true) ||
- param.name.originalKeywordKind && isTypeNodeKind(param.name.originalKeywordKind))) {
+ param.name.originalKeywordKind && isTypeNodeKind(param.name.originalKeywordKind))) {
const newName = "arg" + param.parent.parameters.indexOf(param);
- errorOrSuggestion(noImplicitAny, declaration, Diagnostics.Parameter_has_a_name_but_no_type_Did_you_mean_0_Colon_1, newName, declarationNameToString(param.name));
+ const typeName = declarationNameToString(param.name) + (param.dotDotDotToken ? "[]" : "");
+ errorOrSuggestion(noImplicitAny, declaration, Diagnostics.Parameter_has_a_name_but_no_type_Did_you_mean_0_Colon_1, newName, typeName);
return;
}
diagnostic = (declaration as ParameterDeclaration).dotDotDotToken ?
diff --git a/src/services/codefixes/addNameToNamelessParameter.ts b/src/services/codefixes/addNameToNamelessParameter.ts
index 07bc1bea7e3c6..bd53c23743239 100644
--- a/src/services/codefixes/addNameToNamelessParameter.ts
+++ b/src/services/codefixes/addNameToNamelessParameter.ts
@@ -14,24 +14,24 @@ namespace ts.codefix {
function makeChange(changeTracker: textChanges.ChangeTracker, sourceFile: SourceFile, pos: number) {
const token = getTokenAtPosition(sourceFile, pos);
- if (!isIdentifier(token)) {
- return Debug.fail("add-name-to-nameless-parameter operates on identifiers, but got a " + Debug.formatSyntaxKind(token.kind));
- }
const param = token.parent;
if (!isParameter(param)) {
return Debug.fail("Tried to add a parameter name to a non-parameter: " + Debug.formatSyntaxKind(token.kind));
}
+
const i = param.parent.parameters.indexOf(param);
Debug.assert(!param.type, "Tried to add a parameter name to a parameter that already had one.");
Debug.assert(i > -1, "Parameter not found in parent parameter list.");
+
+ const typeNode = factory.createTypeReferenceNode(param.name as Identifier, /*typeArguments*/ undefined);
const replacement = factory.createParameterDeclaration(
/*decorators*/ undefined,
param.modifiers,
param.dotDotDotToken,
"arg" + i,
param.questionToken,
- factory.createTypeReferenceNode(token, /*typeArguments*/ undefined),
+ param.dotDotDotToken ? factory.createArrayTypeNode(typeNode) : typeNode,
param.initializer);
- changeTracker.replaceNode(sourceFile, token, replacement);
+ changeTracker.replaceNode(sourceFile, param, replacement);
}
}
diff --git a/tests/baselines/reference/noImplicitAnyNamelessParameter.errors.txt b/tests/baselines/reference/noImplicitAnyNamelessParameter.errors.txt
index 9dc95461d63c1..c93dd533a1ef5 100644
--- a/tests/baselines/reference/noImplicitAnyNamelessParameter.errors.txt
+++ b/tests/baselines/reference/noImplicitAnyNamelessParameter.errors.txt
@@ -1,26 +1,30 @@
-tests/cases/compiler/noImplicitAnyNamelessParameter.ts(2,17): error TS7051: Parameter has a name but no type. Did you mean 'arg0: string'?
-tests/cases/compiler/noImplicitAnyNamelessParameter.ts(2,25): error TS7051: Parameter has a name but no type. Did you mean 'arg1: C'?
-tests/cases/compiler/noImplicitAnyNamelessParameter.ts(3,19): error TS7051: Parameter has a name but no type. Did you mean 'arg0: C'?
-tests/cases/compiler/noImplicitAnyNamelessParameter.ts(3,22): error TS7051: Parameter has a name but no type. Did you mean 'arg1: number'?
-tests/cases/compiler/noImplicitAnyNamelessParameter.ts(4,20): error TS7051: Parameter has a name but no type. Did you mean 'arg0: boolean'?
-tests/cases/compiler/noImplicitAnyNamelessParameter.ts(4,29): error TS7051: Parameter has a name but no type. Did you mean 'arg1: C'?
-tests/cases/compiler/noImplicitAnyNamelessParameter.ts(4,32): error TS7051: Parameter has a name but no type. Did you mean 'arg2: object'?
-tests/cases/compiler/noImplicitAnyNamelessParameter.ts(4,40): error TS7051: Parameter has a name but no type. Did you mean 'arg3: undefined'?
+tests/cases/compiler/noImplicitAnyNamelessParameter.ts(2,20): error TS7051: Parameter has a name but no type. Did you mean 'arg0: string[]'?
+tests/cases/compiler/noImplicitAnyNamelessParameter.ts(3,17): error TS7051: Parameter has a name but no type. Did you mean 'arg0: string'?
+tests/cases/compiler/noImplicitAnyNamelessParameter.ts(3,25): error TS7051: Parameter has a name but no type. Did you mean 'arg1: C'?
+tests/cases/compiler/noImplicitAnyNamelessParameter.ts(4,19): error TS7051: Parameter has a name but no type. Did you mean 'arg0: C'?
+tests/cases/compiler/noImplicitAnyNamelessParameter.ts(4,22): error TS7051: Parameter has a name but no type. Did you mean 'arg1: number'?
+tests/cases/compiler/noImplicitAnyNamelessParameter.ts(5,20): error TS7051: Parameter has a name but no type. Did you mean 'arg0: boolean'?
+tests/cases/compiler/noImplicitAnyNamelessParameter.ts(5,29): error TS7051: Parameter has a name but no type. Did you mean 'arg1: C'?
+tests/cases/compiler/noImplicitAnyNamelessParameter.ts(5,32): error TS7051: Parameter has a name but no type. Did you mean 'arg2: object'?
+tests/cases/compiler/noImplicitAnyNamelessParameter.ts(5,40): error TS7051: Parameter has a name but no type. Did you mean 'arg3: undefined'?
-==== tests/cases/compiler/noImplicitAnyNamelessParameter.ts (8 errors) ====
+==== tests/cases/compiler/noImplicitAnyNamelessParameter.ts (9 errors) ====
class C { }
- declare var x: (string, C) => void;
+ declare var a: { m(...string): void }
+ ~~~~~~~~~
+!!! error TS7051: Parameter has a name but no type. Did you mean 'arg0: string[]'?
+ declare var b: (string, C) => void;
~~~~~~
!!! error TS7051: Parameter has a name but no type. Did you mean 'arg0: string'?
~
!!! error TS7051: Parameter has a name but no type. Did you mean 'arg1: C'?
- declare var y: { (C, number): void };
+ declare var c: { (C, number): void };
~
!!! error TS7051: Parameter has a name but no type. Did you mean 'arg0: C'?
~~~~~~
!!! error TS7051: Parameter has a name but no type. Did you mean 'arg1: number'?
- declare var z: { m(boolean, C, object, undefined): void }
+ declare var d: { m(boolean, C, object, undefined): void }
~~~~~~~
!!! error TS7051: Parameter has a name but no type. Did you mean 'arg0: boolean'?
~
diff --git a/tests/baselines/reference/noImplicitAnyNamelessParameter.js b/tests/baselines/reference/noImplicitAnyNamelessParameter.js
index 39d7e644578b3..5fabc25b94043 100644
--- a/tests/baselines/reference/noImplicitAnyNamelessParameter.js
+++ b/tests/baselines/reference/noImplicitAnyNamelessParameter.js
@@ -1,8 +1,9 @@
//// [noImplicitAnyNamelessParameter.ts]
class C { }
-declare var x: (string, C) => void;
-declare var y: { (C, number): void };
-declare var z: { m(boolean, C, object, undefined): void }
+declare var a: { m(...string): void }
+declare var b: (string, C) => void;
+declare var c: { (C, number): void };
+declare var d: { m(boolean, C, object, undefined): void }
// note: null and void do not parse correctly without a preceding parameter name
diff --git a/tests/baselines/reference/noImplicitAnyNamelessParameter.symbols b/tests/baselines/reference/noImplicitAnyNamelessParameter.symbols
index 2a22f5389d6bb..1662ce08e4693 100644
--- a/tests/baselines/reference/noImplicitAnyNamelessParameter.symbols
+++ b/tests/baselines/reference/noImplicitAnyNamelessParameter.symbols
@@ -2,23 +2,28 @@
class C { }
>C : Symbol(C, Decl(noImplicitAnyNamelessParameter.ts, 0, 0))
-declare var x: (string, C) => void;
->x : Symbol(x, Decl(noImplicitAnyNamelessParameter.ts, 1, 11))
->string : Symbol(string, Decl(noImplicitAnyNamelessParameter.ts, 1, 16))
->C : Symbol(C, Decl(noImplicitAnyNamelessParameter.ts, 1, 23))
+declare var a: { m(...string): void }
+>a : Symbol(a, Decl(noImplicitAnyNamelessParameter.ts, 1, 11))
+>m : Symbol(m, Decl(noImplicitAnyNamelessParameter.ts, 1, 16))
+>string : Symbol(string, Decl(noImplicitAnyNamelessParameter.ts, 1, 19))
-declare var y: { (C, number): void };
->y : Symbol(y, Decl(noImplicitAnyNamelessParameter.ts, 2, 11))
->C : Symbol(C, Decl(noImplicitAnyNamelessParameter.ts, 2, 18))
->number : Symbol(number, Decl(noImplicitAnyNamelessParameter.ts, 2, 20))
+declare var b: (string, C) => void;
+>b : Symbol(b, Decl(noImplicitAnyNamelessParameter.ts, 2, 11))
+>string : Symbol(string, Decl(noImplicitAnyNamelessParameter.ts, 2, 16))
+>C : Symbol(C, Decl(noImplicitAnyNamelessParameter.ts, 2, 23))
-declare var z: { m(boolean, C, object, undefined): void }
->z : Symbol(z, Decl(noImplicitAnyNamelessParameter.ts, 3, 11))
->m : Symbol(m, Decl(noImplicitAnyNamelessParameter.ts, 3, 16))
->boolean : Symbol(boolean, Decl(noImplicitAnyNamelessParameter.ts, 3, 19))
->C : Symbol(C, Decl(noImplicitAnyNamelessParameter.ts, 3, 27))
->object : Symbol(object, Decl(noImplicitAnyNamelessParameter.ts, 3, 30))
->undefined : Symbol(undefined, Decl(noImplicitAnyNamelessParameter.ts, 3, 38))
+declare var c: { (C, number): void };
+>c : Symbol(c, Decl(noImplicitAnyNamelessParameter.ts, 3, 11))
+>C : Symbol(C, Decl(noImplicitAnyNamelessParameter.ts, 3, 18))
+>number : Symbol(number, Decl(noImplicitAnyNamelessParameter.ts, 3, 20))
+
+declare var d: { m(boolean, C, object, undefined): void }
+>d : Symbol(d, Decl(noImplicitAnyNamelessParameter.ts, 4, 11))
+>m : Symbol(m, Decl(noImplicitAnyNamelessParameter.ts, 4, 16))
+>boolean : Symbol(boolean, Decl(noImplicitAnyNamelessParameter.ts, 4, 19))
+>C : Symbol(C, Decl(noImplicitAnyNamelessParameter.ts, 4, 27))
+>object : Symbol(object, Decl(noImplicitAnyNamelessParameter.ts, 4, 30))
+>undefined : Symbol(undefined, Decl(noImplicitAnyNamelessParameter.ts, 4, 38))
// note: null and void do not parse correctly without a preceding parameter name
diff --git a/tests/baselines/reference/noImplicitAnyNamelessParameter.types b/tests/baselines/reference/noImplicitAnyNamelessParameter.types
index 7ab5cdcc4bdb7..bd274700b7e60 100644
--- a/tests/baselines/reference/noImplicitAnyNamelessParameter.types
+++ b/tests/baselines/reference/noImplicitAnyNamelessParameter.types
@@ -2,18 +2,23 @@
class C { }
>C : C
-declare var x: (string, C) => void;
->x : (string: any, C: any) => void
+declare var a: { m(...string): void }
+>a : { m(...string: any[]): void; }
+>m : (...string: any[]) => void
+>string : any[]
+
+declare var b: (string, C) => void;
+>b : (string: any, C: any) => void
>string : any
>C : any
-declare var y: { (C, number): void };
->y : (C: any, number: any) => void
+declare var c: { (C, number): void };
+>c : (C: any, number: any) => void
>C : any
>number : any
-declare var z: { m(boolean, C, object, undefined): void }
->z : { m(boolean: any, C: any, object: any, undefined: any): void; }
+declare var d: { m(boolean, C, object, undefined): void }
+>d : { m(boolean: any, C: any, object: any, undefined: any): void; }
>m : (boolean: any, C: any, object: any, undefined: any) => void
>boolean : any
>C : any
diff --git a/tests/cases/compiler/noImplicitAnyNamelessParameter.ts b/tests/cases/compiler/noImplicitAnyNamelessParameter.ts
index 6206a5e68ad24..aa98a725bd687 100644
--- a/tests/cases/compiler/noImplicitAnyNamelessParameter.ts
+++ b/tests/cases/compiler/noImplicitAnyNamelessParameter.ts
@@ -1,6 +1,7 @@
// @noImplicitAny: true
class C { }
-declare var x: (string, C) => void;
-declare var y: { (C, number): void };
-declare var z: { m(boolean, C, object, undefined): void }
+declare var a: { m(...string): void }
+declare var b: (string, C) => void;
+declare var c: { (C, number): void };
+declare var d: { m(boolean, C, object, undefined): void }
// note: null and void do not parse correctly without a preceding parameter name
diff --git a/tests/cases/fourslash/codeFixAddParameterNames.ts b/tests/cases/fourslash/codeFixAddParameterNames1.ts
similarity index 100%
rename from tests/cases/fourslash/codeFixAddParameterNames.ts
rename to tests/cases/fourslash/codeFixAddParameterNames1.ts
diff --git a/tests/cases/fourslash/codeFixAddParameterNames2.ts b/tests/cases/fourslash/codeFixAddParameterNames2.ts
new file mode 100644
index 0000000000000..31e26358aebc4
--- /dev/null
+++ b/tests/cases/fourslash/codeFixAddParameterNames2.ts
@@ -0,0 +1,6 @@
+///
+
+// @noImplicitAny: true
+////type Rest = ([|...number|]) => void;
+
+verify.rangeAfterCodeFix("...arg0: number[]");
diff --git a/tests/cases/fourslash/codeFixAddParameterNames3.ts b/tests/cases/fourslash/codeFixAddParameterNames3.ts
new file mode 100644
index 0000000000000..465471e11287f
--- /dev/null
+++ b/tests/cases/fourslash/codeFixAddParameterNames3.ts
@@ -0,0 +1,6 @@
+///
+
+// @noImplicitAny: true
+////type Rest = ([|public string|]) => void;
+
+verify.rangeAfterCodeFix("public arg0: string");