brighterscript 0.66.0-alpha.4 → 0.66.0-alpha.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (214) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/dist/DiagnosticMessages.d.ts +21 -3
  3. package/dist/DiagnosticMessages.js +35 -2
  4. package/dist/DiagnosticMessages.js.map +1 -1
  5. package/dist/LanguageServer.d.ts +1 -0
  6. package/dist/LanguageServer.js +8 -5
  7. package/dist/LanguageServer.js.map +1 -1
  8. package/dist/Program.d.ts +20 -8
  9. package/dist/Program.js +107 -60
  10. package/dist/Program.js.map +1 -1
  11. package/dist/ProgramBuilder.js +14 -2
  12. package/dist/ProgramBuilder.js.map +1 -1
  13. package/dist/Scope.d.ts +15 -13
  14. package/dist/Scope.js +26 -65
  15. package/dist/Scope.js.map +1 -1
  16. package/dist/SymbolTable.d.ts +17 -10
  17. package/dist/SymbolTable.js +48 -26
  18. package/dist/SymbolTable.js.map +1 -1
  19. package/dist/XmlScope.d.ts +2 -0
  20. package/dist/XmlScope.js +38 -0
  21. package/dist/XmlScope.js.map +1 -1
  22. package/dist/astUtils/creators.d.ts +3 -1
  23. package/dist/astUtils/creators.js +14 -4
  24. package/dist/astUtils/creators.js.map +1 -1
  25. package/dist/astUtils/reflection.d.ts +24 -5
  26. package/dist/astUtils/reflection.js +58 -13
  27. package/dist/astUtils/reflection.js.map +1 -1
  28. package/dist/astUtils/reflection.spec.js +85 -3
  29. package/dist/astUtils/reflection.spec.js.map +1 -1
  30. package/dist/bscPlugin/CallExpressionInfo.d.ts +3 -3
  31. package/dist/bscPlugin/CallExpressionInfo.js.map +1 -1
  32. package/dist/bscPlugin/codeActions/CodeActionsProcessor.spec.js +4 -4
  33. package/dist/bscPlugin/codeActions/CodeActionsProcessor.spec.js.map +1 -1
  34. package/dist/bscPlugin/completions/CompletionsProcessor.d.ts +44 -1
  35. package/dist/bscPlugin/completions/CompletionsProcessor.js +353 -20
  36. package/dist/bscPlugin/completions/CompletionsProcessor.js.map +1 -1
  37. package/dist/bscPlugin/completions/CompletionsProcessor.spec.d.ts +1 -0
  38. package/dist/bscPlugin/completions/CompletionsProcessor.spec.js +1452 -0
  39. package/dist/bscPlugin/completions/CompletionsProcessor.spec.js.map +1 -0
  40. package/dist/bscPlugin/hover/HoverProcessor.d.ts +9 -4
  41. package/dist/bscPlugin/hover/HoverProcessor.js +64 -67
  42. package/dist/bscPlugin/hover/HoverProcessor.js.map +1 -1
  43. package/dist/bscPlugin/hover/HoverProcessor.spec.js +162 -4
  44. package/dist/bscPlugin/hover/HoverProcessor.spec.js.map +1 -1
  45. package/dist/bscPlugin/validation/BrsFileValidator.js +20 -16
  46. package/dist/bscPlugin/validation/BrsFileValidator.js.map +1 -1
  47. package/dist/bscPlugin/validation/ScopeValidator.d.ts +22 -1
  48. package/dist/bscPlugin/validation/ScopeValidator.js +194 -42
  49. package/dist/bscPlugin/validation/ScopeValidator.js.map +1 -1
  50. package/dist/bscPlugin/validation/ScopeValidator.spec.js +621 -1
  51. package/dist/bscPlugin/validation/ScopeValidator.spec.js.map +1 -1
  52. package/dist/diagnosticUtils.d.ts +7 -2
  53. package/dist/diagnosticUtils.js +43 -15
  54. package/dist/diagnosticUtils.js.map +1 -1
  55. package/dist/files/BrsFile.Class.spec.js +10 -8
  56. package/dist/files/BrsFile.Class.spec.js.map +1 -1
  57. package/dist/files/BrsFile.d.ts +3 -20
  58. package/dist/files/BrsFile.js +7 -355
  59. package/dist/files/BrsFile.js.map +1 -1
  60. package/dist/files/BrsFile.spec.js +2 -248
  61. package/dist/files/BrsFile.spec.js.map +1 -1
  62. package/dist/files/XmlFile.d.ts +1 -6
  63. package/dist/files/XmlFile.js +0 -13
  64. package/dist/files/XmlFile.js.map +1 -1
  65. package/dist/files/XmlFile.spec.js +0 -36
  66. package/dist/files/XmlFile.spec.js.map +1 -1
  67. package/dist/globalCallables.js +1 -5
  68. package/dist/globalCallables.js.map +1 -1
  69. package/dist/interfaces.d.ts +22 -2
  70. package/dist/interfaces.js +4 -1
  71. package/dist/interfaces.js.map +1 -1
  72. package/dist/lexer/Lexer.d.ts +12 -0
  73. package/dist/lexer/Lexer.js +27 -2
  74. package/dist/lexer/Lexer.js.map +1 -1
  75. package/dist/lexer/Lexer.spec.js +40 -0
  76. package/dist/lexer/Lexer.spec.js.map +1 -1
  77. package/dist/lexer/Token.d.ts +4 -0
  78. package/dist/lexer/Token.js.map +1 -1
  79. package/dist/lexer/TokenKind.d.ts +4 -0
  80. package/dist/lexer/TokenKind.js +10 -1
  81. package/dist/lexer/TokenKind.js.map +1 -1
  82. package/dist/parser/AstNode.d.ts +8 -1
  83. package/dist/parser/AstNode.js +16 -0
  84. package/dist/parser/AstNode.js.map +1 -1
  85. package/dist/parser/Expression.d.ts +16 -1
  86. package/dist/parser/Expression.js +75 -11
  87. package/dist/parser/Expression.js.map +1 -1
  88. package/dist/parser/Parser.d.ts +7 -0
  89. package/dist/parser/Parser.js +55 -7
  90. package/dist/parser/Parser.js.map +1 -1
  91. package/dist/parser/Parser.spec.js +330 -4
  92. package/dist/parser/Parser.spec.js.map +1 -1
  93. package/dist/parser/SGTypes.d.ts +1 -1
  94. package/dist/parser/Statement.d.ts +18 -6
  95. package/dist/parser/Statement.js +54 -16
  96. package/dist/parser/Statement.js.map +1 -1
  97. package/dist/parser/tests/Parser.spec.js +2 -1
  98. package/dist/parser/tests/Parser.spec.js.map +1 -1
  99. package/dist/parser/tests/controlFlow/For.spec.js +16 -8
  100. package/dist/parser/tests/controlFlow/For.spec.js.map +1 -1
  101. package/dist/parser/tests/controlFlow/ForEach.spec.js +12 -6
  102. package/dist/parser/tests/controlFlow/ForEach.spec.js.map +1 -1
  103. package/dist/parser/tests/controlFlow/While.spec.js +8 -4
  104. package/dist/parser/tests/controlFlow/While.spec.js.map +1 -1
  105. package/dist/parser/tests/expression/Call.spec.js +4 -4
  106. package/dist/parser/tests/expression/Call.spec.js.map +1 -1
  107. package/dist/parser/tests/expression/NullCoalescenceExpression.spec.js +13 -13
  108. package/dist/parser/tests/expression/NullCoalescenceExpression.spec.js.map +1 -1
  109. package/dist/parser/tests/statement/ConstStatement.spec.js +1 -34
  110. package/dist/parser/tests/statement/ConstStatement.spec.js.map +1 -1
  111. package/dist/parser/tests/statement/Enum.spec.js +1 -257
  112. package/dist/parser/tests/statement/Enum.spec.js.map +1 -1
  113. package/dist/parser/tests/statement/InterfaceStatement.spec.js +8 -0
  114. package/dist/parser/tests/statement/InterfaceStatement.spec.js.map +1 -1
  115. package/dist/parser/tests/statement/PrintStatement.spec.js +6 -3
  116. package/dist/parser/tests/statement/PrintStatement.spec.js.map +1 -1
  117. package/dist/parser/tests/statement/ReturnStatement.spec.js +5 -3
  118. package/dist/parser/tests/statement/ReturnStatement.spec.js.map +1 -1
  119. package/dist/parser/tests/statement/Set.spec.js +26 -13
  120. package/dist/parser/tests/statement/Set.spec.js.map +1 -1
  121. package/dist/roku-types/data.json +156 -111
  122. package/dist/roku-types/index.d.ts +2 -27
  123. package/dist/types/ArrayType.d.ts +4 -1
  124. package/dist/types/ArrayType.js +43 -7
  125. package/dist/types/ArrayType.js.map +1 -1
  126. package/dist/types/ArrayType.spec.js +31 -2
  127. package/dist/types/ArrayType.spec.js.map +1 -1
  128. package/dist/types/AssociativeArrayType.d.ts +11 -0
  129. package/dist/types/AssociativeArrayType.js +52 -0
  130. package/dist/types/AssociativeArrayType.js.map +1 -0
  131. package/dist/types/BaseFunctionType.d.ts +2 -1
  132. package/dist/types/BaseFunctionType.js +1 -1
  133. package/dist/types/BaseFunctionType.js.map +1 -1
  134. package/dist/types/BooleanType.d.ts +2 -4
  135. package/dist/types/BooleanType.js +6 -7
  136. package/dist/types/BooleanType.js.map +1 -1
  137. package/dist/types/BscType.d.ts +8 -4
  138. package/dist/types/BscType.js +42 -14
  139. package/dist/types/BscType.js.map +1 -1
  140. package/dist/types/BscTypeKind.d.ts +2 -0
  141. package/dist/types/BscTypeKind.js +2 -0
  142. package/dist/types/BscTypeKind.js.map +1 -1
  143. package/dist/types/BuiltInInterfaceAdder.d.ts +20 -0
  144. package/dist/types/BuiltInInterfaceAdder.js +139 -0
  145. package/dist/types/BuiltInInterfaceAdder.js.map +1 -0
  146. package/dist/types/BuiltInInterfaceAdder.spec.d.ts +1 -0
  147. package/dist/types/BuiltInInterfaceAdder.spec.js +109 -0
  148. package/dist/types/BuiltInInterfaceAdder.spec.js.map +1 -0
  149. package/dist/types/ClassType.d.ts +6 -1
  150. package/dist/types/ClassType.js +26 -2
  151. package/dist/types/ClassType.js.map +1 -1
  152. package/dist/types/ComponentType.d.ts +26 -0
  153. package/dist/types/ComponentType.js +80 -0
  154. package/dist/types/ComponentType.js.map +1 -0
  155. package/dist/types/DoubleType.d.ts +2 -4
  156. package/dist/types/DoubleType.js +6 -7
  157. package/dist/types/DoubleType.js.map +1 -1
  158. package/dist/types/DynamicType.d.ts +2 -2
  159. package/dist/types/DynamicType.js +3 -1
  160. package/dist/types/DynamicType.js.map +1 -1
  161. package/dist/types/EnumType.d.ts +4 -5
  162. package/dist/types/EnumType.js +8 -7
  163. package/dist/types/EnumType.js.map +1 -1
  164. package/dist/types/FloatType.d.ts +2 -4
  165. package/dist/types/FloatType.js +6 -7
  166. package/dist/types/FloatType.js.map +1 -1
  167. package/dist/types/FunctionType.d.ts +2 -1
  168. package/dist/types/FunctionType.js +6 -2
  169. package/dist/types/FunctionType.js.map +1 -1
  170. package/dist/types/IntegerType.d.ts +2 -4
  171. package/dist/types/IntegerType.js +6 -7
  172. package/dist/types/IntegerType.js.map +1 -1
  173. package/dist/types/InterfaceType.d.ts +2 -1
  174. package/dist/types/InterfaceType.js +8 -4
  175. package/dist/types/InterfaceType.js.map +1 -1
  176. package/dist/types/InterfaceType.spec.js +2 -2
  177. package/dist/types/InvalidType.d.ts +1 -1
  178. package/dist/types/InvalidType.js +5 -1
  179. package/dist/types/InvalidType.js.map +1 -1
  180. package/dist/types/LongIntegerType.d.ts +2 -4
  181. package/dist/types/LongIntegerType.js +6 -7
  182. package/dist/types/LongIntegerType.js.map +1 -1
  183. package/dist/types/ObjectType.d.ts +3 -3
  184. package/dist/types/ObjectType.js +3 -1
  185. package/dist/types/ObjectType.js.map +1 -1
  186. package/dist/types/ReferenceType.d.ts +14 -0
  187. package/dist/types/ReferenceType.js +114 -13
  188. package/dist/types/ReferenceType.js.map +1 -1
  189. package/dist/types/ReferenceType.spec.js +15 -0
  190. package/dist/types/ReferenceType.spec.js.map +1 -1
  191. package/dist/types/StringType.d.ts +2 -4
  192. package/dist/types/StringType.js +5 -6
  193. package/dist/types/StringType.js.map +1 -1
  194. package/dist/types/TypedFunctionType.d.ts +2 -1
  195. package/dist/types/TypedFunctionType.js +10 -3
  196. package/dist/types/TypedFunctionType.js.map +1 -1
  197. package/dist/types/UninitializedType.d.ts +2 -1
  198. package/dist/types/UninitializedType.js +1 -1
  199. package/dist/types/UninitializedType.js.map +1 -1
  200. package/dist/types/UnionType.d.ts +4 -2
  201. package/dist/types/UnionType.js +25 -4
  202. package/dist/types/UnionType.js.map +1 -1
  203. package/dist/types/UnionType.spec.js +46 -19
  204. package/dist/types/UnionType.spec.js.map +1 -1
  205. package/dist/types/VoidType.d.ts +2 -1
  206. package/dist/types/VoidType.js +6 -2
  207. package/dist/types/VoidType.js.map +1 -1
  208. package/dist/types/helpers.d.ts +2 -0
  209. package/dist/types/helpers.js +18 -3
  210. package/dist/types/helpers.js.map +1 -1
  211. package/dist/util.d.ts +25 -2
  212. package/dist/util.js +179 -13
  213. package/dist/util.js.map +1 -1
  214. package/package.json +1 -1
