From 8ae5febdaefcbc52872edf1492f900db32fac610 Mon Sep 17 00:00:00 2001 From: Bronley Plumb Date: Fri, 8 Dec 2023 11:22:50 -0500 Subject: [PATCH] Fix broken enum transpiling --- src/Scope.ts | 1 - .../transpile/BrsFilePreTranspileProcessor.ts | 32 +++++++++---------- src/parser/Statement.ts | 7 ++++ src/parser/tests/statement/Enum.spec.ts | 18 +++++++++++ 4 files changed, 40 insertions(+), 18 deletions(-) diff --git a/src/Scope.ts b/src/Scope.ts index 2f1e3cc6d..932bef474 100644 --- a/src/Scope.ts +++ b/src/Scope.ts @@ -181,7 +181,6 @@ export class Scope { let member = enumeration.item.findChild((child) => isEnumMemberStatement(child) && child.name?.toLowerCase() === memberName); return member ? { item: member, file: enumeration.file } : undefined; } - return enumeration; } /** diff --git a/src/bscPlugin/transpile/BrsFilePreTranspileProcessor.ts b/src/bscPlugin/transpile/BrsFilePreTranspileProcessor.ts index f19107e58..2e7f60581 100644 --- a/src/bscPlugin/transpile/BrsFilePreTranspileProcessor.ts +++ b/src/bscPlugin/transpile/BrsFilePreTranspileProcessor.ts @@ -39,25 +39,13 @@ export class BrsFilePreTranspileProcessor { * For example, all of these would return the enum: `SomeNamespace.SomeEnum.SomeMember`, SomeEnum.SomeMember, `SomeEnum` */ private getEnumInfo(name: string, containingNamespace: string, scope: Scope) { - //look for the enum directly - let result = scope?.getEnumFileLink(name, containingNamespace); - if (result) { + //do we have an enum MEMBER reference? (i.e. SomeEnum.someMember or SomeNamespace.SomeEnum.SomeMember) + let memberLink = scope.getEnumMemberFileLink(name, containingNamespace); + if (memberLink) { + const value = memberLink.item.getValue(); return { - enum: result.item - }; - } - //assume we've been given the enum.member syntax, so pop the member and try again - const parts = name.toLowerCase().split('.'); - const memberName = parts.pop(); - if (containingNamespace && parts[0] !== containingNamespace.toLowerCase()) { - parts.unshift(containingNamespace.toLowerCase()); - } - result = scope?.getEnumMap().get(parts.join('.')); - if (result) { - const value = result.item.getMemberValue(memberName); - return { - enum: result.item, + enum: memberLink.item.parent, value: new LiteralExpression(createToken( //just use float literal for now...it will transpile properly with any literal value value.startsWith('"') ? TokenKind.StringLiteral : TokenKind.FloatLiteral, @@ -65,6 +53,16 @@ export class BrsFilePreTranspileProcessor { )) }; } + + //do we have an enum reference? (i.e. SomeEnum or SomeNamespace.SomeEnum) + let enumLink = scope?.getEnumFileLink(name, containingNamespace); + + if (enumLink) { + return { + enum: enumLink.item + }; + } + } private processExpression(expression: Expression, scope: Scope) { diff --git a/src/parser/Statement.ts b/src/parser/Statement.ts index 5f2fd7fc3..c98284f2f 100644 --- a/src/parser/Statement.ts +++ b/src/parser/Statement.ts @@ -2574,6 +2574,13 @@ export class EnumMemberStatement extends Statement implements TypedefProvider { ); } + /** + * Get the value of this enum. Requires that `.parent` is set + */ + public getValue() { + return (this.parent as EnumStatement).getMemberValue(this.name); + } + public transpile(state: BrsTranspileState): TranspileResult { return []; } diff --git a/src/parser/tests/statement/Enum.spec.ts b/src/parser/tests/statement/Enum.spec.ts index 806bb2268..5a11f1760 100644 --- a/src/parser/tests/statement/Enum.spec.ts +++ b/src/parser/tests/statement/Enum.spec.ts @@ -519,6 +519,24 @@ describe('EnumStatement', () => { }); describe('transpile', () => { + it('supports non-namespaced enum from within a namespace', () => { + program.options.autoImportComponentScript = true; + testTranspile(` + namespace alpha + sub test() + print Direction.up + end sub + end namespace + enum Direction + up = "up" + end enum + `, ` + sub alpha_test() + print "up" + end sub + `); + }); + it('transpiles negative number', () => { testTranspile(` sub main()