Skip to content

Commit

Permalink
Fix injection of duplicate super calls into classes (#823)
Browse files Browse the repository at this point in the history
  • Loading branch information
Joseph Junker authored Jun 9, 2023
1 parent f260abc commit d6f103e
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 8 deletions.
39 changes: 39 additions & 0 deletions src/files/BrsFile.Class.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
18 changes: 10 additions & 8 deletions src/parser/Statement.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down

0 comments on commit d6f103e

Please sign in to comment.