Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix typedef auto-generated class constructor funcs #535

Merged
merged 1 commit into from
Mar 9, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/astUtils/creators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -148,9 +148,9 @@ export function createFunctionExpression(kind: TokenKind.Sub | TokenKind.Functio
);
}

export function createClassMethodStatement(name: string, kind: TokenKind.Sub | TokenKind.Function = TokenKind.Function) {
export function createClassMethodStatement(name: string, kind: TokenKind.Sub | TokenKind.Function = TokenKind.Function, accessModifier?: Token) {
return new ClassMethodStatement(
createToken(TokenKind.Class),
accessModifier,
createIdentifier(name),
createFunctionExpression(kind),
null
Expand Down
33 changes: 32 additions & 1 deletion src/files/BrsFile.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2629,11 +2629,16 @@ describe('BrsFile', () => {
end class
class Duck extends Bird
end class
end namespace`, trim`
end namespace
`, trim`
namespace AnimalKingdom
class Bird
sub new()
end sub
end class
class Duck extends AnimalKingdom.Bird
sub new()
end sub
end class
end namespace
`);
Expand Down Expand Up @@ -2675,6 +2680,8 @@ describe('BrsFile', () => {
function getDuck()
end function
class Duck
sub new()
end sub
@anMember
@anMember("field")
private thing as dynamic
Expand Down Expand Up @@ -2737,13 +2744,17 @@ describe('BrsFile', () => {
end namespace
`, trim`
class Person
sub new()
end sub
public name as string
public age as integer
public sub getAge() as integer
end sub
end class
namespace NameA.NameB
class Person
sub new()
end sub
public name as string
public age as integer
public sub getAge() as integer
Expand All @@ -2753,6 +2764,18 @@ describe('BrsFile', () => {
`);
});

it('creates constructor properly', () => {
testTypedef(`
class Parent
end class
`, trim`
class Parent
sub new()
end sub
end class
`);
});

it('sets properties to dynamic when initialized to invalid', () => {
testTypedef(`
class Human
Expand All @@ -2761,6 +2784,8 @@ describe('BrsFile', () => {
end class
`, trim`
class Human
sub new()
end sub
public firstName as dynamic
public lastName as string
end class
Expand Down Expand Up @@ -2809,6 +2834,8 @@ describe('BrsFile', () => {
end class
`, trim`
class Human
sub new()
end sub
public firstName as string
protected middleName as string
private lastName as string
Expand Down Expand Up @@ -2836,10 +2863,14 @@ describe('BrsFile', () => {
end class
`, trim`
class Animal
sub new()
end sub
public sub speak()
end sub
end class
class Dog extends Animal
sub new()
end sub
public override sub speak()
end sub
end class
Expand Down
24 changes: 16 additions & 8 deletions src/parser/Statement.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1563,6 +1563,8 @@ export class ClassStatement extends Statement implements TypedefProvider {
}

getTypedef(state: BrsTranspileState) {
this.ensureConstructorFunctionExists();

const result = [] as TranspileResult;
for (let annotation of this.annotations ?? []) {
result.push(
Expand Down Expand Up @@ -1674,6 +1676,16 @@ export class ClassStatement extends Statement implements TypedefProvider {
return createClassMethodStatement('new', TokenKind.Sub);
}

/**
* Create an empty `new` function if class is missing it (simplifies transpile logic)
*/
private ensureConstructorFunctionExists() {
if (!this.getConstructorFunction()) {
this.memberMap.new = this.getEmptyNewFunction();
this.body = [this.memberMap.new, ...this.body];
}
}

/**
* Determine if the specified field was declared in one of the ancestor classes
*/
Expand All @@ -1693,6 +1705,8 @@ export class ClassStatement extends Statement implements TypedefProvider {
* without instantiating the parent constructor at that point in time.
*/
private getTranspiledBuilder(state: BrsTranspileState) {
this.ensureConstructorFunctionExists();

let result = [];
result.push(`function ${this.getBuilderName(this.getName(ParseMode.BrightScript))}()\n`);
state.blockDepth++;
Expand Down Expand Up @@ -1723,12 +1737,6 @@ export class ClassStatement extends Statement implements TypedefProvider {
);
let parentClassIndex = this.getParentClassIndex(state);

//create empty `new` function if class is missing it (simplifies transpile logic)
if (!this.getConstructorFunction()) {
this.memberMap.new = this.getEmptyNewFunction();
this.body = [this.memberMap.new, ...this.body];
}

for (let statement of this.body) {
//is field statement
if (isClassFieldStatement(statement)) {
Expand Down Expand Up @@ -1853,10 +1861,10 @@ export class ClassStatement extends Statement implements TypedefProvider {

export class ClassMethodStatement extends FunctionStatement {
constructor(
readonly accessModifier: Token,
public accessModifier: Token,
name: Identifier,
func: FunctionExpression,
readonly override: Token
public override: Token
) {
super(name, func, undefined);
this.range = util.createRangeFromPositions(
Expand Down