@@ -17,19 +17,19 @@ import { BooleanType } from './types/BooleanType';
1717import { StringType } from './types/StringType' ;
1818import { IntegerType } from './types/IntegerType' ;
1919import { DynamicType } from './types/DynamicType' ;
20- import { ObjectType } from './types/ObjectType' ;
2120import { FloatType } from './types/FloatType' ;
2221import { NamespaceType } from './types/NamespaceType' ;
2322import { DoubleType } from './types/DoubleType' ;
2423import { UnionType } from './types/UnionType' ;
25- import { isForEachStatement , isFunctionExpression , isFunctionStatement , isNamespaceStatement } from './astUtils/reflection' ;
24+ import { isBlock , isForEachStatement , isFunctionExpression , isFunctionStatement , isNamespaceStatement } from './astUtils/reflection' ;
2625import { ArrayType } from './types/ArrayType' ;
2726import { AssociativeArrayType } from './types/AssociativeArrayType' ;
2827import { InterfaceType } from './types/InterfaceType' ;
2928import { ComponentType } from './types/ComponentType' ;
3029import * as path from 'path' ;
3130import { WalkMode , createVisitor } from './astUtils/visitors' ;
3231import type { FunctionExpression } from './parser/Expression' ;
32+ import { ObjectType } from './types' ;
3333
3434describe ( 'Scope' , ( ) => {
3535 let sinon = sinonImport . createSandbox ( ) ;
@@ -800,6 +800,71 @@ describe('Scope', () => {
800800 DiagnosticMessages . unknownBrightScriptComponent ( 'roFontMetrics' )
801801 ] ) ;
802802 } ) ;
803+
804+ it ( 'infers the correct type' , ( ) => {
805+ const file = program . setFile < BrsFile > ( `source/file.brs` , `
806+ sub main()
807+ scene = CreateObject("roSGScreen")
808+ button = CreateObject("roSGNode", "Button")
809+ list = CreateObject("roSGNode", "MarkupList")
810+ end sub
811+ ` ) ;
812+ program . validate ( ) ;
813+ expectZeroDiagnostics ( program ) ;
814+ const mainSymbolTable = file . ast . findChild ( isBlock ) . getSymbolTable ( ) ;
815+ const sceneType = mainSymbolTable . getSymbolType ( 'scene' , { flags : SymbolTypeFlag . runtime } ) as InterfaceType ;
816+ expectTypeToBe ( sceneType , InterfaceType ) ;
817+ expect ( sceneType . name ) . to . eq ( 'roSGScreen' ) ;
818+ const buttonType = mainSymbolTable . getSymbolType ( 'button' , { flags : SymbolTypeFlag . runtime } ) as InterfaceType ;
819+ expectTypeToBe ( buttonType , ComponentType ) ;
820+ expect ( buttonType . name ) . to . eq ( 'Button' ) ;
821+ const listType = mainSymbolTable . getSymbolType ( 'list' , { flags : SymbolTypeFlag . runtime } ) as InterfaceType ;
822+ expectTypeToBe ( listType , ComponentType ) ;
823+ expect ( listType . name ) . to . eq ( 'MarkupList' ) ;
824+ } ) ;
825+
826+ it ( 'infers custom component types' , ( ) => {
827+ program . setFile ( 'components/Comp1.xml' , trim `
828+ <?xml version="1.0" encoding="utf-8" ?>
829+ <component name="Comp1" extends="Group">
830+ </component>
831+ ` ) ;
832+ program . setFile ( 'components/Comp2.xml' , trim `
833+ <?xml version="1.0" encoding="utf-8" ?>
834+ <component name="Comp2" extends="Poster">
835+ </component>
836+ ` ) ;
837+ const file = program . setFile < BrsFile > ( `source/file.brs` , `
838+ sub main()
839+ comp1 = CreateObject("roSGNode", "Comp1")
840+ comp2 = CreateObject("roSGNode", "Comp2")
841+ end sub
842+ ` ) ;
843+ program . validate ( ) ;
844+ expectZeroDiagnostics ( program ) ;
845+ program . getScopeByName ( 'source' ) . linkSymbolTable ( ) ;
846+ const mainSymbolTable = file . ast . findChild ( isBlock ) . getSymbolTable ( ) ;
847+ const comp1Type = mainSymbolTable . getSymbolType ( 'comp1' , { flags : SymbolTypeFlag . runtime } ) as InterfaceType ;
848+ expectTypeToBe ( comp1Type , ComponentType ) ;
849+ expect ( comp1Type . name ) . to . eq ( 'Comp1' ) ;
850+ const comp2Type = mainSymbolTable . getSymbolType ( 'comp2' , { flags : SymbolTypeFlag . runtime } ) as InterfaceType ;
851+ expectTypeToBe ( comp2Type , ComponentType ) ;
852+ expect ( comp2Type . name ) . to . eq ( 'Comp2' ) ;
853+ } ) ;
854+
855+ it ( 'implies objectType by default' , ( ) => {
856+ const file = program . setFile < BrsFile > ( `source/file.brs` , `
857+ function getObj(myObjName)
858+ result = CreateObject(myObjName)
859+ return result
860+ end function
861+ ` ) ;
862+ program . validate ( ) ;
863+ expectZeroDiagnostics ( program ) ;
864+ const mainSymbolTable = file . ast . findChild ( isBlock ) . getSymbolTable ( ) ;
865+ const resultType = mainSymbolTable . getSymbolType ( 'result' , { flags : SymbolTypeFlag . runtime } ) ;
866+ expectTypeToBe ( resultType , ObjectType ) ;
867+ } ) ;
803868 } ) ;
804869
805870 it ( 'marks the scope as validated after validation has occurred' , ( ) => {
@@ -2589,9 +2654,9 @@ describe('Scope', () => {
25892654 expect ( mainFnScope ) . to . exist ;
25902655 const getTypeOptions = { flags : SymbolTypeFlag . runtime } ;
25912656 let dtType = mainFnScope . symbolTable . getSymbolType ( 'dt' , getTypeOptions ) ;
2592- expectTypeToBe ( dtType , ObjectType ) ;
2657+ expectTypeToBe ( dtType , InterfaceType ) ;
25932658 let hoursType = mainFnScope . symbolTable . getSymbolType ( 'hours' , getTypeOptions ) ;
2594- expectTypeToBe ( hoursType , DynamicType ) ;
2659+ expectTypeToBe ( hoursType , IntegerType ) ;
25952660 } ) ;
25962661
25972662 describe ( 'union types' , ( ) => {
0 commit comments