From d6f103e2201e56d8245ad28e7743d60dbef0bb71 Mon Sep 17 00:00:00 2001 From: Joseph Junker Date: Fri, 9 Jun 2023 06:13:57 -0700 Subject: [PATCH] Fix injection of duplicate super calls into classes (#823) --- src/files/BrsFile.Class.spec.ts | 39 +++++++++++++++++++++++++++++++++ src/parser/Statement.ts | 18 ++++++++------- 2 files changed, 49 insertions(+), 8 deletions(-) diff --git a/src/files/BrsFile.Class.spec.ts b/src/files/BrsFile.Class.spec.ts index 970a8fef2..dac76ac56 100644 --- a/src/files/BrsFile.Class.spec.ts +++ b/src/files/BrsFile.Class.spec.ts @@ -298,6 +298,45 @@ describe('BrsFile BrighterScript classes', () => { `); }); + it('does not inject a call to super if one exists', () => { + testTranspile(` + class Animal + end class + class Duck extends Animal + sub new() + print "I am a statement which does not use m" + super() + end sub + end class + `, ` + function __Animal_builder() + instance = {} + instance.new = sub() + end sub + return instance + end function + function Animal() + instance = __Animal_builder() + instance.new() + return instance + end function + function __Duck_builder() + instance = __Animal_builder() + instance.super0_new = instance.new + instance.new = sub() + print "I am a statement which does not use m" + m.super0_new() + end sub + return instance + end function + function Duck() + instance = __Duck_builder() + instance.new() + return instance + end function + `); + }); + it('handles class inheritance inferred constructor calls', () => { testTranspile(` class Animal diff --git a/src/parser/Statement.ts b/src/parser/Statement.ts index 96428769c..e16e3f46d 100644 --- a/src/parser/Statement.ts +++ b/src/parser/Statement.ts @@ -2069,19 +2069,21 @@ export class MethodStatement extends FunctionStatement { return; } - //find the first non-comment statement - let firstStatement = this.func.body.statements.find(x => !isCommentStatement(x)); - //if the first statement is a call to super, quit here - if ( + //check whether any calls to super exist + let containsSuperCall = + this.func.body.statements.findIndex((x) => { //is a call statement - isExpressionStatement(firstStatement) && isCallExpression(firstStatement.expression) && + return isExpressionStatement(x) && isCallExpression(x.expression) && //is a call to super - util.findBeginningVariableExpression(firstStatement?.expression.callee as any).name.text.toLowerCase() === 'super' - ) { + util.findBeginningVariableExpression(x.expression.callee as any).name.text.toLowerCase() === 'super'; + }) !== -1; + + //if a call to super exists, quit here + if (containsSuperCall) { return; } - //this is a child class, and the first statement isn't a call to super. Inject one + //this is a child class, and the constructor doesn't contain a call to super. Inject one const superCall = new ExpressionStatement( new CallExpression( new VariableExpression(