@@ -608,4 +608,258 @@ describe('BrsFileValidator', () => {
608608 } ) ;
609609 } ) ;
610610 } ) ;
611+
612+ describe ( 'unreferencable builtins' , ( ) => {
613+ const reservedBuiltinCode = DiagnosticMessages . reservedBuiltinUsedAsValue ( '' ) . code ;
614+
615+ function reservedBuiltinDiagnostics ( ) {
616+ return program . getDiagnostics ( ) . filter ( diagnostic => diagnostic . code === reservedBuiltinCode ) ;
617+ }
618+
619+ function expectFlagged ( names : string [ ] ) {
620+ expect (
621+ reservedBuiltinDiagnostics ( ) . map ( diagnostic => diagnostic . message )
622+ ) . to . eql (
623+ names . map ( name => DiagnosticMessages . reservedBuiltinUsedAsValue ( name ) . message )
624+ ) ;
625+ }
626+
627+ function expectNotFlagged ( ) {
628+ expect ( reservedBuiltinDiagnostics ( ) ) . to . eql ( [ ] ) ;
629+ }
630+
631+ it ( 'flags `x = ObjFun` (RHS value read)' , ( ) => {
632+ program . setFile ( 'source/main.brs' , `
633+ sub a()
634+ x = ObjFun
635+ print x
636+ end sub
637+ ` ) ;
638+ program . validate ( ) ;
639+ expectFlagged ( [ 'ObjFun' ] ) ;
640+ } ) ;
641+
642+ it ( 'flags `print type(ObjFun)` (passed as argument)' , ( ) => {
643+ program . setFile ( 'source/main.brs' , `
644+ sub a()
645+ print type(ObjFun)
646+ end sub
647+ ` ) ;
648+ program . validate ( ) ;
649+ expectFlagged ( [ 'ObjFun' ] ) ;
650+ } ) ;
651+
652+ it ( 'flags `f(ObjFun, 2)` (passed by value)' , ( ) => {
653+ program . setFile ( 'source/main.brs' , `
654+ sub a()
655+ f(ObjFun, 2)
656+ end sub
657+ sub f(arg1, arg2)
658+ end sub
659+ ` ) ;
660+ program . validate ( ) ;
661+ expectFlagged ( [ 'ObjFun' ] ) ;
662+ } ) ;
663+
664+ it ( 'flags `x = type` (RHS value read)' , ( ) => {
665+ program . setFile ( 'source/main.brs' , `
666+ sub a()
667+ x = type
668+ print x
669+ end sub
670+ ` ) ;
671+ program . validate ( ) ;
672+ expectFlagged ( [ 'type' ] ) ;
673+ } ) ;
674+
675+ it ( 'does not flag `ObjFun(m)` (canonical call)' , ( ) => {
676+ program . setFile ( 'source/main.brs' , `
677+ sub a()
678+ ObjFun(m, "")
679+ end sub
680+ ` ) ;
681+ program . validate ( ) ;
682+ expectNotFlagged ( ) ;
683+ } ) ;
684+
685+ it ( 'does not flag `type(123)` (canonical call)' , ( ) => {
686+ program . setFile ( 'source/main.brs' , `
687+ sub a()
688+ print type(123)
689+ end sub
690+ ` ) ;
691+ program . validate ( ) ;
692+ expectNotFlagged ( ) ;
693+ } ) ;
694+
695+ it ( 'does not flag `m.ObjFun = 1` (property assignment)' , ( ) => {
696+ program . setFile ( 'source/main.brs' , `
697+ sub a()
698+ m.ObjFun = 1
699+ end sub
700+ ` ) ;
701+ program . validate ( ) ;
702+ expectNotFlagged ( ) ;
703+ } ) ;
704+
705+ it ( 'does not flag `m.type = 1` (property assignment)' , ( ) => {
706+ program . setFile ( 'source/main.brs' , `
707+ sub a()
708+ m.type = 1
709+ end sub
710+ ` ) ;
711+ program . validate ( ) ;
712+ expectNotFlagged ( ) ;
713+ } ) ;
714+
715+ it ( 'does not flag `{ ObjFun: 1 }` (AA literal key)' , ( ) => {
716+ program . setFile ( 'source/main.brs' , `
717+ sub a()
718+ aa = { ObjFun: 1 }
719+ end sub
720+ ` ) ;
721+ program . validate ( ) ;
722+ expectNotFlagged ( ) ;
723+ } ) ;
724+
725+ it ( 'does not flag `{ type: 1 }` (AA literal key)' , ( ) => {
726+ program . setFile ( 'source/main.brs' , `
727+ sub a()
728+ aa = { type: 1 }
729+ end sub
730+ ` ) ;
731+ program . validate ( ) ;
732+ expectNotFlagged ( ) ;
733+ } ) ;
734+
735+ it ( 'does not flag a BrighterScript `type Name = ...` statement' , ( ) => {
736+ program . setFile ( 'source/main.bs' , `
737+ type MyAlias = string or integer
738+ ` ) ;
739+ program . validate ( ) ;
740+ expectNotFlagged ( ) ;
741+ } ) ;
742+
743+ it ( 'case-insensitive match for OBJFUN, ObjFun, objfun' , ( ) => {
744+ program . setFile ( 'source/main.brs' , `
745+ sub a()
746+ x = OBJFUN
747+ y = objfun
748+ end sub
749+ ` ) ;
750+ program . validate ( ) ;
751+ expectFlagged ( [ 'OBJFUN' , 'objfun' ] ) ;
752+ } ) ;
753+
754+ //per-builtin coverage for each device-verified entry in UnreferencableBuiltins.
755+ //each pair: (1) bare value read flags, (2) canonical call form does not flag.
756+
757+ it ( 'flags `x = Box` (RHS value read)' , ( ) => {
758+ program . setFile ( 'source/main.brs' , `sub a()\nx = Box\nend sub` ) ;
759+ program . validate ( ) ;
760+ expectFlagged ( [ 'Box' ] ) ;
761+ } ) ;
762+
763+ it ( 'does not flag `Box(1)` (canonical call)' , ( ) => {
764+ program . setFile ( 'source/main.brs' , `sub a()\nx = Box(1)\nend sub` ) ;
765+ program . validate ( ) ;
766+ expectNotFlagged ( ) ;
767+ } ) ;
768+
769+ it ( 'flags `x = CreateObject` (RHS value read)' , ( ) => {
770+ program . setFile ( 'source/main.brs' , `sub a()\nx = CreateObject\nend sub` ) ;
771+ program . validate ( ) ;
772+ expectFlagged ( [ 'CreateObject' ] ) ;
773+ } ) ;
774+
775+ it ( 'does not flag `CreateObject("roSGNode", "Node")` (canonical call)' , ( ) => {
776+ program . setFile ( 'source/main.brs' , `sub a()\nx = CreateObject("roSGNode", "Node")\nend sub` ) ;
777+ program . validate ( ) ;
778+ expectNotFlagged ( ) ;
779+ } ) ;
780+
781+ it ( 'flags `x = GetGlobalAA` (RHS value read)' , ( ) => {
782+ program . setFile ( 'source/main.brs' , `sub a()\nx = GetGlobalAA\nend sub` ) ;
783+ program . validate ( ) ;
784+ expectFlagged ( [ 'GetGlobalAA' ] ) ;
785+ } ) ;
786+
787+ it ( 'does not flag `GetGlobalAA()` (canonical call)' , ( ) => {
788+ program . setFile ( 'source/main.brs' , `sub a()\nx = GetGlobalAA()\nend sub` ) ;
789+ program . validate ( ) ;
790+ expectNotFlagged ( ) ;
791+ } ) ;
792+
793+ it ( 'flags `x = GetLastRunCompileError` (RHS value read)' , ( ) => {
794+ program . setFile ( 'source/main.brs' , `sub a()\nx = GetLastRunCompileError\nend sub` ) ;
795+ program . validate ( ) ;
796+ expectFlagged ( [ 'GetLastRunCompileError' ] ) ;
797+ } ) ;
798+
799+ it ( 'does not flag `GetLastRunCompileError()` (canonical call)' , ( ) => {
800+ program . setFile ( 'source/main.brs' , `sub a()\nx = GetLastRunCompileError()\nend sub` ) ;
801+ program . validate ( ) ;
802+ expectNotFlagged ( ) ;
803+ } ) ;
804+
805+ it ( 'flags `x = GetLastRunRunTimeError` (RHS value read)' , ( ) => {
806+ program . setFile ( 'source/main.brs' , `sub a()\nx = GetLastRunRunTimeError\nend sub` ) ;
807+ program . validate ( ) ;
808+ expectFlagged ( [ 'GetLastRunRunTimeError' ] ) ;
809+ } ) ;
810+
811+ it ( 'does not flag `GetLastRunRunTimeError()` (canonical call)' , ( ) => {
812+ program . setFile ( 'source/main.brs' , `sub a()\nx = GetLastRunRunTimeError()\nend sub` ) ;
813+ program . validate ( ) ;
814+ expectNotFlagged ( ) ;
815+ } ) ;
816+
817+ it ( 'flags `x = Pos` (RHS value read)' , ( ) => {
818+ program . setFile ( 'source/main.brs' , `sub a()\nx = Pos\nend sub` ) ;
819+ program . validate ( ) ;
820+ expectFlagged ( [ 'Pos' ] ) ;
821+ } ) ;
822+
823+ it ( 'does not flag `Pos(0)` (canonical call)' , ( ) => {
824+ program . setFile ( 'source/main.brs' , `sub a()\nx = Pos(0)\nend sub` ) ;
825+ program . validate ( ) ;
826+ expectNotFlagged ( ) ;
827+ } ) ;
828+
829+ it ( 'flags `x = Run` (RHS value read)' , ( ) => {
830+ program . setFile ( 'source/main.brs' , `sub a()\nx = Run\nend sub` ) ;
831+ program . validate ( ) ;
832+ expectFlagged ( [ 'Run' ] ) ;
833+ } ) ;
834+
835+ it ( 'does not flag `Run("pkg:/source/foo.brs")` (canonical call)' , ( ) => {
836+ program . setFile ( 'source/main.brs' , `sub a()\nx = Run("pkg:/source/foo.brs")\nend sub` ) ;
837+ program . validate ( ) ;
838+ expectNotFlagged ( ) ;
839+ } ) ;
840+
841+ it ( 'flags `x = Tab` (RHS value read)' , ( ) => {
842+ program . setFile ( 'source/main.brs' , `sub a()\nx = Tab\nend sub` ) ;
843+ program . validate ( ) ;
844+ expectFlagged ( [ 'Tab' ] ) ;
845+ } ) ;
846+
847+ it ( 'does not flag `Tab(5)` (canonical call)' , ( ) => {
848+ program . setFile ( 'source/main.brs' , `sub a()\nx = Tab(5)\nend sub` ) ;
849+ program . validate ( ) ;
850+ expectNotFlagged ( ) ;
851+ } ) ;
852+
853+ it ( 'flags `x = eval` (RHS value read)' , ( ) => {
854+ program . setFile ( 'source/main.brs' , `sub a()\nx = eval\nend sub` ) ;
855+ program . validate ( ) ;
856+ expectFlagged ( [ 'eval' ] ) ;
857+ } ) ;
858+
859+ it ( 'does not flag `eval("print 1")` (canonical call)' , ( ) => {
860+ program . setFile ( 'source/main.brs' , `sub a()\neval("print 1")\nend sub` ) ;
861+ program . validate ( ) ;
862+ expectNotFlagged ( ) ;
863+ } ) ;
864+ } ) ;
611865} ) ;
0 commit comments