@@ -5,6 +5,8 @@ const DiagnosticMessages_1 = require("../../DiagnosticMessages");
5
5
  const Program_1 = require("../../Program");
6
6
  const testHelpers_spec_1 = require("../../testHelpers.spec");
7
7
  const chai_1 = require("chai");
8
+ const IntegerType_1 = require("../../types/IntegerType");
9
+ const StringType_1 = require("../../types/StringType");
8
10
  describe('ScopeValidator', () => {
9
11
  let sinon = sinonImport.createSandbox();
10
12
  let rootDir = process.cwd();
@@ -265,7 +267,7 @@ describe('ScopeValidator', () => {
265
267
  `);
266
268
  program.validate();
267
269
  (0, testHelpers_spec_1.expectDiagnostics)(program, [
268
- DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('string', 'Direction')
270
+ DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('string', 'Direction').message
269
271
  ]);
270
272
  });
271
273
  it('supports passing enum type as enum type', () => {
@@ -697,6 +699,255 @@ describe('ScopeValidator', () => {
697
699
  //should have no errors
698
700
  (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
699
701
  });
702
+ it('allows calling future function and save to same variable', () => {
703
+ program.setFile('source/util.brs', `
704
+ function getSomeInt() as integer
705
+ numVal = getUntypedNum()
706
+ numVal = cInt(numVal)
707
+ return numVal
708
+ end function
709
+
710
+ function getUntypedNum()
711
+ return 1
712
+ end function
713
+ `);
714
+ program.validate();
715
+ //should have no errors
716
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
717
+ });
718
+ it('allows union types of all compatible types as arg', () => {
719
+ program.setFile('source/util.bs', `
720
+ sub printIntNum(num as float or double or integer)
721
+ print cInt(num)
722
+ end sub
723
+ `);
724
+ program.validate();
725
+ //should have no errors
726
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
727
+ });
728
+ it('allows function calls of built-in members of primitives', () => {
729
+ program.setFile('source/util.brs', `
730
+ sub doSomething()
731
+ myStr = "Hello World"
732
+ myStr = myStr.replace("World", "You")
733
+ print myStr
734
+ end sub
735
+ `);
736
+ program.validate();
737
+ //should have no errors
738
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
739
+ });
740
+ it('validates union types of all compatible types as arg - when some do not work', () => {
741
+ program.setFile('source/util.bs', `
742
+ sub printIntNum(maybeNum as float or string)
743
+ print cInt(maybeNum)
744
+ end sub
745
+ `);
746
+ program.validate();
747
+ //should have no errors
748
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
749
+ DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('float or string', 'float').message
750
+ ]);
751
+ });
752
+ it('validates function calls of built-in members of primitives', () => {
753
+ program.setFile('source/util.brs', `
754
+ sub doSomething()
755
+ myStr = "Hello World"
756
+ notAString = 3.14
757
+ myStr = myStr.replace("World", notAString)
758
+ print myStr
759
+ end sub
760
+ `);
761
+ program.validate();
762
+ //should have error - 2nd param should be a string, not a float
763
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
764
+ DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('float', 'string').message
765
+ ]);
766
+ });
767
+ it('validates method calls of classes', () => {
768
+ program.setFile('source/util.bs', `
769
+ class Klass
770
+ sub test(input as string)
771
+ end sub
772
+ end class
773
+
774
+ sub doSomething()
775
+ k = new Klass()
776
+ k.test(3.14)
777
+ end sub
778
+ `);
779
+ program.validate();
780
+ //should have error - param should be a string, not a float
781
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
782
+ DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('float', 'string').message
783
+ ]);
784
+ });
785
+ it('validates inside method calls of classes', () => {
786
+ program.setFile('source/util.bs', `
787
+ class Klass
788
+ sub test(input as string)
789
+ end sub
790
+
791
+ sub otherTest()
792
+ m.test(3.14)
793
+ end sub
794
+ end class
795
+ `);
796
+ program.validate();
797
+ //should have error - param should be a string, not a float
798
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
799
+ DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('float', 'string').message
800
+ ]);
801
+ });
802
+ it('validates calls of a constructor', () => {
803
+ program.setFile('source/util.bs', `
804
+ class Klass
805
+ sub new(name as string)
806
+ end sub
807
+ end class
808
+
809
+ sub createKlass()
810
+ k = new Klass(3.14)
811
+ end sub
812
+ `);
813
+ program.validate();
814
+ //should have error - param should be a string, not a float
815
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
816
+ DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('float', 'string').message
817
+ ]);
818
+ });
819
+ it('validates super calls in a constructor', () => {
820
+ program.setFile('source/util.bs', `
821
+ class Klass
822
+ sub new(name as string)
823
+ end sub
824
+ end class
825
+
826
+ class SubKlass extends Klass
827
+ sub new()
828
+ super(3.14)
829
+ end sub
830
+ end class
831
+ `);
832
+ program.validate();
833
+ //should have error - param should be a string, not a float
834
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
835
+ DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('float', 'string').message
836
+ ]);
837
+ });
838
+ it('validates super calls in a class methods', () => {
839
+ program.setFile('source/util.bs', `
840
+ class Klass
841
+ sub test(name as string)
842
+ end sub
843
+ end class
844
+
845
+ class SubKlass extends Klass
846
+ sub test2()
847
+ super.test(3.14)
848
+ end sub
849
+ end class
850
+ `);
851
+ program.validate();
852
+ //should have error - param should be a string, not a float
853
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
854
+ DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('float', 'string').message
855
+ ]);
856
+ });
857
+ it('validates a function passed as an arg', () => {
858
+ program.setFile('source/util.bs', `
859
+ sub foo()
860
+ getPi = function()
861
+ return 3.14
862
+ end function
863
+ bar(getPi)
864
+ end sub
865
+
866
+
867
+ sub bar(num as integer)
868
+ print num
869
+ end sub
870
+ `);
871
+ program.validate();
872
+ //should have error - param should be a string, not a float
873
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
874
+ DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('function () as dynamic', 'integer').message
875
+ ]);
876
+ });
877
+ it('allows AAs that match an interface to be passed as args', () => {
878
+ program.setFile('source/util.bs', `
879
+ sub doStuff()
880
+ takesMyIface({beta: "hello", charlie: "world"})
881
+ end sub
882
+
883
+ sub takesMyIface(iFace as MyIFace)
884
+ end sub
885
+
886
+ interface MyIFace
887
+ beta as string
888
+ charlie as string
889
+ end interface
890
+ `);
891
+ program.validate();
892
+ //should have error
893
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
894
+ });
895
+ it('validates empty AAs that are passed as args to param expecting interface', () => {
896
+ program.setFile('source/util.bs', `
897
+ sub doStuff()
898
+ takesMyIface({})
899
+ end sub
900
+
901
+ sub takesMyIface(iFace as MyIFace)
902
+ end sub
903
+
904
+ interface MyIFace
905
+ beta as string
906
+ charlie as string
907
+ end interface
908
+ `);
909
+ program.validate();
910
+ //should have error
911
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
912
+ DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('roAssociativeArray', 'MyIFace', {
913
+ missingFields: [{ name: 'beta', expectedType: StringType_1.StringType.instance }, { name: 'charlie', expectedType: StringType_1.StringType.instance }]
914
+ }).message
915
+ ]);
916
+ });
917
+ it('includes data on missing fields', () => {
918
+ program.setFile('source/util.bs', `
919
+ sub doStuff()
920
+ takesMyIface({charlie: "hello"})
921
+ end sub
922
+
923
+ sub takesMyIface(iFace as MyIFace)
924
+ end sub
925
+
926
+ interface MyIFace
927
+ beta as string
928
+ charlie as integer
929
+ end interface
930
+ `);
931
+ program.validate();
932
+ //should have error
933
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
934
+ DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('roAssociativeArray', 'MyIFace', {
935
+ missingFields: [{ name: 'beta', expectedType: StringType_1.StringType.instance }],
936
+ fieldMismatches: [{ name: 'charlie', expectedType: IntegerType_1.IntegerType.instance, actualType: StringType_1.StringType.instance }]
937
+ }).message
938
+ ]);
939
+ //The aa should have 'beta' and 'charlie' properties of type string and integer
940
+ const diagnostics = program.getDiagnostics();
941
+ (0, chai_1.expect)(diagnostics.length).to.eq(1);
942
+ const data = diagnostics[0].data;
943
+ (0, chai_1.expect)(data.missingFields.length).to.eq(1);
944
+ (0, chai_1.expect)(data.missingFields[0].name).to.eq('beta');
945
+ (0, testHelpers_spec_1.expectTypeToBe)(data.missingFields[0].expectedType, StringType_1.StringType);
946
+ (0, chai_1.expect)(data.fieldMismatches.length).to.eq(1);
947
+ (0, chai_1.expect)(data.fieldMismatches[0].name).to.eq('charlie');
948
+ (0, testHelpers_spec_1.expectTypeToBe)(data.fieldMismatches[0].expectedType, IntegerType_1.IntegerType);
949
+ (0, testHelpers_spec_1.expectTypeToBe)(data.fieldMismatches[0].actualType, StringType_1.StringType);
950
+ });
700
951
  });
701
952
  describe('cannotFindName', () => {
702
953
  it('finds variables from assignments from member functions of primitive types', () => {
@@ -710,6 +961,375 @@ describe('ScopeValidator', () => {
710
961
  //should have no errors
711
962
  (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
712
963
  });
964
+ it('validates when lhs of compound assignment does not exist', () => {
965
+ program.setFile('source/util.brs', `
966
+ sub main()
967
+ expected += chr(10) + " version=""2.0"""
968
+ end sub
969
+ `);
970
+ program.validate();
971
+ //should have error - cannot find "expected"
972
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
973
+ DiagnosticMessages_1.DiagnosticMessages.cannotFindName('expected').message
974
+ ]);
975
+ });
976
+ });
977
+ describe('returnTypeMismatch', () => {
978
+ it('finds when a function returns a type that is not what was declared', () => {
979
+ program.setFile('source/util.bs', `
980
+ function getPi() as float
981
+ return "apple" ' get it?
982
+ end function
983
+ `);
984
+ program.validate();
985
+ //should have error - return value should be a float, not a string
986
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
987
+ DiagnosticMessages_1.DiagnosticMessages.returnTypeMismatch('string', 'float').message
988
+ ]);
989
+ });
990
+ it('finds all return statements that do not match', () => {
991
+ program.setFile('source/util.bs', `
992
+ function getPi(kind as integer) as float
993
+ if kind = 1
994
+ return "apple"
995
+ else if kind = 2
996
+ return false
997
+ else if kind = 3
998
+ return new Pie("lemon")
999
+ end if
1000
+ return 3.14
1001
+ end function
1002
+
1003
+ class Pie
1004
+ kind as string
1005
+ sub new(kind as string)
1006
+ m.kind = kind
1007
+ end sub
1008
+ end class
1009
+ `);
1010
+ program.validate();
1011
+ //should have error - return value should be a float, not whatever else
1012
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
1013
+ DiagnosticMessages_1.DiagnosticMessages.returnTypeMismatch('string', 'float').message,
1014
+ DiagnosticMessages_1.DiagnosticMessages.returnTypeMismatch('boolean', 'float').message,
1015
+ DiagnosticMessages_1.DiagnosticMessages.returnTypeMismatch('Pie', 'float').message
1016
+ ]);
1017
+ });
1018
+ it('allows returning compatible types', () => {
1019
+ program.setFile('source/util.bs', `
1020
+ function getPi() as float
1021
+ return 3 ' integers are compatible with floats
1022
+ end function
1023
+
1024
+ function getPie() as Pie
1025
+ return new Tart("lemon") ' Tart extends Pie
1026
+ end function
1027
+
1028
+ class Pie
1029
+ kind as string
1030
+ sub new(kind as string)
1031
+ m.kind = kind
1032
+ end sub
1033
+ end class
1034
+
1035
+ class Tart extends Pie
1036
+ size = "small"
1037
+ end class
1038
+ `);
1039
+ program.validate();
1040
+ //should have no errors
1041
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
1042
+ });
1043
+ it('detects return types on void functions (subs)', () => {
1044
+ program.setFile('source/util.bs', `
1045
+ sub sayHello(name as string)
1046
+ return "hello " + name ' return should be void in subs
1047
+ end sub
1048
+ `);
1049
+ program.validate();
1050
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
1051
+ DiagnosticMessages_1.DiagnosticMessages.returnTypeMismatch('string', 'void').message
1052
+ ]);
1053
+ });
1054
+ it('detects return types on void functions', () => {
1055
+ program.setFile('source/util.bs', `
1056
+ function sayHello(name as string) as void
1057
+ return "hello " + name ' return should be void in subs
1058
+ end function
1059
+ `);
1060
+ program.validate();
1061
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
1062
+ DiagnosticMessages_1.DiagnosticMessages.returnTypeMismatch('string', 'void').message
1063
+ ]);
1064
+ });
1065
+ });
1066
+ describe('assignmentTypeMismatch', () => {
1067
+ it('finds when the type of the lhs is not compatible with the expected type', () => {
1068
+ program.setFile('source/util.bs', `
1069
+ sub doStuff(thing as iThing)
1070
+ thing.name = 123
1071
+ end sub
1072
+
1073
+ interface iThing
1074
+ name as string
1075
+ end interface
1076
+ `);
1077
+ program.validate();
1078
+ //should have error - assignment value should be a string, not a float
1079
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
1080
+ DiagnosticMessages_1.DiagnosticMessages.assignmentTypeMismatch('integer', 'string').message
1081
+ ]);
1082
+ });
1083
+ it('allows setting a member with correct type that is a union type', () => {
1084
+ program.setFile('source/util.bs', `
1085
+ sub doStuff(thing as iThing)
1086
+ thing.name = 123
1087
+ end sub
1088
+
1089
+ interface iThing
1090
+ name as string or integer
1091
+ end interface
1092
+ `);
1093
+ program.validate();
1094
+ //should have no error - assignment value should be a string, not a float
1095
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
1096
+ });
1097
+ it('finds when the rhs type is not compatible with the lhs, which is a union type', () => {
1098
+ program.setFile('source/util.bs', `
1099
+ sub doStuff(thing as iThing)
1100
+ thing.name = false
1101
+ end sub
1102
+
1103
+ interface iThing
1104
+ name as string or integer
1105
+ end interface
1106
+ `);
1107
+ program.validate();
1108
+ //should have error - assignment value should be a string or integer, not a boolean
1109
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
1110
+ DiagnosticMessages_1.DiagnosticMessages.assignmentTypeMismatch('boolean', 'string or integer').message
1111
+ ]);
1112
+ });
1113
+ it('validates when trying to assign to a class method', () => {
1114
+ program.setFile('source/util.bs', `
1115
+ sub doStuff(myThing as Thing)
1116
+ myThing.getPi = 3.14
1117
+ end sub
1118
+
1119
+ class Thing
1120
+ function getPi() as float
1121
+ return 3.14
1122
+ end function
1123
+ end class
1124
+ `);
1125
+ program.validate();
1126
+ //should have error
1127
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
1128
+ DiagnosticMessages_1.DiagnosticMessages.assignmentTypeMismatch('float', 'function getPi() as float').message
1129
+ ]);
1130
+ });
1131
+ it('allows adding new properties to a class (but why would you want to?)', () => {
1132
+ program.setFile('source/util.bs', `
1133
+ sub doStuff(myThing as Thing)
1134
+ myThing.getPi = 3.14
1135
+ end sub
1136
+
1137
+ class Thing
1138
+ end class
1139
+ `);
1140
+ program.validate();
1141
+ //should have no errors
1142
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
1143
+ });
1144
+ it('validates class constructors', () => {
1145
+ program.setFile('source/util.bs', `
1146
+ class Video
1147
+ sub new(url as integer)
1148
+ m.url = url 'this should be a compile error
1149
+ end sub
1150
+ public url as string
1151
+ end class
1152
+ `);
1153
+ program.validate();
1154
+ //should have errors
1155
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
1156
+ DiagnosticMessages_1.DiagnosticMessages.assignmentTypeMismatch('integer', 'string').message
1157
+ ]);
1158
+ });
1159
+ it('validates when assigning to a sgNode', () => {
1160
+ program.setFile('source/util.bs', `
1161
+ sub setLabelText(label as roSGNodeLabel)
1162
+ label.text = 1234
1163
+ end sub
1164
+
1165
+ `);
1166
+ program.validate();
1167
+ //should have errors
1168
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
1169
+ DiagnosticMessages_1.DiagnosticMessages.assignmentTypeMismatch('integer', 'string').message
1170
+ ]);
1171
+ });
1172
+ });
1173
+ describe('operatorTypeMismatch', () => {
1174
+ it('finds when the type of the lhs is not compatible with the rhs type', () => {
1175
+ program.setFile('source/util.bs', `
1176
+ sub doStuff()
1177
+ a = 1 + true
1178
+ b = "hello" * 2
1179
+ end sub
1180
+
1181
+ `);
1182
+ program.validate();
1183
+ //should have errors
1184
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
1185
+ DiagnosticMessages_1.DiagnosticMessages.operatorTypeMismatch('+', 'integer', 'boolean').message,
1186
+ DiagnosticMessages_1.DiagnosticMessages.operatorTypeMismatch('*', 'string', 'integer').message
1187
+ ]);
1188
+ });
1189
+ it('allows when the type of the lhs is compatible with the rhs type', () => {
1190
+ program.setFile('source/util.bs', `
1191
+ sub doStuff()
1192
+ a = 10 << 1
1193
+ b = "hello" + "world"
1194
+ c = 78 / 34
1195
+ d = 100 \\ 5
1196
+ thing = new Klass()
1197
+ e = thing <> invalid
1198
+ end sub
1199
+
1200
+ class Klass
1201
+ end class
1202
+ `);
1203
+ program.validate();
1204
+ //should have no errors
1205
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
1206
+ });
1207
+ it('allows tests against invalid', () => {
1208
+ program.setFile('source/util.bs', `
1209
+ sub doStuff()
1210
+ thing = new Klass()
1211
+ x = thing <> invalid
1212
+ end sub
1213
+
1214
+ class Klass
1215
+ end class
1216
+ `);
1217
+ program.validate();
1218
+ //should have no errors
1219
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
1220
+ });
1221
+ it('disallows equality tests of classes', () => {
1222
+ program.setFile('source/util.bs', `
1223
+ sub doStuff()
1224
+ thing = new Klass()
1225
+ thing2 = new Klass()
1226
+ x = thing = thing2
1227
+ end sub
1228
+
1229
+ class Klass
1230
+ end class
1231
+ `);
1232
+ program.validate();
1233
+ //should have errors
1234
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
1235
+ DiagnosticMessages_1.DiagnosticMessages.operatorTypeMismatch('=', 'Klass', 'Klass').message
1236
+ ]);
1237
+ });
1238
+ it('disallows operations between dynamic and custom types', () => {
1239
+ program.setFile('source/util.bs', `
1240
+ sub doStuff(input)
1241
+ thing = new Klass()
1242
+ x = thing + input
1243
+ end sub
1244
+
1245
+ class Klass
1246
+ end class
1247
+ `);
1248
+ program.validate();
1249
+ //should have errors
1250
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
1251
+ DiagnosticMessages_1.DiagnosticMessages.operatorTypeMismatch('+', 'Klass', 'dynamic').message
1252
+ ]);
1253
+ });
1254
+ it('allows valid operations on enum members', () => {
1255
+ program.setFile('source/util.bs', `
1256
+ sub makeEasterly(d as Direction)
1257
+ print d + "e"
1258
+ print Direction.north + "east"
1259
+ end sub
1260
+
1261
+ function getTax(itemAmt as ItemCost) as Float
1262
+ return itemAmt * 1.15
1263
+ end function
1264
+
1265
+ enum Direction
1266
+ north = "n"
1267
+ south = "s"
1268
+ end enum
1269
+
1270
+ enum ItemCost
1271
+ x = 99.99
1272
+ y = 29.99
1273
+ end enum
1274
+
1275
+ `);
1276
+ program.validate();
1277
+ //should have no errors
1278
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
1279
+ });
1280
+ it('finds invalid operations on enum members', () => {
1281
+ program.setFile('source/util.bs', `
1282
+ enum Direction
1283
+ north = "n"
1284
+ south = "s"
1285
+ end enum
1286
+
1287
+ sub makeEasterly(d as Direction)
1288
+ print d + 2
1289
+ print 3.14 * Direction.north
1290
+ end sub
1291
+ `);
1292
+ program.validate();
1293
+ //should have errors
1294
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
1295
+ DiagnosticMessages_1.DiagnosticMessages.operatorTypeMismatch('+', 'Direction', 'integer').message,
1296
+ DiagnosticMessages_1.DiagnosticMessages.operatorTypeMismatch('*', 'float', 'Direction').message
1297
+ ]);
1298
+ });
1299
+ it('validates unary operators', () => {
1300
+ program.setFile('source/util.bs', `
1301
+ sub doStuff()
1302
+ x = - "hello world"
1303
+ end sub
1304
+ `);
1305
+ program.validate();
1306
+ //should have errors
1307
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
1308
+ DiagnosticMessages_1.DiagnosticMessages.operatorTypeMismatch('-', 'string').message
1309
+ ]);
1310
+ });
1311
+ it('allows unary on dynamic and union types', () => {
1312
+ program.setFile('source/util.bs', `
1313
+ sub doStuff(x)
1314
+ y = -x
1315
+ print y
1316
+ end sub
1317
+
1318
+ sub doOtherStuff(x as float or integer)
1319
+ y = -x
1320
+ print y
1321
+ end sub
1322
+
1323
+ sub doEventMoreStuff(x as boolean or dynamic)
1324
+ if not x
1325
+ print "ok"
1326
+ end if
1327
+ end sub
1328
+ `);
1329
+ program.validate();
1330
+ //should have no errors
1331
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
1332
+ });
713
1333
  });
714
1334
  });
715
1335
  //# sourceMappingURL=ScopeValidator.spec.js.map