diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 26c27cb3be2e3..c1b9a7ac0e3cd 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -15780,19 +15780,20 @@ namespace ts { } function checkClassForDuplicateDeclarations(node: ClassLikeDeclaration) { - const enum Accessor { + const enum Declaration { Getter = 1, Setter = 2, + Method = 4, Property = Getter | Setter } - const instanceNames = createMap(); - const staticNames = createMap(); + const instanceNames = createMap(); + const staticNames = createMap(); for (const member of node.members) { if (member.kind === SyntaxKind.Constructor) { for (const param of (member as ConstructorDeclaration).parameters) { if (isParameterPropertyDeclaration(param)) { - addName(instanceNames, param.name, (param.name as Identifier).text, Accessor.Property); + addName(instanceNames, param.name, (param.name as Identifier).text, Declaration.Property); } } } @@ -15804,25 +15805,34 @@ namespace ts { if (memberName) { switch (member.kind) { case SyntaxKind.GetAccessor: - addName(names, member.name, memberName, Accessor.Getter); + addName(names, member.name, memberName, Declaration.Getter); break; case SyntaxKind.SetAccessor: - addName(names, member.name, memberName, Accessor.Setter); + addName(names, member.name, memberName, Declaration.Setter); break; case SyntaxKind.PropertyDeclaration: - addName(names, member.name, memberName, Accessor.Property); + addName(names, member.name, memberName, Declaration.Property); + break; + + case SyntaxKind.MethodDeclaration: + addName(names, member.name, memberName, Declaration.Method); break; } } } } - function addName(names: Map, location: Node, name: string, meaning: Accessor) { + function addName(names: Map, location: Node, name: string, meaning: Declaration) { const prev = names.get(name); if (prev) { - if (prev & meaning) { + if (prev & Declaration.Method) { + if (meaning !== Declaration.Method) { + error(location, Diagnostics.Duplicate_identifier_0, getTextOfNode(location)); + } + } + else if (prev & meaning) { error(location, Diagnostics.Duplicate_identifier_0, getTextOfNode(location)); } else { diff --git a/tests/baselines/reference/classWithDuplicateIdentifier.errors.txt b/tests/baselines/reference/classWithDuplicateIdentifier.errors.txt new file mode 100644 index 0000000000000..325db86d47d50 --- /dev/null +++ b/tests/baselines/reference/classWithDuplicateIdentifier.errors.txt @@ -0,0 +1,31 @@ +tests/cases/compiler/classWithDuplicateIdentifier.ts(3,5): error TS2300: Duplicate identifier 'a'. +tests/cases/compiler/classWithDuplicateIdentifier.ts(6,5): error TS2300: Duplicate identifier 'b'. +tests/cases/compiler/classWithDuplicateIdentifier.ts(7,5): error TS2300: Duplicate identifier 'b'. +tests/cases/compiler/classWithDuplicateIdentifier.ts(11,5): error TS2300: Duplicate identifier 'c'. +tests/cases/compiler/classWithDuplicateIdentifier.ts(11,5): error TS2403: Subsequent variable declarations must have the same type. Variable 'c' must be of type 'number', but here has type 'string'. + + +==== tests/cases/compiler/classWithDuplicateIdentifier.ts (5 errors) ==== + class C { + a(): number { return 0; } // error: duplicate identifier + a: number; + ~ +!!! error TS2300: Duplicate identifier 'a'. + } + class K { + b: number; // error: duplicate identifier + ~ +!!! error TS2300: Duplicate identifier 'b'. + b(): number { return 0; } + ~ +!!! error TS2300: Duplicate identifier 'b'. + } + class D { + c: number; + c: string; + ~ +!!! error TS2300: Duplicate identifier 'c'. + ~ +!!! error TS2403: Subsequent variable declarations must have the same type. Variable 'c' must be of type 'number', but here has type 'string'. + } + \ No newline at end of file diff --git a/tests/baselines/reference/classWithDuplicateIdentifier.js b/tests/baselines/reference/classWithDuplicateIdentifier.js new file mode 100644 index 0000000000000..515b1749aa3d5 --- /dev/null +++ b/tests/baselines/reference/classWithDuplicateIdentifier.js @@ -0,0 +1,33 @@ +//// [classWithDuplicateIdentifier.ts] +class C { + a(): number { return 0; } // error: duplicate identifier + a: number; +} +class K { + b: number; // error: duplicate identifier + b(): number { return 0; } +} +class D { + c: number; + c: string; +} + + +//// [classWithDuplicateIdentifier.js] +var C = (function () { + function C() { + } + C.prototype.a = function () { return 0; }; // error: duplicate identifier + return C; +}()); +var K = (function () { + function K() { + } + K.prototype.b = function () { return 0; }; + return K; +}()); +var D = (function () { + function D() { + } + return D; +}()); diff --git a/tests/cases/compiler/classWithDuplicateIdentifier.ts b/tests/cases/compiler/classWithDuplicateIdentifier.ts new file mode 100644 index 0000000000000..1612bd3f378f5 --- /dev/null +++ b/tests/cases/compiler/classWithDuplicateIdentifier.ts @@ -0,0 +1,12 @@ +class C { + a(): number { return 0; } // error: duplicate identifier + a: number; +} +class K { + b: number; // error: duplicate identifier + b(): number { return 0; } +} +class D { + c: number; + c: string; +}