From 9c3238fb047a524f80ebc815c450da0eac998e35 Mon Sep 17 00:00:00 2001 From: Mark Pearce Date: Tue, 8 Oct 2024 09:04:43 -0300 Subject: [PATCH 1/3] Fixes using upper namespaced function indirectly --- .../validation/ScopeValidator.spec.ts | 38 +++++++++++++++++ src/files/BrsFile.spec.ts | 41 +++++++++++++++++++ src/parser/Statement.ts | 2 +- 3 files changed, 80 insertions(+), 1 deletion(-) diff --git a/src/bscPlugin/validation/ScopeValidator.spec.ts b/src/bscPlugin/validation/ScopeValidator.spec.ts index 0b6a1ac47..b9816d974 100644 --- a/src/bscPlugin/validation/ScopeValidator.spec.ts +++ b/src/bscPlugin/validation/ScopeValidator.spec.ts @@ -1839,6 +1839,44 @@ describe('ScopeValidator', () => { program.validate(); expectZeroDiagnostics(program); }); + + it('has error when referencing something in outer namespace directly', () => { + program.setFile('source/main.bs', ` + namespace alpha + sub foo() + end sub + + namespace beta + sub bar() + foo() + end sub + end namespace + end namespace + `); + + program.validate(); + expectDiagnostics(program, [ + DiagnosticMessages.cannotFindFunction('foo').message + ]); + }); + + it('allows referencing something in outer namespace with namespace in front', () => { + program.setFile('source/main.bs', ` + namespace alpha + sub foo() + end sub + + namespace beta + sub bar() + alpha.foo() + end sub + end namespace + end namespace + `); + + program.validate(); + expectZeroDiagnostics(program); + }); }); describe('itemCannotBeUsedAsVariable', () => { diff --git a/src/files/BrsFile.spec.ts b/src/files/BrsFile.spec.ts index 90ada058b..1b9fe0962 100644 --- a/src/files/BrsFile.spec.ts +++ b/src/files/BrsFile.spec.ts @@ -2344,6 +2344,47 @@ describe('BrsFile', () => { ); }); + it('transpiles namespaced functions when used as variables', async () => { + await testTranspile(` + namespace Vertibrates.Birds + function GetAllBirds() + return [ + GetDuck(), + GetGoose() + ] + end function + + function GetDuck() + end function + + function GetGoose() + end function + + function Test() + duckGetter = Vertibrates.Birds.GetDuck + gooseGetter = GetGoose + end function + end namespace`, ` + function Vertibrates_Birds_GetAllBirds() + return [ + Vertibrates_Birds_GetDuck() + Vertibrates_Birds_GetGoose() + ] + end function + + function Vertibrates_Birds_GetDuck() + end function + + function Vertibrates_Birds_GetGoose() + end function + + function Vertibrates_Birds_Test() + duckGetter = Vertibrates_Birds_GetDuck + gooseGetter = Vertibrates_Birds_GetGoose + end function + `); + }); + }); describe('shadowing', () => { diff --git a/src/parser/Statement.ts b/src/parser/Statement.ts index bd0f2b0a5..a8dc19850 100644 --- a/src/parser/Statement.ts +++ b/src/parser/Statement.ts @@ -1879,7 +1879,7 @@ export class NamespaceStatement extends Statement implements TypedefProvider { }; this.nameExpression = options.nameExpression; this.body = options.body; - this.symbolTable = new SymbolTable(`NamespaceStatement: '${this.name}'`, () => this.parent?.getSymbolTable()); + this.symbolTable = new SymbolTable(`NamespaceStatement: '${this.name}'`, () => this.getRoot()?.getSymbolTable()); } public readonly tokens: { From 8692f60fbae85e40867db70a241000adc73d9c95 Mon Sep 17 00:00:00 2001 From: Mark Pearce Date: Tue, 8 Oct 2024 09:10:59 -0300 Subject: [PATCH 2/3] Added test to verify validating correct function --- .../validation/ScopeValidator.spec.ts | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/src/bscPlugin/validation/ScopeValidator.spec.ts b/src/bscPlugin/validation/ScopeValidator.spec.ts index b9816d974..676548a3d 100644 --- a/src/bscPlugin/validation/ScopeValidator.spec.ts +++ b/src/bscPlugin/validation/ScopeValidator.spec.ts @@ -227,6 +227,30 @@ describe('ScopeValidator', () => { //should have an error expectZeroDiagnostics(program); }); + + it('validates against scope-defined func in inner namespace, when outer namespace has same named func', () => { + program.setFile('source/main.bs', ` + namespace alpha + sub foo() + end sub + + namespace beta + sub bar() + foo() + end sub + end namespace + end namespace + + function foo(x as integer) as integer + return x + end function + `); + + program.validate(); + expectDiagnostics(program, [ + DiagnosticMessages.mismatchArgumentCount(1, 0).message + ]); + }); }); describe('argumentTypeMismatch', () => { @@ -1877,6 +1901,28 @@ describe('ScopeValidator', () => { program.validate(); expectZeroDiagnostics(program); }); + + it('allows referencing scope-defined func in inner namespace, when outer namespace has same named func', () => { + program.setFile('source/main.bs', ` + namespace alpha + sub foo() + end sub + + namespace beta + sub bar() + foo(1) + end sub + end namespace + end namespace + + function foo(x as integer) as integer + return x + end function + `); + + program.validate(); + expectZeroDiagnostics(program); + }); }); describe('itemCannotBeUsedAsVariable', () => { From fc962a9782bf3a308ca74ed4c05b12561795f28f Mon Sep 17 00:00:00 2001 From: Mark Pearce Date: Tue, 8 Oct 2024 09:45:02 -0300 Subject: [PATCH 3/3] Clarifies namespace docs --- docs/namespaces.md | 46 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 42 insertions(+), 4 deletions(-) diff --git a/docs/namespaces.md b/docs/namespaces.md index 122279e25..b47bf73cd 100644 --- a/docs/namespaces.md +++ b/docs/namespaces.md @@ -110,14 +110,18 @@ end sub ``` -## Sharing name of namespaced item and non-namespaced item is prohibited -The compiler will throw an error whenever it encounters a namespaced function with the same name as a global function. The same rule applies to classes. +## Sharing name of namespaced item and non-namespaced items +The compiler allows a namespaced function with the same name as a global function. As per the [name-shadowing](./variable-shadowing.md) rules, the function inside the namespace will be used in the transpiled code. The same rule applies to classes. ```BrighterScript sub Quack() end sub namespace Vertibrates.Birds - sub Quack() ' this will result in a compile error. + sub Quack() + end sub + + sub Speak() + Quack() ' calls the function Vertibrates.Birds.Quack() end sub end namespace ``` @@ -128,7 +132,10 @@ end namespace ```BrightScript sub Quack() end sub -sub Vertibrates_Birds_Quack() ' this will result in a compile error. +sub Vertibrates_Birds_Quack() +end sub +sub Vertibrates_Birds_Speak() + Vertibrates_Birds_Quack() ' calls the function Vertibrates.Birds.Quack() end sub ``` @@ -161,3 +168,34 @@ sub Vertibrates_Reptiles_Hiss() end sub ``` + +## Calling parent namespace functions + +Brighterscript does not support accessing a function (or other entity) of a parent namespace without fully qualifying the name of the function. + +```BrighterScript +namespace Vertibrates + sub Move() + end sub + + namespace Birds + sub Fly() + Move() ' this is an error - no global Move() function + Vertibrates.Move() ' this is allowed + end sub + end namespace +end namespace +``` + +
+ View the transpiled BrightScript code + +```BrightScript +sub Vertibrates_Move() +end sub +sub Vertibrates_Birds_Fly() + Move() ' this is an error - no global Move() function + Vertibrates_Move() ' this is allowed +end sub +``` +
\ No newline at end of file