brighterscript 1.0.0-alpha.41 → 1.0.0-alpha.43

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 (212) hide show
  1. package/CHANGELOG.md +78 -2
  2. package/dist/AstValidationSegmenter.d.ts +3 -0
  3. package/dist/AstValidationSegmenter.js +62 -2
  4. package/dist/AstValidationSegmenter.js.map +1 -1
  5. package/dist/BsConfig.d.ts +7 -7
  6. package/dist/CrossScopeValidator.js +3 -3
  7. package/dist/CrossScopeValidator.js.map +1 -1
  8. package/dist/DiagnosticFilterer.d.ts +5 -1
  9. package/dist/DiagnosticFilterer.js +92 -33
  10. package/dist/DiagnosticFilterer.js.map +1 -1
  11. package/dist/DiagnosticManager.js +12 -9
  12. package/dist/DiagnosticManager.js.map +1 -1
  13. package/dist/DiagnosticMessages.d.ts +374 -225
  14. package/dist/DiagnosticMessages.js +641 -424
  15. package/dist/DiagnosticMessages.js.map +1 -1
  16. package/dist/DiagnosticSeverityAdjuster.js +4 -0
  17. package/dist/DiagnosticSeverityAdjuster.js.map +1 -1
  18. package/dist/LanguageServer.js +0 -7
  19. package/dist/LanguageServer.js.map +1 -1
  20. package/dist/PluginInterface.js +2 -0
  21. package/dist/PluginInterface.js.map +1 -1
  22. package/dist/Program.d.ts +22 -1
  23. package/dist/Program.js +206 -49
  24. package/dist/Program.js.map +1 -1
  25. package/dist/SymbolTable.d.ts +3 -0
  26. package/dist/SymbolTable.js +19 -1
  27. package/dist/SymbolTable.js.map +1 -1
  28. package/dist/XmlScope.js +3 -6
  29. package/dist/XmlScope.js.map +1 -1
  30. package/dist/astUtils/creators.d.ts +35 -3
  31. package/dist/astUtils/creators.js +52 -1
  32. package/dist/astUtils/creators.js.map +1 -1
  33. package/dist/astUtils/reflection.d.ts +24 -5
  34. package/dist/astUtils/reflection.js +89 -19
  35. package/dist/astUtils/reflection.js.map +1 -1
  36. package/dist/astUtils/visitors.d.ts +3 -2
  37. package/dist/astUtils/visitors.js +37 -14
  38. package/dist/astUtils/visitors.js.map +1 -1
  39. package/dist/astUtils/visitors.spec.js +172 -6
  40. package/dist/astUtils/visitors.spec.js.map +1 -1
  41. package/dist/bscPlugin/codeActions/CodeActionsProcessor.d.ts +0 -1
  42. package/dist/bscPlugin/codeActions/CodeActionsProcessor.js +0 -13
  43. package/dist/bscPlugin/codeActions/CodeActionsProcessor.js.map +1 -1
  44. package/dist/bscPlugin/completions/CompletionsProcessor.d.ts +2 -1
  45. package/dist/bscPlugin/completions/CompletionsProcessor.js +5 -5
  46. package/dist/bscPlugin/completions/CompletionsProcessor.js.map +1 -1
  47. package/dist/bscPlugin/completions/CompletionsProcessor.spec.js +106 -2
  48. package/dist/bscPlugin/completions/CompletionsProcessor.spec.js.map +1 -1
  49. package/dist/bscPlugin/hover/HoverProcessor.spec.js +51 -3
  50. package/dist/bscPlugin/hover/HoverProcessor.spec.js.map +1 -1
  51. package/dist/bscPlugin/transpile/BrsFileTranspileProcessor.d.ts +1 -0
  52. package/dist/bscPlugin/transpile/BrsFileTranspileProcessor.js +149 -0
  53. package/dist/bscPlugin/transpile/BrsFileTranspileProcessor.js.map +1 -1
  54. package/dist/bscPlugin/validation/BrsFileValidator.js +15 -8
  55. package/dist/bscPlugin/validation/BrsFileValidator.js.map +1 -1
  56. package/dist/bscPlugin/validation/BrsFileValidator.spec.js +170 -24
  57. package/dist/bscPlugin/validation/BrsFileValidator.spec.js.map +1 -1
  58. package/dist/bscPlugin/validation/ScopeValidator.d.ts +7 -0
  59. package/dist/bscPlugin/validation/ScopeValidator.js +150 -80
  60. package/dist/bscPlugin/validation/ScopeValidator.js.map +1 -1
  61. package/dist/bscPlugin/validation/ScopeValidator.spec.js +1341 -29
  62. package/dist/bscPlugin/validation/ScopeValidator.spec.js.map +1 -1
  63. package/dist/bscPlugin/validation/XmlFileValidator.js +0 -8
  64. package/dist/bscPlugin/validation/XmlFileValidator.js.map +1 -1
  65. package/dist/diagnosticUtils.js +6 -5
  66. package/dist/diagnosticUtils.js.map +1 -1
  67. package/dist/files/BrsFile.Class.spec.js +87 -28
  68. package/dist/files/BrsFile.Class.spec.js.map +1 -1
  69. package/dist/files/BrsFile.d.ts +1 -0
  70. package/dist/files/BrsFile.js +20 -8
  71. package/dist/files/BrsFile.js.map +1 -1
  72. package/dist/files/BrsFile.spec.js +133 -34
  73. package/dist/files/BrsFile.spec.js.map +1 -1
  74. package/dist/files/XmlFile.js +2 -2
  75. package/dist/files/XmlFile.js.map +1 -1
  76. package/dist/files/XmlFile.spec.js +3 -20
  77. package/dist/files/XmlFile.spec.js.map +1 -1
  78. package/dist/globalCallables.js +1 -1
  79. package/dist/index.d.ts +8 -3
  80. package/dist/index.js +24 -16
  81. package/dist/index.js.map +1 -1
  82. package/dist/interfaces.d.ts +18 -0
  83. package/dist/interfaces.js.map +1 -1
  84. package/dist/lexer/Lexer.js +17 -11
  85. package/dist/lexer/Lexer.js.map +1 -1
  86. package/dist/lexer/Lexer.spec.js +21 -3
  87. package/dist/lexer/Lexer.spec.js.map +1 -1
  88. package/dist/lexer/TokenKind.d.ts +9 -0
  89. package/dist/lexer/TokenKind.js +11 -1
  90. package/dist/lexer/TokenKind.js.map +1 -1
  91. package/dist/parser/AstNode.d.ts +2 -1
  92. package/dist/parser/AstNode.js +3 -2
  93. package/dist/parser/AstNode.js.map +1 -1
  94. package/dist/parser/Expression.d.ts +22 -2
  95. package/dist/parser/Expression.js +84 -49
  96. package/dist/parser/Expression.js.map +1 -1
  97. package/dist/parser/Parser.Class.spec.js +3 -3
  98. package/dist/parser/Parser.Class.spec.js.map +1 -1
  99. package/dist/parser/Parser.js +73 -61
  100. package/dist/parser/Parser.js.map +1 -1
  101. package/dist/parser/Parser.spec.js +198 -15
  102. package/dist/parser/Parser.spec.js.map +1 -1
  103. package/dist/parser/SGParser.js +9 -9
  104. package/dist/parser/SGParser.js.map +1 -1
  105. package/dist/parser/SGParser.spec.js +3 -2
  106. package/dist/parser/SGParser.spec.js.map +1 -1
  107. package/dist/parser/Statement.d.ts +16 -18
  108. package/dist/parser/Statement.js +136 -82
  109. package/dist/parser/Statement.js.map +1 -1
  110. package/dist/parser/tests/controlFlow/If.spec.js +1 -1
  111. package/dist/parser/tests/controlFlow/If.spec.js.map +1 -1
  112. package/dist/parser/tests/expression/ArrayLiterals.spec.js +3 -3
  113. package/dist/parser/tests/expression/ArrayLiterals.spec.js.map +1 -1
  114. package/dist/parser/tests/expression/AssociativeArrayLiterals.spec.js +3 -3
  115. package/dist/parser/tests/expression/AssociativeArrayLiterals.spec.js.map +1 -1
  116. package/dist/parser/tests/expression/Call.spec.js +9 -9
  117. package/dist/parser/tests/expression/Call.spec.js.map +1 -1
  118. package/dist/parser/tests/expression/Indexing.spec.js +3 -3
  119. package/dist/parser/tests/expression/Indexing.spec.js.map +1 -1
  120. package/dist/parser/tests/expression/TemplateStringExpression.spec.js +1 -1
  121. package/dist/parser/tests/expression/TemplateStringExpression.spec.js.map +1 -1
  122. package/dist/parser/tests/expression/TernaryExpression.spec.js +353 -71
  123. package/dist/parser/tests/expression/TernaryExpression.spec.js.map +1 -1
  124. package/dist/parser/tests/statement/Dim.spec.js +10 -3
  125. package/dist/parser/tests/statement/Dim.spec.js.map +1 -1
  126. package/dist/parser/tests/statement/Enum.spec.js +2 -2
  127. package/dist/parser/tests/statement/Enum.spec.js.map +1 -1
  128. package/dist/parser/tests/statement/Increment.spec.js +3 -5
  129. package/dist/parser/tests/statement/Increment.spec.js.map +1 -1
  130. package/dist/parser/tests/statement/PrintStatement.spec.js +3 -3
  131. package/dist/parser/tests/statement/TryCatch.spec.js +1 -1
  132. package/dist/parser/tests/statement/TryCatch.spec.js.map +1 -1
  133. package/dist/roku-types/data.json +567 -247
  134. package/dist/roku-types/index.d.ts +72 -42
  135. package/dist/types/ArrayType.d.ts +3 -0
  136. package/dist/types/ArrayType.js +18 -5
  137. package/dist/types/ArrayType.js.map +1 -1
  138. package/dist/types/AssociativeArrayType.d.ts +1 -0
  139. package/dist/types/AssociativeArrayType.js +1 -0
  140. package/dist/types/AssociativeArrayType.js.map +1 -1
  141. package/dist/types/BaseFunctionType.d.ts +1 -0
  142. package/dist/types/BaseFunctionType.js +1 -0
  143. package/dist/types/BaseFunctionType.js.map +1 -1
  144. package/dist/types/BooleanType.d.ts +1 -0
  145. package/dist/types/BooleanType.js +1 -0
  146. package/dist/types/BooleanType.js.map +1 -1
  147. package/dist/types/BscType.d.ts +8 -1
  148. package/dist/types/BscType.js +22 -6
  149. package/dist/types/BscType.js.map +1 -1
  150. package/dist/types/BuiltInInterfaceAdder.js +10 -6
  151. package/dist/types/BuiltInInterfaceAdder.js.map +1 -1
  152. package/dist/types/ClassType.d.ts +1 -0
  153. package/dist/types/ClassType.js +5 -2
  154. package/dist/types/ClassType.js.map +1 -1
  155. package/dist/types/ComponentType.d.ts +11 -4
  156. package/dist/types/ComponentType.js +100 -8
  157. package/dist/types/ComponentType.js.map +1 -1
  158. package/dist/types/DoubleType.d.ts +2 -0
  159. package/dist/types/DoubleType.js +4 -5
  160. package/dist/types/DoubleType.js.map +1 -1
  161. package/dist/types/DynamicType.d.ts +1 -0
  162. package/dist/types/DynamicType.js +4 -0
  163. package/dist/types/DynamicType.js.map +1 -1
  164. package/dist/types/EnumType.d.ts +2 -0
  165. package/dist/types/EnumType.js +20 -2
  166. package/dist/types/EnumType.js.map +1 -1
  167. package/dist/types/FloatType.d.ts +2 -0
  168. package/dist/types/FloatType.js +4 -5
  169. package/dist/types/FloatType.js.map +1 -1
  170. package/dist/types/FunctionType.js +2 -1
  171. package/dist/types/FunctionType.js.map +1 -1
  172. package/dist/types/InheritableType.js +8 -0
  173. package/dist/types/InheritableType.js.map +1 -1
  174. package/dist/types/IntegerType.d.ts +2 -0
  175. package/dist/types/IntegerType.js +4 -5
  176. package/dist/types/IntegerType.js.map +1 -1
  177. package/dist/types/InterfaceType.js +4 -1
  178. package/dist/types/InterfaceType.js.map +1 -1
  179. package/dist/types/InvalidType.d.ts +2 -1
  180. package/dist/types/InvalidType.js +3 -2
  181. package/dist/types/InvalidType.js.map +1 -1
  182. package/dist/types/LongIntegerType.d.ts +2 -0
  183. package/dist/types/LongIntegerType.js +4 -5
  184. package/dist/types/LongIntegerType.js.map +1 -1
  185. package/dist/types/ObjectType.d.ts +1 -0
  186. package/dist/types/ObjectType.js +1 -0
  187. package/dist/types/ObjectType.js.map +1 -1
  188. package/dist/types/ReferenceType.d.ts +20 -2
  189. package/dist/types/ReferenceType.js +106 -5
  190. package/dist/types/ReferenceType.js.map +1 -1
  191. package/dist/types/StringType.d.ts +1 -0
  192. package/dist/types/StringType.js +3 -2
  193. package/dist/types/StringType.js.map +1 -1
  194. package/dist/types/TypedFunctionType.d.ts +1 -1
  195. package/dist/types/TypedFunctionType.js +8 -2
  196. package/dist/types/TypedFunctionType.js.map +1 -1
  197. package/dist/types/UninitializedType.d.ts +2 -0
  198. package/dist/types/UninitializedType.js +5 -6
  199. package/dist/types/UninitializedType.js.map +1 -1
  200. package/dist/types/UnionType.js +8 -2
  201. package/dist/types/UnionType.js.map +1 -1
  202. package/dist/types/VoidType.d.ts +4 -1
  203. package/dist/types/VoidType.js +5 -0
  204. package/dist/types/VoidType.js.map +1 -1
  205. package/dist/types/helpers.js +8 -1
  206. package/dist/types/helpers.js.map +1 -1
  207. package/dist/util.d.ts +17 -6
  208. package/dist/util.js +320 -24
  209. package/dist/util.js.map +1 -1
  210. package/dist/validators/ClassValidator.js +13 -5
  211. package/dist/validators/ClassValidator.js.map +1 -1
  212. package/package.json +2 -2
