From 2cd76239bb4bf0a6dd526e844c5acbf34d992263 Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Fri, 21 May 2021 17:29:10 +0300 Subject: [PATCH 01/10] check params duplicates during parse function --- src/parser.ts | 53 ++++++++++++++++++- tests/parser/function-expression.ts | 4 ++ .../parser/function-expression.ts.fixture.ts | 4 ++ tests/parser/function-type.ts | 2 + tests/parser/function-type.ts.fixture.ts | 2 + tests/parser/parameter-order.ts | 3 ++ tests/parser/parameter-order.ts.fixture.ts | 2 + 7 files changed, 69 insertions(+), 1 deletion(-) diff --git a/src/parser.ts b/src/parser.ts index 31987d8bf6..b32e64fbd7 100644 --- a/src/parser.ts +++ b/src/parser.ts @@ -845,7 +845,24 @@ export class Parser extends DiagnosticEmitter { return null; } this.tryParseSignatureIsSignature = true; - if (!parameters) parameters = []; + if (!parameters) { + parameters = []; + } else { + // check duplicates + let visited = new Set(); + for (let i = 0, k = parameters.length; i < k; i++) { + let paramIdentifier = parameters[i].name; + let paramName = paramIdentifier.text; + if (!visited.has(paramName)) { + visited.add(paramName); + } else { + this.error( + DiagnosticCode.Duplicate_identifier_0, + paramIdentifier.range, paramName + ); + } + } + } return Node.createFunctionType( parameters, returnType, @@ -1484,6 +1501,23 @@ export class Parser extends DiagnosticEmitter { } } + // check duplicates + if (parameters.length >= 2) { + let visited = new Set(); + for (let i = 0, k = parameters.length; i < k; i++) { + let paramIdentifier = parameters[i].name; + let paramName = paramIdentifier.text; + if (!visited.has(paramName)) { + visited.add(paramName); + } else { + this.error( + DiagnosticCode.Duplicate_identifier_0, + paramIdentifier.range, paramName + ); + } + } + } + var signature = Node.createFunctionType( parameters, returnType, @@ -1564,6 +1598,23 @@ export class Parser extends DiagnosticEmitter { var parameters = this.parseParameters(tn); if (!parameters) return null; + // check duplicates + if (parameters.length >= 2) { + let visited = new Set(); + for (let i = 0, k = parameters.length; i < k; i++) { + let paramIdentifier = parameters[i].name; + let paramName = paramIdentifier.text; + if (!visited.has(paramName)) { + visited.add(paramName); + } else { + this.error( + DiagnosticCode.Duplicate_identifier_0, + paramIdentifier.range, paramName + ); + } + } + } + return this.parseFunctionExpressionCommon(tn, name, parameters, this.parseParametersThis, arrowKind, startPos, signatureStart); } diff --git a/tests/parser/function-expression.ts b/tests/parser/function-expression.ts index bbd37e9918..9c3f82d0bd 100644 --- a/tests/parser/function-expression.ts +++ b/tests/parser/function-expression.ts @@ -14,3 +14,7 @@ var e = (a: i32, b: i32): i32 => { ; }; var f = (a: i32): i32 => a; +// 2300: Duplicate identifier 'a' +var g = (a: i32, a: i32): void => { + ; +}; diff --git a/tests/parser/function-expression.ts.fixture.ts b/tests/parser/function-expression.ts.fixture.ts index bbd37e9918..cb266d134a 100644 --- a/tests/parser/function-expression.ts.fixture.ts +++ b/tests/parser/function-expression.ts.fixture.ts @@ -14,3 +14,7 @@ var e = (a: i32, b: i32): i32 => { ; }; var f = (a: i32): i32 => a; +var g = (a: i32, a: i32): void => { + ; +}; +// ERROR 2300: "Duplicate identifier 'a'." in function-expression.ts(18,18+1) diff --git a/tests/parser/function-type.ts b/tests/parser/function-type.ts index 39f741eaf4..e518cfb04f 100644 --- a/tests/parser/function-type.ts +++ b/tests/parser/function-type.ts @@ -2,3 +2,5 @@ var a: () => void; var b: (a: i32, b: i32) => void; var c: (a: i32, b: i32) => (a: i32, b: i32) => void; var d: (a) => void; // TS1110 +// TS2300: Duplicate identifier 'a' +var g: (a: i32, a: i32) => void; diff --git a/tests/parser/function-type.ts.fixture.ts b/tests/parser/function-type.ts.fixture.ts index da4cc376b9..20db1a86e3 100644 --- a/tests/parser/function-type.ts.fixture.ts +++ b/tests/parser/function-type.ts.fixture.ts @@ -2,4 +2,6 @@ var a: () => void; var b: (a: i32, b: i32) => void; var c: (a: i32, b: i32) => (a: i32, b: i32) => void; var d: (a) => void; +var g: (a: i32, a: i32) => void; // ERROR 1110: "Type expected." in function-type.ts(4,10+0) +// ERROR 2300: "Duplicate identifier 'a'." in function-type.ts(6,17+1) diff --git a/tests/parser/parameter-order.ts b/tests/parser/parameter-order.ts index 1893dbe7d7..138375f460 100644 --- a/tests/parser/parameter-order.ts +++ b/tests/parser/parameter-order.ts @@ -9,3 +9,6 @@ function optionalCannotPrecedeRequired(a?: i32, b: i32): void {} // 1016: A required parameter cannot follow an optional parameter. function optionalWithInitializerCannotPrecedeRequired(a: i32 = 1, b: i32): void {} + +// 2300: Duplicate identifier 'a' +function duplicateParams(a: i32, a: i32): void {} diff --git a/tests/parser/parameter-order.ts.fixture.ts b/tests/parser/parameter-order.ts.fixture.ts index e972dfe4d7..3e3611615e 100644 --- a/tests/parser/parameter-order.ts.fixture.ts +++ b/tests/parser/parameter-order.ts.fixture.ts @@ -3,6 +3,8 @@ function optionalValid(a: i32, b?: i32): void {} function restParameterMustBeLast(...a: Array, b: i32): void {} function optionalCannotPrecedeRequired(a?: i32, b: i32): void {} function optionalWithInitializerCannotPrecedeRequired(a: i32 = 1, b: i32): void {} +function duplicateParams(a: i32, a: i32): void {} // ERROR 1014: "A rest parameter must be last in a parameter list." in parameter-order.ts(5,37+1) // ERROR 1016: "A required parameter cannot follow an optional parameter." in parameter-order.ts(8,49+1) // ERROR 1016: "A required parameter cannot follow an optional parameter." in parameter-order.ts(11,67+1) +// ERROR 2300: "Duplicate identifier 'a'." in parameter-order.ts(14,34+1) From 0ac7d744e7b46f26189fd23fe25e170774ff1dc4 Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Fri, 21 May 2021 17:31:23 +0300 Subject: [PATCH 02/10] more --- src/parser.ts | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/src/parser.ts b/src/parser.ts index b32e64fbd7..f7195a680a 100644 --- a/src/parser.ts +++ b/src/parser.ts @@ -849,17 +849,19 @@ export class Parser extends DiagnosticEmitter { parameters = []; } else { // check duplicates - let visited = new Set(); - for (let i = 0, k = parameters.length; i < k; i++) { - let paramIdentifier = parameters[i].name; - let paramName = paramIdentifier.text; - if (!visited.has(paramName)) { - visited.add(paramName); - } else { - this.error( - DiagnosticCode.Duplicate_identifier_0, - paramIdentifier.range, paramName - ); + if (parameters.length >= 2) { + let visited = new Set(); + for (let i = 0, k = parameters.length; i < k; i++) { + let paramIdentifier = parameters[i].name; + let paramName = paramIdentifier.text; + if (!visited.has(paramName)) { + visited.add(paramName); + } else { + this.error( + DiagnosticCode.Duplicate_identifier_0, + paramIdentifier.range, paramName + ); + } } } } From 414ec4fa7c91cc5408cedfdf1289a8183a7ffc67 Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Fri, 21 May 2021 17:36:43 +0300 Subject: [PATCH 03/10] move code to private function --- src/parser.ts | 70 ++++++++++++++++----------------------------------- 1 file changed, 21 insertions(+), 49 deletions(-) diff --git a/src/parser.ts b/src/parser.ts index f7195a680a..864ac59b32 100644 --- a/src/parser.ts +++ b/src/parser.ts @@ -848,22 +848,7 @@ export class Parser extends DiagnosticEmitter { if (!parameters) { parameters = []; } else { - // check duplicates - if (parameters.length >= 2) { - let visited = new Set(); - for (let i = 0, k = parameters.length; i < k; i++) { - let paramIdentifier = parameters[i].name; - let paramName = paramIdentifier.text; - if (!visited.has(paramName)) { - visited.add(paramName); - } else { - this.error( - DiagnosticCode.Duplicate_identifier_0, - paramIdentifier.range, paramName - ); - } - } - } + this.checkFunctionParameterDuplicates(parameters); } return Node.createFunctionType( parameters, @@ -1503,22 +1488,7 @@ export class Parser extends DiagnosticEmitter { } } - // check duplicates - if (parameters.length >= 2) { - let visited = new Set(); - for (let i = 0, k = parameters.length; i < k; i++) { - let paramIdentifier = parameters[i].name; - let paramName = paramIdentifier.text; - if (!visited.has(paramName)) { - visited.add(paramName); - } else { - this.error( - DiagnosticCode.Duplicate_identifier_0, - paramIdentifier.range, paramName - ); - } - } - } + this.checkFunctionParameterDuplicates(parameters); var signature = Node.createFunctionType( parameters, @@ -1600,23 +1570,7 @@ export class Parser extends DiagnosticEmitter { var parameters = this.parseParameters(tn); if (!parameters) return null; - // check duplicates - if (parameters.length >= 2) { - let visited = new Set(); - for (let i = 0, k = parameters.length; i < k; i++) { - let paramIdentifier = parameters[i].name; - let paramName = paramIdentifier.text; - if (!visited.has(paramName)) { - visited.add(paramName); - } else { - this.error( - DiagnosticCode.Duplicate_identifier_0, - paramIdentifier.range, paramName - ); - } - } - } - + this.checkFunctionParameterDuplicates(parameters); return this.parseFunctionExpressionCommon(tn, name, parameters, this.parseParametersThis, arrowKind, startPos, signatureStart); } @@ -4276,6 +4230,24 @@ export class Parser extends DiagnosticEmitter { return expr; } + private checkFunctionParameterDuplicates(parameters: ParameterNode[]): void { + if (parameters.length >= 2) { + let visited = new Set(); + for (let i = 0, k = parameters.length; i < k; i++) { + let paramIdentifier = parameters[i].name; + let paramName = paramIdentifier.text; + if (!visited.has(paramName)) { + visited.add(paramName); + } else { + this.error( + DiagnosticCode.Duplicate_identifier_0, + paramIdentifier.range, paramName + ); + } + } + } + } + /** Skips over a statement on errors in an attempt to reduce unnecessary diagnostic noise. */ skipStatement(tn: Tokenizer): void { tn.peek(true); From 33ca9a0d83130750e694725a60abdb26e0dbaeeb Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Fri, 21 May 2021 17:40:12 +0300 Subject: [PATCH 04/10] refactor --- src/parser.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/parser.ts b/src/parser.ts index 864ac59b32..5f1fe31d22 100644 --- a/src/parser.ts +++ b/src/parser.ts @@ -4231,9 +4231,10 @@ export class Parser extends DiagnosticEmitter { } private checkFunctionParameterDuplicates(parameters: ParameterNode[]): void { - if (parameters.length >= 2) { + var numParameters = parameters.length; + if (numParameters >= 2) { let visited = new Set(); - for (let i = 0, k = parameters.length; i < k; i++) { + for (let i = 0; i < numParameters; i++) { let paramIdentifier = parameters[i].name; let paramName = paramIdentifier.text; if (!visited.has(paramName)) { From 6ef30c14142426e9f754597773eb27efeb434883 Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Fri, 21 May 2021 18:56:18 +0300 Subject: [PATCH 05/10] minor opt --- src/parser.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/parser.ts b/src/parser.ts index 5f1fe31d22..6a14a07a32 100644 --- a/src/parser.ts +++ b/src/parser.ts @@ -4234,7 +4234,8 @@ export class Parser extends DiagnosticEmitter { var numParameters = parameters.length; if (numParameters >= 2) { let visited = new Set(); - for (let i = 0; i < numParameters; i++) { + visited.add(parameters[0].name.text); + for (let i = 1; i < numParameters; i++) { let paramIdentifier = parameters[i].name; let paramName = paramIdentifier.text; if (!visited.has(paramName)) { From d0ff8aa7518f37d5063043da17da3c805615bf2e Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Fri, 21 May 2021 19:04:51 +0300 Subject: [PATCH 06/10] more opt --- src/parser.ts | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/src/parser.ts b/src/parser.ts index 6a14a07a32..f337debf00 100644 --- a/src/parser.ts +++ b/src/parser.ts @@ -4233,19 +4233,31 @@ export class Parser extends DiagnosticEmitter { private checkFunctionParameterDuplicates(parameters: ParameterNode[]): void { var numParameters = parameters.length; if (numParameters >= 2) { - let visited = new Set(); - visited.add(parameters[0].name.text); - for (let i = 1; i < numParameters; i++) { - let paramIdentifier = parameters[i].name; - let paramName = paramIdentifier.text; - if (!visited.has(paramName)) { - visited.add(paramName); - } else { + if (numParameters == 2) { + // fast allocation free path for only 2 parameters + let secondParamIdentifier = parameters[1].name; + let secondParamName = secondParamIdentifier.text; + if (parameters[0].name.text == secondParamName) { this.error( DiagnosticCode.Duplicate_identifier_0, - paramIdentifier.range, paramName + secondParamIdentifier.range, secondParamName ); } + } else { + let visited = new Set(); + visited.add(parameters[0].name.text); + for (let i = 1; i < numParameters; i++) { + let paramIdentifier = parameters[i].name; + let paramName = paramIdentifier.text; + if (!visited.has(paramName)) { + visited.add(paramName); + } else { + this.error( + DiagnosticCode.Duplicate_identifier_0, + paramIdentifier.range, paramName + ); + } + } } } } From 625999d367ef95526573f94ae861b352cf37aa9d Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Fri, 21 May 2021 22:00:42 +0300 Subject: [PATCH 07/10] move check to parseFunctionExpressionCommon --- src/parser.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/parser.ts b/src/parser.ts index f337debf00..1f3e6217fc 100644 --- a/src/parser.ts +++ b/src/parser.ts @@ -1570,7 +1570,6 @@ export class Parser extends DiagnosticEmitter { var parameters = this.parseParameters(tn); if (!parameters) return null; - this.checkFunctionParameterDuplicates(parameters); return this.parseFunctionExpressionCommon(tn, name, parameters, this.parseParametersThis, arrowKind, startPos, signatureStart); } @@ -1583,6 +1582,8 @@ export class Parser extends DiagnosticEmitter { startPos: i32 = -1, signatureStart: i32 = -1 ): FunctionExpression | null { + this.checkFunctionParameterDuplicates(parameters); + if (startPos < 0) startPos = name.range.start; if (signatureStart < 0) signatureStart = startPos; From 4ebc9f403086d6f91f9e1fc8944f9dad6d3c18e3 Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Tue, 25 May 2021 21:08:57 +0300 Subject: [PATCH 08/10] move error check to semantic level --- src/compiler.ts | 35 +++++++++++++++ src/parser.ts | 44 ++----------------- tests/compiler/function-expression.json | 5 ++- tests/compiler/function-expression.ts | 4 ++ tests/compiler/function.json | 5 ++- tests/compiler/function.ts | 4 ++ tests/parser/function-expression.ts | 4 -- .../parser/function-expression.ts.fixture.ts | 4 -- tests/parser/function-type.ts | 5 +-- tests/parser/function-type.ts.fixture.ts | 7 ++- tests/parser/parameter-order.ts | 3 -- tests/parser/parameter-order.ts.fixture.ts | 2 +- 12 files changed, 60 insertions(+), 62 deletions(-) diff --git a/src/compiler.ts b/src/compiler.ts index 0a91a5246d..cefe56a946 100644 --- a/src/compiler.ts +++ b/src/compiler.ts @@ -1454,6 +1454,39 @@ export class Compiler extends DiagnosticEmitter { // === Functions ================================================================================ + private ensureNonDuplicateFunctionParameters(instance: Function): void { + var parameters = instance.prototype.functionTypeNode.parameters; + var numParameters = parameters.length; + if (numParameters >= 2) { + if (numParameters == 2) { + // fast allocation free path for only 2 parameters + let secondParamIdentifier = parameters[1].name; + let secondParamName = secondParamIdentifier.text; + if (parameters[0].name.text == secondParamName) { + this.error( + DiagnosticCode.Duplicate_identifier_0, + secondParamIdentifier.range, secondParamName + ); + } + } else { + let visited = new Set(); + visited.add(parameters[0].name.text); + for (let i = 1; i < numParameters; i++) { + let paramIdentifier = parameters[i].name; + let paramName = paramIdentifier.text; + if (!visited.has(paramName)) { + visited.add(paramName); + } else { + this.error( + DiagnosticCode.Duplicate_identifier_0, + paramIdentifier.range, paramName + ); + } + } + } + } + } + /** Compiles a priorly resolved function. */ compileFunction( /** Function to compile. */ @@ -1471,6 +1504,8 @@ export class Compiler extends DiagnosticEmitter { } } + this.ensureNonDuplicateFunctionParameters(instance); + instance.set(CommonFlags.COMPILED); var pendingElements = this.pendingElements; pendingElements.add(instance); diff --git a/src/parser.ts b/src/parser.ts index 1f3e6217fc..9e9684a627 100644 --- a/src/parser.ts +++ b/src/parser.ts @@ -845,11 +845,9 @@ export class Parser extends DiagnosticEmitter { return null; } this.tryParseSignatureIsSignature = true; - if (!parameters) { - parameters = []; - } else { - this.checkFunctionParameterDuplicates(parameters); - } + + if (!parameters) parameters = []; + return Node.createFunctionType( parameters, returnType, @@ -1488,8 +1486,6 @@ export class Parser extends DiagnosticEmitter { } } - this.checkFunctionParameterDuplicates(parameters); - var signature = Node.createFunctionType( parameters, returnType, @@ -1582,8 +1578,6 @@ export class Parser extends DiagnosticEmitter { startPos: i32 = -1, signatureStart: i32 = -1 ): FunctionExpression | null { - this.checkFunctionParameterDuplicates(parameters); - if (startPos < 0) startPos = name.range.start; if (signatureStart < 0) signatureStart = startPos; @@ -4231,38 +4225,6 @@ export class Parser extends DiagnosticEmitter { return expr; } - private checkFunctionParameterDuplicates(parameters: ParameterNode[]): void { - var numParameters = parameters.length; - if (numParameters >= 2) { - if (numParameters == 2) { - // fast allocation free path for only 2 parameters - let secondParamIdentifier = parameters[1].name; - let secondParamName = secondParamIdentifier.text; - if (parameters[0].name.text == secondParamName) { - this.error( - DiagnosticCode.Duplicate_identifier_0, - secondParamIdentifier.range, secondParamName - ); - } - } else { - let visited = new Set(); - visited.add(parameters[0].name.text); - for (let i = 1; i < numParameters; i++) { - let paramIdentifier = parameters[i].name; - let paramName = paramIdentifier.text; - if (!visited.has(paramName)) { - visited.add(paramName); - } else { - this.error( - DiagnosticCode.Duplicate_identifier_0, - paramIdentifier.range, paramName - ); - } - } - } - } - } - /** Skips over a statement on errors in an attempt to reduce unnecessary diagnostic noise. */ skipStatement(tn: Tokenizer): void { tn.peek(true); diff --git a/tests/compiler/function-expression.json b/tests/compiler/function-expression.json index 73d40f91f2..60507dccd4 100644 --- a/tests/compiler/function-expression.json +++ b/tests/compiler/function-expression.json @@ -1,4 +1,7 @@ { "asc_flags": [ + ], + "stderr": [ + "TS2300: Duplicate identifier 'a'" ] -} \ No newline at end of file +} diff --git a/tests/compiler/function-expression.ts b/tests/compiler/function-expression.ts index b69ec8ca86..ebdc2a7c8f 100644 --- a/tests/compiler/function-expression.ts +++ b/tests/compiler/function-expression.ts @@ -93,3 +93,7 @@ export function semanticallyAnonymous(): void { assert(fnDecl != exprDecl); } semanticallyAnonymous(); + +var duplicateParams = (a: i32, a: i32): void => {}; +// TS2300: Duplicate identifier 'a' +duplicateParams(1, 2); diff --git a/tests/compiler/function.json b/tests/compiler/function.json index 73d40f91f2..60507dccd4 100644 --- a/tests/compiler/function.json +++ b/tests/compiler/function.json @@ -1,4 +1,7 @@ { "asc_flags": [ + ], + "stderr": [ + "TS2300: Duplicate identifier 'a'" ] -} \ No newline at end of file +} diff --git a/tests/compiler/function.ts b/tests/compiler/function.ts index 9f74a3cd1a..bc57107fc8 100644 --- a/tests/compiler/function.ts +++ b/tests/compiler/function.ts @@ -39,3 +39,7 @@ iii(1, 2); jjj(1, 2); fff(1, 2); ddd(1, 2); + +function duplicateParams(a: i32, a: i32): void {} +// TS2300: Duplicate identifier 'a' +duplicateParams(1, 2); diff --git a/tests/parser/function-expression.ts b/tests/parser/function-expression.ts index 9c3f82d0bd..bbd37e9918 100644 --- a/tests/parser/function-expression.ts +++ b/tests/parser/function-expression.ts @@ -14,7 +14,3 @@ var e = (a: i32, b: i32): i32 => { ; }; var f = (a: i32): i32 => a; -// 2300: Duplicate identifier 'a' -var g = (a: i32, a: i32): void => { - ; -}; diff --git a/tests/parser/function-expression.ts.fixture.ts b/tests/parser/function-expression.ts.fixture.ts index cb266d134a..bbd37e9918 100644 --- a/tests/parser/function-expression.ts.fixture.ts +++ b/tests/parser/function-expression.ts.fixture.ts @@ -14,7 +14,3 @@ var e = (a: i32, b: i32): i32 => { ; }; var f = (a: i32): i32 => a; -var g = (a: i32, a: i32): void => { - ; -}; -// ERROR 2300: "Duplicate identifier 'a'." in function-expression.ts(18,18+1) diff --git a/tests/parser/function-type.ts b/tests/parser/function-type.ts index e518cfb04f..4c9a385fe5 100644 --- a/tests/parser/function-type.ts +++ b/tests/parser/function-type.ts @@ -1,6 +1,5 @@ var a: () => void; var b: (a: i32, b: i32) => void; var c: (a: i32, b: i32) => (a: i32, b: i32) => void; -var d: (a) => void; // TS1110 -// TS2300: Duplicate identifier 'a' -var g: (a: i32, a: i32) => void; +var d: (a: i32, a: i32) => void; // NOTE: duplicates in type signatures doesn't in TypeScript +var e: (a) => void; // TS1110 diff --git a/tests/parser/function-type.ts.fixture.ts b/tests/parser/function-type.ts.fixture.ts index 20db1a86e3..061e00711d 100644 --- a/tests/parser/function-type.ts.fixture.ts +++ b/tests/parser/function-type.ts.fixture.ts @@ -1,7 +1,6 @@ var a: () => void; var b: (a: i32, b: i32) => void; var c: (a: i32, b: i32) => (a: i32, b: i32) => void; -var d: (a) => void; -var g: (a: i32, a: i32) => void; -// ERROR 1110: "Type expected." in function-type.ts(4,10+0) -// ERROR 2300: "Duplicate identifier 'a'." in function-type.ts(6,17+1) +var d: (a: i32, a: i32) => void; +var e: (a) => void; +// ERROR 1110: "Type expected." in function-type.ts(5,10+0) diff --git a/tests/parser/parameter-order.ts b/tests/parser/parameter-order.ts index 138375f460..1893dbe7d7 100644 --- a/tests/parser/parameter-order.ts +++ b/tests/parser/parameter-order.ts @@ -9,6 +9,3 @@ function optionalCannotPrecedeRequired(a?: i32, b: i32): void {} // 1016: A required parameter cannot follow an optional parameter. function optionalWithInitializerCannotPrecedeRequired(a: i32 = 1, b: i32): void {} - -// 2300: Duplicate identifier 'a' -function duplicateParams(a: i32, a: i32): void {} diff --git a/tests/parser/parameter-order.ts.fixture.ts b/tests/parser/parameter-order.ts.fixture.ts index 3e3611615e..908673fe85 100644 --- a/tests/parser/parameter-order.ts.fixture.ts +++ b/tests/parser/parameter-order.ts.fixture.ts @@ -4,7 +4,7 @@ function restParameterMustBeLast(...a: Array, b: i32): void {} function optionalCannotPrecedeRequired(a?: i32, b: i32): void {} function optionalWithInitializerCannotPrecedeRequired(a: i32 = 1, b: i32): void {} function duplicateParams(a: i32, a: i32): void {} +duplicateParams(1, 2); // ERROR 1014: "A rest parameter must be last in a parameter list." in parameter-order.ts(5,37+1) // ERROR 1016: "A required parameter cannot follow an optional parameter." in parameter-order.ts(8,49+1) // ERROR 1016: "A required parameter cannot follow an optional parameter." in parameter-order.ts(11,67+1) -// ERROR 2300: "Duplicate identifier 'a'." in parameter-order.ts(14,34+1) From e2fff33d42f1c4aa8e652b6149ec4e5393fa1914 Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Tue, 25 May 2021 21:11:22 +0300 Subject: [PATCH 09/10] cleanup fixture --- tests/parser/parameter-order.ts.fixture.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/parser/parameter-order.ts.fixture.ts b/tests/parser/parameter-order.ts.fixture.ts index 908673fe85..e972dfe4d7 100644 --- a/tests/parser/parameter-order.ts.fixture.ts +++ b/tests/parser/parameter-order.ts.fixture.ts @@ -3,8 +3,6 @@ function optionalValid(a: i32, b?: i32): void {} function restParameterMustBeLast(...a: Array, b: i32): void {} function optionalCannotPrecedeRequired(a?: i32, b: i32): void {} function optionalWithInitializerCannotPrecedeRequired(a: i32 = 1, b: i32): void {} -function duplicateParams(a: i32, a: i32): void {} -duplicateParams(1, 2); // ERROR 1014: "A rest parameter must be last in a parameter list." in parameter-order.ts(5,37+1) // ERROR 1016: "A required parameter cannot follow an optional parameter." in parameter-order.ts(8,49+1) // ERROR 1016: "A required parameter cannot follow an optional parameter." in parameter-order.ts(11,67+1) From f1f1e8d22140e53bb779584d72c395d1fa626b07 Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Tue, 25 May 2021 21:25:00 +0300 Subject: [PATCH 10/10] inline and remove fast path --- src/compiler.ts | 53 ++++++++++++++++++------------------------------- 1 file changed, 19 insertions(+), 34 deletions(-) diff --git a/src/compiler.ts b/src/compiler.ts index cefe56a946..96de35973e 100644 --- a/src/compiler.ts +++ b/src/compiler.ts @@ -1454,39 +1454,6 @@ export class Compiler extends DiagnosticEmitter { // === Functions ================================================================================ - private ensureNonDuplicateFunctionParameters(instance: Function): void { - var parameters = instance.prototype.functionTypeNode.parameters; - var numParameters = parameters.length; - if (numParameters >= 2) { - if (numParameters == 2) { - // fast allocation free path for only 2 parameters - let secondParamIdentifier = parameters[1].name; - let secondParamName = secondParamIdentifier.text; - if (parameters[0].name.text == secondParamName) { - this.error( - DiagnosticCode.Duplicate_identifier_0, - secondParamIdentifier.range, secondParamName - ); - } - } else { - let visited = new Set(); - visited.add(parameters[0].name.text); - for (let i = 1; i < numParameters; i++) { - let paramIdentifier = parameters[i].name; - let paramName = paramIdentifier.text; - if (!visited.has(paramName)) { - visited.add(paramName); - } else { - this.error( - DiagnosticCode.Duplicate_identifier_0, - paramIdentifier.range, paramName - ); - } - } - } - } - } - /** Compiles a priorly resolved function. */ compileFunction( /** Function to compile. */ @@ -1504,7 +1471,25 @@ export class Compiler extends DiagnosticEmitter { } } - this.ensureNonDuplicateFunctionParameters(instance); + // ensure the function hasn't duplicate parameters + var parameters = instance.prototype.functionTypeNode.parameters; + var numParameters = parameters.length; + if (numParameters >= 2) { + let visited = new Set(); + visited.add(parameters[0].name.text); + for (let i = 1; i < numParameters; i++) { + let paramIdentifier = parameters[i].name; + let paramName = paramIdentifier.text; + if (!visited.has(paramName)) { + visited.add(paramName); + } else { + this.error( + DiagnosticCode.Duplicate_identifier_0, + paramIdentifier.range, paramName + ); + } + } + } instance.set(CommonFlags.COMPILED); var pendingElements = this.pendingElements;