@@ -173,7 +173,7 @@ describe('ScopeValidator', () => {
173
173
  print input
174
174
  end sub
175
175
  `);
176
- program.setFile('source/util.brs', `
176
+ program.setFile('source/util.bs', `
177
177
  sub useCallFunc(input as roSGNodeWidget)
178
178
  input.callFunc()
179
179
  end sub
@@ -199,15 +199,39 @@ describe('ScopeValidator', () => {
199
199
  print input
200
200
  end sub
201
201
  `);
202
- program.setFile('source/util.brs', `
202
+ program.setFile('source/util.bs', `
203
+ sub useCallFunc(input as roSGNodeWidget, funcToCall as string)
204
+ input.callFunc(funcToCall, 1, 2, 3, {})
205
+ end sub
206
+ `);
207
+ program.validate();
208
+ // no error, because we can't know what function you're actually calling
209
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
210
+ });
211
+ it('checks for target args count on callfunc', () => {
212
+ program.setFile('components/Widget.xml', (0, testHelpers_spec_1.trim) `
213
+ <?xml version="1.0" encoding="utf-8" ?>
214
+ <component name="Widget" extends="Group">
215
+ <script uri="Widget.brs"/>
216
+ <interface>
217
+ <function name="someFunc" />
218
+ </interface>
219
+ </component>
220
+ `);
221
+ program.setFile('components/Widget.brs', `
222
+ sub someFunc(input as object)
223
+ print input
224
+ end sub
225
+ `);
226
+ program.setFile('source/util.bs', `
203
227
  sub useCallFunc(input as roSGNodeWidget)
204
228
  input.callFunc("someFunc", 1, 2, 3, {})
205
229
  end sub
206
230
  `);
207
231
  program.validate();
208
- //TODO: do a better job of handling callFunc() invocations!
209
- //should have an error
210
- (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
232
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
233
+ DiagnosticMessages_1.DiagnosticMessages.mismatchArgumentCount(2, 5)
234
+ ]);
211
235
  });
212
236
  it('validates against scope-defined func in inner namespace, when outer namespace has same named func', () => {
213
237
  program.setFile('source/main.bs', `
@@ -1159,6 +1183,148 @@ describe('ScopeValidator', () => {
1159
1183
  (0, testHelpers_spec_1.expectTypeToBe)(data.fieldMismatches[0].expectedType, IntegerType_1.IntegerType);
1160
1184
  (0, testHelpers_spec_1.expectTypeToBe)(data.fieldMismatches[0].actualType, StringType_1.StringType);
1161
1185
  });
1186
+ it('allows a non-built-in void function as an argument', () => {
1187
+ program.setFile('source/main.bs', `
1188
+ sub voidFunc() as void
1189
+ end sub
1190
+
1191
+ sub doPrint(x)
1192
+ print x
1193
+ end sub
1194
+
1195
+ sub useVoidAsArg()
1196
+ doPrint(voidFunc()) ' will print "invalid"
1197
+ end sub
1198
+ `);
1199
+ program.validate();
1200
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
1201
+ });
1202
+ it('validates a built-in void function as an argument', () => {
1203
+ program.setFile('source/main.bs', `
1204
+ sub doPrint(x)
1205
+ print x
1206
+ end sub
1207
+
1208
+ sub useVoidAsArg()
1209
+ arr = [1,2,3]
1210
+ doPrint(arr.push(4))
1211
+ end sub
1212
+ `);
1213
+ program.validate();
1214
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
1215
+ DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('uninitialized', 'dynamic').message
1216
+ ]);
1217
+ });
1218
+ describe('default params', () => {
1219
+ it('generalizes EnumMembers to their parent types', () => {
1220
+ program.setFile('source/util.bs', `
1221
+ sub takesEnum(enumVal = Direction.South)
1222
+ print enumVal
1223
+ end sub
1224
+
1225
+ sub callTestFunc()
1226
+ takesEnum(Direction.North)
1227
+ end sub
1228
+
1229
+ enum Direction
1230
+ North
1231
+ South
1232
+ end enum
1233
+ `);
1234
+ program.validate();
1235
+ //should have no errors
1236
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
1237
+ });
1238
+ it('works with future declared types', () => {
1239
+ program.setFile('source/util.bs', `
1240
+ sub takesKlass(klassInstance = new Klass())
1241
+ print klassInstance
1242
+ end sub
1243
+
1244
+ sub callTestFunc()
1245
+ takesKlass()
1246
+ myKlass = new Klass()
1247
+ takesKlass(myKlass)
1248
+ end sub
1249
+
1250
+ class Klass
1251
+ name as string
1252
+ end class
1253
+ `);
1254
+ program.validate();
1255
+ //should have no errors
1256
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
1257
+ });
1258
+ it('validates against future declared types', () => {
1259
+ program.setFile('source/util.bs', `
1260
+ sub takesKlass(klassInstance = new Klass())
1261
+ print klassInstance
1262
+ end sub
1263
+
1264
+ sub callTestFunc()
1265
+ myOKlass = new OtherKlass()
1266
+ takesKlass(myOKlass)
1267
+ end sub
1268
+
1269
+ class Klass
1270
+ name as string
1271
+ end class
1272
+
1273
+ class OtherKlass
1274
+ name as integer
1275
+ end class
1276
+ `);
1277
+ program.validate();
1278
+ //should have no errors
1279
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
1280
+ DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('OtherKlass', 'Klass').message
1281
+ ]);
1282
+ });
1283
+ it('validates against future declared types in different namespace', () => {
1284
+ program.setFile('source/util.bs', `
1285
+ sub takesKlass(klassInstance = new alpha.beta.Klass())
1286
+ print klassInstance
1287
+ end sub
1288
+
1289
+ sub callTestFunc()
1290
+ myOKlass = new alpha.beta.OtherKlass()
1291
+ takesKlass(myOKlass)
1292
+ end sub
1293
+
1294
+ namespace alpha.beta
1295
+ class Klass
1296
+ name as string
1297
+ end class
1298
+
1299
+ class OtherKlass
1300
+ name as integer
1301
+ end class
1302
+ end namespace
1303
+ `);
1304
+ program.validate();
1305
+ //should have no errors
1306
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
1307
+ DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('alpha.beta.OtherKlass', 'alpha.beta.Klass').message
1308
+ ]);
1309
+ });
1310
+ it('should correctly be able to modify an array with enum initial values', () => {
1311
+ program.setFile('source/util.bs', `
1312
+ function alsoGoEast(path = [Direction.North, Direction.South])
1313
+ path.Push(Direction.East) ' "path" should be typed as Array<Direction>
1314
+ return path
1315
+ end function
1316
+
1317
+ enum Direction
1318
+ North = "North"
1319
+ South = "South"
1320
+ East = "East"
1321
+ West = "West"
1322
+ end enum
1323
+ `);
1324
+ program.validate();
1325
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
1326
+ });
1327
+ });
1162
1328
  describe('array compatibility', () => {
1163
1329
  it('accepts dynamic when assigning to a roArray', () => {
1164
1330
  program.setFile('source/util.bs', `
@@ -1487,6 +1653,66 @@ describe('ScopeValidator', () => {
1487
1653
  (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
1488
1654
  });
1489
1655
  });
1656
+ it('allows boxed types', () => {
1657
+ program.setFile('source/main.bs', `
1658
+ function takesBoxedLongInt(x as roLongInteger)
1659
+ return 123456& + x
1660
+ end function
1661
+
1662
+ function takesLongInt(x as longInteger)
1663
+ return 123456& + x
1664
+ end function
1665
+
1666
+ sub test()
1667
+ long = 123456&
1668
+ boxedLong = createObject("roLongInteger")
1669
+ print takesBoxedLongInt(long)
1670
+ print takesBoxedLongInt(boxedLong)
1671
+ print takesLongInt(long)
1672
+ print takesLongInt(boxedLong)
1673
+ end sub
1674
+ `);
1675
+ program.validate();
1676
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
1677
+ });
1678
+ describe('AA args with string literal keys', () => {
1679
+ it('finds keys with string literal names', () => {
1680
+ program.setFile('source/main.bs', `
1681
+ interface Data
1682
+ id
1683
+ end interface
1684
+
1685
+ sub takesData(datum as Data)
1686
+ end sub
1687
+
1688
+ sub usesData()
1689
+ takesData({"id": 1234})
1690
+ end sub
1691
+ `);
1692
+ program.validate();
1693
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
1694
+ });
1695
+ it('validates keys with string literal names, but type is incorrect', () => {
1696
+ program.setFile('source/main.bs', `
1697
+ interface Data
1698
+ id as string
1699
+ end interface
1700
+
1701
+ sub takesData(datum as Data)
1702
+ end sub
1703
+
1704
+ sub usesData()
1705
+ takesData({"id": 1234})
1706
+ end sub
1707
+ `);
1708
+ program.validate();
1709
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
1710
+ DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('roAssociativeArray', 'Data', {
1711
+ fieldMismatches: [{ name: 'id', expectedType: StringType_1.StringType.instance, actualType: IntegerType_1.IntegerType.instance }]
1712
+ }).message
1713
+ ]);
1714
+ });
1715
+ });
1490
1716
  });
1491
1717
  describe('cannotFindName', () => {
1492
1718
  it('finds variables from assignments from member functions of primitive types', () => {
@@ -1823,6 +2049,135 @@ describe('ScopeValidator', () => {
1823
2049
  program.validate();
1824
2050
  (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
1825
2051
  });
2052
+ it('has an diagnostic when using a variable defined in parent function', () => {
2053
+ program.setFile('source/main.bs', `
2054
+ function parentFunction()
2055
+ parentVar = "test"
2056
+
2057
+ innerFunction = sub()
2058
+ ' Attempting to use parentVar from the parent function scope
2059
+ print parentVar ' This should trigger a diagnostic
2060
+ otherFunc() ' this is fine
2061
+ end sub
2062
+
2063
+ innerFunction()
2064
+ end function
2065
+
2066
+ sub otherFunc()
2067
+ print "hello"
2068
+ end sub
2069
+ `);
2070
+ program.validate();
2071
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
2072
+ DiagnosticMessages_1.DiagnosticMessages.cannotFindName('parentVar')
2073
+ ]);
2074
+ });
2075
+ it('has an diagnostic when using a param from parent function', () => {
2076
+ program.setFile('source/main.bs', `
2077
+ function parentFunction(outerVal)
2078
+ parentVar = "test"
2079
+
2080
+ innerFunction = sub(inner)
2081
+ print inner + outer
2082
+ end sub
2083
+
2084
+ innerFunction(2)
2085
+ end function
2086
+ `);
2087
+ program.validate();
2088
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
2089
+ DiagnosticMessages_1.DiagnosticMessages.cannotFindName('outer')
2090
+ ]);
2091
+ });
2092
+ it('allows method call on hex literal', () => {
2093
+ program.setFile('source/main.bs', `
2094
+ function test()
2095
+ x = &HFF.toStr()
2096
+ return x
2097
+ end function
2098
+ `);
2099
+ program.validate();
2100
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
2101
+ });
2102
+ it('allows method call on hex literal', () => {
2103
+ program.setFile('source/main.bs', `
2104
+ function test()
2105
+ x = &HFF.toStr()
2106
+ return x
2107
+ end function
2108
+ `);
2109
+ program.validate();
2110
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
2111
+ });
2112
+ it('has no validation errors with print statement with hex followed by dot <number>', () => {
2113
+ program.setFile('source/main.bs', `
2114
+ sub test()
2115
+ print &hFF.123.456.5678
2116
+ end sub
2117
+ `);
2118
+ program.validate();
2119
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
2120
+ });
2121
+ it('allows access of properties of union with invalid', () => {
2122
+ program.setFile('source/main.bs', `
2123
+ sub test()
2124
+ channel = invalid
2125
+ if true
2126
+ channel = {
2127
+ height: 123
2128
+ }
2129
+ end if
2130
+
2131
+ height = 0
2132
+ if channel <> invalid then
2133
+ height += channel.height
2134
+ end if
2135
+ end sub
2136
+ `);
2137
+ program.validate();
2138
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
2139
+ });
2140
+ it('sets default arg of invalid as dynamic', () => {
2141
+ program.setFile('source/main.bs', `
2142
+ sub test(channel = invalid)
2143
+ if true
2144
+ channel = {
2145
+ height: 123
2146
+ }
2147
+ end if
2148
+
2149
+ height = 0
2150
+ if channel <> invalid then
2151
+ height += channel.height
2152
+ end if
2153
+ end sub
2154
+ `);
2155
+ program.validate();
2156
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
2157
+ });
2158
+ it('sets assignment of function returning invalid as dynamic', () => {
2159
+ program.setFile('source/main.bs', `
2160
+ sub test()
2161
+ channel = noReturn()
2162
+ if true
2163
+ channel = {
2164
+ height: 123
2165
+ }
2166
+ end if
2167
+
2168
+ height = 0
2169
+ if channel <> invalid then
2170
+ height += channel.height
2171
+ end if
2172
+ end sub
2173
+
2174
+ sub noReturn()
2175
+ print "hello"
2176
+ end sub
2177
+ `);
2178
+ program.validate();
2179
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
2180
+ });
1826
2181
  });
1827
2182
  describe('itemCannotBeUsedAsVariable', () => {
1828
2183
  it('detects assigning to a member of a namespace outside the namespace', () => {
@@ -1840,6 +2195,40 @@ describe('ScopeValidator', () => {
1840
2195
  DiagnosticMessages_1.DiagnosticMessages.itemCannotBeUsedAsVariable('namespace')
1841
2196
  ]);
1842
2197
  });
2198
+ it('validates when trying to print a namespace', () => {
2199
+ program.setFile('source/main.bs', `
2200
+ namespace Alpha
2201
+ const Name = "Alpha"
2202
+ end namespace
2203
+
2204
+ sub main()
2205
+ print alpha
2206
+ end sub
2207
+ `);
2208
+ program.validate();
2209
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
2210
+ DiagnosticMessages_1.DiagnosticMessages.itemCannotBeUsedAsVariable('namespace')
2211
+ ]);
2212
+ });
2213
+ it('validates when trying to pass a namespace as an arg', () => {
2214
+ program.setFile('source/main.bs', `
2215
+ namespace Alpha
2216
+ const Name = "Alpha"
2217
+ end namespace
2218
+
2219
+ sub main()
2220
+ someFunc(alpha)
2221
+ end sub
2222
+
2223
+ sub someFunc(arg)
2224
+ print sub
2225
+ end sub
2226
+ `);
2227
+ program.validate();
2228
+ (0, testHelpers_spec_1.expectDiagnosticsIncludes)(program, [
2229
+ DiagnosticMessages_1.DiagnosticMessages.itemCannotBeUsedAsVariable('namespace')
2230
+ ]);
2231
+ });
1843
2232
  it('detects assigning to a member of a namespace inside the namespace', () => {
1844
2233
  program.setFile('source/main.bs', `
1845
2234
  namespace Alpha
@@ -2262,9 +2651,47 @@ describe('ScopeValidator', () => {
2262
2651
  DiagnosticMessages_1.DiagnosticMessages.returnTypeMismatch('integer', 'void').message
2263
2652
  ]);
2264
2653
  });
2265
- });
2266
- describe('expectedReturnStatement', () => {
2267
- it('allows functions, subs, and "function as void/dynamic" to not have return statements', () => {
2654
+ it('allows empty return when return as void', () => {
2655
+ program.setFile('source/util.bs', `
2656
+ function doNothing1() as void
2657
+ return
2658
+ end function
2659
+
2660
+ sub doNothing2() as void
2661
+ return
2662
+ end sub
2663
+
2664
+ sub doNothing3() as void
2665
+ end sub
2666
+
2667
+ sub doNothing4()
2668
+ return
2669
+ end sub
2670
+
2671
+ function doNothing5()
2672
+ return
2673
+ end function
2674
+ `);
2675
+ program.validate();
2676
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
2677
+ });
2678
+ it('allows boxed types', () => {
2679
+ program.setFile('source/main.bs', `
2680
+ function getBoxedLongInt() as roLongInteger
2681
+ return 123456&
2682
+ end function
2683
+
2684
+ function getLongInt() as longInteger
2685
+ x = createObject("roLongInteger")
2686
+ return x
2687
+ end function
2688
+ `);
2689
+ program.validate();
2690
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
2691
+ });
2692
+ });
2693
+ describe('returnTypeCoercionMismatch', () => {
2694
+ it('allows functions, subs, and "function as void/dynamic" to not have return statements', () => {
2268
2695
  program.setFile('source/util.bs', `
2269
2696
  function noTypeSpecified()
2270
2697
  end function
@@ -2283,30 +2710,56 @@ describe('ScopeValidator', () => {
2283
2710
  });
2284
2711
  it('detects when a function does not have a return statement', () => {
2285
2712
  program.setFile('source/util.bs', `
2286
- function doSomething() as integer
2713
+ function doSomething() as string
2287
2714
  end function
2288
2715
  `);
2289
2716
  program.validate();
2290
2717
  (0, testHelpers_spec_1.expectDiagnostics)(program, [
2291
- DiagnosticMessages_1.DiagnosticMessages.expectedReturnStatement().message
2718
+ DiagnosticMessages_1.DiagnosticMessages.returnTypeCoercionMismatch().message
2292
2719
  ]);
2293
2720
  });
2721
+ it('allows when a function does not have a return statement, but type coercsion is okay', () => {
2722
+ program.setFile('source/util.bs', `
2723
+ interface Whatever
2724
+ name as string
2725
+ end interface
2726
+
2727
+ function doSomething() as Whatever
2728
+ end function
2729
+
2730
+ function doSomething2() as object
2731
+ end function
2732
+
2733
+ function doSomething3() as integer
2734
+ end function
2735
+
2736
+ function doSomething4() as float
2737
+ end function
2738
+
2739
+ function doSomething5() as boolean
2740
+ end function
2741
+
2742
+ `);
2743
+ program.validate();
2744
+ // all these are ok
2745
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
2746
+ });
2294
2747
  it('detects when a namespaced function does not have a return statement', () => {
2295
2748
  program.setFile('source/util.bs', `
2296
2749
  namespace alpha
2297
- function doSomething() as integer
2750
+ function doSomething() as string
2298
2751
  end function
2299
2752
  end namespace
2300
2753
  `);
2301
2754
  program.validate();
2302
2755
  (0, testHelpers_spec_1.expectDiagnostics)(program, [
2303
- DiagnosticMessages_1.DiagnosticMessages.expectedReturnStatement().message
2756
+ DiagnosticMessages_1.DiagnosticMessages.returnTypeCoercionMismatch().message
2304
2757
  ]);
2305
2758
  });
2306
2759
  it('detects when an inline function does not have a return statement', () => {
2307
2760
  program.setFile('source/util.bs', `
2308
- function outer() as integer
2309
- inner = function() as integer
2761
+ function outer() as string
2762
+ inner = function () as string
2310
2763
  print "no return!"
2311
2764
  end function
2312
2765
  return inner()
@@ -2314,30 +2767,30 @@ describe('ScopeValidator', () => {
2314
2767
  `);
2315
2768
  program.validate();
2316
2769
  (0, testHelpers_spec_1.expectDiagnostics)(program, [
2317
- DiagnosticMessages_1.DiagnosticMessages.expectedReturnStatement().message
2770
+ DiagnosticMessages_1.DiagnosticMessages.returnTypeCoercionMismatch().message
2318
2771
  ]);
2319
2772
  });
2320
2773
  it('detects when an outer function does not have a return statement', () => {
2321
2774
  program.setFile('source/util.bs', `
2322
- function outer() as integer
2323
- inner = function() as integer
2324
- return 1
2775
+ function outer() as string
2776
+ inner = function() as string
2777
+ return "abc"
2325
2778
  end function
2326
2779
  print inner()
2327
2780
  end function
2328
2781
  `);
2329
2782
  program.validate();
2330
2783
  (0, testHelpers_spec_1.expectDiagnostics)(program, [
2331
- DiagnosticMessages_1.DiagnosticMessages.expectedReturnStatement().message
2784
+ DiagnosticMessages_1.DiagnosticMessages.returnTypeCoercionMismatch().message
2332
2785
  ]);
2333
2786
  });
2334
2787
  it('detects when a outer function has a return statement in a branch', () => {
2335
2788
  program.setFile('source/util.bs', `
2336
- function hasBranch(x) as integer
2789
+ function hasBranch(x) as string
2337
2790
  if x = 1
2338
- return 1
2791
+ return "1"
2339
2792
  else
2340
- return 2
2793
+ return "2"
2341
2794
  end if
2342
2795
  end function
2343
2796
  `);
@@ -2346,18 +2799,18 @@ describe('ScopeValidator', () => {
2346
2799
  });
2347
2800
  it('works for sub with return types with missing return', () => {
2348
2801
  program.setFile('source/util.bs', `
2349
- sub doSomething() as integer
2802
+ sub doSomething() as string
2350
2803
  end sub
2351
2804
  `);
2352
2805
  program.validate();
2353
2806
  (0, testHelpers_spec_1.expectDiagnostics)(program, [
2354
- DiagnosticMessages_1.DiagnosticMessages.expectedReturnStatement().message
2807
+ DiagnosticMessages_1.DiagnosticMessages.returnTypeCoercionMismatch().message
2355
2808
  ]);
2356
2809
  });
2357
2810
  it('works for sub with return types', () => {
2358
2811
  program.setFile('source/util.bs', `
2359
- sub doSomething() as integer
2360
- return 1
2812
+ sub doSomething() as string
2813
+ return "1"
2361
2814
  end sub
2362
2815
  `);
2363
2816
  program.validate();
@@ -2495,6 +2948,47 @@ describe('ScopeValidator', () => {
2495
2948
  DiagnosticMessages_1.DiagnosticMessages.assignmentTypeMismatch('string', 'integer').message
2496
2949
  ]);
2497
2950
  });
2951
+ it('allows an assignment to a class field with enum initial value', () => {
2952
+ program.setFile('source/util.bs', `
2953
+ sub setDirection(k as Klass, d as Direction)
2954
+ k.dir = Direction.South
2955
+ k.dir = d
2956
+ end sub
2957
+
2958
+ class Klass
2959
+ dir = Direction.north
2960
+ end class
2961
+
2962
+ enum Direction
2963
+ north
2964
+ south
2965
+ end enum
2966
+ `);
2967
+ program.validate();
2968
+ //should have no errors
2969
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
2970
+ });
2971
+ it('validates an assignment to a class field with enum initial value', () => {
2972
+ program.setFile('source/util.bs', `
2973
+ sub setDirection(k as Klass)
2974
+ k.dir = "NOT a direction"
2975
+ end sub
2976
+
2977
+ class Klass
2978
+ dir = Direction.north
2979
+ end class
2980
+
2981
+ enum Direction
2982
+ north
2983
+ south
2984
+ end enum
2985
+ `);
2986
+ program.validate();
2987
+ //should have errors
2988
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
2989
+ DiagnosticMessages_1.DiagnosticMessages.assignmentTypeMismatch('string', 'Direction').message
2990
+ ]);
2991
+ });
2498
2992
  describe('Component fields', () => {
2499
2993
  it('allows assigning string to font fields', () => {
2500
2994
  program.setFile('source/util.bs', `
@@ -2805,6 +3299,98 @@ describe('ScopeValidator', () => {
2805
3299
  DiagnosticMessages_1.DiagnosticMessages.operatorTypeMismatch('++', 'string').message
2806
3300
  ]);
2807
3301
  });
3302
+ it('deals with adding int, bool and invalid', () => {
3303
+ program.setFile('source/util.bs', `
3304
+ sub doStuff()
3305
+ print 1 + (true + invalid)
3306
+ end sub
3307
+
3308
+ `);
3309
+ program.validate();
3310
+ //should have errors
3311
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
3312
+ DiagnosticMessages_1.DiagnosticMessages.operatorTypeMismatch('+', 'boolean', 'invalid').message
3313
+ ]);
3314
+ });
3315
+ it('allows using return of a void func as a variable', () => {
3316
+ program.setFile('source/main.brs', `
3317
+ sub voidFunc() as void
3318
+ end sub
3319
+
3320
+ sub test()
3321
+ x = voidFunc()
3322
+ if x = invalid
3323
+ print "invalid"
3324
+ end if
3325
+ end sub
3326
+ `);
3327
+ program.validate();
3328
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
3329
+ });
3330
+ it('validates using return of a built-in void func as a variable', () => {
3331
+ program.setFile('source/main.brs', `
3332
+ sub test()
3333
+ arr = [1,2,3]
3334
+ x = arr.push(4)
3335
+ if x = invalid
3336
+ print "invalid"
3337
+ end if
3338
+ end sub
3339
+ `);
3340
+ program.validate();
3341
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
3342
+ DiagnosticMessages_1.DiagnosticMessages.operatorTypeMismatch('=', 'uninitialized', 'invalid').message
3343
+ ]);
3344
+ });
3345
+ it('allows string comparisons with object', () => {
3346
+ program.setFile('source/main.brs', `
3347
+ sub test(x as object)
3348
+ if x <> "test"
3349
+ print x
3350
+ end if
3351
+ end sub
3352
+ `);
3353
+ program.validate();
3354
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
3355
+ });
3356
+ it('allows boxed types', () => {
3357
+ program.setFile('source/main.bs', `
3358
+ function math(a as rolonginteger, b as longinteger)
3359
+ c = a + b
3360
+ c = a - b
3361
+ c = a * b
3362
+ c = a / b
3363
+ c = a \\ b
3364
+
3365
+ d = a mod b
3366
+ d = a ^ b
3367
+
3368
+ a++
3369
+ a--
3370
+ a += 1
3371
+ a -= 1
3372
+ a *= 1
3373
+ a /= 1
3374
+ a \= 1
3375
+ a <<= 1
3376
+ a >>= 1
3377
+
3378
+ ? 1 << (2 as roInt)
3379
+ ? (1 as roInt) << 2
3380
+ ? a and b
3381
+ ? a or b
3382
+
3383
+ j = a = b
3384
+ j = a <> b
3385
+ j = a < b
3386
+ j = a <= b
3387
+ j = a > b
3388
+ j = a >= b
3389
+ end function
3390
+ `);
3391
+ program.validate();
3392
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
3393
+ });
2808
3394
  });
2809
3395
  describe('memberAccessibilityMismatch', () => {
2810
3396
  it('should flag when accessing a private member', () => {
@@ -3056,7 +3642,7 @@ describe('ScopeValidator', () => {
3056
3642
  `);
3057
3643
  program.validate();
3058
3644
  (0, testHelpers_spec_1.expectDiagnostics)(program, [
3059
- DiagnosticMessages_1.DiagnosticMessages.cannotFindTypeInCommentDoc('TypeNotThere').message
3645
+ DiagnosticMessages_1.DiagnosticMessages.cannotFindName('TypeNotThere').message
3060
3646
  ]);
3061
3647
  });
3062
3648
  it('validates types it cannot find in @return', () => {
@@ -3068,7 +3654,7 @@ describe('ScopeValidator', () => {
3068
3654
  `);
3069
3655
  program.validate();
3070
3656
  (0, testHelpers_spec_1.expectDiagnostics)(program, [
3071
- DiagnosticMessages_1.DiagnosticMessages.cannotFindTypeInCommentDoc('TypeNotThere').message
3657
+ DiagnosticMessages_1.DiagnosticMessages.cannotFindName('TypeNotThere').message
3072
3658
  ]);
3073
3659
  });
3074
3660
  it('validates types it cannot find in @type', () => {
@@ -3080,7 +3666,7 @@ describe('ScopeValidator', () => {
3080
3666
  `);
3081
3667
  program.validate();
3082
3668
  (0, testHelpers_spec_1.expectDiagnostics)(program, [
3083
- DiagnosticMessages_1.DiagnosticMessages.cannotFindTypeInCommentDoc('TypeNotThere').message
3669
+ DiagnosticMessages_1.DiagnosticMessages.cannotFindName('TypeNotThere').message
3084
3670
  ]);
3085
3671
  });
3086
3672
  });
@@ -3312,6 +3898,202 @@ describe('ScopeValidator', () => {
3312
3898
  DiagnosticMessages_1.DiagnosticMessages.cannotFindName('missingBool2', undefined, 'MediaObject').message
3313
3899
  ]);
3314
3900
  });
3901
+ it('rechecks source when member type of import changes', () => {
3902
+ // notice that width is wrongly typed as a boolean
3903
+ program.setFile('source/type1.bs', `
3904
+ interface SubType
3905
+ value as string
3906
+ end interface
3907
+ `);
3908
+ program.setFile('source/type2.bs', `
3909
+ interface ParentType
3910
+ child as Subtype
3911
+ end interface
3912
+ `);
3913
+ program.setFile('source/main.bs', `
3914
+ sub foo(input as ParentType)
3915
+ input.child.value = 1
3916
+ end sub
3917
+ `);
3918
+ program.validate();
3919
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
3920
+ DiagnosticMessages_1.DiagnosticMessages.assignmentTypeMismatch('integer', 'string').message
3921
+ ]);
3922
+ // fix width field type to integer
3923
+ program.setFile('source/type1.bs', `
3924
+ interface SubType
3925
+ value as integer
3926
+ end interface
3927
+ `);
3928
+ program.validate();
3929
+ // there should be no more errors
3930
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
3931
+ });
3932
+ it('rechecks component source when xml changes', () => {
3933
+ // notice that width is wrongly typed as a boolean
3934
+ program.setFile('components/Widget.xml', (0, testHelpers_spec_1.trim) `
3935
+ <?xml version="1.0" encoding="utf-8" ?>
3936
+ <component name="Widget" extends="Group">
3937
+ <script uri="Widget.bs"/>
3938
+ <interface>
3939
+ <field id="width" type="boolean" />
3940
+ </interface>
3941
+ </component>
3942
+ `);
3943
+ program.setFile('components/Widget.bs', `
3944
+ interface IWidget
3945
+ top as roSGNodeWidget
3946
+ data as roAssociativeArray
3947
+ end interface
3948
+
3949
+ sub init()
3950
+ (m as IWidget).top.width = 100
3951
+ end sub
3952
+ `);
3953
+ program.validate();
3954
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
3955
+ DiagnosticMessages_1.DiagnosticMessages.assignmentTypeMismatch('integer', 'boolean').message
3956
+ ]);
3957
+ // fix width field type to integer
3958
+ program.setFile('components/Widget.xml', (0, testHelpers_spec_1.trim) `
3959
+ <?xml version="1.0" encoding="utf-8" ?>
3960
+ <component name="Widget" extends="Group">
3961
+ <script uri="Widget.bs"/>
3962
+ <interface>
3963
+ <field id="width" type="integer" />
3964
+ </interface>
3965
+ </component>
3966
+ `);
3967
+ program.validate();
3968
+ // there should be no more errors
3969
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
3970
+ });
3971
+ it('rechecks complete file when type of typecasted m changes indirectly', () => {
3972
+ program.setFile('components/Widget.xml', (0, testHelpers_spec_1.trim) `
3973
+ <?xml version="1.0" encoding="utf-8" ?>
3974
+ <component name="Widget" extends="Group">
3975
+ <interface>
3976
+ <field id="width" type="boolean" />
3977
+ </interface>
3978
+ </component>
3979
+ `);
3980
+ // notice that width is wrongly typed as a boolean
3981
+ program.setFile('components/WidgetContainer.xml', (0, testHelpers_spec_1.trim) `
3982
+ <?xml version="1.0" encoding="utf-8" ?>
3983
+ <component name="WidgetContainer" extends="Group">
3984
+ <script uri="WidgetContainer.bs"/>
3985
+ </component>
3986
+ `);
3987
+ program.setFile('components/WidgetContainerTypes.bs', `
3988
+ interface IWidgetContainer
3989
+ top as roSGNodeWidgetContainer
3990
+ widget as roSGNodeWidget
3991
+ end interface
3992
+ `);
3993
+ program.setFile('components/WidgetContainer.bs', `
3994
+ import "WidgetContainerTypes.bs"
3995
+ typecast m as IWidgetContainer
3996
+
3997
+ sub init()
3998
+ m.widget.width = 100
3999
+ end sub
4000
+ `);
4001
+ program.validate();
4002
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
4003
+ DiagnosticMessages_1.DiagnosticMessages.assignmentTypeMismatch('integer', 'boolean').message
4004
+ ]);
4005
+ // fix width field type to integer
4006
+ program.setFile('components/Widget.xml', (0, testHelpers_spec_1.trim) `
4007
+ <?xml version="1.0" encoding="utf-8" ?>
4008
+ <component name="Widget" extends="Group">
4009
+ <interface>
4010
+ <field id="width" type="integer" />
4011
+ </interface>
4012
+ </component>
4013
+ `);
4014
+ program.validate();
4015
+ // there should be no more errors
4016
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
4017
+ });
4018
+ it('rechecks file using callfunc when exported function type of xml changes', () => {
4019
+ program.setFile('components/Widget.xml', (0, testHelpers_spec_1.trim) `
4020
+ <?xml version="1.0" encoding="utf-8" ?>
4021
+ <component name="Widget" extends="Group">
4022
+ <script uri="Widget.bs"/>
4023
+ <interface>
4024
+ <function name="foo" />
4025
+ </interface>
4026
+ </component>
4027
+ `);
4028
+ program.setFile('components/Widget.bs', `
4029
+ sub foo(input as string)
4030
+ print input
4031
+ end sub
4032
+ `);
4033
+ program.setFile('source/callFoo.bs', `
4034
+ sub callFoo(widget as roSGNodeWidget)
4035
+ widget@.foo(123) ' foo expects string
4036
+ end sub
4037
+ `);
4038
+ program.validate();
4039
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
4040
+ DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('integer', 'string').message
4041
+ ]);
4042
+ // fix function
4043
+ program.setFile('components/Widget.bs', `
4044
+ sub foo(input as integer)
4045
+ print input
4046
+ end sub
4047
+ `);
4048
+ program.validate();
4049
+ // there should be no more errors
4050
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
4051
+ });
4052
+ it('rechecks complete file when type of typecasted m in same file changes indirectly', () => {
4053
+ program.setFile('components/Widget.xml', (0, testHelpers_spec_1.trim) `
4054
+ <?xml version="1.0" encoding="utf-8" ?>
4055
+ <component name="Widget" extends="Group">
4056
+ <interface>
4057
+ <field id="width" type="boolean" />
4058
+ </interface>
4059
+ </component>
4060
+ `);
4061
+ // notice that width is wrongly typed as a boolean
4062
+ program.setFile('components/WidgetContainer.xml', (0, testHelpers_spec_1.trim) `
4063
+ <?xml version="1.0" encoding="utf-8" ?>
4064
+ <component name="WidgetContainer" extends="Group">
4065
+ <script uri="WidgetContainer.bs"/>
4066
+ </component>
4067
+ `);
4068
+ program.setFile('components/WidgetContainer.bs', `
4069
+ typecast m as IWidgetContainer
4070
+
4071
+ interface IWidgetContainer
4072
+ top as roSGNodeWidgetContainer
4073
+ widget as roSGNodeWidget
4074
+ end interface
4075
+
4076
+ sub init()
4077
+ m.widget.width = 100
4078
+ end sub
4079
+ `);
4080
+ program.validate();
4081
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
4082
+ DiagnosticMessages_1.DiagnosticMessages.assignmentTypeMismatch('integer', 'boolean').message
4083
+ ]);
4084
+ // fix width field type to integer
4085
+ program.setFile('components/Widget.xml', (0, testHelpers_spec_1.trim) `
4086
+ <?xml version="1.0" encoding="utf-8" ?>
4087
+ <component name="Widget" extends="Group">
4088
+ <interface>
4089
+ <field id="width" type="integer" />
4090
+ </interface>
4091
+ </component>
4092
+ `);
4093
+ program.validate();
4094
+ // there should be no more errors
4095
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
4096
+ });
3315
4097
  });
3316
4098
  describe('preprocessor', () => {
3317
4099
  it('should process class inheritance correctly', () => {
@@ -3376,5 +4158,535 @@ describe('ScopeValidator', () => {
3376
4158
  (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
3377
4159
  });
3378
4160
  });
4161
+ describe('callFunc', () => {
4162
+ it('allows access to member of return type when return type is custom node', () => {
4163
+ program.setFile('components/Widget.xml', (0, testHelpers_spec_1.trim) `
4164
+ <?xml version="1.0" encoding="utf-8" ?>
4165
+ <component name="Widget" extends="Group">
4166
+ <script uri="Widget.bs"/>
4167
+ <interface>
4168
+ <function name="getOther" />
4169
+ </interface>
4170
+ </component>
4171
+ `);
4172
+ program.setFile('components/Widget.bs', `
4173
+ function getOther(name as string) as roSgNodeOther
4174
+ other = createObject("roSgNode", "Other")
4175
+ other.myValue = name
4176
+ return other
4177
+ end function
4178
+ `);
4179
+ program.setFile('components/Other.xml', (0, testHelpers_spec_1.trim) `
4180
+ <?xml version="1.0" encoding="utf-8" ?>
4181
+ <component name="Other" extends="Group">
4182
+ <interface>
4183
+ <field id="myValue" type="string" />
4184
+ </interface>
4185
+ </component>
4186
+ `);
4187
+ program.setFile('components/MainScene.xml', (0, testHelpers_spec_1.trim) `
4188
+ <?xml version="1.0" encoding="utf-8" ?>
4189
+ <component name="MainScene" extends="Scene">
4190
+ <script uri="MainScene.bs"/>
4191
+ </component>
4192
+ `);
4193
+ program.setFile('components/MainScene.bs', `
4194
+ sub someFunc(widget as roSGNodeWidget)
4195
+ otherNode = widget@.getOther("3.14")
4196
+ print otherNode.myValue
4197
+ end sub
4198
+ `);
4199
+ program.validate();
4200
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
4201
+ });
4202
+ it('allows access to member of return type when return type is custom type', () => {
4203
+ program.setFile('components/Widget.xml', (0, testHelpers_spec_1.trim) `
4204
+ <?xml version="1.0" encoding="utf-8" ?>
4205
+ <component name="Widget" extends="Group">
4206
+ <script uri="Widget.bs"/>
4207
+ <interface>
4208
+ <function name="getOther" />
4209
+ </interface>
4210
+ </component>
4211
+ `);
4212
+ program.setFile('components/types.bs', `
4213
+ interface SomeIFace
4214
+ myValue as string
4215
+ end interface
4216
+ `);
4217
+ program.setFile('components/Widget.bs', `
4218
+ import "pkg:/components/types.bs"
4219
+
4220
+ function getOther(name as string) as SomeIFace
4221
+ other = {myValue: name} as SomeIface
4222
+ other.myValue = name
4223
+ return other
4224
+ end function
4225
+ `);
4226
+ program.setFile('components/MainScene.xml', (0, testHelpers_spec_1.trim) `
4227
+ <?xml version="1.0" encoding="utf-8" ?>
4228
+ <component name="MainScene" extends="Scene">
4229
+ <script uri="MainScene.bs"/>
4230
+ </component>
4231
+ `);
4232
+ program.setFile('components/MainScene.bs', `
4233
+ sub someFunc(widget as roSGNodeWidget)
4234
+ otherNode = widget@.getOther("3.14")
4235
+ print otherNode.myValue
4236
+ end sub
4237
+ `);
4238
+ program.validate();
4239
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
4240
+ });
4241
+ it('allows access to custom type member of return type when return type is custom type', () => {
4242
+ program.setFile('components/Widget.xml', (0, testHelpers_spec_1.trim) `
4243
+ <?xml version="1.0" encoding="utf-8" ?>
4244
+ <component name="Widget" extends="Group">
4245
+ <script uri="Widget.bs"/>
4246
+ <interface>
4247
+ <function name="getOther" />
4248
+ </interface>
4249
+ </component>
4250
+ `);
4251
+ program.setFile('components/types.bs', `
4252
+ interface SomeIFace
4253
+ subFace as SubIface
4254
+ end interface
4255
+
4256
+ interface SubIface
4257
+ myValue as string
4258
+ end interface
4259
+ `);
4260
+ program.setFile('components/Widget.bs', `
4261
+ import "pkg:/components/types.bs"
4262
+
4263
+ function getOther(name as string) as SomeIFace
4264
+ other = {subFace: {myValue: name}} as SomeIface
4265
+ return other
4266
+ end function
4267
+ `);
4268
+ program.setFile('components/MainScene.xml', (0, testHelpers_spec_1.trim) `
4269
+ <?xml version="1.0" encoding="utf-8" ?>
4270
+ <component name="MainScene" extends="Scene">
4271
+ <script uri="MainScene.bs"/>
4272
+ </component>
4273
+ `);
4274
+ program.setFile('components/MainScene.bs', `
4275
+ sub someFunc(widget as roSGNodeWidget)
4276
+ otherNode = widget@.getOther("3.14")
4277
+ print otherNode.subFace.myValue
4278
+ end sub
4279
+ `);
4280
+ program.validate();
4281
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
4282
+ });
4283
+ it('correctly finds error with using unknown member of callfunc return type when return type is custom type', () => {
4284
+ program.setFile('components/Widget.xml', (0, testHelpers_spec_1.trim) `
4285
+ <?xml version="1.0" encoding="utf-8" ?>
4286
+ <component name="Widget" extends="Group">
4287
+ <script uri="Widget.bs"/>
4288
+ <interface>
4289
+ <function name="getOther" />
4290
+ </interface>
4291
+ </component>
4292
+ `);
4293
+ program.setFile('components/types.bs', `
4294
+ interface SomeIFace
4295
+ subFace as SubIface
4296
+ end interface
4297
+
4298
+ interface SubIface
4299
+ myValue as string
4300
+ end interface
4301
+ `);
4302
+ program.setFile('components/Widget.bs', `
4303
+ import "pkg:/components/types.bs"
4304
+
4305
+ function getOther(name as string) as SomeIFace
4306
+ other = {subFace: {myValue: name}} as SomeIface
4307
+ return other
4308
+ end function
4309
+ `);
4310
+ program.setFile('components/MainScene.xml', (0, testHelpers_spec_1.trim) `
4311
+ <?xml version="1.0" encoding="utf-8" ?>
4312
+ <component name="MainScene" extends="Scene">
4313
+ <script uri="MainScene.bs"/>
4314
+ </component>
4315
+ `);
4316
+ program.setFile('components/MainScene.bs', `
4317
+ sub someFunc(widget as roSGNodeWidget)
4318
+ otherNode = widget@.getOther("3.14")
4319
+ print otherNode.subFace.notIncluded
4320
+ end sub
4321
+ `);
4322
+ program.validate();
4323
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
4324
+ DiagnosticMessages_1.DiagnosticMessages.cannotFindName('notIncluded', 'SubIface.notIncluded', 'SubIface').message
4325
+ ]);
4326
+ });
4327
+ it('catches when a non-component type has callfunc invocation', () => {
4328
+ program.setFile('source/test.bs', `
4329
+ sub printName(widget as integer)
4330
+ print widget@.toStr()
4331
+ end sub
4332
+ `);
4333
+ program.validate();
4334
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
4335
+ DiagnosticMessages_1.DiagnosticMessages.cannotFindCallFuncFunction('toStr', 'integer@.toStr', 'integer').message
4336
+ ]);
4337
+ });
4338
+ it('allows to types that reference themselves', () => {
4339
+ program.setFile('components/Widget.xml', (0, testHelpers_spec_1.trim) `
4340
+ <?xml version="1.0" encoding="utf-8" ?>
4341
+ <component name="Widget" extends="Group">
4342
+ <script uri="Widget.bs"/>
4343
+ <interface>
4344
+ <function name="getList" />
4345
+ </interface>
4346
+ </component>
4347
+ `);
4348
+ program.setFile('components/types.bs', `
4349
+ interface LinkedList
4350
+ value as integer
4351
+ optional data as roAssociativeArray
4352
+ optional next as LinkedList
4353
+ end interface
4354
+ `);
4355
+ program.setFile('components/Widget.bs', `
4356
+ import "pkg:/components/types.bs"
4357
+
4358
+ function getList() as LinkedList
4359
+ list = {
4360
+ value: 1,
4361
+ next: {
4362
+ value: 2,
4363
+ next: {
4364
+ value: 3
4365
+ }
4366
+ }
4367
+ } as LinkedList
4368
+ return list
4369
+ end function
4370
+ `);
4371
+ program.setFile('components/MainScene.xml', (0, testHelpers_spec_1.trim) `
4372
+ <?xml version="1.0" encoding="utf-8" ?>
4373
+ <component name="MainScene" extends="Scene">
4374
+ <script uri="MainScene.bs"/>
4375
+ </component>
4376
+ `);
4377
+ program.setFile('components/MainScene.bs', `
4378
+ sub someFunc(widget as roSGNodeWidget)
4379
+ list = widget@.getList()
4380
+ print list.next.next.value
4381
+ end sub
4382
+ `);
4383
+ program.validate();
4384
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
4385
+ });
4386
+ it('finds invalid func name of callfunc()', () => {
4387
+ program.setFile('components/Widget.xml', (0, testHelpers_spec_1.trim) `
4388
+ <?xml version="1.0" encoding="utf-8" ?>
4389
+ <component name="Widget" extends="Group">
4390
+ <script uri="Widget.bs"/>
4391
+ <interface>
4392
+ <function name="getName" />
4393
+ </interface>
4394
+ </component>
4395
+ `);
4396
+ program.setFile('components/Widget.bs', `
4397
+ function getName() as string
4398
+ return "John Doe"
4399
+ end function
4400
+ `);
4401
+ program.setFile('source/test.bs', `
4402
+ sub printName(widget as roSGNodeWidget)
4403
+ print widget.callFunc("whatever")
4404
+ end sub
4405
+ `);
4406
+ program.validate();
4407
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
4408
+ DiagnosticMessages_1.DiagnosticMessages.cannotFindCallFuncFunction('whatever', 'roSGNodeWidget@.whatever', 'roSGNodeWidget').message
4409
+ ]);
4410
+ });
4411
+ it('finds invalid func name of @ callfunc invocation', () => {
4412
+ program.setFile('components/Widget.xml', (0, testHelpers_spec_1.trim) `
4413
+ <?xml version="1.0" encoding="utf-8" ?>
4414
+ <component name="Widget" extends="Group">
4415
+ <script uri="Widget.bs"/>
4416
+ <interface>
4417
+ <function name="getName" />
4418
+ </interface>
4419
+ </component>
4420
+ `);
4421
+ program.setFile('components/Widget.bs', `
4422
+ function getName() as string
4423
+ return "John Doe"
4424
+ end function
4425
+ `);
4426
+ program.setFile('source/test.bs', `
4427
+ sub printName(widget as roSGNodeWidget)
4428
+ print widget@.whatever()
4429
+ end sub
4430
+ `);
4431
+ program.validate();
4432
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
4433
+ DiagnosticMessages_1.DiagnosticMessages.cannotFindCallFuncFunction('whatever', 'roSGNodeWidget@.whatever', 'roSGNodeWidget').message
4434
+ ]);
4435
+ });
4436
+ it('catches func name of callfunc() with spaces', () => {
4437
+ program.setFile('components/Widget.xml', (0, testHelpers_spec_1.trim) `
4438
+ <?xml version="1.0" encoding="utf-8" ?>
4439
+ <component name="Widget" extends="Group">
4440
+ <script uri="Widget.bs"/>
4441
+ <interface>
4442
+ <function name="getName" />
4443
+ </interface>
4444
+ </component>
4445
+ `);
4446
+ program.setFile('components/Widget.bs', `
4447
+ function getName() as string
4448
+ return "John Doe"
4449
+ end function
4450
+ `);
4451
+ program.setFile('source/test.bs', `
4452
+ sub printName(widget as roSGNodeWidget)
4453
+ print widget.callFunc("whatever the name is")
4454
+ end sub
4455
+ `);
4456
+ program.validate();
4457
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
4458
+ DiagnosticMessages_1.DiagnosticMessages.cannotFindCallFuncFunction('whatever the name is', 'roSGNodeWidget@.whatever the name is', 'roSGNodeWidget').message
4459
+ ]);
4460
+ });
4461
+ it('validates arg type of callfunc()', () => {
4462
+ program.setFile('components/Widget.xml', (0, testHelpers_spec_1.trim) `
4463
+ <?xml version="1.0" encoding="utf-8" ?>
4464
+ <component name="Widget" extends="Group">
4465
+ <script uri="Widget.bs"/>
4466
+ <interface>
4467
+ <function name="getName" />
4468
+ </interface>
4469
+ </component>
4470
+ `);
4471
+ program.setFile('components/Widget.bs', `
4472
+ function getName(name as string, count as integer) as string
4473
+ return "John Doe"
4474
+ end function
4475
+ `);
4476
+ program.setFile('source/test.bs', `
4477
+ sub printName(widget as roSGNodeWidget)
4478
+ print widget.callFunc("getName", 12, "not int")
4479
+ end sub
4480
+ `);
4481
+ program.validate();
4482
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
4483
+ DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('integer', 'string').message,
4484
+ DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('string', 'integer').message
4485
+ ]);
4486
+ });
4487
+ it('has no error on plain roSGNode', () => {
4488
+ program.setFile('source/test.bs', `
4489
+ sub doCallfunc(nodeName as string)
4490
+ node = createObject("roSgNode", nodeName)
4491
+ node.callfunc("someFunc", 1, 2, 3)
4492
+ end sub
4493
+ `);
4494
+ program.validate();
4495
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
4496
+ });
4497
+ it('has error on regular builtIn types', () => {
4498
+ program.setFile('source/test.bs', `
4499
+ sub doCallfunc()
4500
+ node = createObject("roSgNode", "Rectangle")
4501
+ node.callfunc("someFunc", 1, 2, 3)
4502
+ end sub
4503
+ `);
4504
+ program.validate();
4505
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
4506
+ DiagnosticMessages_1.DiagnosticMessages.cannotFindCallFuncFunction('someFunc', 'roSGNodeRectangle@.someFunc', 'roSGNodeRectangle')
4507
+ ]);
4508
+ });
4509
+ it('allows callfunc on flexible types', () => {
4510
+ program.setFile('source/test.bs', `
4511
+ sub doCallfunc(obj as object, dyn as dynamic, node as roSGNode)
4512
+ obj.callfunc("testFunc")
4513
+ obj@.testFunc()
4514
+
4515
+ dyn.callfunc("testFunc")
4516
+ dyn@.testFunc()
4517
+
4518
+ node.callfunc("testFunc")
4519
+ node@.testFunc()
4520
+ end sub
4521
+ `);
4522
+ program.validate();
4523
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
4524
+ });
4525
+ it('allows callfunc on components from component library', () => {
4526
+ program.setFile('source/test.bs', `
4527
+ sub doCallfunc()
4528
+ fromComponentLibrary = CreateObject("roSGNode", "library:SomeComponent")
4529
+ fromComponentLibrary@.someFunc()
4530
+ fromComponentLibrary.callfunc("someFunc")
4531
+ end sub
4532
+ `);
4533
+ program.validate();
4534
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
4535
+ });
4536
+ it('allows callfunc on the dynamic result of a function call', () => {
4537
+ program.setFile('source/test.bs', `
4538
+ sub doCallfunc(nodeName)
4539
+ getNode(nodeName)@.someCallFunc(1,2,3)
4540
+ end sub
4541
+
4542
+ function getNode(nodeType)
4543
+ return CreateObject("roSGNode", nodeType)
4544
+ end function
4545
+ `);
4546
+ program.validate();
4547
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
4548
+ });
4549
+ it('validates callfunc on a known result of a function call', () => {
4550
+ program.setFile('components/Widget.xml', (0, testHelpers_spec_1.trim) `
4551
+ <?xml version="1.0" encoding="utf-8" ?>
4552
+ <component name="Widget" extends="Group">
4553
+ <script uri="Widget.bs"/>
4554
+ <interface>
4555
+ <function name="getName" />
4556
+ </interface>
4557
+ </component>
4558
+ `);
4559
+ program.setFile('components/Widget.bs', `
4560
+ function getName(name as string, count as integer) as string
4561
+ return "John Doe"
4562
+ end function
4563
+ `);
4564
+ program.setFile('source/test.bs', `
4565
+ sub doCallfunc()
4566
+ getWidget()@.getName("someStr", "not an int")
4567
+ end sub
4568
+
4569
+ function getWidget() as roSGNodeWidget
4570
+ return CreateObject("roSGNode", "Widget")
4571
+ end function
4572
+ `);
4573
+ program.validate();
4574
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
4575
+ DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('string', 'integer').message
4576
+ ]);
4577
+ });
4578
+ it('validates callfunc on a known result of a callfunc call', () => {
4579
+ program.setFile('components/Widget.xml', (0, testHelpers_spec_1.trim) `
4580
+ <?xml version="1.0" encoding="utf-8" ?>
4581
+ <component name="Widget" extends="Group">
4582
+ <script uri="Widget.bs"/>
4583
+ <interface>
4584
+ <function name="getName" />
4585
+ <function name="getSelf" />
4586
+ </interface>
4587
+ </component>
4588
+ `);
4589
+ program.setFile('components/Widget.bs', `
4590
+ function getName(name as string, count as integer) as string
4591
+ return "John Doe"
4592
+ end function
4593
+
4594
+ function getSelf() as roSGNodeWidget
4595
+ return m.top
4596
+ end function
4597
+ `);
4598
+ program.setFile('source/test.bs', `
4599
+ sub doCallfunc(widget as roSGNodeWidget)
4600
+ widget@.getSelf()@.getName("someStr", "not an int")
4601
+ end sub
4602
+ `);
4603
+ program.validate();
4604
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
4605
+ DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('string', 'integer').message
4606
+ ]);
4607
+ });
4608
+ it('respects return value of as callfunc functions', () => {
4609
+ program.setFile('components/Widget.xml', (0, testHelpers_spec_1.trim) `
4610
+ <?xml version="1.0" encoding="utf-8" ?>
4611
+ <component name="Widget" extends="Group">
4612
+ <script uri="Widget.bs"/>
4613
+ <interface>
4614
+ <function name="getInt" />
4615
+ </interface>
4616
+ </component>
4617
+ `);
4618
+ program.setFile('components/Widget.bs', `
4619
+ sub getInt() as integer
4620
+ return 1
4621
+ end sub
4622
+ `);
4623
+ program.setFile('source/test.bs', `
4624
+ sub doCallfunc(widget as roSGNodeWidget)
4625
+ takesInt(widget@.getInt())
4626
+ end sub
4627
+
4628
+ sub takesInt(number as integer)
4629
+ print number
4630
+ end sub
4631
+ `);
4632
+ program.validate();
4633
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
4634
+ });
4635
+ it('respects return value of as callfunc functions - negative case', () => {
4636
+ program.setFile('components/Widget.xml', (0, testHelpers_spec_1.trim) `
4637
+ <?xml version="1.0" encoding="utf-8" ?>
4638
+ <component name="Widget" extends="Group">
4639
+ <script uri="Widget.bs"/>
4640
+ <interface>
4641
+ <function name="getInt" />
4642
+ </interface>
4643
+ </component>
4644
+ `);
4645
+ program.setFile('components/Widget.bs', `
4646
+ sub getInt() as integer
4647
+ return 1
4648
+ end sub
4649
+ `);
4650
+ program.setFile('source/test.bs', `
4651
+ sub doCallfunc(widget as roSGNodeWidget)
4652
+ takesString(widget@.getInt())
4653
+ end sub
4654
+
4655
+ sub takesString(word as string)
4656
+ print word
4657
+ end sub
4658
+ `);
4659
+ program.validate();
4660
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
4661
+ DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('integer', 'string').message
4662
+ ]);
4663
+ });
4664
+ it('allows return value of as void functions to be dynamic', () => {
4665
+ program.setFile('components/Widget.xml', (0, testHelpers_spec_1.trim) `
4666
+ <?xml version="1.0" encoding="utf-8" ?>
4667
+ <component name="Widget" extends="Group">
4668
+ <script uri="Widget.bs"/>
4669
+ <interface>
4670
+ <function name="noop" />
4671
+ </interface>
4672
+ </component>
4673
+ `);
4674
+ program.setFile('components/Widget.bs', `
4675
+ sub noop()
4676
+ end sub
4677
+ `);
4678
+ program.setFile('source/test.bs', `
4679
+ sub doCallfunc(widget as roSGNodeWidget)
4680
+ takesAny(widget@.noop())
4681
+ end sub
4682
+
4683
+ sub takesAny(anything)
4684
+ print anything
4685
+ end sub
4686
+ `);
4687
+ program.validate();
4688
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
4689
+ });
4690
+ });
3379
4691
  });
3380
4692
  //# sourceMappingURL=ScopeValidator.spec.js.map